summaryrefslogtreecommitdiffstats
path: root/cpukit
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit')
-rw-r--r--cpukit/.cvsignore16
-rw-r--r--cpukit/ChangeLog5870
-rw-r--r--cpukit/Makefile.am186
-rw-r--r--cpukit/acinclude.m421
-rw-r--r--cpukit/aclocal/canonical-target-name.m440
-rw-r--r--cpukit/aclocal/canonicalize-tools.m415
-rw-r--r--cpukit/aclocal/check-itron.m423
-rw-r--r--cpukit/aclocal/check-multiprocessing.m49
-rw-r--r--cpukit/aclocal/check-networking.m428
-rw-r--r--cpukit/aclocal/check-newlib.m430
-rw-r--r--cpukit/aclocal/check-posix.m423
-rw-r--r--cpukit/aclocal/check-rtems-debug.m47
-rw-r--r--cpukit/aclocal/check-tool.m411
-rw-r--r--cpukit/aclocal/enable-inlines.m411
-rw-r--r--cpukit/aclocal/enable-itron.m433
-rw-r--r--cpukit/aclocal/enable-multiprocessing.m412
-rw-r--r--cpukit/aclocal/enable-networking.m414
-rw-r--r--cpukit/aclocal/enable-posix.m433
-rw-r--r--cpukit/aclocal/enable-rtems-debug.m412
-rw-r--r--cpukit/aclocal/env-rtemscpu.m414
-rw-r--r--cpukit/aclocal/gcc-isystem.m425
-rw-r--r--cpukit/aclocal/gcc-pipe.m421
-rw-r--r--cpukit/aclocal/multi.m452
-rw-r--r--cpukit/aclocal/multilib.m414
-rw-r--r--cpukit/aclocal/prog-cc.m446
-rw-r--r--cpukit/aclocal/prog-ccas.m48
-rw-r--r--cpukit/aclocal/prog-gnat.m445
-rw-r--r--cpukit/aclocal/rtems-flags.m411
-rw-r--r--cpukit/aclocal/rtems-top.m470
-rw-r--r--cpukit/aclocal/sysv-ipc.m4125
-rw-r--r--cpukit/aclocal/version.m42
-rw-r--r--cpukit/ada/.cvsignore2
-rw-r--r--cpukit/ada/ChangeLog109
-rw-r--r--cpukit/ada/Makefile.am42
-rw-r--r--cpukit/ada/rtems-multiprocessing.adb38
-rw-r--r--cpukit/ada/rtems-multiprocessing.ads30
-rw-r--r--cpukit/ada/rtems.adb1947
-rw-r--r--cpukit/ada/rtems.ads1481
-rw-r--r--cpukit/automake/compile.am80
-rw-r--r--cpukit/automake/local.am8
-rw-r--r--cpukit/automake/multilib.am36
-rw-r--r--cpukit/automake/subdirs.am32
-rw-r--r--cpukit/backward/asm.h7
-rw-r--r--cpukit/backward/chain.h7
-rw-r--r--cpukit/backward/clockdrv.h7
-rw-r--r--cpukit/backward/confdefs.h7
-rw-r--r--cpukit/backward/console.h7
-rw-r--r--cpukit/backward/dosfs.h7
-rw-r--r--cpukit/backward/imfs.h7
-rw-r--r--cpukit/backward/iosupp.h7
-rw-r--r--cpukit/backward/itron.h7
-rw-r--r--cpukit/backward/motorola/mc68230.h7
-rw-r--r--cpukit/backward/motorola/mc68681.h7
-rw-r--r--cpukit/backward/ringbuf.h7
-rw-r--r--cpukit/backward/rtc.h7
-rw-r--r--cpukit/backward/spurious.h7
-rw-r--r--cpukit/backward/timerdrv.h7
-rw-r--r--cpukit/backward/vmeintr.h7
-rw-r--r--cpukit/backward/zilog/z8030.h7
-rw-r--r--cpukit/backward/zilog/z8036.h7
-rw-r--r--cpukit/backward/zilog/z8536.h7
-rw-r--r--cpukit/configure.ac323
-rw-r--r--cpukit/ftpd/Makefile.am45
-rw-r--r--cpukit/ftpd/ftpd.c2062
-rw-r--r--cpukit/ftpd/ftpd.h56
-rw-r--r--cpukit/httpd/.cvsignore2
-rw-r--r--cpukit/httpd/Makefile.am97
-rw-r--r--cpukit/httpd/NOTES36
-rw-r--r--cpukit/httpd/asp.c321
-rw-r--r--cpukit/httpd/balloc.c967
-rw-r--r--cpukit/httpd/cgi.c331
-rw-r--r--cpukit/httpd/default.c431
-rw-r--r--cpukit/httpd/ej.h46
-rw-r--r--cpukit/httpd/ejIntrn.h230
-rw-r--r--cpukit/httpd/ejlex.c721
-rw-r--r--cpukit/httpd/ejparse.c1804
-rw-r--r--cpukit/httpd/emfdb.c1050
-rw-r--r--cpukit/httpd/emfdb.h101
-rw-r--r--cpukit/httpd/form.c168
-rw-r--r--cpukit/httpd/h.c194
-rw-r--r--cpukit/httpd/handler.c411
-rw-r--r--cpukit/httpd/license.txt282
-rw-r--r--cpukit/httpd/md5.h50
-rw-r--r--cpukit/httpd/md5c.c337
-rw-r--r--cpukit/httpd/mime.c116
-rw-r--r--cpukit/httpd/misc.c675
-rw-r--r--cpukit/httpd/ringq.c584
-rw-r--r--cpukit/httpd/rom.c193
-rw-r--r--cpukit/httpd/rtems_webserver.h6
-rw-r--r--cpukit/httpd/security.c235
-rw-r--r--cpukit/httpd/sock.c791
-rw-r--r--cpukit/httpd/sockGen.c1043
-rw-r--r--cpukit/httpd/socket.c1023
-rw-r--r--cpukit/httpd/sym.c474
-rw-r--r--cpukit/httpd/uemf.c293
-rw-r--r--cpukit/httpd/uemf.h1110
-rw-r--r--cpukit/httpd/um.c1435
-rw-r--r--cpukit/httpd/um.h183
-rw-r--r--cpukit/httpd/umui.c641
-rw-r--r--cpukit/httpd/url.c212
-rw-r--r--cpukit/httpd/value.c1213
-rw-r--r--cpukit/httpd/wbase64.c149
-rw-r--r--cpukit/httpd/webcomp.c188
-rw-r--r--cpukit/httpd/webmain.c499
-rw-r--r--cpukit/httpd/webpage.c141
-rw-r--r--cpukit/httpd/webrom.c15
-rw-r--r--cpukit/httpd/webs.c2961
-rw-r--r--cpukit/httpd/webs.h233
-rw-r--r--cpukit/httpd/websSSL.c706
-rw-r--r--cpukit/httpd/websSSL.h67
-rw-r--r--cpukit/httpd/websda.c244
-rw-r--r--cpukit/httpd/websda.h41
-rw-r--r--cpukit/httpd/websuemf.c217
-rw-r--r--cpukit/httpd/wsIntrn.h309
-rw-r--r--cpukit/include/rtems/bspIo.h39
-rw-r--r--cpukit/include/rtems/concat.h19
-rw-r--r--cpukit/include/rtems/fs.h59
-rw-r--r--cpukit/include/rtems/pci.h1153
-rw-r--r--cpukit/include/rtems/stdint.h54
-rw-r--r--cpukit/include/rtems/userenv.h86
-rw-r--r--cpukit/itron/.cvsignore2
-rw-r--r--cpukit/itron/Makefile.am370
-rw-r--r--cpukit/itron/include/itron.h51
-rw-r--r--cpukit/itron/include/itronsys/README9
-rw-r--r--cpukit/itron/include/itronsys/eventflags.h145
-rw-r--r--cpukit/itron/include/itronsys/fmempool.h124
-rw-r--r--cpukit/itron/include/itronsys/intr.h105
-rw-r--r--cpukit/itron/include/itronsys/mbox.h137
-rw-r--r--cpukit/itron/include/itronsys/msgbuffer.h159
-rw-r--r--cpukit/itron/include/itronsys/network.h77
-rw-r--r--cpukit/itron/include/itronsys/port.h189
-rw-r--r--cpukit/itron/include/itronsys/semaphore.h120
-rw-r--r--cpukit/itron/include/itronsys/status.h69
-rw-r--r--cpukit/itron/include/itronsys/sysmgmt.h318
-rw-r--r--cpukit/itron/include/itronsys/task.h297
-rw-r--r--cpukit/itron/include/itronsys/time.h184
-rw-r--r--cpukit/itron/include/itronsys/types.h120
-rw-r--r--cpukit/itron/include/itronsys/vmempool.h131
-rw-r--r--cpukit/itron/include/rtems/itron/README10
-rw-r--r--cpukit/itron/include/rtems/itron/config.h62
-rw-r--r--cpukit/itron/include/rtems/itron/eventflags.h60
-rw-r--r--cpukit/itron/include/rtems/itron/fmempool.h61
-rw-r--r--cpukit/itron/include/rtems/itron/intr.h30
-rw-r--r--cpukit/itron/include/rtems/itron/itronapi.h30
-rw-r--r--cpukit/itron/include/rtems/itron/mbox.h72
-rw-r--r--cpukit/itron/include/rtems/itron/msgbuffer.h72
-rw-r--r--cpukit/itron/include/rtems/itron/network.h30
-rw-r--r--cpukit/itron/include/rtems/itron/object.h119
-rw-r--r--cpukit/itron/include/rtems/itron/port.h60
-rw-r--r--cpukit/itron/include/rtems/itron/semaphore.h58
-rw-r--r--cpukit/itron/include/rtems/itron/sysmgmt.h30
-rw-r--r--cpukit/itron/include/rtems/itron/task.h101
-rw-r--r--cpukit/itron/include/rtems/itron/time.h30
-rw-r--r--cpukit/itron/include/rtems/itron/vmempool.h61
-rw-r--r--cpukit/itron/inline/rtems/itron/eventflags.inl151
-rw-r--r--cpukit/itron/inline/rtems/itron/fmempool.inl158
-rw-r--r--cpukit/itron/inline/rtems/itron/intr.inl30
-rw-r--r--cpukit/itron/inline/rtems/itron/mbox.inl151
-rw-r--r--cpukit/itron/inline/rtems/itron/msgbuffer.inl156
-rw-r--r--cpukit/itron/inline/rtems/itron/network.inl30
-rw-r--r--cpukit/itron/inline/rtems/itron/port.inl151
-rw-r--r--cpukit/itron/inline/rtems/itron/semaphore.inl183
-rw-r--r--cpukit/itron/inline/rtems/itron/sysmgmt.inl30
-rw-r--r--cpukit/itron/inline/rtems/itron/task.inl181
-rw-r--r--cpukit/itron/inline/rtems/itron/time.inl30
-rw-r--r--cpukit/itron/inline/rtems/itron/vmempool.inl161
-rw-r--r--cpukit/itron/macros/rtems/itron/eventflags.inl76
-rw-r--r--cpukit/itron/macros/rtems/itron/fmempool.inl78
-rw-r--r--cpukit/itron/macros/rtems/itron/intr.inl30
-rw-r--r--cpukit/itron/macros/rtems/itron/mbox.inl75
-rw-r--r--cpukit/itron/macros/rtems/itron/msgbuffer.inl78
-rw-r--r--cpukit/itron/macros/rtems/itron/network.inl30
-rw-r--r--cpukit/itron/macros/rtems/itron/port.inl75
-rw-r--r--cpukit/itron/macros/rtems/itron/semaphore.inl102
-rw-r--r--cpukit/itron/macros/rtems/itron/sysmgmt.inl30
-rw-r--r--cpukit/itron/macros/rtems/itron/task.inl102
-rw-r--r--cpukit/itron/macros/rtems/itron/time.inl30
-rw-r--r--cpukit/itron/macros/rtems/itron/vmempool.inl81
-rw-r--r--cpukit/itron/src/.cvsignore4
-rw-r--r--cpukit/itron/src/TODO13
-rw-r--r--cpukit/itron/src/can_wup.c52
-rw-r--r--cpukit/itron/src/chg_pri.c68
-rw-r--r--cpukit/itron/src/cre_mbf.c89
-rw-r--r--cpukit/itron/src/cre_mbx.c107
-rw-r--r--cpukit/itron/src/cre_sem.c98
-rw-r--r--cpukit/itron/src/cre_tsk.c120
-rw-r--r--cpukit/itron/src/del_mbf.c58
-rw-r--r--cpukit/itron/src/del_mbx.c68
-rw-r--r--cpukit/itron/src/del_sem.c68
-rw-r--r--cpukit/itron/src/del_tsk.c58
-rw-r--r--cpukit/itron/src/dis_dsp.c40
-rw-r--r--cpukit/itron/src/ena_dsp.c36
-rw-r--r--cpukit/itron/src/eventflags.c159
-rw-r--r--cpukit/itron/src/exd_tsk.c46
-rw-r--r--cpukit/itron/src/ext_tsk.c46
-rw-r--r--cpukit/itron/src/fmempool.c142
-rw-r--r--cpukit/itron/src/frsm_tsk.c60
-rw-r--r--cpukit/itron/src/get_tid.c41
-rw-r--r--cpukit/itron/src/itronintr.c110
-rw-r--r--cpukit/itron/src/itronsem.c60
-rw-r--r--cpukit/itron/src/itrontime.c247
-rw-r--r--cpukit/itron/src/mbox.c59
-rw-r--r--cpukit/itron/src/mboxtranslatereturncode.c48
-rw-r--r--cpukit/itron/src/msgbuffer.c60
-rw-r--r--cpukit/itron/src/msgbuffertranslatereturncode.c48
-rw-r--r--cpukit/itron/src/network.c71
-rw-r--r--cpukit/itron/src/port.c211
-rw-r--r--cpukit/itron/src/prcv_mbf.c34
-rw-r--r--cpukit/itron/src/prcv_mbx.c33
-rw-r--r--cpukit/itron/src/preq_sem.c33
-rw-r--r--cpukit/itron/src/psnd_mbf.c34
-rw-r--r--cpukit/itron/src/rcv_mbf.c34
-rw-r--r--cpukit/itron/src/rcv_mbx.c33
-rw-r--r--cpukit/itron/src/ref_mbf.c83
-rw-r--r--cpukit/itron/src/ref_mbx.c65
-rw-r--r--cpukit/itron/src/ref_sem.c65
-rw-r--r--cpukit/itron/src/ref_tsk.c99
-rw-r--r--cpukit/itron/src/rel_wai.c52
-rw-r--r--cpukit/itron/src/rot_rdq.c55
-rw-r--r--cpukit/itron/src/rsm_tsk.c60
-rw-r--r--cpukit/itron/src/sig_sem.c56
-rw-r--r--cpukit/itron/src/slp_tsk.c35
-rw-r--r--cpukit/itron/src/snd_mbf.c34
-rw-r--r--cpukit/itron/src/snd_mbx.c70
-rw-r--r--cpukit/itron/src/sta_tsk.c69
-rw-r--r--cpukit/itron/src/sus_tsk.c62
-rw-r--r--cpukit/itron/src/sysmgmt.c75
-rw-r--r--cpukit/itron/src/task.c227
-rw-r--r--cpukit/itron/src/ter_tsk.c58
-rw-r--r--cpukit/itron/src/trcv_mbf.c84
-rw-r--r--cpukit/itron/src/trcv_mbx.c76
-rw-r--r--cpukit/itron/src/tslp_tsk.c36
-rw-r--r--cpukit/itron/src/tsnd_mbf.c90
-rw-r--r--cpukit/itron/src/twai_sem.c69
-rw-r--r--cpukit/itron/src/vmempool.c145
-rw-r--r--cpukit/itron/src/wai_sem.c33
-rw-r--r--cpukit/itron/src/wup_tsk.c36
-rw-r--r--cpukit/libblock/.cvsignore2
-rw-r--r--cpukit/libblock/Makefile.am68
-rw-r--r--cpukit/libblock/README14
-rw-r--r--cpukit/libblock/include/rtems/bdbuf.h275
-rw-r--r--cpukit/libblock/include/rtems/blkdev.h151
-rw-r--r--cpukit/libblock/include/rtems/diskdevs.h206
-rw-r--r--cpukit/libblock/include/rtems/ide_part_table.h193
-rw-r--r--cpukit/libblock/include/rtems/ramdisk.h52
-rw-r--r--cpukit/libblock/src/bdbuf.c1653
-rw-r--r--cpukit/libblock/src/blkdev.c249
-rw-r--r--cpukit/libblock/src/diskdevs.c635
-rw-r--r--cpukit/libblock/src/ide_part_table.c550
-rw-r--r--cpukit/libblock/src/ramdisk.c231
-rw-r--r--cpukit/libcsupport/.cvsignore2
-rw-r--r--cpukit/libcsupport/Makefile.am282
-rw-r--r--cpukit/libcsupport/include/chain.h361
-rw-r--r--cpukit/libcsupport/include/clockdrv.h50
-rw-r--r--cpukit/libcsupport/include/console.h68
-rw-r--r--cpukit/libcsupport/include/inttypes.h22
-rw-r--r--cpukit/libcsupport/include/iosupp.h43
-rw-r--r--cpukit/libcsupport/include/motorola/mc68230.h70
-rw-r--r--cpukit/libcsupport/include/motorola/mc68681.h303
-rw-r--r--cpukit/libcsupport/include/ringbuf.h53
-rw-r--r--cpukit/libcsupport/include/rtc.h38
-rw-r--r--cpukit/libcsupport/include/rtems/assoc.h42
-rw-r--r--cpukit/libcsupport/include/rtems/cdefs.h177
-rw-r--r--cpukit/libcsupport/include/rtems/error.h47
-rw-r--r--cpukit/libcsupport/include/rtems/libcsupport.h43
-rw-r--r--cpukit/libcsupport/include/rtems/libio.h633
-rw-r--r--cpukit/libcsupport/include/rtems/libio_.h254
-rw-r--r--cpukit/libcsupport/include/rtems/termiostypes.h177
-rw-r--r--cpukit/libcsupport/include/spurious.h38
-rw-r--r--cpukit/libcsupport/include/stdint.h35
-rw-r--r--cpukit/libcsupport/include/sys/cdefs.h177
-rw-r--r--cpukit/libcsupport/include/sys/filio.h59
-rw-r--r--cpukit/libcsupport/include/sys/ioccom.h100
-rw-r--r--cpukit/libcsupport/include/sys/ioctl.h77
-rw-r--r--cpukit/libcsupport/include/sys/sockio.h92
-rw-r--r--cpukit/libcsupport/include/sys/termios.h198
-rw-r--r--cpukit/libcsupport/include/sys/ttycom.h141
-rw-r--r--cpukit/libcsupport/include/sys/utsname.h55
-rw-r--r--cpukit/libcsupport/include/timerdrv.h39
-rw-r--r--cpukit/libcsupport/include/vmeintr.h57
-rw-r--r--cpukit/libcsupport/include/zilog/z8036.h107
-rw-r--r--cpukit/libcsupport/include/zilog/z8530.h98
-rw-r--r--cpukit/libcsupport/include/zilog/z8536.h111
-rw-r--r--cpukit/libcsupport/src/.cvsignore4
-rw-r--r--cpukit/libcsupport/src/CASES23
-rw-r--r--cpukit/libcsupport/src/README37
-rw-r--r--cpukit/libcsupport/src/TODO14
-rw-r--r--cpukit/libcsupport/src/__brk.c32
-rw-r--r--cpukit/libcsupport/src/__getpid.c17
-rw-r--r--cpukit/libcsupport/src/__gettod.c120
-rw-r--r--cpukit/libcsupport/src/__sbrk.c32
-rw-r--r--cpukit/libcsupport/src/__times.c89
-rw-r--r--cpukit/libcsupport/src/access.c48
-rw-r--r--cpukit/libcsupport/src/assoc.c254
-rw-r--r--cpukit/libcsupport/src/assocnamebad.c39
-rw-r--r--cpukit/libcsupport/src/base_fs.c150
-rw-r--r--cpukit/libcsupport/src/cfgetispeed.c32
-rw-r--r--cpukit/libcsupport/src/cfgetospeed.c32
-rw-r--r--cpukit/libcsupport/src/cfsetispeed.c40
-rw-r--r--cpukit/libcsupport/src/cfsetospeed.c40
-rw-r--r--cpukit/libcsupport/src/chdir.c61
-rw-r--r--cpukit/libcsupport/src/chmod.c56
-rw-r--r--cpukit/libcsupport/src/chown.c49
-rw-r--r--cpukit/libcsupport/src/chroot.c54
-rw-r--r--cpukit/libcsupport/src/close.c58
-rw-r--r--cpukit/libcsupport/src/closedir.c74
-rw-r--r--cpukit/libcsupport/src/creat.c19
-rw-r--r--cpukit/libcsupport/src/ctermid.c37
-rw-r--r--cpukit/libcsupport/src/dup.c26
-rw-r--r--cpukit/libcsupport/src/dup2.c52
-rw-r--r--cpukit/libcsupport/src/envlock.c108
-rw-r--r--cpukit/libcsupport/src/error.c213
-rw-r--r--cpukit/libcsupport/src/eval.c123
-rw-r--r--cpukit/libcsupport/src/fchdir.c90
-rw-r--r--cpukit/libcsupport/src/fchmod.c48
-rw-r--r--cpukit/libcsupport/src/fcntl.c188
-rw-r--r--cpukit/libcsupport/src/fdatasync.c42
-rw-r--r--cpukit/libcsupport/src/fpathconf.c87
-rw-r--r--cpukit/libcsupport/src/fs_null_handlers.c41
-rw-r--r--cpukit/libcsupport/src/fstat.c80
-rw-r--r--cpukit/libcsupport/src/fsync.c45
-rw-r--r--cpukit/libcsupport/src/ftruncate.c57
-rw-r--r--cpukit/libcsupport/src/getcwd.c287
-rw-r--r--cpukit/libcsupport/src/getdents.c63
-rw-r--r--cpukit/libcsupport/src/getegid.c32
-rw-r--r--cpukit/libcsupport/src/geteuid.c33
-rw-r--r--cpukit/libcsupport/src/getgid.c47
-rw-r--r--cpukit/libcsupport/src/getgroups.c29
-rw-r--r--cpukit/libcsupport/src/getlogin.c64
-rw-r--r--cpukit/libcsupport/src/getpgrp.c31
-rw-r--r--cpukit/libcsupport/src/getpid.c44
-rw-r--r--cpukit/libcsupport/src/getppid.c28
-rw-r--r--cpukit/libcsupport/src/getpwent.c443
-rw-r--r--cpukit/libcsupport/src/getuid.c47
-rw-r--r--cpukit/libcsupport/src/gxx_wrappers.c217
-rw-r--r--cpukit/libcsupport/src/hosterr.c51
-rw-r--r--cpukit/libcsupport/src/ioctl.c60
-rw-r--r--cpukit/libcsupport/src/isatty.c31
-rw-r--r--cpukit/libcsupport/src/libio.c333
-rw-r--r--cpukit/libcsupport/src/libio_sockets.c75
-rw-r--r--cpukit/libcsupport/src/link.c104
-rw-r--r--cpukit/libcsupport/src/lseek.c101
-rw-r--r--cpukit/libcsupport/src/lstat.c18
-rw-r--r--cpukit/libcsupport/src/malloc.c487
-rw-r--r--cpukit/libcsupport/src/mallocfreespace.c44
-rw-r--r--cpukit/libcsupport/src/mkdir.c30
-rw-r--r--cpukit/libcsupport/src/mkfifo.c28
-rw-r--r--cpukit/libcsupport/src/mknod.c73
-rw-r--r--cpukit/libcsupport/src/mount.c291
-rw-r--r--cpukit/libcsupport/src/newlibc.c386
-rw-r--r--cpukit/libcsupport/src/no_libc.c59
-rw-r--r--cpukit/libcsupport/src/no_posix.c87
-rw-r--r--cpukit/libcsupport/src/open.c221
-rw-r--r--cpukit/libcsupport/src/opendir.c89
-rw-r--r--cpukit/libcsupport/src/pathconf.c41
-rw-r--r--cpukit/libcsupport/src/pipe.c26
-rw-r--r--cpukit/libcsupport/src/printk.c157
-rw-r--r--cpukit/libcsupport/src/privateenv.c163
-rw-r--r--cpukit/libcsupport/src/read.c71
-rw-r--r--cpukit/libcsupport/src/readdir.c90
-rw-r--r--cpukit/libcsupport/src/readdir_r.c22
-rw-r--r--cpukit/libcsupport/src/readlink.c57
-rw-r--r--cpukit/libcsupport/src/rewinddir.c39
-rw-r--r--cpukit/libcsupport/src/rmdir.c76
-rw-r--r--cpukit/libcsupport/src/scandir.c168
-rw-r--r--cpukit/libcsupport/src/seekdir.c44
-rw-r--r--cpukit/libcsupport/src/setpgid.c29
-rw-r--r--cpukit/libcsupport/src/setsid.c26
-rw-r--r--cpukit/libcsupport/src/stat.c104
-rw-r--r--cpukit/libcsupport/src/strlcat.c41
-rw-r--r--cpukit/libcsupport/src/strlcpy.c49
-rw-r--r--cpukit/libcsupport/src/symlink.c46
-rw-r--r--cpukit/libcsupport/src/sync.c89
-rw-r--r--cpukit/libcsupport/src/tcdrain.c36
-rw-r--r--cpukit/libcsupport/src/tcflow.c34
-rw-r--r--cpukit/libcsupport/src/tcflush.c34
-rw-r--r--cpukit/libcsupport/src/tcgetattr.c36
-rw-r--r--cpukit/libcsupport/src/tcgetprgrp.c34
-rw-r--r--cpukit/libcsupport/src/tcsendbreak.c34
-rw-r--r--cpukit/libcsupport/src/tcsetattr.c51
-rw-r--r--cpukit/libcsupport/src/tcsetpgrp.c34
-rw-r--r--cpukit/libcsupport/src/telldir.c47
-rw-r--r--cpukit/libcsupport/src/termios.c1495
-rw-r--r--cpukit/libcsupport/src/termiosinitialize.c54
-rw-r--r--cpukit/libcsupport/src/termiosreserveresources.c36
-rw-r--r--cpukit/libcsupport/src/truncate.c43
-rw-r--r--cpukit/libcsupport/src/ttyname.c77
-rw-r--r--cpukit/libcsupport/src/ttyname_r.c118
-rw-r--r--cpukit/libcsupport/src/umask.c33
-rw-r--r--cpukit/libcsupport/src/unixlibc.c53
-rw-r--r--cpukit/libcsupport/src/unlink.c83
-rw-r--r--cpukit/libcsupport/src/unmount.c219
-rw-r--r--cpukit/libcsupport/src/utime.c46
-rw-r--r--cpukit/libcsupport/src/utsname.c53
-rw-r--r--cpukit/libcsupport/src/write.c78
-rw-r--r--cpukit/libfs/.cvsignore3
-rw-r--r--cpukit/libfs/Makefile.am110
-rw-r--r--cpukit/libfs/README13
-rw-r--r--cpukit/libfs/src/dosfs/.cvsignore4
-rw-r--r--cpukit/libfs/src/dosfs/dosfs.h31
-rw-r--r--cpukit/libfs/src/dosfs/fat.c708
-rw-r--r--cpukit/libfs/src/dosfs/fat.h492
-rw-r--r--cpukit/libfs/src/dosfs/fat_fat_operations.c437
-rw-r--r--cpukit/libfs/src/dosfs/fat_fat_operations.h58
-rw-r--r--cpukit/libfs/src/dosfs/fat_file.c987
-rw-r--r--cpukit/libfs/src/dosfs/fat_file.h195
-rw-r--r--cpukit/libfs/src/dosfs/msdos.h436
-rw-r--r--cpukit/libfs/src/dosfs/msdos_conv.c268
-rw-r--r--cpukit/libfs/src/dosfs/msdos_create.c345
-rw-r--r--cpukit/libfs/src/dosfs/msdos_dir.c553
-rw-r--r--cpukit/libfs/src/dosfs/msdos_eval.c435
-rw-r--r--cpukit/libfs/src/dosfs/msdos_file.c485
-rw-r--r--cpukit/libfs/src/dosfs/msdos_free.c56
-rw-r--r--cpukit/libfs/src/dosfs/msdos_fsunmount.c71
-rw-r--r--cpukit/libfs/src/dosfs/msdos_handlers_dir.c36
-rw-r--r--cpukit/libfs/src/dosfs/msdos_handlers_file.c36
-rw-r--r--cpukit/libfs/src/dosfs/msdos_init.c64
-rw-r--r--cpukit/libfs/src/dosfs/msdos_initsupp.c149
-rw-r--r--cpukit/libfs/src/dosfs/msdos_misc.c942
-rw-r--r--cpukit/libfs/src/dosfs/msdos_mknod.c90
-rw-r--r--cpukit/libfs/src/dosfs/msdos_node_type.c58
-rw-r--r--cpukit/libfs/src/imfs/.cvsignore5
-rw-r--r--cpukit/libfs/src/imfs/deviceio.c257
-rw-r--r--cpukit/libfs/src/imfs/imfs.h546
-rw-r--r--cpukit/libfs/src/imfs/imfs_chown.c56
-rw-r--r--cpukit/libfs/src/imfs/imfs_config.c35
-rw-r--r--cpukit/libfs/src/imfs/imfs_creat.c137
-rw-r--r--cpukit/libfs/src/imfs/imfs_debug.c176
-rw-r--r--cpukit/libfs/src/imfs/imfs_directory.c351
-rw-r--r--cpukit/libfs/src/imfs/imfs_eval.c660
-rw-r--r--cpukit/libfs/src/imfs/imfs_fchmod.c84
-rw-r--r--cpukit/libfs/src/imfs/imfs_fcntl.c28
-rw-r--r--cpukit/libfs/src/imfs/imfs_fdatasync.c29
-rw-r--r--cpukit/libfs/src/imfs/imfs_free.c39
-rw-r--r--cpukit/libfs/src/imfs/imfs_fsunmount.c96
-rw-r--r--cpukit/libfs/src/imfs/imfs_getchild.c73
-rw-r--r--cpukit/libfs/src/imfs/imfs_gtkn.c90
-rw-r--r--cpukit/libfs/src/imfs/imfs_handlers_device.c41
-rw-r--r--cpukit/libfs/src/imfs/imfs_handlers_directory.c41
-rw-r--r--cpukit/libfs/src/imfs/imfs_handlers_link.c41
-rw-r--r--cpukit/libfs/src/imfs/imfs_handlers_memfile.c58
-rw-r--r--cpukit/libfs/src/imfs/imfs_init.c70
-rw-r--r--cpukit/libfs/src/imfs/imfs_initsupp.c89
-rw-r--r--cpukit/libfs/src/imfs/imfs_link.c75
-rw-r--r--cpukit/libfs/src/imfs/imfs_load_tar.c260
-rw-r--r--cpukit/libfs/src/imfs/imfs_mknod.c77
-rw-r--r--cpukit/libfs/src/imfs/imfs_mount.c53
-rw-r--r--cpukit/libfs/src/imfs/imfs_ntype.c32
-rw-r--r--cpukit/libfs/src/imfs/imfs_readlink.c44
-rw-r--r--cpukit/libfs/src/imfs/imfs_rmnod.c79
-rw-r--r--cpukit/libfs/src/imfs/imfs_stat.c68
-rw-r--r--cpukit/libfs/src/imfs/imfs_symlink.c62
-rw-r--r--cpukit/libfs/src/imfs/imfs_unixstub.c74
-rw-r--r--cpukit/libfs/src/imfs/imfs_unlink.c81
-rw-r--r--cpukit/libfs/src/imfs/imfs_unmount.c62
-rw-r--r--cpukit/libfs/src/imfs/imfs_utime.c41
-rw-r--r--cpukit/libfs/src/imfs/ioman.c107
-rw-r--r--cpukit/libfs/src/imfs/linearfile.c115
-rw-r--r--cpukit/libfs/src/imfs/memfile.c1143
-rw-r--r--cpukit/libfs/src/imfs/miniimfs_init.c70
-rw-r--r--cpukit/libmisc/.cvsignore2
-rw-r--r--cpukit/libmisc/Makefile.am331
-rw-r--r--cpukit/libmisc/README23
-rw-r--r--cpukit/libmisc/capture/README255
-rw-r--r--cpukit/libmisc/capture/capture-cli.c1470
-rw-r--r--cpukit/libmisc/capture/capture-cli.h52
-rw-r--r--cpukit/libmisc/capture/capture.c1569
-rw-r--r--cpukit/libmisc/capture/capture.h869
-rw-r--r--cpukit/libmisc/cpuuse/README41
-rw-r--r--cpukit/libmisc/cpuuse/cpuuse.c148
-rw-r--r--cpukit/libmisc/cpuuse/cpuuse.h40
-rw-r--r--cpukit/libmisc/devnull/devnull.c184
-rw-r--r--cpukit/libmisc/devnull/devnull.h71
-rw-r--r--cpukit/libmisc/dummy/README23
-rw-r--r--cpukit/libmisc/dummy/dummy.c45
-rw-r--r--cpukit/libmisc/dumpbuf/dumpbuf.c79
-rw-r--r--cpukit/libmisc/dumpbuf/dumpbuf.h21
-rw-r--r--cpukit/libmisc/fsmount/README24
-rw-r--r--cpukit/libmisc/fsmount/fsmount.c195
-rw-r--r--cpukit/libmisc/fsmount/fsmount.h71
-rw-r--r--cpukit/libmisc/monitor/README97
-rw-r--r--cpukit/libmisc/monitor/mon-command.c745
-rw-r--r--cpukit/libmisc/monitor/mon-config.c134
-rw-r--r--cpukit/libmisc/monitor/mon-dname.c116
-rw-r--r--cpukit/libmisc/monitor/mon-driver.c140
-rw-r--r--cpukit/libmisc/monitor/mon-extension.c102
-rw-r--r--cpukit/libmisc/monitor/mon-itask.c119
-rw-r--r--cpukit/libmisc/monitor/mon-manager.c54
-rw-r--r--cpukit/libmisc/monitor/mon-monitor.c591
-rw-r--r--cpukit/libmisc/monitor/mon-mpci.c162
-rw-r--r--cpukit/libmisc/monitor/mon-object.c387
-rw-r--r--cpukit/libmisc/monitor/mon-prmisc.c268
-rw-r--r--cpukit/libmisc/monitor/mon-queue.c68
-rw-r--r--cpukit/libmisc/monitor/mon-server.c307
-rw-r--r--cpukit/libmisc/monitor/mon-symbols.c486
-rw-r--r--cpukit/libmisc/monitor/mon-task.c96
-rw-r--r--cpukit/libmisc/monitor/monitor.h459
-rw-r--r--cpukit/libmisc/monitor/symbols.h64
-rw-r--r--cpukit/libmisc/mw-fb/mw_fb.c194
-rw-r--r--cpukit/libmisc/mw-fb/mw_fb.h170
-rw-r--r--cpukit/libmisc/mw-fb/mw_uid.c248
-rw-r--r--cpukit/libmisc/mw-fb/mw_uid.h160
-rw-r--r--cpukit/libmisc/rtmonuse/rtmonuse.c208
-rw-r--r--cpukit/libmisc/rtmonuse/rtmonuse.h18
-rw-r--r--cpukit/libmisc/serdbg/README138
-rw-r--r--cpukit/libmisc/serdbg/serdbg.c94
-rw-r--r--cpukit/libmisc/serdbg/serdbg.h174
-rw-r--r--cpukit/libmisc/serdbg/serdbgcnf.h81
-rw-r--r--cpukit/libmisc/serdbg/serdbgio.c256
-rw-r--r--cpukit/libmisc/serdbg/termios_printk.c237
-rw-r--r--cpukit/libmisc/serdbg/termios_printk.h95
-rw-r--r--cpukit/libmisc/serdbg/termios_printk_cnf.h70
-rw-r--r--cpukit/libmisc/shell/README27
-rw-r--r--cpukit/libmisc/shell/cmds.c526
-rw-r--r--cpukit/libmisc/shell/shell.c682
-rw-r--r--cpukit/libmisc/shell/shell.h88
-rw-r--r--cpukit/libmisc/stackchk/README56
-rw-r--r--cpukit/libmisc/stackchk/check.c553
-rw-r--r--cpukit/libmisc/stackchk/internal.h95
-rw-r--r--cpukit/libmisc/stackchk/stackchk.h82
-rw-r--r--cpukit/libmisc/untar/README26
-rw-r--r--cpukit/libmisc/untar/untar.c385
-rw-r--r--cpukit/libmisc/untar/untar.h25
-rw-r--r--cpukit/libnetworking/.cvsignore2
-rw-r--r--cpukit/libnetworking/Makefile.am654
-rw-r--r--cpukit/libnetworking/README72
-rw-r--r--cpukit/libnetworking/arpa/ftp.h111
-rw-r--r--cpukit/libnetworking/arpa/inet.h105
-rw-r--r--cpukit/libnetworking/arpa/nameser.h448
-rw-r--r--cpukit/libnetworking/arpa/nameser_compat.h194
-rw-r--r--cpukit/libnetworking/arpa/telnet.h342
-rw-r--r--cpukit/libnetworking/bpfilter.h5
-rw-r--r--cpukit/libnetworking/kern/kern_mib.c382
-rw-r--r--cpukit/libnetworking/kern/kern_subr.c206
-rw-r--r--cpukit/libnetworking/kern/kern_sysctl.c1543
-rw-r--r--cpukit/libnetworking/kern/uipc_domain.c228
-rw-r--r--cpukit/libnetworking/kern/uipc_mbuf.c777
-rw-r--r--cpukit/libnetworking/kern/uipc_socket.c1142
-rw-r--r--cpukit/libnetworking/kern/uipc_socket2.c964
-rw-r--r--cpukit/libnetworking/lib/README5
-rw-r--r--cpukit/libnetworking/lib/ftpfs.c1159
-rw-r--r--cpukit/libnetworking/lib/getprotoby.c46
-rw-r--r--cpukit/libnetworking/lib/rtems_bsdnet_ntp.c187
-rw-r--r--cpukit/libnetworking/lib/syslog.c190
-rw-r--r--cpukit/libnetworking/lib/tftpDriver.c1049
-rw-r--r--cpukit/libnetworking/libc/addr2ascii.3217
-rw-r--r--cpukit/libnetworking/libc/addr2ascii.c94
-rw-r--r--cpukit/libnetworking/libc/ascii2addr.c74
-rw-r--r--cpukit/libnetworking/libc/base64.c318
-rw-r--r--cpukit/libnetworking/libc/byteorder.377
-rw-r--r--cpukit/libnetworking/libc/ether_addr.c226
-rw-r--r--cpukit/libnetworking/libc/ethers.3193
-rw-r--r--cpukit/libnetworking/libc/gethostbydns.c775
-rw-r--r--cpukit/libnetworking/libc/gethostbyht.c202
-rw-r--r--cpukit/libnetworking/libc/gethostbyname.3305
-rw-r--r--cpukit/libnetworking/libc/gethostbynis.c142
-rw-r--r--cpukit/libnetworking/libc/gethostnamadr.c224
-rw-r--r--cpukit/libnetworking/libc/gethostname.c26
-rw-r--r--cpukit/libnetworking/libc/getnetbydns.c313
-rw-r--r--cpukit/libnetworking/libc/getnetbyht.c173
-rw-r--r--cpukit/libnetworking/libc/getnetbynis.c177
-rw-r--r--cpukit/libnetworking/libc/getnetent.3159
-rw-r--r--cpukit/libnetworking/libc/getnetnamadr.c190
-rw-r--r--cpukit/libnetworking/libc/getproto.c62
-rw-r--r--cpukit/libnetworking/libc/getprotoent.3147
-rw-r--r--cpukit/libnetworking/libc/getprotoent.c121
-rw-r--r--cpukit/libnetworking/libc/getprotoname.c69
-rw-r--r--cpukit/libnetworking/libc/getservbyname.c81
-rw-r--r--cpukit/libnetworking/libc/getservbyport.c76
-rw-r--r--cpukit/libnetworking/libc/getservent.3156
-rw-r--r--cpukit/libnetworking/libc/getservent.c281
-rw-r--r--cpukit/libnetworking/libc/herror.c122
-rw-r--r--cpukit/libnetworking/libc/inet.3210
-rw-r--r--cpukit/libnetworking/libc/inet_addr.c180
-rw-r--r--cpukit/libnetworking/libc/inet_lnaof.c61
-rw-r--r--cpukit/libnetworking/libc/inet_makeaddr.c64
-rw-r--r--cpukit/libnetworking/libc/inet_net_ntop.c140
-rw-r--r--cpukit/libnetworking/libc/inet_net_pton.c207
-rw-r--r--cpukit/libnetworking/libc/inet_neta.c84
-rw-r--r--cpukit/libnetworking/libc/inet_netof.c60
-rw-r--r--cpukit/libnetworking/libc/inet_network.c92
-rw-r--r--cpukit/libnetworking/libc/inet_ntoa.c60
-rw-r--r--cpukit/libnetworking/libc/inet_ntop.c191
-rw-r--r--cpukit/libnetworking/libc/inet_pton.c214
-rw-r--r--cpukit/libnetworking/libc/iso_addr.3111
-rw-r--r--cpukit/libnetworking/libc/iso_addr.c119
-rw-r--r--cpukit/libnetworking/libc/linkaddr.3138
-rw-r--r--cpukit/libnetworking/libc/linkaddr.c161
-rw-r--r--cpukit/libnetworking/libc/map_v4v6.c128
-rw-r--r--cpukit/libnetworking/libc/ns.3131
-rw-r--r--cpukit/libnetworking/libc/ns_addr.c229
-rw-r--r--cpukit/libnetworking/libc/ns_name.c595
-rw-r--r--cpukit/libnetworking/libc/ns_netint.c56
-rw-r--r--cpukit/libnetworking/libc/ns_ntoa.c102
-rw-r--r--cpukit/libnetworking/libc/ns_parse.c192
-rw-r--r--cpukit/libnetworking/libc/ns_print.c745
-rw-r--r--cpukit/libnetworking/libc/ns_ttl.c153
-rw-r--r--cpukit/libnetworking/libc/nsap_addr.c105
-rw-r--r--cpukit/libnetworking/libc/rcmd.3204
-rw-r--r--cpukit/libnetworking/libc/rcmd.c547
-rw-r--r--cpukit/libnetworking/libc/recv.c52
-rw-r--r--cpukit/libnetworking/libc/res_comp.c258
-rw-r--r--cpukit/libnetworking/libc/res_config.h20
-rw-r--r--cpukit/libnetworking/libc/res_data.c83
-rw-r--r--cpukit/libnetworking/libc/res_debug.c966
-rw-r--r--cpukit/libnetworking/libc/res_init.c501
-rw-r--r--cpukit/libnetworking/libc/res_mkquery.c199
-rw-r--r--cpukit/libnetworking/libc/res_mkupdate.c415
-rw-r--r--cpukit/libnetworking/libc/res_query.c410
-rw-r--r--cpukit/libnetworking/libc/res_send.c932
-rw-r--r--cpukit/libnetworking/libc/res_stubs.c75
-rw-r--r--cpukit/libnetworking/libc/res_update.c518
-rw-r--r--cpukit/libnetworking/libc/resolver.3352
-rw-r--r--cpukit/libnetworking/libc/send.c52
-rw-r--r--cpukit/libnetworking/libc/strsep.c85
-rw-r--r--cpukit/libnetworking/loop.h5
-rw-r--r--cpukit/libnetworking/machine/conf.h5
-rw-r--r--cpukit/libnetworking/machine/cpu.h5
-rw-r--r--cpukit/libnetworking/machine/cpufunc.h5
-rw-r--r--cpukit/libnetworking/machine/endian.h64
-rw-r--r--cpukit/libnetworking/machine/in_cksum.h218
-rw-r--r--cpukit/libnetworking/machine/limits.h5
-rw-r--r--cpukit/libnetworking/machine/vmparam.h5
-rw-r--r--cpukit/libnetworking/memory.h5
-rw-r--r--cpukit/libnetworking/net/bpf.h236
-rw-r--r--cpukit/libnetworking/net/bsd-comp.c1117
-rw-r--r--cpukit/libnetworking/net/ethernet.h65
-rw-r--r--cpukit/libnetworking/net/if.c794
-rw-r--r--cpukit/libnetworking/net/if.h474
-rw-r--r--cpukit/libnetworking/net/if_arp.h92
-rw-r--r--cpukit/libnetworking/net/if_dl.h86
-rw-r--r--cpukit/libnetworking/net/if_ethersubr.c998
-rw-r--r--cpukit/libnetworking/net/if_llc.h145
-rw-r--r--cpukit/libnetworking/net/if_loop.c302
-rw-r--r--cpukit/libnetworking/net/if_ppp.c1764
-rw-r--r--cpukit/libnetworking/net/if_ppp.h134
-rw-r--r--cpukit/libnetworking/net/if_pppvar.h141
-rw-r--r--cpukit/libnetworking/net/if_types.h101
-rw-r--r--cpukit/libnetworking/net/netisr.h90
-rw-r--r--cpukit/libnetworking/net/ppp-comp.h165
-rw-r--r--cpukit/libnetworking/net/ppp-deflate.c683
-rw-r--r--cpukit/libnetworking/net/ppp.h11
-rw-r--r--cpukit/libnetworking/net/ppp_defs.h184
-rw-r--r--cpukit/libnetworking/net/ppp_tty.c954
-rw-r--r--cpukit/libnetworking/net/pppcompress.c593
-rw-r--r--cpukit/libnetworking/net/pppcompress.h164
-rw-r--r--cpukit/libnetworking/net/radix.c1078
-rw-r--r--cpukit/libnetworking/net/radix.h168
-rw-r--r--cpukit/libnetworking/net/raw_cb.c148
-rw-r--r--cpukit/libnetworking/net/raw_cb.h75
-rw-r--r--cpukit/libnetworking/net/raw_usrreq.c315
-rw-r--r--cpukit/libnetworking/net/route.c959
-rw-r--r--cpukit/libnetworking/net/route.h286
-rw-r--r--cpukit/libnetworking/net/rtsock.c829
-rw-r--r--cpukit/libnetworking/net/zlib.c5376
-rw-r--r--cpukit/libnetworking/net/zlib.h1010
-rw-r--r--cpukit/libnetworking/netdb.h182
-rw-r--r--cpukit/libnetworking/netinet/icmp_var.h79
-rw-r--r--cpukit/libnetworking/netinet/if_ether.c639
-rw-r--r--cpukit/libnetworking/netinet/if_ether.h210
-rw-r--r--cpukit/libnetworking/netinet/igmp.c479
-rw-r--r--cpukit/libnetworking/netinet/igmp.h96
-rw-r--r--cpukit/libnetworking/netinet/igmp_var.h107
-rw-r--r--cpukit/libnetworking/netinet/in.c723
-rw-r--r--cpukit/libnetworking/netinet/in.h443
-rw-r--r--cpukit/libnetworking/netinet/in_cksum.c176
-rw-r--r--cpukit/libnetworking/netinet/in_cksum_arm.h276
-rw-r--r--cpukit/libnetworking/netinet/in_cksum_i386.h204
-rw-r--r--cpukit/libnetworking/netinet/in_cksum_m68k.h223
-rw-r--r--cpukit/libnetworking/netinet/in_cksum_powerpc.h173
-rw-r--r--cpukit/libnetworking/netinet/in_pcb.c760
-rw-r--r--cpukit/libnetworking/netinet/in_pcb.h157
-rw-r--r--cpukit/libnetworking/netinet/in_proto.c202
-rw-r--r--cpukit/libnetworking/netinet/in_rmx.c383
-rw-r--r--cpukit/libnetworking/netinet/in_systm.h62
-rw-r--r--cpukit/libnetworking/netinet/in_var.h241
-rw-r--r--cpukit/libnetworking/netinet/ip.h191
-rw-r--r--cpukit/libnetworking/netinet/ip_divert.c382
-rw-r--r--cpukit/libnetworking/netinet/ip_fw.c1074
-rw-r--r--cpukit/libnetworking/netinet/ip_fw.h183
-rw-r--r--cpukit/libnetworking/netinet/ip_icmp.c711
-rw-r--r--cpukit/libnetworking/netinet/ip_icmp.h190
-rw-r--r--cpukit/libnetworking/netinet/ip_input.c1488
-rw-r--r--cpukit/libnetworking/netinet/ip_mroute.c2302
-rw-r--r--cpukit/libnetworking/netinet/ip_mroute.h262
-rw-r--r--cpukit/libnetworking/netinet/ip_output.c1307
-rw-r--r--cpukit/libnetworking/netinet/ip_var.h212
-rw-r--r--cpukit/libnetworking/netinet/raw_ip.c486
-rw-r--r--cpukit/libnetworking/netinet/tcp.h122
-rw-r--r--cpukit/libnetworking/netinet/tcp_debug.c172
-rw-r--r--cpukit/libnetworking/netinet/tcp_debug.h69
-rw-r--r--cpukit/libnetworking/netinet/tcp_fsm.h92
-rw-r--r--cpukit/libnetworking/netinet/tcp_input.c2165
-rw-r--r--cpukit/libnetworking/netinet/tcp_output.c755
-rw-r--r--cpukit/libnetworking/netinet/tcp_seq.h102
-rw-r--r--cpukit/libnetworking/netinet/tcp_subr.c762
-rw-r--r--cpukit/libnetworking/netinet/tcp_timer.c387
-rw-r--r--cpukit/libnetworking/netinet/tcp_timer.h138
-rw-r--r--cpukit/libnetworking/netinet/tcp_usrreq.c839
-rw-r--r--cpukit/libnetworking/netinet/tcp_var.h405
-rw-r--r--cpukit/libnetworking/netinet/tcpip.h75
-rw-r--r--cpukit/libnetworking/netinet/udp.h51
-rw-r--r--cpukit/libnetworking/netinet/udp_usrreq.c731
-rw-r--r--cpukit/libnetworking/netinet/udp_var.h106
-rw-r--r--cpukit/libnetworking/nfs/bootp_subr.c1164
-rw-r--r--cpukit/libnetworking/nfs/krpc.h26
-rw-r--r--cpukit/libnetworking/nfs/nfs.h620
-rw-r--r--cpukit/libnetworking/nfs/nfsdiskless.h100
-rw-r--r--cpukit/libnetworking/nfs/nfsproto.h441
-rw-r--r--cpukit/libnetworking/nfs/rpcv2.h142
-rw-r--r--cpukit/libnetworking/nfs/xdr_subs.h90
-rw-r--r--cpukit/libnetworking/opt_ipfw.h5
-rw-r--r--cpukit/libnetworking/opt_mrouting.h5
-rw-r--r--cpukit/libnetworking/opt_tcpdebug.h16
-rw-r--r--cpukit/libnetworking/poll.h6
-rw-r--r--cpukit/libnetworking/resolv.h306
-rw-r--r--cpukit/libnetworking/rtems/ftpfs.h34
-rw-r--r--cpukit/libnetworking/rtems/issetugid.c11
-rw-r--r--cpukit/libnetworking/rtems/mkrootfs.c331
-rw-r--r--cpukit/libnetworking/rtems/mkrootfs.h66
-rw-r--r--cpukit/libnetworking/rtems/rtems_bootp.c32
-rw-r--r--cpukit/libnetworking/rtems/rtems_bsdnet.h192
-rw-r--r--cpukit/libnetworking/rtems/rtems_bsdnet_internal.h200
-rw-r--r--cpukit/libnetworking/rtems/rtems_bsdnet_malloc_starvation.c15
-rw-r--r--cpukit/libnetworking/rtems/rtems_glue.c1231
-rw-r--r--cpukit/libnetworking/rtems/rtems_select.c174
-rw-r--r--cpukit/libnetworking/rtems/rtems_showicmpstat.c60
-rw-r--r--cpukit/libnetworking/rtems/rtems_showifstat.c152
-rw-r--r--cpukit/libnetworking/rtems/rtems_showipstat.c59
-rw-r--r--cpukit/libnetworking/rtems/rtems_showmbuf.c65
-rw-r--r--cpukit/libnetworking/rtems/rtems_showroute.c236
-rw-r--r--cpukit/libnetworking/rtems/rtems_showtcpstat.c102
-rw-r--r--cpukit/libnetworking/rtems/rtems_showudpstat.c48
-rw-r--r--cpukit/libnetworking/rtems/rtems_syscall.c787
-rw-r--r--cpukit/libnetworking/rtems/sghostname.c49
-rw-r--r--cpukit/libnetworking/rtems/tftp.h43
-rw-r--r--cpukit/libnetworking/sys/buf.h248
-rw-r--r--cpukit/libnetworking/sys/callout.h57
-rw-r--r--cpukit/libnetworking/sys/conf.h228
-rw-r--r--cpukit/libnetworking/sys/domain.h75
-rw-r--r--cpukit/libnetworking/sys/kernel.h264
-rw-r--r--cpukit/libnetworking/sys/libkern.h89
-rw-r--r--cpukit/libnetworking/sys/linker_set.h93
-rw-r--r--cpukit/libnetworking/sys/malloc.h355
-rw-r--r--cpukit/libnetworking/sys/mbuf.h440
-rw-r--r--cpukit/libnetworking/sys/mount.h531
-rw-r--r--cpukit/libnetworking/sys/poll.h104
-rw-r--r--cpukit/libnetworking/sys/proc.h8
-rw-r--r--cpukit/libnetworking/sys/protosw.h300
-rw-r--r--cpukit/libnetworking/sys/queue.h611
-rw-r--r--cpukit/libnetworking/sys/reboot.h106
-rw-r--r--cpukit/libnetworking/sys/resourcevar.h5
-rw-r--r--cpukit/libnetworking/sys/rtprio.h70
-rw-r--r--cpukit/libnetworking/sys/select.h75
-rw-r--r--cpukit/libnetworking/sys/signalvar.h171
-rw-r--r--cpukit/libnetworking/sys/socket.h383
-rw-r--r--cpukit/libnetworking/sys/socketvar.h283
-rw-r--r--cpukit/libnetworking/sys/sysctl.h637
-rw-r--r--cpukit/libnetworking/sys/syslog.h195
-rw-r--r--cpukit/libnetworking/sys/systm.h199
-rw-r--r--cpukit/libnetworking/sys/ttydefaults.h97
-rw-r--r--cpukit/libnetworking/sys/ucred.h64
-rw-r--r--cpukit/libnetworking/sys/uio.h92
-rw-r--r--cpukit/libnetworking/sys/un.h68
-rw-r--r--cpukit/libnetworking/syslog.h5
-rw-r--r--cpukit/libnetworking/vm/vm.h73
-rw-r--r--cpukit/libnetworking/vm/vm_extern.h103
-rw-r--r--cpukit/libnetworking/vm/vm_kern.h84
-rw-r--r--cpukit/libnetworking/vm/vm_param.h165
-rw-r--r--cpukit/librpc/.cvsignore2
-rw-r--r--cpukit/librpc/Makefile.am187
-rw-r--r--cpukit/librpc/README_RTEMS64
-rw-r--r--cpukit/librpc/include/rpc/auth.h260
-rw-r--r--cpukit/librpc/include/rpc/auth_des.h109
-rw-r--r--cpukit/librpc/include/rpc/auth_unix.h84
-rw-r--r--cpukit/librpc/include/rpc/clnt.h419
-rw-r--r--cpukit/librpc/include/rpc/des.h82
-rw-r--r--cpukit/librpc/include/rpc/des_crypt.h120
-rw-r--r--cpukit/librpc/include/rpc/pmap_clnt.h85
-rw-r--r--cpukit/librpc/include/rpc/pmap_prot.h104
-rw-r--r--cpukit/librpc/include/rpc/pmap_rmt.h63
-rw-r--r--cpukit/librpc/include/rpc/rpc.h137
-rw-r--r--cpukit/librpc/include/rpc/rpc_com.h78
-rw-r--r--cpukit/librpc/include/rpc/rpc_msg.h196
-rw-r--r--cpukit/librpc/include/rpc/svc.h324
-rw-r--r--cpukit/librpc/include/rpc/svc_auth.h56
-rw-r--r--cpukit/librpc/include/rpc/types.h62
-rw-r--r--cpukit/librpc/include/rpc/xdr.h314
-rw-r--r--cpukit/librpc/include/rpcsvc/bootparam_prot.x103
-rw-r--r--cpukit/librpc/include/rpcsvc/crypt.x91
-rw-r--r--cpukit/librpc/include/rpcsvc/key_prot.x282
-rw-r--r--cpukit/librpc/include/rpcsvc/klm_prot.x139
-rw-r--r--cpukit/librpc/include/rpcsvc/mount.x257
-rw-r--r--cpukit/librpc/include/rpcsvc/nfs_prot.x1265
-rw-r--r--cpukit/librpc/include/rpcsvc/nis.x466
-rw-r--r--cpukit/librpc/include/rpcsvc/nis_cache.x87
-rw-r--r--cpukit/librpc/include/rpcsvc/nis_callback.x76
-rw-r--r--cpukit/librpc/include/rpcsvc/nis_db.h162
-rw-r--r--cpukit/librpc/include/rpcsvc/nis_object.x317
-rw-r--r--cpukit/librpc/include/rpcsvc/nis_tags.h137
-rw-r--r--cpukit/librpc/include/rpcsvc/nislib.h317
-rw-r--r--cpukit/librpc/include/rpcsvc/nlm_prot.x183
-rw-r--r--cpukit/librpc/include/rpcsvc/pmap_prot.x284
-rw-r--r--cpukit/librpc/include/rpcsvc/rex.x235
-rw-r--r--cpukit/librpc/include/rpcsvc/rnusers.x122
-rw-r--r--cpukit/librpc/include/rpcsvc/rquota.x67
-rw-r--r--cpukit/librpc/include/rpcsvc/rstat.x151
-rw-r--r--cpukit/librpc/include/rpcsvc/rwall.x57
-rw-r--r--cpukit/librpc/include/rpcsvc/sm_inter.x122
-rw-r--r--cpukit/librpc/include/rpcsvc/spray.x90
-rw-r--r--cpukit/librpc/include/rpcsvc/yp.x379
-rw-r--r--cpukit/librpc/include/rpcsvc/yp_prot.h329
-rw-r--r--cpukit/librpc/include/rpcsvc/ypclnt.h93
-rw-r--r--cpukit/librpc/include/rpcsvc/yppasswd.x75
-rw-r--r--cpukit/librpc/include/rpcsvc/ypupdate_prot.x88
-rw-r--r--cpukit/librpc/include/rpcsvc/ypxfrd.x173
-rw-r--r--cpukit/librpc/src/rpc/DISCLAIMER28
-rw-r--r--cpukit/librpc/src/rpc/PSD.doc/nfs.rfc.ms1372
-rw-r--r--cpukit/librpc/src/rpc/PSD.doc/rpc.prog.ms2684
-rw-r--r--cpukit/librpc/src/rpc/PSD.doc/rpc.rfc.ms1302
-rw-r--r--cpukit/librpc/src/rpc/PSD.doc/rpcgen.ms1299
-rw-r--r--cpukit/librpc/src/rpc/PSD.doc/xdr.nts.ms1966
-rw-r--r--cpukit/librpc/src/rpc/PSD.doc/xdr.rfc.ms1058
-rw-r--r--cpukit/librpc/src/rpc/README233
-rw-r--r--cpukit/librpc/src/rpc/auth_des.c554
-rw-r--r--cpukit/librpc/src/rpc/auth_none.c136
-rw-r--r--cpukit/librpc/src/rpc/auth_time.c503
-rw-r--r--cpukit/librpc/src/rpc/auth_unix.c349
-rw-r--r--cpukit/librpc/src/rpc/authdes_prot.c82
-rw-r--r--cpukit/librpc/src/rpc/authunix_prot.c67
-rw-r--r--cpukit/librpc/src/rpc/bindresvport.3106
-rw-r--r--cpukit/librpc/src/rpc/bindresvport.c147
-rw-r--r--cpukit/librpc/src/rpc/clnt_generic.c141
-rw-r--r--cpukit/librpc/src/rpc/clnt_perror.c254
-rw-r--r--cpukit/librpc/src/rpc/clnt_raw.c243
-rw-r--r--cpukit/librpc/src/rpc/clnt_simple.c123
-rw-r--r--cpukit/librpc/src/rpc/clnt_tcp.c581
-rw-r--r--cpukit/librpc/src/rpc/clnt_udp.c568
-rw-r--r--cpukit/librpc/src/rpc/clnt_unix.c635
-rw-r--r--cpukit/librpc/src/rpc/crypt_client.c90
-rw-r--r--cpukit/librpc/src/rpc/des_crypt.3130
-rw-r--r--cpukit/librpc/src/rpc/des_crypt.c153
-rw-r--r--cpukit/librpc/src/rpc/des_soft.c67
-rw-r--r--cpukit/librpc/src/rpc/get_myaddress.c112
-rw-r--r--cpukit/librpc/src/rpc/getpublickey.c172
-rw-r--r--cpukit/librpc/src/rpc/getrpcent.398
-rw-r--r--cpukit/librpc/src/rpc/getrpcent.c302
-rw-r--r--cpukit/librpc/src/rpc/getrpcport.331
-rw-r--r--cpukit/librpc/src/rpc/getrpcport.c63
-rw-r--r--cpukit/librpc/src/rpc/key_call.c427
-rw-r--r--cpukit/librpc/src/rpc/key_prot_xdr.c166
-rw-r--r--cpukit/librpc/src/rpc/netname.c136
-rw-r--r--cpukit/librpc/src/rpc/netnamer.c326
-rw-r--r--cpukit/librpc/src/rpc/pmap_clnt.c149
-rw-r--r--cpukit/librpc/src/rpc/pmap_getmaps.c86
-rw-r--r--cpukit/librpc/src/rpc/pmap_getport.c91
-rw-r--r--cpukit/librpc/src/rpc/pmap_prot.c59
-rw-r--r--cpukit/librpc/src/rpc/pmap_prot2.c118
-rw-r--r--cpukit/librpc/src/rpc/pmap_rmt.c415
-rw-r--r--cpukit/librpc/src/rpc/publickey.347
-rw-r--r--cpukit/librpc/src/rpc/publickey.538
-rw-r--r--cpukit/librpc/src/rpc/rpc.31767
-rw-r--r--cpukit/librpc/src/rpc/rpc.535
-rw-r--r--cpukit/librpc/src/rpc/rpc_callmsg.c192
-rw-r--r--cpukit/librpc/src/rpc/rpc_commondata.c41
-rw-r--r--cpukit/librpc/src/rpc/rpc_dtablesize.c61
-rw-r--r--cpukit/librpc/src/rpc/rpc_prot.c297
-rw-r--r--cpukit/librpc/src/rpc/rpc_secure.3254
-rw-r--r--cpukit/librpc/src/rpc/rpcdname.c80
-rw-r--r--cpukit/librpc/src/rpc/rstat.158
-rw-r--r--cpukit/librpc/src/rpc/rstat_svc.822
-rw-r--r--cpukit/librpc/src/rpc/rtems_portmapper.c489
-rw-r--r--cpukit/librpc/src/rpc/rtems_rpc.c59
-rw-r--r--cpukit/librpc/src/rpc/rtime.347
-rw-r--r--cpukit/librpc/src/rpc/rtime.c158
-rw-r--r--cpukit/librpc/src/rpc/svc.c491
-rw-r--r--cpukit/librpc/src/rpc/svc_auth.c216
-rw-r--r--cpukit/librpc/src/rpc/svc_auth_des.c530
-rw-r--r--cpukit/librpc/src/rpc/svc_auth_unix.c148
-rw-r--r--cpukit/librpc/src/rpc/svc_raw.c169
-rw-r--r--cpukit/librpc/src/rpc/svc_run.c84
-rw-r--r--cpukit/librpc/src/rpc/svc_simple.c150
-rw-r--r--cpukit/librpc/src/rpc/svc_tcp.c482
-rw-r--r--cpukit/librpc/src/rpc/svc_udp.c479
-rw-r--r--cpukit/librpc/src/rpc/svc_unix.c527
-rw-r--r--cpukit/librpc/src/xdr/xdr.3837
-rw-r--r--cpukit/librpc/src/xdr/xdr.c777
-rw-r--r--cpukit/librpc/src/xdr/xdr_array.c156
-rw-r--r--cpukit/librpc/src/xdr/xdr_float.c333
-rw-r--r--cpukit/librpc/src/xdr/xdr_mem.c242
-rw-r--r--cpukit/librpc/src/xdr/xdr_rec.c601
-rw-r--r--cpukit/librpc/src/xdr/xdr_reference.c138
-rw-r--r--cpukit/librpc/src/xdr/xdr_sizeof.c163
-rw-r--r--cpukit/librpc/src/xdr/xdr_stdio.c190
-rw-r--r--cpukit/posix/.cvsignore2
-rw-r--r--cpukit/posix/Makefile.am360
-rw-r--r--cpukit/posix/include/aio.h145
-rw-r--r--cpukit/posix/include/devctl.h38
-rw-r--r--cpukit/posix/include/intr.h80
-rw-r--r--cpukit/posix/include/mqueue.h153
-rw-r--r--cpukit/posix/include/rtems/posix/cancel.h29
-rw-r--r--cpukit/posix/include/rtems/posix/cond.h168
-rw-r--r--cpukit/posix/include/rtems/posix/condmp.h161
-rw-r--r--cpukit/posix/include/rtems/posix/config.h62
-rw-r--r--cpukit/posix/include/rtems/posix/intr.h152
-rw-r--r--cpukit/posix/include/rtems/posix/key.h134
-rw-r--r--cpukit/posix/include/rtems/posix/mqueue.h248
-rw-r--r--cpukit/posix/include/rtems/posix/mqueuemp.h160
-rw-r--r--cpukit/posix/include/rtems/posix/mutex.h157
-rw-r--r--cpukit/posix/include/rtems/posix/mutexmp.h173
-rw-r--r--cpukit/posix/include/rtems/posix/posixapi.h33
-rw-r--r--cpukit/posix/include/rtems/posix/priority.h44
-rw-r--r--cpukit/posix/include/rtems/posix/psignal.h121
-rw-r--r--cpukit/posix/include/rtems/posix/pthread.h149
-rw-r--r--cpukit/posix/include/rtems/posix/pthreadmp.h160
-rw-r--r--cpukit/posix/include/rtems/posix/ptimer.h90
-rw-r--r--cpukit/posix/include/rtems/posix/semaphore.h180
-rw-r--r--cpukit/posix/include/rtems/posix/semaphoremp.h160
-rw-r--r--cpukit/posix/include/rtems/posix/threadsup.h44
-rw-r--r--cpukit/posix/include/rtems/posix/time.h50
-rw-r--r--cpukit/posix/include/rtems/posix/timer.h72
-rw-r--r--cpukit/posix/include/sched.h95
-rw-r--r--cpukit/posix/include/semaphore.h116
-rw-r--r--cpukit/posix/inline/rtems/posix/cond.inl100
-rw-r--r--cpukit/posix/inline/rtems/posix/intr.inl71
-rw-r--r--cpukit/posix/inline/rtems/posix/key.inl69
-rw-r--r--cpukit/posix/inline/rtems/posix/mqueue.inl150
-rw-r--r--cpukit/posix/inline/rtems/posix/mutex.inl110
-rw-r--r--cpukit/posix/inline/rtems/posix/priority.inl37
-rw-r--r--cpukit/posix/inline/rtems/posix/pthread.inl69
-rw-r--r--cpukit/posix/inline/rtems/posix/semaphore.inl85
-rw-r--r--cpukit/posix/inline/rtems/posix/timer.inl90
-rw-r--r--cpukit/posix/macros/rtems/posix/cond.inl95
-rw-r--r--cpukit/posix/macros/rtems/posix/intr.inl55
-rw-r--r--cpukit/posix/macros/rtems/posix/key.inl54
-rw-r--r--cpukit/posix/macros/rtems/posix/mqueue.inl101
-rw-r--r--cpukit/posix/macros/rtems/posix/mutex.inl100
-rw-r--r--cpukit/posix/macros/rtems/posix/priority.inl25
-rw-r--r--cpukit/posix/macros/rtems/posix/pthread.inl54
-rw-r--r--cpukit/posix/macros/rtems/posix/semaphore.inl64
-rw-r--r--cpukit/posix/macros/rtems/posix/timer.inl53
-rw-r--r--cpukit/posix/src/.cvsignore4
-rw-r--r--cpukit/posix/src/README.mqueue38
-rw-r--r--cpukit/posix/src/adasupp.c32
-rw-r--r--cpukit/posix/src/adjtime.c60
-rw-r--r--cpukit/posix/src/aio.c118
-rw-r--r--cpukit/posix/src/alarm.c82
-rw-r--r--cpukit/posix/src/cancel.c62
-rw-r--r--cpukit/posix/src/cancelrun.c63
-rw-r--r--cpukit/posix/src/cleanuppop.c60
-rw-r--r--cpukit/posix/src/cleanuppush.c56
-rw-r--r--cpukit/posix/src/clockgetcpuclockid.c32
-rw-r--r--cpukit/posix/src/clockgetenableattr.c32
-rw-r--r--cpukit/posix/src/clockgetres.c55
-rw-r--r--cpukit/posix/src/clockgettime.c69
-rw-r--r--cpukit/posix/src/clocksetenableattr.c32
-rw-r--r--cpukit/posix/src/clocksettime.c88
-rw-r--r--cpukit/posix/src/cond.c52
-rw-r--r--cpukit/posix/src/condattrdestroy.c35
-rw-r--r--cpukit/posix/src/condattrgetpshared.c36
-rw-r--r--cpukit/posix/src/condattrinit.c35
-rw-r--r--cpukit/posix/src/condattrsetpshared.c43
-rw-r--r--cpukit/posix/src/condbroadcast.c30
-rw-r--r--cpukit/posix/src/conddefaultattributes.c28
-rw-r--r--cpukit/posix/src/conddestroy.c80
-rw-r--r--cpukit/posix/src/condinit.c99
-rw-r--r--cpukit/posix/src/condmp.c45
-rw-r--r--cpukit/posix/src/condsignal.c30
-rw-r--r--cpukit/posix/src/condsignalsupp.c61
-rw-r--r--cpukit/posix/src/condtimedwait.c61
-rw-r--r--cpukit/posix/src/condwait.c36
-rw-r--r--cpukit/posix/src/condwaitsupp.c108
-rw-r--r--cpukit/posix/src/devctl.c26
-rw-r--r--cpukit/posix/src/execl.c21
-rw-r--r--cpukit/posix/src/execle.c21
-rw-r--r--cpukit/posix/src/execlp.c21
-rw-r--r--cpukit/posix/src/execv.c20
-rw-r--r--cpukit/posix/src/execve.c21
-rw-r--r--cpukit/posix/src/execvp.c20
-rw-r--r--cpukit/posix/src/fork.c18
-rw-r--r--cpukit/posix/src/getpagesize.c23
-rw-r--r--cpukit/posix/src/intr.c349
-rw-r--r--cpukit/posix/src/key.c46
-rw-r--r--cpukit/posix/src/keycreate.c90
-rw-r--r--cpukit/posix/src/keydelete.c58
-rw-r--r--cpukit/posix/src/keygetspecific.c48
-rw-r--r--cpukit/posix/src/keyrundestructors.c80
-rw-r--r--cpukit/posix/src/keysetspecific.c47
-rw-r--r--cpukit/posix/src/kill.c51
-rw-r--r--cpukit/posix/src/killinfo.c338
-rw-r--r--cpukit/posix/src/mprotect.c23
-rw-r--r--cpukit/posix/src/mqueue.c82
-rw-r--r--cpukit/posix/src/mqueueclose.c79
-rw-r--r--cpukit/posix/src/mqueuecreatesupp.c173
-rw-r--r--cpukit/posix/src/mqueuedeletesupp.c78
-rw-r--r--cpukit/posix/src/mqueuegetattr.c79
-rw-r--r--cpukit/posix/src/mqueuenametoid.c66
-rw-r--r--cpukit/posix/src/mqueuenotify.c107
-rw-r--r--cpukit/posix/src/mqueueopen.c158
-rw-r--r--cpukit/posix/src/mqueuereceive.c56
-rw-r--r--cpukit/posix/src/mqueuerecvsupp.c107
-rw-r--r--cpukit/posix/src/mqueuesend.c56
-rw-r--r--cpukit/posix/src/mqueuesendsupp.c117
-rw-r--r--cpukit/posix/src/mqueuesetattr.c81
-rw-r--r--cpukit/posix/src/mqueuetimedreceive.c57
-rw-r--r--cpukit/posix/src/mqueuetimedsend.c57
-rw-r--r--cpukit/posix/src/mqueuetranslatereturncode.c101
-rw-r--r--cpukit/posix/src/mqueueunlink.c85
-rw-r--r--cpukit/posix/src/mutex.c54
-rw-r--r--cpukit/posix/src/mutexattrdestroy.c37
-rw-r--r--cpukit/posix/src/mutexattrgetprioceiling.c38
-rw-r--r--cpukit/posix/src/mutexattrgetprotocol.c38
-rw-r--r--cpukit/posix/src/mutexattrgetpshared.c38
-rw-r--r--cpukit/posix/src/mutexattrinit.c37
-rw-r--r--cpukit/posix/src/mutexattrsetprioceiling.c41
-rw-r--r--cpukit/posix/src/mutexattrsetprotocol.c46
-rw-r--r--cpukit/posix/src/mutexattrsetpshared.c45
-rw-r--r--cpukit/posix/src/mutexdefaultattributes.c34
-rw-r--r--cpukit/posix/src/mutexdestroy.c87
-rw-r--r--cpukit/posix/src/mutexfromcorestatus.c52
-rw-r--r--cpukit/posix/src/mutexgetprioceiling.c55
-rw-r--r--cpukit/posix/src/mutexinit.c186
-rw-r--r--cpukit/posix/src/mutexlock.c35
-rw-r--r--cpukit/posix/src/mutexlocksupp.c67
-rw-r--r--cpukit/posix/src/mutexmp.c66
-rw-r--r--cpukit/posix/src/mutexsetprioceiling.c82
-rw-r--r--cpukit/posix/src/mutextimedlock.c40
-rw-r--r--cpukit/posix/src/mutextrylock.c35
-rw-r--r--cpukit/posix/src/mutexunlock.c66
-rw-r--r--cpukit/posix/src/nanosleep.c104
-rw-r--r--cpukit/posix/src/pause.c40
-rw-r--r--cpukit/posix/src/posixintervaltotimespec.c38
-rw-r--r--cpukit/posix/src/posixtimespecsubtract.c50
-rw-r--r--cpukit/posix/src/posixtimespectointerval.c42
-rw-r--r--cpukit/posix/src/psignal.c206
-rw-r--r--cpukit/posix/src/psignalchecksignal.c93
-rw-r--r--cpukit/posix/src/psignalclearprocesssignals.c42
-rw-r--r--cpukit/posix/src/psignalclearsignals.c89
-rw-r--r--cpukit/posix/src/psignalsetprocesssignals.c42
-rw-r--r--cpukit/posix/src/psignalunblockthread.c93
-rw-r--r--cpukit/posix/src/pthread.c387
-rw-r--r--cpukit/posix/src/pthreadatfork.c31
-rw-r--r--cpukit/posix/src/pthreadattrdestroy.c32
-rw-r--r--cpukit/posix/src/pthreadattrgetdetachstate.c31
-rw-r--r--cpukit/posix/src/pthreadattrgetinheritsched.c31
-rw-r--r--cpukit/posix/src/pthreadattrgetschedparam.c31
-rw-r--r--cpukit/posix/src/pthreadattrgetschedpolicy.c31
-rw-r--r--cpukit/posix/src/pthreadattrgetscope.c31
-rw-r--r--cpukit/posix/src/pthreadattrgetstackaddr.c31
-rw-r--r--cpukit/posix/src/pthreadattrgetstacksize.c31
-rw-r--r--cpukit/posix/src/pthreadattrinit.c33
-rw-r--r--cpukit/posix/src/pthreadattrsetdetachstate.c38
-rw-r--r--cpukit/posix/src/pthreadattrsetinheritsched.c41
-rw-r--r--cpukit/posix/src/pthreadattrsetschedparam.c31
-rw-r--r--cpukit/posix/src/pthreadattrsetschedpolicy.c43
-rw-r--r--cpukit/posix/src/pthreadattrsetscope.c43
-rw-r--r--cpukit/posix/src/pthreadattrsetstackaddr.c31
-rw-r--r--cpukit/posix/src/pthreadattrsetstacksize.c37
-rw-r--r--cpukit/posix/src/pthreadcreate.c256
-rw-r--r--cpukit/posix/src/pthreaddetach.c47
-rw-r--r--cpukit/posix/src/pthreadequal.c82
-rw-r--r--cpukit/posix/src/pthreadexit.c48
-rw-r--r--cpukit/posix/src/pthreadgetcpuclockid.c29
-rw-r--r--cpukit/posix/src/pthreadgetcputime.c31
-rw-r--r--cpukit/posix/src/pthreadgetschedparam.c59
-rw-r--r--cpukit/posix/src/pthreadjoin.c71
-rw-r--r--cpukit/posix/src/pthreadkill.c83
-rw-r--r--cpukit/posix/src/pthreadonce.c44
-rw-r--r--cpukit/posix/src/pthreadself.c27
-rw-r--r--cpukit/posix/src/pthreadsetcputime.c38
-rw-r--r--cpukit/posix/src/pthreadsetschedparam.c129
-rw-r--r--cpukit/posix/src/pthreadsigmask.c73
-rw-r--r--cpukit/posix/src/ptimer.c101
-rw-r--r--cpukit/posix/src/ptimer1.c799
-rw-r--r--cpukit/posix/src/sched.c157
-rw-r--r--cpukit/posix/src/semaphore.c54
-rw-r--r--cpukit/posix/src/semaphorecreatesupp.c129
-rw-r--r--cpukit/posix/src/semaphoredeletesupp.c65
-rw-r--r--cpukit/posix/src/semaphoremp.c146
-rw-r--r--cpukit/posix/src/semaphorenametoid.c51
-rw-r--r--cpukit/posix/src/semaphorewaitsupp.c71
-rw-r--r--cpukit/posix/src/semclose.c55
-rw-r--r--cpukit/posix/src/semdestroy.c58
-rw-r--r--cpukit/posix/src/semgetvalue.c50
-rw-r--r--cpukit/posix/src/seminit.c51
-rw-r--r--cpukit/posix/src/semopen.c122
-rw-r--r--cpukit/posix/src/sempost.c57
-rw-r--r--cpukit/posix/src/semtimedwait.c40
-rw-r--r--cpukit/posix/src/semtrywait.c35
-rw-r--r--cpukit/posix/src/semunlink.c75
-rw-r--r--cpukit/posix/src/semwait.c35
-rw-r--r--cpukit/posix/src/setcancelstate.c61
-rw-r--r--cpukit/posix/src/setcanceltype.c61
-rw-r--r--cpukit/posix/src/sigaction.c93
-rw-r--r--cpukit/posix/src/sigaddset.c42
-rw-r--r--cpukit/posix/src/sigdelset.c46
-rw-r--r--cpukit/posix/src/sigemptyset.c35
-rw-r--r--cpukit/posix/src/sigfillset.c35
-rw-r--r--cpukit/posix/src/sigismember.c44
-rw-r--r--cpukit/posix/src/signal_2.c52
-rw-r--r--cpukit/posix/src/sigpending.c40
-rw-r--r--cpukit/posix/src/sigprocmask.c39
-rw-r--r--cpukit/posix/src/sigqueue.c32
-rw-r--r--cpukit/posix/src/sigsuspend.c53
-rw-r--r--cpukit/posix/src/sigtimedwait.c140
-rw-r--r--cpukit/posix/src/sigwait.c44
-rw-r--r--cpukit/posix/src/sigwaitinfo.c33
-rw-r--r--cpukit/posix/src/sleep.c31
-rw-r--r--cpukit/posix/src/sysconf.c49
-rw-r--r--cpukit/posix/src/testcancel.c46
-rw-r--r--cpukit/posix/src/time.c52
-rw-r--r--cpukit/posix/src/types.c46
-rw-r--r--cpukit/posix/src/ualarm.c94
-rw-r--r--cpukit/posix/src/usleep.c34
-rw-r--r--cpukit/posix/src/wait.c21
-rw-r--r--cpukit/posix/src/waitpid.c23
-rw-r--r--cpukit/pppd/Makefile.am55
-rw-r--r--cpukit/pppd/README29
-rw-r--r--cpukit/pppd/STATUS27
-rw-r--r--cpukit/pppd/auth.c1121
-rw-r--r--cpukit/pppd/cbcp.c456
-rw-r--r--cpukit/pppd/cbcp.h26
-rw-r--r--cpukit/pppd/ccp.c1226
-rw-r--r--cpukit/pppd/ccp.h48
-rw-r--r--cpukit/pppd/chap.c858
-rw-r--r--cpukit/pppd/chap.h124
-rw-r--r--cpukit/pppd/chap_ms.c338
-rw-r--r--cpukit/pppd/chap_ms.h33
-rw-r--r--cpukit/pppd/chat.c857
-rw-r--r--cpukit/pppd/demand.c347
-rw-r--r--cpukit/pppd/example/Makefile-user45
-rw-r--r--cpukit/pppd/example/README15
-rw-r--r--cpukit/pppd/example/init.c24
-rw-r--r--cpukit/pppd/example/netconfig.h36
-rw-r--r--cpukit/pppd/example/ppp.conf27
-rw-r--r--cpukit/pppd/example/pppd.options9
-rw-r--r--cpukit/pppd/example/pppdapp.c146
-rw-r--r--cpukit/pppd/example/system.h42
-rw-r--r--cpukit/pppd/fsm.c764
-rw-r--r--cpukit/pppd/fsm.h144
-rw-r--r--cpukit/pppd/ipcp.c1769
-rw-r--r--cpukit/pppd/ipcp.h73
-rw-r--r--cpukit/pppd/ipxcp.c1449
-rw-r--r--cpukit/pppd/ipxcp.h71
-rw-r--r--cpukit/pppd/lcp.c1953
-rw-r--r--cpukit/pppd/lcp.h88
-rw-r--r--cpukit/pppd/magic.c58
-rw-r--r--cpukit/pppd/magic.h23
-rw-r--r--cpukit/pppd/md4.c298
-rw-r--r--cpukit/pppd/md4.h64
-rw-r--r--cpukit/pppd/md5.c308
-rw-r--r--cpukit/pppd/md5.h58
-rw-r--r--cpukit/pppd/options.c1525
-rw-r--r--cpukit/pppd/patchlevel.h6
-rw-r--r--cpukit/pppd/pathnames.h43
-rw-r--r--cpukit/pppd/pppd.81480
-rw-r--r--cpukit/pppd/pppd.h663
-rw-r--r--cpukit/pppd/rtemsdialer.h24
-rw-r--r--cpukit/pppd/rtemsmain.c896
-rw-r--r--cpukit/pppd/rtemspppd.c217
-rw-r--r--cpukit/pppd/rtemspppd.h29
-rw-r--r--cpukit/pppd/sys-rtems.c1330
-rw-r--r--cpukit/pppd/upap.c638
-rw-r--r--cpukit/pppd/upap.h87
-rw-r--r--cpukit/pppd/utils.c832
-rw-r--r--cpukit/rtems/.cvsignore2
-rw-r--r--cpukit/rtems/Makefile.am411
-rw-r--r--cpukit/rtems/include/rtems.h143
-rw-r--r--cpukit/rtems/include/rtems/rtems/asr.h111
-rw-r--r--cpukit/rtems/include/rtems/rtems/attr.h89
-rw-r--r--cpukit/rtems/include/rtems/rtems/cache.h137
-rw-r--r--cpukit/rtems/include/rtems/rtems/clock.h102
-rw-r--r--cpukit/rtems/include/rtems/rtems/config.h53
-rw-r--r--cpukit/rtems/include/rtems/rtems/dpmem.h156
-rw-r--r--cpukit/rtems/include/rtems/rtems/event.h175
-rw-r--r--cpukit/rtems/include/rtems/rtems/eventmp.h146
-rw-r--r--cpukit/rtems/include/rtems/rtems/eventset.h88
-rw-r--r--cpukit/rtems/include/rtems/rtems/intr.h159
-rw-r--r--cpukit/rtems/include/rtems/rtems/message.h328
-rw-r--r--cpukit/rtems/include/rtems/rtems/modes.h88
-rw-r--r--cpukit/rtems/include/rtems/rtems/mp.h52
-rw-r--r--cpukit/rtems/include/rtems/rtems/msgmp.h176
-rw-r--r--cpukit/rtems/include/rtems/rtems/options.h52
-rw-r--r--cpukit/rtems/include/rtems/rtems/part.h169
-rw-r--r--cpukit/rtems/include/rtems/rtems/partmp.h160
-rw-r--r--cpukit/rtems/include/rtems/rtems/ratemon.h213
-rw-r--r--cpukit/rtems/include/rtems/rtems/region.h252
-rw-r--r--cpukit/rtems/include/rtems/rtems/regionmp.h165
-rw-r--r--cpukit/rtems/include/rtems/rtems/rtemsapi.h35
-rw-r--r--cpukit/rtems/include/rtems/rtems/sem.h276
-rw-r--r--cpukit/rtems/include/rtems/rtems/semmp.h162
-rw-r--r--cpukit/rtems/include/rtems/rtems/signal.h84
-rw-r--r--cpukit/rtems/include/rtems/rtems/signalmp.h146
-rw-r--r--cpukit/rtems/include/rtems/rtems/status.h85
-rw-r--r--cpukit/rtems/include/rtems/rtems/support.h98
-rw-r--r--cpukit/rtems/include/rtems/rtems/taskmp.h166
-rw-r--r--cpukit/rtems/include/rtems/rtems/tasks.h467
-rw-r--r--cpukit/rtems/include/rtems/rtems/timer.h366
-rw-r--r--cpukit/rtems/include/rtems/rtems/types.h111
-rw-r--r--cpukit/rtems/inline/rtems/rtems/asr.inl127
-rw-r--r--cpukit/rtems/inline/rtems/rtems/attr.inl212
-rw-r--r--cpukit/rtems/inline/rtems/rtems/dpmem.inl94
-rw-r--r--cpukit/rtems/inline/rtems/rtems/event.inl20
-rw-r--r--cpukit/rtems/inline/rtems/rtems/eventset.inl94
-rw-r--r--cpukit/rtems/inline/rtems/rtems/message.inl82
-rw-r--r--cpukit/rtems/inline/rtems/rtems/modes.inl151
-rw-r--r--cpukit/rtems/inline/rtems/rtems/options.inl54
-rw-r--r--cpukit/rtems/inline/rtems/rtems/part.inl198
-rw-r--r--cpukit/rtems/inline/rtems/rtems/ratemon.inl142
-rw-r--r--cpukit/rtems/inline/rtems/rtems/region.inl126
-rw-r--r--cpukit/rtems/inline/rtems/rtems/sem.inl102
-rw-r--r--cpukit/rtems/inline/rtems/rtems/status.inl55
-rw-r--r--cpukit/rtems/inline/rtems/rtems/support.inl60
-rw-r--r--cpukit/rtems/inline/rtems/rtems/tasks.inl89
-rw-r--r--cpukit/rtems/inline/rtems/rtems/timer.inl141
-rw-r--r--cpukit/rtems/macros/rtems/rtems/asr.inl89
-rw-r--r--cpukit/rtems/macros/rtems/rtems/attr.inl119
-rw-r--r--cpukit/rtems/macros/rtems/rtems/dpmem.inl58
-rw-r--r--cpukit/rtems/macros/rtems/rtems/event.inl20
-rw-r--r--cpukit/rtems/macros/rtems/rtems/eventset.inl58
-rw-r--r--cpukit/rtems/macros/rtems/rtems/message.inl48
-rw-r--r--cpukit/rtems/macros/rtems/rtems/modes.inl91
-rw-r--r--cpukit/rtems/macros/rtems/rtems/options.inl38
-rw-r--r--cpukit/rtems/macros/rtems/rtems/part.inl116
-rw-r--r--cpukit/rtems/macros/rtems/rtems/ratemon.inl84
-rw-r--r--cpukit/rtems/macros/rtems/rtems/region.inl74
-rw-r--r--cpukit/rtems/macros/rtems/rtems/sem.inl62
-rw-r--r--cpukit/rtems/macros/rtems/rtems/status.inl38
-rw-r--r--cpukit/rtems/macros/rtems/rtems/support.inl43
-rw-r--r--cpukit/rtems/macros/rtems/rtems/tasks.inl57
-rw-r--r--cpukit/rtems/macros/rtems/rtems/timer.inl85
-rw-r--r--cpukit/rtems/src/attr.c28
-rw-r--r--cpukit/rtems/src/clockget.c92
-rw-r--r--cpukit/rtems/src/clockset.c53
-rw-r--r--cpukit/rtems/src/clocktick.c51
-rw-r--r--cpukit/rtems/src/clocktodtoseconds.c63
-rw-r--r--cpukit/rtems/src/clocktodvalidate.c63
-rw-r--r--cpukit/rtems/src/dpmem.c55
-rw-r--r--cpukit/rtems/src/dpmemcreate.c84
-rw-r--r--cpukit/rtems/src/dpmemdelete.c61
-rw-r--r--cpukit/rtems/src/dpmemexternal2internal.c75
-rw-r--r--cpukit/rtems/src/dpmemident.c55
-rw-r--r--cpukit/rtems/src/dpmeminternal2external.c75
-rw-r--r--cpukit/rtems/src/event.c44
-rw-r--r--cpukit/rtems/src/eventmp.c189
-rw-r--r--cpukit/rtems/src/eventreceive.c65
-rw-r--r--cpukit/rtems/src/eventseize.c138
-rw-r--r--cpukit/rtems/src/eventsend.c71
-rw-r--r--cpukit/rtems/src/eventsurrender.c106
-rw-r--r--cpukit/rtems/src/eventtimeout.c87
-rw-r--r--cpukit/rtems/src/intr.c31
-rw-r--r--cpukit/rtems/src/intrbody.c70
-rw-r--r--cpukit/rtems/src/intrcatch.c54
-rw-r--r--cpukit/rtems/src/mp.c41
-rw-r--r--cpukit/rtems/src/msg.c77
-rw-r--r--cpukit/rtems/src/msgmp.c506
-rw-r--r--cpukit/rtems/src/msgqallocate.c56
-rw-r--r--cpukit/rtems/src/msgqbroadcast.c109
-rw-r--r--cpukit/rtems/src/msgqcreate.c161
-rw-r--r--cpukit/rtems/src/msgqdelete.c104
-rw-r--r--cpukit/rtems/src/msgqflush.c89
-rw-r--r--cpukit/rtems/src/msgqgetnumberpending.c86
-rw-r--r--cpukit/rtems/src/msgqident.c67
-rw-r--r--cpukit/rtems/src/msgqreceive.c110
-rw-r--r--cpukit/rtems/src/msgqsend.c57
-rw-r--r--cpukit/rtems/src/msgqsubmit.c147
-rw-r--r--cpukit/rtems/src/msgqtranslatereturncode.c68
-rw-r--r--cpukit/rtems/src/msgqurgent.c57
-rw-r--r--cpukit/rtems/src/part.c67
-rw-r--r--cpukit/rtems/src/partcreate.c125
-rw-r--r--cpukit/rtems/src/partdelete.c87
-rw-r--r--cpukit/rtems/src/partgetbuffer.c82
-rw-r--r--cpukit/rtems/src/partident.c58
-rw-r--r--cpukit/rtems/src/partmp.c303
-rw-r--r--cpukit/rtems/src/partreturnbuffer.c75
-rw-r--r--cpukit/rtems/src/ratemon.c57
-rw-r--r--cpukit/rtems/src/ratemoncancel.c64
-rw-r--r--cpukit/rtems/src/ratemoncreate.c74
-rw-r--r--cpukit/rtems/src/ratemondelete.c62
-rw-r--r--cpukit/rtems/src/ratemongetstatus.c79
-rw-r--r--cpukit/rtems/src/ratemonident.c55
-rw-r--r--cpukit/rtems/src/ratemonperiod.c163
-rw-r--r--cpukit/rtems/src/ratemontimeout.c81
-rw-r--r--cpukit/rtems/src/region.c71
-rw-r--r--cpukit/rtems/src/regioncreate.c110
-rw-r--r--cpukit/rtems/src/regiondelete.c72
-rw-r--r--cpukit/rtems/src/regionextend.c96
-rw-r--r--cpukit/rtems/src/regiongetinfo.c75
-rw-r--r--cpukit/rtems/src/regiongetsegment.c115
-rw-r--r--cpukit/rtems/src/regiongetsegmentsize.c81
-rw-r--r--cpukit/rtems/src/regionident.c57
-rw-r--r--cpukit/rtems/src/regionmp.c311
-rw-r--r--cpukit/rtems/src/regionreturnsegment.c122
-rw-r--r--cpukit/rtems/src/rtclock.c22
-rw-r--r--cpukit/rtems/src/rtemsidtoname.c46
-rw-r--r--cpukit/rtems/src/rtemstimer.c61
-rw-r--r--cpukit/rtems/src/sem.c90
-rw-r--r--cpukit/rtems/src/semcreate.c226
-rw-r--r--cpukit/rtems/src/semdelete.c132
-rw-r--r--cpukit/rtems/src/semflush.c98
-rw-r--r--cpukit/rtems/src/semident.c82
-rw-r--r--cpukit/rtems/src/semmp.c363
-rw-r--r--cpukit/rtems/src/semobtain.c121
-rw-r--r--cpukit/rtems/src/semrelease.c115
-rw-r--r--cpukit/rtems/src/semtranslatereturncode.c120
-rw-r--r--cpukit/rtems/src/signal.c47
-rw-r--r--cpukit/rtems/src/signalcatch.c65
-rw-r--r--cpukit/rtems/src/signalmp.c188
-rw-r--r--cpukit/rtems/src/signalsend.c87
-rw-r--r--cpukit/rtems/src/taskcreate.c231
-rw-r--r--cpukit/rtems/src/taskdelete.c100
-rw-r--r--cpukit/rtems/src/taskgetnote.c108
-rw-r--r--cpukit/rtems/src/taskident.c70
-rw-r--r--cpukit/rtems/src/taskinitusers.c83
-rw-r--r--cpukit/rtems/src/taskissuspended.c77
-rw-r--r--cpukit/rtems/src/taskmode.c125
-rw-r--r--cpukit/rtems/src/taskmp.c339
-rw-r--r--cpukit/rtems/src/taskrestart.c79
-rw-r--r--cpukit/rtems/src/taskresume.c81
-rw-r--r--cpukit/rtems/src/tasks.c290
-rw-r--r--cpukit/rtems/src/tasksetnote.c102
-rw-r--r--cpukit/rtems/src/tasksetpriority.c98
-rw-r--r--cpukit/rtems/src/taskstart.c84
-rw-r--r--cpukit/rtems/src/tasksuspend.c82
-rw-r--r--cpukit/rtems/src/taskvariableadd.c88
-rw-r--r--cpukit/rtems/src/taskvariabledelete.c75
-rw-r--r--cpukit/rtems/src/taskvariableget.c78
-rw-r--r--cpukit/rtems/src/taskwakeafter.c64
-rw-r--r--cpukit/rtems/src/taskwakewhen.c82
-rw-r--r--cpukit/rtems/src/timercancel.c61
-rw-r--r--cpukit/rtems/src/timercreate.c73
-rw-r--r--cpukit/rtems/src/timerdelete.c62
-rw-r--r--cpukit/rtems/src/timerfireafter.c75
-rw-r--r--cpukit/rtems/src/timerfirewhen.c86
-rw-r--r--cpukit/rtems/src/timergetinfo.c70
-rw-r--r--cpukit/rtems/src/timerident.c56
-rw-r--r--cpukit/rtems/src/timerreset.c77
-rw-r--r--cpukit/rtems/src/timerserver.c317
-rw-r--r--cpukit/rtems/src/timerserverfireafter.c86
-rw-r--r--cpukit/rtems/src/timerserverfirewhen.c94
-rw-r--r--cpukit/sapi/.cvsignore2
-rw-r--r--cpukit/sapi/Makefile.am99
-rw-r--r--cpukit/sapi/include/confdefs.h1097
-rw-r--r--cpukit/sapi/include/rtems/README133
-rw-r--r--cpukit/sapi/include/rtems/config.h183
-rw-r--r--cpukit/sapi/include/rtems/extension.h137
-rw-r--r--cpukit/sapi/include/rtems/fatal.h48
-rw-r--r--cpukit/sapi/include/rtems/init.h109
-rw-r--r--cpukit/sapi/include/rtems/io.h272
-rw-r--r--cpukit/sapi/include/rtems/mptables.h28
-rw-r--r--cpukit/sapi/include/rtems/sptables.h71
-rw-r--r--cpukit/sapi/inline/rtems/extension.inl90
-rw-r--r--cpukit/sapi/macros/rtems/extension.inl57
-rw-r--r--cpukit/sapi/src/debug.c61
-rw-r--r--cpukit/sapi/src/exinit.c328
-rw-r--r--cpukit/sapi/src/extension.c51
-rw-r--r--cpukit/sapi/src/extensioncreate.c65
-rw-r--r--cpukit/sapi/src/extensiondelete.c56
-rw-r--r--cpukit/sapi/src/extensionident.c53
-rw-r--r--cpukit/sapi/src/fatal.c37
-rw-r--r--cpukit/sapi/src/io.c419
-rw-r--r--cpukit/sapi/src/itronapi.c119
-rw-r--r--cpukit/sapi/src/posixapi.c115
-rw-r--r--cpukit/sapi/src/rtemsapi.c97
-rw-r--r--cpukit/score/.cvsignore2
-rw-r--r--cpukit/score/Makefile.am490
-rw-r--r--cpukit/score/cpu/.cvsignore2
-rw-r--r--cpukit/score/cpu/Makefile.am11
-rw-r--r--cpukit/score/cpu/arm/.cvsignore2
-rw-r--r--cpukit/score/cpu/arm/ChangeLog331
-rw-r--r--cpukit/score/cpu/arm/Makefile.am62
-rw-r--r--cpukit/score/cpu/arm/asm.h123
-rw-r--r--cpukit/score/cpu/arm/cpu.c320
-rw-r--r--cpukit/score/cpu/arm/cpu_asm.S154
-rw-r--r--cpukit/score/cpu/arm/rtems/asm.h123
-rw-r--r--cpukit/score/cpu/arm/rtems/score/arm.h80
-rw-r--r--cpukit/score/cpu/arm/rtems/score/cpu.h928
-rw-r--r--cpukit/score/cpu/arm/rtems/score/cpu_asm.h35
-rw-r--r--cpukit/score/cpu/arm/rtems/score/types.h55
-rw-r--r--cpukit/score/cpu/c4x/.cvsignore2
-rw-r--r--cpukit/score/cpu/c4x/ChangeLog262
-rw-r--r--cpukit/score/cpu/c4x/Makefile.am74
-rw-r--r--cpukit/score/cpu/c4x/asm.h99
-rw-r--r--cpukit/score/cpu/c4x/c4xio.h110
-rw-r--r--cpukit/score/cpu/c4x/cpu.c199
-rw-r--r--cpukit/score/cpu/c4x/cpu_asm.S769
-rw-r--r--cpukit/score/cpu/c4x/irq.c89
-rw-r--r--cpukit/score/cpu/c4x/rtems/asm.h99
-rw-r--r--cpukit/score/cpu/c4x/rtems/score/c4x.h365
-rw-r--r--cpukit/score/cpu/c4x/rtems/score/cpu.h1261
-rw-r--r--cpukit/score/cpu/c4x/rtems/score/cpu_asm.h70
-rw-r--r--cpukit/score/cpu/c4x/rtems/score/types.h56
-rw-r--r--cpukit/score/cpu/c4x/rtems/tic4x/c4xio.h110
-rw-r--r--cpukit/score/cpu/h8300/.cvsignore2
-rw-r--r--cpukit/score/cpu/h8300/ChangeLog256
-rw-r--r--cpukit/score/cpu/h8300/Makefile.am58
-rw-r--r--cpukit/score/cpu/h8300/README31
-rw-r--r--cpukit/score/cpu/h8300/asm.h122
-rw-r--r--cpukit/score/cpu/h8300/cpu.c174
-rw-r--r--cpukit/score/cpu/h8300/cpu_asm.S224
-rw-r--r--cpukit/score/cpu/h8300/rtems/asm.h122
-rw-r--r--cpukit/score/cpu/h8300/rtems/score/cpu.h1189
-rw-r--r--cpukit/score/cpu/h8300/rtems/score/h8300.h57
-rw-r--r--cpukit/score/cpu/h8300/rtems/score/types.h56
-rw-r--r--cpukit/score/cpu/i386/.cvsignore2
-rw-r--r--cpukit/score/cpu/i386/ChangeLog272
-rw-r--r--cpukit/score/cpu/i386/Makefile.am71
-rw-r--r--cpukit/score/cpu/i386/asm.h143
-rw-r--r--cpukit/score/cpu/i386/cpu.c197
-rw-r--r--cpukit/score/cpu/i386/cpu_asm.S274
-rw-r--r--cpukit/score/cpu/i386/rtems/asm.h143
-rw-r--r--cpukit/score/cpu/i386/rtems/score/cpu.h513
-rw-r--r--cpukit/score/cpu/i386/rtems/score/i386.h244
-rw-r--r--cpukit/score/cpu/i386/rtems/score/idtr.h62
-rw-r--r--cpukit/score/cpu/i386/rtems/score/interrupts.h75
-rw-r--r--cpukit/score/cpu/i386/rtems/score/registers.h183
-rw-r--r--cpukit/score/cpu/i386/rtems/score/types.h57
-rw-r--r--cpukit/score/cpu/i960/.cvsignore2
-rw-r--r--cpukit/score/cpu/i960/ChangeLog224
-rw-r--r--cpukit/score/cpu/i960/Makefile.am58
-rw-r--r--cpukit/score/cpu/i960/asm.h110
-rw-r--r--cpukit/score/cpu/i960/cpu.c81
-rw-r--r--cpukit/score/cpu/i960/cpu_asm.S213
-rw-r--r--cpukit/score/cpu/i960/rtems/score/cpu.h485
-rw-r--r--cpukit/score/cpu/i960/rtems/score/i960.h194
-rw-r--r--cpukit/score/cpu/i960/rtems/score/types.h57
-rw-r--r--cpukit/score/cpu/m68k/.cvsignore2
-rw-r--r--cpukit/score/cpu/m68k/ChangeLog309
-rw-r--r--cpukit/score/cpu/m68k/Makefile.am84
-rw-r--r--cpukit/score/cpu/m68k/asm.h145
-rw-r--r--cpukit/score/cpu/m68k/cpu.c212
-rw-r--r--cpukit/score/cpu/m68k/cpu_asm.S265
-rw-r--r--cpukit/score/cpu/m68k/m68302.h661
-rw-r--r--cpukit/score/cpu/m68k/m68360.h889
-rw-r--r--cpukit/score/cpu/m68k/qsm.h204
-rw-r--r--cpukit/score/cpu/m68k/rtems/asm.h145
-rw-r--r--cpukit/score/cpu/m68k/rtems/m68k/m68302.h661
-rw-r--r--cpukit/score/cpu/m68k/rtems/m68k/m68360.h889
-rw-r--r--cpukit/score/cpu/m68k/rtems/m68k/qsm.h204
-rw-r--r--cpukit/score/cpu/m68k/rtems/m68k/sim.h333
-rw-r--r--cpukit/score/cpu/m68k/rtems/score/cpu.h689
-rw-r--r--cpukit/score/cpu/m68k/rtems/score/m68k.h416
-rw-r--r--cpukit/score/cpu/m68k/rtems/score/types.h57
-rw-r--r--cpukit/score/cpu/m68k/sim.h333
-rw-r--r--cpukit/score/cpu/mips/.cvsignore2
-rw-r--r--cpukit/score/cpu/mips/ChangeLog501
-rw-r--r--cpukit/score/cpu/mips/Makefile.am74
-rw-r--r--cpukit/score/cpu/mips/asm.h158
-rw-r--r--cpukit/score/cpu/mips/cpu.c275
-rw-r--r--cpukit/score/cpu/mips/cpu_asm.S1088
-rw-r--r--cpukit/score/cpu/mips/idtcpu.h477
-rw-r--r--cpukit/score/cpu/mips/iregdef.h331
-rw-r--r--cpukit/score/cpu/mips/rtems/asm.h158
-rw-r--r--cpukit/score/cpu/mips/rtems/mips/idtcpu.h477
-rw-r--r--cpukit/score/cpu/mips/rtems/mips/iregdef.h331
-rw-r--r--cpukit/score/cpu/mips/rtems/score/cpu.h1196
-rw-r--r--cpukit/score/cpu/mips/rtems/score/mips.h271
-rw-r--r--cpukit/score/cpu/mips/rtems/score/types.h57
-rw-r--r--cpukit/score/cpu/no_cpu/.cvsignore2
-rw-r--r--cpukit/score/cpu/no_cpu/ChangeLog228
-rw-r--r--cpukit/score/cpu/no_cpu/Makefile.am62
-rw-r--r--cpukit/score/cpu/no_cpu/asm.h99
-rw-r--r--cpukit/score/cpu/no_cpu/cpu.c185
-rw-r--r--cpukit/score/cpu/no_cpu/cpu_asm.c182
-rw-r--r--cpukit/score/cpu/no_cpu/rtems/asm.h99
-rw-r--r--cpukit/score/cpu/no_cpu/rtems/score/cpu.h1142
-rw-r--r--cpukit/score/cpu/no_cpu/rtems/score/cpu_asm.h70
-rw-r--r--cpukit/score/cpu/no_cpu/rtems/score/no_cpu.h70
-rw-r--r--cpukit/score/cpu/no_cpu/rtems/score/types.h56
-rw-r--r--cpukit/score/cpu/or32/.cvsignore2
-rw-r--r--cpukit/score/cpu/or32/ChangeLog239
-rw-r--r--cpukit/score/cpu/or32/Makefile.am62
-rw-r--r--cpukit/score/cpu/or32/asm.h99
-rw-r--r--cpukit/score/cpu/or32/cpu.c192
-rw-r--r--cpukit/score/cpu/or32/cpu_asm.c578
-rw-r--r--cpukit/score/cpu/or32/rtems/asm.h99
-rw-r--r--cpukit/score/cpu/or32/rtems/score/cpu.h1071
-rw-r--r--cpukit/score/cpu/or32/rtems/score/cpu_asm.h70
-rw-r--r--cpukit/score/cpu/or32/rtems/score/or32.h70
-rw-r--r--cpukit/score/cpu/or32/rtems/score/types.h69
-rw-r--r--cpukit/score/cpu/powerpc/.cvsignore2
-rw-r--r--cpukit/score/cpu/powerpc/ChangeLog336
-rw-r--r--cpukit/score/cpu/powerpc/Makefile.am93
-rw-r--r--cpukit/score/cpu/powerpc/asm.h296
-rw-r--r--cpukit/score/cpu/powerpc/rtems/asm.h296
-rw-r--r--cpukit/score/cpu/powerpc/rtems/new-exceptions/cpu.h948
-rw-r--r--cpukit/score/cpu/powerpc/rtems/old-exceptions/cpu.h1152
-rw-r--r--cpukit/score/cpu/powerpc/rtems/powerpc/registers.h310
-rw-r--r--cpukit/score/cpu/powerpc/rtems/score/cpu.h60
-rw-r--r--cpukit/score/cpu/powerpc/rtems/score/powerpc.h744
-rw-r--r--cpukit/score/cpu/powerpc/rtems/score/ppc.h15
-rw-r--r--cpukit/score/cpu/powerpc/rtems/score/types.h72
-rw-r--r--cpukit/score/cpu/sh/.cvsignore2
-rw-r--r--cpukit/score/cpu/sh/ChangeLog253
-rw-r--r--cpukit/score/cpu/sh/Makefile.am62
-rw-r--r--cpukit/score/cpu/sh/asm.h136
-rw-r--r--cpukit/score/cpu/sh/cpu.c254
-rw-r--r--cpukit/score/cpu/sh/rtems/asm.h136
-rw-r--r--cpukit/score/cpu/sh/rtems/score/cpu.h945
-rw-r--r--cpukit/score/cpu/sh/rtems/score/sh.h269
-rw-r--r--cpukit/score/cpu/sh/rtems/score/sh_io.h47
-rw-r--r--cpukit/score/cpu/sh/rtems/score/types.h65
-rw-r--r--cpukit/score/cpu/sparc/.cvsignore2
-rw-r--r--cpukit/score/cpu/sparc/ChangeLog269
-rw-r--r--cpukit/score/cpu/sparc/Makefile.am58
-rw-r--r--cpukit/score/cpu/sparc/README110
-rw-r--r--cpukit/score/cpu/sparc/asm.h121
-rw-r--r--cpukit/score/cpu/sparc/cpu.c330
-rw-r--r--cpukit/score/cpu/sparc/cpu_asm.S806
-rw-r--r--cpukit/score/cpu/sparc/rtems/asm.h121
-rw-r--r--cpukit/score/cpu/sparc/rtems/score/cpu.h1000
-rw-r--r--cpukit/score/cpu/sparc/rtems/score/sparc.h266
-rw-r--r--cpukit/score/cpu/sparc/rtems/score/types.h56
-rw-r--r--cpukit/score/cpu/unix/.cvsignore3
-rw-r--r--cpukit/score/cpu/unix/ChangeLog277
-rw-r--r--cpukit/score/cpu/unix/Makefile.am60
-rw-r--r--cpukit/score/cpu/unix/asm.h33
-rw-r--r--cpukit/score/cpu/unix/cpu.c1137
-rw-r--r--cpukit/score/cpu/unix/rtems/asm.h33
-rw-r--r--cpukit/score/cpu/unix/rtems/score/cpu.h1105
-rw-r--r--cpukit/score/cpu/unix/rtems/score/types.h71
-rw-r--r--cpukit/score/cpu/unix/rtems/score/unix.h71
-rw-r--r--cpukit/score/include/rtems/debug.h97
-rw-r--r--cpukit/score/include/rtems/score/.cvsignore6
-rw-r--r--cpukit/score/include/rtems/score/address.h30
-rw-r--r--cpukit/score/include/rtems/score/apiext.h101
-rw-r--r--cpukit/score/include/rtems/score/apimutex.h154
-rw-r--r--cpukit/score/include/rtems/score/bitfield.h97
-rw-r--r--cpukit/score/include/rtems/score/chain.h167
-rw-r--r--cpukit/score/include/rtems/score/context.h133
-rw-r--r--cpukit/score/include/rtems/score/copyrt.h40
-rw-r--r--cpukit/score/include/rtems/score/coremsg.h299
-rw-r--r--cpukit/score/include/rtems/score/coremutex.h236
-rw-r--r--cpukit/score/include/rtems/score/coresem.h154
-rw-r--r--cpukit/score/include/rtems/score/heap.h269
-rw-r--r--cpukit/score/include/rtems/score/interr.h96
-rw-r--r--cpukit/score/include/rtems/score/isr.h248
-rw-r--r--cpukit/score/include/rtems/score/mpci.h411
-rw-r--r--cpukit/score/include/rtems/score/mppkt.h100
-rw-r--r--cpukit/score/include/rtems/score/object.h570
-rw-r--r--cpukit/score/include/rtems/score/objectmp.h151
-rw-r--r--cpukit/score/include/rtems/score/priority.h96
-rw-r--r--cpukit/score/include/rtems/score/stack.h49
-rw-r--r--cpukit/score/include/rtems/score/states.h83
-rw-r--r--cpukit/score/include/rtems/score/sysstate.h66
-rw-r--r--cpukit/score/include/rtems/score/thread.h792
-rw-r--r--cpukit/score/include/rtems/score/threadmp.h88
-rw-r--r--cpukit/score/include/rtems/score/threadq.h300
-rw-r--r--cpukit/score/include/rtems/score/tod.h276
-rw-r--r--cpukit/score/include/rtems/score/tqdata.h89
-rw-r--r--cpukit/score/include/rtems/score/userext.h230
-rw-r--r--cpukit/score/include/rtems/score/watchdog.h195
-rw-r--r--cpukit/score/include/rtems/score/wkspace.h70
-rw-r--r--cpukit/score/include/rtems/seterr.h22
-rw-r--r--cpukit/score/include/rtems/system.h219
-rw-r--r--cpukit/score/inline/rtems/score/address.inl125
-rw-r--r--cpukit/score/inline/rtems/score/chain.inl389
-rw-r--r--cpukit/score/inline/rtems/score/coremsg.inl275
-rw-r--r--cpukit/score/inline/rtems/score/coremutex.inl196
-rw-r--r--cpukit/score/inline/rtems/score/coresem.inl107
-rw-r--r--cpukit/score/inline/rtems/score/heap.inl273
-rw-r--r--cpukit/score/inline/rtems/score/isr.inl55
-rw-r--r--cpukit/score/inline/rtems/score/mppkt.inl57
-rw-r--r--cpukit/score/inline/rtems/score/object.inl315
-rw-r--r--cpukit/score/inline/rtems/score/objectmp.inl72
-rw-r--r--cpukit/score/inline/rtems/score/priority.inl246
-rw-r--r--cpukit/score/inline/rtems/score/stack.inl80
-rw-r--r--cpukit/score/inline/rtems/score/states.inl383
-rw-r--r--cpukit/score/inline/rtems/score/sysstate.inl153
-rw-r--r--cpukit/score/inline/rtems/score/thread.inl427
-rw-r--r--cpukit/score/inline/rtems/score/threadmp.inl60
-rw-r--r--cpukit/score/inline/rtems/score/tod.inl66
-rw-r--r--cpukit/score/inline/rtems/score/tqdata.inl72
-rw-r--r--cpukit/score/inline/rtems/score/userext.inl169
-rw-r--r--cpukit/score/inline/rtems/score/watchdog.inl323
-rw-r--r--cpukit/score/inline/rtems/score/wkspace.inl56
-rw-r--r--cpukit/score/macros/README18
-rw-r--r--cpukit/score/macros/rtems/score/address.inl75
-rw-r--r--cpukit/score/macros/rtems/score/chain.inl199
-rw-r--r--cpukit/score/macros/rtems/score/coremsg.inl146
-rw-r--r--cpukit/score/macros/rtems/score/coremutex.inl81
-rw-r--r--cpukit/score/macros/rtems/score/coresem.inl71
-rw-r--r--cpukit/score/macros/rtems/score/heap.inl149
-rw-r--r--cpukit/score/macros/rtems/score/isr.inl38
-rw-r--r--cpukit/score/macros/rtems/score/mppkt.inl40
-rw-r--r--cpukit/score/macros/rtems/score/object.inl188
-rw-r--r--cpukit/score/macros/rtems/score/objectmp.inl49
-rw-r--r--cpukit/score/macros/rtems/score/priority.inl169
-rw-r--r--cpukit/score/macros/rtems/score/stack.inl49
-rw-r--r--cpukit/score/macros/rtems/score/states.inl209
-rw-r--r--cpukit/score/macros/rtems/score/sysstate.inl89
-rw-r--r--cpukit/score/macros/rtems/score/thread.inl234
-rw-r--r--cpukit/score/macros/rtems/score/threadmp.inl49
-rw-r--r--cpukit/score/macros/rtems/score/tod.inl48
-rw-r--r--cpukit/score/macros/rtems/score/tqdata.inl49
-rw-r--r--cpukit/score/macros/rtems/score/userext.inl133
-rw-r--r--cpukit/score/macros/rtems/score/watchdog.inl171
-rw-r--r--cpukit/score/macros/rtems/score/wkspace.inl38
-rw-r--r--cpukit/score/src/Unlimited.txt387
-rw-r--r--cpukit/score/src/apiext.c104
-rw-r--r--cpukit/score/src/chain.c201
-rw-r--r--cpukit/score/src/coremsg.c103
-rw-r--r--cpukit/score/src/coremsgbroadcast.c111
-rw-r--r--cpukit/score/src/coremsgclose.c76
-rw-r--r--cpukit/score/src/coremsgflush.c54
-rw-r--r--cpukit/score/src/coremsgflushsupp.c104
-rw-r--r--cpukit/score/src/coremsgflushwait.c69
-rw-r--r--cpukit/score/src/coremsginsert.c102
-rw-r--r--cpukit/score/src/coremsgseize.c136
-rw-r--r--cpukit/score/src/coremsgsubmit.c175
-rw-r--r--cpukit/score/src/coremutex.c88
-rw-r--r--cpukit/score/src/coremutexflush.c51
-rw-r--r--cpukit/score/src/coremutexseize.c154
-rw-r--r--cpukit/score/src/coremutexsurrender.c141
-rw-r--r--cpukit/score/src/coresem.c62
-rw-r--r--cpukit/score/src/coresemflush.c57
-rw-r--r--cpukit/score/src/coresemseize.c80
-rw-r--r--cpukit/score/src/coresemsurrender.c73
-rw-r--r--cpukit/score/src/coretod.c59
-rw-r--r--cpukit/score/src/coretodset.c62
-rw-r--r--cpukit/score/src/coretodtickle.c67
-rw-r--r--cpukit/score/src/coretodtoseconds.c63
-rw-r--r--cpukit/score/src/coretodvalidate.c63
-rw-r--r--cpukit/score/src/heap.c92
-rw-r--r--cpukit/score/src/heapallocate.c113
-rw-r--r--cpukit/score/src/heapextend.c111
-rw-r--r--cpukit/score/src/heapfree.c103
-rw-r--r--cpukit/score/src/heapgetinfo.c101
-rw-r--r--cpukit/score/src/heapsizeofuserarea.c62
-rw-r--r--cpukit/score/src/heapwalk.c149
-rw-r--r--cpukit/score/src/interr.c60
-rw-r--r--cpukit/score/src/isr.c65
-rw-r--r--cpukit/score/src/iterateoverthreads.c46
-rw-r--r--cpukit/score/src/mpci.c524
-rw-r--r--cpukit/score/src/object.c64
-rw-r--r--cpukit/score/src/objectallocate.c68
-rw-r--r--cpukit/score/src/objectallocatebyindex.c73
-rw-r--r--cpukit/score/src/objectclearname.c46
-rw-r--r--cpukit/score/src/objectcomparenameraw.c57
-rw-r--r--cpukit/score/src/objectcomparenamestring.c53
-rw-r--r--cpukit/score/src/objectcopynameraw.c46
-rw-r--r--cpukit/score/src/objectcopynamestring.c48
-rw-r--r--cpukit/score/src/objectextendinformation.c291
-rw-r--r--cpukit/score/src/objectfree.c65
-rw-r--r--cpukit/score/src/objectget.c83
-rw-r--r--cpukit/score/src/objectgetbyindex.c73
-rw-r--r--cpukit/score/src/objectgetisr.c89
-rw-r--r--cpukit/score/src/objectgetnext.c90
-rw-r--r--cpukit/score/src/objectgetnoprotection.c83
-rw-r--r--cpukit/score/src/objectidtoname.c67
-rw-r--r--cpukit/score/src/objectinitializeinformation.c177
-rw-r--r--cpukit/score/src/objectmp.c276
-rw-r--r--cpukit/score/src/objectnametoid.c98
-rw-r--r--cpukit/score/src/objectshrinkinformation.c115
-rw-r--r--cpukit/score/src/thread.c107
-rw-r--r--cpukit/score/src/threadchangepriority.c113
-rw-r--r--cpukit/score/src/threadclearstate.c81
-rw-r--r--cpukit/score/src/threadclose.c73
-rw-r--r--cpukit/score/src/threadcreateidle.c96
-rw-r--r--cpukit/score/src/threaddelayended.c60
-rw-r--r--cpukit/score/src/threaddispatch.c141
-rw-r--r--cpukit/score/src/threadevaluatemode.c49
-rw-r--r--cpukit/score/src/threadget.c83
-rw-r--r--cpukit/score/src/threadhandler.c164
-rw-r--r--cpukit/score/src/threadidlebody.c51
-rw-r--r--cpukit/score/src/threadinitialize.c218
-rw-r--r--cpukit/score/src/threadloadenv.c72
-rw-r--r--cpukit/score/src/threadmp.c163
-rw-r--r--cpukit/score/src/threadq.c65
-rw-r--r--cpukit/score/src/threadqdequeue.c61
-rw-r--r--cpukit/score/src/threadqdequeuefifo.c85
-rw-r--r--cpukit/score/src/threadqdequeuepriority.c124
-rw-r--r--cpukit/score/src/threadqenqueue.c76
-rw-r--r--cpukit/score/src/threadqenqueuefifo.c100
-rw-r--r--cpukit/score/src/threadqenqueuepriority.c220
-rw-r--r--cpukit/score/src/threadqextract.c53
-rw-r--r--cpukit/score/src/threadqextractfifo.c72
-rw-r--r--cpukit/score/src/threadqextractpriority.c103
-rw-r--r--cpukit/score/src/threadqextractwithproxy.c62
-rw-r--r--cpukit/score/src/threadqfirst.c57
-rw-r--r--cpukit/score/src/threadqfirstfifo.c46
-rw-r--r--cpukit/score/src/threadqfirstpriority.c52
-rw-r--r--cpukit/score/src/threadqflush.c54
-rw-r--r--cpukit/score/src/threadqtimeout.c77
-rw-r--r--cpukit/score/src/threadready.c74
-rw-r--r--cpukit/score/src/threadreset.c64
-rw-r--r--cpukit/score/src/threadresettimeslice.c71
-rw-r--r--cpukit/score/src/threadrestart.c64
-rw-r--r--cpukit/score/src/threadresume.c94
-rw-r--r--cpukit/score/src/threadrotatequeue.c86
-rw-r--r--cpukit/score/src/threadsetpriority.c52
-rw-r--r--cpukit/score/src/threadsetstate.c83
-rw-r--r--cpukit/score/src/threadsettransient.c73
-rw-r--r--cpukit/score/src/threadstackallocate.c81
-rw-r--r--cpukit/score/src/threadstackfree.c56
-rw-r--r--cpukit/score/src/threadstart.c66
-rw-r--r--cpukit/score/src/threadstartmultitasking.c89
-rw-r--r--cpukit/score/src/threadsuspend.c82
-rw-r--r--cpukit/score/src/threadtickletimeslice.c86
-rw-r--r--cpukit/score/src/threadyieldprocessor.c72
-rw-r--r--cpukit/score/src/userext.c201
-rw-r--r--cpukit/score/src/watchdog.c38
-rw-r--r--cpukit/score/src/watchdogadjust.c83
-rw-r--r--cpukit/score/src/watchdoginsert.c109
-rw-r--r--cpukit/score/src/watchdogremove.c69
-rw-r--r--cpukit/score/src/watchdogtickle.c97
-rw-r--r--cpukit/score/src/wkspace.c87
-rw-r--r--cpukit/telnetd/Makefile.am52
-rw-r--r--cpukit/telnetd/README28
-rw-r--r--cpukit/telnetd/icmds.c47
-rw-r--r--cpukit/telnetd/pty.c407
-rw-r--r--cpukit/telnetd/pty.h63
-rw-r--r--cpukit/telnetd/telnetd.c133
-rw-r--r--cpukit/telnetd/telnetd.h34
-rw-r--r--cpukit/wrapup/.cvsignore2
-rw-r--r--cpukit/wrapup/Makefile.am122
1716 files changed, 336316 insertions, 0 deletions
diff --git a/cpukit/.cvsignore b/cpukit/.cvsignore
new file mode 100644
index 0000000000..5c181fbb08
--- /dev/null
+++ b/cpukit/.cvsignore
@@ -0,0 +1,16 @@
+aclocal.m4
+autom4te*.cache
+config.cache
+config.guess
+config.h.in
+config.log
+config.status
+config.sub
+configure
+depcomp
+install-sh
+Makefile
+Makefile.in
+missing
+mkinstalldirs
+stamp-h.in
diff --git a/cpukit/ChangeLog b/cpukit/ChangeLog
new file mode 100644
index 0000000000..2e1a2d60b2
--- /dev/null
+++ b/cpukit/ChangeLog
@@ -0,0 +1,5870 @@
+2004-05-21 Joel Sherrill <joel@OARcorp.com>
+
+ PR 628/rtems
+ * posix/src/killinfo.c, posix/src/pthreadkill.c, posix/src/ptimer1.c,
+ posix/src/sigaction.c, posix/src/sigaddset.c, posix/src/sigsuspend.c:
+ Signal set of 0 is supposed to return EINVAL. In addition
+ timer_create needed to return an error if the clock was not
+ CLOCK_REALTIME.
+
+2004-05-21 Joel Sherrill <joel@OARcorp.com>
+
+ PR 629/rtems
+ * cpukit/src/mqueuecreatesupp.c: Return EINVAL is mq_maxmsg is
+ <= 0, not <.
+
+2004-05-21 Till Strauman <strauman@slac.stanford.edu>
+
+ PR 626/networking
+ * libnetworking/rtems/rtems_showifstat.c: Use unsigned char to avoid
+ printing leading FFFFFF for byte values > 127.
+
+2004-05-06 Joel Sherrill <joel@OARcorp.com>
+
+ PR 618/rtems
+ * rtems/include/rtems/rtems/status.h, rtems/src/clockget.c,
+ rtems/src/clockset.c, rtems/src/dpmemcreate.c,
+ rtems/src/dpmemexternal2internal.c,
+ rtems/src/dpmeminternal2external.c, rtems/src/eventmp.c,
+ rtems/src/eventreceive.c, rtems/src/eventsend.c,
+ rtems/src/msgqbroadcast.c, rtems/src/msgqcreate.c,
+ rtems/src/msgqflush.c, rtems/src/msgqgetnumberpending.c,
+ rtems/src/msgqreceive.c, rtems/src/msgqsubmit.c,
+ rtems/src/partcreate.c, rtems/src/partdelete.c,
+ rtems/src/partgetbuffer.c, rtems/src/ratemoncancel.c,
+ rtems/src/ratemoncreate.c, rtems/src/ratemondelete.c,
+ rtems/src/ratemongetstatus.c, rtems/src/ratemonident.c,
+ rtems/src/ratemonperiod.c, rtems/src/regioncreate.c,
+ rtems/src/regiondelete.c, rtems/src/regionextend.c,
+ rtems/src/regiongetsegment.c, rtems/src/regiongetsegmentsize.c,
+ rtems/src/regionreturnsegment.c, rtems/src/semcreate.c,
+ rtems/src/semdelete.c, rtems/src/semflush.c, rtems/src/semident.c,
+ rtems/src/taskcreate.c, rtems/src/taskgetnote.c,
+ rtems/src/taskmode.c, rtems/src/taskrestart.c,
+ rtems/src/taskresume.c, rtems/src/tasksetnote.c,
+ rtems/src/tasksuspend.c, rtems/src/taskvariableadd.c,
+ rtems/src/taskvariabledelete.c, rtems/src/taskvariableget.c,
+ rtems/src/taskwakewhen.c, rtems/src/timercreate.c,
+ rtems/src/timerdelete.c, rtems/src/timerfireafter.c,
+ rtems/src/timerfirewhen.c, rtems/src/timerserverfireafter.c,
+ rtems/src/timerserverfirewhen.c, score/include/rtems/score/object.h,
+ score/src/coretodvalidate.c, score/src/objectnametoid.c: Add NULL
+ checks.
+
+2004-04-30 Joel Sherrill <joel@OARcorp.com>
+
+ * libnetworking/kern/kern_sysctl.c: sysctl_register_all cannot be
+ static with RTEMS.
+
+2004-04-30 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * libnetworking/netinet/in.c: Partial update from FreeBSD.
+
+2004-04-26 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * libnetworking/kern/kern_sysctl.c: Partial updates from FreeBSD.
+
+2004-04-26 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * libnetworking/netinet/igmp_var.h: Cosmetic updates from FreeBSD.
+ * libnetworking/sys/sysctl.h: Update from FreeBSD.
+ * libnetworking/sys/socketvar.h: Update from FreeBSD.
+
+2004-04-24 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * libnetworking/sys/protosw.h: More partial updates from FreeBSD.
+
+2004-04-24 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * libnetworking/net/route.c: Reflect changes to radix.h.
+
+2004-04-22 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * libnetworking/net/radix.h, libnetworking/net/radix.c: Partial
+ update from FreeBSD.
+
+2004-04-22 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * libnetworking/sys/socket.h: Further update from FreeBSD
+ (Add sa_family_t).
+
+2004-04-22 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * libnetworking/sys/protosw.h: Partial update from FreeBSD.
+ * libnetworking/sys/socket.h: Partial update from FreeBSD.
+ * libnetworking/rtems/rtems_syscall.c: Reflect changes to socket.h.
+
+2004-04-22 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * libnetworking/kern/uipc_socket.c: Partial update from FreeBSD
+ (Remove adv-clause from copyright notice).
+ * libnetworking/netinet/igmp_var.h: Partial update from FreeBSD.
+
+2004-04-20 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * libnetworking/net/bpf.h, libnetworking/net/if.h,
+ libnetworking/net/if_dl.h, libnetworking/net/if_ppp.h,
+ libnetworking/net/netisr.h, libnetworking/net/pppcompress.c,
+ libnetworking/net/radix.c, libnetworking/net/radix.h,
+ libnetworking/net/raw_cb.h, libnetworking/net/route.h,
+ libnetworking/netinet/icmp_var.h, libnetworking/netinet/if_ether.h,
+ libnetworking/netinet/igmp_var.h, libnetworking/netinet/in.h,
+ libnetworking/netinet/in_pcb.h, libnetworking/netinet/in_systm.h,
+ libnetworking/netinet/in_var.h, libnetworking/netinet/ip_fw.h,
+ libnetworking/netinet/ip_icmp.h, libnetworking/netinet/ip_mroute.h,
+ libnetworking/netinet/ip_var.h, libnetworking/netinet/tcp_debug.h,
+ libnetworking/netinet/tcp_seq.h, libnetworking/netinet/tcp_timer.h,
+ libnetworking/netinet/tcp_var.h, libnetworking/netinet/udp_var.h,
+ libnetworking/nfs/nfs.h, libnetworking/rtems/rtems_bsdnet.h,
+ libnetworking/rtems/rtems_bsdnet_internal.h,
+ libnetworking/sys/buf.h, libnetworking/sys/callout.h,
+ libnetworking/sys/conf.h, libnetworking/sys/domain.h,
+ libnetworking/sys/malloc.h, libnetworking/sys/mbuf.h,
+ libnetworking/sys/mount.h, libnetworking/sys/protosw.h,
+ libnetworking/sys/queue.h, libnetworking/sys/rtprio.h,
+ libnetworking/sys/select.h, libnetworking/sys/signalvar.h,
+ libnetworking/sys/socket.h, libnetworking/sys/socketvar.h,
+ libnetworking/sys/sysctl.h, libnetworking/sys/syslog.h,
+ libnetworking/sys/ucred.h, libnetworking/sys/uio.h,
+ libnetworking/vm/vm.h, libnetworking/vm/vm_extern.h,
+ libnetworking/vm/vm_param.h: Use -D_KERNEL instead of -DKERNEL for
+ greater FreeBSD compliance.
+
+2004-04-20 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * libnetworking/Makefile.am: Add -D_KERNEL to CPPFLAGS.
+
+2004-04-20 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * libnetworking/net/bpf.h: Partial update from FreeBSD.
+
+2004-04-19 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * libnetworking/sys/sysctl.h: Partial update from FreeBSD.
+ * libnetworking/kern/kern_sysctl.c: Partial update from FreeBSD.
+
+2004-04-17 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * libfs/src/imfs/imfs_debug.c, libfs/src/imfs/memfile.c:
+ Use fprintf(stdout,...) instead of printf.
+
+2004-04-17 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * libblock/src/ide_part_table.c: Use fprintf(stdout,...) instead of
+ printf.
+
+2004-04-17 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * libmisc/capture/capture-cli.c, libmisc/cpuuse/cpuuse.c,
+ libmisc/dumpbuf/dumpbuf.c, libmisc/fsmount/fsmount.c,
+ libmisc/monitor/mon-command.c, libmisc/monitor/mon-config.c,
+ libmisc/monitor/mon-dname.c, libmisc/monitor/mon-driver.c,
+ libmisc/monitor/mon-extension.c, libmisc/monitor/mon-itask.c,
+ libmisc/monitor/mon-monitor.c, libmisc/monitor/mon-mpci.c,
+ libmisc/monitor/mon-object.c, libmisc/monitor/mon-prmisc.c,
+ libmisc/monitor/mon-queue.c, libmisc/monitor/mon-symbols.c,
+ libmisc/monitor/mon-task.c, libmisc/rtmonuse/rtmonuse.c,
+ libmisc/shell/cmds.c, libmisc/shell/shell.c, libmisc/shell/shell.h,
+ libmisc/stackchk/check.c, libmisc/untar/untar.c: Use
+ fprintf(stdout,...) instead of printf.
+
+2004-04-14 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * sapi/include/rtems/sptables.h: Remove _RTEMS_version.
+
+2004-04-14 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * libcsupport/Makefile.am: Install include_sys_HEADERS for NEWLIB
+ only. Merge sys/cdefs.h into general include_sys_HEADERS.
+
+2004-04-13 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * rtems/include/rtems/rtems/types.h: Include <rtems/stdint.h>
+ instead of <stdint.h>.
+ Conditionally typedef rtems*signed64 types.
+ * score/include/rtems/system.h: Include <rtems/stdint.h> instead of
+ <stdint.h>.
+
+2004-04-13 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * configure.ac: Rework stdint.h/inttypes.h support.
+ Add RTEMS_USES_STDINT_H. Add RTEMS_USES_INTTYPES_H.
+ Remove NEED_STDINT_H. Remove NEED_INTTYPES_H.
+ Remove termios-flag detection.
+ * libcsupport/Makefile.am: Install include/stdint.h and
+ include/inttypes.h for NEWLIB only.
+ * libcsupport/include/stdint.h: Rework; Now newlib specific.
+ * libcsupport/src/termios.c: Make newlib specific.
+ * include/rtems/stdint.h: Rework; Now wrapper to <stdint.h>.
+
+2004-04-12 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * acinclude.m4 (RTEMS_CPUOPT): Use AC_DEFINE_UNQUOTED.
+ * backward/motorola/mc68681.h, backward/motorola/mc68230.h,
+ backward/zilog/z8536.h, backward/zilog/z8036.h,
+ backward/zilog/z8030.h: New.
+ * Makefile.am: Reflect having added new files above.
+
+2004-04-09 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * wrapup/Makefile.am: Add libblock for !UNIX only.
+
+2004-04-09 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * libblock/Makefile.am: Build libblock for !UNIX only.
+ * libcsupport/Makefile.am: Build $(TERMIOS_C_FILES) for !UNIX only.
+
+2004-04-09 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * libblock/Makefile.am: Remove LIBC_DEFINES (Unsupported).
+ * libfs/Makefile.am: Remove LIBC_DEFINES (Unsupported).
+
+2004-04-08 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * libcsupport/Makefile.am: Install sys/ioccom.h for NEWLIB only.
+
+2004-04-08 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * libcsupport/Makefile.am: Remove $(LIBC_DEFINES) (Unsupported).
+ Install motorola-headers to $(includedir)/rtems/motorola.
+ Install zilog-headers to $(includedir)/rtems/zilog.
+
+2004-04-06 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * score/cpu/Makefile.am: Add unix to DIST_SUBDIRS.
+
+2004-04-06 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * aclocal/rtems-cpu-subdirs.m4: Remove (Unused).
+ * configure.ac: Remove RTEMS_CPU_SUBDIRS([score/cpu]).
+ Add RTEMS_CHECK_SYSV_UNIX.
+ Add score/cpu/*/Makefile.
+ * score/cpu/Makefile.am: Add DIST_SUBDIRS.
+
+2004-04-05 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * configure.ac: Add AC_CHECK_SIZEOF([CPU_CONTEXT]..).
+ Add SIZEOF_CPU_CONTEXT to cpuopts.h.
+ Add RTEMS_PROG_CCAS.
+ * acinclude.m4: Use unquoted "here" document to propagate $3 to
+ cpuopts.tmp.
+
+2004-04-02 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * libnetworking/Makefile.am: AM_CPPFLAGS += -I$(srcdir).
+ * libnetworking/rtems/rtems_bsdnet_internal.h: Remove USHRT_MAX.
+
+2004-04-02 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * libnetworking/Makefile.am: Fix typo.
+
+2004-04-01 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * libnetworking/poll.h: Replace with sys/poll.h wrapper.
+ * libnetworking/sys/poll.h: New (Original FreeBSD file).
+ * libnetworking/Makefile.am: Don't install opt_ipfw.h,
+ opt_mrouting.h, opt_tcpdebug.h. Add sys/poll.h.
+
+2004-04-01 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * libmisc/serdbg/serdbgcnf.h: Include <rtems/serdbg.h> instead of
+ <serdbg.h>
+ * libmisc/serdbg/termios_printk_cnf.h: Include <rtems/termios_printk.h>
+ instead of <termios_printk.h>.
+
+2004-04-01 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * libmisc/Makefile.am: Install serdbg.h, serdbgcnf.h,
+ termios_printk.h, termios_printk_cnf.h to $(includedir)/rtems.
+ * libmisc/serdbg/serdbg.c: Include <rtems/serdbg.h> instead of
+ <serdbg.h>.
+ * libmisc/serdbg/serdbgio.c: Include <rtems/serdbg.h> instead of
+ <serdbg.h>.
+ * libmisc/serdbg/termios_printk.c: Include <rtems/termios_printk.h>
+ instead of <termios_printk.h>.
+
+2004-04-01 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * libmisc/dummy/dummy.c: Include <rtems/confdefs.h> instead of <confdefs.h>.
+
+2004-04-01 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * backward/confdefs.h: New.
+ * Makefile.am: Add backward/confdefs.h.
+ Add conditional DEPRECATED.
+ * configure.ac: Add --enable-deprecated.
+ Add conditional DEPRECATED.
+
+2004-04-01 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * sapi/Makefile.am: Install confdefs.h to $(includedir)/rtems.
+
+2004-04-01 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * Makefile.am: Add backward/*.h headers.
+ * itron/Makefile.am: Install itron.h to $(includedir)/rtems.
+ * libcsupport/Makefile.am: Install RTEMS specific headers to
+ $(includedir)/rtems.
+ * libfs/Makefile.am: Install imfs.h and dosfs.h to
+ $(includedir)/rtems.
+
+2004-04-01 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * libblock/include/rtems/bdbuf.h: Include <rtems/chain.h> instead of <chain.h>.
+ * libblock/include/rtems/ide_part_table.h: Include <rtems/chain.h> instead of <chain.h>.
+ * libcsupport/src/malloc.c: Include <rtems/chain.h> instead of <chain.h>.
+ * libcsupport/src/mount.c: Include <rtems/chain.h> instead of <chain.h>.
+ * libcsupport/src/unmount.c: Include <rtems/chain.h> instead of <chain.h>.
+ * libfs/src/imfs/imfs.h: Include <rtems/chain.h> instead of <chain.h>.
+ * libfs/src/imfs/imfs_directory.c: Include <rtems/chain.h> instead of <chain.h>.
+ * libfs/src/imfs/imfs_load_tar.c: Include <rtems/chain.h> instead of <chain.h>.
+ * sapi/include/confdefs.h: Include <rtems/clockdrv.h> instead of <clockdrv.h>.
+ * sapi/include/confdefs.h: Include <rtems/console.h> instead of <console.h>.
+ * libfs/src/imfs/imfs_load_tar.c: Include <rtems/imfs.h> instead of <imfs.h>.
+ * libmisc/shell/cmds.c: Include <rtems/imfs.h> instead of <imfs.h>.
+ * libmisc/fsmount/fsmount.c: Include <rtems/imfs.h> instead of <imfs.h>.
+ * sapi/include/confdefs.h: Include <rtems/imfs.h> instead of <imfs.h>.
+ * itron/src/can_wup.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/chg_pri.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/cre_mbf.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/cre_mbx.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/cre_sem.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/cre_tsk.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/del_mbf.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/del_mbx.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/del_sem.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/del_tsk.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/dis_dsp.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/ena_dsp.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/eventflags.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/exd_tsk.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/ext_tsk.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/fmempool.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/frsm_tsk.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/get_tid.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/itronintr.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/itronsem.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/itrontime.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/mbox.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/mboxtranslatereturncode.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/msgbuffer.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/msgbuffertranslatereturncode.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/network.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/port.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/prcv_mbf.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/prcv_mbx.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/preq_sem.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/psnd_mbf.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/rcv_mbf.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/rcv_mbx.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/ref_mbf.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/ref_mbx.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/ref_sem.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/ref_tsk.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/rel_wai.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/rot_rdq.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/rsm_tsk.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/sig_sem.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/slp_tsk.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/snd_mbf.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/snd_mbx.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/sta_tsk.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/sus_tsk.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/sysmgmt.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/task.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/ter_tsk.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/trcv_mbf.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/trcv_mbx.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/tslp_tsk.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/tsnd_mbf.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/twai_sem.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/vmempool.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/wai_sem.c: Include <rtems/itron.h> instead of <itron.h>.
+ * itron/src/wup_tsk.c: Include <rtems/itron.h> instead of <itron.h>.
+ * sapi/include/rtems/config.h: Include <rtems/itron.h> instead of <itron.h>.
+ * sapi/include/confdefs.h: Include <rtems/itron.h> instead of <itron.h>.
+ * sapi/src/itronapi.c: Include <rtems/itron.h> instead of <itron.h>.
+ * sapi/include/confdefs.h: Include <rtems/rtc.h> instead of <rtc.h>.
+ * sapi/include/confdefs.h: Include <rtems/timerdrv.h> instead of <timerdrv.h>.
+
+2004-04-01 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * backward/asm.h, backward/chain.h, backward/clockdrv.h,
+ backward/console.h, backward/dosfs.h, backward/imfs.h,
+ backward/iosupp.h, backward/itron.h, backward/ringbuf.h,
+ backward/rtc.h, backward/spurious.h, backward/timerdrv.h,
+ backward/vmeintr.h: New.
+
+2004-03-30 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * rtems/include/rtems/rtems/region.h:
+ Include stddef.h for size_t.
+ (rtems_region_get_segment_size): Use size_t instead of uint32_t for "size" (3rd arg).
+ * rtems/src/regiongetsegmentsize.c: Reflect changes above.
+ * libcsupport/src/malloc.c: Reflect changes above.
+
+2004-03-30 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * aclocal/rtems-top.m4: Don't AC_SUBST(PROJECT_ROOT).
+ Add project_libdir, project_include and libdir.
+ * aclocal/env-rtemscpu.m4: Remove all references to RTEMS_BSP.
+ Remove project_libdir, project_include and libdir.
+ Unconditionally use CPU_CFLAGS, CFLAGS_OPTIMIZE_V, CFLAGS_DEBUG_V.
+
+2004-03-29 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * libnetworking/lib/ftpfs.c, libnetworking/lib/rtems_bsdnet_ntp.c,
+ libnetworking/lib/tftpDriver.c, libnetworking/machine/endian.h,
+ libnetworking/net/if_ppp.c, libnetworking/rtems/rtems_bsdnet.h,
+ libnetworking/rtems/rtems_bsdnet_internal.h,
+ libnetworking/rtems/rtems_glue.c,
+ libnetworking/rtems/rtems_syscall.c: Convert to using c99 fixed size
+ types.
+
+2004-03-29 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * score/include/rtems/debug.h, score/include/rtems/score/bitfield.h,
+ score/include/rtems/score/chain.h,
+ score/include/rtems/score/coremsg.h,
+ score/include/rtems/score/coremutex.h,
+ score/include/rtems/score/coresem.h,
+ score/include/rtems/score/heap.h,
+ score/include/rtems/score/interr.h, score/include/rtems/score/isr.h,
+ score/include/rtems/score/mpci.h, score/include/rtems/score/mppkt.h,
+ score/include/rtems/score/object.h,
+ score/include/rtems/score/objectmp.h,
+ score/include/rtems/score/priority.h,
+ score/include/rtems/score/stack.h,
+ score/include/rtems/score/states.h,
+ score/include/rtems/score/thread.h,
+ score/include/rtems/score/threadmp.h,
+ score/include/rtems/score/threadq.h,
+ score/include/rtems/score/tod.h, score/include/rtems/score/tqdata.h,
+ score/include/rtems/score/userext.h,
+ score/include/rtems/score/watchdog.h,
+ score/include/rtems/score/wkspace.h,
+ score/inline/rtems/score/address.inl,
+ score/inline/rtems/score/coremsg.inl,
+ score/inline/rtems/score/coresem.inl,
+ score/inline/rtems/score/heap.inl, score/inline/rtems/score/isr.inl,
+ score/inline/rtems/score/object.inl,
+ score/inline/rtems/score/priority.inl,
+ score/inline/rtems/score/stack.inl,
+ score/inline/rtems/score/thread.inl,
+ score/inline/rtems/score/tqdata.inl,
+ score/inline/rtems/score/userext.inl,
+ score/inline/rtems/score/wkspace.inl,
+ score/macros/rtems/score/address.inl,
+ score/macros/rtems/score/heap.inl,
+ score/macros/rtems/score/object.inl,
+ score/macros/rtems/score/priority.inl,
+ score/macros/rtems/score/userext.inl: Convert to using c99 fixed
+ size types.
+
+2004-03-29 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * sapi/include/confdefs.h, sapi/include/rtems/config.h,
+ sapi/include/rtems/extension.h, sapi/include/rtems/fatal.h,
+ sapi/include/rtems/init.h, sapi/include/rtems/io.h,
+ sapi/src/exinit.c, sapi/src/extension.c, sapi/src/fatal.c,
+ sapi/src/io.c: Convert to using c99 fixed size types.
+
+2004-03-29 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * rtems/include/rtems.h,
+ rtems/include/rtems/rtems/asr.h,
+ rtems/include/rtems/rtems/attr.h,
+ rtems/include/rtems/rtems/clock.h,
+ rtems/include/rtems/rtems/config.h,
+ rtems/include/rtems/rtems/dpmem.h,
+ rtems/include/rtems/rtems/eventset.h,
+ rtems/include/rtems/rtems/message.h,
+ rtems/include/rtems/rtems/modes.h,
+ rtems/include/rtems/rtems/msgmp.h,
+ rtems/include/rtems/rtems/options.h,
+ rtems/include/rtems/rtems/part.h,
+ rtems/include/rtems/rtems/ratemon.h,
+ rtems/include/rtems/rtems/region.h,
+ rtems/include/rtems/rtems/regionmp.h,
+ rtems/include/rtems/rtems/sem.h,
+ rtems/include/rtems/rtems/support.h,
+ rtems/include/rtems/rtems/taskmp.h,
+ rtems/include/rtems/rtems/tasks.h,
+ rtems/include/rtems/rtems/timer.h,
+ rtems/inline/rtems/rtems/part.inl,
+ rtems/inline/rtems/rtems/region.inl,
+ rtems/macros/rtems/rtems/part.inl,
+ rtems/src/attr.c,
+ rtems/src/dpmem.c,
+ rtems/src/dpmemcreate.c,
+ rtems/src/dpmemexternal2internal.c,
+ rtems/src/dpmeminternal2external.c,
+ rtems/src/eventseize.c,
+ rtems/src/msg.c,
+ rtems/src/msgmp.c,
+ rtems/src/msgqallocate.c,
+ rtems/src/msgqbroadcast.c,
+ rtems/src/msgqcreate.c,
+ rtems/src/msgqflush.c,
+ rtems/src/msgqgetnumberpending.c,
+ rtems/src/msgqident.c,
+ rtems/src/msgqreceive.c,
+ rtems/src/msgqsend.c,
+ rtems/src/msgqsubmit.c,
+ rtems/src/msgqtranslatereturncode.c,
+ rtems/src/msgqurgent.c,
+ rtems/src/part.c,
+ rtems/src/partcreate.c,
+ rtems/src/partident.c,
+ rtems/src/partmp.c,
+ rtems/src/ratemon.c,
+ rtems/src/region.c,
+ rtems/src/regioncreate.c,
+ rtems/src/regionextend.c,
+ rtems/src/regiongetsegment.c,
+ rtems/src/regiongetsegmentsize.c,
+ rtems/src/regionmp.c,
+ rtems/src/regionreturnsegment.c,
+ rtems/src/rtemstimer.c,
+ rtems/src/sem.c,
+ rtems/src/semcreate.c,
+ rtems/src/semident.c,
+ rtems/src/semmp.c,
+ rtems/src/semobtain.c,
+ rtems/src/semtranslatereturncode.c,
+ rtems/src/taskcreate.c,
+ rtems/src/taskgetnote.c,
+ rtems/src/taskident.c,
+ rtems/src/taskinitusers.c,
+ rtems/src/taskmp.c,
+ rtems/src/taskrestart.c,
+ rtems/src/tasks.c,
+ rtems/src/tasksetnote.c,
+ rtems/src/taskstart.c,
+ rtems/src/timerserver.c: Convert to using c99 fixed size types.
+
+2004-04-29 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * score/src/Unlimited.txt, score/src/chain.c, score/src/coremsg.c,
+ score/src/coremsgbroadcast.c, score/src/coremsgclose.c,
+ score/src/coremsgflush.c, score/src/coremsgflushsupp.c,
+ score/src/coremsgseize.c, score/src/coremsgsubmit.c,
+ score/src/coremutex.c, score/src/coremutexflush.c,
+ score/src/coresem.c, score/src/coresemflush.c, score/src/coretod.c,
+ score/src/coretodtickle.c, score/src/coretodtoseconds.c,
+ score/src/coretodvalidate.c, score/src/heap.c,
+ score/src/heapallocate.c, score/src/heapextend.c,
+ score/src/heapfree.c, score/src/heapsizeofuserarea.c,
+ score/src/interr.c, score/src/iterateoverthreads.c,
+ score/src/mpci.c, score/src/object.c, score/src/objectallocate.c,
+ score/src/objectallocatebyindex.c, score/src/objectclearname.c,
+ score/src/objectcomparenameraw.c,
+ score/src/objectcomparenamestring.c, score/src/objectcopynameraw.c,
+ score/src/objectcopynamestring.c,
+ score/src/objectextendinformation.c, score/src/objectfree.c,
+ score/src/objectget.c, score/src/objectgetbyindex.c,
+ score/src/objectgetisr.c, score/src/objectgetnoprotection.c,
+ score/src/objectidtoname.c, score/src/objectinitializeinformation.c,
+ score/src/objectmp.c, score/src/objectnametoid.c,
+ score/src/objectshrinkinformation.c, score/src/thread.c,
+ score/src/threadcreateidle.c, score/src/threadget.c,
+ score/src/threadidlebody.c, score/src/threadinitialize.c,
+ score/src/threadmp.c, score/src/threadq.c,
+ score/src/threadqdequeuepriority.c,
+ score/src/threadqenqueuepriority.c,
+ score/src/threadqfirstpriority.c, score/src/threadqflush.c,
+ score/src/threadreset.c, score/src/threadrestart.c,
+ score/src/threadsettransient.c, score/src/threadstackallocate.c,
+ score/src/threadstart.c, score/src/userext.c,
+ score/src/watchdoginsert.c, score/src/wkspace.c: Convert to using
+ c99 fixed size types.
+
+2004-03-29 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ PR 561/rtems
+ * include/rtems/concat.h: New.
+ * Makefile.am: Add include/rtems/concat.h.
+
+ PR 589/rtems
+ * Makefile.am: Add include/rtems/pci.h.
+
+ * Makefile.am: Include automake/compile.am.
+ * configure.ac: RTEMS_TOP([..],[]).
+
+2004-03-29 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * aclocal/rtems-top.m4: Add MULTISUBDIR. Add MULTIBUILDTOP.
+ Add rtems_updir. Remove version.m4 check.
+ Add PROJECT_ROOT/with_project_root processing.
+ Add PROJECT_INCLUDE. Add PROJECT_LIB.
+ * aclocal/env-rtemscpu.a4: Remove cpukit_topdir.
+ Remove with_project_root processing. Remove PROJECT_INCLUDE,
+ PROJECT_LIB.
+
+2004-03-26 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * libmisc/capture/capture-cli.c, libmisc/capture/capture.c,
+ libmisc/capture/capture.h, libmisc/cpuuse/cpuuse.c,
+ libmisc/devnull/devnull.c, libmisc/fsmount/fsmount.h,
+ libmisc/monitor/mon-config.c, libmisc/monitor/mon-dname.c,
+ libmisc/monitor/mon-driver.c, libmisc/monitor/mon-extension.c,
+ libmisc/monitor/mon-itask.c, libmisc/monitor/mon-monitor.c,
+ libmisc/monitor/mon-mpci.c, libmisc/monitor/mon-object.c,
+ libmisc/monitor/mon-prmisc.c, libmisc/monitor/mon-queue.c,
+ libmisc/monitor/mon-server.c, libmisc/monitor/mon-symbols.c,
+ libmisc/monitor/monitor.h, libmisc/monitor/symbols.h,
+ libmisc/mw-fb/mw_uid.c, libmisc/rtmonuse/rtmonuse.c,
+ libmisc/serdbg/serdbg.h, libmisc/serdbg/serdbgio.c,
+ libmisc/serdbg/termios_printk.c, libmisc/serdbg/termios_printk.h,
+ libmisc/shell/shell.c, libmisc/shell/shell.h, libmisc/stackchk/check.c,
+ libmisc/stackchk/internal.h: Convert to using c99 fixed size types.
+
+2004-03-23 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * itron/include/itronsys/mbox.h, itron/include/itronsys/types.h,
+ itron/include/rtems/itron/eventflags.h,
+ itron/include/rtems/itron/fmempool.h,
+ itron/include/rtems/itron/mbox.h,
+ itron/include/rtems/itron/msgbuffer.h,
+ itron/include/rtems/itron/port.h,
+ itron/include/rtems/itron/semaphore.h,
+ itron/include/rtems/itron/task.h,
+ itron/include/rtems/itron/vmempool.h,
+ itron/inline/rtems/itron/semaphore.inl,
+ itron/macros/rtems/itron/semaphore.inl, itron/src/eventflags.c,
+ itron/src/fmempool.c, itron/src/itronsem.c, itron/src/mbox.c,
+ itron/src/msgbuffer.c, itron/src/port.c, itron/src/snd_mbx.c,
+ itron/src/task.c, itron/src/trcv_mbx.c, itron/src/vmempool.c:
+ Convert to using c99 fixed size types.
+
+2004-03-23 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * posix/include/rtems/posix/cond.h,
+ posix/include/rtems/posix/intr.h, posix/include/rtems/posix/key.h,
+ posix/include/rtems/posix/mqueue.h,
+ posix/include/rtems/posix/mutex.h,
+ posix/include/rtems/posix/pthread.h,
+ posix/include/rtems/posix/semaphore.h,
+ posix/include/rtems/posix/threadsup.h,
+ posix/include/rtems/posix/timer.h, posix/src/cond.c,
+ posix/src/intr.c, posix/src/key.c, posix/src/keycreate.c,
+ posix/src/keydelete.c, posix/src/keygetspecific.c,
+ posix/src/keyrundestructors.c, posix/src/keysetspecific.c,
+ posix/src/killinfo.c, posix/src/mqueue.c,
+ posix/src/mqueuerecvsupp.c, posix/src/mqueuesendsupp.c,
+ posix/src/mqueuetranslatereturncode.c, posix/src/mutex.c,
+ posix/src/posixintervaltotimespec.c,
+ posix/src/posixtimespecsubtract.c, posix/src/psignal.c,
+ posix/src/pthread.c, posix/src/ptimer1.c, posix/src/semaphore.c,
+ posix/src/sysconf.c: Convert to using c99 fixed size types.
+
+2004-03-23 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * score/include/rtems/system.h: include <stdint.h>.
+
+2004-03-23 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ PR/589 rtems
+ * include/rtems/pci.h: New (Moved from c/src/libchip/network/pci.h).
+
+2004-03-23 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * libcsupport/src/malloc.c: Remove lvalue casts.
+
+2004-03-23 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * libcsupport/include/chain.h, libcsupport/include/clockdrv.h,
+ libcsupport/include/ringbuf.h, libcsupport/include/spurious.h,
+ libcsupport/include/timerdrv.h, libcsupport/include/vmeintr.h,
+ libcsupport/include/motorola/mc68230.h,
+ libcsupport/include/rtems/assoc.h, libcsupport/include/rtems/libio.h,
+ libcsupport/include/rtems/libio_.h,
+ libcsupport/include/rtems/termiostypes.h,
+ libcsupport/include/zilog/z8036.h, libcsupport/include/zilog/z8530.h,
+ libcsupport/include/zilog/z8536.h, libcsupport/src/__gettod.c,
+ libcsupport/src/assoc.c, libcsupport/src/assocnamebad.c,
+ libcsupport/src/error.c, libcsupport/src/libio.c,
+ libcsupport/src/libio_sockets.c, libcsupport/src/malloc.c,
+ libcsupport/src/no_libc.c, libcsupport/src/termios.c,
+ libcsupport/src/termiosreserveresources.c: Convert to using c99
+ fixed-size types.
+
+2004-03-22 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * libfs/src/dosfs/fat.c, libfs/src/dosfs/fat.h,
+ libfs/src/dosfs/fat_fat_operations.c,
+ libfs/src/dosfs/fat_fat_operations.h, libfs/src/dosfs/fat_file.c,
+ libfs/src/dosfs/fat_file.h, libfs/src/dosfs/msdos.h,
+ libfs/src/dosfs/msdos_create.c, libfs/src/dosfs/msdos_dir.c,
+ libfs/src/dosfs/msdos_file.c, libfs/src/dosfs/msdos_initsupp.c,
+ libfs/src/dosfs/msdos_misc.c, libfs/src/imfs/deviceio.c,
+ libfs/src/imfs/imfs.h, libfs/src/imfs/imfs_directory.c,
+ libfs/src/imfs/imfs_fchmod.c, libfs/src/imfs/linearfile.c,
+ libfs/src/imfs/memfile.c: Convert to using c99 fixed-size types.
+
+2004-03-05 Joel Sherrill <joel@OARcorp.com>
+
+ * libnetworking/net/radix.c: Remove warning.
+
+2004-03-05 Joel Sherrill <joel@OARcorp.com>
+
+ * libmisc/shell/cmds.c: Remove warning.
+
+2004-03-05 Joel Sherrill <joel@OARcorp.com>
+
+ * libnetworking/lib/ftpfs.c: Switch bcopy to memcpy.
+
+2004-03-05 Joel Sherrill <joel@OARcorp.com>
+
+ * libcsupport/src/newlibc.c, libcsupport/src/sync.c: Eliminate
+ warnings. Explicitly defeat __STRICT_ANSI__ since both
+ legitimately use routines beyond ANSI.
+
+2004-03-05 Joel Sherrill <joel@OARcorp.com>
+
+ * cpukit/libblock/src/bdbuf.c: Initialize pointer to avoid warning.
+
+2004-03-05 Joel Sherrill <joel@OARcorp.com>
+
+ * score/macros/rtems/score/chain.inl, score/src/objectidtoname.c:
+ Add cast to avoid type punning warning in gcc 3.3.
+2004-03-05 Joel Sherrill <joel@OARcorp.com>
+
+ *
+
+2004-03-05 Joel Sherrill <joel@OARcorp.com>
+
+ * libblock/src/bdbuf.c, libblock/src/ramdisk.c,
+ libcsupport/src/newlibc.c, libcsupport/src/sync.c,
+ libmisc/cpuuse/cpuuse.c, libmisc/monitor/mon-symbols.c,
+ libmisc/shell/cmds.c, libmisc/shell/shell.c,
+ libnetworking/kern/kern_sysctl.c, libnetworking/lib/ftpfs.c,
+ libnetworking/lib/tftpDriver.c, libnetworking/libc/gethostbydns.c,
+ libnetworking/libc/gethostbyht.c, libnetworking/libc/gethostnamadr.c,
+ libnetworking/libc/getnetbyht.c, libnetworking/libc/getnetnamadr.c,
+ libnetworking/libc/inet_addr.c, libnetworking/libc/linkaddr.c,
+ libnetworking/libc/map_v4v6.c, libnetworking/libc/ns_print.c,
+ libnetworking/libc/ns_ttl.c, libnetworking/libc/nsap_addr.c,
+ libnetworking/libc/rcmd.c, libnetworking/libc/res_debug.c,
+ libnetworking/libc/res_mkupdate.c, libnetworking/libc/res_query.c,
+ libnetworking/libc/res_send.c, libnetworking/libc/res_update.c,
+ libnetworking/net/radix.c, libnetworking/rtems/mkrootfs.c,
+ librpc/src/rpc/clnt_perror.c, librpc/src/rpc/rtems_rpc.c,
+ librpc/src/rpc/svc.c, sapi/include/confdefs.h,
+ score/macros/rtems/score/chain.inl, score/src/objectidtoname.c:
+
+2004-02-26 Thomas Rauscher <trauscher@loytec.com.
+
+ PR 584/RTEMS
+ * rtems/src/eventtimeout.c: Fix critical section window.
+
+2004-02-26 Joel Sherrill <joel@OARcorp.com>
+
+ PR 582/core
+ * posix/src/mqueue.c, posix/src/mqueuecreatesupp.c,
+ posix/src/mqueuedeletesupp.c, posix/src/mqueueunlink.c: Use memory
+ from workspace to avoid use of mutex during dispatch disable critical
+ section. Besides memory for object names should come from the
+ Workspace anyway.
+
+2004-02-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * aclocal/version.m4: 4.6.99.0.
+
+2004-02-09 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libnetworking/Makefile.am: Remove ACLOCAL_AMFLAGS.
+
+2004-01-30 Wilfried Busalski <w.busalski@lancier-monitoring.de>
+
+ PR pppd/564
+ * libnetworking/net/if_ppp.c, libnetworking/net/if_pppvar.h,
+ libnetworking/net/ppp_tty.c: ppp0 Interface lose packets if the
+ system use a slow baudrate for the modem or the tcp/ip-packet is
+ fragmented.
+
+2004-01-30 Joel Sherrill <joel@OARcorp.com>
+
+ * ChangeLog, rtems/Makefile.am, rtems/include/rtems/rtems/support.h:
+ Reverse developmental patches accidentally committed.
+
+2004-01-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * ChangeLog: Merge-in libnetworking/ChangeLog.
+ * ChangeLog: Merge-in libcsupport/ChangeLog.
+ * ChangeLog: Merge-in libblock/ChangeLog, libfs/ChangeLog.
+ * ChangeLog: Merge-in libmisc/ChangeLog, librpc/ChangeLog.
+ * ChangeLog: Merge-in itron/ChangeLog, posix/ChangeLog, score/ChangeLog,
+ sapi/ChangeLog, rtems/ChangeLog.
+ * libblock/ChangeLog, libfs/ChangeLog, libcsupport/ChangeLog,
+ libmisc/ChangeLog, librpc/ChangeLog, libnetworking/ChangeLog,
+ itron/ChangeLog, posix/ChangeLog, score/ChangeLog, sapi/ChangeLog,
+ rtems/ChangeLog: Remove.
+
+2004-01-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * aclocal/rtems-top.m4: Remove PROJECT_ROOT. Prepend ../ to $1.
+ * aclocal/env-rtemscpu.m4: Reworked.
+ * configure.ac: RTEMS_TOP([.]).
+
+2004-01-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am, itron/Makefile.am, posix/Makefile.am, score/Makefile.am,
+ sapi/Makefile.am, rtems/Makefile.am, libmisc/Makefile.am,
+ librpc/Makefile.am, libblock/Makefile.am, libfs/Makefile.am,
+ libcsupport/Makefile.am, libnetworking/Makefile.am: Add PREINSTALL_DIRS.
+
+2004-01-14 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * wrapup/Makefile.am: Remove $(ARCH)/$(dirstamp). Add TMPINSTALL_FILES
+ to CLEANFILES.
+ * automake/local.am: Remove depend-am.
+ * automake/subdirs.am: Remove depend-recursive.
+ * score/Makefile.am: Re-add dirstamps to PREINSTALL_FILES. Add
+ PREINSTALL_FILES to CLEANFILES. Add cpuopts.h to DISTCLEANFILES.
+ * Makefile.am, itron/Makefile.am, posix/Makefile.am, sapi/Makefile.am,
+ rtems/Makefile.am, libmisc/Makefile.am, librpc/Makefile.am,
+ libblock/Makefile.am, libfs/Makefile.am, libcsupport/Makefile.am,
+ libnetworking/Makefile.am: Re-add dirstamps to PREINSTALL_FILES. Add
+ PREINSTALL_FILES to CLEANFILES.
+ * libnetworking/netinet/in_cksum.c: #include netinet/in_cksum_<cpu>.h.
+
+2004-01-13 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ PR/549 networking
+ * libnetworking/netinet/in_cksum_powerpc.h: New (copy of
+ in_cksum_powerpc.c).
+ * libnetworking/netinet/in_cksum_i386.h: New (copy of in_cksum_i386.c).
+ * libnetworking/netinet/in_cksum_arm.h: New (copy of in_cksum_arm.c).
+ * libnetworking/netinet/in_cksum_m68k.c: New (copy of in_cksum_m68k.c).
+ * libnetworking/netinet/in_cksum_i386.c,
+ libnetworking/netinet/in_cksum_arm.c,
+ libnetworking/netinet/in_cksum_powerpc.c,
+ libnetworking/netinet/in_cksum_m68k.c: Remove.
+ * libnetworking/netinet/Makefile.am: Reflect changes above.
+
+2004-01-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Requires automake >= 1.8.1.
+ * score/cpu/Makefile.am: Use @RTEMS_CPU@ instead of $(RTEMS_CPU).
+ PR 548/rtems
+ * libcsupport/Makefile.am: Add src/envlock.c.
+
+2004-01-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * aclocal/rtems-top.m4: Don't AC_SUBST PROJECT_ROOT. Remove
+ PROJECT_TOPdir (Unused).
+ * aclocal/env-rtemscpu.m4: Remove PROJECT_RELEASE. Expand
+ ${PROJECT_ROOT}. Remove RTEMS_ENABLE_BARE (Unused). Don't AC_SUBST
+ RTEMS_BSP.
+ * aclocal/enable-bare.m4: Remove (Unused).
+ * aclocal/rtems-top.m4: Remove check for cpukit/aclocal/version.m4.
+ Remove gnu-make endif HACK (Unused).
+ * wrapup/Makefile.am: Include compile.am. Use TMP_LIBS instead of LIBS
+ to avoid potential conflicts with auto*tools' LIBS. Reflect new
+ locations of libscorecpu*.a.
+ * Makefile.am: Remove AUTOMAKE_FILES.
+ * automake/compile.am: Replace contents with contents of
+ automake/amcompile.am.
+ * automake/amcompile.am, automake/lib.am: Remove.
+ * configure.ac, aclocal/enable-bare.m4, aclocal/enable-inlines.m4,
+ aclocal/enable-itron.m4, aclocal/enable-multiprocessing.m4,
+ aclocal/enable-networking.m4, aclocal/enable-posix.m4,
+ aclocal/enable-rtems-debug.m4, aclocal/multi.m4, aclocal/multilib.m4:
+ Use AS_HELP_STRING instead of AC_HELP_STRING (deprecated in
+ autoconf-2.59).
+ * automake/local.am: Remove clean-local, depend-gcc.
+ * itron/Makefile.am, posix/Makefile.am, score/Makefile.am: Include
+ compile.am, again.
+ * score/macros/rtems/score/README: Remove (Redundant with macros/README).
+ * sapi/Makefile.am, rtems/Makefile.am: Include compile.am, again.
+ * libmisc/Makefile.am: Include compile.am again. Misc fixes.
+ * librpc/Makefile.am: Include compile.am, again. Put man-pages into
+ EXTRA_DIST to work around automake not distributing conditionally
+ installed *_MANS. Distribute include/rpcsvc.
+ * libblock/Makefile.am: Include compile.am, again. Eliminate C_FILES.
+ Reformat.
+ * libfs/Makefile.am: Include compile.am, again. Reformat/Cleanup.
+ * libcsupport/Makefile.am: Reformat, add UNUSED_FILES.
+ * libcsupport/Makefile.am: Include compile.am, again. Eliminate
+ DOC_FILES.
+ * libnetworking/Makefile.am: Include compile.am, again. Cleanup.
+
+2004-01-08 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * wrapup/Makefile.am: Cosmetics.
+ * aclocal/enable-networking.m4: Don't AC_SUBST(RTEMS_HAS_NETWORKING).
+ * aclocal/check-networking.m4: Don't AC_SUBST(HAS_NETWORKING).
+ * automake/amcompile.am: Remove $(ARCH).
+ * wrapup/Makefile.am: Add $(ARCH). Remove compile.am, lib.am. Include
+ amcompile.am.
+ * wrapup/Makefile.am: Use ../*/*$(LIB_VARIANT).a instead of
+ $(ARCH)/lib*.a.
+ * wrapup/Makefile.am: Reflect changes to libblock/Makefile.am. Reflect
+ changes to libcsupport/Makefile.am.
+ * itron/Makefile.am: Add libs to CLEANFILES. Set lib*_g_a_SOURCES =
+ lib*_a_SOURCES.
+ * itron/Makefile.am: Build libitron$(LIB_VARIANT).a instead of
+ $(ARCH)/libitron.a.
+ * posix/Makefile.am: Add libs to CLEANFILES Set lib*_g_a_SOURCES =
+ lib*_a_SOURCES.
+ * posix/Makefile.am: Build libposix$(LIB_VARIANT).a instead of
+ $(ARCH)/libposix.a.
+ * score/Makefile.am: Add libs to CLEANFILES Set lib*_g_a_SOURCES =
+ lib*_a_SOURCES.
+ * score/Makefile.am: Build libscore$(LIB_VARIANT).a instead of
+ $(ARCH)/libscore.a.
+ * sapi/Makefile.am: Add libs to CLEANFILES Set lib*_g_a_SOURCES =
+ lib*_a_SOURCES.
+ * sapi/Makefile.am: Build libsapi$(LIB_VARIANT).a instead of
+ $(ARCH)/libsapi.a.
+ * rtems/Makefile.am: Add libs to CLEANFILES Set lib*_g_a_SOURCES =
+ lib*_a_SOURCES.
+ * rtems/Makefile.am: Build librtems$(LIB_VARIANT).a instead of
+ $(ARCH)/librtems.a.
+ * libmisc/Makefile.am: Add libs to CLEANFILES Set lib*_g_a_SOURCES =
+ lib*_a_SOURCES.
+ * libmisc/Makefile.am: Build lib*$(LIB_VARIANT).a instead of
+ $(ARCH)/lib*.a.
+ * librpc/Makefile.am: Add libs to CLEANFILES. Set lib*_g_a_SOURCES =
+ lib*_a_SOURCES.
+ * librpc/Makefile.am: Build lib*$(LIB_VARIANT).a instead of
+ $(ARCH)/lib*.a.
+ * libblock/Makefile.am: Add libs to CLEANFILES Set lib*_g_a_SOURCES =
+ lib*_a_SOURCES.
+ * libblock/include/rtems/blkdev.h,
+ libblock/include/rtems/ide_part_table.h, libblock/src/bdbuf.c,
+ libblock/src/ide_part_table.c, libblock/src/ramdisk.c: Switch to using
+ c99 fixed size types instead of RTEMS-types.
+ * libblock/Makefile.am: Build libblock$(LIB_VARIANT).a instead of
+ $(ARCH)/libblock.a.
+ * libfs/Makefile.am: Add libs to CLEANFILES. Set lib*_g_a_SOURCES =
+ lib*_a_SOURCES.
+ * libfs/Makefile.am: Build lib*$(LIB_VARIANT).a instead of
+ $(ARCH)/lib*.a.
+ * libcsupport/Makefile.am: Add libs to CLEANFILES Set lib*_g_a_SOURCES =
+ lib*_a_SOURCES.
+ * libcsupport/Makefile.am: Build libcsupport$(LIB_VARIANT).a instead of
+ $(ARCH)/libcsupport.a.
+ * libnetworking/Makefile.am: Remove *C_FILES.
+ * libnetworking/Makefile.am: Add libs to CLEANFILES Set lib*_g_a_SOURCES
+ = lib*_a_SOURCES.
+ * libnetworking/Makefile.am: Build lib*$(LIB_VARIANT).a instead of
+ $(ARCH)/lib*.a.
+
+2004-01-07 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * wrapup/Makefile.am: Reflect changes to library Makefile.ams.
+ * automake/amcompile.am: New.
+ * configure.ac: Add subdir-objects, AM_PROG_CC_C_O.
+ * itron/Makefile.am, posix/Makefile.am, score/Makefile.am,
+ sapi/Makefile.am, rtems/Makefile.am, libmisc/Makefile.am,
+ librpc/Makefile.am, libblock/Makefile.am, libfs/Makefile.am,
+ libcsupport/Makefile.am, libnetworking/Makefile.am: Build library using
+ EXTRA_LIBRARIES and automake rules.
+
+2004-01-07 Joel Sherrill <joel@OARcorp.com>
+
+ * aclocal/rtems-cpu-subdirs.m4, score/cpu/Makefile.am: mips64orion port
+ removed as mips port more completely covers the MIPS family.
+ * score/cpu/mips64orion/.cvsignore, score/cpu/mips64orion/ChangeLog,
+ score/cpu/mips64orion/Makefile.am, score/cpu/mips64orion/asm.h,
+ score/cpu/mips64orion/configure.ac, score/cpu/mips64orion/cpu.c,
+ score/cpu/mips64orion/cpu_asm.S, score/cpu/mips64orion/cpu_asm.h,
+ score/cpu/mips64orion/idtcpu.h, score/cpu/mips64orion/idtmon.h,
+ score/cpu/mips64orion/iregdef.h, score/cpu/mips64orion/rtems/.cvsignore,
+ score/cpu/mips64orion/rtems/score/.cvsignore,
+ score/cpu/mips64orion/rtems/score/cpu.h,
+ score/cpu/mips64orion/rtems/score/mips64orion.h,
+ score/cpu/mips64orion/rtems/score/types.h: Removed.
+ * libnetworking/rtems/rtems_bsdnet_internal.h: Include rtems/cdefs.h so
+ things compile.
+
+2003-12-17 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * automake/compile.am: Use $(mkdir_p) instead of $(mkinstalldirs).
+
+2003-12-17 Joel Sherrill <joel@OARcorp.com>
+
+ * aclocal/version.m4: Updated to rtems-20031217-test.
+
+2003-12-16 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ PR 533/bsps
+ * score/startup/linkcmds: Update linkcmds for gcc 3.3.2.
+
+2003-12-16 Joel Sherrill <joel@OARcorp.com>
+
+ PR 543/rtems
+ * score/src/threadclose.c: Make the task delete extension run outside a
+ dispatch disabled critical section so extensions can free resources.
+ PR 542/filesystem
+ * libcsupport/include/rtems/libio_.h: Add rtems_libio_iop_to_descriptor
+ macro to convert iop to the corresponding integer file descriptor.
+
+2003-12-13 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * aclocal/env-rtemscpu.m4: Remove stray '/' in PROJECT_LIB.
+ * wrapup/Makefile.am: Remove duplicate $(PROJECT_LIB) rule.
+ * aclocal/env-rtemscpu.m4: Add PROJECT_LIB.
+ * wrapup/Makefile.am: Use $(PROJECT_LIB) instead of
+ ${PROJECT_RELEASE}/lib.
+
+2003-12-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am, wrapup/Makefile.am: Use mkdir_p. Remove dirs from
+ PRE/TMPINSTALL_FILES.
+ * wrapup/Makefile.am: Reworked.
+ * aclocal/lead-dot.m4: Remove (Use the version in automake-1.8).
+ * automake/lib.am: Remove $(project_libdir)$(MULTISUBDIR).
+ * aclocal/env-rtemscpu.m4: Reflect new definition of project_lib.
+ * Makefile.am: Remove BUILT_SOURCES.
+ * configure.ac: Require automake >= 1.8, autoconf >= 2.59.
+ * itron/Makefile.am, posix/Makefile.am, score/Makefile.am,
+ sapi/Makefile.am, rtems/Makefile.am, libmisc/Makefile.am,
+ librpc/Makefile.am, libblock/Makefile.am, libfs/Makefile.am,
+ libcsupport/Makefile.am: Use mkdir_p. Remove dirs from
+ PRE/TMPINSTALL_FILES.
+ * libcsupport/Makefile.am: Remove BUILT_SOURCES.
+ * libnetworking/Makefile.am: Use mkdir_p. Remove dirs from
+ PRE/TMPINSTALL_FILES.
+
+2003-12-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libmisc/Makefile.am: Cosmetics.
+
+2003-12-11 Joel Sherrill <joel@OARcorp.com>
+
+ PR 540/rtems_misc
+ * libmisc/cpuuse/cpuuse.c, libmisc/rtmonuse/rtmonuse.c: Correct object
+ name printing.
+ PR 531/rtems_misc
+ * libmisc/rtmonuse/rtmonuse.c, libmisc/stackchk/check.c: Correct
+ indexing.
+
+2003-12-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libblock/src/ata.c: Remove.
+
+2003-11-30 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * automake/compile.am: Add $(ARCH)/$(dirstamp) rules.
+ * wrapup/Makefile.am: Reflect $(dirstamp) changes.
+ * Makefile.am: Add $(dirstamp) to preinstallation rules.
+ * aclocal/lead-dot.m4: New (from automake-1.7f).
+ * aclocal/rtems-top.m4: Require AM_SET_LEADING_DOT. Add
+ AC_SUBST(dirstamp).
+ * itron/Makefile.am: Add $(dirstamp) to compilation rules.
+ * itron/Makefile.am: Add $(dirstamp) to preinstallation rules. Remove
+ MACROS.
+ * posix/Makefile.am: Add $(dirstamp) to compilation rules.
+ * posix/Makefile.am: Add $(dirstamp) to preinstallation rules. Remove
+ MACROS.
+ * score/Makefile.am: Add $(dirstamp) to compilation rules.
+ * score/Makefile.am: Add $(dirstamp) to preinstallation rules. Remove
+ MACROS.
+ * sapi/Makefile.am: Add $(dirstamp) to compilation rules. Add
+ AM_CPPFLAGS += -I$(top_builddir).
+ * sapi/Makefile.am: Add $(dirstamp) to preinstallation rules. Remove
+ MACROS.
+ * rtems/Makefile.am: Add $(dirstamp) to compilation rules. Add
+ AM_CPPFLAGS += -I$(top_builddir).
+ * rtems/Makefile.am: Add $(dirstamp) to preinstallation rules. Remove
+ MACROS.
+ * libmisc/Makefile.am: Add $(dirstamp) to compilation rules. Fix misc.
+ typos.
+ * libmisc/Makefile.am: Add $(dirstamp) to preinstallation rules.
+ * librpc/Makefile.am: Add $(dirstamp) to compilation rules.
+ * librpc/Makefile.am: Add $(dirstamp) to preinstallation rules.
+ * libblock/Makefile.am: Add $(dirstamp) to compilation rules.
+ * libblock/Makefile.am: Add $(dirstamp) to preinstallation rules.
+ * libfs/Makefile.am: Add $(dirstamp) to compilation rules.
+ * libfs/Makefile.am: Add $(dirstamp) to preinstallation rules.
+ * libcsupport/Makefile.am: Add $(dirstamp) to compilation rules.
+ * libcsupport/Makefile.am: Add $(dirstamp) to preinstallation rules.
+ * libnetworking/Makefile.am: Add $(dirstamp) to compilation rules.
+ * libnetworking/Makefile.am: Fix libc_OBJS.
+ * libnetworking/Makefile.am: Add $(dirstamp) to preinstallation rules.
+ Restore libc/$(ARCH)/lib.a.
+
+2003-11-28 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Reflect having removed libnetworking/libc/Makefile.am,
+ libnetworking/lib/Makefile.am.
+ * configure.ac: Reflect changes to libmisc/*.
+ * libmisc/Makefile.am: Reformat.
+ * libmisc/capture/Makefile.am, libmisc/cpuuse/Makefile.am,
+ libmisc/devnull/Makefile.am, libmisc/dummy/Makefile.am,
+ libmisc/dumpbuf/Makefile.am, libmisc/fsmount/Makefile.am,
+ libmisc/monitor/Makefile.am, libmisc/mw-fb/Makefile.am,
+ libmisc/rtmonuse/Makefile.am, libmisc/serdbg/Makefile.am,
+ libmisc/shell/Makefile.am, libmisc/stackchk/Makefile.am,
+ libmisc/untar/Makefile.am: Remove.
+ * libmisc/Makefile.am: Merge-in the Makefile.ams above.
+ * libnetworking/libc/Makefile.am, libnetworking/lib/Makefile.am: Remove.
+ * libnetworking/Makefile.am: Merge-in the Makefile.ams above.
+
+2003-11-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * wrapup/Makefile.am: Merge-in former libmisc/wrapup/Makefile.am.
+ * configure.ac: Reflect changes to libfs Makefile.ams. Remove
+ libmisc/wrapup/Makefile.
+ * configure.ac: Use here-documents to generate cpuopts.tmp. Various
+ fixes and changes to argument processing. Reflect changes to librpc
+ Makefile.ams.
+ * acinclude.m4: Use here-documents to generate cpuopts.tmp.
+ * aclocal/check-itron.m4: Remove HAS_IRON_API.
+ * aclocal/check-multiprocessing.m4: Remove HAS_MP.
+ * aclocal/check-posix.m4: Remove HAS_POSIX_API.
+ * libmisc/wrapup/Makefile.am, libmisc/wrapup/.cvsignore: Remove.
+ * libmisc/Makefile.am: Reflect changes above.
+ * librpc/src/rpc/Makefile.am, librpc/src/xdr/Makefile.am,
+ librpc/src/Makefile.am: Removed.
+ * librpc/Makefile.am: Merge-in src/rpc/Makefile.am, src/xdr/Makefile.am,
+ src/Makefile.am. Various fixes. Reformat.
+ * librpc/include/rpc/rpc.hinclude/rpc/rpc.h: Rename struct
+ rtems_rpc_task_variables into struct _rtems_rpc_task_variables (Avoid
+ symbol conflict between struct and variable). struct
+ _rtems_rpc_task_variables *rtems_rpc_task_variables; Reflect changes
+ above.
+ * librpc/src/rpc/clnt_perror.c, librpc/src/rpc/clnt_raw.c,
+ librpc/src/rpc/clnt_simple.c, librpc/src/rpc/rpcdname.c,
+ librpc/src/rpc/rtems_rpc.c, librpc/src/rpc/svc.c, librpc/
+ src/rpc/svc_auth.c, librpc/src/rpc/svc_raw.c,
+ librpc/src/rpc/svc_simple.c: Reflect changes above.
+ * libfs/Makefile.am: Merge-in src/Makefile.am, src/imfs/Makefile.am,
+ src/dosfs/Makefile.am.
+ * libfs/src/Makefile.am, libfs/src/imfs/Makefile.am,
+ libfs/src/dosfs/Makefile.am: Removed.
+
+2003-11-26 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * aclocal/canonicalize-tools.m4, aclocal/check-itron.m4,
+ aclocal/check-multiprocessing.m4, aclocal/check-newlib.m4,
+ aclocal/check-posix.m4, aclocal/check-rtems-debug.m4,
+ aclocal/check-tool.m4, aclocal/enable-bare.m4,
+ aclocal/enable-inlines.m4, aclocal/enable-itron.m4,
+ aclocal/enable-multiprocessing.m4, aclocal/enable-networking.m4,
+ aclocal/enable-posix.m4, aclocal/enable-rtems-debug.m4,
+ aclocal/env-rtemscpu.m4, aclocal/gcc-isystem.m4, aclocal/gcc-pipe.m4,
+ aclocal/multi.m4, aclocal/multilib.m4, aclocal/prog-cc.m4,
+ aclocal/rtems-top.m4, aclocal/sysv-ipc.m4: Fix underquoting to silence
+ automake-1.8.
+
+2003-11-26 Joel Sherrill <joel@OARcorp.com>
+
+ PR 524/filesystem
+ * libcsupport/src/newlibc.c: Address 1K buffer leak from incomplete
+ cleanup of newlib reentrancy handler.
+ PR 523/filesystem
+ * libcsupport/src/malloc.c: Make malloc family safer for use from ISRs
+ and dispatching critical sections. If in a critical section while doing
+ a free(), then the free is deferred until the next malloc() attempt.
+
+2003-11-25 Joel Sherrill <joel@OARcorp.com>
+
+ PR 526/rtems
+ * score/src/threadcreateidle.c: Idle task name should be a string and
+ PR484 broke this.
+
+2003-11-25 Jennifer Averett <jennifer@OARcorp.com>
+
+ PR 519/filesystem
+ * libcsupport/include/rtems/libio_.h, libcsupport/src/eval.c,
+ libcsupport/src/rmdir.c, libcsupport/src/unlink.c: Check write
+ permissions in parent directory for file or directory delete.
+
+2003-11-24 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use RTEMS_INLINES instead of USE_INLINES. Elimimate
+ INLINESdir.
+ * aclocal/enable-inlines.m4: Ditto. Remove RTEMS_USE_MACROS.
+ * .cvsignore: Add config.h.in.
+
+2003-11-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Make RTEMS_DEBUG an RTEMS_CPUOPT.
+ PR 525/rtems
+ * score/include/rtems/system.h: Use RTEMS_INLINES instead of USE_INLINES.
+ * score/include/rtems/score/chain.h, score/include/rtems/score/thread.h,
+ score/src/chain.c, score/src/coremutexseize.c, score/src/threadget.c:
+ Ditto.
+ * score/Makefile.am: Don't use gmake to preinstall.
+ * sapi/Makefile.am: Reworked.
+
+2003-11-22 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * wrapup/Makefile.am: Reflect having removed libnetworking/wrapup.
+ * configure.ac: Ditto.
+ * itron/Makefile.am, posix/Makefile.am, rtems/Makefile.am,
+ libblock/Makefile.am: Reworked.
+ * libcsupport/include/rtems/cdefs.h: Use _RTEMS_CDEFS_H guards.
+ * libcsupport/include/rtems/cdefs.h: New.
+ * libcsupport/Makefile.am: Completely reworked.
+ * libnetworking/rtems/rtems_bsdnet_internal.h: Include rtems/cdefs.h
+ instead of sys/cdefs.h (Nonportable).
+ * libnetworking/wrapup/Makefile.am: Removed.
+ * libnetworking/Makefile.am: Reworked.
+
+2003-11-20 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * acinclude.m4: New.
+ * configure.ac: Don't use AUTOHEADER to generate cpuopts.h. Add local
+ autoheader config.h.
+ * aclocal/canonical-target-name.m4: Require AC_CANONICAL_HOST.
+ * aclocal/enable-inlines.m4: Remove USE_MACROS (Unused).
+ * itron/Makefile.am: Remove src/config.h. AM_CPPFLAGS +=
+ -I$(top_builddir).
+ * posix/Makefile.am: Remove src/config.h AM_CPPFLAGS +=
+ -I$(top_builddir).
+ * libmisc/capture/Makefile.am, libmisc/cpuuse/Makefile.am,
+ libmisc/devnull/Makefile.am, libmisc/dummy/Makefile.am,
+ libmisc/dumpbuf/Makefile.am, libmisc/monitor/Makefile.am,
+ libmisc/mw-fb/Makefile.am, libmisc/rtmonuse/Makefile.am,
+ libmisc/serdbg/Makefile.am, libmisc/shell/Makefile.am,
+ libmisc/stackchk/Makefile.am, libmisc/untar/Makefile.am: Remove
+ config.h. AM_CPPFLAGS += -I$(top_builddir).
+ * libblock/Makefile.am: AM_CPPFLAGS += -I$(top_builddir). Use
+ AM_CPPFLAGS instead of AM_CFLAGS.
+ * libblock/src/ata.c: Include config.h.
+ * libblock/src/bdbuf.c, libblock/src/blkdev.c, libblock/src/diskdevs.c,
+ libblock/src/ide_part_table.c, libblock/src/ramdisk.c: Ditto.
+ * libfs/src/dosfs/Makefile.am, libfs/src/imfs/Makefile.am: Remove
+ config.h AM_CPPFLAGS += -I$(top_builddir).
+ * itron/src/config.h, posix/src/config.h, libmisc/capture/config.h,
+ libmisc/cpuuse/config.h, libmisc/devnull/config.h,
+ libmisc/dummy/config.h, libmisc/dumpbuf/config.h,
+ libmisc/monitor/config.h, libmisc/mw-fb/config.h,
+ libmisc/rtmonuse/config.h, libmisc/serdbg/config.h,
+ libmisc/stackchk/config.h, libmisc/shell/config.h,
+ libmisc/untar/config.h, libfs/src/dosfs/config.h,
+ libfs/src/imfs/config.h, libcsupport/src/config.h: Remove.
+ * libcsupport/src/Makefile.am: AM_CPPFLAGS += -I$(top_builddir).
+
+2003-11-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libfs/Makefile.am: Cosmetics.
+
+2003-10-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/src/regiongetsegment.c: Remove unneccessary typecast in
+ assignment to thread->Wait.return_argment.
+
+2003-10-22 Thomas Doerfler <Thomas.Doerfler@imd-systems.de>
+
+ PR 515/filesystem
+ * libfs/src/dosfs/fat_fat_operations.c: Remove commented out code.
+
+2003-10-22 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ PR 509/filesystem
+ * libfs/src/dosfs/fat.c: _fat_block_read and _fat_block_write return
+ error codes instead of -1 in case of errors, as they are supposed to do
+ according to the comments documenting these functions.
+
+2003-10-22 Joel Sherrill <joel@OARcorp.com>
+
+ PR 512/core
+ * rtems/src/tasks.c, rtems/src/taskvariabledelete.c: Run task variable
+ destructor when task variable is deleted. Also some style cleanup.
+ PR 440/filesystem
+ * libfs/src/dosfs/fat_fat_operations.c: Improve write speed with FAT12
+ and FAT16 filesystems. Previously merged on 4.6 branch.
+ * libfs/ChangeLog: Correct line length.
+ PR 511/filesystem
+ * libcsupport/src/malloc.c: Add deferred free and protect against C
+ Program Heap operations while in a dispatch disable critical section or
+ ISR.
+
+2003-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * aclocal/check-posix.m4: Add m4-quotes. Require
+ RTEMS_CANONICAL_TARGET_CPU instead of RTEMS_CHECK_CPU.
+ * aclocal/canonical-host.m4: Remove.
+ * configure.ac: Remove RTEMS_CANONICAL_HOST.
+ * aclocal/sysv-ipc.m4: Remove reference to RTEMS_CANONICAL_HOST.
+ * aclocal/canonical-target-name.m4: Use AC_CANONICAL_HOST instead of
+ AC_CANONICAL_TARGET. Use $host instead of $target.
+ * aclocal/check-multiprocessing.m4: Add m4-quotes. Remove
+ RTEMS_CHECK_CPU.
+ * aclocal/check-itron.m4, aclocal/check-networking.m4: Add m4-quotes.
+ Require RTEMS_CANONICAL_TARGET_CPU instead of RTEMS_CHECK_CPU.
+ * aclocal/check-cpu.m4: Remove.
+ * aclocal/canonical-target-name.m4: Add m4-quotes.
+ * configure.ac: Merge-in former aclocal/check-cpu.m4.
+ * posix/src/cancelrun.c, posix/src/pthreadexit.c,
+ posix/src/pthreadjoin.c, posix/ src/sigtimedwait.c: Remove unnecessary
+ typecasts in assignments to thread->Wait.return_argument.
+ * score/src/coremsgseize.c, score/src/coremsgsubmit.c: Remove
+ unnecessary typecasts in assignments to thread->Wait.return_argument.
+ * libmisc/capture/capture-cli.c: Reflect new rtems_monitor_command_arg_t.
+ * librpc/src/rpc/Makefile.am, librpc/src/xdr/Makefile.am: Remove __P
+ from AM_CPPFLAGS. Rely on sys/cdefs.h providing it.
+ * libfs/src/dosfs/Makefile.am: noinst_HEADERS += fat.h.
+ * libfs/src/dosfs/msdos_file.c (msdos_file_read,
+ libfs/msdos_file_write): Use '0' as initial value for ret instead of
+ RC_OK.
+ * libfs/src/dosfs/msdos_conv.c: Remove isupper, islower, toupper,
+ tolower (Unused).
+
+2003-10-17 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Check for sys/cdefs.h.
+ * aclocal/env-rtems-cpu.m4: Add project_includedir. Deprecate
+ PROJECT_INCLUDE. Change project_includedir to $(PROJECT_ROOT)/include
+ for multilibs.
+
+2003-10-13 Joel Sherrill <joel@OARcorp.com>
+
+ * posix/src/cleanuppop.c, posix/src/cleanuppush.c: Protect use of
+ _Workspace_Allocate and _Workspec_Free.
+
+2003-10-02 Phil Torre <ptorre@zetron.com>
+
+ PR 504/rtems
+ * score/include/rtems/score/coremutex.h: Add fatal error check for a
+ task blocking on a mutex when thread dispatching is disabled.
+ PR 504/rtems
+ * libcsupport/src/newlibc.c: Fix memory allocation of libc extension so
+ it is dispatch disabled safe See PR for detailed explanation.
+
+2003-09-26 Till Strauman <strauman@slac.stanford.edu>
+
+ PR 498/rtems
+ * libcsupport/src/printk.c: RTEMS printk() does not support the %i
+ format which is used by a lot of driver/BSP etc. code. The trivial patch
+ allows %i/%I as an alias for %d/%D.
+
+2003-09-26 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ PR 495/rtems_misc
+ * libmisc/capture/capture-cli.c, libmisc/monitor/mon-command.c,
+ libmisc/monitor/mon-config.c, libmisc/monitor/mon-monitor.c,
+ libmisc/monitor/mon-object.c, libmisc/monitor/mon-symbols.c,
+ libmisc/monitor/monitor.h, libmisc/shell/cmds.c: Move to making libmisc
+ 16/32 bit clean.
+
+2003-09-26 Joel Sherrill <joel@OARcorp.com>
+
+ * score/cpu/hppa1.1/.cvsignore, score/cpu/hppa1.1/ChangeLog,
+ score/cpu/hppa1.1/Makefile.am, score/cpu/hppa1.1/configure.ac,
+ score/cpu/hppa1.1/cpu.c, score/cpu/hppa1.1/cpu_asm.S,
+ score/cpu/hppa1.1/rtems/.cvsignore,
+ score/cpu/hppa1.1/rtems/score/.cvsignore,
+ score/cpu/hppa1.1/rtems/score/cpu.h,
+ score/cpu/hppa1.1/rtems/score/cpu_asm.h,
+ score/cpu/hppa1.1/rtems/score/hppa.h,
+ score/cpu/hppa1.1/rtems/score/types.h: Removed.
+ PR 492/filesystem
+ * libfs/src/dosfs/fat_file.c: Fix inconsistent types in va_args call.
+
+2003-09-24 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am, librpc/Makefile.am: Merge-in include/Makefile.am.
+ * include/Makefile.am, librpc/include/Makefile.am: Remove.
+ * configure.ac: Reflect having removed include/Makefile.am and
+ librpc/include/Makefile.am.
+
+2003-09-22 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libmisc/monitor/monitor.h: Add rtems_monitor_commands[] (Illegally
+ applied by shell/). Remove ifdef(__mips64) (Make broken code visible
+ again).
+ * libmisc/monitor/mon-command.c: Add several ifndef RTEMS_UNIX to avoid
+ warnings.
+ * libmisc/monitor/mon-monitor.c: Remove RTEMS_CPU_HAS_16_BIT_ADDRESSES
+ (Make broken code visible again).
+ * libmisc/shell/cmds.c: Remove local decls of rtems_monitor_commands[].
+
+2003-09-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libmisc/monitor/monitor.h: Remove STREQ, STNEQ (pollute namespace),
+ RTEMS_MONITOR_PROMPT (pollutes namespace, useless).
+ * libmisc/monitor/mon-command.c: Add RTEMS_MONITOR_PROMPT.
+ * libmisc/monitor/mon-monitor.c: Apply private version of STREQ.
+ * libmisc/monitor/symbols.h: Convert to private header.
+ * libmisc/monitor/monitor.h: Don't include symbols.h. Add forward decls.
+ for symbols from symbols.h.
+ * libmisc/monitor/Makefile.am: Don't install symbols.h.
+ * libmisc/monitor/mon-symbols.c: Include "symbols.h".
+
+2003-09-15 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ PR 489/rtems
+ * score/include/rtems/score/thread.h: Change struct
+ Thread_Control_struct.libc_reent to using struct _reent*.
+ * score/inline/rtems/score/thread.inl: Reflect change above.
+ PR 489/rtems
+ * libcsupport/src/newlibc.c: Reflect struct
+ Thread_Control_struct.libc_reent having changed from void * to struct
+ _reent*.
+
+2003-09-15 Jay Monkman <jtm@smoothsmoothie.com>
+
+ PR 482/networking
+ * libnetworking/rtems/rtems_glue.c: Network interfaces can't be taken
+ down.
+ PR 481/networking
+ * libnetworking/net/ethernet.h, libnetworking/net/if_arp.h,
+ libnetworking/netinet/if_ether.h: Network structs should be packed.
+
+2003-09-13 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libcsupport/src/sync.c: Don't undef __STRICT_ANSI__. Use struct _reent
+ (struct reent doesn't exist).
+ PR 486/rtems
+ * libcsupport/src/newlib.c: Unconditionally include <stdio.h>.
+
+2003-09-11 Joel Sherrill <joel@OARcorp.com>
+
+ PR 488/rtems
+ * rtems/src/taskcreate.c, rtems/src/tasks.c: Ensure notepads are zeroed.
+
+2003-09-09 Ralf Corsepius <ralf_corsepius@rtems.com>
+
+ PR 487/filesystem
+ * libfs/src/dosfs/fat_file.c: Correct typing per gcc 3.3 warnings.
+
+2003-09-08 Mikec Ivica <mikici@acm.org>
+
+ * score/inline/rtems/score/userext.inl,
+ score/macros/rtems/score/userext.inl: Add missing cast.
+
+2003-09-08 Derick Hammond <derick@perkinstechnologies.com.au>
+
+ PR 484/rtems
+ * score/src/threadcreateidle.c: Idle task name was initialized
+ incorrectly.
+
+2003-09-04 Joel Sherrill <joel@OARcorp.com>
+
+ * include/rtems/bspIo.h, include/rtems/fs.h, include/rtems/userenv.h,
+ itron/include/itron.h, itron/include/itronsys/eventflags.h,
+ itron/include/itronsys/fmempool.h, itron/include/itronsys/intr.h,
+ itron/include/itronsys/mbox.h, itron/include/itronsys/msgbuffer.h,
+ itron/include/itronsys/network.h, itron/include/itronsys/port.h,
+ itron/include/itronsys/semaphore.h, itron/include/itronsys/status.h,
+ itron/include/itronsys/sysmgmt.h, itron/include/itronsys/task.h,
+ itron/include/itronsys/time.h, itron/include/itronsys/types.h,
+ itron/include/itronsys/vmempool.h, itron/include/rtems/itron/config.h,
+ itron/include/rtems/itron/eventflags.h,
+ itron/include/rtems/itron/fmempool.h, itron/include/rtems/itron/intr.h,
+ itron/include/rtems/itron/itronapi.h, itron/include/rtems/itron/mbox.h,
+ itron/include/rtems/itron/msgbuffer.h,
+ itron/include/rtems/itron/network.h, itron/include/rtems/itron/object.h,
+ itron/include/rtems/itron/port.h, itron/include/rtems/itron/semaphore.h,
+ itron/include/rtems/itron/sysmgmt.h, itron/include/rtems/itron/task.h,
+ itron/include/rtems/itron/time.h, itron/include/rtems/itron/vmempool.h,
+ itron/inline/rtems/itron/eventflags.inl,
+ itron/inline/rtems/itron/fmempool.inl,
+ itron/inline/rtems/itron/intr.inl, itron/inline/rtems/itron/mbox.inl,
+ itron/inline/rtems/itron/msgbuffer.inl,
+ itron/inline/rtems/itron/network.inl, itron/inline/rtems/itron/port.inl,
+ itron/inline/rtems/itron/semaphore.inl,
+ itron/inline/rtems/itron/sysmgmt.inl, itron/inline/rtems/itron/task.inl,
+ itron/inline/rtems/itron/time.inl,
+ itron/inline/rtems/itron/vmempool.inl,
+ itron/macros/rtems/itron/eventflags.inl,
+ itron/macros/rtems/itron/fmempool.inl,
+ itron/macros/rtems/itron/intr.inl, itron/macros/rtems/itron/mbox.inl,
+ itron/macros/rtems/itron/msgbuffer.inl,
+ itron/macros/rtems/itron/network.inl, itron/macros/rtems/itron/port.inl,
+ itron/macros/rtems/itron/semaphore.inl,
+ itron/macros/rtems/itron/sysmgmt.inl, itron/macros/rtems/itron/task.inl,
+ itron/macros/rtems/itron/time.inl,
+ itron/macros/rtems/itron/vmempool.inl, itron/src/can_wup.c,
+ itron/src/chg_pri.c, itron/src/cre_mbf.c, itron/src/cre_mbx.c,
+ itron/src/cre_sem.c, itron/src/cre_tsk.c, itron/src/del_mbf.c,
+ itron/src/del_mbx.c, itron/src/del_sem.c, itron/src/del_tsk.c,
+ itron/src/dis_dsp.c, itron/src/ena_dsp.c, itron/src/eventflags.c,
+ itron/src/exd_tsk.c, itron/src/ext_tsk.c, itron/src/fmempool.c,
+ itron/src/frsm_tsk.c, itron/src/get_tid.c, itron/src/itronintr.c,
+ itron/src/itronsem.c, itron/src/itrontime.c, itron/src/mbox.c,
+ itron/src/mboxtranslatereturncode.c, itron/src/msgbuffer.c,
+ itron/src/msgbuffertranslatereturncode.c, itron/src/network.c,
+ itron/src/port.c, itron/src/prcv_mbf.c, itron/src/prcv_mbx.c,
+ itron/src/preq_sem.c, itron/src/psnd_mbf.c, itron/src/rcv_mbf.c,
+ itron/src/rcv_mbx.c, itron/src/ref_mbf.c, itron/src/ref_mbx.c,
+ itron/src/ref_sem.c, itron/src/ref_tsk.c, itron/src/rel_wai.c,
+ itron/src/rot_rdq.c, itron/src/rsm_tsk.c, itron/src/sig_sem.c,
+ itron/src/slp_tsk.c, itron/src/snd_mbf.c, itron/src/snd_mbx.c,
+ itron/src/sta_tsk.c, itron/src/sus_tsk.c, itron/src/sysmgmt.c,
+ itron/src/task.c, itron/src/ter_tsk.c, itron/src/trcv_mbf.c,
+ itron/src/trcv_mbx.c, itron/src/tslp_tsk.c, itron/src/tsnd_mbf.c,
+ itron/src/twai_sem.c, itron/src/vmempool.c, itron/src/wai_sem.c,
+ itron/src/wup_tsk.c, posix/include/rtems/posix/cond.h,
+ posix/include/rtems/posix/condmp.h, posix/include/rtems/posix/config.h,
+ posix/include/rtems/posix/intr.h, posix/include/rtems/posix/key.h,
+ posix/include/rtems/posix/mqueue.h,
+ posix/include/rtems/posix/mqueuemp.h, posix/include/rtems/posix/mutex.h,
+ posix/include/rtems/posix/mutexmp.h,
+ posix/include/rtems/posix/posixapi.h,
+ posix/include/rtems/posix/pthread.h,
+ posix/include/rtems/posix/pthreadmp.h,
+ posix/include/rtems/posix/ptimer.h,
+ posix/include/rtems/posix/semaphore.h,
+ posix/include/rtems/posix/semaphoremp.h,
+ posix/inline/rtems/posix/cond.inl, posix/inline/rtems/posix/intr.inl,
+ posix/inline/rtems/posix/key.inl, posix/inline/rtems/posix/mqueue.inl,
+ posix/inline/rtems/posix/mutex.inl,
+ posix/inline/rtems/posix/pthread.inl,
+ posix/inline/rtems/posix/semaphore.inl,
+ posix/inline/rtems/posix/timer.inl, posix/macros/rtems/posix/cond.inl,
+ posix/macros/rtems/posix/intr.inl, posix/macros/rtems/posix/key.inl,
+ posix/macros/rtems/posix/mqueue.inl, posix/macros/rtems/posix/mutex.inl,
+ posix/macros/rtems/posix/pthread.inl,
+ posix/macros/rtems/posix/semaphore.inl,
+ posix/macros/rtems/posix/timer.inl, posix/src/alarm.c, posix/src/kill.c,
+ posix/src/killinfo.c, posix/src/mqueuetranslatereturncode.c,
+ posix/src/pause.c, posix/src/pthreadattrdestroy.c,
+ posix/src/pthreadattrgetdetachstate.c,
+ posix/src/pthreadattrgetinheritsched.c,
+ posix/src/pthreadattrgetschedparam.c,
+ posix/src/pthreadattrgetschedpolicy.c, posix/src/pthreadattrgetscope.c,
+ posix/src/pthreadattrgetstackaddr.c,
+ posix/src/pthreadattrgetstacksize.c, posix/src/pthreadattrinit.c,
+ posix/src/pthreadattrsetdetachstate.c,
+ posix/src/pthreadattrsetinheritsched.c,
+ posix/src/pthreadattrsetschedparam.c,
+ posix/src/pthreadattrsetschedpolicy.c, posix/src/pthreadattrsetscope.c,
+ posix/src/pthreadattrsetstackaddr.c,
+ posix/src/pthreadattrsetstacksize.c, posix/src/pthreadcreate.c,
+ posix/src/pthreaddetach.c, posix/src/pthreadequal.c,
+ posix/src/pthreadexit.c, posix/src/pthreadgetcpuclockid.c,
+ posix/src/pthreadgetcputime.c, posix/src/pthreadgetschedparam.c,
+ posix/src/pthreadjoin.c, posix/src/pthreadkill.c,
+ posix/src/pthreadonce.c, posix/src/pthreadself.c,
+ posix/src/pthreadsetcputime.c, posix/src/pthreadsetschedparam.c,
+ posix/src/pthreadsigmask.c, posix/src/sigaction.c,
+ posix/src/sigaddset.c, posix/src/sigdelset.c, posix/src/sigemptyset.c,
+ posix/src/sigfillset.c, posix/src/sigismember.c, posix/src/signal_2.c,
+ posix/src/sigpending.c, posix/src/sigprocmask.c, posix/src/sigqueue.c,
+ posix/src/sigsuspend.c, posix/src/sigtimedwait.c, posix/src/sigwait.c,
+ posix/src/sigwaitinfo.c, posix/src/ualarm.c,
+ score/include/rtems/debug.h, score/include/rtems/seterr.h,
+ score/include/rtems/system.h, score/include/rtems/score/address.h,
+ score/include/rtems/score/apiext.h,
+ score/include/rtems/score/apimutex.h,
+ score/include/rtems/score/bitfield.h, score/include/rtems/score/chain.h,
+ score/include/rtems/score/context.h, score/include/rtems/score/copyrt.h,
+ score/include/rtems/score/coremsg.h,
+ score/include/rtems/score/coremutex.h,
+ score/include/rtems/score/coresem.h, score/include/rtems/score/heap.h,
+ score/include/rtems/score/interr.h, score/include/rtems/score/isr.h,
+ score/include/rtems/score/mpci.h, score/include/rtems/score/mppkt.h,
+ score/include/rtems/score/object.h,
+ score/include/rtems/score/objectmp.h,
+ score/include/rtems/score/priority.h, score/include/rtems/score/stack.h,
+ score/include/rtems/score/states.h,
+ score/include/rtems/score/sysstate.h,
+ score/include/rtems/score/thread.h,
+ score/include/rtems/score/threadmp.h,
+ score/include/rtems/score/threadq.h, score/include/rtems/score/tod.h,
+ score/include/rtems/score/tqdata.h, score/include/rtems/score/userext.h,
+ score/include/rtems/score/watchdog.h,
+ score/include/rtems/score/wkspace.h,
+ score/inline/rtems/score/address.inl,
+ score/inline/rtems/score/chain.inl,
+ score/inline/rtems/score/coremsg.inl,
+ score/inline/rtems/score/coremutex.inl,
+ score/inline/rtems/score/coresem.inl, score/inline/rtems/score/heap.inl,
+ score/inline/rtems/score/isr.inl, score/inline/rtems/score/mppkt.inl,
+ score/inline/rtems/score/object.inl,
+ score/inline/rtems/score/objectmp.inl,
+ score/inline/rtems/score/priority.inl,
+ score/inline/rtems/score/stack.inl, score/inline/rtems/score/states.inl,
+ score/inline/rtems/score/sysstate.inl,
+ score/inline/rtems/score/thread.inl,
+ score/inline/rtems/score/threadmp.inl, score/inline/rtems/score/tod.inl,
+ score/inline/rtems/score/tqdata.inl,
+ score/inline/rtems/score/userext.inl,
+ score/inline/rtems/score/watchdog.inl,
+ score/inline/rtems/score/wkspace.inl,
+ score/macros/rtems/score/address.inl,
+ score/macros/rtems/score/chain.inl,
+ score/macros/rtems/score/coremsg.inl,
+ score/macros/rtems/score/coremutex.inl,
+ score/macros/rtems/score/coresem.inl, score/macros/rtems/score/heap.inl,
+ score/macros/rtems/score/isr.inl, score/macros/rtems/score/mppkt.inl,
+ score/macros/rtems/score/object.inl,
+ score/macros/rtems/score/objectmp.inl,
+ score/macros/rtems/score/priority.inl,
+ score/macros/rtems/score/stack.inl, score/macros/rtems/score/states.inl,
+ score/macros/rtems/score/sysstate.inl,
+ score/macros/rtems/score/thread.inl,
+ score/macros/rtems/score/threadmp.inl, score/macros/rtems/score/tod.inl,
+ score/macros/rtems/score/tqdata.inl,
+ score/macros/rtems/score/userext.inl,
+ score/macros/rtems/score/watchdog.inl,
+ score/macros/rtems/score/wkspace.inl, score/src/apiext.c,
+ score/src/chain.c, score/src/coremsg.c, score/src/coremsgbroadcast.c,
+ score/src/coremsgclose.c, score/src/coremsgflush.c,
+ score/src/coremsgflushsupp.c, score/src/coremsgflushwait.c,
+ score/src/coremsginsert.c, score/src/coremsgseize.c,
+ score/src/coremsgsubmit.c, score/src/coremutex.c,
+ score/src/coremutexflush.c, score/src/coremutexseize.c,
+ score/src/coremutexsurrender.c, score/src/coresem.c,
+ score/src/coresemflush.c, score/src/coresemseize.c,
+ score/src/coresemsurrender.c, score/src/coretod.c,
+ score/src/coretodset.c, score/src/coretodtickle.c,
+ score/src/coretodtoseconds.c, score/src/coretodvalidate.c,
+ score/src/heap.c, score/src/heapallocate.c, score/src/heapextend.c,
+ score/src/heapfree.c, score/src/heapgetinfo.c,
+ score/src/heapsizeofuserarea.c, score/src/heapwalk.c,
+ score/src/interr.c, score/src/isr.c, score/src/iterateoverthreads.c,
+ score/src/mpci.c, score/src/object.c, score/src/objectallocate.c,
+ score/src/objectallocatebyindex.c, score/src/objectclearname.c,
+ score/src/objectcomparenameraw.c, score/src/objectcomparenamestring.c,
+ score/src/objectcopynameraw.c, score/src/objectcopynamestring.c,
+ score/src/objectextendinformation.c, score/src/objectfree.c,
+ score/src/objectget.c, score/src/objectgetbyindex.c,
+ score/src/objectgetisr.c, score/src/objectgetnext.c,
+ score/src/objectgetnoprotection.c, score/src/objectidtoname.c,
+ score/src/objectinitializeinformation.c, score/src/objectmp.c,
+ score/src/objectnametoid.c, score/src/objectshrinkinformation.c,
+ score/src/thread.c, score/src/threadchangepriority.c,
+ score/src/threadclearstate.c, score/src/threadclose.c,
+ score/src/threadcreateidle.c, score/src/threaddelayended.c,
+ score/src/threaddispatch.c, score/src/threadevaluatemode.c,
+ score/src/threadget.c, score/src/threadhandler.c,
+ score/src/threadidlebody.c, score/src/threadinitialize.c,
+ score/src/threadloadenv.c, score/src/threadmp.c, score/src/threadq.c,
+ score/src/threadqdequeue.c, score/src/threadqdequeuefifo.c,
+ score/src/threadqdequeuepriority.c, score/src/threadqenqueue.c,
+ score/src/threadqenqueuefifo.c, score/src/threadqenqueuepriority.c,
+ score/src/threadqextract.c, score/src/threadqextractfifo.c,
+ score/src/threadqextractpriority.c, score/src/threadqextractwithproxy.c,
+ score/src/threadqfirst.c, score/src/threadqfirstfifo.c,
+ score/src/threadqfirstpriority.c, score/src/threadqflush.c,
+ score/src/threadqtimeout.c, score/src/threadready.c,
+ score/src/threadreset.c, score/src/threadresettimeslice.c,
+ score/src/threadrestart.c, score/src/threadresume.c,
+ score/src/threadrotatequeue.c, score/src/threadsetpriority.c,
+ score/src/threadsetstate.c, score/src/threadsettransient.c,
+ score/src/threadstackallocate.c, score/src/threadstackfree.c,
+ score/src/threadstart.c, score/src/threadstartmultitasking.c,
+ score/src/threadsuspend.c, score/src/threadtickletimeslice.c,
+ score/src/threadyieldprocessor.c, score/src/userext.c,
+ score/src/watchdog.c, score/src/watchdogadjust.c,
+ score/src/watchdoginsert.c, score/src/watchdogremove.c,
+ score/src/watchdogtickle.c, score/src/wkspace.c,
+ sapi/include/confdefs.h, sapi/include/rtems/config.h,
+ sapi/include/rtems/extension.h, sapi/include/rtems/fatal.h,
+ sapi/include/rtems/init.h, sapi/include/rtems/io.h,
+ sapi/include/rtems/mptables.h, sapi/include/rtems/sptables.h,
+ sapi/include/rtems/sptables.h.in, sapi/inline/rtems/extension.inl,
+ sapi/macros/rtems/extension.inl, sapi/src/debug.c, sapi/src/exinit.c,
+ sapi/src/extension.c, sapi/src/extensioncreate.c,
+ sapi/src/extensiondelete.c, sapi/src/extensionident.c, sapi/src/fatal.c,
+ sapi/src/io.c, sapi/src/itronapi.c, sapi/src/posixapi.c,
+ sapi/src/rtemsapi.c, rtems/include/rtems.h,
+ rtems/include/rtems/rtems/asr.h, rtems/include/rtems/rtems/attr.h,
+ rtems/include/rtems/rtems/cache.h, rtems/include/rtems/rtems/clock.h,
+ rtems/include/rtems/rtems/config.h, rtems/include/rtems/rtems/dpmem.h,
+ rtems/include/rtems/rtems/event.h, rtems/include/rtems/rtems/eventmp.h,
+ rtems/include/rtems/rtems/eventset.h, rtems/include/rtems/rtems/intr.h,
+ rtems/include/rtems/rtems/message.h, rtems/include/rtems/rtems/modes.h,
+ rtems/include/rtems/rtems/mp.h, rtems/include/rtems/rtems/msgmp.h,
+ rtems/include/rtems/rtems/options.h, rtems/include/rtems/rtems/part.h,
+ rtems/include/rtems/rtems/partmp.h, rtems/include/rtems/rtems/ratemon.h,
+ rtems/include/rtems/rtems/region.h,
+ rtems/include/rtems/rtems/regionmp.h,
+ rtems/include/rtems/rtems/rtemsapi.h, rtems/include/rtems/rtems/sem.h,
+ rtems/include/rtems/rtems/semmp.h, rtems/include/rtems/rtems/signal.h,
+ rtems/include/rtems/rtems/signalmp.h,
+ rtems/include/rtems/rtems/status.h, rtems/include/rtems/rtems/support.h,
+ rtems/include/rtems/rtems/taskmp.h, rtems/include/rtems/rtems/tasks.h,
+ rtems/include/rtems/rtems/timer.h, rtems/include/rtems/rtems/types.h,
+ rtems/inline/rtems/rtems/asr.inl, rtems/inline/rtems/rtems/attr.inl,
+ rtems/inline/rtems/rtems/dpmem.inl, rtems/inline/rtems/rtems/event.inl,
+ rtems/inline/rtems/rtems/eventset.inl,
+ rtems/inline/rtems/rtems/message.inl,
+ rtems/inline/rtems/rtems/modes.inl,
+ rtems/inline/rtems/rtems/options.inl, rtems/inline/rtems/rtems/part.inl,
+ rtems/inline/rtems/rtems/ratemon.inl,
+ rtems/inline/rtems/rtems/region.inl, rtems/inline/rtems/rtems/sem.inl,
+ rtems/inline/rtems/rtems/status.inl,
+ rtems/inline/rtems/rtems/support.inl,
+ rtems/inline/rtems/rtems/tasks.inl, rtems/inline/rtems/rtems/timer.inl,
+ rtems/macros/rtems/rtems/asr.inl, rtems/macros/rtems/rtems/attr.inl,
+ rtems/macros/rtems/rtems/dpmem.inl, rtems/macros/rtems/rtems/event.inl,
+ rtems/macros/rtems/rtems/eventset.inl,
+ rtems/macros/rtems/rtems/message.inl,
+ rtems/macros/rtems/rtems/modes.inl,
+ rtems/macros/rtems/rtems/options.inl, rtems/macros/rtems/rtems/part.inl,
+ rtems/macros/rtems/rtems/ratemon.inl,
+ rtems/macros/rtems/rtems/region.inl, rtems/macros/rtems/rtems/sem.inl,
+ rtems/macros/rtems/rtems/status.inl,
+ rtems/macros/rtems/rtems/support.inl,
+ rtems/macros/rtems/rtems/tasks.inl, rtems/macros/rtems/rtems/timer.inl,
+ rtems/src/attr.c, rtems/src/clockget.c, rtems/src/clockset.c,
+ rtems/src/clocktick.c, rtems/src/dpmem.c, rtems/src/dpmemcreate.c,
+ rtems/src/dpmemdelete.c, rtems/src/dpmemexternal2internal.c,
+ rtems/src/dpmemident.c, rtems/src/dpmeminternal2external.c,
+ rtems/src/event.c, rtems/src/eventmp.c, rtems/src/eventreceive.c,
+ rtems/src/eventseize.c, rtems/src/eventsend.c,
+ rtems/src/eventsurrender.c, rtems/src/eventtimeout.c, rtems/src/intr.c,
+ rtems/src/intrbody.c, rtems/src/intrcatch.c, rtems/src/mp.c,
+ rtems/src/msg.c, rtems/src/msgmp.c, rtems/src/msgqallocate.c,
+ rtems/src/msgqbroadcast.c, rtems/src/msgqcreate.c,
+ rtems/src/msgqdelete.c, rtems/src/msgqflush.c,
+ rtems/src/msgqgetnumberpending.c, rtems/src/msgqident.c,
+ rtems/src/msgqreceive.c, rtems/src/msgqsend.c, rtems/src/msgqsubmit.c,
+ rtems/src/msgqtranslatereturncode.c, rtems/src/msgqurgent.c,
+ rtems/src/part.c, rtems/src/partcreate.c, rtems/src/partdelete.c,
+ rtems/src/partgetbuffer.c, rtems/src/partident.c, rtems/src/partmp.c,
+ rtems/src/partreturnbuffer.c, rtems/src/ratemon.c,
+ rtems/src/ratemoncancel.c, rtems/src/ratemoncreate.c,
+ rtems/src/ratemondelete.c, rtems/src/ratemongetstatus.c,
+ rtems/src/ratemonident.c, rtems/src/ratemonperiod.c,
+ rtems/src/ratemontimeout.c, rtems/src/region.c,
+ rtems/src/regioncreate.c, rtems/src/regiondelete.c,
+ rtems/src/regionextend.c, rtems/src/regiongetinfo.c,
+ rtems/src/regiongetsegment.c, rtems/src/regiongetsegmentsize.c,
+ rtems/src/regionident.c, rtems/src/regionmp.c,
+ rtems/src/regionreturnsegment.c, rtems/src/rtclock.c,
+ rtems/src/rtemsidtoname.c, rtems/src/rtemstimer.c, rtems/src/sem.c,
+ rtems/src/semcreate.c, rtems/src/semdelete.c, rtems/src/semflush.c,
+ rtems/src/semident.c, rtems/src/semmp.c, rtems/src/semobtain.c,
+ rtems/src/semrelease.c, rtems/src/semtranslatereturncode.c,
+ rtems/src/signal.c, rtems/src/signalcatch.c, rtems/src/signalmp.c,
+ rtems/src/signalsend.c, rtems/src/taskcreate.c, rtems/src/taskdelete.c,
+ rtems/src/taskgetnote.c, rtems/src/taskident.c,
+ rtems/src/taskinitusers.c, rtems/src/taskissuspended.c,
+ rtems/src/taskmode.c, rtems/src/taskmp.c, rtems/src/taskrestart.c,
+ rtems/src/taskresume.c, rtems/src/tasks.c, rtems/src/tasksetnote.c,
+ rtems/src/tasksetpriority.c, rtems/src/taskstart.c,
+ rtems/src/tasksuspend.c, rtems/src/taskvariableadd.c,
+ rtems/src/taskvariabledelete.c, rtems/src/taskvariableget.c,
+ rtems/src/taskwakeafter.c, rtems/src/taskwakewhen.c,
+ rtems/src/timercancel.c, rtems/src/timercreate.c,
+ rtems/src/timerdelete.c, rtems/src/timerfireafter.c,
+ rtems/src/timerfirewhen.c, rtems/src/timergetinfo.c,
+ rtems/src/timerident.c, rtems/src/timerreset.c, rtems/src/timerserver.c,
+ rtems/src/timerserverfireafter.c, rtems/src/timerserverfirewhen.c,
+ libmisc/cpuuse/cpuuse.c, libmisc/cpuuse/cpuuse.h,
+ libmisc/devnull/devnull.c, libmisc/devnull/devnull.h,
+ libmisc/dummy/dummy.c, libmisc/dumpbuf/dumpbuf.c,
+ libmisc/dumpbuf/dumpbuf.h, libmisc/fsmount/fsmount.c,
+ libmisc/fsmount/fsmount.h, libmisc/serdbg/serdbgio.c,
+ libmisc/serdbg/termios_printk.c, libmisc/stackchk/check.c,
+ libmisc/stackchk/internal.h, libmisc/stackchk/stackchk.h,
+ libmisc/untar/untar.c, libmisc/untar/untar.h,
+ libblock/include/rtems/ide_part_table.h, libblock/src/ata.c,
+ libblock/src/ide_part_table.c, libfs/src/dosfs/dosfs.h,
+ libfs/src/dosfs/fat.h, libfs/src/dosfs/fat_fat_operations.h,
+ libfs/src/dosfs/fat_file.h, libfs/src/dosfs/msdos.h,
+ libfs/src/dosfs/msdos_create.c, libfs/src/dosfs/msdos_dir.c,
+ libfs/src/dosfs/msdos_eval.c, libfs/src/dosfs/msdos_file.c,
+ libfs/src/dosfs/msdos_free.c, libfs/src/dosfs/msdos_fsunmount.c,
+ libfs/src/dosfs/msdos_handlers_dir.c,
+ libfs/src/dosfs/msdos_handlers_file.c, libfs/src/dosfs/msdos_init.c,
+ libfs/src/dosfs/msdos_initsupp.c, libfs/src/dosfs/msdos_misc.c,
+ libfs/src/dosfs/msdos_mknod.c, libfs/src/dosfs/msdos_node_type.c,
+ libfs/src/imfs/deviceio.c, libfs/src/imfs/imfs.h,
+ libfs/src/imfs/imfs_chown.c, libfs/src/imfs/imfs_config.c,
+ libfs/src/imfs/imfs_creat.c, libfs/src/imfs/imfs_debug.c,
+ libfs/src/imfs/imfs_directory.c, libfs/src/imfs/imfs_eval.c,
+ libfs/src/imfs/imfs_fchmod.c, libfs/src/imfs/imfs_fcntl.c,
+ libfs/src/imfs/imfs_fdatasync.c, libfs/src/imfs/imfs_free.c,
+ libfs/src/imfs/imfs_fsunmount.c, libfs/src/imfs/imfs_getchild.c,
+ libfs/src/imfs/imfs_gtkn.c, libfs/src/imfs/imfs_handlers_device.c,
+ libfs/src/imfs/imfs_handlers_directory.c,
+ libfs/src/imfs/imfs_handlers_link.c,
+ libfs/src/imfs/imfs_handlers_memfile.c, libfs/src/imfs/imfs_init.c,
+ libfs/src/imfs/imfs_initsupp.c, libfs/src/imfs/imfs_link.c,
+ libfs/src/imfs/imfs_mknod.c, libfs/src/imfs/imfs_mount.c,
+ libfs/src/imfs/imfs_ntype.c, libfs/src/imfs/imfs_readlink.c,
+ libfs/src/imfs/imfs_rmnod.c, libfs/src/imfs/imfs_stat.c,
+ libfs/src/imfs/imfs_symlink.c, libfs/src/imfs/imfs_unixstub.c,
+ libfs/src/imfs/imfs_unlink.c, libfs/src/imfs/imfs_unmount.c,
+ libfs/src/imfs/imfs_utime.c, libfs/src/imfs/ioman.c,
+ libfs/src/imfs/linearfile.c, libfs/src/imfs/memfile.c,
+ libfs/src/imfs/miniimfs_init.c, libcsupport/include/chain.h,
+ libcsupport/include/clockdrv.h, libcsupport/include/console.h,
+ libcsupport/include/iosupp.h, libcsupport/include/rtc.h,
+ libcsupport/include/spurious.h, libcsupport/include/timerdrv.h,
+ libcsupport/include/vmeintr.h, libcsupport/include/motorola/mc68230.h,
+ libcsupport/include/rtems/libcsupport.h,
+ libcsupport/include/rtems/libio.h, libcsupport/include/rtems/libio_.h,
+ libcsupport/include/rtems/termiostypes.h,
+ libcsupport/include/sys/termios.h, libcsupport/include/zilog/z8036.h,
+ libcsupport/include/zilog/z8530.h, libcsupport/include/zilog/z8536.h,
+ libcsupport/src/__brk.c, libcsupport/src/__gettod.c,
+ libcsupport/src/__sbrk.c, libcsupport/src/__times.c,
+ libcsupport/src/access.c, libcsupport/src/base_fs.c,
+ libcsupport/src/cfgetispeed.c, libcsupport/src/cfgetospeed.c,
+ libcsupport/src/cfsetispeed.c, libcsupport/src/cfsetospeed.c,
+ libcsupport/src/chdir.c, libcsupport/src/chmod.c,
+ libcsupport/src/chown.c, libcsupport/src/chroot.c,
+ libcsupport/src/close.c, libcsupport/src/ctermid.c,
+ libcsupport/src/dup.c, libcsupport/src/dup2.c, libcsupport/src/eval.c,
+ libcsupport/src/fchdir.c, libcsupport/src/fchmod.c,
+ libcsupport/src/fcntl.c, libcsupport/src/fdatasync.c,
+ libcsupport/src/fpathconf.c, libcsupport/src/fs_null_handlers.c,
+ libcsupport/src/fstat.c, libcsupport/src/fsync.c,
+ libcsupport/src/ftruncate.c, libcsupport/src/getdents.c,
+ libcsupport/src/getpwent.c, libcsupport/src/hosterr.c,
+ libcsupport/src/ioctl.c, libcsupport/src/isatty.c,
+ libcsupport/src/libio.c, libcsupport/src/libio_sockets.c,
+ libcsupport/src/link.c, libcsupport/src/lseek.c,
+ libcsupport/src/lstat.c, libcsupport/src/malloc.c,
+ libcsupport/src/mallocfreespace.c, libcsupport/src/mkdir.c,
+ libcsupport/src/mkfifo.c, libcsupport/src/mknod.c,
+ libcsupport/src/mount.c, libcsupport/src/newlibc.c,
+ libcsupport/src/no_libc.c, libcsupport/src/no_posix.c,
+ libcsupport/src/open.c, libcsupport/src/pathconf.c,
+ libcsupport/src/pipe.c, libcsupport/src/privateenv.c,
+ libcsupport/src/read.c, libcsupport/src/readlink.c,
+ libcsupport/src/rewinddir.c, libcsupport/src/rmdir.c,
+ libcsupport/src/seekdir.c, libcsupport/src/stat.c,
+ libcsupport/src/symlink.c, libcsupport/src/sync.c,
+ libcsupport/src/tcdrain.c, libcsupport/src/tcflow.c,
+ libcsupport/src/tcflush.c, libcsupport/src/tcgetattr.c,
+ libcsupport/src/tcgetprgrp.c, libcsupport/src/tcsendbreak.c,
+ libcsupport/src/tcsetattr.c, libcsupport/src/tcsetpgrp.c,
+ libcsupport/src/telldir.c, libcsupport/src/termios.c,
+ libcsupport/src/termiosinitialize.c, libcsupport/src/truncate.c,
+ libcsupport/src/umask.c, libcsupport/src/unixlibc.c,
+ libcsupport/src/unlink.c, libcsupport/src/unmount.c,
+ libcsupport/src/utime.c, libcsupport/src/write.c,
+ libnetworking/rtems/mkrootfs.c, libnetworking/rtems/mkrootfs.h: URL for
+ license changed.
+ PR 479/rtems_misc
+ * libcsupport/src/malloc.c: Per multiple standards realloc does not free
+ the original memory if the allocation of the requested larger block
+ fails.
+
+2003-09-03 Joel Sherrill <joel@OARcorp.com>
+
+ * libfs/msdos_create.c: Remove unused variable warning.
+
+2003-09-02 Joel Sherrill <joel@OARcorp.com>
+
+ * libcsupport/src/open.c: Fix typo.
+ * libcsupport/src/malloc.c: Remove test define left in.
+
+2003-09-02 Jiri Gaisler <jiri@gaisler.com>
+
+ PR 476/networking
+ * libnetworking/machine/in_cksum.h: Fix in_cksum calculation on SPARC.
+
+2003-09-02 Ilya Alexeev <ilya@continuum.ru>
+
+ PR 472/filesystem
+ src/malloc.c: Need to include apimutex.h when MALLOC_STATS is defined.
+
+2003-08-28 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * aclocal/rtems-top.m4: Add RTEMS_API.
+ AC_DEFAULT_PREFIX([/opt/rtems-][RTEMS_API]).
+
+2003-08-18 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * aclocal/rtems-debug.m4: Remove.
+ * aclocal/enable-rtems-debug.m4, aclocal/check-rtems-debug.m4: New
+ (Split out from rtems-debug.m4).
+ * automake/local.am: Remove "debug".
+ PR 449/rtems:
+ * posix/src/getegid.c, posix/src/geteuid.c, posix/src/getgid.c,
+ posix/src/getgroups.c, posix/src/getlogin.c, posix/src/getpgrp.c,
+ posix/src/getpid.c, posix/src/getppid.c, posix/src/getuid.c,
+ posix/src/setpgid.c, posix/src/setsid.c: Remove (Moved to
+ ../libcsupport/src).
+ * posix/Makefile.am: Reflect changes above.
+ PR 449/rtems:
+ * libcsupport/src/getegid.c, libcsupport/src/geteuid.c,
+ libcsupport/src/getgid.c, libcsupport/src/getgroups.c,
+ libcsupport/src/getlogin.c, libcsupport/src/getpgrp.c,
+ libcsupport/src/getpid.c, libcsupport/src/getppid.c,
+ libcsupport/src/getuid.c, libcsupport/src/setpgid.c,
+ libcsupport/src/setsid.c: New (Copied from ../posix/src).
+ * libcsupport/src/no_posix: Remove getpid and _getpid_r.
+ * libcsupport/Makefile.am: Reflect changes above.
+
+2003-08-14 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libmisc/fsmount/Makefile.am: Fix path to automake-includes.
+
+2003-08-14 Joel Sherrill <joel@OARcorp.com>
+
+ * posix/src/mqueuenametoid.c, posix/src/semaphorenametoid.c: Added ID to
+ name lookup service and changed name of id/name translation status code.
+ This propagated to multiple functions. The user API service added was
+ rtems_object_id_to_name().
+ PR 92/rtems
+ * posix/Makefile.am, posix/src/alarm.c, posix/src/psignal.c: Added
+ ualarm() and usleep().
+ * posix/src/ualarm.c, posix/src/usleep.c: New files.
+ * score/Makefile.am, score/include/rtems/score/object.h,
+ score/include/rtems/score/objectmp.h, score/src/objectmp.c,
+ score/src/objectnametoid.c: Added ID to name lookup service and changed
+ name of id/name translation status code. This propagated to multiple
+ functions. The user API service added was rtems_object_id_to_name().
+ * score/src/objectidtoname.c: New file.
+ PR 408/filesystem
+ * score/score/Makefile.am, score/score/include/rtems/score/thread.h:
+ Added sync() service. As part of adding this service, the new RTEMS
+ service rtems_iterate_over_all_threads() was also added. This new
+ service makes it easier to iterate over all the tasks/threads in a
+ system and perform an action on them.
+ * score/score/src/iterateoverthreads.c: New file.
+ * score/ChangeLog: Fixed screwup.
+ * sapi/src/extensionident.c, rtems/Makefile.am, rtems/include/rtems.h,
+ rtems/include/rtems/rtems/status.h, rtems/src/dpmemident.c,
+ rtems/src/msgqident.c, rtems/src/partident.c, rtems/src/ratemonident.c,
+ rtems/src/regionident.c, rtems/src/semident.c, rtems/src/taskident.c,
+ rtems/src/timerident.c: Added ID to name lookup service and changed name
+ of id/name translation status code. This propagated to multiple
+ functions. The user API service added was rtems_object_id_to_name().
+ * rtems/src/rtemsidtoname.c: New file.
+ PR 408/filesystem
+ * libmisc/cpuuse/cpuuse.c: Added sync() service. As part of adding this
+ service, the new RTEMS service rtems_iterate_over_all_threads() was also
+ added. This new service makes it easier to iterate over all the
+ tasks/threads in a system and perform an action on them. This change is
+ to use the new thread iteration service.
+ * libcsupport/Makefile.am: Add fileio to list of interactive tests.
+ * libcsupport/src/sync.c: New (Copied from ../posix/src). New file.
+
+2003-08-13 Joel Sherrill <joel@OARcorp.com>
+
+ * libmisc/fsmount/.cvsignore: New file.
+
+2003-08-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use rtems-bugs@rtems.com as bug report email address.
+
+2003-08-11 Joel Sherrill <joel@OARcorp.com>
+
+ * configure.ac: Removed duplicate entry.
+
+2003-08-08 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Add libmisc/fsmount/Makefile.
+
+2003-08-06 Till Strauman <strauman@slac.stanford.edu>
+
+ PR 435/networking
+ * libnetworking/rtems/rtems_showifstat.c: rtems_showifstat misses
+ printing the netmask.
+
+2003-08-06 Thomas Doerfler<Thomas.Doerfler@imd-systems.de>
+
+ PR 369/filesystem
+ * libmisc/Makefile.am, libmisc/shell/cmds.c, libmisc/wrapup/Makefile.am:
+ sample application to show the use of the DOSFS functions.
+ * libmisc/fsmount/Makefile.am, libmisc/fsmount/README,
+ libmisc/fsmount/fsmount.c, libmisc/fsmount/fsmount.h: New files.
+
+2003-08-05 Till Strauman <strauman@slac.stanford.edu>
+
+ PR 436/rtems_misc
+ * libmisc/monitor/mon-monitor.c: monitor registered commands list
+ manipulation bugs.
+ PR 442/filesystem
+ * libcsupport/src/open.c: file never closed if ftruncate() fails in
+ open().
+
+2003-08-05 Thomas Doerfler <Thomas.Doerfler@imd-systems.de>
+
+ PR 440/filesystem
+ * libfs/src/dosfs/fat_fat_operations.c: Improve write data speed for
+ DOSFS FAT12/FAT16 systems.
+ PR 439/filesystem
+ * libfs/src/dosfs/fat_file.c: flush temporary buffer when closing files.
+
+2003-08-05 <djc915@mail.usask.ca>
+
+ PR 443/filesystem
+ * libfs/src/imfs/deviceio.c: deviceio.c mishandles return codes.
+
+2003-08-04 Thomas Doerfler <Thomas.Doerfler@imd-systems.de>
+
+ PR 441/filesystem
+ * libfs/src/dosfs/msdos.h, libfs/src/dosfs/msdos_create.c,
+ libfs/src/dosfs/msdos_file.c, libfs/src/dosfs/msdos_init.c,
+ libfs/src/dosfs/msdos_mknod.c: add rename support to DOSFS.
+
+2003-07-24 Jennifer Averett <jennifer.averett@OARcorp.com>
+
+ PR 434/filesystem
+ * libfs/src/imfs/imfs_init.c, libfs/src/imfs/miniimfs_init.c: Modified
+ to return error code.
+ * libfs/src/imfs/imfs_initsup.c: Modified to set error upon memory
+ failure.
+
+2003-07-18 Till Straumann <strauman@slac.stanford.edu>
+
+ PR 430/rtems
+ * score/include/rtems/score/watchdog.h: _Watchdog_Ticks_since_boot
+ should be a VOLATILE variable.
+ * score/src/watchdoginsert.c: 'restart' algorithm needs to enforce
+ reloading the list head in case a TICK interrupt during ISR_Flash()
+ modified the list. This is achieved by a proper VOLATILE cast. Also
+ _Watchdog_Sync_count++ should be protected by _ISR_Disable (prevent
+ corruption in case ISR calls watchdoginsert).
+ * score/src/watchdogadjust.c: ISR protection added.
+ * score/src/watchdogtickle.c: ISR protection added. NOTE: PowerPC BSPs
+ using the new exception processing MUST BE UPDATED to maintain
+ _ISR_Nest_level. See also PR288 which provides fixes for the affected
+ BSPs distributed with RTEMS.
+
+2003-07-16 Joel Sherrill <joel@OARcorp.com>
+
+ * libfs/ChangeLog: Correct format.
+
+2003-07-15 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * wrapup/Makefile.am: Remove '/' after $(DESTDIR).
+ * wrapup/Makefile.am: Remove bogus $(MULTISUBDIR).
+
+2003-07-15 Chris Johns <cjohns@cybertec.com.au>
+
+ PR 431/filesystem
+ * libfs/src/dosfs/msdos.h: MSDOS Volume semaphore timeout is now NO
+ TIMEOUT. MSDOS volume opertations will wait for ever.
+
+2003-07-08 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Merge-in librpc/configure.ac.
+ * Makefile.am: Add librpc to SUBDIRS. Remove @subdirs@.
+ * configure.ac: Merge-in libcsupport/configure.ac.
+ * Makefile.am: Add libcsupport to SUBDIRS.
+ * configure.ac: Merge-in posix/configure.ac. Merge-in
+ itron/configure.ac. Misc. cosmetical changes.
+ * Makefile.am: Add posix, itron to SUBDIRS.
+ * configure.ac: Merge-in libnetworking/configure.ac. Remove "rtems-"
+ from RTEMS_VERSION. Add AC_CHECK_FUNCS([strsep strcasecmp snprintf]).
+ * Makefile.am: Add libmisc to SUBDIRS.
+ * configure.ac: Merge-in libmisc/configure.ac.
+ * Makefile.am: Add libmisc to SUBDIRS.
+ * configure.ac: Merge-in libfs/configure.ac.
+ * Makefile.am: Add libfs to SUBDIRS.
+ * configure.ac: Merge-in libblock/configure.ac.
+ * Makefile.am: Add libblock to SUBDIRS.
+ * configure.ac: Merge-in ada/configure.ac.
+ * Makefile.am: Add ada to SUBDIRS.
+ * itron/configure.ac: Remove (Merged-in into ../configure.ac).
+ * itron/Makefile.am: Reflect having merged configure.ac into
+ ../configure.ac.
+ * itron/src/config.h: New.
+ * posix/configure.ac: Remove (Merged-in into ../configure.ac).
+ * posix/Makefile.am: Reflect having merged configure.ac into
+ ../configure.ac.
+ * posix/src/config.h: New.
+ * score/cpu/Makefile.am: Add DIST_SUBDIRS = $(RTEMS_CPU).
+ * libmisc/configure.ac: Remove (Merged into ../configure.ac).
+ * libmisc/Makefile.am: Reflect having merged configure.ac into
+ ../configure.ac.
+ * libmisc/capture/config.h: New.
+ * libmisc/capture/Makefile.am: Add config.h. Reflect having merged
+ configure.ac into ../configure.ac.
+ * libmisc/cpuuse/config.h: New.
+ * libmisc/cpuuse/Makefile.am: Add config.h. Reflect having merged
+ configure.ac into ../configure.ac.
+ * libmisc/devnull/config.h: New.
+ * libmisc/devnull/Makefile.am: Add config.h. Reflect having merged
+ configure.ac into ../configure.ac.
+ * libmisc/dummy/config.h: New.
+ * libmisc/dummy/Makefile.am: Add config.h. Reflect having merged
+ configure.ac into ../configure.ac.
+ * libmisc/dumpbuf/config.h: New.
+ * libmisc/dumpbuf/Makefile.am: Add config.h. Reflect having merged
+ configure.ac into ../configure.ac.
+ * libmisc/monitor/config.h: New.
+ * libmisc/monitor/Makefile.am: Add config.h. Reflect having merged
+ configure.ac into ../configure.ac.
+ * libmisc/mw-fb/config.h: New.
+ * libmisc/mw-fb/Makefile.am: Add config.h. Reflect having merged
+ configure.ac into ../configure.ac.
+ * libmisc/rtmonuse/config.h: New.
+ * libmisc/rtmonuse/Makefile.am: Add config.h. Reflect having merged
+ configure.ac into ../configure.ac.
+ * libmisc/serdbg/config.h: New.
+ * libmisc/serdbg/Makefile.am: Add config.h. Reflect having merged
+ configure.ac into ../configure.ac.
+ * libmisc/shell/config.h: New.
+ * libmisc/shell/Makefile.am: Add config.h. Reflect having merged
+ configure.ac into ../configure.ac.
+ * libmisc/stackchk/config.h: New.
+ * libmisc/stackchk/Makefile.am: Add config.h. Reflect having merged
+ configure.ac into ../configure.ac.
+ * libmisc/untar/config.h: New.
+ * libmisc/untar/Makefile.am: Add config.h. Reflect having merged
+ configure.ac into ../configure.ac.
+ * libmisc/wrapup/Makefile.am: Reflect having merged configure.ac into
+ ../configure.ac.
+ * libmisc/capture/capture-cli.c, libmisc/capture/capture.c,
+ libmisc/cpuuse/cpuuse.c, libmisc/devnull/devnull.c,
+ libmisc/dummy/dummy.c, libmisc/dumpbuf/dumpbuf.c,
+ libmisc/monitor/mon-command.c, libmisc/monitor/mon-config.c,
+ libmisc/monitor/mon-dname.c, libmisc/monitor/mon-driver.c,
+ libmisc/monitor/mon-extension.c, libmisc/monitor/mon-itask.c,
+ libmisc/monitor/mon-manager.c, libmisc/monitor/mon-monitor.c,
+ libmisc/monitor/mon-mpci.c, libmisc/monitor/mon-object.c,
+ libmisc/monitor/mon-prmisc.c, libmisc/monitor/mon-queue.c,
+ libmisc/monitor/mon-server.c, libmisc/monitor/mon-symbols.c,
+ libmisc/monitor/mon-task.c, libmisc/mw-fb/mw_fb.c,
+ libmisc/mw-fb/mw_uid.c, libmisc/rtmonuse/rtmonuse.c,
+ libmisc/serdbg/serdbg.c, libmisc/serdbg/serdbgio.c,
+ libmisc/serdbg/termios_printk.c, libmisc/shell/cmds.c,
+ libmisc/stackchk/check.c, libmisc/untar/untar.c: Add config-header
+ support.
+ * librpc/configure.ac: Remove (Merged-in into ../configure.ac).
+ * librpc/Makefile.am, librpc/include/Makefile.am,
+ librpc/src/Makefile.am, librpc/src/rpc/Makefile.am,
+ librpc/src/xdr/Makefile.am: Reflect having merged configure.ac into
+ ../configure.ac.
+ * libblock/configure.ac: Remove (Merged into ../configure.ac).
+ * libblock/Makefile.am: Reflect having merged configure.ac into
+ ../configure.ac.
+ * libfs/configure.ac: Remove (Merged-in into ../configure.ac).
+ * libfs/Makefile.am, libfs/src/Makefile.am, libfs/src/dosfs/Makefile.am,
+ libfs/src/imfs/Makefile.am: Reflect having merged configure.ac into
+ ../configure.ac.
+ * libfs/src/dosfs/config.h: New.
+ * libfs/src/dosfs/Makefile.am: Add config.h.
+ * libfs/src/imfsfs/config.h: New.
+ * libfs/src/imfs/Makefile.am: Add config.h. Remove COMMON_C_FILES,
+ DOC_FILES (Unused).
+ * libfs/src/dosfs/fat.c: include config-header "config.h".
+ * libfs/src/dosfs/fat_fat_operations.c, libfs/src/dosfs/fat_file.c,
+ libfs/src/dosfs/msdos_conv.c: Ditto.
+ * libcsupport/configure.ac: Remove (Merged-in into ../configure.ac).
+ * libcsupport/Makefile.am: DOC_FILES = src/TODO src/CASES, Reflect
+ having merged configure.ac into ../configure.ac.
+ * libcsupport/src/config.h: New.
+ * libnetworking/configure.ac: Remove (Merged into ../configure.ac).
+ * libnetworking/Makefile.am, libnetworking/libc/Makefile.am,
+ libnetworking/lib/Makefile.am, libnetworking/wrapup/Makefile.am: Reflect
+ having merged configure.ac into ../configure.ac.
+ * libnetworking/kern/kern_mib.c: Use RTEMS_VERSION to setup osrelease.
+
+2003-07-08 Joel Sherrill <joel@OARcorp.com>
+
+ PR 419/rtems
+ * libcsupport/src/termios.c: Removed warning.
+
+2003-07-07 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libmisc/configure.ac: Remove RTEMS_BSP from
+ RTEMS_CHECK_MULTIPROCESSING.
+
+2003-07-07 Joel Sherrill <joel@OARcorp.com>
+
+ PR 417/rtems
+ * score/src/coresemsurrender.c: Correct incorrect check for
+ maximum_count reported by Sergei Organov <osv@topconrd.ru>.
+
+2003-07-03 Joel Sherrill <joel@OARcorp.com>
+
+ * aclocal/version.m4: Updated to rtems-ss-20030703.
+
+2003-07-02 Chris Johns <cjohns@cybertec.com.au>
+
+ * libfs/src/dosfs/Makefile.am, libfs/src/dosfs/msdos.h,
+ libfs/src/dosfs/msdos_conv.c, libfs/src/dosfs/msdos_create.c,
+ libfs/src/dosfs/msdos_dir.c, libfs/src/dosfs/msdos_misc.c: Patch from
+ Victor V. Vengerov <vvv@oktet.ru> to remove Linux code.
+ * libfs/src/dosfs/fat.c, libfs/src/dosfs/fat.h: Comment have been
+ updated.
+ * libcsupport/include/rtems/libio.h, libcsupport/src/termios.c: Add the
+ rtems_termios_bufsize call.
+
+2003-06-13 Joel Sherrill <joel@OARcorp.com>
+
+ * score/src/threadloadenv.c: Removed warnings.
+
+2003-06-12 Joel Sherrill <joel@OARcorp.com>
+
+ * score/src/objectmp.c, rtems/include/rtems/rtems/msgmp.h,
+ rtems/include/rtems/rtems/partmp.h,
+ rtems/include/rtems/rtems/regionmp.h, rtems/include/rtems/rtems/semmp.h,
+ rtems/src/msgmp.c, rtems/src/partmp.c, rtems/src/regionmp.c,
+ rtems/src/semmp.c: Removed warnings.
+
+2003-06-10 Phil Torre <ptorre@zetron.com>
+
+ PR 411/filesystem
+ * libfs/src/imfs/imfs_unlink.c: Fix bug where renaming a memfile and
+ then unlinking it causes a memory leak.
+
+2003-06-04 Joel Sherrill <joel@OARcorp.com>
+
+ * libmisc/stackchk/check.c, libblock/src/ide_part_table.c: Removed
+ warnings.
+
+2003-05-30 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/include/rtems/rtems/types.h: Include stdint.h.
+ * libcsupport/Makefile.am: Conditionally install stdint.h/inttypes.h.
+ * libcsupport/configure.ac: Check for system-stdint.h/inttypes.h.
+
+2003-05-29 Joel Sherrill <joel@OARcorp.com>
+
+ * libnetworking/rtems/rtems_syscall.c: Removed warnings.
+
+2003-05-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ PR 409/core
+ * include/Makefile.am: Add rtems/stdint.h.
+ * include/rtems/stdint.h: New.
+ PR 321/bsps
+ * aclocal/env-rtemscpu.m4: Remove support for profile-variant.
+ * automake/compile.am, automake/local.am: Ditto.
+ PR 409:
+ * rtems/include/rtems/rtems/types.h: Include rtems/stdint.h. Apply
+ c99-types to typedef rtems_[un]signed[8|16|32|64].
+ PR 409:
+ * libcsupport/include/stdint.h: Include rtems/stdint.h.
+
+2003-05-15 cjohns@cybertec.com.au <cjohns@cybertec.com.au>
+
+ * libnetworking/netinet/in.h: PR406 - Added INET_ADDRSTRLEN per the
+ SUSv3 standard.
+
+2003-05-14 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * automake/compile.am: Remove LIBSUFFIX_VA (unused).
+
+2003-05-02 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * aclocal/env-rtemscpu.m4: Merge-in env-rtemsbsp.m4.
+ * aclocal/env-rtemsbsp.m4, aclocal/enable-rtemsbsp.m4: Remove.
+ * aclocal/env-rtemscpu.m4: Remove stray '/' in setting up
+ project_libdir.
+
+2003-04-17 Thomas Doerfler <Thomas.Doerfler@imd-systems.de>
+
+ PR 399/rtems_misc
+ * libcsupport/src/termios.c: In canonical mode, when input is present in
+ the input buffer that contains an EOL character and some following
+ characters, a read call read data behind the EOL character, although it
+ should stop reading with the EOL character.
+
+2003-04-17 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libmisc/dummy/Makefile.am: Remove stray dummy.rel.
+ * libcsupport/src/no_posix.c: include <reent.h> instead of <sys/reent.h>.
+
+2003-04-17 Joel Sherrill <joel@OARcorp.com>
+
+ * aclocal/version.m4: Updated to rtems-ss-20030417.
+
+2003-04-16 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ PR 389/rtems
+ * libcsupport/src/no_posix.c: Correct _kill_r() prototype and make it
+ conditional on newlib.
+
+2003-04-15 Joel Sherrill <joel@OARcorp.com>
+
+ PR 388/networking
+ * libnetworking/kern/kern_sysctl.c: Revert previous patch and use
+ strlcpy() now that it is available. Also fixed some warnings.
+
+2003-04-11 Joel Sherrill <joel@OARcorp.com>
+
+ * aclocal/version.m4: Updated to rtems-ss-20020411.
+
+2003-04-03 Eri Valette <eric.valette@free.fr>
+
+ PR 381/core
+ * libcsupport/src/newlibc.c: Switch from using _REENT_INIT to
+ _REEINT_INIT_PTR to fix strange run-time problem where EIP was corrupted
+ on pc386 BSP.
+
+2003-03-27 Joel Sherrill <joel@OARcorp.com>
+
+ * libblock/Makefile.am: ATA code depends upon libchip/ide which is not
+ allowed in the cpukit source code since it must be buildable independent
+ of any BSP. These files were moved to libchip/ide.
+ * libblock/include/rtems/ata.h, libblock/include/rtems/ata_internal.h,
+ libblock/src/ata.c: Removed.
+ * libnetworking/kern/kern_sysctl.c: Converted from BSP strlcpy() to
+ strncpy().
+
+2003-03-25 Thomas Doerfler <Thomas.Doerfler@imd-systems.de>
+
+ PR 367/filesystem
+ * libblock/Makefile.am, libblock/include/rtems/ide_part_table.h,
+ libblock/src/ata.c, libblock/src/ide_part_table.c: Some bugs were still
+ present in the DOSFS implementation: - FAT12 did not work properly on
+ Big-Endian machines - Some synchronization and error handling problems
+ were present - Some legal codings for EOC were not recognized.
+ PR 367/filesystem
+ * libfs/src/dosfs/Makefile.am, libfs/src/dosfs/fat.c,
+ libfs/src/dosfs/fat.h, libfs/src/dosfs/fat_fat_operations.c,
+ libfs/src/dosfs/fat_file.c, libfs/src/dosfs/msdos.h,
+ libfs/src/dosfs/msdos_dir.c: Some bugs were still present in the DOSFS
+ implementation: - FAT12 did not work properly on Big-Endian machines. -
+ Some synchronization and error handling problems were present. - Some
+ legal codings for EOC were not recognized.
+
+2003-03-25 Joel Sherrill <joel@OARcorp.com>
+
+ * libnetworking/rtems/rtems_bsdnet_malloc_starvation.c: Fixed name of
+ include file.
+
+2003-03-18 Till Straumann <strauman@slac.stanford.edu>
+
+ PR 356/bsps
+ * score/src/threadhandlerc: This patch makes RTEMS/PowerPC eabi
+ compliant. Let Thread_Handler verify that _init/_main are non-NULL
+ before calling them (gives the linker script/user more freedom to handle
+ special cases).
+ PR 356/bsps
+ * libnetworking/sys/linker_set.h: This patch makes RTEMS/PowerPC eabi
+ compliant. Declare all linker-script defined addresses as variables of
+ unknown size and not as short objects like 'int', 'void*' etc. Since
+ only addresses are used and never those variable's values, the type used
+ in a declaration is not important.
+
+2003-03-18 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libcsupport/configure.ac: AC_CHECK_FUNCS(strlcpy strlcat).
+ * libcsupport/src/strlcat.c, libcsupport/src/strlcpy.c: New (extracted
+ from pppd/utils.c).
+ * libcsupport/Makefile.am: Add BSD_C_FILES, strlcat.c, strlcpy.c.
+
+2003-03-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * wrapup/Makefile.am: Remove '/' after $(DESTDIR) to work around Cygwin
+ mistreating paths.
+
+2003-03-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * wrapup/Makefile.am: Reflect changes to project_libdir.
+ * aclocal/env-rtemscpu.m4: Remove obsolete comment. Add MULTISUBDIR to
+ project_libdir.
+ * aclocal/env-rtemscpu.m4: Remove RTEMS_ROOT (Unused).
+ * aclocal/env-rtemsbsp.m4: Remove RTEMS_ROOT (Unused). Remove
+ RTEMS_PROJECT_ROOT (Unused).
+ * aclocal/tool-paths.m4: Delete.
+
+2003-03-06 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove AC_CONFIG_AUX_DIR.
+ * aclocal/rtems-top.m4: Add AC_CONFIG_AUX_DIR.
+ * configure.ac: AC_PREREQ(2.57).
+ * configure.ac: Remove sptables.h.in.
+ * itron/configure.ac: Remove AC_CONFIG_AUX_DIR.
+ * sapi/Makefile.am: Remove stray reference to sptables.h.in.
+ * sapi/include/rtems/sptables.h: New.
+ * sapi/include/rtems/sptables.h.in, sapi/include/.cvsignore,
+ sapi/include/rtems/.cvsignore, sapi/inline/.cvsignore,
+ sapi/inline/rtems/.cvsignore, sapi/macros/.cvsignore,
+ sapi/macros/rtems/.cvsignore, sapi/src/.cvsignore: Remove.
+ * libmisc/configure.ac, libblock/configure.ac, libfs/configure.ac,
+ libcsupport/configure.ac, libnetworking/configure.ac: Remove
+ AC_CONFIG_AUX_DIR.
+ * libnetworking/netinet/in_chksum.c: Remove duplicate case to include
+ in_chksum_arm.c.
+
+2003-02-28 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove AC_SUBST(RTEMS_VERSION). AC_DEFINE(RTEMS_VERSION)
+ to propagate it through cpuopts.h.
+ * sapi/include/rtems/sptables.h.in: Remove RTEMS_VERSION (Moved to
+ cpuopts.h).
+
+2003-02-26 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: AC_SUBST(RTEMS_VERSION,_RTEMS_VERSION).
+
+2003-02-20 Wolfram Wadepohl <W.Wadepohl@indumat.de>
+
+ PR 357/rtems_misc
+ * libcsupport/src/termios.c (rtems_termios_open): Fixed code the
+ incorrectly checked that the wrong pointer during allocation was NULL.
+
+2003-02-20 Till Straumann <strauman@slac.stanford.edu>
+
+ PR 351/networking
+ * libnetworking/nfs/bootp_subr.c: Fix ridiculous leak in bootp and use
+ strdup_bootp_realloc() everywhere for sake of consistency.
+
+2003-02-18 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * aclocal/gcc-isystem.m4: New.
+ * aclocal/gcc-specs.m4: Remove.
+ * aclocal/prog-cc.m4: Remove RTEMS_GCC_SPECS. Add RTEMS_GCC_ISYSTEM.
+ Reformat setting up RTEMS_CPPFLAGS.
+ * automake/local.am: Introduce depend-gcc. Remove ${ARCH}.
+ * automake/compile.am: Remove GCCSPECS, GCC_SPECS, CONFIG.CC, CC, CPP.
+ Add ${ARCH}. depend-gcc.
+ * aclocal/prog-cc.m4: Set up RTEMS_CPPFLAGS.
+ * aclocal/env-rtemscpu.m4: Remove GCC_SPECS.
+ * aclocal/env-rtemsbsp.m4: Remove GCC_SPECS. capture/capture-cli.c: Add
+ proper definition to avoid compiler warnings. Apply int = getchar().
+ * libcsupport/src/privateenv.c: Fix prototype for free_user_env.
+
+2003-02-14 Till Straumann <strauman@slac.stanford.edu>
+
+ PR 352/rtems_misc
+ * libmisc/shell/shell.c: make rtems_shell main task an FP enabled task.
+
+2003-02-14 Joel Sherrill <joel@OARcorp.com>
+
+ AMD a29k declared obsolete.
+ * score/cpu/Makefile.am: Removed reference.
+ * score/cpu/a29k/.cvsignore, score/cpu/a29k/ChangeLog,
+ score/cpu/a29k/Makefile.am, score/cpu/a29k/amd.ah, score/cpu/a29k/asm.h,
+ score/cpu/a29k/configure.ac, score/cpu/a29k/cpu.c,
+ score/cpu/a29k/cpu_asm.S, score/cpu/a29k/pswmacro.ah,
+ score/cpu/a29k/register.ah, score/cpu/a29k/sig.S,
+ score/cpu/a29k/rtems/.cvsignore, score/cpu/a29k/rtems/score/.cvsignore,
+ score/cpu/a29k/rtems/score/a29k.h, score/cpu/a29k/rtems/score/cpu.h,
+ score/cpu/a29k/rtems/score/cpu_asm.h,
+ score/cpu/a29k/rtems/score/types.h: Removed.
+
+2003-02-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * aclocal/canonical-target-name.m4: Transform tic4x -> RTEMS_CPU=c4x.
+
+2003-02-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * itron/configure.ac: AM_INIT_AUTOMAKE([1.7.2]).
+ * itron/configure.ac: AC_PREREQ(2.57).
+ * posix/configure.ac: AM_INIT_AUTOMAKE([1.7.2]).
+ * posix/configure.ac: AC_PREREQ(2.57).
+ * librpc/configure.ac: AM_INIT_AUTOMAKE([1.7.2]).
+ * librpc/configure.ac: AC_PREREQ(2.57).
+ * libblock/configure.ac: AM_INIT_AUTOMAKE([1.7.2]).
+ * libblock/configure.ac: AC_PREREQ(2.57).
+ * libfs/configure.ac: AM_INIT_AUTOMAKE([1.7.2]).
+ * libfs/configure.ac: AC_PREREQ(2.57).
+ * libcsupport/configure.ac: AM_INIT_AUTOMAKE([1.7.2]).
+ * libcsupport/configure.ac: AC_PREREQ(2.57).
+ * libnetworking/configure.ac: AM_INIT_AUTOMAKE([1.7.2]).
+ * libnetworking/configure.ac: AC_PREREQ(2.57).
+
+2003-02-11 Mike Siers <mikes@poliac.com>
+
+ * libnetworking/rtems/rtems_glue.c: A small patch to the network daemon
+ task code. I just added code to check the return value of the
+ rtems_bsdnet_event_receive function. Only when this function returns a
+ SUCCESSFUL status, will the event flags be checked. This is more of a
+ code cleanup issue than a bug. The patch will just ensure the ipintr()
+ and arpintr() functions are only called when a event is signaled.
+
+2003-02-06 Mike Siers <mikes@poliac.com>
+
+ PR 342/networking
+ * libnetworking/kern/uipc_mbuf.c: The RTEMS version of the m_copyback is
+ changing the m_len value of the mbuf. I looked into the source from
+ another BSD system and the mbuf length is not changed inside this
+ function. The m_copyback function is only being used in the
+ net/rtsock.c file. So I think this problem is only visable under
+ certain routing table conditions.
+
+2003-02-06 Joel Sherrill <joel@OARcorp.com>
+
+ * libcsupport/include/sys/ioccom.h: Include <sys/types.h> not
+ <machine/types.h> so Linux port builds.
+
+2003-02-05 Till Straumann <strauman@slac.stanford.edu>
+
+ PR 340/filesystem
+ * libcsupport/src/fcntl.c: Add missing _fcntl_r assumed to exist by
+ newlib.
+
+2003-02-05 Thomas Doerfler <Thomas.Doerfler@imd-systems.de>
+
+ PR 341/networking
+ * libnetworking/lib/ftpfs.c: Account for NULL at end of strings when
+ malloc()'ing memory.
+
+2003-02-05 Joel Sherrill <joel@OARcorp.com>
+
+ * libcsupport/include/sys/ioccom.h: Fix so not using internal RTEMS
+ types in libc code.
+
+2003-02-03 Till Straumann <strauman@slac.stanford.edu>
+
+ PR 339/filesystem
+ * libcsupport/src/chroot.c: Fix violation of FS node object copy
+ semantics.
+
+2003-02-03 Steven Johnson <sjohnson@neurizon.net>
+
+ PR 338/filesystem
+ * libfs/src/imfs/ioman.c: Fix reentrancy problem with
+ rtems_io_lookup_name() (API change).
+
+2003-02-03 Joel Sherrill <joel@OARcorp.com>
+
+ PR 338/filesystem
+ * sapi/include/rtems/io.h, sapi/src/io.c: Side-effect of fixing
+ reentrancy problem with rtems_io_lookup_name() (API change).
+ PR 338/filesystem
+ * libcsupport/src/unixlibc.c: Side-effect of fixing reentrancy problem
+ with rtems_io_lookup_name() (API change).
+
+2003-01-28 Joel Sherrill <joel@OARcorp.com>
+
+ * aclocal/version.m4: Updated to rtems-ss-20030128.
+ * libnetworking/Makefile.am: Add kern/kern_sysctl.c to Makefile.am so
+ networking tests build. This was subsequently reported as PR337 before I
+ committed the fix.
+
+2003-01-27 Till Straumann <strauman@SLAC.Stanford.edu>
+
+ * libnetworking/libc/getproto.c, libnetworking/libc/getprotoname.c:
+ modification to call getprotoent_static() if fopen() on /etc/protocols
+ fails.
+
+2003-01-27 Juan Zamorano <jzamora@fi.upm.es>
+
+ * posix/src/ptimer1.c: Correct problem which could lead to overflow in
+ time math.
+
+2003-01-27 Eugeny S. Mints <Eugeny.Mints@oktet.ru>
+
+ * libblock/src/blkdev.c: Per PR331 fix bug which is tripped by writing
+ 512 byte blocks to 512 byte aligned positions.
+
+2003-01-27 Dan Smisko <dan@balanced.com>
+
+ * libmisc/stackchk/check.c: Fix problem where _Objects_Get_information()
+ will dereference a null pointer when checking the interrupt stack. If
+ there's something at 0, you may be ok at run time but it is wrong.
+ * libmisc/monitor/mon-command.c: Correct two potential NULL references.
+
+2003-01-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * automake/local.am: Remove distclean-local. Remove PROJECT_TOOLS.
+
+2003-01-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * automake/compile.am: Remove CLEAN_DEPEND (Unused). Remove
+ CLOBBER_DEPEND (Unused).
+
+2003-01-15 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libnetworking/netinet/tcp_subr.c, libnetworking/netinet/udp_usrreq.c:
+ Add args to INP_INFO_RLOCK, INP_INFO_RUNLOCK, INP_LOCK, INP_UNLOCK
+ macros.
+
+2003-01-10 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libcsupport/Makefile.am: Eliminate OBJS.
+
+2003-01-10 Joel Sherrill <joel@OARcorp.com>
+
+ * score/src/objectmp.c: Corrected use of name parameter to reflect that
+ it is actually the name not a pointer to the name.
+ * rtems/src/msg.c, rtems/src/part.c, rtems/src/sem.c, rtems/src/tasks.c:
+ Correct object class control structure initialization for
+ multiprocessing configurations.
+ * libcsupport/include/rtems/libio.h: Rename __dev_t to __rtems_dev_t to
+ avoid conflict with GNU/Linux header files.
+
+2003-01-03 Till Straumann <strauman@slac.stanford.edu>
+
+ PR 303
+ * libcsupport/src/base_fs.c, libcsupport/src/getpwent.c,
+ libcsupport/src/privateenv.c: Fix violation of node_access copy
+ symantics.
+
+2003-01-03 Joel Sherrill <joel@OARcorp.com>
+
+ * posix/ChangeLog: Corrected entry for sysconf.c which did not include
+ PR.
+
+2003-01-03 Jitendra Vegiraju <jvegiraju@netscape.net>
+
+ * libnetworking/sys/queue.h: Fix alignment problem on ARM.
+
+2003-01-03 Jay Monkman <jtm@smoothsmoothie.com>
+
+ * posix/src/mqueueopen.c: Actually open the message queue descriptor so
+ it is available for others to use.
+
+2003-01-03 Eugeny S. Mints <Eugeny.Mints@oktet.ru>
+
+ * libblock/src/ata.c, libblock/src/bdbuf.c: Correct invocation of
+ rtems_task_mode() so the task's preemption mode setting is properly
+ maintained.
+ * libfs/src/dosfs/msdos_initsupp.c: Specify inherited priority as 0
+ since this is a FIFO queuing semaphore.
+
+2003-01-03 Chris Johns <cjohns@cybertec.com.au>
+
+ * libnetworking/Makefile.am: Added sys/linker_set.h.
+ * libnetworking/kern/Makefile.am: Added kern_mib.c and kern_sysctl.c.
+ * libnetworking/kern/uipc_socket.c: OID changed from KERN_SOMAXCONN to
+ KIPC_SOMAXCONN.
+ * libnetworking/kern/uipc_socket2.c: OID changed from KERN_MAXSOCKBUF to
+ KIPC_MAXSOCKBUF.
+ * libnetworking/net/if_ethersubr.c: FreeBSD 2.2.2 does not have a
+ _net_link node while 5.0 does.
+ * libnetworking/net/if_ppp.c: Removed the TEXT_SET define as these
+ macros are now implemented.
+ * libnetworking/net/rtsock.c: Enable sysctl support plus fix the bug
+ with the lastest FreeBSD sysctl header file.
+ * libnetworking/netinet/icmp_var.h: FreeBSD 2.2.2 does not have a
+ _net_inet_icmp node while 5.0 does.
+ * libnetworking/netinet/if_ether.c: FreeBSD 2.2.2 does not have a
+ _net_link_ether node while 5.0 does.
+ * libnetworking/netinet/igmp_var.h: FreeBSD 2.2.2 does not have a
+ _net_inet_igmp node while 5.0 does.
+ * libnetworking/netinet/in_pcb.c: Fixed the arguments to the sysctl
+ call. Add inp_gencnt and ipi_count. These are used when listing
+ connections.
+ * libnetworking/netinet/in_pcb.h: Added counters to aid the listing of
+ connections.
+ * libnetworking/netinet/in_var.h: Provide the _net_inet_ip and
+ _net_inet_raw nodes.
+ * libnetworking/netinet/ip_fw.c: Disable the firewall sysctl calls.
+ * libnetworking/netinet/tcp_subr.c: Merge tcp_pcblist from the lastest
+ FreeBSD source.
+ * libnetworking/netinet/tcp_var.h: Add structures needed by net-snmp to
+ list connections.
+ * libnetworking/netinet/udp_usrreq.c: Merged udp_pcblist from the
+ lastest FreeBSD source.
+ * libnetworking/netinet/udp_var.h: Added the sysctl id UDPCTL_PCBLIST.
+ Used by net-snmp.
+ * libnetworking/rtems_glue.c: Call sysctl_register_all when initialising
+ the network stack to register all the sysctl calls. These are in the
+ special sections and required an updated linker script.
+ * libnetworking/rtems/rtems_syscall.c: Add the sysctl call.
+ * libnetworking/sys/kernel.h: Use the lastest FreeBSD method of handling
+ sysctl structures. This now held in the sys/linker_set.h file.
+ * libnetworking/sys/queue.h: This is from the lastest FreeBSD code with
+ the circular code merged back in as it is not used in the lastest
+ FreeBSD kernel.
+ * libnetworking/sys/sysctl.h: The lastest sysctl. This was needed to use
+ with the new linker set method. The FreeBSD 2.2.2 version has asm hacks.
+ The lastest version of the FreeBSD does not have these hacks. It uses
+ gcc attribute directives.
+
+2002-12-26 Till Straumann <strauman@slac.stanford.edu
+
+ * libcsupport/src/fchdir.c: PR302 fix violation of FS node object copy
+ semantics.
+
+2002-12-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * automake/compile.am: Remove $(RTEMS_BSP_CFLAGS).
+
+2002-12-18 Eric Norum <eric.norum@usask.ca>
+
+ * libnetworking/Makefile.am: Include netinet sources.
+
+2002-12-14 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * wrapup/Makefile.am: Fix path to libxdr and librpc (Another typo in
+ from the 2002-12-12 patch).
+
+2002-12-13 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * wrapup/Makefile.am: Fix typo in yesterday's patch.
+
+2002-12-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * wrapup/Makefile.am: Don't create $ARCH. Use install-data-local to
+ install librtemscpu.a.
+ * wrapup/Makefile.am: Add libmisc.
+ * configure.ac: Add AC_CONFIG_SUBDIR(libmisc).
+ * itron/Makefile.am, posix/Makefile.am: Don't create $ARCH as
+ side-effect of compilation.
+ * score/Makefile.am: Don't create $ARCH.
+ * sapi/Makefile.am: Don't create $ARCH as side-effect of compilation.
+ * rtems/Makefile.am: Don't create $ARCH as side-effect of compilation.
+ Re-order all-local.
+ * libmisc/configure.ac: Require autoconf-2.57+automake-1.7.2.
+ * libmisc/capture/Makefile.am: Eliminate C_O_FILES.
+ * libmisc/cpuuse/Makefile.am, libmisc/devnull/Makefile.am,
+ libmisc/dummy/Makefile.am, libmisc/dumpbuf/Makefile.am,
+ libmisc/monitor/Makefile.am, libmisc/rtmonuse/Makefile.am,
+ libmisc/serdbg/Makefile.am, libmisc/shell/Makefile.am,
+ libmisc/stackchk/Makefile.am, libmisc/untar/Makefile.am: Ditto.
+ * libmisc/mw-fb/Makefile.am: Eliminate C_O_FILES. Eliminate SRCS. Moving
+ libmisc from rtems/c/src to rtems/cpukit.
+ * libmisc/Makefile.am: Reflect new path.
+ * libmisc/configure.ac: Reflect new path. Use RTEMS_ENV_RTEMSCPU
+ instead of RTEMS_ENV_RTEMSBSP. Remove RTEMS_PROJECT_ROOT.
+ * libmisc/capture/Makefile.am: Reflect new path. Remove OBJS from
+ all-local.
+ * libmisc/cpuuse/Makefile.am, libmisc/devnull/Makefile.am,
+ libmisc/dummy/Makefile.am, libmisc/dumpbuf/Makefile.am,
+ libmisc/monitor/Makefile.am, libmisc/mw-fb/Makefile.am,
+ libmisc/rtmonuse/Makefile.am, libmisc/serdbg/Makefile.am,
+ libmisc/shell/Makefile.am, libmisc/stackchk/Makefile.am,
+ libmisc/untar/Makefile.am: Ditto.
+ * libmisc/wrapup/Makefile.am: Reflect new path.
+ * libblock/Makefile.am: Eliminate C_O_FILES. Eliminate SRCS.
+ * libfs/src/imfs/Makefile.am: Eliminate C_O_FILES.
+ * libfs/src/dosfs/Makefile.am: Ditto.
+ * libnetworking/Makefile.am: Merge-in kern/Makefile.am, net/Makefile.am,
+ netinet/Makefile.am, netinet/Makefile.am, nfs/Makefile.am,
+ rtems/Makefile.am.
+ * libnetworking/kern/Makefile.am, libnetworking/net/Makefile.am,
+ libnetworking/netinet/Makefile.am, libnetworking/nfs/Makefile.am,
+ libnetworking/rtems/Makefile.am: Remove.
+ * libnetworking/wrapup/Makefile.am: Reflect changes above.
+ * libnetworking/configure.ac: Ditto.
+
+2002-12-11 Vladimir Nesic <vnesic@dkts.co.yu>
+
+ * posix/src/cancelrun.c, posix/src/cleanuppop.c: Get the last real node
+ not the permanent null last node.
+
+2002-12-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libnetworking/kern/Makefile.am: Remove C_O_FILES. Don't let all-local
+ depend on $OBJS).
+ * libnetworking/lib/Makefile.am, libnetworking/libc/Makefile.am,
+ libnetworking/net/Makefile.am, libnetworking/netinet/Makefile.am,
+ libnetworking/nfs/Makefile.am, libnetworking/rtems/Makefile.am: Ditto.
+
+2002-12-10 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libmisc/configure.ac: Remove RTEMS_CHECK_CUSTOM_BSP.
+ * libmisc/capture/Makefile.am, libmisc/cpuuse/Makefile.am,
+ libmisc/devnull/Makefile.am, libmisc/dummy/Makefile.am,
+ libmisc/dumpbuf/Makefile.am, libmisc/monitor/Makefile.am,
+ libmisc/mw-fb/Makefile.am, libmisc/rtmonuse/Makefile.am,
+ libmisc/serdbg/Makefile.am, libmisc/shell/Makefile.am,
+ libmisc/stackchk/Makefile.am, libmisc/untar/Makefile.am,
+ libmisc/wrapup/Makefile.am: Don't include @RTEMS_BSP@.cfg.
+
+2002-12-09 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * aclocal/env-rtemsbsp.m4, aclocal/env-rtemscpu.m4: Remove
+ RTEMS_CHECK_CUSTOM_BSP.
+ * aclocal/check-bsps.m4: Remove.
+ * wrapup/Makefile.am: Remove *_OBJS, use LIBS+= instead.
+ * configure.ac: Require autoconf >= 2.54, automake-1.7.2.
+ * wrapup/Makefile.am, configure.ac: Reflect changes to score/.
+ * wrapup/Makefile.am, configure.ac: Reflect changes to sapi/.
+ * configure.ac: Add AC_SUBST(INLINEdir).
+ * wrapup/Makefile.am, configure.ac: Reflect changes to rtems/.
+ * wrapup/Makefile.am: Reflect changes to posix/. Reflect changes to
+ itron/.
+ * itron/include/Makefile.am, itron/inline/Makefile.am,
+ itron/macros/Makefile.am, itron/src/Makefile.am: Remove.
+ * itron/Makefile.am: Merge-in removed Makefile.ams.
+ * itron/configure.ac: Reflect changes above.
+ * posix/include/Makefile.am, posix/inline/Makefile.am,
+ posix/macros/Makefile.am, posix/src/Makefile.am: Remove.
+ * posix/Makefile.am: Merge-in removed Makefile.ams.
+ * posix/configure.ac: Reflect changes above.
+ * score/Makefile.am: Fix macro-file installation.
+ * score/Makefile.am: Move include/rtems/score/cpuopts.h to STD_H_FILES.
+ * score/include/Makefile.am, score/inline/Makefile.am,
+ score/macros/Makefile.am, score/src/Makefile.am: Remove.
+ * score/Makefile.am: Merge-in removed Makefile.ams.
+ * sapi/include/Makefile.am, sapi/inline/Makefile.am,
+ sapi/macros/Makefile.am, sapi/src/Makefile.am: Remove.
+ * sapi/Makefile.am: Merge-in removed Makefile.ams.
+ * rtems/include/Makefile.am, rtems/inline/Makefile.am,
+ rtems/macros/Makefile.am, rtems/src/Makefile.am: Remove.
+ * rtems/Makefile.am: Merge-in removed Makefile.ams.
+
+2002-12-06 Vladimir Nesic <vnesic@dkts.co.yu>
+
+ * posix/inline/rtems/posix/cond.inl, posix/macros/rtems/posix/cond.inl:
+ Implemented PTHREAD_COND_INITIALIZER support. Vladimir implemented the
+ inline version and Joel adapted it to the macro version.
+
+2002-12-06 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * automake/compile.am: Rework *FLAGS, AM_*FLAGS handling.
+ * automake/multilib.am: Don't include @RTEMS_BSP@.cfg.
+ * automake/compile.am: Remove hard-coded CFLAGS_PROFILE_V. Add
+ autoconf-supplied CPU_CFLAGS, CFLAGS_OPTIMIZE_V, CFLAGS_DEBUG_V,
+ CFLAGS_PROFILE_V. Hard-code RTEMS_CFLAGS_PROFILE = -pg.
+ * aclocal/prog-cc.m4: Sync with toplevel/aclocal/prog-cc.m4. Remove
+ GCCSED.
+ * aclocal/env-rtemsbsp.m4: Add AC_ARG_VAR for CPU_CFLAGS,
+ CFLAGS_OPTIMIZE_V, CFLAGS_DEBUG_V, CFLAGS_PROFILE_V.
+ * aclocal/rtems-flags.m4: New.
+ * libcsupport/configure.ac: Add various checks to enhance portability.
+ * libcsupport/src/termios.c: Reflect changes to configure.ac.
+
+2002-12-06 Joel Sherrill <joel@OARcorp.com>
+
+ * libcsupport/src/malloc.c: Fixed code that incorrected did a disable
+ dispatch instead of locking and unlocking the allocator mutex.
+
+2002-12-02 Joel Sherrill <joel@OARcorp.com>
+
+ * posix/include/rtems/posix/timer.h, posix/src/keygetspecific.c,
+ posix/src/posixtimespecsubtract.c, posix/src/ptimer1.c,
+ posix/src/semunlink.c: Added casts to eliminate warnings on 16-bit
+ targets like the h8300.
+ * score/include/rtems/score/object.h, score/include/rtems/score/tod.h,
+ rtems/include/rtems/rtems/support.h: Added casts to eliminate warnings
+ on 16 bit targets like the h8300.
+ * libmisc/stackchk/check.c: Better handling of task name.
+ * libblock/src/bdbuf.c: Added cast to remove warning.
+ * libfs/src/dosfs/fat.h, libfs/src/dosfs/msdos.h: Added casts to remove
+ warnings on 16 bit targets like the h8300.
+ * libcsupport/include/rtems/libio.h: Internally use a union of an
+ unsigned64 and major/minor device so we don't get into trouble shifting.
+ The h8300 seemed to be impossible to remove warnings otherwise.
+ Eventually the structure definition of a dev_t might be better anyway.
+ * libcsupport/include/sys/ioccom.h: Added casts to remove warnings on 16
+ bit targets.
+
+2002-11-29 Eric Norum <eric.norum@usask.ca>
+
+ PR 316
+ * posix/src/sysconf.c: Add support for _SC_GETPW_R_SIZE_MAX. Return
+ error rather than panic if argument is unsupported.
+
+2002-11-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * automake/compile.am: Remove CFLAGS_DEBUG_OPTIMIZE_V (Unused).
+ * aclocal/sysv-ipc.m4: Adaptation to autoconf-2.5x.
+ * aclocal/check-newlib.m4: Sync with ../aclocal/check-newlib.m4.
+ * itron/configure.ac: Cosmetical fixes.
+ * itron/configure.ac: Fix package name.
+ * posix/configure.ac: Cosmetical fixes.
+ * posix/configure.ac, librpc/configure.ac, libblock/configure.ac: Fix
+ package name.
+ * libfs/configure.ac: Cosmetical fixes.
+ * libfs/configure.ac: Fix package name.
+ * libcsupport/configure.ac: Cosmetical fixes.
+ * libcsupport/configure.ac, libnetworking/configure.ac: Fix package name.
+
+2002-11-18 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * include/rtems/libio_.h: Remove.
+ * libcsupport/configure.ac: Check for sys/cdefs.h, Add NEED_SYS_CDEFS_H.
+ Add check for CHAR_BIT.
+ * libcsupport/Makefile.am: Conditionally install sys/cdefs.h iff using
+ newlib or if the host does not provide sys/cdefs.h (Fixes Linux/posix).
+ * libcsupport/configure.ac: Remove -ansi -fasm. Add checks to diagnose
+ potential system header conflicts.
+ * libcsupport/Makefile.am: Unconditionally install sys/cdefs.h.
+ * libnetworking/Makefile.am: Merge-in HEADER-handling from
+ net/Makefile.am, netinet/Makefile.am, nfs/Makefile.am.
+ * libnetworking/net/Makefile.am, libnetworking/netinet/Makefile.am,
+ libnetworking/nfs/Makefile.am: Remove *_HEADERS.
+
+2002-11-18 Joel Sherrill <joel@OARcorp.com>
+
+ * aclocal/version.m4: Updated to rtems-ss-20021118.
+
+2002-11-15 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * include/rtems/userenv.h: Rely upon <limits.h> for
+ _POSIX_LOGIN_NAME_MAX.
+ * aclocal/prog-cc.m4: Acknowledge configuration-time CFLAGS.
+ * automake/compile.am: Acknowledge configuration-time CFLAGS. Remove
+ CFLAGS_DEFAULT.
+ * libmisc/monitor/mon-commands.c: Removed warnings for RTEMS_UNIX.
+ * libblock/src/diskdevs.c: Include <unistd.h> to remove warning.
+ * libnetworking/Makefile.am: Merge-in arpa/Makefile.am,
+ machine/Makefile.am, sys/Makefile.am, vm/Makefile.am. Add . to SUBDIRS.
+ * libnetworking/arpa/Makefile.am, libnetworking/machine/Makefile.am,
+ libnetworking/sys/Makefile.am, libnetworking/vm/Makefile.am: Remove.
+ * libnetworking/configure.ac: Reflect changes above.
+
+2002-11-14 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libmisc/capture/Makefile.am, libmisc/serdbg/Makefile.am: Remove
+ AUTOMAKE_OPTIONS.
+ * libmisc/serdbg/serdbgio.c: Add #include <unistd.h>.
+ * libmisc/shell/Makefile.am, libmisc/wrapup/Makefile.am: Add
+ RTEMS_LIBSHELL conditional.
+ * libmisc/configure.ac: Check for stdio assignments. Add RTEMS_LIBSHELL
+ conditional.
+
+2002-11-14 Joel Sherrill <joel@OARcorp.com>
+
+ * score/macros/rtems/score/object.inl: Keep consistent with inline
+ version.
+
+2002-11-13 Paul Whitfield <paulw@microsol.iinet.net.au>
+
+ * rtems/src/regionreturnsegment.c: When RTEMS_REGION_SHRED_ON_FREE is
+ set, there should have been an & in front of size.
+
+2002-11-11 Joel Sherrill <joel@OARcorp.com>
+
+ * aclocal/version.m4: Updated to rtems-ss-20021111.
+
+2002-11-07 <strauman@slac.stanford.edu>
+
+ * libcsupport/src/mount.c: Per PR297, correct fs_mountme failure paths.
+
+2002-11-06 Chris Johns <ccj@acm.org>
+
+ * libnetworking/sys/select.h: Add C++ to C external.
+
+2002-11-04 Joel Sherrill <joel@OARcorp.com>
+
+ * librpc/src/rpc/pmap_rmt.c: Removed warnings.
+
+2002-11-02 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libnetworking/kern/uipc_mbuf.c: Comment out m0 in m_copydata to
+ suppress warning.
+
+2002-11-01 Joel Sherrill <joel@OARcorp.com>
+
+ * ChangeLog, posix/ChangeLog: Corrected.
+ * libmisc/stackchk/check.c: Removed warnings.
+ * libcsupport/ChangeLog, libnetworking/ChangeLog: Corrected.
+
+2002-11-01 Eric Norum <eric.norum@usask.ca>
+
+ * libnetworking/nfs/bootp_subr.c, libnetworking/rtems/rtems_bsdnet.h,
+ libnetworking/rtems/rtems_glue.c: Till Straumann's patch (PR295) to use
+ bootp option 129 to get command line string. Till Straumann's patch to
+ change inet_ntoa->inet_ntop.
+
+2002-10-31 Joel Sherrill <joel@OARcorp.com>
+
+ * score/src/heapgetinfo.c: Fixed comment.
+ * score/src/mpci.c: Removed warning.
+ * rtems/src/regiongetinfo.c: Corrected return value check.
+ * libmisc/stackchk/check.c: Removed warning.
+ * librpc/src/rpc/svc_run.c: Remove warning.
+ * libcsupport/src/mallocfreespace.c: Corrected sense of status check to
+ match change inside RTEMS.
+ * libcsupport/src/newlibc.c: Removed warning.
+ * libnetworking/libc/rcmd.c, libnetworking/netinet/in_cksum_arm.c:
+ Removed warnings.
+
+2002-10-30 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * aclocal/check-bsp-cache.m4: Remove.
+
+2002-10-30 Eric Norum <eric.norum@usask.ca>
+
+ * include/rtems/bspIo.h: Add vprintk function for kernel printing from
+ routines which have already obtained the va_list pointer.
+ * posix/src/psignal.c: Fix counting problem which resulted in too many
+ entries being in the POSIX signals default behavior table.
+ * posix/src/psignal.c: Reflect changes to signal names in newlib.
+ * libcsupport/src/printk.c: Add vprintk function for kernel printing
+ from routines which have already obtained the va_list pointer.
+
+2002-10-29 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * aclocal/multilib.m4: Remove RTEMS_ENABLE_MULTILIB_MASTER.
+
+2002-10-28 Joel Sherrill <joel@OARcorp.com>
+
+ * score/src/threadhandler.c: Prototype _init() and _main() if they are
+ needed to avoid a warning.
+ * rtems/src/timerserver.c: Add useless return to avoid warning.
+ * librpc/src/rpc/clnt_tcp.c, librpc/src/rpc/clnt_udp.c,
+ librpc/src/rpc/pmap_rmt.c, librpc/src/rpc/rtime.c,
+ librpc/src/rpc/svc_tcp.c: Add include of <sys/select.h> to eliminate
+ warning.
+ * librpc/src/rpc/rpcdname.c: Add prototype of getdomainname() to
+ eliminate warning.
+ * libcsupport/include/rtems/libio.h: Change
+ rtems_filesystem_node_types_t from enumeration to int to eliminate
+ warnings when values are overridden.
+ * Pass to eliminate warnings.
+ * libnetworking/kern/uipc_mbuf.c: Conditional SYSINIT() usage on
+ __rtems__. Fix return statement without a value.
+ * libnetworking/lib/ftpfs.c: read and write filesystem routines return
+ ssize_t.
+ * libnetworking/lib/syslog.c: Add include of <string.h> to eliminate
+ warning.
+ * libnetworking/lib/tftpDriver.c: read and write filesystem routines
+ return ssize_t.
+ * libnetworking/libc/gethostbydns.c: Prototype abort().
+ * libnetworking/libc/inet_ntoa.c: Prototype strcpy().
+ * libnetworking/libc/rcmd.c: Add include of <sys/select.h>.
+ * libnetworking/net/if_loop.c: Turn token at end of endif to comment.
+ * libnetworking/net/rtsock.c, libnetworking/nfs/bootp_subr.c:
+ Conditional SYSINIT() usage on __rtems__.
+ * libnetworking/rtems/rtems_bootp.c: Add include of
+ <rtems/rtems_bsdnet_internal.h>.
+ * libnetworking/rtems/rtems_bsdnet_internal.h: Added prototypes for
+ memcpy() and memset() since the BSD code tries to avoid using libc .h
+ files since it is used to being in the kernel.
+ * libnetworking/rtems/rtems_syscall.c: read and write filesystem
+ routines return ssize_t.
+
+2002-10-28 Eugeny S. Mints <Eugeny.Mints@oktet.ru>
+
+ * libblock/*: Added ATA support.
+ * libblock/include/rtems/blkdev.h: Added last IO status.
+ * libblock/include/rtems/ata.h, libblock/include/rtems/ata_internal.h,
+ libblock/include/rtems/ide_part_table.h, libblock/src/ata.c,
+ libblock/src/ide_part_table.c: New files.
+
+2002-10-26 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libmisc/monitor/mon-command.c: Don't build rtems_monitor_line_editor
+ for RTEMS_UNIX to avoid gcc warning.
+
+2002-10-25 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac, itron/configure.ac, posix/configure.ac,
+ librpc/configure.ac, libblock/configure.ac, libfs/configure.ac,
+ libcsupport/configure.ac, libnetworking/configure.ac: Add nostdinc to
+ AM_INIT_AUTOMAKE.
+ * libnetworking/Makefile.am: Remove bogus reference to CHANGELOG.
+
+2002-10-24 Fabrizio Pirovano <pirovano.thysys@tiscalinet.it>
+
+ * libmisc/capture/capture.c, libmisc/monitor/mon-manager.c,
+ libmisc/stackchk/check.c: Patch to remove problems introduced by object
+ name rework.
+
+2002-10-24 <strauman@slac.stanford.edu>
+
+ * libcsupport/src/eval.c: Per PR293, added freenode calls for evaluate
+ link failures.
+
+2002-10-23 <strauman@slac.stanford.edu>
+
+ PR 290
+ * src/mount.c: Add check for ops->node_type_h.
+ PR 291
+ * src/mknod.c: Remove erroneous call to freenod.
+
+2002-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * .cvsignore, itron/.cvsignore, posix/.cvsignore, libmisc/.cvsignore,
+ librpc/.cvsignore, libblock/.cvsignore, libfs/.cvsignore,
+ libcsupport/.cvsignore, libnetworking/.cvsignore: Reformat. Add
+ autom4te*cache. Remove autom4te.cache.
+
+2002-10-21 Joel Sherrill <joel@OARcorp.com>
+
+ * aclocal/version.m4: Updated to rtems-20021021-test.
+
+2002-10-13 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libnetworking/net/if_ethersubr.c: Add comments to #endif NETATALK to
+ stop gcc from complaining.
+
+2002-10-07 Joel Sherrill <joel@OARcorp.com>
+
+ * aclocal/version.m4: Updated to rtems-ss-20021007.
+
+2002-10-07 Eric Norum <eric.norum@usask.ca>
+
+ * libnetworking/netinet/tcp_var.h: Corrected typo in ARM alignment patch
+ which broke all other ports.
+
+2002-10-04 Joel Sherrill <joel@OARcorp.com>
+
+ * aclocal/version.m4: Updated to rtems-JUNK.
+ * aclocal/version.m4: Updated to rtems-ss-20021004.
+
+2002-10-04 Jay Monkman <jtm@smoothsmoothie.com>
+
+ * libnetworking/netinet/in_cksum.c, libnetworking/netinet/ip_icmp.h,
+ libnetworking/netinet/ip_input.c, libnetworking/netinet/tcp_input.c,
+ libnetworking/netinet/tcp_subr.c, libnetworking/netinet/tcp_var.h,
+ libnetworking/sys/queue.h: Address alignment requirements for the ARM.
+ * libnetworking/rtems/rtems_glue.c: Add IP aliasing ioctls SIOCAIFADDR
+ and SIOCDIFADDR.
+
+2002-10-02 Joel Sherrill <joel@OARcorp.com>
+
+ * libnetworking/kern/uipc_socket.c: Make sure that small non-zero delays
+ work. Suggested cleanup from Eric Norum.
+
+2002-10-02 Jennifer Averett <jennifer@OARcorp.com>
+
+ * libfs/src/imfs/memfile.c: Fixed case where last close of unlinked file
+ did not remove the resources associated with that file. Reported by
+ Till Straumann <strauman@slac.stanford.edu> on the mailing list.
+
+2002-10-02 Eric Norum <eric.norum@usask.ca>
+
+ * libcsupport/src/getpwent.c: Per PR283, reimplement to address
+ reentrancy problems.
+ * libcsupport/src/getgrent.c: Removed as functionality is now just a
+ wrapper for common routines in src/getpwent.c.
+ * libcsupport/Makefile.am: Reflect file removal.
+ * libnetworking/rtems/mkrootfs.c: As part of PR283, remove redundant
+ code that creates /etc/passwd and /etc/group.
+
+2002-09-16 Joel Sherrill <joel@OARcorp.com>
+
+ * libnetworking/netinet/Makefile.am, libnetworking/netinet/udp_usrreq.c:
+ Back off some of the IP_FORWARD patch as it appears to not compile in
+ the current tree.
+
+2002-09-14 Vyacheslav V. Burdjanadze <wr@zelax.ru>
+
+ * libnetworking/kern/uipc_mbuf.c, libnetworking/sys/mbuf.h,
+ libnetworking/netinet/udp_usrreq.c: Add optional UDP broadcast
+ forwarding support.
+ * libnetworking/netinet/Makefile.am: Defined FORWARD_PROTOCOL to enabled
+ UDP broadcast forwarding.
+
+2002-09-14 Joel Sherrill <joel@OARcorp.com>
+
+ * posix/src/psignal.c: Remove duplication from rtems/posix/psignal.h.
+ * rtems/src/dpmemcreate.c, rtems/src/dpmemident.c,
+ rtems/src/msgqcreate.c, rtems/src/msgqident.c, rtems/src/partcreate.c,
+ rtems/src/partident.c, rtems/src/ratemoncreate.c,
+ rtems/src/ratemonident.c, rtems/src/regioncreate.c,
+ rtems/src/regionident.c, rtems/src/semcreate.c, rtems/src/semident.c,
+ rtems/src/taskcreate.c, rtems/src/taskident.c, rtems/src/timercreate.c,
+ rtems/src/timerident.c: Added casts to Objects_Name to eliminate
+ warnings.
+ * libfs/src/dosfs/fat.c, libfs/src/imfs/deviceio.c,
+ libfs/src/imfs/imfs.h, libfs/src/imfs/imfs_directory.c,
+ libfs/src/imfs/imfs_fchmod.c, libfs/src/imfs/memfile.c: Eliminated
+ warnings. A lot of this focus was on changing read and write entry
+ points to return ssize_t as read(2) and write(2) now do.
+ * libcsupport/include/rtems/libio.h: Change rtems_filesystem_read_t and
+ rtems_filesystem_write_t to return ssize_t to match read(2) and write(2)
+ respectively.
+ * libnetworking/kern/uipc_socket.c: Fix case on SO_RCVTIMEO and
+ SO_SNDTIMEO where conversion into ticks can result in a 0 ticks timeout
+ which is the same as requesting no timeout. Reported by Sergei Organov
+ <osv@javad.ru>.
+
+2002-09-14 Eric Norum <eric.norum@usask.ca>
+
+ * libcsupport/src/readdir_r.c: New file.
+ * libcsupport/Makefile.am: Reflect above.
+
+2002-09-07 Joel Sherrill <joel@OARcorp.com>
+
+ * libblock/src/bdbuf.c: Previous fix for PR282 regressed mutex changes.
+
+2002-09-06 Alexander M. Kukuta <kam@oktet.ru>
+
+ * libblock/src/bdbuf.c: Per PR282, correct problem in function
+ rtems_bdbuf_read() where device ioctl() is called with the logical
+ device number used instead of corresponding physical device number.
+
+2002-09-02 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libnetworking/netinet/in_cksum.c: #include <string.h> for puts in
+ generic routines.
+
+2002-08-30 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libmisc/shell/shell.c: #include <time.h>.
+ * libmisc/wrapup/Makefile.am: Eliminate LIBNAME.
+
+2002-08-30 Joel Sherrill <joel@OARcorp.com>
+
+ * sapi/src/io.c: Fixed some spacing.
+
+2002-08-22 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * score/include/Makefile.am: Remove cpuopt.h generation.
+ * configure.ac: Correct package name. Don't build ada if POSIX is
+ disabled. Generate cpuopt.h on the fly, filter out autoconf-2.53 PACKAGE
+ crap.
+ * aclocal/prog-gnat.m4: New.
+ * configure.ac: Add ada subdir handling.
+
+2002-08-21 Joel Sherrill <joel@OARcorp.com>
+
+ * posix/src/adjtime.c: New file -- adjtime() support required by the
+ Network Time Protocol (NTP) port to RTEMS.
+ * posix/src/Makefile.am: Modified to reflect above.
+
+2002-08-20 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * aclocal/bsp-alias.m4: Remove.
+
+2002-08-20 Joel Sherrill <joel@OARcorp.com>
+
+ * librpc/src/xdr/xdr_stdio.c: Per PR268, add include of <netinet/in.h>
+ to avoid warning on ntohl().
+
+2002-08-20 Eric Norum <eric.norum@usask.ca>
+
+ * libnetworking/rtems/rtems_glue.c: Per PR270, the BSD network code
+ expects that the value of the number of seconds since boot is non-zero.
+ The RTEMS network initialization code assures this by waiting for a
+ second. A more efficient technique is to simply wait until the number
+ of seconds since boot is non-zero.
+
+2002-08-14 Joel Sherrill <joel@OARcorp.com>
+
+ * score/macros/rtems/score/coremsg.inl: Add <string.h> to remove warning.
+ * score/src/threadidlebody.c: Add return 0 to avoid warning.
+
+2002-08-12 Eric Norum <eric.norum@usask.ca>
+
+ * libcsupport/src/write.c (_write_r): Change prototype to match newlib's
+ reent.h.
+
+2002-08-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libmisc/capture/Makefile.am, libmisc/cpuuse/Makefile.am,
+ libmisc/devnull/Makefile.am, libmisc/dummy/Makefile.am,
+ libmisc/dumpbuf/Makefile.am, libmisc/monitor/Makefile.am,
+ libmisc/mw-fb/Makefile.am, libmisc/rtmonuse/Makefile.am,
+ libmisc/serdbg/Makefile.am, libmisc/shell/Makefile.am,
+ libmisc/stackchk/Makefile.am, libmisc/untar/Makefile.am: Use .$(OBJEXT)
+ instead of .o.
+ * librpc/src/rpc/rtems_portmapper.c: include <stdlib.h> (Get rid of
+ gcc31 warnings about abort/exit).
+
+2002-08-09 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libmisc/shell/Makefile.am: Remove shell.h from EXTRA_DIST.
+
+2002-08-09 Joel Sherrill <joel@OARcorp.com>
+
+ * posix/src/cancelrun.c: Remove check for PTHREAD_CANCELED not being
+ defined to ensure that newlib patch includes it.
+ * libnetworking/libc/getservent.c: Per PR265, add #include
+ <netinet/in.h> for ntohl() function.
+
+2002-08-07 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Add missing ',' to librpc activation. Add
+ AC_MSG_CHECKING/AC_MSG_RESULT.
+ * aclocal/check-networking.m4: Let AC_MSG_CHECKING refer to CPU.
+ * configure.ac: Fix bug in librpc activation, having introduced by
+ yesterday's patch.
+
+2002-08-07 Joel Sherrill <joel@OARcorp.com>
+
+ * aclocal/version.m4: Updated to rtems-ss-20020807.
+ * libnetworking/netinet/in.h: Per PR263, added include of
+ <machine/endian.h> to <netinet/in.h> so it includes prototypes of
+ ntohl() family of routines.
+
+2002-08-07 Chris Johns <ccj@acm.org>
+
+ * score/src/coretodset.c: Correct calculation of ticks until next
+ section boundary. It was incorrectly based upon current time not the
+ time that is being set.
+
+2002-08-06 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * aclocal/env-rtemsbsp.m4: Remove RTEMS_CONFIG_PER_BSP.
+ * aclocal/env-rtemscpu.m4: Remove RTEMS_CONFIG_PER_BSP. Use AS_IF
+ instead of if/then/else/fi.
+
+2002-08-06 Joel Sherrill <joel@OARcorp.com>
+
+ * configure.ac, librpc/configure.ac: or32 does not currently support
+ librpc.
+
+2002-08-01 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * wrapup/Makefile.am: Use librtems.a.
+ * wrapup/Makefile.am: Use libsapi.a.
+ * sapi/src/Makefile.am: Add libsapi.a.
+ * rtems/src/Makefile.am: Add librtems.a.
+ * libnetworking/wrapup/Makefile.am: Don't install.
+
+2002-08-01 Joel Sherrill <joel@OARcorp.com>
+
+ * libmisc/cpuuse/cpuuse.c (CPU_usage_Dump) : Corrected so it honors when
+ an object name is raw versus being a string.
+ * libnetworking/machine/param.h, libnetworking/sys/syslimits.h: In the
+ continued effort to eliminate .h conflicts between newlib and RTEMS,
+ these were moved to newlib.
+ * libnetworking/machine/Makefile.am, libnetworking/sys/Makefile.am:
+ Reflect above.
+
+2002-07-31 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * wrapup/Makefile.am: Use libscore.a.
+ * aclocal/canonicalize-tools.m4, automake/lib.am: Remove LD.
+ * Makefile.am: Put preinstall-stamp into CLEANFILES.
+ * aclocal/rtems-top.m4: Use with_project_root and MULTIBUILDTOP to
+ compose PROJECT_TOPdir (Fixes hppa1.1/genoffset problem).
+ * wrapup/Makefile.am: LIBBLOCK_OBJS = ../libblock/$(ARCH)/libblock.a.
+ * posix/src/mqueuecreatesupp.c: #include <stdlib.h> (malloc).
+ * score/src/Makefile.am: Build into libscore.a.
+ * libblock/Makefile.am: Merge src/Makefile.am.
+ * libblock/src/Makefile.am: Remove.
+ * libblock/configure.ac: Remove src/Makefile.am.
+ * libfs/wrapup/Makefile.am, libfs/wrapup/.cvsignore: Remove.
+ * libfs/Makefile.am: Remove wrapup SUBDIR.
+ * libfs/configure.ac: Remove wrapup/Makefile.
+
+2002-07-31 Joel Sherrill <joel@OARcorp.com>
+
+ * aclocal/rtems-cpu-subdirs.m4: Removed the or16 port was just a stub
+ and only the OR32 port is getting worked on.
+
+2002-07-30 Joel Sherrill <joel@OARcorp.com>
+
+ * libmisc/stackchk/check.c: Don't reference the RTEMS allocated
+ interrupt stack if the port doesn't configure using it.
+ * libcsupport/include/sys/utime.h: Removed as file is now part of the
+ RTEMS newlib support.
+ * libcsupport/Makefile.am: Reflect above.
+ * libcsupport/include/rtems/termiostypes.h: Avoid use of __P.
+ * libnetworking/sys/param.h: Removed as a simpler version of this file
+ is now part of the RTEMS newlib support.
+ * libnetworking/sys/Makefile.am: Modified to reflect above.
+ * libnetworking/machine/types.h: Removed as a simpler version of this
+ file is now part of the RTEMS newlib support.
+ * libnetworking/machine/Makefile.am, libnetworking/machine/endian.h,
+ libnetworking/nfs/bootp_subr.c,
+ libnetworking/rtems/rtems_bsdnet_internal.h,
+ libnetworking/sys/Makefile.am, libnetworking/sys/systm.h: Minor
+ modifications to use the simpler machine/types.h. Mostly more complete
+ sets of #include's to account for machine/types.h no longer doing this.
+
+2002-07-30 Jay Monkman <jtm@smoothsmoothie.com>
+
+ * libnetworking/netinet/in_cksum.c,
+ libnetworking/netinet/in_cksum_arm.c: Added ARM in_cksum support.
+
+2002-07-29 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * librpc/src/rpc/Makefile.am: Merge src/rpc/PSD.doc/Makefile.am.
+ * librpc/include/Makefile.am: Merge include/rpc/Makefile.am. Merge
+ include/rpcsvc/Makefile.am.
+ * librpc/include/rpc/Makefile.am, librpc/include/rpcsvc/Makefile.am,
+ librpc/src/rpc/PSD.doc/Makefile.am: Remove.
+ * librpc/configure.ac: Remove duplicate AC_PROG_RANLIB. Remove
+ include/rpc/Makefile. Remove include/rpcsvc/Makefile. Remove
+ src/rpc/PSD.doc/Makefile.
+
+2002-07-26 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * automake/compile.am: Use .$(OBJEXT) instead of .o.
+
+2002-07-24 Joel Sherrill <joel@OARcorp.com>
+
+ * libmisc/wrapup/Makefile.am: Temporarily don't include serdbg since it
+ causes some BSPs to not link "main(){}" as required by autoconf.
+ * libnetworking/sys/select.h: Add a prototype of select() to avoid
+ warnings. In particular a C++ application using select() required a
+ prototype.
+ * libnetworking/Makefile.am, libnetworking/libc/res_send.c: Do not
+ install or use <poll.h> since RTEMS does not support it.
+
+2002-07-23 Joel Sherrill <joel@OARcorp.com>
+
+ * librpc/src/rpc/pmap_clnt.c (pmap_set): Changed prototype to match .h.
+
+2002-07-22 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * wrapup/Makefile.am: Use .$(OBJEXT) instead of .o.
+ * wrapup/Makefile.am: Use project_libdir instead of
+ $(PROJECT_RELEASE)/lib. Eliminate LIBNAME. Pickup *.o's instead of
+ *.rels for CPU_OBJS. Manually create $(project_libdir)$(MULTISUBDIR).
+ * automake/lib.am: Use project_libdir instead of $(PROJECT_RELEASE)/lib.
+ * aclocal/env-rtemsbsp.m4, aclocal/env-rtemscpu.m4: Remove
+ RTEMS_BSP_SPECS, PROJECT_RELEASE. Add project_libdir, libdir. New
+ GCC_SPECS. Various cleanups.
+ * aclocal/rtems-top.m4: New PROJECT_ROOT handling.
+ * automake/compile.am: Remove RTEMS_BSP_SPECS, LD* flags, LINK,
+ references to bsp_specs. Use project_libdir instead of
+ $(PROJECT_RELEASE)/lib.
+ * itron/src/Makefile.am: Use .$(OBJEXT) instead of .o.
+ * itron/src/Makefile.am: Use AM_CPPFLAGS instead of INCLUDES.
+ * posix/src/Makefile.am: Use .$(OBJEXT) instead of .o.
+ * posix/src/Makefile.am: Use AM_CPPFLAGS instead of INCLUDES.
+ * score/src/Makefile.am, sapi/src/Makefile.am, rtems/src/Makefile.am,
+ librpc/src/xdr/Makefile.am, librpc/src/rpc/Makefile.am: Use .$(OBJEXT)
+ instead of .o.
+ * librpc/src/xdr/Makefile.am, librpc/src/rpc/Makefile.am: Eliminate
+ LIBNAME.
+ * libblock/src/Makefile.am: Use .$(OBJEXT) instead of .o.
+ * libblock/src/Makefile.am: Eliminate LIBNAME. Cosmetical cleanups.
+ * libcsupport/Makefile.am: Use .$(OBJEXT) instead of .o.
+ * libcsupport/Makefile.am: Eliminate LIBNAME. Use AM_CPPFLAGS instead of
+ INCLUDES (Upcoming automake standard).
+ * libnetworking/kern/Makefile.am: Use .$(OBJEXT) instead of .o.
+ * libnetworking/lib/Makefile.am, libnetworking/libc/Makefile.am,
+ libnetworking/net/Makefile.am, libnetworking/netinet/Makefile.am,
+ libnetworking/nfs/Makefile.am, libnetworking/rtems/Makefile.am,
+ libnetworking/wrapup/Makefile.am: Ditto.
+ * libnetworking/kern/Makefile.am: Eliminate LIBNAME.
+ * libnetworking/lib/Makefile.am, libnetworking/libc/Makefile.am,
+ libnetworking/net/Makefile.am, libnetworking/netinet/Makefile.am,
+ libnetworking/nfs/Makefile.am, libnetworking/rtems/Makefile.am: Ditto.
+ * libnetworking/wrapup/Makefile.am: Use project_libdir instead of
+ $(PROJECT_RELEASE)/lib.
+
+2002-07-22 Joel Sherrill <joel@OARcorp.com>
+
+ * score/include/rtems/score/apimutex.h (_API_Mutex_Lock): Per PR253 add
+ the missing _ISR_Disable. This fix was already applied to the old
+ location (c/src/exec/score/...).
+
+2002-07-20 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libmisc/capture/capture.c, libmisc/capture/capture-cli.c: include
+ <string.h> for memset.
+
+2002-07-17 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * aclocal/rtems-top.m4: Reflect relocation of c/src/exec to cpukit.
+ * aclocal/check-cpu.m4, aclocal/check-bsps.m4: Ditto.
+
+2002-07-17 Jay Monkman <jtm@smoothsmoothie.com>
+
+ * libnetworking/netinet/in.h, libnetworking/netinet/ip.h,
+ libnetworking/netinet/ip_var.h, libnetworking/netinet/tcp.h: Modified to
+ added packed attribute.o.
+
+2002-07-16 Joel Sherrill <joel@OARcorp.com>
+
+ * score/macros/rtems/score/object.inl: Corrected typos in
+ _Objects_Open, _Objects_Close, and _Objects_Namespace_remove.
+
+2002-07-05 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * automake/multilib.am: Add install-multi.
+ * aclocal/rtems-top.m4: Reflect new RTEMS_TOPdir to detecting
+ version.m4. Add --with-project-root. Reflect --with-project-root to
+ setting up PROJECT_ROOT.
+ * aclocal/env-rtemscpu.m4: Reflect new RTEMS_TOPdir (HACK).
+ * aclocal/check-cpu.m4, aclocal/check-bsps.m4: Reflect new RTEMS_TOPdir.
+ * configure.ac: RTEMS_TOP(..).
+ * itron/configure.ac, posix/configure.ac, librpc/configure.ac,
+ libblock/configure.ac, libfs/configure.ac, libcsupport/configure.ac,
+ libnetworking/configure.ac: RTEMS_TOP(../..).
+
+2002-07-05 Joel Sherrill <joel@OARcorp.com>
+
+ * posix/include/rtems/posix/cancel.h, posix/src/cancel.c,
+ posix/src/cancelrun.c, posix/src/mqueue.c, posix/src/pthread.c,
+ posix/src/semaphore.c, posix/src/setcancelstate.c,
+ posix/src/setcanceltype.c, posix/src/testcancel.c: Per PR164, corrected
+ the behavior of thread cancellation and did some cleanup as a
+ side-effect.
+ * score/macros/rtems/score/object.inl: Corrected implementation of
+ _Objects_Open, _Objects_Close, and _Objects_Namespace_remove to be
+ consistent with the inline implementation.
+ * rtems/src/dpmemident.c, rtems/src/msgqident.c, rtems/src/partident.c,
+ rtems/src/ratemonident.c, rtems/src/regionident.c, rtems/src/semident.c,
+ rtems/src/timerident.c: Corrected use of name parameter to be
+ consistent with fixes implemented to string name processing which were
+ committed with the POSIX Message Queue update.
+
+2002-07-04 Joel Sherrill <joel@OARcorp.com>
+
+ * Jump table for single entry point removed.
+ * sapi/include/rtems/directives.h, sapi/src/entrytable.c: Removed.
+ * sapi/include/Makefile.am, sapi/src/Makefile.am, sapi/src/exinit.c:
+ Modified to reflect above.
+
+2002-07-01 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * wrapup/Makefile.am: Install by using cpulibdir, cpulib_DATA.
+ * aclocal/check-bsp-cache.m4: Remove RTEMS_BSP_FAMILY.
+ * configure.ac: Remove RTEMS_PROJECT_ROOT.
+ * aclocal/project-root.m4: Remove.
+ * aclocal/enable-multiprocessing.m4: Fix typo.
+ * aclocal/prog-cc.m4: Remove obsolete comments. Comment out GCCSED.
+ * itron/configure.ac, posix/configure.ac, librpc/configure.ac,
+ libblock/configure.ac, libfs/configure.ac, libcsupport/configure.ac,
+ libnetworking/configure.ac: Remove RTEMS_PROJECT_ROOT.
+
+2002-07-01 Joel Sherrill <joel@OARcorp.com>
+
+ * Mega patch merge to change the format of the object IDs to loosen the
+ dependency between the SCORE and the various APIs. There was
+ considerable work to simplify the object name management and it appears
+ that the name_table field is no longer needed. This patch also includes
+ the addition of the internal mutex which is currently only used to
+ protect some types of allocation and deallocation. This significantly
+ can reduce context switch latency under certain circumstances. In
+ particular, some heap/region operations were O(n) and had dispatching
+ disabled. This should help enormously. With this merge, the patch is
+ not as clean as it should be. In particular, the documentation has not
+ been modified to reflect the new object ID layout, the IDs in the test
+ screens are not updated, and _Objects_Get_information needs to be a real
+ routine not inlined. As part of this patch a lot of MP code for
+ thread/proxy blocking was made conditional and cleaned up.
+ * itron/src/cre_mbf.c, itron/src/cre_sem.c, itron/src/eventflags.c,
+ itron/src/fmempool.c, itron/src/itronsem.c, itron/src/mbox.c,
+ itron/src/msgbuffer.c, itron/src/port.c, itron/src/task.c,
+ itron/src/vmempool.c: Modified as part of above.
+ * Mega patch merge to change the format of the object IDs to loosen the
+ dependency between the SCORE and the various APIs. There was
+ considerable work to simplify the object name management and it appears
+ that the name_table field is no longer needed. This patch also includes
+ the addition of the internal mutex which is currently only used to
+ protect some types of allocation and deallocation. This significantly
+ can reduce context switch latency under certain circumstances. In
+ particular, some heap/region operations were O(n) and had dispatching
+ disabled. This should help enormously. With this merge, the patch is
+ not as clean as it should be. In particular, the documentation has not
+ been modified to reflect the new object ID layout, the IDs in the test
+ screens are not updated, and _Objects_Get_information needs to be a real
+ routine not inlined. As part of this patch a lot of MP code for
+ thread/proxy blocking was made conditional and cleaned up.
+ * posix/include/rtems/posix/key.h, posix/src/cond.c,
+ posix/src/condinit.c, posix/src/intr.c, posix/src/key.c,
+ posix/src/keycreate.c, posix/src/keydelete.c, posix/src/killinfo.c,
+ posix/src/mqueue.c, posix/src/mqueuecreatesupp.c, posix/src/mutex.c,
+ posix/src/mutexinit.c, posix/src/psignal.c, posix/src/pthread.c,
+ posix/src/semaphore.c, posix/src/semaphorecreatesupp.c: Modified as part
+ of above.
+ * Mega patch merge to change the format of the object IDs to loosen the
+ dependency between the SCORE and the various APIs. There was
+ considerable work to simplify the object name management and it appears
+ that the name_table field is no longer needed. This patch also includes
+ the addition of the internal mutex which is currently only used to
+ protect some types of allocation and deallocation. This significantly
+ can reduce context switch latency under certain circumstances. In
+ particular, some heap/region operations were O(n) and had dispatching
+ disabled. This should help enormously. With this merge, the patch is
+ not as clean as it should be. In particular, the documentation has not
+ been modified to reflect the new object ID layout, the IDs in the test
+ screens are not updated, and _Objects_Get_information needs to be a real
+ routine not inlined. As part of this patch a lot of MP code for
+ thread/proxy blocking was made conditional and cleaned up.
+ * score/include/Makefile.am, score/include/rtems/score/coremsg.h,
+ score/include/rtems/score/coremutex.h,
+ score/include/rtems/score/coresem.h, score/include/rtems/score/object.h,
+ score/include/rtems/score/threadq.h,
+ score/inline/rtems/score/object.inl,
+ score/inline/rtems/score/thread.inl,
+ score/macros/rtems/score/object.inl, score/src/Makefile.am,
+ score/src/coremsg.c, score/src/coremutex.c, score/src/coresem.c,
+ score/src/mpci.c, score/src/objectcomparenameraw.c,
+ score/src/objectextendinformation.c,
+ score/src/objectinitializeinformation.c, score/src/objectnametoid.c,
+ score/src/thread.c, score/src/threadclose.c, score/src/threadget.c,
+ score/src/threadq.c, score/src/threadqextractwithproxy.c: Modified as
+ part of above.
+ * score/include/rtems/score/apimutex.h,
+ score/src/objectgetnoprotection.c: New files.
+ * Mega patch merge to change the format of the object IDs to loosen the
+ dependency between the SCORE and the various APIs. There was
+ considerable work to simplify the object name management and it appears
+ that the name_table field is no longer needed. This patch also includes
+ the addition of the internal mutex which is currently only used to
+ protect some types of allocation and deallocation. This significantly
+ can reduce context switch latency under certain circumstances. In
+ particular, some heap/region operations were O(n) and had dispatching
+ disabled. This should help enormously. With this merge, the patch is
+ not as clean as it should be. In particular, the documentation has not
+ been modified to reflect the new object ID layout, the IDs in the test
+ screens are not updated, and _Objects_Get_information needs to be a real
+ routine not inlined. As part of this patch a lot of MP code for
+ thread/proxy blocking was made conditional and cleaned up.
+ * sapi/include/confdefs.h, sapi/src/exinit.c, sapi/src/extension.c,
+ sapi/src/itronapi.c, sapi/src/posixapi.c, sapi/src/rtemsapi.c: Modified
+ as part of above.
+ * Mega patch merge to change the format of the object IDs to loosen the
+ dependency between the SCORE and the various APIs. There was
+ considerable work to simplify the object name management and it appears
+ that the name_table field is no longer needed. This patch also includes
+ the addition of the internal mutex which is currently only used to
+ protect some types of allocation and deallocation. This significantly
+ can reduce context switch latency under certain circumstances. In
+ particular, some heap/region operations were O(n) and had dispatching
+ disabled. This should help enormously. With this merge, the patch is
+ not as clean as it should be. In particular, the documentation has not
+ been modified to reflect the new object ID layout, the IDs in the test
+ screens are not updated, and _Objects_Get_information needs to be a real
+ routine not inlined. As part of this patch a lot of MP code for
+ thread/proxy blocking was made conditional and cleaned up.
+ * rtems/include/rtems.h, rtems/inline/rtems/rtems/region.inl,
+ rtems/macros/rtems/rtems/region.inl, rtems/src/dpmem.c,
+ rtems/src/dpmemcreate.c, rtems/src/msg.c, rtems/src/msgqcreate.c,
+ rtems/src/part.c, rtems/src/partcreate.c, rtems/src/ratemon.c,
+ rtems/src/ratemoncreate.c, rtems/src/region.c, rtems/src/regioncreate.c,
+ rtems/src/regiondelete.c, rtems/src/regionextend.c,
+ rtems/src/regiongetinfo.c, rtems/src/regiongetsegment.c,
+ rtems/src/regiongetsegmentsize.c, rtems/src/regionident.c,
+ rtems/src/regionreturnsegment.c, rtems/src/rtemstimer.c,
+ rtems/src/sem.c, rtems/src/semcreate.c, rtems/src/taskcreate.c,
+ rtems/src/taskident.c, rtems/src/tasks.c, rtems/src/timercreate.c:
+ Modified as part of above.
+ * libmisc/capture/capture-cli.c, libmisc/cpuuse/cpuuse.c,
+ libmisc/monitor/mon-monitor.c, libmisc/monitor/mon-object.c,
+ libmisc/monitor/monitor.h: Corrected use of _Objects_Information_table
+ now that it is a two dimensional array based upon API and class. In
+ addition, in the monitor, corrected an error which occured when a
+ target has 64 bit pointers.
+ * libmisc/stackchk/check.c: Corrected use of _Objects_Information_table
+ now that it is a two dimensional array based upon API and class.
+ * Mega patch merge to change the format of the object IDs to loosen the
+ dependency between the SCORE and the various APIs. There was
+ considerable work to simplify the object name management and it appears
+ that the name_table field is no longer needed. This patch also includes
+ the addition of the internal mutex which is currently only used to
+ protect some types of allocation and deallocation. This significantly
+ can reduce context switch latency under certain circumstances. In
+ particular, some heap/region operations were O(n) and had dispatching
+ disabled. This should help enormously. With this merge, the patch is
+ not as clean as it should be. In particular, the documentation has not
+ been modified to reflect the new object ID layout, the IDs in the test
+ screens are not updated, and _Objects_Get_information needs to be a real
+ routine not inlined. As part of this patch a lot of MP code for
+ thread/proxy blocking was made conditional and cleaned up.
+ * libblock/src/bdbuf.c: Modified as part of above.
+ * libcsupport/src/__times.c: Corrected from previous attempt to cleanup.
+
+2002-06-28 Joel Sherrill <joel@OARcorp.com>
+
+ * libcsupport/src/__times.c: Cleaned up comments, return more
+ information, and eliminated the fatal error on clock not set since it
+ cannot occur.
+
+2002-06-27 Thomas Doerfler <Thomas.Doerfler@imd-systems.de>
+
+ * Addition of a ftp client filesystem, comparable to the tftp one.
+ * libnetworking/lib/ftpfs.c, libnetworking/rtems/ftpfs.h: New files.
+ * libnetworking/lib/Makefile.am, libnetworking/rtems/Makefile.am:
+ Modified to reflect above.
+
+2002-06-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * aclocal/prog-ccas.m4: New.
+ * aclocal/canonicalize-tools.m4: Remove AS, OBJCOPY, NM, SIZE, STRIP.
+ RTEMS_GCC_PRINT.
+ * aclocal/check-multiprocessing.m4: Fix typo.
+ * automake/compile.am: Remove CXX support. Replace AS by CCAS. Remove
+ LINK_LIBS, LINK_OBJS, LINK_FILES.
+ * configure.ac: Use AC_CONFIG_AUX_DIR(..).
+ * itron/configure.ac, posix/configure.ac, librpc/configure.ac,
+ libblock/configure.ac, libfs/configure.ac, libcsupport/configure.ac,
+ libnetworking/configure.ac: Use AC_CONFIG_AUX_DIR(../..). Add
+ AC_PROG_RANLIB.
+
+2002-06-26 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove references to RTEMS_BSP.
+ * aclocal/check-multiprocessing.m4: Remove references to RTEMS_BSP.
+ Allow building w/ --enable-multiprocessing --enable-multilib.
+ * aclocal/enable-multiprocessing.m4: Eliminate RTEMS_HAS_MULTIPROCESSING.
+ * itron/configure.ac: Remove references to RTEMS_BSP.
+ * itron/src/Makefile.am: Add libitron.a.
+ * posix/configure.ac: Remove references to RTEMS_BSP.
+ * posix/src/Makefile.am: Add libposix.a.
+ * libmisc/wrapup/Makefile.am: Don't preinstall libmisc.a.
+ * libblock/src/Makefile.am: Don't preinstall libblock.a.
+ * libfs/wrapup/Makefile.am: Don't preinstall libfs.a.
+ * libnetworking/wrapup/Makefile.am: Don't preinstall libnetworking.a.
+
+2002-06-25 Thomas Doerfler <Thomas.Doerfler@imd-systems.de>
+
+ * With the addition of serdbg, the standard polled I/O functions for
+ gdbstub and/or printk are optionally routed to any termios-aware device
+ driver, that supports polled mode. See libmisc/serdbg/README.
+ * libmisc/serdbg/Makefile.am, libmisc/serdbg/README,
+ libmisc/serdbg/serdbg.c, libmisc/serdbg/serdbg.h,
+ libmisc/serdbg/serdbgcnf.h, libmisc/serdbg/serdbgio.c,
+ libmisc/serdbg/termios_printk.c, libmisc/serdbg/termios_printk.h,
+ libmisc/serdbg/termios_printk_cnf.h, libmisc/serdbg/.cvsignore: New
+ files.
+ * libmisc/configure.ac, libmisc/Makefile.am, libmisc/wrapup/Makefile.am:
+ Modified to reflect addition.
+
+2002-06-25 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * wrapup/Makefile.am: Fix stupid typo in previous patch.
+ * configure.ac: Add librpc. AC_PROG_RANLIB.
+ * wrapup/Makefile.am: Add librpc. Use relative path to lib*.a for
+ POSIX_OBJS, ITRON_OBJS, NETWORKING_OBJS.
+ * librpc/configure.ac: RTEMS_TOP(../../../..).
+ AC_CONFIG_AUX_DIR(../../../..). Remove RTEMS_CANONICAL_HOST. Use
+ RTEMS_ENV_RTEMSCPU. Add AC_PROG_RANLIB.
+ * librpc/include/rpc/Makefile.am, librpc/include/Makefile.am,
+ librpc/include/rpcsvc/Makefile.am: Include
+ $(top_srcdir)/../automake/*.am.
+ * librpc/Makefile.am: Include $(top_srcdir)/../automake/*.am.
+ ACLOCAL_AMFLAGS = -I ../aclocal.
+ * librpc/src/rpc/PSD.doc/Makefile.am, librpc/src/rpc/Makefile.am,
+ librpc/src/xdr/Makefile.am, librpc/src/Makefile.am: Include
+ $(top_srcdir)/../automake/*.am.
+
+2002-06-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * aclocal/subdirs.m4: Remove.
+
+2002-06-18 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * wrapup/Makefile.am: Use relative path to lib*.a for LIBCSUPPORT_OBJS,
+ LIBBLOCK_OBJS, LIBDOSFS_OBJS, LIBIMFS_OBJS.
+ * libblock/Makefile.am: Merge-in include/Makefile.am.
+ * libblock/include/Makefile.am: Remove.
+ * libblock/configure.ac: Reflect changes above.
+ * libnetworking/Makefile.am: Remove commented out net-apps.
+
+2002-06-17 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include $(top_srcdir)/automake/*.am. Use aclocal.
+ * sapi/include/Makefile.am, sapi/Makefile.am, sapi/inline/Makefile.am,
+ sapi/macros/Makefile.am, sapi/src/Makefile.am,
+ score/include/Makefile.am, score/Makefile.am, score/cpu/Makefile.am,
+ score/inline/Makefile.am, score/macros/Makefile.am,
+ score/src/Makefile.am, wrapup/Makefile.am, include/Makefile.am,
+ rtems/include/Makefile.am, rtems/Makefile.am, rtems/inline/Makefile.am,
+ rtems/macros/Makefile.am, rtems/src/Makefile.am: Include
+ $(top_srcdir)/automake/*.am.
+ * aclocal/bsp-alias.m4: Copied over from aclocal/.
+ * aclocal/canonical-host.m4, aclocal/canonical-target-name.m4,
+ aclocal/canonicalize-tools.m4, aclocal/check-bsp-cache.m4,
+ aclocal/check-bsps.m4, aclocal/check-cpu.m4, aclocal/check-itron.m4,
+ aclocal/check-multiprocessing.m4, aclocal/check-networking.m4,
+ aclocal/check-newlib.m4, aclocal/check-posix.m4, aclocal/check-tool.m4,
+ aclocal/enable-bare.m4, aclocal/enable-inlines.m4,
+ aclocal/enable-itron.m4, aclocal/enable-multiprocessing.m4,
+ aclocal/enable-networking.m4, aclocal/enable-posix.m4,
+ aclocal/enable-rtemsbsp.m4, aclocal/env-rtemsbsp.m4,
+ aclocal/env-rtemscpu.m4, aclocal/gcc-pipe.m4, aclocal/gcc-specs.m4,
+ aclocal/multi.m4, aclocal/multilib.m4, aclocal/prog-cc.m4,
+ aclocal/project-root.m4, aclocal/rtems-cpu-subdirs.m4,
+ aclocal/rtems-debug.m4, aclocal/rtems-top.m4, aclocal/subdirs.m4,
+ aclocal/sysv-ipc.m4, aclocal/tool-paths.m4, aclocal/version.m4: Ditto.
+ * itron/include/Makefile.am: Include $(top_srcdir)/../automake/*.am.
+ * itron/Makefile.am: Include $(top_srcdir)/../automake/*.am. Use
+ ../aclocal.
+ * itron/inline/Makefile.am, itron/macros/Makefile.am,
+ itron/src/Makefile.am, posix/include/Makefile.am: Include
+ $(top_srcdir)/../automake/*.am.
+ * posix/Makefile.am: Include $(top_srcdir)/../automake/*.am. Use
+ ../aclocal.
+ * posix/inline/Makefile.am, posix/macros/Makefile.am,
+ posix/src/Makefile.am, libblock/include/Makefile.am: Include
+ $(top_srcdir)/../automake/*.am.
+ * libblock/Makefile.am: Include $(top_srcdir)/../automake/*.am. Use
+ ../aclocal.
+ * libblock/src/Makefile.am, libfs/src/dosfs/Makefile.am,
+ libfs/src/Makefile.am, libfs/src/imfs/Makefile.am: Include
+ $(top_srcdir)/../automake/*.am.
+ * libfs/Makefile.am: Include $(top_srcdir)/../automake/*.am. Use
+ ../aclocal.
+ * libfs/wrapup/Makefile.am: Include $(top_srcdir)/../automake/*.am.
+ * libcsupport/Makefile.am: Merge src/Makefile.am.
+ * libcsupport/configure.ac: Reflect changes above.
+ * libcsupport/src/Makefile.am: Remove.
+ * libcsupport/Makefile.am: Include $(top_srcdir)/../automake/*.am. Use
+ ../aclocal.
+ * libcsupport/src/Makefile.am, libnetworking/arpa/Makefile.am,
+ libnetworking/kern/Makefile.am: Include $(top_srcdir)/../automake/*.am.
+ * libnetworking/Makefile.am: Include $(top_srcdir)/../automake/*.am. Use
+ ../aclocal.
+ * libnetworking/lib/Makefile.am, libnetworking/libc/Makefile.am,
+ libnetworking/machine/Makefile.am, libnetworking/net/Makefile.am,
+ libnetworking/netinet/Makefile.am, libnetworking/nfs/Makefile.am,
+ libnetworking/rtems/Makefile.am, libnetworking/sys/Makefile.am,
+ libnetworking/vm/Makefile.am, libnetworking/wrapup/Makefile.am: Include
+ $(top_srcdir)/../automake/*.am.
+
+2002-06-15 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * automake/compile.am, automake/lib.am, automake/local.am,
+ automake/multilib.am, automake/subdirs.am: Copied over from automake/.
+ * Makefile.am: Add automake/*.am.
+
+2002-06-02 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libnetworking/rtems/Makefile.am: include multilib.am instead of
+ RTEMS_BSP.cfg.
+
+2002-05-30 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libnetworking/configure.ac: Remove RTEMS_CHECK_POSIX_API. Remove
+ RTEMS_ENABLE_POSIX. Remove RTEMS_CHECK_CUSTOM_BSP. Remove
+ RTEMS_ENABLE_POSIX.
+
+2002-05-29 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Add libnetworking.
+ * wrapup/Makefile.am: Ditto. Relocate c/src/libnetworking.
+ * libnetworking/Makefile.am: Reflect moval.
+ * libnetworking/machine/Makefile.am, libnetworking/net/Makefile.am,
+ libnetworking/lib/Makefile.am, libnetworking/netinet/Makefile.am,
+ libnetworking/vm/Makefile.am, libnetworking/libc/Makefile.am,
+ libnetworking/sys/Makefile.am, libnetworking/arpa/Makefile.am,
+ libnetworking/nfs/Makefile.am, libnetworking/kern/Makefile.am,
+ libnetworking/rtems/Makefile.am, libnetworking/configure.ac: Ditto.
+ * libnetworking/wrapup/Makefile.am: Ditto. Remove references to
+ networking apps.
+
+2002-05-24 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libmisc/configure.ac, libmisc/Makefile.am: Remove references to rootfs.
+
+2002-05-18 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Add libblock. Add libfs. Add AM_CONDITIONAL(UNIX).
+ * wrapup/Makefile.am: Add libblock, libfs/dosfs, libfs/imfs.
+ * libblock/configure.ac, libblock/Makefile.am,
+ libblock/include/Makefile.am, libblock/src/Makefile.am: Reflect move
+ from c/src/libblock to c/src/exec/libblock.
+ * libfs/configure.ac: Reflect move from c/src/libfs to c/src/exec/libfs.
+ * libfs/Makefile.am, libfs/src/Makefile.am, libfs/src/dosfs/Makefile.am,
+ libfs/src/imfs/Makefile.am, libfs/wrapup/Makefile.am: Ditto.
+ * libnetworking/rtems_telnetd/pty.c: Remove bsp.h. Include
+ <rtems/bspIo.h>.
+
+2002-05-16 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libmisc/rootfs/.cvsignore, libmisc/rootfs/Makefile.am,
+ libmisc/rootfs/mkrootfs.h, libmisc/rootfs/mkrootfs.c: Remove.
+ * libmisc/configure.ac: Remove rootfs and NETWORKING macros.
+ * libmisc/wrapup/Makefile.am: Remove rootfs and HAS_NETWORKING.
+ * libnetworking/rtems/mkrootfs.c: Add (relocated from libmisc/rootfs).
+ * libnetworking/rtems/mkrootfs.h: Ditto.
+ * libnetworking/rtems/Makefile.am: Reflect changes above.
+
+2002-05-16 Chris Johns <ccj@acm.org>
+
+ PR 194
+ * libmisc/*: Added the Capture engine.
+ * libmisc/capture/Makefile.am, libmisc/capture/README,
+ libmisc/capture/capture-cli.c, libmisc/capture/capture-cli.h,
+ libmisc/capture/capture.c, libmisc/capture/capture.h,
+ libmisc/capture/.cvsignore: New files.
+ * libmisc/Makefile.am, libmisc/configure.ac, libmisc/wrapup/Makefile.am:
+ Modified to reflect addition.
+
+2002-05-15 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Add libcsupport.
+ * wrapup/Makefile.am: Ditto.
+ * Makefile.am: Add preinstall-stamp.
+
+2002-05-15 Chris Johns <ccj@acm.org>
+
+ * score/include/rtems/score/thread.h,
+ score/inline/rtems/score/thread.inl, score/src/threaddispatch.c,
+ score/src/threadinitialize.c: Move the C library re-enterrant support
+ directly into the thread dispatch code. RTEMS needs libc and so
+ requiring libc to use a user extension with its overhead is not the best
+ solution. This patch lowers the overhead to 2 pointer moves.
+
+2002-05-14 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libnetworking/sys/ioctl.h, libnetworking/sys/sockio.h,
+ libnetworking/sys/filio.h: Remove.
+ * libnetworking/sys/Makefile.am: Reflect changes above.
+
+2002-05-03 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * score/include/Makefile.am: Work-around to autoconf-2.53 adding
+ PACKAGE_* to autoheaders - sed out *PACKAGE* from cpuopts-tmp.h.
+
+2002-05-03 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * posix/include/sys/utsname.h: Remove.
+ * posix/include/Makefile.am: Reflect changes above.
+ * posix/src/utsname.c: Remove.
+ * posix/src/Makefile.am: Reflect changes above.
+
+2002-05-01 Eric Norum <eric.norum@usask.ca>
+
+ * libnetworking/machine/in_cksum.h: Per PR200 fix multi-line inline
+ assembly to satisfy gcc 3.1 and newer.
+
+2002-04-26 Eric Norum <eric.norum@usask.ca>
+
+ * libnetworking/netinet/in_cksum_i386.c: Add volatile so the more
+ agressive optimization in gcc 3.1 does not reorder things.
+
+2002-04-18 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * score/include/rtems/system.h: Remove targopts.h.
+ * libnetworking/pppd/utils.c: Adapt to gcc-3.x.
+
+2002-04-17 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * score/include/rtems/system.h: Add the sparc to the target supporting
+ multlibs.
+
+2002-04-16 Chris Johns <ccj@acm.org>
+
+ * score/src/threadinitialize.c: Per PR181, clear the array of user
+ extension pointers. This lets user extensions that have hooked the
+ switch handler know if a task has been processed by the user extension
+ before. If a user extension is created after a task is started it may
+ not know it.
+
+2002-04-14 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove ENABLE_GCC28.
+
+2002-04-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * score/include/rtems/system.h: Add i386 to multilib-able targets.
+
+2002-04-11 Chris Johns <ccj@acm.org>
+
+ PR 59/networking
+ * libnetworking/c/src/libnetworking/rtems/rtems_bsdnet.h: Add the
+ drv_ctrl driver control block field to the ifconfig network driver
+ structure. This field is needed by the i82586 driver which was ported
+ from NetBSD as it had better hardware abstraction.
+
+2002-04-10 Victor V. Vengerov <vvv@oktet.ru>
+
+ PR 385/filesystem
+ * libblock/src/ramdisk.c: The "from" and "to" locations are calculated
+ as the start of the block within the ram that data is to be transferred
+ from/to for reads and writes respectively. However, within the loops,
+ the "from" and "to" locations are never updated. The loop should have
+ been updated as: from += rd->block_size; and to += rd->block_size;
+ within the for loops in the ramdisk_read and ramdisk_write routines,
+ respectively.
+
+2002-04-08 Chris Johns <ccj@acm.org>
+
+ * Per PR142, make task switch extension its own list.
+ * posix/src/pthread.c (_POSIX_Threads_User_extensions): Reflect above.
+ * Per PR141 and PR174, make task switch extension its own list and fix
+ all odd problems introduced by providing macro version.
+ * score/inline/rtems/score/userext.inl: Fix.
+ * Per PR142, make task switch extension its own list.
+ * score/include/rtems/score/userext.h: Reflect above by adding
+ User_extensions_Switch_control and adding it to User_extenions_Control.
+ * score/inline/rtems/score/userext.inl: Allocate all memory in one chunk
+ to minimize overhead. Address processing dedicated switch chain.
+ * Per PR142, make task switch extension its own list.
+ * score/include/rtems/score/userext.h: Reflect above by adding
+ User_extensions_Switch_control and adding it to User_extenions_Control.
+ * score/inline/rtems/score/userext.inl: Allocate all memory in one chunk
+ to minimize overhead. Address processing dedicated switch chain.
+ * Per PR142, make task switch extension its own list.
+ * rtems/src/tasks.c (_RTEMS_tasks_User_extensions): Reflect above.
+
+2002-04-06 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * include/rtems/bspIo.h: Fix cpp-guards, remove references to i386.
+ * posix/src/psignal.c: Include <stdlib.h>.
+ * libblock/src/ramdisk.c, libblock/src/blkdev.c,
+ libfs/src/imfs/imfs_getchild.c: include <string.h>.
+ * libfs/src/imfs/imfs_gtkn.c, libfs/src/imfs/ioman.c,
+ libfs/src/imfs/linearfile.c, libfs/src/imfs/memfile.c: Include
+ <string.h>.
+ * libnetworking/ChangeLog: Fix dates.
+
+2002-04-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libmisc/monitor/mon-monitor.c: Replace done with return (gcc3).
+ * libfs/src/dosfs/fat.h: Include <string.h>. Remove DBG1 and DBG2
+ (unused).
+ * Per PR169.
+ * libfs/src/dosfs/config.h.in, libfs/src/dosfs/stamp-h2.in: Removed from
+ CVS.
+
+2002-04-03 Alexander Kukuta <kam@oktet.ru>
+
+ * libblock/include/rtems/bdbuf.h: Address PR168 by changing
+ bdbuf_buffer.avl.bal and bdbuf_buffer.avl.cache to signed char instead
+ of char.
+
+2002-04-02 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * posix/src/getegid.c: Remove <errno.h>.
+ * posix/src/geteuid.c, posix/src/getgid.c, posix/src/getuid.c: Ditto.
+ * posix/src/getlogin.c: Move <errno.h>.
+
+2002-03-30 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libnetworking/libc/rcmd.c: Replace __rtems w/ __rtems__.
+
+2002-03-27 Thomas.Doerfler@imd-systems.de
+
+ PR 144
+ * libnetworking/nfs/bootp_subr.c bootpc_init(): Performs a write to
+ memory address 0 when called for the first time. This is done when
+ trying to clear the variable "dhcp_hostname".
+
+2002-03-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: AC_INIT(package,_RTEMS_VERSION,_RTEMS_BUGS).
+ AM_INIT_AUTOMAKE([no-define foreign 1.6]).
+ * include/Makefile.am, Makefile.am, wrapup/Makefile.am: Remove
+ AUTOMAKE_OPTIONS.
+ * itron/configure.ac: AC_INIT(package,_RTEMS_VERSION,_RTEMS_BUGS).
+ AM_INIT_AUTOMAKE([no-define foreign 1.6]).
+ * itron/include/Makefile.am, itron/Makefile.am,
+ itron/inline/Makefile.am, itron/macros/Makefile.am,
+ itron/src/Makefile.am: Remove AUTOMAKE_OPTIONS.
+ * posix/configure.ac: AC_INIT(package,_RTEMS_VERSION,_RTEMS_BUGS).
+ AM_INIT_AUTOMAKE([no-define foreign 1.6]).
+ * posix/src/Makefile.am, posix/Makefile.am, posix/include/Makefile.am,
+ posix/inline/Makefile.am, posix/macros/Makefile.am,
+ score/cpu/Makefile.am, score/src/Makefile.am, score/Makefile.am,
+ score/include/Makefile.am, score/inline/Makefile.am,
+ score/macros/Makefile.am, sapi/Makefile.am, sapi/include/Makefile.am,
+ sapi/inline/Makefile.am, sapi/macros/Makefile.am, sapi/src/Makefile.am,
+ rtems/Makefile.am, rtems/include/Makefile.am, rtems/inline/Makefile.am,
+ rtems/macros/Makefile.am, rtems/src/Makefile.am: Remove AUTOMAKE_OPTIONS.
+ * libmisc/configure.ac: AC_INIT(package,_RTEMS_VERSION,_RTEMS_BUGS).
+ AM_INIT_AUTOMAKE([no-define foreign 1.6]).
+ * libmisc/Makefile.am, libmisc/cpuuse/Makefile.am,
+ libmisc/devnull/Makefile.am, libmisc/dummy/Makefile.am,
+ libmisc/dumpbuf/Makefile.am, libmisc/monitor/Makefile.am,
+ libmisc/mw-fb/Makefile.am, libmisc/rootfs/Makefile.am,
+ libmisc/rtmonuse/Makefile.am, libmisc/shell/Makefile.am,
+ libmisc/stackchk/Makefile.am, libmisc/untar/Makefile.am,
+ libmisc/wrapup/Makefile.am: Remove AUTOMAKE_OPTIONS.
+ * librpc/configure.ac: AC_INIT(package,_RTEMS_VERSION,_RTEMS_BUGS).
+ AM_INIT_AUTOMAKE([no-define foreign 1.6]).
+ * librpc/include/rpc/Makefile.am, librpc/include/Makefile.am,
+ librpc/include/rpcsvc/Makefile.am, librpc/Makefile.am,
+ librpc/src/rpc/PSD.doc/Makefile.am, librpc/src/rpc/Makefile.am,
+ librpc/src/xdr/Makefile.am, librpc/src/Makefile.am: Remove
+ AUTOMAKE_OPTIONS.
+ * libblock/configure.ac: AC_INIT(package,_RTEMS_VERSION,_RTEMS_BUGS).
+ AM_INIT_AUTOMAKE([no-define foreign 1.6]).
+ * libblock/include/Makefile.am, libblock/Makefile.am,
+ libblock/src/Makefile.am: Remove AUTOMAKE_OPTIONS.
+ * libfs/src/dosfs/fat_file.c: Remove bsp.h. fat_file_write(.. const
+ char*buf ..).
+ * libfs/src/dosfs/fat_file.h: fat_file_write(.. const char*buf ..).
+ * libfs/configure.ac: AC_INIT(package,_RTEMS_VERSION,_RTEMS_BUGS).
+ AM_INIT_AUTOMAKE([no-define foreign 1.6]).
+ * libfs/src/dosfs/Makefile.am, libfs/src/Makefile.am,
+ libfs/src/imfs/Makefile.am, libfs/Makefile.am, libfs/wrapup/Makefile.am:
+ Remove AUTOMAKE_OPTIONS.
+ * libnetworking/configure.ac:
+ AC_INIT(package,_RTEMS_VERSION,_RTEMS_BUGS). AM_INIT_AUTOMAKE([no-define
+ foreign 1.6]).
+ * libnetworking/arpa/Makefile.am, libnetworking/kern/Makefile.am,
+ libnetworking/Makefile.am, libnetworking/lib/Makefile.am,
+ libnetworking/libc/Makefile.am, libnetworking/machine/Makefile.am,
+ libnetworking/net/Makefile.am, libnetworking/netinet/Makefile.am,
+ libnetworking/nfs/Makefile.am, libnetworking/pppd/Makefile.am,
+ libnetworking/rtems/Makefile.am,
+ libnetworking/rtems_servers/Makefile.am,
+ libnetworking/rtems_telnetd/Makefile.am,
+ libnetworking/rtems_webserver/Makefile.am,
+ libnetworking/sys/Makefile.am, libnetworking/vm/Makefile.am,
+ libnetworking/wrapup/Makefile.am: Remove AUTOMAKE_OPTIONS.
+
+2002-03-27 Ilya Alexeev <ilya@continuum.ru>
+
+ PR 162
+ * libnetworking/net/if_ppp.c ppp_txdaemon(),
+ libnetworking/net/if_pppvar.h pppstart(): Local variables must not be
+ used in a device write routines. Now ppp_softc structure have own
+ character for writing to device (sc_outchar). I think that converting
+ local variables to static is not a right solution, because problems will
+ occur in the case of two or more ppp instances.
+ * libnetworking/net/ppp_tty.c pppstart(): Type of the ioffset variable
+ must be u_long, otherwise in the case of the big output packet endless
+ loop may occur.
+
+2002-03-25 Eric Norum <norume@aps.anl.gov>
+
+ PR 374/networking
+ * libnetworking/Makefile.am, libnetworking/rtems/rtems_bsdnet.h,
+ libnetworking/rtems/rtems_glue.c: The patch sent as part of PR270 got
+ applied to the wrong place. The effect was that (1) startup was no
+ faster than before and (2) malloc starvation messages came way too
+ quickly. The attached patch fixes both these problems and also provides
+ a mechanism for applications to handle malloc starvation conditions as
+ they see fit.
+ * libnetworking/rtems/rtems_bsdnet_malloc_starvation.c: New file.
+
+2002-03-21 Ilya Alexeev <ilya@continuum.ru>
+
+ * libnetworking/net/if_ppp.c, libnetworking/net/ppp_tty.c: Initial
+ preparations for multiple PPPD connections.
+
+2002-03-21 Alexander Kukuta <kam@oktet.ru>
+
+ * libblock/src/bdbuf.c (avl_insert, libblock/avl_remove): Reimplemented
+ from scratch to avoid using GPLed sources in RTEMS core.
+ * libblock/src/bdbuf.c, libblock/include/rtems/bdbuf.h: Remove "binary
+ tree" implementation which was used for debugging only.
+
+2002-03-20 Chris Johns <ccj@acm.org>
+
+ PR 192
+ * libmisc/monitor/mon-command.c: The RTEMS monitor makes everything
+ lowercase. The capture engine need to set triggers or watches on task
+ with uppercase names. Also stop the monitor repeating command when
+ enter is pressed.
+ PR 148.
+ * libmisc/monitor/mon-prmisc.c: Fixed to print task states correctly.
+
+2002-03-16 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ PR 140
+ * libfs/src/dosfs/config.h.in, libfs/src/dosfs/stamp-h2.in: Removed.
+ * libfs/.cvsignore: Add config.h*, stamp-h*.
+ * libfs/configure.ac: Remove AC_SRC_DIR(.../dosfs.h). Remove
+ AM_CONFIG_HEADER(src/dosfs/config.h). Remove
+ AM_CONFIG_HEADER(src/imfs/config.h). Add AM_CONFIG_HEADER(config.h).
+ * libfs/src/dosfs/Makefile.am, libfs/src/imfs/Makefile.am: INCLUDES =
+ -I../...
+
+2002-03-14 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ PR 130
+ * libfs/src/dosfs/Makefile.am: Reworked, Disable dosfs for UNIX.
+ * libfs/wrapup/Makefile.am: Disable dosfs for UNIX.
+
+2002-03-13 Victor V. Vengerov <vvv@oktet.ru>
+
+ * libblock/src/bdbuf.c (find_or_assign_buffer,
+ libblock/rtems_bdbuf_read, libblock/rtems_bdbuf_sync,
+ libblock/rtems_bdbuf_syncdev, libblock/bdbuf_swapout_task): Fix bug:
+ disable interrupts and set level properly before _CORE_mutex_Seize
+ invocation).
+
+2002-03-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * score/include/rtems/system.h: Add __RTEMS_REVISION__.
+
+2002-03-01 Eric Norum <eric.norum@usask.ca>
+
+ * posix/src/pthreadonce.c: Task is not preemptable while running a
+ pthread_once init function. This is slightly less heavy handed than
+ disabling dispatching and seems better than consuming a mutex.
+
+2002-02-28 Victor V. Vengerov <vvv@oktet.ru>
+
+ * DOS filesystem including FAT12, FAT16, and FAT32 support submitted.
+ * libfs/src/dosfs, libfs/src/dosfs/Makefile.am,
+ libfs/src/dosfs/stamp-h2.in, libfs/src/dosfs/config.h.in,
+ libfs/src/dosfs/dosfs.h, libfs/src/dosfs/fat.c, libfs/src/dosfs/fat.h,
+ libfs/src/dosfs/fat_fat_operations.c,
+ libfs/src/dosfs/fat_fat_operations.h, libfs/src/dosfs/fat_file.c,
+ libfs/src/dosfs/fat_file.h, libfs/src/dosfs/msdos.h,
+ libfs/src/dosfs/msdos_create.c, libfs/src/dosfs/msdos_dir.c,
+ libfs/src/dosfs/msdos_eval.c, libfs/src/dosfs/msdos_file.c,
+ libfs/src/dosfs/msdos_free.c, libfs/src/dosfs/msdos_fsunmount.c,
+ libfs/src/dosfs/msdos_handlers_dir.c,
+ libfs/src/dosfs/msdos_handlers_file.c, libfs/src/dosfs/msdos_init.c,
+ libfs/src/dosfs/msdos_initsupp.c, libfs/src/dosfs/msdos_misc.c,
+ libfs/src/dosfs/msdos_mknod.c, libfs/src/dosfs/msdos_node_type.c,
+ libfs/src/dosfs/.cvsignore: New files.
+ * libfs/configure.ac, libfs/src/Makefile.am, libfs/wrapup/Makefile.am:
+ Modified to reflect addition.
+
+2002-02-28 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * score/include/rtems/system.h: Add __RTEMS_MAJOR__, __RTEMS_MINOR__.
+
+2002-02-28 Joel Sherrill <joel@OARcorp.com>
+
+ * Submitted by Victor V. Vengerov <vvv@oktet.ru> and merged into the
+ RTEMS source.
+ * libblock/ChangeLog, libblock/Makefile.am, libblock/README,
+ libblock/configure.ac, libblock/include/Makefile.am,
+ libblock/include/rtems/bdbuf.h, libblock/include/rtems/blkdev.h,
+ libblock/include/rtems/diskdevs.h, libblock/include/rtems/ramdisk.h,
+ libblock/include/rtems/.cvsignore, libblock/include/.cvsignore,
+ libblock/src/Makefile.am, libblock/src/bdbuf.c, libblock/src/blkdev.c,
+ libblock/src/diskdevs.c, libblock/src/ramdisk.c,
+ libblock/src/.cvsignore, libblock/.cvsignore: New files.
+
+2002-02-27 Ilya Alexeev <ilya@continuum.ru>
+
+ * libnetworking/net/if_ppp.c, libnetworking/pppd/auth.c,
+ libnetworking/pppd/chat.c, libnetworking/pppd/pppd.h,
+ libnetworking/pppd/sys-rtems.c: Add server with pap-authorization
+ capabilities as well as eliminate some warnings.
+
+2002-02-27 Eric Norum <eric.norum@usask.ca>
+
+ * libnetworking/net/radix.c: Properly handle fetching the default route
+ when there is no route. This was a bug in the original FreeBSD code and
+ this fix is from an updated version of their code.
+
+2002-02-16 Eric Norum <eric.norum@usask.ca>
+
+ * libnetworking/lib/tftpDriver.clib/tftpDriver.c: Fix TFTP block number
+ checking.
+
+2002-02-09 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * posix/src/getegid.c: Add #include <rtems/userenv.h>. Remove #include
+ <rtems/libio_.h>.
+ * posix/src/geteuid.c, posix/src/getgid.c, posix/src/getlogin.c,
+ posix/src/getuid.c: Ditto.
+
+2002-02-05 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Readded reference to wrapup.
+ * posix/configure.ac: AC_CONFIG_SRCDIR([src/pthreads.c]).
+ * posix/src/psignal.c: #include <string.h>.
+ * libnetworking/pppd/sys-rtems.c: Remove unused variable status from
+ dodefaultroute.
+
+2002-02-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libnetworking/lib/tftpDriver.c: Remove set_errno_and_return_minus_one,
+ include <rtems/seterr.h>.
+
+2002-02-01 Mike Siers <mikes@poliac.com>
+
+ * libnetworking/pppd/rtemspppd.c (rtems_pppd_disconnect): Modified to
+ avoid bringing the link down too fast. NOTE: Mike reports successfully
+ running at 56K baud on a direct link.
+
+2002-01-31 Mike Siers <mikes@poliac.com>
+
+ * libnetworking/pppd/rtemsdialer.h: New file missed in previous commit.
+ * libnetworking/*: Update of PPPD support which eliminates the
+ requirement that drivers be in the termios TASK_DRIVEN mode. Mike did
+ significant testing and reports that it seems to be more stable and
+ handle larger packets better. This patch replaces the termios tasks
+ with more general pppd network driver tasks. The functions pppinput()
+ and pppstart() get called from the interrupt service routine.
+ * libnetworking/Makefile.am, libnetworking/configure.ac,
+ libnetworking/net/Makefile.am, libnetworking/net/bpf.h,
+ libnetworking/net/ethernet.h, libnetworking/net/if.c,
+ libnetworking/net/if.h, libnetworking/net/if_arp.h,
+ libnetworking/net/if_dl.h, libnetworking/net/if_ethersubr.c,
+ libnetworking/net/if_llc.h, libnetworking/net/if_loop.c,
+ libnetworking/net/if_ppp.h, libnetworking/net/if_pppvar.h,
+ libnetworking/net/if_types.h, libnetworking/net/netisr.h,
+ libnetworking/net/ppp-comp.h, libnetworking/net/ppp_defs.h,
+ libnetworking/net/pppcompress.h, libnetworking/net/radix.c,
+ libnetworking/net/radix.h, libnetworking/net/raw_cb.c,
+ libnetworking/net/raw_cb.h, libnetworking/net/raw_usrreq.c,
+ libnetworking/net/route.c, libnetworking/net/route.h,
+ libnetworking/net/rtsock.c, libnetworking/pppd/Makefile.am,
+ libnetworking/pppd/README, libnetworking/pppd/STATUS,
+ libnetworking/pppd/auth.c, libnetworking/pppd/cbcp.c,
+ libnetworking/pppd/ccp.c, libnetworking/pppd/ccp.h,
+ libnetworking/pppd/chap.c, libnetworking/pppd/chap.h,
+ libnetworking/pppd/chap_ms.c, libnetworking/pppd/chap_ms.h,
+ libnetworking/pppd/chat.c, libnetworking/pppd/demand.c,
+ libnetworking/pppd/fsm.c, libnetworking/pppd/fsm.h,
+ libnetworking/pppd/ipcp.c, libnetworking/pppd/ipcp.h,
+ libnetworking/pppd/ipxcp.c, libnetworking/pppd/ipxcp.h,
+ libnetworking/pppd/lcp.c, libnetworking/pppd/lcp.h,
+ libnetworking/pppd/magic.c, libnetworking/pppd/magic.h,
+ libnetworking/pppd/options.c, libnetworking/pppd/patchlevel.h,
+ libnetworking/pppd/pathnames.h, libnetworking/pppd/pppd.8,
+ libnetworking/pppd/pppd.h, libnetworking/pppd/rtemsmain.c,
+ libnetworking/pppd/rtemspppd.c, libnetworking/pppd/rtemspppd.h,
+ libnetworking/pppd/sys-rtems.c, libnetworking/pppd/upap.c,
+ libnetworking/pppd/upap.h, libnetworking/pppd/utils.c,
+ libnetworking/pppd/example/README,
+ libnetworking/pppd/example/netconfig.h,
+ libnetworking/wrapup/Makefile.am: Modified.
+ * libnetworking/net/bsd-comp.c, libnetworking/net/if_ppp.c,
+ libnetworking/net/ppp-deflate.c, libnetworking/net/ppp.h,
+ libnetworking/net/ppp_tty.c, libnetworking/net/pppcompress.c,
+ libnetworking/net/zlib.c, libnetworking/net/zlib.h: New file.
+ * libnetworking/modem/, libnetworking/modem/.cvsignore,
+ libnetworking/modem/Makefile.am, libnetworking/modem/ppp.c,
+ libnetworking/modem/ppp.h, libnetworking/modem/ppp_tty.c,
+ libnetworking/modem/pppcompress.c: Subdirectory removed.
+
+2002-01-29 Joel Sherrill <joel@OARcorp.com>
+
+ * score/include/rtems/score/watchdog.h: Added WATCHDOG_MAXIMUM_INTERVAL.
+
+2002-01-28 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libmisc/shell/shell.c: Remove #undef __STRICT_ANSI__.
+
+2002-01-25 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libmisc/configure.ac: Fix tests for GCC.
+
+2002-01-24 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libmisc/configure.ac: Add check for weak function attribute. Remove
+ AM_CONDITIONAL([RTEMS_LIBSHELL]. Add AM_CONDITIONAL(LIBSHELL),
+ AM_CONDITIONAL(LIBSERDBG).
+ * libmisc/capture/Makefile.am, libmisc/cpuuse/Makefile.am,
+ libmisc/devnull/Makefile.am, libmisc/dummy/Makefile.am,
+ libmisc/dumpbuf/Makefile.am, libmisc/monitor/Makefile.am,
+ libmisc/mw-fb/Makefile.am, libmisc/rtmonuse/Makefile.am: Use *.a instead
+ of *-tmp.a.
+ * libmisc/serdbg/Makefile.am: Use *.a instead of *-tmp.a. Build iff
+ LIBSERDBG is true.
+ * libmisc/shell/Makefile.am: Use *.a instead of *-tmp.a. Build iff
+ LIBSHELL is true.
+ * libmisc/stackchk/Makefile.am, libmisc/untar/Makefile.am: Use *.a
+ instead of *-tmp.a.
+ * libmisc/wrapup/Makefile.am: Reflect changes above.
+
+2002-01-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libnetworking/rtems_telnetd/pty.c: Move config.h to were it belongs.
+ Remove printf (Reported by Till Straumann <strauman@SLAC.Stanford.EDU>).
+
+2002-01-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * score/include/rtems/system.h: Fix typo in yesterday's change:
+ RTEMS_MULTILIBS.
+
+2002-01-09 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Apply @subdirs. Remove POSIX_SUBDIRS. Remove
+ ITRON_SUBDIRS.
+ * configure.ac: Rework enable_unixlib handling. Add RTEMS_MULTILIBS to
+ cpuopts.h.
+ * include/Makefile.am: Add rtems/fs.h, rtems/userenv.h. Add
+ $(PROJECT_INCLUDE)/rtems. Remove libio_.h.
+
+2002-01-07 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * wrapup/Makefile.am: Add install-hook. Remove SIZE_RTEMS.
+ * include/rtems/fs.h: New, extracted from libio_.h.
+ * include/rtems/userenv.h: New. extracted from libio_.h.
+ * libmisc/rootfs/Makefile.am: Use include_rtems_HEADERS instead of
+ H_FILES.
+ * libfs/src/imfs/imfs_load_tar.c: Add include <sys/types.h>. Add include
+ <sys/stat.h>. Add include <fcntl.h>.
+ * libfs/src/imfs/imfs_rmnod.c: Add include <stdlib.h>.
+
+2002-01-07 Joel Sherrill <joel@OARcorp.com>
+
+ * posix/optman/, posix/optman/.cvsignore, posix/optman/Makefile.am,
+ sapi/optman/, sapi/optman/.cvsignore, sapi/optman/Makefile.am,
+ sapi/optman/no-ext.c, sapi/optman/no-io.c, rtems/optman/,
+ rtems/optman/.cvsignore, rtems/optman/Makefile.am,
+ rtems/optman/no-dpmem.c, rtems/optman/no-event.c, rtems/optman/no-mp.c,
+ rtems/optman/no-msg.c, rtems/optman/no-part.c, rtems/optman/no-region.c,
+ rtems/optman/no-rtmon.c, rtems/optman/no-sem.c,
+ rtems/optman/no-signal.c, rtems/optman/no-timer.c: Removed entire
+ contents of optman/ directory since it has been moved.
+
+2002-01-06 Joel Sherrill <joel@OARcorp.com>
+
+ * wrapup/.cvsignore: Readded.
+ * include/.cvsignore: New file.
+
+2002-01-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * score/include/rtems/seterr.h: Add do {..} while (0) in defines. Rename
+ set_errno_and_return_minus_one into rtems_set_errno_and_return_minus_one.
+ * libmisc/mw-fb/mw_uid.c: Apply rtems_set_errno_and_return_minus_one.
+ * libfs/src/imfs/imfs_eval.c, libfs/src/imfs/memfile.c,
+ libfs/src/imfs/imfs_readlink.c, libfs/src/imfs/imfs_unlink.c,
+ libfs/src/imfs/imfs_link.c, libfs/src/imfs/imfs_chown.c,
+ libfs/src/imfs/ioman.c, libfs/src/imfs/imfs_mount.c,
+ libfs/src/imfs/imfs_directory.c, libfs/src/imfs/imfs_stat.c,
+ libfs/src/imfs/imfs_fchmod.c, libfs/src/imfs/imfs_symlink.c,
+ libfs/src/imfs/imfs_mknod.c, libfs/src/imfs/linearfile.c,
+ libfs/src/imfs/imfs_unmount.c: Include <rtems/seterr.h>. Apply
+ rtems_set_errno_and_return_minus_one.
+ * libfs/src/imfs/imfs.h: Apply rtems_set_errno_and_return_minus_one.
+ Comment out increment_and_check_linkcounts.
+
+2002-01-04 Joel Sherrill <joel@OARcorp.com>
+
+ * Makefile.am, configure.ac: Remove references to wrapup subdirectory.
+
+2001-12-22 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use AS_IF instead of if/then/else. Add
+ AC_DEFINE_UNQUOTED(RTEMS_UNIX) for RTEMS_CPU==unix. Add
+ AC_DEFINE_UNQUOTED(RTEMS_UNIXLIB) for RTEMS_CPU==unix. Add
+ include/Makefile to CONFIG_FILES. Add AC_ENABLE_MULITLIB. Remove
+ wrapup/rtems, wrapup/itron, wrapup/posix. Remove */optman/Makefile from
+ CONFIG_FILES.
+ * Makefile.am: Add include to SUBDIRS.
+ * rtems/Makefile.am, sapi/Makefile.am: Remove optman from SUBDIRS.
+ * include/Makefile.am: New file.
+ * include/rtems/bspIo.h, include/rtems/libio_.h: Relocated from
+ lib/include.
+ * posix/configure.ac: Remove optman/Makefile from CONFIG_FILES.
+ * posix/Makefile.am: Remove optman from SUBDIRS.
+
+2001-12-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * wrapup/posix/Makefile.am, wrapup/itron/Makefile.am,
+ wrapup/rtems/Makefile.am, Makefile.am, itron/src/Makefile.am: Add
+ multilib support.
+ * posix/optman/Makefile.am: Add multilib support. Remove ASM4FLAGS.
+ * posix/src/Makefile.am: Add multilib support.
+ * score/inline/rtems/score/object.inl,
+ score/macros/rtems/score/object.inl: Add add casts to Objects_Id in
+ _Objects_Build_ids to avoid implicit typecasts from enum to int16 on
+ bit16 targets (here: h8300).
+ * score/src/Makefile.am, sapi/optman/Makefile.am, sapi/src/Makefile.am,
+ rtems/src/Makefile.am, rtems/optman/Makefile.am: Add multilib support.
+
+2001-12-18 Eric Norum <eric.norum@usask.ca>
+
+ * libnetworking/lib/tftpDriver.c: Allow chdir() to work on TFTP
+ `directories' (path names with a / at the end) while disallowing open()
+ operations on TFTP `directories'.
+
+2001-12-07 Eric Norum <eric.norum@usask.ca>
+
+ * libnetworking/lib/tftpDriver.c: Restore write capability.
+
+2001-11-29 Victor V. Vengerov <vvv@oktet.ru>
+
+ * AVL trees implementation added.
+
+2001-11-28 Joel Sherrill <joel@OARcorp.com>,
+
+ PR 91
+ * score/include/rtems/score/isr.h, score/inline/rtems/score/isr.inl,
+ score/macros/rtems/score/isr.inl: Modified to allow any port to provide
+ its own implementation of the macro _ISR_Is_in_progress. If the port
+ overrides this macro, it must provide a non-inlined function
+ implementation.
+
+2001-11-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libfs/wrapup/Makefile.am: Remove HAS_IMFS.
+
+2001-11-26 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libfs/src/imfs/Makefile.am: Cleanup.
+ * libnetworking/arpa/Makefile.am: Remove stray lines.
+
+2001-11-20 Joel Sherrill <joel@OARcorp.com>
+
+ * score/src/threadhandler.c: When __USE__MAIN__ is defined by the
+ toolset, invoke the global constructors via __main. Reported as tested
+ by Alexandra Kossovsky <sasha@oktet.ru> and Victor V. Vengerov
+ <vvv@oktet.ru> in conjunction with a new set of tool RPMs
+ (gcc2.95.3newlib1.9.0-3). This was tracked as GNATS PR tools/84.
+
+2001-11-16 Victor V. Vengerov <vvv@oktet.ru>
+
+ * libblock/include/rtems/bdbuf.h,
+ libblock/src/bdbuf.c(rtems_bdbuf_syncdev): New.
+
+2001-11-07 Victor V. Vengerov <vvv@oktet.ru>
+
+ * libblock/ChangeLog: New file.
+ * libblock/src/, libblock/include/, libblock/include/rtems/: New
+ directories.
+ * libblock/README, libblock/configure.ac, libblock/Makefile.am,
+ libblock/src/Makefile.am, libblock/include/Makefile.am,
+ libblock/include/rtems/bdbuf.h include/rtems/blkdev.h
+ include/rtems/diskdevs.h include/rtems/ramdisk.h src/bdbuf.c
+ src/blkdev.c src/diskdevs.c src/ramdisk.c: New files.
+
+2001-11-07 Joel Sherrill <joel@OARcorp.com>
+
+ Discovered while fixing PR36 reported by Todor.Todorov@barco.com.
+ * itron/include/rtems/itron/object.h: Corrected _ITRON_Objects_Get() to
+ use _Objects_Get_by_index().
+ PR 36 (Reported by Todor.Todorov@barco.com)
+ * score/include/rtems/score/object.h: Added prototype for
+ _Objects_Get_by_index().
+ * score/src/objectget.c, score/src/objectgetisr.c: Corrected procedure
+ for getting index from Id so it is correct and optimal for both single
+ and multiprocessor configurations.
+
+2001-11-07 Jennifer Averett <jennifer@OARcorp.com>
+
+ Reported by Ibragimov Ilya <ibr@oktet.ru> and tracked as PR49.
+ * libfs/ src/imfs/imfs_directory.c: Do not calculate the offset twice.
+
+2001-10-26 Victor V. Vengerov <vvv@oktet.ru>
+
+ * libfs/src/imfs/imfs_load_tar.c: Minor modification so this will
+ compile with gcc-2.95.3 with the arguments "-m5200 -O4".
+
+2001-10-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/macros/Makefile.am: Replace INLINES w/ MACROS (Fix stupid typo
+ in previous patch).
+
+2001-10-23 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/macros/rtems/rtems/asr.nil: Fixed typo.
+
+2001-10-22 Joel Sherrill <joel@OARcorp.com>
+
+ * score/src/threadhandler.c: Use __USE_INIT_FINI__ since USE_INIT_FINI
+ pollutes the application namespace.
+
+2001-10-18 Eric Norum <eric.norum@usask.ca>
+
+ * libnetworking/lib/tftpDriver.c: Properly handles ../ components in
+ chdir() and open() operations within the TFTP file system.
+
+2001-10-16 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use RTEMS_CPU_SUBDIRS to make autoconf-2.52 happy.
+ * configure.ac: Use AC_CONFIG_SUBDIRS for posix and itron. Reflect
+ changes to configuration of rtems, score and sapi subdirs.
+ * Makefile.am: require automake-1.5.
+ * itron/include/itronsys/Makefile.am, itron/include/rtems/Makefile.am,
+ itron/include/rtems/itron/Makefile.am, itron/inline/rtems/Makefile.am,
+ itron/inline/rtems/itron/Makefile.am, itron/macros/rtems/Makefile.am,
+ itron/macros/rtems/itron/Makefile.am: Remove.
+ * itron/include/Makefile.am, itron/inline/Makefile.am,
+ itron/macros/Makefile.am: handle subdirs.
+ * itron/configure.ac: Reflect changes above.
+ * posix/include/sys/Makefile.am, posix/include/rtems/Makefile.am,
+ posix/include/rtems/posix/Makefile.am: Remove.
+ * posix/include/Makefile.am: Handle subdirs.
+ * posix/inline/rtems/Makefile.am, posix/inline/rtems/posix/Makefile.am:
+ Remove.
+ * posix/inline/Makefile.am: Handle subdirs.
+ * posix/macros/rtems/Makefile.am, posix/macros/rtems/posix/Makefile.am:
+ Remove.
+ * posix/macros/Makefile.am: Handle subdirs.
+ * posix/configure.ac: Reflect changes above.
+ * score/include/rtems/Makefile.am, score/include/rtems/Makefile.am:
+ Remove.
+ * score/include/Makefile.am: Handle subdirs, require automake-1.5.
+ * score/macros/rtems/Makefile.am, score/macros/rtems/score/Makefile.am:
+ Remove.
+ * score/macros/Makefile.am: Handle subdirs, require automake-1.5.
+ * score/inline/rtems/Makefile.am, score/inline/rtems/score/Makefile.am:
+ Remove.
+ * score/inline/Makefile.am: Handle subdirs, require automake-1.5.
+ * score/Makefile.am: require automake-1.5.
+ * sapi/include/rtems/Makefile.am: Remove.
+ * sapi/include/Makefile.am: Handle subdirs, require automake-1.5.
+ * sapi/inline/rtems/Makefile.am: Remove.
+ * sapi/inline/Makefile.am: Handle subdirs, require automake-1.5.
+ * sapi/macros/rtems/Makefile.am: Remove.
+ * sapi/Makefile.am: require automake-1.5.
+ * rtems/include/rtems/Makefile.am,
+ rtems/include/rtems/rtems/Makefile.am: Remove.
+ * rtems/include/Makefile.am: Handle subdirs, require automake-1.5.
+ * rtems/inline/rtems/Makefile.am, rtems/inline/rtems/rtems/Makefile.am:
+ Remove.
+ * rtems/inline/Makefile.am: Handle subdirs, require automake-1.5.
+ * rtems/macros/rtems/Makefile.am, rtems/macros/rtems/rtems/Makefile.am:
+ Remove.
+ * rtems/macros: Handle subdirs, require automake-1.5.
+ * rtems/Makefile.am: require automake-1.5.
+
+2001-10-16 Joel Sherrill <joel@OARcorp.com>
+
+ * score/.cvsignore: Add stamp-h.in.
+ * score/include/Makefile.am: Fixed path to cpuopts-tmp.h.
+
+2001-10-16 Chris Johns <ccj@acm.org>
+
+ * sapi/include/confdefs.h, sapi/include/rtems/config.h,
+ sapi/include/rtems/io.h, sapi/optman/no-io.c, sapi/src/exinit.c,
+ sapi/src/io.c: Added a device driver register/unregister interface to
+ allow device drivers to be installed and removed at runtime. This means
+ you do not need devices present in the device table when you build.
+ * libfs/imfs/imfs_load_tar.c: Changed the code around to remove an
+ internal compiler error on the Coldfire target.
+
+2001-10-12 Mike Siers <mikes@poliac.com>
+
+ * Update to stable working state.
+ * libnetworking/modem_example/16550.h,
+ libnetworking/modem_example/README, libnetworking/modem_example/modem.c,
+ libnetworking/modem_example/modem.h, libnetworking/modem_example/ppp.c,
+ libnetworking/modem_example/ppp.h,
+ libnetworking/modem_example/pppcompress.c: Files removed.
+ * libnetworking/pppd/example/pppd.options: New file.
+ * libnetworking/pppd/README, libnetworking/pppd/STATUS,
+ libnetworking/pppd/cbcp.c, libnetworking/pppd/cbcp.h,
+ libnetworking/pppd/chat.c, libnetworking/pppd/pppd.h,
+ libnetworking/pppd/rtemsmain.c: Updated.
+
+2001-10-12 Joel Sherrill <joel@OARcorp.com>
+
+ * sapi/include/rtems/directives.h, libmisc/rootfs/mkrootfs.c,
+ libmisc/rootfs/mkrootfs.h: Fixed typo.
+
+2001-10-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * .cvsignore: Add autom4te.cache for autoconf > 2.52.
+ * configure.in: Remove.
+ * configure.ac: New file, generated from configure.in by autoupdate.
+ * itron/.cvsignore: Add autom4te.cache for autoconf > 2.52.
+ * itron/configure.in: Remove.
+ * itron/configure.ac: New file, generated from configure.in by
+ autoupdate.
+ * posix/.cvsignore: Add autom4te.cache for autoconf > 2.52.
+ * posix/configure.in: Remove.
+ * posix/configure.ac: New file, generated from configure.in by
+ autoupdate.
+ * libmisc/.cvsignore: Add autom4te.cache for autoconf > 2.52.
+ * libmisc/configure.in: Remove.
+ * libmisc/configure.ac: New file, generated from configure.in by
+ autoupdate.
+ * librpc/.cvsignore: Add autom4te.cache for autoconf > 2.52.
+ * librpc/configure.in: Remove.
+ * librpc/configure.ac: New file, generated from configure.in by
+ autoupdate.
+ * libfs/.cvsignore: Add autom4te.cache for autoconf > 2.52.
+ * libfs/configure.in: Remove.
+ * libfs/configure.ac: New file, generated from configure.in by
+ autoupdate.
+ * libnetworking/.cvsignore: Add autom4te.cache for autoconf > 2.52.
+ * libnetworking/configure.in: Remove.
+ * libnetworking/configure.ac: New file, generated from configure.in by
+ autoupdate.
+
+2001-10-10 Joel Sherrill <joel@OARcorp.com>
+
+ * libfs/src/imfs/imfs_getchild.c: Correct length of static string as
+ reported by Ibragimov Ilya <ibr@oktet.ru>.
+
+2001-09-28 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * score/include/rtems/score/Makefile.am,
+ score/include/rtems/Makefile.am, score/inline/rtems/score/Makefile.am,
+ score/macros/rtems/score/Makefile.am, sapi/include/rtems/Makefile.am,
+ sapi/include/Makefile.am, sapi/inline/rtems/Makefile.am,
+ sapi/macros/rtems/Makefile.am, rtems/include/rtems/rtems/Makefile.am,
+ rtems/include/Makefile.am, rtems/inline/rtems/rtems/Makefile.am,
+ rtems/macros/rtems/rtems/Makefile.am, libmisc/untar/Makefile.am,
+ libmisc/monitor/Makefile.am, libmisc/shell/Makefile.am,
+ libmisc/devnull/Makefile.am, libmisc/dumpbuf/Makefile.am,
+ libmisc/mw-fb/Makefile.am, libmisc/stackchk/Makefile.am,
+ libmisc/rtmonuse/Makefile.am, libmisc/cpuuse/Makefile.am,
+ libmisc/rootfs/Makefile.am, librpc/include/rpc/Makefile.am,
+ libfs/src/imfs/Makefile.am: Use 'PREINSTALL_FILES ='.
+
+2001-09-28 Joel Sherrill <joel@OARcorp.com>
+
+ * posix/src/mqueueopen.c, posix/src/semopen.c: Clarify type on va_arg.
+ * libmisc/dummy/dummy.c: Now a useful configuration that starts main().
+ * libmisc/wrapup/Makefile.am: Include a base level configuration in
+ RTEMS library.
+
+2001-09-27 Joel Sherrill <joel@OARcorp.com>
+
+ * libmisc/ChangeLog: Fixed typo in date.
+
+2001-09-27 Eric Norum <eric.norum@usask.ca>
+
+ * score/src/threadhandler.c: Now process C++ global constructors (_init)
+ as part of the first task execution not in BSP space. This depends on
+ the toolset defining USE_INIT_FINI so you have to have the right toolset
+ version.
+ * libnetworking/lib/tftpDriver.c: Add limited chdir() support to the
+ TFTP filesystem.
+
+2001-09-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * itron/include/itronsys/Makefile.am,
+ itron/include/rtems/itron/Makefile.am, itron/include/Makefile.am,
+ itron/inline/rtems/itron/Makefile.am,
+ itron/macros/rtems/itron/Makefile.am, posix/include/sys/Makefile.am,
+ posix/include/rtems/posix/Makefile.am, posix/include/Makefile.am,
+ posix/inline/rtems/posix/Makefile.am,
+ posix/macros/rtems/posix/Makefile.am,
+ score/include/rtems/score/Makefile.am, score/include/rtems/Makefile.am,
+ score/inline/rtems/score/Makefile.am,
+ score/macros/rtems/score/Makefile.am, libnetworking/machine/Makefile.am,
+ libnetworking/net/Makefile.am, libnetworking/netinet/Makefile.am,
+ libnetworking/vm/Makefile.am, libnetworking/pppd/Makefile.am,
+ libnetworking/sys/Makefile.am, libnetworking/rtems_servers/Makefile.am,
+ libnetworking/arpa/Makefile.am, libnetworking/nfs/Makefile.am,
+ libnetworking/rtems_webserver/Makefile.am,
+ libnetworking/rtems/Makefile.am,
+ libnetworking/rtems_telnetd/Makefile.am: Use 'PREINSTALL_FILES ='.
+
+2001-09-22 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * wrapup/rtems/Makefile.am: Fix comments to make automake-1.5 happy.
+ * itron/src/Makefile.am: Revamp INCLUDES handling to make automake-1.5
+ happy.
+ * posix/optman/Makefile.am: Adapt ASM4FLAGS to automake-1.5 happy.
+ * posix/src/Makefile.am: Adapt INCLUDES to make automake-1.5 happy.
+ * sapi/optman/Makefile.am: Adapt ASM4FLAGS to automake-1.5.
+ * libfs/src/imfs/Makefile.am: Revamp INCLUDES handling to make
+ automake-1.5 happy.
+ * libnetworking/Makefile.am: Use PREINSTALL_FILES = to make automake-1.5
+ happy.
+
+2001-09-21 Joel Sherrill <joel@OARcorp.com>
+
+ * libmisc/configure.in, libmisc/rootfs/Makefile.am: Added conditional to
+ make sure rootfs does not get built with networking is disabled. Also
+ added include of compile.am to rootfs/Makefile.am.
+ * libmisc/wrapup/Makefile.am: Added rootfs conditionally if networking
+ enabled.
+
+2001-09-19 Eric Norum <eric.norum@usask.ca>
+
+ * libnetworking/lib/tftpDriver.c: Add some debugging capability.
+
+2001-09-19 Chris Johns <ccj@acm.org>
+
+ * Added support for populating the initial "root" filesystem with
+ information obtained via the DHCP response.
+ * libmisc/rootfs: New directory.
+ * libmisc/rootfs/.cvsignore, libmisc/rootfs/Makefile.am,
+ libmisc/rootfs/mkrootfs.c, libmisc/rootfs/mkrootfs.h: New files.
+ * libmisc/configure.in, libmisc/Makefile.am: Modified to reflect
+ addition.
+ * nfs/bootp_subr.c, rtems/rtems_bootp.c, rtems/rtems_bsdnet.h,
+ rtems/rtems_bsdnet_internal.h Added support for populating the initial
+ "root" filesystem with information obtained via the DHCP response.
+
+2001-09-14 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libmisc/aclocal/canonical-target-name.m4: Use AC_CANONICAL_TARGET
+ instead of AC_CANONICAL_SYSTEM.
+ * libmisc/aclocal/config-subdirs.m4: Use AS_MKDIR_P instead of
+ mkinstalldirs and mkdir.
+ * libmisc/aclocal/target.m4: Obsolete RTEMS_OUTPUT_BUILD_SUBDIRS, hack
+ RTEMS_CONFIG_BUILD_SUBDIRS, introduce _RTEMS_OUTPUT_BUILD_SUBDIRS.
+ * libmisc/aclocal/canonical-target-name.m4: Use AC_CANONICAL_TARGET
+ instead of AC_CANONICAL_SYSTEM.
+ * libmisc/aclocal/config-subdirs.m4: Use AS_MKDIR_P instead of
+ mkinstalldirs and mkdir.
+ * libmisc/aclocal/target.m4: Obsolete RTEMS_OUTPUT_BUILD_SUBDIRS, hack
+ RTEMS_CONFIG_BUILD_SUBDIRS, introduce _RTEMS_OUTPUT_BUILD_SUBDIRS.
+
+2001-09-14 Fernando Ruiz <fernando.ruiz@ctv.es>
+
+ * rtems/src/tasks.c: Dereference pointer passed to destructor.
+ * libmisc/shell/shell.c: Don't close file it wasn't open.
+
+2001-09-13 Joel Sherrill <joel@OARcorp.com>
+
+ * posix/src/sysconf.c: Fix typo syntax error accidentally committed.
+ * posix/src/mprotect.c: New file. Stub required by some gcc's to pass
+ tests. In particular, about 350 ACATS tests fail if this is not present.
+ * posix/src/getpagesize.c: Ditto.
+ * posix/src/sysconf.c: Addition of Solaris value for _SC_STACK_PROT
+ required to pass about 350 ACATS test cases.
+ * posix/src/Makefile.am: Added new files.
+ * libmisc/devnull/devnull.c: Eliminate warning.
+
+2001-08-30 Joel Sherrill <joel@OARcorp.com>
+
+ * posix/macros/rtems/posix/mqueue.inl: Add cast so negation works.
+ * score/ src/coremutex.c, score/src/coremutexseize.c,
+ score/src/coremutexsurrender.c, score/inline/rtems/score/coremutex.inl:
+ The per thread field resource_count should only be manipulated when a
+ mutex is priority ceiling or priority inherit. This was reported by
+ Chris Johns <ccj@acm.org> who also noticed that the use of switches for
+ all disciplines generated less efficient code than using explicit tests
+ for the one or two cases we were really interested in. Further review
+ of his modifications made it apparent that the "isa" methods to test
+ mutex discipline were not being used so this modification was swept into
+ the code as well.
+ * score/src/coremutexseize.c: Add missing code for proper handling of
+ nesting acquisitions. This only impacts building with inlines disabled
+ on the source with the "fast mutex" optimizations. This was post the 4.5
+ branch and did not impact released versions.
+ * rtems/inline/rtems/rtems/attr.inl: Correct typo and use correct
+ attribute RTEMS_SYSTEM_TASK. Reported by Chris Johns <ccj@acm.org>.
+
+2001-08-16 Mike Siers <mikes@poliac.com>
+
+ * libnetworking/pppd/STATUS: Updated by Joel based upon email from Mike.
+ * libnetworking/pppd/cbcp.c, libnetworking/pppd/cbcp.h: Readded files.
+ These support callback functionality that has not even been compiled
+ under RTEMS yet.
+ * libnetworking/pppd/*: Update of PPPD to 2.3.11 from 2.3.5 and addition
+ of an example application. - renamed error() function because of
+ namespace problems. - removed calls to the exit() function. - removed
+ extra files from the pppd source directory. - defined pppd task constant
+ values in rtemspppd.h. - modifyied example code to get actual tick per
+ second value. - placed the pppd 2.3.11 man page file (pppd.8) into the
+ pppd directory.
+ * libnetworking/pppd/cbcp.c, libnetworking/pppd/cbcp.h,
+ libnetworking/pppd/main.c, libnetworking/pppd/ppp_tty.c,
+ libnetworking/pppd/pppmain.c, libnetworking/pppd/rtems-ppp.c,
+ libnetworking/pppd/rtems-ppp.c: Deleted.
+ * libnetworking/pppd/pppd.8, libnetworking/pppd/rtemsmain.c,
+ libnetworking/pppd/rtemspppd.c, libnetworking/pppd/rtemspppd.h,
+ libnetworking/pppd/sys-rtems.c, libnetworking/pppd/utils.c,
+ libnetworking/pppd/example/Makefile, libnetworking/pppd/example/README,
+ libnetworking/pppd/example/init.c,
+ libnetworking/pppd/example/netconfig.h,
+ libnetworking/pppd/example/ppp.conf,
+ libnetworking/pppd/example/pppdapp.c,
+ libnetworking/pppd/example/system.h: New files.
+ * libnetworking/modem/ppp_tty.c, libnetworking/net/if_ppp.h,
+ libnetworking/pppd/Makefile.am, libnetworking/pppd/README,
+ libnetworking/pppd/STATUS, libnetworking/pppd/auth.c,
+ libnetworking/pppd/ccp.c, libnetworking/pppd/ccp.h,
+ libnetworking/pppd/chap.c, libnetworking/pppd/chap.h,
+ libnetworking/pppd/chap_ms.c, libnetworking/pppd/chap_ms.h,
+ libnetworking/pppd/chat.c, libnetworking/pppd/demand.c,
+ libnetworking/pppd/fsm.c, libnetworking/pppd/fsm.h,
+ libnetworking/pppd/ipcp.c, libnetworking/pppd/ipcp.h,
+ libnetworking/pppd/ipxcp.c, libnetworking/pppd/ipxcp.h,
+ libnetworking/pppd/lcp.c, libnetworking/pppd/lcp.h,
+ libnetworking/pppd/magic.c, libnetworking/pppd/magic.h,
+ libnetworking/pppd/options.c, libnetworking/pppd/patchlevel.h,
+ libnetworking/pppd/pathnames.h, libnetworking/pppd/pppd.h,
+ libnetworking/pppd/upap.c, libnetworking/pppd/upap.h: Modified.
+
+2001-08-16 Joel Sherrill <joel@OARcorp.com>
+
+ * posix/src/mqueuesendsupp.c: Account for possibly blocking during the
+ core send operation.
+ * score/src/coremutexsurrender.c: Use holder thread not executing thread
+ because even though they may and often are the same it is not guaranteed
+ unless the proper attribute is set.
+ * score/include/rtems/score/coremsg.h, score/src/coremsgsubmit.c: Add a
+ new return status to account for blocking sends. Otherwise, the caller
+ will think that the returned message status will have the ultimate
+ results of the operation. If the send times out, the final status will
+ be in the return_code of the thread.
+ * rtems/src/msgqsubmit.c: Add a comment indicating that we do not have
+ to account for possibly blocking during the core send operation because
+ Classic API message queue send is always non-blocking.
+ * libnetworking/pppd/example/Makefile: Removed.
+ * libnetworking/pppd/example/Makefile-user: Added was Makefile. Renamed
+ to avoid bootstrap -c clobbering it.
+ * libnetworking/rtems_telnetd/.cvsignore: New file.
+
+2001-08-09 Keith Outwater <vac4050@cae597.rsc.raytheon.com>
+
+ * libmisc/monitor/mon-command.c: Add support for partial command
+ matching. The monitor used to have this functionality before it was
+ overhauled to support addition of user commands.
+
+2001-08-09 Joel Sherrill <joel@OARcorp.com>
+
+ * itron/src/snd_mbx.c, itron/src/tsnd_mbf.c, posix/src/mqueuesendsupp.c,
+ score/include/rtems/score/coremsg.h,
+ score/inline/rtems/score/coremsg.inl, score/src/coremsgsubmit.c,
+ rtems/src/msgqsubmit.c: Unblocking message queue operations should NOT
+ use _Thread_Executing for return status since it is permissible to
+ invoke message send operations from an ISR. This was reported by Suvrat
+ Gupta <suvrat@utstar.com>.
+
+2001-08-09 Fernando-Ruiz Casas <correo@fernando-ruiz.com>
+
+ * libmisc/shell/pty.c: Moved to libnetworking/rtems_telnetd.
+ * libmisc/shell/Makefile.am, libmisc/shell/README, libmisc/shell/cmds.c,
+ libmisc/shell/shell.c, libmisc/shell/shell.h: Updates.
+ * libfs/src/imfs/imfs_eval.c: The CD_UP problem in imfs_eval has been
+ touched. The order of the questions is the key.
+ * libnetworking/Makefile.am, libnetworking/configure.in,
+ libnetworking/rtems_servers/Makefile.am,
+ libnetworking/rtems_servers/telnetd.c,
+ libnetworking/rtems_servers/telnetd.h,
+ libnetworking/rtems_telnetd/Makefile.am,
+ libnetworking/rtems_telnetd/README, libnetworking/rtems_telnetd/icmds.c,
+ libnetworking/rtems_telnetd/pty.c, libnetworking/rtems_telnetd/pty.h,
+ libnetworking/rtems_telnetd/telnetd.c,
+ libnetworking/rtems_telnetd/telnetd.h, libnetworking/wrapup/Makefile.am:
+ - pty and telnetd have a new subdir rtems_telnetd to avoid the side
+ effect when ftpd change. - the tcp/ip stats have been implemented into
+ icmds.c and started when telnetd daemon is started.
+ * libnetworking/rtems_servers/telnetd.c,
+ libnetworking/rtems_servers/telnetd.h: Removed.
+ * libnetworking/rtems_telnetd: New directory.
+ * libnetworking/rtems_telnetd/Makefile.am,
+ libnetworking/rtems_telnetd/README, libnetworking/rtems_telnetd/icmds.c,
+ libnetworking/rtems_telnetd/pty.c, libnetworking/rtems_telnetd/pty.h,
+ libnetworking/rtems_telnetd/telnetd.c,
+ libnetworking/rtems_telnetd/telnetd.h: New files.
+
+2001-07-06 Thomas Doerfler <Thomas.Doerfler@imd-systems.de>
+
+ * libfs/src/imfs/deviceio.c: Make sure errno gets set to reflect the
+ status from the driver.
+
+2001-06-14 Joel Sherrill <joel@OARcorp.com>
+
+ * libmisc/shell/telnetd.c, libmisc/shell/telnetd.h: Moved to
+ libnetworking/rtems_servers so the network stack to address network
+ depenendency.
+ * libmisc/shell/Makefile.am: Modified to reflect above.
+ * libnetworking/rtems_servers/telnetd.c, libnetworking/shell/telnetd.h:
+ Moved from libmisc/shell so the network stack to address network
+ depenendency.
+ * libnetworking/rtems_servers/Makefile.am: Modified to reflect above.
+
+2001-05-26 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libnetworking/rtems_servers/Makefile.am: Deleted blank lines.
+
+2001-05-25 Sergei Organov <osv@javad.ru>
+
+ * score/macros/rtems/score/coresem.inl,
+ score/inline/rtems/score/coresem.inl: Cut and paste problem incorrectly
+ enabled interrupts twice with the first time being too early.
+
+2001-05-25 Joel Sherrill <joel@OARcorp.com>
+
+ * libmisc/shell/cmds.c: Removed code from inappropriate source.
+ * libfs/src/imfs/imfs_initsupp.c: Create the root node with the desired
+ permissions. Nodes should be created with the right permissions because
+ chmod() is not supported by the miniIMFS so changing after creation is
+ not possible.
+
+2001-05-24 Joel Sherrill <joel@OARcorp.com>
+
+ * libcsupport/src/.cvsignore: New file.
+
+2001-05-24 Fernando Ruiz Casas <fernando.ruiz@ctv.es>
+
+ * posix/src/getegid.c, posix/src/geteuid.c, posix/src/getgid.c,
+ posix/src/getlogin.c, posix/src/getuid.c: Now save their values in
+ private user environment.
+ * libmisc/monitor/mon-prmisc.c: Correct print line.
+ * libmisc/shell/Makefile.am: Added new file telnetd.c.
+ * libmisc/shell/telnetd.c, libmisc/shell/telnetd.h, libmisc/shell/pty.c:
+ New files.
+ * libmisc/shell/shell.c, libmisc/shell/cmds.c, libmisc/shell/shell.h:
+ Numerous improvments: - The shell_init has a new parameter 'forever'
+ because in /dev/console you need that this process runs forever but in
+ tcp/ip not. (respawn?) - A new task for every session opened trought
+ tcp/ip telnet client. (the chargen,daytime and more are possible of
+ implementation but I ask me if they are necesary) - Exit from the
+ session delete the task and when the client fails too. - More cmds have
+ been implemented. (very reduced version of these) umask, chmod, id,
+ whoami, rm, cat, ... - A reduced line edit has been implemented. Ctrl-C
+ abort the input, Ctrl-d in the first position gives EOF (logout). '\b'
+ and DEL makes the rubout operation. I think that readline() for every
+ session spents a lot of resources.
+
+2001-05-17 Joel Sherrill <joel@OARcorp.com>
+
+ * posix/macros/rtems/posix/mqueue.inl: Implemented missing routines to
+ support message queue FDs.
+ * score/macros/rtems/score/thread..inl: Implemented missing routines for
+ new libc reentrancy support.
+
+2001-05-14 Till Straumann <strauman@slac.stanford.edu>
+
+ * score/src/threaddispatch.c, score/src/threadhandler.c: Per PR211 fix
+ saving/restoring floating point context. The fpsave and fprestore
+ routines are only used in a executing context which _is_ fp and hence
+ has the FPU enabled. The current behavior required the FPU always to be
+ on which is very dangerous if lazy context switching is used. [Joel
+ Note: Some ports explicitly enabled the FPU in the FP save and restore
+ routines to avoid this.] The patch also makes sure (on powerpc only)
+ that the FPU is disabled for integer tasks. Note that this is crucial if
+ deferred fp context switching is used. Otherwise, fp context corruption
+ may go undetected! Also note that even tasks which merely push/pop FP
+ registers to/from the stack without modifying them still MUST be FP
+ tasks - otherwise (if lazy FP context switching is used), FP register
+ corruption (of other, FP, tasks may occur)! Furthermore, (on PPC) by
+ default, lazy FP context save/restore is _disabled_.
+
+2001-05-14 Joel Sherrill <joel@OARcorp.com>
+
+ * libmisc/dummy/Makefile.am, libmisc/wrapup/Makefile.am: Fixed to
+ generate a library of the same name.
+ * libnetworking/ChangeLog: Corrected -- entry should have been in
+ libchip.
+
+2001-05-09 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * score/include/rtems/score/.cvsignore: Add stamp-h, cpuopts.h,
+ cpuopts.h.in, cpuopts-tmp.h.
+ * libnetworking/libc/Makefile.am: Remove -D__STRICT_ANSI__.
+
+2001-05-09 Joel Sherrill <joel@OARcorp.com>
+
+ * sapi/src/exinit.c: Slightly rework initialization so there is a valid
+ thread as _Thread_Executing when the pre_tasking hook is called. This
+ allows one directives and malloc to potentially use mutex protection.
+
+2001-04-28 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libmisc/shell/cmds.c, libmisc/shell/shell.c: Remove fileno-hacks.
+ * libmisc/monitor/mon-symbols.c: Remove #undef __STRICT_ANSI__.
+
+2001-04-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.in, itron/configure.in, posix/configure.in,
+ libfs/configure.in: Add [-ansi -fasm] to RTEMS_PROG_CC_FOR_TARGET.
+
+2001-04-26 Joel Sherrill <joel@OARcorp.com>
+
+ * posix/include/rtems/posix/mqueue.h,
+ posix/inline/rtems/posix/mqueue.inl, posix/src/mqueue.c,
+ posix/src/mqueueclose.c, posix/src/mqueuecreatesupp.c,
+ posix/src/mqueuegetattr.c, posix/src/mqueuenotify.c,
+ posix/src/mqueueopen.c, posix/src/mqueuerecvsupp.c,
+ posix/src/mqueuesendsupp.c, posix/src/mqueuesetattr.c: Per PR81 reworked
+ to add a message queue descriptor separate from the underlying message
+ queue. This allows non-blocking to follow the "open" not the underlying
+ queue.
+ * score/src/objectcomparenamestring.c: Fix typos.
+ * score/include/rtems/score/object.h,
+ score/inline/rtems/score/object.inl, score/
+ src/objectcomparenamestring.c: Address PR81 that reworked POSIX message
+ queues to add a descriptor separate from the underlying message queue.
+ This allows non-blocking to follow the "open" not the underlying queue.
+ As part of debugging this it became clear that
+ _Objects_Compare_name_string was broken and a simple version using
+ strncmp() was substituted.
+
+2001-04-24 Joel Sherrill <joel@OARcorp.com>
+
+ * libfs/src/imfs/memfile.c (memfile_open): Did not set iop->size and
+ thus the value was incorrect. Before this field was cleared, this
+ resulted in the value from the last time that IOP was used being still
+ in place. Discovered by Andrew Bythell <abythell@nortelnetworks.com>.
+
+2001-04-24 Eric Norum <eric.norum@usask.ca>
+
+ * libnetworking/lib/rtems_bsdnet_ntp.c: Modifications to make the RTEMS
+ NTP synchronization a little more robust -- no NTP daemon yet, but at
+ least it trys a little harder when the primary NTP server is down.
+
+2001-04-22 Joel Sherrill <joel@OARcorp.com>
+
+ * itron/src/task.c (_ITRON_Task_User_extensions): Add new fields to be
+ correct in respect to newly added fields for separate switch list.
+
+2001-04-20 Radzislaw Galler <rgaller@et.put.poznan.pl>
+
+ * libnetworking/modem/ppp.c, libnetworking/pppd/main.c,
+ libnetworking/pppd/pppmain.c, libnetworking/pppd/rtems-ppp.c,
+ libnetworking/pppd/modem_example/modem.c,
+ libnetworking/pppd/modem_example/ppp.c: Translated Polish comments and
+ other strings into English.
+ * libnetworking/pppd/STATUS: updated to reflect the changes.
+
+2001-04-20 Joel Sherrill <joel@OARcorp.com>
+
+ * libmisc/devnull/devnull.c (null_initialize): Added check to ensure
+ that the driver is only initialized once. Otherwise, it will abort when
+ the device /dev/null is present. (null_write): Do not dereference a NULL
+ pointer.
+ * libfs/src/imfs/imfs_debug.c (IMFS_print_jnode): Modified to print only
+ information that does not vary based on target or memory configuration.
+ The old prints are still there in case they are needed in the future to
+ debug. Printing target dependent addresses makes the test output vary
+ by target unnecessarily.
+
+2001-04-20 Jake Janovetz <janovetz@uiuc.edu>
+
+ * libnetworking/rtems_servers/ftpd.c: Correct argument so hooks work
+ again.
+
+2001-04-20 Fernando Ruiz Casas <correo@fernando-ruiz.com>
+
+ * Added initial shell functionality.
+ * libmisc/Makefile.am, libmisc/configure.in, libmisc/wrapup/Makefile.am:
+ Reflect having added shell.
+ * libmisc/shell/.cvsignore, libmisc/shell/Makefile.am,
+ libmisc/shell/README, libmisc/shell/cmds.c, libmisc/shell/shell.c,
+ libmisc/shell/shell.h: New files.
+
+2001-04-16 Joel Sherrill <joel@OARcorp.com>
+
+ * sapi/include/confdefs.h: Fix real-time clock support.
+
+2001-04-11 Joel Sherrill <joel@OARcorp.com>
+
+ * score/macros/rtems/score/userext.inl: Now works after merging patch
+ for functionality requested in PR174.
+ * score/inline/rtems/score/userext.inl: Added a comment explaining the
+ order in which routines appear since it is not the obvious order.
+
+2001-04-08 Joel Sherrill <joel@OARcorp.com>
+
+ * score/macros/rtems/score/object.inl: Corrected arguments.
+ * score/macros/rtems/score/userext.inl: Updated to reflect modifications
+ to inline version from PR142.
+ * score/inline/rtems/score/userext.inl: Cleanup as side-effect of above.
+ * rtems/src/tasks.c: Pre-initialized switch extension for list.
+ * rtems/macros/rtems/score/timer.inl: Corrected typo on end of line.
+
+2001-04-04 Joel Sherrill <joel@OARcorp.com>
+
+ * libfs/src/dosfs/Makefile.am: Per PR129 do not install as many files to
+ the $(includedir).
+
+2001-03-29 Joel Sherrill <joel@OARcorp.com>
+
+ * Per PR126, configuration structures now match docs.
+ * sapi/include/rtems/config.h: Use public data types.
+ * Per PR126, configuration structures now match docs.
+ * rtems/include/rtems/rtems/config.h: Use public data types.
+ * Per PR147 addressed problems when reseting and inserting a timer into
+ a timer chain that did not honor time passage since the last time the
+ timer server was scheduled and the new insertion.
+ * rtems/include/rtems/rtems/timer.h, rtems/src/timerreset.c,
+ rtems/src/timerserver.c, rtems/src/timerserverfireafter.c,
+ rtems/src/timerserverfirewhen.c: Broke up the "reset server" routine
+ into a set of very specific routines that allowed the server to be
+ unscheduled, timer chains to be "synchronized" with the current time
+ before inserting a new timer.
+
+2001-03-28 Joel Sherrill <joel@OARcorp.com>
+
+ * PR132 requested some tinkering ot lower memory.
+ * sapi/include/confdefs.h: Lowered footprint of device driver table and
+ statically configure user extensions. Now if no static extensions are
+ configured, then the table is not instantiated.
+
+2001-03-26 Zoltan Kocsi <zoltan@bendor.com.au>
+
+ * rtems/src/eventsurrender.c: Clear event condition when task is
+ unblocked. This makes sure that subsequent event send thinks the task is
+ still blocked and overwrites the initial events received.
+
+2001-03-23 Joel Sherrill <joel@OARcorp.com>
+
+ * libfs/src/imfs/memfile.c: Reapply fix from bug report from Jose
+ Sturniolo <jsturnio@nec.com.ar> where NULL pointer was dereferenced when
+ freeing a triply indirect file. The fix was applied to the 4.5 release
+ branch and not the development branch.
+
+2001-03-20 Till Straumann <strauman@SLAC.Stanford.EDU>
+
+ * PR158
+ * libnetworking/libc/rcmd.c, libnetworking/libc/rcmd.c: Enable the
+ rcmd() library call by commenting out the parts that deal with signals.
+ This enables RTEMS to 'rsh' command to a server connecting fd to remote
+ stdio. The 'server-side' parts of this file which deal with
+ authentication are disabled since they are not needed.
+
+2001-03-19 Joel Sherrill <joel@OARcorp.com>
+
+ * posix/sys/utsname.h: Added C++ wrapper.
+
+2001-03-15 Ralf Corsepius <corsepius@faw.uni-ulm.de>
+
+ * libnetworking/include/.cvsignore: Remove dangling file.
+
+2001-03-15 Joel Sherrill <joel@OARcorp.com>
+
+ * sapi/src/extension.c: Split to reduce minimum code size per PR134.
+ * sapi/src/extensioncreate.c, sapi/src/extensiondelete.c,
+ sapi/src/extensionident.c: New files. src/Makefile.am: Modified to
+ reflect above.
+
+2001-03-01 Joel Sherrill <joel@OARcorp.com>
+
+ * libfs/src/imfs/.cvsignore: Added stamp-h1.in.
+
+2001-02-07 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.in: AC_DEFINE RTEMS_UNIX if RTEMS_CPU=unix.
+
+2001-02-06 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libmisc/monitor/mon-command.c: Use #if defined(RTEMS_UNIX).
+
+2001-02-03 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * itron/include/Makefile.am, itron/include/itronsys/Makefile.am,
+ itron/include/rtems/itron/Makefile.am,
+ itron/inline/rtems/itron/Makefile.am,
+ itron/macros/rtems/itron/Makefile.am, posix/include/Makefile.am,
+ posix/include/rtems/posix/Makefile.am, posix/include/sys/Makefile.am,
+ posix/inline/rtems/posix/Makefile.am,
+ posix/macros/rtems/posix/Makefile.am: Apply include_*HEADERS instead of
+ H_FILES.
+ * include/rtems/Makefile.am, include/rtems/score/Makefile.am,
+ inline/rtems/score/Makefile.am, macros/rtems/score/Makefile.am Apply
+ include_*HEADERS instead of H_FILES.
+ * sapi/include/Makefile.am, sapi/include/rtems/Makefile.am,
+ sapi/inline/rtems/Makefile.am, sapi/macros/rtems/Makefile.am,
+ rtems/include/Makefile.am, rtems/include/rtems/rtems/Makefile.am,
+ rtems/inline/rtems/rtems/Makefile.am,
+ rtems/macros/rtems/rtems/Makefile.am, rtems/ rtems/optman/Makefile.am,
+ libmisc/untar/Makefile.am, libmisc/monitor/Makefile.am,
+ libmisc/dummy/Makefile.am, libmisc/devnull/Makefile.am,
+ libmisc/dumpbuf/Makefile.am, libmisc/mw-fb/Makefile.am,
+ libmisc/stackchk/Makefile.am, libmisc/rtmonuse/Makefile.am,
+ libmisc/cpuuse/Makefile.am, librpc/include/rpc/Makefile.am,
+ libfs/src/imfs/Makefile.am, libnetworking/Makefile.am,
+ libnetworking/arpa/Makefile.am, libnetworking/machine/Makefile.am,
+ libnetworking/net/Makefile.am, libnetworking/ netinet/Makefile.am,
+ libnetworking/nfs/Makefile.am, libnetworking/rtems/Makefile.am,
+ libnetworking/ rtems_servers/Makefile.am,
+ libnetworking/rtems_webserver/Makefile.am,
+ libnetworking/sys/Makefile.am, libnetworking/vm/Makefile.am: Apply
+ include_*HEADERS instead of H_FILES.
+ * libnetworking/include/Makefile.am: Remove.
+ * libnetworking/Makefile.am: Add handling of *.h files.
+ * libnetworking/configure.in: Remove include/Makefile.
+
+2001-01-31 Sergei Organov <osv@javad.ru>
+
+ * libnetworking/rtems_servers/ftp.d: Following changes: - Hacks with
+ current dir and root dir removed in favor of new libio support for
+ task-local current and root directories. - Bug in `close_data_socket()'
+ introduced by previous change fixed. - `command_pasv()' changed to set
+ timeout on socket we are listening on and code fixed to don't close
+ socket twice on error. - `serr()' changed to clear `errno'. -
+ `data_socket()' changed to clear `errno' before `bind()'. - `session()'
+ changed to clear `errno' before processing session. -
+ `close_data_socket()' fixed to close both active and passive sockets. -
+ Initialize info->data_socket to -1 in `daemon()'. - Initialize `fname'
+ to empty string in `exec_command()'.
+
+2001-01-31 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/include/rtems/rtems/timer.h: Missed merging these modifications
+ in previous merge of new timer functionality.
+
+2001-01-29 Joel Sherrill <joel@OARcorp.com>
+
+ * score/src/objectextendinformation.c: Added include of string.h to
+ eliminate warning.
+ * Fixed bug where resetting a timer that was not at the head of one of
+ the task timer chains resulted in the Timer Server task waking up too
+ far in the future.
+ * Added rtems_timer_get_information() directive to support testing.
+ * src/timerserver.c, include/rtems/rtems/timer.h,
+ * rtems/src/timergetinfo.c: New file.
+ * rtems/src/Makefile.am: Modified to reflect above.
+
+2001-01-28 Ralf Corsepius <corsepiu@faw.uni-ulm.d>
+
+ * sapi/include/confdefs.h: define CONFIGURE_NEWLIB_EXTENSION 0 if not
+ using NEWLIB, cleanup related comment.
+
+2001-01-26 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * sapi/include/confdefs.h: include cpuopts.h, replace stubdr w/ devnull.
+
+2001-01-25 Eric Norum <eric.norum@usask.ca>
+
+ * libnetworking/lib/tftpDriver.c: Reduce first timeout interval. This
+ improves throughput on systems which are dropping packets. Only the
+ first timeout is reduced. This keeps the number of extra packets down
+ on networks that are very busy and dropping lots of packets.
+
+2001-01-24 Sergei Organov <osv@javad.ru>
+
+ * libnetworking/rtems_servers/ftpd.c,
+ libnetworking/rtems_servers/ftpd.h: - Timeouts on sockets implemented.
+ 'idle' field added to configuration. No timeout by default to keep
+ backward compatibility. Note: SITE IDLE command not implemented yet. -
+ Basic global access control implemented. 'access' field added to
+ configuration. No access limitations by default to keep backward
+ compatibility. - Anchor data socket for active mode (using self IP and
+ port 20.) - Fixed default data port support (still not tested). - Don't
+ allow IP address different from originating host in PORT command to
+ improve security. - Fixed bug in MDTM command. - Check for correctness
+ of parsing of argument in command_port(). - Fixed squeeze_path() to
+ don't allow names like 'NAME/smth' where 'NAME' is not a directory. -
+ Command parsing a little bit improved: command names are now converted
+ to upper-case to be more compatible with RFC (command names are not
+ case-sensitive.). - Reformat comments so that they have RTEMS
+ look-and-feel. - Fixed DELE, SITE CHMOD, RMD, MKD broken by previous
+ changes. - True ASCII mode implemented (doesn't work for hooks and
+ /dev/null) - Passive mode implemented, PASV command added. - Default
+ port for data connection could be used (untested, can't find ftp client
+ that doesn't send PORT command). - SYST reply changed to UNIX, as former
+ RTEMS isn't registered name. - Reply codes reviewed and fixed.
+
+2001-01-24 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * posix/configure.in: Add src/config.h.
+ * posix/src/Makefile.am: Add INCLUDES += -I. to pickup config.h.
+ * posix/src/.cvsignore: Add config.h and stamp-h.
+ * posix/src/*.c: Add config.h support.
+
+2001-01-23 Joel Sherrill <joel@OARcorp.com>
+
+ * posix/src/alarm.c: Eliminated use of C++ style comments.
+
+2001-01-22 Michael Hamel <mhamel@adi.co.nz>
+
+ * posix/include/rtems/posix/semaphore.h,
+ posix/inline/rtems/posix/semaphore.inl, posix/ src/ptimer1.c,
+ posix/include/rtems/posix/semaphore.h,
+ posix/inline/rtems/posix/semaphore.inl, posix/src/alarm.c,
+ posix/src/ptimer1.c, posix/src/semaphorenametoid.c, posix/src/semopen.c,
+ posix/src/semunlink.c, rtems/include/rtems.h, rtems/src/signalcatch.c:
+ Modifications to make CodeWarrior happy.
+
+2001-01-22 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/include/rtems/rtems/timer.h, rtems/src/timerserver.c: Add
+ priority argument to rtems_timer_initiate_server().
+
+2001-01-18 Joel Sherrill <joel@OARcorp.com>
+
+ * score/include/rtems/system.h, rtems/include/rtems/system.h: Only
+ include cpuopts.h when building a multilib configuration. Some ports
+ still need targopts.h but this small modification lets those ports work
+ non-multilib while fixing being fixed for multilib.
+
+2001-01-17 Joel Sherrill <joel@OARcorp.com>
+
+ * ChangeLog: Deleted duplicate blank line.
+
+2001-01-16 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libfs/configure.in: Add src/imfs/config.h.
+ * libfs/src/imfs/Makefile.am: Add INCLUDES += -I. to pickup config.h.
+ * libfs/src/imfs/.cvsignore: Add config.h and stamp-h.
+ * libfs/src/imfs/*.c: Add config.h support.
+
+2001-01-16 Joel Sherrill <joel@OARcorp.com>
+
+ * posix/inline/rtems/posix/mutex.inl (_POSIX_Mutex_Get_support):
+ Corrected name of routine in header.
+ * rtems/Added task-based timers to the Timer Manager. This added three
+ new directives: - rtems_timer_initiate_server -
+ rtems_timer_server_fire_after - rtems_timer_server_fire_when In the
+ process of doing this, a number of cleanups were made.
+ * rtems/src/timerserver.c, rtems/src/timerserverfireafter.c,
+ rtems/src/timerserverfirewhen.c: New files.
+ * rtems/include/timer/timer.h: Added new prototypes and supporting types.
+ * rtems/inline/rtems/rtems/timer.h, rtems/macros/rtems/rtems/timer.h:
+ Enhanced _Timer_Is_interval_class() to cover the class
+ TIMER_INTERVAL_ON_TASK.
+ * rtems/src/Makefile.am: Accounted for new files.
+ * rtems/src/rtemstimer.c: Added initialization of _Timer_Server variable.
+ * rtems/src/timercancel.c, rtems/src/timerreset.c: Account for addition
+ of timer classes. Also corrected the headers.
+ * rtems/src/timercreate.c, rtems/src/timerdelete.c,
+ rtems/src/timerfireafter.c, rtems/ src/timerfireafter.c,
+ rtems/src/timerident.c: Corrected header.
+ * rtems/src/taskmode.c: Ensure the this service does not dispatch before
+ tasking is enabled at initialization time.
+
+2001-01-12 Sergei Organov <osv@javad.ru>
+
+ * libnetworking/rtems_servers/ftpd.c,
+ libnetworking/rtems_servers/ftpd.h: - use pool of pre-created threads to
+ handle sessions instead of creating/deleting threads on the fly. - LIST
+ output is now similar to what "/bin/ls -al" would output, thus FTP
+ clients such Netscape are happy with it. - LIST NAME now works (both for
+ files and directories) - added support for NLST, CDUP, and MDTM FTP
+ commands to make more FTP clients happy . - keep track of CWD for every
+ session separately. - ability to specify root directory name for FTPD in
+ configuration table. FTPD will then create illusion for FTP clients that
+ this is actually root directory. - ignore options sent in commands, thus
+ LIST -al FILE works and doesn't try to list "-al" directory. - buffers
+ are allocated on stack instead of heap where possible to eliminate
+ malloc/free calls (avoid possible heap fragmentation troubles). - drop
+ using of task notepad to pass parameters - use function arguments
+ instead. - use snprintf() instead of sprintf() as the latter is unsafe.
+ - use of PF_INET in socket() instead of AF_INET.
+
+2001-01-12 Joel Sherrill <joel@OARcorp.com>
+
+ * posix/src/clockgetres.c: Fixed match problem. We are not converting
+ an interval to a timespec -- it is actually a real number of
+ microseconds.
+ * posix/src/README.mqueue: Enhanced example.
+
+2001-01-12 Jake Janovetz <janovetz@uiuc.edu>
+
+ * libfs/src/imfs/imfs.h, libfs/src/imfs/imfs_creat.c,
+ libfs/src/imfs/imfs_debug.c, libfs/src/imfs/imfs_eval.c,
+ libfs/src/imfs/imfs_fchmod.c, libfs/src/imfs/imfs_handlers_memfile.c,
+ libfs/src/imfs/imfs_init.c, libfs/src/imfs/imfs_initsupp.c,
+ libfs/src/imfs/imfs_stat.c, libfs/src/imfs/memfile.c,
+ libfs/src/imfs/miniimfs_init.c: Final developmental update to "tarfs".
+ When rtems_tarfs_load() is called, it checks the permissions on each
+ file. If there is write permission, it just creates a standard file
+ using "creat()" and therefore, uses the IMFS MEMORY_FILE. If there is no
+ write permission, it creates a LINEAR_FILE node with the appropriate
+ properties. If the permission is ever changed to writeable, IMFS_fchmod
+ converts it to a regular memory file.
+
+2001-01-08 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * score/src/threadinitialize.c: Removed warning.
+
+2001-01-08 Joel Sherrill <joel@OARcorp.com>
+
+ * score/src/threadinitialize.c: Fix my bad hack of Ralf's fp_area
+ warning removal patch. :(.
+
+2001-01-06 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * itron/configure.in: Add src/config.h.
+ * itron/src/Makefile.am: Add INCLUDES += -I. to pickup config.h.
+ * itron/src/.cvsignore: Add config.h and stamp-h.
+ * itron/src/*.c: Add config.h support.
+
+2001-01-05 Joel Sherrill <joel@OARcorp.com>
+
+ * libmisc/devnull: New addition. Moved from libcpu/sh.
+ * libmisc/devnull/devnull.c, libmisc/devnull/devnull.h,
+ libmisc/devnull/.cvsignore, libmisc/ devnull/Makefile.am: New files.
+ * libmisc/Makefile.am, libmisc/configure.in, libmisc/wrapup/Makefile.am:
+ Modified to reflect addition of above.
+
+2001-01-03 Joel Sherrill <joel@OARcorp.com>
+
+ * score/src/isr.c: Modify to properly dereference _ISR_Vector_table now
+ that it is dynamically allocated.
+
+2001-01-02 Joel Sherrill <joel@OARcorp.com>
+
+ * libnetworking/CHANGELOG: Removed.
+ * libnetworking/README: Merged CHANGELOG contents as initial changes.
+
+2000-12-19 Joel Sherrill <joel@OARcorp.com>
+
+ * posix/src/pthreadgetschedparam.c: Do not set output parameters if the
+ pointers are NULL.
+ * score/src/isr.c: Allocate the _ISR_Vector_table all the time not just
+ when we are allocating an interrupt stack.
+
+2000-12-14 Eric Norum <eric.norum@usask.ca>
+
+ * libnetworking/lib/tftpDriver.c: Added write capability.
+
+2000-12-13 Joel Sherrill <joel@OARcorp.com>
+
+ * score/include/rtems/score/isr.h, score/src/isr.c: Allocate it from the
+ workspace rather than explicitly declaring it. This allows the size to
+ be a non-constant from the perspective of score/cpu.
+
+2000-12-12 Jake Janovetz <janovetz@uiuc.edu>
+
+ * libfs/src/imfs/linearfile.c, libfs/src/imfs/imfs_load_tar.c: New files.
+ * libfs/src/imfs/Makefile.am, libfs/src/imfs/imfs.h,
+ libfs/src/imfs/imfs_creat.c, libfs/src/imfs/imfs_debug.c,
+ libfs/src/imfs/imfs_eval.c, libfs/src/imfs/imfs_handlers_memfile.c,
+ libfs/src/imfs/imfs_init.c, libfs/src/imfs/imfs_initsupp.c,
+ libfs/src/imfs/imfs_stat.c, libfs/src/imfs/miniimfs_init.c: Added
+ "tarfs". This is not really a tar filesystem. It is a way to load a tar
+ image into the IMFS but actually leave bulky file contents in the
+ original tar image. It essentially adds the linear file type and
+ associated support and a loader routine.
+
+2000-12-08 Joel Sherrill <joel@OARcorp.com>
+
+ * libnetworking/libc/linkaddr.c: Initialized variable to remove warning.
+ * libnetworking/modem/ppp.c, libnetworking/modem/ppp_tty.c: Made
+ numerous variable declarations conditional on PPP_COMPRESS and
+ PPP_FILTER. Commented out variables that were not used because the code
+ using them was commented out. Removed totally unused variables.
+ * libnetworking/modem/pppcompress.c: Added parentheses to avoid warnings.
+ * libnetworking/pppd/pppmain.c: Removed numerous warnings.
+
+2000-12-06 Joel Sherrill <joel@OARcorp.com>
+
+ * posix/src/pthreadgetcpuclockid.c: Add include of <rtems/system.h> to
+ eliminate warning.
+ * rtems/src/regiongetinfo.c: Removed unused variable to eliminate
+ warning.
+
+2000-12-01 Joel Sherrill <joel@OARcorp.com>
+
+ * configure.in: Removed error check for enabling macros with either
+ POSIX or ITRON API.
+ * Added macro support to ITRON API. This is known to compile.
+ * itron/Makefile.am: Added macros directory.
+ * itron/configure.in: Removed error check for enabling macros.
+ * itron/macros/.cvsignore, itron/macros/Makefile.am,
+ itron/macros/rtems/.cvsignore, itron/macros/rtems/Makefile.am,
+ itron/macros/rtems/itron/.cvsignore,
+ itron/macros/rtems/itron/Makefile.am,
+ itron/macros/rtems/itron/eventflags.inl,
+ itron/macros/rtems/itron/fmempool.inl,
+ itron/macros/rtems/itron/intr.inl, itron/macros/rtems/itron/mbox.inl,
+ itron/macros/rtems/itron/msgbuffer.inl,
+ itron/macros/rtems/itron/network.inl, itron/macros/rtems/itron/port.inl,
+ itron/macros/rtems/itron/semaphore.inl,
+ itron/macros/rtems/itron/sysmgmt.inl, itron/macros/rtems/itron/task.inl,
+ itron/macros/rtems/itron/time.inl,
+ itron/macros/rtems/itron/vmempool.inl: New files.
+ * posix/include/rtems/posix/cond.h: #if 0'ed out prototype of
+ _POSIX_Condition_variables_Get to avoid conflict with macro
+ implementation.
+ * Added macro support to POSIX API. This is known to compile.
+ * posix/macros/rtems/posix/cond.inl, posix/macros/rtems/posix/intr.inl,
+ posix/macros/rtems/posix/key.inl, posix/macros/rtems/posix/mqueue.inl,
+ posix/macros/rtems/posix/mutex.inl,
+ posix/macros/rtems/posix/priority.inl,
+ posix/macros/rtems/posix/pthread.inl,
+ posix/macros/rtems/posix/semaphore.inl,
+ posix/macros/rtems/posix/timer.inl: New files.
+ * posix/configure.in: Removed error check for enabling macros.
+ * posix/rtems/posix/mutex.h: #if 0'ed out prototypes for inlined
+ routines since you cannot have prototypes for macros.
+ * posix/macros/rtems/posix/Makefile.am: Added files.
+ * score/macros/rtems/score/coresem.inl: Removed comments since
+ convention calls for comments to be in inline versin.
+ * score/macros/rtems/score/object.inl (Objects_Get_local_object): Fixed
+ style to use _ prefix on variable names and use parentheses.
+ * score/macros/rtems/score/object.inl (_Objects_Namespace_remove): Added.
+
+2000-11-30 Joel Sherrill <joel@OARcorp.com>
+
+ * posix/inline/rtems/posix/mqueue.inl: Removed explicit dependency on
+ abs().
+ * General effort to make things compile with macros not inlines
+ * score/inline/rtems/score/coremutex.inl: Added comment indicating for
+ macros there is another copy of _CORE_mutex_Seize_interrupt_trylock() in
+ src/coremutexseize.c.
+ * score/src/coremutexseize.c: Added body of
+ _CORE_mutex_Seize_interrupt_trylock() for macro case.
+ * score/macros/rtems/score/coremutex.inl: Added prototype for
+ _CORE_mutex_Seize_interrupt_trylock() since there is a real body when
+ macros are enabled.
+ * score/macros/rtems/score/coresem.inl: Added macro implementation of
+ _CORE_semaphore_Seize_isr_disable.
+ * score/macros/score/Makefile.am: Fixed typos.
+ * score/rtems/score/address.inl: Correct macro implementation of
+ _Addresses_Is_aligned() so it would compile.
+ * score/macros/rtems/score/coremsg.inl: Added closing parentheses.
+ * rtems/src/msgqsubmit.c: Modified multiprocessing conditional so this
+ would compile with both macros and inlines.
+ * rtems/macros/rtems/rtems/sem.inl: Added macro implementation of
+ _Semaphore_Get_interrupt_disable().
+ * libmisc/mw-fb/mw_uid.c: Removed unnecessary dependency on <bsp.h>.
+ * libnetworking/modem/ppp_tty.c: Changed to include
+ <rtems/termiostypes.h> since that is an RTEMS specific header file.
+ * libnetworking/sys/ttycom.h: Moved to lib/include/sys.
+ * libnetworking/Makefile.am: Modified to reflect above.
+
+2000-11-28 Joel Sherrill <joel@OARcorp.com>
+
+ * libfs/src/imfs/memfile.c: Bug report from Sturniolo Jose
+ <jsturnio@nec.com.ar> where NULL pointer was dereferenced.
+
+2000-11-28 Chris Johns <ccj@acm.org>
+
+ * score/src/heapallocate.c: Do not allow the size to overflow when
+ adjusting it. A test allocated a stack of -1 (~0). This actually
+ resulted in a stack being allocated but with a size of 0xb. The
+ allocator did not test the size to see if it rolled through 0 and so
+ allowed the allocation to happen, the thread to get created. The task
+ crashed as you would expect.
+
+2000-11-27 Joel Sherrill <joel@OARcorp.com>
+
+ * posix/src/sysconf.c: Add support for _SC_CLK_TCK and _SC_OPEN_MAX.
+ * libnetworking/libc/res_init.c: Fix typo - adding missing # on include.
+
+2000-11-25 Eric Norum <eric.norum@usask.ca>
+
+ * libnetworking/libc/res_init.c: Move include to avoid compiler dumping
+ core.
+
+2000-11-25 Antti P Miettinen <antti.p.miettinen@nokia.com>
+
+ * libnetworking/wrapup/Makefile.am, libnetworking/configure.in,
+ libnetworking/Makefile.am: Added modem subdir.
+ * libnetworking/net/Makefile.am: Added if_pppvar.h, pppcompress.h.
+ * libnetworking/pppd/Makefile.am: Added pppmain.c (which needs work).
+ * libnetworking/pppd/chat.c, libnetworking/pppd/fsm.c,
+ libnetworking/pppd/fsm.h, libnetworking/pppd/ipxcp.c,
+ libnetworking/pppd/main.c, libnetworking/pppd/ppp_tty.c,
+ libnetworking/pppd/upap.c: Changes from Thomas Doerfler
+ <Thomas.Doerfler@imd-systems.de> and cosmetic changes by me. Actually
+ main.c and ppp_tty.c should be scratched. The modem subdir has the real
+ ppp_tty.c and the real pppd main is in pppmain.c.
+
+2000-11-17 Jennifer Averret <jennifer@OARcorp.com>
+
+ * libfs/src/imfs/imfs_eval.c: Always return imaginary node at mount
+ points.
+
+2000-11-09 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am, itron/Makefile.am, posix/Makefile.am,
+ libmisc/Makefile.am, librpc/Makefile.am, libfs/Makefile.am,
+ libnetworking/Makefile.am: Use ... instead of RTEMS_TOPdir in
+ ACLOCAL_AMFLAGS.
+
+2000-11-02 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am, itron/Makefile.am, posix/Makefile.am,
+ libmisc/Makefile.am, librpc/Makefile.am, libfs/Makefile.am,
+ libnetworking/Makefile.am: Switch to ACLOCAL_AMFLAGS = -I
+ $(RTEMS_TOPdir)/aclocal.
+
+2000-11-02 Joel Sherrill <joel@OARcorp.com>
+
+ * score/include/rtems/system.h: Use proper conditional (RTEMS_POSIX_API)
+ so prototypes for POSIX_MP_NOT_IMPLEMENTED(), POSIX_NOT_IMPLEMENTED(),
+ POSIX_BOTTOM_REACHED() are actually included.
+ * score/include/rtems/system.h: Add prototypes for
+ POSIX_MP_NOT_IMPLEMENTED(), POSIX_NOT_IMPLEMENTED(),
+ POSIX_BOTTOM_REACHED() removed from newlib.
+
+2000-11-01 Joel Sherrill <joel@OARcorp.com>
+
+ * libfs/src/imfs/Makefile.am, libfs/src/imfs/deviceio.c,
+ libfs/src/imfs/imfs_chown.c, libfs/src/imfs/imfs_config.c,
+ libfs/src/imfs/imfs_creat.c, libfs/src/imfs/imfs_debug.c,
+ libfs/src/imfs/imfs_directory.c, libfs/src/imfs/imfs_eval.c,
+ libfs/src/imfs/imfs_fchmod.c, libfs/src/imfs/imfs_free.c,
+ libfs/src/imfs/imfs_fsunmount.c, libfs/src/imfs/imfs_gtkn.c,
+ libfs/src/imfs/imfs_init.c, libfs/src/imfs/imfs_initsupp.c,
+ libfs/src/imfs/imfs_link.c, libfs/src/imfs/imfs_mknod.c,
+ libfs/src/imfs/imfs_mount.c, libfs/src/imfs/imfs_readlink.c,
+ libfs/src/imfs/imfs_rmnod.c, libfs/src/imfs/imfs_stat.c,
+ libfs/src/imfs/imfs_symlink.c, libfs/src/imfs/imfs_unixstub.c,
+ libfs/src/imfs/imfs_unlink.c, libfs/src/imfs/imfs_unmount.c,
+ libfs/src/imfs/imfs_utime.c, libfs/src/imfs/ioman.c,
+ libfs/src/imfs/memfile.c, libfs/src/imfs/miniimfs_init.c: assoc.h,
+ error.h, libio_.h, libio.h, and libcsupport.h moved from libc to
+ lib/include/rtems and now must be referenced as <rtems/XXX.h>. Now we
+ do not have to reach up and over to libc to pick them up.
+
+2000-10-30 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * posix/configure.in: Cleanup comments.
+
+2000-10-30 Joel Sherrill <joel@OARcorp.com>
+
+ * posix/include/Makefile.am: Updated to reflect files merged into
+ newlib. This resulted in some definitions moving to other files and thus
+ some secondary effects in RTEMS source code.
+ * posix/include/unistd.h: Removed. Now use newlib's.
+ * posix/include/rtems/posix/mqueue.h: Add include of <signal.h>.
+ * posix/include/rtems/posix/threadsup.h: Add include of <sys/signal.h>.
+ * posix/src/execv.c, posix/src/execve.c, posix/src/execvp.c: Corrected
+ prototype to agree with newlib.
+ * posix/src/psignal.c: Rewrote reference to <siginfo.h> in comment since
+ that file no longer exists.
+ * posix/src/pthreadkill.c, posix/src/sigaction.c: Added include of
+ <signal.h>.
+ * posix/src/sigtimedwait.c: Rewrote reference to <siginfo.h> in comment
+ since that file no longer exists.
+ * POSIX include files merged into newlib. This resulted in some
+ definitions moving to other files and thus some secondary effects in
+ RTEMS source code.
+ * sapi/include/confdefs.h: Replaced include of <sys/siginfo.h> with
+ <signal.h> since that file no longer exists.
+ * POSIX include files merged into newlib. This resulted in some
+ definitions moving to other files and thus some secondary effects in
+ RTEMS source code.
+ * librpc/src/rpc/Makefile.am, librpc/src/rpc/auth_time.c,
+ librpc/src/rpc/clnt_simple.c, librpc/src/rpc/clnt_tcp.c,
+ librpc/src/rpc/clnt_udp.c, librpc/src/rpc/clnt_unix.c,
+ librpc/src/rpc/get_myaddress.c, librpc/src/rpc/pmap_clnt.c,
+ librpc/src/rpc/pmap_getmaps.c, librpc/src/rpc/pmap_getport.c,
+ librpc/src/rpc/pmap_rmt.c, librpc/src/rpc/rtime.c,
+ librpc/src/rpc/svc_tcp.c, librpc/src/rpc/svc_udp.c,
+ librpc/src/rpc/svc_unix.c: Use of _read, _write, and _close as macros
+ conflicted with newlib's use of these as routine names. They were
+ renamed to include "_RPC_" prefix.
+ * POSIX include files merged into newlib. This resulted in some
+ definitions moving to other files and thus some secondary effects in
+ RTEMS source code.
+ * libnetworking/machine/types.h: Added _CLOCKID_T_ and _TIMER_T_ to be
+ in sync with newlib's <machine/types.h>.
+ * libnetworking/rtems/rtems_bsdnet_internal.h: newlib now includes
+ definition of struct itimerval in <sys/time.h>.
+
+2000-10-25 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am, itron/Makefile.am, posix/Makefile.am,
+ libmisc/Makefile.am, librpc/Makefile.am, libnetworking/Makefile.am:
+ ACLOCAL_AMFLAGS= -I $(RTEMS_TOPdir)/macros. Switch to GNU
+ canonicalization.
+
+2000-10-24 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libfs/Makefile.am, libfs/configure.in: Introduce GNU canonicalization
+ to libfs/. The approach is currently a bit of a hack as GNU
+ canonicalization does not support the per-BSP build some of the other
+ directories require. As more of the tree is converted, this will become
+ less of an issue.
+
+2000-10-24 Joel Sherrill <joel@OARcorp.com>
+
+ * libfs/src/imfs/imfs_config.c: New file containing IMFS configuration
+ information split from libc/base_fs.c.
+ * libfs/src/imfs/ioman.c: New file. Moved from lib/libc. Missed
+ previously.
+ * libfs/src/imfs/Makefile.am: Added imfs_config.c and ioman.c.
+
+2000-10-19 Joel Sherrill <joel@OARcorp.com>
+
+ * libfs/.cvsignore, libfs/src/.cvsignore, libfs/src/imfs/.cvsignore,
+ libfs/wrapup/.cvsignore: New files.
+
+2000-10-19 Antti P Miettinen <anmietti@trshp.ntc.nokia.com>
+
+ * libnetworking/lib/tftpDriver.c: add comments to handlers struct
+ function pointers.
+ * libnetworking/rtems/rtems_glue.c: move pointer arithmetic to be
+ _after_ pointer has been checked against NULL.
+
+2000-10-18 Nick Simon <Nick.SIMON@syntegra.bt.co.uk>
+
+ * score/src/heapgetinfo.c, score/include/rtems/score/heap.h,
+ score/src/Makefile.am: Added _Heap_Get_information() and information
+ control block.
+ * score/src/heapgetinfo.c: New file.
+
+2000-10-18 Joel Sherrill <joel@OARcorp.com>
+
+ * sapi/include/confdefs.h: Set CONFIGURE_INIT_TASK_STACK_SIZE to 0 if
+ there is no Classic API Initialization Tasks Table defined.
+ * sapi/include/confdefs.h: Modified code that accounts for
+ initialization task/threads with greater than minimum stack sizes so it
+ would compile even if optional APIs are disabled.
+ * rtems/src/regiongetinfo.c, rtems/include/rtems/rtems/region.h,
+ rtems/include/rtems/rtems/types.h, rtems/src/Makefile.am: Added
+ region_get_information() and information control block.
+ * rtems/src/regiongetinfo.c: New file.
+
+2000-10-18 Chris Johns <ccj@acm.org>
+
+ * libfs created.
+ * libfs/src, libfs/src/imfs, libfs/wrapup: New directories.
+ * libfs/ChangeLog, libfs/Makefile.am, libfs/README, libfs/configure.in,
+ libfs/src/Makefile.am, libfs/wrapup/Makefile.am: New files.
+ * libfs/src/imfs/deviceio.c, libfs/src/imfs/imfs_getchild.c,
+ libfs/src/imfs/imfs_readlink.c, libfs/src/imfs/imfs.h,
+ libfs/src/imfs/imfs_gtkn.c, libfs/src/imfs/imfs_rmnod.c,
+ libfs/src/imfs/imfs_chown.c, libfs/src/imfs/imfs_handlers_device.c,
+ libfs/src/imfs/imfs_stat.c, libfs/src/imfs/imfs_creat.c,
+ libfs/src/imfs/imfs_handlers_directory.c, libfs/src/imfs/imfs_symlink.c,
+ libfs/src/imfs/imfs_debug.c, libfs/src/imfs/imfs_handlers_link.c,
+ libfs/src/imfs/imfs_unixstub.c, libfs/src/imfs/imfs_directory.c,
+ libfs/src/imfs/imfs_handlers_memfile.c, libfs/src/imfs/imfs_unlink.c,
+ libfs/src/imfs/imfs_eval.c, libfs/src/imfs/imfs_init.c,
+ libfs/src/imfs/imfs_unmount.c, libfs/src/imfs/imfs_fchmod.c,
+ libfs/src/imfs/imfs_initsupp.c, libfs/src/imfs/imfs_utime.c,
+ libfs/src/imfs/imfs_fcntl.c, libfs/src/imfs/imfs_link.c,
+ libfs/src/imfs/memfile.c, libfs/src/imfs/imfs_fdatasync.c,
+ libfs/src/imfs/imfs_mknod.c, libfs/src/imfs/miniimfs_init.c,
+ libfs/src/imfs/imfs_free.c, libfs/src/imfs/imfs_mount.c,
+ libfs/src/imfs/imfs_fsunmount.c, libfs/src/imfs/imfs_ntype.c: New files.
+ Moved from libc.
+ * libnetworking/pppd/ipxcp.c: Fixed a typo.
+
+2000-10-12 Joel Sherrill <joel@OARcorp.com>
+
+ * sapi/include/confdefs.h: Account for initialization tasks and threads
+ which use larger than minimum stack sizes.
+
+2000-09-29 Stephan Merker <merker@decrc.abb.de>
+
+ * rtems/include/rtems/rtems/ratemon.h, rtems/src/ratemonperiod.c,
+ rtems/src/ratemontimeout.c: Add next_length field so period length can
+ be changed by the the sequence period(X), period(not X) with no
+ intervening cancel or expiration.
+
+2000-09-28 Joel Sherrill <joel@OARcorp.com>
+
+ * sapi/include/rtems/io.h (rtems_driver_address_table): Added "_entry"
+ to all names.
+ * sapi/src/io.c: Accounted for above.
+ * libmisc/monitor/mon-driver.c: Accounted for addition of "_entry" to
+ fields in rtems_driver_address_table.
+ * libnetworking/rtems_webserver/Makefile.am,
+ libnetworking/rtems_webserver/base64.c,
+ libnetworking/rtems_webserver/base64.c: Renamed base64.c to wbase64.c.
+ * libnetworking/rtems_webserver/sock.c: Added file missed in merger.
+
+2000-09-25 Joel Sherrill <joel@OARcorp.com>
+
+ * score/rtems/system.h: Switched a29k and hppa1.1 to using cpuopts.h not
+ targopts.h to reduce dependency on BSP.
+
+2000-09-22 Joel Sherrill <joel@OARcorp.com>
+
+ * librpc/src/xdr/xdr_float.c: Added A29K support.
+ * libnetworking/machine/types.h, libnetworking/pppd/pppd.h,
+ libnetworking/rtems/rtems_bsdnet_internal.h,
+ libnetworking/rtems_webserver/webmain.c: machine/types.h should not
+ have included rtems.h. It is now including precisely the least amount
+ of low level, yet portable .h files to get the basic RTEMS types
+ defined. This rippled into other files since rtems_bsdnet_internal.h
+ used machine/types.h to include rtems.h.
+
+2000-09-20 Joel Sherrill <joel@OARcorp.com>
+
+ * score/src/objectgetbyindex.c: Do not enable dispatching on an error
+ path it was not disabled on.
+
+2000-09-06 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * wrapup/rtems/Makefile.am: Use PROJECT_TOPdir in path to size_rtems.
+ * libnetworking/ChangeLog: Cleanup.
+
+2000-09-05 Joel Sherrill <joel@OARcorp.com>
+
+ * libnetworking/rtems/rtems_syscall.c: Changed from O_NONBLOCK to
+ internal RTEMS_LIBIO_FLAGS_NO_DELAY to avoid O_NONBLOCK/O_NDELAY
+ confusion and to work with the converted flags.
+
+2000-09-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * wrapup/itron/Makefile.am, wrapup/posix/Makefile.am,
+ wrapup/rtems/Makefile.am, itron/src/Makefile.am, posix/src/Makefile.am,
+ posix/optman/Makefile.am, score/src/Makefile.am, sapi/src/Makefile.am,
+ sapi/optman/Makefile.am, rtems/optman/Makefile.am,
+ rtems/src/Makefile.am, libmisc/cpuuse/Makefile.am,
+ libmisc/dummy/Makefile.am, libmisc/dumpbuf/Makefile.am,
+ libmisc/monitor/Makefile.am, libmisc/rtmonuse/Makefile.am,
+ libmisc/stackchk/Makefile.am, libmisc/untar/Makefile.am,
+ libmisc/wrapup/Makefile.am, libmisc/mw-fb/Makefile.am,
+ librpc/src/rpc/Makefile.am, librpc/src/xdr/Makefile.am,
+ libnetworking/kern/Makefile.am, libnetworking/lib/Makefile.am,
+ libnetworking/libc/Makefile.am, libnetworking/net/Makefile.am,
+ libnetworking/netinet/Makefile.am, libnetworking/nfs/Makefile.am,
+ libnetworking/pppd/Makefile.am, libnetworking/rtems/Makefile.am,
+ libnetworking/rtems_servers/Makefile.am,
+ libnetworking/rtems_webserver/Makefile.am,
+ libnetworking/wrapup/Makefile.am: Include compile.am.
+
+2000-09-01 Rosimildo daSilva <rdasilva@connecttel.com>
+
+ * libnetworking/emfdb.c: Removed stray semi-colon. Reported on GoAhead
+ mailing lists by Jim Rudnicki <jdrudnicki@yahoo.com>.
+
+2000-08-31 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * libnetworking/netinet/tcp_input.c: Spelling corrections.
+
+2000-08-31 Joel Sherrill <joel@OARcorp.com>
+
+ * Merged version 2.1 of GoAhead webserver. This update was submitted by
+ Antti P Miettinen <antti.p.miettinen@nokia.com>.
+ * libnetworking/NOTES, libnetworking/base64.c, libnetworking/ejIntrn.h,
+ libnetworking/emfdb.c, libnetworking/emfdb.h, libnetworking/md5.h,
+ libnetworking/md5c.c, libnetworking/ um.c, libnetworking/um.h: New files.
+ * libnetworking/wbase64.c: Removed.
+ * libnetworking/Makefile.am, libnetworking/asp.c,
+ libnetworking/balloc.c, libnetworking/default.c, libnetworking/ej.h,
+ libnetworking/ejlex.c, libnetworking/ejparse.c, libnetworking/ form.c,
+ libnetworking/h.c, libnetworking/handler.c, libnetworking/mime.c,
+ libnetworking/misc.c, libnetworking/ringq.c, libnetworking/rom.c,
+ libnetworking/security.c, libnetworking/ socket.c, libnetworking/sym.c,
+ libnetworking/uemf.c, libnetworking/uemf.h, libnetworking/url.c,
+ libnetworking/value.c, libnetworking/webcomp.c, libnetworking/webmain.c,
+ libnetworking/ webpage.c, libnetworking/webrom.c, libnetworking/webs.c,
+ libnetworking/webs.h, libnetworking/websuemf.c, libnetworking/wsIntrn.h:
+ Modified.
+
+2000-08-30 Joel Sherrill <joel@OARcorp.com>
+
+ * posix/Many files, score/Many files, libmisc/Many files: Moved
+ posix/include/rtems/posix/seterr.h to score/include/rtems/seterr.h so
+ it would be available within all APIs.
+ * libmisc/mw-fb/.cvsignore, libnetworking/rtems_webserver/license.txt:
+ New file.
+
+2000-08-30 Joel Sherrill <joel.sherrill@OARcorp.com>
+
+ * rtems/taskstart.c: Removed 1st cut at rtems_task_start_main_style.
+ Only committed this so it could be easily revisited as we discussing
+ moving main() to user space from BSP space.
+ * rtems/taskstart.c: Added 1st cut at rtems_task_start_main_style.
+
+2000-08-26 Rosimildo da Silva <rdasilva@connecttel.com>
+
+ * Added generic Micro FrameBuffer interface for MicroWindows. This
+ interface allows MicroWindows to under RTEMS. A sample driver has been
+ developed for the pc386 BSP. See pc386/fb_vga.c as a sample.
+ * Added Uniform Input Device interface for MicroWindows. See PC386 bsp
+ for sample drivers for mouse and keyboard (console).
+ * libmisc/mw-bf: New directory.
+ * libmisc/Makefile.am, libmisc/configure.in, libmisc/wrapup/Makefile.am:
+ Account for mw-fb.
+ * libmisc/mw-fb/Makefile.am, libmisc/mw-fb/mw_fb.c,
+ libmisc/mw-fb/mw_fb.h, libmisc/mw-fb/mw_uid.c, libmisc/mw-fb/mw_uid.h:
+ New file.
+
+2000-08-25 Joel Sherrill <joel.sherrill@OARcorp.com>
+
+ * posix/inline/rtems/posix/timer.inl, posix/include/rtems/posix/timer.h,
+ posix/ inline/rtems/posix/Makefile.am, posix/src/ptimer1.c: Redid the
+ style of src/ptimer1.c. Continued effort to make the POSIX Timer
+ implementation match that of other managers. Added data structures
+ required to use SuperCore Object Handler.
+
+2000-08-17 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * score/include/rtems/system.h: Include cpuopts.h for __i386__.
+
+2000-08-15 Joel Sherrill <joel@OARcorp.com>
+
+ * posix/src/ptimer1.c: Minor formatting fixes.
+ * posix/src/ptimer1.c: Removed unused routine PRINT_ERRNO_S.
+ * posix/src/ptimer1.c: Removed unnecessary routine COPY_ITIMERSPEC_S and
+ used structure copy instead.
+ * posix/src/ptimer1.c: Renamed timer_alive_t to POSIX_Timer_Control.
+ * posix/include/rtems/posix/timer.h: Ditto.
+ * posix/src/ptimer1.c: Switched to using
+ set_errno_and_return_minus_one() to ensure that errno was always set.
+ * posix/src/ptimer1.c (timer_settime): Converted use of rtems_clock_get
+ to use SuperCore _TOD_Current variable.
+
+2000-08-10 Joel Sherrill <joel@OARcorp.com>
+
+ * ChangeLog, itron/ChangeLog, posix/ChangeLog, score/ChangeLog,
+ sapi/ChangeLog, rtems/ChangeLog, libmisc/ChangeLog, librpc/ChangeLog,
+ libnetworking/ChangeLog: New file.
+
diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am
new file mode 100644
index 0000000000..6d72915a8d
--- /dev/null
+++ b/cpukit/Makefile.am
@@ -0,0 +1,186 @@
+##
+## $Id$
+##
+
+ACLOCAL_AMFLAGS = -I aclocal
+
+include $(top_srcdir)/automake/compile.am
+include $(top_srcdir)/automake/multilib.am
+
+SUBDIRS = . ada score rtems sapi posix itron
+SUBDIRS += libcsupport libblock libfs
+SUBDIRS += libnetworking librpc
+SUBDIRS += libmisc
+SUBDIRS += wrapup
+
+noinst_DATA = preinstall-stamp
+
+preinstall-stamp:
+ $(MAKE) $(AM_MAKEFLAGS) preinstall
+ touch preinstall-stamp
+CLEANFILES = preinstall-stamp
+
+include_HEADERS =
+
+if DEPRECATED
+include_HEADERS += backward/asm.h backward/chain.h backward/clockdrv.h \
+ backward/confdefs.h backward/console.h backward/imfs.h backward/iosupp.h \
+ backward/ringbuf.h backward/rtc.h backward/spurious.h \
+ backward/timerdrv.h backward/vmeintr.h
+
+include_motoroladir = $(includedir)/motorola
+include_motorola_HEADERS = backward/motorola/mc68681.h \
+ backward/motorola/mc68230.h
+
+include_zilogdir = $(includedir)/zilog
+include_zilog_HEADERS = backward/zilog/z8536.h backward/zilog/z8036.h \
+ backward/zilog/z8030.h
+
+if !UNIX
+include_HEADERS += backward/dosfs.h
+endif
+
+if HAS_ITRON
+include_HEADERS += backward/itron.h
+endif
+endif
+
+include_rtemsdir = $(includedir)/rtems
+include_rtems_HEADERS = include/rtems/bspIo.h include/rtems/userenv.h \
+ include/rtems/fs.h include/rtems/pci.h include/rtems/stdint.h \
+ include/rtems/concat.h
+
+PREINSTALL_DIRS =
+PREINSTALL_FILES =
+
+$(PROJECT_INCLUDE)/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)
+ @: > $(PROJECT_INCLUDE)/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/$(dirstamp)
+
+if DEPRECATED
+$(PROJECT_INCLUDE)/asm.h: backward/asm.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/asm.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/asm.h
+
+$(PROJECT_INCLUDE)/chain.h: backward/chain.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/chain.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/chain.h
+
+$(PROJECT_INCLUDE)/clockdrv.h: backward/clockdrv.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/clockdrv.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/clockdrv.h
+
+$(PROJECT_INCLUDE)/confdefs.h: backward/confdefs.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/confdefs.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/confdefs.h
+
+$(PROJECT_INCLUDE)/console.h: backward/console.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/console.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/console.h
+
+$(PROJECT_INCLUDE)/imfs.h: backward/imfs.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/imfs.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/imfs.h
+
+$(PROJECT_INCLUDE)/iosupp.h: backward/iosupp.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/iosupp.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/iosupp.h
+
+$(PROJECT_INCLUDE)/ringbuf.h: backward/ringbuf.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/ringbuf.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/ringbuf.h
+
+$(PROJECT_INCLUDE)/rtc.h: backward/rtc.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtc.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtc.h
+
+$(PROJECT_INCLUDE)/spurious.h: backward/spurious.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/spurious.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/spurious.h
+
+$(PROJECT_INCLUDE)/timerdrv.h: backward/timerdrv.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/timerdrv.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/timerdrv.h
+
+$(PROJECT_INCLUDE)/vmeintr.h: backward/vmeintr.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/vmeintr.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/vmeintr.h
+
+$(PROJECT_INCLUDE)/motorola/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/motorola
+ @: > $(PROJECT_INCLUDE)/motorola/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/motorola/$(dirstamp)
+
+$(PROJECT_INCLUDE)/motorola/mc68681.h: backward/motorola/mc68681.h $(PROJECT_INCLUDE)/motorola/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/motorola/mc68681.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/motorola/mc68681.h
+
+$(PROJECT_INCLUDE)/motorola/mc68230.h: backward/motorola/mc68230.h $(PROJECT_INCLUDE)/motorola/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/motorola/mc68230.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/motorola/mc68230.h
+
+$(PROJECT_INCLUDE)/zilog/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/zilog
+ @: > $(PROJECT_INCLUDE)/zilog/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/zilog/$(dirstamp)
+
+$(PROJECT_INCLUDE)/zilog/z8536.h: backward/zilog/z8536.h $(PROJECT_INCLUDE)/zilog/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/zilog/z8536.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/zilog/z8536.h
+
+$(PROJECT_INCLUDE)/zilog/z8036.h: backward/zilog/z8036.h $(PROJECT_INCLUDE)/zilog/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/zilog/z8036.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/zilog/z8036.h
+
+$(PROJECT_INCLUDE)/zilog/z8030.h: backward/zilog/z8030.h $(PROJECT_INCLUDE)/zilog/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/zilog/z8030.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/zilog/z8030.h
+
+if !UNIX
+$(PROJECT_INCLUDE)/dosfs.h: backward/dosfs.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/dosfs.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/dosfs.h
+endif
+
+if HAS_ITRON
+$(PROJECT_INCLUDE)/itron.h: backward/itron.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/itron.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/itron.h
+endif
+endif
+
+$(PROJECT_INCLUDE)/rtems/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems
+ @: > $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/bspIo.h: include/rtems/bspIo.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/bspIo.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/bspIo.h
+
+$(PROJECT_INCLUDE)/rtems/userenv.h: include/rtems/userenv.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/userenv.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/userenv.h
+
+$(PROJECT_INCLUDE)/rtems/fs.h: include/rtems/fs.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/fs.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/fs.h
+
+$(PROJECT_INCLUDE)/rtems/pci.h: include/rtems/pci.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/pci.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/pci.h
+
+$(PROJECT_INCLUDE)/rtems/stdint.h: include/rtems/stdint.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/stdint.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/stdint.h
+
+$(PROJECT_INCLUDE)/rtems/concat.h: include/rtems/concat.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/concat.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/concat.h
+
+CLEANFILES += $(PREINSTALL_FILES)
+DISTCLEANFILES = $(PREINSTALL_DIRS)
+
+include $(top_srcdir)/automake/subdirs.am
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/acinclude.m4 b/cpukit/acinclude.m4
new file mode 100644
index 0000000000..ef4268e84b
--- /dev/null
+++ b/cpukit/acinclude.m4
@@ -0,0 +1,21 @@
+# RTEMS_CPUOPT(NAME,CONDITION,VALUE,EXPLANATION)
+
+AC_DEFUN([RTEMS_CPUOPT],
+[
+ if $2; then
+cat >>cpuopts.tmp <<_ACEOF
+
+/* $4 */
+#define $1 $3
+_ACEOF
+## FIXME: Duplicate the define to the autoheader
+## Sanity check - Should be removed in future
+ AC_DEFINE_UNQUOTED([$1],[$3],[$4])
+ else
+cat >>cpuopts.tmp <<\_ACEOF
+
+/* $4 */
+/* #undef $1 */
+_ACEOF
+ fi
+])
diff --git a/cpukit/aclocal/canonical-target-name.m4 b/cpukit/aclocal/canonical-target-name.m4
new file mode 100644
index 0000000000..963a71cda3
--- /dev/null
+++ b/cpukit/aclocal/canonical-target-name.m4
@@ -0,0 +1,40 @@
+dnl
+dnl $Id$
+dnl
+
+dnl canonicalize target cpu
+dnl NOTE: Most rtems targets do not fullfil autoconf's
+dnl target naming conventions "processor-vendor-os"
+dnl Therefore autoconf's AC_CANONICAL_TARGET will fail for them
+dnl and we have to fix it for rtems ourselves
+
+AC_DEFUN([RTEMS_CANONICAL_TARGET_CPU],
+[AC_REQUIRE([AC_CANONICAL_HOST])
+AC_MSG_CHECKING(rtems target cpu)
+case "${host}" in
+ # hpux unix port should go here
+ i[[34567]]86-*linux*) # unix "simulator" port
+ RTEMS_CPU=unix
+ ;;
+ i[[34567]]86-*freebsd*) # unix "simulator" port
+ RTEMS_CPU=unix
+ ;;
+ i[[34567]]86-pc-cygwin*) # Cygwin is just enough unix like :)
+ RTEMS_CPU=unix
+ ;;
+ no_cpu-*rtems*)
+ RTEMS_CPU=no_cpu
+ ;;
+ sparc-sun-solaris*) # unix "simulator" port
+ RTEMS_CPU=unix
+ ;;
+ tic4x-*rtems*) # gcc changed the name
+ RTEMS_CPU=c4x
+ ;;
+ *)
+ RTEMS_CPU=`echo $host | sed 's%^\([[^-]]*\)-\(.*\)$%\1%'`
+ ;;
+esac
+AC_SUBST(RTEMS_CPU)
+AC_MSG_RESULT($RTEMS_CPU)
+])
diff --git a/cpukit/aclocal/canonicalize-tools.m4 b/cpukit/aclocal/canonicalize-tools.m4
new file mode 100644
index 0000000000..540c9a4c29
--- /dev/null
+++ b/cpukit/aclocal/canonicalize-tools.m4
@@ -0,0 +1,15 @@
+dnl
+dnl $Id$
+dnl
+dnl Set target tools
+dnl
+
+AC_DEFUN([RTEMS_CANONICALIZE_TOOLS],
+[AC_REQUIRE([RTEMS_PROG_CC])dnl
+
+dnl FIXME: What shall be done if these tools are not available?
+ RTEMS_CHECK_TOOL(AR,ar,no)
+
+dnl special treatment of ranlib
+ RTEMS_CHECK_TOOL(RANLIB,ranlib,:)
+])
diff --git a/cpukit/aclocal/check-itron.m4 b/cpukit/aclocal/check-itron.m4
new file mode 100644
index 0000000000..88f4013e5e
--- /dev/null
+++ b/cpukit/aclocal/check-itron.m4
@@ -0,0 +1,23 @@
+dnl $Id$
+dnl
+AC_DEFUN([RTEMS_CHECK_ITRON_API],
+[dnl
+AC_REQUIRE([RTEMS_CANONICAL_TARGET_CPU])dnl
+AC_REQUIRE([RTEMS_ENABLE_ITRON])dnl
+
+AC_CACHE_CHECK([whether CPU supports libitron],
+ rtems_cv_HAS_ITRON_API,
+ [dnl
+ case "$RTEMS_CPU" in
+ unix*)
+ rtems_cv_HAS_ITRON_API="no"
+ ;;
+ *)
+ if test "${RTEMS_HAS_ITRON_API}" = "yes"; then
+ rtems_cv_HAS_ITRON_API="yes";
+ else
+ rtems_cv_HAS_ITRON_API="disabled";
+ fi
+ ;;
+ esac])
+])
diff --git a/cpukit/aclocal/check-multiprocessing.m4 b/cpukit/aclocal/check-multiprocessing.m4
new file mode 100644
index 0000000000..ca4338b09a
--- /dev/null
+++ b/cpukit/aclocal/check-multiprocessing.m4
@@ -0,0 +1,9 @@
+dnl
+dnl $Id$
+dnl
+
+AC_DEFUN([RTEMS_CHECK_MULTIPROCESSING],
+[dnl
+AC_REQUIRE([RTEMS_ENV_RTEMSCPU])dnl
+AC_REQUIRE([RTEMS_ENABLE_MULTIPROCESSING])dnl
+])
diff --git a/cpukit/aclocal/check-networking.m4 b/cpukit/aclocal/check-networking.m4
new file mode 100644
index 0000000000..289c1b3eb2
--- /dev/null
+++ b/cpukit/aclocal/check-networking.m4
@@ -0,0 +1,28 @@
+dnl $Id$
+dnl
+AC_DEFUN([RTEMS_CHECK_NETWORKING],
+[dnl
+AC_REQUIRE([RTEMS_CANONICAL_TARGET_CPU])dnl
+AC_REQUIRE([RTEMS_ENABLE_NETWORKING])dnl
+
+AC_CACHE_CHECK([whether CPU supports networking],
+ rtems_cv_HAS_NETWORKING,
+ [dnl
+ case "$RTEMS_CPU" in
+ unix*)
+ rtems_cv_HAS_NETWORKING="no"
+ ;;
+ *)
+ if test "${RTEMS_HAS_NETWORKING}" = "yes"; then
+ rtems_cv_HAS_NETWORKING="yes";
+ else
+ rtems_cv_HAS_NETWORKING="disabled";
+ fi
+ ;;
+ esac])
+if test "$rtems_cv_HAS_NETWORKING" = "yes"; then
+ HAS_NETWORKING="yes";
+else
+ HAS_NETWORKING="no";
+fi
+])
diff --git a/cpukit/aclocal/check-newlib.m4 b/cpukit/aclocal/check-newlib.m4
new file mode 100644
index 0000000000..bbf5f68dc2
--- /dev/null
+++ b/cpukit/aclocal/check-newlib.m4
@@ -0,0 +1,30 @@
+dnl $Id$
+
+AC_DEFUN([RTEMS_CHECK_NEWLIB],
+[dnl
+AC_REQUIRE([RTEMS_PROG_CC_FOR_TARGET])dnl
+AC_REQUIRE([RTEMS_CANONICALIZE_TOOLS])dnl
+AC_CACHE_CHECK([for RTEMS newlib],
+ rtems_cv_use_newlib,
+ [
+dnl some versions of newlib provide not_required_by_rtems
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM([[extern void not_required_by_rtems() ;]],
+ [[not_required_by_rtems()]])],
+ [rtems_cv_use_newlib="yes"],[])
+
+dnl some versions of newlib provide rtems_provides_crt0()
+ AS_IF([test -z "$rtems_cv_use_newlib"],
+ [AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM([[extern void rtems_provides_crt0() ;]],
+ [[rtems_provides_crt0()]])],
+ [rtems_cv_use_newlib="yes"],[rtems_cv_use_newlib="no"])
+ ])
+ ])
+ RTEMS_USE_NEWLIB="$rtems_cv_use_newlib"
+ AC_SUBST(RTEMS_USE_NEWLIB)
+
+ AS_IF([test x"${RTEMS_USE_NEWLIB}" = x"yes"],
+ [ AC_DEFINE_UNQUOTED(RTEMS_NEWLIB,1,[if using newlib])]
+ )
+])
diff --git a/cpukit/aclocal/check-posix.m4 b/cpukit/aclocal/check-posix.m4
new file mode 100644
index 0000000000..be60c5f74a
--- /dev/null
+++ b/cpukit/aclocal/check-posix.m4
@@ -0,0 +1,23 @@
+dnl $Id$
+dnl
+AC_DEFUN([RTEMS_CHECK_POSIX_API],
+[dnl
+AC_REQUIRE([RTEMS_CANONICAL_TARGET_CPU])dnl
+AC_REQUIRE([RTEMS_ENABLE_POSIX])dnl
+
+AC_CACHE_CHECK([whether CPU supports libposix],
+ rtems_cv_HAS_POSIX_API,
+ [dnl
+ case "$RTEMS_CPU" in
+ unix*)
+ rtems_cv_HAS_POSIX_API="no"
+ ;;
+ *)
+ if test "${RTEMS_HAS_POSIX_API}" = "yes"; then
+ rtems_cv_HAS_POSIX_API="yes";
+ else
+ rtems_cv_HAS_POSIX_API="disabled";
+ fi
+ ;;
+ esac])
+])
diff --git a/cpukit/aclocal/check-rtems-debug.m4 b/cpukit/aclocal/check-rtems-debug.m4
new file mode 100644
index 0000000000..d8d1818520
--- /dev/null
+++ b/cpukit/aclocal/check-rtems-debug.m4
@@ -0,0 +1,7 @@
+## $Id$
+
+AC_DEFUN([RTEMS_CHECK_RTEMS_DEBUG],
+[AC_REQUIRE([RTEMS_ENABLE_RTEMS_DEBUG])
+AS_IF([test x"${enable_rtems_debug}" = x"yes"]
+ [AC_DEFINE_UNQUOTED(RTEMS_DEBUG,1,[if RTEMS_DEBUG is enabled])])
+])
diff --git a/cpukit/aclocal/check-tool.m4 b/cpukit/aclocal/check-tool.m4
new file mode 100644
index 0000000000..4c412c074a
--- /dev/null
+++ b/cpukit/aclocal/check-tool.m4
@@ -0,0 +1,11 @@
+dnl $Id$
+
+## Check for a cross tool, similar to AC_CHECK_TOOL, but do not fall back to
+## the un-prefixed version of PROG-TO-CHECK-FOR.
+dnl RTEMS_CHECK_TOOL(VARIABLE, PROG-TO-CHECK-FOR[, VALUE-IF-NOT-FOUND [, PATH]])
+AC_DEFUN([RTEMS_CHECK_TOOL],
+[
+ AS_IF([test "x$build_alias" != "x$host_alias"],
+ [rtems_tool_prefix=${ac_tool_prefix}])
+ AC_CHECK_PROG($1, ${rtems_tool_prefix}$2, ${rtems_tool_prefix}$2, $3, $4)
+])
diff --git a/cpukit/aclocal/enable-inlines.m4 b/cpukit/aclocal/enable-inlines.m4
new file mode 100644
index 0000000000..2c79538dce
--- /dev/null
+++ b/cpukit/aclocal/enable-inlines.m4
@@ -0,0 +1,11 @@
+dnl $Id$
+
+AC_DEFUN([RTEMS_ENABLE_INLINES],
+[AC_ARG_ENABLE(rtems-inlines,
+AS_HELP_STRING(--enable-rtems-inlines,enable RTEMS inline functions (default:enabled, disable to use macros)),
+[case "${enableval}" in
+ yes) enable_rtems_inlines=yes ;;
+ no) enable_rtems_inlines=no ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for enable-rtems-inlines option) ;;
+esac],[enable_rtems_inlines=yes])
+])
diff --git a/cpukit/aclocal/enable-itron.m4 b/cpukit/aclocal/enable-itron.m4
new file mode 100644
index 0000000000..552e8df267
--- /dev/null
+++ b/cpukit/aclocal/enable-itron.m4
@@ -0,0 +1,33 @@
+dnl $Id$
+
+AC_DEFUN([RTEMS_ENABLE_ITRON],
+[
+## AC_BEFORE([$0], [RTEMS_CHECK_ITRON_API])dnl
+
+AC_ARG_ENABLE(itron,
+AS_HELP_STRING(--enable-itron,enable itron interface),
+[case "${enableval}" in
+ yes) RTEMS_HAS_ITRON_API=yes ;;
+ no) RTEMS_HAS_ITRON_API=no ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for enable-itron option) ;;
+esac],[RTEMS_HAS_ITRON_API=yes])
+
+case "${host}" in
+ # hpux unix port should go here
+ i[[34567]]86-pc-linux*) # unix "simulator" port
+ RTEMS_HAS_ITRON_API=no
+ ;;
+ i[[34567]]86-*freebsd*) # unix "simulator" port
+ RTEMS_HAS_ITRON_API=no
+ ;;
+ no_cpu-*rtems*)
+ RTEMS_HAS_ITRON_API=no
+ ;;
+ sparc-sun-solaris*) # unix "simulator" port
+ RTEMS_HAS_ITRON_API=no
+ ;;
+ *)
+ ;;
+esac
+AC_SUBST(RTEMS_HAS_ITRON_API)
+])
diff --git a/cpukit/aclocal/enable-multiprocessing.m4 b/cpukit/aclocal/enable-multiprocessing.m4
new file mode 100644
index 0000000000..f664800e40
--- /dev/null
+++ b/cpukit/aclocal/enable-multiprocessing.m4
@@ -0,0 +1,12 @@
+dnl $Id$
+
+AC_DEFUN([RTEMS_ENABLE_MULTIPROCESSING],
+[
+AC_ARG_ENABLE(multiprocessing,
+AS_HELP_STRING(--enable-multiprocessing,enable multiprocessing interface),
+[case "${enable_multiprocessing}" in
+ yes) ;;
+ no) ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for enable-multiprocessing option) ;;
+esac],[enable_multiprocessing=no])
+])
diff --git a/cpukit/aclocal/enable-networking.m4 b/cpukit/aclocal/enable-networking.m4
new file mode 100644
index 0000000000..a7be7b4df7
--- /dev/null
+++ b/cpukit/aclocal/enable-networking.m4
@@ -0,0 +1,14 @@
+dnl $Id$
+
+AC_DEFUN([RTEMS_ENABLE_NETWORKING],
+[
+## AC_BEFORE([$0], [RTEMS_CHECK_NETWORKING])dnl
+
+AC_ARG_ENABLE(networking,
+AS_HELP_STRING(--enable-networking,enable TCP/IP stack),
+[case "${enableval}" in
+ yes) RTEMS_HAS_NETWORKING=yes ;;
+ no) RTEMS_HAS_NETWORKING=no ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for enable-networking option) ;;
+esac],[RTEMS_HAS_NETWORKING=yes])
+])
diff --git a/cpukit/aclocal/enable-posix.m4 b/cpukit/aclocal/enable-posix.m4
new file mode 100644
index 0000000000..fe0f314e76
--- /dev/null
+++ b/cpukit/aclocal/enable-posix.m4
@@ -0,0 +1,33 @@
+dnl $Id$
+
+AC_DEFUN([RTEMS_ENABLE_POSIX],
+[
+## AC_BEFORE([$0], [RTEMS_CHECK_POSIX_API])dnl
+
+AC_ARG_ENABLE(posix,
+AS_HELP_STRING(--enable-posix,enable posix interface),
+[case "${enableval}" in
+ yes) RTEMS_HAS_POSIX_API=yes ;;
+ no) RTEMS_HAS_POSIX_API=no ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for enable-posix option) ;;
+esac],[RTEMS_HAS_POSIX_API=yes])
+
+case "${host}" in
+ # hpux unix port should go here
+ i[[34567]]86-pc-linux*) # unix "simulator" port
+ RTEMS_HAS_POSIX_API=no
+ ;;
+ i[[34567]]86-*freebsd*) # unix "simulator" port
+ RTEMS_HAS_POSIX_API=no
+ ;;
+ no_cpu-*rtems*)
+ RTEMS_HAS_POSIX_API=no
+ ;;
+ sparc-sun-solaris*) # unix "simulator" port
+ RTEMS_HAS_POSIX_API=no
+ ;;
+ *)
+ ;;
+esac
+AC_SUBST(RTEMS_HAS_POSIX_API)
+])
diff --git a/cpukit/aclocal/enable-rtems-debug.m4 b/cpukit/aclocal/enable-rtems-debug.m4
new file mode 100644
index 0000000000..ada9fe30f4
--- /dev/null
+++ b/cpukit/aclocal/enable-rtems-debug.m4
@@ -0,0 +1,12 @@
+## $Id$
+
+AC_DEFUN([RTEMS_ENABLE_RTEMS_DEBUG],
+[
+AC_ARG_ENABLE(rtems-debug,
+AS_HELP_STRING(--enable-rtems-debug,enable RTEMS_DEBUG),
+[case "${enable_rtems_debug}" in
+ yes) enable_rtems_debug=yes ;;
+ no) enable_rtems_debug=no ;;
+ *) AC_MSG_ERROR([bad value ${enable_rtems_debug} for RTEMS_DEBUG]) ;;
+esac],[enable_rtems_debug=no])
+])
diff --git a/cpukit/aclocal/env-rtemscpu.m4 b/cpukit/aclocal/env-rtemscpu.m4
new file mode 100644
index 0000000000..eee3c5dd5f
--- /dev/null
+++ b/cpukit/aclocal/env-rtemscpu.m4
@@ -0,0 +1,14 @@
+dnl $Id$
+
+AC_DEFUN([RTEMS_ENV_RTEMSCPU],
+[
+ AC_REQUIRE([RTEMS_ENABLE_MULTILIB])
+
+ AC_ARG_VAR([CPU_CFLAGS],[])
+ AC_ARG_VAR([CFLAGS_OPTIMIZE_V],
+ [CFLAGS for building the optimized variant])
+ AC_ARG_VAR([CFLAGS_DEBUG_V],
+ [CFLAGS for building the debugging variant])
+
+ AM_CONDITIONAL([MULTILIB],[test x"$multilib" = x"yes"])
+])
diff --git a/cpukit/aclocal/gcc-isystem.m4 b/cpukit/aclocal/gcc-isystem.m4
new file mode 100644
index 0000000000..94098cf33c
--- /dev/null
+++ b/cpukit/aclocal/gcc-isystem.m4
@@ -0,0 +1,25 @@
+dnl
+dnl $Id$
+dnl
+dnl Check whether the gcc accepts -isystem
+dnl
+
+AC_DEFUN([RTEMS_GCC_ISYSTEM],
+[AC_REQUIRE([RTEMS_PROG_CC])
+AC_CACHE_CHECK(whether $CC accepts -isystem,rtems_cv_gcc_isystem,
+[
+rtems_cv_gcc_isystem=no
+if test x"$GCC" = x"yes"; then
+cat << EOF > conftest.h
+int conftest123();
+EOF
+cat << EOF > conftest.c
+#include <conftest.h>
+int conftest123() {}
+EOF
+ if test -z "`${CC} -isystem./ -c conftest.c 2>&1`";then
+ rtems_cv_gcc_isystem=yes
+ fi
+fi
+rm -f conftest*
+])])
diff --git a/cpukit/aclocal/gcc-pipe.m4 b/cpukit/aclocal/gcc-pipe.m4
new file mode 100644
index 0000000000..2a04629bb2
--- /dev/null
+++ b/cpukit/aclocal/gcc-pipe.m4
@@ -0,0 +1,21 @@
+dnl
+dnl $Id$
+dnl
+dnl Check whether the target compiler accepts -pipe
+dnl
+
+AC_DEFUN([RTEMS_GCC_PIPE],
+[AC_REQUIRE([RTEMS_PROG_CC])
+AC_REQUIRE([AC_CANONICAL_HOST])
+AC_CACHE_CHECK(whether $CC accepts --pipe,rtems_cv_gcc_pipe,
+[
+rtems_cv_gcc_pipe=no
+if test x"$GCC" = x"yes"; then
+ echo 'void f(){}' >conftest.c
+ if test -z "`${CC} --pipe -c conftest.c 2>&1`";then
+ rtems_cv_gcc_pipe=yes
+ fi
+ rm -f conftest*
+fi
+])
+])
diff --git a/cpukit/aclocal/multi.m4 b/cpukit/aclocal/multi.m4
new file mode 100644
index 0000000000..d629840d25
--- /dev/null
+++ b/cpukit/aclocal/multi.m4
@@ -0,0 +1,52 @@
+#serial 99
+
+AC_DEFUN([AC_ENABLE_MULTILIB],
+[
+AC_ARG_ENABLE(multilib,
+AS_HELP_STRING(--enable-multilib,build many library versions (default=no)),
+[case "${enableval}" in
+ yes) multilib=yes ;;
+ no) multilib=no ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for multilib option) ;;
+ esac], [multilib=no])dnl
+
+AM_CONDITIONAL(MULTILIB,test x"${multilib}" = x"yes")
+
+dnl We may get other options which we don't document:
+dnl --with-target-subdir, --with-multisrctop, --with-multisubdir
+
+if test "[$]{srcdir}" = "."; then
+ if test "[$]{with_target_subdir}" != "."; then
+ multilib_basedir="[$]{srcdir}/[$]{with_multisrctop}../ifelse([$2],,,[$2])"
+ else
+ multilib_basedir="[$]{srcdir}/[$]{with_multisrctop}ifelse([$2],,,[$2])"
+ fi
+else
+ multilib_basedir="[$]{srcdir}/ifelse([$2],,,[$2])"
+fi
+AC_SUBST(multilib_basedir)
+
+if test "${multilib}" = "yes"; then
+ multilib_arg="--enable-multilib"
+else
+ multilib_arg=
+fi
+
+AC_OUTPUT_COMMANDS(
+[case " $CONFIG_FILES " in
+ *" ]m4_if([$1],,Makefile,[$1])[ "*)
+ ac_file=]m4_if([$1],,Makefile,[$1])[ . ${multilib_basedir}/config-ml.in
+esac],
+[
+ srcdir=${srcdir}
+ host=${host}
+ target=${target}
+ with_multisrctop="${with_multisrctop}"
+ with_target_subdir="${with_target_subdir}"
+ with_multisubdir="${with_multisubdir}"
+ ac_configure_args="${multilib_arg} ${ac_configure_args}"
+ CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+ multilib_basedir=${multilib_basedir}
+ CC="${CC}"]
+)
+])
diff --git a/cpukit/aclocal/multilib.m4 b/cpukit/aclocal/multilib.m4
new file mode 100644
index 0000000000..90e6217780
--- /dev/null
+++ b/cpukit/aclocal/multilib.m4
@@ -0,0 +1,14 @@
+dnl This provides configure definitions used for multilib support
+
+AC_DEFUN([RTEMS_ENABLE_MULTILIB],
+[
+AC_ARG_ENABLE(multilib,
+AS_HELP_STRING(--enable-multilib,build many library versions (default=no)),
+[case "${enableval}" in
+ yes) multilib=yes ;;
+ no) multilib=no ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for multilib option) ;;
+ esac], [multilib=no])dnl
+
+AM_CONDITIONAL([MULTILIB],[test x"${multilib}" = x"yes"])
+])
diff --git a/cpukit/aclocal/prog-cc.m4 b/cpukit/aclocal/prog-cc.m4
new file mode 100644
index 0000000000..344081f98c
--- /dev/null
+++ b/cpukit/aclocal/prog-cc.m4
@@ -0,0 +1,46 @@
+dnl
+dnl $Id$
+dnl
+dnl Check for target gcc
+dnl
+
+AC_DEFUN([RTEMS_PROG_CC],
+[
+AC_BEFORE([$0], [AC_PROG_CPP])dnl
+AC_BEFORE([$0], [AC_PROG_CC])dnl
+AC_BEFORE([$0], [RTEMS_CANONICALIZE_TOOLS])dnl
+
+_RTEMS_FLAGS([CFLAGS],
+ ["\$(CPU_CFLAGS) \$(RTEMS_CFLAGS_\$(VARIANT_V)_V) \$(CFLAGS_\$(VARIANT_V)_V) -g"])
+
+RTEMS_CHECK_TOOL(CC,gcc)
+test -z "$CC" && \
+ AC_MSG_ERROR([no acceptable cc found in \$PATH])
+AC_PROG_CC
+AC_PROG_CPP
+
+AM_CONDITIONAL(RTEMS_USE_GCC,test x"$GCC" = x"yes")
+])
+
+AC_DEFUN([RTEMS_PROG_CC_FOR_TARGET],
+[
+dnl check target cc
+RTEMS_PROG_CC
+dnl check if the compiler supports -isystem
+RTEMS_GCC_ISYSTEM
+dnl check if the target compiler may use --pipe
+RTEMS_GCC_PIPE
+test "$rtems_cv_gcc_pipe" = "yes" && CC="$CC --pipe"
+
+if test "$GCC" = yes; then
+RTEMS_CFLAGS="$RTEMS_CFLAGS -Wall"
+m4_if([$1],,[],[RTEMS_CFLAGS="$RTEMS_CFLAGS $1"])
+fi
+
+AS_IF([test x"$rtems_cv_gcc_isystem" = x"yes"],[
+ RTEMS_CPPFLAGS="-isystem \$(PROJECT_INCLUDE)"],[
+ RTEMS_CPPFLAGS="-I\$(PROJECT_INCLUDE)"
+])
+AC_SUBST(RTEMS_CPPFLAGS)
+
+])
diff --git a/cpukit/aclocal/prog-ccas.m4 b/cpukit/aclocal/prog-ccas.m4
new file mode 100644
index 0000000000..aeef25ec0c
--- /dev/null
+++ b/cpukit/aclocal/prog-ccas.m4
@@ -0,0 +1,8 @@
+## $Id$
+
+AC_DEFUN([RTEMS_PROG_CCAS],
+[
+AC_REQUIRE([RTEMS_PROG_CC])
+AC_SUBST(CCAS,["$CC \$(GCCSPECS)"])
+AC_SUBST(CCASFLAGS,["-DASM \$(CFLAGS) \$(INCLUDES)"])
+])
diff --git a/cpukit/aclocal/prog-gnat.m4 b/cpukit/aclocal/prog-gnat.m4
new file mode 100644
index 0000000000..6e169a8dc7
--- /dev/null
+++ b/cpukit/aclocal/prog-gnat.m4
@@ -0,0 +1,45 @@
+## $Id$
+##
+## Partially borrowed from gcc-3.2
+##
+## WARNING: All the stuff below is pretty immature.
+
+AC_DEFUN([RTEMS_PROG_GNAT],
+[AC_REQUIRE([AC_CHECK_TOOL_PREFIX])
+AC_REQUIRE([RTEMS_PROG_CC_FOR_TARGET])
+
+AC_CHECK_TOOL([GNATMAKE],[gnatmake],[])
+AC_CACHE_CHECK([for compiler driver that understands Ada],
+ [rtems_cv_prog_CCADA],
+[cat >conftest.adb <<EOF
+procedure conftest is begin null; end conftest;
+EOF
+rtems_cv_prog_CCADA=
+# Have to do ac_tool_prefix and user overrides by hand.
+user_ccada=$CCADA
+user_cc=$CC
+for cand in ${ac_tool_prefix}$user_ccada $user_ccada \
+ ${ac_tool_prefix}$user_cc $user_cc \
+ ${ac_tool_prefix}gcc gcc \
+ ${ac_tool_prefix}cc cc \
+ ${ac_tool_prefix}gnatgcc gnatgcc \
+ ${ac_tool_prefix}gnatcc gnatcc \
+ ${ac_tool_prefix}adagcc adagcc \
+ ${ac_tool_prefix}adac adac ; do
+ # There is a bug in all released versions of GCC which causes the
+ # driver to exit successfully when the appropriate language module
+ # has not been installed. This is fixed in 2.95.4, 3.0.2, and 3.1.
+ # Therefore we must check for the error message as well as an
+ # unsuccessful exit.
+ errors=`($cand -c conftest.adb) 2>&1 || echo failure`
+ AS_IF([test -z "$errors"],
+ [rtems_cv_prog_CCADA=$cand
+ break])
+done
+rm -f conftest.*])
+AC_SUBST([CCADA],[$rtems_cv_prog_CCADA])
+
+AS_IF([test -n "$GNATMAKE" && test -n "$CCADA"],
+ [HAVE_GNAT=yes],
+ [HAVE_GNAT=no])
+])
diff --git a/cpukit/aclocal/rtems-flags.m4 b/cpukit/aclocal/rtems-flags.m4
new file mode 100644
index 0000000000..8e034e52c2
--- /dev/null
+++ b/cpukit/aclocal/rtems-flags.m4
@@ -0,0 +1,11 @@
+## $Id$
+##
+## Some hacks to set up RTEMS_*FLAGS
+## Internal macro, not supposed to be explictly used in configure.ac's
+
+AC_DEFUN([_RTEMS_FLAGS],[
+AS_IF([test -n "[$]{$1}"],
+ [RTEMS_$1=[$]{$1}],
+ [RTEMS_$1=$2])
+AC_SUBST([RTEMS_$1])
+])
diff --git a/cpukit/aclocal/rtems-top.m4 b/cpukit/aclocal/rtems-top.m4
new file mode 100644
index 0000000000..c3f74304e5
--- /dev/null
+++ b/cpukit/aclocal/rtems-top.m4
@@ -0,0 +1,70 @@
+dnl $Id$
+
+m4_define([RTEMS_API],[4.7])
+
+dnl
+dnl RTEMS_TOP($1)
+dnl
+dnl $1 .. relative path from this configure.ac to the toplevel configure.ac
+dnl
+AC_DEFUN([RTEMS_TOP],
+[dnl
+AC_REQUIRE([RTEMS_VERSIONING])
+AC_REQUIRE([AM_SET_LEADING_DOT])
+AC_CONFIG_AUX_DIR([$1])
+AC_CHECK_PROGS(MAKE, gmake make)
+AC_BEFORE([$0], [AM_INIT_AUTOMAKE])dnl
+
+AC_PREFIX_DEFAULT([/opt/rtems-][RTEMS_API])
+
+AC_SUBST([RTEMS_TOPdir],["$1"])
+
+# HACK: The sed pattern below strips of "../", corresponding to "cpukit/"
+rtems_updir="/"m4_if([$2],[],[`echo "$1/" | sed s,^\.\.\/,,`],[$2/])
+
+AS_IF([test -n "$with_multisubdir"],
+ [MULTIBUILDTOP=`echo "/$with_multisubdir" | sed 's,/[[^\\/]]*,../,g'`])
+AC_SUBST(MULTIBUILDTOP)
+
+AS_IF([test -n "$with_multisubdir"],
+ [MULTISUBDIR="/$with_multisubdir"])
+AC_SUBST(MULTISUBDIR)
+
+AC_ARG_WITH([project-root],[
+AS_HELP_STRING(--with-project-root,directory to pre-install files into)],[
+## Make sure to have a terminating '/'
+case "${with_project_root}" in
+*/) ;;
+*) with_project_root="${with_project_root}/" ;;
+esac
+
+case "${with_project_root}" in
+ [[\\/$]]* | ?:[[\\/]]* ) # absolute directory
+ PROJECT_ROOT=${with_project_root}
+ ;;
+ *) # relative directory
+ sav0dir=`pwd` && cd ./${rtems_updir}
+ sav1dir=`pwd` && cd ../${MULTIBUILDTOP}
+ sav2dir=`pwd` && cd $sav0dir
+ mydir=`echo $sav1dir | sed s,^$sav2dir${MULTISUBDIR}/,,`
+ PROJECT_ROOT='$(top_builddir)'${rtems_updir}'../$(MULTIBUILDTOP)'${mydir}/${with_project_root}
+ ;;
+esac],[
+## Defaults: Note: Two different defaults!
+## ../ for multilib
+## '.' for non-multilib
+AS_IF([test "$enable_multilib" = "yes"],[
+ PROJECT_ROOT='$(top_builddir)'${rtems_updir}'../$(MULTIBUILDTOP)'],[
+ PROJECT_ROOT='$(top_builddir)'${rtems_updir}])
+])
+
+AC_SUBST([PROJECT_INCLUDE],["${PROJECT_ROOT}lib/include"])
+AC_SUBST([PROJECT_LIB],["${PROJECT_ROOT}lib\$(MULTISUBDIR)"])
+
+libdir="${libdir}\$(MULTISUBDIR)"
+
+AC_SUBST([project_libdir],["\$(libdir)"])
+AC_SUBST([project_includedir],["\$(includedir)"])
+
+AC_SUBST([dirstamp],[\${am__leading_dot}dirstamp])
+])dnl
diff --git a/cpukit/aclocal/sysv-ipc.m4 b/cpukit/aclocal/sysv-ipc.m4
new file mode 100644
index 0000000000..0b263b5f4c
--- /dev/null
+++ b/cpukit/aclocal/sysv-ipc.m4
@@ -0,0 +1,125 @@
+dnl
+dnl $Id$
+dnl
+dnl Check for System V IPC calls used by Unix simulators
+dnl
+dnl 98/07/17 Dario Alcocer alcocer@netcom.com
+dnl Ralf Corsepius corsepiu@faw.uni-ulm.de
+dnl
+dnl Note: $host_os should probably *not* ever be used here to
+dnl determine if host supports System V IPC calls, since some
+dnl (e.g. FreeBSD 2.x) are configured by default to include only
+dnl a subset of the System V IPC calls. Therefore, to make sure
+dnl all of the required calls are found, test for each call explicitly.
+dnl
+dnl All of the calls use IPC_PRIVATE, so tests will not unintentionally
+dnl modify any existing key sets. See the man pages for semget, shmget,
+dnl msgget, semctl, shmctl and msgctl for details.
+
+AC_DEFUN([RTEMS_UNION_SEMUN],
+[
+AC_CACHE_CHECK([whether $host defines union semun],
+ rtems_cv_HAS_UNION_SEMUN,
+ [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>]], [[union semun arg ;]])],[rtems_cv_HAS_UNION_SEMUN="yes"],[rtems_cv_HAS_UNION_SEMUN="no"])
+])
+if test "$rtems_cv_HAS_UNION_SEMUN" = "yes"; then
+ AC_DEFINE(HAS_UNION_SEMUN,[1],[if having union semum])
+fi
+])
+
+AC_DEFUN([RTEMS_SYSV_SEM],
+[AC_REQUIRE([AC_PROG_CC])
+AC_CACHE_CHECK(whether $host supports System V semaphores,
+rtems_cv_sysv_sem,
+[
+AC_RUN_IFELSE([AC_LANG_SOURCE([[
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#if !HAS_UNION_SEMUN
+ union semun {
+ int val;
+ struct semid_ds *buf;
+ ushort *array;
+ } ;
+#endif
+int main () {
+ union semun arg ;
+
+ int id=semget(IPC_PRIVATE,1,IPC_CREAT|0400);
+ if (id == -1)
+ exit(1);
+ arg.val = 0; /* avoid implicit type cast to union */
+ if (semctl(id, 0, IPC_RMID, arg) == -1)
+ exit(1);
+ exit(0);
+}
+]])],[rtems_cv_sysv_sem="yes"],[rtems_cv_sysv_sem="no"],[:])
+])
+])
+
+AC_DEFUN([RTEMS_SYSV_SHM],
+[AC_REQUIRE([AC_PROG_CC])
+# AC_REQUIRE([RTEMS_CANONICAL_HOST])
+AC_CACHE_CHECK(whether $host supports System V shared memory,
+rtems_cv_sysv_shm,
+[
+AC_RUN_IFELSE([AC_LANG_SOURCE([[
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+int main () {
+ int id=shmget(IPC_PRIVATE,1,IPC_CREAT|0400);
+ if (id == -1)
+ exit(1);
+ if (shmctl(id, IPC_RMID, 0) == -1)
+ exit(1);
+ exit(0);
+}
+]])],[rtems_cv_sysv_shm="yes"],[rtems_cv_sysv_shm="no"],[:])
+])
+])
+
+AC_DEFUN([RTEMS_SYSV_MSG],
+[AC_REQUIRE([AC_PROG_CC])
+# AC_REQUIRE([RTEMS_CANONICAL_HOST])
+AC_CACHE_CHECK(whether $host supports System V messages,
+rtems_cv_sysv_msg,
+[
+AC_RUN_IFELSE([AC_LANG_SOURCE([[
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+int main () {
+ int id=msgget(IPC_PRIVATE,IPC_CREAT|0400);
+ if (id == -1)
+ exit(1);
+ if (msgctl(id, IPC_RMID, 0) == -1)
+ exit(1);
+ exit(0);
+}
+]])],[rtems_cv_sysv_msg="yes"],[rtems_cv_sysv_msg="no"],[:])
+])
+])
+
+AC_DEFUN([RTEMS_CHECK_SYSV_UNIX],
+[# AC_REQUIRE([RTEMS_CANONICAL_HOST])
+if test "$RTEMS_CPU" = "unix" ; then
+ RTEMS_UNION_SEMUN
+ RTEMS_SYSV_SEM
+ if test "$rtems_cv_sysv_sem" != "yes" ; then
+ AC_MSG_ERROR([System V semaphores don't work, required by simulator])
+ fi
+ RTEMS_SYSV_SHM
+ if test "$rtems_cv_sysv_shm" != "yes" ; then
+ AC_MSG_ERROR([System V shared memory doesn't work, required by simulator])
+ fi
+ RTEMS_SYSV_MSG
+ if test "$rtems_cv_sysv_msg" != "yes" ; then
+ AC_MSG_ERROR([System V messages don't work, required by simulator])
+ fi
+fi
+])
diff --git a/cpukit/aclocal/version.m4 b/cpukit/aclocal/version.m4
new file mode 100644
index 0000000000..adf855f413
--- /dev/null
+++ b/cpukit/aclocal/version.m4
@@ -0,0 +1,2 @@
+AC_DEFUN([RTEMS_VERSIONING],
+m4_define([_RTEMS_VERSION],[4.6.99.0]))
diff --git a/cpukit/ada/.cvsignore b/cpukit/ada/.cvsignore
new file mode 100644
index 0000000000..282522db03
--- /dev/null
+++ b/cpukit/ada/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/cpukit/ada/ChangeLog b/cpukit/ada/ChangeLog
new file mode 100644
index 0000000000..9aea452831
--- /dev/null
+++ b/cpukit/ada/ChangeLog
@@ -0,0 +1,109 @@
+2004-01-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add PREINSTALL_DIRS.
+
+2003-12-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Move include_adadir into RTEMS_ADA condional block.
+ Add CLEANFILES. Add PREINSTALL_FILES to CLEANFILES.
+
+2003-12-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use mkdir_p. Remove dirs from PRE/TMPINSTALL_FILES.
+
+2003-12-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use include_ada_HEADERS.
+
+2003-11-30 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Preinstall adainclude_HEADERS.
+ Add $(dirstamp) to preinstallation rules.
+
+2003-11-25 Joel Sherrill <joel@OARcorp.com>
+
+ PR 528/rtems_misc
+ * rtems.ads: Add task variables to Ada binding.
+
+2003-09-04 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems-multiprocessing.adb, rtems-multiprocessing.ads, rtems.adb,
+ rtems.ads: URL for license changed.
+
+2003-07-08 Joel Sherrill <joel@OARcorp.com>
+
+ PR 418/ada
+ * rtems.adb: Add missing all keyword to derefence pointer.
+
+2003-07-08 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove (Merged into ../configure.ac).
+ * Makefile.am: Reflect having merged configure.ac into
+ ../configure.ac.
+
+2003-03-06 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove AC_CONFIG_AUX_DIR.
+
+2003-02-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: AM_INIT_AUTOMAKE([1.7.2]).
+
+2003-02-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: AC_PREREQ(2.57).
+
+2003-02-03 Joel Sherrill <joel@OARcorp.com>
+
+ PR 338/filesystem
+ * rtems.adb, rtems.ads: Side-effect of fixing reentrancy problem with
+ rtems_io_lookup_name() (API change).
+
+2003-01-03 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems.ads: Corrected Configuration_Table record definition to
+ match current RTEMS source. sp01 now runs.
+
+2002-11-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Fix package name.
+
+2002-10-29 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove AC_ENABLE_MULTILIB.
+ * Makefile.am: Add CVS-Id.
+
+2002-10-25 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Add nostdinc to AM_INIT_AUTOMAKE.
+
+2002-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * .cvsignore: Reformat.
+ Add autom4te*cache.
+ Remove autom4te.cache.
+
+2002-08-30 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems.adb (IO_Initialize): Make this match the C prototype.
+
+2002-08-27 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems.ads: Corrected binding for Io_Initialize.
+
+2001-08-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: New.
+ * Makefile.am: New.
+ * .cvsignore: New.
+
+2001-02-01 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems.ads, rtems.adb: Formatting cleaned up. Task based timer
+ directives added. This is Timer_Initiate_Server,
+ Timer_Server_Fire_After, and Timer_Server_Fire_When.
+
+2001-02-01 Joel Sherrill <joel@OARcorp.com>
+
+ * ChangeLog: New file.
+
diff --git a/cpukit/ada/Makefile.am b/cpukit/ada/Makefile.am
new file mode 100644
index 0000000000..c6b08ce9eb
--- /dev/null
+++ b/cpukit/ada/Makefile.am
@@ -0,0 +1,42 @@
+#
+# $Id$
+#
+
+if RTEMS_ADA
+include_adadir = $(includedir)/adainclude
+include_ada_HEADERS = rtems.adb rtems.ads
+include_ada_HEADERS += rtems-multiprocessing.adb rtems-multiprocessing.ads
+endif
+
+all-local: $(PREINSTALL_FILES)
+
+PREINSTALL_DIRS =
+PREINSTALL_FILES =
+
+if RTEMS_ADA
+$(PROJECT_INCLUDE)/adainclude/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/adainclude
+ @: > $(PROJECT_INCLUDE)/adainclude/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/adainclude/$(dirstamp)
+
+$(PROJECT_INCLUDE)/adainclude/rtems.adb: rtems.adb $(PROJECT_INCLUDE)/adainclude/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/adainclude/rtems.adb
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/adainclude/rtems.adb
+
+$(PROJECT_INCLUDE)/adainclude/rtems.ads: rtems.ads $(PROJECT_INCLUDE)/adainclude/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/adainclude/rtems.ads
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/adainclude/rtems.ads
+
+$(PROJECT_INCLUDE)/adainclude/rtems-multiprocessing.adb: rtems-multiprocessing.adb $(PROJECT_INCLUDE)/adainclude/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/adainclude/rtems-multiprocessing.adb
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/adainclude/rtems-multiprocessing.adb
+
+$(PROJECT_INCLUDE)/adainclude/rtems-multiprocessing.ads: rtems-multiprocessing.ads $(PROJECT_INCLUDE)/adainclude/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/adainclude/rtems-multiprocessing.ads
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/adainclude/rtems-multiprocessing.ads
+endif
+
+CLEANFILES = $(PREINSTALL_FILES)
+DISTCLEANFILES = $(PREINSTALL_DIRS)
+
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/ada/rtems-multiprocessing.adb b/cpukit/ada/rtems-multiprocessing.adb
new file mode 100644
index 0000000000..3654b41752
--- /dev/null
+++ b/cpukit/ada/rtems-multiprocessing.adb
@@ -0,0 +1,38 @@
+--
+-- RTEMS Multiprocessing Manager/ Body
+--
+-- DESCRIPTION:
+--
+-- This package provides the interface to the Multiprocessing Manager
+-- of the RTEMS API.
+--
+-- DEPENDENCIES:
+--
+--
+-- COPYRIGHT (c) 1997.
+-- On-Line Applications Research Corporation (OAR).
+--
+-- The license and distribution terms for this file may in
+-- the file LICENSE in this distribution or at
+-- http://www.rtems.com/license/LICENSE.
+--
+-- $Id$
+--
+
+package body RTEMS.Multiprocessing is
+
+ --
+ -- Announce
+ --
+
+ procedure Announce is
+ procedure Multiprocessing_Announce_Base;
+ pragma Import (C, Multiprocessing_Announce_Base,
+ "rtems_multiprocessing_announce");
+ begin
+
+ Multiprocessing_Announce_Base;
+
+ end Announce;
+
+end RTEMS.Multiprocessing;
diff --git a/cpukit/ada/rtems-multiprocessing.ads b/cpukit/ada/rtems-multiprocessing.ads
new file mode 100644
index 0000000000..3d6f60879d
--- /dev/null
+++ b/cpukit/ada/rtems-multiprocessing.ads
@@ -0,0 +1,30 @@
+--
+-- RTEMS Multiprocessing Manager/ Specification
+--
+-- DESCRIPTION:
+--
+-- This package provides the interface to the Multiprocessing Manager
+-- of the RTEMS API.
+--
+-- DEPENDENCIES:
+--
+--
+-- COPYRIGHT (c) 1997.
+-- On-Line Applications Research Corporation (OAR).
+--
+-- The license and distribution terms for this file may in
+-- the file LICENSE in this distribution or at
+-- http://www.rtems.com/license/LICENSE.
+--
+-- $Id$
+--
+
+package RTEMS.Multiprocessing is
+
+ --
+ -- Multiprocessing Manager
+ --
+
+ procedure Announce;
+
+end RTEMS.Multiprocessing;
diff --git a/cpukit/ada/rtems.adb b/cpukit/ada/rtems.adb
new file mode 100644
index 0000000000..e9d7811f85
--- /dev/null
+++ b/cpukit/ada/rtems.adb
@@ -0,0 +1,1947 @@
+--
+-- RTEMS / Body
+--
+-- DESCRIPTION:
+--
+-- This package provides the interface to the RTEMS API.
+--
+--
+-- DEPENDENCIES:
+--
+--
+--
+-- COPYRIGHT (c) 1997-2003.
+-- On-Line Applications Research Corporation (OAR).
+--
+-- The license and distribution terms for this file may in
+-- the file LICENSE in this distribution or at
+-- http://www.rtems.com/license/LICENSE.
+--
+-- $Id$
+--
+
+with Ada;
+with Ada.Unchecked_Conversion;
+with System;
+with Interfaces; use Interfaces;
+with Interfaces.C;
+
+package body RTEMS is
+
+ --
+ -- Utility Functions
+ --
+
+ function From_Ada_Boolean (
+ Ada_Boolean : Standard.Boolean
+ ) return RTEMS.Boolean is
+ begin
+
+ if Ada_Boolean = Standard.True then
+ return RTEMS.True;
+ end if;
+
+ return RTEMS.False;
+
+ end From_Ada_Boolean;
+
+ function To_Ada_Boolean (
+ RTEMS_Boolean : RTEMS.Boolean
+ ) return Standard.Boolean is
+ begin
+
+ if RTEMS_Boolean = RTEMS.True then
+ return Standard.True;
+ end if;
+
+ return Standard.False;
+
+ end To_Ada_Boolean;
+
+ function Milliseconds_To_Microseconds (
+ Milliseconds : RTEMS.Unsigned32
+ ) return RTEMS.Unsigned32 is
+ begin
+
+ return Milliseconds * 1000;
+
+ end Milliseconds_To_Microseconds;
+
+ function Microseconds_To_Ticks (
+ Microseconds : RTEMS.Unsigned32
+ ) return RTEMS.Interval is
+ Microseconds_Per_Tick : RTEMS.Interval;
+ pragma Import (C, Microseconds_Per_Tick, "_TOD_Microseconds_per_tick");
+ begin
+
+ return Microseconds / Microseconds_Per_Tick;
+
+ end Microseconds_To_Ticks;
+
+ function Milliseconds_To_Ticks (
+ Milliseconds : RTEMS.Unsigned32
+ ) return RTEMS.Interval is
+ begin
+
+ return Microseconds_To_Ticks(Milliseconds_To_Microseconds(Milliseconds));
+
+ end Milliseconds_To_Ticks;
+
+ function Build_Name (
+ C1 : in Character;
+ C2 : in Character;
+ C3 : in Character;
+ C4 : in Character
+ ) return RTEMS.Name is
+ C1_Value : RTEMS.Unsigned32;
+ C2_Value : RTEMS.Unsigned32;
+ C3_Value : RTEMS.Unsigned32;
+ C4_Value : RTEMS.Unsigned32;
+ begin
+
+ C1_Value := Character'Pos( C1 );
+ C2_Value := Character'Pos( C2 );
+ C3_Value := Character'Pos( C3 );
+ C4_Value := Character'Pos( C4 );
+
+ return Interfaces.Shift_Left( C1_Value, 24 ) or
+ Interfaces.Shift_Left( C2_Value, 16 ) or
+ Interfaces.Shift_Left( C3_Value, 8 ) or
+ C4_Value;
+
+ end Build_Name;
+
+ procedure Name_To_Characters (
+ Name : in RTEMS.Name;
+ C1 : out Character;
+ C2 : out Character;
+ C3 : out Character;
+ C4 : out Character
+ ) is
+ C1_Value : RTEMS.Unsigned32;
+ C2_Value : RTEMS.Unsigned32;
+ C3_Value : RTEMS.Unsigned32;
+ C4_Value : RTEMS.Unsigned32;
+ begin
+
+ C1_Value := Interfaces.Shift_Right( Name, 24 );
+ C2_Value := Interfaces.Shift_Right( Name, 16 );
+ C3_Value := Interfaces.Shift_Right( Name, 8 );
+ C4_Value := Name;
+
+ C1_Value := C1_Value and 16#00FF#;
+ C2_Value := C2_Value and 16#00FF#;
+ C3_Value := C3_Value and 16#00FF#;
+ C4_Value := C4_Value and 16#00FF#;
+
+ C1 := Character'Val( C1_Value );
+ C2 := Character'Val( C2_Value );
+ C3 := Character'Val( C3_Value );
+ C4 := Character'Val( C4_Value );
+
+ end Name_To_Characters;
+
+ function Get_Node (
+ ID : in RTEMS.ID
+ ) return RTEMS.Unsigned32 is
+ begin
+
+ -- May not be right
+ return Interfaces.Shift_Right( ID, 16 );
+
+ end Get_Node;
+
+ function Get_Index (
+ ID : in RTEMS.ID
+ ) return RTEMS.Unsigned32 is
+ begin
+
+ -- May not be right
+ return ID and 16#FFFF#;
+
+ end Get_Index;
+
+ function Are_Statuses_Equal (
+ Status : in RTEMS.Status_Codes;
+ Desired : in RTEMS.Status_Codes
+ ) return Standard.Boolean is
+ begin
+
+ if Status = Desired then
+ return Standard.True;
+ end if;
+
+ return Standard.False;
+
+ end Are_Statuses_Equal;
+
+ function Is_Status_Successful (
+ Status : in RTEMS.Status_Codes
+ ) return Standard.Boolean is
+ begin
+
+ if Status = RTEMS.Successful then
+ return Standard.True;
+ end if;
+
+ return Standard.False;
+
+ end Is_Status_Successful;
+
+ function Subtract (
+ Left : in RTEMS.Address;
+ Right : in RTEMS.Address
+ ) return RTEMS.Unsigned32 is
+ function To_Unsigned32 is
+ new Ada.Unchecked_Conversion (System.Address, RTEMS.Unsigned32);
+
+ begin
+ return To_Unsigned32(Left) - To_Unsigned32(Right);
+ end Subtract;
+
+ function Are_Equal (
+ Left : in RTEMS.Address;
+ Right : in RTEMS.Address
+ ) return Standard.Boolean is
+ function To_Unsigned32 is
+ new Ada.Unchecked_Conversion (System.Address, RTEMS.Unsigned32);
+
+ begin
+ return (To_Unsigned32(Left) = To_Unsigned32(Right));
+ end Are_Equal;
+
+ --
+ --
+ -- RTEMS API
+ --
+
+ --
+ -- Initialization Manager
+ --
+
+ procedure Initialize_Executive (
+ Configuration_Table : in RTEMS.Configuration_Table_Pointer;
+ CPU_Table : in RTEMS.CPU_Table_Pointer
+ ) is
+ procedure Initialize_Executive_Base (
+ Configuration_Table : in RTEMS.Configuration_Table_Pointer;
+ CPU_Table : in RTEMS.CPU_Table_Pointer
+ );
+ pragma Import (C, Initialize_Executive_Base,
+ "rtems_initialize_executive");
+
+ begin
+
+ Initialize_Executive_Base (Configuration_Table, CPU_Table);
+
+ end Initialize_Executive;
+
+ procedure Initialize_Executive_Early (
+ Configuration_Table : in RTEMS.Configuration_Table_Pointer;
+ CPU_Table : in RTEMS.CPU_Table_Pointer;
+ Level : out RTEMS.ISR_Level
+ ) is
+ function Initialize_Executive_Early_Base (
+ Configuration_Table : in RTEMS.Configuration_Table_Pointer;
+ CPU_Table : in RTEMS.CPU_Table_Pointer
+ ) return RTEMS.ISR_Level;
+ pragma Import (C, Initialize_Executive_Early_Base,
+ "rtems_initialize_executive_early");
+
+ begin
+
+ Level := Initialize_Executive_Early_Base (Configuration_Table, CPU_Table);
+
+ end Initialize_Executive_Early;
+
+ procedure Initialize_Executive_Late (
+ BSP_Level : in RTEMS.ISR_Level
+ ) is
+ procedure Initialize_Executive_Late_Base (
+ Level : in RTEMS.ISR_Level
+ );
+ pragma Import (C, Initialize_Executive_Late_Base,
+ "rtems_initialize_executive_late");
+
+ begin
+
+ Initialize_Executive_Late_Base (BSP_Level);
+
+ end Initialize_Executive_Late;
+
+ procedure Shutdown_Executive (
+ Result : in RTEMS.Unsigned32
+ ) is
+ procedure Shutdown_Executive_Base;
+ pragma Import (C,Shutdown_Executive_Base,"rtems_shutdown_executive");
+ begin
+
+ Shutdown_Executive_Base;
+
+ end Shutdown_Executive;
+
+ --
+ -- Task Manager
+ --
+
+ procedure Task_Create (
+ Name : in RTEMS.Name;
+ Initial_Priority : in RTEMS.Task_Priority;
+ Stack_Size : in RTEMS.Unsigned32;
+ Initial_Modes : in RTEMS.Mode;
+ Attribute_Set : in RTEMS.Attribute;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Task_Create_Base (
+ Name : RTEMS.Name;
+ Initial_Priority : RTEMS.Task_Priority;
+ Stack_Size : RTEMS.Unsigned32;
+ Initial_Modes : RTEMS.Mode;
+ Attribute_Set : RTEMS.Attribute;
+ ID : access RTEMS.ID
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Task_Create_Base, "rtems_task_create");
+ ID_Base : aliased RTEMS.ID := ID;
+ begin
+ Result := Task_Create_Base (
+ Name,
+ Initial_Priority,
+ Stack_Size,
+ Initial_Modes,
+ Attribute_Set,
+ ID_Base'Unchecked_Access
+ );
+ ID := ID_Base;
+ end Task_Create;
+
+ procedure Task_Ident (
+ Name : in RTEMS.Name;
+ Node : in RTEMS.Node;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ ) is
+
+ function Task_Ident_Base (
+ Name : RTEMS.Name;
+ Node : RTEMS.Node;
+ ID : access RTEMS.ID
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Task_Ident_Base, "rtems_task_ident");
+ ID_Base : aliased RTEMS.ID := ID;
+
+ begin
+
+ Result := Task_Ident_Base ( Name, Node, ID_Base'Unchecked_Access );
+ ID := ID_Base;
+
+ end Task_Ident;
+
+ procedure Task_Start (
+ ID : in RTEMS.ID;
+ Entry_Point : in RTEMS.Task_Entry;
+ Argument : in RTEMS.Task_Argument;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Task_Start_Base (
+ ID : RTEMS.ID;
+ Entry_Point : RTEMS.Task_Entry;
+ Argument : RTEMS.Task_Argument
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Task_Start_Base, "rtems_task_start");
+ begin
+
+ Result := Task_Start_Base ( ID, Entry_Point, Argument );
+
+ end Task_Start;
+
+ procedure Task_Restart (
+ ID : in RTEMS.ID;
+ Argument : in RTEMS.Task_Argument;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Task_Restart_Base (
+ ID : RTEMS.ID;
+ Argument : RTEMS.Task_Argument
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Task_Restart_Base, "rtems_task_restart");
+ begin
+
+ Result := Task_Restart_Base ( ID, Argument );
+
+ end Task_Restart;
+
+ procedure Task_Delete (
+ ID : in RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Task_Delete_Base (
+ ID : RTEMS.ID
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Task_Delete_Base, "rtems_task_delete");
+ begin
+
+ Result := Task_Delete_Base ( ID );
+
+ end Task_Delete;
+
+ procedure Task_Suspend (
+ ID : in RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Task_Suspend_Base (
+ ID : RTEMS.ID
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Task_Suspend_Base, "rtems_task_suspend");
+ begin
+
+ Result := Task_Suspend_Base ( ID );
+
+ end Task_Suspend;
+
+ procedure Task_Resume (
+ ID : in RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Task_Resume_Base (
+ ID : RTEMS.ID
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Task_Resume_Base, "rtems_task_resume");
+ begin
+
+ Result := Task_Resume_Base ( ID );
+
+ end Task_Resume;
+
+ procedure Task_Set_Priority (
+ ID : in RTEMS.ID;
+ New_Priority : in RTEMS.Task_Priority;
+ Old_Priority : out RTEMS.Task_Priority;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Task_Set_Priority_Base (
+ ID : RTEMS.ID;
+ New_Priority : RTEMS.Task_Priority;
+ Old_Priority : access RTEMS.Task_Priority
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Task_Set_Priority_Base, "rtems_task_set_priority");
+ Old_Priority_Base : aliased RTEMS.Task_Priority := Old_Priority;
+ begin
+
+ Result := Task_Set_Priority_Base (
+ ID,
+ New_Priority,
+ Old_Priority_Base'Unchecked_Access
+ );
+ Old_Priority := Old_Priority_Base;
+
+ end Task_Set_Priority;
+
+ procedure Task_Mode (
+ Mode_Set : in RTEMS.Mode;
+ Mask : in RTEMS.Mode;
+ Previous_Mode_Set : out RTEMS.Mode;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Task_Mode_Base (
+ Mode_Set : RTEMS.Mode;
+ Mask : RTEMS.Mode;
+ Previous_Mode_Set : access RTEMS.Mode
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Task_Mode_Base, "rtems_task_mode");
+ Previous_Mode_Set_Base : aliased RTEMS.Mode := Previous_Mode_Set;
+ begin
+
+ Result := Task_Mode_Base (
+ Mode_Set,
+ Mask,
+ Previous_Mode_Set_Base'Unchecked_Access
+ );
+ Previous_Mode_Set := Previous_Mode_Set_Base;
+
+ end Task_Mode;
+
+ procedure Task_Get_Note (
+ ID : in RTEMS.ID;
+ Notepad : in RTEMS.Notepad_Index;
+ Note : out RTEMS.Unsigned32;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Task_Get_Note_Base (
+ ID : RTEMS.ID;
+ Notepad : RTEMS.Notepad_Index;
+ Note : access RTEMS.Unsigned32
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Task_Get_Note_Base, "rtems_task_get_note");
+ Note_Base : aliased RTEMS.Unsigned32 := Note;
+ begin
+
+ Result := Task_Get_Note_Base ( ID, Notepad, Note_Base'Unchecked_Access );
+ Note := NOTE_Base;
+
+ end Task_Get_Note;
+
+ procedure Task_Set_Note (
+ ID : in RTEMS.ID;
+ Notepad : in RTEMS.Notepad_Index;
+ Note : in RTEMS.Unsigned32;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Task_Set_Note_Base (
+ ID : RTEMS.ID;
+ Notepad : RTEMS.Notepad_Index;
+ Note : RTEMS.Unsigned32
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Task_Set_Note_Base, "rtems_task_set_note");
+ begin
+
+ Result := Task_Set_Note_Base ( ID, Notepad, Note );
+
+ end Task_Set_Note;
+
+ procedure Task_Wake_When (
+ Time_Buffer : in RTEMS.Time_Of_Day;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Task_Wake_When_Base (
+ Time_Buffer : RTEMS.Time_Of_Day
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Task_Wake_When_Base, "rtems_task_wake_when");
+ begin
+
+ Result := Task_Wake_When_Base ( Time_Buffer );
+
+ end Task_Wake_When;
+
+ procedure Task_Wake_After (
+ Ticks : in RTEMS.Interval;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Task_Wake_After_Base (
+ Ticks : RTEMS.Interval
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Task_Wake_After_Base, "rtems_task_wake_after");
+ begin
+
+ Result := Task_Wake_After_Base ( Ticks );
+
+ end Task_Wake_After;
+
+ --
+ -- Interrupt Manager
+ --
+
+ procedure Interrupt_Catch (
+ New_ISR_Handler : in RTEMS.Address;
+ Vector : in RTEMS.Vector_Number;
+ Old_ISR_Handler : out RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Interrupt_Catch_Base (
+ New_ISR_Handler : RTEMS.Address;
+ Vector : RTEMS.Vector_Number;
+ Old_ISR_Handler : access RTEMS.Address
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Interrupt_Catch_Base, "rtems_interrupt_catch");
+ Old_ISR_Handler_Base : aliased RTEMS.Address := Old_ISR_Handler;
+ begin
+
+ Result := Interrupt_Catch_Base (
+ New_ISR_Handler,
+ Vector,
+ OLD_ISR_HANDLER_Base'Unchecked_Access
+ );
+ Old_ISR_Handler := OLD_ISR_HANDLER_Base;
+
+ end Interrupt_Catch;
+
+ -- Interrupt_Disable is interfaced in the specification
+ -- Interrupt_Enable is interfaced in the specification
+ -- Interrupt_Flash is interfaced in the specification
+ -- Interrupt_Is_In_Progress is interfaced in the specification
+
+ --
+ -- Clock Manager
+ --
+
+ procedure Clock_Get (
+ Option : in RTEMS.Clock_Get_Options;
+ Time_Buffer : in RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Clock_Get_base (
+ Option : RTEMS.Clock_Get_Options;
+ Time_Buffer : RTEMS.Address
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Clock_Get_base, "rtems_clock_get");
+ begin
+
+ Result := Clock_Get_base ( Option, Time_Buffer );
+
+ end Clock_Get;
+
+ procedure Clock_Set (
+ Time_Buffer : in RTEMS.Time_Of_Day;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Clock_Set_base (
+ Time_Buffer : RTEMS.Time_Of_Day
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Clock_Set_base, "rtems_clock_set");
+ begin
+
+ Result := Clock_Set_base ( Time_Buffer );
+
+ end Clock_Set;
+
+ procedure Clock_Tick (
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Clock_Tick_Base return RTEMS.Status_Codes;
+ pragma Import (C, Clock_Tick_Base, "rtems_clock_tick");
+ begin
+
+ Result := Clock_Tick_Base;
+
+ end Clock_Tick;
+
+ --
+ -- Extension Manager
+ --
+
+ procedure Extension_Create (
+ Name : in RTEMS.Name;
+ Table : in RTEMS.Extensions_Table_Pointer;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Extension_Create_Base (
+ Name : RTEMS.Name;
+ Table : RTEMS.Extensions_Table_Pointer;
+ ID : access RTEMS.ID
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Extension_Create_Base, "rtems_extension_create");
+ ID_Base : aliased RTEMS.ID := ID;
+ begin
+
+ Result := Extension_Create_Base ( Name, Table, ID_Base'Unchecked_Access );
+ ID := ID_Base;
+
+ end Extension_Create;
+
+ procedure Extension_Ident (
+ Name : in RTEMS.Name;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Extension_Ident_Base (
+ Name : RTEMS.Name;
+ ID : access RTEMS.ID
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Extension_Ident_Base, "rtems_extension_ident");
+ ID_Base : aliased RTEMS.ID := ID;
+ begin
+
+ Result := Extension_Ident_Base ( Name, ID_Base'Unchecked_Access );
+ ID := ID_Base;
+
+ end Extension_Ident;
+
+ procedure Extension_Delete (
+ ID : in RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Extension_Delete_Base (
+ ID : RTEMS.ID
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Extension_Delete_Base, "rtems_extension_delete");
+ begin
+
+ Result := Extension_Delete_Base ( ID );
+
+ end Extension_Delete;
+
+ --
+ -- Timer Manager
+ --
+
+ procedure Timer_Create (
+ Name : in RTEMS.Name;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Timer_Create_Base (
+ Name : RTEMS.Name;
+ ID : access RTEMS.ID
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Timer_Create_Base, "rtems_timer_create");
+ ID_Base : aliased RTEMS.ID := ID;
+ begin
+
+ Result := Timer_Create_Base ( Name, ID_Base'Unchecked_Access );
+ ID := ID_Base;
+
+ end Timer_Create;
+
+ procedure Timer_Ident (
+ Name : in RTEMS.Name;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Timer_Ident_Base (
+ Name : RTEMS.Name;
+ ID : access RTEMS.ID
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Timer_Ident_Base, "rtems_timer_ident");
+ ID_Base : aliased RTEMS.ID := ID;
+ begin
+
+ Result := Timer_Ident_Base ( Name, ID_Base'Unchecked_Access );
+ ID := ID_Base;
+
+ end Timer_Ident;
+
+ procedure Timer_Delete (
+ ID : in RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Timer_Delete_Base (
+ ID : RTEMS.ID
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Timer_Delete_Base, "rtems_timer_delete");
+ begin
+
+ Result := Timer_Delete_Base ( ID );
+
+ end Timer_Delete;
+
+ procedure Timer_Fire_After (
+ ID : in RTEMS.ID;
+ Ticks : in RTEMS.Interval;
+ Routine : in RTEMS.Timer_Service_Routine;
+ User_Data : in RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Timer_Fire_After_Base (
+ ID : RTEMS.ID;
+ Ticks : RTEMS.Interval;
+ Routine : RTEMS.Timer_Service_Routine;
+ User_Data : RTEMS.Address
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Timer_Fire_After_Base, "rtems_timer_fire_after");
+ begin
+
+ Result := Timer_Fire_After_Base ( ID, Ticks, Routine, User_Data );
+
+ end Timer_Fire_After;
+
+ procedure Timer_Server_Fire_After (
+ ID : in RTEMS.ID;
+ Ticks : in RTEMS.Interval;
+ Routine : in RTEMS.Timer_Service_Routine;
+ User_Data : in RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Timer_Server_Fire_After_Base (
+ ID : RTEMS.ID;
+ Ticks : RTEMS.Interval;
+ Routine : RTEMS.Timer_Service_Routine;
+ User_Data : RTEMS.Address
+ ) return RTEMS.Status_Codes;
+ pragma Import (
+ C,
+ Timer_Server_Fire_After_Base,
+ "rtems_timer_server_fire_after"
+ );
+ begin
+
+ Result := Timer_Server_Fire_After_Base ( ID, Ticks, Routine, User_Data );
+
+ end Timer_Server_Fire_After;
+
+ procedure Timer_Fire_When (
+ ID : in RTEMS.ID;
+ Wall_Time : in RTEMS.Time_Of_Day;
+ Routine : in RTEMS.Timer_Service_Routine;
+ User_Data : in RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Timer_Fire_When_Base (
+ ID : RTEMS.ID;
+ Wall_Time : RTEMS.Time_Of_Day;
+ Routine : RTEMS.Timer_Service_Routine;
+ User_Data : RTEMS.Address
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Timer_Fire_When_Base, "rtems_timer_fire_when");
+ begin
+
+ Result := Timer_Fire_When_Base ( ID, Wall_Time, Routine, User_Data );
+
+ end Timer_Fire_When;
+
+ procedure Timer_Server_Fire_When (
+ ID : in RTEMS.ID;
+ Wall_Time : in RTEMS.Time_Of_Day;
+ Routine : in RTEMS.Timer_Service_Routine;
+ User_Data : in RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Timer_Server_Fire_When_Base (
+ ID : RTEMS.ID;
+ Wall_Time : RTEMS.Time_Of_Day;
+ Routine : RTEMS.Timer_Service_Routine;
+ User_Data : RTEMS.Address
+ ) return RTEMS.Status_Codes;
+ pragma Import (
+ C,
+ Timer_Server_Fire_When_Base,
+ "rtems_timer_server_fire_when"
+ );
+ begin
+
+ Result :=
+ Timer_Server_Fire_When_Base ( ID, Wall_Time, Routine, User_Data );
+ end Timer_Server_Fire_When;
+
+ procedure Timer_Reset (
+ ID : in RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Timer_Reset_Base (
+ ID : RTEMS.ID
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Timer_Reset_Base, "rtems_timer_reset");
+ begin
+
+ Result := Timer_Reset_Base ( ID );
+
+ end Timer_Reset;
+
+ procedure Timer_Cancel (
+ ID : in RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Timer_Cancel_Base (
+ ID : RTEMS.ID
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Timer_Cancel_Base, "rtems_timer_cancel");
+ begin
+
+ Result := Timer_Cancel_Base ( ID );
+
+ end Timer_Cancel;
+
+ procedure Timer_Initiate_Server (
+ Server_Priority : in RTEMS.Task_Priority;
+ Stack_Size : in RTEMS.Unsigned32;
+ Attribute_Set : in RTEMS.Attribute;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Timer_Initiate_Server_Base (
+ Server_Priority : RTEMS.Task_Priority;
+ Stack_Size : RTEMS.Unsigned32;
+ Attribute_Set : RTEMS.Attribute
+ ) return RTEMS.Status_Codes;
+ pragma Import (
+ C,
+ Timer_Initiate_Server_Base,
+ "rtems_timer_initiate_server"
+ );
+ begin
+ Result := Timer_Initiate_Server_Base (
+ Server_Priority,
+ Stack_Size,
+ Attribute_Set
+ );
+ end Timer_Initiate_Server;
+
+ --
+ -- Semaphore Manager
+ --
+
+ procedure Semaphore_Create (
+ Name : in RTEMS.Name;
+ Count : in RTEMS.Unsigned32;
+ Attribute_Set : in RTEMS.Attribute;
+ Priority_Ceiling : in RTEMS.Task_Priority;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Semaphore_Create_Base (
+ Name : RTEMS.Name;
+ Count : RTEMS.Unsigned32;
+ Attribute_Set : RTEMS.Attribute;
+ Priority_Ceiling : RTEMS.Task_Priority;
+ ID : access RTEMS.ID
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Semaphore_Create_Base, "rtems_semaphore_create");
+ ID_Base : aliased RTEMS.ID := ID;
+ begin
+
+ Result := Semaphore_Create_Base (
+ Name,
+ Count,
+ Attribute_Set,
+ Priority_Ceiling,
+ ID_Base'Unchecked_Access
+ );
+ ID := ID_Base;
+
+ end Semaphore_Create;
+
+ procedure Semaphore_Delete (
+ ID : in RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Semaphore_Delete_Base (
+ ID : RTEMS.ID
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Semaphore_Delete_Base, "rtems_semaphore_delete");
+ begin
+
+ Result := Semaphore_Delete_Base ( ID );
+
+ end Semaphore_Delete;
+
+ procedure Semaphore_Ident (
+ Name : in RTEMS.Name;
+ Node : in RTEMS.Unsigned32;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Semaphore_Ident_Base (
+ Name : RTEMS.Name;
+ Node : RTEMS.Unsigned32;
+ ID : access RTEMS.ID
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Semaphore_Ident_Base, "rtems_semaphore_ident");
+ ID_Base : aliased RTEMS.ID := ID;
+ begin
+
+ Result := Semaphore_Ident_Base ( Name, Node, ID_Base'Unchecked_Access );
+ ID := ID_Base;
+
+ end Semaphore_Ident;
+
+ procedure Semaphore_Obtain (
+ ID : in RTEMS.ID;
+ Option_Set : in RTEMS.Option;
+ Timeout : in RTEMS.Interval;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Semaphore_Obtain_Base (
+ ID : RTEMS.ID;
+ Option_Set : RTEMS.Option;
+ Timeout : RTEMS.Interval
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Semaphore_Obtain_Base, "rtems_semaphore_obtain");
+ begin
+
+ Result := Semaphore_Obtain_Base ( ID, Option_Set, Timeout );
+
+ end Semaphore_Obtain;
+
+ procedure Semaphore_Release (
+ ID : in RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Semaphore_Release_Base (
+ ID : RTEMS.ID
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Semaphore_Release_Base, "rtems_semaphore_release");
+ begin
+
+ Result := Semaphore_Release_Base ( ID );
+
+ end Semaphore_Release;
+
+ --
+ -- Message Queue Manager
+ --
+
+ procedure Message_Queue_Create (
+ Name : in RTEMS.Name;
+ Count : in RTEMS.Unsigned32;
+ Max_Message_Size : in RTEMS.Unsigned32;
+ Attribute_Set : in RTEMS.Attribute;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ ) is
+ -- XXX broken
+ function Message_Queue_Create_Base (
+ Name : RTEMS.Name;
+ Count : RTEMS.Unsigned32;
+ Max_Message_Size : RTEMS.Unsigned32;
+ Attribute_Set : RTEMS.Attribute;
+ ID : access RTEMS.ID
+ ) return RTEMS.Status_Codes;
+ pragma Import (C,
+ Message_Queue_Create_Base, "rtems_message_queue_create");
+ ID_Base : aliased RTEMS.ID := ID;
+ begin
+
+ Result := Message_Queue_Create_Base (
+ Name,
+ Count,
+ Max_Message_Size,
+ Attribute_Set,
+ ID_Base'Unchecked_Access
+ );
+ ID := ID_Base;
+
+ end Message_Queue_Create;
+
+ procedure Message_Queue_Ident (
+ Name : in RTEMS.Name;
+ Node : in RTEMS.Unsigned32;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Message_Queue_Ident_Base (
+ Name : RTEMS.Name;
+ Node : RTEMS.Unsigned32;
+ ID : access RTEMS.ID
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Message_Queue_Ident_Base, "rtems_message_queue_ident");
+ ID_Base : aliased RTEMS.ID := ID;
+ begin
+
+ Result :=
+ Message_Queue_Ident_Base ( Name, Node, ID_Base'Unchecked_Access );
+ ID := ID_Base;
+
+ end Message_Queue_Ident;
+
+ procedure Message_Queue_Delete (
+ ID : in RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Message_Queue_Delete_Base (
+ ID : RTEMS.ID
+ ) return RTEMS.Status_Codes;
+ pragma Import (
+ C, Message_Queue_Delete_Base, "rtems_message_queue_delete");
+ begin
+
+ Result := Message_Queue_Delete_Base ( ID );
+
+ end Message_Queue_Delete;
+
+ procedure Message_Queue_Send (
+ ID : in RTEMS.ID;
+ Buffer : in RTEMS.Address;
+ Size : in RTEMS.Unsigned32;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Message_Queue_Send_Base (
+ ID : RTEMS.ID;
+ Buffer : RTEMS.Address;
+ Size : RTEMS.Unsigned32
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Message_Queue_Send_Base, "rtems_message_queue_send");
+ begin
+
+ Result := Message_Queue_Send_Base ( ID, Buffer, Size );
+
+ end Message_Queue_Send;
+
+ procedure Message_Queue_Urgent (
+ ID : in RTEMS.ID;
+ Buffer : in RTEMS.Address;
+ Size : in RTEMS.Unsigned32;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Message_Queue_Urgent_Base (
+ ID : RTEMS.ID;
+ Buffer : RTEMS.Address;
+ Size : RTEMS.Unsigned32
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Message_Queue_Urgent_Base,
+ "rtems_message_queue_urgent");
+ begin
+
+ Result := Message_Queue_Urgent_Base ( ID, Buffer, Size );
+
+ end Message_Queue_Urgent;
+
+ procedure Message_Queue_Broadcast (
+ ID : in RTEMS.ID;
+ Buffer : in RTEMS.Address;
+ Size : in RTEMS.Unsigned32;
+ Count : out RTEMS.Unsigned32;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Message_Queue_Broadcast_Base (
+ ID : RTEMS.ID;
+ Buffer : RTEMS.Address;
+ Size : RTEMS.Unsigned32;
+ Count : access RTEMS.Unsigned32
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Message_Queue_Broadcast_Base,
+ "rtems_message_queue_broadcast");
+ Count_Base : aliased RTEMS.Unsigned32 := Count;
+ begin
+
+ Result := Message_Queue_Broadcast_Base (
+ ID,
+ Buffer,
+ Size,
+ Count_Base'Unchecked_Access
+ );
+ Count := Count_Base;
+
+ end Message_Queue_Broadcast;
+
+ procedure Message_Queue_Receive (
+ ID : in RTEMS.ID;
+ Buffer : in RTEMS.Address;
+ Option_Set : in RTEMS.Option;
+ Timeout : in RTEMS.Interval;
+ Size : out RTEMS.Unsigned32;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Message_Queue_Receive_Base (
+ ID : RTEMS.ID;
+ Buffer : RTEMS.Address;
+ Size : access RTEMS.Unsigned32;
+ Option_Set : RTEMS.Option;
+ Timeout : RTEMS.Interval
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Message_Queue_Receive_Base,
+ "rtems_message_queue_receive");
+ Size_Base : aliased RTEMS.Unsigned32;
+ begin
+
+ Result := Message_Queue_Receive_Base (
+ ID,
+ Buffer,
+ Size_Base'Unchecked_Access,
+ Option_Set,
+ Timeout
+ );
+ Size := Size_Base;
+
+ end Message_Queue_Receive;
+
+ procedure Message_Queue_Flush (
+ ID : in RTEMS.ID;
+ Count : out RTEMS.Unsigned32;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Message_Queue_Flush_Base (
+ ID : RTEMS.ID;
+ Count : access RTEMS.Unsigned32
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Message_Queue_Flush_Base, "rtems_message_queue_flush");
+ COUNT_Base : aliased RTEMS.Unsigned32 := Count;
+ begin
+
+ Result := Message_Queue_Flush_Base ( ID, COUNT_Base'Unchecked_Access );
+ Count := COUNT_Base;
+
+ end Message_Queue_Flush;
+
+ --
+ -- Event Manager
+ --
+
+ procedure Event_Send (
+ ID : in RTEMS.ID;
+ Event_In : in RTEMS.Event_Set;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Event_Send_Base (
+ ID : RTEMS.ID;
+ Event_In : RTEMS.Event_Set
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Event_Send_Base, "rtems_event_send");
+ begin
+
+ Result := Event_Send_Base ( ID, Event_In );
+
+ end Event_Send;
+
+ procedure Event_Receive (
+ Event_In : in RTEMS.Event_Set;
+ Option_Set : in RTEMS.Option;
+ Ticks : in RTEMS.Interval;
+ Event_Out : out RTEMS.Event_Set;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Event_Receive_Base (
+ Event_In : RTEMS.Event_Set;
+ Option_Set : RTEMS.Option;
+ Ticks : RTEMS.Interval;
+ Event_Out : access RTEMS.Event_Set
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Event_Receive_Base, "rtems_event_receive");
+ Event_Out_Base : aliased RTEMS.Event_Set; -- := Event_Out;
+ begin
+
+ Result := Event_Receive_Base (
+ Event_In,
+ Option_Set,
+ Ticks,
+ Event_Out_Base'Access
+ );
+ Event_Out := Event_Out_Base;
+
+ end Event_Receive;
+
+ --
+ -- Signal Manager
+ --
+
+ procedure Signal_Catch (
+ ASR_Handler : in RTEMS.ASR_Handler;
+ Mode_Set : in RTEMS.Mode;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Signal_Catch_Base (
+ ASR_Handler : RTEMS.ASR_Handler;
+ Mode_Set : RTEMS.Mode
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Signal_Catch_Base, "rtems_signal_catch");
+ begin
+
+ Result := Signal_Catch_Base ( ASR_Handler, Mode_Set );
+
+ end Signal_Catch;
+
+ procedure Signal_Send (
+ ID : in RTEMS.ID;
+ Signal_Set : in RTEMS.Signal_Set;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Signal_Send_Base (
+ ID : RTEMS.ID;
+ Signal_Set : RTEMS.Signal_Set
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Signal_Send_Base, "rtems_signal_send");
+ begin
+
+ Result := Signal_Send_Base ( ID, Signal_Set );
+
+ end Signal_Send;
+
+
+ --
+ -- Partition Manager
+ --
+
+ procedure Partition_Create (
+ Name : in RTEMS.Name;
+ Starting_Address : in RTEMS.Address;
+ Length : in RTEMS.Unsigned32;
+ Buffer_Size : in RTEMS.Unsigned32;
+ Attribute_Set : in RTEMS.Attribute;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Partition_Create_Base (
+ Name : RTEMS.Name;
+ Starting_Address : RTEMS.Address;
+ Length : RTEMS.Unsigned32;
+ Buffer_Size : RTEMS.Unsigned32;
+ Attribute_Set : RTEMS.Attribute;
+ ID : access RTEMS.Event_Set
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Partition_Create_Base, "rtems_partition_create");
+ ID_Base : aliased RTEMS.ID := ID;
+ begin
+
+ Result := Partition_Create_Base (
+ Name,
+ Starting_Address,
+ Length,
+ Buffer_Size,
+ Attribute_Set,
+ ID_Base'Unchecked_Access
+ );
+ ID := ID_Base;
+
+ end Partition_Create;
+
+ procedure Partition_Ident (
+ Name : in RTEMS.Name;
+ Node : in RTEMS.Unsigned32;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Partition_Ident_Base (
+ Name : RTEMS.Name;
+ Node : RTEMS.Unsigned32;
+ ID : access RTEMS.Event_Set
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Partition_Ident_Base, "rtems_partition_ident");
+ ID_Base : aliased RTEMS.ID := ID;
+ begin
+
+ Result := Partition_Ident_Base ( Name, Node, ID_Base'Unchecked_Access );
+ ID := ID_Base;
+
+ end Partition_Ident;
+
+ procedure Partition_Delete (
+ ID : in RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Partition_Delete_Base (
+ ID : RTEMS.ID
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Partition_Delete_Base, "rtems_partition_delete");
+ begin
+
+ Result := Partition_Delete_Base ( ID );
+
+ end Partition_Delete;
+
+ procedure Partition_Get_Buffer (
+ ID : in RTEMS.ID;
+ Buffer : out RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Partition_Get_Buffer_Base (
+ ID : RTEMS.ID;
+ Buffer : access RTEMS.Address
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Partition_Get_Buffer_Base,
+ "rtems_partition_get_buffer");
+ Buffer_Base : aliased RTEMS.Address := Buffer;
+ begin
+
+ Result := Partition_Get_Buffer_Base ( ID, Buffer_Base'Unchecked_Access );
+ Buffer := Buffer_Base;
+
+ end Partition_Get_Buffer;
+
+ procedure Partition_Return_Buffer (
+ ID : in RTEMS.ID;
+ Buffer : in RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Partition_Return_Buffer_Base (
+ ID : RTEMS.Name;
+ Buffer : RTEMS.Address
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Partition_Return_Buffer_Base,
+ "rtems_partition_return_buffer");
+ begin
+
+ Result := Partition_Return_Buffer_Base ( ID, Buffer );
+
+ end Partition_Return_Buffer;
+
+ --
+ -- Region Manager
+ --
+
+ procedure Region_Create (
+ Name : in RTEMS.Name;
+ Starting_Address : in RTEMS.Address;
+ Length : in RTEMS.Unsigned32;
+ Page_Size : in RTEMS.Unsigned32;
+ Attribute_Set : in RTEMS.Attribute;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Region_Create_Base (
+ Name : RTEMS.Name;
+ Starting_Address : RTEMS.Address;
+ Length : RTEMS.Unsigned32;
+ Page_Size : RTEMS.Unsigned32;
+ Attribute_Set : RTEMS.Attribute;
+ ID : access RTEMS.ID
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Region_Create_Base, "rtems_region_create");
+ ID_Base : aliased RTEMS.ID := ID;
+ begin
+
+ Result := Region_Create_Base (
+ Name,
+ Starting_Address,
+ Length,
+ Page_Size,
+ Attribute_Set,
+ ID_Base'Unchecked_Access
+ );
+ ID := ID_Base;
+
+ end Region_Create;
+
+ procedure Region_Ident (
+ Name : in RTEMS.Name;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Region_Ident_Base (
+ Name : RTEMS.Name;
+ ID : access RTEMS.ID
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Region_Ident_Base, "rtems_region_ident");
+ ID_Base : aliased RTEMS.ID := ID;
+ begin
+
+ Result := Region_Ident_Base ( Name, ID_Base'Unchecked_Access );
+ ID := ID_Base;
+
+ end Region_Ident;
+
+ procedure Region_Delete (
+ ID : in RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Region_Delete_Base (
+ ID : RTEMS.ID
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Region_Delete_Base, "rtems_region_delete");
+ begin
+
+ Result := Region_Delete_Base ( ID );
+
+ end Region_Delete;
+
+ procedure Region_Extend (
+ ID : in RTEMS.ID;
+ Starting_Address : in RTEMS.Address;
+ Length : in RTEMS.Unsigned32;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Region_Extend_Base (
+ ID : RTEMS.ID;
+ Starting_Address : RTEMS.Address;
+ Length : RTEMS.Unsigned32
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Region_Extend_Base, "rtems_region_extend");
+ begin
+
+ Result := Region_Extend_Base ( ID, Starting_Address, Length );
+
+ end Region_Extend;
+
+ procedure Region_Get_Segment (
+ ID : in RTEMS.ID;
+ Size : in RTEMS.Unsigned32;
+ Option_Set : in RTEMS.Option;
+ Timeout : in RTEMS.Interval;
+ Segment : out RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Region_Get_Segment_Base (
+ ID : RTEMS.ID;
+ Size : RTEMS.Unsigned32;
+ Option_Set : RTEMS.Option;
+ Timeout : RTEMS.Interval;
+ Segment : access RTEMS.Address
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Region_Get_Segment_Base, "rtems_region_get_segment");
+ Segment_Base : aliased RTEMS.Address := Segment;
+ begin
+
+ Result := Region_Get_Segment_Base (
+ ID,
+ Size,
+ Option_Set,
+ Timeout,
+ Segment_Base'Unchecked_Access
+ );
+ Segment := SEGMENT_Base;
+
+ end Region_Get_Segment;
+
+ procedure Region_Get_Segment_Size (
+ ID : in RTEMS.ID;
+ Segment : in RTEMS.Address;
+ Size : out RTEMS.Unsigned32;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Region_Get_Segment_Size_Base (
+ ID : RTEMS.ID;
+ Segment : RTEMS.Address;
+ Size : access RTEMS.Unsigned32
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Region_Get_Segment_Size_Base,
+ "rtems_region_get_segment_size");
+ Size_Base : aliased RTEMS.Unsigned32 := Size;
+ begin
+
+ Result := Region_Get_Segment_Size_Base (
+ ID,
+ Segment,
+ Size_Base'Unchecked_Access
+ );
+ Size := SIZE_Base;
+
+ end Region_Get_Segment_Size;
+
+ procedure Region_Return_Segment (
+ ID : in RTEMS.ID;
+ Segment : in RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Region_Return_Segment_Base (
+ ID : RTEMS.ID;
+ Segment : RTEMS.Address
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Region_Return_Segment_Base,
+ "rtems_region_return_segment");
+ begin
+
+ Result := Region_Return_Segment_Base ( ID, Segment );
+
+ end Region_Return_Segment;
+
+ --
+ -- Dual Ported Memory Manager
+ --
+
+ procedure Port_Create (
+ Name : in RTEMS.Name;
+ Internal_Start : in RTEMS.Address;
+ External_Start : in RTEMS.Address;
+ Length : in RTEMS.Unsigned32;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Port_Create_Base (
+ Name : RTEMS.Name;
+ Internal_Start : RTEMS.Address;
+ External_Start : RTEMS.Address;
+ Length : RTEMS.Unsigned32;
+ ID : access RTEMS.ID
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Port_Create_Base, "rtems_port_create");
+ ID_Base : aliased RTEMS.ID := ID;
+ begin
+
+ Result := Port_Create_Base (
+ Name,
+ Internal_Start,
+ External_Start,
+ Length,
+ ID_Base'Unchecked_Access
+ );
+ ID := ID_Base;
+
+ end Port_Create;
+
+ procedure Port_Ident (
+ Name : in RTEMS.Name;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Port_Ident_Base (
+ Name : RTEMS.Name;
+ ID : access RTEMS.ID
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Port_Ident_Base, "rtems_port_ident");
+ ID_Base : aliased RTEMS.ID := ID;
+ begin
+
+ Result := Port_Ident_Base ( Name, ID_Base'Unchecked_Access );
+ ID := ID_Base;
+
+ end Port_Ident;
+
+ procedure Port_Delete (
+ ID : in RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Port_Delete_Base (
+ ID : RTEMS.ID
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Port_Delete_Base, "rtems_port_delete");
+ begin
+
+ Result := Port_Delete_Base ( ID );
+
+ end Port_Delete;
+
+ procedure Port_External_To_Internal (
+ ID : in RTEMS.ID;
+ External : in RTEMS.Address;
+ Internal : out RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Port_External_To_Internal_Base (
+ ID : RTEMS.ID;
+ External : RTEMS.Address;
+ Internal : access RTEMS.Address
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Port_External_To_Internal_Base,
+ "rtems_port_external_to_internal");
+ Internal_Base : aliased RTEMS.Address := Internal;
+ begin
+
+ Result := Port_External_To_Internal_Base (
+ ID,
+ External,
+ Internal_Base'Unchecked_Access
+ );
+ Internal := INTERNAL_Base;
+
+ end Port_External_To_Internal;
+
+ procedure Port_Internal_To_External (
+ ID : in RTEMS.ID;
+ Internal : in RTEMS.Address;
+ External : out RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Port_Internal_To_External_Base (
+ ID : RTEMS.ID;
+ Internal : RTEMS.Address;
+ External : access RTEMS.Address
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Port_Internal_To_External_Base,
+ "rtems_port_internal_to_external");
+ External_Base : aliased RTEMS.Address := External;
+ begin
+
+ Result := Port_Internal_To_External_Base (
+ ID,
+ Internal,
+ External_Base'Unchecked_Access
+ );
+ External := EXTERNAL_Base;
+
+ end Port_Internal_To_External;
+
+ --
+ -- Input/Output Manager
+ --
+
+ procedure IO_Initialize (
+ Major : in RTEMS.Device_Major_Number;
+ Minor : in RTEMS.Device_Minor_Number;
+ Argument : in RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function IO_Initialize_Base (
+ Major : RTEMS.Device_Major_Number;
+ Minor : RTEMS.Device_Minor_Number;
+ Argument : RTEMS.Address
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, IO_Initialize_Base, "rtems_io_initialize");
+ begin
+
+ Result := IO_Initialize_Base ( Major, Minor, Argument );
+
+ end IO_Initialize;
+
+ procedure IO_Register_Name (
+ Name : in String;
+ Major : in RTEMS.Device_Major_Number;
+ Minor : in RTEMS.Device_Minor_Number;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function IO_Register_Name_Base (
+ Name : Interfaces.C.Char_Array;
+ Major : RTEMS.Device_Major_Number;
+ Minor : RTEMS.Device_Minor_Number
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, IO_Register_Name_Base, "rtems_io_register_name");
+ begin
+
+ Result :=
+ IO_Register_Name_Base ( Interfaces.C.To_C (Name), Major, Minor );
+
+ end IO_Register_Name;
+
+ procedure IO_Lookup_Name (
+ Name : in String;
+ Device_Info : in RTEMS.Driver_Name_t_Pointer;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function IO_Lookup_Name_Base (
+ Name : Interfaces.C.Char_Array;
+ Device_Info : access RTEMS.Driver_Name_t
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, IO_Lookup_Name_Base, "rtems_io_lookup_name");
+ Device_Info_Base : aliased RTEMS.Driver_Name_t;
+ begin
+
+ Result := IO_Lookup_Name_Base (
+ Interfaces.C.To_C (Name),
+ Device_Info_Base'Unchecked_Access
+ );
+ Device_Info.All := Device_Info_Base;
+
+ end IO_Lookup_Name;
+
+ procedure IO_Open (
+ Major : in RTEMS.Device_Major_Number;
+ Minor : in RTEMS.Device_Minor_Number;
+ Argument : in RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function IO_Open_Base (
+ Major : RTEMS.Device_Major_Number;
+ Minor : RTEMS.Device_Minor_Number;
+ Argument : RTEMS.Address
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, IO_Open_Base, "rtems_io_open");
+ begin
+
+ Result := IO_Open_Base (Major, Minor, Argument);
+
+ end IO_Open;
+
+ procedure IO_Close (
+ Major : in RTEMS.Device_Major_Number;
+ Minor : in RTEMS.Device_Minor_Number;
+ Argument : in RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function IO_Close_Base (
+ Major : RTEMS.Device_Major_Number;
+ Minor : RTEMS.Device_Minor_Number;
+ Argument : RTEMS.Address
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, IO_Close_Base, "rtems_io_close");
+ begin
+
+ Result := IO_Close_Base (Major, Minor, Argument);
+
+ end IO_Close;
+
+ procedure IO_Read (
+ Major : in RTEMS.Device_Major_Number;
+ Minor : in RTEMS.Device_Minor_Number;
+ Argument : in RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function IO_Read_Base (
+ Major : RTEMS.Device_Major_Number;
+ Minor : RTEMS.Device_Minor_Number;
+ Argument : RTEMS.Address
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, IO_Read_Base, "rtems_io_read");
+ begin
+
+ Result := IO_Read_Base (Major, Minor, Argument);
+
+ end IO_Read;
+
+ procedure IO_Write (
+ Major : in RTEMS.Device_Major_Number;
+ Minor : in RTEMS.Device_Minor_Number;
+ Argument : in RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function IO_Write_Base (
+ Major : RTEMS.Device_Major_Number;
+ Minor : RTEMS.Device_Minor_Number;
+ Argument : RTEMS.Address
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, IO_Write_Base, "rtems_io_write");
+ begin
+
+ Result := IO_Write_Base (Major, Minor, Argument);
+
+ end IO_Write;
+
+ procedure IO_Control (
+ Major : in RTEMS.Device_Major_Number;
+ Minor : in RTEMS.Device_Minor_Number;
+ Argument : in RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function IO_Control_Base (
+ Major : RTEMS.Device_Major_Number;
+ Minor : RTEMS.Device_Minor_Number;
+ Argument : RTEMS.Address
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, IO_Control_Base, "rtems_io_control");
+ begin
+
+ Result := IO_Control_Base (Major, Minor, Argument);
+
+ end IO_Control;
+
+ --
+ -- Fatal Error Manager
+ --
+
+ procedure Fatal_Error_Occurred (
+ The_Error : in RTEMS.Unsigned32
+ ) is
+ procedure Fatal_Error_Occurred_base (
+ The_Error : RTEMS.Unsigned32
+ );
+ pragma Import (C, Fatal_Error_Occurred_Base, "rtems_fatal_error_occurred");
+ begin
+
+ Fatal_Error_Occurred_Base ( The_Error );
+
+ end Fatal_Error_Occurred;
+
+
+ --
+ -- Rate Monotonic Manager
+ --
+
+ procedure Rate_Monotonic_Create (
+ Name : in RTEMS.Name;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Rate_Monotonic_Create_base (
+ Name : RTEMS.Name;
+ ID : access RTEMS.ID
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Rate_Monotonic_Create_base, "rtems_rate_monotonic_create");
+ ID_Base : aliased RTEMS.ID := ID;
+ begin
+
+ Result := Rate_Monotonic_Create_base ( Name, ID_Base'Unchecked_Access );
+ ID := ID_Base;
+
+ end Rate_Monotonic_Create;
+
+ procedure Rate_Monotonic_Ident (
+ Name : in RTEMS.Name;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Rate_Monotonic_Ident_Base (
+ Name : RTEMS.Name;
+ ID : access RTEMS.ID
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Rate_Monotonic_Ident_Base, "rtems_rate_monotonic_ident");
+ ID_Base : aliased RTEMS.ID := ID;
+ begin
+
+ Result := Rate_Monotonic_Ident_Base ( Name, ID_Base'Unchecked_Access );
+
+ ID := ID_Base;
+
+ end Rate_Monotonic_Ident;
+
+ procedure Rate_Monotonic_Delete (
+ ID : in RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Rate_Monotonic_Delete_Base (
+ ID : RTEMS.ID
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Rate_Monotonic_Delete_Base,
+ "rtems_rate_monotonic_delete");
+ begin
+
+ Result := Rate_Monotonic_Delete_base ( ID );
+
+ end Rate_Monotonic_Delete;
+
+ procedure Rate_Monotonic_Cancel (
+ ID : in RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Rate_Monotonic_Cancel_Base (
+ ID : RTEMS.ID
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Rate_Monotonic_Cancel_Base,
+ "rtems_rate_monotonic_cancel");
+ begin
+
+ Result := Rate_Monotonic_Cancel_Base ( ID );
+
+ end Rate_Monotonic_Cancel;
+
+ procedure Rate_Monotonic_Period (
+ ID : in RTEMS.ID;
+ Length : in RTEMS.Interval;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Rate_Monotonic_Period_Base (
+ ID : RTEMS.ID;
+ Length : RTEMS.Interval
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Rate_Monotonic_Period_Base,
+ "rtems_rate_monotonic_period");
+ begin
+
+ Result := Rate_Monotonic_Period_base ( ID, Length );
+
+ end Rate_Monotonic_Period;
+
+
+ procedure Rate_Monotonic_Get_Status (
+ ID : in RTEMS.ID;
+ Status : out RTEMS.Rate_Monotonic_Period_Status;
+ Result : out RTEMS.Status_Codes
+ ) is
+ function Rate_Monotonic_Get_Status_Base (
+ ID : RTEMS.ID;
+ Status : access RTEMS.Rate_Monotonic_Period_Status
+ ) return RTEMS.Status_Codes;
+ pragma Import (C, Rate_Monotonic_Get_Status_Base,
+ "rtems_rate_monotonic_get_status");
+
+ Status_Base : aliased RTEMS.Rate_Monotonic_Period_Status;
+ begin
+
+ Result := Rate_Monotonic_Get_Status_Base (
+ ID,
+ Status_Base'Unchecked_Access
+ );
+
+ Status := Status_Base;
+
+
+ end Rate_Monotonic_Get_Status;
+
+
+ --
+ -- Debug Manager
+ --
+
+ procedure Debug_Enable (
+ To_Be_Enabled : in RTEMS.Debug_Set
+ ) is
+ procedure Debug_Enable_Base (
+ To_Be_Enabled : RTEMS.Debug_Set
+ );
+ pragma Import (C, Debug_Enable_Base, "rtems_debug_enable");
+ begin
+
+ Debug_Enable_Base ( To_Be_Enabled );
+
+ end Debug_Enable;
+
+ procedure Debug_Disable (
+ To_Be_Disabled : in RTEMS.Debug_Set
+ ) is
+ procedure Debug_Disable_Base (
+ To_Be_Disabled : RTEMS.Debug_Set
+ );
+ pragma Import (C, Debug_Disable_Base, "rtems_debug_disable");
+ begin
+
+ Debug_Disable_Base ( To_Be_Disabled );
+
+ end Debug_Disable;
+
+ function Debug_Is_Enabled (
+ Level : in RTEMS.Debug_Set
+ ) return RTEMS.Boolean is
+ function Debug_Is_Enabled_Base (
+ Level : RTEMS.Debug_Set
+ ) return RTEMS.Boolean;
+ pragma Import (C, Debug_Is_Enabled_Base, "_Debug_Is_enabled");
+ begin
+
+ return Debug_Is_Enabled_Base ( Level );
+
+ end Debug_Is_Enabled;
+
+ -- HACK
+ -- function Configuration
+ -- return RTEMS.Configuration_Table_Pointer is
+ -- Configuration_base : RTEMS.Configuration_Table_Pointer;
+ -- pragma Import (C, Configuration_base, "_Configuration_Table");
+ -- begin
+ -- return Configuration_Base;
+ -- end Configuration;
+
+end RTEMS;
diff --git a/cpukit/ada/rtems.ads b/cpukit/ada/rtems.ads
new file mode 100644
index 0000000000..de86703552
--- /dev/null
+++ b/cpukit/ada/rtems.ads
@@ -0,0 +1,1481 @@
+--
+-- RTEMS / Specification
+--
+-- DESCRIPTION:
+--
+-- This package provides the interface to the RTEMS API.
+--
+-- DEPENDENCIES:
+--
+--
+--
+-- COPYRIGHT (c) 1997.
+-- On-Line Applications Research Corporation (OAR).
+--
+-- The license and distribution terms for this file may in
+-- the file LICENSE in this distribution or at
+-- http://www.rtems.com/license/LICENSE.
+--
+-- $Id$
+--
+
+with System;
+with System.Storage_Elements; use System.Storage_Elements;
+with Interfaces;
+with Interfaces.C;
+
+package RTEMS is
+pragma Elaborate_Body (RTEMS);
+
+ Structure_Alignment : constant := 8;
+
+ --
+ -- RTEMS Base Types
+ --
+
+ subtype Unsigned8 is Interfaces.Unsigned_8;
+ subtype Unsigned16 is Interfaces.Unsigned_16;
+ subtype Unsigned32 is Interfaces.Unsigned_32;
+ subtype Signed32 is Interfaces.Integer_32;
+
+ type Unsigned32_Pointer is access all RTEMS.Unsigned32;
+ type Unsigned16_Pointer is access all RTEMS.Unsigned16;
+ type Unsigned8_Pointer is access all RTEMS.Unsigned8;
+ type Signed32_Pointer is access all RTEMS.Signed32;
+
+ subtype Boolean is RTEMS.Unsigned32;
+ subtype Address is System.Address;
+ subtype Single is Interfaces.C.C_float;
+ subtype Double is Interfaces.C.Double;
+
+ --
+ -- The following define the size of each of the base types in
+ -- both bits and system units.
+ --
+
+ Unsigned8_Bits : constant := 7;
+ Unsigned16_Bits : constant := 15;
+ Unsigned32_Bits : constant := 31;
+ Boolean_Bits : constant := 31;
+ Address_Bits : constant := 31;
+ Single_Bits : constant := 31;
+ Double_Bits : constant := 63;
+
+ Unsigned8_Units : constant := 1;
+ Unsigned16_Units : constant := 2;
+ Unsigned32_Units : constant := 4;
+ Boolean_Units : constant := 4;
+ Address_Units : constant := 4;
+ Single_Units : constant := 4;
+ Double_Units : constant := 8;
+
+ Null_Address : constant RTEMS.Address :=
+ System.Storage_Elements.To_Address(0);
+
+ True : constant RTEMS.Boolean := 1;
+ False : constant RTEMS.Boolean := 0;
+
+ -- More Types
+ --
+
+ subtype Name is RTEMS.Unsigned32;
+ subtype ID is RTEMS.Unsigned32;
+ subtype Interval is RTEMS.Unsigned32;
+ subtype Attribute is RTEMS.Unsigned32;
+ subtype Mode is RTEMS.Unsigned32;
+ subtype Option is RTEMS.Unsigned32;
+ subtype Task_Priority is RTEMS.Unsigned32;
+ subtype Notepad_Index is RTEMS.Unsigned32 range 0 .. 15;
+
+ subtype Event_Set is RTEMS.Unsigned32;
+ subtype Signal_Set is RTEMS.Unsigned32;
+ subtype Debug_Set is RTEMS.Unsigned32;
+ subtype Device_Major_Number is RTEMS.Unsigned32;
+ subtype Device_Minor_Number is RTEMS.Unsigned32;
+ subtype Vector_Number is RTEMS.Unsigned32;
+ subtype ISR_Level is RTEMS.Unsigned32;
+
+ subtype Node is RTEMS.Unsigned32;
+
+ --
+ -- Task Related Types
+ -- XXXX fix this
+ subtype Task_Argument is RTEMS.Unsigned32;
+ type Task_Argument_PTR is access all Task_Argument;
+
+ -- XXXX fix this
+ subtype TCB is RTEMS.Unsigned32;
+ type TCB_Pointer is access all RTEMS.TCB;
+
+ subtype Task_States is RTEMS.Unsigned32;
+
+ type Task_Entry is access procedure (
+ Argument : RTEMS.Unsigned32
+ );
+
+ --
+ -- Clock and Time of Day Types
+ --
+
+ type Time_Of_Day is
+ record
+ Year : RTEMS.Unsigned32; -- year, A.D.
+ Month : RTEMS.Unsigned32; -- month, 1 .. 12
+ Day : RTEMS.Unsigned32; -- day, 1 .. 31
+ Hour : RTEMS.Unsigned32; -- hour, 0 .. 23
+ Minute : RTEMS.Unsigned32; -- minute, 0 .. 59
+ Second : RTEMS.Unsigned32; -- second, 0 .. 59
+ Ticks : RTEMS.Unsigned32; -- elapsed ticks between seconds
+ end record;
+
+ type Clock_Time_Value is
+ record
+ Seconds : RTEMS.Unsigned32;
+ Microseconds : RTEMS.Unsigned32;
+ end record;
+
+ type Clock_Get_Options is (
+ Clock_Get_TOD,
+ Clock_Get_Seconds_Since_Epoch,
+ Clock_Get_Ticks_Since_Boot,
+ Clock_Get_Ticks_Per_Seconds,
+ Clock_Get_Time_Value
+ );
+
+ --
+ -- Device Driver Entry Prototype
+ --
+
+ type Device_Driver_Entry is access function (
+ Major : in RTEMS.Device_Major_Number;
+ Minor : in RTEMS.Device_Major_Number;
+ Argument : in RTEMS.Unsigned32;
+ ID : in RTEMS.Unsigned32
+ ) return RTEMS.Unsigned32;
+
+ type Driver_Address_Table_Entry is
+ record
+ Initialization : RTEMS.Device_Driver_Entry;
+ Open : RTEMS.Device_Driver_Entry;
+ Close : RTEMS.Device_Driver_Entry;
+ Read : RTEMS.Device_Driver_Entry;
+ Write : RTEMS.Device_Driver_Entry;
+ Control : RTEMS.Device_Driver_Entry;
+ end record;
+
+ type Driver_Address_Table is array ( RTEMS.Unsigned32
+ range 1 .. RTEMS.Unsigned32'Last ) of RTEMS.Driver_Address_Table_Entry;
+
+ type Driver_Address_Table_Pointer is access all Driver_Address_Table;
+
+ type Driver_Name_t is
+ record
+ Device_Name : RTEMS.Address;
+ Device_Name_Length : RTEMS.Unsigned32;
+ Major : RTEMS.Device_Major_Number;
+ Minor : RTEMS.Device_Minor_Number;
+ end record;
+
+ type Driver_Name_t_Pointer is access all Driver_Name_t;
+
+ --
+ -- Ident Options
+ --
+
+ Search_All_Nodes : constant RTEMS.Node := 0;
+
+ --
+ -- Options
+ --
+
+ Default_Options : constant RTEMS.Option := 16#0000#;
+
+ Wait : constant RTEMS.Option := 16#0000#;
+ No_Wait : constant RTEMS.Option := 16#0001#;
+
+ Event_All : constant RTEMS.Option := 16#0000#;
+ Event_Any : constant RTEMS.Option := 16#0002#;
+
+ --
+ -- Mode constants
+ --
+
+ Default_Modes : constant RTEMS.Mode := 16#0000#;
+
+ All_Mode_Masks : constant RTEMS.Mode := 16#0000_ffff#;
+ Current_Mode : constant RTEMS.Mode := 16#0000_0000#;
+ Preempt_Mask : constant RTEMS.Mode := 16#0000_0100#;
+ Timeslice_Mask : constant RTEMS.Mode := 16#0000_0200#;
+ ASR_Mask : constant RTEMS.Mode := 16#0000_0400#;
+ Interrupt_Mask : RTEMS.Mode;
+ Preempt : constant RTEMS.Mode := 16#0000_0000#;
+ No_Preempt : constant RTEMS.Mode := 16#0000_0100#;
+ No_Timeslice : constant RTEMS.Mode := 16#0000_0000#;
+ Timeslice : constant RTEMS.Mode := 16#0000_0200#;
+ ASR : constant RTEMS.Mode := 16#0000_0000#;
+ No_ASR : constant RTEMS.Mode := 16#0000_0400#;
+
+ pragma Import (C, Interrupt_Mask, "rtems_interrupt_mask");
+
+ --
+ -- Attribute constants
+ --
+
+ Default_Attributes : constant RTEMS.Attribute := 16#00000000#;
+ No_Floating_Point : constant RTEMS.Attribute := 16#00000000#;
+ Floating_Point : constant RTEMS.Attribute := 16#00000001#;
+ Local : constant RTEMS.Attribute := 16#00000000#;
+ Global : constant RTEMS.Attribute := 16#00000002#;
+ FIFO : constant RTEMS.Attribute := 16#00000000#;
+ Priority : constant RTEMS.Attribute := 16#00000004#;
+ Counting_Semaphore : constant RTEMS.Attribute := 16#00000000#;
+ Binary_Semaphore : constant RTEMS.Attribute := 16#00000010#;
+ No_Inherit_Priority : constant RTEMS.Attribute := 16#00000000#;
+ Inherit_Priority : constant RTEMS.Attribute := 16#00000020#;
+ No_Priority_Ceiling : constant RTEMS.Attribute := 16#00000000#;
+ Priority_Ceiling : constant RTEMS.Attribute := 16#00000040#;
+
+ function Interrupt_Level (
+ Level : in RTEMS.Unsigned32
+ ) return RTEMS.Attribute;
+ pragma Import (C, Interrupt_Level, "rtems_interrupt_level_attribute");
+
+ Minimum_Stack_Size : RTEMS.Unsigned32;
+ pragma Import (C, Minimum_Stack_Size, "rtems_minimum_stack_size");
+
+
+ --
+ -- Notepad index constants
+ --
+
+ Notepad_0 : constant RTEMS.Unsigned32 := 0;
+ Notepad_1 : constant RTEMS.Unsigned32 := 1;
+ Notepad_2 : constant RTEMS.Unsigned32 := 2;
+ Notepad_3 : constant RTEMS.Unsigned32 := 3;
+ Notepad_4 : constant RTEMS.Unsigned32 := 4;
+ Notepad_5 : constant RTEMS.Unsigned32 := 5;
+ Notepad_6 : constant RTEMS.Unsigned32 := 6;
+ Notepad_7 : constant RTEMS.Unsigned32 := 7;
+ Notepad_8 : constant RTEMS.Unsigned32 := 8;
+ Notepad_9 : constant RTEMS.Unsigned32 := 9;
+ Notepad_10 : constant RTEMS.Unsigned32 := 10;
+ Notepad_11 : constant RTEMS.Unsigned32 := 11;
+ Notepad_12 : constant RTEMS.Unsigned32 := 12;
+ Notepad_13 : constant RTEMS.Unsigned32 := 13;
+ Notepad_14 : constant RTEMS.Unsigned32 := 14;
+ Notepad_15 : constant RTEMS.Unsigned32 := 15;
+
+ --
+ -- Miscellaneous
+ --
+
+ No_Timeout : constant RTEMS.Interval := 0;
+ Self : constant RTEMS.ID := 0;
+ Period_Status : constant RTEMS.Interval := 0;
+ Yield_Processor : constant RTEMS.Interval := 0;
+ Current_Priority : constant RTEMS.Task_Priority := 0;
+ No_Priority : constant RTEMS.Task_Priority := 0;
+
+
+ --
+ -- Extension Callouts and Table
+ --
+
+ type Thread_Create_Extension is access procedure (
+ Current_Task : in RTEMS.TCB_Pointer;
+ New_Task : in RTEMS.TCB_Pointer
+ );
+
+ type Thread_Start_Extension is access procedure (
+ Current_Task : in RTEMS.TCB_Pointer;
+ Started_Task : in RTEMS.TCB_Pointer
+ );
+
+ type Thread_Restart_Extension is access procedure (
+ Current_Task : in RTEMS.TCB_Pointer;
+ Restarted_Task : in RTEMS.TCB_Pointer
+ );
+
+ type Thread_Delete_Extension is access procedure (
+ Current_Task : in RTEMS.TCB_Pointer;
+ Deleted_Task : in RTEMS.TCB_Pointer
+ );
+
+ type Thread_Switch_Extension is access procedure (
+ Current_Task : in RTEMS.TCB_Pointer;
+ Heir_Task : in RTEMS.TCB_Pointer
+ );
+
+ type Thread_Post_Switch_Extension is access procedure (
+ Current_Task : in RTEMS.TCB_Pointer
+ );
+
+ type Thread_Begin_Extension is access procedure (
+ Current_Task : in RTEMS.TCB_Pointer
+ );
+
+ type Thread_Exitted_Extension is access procedure (
+ Current_Task : in RTEMS.TCB_Pointer
+ );
+
+ type Fatal_Error_Extension is access procedure (
+ Error : in RTEMS.Unsigned32
+ );
+
+ type Extensions_Table is
+ record
+ Thread_Create : RTEMS.Thread_Create_Extension;
+ Thread_Start : RTEMS.Thread_Start_Extension;
+ Thread_Restart : RTEMS.Thread_Restart_Extension;
+ Thread_Delete : RTEMS.Thread_Delete_Extension;
+ Thread_Switch : RTEMS.Thread_Switch_Extension;
+ Thread_Post_Switch : RTEMS.Thread_Post_Switch_Extension;
+ Thread_Begin : RTEMS.Thread_Begin_Extension;
+ Thread_Exitted : RTEMS.Thread_Exitted_Extension;
+ Fatal : RTEMS.Fatal_Error_Extension;
+ end record;
+
+ type Extensions_Table_Pointer is access all Extensions_Table;
+
+ --
+ -- The following type define a pointer to a watchdog/timer service routine.
+ --
+
+ type Timer_Service_Routine is access procedure (
+ ID : in RTEMS.ID;
+ User_Data : in RTEMS.Address
+ );
+
+ --
+ -- The following type define a pointer to a signal service routine.
+ --
+
+ type ASR_Handler is access procedure (
+ Signals : in RTEMS.Signal_Set
+ );
+
+ --
+ -- The following type defines the status information returned
+ -- about a period.
+ --
+
+ type Rate_Monotonic_Period_States is (
+ Inactive, -- off chain, never initialized
+ Owner_Is_Blocking, -- on chain, owner is blocking on it
+ Active, -- on chain, running continuously
+ Expired_While_Blocking, -- on chain, expired while owner was was blocking
+ Expired -- off chain, will be reset by next
+ -- rtems_rate_monotonic_period
+ );
+
+ for Rate_Monotonic_Period_States'Size use 32;
+
+ for Rate_Monotonic_Period_States use (
+ Inactive => 0,
+ Owner_Is_Blocking => 1,
+ Active => 2,
+ Expired_While_Blocking => 3,
+ Expired => 4
+ );
+
+ type Rate_Monotonic_Period_Status is
+ record
+ State : RTEMS.Rate_Monotonic_Period_States;
+ Ticks_Since_Last_Period : RTEMS.Unsigned32;
+ Ticks_Executed_Since_Last_Period : RTEMS.Unsigned32;
+ end record;
+
+ --
+ -- Method Completions Status Codes
+ --
+
+ type Status_Codes is (
+ Successful, -- successful completion
+ Task_Exitted, -- returned from a task
+ MP_Not_Configured, -- multiprocessing not configured
+ Invalid_Name, -- invalid object name
+ Invalid_ID, -- invalid object id
+ Too_Many, -- too many
+ Timeout, -- timed out waiting
+ Object_Was_Deleted, -- object deleted while waiting
+ Invalid_Size, -- specified size was invalid
+ Invalid_Address, -- address specified is invalid
+ Invalid_Number, -- number was invalid
+ Not_Defined, -- item has not been initialized
+ Resource_In_Use, -- resources still outstanding
+ Unsatisfied, -- request not satisfied
+ Incorrect_State, -- task is in wrong state
+ Already_Suspended, -- task already in state
+ Illegal_On_Self, -- illegal on calling task
+ Illegal_On_Remote_Object, -- illegal for remote object
+ Called_From_ISR, -- called from wrong environment
+ Invalid_Priority, -- invalid task priority
+ Invalid_Clock, -- invalid date/time
+ Invalid_Node, -- invalid node id
+ Not_Configured, -- directive not configured
+ Not_Owner_Of_Resource, -- not owner of resource
+ Not_Implemented, -- directive not implemented
+ Internal_Error, -- RTEMS inconsistency detected
+ No_Memory, -- no memory left in heap
+ IO_Error, -- driver IO error
+ Proxy_Blocking -- internal multiprocessing only
+ );
+
+ for Status_Codes'Size use 32;
+
+ for Status_Codes use (
+ Successful => 0,
+ Task_Exitted => 1,
+ MP_Not_Configured => 2,
+ Invalid_Name => 3,
+ Invalid_ID => 4,
+ Too_Many => 5,
+ Timeout => 6,
+ Object_Was_Deleted => 7,
+ Invalid_Size => 8,
+ Invalid_Address => 9,
+ Invalid_NumbeR => 10,
+ Not_Defined => 11,
+ Resource_In_Use => 12,
+ Unsatisfied => 13,
+ Incorrect_State => 14,
+ Already_Suspended => 15,
+ Illegal_On_Self => 16,
+ Illegal_On_Remote_Object => 17,
+ Called_From_ISR => 18,
+ Invalid_Priority => 19,
+ Invalid_Clock => 20,
+ Invalid_Node => 21,
+ Not_Configured => 22,
+ Not_Owner_Of_Resource => 23,
+ Not_ImplementeD => 24,
+ Internal_Error => 25,
+ No_Memory => 26,
+ IO_Error => 27,
+ Proxy_Blocking => 28
+ );
+
+ --
+ -- RTEMS Events
+ --
+
+ Pending_Events : constant RTEMS.Event_Set := 16#0000_0000#;
+ All_Events : constant RTEMS.Event_Set := 16#FFFF_FFFF#;
+ Event_0 : constant RTEMS.Event_Set := 16#0000_0001#;
+ Event_1 : constant RTEMS.Event_Set := 16#0000_0002#;
+ Event_2 : constant RTEMS.Event_Set := 16#0000_0004#;
+ Event_3 : constant RTEMS.Event_Set := 16#0000_0008#;
+ Event_4 : constant RTEMS.Event_Set := 16#0000_0010#;
+ Event_5 : constant RTEMS.Event_Set := 16#0000_0020#;
+ Event_6 : constant RTEMS.Event_Set := 16#0000_0040#;
+ Event_7 : constant RTEMS.Event_Set := 16#0000_0080#;
+ Event_8 : constant RTEMS.Event_Set := 16#0000_0100#;
+ Event_9 : constant RTEMS.Event_Set := 16#0000_0200#;
+ Event_10 : constant RTEMS.Event_Set := 16#0000_0400#;
+ Event_11 : constant RTEMS.Event_Set := 16#0000_0800#;
+ Event_12 : constant RTEMS.Event_Set := 16#0000_1000#;
+ Event_13 : constant RTEMS.Event_Set := 16#0000_2000#;
+ Event_14 : constant RTEMS.Event_Set := 16#0000_4000#;
+ Event_15 : constant RTEMS.Event_Set := 16#0000_8000#;
+ Event_16 : constant RTEMS.Event_Set := 16#0001_0000#;
+ Event_17 : constant RTEMS.Event_Set := 16#0002_0000#;
+ Event_18 : constant RTEMS.Event_Set := 16#0004_0000#;
+ Event_19 : constant RTEMS.Event_Set := 16#0008_0000#;
+ Event_20 : constant RTEMS.Event_Set := 16#0010_0000#;
+ Event_21 : constant RTEMS.Event_Set := 16#0020_0000#;
+ Event_22 : constant RTEMS.Event_Set := 16#0040_0000#;
+ Event_23 : constant RTEMS.Event_Set := 16#0080_0000#;
+ Event_24 : constant RTEMS.Event_Set := 16#0100_0000#;
+ Event_25 : constant RTEMS.Event_Set := 16#0200_0000#;
+ Event_26 : constant RTEMS.Event_Set := 16#0400_0000#;
+ Event_27 : constant RTEMS.Event_Set := 16#0800_0000#;
+ Event_28 : constant RTEMS.Event_Set := 16#1000_0000#;
+ Event_29 : constant RTEMS.Event_Set := 16#2000_0000#;
+ Event_30 : constant RTEMS.Event_Set := 16#4000_0000#;
+ Event_31 : constant RTEMS.Event_Set := 16#8000_0000#;
+
+ --
+ -- RTEMS Signals
+ --
+
+ All_Signals : constant RTEMS.Signal_Set := 16#7FFFFFFF#;
+ Signal_0 : constant RTEMS.Signal_Set := 16#00000001#;
+ Signal_1 : constant RTEMS.Signal_Set := 16#00000002#;
+ Signal_2 : constant RTEMS.Signal_Set := 16#00000004#;
+ Signal_3 : constant RTEMS.Signal_Set := 16#00000008#;
+ Signal_4 : constant RTEMS.Signal_Set := 16#00000010#;
+ Signal_5 : constant RTEMS.Signal_Set := 16#00000020#;
+ Signal_6 : constant RTEMS.Signal_Set := 16#00000040#;
+ Signal_7 : constant RTEMS.Signal_Set := 16#00000080#;
+ Signal_8 : constant RTEMS.Signal_Set := 16#00000100#;
+ Signal_9 : constant RTEMS.Signal_Set := 16#00000200#;
+ Signal_10 : constant RTEMS.Signal_Set := 16#00000400#;
+ Signal_11 : constant RTEMS.Signal_Set := 16#00000800#;
+ Signal_12 : constant RTEMS.Signal_Set := 16#00001000#;
+ Signal_13 : constant RTEMS.Signal_Set := 16#00002000#;
+ Signal_14 : constant RTEMS.Signal_Set := 16#00004000#;
+ Signal_15 : constant RTEMS.Signal_Set := 16#00008000#;
+ Signal_16 : constant RTEMS.Signal_Set := 16#00010000#;
+ Signal_17 : constant RTEMS.Signal_Set := 16#00020000#;
+ Signal_18 : constant RTEMS.Signal_Set := 16#00040000#;
+ Signal_19 : constant RTEMS.Signal_Set := 16#00080000#;
+ Signal_20 : constant RTEMS.Signal_Set := 16#00100000#;
+ Signal_21 : constant RTEMS.Signal_Set := 16#00200000#;
+ Signal_22 : constant RTEMS.Signal_Set := 16#00400000#;
+ Signal_23 : constant RTEMS.Signal_Set := 16#00800000#;
+ Signal_24 : constant RTEMS.Signal_Set := 16#01000000#;
+ Signal_25 : constant RTEMS.Signal_Set := 16#02000000#;
+ Signal_26 : constant RTEMS.Signal_Set := 16#04000000#;
+ Signal_27 : constant RTEMS.Signal_Set := 16#08000000#;
+ Signal_28 : constant RTEMS.Signal_Set := 16#10000000#;
+ Signal_29 : constant RTEMS.Signal_Set := 16#20000000#;
+ Signal_30 : constant RTEMS.Signal_Set := 16#40000000#;
+ Signal_31 : constant RTEMS.Signal_Set := 16#80000000#;
+
+ --
+ -- RTEMS API Configuration Information
+ --
+
+ type Initialization_Tasks_Table_Entry is
+ record
+ Name : RTEMS.Name; -- task name
+ Stack_Size : RTEMS.Unsigned32; -- task stack size
+ Initial_Priority : RTEMS.Task_priority; -- task priority
+ Attribute_Set : RTEMS.Attribute; -- task attributes
+ Entry_Point : RTEMS.Task_Entry; -- task entry point
+ Mode_Set : RTEMS.Mode; -- task initial mode
+ Argument : RTEMS.Unsigned32; -- task argument
+ end record;
+
+ type Initialization_Tasks_Table is array ( RTEMS.Unsigned32 range <> ) of
+ RTEMS.Initialization_Tasks_Table_Entry;
+
+ type Initialization_Tasks_Table_Pointer is access all
+ Initialization_Tasks_Table;
+
+ type API_Configuration_Table is
+ record
+ Maximum_Tasks : RTEMS.Unsigned32;
+ Maximum_Timers : RTEMS.Unsigned32;
+ Maximum_Semaphores : RTEMS.Unsigned32;
+ Maximum_Message_queues : RTEMS.Unsigned32;
+ Maximum_Partitions : RTEMS.Unsigned32;
+ Maximum_Regions : RTEMS.Unsigned32;
+ Maximum_Ports : RTEMS.Unsigned32;
+ Maximum_Periods : RTEMS.Unsigned32;
+ Number_Of_Initialization_Tasks : RTEMS.Unsigned32;
+ User_Initialization_Tasks_Table :
+ RTEMS.Initialization_Tasks_Table_Pointer;
+ end record;
+
+ type API_Configuration_Table_Pointer is access all API_Configuration_Table;
+
+ --
+ -- RTEMS POSIX API Configuration Information
+ --
+
+ type POSIX_Thread_Entry is access procedure (
+ Argument : in RTEMS.Address
+ );
+
+ type POSIX_Initialization_Threads_Table_Entry is
+ record
+ Thread_Entry : RTEMS.POSIX_Thread_Entry;
+ end record;
+
+ type POSIX_Initialization_Threads_Table is array
+ ( RTEMS.Unsigned32 range <> ) of
+ RTEMS.POSIX_Initialization_Threads_Table_Entry;
+
+ type POSIX_Initialization_Threads_Table_Pointer is access all
+ POSIX_Initialization_Threads_Table;
+
+ type POSIX_API_Configuration_Table_Entry is
+ record
+ Maximum_Threads : Interfaces.C.Int;
+ Maximum_Mutexes : Interfaces.C.Int;
+ Maximum_Condition_Variables : Interfaces.C.Int;
+ Maximum_Keys : Interfaces.C.Int;
+ Maximum_Queued_Signals : Interfaces.C.Int;
+ Number_Of_Initialization_Tasks : Interfaces.C.Int;
+ User_Initialization_Tasks_Table :
+ RTEMS.POSIX_Initialization_Threads_Table_Pointer;
+ end record;
+
+ type POSIX_API_Configuration_Table is array ( RTEMS.Unsigned32 range <> ) of
+ RTEMS.POSIX_API_Configuration_Table_Entry;
+
+ type POSIX_API_Configuration_Table_Pointer is access all
+ RTEMS.POSIX_API_Configuration_Table;
+
+ --
+ -- MPCI Information include MPCI Configuration
+ --
+
+ type Configuration_Table_Pointer;
+
+ type MP_Packet_Classes is (
+ MP_PACKET_MPCI_INTERNAL,
+ MP_PACKET_TASKS,
+ MP_PACKET_MESSAGE_QUEUE,
+ MP_PACKET_SEMAPHORE,
+ MP_PACKET_PARTITION,
+ MP_PACKET_REGION,
+ MP_PACKET_EVENT,
+ MP_PACKET_SIGNAL
+ );
+
+ for MP_Packet_Classes use (
+ MP_PACKET_MPCI_INTERNAL => 0,
+ MP_PACKET_TASKS => 1,
+ MP_PACKET_MESSAGE_QUEUE => 2,
+ MP_PACKET_SEMAPHORE => 3,
+ MP_PACKET_PARTITION => 4,
+ MP_PACKET_REGION => 5,
+ MP_PACKET_EVENT => 6,
+ MP_PACKET_SIGNAL => 7
+ );
+
+ type Packet_Prefix is
+ record
+ The_Class : RTEMS.MP_Packet_Classes;
+ ID : RTEMS.ID;
+ Source_TID : RTEMS.ID;
+ Source_Priority : RTEMS.Task_Priority;
+ Return_Code : RTEMS.Unsigned32;
+ Length : RTEMS.Unsigned32;
+ To_Convert : RTEMS.Unsigned32;
+ Timeout : RTEMS.Interval;
+ end record;
+
+ type Packet_Prefix_Pointer is access all Packet_Prefix;
+
+ type MPCI_Initialization_Entry is access procedure (
+ Configuration : in RTEMS.Configuration_Table_Pointer
+ );
+
+ type MPCI_Get_Packet_Entry is access procedure (
+ Packet : access RTEMS.Packet_Prefix_Pointer
+ );
+
+ type MPCI_Return_Packet_Entry is access procedure (
+ Packet : in RTEMS.Packet_Prefix_Pointer
+ );
+
+ type MPCI_Send_Entry is access procedure (
+ Packet : in RTEMS.Packet_Prefix_Pointer
+ );
+
+ type MPCI_Receive_Entry is access procedure (
+ Packet : access RTEMS.Packet_Prefix_Pointer
+ );
+
+ type MPCI_Table is
+ record
+ Default_Timeout : RTEMS.Unsigned32; -- in ticks
+ Maximum_Packet_Size : RTEMS.Unsigned32;
+ Initialization : RTEMS.MPCI_Initialization_Entry;
+ Get_Packet : RTEMS.MPCI_Get_Packet_Entry;
+ Return_Packet : RTEMS.MPCI_Return_Packet_Entry;
+ Send : RTEMS.MPCI_Send_Entry;
+ Receive : RTEMS.MPCI_Receive_Entry;
+ end record;
+
+ type MPCI_Table_Pointer is access all MPCI_Table;
+
+ --
+ -- Configuration Information
+ --
+
+ type Multiprocessing_Table is
+ record
+ Node : RTEMS.Unsigned32;
+ Maximum_Nodes : RTEMS.Unsigned32;
+ Maximum_Global_Objects : RTEMS.Unsigned32;
+ Maximum_Proxies : RTEMS.Unsigned32;
+ User_MPCI_Table : RTEMS.MPCI_Table_Pointer;
+ end record;
+
+ type Multiprocessing_Table_Pointer is access all Multiprocessing_Table;
+
+ type Configuration_Table is
+ record
+ Work_Space_Start : RTEMS.Address;
+ Work_Space_Size : RTEMS.Unsigned32;
+ Maximum_Extensions : RTEMS.Unsigned32;
+ Microseconds_Per_Tick : RTEMS.Unsigned32;
+ Ticks_Per_Timeslice : RTEMS.Unsigned32;
+ Maximum_Devices : RTEMS.Unsigned32;
+ Maximum_Drivers : RTEMS.Unsigned32;
+ Number_Of_Device_Drivers : RTEMS.Unsigned32;
+ Device_Driver_Table : RTEMS.Driver_Address_Table_Pointer;
+ Number_Of_Initial_Extensions : RTEMS.Unsigned32;
+ User_Extension_Table : RTEMS.Extensions_Table_Pointer;
+ User_Multiprocessing_Table : RTEMS.Multiprocessing_Table_Pointer;
+
+ RTEMS_API_Configuration : RTEMS.API_Configuration_Table_Pointer;
+ POSIX_API_Configuration : RTEMS.POSIX_API_Configuration_Table_Pointer;
+ ITRON_API_Configuration : RTEMS.Address; -- XXX FIX ME
+ end record;
+
+ type Configuration_Table_Pointer is access all Configuration_Table;
+
+ --
+ -- For now, do not provide access to the CPU Table from Ada.
+ -- When this type is provided, a CPU dependent file must
+ -- define it.
+ --
+
+ subtype CPU_Table is RTEMS.Address;
+ type CPU_Table_Pointer is access all CPU_Table;
+
+ --
+ -- Utility Functions
+ --
+
+ function From_Ada_Boolean (
+ Ada_Boolean : Standard.Boolean
+ ) return RTEMS.Boolean;
+
+ function To_Ada_Boolean (
+ RTEMS_Boolean : RTEMS.Boolean
+ ) return Standard.Boolean;
+
+ function Milliseconds_To_Microseconds (
+ Milliseconds : RTEMS.Unsigned32
+ ) return RTEMS.Unsigned32;
+
+ function Microseconds_To_Ticks (
+ Microseconds : RTEMS.Unsigned32
+ ) return RTEMS.Interval;
+
+ function Milliseconds_To_Ticks (
+ Milliseconds : RTEMS.Unsigned32
+ ) return RTEMS.Interval;
+
+ function Build_Name (
+ C1 : in Character;
+ C2 : in Character;
+ C3 : in Character;
+ C4 : in Character
+ ) return RTEMS.Name;
+
+ procedure Name_To_Characters (
+ Name : in RTEMS.Name;
+ C1 : out Character;
+ C2 : out Character;
+ C3 : out Character;
+ C4 : out Character
+ );
+
+ function Get_Node (
+ ID : in RTEMS.ID
+ ) return RTEMS.Unsigned32;
+
+ function Get_Index (
+ ID : in RTEMS.ID
+ ) return RTEMS.Unsigned32;
+
+ function Are_Statuses_Equal (
+ Status : in RTEMS.Status_Codes;
+ Desired : in RTEMS.Status_Codes
+ ) return Standard.Boolean;
+
+ function Is_Status_Successful (
+ Status : in RTEMS.Status_Codes
+ ) return Standard.Boolean;
+
+ function Subtract (
+ Left : in RTEMS.Address;
+ Right : in RTEMS.Address
+ ) return RTEMS.Unsigned32;
+
+ function Are_Equal (
+ Left : in RTEMS.Address;
+ Right : in RTEMS.Address
+ ) return Standard.Boolean;
+ --
+ -- RTEMS API
+ --
+
+ --
+ -- Initialization Manager
+ --
+
+ procedure Initialize_Executive (
+ Configuration_Table : in RTEMS.Configuration_Table_Pointer;
+ CPU_Table : in RTEMS.CPU_Table_Pointer
+ );
+
+ procedure Initialize_Executive_Early (
+ Configuration_Table : in RTEMS.Configuration_Table_Pointer;
+ CPU_Table : in RTEMS.CPU_Table_Pointer;
+ Level : out RTEMS.ISR_Level
+ );
+
+ procedure Initialize_Executive_Late (
+ BSP_Level : in RTEMS.ISR_Level
+ );
+
+ procedure Shutdown_Executive (
+ Result : in RTEMS.Unsigned32
+ );
+
+ --
+ -- Task Manager
+ --
+
+ procedure Task_Create (
+ Name : in RTEMS.Name;
+ Initial_Priority : in RTEMS.Task_Priority;
+ Stack_Size : in Unsigned32;
+ Initial_Modes : in RTEMS.Mode;
+ Attribute_Set : in RTEMS.Attribute;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Task_Ident (
+ Name : in RTEMS.Name;
+ Node : in RTEMS.Node;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Task_Start (
+ ID : in RTEMS.ID;
+ Entry_Point : in RTEMS.Task_Entry;
+ Argument : in RTEMS.Task_Argument;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Task_Restart (
+ ID : in RTEMS.ID;
+ Argument : in RTEMS.Task_Argument;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Task_Delete (
+ ID : in RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Task_Suspend (
+ ID : in RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Task_Resume (
+ ID : in RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Task_Set_Priority (
+ ID : in RTEMS.ID;
+ New_Priority : in RTEMS.Task_Priority;
+ Old_Priority : out RTEMS.Task_Priority;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Task_Mode (
+ Mode_Set : in RTEMS.Mode;
+ Mask : in RTEMS.Mode;
+ Previous_Mode_Set : out RTEMS.Mode;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Task_Get_Note (
+ ID : in RTEMS.ID;
+ Notepad : in RTEMS.Notepad_Index;
+ Note : out RTEMS.Unsigned32;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Task_Set_Note (
+ ID : in RTEMS.ID;
+ Notepad : in RTEMS.Notepad_Index;
+ Note : in RTEMS.Unsigned32;
+ Result : out RTEMS.Status_Codes
+ );
+
+ type Task_Variable_Dtor is access procedure (
+ Argument : in RTEMS.Address;
+ );
+
+ procedure Task_Variable_Add (
+ ID : in RTEMS.ID;
+ Task_Variable : in RTEMS.Address;
+ Dtor : in RTEMS.Task_Variable_Dtor;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Task_Variable_Get (
+ ID : in RTEMS.ID;
+ Task_Variable : out RTEMS.Address;
+ Task_Variable_Value : out RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Task_Variable_Delete (
+ ID : in RTEMS.ID;
+ Task_Variable : out RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Task_Wake_When (
+ Time_Buffer : in RTEMS.Time_Of_Day;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Task_Wake_After (
+ Ticks : in RTEMS.Interval;
+ Result : out RTEMS.Status_Codes
+ );
+
+ --
+ -- Interrupt Manager
+ --
+
+ procedure Interrupt_Catch (
+ New_ISR_Handler : in RTEMS.Address;
+ Vector : in RTEMS.Vector_Number;
+ Old_ISR_Handler : out RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ );
+
+ function Interrupt_Disable return RTEMS.ISR_Level;
+ pragma Interface (C, Interrupt_Disable);
+ pragma Interface_Name (Interrupt_Disable, "rtems_interrupt_disable");
+
+ procedure Interrupt_Enable (
+ Level : in RTEMS.ISR_Level
+ );
+ pragma Interface (C, Interrupt_Enable);
+ pragma Interface_Name (Interrupt_Enable, "rtems_interrupt_enable");
+
+ procedure Interrupt_Flash (
+ Level : in RTEMS.ISR_Level
+ );
+ pragma Interface (C, Interrupt_Flash);
+ pragma Interface_Name (Interrupt_Flash, "rtems_interrupt_flash");
+
+ function Interrupt_Is_In_Progress return RTEMS.Boolean;
+ pragma Interface (C, Interrupt_Is_In_Progress);
+ pragma Interface_Name
+ (Interrupt_Is_In_Progress, "rtems_interrupt_is_in_progress");
+
+ --
+ -- Clock Manager
+ --
+
+ procedure Clock_Get (
+ Option : in RTEMS.Clock_Get_Options;
+ Time_Buffer : in RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Clock_Set (
+ Time_Buffer : in RTEMS.Time_Of_Day;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Clock_Tick (
+ Result : out RTEMS.Status_Codes
+ );
+
+ --
+ -- Extension Manager
+ --
+
+ procedure Extension_Create (
+ Name : in RTEMS.Name;
+ Table : in RTEMS.Extensions_Table_Pointer;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Extension_Ident (
+ Name : in RTEMS.Name;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Extension_Delete (
+ ID : in RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ );
+
+
+ --
+ -- Timer Manager
+ --
+
+ procedure Timer_Create (
+ Name : in RTEMS.Name;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Timer_Ident (
+ Name : in RTEMS.Name;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Timer_Delete (
+ ID : in RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Timer_Fire_After (
+ ID : in RTEMS.ID;
+ Ticks : in RTEMS.Interval;
+ Routine : in RTEMS.Timer_Service_Routine;
+ User_Data : in RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Timer_Server_Fire_After (
+ ID : in RTEMS.ID;
+ Ticks : in RTEMS.Interval;
+ Routine : in RTEMS.Timer_Service_Routine;
+ User_Data : in RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Timer_Fire_When (
+ ID : in RTEMS.ID;
+ Wall_Time : in RTEMS.Time_Of_Day;
+ Routine : in RTEMS.Timer_Service_Routine;
+ User_Data : in RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Timer_Server_Fire_When (
+ ID : in RTEMS.ID;
+ Wall_Time : in RTEMS.Time_Of_Day;
+ Routine : in RTEMS.Timer_Service_Routine;
+ User_Data : in RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Timer_Reset (
+ ID : in RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Timer_Cancel (
+ ID : in RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Timer_Initiate_Server (
+ Server_Priority : in RTEMS.Task_Priority;
+ Stack_Size : in Unsigned32;
+ Attribute_Set : in RTEMS.Attribute;
+ Result : out RTEMS.Status_Codes
+ );
+
+ --
+ -- Semaphore Manager
+ --
+
+ procedure Semaphore_Create (
+ Name : in RTEMS.Name;
+ Count : in RTEMS.Unsigned32;
+ Attribute_Set : in RTEMS.Attribute;
+ Priority_Ceiling : in RTEMS.Task_Priority;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Semaphore_Delete (
+ ID : in RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Semaphore_Ident (
+ Name : in RTEMS.Name;
+ Node : in RTEMS.Unsigned32;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Semaphore_Obtain (
+ ID : in RTEMS.ID;
+ Option_Set : in RTEMS.Option;
+ Timeout : in RTEMS.Interval;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Semaphore_Release (
+ ID : in RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ );
+
+
+ --
+ -- Message Queue Manager
+ --
+
+ procedure Message_Queue_Create (
+ Name : in RTEMS.Name;
+ Count : in RTEMS.Unsigned32;
+ Max_Message_Size : in RTEMS.Unsigned32;
+ Attribute_Set : in RTEMS.Attribute;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Message_Queue_Ident (
+ Name : in RTEMS.Name;
+ Node : in RTEMS.Unsigned32;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Message_Queue_Delete (
+ ID : in RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Message_Queue_Send (
+ ID : in RTEMS.ID;
+ Buffer : in RTEMS.Address;
+ Size : in RTEMS.Unsigned32;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Message_Queue_Urgent (
+ ID : in RTEMS.ID;
+ Buffer : in RTEMS.Address;
+ Size : in RTEMS.Unsigned32;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Message_Queue_Broadcast (
+ ID : in RTEMS.ID;
+ Buffer : in RTEMS.Address;
+ Size : in RTEMS.Unsigned32;
+ Count : out RTEMS.Unsigned32;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Message_Queue_Receive (
+ ID : in RTEMS.ID;
+ Buffer : in RTEMS.Address;
+ Option_Set : in RTEMS.Option;
+ Timeout : in RTEMS.Interval;
+ Size : out RTEMS.Unsigned32;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Message_Queue_Flush (
+ ID : in RTEMS.ID;
+ Count : out RTEMS.Unsigned32;
+ Result : out RTEMS.Status_Codes
+ );
+
+
+ --
+ -- Event Manager
+ --
+
+ procedure Event_Send (
+ ID : in RTEMS.ID;
+ Event_In : in RTEMS.Event_Set;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Event_Receive (
+ Event_In : in RTEMS.Event_Set;
+ Option_Set : in RTEMS.Option;
+ Ticks : in RTEMS.Interval;
+ Event_Out : out RTEMS.Event_Set;
+ Result : out RTEMS.Status_Codes
+ );
+
+ --
+ -- Signal Manager
+ --
+
+ procedure Signal_Catch (
+ ASR_Handler : in RTEMS.ASR_Handler;
+ Mode_Set : in RTEMS.Mode;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Signal_Send (
+ ID : in RTEMS.ID;
+ Signal_Set : in RTEMS.Signal_Set;
+ Result : out RTEMS.Status_Codes
+ );
+
+
+ --
+ -- Partition Manager
+ --
+
+ procedure Partition_Create (
+ Name : in RTEMS.Name;
+ Starting_Address : in RTEMS.Address;
+ Length : in RTEMS.Unsigned32;
+ Buffer_Size : in RTEMS.Unsigned32;
+ Attribute_Set : in RTEMS.Attribute;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Partition_Ident (
+ Name : in RTEMS.Name;
+ Node : in RTEMS.Unsigned32;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Partition_Delete (
+ ID : in RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Partition_Get_Buffer (
+ ID : in RTEMS.ID;
+ Buffer : out RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Partition_Return_Buffer (
+ ID : in RTEMS.ID;
+ Buffer : in RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ );
+
+
+ --
+ -- Region Manager
+ --
+
+ procedure Region_Create (
+ Name : in RTEMS.Name;
+ Starting_Address : in RTEMS.Address;
+ Length : in RTEMS.Unsigned32;
+ Page_Size : in RTEMS.Unsigned32;
+ Attribute_Set : in RTEMS.Attribute;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Region_Ident (
+ Name : in RTEMS.Name;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Region_Delete (
+ ID : in RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Region_Extend (
+ ID : in RTEMS.ID;
+ Starting_Address : in RTEMS.Address;
+ Length : in RTEMS.Unsigned32;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Region_Get_Segment (
+ ID : in RTEMS.ID;
+ Size : in RTEMS.Unsigned32;
+ Option_Set : in RTEMS.Option;
+ Timeout : in RTEMS.Interval;
+ Segment : out RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Region_Get_Segment_Size (
+ ID : in RTEMS.ID;
+ Segment : in RTEMS.Address;
+ Size : out RTEMS.Unsigned32;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Region_Return_Segment (
+ ID : in RTEMS.ID;
+ Segment : in RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ );
+
+
+ --
+ -- Dual Ported Memory Manager
+ --
+
+ procedure Port_Create (
+ Name : in RTEMS.Name;
+ Internal_Start : in RTEMS.Address;
+ External_Start : in RTEMS.Address;
+ Length : in RTEMS.Unsigned32;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Port_Ident (
+ Name : in RTEMS.Name;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Port_Delete (
+ ID : in RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Port_External_To_Internal (
+ ID : in RTEMS.ID;
+ External : in RTEMS.Address;
+ Internal : out RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Port_Internal_To_External (
+ ID : in RTEMS.ID;
+ Internal : in RTEMS.Address;
+ External : out RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ );
+
+ --
+ -- Input/Output Manager
+ --
+
+ procedure IO_Initialize (
+ Major : in RTEMS.Device_Major_Number;
+ Minor : in RTEMS.Device_Minor_Number;
+ Argument : in RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure IO_Register_Name (
+ Name : in String;
+ Major : in RTEMS.Device_Major_Number;
+ Minor : in RTEMS.Device_Minor_Number;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure IO_Lookup_Name (
+ Name : in String;
+ Device_Info : In RTEMS.Driver_Name_t_Pointer;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure IO_Open (
+ Major : in RTEMS.Device_Major_Number;
+ Minor : in RTEMS.Device_Minor_Number;
+ Argument : in RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure IO_Close (
+ Major : in RTEMS.Device_Major_Number;
+ Minor : in RTEMS.Device_Minor_Number;
+ Argument : in RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure IO_Read (
+ Major : in RTEMS.Device_Major_Number;
+ Minor : in RTEMS.Device_Minor_Number;
+ Argument : in RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure IO_Write (
+ Major : in RTEMS.Device_Major_Number;
+ Minor : in RTEMS.Device_Minor_Number;
+ Argument : in RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure IO_Control (
+ Major : in RTEMS.Device_Major_Number;
+ Minor : in RTEMS.Device_Minor_Number;
+ Argument : in RTEMS.Address;
+ Result : out RTEMS.Status_Codes
+ );
+
+
+ --
+ -- Fatal Error Manager
+ --
+
+ procedure Fatal_Error_Occurred (
+ The_Error : in RTEMS.Unsigned32
+ );
+
+
+ --
+ -- Rate Monotonic Manager
+ --
+
+ procedure Rate_Monotonic_Create (
+ Name : in RTEMS.Name;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Rate_Monotonic_Ident (
+ Name : in RTEMS.Name;
+ ID : out RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Rate_Monotonic_Delete (
+ ID : in RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Rate_Monotonic_Cancel (
+ ID : in RTEMS.ID;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Rate_Monotonic_Period (
+ ID : in RTEMS.ID;
+ Length : in RTEMS.Interval;
+ Result : out RTEMS.Status_Codes
+ );
+
+ procedure Rate_Monotonic_Get_Status (
+ ID : in RTEMS.ID;
+ Status : out RTEMS.Rate_Monotonic_Period_Status;
+ Result : out RTEMS.Status_Codes
+ );
+
+
+ --
+ -- Debug Manager
+ --
+
+ Debug_All_Mask : constant RTEMS.Debug_Set := 16#ffffffff#;
+ Debug_Region : constant RTEMS.Debug_Set := 16#00000001#;
+
+ procedure Debug_Enable (
+ To_Be_Enabled : in RTEMS.Debug_Set
+ );
+
+ procedure Debug_Disable (
+ To_Be_Disabled : in RTEMS.Debug_Set
+ );
+
+ function Debug_Is_Enabled (
+ Level : in RTEMS.Debug_Set
+ ) return RTEMS.Boolean;
+
+ --
+ -- Some Useful Data Items
+ --
+
+ Configuration : RTEMS.Configuration_Table_Pointer;
+ pragma Import (C, Configuration, "_Configuration_Table");
+
+end RTEMS;
diff --git a/cpukit/automake/compile.am b/cpukit/automake/compile.am
new file mode 100644
index 0000000000..3a0dc79534
--- /dev/null
+++ b/cpukit/automake/compile.am
@@ -0,0 +1,80 @@
+##
+## $Id$
+##
+
+## -------------------------------------------------------------------------
+## NOTE: This file is rather immature and has to be considered to be
+## almost experimental.
+##
+## Expect frequent changes -- It deserves to be cleaned up :(
+## -------------------------------------------------------------------------
+
+## The section below is based on make/compilers/gcc-target-default.cfg
+## used in former versions of RTEMS.
+
+##
+## Set up the flags for the toolchains:
+##
+## We are considering 3 different building schemes here:
+## * Using gcc's being able to accept -specs (aka gcc-2.8 building scheme)
+## * Using gcc's not being able to accept -specs (aka gcc-2.7.2 building
+## scheme)
+## * Using third party toolchains (aka non-gcc building scheme)
+##
+## Automake conditionals in use:
+## RTEMS_USE_GCC .. if we are using GCC
+
+## CFLAGS_OPTIMIZE_V, CFLAGS_DEBUG_V are the values we
+## would want the corresponding macros to be set to.
+##
+## CFLAGS_OPTIMIZE, CFLAGS_DEBUG are set by the
+## 'VARIANT=<OPTIMIZE|DEBUG>' targets to their _V values.
+
+CPPFLAGS = @CPPFLAGS@ $(CPU_DEFINES) $(DEFINES)
+CFLAGS = @RTEMS_CFLAGS@
+ASFLAGS = $(CPU_ASFLAGS) $(CPU_CFLAGS)
+
+depend:
+
+## -------------------------------------------------------------------------
+
+## translate VARIANT into VARIANT_V
+VARIANT = OPTIMIZE
+
+VARIANT_OPTIMIZE_V = OPTIMIZE
+VARIANT_DEBUG_V = DEBUG
+VARIANT_optimize_V = OPTIMIZE
+VARIANT_debug_V = DEBUG
+
+VARIANT_V = $(VARIANT_$(VARIANT)_V)
+
+## Setup the library suffix
+LIBSUFFIX_OPTIMIZE_V =
+LIBSUFFIX_DEBUG_V = _g
+LIBSUFFIX__V = $(LIBSUFFIX_OPTIMIZE_V)
+
+LIB_VARIANT = $(LIBSUFFIX_$(VARIANT_V)_V)
+
+## These are supposed to be set in make/custom/<bsp>.cfg
+CPU_CFLAGS = @CPU_CFLAGS@
+CFLAGS_OPTIMIZE_V = @CFLAGS_OPTIMIZE_V@
+CFLAGS_DEBUG_V = @CFLAGS_DEBUG_V@
+CFLAGS__V = $(CFLAGS_OPTIMIZE_V)
+
+## ------------------------------------------------------------------------
+## Setup hard-coded flags
+if RTEMS_USE_GCC
+## gcc >= gcc-2.8
+RTEMS_CFLAGS_OPTIMIZE_V =
+RTEMS_CFLAGS_DEBUG_V = -Wno-unused
+
+## non-gcc
+## We can't guess what flags might be required here.
+## Pass the values from the environment if you want to apply them.
+endif
+RTEMS_CFLAGS__V = $(RTEMS_CFLAGS_OPTIMIZE_V)
+
+## -------------------------------------------------------------------------
+AM_CPPFLAGS = $(RTEMS_CPPFLAGS)
+AM_CFLAGS =
+AM_CCASFLAGS = $(RTEMS_CPPFLAGS) $(RTEMS_ASFLAGS)
diff --git a/cpukit/automake/local.am b/cpukit/automake/local.am
new file mode 100644
index 0000000000..9e8c9e804e
--- /dev/null
+++ b/cpukit/automake/local.am
@@ -0,0 +1,8 @@
+## $Id$
+
+preinstall-am: $(PREINSTALL_FILES)
+preinstall: preinstall-am
+.PHONY: preinstall preinstall-am
+
+depend:
+.PHONY: depend
diff --git a/cpukit/automake/multilib.am b/cpukit/automake/multilib.am
new file mode 100644
index 0000000000..9f2024f8d9
--- /dev/null
+++ b/cpukit/automake/multilib.am
@@ -0,0 +1,36 @@
+## $Id$
+
+if MULTILIB
+MULTISRCTOP =
+MULTIDIRS =
+MULTIDO = true
+MULTICLEAN = true
+endif
+
+# Multilib support rules
+.PHONY: all-multi install-multi mostlyclean-multi clean-multi distclean-multi \
+ maintainer-clean-multi
+
+if MULTILIB
+all-recursive: all-multi
+install-recursive: install-multi
+
+mostlyclean-recursive: mostlyclean-multi
+clean-recursive: clean-multi
+distclean-recursive: distclean-multi
+maintainer-clean-recursive: maintainer-clean-multi
+
+all-multi:
+ $(MULTIDO) $(AM_MAKEFLAGS) DO=all multi-do
+install-multi:
+ $(MULTIDO) $(AM_MAKEFLAGS) DO=install multi-do
+
+mostlyclean-multi:
+ $(MULTICLEAN) $(AM_MAKEFLAGS) DO=mostlyclean multi-clean
+clean-multi:
+ $(MULTICLEAN) $(AM_MAKEFLAGS) DO=clean multi-clean
+distclean-multi:
+ $(MULTICLEAN) $(AM_MAKEFLAGS) DO=distclean multi-clean
+maintainer-clean-multi:
+ $(MULTICLEAN) $(AM_MAKEFLAGS) DO=maintainer-clean multi-clean
+endif
diff --git a/cpukit/automake/subdirs.am b/cpukit/automake/subdirs.am
new file mode 100644
index 0000000000..00eba7cd1d
--- /dev/null
+++ b/cpukit/automake/subdirs.am
@@ -0,0 +1,32 @@
+## $Id$
+
+## Borrowed from automake-1.4 and adapted to RTEMS
+
+## NOTE: This is a temporary work-around to keep
+## RTEMS's non automake standard make targets working.
+## Once automake is fully integrated these make targets
+## and this file will probably be removed
+
+preinstall-recursive:
+ @set fnord $(MAKEFLAGS); amf=$$2; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+## This trick allows "-k" to keep its natural meaning when running a
+## recursive rule.
+ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+preinstall: preinstall-recursive
+.PHONY: preinstall-recursive
diff --git a/cpukit/backward/asm.h b/cpukit/backward/asm.h
new file mode 100644
index 0000000000..8c34f7f514
--- /dev/null
+++ b/cpukit/backward/asm.h
@@ -0,0 +1,7 @@
+#ifndef __asm_h
+#define __asm_h
+#ifndef RTEMS_NO_WARN_DEPRECATED
+#warning <asm.h> is deprecated, use <rtems/asm.h> instead
+#endif
+#include <rtems/asm.h>
+#endif
diff --git a/cpukit/backward/chain.h b/cpukit/backward/chain.h
new file mode 100644
index 0000000000..b3c6d371bb
--- /dev/null
+++ b/cpukit/backward/chain.h
@@ -0,0 +1,7 @@
+#ifndef __chain_h
+#define __chain_h
+#ifndef RTEMS_NO_WARN_DEPRECATED
+#warning <chain.h> is deprecated, use <rtems/chain.h> instead
+#endif
+#include <rtems/chain.h>
+#endif
diff --git a/cpukit/backward/clockdrv.h b/cpukit/backward/clockdrv.h
new file mode 100644
index 0000000000..5c2e767d06
--- /dev/null
+++ b/cpukit/backward/clockdrv.h
@@ -0,0 +1,7 @@
+#ifndef __clockdrv_h
+#define __clockdrv_h
+#ifndef RTEMS_NO_WARN_DEPRECATED
+#warning <clockdrv.h> is deprecated, use <rtems/clockdrv.h> instead
+#endif
+#include <rtems/clockdrv.h>
+#endif
diff --git a/cpukit/backward/confdefs.h b/cpukit/backward/confdefs.h
new file mode 100644
index 0000000000..85bc2d6175
--- /dev/null
+++ b/cpukit/backward/confdefs.h
@@ -0,0 +1,7 @@
+#ifndef __confdefs_h
+#define __confdefs_h
+#ifndef RTEMS_NO_WARN_DEPRECATED
+#warning <confdefs.h> is deprecated, use <rtems/confdefs.h> instead
+#endif
+#include <rtems/confdefs.h>
+#endif
diff --git a/cpukit/backward/console.h b/cpukit/backward/console.h
new file mode 100644
index 0000000000..e90f94a0b0
--- /dev/null
+++ b/cpukit/backward/console.h
@@ -0,0 +1,7 @@
+#ifndef __console_h
+#define __console_h
+#ifndef RTEMS_NO_WARN_DEPRECATED
+#warning <console.h> is deprecated, use <rtems/console.h> instead
+#endif
+#include <rtems/console.h>
+#endif
diff --git a/cpukit/backward/dosfs.h b/cpukit/backward/dosfs.h
new file mode 100644
index 0000000000..596247f2be
--- /dev/null
+++ b/cpukit/backward/dosfs.h
@@ -0,0 +1,7 @@
+#ifndef __dosfs_h
+#define __dosfs_h
+#ifndef RTEMS_NO_WARN_DEPRECATED
+#warning <dosfs.h> is deprecated, use <rtems/dosfs.h> instead
+#endif
+#include <rtems/dosfs.h>
+#endif
diff --git a/cpukit/backward/imfs.h b/cpukit/backward/imfs.h
new file mode 100644
index 0000000000..5acf3802f8
--- /dev/null
+++ b/cpukit/backward/imfs.h
@@ -0,0 +1,7 @@
+#ifndef __imfs_h
+#define __imfs_h
+#ifndef RTEMS_NO_WARN_DEPRECATED
+#warning <imfs.h> is deprecated, use <rtems/imfs.h> instead
+#endif
+#include <rtems/imfs.h>
+#endif
diff --git a/cpukit/backward/iosupp.h b/cpukit/backward/iosupp.h
new file mode 100644
index 0000000000..52b5249d63
--- /dev/null
+++ b/cpukit/backward/iosupp.h
@@ -0,0 +1,7 @@
+#ifndef __iosupp_h
+#define __iosupp_h
+#ifndef RTEMS_NO_WARN_DEPRECATED
+#warning <iosupp.h> is deprecated, use <rtems/iosupp.h> instead
+#endif
+#include <rtems/iosupp.h>
+#endif
diff --git a/cpukit/backward/itron.h b/cpukit/backward/itron.h
new file mode 100644
index 0000000000..e02198f63a
--- /dev/null
+++ b/cpukit/backward/itron.h
@@ -0,0 +1,7 @@
+#ifndef __itron_h
+#define __itron_h
+#ifndef RTEMS_NO_WARN_DEPRECATED
+#warning <itron.h> is deprecated, use <rtems/itron.h> instead
+#endif
+#include <rtems/itron.h>
+#endif
diff --git a/cpukit/backward/motorola/mc68230.h b/cpukit/backward/motorola/mc68230.h
new file mode 100644
index 0000000000..30f4f81db5
--- /dev/null
+++ b/cpukit/backward/motorola/mc68230.h
@@ -0,0 +1,7 @@
+#ifndef __motorola_mc68230_h
+#define __motorola_mc68230_h
+#ifndef RTEMS_NO_WARN_DEPRECATED
+#warning <motorola/mc68230.h> is deprecated, use <rtems/motorola/mc68230.h> instead
+#endif
+#include <rtems/motorola/mc68230.h>
+#endif
diff --git a/cpukit/backward/motorola/mc68681.h b/cpukit/backward/motorola/mc68681.h
new file mode 100644
index 0000000000..3f78a7cd59
--- /dev/null
+++ b/cpukit/backward/motorola/mc68681.h
@@ -0,0 +1,7 @@
+#ifndef __motorola_mc68681_h
+#define __motorola_mc68681_h
+#ifndef RTEMS_NO_WARN_DEPRECATED
+#warning <motorola/mc68681.h> is deprecated, use <rtems/motorola/mc68681.h> instead
+#endif
+#include <rtems/motorola/mc68681.h>
+#endif
diff --git a/cpukit/backward/ringbuf.h b/cpukit/backward/ringbuf.h
new file mode 100644
index 0000000000..8ab909be21
--- /dev/null
+++ b/cpukit/backward/ringbuf.h
@@ -0,0 +1,7 @@
+#ifndef __ringbuf_h
+#define __ringbuf_h
+#ifndef RTEMS_NO_WARN_DEPRECATED
+#warning <ringbuf.h> is deprecated, use <rtems/ringbuf.h> instead
+#endif
+#include <rtems/ringbuf.h>
+#endif
diff --git a/cpukit/backward/rtc.h b/cpukit/backward/rtc.h
new file mode 100644
index 0000000000..978aca4359
--- /dev/null
+++ b/cpukit/backward/rtc.h
@@ -0,0 +1,7 @@
+#ifndef __rtc_h
+#define __rtc_h
+#ifndef RTEMS_NO_WARN_DEPRECATED
+#warning <rtc.h> is deprecated, use <rtems/rtc.h> instead
+#endif
+#include <rtems/rtc.h>
+#endif
diff --git a/cpukit/backward/spurious.h b/cpukit/backward/spurious.h
new file mode 100644
index 0000000000..c770fd7acd
--- /dev/null
+++ b/cpukit/backward/spurious.h
@@ -0,0 +1,7 @@
+#ifndef __spurious_h
+#define __spurious_h
+#ifndef RTEMS_NO_WARN_DEPRECATED
+#warning <spurious.h> is deprecated, use <rtems/spurious.h> instead
+#endif
+#include <rtems/spurious.h>
+#endif
diff --git a/cpukit/backward/timerdrv.h b/cpukit/backward/timerdrv.h
new file mode 100644
index 0000000000..a9a40fada1
--- /dev/null
+++ b/cpukit/backward/timerdrv.h
@@ -0,0 +1,7 @@
+#ifndef __timerdrv_h
+#define __timerdrv_h
+#ifndef RTEMS_NO_WARN_DEPRECATED
+#warning <timerdrv.h> is deprecated, use <rtems/timerdrv.h> instead
+#endif
+#include <rtems/timerdrv.h>
+#endif
diff --git a/cpukit/backward/vmeintr.h b/cpukit/backward/vmeintr.h
new file mode 100644
index 0000000000..caf7094a87
--- /dev/null
+++ b/cpukit/backward/vmeintr.h
@@ -0,0 +1,7 @@
+#ifndef __vmeintr_h
+#define __vmeintr_h
+#ifndef RTEMS_NO_WARN_DEPRECATED
+#warning <vmeintr.h> is deprecated, use <rtems/vmeintr.h> instead
+#endif
+#include <rtems/vmeintr.h>
+#endif
diff --git a/cpukit/backward/zilog/z8030.h b/cpukit/backward/zilog/z8030.h
new file mode 100644
index 0000000000..2974a5026e
--- /dev/null
+++ b/cpukit/backward/zilog/z8030.h
@@ -0,0 +1,7 @@
+#ifndef __zilog_z8030_h
+#define __zilog_z8030_h
+#ifndef RTEMS_NO_WARN_DEPRECATED
+#warning <zilog/z8030.h> is deprecated, use <rtems/zilog/z8030.h> instead
+#endif
+#include <rtems/zilog/z8030.h>
+#endif
diff --git a/cpukit/backward/zilog/z8036.h b/cpukit/backward/zilog/z8036.h
new file mode 100644
index 0000000000..d1c5b5ee4c
--- /dev/null
+++ b/cpukit/backward/zilog/z8036.h
@@ -0,0 +1,7 @@
+#ifndef __zilog_z8036_h
+#define __zilog_z8036_h
+#ifndef RTEMS_NO_WARN_DEPRECATED
+#warning <zilog/z8036.h> is deprecated, use <rtems/zilog/z8036.h> instead
+#endif
+#include <rtems/zilog/z8036.h>
+#endif
diff --git a/cpukit/backward/zilog/z8536.h b/cpukit/backward/zilog/z8536.h
new file mode 100644
index 0000000000..4f61feb9ba
--- /dev/null
+++ b/cpukit/backward/zilog/z8536.h
@@ -0,0 +1,7 @@
+#ifndef __zilog_z8536_h
+#define __zilog_z8536_h
+#ifndef RTEMS_NO_WARN_DEPRECATED
+#warning <zilog/z8536.h> is deprecated, use <rtems/zilog/z8536.h> instead
+#endif
+#include <rtems/zilog/z8536.h>
+#endif
diff --git a/cpukit/configure.ac b/cpukit/configure.ac
new file mode 100644
index 0000000000..5611088853
--- /dev/null
+++ b/cpukit/configure.ac
@@ -0,0 +1,323 @@
+## Process this file with autoconf to produce a configure script.
+##
+## $Id$
+
+AC_PREREQ(2.59)
+AC_INIT([rtems-cpukit],[_RTEMS_VERSION],[rtems-bugs@rtems.com])
+AC_CONFIG_SRCDIR([score])
+RTEMS_TOP([..],[])
+
+RTEMS_CANONICAL_TARGET_CPU
+
+AM_INIT_AUTOMAKE([no-define nostdinc subdir-objects foreign 1.8.1])
+AM_MAINTAINER_MODE
+
+RTEMS_ENABLE_MULTILIB
+RTEMS_ENABLE_MULTIPROCESSING
+RTEMS_ENABLE_POSIX
+RTEMS_ENABLE_ITRON
+RTEMS_ENABLE_INLINES
+RTEMS_ENABLE_RTEMS_DEBUG
+RTEMS_ENABLE_NETWORKING
+
+RTEMS_ENV_RTEMSCPU
+RTEMS_CHECK_RTEMS_DEBUG
+
+# Is this a supported CPU?
+AC_MSG_CHECKING([if cpu $RTEMS_CPU is supported])
+if test -d "$srcdir/score/cpu/$RTEMS_CPU"; then
+ AC_MSG_RESULT(yes)
+else
+ AC_MSG_ERROR(no)
+fi
+
+RTEMS_PROG_CC_FOR_TARGET([-ansi -fasm])
+RTEMS_PROG_CCAS
+RTEMS_CANONICALIZE_TOOLS
+AM_PROG_CC_C_O
+AC_PROG_RANLIB
+
+# FIXME: For the moment, no reason to check for ada
+# RTEMS_PROG_GNAT
+
+RTEMS_CHECK_NEWLIB
+
+RTEMS_CHECK_MULTIPROCESSING
+RTEMS_CHECK_POSIX_API
+RTEMS_CHECK_ITRON_API
+RTEMS_CHECK_NETWORKING
+
+AS_IF([test x"$HAS_NETWORKING" = x"yes"],[
+## FIXME: Should better use a feature-based test
+AC_MSG_CHECKING([whether CPU supports librpc])
+ case "$RTEMS_CPU" in
+ c4x ) LIBRPC=no;;
+ or32 ) LIBRPC=no;;
+ * ) LIBRPC=yes;;
+ esac
+AC_MSG_RESULT([$LIBRPC])
+])
+
+AC_ARG_ENABLE([ada],
+[AS_HELP_STRING(--enable-ada,enable ada support)],
+[case "${enable_ada}" in
+ yes) ;;
+ no) ;;
+ *) AC_MSG_ERROR([bad value ${enable_ada} for --enable-ada]) ;;
+esac],[enable_ada=no])
+
+AC_ARG_ENABLE([deprecated],
+[AS_HELP_STRING(--enable-deprecated,allow using deprecated files)],
+[case "${enable_deprecated}" in
+ yes) ;;
+ no) ;;
+ *) enable_deprecated=yes ;;
+esac],[enable_deprecated=yes])
+AM_CONDITIONAL([DEPRECATED],[test "$enable_deprecated" = "yes"])
+
+# HACK: We should use a feature-based configuration.
+AS_IF([test x"${RTEMS_CPU}" = x"unix"],[
+# HACK: silently accept --enable-unixlib
+ test -n "${enable_unixlib}" || enable_unixlib="yes"
+])
+
+# BSD-isms, used throughout the sources
+# Not really used by this configure script
+# FIXME: They should be eliminated if possible.
+AC_CHECK_FUNCS([strsep strcasecmp snprintf])
+AC_CHECK_FUNCS([bcopy bcmp])
+AC_CHECK_FUNCS([isascii fileno])
+
+## Check if the installed toolchain has these headers
+AC_CHECK_HEADER(stdint.h)
+AC_CHECK_HEADER(inttypes.h)
+
+AS_IF([test x"${RTEMS_USE_NEWLIB}" = x"yes"],[
+ RTEMS_USES_STDINT_H=yes
+ RTEMS_USES_INTTYPES_H=yes],[
+ RTEMS_USES_STDINT_H=$ac_cv_header_stdint_h
+ RTEMS_USES_INTTYPES_H=$ac_cv_header_inttypes_h
+])
+
+AS_IF([test x"${RTEMS_CPU}" = x"unix"],[
+## FIXME: This check is doubtful
+AS_IF([test "$HAS_MP" = "yes"],
+ [RTEMS_CHECK_SYSV_UNIX])
+
+## The code fragment below had been used in tools/cpu/unix/gensize.c.
+## FIXME:
+## * The pad very likely is not necessary.
+AC_CHECK_SIZEOF([CPU_CONTEXT],[],[
+#include <stdio.h>
+#include <setjmp.h>
+
+typedef struct {
+ jmp_buf regs;
+ int isr_level;
+ int pad[4]; /* just in case */
+} CPU_CONTEXT;
+])
+])
+
+cat >>cpuopts.tmp <<\_ACEOF
+/* target cpu dependent options file */
+/* automatically generated -- DO NOT EDIT!! */
+#ifndef __CPU_OPTIONS_h
+#define __CPU_OPTIONS_h
+_ACEOF
+
+RTEMS_CPUOPT([RTEMS_DEBUG],
+ [test x"${enable_rtems_debug}" = x"yes"],
+ [1],
+ [if RTEMS_DEBUG is enabled])
+
+RTEMS_CPUOPT([RTEMS_INLINES],
+ [test x"${enable_rtems_inlines}" = x"yes"],
+ [1],
+ [if using inlines])
+
+RTEMS_CPUOPT([RTEMS_ITRON_API],
+ [test x"$rtems_cv_HAS_ITRON_API" = x"yes"],
+ [1],
+ [if itron api is supported])
+
+RTEMS_CPUOPT([RTEMS_MULTILIBS],
+ [test x"$RTEMS_MULTILIBS" = x"yes"],
+ [1],
+ [using multilib'ed RTEMS])
+
+RTEMS_CPUOPT([RTEMS_MULTIPROCESSING],
+ [test x"$enable_multiprocessing" = x"yes"],
+ [1],
+ [if multiprocessing is enabled])
+
+RTEMS_CPUOPT([RTEMS_NEWLIB],
+ [test x"$RTEMS_USE_NEWLIB" = x"yes"],
+ [1],
+ [if using newlib])
+
+RTEMS_CPUOPT([RTEMS_POSIX_API],
+ [test x"$rtems_cv_HAS_POSIX_API" = x"yes"],
+ [1],
+ [if posix api is supported])
+
+RTEMS_CPUOPT([RTEMS_UNIX],
+ [test x"$RTEMS_CPU" = x"unix"],
+ [1],
+ [to indicate RTEMS unix])
+
+RTEMS_CPUOPT([RTEMS_UNIXLIB],
+ [test x"${enable_unixlib}" = x"yes"],
+ [1],
+ [to indicate RTEMS using RTEMS's unixlib])
+
+RTEMS_CPUOPT([RTEMS_USES_STDINT_H],
+ [test x"${RTEMS_USES_STDINT_H}" = x"yes"],
+ [1],
+ [if RTEMS uses stdint.h])
+
+RTEMS_CPUOPT([RTEMS_USES_INTTYPES_H],
+ [test x"${RTEMS_USES_INTTYPES_H}" = x"yes"],
+ [1],
+ [if RTEMS uses inttypes.h])
+
+RTEMS_CPUOPT([RTEMS_VERSION],
+ [true],
+ ["]_RTEMS_VERSION["],
+ [RTEMS version string])
+
+RTEMS_CPUOPT([SIZEOF_CPU_CONTEXT],
+ [test x"$RTEMS_CPU" = x"unix"],
+ [$ac_cv_sizeof_CPU_CONTEXT],
+ [The size of a 'CPU_CONTEXT', as computed by sizeof])
+
+cat >>cpuopts.tmp <<\_ACEOF
+
+#endif
+_ACEOF
+
+AS_MKDIR_P(score/include/rtems/score)
+AS_IF([test -f score/include/rtems/score/cpuopts.h],
+[
+ AS_IF([cmp -s score/include/rtems/score/cpuopts.h cpuopts.tmp 2>/dev/null],
+ [
+ AC_MSG_NOTICE([score/include/rtems/score/cpuopts.h is unchanged])
+ rm -f cpuopts.tmp
+ ],[
+ AC_MSG_NOTICE([creating score/include/rtems/score/cpuopts.h])
+ rm -f score/include/rtems/score/cpuopts.h
+ mv cpuopts.tmp score/include/rtems/score/cpuopts.h
+ ])
+],[
+ AC_MSG_NOTICE([creating score/include/rtems/score/cpuopts.h])
+ rm -f score/include/rtems/score/cpuopts.h
+ mv cpuopts.tmp score/include/rtems/score/cpuopts.h
+])
+
+AC_ENABLE_MULTILIB([Makefile],[..])
+
+# libmisc/shell/* wants to assign file descriptors to stdio file descriptors.
+AC_MSG_CHECKING([for assignable stdio])
+AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM(
+ [#include <stdio.h>],
+ [stdin = fopen("/tmp", "r")])],
+ [HAVE_ASSIGNABLE_STDIO=yes],
+ [HAVE_ASSIGNABLE_STDIO=no])
+AC_MSG_RESULT([$HAVE_ASSIGNABLE_STDIO])
+
+# libmisc/serdbg exploits weak symbols
+AC_CACHE_CHECK([whether $CC supports function __attribute__((weak))],
+[rtems_cv_cc_attribute_weak],[
+ AS_IF([test x"$GCC" = xyes],[
+ save_CFLAGS=$CFLAGS
+ CFLAGS=-Werror])
+
+ AC_COMPILE_IFELSE([
+ AC_LANG_PROGRAM(
+ [void myfunc(char c) __attribute__ ((weak));
+ void myfunc(char c) {}],
+ [])],
+ [rtems_cv_cc_attribute_weak=yes],
+ [rtems_cv_cc_attribute_weak=no])
+
+ AS_IF([test x"$GCC" = xyes],[
+ CFLAGS=$save_CFLAGS])
+])
+
+AC_CHECK_HEADERS([sys/cdefs.h],[NEED_SYS_CDEFS_H=no],[NEED_SYS_CDEFS_H=yes])
+AC_CHECK_HEADERS([sys/queue.h],[NEED_SYS_QUEUE_H=no],[NEED_SYS_QUEUE_H=yes])
+
+# FIXME: These checks are only in here to provide
+# configuration-time diagnostics and are not really used.
+AC_CHECK_DECLS([_POSIX_LOGIN_NAME_MAX],,,[#include <limits.h>])
+AC_CHECK_DECLS([CHAR_BIT],,,[#include <limits.h>])
+
+## BSD-ism, excluded from POSIX, but available on most platforms
+AC_CHECK_DECLS([sbrk],,,[#include <unistd.h>])
+
+## Check if libc provides BSD's strlcpy/strlcat
+AC_CHECK_FUNCS(strlcpy strlcat)
+
+
+# ... far too many conditionals ...
+AM_CONDITIONAL(LIBRPC,[test "$LIBRPC" = "yes"])
+AM_CONDITIONAL(UNIX,[test x"${RTEMS_CPU}" = x"unix"])
+AM_CONDITIONAL(NEWLIB,test x"$RTEMS_USE_NEWLIB" = x"yes")
+
+AM_CONDITIONAL(INLINE,test x"$enable_rtems_inlines" = x"yes" )
+AM_CONDITIONAL(MACROS,test x"$enable_rtems_inlines" = x"no" )
+AM_CONDITIONAL(HAS_MP,test x"$enable_multiprocessing" = x"yes" )
+
+AM_CONDITIONAL(HAS_POSIX,test x"$rtems_cv_HAS_POSIX_API" = x"yes")
+AM_CONDITIONAL(HAS_ITRON,test x"$rtems_cv_HAS_ITRON_API" = x"yes")
+AM_CONDITIONAL(HAS_NETWORKING,test x"$HAS_NETWORKING" = x"yes")
+
+# FIXME: All ports should have a libscorecpu.a - But the powerpc doesn't!
+AM_CONDITIONAL([LIBSCORECPU],
+[test -f "${srcdir}/score/cpu/${RTEMS_CPU}/cpu.c"])
+
+AM_CONDITIONAL(RTEMS_ADA,[test x"$enable_ada" = x"yes" \
+ && test x"$HAS_POSIX_API" = x"yes"])
+
+AM_CONDITIONAL([NEED_SYS_CDEFS_H],[test x"$NEED_SYS_CDEFS_H" = x"yes"])
+AM_CONDITIONAL([NEED_SYS_QUEUE_H],[test x"$NEED_SYS_QUEUE_H" = x"yes"])
+
+AM_CONDITIONAL([LIBSHELL],[test x"$HAVE_ASSIGNABLE_STDIO" = x"yes"])
+AM_CONDITIONAL([LIBSERDBG],[test x"$rtems_cv_cc_attribute_weak" = x"yes"])
+
+AC_CONFIG_HEADER(config.h)
+
+# Explicitly list all Makefiles here
+AC_CONFIG_FILES([
+Makefile
+ada/Makefile
+rtems/Makefile
+sapi/Makefile
+score/Makefile
+score/cpu/Makefile
+score/cpu/arm/Makefile
+score/cpu/c4x/Makefile
+score/cpu/h8300/Makefile
+score/cpu/i386/Makefile
+score/cpu/i960/Makefile
+score/cpu/m68k/Makefile
+score/cpu/mips/Makefile
+score/cpu/or32/Makefile
+score/cpu/powerpc/Makefile
+score/cpu/sh/Makefile
+score/cpu/sparc/Makefile
+score/cpu/unix/Makefile
+posix/Makefile
+itron/Makefile
+libblock/Makefile
+libfs/Makefile
+libcsupport/Makefile
+libnetworking/Makefile
+librpc/Makefile
+libmisc/Makefile
+
+wrapup/Makefile
+])
+
+AC_OUTPUT
diff --git a/cpukit/ftpd/Makefile.am b/cpukit/ftpd/Makefile.am
new file mode 100644
index 0000000000..39ce900b9e
--- /dev/null
+++ b/cpukit/ftpd/Makefile.am
@@ -0,0 +1,45 @@
+##
+## $Id$
+##
+
+include $(top_srcdir)/automake/compile.am
+
+CLEANFILES =
+EXTRA_LIBRARIES =
+
+if HAS_NETWORKING
+include_HEADERS = ftpd.h
+
+EXTRA_LIBRARIES += libftpd.a
+CLEANFILES += libftpd.a
+libftpd_a_SOURCES = ftpd.c ftpd.h
+libftpd_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libftpd_g.a
+CLEANFILES += libftpd_g.a
+libftpd_g_a_SOURCES = $(libftpd_a_SOURCES)
+libftpd_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+noinst_DATA = libftpd$(LIB_VARIANT).a
+endif
+
+all-local: $(PREINSTALL_FILES)
+
+PREINSTALL_DIRS =
+PREINSTALL_FILES =
+
+$(PROJECT_INCLUDE)/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)
+ @: > $(PROJECT_INCLUDE)/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/$(dirstamp)
+
+if HAS_NETWORKING
+$(PROJECT_INCLUDE)/ftpd.h: ftpd.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/ftpd.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/ftpd.h
+endif
+
+CLEANFILES += $(PREINSTALL_FILES)
+DISTCLEANFILES = $(PREINSTALL_DIRS)
+
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/ftpd/ftpd.c b/cpukit/ftpd/ftpd.c
new file mode 100644
index 0000000000..79a293eb0f
--- /dev/null
+++ b/cpukit/ftpd/ftpd.c
@@ -0,0 +1,2062 @@
+/* FIXME: 1. Parse command is a hack. We can do better.
+ * 2. Some sort of access control?
+ * 3. OSV: hooks support seems to be bad, as it requires storing of
+ * entire input file in memory. Seem to be better to change it to
+ * something more reasonable, like having
+ * 'hook_write(void const *buf, int count)' routine that will be
+ * called multiple times while file is being received.
+ * 4. OSV: Remove hack with "/dev/null"?
+ *
+ * FTP Server Daemon
+ *
+ * Submitted by: Jake Janovetz <janovetz@tempest.ece.uiuc.edu>
+ *
+ * Changed by: Sergei Organov <osv@javad.ru> (OSV)
+ *
+ * Changes:
+ *
+ * 2001-01-31 Sergei Organov <osv@javad.ru>
+ *
+ * * Hacks with current dir and root dir removed in favor of new libio
+ * support for task-local current and root directories.
+ *
+ * 2001-01-30 Sergei Organov <osv@javad.ru>
+ *
+ * * Bug in `close_data_socket()' introduced by previous change fixed.
+ * * `command_pasv()' changed to set timeout on socket we are listening on
+ * and code fixed to don't close socket twice on error.
+ * * `serr()' changed to clear `errno'.
+ * * `data_socket()' changed to clear `errno' before `bind()'.
+ * * `session()' changed to clear `errno' before processing session.
+ *
+ * 2001-01-29 Sergei Organov <osv@javad.ru>
+ *
+ * * `close_data_socket()' fixed to close both active and passive sockets
+ * * Initialize info->data_socket to -1 in `daemon()'
+ * * Initialize `fname' to empty string in `exec_command()'
+ *
+ * 2001-01-22 Sergei Organov <osv@javad.ru>
+ *
+ * * Timeouts on sockets implemented. 'idle' field added to
+ * configuration. No timeout by default to keep backward compatibility.
+ * Note: SITE IDLE command not implemented yet.
+ * * Basic global access control implemented. 'access' field added to
+ * configuration. No access limitations by default to keep backward
+ * compatibility.
+ *
+ * 2001-01-17 Sergei Organov <osv@javad.ru>
+ *
+ * * Anchor data socket for active mode (using self IP and port 20.)
+ * * Fixed default data port support (still not tested).
+ * * Don't allow IP address different from originating host in
+ * PORT command to improve security.
+ * * Fixed bug in MDTM command.
+ * * Check for correctness of parsing of argument in command_port().
+ * * Fixed squeeze_path() to don't allow names like 'NAME/smth' where
+ * 'NAME' is not a directory.
+ * * Command parsing a little bit improved: command names are now
+ * converted to upper-case to be more compatible with RFC (command
+ * names are not case-sensitive.)
+ * * Reformat comments so that they have RTEMS look-and-feel.
+ *
+ * 2001-01-16 Sergei Organov <osv@javad.ru>
+ *
+ * * Fixed DELE, SITE CHMOD, RMD, MKD broken by previous changes
+ * * True ASCII mode implemented (doesn't work for hooks and /dev/null)
+ * * Passive mode implemented, PASV command added.
+ * * Default port for data connection could be used (untested, can't find
+ * ftp client that doesn't send PORT command)
+ * * SYST reply changed to UNIX, as former RTEMS isn't registered name.
+ * * Reply codes reviewed and fixed.
+ *
+ * 2001-01-08 Sergei Organov <osv@javad.ru>
+ *
+ * * use pool of pre-created threads to handle sessions
+ * * LIST output now similar to what "/bin/ls -al" would output, thus
+ * FTP clients could parse it.
+ * * LIST NAME now works (both for files and directories)
+ * * keep track of CWD for every session separately
+ * * ability to specify root directory name in configuration table
+ * * options sent in commands are ignored, thus LIST -al FILE works
+ * * added support for NLST, CDUP and MDTM commands
+ * * buffers are allocated on stack instead of heap where possible
+ * * drop using of task notepad to pass parameters - use function
+ * arguments instead
+ * * various bug-fixes, e.g., use of PF_INET in socket() instead of
+ * AF_INET, use snprintf() instead of sprintf() everywhere for safety,
+ * etc.
+ *
+ * $Id$
+ */
+
+/*************************************************************************
+ * ftpd.c
+ *************************************************************************
+ * Description:
+ *
+ * This file contains the daemon which services requests that appear
+ * on the FTP port. This server is compatible with FTP, but it
+ * also provides 'hooks' to make it usable in situations where files
+ * are not used/necessary. Once the server is started, it runs
+ * forever.
+ *
+ *
+ * Organization:
+ *
+ * The FTP daemon is started upon boot along with a (configurable)
+ * number of tasks to handle sessions. It runs all the time and
+ * waits for connections on the known FTP port (21). When
+ * a connection is made, it wakes-up a 'session' task. That
+ * session then interacts with the remote host. When the session
+ * is complete, the session task goes to sleep. The daemon still
+ * runs, however.
+ *
+ *
+ * Supported commands are:
+ *
+ * RETR xxx - Sends a file from the client.
+ * STOR xxx - Receives a file from the client. xxx = filename.
+ * LIST xxx - Sends a file list to the client.
+ * NLST xxx - Sends a file list to the client.
+ * USER - Does nothing.
+ * PASS - Does nothing.
+ * SYST - Replies with the system type (`RTEMS').
+ * DELE xxx - Delete file xxx.
+ * MKD xxx - Create directory xxx.
+ * RMD xxx - Remove directory xxx.
+ * PWD - Print working directory.
+ * CWD xxx - Change working directory.
+ * CDUP - Change to upper directory.
+ * SITE CHMOD xxx yyy - Change permissions on file yyy to xxx.
+ * PORT a,b,c,d,x,y - Setup for a data port to IP address a.b.c.d
+ * and port (x*256 + y).
+ * MDTM xxx - Send file modification date/time to the client.
+ * xxx = filename.
+ * PASV - Use passive mode data connection.
+ *
+ *
+ * The public routines contained in this file are:
+ *
+ * rtems_initialize_ftpd - Initializes and starts the server daemon,
+ * then returns to its caller.
+ *
+ *------------------------------------------------------------------------
+ * Jake Janovetz
+ * University of Illinois
+ * 1406 West Green Street
+ * Urbana IL 61801
+ *************************************************************************
+ * Change History:
+ * 12/01/97 - Creation (JWJ)
+ * 2001-01-08 - Changes by OSV
+ *************************************************************************/
+
+/*************************************************************************
+ * Meanings of first and second digits of reply codes:
+ *
+ * Reply: Description:
+ *-------- --------------
+ * 1yz Positive preliminary reply. The action is being started but
+ * expect another reply before sending another command.
+ * 2yz Positive completion reply. A new command can be sent.
+ * 3yz Positive intermediate reply. The command has been accepted
+ * but another command must be sent.
+ * 4yz Transient negative completion reply. The requested action did
+ * not take place, but the error condition is temporary so the
+ * command can be reissued later.
+ * 5yz Permanent negative completion reply. The command was not
+ * accepted and should not be retried.
+ *-------------------------------------------------------------------------
+ * x0z Syntax errors.
+ * x1z Information.
+ * x2z Connections. Replies referring to the control or data
+ * connections.
+ * x3z Authentication and accounting. Replies for the login or
+ * accounting commands.
+ * x4z Unspecified.
+ * x5z Filesystem status.
+ *************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include <rtems.h>
+#include <rtems/rtems_bsdnet.h>
+#include <rtems/error.h>
+#include <rtems/libio.h>
+#include <rtems/userenv.h>
+#include <syslog.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/ftp.h>
+#include <netinet/in.h>
+
+#include "ftpd.h"
+
+
+#ifdef __GNUC__
+/* change to #if 1 to disable syslog entirely */
+#if 0
+#undef syslog
+#define syslog(a, b, ...) while(0){}
+#endif
+#endif
+
+#define FTPD_SERVER_MESSAGE "RTEMS FTP server (Version 1.1-JWJ) ready."
+
+#define FTPD_SYSTYPE "UNIX Type: L8"
+
+/* Seem to be unused */
+#if 0
+#define FTPD_WELCOME_MESSAGE \
+ "Welcome to the RTEMS FTP server.\n" \
+ "\n" \
+ "Login accepted.\n"
+#endif
+
+/* Various buffer sizes */
+enum
+{
+ FTPD_BUFSIZE = 256, /* Size for temporary buffers */
+ FTPD_DATASIZE = 1024, /* Size for file transfer buffers */
+ FTPD_STACKSIZE = 8 * 1024, /* Tasks stack size */
+};
+
+/* Event to be used by session tasks for waiting */
+enum
+{
+ FTPD_RTEMS_EVENT = RTEMS_EVENT_1
+};
+
+/* Configuration table */
+extern struct rtems_ftpd_configuration rtems_ftpd_configuration;
+
+/* this is not prototyped in strict ansi mode */
+FILE *fdopen (int fildes, const char *mode);
+
+/*PAGE
+ * SessionInfo structure.
+ *
+ * The following structure is allocated for each session.
+ */
+typedef struct
+{
+ struct sockaddr_in ctrl_addr; /* Control connection self address */
+ struct sockaddr_in data_addr; /* Data address set by PORT command */
+ struct sockaddr_in def_addr; /* Default address for data */
+ int use_default; /* 1 - use default address for data */
+ FILE *ctrl_fp; /* File pointer for control connection */
+ int ctrl_socket; /* Socket for ctrl connection */
+ int pasv_socket; /* Socket for PASV connection */
+ int data_socket; /* Socket for data connection */
+ int idle; /* Timeout in seconds */
+ int xfer_mode; /* Transfer mode (ASCII/binary) */
+ rtems_id tid; /* Task id */
+} FTPD_SessionInfo_t;
+
+
+/*
+ * TaskPool structure.
+ */
+typedef struct
+{
+ FTPD_SessionInfo_t *info;
+ FTPD_SessionInfo_t **queue;
+ int count;
+ int head;
+ int tail;
+ rtems_id mutex;
+ rtems_id sem;
+} FTPD_TaskPool_t;
+
+/*
+ * Task pool instance.
+ */
+static FTPD_TaskPool_t task_pool;
+
+/*
+ * Root directory
+ */
+
+static char const* ftpd_root = "/";
+
+/*
+ * Default idle timeout for sockets in seconds.
+ */
+static int ftpd_timeout = 0;
+
+/*
+ * Global access flags.
+ */
+static int ftpd_access = 0;
+
+/*PAGE
+ *
+ * serr
+ *
+ * Return error string corresponding to current 'errno'.
+ *
+ */
+static char const*
+serr(void)
+{
+ int err = errno;
+ errno = 0;
+ return strerror(err);
+}
+
+/*PAGE
+ *
+ * Utility routines for access control.
+ *
+ */
+
+static int
+can_read(void)
+{
+ return (ftpd_access & FTPD_NO_READ) == 0;
+}
+
+static int
+can_write(void)
+{
+ return (ftpd_access & FTPD_NO_WRITE) == 0;
+}
+
+/*PAGE
+ *
+ * Task pool management routines
+ *
+ */
+
+
+/*PAGE
+ *
+ * task_pool_done
+ *
+ * Cleanup task pool.
+ *
+ * Input parameters:
+ * count - number of entries in task pool to cleanup
+ *
+ * Output parameters:
+ * NONE
+ *
+ */
+static void
+task_pool_done(int count)
+{
+ int i;
+ for(i = 0; i < count; ++i)
+ rtems_task_delete(task_pool.info[i].tid);
+ if(task_pool.info)
+ free(task_pool.info);
+ if(task_pool.queue)
+ free(task_pool.queue);
+ if(task_pool.mutex != (rtems_id)-1)
+ rtems_semaphore_delete(task_pool.mutex);
+ if(task_pool.sem != (rtems_id)-1)
+ rtems_semaphore_delete(task_pool.sem);
+ task_pool.info = 0;
+ task_pool.queue = 0;
+ task_pool.count = 0;
+ task_pool.sem = -1;
+ task_pool.mutex = -1;
+}
+
+/*PAGE
+ *
+ * task_pool_init
+ *
+ * Initialize task pool.
+ *
+ * Input parameters:
+ * count - number of entries in task pool to create
+ * priority - priority tasks are started with
+ *
+ * Output parameters:
+ * returns 1 on success, 0 on failure.
+ *
+ */
+static void session(rtems_task_argument arg); /* Forward declare */
+
+static int
+task_pool_init(int count, rtems_task_priority priority)
+{
+ int i;
+ rtems_status_code sc;
+ char id = 'a';
+
+ task_pool.count = 0;
+ task_pool.head = task_pool.tail = 0;
+ task_pool.mutex = (rtems_id)-1;
+ task_pool.sem = (rtems_id)-1;
+
+ sc = rtems_semaphore_create(
+ rtems_build_name('F', 'T', 'P', 'M'),
+ 1,
+ RTEMS_DEFAULT_ATTRIBUTES
+ | RTEMS_BINARY_SEMAPHORE
+ | RTEMS_INHERIT_PRIORITY
+ | RTEMS_PRIORITY,
+ RTEMS_NO_PRIORITY,
+ &task_pool.mutex);
+
+ if(sc == RTEMS_SUCCESSFUL)
+ sc = rtems_semaphore_create(
+ rtems_build_name('F', 'T', 'P', 'S'),
+ count,
+ RTEMS_DEFAULT_ATTRIBUTES,
+ RTEMS_NO_PRIORITY,
+ &task_pool.sem);
+
+ if(sc != RTEMS_SUCCESSFUL) {
+ task_pool_done(0);
+ syslog(LOG_ERR, "ftpd: Can not create semaphores");
+ return 0;
+ }
+
+ task_pool.info = (FTPD_SessionInfo_t*)
+ malloc(sizeof(FTPD_SessionInfo_t) * count);
+ task_pool.queue = (FTPD_SessionInfo_t**)
+ malloc(sizeof(FTPD_SessionInfo_t*) * count);
+ if (NULL == task_pool.info || NULL == task_pool.queue)
+ {
+ task_pool_done(0);
+ syslog(LOG_ERR, "ftpd: Not enough memory");
+ return 0;
+ }
+
+ for(i = 0; i < count; ++i)
+ {
+ FTPD_SessionInfo_t *info = &task_pool.info[i];
+ sc = rtems_task_create(rtems_build_name('F', 'T', 'P', id),
+ priority, FTPD_STACKSIZE,
+ RTEMS_PREEMPT | RTEMS_NO_TIMESLICE |
+ RTEMS_NO_ASR | RTEMS_INTERRUPT_LEVEL(0),
+ RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL,
+ &info->tid);
+ if (sc == RTEMS_SUCCESSFUL)
+ {
+ sc = rtems_task_start(
+ info->tid, session, (rtems_task_argument)info);
+ if (sc != RTEMS_SUCCESSFUL)
+ task_pool_done(i);
+ }
+ else
+ task_pool_done(i + 1);
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ syslog(LOG_ERR, "ftpd: Could not create/start FTPD session: %s",
+ rtems_status_text(sc));
+ return 0;
+ }
+ task_pool.queue[i] = task_pool.info + i;
+ if (++id > 'z')
+ id = 'a';
+ }
+ task_pool.count = count;
+ return 1;
+}
+
+/*PAGE
+ *
+ * task_pool_obtain
+ *
+ * Obtain free task from task pool.
+ *
+ * Input parameters:
+ * NONE
+ *
+ * Output parameters:
+ * returns pointer to the corresponding SessionInfo structure on success,
+ * NULL if there are no free tasks in the pool.
+ *
+ */
+static FTPD_SessionInfo_t*
+task_pool_obtain()
+{
+ FTPD_SessionInfo_t* info = 0;
+ rtems_status_code sc;
+ sc = rtems_semaphore_obtain(task_pool.sem, RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT);
+ if (sc == RTEMS_SUCCESSFUL)
+ {
+ rtems_semaphore_obtain(task_pool.mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ info = task_pool.queue[task_pool.head];
+ if(++task_pool.head >= task_pool.count)
+ task_pool.head = 0;
+ rtems_semaphore_release(task_pool.mutex);
+ }
+ return info;
+}
+
+/*PAGE
+ *
+ * task_pool_release
+ *
+ * Return task obtained by 'obtain()' back to the task pool.
+ *
+ * Input parameters:
+ * info - pointer to corresponding SessionInfo structure.
+ *
+ * Output parameters:
+ * NONE
+ *
+ */
+static void
+task_pool_release(FTPD_SessionInfo_t* info)
+{
+ rtems_semaphore_obtain(task_pool.mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ task_pool.queue[task_pool.tail] = info;
+ if(++task_pool.tail >= task_pool.count)
+ task_pool.tail = 0;
+ rtems_semaphore_release(task_pool.mutex);
+ rtems_semaphore_release(task_pool.sem);
+}
+
+/*
+ * End of task pool routines
+ */
+
+/*PAGE
+ *
+ * Function: send_reply
+ *
+ *
+ * This procedure sends a reply to the client via the control
+ * connection.
+ *
+ *
+ * Input parameters:
+ * code - 3-digit reply code.
+ * text - Reply text.
+ *
+ * Output parameters:
+ * NONE
+ */
+static void
+send_reply(FTPD_SessionInfo_t *info, int code, char *text)
+{
+ char const* s = (info->xfer_mode == TYPE_A) ? "\r" : "";
+ /* If a text reply exists, add it to the reply data. */
+ if (text != NULL)
+ fprintf(info->ctrl_fp, "%d %.70s%s\n", code, text, s);
+ else
+ fprintf(info->ctrl_fp, "%d%s\n", code, s);
+ fflush(info->ctrl_fp);
+}
+
+
+/*PAGE
+ *
+ * close_socket
+ *
+ * Close socket.
+ *
+ * Input parameters:
+ * s - socket descriptor.
+ * seconds - number of seconds the timeout should be,
+ * if >= 0 - infinite timeout (no timeout).
+ *
+ * Output parameters:
+ * returns 1 on success, 0 on failure.
+ */
+static int
+set_socket_timeout(int s, int seconds)
+{
+ int res = 0;
+ struct timeval tv;
+ int len = sizeof(tv);
+
+ if(seconds < 0)
+ seconds = 0;
+ tv.tv_usec = 0;
+ tv.tv_sec = seconds;
+ if(0 != setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &tv, len))
+ syslog(LOG_ERR, "ftpd: Can't set send timeout on socket: %s.", serr());
+ else if(0 != setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, len))
+ syslog(LOG_ERR, "ftpd: Can't set receive timeout on socket: %s.", serr());
+ else
+ res = 1;
+ return res;
+}
+
+/*PAGE
+ *
+ * close_socket
+ *
+ * Close socket.
+ *
+ * Input parameters:
+ * s - socket descriptor to be closed.
+ *
+ * Output parameters:
+ * returns 1 on success, 0 on failure
+ */
+static int
+close_socket(int s)
+{
+ if (0 <= s)
+ {
+ if (0 != close(s))
+ {
+ shutdown(s, 2);
+ if (0 != close(s))
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/*PAGE
+ *
+ * data_socket
+ *
+ * Create data socket for session.
+ *
+ * Input parameters:
+ * info - corresponding SessionInfo structure
+ *
+ * Output parameters:
+ * returns socket descriptor, or -1 if failure
+ *
+ */
+static int
+data_socket(FTPD_SessionInfo_t *info)
+{
+ int s = info->pasv_socket;
+ if(0 > s)
+ {
+ int on = 1;
+ s = socket(PF_INET, SOCK_STREAM, 0);
+ if(0 > s)
+ send_reply(info, 425, "Can't create data socket.");
+ else if(0 > setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)))
+ {
+ close_socket(s);
+ s = -1;
+ }
+ else
+ {
+ struct sockaddr_in data_source;
+ int tries;
+
+ /* anchor socket to avoid multi-homing problems */
+ data_source = info->ctrl_addr;
+ data_source.sin_port = htons(20); /* ftp-data port */
+ for(tries = 1; tries < 10; ++tries)
+ {
+ errno = 0;
+ if(bind(s, (struct sockaddr *)&data_source, sizeof(data_source)) >= 0)
+ break;
+ if (errno != EADDRINUSE)
+ tries = 10;
+ else
+ rtems_task_wake_after(tries * 10);
+ }
+ if(tries >= 10)
+ {
+ send_reply(info, 425, "Can't bind data socket.");
+ close_socket(s);
+ s = -1;
+ }
+ else
+ {
+ struct sockaddr_in *data_dest =
+ (info->use_default) ? &info->def_addr : &info->data_addr;
+ if(0 > connect(s, (struct sockaddr *)data_dest, sizeof(*data_dest)))
+ {
+ send_reply(info, 425, "Can't connect data socket.");
+ close_socket(s);
+ s = -1;
+ }
+ }
+ }
+ }
+ info->data_socket = s;
+ info->use_default = 1;
+ if(s >= 0)
+ set_socket_timeout(s, info->idle);
+ return s;
+}
+
+/*PAGE
+ *
+ * close_data_socket
+ *
+ * Close data socket for session.
+ *
+ * Input parameters:
+ * info - corresponding SessionInfo structure
+ *
+ * Output parameters:
+ * NONE
+ *
+ */
+static void
+close_data_socket(FTPD_SessionInfo_t *info)
+{
+ /* As at most one data socket could be open simultaneously and in some cases
+ data_socket == pasv_socket, we select socket to close, then close it. */
+ int s = info->data_socket;
+ if(0 > s)
+ s = info->pasv_socket;
+ if(!close_socket(s))
+ syslog(LOG_ERR, "ftpd: Error closing data socket.");
+ info->data_socket = -1;
+ info->pasv_socket = -1;
+ info->use_default = 1;
+}
+
+/*PAGE
+ *
+ * close_stream
+ *
+ * Close control stream of session.
+ *
+ * Input parameters:
+ * info - corresponding SessionInfo structure
+ *
+ * Output parameters:
+ * NONE
+ *
+ */
+static void
+close_stream(FTPD_SessionInfo_t* info)
+{
+ if (NULL != info->ctrl_fp)
+ {
+ if (0 != fclose(info->ctrl_fp))
+ {
+ syslog(LOG_ERR, "ftpd: Could not close control stream: %s", serr());
+ }
+ else
+ info->ctrl_socket = -1;
+ }
+
+ if (!close_socket(info->ctrl_socket))
+ syslog(LOG_ERR, "ftpd: Could not close control socket: %s", serr());
+
+ info->ctrl_fp = NULL;
+ info->ctrl_socket = -1;
+}
+
+
+/*PAGE
+ *
+ * send_mode_reply
+ *
+ * Sends BINARY/ASCII reply string depending on current transfer mode.
+ *
+ * Input parameters:
+ * info - corresponding SessionInfo structure
+ *
+ * Output parameters:
+ * NONE
+ *
+ */
+static void
+send_mode_reply(FTPD_SessionInfo_t *info)
+{
+ if(info->xfer_mode == TYPE_I)
+ send_reply(info, 150, "Opening BINARY mode data connection.");
+ else
+ send_reply(info, 150, "Opening ASCII mode data connection.");
+}
+
+/*PAGE
+ *
+ * command_retrieve
+ *
+ * Perform the "RETR" command (send file to client).
+ *
+ * Input parameters:
+ * info - corresponding SessionInfo structure
+ * char *filename - source filename.
+ *
+ * Output parameters:
+ * NONE
+ *
+ */
+static void
+command_retrieve(FTPD_SessionInfo_t *info, char const *filename)
+{
+ int s = -1;
+ int fd = -1;
+ char buf[FTPD_DATASIZE];
+ int res = 0;
+
+ if(!can_read())
+ {
+ send_reply(info, 550, "Access denied.");
+ return;
+ }
+
+ if (0 > (fd = open(filename, O_RDONLY)))
+ {
+ send_reply(info, 550, "Error opening file.");
+ return;
+ }
+
+ send_mode_reply(info);
+
+ s = data_socket(info);
+
+ if (0 <= s)
+ {
+ int n = -1;
+
+ if(info->xfer_mode == TYPE_I)
+ {
+ while ((n = read(fd, buf, FTPD_DATASIZE)) > 0)
+ {
+ if(send(s, buf, n, 0) != n)
+ break;
+ }
+ }
+ else if (info->xfer_mode == TYPE_A)
+ {
+ int rest = 0;
+ while (rest == 0 && (n = read(fd, buf, FTPD_DATASIZE)) > 0)
+ {
+ char const* e = buf;
+ char const* b;
+ int i;
+ rest = n;
+ do
+ {
+ char lf = '\0';
+
+ b = e;
+ for(i = 0; i < rest; ++i, ++e)
+ {
+ if(*e == '\n')
+ {
+ lf = '\n';
+ break;
+ }
+ }
+ if(send(s, b, i, 0) != i)
+ break;
+ if(lf == '\n')
+ {
+ if(send(s, "\r\n", 2, 0) != 2)
+ break;
+ ++e;
+ ++i;
+ }
+ }
+ while((rest -= i) > 0);
+ }
+ }
+
+ if (0 == n)
+ {
+ if (0 == close(fd))
+ {
+ fd = -1;
+ res = 1;
+ }
+ }
+ }
+
+ if (-1 != fd)
+ close(fd);
+
+ if (0 == res)
+ send_reply(info, 451, "File read error.");
+ else
+ send_reply(info, 226, "Transfer complete.");
+
+ close_data_socket(info);
+
+ return;
+}
+
+
+/*PAGE
+ *
+ * discard
+ *
+ * Analog of `write' routine that just discards passed data
+ *
+ * Input parameters:
+ * fd - file descriptor (ignored)
+ * buf - data to write (ignored)
+ * count - number of bytes in `buf'
+ *
+ * Output parameters:
+ * returns `count'
+ *
+ */
+static ssize_t
+discard(int fd, void const* buf, size_t count)
+{
+ (void)fd;
+ (void)buf;
+ return count;
+}
+
+/*PAGE
+ *
+ * command_store
+ *
+ * Performs the "STOR" command (receive data from client).
+ *
+ * Input parameters:
+ * info - corresponding SessionInfo structure
+ * char *filename - Destination filename.
+ *
+ * Output parameters:
+ * NONE
+ */
+static void
+command_store(FTPD_SessionInfo_t *info, char const *filename)
+{
+ int s;
+ int n;
+ unsigned long size = 0;
+ struct rtems_ftpd_hook *usehook = NULL;
+ char buf[FTPD_DATASIZE];
+ int res = 1;
+ int bare_lfs = 0;
+ int null = 0;
+ typedef ssize_t (*WriteProc)(int, void const*, size_t);
+ WriteProc wrt = &write;
+
+ if(!can_write())
+ {
+ send_reply(info, 550, "Access denied.");
+ return;
+ }
+
+ send_mode_reply(info);
+
+ s = data_socket(info);
+ if(0 > s)
+ return;
+
+ null = !strcmp("/dev/null", filename);
+ if (null)
+ {
+ /* File "/dev/null" just throws data away.
+ * FIXME: this is hack. Using `/dev/null' filesystem entry would be
+ * better.
+ */
+ wrt = &discard;
+ }
+
+ if (!null && rtems_ftpd_configuration.hooks != NULL)
+ {
+
+ /* Search our list of hooks to see if we need to do something special. */
+ struct rtems_ftpd_hook *hook;
+ int i;
+
+ i = 0;
+ hook = &rtems_ftpd_configuration.hooks[i++];
+ while (hook->filename != NULL)
+ {
+ if (!strcmp(hook->filename, filename))
+ {
+ usehook = hook;
+ break;
+ }
+ hook = &rtems_ftpd_configuration.hooks[i++];
+ }
+ }
+
+ if (usehook != NULL)
+ {
+ /*
+ * OSV: FIXME: Small buffer could be used and hook routine
+ * called multiple times instead. Alternatively, the support could be
+ * removed entirely in favor of configuring RTEMS pseudo-device with
+ * given name.
+ */
+
+ char *bigBufr;
+ size_t filesize = rtems_ftpd_configuration.max_hook_filesize + 1;
+
+ /*
+ * Allocate space for our "file".
+ */
+ bigBufr = (char *)malloc(filesize);
+ if (bigBufr == NULL)
+ {
+ send_reply(info, 451, "Local resource failure: malloc.");
+ close_data_socket(info);
+ return;
+ }
+
+ /*
+ * Retrieve the file into our buffer space.
+ */
+ size = 0;
+ while ((n = recv(s, bigBufr + size, filesize - size, 0)) > 0)
+ {
+ size += n;
+ }
+ if (size >= filesize)
+ {
+ send_reply(info, 451, "File too long: buffer size exceeded.");
+ free(bigBufr);
+ close_data_socket(info);
+ return;
+ }
+
+ /*
+ * Call our hook.
+ */
+ res = (usehook->hook_function)(bigBufr, size) == 0;
+ free(bigBufr);
+ if(!res)
+ {
+ send_reply(info, 451, "File processing failed.");
+ close_data_socket(info);
+ return;
+ }
+ }
+ else
+ {
+ /* Data transfer to regular file or /dev/null. */
+ int fd = 0;
+
+ if(!null)
+ fd = creat(filename,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
+
+ if (0 > fd)
+ {
+ send_reply(info, 550, "Error creating file.");
+ close_data_socket(info);
+ return;
+ }
+
+ if(info->xfer_mode == TYPE_I)
+ {
+ while ((n = recv(s, buf, FTPD_DATASIZE, 0)) > 0)
+ {
+ if (wrt(fd, buf, n) != n)
+ {
+ res = 0;
+ break;
+ }
+ }
+ }
+ else if(info->xfer_mode == TYPE_A)
+ {
+ int rest = 0;
+ int pended_cr = 0;
+ while (res && rest == 0 && (n = recv(s, buf, FTPD_DATASIZE, 0)) > 0)
+ {
+ char const* e = buf;
+ char const* b;
+ int i;
+
+ rest = n;
+ if(pended_cr && *e != '\n')
+ {
+ char const lf = '\r';
+ pended_cr = 0;
+ if(wrt(fd, &lf, 1) != 1)
+ {
+ res = 0;
+ break;
+ }
+ }
+ do
+ {
+ int count;
+ int sub = 0;
+
+ b = e;
+ for(i = 0; i < rest; ++i, ++e)
+ {
+ int pcr = pended_cr;
+ pended_cr = 0;
+ if(*e == '\r')
+ {
+ pended_cr = 1;
+ }
+ else if(*e == '\n')
+ {
+ if(pcr)
+ {
+ sub = 2;
+ ++i;
+ ++e;
+ break;
+ }
+ ++bare_lfs;
+ }
+ }
+ if(res == 0)
+ break;
+ count = i - sub - pended_cr;
+ if(count > 0 && wrt(fd, b, count) != count)
+ {
+ res = 0;
+ break;
+ }
+ if(sub == 2 && wrt(fd, e - 1, 1) != 1)
+ res = 0;
+ }
+ while((rest -= i) > 0);
+ }
+ }
+
+ if (0 > close(fd) || res == 0)
+ {
+ send_reply(info, 452, "Error writing file.");
+ close_data_socket(info);
+ return;
+ }
+ }
+
+ if (bare_lfs > 0)
+ {
+ snprintf(buf, FTPD_BUFSIZE,
+ "Transfer complete. WARNING! %d bare linefeeds received in ASCII mode.",
+ bare_lfs);
+ send_reply(info, 226, buf);
+ }
+ else
+ send_reply(info, 226, "Transfer complete.");
+ close_data_socket(info);
+
+}
+
+
+/*PAGE
+ *
+ * send_dirline
+ *
+ * Sends one line of LIST command reply corresponding to single file.
+ *
+ * Input parameters:
+ * s - socket descriptor to send data to
+ * wide - if 0, send only file name. If not 0, send 'stat' info as well in
+ * "ls -l" format.
+ * curTime - current time
+ * path - path to be prepended to what is given by 'add'
+ * add - path to be appended to what is given by 'path', the resulting path
+ * is then passed to 'stat()' routine
+ * name - file name to be reported in output
+ * buf - buffer for temporary data
+ *
+ * Output parameters:
+ * returns 0 on failure, 1 on success
+ *
+ */
+static int
+send_dirline(int s, int wide, time_t curTime, char const* path,
+ char const* add, char const* fname, char* buf)
+{
+ if(wide)
+ {
+ struct stat stat_buf;
+
+ int plen = strlen(path);
+ int alen = strlen(add);
+ if(plen == 0)
+ {
+ buf[plen++] = '/';
+ buf[plen] = '\0';
+ }
+ else
+ {
+ strcpy(buf, path);
+ if(alen > 0 && buf[plen - 1] != '/')
+ {
+ buf[plen++] = '/';
+ if(plen >= FTPD_BUFSIZE)
+ return 0;
+ buf[plen] = '\0';
+ }
+ }
+ if(plen + alen >= FTPD_BUFSIZE)
+ return 0;
+ strcpy(buf + plen, add);
+
+ if (stat(buf, &stat_buf) == 0)
+ {
+ int len;
+ struct tm bt;
+ time_t tf = stat_buf.st_mtime;
+ enum { SIZE = 80 };
+ enum { SIX_MONTHS = 365*24*60*60/2 };
+ char timeBuf[SIZE];
+ gmtime_r(&tf, &bt);
+ if(curTime > tf + SIX_MONTHS || tf > curTime + SIX_MONTHS)
+ strftime (timeBuf, SIZE, "%b %d %Y", &bt);
+ else
+ strftime (timeBuf, SIZE, "%b %d %H:%M", &bt);
+
+ len = snprintf(buf, FTPD_BUFSIZE,
+ "%c%c%c%c%c%c%c%c%c%c 1 %5d %5d %11u %s %s\r\n",
+ (S_ISLNK(stat_buf.st_mode)?('l'):
+ (S_ISDIR(stat_buf.st_mode)?('d'):('-'))),
+ (stat_buf.st_mode & S_IRUSR)?('r'):('-'),
+ (stat_buf.st_mode & S_IWUSR)?('w'):('-'),
+ (stat_buf.st_mode & S_IXUSR)?('x'):('-'),
+ (stat_buf.st_mode & S_IRGRP)?('r'):('-'),
+ (stat_buf.st_mode & S_IWGRP)?('w'):('-'),
+ (stat_buf.st_mode & S_IXGRP)?('x'):('-'),
+ (stat_buf.st_mode & S_IROTH)?('r'):('-'),
+ (stat_buf.st_mode & S_IWOTH)?('w'):('-'),
+ (stat_buf.st_mode & S_IXOTH)?('x'):('-'),
+ (int)stat_buf.st_uid,
+ (int)stat_buf.st_gid,
+ (int)stat_buf.st_size,
+ timeBuf,
+ fname
+ );
+
+ if(send(s, buf, len, 0) != len)
+ return 0;
+ }
+ }
+ else
+ {
+ int len = snprintf(buf, FTPD_BUFSIZE, "%s\r\n", fname);
+ if(send(s, buf, len, 0) != len)
+ return 0;
+ }
+ return 1;
+}
+
+/*PAGE
+ *
+ * command_list
+ *
+ * Send file list to client.
+ *
+ * Input parameters:
+ * info - corresponding SessionInfo structure
+ * char *fname - File (or directory) to list.
+ *
+ * Output parameters:
+ * NONE
+ */
+static void
+command_list(FTPD_SessionInfo_t *info, char const *fname, int wide)
+{
+ int s;
+ DIR *dirp = 0;
+ struct dirent *dp = 0;
+ struct stat stat_buf;
+ char buf[FTPD_BUFSIZE];
+ time_t curTime;
+ int sc = 1;
+
+ send_reply(info, 150, "Opening ASCII mode data connection for LIST.");
+
+ s = data_socket(info);
+ if(0 > s)
+ {
+ syslog(LOG_ERR, "ftpd: Error connecting to data socket.");
+ return;
+ }
+
+ if(fname[0] == '\0')
+ fname = ".";
+
+ if (0 > stat(fname, &stat_buf))
+ {
+ snprintf(buf, FTPD_BUFSIZE,
+ "%s: No such file or directory.\r\n", fname);
+ send(s, buf, strlen(buf), 0);
+ }
+ else if (S_ISDIR(stat_buf.st_mode) && (NULL == (dirp = opendir(fname))))
+ {
+ snprintf(buf, FTPD_BUFSIZE,
+ "%s: Can not open directory.\r\n", fname);
+ send(s, buf, strlen(buf), 0);
+ }
+ else
+ {
+ time(&curTime);
+ if(!dirp && *fname)
+ sc = sc && send_dirline(s, wide, curTime, fname, "", fname, buf);
+ else {
+ /* FIXME: need "." and ".." only when '-a' option is given */
+ sc = sc && send_dirline(s, wide, curTime, fname, "", ".", buf);
+ sc = sc && send_dirline(s, wide, curTime, fname,
+ (strcmp(fname, ftpd_root) ? ".." : ""), "..", buf);
+ while (sc && (dp = readdir(dirp)) != NULL)
+ sc = sc &&
+ send_dirline(s, wide, curTime, fname, dp->d_name, dp->d_name, buf);
+ }
+ }
+
+ if(dirp)
+ closedir(dirp);
+ close_data_socket(info);
+
+ if(sc)
+ send_reply(info, 226, "Transfer complete.");
+ else
+ send_reply(info, 426, "Connection aborted.");
+}
+
+
+/*PAGE
+ *
+ * command_cwd
+ *
+ * Change current working directory.
+ *
+ * Input parameters:
+ * info - corresponding SessionInfo structure
+ * dir - directory name passed in CWD command
+ *
+ * Output parameters:
+ * NONE
+ *
+ */
+static void
+command_cwd(FTPD_SessionInfo_t *info, char *dir)
+{
+ if(chdir(dir) == 0)
+ send_reply(info, 250, "CWD command successful.");
+ else
+ send_reply(info, 550, "CWD command failed.");
+}
+
+
+/*PAGE
+ *
+ * command_pwd
+ *
+ * Send current working directory to client.
+ *
+ * Input parameters:
+ * info - corresponding SessionInfo structure
+ *
+ * Output parameters:
+ * NONE
+ */
+static void
+command_pwd(FTPD_SessionInfo_t *info)
+{
+ char buf[FTPD_BUFSIZE];
+ char const* cwd;
+ errno = 0;
+ buf[0] = '"';
+ cwd = getcwd(buf + 1, FTPD_BUFSIZE - 4);
+ if(cwd)
+ {
+ int len = strlen(cwd);
+ static char const txt[] = "\" is the current directory.";
+ int size = sizeof(txt);
+ if(len + size + 1 >= FTPD_BUFSIZE)
+ size = FTPD_BUFSIZE - len - 2;
+ memcpy(buf + len + 1, txt, size);
+ buf[len + size] = '\0';
+ send_reply(info, 250, buf);
+ }
+ else {
+ snprintf(buf, FTPD_BUFSIZE, "Error: %s.", serr());
+ send_reply(info, 452, buf);
+ }
+}
+
+/*PAGE
+ *
+ * command_mdtm
+ *
+ * Handle FTP MDTM command (send file modification time to client)/
+ *
+ * Input parameters:
+ * info - corresponding SessionInfo structure
+ * fname - file name passed in MDTM command
+ *
+ * Output parameters:
+ * info->cwd is set to new CWD value.
+ */
+static void
+command_mdtm(FTPD_SessionInfo_t *info, char const* fname)
+{
+ struct stat stbuf;
+ char buf[FTPD_BUFSIZE];
+
+ if (0 > stat(fname, &stbuf))
+ {
+ snprintf(buf, FTPD_BUFSIZE, "%s: %s.", fname, serr());
+ send_reply(info, 550, buf);
+ }
+ else
+ {
+ struct tm *t = gmtime(&stbuf.st_mtime);
+ snprintf(buf, FTPD_BUFSIZE, "%04d%02d%02d%02d%02d%02d",
+ 1900 + t->tm_year,
+ t->tm_mon+1, t->tm_mday,
+ t->tm_hour, t->tm_min, t->tm_sec);
+ send_reply(info, 213, buf);
+ }
+}
+
+/*PAGE
+ *
+ * command_port
+ *
+ * This procedure fills address for data connection given the IP address and
+ * port of the remote machine.
+ *
+ * Input parameters:
+ * info - corresponding SessionInfo structure
+ * args - arguments to the "PORT" command.
+ *
+ * Output parameters:
+ * info->data_addr is set according to arguments of the PORT command.
+ * info->use_default is set to 0 on success, 1 on failure.
+ */
+static void
+command_port(FTPD_SessionInfo_t *info, char const *args)
+{
+ enum { NUM_FIELDS = 6 };
+ unsigned int a[NUM_FIELDS];
+ int n;
+
+ close_data_socket(info);
+
+ n = sscanf(args, "%u,%u,%u,%u,%u,%u", a+0, a+1, a+2, a+3, a+4, a+5);
+ if(NUM_FIELDS == n)
+ {
+ int i;
+ unsigned8 b[NUM_FIELDS];
+
+ for(i = 0; i < NUM_FIELDS; ++i)
+ {
+ if(a[i] > 255)
+ break;
+ b[i] = (unsigned8)a[i];
+ }
+
+ if(i == NUM_FIELDS)
+ {
+ /* Note: while it contradicts with RFC959, we don't allow PORT command
+ * to specify IP address different than those of the originating client
+ * for the sake of safety. */
+ unsigned32 const *ip = (unsigned32 *)b;
+ if(*ip == info->def_addr.sin_addr.s_addr)
+ {
+ info->data_addr.sin_addr.s_addr = *ip;
+ info->data_addr.sin_port = *(unsigned16 *)(b + 4);
+ info->data_addr.sin_family = AF_INET;
+ memset(info->data_addr.sin_zero, 0, sizeof(info->data_addr.sin_zero));
+
+ info->use_default = 0;
+ send_reply(info, 200, "PORT command successful.");
+ return; /* success */
+ }
+ else
+ {
+ send_reply(info, 425, "Address doesn't match peer's IP.");
+ return;
+ }
+ }
+ }
+ send_reply(info, 501, "Syntax error.");
+}
+
+
+/*PAGE
+ *
+ * command_pasv
+ *
+ * Handle FTP PASV command.
+ * Open socket, listen for and accept connection on it.
+ *
+ * Input parameters:
+ * info - corresponding SessionInfo structure
+ *
+ * Output parameters:
+ * info->pasv_socket is set to the descriptor of the data socket
+ */
+static void
+command_pasv(FTPD_SessionInfo_t *info)
+{
+ int s = -1;
+ int err = 1;
+
+ close_data_socket(info);
+
+ s = socket(PF_INET, SOCK_STREAM, 0);
+ if (s < 0)
+ syslog(LOG_ERR, "ftpd: Error creating PASV socket: %s", serr());
+ else
+ {
+ struct sockaddr_in addr;
+ int addrLen = sizeof(addr);
+
+ addr = info->ctrl_addr;
+ addr.sin_port = htons(0);
+
+ if (0 > bind(s, (struct sockaddr *)&addr, addrLen))
+ syslog(LOG_ERR, "ftpd: Error binding PASV socket: %s", serr());
+ else if (0 > listen(s, 1))
+ syslog(LOG_ERR, "ftpd: Error listening on PASV socket: %s", serr());
+ else if(set_socket_timeout(s, info->idle))
+ {
+ char buf[FTPD_BUFSIZE];
+ unsigned char const *ip, *p;
+
+ getsockname(s, (struct sockaddr *)&addr, &addrLen);
+ ip = (unsigned char const*)&(addr.sin_addr);
+ p = (unsigned char const*)&(addr.sin_port);
+ snprintf(buf, FTPD_BUFSIZE, "Entering passive mode (%u,%u,%u,%u,%u,%u).",
+ ip[0], ip[1], ip[2], ip[3], p[0], p[1]);
+ send_reply(info, 227, buf);
+
+ info->pasv_socket = accept(s, (struct sockaddr *)&addr, &addrLen);
+ if (0 > info->pasv_socket)
+ syslog(LOG_ERR, "ftpd: Error accepting PASV connection: %s", serr());
+ else
+ {
+ close_socket(s);
+ s = -1;
+ err = 0;
+ }
+ }
+ }
+ if(err)
+ {
+ /* (OSV) The note is from FreeBSD FTPD.
+ * Note: a response of 425 is not mentioned as a possible response to
+ * the PASV command in RFC959. However, it has been blessed as a
+ * legitimate response by Jon Postel in a telephone conversation
+ * with Rick Adams on 25 Jan 89. */
+ send_reply(info, 425, "Can't open passive connection.");
+ close_socket(s);
+ }
+}
+
+
+/*PAGE
+ *
+ * skip_options
+ *
+ * Utility routine to skip options (if any) from input command.
+ *
+ * Input parameters:
+ * p - pointer to pointer to command
+ *
+ * Output parameters:
+ * p - is changed to point to first non-option argument
+ */
+static void
+skip_options(char **p)
+{
+ char* buf = *p;
+ char* last = NULL;
+ while(1) {
+ while(isspace(*buf))
+ ++buf;
+ if(*buf == '-') {
+ if(*++buf == '-') { /* `--' should terminate options */
+ if(isspace(*++buf)) {
+ last = buf;
+ do ++buf;
+ while(isspace(*buf));
+ break;
+ }
+ }
+ while(*buf && !isspace(*buf))
+ ++buf;
+ last = buf;
+ }
+ else
+ break;
+ }
+ if(last)
+ *last = '\0';
+ *p = buf;
+}
+
+/*PAGE
+ *
+ * split_command
+ *
+ * Split command into command itself, options, and arguments. Command itself
+ * is converted to upper case.
+ *
+ * Input parameters:
+ * buf - initial command string
+ *
+ * Output parameter:
+ * buf - is modified by inserting '\0' at ends of split entities
+ * cmd - upper-cased command code
+ * opts - string containing all the options
+ * args - string containing all the arguments
+ */
+void
+split_command(char *buf, char **cmd, char **opts, char **args)
+{
+ char* eoc;
+ char* p = buf;
+ while(isspace(*p))
+ ++p;
+ *cmd = p;
+ while(*p && !isspace(*p))
+ {
+ *p = toupper(*p);
+ ++p;
+ }
+ eoc = p;
+ if(*p)
+ *p++ = '\0';
+ while(isspace(*p))
+ ++p;
+ *opts = p;
+ skip_options(&p);
+ *args = p;
+ if(*opts == p)
+ *opts = eoc;
+ while(*p && *p != '\r' && *p != '\n')
+ ++p;
+ if(*p)
+ *p++ = '\0';
+}
+
+/*PAGE
+ *
+ * exec_command
+ *
+ * Parse and execute FTP command.
+ *
+ * FIXME: This section is somewhat of a hack. We should have a better
+ * way to parse commands.
+ *
+ * Input parameters:
+ * info - corresponding SessionInfo structure
+ * cmd - command to be executed (upper-case)
+ * args - arguments of the command
+ *
+ * Output parameters:
+ * NONE
+ */
+static void
+exec_command(FTPD_SessionInfo_t *info, char* cmd, char* args)
+{
+ char fname[FTPD_BUFSIZE];
+ int wrong_command = 0;
+
+ fname[0] = '\0';
+
+ if (!strcmp("PORT", cmd))
+ {
+ command_port(info, args);
+ }
+ else if (!strcmp("PASV", cmd))
+ {
+ command_pasv(info);
+ }
+ else if (!strcmp("RETR", cmd))
+ {
+ sscanf(args, "%254s", fname);
+ command_retrieve(info, fname);
+ }
+ else if (!strcmp("STOR", cmd))
+ {
+ sscanf(args, "%254s", fname);
+ command_store(info, fname);
+ }
+ else if (!strcmp("LIST", cmd))
+ {
+ sscanf(args, "%254s", fname);
+ command_list(info, fname, 1);
+ }
+ else if (!strcmp("NLST", cmd))
+ {
+ sscanf(args, "%254s", fname);
+ command_list(info, fname, 0);
+ }
+ else if (!strcmp("MDTM", cmd))
+ {
+ sscanf(args, "%254s", fname);
+ command_mdtm(info, fname);
+ }
+ else if (!strcmp("SYST", cmd))
+ {
+ send_reply(info, 215, FTPD_SYSTYPE);
+ }
+ else if (!strcmp("TYPE", cmd))
+ {
+ if (args[0] == 'I')
+ {
+ info->xfer_mode = TYPE_I;
+ send_reply(info, 200, "Type set to I.");
+ }
+ else if (args[0] == 'A')
+ {
+ info->xfer_mode = TYPE_A;
+ send_reply(info, 200, "Type set to A.");
+ }
+ else
+ {
+ info->xfer_mode = TYPE_I;
+ send_reply(info, 504, "Type not implemented. Set to I.");
+ }
+ }
+ else if (!strcmp("USER", cmd) || !strcmp("PASS", cmd))
+ {
+ send_reply(info, 230, "User logged in.");
+ }
+ else if (!strcmp("DELE", cmd))
+ {
+ if(!can_write())
+ {
+ send_reply(info, 550, "Access denied.");
+ }
+ else if (
+ 1 == sscanf(args, "%254s", fname) &&
+ unlink(fname) == 0)
+ {
+ send_reply(info, 257, "DELE successful.");
+ }
+ else
+ {
+ send_reply(info, 550, "DELE failed.");
+ }
+ }
+ else if (!strcmp("SITE", cmd))
+ {
+ char* opts;
+ split_command(args, &cmd, &opts, &args);
+ if(!strcmp("CHMOD", cmd))
+ {
+ int mask;
+
+ if(!can_write())
+ {
+ send_reply(info, 550, "Access denied.");
+ }
+ else if(
+ 2 == sscanf(args, "%o %254s", &mask, fname) &&
+ chmod(fname, (mode_t)mask) == 0)
+ {
+ send_reply(info, 257, "CHMOD successful.");
+ }
+ else
+ {
+ send_reply(info, 550, "CHMOD failed.");
+ }
+ }
+ else
+ wrong_command = 1;
+ }
+ else if (!strcmp("RMD", cmd))
+ {
+ if(!can_write())
+ {
+ send_reply(info, 550, "Access denied.");
+ }
+ else if (
+ 1 == sscanf(args, "%254s", fname) &&
+ rmdir(fname) == 0)
+ {
+ send_reply(info, 257, "RMD successful.");
+ }
+ else
+ {
+ send_reply(info, 550, "RMD failed.");
+ }
+ }
+ else if (!strcmp("MKD", cmd))
+ {
+ if(!can_write())
+ {
+ send_reply(info, 550, "Access denied.");
+ }
+ else if (
+ 1 == sscanf(args, "%254s", fname) &&
+ mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO) == 0)
+ {
+ send_reply(info, 257, "MKD successful.");
+ }
+ else
+ {
+ send_reply(info, 550, "MKD failed.");
+ }
+ }
+ else if (!strcmp("CWD", cmd))
+ {
+ sscanf(args, "%254s", fname);
+ command_cwd(info, fname);
+ }
+ else if (!strcmp("CDUP", cmd))
+ {
+ command_cwd(info, "..");
+ }
+ else if (!strcmp("PWD", cmd))
+ {
+ command_pwd(info);
+ }
+ else
+ wrong_command = 1;
+
+ if(wrong_command)
+ send_reply(info, 500, "Command not understood.");
+}
+
+
+/*PAGE
+ *
+ * session
+ *
+ * This task handles single session. It is waked up when the FTP daemon gets a
+ * service request from a remote machine. Here, we watch for commands that
+ * will come through the control connection. These commands are then parsed
+ * and executed until the connection is closed, either unintentionally or
+ * intentionally with the "QUIT" command.
+ *
+ * Input parameters:
+ * arg - pointer to corresponding SessionInfo.
+ *
+ * Output parameters:
+ * NONE
+ */
+static void
+session(rtems_task_argument arg)
+{
+ FTPD_SessionInfo_t *const info = (FTPD_SessionInfo_t *)arg;
+ int chroot_made = 0;
+
+ rtems_libio_set_private_env();
+
+ /* chroot() can fail here because the directory may not exist yet. */
+ chroot_made = chroot(ftpd_root) == 0;
+
+ while(1)
+ {
+ rtems_event_set set;
+
+ rtems_event_receive(FTPD_RTEMS_EVENT, RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT,
+ &set);
+
+ chroot_made = chroot_made || chroot(ftpd_root) == 0;
+ chdir("/");
+
+ errno = 0;
+
+ send_reply(info, 220, FTPD_SERVER_MESSAGE);
+
+ while (1)
+ {
+ char buf[FTPD_BUFSIZE];
+ char *cmd, *opts, *args;
+
+ if (fgets(buf, FTPD_BUFSIZE, info->ctrl_fp) == NULL)
+ {
+ syslog(LOG_INFO, "ftpd: Connection aborted.");
+ break;
+ }
+
+ split_command(buf, &cmd, &opts, &args);
+
+ if (!strcmp("QUIT", cmd))
+ {
+ send_reply(info, 221, "Goodbye.");
+ break;
+ }
+ else
+ {
+ exec_command(info, cmd, args);
+ }
+ }
+
+ /* Close connection and put ourselves back into the task pool. */
+ close_data_socket(info);
+ close_stream(info);
+ task_pool_release(info);
+ }
+}
+
+
+/*PAGE
+ *
+ * daemon
+ *
+ * This task runs forever. It waits for service requests on the FTP port
+ * (port 21 by default). When a request is received, it opens a new session
+ * to handle those requests until the connection is closed.
+ *
+ * Input parameters:
+ * NONE
+ *
+ * Output parameters:
+ * NONE
+ */
+static void
+daemon()
+{
+ int s;
+ int addrLen;
+ struct sockaddr_in addr;
+ FTPD_SessionInfo_t *info = NULL;
+
+
+ s = socket(PF_INET, SOCK_STREAM, 0);
+ if (s < 0)
+ syslog(LOG_ERR, "ftpd: Error creating socket: %s", serr());
+
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(rtems_ftpd_configuration.port);
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
+
+ if (0 > bind(s, (struct sockaddr *)&addr, sizeof(addr)))
+ syslog(LOG_ERR, "ftpd: Error binding control socket: %s", serr());
+ else if (0 > listen(s, 1))
+ syslog(LOG_ERR, "ftpd: Error listening on control socket: %s", serr());
+ else while (1)
+ {
+ int ss;
+ addrLen = sizeof(addr);
+ ss = accept(s, (struct sockaddr *)&addr, &addrLen);
+ if (0 > ss)
+ syslog(LOG_ERR, "ftpd: Error accepting control connection: %s", serr());
+ else if(!set_socket_timeout(ss, ftpd_timeout))
+ close_socket(ss);
+ else
+ {
+ info = task_pool_obtain();
+ if (NULL == info)
+ {
+ close_socket(ss);
+ }
+ else
+ {
+ info->ctrl_socket = ss;
+ if ((info->ctrl_fp = fdopen(info->ctrl_socket, "r+")) == NULL)
+ {
+ syslog(LOG_ERR, "ftpd: fdopen() on socket failed: %s", serr());
+ close_stream(info);
+ task_pool_release(info);
+ }
+ else
+ {
+ /* Initialize corresponding SessionInfo structure */
+ info->def_addr = addr;
+ if(0 > getsockname(ss, (struct sockaddr *)&addr, &addrLen))
+ {
+ syslog(LOG_ERR, "ftpd: getsockname(): %s", serr());
+ close_stream(info);
+ task_pool_release(info);
+ }
+ else
+ {
+ info->use_default = 1;
+ info->ctrl_addr = addr;
+ info->pasv_socket = -1;
+ info->data_socket = -1;
+ info->xfer_mode = TYPE_A;
+ info->data_addr.sin_port =
+ htons(ntohs(info->ctrl_addr.sin_port) - 1);
+ info->idle = ftpd_timeout;
+ /* Wakeup the session task. The task will call task_pool_release
+ after it closes connection. */
+ rtems_event_send(info->tid, FTPD_RTEMS_EVENT);
+ }
+ }
+ }
+ }
+ }
+ rtems_task_delete(RTEMS_SELF);
+}
+
+
+/*PAGE
+ *
+ * rtems_ftpd_start
+ *
+ * Here, we start the FTPD task which waits for FTP requests and services
+ * them. This procedure returns to its caller once the task is started.
+ *
+ *
+ * Input parameters:
+ *
+ * Output parameters:
+ * returns RTEMS_SUCCESSFUL on successful start of the daemon.
+ */
+int
+rtems_initialize_ftpd()
+{
+ rtems_status_code sc;
+ rtems_id tid;
+ rtems_task_priority priority;
+ int count;
+
+ if (rtems_ftpd_configuration.port == 0)
+ {
+ rtems_ftpd_configuration.port = FTPD_CONTROL_PORT;
+ }
+
+ if (rtems_ftpd_configuration.priority == 0)
+ {
+ rtems_ftpd_configuration.priority = 40;
+ }
+ priority = rtems_ftpd_configuration.priority;
+
+ ftpd_timeout = rtems_ftpd_configuration.idle;
+ if (ftpd_timeout < 0)
+ ftpd_timeout = 0;
+ rtems_ftpd_configuration.idle = ftpd_timeout;
+
+ ftpd_access = rtems_ftpd_configuration.access;
+
+ if (rtems_ftpd_configuration.tasks_count <= 0)
+ rtems_ftpd_configuration.tasks_count = 1;
+ count = rtems_ftpd_configuration.tasks_count;
+
+ if (!task_pool_init(count, priority))
+ {
+ syslog(LOG_ERR, "ftpd: Could not initialize task pool.");
+ return RTEMS_UNSATISFIED;
+ }
+
+ sc = rtems_task_create(rtems_build_name('F', 'T', 'P', 'D'),
+ priority, FTPD_STACKSIZE,
+ RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR |
+ RTEMS_INTERRUPT_LEVEL(0),
+ RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL,
+ &tid);
+
+ if (sc == RTEMS_SUCCESSFUL)
+ {
+ sc = rtems_task_start(tid, daemon, 0);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_task_delete(tid);
+ }
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ task_pool_done(count);
+ syslog(LOG_ERR, "ftpd: Could not create/start FTP daemon: %s",
+ rtems_status_text(sc));
+ return RTEMS_UNSATISFIED;
+ }
+
+ ftpd_root = "/";
+ if (
+ rtems_ftpd_configuration.root &&
+ rtems_ftpd_configuration.root[0] == '/'
+ )
+ ftpd_root = rtems_ftpd_configuration.root;
+
+ rtems_ftpd_configuration.root = ftpd_root;
+
+ syslog(LOG_INFO, "ftpd: FTP daemon started (%d session%s max)",
+ count, ((count > 1) ? "s" : ""));
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/ftpd/ftpd.h b/cpukit/ftpd/ftpd.h
new file mode 100644
index 0000000000..bd7c87aab3
--- /dev/null
+++ b/cpukit/ftpd/ftpd.h
@@ -0,0 +1,56 @@
+/*
+ * FTP Server Information
+ *
+ * $Id$
+ */
+
+#ifndef __FTPD_H__
+#define __FTPD_H__
+
+
+#define FTPD_CONTROL_PORT 21
+
+/* FTPD access control flags */
+enum
+{
+ FTPD_NO_WRITE = 0x1,
+ FTPD_NO_READ = 0x2,
+ FTPD_NO_RW = FTPD_NO_WRITE | FTPD_NO_READ
+};
+
+typedef int (*rtems_ftpd_hookfunction)(unsigned char *, unsigned long);
+
+struct rtems_ftpd_hook
+{
+ char *filename;
+ rtems_ftpd_hookfunction hook_function;
+};
+
+struct rtems_ftpd_configuration
+{
+ rtems_task_priority priority; /* FTPD task priority */
+ unsigned long max_hook_filesize; /* Maximum buffersize */
+ /* for hooks */
+ int port; /* Well-known port */
+ struct rtems_ftpd_hook *hooks; /* List of hooks */
+ char const *root; /* Root for FTPD or 0 for / */
+ int tasks_count; /* Max. connections */
+ int idle; /* Idle timeout in seoconds
+ or 0 for no (inf) timeout */
+ int access; /* 0 - r/w, 1 - read-only,
+ 2 - write-only,
+ 3 - browse-only */
+};
+
+/*
+ * Reply codes.
+ */
+#define PRELIM 1 /* positive preliminary */
+#define COMPLETE 2 /* positive completion */
+#define CONTINUE 3 /* positive intermediate */
+#define TRANSIENT 4 /* transient negative completion */
+#define ERROR 5 /* permanent negative completion */
+
+int rtems_initialize_ftpd();
+
+#endif /* __FTPD_H__ */
diff --git a/cpukit/httpd/.cvsignore b/cpukit/httpd/.cvsignore
new file mode 100644
index 0000000000..282522db03
--- /dev/null
+++ b/cpukit/httpd/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/cpukit/httpd/Makefile.am b/cpukit/httpd/Makefile.am
new file mode 100644
index 0000000000..7c66876683
--- /dev/null
+++ b/cpukit/httpd/Makefile.am
@@ -0,0 +1,97 @@
+##
+## $Id$
+##
+
+include $(top_srcdir)/automake/compile.am
+
+EXTRA_LIBRARIES =
+CLEANFILES =
+
+AM_CPPFLAGS += -DWEBS -DUEMF -DOS="RTEMS"
+
+if HAS_NETWORKING
+if HAS_POSIX
+include_goaheaddir = $(includedir)/goahead
+
+include_HEADERS = rtems_webserver.h
+include_goahead_HEADERS = ej.h ejIntrn.h emfdb.h md5.h uemf.h um.h webs.h \
+ wsIntrn.h
+
+EXTRA_LIBRARIES += libhttpd.a
+CLEANFILES += libhttpd.a
+libhttpd_a_SOURCES = asp.c balloc.c default.c ejlex.c ejparse.c emfdb.c \
+ form.c h.c handler.c md5c.c mime.c misc.c webpage.c ringq.c rom.c \
+ security.c sock.c socket.c sym.c uemf.c um.c url.c value.c wbase64.c \
+ webrom.c webs.c websuemf.c webmain.c
+libhttpd_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libhttpd_g.a
+CLEANFILES += libhttpd_g.a
+libhttpd_g_a_SOURCES = $(libhttpd_a_SOURCES)
+libhttpd_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+noinst_DATA = libhttpd$(LIB_VARIANT).a
+endif
+endif
+
+all-local: $(PREINSTALL_FILES)
+
+EXTRA_DIST = webcomp.c webpage.c
+
+PREINSTALL_DIRS =
+PREINSTALL_FILES =
+
+$(PROJECT_INCLUDE)/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)
+ @: > $(PROJECT_INCLUDE)/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/$(dirstamp)
+
+if HAS_NETWORKING
+if HAS_POSIX
+$(PROJECT_INCLUDE)/goahead/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/goahead
+ @: > $(PROJECT_INCLUDE)/goahead/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/goahead/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems_webserver.h: rtems_webserver.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems_webserver.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems_webserver.h
+
+$(PROJECT_INCLUDE)/goahead/ej.h: ej.h $(PROJECT_INCLUDE)/goahead/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/goahead/ej.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/goahead/ej.h
+
+$(PROJECT_INCLUDE)/goahead/ejIntrn.h: ejIntrn.h $(PROJECT_INCLUDE)/goahead/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/goahead/ejIntrn.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/goahead/ejIntrn.h
+
+$(PROJECT_INCLUDE)/goahead/emfdb.h: emfdb.h $(PROJECT_INCLUDE)/goahead/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/goahead/emfdb.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/goahead/emfdb.h
+
+$(PROJECT_INCLUDE)/goahead/md5.h: md5.h $(PROJECT_INCLUDE)/goahead/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/goahead/md5.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/goahead/md5.h
+
+$(PROJECT_INCLUDE)/goahead/uemf.h: uemf.h $(PROJECT_INCLUDE)/goahead/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/goahead/uemf.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/goahead/uemf.h
+
+$(PROJECT_INCLUDE)/goahead/um.h: um.h $(PROJECT_INCLUDE)/goahead/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/goahead/um.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/goahead/um.h
+
+$(PROJECT_INCLUDE)/goahead/webs.h: webs.h $(PROJECT_INCLUDE)/goahead/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/goahead/webs.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/goahead/webs.h
+
+$(PROJECT_INCLUDE)/goahead/wsIntrn.h: wsIntrn.h $(PROJECT_INCLUDE)/goahead/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/goahead/wsIntrn.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/goahead/wsIntrn.h
+endif
+endif
+
+CLEANFILES += $(PREINSTALL_FILES)
+DISTCLEANFILES = $(PREINSTALL_DIRS)
+
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/httpd/NOTES b/cpukit/httpd/NOTES
new file mode 100644
index 0000000000..e2ef07eb34
--- /dev/null
+++ b/cpukit/httpd/NOTES
@@ -0,0 +1,36 @@
+#
+# $Id$
+#
+
+Notes on merging GoAhead Webs 2.1.4. Eventually RTEMS should be supported
+in their distributions and this directory removed.
+
+Applied patch from Antti P Miettinen <antti.p.miettinen@nokia.com>.
+
+Obtain the original distribution from http://www.goahead.com for
+documentation.
+
+Porting
+=======
+ - added rtems complier flags to uemf.h and misc.c
+ - following source files are distributed with the web server
+ but not currently used by RTEMS
+ [cgi.c, sockGen.c, umui.c, websSSL.c, websda.c]
+
+Tailoring
+=========
+socket.c is RTEMS specific
+
+Renames
+=======
+
+Distributed as This Directory
+============== ================
+base64.c wbase64.c
+page.c webpage.c
+
+RTEMS Specific Additions
+========================
+webmain.c
+rtems_webserver.h
+
diff --git a/cpukit/httpd/asp.c b/cpukit/httpd/asp.c
new file mode 100644
index 0000000000..7d20e683b7
--- /dev/null
+++ b/cpukit/httpd/asp.c
@@ -0,0 +1,321 @@
+/*
+ * asp.c -- Active Server Page Support
+ *
+ * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for usage and redistribution license requirements
+ *
+ * $Id$
+ */
+
+/******************************** Description *********************************/
+
+/*
+ * The ASP module processes ASP pages and executes embedded scripts. It
+ * support an open scripting architecture with in-built support for
+ * Ejscript(TM).
+ */
+
+/********************************* Includes ***********************************/
+
+#include "wsIntrn.h"
+
+/********************************** Locals ************************************/
+
+static sym_fd_t websAspFunctions = -1; /* Symbol table of functions */
+static int aspOpenCount = 0; /* count of apps using this module */
+
+/***************************** Forward Declarations ***************************/
+
+static char_t *strtokcmp(char_t *s1, char_t *s2);
+static char_t *skipWhite(char_t *s);
+
+/************************************* Code ***********************************/
+/*
+ * Create script spaces and commands
+ */
+
+int websAspOpen()
+{
+ if (++aspOpenCount == 1) {
+/*
+ * Create the table for ASP functions
+ */
+ websAspFunctions = symOpen(WEBS_SYM_INIT * 2);
+
+/*
+ * Create standard ASP commands
+ */
+ websAspDefine(T("write"), websAspWrite);
+ }
+ return 0;
+}
+
+/************************************* Code ***********************************/
+/*
+ * Close Asp symbol table.
+ */
+
+void websAspClose()
+{
+ if (--aspOpenCount <= 0) {
+ if (websAspFunctions != -1) {
+ symClose(websAspFunctions);
+ websAspFunctions = -1;
+ }
+ }
+}
+
+/******************************************************************************/
+/*
+ * Process ASP requests and expand all scripting commands. We read the
+ * entire ASP page into memory and then process. If you have really big
+ * documents, it is better to make them plain HTML files rather than ASPs.
+ */
+
+int websAspRequest(webs_t wp, char_t *lpath)
+{
+ websStatType sbuf;
+ char *rbuf;
+ char_t *token, *lang, *result, *path, *ep, *cp, *buf, *nextp;
+ char_t *last;
+ int rc, engine, len, ejid;
+
+ a_assert(websValid(wp));
+ a_assert(lpath && *lpath);
+
+ rc = -1;
+ buf = NULL;
+ rbuf = NULL;
+ engine = EMF_SCRIPT_EJSCRIPT;
+ wp->flags |= WEBS_HEADER_DONE;
+ path = websGetRequestPath(wp);
+
+/*
+ * Create Ejscript instance in case it is needed
+ */
+ ejid = ejOpenEngine(wp->cgiVars, websAspFunctions);
+ if (ejid < 0) {
+ websError(wp, 200, T("Can't create Ejscript engine"));
+ goto done;
+ }
+ ejSetUserHandle(ejid, (int) wp);
+
+ if (websPageStat(wp, lpath, path, &sbuf) < 0) {
+ websError(wp, 200, T("Can't stat %s"), lpath);
+ goto done;
+ }
+
+/*
+ * Create a buffer to hold the ASP file in-memory
+ */
+ len = sbuf.size * sizeof(char);
+ if ((rbuf = balloc(B_L, len + 1)) == NULL) {
+ websError(wp, 200, T("Can't get memory"));
+ goto done;
+ }
+ rbuf[len] = '\0';
+
+ if (websPageReadData(wp, rbuf, len) != len) {
+ websError(wp, 200, T("Cant read %s"), lpath);
+ goto done;
+ }
+ websPageClose(wp);
+
+/*
+ * Convert to UNICODE if necessary.
+ */
+ if ((buf = ballocAscToUni(rbuf, len)) == NULL) {
+ websError(wp, 200, T("Can't get memory"));
+ goto done;
+ }
+
+/*
+ * Scan for the next "<%"
+ */
+ last = buf;
+ rc = 0;
+ while (rc == 0 && *last && ((nextp = gstrstr(last, T("<%"))) != NULL)) {
+ websWriteBlock(wp, last, (nextp - last));
+ nextp = skipWhite(nextp + 2);
+
+/*
+ * Decode the language
+ */
+ token = T("language");
+
+ if ((lang = strtokcmp(nextp, token)) != NULL) {
+ if ((cp = strtokcmp(lang, T("=javascript"))) != NULL) {
+ engine = EMF_SCRIPT_EJSCRIPT;
+ } else {
+ cp = nextp;
+ }
+ nextp = cp;
+ }
+
+/*
+ * Find tailing bracket and then evaluate the script
+ */
+ if ((ep = gstrstr(nextp, T("%>"))) != NULL) {
+
+ *ep = '\0';
+ last = ep + 2;
+ nextp = skipWhite(nextp);
+/*
+ * Handle backquoted newlines
+ */
+ for (cp = nextp; *cp; ) {
+ if (*cp == '\\' && (cp[1] == '\r' || cp[1] == '\n')) {
+ *cp++ = ' ';
+ while (*cp == '\r' || *cp == '\n') {
+ *cp++ = ' ';
+ }
+ } else {
+ cp++;
+ }
+ }
+
+/*
+ * Now call the relevant script engine. Output is done directly
+ * by the ASP script procedure by calling websWrite()
+ */
+ if (*nextp) {
+ result = NULL;
+ if (engine == EMF_SCRIPT_EJSCRIPT) {
+ rc = scriptEval(engine, nextp, &result, ejid);
+ } else {
+ rc = scriptEval(engine, nextp, &result, (int) wp);
+ }
+ if (rc < 0) {
+/*
+ * On an error, discard all output accumulated so far
+ * and store the error in the result buffer. Be careful if the
+ * user has called websError() already.
+ */
+ if (websValid(wp)) {
+ if (result) {
+ websWrite(wp, T("<h2><b>ASP Error: %s</b></h2>\n"),
+ result);
+ websWrite(wp, T("<pre>%s</pre>"), nextp);
+ bfree(B_L, result);
+ } else {
+ websWrite(wp, T("<h2><b>ASP Error</b></h2>\n%s\n"),
+ nextp);
+ }
+ websWrite(wp, T("</body></html>\n"));
+ rc = 0;
+ }
+ goto done;
+ }
+ }
+
+ } else {
+ websError(wp, 200, T("Unterminated script in %s: \n"), lpath);
+ rc = -1;
+ goto done;
+ }
+ }
+/*
+ * Output any trailing HTML page text
+ */
+ if (last && *last && rc == 0) {
+ websWriteBlock(wp, last, gstrlen(last));
+ }
+ rc = 0;
+
+/*
+ * Common exit and cleanup
+ */
+done:
+ if (websValid(wp)) {
+ websPageClose(wp);
+ if (ejid >= 0) {
+ ejCloseEngine(ejid);
+ }
+ }
+ bfreeSafe(B_L, buf);
+ bfreeSafe(B_L, rbuf);
+ return rc;
+}
+
+/******************************************************************************/
+/*
+ * Define an ASP Ejscript function. Bind an ASP name to a C procedure.
+ */
+
+int websAspDefine(char_t *name,
+ int (*fn)(int ejid, webs_t wp, int argc, char_t **argv))
+{
+ return ejSetGlobalFunctionDirect(websAspFunctions, name,
+ (int (*)(int, void*, int, char_t**)) fn);
+}
+
+/******************************************************************************/
+/*
+ * Asp write command. This implemements <% write("text"); %> command
+ */
+
+int websAspWrite(int ejid, webs_t wp, int argc, char_t **argv)
+{
+ int i;
+
+ a_assert(websValid(wp));
+
+ for (i = 0; i < argc; ) {
+ a_assert(argv);
+ if (websWriteBlock(wp, argv[i], gstrlen(argv[i])) < 0) {
+ return -1;
+ }
+ if (++i < argc) {
+ if (websWriteBlock(wp, T(" "), 2) < 0) {
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * strtokcmp -- Find s2 in s1. We skip leading white space in s1.
+ * Return a pointer to the location in s1 after s2 ends.
+ */
+
+static char_t *strtokcmp(char_t *s1, char_t *s2)
+{
+ int len;
+
+ s1 = skipWhite(s1);
+ len = gstrlen(s2);
+ for (len = gstrlen(s2); len > 0 && (tolower(*s1) == tolower(*s2)); len--) {
+ if (*s2 == '\0') {
+ return s1;
+ }
+ s1++;
+ s2++;
+ }
+ if (len == 0) {
+ return s1;
+ }
+ return NULL;
+}
+
+/******************************************************************************/
+/*
+ * Skip white space
+ */
+
+static char_t *skipWhite(char_t *s)
+{
+ a_assert(s);
+
+ if (s == NULL) {
+ return s;
+ }
+ while (*s && gisspace(*s)) {
+ s++;
+ }
+ return s;
+}
+
+/******************************************************************************/
diff --git a/cpukit/httpd/balloc.c b/cpukit/httpd/balloc.c
new file mode 100644
index 0000000000..f43bc90acb
--- /dev/null
+++ b/cpukit/httpd/balloc.c
@@ -0,0 +1,967 @@
+/*
+ * balloc.c -- Block allocation module
+ *
+ * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for usage and redistribution license requirements
+ *
+ * $Id$
+ */
+
+/******************************** Description *********************************/
+
+/*
+ * This module implements a very fast block allocation scheme suitable for
+ * ROMed environments. It maintains block class queues for rapid allocation
+ * and minimal fragmentation. This module does not coalesce blocks. The
+ * storage space may be populated statically or via the traditional malloc
+ * mechanisms. Large blocks greater than the maximum class size may be
+ * allocated from the O/S or run-time system via malloc. To permit the use
+ * of malloc, call bopen with flags set to B_USE_MALLOC (this is the default).
+ * It is recommended that bopen be called first thing in the application.
+ * If it is not, it will be called with default values on the first call to
+ * balloc(). Note that this code is not designed for multi-threading purposes
+ * and it depends on newly declared variables being initialized to zero.
+ */
+
+/********************************* Includes ***********************************/
+
+#define IN_BALLOC
+
+#ifdef UEMF
+ #include "uemf.h"
+#else
+ #include "basic/basicInternal.h"
+#endif
+
+#include <stdarg.h>
+#include <stdlib.h>
+
+#ifndef NO_BALLOC
+/********************************* Defines ************************************/
+
+/*
+ * Define B_STATS if you wish to track memory block and stack usage
+ */
+#ifdef B_STATS
+/*
+ * Optional statistics
+ */
+
+typedef struct {
+ long alloc; /* Block allocation calls */
+ long inuse; /* Blocks in use */
+} bStatsType;
+
+typedef struct {
+ char_t file[FNAMESIZE];
+ long allocated; /* Bytes currently allocated */
+ long count; /* Current block count */
+ long times; /* Count of alloc attempts */
+ long largest; /* largest allocated here */
+ int q;
+} bStatsFileType;
+
+/*
+ * This one is very expensive but great stats
+ */
+typedef struct {
+ void *ptr; /* Pointer to memory */
+ bStatsFileType *who; /* Who allocated the memory */
+} bStatsBlkType;
+
+static bStatsType bStats[B_MAX_CLASS]; /* Per class stats */
+static bStatsFileType bStatsFiles[B_MAX_FILES];/* Per file stats */
+static bStatsBlkType bStatsBlks[B_MAX_BLOCKS];/* Per block stats */
+static int bStatsBlksMax = 0; /* Max block entry */
+static int bStatsFilesMax = 0; /* Max file entry */
+static int bStatsMemInUse = 0; /* Memory currently in use */
+static int bStatsBallocInUse = 0; /* Memory currently balloced */
+static int bStatsMemMax = 0; /* Max memory ever used */
+static int bStatsBallocMax = 0; /* Max memory ever balloced */
+static void *bStackMin = (void*) -1;/* Miniumum stack position */
+static void *bStackStart; /* Starting stack position */
+static int bStatsMemMalloc = 0; /* Malloced memory */
+#endif /* B_STATS */
+
+/*
+ * ROUNDUP4(size) returns the next higher integer value of size that is
+ * divisible by 4, or the value of size if size is divisible by 4.
+ * ROUNDUP4() is used in aligning memory allocations on 4-byte boundaries.
+ *
+ * Note: ROUNDUP4() is only required on some operating systems (IRIX).
+ */
+
+#define ROUNDUP4(size) ((size) % 4) ? (size) + (4 - ((size) % 4)) : (size)
+
+/********************************** Locals ************************************/
+/*
+ * bQhead blocks are created as the original memory allocation is freed up.
+ * See bfree.
+ */
+static bType *bQhead[B_MAX_CLASS]; /* Per class block q head */
+static char *bFreeBuf; /* Pointer to free memory */
+static char *bFreeNext; /* Pointer to next free mem */
+static int bFreeSize; /* Size of free memory */
+static int bFreeLeft; /* Size of free left for use */
+static int bFlags = B_USE_MALLOC; /* Default to auto-malloc */
+static int bopenCount = 0; /* Num tasks using balloc */
+
+/*************************** Forward Declarations *****************************/
+
+#ifdef B_STATS
+static void bStatsAlloc(B_ARGS_DEC, void *ptr, int q, int size);
+static void bStatsFree(B_ARGS_DEC, void *ptr, int q, int size);
+static void bstatsWrite(int handle, char_t *fmt, ...);
+static int bStatsFileSort(const void *cp1, const void *cp2);
+#endif /* B_STATS */
+
+#if (defined (B_FILL) || defined (B_VERIFY_CAUSES_SEVERE_OVERHEAD))
+static void bFillBlock(void *buf, int bufsize);
+#endif
+
+#ifdef B_VERIFY_CAUSES_SEVERE_OVERHEAD
+static void verifyUsedBlock(bType *bp, int q);
+static void verifyFreeBlock(bType *bp, int q);
+void verifyBallocSpace();
+#endif
+
+static int ballocGetSize(int size, int *q);
+
+/********************************** Code **************************************/
+/*
+ * Initialize the balloc module. bopen should be called the very first thing
+ * after the application starts and bclose should be called the last thing
+ * before exiting. If bopen is not called, it will be called on the first
+ * allocation with default values. "buf" points to memory to use of size
+ * "bufsize". If buf is NULL, memory is allocated using malloc. flags may
+ * be set to B_USE_MALLOC if using malloc is okay. This routine will allocate
+ * an initial buffer of size bufsize for use by the application.
+ */
+
+int bopen(void *buf, int bufsize, int flags)
+{
+ bFlags = flags;
+
+#ifdef BASTARD_TESTING
+ srand(time(0L));
+#endif /* BASTARD_TESTING */
+
+/*
+ * If bopen already called by a shared process, just increment the count
+ * and return;
+ */
+ if (++bopenCount > 1) {
+ return 0;
+ }
+
+ if (buf == NULL) {
+ if (bufsize == 0) {
+ bufsize = B_DEFAULT_MEM;
+ }
+#ifdef IRIX
+ bufsize = ROUNDUP4(bufsize);
+#endif
+ if ((buf = malloc(bufsize)) == NULL) {
+ return -1;
+ }
+#ifdef B_STATS
+ bStatsMemMalloc += bufsize;
+#endif
+ } else {
+ bFlags |= B_USER_BUF;
+ }
+
+ bFreeSize = bFreeLeft = bufsize;
+ bFreeBuf = bFreeNext = buf;
+ memset(bQhead, 0, sizeof(bQhead));
+#if (defined (B_FILL) || defined (B_VERIFY_CAUSES_SEVERE_OVERHEAD))
+ bFillBlock(buf, bufsize);
+#endif
+#ifdef B_STATS
+ bStackStart = &buf;
+#endif
+#ifdef B_VERIFY_CAUSES_SEVERE_OVERHEAD
+ verifyFreeBlock(buf, bufsize);
+#endif
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Close down the balloc module and free all malloced memory.
+ */
+
+void bclose()
+{
+#ifdef B_VERIFY_CAUSES_SEVERE_OVERHEAD
+ verifyBallocSpace();
+#endif
+ if (--bopenCount <= 0 && !(bFlags & B_USER_BUF)) {
+ free(bFreeBuf);
+ bopenCount = 0;
+ }
+}
+
+/******************************************************************************/
+/*
+ * Allocate a block of the requested size. First check the block
+ * queues for a suitable one.
+ */
+
+void *balloc(B_ARGS_DEC, int size)
+{
+ bType *bp;
+ int q, memSize;
+
+/*
+ * Call bopen with default values if the application has not yet done so
+ */
+ if (bFreeBuf == NULL) {
+ if (bopen(NULL, B_DEFAULT_MEM, 0) < 0) {
+ return NULL;
+ }
+ }
+#ifdef B_VERIFY_CAUSES_SEVERE_OVERHEAD
+ verifyBallocSpace();
+#endif
+ if (size < 0) {
+ return NULL;
+ }
+
+#ifdef BASTARD_TESTING
+ if (rand() == 0x7fff) {
+ return NULL;
+ }
+#endif /* BASTARD_TESTING */
+
+
+ memSize = ballocGetSize(size, &q);
+
+ if (q >= B_MAX_CLASS) {
+/*
+ * Size if bigger than the maximum class. Malloc if use has been okayed
+ */
+ if (bFlags & B_USE_MALLOC) {
+#ifdef B_STATS
+ bstats(0, NULL);
+#endif
+#ifdef IRIX
+ memSize = ROUNDUP4(memSize);
+#endif
+ bp = (bType*) malloc(memSize);
+ if (bp == NULL) {
+ traceRaw(T("B: malloc failed\n"));
+ return NULL;
+ }
+#ifdef B_STATS
+ bStatsMemMalloc += memSize;
+#endif
+#if (defined (B_FILL) || defined (B_VERIFY_CAUSES_SEVERE_OVERHEAD))
+ bFillBlock(bp, memSize);
+#endif
+
+ } else {
+ traceRaw(T("B: malloc failed\n"));
+ return NULL;
+ }
+
+/*
+ * the u.size is the actual size allocated for data
+ */
+ bp->u.size = memSize - sizeof(bType);
+ bp->flags = B_MALLOCED;
+
+ } else if ((bp = bQhead[q]) != NULL) {
+/*
+ * Take first block off the relevant q if non-empty
+ */
+ bQhead[q] = bp->u.next;
+#ifdef B_VERIFY_CAUSES_SEVERE_OVERHEAD
+ verifyFreeBlock(bp, q);
+#endif
+#if (defined (B_FILL) || defined (B_VERIFY_CAUSES_SEVERE_OVERHEAD))
+ bFillBlock(bp, memSize);
+#endif
+ bp->u.size = memSize - sizeof(bType);
+ bp->flags = 0;
+
+ } else {
+ if (bFreeLeft > memSize) {
+/*
+ * The q was empty, and the free list has spare memory so
+ * create a new block out of the primary free block
+ */
+ bp = (bType*) bFreeNext;
+#ifdef B_VERIFY_CAUSES_SEVERE_OVERHEAD
+ verifyFreeBlock(bp, q);
+#endif
+ bFreeNext += memSize;
+ bFreeLeft -= memSize;
+#if (defined (B_FILL) || defined (B_VERIFY_CAUSES_SEVERE_OVERHEAD))
+ bFillBlock(bp, memSize);
+#endif
+ bp->u.size = memSize - sizeof(bType);
+ bp->flags = 0;
+
+ } else if (bFlags & B_USE_MALLOC) {
+#ifdef B_STATS
+ static int once = 0;
+ if (once++ == 0) {
+ bstats(0, NULL);
+ }
+#endif
+/*
+ * Nothing left on the primary free list, so malloc a new block
+ */
+#ifdef IRIX
+ memSize = ROUNDUP4(memSize);
+#endif
+ if ((bp = (bType*) malloc(memSize)) == NULL) {
+ traceRaw(T("B: malloc failed\n"));
+ return NULL;
+ }
+#ifdef B_STATS
+ bStatsMemMalloc += memSize;
+#endif
+#if (defined (B_FILL) || defined (B_VERIFY_CAUSES_SEVERE_OVERHEAD))
+ bFillBlock(bp, memSize);
+#endif
+ bp->u.size = memSize - sizeof(bType);
+ bp->flags = B_MALLOCED;
+
+ } else {
+ traceRaw(T("B: malloc failed\n"));
+ return NULL;
+ }
+ }
+
+#ifdef B_STATS
+ bStatsAlloc(B_ARGS, bp, q, memSize);
+#endif
+ bp->flags |= B_INTEGRITY;
+
+/*
+ * The following is a good place to put a breakpoint when trying to reduce
+ * determine and reduce maximum memory use.
+ */
+#if 0
+#ifdef B_STATS
+ if (bStatsBallocInUse == bStatsBallocMax) {
+ bstats(0, NULL);
+ }
+#endif
+#endif
+ return (void*) ((char*) bp + sizeof(bType));
+}
+
+/******************************************************************************/
+/*
+ * Free a block back to the relevant free q. We don't free back to the O/S
+ * or run time system unless the block is greater than the maximum class size.
+ * We also do not coalesce blocks.
+ */
+
+void bfree(B_ARGS_DEC, void *mp)
+{
+ bType *bp;
+ int q, memSize;
+
+#ifdef B_VERIFY_CAUSES_SEVERE_OVERHEAD
+ verifyBallocSpace();
+#endif
+ bp = (bType*) ((char*) mp - sizeof(bType));
+
+ a_assert((bp->flags & B_INTEGRITY_MASK) == B_INTEGRITY);
+
+ if ((bp->flags & B_INTEGRITY_MASK) != B_INTEGRITY) {
+ return;
+ }
+
+ memSize = ballocGetSize(bp->u.size, &q);
+
+#ifdef B_VERIFY_CAUSES_SEVERE_OVERHEAD
+ verifyUsedBlock(bp,q);
+#endif
+#ifdef B_STATS
+ bStatsFree(B_ARGS, bp, q, bp->u.size+sizeof(bType));
+#endif
+ if (bp->flags & B_MALLOCED) {
+ free(bp);
+ return;
+ }
+
+#ifdef B_VERIFY_CAUSES_SEVERE_OVERHEAD
+ bFillBlock(bp, memSize);
+#endif
+
+/*
+ * Simply link onto the head of the relevant q
+ */
+ bp->u.next = bQhead[q];
+ bQhead[q] = bp;
+
+ bp->flags = B_FILL_WORD;
+}
+
+/******************************************************************************/
+/*
+ * Safe free
+ */
+
+void bfreeSafe(B_ARGS_DEC, void *mp)
+{
+ if (mp) {
+ bfree(B_ARGS, mp);
+ }
+}
+
+/******************************************************************************/
+#ifdef UNICODE
+/*
+ * Duplicate a string, allow NULL pointers and then dup an empty string.
+ */
+
+char *bstrdupA(B_ARGS_DEC, char *s)
+{
+ char *cp;
+ int len;
+
+ if (s == NULL) {
+ s = "";
+ }
+ len = strlen(s) + 1;
+ if (cp = balloc(B_ARGS, len)) {
+ strcpy(cp, s);
+ }
+ return cp;
+}
+
+#endif /* UNICODE */
+/******************************************************************************/
+/*
+ * Duplicate an ascii string, allow NULL pointers and then dup an empty string.
+ * If UNICODE, bstrdup above works with wide chars, so we need this routine
+ * for ascii strings.
+ */
+
+char_t *bstrdup(B_ARGS_DEC, char_t *s)
+{
+ char_t *cp;
+ int len;
+
+ if (s == NULL) {
+ s = T("");
+ }
+ len = gstrlen(s) + 1;
+ if ((cp = balloc(B_ARGS, len * sizeof(char_t))) != NULL) {
+ gstrcpy(cp, s);
+ }
+ return cp;
+}
+
+/******************************************************************************/
+/*
+ * Reallocate a block. Allow NULL pointers and just do a malloc.
+ * Note: if the realloc fails, we return NULL and the previous buffer is
+ * preserved.
+ */
+
+void *brealloc(B_ARGS_DEC, void *mp, int newsize)
+{
+ bType *bp;
+ void *newbuf;
+
+ if (mp == NULL) {
+ return balloc(B_ARGS, newsize);
+ }
+ bp = (bType*) ((char*) mp - sizeof(bType));
+ a_assert((bp->flags & B_INTEGRITY_MASK) == B_INTEGRITY);
+
+/*
+ * If the allocated memory already has enough room just return the previously
+ * allocated address.
+ */
+ if (bp->u.size >= newsize) {
+ return mp;
+ }
+ if ((newbuf = balloc(B_ARGS, newsize)) != NULL) {
+ memcpy(newbuf, mp, bp->u.size);
+ bfree(B_ARGS, mp);
+ }
+ return newbuf;
+}
+
+/******************************************************************************/
+/*
+ * Find the size of the block to be balloc'ed. It takes in a size, finds the
+ * smallest binary block it fits into, adds an overhead amount and returns.
+ * q is the binary size used to keep track of block sizes in use. Called
+ * from both balloc and bfree.
+ */
+
+static int ballocGetSize(int size, int *q)
+{
+ int mask;
+
+ mask = (size == 0) ? 0 : (size-1) >> B_SHIFT;
+ for (*q = 0; mask; mask >>= 1) {
+ *q = *q + 1;
+ }
+ return ((1 << (B_SHIFT + *q)) + sizeof(bType));
+}
+
+/******************************************************************************/
+#if (defined (B_FILL) || defined (B_VERIFY_CAUSES_SEVERE_OVERHEAD))
+/*
+ * Fill the block (useful during development to catch zero fill assumptions)
+ */
+
+static void bFillBlock(void *buf, int bufsize)
+{
+ memset(buf, B_FILL_CHAR, bufsize);
+}
+#endif
+
+/******************************************************************************/
+#ifdef B_STATS
+/*
+ * Statistics. Do output via calling the writefn callback function with
+ * "handle" as the output file handle.
+ */
+
+void bstats(int handle, void (*writefn)(int handle, char_t *fmt, ...))
+{
+ bStatsFileType *fp, *files;
+ bStatsBlkType *blkp;
+ bType *bp;
+ char_t *cp;
+ int q, count, mem, total, len;
+ static int recurseProtect = 0;
+
+ if (recurseProtect++ > 0) {
+ recurseProtect--;
+ return;
+ }
+
+ if (writefn == NULL) {
+ writefn = bstatsWrite;
+ }
+
+/*
+ * Print stats for each memory block
+ */
+ (*writefn)(handle, T("\nMemory Stats\n"));
+
+/*
+ * The following tabular format is now used for the output.
+ * Q Size Free Bytes Inuse Bytes Allocs
+ * dd ddddd ddd ddddd dddd ddddd dddd
+ */
+ (*writefn)(handle, " Q Size Free Bytes Inuse Bytes Allocs\n");
+
+ total = 0;
+ for (q = 0; q < B_MAX_CLASS; q++) {
+ count = 0;
+ for (bp = bQhead[q]; bp; bp = bp->u.next) {
+ count++;
+ }
+ mem = count * (1 << (q + B_SHIFT));
+ total += mem;
+ (*writefn)(handle,
+ T("%2d %5d %4d %6d %4d %5d %4d\n"),
+ q, 1 << (q + B_SHIFT), count, mem, bStats[q].inuse,
+ bStats[q].inuse * (1 << (q + B_SHIFT)), bStats[q].alloc);
+ }
+
+ (*writefn)(handle, T("\n"));
+
+/*
+ * Print summary stats
+ *
+ * bFreeSize Initial memory reserved with bopen call
+ * bStatsMemMalloc memory from calls to system MALLOC
+ * bStatsMemMax
+ * bStatsBallocMax largest amount of memory from balloc calls
+ * bStatsMemInUse
+ * bStatsBallocInUse present balloced memory being used
+ * bStatsBlksMax);
+ * bStackStart
+ * bStackMin);
+ * total);
+ * bFreeLeft);
+ *
+ */
+ (*writefn)(handle, T("Initial free list size %7d\n"), bFreeSize);
+ (*writefn)(handle, T("Max memory malloced %7d\n"), bStatsMemMalloc);
+ (*writefn)(handle, T("Max memory ever used %7d\n"), bStatsMemMax);
+ (*writefn)(handle, T("Max memory ever balloced %7d\n"), bStatsBallocMax);
+ (*writefn)(handle, T("Memory currently in use %7d\n"), bStatsMemInUse);
+ (*writefn)(handle, T("Memory currently balloced %7d\n"), bStatsBallocInUse);
+ (*writefn)(handle, T("Max blocks allocated %7d\n"), bStatsBlksMax);
+ (*writefn)(handle, T("Maximum stack used %7d\n"),
+ (int) bStackStart - (int) bStackMin);
+
+ (*writefn)(handle, T("Free memory on all queues %7d\n"), total);
+ (*writefn)(handle, T("Free list buffer left %7d\n"), bFreeLeft);
+ (*writefn)(handle, T("Total free memory %7d\n"), bFreeLeft + total);
+
+/*
+ * Print per file allocation stats. Sort the copied table.
+ */
+ len = sizeof(bStatsFileType) * B_MAX_FILES;
+ files = malloc(len);
+ if (files == NULL) {
+ (*writefn)(handle, T("Can't allocate stats memory\n"));
+ recurseProtect--;
+ return;
+ }
+ memcpy(files, bStatsFiles, len);
+ qsort(files, bStatsFilesMax, sizeof(bStatsFileType), bStatsFileSort);
+
+ (*writefn)(handle, T("\nMemory Currently Allocated\n"));
+ total = 0;
+ (*writefn)(handle,
+ T(" bytes, blocks in use, total times,")
+ T("largest, q\n"));
+
+ for (fp = files; fp < &files[bStatsFilesMax]; fp++) {
+ if (fp->file[0]) {
+ (*writefn)(handle, T("%18s, %7d, %5d, %6d, %7d,%4d\n"),
+ fp->file, fp->allocated, fp->count, fp->times, fp->largest,
+ fp->q);
+ total += fp->allocated;
+ }
+ }
+ (*writefn)(handle, T("\nTotal allocated %7d\n\n"), total);
+
+/*
+ * Dump the actual strings
+ */
+ (*writefn)(handle, T("\nStrings\n"));
+ for (blkp = &bStatsBlks[bStatsBlksMax - 1]; blkp >= bStatsBlks; blkp--) {
+ if (blkp->ptr) {
+ cp = (char_t*) ((char*) blkp->ptr + sizeof(bType));
+ fp = blkp->who;
+ if (gisalnum(*cp)) {
+ (*writefn)(handle, T("%-50s allocated by %s\n"), cp,
+ fp->file);
+ }
+ }
+ }
+ free(files);
+ recurseProtect--;
+}
+
+/******************************************************************************/
+/*
+ * File sort function. Used to sort per file stats
+ */
+
+static int bStatsFileSort(const void *cp1, const void *cp2)
+{
+ bStatsFileType *s1, *s2;
+
+ s1 = (bStatsFileType*) cp1;
+ s2 = (bStatsFileType*) cp2;
+
+ if (s1->allocated < s2->allocated)
+ return -1;
+ else if (s1->allocated == s2->allocated)
+ return 0;
+ return 1;
+}
+
+/******************************************************************************/
+/*
+ * Accumulate allocation statistics
+ */
+
+static void bStatsAlloc(B_ARGS_DEC, void *ptr, int q, int size)
+{
+ int memSize;
+ bStatsFileType *fp;
+ bStatsBlkType *bp;
+ char_t name[FNAMESIZE + 10];
+
+ gsprintf(name, T("%s:%d"), B_ARGS);
+
+ bStats[q].alloc++;
+ bStats[q].inuse++;
+ bStatsMemInUse += size;
+ if (bStatsMemInUse > bStatsMemMax) {
+ bStatsMemMax = bStatsMemInUse;
+ }
+ memSize = (1 << (B_SHIFT + q)) + sizeof(bType);
+ bStatsBallocInUse += memSize;
+ if (bStatsBallocInUse > bStatsBallocMax) {
+ bStatsBallocMax = bStatsBallocInUse;
+ }
+
+/*
+ * Track maximum stack usage. Assumes a stack growth down. Approximate as
+ * we only measure this on block allocation.
+ */
+ if ((void*) &file < bStackMin) {
+ bStackMin = (void*) &file;
+ }
+
+/*
+ * Find the file and adjust the stats for this file
+ */
+ for (fp = bStatsFiles; fp < &bStatsFiles[bStatsFilesMax]; fp++) {
+ if (fp->file[0] == file[0] && gstrcmp(fp->file, name) == 0) {
+ fp->allocated += size;
+ fp->count++;
+ fp->times++;
+ if (fp->largest < size) {
+ fp->largest = size;
+ fp->q = q;
+ }
+ break;
+ }
+ }
+
+/*
+ * New entry: find the first free slot and create a new entry
+ */
+ if (fp >= &bStatsFiles[bStatsFilesMax]) {
+ for (fp = bStatsFiles; fp < &bStatsFiles[B_MAX_FILES]; fp++) {
+ if (fp->file[0] == '\0') {
+ gstrncpy(fp->file, name, TSZ(fp->file));
+ fp->allocated += size;
+ fp->count++;
+ fp->times++;
+ fp->largest = size;
+ fp->q = q;
+ if ((fp - bStatsFiles) >= bStatsFilesMax) {
+ bStatsFilesMax = (fp - bStatsFiles) + 1;
+ }
+ break;
+ }
+ }
+ }
+
+/*
+ * Update the per block stats. Allocate a new slot.
+ */
+ for (bp = bStatsBlks; bp < &bStatsBlks[B_MAX_BLOCKS]; bp++) {
+ if (bp->ptr == NULL) {
+ bp->ptr = ptr;
+ bp->who = fp;
+ if ((bp - bStatsBlks) >= bStatsBlksMax) {
+ bStatsBlksMax = (bp - bStatsBlks) + 1;
+ }
+ break;
+ }
+ }
+}
+
+/******************************************************************************/
+/*
+ * Free statistics
+ */
+
+static void bStatsFree(B_ARGS_DEC, void *ptr, int q, int size)
+{
+ int memSize;
+ bStatsFileType *fp;
+ bStatsBlkType *bp;
+
+ memSize = (1 << (B_SHIFT + q)) + sizeof(bType);
+ bStatsMemInUse -= size;
+ bStatsBallocInUse -= memSize;
+ bStats[q].inuse--;
+
+/*
+ * Update the per block stats. Try from the end first
+ */
+ for (bp = &bStatsBlks[bStatsBlksMax - 1]; bp >= bStatsBlks; bp--) {
+ if (bp->ptr == ptr) {
+ bp->ptr = NULL;
+ fp = bp->who;
+ bp->who = NULL;
+ fp->allocated -= size;
+ fp->count--;
+ return;
+ }
+ }
+}
+
+/******************************************************************************/
+/*
+ * Default output function. Just send to trace channel.
+ */
+
+#undef sprintf
+static void bstatsWrite(int handle, char_t *fmt, ...)
+{
+ va_list args;
+ char_t buf[BUF_MAX];
+
+ va_start(args, fmt);
+ vsprintf(buf, fmt, args);
+ va_end(args);
+ traceRaw(buf);
+}
+
+
+#else /* not B_STATS */
+/******************************************************************************/
+/*
+ * Dummy bstats for external calls that aren't protected by #if B_STATS.
+ */
+
+void bstats(int handle, void (*writefn)(int handle, char_t *fmt, ...))
+{
+}
+#endif /* B_STATS */
+
+/******************************************************************************/
+#ifdef B_VERIFY_CAUSES_SEVERE_OVERHEAD
+/*
+ * The following routines verify the integrity of the balloc memory space.
+ * These functions use the B_FILL feature. Corruption is defined
+ * as bad integrity flags in allocated blocks or data other than B_FILL_CHAR
+ * being found anywhere in the space which is unallocated and that is not a
+ * next pointer in the free queues. a_assert is called if any corruption is
+ * found. CAUTION: These functions add severe processing overhead and should
+ * only be used when searching for a tough corruption problem.
+ */
+
+/******************************************************************************/
+/*
+ * verifyUsedBlock verifies that a block which was previously allocated is
+ * still uncorrupted.
+ */
+
+static void verifyUsedBlock(bType *bp, int q)
+{
+ int memSize, size;
+ char *p;
+
+ memSize = (1 << (B_SHIFT + q)) + sizeof(bType);
+ a_assert((bp->flags & ~B_MALLOCED) == B_INTEGRITY);
+ size = bp->u.size;
+ for (p = ((char *)bp)+sizeof(bType)+size; p < ((char*)bp)+memSize; p++) {
+ a_assert(*p == B_FILL_CHAR);
+ }
+}
+
+/******************************************************************************/
+/*
+ * verifyFreeBlock verifies that a previously free'd block in one of the queues
+ * is still uncorrupted.
+ */
+
+static void verifyFreeBlock(bType *bp, int q)
+{
+ int memSize;
+ char *p;
+
+ memSize = (1 << (B_SHIFT + q)) + sizeof(bType);
+ for (p = ((char *)bp)+sizeof(void*); p < ((char*)bp)+memSize; p++) {
+ a_assert(*p == B_FILL_CHAR);
+ }
+ bp = (bType *)p;
+ a_assert((bp->flags & ~B_MALLOCED) == B_INTEGRITY ||
+ bp->flags == B_FILL_WORD);
+}
+
+/******************************************************************************/
+/*
+ * verifyBallocSpace reads through the entire balloc memory space and
+ * verifies that all allocated blocks are uncorrupted and that, with the
+ * exception of free list next pointers, all other unallocated space is
+ * filled with B_FILL_CHAR.
+ */
+
+void verifyBallocSpace()
+{
+ int q;
+ char *p;
+ bType *bp;
+
+/*
+ * First verify all the free blocks.
+ */
+ for (q = 0; q < B_MAX_CLASS; q++) {
+ for (bp = bQhead[q]; bp != NULL; bp = bp->u.next) {
+ verifyFreeBlock(bp, q);
+ }
+ }
+
+/*
+ * Now verify other space
+ */
+ p = bFreeBuf;
+ while (p < (bFreeBuf + bFreeSize)) {
+ bp = (bType *)p;
+ if (bp->u.size > 0xFFFFF) {
+ p += sizeof(bp->u);
+ while (p < (bFreeBuf + bFreeSize) && *p == B_FILL_CHAR) {
+ p++;
+ }
+ } else {
+ a_assert(((bp->flags & ~B_MALLOCED) == B_INTEGRITY) ||
+ bp->flags == B_FILL_WORD);
+ p += (sizeof(bType) + bp->u.size);
+ while (p < (bFreeBuf + bFreeSize) && *p == B_FILL_CHAR) {
+ p++;
+ }
+ }
+ }
+}
+#endif /* B_VERIFY_CAUSES_SEVERE_OVERHEAD */
+
+/******************************************************************************/
+
+#else /* NO_BALLOC */
+int bopen(void *buf, int bufsize, int flags)
+{
+ return 0;
+}
+
+/******************************************************************************/
+
+void bclose()
+{
+}
+
+/******************************************************************************/
+
+void bstats(int handle, void (*writefn)(int handle, char_t *fmt, ...))
+{
+}
+
+/******************************************************************************/
+
+char_t *bstrdupNoBalloc(char_t *s)
+{
+#ifdef UNICODE
+ if (s) {
+ return wcsdup(s);
+ } else {
+ return wcsdup(T(""));
+ }
+#else
+ return bstrdupANoBalloc(s);
+#endif
+}
+
+/******************************************************************************/
+
+char *bstrdupANoBalloc(char *s)
+{
+ char* buf;
+
+ if (s == NULL) {
+ s = "";
+ }
+ buf = malloc(strlen(s)+1);
+ strcpy(buf, s);
+ return buf;
+}
+
+#endif /* NO_BALLOC */
+/******************************************************************************/
diff --git a/cpukit/httpd/cgi.c b/cpukit/httpd/cgi.c
new file mode 100644
index 0000000000..c2328eab6e
--- /dev/null
+++ b/cpukit/httpd/cgi.c
@@ -0,0 +1,331 @@
+/*
+ * cgi.c -- CGI processing (for the GoAhead Web server
+ *
+ * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for usage and redistribution license requirements
+ *
+ * $Id$
+ */
+
+/********************************** Description *******************************/
+/*
+ * This module implements the /cgi-bin handler. CGI processing differs from
+ * goforms processing in that each CGI request is executed as a separate
+ * process, rather than within the webserver process. For each CGI request the
+ * environment of the new process must be set to include all the CGI variables
+ * and its standard input and output must be directed to the socket. This
+ * is done using temporary files.
+ */
+
+/*********************************** Includes *********************************/
+#include "wsIntrn.h"
+#ifdef UEMF
+ #include "uemf.h"
+#else
+ #include "basic/basicInternal.h"
+#endif
+
+/************************************ Locals **********************************/
+typedef struct { /* Struct for CGI tasks which have completed */
+ webs_t wp; /* pointer to session websRec */
+ char_t *stdIn; /* file desc. for task's temp input fd */
+ char_t *stdOut; /* file desc. for task's temp output fd */
+ char_t *cgiPath; /* path to executable process file */
+ char_t **argp; /* pointer to buf containing argv tokens */
+ char_t **envp; /* pointer to array of environment strings */
+ int handle; /* process handle of the task */
+ long fplacemark; /* seek location for CGI output file */
+} cgiRec;
+static cgiRec **cgiList; /* hAlloc chain list of wp's to be closed */
+static int cgiMax; /* Size of hAlloc list */
+
+/************************************* Code ***********************************/
+
+/*
+ * Process a form request. Returns 1 always to indicate it handled the URL
+ */
+int websCgiHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
+ char_t *url, char_t *path, char_t* query)
+{
+ cgiRec *cgip;
+ sym_t *s;
+ char_t cgiBuf[FNAMESIZE], *stdIn, *stdOut, cwd[FNAMESIZE];
+ char_t *cp, *cgiName, *cgiPath, **argp, **envp, **ep;
+ int n, envpsize, argpsize, pHandle, cid;
+ a_assert(websValid(wp));
+ a_assert(url && *url);
+ a_assert(path && *path == '/');
+ websStats.cgiHits++;
+/*
+ * Extract the form name and then build the full path name. The form
+ * name will follow the first '/' in path.
+ */
+ gstrncpy(cgiBuf, path, TSZ(cgiBuf));
+ if ((cgiName = gstrchr(&cgiBuf[1], '/')) == NULL) {
+ websError(wp, 200, T("Missing CGI name"));
+ return 1;
+ }
+ cgiName++;
+ if ((cp = gstrchr(cgiName, '/')) != NULL) {
+ *cp = '\0';
+ }
+ fmtAlloc(&cgiPath, FNAMESIZE, T("%s/%s/%s"), websGetDefaultDir(),
+ CGI_BIN, cgiName);
+#ifndef VXWORKS
+/*
+ * See if the file exists and is executable. If not error out.
+ * Don't do this step for VxWorks, since the module may already
+ * be part of the OS image, rather than in the file system.
+ */
+ {
+ gstat_t sbuf;
+ if (gstat(cgiPath, &sbuf) != 0 || (sbuf.st_mode & S_IFREG) == 0) {
+ websError(wp, 200, T("CGI process file does not exist"));
+ bfree(B_L, cgiPath);
+ return 1;
+ }
+#if (defined (WIN) || defined (CE))
+ if (gstrstr(cgiPath, T(".exe")) == NULL &&
+ gstrstr(cgiPath, T(".bat")) == NULL) {
+#elif (defined (NW))
+ if (gstrstr(cgiPath, T(".nlm")) == NULL) {
+#else
+ if (gaccess(cgiPath, X_OK) != 0) {
+#endif /* WIN || CE */
+ websError(wp, 200, T("CGI process file is not executable"));
+ bfree(B_L, cgiPath);
+ return 1;
+ }
+ }
+#endif /* ! VXWORKS */
+
+
+/*
+ * Get the CWD for resetting after launching the child process CGI
+ */
+ ggetcwd(cwd, FNAMESIZE);
+/*
+ * Retrieve the directory of the child process CGI
+ */
+ if ((cp = gstrrchr(cgiPath, '/')) != NULL) {
+ *cp = '\0';
+ gchdir(cgiPath);
+ *cp = '/';
+ }
+/*
+ * Build command line arguments. Only used if there is no non-encoded
+ * = character. This is indicative of a ISINDEX query. POST separators
+ * are & and others are +. argp will point to a balloc'd array of
+ * pointers. Each pointer will point to substring within the
+ * query string. This array of string pointers is how the spawn or
+ * exec routines expect command line arguments to be passed. Since
+ * we don't know ahead of time how many individual items there are in
+ * the query string, the for loop includes logic to grow the array
+ * size via brealloc.
+ */
+ argpsize = 10;
+ argp = balloc(B_L, argpsize * sizeof(char_t *));
+ *argp = cgiPath;
+ n = 1;
+ if (gstrchr(query, '=') == NULL) {
+ websDecodeUrl(query, query, gstrlen(query));
+ for (cp = gstrtok(query, T(" ")); cp != NULL; ) {
+ *(argp+n) = cp;
+ n++;
+ if (n >= argpsize) {
+ argpsize *= 2;
+ argp = brealloc(B_L, argp, argpsize * sizeof(char_t *));
+ }
+ cp = gstrtok(NULL, T(" "));
+ }
+ }
+ *(argp+n) = NULL;
+/*
+ * Add all CGI variables to the environment strings to be passed
+ * to the spawned CGI process. This includes a few we don't
+ * already have in the symbol table, plus all those that are in
+ * the cgiVars symbol table. envp will point to a balloc'd array of
+ * pointers. Each pointer will point to a balloc'd string containing
+ * the keyword value pair in the form keyword=value. Since we don't
+ * know ahead of time how many environment strings there will be the
+ * for loop includes logic to grow the array size via brealloc.
+ */
+ envpsize = WEBS_SYM_INIT;
+ envp = balloc(B_L, envpsize * sizeof(char_t *));
+ n = 0;
+ fmtAlloc(envp+n, FNAMESIZE, T("%s=%s"),T("PATH_TRANSLATED"), cgiPath);
+ n++;
+ fmtAlloc(envp+n, FNAMESIZE, T("%s=%s/%s"),T("SCRIPT_NAME"),
+ CGI_BIN, cgiName);
+ n++;
+ fmtAlloc(envp+n, FNAMESIZE, T("%s=%s"),T("REMOTE_USER"), wp->userName);
+ n++;
+ fmtAlloc(envp+n, FNAMESIZE, T("%s=%s"),T("AUTH_TYPE"), wp->authType);
+ n++;
+ for (s = symFirst(wp->cgiVars); s != NULL; s = symNext(wp->cgiVars)) {
+ if (s->content.valid && s->content.type == string &&
+ gstrcmp(s->name.value.string, T("REMOTE_HOST")) != 0 &&
+ gstrcmp(s->name.value.string, T("HTTP_AUTHORIZATION")) != 0) {
+ fmtAlloc(envp+n, FNAMESIZE, T("%s=%s"), s->name.value.string,
+ s->content.value.string);
+ n++;
+ if (n >= envpsize) {
+ envpsize *= 2;
+ envp = brealloc(B_L, envp, envpsize * sizeof(char_t *));
+ }
+ }
+ }
+ *(envp+n) = NULL;
+/*
+ * Create temporary file name(s) for the child's stdin and stdout.
+ * For POST data the stdin temp file (and name) should already exist.
+ */
+ if (wp->cgiStdin == NULL) {
+ wp->cgiStdin = websGetCgiCommName();
+ }
+ stdIn = wp->cgiStdin;
+ stdOut = websGetCgiCommName();
+/*
+ * Now launch the process. If not successful, do the cleanup of resources.
+ * If successful, the cleanup will be done after the process completes.
+ */
+ if ((pHandle = websLaunchCgiProc(cgiPath, argp, envp, stdIn, stdOut))
+ == -1) {
+ websError(wp, 200, T("failed to spawn CGI task"));
+ for (ep = envp; *ep != NULL; ep++) {
+ bfreeSafe(B_L, *ep);
+ }
+ bfreeSafe(B_L, cgiPath);
+ bfreeSafe(B_L, argp);
+ bfreeSafe(B_L, envp);
+ bfreeSafe(B_L, stdOut);
+ } else {
+/*
+ * If the spawn was successful, put this wp on a queue to be
+ * checked for completion.
+ */
+ cid = hAllocEntry((void***) &cgiList, &cgiMax, sizeof(cgiRec));
+ cgip = cgiList[cid];
+ cgip->handle = pHandle;
+ cgip->stdIn = stdIn;
+ cgip->stdOut = stdOut;
+ cgip->cgiPath = cgiPath;
+ cgip->argp = argp;
+ cgip->envp = envp;
+ cgip->wp = wp;
+ cgip->fplacemark = 0;
+ websTimeoutCancel(wp);
+ }
+/*
+ * Restore the current working directory after spawning child CGI
+ */
+ gchdir(cwd);
+ return 1;
+}
+
+
+
+/******************************************************************************/
+/*
+ * Any entry in the cgiList need to be checked to see if it has
+ */
+void websCgiGatherOutput (cgiRec *cgip)
+{
+ gstat_t sbuf;
+ char_t cgiBuf[FNAMESIZE];
+ if ((gstat(cgip->stdOut, &sbuf) == 0) &&
+ (sbuf.st_size > cgip->fplacemark)) {
+ int fdout;
+ fdout = gopen(cgip->stdOut, O_RDONLY | O_BINARY, 0444 );
+/*
+ * Check to see if any data is available in the
+ * output file and send its contents to the socket.
+ */
+ if (fdout >= 0) {
+ webs_t wp = cgip->wp;
+ int nRead;
+/*
+ * Write the HTTP header on our first pass
+ */
+ if (cgip->fplacemark == 0) {
+ websWrite(wp, T("HTTP/1.0 200 OK\r\n"));
+ }
+ glseek(fdout, cgip->fplacemark, SEEK_SET);
+ while ((nRead = gread(fdout, cgiBuf, FNAMESIZE)) > 0) {
+ websWriteBlock(wp, cgiBuf, nRead);
+ cgip->fplacemark += nRead;
+ }
+ gclose(fdout);
+ }
+ }
+}
+
+
+
+/******************************************************************************/
+/*
+ * Any entry in the cgiList need to be checked to see if it has
+ * completed, and if so, process its output and clean up.
+ */
+void websCgiCleanup()
+{
+ cgiRec *cgip;
+ webs_t wp;
+ char_t **ep;
+ int cid, nTries;
+ for (cid = 0; cid < cgiMax; cid++) {
+ if ((cgip = cgiList[cid]) != NULL) {
+ wp = cgip->wp;
+ websCgiGatherOutput (cgip);
+ if (websCheckCgiProc(cgip->handle) == 0) {
+/*
+ * We get here if the CGI process has terminated. Clean up.
+ */
+ nTries = 0;
+/*
+ * Make sure we didn't miss something during a task switch.
+ * Maximum wait is 100 times 10 msecs (1 second).
+ */
+ while ((cgip->fplacemark == 0) && (nTries < 100)) {
+ websCgiGatherOutput(cgip);
+/*
+ * There are some cases when we detect app exit
+ * before the file is ready.
+ */
+ if (cgip->fplacemark == 0) {
+#ifdef WIN
+ Sleep(10);
+#endif /* WIN*/
+ }
+ nTries++;
+ }
+ if (cgip->fplacemark == 0) {
+ websError(wp, 200, T("CGI generated no output"));
+ } else {
+ websDone(wp, 200);
+ }
+/*
+ * Remove the temporary re-direction files
+ */
+ gunlink(cgip->stdIn);
+ gunlink(cgip->stdOut);
+/*
+ * Free all the memory buffers pointed to by cgip.
+ * The stdin file name (wp->cgiStdin) gets freed as
+ * part of websFree().
+ */
+ cgiMax = hFree((void***) &cgiList, cid);
+ for (ep = cgip->envp; ep != NULL && *ep != NULL; ep++) {
+ bfreeSafe(B_L, *ep);
+ }
+ bfreeSafe(B_L, cgip->cgiPath);
+ bfreeSafe(B_L, cgip->argp);
+ bfreeSafe(B_L, cgip->envp);
+ bfreeSafe(B_L, cgip->stdOut);
+ bfreeSafe(B_L, cgip);
+ }
+ }
+ }
+}
+/******************************************************************************/
diff --git a/cpukit/httpd/default.c b/cpukit/httpd/default.c
new file mode 100644
index 0000000000..2dfb2f70b2
--- /dev/null
+++ b/cpukit/httpd/default.c
@@ -0,0 +1,431 @@
+/*
+ * default.c -- Default URL handler. Includes support for ASP.
+ *
+ * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for usage and redistribution license requirements
+ *
+ * $Id$
+ */
+
+/******************************** Description *********************************/
+
+/*
+ * This module provides default URL handling and Active Server Page support.
+ *
+ * In many cases we don't check the return code of calls to websWrite as
+ * it is easier, smaller and non-fatal to continue even when the requesting
+ * browser has gone away.
+ */
+
+/********************************* Includes ***********************************/
+
+#include "wsIntrn.h"
+
+/*********************************** Locals ***********************************/
+
+static char_t *websDefaultPage; /* Default page name */
+static char_t *websDefaultDir; /* Default Web page directory */
+
+/**************************** Forward Declarations ****************************/
+
+static void websDefaultWriteEvent(webs_t wp);
+
+/*********************************** Code *************************************/
+/*
+ * Process a default URL request. This will validate the URL and handle "../"
+ * and will provide support for Active Server Pages. As the handler is the
+ * last handler to run, it always indicates that it has handled the URL
+ * by returning 1.
+ */
+
+int websDefaultHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
+ char_t *url, char_t *path, char_t *query)
+{
+ websStatType sbuf;
+ char_t *lpath, *tmp, *date;
+ int bytes, flags, nchars;
+
+ a_assert(websValid(wp));
+ a_assert(url && *url);
+ a_assert(path);
+ a_assert(query);
+
+/*
+ * Validate the URL and ensure that ".."s don't give access to unwanted files
+ */
+ flags = websGetRequestFlags(wp);
+
+ if (websValidateUrl(wp, path) < 0) {
+ websError(wp, 500, T("Invalid URL %s"), url);
+ return 1;
+ }
+ lpath = websGetRequestLpath(wp);
+ nchars = gstrlen(lpath) - 1;
+ if (lpath[nchars] == '/' || lpath[nchars] == '\\') {
+ lpath[nchars] = '\0';
+ }
+
+/*
+ * If the file is a directory, redirect using the nominated default page
+ */
+ if (websPageIsDirectory(lpath)) {
+ nchars = gstrlen(path);
+ if (path[nchars-1] == '/' || path[nchars-1] == '\\') {
+ path[--nchars] = '\0';
+ }
+ nchars += gstrlen(websDefaultPage) + 2;
+ fmtAlloc(&tmp, nchars, T("%s/%s"), path, websDefaultPage);
+ websRedirect(wp, tmp);
+ bfreeSafe(B_L, tmp);
+ return 1;
+ }
+
+/*
+ * Open the document. Stat for later use.
+ */
+ if (websPageOpen(wp, lpath, path, SOCKET_RDONLY | SOCKET_BINARY,
+ 0666) < 0) {
+ websError(wp, 400, T("Cannot open URL <b>%s</b>"), url);
+ return 1;
+ }
+
+ if (websPageStat(wp, lpath, path, &sbuf) < 0) {
+ websError(wp, 400, T("Cannot stat page for URL <b>%s</b>"), url);
+ return 1;
+ }
+
+/*
+ * If the page has not been modified since the user last received it and it
+ * is not dynamically generated each time (ASP), then optimize request by
+ * sending a 304 Use local copy response
+ */
+ websStats.localHits++;
+#ifdef WEBS_IF_MODIFIED_SUPPORT
+ if (flags & WEBS_IF_MODIFIED && !(flags & WEBS_ASP)) {
+ if (sbuf.mtime <= wp->since) {
+ websWrite(wp, T("HTTP/1.0 304 Use local copy\r\n"));
+
+/*
+ * by license terms the following line of code must
+ * not be modified.
+ */
+ websWrite(wp, T("Server: %s\r\n"), WEBS_NAME);
+
+ if (flags & WEBS_KEEP_ALIVE) {
+ websWrite(wp, T("Connection: keep-alive\r\n"));
+ }
+ websWrite(wp, T("\r\n"));
+ websSetRequestFlags(wp, flags |= WEBS_HEADER_DONE);
+ websDone(wp, 304);
+ return 1;
+ }
+ }
+#endif
+
+/*
+ * Output the normal HTTP response header
+ */
+ if ((date = websGetDateString(NULL)) != NULL) {
+ websWrite(wp, T("HTTP/1.0 200 OK\r\nDate: %s\r\n"), date);
+
+/*
+ * By license terms the following line of code must not be modified.
+ */
+ websWrite(wp, T("Server: %s\r\n"), WEBS_NAME);
+ bfree(B_L, date);
+ }
+ flags |= WEBS_HEADER_DONE;
+
+/*
+ * If this is an ASP request, ensure the remote browser doesn't cache it.
+ * Send back both HTTP/1.0 and HTTP/1.1 cache control directives
+ */
+ if (flags & WEBS_ASP) {
+ bytes = 0;
+ websWrite(wp, T("Pragma: no-cache\r\nCache-Control: no-cache\r\n"));
+
+ } else {
+ if ((date = websGetDateString(&sbuf)) != NULL) {
+ websWrite(wp, T("Last-modified: %s\r\n"), date);
+ bfree(B_L, date);
+ }
+ bytes = sbuf.size;
+ }
+
+ if (bytes) {
+ websWrite(wp, T("Content-length: %d\r\n"), bytes);
+ websSetRequestBytes(wp, bytes);
+ }
+ websWrite(wp, T("Content-type: %s\r\n"), websGetRequestType(wp));
+
+ if ((flags & WEBS_KEEP_ALIVE) && !(flags & WEBS_ASP)) {
+ websWrite(wp, T("Connection: keep-alive\r\n"));
+ }
+ websWrite(wp, T("\r\n"));
+
+/*
+ * All done if the browser did a HEAD request
+ */
+ if (flags & WEBS_HEAD_REQUEST) {
+ websDone(wp, 200);
+ return 1;
+ }
+
+/*
+ * Evaluate ASP requests
+ */
+ if (flags & WEBS_ASP) {
+ if (websAspRequest(wp, lpath) < 0) {
+ return 1;
+ }
+ websDone(wp, 200);
+ return 1;
+ }
+
+#ifdef WEBS_SSL_SUPPORT
+ if (wp->flags & WEBS_SECURE) {
+ websDefaultWriteEvent(wp);
+ } else {
+ websSetRequestSocketHandler(wp, SOCKET_WRITABLE, websDefaultWriteEvent);
+ }
+#else
+/*
+ * For normal web documents, return the data via background write
+ */
+ websSetRequestSocketHandler(wp, SOCKET_WRITABLE, websDefaultWriteEvent);
+#endif
+ return 1;
+}
+
+/******************************************************************************/
+/*
+ * Validate the URL path and process ".." path segments. Return -1 if the URL
+ * is bad.
+ */
+
+int websValidateUrl(webs_t wp, char_t *path)
+{
+ char_t *parts[64]; /* Array of ptr's to URL parts */
+ char_t *token, *dir, *lpath;
+ int i, len, npart;
+
+ a_assert(websValid(wp));
+ a_assert(path);
+
+ dir = websGetRequestDir(wp);
+ if (dir == NULL || *dir == '\0') {
+ return -1;
+ }
+
+/*
+ * Copy the string so we don't destroy the original
+ */
+ path = bstrdup(B_L, path);
+ websDecodeUrl(path, path, gstrlen(path));
+
+ len = npart = 0;
+ parts[0] = NULL;
+
+ /*
+ * 22 Jul 02 -- there were reports that a directory traversal exploit was
+ * possible in the WebServer running under Windows if directory paths
+ * outside the server's specified root web were given by URL-encoding the
+ * backslash character, like:
+ *
+ * GoAhead is vulnerable to a directory traversal bug. A request such as
+ *
+ * GoAhead-server/../../../../../../../ results in an error message
+ * 'Cannot open URL'.
+
+ * However, by encoding the '/' character, it is possible to break out of
+ * the
+ * web root and read arbitrary files from the server.
+ * Hence a request like:
+ *
+ * GoAhead-server/..%5C..%5C..%5C..%5C..%5C..%5C/winnt/win.ini returns the
+ * contents of the win.ini file.
+ * (Note that the description uses forward slashes (0x2F), but the example
+ * uses backslashes (0x5C). In my tests, forward slashes are correctly
+ * trapped, but backslashes are not. The code below substitutes forward
+ * slashes for backslashes before attempting to validate that there are no
+ * unauthorized paths being accessed.
+ */
+ token = gstrchr(path, '\\');
+ while (token != NULL)
+ {
+ *token = '/';
+ token = gstrchr(token, '\\');
+ }
+
+ token = gstrtok(path, T("/"));
+
+/*
+ * Look at each directory segment and process "." and ".." segments
+ * Don't allow the browser to pop outside the root web.
+ */
+ while (token != NULL) {
+ if (gstrcmp(token, T("..")) == 0) {
+ if (npart > 0) {
+ npart--;
+ }
+
+ } else if (gstrcmp(token, T(".")) != 0) {
+ parts[npart] = token;
+ len += gstrlen(token) + 1;
+ npart++;
+ }
+ token = gstrtok(NULL, T("/"));
+ }
+
+/*
+ * Create local path for document. Need extra space all "/" and null.
+ */
+ if (npart || (gstrcmp(path, T("/")) == 0) || (path[0] == '\0')) {
+ lpath = balloc(B_L, (gstrlen(dir) + 1 + len + 1) * sizeof(char_t));
+ gstrcpy(lpath, dir);
+
+ for (i = 0; i < npart; i++) {
+ gstrcat(lpath, T("/"));
+ gstrcat(lpath, parts[i]);
+ }
+ websSetRequestLpath(wp, lpath);
+ bfree(B_L, path);
+ bfree(B_L, lpath);
+
+ } else {
+ bfree(B_L, path);
+ return -1;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Do output back to the browser in the background. This is a socket
+ * write handler.
+ */
+
+static void websDefaultWriteEvent(webs_t wp)
+{
+ int len, wrote, flags, bytes, written;
+ char *buf;
+
+ a_assert(websValid(wp));
+
+ flags = websGetRequestFlags(wp);
+
+ websSetTimeMark(wp);
+
+ wrote = bytes = 0;
+ written = websGetRequestWritten(wp);
+
+/*
+ * We only do this for non-ASP documents
+ */
+ if ( !(flags & WEBS_ASP)) {
+ bytes = websGetRequestBytes(wp);
+/*
+ * Note: websWriteDataNonBlock may return less than we wanted. It will
+ * return -1 on a socket error
+ */
+ if ((buf = balloc(B_L, PAGE_READ_BUFSIZE)) == NULL) {
+ websError(wp, 200, T("Can't get memory"));
+ } else {
+ while ((len = websPageReadData(wp, buf, PAGE_READ_BUFSIZE)) > 0) {
+ if ((wrote = websWriteDataNonBlock(wp, buf, len)) < 0) {
+ break;
+ }
+ written += wrote;
+ if (wrote != len) {
+ websPageSeek(wp, - (len - wrote));
+ break;
+ }
+ }
+/*
+ * Safety. If we are at EOF, we must be done
+ */
+ if (len == 0) {
+ a_assert(written >= bytes);
+ written = bytes;
+ }
+ bfree(B_L, buf);
+ }
+ }
+
+/*
+ * We're done if an error, or all bytes output
+ */
+ websSetRequestWritten(wp, written);
+ if (wrote < 0 || written >= bytes) {
+ websDone(wp, 200);
+ }
+}
+
+/******************************************************************************/
+/*
+ * Closing down. Free resources.
+ */
+
+void websDefaultClose()
+{
+ if (websDefaultPage) {
+ bfree(B_L, websDefaultPage);
+ websDefaultPage = NULL;
+ }
+ if (websDefaultDir) {
+ bfree(B_L, websDefaultDir);
+ websDefaultDir = NULL;
+ }
+}
+
+/******************************************************************************/
+/*
+ * Get the default page for URL requests ending in "/"
+ */
+
+char_t *websGetDefaultPage()
+{
+ return websDefaultPage;
+}
+
+/******************************************************************************/
+/*
+ * Get the default web directory
+ */
+
+char_t *websGetDefaultDir()
+{
+ return websDefaultDir;
+}
+
+/******************************************************************************/
+/*
+ * Set the default page for URL requests ending in "/"
+ */
+
+void websSetDefaultPage(char_t *page)
+{
+ a_assert(page && *page);
+
+ if (websDefaultPage) {
+ bfree(B_L, websDefaultPage);
+ }
+ websDefaultPage = bstrdup(B_L, page);
+}
+
+/******************************************************************************/
+/*
+ * Set the default web directory
+ */
+
+void websSetDefaultDir(char_t *dir)
+{
+ a_assert(dir && *dir);
+ if (websDefaultDir) {
+ bfree(B_L, websDefaultDir);
+ }
+ websDefaultDir = bstrdup(B_L, dir);
+}
+
+/******************************************************************************/
diff --git a/cpukit/httpd/ej.h b/cpukit/httpd/ej.h
new file mode 100644
index 0000000000..879dae91a7
--- /dev/null
+++ b/cpukit/httpd/ej.h
@@ -0,0 +1,46 @@
+/*
+ * ej.h -- Ejscript(TM) header
+ *
+ * Copyright (c) GoAhead Software Inc., 1992-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for information on usage and redistribution
+ *
+ * $Id$
+ */
+
+#ifndef _h_EJ
+#define _h_EJ 1
+
+/******************************** Description *********************************/
+
+/*
+ * GoAhead Ejscript(TM) header. This defines the Ejscript API and internal
+ * structures.
+ */
+
+/********************************* Includes ***********************************/
+
+#ifndef UEMF
+ #include "basic/basic.h"
+ #include "emf/emf.h"
+#else
+ #include "uemf.h"
+#endif
+
+/********************************** Defines ***********************************/
+
+/******************************** Prototypes **********************************/
+
+extern int ejArgs(int argc, char_t **argv, char_t *fmt, ...);
+extern void ejSetResult(int eid, char_t *s);
+extern int ejOpenEngine(sym_fd_t variables, sym_fd_t functions);
+extern void ejCloseEngine(int eid);
+extern int ejSetGlobalFunction(int eid, char_t *name,
+ int (*fn)(int eid, void *handle, int argc, char_t **argv));
+extern void ejSetVar(int eid, char_t *var, char_t *value);
+extern int ejGetVar(int eid, char_t *var, char_t **value);
+extern char_t *ejEval(int eid, char_t *script, char_t **emsg);
+
+#endif /* _h_EJ */
+
+/*****************************************************************************/
diff --git a/cpukit/httpd/ejIntrn.h b/cpukit/httpd/ejIntrn.h
new file mode 100644
index 0000000000..401da17891
--- /dev/null
+++ b/cpukit/httpd/ejIntrn.h
@@ -0,0 +1,230 @@
+/*
+ * ejIntrn.h -- Ejscript(TM) header
+ *
+ * Copyright (c) GoAhead Software, Inc., 1992-2000
+ *
+ * See the file "license.txt" for information on usage and redistribution
+ *
+ * $Id$
+ */
+
+#ifndef _h_EJINTERNAL
+#define _h_EJINTERNAL 1
+
+/******************************** Description *********************************/
+
+/*
+ * GoAhead Ejscript(TM) header. This defines the Ejscript API and internal
+ * structures.
+ */
+
+/********************************* Includes ***********************************/
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+#ifdef CE
+#ifndef UEMF
+ #include <io.h>
+#endif
+#endif
+
+#ifdef LYNX
+ #include <unistd.h>
+#endif
+
+#ifdef QNX4
+ #include <dirent.h>
+#endif
+
+#ifdef UEMF
+ #include "uemf.h"
+#else
+ #include <param.h>
+ #include <stat.h>
+ #include "basic/basicInternal.h"
+ #include "emf/emfInternal.h"
+#endif
+
+#include "ej.h"
+
+/********************************** Defines ***********************************/
+/*
+ * Constants
+ */
+#define EJ_INC 110 /* Growth for tags/tokens */
+#define EJ_SCRIPT_INC 1023 /* Growth for ej scripts */
+#define EJ_OFFSET 1 /* hAlloc doesn't like 0 entries */
+#define EJ_MAX_RECURSE 100 /* Sanity for maximum recursion */
+
+/*
+ * Ejscript Lexical analyser tokens
+ */
+#define TOK_ERR -1 /* Any error */
+#define TOK_LPAREN 1 /* ( */
+#define TOK_RPAREN 2 /* ) */
+#define TOK_IF 3 /* if */
+#define TOK_ELSE 4 /* else */
+#define TOK_LBRACE 5 /* { */
+#define TOK_RBRACE 6 /* } */
+#define TOK_LOGICAL 7 /* ||, &&, ! */
+#define TOK_EXPR 8 /* +, -, /, % */
+#define TOK_SEMI 9 /* ; */
+#define TOK_LITERAL 10 /* literal string */
+#define TOK_FUNCTION 11 /* function name */
+#define TOK_NEWLINE 12 /* newline white space */
+#define TOK_ID 13 /* function name */
+#define TOK_EOF 14 /* End of script */
+#define TOK_COMMA 15 /* Comma */
+#define TOK_VAR 16 /* var */
+#define TOK_ASSIGNMENT 17 /* = */
+#define TOK_FOR 18 /* for */
+#define TOK_INC_DEC 19 /* ++, -- */
+#define TOK_RETURN 20 /* return */
+
+/*
+ * Expression operators
+ */
+#define EXPR_LESS 1 /* < */
+#define EXPR_LESSEQ 2 /* <= */
+#define EXPR_GREATER 3 /* > */
+#define EXPR_GREATEREQ 4 /* >= */
+#define EXPR_EQ 5 /* == */
+#define EXPR_NOTEQ 6 /* != */
+#define EXPR_PLUS 7 /* + */
+#define EXPR_MINUS 8 /* - */
+#define EXPR_DIV 9 /* / */
+#define EXPR_MOD 10 /* % */
+#define EXPR_LSHIFT 11 /* << */
+#define EXPR_RSHIFT 12 /* >> */
+#define EXPR_MUL 13 /* * */
+#define EXPR_ASSIGNMENT 14 /* = */
+#define EXPR_INC 15 /* ++ */
+#define EXPR_DEC 16 /* -- */
+#define EXPR_BOOL_COMP 17 /* ! */
+/*
+ * Conditional operators
+ */
+#define COND_AND 1 /* && */
+#define COND_OR 2 /* || */
+#define COND_NOT 3 /* ! */
+
+/*
+ * States
+ */
+#define STATE_ERR -1 /* Error state */
+#define STATE_EOF 1 /* End of file */
+#define STATE_COND 2 /* Parsing a "(conditional)" stmt */
+#define STATE_COND_DONE 3
+#define STATE_RELEXP 4 /* Parsing a relational expr */
+#define STATE_RELEXP_DONE 5
+#define STATE_EXPR 6 /* Parsing an expression */
+#define STATE_EXPR_DONE 7
+#define STATE_STMT 8 /* Parsing General statement */
+#define STATE_STMT_DONE 9
+#define STATE_STMT_BLOCK_DONE 10 /* End of block "}" */
+#define STATE_ARG_LIST 11 /* Function arg list */
+#define STATE_ARG_LIST_DONE 12
+#define STATE_DEC_LIST 16 /* Declaration list */
+#define STATE_DEC_LIST_DONE 17
+#define STATE_DEC 18
+#define STATE_DEC_DONE 19
+
+#define STATE_RET 20 /* Return statement */
+
+#define STATE_BEGIN STATE_STMT
+
+/*
+ * Flags. Used in ej_t and as parameter to parse()
+ */
+#define FLAGS_EXE 0x1 /* Execute statements */
+#define FLAGS_VARIABLES 0x2 /* Allocated variables store */
+#define FLAGS_FUNCTIONS 0x4 /* Allocated function store */
+
+/*
+ * Function call structure
+ */
+typedef struct {
+ char_t *fname; /* Function name */
+ char_t **args; /* Args for function (halloc) */
+ int nArgs; /* Number of args */
+} ejfunc_t;
+
+/*
+ * EJ evaluation block structure
+ */
+typedef struct ejEval {
+ ringq_t tokbuf; /* Current token */
+ ringq_t script; /* Input script for parsing */
+ char_t *putBackToken; /* Putback token string */
+ int putBackTokenId; /* Putback token ID */
+ char_t *line; /* Current line */
+ int lineLength; /* Current line length */
+ int lineNumber; /* Parse line number */
+ int lineColumn; /* Column in line */
+} ejinput_t;
+
+/*
+ * Per Ejscript session structure
+ */
+typedef struct ej {
+ ejinput_t *input; /* Input evaluation block */
+ sym_fd_t functions; /* Symbol table for functions */
+ sym_fd_t *variables; /* hAlloc list of variables */
+ int variableMax; /* Number of entries */
+ ejfunc_t *func; /* Current function */
+ char_t *result; /* Current expression result */
+ char_t *error; /* Error message */
+ char_t *token; /* Pointer to token string */
+ int tid; /* Current token id */
+ int eid; /* Halloc handle */
+ int flags; /* Flags */
+ int userHandle; /* User defined handle */
+} ej_t;
+
+/******************************** Prototypes **********************************/
+
+extern int ejOpenBlock(int eid);
+extern int ejCloseBlock(int eid, int vid);
+extern char_t *ejEvalBlock(int eid, char_t *script, char_t **emsg);
+#ifndef __NO_EJ_FILE
+extern char_t *ejEvalFile(int eid, char_t *path, char_t **emsg);
+#endif
+extern int ejRemoveGlobalFunction(int eid, char_t *name);
+extern void *ejGetGlobalFunction(int eid, char_t *name);
+extern int ejSetGlobalFunctionDirect(sym_fd_t functions, char_t *name,
+ int (*fn)(int eid, void *handle, int argc, char_t **argv));
+extern void ejError(ej_t* ep, char_t* fmt, ...);
+extern void ejSetUserHandle(int eid, int handle);
+extern int ejGetUserHandle(int eid);
+extern int ejGetLineNumber(int eid);
+extern char_t *ejGetResult(int eid);
+extern void ejSetLocalVar(int eid, char_t *var, char_t *value);
+extern void ejSetGlobalVar(int eid, char_t *var, char_t *value);
+
+extern int ejLexOpen(ej_t* ep);
+extern void ejLexClose(ej_t* ep);
+extern int ejLexOpenScript(ej_t* ep, char_t *script);
+extern void ejLexCloseScript(ej_t* ep);
+extern void ejLexSaveInputState(ej_t* ep, ejinput_t* state);
+extern void ejLexFreeInputState(ej_t* ep, ejinput_t* state);
+extern void ejLexRestoreInputState(ej_t* ep, ejinput_t* state);
+extern int ejLexGetToken(ej_t* ep, int state);
+extern void ejLexPutbackToken(ej_t* ep, int tid, char_t *string);
+
+extern sym_fd_t ejGetVariableTable(int eid);
+extern sym_fd_t ejGetFunctionTable(int eid);
+
+extern int ejEmfOpen(int eid);
+extern void ejEmfClose(int eid);
+
+extern int ejEmfDbRead(int eid, void *handle, int argc, char_t **argv);
+extern int ejEmfDbReadKeyed(int eid, void *handle, int argc, char_t **argv);
+extern int ejEmfDbTableGetNrow(int eid, void *handle, int argc, char_t **argv);
+extern int ejEmfDbDeleteRow(int eid, void *handle, int argc, char_t **argv);
+extern int ejEmfTrace(int eid, void *handle, int argc, char_t **argv);
+extern int ejEmfDbWrite(int eid, void *handle, int argc, char_t **argv);
+extern int ejEmfDbCollectTable(int eid, void *handle, int argc, char_t **argv);
+
+#endif /* _h_EJINTERNAL */
diff --git a/cpukit/httpd/ejlex.c b/cpukit/httpd/ejlex.c
new file mode 100644
index 0000000000..45181d9d83
--- /dev/null
+++ b/cpukit/httpd/ejlex.c
@@ -0,0 +1,721 @@
+/*
+ * ejlex.c -- Ejscript(TM) Lexical Analyser
+ *
+ * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for usage and redistribution license requirements
+ *
+ * $Id$
+ */
+
+/******************************** Description *********************************/
+
+/*
+ * Ejscript lexical analyser. This implementes a lexical analyser for a
+ * a subset of the JavaScript language.
+ */
+
+/********************************** Includes **********************************/
+
+#include "ejIntrn.h"
+
+#ifdef UEMF
+ #include "uemf.h"
+#else
+ #include "basic/basicInternal.h"
+#endif
+
+/********************************** Defines ***********************************/
+#define OCTAL 8
+#define HEX 16
+/****************************** Forward Declarations **************************/
+
+static int getLexicalToken(ej_t* ep, int state);
+static int tokenAddChar(ej_t *ep, int c);
+static int inputGetc(ej_t* ep);
+static void inputPutback(ej_t* ep, int c);
+static int charConvert(ej_t* ep, int base, int maxDig);
+
+/************************************* Code ***********************************/
+/*
+ * Setup the lexical analyser
+ */
+
+int ejLexOpen(ej_t* ep)
+{
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Close the lexicial analyser
+ */
+
+void ejLexClose(ej_t* ep)
+{
+}
+
+/******************************************************************************/
+/*
+ * Open a new input script
+ */
+
+int ejLexOpenScript(ej_t* ep, char_t *script)
+{
+ ejinput_t *ip;
+
+ a_assert(ep);
+ a_assert(script);
+
+ if ((ep->input = balloc(B_L, sizeof(ejinput_t))) == NULL) {
+ return -1;
+ }
+ ip = ep->input;
+ memset(ip, 0, sizeof(*ip));
+
+ a_assert(ip);
+ a_assert(ip->putBackToken == NULL);
+ a_assert(ip->putBackTokenId == 0);
+
+/*
+ * Create the parse token buffer and script buffer
+ */
+ if (ringqOpen(&ip->tokbuf, EJ_INC, -1) < 0) {
+ return -1;
+ }
+ if (ringqOpen(&ip->script, EJ_SCRIPT_INC, -1) < 0) {
+ return -1;
+ }
+/*
+ * Put the Ejscript into a ring queue for easy parsing
+ */
+ ringqPutStr(&ip->script, script);
+
+ ip->lineNumber = 1;
+ ip->lineLength = 0;
+ ip->lineColumn = 0;
+ ip->line = NULL;
+
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Close the input script
+ */
+
+void ejLexCloseScript(ej_t* ep)
+{
+ ejinput_t *ip;
+
+ a_assert(ep);
+
+ ip = ep->input;
+ a_assert(ip);
+
+ if (ip->putBackToken) {
+ bfree(B_L, ip->putBackToken);
+ ip->putBackToken = NULL;
+ }
+ ip->putBackTokenId = 0;
+
+ if (ip->line) {
+ bfree(B_L, ip->line);
+ ip->line = NULL;
+ }
+
+ ringqClose(&ip->tokbuf);
+ ringqClose(&ip->script);
+
+ bfree(B_L, ip);
+}
+
+/******************************************************************************/
+/*
+ * Save the input state
+ */
+
+void ejLexSaveInputState(ej_t* ep, ejinput_t* state)
+{
+ ejinput_t *ip;
+
+ a_assert(ep);
+
+ ip = ep->input;
+ a_assert(ip);
+
+ *state = *ip;
+ if (ip->putBackToken) {
+ state->putBackToken = bstrdup(B_L, ip->putBackToken);
+ }
+}
+
+/******************************************************************************/
+/*
+ * Restore the input state
+ */
+
+void ejLexRestoreInputState(ej_t* ep, ejinput_t* state)
+{
+ ejinput_t *ip;
+
+ a_assert(ep);
+
+ ip = ep->input;
+ a_assert(ip);
+
+ ip->tokbuf = state->tokbuf;
+ ip->script = state->script;
+ ip->putBackTokenId = state->putBackTokenId;
+ if (ip->putBackToken) {
+ bfree(B_L, ip->putBackToken);
+ }
+ if (state->putBackToken) {
+ ip->putBackToken = bstrdup(B_L, state->putBackToken);
+ }
+}
+
+/******************************************************************************/
+/*
+ * Free a saved input state
+ */
+
+void ejLexFreeInputState(ej_t* ep, ejinput_t* state)
+{
+ if (state->putBackToken) {
+ bfree(B_L, state->putBackToken);
+ state->putBackToken = NULL;
+ }
+}
+
+/******************************************************************************/
+/*
+ * Get the next Ejscript token
+ */
+
+int ejLexGetToken(ej_t* ep, int state)
+{
+ ep->tid = getLexicalToken(ep, state);
+ /*
+ * commented out 04 Apr 02 Bg Porter -- we found a case where very long
+ * arguments to write() were being corrupted downstream in the trace call
+ * (the ep->token pointer was being overwritten with the trace message.
+ * restore this if it's useful for your debugging.
+ trace(9, T("ejGetToken: %d, \"%s\"\n"), ep->tid, ep->token);
+ */
+ return ep->tid;
+}
+
+/******************************************************************************/
+/*
+ * Get the next Ejscript token
+ */
+
+static int getLexicalToken(ej_t* ep, int state)
+{
+ ringq_t *inq, *tokq;
+ ejinput_t* ip;
+ int done, tid, c, quote, style;
+
+ a_assert(ep);
+ ip = ep->input;
+ a_assert(ip);
+
+ inq = &ip->script;
+ tokq = &ip->tokbuf;
+
+ ep->tid = -1;
+ tid = -1;
+ ep->token = T("");
+
+ ringqFlush(tokq);
+
+ if (ip->putBackTokenId > 0) {
+ ringqPutStr(tokq, ip->putBackToken);
+ tid = ip->putBackTokenId;
+ ip->putBackTokenId = 0;
+ ep->token = (char_t*) tokq->servp;
+ return tid;
+ }
+
+ if ((c = inputGetc(ep)) < 0) {
+ return TOK_EOF;
+ }
+
+ for (done = 0; !done; ) {
+ switch (c) {
+ case -1:
+ return TOK_EOF;
+
+ case ' ':
+ case '\t':
+ case '\r':
+ do {
+ if ((c = inputGetc(ep)) < 0)
+ break;
+ } while (c == ' ' || c == '\t' || c == '\r');
+ break;
+
+ case '\n':
+ return TOK_NEWLINE;
+
+ case '(':
+ tokenAddChar(ep, c);
+ return TOK_LPAREN;
+
+ case ')':
+ tokenAddChar(ep, c);
+ return TOK_RPAREN;
+
+ case '{':
+ tokenAddChar(ep, c);
+ return TOK_LBRACE;
+
+ case '}':
+ tokenAddChar(ep, c);
+ return TOK_RBRACE;
+
+ case '+':
+ if ((c = inputGetc(ep)) < 0) {
+ ejError(ep, T("Syntax Error"));
+ return TOK_ERR;
+ }
+ if (c != '+' ) {
+ inputPutback(ep, c);
+ tokenAddChar(ep, EXPR_PLUS);
+ return TOK_EXPR;
+ }
+ tokenAddChar(ep, EXPR_INC);
+ return TOK_INC_DEC;
+
+ case '-':
+ if ((c = inputGetc(ep)) < 0) {
+ ejError(ep, T("Syntax Error"));
+ return TOK_ERR;
+ }
+ if (c != '-' ) {
+ inputPutback(ep, c);
+ tokenAddChar(ep, EXPR_MINUS);
+ return TOK_EXPR;
+ }
+ tokenAddChar(ep, EXPR_DEC);
+ return TOK_INC_DEC;
+
+ case '*':
+ tokenAddChar(ep, EXPR_MUL);
+ return TOK_EXPR;
+
+ case '%':
+ tokenAddChar(ep, EXPR_MOD);
+ return TOK_EXPR;
+
+ case '/':
+/*
+ * Handle the division operator and comments
+ */
+ if ((c = inputGetc(ep)) < 0) {
+ ejError(ep, T("Syntax Error"));
+ return TOK_ERR;
+ }
+ if (c != '*' && c != '/') {
+ inputPutback(ep, c);
+ tokenAddChar(ep, EXPR_DIV);
+ return TOK_EXPR;
+ }
+ style = c;
+/*
+ * Eat comments. Both C and C++ comment styles are supported.
+ */
+ while (1) {
+ if ((c = inputGetc(ep)) < 0) {
+ ejError(ep, T("Syntax Error"));
+ return TOK_ERR;
+ }
+ if (c == '\n' && style == '/') {
+ break;
+ } else if (c == '*') {
+ c = inputGetc(ep);
+ if (style == '/') {
+ if (c == '\n') {
+ break;
+ }
+ } else {
+ if (c == '/') {
+ break;
+ }
+ }
+ }
+ }
+/*
+ * Continue looking for a token, so get the next character
+ */
+ if ((c = inputGetc(ep)) < 0) {
+ return TOK_EOF;
+ }
+ break;
+
+ case '<': /* < and <= */
+ if ((c = inputGetc(ep)) < 0) {
+ ejError(ep, T("Syntax Error"));
+ return TOK_ERR;
+ }
+ if (c == '<') {
+ tokenAddChar(ep, EXPR_LSHIFT);
+ return TOK_EXPR;
+ } else if (c == '=') {
+ tokenAddChar(ep, EXPR_LESSEQ);
+ return TOK_EXPR;
+ }
+ tokenAddChar(ep, EXPR_LESS);
+ inputPutback(ep, c);
+ return TOK_EXPR;
+
+ case '>': /* > and >= */
+ if ((c = inputGetc(ep)) < 0) {
+ ejError(ep, T("Syntax Error"));
+ return TOK_ERR;
+ }
+ if (c == '>') {
+ tokenAddChar(ep, EXPR_RSHIFT);
+ return TOK_EXPR;
+ } else if (c == '=') {
+ tokenAddChar(ep, EXPR_GREATEREQ);
+ return TOK_EXPR;
+ }
+ tokenAddChar(ep, EXPR_GREATER);
+ inputPutback(ep, c);
+ return TOK_EXPR;
+
+ case '=': /* "==" */
+ if ((c = inputGetc(ep)) < 0) {
+ ejError(ep, T("Syntax Error"));
+ return TOK_ERR;
+ }
+ if (c == '=') {
+ tokenAddChar(ep, EXPR_EQ);
+ return TOK_EXPR;
+ }
+ inputPutback(ep, c);
+ return TOK_ASSIGNMENT;
+
+ case '!': /* "!=" or "!"*/
+ if ((c = inputGetc(ep)) < 0) {
+ ejError(ep, T("Syntax Error"));
+ return TOK_ERR;
+ }
+ if (c == '=') {
+ tokenAddChar(ep, EXPR_NOTEQ);
+ return TOK_EXPR;
+ }
+ inputPutback(ep, c);
+ tokenAddChar(ep, EXPR_BOOL_COMP);
+ return TOK_EXPR;
+
+ case ';':
+ tokenAddChar(ep, c);
+ return TOK_SEMI;
+
+ case ',':
+ tokenAddChar(ep, c);
+ return TOK_COMMA;
+
+ case '|': /* "||" */
+ if ((c = inputGetc(ep)) < 0 || c != '|') {
+ ejError(ep, T("Syntax Error"));
+ return TOK_ERR;
+ }
+ tokenAddChar(ep, COND_OR);
+ return TOK_LOGICAL;
+
+ case '&': /* "&&" */
+ if ((c = inputGetc(ep)) < 0 || c != '&') {
+ ejError(ep, T("Syntax Error"));
+ return TOK_ERR;
+ }
+ tokenAddChar(ep, COND_AND);
+ return TOK_LOGICAL;
+
+ case '\"': /* String quote */
+ case '\'':
+ quote = c;
+ if ((c = inputGetc(ep)) < 0) {
+ ejError(ep, T("Syntax Error"));
+ return TOK_ERR;
+ }
+
+ while (c != quote) {
+/*
+ * check for escape sequence characters
+ */
+ if (c == '\\') {
+ c = inputGetc(ep);
+
+ if (gisdigit(c)) {
+/*
+ * octal support, \101 maps to 65 = 'A'. put first char
+ * back so converter will work properly.
+ */
+ inputPutback(ep, c);
+ c = charConvert(ep, OCTAL, 3);
+
+ } else {
+ switch (c) {
+ case 'n':
+ c = '\n'; break;
+ case 'b':
+ c = '\b'; break;
+ case 'f':
+ c = '\f'; break;
+ case 'r':
+ c = '\r'; break;
+ case 't':
+ c = '\t'; break;
+ case 'x':
+/*
+ * hex support, \x41 maps to 65 = 'A'
+ */
+ c = charConvert(ep, HEX, 2);
+ break;
+ case 'u':
+/*
+ * unicode support, \x0401 maps to 65 = 'A'
+ */
+ c = charConvert(ep, HEX, 2);
+ c = c*16 + charConvert(ep, HEX, 2);
+
+ break;
+ case '\'':
+ case '\"':
+ case '\\':
+ break;
+ default:
+ ejError(ep, T("Invalid Escape Sequence"));
+ return TOK_ERR;
+ }
+ }
+ if (tokenAddChar(ep, c) < 0) {
+ return TOK_ERR;
+ }
+ } else {
+ if (tokenAddChar(ep, c) < 0) {
+ return TOK_ERR;
+ }
+ }
+ if ((c = inputGetc(ep)) < 0) {
+ ejError(ep, T("Unmatched Quote"));
+ return TOK_ERR;
+ }
+ }
+ return TOK_LITERAL;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ do {
+ if (tokenAddChar(ep, c) < 0) {
+ return TOK_ERR;
+ }
+ if ((c = inputGetc(ep)) < 0)
+ break;
+ } while (gisdigit(c));
+ inputPutback(ep, c);
+ return TOK_LITERAL;
+
+ default:
+/*
+ * Identifiers or a function names
+ */
+ while (1) {
+ if (c == '\\') {
+/*
+ * just ignore any \ characters.
+ */
+ } else if (tokenAddChar(ep, c) < 0) {
+ break;
+ }
+ if ((c = inputGetc(ep)) < 0) {
+ break;
+ }
+ if (!gisalnum(c) && c != '$' && c != '_' &&
+ c != '\\') {
+ break;
+ }
+ }
+ if (! gisalpha(*tokq->servp) && *tokq->servp != '$' &&
+ *tokq->servp != '_') {
+ ejError(ep, T("Invalid identifier %s"), tokq->servp);
+ return TOK_ERR;
+ }
+/*
+ * Check for reserved words (only "if", "else", "var", "for"
+ * and "return" at the moment)
+ */
+ if (state == STATE_STMT) {
+ if (gstrcmp(ep->token, T("if")) == 0) {
+ return TOK_IF;
+ } else if (gstrcmp(ep->token, T("else")) == 0) {
+ return TOK_ELSE;
+ } else if (gstrcmp(ep->token, T("var")) == 0) {
+ return TOK_VAR;
+ } else if (gstrcmp(ep->token, T("for")) == 0) {
+ return TOK_FOR;
+ } else if (gstrcmp(ep->token, T("return")) == 0) {
+ if ((c == ';') || (c == '(')) {
+ inputPutback(ep, c);
+ }
+ return TOK_RETURN;
+ }
+ }
+
+/*
+ * Skip white space after token to find out whether this is
+ * a function or not.
+ */
+ while (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
+ if ((c = inputGetc(ep)) < 0)
+ break;
+ }
+
+ tid = (c == '(') ? TOK_FUNCTION : TOK_ID;
+ done++;
+ }
+ }
+
+/*
+ * Putback the last extra character for next time
+ */
+ inputPutback(ep, c);
+ return tid;
+}
+
+/******************************************************************************/
+/*
+ * Putback the last token read
+ */
+
+void ejLexPutbackToken(ej_t* ep, int tid, char_t *string)
+{
+ ejinput_t* ip;
+
+ a_assert(ep);
+ ip = ep->input;
+ a_assert(ip);
+
+ if (ip->putBackToken) {
+ bfree(B_L, ip->putBackToken);
+ }
+ ip->putBackTokenId = tid;
+ ip->putBackToken = bstrdup(B_L, string);
+}
+
+/******************************************************************************/
+/*
+ * Add a character to the token ringq buffer
+ */
+
+static int tokenAddChar(ej_t *ep, int c)
+{
+ ejinput_t* ip;
+
+ a_assert(ep);
+ ip = ep->input;
+ a_assert(ip);
+
+ if (ringqPutc(&ip->tokbuf, (char_t) c) < 0) {
+ ejError(ep, T("Token too big"));
+ return -1;
+ }
+ * ((char_t*) ip->tokbuf.endp) = '\0';
+ ep->token = (char_t*) ip->tokbuf.servp;
+
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Get another input character
+ */
+
+static int inputGetc(ej_t* ep)
+{
+ ejinput_t *ip;
+ int c, len;
+
+ a_assert(ep);
+ ip = ep->input;
+
+ if ((len = ringqLen(&ip->script)) == 0) {
+ return -1;
+ }
+
+ c = ringqGetc(&ip->script);
+
+ if (c == '\n') {
+ ip->lineNumber++;
+ ip->lineColumn = 0;
+ } else {
+ if ((ip->lineColumn + 2) >= ip->lineLength) {
+ ip->lineLength += EJ_INC;
+ ip->line = brealloc(B_L, ip->line, ip->lineLength * sizeof(char_t));
+ }
+ ip->line[ip->lineColumn++] = c;
+ ip->line[ip->lineColumn] = '\0';
+ }
+ return c;
+}
+
+/******************************************************************************/
+/*
+ * Putback a character onto the input queue
+ */
+
+static void inputPutback(ej_t* ep, int c)
+{
+ ejinput_t *ip;
+
+ a_assert(ep);
+
+ ip = ep->input;
+ ringqInsertc(&ip->script, (char_t) c);
+ ip->lineColumn--;
+ ip->line[ip->lineColumn] = '\0';
+}
+
+/******************************************************************************/
+/*
+ * Convert a hex or octal character back to binary, return original char if
+ * not a hex digit
+ */
+
+static int charConvert(ej_t* ep, int base, int maxDig)
+{
+ int i, c, lval, convChar;
+
+ lval = 0;
+ for (i = 0; i < maxDig; i++) {
+ if ((c = inputGetc(ep)) < 0) {
+ break;
+ }
+/*
+ * Initialize to out of range value
+ */
+ convChar = base;
+ if (gisdigit(c)) {
+ convChar = c - '0';
+ } else if (c >= 'a' && c <= 'f') {
+ convChar = c - 'a' + 10;
+ } else if (c >= 'A' && c <= 'F') {
+ convChar = c - 'A' + 10;
+ }
+/*
+ * if unexpected character then return it to buffer.
+ */
+ if (convChar >= base) {
+ inputPutback(ep, c);
+ break;
+ }
+ lval = (lval * base) + convChar;
+ }
+ return lval;
+}
+
+/******************************************************************************/
diff --git a/cpukit/httpd/ejparse.c b/cpukit/httpd/ejparse.c
new file mode 100644
index 0000000000..fdbb9c1d8a
--- /dev/null
+++ b/cpukit/httpd/ejparse.c
@@ -0,0 +1,1804 @@
+/*
+ * ejparse.c -- Ejscript(TM) Parser
+ *
+ * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for usage and redistribution license requirements
+ *
+ * $Id$
+ */
+
+/******************************** Description *********************************/
+
+/*
+ * Ejscript parser. This implementes a subset of the JavaScript language.
+ * Multiple Ejscript parsers can be opened at a time.
+ */
+
+/********************************** Includes **********************************/
+
+#include "ejIntrn.h"
+
+#ifdef CE
+ #include "CE/wincompat.h"
+#endif
+
+/********************************** Local Data ********************************/
+
+ej_t **ejHandles; /* List of ej handles */
+int ejMax = -1; /* Maximum size of */
+
+/****************************** Forward Declarations **************************/
+
+#ifndef B_STATS
+#define setString(a,b,c) setstring(b,c)
+#endif
+
+static ej_t *ejPtr(int eid);
+static void clearString(char_t **ptr);
+static void setString(B_ARGS_DEC, char_t **ptr, char_t *s);
+static void appendString(char_t **ptr, char_t *s);
+static int parse(ej_t *ep, int state, int flags);
+static int parseStmt(ej_t *ep, int state, int flags);
+static int parseDeclaration(ej_t *ep, int state, int flags);
+static int parseArgs(ej_t *ep, int state, int flags);
+static int parseCond(ej_t *ep, int state, int flags);
+static int parseExpr(ej_t *ep, int state, int flags);
+static int evalExpr(ej_t *ep, char_t *lhs, int rel, char_t *rhs);
+static int evalCond(ej_t *ep, char_t *lhs, int rel, char_t *rhs);
+static int evalFunction(ej_t *ep);
+static void freeFunc(ejfunc_t *func);
+static void ejRemoveNewlines(ej_t *ep, int state);
+
+/************************************* Code ***********************************/
+/*
+ * Initialize a Ejscript engine
+ */
+
+int ejOpenEngine(sym_fd_t variables, sym_fd_t functions)
+{
+ ej_t *ep;
+ int eid, vid;
+
+ if ((eid = hAllocEntry((void*) &ejHandles, &ejMax, sizeof(ej_t))) < 0) {
+ return -1;
+ }
+ ep = ejHandles[eid];
+ ep->eid = eid;
+
+/*
+ * Create a top level symbol table if one is not provided for variables and
+ * functions. Variables may create other symbol tables for block level
+ * declarations so we use hAlloc to manage a list of variable tables.
+ */
+ if ((vid = hAlloc((void***) &ep->variables)) < 0) {
+ ejMax = hFree((void*) &ejHandles, ep->eid);
+ return -1;
+ }
+ if (vid >= ep->variableMax) {
+ ep->variableMax = vid + 1;
+ }
+
+ if (variables == -1) {
+ ep->variables[vid] = symOpen(64) + EJ_OFFSET;
+ ep->flags |= FLAGS_VARIABLES;
+ } else {
+ ep->variables[vid] = variables + EJ_OFFSET;
+ }
+
+ if (functions == -1) {
+ ep->functions = symOpen(64);
+ ep->flags |= FLAGS_FUNCTIONS;
+ } else {
+ ep->functions = functions;
+ }
+
+ ejLexOpen(ep);
+
+/*
+ * Define standard constants
+ */
+ ejSetGlobalVar(ep->eid, T("null"), NULL);
+
+#ifdef EMF
+ ejEmfOpen(ep->eid);
+#endif
+ return ep->eid;
+}
+
+/******************************************************************************/
+/*
+ * Close
+ */
+
+void ejCloseEngine(int eid)
+{
+ ej_t *ep;
+ int i;
+
+ if ((ep = ejPtr(eid)) == NULL) {
+ return;
+ }
+
+#ifdef EMF
+ ejEmfClose(eid);
+#endif
+
+ bfreeSafe(B_L, ep->error);
+ ep->error = NULL;
+ bfreeSafe(B_L, ep->result);
+ ep->result = NULL;
+
+ ejLexClose(ep);
+
+ for (i = ep->variableMax - 1; i >= 0; i--) {
+ if (ep->flags & FLAGS_VARIABLES) {
+ symClose(ep->variables[i] - EJ_OFFSET);
+ }
+ ep->variableMax = hFree((void***) &ep->variables, i);
+ }
+
+ if (ep->flags & FLAGS_FUNCTIONS) {
+ symClose(ep->functions);
+ }
+
+ ejMax = hFree((void*) &ejHandles, ep->eid);
+ bfree(B_L, ep);
+}
+
+#ifndef __NO_EJ_FILE
+/******************************************************************************/
+/*
+ * Evaluate a Ejscript file
+ */
+
+char_t *ejEvalFile(int eid, char_t *path, char_t **emsg)
+{
+ gstat_t sbuf;
+ ej_t *ep;
+ char_t *script, *rs;
+ char *fileBuf;
+ int fd;
+
+ a_assert(path && *path);
+
+ if (emsg) {
+ *emsg = NULL;
+ }
+
+ if ((ep = ejPtr(eid)) == NULL) {
+ return NULL;
+ }
+
+ if ((fd = gopen(path, O_RDONLY | O_BINARY, 0666)) < 0) {
+ ejError(ep, T("Bad handle %d"), eid);
+ return NULL;
+ }
+
+ if (gstat(path, &sbuf) < 0) {
+ gclose(fd);
+ ejError(ep, T("Cant stat %s"), path);
+ return NULL;
+ }
+
+ if ((fileBuf = balloc(B_L, sbuf.st_size + 1)) == NULL) {
+ gclose(fd);
+ ejError(ep, T("Cant malloc %d"), sbuf.st_size);
+ return NULL;
+ }
+
+ if (gread(fd, fileBuf, sbuf.st_size) != (int)sbuf.st_size) {
+ gclose(fd);
+ bfree(B_L, fileBuf);
+ ejError(ep, T("Error reading %s"), path);
+ return NULL;
+ }
+
+ fileBuf[sbuf.st_size] = '\0';
+ gclose(fd);
+
+ if ((script = ballocAscToUni(fileBuf, sbuf.st_size)) == NULL) {
+ bfree(B_L, fileBuf);
+ ejError(ep, T("Cant malloc %d"), sbuf.st_size + 1);
+ return NULL;
+ }
+ bfree(B_L, fileBuf);
+
+ rs = ejEvalBlock(eid, script, emsg);
+
+ bfree(B_L, script);
+ return rs;
+}
+#endif /* __NO_EJ_FILE */
+
+/******************************************************************************/
+/*
+ * Create a new variable scope block so that consecutive ejEval calls may
+ * be made with the same varible scope. This space MUST be closed with
+ * ejCloseBlock when the evaluations are complete.
+ */
+
+int ejOpenBlock(int eid)
+{
+ ej_t *ep;
+ int vid;
+
+ if((ep = ejPtr(eid)) == NULL) {
+ return -1;
+ }
+
+ if ((vid = hAlloc((void***) &ep->variables)) < 0) {
+ return -1;
+ }
+
+ if (vid >= ep->variableMax) {
+ ep->variableMax = vid + 1;
+ }
+ ep->variables[vid] = symOpen(64) + EJ_OFFSET;
+ return vid;
+
+}
+
+/******************************************************************************/
+/*
+ * Close a variable scope block. The vid parameter is the return value from
+ * the call to ejOpenBlock
+ */
+
+int ejCloseBlock(int eid, int vid)
+{
+ ej_t *ep;
+
+ if((ep = ejPtr(eid)) == NULL) {
+ return -1;
+ }
+ symClose(ep->variables[vid] - EJ_OFFSET);
+ ep->variableMax = hFree((void***) &ep->variables, vid);
+ return 0;
+
+}
+
+/******************************************************************************/
+/*
+ * Create a new variable scope block and evaluate a script. All variables
+ * created during this context will be automatically deleted when complete.
+ */
+
+char_t *ejEvalBlock(int eid, char_t *script, char_t **emsg)
+{
+ char_t* returnVal;
+ int vid;
+
+ a_assert(script);
+
+ vid = ejOpenBlock(eid);
+ returnVal = ejEval(eid, script, emsg);
+ ejCloseBlock(eid, vid);
+
+ return returnVal;
+}
+
+/******************************************************************************/
+/*
+ * Parse and evaluate a Ejscript. The caller may provide a symbol table to
+ * use for variables and function definitions. Return char_t pointer on
+ * success otherwise NULL pointer is returned.
+ */
+
+char_t *ejEval(int eid, char_t *script, char_t **emsg)
+{
+ ej_t *ep;
+ ejinput_t *oldBlock;
+ int state;
+ void *endlessLoopTest;
+ int loopCounter;
+
+
+ a_assert(script);
+
+ if (emsg) {
+ *emsg = NULL;
+ }
+
+ if ((ep = ejPtr(eid)) == NULL) {
+ return NULL;
+ }
+
+ setString(B_L, &ep->result, T(""));
+
+/*
+ * Allocate a new evaluation block, and save the old one
+ */
+ oldBlock = ep->input;
+ ejLexOpenScript(ep, script);
+
+/*
+ * Do the actual parsing and evaluation
+ */
+ loopCounter = 0;
+ endlessLoopTest = NULL;
+
+ do {
+ state = parse(ep, STATE_BEGIN, FLAGS_EXE);
+
+ if (state == STATE_RET) {
+ state = STATE_EOF;
+ }
+/*
+ * prevent parser from going into infinite loop. If parsing the same
+ * line 10 times then fail and report Syntax error. Most normal error
+ * are caught in the parser itself.
+ */
+ if (endlessLoopTest == ep->input->script.servp) {
+ if (loopCounter++ > 10) {
+ state = STATE_ERR;
+ ejError(ep, T("Syntax error"));
+ }
+ } else {
+ endlessLoopTest = ep->input->script.servp;
+ loopCounter = 0;
+ }
+ } while (state != STATE_EOF && state != STATE_ERR);
+
+ ejLexCloseScript(ep);
+
+/*
+ * Return any error string to the user
+ */
+ if (state == STATE_ERR && emsg) {
+ *emsg = bstrdup(B_L, ep->error);
+ }
+
+/*
+ * Restore the old evaluation block
+ */
+ ep->input = oldBlock;
+
+ if (state == STATE_EOF) {
+ return ep->result;
+ }
+
+ if (state == STATE_ERR) {
+ return NULL;
+ }
+
+ return ep->result;
+}
+
+/******************************************************************************/
+/*
+ * Recursive descent parser for Ejscript
+ */
+
+static int parse(ej_t *ep, int state, int flags)
+{
+ a_assert(ep);
+
+ switch (state) {
+/*
+ * Any statement, function arguments or conditional expressions
+ */
+ case STATE_STMT:
+ if ((state = parseStmt(ep, state, flags)) != STATE_STMT_DONE &&
+ state != STATE_EOF && state != STATE_STMT_BLOCK_DONE &&
+ state != STATE_RET) {
+ state = STATE_ERR;
+ }
+ break;
+
+ case STATE_DEC:
+ if ((state = parseStmt(ep, state, flags)) != STATE_DEC_DONE &&
+ state != STATE_EOF) {
+ state = STATE_ERR;
+ }
+ break;
+
+ case STATE_EXPR:
+ if ((state = parseStmt(ep, state, flags)) != STATE_EXPR_DONE &&
+ state != STATE_EOF) {
+ state = STATE_ERR;
+ }
+ break;
+
+/*
+ * Variable declaration list
+ */
+ case STATE_DEC_LIST:
+ state = parseDeclaration(ep, state, flags);
+ break;
+
+/*
+ * Function argument string
+ */
+ case STATE_ARG_LIST:
+ state = parseArgs(ep, state, flags);
+ break;
+
+/*
+ * Logical condition list (relational operations separated by &&, ||)
+ */
+ case STATE_COND:
+ state = parseCond(ep, state, flags);
+ break;
+
+/*
+ * Expression list
+ */
+ case STATE_RELEXP:
+ state = parseExpr(ep, state, flags);
+ break;
+ }
+
+ if (state == STATE_ERR && ep->error == NULL) {
+ ejError(ep, T("Syntax error"));
+ }
+ return state;
+}
+
+/******************************************************************************/
+/*
+ * Parse any statement including functions and simple relational operations
+ */
+
+static int parseStmt(ej_t *ep, int state, int flags)
+{
+ ejfunc_t func;
+ ejfunc_t *saveFunc;
+ ejinput_t condScript, endScript, bodyScript, incrScript;
+ char_t *value, *identifier;
+ int done, expectSemi, thenFlags, elseFlags, tid, cond, forFlags;
+ int ejVarType;
+
+ a_assert(ep);
+
+/*
+ * Set these to NULL, else we try to free them if an error occurs.
+ */
+ endScript.putBackToken = NULL;
+ bodyScript.putBackToken = NULL;
+ incrScript.putBackToken = NULL;
+ condScript.putBackToken = NULL;
+
+ expectSemi = 0;
+ saveFunc = NULL;
+
+ for (done = 0; !done; ) {
+ tid = ejLexGetToken(ep, state);
+
+ switch (tid) {
+ default:
+ ejLexPutbackToken(ep, TOK_EXPR, ep->token);
+ done++;
+ break;
+
+ case TOK_ERR:
+ state = STATE_ERR;
+ done++;
+ break;
+
+ case TOK_EOF:
+ state = STATE_EOF;
+ done++;
+ break;
+
+ case TOK_NEWLINE:
+ break;
+
+ case TOK_SEMI:
+/*
+ * This case is when we discover no statement and just a lone ';'
+ */
+ if (state != STATE_STMT) {
+ ejLexPutbackToken(ep, tid, ep->token);
+ }
+ done++;
+ break;
+
+ case TOK_ID:
+/*
+ * This could either be a reference to a variable or an assignment
+ */
+ identifier = NULL;
+ setString(B_L, &identifier, ep->token);
+/*
+ * Peek ahead to see if this is an assignment
+ */
+ tid = ejLexGetToken(ep, state);
+ if (tid == TOK_ASSIGNMENT) {
+ if (parse(ep, STATE_RELEXP, flags) != STATE_RELEXP_DONE) {
+ clearString(&identifier);
+ goto error;
+ }
+ if (flags & FLAGS_EXE) {
+ if ( state == STATE_DEC ) {
+ ejSetLocalVar(ep->eid, identifier, ep->result);
+ } else {
+ ejVarType = ejGetVar(ep->eid, identifier, &value);
+ if (ejVarType > 0) {
+ ejSetLocalVar(ep->eid, identifier, ep->result);
+ } else {
+ ejSetGlobalVar(ep->eid, identifier, ep->result);
+ }
+ }
+ }
+
+ } else if (tid == TOK_INC_DEC ) {
+ value = NULL;
+ if (flags & FLAGS_EXE) {
+ ejVarType = ejGetVar(ep->eid, identifier, &value);
+ if (ejVarType < 0) {
+ ejError(ep, T("Undefined variable %s\n"), identifier);
+ goto error;
+ }
+ setString(B_L, &ep->result, value);
+ if (evalExpr(ep, value, (int) *ep->token, T("1")) < 0) {
+ state = STATE_ERR;
+ break;
+ }
+
+ if (ejVarType > 0) {
+ ejSetLocalVar(ep->eid, identifier, ep->result);
+ } else {
+ ejSetGlobalVar(ep->eid, identifier, ep->result);
+ }
+ }
+
+ } else {
+/*
+ * If we are processing a declaration, allow undefined vars
+ */
+ value = NULL;
+ if (state == STATE_DEC) {
+ if (ejGetVar(ep->eid, identifier, &value) > 0) {
+ ejError(ep, T("Variable already declared"),
+ identifier);
+ clearString(&identifier);
+ goto error;
+ }
+ ejSetLocalVar(ep->eid, identifier, NULL);
+ } else {
+ if ( flags & FLAGS_EXE ) {
+ if (ejGetVar(ep->eid, identifier, &value) < 0) {
+ ejError(ep, T("Undefined variable %s\n"),
+ identifier);
+ clearString(&identifier);
+ goto error;
+ }
+ }
+ }
+ setString(B_L, &ep->result, value);
+ ejLexPutbackToken(ep, tid, ep->token);
+ }
+ clearString(&identifier);
+
+ if (state == STATE_STMT) {
+ expectSemi++;
+ }
+ done++;
+ break;
+
+ case TOK_LITERAL:
+/*
+ * Set the result to the literal (number or string constant)
+ */
+ setString(B_L, &ep->result, ep->token);
+ if (state == STATE_STMT) {
+ expectSemi++;
+ }
+ done++;
+ break;
+
+ case TOK_FUNCTION:
+/*
+ * We must save any current ep->func value for the current stack frame
+ */
+ if (ep->func) {
+ saveFunc = ep->func;
+ }
+ memset(&func, 0, sizeof(ejfunc_t));
+ setString(B_L, &func.fname, ep->token);
+ ep->func = &func;
+
+ setString(B_L, &ep->result, T(""));
+ if (ejLexGetToken(ep, state) != TOK_LPAREN) {
+ freeFunc(&func);
+ goto error;
+ }
+
+ if (parse(ep, STATE_ARG_LIST, flags) != STATE_ARG_LIST_DONE) {
+ freeFunc(&func);
+ ep->func = saveFunc;
+ goto error;
+ }
+/*
+ * Evaluate the function if required
+ */
+ if (flags & FLAGS_EXE && evalFunction(ep) < 0) {
+ freeFunc(&func);
+ ep->func = saveFunc;
+ goto error;
+ }
+
+ freeFunc(&func);
+ ep->func = saveFunc;
+
+ if (ejLexGetToken(ep, state) != TOK_RPAREN) {
+ goto error;
+ }
+ if (state == STATE_STMT) {
+ expectSemi++;
+ }
+ done++;
+ break;
+
+ case TOK_IF:
+ if (state != STATE_STMT) {
+ goto error;
+ }
+ if (ejLexGetToken(ep, state) != TOK_LPAREN) {
+ goto error;
+ }
+/*
+ * Evaluate the entire condition list "(condition)"
+ */
+ if (parse(ep, STATE_COND, flags) != STATE_COND_DONE) {
+ goto error;
+ }
+ if (ejLexGetToken(ep, state) != TOK_RPAREN) {
+ goto error;
+ }
+/*
+ * This is the "then" case. We need to always parse both cases and
+ * execute only the relevant case.
+ */
+ if (*ep->result == '1') {
+ thenFlags = flags;
+ elseFlags = flags & ~FLAGS_EXE;
+ } else {
+ thenFlags = flags & ~FLAGS_EXE;
+ elseFlags = flags;
+ }
+/*
+ * Process the "then" case. Allow for RETURN statement
+ */
+ switch (parse(ep, STATE_STMT, thenFlags)) {
+ case STATE_RET:
+ return STATE_RET;
+ case STATE_STMT_DONE:
+ break;
+ default:
+ goto error;
+ }
+/*
+ * check to see if there is an "else" case
+ */
+ ejRemoveNewlines(ep, state);
+ tid = ejLexGetToken(ep, state);
+ if (tid != TOK_ELSE) {
+ ejLexPutbackToken(ep, tid, ep->token);
+ done++;
+ break;
+ }
+/*
+ * Process the "else" case. Allow for return.
+ */
+ switch (parse(ep, STATE_STMT, elseFlags)) {
+ case STATE_RET:
+ return STATE_RET;
+ case STATE_STMT_DONE:
+ break;
+ default:
+ goto error;
+ }
+ done++;
+ break;
+
+ case TOK_FOR:
+/*
+ * Format for the expression is:
+ *
+ * for (initial; condition; incr) {
+ * body;
+ * }
+ */
+ if (state != STATE_STMT) {
+ goto error;
+ }
+ if (ejLexGetToken(ep, state) != TOK_LPAREN) {
+ goto error;
+ }
+
+/*
+ * Evaluate the for loop initialization statement
+ */
+ if (parse(ep, STATE_EXPR, flags) != STATE_EXPR_DONE) {
+ goto error;
+ }
+ if (ejLexGetToken(ep, state) != TOK_SEMI) {
+ goto error;
+ }
+
+/*
+ * The first time through, we save the current input context just
+ * to each step: prior to the conditional, the loop increment and the
+ * loop body.
+ */
+ ejLexSaveInputState(ep, &condScript);
+ if (parse(ep, STATE_COND, flags) != STATE_COND_DONE) {
+ goto error;
+ }
+ cond = (*ep->result != '0');
+
+ if (ejLexGetToken(ep, state) != TOK_SEMI) {
+ goto error;
+ }
+
+/*
+ * Don't execute the loop increment statement or the body first time
+ */
+ forFlags = flags & ~FLAGS_EXE;
+ ejLexSaveInputState(ep, &incrScript);
+ if (parse(ep, STATE_EXPR, forFlags) != STATE_EXPR_DONE) {
+ goto error;
+ }
+ if (ejLexGetToken(ep, state) != TOK_RPAREN) {
+ goto error;
+ }
+
+/*
+ * Parse the body and remember the end of the body script
+ */
+ ejLexSaveInputState(ep, &bodyScript);
+ if (parse(ep, STATE_STMT, forFlags) != STATE_STMT_DONE) {
+ goto error;
+ }
+ ejLexSaveInputState(ep, &endScript);
+
+/*
+ * Now actually do the for loop. Note loop has been rotated
+ */
+ while (cond && (flags & FLAGS_EXE) ) {
+/*
+ * Evaluate the body
+ */
+ ejLexRestoreInputState(ep, &bodyScript);
+
+ switch (parse(ep, STATE_STMT, flags)) {
+ case STATE_RET:
+ return STATE_RET;
+ case STATE_STMT_DONE:
+ break;
+ default:
+ goto error;
+ }
+/*
+ * Evaluate the increment script
+ */
+ ejLexRestoreInputState(ep, &incrScript);
+ if (parse(ep, STATE_EXPR, flags) != STATE_EXPR_DONE) {
+ goto error;
+ }
+/*
+ * Evaluate the condition
+ */
+ ejLexRestoreInputState(ep, &condScript);
+ if (parse(ep, STATE_COND, flags) != STATE_COND_DONE) {
+ goto error;
+ }
+ cond = (*ep->result != '0');
+ }
+ ejLexRestoreInputState(ep, &endScript);
+ done++;
+ break;
+
+ case TOK_VAR:
+ if (parse(ep, STATE_DEC_LIST, flags) != STATE_DEC_LIST_DONE) {
+ goto error;
+ }
+ done++;
+ break;
+
+ case TOK_COMMA:
+ ejLexPutbackToken(ep, TOK_EXPR, ep->token);
+ done++;
+ break;
+
+ case TOK_LPAREN:
+ if (state == STATE_EXPR) {
+ if (parse(ep, STATE_RELEXP, flags) != STATE_RELEXP_DONE) {
+ goto error;
+ }
+ if (ejLexGetToken(ep, state) != TOK_RPAREN) {
+ goto error;
+ }
+ return STATE_EXPR_DONE;
+ }
+ done++;
+ break;
+
+ case TOK_RPAREN:
+ ejLexPutbackToken(ep, tid, ep->token);
+ return STATE_EXPR_DONE;
+
+ case TOK_LBRACE:
+/*
+ * This handles any code in braces except "if () {} else {}"
+ */
+ if (state != STATE_STMT) {
+ goto error;
+ }
+
+/*
+ * Parse will return STATE_STMT_BLOCK_DONE when the RBRACE is seen
+ */
+ do {
+ state = parse(ep, STATE_STMT, flags);
+ } while (state == STATE_STMT_DONE);
+
+/*
+ * Allow return statement.
+ */
+ if (state == STATE_RET) {
+ return state;
+ }
+
+ if (ejLexGetToken(ep, state) != TOK_RBRACE) {
+ goto error;
+ }
+ return STATE_STMT_DONE;
+
+ case TOK_RBRACE:
+ if (state == STATE_STMT) {
+ ejLexPutbackToken(ep, tid, ep->token);
+ return STATE_STMT_BLOCK_DONE;
+ }
+ goto error;
+
+ case TOK_RETURN:
+ if (parse(ep, STATE_RELEXP, flags) != STATE_RELEXP_DONE) {
+ goto error;
+ }
+ if (flags & FLAGS_EXE) {
+ while ( ejLexGetToken(ep, state) != TOK_EOF );
+ done++;
+ return STATE_RET;
+ }
+ break;
+ }
+ }
+
+ if (expectSemi) {
+ tid = ejLexGetToken(ep, state);
+ if (tid != TOK_SEMI && tid != TOK_NEWLINE) {
+ goto error;
+ }
+
+/*
+ * Skip newline after semi-colon
+ */
+ ejRemoveNewlines(ep, state);
+ }
+
+/*
+ * Free resources and return the correct status
+ */
+doneParse:
+ if (tid == TOK_FOR) {
+ ejLexFreeInputState(ep, &condScript);
+ ejLexFreeInputState(ep, &incrScript);
+ ejLexFreeInputState(ep, &endScript);
+ ejLexFreeInputState(ep, &bodyScript);
+ }
+
+ if (state == STATE_STMT) {
+ return STATE_STMT_DONE;
+ } else if (state == STATE_DEC) {
+ return STATE_DEC_DONE;
+ } else if (state == STATE_EXPR) {
+ return STATE_EXPR_DONE;
+ } else if (state == STATE_EOF) {
+ return state;
+ } else {
+ return STATE_ERR;
+ }
+
+/*
+ * Common error exit
+ */
+error:
+ state = STATE_ERR;
+ goto doneParse;
+}
+
+/******************************************************************************/
+/*
+ * Parse variable declaration list
+ */
+
+static int parseDeclaration(ej_t *ep, int state, int flags)
+{
+ int tid;
+
+ a_assert(ep);
+
+/*
+ * Declarations can be of the following forms:
+ * var x;
+ * var x, y, z;
+ * var x = 1 + 2 / 3, y = 2 + 4;
+ *
+ * We set the variable to NULL if there is no associated assignment.
+ */
+
+ do {
+ if ((tid = ejLexGetToken(ep, state)) != TOK_ID) {
+ return STATE_ERR;
+ }
+ ejLexPutbackToken(ep, tid, ep->token);
+
+/*
+ * Parse the entire assignment or simple identifier declaration
+ */
+ if (parse(ep, STATE_DEC, flags) != STATE_DEC_DONE) {
+ return STATE_ERR;
+ }
+
+/*
+ * Peek at the next token, continue if comma seen
+ */
+ tid = ejLexGetToken(ep, state);
+ if (tid == TOK_SEMI) {
+ return STATE_DEC_LIST_DONE;
+ } else if (tid != TOK_COMMA) {
+ return STATE_ERR;
+ }
+ } while (tid == TOK_COMMA);
+
+ if (tid != TOK_SEMI) {
+ return STATE_ERR;
+ }
+ return STATE_DEC_LIST_DONE;
+}
+
+/******************************************************************************/
+/*
+ * Parse function arguments
+ */
+
+static int parseArgs(ej_t *ep, int state, int flags)
+{
+ int tid, aid;
+
+ a_assert(ep);
+
+ do {
+ state = parse(ep, STATE_RELEXP, flags);
+ if (state == STATE_EOF || state == STATE_ERR) {
+ return state;
+ }
+ if (state == STATE_RELEXP_DONE) {
+ aid = hAlloc((void***) &ep->func->args);
+ ep->func->args[aid] = bstrdup(B_L, ep->result);
+ ep->func->nArgs++;
+ }
+/*
+ * Peek at the next token, continue if more args (ie. comma seen)
+ */
+ tid = ejLexGetToken(ep, state);
+ if (tid != TOK_COMMA) {
+ ejLexPutbackToken(ep, tid, ep->token);
+ }
+ } while (tid == TOK_COMMA);
+
+ if (tid != TOK_RPAREN && state != STATE_RELEXP_DONE) {
+ return STATE_ERR;
+ }
+ return STATE_ARG_LIST_DONE;
+}
+
+/******************************************************************************/
+/*
+ * Parse conditional expression (relational ops separated by ||, &&)
+ */
+
+static int parseCond(ej_t *ep, int state, int flags)
+{
+ char_t *lhs, *rhs;
+ int tid, operator;
+
+ a_assert(ep);
+
+ setString(B_L, &ep->result, T(""));
+ rhs = lhs = NULL;
+ operator = 0;
+
+ do {
+/*
+ * Recurse to handle one side of a conditional. Accumulate the
+ * left hand side and the final result in ep->result.
+ */
+ state = parse(ep, STATE_RELEXP, flags);
+ if (state != STATE_RELEXP_DONE) {
+ state = STATE_ERR;
+ break;
+ }
+
+ if (operator > 0) {
+ setString(B_L, &rhs, ep->result);
+ if (evalCond(ep, lhs, operator, rhs) < 0) {
+ state = STATE_ERR;
+ break;
+ }
+ }
+ setString(B_L, &lhs, ep->result);
+
+ tid = ejLexGetToken(ep, state);
+ if (tid == TOK_LOGICAL) {
+ operator = (int) *ep->token;
+
+ } else if (tid == TOK_RPAREN || tid == TOK_SEMI) {
+ ejLexPutbackToken(ep, tid, ep->token);
+ state = STATE_COND_DONE;
+ break;
+
+ } else {
+ ejLexPutbackToken(ep, tid, ep->token);
+ }
+
+ } while (state == STATE_RELEXP_DONE);
+
+ if (lhs) {
+ bfree(B_L, lhs);
+ }
+
+ if (rhs) {
+ bfree(B_L, rhs);
+ }
+ return state;
+}
+
+/******************************************************************************/
+/*
+ * Parse expression (leftHandSide operator rightHandSide)
+ */
+
+static int parseExpr(ej_t *ep, int state, int flags)
+{
+ char_t *lhs, *rhs;
+ int rel, tid;
+
+ a_assert(ep);
+
+ setString(B_L, &ep->result, T(""));
+ rhs = lhs = NULL;
+ rel = 0;
+ tid = 0;
+
+ do {
+/*
+ * This loop will handle an entire expression list. We call parse
+ * to evalutate each term which returns the result in ep->result.
+ */
+ if (tid == TOK_LOGICAL) {
+ if ((state = parse(ep, STATE_RELEXP, flags)) != STATE_RELEXP_DONE) {
+ state = STATE_ERR;
+ break;
+ }
+ } else {
+ if ((state = parse(ep, STATE_EXPR, flags)) != STATE_EXPR_DONE) {
+ state = STATE_ERR;
+ break;
+ }
+ }
+
+ if (rel > 0) {
+ setString(B_L, &rhs, ep->result);
+ if (tid == TOK_LOGICAL) {
+ if (evalCond(ep, lhs, rel, rhs) < 0) {
+ state = STATE_ERR;
+ break;
+ }
+ } else {
+ if (evalExpr(ep, lhs, rel, rhs) < 0) {
+ state = STATE_ERR;
+ break;
+ }
+ }
+ }
+ setString(B_L, &lhs, ep->result);
+
+ if ((tid = ejLexGetToken(ep, state)) == TOK_EXPR ||
+ tid == TOK_INC_DEC || tid == TOK_LOGICAL) {
+ rel = (int) *ep->token;
+
+ } else {
+ ejLexPutbackToken(ep, tid, ep->token);
+ state = STATE_RELEXP_DONE;
+ }
+
+ } while (state == STATE_EXPR_DONE);
+
+ if (rhs) {
+ bfree(B_L, rhs);
+ }
+
+ if (lhs) {
+ bfree(B_L, lhs);
+ }
+
+ return state;
+}
+
+/******************************************************************************/
+/*
+ * Evaluate a condition. Implements &&, ||, !
+ */
+
+static int evalCond(ej_t *ep, char_t *lhs, int rel, char_t *rhs)
+{
+ char_t buf[16];
+ int l, r, lval;
+
+ a_assert(lhs);
+ a_assert(rhs);
+ a_assert(rel > 0);
+
+ lval = 0;
+ if (gisdigit((int)*lhs) && gisdigit((int)*rhs)) {
+ l = gatoi(lhs);
+ r = gatoi(rhs);
+ switch (rel) {
+ case COND_AND:
+ lval = l && r;
+ break;
+ case COND_OR:
+ lval = l || r;
+ break;
+ default:
+ ejError(ep, T("Bad operator %d"), rel);
+ return -1;
+ }
+ } else {
+ if (!gisdigit((int)*lhs)) {
+ ejError(ep, T("Conditional must be numeric"), lhs);
+ } else {
+ ejError(ep, T("Conditional must be numeric"), rhs);
+ }
+ }
+
+ stritoa(lval, buf, sizeof(buf));
+ setString(B_L, &ep->result, buf);
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Evaluate an operation
+ */
+
+static int evalExpr(ej_t *ep, char_t *lhs, int rel, char_t *rhs)
+{
+ char_t *cp, buf[16];
+ int numeric, l, r, lval;
+
+ a_assert(lhs);
+ a_assert(rhs);
+ a_assert(rel > 0);
+
+/*
+ * All of the characters in the lhs and rhs must be numeric
+ */
+ numeric = 1;
+ for (cp = lhs; *cp; cp++) {
+ if (!gisdigit((int)*cp)) {
+ numeric = 0;
+ break;
+ }
+ }
+
+ if (numeric) {
+ for (cp = rhs; *cp; cp++) {
+ if (!gisdigit((int)*cp)) {
+ numeric = 0;
+ break;
+ }
+ }
+ }
+
+ if (numeric) {
+ l = gatoi(lhs);
+ r = gatoi(rhs);
+ switch (rel) {
+ case EXPR_PLUS:
+ lval = l + r;
+ break;
+ case EXPR_INC:
+ lval = l + 1;
+ break;
+ case EXPR_MINUS:
+ lval = l - r;
+ break;
+ case EXPR_DEC:
+ lval = l - 1;
+ break;
+ case EXPR_MUL:
+ lval = l * r;
+ break;
+ case EXPR_DIV:
+ if (r != 0) {
+ lval = l / r;
+ } else {
+ lval = 0;
+ }
+ break;
+ case EXPR_MOD:
+ if (r != 0) {
+ lval = l % r;
+ } else {
+ lval = 0;
+ }
+ break;
+ case EXPR_LSHIFT:
+ lval = l << r;
+ break;
+ case EXPR_RSHIFT:
+ lval = l >> r;
+ break;
+ case EXPR_EQ:
+ lval = l == r;
+ break;
+ case EXPR_NOTEQ:
+ lval = l != r;
+ break;
+ case EXPR_LESS:
+ lval = (l < r) ? 1 : 0;
+ break;
+ case EXPR_LESSEQ:
+ lval = (l <= r) ? 1 : 0;
+ break;
+ case EXPR_GREATER:
+ lval = (l > r) ? 1 : 0;
+ break;
+ case EXPR_GREATEREQ:
+ lval = (l >= r) ? 1 : 0;
+ break;
+ case EXPR_BOOL_COMP:
+ lval = (r == 0) ? 1 : 0;
+ break;
+ default:
+ ejError(ep, T("Bad operator %d"), rel);
+ return -1;
+ }
+
+ } else {
+ switch (rel) {
+ case EXPR_PLUS:
+ clearString(&ep->result);
+ appendString(&ep->result, lhs);
+ appendString(&ep->result, rhs);
+ return 0;
+ case EXPR_LESS:
+ lval = gstrcmp(lhs, rhs) < 0;
+ break;
+ case EXPR_LESSEQ:
+ lval = gstrcmp(lhs, rhs) <= 0;
+ break;
+ case EXPR_GREATER:
+ lval = gstrcmp(lhs, rhs) > 0;
+ break;
+ case EXPR_GREATEREQ:
+ lval = gstrcmp(lhs, rhs) >= 0;
+ break;
+ case EXPR_EQ:
+ lval = gstrcmp(lhs, rhs) == 0;
+ break;
+ case EXPR_NOTEQ:
+ lval = gstrcmp(lhs, rhs) != 0;
+ break;
+ case EXPR_INC:
+ case EXPR_DEC:
+ case EXPR_MINUS:
+ case EXPR_DIV:
+ case EXPR_MOD:
+ case EXPR_LSHIFT:
+ case EXPR_RSHIFT:
+ default:
+ ejError(ep, T("Bad operator"));
+ return -1;
+ }
+ }
+
+ stritoa(lval, buf, sizeof(buf));
+ setString(B_L, &ep->result, buf);
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Evaluate a function
+ */
+
+static int evalFunction(ej_t *ep)
+{
+ sym_t *sp;
+ int (*fn)(int eid, void *handle, int argc, char_t **argv);
+
+ if ((sp = symLookup(ep->functions, ep->func->fname)) == NULL) {
+ ejError(ep, T("Undefined procedure %s"), ep->func->fname);
+ return -1;
+ }
+
+ fn = (int (*)(int, void*, int, char_t**)) sp->content.value.integer;
+ if (fn == NULL) {
+ ejError(ep, T("Undefined procedure %s"), ep->func->fname);
+ return -1;
+ }
+
+ return (*fn)(ep->eid, (void*) ep->userHandle, ep->func->nArgs,
+ ep->func->args);
+}
+
+/******************************************************************************/
+/*
+ * Output a parse ej_error message
+ */
+
+void ejError(ej_t* ep, char_t* fmt, ...)
+{
+ va_list args;
+ ejinput_t *ip;
+ char_t *errbuf, *msgbuf;
+
+ a_assert(ep);
+ a_assert(fmt);
+ ip = ep->input;
+
+ va_start(args, fmt);
+ msgbuf = NULL;
+ fmtValloc(&msgbuf, E_MAX_ERROR, fmt, args);
+ va_end(args);
+
+ if (ep && ip) {
+ fmtAlloc(&errbuf, E_MAX_ERROR, T("%s\n At line %d, line => \n\n%s\n"),
+ msgbuf, ip->lineNumber, ip->line);
+ bfreeSafe(B_L, ep->error);
+ ep->error = errbuf;
+ }
+ bfreeSafe(B_L, msgbuf);
+}
+
+/******************************************************************************/
+/*
+ * Clear a string value
+ */
+
+static void clearString(char_t **ptr)
+{
+ a_assert(ptr);
+
+ if (*ptr) {
+ bfree(B_L, *ptr);
+ }
+ *ptr = NULL;
+}
+
+/******************************************************************************/
+/*
+ * Set a string value
+ */
+
+static void setString(B_ARGS_DEC, char_t **ptr, char_t *s)
+{
+ a_assert(ptr);
+
+ if (*ptr) {
+ bfree(B_ARGS, *ptr);
+ }
+ *ptr = bstrdup(B_ARGS, s);
+}
+
+/******************************************************************************/
+/*
+ * Append to the pointer value
+ */
+
+static void appendString(char_t **ptr, char_t *s)
+{
+ int len, oldlen;
+
+ a_assert(ptr);
+
+ if (*ptr) {
+ len = gstrlen(s);
+ oldlen = gstrlen(*ptr);
+ *ptr = brealloc(B_L, *ptr, (len + oldlen + 1) * sizeof(char_t));
+ gstrcpy(&(*ptr)[oldlen], s);
+ } else {
+ *ptr = bstrdup(B_L, s);
+ }
+}
+
+/******************************************************************************/
+/*
+ * Define a function
+ */
+
+int ejSetGlobalFunction(int eid, char_t *name,
+ int (*fn)(int eid, void *handle, int argc, char_t **argv))
+{
+ ej_t *ep;
+
+ if ((ep = ejPtr(eid)) == NULL) {
+ return -1;
+ }
+ return ejSetGlobalFunctionDirect(ep->functions, name, fn);
+}
+
+/******************************************************************************/
+/*
+ * Define a function directly into the function symbol table.
+ */
+
+int ejSetGlobalFunctionDirect(sym_fd_t functions, char_t *name,
+ int (*fn)(int eid, void *handle, int argc, char_t **argv))
+{
+ if (symEnter(functions, name, valueInteger((long) fn), 0) == NULL) {
+ return -1;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Remove ("undefine") a function
+ */
+
+int ejRemoveGlobalFunction(int eid, char_t *name)
+{
+ ej_t *ep;
+
+ if ((ep = ejPtr(eid)) == NULL) {
+ return -1;
+ }
+ return symDelete(ep->functions, name);
+}
+
+/******************************************************************************/
+/*
+ * Get a function definition
+ */
+
+void *ejGetGlobalFunction(int eid, char_t *name)
+{
+ ej_t *ep;
+ sym_t *sp;
+ int (*fn)(int eid, void *handle, int argc, char_t **argv);
+
+ if ((ep = ejPtr(eid)) == NULL) {
+ return NULL;
+ }
+
+ if ((sp = symLookup(ep->functions, name)) != NULL) {
+ fn = (int (*)(int, void*, int, char_t**)) sp->content.value.integer;
+ return (void*) fn;
+ }
+ return NULL;
+}
+
+/******************************************************************************/
+/*
+ * Utility routine to crack Ejscript arguments. Return the number of args
+ * seen. This routine only supports %s and %d type args.
+ *
+ * Typical usage:
+ *
+ * if (ejArgs(argc, argv, "%s %d", &name, &age) < 2) {
+ * error("Insufficient args\n");
+ * return -1;
+ * }
+ */
+
+int ejArgs(int argc, char_t **argv, char_t *fmt, ...)
+{
+ va_list vargs;
+ char_t *cp, **sp;
+ int *ip;
+ int argn;
+
+ va_start(vargs, fmt);
+
+ if (argv == NULL) {
+ return 0;
+ }
+
+ for (argn = 0, cp = fmt; cp && *cp && argv[argn]; ) {
+ if (*cp++ != '%') {
+ continue;
+ }
+
+ switch (*cp) {
+ case 'd':
+ ip = va_arg(vargs, int*);
+ *ip = gatoi(argv[argn]);
+ break;
+
+ case 's':
+ sp = va_arg(vargs, char_t**);
+ *sp = argv[argn];
+ break;
+
+ default:
+/*
+ * Unsupported
+ */
+ a_assert(0);
+ }
+ argn++;
+ }
+
+ va_end(vargs);
+ return argn;
+}
+
+/******************************************************************************/
+/*
+ * Define the user handle
+ */
+
+void ejSetUserHandle(int eid, int handle)
+{
+ ej_t *ep;
+
+ if ((ep = ejPtr(eid)) == NULL) {
+ return;
+ }
+ ep->userHandle = handle;
+}
+
+/******************************************************************************/
+/*
+ * Get the user handle
+ */
+
+int ejGetUserHandle(int eid)
+{
+ ej_t *ep;
+
+ if ((ep = ejPtr(eid)) == NULL) {
+ return -1;
+ }
+ return ep->userHandle;
+}
+
+/******************************************************************************/
+/*
+ * Get the current line number
+ */
+
+int ejGetLineNumber(int eid)
+{
+ ej_t *ep;
+
+ if ((ep = ejPtr(eid)) == NULL) {
+ return -1;
+ }
+ return ep->input->lineNumber;
+}
+
+/******************************************************************************/
+/*
+ * Set the result
+ */
+
+void ejSetResult(int eid, char_t *s)
+{
+ ej_t *ep;
+
+ if ((ep = ejPtr(eid)) == NULL) {
+ return;
+ }
+ setString(B_L, &ep->result, s);
+}
+
+/******************************************************************************/
+/*
+ * Get the result
+ */
+
+char_t *ejGetResult(int eid)
+{
+ ej_t *ep;
+
+ if ((ep = ejPtr(eid)) == NULL) {
+ return NULL;
+ }
+ return ep->result;
+}
+
+/******************************************************************************/
+/*
+ * Set a variable. Note: a variable with a value of NULL means declared but
+ * undefined. The value is defined in the top-most variable frame.
+ */
+
+void ejSetVar(int eid, char_t *var, char_t *value)
+{
+ ej_t *ep;
+ value_t v;
+
+ a_assert(var && *var);
+
+ if ((ep = ejPtr(eid)) == NULL) {
+ return;
+ }
+
+ if (value == NULL) {
+ v = valueString(value, 0);
+ } else {
+ v = valueString(value, VALUE_ALLOCATE);
+ }
+ symEnter(ep->variables[ep->variableMax - 1] - EJ_OFFSET, var, v, 0);
+}
+
+/******************************************************************************/
+/*
+ * Set a local variable. Note: a variable with a value of NULL means
+ * declared but undefined. The value is defined in the top-most variable frame.
+ */
+
+void ejSetLocalVar(int eid, char_t *var, char_t *value)
+{
+ ej_t *ep;
+ value_t v;
+
+ a_assert(var && *var);
+
+ if ((ep = ejPtr(eid)) == NULL) {
+ return;
+ }
+
+ if (value == NULL) {
+ v = valueString(value, 0);
+ } else {
+ v = valueString(value, VALUE_ALLOCATE);
+ }
+ symEnter(ep->variables[ep->variableMax - 1] - EJ_OFFSET, var, v, 0);
+}
+
+/******************************************************************************/
+/*
+ * Set a global variable. Note: a variable with a value of NULL means
+ * declared but undefined. The value is defined in the global variable frame.
+ */
+
+void ejSetGlobalVar(int eid, char_t *var, char_t *value)
+{
+ ej_t *ep;
+ value_t v;
+
+ a_assert(var && *var);
+
+ if ((ep = ejPtr(eid)) == NULL) {
+ return;
+ }
+
+ if (value == NULL) {
+ v = valueString(value, 0);
+ } else {
+ v = valueString(value, VALUE_ALLOCATE);
+ }
+ symEnter(ep->variables[0] - EJ_OFFSET, var, v, 0);
+}
+
+/******************************************************************************/
+/*
+ * Get a variable
+ */
+
+int ejGetVar(int eid, char_t *var, char_t **value)
+{
+ ej_t *ep;
+ sym_t *sp;
+ int i;
+
+ a_assert(var && *var);
+ a_assert(value);
+
+ if ((ep = ejPtr(eid)) == NULL) {
+ return -1;
+ }
+
+ i = ep->variableMax - 1;
+ if ((sp = symLookup(ep->variables[i] - EJ_OFFSET, var)) == NULL) {
+ i = 0;
+ if ((sp = symLookup(ep->variables[0] - EJ_OFFSET, var)) == NULL) {
+ return -1;
+ }
+ }
+ a_assert(sp->content.type == string);
+ *value = sp->content.value.string;
+ return i;
+}
+
+/******************************************************************************/
+/*
+ * Get the variable symbol table
+ */
+
+sym_fd_t ejGetVariableTable(int eid)
+{
+ ej_t *ep;
+
+ if ((ep = ejPtr(eid)) == NULL) {
+ return -1;
+ }
+ return *ep->variables;
+}
+
+/******************************************************************************/
+/*
+ * Get the functions symbol table
+ */
+
+sym_fd_t ejGetFunctionTable(int eid)
+{
+ ej_t *ep;
+
+ if ((ep = ejPtr(eid)) == NULL) {
+ return -1;
+ }
+ return ep->functions;
+}
+
+/******************************************************************************/
+/*
+ * Free an argument list
+ */
+
+static void freeFunc(ejfunc_t *func)
+{
+ int i;
+
+ for (i = func->nArgs - 1; i >= 0; i--) {
+ bfree(B_L, func->args[i]);
+ func->nArgs = hFree((void***) &func->args, i);
+ }
+
+ if (func->fname) {
+ bfree(B_L, func->fname);
+ func->fname = NULL;
+ }
+}
+
+/******************************************************************************/
+/*
+ * Get Ejscript pointer
+ */
+
+static ej_t *ejPtr(int eid)
+{
+ a_assert(0 <= eid && eid < ejMax);
+
+ if (eid < 0 || eid >= ejMax || ejHandles[eid] == NULL) {
+ ejError(NULL, T("Bad handle %d"), eid);
+ return NULL;
+ }
+ return ejHandles[eid];
+}
+
+/******************************************************************************/
+/*
+ * This function removes any new lines. Used for else cases, etc.
+ */
+static void ejRemoveNewlines(ej_t *ep, int state)
+{
+ int tid;
+
+ do {
+ tid = ejLexGetToken(ep, state);
+ } while (tid == TOK_NEWLINE);
+
+ ejLexPutbackToken(ep, tid, ep->token);
+}
+
+/******************************************************************************/
diff --git a/cpukit/httpd/emfdb.c b/cpukit/httpd/emfdb.c
new file mode 100644
index 0000000000..708b51106b
--- /dev/null
+++ b/cpukit/httpd/emfdb.c
@@ -0,0 +1,1050 @@
+/*
+ * emfdb.c -- EMF database compatability functions for GoAhead WebServer.
+ *
+ * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for usage and redistribution license requirements
+ *
+ * $Id$
+ */
+
+/******************************** Description *********************************/
+/*
+ * Textfile-based database support for WebServer 2.1.
+ */
+
+/********************************* Includes ***********************************/
+
+#include "emfdb.h"
+#include "wsIntrn.h"
+
+/********************************* Defines ************************************/
+
+#define KEYWORD_TABLE T("TABLE")
+#define KEYWORD_ROW T("ROW")
+
+/*********************************** Locals ***********************************/
+
+/*
+ * Variable to support the basicSet and basicGet functions.
+ */
+
+static char_t *basicProdDir = NULL;
+static char_t *basicDefaultDir = T("."); /* Default set to current */
+
+/*
+ * hAlloc chain list of table schemas to be closed
+ */
+
+static int dbMaxTables = 0;
+static dbTable_t **dbListTables = NULL;
+
+/****************************** Forward Declarations **************************/
+
+static int crack(char_t *buf, char_t **key, char_t **val);
+static char_t *trim(char_t *str);
+static int GetColumnIndex(int tid, char_t *colName);
+
+/******************************************************************************/
+/*
+ * Add a schema to the module-internal schema database
+ */
+
+int dbRegisterDBSchema(dbTable_t *pTableRegister)
+{
+ dbTable_t *pTable;
+ int tid;
+
+ a_assert(pTableRegister);
+
+ trace(4, T("DB: Registering database table <%s>\n"),
+ pTableRegister->name);
+
+/*
+ * Bump up the size of the table array
+ */
+ tid = hAllocEntry((void*) &dbListTables,
+ &dbMaxTables, sizeof(dbTable_t));
+
+/*
+ * Copy the table schema to the last spot in schema array
+ */
+ a_assert(dbListTables);
+ pTable = dbListTables[tid];
+ a_assert(pTable);
+
+/*
+ * Copy the name of the table
+ */
+ pTable->name = bstrdup(B_L, pTableRegister->name);
+
+/*
+ * Copy the number of columns
+ */
+ pTable->nColumns = pTableRegister->nColumns;
+
+/*
+ * Copy the column definitions
+ */
+ if (pTable->nColumns > 0) {
+ int i;
+ pTable->columnNames = balloc(B_L, sizeof(char_t *) * pTable->nColumns);
+ pTable->columnTypes = balloc(B_L, sizeof(int *) * pTable->nColumns);
+
+ for (i = 0; (i < pTableRegister->nColumns); i++) {
+ pTable->columnNames[i] =
+ bstrdup(B_L, pTableRegister->columnNames[i]);
+ pTable->columnTypes[i] = pTableRegister->columnTypes[i];
+ }
+
+ } else {
+ pTable->columnNames = NULL;
+ pTable->columnTypes = NULL;
+ }
+
+/*
+ * Zero out the table's data (very important!)
+ */
+ pTable->nRows = 0;
+ pTable->rows = NULL;
+
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * This is provided for compatibility with EMF. Tables are "registered"
+ * with staticly defined schemas. There is only one did in this package: 0.
+ */
+
+int dbOpen(char_t *tablename, char_t *filename,
+ int (*gettime)(int did), int flags)
+{
+ basicProdDir = NULL;
+ basicDefaultDir = T(".");
+ dbMaxTables = 0;
+ dbListTables = NULL;
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Delete all the rows of the tables, and all of the tables
+ */
+
+void dbClose(int did)
+{
+ int table, column;
+ dbTable_t *pTable;
+
+/*
+ * Before doing anything, delete all the contents of the database
+ */
+ dbZero(did);
+
+/*
+ * Now delete the tables
+ */
+ for (table = 0; table < dbMaxTables; table++) {
+ pTable = dbListTables[table];
+
+ if (pTable != NULL) {
+/*
+ * Delete the table schema
+ */
+ if (pTable->nColumns) {
+ for (column = 0; column < pTable->nColumns; column++) {
+ bfreeSafe(B_L, pTable->columnNames[column]);
+ }
+ bfreeSafe(B_L, pTable->columnNames);
+ bfreeSafe(B_L, pTable->columnTypes);
+ }
+/*
+ * Delete the table name
+ */
+ bfreeSafe(B_L, pTable->name);
+/*
+ * Free the table
+ */
+ bfreeSafe(B_L, pTable);
+ hFree((void *) &dbListTables, table);
+ }
+ }
+
+ if (dbListTables) {
+ bfree(B_L, dbListTables);
+ }
+
+/*
+ * Set the global table list to a safe value
+ */
+ dbListTables = NULL;
+ dbMaxTables = 0;
+}
+
+
+/******************************************************************************/
+/*
+ * Delete all the data records in all tables
+ */
+
+void dbZero(int did)
+{
+ int table, row, column, nRows, nColumns;
+ int *pRow;
+ dbTable_t *pTable;
+
+/*
+ * Delete all data from all tables
+ */
+ for (table = 0; table < dbMaxTables; table++) {
+ pTable = dbListTables[table];
+/*
+ * Delete the row data contained within the schema
+ */
+ if (pTable) {
+ nColumns = pTable->nColumns;
+ nRows = pTable->nRows;
+ for (row = 0; row < nRows; row++) {
+ pRow = pTable->rows[row];
+ if (pRow) {
+/*
+ * Only delete the contents of rows not previously deleted!
+ */
+ for (column = 0; column < nColumns; column++) {
+ if (pTable->columnTypes[column] == T_STRING) {
+ bfreeSafe(B_L, (char_t *)(pRow[column]));
+ pRow[column] = (int)NULL;
+ }
+ }
+
+ bfreeSafe(B_L, pRow);
+ hFree((void ***) &pTable->rows, row);
+ }
+ }
+
+ pTable->rows = NULL;
+ pTable->nRows = 0;
+ }
+ }
+}
+
+/******************************************************************************/
+/*
+ * Find the a row in the table with the given string in the given column
+ */
+
+int dbSearchStr(int did, char_t *tablename,
+ char_t *colName, char_t *value, int flags)
+{
+ int tid, nRows, nColumns, column;
+ dbTable_t *pTable;
+
+ a_assert(tablename);
+ a_assert(colName);
+ a_assert(value);
+
+ tid = dbGetTableId(0, tablename);
+ a_assert(tid >= 0);
+
+ if ((tid >= 0) && (tid < dbMaxTables) && (dbListTables[tid] != NULL)) {
+ pTable = dbListTables[tid];
+ } else {
+ return DB_ERR_TABLE_NOT_FOUND;
+ }
+
+ nColumns = pTable->nColumns;
+ nRows = pTable->nRows;
+ column = GetColumnIndex(tid, colName);
+ a_assert (column >= 0);
+
+ if (column >= 0) {
+ char_t *compareVal;
+ int row, *pRow;
+/*
+ * Scan through rows until we find a match.
+ * Note that some of these rows may be deleted!
+ */
+ row = 0;
+ while (row < nRows) {
+ pRow = pTable->rows[row];
+ if (pRow) {
+ compareVal = (char_t *)(pRow[column]);
+ if (compareVal && (gstrcmp(compareVal, value) == 0)) {
+ return row;
+ }
+ }
+ row++;
+ }
+ } else {
+/*
+ * Return -2 if search column was not found
+ */
+ trace(3, T("DB: Unable to find column <%s> in table <%s>\n"),
+ colName, tablename);
+ return DB_ERR_COL_NOT_FOUND;
+ }
+
+ return -1;
+}
+
+/******************************************************************************/
+/*
+ * Add a new row to the given table. Return the new row ID.
+ */
+
+int dbAddRow(int did, char_t *tablename)
+{
+ int tid, size;
+ dbTable_t *pTable;
+
+ a_assert(tablename);
+
+ tid = dbGetTableId(0, tablename);
+ a_assert(tid >= 0);
+
+ if ((tid >= 0) && (tid < dbMaxTables) && (dbListTables[tid] != NULL)) {
+ pTable = dbListTables[tid];
+ } else {
+ return DB_ERR_TABLE_NOT_FOUND;
+ }
+
+ a_assert(pTable);
+
+ if (pTable) {
+ trace(5, T("DB: Adding a row to table <%s>\n"), tablename);
+
+ size = pTable->nColumns * max(sizeof(int), sizeof(char_t *));
+ return hAllocEntry((void***) &(pTable->rows), &(pTable->nRows), size);
+ }
+
+ return -1;
+}
+
+/******************************************************************************/
+/*
+ * Delete a row in the table.
+ */
+
+int dbDeleteRow(int did, char_t *tablename, int row)
+{
+ int tid, nColumns, nRows;
+ dbTable_t *pTable;
+
+ a_assert(tablename);
+ tid = dbGetTableId(0, tablename);
+ a_assert(tid >= 0);
+
+ if ((tid >= 0) && (tid < dbMaxTables) && (dbListTables[tid] != NULL)) {
+ pTable = dbListTables[tid];
+ } else {
+ return DB_ERR_TABLE_NOT_FOUND;
+ }
+
+ nColumns = pTable->nColumns;
+ nRows = pTable->nRows;
+
+ if ((row >= 0) && (row < nRows)) {
+ int *pRow = pTable->rows[row];
+
+ if (pRow) {
+ int column = 0;
+/*
+ * Free up any allocated strings
+ */
+ while (column < nColumns) {
+ if (pRow[column] &&
+ (pTable->columnTypes[column] == T_STRING)) {
+ bfree(B_L, (char_t *)pRow[column]);
+ }
+
+ column++;
+ }
+/*
+ * Zero out the row for safety
+ */
+ memset(pRow, 0, nColumns * max(sizeof(int), sizeof(char_t *)));
+
+ bfreeSafe(B_L, pRow);
+ pTable->nRows = hFree((void ***)&pTable->rows, row);
+ trace(5, T("DB: Deleted row <%d> from table <%s>\n"),
+ row, tablename);
+ }
+ return 0;
+ } else {
+ trace(3, T("DB: Unable to delete row <%d> from table <%s>\n"),
+ row, tablename);
+ }
+
+ return -1;
+}
+
+/*****************************************************************************/
+/*
+ * Grow the rows in the table to the nominated size.
+ */
+
+int dbSetTableNrow(int did, char_t *tablename, int nNewRows)
+{
+ int nRet, tid, nRows, nColumns;
+ dbTable_t *pTable;
+
+ a_assert(tablename);
+ tid = dbGetTableId(0, tablename);
+ a_assert(tid >= 0) ;
+
+ if ((tid >= 0) && (tid < dbMaxTables) && (dbListTables[tid] != NULL)) {
+ pTable = dbListTables[tid];
+ } else {
+ return DB_ERR_TABLE_NOT_FOUND;
+ }
+
+ nRet = -1;
+
+ a_assert(pTable);
+ if (pTable) {
+ nColumns = pTable->nColumns;
+ nRows = pTable->nRows;
+ nRet = 0;
+
+ if (nRows >= nNewRows) {
+/*
+ * If number of rows already allocated exceeds requested number, do nothing
+ */
+ trace(4, T("DB: Ignoring row set to <%d> in table <%s>\n"),
+ nNewRows, tablename);
+ } else {
+ trace(4, T("DB: Setting rows to <%d> in table <%s>\n"),
+ nNewRows, tablename);
+ while (pTable->nRows < nNewRows) {
+ if (dbAddRow(did, tablename) < 0) {
+ return -1;
+ }
+ }
+ }
+ }
+
+ return nRet;
+}
+
+/******************************************************************************/
+/*
+ * Return the number of rows in the given table
+ */
+
+int dbGetTableNrow(int did, char_t *tablename)
+{
+ int tid;
+
+ a_assert(tablename);
+ tid = dbGetTableId(did, tablename);
+
+ if ((tid >= 0) && (tid < dbMaxTables) && (dbListTables[tid] != NULL)) {
+ return (dbListTables[tid])->nRows;
+ } else {
+ return -1;
+ }
+}
+
+/******************************************************************************/
+/*
+ * Do table driven read of the database
+ */
+
+int dbReadInt(int did, char_t *table, char_t *column, int row, int *returnValue)
+{
+ int colIndex, *pRow, tid;
+ dbTable_t *pTable;
+
+ a_assert(table);
+ a_assert(column);
+ a_assert(returnValue);
+
+ tid = dbGetTableId(0, table);
+ a_assert(tid >= 0);
+
+/*
+ * Return -6 if table is not found
+ */
+ if (tid < 0) {
+ return DB_ERR_TABLE_NOT_FOUND;
+ }
+
+/*
+ * Return -7 if table id has been deleted
+ */
+ pTable = dbListTables[tid];
+ if (pTable == NULL) {
+ return DB_ERR_TABLE_DELETED;
+ }
+
+ a_assert(row >= 0);
+
+ if ((row >= 0) && (row < pTable->nRows)) {
+ colIndex = GetColumnIndex(tid, column);
+ a_assert(colIndex >= 0);
+
+ if (colIndex >= 0) {
+ pRow = pTable->rows[row];
+ if (pRow) {
+ *returnValue = pRow[colIndex];
+ return 0;
+ }
+ return DB_ERR_ROW_DELETED;
+ }
+ return DB_ERR_COL_NOT_FOUND;
+ }
+
+ return DB_ERR_ROW_NOT_FOUND;
+}
+
+/******************************************************************************/
+/*
+ * dbReadStr calls dbReadInt to do table driven read of database
+ */
+
+int dbReadStr(int did, char_t *table, char_t *column, int row,
+ char_t **returnValue)
+{
+ return dbReadInt(did, table, column, row, (int *)returnValue);
+}
+
+/******************************************************************************/
+/*
+ * The dbWriteInt function writes a value into a table at a given row and
+ * column. The existence of the row and column is verified before the
+ * write. 0 is returned on succes, -1 is returned on error.
+ */
+
+int dbWriteInt(int did, char_t *table, char_t *column, int row, int iData)
+{
+ int tid, colIndex, *pRow;
+ dbTable_t *pTable;
+
+ a_assert(table);
+ a_assert(column);
+
+/*
+ * Make sure that this table exists
+ */
+ tid = dbGetTableId(0, table);
+ a_assert(tid >= 0);
+
+ if (tid < 0) {
+ return DB_ERR_TABLE_NOT_FOUND;
+ }
+
+ pTable = dbListTables[tid];
+
+ if (pTable) {
+/*
+ * Make sure that the column exists
+ */
+ colIndex = GetColumnIndex(tid, column);
+ a_assert(colIndex >= 0);
+ if (colIndex >= 0) {
+/*
+ * Make sure that the row exists
+ */
+ a_assert((row >= 0) && (row < pTable->nRows));
+ if ((row >= 0) && (row < pTable->nRows)) {
+ pRow = pTable->rows[row];
+ if (pRow) {
+ pRow[colIndex] = iData;
+ return 0;
+ }
+ return DB_ERR_ROW_DELETED;
+ }
+ return DB_ERR_ROW_NOT_FOUND;
+ }
+ return DB_ERR_COL_NOT_FOUND;
+ }
+
+ return DB_ERR_TABLE_DELETED;
+}
+
+/******************************************************************************/
+/*
+ * The dbWriteStr function writes a string value into a table at a given row
+ * and column. The existence of the row and column is verified before the
+ * write. The column is also checked to confirm it is a string field.
+ * 0 is returned on succes, -1 is returned on error.
+ */
+
+int dbWriteStr(int did, char_t *table, char_t *column, int row, char_t *s)
+{
+ int tid, colIndex;
+ int *pRow;
+ char_t *ptr;
+ dbTable_t *pTable;
+
+ a_assert(table);
+ a_assert(column);
+
+ tid = dbGetTableId(0, table);
+ a_assert(tid >= 0);
+
+ if (tid < 0) {
+ return DB_ERR_TABLE_NOT_FOUND;
+ }
+
+/*
+ * Make sure that this table exists
+ */
+ pTable = dbListTables[tid];
+ a_assert(pTable);
+ if (!pTable) {
+ return DB_ERR_TABLE_DELETED;
+ }
+
+/*
+ * Make sure that this column exists
+ */
+ colIndex = GetColumnIndex(tid, column);
+ if (colIndex < 0) {
+ return DB_ERR_COL_NOT_FOUND;
+ }
+
+/*
+ * Make sure that this column is a string column
+ */
+ if (pTable->columnTypes[colIndex] != T_STRING) {
+ return DB_ERR_BAD_FORMAT;
+ }
+
+/*
+ * Make sure that the row exists
+ */
+ a_assert((row >= 0) && (row < pTable->nRows));
+ if ((row >= 0) && (row < pTable->nRows)) {
+ pRow = pTable->rows[row];
+ } else {
+ return DB_ERR_ROW_NOT_FOUND;
+ }
+
+ if (!pRow) {
+ return DB_ERR_ROW_DELETED;
+ }
+
+/*
+ * If the column already has a value, be sure to delete it to prevent
+ * memory leaks.
+ */
+ if (pRow[colIndex]) {
+ bfree(B_L, (char_t *) pRow[colIndex]);
+ }
+
+/*
+ * Make sure we make a copy of the string to write into the column.
+ * This allocated string will be deleted when the row is deleted.
+ */
+ ptr = bstrdup(B_L, s);
+ pRow[colIndex] = (int)ptr;
+
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Print a key-value pair to a file
+ */
+
+static int dbWriteKeyValue(int fd, char_t *key, char_t *value)
+{
+ int rc;
+ int len;
+ char_t *pLineOut;
+
+ a_assert(key && *key);
+ a_assert(value);
+
+ fmtAlloc(&pLineOut, BUF_MAX, T("%s=%s\n"), key, value);
+
+ if (pLineOut) {
+ len = gstrlen(pLineOut);
+#ifdef CE
+ rc = writeUniToAsc(fd, pLineOut, len);
+#else
+ rc = gwrite(fd, pLineOut, len);
+#endif
+ bfree(B_L, pLineOut);
+ } else {
+ rc = -1;
+ }
+
+ return rc;
+}
+
+/******************************************************************************/
+/*
+ * Persist a database to a file
+ */
+
+int dbSave(int did, char_t *filename, int flags)
+{
+ int row, column, nColumns, nRows, fd, rc;
+ int *colTypes, *pRow, nRet, tid;
+ char_t *path, *tmpFile, *tmpNum;
+ char_t **colNames;
+ dbTable_t *pTable;
+
+ trace(5, T("DB: About to save database to file\n"));
+
+ a_assert(dbMaxTables > 0);
+
+/*
+ * First write to a temporary file, then switch around later.
+ */
+ fmtAlloc(&tmpFile, FNAMESIZE, T("%s/data.tmp"), basicGetProductDir());
+ if ((fd = gopen(tmpFile,
+ O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0666)) < 0) {
+ trace(1, T("WARNING: Failed to open file %s\n"), tmpFile);
+ bfree(B_L, tmpFile);
+ return -1;
+ }
+
+ nRet = 0;
+
+ for (tid = 0; (tid < dbMaxTables) && (nRet != -1); tid++) {
+ pTable = dbListTables[tid];
+
+ if (pTable) {
+/*
+ * Print the TABLE=tableName directive to the file
+ */
+ rc = dbWriteKeyValue(fd, KEYWORD_TABLE, pTable->name);
+
+ nColumns = pTable->nColumns;
+ nRows = pTable->nRows;
+
+ for (row = 0; (row < nRows) && (nRet == 0); row++) {
+ pRow = pTable->rows[row];
+/*
+ * if row is NULL, the row has been deleted, so don't
+ * write it out.
+ */
+ if ((pRow == NULL) || (pRow[0] == '\0') ||
+ (*(char_t *)(pRow[0]) == '\0')) {
+ continue;
+ }
+/*
+ * Print the ROW=rowNumber directive to the file
+ */
+ fmtAlloc(&tmpNum, 20, T("%d"), row);
+ rc = dbWriteKeyValue(fd, KEYWORD_ROW, tmpNum);
+ bfreeSafe(B_L, tmpNum);
+
+ colNames = pTable->columnNames;
+ colTypes = pTable->columnTypes;
+/*
+ * Print the key-value pairs (COLUMN=value) for data cells
+ */
+ for (column = 0; (column < nColumns) && (rc >= 0);
+ column++, colNames++, colTypes++) {
+ if (*colTypes == T_STRING) {
+ rc = dbWriteKeyValue(fd, *colNames,
+ (char_t *)(pRow[column]));
+ } else {
+ fmtAlloc(&tmpNum, 20, T("%d"), pRow[column]);
+ rc = dbWriteKeyValue(fd, *colNames, tmpNum);
+ bfreeSafe(B_L, tmpNum);
+ }
+ }
+
+ if (rc < 0) {
+ trace(1, T("WARNING: Failed to write to file %s\n"),
+ tmpFile);
+ nRet = -1;
+ }
+ }
+ }
+ }
+
+ gclose(fd);
+
+/*
+ * Replace the existing file with the temporary file, if no errors
+ */
+ if (nRet == 0) {
+ fmtAlloc(&path, FNAMESIZE, T("%s/%s"), basicGetProductDir(), filename);
+
+ gunlink(path);
+ if (grename(tmpFile, path) != 0) {
+ trace(1, T("WARNING: Failed to rename %s to %s\n"), tmpFile, path);
+ nRet = -1;
+ }
+
+ bfree(B_L, path);
+ }
+
+ bfree(B_L, tmpFile);
+
+ return nRet;
+}
+
+/******************************************************************************/
+/*
+ * Crack a keyword=value string into keyword and value. We can change buf.
+ */
+
+static int crack(char_t *buf, char_t **key, char_t **val)
+{
+ char_t *ptr;
+
+ if ((ptr = gstrrchr(buf, '\n')) != NULL ||
+ (ptr = gstrrchr(buf, '\r')) != NULL) {
+ *ptr = '\0';
+ }
+
+/*
+ * Find the = sign. It must exist.
+ */
+ if ((ptr = gstrstr(buf, T("="))) == NULL) {
+ return -1;
+ }
+
+ *ptr++ = '\0';
+ *key = trim(buf);
+ *val = trim(ptr);
+
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Parse the file. These files consist of key-value pairs, separated by the
+ * "=" sign. Parsing of tables starts with the "TABLE=value" pair, and rows
+ * are parsed starting with the "ROW=value" pair.
+ */
+
+int dbLoad(int did, char_t *filename, int flags)
+{
+ gstat_t sbuf;
+ char_t *buf, *keyword, *value, *path, *ptr;
+ char_t *tablename;
+ int fd, tid, row;
+ dbTable_t *pTable;
+
+ a_assert(did >= 0);
+
+ fmtAlloc(&path, FNAMESIZE, T("%s/%s"), basicGetProductDir(), filename);
+ trace(4, T("DB: About to read data file <%s>\n"), path);
+
+ if (gstat(path, &sbuf) < 0) {
+ trace(3, T("DB: Failed to stat persistent data file.\n"));
+ bfree(B_L, path);
+ return -1;
+ }
+
+ fd = gopen(path, O_RDONLY | O_BINARY, 0666);
+ bfree(B_L, path);
+
+ if (fd < 0) {
+ trace(3, T("DB: No persistent data file present.\n"));
+ return -1;
+ }
+
+ if (sbuf.st_size <= 0) {
+ trace(3, T("DB: Persistent data file is empty.\n"));
+ gclose(fd);
+ return -1;
+ }
+/*
+ * Read entire file into temporary buffer
+ */
+ buf = balloc(B_L, sbuf.st_size + 1);
+#ifdef CE
+ if (readAscToUni(fd, &buf, sbuf.st_size) != (int)sbuf.st_size) {
+#else
+ if (gread(fd, buf, sbuf.st_size) != (int)sbuf.st_size) {
+#endif
+ trace(3, T("DB: Persistent data read failed.\n"));
+ bfree(B_L, buf);
+ gclose(fd);
+ return -1;
+ }
+
+ gclose(fd);
+ *(buf + sbuf.st_size) = '\0';
+
+ row = -1;
+ tid = -1;
+ pTable = NULL;
+ ptr = gstrtok(buf, T("\n"));
+ tablename = NULL;
+
+ do {
+ if (crack(ptr, &keyword, &value) < 0) {
+ trace(5, T("DB: Failed to crack line %s\n"), ptr);
+ continue;
+ }
+
+ a_assert(keyword && *keyword);
+
+ if (gstrcmp(keyword, KEYWORD_TABLE) == 0) {
+/*
+ * Table name found, check to see if it's registered
+ */
+ if (tablename) {
+ bfree(B_L, tablename);
+ }
+
+ tablename = bstrdup(B_L, value);
+ tid = dbGetTableId(did, tablename);
+
+ if (tid >= 0) {
+ pTable = dbListTables[tid];
+ } else {
+ pTable = NULL;
+ }
+
+ } else if (gstrcmp(keyword, KEYWORD_ROW) == 0) {
+/*
+ * Row/Record indicator found, add a new row to table
+ */
+ if (tid >= 0) {
+ int nRows = dbGetTableNrow(did, tablename);
+
+ if (dbSetTableNrow(did, tablename, nRows + 1) == 0) {
+ row = nRows;
+ }
+ }
+
+ } else if (row != -1) {
+/*
+ * some other data found, assume it's a COLUMN=value
+ */
+ int nColumn = GetColumnIndex(tid, keyword);
+
+ if ((nColumn >= 0) && (pTable != NULL)) {
+ int nColumnType = pTable->columnTypes[nColumn];
+ if (nColumnType == T_STRING) {
+ dbWriteStr(did, tablename, keyword, row, value);
+ } else {
+ dbWriteInt(did, tablename, keyword, row, gstrtoi(value));
+ }
+ }
+ }
+ } while ((ptr = gstrtok(NULL, T("\n"))) != NULL);
+
+ if (tablename) {
+ bfree(B_L, tablename);
+ }
+
+ bfree(B_L, buf);
+
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Return a table id given the table name
+ */
+
+int dbGetTableId(int did, char_t *tablename)
+{
+ int tid;
+ dbTable_t *pTable;
+
+ a_assert(tablename);
+
+ for (tid = 0; (tid < dbMaxTables); tid++) {
+ if ((pTable = dbListTables[tid]) != NULL) {
+ if (gstrcmp(tablename, pTable->name) == 0) {
+ return tid;
+ }
+ }
+ }
+
+ return -1;
+}
+
+/******************************************************************************/
+/*
+ * Return a pointer to the table name, given its ID
+ */
+
+char_t *dbGetTableName(int did, int tid)
+{
+ if ((tid >= 0) && (tid < dbMaxTables) && (dbListTables[tid] != NULL)) {
+ return (dbListTables[tid])->name;
+ }
+
+ return NULL;
+}
+
+/******************************************************************************/
+/*
+ * Trim leading white space.
+ */
+
+static char_t *trim(char_t *str)
+{
+ while (isspace((int)*str)) {
+ str++;
+ }
+ return str;
+}
+
+/******************************************************************************/
+/*
+ * Return a column index given the column name
+ */
+
+static int GetColumnIndex(int tid, char_t *colName)
+{
+ int column;
+ dbTable_t *pTable;
+
+ a_assert(colName);
+
+ if ((tid >= 0) && (tid < dbMaxTables) && (dbListTables[tid] != NULL)) {
+ pTable = dbListTables[tid];
+
+ for (column = 0; (column < pTable->nColumns); column++) {
+ if (gstrcmp(colName, pTable->columnNames[column]) == 0)
+ return column;
+ }
+ }
+
+ return -1;
+}
+
+/******************************************************************************/
+/*
+ * Set the prefix-directory
+ */
+
+void basicSetProductDir(char_t *proddir)
+{
+ int len;
+
+ if (basicProdDir != NULL) {
+ bfree(B_L, basicProdDir);
+ }
+
+ basicProdDir = bstrdup(B_L, proddir);
+/*
+ * Make sure that prefix-directory doesn't end with a '/'
+ */
+ len = gstrlen(basicProdDir);
+ if ((len > 0) && *(basicProdDir + len - 1) == '/') {
+ *(basicProdDir+len-1) = '\0';
+ }
+}
+
+/******************************************************************************/
+/*
+ * Return the prefix-directory
+ */
+
+char_t *basicGetProductDir()
+{
+ if (basicProdDir) {
+ return basicProdDir;
+ } else {
+ return basicDefaultDir;
+ }
+}
+
+/******************************************************************************/
diff --git a/cpukit/httpd/emfdb.h b/cpukit/httpd/emfdb.h
new file mode 100644
index 0000000000..882c1c80d2
--- /dev/null
+++ b/cpukit/httpd/emfdb.h
@@ -0,0 +1,101 @@
+/*
+ * emfdb.h -- EMF database compatability functions for GoAhead WebServer.
+ *
+ * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for usage and redistribution license requirements
+ *
+ * $Id$
+ */
+
+/******************************** Description *********************************/
+/*
+ * Emf-like textfile database support for WebServer 2.1.
+ */
+
+/********************************* Includes ***********************************/
+
+#ifndef _h_EMFDB
+#define _h_EMFDB 1
+
+#ifndef UEMF
+ #include "basic/basic.h"
+ #include "emf/emf.h"
+#else
+ #include "uemf.h"
+#endif
+
+
+/********************************* Defines ************************************/
+
+#define T_INT 0
+#define T_STRING 1
+
+#define DB_OK 0
+#define DB_ERR_GENERAL -1
+#define DB_ERR_COL_NOT_FOUND -2
+#define DB_ERR_COL_DELETED -3
+#define DB_ERR_ROW_NOT_FOUND -4
+#define DB_ERR_ROW_DELETED -5
+#define DB_ERR_TABLE_NOT_FOUND -6
+#define DB_ERR_TABLE_DELETED -7
+#define DB_ERR_BAD_FORMAT -8
+
+typedef struct dbTable_s {
+ char_t *name;
+ int nColumns;
+ char_t **columnNames;
+ int *columnTypes;
+ int nRows;
+ int **rows;
+} dbTable_t;
+
+/********************************** Prototypes ********************************/
+
+/*
+ * Add a schema to the module-internal schema database
+ */
+extern int dbRegisterDBSchema(dbTable_t *sTable);
+
+extern int dbOpen(char_t *databasename, char_t *filename,
+ int (*gettime)(int did), int flags);
+extern void dbClose(int did);
+extern int dbGetTableId(int did, char_t *tname);
+extern char_t *dbGetTableName(int did, int tid);
+extern int dbReadInt(int did, char_t *table, char_t *column, int row,
+ int *returnValue);
+extern int dbReadStr(int did, char_t *table, char_t *column, int row,
+ char_t **returnValue);
+extern int dbWriteInt(int did, char_t *table, char_t *column, int row,
+ int idata);
+extern int dbWriteStr(int did, char_t *table, char_t *column, int row,
+ char_t *s);
+extern int dbAddRow(int did, char_t *table);
+extern int dbDeleteRow(int did, char_t *table, int rid);
+extern int dbSetTableNrow(int did, char_t *table, int nNewRows);
+extern int dbGetTableNrow(int did, char_t *table);
+
+/*
+ * Dump the contents of a database to file
+ */
+extern int dbSave(int did, char_t *filename, int flags);
+
+/*
+ * Load the contents of a database to file
+ */
+extern int dbLoad(int did, char_t *filename, int flags);
+
+/*
+ * Search for a data in a given column
+ */
+extern int dbSearchStr(int did, char_t *table, char_t *column,
+ char_t *value, int flags);
+
+extern void dbZero(int did);
+
+extern char_t *basicGetProductDir();
+extern void basicSetProductDir(char_t *proddir);
+
+#endif /* _h_EMFDB */
+
+/******************************************************************************/
diff --git a/cpukit/httpd/form.c b/cpukit/httpd/form.c
new file mode 100644
index 0000000000..501cea72e2
--- /dev/null
+++ b/cpukit/httpd/form.c
@@ -0,0 +1,168 @@
+/*
+ * form.c -- Form processing (in-memory CGI) for the GoAhead Web server
+ *
+ * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for usage and redistribution license requirements
+ *
+ * $Id$
+ */
+
+/********************************** Description *******************************/
+
+/*
+ * This module implements the /goform handler. It emulates CGI processing
+ * but performs this in-process and not as an external process. This enables
+ * a very high performance implementation with easy parsing and decoding
+ * of query strings and posted data.
+ */
+
+/*********************************** Includes *********************************/
+
+#include "wsIntrn.h"
+
+/************************************ Locals **********************************/
+
+static sym_fd_t formSymtab = -1; /* Symbol table for form handlers */
+
+/************************************* Code ***********************************/
+/*
+ * Process a form request. Returns 1 always to indicate it handled the URL
+ */
+
+int websFormHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
+ char_t *url, char_t *path, char_t *query)
+{
+ sym_t *sp;
+ char_t formBuf[FNAMESIZE];
+ char_t *cp, *formName;
+ int (*fn)(void *sock, char_t *path, char_t *args);
+
+ a_assert(websValid(wp));
+ a_assert(url && *url);
+ a_assert(path && *path == '/');
+
+ websStats.formHits++;
+
+/*
+ * Extract the form name
+ */
+ gstrncpy(formBuf, path, TSZ(formBuf));
+ if ((formName = gstrchr(&formBuf[1], '/')) == NULL) {
+ websError(wp, 200, T("Missing form name"));
+ return 1;
+ }
+ formName++;
+ if ((cp = gstrchr(formName, '/')) != NULL) {
+ *cp = '\0';
+ }
+
+/*
+ * Lookup the C form function first and then try tcl (no javascript support
+ * yet).
+ */
+ sp = symLookup(formSymtab, formName);
+ if (sp == NULL) {
+ websError(wp, 200, T("Form %s is not defined"), formName);
+ } else {
+ fn = (int (*)(void *, char_t *, char_t *)) sp->content.value.integer;
+ a_assert(fn);
+ if (fn) {
+/*
+ * For good practice, forms must call websDone()
+ */
+ (*fn)((void*) wp, formName, query);
+
+/*
+ * Remove the test to force websDone, since this prevents
+ * the server "push" from a form>
+ */
+#if 0 /* push */
+ if (websValid(wp)) {
+ websError(wp, 200, T("Form didn't call websDone"));
+ }
+#endif /* push */
+ }
+ }
+ return 1;
+}
+
+/******************************************************************************/
+/*
+ * Define a form function in the "form" map space.
+ */
+
+int websFormDefine(char_t *name, void (*fn)(webs_t wp, char_t *path,
+ char_t *query))
+{
+ a_assert(name && *name);
+ a_assert(fn);
+
+ if (fn == NULL) {
+ return -1;
+ }
+
+ symEnter(formSymtab, name, valueInteger((int) fn), (int) NULL);
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Open the symbol table for forms.
+ */
+
+void websFormOpen()
+{
+ formSymtab = symOpen(WEBS_SYM_INIT);
+}
+
+/******************************************************************************/
+/*
+ * Close the symbol table for forms.
+ */
+
+void websFormClose()
+{
+ if (formSymtab != -1) {
+ symClose(formSymtab);
+ formSymtab = -1;
+ }
+}
+
+/******************************************************************************/
+/*
+ * Write a webs header. This is a convenience routine to write a common
+ * header for a form back to the browser.
+ */
+
+void websHeader(webs_t wp)
+{
+ a_assert(websValid(wp));
+
+ websWrite(wp, T("HTTP/1.0 200 OK\n"));
+
+/*
+ * By license terms the following line of code must not be modified
+ */
+ websWrite(wp, T("Server: %s\r\n"), WEBS_NAME);
+
+ websWrite(wp, T("Pragma: no-cache\n"));
+ websWrite(wp, T("Cache-control: no-cache\n"));
+ websWrite(wp, T("Content-Type: text/html\n"));
+ websWrite(wp, T("\n"));
+ websWrite(wp, T("<html>\n"));
+}
+
+/******************************************************************************/
+/*
+ * Write a webs footer
+ */
+
+void websFooter(webs_t wp)
+{
+ a_assert(websValid(wp));
+
+ websWrite(wp, T("</html>\n"));
+}
+
+/******************************************************************************/
diff --git a/cpukit/httpd/h.c b/cpukit/httpd/h.c
new file mode 100644
index 0000000000..35b0bbbae6
--- /dev/null
+++ b/cpukit/httpd/h.c
@@ -0,0 +1,194 @@
+/*
+ * h.c -- Handle allocation module
+ *
+ * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
+ * See the file "license.txt" for usage and redistribution license requirements
+ *
+ * $Id$
+ */
+
+/******************************** Description *********************************/
+
+/*
+ * This module provides a simple API to allocate and free handles
+ * It maintains a dynamic array of pointers. These usually point to
+ * per-handle structures.
+ */
+
+/********************************* Includes ***********************************/
+
+#ifdef UEMF
+ #include "uemf.h"
+#else
+ #include "basic/basicInternal.h"
+#endif
+
+/********************************** Defines ***********************************/
+/*
+ * The handle list stores the length of the list and the number of used
+ * handles in the first two words. These are hidden from the caller by
+ * returning a pointer to the third word to the caller
+ */
+
+#define H_LEN 0 /* First entry holds length of list */
+#define H_USED 1 /* Second entry holds number of used */
+#define H_OFFSET 2 /* Offset to real start of list */
+
+#define H_INCR 16 /* Grow handle list in chunks this size */
+
+/*********************************** Code *************************************/
+/*
+ * Allocate a new file handle. On the first call, the caller must set the
+ * handle map to be a pointer to a null pointer. *map points to the second
+ * element in the handle array.
+ */
+
+#ifdef B_STATS
+int HALLOC(B_ARGS_DEC, void ***map)
+#else
+int hAlloc(void ***map)
+#endif
+{
+ int *mp;
+ int handle, len, memsize, incr;
+
+ a_assert(map);
+
+ if (*map == NULL) {
+ incr = H_INCR;
+ memsize = (incr + H_OFFSET) * sizeof(void**);
+#ifdef B_STATS
+ if ((mp = (int*) balloc(B_ARGS, memsize)) == NULL) {
+#else
+ if ((mp = (int*) balloc(B_L, memsize)) == NULL) {
+#endif
+ return -1;
+ }
+ memset(mp, 0, memsize);
+ mp[H_LEN] = incr;
+ mp[H_USED] = 0;
+ *map = (void**) &mp[H_OFFSET];
+ } else {
+ mp = &((*(int**)map)[-H_OFFSET]);
+ }
+
+ len = mp[H_LEN];
+
+/*
+ * Find the first null handle
+ */
+ if (mp[H_USED] < mp[H_LEN]) {
+ for (handle = 0; handle < len; handle++) {
+ if (mp[handle+H_OFFSET] == 0) {
+ mp[H_USED]++;
+ return handle;
+ }
+ }
+ } else {
+ handle = len;
+ }
+
+/*
+ * No free handle so grow the handle list. Grow list in chunks of H_INCR.
+ */
+ len += H_INCR;
+ memsize = (len + H_OFFSET) * sizeof(void**);
+ if ((mp = (int*) brealloc(B_L, (void*) mp, memsize)) == NULL) {
+ return -1;
+ }
+ *map = (void**) &mp[H_OFFSET];
+ mp[H_LEN] = len;
+ memset(&mp[H_OFFSET + len - H_INCR], 0, sizeof(int*) * H_INCR);
+ mp[H_USED]++;
+ return handle;
+}
+
+/******************************************************************************/
+/*
+ * Free a handle. This function returns the value of the largest
+ * handle in use plus 1, to be saved as a max value.
+ */
+
+int hFree(void ***map, int handle)
+{
+ int *mp;
+ int len;
+
+ a_assert(map);
+ mp = &((*(int**)map)[-H_OFFSET]);
+ a_assert(mp[H_LEN] >= H_INCR);
+
+ a_assert(mp[handle + H_OFFSET]);
+ a_assert(mp[H_USED]);
+ mp[handle + H_OFFSET] = 0;
+ if (--(mp[H_USED]) == 0) {
+ bfree(B_L, (void*) mp);
+ *map = NULL;
+ }
+
+/*
+ * Find the greatest handle number in use.
+ */
+ if (*map == NULL) {
+ handle = -1;
+ } else {
+ len = mp[H_LEN];
+ if (mp[H_USED] < mp[H_LEN]) {
+ for (handle = len - 1; handle >= 0; handle--) {
+ if (mp[handle + H_OFFSET])
+ break;
+ }
+ } else {
+ handle = len;
+ }
+ }
+ return handle + 1;
+}
+
+/******************************************************************************/
+/*
+ * Allocate an entry in the halloc array.
+ */
+
+#ifdef B_STATS
+int HALLOCENTRY(B_ARGS_DEC, void ***list, int *max, int size)
+#else
+int hAllocEntry(void ***list, int *max, int size)
+#endif
+{
+ char_t *cp;
+ int id;
+
+ a_assert(list);
+ a_assert(max);
+
+#ifdef B_STATS
+ if ((id = HALLOC(B_ARGS, (void***) list)) < 0) {
+#else
+ if ((id = hAlloc((void***) list)) < 0) {
+#endif
+ return -1;
+ }
+
+ if (size > 0) {
+#ifdef B_STATS
+ if ((cp = balloc(B_ARGS, size)) == NULL) {
+#else
+ if ((cp = balloc(B_L, size)) == NULL) {
+#endif
+ hFree(list, id);
+ return -1;
+ }
+ a_assert(cp);
+ memset(cp, 0, size);
+
+ (*list)[id] = (void*) cp;
+ }
+
+ if (id >= *max) {
+ *max = id + 1;
+ }
+ return id;
+}
+
+/******************************************************************************/
diff --git a/cpukit/httpd/handler.c b/cpukit/httpd/handler.c
new file mode 100644
index 0000000000..dbbe4148d5
--- /dev/null
+++ b/cpukit/httpd/handler.c
@@ -0,0 +1,411 @@
+/*
+ * handler.c -- URL handler support
+ *
+ * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for usage and redistribution license requirements
+ *
+ * $Id$
+ */
+
+/******************************** Description *********************************/
+
+/*
+ * This module implements a URL handler interface and API to permit
+ * the addition of user definable URL processors.
+ */
+
+/********************************* Includes ***********************************/
+
+#include "wsIntrn.h"
+
+/*********************************** Locals ***********************************/
+
+static websUrlHandlerType *websUrlHandler; /* URL handler list */
+static int websUrlHandlerMax; /* Number of entries */
+static int urlHandlerOpenCount = 0; /* count of apps */
+
+/**************************** Forward Declarations ****************************/
+
+static int websUrlHandlerSort(const void *p1, const void *p2);
+static int websPublishHandler(webs_t wp, char_t *urlPrefix, char_t *webDir,
+ int sid, char_t *url, char_t *path, char_t *query);
+static char_t *websCondenseMultipleChars(char_t *strToCondense, char_t cCondense);
+
+/*********************************** Code *************************************/
+/*
+ * Initialize the URL handler module
+ */
+
+int websUrlHandlerOpen()
+{
+ if (++urlHandlerOpenCount == 1) {
+ websAspOpen();
+ websUrlHandler = NULL;
+ websUrlHandlerMax = 0;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Close the URL handler module
+ */
+
+void websUrlHandlerClose()
+{
+ websUrlHandlerType *sp;
+
+ if (--urlHandlerOpenCount <= 0) {
+ websAspClose();
+ for (sp = websUrlHandler; sp < &websUrlHandler[websUrlHandlerMax];
+ sp++) {
+ bfree(B_L, sp->urlPrefix);
+ if (sp->webDir) {
+ bfree(B_L, sp->webDir);
+ }
+ }
+ bfree(B_L, websUrlHandler);
+ websUrlHandlerMax = 0;
+ }
+}
+
+/******************************************************************************/
+/*
+ * Define a new URL handler. urlPrefix is the URL prefix to match. webDir is
+ * an optional root directory path for a web directory. arg is an optional
+ * arg to pass to the URL handler. flags defines the matching order. Valid
+ * flags include WEBS_HANDLER_LAST, WEBS_HANDLER_FIRST. If multiple users
+ * specify last or first, their order is defined alphabetically by the
+ * urlPrefix.
+ */
+
+int websUrlHandlerDefine(char_t *urlPrefix, char_t *webDir, int arg,
+ int (*handler)(webs_t wp, char_t *urlPrefix, char_t *webdir, int arg,
+ char_t *url, char_t *path, char_t *query), int flags)
+{
+ websUrlHandlerType *sp;
+ int len;
+
+ a_assert(urlPrefix);
+ a_assert(handler);
+
+/*
+ * Grow the URL handler array to create a new slot
+ */
+ len = (websUrlHandlerMax + 1) * sizeof(websUrlHandlerType);
+ if ((websUrlHandler = brealloc(B_L, websUrlHandler, len)) == NULL) {
+ return -1;
+ }
+ sp = &websUrlHandler[websUrlHandlerMax++];
+ memset(sp, 0, sizeof(websUrlHandlerType));
+
+ sp->urlPrefix = bstrdup(B_L, urlPrefix);
+ sp->len = gstrlen(sp->urlPrefix);
+ if (webDir) {
+ sp->webDir = bstrdup(B_L, webDir);
+ } else {
+ sp->webDir = bstrdup(B_L, T(""));
+ }
+ sp->handler = handler;
+ sp->arg = arg;
+ sp->flags = flags;
+
+/*
+ * Sort in decreasing URL length order observing the flags for first and last
+ */
+ qsort(websUrlHandler, websUrlHandlerMax, sizeof(websUrlHandlerType),
+ websUrlHandlerSort);
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Delete an existing URL handler. We don't reclaim the space of the old
+ * handler, just NULL the entry. Return -1 if handler is not found.
+ */
+
+int websUrlHandlerDelete(int (*handler)(webs_t wp, char_t *urlPrefix,
+ char_t *webDir, int arg, char_t *url, char_t *path, char_t *query))
+{
+ websUrlHandlerType *sp;
+ int i;
+
+ for (i = 0; i < websUrlHandlerMax; i++) {
+ sp = &websUrlHandler[i];
+ if (sp->handler == handler) {
+ sp->handler = NULL;
+ return 0;
+ }
+ }
+ return -1;
+}
+
+/******************************************************************************/
+/*
+ * Sort in decreasing URL length order observing the flags for first and last
+ */
+
+static int websUrlHandlerSort(const void *p1, const void *p2)
+{
+ websUrlHandlerType *s1, *s2;
+ int rc;
+
+ a_assert(p1);
+ a_assert(p2);
+
+ s1 = (websUrlHandlerType*) p1;
+ s2 = (websUrlHandlerType*) p2;
+
+ if ((s1->flags & WEBS_HANDLER_FIRST) || (s2->flags & WEBS_HANDLER_LAST)) {
+ return -1;
+ }
+
+ if ((s2->flags & WEBS_HANDLER_FIRST) || (s1->flags & WEBS_HANDLER_LAST)) {
+ return 1;
+ }
+
+ if ((rc = gstrcmp(s1->urlPrefix, s2->urlPrefix)) == 0) {
+ if (s1->len < s2->len) {
+ return 1;
+ } else if (s1->len > s2->len) {
+ return -1;
+ }
+ }
+ return -rc;
+}
+
+/******************************************************************************/
+/*
+ * Publish a new web directory (Use the default URL handler)
+ */
+
+int websPublish(char_t *urlPrefix, char_t *path)
+{
+ return websUrlHandlerDefine(urlPrefix, path, 0, websPublishHandler, 0);
+}
+
+/******************************************************************************/
+/*
+ * Return the directory for a given prefix. Ignore empty prefixes
+ */
+
+char_t *websGetPublishDir(char_t *path, char_t **urlPrefix)
+{
+ websUrlHandlerType *sp;
+ int i;
+
+ for (i = 0; i < websUrlHandlerMax; i++) {
+ sp = &websUrlHandler[i];
+ if (sp->urlPrefix[0] == '\0') {
+ continue;
+ }
+ if (sp->handler && gstrncmp(sp->urlPrefix, path, sp->len) == 0) {
+ if (urlPrefix) {
+ *urlPrefix = sp->urlPrefix;
+ }
+ return sp->webDir;
+ }
+ }
+ return NULL;
+}
+
+/******************************************************************************/
+/*
+ * Publish URL handler. We just patch the web page Directory and let the
+ * default handler do the rest.
+ */
+
+static int websPublishHandler(webs_t wp, char_t *urlPrefix, char_t *webDir,
+ int sid, char_t *url, char_t *path, char_t *query)
+{
+ int len;
+
+ a_assert(websValid(wp));
+ a_assert(path);
+
+/*
+ * Trim the urlPrefix off the path and set the webdirectory. Add one to step
+ * over the trailing '/'
+ */
+ len = gstrlen(urlPrefix) + 1;
+ websSetRequestPath(wp, webDir, &path[len]);
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * See if any valid handlers are defined for this request. If so, call them
+ * and continue calling valid handlers until one accepts the request.
+ * Return true if a handler was invoked, else return FALSE.
+ */
+
+int websUrlHandlerRequest(webs_t wp)
+{
+ websUrlHandlerType *sp;
+ int i, first;
+
+ a_assert(websValid(wp));
+
+/*
+ * Delete the socket handler as we don't want to start reading any
+ * data on the connection as it may be for the next pipelined HTTP/1.1
+ * request if using Keep Alive
+ */
+ socketDeleteHandler(wp->sid);
+ wp->state = WEBS_PROCESSING;
+ websStats.handlerHits++;
+
+ websSetRequestPath(wp, websGetDefaultDir(), NULL);
+
+/*
+ * Eliminate security hole
+ */
+ websCondenseMultipleChars(wp->path, '/');
+ websCondenseMultipleChars(wp->url, '/');
+
+/*
+ * We loop over each handler in order till one accepts the request.
+ * The security handler will handle the request if access is NOT allowed.
+ */
+ first = 1;
+ for (i = 0; i < websUrlHandlerMax; i++) {
+ sp = &websUrlHandler[i];
+ if (sp->handler && gstrncmp(sp->urlPrefix, wp->path, sp->len) == 0) {
+ if (first) {
+ websSetEnv(wp);
+ first = 0;
+ }
+ if ((*sp->handler)(wp, sp->urlPrefix, sp->webDir, sp->arg,
+ wp->url, wp->path, wp->query)) {
+ return 1;
+ }
+ if (!websValid(wp)) {
+ trace(0,
+ T("webs: handler %s called websDone, but didn't return 1\n"),
+ sp->urlPrefix);
+ return 1;
+ }
+ }
+ }
+/*
+ * If no handler processed the request, then return an error. Note: It is
+ * the handlers responsibility to call websDone
+ */
+ if (i >= websUrlHandlerMax) {
+ websError(wp, 200, T("No handler for this URL %s"), wp->url);
+ }
+ return 0;
+}
+
+#ifdef OBSOLETE_CODE
+
+/******************************************************************************/
+/*
+ * Tidy up the URL path. Return -1 if the URL is bad.
+ * Used to eliminate repeated directory delimiters ('/').
+ */
+
+static int websTidyUrl(webs_t wp)
+{
+ char_t *parts[64]; /* Array of ptr's to URL parts */
+ char_t *token, *url, *tidyurl;
+ int i, len, npart;
+
+ a_assert(websValid(wp));
+
+/*
+ * Copy the string so we don't destroy the original (yet)
+ */
+ url = bstrdup(B_L, wp->url);
+ websDecodeUrl(url, url, gstrlen(url));
+
+ len = npart = 0;
+ parts[0] = NULL;
+ token = gstrtok(url, T("/"));
+
+/*
+ * Look at each directory segment and process "." and ".." segments
+ * Don't allow the browser to pop outside the root web.
+ */
+ while (token != NULL) {
+ if (gstrcmp(token, T("..")) == 0) {
+ if (npart > 0) {
+ npart--;
+ }
+
+ } else if (gstrcmp(token, T(".")) != 0) {
+ parts[npart] = token;
+ len += gstrlen(token) + 1;
+ npart++;
+ }
+ token = gstrtok(NULL, T("/"));
+ }
+
+/*
+ * Re-construct URL. Need extra space all "/" and null.
+ */
+ if (npart || (gstrcmp(url, T("/")) == 0) || (url[0] == '\0')) {
+ tidyurl = balloc(B_L, (len + 2) * sizeof(char_t));
+ *tidyurl = '\0';
+
+ for (i = 0; i < npart; i++) {
+ gstrcat(tidyurl, T("/"));
+ gstrcat(tidyurl, parts[i]);
+ }
+
+ bfree(B_L, url);
+
+ bfree(B_L, wp->url);
+ wp->url = tidyurl;
+ return 0;
+ } else {
+ bfree(B_L, url);
+ return -1;
+ }
+}
+
+#endif
+
+/******************************************************************************/
+/*
+ * Convert multiple adjacent occurrences of a given character to a single
+ * instance.
+ */
+
+static char_t *websCondenseMultipleChars(char_t *strToCondense, char_t cCondense)
+{
+ if (strToCondense != NULL) {
+ char_t *pStr, *pScan;
+
+ pStr = pScan = strToCondense;
+
+ while (*pScan && *pStr) {
+/*
+ * Advance scan pointer over multiple occurences of condense character
+ */
+ while ((*pScan == cCondense) && (*(pScan + 1) == cCondense)) {
+ pScan++;
+ }
+/*
+ * Copy character if an advance of the scan pointer has occurred
+ */
+ if (pStr != pScan) {
+ *pStr = *pScan;
+ }
+
+ pScan++;
+ pStr++;
+ }
+/*
+ * Zero terminate string if multiple adjacent characters were found and condensed
+ */
+ if (pStr != pScan) {
+ *pStr = 0;
+ }
+ }
+
+ return strToCondense;
+}
+
+/******************************************************************************/
diff --git a/cpukit/httpd/license.txt b/cpukit/httpd/license.txt
new file mode 100644
index 0000000000..1fa9e67e79
--- /dev/null
+++ b/cpukit/httpd/license.txt
@@ -0,0 +1,282 @@
+License Agreement
+
+THIS LICENSE ALLOWS ONLY THE LIMITED USE OF GO AHEAD SOFTWARE,
+INC. PROPRIETARY CODE. PLEASE CAREFULLY READ THIS AGREEMENT AS IT
+PERTAINS TO THIS LICENSE, YOU CERTIFY THAT YOU WILL USE THE SOFTWARE
+ONLY IN THE MANNER PERMITTED HEREIN.
+
+1. Definitions.
+
+1.1 "Documentation" means any documentation GoAhead includes with the
+Original Code.
+
+1.2 "GoAhead" means Go Ahead Software, Inc.
+
+1.3 "Intellectual Property Rights" means all rights, whether now existing
+or hereinafter acquired, in and to trade secrets, patents, copyrights,
+trademarks, know-how, as well as moral rights and similar rights of any
+type under the laws of any governmental authority, domestic or foreign,
+including rights in and to all applications and registrations relating
+to any of the foregoing.
+
+1.4 "License" or "Agreement" means this document.
+
+1.5 "Modifications" means any addition to or deletion from the substance
+or structure of either the Original Code or any previous Modifications.
+
+1.6 "Original Code" means the Source Code to GoAhead’s proprietary
+computer software entitled GoAhead WebServer.
+
+1.7 "Response Header" means the first portion of the response message
+output by the GoAhead WebServer, containing but not limited to, header
+fields for date, content-type, server identification and cache control.
+
+1.8 "Server Identification Field" means the field in the Response Header
+which contains the text "Server: GoAhead-Webs".
+
+1.9 "You" means an individual or a legal entity exercising rights under,
+and complying with all of the terms of, this license or a future version
+of this license. For legal entities, "You" includes any entity which
+controls, is controlled by, or is under common control with You. For
+purposes of this definition, "control" means (a) the power, direct or
+indirect, to cause the direction or management of such entity, whether
+by contract or otherwise, or (b) ownership of fifty percent (50%) or
+more of the outstanding shares or beneficial ownership of such entity.
+
+2. Source Code License.
+
+2.1 Limited Source Code Grant.
+
+GoAhead hereby grants You a world-wide, royalty-free, non-exclusive
+license, subject to third party intellectual property claims, to use,
+reproduce, modify, copy and distribute the Original Code.
+
+2.2 Binary Code.
+
+GoAhead hereby grants You a world-wide, royalty-free, non-exclusive
+license to copy and distribute the binary code versions of the Original
+Code together with Your Modifications.
+
+2.3 License Back to GoAhead.
+
+You hereby grant in both source code and binary code to GoAhead a
+world-wide, royalty-free, non-exclusive license to copy, modify, display,
+use and sublicense any Modifications You make that are distributed or
+planned for distribution. Within 30 days of either such event, You
+agree to ship to GoAhead a file containing the Modifications (in a media
+to be determined by the parties), including any programmers’ notes and
+other programmers’ materials. Additionally, You will provide to GoAhead
+a complete description of the product, the product code or model number,
+the date on which the product is initially shipped, and a contact name,
+phone number and e-mail address for future correspondence. GoAhead will
+keep confidential all data specifically marked as such.
+
+2.4 Restrictions on Use.
+
+You may sublicense Modifications to third parties such as subcontractors
+or OEM's provided that You enter into license agreements with such third
+parties that bind such third parties to all the obligations under this
+Agreement applicable to you and that are otherwise substantially similar
+in scope and application to this Agreement.
+
+3. Term.
+
+This Agreement and license are effective from the time You accept the
+terms of this Agreement until this Agreement is terminated. You may
+terminate this Agreement at any time by uninstalling or destroying
+all copies of the Original Code including any and all binary versions
+and removing any Modifications to the Original Code existing in any
+products. This Agreement will terminate immediately and without further
+notice if You fail to comply with any provision of this Agreement. All
+restrictions on use, and all other provisions that may reasonably
+be interpreted to survive termination of this Agreement, will survive
+termination of this Agreement for any reason. Upon termination, You agree
+to uninstall or destroy all copies of the Original Code, Modifications,
+and Documentation.
+
+4. Trademarks and Brand.
+
+4.1 License and Use.
+
+GoAhead hereby grants to You a limited world-wide, royalty-free,
+non-exclusive license to use the GoAhead trade names, trademarks, logos,
+service marks and product designations posted in Exhibit A (collectively,
+the "GoAhead Marks") in connection with the activities by You under this
+Agreement. Additionally, GoAhead grants You a license under the terms
+above to such GoAhead trademarks as shall be identified at a URL (the
+"URL") provided by GoAhead. The use by You of GoAhead Marks shall be in
+accordance with GoAhead’s trademark policies regarding trademark usage
+as established at the web site designated by the URL, or as otherwise
+communicated to You by GoAhead at its sole discretion. You understand and
+agree that any use of GoAhead Marks in connection with this Agreement
+shall not create any right, title or interest in or to such GoAhead
+Marks and that all such use and goodwill associated with GoAhead Marks
+will inure to the benefit of GoAhead.
+
+4.2 Promotion by You of GoAhead WebServer Mark.
+
+In consideration for the licenses granted by GoAhead to You herein, You
+agree to notify GoAhead when You incorporate the GoAhead WebServer in
+Your product and to inform GoAhead when such product begins to ship. You
+agree to promote the Original Code by prominently and visibly displaying
+a graphic of the GoAhead WebServer mark on the initial web page of Your
+product that is displayed each time a user connects to it. You also agree
+that GoAhead may identify your company as a user of the GoAhead WebServer
+in conjunction with its own marketing efforts. You may further promote
+the Original Code by displaying the GoAhead WebServer mark in marketing
+and promotional materials such as the home page of your web site or web
+pages promoting the product.
+
+4.3 Placement of Copyright Notice by You.
+
+You agree to include copies of the following notice (the "Notice")
+regarding proprietary rights in all copies of the products that You
+distribute, as follows: (i) embedded in the object code; and (ii) on
+the title pages of all documentation. Furthermore, You agree to use
+commercially reasonable efforts to cause any licensees of your products
+to embed the Notice in object code and on the title pages or relevant
+documentation. The Notice is as follows: Copyright (c) 20xx GoAhead
+Software, Inc. All Rights Reserved. Unless GoAhead otherwise instructs,
+the year 20xx is to be replaced with the year during which the release of
+the Original Code containing the notice is issued by GoAhead. If this year
+is not supplied with Documentation, GoAhead will supply it upon request.
+
+4.4 No Modifications to Server Identification Field.
+
+You agree not to remove or modify the Server identification Field
+contained in the Response Header as defined in Section 1.6 and 1.7.
+
+5. Warranty Disclaimers.
+
+THE ORIGINAL CODE, THE DOCUMENTATION AND THE MEDIA UPON WHICH THE ORIGINAL
+CODE IS RECORDED (IF ANY) ARE PROVIDED "AS IS" AND WITHOUT WARRANTIES OF
+ANY KIND, EXPRESS, STATUTORY OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.
+
+The entire risk as to the quality and performance of the Original Code
+(including any Modifications You make) and the Documentation is with
+You. Should the Original Code or the Documentation prove defective,
+You (and not GoAhead or its distributors, licensors or dealers) assume
+the entire cost of all necessary servicing or repair. GoAhead does not
+warrant that the functions contained in the Original Code will meet your
+requirements or operate in the combination that You may select for use,
+that the operation of the Original Code will be uninterrupted or error
+free, or that defects in the Original Code will be corrected. No oral
+or written statement by GoAhead or by a representative of GoAhead shall
+create a warranty or increase the scope of this warranty.
+
+GOAHEAD DOES NOT WARRANT THE ORIGINAL CODE AGAINST INFRINGEMENT OR THE
+LIKE WITH RESPECT TO ANY COPYRIGHT, PATENT, TRADE SECRET, TRADEMARK
+OR OTHER PROPRIETARY RIGHT OF ANY THIRD PARTY AND DOES NOT WARRANT
+THAT THE ORIGINAL CODE DOES NOT INCLUDE ANY VIRUS, SOFTWARE ROUTINE
+OR OTHER SOFTWARE DESIGNED TO PERMIT UNAUTHORIZED ACCESS, TO DISABLE,
+ERASE OR OTHERWISE HARM SOFTWARE, HARDWARE OR DATA, OR TO PERFORM ANY
+OTHER SUCH ACTIONS.
+
+Any warranties that by law survive the foregoing disclaimers shall
+terminate ninety (90) days from the date You received the Original Code.
+
+6. Limitation of Liability.
+
+YOUR SOLE REMEDIES AND GOAHEAD'S ENTIRE LIABILITY ARE SET FORTH ABOVE. IN
+NO EVENT WILL GOAHEAD OR ITS DISTRIBUTORS OR DEALERS BE LIABLE FOR
+DIRECT, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES RESULTING FROM
+THE USE OF THE ORIGINAL CODE, THE INABILITY TO USE THE ORIGINAL CODE,
+OR ANY DEFECT IN THE ORIGINAL CODE, INCLUDING ANY LOST PROFITS, EVEN IF
+THEY HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+You agree that GoAhead and its distributors and dealers will not be
+LIABLE for defense or indemnity with respect to any claim against You
+by any third party arising from your possession or use of the Original
+Code or the Documentation.
+
+In no event will GoAhead’s total liability to You for all damages, losses,
+and causes of action (whether in contract, tort, including negligence,
+or otherwise) exceed the amount You paid for this product.
+
+SOME STATES DO NOT ALLOW LIMITATIONS ON HOW LONG AN IMPLIED WARRANTY
+LASTS, AND SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION
+OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THE ABOVE LIMITATIONS OR
+EXCLUSIONS MAY NOT APPLY TO YOU. THIS WARRANTY GIVES YOU SPECIFIC LEGAL
+RIGHTS AND YOU MAY ALSO HAVE OTHER RIGHTS WHICH VARY FROM STATE TO STATE.
+
+7. Indemnification by You.
+
+You agree to indemnify and hold GoAhead harmless against any and all
+claims, losses, damages and costs (including legal expenses and reasonable
+counsel fees) arising out of any claim of a third party with respect to
+the contents of the Your products, and any intellectual property rights
+or other rights or interests related thereto.
+
+8. High Risk Activities.
+
+The Original Code is not fault-tolerant and is not designed , manufactured
+or intended for use or resale as online control equipment in hazardous
+environments requiring fail-safe performance, such as in the operation
+of nuclear facilities, aircraft navigation or communication systems,
+air traffic control, direct life support machines or weapons systems,
+in which the failure of the Original Code could lead directly to death,
+personal injury, or severe physical or environmental damage. GoAhead and
+its suppliers specifically disclaim any express or implied warranty of
+fitness for any high risk uses listed above.
+
+9. Government Restricted Rights.
+
+For units of the Department of Defense, use, duplication, or disclosure
+by the Government is subject to restrictions as set forth in subparagraph
+(c)(1)(ii) of the Rights in Technical Data and Computer Software clause
+at DFARS 252.227-7013. Contractor/manufacturer is GoAhead Software,
+Inc., 10900 N.E. 8th Street, Suite 750, Bellevue, Washington 98004.
+
+If the Commercial Computer Software Restricted rights clause at FAR
+52.227-19 or its successors apply, the Software and Documentation
+constitute restricted computer software as defined in that clause and
+the Government shall not have the license for published software set
+forth in subparagraph (c)(3) of that clause.
+
+The Original Code (i) was developed at private expense, and no part of it
+was developed with governmental funds; (ii) is a trade secret of GoAhead
+(or its licensor(s)) for all purposes of the Freedom of Information Act;
+(iii) is "restricted computer software" subject to limited utilization as
+provided in the contract between the vendor and the governmental entity;
+and (iv) in all respects is proprietary data belonging solely to GoAhead
+(or its licensor(s)).
+
+10. Governing Law and Interpretation.
+
+This Agreement shall be interpreted under and governed by the laws of the
+State of Washington, without regard to its rules governing the conflict of
+laws. If any provision of this Agreement is held illegal or unenforceable
+by a court or tribunal of competent jurisdiction, the remaining provisions
+of this Agreement shall remain in effect and the invalid provision deemed
+modified to the least degree necessary to remedy such invalidity.
+
+11. Entire Agreement.
+
+This Agreement is the complete agreement between GoAhead and You and
+supersedes all prior agreements, oral or written, with respect to the
+subject matter hereof.
+
+If You have any questions concerning this Agreement, You may write to
+GoAhead Software, Inc., 10900 N.E. 8th Street, Suite 750, Bellevue,
+Washington 98004 or send e-mail to info@goahead.com.
+
+BY CLICKING ON THE "Register" BUTTON ON THE REGISTRATION FORM, YOU
+ACCEPT AND AGREE TO BE BOUND BY ALL OF THE TERMS AND CONDITIONS SET
+FORTH IN THIS AGREEMENT. IF YOU DO NOT WISH TO ACCEPT THIS LICENSE OR
+YOU DO NOT QUALIFY FOR A LICENSE BASED ON THE TERMS SET FORTH ABOVE,
+YOU MUST NOT CLICK THE "Register" BUTTON.
+
+Exhibit A
+
+GoAhead Trademarks, Logos, and Product Designation Information
+
+
+
+
+01/28/00
+
+
+
+
diff --git a/cpukit/httpd/md5.h b/cpukit/httpd/md5.h
new file mode 100644
index 0000000000..99df4eb735
--- /dev/null
+++ b/cpukit/httpd/md5.h
@@ -0,0 +1,50 @@
+/* MD5.H - header file for MD5C.C
+ *
+ * $Id$
+ */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+rights reserved.
+
+License to copy and use this software is granted provided that it
+is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+Algorithm" in all material mentioning or referencing this software
+or this function.
+
+License is also granted to make and use derivative works provided
+that such works are identified as "derived from the RSA Data
+Security, Inc. MD5 Message-Digest Algorithm" in all material
+mentioning or referencing the derived work.
+
+RSA Data Security, Inc. makes no representations concerning either
+the merchantability of this software or the suitability of this
+software for any particular purpose. It is provided "as is"
+without express or implied warranty of any kind.
+
+These notices must be retained in any copies of any part of this
+documentation and/or software.
+ */
+
+#ifndef _h_MD5
+#define _h_MD5 1
+
+#ifndef UINT4
+#define UINT4 unsigned long
+#endif
+
+#ifndef POINTER
+#define POINTER unsigned char *
+#endif
+
+/* MD5 context. */
+typedef struct {
+ UINT4 state[4]; /* state (ABCD) */
+ UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
+ unsigned char buffer[64]; /* input buffer */
+} MD5_CONTEXT;
+
+extern void MD5Init (MD5_CONTEXT *);
+extern void MD5Update (MD5_CONTEXT *, unsigned char *, unsigned int);
+extern void MD5Final (unsigned char [16], MD5_CONTEXT *);
+
+#endif /* _h_MD5 */
diff --git a/cpukit/httpd/md5c.c b/cpukit/httpd/md5c.c
new file mode 100644
index 0000000000..1e5a3442fa
--- /dev/null
+++ b/cpukit/httpd/md5c.c
@@ -0,0 +1,337 @@
+/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
+ *
+ * $Id$
+ */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+rights reserved.
+
+License to copy and use this software is granted provided that it
+is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+Algorithm" in all material mentioning or referencing this software
+or this function.
+
+License is also granted to make and use derivative works provided
+that such works are identified as "derived from the RSA Data
+Security, Inc. MD5 Message-Digest Algorithm" in all material
+mentioning or referencing the derived work.
+
+RSA Data Security, Inc. makes no representations concerning either
+the merchantability of this software or the suitability of this
+software for any particular purpose. It is provided "as is"
+without express or implied warranty of any kind.
+
+These notices must be retained in any copies of any part of this
+documentation and/or software.
+ */
+
+#include "md5.h"
+
+/* Constants for MD5Transform routine.
+ */
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+
+static void MD5Transform (UINT4 [4], unsigned char [64]);
+static void Encode (unsigned char *, UINT4 *, unsigned int);
+static void Decode (UINT4 *, unsigned char *, unsigned int);
+static void MD5_memcpy (POINTER, POINTER, unsigned int);
+static void MD5_memset (POINTER, int, unsigned int);
+
+static unsigned char PADDING[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * Note: The following MD5 macros can be implemented as functions
+ * for code compactness, (at the expense of execution speed).
+ */
+
+/* F, G, H and I are basic MD5 functions.
+ */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits.
+ */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+Rotation is separate from addition to prevent recomputation.
+ */
+#define FF(a, b, c, d, x, s, ac) { \
+ (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define GG(a, b, c, d, x, s, ac) { \
+ (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define HH(a, b, c, d, x, s, ac) { \
+ (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define II(a, b, c, d, x, s, ac) { \
+ (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+
+/* MD5 initialization. Begins an MD5 operation, writing a new context.
+ */
+void MD5Init (context)
+MD5_CONTEXT *context; /* context */
+{
+ context->count[0] = context->count[1] = 0;
+ /* Load magic initialization constants.
+*/
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xefcdab89;
+ context->state[2] = 0x98badcfe;
+ context->state[3] = 0x10325476;
+}
+
+/* MD5 block update operation. Continues an MD5 message-digest
+ operation, processing another message block, and updating the
+ context.
+ */
+void MD5Update (context, input, inputLen)
+MD5_CONTEXT *context; /* context */
+unsigned char *input; /* input block */
+unsigned int inputLen; /* length of input block */
+{
+ unsigned int i, index, partLen;
+
+ /* Compute number of bytes mod 64 */
+ index = (unsigned int)((context->count[0] >> 3) & 0x3F);
+
+ /* Update number of bits */
+ if ((context->count[0] += ((UINT4)inputLen << 3))
+ < ((UINT4)inputLen << 3))
+ context->count[1]++;
+ context->count[1] += ((UINT4)inputLen >> 29);
+
+ partLen = 64 - index;
+
+ /* Transform as many times as possible.
+*/
+ if (inputLen >= partLen) {
+ MD5_memcpy
+ ((POINTER)&context->buffer[index], (POINTER)input, partLen);
+ MD5Transform (context->state, context->buffer);
+
+ for (i = partLen; i + 63 < inputLen; i += 64)
+ MD5Transform (context->state, &input[i]);
+
+ index = 0;
+ }
+ else
+ i = 0;
+
+ /* Buffer remaining input */
+ MD5_memcpy
+ ((POINTER)&context->buffer[index], (POINTER)&input[i],
+ inputLen-i);
+}
+
+/* MD5 finalization. Ends an MD5 message-digest operation, writing the
+ the message digest and zeroizing the context.
+ */
+void MD5Final (digest, context)
+unsigned char digest[16]; /* message digest */
+MD5_CONTEXT *context; /* context */
+{
+ unsigned char bits[8];
+ unsigned int index, padLen;
+
+ /* Save number of bits */
+ Encode (bits, context->count, 8);
+
+ /* Pad out to 56 mod 64.
+*/
+ index = (unsigned int)((context->count[0] >> 3) & 0x3f);
+ padLen = (index < 56) ? (56 - index) : (120 - index);
+ MD5Update (context, PADDING, padLen);
+
+ /* Append length (before padding) */
+ MD5Update (context, bits, 8);
+ /* Store state in digest */
+ Encode (digest, context->state, 16);
+
+ /* Zeroize sensitive information.
+*/
+ MD5_memset ((POINTER)context, 0, sizeof (*context));
+}
+
+/* MD5 basic transformation. Transforms state based on block.
+ */
+static void MD5Transform (state, block)
+UINT4 state[4];
+unsigned char block[64];
+{
+ UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
+
+ Decode (x, block, 64);
+
+ /* Round 1 */
+ FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
+ FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
+ FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
+ FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
+ FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
+ FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
+ FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
+ FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
+ FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
+ FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
+ FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+ FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+ FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+ FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+ FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+ FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+
+ /* Round 2 */
+ GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
+ GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
+ GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+ GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
+ GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
+ GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
+ GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+ GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
+ GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
+ GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+ GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
+ GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
+ GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+ GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
+ GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
+ GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+
+ /* Round 3 */
+ HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
+ HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
+ HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+ HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+ HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
+ HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
+ HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
+ HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+ HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+ HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
+ HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
+ HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
+ HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
+ HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+ HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+ HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
+
+ /* Round 4 */
+ II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
+ II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
+ II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+ II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
+ II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+ II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
+ II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+ II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
+ II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
+ II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+ II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
+ II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+ II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
+ II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+ II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
+ II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
+
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+
+ /* Zeroize sensitive information.
+*/
+ MD5_memset ((POINTER)x, 0, sizeof (x));
+}
+
+/* Encodes input (UINT4) into output (unsigned char). Assumes len is
+ a multiple of 4.
+ */
+static void Encode (output, input, len)
+unsigned char *output;
+UINT4 *input;
+unsigned int len;
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4) {
+ output[j] = (unsigned char)(input[i] & 0xff);
+ output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
+ output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
+ output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
+ }
+}
+
+/* Decodes input (unsigned char) into output (UINT4). Assumes len is
+ a multiple of 4.
+ */
+static void Decode (output, input, len)
+UINT4 *output;
+unsigned char *input;
+unsigned int len;
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4)
+ output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
+ (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
+}
+
+/* Note: Replace "for loop" with standard memcpy if possible.
+ */
+
+static void MD5_memcpy (output, input, len)
+POINTER output;
+POINTER input;
+unsigned int len;
+{
+ unsigned int i;
+
+ for (i = 0; i < len; i++)
+ output[i] = input[i];
+}
+
+/* Note: Replace "for loop" with standard memset if possible.
+ */
+static void MD5_memset (output, value, len)
+POINTER output;
+int value;
+unsigned int len;
+{
+ unsigned int i;
+
+ for (i = 0; i < len; i++)
+ ((char *)output)[i] = (char)value;
+}
diff --git a/cpukit/httpd/mime.c b/cpukit/httpd/mime.c
new file mode 100644
index 0000000000..689360ea68
--- /dev/null
+++ b/cpukit/httpd/mime.c
@@ -0,0 +1,116 @@
+/*
+ * mime.c -- Web server mime types
+ *
+ * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for usage and redistribution license requirements
+ *
+ * $Id$
+ */
+
+/******************************** Description *********************************/
+
+/*
+ * Mime types and file extensions. This module maps URL extensions to
+ * content types.
+ */
+
+/********************************* Includes ***********************************/
+
+#include "wsIntrn.h"
+
+/******************************** Global Data *********************************/
+/*
+ * Addd entries to the MimeList as required for your content
+ */
+
+
+websMimeType websMimeList[] = {
+ { T("application/java"), T(".class") },
+ { T("application/java"), T(".jar") },
+ { T("text/html"), T(".asp") },
+ { T("text/html"), T(".htm") },
+ { T("text/html"), T(".html") },
+ { T("image/gif"), T(".gif") },
+ { T("image/jpeg"), T(".jpg") },
+ { T("text/css"), T(".css") },
+ { T("text/plain"), T(".txt") },
+ { T("application/x-javascript"), T(".js") },
+
+#ifdef MORE_MIME_TYPES
+ { T("application/binary"), T(".exe") },
+ { T("application/compress"), T(".z") },
+ { T("application/gzip"), T(".gz") },
+ { T("application/octet-stream"), T(".bin") },
+ { T("application/oda"), T(".oda") },
+ { T("application/pdf"), T(".pdf") },
+ { T("application/postscript"), T(".ai") },
+ { T("application/postscript"), T(".eps") },
+ { T("application/postscript"), T(".ps") },
+ { T("application/rtf"), T(".rtf") },
+ { T("application/x-bcpio"), T(".bcpio") },
+ { T("application/x-cpio"), T(".cpio") },
+ { T("application/x-csh"), T(".csh") },
+ { T("application/x-dvi"), T(".dvi") },
+ { T("application/x-gtar"), T(".gtar") },
+ { T("application/x-hdf"), T(".hdf") },
+ { T("application/x-latex"), T(".latex") },
+ { T("application/x-mif"), T(".mif") },
+ { T("application/x-netcdf"), T(".nc") },
+ { T("application/x-netcdf"), T(".cdf") },
+ { T("application/x-ns-proxy-autoconfig"), T(".pac") },
+ { T("application/x-patch"), T(".patch") },
+ { T("application/x-sh"), T(".sh") },
+ { T("application/x-shar"), T(".shar") },
+ { T("application/x-sv4cpio"), T(".sv4cpio") },
+ { T("application/x-sv4crc"), T(".sv4crc") },
+ { T("application/x-tar"), T(".tar") },
+ { T("application/x-tcl"), T(".tcl") },
+ { T("application/x-tex"), T(".tex") },
+ { T("application/x-texinfo"), T(".texinfo") },
+ { T("application/x-texinfo"), T(".texi") },
+ { T("application/x-troff"), T(".t") },
+ { T("application/x-troff"), T(".tr") },
+ { T("application/x-troff"), T(".roff") },
+ { T("application/x-troff-man"), T(".man") },
+ { T("application/x-troff-me"), T(".me") },
+ { T("application/x-troff-ms"), T(".ms") },
+ { T("application/x-ustar"), T(".ustar") },
+ { T("application/x-wais-source"), T(".src") },
+ { T("application/zip"), T(".zip") },
+ { T("audio/basic"), T(".au snd") },
+ { T("audio/x-aiff"), T(".aif") },
+ { T("audio/x-aiff"), T(".aiff") },
+ { T("audio/x-aiff"), T(".aifc") },
+ { T("audio/x-wav"), T(".wav") },
+ { T("audio/x-wav"), T(".ram") },
+ { T("image/ief"), T(".ief") },
+ { T("image/jpeg"), T(".jpeg") },
+ { T("image/jpeg"), T(".jpe") },
+ { T("image/tiff"), T(".tiff") },
+ { T("image/tiff"), T(".tif") },
+ { T("image/x-cmu-raster"), T(".ras") },
+ { T("image/x-portable-anymap"), T(".pnm") },
+ { T("image/x-portable-bitmap"), T(".pbm") },
+ { T("image/x-portable-graymap"), T(".pgm") },
+ { T("image/x-portable-pixmap"), T(".ppm") },
+ { T("image/x-rgb"), T(".rgb") },
+ { T("image/x-xbitmap"), T(".xbm") },
+ { T("image/x-xpixmap"), T(".xpm") },
+ { T("image/x-xwindowdump"), T(".xwd") },
+ { T("text/html"), T(".cfm") },
+ { T("text/html"), T(".shtm") },
+ { T("text/html"), T(".shtml") },
+ { T("text/richtext"), T(".rtx") },
+ { T("text/tab-separated-values"), T(".tsv") },
+ { T("text/x-setext"), T(".etx") },
+ { T("video/mpeg"), T(".mpeg mpg mpe") },
+ { T("video/quicktime"), T(".qt") },
+ { T("video/quicktime"), T(".mov") },
+ { T("video/x-msvideo"), T(".avi") },
+ { T("video/x-sgi-movie"), T(".movie") },
+#endif
+ { NULL, NULL},
+};
+
+/*****************************************************************************/
diff --git a/cpukit/httpd/misc.c b/cpukit/httpd/misc.c
new file mode 100644
index 0000000000..e08b7c76b4
--- /dev/null
+++ b/cpukit/httpd/misc.c
@@ -0,0 +1,675 @@
+/*
+ * misc.c -- Miscellaneous routines.
+ *
+ * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for usage and redistribution license requirements
+ *
+ * $Id$
+ */
+
+/********************************* Includes ***********************************/
+
+#ifdef UEMF
+ #include "uemf.h"
+#else
+ #include "basic/basicInternal.h"
+#endif
+
+/********************************* Defines ************************************/
+/*
+ * Sprintf buffer structure. Make the increment 64 so that
+ * a balloc can use a 64 byte block.
+ */
+
+#define STR_REALLOC 0x1 /* Reallocate the buffer as required */
+#define STR_INC 64 /* Growth increment */
+
+typedef struct {
+ char_t *s; /* Pointer to buffer */
+ int size; /* Current buffer size */
+ int max; /* Maximum buffer size */
+ int count; /* Buffer count */
+ int flags; /* Allocation flags */
+} strbuf_t;
+
+/*
+ * Sprintf formatting flags
+ */
+enum flag {
+ flag_none = 0,
+ flag_minus = 1,
+ flag_plus = 2,
+ flag_space = 4,
+ flag_hash = 8,
+ flag_zero = 16,
+ flag_short = 32,
+ flag_long = 64
+};
+
+/************************** Forward Declarations ******************************/
+
+static int dsnprintf(char_t **s, int size, char_t *fmt, va_list arg,
+ int msize);
+#if !defined(__rtems__)
+static int strnlen(char_t *s, unsigned int n);
+#endif
+static void put_char(strbuf_t *buf, char_t c);
+static void put_string(strbuf_t *buf, char_t *s, int len,
+ int width, int prec, enum flag f);
+static void put_ulong(strbuf_t *buf, unsigned long int value, int base,
+ int upper, char_t *prefix, int width, int prec, enum flag f);
+
+/************************************ Code ************************************/
+/*
+ * "basename" returns a pointer to the last component of a pathname
+ * LINUX, LynxOS and Mac OS X have their own basename function
+ */
+
+#if (!defined (LINUX) && !defined (LYNX) && !defined (MACOSX))
+char_t *basename(char_t *name)
+{
+ char_t *cp;
+
+#if (defined (NW) || defined (WIN))
+ if (((cp = gstrrchr(name, '\\')) == NULL) &&
+ ((cp = gstrrchr(name, '/')) == NULL)) {
+ return name;
+#else
+ if ((cp = gstrrchr(name, '/')) == NULL) {
+ return name;
+#endif
+ } else if (*(cp + 1) == '\0' && cp == name) {
+ return name;
+ } else if (*(cp + 1) == '\0' && cp != name) {
+ return T("");
+ } else {
+ return ++cp;
+ }
+}
+#endif /* ! LINUX & ! LYNX & ! MACOSX */
+
+/******************************************************************************/
+/*
+ * Returns a pointer to the directory component of a pathname. bufsize is
+ * the size of the buffer in BYTES!
+ */
+
+char_t *dirname(char_t *buf, char_t *name, int bufsize)
+{
+ char_t *cp;
+ int len;
+
+ a_assert(name);
+ a_assert(buf);
+ a_assert(bufsize > 0);
+
+#if (defined (WIN) || defined (NW))
+ if ((cp = gstrrchr(name, '/')) == NULL &&
+ (cp = gstrrchr(name, '\\')) == NULL)
+#else
+ if ((cp = gstrrchr(name, '/')) == NULL)
+#endif
+ {
+ gstrcpy(buf, T("."));
+ return buf;
+ }
+
+ if ((*(cp + 1) == '\0' && cp == name)) {
+ gstrncpy(buf, T("."), TSZ(bufsize));
+ gstrcpy(buf, T("."));
+ return buf;
+ }
+
+ len = cp - name;
+
+ if (len < bufsize) {
+ gstrncpy(buf, name, len);
+ buf[len] = '\0';
+ } else {
+ gstrncpy(buf, name, TSZ(bufsize));
+ buf[bufsize - 1] = '\0';
+ }
+
+ return buf;
+}
+
+
+/******************************************************************************/
+/*
+ * sprintf and vsprintf are bad, ok. You can easily clobber memory. Use
+ * fmtAlloc and fmtValloc instead! These functions do _not_ support floating
+ * point, like %e, %f, %g...
+ */
+
+int fmtAlloc(char_t **s, int n, char_t *fmt, ...)
+{
+ va_list ap;
+ int result;
+
+ a_assert(s);
+ a_assert(fmt);
+
+ *s = NULL;
+ va_start(ap, fmt);
+ result = dsnprintf(s, n, fmt, ap, 0);
+ va_end(ap);
+ return result;
+}
+
+/******************************************************************************/
+/*
+ * Support a static buffer version for small buffers only!
+ */
+
+int fmtStatic(char_t *s, int n, char_t *fmt, ...)
+{
+ va_list ap;
+ int result;
+
+ a_assert(s);
+ a_assert(fmt);
+ a_assert(n <= 256);
+
+ if (n <= 0) {
+ return -1;
+ }
+ va_start(ap, fmt);
+ result = dsnprintf(&s, n, fmt, ap, 0);
+ va_end(ap);
+ return result;
+}
+
+/******************************************************************************/
+/*
+ * This function appends the formatted string to the supplied string,
+ * reallocing if required.
+ */
+
+int fmtRealloc(char_t **s, int n, int msize, char_t *fmt, ...)
+{
+ va_list ap;
+ int result;
+
+ a_assert(s);
+ a_assert(fmt);
+
+ if (msize == -1) {
+ *s = NULL;
+ }
+ va_start(ap, fmt);
+ result = dsnprintf(s, n, fmt, ap, msize);
+ va_end(ap);
+ return result;
+}
+
+/******************************************************************************/
+/*
+ * A vsprintf replacement.
+ */
+
+int fmtValloc(char_t **s, int n, char_t *fmt, va_list arg)
+{
+ a_assert(s);
+ a_assert(fmt);
+
+ *s = NULL;
+ return dsnprintf(s, n, fmt, arg, 0);
+}
+
+/******************************************************************************/
+/*
+ * Dynamic sprintf implementation. Supports dynamic buffer allocation.
+ * This function can be called multiple times to grow an existing allocated
+ * buffer. In this case, msize is set to the size of the previously allocated
+ * buffer. The buffer will be realloced, as required. If msize is set, we
+ * return the size of the allocated buffer for use with the next call. For
+ * the first call, msize can be set to -1.
+ */
+
+static int dsnprintf(char_t **s, int size, char_t *fmt, va_list arg, int msize)
+{
+ strbuf_t buf;
+ char_t c;
+
+ a_assert(s);
+ a_assert(fmt);
+
+ memset(&buf, 0, sizeof(buf));
+ buf.s = *s;
+
+ if (*s == NULL || msize != 0) {
+ buf.max = size;
+ buf.flags |= STR_REALLOC;
+ if (msize != 0) {
+ buf.size = max(msize, 0);
+ }
+ if (*s != NULL && msize != 0) {
+ buf.count = gstrlen(*s);
+ }
+ } else {
+ buf.size = size;
+ }
+
+ while ((c = *fmt++) != '\0') {
+ if (c != '%' || (c = *fmt++) == '%') {
+ put_char(&buf, c);
+ } else {
+ enum flag f = flag_none;
+ int width = 0;
+ int prec = -1;
+ for ( ; c != '\0'; c = *fmt++) {
+ if (c == '-') {
+ f |= flag_minus;
+ } else if (c == '+') {
+ f |= flag_plus;
+ } else if (c == ' ') {
+ f |= flag_space;
+ } else if (c == '#') {
+ f |= flag_hash;
+ } else if (c == '0') {
+ f |= flag_zero;
+ } else {
+ break;
+ }
+ }
+ if (c == '*') {
+ width = va_arg(arg, int);
+ if (width < 0) {
+ f |= flag_minus;
+ width = -width;
+ }
+ c = *fmt++;
+ } else {
+ for ( ; gisdigit((int)c); c = *fmt++) {
+ width = width * 10 + (c - '0');
+ }
+ }
+ if (c == '.') {
+ f &= ~flag_zero;
+ c = *fmt++;
+ if (c == '*') {
+ prec = va_arg(arg, int);
+ c = *fmt++;
+ } else {
+ for (prec = 0; gisdigit((int)c); c = *fmt++) {
+ prec = prec * 10 + (c - '0');
+ }
+ }
+ }
+ if (c == 'h' || c == 'l') {
+ f |= (c == 'h' ? flag_short : flag_long);
+ c = *fmt++;
+ }
+ if (c == 'd' || c == 'i') {
+ long int value;
+ if (f & flag_short) {
+ value = (short int) va_arg(arg, int);
+ } else if (f & flag_long) {
+ value = va_arg(arg, long int);
+ } else {
+ value = va_arg(arg, int);
+ }
+ if (value >= 0) {
+ if (f & flag_plus) {
+ put_ulong(&buf, value, 10, 0, T("+"), width, prec, f);
+ } else if (f & flag_space) {
+ put_ulong(&buf, value, 10, 0, T(" "), width, prec, f);
+ } else {
+ put_ulong(&buf, value, 10, 0, NULL, width, prec, f);
+ }
+ } else {
+ put_ulong(&buf, -value, 10, 0, T("-"), width, prec, f);
+ }
+ } else if (c == 'o' || c == 'u' || c == 'x' || c == 'X') {
+ unsigned long int value;
+ if (f & flag_short) {
+ value = (unsigned short int) va_arg(arg, unsigned int);
+ } else if (f & flag_long) {
+ value = va_arg(arg, unsigned long int);
+ } else {
+ value = va_arg(arg, unsigned int);
+ }
+ if (c == 'o') {
+ if (f & flag_hash && value != 0) {
+ put_ulong(&buf, value, 8, 0, T("0"), width, prec, f);
+ } else {
+ put_ulong(&buf, value, 8, 0, NULL, width, prec, f);
+ }
+ } else if (c == 'u') {
+ put_ulong(&buf, value, 10, 0, NULL, width, prec, f);
+ } else {
+ if (f & flag_hash && value != 0) {
+ if (c == 'x') {
+ put_ulong(&buf, value, 16, 0, T("0x"), width,
+ prec, f);
+ } else {
+ put_ulong(&buf, value, 16, 1, T("0X"), width,
+ prec, f);
+ }
+ } else {
+ /* 04 Apr 02 BgP -- changed so that %X correctly outputs
+ * uppercase hex digits when requested.
+ put_ulong(&buf, value, 16, 0, NULL, width, prec, f);
+ */
+ put_ulong(&buf, value, 16, ('X' == c) , NULL, width, prec, f);
+ }
+ }
+
+ } else if (c == 'c') {
+ char_t value = va_arg(arg, int);
+ put_char(&buf, value);
+
+ } else if (c == 's' || c == 'S') {
+ char_t *value = va_arg(arg, char_t *);
+ if (value == NULL) {
+ put_string(&buf, T("(null)"), -1, width, prec, f);
+ } else if (f & flag_hash) {
+ put_string(&buf,
+ value + 1, (char_t) *value, width, prec, f);
+ } else {
+ put_string(&buf, value, -1, width, prec, f);
+ }
+ } else if (c == 'p') {
+ void *value = va_arg(arg, void *);
+ put_ulong(&buf,
+ (unsigned long int) value, 16, 0, T("0x"), width, prec, f);
+ } else if (c == 'n') {
+ if (f & flag_short) {
+ short int *value = va_arg(arg, short int *);
+ *value = buf.count;
+ } else if (f & flag_long) {
+ long int *value = va_arg(arg, long int *);
+ *value = buf.count;
+ } else {
+ int *value = va_arg(arg, int *);
+ *value = buf.count;
+ }
+ } else {
+ put_char(&buf, c);
+ }
+ }
+ }
+ if (buf.s == NULL) {
+ put_char(&buf, '\0');
+ }
+
+/*
+ * If the user requested a dynamic buffer (*s == NULL), ensure it is returned.
+ */
+ if (*s == NULL || msize != 0) {
+ *s = buf.s;
+ }
+
+ if (*s != NULL && size > 0) {
+ if (buf.count < size) {
+ (*s)[buf.count] = '\0';
+ } else {
+ (*s)[buf.size - 1] = '\0';
+ }
+ }
+
+ if (msize != 0) {
+ return buf.size;
+ }
+ return buf.count;
+}
+
+/******************************************************************************/
+/*
+ * Return the length of a string limited by a given length
+ */
+
+#if !defined(__rtems__)
+static int strnlen(char_t *s, unsigned int n)
+{
+ unsigned int len;
+
+ len = gstrlen(s);
+ return min(len, n);
+}
+#endif
+
+/******************************************************************************/
+/*
+ * Add a character to a string buffer
+ */
+
+static void put_char(strbuf_t *buf, char_t c)
+{
+ if (buf->count >= (buf->size - 1)) {
+ if (! (buf->flags & STR_REALLOC)) {
+ return;
+ }
+ buf->size += STR_INC;
+ if (buf->size > buf->max && buf->size > STR_INC) {
+/*
+ * Caller should increase the size of the calling buffer
+ */
+ buf->size -= STR_INC;
+ return;
+ }
+ if (buf->s == NULL) {
+ buf->s = balloc(B_L, buf->size * sizeof(char_t));
+ } else {
+ buf->s = brealloc(B_L, buf->s, buf->size * sizeof(char_t));
+ }
+ }
+ buf->s[buf->count] = c;
+ if (c != '\0') {
+ ++buf->count;
+ }
+}
+
+/******************************************************************************/
+/*
+ * Add a string to a string buffer
+ */
+
+static void put_string(strbuf_t *buf, char_t *s, int len, int width,
+ int prec, enum flag f)
+{
+ int i;
+
+ if (len < 0) {
+ len = strnlen(s, prec >= 0 ? prec : ULONG_MAX);
+ } else if (prec >= 0 && prec < len) {
+ len = prec;
+ }
+ if (width > len && !(f & flag_minus)) {
+ for (i = len; i < width; ++i) {
+ put_char(buf, ' ');
+ }
+ }
+ for (i = 0; i < len; ++i) {
+ put_char(buf, s[i]);
+ }
+ if (width > len && f & flag_minus) {
+ for (i = len; i < width; ++i) {
+ put_char(buf, ' ');
+ }
+ }
+}
+
+/******************************************************************************/
+/*
+ * Add a long to a string buffer
+ */
+
+static void put_ulong(strbuf_t *buf, unsigned long int value, int base,
+ int upper, char_t *prefix, int width, int prec, enum flag f)
+{
+ unsigned long x, x2;
+ int len, zeros, i;
+
+ for (len = 1, x = 1; x < ULONG_MAX / base; ++len, x = x2) {
+ x2 = x * base;
+ if (x2 > value) {
+ break;
+ }
+ }
+ zeros = (prec > len) ? prec - len : 0;
+ width -= zeros + len;
+ if (prefix != NULL) {
+ width -= strnlen(prefix, ULONG_MAX);
+ }
+ if (!(f & flag_minus)) {
+ if (f & flag_zero) {
+ for (i = 0; i < width; ++i) {
+ put_char(buf, '0');
+ }
+ } else {
+ for (i = 0; i < width; ++i) {
+ put_char(buf, ' ');
+ }
+ }
+ }
+ if (prefix != NULL) {
+ put_string(buf, prefix, -1, 0, -1, flag_none);
+ }
+ for (i = 0; i < zeros; ++i) {
+ put_char(buf, '0');
+ }
+ for ( ; x > 0; x /= base) {
+ int digit = (value / x) % base;
+ put_char(buf, (char) ((digit < 10 ? '0' : (upper ? 'A' : 'a') - 10) +
+ digit));
+ }
+ if (f & flag_minus) {
+ for (i = 0; i < width; ++i) {
+ put_char(buf, ' ');
+ }
+ }
+}
+
+/******************************************************************************/
+/*
+ * Convert an ansi string to a unicode string. On an error, we return the
+ * original ansi string which is better than returning NULL. nBytes is the
+ * size of the destination buffer (ubuf) in _bytes_.
+ */
+
+char_t *ascToUni(char_t *ubuf, char *str, int nBytes)
+{
+#ifdef UNICODE
+ if (MultiByteToWideChar(CP_ACP, 0, str, nBytes / sizeof(char_t), ubuf,
+ nBytes / sizeof(char_t)) < 0) {
+ return (char_t*) str;
+ }
+#else
+ strncpy(ubuf, str, nBytes);
+#endif
+ return ubuf;
+}
+
+/******************************************************************************/
+/*
+ * Convert a unicode string to an ansi string. On an error, return the
+ * original unicode string which is better than returning NULL.
+ * N.B. nBytes is the number of _bytes_ in the destination buffer, buf.
+ */
+
+char *uniToAsc(char *buf, char_t *ustr, int nBytes)
+{
+#ifdef UNICODE
+ if (WideCharToMultiByte(CP_ACP, 0, ustr, nBytes, buf, nBytes, NULL,
+ NULL) < 0) {
+ return (char*) ustr;
+ }
+#else
+ strncpy(buf, ustr, nBytes);
+#endif
+ return (char*) buf;
+}
+
+/******************************************************************************/
+/*
+ * allocate (balloc) a buffer and do ascii to unicode conversion into it.
+ * cp points to the ascii buffer. alen is the length of the buffer to be
+ * converted not including a terminating NULL. Return a pointer to the
+ * unicode buffer which must be bfree'd later. Return NULL on failure to
+ * get buffer. The buffer returned is NULL terminated.
+ */
+
+char_t *ballocAscToUni(char *cp, int alen)
+{
+ char_t *unip;
+ int ulen;
+
+ ulen = (alen + 1) * sizeof(char_t);
+ if ((unip = balloc(B_L, ulen)) == NULL) {
+ return NULL;
+ }
+ ascToUni(unip, cp, ulen);
+ unip[alen] = 0;
+ return unip;
+}
+
+/******************************************************************************/
+/*
+ * allocate (balloc) a buffer and do unicode to ascii conversion into it.
+ * unip points to the unicoded string. ulen is the number of characters
+ * in the unicode string not including a teminating null. Return a pointer
+ * to the ascii buffer which must be bfree'd later. Return NULL on failure
+ * to get buffer. The buffer returned is NULL terminated.
+ */
+
+char *ballocUniToAsc(char_t *unip, int ulen)
+{
+ char * cp;
+
+ if ((cp = balloc(B_L, ulen+1)) == NULL) {
+ return NULL;
+ }
+ uniToAsc(cp, unip, ulen);
+ cp[ulen] = '\0';
+ return cp;
+}
+
+/******************************************************************************/
+/*
+ * convert a hex string to an integer. The end of the string or a non-hex
+ * character will indicate the end of the hex specification.
+ */
+
+unsigned int hextoi(char_t *hexstring)
+{
+ register char_t *h;
+ register unsigned int c, v;
+
+ v = 0;
+ h = hexstring;
+ if (*h == '0' && (*(h+1) == 'x' || *(h+1) == 'X')) {
+ h += 2;
+ }
+ while ((c = (unsigned int)*h++) != 0) {
+ if (c >= '0' && c <= '9') {
+ c -= '0';
+ } else if (c >= 'a' && c <= 'f') {
+ c = (c - 'a') + 10;
+ } else if (c >= 'A' && c <= 'F') {
+ c = (c - 'A') + 10;
+ } else {
+ break;
+ }
+ v = (v * 0x10) + c;
+ }
+ return v;
+}
+
+/******************************************************************************/
+/*
+ * convert a string to an integer. If the string starts with "0x" or "0X"
+ * a hexidecimal conversion is done.
+ */
+
+unsigned int gstrtoi(char_t *s)
+{
+ if (*s == '0' && (*(s+1) == 'x' || *(s+1) == 'X')) {
+ s += 2;
+ return hextoi(s);
+ }
+ return gatoi(s);
+}
+
+/******************************************************************************/
diff --git a/cpukit/httpd/ringq.c b/cpukit/httpd/ringq.c
new file mode 100644
index 0000000000..efb9c45a70
--- /dev/null
+++ b/cpukit/httpd/ringq.c
@@ -0,0 +1,584 @@
+/*
+ * ringq.c -- Ring queue buffering module
+ *
+ * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for usage and redistribution license requirements
+ *
+ * $Id$
+ */
+
+/******************************** Description *********************************/
+
+/*
+ * A ring queue allows maximum utilization of memory for data storage and is
+ * ideal for input/output buffering. This module provides a highly efficient
+ * implementation and a vehicle for dynamic strings.
+ *
+ * WARNING: This is a public implementation and callers have full access to
+ * the queue structure and pointers. Change this module very carefully.
+ *
+ * This module follows the open/close model.
+ *
+ * Operation of a ringq where rq is a pointer to a ringq :
+ *
+ * rq->buflen contains the size of the buffer.
+ * rq->buf will point to the start of the buffer.
+ * rq->servp will point to the first (un-consumed) data byte.
+ * rq->endp will point to the next free location to which new data is added
+ * rq->endbuf will point to one past the end of the buffer.
+ *
+ * Eg. If the ringq contains the data "abcdef", it might look like :
+ *
+ * +-------------------------------------------------------------------+
+ * | | | | | | | | a | b | c | d | e | f | | | | |
+ * +-------------------------------------------------------------------+
+ * ^ ^ ^ ^
+ * | | | |
+ * rq->buf rq->servp rq->endp rq->enduf
+ *
+ * The queue is empty when servp == endp. This means that the queue will hold
+ * at most rq->buflen -1 bytes. It is the filler's responsibility to ensure
+ * the ringq is never filled such that servp == endp.
+ *
+ * It is the filler's responsibility to "wrap" the endp back to point to
+ * rq->buf when the pointer steps past the end. Correspondingly it is the
+ * consumers responsibility to "wrap" the servp when it steps to rq->endbuf.
+ * The ringqPutc and ringqGetc routines will do this automatically.
+ */
+
+/********************************* Includes ***********************************/
+
+#ifdef UEMF
+ #include "uemf.h"
+#else
+ #include "basic/basicInternal.h"
+#endif
+
+/*********************************** Defines **********************************/
+/*
+ * Faster than a function call
+ */
+
+#define RINGQ_LEN(rq) \
+ ((rq->servp > rq->endp) ? \
+ (rq->buflen + (rq->endp - rq->servp)) : \
+ (rq->endp - rq->servp))
+
+/***************************** Forward Declarations ***************************/
+
+static int ringqGrow(ringq_t *rq);
+static int getBinBlockSize(int size);
+
+int ringqGrowCalls = 0;
+
+/*********************************** Code *************************************/
+/*
+ * Create a new ringq. "increment" is the amount to increase the size of the
+ * ringq should it need to grow to accomodate data being added. "maxsize" is
+ * an upper limit (sanity level) beyond which the q must not grow. Set maxsize
+ * to -1 to imply no upper limit. The buffer for the ringq is always
+ * dynamically allocated. Set maxsize
+ */
+
+int ringqOpen(ringq_t *rq, int initSize, int maxsize)
+{
+ int increment;
+
+ a_assert(rq);
+ a_assert(initSize >= 0);
+
+ increment = getBinBlockSize(initSize);
+ if ((rq->buf = balloc(B_L, (increment))) == NULL) {
+ return -1;
+ }
+ rq->maxsize = maxsize;
+ rq->buflen = increment;
+ rq->increment = increment;
+ rq->endbuf = &rq->buf[rq->buflen];
+ rq->servp = rq->buf;
+ rq->endp = rq->buf;
+ *rq->servp = '\0';
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Delete a ringq and free the ringq buffer.
+ */
+
+void ringqClose(ringq_t *rq)
+{
+ a_assert(rq);
+ a_assert(rq->buflen == (rq->endbuf - rq->buf));
+
+ if (rq == NULL) {
+ return;
+ }
+
+ ringqFlush(rq);
+ bfree(B_L, (char*) rq->buf);
+ rq->buf = NULL;
+}
+
+/******************************************************************************/
+/*
+ * Return the length of the data in the ringq. Users must fill the queue to
+ * a high water mark of at most one less than the queue size.
+ */
+
+int ringqLen(ringq_t *rq)
+{
+ a_assert(rq);
+ a_assert(rq->buflen == (rq->endbuf - rq->buf));
+
+ if (rq->servp > rq->endp) {
+ return rq->buflen + rq->endp - rq->servp;
+ } else {
+ return rq->endp - rq->servp;
+ }
+}
+
+/******************************************************************************/
+/*
+ * Get a byte from the queue
+ */
+
+int ringqGetc(ringq_t *rq)
+{
+ char_t c;
+ char_t* cp;
+
+ a_assert(rq);
+ a_assert(rq->buflen == (rq->endbuf - rq->buf));
+
+ if (rq->servp == rq->endp) {
+ return -1;
+ }
+
+ cp = (char_t*) rq->servp;
+ c = *cp++;
+ rq->servp = (unsigned char *) cp;
+ if (rq->servp >= rq->endbuf) {
+ rq->servp = rq->buf;
+ }
+ return c;
+}
+
+/******************************************************************************/
+/*
+ * Add a char to the queue. Note if being used to store wide strings
+ * this does not add a trailing '\0'. Grow the q as required.
+ */
+
+int ringqPutc(ringq_t *rq, char_t c)
+{
+ char_t *cp;
+
+ a_assert(rq);
+ a_assert(rq->buflen == (rq->endbuf - rq->buf));
+
+ if ((ringqPutBlkMax(rq) < (int) sizeof(char_t)) && !ringqGrow(rq)) {
+ return -1;
+ }
+
+ cp = (char_t*) rq->endp;
+ *cp++ = (char_t) c;
+ rq->endp = (unsigned char *) cp;
+ if (rq->endp >= rq->endbuf) {
+ rq->endp = rq->buf;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Insert a wide character at the front of the queue
+ */
+
+int ringqInsertc(ringq_t *rq, char_t c)
+{
+ char_t *cp;
+
+ a_assert(rq);
+ a_assert(rq->buflen == (rq->endbuf - rq->buf));
+
+ if (ringqPutBlkMax(rq) < (int) sizeof(char_t) && !ringqGrow(rq)) {
+ return -1;
+ }
+ if (rq->servp <= rq->buf) {
+ rq->servp = rq->endbuf;
+ }
+ cp = (char_t*) rq->servp;
+ *--cp = (char_t) c;
+ rq->servp = (unsigned char *) cp;
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Add a string to the queue. Add a trailing null (maybe two nulls)
+ */
+
+int ringqPutStr(ringq_t *rq, char_t *str)
+{
+ int rc;
+
+ a_assert(rq);
+ a_assert(str);
+ a_assert(rq->buflen == (rq->endbuf - rq->buf));
+
+ rc = ringqPutBlk(rq, (unsigned char*) str, gstrlen(str) * sizeof(char_t));
+ *((char_t*) rq->endp) = (char_t) '\0';
+ return rc;
+}
+
+/******************************************************************************/
+/*
+ * Add a null terminator. This does NOT increase the size of the queue
+ */
+
+void ringqAddNull(ringq_t *rq)
+{
+ a_assert(rq);
+ a_assert(rq->buflen == (rq->endbuf - rq->buf));
+
+ *((char_t*) rq->endp) = (char_t) '\0';
+}
+
+/******************************************************************************/
+#ifdef UNICODE
+/*
+ * Get a byte from the queue
+ */
+
+int ringqGetcA(ringq_t *rq)
+{
+ unsigned char c;
+
+ a_assert(rq);
+ a_assert(rq->buflen == (rq->endbuf - rq->buf));
+
+ if (rq->servp == rq->endp) {
+ return -1;
+ }
+
+ c = *rq->servp++;
+ if (rq->servp >= rq->endbuf) {
+ rq->servp = rq->buf;
+ }
+ return c;
+}
+
+/******************************************************************************/
+/*
+ * Add a byte to the queue. Note if being used to store strings this does not
+ * add a trailing '\0'. Grow the q as required.
+ */
+
+int ringqPutcA(ringq_t *rq, char c)
+{
+ a_assert(rq);
+ a_assert(rq->buflen == (rq->endbuf - rq->buf));
+
+ if (ringqPutBlkMax(rq) == 0 && !ringqGrow(rq)) {
+ return -1;
+ }
+
+ *rq->endp++ = (unsigned char) c;
+ if (rq->endp >= rq->endbuf) {
+ rq->endp = rq->buf;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Insert a byte at the front of the queue
+ */
+
+int ringqInsertcA(ringq_t *rq, char c)
+{
+ a_assert(rq);
+ a_assert(rq->buflen == (rq->endbuf - rq->buf));
+
+ if (ringqPutBlkMax(rq) == 0 && !ringqGrow(rq)) {
+ return -1;
+ }
+ if (rq->servp <= rq->buf) {
+ rq->servp = rq->endbuf;
+ }
+ *--rq->servp = (unsigned char) c;
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Add a string to the queue. Add a trailing null (not really in the q).
+ * ie. beyond the last valid byte.
+ */
+
+int ringqPutStrA(ringq_t *rq, char *str)
+{
+ int rc;
+
+ a_assert(rq);
+ a_assert(str);
+ a_assert(rq->buflen == (rq->endbuf - rq->buf));
+
+ rc = ringqPutBlk(rq, (unsigned char*) str, strlen(str));
+ rq->endp[0] = '\0';
+ return rc;
+}
+
+#endif /* UNICODE */
+/******************************************************************************/
+/*
+ * Add a block of data to the ringq. Return the number of bytes added.
+ * Grow the q as required.
+ */
+
+int ringqPutBlk(ringq_t *rq, unsigned char *buf, int size)
+{
+ int this, bytes_put;
+
+ a_assert(rq);
+ a_assert(rq->buflen == (rq->endbuf - rq->buf));
+ a_assert(buf);
+ a_assert(0 <= size);
+
+/*
+ * Loop adding the maximum bytes we can add in a single straight line copy
+ */
+ bytes_put = 0;
+ while (size > 0) {
+ this = min(ringqPutBlkMax(rq), size);
+ if (this <= 0) {
+ if (! ringqGrow(rq)) {
+ break;
+ }
+ this = min(ringqPutBlkMax(rq), size);
+ }
+
+ memcpy(rq->endp, buf, this);
+ buf += this;
+ rq->endp += this;
+ size -= this;
+ bytes_put += this;
+
+ if (rq->endp >= rq->endbuf) {
+ rq->endp = rq->buf;
+ }
+ }
+ return bytes_put;
+}
+
+/******************************************************************************/
+/*
+ * Get a block of data from the ringq. Return the number of bytes returned.
+ */
+
+int ringqGetBlk(ringq_t *rq, unsigned char *buf, int size)
+{
+ int this, bytes_read;
+
+ a_assert(rq);
+ a_assert(rq->buflen == (rq->endbuf - rq->buf));
+ a_assert(buf);
+ a_assert(0 <= size && size < rq->buflen);
+
+/*
+ * Loop getting the maximum bytes we can get in a single straight line copy
+ */
+ bytes_read = 0;
+ while (size > 0) {
+ this = ringqGetBlkMax(rq);
+ this = min(this, size);
+ if (this <= 0) {
+ break;
+ }
+
+ memcpy(buf, rq->servp, this);
+ buf += this;
+ rq->servp += this;
+ size -= this;
+ bytes_read += this;
+
+ if (rq->servp >= rq->endbuf) {
+ rq->servp = rq->buf;
+ }
+ }
+ return bytes_read;
+}
+
+/******************************************************************************/
+/*
+ * Return the maximum number of bytes the ring q can accept via a single
+ * block copy. Useful if the user is doing their own data insertion.
+ */
+
+int ringqPutBlkMax(ringq_t *rq)
+{
+ int space, in_a_line;
+
+ a_assert(rq);
+ a_assert(rq->buflen == (rq->endbuf - rq->buf));
+
+ space = rq->buflen - RINGQ_LEN(rq) - 1;
+ in_a_line = rq->endbuf - rq->endp;
+
+ return min(in_a_line, space);
+}
+
+/******************************************************************************/
+/*
+ * Return the maximum number of bytes the ring q can provide via a single
+ * block copy. Useful if the user is doing their own data retrieval.
+ */
+
+int ringqGetBlkMax(ringq_t *rq)
+{
+ int len, in_a_line;
+
+ a_assert(rq);
+ a_assert(rq->buflen == (rq->endbuf - rq->buf));
+
+ len = RINGQ_LEN(rq);
+ in_a_line = rq->endbuf - rq->servp;
+
+ return min(in_a_line, len);
+}
+
+/******************************************************************************/
+/*
+ * Adjust the endp pointer after the user has copied data into the queue.
+ */
+
+void ringqPutBlkAdj(ringq_t *rq, int size)
+{
+ a_assert(rq);
+ a_assert(rq->buflen == (rq->endbuf - rq->buf));
+ a_assert(0 <= size && size < rq->buflen);
+
+ rq->endp += size;
+ if (rq->endp >= rq->endbuf) {
+ rq->endp -= rq->buflen;
+ }
+/*
+ * Flush the queue if the endp pointer is corrupted via a bad size
+ */
+ if (rq->endp >= rq->endbuf) {
+ error(E_L, E_LOG, T("Bad end pointer"));
+ ringqFlush(rq);
+ }
+}
+
+/******************************************************************************/
+/*
+ * Adjust the servp pointer after the user has copied data from the queue.
+ */
+
+void ringqGetBlkAdj(ringq_t *rq, int size)
+{
+ a_assert(rq);
+ a_assert(rq->buflen == (rq->endbuf - rq->buf));
+ a_assert(0 < size && size < rq->buflen);
+
+ rq->servp += size;
+ if (rq->servp >= rq->endbuf) {
+ rq->servp -= rq->buflen;
+ }
+/*
+ * Flush the queue if the servp pointer is corrupted via a bad size
+ */
+ if (rq->servp >= rq->endbuf) {
+ error(E_L, E_LOG, T("Bad serv pointer"));
+ ringqFlush(rq);
+ }
+}
+
+/******************************************************************************/
+/*
+ * Flush all data in a ring q. Reset the pointers.
+ */
+
+void ringqFlush(ringq_t *rq)
+{
+ a_assert(rq);
+ a_assert(rq->servp);
+
+ rq->servp = rq->buf;
+ rq->endp = rq->buf;
+ if (rq->servp) {
+ *rq->servp = '\0';
+ }
+}
+
+/******************************************************************************/
+/*
+ * Grow the buffer. Return true if the buffer can be grown. Grow using
+ * the increment size specified when opening the ringq. Don't grow beyond
+ * the maximum possible size.
+ */
+
+static int ringqGrow(ringq_t *rq)
+{
+ unsigned char *newbuf;
+ int len;
+
+ a_assert(rq);
+
+ if (rq->maxsize >= 0 && rq->buflen >= rq->maxsize) {
+ return 0;
+ }
+
+ len = ringqLen(rq);
+
+ if ((newbuf = balloc(B_L, rq->buflen + rq->increment)) == NULL) {
+ return 0;
+ }
+ ringqGetBlk(rq, newbuf, ringqLen(rq));
+ bfree(B_L, (char*) rq->buf);
+
+#ifdef OLD
+ rq->endp = &newbuf[endp];
+ rq->servp = &newbuf[servp];
+ rq->endbuf = &newbuf[rq->buflen];
+ rq->buf = newbuf;
+#endif
+
+ rq->buflen += rq->increment;
+ rq->endp = newbuf;
+ rq->servp = newbuf;
+ rq->buf = newbuf;
+ rq->endbuf = &rq->buf[rq->buflen];
+
+ ringqPutBlk(rq, newbuf, len);
+
+/*
+ * Double the increment so the next grow will line up with balloc'ed memory
+ */
+ rq->increment = getBinBlockSize(2 * rq->increment);
+
+ return 1;
+}
+
+/******************************************************************************/
+/*
+ * Find the smallest binary memory size that "size" will fit into. This
+ * makes the ringq and ringqGrow routines much more efficient. The balloc
+ * routine likes powers of 2 minus 1.
+ */
+
+static int getBinBlockSize(int size)
+{
+ int q;
+
+ size = size >> B_SHIFT;
+ for (q = 0; size; size >>= 1) {
+ q++;
+ }
+ return (1 << (B_SHIFT + q));
+}
+
+/******************************************************************************/
diff --git a/cpukit/httpd/rom.c b/cpukit/httpd/rom.c
new file mode 100644
index 0000000000..f9ff5312ac
--- /dev/null
+++ b/cpukit/httpd/rom.c
@@ -0,0 +1,193 @@
+/*
+ * rom.c -- Support for ROMed page retrieval.
+ *
+ * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for usage and redistribution license requirements
+ *
+ * $Id$
+ */
+
+/******************************** Description *********************************/
+
+/*
+ * This module provides web page retrieval from compiled web pages. Use the
+ * webcomp program to compile web pages and link into the GoAhead WebServer.
+ * This module uses a hashed symbol table for fast page lookup.
+ *
+ * Usage: webcomp -f webPageFileList -p Prefix >webrom.c
+ */
+
+/********************************* Includes ***********************************/
+
+#include <stdlib.h>
+
+#include "wsIntrn.h"
+
+/******************************** Local Data **********************************/
+
+#ifdef WEBS_PAGE_ROM
+
+sym_fd_t romTab; /* Symbol table for web pages */
+
+/*********************************** Code *************************************/
+/*
+ * Open the ROM module
+ */
+
+int websRomOpen()
+{
+ websRomPageIndexType *wip;
+ int nchars;
+ char_t name[SYM_MAX];
+
+ romTab = symOpen(WEBS_SYM_INIT);
+
+ for (wip = websRomPageIndex; wip->path; wip++) {
+ gstrncpy(name, wip->path, SYM_MAX);
+ nchars = gstrlen(name) - 1;
+ if (nchars > 0 &&
+ (name[nchars] == '/' || name[nchars] == '\\')) {
+ name[nchars] = '\0';
+ }
+ symEnter(romTab, name, valueInteger((int) wip), 0);
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Close the ROM module
+ */
+
+void websRomClose()
+{
+ symClose(romTab);
+}
+
+/******************************************************************************/
+/*
+ * Open a web page
+ */
+
+int websRomPageOpen(webs_t wp, char_t *path, int mode, int perm)
+{
+ websRomPageIndexType *wip;
+ sym_t *sp;
+
+ a_assert(websValid(wp));
+ a_assert(path && *path);
+
+ if ((sp = symLookup(romTab, path)) == NULL) {
+ return -1;
+ }
+ wip = (websRomPageIndexType*) sp->content.value.integer;
+ wip->pos = 0;
+ return (wp->docfd = wip - websRomPageIndex);
+}
+
+/******************************************************************************/
+/*
+ * Close a web page
+ */
+
+void websRomPageClose(int fd)
+{
+}
+
+/******************************************************************************/
+/*
+ * Stat a web page
+ */
+
+int websRomPageStat(char_t *path, websStatType *sbuf)
+{
+ websRomPageIndexType *wip;
+ sym_t *sp;
+
+ a_assert(path && *path);
+
+ if ((sp = symLookup(romTab, path)) == NULL) {
+ return -1;
+ }
+ wip = (websRomPageIndexType*) sp->content.value.integer;
+
+ memset(sbuf, 0, sizeof(websStatType));
+ sbuf->size = wip->size;
+ if (wip->page == NULL) {
+ sbuf->isDir = 1;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Read a web page
+ */
+
+int websRomPageReadData(webs_t wp, char *buf, int nBytes)
+{
+ websRomPageIndexType *wip;
+ int len;
+
+ a_assert(websValid(wp));
+ a_assert(buf);
+ a_assert(wp->docfd >= 0);
+
+ wip = &websRomPageIndex[wp->docfd];
+
+ len = min(wip->size - wip->pos, nBytes);
+ memcpy(buf, &wip->page[wip->pos], len);
+ wip->pos += len;
+ return len;
+}
+
+/******************************************************************************/
+/*
+ * Position a web page
+ */
+
+long websRomPageSeek(webs_t wp, long offset, int origin)
+{
+ websRomPageIndexType *wip;
+ long pos;
+
+ a_assert(websValid(wp));
+ a_assert(origin == SEEK_SET || origin == SEEK_CUR || origin == SEEK_END);
+ a_assert(wp->docfd >= 0);
+
+ wip = &websRomPageIndex[wp->docfd];
+
+ if (origin != SEEK_SET && origin != SEEK_CUR && origin != SEEK_END) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (wp->docfd < 0) {
+ errno = EBADF;
+ return -1;
+ }
+
+ pos = offset;
+ switch (origin) {
+ case SEEK_CUR:
+ pos = wip->pos + offset;
+ break;
+ case SEEK_END:
+ pos = wip->size + offset;
+ break;
+ default:
+ break;
+ }
+
+ if (pos < 0) {
+ errno = EBADF;
+ return -1;
+ }
+
+ return (wip->pos = pos);
+}
+
+#endif /* WEBS_PAGE_ROM */
+
+/******************************************************************************/
diff --git a/cpukit/httpd/rtems_webserver.h b/cpukit/httpd/rtems_webserver.h
new file mode 100644
index 0000000000..f62790b601
--- /dev/null
+++ b/cpukit/httpd/rtems_webserver.h
@@ -0,0 +1,6 @@
+/*
+ * rtems_webserver.h --
+ *
+ */
+
+int rtems_initialize_webserver();
diff --git a/cpukit/httpd/security.c b/cpukit/httpd/security.c
new file mode 100644
index 0000000000..9064b5d56f
--- /dev/null
+++ b/cpukit/httpd/security.c
@@ -0,0 +1,235 @@
+/*
+ * security.c -- Security handler
+ *
+ * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for usage and redistribution license requirements
+ *
+ * $Id$
+ */
+
+/******************************** Description *********************************/
+
+/*
+ * This module provides a basic security policy.
+ */
+
+/********************************* Includes ***********************************/
+
+#include "wsIntrn.h"
+#include "um.h"
+#ifdef DIGEST_ACCESS_SUPPORT
+#include "websda.h"
+#endif
+
+/********************************** Defines ***********************************/
+/*
+ * The following #defines change the behaviour of security in the absence
+ * of User Management.
+ * Note that use of User management functions require prior calling of
+ * umInit() to behave correctly
+ */
+
+#ifndef USER_MANAGEMENT_SUPPORT
+#define umGetAccessMethodForURL(url) AM_FULL
+#define umUserExists(userid) 0
+#define umUserCanAccessURL(userid, url) 1
+#define umGetUserPassword(userid) websGetPassword()
+#define umGetAccessLimitSecure(accessLimit) 0
+#define umGetAccessLimit(url) NULL
+#endif
+
+/******************************** Local Data **********************************/
+
+static char_t websPassword[WEBS_MAX_PASS]; /* Access password (decoded) */
+#ifdef _DEBUG
+static int debugSecurity = 1;
+#else
+static int debugSecurity = 0;
+#endif
+
+/*********************************** Code *************************************/
+/*
+ * Determine if this request should be honored
+ */
+
+int websSecurityHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
+ char_t *url, char_t *path, char_t *query)
+{
+ char_t *type, *userid, *password, *accessLimit;
+ int flags, nRet;
+ accessMeth_t am;
+
+ a_assert(websValid(wp));
+ a_assert(url && *url);
+ a_assert(path && *path);
+/*
+ * Get the critical request details
+ */
+ type = websGetRequestType(wp);
+ password = websGetRequestPassword(wp);
+ userid = websGetRequestUserName(wp);
+ flags = websGetRequestFlags(wp);
+/*
+ * Get the access limit for the URL. Exit if none found.
+ */
+ accessLimit = umGetAccessLimit(path);
+ if (accessLimit == NULL) {
+ return 0;
+ }
+
+/*
+ * Check to see if URL must be encrypted
+ */
+#ifdef WEBS_SSL_SUPPORT
+ nRet = umGetAccessLimitSecure(accessLimit);
+ if (nRet && ((flags & WEBS_SECURE) == 0)) {
+ websStats.access++;
+ websError(wp, 405, T("Access Denied\nSecure access is required."));
+ trace(3, T("SEC: Non-secure access attempted on <%s>\n"), path);
+ /* bugfix 5/24/02 -- we were leaking the memory pointed to by
+ * 'accessLimit'. Thanks to Simon Byholm.
+ */
+ bfree(B_L, accessLimit);
+ return 1;
+ }
+#endif
+
+/*
+ * Get the access limit for the URL
+ */
+ am = umGetAccessMethodForURL(accessLimit);
+
+ nRet = 0;
+ if ((flags & WEBS_LOCAL_REQUEST) && (debugSecurity == 0)) {
+/*
+ * Local access is always allowed (defeat when debugging)
+ */
+ } else if (am == AM_NONE) {
+/*
+ * URL is supposed to be hidden! Make like it wasn't found.
+ */
+ websStats.access++;
+ websError(wp, 400, T("Page Not Found"));
+ nRet = 1;
+ } else if (userid && *userid) {
+ if (!umUserExists(userid)) {
+ websStats.access++;
+ websError(wp, 401, T("Access Denied\nUnknown User"));
+ trace(3, T("SEC: Unknown user <%s> attempted to access <%s>\n"),
+ userid, path);
+ nRet = 1;
+ } else if (!umUserCanAccessURL(userid, accessLimit)) {
+ websStats.access++;
+ websError(wp, 403, T("Access Denied\nProhibited User"));
+ nRet = 1;
+ } else if (password && * password) {
+ char_t * userpass = umGetUserPassword(userid);
+ if (userpass) {
+ if (gstrcmp(password, userpass) != 0) {
+ websStats.access++;
+ websError(wp, 401, T("Access Denied\nWrong Password"));
+ trace(3, T("SEC: Password fail for user <%s>")
+ T("attempt to access <%s>\n"), userid, path);
+ nRet = 1;
+ } else {
+/*
+ * User and password check out.
+ */
+ }
+
+ bfree (B_L, userpass);
+ }
+#ifdef DIGEST_ACCESS_SUPPORT
+ } else if (flags & WEBS_AUTH_DIGEST) {
+
+ char_t *digestCalc;
+
+/*
+ * Check digest for equivalence
+ */
+ wp->password = umGetUserPassword(userid);
+
+ a_assert(wp->digest);
+ a_assert(wp->nonce);
+ a_assert(wp->password);
+
+ digestCalc = websCalcDigest(wp);
+ a_assert(digestCalc);
+
+ if (gstrcmp(wp->digest, digestCalc) != 0) {
+ websStats.access++;
+ websError(wp, 405, T("Access Denied\nWrong Password"));
+ nRet = 1;
+ }
+
+ bfree (B_L, digestCalc);
+#endif
+ } else {
+/*
+ * No password has been specified
+ */
+#ifdef DIGEST_ACCESS_SUPPORT
+ if (am == AM_DIGEST) {
+ wp->flags |= WEBS_AUTH_DIGEST;
+ }
+#endif
+ websStats.errors++;
+ websError(wp, 401,
+ T("Access to this document requires a password"));
+ nRet = 1;
+ }
+ } else if (am != AM_FULL) {
+/*
+ * This will cause the browser to display a password / username
+ * dialog
+ */
+#ifdef DIGEST_ACCESS_SUPPORT
+ if (am == AM_DIGEST) {
+ wp->flags |= WEBS_AUTH_DIGEST;
+ }
+#endif
+ websStats.errors++;
+ websError(wp, 401, T("Access to this document requires a User ID"));
+ nRet = 1;
+ }
+
+ bfree(B_L, accessLimit);
+
+ return nRet;
+}
+
+/******************************************************************************/
+/*
+ * Delete the default security handler
+ */
+
+void websSecurityDelete()
+{
+ websUrlHandlerDelete(websSecurityHandler);
+}
+
+/******************************************************************************/
+/*
+ * Store the new password, expect a decoded password. Store in websPassword in
+ * the decoded form.
+ */
+
+void websSetPassword(char_t *password)
+{
+ a_assert(password);
+
+ gstrncpy(websPassword, password, TSZ(websPassword));
+}
+
+/******************************************************************************/
+/*
+ * Get password, return the decoded form
+ */
+
+char_t *websGetPassword()
+{
+ return bstrdup(B_L, websPassword);
+}
+
+/******************************************************************************/
diff --git a/cpukit/httpd/sock.c b/cpukit/httpd/sock.c
new file mode 100644
index 0000000000..fce0b692cb
--- /dev/null
+++ b/cpukit/httpd/sock.c
@@ -0,0 +1,791 @@
+/*
+ * sock.c -- Posix Socket upper layer support module for general posix use
+ *
+ * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
+ *
+ * $Id$
+ */
+
+/******************************** Description *********************************/
+
+/*
+ * Posix Socket Module. This supports blocking and non-blocking buffered
+ * socket I/O.
+ */
+
+/********************************** Includes **********************************/
+
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef UEMF
+ #include "uemf.h"
+#else
+ #include <socket.h>
+ #include <types.h>
+ #include <unistd.h>
+ #include "emfInternal.h"
+#endif
+
+/************************************ Locals **********************************/
+
+socket_t **socketList; /* List of open sockets */
+int socketMax; /* Maximum size of socket */
+int socketHighestFd = -1; /* Highest socket fd opened */
+
+/***************************** Forward Declarations ***************************/
+
+static int socketDoOutput(socket_t *sp, char *buf, int toWrite, int *errCode);
+static int tryAlternateSendTo(int sock, char *buf, int toWrite, int i,
+ struct sockaddr *server);
+
+/*********************************** Code *************************************/
+/*
+ * Write to a socket. Absorb as much data as the socket can buffer. Block if
+ * the socket is in blocking mode. Returns -1 on error, otherwise the number
+ * of bytes written.
+ */
+
+int socketWrite(int sid, char *buf, int bufsize)
+{
+ socket_t *sp;
+ ringq_t *rq;
+ int len, bytesWritten, room;
+
+ a_assert(buf);
+ a_assert(bufsize >= 0);
+
+ if ((sp = socketPtr(sid)) == NULL) {
+ return -1;
+ }
+
+/*
+ * Loop adding as much data to the output ringq as we can absorb. Initiate a
+ * flush when the ringq is too full and continue. Block in socketFlush if the
+ * socket is in blocking mode.
+ */
+ rq = &sp->outBuf;
+ for (bytesWritten = 0; bufsize > 0; ) {
+ if ((room = ringqPutBlkMax(rq)) == 0) {
+ if (socketFlush(sid) < 0) {
+ return -1;
+ }
+ if ((room = ringqPutBlkMax(rq)) == 0) {
+ if (sp->flags & SOCKET_BLOCK) {
+#if (defined (WIN) || defined (CE))
+ int errCode;
+ if (! socketWaitForEvent(sp, FD_WRITE | SOCKET_WRITABLE,
+ &errCode)) {
+ return -1;
+ }
+#endif
+ continue;
+ }
+ break;
+ }
+ continue;
+ }
+ len = min(room, bufsize);
+ ringqPutBlk(rq, (unsigned char *) buf, len);
+ bytesWritten += len;
+ bufsize -= len;
+ buf += len;
+ }
+ return bytesWritten;
+}
+
+/******************************************************************************/
+/*
+ * Write a string to a socket
+ */
+
+int socketWriteString(int sid, char_t *buf)
+{
+ #ifdef UNICODE
+ char *byteBuf;
+ int r, len;
+
+ len = gstrlen(buf);
+ byteBuf = ballocUniToAsc(buf, len);
+ r = socketWrite(sid, byteBuf, len);
+ bfreeSafe(B_L, byteBuf);
+ return r;
+ #else
+ return socketWrite(sid, buf, strlen(buf));
+ #endif /* UNICODE */
+}
+
+/******************************************************************************/
+/*
+ * Read from a socket. Return the number of bytes read if successful. This
+ * may be less than the requested "bufsize" and may be zero. Return -1 for
+ * errors. Return 0 for EOF. Otherwise return the number of bytes read.
+ * If this routine returns zero it indicates an EOF condition.
+ * which can be verified with socketEof()
+
+ * Note: this ignores the line buffer, so a previous socketGets
+ * which read a partial line may cause a subsequent socketRead to miss some
+ * data. This routine may block if the socket is in blocking mode.
+ *
+ */
+
+int socketRead(int sid, char *buf, int bufsize)
+{
+ socket_t *sp;
+ ringq_t *rq;
+ int len, room, errCode, bytesRead;
+
+ a_assert(buf);
+ a_assert(bufsize > 0);
+
+ if ((sp = socketPtr(sid)) == NULL) {
+ return -1;
+ }
+
+ if (sp->flags & SOCKET_EOF) {
+ return 0;
+ }
+
+ rq = &sp->inBuf;
+ for (bytesRead = 0; bufsize > 0; ) {
+ len = min(ringqLen(rq), bufsize);
+ if (len <= 0) {
+/*
+ * if blocking mode and already have data, exit now or it may block
+ * forever.
+ */
+ if ((sp->flags & SOCKET_BLOCK) &&
+ (bytesRead > 0)) {
+ break;
+ }
+/*
+ * This flush is critical for readers of datagram packets. If the
+ * buffer is not big enough to read the whole datagram in one hit,
+ * the recvfrom call will fail.
+ */
+ ringqFlush(rq);
+ room = ringqPutBlkMax(rq);
+ len = socketGetInput(sid, (char *) rq->endp, room, &errCode);
+ if (len < 0) {
+ if (errCode == EWOULDBLOCK) {
+ if ((sp->flags & SOCKET_BLOCK) &&
+ (bytesRead == 0)) {
+ continue;
+ }
+ if (bytesRead >= 0) {
+ return bytesRead;
+ }
+ }
+ return -1;
+
+ } else if (len == 0) {
+/*
+ * If bytesRead is 0, this is EOF since socketRead should never
+ * be called unless there is data yet to be read. Set the flag.
+ * Then pass back the number of bytes read.
+ */
+ if (bytesRead == 0) {
+ sp->flags |= SOCKET_EOF;
+ }
+ return bytesRead;
+ }
+ ringqPutBlkAdj(rq, len);
+ len = min(len, bufsize);
+ }
+ memcpy(&buf[bytesRead], rq->servp, len);
+ ringqGetBlkAdj(rq, len);
+ bufsize -= len;
+ bytesRead += len;
+ }
+ return bytesRead;
+}
+
+/******************************************************************************/
+/*
+ * Get a string from a socket. This returns data in *buf in a malloced string
+ * after trimming the '\n'. If there is zero bytes returned, *buf will be set
+ * to NULL. If doing non-blocking I/O, it returns -1 for error, EOF or when
+ * no complete line yet read. If doing blocking I/O, it will block until an
+ * entire line is read. If a partial line is read socketInputBuffered or
+ * socketEof can be used to distinguish between EOF and partial line still
+ * buffered. This routine eats and ignores carriage returns.
+ */
+
+int socketGets(int sid, char_t **buf)
+{
+ socket_t *sp;
+ ringq_t *lq;
+ char c;
+ int rc, len;
+
+ a_assert(buf);
+ *buf = NULL;
+
+ if ((sp = socketPtr(sid)) == NULL) {
+ return -1;
+ }
+ lq = &sp->lineBuf;
+
+ while (1) {
+
+ if ((rc = socketRead(sid, &c, 1)) < 0) {
+ return rc;
+ }
+
+ if (rc == 0) {
+/*
+ * If there is a partial line and we are at EOF, pretend we saw a '\n'
+ */
+ if (ringqLen(lq) > 0 && (sp->flags & SOCKET_EOF)) {
+ c = '\n';
+ } else {
+ return -1;
+ }
+ }
+/*
+ * If a newline is seen, return the data excluding the new line to the
+ * caller. If carriage return is seen, just eat it.
+ */
+ if (c == '\n') {
+ len = ringqLen(lq);
+ if (len > 0) {
+ *buf = ballocAscToUni((char *)lq->servp, len);
+ } else {
+ *buf = NULL;
+ }
+ ringqFlush(lq);
+ return len;
+
+ } else if (c == '\r') {
+ continue;
+ }
+ ringqPutcA(lq, c);
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Flush the socket. Block if the socket is in blocking mode.
+ * This will return -1 on errors and 0 if successful.
+ */
+
+int socketFlush(int sid)
+{
+ socket_t *sp;
+ ringq_t *rq;
+ int len, bytesWritten, errCode;
+
+ if ((sp = socketPtr(sid)) == NULL) {
+ return -1;
+ }
+ rq = &sp->outBuf;
+
+/*
+ * Set the background flushing flag which socketEventProc will check to
+ * continue the flush.
+ */
+ if (! (sp->flags & SOCKET_BLOCK)) {
+ sp->flags |= SOCKET_FLUSHING;
+ }
+
+/*
+ * Break from loop if not blocking after initiating output. If we are blocking
+ * we wait for a write event.
+ */
+ while (ringqLen(rq) > 0) {
+ len = ringqGetBlkMax(&sp->outBuf);
+ bytesWritten = socketDoOutput(sp, (char*) rq->servp, len, &errCode);
+ if (bytesWritten < 0) {
+ if (errCode == EINTR) {
+ continue;
+ } else if (errCode == EWOULDBLOCK || errCode == EAGAIN) {
+#if (defined (WIN) || defined (CE))
+ if (sp->flags & SOCKET_BLOCK) {
+ int errCode;
+ if (! socketWaitForEvent(sp, FD_WRITE | SOCKET_WRITABLE,
+ &errCode)) {
+ return -1;
+ }
+ continue;
+ }
+#endif
+/*
+ * Ensure we get a FD_WRITE message when the socket can absorb
+ * more data (non-blocking only.) Store the user's mask if we
+ * haven't done it already.
+ */
+ if (sp->saveMask < 0 ) {
+ sp->saveMask = sp->handlerMask;
+ socketRegisterInterest(sp,
+ sp->handlerMask | SOCKET_WRITABLE);
+ }
+ return 0;
+ }
+ return -1;
+ }
+ ringqGetBlkAdj(rq, bytesWritten);
+ }
+/*
+ * If the buffer is empty, reset the ringq pointers to point to the start
+ * of the buffer. This is essential to ensure that datagrams get written
+ * in one single I/O operation.
+ */
+ if (ringqLen(rq) == 0) {
+ ringqFlush(rq);
+ }
+/*
+ * Restore the users mask if it was saved by the non-blocking code above.
+ * Note: saveMask = -1 if empty. socketRegisterInterest will set handlerMask
+ */
+ if (sp->saveMask >= 0) {
+ socketRegisterInterest(sp, sp->saveMask);
+ sp->saveMask = -1;
+ }
+ sp->flags &= ~SOCKET_FLUSHING;
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Return the count of input characters buffered. We look at both the line
+ * buffer and the input (raw) buffer. Return -1 on error or EOF.
+ */
+
+int socketInputBuffered(int sid)
+{
+ socket_t *sp;
+
+ if ((sp = socketPtr(sid)) == NULL) {
+ return -1;
+ }
+ if (socketEof(sid)) {
+ return -1;
+ }
+ return ringqLen(&sp->lineBuf) + ringqLen(&sp->inBuf);
+}
+
+/******************************************************************************/
+/*
+ * Return true if EOF
+ */
+
+int socketEof(int sid)
+{
+ socket_t *sp;
+
+ if ((sp = socketPtr(sid)) == NULL) {
+ return -1;
+ }
+ return sp->flags & SOCKET_EOF;
+}
+
+/******************************************************************************/
+/*
+ * Return the number of bytes the socket can absorb without blocking
+ */
+
+int socketCanWrite(int sid)
+{
+ socket_t *sp;
+
+ if ((sp = socketPtr(sid)) == NULL) {
+ return -1;
+ }
+ return sp->outBuf.buflen - ringqLen(&sp->outBuf) - 1;
+}
+
+/******************************************************************************/
+/*
+ * Add one to allow the user to write exactly SOCKET_BUFSIZ
+ */
+
+void socketSetBufferSize(int sid, int in, int line, int out)
+{
+ socket_t *sp;
+
+ if ((sp = socketPtr(sid)) == NULL) {
+ return;
+ }
+
+ if (in >= 0) {
+ ringqClose(&sp->inBuf);
+ in++;
+ ringqOpen(&sp->inBuf, in, in);
+ }
+
+ if (line >= 0) {
+ ringqClose(&sp->lineBuf);
+ line++;
+ ringqOpen(&sp->lineBuf, line, line);
+ }
+
+ if (out >= 0) {
+ ringqClose(&sp->outBuf);
+ out++;
+ ringqOpen(&sp->outBuf, out, out);
+ }
+}
+
+/******************************************************************************/
+/*
+ * Create a user handler for this socket. The handler called whenever there
+ * is an event of interest as defined by handlerMask (SOCKET_READABLE, ...)
+ */
+
+void socketCreateHandler(int sid, int handlerMask, socketHandler_t handler,
+ int data)
+{
+ socket_t *sp;
+
+ if ((sp = socketPtr(sid)) == NULL) {
+ return;
+ }
+ sp->handler = handler;
+ sp->handler_data = data;
+ socketRegisterInterest(sp, handlerMask);
+}
+
+/******************************************************************************/
+/*
+ * Delete a handler
+ */
+
+void socketDeleteHandler(int sid)
+{
+ socket_t *sp;
+
+ if ((sp = socketPtr(sid)) == NULL) {
+ return;
+ }
+ sp->handler = NULL;
+ socketRegisterInterest(sp, 0);
+}
+
+/******************************************************************************/
+/*
+ * Socket output procedure. Return -1 on errors otherwise return the number
+ * of bytes written.
+ */
+
+static int socketDoOutput(socket_t *sp, char *buf, int toWrite, int *errCode)
+{
+ struct sockaddr_in server;
+ int bytes;
+
+ a_assert(sp);
+ a_assert(buf);
+ a_assert(toWrite > 0);
+ a_assert(errCode);
+
+ *errCode = 0;
+
+#if (defined (WIN) || defined (CE))
+ if ((sp->flags & SOCKET_ASYNC)
+ && ! socketWaitForEvent(sp, FD_CONNECT, errCode)) {
+ return -1;
+ }
+#endif
+
+/*
+ * Write the data
+ */
+ if (sp->flags & SOCKET_BROADCAST) {
+ server.sin_family = AF_INET;
+#if (defined (UEMF) || defined (LITTLEFOOT))
+ server.sin_addr.s_addr = INADDR_BROADCAST;
+#else
+ server.sin_addr.s_addr = inet_addr(basicGetBroadcastAddress());
+#endif
+ server.sin_port = htons((short)(sp->port & 0xFFFF));
+ if ((bytes = sendto(sp->sock, buf, toWrite, 0,
+ (struct sockaddr *) &server, sizeof(server))) < 0) {
+ bytes = tryAlternateSendTo(sp->sock, buf, toWrite, 0,
+ (struct sockaddr *) &server);
+ }
+ } else if (sp->flags & SOCKET_DATAGRAM) {
+ server.sin_family = AF_INET;
+ server.sin_addr.s_addr = inet_addr(sp->host);
+ server.sin_port = htons((short)(sp->port & 0xFFFF));
+ bytes = sendto(sp->sock, buf, toWrite, 0,
+ (struct sockaddr *) &server, sizeof(server));
+
+ } else {
+ bytes = send(sp->sock, buf, toWrite, 0);
+ }
+
+ if (bytes < 0) {
+ *errCode = socketGetError();
+#if (defined (WIN) || defined (CE))
+ sp->currentEvents &= ~FD_WRITE;
+#endif
+
+ return -1;
+
+ } else if (bytes == 0 && bytes != toWrite) {
+ *errCode = EWOULDBLOCK;
+#if (defined (WIN) || defined (CE))
+ sp->currentEvents &= ~FD_WRITE;
+#endif
+ return -1;
+ }
+
+/*
+ * Ensure we get to write some more data real soon if the socket can absorb
+ * more data
+ */
+#ifndef UEMF
+#ifdef WIN
+ if (sp->interestEvents & FD_WRITE) {
+ emfTime_t blockTime = { 0, 0 };
+ emfSetMaxBlockTime(&blockTime);
+ }
+#endif /* WIN */
+#endif
+ return bytes;
+}
+
+/******************************************************************************/
+/*
+ * If the sendto failed, swap the first two bytes in the
+ * sockaddr structure. This is a kludge due to a change in
+ * VxWorks between versions 5.3 and 5.4, but we want the
+ * product to run on either.
+ */
+static int tryAlternateSendTo(int sock, char *buf, int toWrite, int i,
+ struct sockaddr *server)
+{
+#ifdef VXWORKS
+ char *ptr;
+
+ ptr = (char *)server;
+ *ptr = *(ptr+1);
+ *(ptr+1) = 0;
+ return sendto(sock, buf, toWrite, i, server, sizeof(struct sockaddr));
+#else
+ return -1;
+#endif /* VXWORKS */
+}
+
+/******************************************************************************/
+/*
+ * Allocate a new socket structure
+ */
+
+int socketAlloc(char *host, int port, socketAccept_t accept, int flags)
+{
+ socket_t *sp;
+ int sid;
+
+ if ((sid = hAllocEntry((void*) &socketList, &socketMax,
+ sizeof(socket_t))) < 0) {
+ return -1;
+ }
+ sp = socketList[sid];
+
+ sp->sid = sid;
+ sp->accept = accept;
+ sp->port = port;
+ sp->fileHandle = -1;
+ sp->saveMask = -1;
+
+ if (host) {
+ strncpy(sp->host, host, sizeof(sp->host));
+ }
+
+/*
+ * Preserve only specified flags from the callers open
+ */
+ a_assert((flags & ~(SOCKET_BROADCAST|SOCKET_DATAGRAM|SOCKET_BLOCK|
+ SOCKET_LISTENING)) == 0);
+ sp->flags = flags & (SOCKET_BROADCAST | SOCKET_DATAGRAM | SOCKET_BLOCK|
+ SOCKET_LISTENING);
+
+/*
+ * Add one to allow the user to write exactly SOCKET_BUFSIZ
+ */
+ ringqOpen(&sp->inBuf, SOCKET_BUFSIZ, SOCKET_BUFSIZ);
+ ringqOpen(&sp->outBuf, SOCKET_BUFSIZ + 1, SOCKET_BUFSIZ + 1);
+ ringqOpen(&sp->lineBuf, SOCKET_BUFSIZ, -1);
+
+ return sid;
+}
+
+/******************************************************************************/
+/*
+ * Free a socket structure
+ */
+
+void socketFree(int sid)
+{
+ socket_t *sp;
+ char_t buf[256];
+ int i;
+
+ if ((sp = socketPtr(sid)) == NULL) {
+ return;
+ }
+
+/*
+ * To close a socket, remove any registered interests, set it to
+ * non-blocking so that the recv which follows won't block, do a
+ * shutdown on it so peers on the other end will receive a FIN,
+ * then read any data not yet retrieved from the receive buffer,
+ * and finally close it. If these steps are not all performed
+ * RESETs may be sent to the other end causing problems.
+ */
+ socketRegisterInterest(sp, 0);
+ if (sp->sock >= 0) {
+ socketSetBlock(sid, 0);
+ if (shutdown(sp->sock, 1) >= 0) {
+ recv(sp->sock, buf, sizeof(buf), 0);
+ }
+#if (defined (WIN) || defined (CE))
+ closesocket(sp->sock);
+#else
+ close(sp->sock);
+#endif
+ }
+
+ ringqClose(&sp->inBuf);
+ ringqClose(&sp->outBuf);
+ ringqClose(&sp->lineBuf);
+
+ bfree(B_L, sp);
+ socketMax = hFree((void*) &socketList, sid);
+
+/*
+ * Calculate the new highest socket number
+ */
+ socketHighestFd = -1;
+ for (i = 0; i < socketMax; i++) {
+ if ((sp = socketList[i]) == NULL) {
+ continue;
+ }
+ socketHighestFd = max(socketHighestFd, sp->sock);
+ }
+}
+
+/******************************************************************************/
+/*
+ * Validate a socket handle
+ */
+
+socket_t *socketPtr(int sid)
+{
+ if (sid < 0 || sid >= socketMax || socketList[sid] == NULL) {
+ a_assert(NULL);
+ errno = EBADF;
+ return NULL;
+ }
+
+ a_assert(socketList[sid]);
+ return socketList[sid];
+}
+
+/******************************************************************************/
+/*
+ * Get the operating system error code
+ */
+
+int socketGetError()
+{
+#if (defined (WIN) || defined (CE))
+ switch (WSAGetLastError()) {
+ case WSAEWOULDBLOCK:
+ return EWOULDBLOCK;
+ case WSAECONNRESET:
+ return ECONNRESET;
+ case WSAENETDOWN:
+ return ENETDOWN;
+ case WSAEPROCLIM:
+ return EAGAIN;
+ case WSAEINTR:
+ return EINTR;
+ default:
+ return EINVAL;
+ }
+#else
+ return errno;
+#endif
+}
+
+/******************************************************************************/
+/*
+ * Return the underlying socket handle
+ */
+
+int socketGetHandle(int sid)
+{
+ socket_t *sp;
+
+ if ((sp = socketPtr(sid)) == NULL) {
+ return -1;
+ }
+ return sp->sock;
+}
+
+/******************************************************************************/
+/*
+ * Get blocking mode
+ */
+
+int socketGetBlock(int sid)
+{
+ socket_t *sp;
+
+ if ((sp = socketPtr(sid)) == NULL) {
+ a_assert(0);
+ return 0;
+ }
+ return (sp->flags & SOCKET_BLOCK);
+}
+
+/******************************************************************************/
+/*
+ * Get mode
+ */
+
+int socketGetMode(int sid)
+{
+ socket_t *sp;
+
+ if ((sp = socketPtr(sid)) == NULL) {
+ a_assert(0);
+ return 0;
+ }
+ return sp->flags;
+}
+
+/******************************************************************************/
+/*
+ * Set mode
+ */
+
+void socketSetMode(int sid, int mode)
+{
+ socket_t *sp;
+
+ if ((sp = socketPtr(sid)) == NULL) {
+ a_assert(0);
+ return;
+ }
+ sp->flags = mode;
+}
+
+/******************************************************************************/
+/*
+ * Get port.
+ */
+
+int socketGetPort(int sid)
+{
+ socket_t *sp;
+
+ if ((sp = socketPtr(sid)) == NULL) {
+ return -1;
+ }
+ return sp->port;
+}
+
+/******************************************************************************/
diff --git a/cpukit/httpd/sockGen.c b/cpukit/httpd/sockGen.c
new file mode 100644
index 0000000000..822aea6407
--- /dev/null
+++ b/cpukit/httpd/sockGen.c
@@ -0,0 +1,1043 @@
+
+/*
+ * sockGen.c -- Posix Socket support module for general posix use
+ *
+ * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
+ *
+ * $Id$
+ */
+
+/******************************** Description *********************************/
+
+/*
+ * Posix Socket Module. This supports blocking and non-blocking buffered
+ * socket I/O.
+ */
+
+#if (!defined (WIN) || defined (LITTLEFOOT) || defined (WEBS))
+
+/********************************** Includes **********************************/
+
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef UEMF
+ #include "uemf.h"
+#else
+ #include <socket.h>
+ #include <types.h>
+ #include <unistd.h>
+ #include "emfInternal.h"
+#endif
+
+#ifdef VXWORKS
+ #include <hostLib.h>
+#endif
+
+/************************************ Locals **********************************/
+
+extern socket_t **socketList; /* List of open sockets */
+extern int socketMax; /* Maximum size of socket */
+extern int socketHighestFd; /* Highest socket fd opened */
+static int socketOpenCount = 0; /* Number of task using sockets */
+
+/***************************** Forward Declarations ***************************/
+
+static void socketAccept(socket_t *sp);
+static int socketDoEvent(socket_t *sp);
+static int tryAlternateConnect(int sock, struct sockaddr *sockaddr);
+
+/*********************************** Code *************************************/
+/*
+ * Open socket module
+ */
+
+int socketOpen()
+{
+#if (defined (CE) || defined (WIN))
+ WSADATA wsaData;
+#endif
+
+ if (++socketOpenCount > 1) {
+ return 0;
+ }
+
+#if (defined (CE) || defined (WIN))
+ if (WSAStartup(MAKEWORD(1,1), &wsaData) != 0) {
+ return -1;
+ }
+ if (wsaData.wVersion != MAKEWORD(1,1)) {
+ WSACleanup();
+ return -1;
+ }
+#endif
+
+ socketList = NULL;
+ socketMax = 0;
+ socketHighestFd = -1;
+
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Close the socket module, by closing all open connections
+ */
+
+void socketClose()
+{
+ int i;
+
+ if (--socketOpenCount <= 0) {
+ for (i = socketMax; i >= 0; i--) {
+ if (socketList && socketList[i]) {
+ socketCloseConnection(i);
+ }
+ }
+ socketOpenCount = 0;
+ }
+}
+
+/******************************************************************************/
+/*
+ * Open a client or server socket. Host is NULL if we want server capability.
+ */
+
+int socketOpenConnection(char *host, int port, socketAccept_t accept, int flags)
+{
+#if (!defined (NO_GETHOSTBYNAME) && !defined (VXWORKS))
+ struct hostent *hostent; /* Host database entry */
+#endif /* ! (NO_GETHOSTBYNAME || VXWORKS) */
+ socket_t *sp;
+ struct sockaddr_in sockaddr;
+ int sid, bcast, dgram, rc;
+
+ if (port > SOCKET_PORT_MAX) {
+ return -1;
+ }
+/*
+ * Allocate a socket structure
+ */
+ if ((sid = socketAlloc(host, port, accept, flags)) < 0) {
+ return -1;
+ }
+ sp = socketList[sid];
+ a_assert(sp);
+
+/*
+ * Create the socket address structure
+ */
+ memset((char *) &sockaddr, '\0', sizeof(struct sockaddr_in));
+ sockaddr.sin_family = AF_INET;
+ sockaddr.sin_port = htons((short) (port & 0xFFFF));
+
+ if (host == NULL) {
+ sockaddr.sin_addr.s_addr = INADDR_ANY;
+ } else {
+ sockaddr.sin_addr.s_addr = inet_addr(host);
+ if (sockaddr.sin_addr.s_addr == INADDR_NONE) {
+/*
+ * If the OS does not support gethostbyname functionality, the macro:
+ * NO_GETHOSTBYNAME should be defined to skip the use of gethostbyname.
+ * Unfortunatly there is no easy way to recover, the following code
+ * simply uses the basicGetHost IP for the sockaddr.
+ */
+
+#ifdef NO_GETHOSTBYNAME
+ if (strcmp(host, basicGetHost()) == 0) {
+ sockaddr.sin_addr.s_addr = inet_addr(basicGetAddress());
+ }
+ if (sockaddr.sin_addr.s_addr == INADDR_NONE) {
+ socketFree(sid);
+ return -1;
+ }
+#elif (defined (VXWORKS))
+ sockaddr.sin_addr.s_addr = (unsigned long) hostGetByName(host);
+ if (sockaddr.sin_addr.s_addr == NULL) {
+ errno = ENXIO;
+ socketFree(sid);
+ return -1;
+ }
+#else
+ hostent = gethostbyname(host);
+ if (hostent != NULL) {
+ memcpy((char *) &sockaddr.sin_addr,
+ (char *) hostent->h_addr_list[0],
+ (size_t) hostent->h_length);
+ } else {
+ char *asciiAddress;
+ char_t *address;
+
+ address = basicGetAddress();
+ asciiAddress = ballocUniToAsc(address, gstrlen(address));
+ sockaddr.sin_addr.s_addr = inet_addr(asciiAddress);
+ bfree(B_L, asciiAddress);
+ if (sockaddr.sin_addr.s_addr == INADDR_NONE) {
+ errno = ENXIO;
+ socketFree(sid);
+ return -1;
+ }
+ }
+#endif /* (NO_GETHOSTBYNAME || VXWORKS) */
+ }
+ }
+
+ bcast = sp->flags & SOCKET_BROADCAST;
+ if (bcast) {
+ sp->flags |= SOCKET_DATAGRAM;
+ }
+ dgram = sp->flags & SOCKET_DATAGRAM;
+
+/*
+ * Create the socket. Support for datagram sockets. Set the close on
+ * exec flag so children don't inherit the socket.
+ */
+ sp->sock = socket(AF_INET, dgram ? SOCK_DGRAM: SOCK_STREAM, 0);
+ if (sp->sock < 0) {
+ socketFree(sid);
+ return -1;
+ }
+#ifndef __NO_FCNTL
+ fcntl(sp->sock, F_SETFD, FD_CLOEXEC);
+#endif
+ socketHighestFd = max(socketHighestFd, sp->sock);
+
+/*
+ * If broadcast, we need to turn on broadcast capability.
+ */
+ if (bcast) {
+ int broadcastFlag = 1;
+ if (setsockopt(sp->sock, SOL_SOCKET, SO_BROADCAST,
+ (char *) &broadcastFlag, sizeof(broadcastFlag)) < 0) {
+ socketFree(sid);
+ return -1;
+ }
+ }
+
+/*
+ * Host is set if we are the client
+ */
+ if (host) {
+/*
+ * Connect to the remote server in blocking mode, then go into
+ * non-blocking mode if desired.
+ */
+ if (!dgram) {
+ if (! (sp->flags & SOCKET_BLOCK)) {
+/*
+ * sockGen.c is only used for Windows products when blocking
+ * connects are expected. This applies to FieldUpgrader
+ * agents and open source webserver connectws. Therefore the
+ * asynchronous connect code here is not compiled.
+ */
+#if (defined (WIN) || defined (CE)) && (!defined (LITTLEFOOT) && !defined (WEBS))
+ int flag;
+
+ sp->flags |= SOCKET_ASYNC;
+/*
+ * Set to non-blocking for an async connect
+ */
+ flag = 1;
+ if (ioctlsocket(sp->sock, FIONBIO, &flag) == SOCKET_ERROR) {
+ socketFree(sid);
+ return -1;
+ }
+#else
+ socketSetBlock(sid, 1);
+#endif /* #if (WIN || CE) && !(LITTLEFOOT || WEBS) */
+
+ }
+ if ((rc = connect(sp->sock, (struct sockaddr *) &sockaddr,
+ sizeof(sockaddr))) < 0 &&
+ (rc = tryAlternateConnect(sp->sock,
+ (struct sockaddr *) &sockaddr)) < 0) {
+#if (defined (WIN) || defined (CE))
+ if (socketGetError() != EWOULDBLOCK) {
+ socketFree(sid);
+ return -1;
+ }
+#else
+ socketFree(sid);
+ return -1;
+
+#endif /* WIN || CE */
+
+ }
+ }
+ } else {
+/*
+ * Bind to the socket endpoint and the call listen() to start listening
+ */
+ rc = 1;
+ setsockopt(sp->sock, SOL_SOCKET, SO_REUSEADDR, (char *)&rc, sizeof(rc));
+ if (bind(sp->sock, (struct sockaddr *) &sockaddr,
+ sizeof(sockaddr)) < 0) {
+ socketFree(sid);
+ return -1;
+ }
+
+ if (! dgram) {
+ if (listen(sp->sock, SOMAXCONN) < 0) {
+ socketFree(sid);
+ return -1;
+ }
+#ifndef UEMF
+ sp->fileHandle = emfCreateFileHandler(sp->sock, SOCKET_READABLE,
+ (emfFileProc *) socketAccept, (void *) sp);
+#else
+ sp->flags |= SOCKET_LISTENING;
+#endif
+ }
+ sp->handlerMask |= SOCKET_READABLE;
+ }
+
+/*
+ * Set the blocking mode
+ */
+
+ if (flags & SOCKET_BLOCK) {
+ socketSetBlock(sid, 1);
+ } else {
+ socketSetBlock(sid, 0);
+ }
+ return sid;
+}
+
+
+/******************************************************************************/
+/*
+ * If the connection failed, swap the first two bytes in the
+ * sockaddr structure. This is a kludge due to a change in
+ * VxWorks between versions 5.3 and 5.4, but we want the
+ * product to run on either.
+ */
+
+static int tryAlternateConnect(int sock, struct sockaddr *sockaddr)
+{
+#ifdef VXWORKS
+ char *ptr;
+
+ ptr = (char *)sockaddr;
+ *ptr = *(ptr+1);
+ *(ptr+1) = 0;
+ return connect(sock, sockaddr, sizeof(struct sockaddr));
+#else
+ return -1;
+#endif /* VXWORKS */
+}
+
+/******************************************************************************/
+/*
+ * Close a socket
+ */
+
+void socketCloseConnection(int sid)
+{
+ socket_t *sp;
+
+ if ((sp = socketPtr(sid)) == NULL) {
+ return;
+ }
+ socketFree(sid);
+}
+
+/******************************************************************************/
+/*
+ * Accept a connection. Called as a callback on incoming connection.
+ */
+
+static void socketAccept(socket_t *sp)
+{
+ struct sockaddr_in addr;
+ socket_t *nsp;
+ size_t len;
+ char *pString;
+ int newSock, nid;
+
+
+#ifdef NW
+ NETINET_DEFINE_CONTEXT;
+#endif
+
+ a_assert(sp);
+
+/*
+ * Accept the connection and prevent inheriting by children (F_SETFD)
+ */
+ len = sizeof(struct sockaddr_in);
+ if ((newSock = accept(sp->sock, (struct sockaddr *) &addr, (int *) &len)) < 0) {
+ return;
+ }
+#ifndef __NO_FCNTL
+ fcntl(newSock, F_SETFD, FD_CLOEXEC);
+#endif
+ socketHighestFd = max(socketHighestFd, newSock);
+
+/*
+ * Create a socket structure and insert into the socket list
+ */
+ nid = socketAlloc(sp->host, sp->port, sp->accept, sp->flags);
+ nsp = socketList[nid];
+ a_assert(nsp);
+ nsp->sock = newSock;
+ nsp->flags &= ~SOCKET_LISTENING;
+
+ if (nsp == NULL) {
+ return;
+ }
+/*
+ * Set the blocking mode before calling the accept callback.
+ */
+
+ socketSetBlock(nid, (nsp->flags & SOCKET_BLOCK) ? 1: 0);
+/*
+ * Call the user accept callback. The user must call socketCreateHandler
+ * to register for further events of interest.
+ */
+ if (sp->accept != NULL) {
+ pString = inet_ntoa(addr.sin_addr);
+ if ((sp->accept)(nid, pString, ntohs(addr.sin_port), sp->sid) < 0) {
+ socketFree(nid);
+ }
+#ifdef VXWORKS
+ free(pString);
+#endif
+ }
+}
+
+/******************************************************************************/
+/*
+ * Get more input from the socket and return in buf.
+ * Returns 0 for EOF, -1 for errors and otherwise the number of bytes read.
+ */
+
+int socketGetInput(int sid, char *buf, int toRead, int *errCode)
+{
+ struct sockaddr_in server;
+ socket_t *sp;
+ int len, bytesRead;
+
+ a_assert(buf);
+ a_assert(errCode);
+
+ *errCode = 0;
+
+ if ((sp = socketPtr(sid)) == NULL) {
+ return -1;
+ }
+
+/*
+ * If we have previously seen an EOF condition, then just return
+ */
+ if (sp->flags & SOCKET_EOF) {
+ return 0;
+ }
+#if ((defined (WIN) || defined (CE)) && (!defined (LITTLEFOOT) && !defined (WEBS)))
+ if ( !(sp->flags & SOCKET_BLOCK)
+ && ! socketWaitForEvent(sp, FD_CONNECT, errCode)) {
+ return -1;
+ }
+#endif
+
+/*
+ * Read the data
+ */
+ if (sp->flags & SOCKET_DATAGRAM) {
+ len = sizeof(server);
+ bytesRead = recvfrom(sp->sock, buf, toRead, 0,
+ (struct sockaddr *) &server, &len);
+ } else {
+ bytesRead = recv(sp->sock, buf, toRead, 0);
+ }
+
+ /*
+ * BUG 01865 -- CPU utilization hangs on Windows. The original code used
+ * the 'errno' global variable, which is not set by the winsock functions
+ * as it is under *nix platforms. We use the platform independent
+ * socketGetError() function instead, which does handle Windows correctly.
+ * Other, *nix compatible platforms should work as well, since on those
+ * platforms, socketGetError() just returns the value of errno.
+ * Thanks to Jonathan Burgoyne for the fix.
+ */
+ if (bytesRead < 0)
+ {
+ *errCode = socketGetError();
+ if (*errCode == ECONNRESET)
+ {
+ sp->flags |= SOCKET_CONNRESET;
+ return 0;
+ }
+ return -1;
+ }
+ return bytesRead;
+}
+
+/******************************************************************************/
+/*
+ * Process an event on the event queue
+ */
+
+#ifndef UEMF
+
+static int socketEventProc(void *data, int mask)
+{
+ socket_t *sp;
+ ringq_t *rq;
+ int sid;
+
+ sid = (int) data;
+
+ a_assert(sid >= 0 && sid < socketMax);
+ a_assert(socketList[sid]);
+
+ if ((sp = socketPtr(sid)) == NULL) {
+ return 1;
+ }
+
+/*
+ * If now writable and flushing in the background, continue flushing
+ */
+ if (mask & SOCKET_WRITABLE) {
+ if (sp->flags & SOCKET_FLUSHING) {
+ rq = &sp->outBuf;
+ if (ringqLen(rq) > 0) {
+ socketFlush(sp->sid);
+ } else {
+ sp->flags &= ~SOCKET_FLUSHING;
+ }
+ }
+ }
+
+/*
+ * Now invoke the users socket handler. NOTE: the handler may delete the
+ * socket, so we must be very careful after calling the handler.
+ */
+ if (sp->handler && (sp->handlerMask & mask)) {
+ (sp->handler)(sid, mask & sp->handlerMask, sp->handler_data);
+ }
+ if (socketList && sid < socketMax && socketList[sid] == sp) {
+ socketRegisterInterest(sp, sp->handlerMask);
+ }
+ return 1;
+}
+#endif /* ! UEMF */
+
+/******************************************************************************/
+/*
+ * Define the events of interest
+ */
+
+void socketRegisterInterest(socket_t *sp, int handlerMask)
+{
+ a_assert(sp);
+
+ sp->handlerMask = handlerMask;
+#ifndef UEMF
+ if (handlerMask) {
+ sp->fileHandle = emfCreateFileHandler(sp->sock, handlerMask,
+ (emfFileProc *) socketEventProc, (void *) sp->sid);
+ } else {
+ emfDeleteFileHandler(sp->fileHandle);
+ sp->fileHandle = -1;
+ }
+#endif /* ! UEMF */
+}
+
+/******************************************************************************/
+/*
+ * Wait until an event occurs on a socket. Return 1 on success, 0 on failure.
+ * or -1 on exception (UEMF only)
+ */
+
+int socketWaitForEvent(socket_t *sp, int handlerMask, int *errCode)
+{
+ int mask;
+
+ a_assert(sp);
+
+ mask = sp->handlerMask;
+ sp->handlerMask |= handlerMask;
+ while (socketSelect(sp->sid, 1000)) {
+ if (sp->currentEvents & (handlerMask | SOCKET_EXCEPTION)) {
+ break;
+ }
+ }
+ sp->handlerMask = mask;
+ if (sp->currentEvents & SOCKET_EXCEPTION) {
+ return -1;
+ } else if (sp->currentEvents & handlerMask) {
+ return 1;
+ }
+ if (errCode) {
+ *errCode = errno = EWOULDBLOCK;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Return TRUE if there is a socket with an event ready to process,
+ */
+
+int socketReady(int sid)
+{
+ socket_t *sp;
+ int all;
+
+ all = 0;
+ if (sid < 0) {
+ sid = 0;
+ all = 1;
+ }
+
+ for (; sid < socketMax; sid++) {
+ if ((sp = socketList[sid]) == NULL) {
+ if (! all) {
+ break;
+ } else {
+ continue;
+ }
+ }
+ if (sp->flags & SOCKET_CONNRESET) {
+ socketCloseConnection(sid);
+ return 0;
+ }
+ if (sp->currentEvents & sp->handlerMask) {
+ return 1;
+ }
+/*
+ * If there is input data, also call select to test for new events
+ */
+ if (sp->handlerMask & SOCKET_READABLE && socketInputBuffered(sid) > 0) {
+ socketSelect(sid, 0);
+ return 1;
+ }
+ if (! all) {
+ break;
+ }
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Wait for a handle to become readable or writable and return a number of
+ * noticed events. Timeout is in milliseconds.
+ */
+
+#if (defined (WIN) || defined (CE) || defined (NW))
+
+int socketSelect(int sid, int timeout)
+{
+ struct timeval tv;
+ socket_t *sp;
+ fd_set readFds, writeFds, exceptFds;
+ int nEvents;
+ int all, socketHighestFd; /* Highest socket fd opened */
+
+ FD_ZERO(&readFds);
+ FD_ZERO(&writeFds);
+ FD_ZERO(&exceptFds);
+ socketHighestFd = -1;
+
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
+
+/*
+ * Set the select event masks for events to watch
+ */
+ all = nEvents = 0;
+
+ if (sid < 0) {
+ all++;
+ sid = 0;
+ }
+
+ for (; sid < socketMax; sid++) {
+ if ((sp = socketList[sid]) == NULL) {
+ continue;
+ }
+ a_assert(sp);
+/*
+ * Set the appropriate bit in the ready masks for the sp->sock.
+ */
+ if (sp->handlerMask & SOCKET_READABLE) {
+ FD_SET(sp->sock, &readFds);
+ nEvents++;
+ if (socketInputBuffered(sid) > 0) {
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ }
+ }
+ if (sp->handlerMask & SOCKET_WRITABLE) {
+ FD_SET(sp->sock, &writeFds);
+ nEvents++;
+ }
+ if (sp->handlerMask & SOCKET_EXCEPTION) {
+ FD_SET(sp->sock, &exceptFds);
+ nEvents++;
+ }
+ if (! all) {
+ break;
+ }
+ }
+
+/*
+ * Windows select() fails if no descriptors are set, instead of just sleeping
+ * like other, nice select() calls. So, if WIN, sleep.
+ */
+ if (nEvents == 0) {
+ Sleep(timeout);
+ return 0;
+ }
+
+/*
+ * Wait for the event or a timeout.
+ */
+ nEvents = select(socketHighestFd+1, &readFds, &writeFds, &exceptFds, &tv);
+
+ if (all) {
+ sid = 0;
+ }
+ for (; sid < socketMax; sid++) {
+ if ((sp = socketList[sid]) == NULL) {
+ continue;
+ }
+
+ if (FD_ISSET(sp->sock, &readFds) || socketInputBuffered(sid) > 0) {
+ sp->currentEvents |= SOCKET_READABLE;
+ }
+ if (FD_ISSET(sp->sock, &writeFds)) {
+ sp->currentEvents |= SOCKET_WRITABLE;
+ }
+ if (FD_ISSET(sp->sock, &exceptFds)) {
+ sp->currentEvents |= SOCKET_EXCEPTION;
+ }
+ if (! all) {
+ break;
+ }
+ }
+
+ return nEvents;
+}
+
+#else /* not WIN || CE || NW */
+
+int socketSelect(int sid, int timeout)
+{
+ socket_t *sp;
+ struct timeval tv;
+ fd_mask *readFds, *writeFds, *exceptFds;
+ int all, len, nwords, index, bit, nEvents;
+
+/*
+ * Allocate and zero the select masks
+ */
+ nwords = (socketHighestFd + NFDBITS) / NFDBITS;
+ len = nwords * sizeof(int);
+
+ readFds = balloc(B_L, len);
+ memset(readFds, 0, len);
+ writeFds = balloc(B_L, len);
+ memset(writeFds, 0, len);
+ exceptFds = balloc(B_L, len);
+ memset(exceptFds, 0, len);
+
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
+
+/*
+ * Set the select event masks for events to watch
+ */
+ all = nEvents = 0;
+
+ if (sid < 0) {
+ all++;
+ sid = 0;
+ }
+
+ for (; sid < socketMax; sid++) {
+ if ((sp = socketList[sid]) == NULL) {
+ if (all == 0) {
+ break;
+ } else {
+ continue;
+ }
+ }
+ a_assert(sp);
+
+/*
+ * Initialize the ready masks and compute the mask offsets.
+ */
+ index = sp->sock / (NBBY * sizeof(fd_mask));
+ bit = 1 << (sp->sock % (NBBY * sizeof(fd_mask)));
+
+/*
+ * Set the appropriate bit in the ready masks for the sp->sock.
+ */
+ if (sp->handlerMask & SOCKET_READABLE) {
+ readFds[index] |= bit;
+ nEvents++;
+ if (socketInputBuffered(sid) > 0) {
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ }
+ }
+ if (sp->handlerMask & SOCKET_WRITABLE) {
+ writeFds[index] |= bit;
+ nEvents++;
+ }
+ if (sp->handlerMask & SOCKET_EXCEPTION) {
+ exceptFds[index] |= bit;
+ nEvents++;
+ }
+ if (! all) {
+ break;
+ }
+ }
+
+/*
+ * Wait for the event or a timeout. Reset nEvents to be the number of actual
+ * events now.
+ */
+ nEvents = select(socketHighestFd + 1, (fd_set *) readFds,
+ (fd_set *) writeFds, (fd_set *) exceptFds, &tv);
+
+ if (nEvents > 0) {
+ if (all) {
+ sid = 0;
+ }
+ for (; sid < socketMax; sid++) {
+ if ((sp = socketList[sid]) == NULL) {
+ if (all == 0) {
+ break;
+ } else {
+ continue;
+ }
+ }
+
+ index = sp->sock / (NBBY * sizeof(fd_mask));
+ bit = 1 << (sp->sock % (NBBY * sizeof(fd_mask)));
+
+ if (readFds[index] & bit || socketInputBuffered(sid) > 0) {
+ sp->currentEvents |= SOCKET_READABLE;
+ }
+ if (writeFds[index] & bit) {
+ sp->currentEvents |= SOCKET_WRITABLE;
+ }
+ if (exceptFds[index] & bit) {
+ sp->currentEvents |= SOCKET_EXCEPTION;
+ }
+ if (! all) {
+ break;
+ }
+ }
+ }
+
+ bfree(B_L, readFds);
+ bfree(B_L, writeFds);
+ bfree(B_L, exceptFds);
+
+ return nEvents;
+}
+#endif /* WIN || CE */
+
+/******************************************************************************/
+/*
+ * Process socket events
+ */
+
+void socketProcess(int sid)
+{
+ socket_t *sp;
+ int all;
+
+ all = 0;
+ if (sid < 0) {
+ all = 1;
+ sid = 0;
+ }
+/*
+ * Process each socket
+ */
+ for (; sid < socketMax; sid++) {
+ if ((sp = socketList[sid]) == NULL) {
+ if (! all) {
+ break;
+ } else {
+ continue;
+ }
+ }
+ if (socketReady(sid)) {
+ socketDoEvent(sp);
+ }
+ if (! all) {
+ break;
+ }
+ }
+}
+
+/******************************************************************************/
+/*
+ * Process an event on the event queue
+ */
+
+static int socketDoEvent(socket_t *sp)
+{
+ ringq_t *rq;
+ int sid;
+
+ a_assert(sp);
+
+ sid = sp->sid;
+ if (sp->currentEvents & SOCKET_READABLE) {
+ if (sp->flags & SOCKET_LISTENING) {
+ socketAccept(sp);
+ sp->currentEvents = 0;
+ return 1;
+ }
+
+ } else {
+/*
+ * If there is still read data in the buffers, trigger the read handler
+ * NOTE: this may busy spin if the read handler doesn't read the data
+ */
+ if (sp->handlerMask & SOCKET_READABLE && socketInputBuffered(sid) > 0) {
+ sp->currentEvents |= SOCKET_READABLE;
+ }
+ }
+
+
+/*
+ * If now writable and flushing in the background, continue flushing
+ */
+ if (sp->currentEvents & SOCKET_WRITABLE) {
+ if (sp->flags & SOCKET_FLUSHING) {
+ rq = &sp->outBuf;
+ if (ringqLen(rq) > 0) {
+ socketFlush(sp->sid);
+ } else {
+ sp->flags &= ~SOCKET_FLUSHING;
+ }
+ }
+ }
+
+/*
+ * Now invoke the users socket handler. NOTE: the handler may delete the
+ * socket, so we must be very careful after calling the handler.
+ */
+ if (sp->handler && (sp->handlerMask & sp->currentEvents)) {
+ (sp->handler)(sid, sp->handlerMask & sp->currentEvents,
+ sp->handler_data);
+/*
+ * Make sure socket pointer is still valid, then reset the currentEvents.
+ */
+ if (socketList && sid < socketMax && socketList[sid] == sp) {
+ sp->currentEvents = 0;
+ }
+ }
+ return 1;
+}
+
+/******************************************************************************/
+/*
+ * Set the socket blocking mode
+ */
+
+int socketSetBlock(int sid, int on)
+{
+ socket_t *sp;
+ unsigned long flag;
+ int iflag;
+ int oldBlock;
+
+ flag = iflag = !on;
+
+ if ((sp = socketPtr(sid)) == NULL) {
+ a_assert(0);
+ return 0;
+ }
+ oldBlock = (sp->flags & SOCKET_BLOCK);
+ sp->flags &= ~(SOCKET_BLOCK);
+ if (on) {
+ sp->flags |= SOCKET_BLOCK;
+ }
+
+/*
+ * Put the socket into block / non-blocking mode
+ */
+ if (sp->flags & SOCKET_BLOCK) {
+#if (defined (CE) || defined (WIN))
+ ioctlsocket(sp->sock, FIONBIO, &flag);
+#elif (defined (ECOS))
+ int off;
+ off = 0;
+ ioctl(sp->sock, FIONBIO, &off);
+#elif (defined (VXWORKS) || defined (NW))
+ ioctl(sp->sock, FIONBIO, (int)&iflag);
+#else
+ fcntl(sp->sock, F_SETFL, fcntl(sp->sock, F_GETFL) & ~O_NONBLOCK);
+#endif
+
+ } else {
+#if (defined (CE) || defined (WIN))
+ ioctlsocket(sp->sock, FIONBIO, &flag);
+#elif (defined (ECOS))
+ int on;
+ on = 1;
+ ioctl(sp->sock, FIONBIO, &on);
+#elif (defined (VXWORKS) || defined (NW))
+ ioctl(sp->sock, FIONBIO, (int)&iflag);
+#else
+ fcntl(sp->sock, F_SETFL, fcntl(sp->sock, F_GETFL) | O_NONBLOCK);
+#endif
+ }
+ return oldBlock;
+}
+
+/******************************************************************************/
+/*
+ * Return true if a readable socket has buffered data. - not public
+ */
+
+int socketDontBlock()
+{
+ socket_t *sp;
+ int i;
+
+ for (i = 0; i < socketMax; i++) {
+ if ((sp = socketList[i]) == NULL ||
+ (sp->handlerMask & SOCKET_READABLE) == 0) {
+ continue;
+ }
+ if (socketInputBuffered(i) > 0) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Return true if a particular socket buffered data. - not public
+ */
+
+int socketSockBuffered(int sock)
+{
+ socket_t *sp;
+ int i;
+
+ for (i = 0; i < socketMax; i++) {
+ if ((sp = socketList[i]) == NULL || sp->sock != sock) {
+ continue;
+ }
+ return socketInputBuffered(i);
+ }
+ return 0;
+}
+
+#endif /* (!WIN) | LITTLEFOOT | WEBS */
+
+/******************************************************************************/
diff --git a/cpukit/httpd/socket.c b/cpukit/httpd/socket.c
new file mode 100644
index 0000000000..bca64741d5
--- /dev/null
+++ b/cpukit/httpd/socket.c
@@ -0,0 +1,1023 @@
+
+/*
+ * sockGen.c -- Posix Socket support module for general posix use
+ *
+ * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
+ */
+
+/******************************** Description *********************************/
+
+/*
+ * Posix Socket Module. This supports blocking and non-blocking buffered
+ * socket I/O.
+ */
+
+#if (!WIN) || LITTLEFOOT || WEBS
+
+/********************************** Includes **********************************/
+
+#include <string.h>
+#include <stdlib.h>
+
+#if UEMF
+ #include "uemf.h"
+#else
+ #include <socket.h>
+ #include <types.h>
+ #include <unistd.h>
+ #include "emfInternal.h"
+#endif
+
+#if VXWORKS
+ #include <hostLib.h>
+#endif
+
+#if __rtems__
+ #include <sys/select.h>
+#endif
+
+/************************************ Locals **********************************/
+
+extern socket_t **socketList; /* List of open sockets */
+extern int socketMax; /* Maximum size of socket */
+extern int socketHighestFd; /* Highest socket fd opened */
+static int socketOpenCount = 0; /* Number of task using sockets */
+
+/***************************** Forward Declarations ***************************/
+
+static void socketAccept(socket_t *sp);
+static int socketDoEvent(socket_t *sp);
+static int tryAlternateConnect(int sock, struct sockaddr *sockaddr);
+
+/*********************************** Code *************************************/
+/*
+ * Open socket module
+ */
+
+int socketOpen()
+{
+#if CE || WIN
+ WSADATA wsaData;
+#endif
+
+ if (++socketOpenCount > 1) {
+ return 0;
+ }
+
+#if CE || WIN
+ if (WSAStartup(MAKEWORD(1,1), &wsaData) != 0) {
+ return -1;
+ }
+ if (wsaData.wVersion != MAKEWORD(1,1)) {
+ WSACleanup();
+ return -1;
+ }
+#endif
+ socketList = NULL;
+ socketMax = 0;
+ socketHighestFd = -1;
+
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Close the socket module, by closing all open connections
+ */
+
+void socketClose()
+{
+ int i;
+
+ if (--socketOpenCount <= 0) {
+ for (i = socketMax; i >= 0; i--) {
+ if (socketList && socketList[i]) {
+ socketCloseConnection(i);
+ }
+ }
+ socketOpenCount = 0;
+ }
+}
+
+/******************************************************************************/
+/*
+ * Open a client or server socket. Host is NULL if we want server capability.
+ */
+
+int socketOpenConnection(char *host, int port, socketAccept_t accept, int flags)
+{
+#if ! (NO_GETHOSTBYNAME || VXWORKS)
+ struct hostent *hostent; /* Host database entry */
+#endif /* ! (NO_GETHOSTBYNAME || VXWORKS) */
+ socket_t *sp;
+ struct sockaddr_in sockaddr;
+ int sid, bcast, dgram, rc;
+
+ if (port > SOCKET_PORT_MAX) {
+ return -1;
+ }
+/*
+ * Allocate a socket structure
+ */
+ if ((sid = socketAlloc(host, port, accept, flags)) < 0) {
+ return -1;
+ }
+ sp = socketList[sid];
+ a_assert(sp);
+
+/*
+ * Create the socket address structure
+ */
+ memset((char *) &sockaddr, '\0', sizeof(struct sockaddr_in));
+ sockaddr.sin_family = AF_INET;
+ sockaddr.sin_port = htons((short) (port & 0xFFFF));
+
+ if (host == NULL) {
+ sockaddr.sin_addr.s_addr = INADDR_ANY;
+ } else {
+ sockaddr.sin_addr.s_addr = inet_addr(host);
+ if (sockaddr.sin_addr.s_addr == INADDR_NONE) {
+/*
+ * If the OS does not support gethostbyname functionality, the macro:
+ * NO_GETHOSTBYNAME should be defined to skip the use of gethostbyname.
+ * Unfortunatly there is no easy way to recover, the following code
+ * simply uses the basicGetHost IP for the sockaddr.
+ */
+
+#if NO_GETHOSTBYNAME
+ if (strcmp(host, basicGetHost()) == 0) {
+ sockaddr.sin_addr.s_addr = inet_addr(basicGetAddress());
+ }
+ if (sockaddr.sin_addr.s_addr == INADDR_NONE) {
+ socketFree(sid);
+ return -1;
+ }
+#elif VXWORKS
+ sockaddr.sin_addr.s_addr = (unsigned long) hostGetByName(host);
+ if (sockaddr.sin_addr.s_addr == NULL) {
+ errno = ENXIO;
+ socketFree(sid);
+ return -1;
+ }
+#else
+ hostent = gethostbyname(host);
+ if (hostent != NULL) {
+ memcpy((char *) &sockaddr.sin_addr,
+ (char *) hostent->h_addr_list[0],
+ (size_t) hostent->h_length);
+ } else {
+ char *asciiAddress;
+ char_t *address;
+
+ address = basicGetAddress();
+ asciiAddress = ballocUniToAsc(address, gstrlen(address));
+ sockaddr.sin_addr.s_addr = inet_addr(asciiAddress);
+ bfree(B_L, asciiAddress);
+ if (sockaddr.sin_addr.s_addr == INADDR_NONE) {
+ errno = ENXIO;
+ socketFree(sid);
+ return -1;
+ }
+ }
+#endif /* (NO_GETHOSTBYNAME || VXWORKS) */
+ }
+ }
+
+ bcast = sp->flags & SOCKET_BROADCAST;
+ if (bcast) {
+ sp->flags |= SOCKET_DATAGRAM;
+ }
+ dgram = sp->flags & SOCKET_DATAGRAM;
+
+/*
+ * Create the socket. Support for datagram sockets. Set the close on
+ * exec flag so children don't inherit the socket.
+ */
+ sp->sock = socket(AF_INET, dgram ? SOCK_DGRAM: SOCK_STREAM, 0);
+ if (sp->sock < 0) {
+ socketFree(sid);
+ return -1;
+ }
+#ifndef __NO_FCNTL
+ fcntl(sp->sock, F_SETFD, FD_CLOEXEC);
+#endif
+ socketHighestFd = max(socketHighestFd, sp->sock);
+
+/*
+ * If broadcast, we need to turn on broadcast capability.
+ */
+ if (bcast) {
+ int broadcastFlag = 1;
+ if (setsockopt(sp->sock, SOL_SOCKET, SO_BROADCAST,
+ (char *) &broadcastFlag, sizeof(broadcastFlag)) < 0) {
+ socketFree(sid);
+ return -1;
+ }
+ }
+
+/*
+ * Host is set if we are the client
+ */
+ if (host) {
+/*
+ * Connect to the remote server in blocking mode, then go into
+ * non-blocking mode if desired.
+ */
+ if (!dgram) {
+ if (! (sp->flags & SOCKET_BLOCK)) {
+/*
+ * sockGen.c is only used for Windows products when blocking
+ * connects are expected. This applies to FieldUpgrader
+ * agents and open source webserver connectws. Therefore the
+ * asynchronous connect code here is not compiled.
+ */
+#if (WIN || CE) && !(LITTLEFOOT || WEBS)
+ int flag;
+
+ sp->flags |= SOCKET_ASYNC;
+/*
+ * Set to non-blocking for an async connect
+ */
+ flag = 1;
+ if (ioctlsocket(sp->sock, FIONBIO, &flag) == SOCKET_ERROR) {
+ socketFree(sid);
+ return -1;
+ }
+#else
+ socketSetBlock(sid, 1);
+#endif /* #if (WIN || CE) && !(LITTLEFOOT || WEBS) */
+
+ }
+ if ((rc = connect(sp->sock, (struct sockaddr *) &sockaddr,
+ sizeof(sockaddr))) < 0 &&
+ (rc = tryAlternateConnect(sp->sock,
+ (struct sockaddr *) &sockaddr)) < 0) {
+#if WIN || CE
+ if (socketGetError() != EWOULDBLOCK) {
+ socketFree(sid);
+ return -1;
+ }
+#else
+ socketFree(sid);
+ return -1;
+
+#endif /* WIN || CE */
+
+ }
+ }
+ } else {
+/*
+ * Bind to the socket endpoint and the call listen() to start listening
+ */
+ rc = 1;
+ setsockopt(sp->sock, SOL_SOCKET, SO_REUSEADDR, (char *)&rc, sizeof(rc));
+ if (bind(sp->sock, (struct sockaddr *) &sockaddr,
+ sizeof(sockaddr)) < 0) {
+ socketFree(sid);
+ return -1;
+ }
+
+ if (! dgram) {
+ if (listen(sp->sock, SOMAXCONN) < 0) {
+ socketFree(sid);
+ return -1;
+ }
+#if !UEMF
+ sp->fileHandle = emfCreateFileHandler(sp->sock, SOCKET_READABLE,
+ (emfFileProc *) socketAccept, (void *) sp);
+#else
+ sp->flags |= SOCKET_LISTENING;
+#endif
+ }
+ sp->handlerMask |= SOCKET_READABLE;
+ }
+
+/*
+ * Set the blocking mode
+ */
+
+ if (flags & SOCKET_BLOCK) {
+ socketSetBlock(sid, 1);
+ } else {
+ socketSetBlock(sid, 0);
+ }
+ return sid;
+}
+
+/******************************************************************************/
+/*
+ * If the connection failed, swap the first two bytes in the
+ * sockaddr structure. This is a kludge due to a change in
+ * VxWorks between versions 5.3 and 5.4, but we want the
+ * product to run on either.
+ */
+
+static int tryAlternateConnect(int sock, struct sockaddr *sockaddr)
+{
+#if VXWORKS
+ char *ptr;
+
+ ptr = (char *)sockaddr;
+ *ptr = *(ptr+1);
+ *(ptr+1) = 0;
+ return connect(sock, sockaddr, sizeof(struct sockaddr));
+#else
+ return -1;
+#endif /* VXWORKS */
+}
+
+/******************************************************************************/
+/*
+ * Close a socket
+ */
+
+void socketCloseConnection(int sid)
+{
+ socket_t *sp;
+
+ if ((sp = socketPtr(sid)) == NULL) {
+ return;
+ }
+ socketFree(sid);
+}
+
+/******************************************************************************/
+/*
+ * Accept a connection. Called as a callback on incoming connection.
+ */
+
+static void socketAccept(socket_t *sp)
+{
+ union {
+ struct sockaddr addr;
+ struct sockaddr_in addr_in;
+ } overlay;
+ struct sockaddr_in *addr;
+ socket_t *nsp;
+ int len;
+ char *pString;
+ int newSock, nid;
+
+ a_assert(sp);
+ addr = &overlay.addr_in;
+
+/*
+ * Accept the connection and prevent inheriting by children (F_SETFD)
+ */
+ len = sizeof(struct sockaddr_in);
+ if ((newSock = accept(sp->sock, &overlay.addr, &len)) < 0) {
+ return;
+ }
+#ifndef __NO_FCNTL
+ fcntl(newSock, F_SETFD, FD_CLOEXEC);
+#endif
+ socketHighestFd = max(socketHighestFd, newSock);
+
+/*
+ * Create a socket structure and insert into the socket list
+ */
+ nid = socketAlloc(sp->host, sp->port, sp->accept, sp->flags);
+ nsp = socketList[nid];
+ a_assert(nsp);
+ nsp->sock = newSock;
+ nsp->flags &= ~SOCKET_LISTENING;
+
+ if (nsp == NULL) {
+ return;
+ }
+/*
+ * Set the blocking mode before calling the accept callback.
+ */
+
+ socketSetBlock(nid, (nsp->flags & SOCKET_BLOCK) ? 1: 0);
+/*
+ * Call the user accept callback. The user must call socketCreateHandler
+ * to register for further events of interest.
+ */
+ if (sp->accept != NULL) {
+ pString = inet_ntoa(addr->sin_addr);
+ if ((sp->accept)(nid, pString, ntohs(addr->sin_port), sp->sid) < 0) {
+ socketFree(nid);
+ }
+#if VXWORKS
+ free(pString);
+#endif
+ }
+}
+
+/******************************************************************************/
+/*
+ * Get more input from the socket and return in buf.
+ * Returns 0 for EOF, -1 for errors and otherwise the number of bytes read.
+ */
+
+int socketGetInput(int sid, char *buf, int toRead, int *errCode)
+{
+ struct sockaddr_in server;
+ socket_t *sp;
+ int len, bytesRead;
+
+ a_assert(buf);
+ a_assert(errCode);
+
+ *errCode = 0;
+
+ if ((sp = socketPtr(sid)) == NULL) {
+ return -1;
+ }
+
+/*
+ * If we have previously seen an EOF condition, then just return
+ */
+ if (sp->flags & SOCKET_EOF) {
+ return 0;
+ }
+#if (WIN || CE) && !(LITTLEFOOT || WEBS)
+ if ( !(sp->flags & SOCKET_BLOCK)
+ && ! socketWaitForEvent(sp, FD_CONNECT, errCode)) {
+ return -1;
+ }
+#endif
+
+/*
+ * Read the data
+ */
+ if (sp->flags & SOCKET_DATAGRAM) {
+ len = sizeof(server);
+ bytesRead = recvfrom(sp->sock, buf, toRead, 0,
+ (struct sockaddr *) &server, &len);
+ } else {
+ bytesRead = recv(sp->sock, buf, toRead, 0);
+ }
+ if (bytesRead < 0) {
+ if (errno == ECONNRESET) {
+ return 0;
+ }
+ *errCode = socketGetError();
+ return -1;
+ }
+ return bytesRead;
+}
+
+/******************************************************************************/
+/*
+ * Process an event on the event queue
+ */
+
+#ifndef UEMF
+
+static int socketEventProc(void *data, int mask)
+{
+ socket_t *sp;
+ ringq_t *rq;
+ int sid;
+
+ sid = (int) data;
+
+ a_assert(sid >= 0 && sid < socketMax);
+ a_assert(socketList[sid]);
+
+ if ((sp = socketPtr(sid)) == NULL) {
+ return 1;
+ }
+
+/*
+ * If now writable and flushing in the background, continue flushing
+ */
+ if (mask & SOCKET_WRITABLE) {
+ if (sp->flags & SOCKET_FLUSHING) {
+ rq = &sp->outBuf;
+ if (ringqLen(rq) > 0) {
+ socketFlush(sp->sid);
+ } else {
+ sp->flags &= ~SOCKET_FLUSHING;
+ }
+ }
+ }
+
+/*
+ * Now invoke the users socket handler. NOTE: the handler may delete the
+ * socket, so we must be very careful after calling the handler.
+ */
+ if (sp->handler && (sp->handlerMask & mask)) {
+ (sp->handler)(sid, mask & sp->handlerMask, sp->handler_data);
+ }
+ if (socketList && sid < socketMax && socketList[sid] == sp) {
+ socketRegisterInterest(sp, sp->handlerMask);
+ }
+ return 1;
+}
+#endif /* ! UEMF */
+
+/******************************************************************************/
+/*
+ * Define the events of interest
+ */
+
+void socketRegisterInterest(socket_t *sp, int handlerMask)
+{
+ a_assert(sp);
+
+ sp->handlerMask = handlerMask;
+#if !UEMF
+ if (handlerMask) {
+ sp->fileHandle = emfCreateFileHandler(sp->sock, handlerMask,
+ (emfFileProc *) socketEventProc, (void *) sp->sid);
+ } else {
+ emfDeleteFileHandler(sp->fileHandle);
+ }
+#endif /* ! UEMF */
+}
+
+/******************************************************************************/
+/*
+ * Wait until an event occurs on a socket. Return 1 on success, 0 on failure.
+ * or -1 on exception (UEMF only)
+ */
+
+int socketWaitForEvent(socket_t *sp, int handlerMask, int *errCode)
+{
+ int mask;
+
+ a_assert(sp);
+
+ mask = sp->handlerMask;
+ sp->handlerMask |= handlerMask;
+ while (socketSelect(sp->sid, 1000)) {
+ if (sp->currentEvents & (handlerMask | SOCKET_EXCEPTION)) {
+ break;
+ }
+ }
+ sp->handlerMask = mask;
+ if (sp->currentEvents & SOCKET_EXCEPTION) {
+ return -1;
+ } else if (sp->currentEvents & handlerMask) {
+ return 1;
+ }
+ if (errCode) {
+ *errCode = errno = EWOULDBLOCK;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Return TRUE if there is a socket with an event ready to process,
+ */
+
+int socketReady(int sid)
+{
+ socket_t *sp;
+ int all;
+
+ all = 0;
+ if (sid < 0) {
+ sid = 0;
+ all = 1;
+ }
+
+ for (; sid < socketMax; sid++) {
+ if ((sp = socketList[sid]) == NULL) {
+ if (! all) {
+ break;
+ } else {
+ continue;
+ }
+ }
+ if (sp->currentEvents & sp->handlerMask) {
+ return 1;
+ }
+/*
+ * If there is input data, also call select to test for new events
+ */
+ if (sp->handlerMask & SOCKET_READABLE && socketInputBuffered(sid)) {
+ socketSelect(sid, 0);
+ return 1;
+ }
+ if (! all) {
+ break;
+ }
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Wait for a handle to become readable or writable and return a number of
+ * noticed events. Timeout is in milliseconds.
+ */
+
+#if WIN || CE
+
+int socketSelect(int sid, int timeout)
+{
+ struct timeval tv;
+ socket_t *sp;
+ fd_set readFds, writeFds, exceptFds;
+ int nEvents;
+ int all, socketHighestFd; /* Highest socket fd opened */
+
+ FD_ZERO(&readFds);
+ FD_ZERO(&writeFds);
+ FD_ZERO(&exceptFds);
+ socketHighestFd = -1;
+
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
+
+/*
+ * Set the select event masks for events to watch
+ */
+ all = nEvents = 0;
+
+ if (sid < 0) {
+ all++;
+ sid = 0;
+ }
+
+ for (; sid < socketMax; sid++) {
+ if ((sp = socketList[sid]) == NULL) {
+ continue;
+ }
+ a_assert(sp);
+/*
+ * Set the appropriate bit in the ready masks for the sp->sock.
+ */
+ if (sp->handlerMask & SOCKET_READABLE) {
+ FD_SET(sp->sock, &readFds);
+ nEvents++;
+ if (socketInputBuffered(sid) > 0) {
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ }
+ }
+ if (sp->handlerMask & SOCKET_WRITABLE) {
+ FD_SET(sp->sock, &writeFds);
+ nEvents++;
+ }
+ if (sp->handlerMask & SOCKET_EXCEPTION) {
+ FD_SET(sp->sock, &exceptFds);
+ nEvents++;
+ }
+ if (! all) {
+ break;
+ }
+ }
+
+/*
+ * Windows select() fails if no descriptors are set, instead of just sleeping
+ * like other, nice select() calls. So, if WIN, sleep.
+ */
+ if (nEvents == 0) {
+ Sleep(timeout);
+ return 0;
+ }
+
+/*
+ * Wait for the event or a timeout.
+ */
+ nEvents = select(socketHighestFd+1, &readFds, &writeFds, &exceptFds, &tv);
+
+ if (all) {
+ sid = 0;
+ }
+ for (; sid < socketMax; sid++) {
+ if ((sp = socketList[sid]) == NULL) {
+ continue;
+ }
+
+ if (FD_ISSET(sp->sock, &readFds) || socketInputBuffered(sid) > 0) {
+ sp->currentEvents |= SOCKET_READABLE;
+ }
+ if (FD_ISSET(sp->sock, &writeFds)) {
+ sp->currentEvents |= SOCKET_WRITABLE;
+ }
+ if (FD_ISSET(sp->sock, &exceptFds)) {
+ sp->currentEvents |= SOCKET_EXCEPTION;
+ }
+ if (! all) {
+ break;
+ }
+ }
+
+ return nEvents;
+}
+
+#else /* not WIN || CE */
+
+int socketSelect(int sid, int timeout)
+{
+ socket_t *sp;
+ struct timeval tv;
+ fd_mask *readFds, *writeFds, *exceptFds;
+ int all, len, nwords, index, bit, nEvents;
+
+/*
+ * Allocate and zero the select masks
+ */
+ nwords = (socketHighestFd + NFDBITS) / NFDBITS;
+ len = nwords * sizeof(int);
+
+ readFds = balloc(B_L, len);
+ memset(readFds, 0, len);
+ writeFds = balloc(B_L, len);
+ memset(writeFds, 0, len);
+ exceptFds = balloc(B_L, len);
+ memset(exceptFds, 0, len);
+
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
+
+/*
+ * Set the select event masks for events to watch
+ */
+ all = nEvents = 0;
+
+ if (sid < 0) {
+ all++;
+ sid = 0;
+ }
+
+ for (; sid < socketMax; sid++) {
+ if ((sp = socketList[sid]) == NULL) {
+ if (all == 0) {
+ break;
+ } else {
+ continue;
+ }
+ }
+ a_assert(sp);
+
+/*
+ * Initialize the ready masks and compute the mask offsets.
+ */
+ index = sp->sock / (NBBY * sizeof(fd_mask));
+ bit = 1 << (sp->sock % (NBBY * sizeof(fd_mask)));
+
+/*
+ * Set the appropriate bit in the ready masks for the sp->sock.
+ */
+ if (sp->handlerMask & SOCKET_READABLE) {
+ readFds[index] |= bit;
+ nEvents++;
+ if (socketInputBuffered(sid) > 0) {
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ }
+ }
+ if (sp->handlerMask & SOCKET_WRITABLE) {
+ writeFds[index] |= bit;
+ nEvents++;
+ }
+ if (sp->handlerMask & SOCKET_EXCEPTION) {
+ exceptFds[index] |= bit;
+ nEvents++;
+ }
+ if (! all) {
+ break;
+ }
+ }
+
+/*
+ * Wait for the event or a timeout. Reset nEvents to be the number of actual
+ * events now.
+ */
+ nEvents = select(socketHighestFd + 1, (fd_set *) readFds,
+ (fd_set *) writeFds, (fd_set *) exceptFds, &tv);
+
+ if (nEvents > 0) {
+ if (all) {
+ sid = 0;
+ }
+ for (; sid < socketMax; sid++) {
+ if ((sp = socketList[sid]) == NULL) {
+ if (all == 0) {
+ break;
+ } else {
+ continue;
+ }
+ }
+
+ index = sp->sock / (NBBY * sizeof(fd_mask));
+ bit = 1 << (sp->sock % (NBBY * sizeof(fd_mask)));
+
+ if (readFds[index] & bit || socketInputBuffered(sid) > 0) {
+ sp->currentEvents |= SOCKET_READABLE;
+ }
+ if (writeFds[index] & bit) {
+ sp->currentEvents |= SOCKET_WRITABLE;
+ }
+ if (exceptFds[index] & bit) {
+ sp->currentEvents |= SOCKET_EXCEPTION;
+ }
+ if (! all) {
+ break;
+ }
+ }
+ }
+
+ bfree(B_L, readFds);
+ bfree(B_L, writeFds);
+ bfree(B_L, exceptFds);
+
+ return nEvents;
+}
+#endif /* WIN || CE */
+
+/******************************************************************************/
+/*
+ * Process socket events
+ */
+
+void socketProcess(int sid)
+{
+ socket_t *sp;
+ int all;
+
+ all = 0;
+ if (sid < 0) {
+ all = 1;
+ sid = 0;
+ }
+/*
+ * Process each socket
+ */
+ for (; sid < socketMax; sid++) {
+ if ((sp = socketList[sid]) == NULL) {
+ if (! all) {
+ break;
+ } else {
+ continue;
+ }
+ }
+ if (socketReady(sid)) {
+ socketDoEvent(sp);
+ }
+ if (! all) {
+ break;
+ }
+ }
+}
+
+/******************************************************************************/
+/*
+ * Process an event on the event queue
+ */
+
+static int socketDoEvent(socket_t *sp)
+{
+ ringq_t *rq;
+ int sid;
+
+ a_assert(sp);
+
+ sid = sp->sid;
+ if (sp->currentEvents & SOCKET_READABLE) {
+ if (sp->flags & SOCKET_LISTENING) {
+ socketAccept(sp);
+ sp->currentEvents = 0;
+ return 1;
+ }
+
+ } else {
+/*
+ * If there is still read data in the buffers, trigger the read handler
+ * NOTE: this may busy spin if the read handler doesn't read the data
+ */
+ if (sp->handlerMask & SOCKET_READABLE && socketInputBuffered(sid)) {
+ sp->currentEvents |= SOCKET_READABLE;
+ }
+ }
+
+
+/*
+ * If now writable and flushing in the background, continue flushing
+ */
+ if (sp->currentEvents & SOCKET_WRITABLE) {
+ if (sp->flags & SOCKET_FLUSHING) {
+ rq = &sp->outBuf;
+ if (ringqLen(rq) > 0) {
+ socketFlush(sp->sid);
+ } else {
+ sp->flags &= ~SOCKET_FLUSHING;
+ }
+ }
+ }
+
+/*
+ * Now invoke the users socket handler. NOTE: the handler may delete the
+ * socket, so we must be very careful after calling the handler.
+ */
+ if (sp->handler && (sp->handlerMask & sp->currentEvents)) {
+ (sp->handler)(sid, sp->handlerMask & sp->currentEvents,
+ sp->handler_data);
+/*
+ * Make sure socket pointer is still valid, then reset the currentEvents.
+ */
+ if (socketList && sid < socketMax && socketList[sid] == sp) {
+ sp->currentEvents = 0;
+ }
+ }
+ return 1;
+}
+
+/******************************************************************************/
+/*
+ * Set the socket blocking mode
+ */
+
+int socketSetBlock(int sid, int on)
+{
+ socket_t *sp;
+ unsigned long flag;
+ int iflag;
+ int oldBlock;
+
+ flag = iflag = !on;
+
+ if ((sp = socketPtr(sid)) == NULL) {
+ a_assert(0);
+ return 0;
+ }
+ oldBlock = (sp->flags & SOCKET_BLOCK);
+ sp->flags &= ~(SOCKET_BLOCK);
+ if (on) {
+ sp->flags |= SOCKET_BLOCK;
+ }
+
+/*
+ * Put the socket into block / non-blocking mode
+ */
+ if (sp->flags & SOCKET_BLOCK) {
+#if CE || WIN
+ ioctlsocket(sp->sock, FIONBIO, &flag);
+#elif ECOS
+ int off;
+ off = 0;
+ ioctl(sp->sock, FIONBIO, &off);
+#elif VXWORKS
+ ioctl(sp->sock, FIONBIO, (int)&iflag);
+#else
+ fcntl(sp->sock, F_SETFL, fcntl(sp->sock, F_GETFL) & ~O_NONBLOCK);
+#endif
+
+ } else {
+#if CE || WIN
+ ioctlsocket(sp->sock, FIONBIO, &flag);
+#elif ECOS
+ int on;
+ on = 1;
+ ioctl(sp->sock, FIONBIO, &on);
+#elif VXWORKS
+ ioctl(sp->sock, FIONBIO, (int)&iflag);
+#else
+ fcntl(sp->sock, F_SETFL, fcntl(sp->sock, F_GETFL) | O_NONBLOCK);
+#endif
+ }
+ return oldBlock;
+}
+
+/******************************************************************************/
+/*
+ * Return true if a readable socket has buffered data. - not public
+ */
+
+int socketDontBlock()
+{
+ socket_t *sp;
+ int i;
+
+ for (i = 0; i < socketMax; i++) {
+ if ((sp = socketList[i]) == NULL ||
+ (sp->handlerMask & SOCKET_READABLE) == 0) {
+ continue;
+ }
+ if (socketInputBuffered(i) > 0) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Return true if a particular socket buffered data. - not public
+ */
+
+int socketSockBuffered(int sock)
+{
+ socket_t *sp;
+ int i;
+
+ for (i = 0; i < socketMax; i++) {
+ if ((sp = socketList[i]) == NULL || sp->sock != sock) {
+ continue;
+ }
+ return socketInputBuffered(i);
+ }
+ return 0;
+}
+
+#endif /* (!WIN) | LITTLEFOOT | WEBS */
+
+/******************************************************************************/
diff --git a/cpukit/httpd/sym.c b/cpukit/httpd/sym.c
new file mode 100644
index 0000000000..3df45e86d7
--- /dev/null
+++ b/cpukit/httpd/sym.c
@@ -0,0 +1,474 @@
+/*
+ * sym.c -- Symbol Table module
+ *
+ * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for usage and redistribution license requirements
+ *
+ * $Id$
+ */
+
+/******************************** Description *********************************/
+/*
+ * This module implements a highly efficient generic symbol table with
+ * update and access routines. Symbols are simple character strings and
+ * the values they take can be flexible types as defined by value_t.
+ * This modules allows multiple symbol tables to be created.
+ */
+
+/********************************* Includes ***********************************/
+
+#ifdef UEMF
+ #include "uemf.h"
+#else
+ #include "basic/basicInternal.h"
+#endif
+
+/********************************* Defines ************************************/
+
+typedef struct { /* Symbol table descriptor */
+ int inuse; /* Is this entry in use */
+ int hash_size; /* Size of the table below */
+ sym_t **hash_table; /* Allocated at run time */
+} sym_tabent_t;
+
+/********************************* Globals ************************************/
+
+static sym_tabent_t **sym; /* List of symbol tables */
+static int symMax; /* One past the max symbol table */
+static int symOpenCount = 0; /* Count of apps using sym */
+
+static int htIndex; /* Current location in table */
+static sym_t* next; /* Next symbol in iteration */
+
+/**************************** Forward Declarations ****************************/
+
+static int hashIndex(sym_tabent_t *tp, char_t *name);
+static sym_t *hash(sym_tabent_t *tp, char_t *name);
+static int calcPrime(int size);
+
+/*********************************** Code *************************************/
+/*
+ * Open the symbol table subSystem.
+ */
+
+int symSubOpen()
+{
+ if (++symOpenCount == 1) {
+ symMax = 0;
+ sym = NULL;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Close the symbol table subSystem.
+ */
+
+void symSubClose()
+{
+ if (--symOpenCount <= 0) {
+ symOpenCount = 0;
+ }
+}
+
+/******************************************************************************/
+/*
+ * Create a symbol table.
+ */
+
+sym_fd_t symOpen(int hash_size)
+{
+ sym_fd_t sd;
+ sym_tabent_t *tp;
+
+ a_assert(hash_size > 2);
+
+/*
+ * Create a new handle for this symbol table
+ */
+ if ((sd = hAlloc((void*) &sym)) < 0) {
+ return -1;
+ }
+
+/*
+ * Create a new symbol table structure and zero
+ */
+ if ((tp = (sym_tabent_t*) balloc(B_L, sizeof(sym_tabent_t))) == NULL) {
+ symMax = hFree((void*) &sym, sd);
+ return -1;
+ }
+ memset(tp, 0, sizeof(sym_tabent_t));
+ if (sd >= symMax) {
+ symMax = sd + 1;
+ }
+ a_assert(0 <= sd && sd < symMax);
+ sym[sd] = tp;
+
+/*
+ * Now create the hash table for fast indexing.
+ */
+ tp->hash_size = calcPrime(hash_size);
+ tp->hash_table = (sym_t**) balloc(B_L, tp->hash_size * sizeof(sym_t*));
+ a_assert(tp->hash_table);
+ memset(tp->hash_table, 0, tp->hash_size * sizeof(sym_t*));
+
+ return sd;
+}
+
+/******************************************************************************/
+/*
+ * Close this symbol table. Call a cleanup function to allow the caller
+ * to free resources associated with each symbol table entry.
+ */
+
+void symClose(sym_fd_t sd)
+{
+ sym_tabent_t *tp;
+ sym_t *sp, *forw;
+ int i;
+
+ a_assert(0 <= sd && sd < symMax);
+ tp = sym[sd];
+ a_assert(tp);
+
+/*
+ * Free all symbols in the hash table, then the hash table itself.
+ */
+ for (i = 0; i < tp->hash_size; i++) {
+ for (sp = tp->hash_table[i]; sp; sp = forw) {
+ forw = sp->forw;
+ valueFree(&sp->name);
+ valueFree(&sp->content);
+ bfree(B_L, (void*) sp);
+ sp = forw;
+ }
+ }
+ bfree(B_L, (void*) tp->hash_table);
+
+ symMax = hFree((void*) &sym, sd);
+ bfree(B_L, (void*) tp);
+}
+
+/******************************************************************************/
+/*
+ * Return the first symbol in the hashtable if there is one. This call is used
+ * as the first step in traversing the table. A call to symFirst should be
+ * followed by calls to symNext to get all the rest of the entries.
+ */
+
+sym_t* symFirst(sym_fd_t sd)
+{
+ sym_tabent_t *tp;
+ sym_t *sp, *forw;
+ int i;
+
+ a_assert(0 <= sd && sd < symMax);
+ tp = sym[sd];
+ a_assert(tp);
+
+/*
+ * Find the first symbol in the hashtable and return a pointer to it.
+ */
+ for (i = 0; i < tp->hash_size; i++) {
+ for (sp = tp->hash_table[i]; sp; sp = forw) {
+ forw = sp->forw;
+
+ if (forw == NULL) {
+ htIndex = i + 1;
+ next = tp->hash_table[htIndex];
+ } else {
+ htIndex = i;
+ next = forw;
+ }
+ return sp;
+ }
+ }
+ return NULL;
+}
+
+/******************************************************************************/
+/*
+ * Return the next symbol in the hashtable if there is one. See symFirst.
+ */
+
+sym_t* symNext(sym_fd_t sd)
+{
+ sym_tabent_t *tp;
+ sym_t *sp, *forw;
+ int i;
+
+ a_assert(0 <= sd && sd < symMax);
+ tp = sym[sd];
+ a_assert(tp);
+
+/*
+ * Find the first symbol in the hashtable and return a pointer to it.
+ */
+ for (i = htIndex; i < tp->hash_size; i++) {
+ for (sp = next; sp; sp = forw) {
+ forw = sp->forw;
+
+ if (forw == NULL) {
+ htIndex = i + 1;
+ next = tp->hash_table[htIndex];
+ } else {
+ htIndex = i;
+ next = forw;
+ }
+ return sp;
+ }
+ next = tp->hash_table[i + 1];
+ }
+ return NULL;
+}
+
+/******************************************************************************/
+/*
+ * Lookup a symbol and return a pointer to the symbol entry. If not present
+ * then return a NULL.
+ */
+
+sym_t *symLookup(sym_fd_t sd, char_t *name)
+{
+ sym_tabent_t *tp;
+ sym_t *sp;
+ char_t *cp;
+
+ a_assert(0 <= sd && sd < symMax);
+ if ((tp = sym[sd]) == NULL) {
+ return NULL;
+ }
+
+ if (name == NULL || *name == '\0') {
+ return NULL;
+ }
+
+/*
+ * Do an initial hash and then follow the link chain to find the right entry
+ */
+ for (sp = hash(tp, name); sp; sp = sp->forw) {
+ cp = sp->name.value.string;
+ if (cp[0] == name[0] && gstrcmp(cp, name) == 0) {
+ break;
+ }
+ }
+ return sp;
+}
+
+/******************************************************************************/
+/*
+ * Enter a symbol into the table. If already there, update its value.
+ * Always succeeds if memory available. We allocate a copy of "name" here
+ * so it can be a volatile variable. The value "v" is just a copy of the
+ * passed in value, so it MUST be persistent.
+ */
+
+sym_t *symEnter(sym_fd_t sd, char_t *name, value_t v, int arg)
+{
+ sym_tabent_t *tp;
+ sym_t *sp, *last;
+ char_t *cp;
+ int hindex;
+
+ a_assert(name);
+ a_assert(0 <= sd && sd < symMax);
+ tp = sym[sd];
+ a_assert(tp);
+
+/*
+ * Calculate the first daisy-chain from the hash table. If non-zero, then
+ * we have daisy-chain, so scan it and look for the symbol.
+ */
+ last = NULL;
+ hindex = hashIndex(tp, name);
+ if ((sp = tp->hash_table[hindex]) != NULL) {
+ for (; sp; sp = sp->forw) {
+ cp = sp->name.value.string;
+ if (cp[0] == name[0] && gstrcmp(cp, name) == 0) {
+ break;
+ }
+ last = sp;
+ }
+ if (sp) {
+/*
+ * Found, so update the value
+ * If the caller stores handles which require freeing, they
+ * will be lost here. It is the callers responsibility to free
+ * resources before overwriting existing contents. We will here
+ * free allocated strings which occur due to value_instring().
+ * We should consider providing the cleanup function on the open rather
+ * than the close and then we could call it here and solve the problem.
+ */
+ if (sp->content.valid) {
+ valueFree(&sp->content);
+ }
+ sp->content = v;
+ sp->arg = arg;
+ return sp;
+ }
+/*
+ * Not found so allocate and append to the daisy-chain
+ */
+ sp = (sym_t*) balloc(B_L, sizeof(sym_t));
+ if (sp == NULL) {
+ return NULL;
+ }
+ sp->name = valueString(name, VALUE_ALLOCATE);
+ sp->content = v;
+ sp->forw = (sym_t*) NULL;
+ sp->arg = arg;
+ last->forw = sp;
+
+ } else {
+/*
+ * Daisy chain is empty so we need to start the chain
+ */
+ sp = (sym_t*) balloc(B_L, sizeof(sym_t));
+ if (sp == NULL) {
+ return NULL;
+ }
+ tp->hash_table[hindex] = sp;
+ tp->hash_table[hashIndex(tp, name)] = sp;
+
+ sp->forw = (sym_t*) NULL;
+ sp->content = v;
+ sp->arg = arg;
+ sp->name = valueString(name, VALUE_ALLOCATE);
+ }
+ return sp;
+}
+
+/******************************************************************************/
+/*
+ * Delete a symbol from a table
+ */
+
+int symDelete(sym_fd_t sd, char_t *name)
+{
+ sym_tabent_t *tp;
+ sym_t *sp, *last;
+ char_t *cp;
+ int hindex;
+
+ a_assert(name && *name);
+ a_assert(0 <= sd && sd < symMax);
+ tp = sym[sd];
+ a_assert(tp);
+
+/*
+ * Calculate the first daisy-chain from the hash table. If non-zero, then
+ * we have daisy-chain, so scan it and look for the symbol.
+ */
+ last = NULL;
+ hindex = hashIndex(tp, name);
+ if ((sp = tp->hash_table[hindex]) != NULL) {
+ for ( ; sp; sp = sp->forw) {
+ cp = sp->name.value.string;
+ if (cp[0] == name[0] && gstrcmp(cp, name) == 0) {
+ break;
+ }
+ last = sp;
+ }
+ }
+ if (sp == (sym_t*) NULL) { /* Not Found */
+ return -1;
+ }
+
+/*
+ * Unlink and free the symbol. Last will be set if the element to be deleted
+ * is not first in the chain.
+ */
+ if (last) {
+ last->forw = sp->forw;
+ } else {
+ tp->hash_table[hindex] = sp->forw;
+ }
+ valueFree(&sp->name);
+ valueFree(&sp->content);
+ bfree(B_L, (void*) sp);
+
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Hash a symbol and return a pointer to the hash daisy-chain list
+ * All symbols reside on the chain (ie. none stored in the hash table itself)
+ */
+
+static sym_t *hash(sym_tabent_t *tp, char_t *name)
+{
+ a_assert(tp);
+
+ return tp->hash_table[hashIndex(tp, name)];
+}
+
+/******************************************************************************/
+/*
+ * Compute the hash function and return an index into the hash table
+ * We use a basic additive function that is then made modulo the size of the
+ * table.
+ */
+
+static int hashIndex(sym_tabent_t *tp, char_t *name)
+{
+ unsigned int sum;
+ int i;
+
+ a_assert(tp);
+/*
+ * Add in each character shifted up progressively by 7 bits. The shift
+ * amount is rounded so as to not shift too far. It thus cycles with each
+ * new cycle placing character shifted up by one bit.
+ */
+ i = 0;
+ sum = 0;
+ while (*name) {
+ sum += (((int) *name++) << i);
+ i = (i + 7) % (BITS(int) - BITSPERBYTE);
+ }
+ return sum % tp->hash_size;
+}
+
+/******************************************************************************/
+/*
+ * Check if this number is a prime
+ */
+
+static int isPrime(int n)
+{
+ int i, max;
+
+ a_assert(n > 0);
+
+ max = n / 2;
+ for (i = 2; i <= max; i++) {
+ if (n % i == 0) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/******************************************************************************/
+/*
+ * Calculate the largest prime smaller than size.
+ */
+
+static int calcPrime(int size)
+{
+ int count;
+
+ a_assert(size > 0);
+
+ for (count = size; count > 0; count--) {
+ if (isPrime(count)) {
+ return count;
+ }
+ }
+ return 1;
+}
+
+/******************************************************************************/
diff --git a/cpukit/httpd/uemf.c b/cpukit/httpd/uemf.c
new file mode 100644
index 0000000000..ffe6a04cd1
--- /dev/null
+++ b/cpukit/httpd/uemf.c
@@ -0,0 +1,293 @@
+/*
+ * uemf.c -- GoAhead Micro Embedded Management Framework
+ *
+ * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for usage and redistribution license requirements
+ *
+ * $Id$
+ */
+
+/********************************** Description *******************************/
+
+/*
+ * This module provides compatibility with the full GoAhead EMF.
+ * It is a collection of routines which permits the GoAhead WebServer to
+ * run stand-alone and to also load as a solution pack under the GoAhead EMF.
+ */
+
+/*********************************** Includes *********************************/
+
+#include "uemf.h"
+
+/********************************** Local Data ********************************/
+
+int emfInst; /* Application instance handle */
+
+/****************************** Forward Declarations **************************/
+
+extern void defaultErrorHandler(int etype, char_t *buf);
+static void (*errorHandler)(int etype, char_t *msg) = defaultErrorHandler;
+
+extern void defaultTraceHandler(int level, char_t *buf);
+static void (*traceHandler)(int level, char_t *buf) = defaultTraceHandler;
+
+/************************************* Code ***********************************/
+/*
+ * Error message that doesn't need user attention. Customize this code
+ * to direct error messages to wherever the developer wishes
+ */
+
+void error(E_ARGS_DEC, int etype, char_t *fmt, ...)
+{
+ va_list args;
+ char_t *fmtBuf, *buf;
+
+ va_start(args, fmt);
+ fmtValloc(&fmtBuf, E_MAX_ERROR, fmt, args);
+
+ if (etype == E_LOG) {
+ fmtAlloc(&buf, E_MAX_ERROR, T("%s\n"), fmtBuf);
+/*#ifdef DEV*/
+ } else if (etype == E_ASSERT) {
+ fmtAlloc(&buf, E_MAX_ERROR,
+ T("Assertion %s, failed at %s %d\n"), fmtBuf, E_ARGS);
+/*#endif*/
+ } else if (etype == E_USER) {
+ fmtAlloc(&buf, E_MAX_ERROR, T("%s\n"), fmtBuf);
+ }
+ /*
+ * bugfix -- if etype is not E_LOG, E_ASSERT, or E_USER, the call to
+ * bfreeSafe(B_L, buf) below will fail, because 'buf' is randomly
+ * initialized. To be nice, we format a message saying that this is an
+ * unknown message type, and in doing so give buf a valid value. Thanks
+ * to Simon Byholm.
+ */
+ else {
+ fmtAlloc(&buf, E_MAX_ERROR, T("Unknown error"));
+ }
+ va_end(args);
+
+ bfree(B_L, fmtBuf);
+
+ if (errorHandler) {
+ errorHandler(etype, buf);
+ }
+
+ bfreeSafe(B_L, buf);
+}
+
+/******************************************************************************/
+/*
+ * Replace the default error handler. Return pointer to old error handler.
+ */
+
+void (*errorSetHandler(void (*function)(int etype, char_t *msg))) \
+ (int etype, char_t *msg)
+{
+ void (*oldHandler)(int etype, char_t *buf);
+
+ oldHandler = errorHandler;
+ errorHandler = function;
+ return oldHandler;
+}
+
+/******************************************************************************/
+/*
+ * Trace log. Customize this function to log trace output
+ */
+
+void trace(int level, char_t *fmt, ...)
+{
+ va_list args;
+ char_t *buf;
+
+ va_start(args, fmt);
+ fmtValloc(&buf, VALUE_MAX_STRING, fmt, args);
+
+ if (traceHandler) {
+ traceHandler(level, buf);
+ }
+ bfreeSafe(B_L, buf);
+ va_end(args);
+}
+
+/******************************************************************************/
+/*
+ * Trace log. Customize this function to log trace output
+ */
+
+void traceRaw(char_t *buf)
+{
+ if (traceHandler) {
+ traceHandler(0, buf);
+ }
+}
+
+/******************************************************************************/
+/*
+ * Replace the default trace handler. Return a pointer to the old handler.
+ */
+
+void (*traceSetHandler(void (*function)(int level, char_t *buf)))
+ (int level, char *buf)
+{
+ void (*oldHandler)(int level, char_t *buf);
+
+ oldHandler = traceHandler;
+ if (function) {
+ traceHandler = function;
+ }
+ return oldHandler;
+}
+
+/******************************************************************************/
+/*
+ * Save the instance handle
+ */
+
+void emfInstSet(int inst)
+{
+ emfInst = inst;
+}
+
+/******************************************************************************/
+/*
+ * Get the instance handle
+ */
+
+int emfInstGet()
+{
+ return emfInst;
+}
+
+/******************************************************************************/
+/*
+ * Convert a string to lower case
+ */
+
+char_t *strlower(char_t *string)
+{
+ char_t *s;
+
+ a_assert(string);
+
+ if (string == NULL) {
+ return NULL;
+ }
+
+ s = string;
+ while (*s) {
+ if (gisupper(*s)) {
+ *s = (char_t) gtolower(*s);
+ }
+ s++;
+ }
+ *s = '\0';
+ return string;
+}
+
+/******************************************************************************/
+/*
+ * Convert a string to upper case
+ */
+
+char_t *strupper(char_t *string)
+{
+ char_t *s;
+
+ a_assert(string);
+ if (string == NULL) {
+ return NULL;
+ }
+
+ s = string;
+ while (*s) {
+ if (gislower(*s)) {
+ *s = (char_t) gtoupper(*s);
+ }
+ s++;
+ }
+ *s = '\0';
+ return string;
+}
+
+/******************************************************************************/
+/*
+ * Convert integer to ascii string. Allow a NULL string in which case we
+ * allocate a dynamic buffer.
+ */
+
+char_t *stritoa(int n, char_t *string, int width)
+{
+ char_t *cp, *lim, *s;
+ char_t buf[16]; /* Just temp to hold number */
+ int next, minus;
+
+ a_assert(string && width > 0);
+
+ if (string == NULL) {
+ if (width == 0) {
+ width = 10;
+ }
+ if ((string = balloc(B_L, width + 1)) == NULL) {
+ return NULL;
+ }
+ }
+ if (n < 0) {
+ minus = 1;
+ n = -n;
+ width--;
+ } else {
+ minus = 0;
+ }
+
+ cp = buf;
+ lim = &buf[width - 1];
+ while (n > 9 && cp < lim) {
+ next = n;
+ n /= 10;
+ *cp++ = (char_t) (next - n * 10 + '0');
+ }
+ if (cp < lim) {
+ *cp++ = (char_t) (n + '0');
+ }
+
+ s = string;
+ if (minus) {
+ *s++ = '-';
+ }
+
+ while (cp > buf) {
+ *s++ = *--cp;
+ }
+
+ *s++ = '\0';
+ return string;
+}
+
+/******************************************************************************/
+/*
+ * Stubs
+ */
+
+char_t *basicGetProduct()
+{
+ return T("uemf");
+}
+
+char_t *basicGetAddress()
+{
+ return T("localhost");
+}
+
+int errorOpen(char_t *pname)
+{
+ return 0;
+}
+
+void errorClose()
+{
+}
+
+/******************************************************************************/
diff --git a/cpukit/httpd/uemf.h b/cpukit/httpd/uemf.h
new file mode 100644
index 0000000000..19eb9f559d
--- /dev/null
+++ b/cpukit/httpd/uemf.h
@@ -0,0 +1,1110 @@
+/*
+ * uemf.h -- GoAhead Micro Embedded Management Framework Header
+ *
+ * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for usage and redistribution license requirements
+ *
+ * $Id$
+ */
+
+#ifndef _h_UEMF
+#define _h_UEMF 1
+
+/******************************** Description *********************************/
+
+/*
+ * GoAhead Web Server header. This defines the Web public APIs
+ */
+
+/******************************* Per O/S Includes *****************************/
+
+#ifdef WIN
+ #include <direct.h>
+ #include <io.h>
+ #include <sys/stat.h>
+ #include <limits.h>
+ #include <tchar.h>
+ #include <windows.h>
+ #include <winnls.h>
+ #include <time.h>
+ #include <sys/types.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <fcntl.h>
+ #include <errno.h>
+#endif /* WIN */
+
+#ifdef CE
+ #include <errno.h>
+ #include <limits.h>
+ #include <tchar.h>
+ #include <windows.h>
+ #include <winsock.h>
+ #include <winnls.h>
+ #include "CE/wincompat.h"
+ #include <winsock.h>
+#endif /* CE */
+
+#ifdef NW
+ #include <direct.h>
+ #include <io.h>
+ #include <sys/stat.h>
+ #include <time.h>
+ #include <sys/types.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <fcntl.h>
+ #include <errno.h>
+ #include <niterror.h>
+ #define EINTR EINUSE
+ #define WEBS 1
+ #include <limits.h>
+ #include <netdb.h>
+ #include <process.h>
+ #include <tiuser.h>
+ #include <sys/time.h>
+ #include <arpa/inet.h>
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <sys/filio.h>
+ #include <netinet/in.h>
+#endif /* NW */
+
+#ifdef SCOV5
+ #include <sys/types.h>
+ #include <stdio.h>
+ #include "sys/socket.h"
+ #include "sys/select.h"
+ #include "netinet/in.h"
+ #include "arpa/inet.h"
+ #include "netdb.h"
+#endif /* SCOV5 */
+
+#ifdef UNIX
+ #include <stdio.h>
+#endif /* UNIX */
+
+#if LINUX || __rtems__
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <sys/param.h>
+ #include <limits.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <sys/socket.h>
+ #include <sys/select.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+ #include <netdb.h>
+ #include <time.h>
+ #include <fcntl.h>
+ #include <errno.h>
+#endif /* LINUX */
+
+#ifdef LYNX
+ #include <limits.h>
+ #include <stdarg.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <socket.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+ #include <netdb.h>
+ #include <time.h>
+ #include <fcntl.h>
+ #include <errno.h>
+#endif /* LYNX */
+
+#ifdef MACOSX
+ #include <sys/stat.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+ #include <netdb.h>
+ #include <fcntl.h>
+ #include <errno.h>
+#endif /* MACOSX */
+
+#ifdef UW
+ #include <stdio.h>
+#endif /* UW */
+
+#ifdef VXWORKS
+ #include <vxWorks.h>
+ #include <sockLib.h>
+ #include <selectLib.h>
+ #include <inetLib.h>
+ #include <ioLib.h>
+ #include <stdio.h>
+ #include <stat.h>
+ #include <time.h>
+ #include <usrLib.h>
+ #include <fcntl.h>
+ #include <errno.h>
+#endif /* VXWORKS */
+
+#ifdef SOLARIS
+ #include <sys/types.h>
+ #include <limits.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <socket.h>
+ #include <sys/select.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+ #include <netdb.h>
+ #include <time.h>
+ #include <fcntl.h>
+ #include <errno.h>
+#endif /* SOLARIS */
+
+#ifdef QNX4
+ #include <sys/types.h>
+ #include <stdio.h>
+ #include <sys/socket.h>
+ #include <sys/select.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+ #include <netdb.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <sys/uio.h>
+ #include <sys/wait.h>
+#endif /* QNX4 */
+
+#ifdef ECOS
+ #include <limits.h>
+ #include <cyg/infra/cyg_type.h>
+ #include <cyg/kernel/kapi.h>
+ #include <time.h>
+ #include <network.h>
+ #include <errno.h>
+#endif /* ECOS */
+
+/********************************** Includes **********************************/
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <string.h>
+
+#ifndef WEBS
+#include "messages.h"
+#endif /* ! WEBS */
+
+/******************************* Per O/S Defines *****************************/
+
+#if defined(__rtems__)
+#define __NO_PACK 1
+#endif
+
+#ifdef UW
+ #define __NO_PACK 1
+#endif /* UW */
+
+#if (defined (SCOV5) || defined (VXWORKS) || defined (LINUX) || defined (LYNX) || defined (MACOSX) || defined (__rtems__))
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif /* O_BINARY */
+#define SOCKET_ERROR -1
+#endif /* SCOV5 || VXWORKS || LINUX || LYNX || MACOSX */
+
+#if (defined (WIN) || defined (CE))
+/*
+ * __NO_FCNTL means can't access fcntl function. Fcntl.h is still available.
+ */
+#define __NO_FCNTL 1
+
+#undef R_OK
+#define R_OK 4
+#undef W_OK
+#define W_OK 2
+#undef X_OK
+#define X_OK 1
+#undef F_OK
+#define F_OK 0
+#endif /* WIN || CE */
+
+#if (defined (LINUX) && !defined(__rtems__) && !defined (_STRUCT_TIMEVAL))
+struct timeval
+{
+ time_t tv_sec; /* Seconds. */
+ time_t tv_usec; /* Microseconds. */
+};
+#define _STRUCT_TIMEVAL 1
+#endif /* LINUX && ! _STRUCT_TIMEVAL */
+
+#ifdef ECOS
+ #define O_RDONLY 1
+ #define O_BINARY 2
+
+ #define __NO_PACK 1
+ #define __NO_EJ_FILE 1
+ #define __NO_CGI_BIN 1
+ #define __NO_FCNTL 1
+
+/*
+ * #define LIBKERN_INLINE to avoid kernel inline functions
+ */
+ #define LIBKERN_INLINE
+
+#endif /* ECOS */
+
+#ifdef QNX4
+ typedef long fd_mask;
+ #define NFDBITS (sizeof (fd_mask) * NBBY) /* bits per mask */
+#endif /* QNX4 */
+
+#ifdef NW
+ #define fd_mask fd_set
+ #define INADDR_NONE -1l
+ #define Sleep delay
+
+ #define __NO_FCNTL 1
+
+ #undef R_OK
+ #define R_OK 4
+ #undef W_OK
+ #define W_OK 2
+ #undef X_OK
+ #define X_OK 1
+ #undef F_OK
+ #define F_OK 0
+#endif /* NW */
+
+/********************************** Unicode ***********************************/
+/*
+ * Constants and limits. Also FNAMESIZE and PATHSIZE are currently defined
+ * in param.h to be 128 and 512
+ */
+#define TRACE_MAX (4096 - 48)
+#define VALUE_MAX_STRING (4096 - 48)
+#define SYM_MAX (512)
+#define XML_MAX 4096 /* Maximum size for tags/tokens */
+#define BUF_MAX 4096 /* General sanity check for bufs */
+#define FMT_STATIC_MAX 256 /* Maximum for fmtStatic calls */
+
+#if (defined (LITTLEFOOT) || defined (WEBS))
+#define LF_BUF_MAX (510)
+#define LF_PATHSIZE LF_BUF_MAX
+#else
+#define LF_BUF_MAX BUF_MAX
+#define LF_PATHSIZE PATHSIZE
+#define UPPATHSIZE PATHSIZE
+#endif /* LITTLEFOOT || WEBS */
+
+#ifndef CHAR_T_DEFINED
+#define CHAR_T_DEFINED 1
+#ifdef UNICODE
+/*
+ * To convert strings to UNICODE. We have a level of indirection so things
+ * like T(__FILE__) will expand properly.
+ */
+#define T(x) __TXT(x)
+#define __TXT(s) L ## s
+typedef unsigned short char_t;
+typedef unsigned short uchar_t;
+
+/*
+ * Text size of buffer macro. A buffer bytes will hold (size / char size)
+ * characters.
+ */
+#define TSZ(x) (sizeof(x) / sizeof(char_t))
+
+/*
+ * How many ASCII bytes are required to represent this UNICODE string?
+ */
+#define TASTRL(x) ((wcslen(x) + 1) * sizeof(char_t))
+
+#else
+#define T(s) s
+typedef char char_t;
+#define TSZ(x) (sizeof(x))
+#define TASTRL(x) (strlen(x) + 1)
+#ifdef WIN
+typedef unsigned char uchar_t;
+#endif /* WIN */
+
+#endif /* UNICODE */
+
+#endif /* ! CHAR_T_DEFINED */
+
+/*
+ * "Boolean" constants
+ */
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+/*
+ * GoAhead Copyright.
+ */
+#define GOAHEAD_COPYRIGHT \
+ T("Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.")
+
+/*
+ * The following include has to be after the unicode defines. By putting it
+ * here, many modules in various parts of the tree are cleaner.
+ */
+#if (defined (LITTLEFOOT) && defined (INMEM))
+ #include "lf/inmem.h"
+#endif /* LITTLEFOOT && INMEM */
+
+/*
+ * Type for unicode systems
+ */
+#ifdef UNICODE
+
+#define gmain wmain
+
+#define gasctime _wasctime
+#define gsprintf swprintf
+#define gprintf wprintf
+#define gfprintf fwprintf
+#define gsscanf swscanf
+#define gvsprintf vswprintf
+
+#define gstrcpy wcscpy
+#define gstrncpy wcsncpy
+#define gstrncat wcsncat
+#define gstrlen wcslen
+#define gstrcat wcscat
+#define gstrcmp wcscmp
+#define gstrncmp wcsncmp
+#define gstricmp wcsicmp
+#define gstrchr wcschr
+#define gstrrchr wcsrchr
+#define gstrtok wcstok
+#define gstrnset wcsnset
+#define gstrrchr wcsrchr
+#define gstrstr wcsstr
+#define gstrtol wcstol
+
+#define gfopen _wfopen
+#define gopen _wopen
+#define gclose close
+#define gcreat _wcreat
+#define gfgets fgetws
+#define gfputs fputws
+#define gfscanf fwscanf
+#define ggets _getws
+#define glseek lseek
+#define gunlink _wunlink
+#define gread read
+#define grename _wrename
+#define gwrite write
+#define gtmpnam _wtmpnam
+#define gtempnam _wtempnam
+#define gfindfirst _wfindfirst
+#define gfinddata_t _wfinddata_t
+#define gfindnext _wfindnext
+#define gfindclose _findclose
+#define gstat _wstat
+#define gaccess _waccess
+#define gchmod _wchmod
+
+typedef struct _stat gstat_t;
+
+#define gmkdir _wmkdir
+#define gchdir _wchdir
+#define grmdir _wrmdir
+#define ggetcwd _wgetcwd
+
+#define gtolower towlower
+#define gtoupper towupper
+#ifdef CE
+#define gisspace isspace
+#define gisdigit isdigit
+#define gisxdigit isxdigit
+#define gisupper isupper
+#define gislower islower
+#define gisprint isprint
+#else
+#define gremove _wremove
+#define gisspace iswspace
+#define gisdigit iswdigit
+#define gisxdigit iswxdigit
+#define gisupper iswupper
+#define gislower iswlower
+#endif /* if CE */
+#define gisalnum iswalnum
+#define gisalpha iswalpha
+#define gatoi(s) wcstol(s, NULL, 10)
+
+#define gctime _wctime
+#define ggetenv _wgetenv
+#define gexecvp _wexecvp
+
+#else /* ! UNICODE */
+
+#ifndef gopen
+#if INMEM
+#define gchdir imChdir
+#define gmkdir imMkdir
+#define grmdir imRmdir
+#define gclose imClose
+#define gclosedir imClosedir
+#define gchmod imChmod
+#define ggetcwd imGetcwd
+#define glseek imLseek
+#define gloadModule imLoadModule
+#define gopen imOpen
+#define gopendir imOpendir
+#define gread imRead
+#define greaddir imReaddir
+#define grename imRename
+#define gstat imStat
+#define gunlink imUnlink
+#define gwrite imWrite
+#else
+#if VXWORKS
+#define gchdir vxchdir
+#define gmkdir vxmkdir
+#define grmdir vxrmdir
+#elif (defined (LYNX) || defined (LINUX) || defined (MACOSX) || defined (SOLARIS))
+#define gchdir chdir
+#define gmkdir(s) mkdir(s,0755)
+#define grmdir rmdir
+#else
+#define gchdir chdir
+#define gmkdir mkdir
+#define grmdir rmdir
+#endif /* VXWORKS #elif LYNX || LINUX || MACOSX || SOLARIS*/
+#define gclose close
+#define gclosedir closedir
+#define gchmod chmod
+#define ggetcwd getcwd
+#define glseek lseek
+#define gloadModule loadModule
+#define gopen open
+#define gopendir opendir
+#define gread read
+#define greaddir readdir
+#define grename rename
+#define gstat stat
+#define gunlink unlink
+#define gwrite write
+#endif /* INMEM */
+#endif /* ! gopen */
+
+#define gasctime asctime
+#define gsprintf sprintf
+#define gprintf printf
+#define gfprintf fprintf
+#define gsscanf sscanf
+#define gvsprintf vsprintf
+
+#define gstrcpy strcpy
+#define gstrncpy strncpy
+#define gstrncat strncat
+#define gstrlen strlen
+#define gstrcat strcat
+#define gstrcmp strcmp
+#define gstrncmp strncmp
+#define gstricmp strcmpci
+#define gstrchr strchr
+#define gstrrchr strrchr
+#define gstrtok strtok
+#define gstrnset strnset
+#define gstrrchr strrchr
+#define gstrstr strstr
+#define gstrtol strtol
+
+#define gfopen fopen
+#define gcreat creat
+#define gfgets fgets
+#define gfputs fputs
+#define gfscanf fscanf
+#define ggets gets
+#define gtmpnam tmpnam
+#define gtempnam tempnam
+#define gfindfirst _findfirst
+#define gfinddata_t _finddata_t
+#define gfindnext _findnext
+#define gfindclose _findclose
+#define gaccess access
+
+typedef struct stat gstat_t;
+
+#define gremove remove
+
+#define gtolower tolower
+#define gtoupper toupper
+#define gisspace isspace
+#define gisdigit isdigit
+#define gisxdigit isxdigit
+#define gisalnum isalnum
+#define gisalpha isalpha
+#define gisupper isupper
+#define gislower islower
+#define gatoi atoi
+
+#define gctime ctime
+#define ggetenv getenv
+#define gexecvp execvp
+#ifndef VXWORKS
+#define gmain main
+#endif /* ! VXWORKS */
+#ifdef VXWORKS
+#define fcntl(a, b, c)
+#endif /* VXWORKS */
+#endif /* ! UNICODE */
+
+/*
+ * Include inmem.h here because it redefines many of the file access fucntions.
+ * Otherwise there would be lots more #if-#elif-#else-#endif ugliness.
+ */
+#ifdef INMEM
+ #include "lf/inmem.h"
+#endif
+
+/********************************** Defines ***********************************/
+
+#ifndef FNAMESIZE
+#define FNAMESIZE 254 /* Max length of file names */
+#endif /* FNAMESIZE */
+
+#define E_MAX_ERROR 4096
+#define URL_MAX 4096
+
+/*
+ * Error types
+ */
+#define E_ASSERT 0x1 /* Assertion error */
+#define E_LOG 0x2 /* Log error to log file */
+#define E_USER 0x3 /* Error that must be displayed */
+
+#define E_L T(__FILE__), __LINE__
+#define E_ARGS_DEC char_t *file, int line
+#define E_ARGS file, line
+
+#if (defined (ASSERT) || defined (ASSERT_CE))
+ #define a_assert(C) if (C) ; else error(E_L, E_ASSERT, T("%s"), T(#C))
+#else
+ #define a_assert(C) if (1) ; else
+#endif /* ASSERT || ASSERT_CE */
+
+/******************************************************************************/
+/* VALUE */
+/******************************************************************************/
+/*
+ * These values are not prefixed so as to aid code readability
+ */
+
+typedef enum {
+ undefined = 0,
+ byteint = 1,
+ shortint = 2,
+ integer = 3,
+ hex = 4,
+ percent = 5,
+ octal = 6,
+ big = 7,
+ flag = 8,
+ floating = 9,
+ string = 10,
+ bytes = 11,
+ symbol = 12,
+ errmsg = 13
+} vtype_t;
+
+#ifndef __NO_PACK
+#pragma pack(2)
+#endif /* _NO_PACK */
+
+typedef struct {
+
+ union {
+ char flag;
+ char byteint;
+ short shortint;
+ char percent;
+ long integer;
+ long hex;
+ long octal;
+ long big[2];
+#ifdef FLOATING_POINT_SUPPORT
+ double floating;
+#endif /* FLOATING_POINT_SUPPORT */
+ char_t *string;
+ char *bytes;
+ char_t *errmsg;
+ void *symbol;
+ } value;
+
+ vtype_t type;
+ unsigned int valid : 8;
+ unsigned int allocated : 8; /* String was balloced */
+} value_t;
+
+#ifndef __NO_PACK
+#pragma pack()
+#endif /* __NO_PACK */
+
+/*
+ * Allocation flags
+ */
+#define VALUE_ALLOCATE 0x1
+
+#define value_numeric(t) (t >= byteint && t <= big)
+#define value_str(t) (t >= string && t <= bytes)
+#define value_ok(t) (t > undefined && t <= symbol)
+
+#define VALUE_VALID { {0}, integer, 1 }
+#define VALUE_INVALID { {0}, undefined, 0 }
+
+/******************************************************************************/
+/*
+ * A ring queue allows maximum utilization of memory for data storage and is
+ * ideal for input/output buffering. This module provides a highly effecient
+ * implementation and a vehicle for dynamic strings.
+ *
+ * WARNING: This is a public implementation and callers have full access to
+ * the queue structure and pointers. Change this module very carefully.
+ *
+ * This module follows the open/close model.
+ *
+ * Operation of a ringq where rq is a pointer to a ringq :
+ *
+ * rq->buflen contains the size of the buffer.
+ * rq->buf will point to the start of the buffer.
+ * rq->servp will point to the first (un-consumed) data byte.
+ * rq->endp will point to the next free location to which new data is added
+ * rq->endbuf will point to one past the end of the buffer.
+ *
+ * Eg. If the ringq contains the data "abcdef", it might look like :
+ *
+ * +-------------------------------------------------------------------+
+ * | | | | | | | | a | b | c | d | e | f | | | | |
+ * +-------------------------------------------------------------------+
+ * ^ ^ ^ ^
+ * | | | |
+ * rq->buf rq->servp rq->endp rq->enduf
+ *
+ * The queue is empty when servp == endp. This means that the queue will hold
+ * at most rq->buflen -1 bytes. It is the fillers responsibility to ensure
+ * the ringq is never filled such that servp == endp.
+ *
+ * It is the fillers responsibility to "wrap" the endp back to point to
+ * rq->buf when the pointer steps past the end. Correspondingly it is the
+ * consumers responsibility to "wrap" the servp when it steps to rq->endbuf.
+ * The ringqPutc and ringqGetc routines will do this automatically.
+ */
+
+/*
+ * Ring queue buffer structure
+ */
+typedef struct {
+ unsigned char *buf; /* Holding buffer for data */
+ unsigned char *servp; /* Pointer to start of data */
+ unsigned char *endp; /* Pointer to end of data */
+ unsigned char *endbuf; /* Pointer to end of buffer */
+ int buflen; /* Length of ring queue */
+ int maxsize; /* Maximum size */
+ int increment; /* Growth increment */
+} ringq_t;
+
+/*
+ * Block allocation (balloc) definitions
+ */
+#ifdef B_STATS
+#ifndef B_L
+#define B_L T(__FILE__), __LINE__
+#define B_ARGS_DEC char_t *file, int line
+#define B_ARGS file, line
+#endif /* B_L */
+#endif /* B_STATS */
+
+/*
+ * Block classes are: 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192,
+ * 16384, 32768, 65536
+ */
+typedef struct {
+ union {
+ void *next; /* Pointer to next in q */
+ int size; /* Actual requested size */
+ } u;
+ int flags; /* Per block allocation flags */
+} bType;
+
+#define B_SHIFT 4 /* Convert size to class */
+#define B_ROUND ((1 << (B_SHIFT)) - 1)
+#define B_MAX_CLASS 13 /* Maximum class number + 1 */
+#define B_MALLOCED 0x80000000 /* Block was malloced */
+#define B_DEFAULT_MEM (64 * 1024) /* Default memory allocation */
+#define B_MAX_FILES (512) /* Maximum number of files */
+#define B_FILL_CHAR (0x77) /* Fill byte for buffers */
+#define B_FILL_WORD (0x77777777) /* Fill word for buffers */
+#define B_MAX_BLOCKS (64 * 1024) /* Maximum allocated blocks */
+
+/*
+ * Flags. The integrity value is used as an arbitrary value to fill the flags.
+ */
+#define B_INTEGRITY 0x8124000 /* Integrity value */
+#define B_INTEGRITY_MASK 0xFFFF000 /* Integrity mask */
+#define B_USE_MALLOC 0x1 /* Okay to use malloc if required */
+#define B_USER_BUF 0x2 /* User supplied buffer for mem */
+
+/*
+ * The symbol table record for each symbol entry
+ */
+
+typedef struct sym_t {
+ struct sym_t *forw; /* Pointer to next hash list */
+ value_t name; /* Name of symbol */
+ value_t content; /* Value of symbol */
+ int arg; /* Parameter value */
+} sym_t;
+
+typedef int sym_fd_t; /* Returned by symOpen */
+
+/*
+ * Script engines
+ */
+#define EMF_SCRIPT_JSCRIPT 0 /* javascript */
+#define EMF_SCRIPT_TCL 1 /* tcl */
+#define EMF_SCRIPT_EJSCRIPT 2 /* Ejscript */
+#define EMF_SCRIPT_MAX 3
+
+#define MAXINT INT_MAX
+#define BITSPERBYTE 8
+#define BITS(type) (BITSPERBYTE * (int) sizeof(type))
+#define STRSPACE T("\t \n\r\t")
+
+#ifndef max
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+#endif /* max */
+
+#ifndef min
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+#endif /* min */
+
+/******************************************************************************/
+/* CRON */
+/******************************************************************************/
+
+typedef struct {
+ char_t *minute;
+ char_t *hour;
+ char_t *day;
+ char_t *month;
+ char_t *dayofweek;
+} cron_t;
+
+extern long cronUntil(cron_t *cp, int period, time_t testTime);
+extern int cronAlloc(cron_t *cp, char_t *str);
+extern int cronFree(cron_t *cp);
+
+/******************************************************************************/
+/* SOCKET */
+/******************************************************************************/
+/*
+ * Socket flags
+ */
+
+#if ((defined (WIN) || defined (CE)) && defined (WEBS))
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#define ENETDOWN WSAENETDOWN
+#define ECONNRESET WSAECONNRESET
+#endif /* (WIN || CE) && WEBS) */
+
+#define SOCKET_EOF 0x1 /* Seen end of file */
+#define SOCKET_CONNECTING 0x2 /* Connect in progress */
+#define SOCKET_BROADCAST 0x4 /* Broadcast mode */
+#define SOCKET_PENDING 0x8 /* Message pending on this socket */
+#define SOCKET_FLUSHING 0x10 /* Background flushing */
+#define SOCKET_DATAGRAM 0x20 /* Use datagrams */
+#define SOCKET_ASYNC 0x40 /* Use async connect */
+#define SOCKET_BLOCK 0x80 /* Use blocking I/O */
+#define SOCKET_LISTENING 0x100 /* Socket is server listener */
+#define SOCKET_CLOSING 0x200 /* Socket is closing */
+#define SOCKET_CONNRESET 0x400 /* Socket connection was reset */
+
+#define SOCKET_PORT_MAX 0xffff /* Max Port size */
+
+/*
+ * Socket error values
+ */
+#define SOCKET_WOULDBLOCK 1 /* Socket would block on I/O */
+#define SOCKET_RESET 2 /* Socket has been reset */
+#define SOCKET_NETDOWN 3 /* Network is down */
+#define SOCKET_AGAIN 4 /* Issue the request again */
+#define SOCKET_INTR 5 /* Call was interrupted */
+#define SOCKET_INVAL 6 /* Invalid */
+
+/*
+ * Handler event masks
+ */
+#define SOCKET_READABLE 0x2 /* Make socket readable */
+#define SOCKET_WRITABLE 0x4 /* Make socket writable */
+#define SOCKET_EXCEPTION 0x8 /* Interested in exceptions */
+#define EMF_SOCKET_MESSAGE (WM_USER+13)
+
+#ifdef LITTLEFOOT
+#define SOCKET_BUFSIZ 510 /* Underlying buffer size */
+#else
+#define SOCKET_BUFSIZ 1024 /* Underlying buffer size */
+#endif /* LITTLEFOOT */
+
+typedef void (*socketHandler_t)(int sid, int mask, int data);
+typedef int (*socketAccept_t)(int sid, char *ipaddr, int port,
+ int listenSid);
+typedef struct {
+ char host[64]; /* Host name */
+ ringq_t inBuf; /* Input ring queue */
+ ringq_t outBuf; /* Output ring queue */
+ ringq_t lineBuf; /* Line ring queue */
+ socketAccept_t accept; /* Accept handler */
+ socketHandler_t handler; /* User I/O handler */
+ int handler_data; /* User handler data */
+ int handlerMask; /* Handler events of interest */
+ int sid; /* Index into socket[] */
+ int port; /* Port to listen on */
+ int flags; /* Current state flags */
+ int sock; /* Actual socket handle */
+ int fileHandle; /* ID of the file handler */
+ int interestEvents; /* Mask of events to watch for */
+ int currentEvents; /* Mask of ready events (FD_xx) */
+ int selectEvents; /* Events being selected */
+ int saveMask; /* saved Mask for socketFlush */
+ int error; /* Last error */
+} socket_t;
+
+/********************************* Prototypes *********************************/
+/*
+ * Balloc module
+ *
+ */
+
+extern void bclose();
+extern int bopen(void *buf, int bufsize, int flags);
+
+/*
+ * Define NO_BALLOC to turn off our balloc module altogether
+ * #define NO_BALLOC 1
+ */
+
+#ifdef NO_BALLOC
+#define balloc(B_ARGS, num) malloc(num)
+#define bfree(B_ARGS, p) free(p)
+#define bfreeSafe(B_ARGS, p) \
+ if (p) { free(p); } else
+#define brealloc(B_ARGS, p, num) realloc(p, num)
+extern char_t *bstrdupNoBalloc(char_t *s);
+extern char *bstrdupANoBalloc(char *s);
+#define bstrdup(B_ARGS, s) bstrdupNoBalloc(s)
+#define bstrdupA(B_ARGS, s) bstrdupANoBalloc(s)
+#define gstrdup(B_ARGS, s) bstrdupNoBalloc(s)
+
+#else /* BALLOC */
+
+#ifndef B_STATS
+#define balloc(B_ARGS, num) balloc(num)
+#define bfree(B_ARGS, p) bfree(p)
+#define bfreeSafe(B_ARGS, p) bfreeSafe(p)
+#define brealloc(B_ARGS, p, size) brealloc(p, size)
+#define bstrdup(B_ARGS, p) bstrdup(p)
+
+#ifdef UNICODE
+#define bstrdupA(B_ARGS, p) bstrdupA(p)
+#else /* UNICODE */
+#define bstrdupA bstrdup
+#endif /* UNICODE */
+
+#endif /* B_STATS */
+
+#define gstrdup bstrdup
+extern void *balloc(B_ARGS_DEC, int size);
+extern void bfree(B_ARGS_DEC, void *mp);
+extern void bfreeSafe(B_ARGS_DEC, void *mp);
+extern void *brealloc(B_ARGS_DEC, void *buf, int newsize);
+extern char_t *bstrdup(B_ARGS_DEC, char_t *s);
+
+#ifdef UNICODE
+extern char *bstrdupA(B_ARGS_DEC, char *s);
+#else /* UNICODE */
+#define bstrdupA bstrdup
+#endif /* UNICODE */
+#endif /* BALLOC */
+
+extern void bstats(int handle, void (*writefn)(int handle, char_t *fmt, ...));
+
+/*
+ * Flags. The integrity value is used as an arbitrary value to fill the flags.
+ */
+#define B_USE_MALLOC 0x1 /* Okay to use malloc if required */
+#define B_USER_BUF 0x2 /* User supplied buffer for mem */
+
+
+#if !LINUX && !__rtems__
+extern char_t *basename(char_t *name);
+#endif /* !LINUX */
+
+#if (defined (UEMF) && defined (WEBS))
+/*
+ * The open source webserver uses a different callback/timer mechanism
+ * than other emf derivative products such as FieldUpgrader agents
+ * so redefine those API for webserver so that they can coexist in the
+ * same address space as the others.
+ */
+#define emfSchedCallback websSchedCallBack
+#define emfUnschedCallback websUnschedCallBack
+#define emfReschedCallback websReschedCallBack
+#endif /* UEMF && WEBS */
+
+typedef void (emfSchedProc)(void *data, int id);
+extern int emfSchedCallback(int delay, emfSchedProc *proc, void *arg);
+extern void emfUnschedCallback(int id);
+extern void emfReschedCallback(int id, int delay);
+extern void emfSchedProcess();
+extern int emfInstGet();
+extern void emfInstSet(int inst);
+extern void error(E_ARGS_DEC, int flags, char_t *fmt, ...);
+extern void (*errorSetHandler(void (*function)(int etype, char_t *msg))) \
+ (int etype, char_t *msg);
+
+#ifdef B_STATS
+#define hAlloc(x) HALLOC(B_L, x)
+#define hAllocEntry(x, y, z) HALLOCENTRY(B_L, x, y, z)
+extern int HALLOC(B_ARGS_DEC, void ***map);
+extern int HALLOCENTRY(B_ARGS_DEC, void ***list, int *max, int size);
+#else
+extern int hAlloc(void ***map);
+extern int hAllocEntry(void ***list, int *max, int size);
+#endif /* B_STATS */
+
+extern int hFree(void ***map, int handle);
+
+extern int ringqOpen(ringq_t *rq, int increment, int maxsize);
+extern void ringqClose(ringq_t *rq);
+extern int ringqLen(ringq_t *rq);
+
+extern int ringqPutc(ringq_t *rq, char_t c);
+extern int ringqInsertc(ringq_t *rq, char_t c);
+extern int ringqPutStr(ringq_t *rq, char_t *str);
+extern int ringqGetc(ringq_t *rq);
+
+extern int fmtValloc(char_t **s, int n, char_t *fmt, va_list arg);
+extern int fmtAlloc(char_t **s, int n, char_t *fmt, ...);
+extern int fmtStatic(char_t *s, int n, char_t *fmt, ...);
+
+#ifdef UNICODE
+extern int ringqPutcA(ringq_t *rq, char c);
+extern int ringqInsertcA(ringq_t *rq, char c);
+extern int ringqPutStrA(ringq_t *rq, char *str);
+extern int ringqGetcA(ringq_t *rq);
+#else
+#define ringqPutcA ringqPutc
+#define ringqInsertcA ringqInsertc
+#define ringqPutStrA ringqPutStr
+#define ringqGetcA ringqGetc
+#endif /* UNICODE */
+
+extern int ringqPutBlk(ringq_t *rq, unsigned char *buf, int len);
+extern int ringqPutBlkMax(ringq_t *rq);
+extern void ringqPutBlkAdj(ringq_t *rq, int size);
+extern int ringqGetBlk(ringq_t *rq, unsigned char *buf, int len);
+extern int ringqGetBlkMax(ringq_t *rq);
+extern void ringqGetBlkAdj(ringq_t *rq, int size);
+extern void ringqFlush(ringq_t *rq);
+extern void ringqAddNull(ringq_t *rq);
+
+extern int scriptSetVar(int engine, char_t *var, char_t *value);
+extern int scriptEval(int engine, char_t *cmd, char_t **rslt, int chan);
+
+extern void socketClose();
+extern void socketCloseConnection(int sid);
+extern void socketCreateHandler(int sid, int mask, socketHandler_t
+ handler, int arg);
+extern void socketDeleteHandler(int sid);
+extern int socketEof(int sid);
+extern int socketCanWrite(int sid);
+extern void socketSetBufferSize(int sid, int in, int line, int out);
+extern int socketFlush(int sid);
+extern int socketGets(int sid, char_t **buf);
+extern int socketGetPort(int sid);
+extern int socketInputBuffered(int sid);
+extern int socketOpen();
+extern int socketOpenConnection(char *host, int port,
+ socketAccept_t accept, int flags);
+extern void socketProcess(int hid);
+extern int socketRead(int sid, char *buf, int len);
+extern int socketReady(int hid);
+extern int socketWrite(int sid, char *buf, int len);
+extern int socketWriteString(int sid, char_t *buf);
+extern int socketSelect(int hid, int timeout);
+extern int socketGetHandle(int sid);
+extern int socketSetBlock(int sid, int flags);
+extern int socketGetBlock(int sid);
+extern int socketAlloc(char *host, int port, socketAccept_t accept,
+ int flags);
+extern void socketFree(int sid);
+extern int socketGetError();
+extern socket_t *socketPtr(int sid);
+extern int socketWaitForEvent(socket_t *sp, int events, int *errCode);
+extern void socketRegisterInterest(socket_t *sp, int handlerMask);
+extern int socketGetInput(int sid, char *buf, int toRead, int *errCode);
+
+extern char_t *strlower(char_t *string);
+extern char_t *strupper(char_t *string);
+
+extern char_t *stritoa(int n, char_t *string, int width);
+
+extern sym_fd_t symOpen(int hash_size);
+extern void symClose(sym_fd_t sd);
+extern sym_t *symLookup(sym_fd_t sd, char_t *name);
+extern sym_t *symEnter(sym_fd_t sd, char_t *name, value_t v, int arg);
+extern int symDelete(sym_fd_t sd, char_t *name);
+extern void symWalk(sym_fd_t sd, void (*fn)(sym_t *symp));
+extern sym_t *symFirst(sym_fd_t sd);
+extern sym_t *symNext(sym_fd_t sd);
+extern int symSubOpen();
+extern void symSubClose();
+
+extern void trace(int lev, char_t *fmt, ...);
+extern void traceRaw(char_t *buf);
+extern void (*traceSetHandler(void (*function)(int level, char_t *buf)))
+ (int level, char_t *buf);
+
+extern value_t valueInteger(long value);
+extern value_t valueString(char_t *value, int flags);
+extern value_t valueErrmsg(char_t *value);
+extern void valueFree(value_t *v);
+extern int vxchdir(char *dirname);
+
+extern unsigned int hextoi(char_t *hexstring);
+extern unsigned int gstrtoi(char_t *s);
+extern time_t timeMsec();
+
+extern char_t *ascToUni(char_t *ubuf, char *str, int nBytes);
+extern char *uniToAsc(char *buf, char_t *ustr, int nBytes);
+extern char_t *ballocAscToUni(char *cp, int alen);
+extern char *ballocUniToAsc(char_t *unip, int ulen);
+
+extern char_t *basicGetHost();
+extern char_t *basicGetAddress();
+extern char_t *basicGetProduct();
+extern void basicSetHost(char_t *host);
+extern void basicSetAddress(char_t *addr);
+
+extern int harnessOpen(char_t **argv);
+extern void harnessClose(int status);
+extern void harnessTesting(char_t *msg, ...);
+extern void harnessPassed();
+extern void harnessFailed(int line);
+extern int harnessLevel();
+
+#endif /* _h_UEMF */
+
+/******************************************************************************/
diff --git a/cpukit/httpd/um.c b/cpukit/httpd/um.c
new file mode 100644
index 0000000000..e960f02719
--- /dev/null
+++ b/cpukit/httpd/um.c
@@ -0,0 +1,1435 @@
+/*
+ * um.c -- User Management
+ *
+ * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for usage and redistribution license requirements
+ *
+ * $Id$
+ */
+
+/******************************** Description *********************************/
+/*
+ * User Management routines for adding/deleting/changing users and groups
+ * Also, routines for determining user access
+ */
+
+/********************************* Includes ***********************************/
+
+#include "um.h"
+#include "emfdb.h"
+#include "webs.h"
+
+/********************************** Defines ***********************************/
+
+#define UM_DB_FILENAME T("um.xml")
+#define UM_TXT_FILENAME T("umconfig.txt")
+
+/*
+ * Table names
+ */
+#define UM_USER_TABLENAME T("users")
+#define UM_GROUP_TABLENAME T("groups")
+#define UM_ACCESS_TABLENAME T("access")
+
+/*
+ * Column names
+ */
+#define UM_NAME T("name")
+#define UM_PASS T("password")
+#define UM_GROUP T("group")
+#define UM_PROT T("prot")
+#define UM_DISABLE T("disable")
+#define UM_METHOD T("method")
+#define UM_PRIVILEGE T("priv")
+#define UM_SECURE T("secure")
+
+/*
+ * XOR encryption mask
+ * Note: This string should be modified for individual sites
+ * in order to enhance user password security.
+ */
+#define UM_XOR_ENCRYPT T("*j7a(L#yZ98sSd5HfSgGjMj8;Ss;d)(*&^#@$a2s0i3g")
+
+/******************************** Local Data **********************************/
+
+#ifdef qHierarchicalAccess
+/*
+ * user-provided function to allow hierarchical access protection. See below.
+ * for details.
+ */
+extern bool_t dmfCanAccess(const char_t* usergroup, const char_t* group);
+#endif
+#ifdef UEMF
+/*
+ * User table definition
+ */
+#define NUMBER_OF_USER_COLUMNS 5
+
+char_t *userColumnNames[NUMBER_OF_USER_COLUMNS] = {
+ UM_NAME, UM_PASS, UM_GROUP, UM_PROT, UM_DISABLE
+};
+
+int userColumnTypes[NUMBER_OF_USER_COLUMNS] = {
+ T_STRING, T_STRING, T_STRING, T_INT, T_INT
+};
+
+dbTable_t userTable = {
+ UM_USER_TABLENAME,
+ NUMBER_OF_USER_COLUMNS,
+ userColumnNames,
+ userColumnTypes,
+ 0,
+ NULL
+};
+
+/*
+ * Group table definition
+ */
+#define NUMBER_OF_GROUP_COLUMNS 5
+
+char_t *groupColumnNames[NUMBER_OF_GROUP_COLUMNS] = {
+ UM_NAME, UM_PRIVILEGE, UM_METHOD, UM_PROT, UM_DISABLE
+};
+
+int groupColumnTypes[NUMBER_OF_GROUP_COLUMNS] = {
+ T_STRING, T_INT, T_INT, T_INT, T_INT
+};
+
+dbTable_t groupTable = {
+ UM_GROUP_TABLENAME,
+ NUMBER_OF_GROUP_COLUMNS,
+ groupColumnNames,
+ groupColumnTypes,
+ 0,
+ NULL
+};
+
+/*
+ * Access Limit table definition
+ */
+#define NUMBER_OF_ACCESS_COLUMNS 4
+
+char_t *accessColumnNames[NUMBER_OF_ACCESS_COLUMNS] = {
+ UM_NAME, UM_METHOD, UM_SECURE, UM_GROUP
+};
+
+int accessColumnTypes[NUMBER_OF_ACCESS_COLUMNS] = {
+ T_STRING, T_INT, T_INT, T_STRING
+};
+
+dbTable_t accessTable = {
+ UM_ACCESS_TABLENAME,
+ NUMBER_OF_ACCESS_COLUMNS,
+ accessColumnNames,
+ accessColumnTypes,
+ 0,
+ NULL
+};
+#endif /* #ifdef UEMF */
+
+/*
+ * Database Identifier returned from dbOpen()
+ */
+static int didUM = -1;
+
+/*
+ * Configuration database persist filename
+ */
+static char_t *saveFilename = NULL;
+
+static int umOpenCount = 0; /* count of apps using this module */
+
+/*************************** Forward Declarations *****************************/
+
+static bool_t umCheckName(char_t *name);
+
+/*********************************** Code *************************************/
+/*
+ * umOpen() registers the UM tables in the fake emf-database
+ */
+
+int umOpen()
+{
+ if (++umOpenCount != 1) {
+ return didUM;
+ }
+/*
+ * Do not initialize if intialization has already taken place
+ */
+ if (didUM == -1) {
+ didUM = dbOpen(UM_USER_TABLENAME, UM_DB_FILENAME, NULL, 0);
+#ifdef UEMF
+ dbRegisterDBSchema(&userTable);
+ dbRegisterDBSchema(&groupTable);
+ dbRegisterDBSchema(&accessTable);
+#endif
+ }
+
+ if (saveFilename == NULL) {
+ saveFilename = bstrdup(B_L, UM_TXT_FILENAME);
+ }
+
+ return didUM;
+}
+
+/******************************************************************************/
+/*
+ * umClose() frees up the UM tables in the fake emf-database
+ */
+
+void umClose()
+{
+ if (--umOpenCount > 0) {
+ return;
+ }
+/*
+ * Do not close if intialization has not taken place
+ */
+ if (didUM != -1) {
+ dbClose(didUM);
+ didUM = -1;
+ }
+
+ if (saveFilename != NULL) {
+ bfree(B_L, saveFilename);
+ saveFilename = NULL;
+ }
+}
+
+/******************************************************************************/
+/*
+ * umCommit() persists all of the UM tables
+ */
+
+int umCommit(char_t *filename)
+{
+ if (filename && *filename) {
+ if (saveFilename != NULL) {
+ bfree(B_L, saveFilename);
+ }
+
+ saveFilename = bstrdup(B_L, filename);
+ }
+
+ a_assert (saveFilename && *saveFilename);
+ trace(3, T("UM: Writing User Configuration to file <%s>\n"),
+ saveFilename);
+
+ return dbSave(didUM, saveFilename, 0);
+}
+
+/******************************************************************************/
+/*
+ * umRestore() loads up the UM tables with persisted data
+ */
+
+int umRestore(char_t *filename)
+{
+ if (filename && *filename) {
+ if (saveFilename != NULL) {
+ bfree(B_L, saveFilename);
+ }
+
+ saveFilename = bstrdup(B_L, filename);
+ }
+
+ a_assert(saveFilename && *saveFilename);
+
+ trace(3, T("UM: Loading User Configuration from file <%s>\n"),
+ saveFilename);
+
+/*
+ * First empty the database, otherwise we wind up with duplicates!
+ */
+ dbZero(didUM);
+ return dbLoad(didUM, saveFilename, 0);
+}
+
+/******************************************************************************/
+/*
+ * Encrypt/Decrypt a text string.
+ * Returns the number of characters encrypted.
+ */
+
+static int umEncryptString(char_t *textString)
+{
+ char_t *enMask;
+ char_t enChar;
+ int numChars;
+
+ a_assert(textString);
+
+ enMask = UM_XOR_ENCRYPT;
+ numChars = 0;
+
+ while (*textString) {
+ enChar = *textString ^ *enMask;
+/*
+ * Do not produce encrypted text with embedded linefeeds or tabs.
+ * Simply use existing character.
+ */
+ if (enChar && !gisspace(enChar))
+ *textString = enChar;
+/*
+ * Increment all pointers.
+ */
+ enMask++;
+ textString++;
+ numChars++;
+/*
+ * Wrap encryption mask pointer if at end of length.
+ */
+ if (*enMask == '\0') {
+ enMask = UM_XOR_ENCRYPT;
+ }
+ }
+
+ return numChars;
+}
+
+/******************************************************************************/
+/*
+ * umGetFirstRowData() - return a pointer to the first non-blank key value
+ * in the given column for the given table.
+ */
+
+static char_t *umGetFirstRowData(char_t *tableName, char_t *columnName)
+{
+ char_t *columnData;
+ int row;
+ int check;
+
+ a_assert(tableName && *tableName);
+ a_assert(columnName && *columnName);
+
+ row = 0;
+/*
+ * Move through table until we retrieve the first row with non-null
+ * column data.
+ */
+ columnData = NULL;
+ while ((check = dbReadStr(didUM, tableName, columnName, row++,
+ &columnData)) == 0 || (check == DB_ERR_ROW_DELETED)) {
+ if (columnData && *columnData) {
+ return columnData;
+ }
+ }
+
+ return NULL;
+}
+
+/******************************************************************************/
+/*
+ * umGetNextRowData() - return a pointer to the first non-blank
+ * key value following the given one.
+ */
+
+static char_t *umGetNextRowData(char_t *tableName, char_t *columnName,
+ char_t *keyLast)
+{
+ char_t *key;
+ int row;
+ int check;
+
+ a_assert(tableName && *tableName);
+ a_assert(columnName && *columnName);
+ a_assert(keyLast && *keyLast);
+/*
+ * Position row counter to row where the given key value was found
+ */
+ row = 0;
+ key = NULL;
+
+ while ((((check = dbReadStr(didUM, tableName, columnName, row++,
+ &key)) == 0) || (check == DB_ERR_ROW_DELETED)) &&
+ ((key == NULL) || (gstrcmp(key, keyLast) != 0))) {
+ }
+/*
+ * If the last key value was not found, return NULL
+ */
+ if (!key || gstrcmp(key, keyLast) != 0) {
+ return NULL;
+ }
+/*
+ * Move through table until we retrieve the next row with a non-null key
+ */
+ while (((check = dbReadStr(didUM, tableName, columnName, row++, &key))
+ == 0) || (check == DB_ERR_ROW_DELETED)) {
+ if (key && *key && (gstrcmp(key, keyLast) != 0)) {
+ return key;
+ }
+ }
+
+ return NULL;
+}
+
+/******************************************************************************/
+/*
+ * umAddUser() - Adds a user to the "users" table.
+ */
+
+int umAddUser(char_t *user, char_t *pass, char_t *group,
+ bool_t prot, bool_t disabled)
+{
+ int row;
+ char_t *password;
+
+ a_assert(user && *user);
+ a_assert(pass && *pass);
+ a_assert(group && *group);
+
+ trace(3, T("UM: Adding User <%s>\n"), user);
+
+/*
+ * Do not allow duplicates
+ */
+ if (umUserExists(user)) {
+ return UM_ERR_DUPLICATE;
+ }
+
+/*
+ * Make sure user name and password contain valid characters
+ */
+ if (!umCheckName(user)) {
+ return UM_ERR_BAD_NAME;
+ }
+
+ if (!umCheckName(pass)) {
+ return UM_ERR_BAD_PASSWORD;
+ }
+
+/*
+ * Make sure group exists
+ */
+ if (!umGroupExists(group)) {
+ return UM_ERR_NOT_FOUND;
+ }
+
+/*
+ * Now create the user record
+ */
+ row = dbAddRow(didUM, UM_USER_TABLENAME);
+
+ if (row < 0) {
+ return UM_ERR_GENERAL;
+ }
+
+ if (dbWriteStr(didUM, UM_USER_TABLENAME, UM_NAME, row, user) != 0) {
+ return UM_ERR_GENERAL;
+ }
+
+ password = bstrdup(B_L, pass);
+ umEncryptString(password);
+ dbWriteStr(didUM, UM_USER_TABLENAME, UM_PASS, row, password);
+ bfree(B_L, password);
+ dbWriteStr(didUM, UM_USER_TABLENAME, UM_GROUP, row, group);
+ dbWriteInt(didUM, UM_USER_TABLENAME, UM_PROT, row, prot);
+ dbWriteInt(didUM, UM_USER_TABLENAME, UM_DISABLE, row, disabled);
+
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * umDeleteUser() - remove a user from the "users" table
+ */
+
+int umDeleteUser(char_t *user)
+{
+ int row;
+
+ a_assert(user && *user);
+ trace(3, T("UM: Deleting User <%s>\n"), user);
+/*
+ * Check to see if user is delete-protected
+ */
+ if (umGetUserProtected(user)) {
+ return UM_ERR_PROTECTED;
+ }
+
+/*
+ * If found, delete the user from the database
+ */
+ if ((row = dbSearchStr(didUM, UM_USER_TABLENAME, UM_NAME, user, 0)) >= 0) {
+ return dbDeleteRow(didUM, UM_USER_TABLENAME, row);
+ }
+
+ return UM_ERR_NOT_FOUND;
+}
+
+/******************************************************************************/
+/*
+ * umGetFirstUser() - Returns the user ID of the first user found in the
+ * "users" table.
+ */
+
+char_t *umGetFirstUser()
+{
+ return umGetFirstRowData(UM_USER_TABLENAME, UM_NAME);
+}
+
+/******************************************************************************/
+/*
+ * umGetNextUser() Returns the next user found in the "users" table after
+ * the given user.
+ */
+
+char_t *umGetNextUser(char_t *userLast)
+{
+ return umGetNextRowData(UM_USER_TABLENAME, UM_NAME, userLast);
+}
+
+/******************************************************************************/
+/*
+ * umUserExists() Returns TRUE if userid exists.
+ */
+
+bool_t umUserExists(char_t *user)
+{
+ a_assert(user && *user);
+
+ if (dbSearchStr(didUM, UM_USER_TABLENAME, UM_NAME, user, 0) >= 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/******************************************************************************/
+/*
+ * umGetUserPassword() returns a de-crypted copy of the user password
+ */
+
+char_t *umGetUserPassword(char_t *user)
+{
+ char_t *password;
+ int row;
+
+ a_assert(user && *user);
+
+ password = NULL;
+ row = dbSearchStr(didUM, UM_USER_TABLENAME, UM_NAME, user, 0);
+
+ if (row >= 0) {
+ char_t *pass = NULL;
+ dbReadStr(didUM, UM_USER_TABLENAME, UM_PASS, row, &pass);
+/*
+ * Decrypt password
+ * Note, this function returns a copy of the password, which must
+ * be deleted at some time in the future.
+ */
+ password = bstrdup(B_L, pass);
+ umEncryptString(password);
+ }
+
+ return password;
+}
+
+/******************************************************************************/
+/*
+ * umSetUserPassword() updates the user password in the user "table" after
+ * encrypting the given password
+ */
+
+int umSetUserPassword(char_t *user, char_t *pass)
+{
+ int row, nRet;
+ char_t *password;
+
+ a_assert(user && *user);
+ a_assert(pass && *pass);
+ trace(3, T("UM: Attempting to change the password for user <%s>\n"), user);
+/*
+ * Find the row of the user
+ */
+ if ((row = dbSearchStr(didUM, UM_USER_TABLENAME, UM_NAME, user, 0)) < 0) {
+ return UM_ERR_NOT_FOUND;
+ }
+
+ password = bstrdup(B_L, pass);
+ umEncryptString(password);
+ nRet = dbWriteStr(didUM, UM_USER_TABLENAME, UM_PASS, row, password);
+ bfree(B_L, password);
+
+ return nRet;
+}
+
+/******************************************************************************/
+/*
+ * umGetUserGroup() returns the name of the user group
+ */
+
+char_t *umGetUserGroup(char_t *user)
+{
+ char_t *group;
+ int row;
+
+ a_assert(user && *user);
+ group = NULL;
+/*
+ * Find the row of the user
+ */
+ row = dbSearchStr(didUM, UM_USER_TABLENAME, UM_NAME, user, 0);
+
+ if (row >= 0) {
+ dbReadStr(didUM, UM_USER_TABLENAME, UM_GROUP, row, &group);
+ }
+
+ return group;
+}
+
+/******************************************************************************/
+/*
+ * umSetUserGroup() Sets the name of the user group for the user
+ */
+
+int umSetUserGroup(char_t *user, char_t *group)
+{
+ int row;
+
+ a_assert(user && *user);
+ a_assert(group && *group);
+/*
+ * Find the row of the user
+ */
+ row = dbSearchStr(didUM, UM_USER_TABLENAME, UM_NAME, user, 0);
+
+ if (row >= 0) {
+ return dbWriteStr(didUM, UM_USER_TABLENAME, UM_GROUP, row, group);
+ } else {
+ return UM_ERR_NOT_FOUND;
+ }
+}
+
+/******************************************************************************/
+/*
+ * umGetUserEnabled() - returns if the user is enabled
+ * Returns FALSE if the user is not found.
+ */
+
+bool_t umGetUserEnabled(char_t *user)
+{
+ int disabled, row;
+
+ a_assert(user && *user);
+
+ disabled = 1;
+/*
+ * Find the row of the user
+ */
+ row = dbSearchStr(didUM, UM_USER_TABLENAME, UM_NAME, user, 0);
+
+ if (row >= 0) {
+ dbReadInt(didUM, UM_USER_TABLENAME, UM_DISABLE, row, &disabled);
+ }
+
+ return (bool_t)!disabled;
+}
+
+/******************************************************************************/
+/*
+ * umSetUserEnabled() Enables/disables the user
+ */
+int umSetUserEnabled(char_t *user, bool_t enabled)
+{
+ int row;
+
+ a_assert(user && *user);
+/*
+ * Find the row of the user
+ */
+ row = dbSearchStr(didUM, UM_USER_TABLENAME, UM_NAME, user, 0);
+ if (row >= 0) {
+ return dbWriteInt(didUM, UM_USER_TABLENAME, UM_DISABLE, row, !enabled);
+ } else {
+ return UM_ERR_NOT_FOUND;
+ }
+}
+
+/******************************************************************************/
+/*
+ * umGetUserProtected() - determine deletability of user
+ */
+
+bool_t umGetUserProtected(char_t *user)
+{
+ int protect, row;
+
+ a_assert(user && *user);
+/*
+ * Find the row of the user
+ */
+ row = dbSearchStr(didUM, UM_USER_TABLENAME, UM_NAME, user, 0);
+ protect = FALSE;
+
+ if (row >= 0) {
+ dbReadInt(didUM, UM_USER_TABLENAME, UM_PROT, row, &protect);
+ }
+
+ return (bool_t)protect;
+}
+
+/******************************************************************************/
+/*
+ * umSetUserProtected() sets the delete protection for the user
+ */
+int umSetUserProtected(char_t *user, bool_t protect)
+{
+ int row;
+
+ a_assert(user && *user);
+/*
+ * Find the row of the user
+ */
+ row = dbSearchStr(didUM, UM_USER_TABLENAME, UM_NAME, user, 0);
+
+ if (row >= 0) {
+ return dbWriteInt(didUM, UM_USER_TABLENAME, UM_PROT, row, protect);
+ } else {
+ return UM_ERR_NOT_FOUND;
+ }
+}
+
+
+/******************************************************************************/
+/*
+ * umAddGroup() adds a group to the "Group" table
+ */
+
+int umAddGroup(char_t *group, short priv, accessMeth_t am,
+ bool_t prot, bool_t disabled)
+{
+ int row;
+
+ a_assert(group && *group);
+ trace(3, T("UM: Adding group <%s>\n"), group);
+
+/*
+ * Do not allow duplicates
+ */
+ if (umGroupExists(group)) {
+ return UM_ERR_DUPLICATE;
+ }
+
+/*
+ * Only allow valid characters in key field
+ */
+ if (!umCheckName(group)) {
+ return UM_ERR_BAD_NAME;
+ }
+
+/*
+ * Add a new row to the table
+ */
+ if ((row = dbAddRow(didUM, UM_GROUP_TABLENAME)) < 0) {
+ return UM_ERR_GENERAL;
+ }
+
+/*
+ * Write the key field
+ */
+ if (dbWriteStr(didUM, UM_GROUP_TABLENAME, UM_NAME, row, group) != 0) {
+ return UM_ERR_GENERAL;
+ }
+
+/*
+ * Write the remaining fields
+ */
+ dbWriteInt(didUM, UM_GROUP_TABLENAME, UM_PRIVILEGE, row, priv);
+ dbWriteInt(didUM, UM_GROUP_TABLENAME, UM_METHOD, row, (int) am);
+ dbWriteInt(didUM, UM_GROUP_TABLENAME, UM_PROT, row, prot);
+ dbWriteInt(didUM, UM_GROUP_TABLENAME, UM_DISABLE, row, disabled);
+
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * umDeleteGroup() - Delete a user group, if not protected
+ */
+
+int umDeleteGroup(char_t *group)
+{
+ int row;
+
+ a_assert(group && *group);
+ trace(3, T("UM: Deleting Group <%s>\n"), group);
+
+/*
+ * Check to see if the group is in use
+ */
+ if (umGetGroupInUse(group)) {
+ return UM_ERR_IN_USE;
+ }
+
+/*
+ * Check to see if the group is delete-protected
+ */
+ if (umGetGroupProtected(group)) {
+ return UM_ERR_PROTECTED;
+ }
+
+/*
+ * Find the row of the group to delete
+ */
+ if ((row = dbSearchStr(didUM, UM_GROUP_TABLENAME, UM_NAME, group, 0)) < 0) {
+ return UM_ERR_NOT_FOUND;
+ }
+
+ return dbDeleteRow(didUM, UM_GROUP_TABLENAME, row);
+}
+
+/******************************************************************************/
+/*
+ * umGroupExists() returns TRUE if group exists, FALSE otherwise
+ */
+
+bool_t umGroupExists(char_t *group)
+{
+ a_assert(group && *group);
+
+ if (dbSearchStr(didUM, UM_GROUP_TABLENAME, UM_NAME, group, 0) >= 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+
+/******************************************************************************/
+/*
+ * umGetGroupInUse() returns TRUE if the group is referenced by a user or by
+ * an access limit.
+ */
+
+bool_t umGetGroupInUse(char_t *group)
+{
+ a_assert(group && *group);
+
+/*
+ * First, check the user table
+ */
+ if (dbSearchStr(didUM, UM_USER_TABLENAME, UM_GROUP, group, 0) >= 0) {
+ return TRUE;
+ }
+
+/*
+ * Second, check the access limit table
+ */
+ if (dbSearchStr(didUM, UM_ACCESS_TABLENAME, UM_GROUP, group, 0) >= 0) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/******************************************************************************/
+/*
+ * umGetFirstGroup() - return a pointer to the first non-blank group name
+ */
+
+char_t *umGetFirstGroup()
+{
+ return umGetFirstRowData(UM_GROUP_TABLENAME, UM_NAME);
+}
+
+/******************************************************************************/
+/*
+ * umGetNextGroup() - return a pointer to the first non-blank group name
+ * following the given group name
+ */
+
+char_t *umGetNextGroup(char_t *groupLast)
+{
+ return umGetNextRowData(UM_GROUP_TABLENAME, UM_NAME, groupLast);
+}
+
+/******************************************************************************/
+/*
+ * Returns the default access method to use for a given group
+ */
+
+accessMeth_t umGetGroupAccessMethod(char_t *group)
+{
+ int am, row;
+
+ a_assert(group && *group);
+ row = dbSearchStr(didUM, UM_GROUP_TABLENAME, UM_NAME, group, 0);
+
+ if (row >= 0) {
+ dbReadInt(didUM, UM_GROUP_TABLENAME, UM_METHOD, row, (int *)&am);
+ } else {
+ am = AM_INVALID;
+ }
+
+ return (accessMeth_t) am;
+}
+
+/******************************************************************************/
+/*
+ * Set the default access method to use for a given group
+ */
+
+int umSetGroupAccessMethod(char_t *group, accessMeth_t am)
+{
+ int row;
+
+ a_assert(group && *group);
+ row = dbSearchStr(didUM, UM_GROUP_TABLENAME, UM_NAME, group, 0);
+
+ if (row >= 0) {
+ return dbWriteInt(didUM, UM_GROUP_TABLENAME, UM_METHOD, row, (int) am);
+ } else {
+ return UM_ERR_NOT_FOUND;
+ }
+}
+
+/******************************************************************************/
+/*
+ * Returns the privilege mask for a given group
+ */
+
+short umGetGroupPrivilege(char_t *group)
+{
+ int privilege, row;
+
+ a_assert(group && *group);
+ privilege = -1;
+ row = dbSearchStr(didUM, UM_GROUP_TABLENAME, UM_NAME, group, 0);
+
+ if (row >= 0) {
+ dbReadInt(didUM, UM_GROUP_TABLENAME, UM_PRIVILEGE, row, &privilege);
+ }
+
+ return (short) privilege;
+}
+
+/******************************************************************************/
+/*
+ * Set the privilege mask for a given group
+ */
+
+int umSetGroupPrivilege(char_t *group, short privilege)
+{
+ int row;
+
+ a_assert(group && *group);
+ row = dbSearchStr(didUM, UM_GROUP_TABLENAME, UM_NAME, group, 0);
+
+ if (row >= 0) {
+ return dbWriteInt(didUM, UM_GROUP_TABLENAME, UM_PRIVILEGE, row,
+ (int)privilege);
+ } else {
+ return UM_ERR_NOT_FOUND;
+ }
+}
+
+/******************************************************************************/
+/*
+ * Returns the enabled setting for a given group.
+ * Returns FALSE if group is not found.
+ */
+
+bool_t umGetGroupEnabled(char_t *group)
+{
+ int disabled, row;
+
+ a_assert(group && *group);
+ row = dbSearchStr(didUM, UM_GROUP_TABLENAME, UM_NAME, group, 0);
+ disabled = 1;
+
+ if (row >= 0) {
+ dbReadInt(didUM, UM_GROUP_TABLENAME, UM_DISABLE, row, &disabled);
+ }
+
+ return (bool_t) !disabled;
+}
+
+/******************************************************************************/
+/*
+ * Sets the enabled setting for a given group.
+ */
+
+int umSetGroupEnabled(char_t *group, bool_t enabled)
+{
+ int row;
+
+ a_assert(group && *group);
+ row = dbSearchStr(didUM, UM_GROUP_TABLENAME, UM_NAME, group, 0);
+
+ if (row >= 0) {
+ return dbWriteInt(didUM, UM_GROUP_TABLENAME, UM_DISABLE, row,
+ (int) !enabled);
+ } else {
+ return UM_ERR_NOT_FOUND;
+ }
+}
+
+/******************************************************************************/
+/*
+ * Returns the protected setting for a given group
+ * Returns FALSE if user is not found
+ */
+
+bool_t umGetGroupProtected(char_t *group)
+{
+ int protect, row;
+
+ a_assert(group && *group);
+
+ protect = 0;
+ row = dbSearchStr(didUM, UM_GROUP_TABLENAME, UM_NAME, group, 0);
+ if (row >= 0) {
+ dbReadInt(didUM, UM_GROUP_TABLENAME, UM_PROT, row, &protect);
+ }
+
+ return (bool_t) protect;
+}
+
+/******************************************************************************/
+/*
+ * Sets the protected setting for a given group
+ */
+
+int umSetGroupProtected(char_t *group, bool_t protect)
+{
+ int row;
+
+ a_assert(group && *group);
+ row = dbSearchStr(didUM, UM_GROUP_TABLENAME, UM_NAME, group, 0);
+
+ if (row >= 0) {
+ return dbWriteInt(didUM, UM_GROUP_TABLENAME, UM_PROT, row,
+ (int) protect);
+ } else {
+ return UM_ERR_NOT_FOUND;
+ }
+}
+
+
+/******************************************************************************/
+/*
+ * umAddAccessLimit() adds an access limit to the "access" table
+ */
+
+int umAddAccessLimit(char_t *url, accessMeth_t am, short secure, char_t *group)
+{
+ int row;
+
+ a_assert(url && *url);
+ trace(3, T("UM: Adding Access Limit for <%s>\n"), url);
+
+/*
+ * Do not allow duplicates
+ */
+ if (umAccessLimitExists(url)) {
+ return UM_ERR_DUPLICATE;
+ }
+
+/*
+ * Add a new row to the table
+ */
+ if ((row = dbAddRow(didUM, UM_ACCESS_TABLENAME)) < 0) {
+ return UM_ERR_GENERAL;
+ }
+
+/*
+ * Write the key field
+ */
+ if(dbWriteStr(didUM, UM_ACCESS_TABLENAME, UM_NAME, row, url) < 0) {
+ return UM_ERR_GENERAL;
+ }
+
+/*
+ * Write the remaining fields
+ */
+ dbWriteInt(didUM, UM_ACCESS_TABLENAME, UM_METHOD, row, (int)am);
+ dbWriteInt(didUM, UM_ACCESS_TABLENAME, UM_SECURE, row, (int)secure);
+ dbWriteStr(didUM, UM_ACCESS_TABLENAME, UM_GROUP, row, group);
+
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * umDeleteAccessLimit()
+ */
+
+int umDeleteAccessLimit(char_t *url)
+{
+ int row;
+
+ a_assert(url && *url);
+ trace(3, T("UM: Deleting Access Limit for <%s>\n"), url);
+/*
+ * Find the row of the access limit to delete
+ */
+ if ((row = dbSearchStr(didUM, UM_ACCESS_TABLENAME, UM_NAME, url, 0)) < 0) {
+ return UM_ERR_NOT_FOUND;
+ }
+
+ return dbDeleteRow(didUM, UM_ACCESS_TABLENAME, row);
+}
+
+/******************************************************************************/
+/*
+ * umGetFirstGroup() - return a pointer to the first non-blank access limit
+ */
+
+char_t *umGetFirstAccessLimit()
+{
+ return umGetFirstRowData(UM_ACCESS_TABLENAME, UM_NAME);
+}
+
+/******************************************************************************/
+/*
+ * umGetNextAccessLimit() - return a pointer to the first non-blank
+ * access limit following the given one
+ */
+
+char_t *umGetNextAccessLimit(char_t *urlLast)
+{
+ return umGetNextRowData(UM_ACCESS_TABLENAME, UM_NAME, urlLast);
+}
+
+/******************************************************************************/
+/*
+ * umAccessLimitExists() returns TRUE if this access limit exists
+ */
+
+bool_t umAccessLimitExists(char_t *url)
+{
+ a_assert(url && *url);
+
+ if (dbSearchStr(didUM, UM_ACCESS_TABLENAME, UM_NAME, url, 0) < 0) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
+/******************************************************************************/
+/*
+ * umGetAccessLimit() returns the Access Method for the URL
+ */
+
+accessMeth_t umGetAccessLimitMethod(char_t *url)
+{
+ int am, row;
+
+ am = (int) AM_INVALID;
+ row = dbSearchStr(didUM, UM_ACCESS_TABLENAME, UM_NAME, url, 0);
+
+ if (row >= 0) {
+ dbReadInt(didUM, UM_ACCESS_TABLENAME, UM_METHOD, row, &am);
+ }
+
+ return (accessMeth_t) am;
+}
+
+/******************************************************************************/
+/*
+ * umSetAccessLimitMethod() - set Access Method for Access Limit
+ */
+
+int umSetAccessLimitMethod(char_t *url, accessMeth_t am)
+{
+ int row;
+
+ a_assert(url && *url);
+ row = dbSearchStr(didUM, UM_ACCESS_TABLENAME, UM_NAME, url, 0);
+
+ if (row >= 0) {
+ return dbWriteInt(didUM, UM_ACCESS_TABLENAME, UM_METHOD, row, (int) am);
+ } else {
+ return UM_ERR_NOT_FOUND;
+ }
+}
+
+/******************************************************************************/
+/*
+ * umGetAccessLimitSecure() - returns secure switch for access limit
+ */
+
+short umGetAccessLimitSecure(char_t *url)
+{
+ int secure, row;
+
+ a_assert(url && *url);
+ secure = -1;
+ row = dbSearchStr(didUM, UM_ACCESS_TABLENAME, UM_NAME, url, 0);
+
+ if (row >= 0) {
+ dbReadInt(didUM, UM_ACCESS_TABLENAME, UM_SECURE, row, &secure);
+ }
+
+ return (short)secure;
+}
+
+/******************************************************************************/
+/*
+ * umSetAccessLimitSecure() - sets the secure flag for the URL
+ */
+
+int umSetAccessLimitSecure(char_t *url, short secure)
+{
+ int row;
+
+ a_assert(url && *url);
+ row = dbSearchStr(didUM, UM_ACCESS_TABLENAME, UM_NAME, url, 0);
+
+ if (row >= 0) {
+ return dbWriteInt(didUM, UM_ACCESS_TABLENAME, UM_SECURE, row,
+ (int)secure);
+ } else {
+ return UM_ERR_NOT_FOUND;
+ }
+}
+
+/******************************************************************************/
+/*
+ * umGetAccessLimitGroup() - returns the user group of the access limit
+ */
+
+char_t *umGetAccessLimitGroup(char_t *url)
+{
+ char_t *group;
+ int row;
+
+ a_assert(url && *url);
+ group = NULL;
+ row = dbSearchStr(didUM, UM_ACCESS_TABLENAME, UM_NAME, url, 0);
+
+ if (row >= 0) {
+ dbReadStr(didUM, UM_ACCESS_TABLENAME, UM_GROUP, row, &group);
+ }
+
+ return group;
+}
+
+/******************************************************************************/
+/*
+ * umSetAccessLimitGroup() - sets the user group for the access limit.
+ */
+
+int umSetAccessLimitGroup(char_t *url, char_t *group)
+{
+ int row;
+
+ a_assert(url && *url);
+ row = dbSearchStr(didUM, UM_ACCESS_TABLENAME, UM_NAME, url, 0);
+
+ if (row >= 0) {
+ return dbWriteStr(didUM, UM_ACCESS_TABLENAME, UM_GROUP, row, group);
+ } else {
+ return UM_ERR_NOT_FOUND;
+ }
+}
+
+/******************************************************************************/
+/*
+ * Returns the access limit to use for a given URL, by checking for URLs up
+ * the directory tree. Creates a new string that must be deleted.
+ */
+
+char_t *umGetAccessLimit(char_t *url)
+{
+ char_t *urlRet, *urlCheck, *lastChar;
+ int len;
+
+ a_assert(url && *url);
+ urlRet = NULL;
+ urlCheck = bstrdup(B_L, url);
+ a_assert(urlCheck);
+ len = gstrlen(urlCheck);
+/*
+ * Scan back through URL to see if there is a "parent" access limit
+ */
+ while (len && !urlRet) {
+ if (umAccessLimitExists(urlCheck)) {
+ urlRet = bstrdup(B_L, urlCheck);
+ } else {
+/*
+ * Trim the end portion of the URL to the previous directory marker
+ */
+ lastChar = urlCheck + len;
+ lastChar--;
+
+ while ((lastChar >= urlCheck) && ((*lastChar == '/') ||
+ (*lastChar == '\\'))) {
+ *lastChar = 0;
+ lastChar--;
+ }
+
+ while ((lastChar >= urlCheck) && (*lastChar != '/') &&
+ (*lastChar != '\\')) {
+ *lastChar = 0;
+ lastChar--;
+ }
+
+ len = gstrlen(urlCheck);
+ }
+ }
+ bfree (B_L, urlCheck);
+
+ return urlRet;
+}
+
+/******************************************************************************/
+/*
+ * Returns the access method to use for a given URL
+ */
+
+accessMeth_t umGetAccessMethodForURL(char_t *url)
+{
+ accessMeth_t amRet;
+ char_t *urlHavingLimit, *group;
+
+ urlHavingLimit = umGetAccessLimit(url);
+ if (urlHavingLimit) {
+ group = umGetAccessLimitGroup(urlHavingLimit);
+
+ if (group && *group) {
+ amRet = umGetGroupAccessMethod(group);
+ } else {
+ amRet = umGetAccessLimitMethod(urlHavingLimit);
+ }
+
+ bfree(B_L, urlHavingLimit);
+ } else {
+ amRet = AM_FULL;
+ }
+
+ return amRet;
+}
+
+/******************************************************************************/
+/*
+ * Returns TRUE if user can access URL
+ */
+
+bool_t umUserCanAccessURL(char_t *user, char_t *url)
+{
+ accessMeth_t amURL;
+ char_t *group, *usergroup, *urlHavingLimit;
+ short priv;
+
+ a_assert(user && *user);
+ a_assert(url && *url);
+
+/*
+ * Make sure user exists
+ */
+ if (!umUserExists(user)) {
+ return FALSE;
+ }
+
+/*
+ * Make sure user is enabled
+ */
+ if (!umGetUserEnabled(user)) {
+ return FALSE;
+ }
+
+/*
+ * Make sure user has sufficient privileges (any will do)
+ */
+ usergroup = umGetUserGroup(user);
+ priv = umGetGroupPrivilege(usergroup);
+ if (priv == 0) {
+ return FALSE;
+ }
+
+/*
+ * Make sure user's group is enabled
+ */
+ if (!umGetGroupEnabled(usergroup)) {
+ return FALSE;
+ }
+
+/*
+ * The access method of the user group must not be AM_NONE
+ */
+ if (umGetGroupAccessMethod(usergroup) == AM_NONE) {
+ return FALSE;
+ }
+
+/*
+ * Check to see if there is an Access Limit for this URL
+ */
+ urlHavingLimit = umGetAccessLimit(url);
+ if (urlHavingLimit) {
+ amURL = umGetAccessLimitMethod(urlHavingLimit);
+ group = umGetAccessLimitGroup(urlHavingLimit);
+ bfree(B_L, urlHavingLimit);
+ } else {
+/*
+ * If there isn't an access limit for the URL, user has full access
+ */
+ return TRUE;
+ }
+
+/*
+ * If the access method for the URL is AM_NONE then
+ * the file "doesn't exist".
+ */
+ if (amURL == AM_NONE) {
+ return FALSE;
+ }
+
+/*
+ * If Access Limit has a group specified, then the user must be a
+ * member of that group
+ */
+ if (group && *group) {
+#ifdef qHierarchicalAccess
+ /*
+ * If we are compiling with the hierarchical access extensions, we
+ * instead call the user-provided function that checks to see whether
+ * the current user's access level is greater than or equal to the
+ * access level required for this URL.
+ */
+ return dmfCanAccess(usergroup, group);
+
+#else
+ if (usergroup && (gstrcmp(group, usergroup) != 0)) {
+ return FALSE;
+
+ }
+#endif
+ }
+
+/*
+ * Otherwise, user can access the URL
+ */
+ return TRUE;
+
+}
+
+/******************************************************************************/
+/*
+ * Returns TRUE if given name has only valid chars
+ */
+
+static bool_t umCheckName(char_t *name)
+{
+ a_assert(name && *name);
+
+ if (name && *name) {
+ while (*name) {
+ if (gisspace(*name)) {
+ return FALSE;
+ }
+
+ name++;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/******************************************************************************/
diff --git a/cpukit/httpd/um.h b/cpukit/httpd/um.h
new file mode 100644
index 0000000000..b520893275
--- /dev/null
+++ b/cpukit/httpd/um.h
@@ -0,0 +1,183 @@
+/*
+ * um.h -- GoAhead User Management public header
+ *
+ * Copyright (c) GoAhead Software Inc., 1992-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for information on usage and redistribution
+ *
+ * $Id$
+ */
+
+#ifndef _h_UM
+#define _h_UM 1
+
+/******************************** Description *********************************/
+
+/*
+ * GoAhead User Management header. This defines the User Management
+ * public APIs. Include this header for files that contain access to
+ * user inquiry or management.
+ */
+
+/********************************* Includes ***********************************/
+
+#ifndef UEMF
+ #include "basic/basic.h"
+ #include "emf/emf.h"
+#else
+ #include "uemf.h"
+#endif
+
+/********************************** Defines ***********************************/
+
+/*
+ * Error Return Flags
+ */
+#define UM_OK 0
+#define UM_ERR_GENERAL -1
+#define UM_ERR_NOT_FOUND -2
+#define UM_ERR_PROTECTED -3
+#define UM_ERR_DUPLICATE -4
+#define UM_ERR_IN_USE -5
+#define UM_ERR_BAD_NAME -6
+#define UM_ERR_BAD_PASSWORD -7
+
+/*
+ * Privilege Masks
+ */
+#define PRIV_NONE 0x00
+#define PRIV_READ 0x01
+#define PRIV_WRITE 0x02
+#define PRIV_ADMIN 0x04
+
+/*
+ * User classes
+ */
+typedef short bool_t;
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+typedef enum {
+ AM_NONE = 0,
+ AM_FULL,
+ AM_BASIC,
+ AM_DIGEST,
+ AM_INVALID
+} accessMeth_t;
+
+/********************************** Prototypes ********************************/
+
+/*
+ * umOpen() must be called before accessing User Management functions
+ */
+extern int umOpen();
+
+/*
+ * umClose() should be called before shutdown to free memory
+ */
+extern void umClose();
+
+/*
+ * umCommit() persists the user management database
+ */
+extern int umCommit(char_t *filename);
+
+/*
+ * umRestore() loads the user management database
+ */
+extern int umRestore(char_t *filename);
+
+/*
+ * umUser functions use a user ID for a key
+ */
+extern int umAddUser(char_t *user, char_t *password,
+ char_t *group, bool_t protect, bool_t disabled);
+
+extern int umDeleteUser(char_t *user);
+
+extern char_t *umGetFirstUser();
+extern char_t *umGetNextUser(char_t *lastUser);
+
+extern bool_t umUserExists(char_t *user);
+
+extern char_t *umGetUserPassword(char_t *user);
+extern int umSetUserPassword(char_t *user, char_t *password);
+
+extern char_t *umGetUserGroup(char_t *user);
+extern int umSetUserGroup(char_t *user, char_t *password);
+
+extern bool_t umGetUserEnabled(char_t *user);
+extern int umSetUserEnabled(char_t *user, bool_t enabled);
+
+extern bool_t umGetUserProtected(char_t *user);
+extern int umSetUserProtected(char_t *user, bool_t protect);
+
+/*
+ * umGroup functions use a group name for a key
+ */
+extern int umAddGroup(char_t *group, short privilege,
+ accessMeth_t am, bool_t protect, bool_t disabled);
+
+extern int umDeleteGroup(char_t *group);
+
+extern char_t *umGetFirstGroup();
+extern char_t *umGetNextGroup(char_t *lastUser);
+
+extern bool_t umGroupExists(char_t *group);
+extern bool_t umGetGroupInUse(char_t *group);
+
+extern accessMeth_t umGetGroupAccessMethod(char_t *group);
+extern int umSetGroupAccessMethod(char_t *group, accessMeth_t am);
+
+extern bool_t umGetGroupEnabled(char_t *group);
+extern int umSetGroupEnabled(char_t *group, bool_t enabled);
+
+extern short umGetGroupPrivilege(char_t *group);
+extern int umSetGroupPrivilege(char_t *group, short privileges);
+
+extern bool_t umGetGroupProtected(char_t *group);
+extern int umSetGroupProtected(char_t *group, bool_t protect);
+
+/*
+ * umAccessLimit functions use a URL as a key
+ */
+extern int umAddAccessLimit(char_t *url, accessMeth_t am,
+ short secure, char_t *group);
+
+extern int umDeleteAccessLimit(char_t *url);
+
+extern char_t *umGetFirstAccessLimit();
+extern char_t *umGetNextAccessLimit(char_t *lastUser);
+
+/*
+ * Returns the name of an ancestor access limit if
+ */
+extern char_t *umGetAccessLimit(char_t *url);
+
+extern bool_t umAccessLimitExists(char_t *url);
+
+extern accessMeth_t umGetAccessLimitMethod(char_t *url);
+extern int umSetAccessLimitMethod(char_t *url, accessMeth_t am);
+
+extern short umGetAccessLimitSecure(char_t *url);
+extern int umSetAccessLimitSecure(char_t *url, short secure);
+
+extern char_t *umGetAccessLimitGroup(char_t *url);
+extern int umSetAccessLimitGroup(char_t *url, char_t *group);
+
+/*
+ * Convenience Functions
+ */
+
+extern accessMeth_t umGetAccessMethodForURL(char_t *url);
+extern bool_t umUserCanAccessURL(char_t *user, char_t *url);
+
+#endif /* _h_UM */
+
+/******************************************************************************/
diff --git a/cpukit/httpd/umui.c b/cpukit/httpd/umui.c
new file mode 100644
index 0000000000..971b059bc7
--- /dev/null
+++ b/cpukit/httpd/umui.c
@@ -0,0 +1,641 @@
+/*
+ * umui.c -- User Management GoForm Processing
+ *
+ * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for usage and redistribution license requirements
+ *
+ * $Id$
+ */
+
+/******************************** Description *********************************/
+
+/*
+ * This module provides GoForm functions for User management
+ */
+
+/********************************* Includes ***********************************/
+
+#include "wsIntrn.h"
+#include "um.h"
+
+/********************************* Defines ************************************/
+
+#define NONE_OPTION T("<NONE>")
+#define MSG_START T("<body><h2>")
+#define MSG_END T("</h2></body>")
+
+/**************************** Forward Declarations ****************************/
+
+static void formAddUser(webs_t wp, char_t *path, char_t *query);
+static void formDeleteUser(webs_t wp, char_t *path, char_t *query);
+static void formDisplayUser(webs_t wp, char_t *path, char_t *query);
+static int aspGenerateUserList(int eid, webs_t wp,
+ int argc, char_t **argv);
+
+static void formAddGroup(webs_t wp, char_t *path, char_t *query);
+static void formDeleteGroup(webs_t wp, char_t *path, char_t *query);
+static int aspGenerateGroupList(int eid, webs_t wp,
+ int argc, char_t **argv);
+
+static void formAddAccessLimit(webs_t wp, char_t *path, char_t *query);
+static void formDeleteAccessLimit(webs_t wp, char_t *path, char_t *query);
+static int aspGenerateAccessLimitList(int eid, webs_t wp,
+ int argc, char_t **argv);
+
+static int aspGenerateAccessMethodList(int eid, webs_t wp,
+ int argc, char_t **argv);
+static int aspGeneratePrivilegeList(int eid, webs_t wp,
+ int argc, char_t **argv);
+
+static void formSaveUserManagement(webs_t wp, char_t *path, char_t *query);
+static void formLoadUserManagement(webs_t wp, char_t *path, char_t *query);
+
+static void websMsgStart(webs_t wp);
+static void websMsgEnd(webs_t wp);
+
+/*********************************** Code *************************************/
+/*
+ * Set up the User Management form handlers
+ */
+
+void formDefineUserMgmt(void)
+{
+ websAspDefine(T("MakeGroupList"), aspGenerateGroupList);
+ websAspDefine(T("MakeUserList"), aspGenerateUserList);
+ websAspDefine(T("MakeAccessLimitList"), aspGenerateAccessLimitList);
+ websAspDefine(T("MakeAccessMethodList"), aspGenerateAccessMethodList);
+ websAspDefine(T("MakePrivilegeList"), aspGeneratePrivilegeList);
+
+ websFormDefine(T("AddUser"), formAddUser);
+ websFormDefine(T("DeleteUser"), formDeleteUser);
+ websFormDefine(T("DisplayUser"), formDisplayUser);
+ websFormDefine(T("AddGroup"), formAddGroup);
+ websFormDefine(T("DeleteGroup"), formDeleteGroup);
+ websFormDefine(T("AddAccessLimit"), formAddAccessLimit);
+ websFormDefine(T("DeleteAccessLimit"), formDeleteAccessLimit);
+
+ websFormDefine(T("SaveUserManagement"), formSaveUserManagement);
+ websFormDefine(T("LoadUserManagement"), formLoadUserManagement);
+}
+
+/******************************************************************************/
+/*
+ * Add a user
+ */
+
+static void formAddUser(webs_t wp, char_t *path, char_t *query)
+{
+ char_t *userid, *pass1, *pass2, *group, *enabled, *ok;
+ bool_t bDisable;
+ int nCheck;
+
+ a_assert(wp);
+
+ userid = websGetVar(wp, T("user"), T(""));
+ pass1 = websGetVar(wp, T("password"), T(""));
+ pass2 = websGetVar(wp, T("passconf"), T(""));
+ group = websGetVar(wp, T("group"), T(""));
+ enabled = websGetVar(wp, T("enabled"), T(""));
+ ok = websGetVar(wp, T("ok"), T(""));
+
+ websHeader(wp);
+ websMsgStart(wp);
+
+ if (gstricmp(ok, T("ok")) != 0) {
+ websWrite(wp, T("Add User Cancelled"));
+ } else if (gstrcmp(pass1, pass2) != 0) {
+ websWrite(wp, T("Confirmation Password did not match."));
+ } else {
+ if (enabled && *enabled && (gstrcmp(enabled, T("on")) == 0)) {
+ bDisable = FALSE;
+ } else {
+ bDisable = TRUE;
+ }
+
+ nCheck = umAddUser(userid, pass1, group, 0, bDisable);
+ if (nCheck != 0) {
+ char_t * strError;
+
+ switch (nCheck) {
+ case UM_ERR_DUPLICATE:
+ strError = T("User already exists.");
+ break;
+
+ case UM_ERR_BAD_NAME:
+ strError = T("Invalid user name.");
+ break;
+
+ case UM_ERR_BAD_PASSWORD:
+ strError = T("Invalid password.");
+ break;
+
+ case UM_ERR_NOT_FOUND:
+ strError = T("Invalid or unselected group.");
+ break;
+
+ default:
+ strError = T("Error writing user record.");
+ break;
+ }
+
+ websWrite(wp, T("Unable to add user, \"%s\". %s"),
+ userid, strError);
+ } else {
+ websWrite(wp, T("User, \"%s\" was successfully added."),
+ userid);
+ }
+ }
+
+ websMsgEnd(wp);
+ websFooter(wp);
+ websDone(wp, 200);
+}
+
+/******************************************************************************/
+/*
+ * Delete a user
+ */
+
+static void formDeleteUser(webs_t wp, char_t *path, char_t *query)
+{
+ char_t *userid, *ok;
+
+ a_assert(wp);
+
+ userid = websGetVar(wp, T("user"), T(""));
+ ok = websGetVar(wp, T("ok"), T(""));
+
+ websHeader(wp);
+ websMsgStart(wp);
+
+ if (gstricmp(ok, T("ok")) != 0) {
+ websWrite(wp, T("Delete User Cancelled"));
+ } else if (umUserExists(userid) == FALSE) {
+ websWrite(wp, T("ERROR: User \"%s\" not found"), userid);
+ } else if (umGetUserProtected(userid)) {
+ websWrite(wp, T("ERROR: User, \"%s\" is delete-protected."), userid);
+ } else if (umDeleteUser(userid) != 0) {
+ websWrite(wp, T("ERROR: Unable to delete user, \"%s\" "), userid);
+ } else {
+ websWrite(wp, T("User, \"%s\" was successfully deleted."), userid);
+ }
+
+ websMsgEnd(wp);
+ websFooter(wp);
+ websDone(wp, 200);
+}
+
+/******************************************************************************/
+/*
+ * Display the user info
+ */
+
+static void formDisplayUser(webs_t wp, char_t *path, char_t *query)
+{
+ char_t *userid, *ok, *temp;
+ bool_t enabled;
+
+ a_assert(wp);
+
+ userid = websGetVar(wp, T("user"), T(""));
+ ok = websGetVar(wp, T("ok"), T(""));
+
+ websHeader(wp);
+ websWrite(wp, T("<body>"));
+
+ if (gstricmp(ok, T("ok")) != 0) {
+ websWrite(wp, T("Display User Cancelled"));
+ } else if (umUserExists(userid) == FALSE) {
+ websWrite(wp, T("ERROR: User <b>%s</b> not found.\n"), userid);
+ } else {
+ websWrite(wp, T("<h2>User ID: <b>%s</b></h2>\n"), userid);
+ temp = umGetUserGroup(userid);
+ websWrite(wp, T("<h3>User Group: <b>%s</b></h3>\n"), temp);
+ enabled = umGetUserEnabled(userid);
+ websWrite(wp, T("<h3>Enabled: <b>%d</b></h3>\n"), enabled);
+ }
+
+ websWrite(wp, T("</body>\n"));
+ websFooter(wp);
+ websDone(wp, 200);
+}
+
+
+/******************************************************************************/
+/*
+ * Generate HTML to create a list box containing the users
+ */
+
+static int aspGenerateUserList(int eid, webs_t wp, int argc, char_t **argv)
+{
+ char_t *userid;
+ int row, nBytesSent, nBytes;
+
+ a_assert(wp);
+
+ nBytes = websWrite(wp,
+ T("<SELECT NAME=\"user\" SIZE=\"3\" TITLE=\"Select a User\">"));
+ row = 0;
+ userid = umGetFirstUser();
+ nBytesSent = 0;
+
+ while (userid && (nBytes > 0)) {
+ nBytes = websWrite(wp, T("<OPTION VALUE=\"%s\">%s\n"),
+ userid, userid);
+ userid = umGetNextUser(userid);
+ nBytesSent += nBytes;
+ }
+
+ nBytesSent += websWrite(wp, T("</SELECT>"));
+
+ return nBytesSent;
+}
+
+/******************************************************************************/
+/*
+ * Add a group
+ */
+
+static void formAddGroup(webs_t wp, char_t *path, char_t *query)
+{
+ char_t *group, *enabled, *privilege, *method, *ok, *pChar;
+ int nCheck;
+ short priv;
+ accessMeth_t am;
+ bool_t bDisable;
+
+ a_assert(wp);
+
+ group = websGetVar(wp, T("group"), T(""));
+ method = websGetVar(wp, T("method"), T(""));
+ enabled = websGetVar(wp, T("enabled"), T(""));
+ privilege = websGetVar(wp, T("privilege"), T(""));
+ ok = websGetVar(wp, T("ok"), T(""));
+
+ websHeader(wp);
+ websMsgStart(wp);
+
+ if (gstricmp(ok, T("ok")) != 0) {
+ websWrite(wp, T("Add Group Cancelled."));
+ } else if ((group == NULL) || (*group == 0)) {
+ websWrite(wp, T("No Group Name was entered."));
+ } else if (umGroupExists(group)) {
+ websWrite(wp, T("ERROR: Group, \"%s\" already exists."), group);
+ } else {
+ if (privilege && *privilege) {
+/*
+ * privilege is a mulitple <SELECT> var, and must be parsed.
+ * Values for these variables are space delimited.
+ */
+ priv = 0;
+ for (pChar = privilege; *pChar; pChar++) {
+ if (*pChar == ' ') {
+ *pChar = '\0';
+ priv |= gatoi(privilege);
+ *pChar = ' ';
+ privilege = pChar + 1;
+ }
+ }
+ priv |= gatoi(privilege);
+ } else {
+ priv = 0;
+ }
+
+ if (method && *method) {
+ am = (accessMeth_t) gatoi(method);
+ } else {
+ am = AM_FULL;
+ }
+
+ if (enabled && *enabled && (gstrcmp(enabled, T("on")) == 0)) {
+ bDisable = FALSE;
+ } else {
+ bDisable = TRUE;
+ }
+
+ nCheck = umAddGroup(group, priv, am, 0, bDisable);
+ if (nCheck != 0) {
+ websWrite(wp, T("Unable to add group, \"%s\", code: %d "),
+ group, nCheck);
+ } else {
+ websWrite(wp, T("Group, \"%s\" was successfully added."),
+ group);
+ }
+ }
+
+ websMsgEnd(wp);
+ websFooter(wp);
+ websDone(wp, 200);
+}
+
+/******************************************************************************/
+/*
+ * Delete a group
+ */
+
+static void formDeleteGroup(webs_t wp, char_t *path, char_t *query)
+{
+ char_t *group, *ok;
+
+ a_assert(wp);
+
+ group = websGetVar(wp, T("group"), T(""));
+ ok = websGetVar(wp, T("ok"), T(""));
+
+ websHeader(wp);
+ websMsgStart(wp);
+
+ if (gstricmp(ok, T("ok")) != 0) {
+ websWrite(wp, T("Delete Group Cancelled."));
+ } else if ((group == NULL) || (*group == '\0')) {
+ websWrite(wp, T("ERROR: No group was selected."));
+ } else if (umGetGroupProtected(group)) {
+ websWrite(wp, T("ERROR: Group, \"%s\" is delete-protected."), group);
+ } else if (umGetGroupInUse(group)) {
+ websWrite(wp, T("ERROR: Group, \"%s\" is being used."), group);
+ } else if (umDeleteGroup(group) != 0) {
+ websWrite(wp, T("ERROR: Unable to delete group, \"%s\" "), group);
+ } else {
+ websWrite(wp, T("Group, \"%s\" was successfully deleted."), group);
+ }
+
+ websMsgEnd(wp);
+ websFooter(wp);
+ websDone(wp, 200);
+}
+
+/******************************************************************************/
+/*
+ * Generate HTML to create a list box containing the groups
+ */
+
+static int aspGenerateGroupList(int eid, webs_t wp, int argc, char_t **argv)
+{
+ char_t *group;
+ int row, nBytesSent, nBytes;
+
+ a_assert(wp);
+
+ row = 0;
+ nBytesSent = 0;
+ nBytes = websWrite(wp,
+ T("<SELECT NAME=\"group\" SIZE=\"3\" TITLE=\"Select a Group\">"));
+/*
+ * Add a special "<NONE>" element to allow de-selection
+ */
+ nBytes = websWrite(wp, T("<OPTION VALUE=\"\">[NONE]\n"));
+
+ group = umGetFirstGroup();
+ while (group && (nBytes > 0)) {
+ nBytes = websWrite(wp, T("<OPTION VALUE=\"%s\">%s\n"), group, group);
+ group = umGetNextGroup(group);
+ nBytesSent += nBytes;
+ }
+
+ nBytesSent += websWrite(wp, T("</SELECT>"));
+
+ return nBytesSent;
+}
+
+/******************************************************************************/
+/*
+ * Add an access limit
+ */
+
+static void formAddAccessLimit(webs_t wp, char_t *path, char_t *query)
+{
+ char_t *url, *method, *group, *secure, *ok;
+ int nCheck;
+ accessMeth_t am;
+ short nSecure;
+
+ a_assert(wp);
+
+ url = websGetVar(wp, T("url"), T(""));
+ group = websGetVar(wp, T("group"), T(""));
+ method = websGetVar(wp, T("method"), T(""));
+ secure = websGetVar(wp, T("secure"), T(""));
+ ok = websGetVar(wp, T("ok"), T(""));
+
+ websHeader(wp);
+ websMsgStart(wp);
+
+ if (gstricmp(ok, T("ok")) != 0) {
+ websWrite(wp, T("Add Access Limit Cancelled."));
+ } else if ((url == NULL) || (*url == 0)) {
+ websWrite(wp, T("ERROR: No URL was entered."));
+ } else if (umAccessLimitExists(url)) {
+ websWrite(wp, T("ERROR: An Access Limit for [%s] already exists."),
+ url);
+ } else {
+ if (method && *method) {
+ am = (accessMeth_t) gatoi(method);
+ } else {
+ am = AM_FULL;
+ }
+
+ if (secure && *secure) {
+ nSecure = (short) gatoi(secure);
+ } else {
+ nSecure = 0;
+ }
+
+ nCheck = umAddAccessLimit(url, am, nSecure, group);
+ if (nCheck != 0) {
+ websWrite(wp, T("Unable to add Access Limit for [%s]"), url);
+ } else {
+ websWrite(wp, T("Access limit for [%s], was successfully added."),
+ url);
+ }
+ }
+
+ websMsgEnd(wp);
+ websFooter(wp);
+ websDone(wp, 200);
+}
+
+/******************************************************************************/
+/*
+ * Delete an Access Limit
+ */
+
+static void formDeleteAccessLimit(webs_t wp, char_t *path, char_t *query)
+{
+ char_t *url, *ok;
+
+ a_assert(wp);
+
+ url = websGetVar(wp, T("url"), T(""));
+ ok = websGetVar(wp, T("ok"), T(""));
+
+ websHeader(wp);
+ websMsgStart(wp);
+
+ if (gstricmp(ok, T("ok")) != 0) {
+ websWrite(wp, T("Delete Access Limit Cancelled"));
+ } else if (umDeleteAccessLimit(url) != 0) {
+ websWrite(wp, T("ERROR: Unable to delete Access Limit for [%s]"),
+ url);
+ } else {
+ websWrite(wp, T("Access Limit for [%s], was successfully deleted."),
+ url);
+ }
+
+ websMsgEnd(wp);
+ websFooter(wp);
+ websDone(wp, 200);
+}
+
+/******************************************************************************/
+/*
+ * Generate HTML to create a list box containing the access limits
+ */
+
+static int aspGenerateAccessLimitList(int eid, webs_t wp,
+ int argc, char_t **argv)
+{
+ char_t *url;
+ int row, nBytesSent, nBytes;
+
+ a_assert(wp);
+
+ row = nBytesSent = 0;
+ url = umGetFirstAccessLimit();
+ nBytes = websWrite(wp,
+ T("<SELECT NAME=\"url\" SIZE=\"3\" TITLE=\"Select a URL\">"));
+
+ while (url && (nBytes > 0)) {
+ nBytes = websWrite(wp, T("<OPTION VALUE=\"%s\">%s\n"), url, url);
+ url = umGetNextAccessLimit(url);
+ nBytesSent += nBytes;
+ }
+
+ nBytesSent += websWrite(wp, T("</SELECT>"));
+
+ return nBytesSent;
+}
+
+/******************************************************************************/
+/*
+ * Generate HTML to create a list box containing the access methods
+ */
+
+static int aspGenerateAccessMethodList(int eid, webs_t wp,
+ int argc, char_t **argv)
+{
+ int nBytes;
+
+ a_assert(wp);
+
+ nBytes = websWrite(wp,
+ T("<SELECT NAME=\"method\" SIZE=\"3\" TITLE=\"Select a Method\">"));
+ nBytes += websWrite(wp, T("<OPTION VALUE=\"%d\">FULL ACCESS\n"),
+ AM_FULL);
+ nBytes += websWrite(wp, T("<OPTION VALUE=\"%d\">BASIC ACCESS\n"),
+ AM_BASIC);
+ nBytes += websWrite(wp, T("<OPTION VALUE=\"%d\" SELECTED>DIGEST ACCESS\n"),
+ AM_DIGEST);
+ nBytes += websWrite(wp, T("<OPTION VALUE=\"%d\">NO ACCESS\n"),
+ AM_NONE);
+ nBytes += websWrite(wp, T("</SELECT>"));
+
+ return nBytes;
+}
+/******************************************************************************/
+/*
+ * Generate HTML to create a list box containing privileges
+ */
+
+static int aspGeneratePrivilegeList(int eid, webs_t wp,
+ int argc, char_t **argv)
+{
+ int nBytes;
+
+ a_assert(wp);
+
+ nBytes = websWrite(wp, T("<SELECT NAME=\"privilege\" SIZE=\"3\" "));
+ nBytes += websWrite(wp, T("MULTIPLE TITLE=\"Choose Privileges\">"));
+ nBytes += websWrite(wp, T("<OPTION VALUE=\"%d\">READ\n"), PRIV_READ);
+ nBytes += websWrite(wp, T("<OPTION VALUE=\"%d\">EXECUTE\n"), PRIV_WRITE);
+ nBytes += websWrite(wp, T("<OPTION VALUE=\"%d\">ADMINISTRATE\n"),
+ PRIV_ADMIN);
+ nBytes += websWrite(wp, T("</SELECT>"));
+
+ return nBytes;
+}
+
+/******************************************************************************/
+/*
+ * Save the user management configuration to a file
+ */
+
+static void formSaveUserManagement(webs_t wp, char_t *path, char_t *query)
+{
+ char_t *ok;
+
+ a_assert(wp);
+
+ ok = websGetVar(wp, T("ok"), T(""));
+
+ websHeader(wp);
+ websMsgStart(wp);
+
+ if (gstricmp(ok, T("ok")) != 0) {
+ websWrite(wp, T("Save Cancelled."));
+ } else if (umCommit(NULL) != 0) {
+ websWrite(wp, T("ERROR: Unable to save user configuration."));
+ } else {
+ websWrite(wp, T("User configuration was saved successfully."));
+ }
+
+ websMsgEnd(wp);
+ websFooter(wp);
+ websDone(wp, 200);
+}
+
+/******************************************************************************/
+/*
+ * Load the user management configuration from a file
+ */
+
+static void formLoadUserManagement(webs_t wp, char_t *path, char_t *query)
+{
+ char_t *ok;
+
+ a_assert(wp);
+
+ ok = websGetVar(wp, T("ok"), T(""));
+
+ websHeader(wp);
+ websMsgStart(wp);
+
+ if (gstricmp(ok, T("ok")) != 0) {
+ websWrite(wp, T("Load Cancelled."));
+ } else if (umRestore(NULL) != 0) {
+ websWrite(wp, T("ERROR: Unable to load user configuration."));
+ } else {
+ websWrite(wp, T("User configuration was re-loaded successfully."));
+ }
+
+ websMsgEnd(wp);
+ websFooter(wp);
+ websDone(wp, 200);
+}
+
+/******************************************************************************/
+/*
+ * Message start and end convenience functions
+ */
+
+static void websMsgStart(webs_t wp)
+{
+ websWrite(wp, MSG_START);
+}
+
+static void websMsgEnd(webs_t wp)
+{
+ websWrite(wp, MSG_END);
+}
+
+/******************************************************************************/
diff --git a/cpukit/httpd/url.c b/cpukit/httpd/url.c
new file mode 100644
index 0000000000..07a99cc843
--- /dev/null
+++ b/cpukit/httpd/url.c
@@ -0,0 +1,212 @@
+/*
+ * url.c -- Parse URLs
+ *
+ * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for usage and redistribution license requirements
+ *
+ * $Id$
+ */
+
+/******************************** Description *********************************/
+
+/*
+ * This module parses URLs into their components.
+ */
+
+/********************************* Includes ***********************************/
+
+#include "wsIntrn.h"
+
+/********************************* Statics ************************************/
+/*
+ * htmExt is declared in this way to avoid a Linux and Solaris segmentation
+ * fault when a constant string is passed to strlower which could change its
+ * argument.
+ */
+
+char_t htmExt[] = T(".htm");
+
+
+/*********************************** Code *************************************/
+/*
+ * Return the mime type for the given URL given a URL.
+ * The caller supplies the buffer to hold the result.
+ * charCnt is the number of characters the buffer will hold, ascii or UNICODE.
+ */
+
+char_t *websUrlType(char_t *url, char_t *buf, int charCnt)
+{
+ sym_t *sp;
+ char_t *ext, *parsebuf;
+
+ a_assert(url && *url);
+ a_assert(buf && charCnt > 0);
+
+ if (url == NULL || *url == '\0') {
+ gstrcpy(buf, T("text/plain"));
+ return buf;
+ }
+ if (websUrlParse(url, &parsebuf, NULL, NULL, NULL, NULL, NULL,
+ NULL, &ext) < 0) {
+ gstrcpy(buf, T("text/plain"));
+ return buf;
+ }
+ strlower(ext);
+
+/*
+ * Lookup the mime type symbol table to find the relevant content type
+ */
+ if ((sp = symLookup(websMime, ext)) != NULL) {
+ gstrncpy(buf, sp->content.value.string, charCnt);
+ } else {
+ gstrcpy(buf, T("text/plain"));
+ }
+ bfree(B_L, parsebuf);
+ return buf;
+}
+
+/******************************************************************************/
+/*
+ * Parse the URL. A buffer is allocated to store the parsed URL in *pbuf.
+ * This must be freed by the caller. NOTE: tag is not yet fully supported.
+ */
+
+int websUrlParse(char_t *url, char_t **pbuf, char_t **phost, char_t **ppath,
+ char_t **pport, char_t **pquery, char_t **pproto, char_t **ptag,
+ char_t **pext)
+{
+ char_t *tok, *cp, *host, *path, *port, *proto, *tag, *query, *ext;
+ char_t *last_delim, *hostbuf, *portbuf, *buf;
+ int c, len, ulen;
+
+ a_assert(url);
+ a_assert(pbuf);
+
+ ulen = gstrlen(url);
+/*
+ * We allocate enough to store separate hostname and port number fields.
+ * As there are 3 strings in the one buffer, we need room for 3 null chars.
+ * We allocate MAX_PORT_LEN char_t's for the port number.
+ */
+ len = ulen * 2 + MAX_PORT_LEN + 3;
+ if ((buf = balloc(B_L, len * sizeof(char_t))) == NULL) {
+ return -1;
+ }
+ portbuf = &buf[len - MAX_PORT_LEN - 1];
+ hostbuf = &buf[ulen+1];
+ gstrcpy(buf, url);
+ url = buf;
+
+/*
+ * Convert the current listen port to a string. We use this if the URL has
+ * no explicit port setting
+ */
+ stritoa(websGetPort(), portbuf, MAX_PORT_LEN);
+ port = portbuf;
+ path = T("/");
+ proto = T("http");
+ host = T("localhost");
+ query = T("");
+ ext = htmExt;
+ tag = T("");
+
+ if (gstrncmp(url, T("http://"), 7) == 0) {
+ tok = &url[7];
+ tok[-3] = '\0';
+ proto = url;
+ host = tok;
+ for (cp = tok; *cp; cp++) {
+ if (*cp == '/') {
+ break;
+ }
+ if (*cp == ':') {
+ *cp++ = '\0';
+ port = cp;
+ tok = cp;
+ }
+ }
+ if ((cp = gstrchr(tok, '/')) != NULL) {
+/*
+ * If a full URL is supplied, we need to copy the host and port
+ * portions into static buffers.
+ */
+ c = *cp;
+ *cp = '\0';
+ gstrncpy(hostbuf, host, ulen);
+ gstrncpy(portbuf, port, MAX_PORT_LEN);
+ *cp = c;
+ host = hostbuf;
+ port = portbuf;
+ path = cp;
+ tok = cp;
+ }
+
+ } else {
+ path = url;
+ tok = url;
+ }
+
+/*
+ * Parse the query string
+ */
+ if ((cp = gstrchr(tok, '?')) != NULL) {
+ *cp++ = '\0';
+ query = cp;
+ path = tok;
+ tok = query;
+ }
+
+/*
+ * Parse the fragment identifier
+ */
+ if ((cp = gstrchr(tok, '#')) != NULL) {
+ *cp++ = '\0';
+ if (*query == 0) {
+ path = tok;
+ }
+ }
+
+/*
+ * Only do the following if asked for the extension
+ */
+ if (pext) {
+ if ((cp = gstrrchr(path, '.')) != NULL) {
+ if ((last_delim = gstrrchr(path, '/')) != NULL) {
+ if (last_delim > cp) {
+ ext = htmExt;
+ } else {
+ ext = cp;
+ }
+ } else {
+ ext = cp;
+ }
+ } else {
+ if (path[gstrlen(path) - 1] == '/') {
+ ext = htmExt;
+ }
+ }
+ }
+
+/*
+ * Pass back the fields requested (if not NULL)
+ */
+ if (phost)
+ *phost = host;
+ if (ppath)
+ *ppath = path;
+ if (pport)
+ *pport = port;
+ if (pproto)
+ *pproto = proto;
+ if (pquery)
+ *pquery = query;
+ if (ptag)
+ *ptag = tag;
+ if (pext)
+ *pext = ext;
+ *pbuf = buf;
+ return 0;
+}
+
+/******************************************************************************/
diff --git a/cpukit/httpd/value.c b/cpukit/httpd/value.c
new file mode 100644
index 0000000000..ac21ec6afe
--- /dev/null
+++ b/cpukit/httpd/value.c
@@ -0,0 +1,1213 @@
+/*
+ * value.c -- Generic type (holds all types)
+ *
+ * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
+ *
+ * $Id$
+ */
+
+/******************************** Description *********************************/
+
+/*
+ * This module provides a generic type that can hold all possible types.
+ * It is designed to provide maximum effeciency.
+ */
+
+/********************************* Includes ***********************************/
+
+#ifdef UEMF
+ #include "uemf.h"
+#else
+ #include "basic/basicInternal.h"
+#endif
+
+/*********************************** Locals ***********************************/
+#ifndef UEMF
+static value_t value_null; /* All zeros */
+
+/***************************** Forward Declarations ***************************/
+
+static void coerce_types(value_t* v1, value_t* v2);
+static int value_to_integer(value_t* vp);
+#endif /*!UEMF*/
+/*********************************** Code *************************************/
+/*
+ * Initialize a integer value.
+ */
+
+value_t valueInteger(long value)
+{
+ value_t v;
+
+ memset(&v, 0x0, sizeof(v));
+ v.valid = 1;
+ v.type = integer;
+ v.value.integer = value;
+ return v;
+}
+
+/******************************************************************************/
+/*
+ * Initialize a string value.
+ */
+
+value_t valueString(char_t* value, int flags)
+{
+ value_t v;
+
+ memset(&v, 0x0, sizeof(v));
+ v.valid = 1;
+ v.type = string;
+ if (flags & VALUE_ALLOCATE) {
+ v.allocated = 1;
+ v.value.string = gstrdup(B_L, value);
+ } else {
+ v.allocated = 0;
+ v.value.string = value;
+ }
+ return v;
+}
+
+/******************************************************************************/
+/*
+ * Free any storage allocated for a value.
+ */
+
+void valueFree(value_t* v)
+{
+ if (v->valid && v->allocated && v->type == string &&
+ v->value.string != NULL) {
+ bfree(B_L, v->value.string);
+ }
+#ifndef UEMF
+ if (v->valid && v->type == symbol && v->value.symbol.data != NULL &&
+ v->value.symbol.freeCb !=NULL) {
+ v->value.symbol.freeCb(v->value.symbol.data);
+ }
+#endif
+ v->type = undefined;
+ v->valid = 0;
+ v->allocated = 0;
+}
+
+#ifndef UEMF
+
+/******************************************************************************/
+/*
+ * Initialize an invalid value.
+ */
+
+value_t valueInvalid()
+{
+ value_t v;
+ v.valid = 0;
+ v.type = undefined;
+ return v;
+}
+
+/******************************************************************************/
+/*
+ * Initialize a flag value.
+ */
+
+value_t valueBool(int value)
+{
+ value_t v;
+
+ memset(&v, 0x0, sizeof(v));
+ v.type = flag;
+ v.valid = 1;
+ v.value.flag = (char) value;
+ return v;
+}
+
+/******************************************************************************/
+/*
+ * Initialize a byteint value.
+ */
+
+value_t valueByteint(char value)
+{
+ value_t v;
+
+ memset(&v, 0x0, sizeof(v));
+ v.valid = 1;
+ v.type = byteint;
+ v.value.byteint = value;
+ return v;
+}
+
+/******************************************************************************/
+/*
+ * Initialize a shortint value.
+ */
+
+value_t valueShortint(short value)
+{
+ value_t v;
+
+ memset(&v, 0x0, sizeof(v));
+ v.valid = 1;
+ v.type = shortint;
+ v.value.shortint = value;
+ return v;
+}
+
+#ifdef FLOATING_POINT_SUPPORT
+/******************************************************************************/
+/*
+ * Initialize a floating value.
+ */
+
+value_t valueFloating(double value)
+{
+ value_t v;
+
+ memset(&v, 0x0, sizeof(v));
+ v.valid = 1;
+ v.type = floating;
+ v.value.floating = value;
+ return v;
+}
+#endif /* FLOATING_POINT_SUPPORT */
+
+/******************************************************************************/
+/*
+ * Initialize a big value.
+ */
+
+value_t valueBig(long high_word, long low_word)
+{
+ value_t v;
+
+ memset(&v, 0x0, sizeof(v));
+ v.valid = 1;
+ v.type = big;
+ v.value.big[BLOW] = low_word;
+ v.value.big[BHIGH] = high_word;
+ return v;
+}
+
+/******************************************************************************/
+/*
+ * Initialize a hex value.
+ */
+
+value_t valueHex(int value)
+{
+ value_t v;
+
+ memset(&v, 0x0, sizeof(v));
+ v.valid = 1;
+ v.type = hex;
+ v.value.integer = value;
+ return v;
+}
+
+/******************************************************************************/
+/*
+ * Initialize a octal value.
+ */
+
+value_t valueOctal(int value)
+{
+ value_t v;
+
+ memset(&v, 0x0, sizeof(v));
+ v.valid = 1;
+ v.type = octal;
+ v.value.integer = value;
+ return v;
+}
+
+/******************************************************************************/
+/*
+ * Initialize a percent value.
+ */
+
+value_t valuePercent(int value)
+{
+ value_t v;
+
+ memset(&v, 0x0, sizeof(v));
+ v.valid = 1;
+ v.type = percent;
+ v.value.percent = (char) value;
+ return v;
+}
+
+/******************************************************************************/
+/*
+ * Initialize an byte array. Note: no allocation, just store the ptr
+ */
+
+value_t valueBytes(char* value, int flags)
+{
+ value_t v;
+
+ memset(&v, 0x0, sizeof(v));
+ v.valid = 1;
+ v.type = bytes;
+ if (flags & VALUE_ALLOCATE) {
+ v.allocated = 1;
+ v.value.bytes = bstrdupA(B_L, value);
+ } else {
+ v.allocated = 0;
+ v.value.bytes = value;
+ }
+ return v;
+}
+
+/******************************************************************************/
+/*
+ * Initialize a symbol value.
+ * Value parameter can hold a pointer to any type of value
+ * Free parameter can be NULL, or a function pointer to a function that will
+ * free the value
+ */
+
+value_t valueSymbol(void *value, freeCallback freeCb)
+{
+ value_t v;
+
+ memset(&v, 0x0, sizeof(v));
+ v.valid = 1;
+ v.type = symbol;
+ v.value.symbol.data = value;
+ v.value.symbol.freeCb = freeCb;
+ return v;
+}
+
+/******************************************************************************/
+/*
+ * Initialize an error message value.
+ */
+
+value_t valueErrmsg(char_t* value)
+{
+ value_t v;
+
+ memset(&v, 0x0, sizeof(v));
+ v.valid = 1;
+ v.type = errmsg;
+ v.value.errmsg = value;
+ return v;
+}
+
+/******************************************************************************/
+/*
+ * Copy a value. If the type is 'string' then allocate another string.
+ * Note: we allow the copy of a null value.
+ */
+
+value_t valueCopy(value_t v2)
+{
+ value_t v1;
+
+ v1 = v2;
+ if (v2.valid && v2.type == string && v2.value.string != NULL) {
+ v1.value.string = gstrdup(B_L, v2.value.string);
+ v1.allocated = 1;
+ }
+ return v1;
+}
+
+
+/******************************************************************************/
+/*
+ * Add a value.
+ */
+
+value_t valueAdd(value_t v1, value_t v2)
+{
+ value_t v;
+
+ a_assert(v1.valid);
+ a_assert(v2.valid);
+
+ memset(&v, 0x0, sizeof(v));
+ v.valid = 1;
+
+ if (v1.type != v2.type)
+ coerce_types(&v1, &v2);
+
+ switch (v1.type) {
+ default:
+ case string:
+ case bytes:
+ a_assert(0);
+ break;
+
+#ifdef FLOATING_POINT_SUPPORT
+ case floating:
+ v1.value.floating += v2.value.floating;
+ return v1;
+#endif
+
+ case flag:
+ v1.value.bool |= v2.value.flag;
+ return v1;
+
+ case byteint:
+ case percent:
+ v1.value.byteint += v2.value.byteint;
+ return v1;
+
+ case shortint:
+ v1.value.shortint += v2.value.shortint;
+ return v1;
+
+ case hex:
+ case integer:
+ case octal:
+ v1.value.integer += v2.value.integer;
+ return v1;
+
+ case big:
+ v.type = big;
+ badd(v.value.big, v1.value.big, v2.value.big);
+ return v;
+ }
+
+ return v1;
+}
+
+
+/******************************************************************************/
+/*
+ * Subtract a value.
+ */
+
+value_t valueSub(value_t v1, value_t v2)
+{
+ value_t v;
+
+ a_assert(v1.valid);
+ a_assert(v2.valid);
+
+ memset(&v, 0x0, sizeof(v));
+ v.valid = 1;
+
+ if (v1.type != v2.type)
+ coerce_types(&v1, &v2);
+ switch (v1.type) {
+ default:
+ a_assert(0);
+ break;
+
+#ifdef FLOATING_POINT_SUPPORT
+ case floating:
+ v1.value.floating -= v2.value.floating;
+ return v1;
+#endif
+
+ case flag:
+ v1.value.flag &= v2.value.flag;
+ return v1;
+
+ case byteint:
+ case percent:
+ v1.value.byteint -= v2.value.byteint;
+ return v1;
+
+ case shortint:
+ v1.value.shortint -= v2.value.shortint;
+ return v1;
+
+ case hex:
+ case integer:
+ case octal:
+ v1.value.integer -= v2.value.integer;
+ return v1;
+
+ case big:
+ v.type = big;
+ bsub(v.value.big, v1.value.big, v2.value.big);
+ return v;
+ }
+
+ return v1;
+}
+
+
+/******************************************************************************/
+/*
+ * Multiply a value.
+ */
+
+value_t valueMul(value_t v1, value_t v2)
+{
+ value_t v;
+
+ a_assert(v1.valid);
+ a_assert(v2.valid);
+
+ memset(&v, 0x0, sizeof(v));
+ v.valid = 1;
+
+ if (v1.type != v2.type)
+ coerce_types(&v1, &v2);
+ switch (v1.type) {
+ default:
+ a_assert(0);
+ break;
+
+ case flag:
+ a_assert(v1.type != flag);
+ break;
+
+#ifdef FLOATING_POINT_SUPPORT
+ case floating:
+ v1.value.floating *= v2.value.floating;
+ return v1;
+#endif
+
+ case byteint:
+ case percent:
+ v1.value.byteint *= v2.value.byteint;
+ return v1;
+
+ case shortint:
+ v1.value.shortint *= v2.value.shortint;
+ return v1;
+
+ case hex:
+ case integer:
+ case octal:
+ v1.value.integer *= v2.value.integer;
+ return v1;
+
+ case big:
+ v.type = big;
+ bmul(v.value.big, v1.value.big, v2.value.big);
+ return v;
+ }
+
+ return v1;
+}
+
+
+/******************************************************************************/
+/*
+ * Divide a value.
+ */
+
+value_t valueDiv(value_t v1, value_t v2)
+{
+ value_t v;
+
+ a_assert(v1.valid);
+ a_assert(v2.valid);
+
+ memset(&v, 0x0, sizeof(v));
+ v.valid = 1;
+
+ if (v1.type != v2.type)
+ coerce_types(&v1, &v2);
+ switch (v1.type) {
+ default:
+ a_assert(0);
+ break;
+
+ case flag:
+ a_assert(v1.type != flag);
+ break;
+
+#ifdef FLOATING_POINT_SUPPORT
+ case floating:
+ v1.value.floating /= v2.value.floating;
+ return v1;
+#endif
+
+ case byteint:
+ case percent:
+ v1.value.byteint /= v2.value.byteint;
+ return v1;
+
+ case shortint:
+ v1.value.shortint /= v2.value.shortint;
+ return v1;
+
+ case hex:
+ case integer:
+ case octal:
+ v1.value.integer /= v2.value.integer;
+ return v1;
+
+ case big:
+ v.type = big;
+ bdiv(v.value.big, v1.value.big, v2.value.big);
+ return v;
+ }
+
+ return v1;
+}
+
+
+/******************************************************************************/
+/*
+ * Compare a value.
+ */
+
+int valueCmp(value_t v1, value_t v2)
+{
+ a_assert(v1.valid);
+ a_assert(v2.valid);
+
+ if (v1.type != v2.type)
+ coerce_types(&v1, &v2);
+ if (v1.type != v2.type) {
+/*
+ * Make v2 == v1
+ */
+ a_assert(v1.type == v2.type);
+ v2 = v1;
+ return 0;
+ }
+ switch (v1.type) {
+ case string:
+ if (v1.value.string == NULL && v2.value.string == NULL) {
+ return 0;
+ } else if (v1.value.string == NULL) {
+ return -1;
+ } else if (v2.value.string == NULL) {
+ return 1;
+ } else {
+ return gstrcmp(v1.value.string, v2.value.string);
+ }
+ /* Nobody here */
+
+ case flag:
+ if (v1.value.flag < v2.value.flag)
+ return -1;
+ else if (v1.value.flag == v2.value.flag)
+ return 0;
+ else return 1;
+
+#ifdef FLOATING_POINT_SUPPORT
+ case floating:
+ if (v1.value.floating < v2.value.floating)
+ return -1;
+ else if (v1.value.floating == v2.value.floating)
+ return 0;
+ else return 1;
+#endif
+
+ case byteint:
+ case percent:
+ if (v1.value.byteint < v2.value.byteint)
+ return -1;
+ else if (v1.value.byteint == v2.value.byteint)
+ return 0;
+ else return 1;
+
+ case shortint:
+ if (v1.value.shortint < v2.value.shortint)
+ return -1;
+ else if (v1.value.shortint == v2.value.shortint)
+ return 0;
+ else return 1;
+
+ case hex:
+ case integer:
+ case octal:
+ if (v1.value.integer < v2.value.integer)
+ return -1;
+ else if (v1.value.integer == v2.value.integer)
+ return 0;
+ else return 1;
+
+ case big:
+ return bcompare(v1.value.big, v2.value.big);
+
+ default:
+ a_assert(0);
+ return 0;
+ }
+}
+
+
+/******************************************************************************/
+/*
+ * If type mismatch, then coerce types to big.
+ * Note: Known bug, casting of negative bigs to floats doesn't work.
+ */
+
+static void coerce_types(register value_t* v1, register value_t* v2)
+{
+#ifdef FLOATING_POINT_SUPPORT
+ if (v1->type == floating) {
+ v2->type = floating;
+ v2->value.floating = (double) v2->value.integer;
+ if (v2->type == big)
+ v2->value.floating = (double) v2->value.big[BLOW] +
+ (double) v2->value.big[BHIGH] * (double) MAXINT;
+
+ } else if (v2->type == floating) {
+ v1->type = floating;
+ v1->value.floating = (double) v1->value.integer;
+ if (v1->type == big)
+ v1->value.floating = (double) v1->value.big[BLOW] +
+ (double) v1->value.big[BHIGH] * (double) MAXINT;
+
+ } else if (v1->type == big) {
+#else
+ if (v1->type == big) {
+#endif /* FLOATING_POINT_SUPPORT */
+ v2->value.big[BLOW] = value_to_integer(v2);
+ if (valueNegative(v2))
+ v2->value.big[BHIGH] = -1;
+ else
+ v2->value.big[BHIGH] = 0;
+ v2->type = big;
+
+ } else if (v2->type == big) {
+ if (valueNegative(v1))
+ v1->value.big[BHIGH] = -1;
+ else
+ v1->value.big[BHIGH] = 0;
+ v1->value.big[BLOW] = value_to_integer(v1);
+ v1->type = big;
+
+
+ } else if (v1->type == integer) {
+ v2->value.integer = value_to_integer(v2);
+ v2->type = integer;
+
+ } else if (v2->type == integer) {
+ v1->value.integer = value_to_integer(v1);
+ v1->type = integer;
+
+ } else if (v1->type != integer) {
+ v2->type = v1->type;
+
+ } else if (v2->type != integer) {
+ v1->type = v2->type;
+
+ }
+ a_assert(v1->type == v2->type);
+}
+
+
+/******************************************************************************/
+/*
+ * Return true if the value is numeric and negative. Otherwise return 0.
+ */
+
+int valueNegative(value_t* vp)
+{
+ switch (vp->type) {
+ default:
+ case string:
+ case bytes:
+ return 0;
+
+#ifdef FLOATING_POINT_SUPPORT
+ case floating:
+ if (vp->value.floating < 0)
+ return 1;
+ return 0;
+#endif
+
+ case flag:
+ if ((signed char)vp->value.flag < 0)
+ return 1;
+ return 0;
+
+ case byteint:
+ case percent:
+ if ((signed char)vp->value.byteint < 0)
+ return 1;
+ return 0;
+
+ case shortint:
+ if (vp->value.shortint < 0)
+ return 1;
+ return 0;
+
+ case hex:
+ case integer:
+ case octal:
+ if (vp->value.integer < 0)
+ return 1;
+ return 0;
+
+ case big:
+ if (vp->value.big[BHIGH] < 0)
+ return 1;
+ return 0;
+ }
+}
+
+/******************************************************************************/
+/*
+ * Return true if the value is numeric and zero. Otherwise return 0.
+ */
+
+int valueZero(value_t* vp)
+{
+ switch (vp->type) {
+ default:
+ case string:
+ case bytes:
+ return 0;
+
+#ifdef FLOATING_POINT_SUPPORT
+ case floating:
+ if (vp->value.floating == 0)
+ return 1;
+ return 0;
+#endif
+
+ case flag:
+ if (vp->value.flag == 0)
+ return 1;
+ return 0;
+
+ case byteint:
+ case percent:
+ if (vp->value.byteint == 0)
+ return 1;
+ return 0;
+
+ case shortint:
+ if (vp->value.shortint == 0)
+ return 1;
+ return 0;
+
+ case hex:
+ case integer:
+ case octal:
+ if (vp->value.integer == 0)
+ return 1;
+ return 0;
+
+ case big:
+ if (vp->value.big[BHIGH] == 0 && vp->value.big[BLOW] == 0)
+ return 1;
+ return 0;
+ }
+}
+
+
+/******************************************************************************/
+/*
+ * Cast a value to an integer. Cannot be called for floating, non-numerics
+ * or bigs.
+ */
+
+static int value_to_integer(value_t* vp)
+{
+ switch (vp->type) {
+ default:
+ case string:
+ case bytes:
+ case big:
+#ifdef FLOATING_POINT_SUPPORT
+ case floating:
+ a_assert(0);
+ return -1;
+#endif
+
+ case flag:
+ return (int) vp->value.flag;
+
+ case byteint:
+ case percent:
+ return (int) vp->value.byteint;
+
+ case shortint:
+ return (int) vp->value.shortint;
+
+ case hex:
+ case integer:
+ case octal:
+ return (int) vp->value.integer;
+ }
+}
+
+
+/******************************************************************************/
+/*
+ * Convert a value to a text based representation of its value
+ */
+
+void valueSprintf(char_t** out, int size, char_t* fmt, value_t vp)
+{
+ char_t *src, *dst, *tmp, *dst_start;
+
+ a_assert(out);
+
+ *out = NULL;
+
+ if (! vp.valid) {
+ *out = bstrdup(B_L, T("Invalid"));
+ return;
+ }
+
+ switch (vp.type) {
+ case flag:
+ if (fmt == NULL || *fmt == '\0') {
+ *out = bstrdup(B_L, (vp.value.flag) ? T("true") : T("false"));
+ } else {
+ fmtAlloc(out, size, fmt, (vp.value.flag) ? T("true") : T("false"));
+ }
+ break;
+
+#ifdef FLOATING_POINT_SUPPORT
+ case floating:
+ if (fmt == NULL || *fmt == '\0') {
+ fmtAlloc(out, size, T("%f"), vp.value.floating);
+ } else {
+ fmtAlloc(out, size, fmt, vp.value.floating);
+ }
+ break;
+#endif
+
+ case hex:
+ if (fmt == NULL || *fmt == '\0') {
+ fmtAlloc(out, size, T("0x%lx"), vp.value.hex);
+ } else {
+ fmtAlloc(out, size, fmt, vp.value.hex);
+ }
+ break;
+
+ case big:
+ if (*out == NULL) {
+ *out = btoa(vp.value.big, NULL, 0);
+ } else {
+ btoa(vp.value.big, *out, size);
+ }
+ break;
+
+ case integer:
+ if (fmt == NULL || *fmt == '\0') {
+ fmtAlloc(out, size, T("%ld"), vp.value.integer);
+ } else {
+ fmtAlloc(out, size, fmt, vp.value.integer);
+ }
+ break;
+
+ case octal:
+ if (fmt == NULL || *fmt == '\0') {
+ fmtAlloc(out, size, T("0%lo"), vp.value.octal);
+ } else {
+ fmtAlloc(out, size, fmt, vp.value.octal);
+ }
+ break;
+
+ case percent:
+ if (fmt == NULL || *fmt == '\0') {
+ fmtAlloc(out, size, T("%d%%"), vp.value.percent);
+ } else {
+ fmtAlloc(out, size, fmt, vp.value.percent);
+ }
+ break;
+
+ case byteint:
+ if (fmt == NULL || *fmt == '\0') {
+ fmtAlloc(out, size, T("%d"), (int) vp.value.byteint);
+ } else {
+ fmtAlloc(out, size, fmt, (int) vp.value.byteint);
+ }
+ break;
+
+ case shortint:
+ if (fmt == NULL || *fmt == '\0') {
+ fmtAlloc(out, size, T("%d"), (int) vp.value.shortint);
+ } else {
+ fmtAlloc(out, size, fmt, (int) vp.value.shortint);
+ }
+ break;
+
+ case string:
+ case errmsg:
+ src = vp.value.string;
+
+ if (src == NULL) {
+ *out = bstrdup(B_L, T("NULL"));
+ } else if (fmt && *fmt) {
+ fmtAlloc(out, size, fmt, src);
+
+ } else {
+
+ *out = balloc(B_L, size);
+ dst_start = dst = *out;
+ for (; *src != '\0'; src++) {
+ if (dst >= &dst_start[VALUE_MAX_STRING - 5])
+ break;
+ switch (*src) {
+ case '\a': *dst++ = '\\'; *dst++ = 'a'; break;
+ case '\b': *dst++ = '\\'; *dst++ = 'b'; break;
+ case '\f': *dst++ = '\\'; *dst++ = 'f'; break;
+ case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
+ case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
+ case '\t': *dst++ = '\\'; *dst++ = 't'; break;
+ case '\v': *dst++ = '\\'; *dst++ = 'v'; break;
+ case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
+ case '"': *dst++ = '\\'; *dst++ = '\"'; break;
+ default:
+ if (gisprint(*src)) {
+ *dst++ = *src;
+ } else {
+ fmtAlloc(&tmp, size, T("\\x%02x"),
+ (unsigned int) *src);
+ gstrcpy(dst, tmp);
+ bfreeSafe(B_L, tmp);
+ dst += 4;
+ }
+ break;
+ }
+ }
+ *dst++ = '\0';
+ }
+ break;
+
+#ifdef UNUSED
+ case bytes:
+ asrc = vp.value.bytes;
+
+ if (asrc == NULL) {
+ *out = bstrdup(B_L, T("NULL"));
+
+ } else if (fmt && *fmt) {
+ fmtAlloc(out, size, fmt, asrc);
+
+ } else {
+
+ dst_start = dst;
+ for (; *asrc != '\0'; asrc++) {
+ if (dst >= &dst_start[VALUE_MAX_STRING - 5])
+ break;
+ switch (*asrc) {
+ case '\a': *dst++ = '\\'; *dst++ = 'a'; break;
+ case '\b': *dst++ = '\\'; *dst++ = 'b'; break;
+ case '\f': *dst++ = '\\'; *dst++ = 'f'; break;
+ case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
+ case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
+ case '\t': *dst++ = '\\'; *dst++ = 't'; break;
+ case '\v': *dst++ = '\\'; *dst++ = 'v'; break;
+ case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
+ case '"': *dst++ = '\\'; *dst++ = '\"'; break;
+ default:
+ if (gisprint(*asrc)) {
+ *dst++ = *asrc;
+ } else {
+ fmtAlloc(dst, size,
+ T("\\x%02x"), (unsigned int) *asrc);
+ dst += 4;
+ }
+ break;
+ }
+ }
+ *dst++ = '\0';
+ }
+ break;
+#endif
+
+ default:
+ a_assert(0);
+ }
+}
+
+/******************************************************************************/
+/*
+ * Print a value to the named file descriptor
+ */
+
+void valueFprintf(FILE* fp, char_t* fmt, value_t vp)
+{
+ char_t *buf;
+
+ buf = NULL;
+ valueSprintf(&buf, VALUE_MAX_STRING, fmt, vp);
+ gfputs(buf, fp);
+ bfreeSafe(B_L, buf);
+ fflush(fp);
+}
+
+/******************************************************************************/
+/*
+ * Ascii to value conversion
+ */
+
+value_t valueAtov(char_t* s, int pref_type)
+{
+ vtype_t type;
+ value_t v;
+ long tmp[2], tmp2[2], base[2];
+ int i, len, num;
+
+ a_assert(0 <= pref_type && pref_type < 99); /* Sanity check */
+ a_assert(s);
+
+ v = value_null;
+ if (s == NULL) {
+ return value_null;
+ }
+
+ base[BLOW] = 10;
+ base[BHIGH] = 0;
+ len = gstrlen(s);
+
+/*
+ * Determine the value type
+ */
+ type = undefined;
+ if (pref_type <= 0) {
+ if (gisdigit(*s)) {
+ base[BHIGH] = 0;
+ if (s[len - 1] == '%') {
+ type = percent;
+ len --;
+ base[BLOW] = 10;
+ } else if (*s == '0') {
+ if (s[1] == 'x') {
+ type = hex;
+ s += 2;
+ len -= 2;
+ base[BLOW] = 16;
+ } else if (s[1] == '\0') {
+ type = integer;
+ base[BLOW] = 10;
+ } else {
+ type = octal;
+ s++;
+ len--;
+ base[BLOW] = 8;
+ }
+ } else {
+ type = integer;
+ base[BLOW] = 10;
+ }
+
+ } else {
+ if (gstrcmp(s, T("true")) == 0 || gstrcmp(s, T("false")) == 0) {
+ type = flag;
+ } else if (*s == '\'' && s[len - 1] == '\'') {
+ type = string;
+ s++;
+ len -= 2;
+ } else if (*s == '\"' && s[len - 1] == '\"') {
+ type = string;
+ s++;
+ len -= 2;
+ } else {
+ type = string;
+ }
+ }
+ v.type = type;
+
+ } else
+ v.type = pref_type;
+ v.valid = 1;
+
+/*
+ * Do the conversion. Always use big arithmetic
+ */
+ switch (v.type) {
+ case hex:
+ if (!isdigit(s[0])) {
+ if (gtolower(s[0]) >= 'a' || gtolower(s[0]) <= 'f') {
+ v.value.big[BLOW] = 10 + gtolower(s[0]) - 'a';
+ } else {
+ v.value.big[BLOW] = 0;
+ }
+ } else {
+ v.value.big[BLOW] = s[0] - '0';
+ }
+ v.value.big[BHIGH] = 0;
+ for (i = 1; i < len; i++) {
+ if (!isdigit(s[i])) {
+ if (gtolower(s[i]) < 'a' || gtolower(s[i]) > 'f') {
+ break;
+ }
+ num = 10 + gtolower(s[i]) - 'a';
+ } else {
+ num = s[i] - '0';
+ }
+ bmul(tmp, v.value.big, base);
+ binit(tmp2, 0, num);
+ badd(v.value.big, tmp, tmp2);
+ }
+ v.value.hex = v.value.big[BLOW];
+ break;
+
+ case shortint:
+ case byteint:
+ case integer:
+ case percent:
+ case octal:
+ case big:
+ v.value.big[BHIGH] = 0;
+ if (gisdigit(s[0]))
+ v.value.big[BLOW] = s[0] - '0';
+ else
+ v.value.big[BLOW] = 0;
+ for (i = 1; i < len && gisdigit(s[i]); i++) {
+ bmul(tmp, v.value.big, base);
+ binit(tmp2, 0, s[i] - '0');
+ badd(v.value.big, tmp, tmp2);
+ }
+ switch (v.type) {
+ case shortint:
+ v.value.shortint = (short) v.value.big[BLOW];
+ break;
+ case byteint:
+ v.value.byteint = (char) v.value.big[BLOW];
+ break;
+ case integer:
+ v.value.integer = (int) v.value.big[BLOW];
+ break;
+ case percent:
+ v.value.percent = (char) v.value.big[BLOW];
+ break;
+ case octal:
+ v.value.octal = (int) v.value.big[BLOW];
+ break;
+ default:
+ break;
+ }
+ break;
+
+#ifdef FLOATING_POINT_SUPPORT
+ case floating:
+ gsscanf(s, T("%f"), &v.value.floating);
+ break;
+#endif
+
+ case flag:
+ if (*s == 't')
+ v.value.flag = 1;
+ else v.value.flag = 0;
+ break;
+
+ case string:
+/*
+ * Note this always ballocs a string
+ */
+ v = valueString(s, VALUE_ALLOCATE);
+ break;
+
+ case bytes:
+ v = valueBytes((char*) s, VALUE_ALLOCATE);
+ break;
+
+#ifdef UNUSED
+ case literal:
+ v = value_literal(bstrdup(B_L, s));
+ v.value.literal[len] = '\0';
+ break;
+#endif
+
+ case undefined:
+ case symbol:
+ default:
+ v.valid = 0;
+ a_assert(0);
+ }
+ return v;
+}
+
+#endif /* !UEMF */
+/******************************************************************************/
diff --git a/cpukit/httpd/wbase64.c b/cpukit/httpd/wbase64.c
new file mode 100644
index 0000000000..87659eeb6a
--- /dev/null
+++ b/cpukit/httpd/wbase64.c
@@ -0,0 +1,149 @@
+/*
+ * base64.c -- Base64 Mime encoding
+ *
+ * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for usage and redistribution license requirements
+ *
+ * $Id$
+ */
+
+/******************************** Description *********************************/
+
+/*
+ * The base64 command encodes and decodes a string in mime base64 format
+ */
+
+/********************************* Includes ***********************************/
+
+#include "wsIntrn.h"
+
+/******************************** Local Data **********************************/
+/*
+ * Mapping of ANSI chars to base64 Mime encoding alphabet (see below)
+ */
+
+static char_t map64[] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
+ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
+ -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+};
+
+static char_t alphabet64[] = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+ 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
+ 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+ 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+ 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+ 'w', 'x', 'y', 'z', '0', '1', '2', '3',
+ '4', '5', '6', '7', '8', '9', '+', '/',
+};
+
+/*********************************** Code *************************************/
+/*
+ * Decode a buffer from "string" and into "outbuf"
+ */
+
+int websDecode64(char_t *outbuf, char_t *string, int outlen)
+{
+ unsigned long shiftbuf;
+ char_t *cp, *op;
+ int c, i, j, shift;
+
+ op = outbuf;
+ *op = '\0';
+ cp = string;
+ while (*cp && *cp != '=') {
+/*
+ * Map 4 (6bit) input bytes and store in a single long (shiftbuf)
+ */
+ shiftbuf = 0;
+ shift = 18;
+ for (i = 0; i < 4 && *cp && *cp != '='; i++, cp++) {
+ c = map64[*cp & 0xff];
+ if (c == -1) {
+ error(E_L, E_LOG, T("Bad string: %s at %c index %d"), string,
+ c, i);
+ return -1;
+ }
+ shiftbuf = shiftbuf | (c << shift);
+ shift -= 6;
+ }
+/*
+ * Interpret as 3 normal 8 bit bytes (fill in reverse order).
+ * Check for potential buffer overflow before filling.
+ */
+ --i;
+ if ((op + i) >= &outbuf[outlen]) {
+ gstrcpy(outbuf, T("String too big"));
+ return -1;
+ }
+ for (j = 0; j < i; j++) {
+ *op++ = (char_t) ((shiftbuf >> (8 * (2 - j))) & 0xff);
+ }
+ *op = '\0';
+ }
+ return 0;
+}
+
+
+/******************************************************************************/
+/*
+ * Encode a buffer from "string" into "outbuf"
+ */
+
+void websEncode64(char_t *outbuf, char_t *string, int outlen)
+{
+ unsigned long shiftbuf;
+ char_t *cp, *op;
+ int x, i, j, shift;
+
+ op = outbuf;
+ *op = '\0';
+ cp = string;
+ while (*cp) {
+/*
+ * Take three characters and create a 24 bit number in shiftbuf
+ */
+ shiftbuf = 0;
+ for (j = 2; j >= 0 && *cp; j--, cp++) {
+ shiftbuf |= ((*cp & 0xff) << (j * 8));
+ }
+/*
+ * Now convert shiftbuf to 4 base64 letters. The i,j magic calculates
+ * how many letters need to be output.
+ */
+ shift = 18;
+ for (i = ++j; i < 4 && op < &outbuf[outlen] ; i++) {
+ x = (shiftbuf >> shift) & 0x3f;
+ *op++ = alphabet64[(shiftbuf >> shift) & 0x3f];
+ shift -= 6;
+ }
+/*
+ * Pad at the end with '='
+ */
+ while (j-- > 0) {
+ *op++ = '=';
+ }
+ *op = '\0';
+ }
+}
+/******************************************************************************/
diff --git a/cpukit/httpd/webcomp.c b/cpukit/httpd/webcomp.c
new file mode 100644
index 0000000000..6b19b3ba18
--- /dev/null
+++ b/cpukit/httpd/webcomp.c
@@ -0,0 +1,188 @@
+/*
+ * webcomp -- Compile web pages into C source
+ *
+ * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for usage and redistribution license requirements
+ *
+ * $Id$
+ */
+
+/******************************** Description *********************************/
+
+/*
+ * Usage: webcomp prefix filelist >webrom.c
+ *
+ * filelist is a file containing the pathnames of all web pages
+ * prefix is a path prefix to remove from all the web page pathnames
+ * webrom.c is the resulting C source file to compile and link.
+ */
+
+/********************************* Includes ***********************************/
+
+#include "wsIntrn.h"
+
+/**************************** Forward Declarations ****************************/
+
+static int compile(char_t *fileList, char_t *prefix);
+static void usage();
+
+/*********************************** Code *************************************/
+/*
+ * Main program for webpack test harness
+ */
+
+int gmain(int argc, char_t* argv[])
+{
+ char_t *fileList, *prefix;
+
+ fileList = NULL;
+
+ if (argc != 3) {
+ usage();
+ }
+
+ prefix = argv[1];
+ fileList = argv[2];
+
+ if (compile(fileList, prefix) < 0) {
+ return -1;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Output usage message
+ */
+
+static void usage()
+{
+ fprintf(stderr, "usage: webcomp prefix filelist >output.c\n");
+ exit(2);
+}
+
+/******************************************************************************/
+/*
+ * Compile the web pages
+ */
+
+static int compile(char_t *fileList, char_t *prefix)
+{
+ gstat_t sbuf;
+ FILE *lp;
+ time_t now;
+ char_t file[FNAMESIZE];
+ char_t *cp, *sl;
+ char buf[512];
+ unsigned char *p;
+ int j, i, len, fd, nFile;
+
+/*
+ * Open list of files
+ */
+ if ((lp = fopen(fileList, "r")) == NULL) {
+ fprintf(stderr, "Can't open file list %s\n", fileList);
+ return -1;
+ }
+
+ time(&now);
+ fprintf(stdout, "/*\n * webrom.c -- Compiled Web Pages\n *\n");
+ fprintf(stdout, " * Compiled by GoAhead WebCompile: %s */\n\n",
+ gctime(&now));
+ fprintf(stdout, "#include \"wsIntrn.h\"\n\n");
+ fprintf(stdout, "#ifndef WEBS_PAGE_ROM\n");
+ fprintf(stdout, "websRomPageIndexType websRomPageIndex[] = {\n");
+ fprintf(stdout, " { 0, 0, 0 },\n};\n");
+ fprintf(stdout, "#else\n");
+
+/*
+ * Open each input file and compile each web page
+ */
+ nFile = 0;
+ while (fgets(file, sizeof(file), lp) != NULL) {
+ if ((p = strchr(file, '\n')) || (p = strchr(file, '\r'))) {
+ *p = '\0';
+ }
+ if (*file == '\0') {
+ continue;
+ }
+ if (gstat(file, &sbuf) == 0 && sbuf.st_mode & S_IFDIR) {
+ continue;
+ }
+ if ((fd = gopen(file, O_RDONLY | O_BINARY)) < 0) {
+ fprintf(stderr, "Can't open file %s\n", file);
+ return -1;
+ }
+ fprintf(stdout, "static unsigned char page_%d[] = {\n", nFile);
+
+ while ((len = read(fd, buf, sizeof(buf))) > 0) {
+ p = buf;
+ for (i = 0; i < len; ) {
+ fprintf(stdout, " ");
+ for (j = 0; p < &buf[len] && j < 16; j++, p++) {
+ fprintf(stdout, "%3d,", *p);
+ }
+ i += j;
+ fprintf(stdout, "\n");
+ }
+ }
+ fprintf(stdout, " 0 };\n\n");
+
+ close(fd);
+ nFile++;
+ }
+ fclose(lp);
+
+/*
+ * Now output the page index
+ */
+ fprintf(stdout, "websRomPageIndexType websRomPageIndex[] = {\n");
+
+ if ((lp = fopen(fileList, "r")) == NULL) {
+ fprintf(stderr, "Can't open file list %s\n", fileList);
+ return -1;
+ }
+ nFile = 0;
+ while (fgets(file, sizeof(file), lp) != NULL) {
+ if ((p = strchr(file, '\n')) || (p = strchr(file, '\r'))) {
+ *p = '\0';
+ }
+ if (*file == '\0') {
+ continue;
+ }
+/*
+ * Remove the prefix and add a leading "/" when we print the path
+ */
+ if (strncmp(file, prefix, gstrlen(prefix)) == 0) {
+ cp = &file[gstrlen(prefix)];
+ } else {
+ cp = file;
+ }
+ while((sl = strchr(file, '\\')) != NULL) {
+ *sl = '/';
+ }
+ if (*cp == '/') {
+ cp++;
+ }
+
+ if (gstat(file, &sbuf) == 0 && sbuf.st_mode & S_IFDIR) {
+ fprintf(stdout, " { T(\"/%s\"), 0, 0 },\n", cp);
+ continue;
+ }
+ fprintf(stdout, " { T(\"/%s\"), page_%d, %d },\n", cp, nFile,
+ sbuf.st_size);
+ nFile++;
+ }
+ fclose(lp);
+
+ fprintf(stdout, " { 0, 0, 0 },\n");
+ fprintf(stdout, "};\n");
+ fprintf(stdout, "#endif /* WEBS_PAGE_ROM */\n");
+
+ fclose(lp);
+ fflush(stdout);
+ return 0;
+}
+
+/******************************************************************************/
diff --git a/cpukit/httpd/webmain.c b/cpukit/httpd/webmain.c
new file mode 100644
index 0000000000..c9c0b9cc15
--- /dev/null
+++ b/cpukit/httpd/webmain.c
@@ -0,0 +1,499 @@
+/*
+ * main.c -- Main program for the GoAhead WebServer (RTEMS version)
+ *
+ * Copyright (c) Go Ahead Software Inc., 1995-1999. All Rights Reserved.
+ *
+ * See the file "license.txt" for usage and redistribution license requirements
+ *
+ * $Id$
+ */
+
+/******************************** Description *********************************/
+
+/*
+ * Main program for for the GoAhead WebServer. This is a demonstration
+ * main program to initialize and configure the web server.
+ */
+
+/********************************* Includes ***********************************/
+
+#include "uemf.h"
+#include "wsIntrn.h"
+#include <signal.h>
+#include <sys/time.h>
+#include <pthread.h>
+
+#include <rtems.h>
+#include <rtems/error.h>
+
+#ifdef WEBS_SSL_SUPPORT
+#include "websSSL.h"
+#endif
+
+#ifdef USER_MANAGEMENT_SUPPORT
+#include "um.h"
+void formDefineUserMgmt(void);
+#endif
+
+/*********************************** Locals ***********************************/
+/*
+ * Change configuration here
+ */
+
+extern const char *tftpServer;
+/* static char_t *rootWeb = T("goahead"); * Root web directory */
+static char_t *password = T(""); /* Security password */
+static int port = 80; /* Server port */
+static int retries = 5; /* Server port retries */
+static int finished; /* Finished flag */
+
+/*
+ * Structure to hold timer events
+ */
+typedef struct {
+ void (*routine)(long arg); /* Timer routine */
+ long arg; /* Argument to routine */
+} websTimer_t;
+
+/* The following holds the pointer to an allocated websTimer_t structure .
+ * Using this method only one timer can be active at a time, but
+ * for the WebServer, this should be OK.
+ */
+websTimer_t *tp;
+
+/****************************** Forward Declarations **************************/
+
+static int initWebs();
+static int aspTest(int eid, webs_t wp, int argc, char_t **argv);
+static void formTest(webs_t wp, char_t *path, char_t *query);
+static int websHomePageHandler(webs_t wp, char_t *urlPrefix, char_t *webDir,
+ int arg, char_t* url, char_t* path, char_t* query);
+static void timerProc(int signo);
+#if B_STATS
+static void printMemStats(int handle, char_t *fmt, ...);
+static void memLeaks();
+#endif
+static timer_t timer_id;
+static void rtems_httpd_daemon();
+
+/*********************************** Code *************************************/
+/*
+ * Main -- entry point from RTEMS
+ */
+int rtems_initialize_webserver()
+{
+ rtems_status_code sc;
+ rtems_id tid;
+ int priority;
+
+ /***********************************************************************
+ * Default HTTPD priority.
+ **********************************************************************/
+ priority = 40;
+
+ sc = rtems_task_create(rtems_build_name('H', 'T', 'P', 'D'),
+ priority, 8*1024,
+ RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR |
+ RTEMS_INTERRUPT_LEVEL(0),
+ RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL,
+ &tid);
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ return(RTEMS_UNSATISFIED);
+ }
+
+ sc = rtems_task_start(tid, rtems_httpd_daemon, 0);
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ return(RTEMS_UNSATISFIED);
+ }
+
+ return(RTEMS_SUCCESSFUL);
+
+}
+
+static void
+rtems_httpd_daemon()
+{
+/*
+ * Initialize the memory allocator. Allow use of malloc and start with a
+ * 10K heap.
+ */
+ bopen(NULL, (10 * 1024), B_USE_MALLOC);
+
+/*
+ * Initialize the web server
+ */
+ if (initWebs() < 0) {
+ rtems_panic("Unable to initialize Web server !!\n");
+ }
+
+#ifdef WEBS_SSL_SUPPORT
+ websSSLOpen();
+#endif
+
+/*
+ * Basic event loop. SocketReady returns true when a socket is ready for
+ * service. SocketSelect will block until an event occurs. SocketProcess
+ * will actually do the servicing.
+ */
+ while (!finished) {
+ if (socketReady(-1) || socketSelect(-1, 2000)) {
+ socketProcess(-1);
+ }
+ /*websCgiCleanup();*/
+ emfSchedProcess();
+ }
+
+#ifdef WEBS_SSL_SUPPORT
+ websSSLClose();
+#endif
+
+#ifdef USER_MANAGEMENT_SUPPORT
+ umClose();
+#endif
+
+/*
+ * Close the socket module, report memory leaks and close the memory allocator
+ */
+ websCloseServer();
+ websDefaultClose();
+ socketClose();
+ symSubClose();
+#if B_STATS
+ memLeaks();
+#endif
+ bclose();
+ rtems_task_delete( RTEMS_SELF );
+}
+
+/******************************************************************************/
+/*
+ * Initialize the web server.
+ */
+
+static int initWebs()
+{
+ struct hostent* hp;
+ struct in_addr intaddr;
+ char host[128], webdir[128];
+ char_t wbuf[128];
+
+/*
+ * Initialize the socket subsystem
+ */
+ socketOpen();
+
+/*
+ * Define the local Ip address, host name, default home page and the
+ * root web directory.
+ */
+ if (gethostname(host, sizeof(host)) < 0) {
+ error(E_L, E_LOG, T("Can't get hostname"));
+ return -1;
+ }
+
+/* intaddr.s_addr = (unsigned long) hostGetByName(host); */
+ if ((hp = gethostbyname(host)) == NULL) {
+ error(E_L, E_LOG, T("Can't get host address"));
+ return -1;
+ }
+ memcpy((char *) &intaddr, (char *) hp->h_addr_list[0],
+ (size_t) hp->h_length);
+
+#if 0
+/*
+ * Set /TFTP/x.y.z.w/goahead as the root web. Modify to suit your needs
+ */
+ sprintf(webdir, "/TFTP/%s/%s", tftpServer, rootWeb);
+#else
+ sprintf(webdir, "/");
+#endif
+/*
+ * Configure the web server options before opening the web server
+ */
+ websSetDefaultDir(webdir);
+ ascToUni(wbuf, inet_ntoa(intaddr), sizeof(wbuf));
+ websSetIpaddr(wbuf);
+ ascToUni(wbuf, host, sizeof(wbuf));
+ websSetHost(wbuf);
+
+/*
+ * Configure the web server options before opening the web server
+ */
+#if 0
+ websSetDefaultPage(T("default.asp"));
+#else
+ websSetDefaultPage(T("index.html"));
+#endif
+ websSetPassword(password);
+
+/*
+ * Open the web server on the given port. If that port is taken, try
+ * the next sequential port for up to "retries" attempts.
+ */
+ websOpenServer(port, retries);
+
+/*
+ * First create the URL handlers. Note: handlers are called in sorted order
+ * with the longest path handler examined first. Here we define the security
+ * handler, forms handler and the default web page handler.
+ */
+ websUrlHandlerDefine(T(""), NULL, 0, websSecurityHandler,
+ WEBS_HANDLER_FIRST);
+ websUrlHandlerDefine(T("/goform"), NULL, 0, websFormHandler, 0);
+ websUrlHandlerDefine(T(""), NULL, 0, websDefaultHandler,
+ WEBS_HANDLER_LAST);
+
+/*
+ * Now define two test procedures. Replace these with your application
+ * relevant ASP script procedures and form functions.
+ */
+ websAspDefine(T("aspTest"), aspTest);
+ websFormDefine(T("formTest"), formTest);
+
+/*
+ * Create a handler for the default home page
+ */
+ websUrlHandlerDefine(T("/"), NULL, 0, websHomePageHandler, 0);
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Test Javascript binding for ASP. This will be invoked when "aspTest" is
+ * embedded in an ASP page. See web/asp.asp for usage. Set browser to
+ * "localhost/asp.asp" to test.
+ */
+
+static int aspTest(int eid, webs_t wp, int argc, char_t **argv)
+{
+ char_t *name, *address;
+
+ if (ejArgs(argc, argv, T("%s %s"), &name, &address) < 2) {
+ websError(wp, 400, T("Insufficient args\n"));
+ return -1;
+ }
+ return websWrite(wp, T("Name: %s, Address %s"), name, address);
+}
+/******************************************************************************/
+/*
+ * Test form for posted data (in-memory CGI). This will be called when the
+ * form in web/asp.asp is invoked. Set browser to "localhost/asp.asp" to test.
+ */
+
+static void formTest(webs_t wp, char_t *path, char_t *query)
+{
+ char_t *name, *address;
+
+ name = websGetVar(wp, T("name"), T("Joe Smith"));
+ address = websGetVar(wp, T("address"), T("1212 Milky Way Ave."));
+
+ websHeader(wp);
+ websWrite(wp, T("<body><h2>Name: %s, Address: %s</h2>\n"), name, address);
+ websFooter(wp);
+ websDone(wp, 200);
+}
+
+/******************************************************************************/
+/*
+ * Create a timer to invoke the routine in "delay" milliseconds.
+ */
+
+void *emfCreateTimer(int delay, void (*routine)(long arg), long arg)
+{
+/* this variable is only used in the if'ed 0 section below */
+#if 0
+ struct sigaction act;
+#endif
+ struct itimerspec its = { {0,0}, {0,0} };
+ struct sigevent se;
+ int status;
+
+ if ((tp = balloc(B_L, sizeof(websTimer_t)))) {
+ tp->routine = routine;
+ tp->arg = arg;
+ }
+ else {
+ return NULL;
+ }
+
+ se.sigev_notify = SIGEV_THREAD;
+ se.sigev_value.sival_ptr = tp;
+ se.sigev_notify_function = (void (*)(union sigval)) timerProc;
+
+ /*
+ * NOT POSIX?
+ * se.sigev_notify_attributes = NULL;
+ */
+
+
+ status = timer_create(CLOCK_REALTIME, &se, &timer_id);
+ if (status != 0) {
+ bfree(B_L, tp);
+ return NULL;
+ }
+ /* convert delay millisecs to secs and usecs required by struct */
+ its.it_value.tv_sec = delay / 1000;
+ its.it_value.tv_nsec = (delay % 1000) * 1000000;
+
+ status = timer_settime(timer_id, 0, &its, 0);
+ if (status != 0) {
+ bfree(B_L, tp);
+ return NULL;
+ }
+
+#if 0
+ act.sa_flags = 0;
+ sigemptyset(&act.sa_mask);
+ act.sa_handler = timerProc;
+ sigaction(SIGALRM, &act, NULL);
+
+ /* convert delay millisecs to secs and usecs required by struct */
+ its.it_value.tv_sec = delay / 1000;
+ its.it_value.tv_usec = (delay % 1000) * 1000;
+
+ if (setitimer(ITIMER_REAL, &its, NULL) == -1) {
+ bfree(B_L, tp);
+ return NULL;
+ }
+#endif
+ return tp;
+}
+
+/******************************************************************************/
+/*
+ * Delete a timer
+ */
+
+void emfDeleteTimer(void * id)
+{
+ websTimer_t *wtp;
+ /*struct itimerval its = { {0,0}, {0,0} };*/
+
+ wtp = (websTimer_t *)id;
+ /* setitimer(ITIMER_REAL, &its, NULL);*/
+ timer_delete(timer_id);
+ bfree(B_L, wtp);
+}
+
+/******************************************************************************/
+/*
+ * Timer handler
+ */
+
+static void timerProc(int signo)
+{
+ websTimer_t wtp = *tp;
+
+/* Copy the timer structure to a local first and delete it before calling
+ * the function, since the function could create another timer. In this
+ * implementation, only one timer can be allocated at a time.
+ */
+
+ bfree(B_L, tp);
+ (wtp.routine)(wtp.arg);
+}
+
+/******************************************************************************/
+/*
+ * Home page handler
+ */
+
+static int websHomePageHandler(webs_t wp, char_t *urlPrefix, char_t *webDir,
+ int arg, char_t* url, char_t* path, char_t* query)
+{
+/*
+ * If the empty or "/" URL is invoked, redirect default URLs to the home page
+ */
+ if (*url == '\0' || gstrcmp(url, T("/")) == 0) {
+#if 0
+ websRedirect(wp, T("home.asp"));
+#else
+ websRedirect(wp, T("index.html"));
+#endif
+ return 1;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+
+#if B_STATS
+static void memLeaks()
+{
+ int fd=1;
+
+ /* if ((fd = gopen(T("leak.txt"), O_CREAT | O_TRUNC | O_WRONLY)) >= 0) { */
+ bstats(fd, printMemStats);
+ /*
+ close(fd);
+ }
+ */
+}
+
+/******************************************************************************/
+/*
+ * Print memory usage / leaks
+ */
+
+static void printMemStats(int handle, char_t *fmt, ...)
+{
+ va_list args;
+ char_t buf[256];
+
+ va_start(args, fmt);
+ vsprintf(buf, fmt, args);
+ va_end(args);
+ write(handle, buf, strlen(buf));
+}
+#endif
+
+/*****************************************************************************/
+
+/*****************************************************************************/
+/*
+ * Default error handler. The developer should insert code to handle
+ * error messages in the desired manner.
+ */
+
+void defaultErrorHandler(int etype, char_t *msg)
+{
+#if 1
+ write(1, msg, gstrlen(msg));
+#endif
+}
+
+/*****************************************************************************/
+/*
+ * Trace log. Customize this function to log trace output
+ */
+
+void defaultTraceHandler(int level, char_t *buf)
+{
+/*
+ * The following code would write all trace regardless of level
+ * to stdout.
+ */
+#if 1
+ if (buf) {
+ write(1, buf, gstrlen(buf));
+ }
+#endif
+}
+
+/*****************************************************************************/
+/*
+ * Returns a pointer to an allocated qualified unique temporary file name.
+ * This filename must eventually be deleted with bfree();
+ */
+
+char_t *websGetCgiCommName()
+{
+ char_t *pname1, *pname2;
+
+ pname1 = tempnam(NULL, T("cgi"));
+ pname2 = bstrdup(B_L, pname1);
+ free(pname1);
+ return pname2;
+}
diff --git a/cpukit/httpd/webpage.c b/cpukit/httpd/webpage.c
new file mode 100644
index 0000000000..a42a8b45c9
--- /dev/null
+++ b/cpukit/httpd/webpage.c
@@ -0,0 +1,141 @@
+/*
+ * Page.c -- Support for page retrieval.
+ *
+ * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for usage and redistribution license requirements
+ *
+ * $Id$
+ */
+
+/******************************** Description *********************************/
+
+/*
+ * This module provides page retrieval handling. It provides support for
+ * reading web pages from file systems and has expansion for ROMed web
+ * pages.
+ */
+
+/********************************* Includes ***********************************/
+
+#include "wsIntrn.h"
+
+/*********************************** Code *************************************/
+/*
+ * Open a web page. lpath is the local filename. path is the URL path name.
+ */
+
+int websPageOpen(webs_t wp, char_t *lpath, char_t *path, int mode, int perm)
+{
+ a_assert(websValid(wp));
+
+#ifdef WEBS_PAGE_ROM
+ return websRomPageOpen(wp, path, mode, perm);
+#else
+ return (wp->docfd = gopen(lpath, mode, perm));
+#endif /* WEBS_PAGE_ROM */
+}
+
+/******************************************************************************/
+/*
+ * Close a web page
+ */
+
+void websPageClose(webs_t wp)
+{
+ a_assert(websValid(wp));
+
+#ifdef WEBS_PAGE_ROM
+ websRomPageClose(wp->docfd);
+#else
+ if (wp->docfd >= 0) {
+ close(wp->docfd);
+ wp->docfd = -1;
+ }
+#endif
+}
+
+/******************************************************************************/
+/*
+ * Stat a web page lpath is the local filename. path is the URL path name.
+ */
+
+int websPageStat(webs_t wp, char_t *lpath, char_t *path, websStatType* sbuf)
+{
+#ifdef WEBS_PAGE_ROM
+ return websRomPageStat(path, sbuf);
+#else
+ gstat_t s;
+
+ if (gstat(lpath, &s) < 0) {
+ return -1;
+ }
+ sbuf->size = s.st_size;
+ sbuf->mtime = s.st_mtime;
+ sbuf->isDir = s.st_mode & S_IFDIR;
+ return 0;
+#endif
+}
+
+/******************************************************************************/
+/*
+ * Is this file a directory?
+ */
+
+int websPageIsDirectory(char_t *lpath)
+{
+#ifdef WEBS_PAGE_ROM
+ websStatType sbuf;
+
+ if (websRomPageStat(lpath, &sbuf) >= 0) {
+ return(sbuf.isDir);
+ } else {
+ return 0;
+ }
+#else
+ gstat_t sbuf;
+
+ if (gstat(lpath, &sbuf) >= 0) {
+ return(sbuf.st_mode & S_IFDIR);
+ } else {
+ return 0;
+ }
+#endif
+}
+
+
+/******************************************************************************/
+/*
+ * Read a web page. Returns the number of _bytes_ read.
+ * len is the size of buf, in bytes.
+ */
+
+int websPageReadData(webs_t wp, char *buf, int nBytes)
+{
+
+#ifdef WEBS_PAGE_ROM
+ a_assert(websValid(wp));
+ return websRomPageReadData(wp, buf, nBytes);
+#else
+ a_assert(websValid(wp));
+ return read(wp->docfd, buf, nBytes);
+#endif
+}
+
+/******************************************************************************/
+/*
+ * Move file pointer offset bytes.
+ */
+
+void websPageSeek(webs_t wp, long offset)
+{
+ a_assert(websValid(wp));
+
+#ifdef WEBS_PAGE_ROM
+ websRomPageSeek(wp, offset, SEEK_CUR);
+#else
+ lseek(wp->docfd, offset, SEEK_CUR);
+#endif
+}
+
+/******************************************************************************/
diff --git a/cpukit/httpd/webrom.c b/cpukit/httpd/webrom.c
new file mode 100644
index 0000000000..23de2c6d60
--- /dev/null
+++ b/cpukit/httpd/webrom.c
@@ -0,0 +1,15 @@
+/*
+ * webrom.c -- Compiled Web Pages
+ *
+ * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for usage and redistribution license requirements
+ *
+ * $Id$
+ */
+
+#include "wsIntrn.h"
+
+websRomPageIndexType websRomPageIndex[] = {
+ { 0, 0, 0 },
+};
diff --git a/cpukit/httpd/webs.c b/cpukit/httpd/webs.c
new file mode 100644
index 0000000000..9073fe8b7c
--- /dev/null
+++ b/cpukit/httpd/webs.c
@@ -0,0 +1,2961 @@
+/*
+ * webs.c -- GoAhead Embedded HTTP webs server
+ *
+ * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for usage and redistribution license requirements
+ *
+ * $Id$
+ */
+
+/******************************** Description *********************************/
+
+/*
+ * This module implements an embedded HTTP/1.1 web server. It supports
+ * loadable URL handlers that define the nature of URL processing performed.
+ */
+
+/********************************* Includes ***********************************/
+
+#include "wsIntrn.h"
+#ifdef DIGEST_ACCESS_SUPPORT
+ #include "websda.h"
+#endif
+
+/******************************** Global Data *********************************/
+
+websStatsType websStats; /* Web access stats */
+webs_t *webs; /* Open connection list head */
+sym_fd_t websMime; /* Set of mime types */
+int websMax; /* List size */
+int websPort; /* Listen port for server */
+char_t websHost[64]; /* Host name for the server */
+char_t websIpaddr[64]; /* IP address for the server */
+char_t *websHostUrl = NULL; /* URL to access server */
+char_t *websIpaddrUrl = NULL; /* URL to access server */
+
+/*********************************** Locals ***********************************/
+/*
+ * Standard HTTP error codes
+ */
+
+websErrorType websErrors[] = {
+ { 200, T("Data follows") },
+ { 204, T("No Content") },
+ { 301, T("Redirect") },
+ { 302, T("Redirect") },
+ { 304, T("Use local copy") },
+ { 400, T("Page not found") },
+ { 401, T("Unauthorized") },
+ { 403, T("Forbidden") },
+ { 404, T("Site or Page Not Found") },
+ { 405, T("Access Denied") },
+ { 500, T("Web Error") },
+ { 501, T("Not Implemented") },
+ { 503, T("Site Temporarily Unavailable. Try again.") },
+ { 0, NULL }
+};
+
+#ifdef WEBS_LOG_SUPPORT
+static char_t websLogname[64] = T("log.txt"); /* Log filename */
+static int websLogFd; /* Log file handle */
+#endif
+
+static int websListenSock; /* Listen socket */
+static char_t websRealm[64] = T("GoAhead"); /* Realm name */
+
+static int websOpenCount = 0; /* count of apps using this module */
+
+/**************************** Forward Declarations ****************************/
+
+
+/*static char_t *websErrorMsg(int code);*/
+static int websGetInput(webs_t wp, char_t **ptext, int *nbytes);
+static int websParseFirst(webs_t wp, char_t *text);
+static void websParseRequest(webs_t wp);
+static void websSocketEvent(int sid, int mask, int data);
+static int websGetTimeSinceMark(webs_t wp);
+
+#ifdef WEBS_LOG_SUPPORT
+static void websLog(webs_t wp, int code);
+#endif
+#ifdef WEBS_IF_MODIFIED_SUPPORT
+static time_t dateParse(time_t tip, char_t *cmd);
+#endif
+
+/*********************************** Code *************************************/
+/*
+ * Open the GoAhead WebServer
+ */
+
+int websOpenServer(int port, int retries)
+{
+ websMimeType *mt;
+
+ if (++websOpenCount != 1) {
+ return websPort;
+ }
+
+ a_assert(port > 0);
+ a_assert(retries >= 0);
+
+#ifdef WEBS_PAGE_ROM
+ websRomOpen();
+#endif
+
+ webs = NULL;
+ websMax = 0;
+/*
+ * Create a mime type lookup table for quickly determining the content type
+ */
+ websMime = symOpen(WEBS_SYM_INIT * 4);
+ a_assert(websMime >= 0);
+ for (mt = websMimeList; mt->type; mt++) {
+ symEnter(websMime, mt->ext, valueString(mt->type, 0), 0);
+ }
+
+/*
+ * Open the URL handler module. The caller should create the required
+ * URL handlers after calling this function.
+ */
+ if (websUrlHandlerOpen() < 0) {
+ return -1;
+ }
+ websFormOpen();
+
+#ifdef WEBS_LOG_SUPPORT
+/*
+ * Optional request log support
+ */
+ websLogFd = gopen(websLogname, O_CREAT | O_TRUNC | O_APPEND | O_WRONLY,
+ 0666);
+ a_assert(websLogFd >= 0);
+#endif
+
+ return websOpenListen(port, retries);
+}
+
+/******************************************************************************/
+/*
+ * Close the GoAhead WebServer
+ */
+
+void websCloseServer()
+{
+ webs_t wp;
+ int wid;
+
+ if (--websOpenCount > 0) {
+ return;
+ }
+
+/*
+ * Close the listen handle first then all open connections.
+ */
+ websCloseListen();
+
+/*
+ * Close each open browser connection and free all resources
+ */
+ for (wid = websMax; webs && wid >= 0; wid--) {
+ if ((wp = webs[wid]) == NULL) {
+ continue;
+ }
+ socketCloseConnection(wp->sid);
+ websFree(wp);
+ }
+
+#ifdef WEBS_LOG_SUPPORT
+ if (websLogFd >= 0) {
+ close(websLogFd);
+ websLogFd = -1;
+ }
+#endif
+
+#ifdef WEBS_PAGE_ROM
+ websRomClose();
+#endif
+ symClose(websMime);
+ websFormClose();
+ websUrlHandlerClose();
+}
+
+/******************************************************************************/
+/*
+ * Open the GoAhead WebServer listen port
+ */
+
+int websOpenListen(int port, int retries)
+{
+ int i, orig;
+
+ a_assert(port > 0);
+ a_assert(retries >= 0);
+
+ orig = port;
+/*
+ * Open the webs webs listen port. If we fail, try the next port.
+ */
+ for (i = 0; i <= retries; i++) {
+ websListenSock = socketOpenConnection(NULL, port, websAccept, 0);
+ if (websListenSock >= 0) {
+ break;
+ }
+ port++;
+ }
+ if (i > retries) {
+ error(E_L, E_USER, T("Couldn't open a socket on ports %d - %d"),
+ orig, port - 1);
+ return -1;
+ }
+
+/*
+ * Determine the full URL address to access the home page for this web server
+ */
+ websPort = port;
+ bfreeSafe(B_L, websHostUrl);
+ bfreeSafe(B_L, websIpaddrUrl);
+ websIpaddrUrl = websHostUrl = NULL;
+
+ if (port == 80) {
+ websHostUrl = bstrdup(B_L, websHost);
+ websIpaddrUrl = bstrdup(B_L, websIpaddr);
+ } else {
+ fmtAlloc(&websHostUrl, WEBS_MAX_URL + 80, T("%s:%d"), websHost, port);
+ fmtAlloc(&websIpaddrUrl, WEBS_MAX_URL + 80, T("%s:%d"),
+ websIpaddr, port);
+ }
+ trace(0, T("webs: Listening for HTTP requests at address %s\n"),
+ websIpaddrUrl);
+
+ return port;
+}
+
+/******************************************************************************/
+/*
+ * Close webs listen port
+ */
+
+void websCloseListen()
+{
+ if (websListenSock >= 0) {
+ socketCloseConnection(websListenSock);
+ websListenSock = -1;
+ }
+ bfreeSafe(B_L, websHostUrl);
+ bfreeSafe(B_L, websIpaddrUrl);
+ websIpaddrUrl = websHostUrl = NULL;
+}
+
+/******************************************************************************/
+/*
+ * Accept a connection
+ */
+
+int websAccept(int sid, char *ipaddr, int port, int listenSid)
+{
+ webs_t wp;
+ int wid;
+
+ a_assert(ipaddr && *ipaddr);
+ a_assert(sid >= 0);
+ a_assert(port >= 0);
+
+/*
+ * Allocate a new handle for this accepted connection. This will allocate
+ * a webs_t structure in the webs[] list
+ */
+ if ((wid = websAlloc(sid)) < 0) {
+ return -1;
+ }
+ wp = webs[wid];
+ a_assert(wp);
+ wp->listenSid = listenSid;
+
+ ascToUni(wp->ipaddr, ipaddr, min(sizeof(wp->ipaddr), strlen(ipaddr) + 1));
+
+/*
+ * Check if this is a request from a browser on this system. This is useful
+ * to know for permitting administrative operations only for local access
+ */
+ if (gstrcmp(wp->ipaddr, T("127.0.0.1")) == 0 ||
+ gstrcmp(wp->ipaddr, websIpaddr) == 0 ||
+ gstrcmp(wp->ipaddr, websHost) == 0) {
+ wp->flags |= WEBS_LOCAL_REQUEST;
+ }
+
+/*
+ * Arrange for websSocketEvent to be called when read data is available
+ */
+ socketCreateHandler(sid, SOCKET_READABLE, websSocketEvent, (int) wp);
+
+/*
+ * Arrange for a timeout to kill hung requests
+ */
+ wp->timeout = emfSchedCallback(WEBS_TIMEOUT, websTimeout, (void *) wp);
+ trace(8, T("webs: accept request\n"));
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * The webs socket handler. Called in response to I/O. We just pass control
+ * to the relevant read or write handler. A pointer to the webs structure
+ * is passed as an (int) in iwp.
+ */
+
+static void websSocketEvent(int sid, int mask, int iwp)
+{
+ webs_t wp;
+
+ wp = (webs_t) iwp;
+ a_assert(wp);
+
+ if (! websValid(wp)) {
+ return;
+ }
+
+ if (mask & SOCKET_READABLE) {
+ websReadEvent(wp);
+ }
+ if (mask & SOCKET_WRITABLE) {
+ if (websValid(wp) && wp->writeSocket) {
+ (*wp->writeSocket)(wp);
+ }
+ }
+}
+
+/******************************************************************************/
+/*
+ * The webs read handler. This is the primary read event loop. It uses a
+ * state machine to track progress while parsing the HTTP request.
+ * Note: we never block as the socket is always in non-blocking mode.
+ */
+
+void websReadEvent(webs_t wp)
+{
+ char_t *text;
+ int rc, nbytes, len, done, fd;
+
+ a_assert(wp);
+ a_assert(websValid(wp));
+
+ websSetTimeMark(wp);
+
+/*
+ * Read as many lines as possible. socketGets is called to read the header
+ * and socketRead is called to read posted data.
+ */
+ text = NULL;
+ fd = -1;
+ for (done = 0; !done; ) {
+ if (text) {
+ bfree(B_L, text);
+ text = NULL;
+ }
+
+/*
+ * Get more input into "text". Returns 0, if more data is needed
+ * to continue, -1 if finished with the request, or 1 if all
+ * required data is available for current state.
+ */
+ while ((rc = websGetInput(wp, &text, &nbytes)) == 0) {
+ ;
+ }
+
+/*
+ * websGetInput returns -1 if it finishes with the request
+ */
+ if (rc < 0) {
+ break;
+ }
+
+/*
+ * This is the state machine for the web server.
+ */
+ switch(wp->state) {
+ case WEBS_BEGIN:
+/*
+ * Parse the first line of the Http header
+ */
+ if (websParseFirst(wp, text) < 0) {
+ done++;
+ break;
+ }
+ wp->state = WEBS_HEADER;
+ break;
+
+ case WEBS_HEADER:
+/*
+ * Store more of the HTTP header. As we are doing line reads, we
+ * need to separate the lines with '\n'
+ */
+ if (ringqLen(&wp->header) > 0) {
+ ringqPutStr(&wp->header, T("\n"));
+ }
+ ringqPutStr(&wp->header, text);
+ break;
+
+ case WEBS_POST_CLEN:
+/*
+ * POST request with content specified by a content length.
+ * If this is a CGI request, write the data to the cgi stdin.
+ * socketGets was used to get the data and it strips \n's so
+ * add them back in here.
+ */
+#ifndef __NO_CGI_BIN
+ if (wp->flags & WEBS_CGI_REQUEST) {
+ if (fd == -1) {
+ fd = gopen(wp->cgiStdin, O_CREAT | O_WRONLY | O_BINARY,
+ 0666);
+ }
+ gwrite(fd, text, gstrlen(text));
+ /*
+ * NOTE that the above comment is wrong -- if the content length
+ * is set, websGetInput() does NOT use socketGets(), it uses
+ * socketRead(), so the line below that adds an additional newline
+ * is destructive.
+ */
+ /*gwrite(fd, T("\n"), sizeof(char_t));*/
+/*
+ * Line removed as per BUG02488
+ *
+ nbytes += 1;
+ */
+ } else
+#endif
+ if (wp->query) {
+ if (wp->query[0] && !(wp->flags & WEBS_POST_DATA)) {
+/*
+ * Special case where the POST request also had query data
+ * specified in the URL, ie. url?query_data. In this case
+ * the URL query data is separated by a '&' from the posted
+ * query data.
+ */
+ len = gstrlen(wp->query);
+ wp->query = brealloc(B_L, wp->query, (len + gstrlen(text) +
+ 2) * sizeof(char_t));
+ wp->query[len++] = '&';
+ gstrcpy(&wp->query[len], text);
+
+ } else {
+/*
+ * The existing query data came from the POST request so just
+ * append it.
+ */
+ if (text != NULL)
+ {
+ len = gstrlen(wp->query);
+ wp->query = brealloc(B_L, wp->query, (len + gstrlen(text) +
+ 1) * sizeof(char_t));
+ if (wp->query) {
+ gstrcpy(&wp->query[len], text);
+ }
+ }
+ }
+
+ } else {
+ wp->query = bstrdup(B_L, text);
+ }
+/*
+ * Calculate how much more post data is to be read.
+ */
+ wp->flags |= WEBS_POST_DATA;
+ wp->clen -= nbytes;
+ if (wp->clen > 0) {
+ if (nbytes > 0) {
+ break;
+ }
+ done++;
+ break;
+ }
+/*
+ * No more data so process the request, (but be sure to close
+ * the input file first!).
+ */
+ if (fd != -1) {
+ gclose (fd);
+ fd = -1;
+ }
+ websUrlHandlerRequest(wp);
+ done++;
+ break;
+
+ case WEBS_POST:
+/*
+ * POST without content-length specification
+ * If this is a CGI request, write the data to the cgi stdin.
+ * socketGets was used to get the data and it strips \n's so
+ * add them back in here.
+ */
+
+#ifndef __NO_CGI_BIN
+ if (wp->flags & WEBS_CGI_REQUEST) {
+ if (fd == -1) {
+ fd = gopen(wp->cgiStdin, O_CREAT | O_WRONLY | O_BINARY,
+ 0666);
+ }
+ gwrite(fd, text, gstrlen(text));
+ gwrite(fd, T("\n"), sizeof(char_t));
+ } else
+#endif
+ if (wp->query && *wp->query && !(wp->flags & WEBS_POST_DATA)) {
+ len = gstrlen(wp->query);
+ wp->query = brealloc(B_L, wp->query, (len + gstrlen(text) +
+ 2) * sizeof(char_t));
+ if (wp->query) {
+ wp->query[len++] = '&';
+ gstrcpy(&wp->query[len], text);
+ }
+
+ } else {
+ wp->query = bstrdup(B_L, text);
+ }
+ wp->flags |= WEBS_POST_DATA;
+ done++;
+ break;
+
+ default:
+ websError(wp, 404, T("Bad state"));
+ done++;
+ break;
+ }
+ }
+
+ if (fd != -1) {
+ fd = gclose (fd);
+ }
+
+ if (text) {
+ bfree(B_L, text);
+ }
+}
+
+/******************************************************************************/
+/*
+ * Get input from the browser. Return TRUE (!0) if the request has been
+ * handled. Return -1 on errors or if the request has been processed,
+ * 1 if input read, and 0 to instruct the caller to call again for more input.
+ *
+ * Note: socketRead will Return the number of bytes read if successful. This
+ * may be less than the requested "bufsize" and may be zero. It returns -1 for
+ * errors. It returns 0 for EOF. Otherwise it returns the number of bytes
+ * read. Since this may be zero, callers should use socketEof() to
+ * distinguish between this and EOF.
+ */
+
+static int websGetInput(webs_t wp, char_t **ptext, int *pnbytes)
+{
+ char_t *text;
+ char buf[WEBS_SOCKET_BUFSIZ+1];
+ int nbytes, len, clen;
+
+ a_assert(websValid(wp));
+ a_assert(ptext);
+ a_assert(pnbytes);
+
+ *ptext = text = NULL;
+ *pnbytes = 0;
+
+/*
+ * If this request is a POST with a content length, we know the number
+ * of bytes to read so we use socketRead().
+ */
+ if (wp->state == WEBS_POST_CLEN) {
+ len = (wp->clen > WEBS_SOCKET_BUFSIZ) ? WEBS_SOCKET_BUFSIZ : wp->clen;
+ } else {
+ len = 0;
+ }
+
+ if (len > 0) {
+
+#ifdef WEBS_SSL_SUPPORT
+ if (wp->flags & WEBS_SECURE) {
+ nbytes = websSSLRead(wp->wsp, buf, len);
+ } else {
+ nbytes = socketRead(wp->sid, buf, len);
+ }
+#else
+ nbytes = socketRead(wp->sid, buf, len);
+#endif
+ if (nbytes < 0) { /* Error */
+ websDone(wp, 0);
+ return -1;
+
+ } else if (nbytes == 0) { /* EOF or No data available */
+ return -1;
+
+ } else { /* Valid data */
+/*
+ * Convert to UNICODE if necessary. First be sure the string
+ * is NULL terminated.
+ */
+ buf[nbytes] = '\0';
+ if ((text = ballocAscToUni(buf, nbytes)) == NULL) {
+ websError(wp, 503, T("Insufficient memory"));
+ return -1;
+ }
+ }
+
+ } else {
+#ifdef WEBS_SSL_SUPPORT
+ if (wp->flags & WEBS_SECURE) {
+ nbytes = websSSLGets(wp->wsp, &text);
+ } else {
+ nbytes = socketGets(wp->sid, &text);
+ }
+#else
+ nbytes = socketGets(wp->sid, &text);
+#endif
+
+ if (nbytes < 0) {
+ int eof;
+/*
+ * Error, EOF or incomplete
+ */
+#ifdef WEBS_SSL_SUPPORT
+ if (wp->flags & WEBS_SECURE) {
+/*
+ * If state is WEBS_BEGIN and the request is secure, a -1 will
+ * usually indicate SSL negotiation
+ */
+ if (wp->state == WEBS_BEGIN) {
+ eof = 1;
+ } else {
+ eof = websSSLEof(wp->wsp);
+ }
+ } else {
+ eof = socketEof(wp->sid);
+ }
+#else
+ eof = socketEof(wp->sid);
+#endif
+
+ if (eof) {
+/*
+ * If this is a post request without content length, process
+ * the request as we now have all the data. Otherwise just
+ * close the connection.
+ */
+ if (wp->state == WEBS_POST) {
+ websUrlHandlerRequest(wp);
+ } else {
+ websDone(wp, 0);
+ }
+ } else {
+/*
+ * If an error occurred and it wasn't an eof, close the connection
+ */
+#ifdef HP_FIX
+ websDone(wp, 0);
+#endif /*HP_FIX*/
+
+ }
+/*
+ * If state is WEBS_HEADER and the ringq is empty, then this is a
+ * simple request with no additional header fields to process and
+ * no empty line terminator.
+ */
+/*
+ * NOTE: this fix for earlier versions of browsers is troublesome
+ * because if we don't receive the entire header in the first pass
+ * this code assumes we were only expecting a one line header, which
+ * is not necessarily the case. So we weren't processing the whole
+ * header and weren't fufilling requests properly.
+ */
+#ifdef UNUSED
+ if (wp->state == WEBS_HEADER && ringqLen(&wp->header) <= 0) {
+ websParseRequest(wp);
+ websUrlHandlerRequest(wp);
+ }
+#endif
+ return -1;
+
+ } else if (nbytes == 0) {
+ if (wp->state == WEBS_HEADER) {
+/*
+ * Valid empty line, now finished with header
+ */
+ websParseRequest(wp);
+ if (wp->flags & WEBS_POST_REQUEST) {
+ if (wp->flags & WEBS_CLEN) {
+ wp->state = WEBS_POST_CLEN;
+ clen = wp->clen;
+ } else {
+ wp->state = WEBS_POST;
+ clen = 1;
+ }
+ if (clen > 0) {
+/*
+ * Return 0 to get more data.
+ */
+ return 0;
+ }
+ return 1;
+ }
+/*
+ * We've read the header so go and handle the request
+ */
+ websUrlHandlerRequest(wp);
+ }
+ return -1;
+ }
+ }
+ a_assert(text);
+ a_assert(nbytes > 0);
+ *ptext = text;
+ *pnbytes = nbytes;
+ return 1;
+}
+
+/******************************************************************************/
+/*
+ * Parse the first line of a HTTP request
+ */
+
+static int websParseFirst(webs_t wp, char_t *text)
+{
+ char_t *op, *proto, *protoVer, *url, *host, *query, *path, *port, *ext;
+ char_t *buf;
+ int testPort;
+
+ a_assert(websValid(wp));
+ a_assert(text && *text);
+
+/*
+ * Determine the request type: GET, HEAD or POST
+ */
+ op = gstrtok(text, T(" \t"));
+ if (op == NULL || *op == '\0') {
+ websError(wp, 400, T("Bad HTTP request"));
+ return -1;
+ }
+ if (gstrcmp(op, T("GET")) != 0) {
+ if (gstrcmp(op, T("POST")) == 0) {
+ wp->flags |= WEBS_POST_REQUEST;
+ } else if (gstrcmp(op, T("HEAD")) == 0) {
+ wp->flags |= WEBS_HEAD_REQUEST;
+ } else {
+ websError(wp, 400, T("Bad request type"));
+ return -1;
+ }
+ }
+
+/*
+ * Store result in the form (CGI) variable store
+ */
+ websSetVar(wp, T("REQUEST_METHOD"), op);
+
+ url = gstrtok(NULL, T(" \t\n"));
+ if (url == NULL || *url == '\0') {
+ websError(wp, 400, T("Bad HTTP request"));
+ return -1;
+ }
+ protoVer = gstrtok(NULL, T(" \t\n"));
+
+/*
+ * Parse the URL and store all the various URL components. websUrlParse
+ * returns an allocated buffer in buf which we must free. We support both
+ * proxied and non-proxied requests. Proxied requests will have http://host/
+ * at the start of the URL. Non-proxied will just be local path names.
+ */
+ host = path = port = proto = query = ext = NULL;
+ if (websUrlParse(url, &buf, &host, &path, &port, &query, &proto,
+ NULL, &ext) < 0) {
+ websError(wp, 400, T("Bad URL format"));
+ return -1;
+ }
+
+ wp->url = bstrdup(B_L, url);
+
+#ifndef __NO_CGI_BIN
+ if (gstrstr(url, CGI_BIN) != NULL) {
+ wp->flags |= WEBS_CGI_REQUEST;
+ if (wp->flags & WEBS_POST_REQUEST) {
+ wp->cgiStdin = websGetCgiCommName();
+ }
+ }
+#endif
+
+ wp->query = bstrdup(B_L, query);
+ wp->host = bstrdup(B_L, host);
+ wp->path = bstrdup(B_L, path);
+ wp->protocol = bstrdup(B_L, proto);
+ wp->protoVersion = bstrdup(B_L, protoVer);
+
+ if ((testPort = socketGetPort(wp->listenSid)) >= 0) {
+ wp->port = testPort;
+ } else {
+ wp->port = gatoi(port);
+ }
+
+ if (gstrcmp(ext, T(".asp")) == 0) {
+ wp->flags |= WEBS_ASP;
+ }
+ bfree(B_L, buf);
+
+ websUrlType(url, wp->type, TSZ(wp->type));
+
+#ifdef WEBS_PROXY_SUPPORT
+/*
+ * Determine if this is a request for local webs data. If it is not a proxied
+ * request from the browser, we won't see the "http://" or the system name, so
+ * we assume it must be talking to us directly for local webs data.
+ * Note: not fully implemented yet.
+ */
+ if (gstrstr(wp->url, T("http://")) == NULL ||
+ ((gstrcmp(wp->host, T("localhost")) == 0 ||
+ gstrcmp(wp->host, websHost) == 0) && (wp->port == websPort))) {
+ wp->flags |= WEBS_LOCAL_PAGE;
+ if (gstrcmp(wp->path, T("/")) == 0) {
+ wp->flags |= WEBS_HOME_PAGE;
+ }
+ }
+#endif
+
+ ringqFlush(&wp->header);
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Parse a full request
+ */
+
+#define isgoodchar(s) (gisalnum((s)) || ((s) == '/') || ((s) == '_') || \
+ ((s) == '.') || ((s) == '-') )
+
+static void websParseRequest(webs_t wp)
+{
+ char_t *authType, *upperKey, *cp, *browser, *lp, *key, *value;
+
+ a_assert(websValid(wp));
+
+/*
+ * Define default CGI values
+ */
+ websSetVar(wp, T("HTTP_AUTHORIZATION"), T(""));
+
+/*
+ * Parse the header and create the Http header keyword variables
+ * We rewrite the header as we go for non-local requests. NOTE: this
+ * modifies the header string directly and tokenizes each line with '\0'.
+ */
+ browser = NULL;
+ for (lp = (char_t*) wp->header.servp; lp && *lp; ) {
+ cp = lp;
+ if ((lp = gstrchr(lp, '\n')) != NULL) {
+ lp++;
+ }
+
+ if ((key = gstrtok(cp, T(": \t\n"))) == NULL) {
+ continue;
+ }
+
+ if ((value = gstrtok(NULL, T("\n"))) == NULL) {
+ value = T("");
+ }
+
+ while (gisspace(*value)) {
+ value++;
+ }
+ strlower(key);
+
+/*
+ * Create a variable (CGI) for each line in the header
+ */
+ fmtAlloc(&upperKey, (gstrlen(key) + 6), T("HTTP_%s"), key);
+ for (cp = upperKey; *cp; cp++) {
+ if (*cp == '-')
+ *cp = '_';
+ }
+ strupper(upperKey);
+ websSetVar(wp, upperKey, value);
+ bfree(B_L, upperKey);
+
+/*
+ * Track the requesting agent (browser) type
+ */
+ if (gstrcmp(key, T("user-agent")) == 0) {
+ wp->userAgent = bstrdup(B_L, value);
+
+/*
+ * Parse the user authorization. ie. password
+ */
+ } else if (gstricmp(key, T("authorization")) == 0) {
+/*
+ * Determine the type of Authorization Request
+ */
+ authType = bstrdup (B_L, value);
+ a_assert (authType);
+/*
+ * Truncate authType at the next non-alpha character
+ */
+ cp = authType;
+ while (gisalpha(*cp)) {
+ cp++;
+ }
+ *cp = '\0';
+
+ wp->authType = bstrdup(B_L, authType);
+ bfree(B_L, authType);
+
+ if (gstricmp(wp->authType, T("basic")) == 0) {
+ char_t userAuth[FNAMESIZE];
+/*
+ * The incoming value is username:password (Basic authentication)
+ */
+ if ((cp = gstrchr(value, ' ')) != NULL) {
+ *cp = '\0';
+ /*
+ * bugfix 5/24/02 -- we were leaking the memory pointed to by
+ * wp->authType that was allocated just before the if()
+ * statement that we are currently in. Thanks to Simon Byholm.
+ */
+ bfree(B_L, wp->authType);
+ wp->authType = bstrdup(B_L, value);
+ websDecode64(userAuth, ++cp, sizeof(userAuth));
+ } else {
+ websDecode64(userAuth, value, sizeof(userAuth));
+ }
+/*
+ * Split userAuth into userid and password
+ */
+ if ((cp = gstrchr(userAuth, ':')) != NULL) {
+ *cp++ = '\0';
+ }
+ if (cp) {
+ wp->userName = bstrdup(B_L, userAuth);
+ wp->password = bstrdup(B_L, cp);
+ } else {
+ wp->userName = bstrdup(B_L, T(""));
+ wp->password = bstrdup(B_L, T(""));
+ }
+/*
+ * Set the flags to indicate digest authentication
+ */
+ wp->flags |= WEBS_AUTH_BASIC;
+ } else {
+#ifdef DIGEST_ACCESS_SUPPORT
+/*
+ * The incoming value is slightly more complicated (Digest)
+ */
+ char_t *np; /* pointer to end of tag name */
+ char_t tp; /* temporary character holding space */
+ char_t *vp; /* pointer to value */
+ char_t *npv; /* pointer to end of value, "next" pointer */
+ char_t tpv; /* temporary character holding space */
+/*
+ * Set the flags to indicate digest authentication
+ */
+ wp->flags |= WEBS_AUTH_DIGEST;
+/*
+ * Move cp to Next word beyond "Digest",
+ * vp to first char after '='.
+ */
+ cp = value;
+ while (isgoodchar(*cp)) {
+ cp++;
+ }
+ while (!isgoodchar(*cp)) {
+ cp++;
+ }
+
+/*
+ * Find beginning of value
+ */
+ vp = gstrchr(cp, '=');
+ while (vp) {
+/*
+ * Zero-terminate tag name
+ */
+ np = cp;
+ while (isgoodchar(*np)) {
+ np++;
+ }
+ tp = *np;
+ *np = 0;
+/*
+ * Advance value pointer to first legit character
+ */
+ vp++;
+ while (!isgoodchar(*vp)) {
+ vp++;
+ }
+/*
+ * Zero-terminate value
+ */
+ npv = vp;
+ while (isgoodchar(*npv)) {
+ npv++;
+ }
+ tpv = *npv;
+ *npv = 0;
+/*
+ * Extract the fields
+ */
+ if (gstricmp(cp, T("username")) == 0) {
+ wp->userName = bstrdup(B_L, vp);
+ } else if (gstricmp(cp, T("response")) == 0) {
+ wp->digest = bstrdup(B_L, vp);
+ } else if (gstricmp(cp, T("opaque")) == 0) {
+ wp->opaque = bstrdup(B_L, vp);
+ } else if (gstricmp(cp, T("uri")) == 0) {
+ wp->uri = bstrdup(B_L, vp);
+ } else if (gstricmp(cp, T("realm")) == 0) {
+ wp->realm = bstrdup(B_L, vp);
+ } else if (gstricmp(cp, T("nonce")) == 0) {
+ wp->nonce = bstrdup(B_L, vp);
+ } else if (gstricmp(cp, T("nc")) == 0) {
+ wp->nc = bstrdup(B_L, vp);
+ } else if (gstricmp(cp, T("cnonce")) == 0) {
+ wp->cnonce = bstrdup(B_L, vp);
+ } else if (gstricmp(cp, T("qop")) == 0) {
+ wp->qop = bstrdup(B_L, vp);
+ }
+/*
+ * Restore tag name and value zero-terminations
+ */
+ *np = tp;
+ *npv = tpv;
+/*
+ * Advance tag name and value pointers
+ */
+ cp = npv;
+ while (*cp && isgoodchar(*cp)) {
+ cp++;
+ }
+ while (*cp && !isgoodchar(*cp)) {
+ cp++;
+ }
+
+ if (*cp) {
+ vp = gstrchr(cp, '=');
+ } else {
+ vp = NULL;
+ }
+ }
+#endif /* DIGEST_ACCESS_SUPPORT */
+ } /* if (gstrcmp(wp->authType)) */
+/*
+ * Parse the content length
+ */
+ } else if (gstrcmp(key, T("content-length")) == 0) {
+ /*
+ * 11 Oct 02 BgP -- The server would crash if an attacker sent a POST
+ * message with a content-length value <= 0. We assume that anyone
+ * sending this is malicious, and the POST is read from the socket,
+ * but it is ignored, and the socket is closed.
+ */
+ wp->clen = gatoi(value);
+ if (wp->clen > 0)
+ {
+ wp->flags |= WEBS_CLEN;
+ websSetVar(wp, T("CONTENT_LENGTH"), value);
+ }
+ else
+ {
+ wp->clen = 0;
+ }
+
+/*
+ * Parse the content type
+ */
+ } else if (gstrcmp(key, T("content-type")) == 0) {
+ websSetVar(wp, T("CONTENT_TYPE"), value);
+
+#ifdef WEBS_KEEP_ALIVE_SUPPORT
+ } else if (gstrcmp(key, T("connection")) == 0) {
+ strlower(value);
+ if (gstrcmp(value, T("keep-alive")) == 0) {
+ wp->flags |= WEBS_KEEP_ALIVE;
+ }
+#endif
+
+#ifdef WEBS_PROXY_SUPPORT
+/*
+ * This may be useful if you wish to keep a local cache of web pages
+ * for proxied requests.
+ */
+ } else if (gstrcmp(key, T("pragma")) == 0) {
+ char_t tmp[256];
+ gstrncpy(tmp, value, TSZ(tmp));
+ strlower(tmp);
+ if (gstrstr(tmp, T("no-cache"))) {
+ wp->flags |= WEBS_DONT_USE_CACHE;
+ }
+#endif /* WEBS_PROXY_SUPPORT */
+
+/*
+ * Store the cookie
+ */
+ } else if (gstrcmp(key, T("cookie")) == 0) {
+ wp->flags |= WEBS_COOKIE;
+ wp->cookie = bstrdup(B_L, value);
+
+#ifdef WEBS_IF_MODIFIED_SUPPORT
+/*
+ * See if the local page has been modified since the browser last
+ * requested this document. If not, just return a 302
+ */
+ } else if (gstrcmp(key, T("if-modified-since")) == 0) {
+ char_t *cmd;
+ time_t tip = 0;
+
+ if ((cp = gstrchr(value, ';')) != NULL) {
+ *cp = '\0';
+ }
+
+ fmtAlloc(&cmd, 64, T("%s"), value);
+
+ if ((wp->since = dateParse(tip, cmd)) != 0) {
+ wp->flags |= WEBS_IF_MODIFIED;
+ }
+
+ bfreeSafe(B_L, cmd);
+#endif /* WEBS_IF_MODIFIED_SUPPORT */
+ }
+ }
+}
+
+/******************************************************************************/
+/*
+ * Set the variable (CGI) environment for this request. Create variables
+ * for all standard CGI variables. Also decode the query string and create
+ * a variable for each name=value pair.
+ */
+
+void websSetEnv(webs_t wp)
+{
+ char_t portBuf[8];
+ char_t *keyword, *value, *valCheck, *valNew;
+
+ a_assert(websValid(wp));
+
+ websSetVar(wp, T("QUERY_STRING"), wp->query);
+ websSetVar(wp, T("GATEWAY_INTERFACE"), T("CGI/1.1"));
+ websSetVar(wp, T("SERVER_HOST"), websHost);
+ websSetVar(wp, T("SERVER_NAME"), websHost);
+ websSetVar(wp, T("SERVER_URL"), websHostUrl);
+ websSetVar(wp, T("REMOTE_HOST"), wp->ipaddr);
+ websSetVar(wp, T("REMOTE_ADDR"), wp->ipaddr);
+ websSetVar(wp, T("PATH_INFO"), wp->path);
+ stritoa(websPort, portBuf, sizeof(portBuf));
+ websSetVar(wp, T("SERVER_PORT"), portBuf);
+ websSetVar(wp, T("SERVER_ADDR"), websIpaddr);
+ fmtAlloc(&value, FNAMESIZE, T("%s/%s"), WEBS_NAME, WEBS_VERSION);
+ websSetVar(wp, T("SERVER_SOFTWARE"), value);
+ bfreeSafe(B_L, value);
+ websSetVar(wp, T("SERVER_PROTOCOL"), wp->protoVersion);
+
+/*
+ * Decode and create an environment query variable for each query keyword.
+ * We split into pairs at each '&', then split pairs at the '='.
+ * Note: we rely on wp->decodedQuery preserving the decoded values in the
+ * symbol table.
+ */
+ wp->decodedQuery = bstrdup(B_L, wp->query);
+ keyword = gstrtok(wp->decodedQuery, T("&"));
+ while (keyword != NULL) {
+ if ((value = gstrchr(keyword, '=')) != NULL) {
+ *value++ = '\0';
+ websDecodeUrl(keyword, keyword, gstrlen(keyword));
+ websDecodeUrl(value, value, gstrlen(value));
+ } else {
+ value = T("");
+ }
+
+ if (*keyword) {
+/*
+ * If keyword has already been set, append the new value to what has
+ * been stored.
+ */
+ if ((valCheck = websGetVar(wp, keyword, NULL)) != 0) {
+ fmtAlloc(&valNew, 256, T("%s %s"), valCheck, value);
+ websSetVar(wp, keyword, valNew);
+ bfreeSafe(B_L, valNew);
+ } else {
+ websSetVar(wp, keyword, value);
+ }
+ }
+ keyword = gstrtok(NULL, T("&"));
+ }
+
+#ifdef EMF
+/*
+ * Add GoAhead Embedded Management Framework defines
+ */
+ websSetEmfEnvironment(wp);
+#endif
+}
+
+/******************************************************************************/
+/*
+ * Define a webs (CGI) variable for this connection. Also create in relevant
+ * scripting engines. Note: the incoming value may be volatile.
+ */
+
+void websSetVar(webs_t wp, char_t *var, char_t *value)
+{
+ value_t v;
+
+ a_assert(websValid(wp));
+
+/*
+ * value_instring will allocate the string if required.
+ */
+ if (value) {
+ v = valueString(value, VALUE_ALLOCATE);
+ } else {
+ v = valueString(T(""), VALUE_ALLOCATE);
+ }
+ symEnter(wp->cgiVars, var, v, 0);
+}
+
+/******************************************************************************/
+/*
+ * Return TRUE if a webs variable exists for this connection.
+ */
+
+int websTestVar(webs_t wp, char_t *var)
+{
+ sym_t *sp;
+
+ a_assert(websValid(wp));
+
+ if (var == NULL || *var == '\0') {
+ return 0;
+ }
+
+ if ((sp = symLookup(wp->cgiVars, var)) == NULL) {
+ return 0;
+ }
+ return 1;
+}
+
+/******************************************************************************/
+/*
+ * Get a webs variable but return a default value if string not found.
+ * Note, defaultGetValue can be NULL to permit testing existence.
+ */
+
+char_t *websGetVar(webs_t wp, char_t *var, char_t *defaultGetValue)
+{
+ sym_t *sp;
+
+ a_assert(websValid(wp));
+ a_assert(var && *var);
+
+ if ((sp = symLookup(wp->cgiVars, var)) != NULL) {
+ a_assert(sp->content.type == string);
+ if (sp->content.value.string) {
+ return sp->content.value.string;
+ } else {
+ return T("");
+ }
+ }
+ return defaultGetValue;
+}
+
+/******************************************************************************/
+/*
+ * Return TRUE if a webs variable is set to a given value
+ */
+
+int websCompareVar(webs_t wp, char_t *var, char_t *value)
+{
+ a_assert(websValid(wp));
+ a_assert(var && *var);
+
+ if (gstrcmp(value, websGetVar(wp, var, T(" __UNDEF__ "))) == 0) {
+ return 1;
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Cancel the request timeout. Note may be called multiple times.
+ */
+
+void websTimeoutCancel(webs_t wp)
+{
+ a_assert(websValid(wp));
+
+ if (wp->timeout >= 0) {
+ emfUnschedCallback(wp->timeout);
+ wp->timeout = -1;
+ }
+}
+
+/******************************************************************************/
+/*
+ * Output a HTTP response back to the browser. If redirect is set to a
+ * URL, the browser will be sent to this location.
+ */
+
+void websResponse(webs_t wp, int code, char_t *message, char_t *redirect)
+{
+ char_t *date;
+
+ a_assert(websValid(wp));
+
+/*
+ * IE3.0 needs no Keep Alive for some return codes.
+ */
+ wp->flags &= ~WEBS_KEEP_ALIVE;
+
+/*
+ * Only output the header if a header has not already been output.
+ */
+ if ( !(wp->flags & WEBS_HEADER_DONE)) {
+ wp->flags |= WEBS_HEADER_DONE;
+/*
+ * Redirect behaves much better when sent with HTTP/1.0
+ */
+ if (redirect != NULL) {
+ websWrite(wp, T("HTTP/1.0 %d %s\r\n"), code, websErrorMsg(code));
+ } else {
+ websWrite(wp, T("HTTP/1.1 %d %s\r\n"), code, websErrorMsg(code));
+ }
+
+/*
+ * By license terms the following line of code must not be modified.
+ */
+ websWrite(wp, T("Server: %s\r\n"), WEBS_NAME);
+
+/*
+ * Timestamp/Date is usually the next to go
+ */
+ if ((date = websGetDateString(NULL)) != NULL) {
+ websWrite(wp, T("Date: %s\r\n"), date);
+ bfree(B_L, date);
+ }
+/*
+ * If authentication is required, send the auth header info
+ */
+ if (code == 401) {
+ if (!(wp->flags & WEBS_AUTH_DIGEST)) {
+ websWrite(wp, T("WWW-Authenticate: Basic realm=\"%s\"\r\n"),
+ websGetRealm());
+#ifdef DIGEST_ACCESS_SUPPORT
+ } else {
+ char_t *nonce, *opaque;
+
+ /* $$$ before... (note commas instead of semicolons...)
+ nonce = websCalcNonce(wp),
+ opaque = websCalcOpaque(wp),
+ $$$ after */
+ nonce = websCalcNonce(wp);
+ opaque = websCalcOpaque(wp);
+ /* ...$$$ end */
+ websWrite(wp,
+ T("WWW-Authenticate: Digest realm=\"%s\", domain=\"%s\",")
+ T("qop=\"%s\", nonce=\"%s\", opaque=\"%s\",")
+ T("algorithm=\"%s\", stale=\"%s\"\r\n"),
+ websGetRealm(),
+ websGetHostUrl(),
+ T("auth"),
+ nonce,
+ opaque, T("MD5"), T("FALSE"));
+ bfree(B_L, nonce);
+ bfree(B_L, opaque);
+#endif
+ }
+ }
+
+ if (wp->flags & WEBS_KEEP_ALIVE) {
+ websWrite(wp, T("Connection: keep-alive\r\n"));
+ }
+
+ websWrite(wp, T("Pragma: no-cache\r\nCache-Control: no-cache\r\n"));
+ websWrite(wp, T("Content-Type: text/html\r\n"));
+/*
+ * We don't do a string length here as the message may be multi-line.
+ * Ie. <CR><LF> will count as only one and we will have a content-length
+ * that is too short.
+ *
+ * websWrite(wp, T("Content-Length: %s\r\n"), message);
+ */
+ if (redirect) {
+ websWrite(wp, T("Location: %s\r\n"), redirect);
+ }
+ websWrite(wp, T("\r\n"));
+ }
+
+/*
+ * If the browser didn't do a HEAD only request, send the message as well.
+ */
+ if ((wp->flags & WEBS_HEAD_REQUEST) == 0 && message && *message) {
+ websWrite(wp, T("%s\r\n"), message);
+ }
+ websDone(wp, code);
+}
+
+/******************************************************************************/
+/*
+ * Redirect the user to another webs page
+ */
+
+void websRedirect(webs_t wp, char_t *url)
+{
+ char_t *msgbuf, *urlbuf, *redirectFmt;
+
+ a_assert(websValid(wp));
+ a_assert(url);
+
+ websStats.redirects++;
+ msgbuf = urlbuf = NULL;
+
+/*
+ * Some browsers require a http://host qualified URL for redirection
+ */
+ if (gstrstr(url, T("http://")) == NULL) {
+ if (*url == '/') {
+ url++;
+ }
+
+ redirectFmt = T("http://%s/%s");
+
+#ifdef WEBS_SSL_SUPPORT
+ if (wp->flags & WEBS_SECURE) {
+ redirectFmt = T("https://%s/%s");
+ }
+#endif
+
+ fmtAlloc(&urlbuf, WEBS_MAX_URL + 80, redirectFmt,
+ websGetVar(wp, T("HTTP_HOST"), websHostUrl), url);
+ url = urlbuf;
+ }
+
+/*
+ * Add human readable message for completeness. Should not be required.
+ */
+ fmtAlloc(&msgbuf, WEBS_MAX_URL + 80,
+ T("<html><head></head><body>\r\n\
+ This document has moved to a new <a href=\"%s\">location</a>.\r\n\
+ Please update your documents to reflect the new location.\r\n\
+ </body></html>\r\n"), url);
+
+ websResponse(wp, 302, msgbuf, url);
+
+ bfreeSafe(B_L, msgbuf);
+ bfreeSafe(B_L, urlbuf);
+}
+
+/******************************************************************************/
+/*
+ * Output an error message and cleanup
+ */
+
+#ifdef qRichErrorPage
+extern int dmfRichError(webs_t wp, int code, char_t* userMsg);
+#endif
+void websError(webs_t wp, int code, char_t *fmt, ...)
+{
+ va_list args;
+ char_t *msg, *userMsg, *buf;
+#ifdef qRichErrorPage
+ static int reEntry = 0;
+ int errorOk;
+#endif
+
+ a_assert(websValid(wp));
+ a_assert(fmt);
+
+ websStats.errors++;
+
+ va_start(args, fmt);
+ userMsg = NULL;
+ fmtValloc(&userMsg, WEBS_BUFSIZE, fmt, args);
+ va_end(args);
+
+#ifdef qRichErrorPage
+ if (!reEntry)
+ {
+ /*
+ * The dmfRichError function that we're about to call may very well call
+ * websError() as part of its work. If that happens, we do NOT want to
+ * get into a never-ending recursive call chain. When we get back here
+ * in a call from inside dmfRichError(), we check to see if we're
+ * already trying to call dmfRichError. If we are, we just revert to the
+ * old non-rich behavior and display a black on white error page.
+ */
+
+ reEntry = 1;
+ errorOk = dmfRichError(wp, code, userMsg);
+ reEntry = 0;
+ if (errorOk)
+ {
+ return;
+ }
+ /* ...else we need to fall through and execute the simple error page. */
+ }
+ /* implicit else... */
+#endif
+
+ msg = T("<html><head><title>Document Error: %s</title></head>\r\n\
+ <body><h2>Access Error: %s</h2>\r\n\
+ when trying to obtain <b>%s</b><br><p>%s</p></body></html>\r\n");
+/*
+ * Ensure we have plenty of room
+ */
+ buf = NULL;
+ fmtAlloc(&buf, WEBS_BUFSIZE, msg, websErrorMsg(code),
+ websErrorMsg(code), wp->url, userMsg);
+
+ websResponse(wp, code, buf, NULL);
+ bfreeSafe(B_L, buf);
+ bfreeSafe(B_L, userMsg);
+}
+
+/******************************************************************************/
+/*
+ * Return the error message for a given code
+ */
+
+/*static char_t *websErrorMsg(int code)*/
+char_t *websErrorMsg(int code)
+{
+ websErrorType *ep;
+
+ for (ep = websErrors; ep->code; ep++) {
+ if (code == ep->code) {
+ return ep->msg;
+ }
+ }
+ a_assert(0);
+ return T("");
+}
+
+/******************************************************************************/
+/*
+ * Do formatted output to the browser. This is the public ASP and form
+ * write procedure.
+ */
+
+int websWrite(webs_t wp, char_t *fmt, ...)
+{
+ va_list vargs;
+ char_t *buf;
+ int rc;
+
+ a_assert(websValid(wp));
+
+ va_start(vargs, fmt);
+
+ buf = NULL;
+ rc = 0;
+
+ if (fmtValloc(&buf, WEBS_BUFSIZE, fmt, vargs) >= WEBS_BUFSIZE) {
+ trace(0, T("webs: websWrite lost data, buffer overflow\n"));
+ }
+
+ va_end(vargs);
+ a_assert(buf);
+ if (buf) {
+ rc = websWriteBlock(wp, buf, gstrlen(buf));
+ bfree(B_L, buf);
+ }
+ return rc;
+}
+
+/******************************************************************************/
+/*
+ * Write a block of data of length "nChars" to the user's browser. Public
+ * write block procedure. If unicode is turned on this function expects
+ * buf to be a unicode string and it converts it to ASCII before writing.
+ * See websWriteDataNonBlock to always write binary or ASCII data with no
+ * unicode conversion. This returns the number of char_t's processed.
+ * It spins until nChars are flushed to the socket. For non-blocking
+ * behavior, use websWriteDataNonBlock.
+ */
+
+int websWriteBlock(webs_t wp, char_t *buf, int nChars)
+{
+ int len, done;
+ char *asciiBuf, *pBuf;
+
+ a_assert(wp);
+ a_assert(websValid(wp));
+ a_assert(buf);
+ a_assert(nChars >= 0);
+
+ done = len = 0;
+
+/*
+ * ballocUniToAsc will convert Unicode to strings to Ascii. If Unicode is
+ * not turned on then ballocUniToAsc will not do the conversion.
+ */
+ pBuf = asciiBuf = ballocUniToAsc(buf, nChars);
+
+ while (nChars > 0) {
+#ifdef WEBS_SSL_SUPPORT
+ if (wp->flags & WEBS_SECURE) {
+ if ((len = websSSLWrite(wp->wsp, pBuf, nChars)) < 0) {
+ bfree(B_L, asciiBuf);
+ return -1;
+ }
+ websSSLFlush(wp->wsp);
+ } else {
+ if ((len = socketWrite(wp->sid, pBuf, nChars)) < 0) {
+ bfree(B_L, asciiBuf);
+ return -1;
+ }
+ socketFlush(wp->sid);
+ }
+#else /* ! WEBS_SSL_SUPPORT */
+ if ((len = socketWrite(wp->sid, pBuf, nChars)) < 0) {
+ bfree(B_L, asciiBuf);
+ return -1;
+ }
+ socketFlush(wp->sid);
+#endif /* WEBS_SSL_SUPPORT */
+ nChars -= len;
+ pBuf += len;
+ done += len;
+ }
+
+ bfree(B_L, asciiBuf);
+ return done;
+}
+
+/******************************************************************************/
+/*
+ * Write a block of data of length "nChars" to the user's browser. Same as
+ * websWriteBlock except that it expects straight ASCII or binary and does no
+ * unicode conversion before writing the data. If the socket cannot hold all
+ * the data, it will return the number of bytes flushed to the socket before
+ * it would have blocked. This returns the number of chars processed or -1
+ * if socketWrite fails.
+ */
+
+int websWriteDataNonBlock(webs_t wp, char *buf, int nChars)
+{
+ int r;
+
+ a_assert(wp);
+ a_assert(websValid(wp));
+ a_assert(buf);
+ a_assert(nChars >= 0);
+
+#ifdef WEBS_SSL_SUPPORT
+ if (wp->flags & WEBS_SECURE) {
+ r = websSSLWrite(wp->wsp, buf, nChars);
+ websSSLFlush(wp->wsp);
+ } else {
+ r = socketWrite(wp->sid, buf, nChars);
+ socketFlush(wp->sid);
+ }
+#else
+ r = socketWrite(wp->sid, buf, nChars);
+ socketFlush(wp->sid);
+#endif
+
+ return r;
+}
+
+/******************************************************************************/
+/*
+ * Decode a URL (or part thereof). Allows insitu decoding.
+ */
+
+void websDecodeUrl(char_t *decoded, char_t *token, int len)
+{
+ char_t *ip, *op;
+ int num, i, c;
+
+ a_assert(decoded);
+ a_assert(token);
+
+ op = decoded;
+ for (ip = token; *ip && len > 0; ip++, op++) {
+ if (*ip == '+') {
+ *op = ' ';
+ } else if (*ip == '%' && gisxdigit(ip[1]) && gisxdigit(ip[2])) {
+
+/*
+ * Convert %nn to a single character
+ */
+ ip++;
+ for (i = 0, num = 0; i < 2; i++, ip++) {
+ c = tolower(*ip);
+ if (c >= 'a' && c <= 'f') {
+ num = (num * 16) + 10 + c - 'a';
+ } else {
+ num = (num * 16) + c - '0';
+ }
+ }
+ *op = (char_t) num;
+ ip--;
+
+ } else {
+ *op = *ip;
+ }
+ len--;
+ }
+ *op = '\0';
+}
+
+/******************************************************************************/
+#ifdef WEBS_LOG_SUPPORT
+/*
+ * Output a log message
+ */
+
+static void websLog(webs_t wp, int code)
+{
+ char_t *buf;
+ char *abuf;
+ int len;
+#define qAnlLog 1
+#ifdef qAnlLog
+ time_t timer;
+ char_t* newLine = NULL;
+ char_t* timeStr = NULL;
+#endif
+ a_assert(websValid(wp));
+
+ buf = NULL;
+
+#ifdef qAnlLog
+ time(&timer);
+ timeStr = ctime(&timer);
+ newLine = gstrchr(timeStr, '\n');
+ if (newLine)
+ {
+ *newLine = '\0';
+ }
+ fmtAlloc(&buf, WEBS_MAX_URL + 80, T("%s\t%s\t%s\tcode = %d\n"),
+ timeStr, wp->ipaddr, wp->url, code);
+#else
+ fmtAlloc(&buf, WEBS_MAX_URL + 80, T("%d %s %d %d\n"), time(0),
+ wp->url, code, wp->written);
+#endif
+ len = gstrlen(buf);
+ abuf = ballocUniToAsc(buf, len+1);
+ write(websLogFd, abuf, len);
+ bfreeSafe(B_L, buf);
+ bfreeSafe(B_L, abuf);
+}
+
+#endif /* WEBS_LOG_SUPPORT */
+
+/******************************************************************************/
+/*
+ * Request timeout. The timeout triggers if we have not read any data from
+ * the users browser in the last WEBS_TIMEOUT period. If we have heard from
+ * the browser, simply re-issue the timeout.
+ */
+
+void websTimeout(void *arg, int id)
+{
+ webs_t wp;
+ int delay, tm;
+
+ wp = (webs_t) arg;
+ a_assert(websValid(wp));
+
+ tm = websGetTimeSinceMark(wp) * 1000;
+ if (tm >= WEBS_TIMEOUT) {
+ websStats.timeouts++;
+ emfUnschedCallback(id);
+
+/*
+ * Clear the timeout id
+ */
+ wp->timeout = -1;
+ websDone(wp, 404);
+ } else {
+ delay = WEBS_TIMEOUT - tm;
+ a_assert(delay > 0);
+ emfReschedCallback(id, delay);
+ }
+}
+
+/******************************************************************************/
+/*
+ * Called when the request is done.
+ */
+
+void websDone(webs_t wp, int code)
+{
+ a_assert(websValid(wp));
+
+/*
+ * Disable socket handler in case keep alive set.
+ */
+ socketDeleteHandler(wp->sid);
+
+ if (code != 200) {
+ wp->flags &= ~WEBS_KEEP_ALIVE;
+ }
+
+#ifdef WEBS_PROXY_SUPPORT
+ if (! (wp->flags & WEBS_LOCAL_PAGE)) {
+ websStats.activeNetRequests--;
+ }
+#endif
+
+#ifdef WEBS_LOG_SUPPORT
+ if (! (wp->flags & WEBS_REQUEST_DONE)) {
+ websLog(wp, code);
+ }
+#endif
+
+/*
+ * Close any opened document by a handler
+ */
+ websPageClose(wp);
+
+/*
+ * Exit if secure.
+ */
+#ifdef WEBS_SSL_SUPPORT
+ if (wp->flags & WEBS_SECURE) {
+ websTimeoutCancel(wp);
+ websSSLFlush(wp->wsp);
+ socketCloseConnection(wp->sid);
+ websFree(wp);
+ return;
+ }
+#endif
+
+/*
+ * If using Keep Alive (HTTP/1.1) we keep the socket open for a period
+ * while waiting for another request on the socket.
+ */
+ if (wp->flags & WEBS_KEEP_ALIVE) {
+ if (socketFlush(wp->sid) == 0) {
+ wp->state = WEBS_BEGIN;
+ wp->flags |= WEBS_REQUEST_DONE;
+ if (wp->header.buf) {
+ ringqFlush(&wp->header);
+ }
+ socketCreateHandler(wp->sid, SOCKET_READABLE, websSocketEvent,
+ (int) wp);
+ websTimeoutCancel(wp);
+ wp->timeout = emfSchedCallback(WEBS_TIMEOUT, websTimeout,
+ (void *) wp);
+ return;
+ }
+ } else {
+ websTimeoutCancel(wp);
+ socketSetBlock(wp->sid, 1);
+ socketFlush(wp->sid);
+ socketCloseConnection(wp->sid);
+ }
+ websFree(wp);
+}
+
+/******************************************************************************/
+/*
+ * Allocate a new webs structure
+ */
+
+int websAlloc(int sid)
+{
+ webs_t wp;
+ int wid;
+
+/*
+ * Allocate a new handle for this connection
+ */
+ if ((wid = hAllocEntry((void*) &webs, &websMax,
+ sizeof(struct websRec))) < 0) {
+ return -1;
+ }
+ wp = webs[wid];
+
+ wp->wid = wid;
+ wp->sid = sid;
+ wp->state = WEBS_BEGIN;
+ wp->docfd = -1;
+ wp->timeout = -1;
+ wp->dir = NULL;
+ wp->authType = NULL;
+ wp->protocol = NULL;
+ wp->protoVersion = NULL;
+ wp->password = NULL;
+ wp->userName = NULL;
+#ifdef DIGEST_ACCESS_SUPPORT
+ wp->realm = NULL;
+ wp->nonce = NULL;
+ wp->digest = NULL;
+ wp->uri = NULL;
+ wp->opaque = NULL;
+ wp->nc = NULL;
+ wp->cnonce = NULL;
+ wp->qop = NULL;
+#endif
+#ifdef WEBS_SSL_SUPPORT
+ wp->wsp = NULL;
+#endif
+
+ ringqOpen(&wp->header, WEBS_HEADER_BUFINC, WEBS_MAX_HEADER);
+
+/*
+ * Create storage for the CGI variables. We supply the symbol tables for
+ * both the CGI variables and for the global functions. The function table
+ * is common to all webs instances (ie. all browsers)
+ */
+ wp->cgiVars = symOpen(WEBS_SYM_INIT);
+
+ return wid;
+}
+
+/******************************************************************************/
+/*
+ * Free a webs structure
+ */
+
+void websFree(webs_t wp)
+{
+ a_assert(websValid(wp));
+
+ if (wp->path)
+ bfree(B_L, wp->path);
+ if (wp->url)
+ bfree(B_L, wp->url);
+ if (wp->host)
+ bfree(B_L, wp->host);
+ if (wp->lpath)
+ bfree(B_L, wp->lpath);
+ if (wp->query)
+ bfree(B_L, wp->query);
+ if (wp->decodedQuery)
+ bfree(B_L, wp->decodedQuery);
+ if (wp->authType)
+ bfree(B_L, wp->authType);
+ if (wp->password)
+ bfree(B_L, wp->password);
+ if (wp->userName)
+ bfree(B_L, wp->userName);
+ if (wp->cookie)
+ bfree(B_L, wp->cookie);
+ if (wp->userAgent)
+ bfree(B_L, wp->userAgent);
+ if (wp->dir)
+ bfree(B_L, wp->dir);
+ if (wp->protocol)
+ bfree(B_L, wp->protocol);
+ if (wp->protoVersion)
+ bfree(B_L, wp->protoVersion);
+ if (wp->cgiStdin)
+ bfree(B_L, wp->cgiStdin);
+
+
+#ifdef DIGEST_ACCESS_SUPPORT
+ if (wp->realm)
+ bfree(B_L, wp->realm);
+ if (wp->uri)
+ bfree(B_L, wp->uri);
+ if (wp->digest)
+ bfree(B_L, wp->digest);
+ if (wp->opaque)
+ bfree(B_L, wp->opaque);
+ if (wp->nonce)
+ bfree(B_L, wp->nonce);
+ if (wp->nc)
+ bfree(B_L, wp->nc);
+ if (wp->cnonce)
+ bfree(B_L, wp->cnonce);
+ if (wp->qop)
+ bfree(B_L, wp->qop);
+#endif
+#ifdef WEBS_SSL_SUPPORT
+ websSSLFree(wp->wsp);
+#endif
+ symClose(wp->cgiVars);
+
+ if (wp->header.buf) {
+ ringqClose(&wp->header);
+ }
+
+ websMax = hFree((void*) &webs, wp->wid);
+ bfree(B_L, wp);
+ a_assert(websMax >= 0);
+}
+
+/******************************************************************************/
+/*
+ * Return the server address
+ */
+
+char_t *websGetHost()
+{
+ return websHost;
+}
+
+/******************************************************************************/
+/*
+ * Return the the url to access the server. (ip address)
+ */
+
+char_t *websGetIpaddrUrl()
+{
+ return websIpaddrUrl;
+}
+
+/******************************************************************************/
+/*
+ * Return the server address
+ */
+
+char_t *websGetHostUrl()
+{
+ return websHostUrl;
+}
+
+/******************************************************************************/
+/*
+ * Return the listen port
+ */
+
+int websGetPort()
+{
+ return websPort;
+}
+
+/******************************************************************************/
+/*
+ * Get the number of bytes to write
+ */
+
+int websGetRequestBytes(webs_t wp)
+{
+ a_assert(websValid(wp));
+
+ return wp->numbytes;
+}
+
+/******************************************************************************/
+/*
+ * Get the directory for this request
+ */
+
+char_t *websGetRequestDir(webs_t wp)
+{
+ a_assert(websValid(wp));
+
+ if (wp->dir == NULL) {
+ return T("");
+ }
+
+ return wp->dir;
+}
+
+/******************************************************************************/
+/*
+ * Get the flags for this request
+ */
+
+int websGetRequestFlags(webs_t wp)
+{
+ a_assert(websValid(wp));
+
+ return wp->flags;
+}
+
+/******************************************************************************/
+/*
+ * Return the IP address
+ */
+
+char_t *websGetRequestIpaddr(webs_t wp)
+{
+ a_assert(websValid(wp));
+
+ return wp->ipaddr;
+}
+
+/******************************************************************************/
+/*
+ * Set the local path for the request
+ */
+
+char_t *websGetRequestLpath(webs_t wp)
+{
+ a_assert(websValid(wp));
+
+#ifdef WEBS_PAGE_ROM
+ return wp->path;
+#else
+ return wp->lpath;
+#endif
+}
+
+/******************************************************************************/
+/*
+ * Get the path for this request
+ */
+
+char_t *websGetRequestPath(webs_t wp)
+{
+ a_assert(websValid(wp));
+
+ if (wp->path == NULL) {
+ return T("");
+ }
+
+ return wp->path;
+}
+
+/******************************************************************************/
+/*
+ * Return the password
+ */
+
+char_t *websGetRequestPassword(webs_t wp)
+{
+ a_assert(websValid(wp));
+
+ return wp->password;
+}
+
+/******************************************************************************/
+/*
+ * Return the request type
+ */
+
+char_t *websGetRequestType(webs_t wp)
+{
+ a_assert(websValid(wp));
+
+ return wp->type;
+}
+
+/******************************************************************************/
+/*
+ * Return the username
+ */
+
+char_t *websGetRequestUserName(webs_t wp)
+{
+ a_assert(websValid(wp));
+
+ return wp->userName;
+}
+
+/******************************************************************************/
+/*
+ * Get the number of bytes written
+ */
+
+int websGetRequestWritten(webs_t wp)
+{
+ a_assert(websValid(wp));
+
+ return wp->written;
+}
+
+/******************************************************************************/
+/*
+ * Set the hostname
+ */
+
+void websSetHost(char_t *host)
+{
+ gstrncpy(websHost, host, TSZ(websHost));
+}
+
+/******************************************************************************/
+/*
+ * Set the host URL
+ */
+
+void websSetHostUrl(char_t *url)
+{
+ a_assert(url && *url);
+
+ bfreeSafe(B_L, websHostUrl);
+ websHostUrl = gstrdup(B_L, url);
+}
+
+/******************************************************************************/
+/*
+ * Set the IP address
+ */
+
+void websSetIpaddr(char_t *ipaddr)
+{
+ a_assert(ipaddr && *ipaddr);
+
+ gstrncpy(websIpaddr, ipaddr, TSZ(websIpaddr));
+}
+
+/******************************************************************************/
+/*
+ * Set the number of bytes to write
+ */
+
+void websSetRequestBytes(webs_t wp, int bytes)
+{
+ a_assert(websValid(wp));
+ a_assert(bytes >= 0);
+
+ wp->numbytes = bytes;
+}
+
+/******************************************************************************/
+/*
+ * Set the flags for this request
+ */
+
+void websSetRequestFlags(webs_t wp, int flags)
+{
+ a_assert(websValid(wp));
+
+ wp->flags = flags;
+}
+
+/******************************************************************************/
+/*
+ * Set the local path for the request
+ */
+
+void websSetRequestLpath(webs_t wp, char_t *lpath)
+{
+ a_assert(websValid(wp));
+ a_assert(lpath && *lpath);
+
+ if (wp->lpath) {
+ bfree(B_L, wp->lpath);
+ }
+ wp->lpath = bstrdup(B_L, lpath);
+ websSetVar(wp, T("PATH_TRANSLATED"), wp->lpath);
+}
+
+/******************************************************************************/
+/*
+ * Update the URL path and the directory containing the web page
+ */
+
+void websSetRequestPath(webs_t wp, char_t *dir, char_t *path)
+{
+ char_t *tmp;
+
+ a_assert(websValid(wp));
+
+ if (dir) {
+ tmp = wp->dir;
+ wp->dir = bstrdup(B_L, dir);
+ if (tmp) {
+ bfree(B_L, tmp);
+ }
+ }
+ if (path) {
+ tmp = wp->path;
+ wp->path = bstrdup(B_L, path);
+ websSetVar(wp, T("PATH_INFO"), wp->path);
+ if (tmp) {
+ bfree(B_L, tmp);
+ }
+ }
+}
+
+/******************************************************************************/
+/*
+ * Set the Write handler for this socket
+ */
+
+void websSetRequestSocketHandler(webs_t wp, int mask, void (*fn)(webs_t wp))
+{
+ a_assert(websValid(wp));
+
+ wp->writeSocket = fn;
+ socketCreateHandler(wp->sid, SOCKET_WRITABLE, websSocketEvent, (int) wp);
+}
+
+/******************************************************************************/
+/*
+ * Set the number of bytes written
+ */
+
+void websSetRequestWritten(webs_t wp, int written)
+{
+ a_assert(websValid(wp));
+
+ wp->written = written;
+}
+
+/******************************************************************************/
+/*
+ * Reurn true if the webs handle is valid
+ */
+
+int websValid(webs_t wp)
+{
+ int wid;
+
+ for (wid = 0; wid < websMax; wid++) {
+ if (wp == webs[wid]) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Build an ASCII time string. If sbuf is NULL we use the current time,
+ * else we use the last modified time of sbuf;
+ */
+
+char_t *websGetDateString(websStatType *sbuf)
+{
+ char_t* cp, *r;
+ time_t now;
+
+ if (sbuf == NULL) {
+ time(&now);
+ } else {
+ now = sbuf->mtime;
+ }
+ if ((cp = gctime(&now)) != NULL) {
+ cp[gstrlen(cp) - 1] = '\0';
+ r = bstrdup(B_L, cp);
+ return r;
+ }
+ return NULL;
+}
+
+/******************************************************************************/
+/*
+ * Mark time. Set a timestamp so that, later, we can return the number of
+ * seconds since we made the mark. Note that the mark my not be a
+ * "real" time, but rather a relative marker.
+ */
+
+void websSetTimeMark(webs_t wp)
+{
+ wp->timestamp = time(0);
+}
+
+/******************************************************************************/
+/*
+ * Get the number of seconds since the last mark.
+ */
+
+static int websGetTimeSinceMark(webs_t wp)
+{
+ return time(0) - wp->timestamp;
+}
+
+/******************************************************************************/
+/*
+ * Store the new realm name
+ */
+
+void websSetRealm(char_t *realmName)
+{
+ a_assert(realmName);
+
+ gstrncpy(websRealm, realmName, TSZ(websRealm));
+}
+
+/******************************************************************************/
+/*
+ * Return the realm name (used for authorization)
+ */
+
+char_t *websGetRealm()
+{
+ return websRealm;
+}
+
+
+#ifdef WEBS_IF_MODIFIED_SUPPORT
+/******************************************************************************/
+/*
+ * These functions are intended to closely mirror the syntax for HTTP-date
+ * from RFC 2616 (HTTP/1.1 spec). This code was submitted by Pete Bergstrom.
+ */
+
+/*
+ * RFC1123Date = wkday "," SP date1 SP time SP "GMT"
+ * RFC850Date = weekday "," SP date2 SP time SP "GMT"
+ * ASCTimeDate = wkday SP date3 SP time SP 4DIGIT
+ *
+ * Each of these functions tries to parse the value and update the index to
+ * the point it leaves off parsing.
+ */
+
+typedef enum { JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC } MonthEnumeration;
+typedef enum { SUN, MON, TUE, WED, THU, FRI, SAT } WeekdayEnumeration;
+
+/******************************************************************************/
+/*
+ * Parse an N-digit value
+ */
+
+static int parseNDIGIT(char_t *buf, int digits, int *index)
+{
+ int tmpIndex, returnValue;
+
+ returnValue = 0;
+
+ for (tmpIndex = *index; tmpIndex < *index+digits; tmpIndex++) {
+ if (gisdigit(buf[tmpIndex])) {
+ returnValue = returnValue * 10 + (buf[tmpIndex] - T('0'));
+ }
+ }
+ *index = tmpIndex;
+
+ return returnValue;
+}
+
+/******************************************************************************/
+/*
+ * Return an index into the month array
+ */
+
+static int parseMonth(char_t *buf, int *index)
+{
+/*
+ * "Jan" | "Feb" | "Mar" | "Apr" | "May" | "Jun" |
+ * "Jul" | "Aug" | "Sep" | "Oct" | "Nov" | "Dec"
+ */
+ int tmpIndex, returnValue;
+
+ returnValue = -1;
+ tmpIndex = *index;
+
+ switch (buf[tmpIndex]) {
+ case 'A':
+ switch (buf[tmpIndex+1]) {
+ case 'p':
+ returnValue = APR;
+ break;
+ case 'u':
+ returnValue = AUG;
+ break;
+ }
+ break;
+ case 'D':
+ returnValue = DEC;
+ break;
+ case 'F':
+ returnValue = FEB;
+ break;
+ case 'J':
+ switch (buf[tmpIndex+1]) {
+ case 'a':
+ returnValue = JAN;
+ break;
+ case 'u':
+ switch (buf[tmpIndex+2]) {
+ case 'l':
+ returnValue = JUL;
+ break;
+ case 'n':
+ returnValue = JUN;
+ break;
+ }
+ break;
+ }
+ break;
+ case 'M':
+ switch (buf[tmpIndex+1]) {
+ case 'a':
+ switch (buf[tmpIndex+2]) {
+ case 'r':
+ returnValue = MAR;
+ break;
+ case 'y':
+ returnValue = MAY;
+ break;
+ }
+ break;
+ }
+ break;
+ case 'N':
+ returnValue = NOV;
+ break;
+ case 'O':
+ returnValue = OCT;
+ break;
+ case 'S':
+ returnValue = SEP;
+ break;
+ }
+
+ if (returnValue >= 0) {
+ *index += 3;
+ }
+
+ return returnValue;
+}
+
+/******************************************************************************/
+/*
+ * Parse a year value (either 2 or 4 digits)
+ */
+
+static int parseYear(char_t *buf, int *index)
+{
+ int tmpIndex, returnValue;
+
+ tmpIndex = *index;
+ returnValue = parseNDIGIT(buf, 4, &tmpIndex);
+
+ if (returnValue >= 0) {
+ *index = tmpIndex;
+ } else {
+ returnValue = parseNDIGIT(buf, 2, &tmpIndex);
+ if (returnValue >= 0) {
+/*
+ * Assume that any year earlier than the start of the
+ * epoch for time_t (1970) specifies 20xx
+ */
+ if (returnValue < 70) {
+ returnValue += 2000;
+ } else {
+ returnValue += 1900;
+ }
+
+ *index = tmpIndex;
+ }
+ }
+
+ return returnValue;
+}
+
+/******************************************************************************/
+/*
+ * The formulas used to build these functions are from "Calendrical Calculations",
+ * by Nachum Dershowitz, Edward M. Reingold, Cambridge University Press, 1997.
+ */
+
+#include <math.h>
+
+const int GregorianEpoch = 1;
+
+/******************************************************************************/
+/*
+ * Determine if year is a leap year
+ */
+
+int GregorianLeapYearP(long year)
+{
+ int result;
+ long tmp;
+
+ tmp = year % 400;
+
+ if ((year % 4 == 0) &&
+ (tmp != 100) &&
+ (tmp != 200) &&
+ (tmp != 300)) {
+ result = TRUE;
+ } else {
+ result = FALSE;
+ }
+
+ return result;
+}
+
+/******************************************************************************/
+/*
+ * Return the fixed date from the gregorian date
+ */
+
+long FixedFromGregorian(long month, long day, long year)
+{
+ long fixedDate;
+
+ fixedDate = (long)(GregorianEpoch - 1 + 365 * (year - 1) +
+ floor((year - 1) / 4.0) -
+ floor((double)(year - 1) / 100.0) +
+ floor((double)(year - 1) / 400.0) +
+ floor((367.0 * ((double)month) - 362.0) / 12.0));
+
+ if (month <= 2) {
+ fixedDate += 0;
+ } else if (TRUE == GregorianLeapYearP(year)) {
+ fixedDate += -1;
+ } else {
+ fixedDate += -2;
+ }
+
+ fixedDate += day;
+
+ return fixedDate;
+}
+
+/******************************************************************************/
+/*
+ * Return the gregorian year from a fixed date
+ */
+
+long GregorianYearFromFixed(long fixedDate)
+{
+ long result, d0, n400, d1, n100, d2, n4, d3, n1, d4, year;
+
+ d0 = fixedDate - GregorianEpoch;
+ n400 = (long)(floor((double)d0 / (double)146097));
+ d1 = d0 % 146097;
+ n100 = (long)(floor((double)d1 / (double)36524));
+ d2 = d1 % 36524;
+ n4 = (long)(floor((double)d2 / (double)1461));
+ d3 = d2 % 1461;
+ n1 = (long)(floor((double)d3 / (double)365));
+ d4 = (d3 % 365) + 1;
+ year = 400 * n400 + 100 * n100 + 4 * n4 + n1;
+
+ if ((n100 == 4) || (n1 == 4)) {
+ result = year;
+ } else {
+ result = year + 1;
+ }
+
+ return result;
+}
+
+/******************************************************************************/
+/*
+ * Returns the Gregorian date from a fixed date
+ * (not needed for this use, but included for completeness
+ */
+
+#if 0
+GregorianFromFixed(long fixedDate, long *month, long *day, long *year)
+{
+ long priorDays, correction;
+
+ *year = GregorianYearFromFixed(fixedDate);
+ priorDays = fixedDate - FixedFromGregorian(1, 1, *year);
+
+ if (fixedDate < FixedFromGregorian(3,1,*year)) {
+ correction = 0;
+ } else if (true == GregorianLeapYearP(*year)) {
+ correction = 1;
+ } else {
+ correction = 2;
+ }
+
+ *month = (long)(floor((12.0 * (double)(priorDays + correction) + 373.0) / 367.0));
+ *day = fixedDate - FixedFromGregorian(*month, 1, *year);
+}
+#endif
+
+/******************************************************************************/
+/*
+ * Returns the difference between two Gregorian dates
+ */
+
+long GregorianDateDifference( long month1, long day1, long year1,
+ long month2, long day2, long year2)
+{
+ return FixedFromGregorian(month2, day2, year2) -
+ FixedFromGregorian(month1, day1, year1);
+}
+
+
+/******************************************************************************/
+/*
+ * Return the number of seconds into the current day
+ */
+
+#define SECONDS_PER_DAY 24*60*60
+
+static int parseTime(char_t *buf, int *index)
+{
+/*
+ * Format of buf is - 2DIGIT ":" 2DIGIT ":" 2DIGIT
+ */
+ int returnValue, tmpIndex, hourValue, minuteValue, secondValue;
+
+ hourValue = minuteValue = secondValue = -1;
+ returnValue = -1;
+ tmpIndex = *index;
+
+ hourValue = parseNDIGIT(buf, 2, &tmpIndex);
+
+ if (hourValue >= 0) {
+ tmpIndex++;
+ minuteValue = parseNDIGIT(buf, 2, &tmpIndex);
+ if (minuteValue >= 0) {
+ tmpIndex++;
+ secondValue = parseNDIGIT(buf, 2, &tmpIndex);
+ }
+ }
+
+ if ((hourValue >= 0) &&
+ (minuteValue >= 0) &&
+ (secondValue >= 0)) {
+ returnValue = (((hourValue * 60) + minuteValue) * 60) + secondValue;
+ *index = tmpIndex;
+ }
+
+ return returnValue;
+}
+
+/******************************************************************************/
+/*
+ * Return the equivalent of time() given a gregorian date
+ */
+
+static time_t dateToTimet(int year, int month, int day)
+{
+ long dayDifference;
+
+ /*
+ * Bug fix by Jeff Reeder (Jun 14, 2002): The 'month' parameter is
+ * numbered from 0 (Jan == 0), but FixedFromGregorian() takes
+ * months numbered from 1 (January == 1). We need to add 1
+ * to the month
+ */
+ dayDifference = FixedFromGregorian(month + 1, day, year) -
+ FixedFromGregorian(1, 1, 1970);
+
+ return dayDifference * SECONDS_PER_DAY;
+}
+
+/******************************************************************************/
+/*
+ * Return the number of seconds between Jan 1, 1970 and the parsed date
+ * (corresponds to documentation for time() function)
+ */
+
+static time_t parseDate1or2(char_t *buf, int *index)
+{
+/*
+ * Format of buf is either
+ * 2DIGIT SP month SP 4DIGIT
+ * or
+ * 2DIGIT "-" month "-" 2DIGIT
+ */
+ int dayValue, monthValue, yearValue, tmpIndex;
+ time_t returnValue;
+
+ returnValue = (time_t) -1;
+ tmpIndex = *index;
+
+ dayValue = monthValue = yearValue = -1;
+
+ if (buf[tmpIndex] == T(',')) {
+/*
+ * Skip over the ", "
+ */
+ tmpIndex += 2;
+
+ dayValue = parseNDIGIT(buf, 2, &tmpIndex);
+ if (dayValue >= 0) {
+/*
+ * Skip over the space or hyphen
+ */
+ tmpIndex++;
+ monthValue = parseMonth(buf, &tmpIndex);
+ if (monthValue >= 0) {
+/*
+ * Skip over the space or hyphen
+ */
+ tmpIndex++;
+ yearValue = parseYear(buf, &tmpIndex);
+ }
+ }
+
+ if ((dayValue >= 0) &&
+ (monthValue >= 0) &&
+ (yearValue >= 0)) {
+ if (yearValue < 1970) {
+/*
+ * Allow for Microsoft IE's year 1601 dates
+ */
+ returnValue = 0;
+ } else {
+ returnValue = dateToTimet(yearValue, monthValue, dayValue);
+ }
+ *index = tmpIndex;
+ }
+ }
+
+ return returnValue;
+}
+
+/******************************************************************************/
+/*
+ * Return the number of seconds between Jan 1, 1970 and the parsed date
+ */
+
+static time_t parseDate3Time(char_t *buf, int *index)
+{
+/*
+ * Format of buf is month SP ( 2DIGIT | ( SP 1DIGIT ))
+ */
+ int dayValue, monthValue, yearValue, timeValue, tmpIndex;
+ time_t returnValue;
+
+ returnValue = (time_t) -1;
+ tmpIndex = *index;
+
+ dayValue = monthValue = yearValue = timeValue = -1;
+
+ monthValue = parseMonth(buf, &tmpIndex);
+ if (monthValue >= 0) {
+/*
+ * Skip over the space
+ */
+ tmpIndex++;
+ if (buf[tmpIndex] == T(' ')) {
+/*
+ * Skip over this space too
+ */
+ tmpIndex++;
+ dayValue = parseNDIGIT(buf, 1, &tmpIndex);
+ } else {
+ dayValue = parseNDIGIT(buf, 2, &tmpIndex);
+ }
+/*
+ * Now get the time and time SP 4DIGIT
+ */
+ timeValue = parseTime(buf, &tmpIndex);
+ if (timeValue >= 0) {
+/*
+ * Now grab the 4DIGIT year value
+ */
+ yearValue = parseYear(buf, &tmpIndex);
+ }
+ }
+
+ if ((dayValue >= 0) &&
+ (monthValue >= 0) &&
+ (yearValue >= 0)) {
+ returnValue = dateToTimet(yearValue, monthValue, dayValue);
+ returnValue += timeValue;
+ *index = tmpIndex;
+ }
+
+ return returnValue;
+}
+
+
+/******************************************************************************/
+/*
+ * Although this looks like a trivial function, I found I was replicating the implementation
+ * seven times in the parseWeekday function. In the interests of minimizing code size
+ * and redundancy, it is broken out into a separate function. The cost of an extra
+ * function call I can live with given that it should only be called once per HTTP request.
+ */
+
+static int bufferIndexIncrementGivenNTest(char_t *buf, int testIndex, char_t testChar,
+ int foundIncrement, int notfoundIncrement)
+{
+ if (buf[testIndex] == testChar) {
+ return foundIncrement;
+ }
+
+ return notfoundIncrement;
+}
+
+/******************************************************************************/
+/*
+ * Return an index into a logical weekday array
+ */
+
+static int parseWeekday(char_t *buf, int *index)
+{
+/*
+ * Format of buf is either
+ * "Mon" | "Tue" | "Wed" | "Thu" | "Fri" | "Sat" | "Sun"
+ * or
+ * "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday" | "Saturday" | "Sunday"
+ */
+ int tmpIndex, returnValue;
+
+ returnValue = -1;
+ tmpIndex = *index;
+
+ switch (buf[tmpIndex]) {
+ case 'F':
+ returnValue = FRI;
+ *index += bufferIndexIncrementGivenNTest(buf, tmpIndex+3, 'd', sizeof("Friday"), 3);
+ break;
+ case 'M':
+ returnValue = MON;
+ *index += bufferIndexIncrementGivenNTest(buf, tmpIndex+3, 'd', sizeof("Monday"), 3);
+ break;
+ case 'S':
+ switch (buf[tmpIndex+1]) {
+ case 'a':
+ returnValue = SAT;
+ *index += bufferIndexIncrementGivenNTest(buf, tmpIndex+3, 'u', sizeof("Saturday"), 3);
+ break;
+ case 'u':
+ returnValue = SUN;
+ *index += bufferIndexIncrementGivenNTest(buf, tmpIndex+3, 'd', sizeof("Sunday"), 3);
+ break;
+ }
+ break;
+ case 'T':
+ switch (buf[tmpIndex+1]) {
+ case 'h':
+ returnValue = THU;
+ *index += bufferIndexIncrementGivenNTest(buf, tmpIndex+3, 'r', sizeof("Thursday"), 3);
+ break;
+ case 'u':
+ returnValue = TUE;
+ *index += bufferIndexIncrementGivenNTest(buf, tmpIndex+3, 's', sizeof("Tuesday"), 3);
+ break;
+ }
+ break;
+ case 'W':
+ returnValue = WED;
+ *index += bufferIndexIncrementGivenNTest(buf, tmpIndex+3, 'n', sizeof("Wednesday"), 3);
+ break;
+ }
+ return returnValue;
+}
+
+/******************************************************************************/
+/*
+ * Parse the date and time string.
+ */
+
+static time_t dateParse(time_t tip, char_t *cmd)
+{
+ int index, tmpIndex, weekday, timeValue;
+ time_t parsedValue, dateValue;
+
+ parsedValue = (time_t) 0;
+ index = timeValue = 0;
+ weekday = parseWeekday(cmd, &index);
+
+ if (weekday >= 0) {
+ tmpIndex = index;
+ dateValue = parseDate1or2(cmd, &tmpIndex);
+ if (dateValue >= 0) {
+ index = tmpIndex + 1;
+/*
+ * One of these two forms is being used
+ * wkday "," SP date1 SP time SP "GMT"
+ * weekday "," SP date2 SP time SP "GMT"
+ */
+ timeValue = parseTime(cmd, &index);
+ if (timeValue >= 0) {
+/*
+ * Now match up that "GMT" string for completeness
+ * Compute the final value if there were no problems in the parse
+ */
+ if ((weekday >= 0) &&
+ (dateValue >= 0) &&
+ (timeValue >= 0)) {
+ parsedValue = dateValue + timeValue;
+ }
+ }
+ } else {
+/*
+ * Try the other form - wkday SP date3 SP time SP 4DIGIT
+ */
+ tmpIndex = index;
+ parsedValue = parseDate3Time(cmd, &tmpIndex);
+ }
+ }
+
+ return parsedValue;
+}
+
+#endif /* WEBS_IF_MODIFIED_SUPPORT */
+
+/******************************************************************************/
diff --git a/cpukit/httpd/webs.h b/cpukit/httpd/webs.h
new file mode 100644
index 0000000000..9bc61ddf5e
--- /dev/null
+++ b/cpukit/httpd/webs.h
@@ -0,0 +1,233 @@
+/*
+ * webs.h -- GoAhead Web public header
+ *
+ * Copyright (c) GoAhead Software Inc., 1992-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for information on usage and redistribution
+ *
+ * $Id$
+ */
+
+#ifndef _h_WEBS
+#define _h_WEBS 1
+
+/******************************** Description *********************************/
+
+/*
+ * GoAhead Web Server header. This defines the Web public APIs.
+ * Include this header for files that contain ASP or Form procedures.
+ * Include wsIntrn.h when creating URL handlers.
+ */
+
+/********************************* Includes ***********************************/
+
+#include "ej.h"
+#ifdef WEBS_SSL_SUPPORT
+ #include "websSSL.h"
+#endif
+
+/********************************** Defines ***********************************/
+/*
+ * By license terms the server software name defined in the following line of
+ * code must not be modified.
+ */
+#define WEBS_NAME T("GoAhead-Webs")
+#define WEBS_VERSION T("2.1.3")
+
+#define WEBS_HEADER_BUFINC 512 /* Header buffer size */
+#define WEBS_ASP_BUFINC 512 /* Asp expansion increment */
+#define WEBS_MAX_PASS 32 /* Size of password */
+#define WEBS_BUFSIZE 1000 /* websWrite max output string */
+#define WEBS_MAX_HEADER (5 * 1024) /* Sanity check header */
+#define WEBS_MAX_URL 4096 /* Maximum URL size for sanity */
+#define WEBS_SOCKET_BUFSIZ 256 /* Bytes read from socket */
+
+#define WEBS_HTTP_PORT T("httpPort")
+#define CGI_BIN T("cgi-bin")
+
+/*
+ * Request flags. Also returned by websGetRequestFlags().
+ */
+#define WEBS_LOCAL_PAGE 0x1 /* Request for local webs page */
+#define WEBS_KEEP_ALIVE 0x2 /* HTTP/1.1 keep alive */
+#define WEBS_DONT_USE_CACHE 0x4 /* Not implemented cache support */
+#define WEBS_COOKIE 0x8 /* Cookie supplied in request */
+#define WEBS_IF_MODIFIED 0x10 /* If-modified-since in request */
+#define WEBS_POST_REQUEST 0x20 /* Post request operation */
+#define WEBS_LOCAL_REQUEST 0x40 /* Request from this system */
+#define WEBS_HOME_PAGE 0x80 /* Request for the home page */
+#define WEBS_ASP 0x100 /* ASP request */
+#define WEBS_HEAD_REQUEST 0x200 /* Head request */
+#define WEBS_CLEN 0x400 /* Request had a content length */
+#define WEBS_FORM 0x800 /* Request is a form */
+#define WEBS_REQUEST_DONE 0x1000 /* Request complete */
+#define WEBS_POST_DATA 0x2000 /* Already appended post data */
+#define WEBS_CGI_REQUEST 0x4000 /* cgi-bin request */
+#define WEBS_SECURE 0x8000 /* connection uses SSL */
+#define WEBS_AUTH_BASIC 0x10000 /* Basic authentication request */
+#define WEBS_AUTH_DIGEST 0x20000 /* Digest authentication request */
+#define WEBS_HEADER_DONE 0x40000 /* Already output the HTTP header */
+
+/*
+ * URL handler flags
+ */
+#define WEBS_HANDLER_FIRST 0x1 /* Process this handler first */
+#define WEBS_HANDLER_LAST 0x2 /* Process this handler last */
+
+/*
+ * Per socket connection webs structure
+ */
+typedef struct websRec {
+ ringq_t header; /* Header dynamic string */
+ time_t since; /* Parsed if-modified-since time */
+ sym_fd_t cgiVars; /* CGI standard variables */
+ sym_fd_t cgiQuery; /* CGI decoded query string */
+ time_t timestamp; /* Last transaction with browser */
+ int timeout; /* Timeout handle */
+ char_t ipaddr[32]; /* Connecting ipaddress */
+ char_t type[64]; /* Mime type */
+ char_t *dir; /* Directory containing the page */
+ char_t *path; /* Path name without query */
+ char_t *url; /* Full request url */
+ char_t *host; /* Requested host */
+ char_t *lpath; /* Cache local path name */
+ char_t *query; /* Request query */
+ char_t *decodedQuery; /* Decoded request query */
+ char_t *authType; /* Authorization type (Basic/DAA) */
+ char_t *password; /* Authorization password */
+ char_t *userName; /* Authorization username */
+ char_t *cookie; /* Cookie string */
+ char_t *userAgent; /* User agent (browser) */
+ char_t *protocol; /* Protocol (normally HTTP) */
+ char_t *protoVersion; /* Protocol version */
+ int sid; /* Socket id (handler) */
+ int listenSid; /* Listen Socket id */
+ int port; /* Request port number */
+ int state; /* Current state */
+ int flags; /* Current flags -- see above */
+ int code; /* Request result code */
+ int clen; /* Content length */
+ int wid; /* Index into webs */
+ char_t *cgiStdin; /* filename for CGI stdin */
+ int docfd; /* Document file descriptor */
+ int numbytes; /* Bytes to transfer to browser */
+ int written; /* Bytes actually transferred */
+ void (*writeSocket)(struct websRec *wp);
+#ifdef DIGEST_ACCESS_SUPPORT
+ char_t *realm; /* usually the same as "host" from websRec */
+ char_t *nonce; /* opaque-to-client string sent by server */
+ char_t *digest; /* digest form of user password */
+ char_t *uri; /* URI found in DAA header */
+ char_t *opaque; /* opaque value passed from server */
+ char_t *nc; /* nonce count */
+ char_t *cnonce; /* check nonce */
+ char_t *qop; /* quality operator */
+#endif
+#ifdef WEBS_SSL_SUPPORT
+ websSSL_t *wsp; /* SSL data structure */
+#endif
+} websRec;
+
+typedef websRec *webs_t;
+typedef websRec websType;
+
+/******************************** Prototypes **********************************/
+extern int websAccept(int sid, char *ipaddr, int port, int listenSid);
+extern int websAspDefine(char_t *name,
+ int (*fn)(int ejid, webs_t wp, int argc, char_t **argv));
+extern int websAspRequest(webs_t wp, char_t *lpath);
+extern void websCloseListen();
+extern int websDecode64(char_t *outbuf, char_t *string, int buflen);
+extern void websDecodeUrl(char_t *token, char_t *decoded, int len);
+extern void websDone(webs_t wp, int code);
+extern void websEncode64(char_t *outbuf, char_t *string, int buflen);
+extern void websError(webs_t wp, int code, char_t *msg, ...);
+/* function websErrorMsg() made extern 03 Jun 02 BgP */
+extern char_t *websErrorMsg(int code);
+extern void websFooter(webs_t wp);
+extern int websFormDefine(char_t *name, void (*fn)(webs_t wp,
+ char_t *path, char_t *query));
+extern char_t *websGetDefaultDir();
+extern char_t *websGetDefaultPage();
+extern char_t *websGetHostUrl();
+extern char_t *websGetIpaddrUrl();
+extern char_t *websGetPassword();
+extern int websGetPort();
+extern char_t *websGetPublishDir(char_t *path, char_t **urlPrefix);
+extern char_t *websGetRealm();
+extern int websGetRequestBytes(webs_t wp);
+extern char_t *websGetRequestDir(webs_t wp);
+extern int websGetRequestFlags(webs_t wp);
+extern char_t *websGetRequestIpaddr(webs_t wp);
+extern char_t *websGetRequestLpath(webs_t wp);
+extern char_t *websGetRequestPath(webs_t wp);
+extern char_t *websGetRequestPassword(webs_t wp);
+extern char_t *websGetRequestType(webs_t wp);
+extern int websGetRequestWritten(webs_t wp);
+extern char_t *websGetVar(webs_t wp, char_t *var, char_t *def);
+extern int websCompareVar(webs_t wp, char_t *var, char_t *value);
+extern void websHeader(webs_t wp);
+extern int websOpenListen(int port, int retries);
+extern int websPageOpen(webs_t wp, char_t *lpath, char_t *path,
+ int mode, int perm);
+extern void websPageClose(webs_t wp);
+extern int websPublish(char_t *urlPrefix, char_t *path);
+extern void websRedirect(webs_t wp, char_t *url);
+extern void websSecurityDelete();
+extern int websSecurityHandler(webs_t wp, char_t *urlPrefix,
+ char_t *webDir, int arg, char_t *url, char_t *path,
+ char_t *query);
+extern void websSetDefaultDir(char_t *dir);
+extern void websSetDefaultPage(char_t *page);
+extern void websSetEnv(webs_t wp);
+extern void websSetHost(char_t *host);
+extern void websSetIpaddr(char_t *ipaddr);
+extern void websSetPassword(char_t *password);
+extern void websSetRealm(char_t *realmName);
+extern void websSetRequestBytes(webs_t wp, int bytes);
+extern void websSetRequestFlags(webs_t wp, int flags);
+extern void websSetRequestLpath(webs_t wp, char_t *lpath);
+extern void websSetRequestPath(webs_t wp, char_t *dir, char_t *path);
+extern char_t *websGetRequestUserName(webs_t wp);
+extern void websSetRequestWritten(webs_t wp, int written);
+extern void websSetVar(webs_t wp, char_t *var, char_t *value);
+extern int websTestVar(webs_t wp, char_t *var);
+extern void websTimeoutCancel(webs_t wp);
+extern int websUrlHandlerDefine(char_t *urlPrefix, char_t *webDir,
+ int arg, int (*fn)(webs_t wp, char_t *urlPrefix,
+ char_t *webDir, int arg, char_t *url, char_t *path,
+ char_t *query), int flags);
+extern int websUrlHandlerDelete(int (*fn)(webs_t wp, char_t *urlPrefix,
+ char_t *webDir, int arg, char_t *url, char_t *path,
+ char_t *query));
+extern int websUrlHandlerRequest(webs_t wp);
+extern int websUrlParse(char_t *url, char_t **buf, char_t **host,
+ char_t **path, char_t **port, char_t **query,
+ char_t **proto, char_t **tag, char_t **ext);
+extern char_t *websUrlType(char_t *webs, char_t *buf, int charCnt);
+extern int websWrite(webs_t wp, char_t* fmt, ...);
+extern int websWriteBlock(webs_t wp, char_t *buf, int nChars);
+extern int websWriteDataNonBlock(webs_t wp, char *buf, int nChars);
+extern int websValid(webs_t wp);
+extern int websValidateUrl(webs_t wp, char_t *path);
+extern void websSetTimeMark(webs_t wp);
+
+/*
+ * The following prototypes are used by the SSL patch found in websSSL.c
+ */
+extern int websAlloc(int sid);
+extern void websFree(webs_t wp);
+extern void websTimeout(void *arg, int id);
+extern void websReadEvent(webs_t wp);
+
+/*
+ * Prototypes for functions available when running as part of the
+ * GoAhead Embedded Management Framework (EMF)
+ */
+#ifdef EMF
+extern void websFormExplain(webs_t wp, char_t *path, char_t *query);
+#endif
+
+#endif /* _h_WEBS */
+
+/******************************************************************************/
diff --git a/cpukit/httpd/websSSL.c b/cpukit/httpd/websSSL.c
new file mode 100644
index 0000000000..6c2e4ce5da
--- /dev/null
+++ b/cpukit/httpd/websSSL.c
@@ -0,0 +1,706 @@
+/*
+ * websSSL.c -- SSL envrionment creation
+ *
+ * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for usage and redistribution license requirements
+ *
+ * $Id$
+ */
+
+/******************************** Description *********************************/
+
+/*
+ * This module implements a patch into SSL implementations for the webs
+ * module.
+ */
+
+/********************************* Includes ***********************************/
+
+#include "wsIntrn.h"
+#include "webs.h"
+#include "websSSL.h"
+
+/******************************* Definitions **********************************/
+
+#define DEFAULT_CERT_FILE "./server.pem"
+#define DEFAULT_KEY_FILE "./certs/cakey.pem"
+#define DEFAULT_CA_FILE "./certs/cacert.pem"
+#define DEFAULT_CA_PATH "./certs/"
+#define SSL_PORT 443
+
+/*
+ * Define the components of the apps_startup() macro
+ */
+
+#ifdef SIGPIPE
+#define do_pipe_sig() signal(SIGPIPE,SIG_IGN)
+#else
+#define do_pipe_sig()
+#endif
+
+#ifdef OPENSSL
+#define SSLC_add_all_algorithms() SSLeay_add_all_algorithms()
+#else
+extern void SSLC_add_all_algorithms(void);
+#endif
+
+/*
+ * Define the apps_startup() macro
+ */
+
+# if defined(MSDOS) || defined(WIN16) || defined(WIN32)
+# ifdef _O_BINARY
+# define apps_startup() \
+ _fmode=_O_BINARY; do_pipe_sig(); CRYPTO_malloc_init(); \
+ SSLC_add_all_algorithms()
+# else
+# define apps_startup() \
+ _fmode=O_BINARY; do_pipe_sig(); CRYPTO_malloc_init(); \
+ SSLC_add_all_algorithms()
+# endif
+# else
+# define apps_startup() do_pipe_sig(); SSLC_add_all_algorithms();
+# endif
+
+/*************************** Forward Declarations *****************************/
+
+static int websSSLSetCertStuff(SSL_CTX *ctx,
+ char *cert_file,
+ char *key_file);
+static int websSSLVerifyCallback(int ok, X509_STORE_CTX *ctx);
+static RSA *websSSLTempRSACallback(SSL *s, int is_export, int keylength);
+
+static int websSSLReadEvent (webs_t wp);
+static int websSSLAccept(int sid, char *ipaddr, int port, int listenSid);
+static void websSSLSocketEvent(int sid, int mask, int data);
+
+/*********************************** Locals ***********************************/
+
+static int sslListenSock = -1; /* Listen socket */
+static SSL_CTX *sslctx = NULL;
+
+/******************************************************************************/
+/*
+ * Start up the SSL Context for the application, and start a listen on the
+ * SSL port (usually 443, and defined by SSL_PORT)
+ * Return 0 on success, -1 on failure.
+ */
+
+int websSSLOpen()
+{
+ char *certFile, *keyFile, *CApath, *CAfile;
+ SSL_METHOD *meth;
+
+/*
+ * Install and initialize the SSL library
+ */
+ apps_startup();
+ trace(7, T("SSL: Initializing SSL\n"));
+
+#ifdef SSLC
+ SSL_library_init();
+#endif
+
+ SSL_load_error_strings();
+
+#ifdef OPENSSL
+ SSLeay_add_ssl_algorithms();
+#endif
+
+/*
+ * Important! Enable both SSL versions 2 and 3
+ */
+ meth = SSLv23_server_method();
+ sslctx = SSL_CTX_new(meth);
+
+ a_assert(sslctx);
+
+ if (sslctx == NULL) {
+ trace(2, T("SSL: Unable to create SSL context!\n"));
+ return -1;
+ }
+
+/*
+ * Adjust some SSL Context variables
+ */
+ SSL_CTX_set_quiet_shutdown(sslctx, 1);
+ SSL_CTX_set_options(sslctx, 0);
+ SSL_CTX_sess_set_cache_size(sslctx, 128);
+
+/*
+ * Set the certificate verification locations
+ */
+ CApath = DEFAULT_CA_PATH;
+ CAfile = DEFAULT_CA_FILE;
+ if ((!SSL_CTX_load_verify_locations(sslctx, CAfile, CApath)) ||
+ (!SSL_CTX_set_default_verify_paths(sslctx))) {
+ trace(2, T("SSL: Unable to set cert verification locations!\n"));
+ websSSLClose();
+ return -1;
+ }
+
+/*
+ * Set the certificate and key files for the SSL context
+ */
+ certFile = DEFAULT_CERT_FILE;
+ keyFile = NULL;
+ if (websSSLSetCertStuff(sslctx, certFile, keyFile) != 0) {
+ websSSLClose();
+ return -1;
+ }
+
+/*
+ * Set the RSA callback for the SSL context
+ */
+ SSL_CTX_set_tmp_rsa_callback(sslctx, websSSLTempRSACallback);
+
+/*
+ * Set the verification callback for the SSL context
+ */
+ SSL_CTX_set_verify(sslctx, SSL_VERIFY_NONE, websSSLVerifyCallback);
+
+/*
+ * Set the certificate authority list for the client
+ */
+ SSL_CTX_set_client_CA_list(sslctx, SSL_load_client_CA_file(CAfile));
+
+/*
+ * Open the socket
+ */
+ sslListenSock = socketOpenConnection(NULL, SSL_PORT,
+ websSSLAccept, SOCKET_BLOCK);
+
+ if (sslListenSock < 0) {
+ trace(2, T("SSL: Unable to open SSL socket on port <%d>!\n"),
+ SSL_PORT);
+ return -1;
+ }
+
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Return TRUE if websSSL has been opened
+ */
+
+int websSSLIsOpen()
+{
+ return (sslListenSock != -1);
+}
+
+/******************************************************************************/
+/*
+ * Stops the SSL
+ */
+
+void websSSLClose()
+{
+ trace(7, T("SSL: Closing SSL\n"));
+
+ if (sslctx != NULL) {
+ SSL_CTX_free(sslctx);
+ sslctx = NULL;
+ }
+
+ if (sslListenSock != -1) {
+ socketCloseConnection(sslListenSock);
+ sslListenSock = -1;
+ }
+
+#ifdef SSLC
+ SSL_library_cleanup();
+#endif
+}
+
+/******************************************************************************/
+/*
+ * Accept a connection
+ */
+
+int websSSLAccept(int sid, char *ipaddr, int port, int listenSid)
+{
+ webs_t wp;
+ int wid;
+
+ a_assert(ipaddr && *ipaddr);
+ a_assert(sid >= 0);
+ a_assert(port >= 0);
+
+/*
+ * Allocate a new handle for this accepted connection. This will allocate
+ * a webs_t structure in the webs[] list
+ */
+ if ((wid = websAlloc(sid)) < 0) {
+ return -1;
+ }
+ wp = webs[wid];
+ a_assert(wp);
+ wp->listenSid = listenSid;
+
+ ascToUni(wp->ipaddr, ipaddr, min(sizeof(wp->ipaddr), strlen(ipaddr)+1));
+
+/*
+ * Check if this is a request from a browser on this system. This is useful
+ * to know for permitting administrative operations only for local access
+ */
+ if (gstrcmp(wp->ipaddr, T("127.0.0.1")) == 0 ||
+ gstrcmp(wp->ipaddr, websIpaddr) == 0 ||
+ gstrcmp(wp->ipaddr, websHost) == 0) {
+ wp->flags |= WEBS_LOCAL_REQUEST;
+ }
+/*
+ * Since the acceptance came in on this channel, it must be secure
+ */
+ wp->flags |= WEBS_SECURE;
+
+/*
+ * Arrange for websSocketEvent to be called when read data is available
+ */
+ socketCreateHandler(sid, SOCKET_READABLE, websSSLSocketEvent, (int) wp);
+
+/*
+ * Arrange for a timeout to kill hung requests
+ */
+ wp->timeout = emfSchedCallback(WEBS_TIMEOUT, websTimeout, (void *) wp);
+ trace(8, T("webs: accept request\n"));
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * The webs socket handler. Called in response to I/O. We just pass control
+ * to the relevant read or write handler. A pointer to the webs structure
+ * is passed as an (int) in iwp.
+ */
+
+static void websSSLSocketEvent(int sid, int mask, int iwp)
+{
+ webs_t wp;
+
+ wp = (webs_t) iwp;
+ a_assert(wp);
+
+ if (! websValid(wp)) {
+ return;
+ }
+
+ if (mask & SOCKET_READABLE) {
+ websSSLReadEvent(wp);
+ }
+ if (mask & SOCKET_WRITABLE) {
+ if (wp->writeSocket) {
+ (*wp->writeSocket)(wp);
+ }
+ }
+}
+
+/******************************************************************************/
+/*
+ * Handler for SSL Read Events
+ */
+
+static int websSSLReadEvent (webs_t wp)
+{
+ int ret, sock;
+ socket_t *sptr;
+ SSL *ssl;
+ BIO *bio, *bioSSL, *bioSock;
+#ifdef DEV
+ const char *ciphers;
+#endif
+
+ a_assert (wp);
+ a_assert(websValid(wp));
+
+ sptr = socketPtr(wp->sid);
+ a_assert(sptr);
+
+ sock = sptr->sock;
+
+/*
+ * Create a new BIO and SSL session for this web request
+ */
+ bio = BIO_new(BIO_f_buffer());
+ a_assert(bio);
+
+ if (!BIO_set_write_buffer_size(bio, 128)) {
+ return -1;
+ }
+
+ ssl = (SSL *) SSL_new(sslctx);
+ a_assert(ssl);
+
+ if (ssl == NULL) {
+ return -1;
+ }
+
+ SSL_set_session(ssl, NULL);
+
+ bioSSL = BIO_new(BIO_f_ssl());
+ a_assert(bioSSL);
+
+ bioSock = BIO_new_socket(sock, BIO_NOCLOSE);
+ a_assert(bioSock);
+
+ SSL_set_bio(ssl, bioSock, bioSock);
+ SSL_set_accept_state(ssl);
+
+ ret = BIO_set_ssl(bioSSL, ssl, BIO_CLOSE);
+ BIO_push(bio, bioSSL);
+
+#ifdef DEV
+ ciphers = SSL_get_cipher_list(ssl, 10);
+#endif
+
+/*
+ * Create the SSL data structure in the wp.
+ */
+#ifdef WEBS_SSL_SUPPORT
+ wp->wsp = balloc(B_L, sizeof(websSSL_t));
+ a_assert (wp->wsp);
+ (wp->wsp)->bio = bio;
+ (wp->wsp)->ssl = ssl;
+#endif
+
+/*
+ * Call the default Read Event
+ */
+ websReadEvent(wp);
+
+ return ret;
+}
+
+
+/******************************************************************************/
+/*
+ * SSL Verification Callback
+ */
+
+static int sslVerifyDepth = 0;
+static int sslVerifyError = X509_V_OK;
+
+int websSSLVerifyCallback(int ok, X509_STORE_CTX *ctx)
+{
+ char buf[256];
+ X509 *errCert;
+ int err;
+ int depth;
+
+ errCert = X509_STORE_CTX_get_current_cert(ctx);
+ err = X509_STORE_CTX_get_error(ctx);
+ depth = X509_STORE_CTX_get_error_depth(ctx);
+
+ X509_NAME_oneline(X509_get_subject_name(errCert), buf, 256);
+
+ if (!ok) {
+ if (sslVerifyDepth >= depth) {
+ ok = 1;
+ sslVerifyError = X509_V_OK;
+ } else {
+ ok=0;
+ sslVerifyError = X509_V_ERR_CERT_CHAIN_TOO_LONG;
+ }
+ }
+
+ switch (err) {
+ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
+#ifdef OPENSSL
+ X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256);
+#endif
+ break;
+
+ case X509_V_ERR_CERT_NOT_YET_VALID:
+ case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
+ case X509_V_ERR_CERT_HAS_EXPIRED:
+ case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
+ break;
+ }
+
+ return ok;
+}
+
+/******************************************************************************/
+/*
+ * Set the SSL certificate and key for the SSL context
+ */
+
+int websSSLSetCertStuff(SSL_CTX *ctx, char *certFile, char *keyFile)
+{
+ a_assert (ctx);
+ a_assert (certFile);
+
+ if (certFile != NULL) {
+ if (SSL_CTX_use_certificate_file(ctx, certFile,
+ SSL_FILETYPE_PEM) <= 0) {
+ trace(2, T("SSL: Unable to set certificate file <%s>\n"),
+ certFile);
+ return -1;
+ }
+
+ if (keyFile == NULL) {
+ keyFile = certFile;
+ }
+
+ if (SSL_CTX_use_PrivateKey_file(ctx, keyFile, SSL_FILETYPE_PEM) <= 0) {
+ trace(2, T("SSL: Unable to set private key file <%s>\n"),
+ keyFile);
+ return -1;
+ }
+
+/*
+ * Now we know that a key and cert have been set against
+ * the SSL context
+ */
+ if (!SSL_CTX_check_private_key(ctx)) {
+ trace(2, T("SSL: Check of private key file <%s> FAILED!\n"),
+ keyFile);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Set certificate file for SSL context
+ */
+
+int websSSLSetCertFile(char_t *certFile)
+{
+ a_assert (sslctx);
+ a_assert (certFile);
+
+ if (sslctx == NULL) {
+ return -1;
+ }
+
+ if (SSL_CTX_use_certificate_file(sslctx, certFile,
+ SSL_FILETYPE_PEM) <= 0) {
+ return -1;
+ }
+/*
+ * Confirm that the certificate and the private key jive.
+ */
+ if (!SSL_CTX_check_private_key(sslctx)) {
+ return -1;
+ }
+
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Set key file for SSL context
+ */
+
+int websSSLSetKeyFile(char_t *keyFile)
+{
+ a_assert (sslctx);
+ a_assert (keyFile);
+
+ if (sslctx == NULL) {
+ return -1;
+ }
+
+ if (SSL_CTX_use_PrivateKey_file(sslctx, keyFile, SSL_FILETYPE_PEM) <= 0) {
+ return -1;
+ }
+/*
+ * Confirm that the certificate and the private key jive.
+ */
+ if (!SSL_CTX_check_private_key(sslctx)) {
+ return -1;
+ }
+
+ return 0;
+}
+
+#ifdef SSLC
+extern RSA *RSA_new(void);
+#endif
+
+/******************************************************************************/
+/*
+ * the Temporary RSA callback
+ */
+
+static RSA *websSSLTempRSACallback(SSL *ssl, int isExport, int keyLength)
+{
+ static RSA *rsaTemp = NULL;
+
+ if (rsaTemp == NULL) {
+
+#ifdef OPENSSL
+ rsaTemp = RSA_generate_key(keyLength, RSA_F4, NULL, NULL);
+#endif
+
+#ifdef SSLC
+ rsaTemp = RSA_new();
+#endif
+
+ }
+
+ return rsaTemp;
+}
+
+/******************************************************************************/
+/*
+ * Free SSL resources
+ */
+
+int websSSLFree(websSSL_t *wsp)
+{
+ if (wsp == NULL) {
+ return -1;
+ }
+
+/*
+ * Make sure we re-use sessions
+ */
+ if (wsp->ssl != NULL) {
+ SSL_set_shutdown(wsp->ssl, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
+ }
+
+ if (wsp->bio != NULL) {
+ BIO_free_all(wsp->bio);
+ }
+
+ bfree(B_L, wsp);
+
+ return 0;
+}
+
+/******************************************************************************/
+/*
+ * Return Eof for the SSL BIO
+ */
+
+int websSSLEof(websSSL_t *wsp)
+{
+ a_assert(wsp);
+
+ if ((wsp == NULL) || (wsp->bio == NULL)) {
+ return -1;
+ }
+
+ return BIO_eof(wsp->bio);
+}
+
+/******************************************************************************/
+/*
+ * Perform a read of the SSL BIO
+ */
+
+int websSSLRead(websSSL_t *wsp, char_t *buf, int len)
+{
+ a_assert(wsp);
+ a_assert(buf);
+
+ if ((wsp == NULL) || (wsp->bio == NULL)) {
+ return -1;
+ }
+
+ return BIO_read(wsp->bio, buf, len);
+}
+
+/******************************************************************************/
+/*
+ * Perform a gets of the SSL BIO, returning an balloc'ed string
+ */
+
+#define BUF_BLOCK 256
+
+int websSSLGets(websSSL_t *wsp, char_t **buf)
+{
+ int rc, len, lenBuf;
+ char c;
+
+ a_assert(wsp);
+ a_assert(buf);
+
+ lenBuf = 0;
+ len = 0;
+
+ if ((wsp == NULL) || (wsp->bio == NULL)) {
+ return -1;
+ }
+
+ while (1) {
+
+ if ((rc = BIO_read(wsp->bio, &c, 1)) < 0) {
+ return rc;
+ }
+
+ if (rc == 0) {
+/*
+ * If there is a partial line and we are at EOF, pretend we saw a '\n'
+ */
+ if (len > 0 && BIO_eof(wsp->bio)) {
+ c = '\n';
+ } else {
+ return -1;
+ }
+ }
+/*
+ * If a newline is seen, return the data excluding the new line to the
+ * caller. If carriage return is seen, just eat it.
+ */
+ if (c == '\n') {
+ if ((len > 0) && (len < lenBuf)) {
+ (*buf)[len] = 0;
+ }
+ return len;
+ } else if (c == '\r') {
+ continue;
+ }
+/*
+ * Append character to buf
+ */
+ if (len >= lenBuf) {
+ lenBuf += BUF_BLOCK;
+ *buf = brealloc(B_L, *buf, lenBuf);
+ }
+
+ a_assert(*buf);
+ (*buf)[len] = c;
+ len++;
+ }
+}
+
+/******************************************************************************/
+/*
+ * Perform a write to the SSL BIO
+ */
+
+int websSSLWrite(websSSL_t *wsp, char_t *buf, int len)
+{
+ a_assert(wsp);
+ a_assert(buf);
+
+ if ((wsp == NULL) || (wsp->bio == NULL)) {
+ return -1;
+ }
+
+ return BIO_write(wsp->bio, buf, len);
+}
+
+/******************************************************************************/
+/*
+ * Perform a flush of the SSL BIO
+ */
+
+int websSSLFlush(websSSL_t *wsp)
+{
+ a_assert(wsp);
+
+ if ((wsp == NULL) || (wsp->bio == NULL)) {
+ return -1;
+ }
+
+ return BIO_flush(wsp->bio);
+}
+
+/******************************************************************************/
diff --git a/cpukit/httpd/websSSL.h b/cpukit/httpd/websSSL.h
new file mode 100644
index 0000000000..62bcc44930
--- /dev/null
+++ b/cpukit/httpd/websSSL.h
@@ -0,0 +1,67 @@
+/*
+ * websSSL.h -- SSL Patch header
+ *
+ * Copyright (c) GoAhead Software Inc., 1992-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for information on usage and redistribution
+ *
+ * $Id$
+ */
+
+#ifndef _h_websSSL
+#define _h_websSSL 1
+
+/******************************** Description *********************************/
+
+/*
+ * Header file for the GoAhead Patch for SSL. This defines the interface to
+ * integrate SSL into the GoAhead Webserver.
+ */
+
+/********************************* Includes ***********************************/
+
+
+#ifdef OPENSSL
+#define SSLEAY /* turn off a few special case MONOLITH macros */
+#define USE_SOCKETS /* needed for the _O_BINARY defs in the MS world */
+#include <openssl/ssl.h>
+#else
+#include <sslc.h>
+#endif
+
+#ifndef UEMF
+ #include "basic/basic.h"
+ #include "emf/emf.h"
+#else
+ #include "uemf.h"
+#endif
+
+/********************************** Defines ***********************************/
+
+typedef struct {
+ SSL *ssl;
+ BIO *bio;
+} websSSL_t;
+
+
+/******************************** Prototypes **********************************/
+
+extern int websSSLOpen();
+extern int websSSLIsOpen();
+extern void websSSLClose();
+
+extern int websSSLWrite(websSSL_t *wsp, char_t *buf, int nChars);
+extern int websSSLGets(websSSL_t *wsp, char_t **buf);
+extern int websSSLRead(websSSL_t *wsp, char_t *buf, int nChars);
+extern int websSSLEof(websSSL_t *wsp);
+
+extern int websSSLFree(websSSL_t *wsp);
+extern int websSSLFlush(websSSL_t *wsp);
+
+extern int websSSLSetKeyFile(char_t *keyFile);
+extern int websSSLSetCertFile(char_t *certFile);
+
+
+#endif /* _h_websSSL */
+
+/*****************************************************************************/
diff --git a/cpukit/httpd/websda.c b/cpukit/httpd/websda.c
new file mode 100644
index 0000000000..a4a95775b8
--- /dev/null
+++ b/cpukit/httpd/websda.c
@@ -0,0 +1,244 @@
+/*
+ * websda.c -- Digest Access Authentication routines
+ *
+ * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for usage and redistribution license requirements
+ *
+ * $Id$
+ */
+
+/******************************** Description *********************************/
+
+/*
+ * Routines for generating DAA data. The module uses the
+ * "RSA Data Security, Inc. MD5 Message-Digest Algorithm" found in md5c.c
+ */
+
+/********************************* Includes ***********************************/
+
+#ifndef CE
+#include <time.h>
+#endif
+#include "websda.h"
+#include "md5.h"
+
+/******************************** Local Data **********************************/
+
+#define RANDOMKEY T("onceuponatimeinparadise")
+#define NONCE_SIZE 34
+#define HASH_SIZE 16
+
+/*********************************** Code *************************************/
+/*
+ * websMD5binary returns the MD5 hash
+ */
+
+char *websMD5binary(unsigned char *buf, int length)
+{
+ const char *hex = "0123456789abcdef";
+ MD5_CONTEXT md5ctx;
+ unsigned char hash[HASH_SIZE];
+ char *r, *strReturn;
+ char result[(HASH_SIZE * 2) + 1];
+ int i;
+
+/*
+ * Take the MD5 hash of the string argument.
+ */
+ MD5Init(&md5ctx);
+ MD5Update(&md5ctx, buf, (unsigned int)length);
+ MD5Final(hash, &md5ctx);
+
+/*
+ * Prepare the resulting hash string
+ */
+ for (i = 0, r = result; i < 16; i++) {
+ *r++ = hex[hash[i] >> 4];
+ *r++ = hex[hash[i] & 0xF];
+ }
+
+/*
+ * Zero terminate the hash string
+ */
+ *r = '\0';
+
+/*
+ * Allocate a new copy of the hash string
+ */
+ strReturn = balloc(B_L, sizeof(result));
+ strcpy(strReturn, result);
+
+ return strReturn;
+}
+
+/*****************************************************************************/
+/*
+ * Convenience call to websMD5binary
+ * (Performs char_t to char conversion and back)
+ */
+
+char_t *websMD5(char_t *string)
+{
+ char_t *strReturn;
+
+ a_assert(string && *string);
+
+ if (string && *string) {
+ char *strTemp, *strHash;
+ int nLen;
+/*
+ * Convert input char_t string to char string
+ */
+ nLen = gstrlen(string);
+ strTemp = ballocUniToAsc(string, nLen + 1);
+/*
+ * Execute the digest calculation
+ */
+ strHash = websMD5binary((unsigned char *)strTemp, nLen);
+/*
+ * Convert the returned char string digest to a char_t string
+ */
+ nLen = strlen(strHash);
+ strReturn = ballocAscToUni(strHash, nLen);
+/*
+ * Free up the temporary allocated resources
+ */
+ bfree(B_L, strTemp);
+ bfree(B_L, strHash);
+ } else {
+ strReturn = NULL;
+ }
+
+ return strReturn;
+}
+
+/******************************************************************************/
+/*
+ * Get a Nonce value for passing along to the client. This function
+ * composes the string "RANDOMKEY:timestamp:myrealm" and
+ * calculates the MD5 digest placing it in output.
+ */
+
+char_t *websCalcNonce(webs_t wp)
+{
+ char_t *nonce, *prenonce;
+ struct tm *newtime;
+ time_t longTime;
+
+ a_assert(wp);
+/*
+ * Get time as long integer.
+ */
+ time(&longTime);
+/*
+ * Convert to local time.
+ */
+ newtime = localtime(&longTime);
+/*
+ * Create prenonce string.
+ */
+ prenonce = NULL;
+#ifdef DIGEST_ACCESS_SUPPORT
+ fmtAlloc(&prenonce, 256, T("%s:%s:%s"), RANDOMKEY, gasctime(newtime),
+ wp->realm);
+#else
+ fmtAlloc(&prenonce, 256, T("%s:%s:%s"), RANDOMKEY, gasctime(newtime),
+ RANDOMKEY);
+#endif
+ a_assert(prenonce);
+/*
+ * Create the nonce
+ */
+ nonce = websMD5(prenonce);
+/*
+ * Cleanup
+ */
+ bfreeSafe(B_L, prenonce);
+
+ return nonce;
+}
+
+/******************************************************************************/
+/*
+ * Get an Opaque value for passing along to the client
+ */
+
+char_t *websCalcOpaque(webs_t wp)
+{
+ char_t *opaque;
+ a_assert(wp);
+/*
+ * Temporary stub!
+ */
+ opaque = bstrdup(B_L, T("5ccc069c403ebaf9f0171e9517f40e41"));
+
+ return opaque;
+}
+
+/******************************************************************************/
+/*
+ * Get a Digest value using the MD5 algorithm
+ */
+
+char_t *websCalcDigest(webs_t wp)
+{
+#ifdef DIGEST_ACCESS_SUPPORT
+ char_t *digest, *a1, *a1prime, *a2, *a2prime, *preDigest, *method;
+
+ a_assert(wp);
+ digest = NULL;
+
+/*
+ * Calculate first portion of digest H(A1)
+ */
+ a1 = NULL;
+ fmtAlloc(&a1, 255, T("%s:%s:%s"), wp->userName, wp->realm, wp->password);
+ a_assert(a1);
+ a1prime = websMD5(a1);
+ bfreeSafe(B_L, a1);
+/*
+ * Calculate second portion of digest H(A2)
+ */
+ method = websGetVar(wp, T("REQUEST_METHOD"), NULL);
+ a_assert(method);
+ a2 = NULL;
+ fmtAlloc(&a2, 255, T("%s:%s"), method, wp->uri);
+ a_assert(a2);
+ a2prime = websMD5(a2);
+ bfreeSafe(B_L, a2);
+/*
+ * Construct final digest KD(H(A1):nonce:H(A2))
+ */
+ a_assert(a1prime);
+ a_assert(a2prime);
+ a_assert(wp->nonce);
+
+ preDigest = NULL;
+ if (!wp->qop) {
+ fmtAlloc(&preDigest, 255, T("%s:%s:%s"), a1prime, wp->nonce, a2prime);
+ } else {
+ fmtAlloc(&preDigest, 255, T("%s:%s:%s:%s:%s:%s"),
+ a1prime,
+ wp->nonce,
+ wp->nc,
+ wp->cnonce,
+ wp->qop,
+ a2prime);
+ }
+
+ a_assert(preDigest);
+ digest = websMD5(preDigest);
+/*
+ * Now clean up
+ */
+ bfreeSafe(B_L, a1prime);
+ bfreeSafe(B_L, a2prime);
+ bfreeSafe(B_L, preDigest);
+ return digest;
+#else
+ return NULL;
+#endif /* DIGEST_ACCESS_SUPPORT */
+}
+
+/******************************************************************************/
diff --git a/cpukit/httpd/websda.h b/cpukit/httpd/websda.h
new file mode 100644
index 0000000000..3852ab8f53
--- /dev/null
+++ b/cpukit/httpd/websda.h
@@ -0,0 +1,41 @@
+/*
+ * websda.h -- GoAhead Digest Access Authentication public header
+ *
+ * Copyright (c) GoAhead Software Inc., 1992-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for information on usage and redistribution
+ *
+ * $Id$
+ */
+
+#ifndef _h_WEBSDA
+#define _h_WEBSDA 1
+
+/******************************** Description *********************************/
+
+/*
+ * GoAhead Digest Access Authentication header. This defines the Digest
+ * access authentication public APIs. Include this header for files that
+ * use DAA functions
+ */
+
+/********************************* Includes ***********************************/
+
+#ifndef UEMF
+ #include "basic/basic.h"
+ #include "emf/emf.h"
+#else
+ #include "uemf.h"
+#endif
+
+#include "webs.h"
+
+/****************************** Definitions ***********************************/
+
+extern char_t *websCalcNonce(webs_t wp);
+extern char_t *websCalcOpaque(webs_t wp);
+extern char_t *websCalcDigest(webs_t wp);
+
+#endif /* _h_WEBSDA */
+
+/******************************************************************************/
diff --git a/cpukit/httpd/websuemf.c b/cpukit/httpd/websuemf.c
new file mode 100644
index 0000000000..4ff1b92a7e
--- /dev/null
+++ b/cpukit/httpd/websuemf.c
@@ -0,0 +1,217 @@
+/*
+ * websuemf.c -- GoAhead Micro Embedded Management Framework
+ *
+ * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for usage and redistribution license requirements
+ *
+ * $Id$
+ */
+
+/********************************** Description *******************************/
+
+/*
+ * This modules provides compatibility with the full GoAhead EMF.
+ */
+
+/*********************************** Includes *********************************/
+
+#include "ejIntrn.h"
+#include "wsIntrn.h"
+
+/*********************************** Defines **********************************/
+
+/*
+ * This structure stores scheduled events.
+ */
+typedef struct {
+ void (*routine)(void *arg, int id);
+ void *arg;
+ time_t at;
+ int schedid;
+} sched_t;
+
+/*********************************** Locals ***********************************/
+
+static sched_t **sched;
+static int schedMax;
+
+/************************************* Code ***********************************/
+/*
+ * Evaluate a script
+ */
+
+int scriptEval(int engine, char_t *cmd, char_t **result, int chan)
+{
+ int ejid;
+
+ if (engine == EMF_SCRIPT_EJSCRIPT) {
+ ejid = (int) chan;
+ /*
+ * NOTE -- to disable better reporting of ASP errors, change the
+ * following line of code to
+ * if (ejEval(ejid, cmd, NULL) ) {
+ */
+ if (ejEval(ejid, cmd, result) ) {
+ return 0;
+ } else {
+ return -1;
+ }
+ }
+ return -1;
+}
+
+/******************************************************************************/
+/*
+ * Compare strings, ignoring case: normal strcmp return codes.
+ *
+ * WARNING: It is not good form to increment or decrement pointers inside a
+ * "call" to tolower et al. These can be MACROS, and have undesired side
+ * effects.
+ */
+
+int strcmpci(char_t *s1, char_t *s2)
+{
+ int rc;
+
+ a_assert(s1 && s2);
+ if (s1 == NULL || s2 == NULL) {
+ return 0;
+ }
+
+ if (s1 == s2) {
+ return 0;
+ }
+
+ do {
+ rc = gtolower(*s1) - gtolower(*s2);
+ if (*s1 == '\0') {
+ break;
+ }
+ s1++;
+ s2++;
+ } while (rc == 0);
+ return rc;
+}
+
+/******************************************************************************/
+/*
+ * This function is called when a scheduled process time has come.
+ */
+
+void TimerProc(int schedid)
+{
+ sched_t *s;
+
+ a_assert(0 <= schedid && schedid < schedMax);
+ s = sched[schedid];
+ a_assert(s);
+
+ (s->routine)(s->arg, s->schedid);
+}
+
+/******************************************************************************/
+/*
+ * Schedule an event in delay milliseconds time. We will use 1 second
+ * granularity for webServer.
+ */
+
+int emfSchedCallback(int delay, emfSchedProc *proc, void *arg)
+{
+ sched_t *s;
+ int schedid;
+
+ if ((schedid = hAllocEntry((void*) &sched, &schedMax,
+ sizeof(sched_t))) < 0) {
+ return -1;
+ }
+ s = sched[schedid];
+ s->routine = proc;
+ s->arg = arg;
+ s->schedid = schedid;
+
+/*
+ * Round the delay up to seconds.
+ */
+ s->at = ((delay + 500) / 1000) + time(0);
+
+ return schedid;
+}
+
+/******************************************************************************/
+/*
+ * Reschedule to a new delay.
+ */
+
+void emfReschedCallback(int schedid, int delay)
+{
+ sched_t *s;
+
+ if (sched == NULL || schedid == -1 || schedid >= schedMax ||
+ (s = sched[schedid]) == NULL) {
+ return;
+ }
+ s->at = ((delay + 500) / 1000) + time(0);
+}
+
+/******************************************************************************/
+
+void emfUnschedCallback(int schedid)
+{
+ sched_t *s;
+
+ if (sched == NULL || schedid == -1 || schedid >= schedMax ||
+ (s = sched[schedid]) == NULL) {
+ return;
+ }
+ bfree(B_L, s);
+ schedMax = hFree((void*) &sched, schedid);
+}
+
+/******************************************************************************/
+/*
+ * Take the tasks off the queue in a round robin fashion.
+ */
+
+void emfSchedProcess()
+{
+ sched_t *s;
+ int schedid;
+ static int next = 0;
+
+/*
+ * If schedMax is 0, there are no tasks scheduled, so just return.
+ */
+ if (schedMax <= 0) {
+ return;
+ }
+
+/*
+ * If next >= schedMax, the schedule queue was reduced in our absence
+ * so reset next to 0 to start from the begining of the queue again.
+ */
+ if (next >= schedMax) {
+ next = 0;
+ }
+
+ schedid = next;
+ for (;;) {
+ if ((s = sched[schedid]) != NULL && (int)s->at <= (int)time(0)) {
+ TimerProc(schedid);
+ next = schedid + 1;
+ return;
+ }
+ if (++schedid >= schedMax) {
+ schedid = 0;
+ }
+ if (schedid == next) {
+/*
+ * We've gone all the way through the queue without finding
+ * anything to do so just return.
+ */
+ return;
+ }
+ }
+}
+
+/******************************************************************************/
diff --git a/cpukit/httpd/wsIntrn.h b/cpukit/httpd/wsIntrn.h
new file mode 100644
index 0000000000..9fb11f9937
--- /dev/null
+++ b/cpukit/httpd/wsIntrn.h
@@ -0,0 +1,309 @@
+/*
+ * wsIntrn.h -- Internal GoAhead Web server header
+ *
+ * Copyright (c) GoAhead Software Inc., 1992-2000. All Rights Reserved.
+ *
+ * See the file "license.txt" for information on usage and redistribution
+ *
+ * $Id$
+ */
+
+#ifndef _h_WEBS_INTERNAL
+#define _h_WEBS_INTERNAL 1
+
+/******************************** Description *********************************/
+
+/*
+ * Internal GoAhead Web Server header. This defines the Web private APIs
+ * Include this header when you want to create URL handlers.
+ */
+
+/*********************************** Defines **********************************/
+
+/*
+ * Define this to enable logging of web accesses to a file
+ * #define WEBS_LOG_SUPPORT 1
+ *
+ * Define this to enable HTTP/1.1 keep alive support
+ * #define WEBS_KEEP_ALIVE_SUPPORT 1
+ *
+ * Define this to enable if-modified-since support
+ * #define WEBS_IF_MODIFIED_SUPPORT 1
+ *
+ * Define this to support proxy capability and track local vs remote request
+ * Note: this is not yet fully implemented.
+ * #define WEBS_PROXY_SUPPORT 1
+ *
+ * Define this to support reading pages from ROM
+ * #define WEBS_PAGE_ROM 1
+ *
+ * Define this to enable memory allocation and stack usage tracking
+ * #define B_STATS 1
+ */
+
+/********************************** Includes **********************************/
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#ifdef NETWARE
+ #include <fcntl.h>
+ #include <sys/stat.h>
+ #include <signal.h>
+ #include <io.h>
+#endif
+
+#ifdef WIN
+ #include <fcntl.h>
+ #include <sys/stat.h>
+ #include <io.h>
+#endif
+
+#ifdef CE
+#ifndef UEMF
+ #include <io.h>
+#endif
+#endif
+
+#ifdef NW
+ #include <fcntl.h>
+ #include <sys/stat.h>
+#endif
+
+#ifdef SCOV5
+ #include <fcntl.h>
+ #include <sys/stat.h>
+ #include <signal.h>
+ #include <unistd.h>
+#endif
+
+#ifdef LYNX
+ #include <fcntl.h>
+ #include <sys/stat.h>
+ #include <signal.h>
+ #include <unistd.h>
+#endif
+
+#ifdef UNIX
+ #include <fcntl.h>
+ #include <sys/stat.h>
+ #include <signal.h>
+ #include <unistd.h>
+#endif
+
+#ifdef QNX4
+ #include <fcntl.h>
+ #include <sys/stat.h>
+ #include <signal.h>
+ #include <unistd.h>
+ #include <unix.h>
+#endif
+
+#ifdef UW
+ #include <fcntl.h>
+ #include <sys/stat.h>
+#endif
+
+#ifdef VXWORKS
+ #include <vxWorks.h>
+ #include <fcntl.h>
+ #include <sys/stat.h>
+#endif
+
+#ifdef SOLARIS
+ #include <macros.h>
+ #include <fcntl.h>
+ #include <sys/stat.h>
+#endif
+
+#ifdef UEMF
+ #include "uemf.h"
+ #include "ejIntrn.h"
+#else
+ #include "emf/emfInternal.h"
+ #include "ej/ejIntrn.h"
+#endif
+
+#include "webs.h"
+
+/********************************** Defines ***********************************/
+/*
+ * Read handler flags and state
+ */
+#define WEBS_BEGIN 0x1 /* Beginning state */
+#define WEBS_HEADER 0x2 /* Ready to read first line */
+#define WEBS_POST 0x4 /* POST without content */
+#define WEBS_POST_CLEN 0x8 /* Ready to read content for POST */
+#define WEBS_PROCESSING 0x10 /* Processing request */
+#define WEBS_KEEP_TIMEOUT 15000 /* Keep-alive timeout (15 secs) */
+#define WEBS_TIMEOUT 60000 /* General request timeout (60) */
+
+#define PAGE_READ_BUFSIZE 512 /* bytes read from page files */
+#define MAX_PORT_LEN 10 /* max digits in port number */
+#define WEBS_SYM_INIT 64 /* initial # of sym table entries */
+
+/*
+ * URL handler structure. Stores the leading URL path and the handler
+ * function to call when the URL path is seen.
+ */
+typedef struct {
+ int (*handler)(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
+ char_t *url, char_t *path,
+ char_t *query); /* Callback URL handler function */
+ char_t *webDir; /* Web directory if required */
+ char_t *urlPrefix; /* URL leading prefix */
+ int len; /* Length of urlPrefix for speed */
+ int arg; /* Argument to provide to handler */
+ int flags; /* Flags */
+} websUrlHandlerType;
+
+/*
+ * Webs statistics
+ */
+typedef struct {
+ long errors; /* General errors */
+ long redirects;
+ long net_requests;
+ long activeNetRequests;
+ long activeBrowserRequests;
+ long timeouts;
+ long access; /* Access violations */
+ long localHits;
+ long remoteHits;
+ long formHits;
+ long cgiHits;
+ long handlerHits;
+} websStatsType;
+
+extern websStatsType websStats; /* Web access stats */
+
+/*
+ * Error code list
+ */
+typedef struct {
+ int code; /* HTTP error code */
+ char_t *msg; /* HTTP error message */
+} websErrorType;
+
+/*
+ * Mime type list
+ */
+typedef struct {
+ char_t *type; /* Mime type */
+ char_t *ext; /* File extension */
+} websMimeType;
+
+/*
+ * File information structure.
+ */
+typedef struct {
+ unsigned long size; /* File length */
+ int isDir; /* Set if directory */
+ time_t mtime; /* Modified time */
+} websStatType;
+
+/*
+ * Compiled Rom Page Index
+ */
+typedef struct {
+ char_t *path; /* Web page URL path */
+ unsigned char *page; /* Web page data */
+ int size; /* Size of web page in bytes */
+ int pos; /* Current read position */
+} websRomPageIndexType;
+
+/*
+ * Defines for file open.
+ */
+#ifndef CE
+#define SOCKET_RDONLY O_RDONLY
+#define SOCKET_BINARY O_BINARY
+#else /* CE */
+#define SOCKET_RDONLY 0x1
+#define SOCKET_BINARY 0x2
+#endif /* CE */
+
+extern websRomPageIndexType websRomPageIndex[];
+extern websMimeType websMimeList[]; /* List of mime types */
+extern sym_fd_t websMime; /* Set of mime types */
+extern webs_t* webs; /* Session list head */
+extern int websMax; /* List size */
+extern char_t websHost[64]; /* Name of this host */
+extern char_t websIpaddr[64]; /* IP address of this host */
+extern char_t *websHostUrl; /* URL for this host */
+extern char_t *websIpaddrUrl; /* URL for this host */
+extern int websPort; /* Port number */
+
+/******************************** Prototypes **********************************/
+
+extern int websAspOpen();
+extern void websAspClose();
+extern void websFormOpen();
+extern void websFormClose();
+extern int websAspWrite(int ejid, webs_t wp, int argc, char_t **argv);
+extern void websDefaultClose();
+extern int websDefaultHandler(webs_t wp, char_t *urlPrefix,
+ char_t *webDir, int arg, char_t *url, char_t *path,
+ char_t *query);
+extern int websFormHandler(webs_t wp, char_t *urlPrefix, char_t *webDir,
+ int arg, char_t *url, char_t *path, char_t *query);
+extern int websCgiHandler(webs_t wp, char_t *urlPrefix, char_t *webDir,
+ int arg, char_t *url, char_t *path, char_t *query);
+extern void websCgiCleanup();
+extern int websCheckCgiProc(int handle);
+extern char_t *websGetCgiCommName();
+
+extern int websLaunchCgiProc(char_t *cgiPath, char_t **argp,
+ char_t **envp, char_t *stdIn, char_t *stdOut);
+extern int websOpen(int sid);
+extern void websResponse(webs_t wp, int code, char_t *msg,
+ char_t *redirect);
+extern int websJavaScriptEval(webs_t wp, char_t *script);
+extern int websPageReadData(webs_t wp, char *buf, int nBytes);
+extern int websPageOpen(webs_t wp, char_t *lpath, char_t *path, int mode,
+ int perm);
+extern void websPageClose(webs_t wp);
+extern void websPageSeek(webs_t wp, long offset);
+extern int websPageStat(webs_t wp, char_t *lpath, char_t *path,
+ websStatType *sbuf);
+extern int websPageIsDirectory(char_t *lpath);
+extern int websRomOpen();
+extern void websRomClose();
+extern int websRomPageOpen(webs_t wp, char_t *path, int mode, int perm);
+extern void websRomPageClose(int fd);
+extern int websRomPageReadData(webs_t wp, char *buf, int len);
+extern int websRomPageStat(char_t *path, websStatType *sbuf);
+extern long websRomPageSeek(webs_t wp, long offset, int origin);
+extern void websSetRequestSocketHandler(webs_t wp, int mask,
+ void (*fn)(webs_t wp));
+extern int websSolutionHandler(webs_t wp, char_t *urlPrefix,
+ char_t *webDir, int arg, char_t *url, char_t *path,
+ char_t *query);
+extern void websUrlHandlerClose();
+extern int websUrlHandlerOpen();
+extern int websOpenServer(int port, int retries);
+extern void websCloseServer();
+extern char_t* websGetDateString(websStatType* sbuf);
+
+extern int strcmpci(char_t* s1, char_t* s2);
+
+/*
+ * Prototypes for functions available when running as part of the
+ * GoAhead Embedded Management Framework (EMF)
+ */
+#ifdef EMF
+extern int websEmfOpen();
+extern void websEmfClose();
+extern void websSetEmfEnvironment(webs_t wp);
+#endif
+
+#ifdef CE
+extern int writeUniToAsc(int fid, void *buf, unsigned int len);
+extern int readAscToUni(int fid, void **buf, unsigned int len);
+#endif
+
+#endif /* _h_WEBS_INTERNAL */
+
+/******************************************************************************/
diff --git a/cpukit/include/rtems/bspIo.h b/cpukit/include/rtems/bspIo.h
new file mode 100644
index 0000000000..8e1aafeab8
--- /dev/null
+++ b/cpukit/include/rtems/bspIo.h
@@ -0,0 +1,39 @@
+/* bspIo.h
+ *
+ * This include file contains declaration of interface that
+ * will be provided by the file contained in this directory.
+ *
+ * COPYRIGHT (c) 1998 valette@crf.canon.fr
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+#ifndef _rtems_bspIo_h
+#define _rtems_bspIo_h
+
+/*
+ * All the functions declared as extern after this comment
+ * MUST be implemented in each BSP. Using this function,
+ * this directory contains shared code that export higher level
+ * functionnality described after the next command.
+ */
+typedef void (*BSP_output_char_function_type) (char c);
+typedef char (*BSP_polling_getchar_function_type) (void);
+
+extern BSP_output_char_function_type BSP_output_char;
+extern BSP_polling_getchar_function_type BSP_poll_char;
+
+/*
+ * All the function declared as extern after this comment
+ * are available for each BSP by compiling and linking
+ * the files contained in this directory PROVIDED definition
+ * and initialisation of the previous variable are done.
+ */
+#include <stdarg.h>
+extern void vprintk(char *fmt, va_list ap);
+extern void printk(char *fmt, ...);
+
+#endif
diff --git a/cpukit/include/rtems/concat.h b/cpukit/include/rtems/concat.h
new file mode 100644
index 0000000000..df4a7a7b19
--- /dev/null
+++ b/cpukit/include/rtems/concat.h
@@ -0,0 +1,19 @@
+/*
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef _rtems_concat_h
+#define _rtems_concat_h
+
+/* ANSI concatenation macros. */
+
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+#define EXPAND0(x) x
+
+#endif
diff --git a/cpukit/include/rtems/fs.h b/cpukit/include/rtems/fs.h
new file mode 100644
index 0000000000..820630e343
--- /dev/null
+++ b/cpukit/include/rtems/fs.h
@@ -0,0 +1,59 @@
+/*
+ * Some basic filesystem types
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __rtems_fstypes_h
+#define __rtems_fstypes_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * File descriptor Table Information
+ */
+
+/* Forward declarations */
+
+/* FIXME: shouldn't this better not be here? */
+typedef struct rtems_libio_tt rtems_libio_t;
+
+typedef struct rtems_filesystem_location_info_tt
+ rtems_filesystem_location_info_t;
+
+struct rtems_filesystem_mount_table_entry_tt;
+typedef struct rtems_filesystem_mount_table_entry_tt
+ rtems_filesystem_mount_table_entry_t;
+
+typedef struct _rtems_filesystem_file_handlers_r
+ rtems_filesystem_file_handlers_r;
+typedef struct _rtems_filesystem_operations_table
+ rtems_filesystem_operations_table;
+
+/*
+ * Structure used to determine a location/filesystem in the tree.
+ */
+
+struct rtems_filesystem_location_info_tt
+{
+ void *node_access;
+ rtems_filesystem_file_handlers_r *handlers;
+ rtems_filesystem_operations_table *ops;
+ rtems_filesystem_mount_table_entry_t *mt_entry;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/include/rtems/pci.h b/cpukit/include/rtems/pci.h
new file mode 100644
index 0000000000..2070bb434d
--- /dev/null
+++ b/cpukit/include/rtems/pci.h
@@ -0,0 +1,1153 @@
+/*
+ *
+ * PCI defines and function prototypes
+ * Copyright 1994, Drew Eckhardt
+ * Copyright 1997, 1998 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ *
+ * For more information, please consult the following manuals (look at
+ * http://www.pcisig.com/ for how to get them):
+ *
+ * PCI BIOS Specification
+ * PCI Local Bus Specification
+ * PCI to PCI Bridge Specification
+ * PCI System Design Guide
+ *
+ * $Id$
+ */
+
+#ifndef RTEMS_PCI_H
+#define RTEMS_PCI_H
+
+/*
+ * Under PCI, each device has 256 bytes of configuration address space,
+ * of which the first 64 bytes are standardized as follows:
+ */
+#define PCI_VENDOR_ID 0x00 /* 16 bits */
+#define PCI_DEVICE_ID 0x02 /* 16 bits */
+#define PCI_COMMAND 0x04 /* 16 bits */
+#define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */
+#define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */
+#define PCI_COMMAND_MASTER 0x4 /* Enable bus mastering */
+#define PCI_COMMAND_SPECIAL 0x8 /* Enable response to special cycles */
+#define PCI_COMMAND_INVALIDATE 0x10 /* Use memory write and invalidate */
+#define PCI_COMMAND_VGA_PALETTE 0x20 /* Enable palette snooping */
+#define PCI_COMMAND_PARITY 0x40 /* Enable parity checking */
+#define PCI_COMMAND_WAIT 0x80 /* Enable address/data stepping */
+#define PCI_COMMAND_SERR 0x100 /* Enable SERR */
+#define PCI_COMMAND_FAST_BACK 0x200 /* Enable back-to-back writes */
+
+#define PCI_STATUS 0x06 /* 16 bits */
+#define PCI_STATUS_66MHZ 0x20 /* Support 66 Mhz PCI 2.1 bus */
+#define PCI_STATUS_UDF 0x40 /* Support User Definable Features */
+
+#define PCI_STATUS_FAST_BACK 0x80 /* Accept fast-back to back */
+#define PCI_STATUS_PARITY 0x100 /* Detected parity error */
+#define PCI_STATUS_DEVSEL_MASK 0x600 /* DEVSEL timing */
+#define PCI_STATUS_DEVSEL_FAST 0x000
+#define PCI_STATUS_DEVSEL_MEDIUM 0x200
+#define PCI_STATUS_DEVSEL_SLOW 0x400
+#define PCI_STATUS_SIG_TARGET_ABORT 0x800 /* Set on target abort */
+#define PCI_STATUS_REC_TARGET_ABORT 0x1000 /* Master ack of " */
+#define PCI_STATUS_REC_MASTER_ABORT 0x2000 /* Set on master abort */
+#define PCI_STATUS_SIG_SYSTEM_ERROR 0x4000 /* Set when we drive SERR */
+#define PCI_STATUS_DETECTED_PARITY 0x8000 /* Set on parity error */
+
+#define PCI_CLASS_REVISION 0x08 /* High 24 bits are class, low 8
+ revision */
+#define PCI_REVISION_ID 0x08 /* Revision ID */
+#define PCI_CLASS_PROG 0x09 /* Reg. Level Programming Interface */
+#define PCI_CLASS_DEVICE 0x0a /* Device class */
+
+#define PCI_CACHE_LINE_SIZE 0x0c /* 8 bits */
+#define PCI_LATENCY_TIMER 0x0d /* 8 bits */
+#define PCI_HEADER_TYPE 0x0e /* 8 bits */
+#define PCI_HEADER_TYPE_NORMAL 0
+#define PCI_HEADER_TYPE_BRIDGE 1
+#define PCI_HEADER_TYPE_CARDBUS 2
+
+#define PCI_BIST 0x0f /* 8 bits */
+#define PCI_BIST_CODE_MASK 0x0f /* Return result */
+#define PCI_BIST_START 0x40 /* 1 to start BIST, 2 secs or less */
+#define PCI_BIST_CAPABLE 0x80 /* 1 if BIST capable */
+
+/*
+ * Base addresses specify locations in memory or I/O space.
+ * Decoded size can be determined by writing a value of
+ * 0xffffffff to the register, and reading it back. Only
+ * 1 bits are decoded.
+ */
+#define PCI_BASE_ADDRESS_0 0x10 /* 32 bits */
+#define PCI_BASE_ADDRESS_1 0x14 /* 32 bits [htype 0,1 only] */
+#define PCI_BASE_ADDRESS_2 0x18 /* 32 bits [htype 0 only] */
+#define PCI_BASE_ADDRESS_3 0x1c /* 32 bits */
+#define PCI_BASE_ADDRESS_4 0x20 /* 32 bits */
+#define PCI_BASE_ADDRESS_5 0x24 /* 32 bits */
+#define PCI_BASE_ADDRESS_SPACE 0x01 /* 0 = memory, 1 = I/O */
+#define PCI_BASE_ADDRESS_SPACE_IO 0x01
+#define PCI_BASE_ADDRESS_SPACE_MEMORY 0x00
+#define PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06
+#define PCI_BASE_ADDRESS_MEM_TYPE_32 0x00 /* 32 bit address */
+#define PCI_BASE_ADDRESS_MEM_TYPE_1M 0x02 /* Below 1M */
+#define PCI_BASE_ADDRESS_MEM_TYPE_64 0x04 /* 64 bit address */
+#define PCI_BASE_ADDRESS_MEM_PREFETCH 0x08 /* prefetchable? */
+#define PCI_BASE_ADDRESS_MEM_MASK (~0x0fUL)
+#define PCI_BASE_ADDRESS_IO_MASK (~0x03UL)
+/* bit 1 is reserved if address_space = 1 */
+
+/* Header type 0 (normal devices) */
+#define PCI_CARDBUS_CIS 0x28
+#define PCI_SUBSYSTEM_VENDOR_ID 0x2c
+#define PCI_SUBSYSTEM_ID 0x2e
+#define PCI_ROM_ADDRESS 0x30 /* Bits 31..11 are address, 10..1 reserved */
+#define PCI_ROM_ADDRESS_ENABLE 0x01
+#define PCI_ROM_ADDRESS_MASK (~0x7ffUL)
+
+/* 0x34-0x3b are reserved */
+#define PCI_INTERRUPT_LINE 0x3c /* 8 bits */
+#define PCI_INTERRUPT_PIN 0x3d /* 8 bits */
+#define PCI_MIN_GNT 0x3e /* 8 bits */
+#define PCI_MAX_LAT 0x3f /* 8 bits */
+
+/* Header type 1 (PCI-to-PCI bridges) */
+#define PCI_PRIMARY_BUS 0x18 /* Primary bus number */
+#define PCI_SECONDARY_BUS 0x19 /* Secondary bus number */
+#define PCI_SUBORDINATE_BUS 0x1a /* Highest bus number behind the bridge */
+#define PCI_SEC_LATENCY_TIMER 0x1b /* Latency timer for secondary interface */
+#define PCI_IO_BASE 0x1c /* I/O range behind the bridge */
+#define PCI_IO_LIMIT 0x1d
+#define PCI_IO_RANGE_TYPE_MASK 0x0f /* I/O bridging type */
+#define PCI_IO_RANGE_TYPE_16 0x00
+#define PCI_IO_RANGE_TYPE_32 0x01
+#define PCI_IO_RANGE_MASK ~0x0f
+#define PCI_SEC_STATUS 0x1e /* Secondary status register, only bit 14 used */
+#define PCI_MEMORY_BASE 0x20 /* Memory range behind */
+#define PCI_MEMORY_LIMIT 0x22
+#define PCI_MEMORY_RANGE_TYPE_MASK 0x0f
+#define PCI_MEMORY_RANGE_MASK ~0x0f
+#define PCI_PREF_MEMORY_BASE 0x24 /* Prefetchable memory range behind */
+#define PCI_PREF_MEMORY_LIMIT 0x26
+#define PCI_PREF_RANGE_TYPE_MASK 0x0f
+#define PCI_PREF_RANGE_TYPE_32 0x00
+#define PCI_PREF_RANGE_TYPE_64 0x01
+#define PCI_PREF_RANGE_MASK ~0x0f
+#define PCI_PREF_BASE_UPPER32 0x28 /* Upper half of prefetchable memory range */
+#define PCI_PREF_LIMIT_UPPER32 0x2c
+#define PCI_IO_BASE_UPPER16 0x30 /* Upper half of I/O addresses */
+#define PCI_IO_LIMIT_UPPER16 0x32
+/* 0x34-0x3b is reserved */
+#define PCI_ROM_ADDRESS1 0x38 /* Same as PCI_ROM_ADDRESS, but for htype 1 */
+/* 0x3c-0x3d are same as for htype 0 */
+#define PCI_BRIDGE_CONTROL 0x3e
+#define PCI_BRIDGE_CTL_PARITY 0x01 /* Enable parity detection on secondary interface */
+#define PCI_BRIDGE_CTL_SERR 0x02 /* The same for SERR forwarding */
+#define PCI_BRIDGE_CTL_NO_ISA 0x04 /* Disable bridging of ISA ports */
+#define PCI_BRIDGE_CTL_VGA 0x08 /* Forward VGA addresses */
+#define PCI_BRIDGE_CTL_MASTER_ABORT 0x20 /* Report master aborts */
+#define PCI_BRIDGE_CTL_BUS_RESET 0x40 /* Secondary bus reset */
+#define PCI_BRIDGE_CTL_FAST_BACK 0x80 /* Fast Back2Back enabled on secondary interface */
+
+/* Header type 2 (CardBus bridges) */
+/* 0x14-0x15 reserved */
+#define PCI_CB_SEC_STATUS 0x16 /* Secondary status */
+#define PCI_CB_PRIMARY_BUS 0x18 /* PCI bus number */
+#define PCI_CB_CARD_BUS 0x19 /* CardBus bus number */
+#define PCI_CB_SUBORDINATE_BUS 0x1a /* Subordinate bus number */
+#define PCI_CB_LATENCY_TIMER 0x1b /* CardBus latency timer */
+#define PCI_CB_MEMORY_BASE_0 0x1c
+#define PCI_CB_MEMORY_LIMIT_0 0x20
+#define PCI_CB_MEMORY_BASE_1 0x24
+#define PCI_CB_MEMORY_LIMIT_1 0x28
+#define PCI_CB_IO_BASE_0 0x2c
+#define PCI_CB_IO_BASE_0_HI 0x2e
+#define PCI_CB_IO_LIMIT_0 0x30
+#define PCI_CB_IO_LIMIT_0_HI 0x32
+#define PCI_CB_IO_BASE_1 0x34
+#define PCI_CB_IO_BASE_1_HI 0x36
+#define PCI_CB_IO_LIMIT_1 0x38
+#define PCI_CB_IO_LIMIT_1_HI 0x3a
+#define PCI_CB_IO_RANGE_MASK ~0x03
+/* 0x3c-0x3d are same as for htype 0 */
+#define PCI_CB_BRIDGE_CONTROL 0x3e
+#define PCI_CB_BRIDGE_CTL_PARITY 0x01 /* Similar to standard bridge control register */
+#define PCI_CB_BRIDGE_CTL_SERR 0x02
+#define PCI_CB_BRIDGE_CTL_ISA 0x04
+#define PCI_CB_BRIDGE_CTL_VGA 0x08
+#define PCI_CB_BRIDGE_CTL_MASTER_ABORT 0x20
+#define PCI_CB_BRIDGE_CTL_CB_RESET 0x40 /* CardBus reset */
+#define PCI_CB_BRIDGE_CTL_16BIT_INT 0x80 /* Enable interrupt for 16-bit cards */
+#define PCI_CB_BRIDGE_CTL_PREFETCH_MEM0 0x100 /* Prefetch enable for both memory regions */
+#define PCI_CB_BRIDGE_CTL_PREFETCH_MEM1 0x200
+#define PCI_CB_BRIDGE_CTL_POST_WRITES 0x400
+#define PCI_CB_SUBSYSTEM_VENDOR_ID 0x40
+#define PCI_CB_SUBSYSTEM_ID 0x42
+#define PCI_CB_LEGACY_MODE_BASE 0x44 /* 16-bit PC Card legacy mode base address (ExCa) */
+/* 0x48-0x7f reserved */
+
+/* Device classes and subclasses */
+
+#define PCI_CLASS_NOT_DEFINED 0x0000
+#define PCI_CLASS_NOT_DEFINED_VGA 0x0001
+
+#define PCI_BASE_CLASS_STORAGE 0x01
+#define PCI_CLASS_STORAGE_SCSI 0x0100
+#define PCI_CLASS_STORAGE_IDE 0x0101
+#define PCI_CLASS_STORAGE_FLOPPY 0x0102
+#define PCI_CLASS_STORAGE_IPI 0x0103
+#define PCI_CLASS_STORAGE_RAID 0x0104
+#define PCI_CLASS_STORAGE_OTHER 0x0180
+
+#define PCI_BASE_CLASS_NETWORK 0x02
+#define PCI_CLASS_NETWORK_ETHERNET 0x0200
+#define PCI_CLASS_NETWORK_TOKEN_RING 0x0201
+#define PCI_CLASS_NETWORK_FDDI 0x0202
+#define PCI_CLASS_NETWORK_ATM 0x0203
+#define PCI_CLASS_NETWORK_OTHER 0x0280
+
+#define PCI_BASE_CLASS_DISPLAY 0x03
+#define PCI_CLASS_DISPLAY_VGA 0x0300
+#define PCI_CLASS_DISPLAY_XGA 0x0301
+#define PCI_CLASS_DISPLAY_OTHER 0x0380
+
+#define PCI_BASE_CLASS_MULTIMEDIA 0x04
+#define PCI_CLASS_MULTIMEDIA_VIDEO 0x0400
+#define PCI_CLASS_MULTIMEDIA_AUDIO 0x0401
+#define PCI_CLASS_MULTIMEDIA_OTHER 0x0480
+
+#define PCI_BASE_CLASS_MEMORY 0x05
+#define PCI_CLASS_MEMORY_RAM 0x0500
+#define PCI_CLASS_MEMORY_FLASH 0x0501
+#define PCI_CLASS_MEMORY_OTHER 0x0580
+
+#define PCI_BASE_CLASS_BRIDGE 0x06
+#define PCI_CLASS_BRIDGE_HOST 0x0600
+#define PCI_CLASS_BRIDGE_ISA 0x0601
+#define PCI_CLASS_BRIDGE_EISA 0x0602
+#define PCI_CLASS_BRIDGE_MC 0x0603
+#define PCI_CLASS_BRIDGE_PCI 0x0604
+#define PCI_CLASS_BRIDGE_PCMCIA 0x0605
+#define PCI_CLASS_BRIDGE_NUBUS 0x0606
+#define PCI_CLASS_BRIDGE_CARDBUS 0x0607
+#define PCI_CLASS_BRIDGE_OTHER 0x0680
+
+#define PCI_BASE_CLASS_COMMUNICATION 0x07
+#define PCI_CLASS_COMMUNICATION_SERIAL 0x0700
+#define PCI_CLASS_COMMUNICATION_PARALLEL 0x0701
+#define PCI_CLASS_COMMUNICATION_OTHER 0x0780
+
+#define PCI_BASE_CLASS_SYSTEM 0x08
+#define PCI_CLASS_SYSTEM_PIC 0x0800
+#define PCI_CLASS_SYSTEM_DMA 0x0801
+#define PCI_CLASS_SYSTEM_TIMER 0x0802
+#define PCI_CLASS_SYSTEM_RTC 0x0803
+#define PCI_CLASS_SYSTEM_OTHER 0x0880
+
+#define PCI_BASE_CLASS_INPUT 0x09
+#define PCI_CLASS_INPUT_KEYBOARD 0x0900
+#define PCI_CLASS_INPUT_PEN 0x0901
+#define PCI_CLASS_INPUT_MOUSE 0x0902
+#define PCI_CLASS_INPUT_OTHER 0x0980
+
+#define PCI_BASE_CLASS_DOCKING 0x0a
+#define PCI_CLASS_DOCKING_GENERIC 0x0a00
+#define PCI_CLASS_DOCKING_OTHER 0x0a01
+
+#define PCI_BASE_CLASS_PROCESSOR 0x0b
+#define PCI_CLASS_PROCESSOR_386 0x0b00
+#define PCI_CLASS_PROCESSOR_486 0x0b01
+#define PCI_CLASS_PROCESSOR_PENTIUM 0x0b02
+#define PCI_CLASS_PROCESSOR_ALPHA 0x0b10
+#define PCI_CLASS_PROCESSOR_POWERPC 0x0b20
+#define PCI_CLASS_PROCESSOR_CO 0x0b40
+
+#define PCI_BASE_CLASS_SERIAL 0x0c
+#define PCI_CLASS_SERIAL_FIREWIRE 0x0c00
+#define PCI_CLASS_SERIAL_ACCESS 0x0c01
+#define PCI_CLASS_SERIAL_SSA 0x0c02
+#define PCI_CLASS_SERIAL_USB 0x0c03
+#define PCI_CLASS_SERIAL_FIBER 0x0c04
+
+#define PCI_CLASS_OTHERS 0xff
+
+/*
+ * Vendor and card ID's: sort these numerically according to vendor
+ * (and according to card ID within vendor). Send all updates to
+ * <linux-pcisupport@cck.uni-kl.de>.
+ */
+#define PCI_VENDOR_ID_COMPAQ 0x0e11
+#define PCI_DEVICE_ID_COMPAQ_1280 0x3033
+#define PCI_DEVICE_ID_COMPAQ_TRIFLEX 0x4000
+#define PCI_DEVICE_ID_COMPAQ_SMART2P 0xae10
+#define PCI_DEVICE_ID_COMPAQ_NETEL100 0xae32
+#define PCI_DEVICE_ID_COMPAQ_NETEL10 0xae34
+#define PCI_DEVICE_ID_COMPAQ_NETFLEX3I 0xae35
+#define PCI_DEVICE_ID_COMPAQ_NETEL100D 0xae40
+#define PCI_DEVICE_ID_COMPAQ_NETEL100PI 0xae43
+#define PCI_DEVICE_ID_COMPAQ_NETEL100I 0xb011
+#define PCI_DEVICE_ID_COMPAQ_THUNDER 0xf130
+#define PCI_DEVICE_ID_COMPAQ_NETFLEX3B 0xf150
+
+#define PCI_VENDOR_ID_NCR 0x1000
+#define PCI_DEVICE_ID_NCR_53C810 0x0001
+#define PCI_DEVICE_ID_NCR_53C820 0x0002
+#define PCI_DEVICE_ID_NCR_53C825 0x0003
+#define PCI_DEVICE_ID_NCR_53C815 0x0004
+#define PCI_DEVICE_ID_NCR_53C860 0x0006
+#define PCI_DEVICE_ID_NCR_53C896 0x000b
+#define PCI_DEVICE_ID_NCR_53C895 0x000c
+#define PCI_DEVICE_ID_NCR_53C885 0x000d
+#define PCI_DEVICE_ID_NCR_53C875 0x000f
+#define PCI_DEVICE_ID_NCR_53C875J 0x008f
+
+#define PCI_VENDOR_ID_ATI 0x1002
+#define PCI_DEVICE_ID_ATI_68800 0x4158
+#define PCI_DEVICE_ID_ATI_215CT222 0x4354
+#define PCI_DEVICE_ID_ATI_210888CX 0x4358
+#define PCI_DEVICE_ID_ATI_215GB 0x4742
+#define PCI_DEVICE_ID_ATI_215GD 0x4744
+#define PCI_DEVICE_ID_ATI_215GI 0x4749
+#define PCI_DEVICE_ID_ATI_215GP 0x4750
+#define PCI_DEVICE_ID_ATI_215GQ 0x4751
+#define PCI_DEVICE_ID_ATI_215GT 0x4754
+#define PCI_DEVICE_ID_ATI_215GTB 0x4755
+#define PCI_DEVICE_ID_ATI_210888GX 0x4758
+#define PCI_DEVICE_ID_ATI_215LG 0x4c47
+#define PCI_DEVICE_ID_ATI_264LT 0x4c54
+#define PCI_DEVICE_ID_ATI_264VT 0x5654
+
+#define PCI_VENDOR_ID_VLSI 0x1004
+#define PCI_DEVICE_ID_VLSI_82C592 0x0005
+#define PCI_DEVICE_ID_VLSI_82C593 0x0006
+#define PCI_DEVICE_ID_VLSI_82C594 0x0007
+#define PCI_DEVICE_ID_VLSI_82C597 0x0009
+#define PCI_DEVICE_ID_VLSI_82C541 0x000c
+#define PCI_DEVICE_ID_VLSI_82C543 0x000d
+#define PCI_DEVICE_ID_VLSI_82C532 0x0101
+#define PCI_DEVICE_ID_VLSI_82C534 0x0102
+#define PCI_DEVICE_ID_VLSI_82C535 0x0104
+#define PCI_DEVICE_ID_VLSI_82C147 0x0105
+#define PCI_DEVICE_ID_VLSI_VAS96011 0x0702
+
+#define PCI_VENDOR_ID_ADL 0x1005
+#define PCI_DEVICE_ID_ADL_2301 0x2301
+
+#define PCI_VENDOR_ID_NS 0x100b
+#define PCI_DEVICE_ID_NS_87415 0x0002
+#define PCI_DEVICE_ID_NS_87410 0xd001
+
+#define PCI_VENDOR_ID_TSENG 0x100c
+#define PCI_DEVICE_ID_TSENG_W32P_2 0x3202
+#define PCI_DEVICE_ID_TSENG_W32P_b 0x3205
+#define PCI_DEVICE_ID_TSENG_W32P_c 0x3206
+#define PCI_DEVICE_ID_TSENG_W32P_d 0x3207
+#define PCI_DEVICE_ID_TSENG_ET6000 0x3208
+
+#define PCI_VENDOR_ID_WEITEK 0x100e
+#define PCI_DEVICE_ID_WEITEK_P9000 0x9001
+#define PCI_DEVICE_ID_WEITEK_P9100 0x9100
+
+#define PCI_VENDOR_ID_DEC 0x1011
+#define PCI_DEVICE_ID_DEC_BRD 0x0001
+#define PCI_DEVICE_ID_DEC_TULIP 0x0002
+#define PCI_DEVICE_ID_DEC_TGA 0x0004
+#define PCI_DEVICE_ID_DEC_TULIP_FAST 0x0009
+#define PCI_DEVICE_ID_DEC_TGA2 0x000D
+#define PCI_DEVICE_ID_DEC_FDDI 0x000F
+#define PCI_DEVICE_ID_DEC_TULIP_PLUS 0x0014
+#define PCI_DEVICE_ID_DEC_21142 0x0019
+#define PCI_DEVICE_ID_DEC_21052 0x0021
+#define PCI_DEVICE_ID_DEC_21150 0x0022
+#define PCI_DEVICE_ID_DEC_21152 0x0024
+
+#define PCI_VENDOR_ID_CIRRUS 0x1013
+#define PCI_DEVICE_ID_CIRRUS_7548 0x0038
+#define PCI_DEVICE_ID_CIRRUS_5430 0x00a0
+#define PCI_DEVICE_ID_CIRRUS_5434_4 0x00a4
+#define PCI_DEVICE_ID_CIRRUS_5434_8 0x00a8
+#define PCI_DEVICE_ID_CIRRUS_5436 0x00ac
+#define PCI_DEVICE_ID_CIRRUS_5446 0x00b8
+#define PCI_DEVICE_ID_CIRRUS_5480 0x00bc
+#define PCI_DEVICE_ID_CIRRUS_5464 0x00d4
+#define PCI_DEVICE_ID_CIRRUS_5465 0x00d6
+#define PCI_DEVICE_ID_CIRRUS_6729 0x1100
+#define PCI_DEVICE_ID_CIRRUS_6832 0x1110
+#define PCI_DEVICE_ID_CIRRUS_7542 0x1200
+#define PCI_DEVICE_ID_CIRRUS_7543 0x1202
+#define PCI_DEVICE_ID_CIRRUS_7541 0x1204
+
+#define PCI_VENDOR_ID_IBM 0x1014
+#define PCI_DEVICE_ID_IBM_FIRE_CORAL 0x000a
+#define PCI_DEVICE_ID_IBM_TR 0x0018
+#define PCI_DEVICE_ID_IBM_82G2675 0x001d
+#define PCI_DEVICE_ID_IBM_MCA 0x0020
+#define PCI_DEVICE_ID_IBM_82351 0x0022
+#define PCI_DEVICE_ID_IBM_SERVERAID 0x002e
+#define PCI_DEVICE_ID_IBM_TR_WAKE 0x003e
+#define PCI_DEVICE_ID_IBM_MPIC 0x0046
+#define PCI_DEVICE_ID_IBM_3780IDSP 0x007d
+#define PCI_DEVICE_ID_IBM_MPIC_2 0xffff
+
+#define PCI_VENDOR_ID_WD 0x101c
+#define PCI_DEVICE_ID_WD_7197 0x3296
+
+#define PCI_VENDOR_ID_AMD 0x1022
+#define PCI_DEVICE_ID_AMD_LANCE 0x2000
+#define PCI_DEVICE_ID_AMD_SCSI 0x2020
+
+#define PCI_VENDOR_ID_TRIDENT 0x1023
+#define PCI_DEVICE_ID_TRIDENT_9397 0x9397
+#define PCI_DEVICE_ID_TRIDENT_9420 0x9420
+#define PCI_DEVICE_ID_TRIDENT_9440 0x9440
+#define PCI_DEVICE_ID_TRIDENT_9660 0x9660
+#define PCI_DEVICE_ID_TRIDENT_9750 0x9750
+
+#define PCI_VENDOR_ID_AI 0x1025
+#define PCI_DEVICE_ID_AI_M1435 0x1435
+
+#define PCI_VENDOR_ID_MATROX 0x102B
+#define PCI_DEVICE_ID_MATROX_MGA_2 0x0518
+#define PCI_DEVICE_ID_MATROX_MIL 0x0519
+#define PCI_DEVICE_ID_MATROX_MYS 0x051A
+#define PCI_DEVICE_ID_MATROX_MIL_2 0x051b
+#define PCI_DEVICE_ID_MATROX_MIL_2_AGP 0x051f
+#define PCI_DEVICE_ID_MATROX_MGA_IMP 0x0d10
+
+#define PCI_VENDOR_ID_CT 0x102c
+#define PCI_DEVICE_ID_CT_65545 0x00d8
+#define PCI_DEVICE_ID_CT_65548 0x00dc
+#define PCI_DEVICE_ID_CT_65550 0x00e0
+#define PCI_DEVICE_ID_CT_65554 0x00e4
+#define PCI_DEVICE_ID_CT_65555 0x00e5
+
+#define PCI_VENDOR_ID_MIRO 0x1031
+#define PCI_DEVICE_ID_MIRO_36050 0x5601
+
+#define PCI_VENDOR_ID_NEC 0x1033
+#define PCI_DEVICE_ID_NEC_PCX2 0x0046
+
+#define PCI_VENDOR_ID_FD 0x1036
+#define PCI_DEVICE_ID_FD_36C70 0x0000
+
+#define PCI_VENDOR_ID_SI 0x1039
+#define PCI_DEVICE_ID_SI_5591_AGP 0x0001
+#define PCI_DEVICE_ID_SI_6202 0x0002
+#define PCI_DEVICE_ID_SI_503 0x0008
+#define PCI_DEVICE_ID_SI_ACPI 0x0009
+#define PCI_DEVICE_ID_SI_5597_VGA 0x0200
+#define PCI_DEVICE_ID_SI_6205 0x0205
+#define PCI_DEVICE_ID_SI_501 0x0406
+#define PCI_DEVICE_ID_SI_496 0x0496
+#define PCI_DEVICE_ID_SI_601 0x0601
+#define PCI_DEVICE_ID_SI_5107 0x5107
+#define PCI_DEVICE_ID_SI_5511 0x5511
+#define PCI_DEVICE_ID_SI_5513 0x5513
+#define PCI_DEVICE_ID_SI_5571 0x5571
+#define PCI_DEVICE_ID_SI_5591 0x5591
+#define PCI_DEVICE_ID_SI_5597 0x5597
+#define PCI_DEVICE_ID_SI_7001 0x7001
+
+#define PCI_VENDOR_ID_HP 0x103c
+#define PCI_DEVICE_ID_HP_J2585A 0x1030
+#define PCI_DEVICE_ID_HP_J2585B 0x1031
+
+#define PCI_VENDOR_ID_PCTECH 0x1042
+#define PCI_DEVICE_ID_PCTECH_RZ1000 0x1000
+#define PCI_DEVICE_ID_PCTECH_RZ1001 0x1001
+#define PCI_DEVICE_ID_PCTECH_SAMURAI_0 0x3000
+#define PCI_DEVICE_ID_PCTECH_SAMURAI_1 0x3010
+#define PCI_DEVICE_ID_PCTECH_SAMURAI_IDE 0x3020
+
+#define PCI_VENDOR_ID_DPT 0x1044
+#define PCI_DEVICE_ID_DPT 0xa400
+
+#define PCI_VENDOR_ID_OPTI 0x1045
+#define PCI_DEVICE_ID_OPTI_92C178 0xc178
+#define PCI_DEVICE_ID_OPTI_82C557 0xc557
+#define PCI_DEVICE_ID_OPTI_82C558 0xc558
+#define PCI_DEVICE_ID_OPTI_82C621 0xc621
+#define PCI_DEVICE_ID_OPTI_82C700 0xc700
+#define PCI_DEVICE_ID_OPTI_82C701 0xc701
+#define PCI_DEVICE_ID_OPTI_82C814 0xc814
+#define PCI_DEVICE_ID_OPTI_82C822 0xc822
+#define PCI_DEVICE_ID_OPTI_82C825 0xd568
+
+#define PCI_VENDOR_ID_SGS 0x104a
+#define PCI_DEVICE_ID_SGS_2000 0x0008
+#define PCI_DEVICE_ID_SGS_1764 0x0009
+
+#define PCI_VENDOR_ID_BUSLOGIC 0x104B
+#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140
+#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER 0x1040
+#define PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT 0x8130
+
+#define PCI_VENDOR_ID_TI 0x104c
+#define PCI_DEVICE_ID_TI_TVP4010 0x3d04
+#define PCI_DEVICE_ID_TI_TVP4020 0x3d07
+#define PCI_DEVICE_ID_TI_PCI1130 0xac12
+#define PCI_DEVICE_ID_TI_PCI1031 0xac13
+#define PCI_DEVICE_ID_TI_PCI1131 0xac15
+#define PCI_DEVICE_ID_TI_PCI1250 0xac16
+#define PCI_DEVICE_ID_TI_PCI1220 0xac17
+
+#define PCI_VENDOR_ID_OAK 0x104e
+#define PCI_DEVICE_ID_OAK_OTI107 0x0107
+
+/* Winbond have two vendor IDs! See 0x10ad as well */
+#define PCI_VENDOR_ID_WINBOND2 0x1050
+#define PCI_DEVICE_ID_WINBOND2_89C940 0x0940
+
+#define PCI_VENDOR_ID_MOTOROLA 0x1057
+#define PCI_DEVICE_ID_MOTOROLA_MPC105 0x0001
+#define PCI_DEVICE_ID_MOTOROLA_MPC106 0x0002
+#define PCI_DEVICE_ID_MOTOROLA_RAVEN 0x4801
+
+#define PCI_VENDOR_ID_PROMISE 0x105a
+#define PCI_DEVICE_ID_PROMISE_20246 0x4d33
+#define PCI_DEVICE_ID_PROMISE_5300 0x5300
+
+#define PCI_VENDOR_ID_N9 0x105d
+#define PCI_DEVICE_ID_N9_I128 0x2309
+#define PCI_DEVICE_ID_N9_I128_2 0x2339
+#define PCI_DEVICE_ID_N9_I128_T2R 0x493d
+
+#define PCI_VENDOR_ID_UMC 0x1060
+#define PCI_DEVICE_ID_UMC_UM8673F 0x0101
+#define PCI_DEVICE_ID_UMC_UM8891A 0x0891
+#define PCI_DEVICE_ID_UMC_UM8886BF 0x673a
+#define PCI_DEVICE_ID_UMC_UM8886A 0x886a
+#define PCI_DEVICE_ID_UMC_UM8881F 0x8881
+#define PCI_DEVICE_ID_UMC_UM8886F 0x8886
+#define PCI_DEVICE_ID_UMC_UM9017F 0x9017
+#define PCI_DEVICE_ID_UMC_UM8886N 0xe886
+#define PCI_DEVICE_ID_UMC_UM8891N 0xe891
+
+#define PCI_VENDOR_ID_X 0x1061
+#define PCI_DEVICE_ID_X_AGX016 0x0001
+
+#define PCI_VENDOR_ID_PICOP 0x1066
+#define PCI_DEVICE_ID_PICOP_PT86C52X 0x0001
+#define PCI_DEVICE_ID_PICOP_PT80C524 0x8002
+
+#define PCI_VENDOR_ID_APPLE 0x106b
+#define PCI_DEVICE_ID_APPLE_BANDIT 0x0001
+#define PCI_DEVICE_ID_APPLE_GC 0x0002
+#define PCI_DEVICE_ID_APPLE_HYDRA 0x000e
+
+#define PCI_VENDOR_ID_NEXGEN 0x1074
+#define PCI_DEVICE_ID_NEXGEN_82C501 0x4e78
+
+#define PCI_VENDOR_ID_QLOGIC 0x1077
+#define PCI_DEVICE_ID_QLOGIC_ISP1020 0x1020
+#define PCI_DEVICE_ID_QLOGIC_ISP1022 0x1022
+
+#define PCI_VENDOR_ID_CYRIX 0x1078
+#define PCI_DEVICE_ID_CYRIX_5510 0x0000
+#define PCI_DEVICE_ID_CYRIX_PCI_MASTER 0x0001
+#define PCI_DEVICE_ID_CYRIX_5520 0x0002
+#define PCI_DEVICE_ID_CYRIX_5530_LEGACY 0x0100
+#define PCI_DEVICE_ID_CYRIX_5530_SMI 0x0101
+#define PCI_DEVICE_ID_CYRIX_5530_IDE 0x0102
+#define PCI_DEVICE_ID_CYRIX_5530_AUDIO 0x0103
+#define PCI_DEVICE_ID_CYRIX_5530_VIDEO 0x0104
+
+#define PCI_VENDOR_ID_LEADTEK 0x107d
+#define PCI_DEVICE_ID_LEADTEK_805 0x0000
+
+#define PCI_VENDOR_ID_CONTAQ 0x1080
+#define PCI_DEVICE_ID_CONTAQ_82C599 0x0600
+#define PCI_DEVICE_ID_CONTAQ_82C693 0xc693
+
+#define PCI_VENDOR_ID_FOREX 0x1083
+
+#define PCI_VENDOR_ID_OLICOM 0x108d
+#define PCI_DEVICE_ID_OLICOM_OC3136 0x0001
+#define PCI_DEVICE_ID_OLICOM_OC2315 0x0011
+#define PCI_DEVICE_ID_OLICOM_OC2325 0x0012
+#define PCI_DEVICE_ID_OLICOM_OC2183 0x0013
+#define PCI_DEVICE_ID_OLICOM_OC2326 0x0014
+#define PCI_DEVICE_ID_OLICOM_OC6151 0x0021
+
+#define PCI_VENDOR_ID_SUN 0x108e
+#define PCI_DEVICE_ID_SUN_EBUS 0x1000
+#define PCI_DEVICE_ID_SUN_HAPPYMEAL 0x1001
+#define PCI_DEVICE_ID_SUN_SIMBA 0x5000
+#define PCI_DEVICE_ID_SUN_PBM 0x8000
+#define PCI_DEVICE_ID_SUN_SABRE 0xa000
+
+#define PCI_VENDOR_ID_CMD 0x1095
+#define PCI_DEVICE_ID_CMD_640 0x0640
+#define PCI_DEVICE_ID_CMD_643 0x0643
+#define PCI_DEVICE_ID_CMD_646 0x0646
+#define PCI_DEVICE_ID_CMD_647 0x0647
+#define PCI_DEVICE_ID_CMD_670 0x0670
+
+#define PCI_VENDOR_ID_VISION 0x1098
+#define PCI_DEVICE_ID_VISION_QD8500 0x0001
+#define PCI_DEVICE_ID_VISION_QD8580 0x0002
+
+#define PCI_VENDOR_ID_BROOKTREE 0x109e
+#define PCI_DEVICE_ID_BROOKTREE_848 0x0350
+#define PCI_DEVICE_ID_BROOKTREE_849A 0x0351
+#define PCI_DEVICE_ID_BROOKTREE_8474 0x8474
+
+#define PCI_VENDOR_ID_SIERRA 0x10a8
+#define PCI_DEVICE_ID_SIERRA_STB 0x0000
+
+#define PCI_VENDOR_ID_ACC 0x10aa
+#define PCI_DEVICE_ID_ACC_2056 0x0000
+
+#define PCI_VENDOR_ID_WINBOND 0x10ad
+#define PCI_DEVICE_ID_WINBOND_83769 0x0001
+#define PCI_DEVICE_ID_WINBOND_82C105 0x0105
+#define PCI_DEVICE_ID_WINBOND_83C553 0x0565
+
+#define PCI_VENDOR_ID_DATABOOK 0x10b3
+#define PCI_DEVICE_ID_DATABOOK_87144 0xb106
+
+#define PCI_VENDOR_ID_PLX 0x10b5
+#define PCI_DEVICE_ID_PLX_9050 0x9050
+#define PCI_DEVICE_ID_PLX_9060 0x9060
+#define PCI_DEVICE_ID_PLX_9060ES 0x906E
+#define PCI_DEVICE_ID_PLX_9060SD 0x906D
+#define PCI_DEVICE_ID_PLX_9080 0x9080
+
+#define PCI_VENDOR_ID_MADGE 0x10b6
+#define PCI_DEVICE_ID_MADGE_MK2 0x0002
+#define PCI_DEVICE_ID_MADGE_C155S 0x1001
+
+#define PCI_VENDOR_ID_3COM 0x10b7
+#define PCI_DEVICE_ID_3COM_3C339 0x3390
+#define PCI_DEVICE_ID_3COM_3C590 0x5900
+#define PCI_DEVICE_ID_3COM_3C595TX 0x5950
+#define PCI_DEVICE_ID_3COM_3C595T4 0x5951
+#define PCI_DEVICE_ID_3COM_3C595MII 0x5952
+#define PCI_DEVICE_ID_3COM_3C900TPO 0x9000
+#define PCI_DEVICE_ID_3COM_3C900COMBO 0x9001
+#define PCI_DEVICE_ID_3COM_3C905TX 0x9050
+#define PCI_DEVICE_ID_3COM_3C905T4 0x9051
+#define PCI_DEVICE_ID_3COM_3C905B_TX 0x9055
+
+#define PCI_VENDOR_ID_SMC 0x10b8
+#define PCI_DEVICE_ID_SMC_EPIC100 0x0005
+
+#define PCI_VENDOR_ID_AL 0x10b9
+#define PCI_DEVICE_ID_AL_M1445 0x1445
+#define PCI_DEVICE_ID_AL_M1449 0x1449
+#define PCI_DEVICE_ID_AL_M1451 0x1451
+#define PCI_DEVICE_ID_AL_M1461 0x1461
+#define PCI_DEVICE_ID_AL_M1489 0x1489
+#define PCI_DEVICE_ID_AL_M1511 0x1511
+#define PCI_DEVICE_ID_AL_M1513 0x1513
+#define PCI_DEVICE_ID_AL_M1521 0x1521
+#define PCI_DEVICE_ID_AL_M1523 0x1523
+#define PCI_DEVICE_ID_AL_M1531 0x1531
+#define PCI_DEVICE_ID_AL_M1533 0x1533
+#define PCI_DEVICE_ID_AL_M3307 0x3307
+#define PCI_DEVICE_ID_AL_M4803 0x5215
+#define PCI_DEVICE_ID_AL_M5219 0x5219
+#define PCI_DEVICE_ID_AL_M5229 0x5229
+#define PCI_DEVICE_ID_AL_M5237 0x5237
+#define PCI_DEVICE_ID_AL_M7101 0x7101
+
+#define PCI_VENDOR_ID_MITSUBISHI 0x10ba
+
+#define PCI_VENDOR_ID_SURECOM 0x10bd
+#define PCI_DEVICE_ID_SURECOM_NE34 0x0e34
+
+#define PCI_VENDOR_ID_NEOMAGIC 0x10c8
+#define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_NM2070 0x0001
+#define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_128V 0x0002
+#define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_128ZV 0x0003
+#define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_NM2160 0x0004
+
+#define PCI_VENDOR_ID_ASP 0x10cd
+#define PCI_DEVICE_ID_ASP_ABP940 0x1200
+#define PCI_DEVICE_ID_ASP_ABP940U 0x1300
+#define PCI_DEVICE_ID_ASP_ABP940UW 0x2300
+
+#define PCI_VENDOR_ID_MACRONIX 0x10d9
+#define PCI_DEVICE_ID_MACRONIX_MX98713 0x0512
+#define PCI_DEVICE_ID_MACRONIX_MX987x5 0x0531
+
+#define PCI_VENDOR_ID_CERN 0x10dc
+#define PCI_DEVICE_ID_CERN_SPSB_PMC 0x0001
+#define PCI_DEVICE_ID_CERN_SPSB_PCI 0x0002
+#define PCI_DEVICE_ID_CERN_HIPPI_DST 0x0021
+#define PCI_DEVICE_ID_CERN_HIPPI_SRC 0x0022
+
+#define PCI_VENDOR_ID_NVIDIA 0x10de
+
+#define PCI_VENDOR_ID_IMS 0x10e0
+#define PCI_DEVICE_ID_IMS_8849 0x8849
+
+#define PCI_VENDOR_ID_TEKRAM2 0x10e1
+#define PCI_DEVICE_ID_TEKRAM2_690c 0x690c
+
+#define PCI_VENDOR_ID_TUNDRA 0x10e3
+#define PCI_DEVICE_ID_TUNDRA_CA91C042 0x0000
+
+#define PCI_VENDOR_ID_AMCC 0x10e8
+#define PCI_DEVICE_ID_AMCC_MYRINET 0x8043
+#define PCI_DEVICE_ID_AMCC_PARASTATION 0x8062
+#define PCI_DEVICE_ID_AMCC_S5933 0x807d
+#define PCI_DEVICE_ID_AMCC_S5933_HEPC3 0x809c
+
+#define PCI_VENDOR_ID_INTERG 0x10ea
+#define PCI_DEVICE_ID_INTERG_1680 0x1680
+#define PCI_DEVICE_ID_INTERG_1682 0x1682
+
+#define PCI_VENDOR_ID_REALTEK 0x10ec
+#define PCI_DEVICE_ID_REALTEK_8029 0x8029
+#define PCI_DEVICE_ID_REALTEK_8129 0x8129
+#define PCI_DEVICE_ID_REALTEK_8139 0x8139
+
+#define PCI_VENDOR_ID_TRUEVISION 0x10fa
+#define PCI_DEVICE_ID_TRUEVISION_T1000 0x000c
+
+#define PCI_VENDOR_ID_INIT 0x1101
+#define PCI_DEVICE_ID_INIT_320P 0x9100
+#define PCI_DEVICE_ID_INIT_360P 0x9500
+
+#define PCI_VENDOR_ID_TTI 0x1103
+#define PCI_DEVICE_ID_TTI_HPT343 0x0003
+
+#define PCI_VENDOR_ID_VIA 0x1106
+#define PCI_DEVICE_ID_VIA_82C505 0x0505
+#define PCI_DEVICE_ID_VIA_82C561 0x0561
+#define PCI_DEVICE_ID_VIA_82C586_1 0x0571
+#define PCI_DEVICE_ID_VIA_82C576 0x0576
+#define PCI_DEVICE_ID_VIA_82C585 0x0585
+#define PCI_DEVICE_ID_VIA_82C586_0 0x0586
+#define PCI_DEVICE_ID_VIA_82C595 0x0595
+#define PCI_DEVICE_ID_VIA_82C597_0 0x0597
+#define PCI_DEVICE_ID_VIA_82C926 0x0926
+#define PCI_DEVICE_ID_VIA_82C416 0x1571
+#define PCI_DEVICE_ID_VIA_82C595_97 0x1595
+#define PCI_DEVICE_ID_VIA_82C586_2 0x3038
+#define PCI_DEVICE_ID_VIA_82C586_3 0x3040
+#define PCI_DEVICE_ID_VIA_86C100A 0x6100
+#define PCI_DEVICE_ID_VIA_82C597_1 0x8597
+
+#define PCI_VENDOR_ID_VORTEX 0x1119
+#define PCI_DEVICE_ID_VORTEX_GDT60x0 0x0000
+#define PCI_DEVICE_ID_VORTEX_GDT6000B 0x0001
+#define PCI_DEVICE_ID_VORTEX_GDT6x10 0x0002
+#define PCI_DEVICE_ID_VORTEX_GDT6x20 0x0003
+#define PCI_DEVICE_ID_VORTEX_GDT6530 0x0004
+#define PCI_DEVICE_ID_VORTEX_GDT6550 0x0005
+#define PCI_DEVICE_ID_VORTEX_GDT6x17 0x0006
+#define PCI_DEVICE_ID_VORTEX_GDT6x27 0x0007
+#define PCI_DEVICE_ID_VORTEX_GDT6537 0x0008
+#define PCI_DEVICE_ID_VORTEX_GDT6557 0x0009
+#define PCI_DEVICE_ID_VORTEX_GDT6x15 0x000a
+#define PCI_DEVICE_ID_VORTEX_GDT6x25 0x000b
+#define PCI_DEVICE_ID_VORTEX_GDT6535 0x000c
+#define PCI_DEVICE_ID_VORTEX_GDT6555 0x000d
+#define PCI_DEVICE_ID_VORTEX_GDT6x17RP 0x0100
+#define PCI_DEVICE_ID_VORTEX_GDT6x27RP 0x0101
+#define PCI_DEVICE_ID_VORTEX_GDT6537RP 0x0102
+#define PCI_DEVICE_ID_VORTEX_GDT6557RP 0x0103
+#define PCI_DEVICE_ID_VORTEX_GDT6x11RP 0x0104
+#define PCI_DEVICE_ID_VORTEX_GDT6x21RP 0x0105
+#define PCI_DEVICE_ID_VORTEX_GDT6x17RP1 0x0110
+#define PCI_DEVICE_ID_VORTEX_GDT6x27RP1 0x0111
+#define PCI_DEVICE_ID_VORTEX_GDT6537RP1 0x0112
+#define PCI_DEVICE_ID_VORTEX_GDT6557RP1 0x0113
+#define PCI_DEVICE_ID_VORTEX_GDT6x11RP1 0x0114
+#define PCI_DEVICE_ID_VORTEX_GDT6x21RP1 0x0115
+#define PCI_DEVICE_ID_VORTEX_GDT6x17RP2 0x0120
+#define PCI_DEVICE_ID_VORTEX_GDT6x27RP2 0x0121
+#define PCI_DEVICE_ID_VORTEX_GDT6537RP2 0x0122
+#define PCI_DEVICE_ID_VORTEX_GDT6557RP2 0x0123
+#define PCI_DEVICE_ID_VORTEX_GDT6x11RP2 0x0124
+#define PCI_DEVICE_ID_VORTEX_GDT6x21RP2 0x0125
+
+#define PCI_VENDOR_ID_EF 0x111a
+#define PCI_DEVICE_ID_EF_ATM_FPGA 0x0000
+#define PCI_DEVICE_ID_EF_ATM_ASIC 0x0002
+
+#define PCI_VENDOR_ID_FORE 0x1127
+#define PCI_DEVICE_ID_FORE_PCA200PC 0x0210
+#define PCI_DEVICE_ID_FORE_PCA200E 0x0300
+
+#define PCI_VENDOR_ID_IMAGINGTECH 0x112f
+#define PCI_DEVICE_ID_IMAGINGTECH_ICPCI 0x0000
+
+#define PCI_VENDOR_ID_PHILIPS 0x1131
+#define PCI_DEVICE_ID_PHILIPS_SAA7145 0x7145
+#define PCI_DEVICE_ID_PHILIPS_SAA7146 0x7146
+
+#define PCI_VENDOR_ID_CYCLONE 0x113c
+#define PCI_DEVICE_ID_CYCLONE_SDK 0x0001
+
+#define PCI_VENDOR_ID_ALLIANCE 0x1142
+#define PCI_DEVICE_ID_ALLIANCE_PROMOTIO 0x3210
+#define PCI_DEVICE_ID_ALLIANCE_PROVIDEO 0x6422
+#define PCI_DEVICE_ID_ALLIANCE_AT24 0x6424
+#define PCI_DEVICE_ID_ALLIANCE_AT3D 0x643d
+
+#define PCI_VENDOR_ID_SK 0x1148
+#define PCI_DEVICE_ID_SK_FP 0x4000
+#define PCI_DEVICE_ID_SK_TR 0x4200
+#define PCI_DEVICE_ID_SK_GE 0x4300
+
+#define PCI_VENDOR_ID_VMIC 0x114a
+#define PCI_DEVICE_ID_VMIC_VME 0x7587
+
+#define PCI_VENDOR_ID_DIGI 0x114f
+#define PCI_DEVICE_ID_DIGI_EPC 0x0002
+#define PCI_DEVICE_ID_DIGI_RIGHTSWITCH 0x0003
+#define PCI_DEVICE_ID_DIGI_XEM 0x0004
+#define PCI_DEVICE_ID_DIGI_XR 0x0005
+#define PCI_DEVICE_ID_DIGI_CX 0x0006
+#define PCI_DEVICE_ID_DIGI_XRJ 0x0009
+#define PCI_DEVICE_ID_DIGI_EPCJ 0x000a
+#define PCI_DEVICE_ID_DIGI_XR_920 0x0027
+
+#define PCI_VENDOR_ID_MUTECH 0x1159
+#define PCI_DEVICE_ID_MUTECH_MV1000 0x0001
+
+#define PCI_VENDOR_ID_RENDITION 0x1163
+#define PCI_DEVICE_ID_RENDITION_VERITE 0x0001
+#define PCI_DEVICE_ID_RENDITION_VERITE2100 0x2000
+
+#define PCI_VENDOR_ID_TOSHIBA 0x1179
+#define PCI_DEVICE_ID_TOSHIBA_601 0x0601
+#define PCI_DEVICE_ID_TOSHIBA_TOPIC95 0x060a
+#define PCI_DEVICE_ID_TOSHIBA_TOPIC97 0x060f
+
+#define PCI_VENDOR_ID_RICOH 0x1180
+#define PCI_DEVICE_ID_RICOH_RL5C465 0x0465
+#define PCI_DEVICE_ID_RICOH_RL5C466 0x0466
+#define PCI_DEVICE_ID_RICOH_RL5C475 0x0475
+#define PCI_DEVICE_ID_RICOH_RL5C478 0x0478
+
+#define PCI_VENDOR_ID_ARTOP 0x1191
+#define PCI_DEVICE_ID_ARTOP_ATP8400 0x0004
+#define PCI_DEVICE_ID_ARTOP_ATP850UF 0x0005
+
+#define PCI_VENDOR_ID_ZEITNET 0x1193
+#define PCI_DEVICE_ID_ZEITNET_1221 0x0001
+#define PCI_DEVICE_ID_ZEITNET_1225 0x0002
+
+#define PCI_VENDOR_ID_OMEGA 0x119b
+#define PCI_DEVICE_ID_OMEGA_82C092G 0x1221
+
+#define PCI_VENDOR_ID_LITEON 0x11ad
+#define PCI_DEVICE_ID_LITEON_LNE100TX 0x0002
+
+#define PCI_VENDOR_ID_NP 0x11bc
+#define PCI_DEVICE_ID_NP_PCI_FDDI 0x0001
+
+#define PCI_VENDOR_ID_ATT 0x11c1
+#define PCI_DEVICE_ID_ATT_L56XMF 0x0440
+
+#define PCI_VENDOR_ID_SPECIALIX 0x11cb
+#define PCI_DEVICE_ID_SPECIALIX_IO8 0x2000
+#define PCI_DEVICE_ID_SPECIALIX_XIO 0x4000
+#define PCI_DEVICE_ID_SPECIALIX_RIO 0x8000
+
+#define PCI_VENDOR_ID_AURAVISION 0x11d1
+#define PCI_DEVICE_ID_AURAVISION_VXP524 0x01f7
+
+#define PCI_VENDOR_ID_IKON 0x11d5
+#define PCI_DEVICE_ID_IKON_10115 0x0115
+#define PCI_DEVICE_ID_IKON_10117 0x0117
+
+#define PCI_VENDOR_ID_ZORAN 0x11de
+#define PCI_DEVICE_ID_ZORAN_36057 0x6057
+#define PCI_DEVICE_ID_ZORAN_36120 0x6120
+
+#define PCI_VENDOR_ID_KINETIC 0x11f4
+#define PCI_DEVICE_ID_KINETIC_2915 0x2915
+
+#define PCI_VENDOR_ID_COMPEX 0x11f6
+#define PCI_DEVICE_ID_COMPEX_ENET100VG4 0x0112
+#define PCI_DEVICE_ID_COMPEX_RL2000 0x1401
+
+#define PCI_VENDOR_ID_RP 0x11fe
+#define PCI_DEVICE_ID_RP32INTF 0x0001
+#define PCI_DEVICE_ID_RP8INTF 0x0002
+#define PCI_DEVICE_ID_RP16INTF 0x0003
+#define PCI_DEVICE_ID_RP4QUAD 0x0004
+#define PCI_DEVICE_ID_RP8OCTA 0x0005
+#define PCI_DEVICE_ID_RP8J 0x0006
+#define PCI_DEVICE_ID_RPP4 0x000A
+#define PCI_DEVICE_ID_RPP8 0x000B
+#define PCI_DEVICE_ID_RP8M 0x000C
+
+#define PCI_VENDOR_ID_CYCLADES 0x120e
+#define PCI_DEVICE_ID_CYCLOM_Y_Lo 0x0100
+#define PCI_DEVICE_ID_CYCLOM_Y_Hi 0x0101
+#define PCI_DEVICE_ID_CYCLOM_Z_Lo 0x0200
+#define PCI_DEVICE_ID_CYCLOM_Z_Hi 0x0201
+
+#define PCI_VENDOR_ID_ESSENTIAL 0x120f
+#define PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER 0x0001
+
+#define PCI_VENDOR_ID_O2 0x1217
+#define PCI_DEVICE_ID_O2_6729 0x6729
+#define PCI_DEVICE_ID_O2_6730 0x673a
+#define PCI_DEVICE_ID_O2_6832 0x6832
+#define PCI_DEVICE_ID_O2_6836 0x6836
+
+#define PCI_VENDOR_ID_3DFX 0x121a
+#define PCI_DEVICE_ID_3DFX_VOODOO 0x0001
+#define PCI_DEVICE_ID_3DFX_VOODOO2 0x0002
+
+#define PCI_VENDOR_ID_SIGMADES 0x1236
+#define PCI_DEVICE_ID_SIGMADES_6425 0x6401
+
+#define PCI_VENDOR_ID_CCUBE 0x123f
+
+#define PCI_VENDOR_ID_DIPIX 0x1246
+
+#define PCI_VENDOR_ID_STALLION 0x124d
+#define PCI_DEVICE_ID_STALLION_ECHPCI832 0x0000
+#define PCI_DEVICE_ID_STALLION_ECHPCI864 0x0002
+#define PCI_DEVICE_ID_STALLION_EIOPCI 0x0003
+
+#define PCI_VENDOR_ID_OPTIBASE 0x1255
+#define PCI_DEVICE_ID_OPTIBASE_FORGE 0x1110
+#define PCI_DEVICE_ID_OPTIBASE_FUSION 0x1210
+#define PCI_DEVICE_ID_OPTIBASE_VPLEX 0x2110
+#define PCI_DEVICE_ID_OPTIBASE_VPLEXCC 0x2120
+#define PCI_DEVICE_ID_OPTIBASE_VQUEST 0x2130
+
+#define PCI_VENDOR_ID_SATSAGEM 0x1267
+#define PCI_DEVICE_ID_SATSAGEM_PCR2101 0x5352
+#define PCI_DEVICE_ID_SATSAGEM_TELSATTURBO 0x5a4b
+
+#define PCI_VENDOR_ID_HUGHES 0x1273
+#define PCI_DEVICE_ID_HUGHES_DIRECPC 0x0002
+
+#define PCI_VENDOR_ID_ENSONIQ 0x1274
+#define PCI_DEVICE_ID_ENSONIQ_AUDIOPCI 0x5000
+
+#define PCI_VENDOR_ID_ALTEON 0x12ae
+#define PCI_DEVICE_ID_ALTEON_ACENIC 0x0001
+
+#define PCI_VENDOR_ID_PICTUREL 0x12c5
+#define PCI_DEVICE_ID_PICTUREL_PCIVST 0x0081
+
+#define PCI_VENDOR_ID_NVIDIA_SGS 0x12d2
+#define PCI_DEVICE_ID_NVIDIA_SGS_RIVA128 0x0018
+
+#define PCI_VENDOR_ID_CBOARDS 0x1307
+#define PCI_DEVICE_ID_CBOARDS_DAS1602_16 0x0001
+
+#define PCI_VENDOR_ID_SYMPHONY 0x1c1c
+#define PCI_DEVICE_ID_SYMPHONY_101 0x0001
+
+#define PCI_VENDOR_ID_TEKRAM 0x1de1
+#define PCI_DEVICE_ID_TEKRAM_DC290 0xdc29
+
+#define PCI_VENDOR_ID_3DLABS 0x3d3d
+#define PCI_DEVICE_ID_3DLABS_300SX 0x0001
+#define PCI_DEVICE_ID_3DLABS_500TX 0x0002
+#define PCI_DEVICE_ID_3DLABS_DELTA 0x0003
+#define PCI_DEVICE_ID_3DLABS_PERMEDIA 0x0004
+#define PCI_DEVICE_ID_3DLABS_MX 0x0006
+
+#define PCI_VENDOR_ID_AVANCE 0x4005
+#define PCI_DEVICE_ID_AVANCE_ALG2064 0x2064
+#define PCI_DEVICE_ID_AVANCE_2302 0x2302
+
+#define PCI_VENDOR_ID_NETVIN 0x4a14
+#define PCI_DEVICE_ID_NETVIN_NV5000SC 0x5000
+
+#define PCI_VENDOR_ID_S3 0x5333
+#define PCI_DEVICE_ID_S3_PLATO_PXS 0x0551
+#define PCI_DEVICE_ID_S3_ViRGE 0x5631
+#define PCI_DEVICE_ID_S3_TRIO 0x8811
+#define PCI_DEVICE_ID_S3_AURORA64VP 0x8812
+#define PCI_DEVICE_ID_S3_TRIO64UVP 0x8814
+#define PCI_DEVICE_ID_S3_ViRGE_VX 0x883d
+#define PCI_DEVICE_ID_S3_868 0x8880
+#define PCI_DEVICE_ID_S3_928 0x88b0
+#define PCI_DEVICE_ID_S3_864_1 0x88c0
+#define PCI_DEVICE_ID_S3_864_2 0x88c1
+#define PCI_DEVICE_ID_S3_964_1 0x88d0
+#define PCI_DEVICE_ID_S3_964_2 0x88d1
+#define PCI_DEVICE_ID_S3_968 0x88f0
+#define PCI_DEVICE_ID_S3_TRIO64V2 0x8901
+#define PCI_DEVICE_ID_S3_PLATO_PXG 0x8902
+#define PCI_DEVICE_ID_S3_ViRGE_DXGX 0x8a01
+#define PCI_DEVICE_ID_S3_ViRGE_GX2 0x8a10
+#define PCI_DEVICE_ID_S3_ViRGE_MX 0x8c01
+#define PCI_DEVICE_ID_S3_ViRGE_MXP 0x8c02
+#define PCI_DEVICE_ID_S3_ViRGE_MXPMV 0x8c03
+#define PCI_DEVICE_ID_S3_SONICVIBES 0xca00
+
+#define PCI_VENDOR_ID_INTEL 0x8086
+#define PCI_DEVICE_ID_INTEL_82375 0x0482
+#define PCI_DEVICE_ID_INTEL_82424 0x0483
+#define PCI_DEVICE_ID_INTEL_82378 0x0484
+#define PCI_DEVICE_ID_INTEL_82430 0x0486
+#define PCI_DEVICE_ID_INTEL_82434 0x04a3
+#define PCI_DEVICE_ID_INTEL_82092AA_0 0x1221
+#define PCI_DEVICE_ID_INTEL_82092AA_1 0x1222
+#define PCI_DEVICE_ID_INTEL_7116 0x1223
+#define PCI_DEVICE_ID_INTEL_82596 0x1226
+#define PCI_DEVICE_ID_INTEL_82865 0x1227
+#define PCI_DEVICE_ID_INTEL_82557 0x1229
+#define PCI_DEVICE_ID_INTEL_82437 0x122d
+#define PCI_DEVICE_ID_INTEL_82371FB_0 0x122e
+#define PCI_DEVICE_ID_INTEL_82371FB_1 0x1230
+#define PCI_DEVICE_ID_INTEL_82371MX 0x1234
+#define PCI_DEVICE_ID_INTEL_82437MX 0x1235
+#define PCI_DEVICE_ID_INTEL_82441 0x1237
+#define PCI_DEVICE_ID_INTEL_82380FB 0x124b
+#define PCI_DEVICE_ID_INTEL_82439 0x1250
+#define PCI_DEVICE_ID_INTEL_82371SB_0 0x7000
+#define PCI_DEVICE_ID_INTEL_82371SB_1 0x7010
+#define PCI_DEVICE_ID_INTEL_82371SB_2 0x7020
+#define PCI_DEVICE_ID_INTEL_82437VX 0x7030
+#define PCI_DEVICE_ID_INTEL_82439TX 0x7100
+#define PCI_DEVICE_ID_INTEL_82371AB_0 0x7110
+#define PCI_DEVICE_ID_INTEL_82371AB 0x7111
+#define PCI_DEVICE_ID_INTEL_82371AB_2 0x7112
+#define PCI_DEVICE_ID_INTEL_82371AB_3 0x7113
+#define PCI_DEVICE_ID_INTEL_82443LX_0 0x7180
+#define PCI_DEVICE_ID_INTEL_82443LX_1 0x7181
+#define PCI_DEVICE_ID_INTEL_82443BX_0 0x7190
+#define PCI_DEVICE_ID_INTEL_82443BX_1 0x7191
+#define PCI_DEVICE_ID_INTEL_82443BX_2 0x7192
+#define PCI_DEVICE_ID_INTEL_P6 0x84c4
+#define PCI_DEVICE_ID_INTEL_82450GX 0x84c5
+
+#define PCI_VENDOR_ID_KTI 0x8e2e
+#define PCI_DEVICE_ID_KTI_ET32P2 0x3000
+
+#define PCI_VENDOR_ID_ADAPTEC 0x9004
+#define PCI_DEVICE_ID_ADAPTEC_7810 0x1078
+#define PCI_DEVICE_ID_ADAPTEC_7850 0x5078
+#define PCI_DEVICE_ID_ADAPTEC_7855 0x5578
+#define PCI_DEVICE_ID_ADAPTEC_5800 0x5800
+#define PCI_DEVICE_ID_ADAPTEC_1480A 0x6075
+#define PCI_DEVICE_ID_ADAPTEC_7860 0x6078
+#define PCI_DEVICE_ID_ADAPTEC_7861 0x6178
+#define PCI_DEVICE_ID_ADAPTEC_7870 0x7078
+#define PCI_DEVICE_ID_ADAPTEC_7871 0x7178
+#define PCI_DEVICE_ID_ADAPTEC_7872 0x7278
+#define PCI_DEVICE_ID_ADAPTEC_7873 0x7378
+#define PCI_DEVICE_ID_ADAPTEC_7874 0x7478
+#define PCI_DEVICE_ID_ADAPTEC_7895 0x7895
+#define PCI_DEVICE_ID_ADAPTEC_7880 0x8078
+#define PCI_DEVICE_ID_ADAPTEC_7881 0x8178
+#define PCI_DEVICE_ID_ADAPTEC_7882 0x8278
+#define PCI_DEVICE_ID_ADAPTEC_7883 0x8378
+#define PCI_DEVICE_ID_ADAPTEC_7884 0x8478
+#define PCI_DEVICE_ID_ADAPTEC_1030 0x8b78
+
+#define PCI_VENDOR_ID_ADAPTEC2 0x9005
+#define PCI_DEVICE_ID_ADAPTEC2_2940U2 0x0010
+#define PCI_DEVICE_ID_ADAPTEC2_7890 0x001f
+#define PCI_DEVICE_ID_ADAPTEC2_3940U2 0x0050
+#define PCI_DEVICE_ID_ADAPTEC2_7896 0x005f
+
+#define PCI_VENDOR_ID_ATRONICS 0x907f
+#define PCI_DEVICE_ID_ATRONICS_2015 0x2015
+
+#define PCI_VENDOR_ID_HOLTEK 0x9412
+#define PCI_DEVICE_ID_HOLTEK_6565 0x6565
+
+#define PCI_VENDOR_ID_TIGERJET 0xe159
+#define PCI_DEVICE_ID_TIGERJET_300 0x0001
+
+#define PCI_VENDOR_ID_ARK 0xedd8
+#define PCI_DEVICE_ID_ARK_STING 0xa091
+#define PCI_DEVICE_ID_ARK_STINGARK 0xa099
+#define PCI_DEVICE_ID_ARK_2000MT 0xa0a1
+
+/*
+ * The PCI interface treats multi-function devices as independent
+ * devices. The slot/function address of each device is encoded
+ * in a single byte as follows:
+ *
+ * 7:3 = slot
+ * 2:0 = function
+ */
+#define PCI_DEVFN(slot,func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
+#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f)
+#define PCI_FUNC(devfn) ((devfn) & 0x07)
+
+/*
+ * Error values that may be returned by the PCI bios.
+ */
+#define PCIBIOS_SUCCESSFUL 0x00
+#define PCIBIOS_FUNC_NOT_SUPPORTED 0x81
+#define PCIBIOS_BAD_VENDOR_ID 0x83
+#define PCIBIOS_DEVICE_NOT_FOUND 0x86
+#define PCIBIOS_BAD_REGISTER_NUMBER 0x87
+#define PCIBIOS_SET_FAILED 0x88
+#define PCIBIOS_BUFFER_TOO_SMALL 0x89
+
+#define PCI_MAX_DEVICES 16
+#define PCI_MAX_FUNCTIONS 8
+
+typedef struct {
+ int (*read_config_byte)(unsigned char, unsigned char, unsigned char,
+ unsigned char, unsigned char *);
+ int (*read_config_word)(unsigned char, unsigned char, unsigned char,
+ unsigned char, unsigned short *);
+ int (*read_config_dword)(unsigned char, unsigned char, unsigned char,
+ unsigned char, unsigned int *);
+ int (*write_config_byte)(unsigned char, unsigned char, unsigned char,
+ unsigned char, unsigned char);
+ int (*write_config_word)(unsigned char, unsigned char, unsigned char,
+ unsigned char, unsigned short);
+ int (*write_config_dword)(unsigned char, unsigned char, unsigned char,
+ unsigned char, unsigned int);
+}pci_config_access_functions;
+
+typedef struct {
+ volatile unsigned char* pci_config_addr;
+ volatile unsigned char* pci_config_data;
+ pci_config_access_functions* pci_functions;
+} pci_config;
+
+extern pci_config pci;
+
+extern inline int
+pci_read_config_byte(unsigned char bus, unsigned char slot, unsigned char function,
+ unsigned char where, unsigned char * val) {
+ return pci.pci_functions->read_config_byte(bus, slot, function, where, val);
+}
+
+extern inline int
+pci_read_config_word(unsigned char bus, unsigned char slot, unsigned char function,
+ unsigned char where, unsigned short * val) {
+ return pci.pci_functions->read_config_word(bus, slot, function, where, val);
+}
+
+extern inline int
+pci_read_config_dword(unsigned char bus, unsigned char slot, unsigned char function,
+ unsigned char where, unsigned int * val) {
+ return pci.pci_functions->read_config_dword(bus, slot, function, where, val);
+}
+
+extern inline int
+pci_write_config_byte(unsigned char bus, unsigned char slot, unsigned char function,
+ unsigned char where, unsigned char val) {
+ return pci.pci_functions->write_config_byte(bus, slot, function, where, val);
+}
+
+extern inline int
+pci_write_config_word(unsigned char bus, unsigned char slot, unsigned char function,
+ unsigned char where, unsigned short val) {
+ return pci.pci_functions->write_config_word(bus, slot, function, where, val);
+}
+
+extern inline int
+pci_write_config_dword(unsigned char bus, unsigned char slot, unsigned char function,
+ unsigned char where, unsigned int val) {
+ return pci.pci_functions->write_config_dword(bus, slot, function, where, val);
+}
+
+/*
+ * Return the number of PCI busses in the system
+ */
+extern unsigned char BusCountPCI();
+extern void InitializePCI();
+
+#endif /* RTEMS_PCI_H */
diff --git a/cpukit/include/rtems/stdint.h b/cpukit/include/rtems/stdint.h
new file mode 100644
index 0000000000..5703f4273f
--- /dev/null
+++ b/cpukit/include/rtems/stdint.h
@@ -0,0 +1,54 @@
+/*
+ * rtems/stdint.h
+ *
+ * ISO C99 integer types
+ *
+ * $Id$
+ */
+
+#ifndef __rtems_stdint_h
+#define __rtems_stdint_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/cpuopts.h>
+
+#if RTEMS_USES_STDINT_H
+#include <stdint.h>
+
+#elif RTEMS_USES_INTTYPES_H
+#include <inttypes.h>
+
+#else
+/*
+ * Wild guesses on systems not providing stdint.h nor inttypes.h
+ * Known to work on Cywgin-1.3
+ */
+
+#include <sys/types.h>
+
+#if !defined(uint8_t) && defined(__uint8_t)
+typedef __uint8_t uint8_t;
+#endif
+
+#if !defined(uint16_t) && defined(__uint16_t)
+typedef __uint16_t uint16_t;
+#endif
+
+#if !defined(uint32_t) && defined(__uint32_t)
+typedef __uint32_t uint32_t;
+#endif
+
+#if !defined(uint64_t) && defined(__uint64_t)
+typedef __uint64_t uint64_t;
+#endif
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/include/rtems/userenv.h b/cpukit/include/rtems/userenv.h
new file mode 100644
index 0000000000..663f97d73a
--- /dev/null
+++ b/cpukit/include/rtems/userenv.h
@@ -0,0 +1,86 @@
+/*
+ * Libio Internal Information
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __rtems_userenv_h
+#define __rtems_userenv_h
+
+#include <rtems.h>
+#include <rtems/fs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * External structures
+ */
+
+/*
+ * According to IEEE Std 1003.1-2001,
+ * limits.h is supposed to provide _POSIX_LOGIN_NAME_MAX
+ * FIXME: We should not rely on this.
+ */
+#include <limits.h>
+
+#ifdef _POSIX_LOGIN_NAME_MAX
+#define LOGIN_NAME_MAX _POSIX_LOGIN_NAME_MAX
+#else
+/* Fallback */
+#define LOGIN_NAME_MAX 9
+#endif
+
+typedef struct {
+ rtems_id task_id;
+ rtems_filesystem_location_info_t current_directory;
+ rtems_filesystem_location_info_t root_directory;
+ /* Default mode for all files. */
+ mode_t umask;
+ nlink_t link_counts;
+ /* _POSIX_types */
+ uid_t uid;
+ gid_t gid;
+ uid_t euid;
+ gid_t egid;
+ char login_buffer[LOGIN_NAME_MAX];
+
+ pid_t pgrp; /* process group id */
+} rtems_user_env_t;
+
+extern rtems_user_env_t * rtems_current_user_env;
+extern rtems_user_env_t rtems_global_user_env;
+
+#define rtems_filesystem_current (rtems_current_user_env->current_directory)
+#define rtems_filesystem_root (rtems_current_user_env->root_directory)
+#define rtems_filesystem_link_counts (rtems_current_user_env->link_counts)
+#define rtems_filesystem_umask (rtems_current_user_env->umask)
+
+#define _POSIX_types_Uid (rtems_current_user_env->uid)
+#define _POSIX_types_Gid (rtems_current_user_env->gid)
+#define _POSIX_types_Euid (rtems_current_user_env->euid)
+#define _POSIX_types_Egid (rtems_current_user_env->egid)
+#define _POSIX_types_Getlogin_buffer (rtems_current_user_env->login_buffer)
+
+
+/*
+ * Instantiate a private copy of the per user information for the calling task.
+ */
+
+rtems_status_code rtems_libio_set_private_env(void);
+rtems_status_code rtems_libio_share_private_env(rtems_id task_id) ;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/itron/.cvsignore b/cpukit/itron/.cvsignore
new file mode 100644
index 0000000000..282522db03
--- /dev/null
+++ b/cpukit/itron/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/cpukit/itron/Makefile.am b/cpukit/itron/Makefile.am
new file mode 100644
index 0000000000..cdcf7797e1
--- /dev/null
+++ b/cpukit/itron/Makefile.am
@@ -0,0 +1,370 @@
+##
+## $Id$
+##
+
+include $(top_srcdir)/automake/multilib.am
+include $(top_srcdir)/automake/compile.am
+
+EXTRA_DIST =
+CLEANFILES =
+
+if HAS_ITRON
+## include
+
+include_rtemsdir = $(includedir)/rtems
+include_rtems_HEADERS = include/itron.h
+
+## itronsys
+
+include_itronsysdir = $(includedir)/itronsys
+
+include_itronsys_HEADERS = include/itronsys/eventflags.h \
+ include/itronsys/fmempool.h include/itronsys/intr.h \
+ include/itronsys/mbox.h include/itronsys/msgbuffer.h \
+ include/itronsys/network.h include/itronsys/port.h \
+ include/itronsys/semaphore.h include/itronsys/status.h \
+ include/itronsys/sysmgmt.h include/itronsys/task.h \
+ include/itronsys/time.h include/itronsys/types.h \
+ include/itronsys/vmempool.h
+
+EXTRA_DIST += include/itronsys/README
+
+## rtems/itron
+include_rtems_itrondir = $(includedir)/rtems/itron
+
+include_rtems_itron_HEADERS = include/rtems/itron/config.h \
+ include/rtems/itron/eventflags.h include/rtems/itron/fmempool.h \
+ include/rtems/itron/intr.h include/rtems/itron/itronapi.h \
+ include/rtems/itron/mbox.h include/rtems/itron/msgbuffer.h \
+ include/rtems/itron/network.h include/rtems/itron/object.h \
+ include/rtems/itron/port.h include/rtems/itron/semaphore.h \
+ include/rtems/itron/sysmgmt.h include/rtems/itron/task.h \
+ include/rtems/itron/time.h include/rtems/itron/vmempool.h
+
+EXTRA_DIST += include/rtems/itron/README
+
+## Inline
+
+if INLINE
+include_rtems_itron_HEADERS += inline/rtems/itron/eventflags.inl \
+ inline/rtems/itron/fmempool.inl inline/rtems/itron/intr.inl \
+ inline/rtems/itron/mbox.inl inline/rtems/itron/msgbuffer.inl \
+ inline/rtems/itron/network.inl inline/rtems/itron/port.inl \
+ inline/rtems/itron/semaphore.inl inline/rtems/itron/sysmgmt.inl \
+ inline/rtems/itron/task.inl inline/rtems/itron/time.inl \
+ inline/rtems/itron/vmempool.inl
+else
+include_rtems_itron_HEADERS += macros/rtems/itron/eventflags.inl \
+ macros/rtems/itron/fmempool.inl macros/rtems/itron/intr.inl \
+ macros/rtems/itron/mbox.inl macros/rtems/itron/msgbuffer.inl \
+ macros/rtems/itron/network.inl macros/rtems/itron/port.inl \
+ macros/rtems/itron/semaphore.inl macros/rtems/itron/sysmgmt.inl \
+ macros/rtems/itron/task.inl macros/rtems/itron/time.inl \
+ macros/rtems/itron/vmempool.inl
+endif
+
+## Sources
+
+TASK_C_FILES = src/task.c src/cre_tsk.c src/del_tsk.c src/sta_tsk.c \
+ src/ext_tsk.c src/exd_tsk.c src/ter_tsk.c src/dis_dsp.c src/ena_dsp.c \
+ src/chg_pri.c src/rot_rdq.c src/rel_wai.c src/get_tid.c src/ref_tsk.c
+
+TASKSYNC_C_FILES = src/sus_tsk.c src/rsm_tsk.c src/frsm_tsk.c src/slp_tsk.c \
+ src/tslp_tsk.c src/wup_tsk.c src/can_wup.c
+
+SEMAPHORE_C_FILES = src/itronsem.c src/cre_sem.c src/del_sem.c \
+ src/preq_sem.c src/ref_sem.c src/sig_sem.c src/twai_sem.c src/wai_sem.c
+
+EVENTFLAGS_C_FILES = src/eventflags.c
+
+MAILBOX_C_FILES = src/mbox.c
+
+MSGBUFFER_C_FILES = src/msgbuffer.c src/msgbuffertranslatereturncode.c \
+ src/cre_mbf.c src/del_mbf.c src/prcv_mbf.c src/psnd_mbf.c src/rcv_mbf.c \
+ src/ref_mbf.c src/snd_mbf.c src/trcv_mbf.c src/tsnd_mbf.c
+
+RENDEZVOUS_C_FILES = src/port.c
+
+INTERRUPT_C_FILES = src/itronintr.c
+
+VARIABLE_MEMORY_POOL_C_FILES = src/vmempool.c
+
+FIXED_MEMORY_POOL_C_FILES = src/fmempool.c
+
+TIME_C_FILES = src/itrontime.c
+
+CONFIGURATION_C_FILES = src/sysmgmt.c
+
+NETWORK_C_FILES = src/network.c
+
+C_FILES = $(TASK_C_FILES) $(TASKSYNC_C_FILES) $(SEMAPHORE_C_FILES) \
+ $(EVENTFLAGS_C_FILES) $(MAILBOX_C_FILES) $(MSGBUFFER_C_FILES) \
+ $(RENDEZVOUS_C_FILES) $(INTERRUPT_C_FILES) \
+ $(VARIABLE_MEMORY_POOL_C_FILES) $(FIXED_MEMORY_POOL_C_FILES) \
+ $(TIME_C_FILES)
+
+AM_CPPFLAGS += -I$(top_builddir)
+AM_CPPFLAGS += -D__RTEMS_INSIDE__
+
+EXTRA_LIBRARIES = libitron.a
+CLEANFILES += libitron.a
+libitron_a_SOURCES = $(C_FILES)
+libitron_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libitron_g.a
+CLEANFILES += libitron_g.a
+libitron_g_a_SOURCES = $(libitron_a_SOURCES)
+libitron_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+all-local: $(PREINSTALL_FILES) libitron$(LIB_VARIANT).a
+endif
+
+UNUSED_C_FILES = src/cre_mbx.c src/del_mbx.c src/mboxtranslatereturncode.c \
+ $(NETWORK_C_FILES) src/prcv_mbx.c src/rcv_mbx.c src/ref_mbx.c \
+ src/snd_mbx.c $(CONFIGURATION_C_FILES) src/trcv_mbx.c
+
+EXTRA_DIST += $(UNUSED_C_FILES) src/TODO
+
+PREINSTALL_DIRS =
+PREINSTALL_FILES =
+
+if HAS_ITRON
+$(PROJECT_INCLUDE)/rtems/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems
+ @: > $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/itron.h: include/itron.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron.h
+
+$(PROJECT_INCLUDE)/itronsys/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/itronsys
+ @: > $(PROJECT_INCLUDE)/itronsys/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/itronsys/$(dirstamp)
+
+$(PROJECT_INCLUDE)/itronsys/eventflags.h: include/itronsys/eventflags.h $(PROJECT_INCLUDE)/itronsys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/itronsys/eventflags.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/itronsys/eventflags.h
+
+$(PROJECT_INCLUDE)/itronsys/fmempool.h: include/itronsys/fmempool.h $(PROJECT_INCLUDE)/itronsys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/itronsys/fmempool.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/itronsys/fmempool.h
+
+$(PROJECT_INCLUDE)/itronsys/intr.h: include/itronsys/intr.h $(PROJECT_INCLUDE)/itronsys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/itronsys/intr.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/itronsys/intr.h
+
+$(PROJECT_INCLUDE)/itronsys/mbox.h: include/itronsys/mbox.h $(PROJECT_INCLUDE)/itronsys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/itronsys/mbox.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/itronsys/mbox.h
+
+$(PROJECT_INCLUDE)/itronsys/msgbuffer.h: include/itronsys/msgbuffer.h $(PROJECT_INCLUDE)/itronsys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/itronsys/msgbuffer.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/itronsys/msgbuffer.h
+
+$(PROJECT_INCLUDE)/itronsys/network.h: include/itronsys/network.h $(PROJECT_INCLUDE)/itronsys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/itronsys/network.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/itronsys/network.h
+
+$(PROJECT_INCLUDE)/itronsys/port.h: include/itronsys/port.h $(PROJECT_INCLUDE)/itronsys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/itronsys/port.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/itronsys/port.h
+
+$(PROJECT_INCLUDE)/itronsys/semaphore.h: include/itronsys/semaphore.h $(PROJECT_INCLUDE)/itronsys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/itronsys/semaphore.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/itronsys/semaphore.h
+
+$(PROJECT_INCLUDE)/itronsys/status.h: include/itronsys/status.h $(PROJECT_INCLUDE)/itronsys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/itronsys/status.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/itronsys/status.h
+
+$(PROJECT_INCLUDE)/itronsys/sysmgmt.h: include/itronsys/sysmgmt.h $(PROJECT_INCLUDE)/itronsys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/itronsys/sysmgmt.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/itronsys/sysmgmt.h
+
+$(PROJECT_INCLUDE)/itronsys/task.h: include/itronsys/task.h $(PROJECT_INCLUDE)/itronsys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/itronsys/task.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/itronsys/task.h
+
+$(PROJECT_INCLUDE)/itronsys/time.h: include/itronsys/time.h $(PROJECT_INCLUDE)/itronsys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/itronsys/time.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/itronsys/time.h
+
+$(PROJECT_INCLUDE)/itronsys/types.h: include/itronsys/types.h $(PROJECT_INCLUDE)/itronsys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/itronsys/types.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/itronsys/types.h
+
+$(PROJECT_INCLUDE)/itronsys/vmempool.h: include/itronsys/vmempool.h $(PROJECT_INCLUDE)/itronsys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/itronsys/vmempool.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/itronsys/vmempool.h
+
+$(PROJECT_INCLUDE)/rtems/itron/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems/itron
+ @: > $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/itron/config.h: include/rtems/itron/config.h $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/config.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/config.h
+
+$(PROJECT_INCLUDE)/rtems/itron/eventflags.h: include/rtems/itron/eventflags.h $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/eventflags.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/eventflags.h
+
+$(PROJECT_INCLUDE)/rtems/itron/fmempool.h: include/rtems/itron/fmempool.h $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/fmempool.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/fmempool.h
+
+$(PROJECT_INCLUDE)/rtems/itron/intr.h: include/rtems/itron/intr.h $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/intr.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/intr.h
+
+$(PROJECT_INCLUDE)/rtems/itron/itronapi.h: include/rtems/itron/itronapi.h $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/itronapi.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/itronapi.h
+
+$(PROJECT_INCLUDE)/rtems/itron/mbox.h: include/rtems/itron/mbox.h $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/mbox.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/mbox.h
+
+$(PROJECT_INCLUDE)/rtems/itron/msgbuffer.h: include/rtems/itron/msgbuffer.h $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/msgbuffer.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/msgbuffer.h
+
+$(PROJECT_INCLUDE)/rtems/itron/network.h: include/rtems/itron/network.h $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/network.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/network.h
+
+$(PROJECT_INCLUDE)/rtems/itron/object.h: include/rtems/itron/object.h $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/object.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/object.h
+
+$(PROJECT_INCLUDE)/rtems/itron/port.h: include/rtems/itron/port.h $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/port.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/port.h
+
+$(PROJECT_INCLUDE)/rtems/itron/semaphore.h: include/rtems/itron/semaphore.h $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/semaphore.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/semaphore.h
+
+$(PROJECT_INCLUDE)/rtems/itron/sysmgmt.h: include/rtems/itron/sysmgmt.h $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/sysmgmt.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/sysmgmt.h
+
+$(PROJECT_INCLUDE)/rtems/itron/task.h: include/rtems/itron/task.h $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/task.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/task.h
+
+$(PROJECT_INCLUDE)/rtems/itron/time.h: include/rtems/itron/time.h $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/time.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/time.h
+
+$(PROJECT_INCLUDE)/rtems/itron/vmempool.h: include/rtems/itron/vmempool.h $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/vmempool.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/vmempool.h
+
+if INLINE
+$(PROJECT_INCLUDE)/rtems/itron/eventflags.inl: inline/rtems/itron/eventflags.inl $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/eventflags.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/eventflags.inl
+
+$(PROJECT_INCLUDE)/rtems/itron/fmempool.inl: inline/rtems/itron/fmempool.inl $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/fmempool.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/fmempool.inl
+
+$(PROJECT_INCLUDE)/rtems/itron/intr.inl: inline/rtems/itron/intr.inl $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/intr.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/intr.inl
+
+$(PROJECT_INCLUDE)/rtems/itron/mbox.inl: inline/rtems/itron/mbox.inl $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/mbox.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/mbox.inl
+
+$(PROJECT_INCLUDE)/rtems/itron/msgbuffer.inl: inline/rtems/itron/msgbuffer.inl $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/msgbuffer.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/msgbuffer.inl
+
+$(PROJECT_INCLUDE)/rtems/itron/network.inl: inline/rtems/itron/network.inl $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/network.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/network.inl
+
+$(PROJECT_INCLUDE)/rtems/itron/port.inl: inline/rtems/itron/port.inl $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/port.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/port.inl
+
+$(PROJECT_INCLUDE)/rtems/itron/semaphore.inl: inline/rtems/itron/semaphore.inl $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/semaphore.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/semaphore.inl
+
+$(PROJECT_INCLUDE)/rtems/itron/sysmgmt.inl: inline/rtems/itron/sysmgmt.inl $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/sysmgmt.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/sysmgmt.inl
+
+$(PROJECT_INCLUDE)/rtems/itron/task.inl: inline/rtems/itron/task.inl $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/task.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/task.inl
+
+$(PROJECT_INCLUDE)/rtems/itron/time.inl: inline/rtems/itron/time.inl $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/time.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/time.inl
+
+$(PROJECT_INCLUDE)/rtems/itron/vmempool.inl: inline/rtems/itron/vmempool.inl $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/vmempool.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/vmempool.inl
+
+else
+$(PROJECT_INCLUDE)/rtems/itron/eventflags.inl: macros/rtems/itron/eventflags.inl $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/eventflags.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/eventflags.inl
+
+$(PROJECT_INCLUDE)/rtems/itron/fmempool.inl: macros/rtems/itron/fmempool.inl $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/fmempool.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/fmempool.inl
+
+$(PROJECT_INCLUDE)/rtems/itron/intr.inl: macros/rtems/itron/intr.inl $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/intr.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/intr.inl
+
+$(PROJECT_INCLUDE)/rtems/itron/mbox.inl: macros/rtems/itron/mbox.inl $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/mbox.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/mbox.inl
+
+$(PROJECT_INCLUDE)/rtems/itron/msgbuffer.inl: macros/rtems/itron/msgbuffer.inl $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/msgbuffer.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/msgbuffer.inl
+
+$(PROJECT_INCLUDE)/rtems/itron/network.inl: macros/rtems/itron/network.inl $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/network.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/network.inl
+
+$(PROJECT_INCLUDE)/rtems/itron/port.inl: macros/rtems/itron/port.inl $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/port.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/port.inl
+
+$(PROJECT_INCLUDE)/rtems/itron/semaphore.inl: macros/rtems/itron/semaphore.inl $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/semaphore.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/semaphore.inl
+
+$(PROJECT_INCLUDE)/rtems/itron/sysmgmt.inl: macros/rtems/itron/sysmgmt.inl $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/sysmgmt.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/sysmgmt.inl
+
+$(PROJECT_INCLUDE)/rtems/itron/task.inl: macros/rtems/itron/task.inl $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/task.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/task.inl
+
+$(PROJECT_INCLUDE)/rtems/itron/time.inl: macros/rtems/itron/time.inl $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/time.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/time.inl
+
+$(PROJECT_INCLUDE)/rtems/itron/vmempool.inl: macros/rtems/itron/vmempool.inl $(PROJECT_INCLUDE)/rtems/itron/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/itron/vmempool.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/itron/vmempool.inl
+endif
+endif
+
+CLEANFILES += $(PREINSTALL_FILES)
+DISTCLEANFILES = $(PREINSTALL_DIRS)
+
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/itron/include/itron.h b/cpukit/itron/include/itron.h
new file mode 100644
index 0000000000..af43e6f719
--- /dev/null
+++ b/cpukit/itron/include/itron.h
@@ -0,0 +1,51 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_h_
+#define __ITRON_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Include the basic requirements
+ */
+
+#include <rtems/system.h> /* basic RTEMS types defined by */
+ /* each port */
+#include <itronsys/types.h> /* define all the TRON types */
+ /* in terms of the RTEMS base types */
+#include <itronsys/status.h> /* define all ITRON status codes */
+
+/*
+ * Now include the per manager include files
+ */
+
+#include <itronsys/eventflags.h>
+#include <itronsys/fmempool.h>
+#include <itronsys/intr.h>
+#include <itronsys/mbox.h>
+#include <itronsys/msgbuffer.h>
+#include <itronsys/sysmgmt.h> /* network depends on this file */
+#include <itronsys/network.h>
+#include <itronsys/port.h>
+#include <itronsys/semaphore.h>
+#include <itronsys/task.h>
+#include <itronsys/time.h>
+#include <itronsys/vmempool.h>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/itron/include/itronsys/README b/cpukit/itron/include/itronsys/README
new file mode 100644
index 0000000000..8191ad3c5f
--- /dev/null
+++ b/cpukit/itron/include/itronsys/README
@@ -0,0 +1,9 @@
+#
+# $Id$
+#
+
+This directory contains the public interface of each manager.
+Each file in this directory is included from <itron.h>.
+
+The private header file for each ITRON manager is in
+../rtems/itron. \ No newline at end of file
diff --git a/cpukit/itron/include/itronsys/eventflags.h b/cpukit/itron/include/itronsys/eventflags.h
new file mode 100644
index 0000000000..165a3763e5
--- /dev/null
+++ b/cpukit/itron/include/itronsys/eventflags.h
@@ -0,0 +1,145 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_EVENTFLAGS_h_
+#define __ITRON_EVENTFLAGS_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Create Eventflags (cre_flg) Structure
+ */
+
+typedef struct t_cflg {
+ VP exinf; /* extended information */
+ ATR flgatr; /* eventflag attribute */
+ UINT iflgptn; /* initial eventflag */
+ /* additional information may be included depending on the implementation */
+} T_CFLG;
+
+/*
+ * flgatr
+ */
+
+#define TA_WSGL 0x00 /* multiple tasks are not allowed to wait (Wait
+ Single Task) */
+#define TA_WMUL 0x08 /* multiple tasks are allowed to wait (Wait
+ Multiple Task) */
+
+/*
+ * wfmode
+ */
+
+#define TWF_ANDW 0x00 /* AND wait */
+#define TWF_ORW 0x02 /* OR wait */
+#define TWF_CLR 0x01 /* clear specification */
+
+/*
+ * Reference Eventflags (ref_flg) Structure
+ */
+
+typedef struct t_rflg {
+ VP exinf; /* extended information */
+ BOOL_ID wtsk; /* indicates whether or not there is a waiting task */
+ UINT flgptn; /* eventflag bit pattern */
+ /* additional information may be included depending on the implementation */
+} T_RFLG;
+
+/*
+ * Eventflag Functions
+ */
+
+/*
+ * cre_flg - Create Eventflag
+ */
+
+ER cre_flg(
+ ID flgid,
+ T_CFLG *pk_cflg
+);
+
+/*
+ * del_flg - Delete Eventflag
+ */
+
+ER del_flg(
+ ID flgid
+);
+
+/*
+ * set_flg - Set Eventflag
+ */
+
+ER set_flg(
+ ID flgid,
+ UINT setptn
+);
+
+/*
+ * clr_flg - Clear Eventflag
+ */
+
+ER clr_flg(
+ ID flgid,
+ UINT clrptn
+);
+
+/*
+ * wai_flg - Wait on Eventflag
+ */
+
+ER wai_flg(
+ UINT *p_flgptn,
+ ID flgid,
+ UINT waiptn,
+ UINT wfmode
+);
+
+/*
+ * pol_flg - Wait for Eventflag(Polling)
+ */
+
+ER pol_flg(
+ UINT *p_flgptn,
+ ID flgid,
+ UINT waiptn,
+ UINT wfmode
+);
+
+/*
+ * twai_flg - Wait on Eventflag with Timeout
+ */
+
+ER twai_flg(
+ UINT *p_flgptn,
+ ID flgid,
+ UINT waiptn,
+ UINT wfmode,
+ TMO tmout
+);
+
+/*
+ * ref_flg - Reference Eventflag Status
+ */
+
+ER ref_flg(
+ T_RFLG *pk_rflg,
+ ID flgid
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/itron/include/itronsys/fmempool.h b/cpukit/itron/include/itronsys/fmempool.h
new file mode 100644
index 0000000000..bbf74f9b13
--- /dev/null
+++ b/cpukit/itron/include/itronsys/fmempool.h
@@ -0,0 +1,124 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_FIXED_MEMORYPOOL_h_
+#define __ITRON_FIXED_MEMORYPOOL_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Create Fixed Memory Pool (cre_mpf) Structure
+ */
+
+ /* cre_mpf */
+typedef struct t_cmpf {
+ VP exinf; /* extended information */
+ ATR mpfatr; /* memorypool attributes */
+ INT mpfcnt; /* block count for entire memorypool */
+ INT blfsz; /* fixed-size memory block size */
+ /* additional information may be included depending on the implementation */
+} T_CMPF;
+
+/*
+ * mpfatr
+ */
+
+#define TA_TFIFO 0x00 /* waiting tasks are handled by FIFO */
+#define TA_TPRI 0x01 /* waiting tasks are handled by priority */
+
+
+/*
+ * Reference Fixed Memory Pool (ref_mpf) Structure
+ */
+
+ /* ref_mpf */
+typedef struct t_rmpf {
+ VP exinf; /* extended information */
+ BOOL_ID wtsk; /* indicates whether or not there are waiting tasks */
+ INT frbcnt; /* free block count */
+ /* additional information may be included depending on the implementation */
+} T_RMPF;
+
+/*
+ * Fixed Memory Pool Functions
+ */
+
+/*
+ * cre_mpf - Create Fixed-Size Memorypool
+ */
+
+ER cre_mpf(
+ ID mpfid,
+ T_CMPF *pk_cmpf
+);
+
+/*
+ * del_mpf - Delete Fixed-Size Memorypool
+ */
+
+ER del_mpf(
+ ID mpfid
+);
+
+/*
+ * get_blf - Get Fixed-Size Memory Block
+ */
+
+ER get_blf(
+ VP *p_blf,
+ ID mpfid
+);
+
+/*
+ * pget_blf - Poll and Get Fixed-Size Memory Block
+ */
+
+ER pget_blf(
+ VP *p_blf,
+ ID mpfid
+);
+
+/*
+ * tget_blf - Get Fixed-Size Memory Block with Timeout
+ */
+
+ER tget_blf(
+ VP *p_blf,
+ ID mpfid,
+ TMO tmout
+);
+
+/*
+ * rel_blf - Release Fixed-Size Memory Block
+ */
+
+ER rel_blf(
+ ID mpfid,
+ VP blf
+);
+
+/*
+ * ref_mpf - Reference Fixed-Size Memorypool Status
+ */
+
+ER ref_mpf(
+ T_RMPF *pk_rmpf,
+ ID mpfid
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/itron/include/itronsys/intr.h b/cpukit/itron/include/itronsys/intr.h
new file mode 100644
index 0000000000..ca03ec54d7
--- /dev/null
+++ b/cpukit/itron/include/itronsys/intr.h
@@ -0,0 +1,105 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_INTERRUPT_h_
+#define __ITRON_INTERRUPT_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Define Interrupt (def_int) Structure
+ */
+
+typedef struct t_dint {
+ ATR intatr; /* interrupt handler attributes */
+ FP inthdr; /* interrupt handler address */
+ /* additional information may be included depending on the implementation */
+} T_DINT;
+
+/*
+ * Interrupt Functions
+ */
+
+/*
+ * def_int - Define Interrupt Handler
+ */
+
+ER def_int(
+ UINT dintno,
+ T_DINT *pk_dint
+);
+
+/*
+ * ret_int - Return from Interrupt Handler
+ */
+
+void ret_int( void );
+
+/*
+ * ret_wup - Return and Wakeup Task
+ */
+
+void ret_wup(
+ ID tskid
+);
+
+/*
+ * loc_cpu - Lock CPU
+ */
+
+ER loc_cpu( void );
+
+/*
+ * unl_cpu - Unlock CPU
+ */
+
+ER unl_cpu( void );
+
+/*
+ * dis_int - Disable Interrupt
+ */
+
+ER dis_int(
+ UINT eintno
+);
+
+/*
+ * ena_int - Enable Interrupt
+ */
+
+ER ena_int(
+ UINT eintno
+);
+
+/*
+ * chg_iXX - Change Interrupt Mask(Level or Priority)
+ */
+
+ER chg_iXX(
+ UINT iXXXX
+);
+
+/*
+ * ref_iXX - Reference Interrupt Mask(Level or Priority)
+ */
+
+ER ref_iXX(
+ UINT *p_iXXXX
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/itron/include/itronsys/mbox.h b/cpukit/itron/include/itronsys/mbox.h
new file mode 100644
index 0000000000..c65e156832
--- /dev/null
+++ b/cpukit/itron/include/itronsys/mbox.h
@@ -0,0 +1,137 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_MBOX_h_
+#define __ITRON_MBOX_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Create Mailbox (cre_mbx) Structure
+ */
+
+typedef struct t_cmbx {
+ VP exinf; /* extended information */
+ ATR mbxatr; /* mailbox attributes */
+ /* Following is implementation-dependent function */
+ INT bufcnt; /* maximum number of messages to let pend */
+ /* additional information may be included depending on the implementation */
+} T_CMBX;
+
+/*
+ * mbxatr
+ */
+
+#define TA_TFIFO 0x00 /* waiting tasks are handled by FIFO */
+#define TA_TPRI 0x01 /* waiting tasks are handled by priority */
+#define TA_MFIFO 0x00 /* messages are handled by FIFO */
+#define TA_MPRI 0x02 /* messages are handled by priority */
+
+typedef struct t_msg {
+ /*
+ * A region (header) reserved by the OS may be included first
+ * depending on the implementation.
+ *
+ * NOTE: The first two fields are RTEMS specific.
+ */
+
+ INT msgpri; /* priority of each message */
+ /* VB msgcont[]; XXX */
+ uint8_t msgcont[1];
+} T_MSG;
+
+/*
+ * Reference Mailbox (ref_mbx) Structure
+ */
+
+typedef struct t_rmbx {
+ VP exinf; /* extended information */
+ BOOL_ID wtsk; /* indicates whether or not there is a waiting task */
+ T_MSG *pk_msg; /* message to be sent next */
+ /* additional information may be included depending on the implementation */
+} T_RMBX;
+
+/*
+ * Mailbox Functions
+ */
+
+/*
+ * cre_mbx - Create Mailbox
+ */
+
+ER cre_mbx(
+ ID mbxid,
+ T_CMBX *pk_cmbx
+);
+
+/*
+ * del_mbx - Delete Mailbox
+ */
+
+ER del_mbx(
+ ID mbxid
+);
+
+/*
+ * snd_msg - Send Message to Mailbox
+ */
+
+ER snd_msg(
+ ID mbxid,
+ T_MSG *pk_msg
+);
+
+/*
+ * rcv_msg - Receive Message from Mailbox
+ */
+
+ER rcv_msg(
+ T_MSG **ppk_msg,
+ ID mbxid
+);
+
+/*
+ * prcv_msg - Poll and Receive Message from Mailbox
+ */
+
+ER prcv_msg(
+ T_MSG **ppk_msg,
+ ID mbxid
+);
+
+/*
+ * trcv_msg - Receive Message from Mailbox with Timeout
+ */
+
+ER trcv_msg(
+ T_MSG **ppk_msg,
+ ID mbxid,
+ TMO tmout
+);
+
+/*
+ * ref_mbx - Reference Mailbox Status
+ */
+
+ER ref_mbx(
+ T_RMBX *pk_rmbx,
+ ID mbxid
+);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/itron/include/itronsys/msgbuffer.h b/cpukit/itron/include/itronsys/msgbuffer.h
new file mode 100644
index 0000000000..bac82de649
--- /dev/null
+++ b/cpukit/itron/include/itronsys/msgbuffer.h
@@ -0,0 +1,159 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_MESSAGEBUFFER_h_
+#define __ITRON_MESSAGEBUFFER_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Create Message Buffer (cre_mbf) Structure
+ */
+
+typedef struct t_cmbf {
+ VP exinf; /* extended information */
+ ATR mbfatr; /* messagebuffer attributes */
+ INT bufsz; /* messagebuffer size */
+ INT maxmsz; /* maximum size of messages */
+ /* additional information may be included depending on the implementation */
+} T_CMBF;
+
+/*
+ * mbfatr
+ */
+
+#define TA_TFIFO 0x00 /* tasks waiting to receive messages are handled
+ by FIFO */
+#define TA_TPRI 0x01 /* tasks waiting to receive messages are handled
+ by priority */
+
+/*
+ * mbfid
+ */
+
+#define TMBF_OS (-4) /* messagebuffer used for OS error log */
+#define TMBF_DB (-3) /* messagebuffer used for debugging */
+
+/*
+ * Reference Message Buffer (ref_mbf) Structure
+ */
+
+typedef struct t_rmbf {
+ VP exinf; /* extended information */
+ BOOL_ID wtsk; /* indicates whether or not there is a */
+ /* task waiting to receive a message */
+ BOOL_ID stsk; /* indicates whether or not there is a */
+ /* task waiting to send a message */
+ INT msgsz; /* size of message to be sent next */
+ INT frbufsz; /* size of free buffer */
+ /* additional information may be included depending on the implementation */
+} T_RMBF;
+
+/*
+ * Message Buffer Functions
+ */
+
+/*
+ * cre_mbf - Create MessageBuffer
+ */
+
+ER cre_mbf(
+ ID mbfid,
+ T_CMBF *pk_cmbf
+);
+
+/*
+ * del_mbf - Delete MessageBuffer
+ */
+
+ER del_mbf(
+ ID mbfid
+);
+
+/*
+ * snd_mbf - Send Message to MessageBuffer
+ */
+
+ER snd_mbf(
+ ID mbfid,
+ VP msg,
+ INT msgsz
+);
+
+/*
+ * psnd_mbf - Poll and Send Message to MessageBuffer
+ */
+
+ER psnd_mbf(
+ ID mbfid,
+ VP msg,
+ INT msgsz
+);
+
+/*
+ * tsnd_mbf - Send Message to MessageBuffer with Timeout
+ */
+
+ER tsnd_mbf(
+ ID mbfid,
+ VP msg,
+ INT msgsz,
+ TMO tmout
+);
+
+/*
+ * rcv_mbf - Receive Message from MessageBuffer
+ */
+
+ER rcv_mbf(
+ VP msg,
+ INT *p_msgsz,
+ ID mbfid
+);
+
+/*
+ * prcv_mbf - Poll and Receive Message from MessageBuffer
+ */
+
+ER prcv_mbf(
+ VP msg,
+ INT *p_msgsz,
+ ID mbfid
+);
+
+/*
+ * trcv_mbf - Receive Message from MessageBuffer with Timeout
+ */
+
+ER trcv_mbf(
+ VP msg,
+ INT *p_msgsz,
+ ID mbfid,
+ TMO tmout
+);
+
+/*
+ * ref_mbf - Reference MessageBuffer Status
+ */
+
+ER ref_mbf(
+ T_RMBF *pk_rmbf,
+ ID mbfid
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/itron/include/itronsys/network.h b/cpukit/itron/include/itronsys/network.h
new file mode 100644
index 0000000000..88d8d4e4d7
--- /dev/null
+++ b/cpukit/itron/include/itronsys/network.h
@@ -0,0 +1,77 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_NETWORK_h_
+#define __ITRON_NETWORK_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * NODE srcnode, dstnode, nod:
+ */
+
+#define TND_SELF 0 /* specifies the local node */
+#define TND_OTHR (-1) /* specifies default remote node */
+
+/*
+ * Network Functions
+ */
+
+/*
+ * nrea_dat - Read Data from another Node
+ */
+
+ER nrea_dat(
+ INT *p_reasz,
+ VP dstadr,
+ NODE srcnode,
+ VP srcadr,
+ INT datsz
+);
+
+/*
+ * nwri_dat - Write Data to another Node
+ */
+
+ER nwri_dat(
+ INT *p_wrisz,
+ NODE dstnode,
+ VP dstadr,
+ VP srcadr,
+ INT datsz
+);
+
+/*
+ * nget_nod - Get Local Node Number
+ */
+
+ER nget_nod(
+ NODE *p_node
+);
+
+/*
+ * nget_ver - Get Version Information of another Node
+ */
+
+ER nget_ver(
+ T_VER *pk_ver,
+ NODE node
+);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/itron/include/itronsys/port.h b/cpukit/itron/include/itronsys/port.h
new file mode 100644
index 0000000000..1bbff13bec
--- /dev/null
+++ b/cpukit/itron/include/itronsys/port.h
@@ -0,0 +1,189 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_PORT_h_
+#define __ITRON_PORT_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Create Port (cre_por) Structure
+ */
+
+typedef struct t_cpor {
+ VP exinf; /* extended information */
+ ATR poratr; /* port attributes */
+ INT maxcmsz; /* maximum call message size */
+ INT maxrmsz; /* maximum reply message size */
+ /* additional information may be included depending on the implementation */
+} T_CPOR;
+
+/*
+ * poratr
+ */
+
+#define TA_NULL 0 /* specifies no particular attributes */
+
+/*
+ * TA_NULL should be used in place of zeroes to turn off all
+ * attribute features.
+ */
+
+/*
+ * Reference Port (ref_por) Structure
+ */
+
+typedef struct t_rpor {
+ VP exinf; /* extended information */
+ BOOL_ID wtsk; /* indicates whether or not there is a task */
+ /* waiting to call a rendezvous */
+ BOOL_ID atsk; /* indicates whether or not there is a task */
+ /* waiting to accept a rendezvous */
+ /* additional information may be included depending on the implementation */
+} T_RPOR;
+
+/*
+ * Port Functions
+ */
+
+/*
+ * cre_por - Create Port for Rendezvous
+ */
+
+ER cre_por(
+ ID porid,
+ T_CPOR *pk_cpor
+);
+
+/*
+ * del_por - Delete Port for Rendezvous
+ */
+
+ER del_por(
+ ID porid
+);
+
+/*
+ * cal_por - Call Port for Rendezvous Poll
+ */
+
+ER cal_por(
+ VP msg,
+ INT *p_rmsgsz,
+ ID porid,
+ UINT calptn,
+ INT cmsgsz
+);
+
+/*
+ * pcal_por - Poll and Call Port for Rendezvous
+ */
+
+ER pcal_por(
+ VP msg,
+ INT *p_rmsgsz,
+ ID porid,
+ UINT calptn,
+ INT cmsgsz
+);
+
+/*
+ * tcal_por - Call Port for Rendezvous with Timeout
+ */
+
+ER tcal_por(
+ VP msg,
+ INT *p_rmsgsz,
+ ID porid,
+ UINT calptn,
+ INT cmsgsz,
+ TMO tmout
+);
+
+/*
+ * acp_por - Accept Port for Rendezvous Poll
+ */
+
+ER acp_por(
+ RNO *p_rdvno,
+ VP msg,
+ INT *p_cmsgsz,
+ ID porid,
+ UINT acpptn
+);
+
+/*
+ * pacp_por - Poll and Accept Port for Rendezvous
+ */
+
+ER pacp_por(
+ RNO *p_rdvno,
+ VP msg,
+ INT *p_cmsgsz,
+ ID porid,
+ UINT acpptn
+);
+
+/*
+ * tacp_por - Accept Port for Rendezvous with Timeout
+ */
+
+ER tacp_por(
+ RNO *p_rdvno,
+ VP msg,
+ INT *p_cmsgsz,
+ ID porid,
+ UINT acpptn,
+ TMO tmout
+);
+
+/*
+ * fwd_por - Forward Rendezvous to Other Port
+ */
+
+ER fwd_por(
+ ID porid,
+ UINT calptn,
+ RNO rdvno,
+ VP msg,
+ INT cmsgsz
+);
+
+/*
+ * rpl_rdv - Reply Rendezvous
+ */
+
+ER rpl_rdv(
+ RNO rdvno,
+ VP msg,
+ INT rmsgsz
+);
+
+/*
+ * ref_por - Reference Port Status
+ */
+
+ER ref_por(
+ T_RPOR *pk_rpor,
+ ID porid
+);
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/itron/include/itronsys/semaphore.h b/cpukit/itron/include/itronsys/semaphore.h
new file mode 100644
index 0000000000..1ee7c144f5
--- /dev/null
+++ b/cpukit/itron/include/itronsys/semaphore.h
@@ -0,0 +1,120 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_SEMAPHORE_h_
+#define __ITRON_SEMAPHORE_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Create Semaphore (cre_sem) Structure
+ */
+
+typedef struct t_csem {
+ VP exinf; /* extended information */
+ ATR sematr; /* semaphore attributes */
+ /* Following is the extended function for [level X]. */
+ INT isemcnt; /* initial semaphore count */
+ INT maxsem; /* maximum semaphore count */
+ /* additional information may be included depending on the implementation */
+} T_CSEM;
+
+/*
+ * sematr - Semaphore Attribute Values
+ */
+
+#define TA_TFIFO 0x00 /* waiting tasks are handled by FIFO */
+#define TA_TPRI 0x01 /* waiting tasks are handled by priority */
+
+#define _ITRON_SEMAPHORE_UNUSED_ATTRIBUTES ~(TA_TPRI)
+
+/*
+ * Reference Semaphore (ref_sem) Structure
+ */
+
+typedef struct t_rsem {
+ VP exinf; /* extended information */
+ BOOL_ID wtsk; /* indicates whether or not there is a waiting task */
+ INT semcnt; /* current semaphore count */
+ /* additional information may be included depending on the implementation */
+} T_RSEM;
+
+/*
+ * Semaphore Functions
+ */
+
+/*
+ * cre_sem - Create Semaphore
+ */
+
+ER cre_sem(
+ ID semid,
+ T_CSEM *pk_csem
+);
+
+/*
+ * del_sem - Delete Semaphore
+ */
+
+ER del_sem(
+ ID semid
+);
+
+/*
+ * sig_sem - Signal Semaphore
+ */
+
+ER sig_sem(
+ ID semid
+);
+
+/*
+ * wai_sem - Wait on Semaphore
+ */
+
+ER wai_sem(
+ ID semid
+);
+
+/*
+ * preq_sem - Poll and Request Semaphore
+ */
+
+ER preq_sem(
+ ID semid
+);
+
+/*
+ * twai_sem - Wait on Semaphore with Timeout
+ */
+
+ER twai_sem(
+ ID semid,
+ TMO tmout
+);
+
+/*
+ * ref_sem - Reference Semaphore Status
+ */
+
+ER ref_sem(
+ ID semid,
+ T_RSEM *pk_rsem
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/itron/include/itronsys/status.h b/cpukit/itron/include/itronsys/status.h
new file mode 100644
index 0000000000..4fab7a4994
--- /dev/null
+++ b/cpukit/itron/include/itronsys/status.h
@@ -0,0 +1,69 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_STATUS_h_
+#define __ITRON_STATUS_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define E_OK 0 /* Normal completion */
+#define E_SYS (-5) /* System error */
+#define E_NOMEM (-10) /* Insufficient memory */
+#define E_NOSPT (-17) /* Feature not supported */
+#define E_INOSPT (-18) /* Feature not supported by ITRON/FILE */
+ /* specification */
+#define E_RSFN (-20) /* Reserved function code number */
+#define E_RSATR (-24) /* Reserved attribute */
+#define E_PAR (-33) /* Parameter error */
+#define E_ID (-35) /* Invalid ID number */
+#define E_NOEXS (-52) /* Object does not exist */
+#define E_OBJ (-63) /* Invalid object state */
+#define E_MACV (-65) /* Memory access disabled or memory access */
+ /* violation */
+#define E_OACV (-66) /* Object access violation */
+#define E_CTX (-69) /* Context error */
+#define E_QOVR (-73) /* Queuing or nesting overflow */
+#define E_DLT (-81) /* Object being waited for was deleted */
+#define E_TMOUT (-85) /* Polling failure or timeout exceeded */
+#define E_RLWAI (-86) /* WAIT state was forcibly released */
+#define EN_NOND (-113) /* Target node does not exist or cannot be */
+ /* accessed */
+#define EN_OBJNO (-114) /* Specifies an object number which could not be */
+ /* accessed on the target node */
+#define EN_PROTO (-115) /* Protocol not supported on target node */
+#define EN_RSFN (-116) /* System call or function not supported on */
+ /* target node */
+#define EN_COMM (-117) /* No response from target node */
+#define EN_RLWAI (-118) /* Connection function response wait state was */
+ /* forcibly released */
+#define EN_PAR (-119) /* A value outside the range supported by the */
+ /* target node and/or transmission packet */
+ /* format was specified as a parameter */
+#define EN_RPAR (-120) /* A value outside the range supported by the */
+ /* issuing node and/or transmission packet */
+ /* format was returned as a return parameter */
+#define EN_CTXID (-121) /* An object on another node was specified to */
+ /* a system call issued from a task in dispatch */
+ /* disabled state or from a task-independent */
+ /* portion */
+#define EN_EXEC (-122) /* System call could not be executed due to */
+ /* insufficient resources on the target node */
+#define EN_NOSPT (-123) /* Connection function not supported */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/itron/include/itronsys/sysmgmt.h b/cpukit/itron/include/itronsys/sysmgmt.h
new file mode 100644
index 0000000000..5213a430d9
--- /dev/null
+++ b/cpukit/itron/include/itronsys/sysmgmt.h
@@ -0,0 +1,318 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_SYSTEM_MANAGEMENT_h_
+#define __ITRON_SYSTEM_MANAGEMENT_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Get Version (get_ver) Structure
+ */
+
+typedef struct t_ver {
+ UH maker; /* vendor */
+ UH id; /* format number */
+ UH spver; /* specification version */
+ UH prver; /* product version */
+ UH prno[4]; /* product control information */
+ UH cpu; /* CPU information */
+ UH var; /* variation descriptor */
+} T_VER;
+
+/*
+ * Specific MAKER codes established as of March, 1993 are as follows.
+ * Due to restrictions on the assignment of CPU codes described below, it is
+ * necessary to use maker codes in the range 0x000 through 0x00ff for vendors
+ * developing CPUs.
+ */
+
+/*
+ * CPU defines XXX need to name the constants
+ */
+
+#if 0
+#define 0x000 /* No version (test systems, etc.) */
+#define 0x001 /* University of Tokyo */
+#define 0x009 /* FUJITSU LIMITED */
+#define 0x00a /* Hitachi, Ltd. */
+#define 0x00b /* Matsushita Electric Industrial Co., Ltd. */
+#define 0x00c /* Mitsubishi Electric Corporation */
+#define 0x00d /* NEC Corporation */
+#define 0x00e /* Oki Electric Industry Co., Ltd. */
+#define 0x00f /* TOSHIBA CORPORATION */
+#endif
+
+/*
+ * The above have been assigned in alphabetical order.
+ */
+
+#if 0
+#define 0x010 /* ALPS ELECTRIC CO., LTD. */
+#define 0x011 /* WACOM Co., Ltd. */
+#define 0x012 /* Personal Media Corporation */
+#define 0x101 /* OMRON CORPORATION */
+#define 0x102 /* SEIKOSHA CO., LTD. */
+#define 0x103 /* SYSTEM ALGO CO., LTD. */
+#define 0x104 /* Tokyo Computer Service Co., Ltd. */
+#define 0x105 /* YAMAHA CORPORATION */
+#define 0x106 /* MORSON JAPAN */
+#define 0x107 /* TOSHIBA INFORMATION SYSTEMS (JAPAN) CORP. */
+#define 0x108 /* Miyazaki System Planning Office */
+#define 0x109 /* Three Ace Computer Corporation */
+#endif
+
+/*
+ * CPU Codes
+ *
+ * Figure 47 shows the format of cpu code. Some processors use the format
+ * given in Figure 47(1). The format given in Figure 47(2) is used for all
+ * other proprietary processors.
+ *
+ * The code assignment of the CPU1 region in the format given in Figure 47(1)
+ * is common to ITRON and BTRON specifications. The same number is used in
+ * the CPU type of the standard object format of BTRON specification
+ * operating systems implemented on a TRON-specification chip.
+ *
+ * When using the format given in Figure 47(2) the code used for MAKER1 is
+ * assigned by using the lower 8 bits of MAKER described in the previous
+ * subsection. The code assignment of CPU2 is left up to each maker.
+ *
+ *
+ *
+ * +---------------+---------------+---------------+---------------+
+ * (1) | 0 0 0 0 0 0 0 0 | CPU1 |
+ * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ * +---------------+---------------+---------------+---------------+
+ * (2) | MAKER1 | CPU2 |
+ * +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+ *
+ * Figure 47 Format of cpu Returned by get_ver
+ *
+ *
+ * Specific CPU codes established as of March, 1993 are as follows.
+ */
+
+#if 0
+/*
+ * XXX CONVERT THESE to #defines
+ */
+
+
+/*
+ * Contents of the CPU1 field
+ */
+
+#define (0x0) CPU unspecified, no CPU information given
+#define (0x1) TRONCHIP32 shared
+#define (0x2) reserved
+#define (0x3) reserved
+#define (0x4) reserved
+#define (0x5) reserved (<<L1R>> TRON-specification chip)
+#define (0x6) reserved (<<L1>> TRON-specification chip)
+#define (0x7) reserved (TRON-specification chip supporting the
+ LSID function)
+/* CPU vendors are unspecified for codes B'00000000 through B'00000111. */
+
+#define (0x8) reserved
+#define (0x9) GMICRO/100
+#define (0xa) GMICRO/200
+#define (0xb) GMICRO/300
+#define (0xc) reserved
+#define (0xd) TX1
+#define (0xe) TX2
+#define (0xf) reserved
+
+#define (0x10) reserved
+#define (0x11) reserved
+#define (0x12) reserved
+#define (0x13) O32
+#define (0x14) reserved
+#define (0x15) MN10400
+#define (0x16) reserved
+#define (0x17) reserved
+
+#define (0x18) GMICRO/400
+#define (0x19) GMICRO/500
+#define (0x1a) reserved
+#define (0x1b-0x3f)
+ reserved
+ * For GMICRO extended, TX series extended, and TRONCHIP64 chips.
+
+#define (0x40) Motorola 68000
+#define (0x41) Motorola 68010
+#define (0x42) Motorola 68020
+#define (0x43) Motorola 68030
+#define (0x44) Motorola 68040
+#define -(0x40-0x4f)
+#define Motorola 68000 family
+#define (0x50) National Semiconductor NS32032
+#define (0x50-0x5f)
+ National Semiconductor NS32000 family
+#define (0x60) Intel 8086, 8088
+#define (0x61) Intel 80186
+#define (0x62) Intel 80286
+#define (0x63) Intel 80386
+#define (0x64) Intel 80486
+#define (0x60-0x6f)
+ Intel iAPX86 family
+
+#define (0x70-0x7f)
+ NEC V Series
+
+#define (0x80-0xff)
+ reserved
+#endif
+
+/*
+ * Assigning Version Numbers
+ *
+ * The version numbers of ITRON and uITRON specifications take the following
+ * form.
+ *
+ * Ver X.YY.ZZ[.WW]
+ *
+ * where "X" represents major version number of the ITRON specification to
+ * distinguish ITRON1, ITRON2 and uITRON 3.0 specifications. Specific
+ * assignment is as follows.
+ *
+ * "X" = 1 ITRON1 specification
+ * = 2 ITRON2 or uITRON 2.0 specification
+ * = 3 uITRON 3.0 specification
+ *
+ * "YY" is a number used to distinguish versions according to changes and
+ * additions made to the specification. After the specification is published,
+ * this number is incremented in order "YY" = 00, 01, 02... according to
+ * version upgrades. The first digit of "YY" is 'A', 'B' or 'C' for draft
+ * standard versions and test versions within the TRON Association before the
+ * specification have been published.
+ *
+ * The "X.YY" part of the specification version numbers is returned by spver
+ * to get_ver system call. The corresponding hexadecimal value is used when
+ * "YY" includes 'A', 'B' or 'C'.
+ *
+ * "ZZ" represents a number used to distinguish versions related to the written
+ * style of a specification. This number is incremented in order
+ * "ZZ" = 00, 01, 02... when there have been changes in specification
+ * configuration, reordering of chapters or corrections of misprints.
+ * When a further distinction of the written style of specifications is
+ * desired, ".WW" may be added optionally after "ZZ". WW will be assumed
+ * to be zero if ".WW" is omitted.
+ */
+
+/*
+ * Reference System (ref_sys) Structure
+ */
+
+typedef struct t_rsys {
+ INT sysstat; /* system state */
+ /* additional information may be included depending on the implementation */
+} T_RSYS;
+
+/*
+ * sysstat
+ */
+
+#define TSS_TSK 0 /* normal state in which dispatching is enabled during
+ task portion execution */
+#define TSS_DDSP 1 /* state after dis_dsp has been executed during task
+ portion execution (dispatch disabled) */
+#define TSS_LOC 3 /* state after loc_cpu has been executed during task
+ portion execution (interrupt and dispatch disabled)
+ */
+#define TSS_INDP 4 /* state during execution of task-independent portions
+ (interrupt and timer handlers) */
+
+/*
+ * Reference Configuration (ref_cfg) Structure
+ */
+
+typedef struct t_rcfg {
+ /* details concerning members are implementation dependent */
+} T_RCFG;
+
+/*
+ * Define Service (def_svc) Structure
+ */
+
+typedef struct t_dsvc {
+ ATR svcatr; /* extended SVC handler attributes */
+ FP svchdr; /* extended SVC handler address */
+ /* additional information may be included depending on the implementation */
+} T_DSVC;
+
+/*
+ * Define Exception (def_exc) Structure
+ */
+
+typedef struct t_dexc {
+ ATR excatr; /* exception handler attributes */
+ FP exchdr; /* exception handler address */
+ /* additional information may be included depending on the implementation */
+} T_DEXC;
+
+/*
+ * System Management Functions
+ */
+
+/*
+ * get_ver - Get Version Information
+ */
+
+ER get_ver(
+ T_VER *pk_ver
+);
+
+/*
+ * ref_sys - Reference Semaphore Status
+ */
+
+ER ref_sys(
+ T_RSYS *pk_rsys
+);
+
+/*
+ * ref_cfg - Reference Configuration Information
+ */
+
+ER ref_cfg(
+ T_RCFG *pk_rcfg
+);
+
+/*
+ * def_svc - Define Extended SVC Handler
+ */
+
+ER def_svc(
+ FN s_fncd,
+ T_DSVC *pk_dsvc
+);
+
+/*
+ * def_exc - Define Exception Handler
+ */
+
+ER def_exc(
+ UINT exckind,
+ T_DEXC *pk_dexc
+);
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/itron/include/itronsys/task.h b/cpukit/itron/include/itronsys/task.h
new file mode 100644
index 0000000000..7eba7388e4
--- /dev/null
+++ b/cpukit/itron/include/itronsys/task.h
@@ -0,0 +1,297 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_TASK_h_
+#define __ITRON_TASK_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Create Task (cre_tsk) Structure
+ */
+
+typedef struct t_ctsk {
+ VP exinf; /* extended information */
+ ATR tskatr; /* task attributes */
+ FP task; /* task start address */
+ PRI itskpri; /* initial task priority */
+ INT stksz; /* stack size */
+ /* additional information may be included depending on the implementation */
+} T_CTSK;
+
+/*
+ * Values for the tskatr field
+ */
+
+#define TA_ASM 0x00 /* program written in assembly language */
+#define TA_HLNG 0x01 /* program written in high-level language */
+#define TA_COP0 0x8000 /* uses coprocessor having ID = 0 */
+#define TA_COP1 0x4000 /* uses coprocessor having ID = 1 */
+#define TA_COP2 0x2000 /* uses coprocessor having ID = 2 */
+#define TA_COP3 0x1000 /* uses coprocessor having ID = 3 */
+#define TA_COP4 0x0800 /* uses coprocessor having ID = 4 */
+#define TA_COP5 0x0400 /* uses coprocessor having ID = 5 */
+#define TA_COP6 0x0200 /* uses coprocessor having ID = 6 */
+#define TA_COP7 0x0100 /* uses coprocessor having ID = 7 */
+
+/*
+ * Values for the tskid field
+ */
+
+#define TSK_SELF 0 /* task specifies itself */
+
+/* XXX is this a mistake in ITRON? FALSE was here and in the types list */
+#if 0
+
+#define FALSE 0 /* indicates a task-independent portion (return */
+ /* parameters only) */
+#endif
+
+/*
+ * Values for the tskpri field
+ */
+
+#define TPRI_INI 0 /* specifies the initial priority on */
+ /* task startup (chg_pri) */
+#define TPRI_RUN 0 /* specifies the highest priority during */
+ /* execution (rot_rdq) */
+
+
+/*
+ * Reference Task (ref_tsk) Structure
+ */
+
+typedef struct t_rtsk {
+ VP exinf; /* extended information */
+ PRI tskpri; /* current priority */
+ UINT tskstat; /* task state */
+ /*
+ * The following are represent extended features of support
+ * [level X] (implementation-dependent).
+ */
+ UINT tskwait; /* cause of wait */
+ ID wid; /* ID of object being waited for */
+ INT wupcnt; /* wakeup request count */
+ INT suscnt; /* SUSPEND request count */
+ ATR tskatr; /* task attributes */
+ FP task; /* task start address */
+ PRI itskpri; /* initial task priority */
+ INT stksz; /* stack size */
+} T_RTSK;
+
+/*
+ * Values for the tskstat field
+ */
+
+
+#define TTS_RUN 0x01 /* RUN */
+#define TTS_RDY 0x02 /* READY */
+#define TTS_WAI 0x04 /* WAIT */
+#define TTS_SUS 0x08 /* SUSPEND */
+#define TTS_WAS 0x0C /* WAIT-SUSPEND */
+#define TTS_DMT 0x10 /* DORMANT */
+
+/*
+ * Values for the tskwait field
+ */
+
+#define TTW_SLP 0x0001 /* wait due to slp_tsk or tslp_tsk */
+#define TTW_DLY 0x0002 /* wait due to dly_tsk */
+#define TTW_NOD 0x0008 /* connection function response wait */
+#define TTW_FLG 0x0010 /* wait due to wai_flg or twai_flg */
+#define TTW_SEM 0x0020 /* wait due to wai_sem or twai_sem */
+#define TTW_MBX 0x0040 /* wait due to rcv_msg or trcv_msg */
+#define TTW_SMBF 0x0080 /* wait due to snd_mbf or tsnd_mbf */
+#define TTW_MBF 0x0100 /* wait due to rcv_mbf or trcv_mbf */
+#define TTW_CAL 0x0200 /* wait for rendezvous call */
+#define TTW_ACP 0x0400 /* wait for rendezvous accept */
+#define TTW_RDV 0x0800 /* wait for rendezvous completion */
+#define TTW_MPL 0x1000 /* wait due to get_blk or tget_blk */
+#define TTW_MPF 0x2000 /* wait due to get_blf or tget_blf */
+
+/*
+ * Since the task states given by tskstat and tskwait are expressed
+ * by bit correspondences, they are convenient when looking for OR
+ * conditions (such as whether a task is in WAIT or READY state).
+ */
+
+/*
+ * Task Management Functions
+ */
+
+/*
+ * cre_tsk - Create Task
+ */
+
+ER cre_tsk(
+ ID tskid,
+ T_CTSK *pk_ctsk
+);
+
+/*
+ * del_tsk - Delete Task
+ */
+
+ER del_tsk(
+ ID tskid
+);
+
+/*
+ * sta_tsk - Start Task
+ */
+
+ER sta_tsk(
+ ID tskid,
+ INT stacd
+);
+
+/*
+ * ext_tsk - Exit Issuing Task
+ */
+
+void ext_tsk( void );
+
+/*
+ * exd_tsk - Exit and Delete Task
+ */
+
+void exd_tsk( void );
+
+/*
+ * ter_tsk - Terminate Other Task
+ */
+
+ER ter_tsk(
+ ID tskid
+);
+
+/*
+ * dis_dsp - Disable Dispatch
+ */
+
+ER dis_dsp( void );
+
+/*
+ * ena_dsp - Enable Dispatch
+ */
+
+ER ena_dsp( void );
+
+/*
+ * chg_pri - Change Task Priority
+ */
+
+ER chg_pri(
+ ID tskid,
+ PRI tskpri
+);
+
+/*
+ * rot_rdq - Rotate Tasks on the Ready Queue
+ */
+
+ER rot_rdq(
+ PRI tskpri
+);
+
+/*
+ * rel_wai - Release Wait of Other Task
+ */
+
+ER rel_wai(
+ ID tskid
+);
+
+/*
+ * get_tid - Get Task Identifier
+ */
+
+ER get_tid(
+ ID *p_tskid
+);
+
+/*
+ * ref_tsk - Reference Task Status
+ */
+
+ER ref_tsk(
+ T_RTSK *pk_rtsk,
+ ID tskid
+);
+
+
+/*
+ * Task-Dependent Synchronization Functions
+ */
+
+/*
+ * sus_tsk - Suspend Other Task
+ */
+
+ER sus_tsk(
+ ID tskid
+);
+
+/*
+ * rsm_tsk - Resume Suspended Task
+ */
+
+ER rsm_tsk(
+ ID tskid
+);
+
+/*
+ * frsm_tsk - Forcibly Resume Suspended Task
+ */
+
+ER frsm_tsk(
+ ID tskid
+);
+
+/*
+ * slp_tsk - Sleep Task Sleep Task with Timeout
+ */
+
+ER slp_tsk( void );
+
+/*
+ * tslp_tsk - Sleep Task with Timeout
+ */
+
+ER tslp_tsk(
+ TMO tmout
+);
+
+/*
+ * wup_tsk - Wakeup Other Task
+ */
+
+ER wup_tsk(
+ ID tskid
+);
+
+/*
+ * can_wup - Cancel Wakeup Request
+ */
+
+ER can_wup(
+ INT *p_wupcnt,
+ ID tskid
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/itron/include/itronsys/time.h b/cpukit/itron/include/itronsys/time.h
new file mode 100644
index 0000000000..57c73e69e1
--- /dev/null
+++ b/cpukit/itron/include/itronsys/time.h
@@ -0,0 +1,184 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_TIME_h_
+#define __ITRON_TIME_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * System Time Data Type
+ *
+ * Member configuration depends on the bit width of the processor and
+ * on the implementation. A total of 48 bits is recommended.
+ *
+ */
+
+typedef struct t_systime {
+ H utime; /* upper 16 bits */
+ UW ltime; /* lower 32 bits */
+} SYSTIME, CYCTIME, ALMTIME;
+
+/*
+ * XXX Look this up in the spec and figure out where it comes
+ * XXX from. dly_tim() references it but it was left out
+ * XXX of the initial cut at the header files.
+ */
+
+typedef int DLYTIME;
+
+/*
+ * XXX (def_cyc) Structure
+ */
+
+typedef struct t_dcyc {
+ VP exinf; /* extended information */
+ ATR cycatr; /* cyclic handler attributes */
+ FP cychdr; /* cyclic handler address */
+ UINT cycact; /* cyclic handler activation */
+ CYCTIME cyctim; /* cyclic startup period */
+} T_DCYC;
+
+/*
+ * cycact
+ */
+
+#define TCY_OFF 0x00 /* do not invoke cyclic handler */
+#define TCY_ON 0x01 /* invoke cyclic handler */
+#define TCY_INT 0x02 /* initialize cycle count */
+
+/*
+ * Reference Cyclic Handler (ref_cyc) Structure
+ */
+
+typedef struct t_rcyc {
+ VP exinf; /* extended information */
+ CYCTIME lfttim; /* time left before next handler startup */
+ UINT cycact; /* cyclic handler activation */
+ /* additional information may be included depending on the implementation */
+} T_RCYC;
+
+/*
+ * Define Alarm (def_alm) Structure
+ */
+
+typedef struct t_dalm {
+ VP exinf; /* extended information */
+ ATR almatr; /* alarm handler attributes */
+ FP almhdr; /* alarm handler address */
+ UINT tmmode; /* start time specification mode */
+ ALMTIME almtim; /* handler startup time */
+} T_DALM;
+
+/*
+ * tmmode
+ */
+
+#define TTM_ABS 0x00 /* specified as an absolute time */
+#define TTM_REL 0x01 /* specified as a relative time */
+
+/*
+ * Reference Alarm (ref_alm) Structure
+ */
+
+typedef struct t_ralm {
+ VP exinf; /* extended information */
+ ALMTIME lfttim; /* time left before next handler startup */
+ /* additional information may be included depending on the implementation */
+} T_RALM;
+
+/*
+ * Time Management Functions
+ */
+
+/*
+ * set_tim - Set System Clock
+ */
+
+ER set_tim(
+ SYSTIME *pk_tim
+);
+
+/*
+ * get_tim - Get System Clock
+ */
+
+ER get_tim(
+ SYSTIME *pk_tim
+);
+
+/*
+ * dly_tsk - Delay Task
+ */
+
+ER dly_tsk(
+ DLYTIME dlytim
+);
+
+/*
+ * def_cyc - Define Cyclic Handler
+ */
+
+ER def_cyc(
+ HNO cycno,
+ T_DCYC *pk_dcyc
+);
+
+/*
+ * act_cyc - Activate Cyclic Handler
+ */
+
+ER act_cyc(
+ HNO cycno,
+ UINT cycact
+);
+
+/*
+ * ref_cyc - Reference Cyclic Handler Status
+ */
+
+ER ref_cyc(
+ T_RCYC *pk_rcyc,
+ HNO cycno
+);
+
+/*
+ * def_alm - Define Alarm Handler
+ */
+
+ER def_alm(
+ HNO almno,
+ T_DALM *pk_dalm
+);
+
+/*
+ * ref_alm - Reference Alarm Handler Status
+ */
+
+ER ref_alm(
+ T_RALM *pk_ralm,
+ HNO almno
+);
+
+/*
+ * ret_tmr - Return from Timer Handler
+ */
+
+void ret_tmr( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/itron/include/itronsys/types.h b/cpukit/itron/include/itronsys/types.h
new file mode 100644
index 0000000000..73ec53869c
--- /dev/null
+++ b/cpukit/itron/include/itronsys/types.h
@@ -0,0 +1,120 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_TYPES_h_
+#define __ITRON_TYPES_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* XXX some of these may need to be moved */
+/*
+ * XXX: These names are too short and conflict with numerous
+ * off the shell programs including paranoia.
+ */
+
+typedef int8_t B; /* signed 8-bit integer */
+typedef int16_t H; /* signed 16-bit integer */
+typedef int32_t W; /* signed 32-bit integer */
+typedef uint8_t UB; /* unsigned 8-bit integer */
+typedef uint16_t UH; /* unsigned 16-bit integer */
+typedef uint32_t UW; /* unsigned 32-bit integer */
+
+typedef uint32_t VW; /* unpredictable data type (32-bit size) */
+typedef uint16_t VH; /* unpredictable data type (16-bit size) */
+typedef uint8_t VB; /* unpredictable data type (8-bit size) */
+
+typedef void *VP; /* pointer to an unpredictable data type */
+
+typedef void (*FP)(); /* program start address */
+
+/*
+ * 6.4 Data Types
+ *
+ * The difference between VB, VH and VW and B, H and W is that only the
+ * number of bits is known for the former, not the data type of the
+ * contents. The latter clearly represent integers.
+ */
+
+/*
+ * Data Types Dependent on ITRON Specification
+ *
+ * In order to clarify the meanings of certain parameters, the
+ * following names are used for data types which appear frequently
+ * and/or have special meanings.
+ */
+
+typedef int32_t INT; /* Signed integer (bit width of processor) */
+typedef uint32_t UINT; /* Unsigned integer (bit width of processor) */
+typedef boolean BOOL; /* Boolean value. TRUE (1) or FALSE (0). */
+typedef int16_t FN; /* Function code. Signed integer. Maximum 2 bytes. */
+typedef int ID; /* Object ID number (???id) */
+ /* Value range depends on the system. Usually */
+ /* a signed integer. Certain ID values may */
+ /* represent objects on other nodes when the */
+ /* connection function is supported. */
+
+typedef uint32_t BOOL_ID;/* Boolean value or ID number */
+
+typedef int32_t HNO; /* Handler number */
+typedef int32_t RNO; /* Rendezvous number */
+typedef int32_t NODE; /* Node Number. Usually a signed integer. */
+typedef int32_t ATR; /* Object or handler attribute. */
+ /* An unsigned integer. */
+typedef int32_t ER; /* Error code. A signed integer. */
+typedef uint32_t PRI; /* Task priority. A signed integer. */
+typedef int32_t TMO; /* Timeout value. A signed integer. */
+ /* TMO_POL = 0 indicates polling, */
+ /* while TMO_FEVR = -1 indicates wait forever. */
+
+/*
+ * 6.6 Common Constants and Data Structure Packet Formats
+ */
+
+#define NADR (-1) /* invalid address or pointer value */
+
+#ifndef TRUE
+#define TRUE 1 /* true */
+#endif
+
+#ifndef FALSE
+#define FALSE 0 /* false */
+#endif
+
+/*
+ * ATR tskatr, intatr, cycatr, almatr, svcatr, excatr:
+ *
+ * TA_ASM indicates that the task or handler is directly started
+ * at the assembly language level. The TA_ASM attribute has the
+ * opposite meaning of TA_HLNG.
+ *
+ * NOTE: Really in <itronsys/task.h>
+ */
+
+#if 0
+#define TA_ASM 0x00 /* program written in assembly language */
+#define TA_HLNG 0x01 /* program written in high-level language */
+#endif
+
+/*
+ * TMO tmout:
+ */
+
+#define TMO_POL 0 /* polling */
+#define TMO_FEVR (-1) /* wait forever */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/itron/include/itronsys/vmempool.h b/cpukit/itron/include/itronsys/vmempool.h
new file mode 100644
index 0000000000..c1aec95fc9
--- /dev/null
+++ b/cpukit/itron/include/itronsys/vmempool.h
@@ -0,0 +1,131 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_VARIABLE_MEMORYPOOL_h_
+#define __ITRON_VARIABLE_MEMORYPOOL_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Create Variable Memory Pool (cre_mpl) Structure
+ */
+
+typedef struct t_cmpl {
+ VP exinf; /* extended information */
+ ATR mplatr; /* memorypool attributes */
+ INT mplsz; /* memorypool size */
+ /* additional information may be included depending on the implementation */
+} T_CMPL;
+
+/*
+ * mplatr
+ */
+
+#define TA_TFIFO 0x00 /* waiting tasks are handled by FIFO */
+#define TA_TPRI 0x01 /* waiting tasks are handled by priority */
+
+/*
+ * mplid
+ */
+
+#define TMPL_OS (-4) /* memorypool used by OS */
+
+/*
+ * Reference Variable Memory Pool (ref_mpl) Structure
+ */
+
+typedef struct t_rmpl {
+ VP exinf; /* extended information */
+ BOOL_ID wtsk; /* indicates whether or not there are waiting tasks */
+ INT frsz; /* total size of free memory */
+ INT maxsz; /* size of largest contiguous memory */
+ /* additional information may be included depending on the implementation */
+} T_RMPL;
+
+/*
+ * Variable Memory Pool Functions
+ */
+
+/*
+ * cre_mpl - Create Variable-Size Memorypool
+ */
+
+ER cre_mpl(
+ ID mplid,
+ T_CMPL *pk_cmpl
+);
+
+/*
+ * del_mpl - Delete Variable-Size Memorypool
+ */
+
+ER del_mpl(
+ ID mplid
+);
+
+/*
+ * get_blk - Get Variable-Size Memory Block
+ */
+
+ER get_blk(
+ VP *p_blk,
+ ID mplid,
+ INT blksz
+);
+
+/*
+ * pget_blk - Poll and Get Variable-Size Memory Block
+ */
+
+ER pget_blk(
+ VP *p_blk,
+ ID mplid,
+ INT blksz
+);
+
+/*
+ * tget_blk - Get Variable-Size Memory Block with Timeout
+ */
+
+ER tget_blk(
+ VP *p_blk,
+ ID mplid,
+ INT blksz,
+ TMO tmout
+);
+
+/*
+ * rel_blk - Release Variable-Size Memory Block
+ */
+
+ER rel_blk(
+ ID mplid,
+ VP blk
+);
+
+/*
+ * ref_mpl - Reference Variable-Size Memorypool Status
+ */
+
+ER ref_mpl(
+ T_RMPL *pk_rmpl,
+ ID mplid
+);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/itron/include/rtems/itron/README b/cpukit/itron/include/rtems/itron/README
new file mode 100644
index 0000000000..9ac3bf3417
--- /dev/null
+++ b/cpukit/itron/include/rtems/itron/README
@@ -0,0 +1,10 @@
+#
+# $Id$
+#
+
+This directory contains the private interface of each manager.
+These files should only be included from the from the
+implementation of each manager.
+
+The public header file for each ITRON manager is in
+../../../tronsys. \ No newline at end of file
diff --git a/cpukit/itron/include/rtems/itron/config.h b/cpukit/itron/include/rtems/itron/config.h
new file mode 100644
index 0000000000..3ed6ae949f
--- /dev/null
+++ b/cpukit/itron/include/rtems/itron/config.h
@@ -0,0 +1,62 @@
+/* config.h
+ *
+ * This include file contains the table of user defined configuration
+ * parameters specific for the ITRON API.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_ITRON_CONFIGURATION_h
+#define __RTEMS_ITRON_CONFIGURATION_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * XXX
+ *
+ * The following records define the Configuration Table. The
+ * information contained in this table is required in all
+ * RTEMS systems, whether single or multiprocessor. This
+ * table primarily defines the following:
+ *
+ * + required number of each object type
+ */
+
+/*
+ * For now, we are only allowing the user to specify the entry point
+ * and stack size for ITRON initialization threads.
+ */
+
+typedef struct {
+ ID id;
+ T_CTSK attributes;
+} itron_initialization_tasks_table;
+
+typedef struct {
+ int maximum_tasks;
+ int maximum_semaphores;
+ int maximum_eventflags;
+ int maximum_mailboxes;
+ int maximum_message_buffers;
+ int maximum_ports;
+ int maximum_memory_pools;
+ int maximum_fixed_memory_pools;
+ int number_of_initialization_tasks;
+ itron_initialization_tasks_table *User_initialization_tasks_table;
+} itron_api_configuration_table;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/itron/include/rtems/itron/eventflags.h b/cpukit/itron/include/rtems/itron/eventflags.h
new file mode 100644
index 0000000000..86b15baabe
--- /dev/null
+++ b/cpukit/itron/include/rtems/itron/eventflags.h
@@ -0,0 +1,60 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_ITRON_EVENTFLAGS_h_
+#define __RTEMS_ITRON_EVENTFLAGS_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/itron/object.h>
+
+/*
+ * The following defines the control block used to manage each event flag.
+ */
+
+typedef struct {
+ ITRON_Objects_Control Object;
+ uint32_t XXX_more_stuff_goes_here;
+} ITRON_Eventflags_Control;
+
+/*
+ * The following defines the information control block used to manage
+ * this class of objects.
+ */
+
+ITRON_EXTERN Objects_Information _ITRON_Eventflags_Information;
+
+/*
+ * _ITRON_Eventflags_Manager_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this manager.
+ */
+
+void _ITRON_Eventflags_Manager_initialization(
+ uint32_t maximum_eventflags
+);
+
+/*
+ * XXX insert private stuff here
+ */
+
+#include <rtems/itron/eventflags.inl>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/itron/include/rtems/itron/fmempool.h b/cpukit/itron/include/rtems/itron/fmempool.h
new file mode 100644
index 0000000000..a8f6e7a698
--- /dev/null
+++ b/cpukit/itron/include/rtems/itron/fmempool.h
@@ -0,0 +1,61 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_ITRON_FIXED_MEMORYPOOL_h_
+#define __RTEMS_ITRON_FIXED_MEMORYPOOL_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/itron/object.h>
+
+/*
+ * The following defines the control block used to manage each
+ * fixed memory pool.
+ */
+
+typedef struct {
+ ITRON_Objects_Control Object;
+ uint32_t XXX_more_stuff_goes_here;
+} ITRON_Fixed_memory_pool_Control;
+
+/*
+ * The following defines the information control block used to manage
+ * this class of objects.
+ */
+
+ITRON_EXTERN Objects_Information _ITRON_Fixed_memory_pool_Information;
+
+/*
+ * _ITRON_Fixed_memory_pool_Manager_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this manager.
+ */
+
+void _ITRON_Fixed_memory_pool_Manager_initialization(
+ uint32_t maximum_fixed_memory_pools
+);
+
+/*
+ * XXX insert private stuff here
+ */
+
+#include <rtems/itron/fmempool.inl>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/itron/include/rtems/itron/intr.h b/cpukit/itron/include/rtems/itron/intr.h
new file mode 100644
index 0000000000..acb19ebecb
--- /dev/null
+++ b/cpukit/itron/include/rtems/itron/intr.h
@@ -0,0 +1,30 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_ITRON_INTERRUPT_h_
+#define __RTEMS_ITRON_INTERRUPT_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * XXX insert private stuff here
+ */
+
+#include <rtems/itron/intr.inl>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/itron/include/rtems/itron/itronapi.h b/cpukit/itron/include/rtems/itron/itronapi.h
new file mode 100644
index 0000000000..ea02aed805
--- /dev/null
+++ b/cpukit/itron/include/rtems/itron/itronapi.h
@@ -0,0 +1,30 @@
+/*
+ * ITRON API Support
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_API_h
+#define __ITRON_API_h
+
+#include <rtems/config.h>
+
+/*
+ * _ITRON_API_Initialize
+ *
+ * Initialize the ITRON API.
+ */
+
+void _ITRON_API_Initialize(
+ rtems_configuration_table *configuration_table
+);
+
+#endif
+/* end of include file */
diff --git a/cpukit/itron/include/rtems/itron/mbox.h b/cpukit/itron/include/rtems/itron/mbox.h
new file mode 100644
index 0000000000..09185935c1
--- /dev/null
+++ b/cpukit/itron/include/rtems/itron/mbox.h
@@ -0,0 +1,72 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_ITRON_MBOX_h_
+#define __RTEMS_ITRON_MBOX_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/itron/object.h>
+#include <rtems/score/coremsg.h>
+
+/*
+ * The following defines the control block used to manage each mailbox.
+ */
+
+typedef struct {
+ ITRON_Objects_Control Object;
+ uint32_t count;
+ boolean do_message_priority;
+ CORE_message_queue_Control message_queue;
+} ITRON_Mailbox_Control;
+
+/*
+ * The following defines the information control block used to manage
+ * this class of objects.
+ */
+
+ITRON_EXTERN Objects_Information _ITRON_Mailbox_Information;
+
+/*
+ * _ITRON_Mailbox_Manager_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this manager.
+ */
+
+void _ITRON_Mailbox_Manager_initialization(
+ uint32_t maximum_mailboxes
+);
+
+/*
+ * _ITRON_Mailbox_Translate_core_message_queue_return_code
+ *
+ * DESCRIPTION:
+ *
+ * This routine translates a core message queue object status
+ * into the appropriate ITRON status code.
+ */
+
+ER _ITRON_Mailbox_Translate_core_message_queue_return_code(
+ CORE_message_queue_Status status
+);
+
+#include <rtems/itron/mbox.inl>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/itron/include/rtems/itron/msgbuffer.h b/cpukit/itron/include/rtems/itron/msgbuffer.h
new file mode 100644
index 0000000000..ddda78f217
--- /dev/null
+++ b/cpukit/itron/include/rtems/itron/msgbuffer.h
@@ -0,0 +1,72 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_ITRON_MESSAGEBUFFER_h_
+#define __RTEMS_ITRON_MESSAGEBUFFER_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/itron/object.h>
+#include <rtems/score/coremsg.h>
+
+/*
+ * The following defines the control block used to manage each
+ * message buffer.
+ */
+
+typedef struct {
+ ITRON_Objects_Control Object;
+ boolean is_priority_blocking;
+ CORE_message_queue_Control message_queue;
+} ITRON_Message_buffer_Control;
+
+/*
+ * The following defines the information control block used to manage
+ * this class of objects.
+ */
+
+ITRON_EXTERN Objects_Information _ITRON_Message_buffer_Information;
+
+/*
+ * _ITRON_Message_buffer_Manager_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this manager.
+ */
+
+void _ITRON_Message_buffer_Manager_initialization(
+ uint32_t maximum_message_buffers
+);
+
+/*
+ * _ITRON_Message_buffer_Translate_core_message_buffer_return_code
+ *
+ * DESCRIPTION:
+ *
+ * This routine translates a core message buffer object status
+ * into the appropriate ITRON status code.
+ */
+
+ER _ITRON_Message_buffer_Translate_core_message_buffer_return_code(
+ CORE_message_queue_Status status
+);
+
+#include <rtems/itron/msgbuffer.inl>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/itron/include/rtems/itron/network.h b/cpukit/itron/include/rtems/itron/network.h
new file mode 100644
index 0000000000..44e9a67796
--- /dev/null
+++ b/cpukit/itron/include/rtems/itron/network.h
@@ -0,0 +1,30 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_ITRON_NETWORK_h_
+#define __RTEMS_ITRON_NETWORK_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * XXX insert private stuff here
+ */
+
+#include <rtems/itron/network.inl>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/itron/include/rtems/itron/object.h b/cpukit/itron/include/rtems/itron/object.h
new file mode 100644
index 0000000000..e4e6ce3e9c
--- /dev/null
+++ b/cpukit/itron/include/rtems/itron/object.h
@@ -0,0 +1,119 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_ITRON_OBJECT_h_
+#define __RTEMS_ITRON_OBJECT_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/object.h>
+
+typedef Objects_Control ITRON_Objects_Control;
+
+/*
+ * Maximum length of an ITRON object name
+ *
+ * NOTE: Since ITRON objects do not have names, then then length is 0.
+ */
+
+#define ITRON_MAXIMUM_NAME_LENGTH 0
+
+/*
+ * _ITRON_Objects_Open
+ *
+ * Make this ITRON object visible to the system.
+ *
+ * NOTE: This macro hides the fact that ITRON objects don't have names.
+ */
+
+#define _ITRON_Objects_Open( _the_information, _the_object ) \
+ _Objects_Open( (_the_information), (_the_object), NULL )
+
+/*
+ * _ITRON_Objects_Close
+ *
+ * Make this ITRON object invisible from the system. Usually used as
+ * the first step of deleting an object.
+ */
+
+#define _ITRON_Objects_Close( _the_information, _the_object ) \
+ _Objects_Close( (_the_information), (_the_object) )
+
+/*
+ * _ITRON_Objects_Allocate_by_index
+ *
+ * Allocate the ITRON object specified by "_id". The ITRON id is the
+ * index portion of the traditional RTEMS ID. The Classic and POSIX
+ * APIs do not require that a specific object be allocated.
+ */
+
+#define _ITRON_Objects_Allocate_by_index( _the_information, _id, _sizeof ) \
+ _Objects_Allocate_by_index( (_the_information), (_id), (_sizeof) )
+
+/*
+ * _ITRON_Objects_Clarify_allocation_id_error
+ *
+ * This function is invoked when an object allocation ID error
+ * occurs to determine the specific ITRON error code to return.
+ */
+
+#define _ITRON_Objects_Clarify_allocation_id_error( _the_information, _id ) \
+ (((_id) < -4) ? E_OACV : /* attempt to access a "system object" */ \
+ ((_id) <= 0) ? E_ID : /* bogus index of 0 - -3 */ \
+ ((_id) <= (_the_information)->maximum) ? E_OBJ : /* object is in use */ \
+ E_ID) /* simply a bad id */
+
+/*
+ * _ITRON_Objects_Clarify_get_id_error
+ *
+ * This function is invoked when an object get ID error
+ * occurs to determine the specific ITRON error code to return.
+ */
+
+#define _ITRON_Objects_Clarify_get_id_error( _the_information, _id ) \
+ (((_id) < -4) ? E_OACV : /* attempt to access a "system object" */ \
+ ((_id) <= 0) ? E_ID : /* bogus index of 0 - -3 */ \
+ ((_id) <= (_the_information)->maximum) ? E_NOEXS : /* does not exist */ \
+ E_ID) /* simply a bad id */
+
+
+/*
+ * _ITRON_Objects_Free
+ *
+ * Free this ITRON object to the pool of inactive objects. This
+ * operation is the same as for the Classic and POSIX APIs.
+ */
+
+#define _ITRON_Objects_Free( _the_information, _the_object ) \
+ _Objects_Free( (_the_information), (_the_object) )
+
+
+/*
+ * _ITRON_Objects_Get
+ *
+ * Obtain (get) the pointer to the control block for the object
+ * specified by "id". The ITRON id passed in here is simply
+ * the "index" portion of the traditional RTEMS ID. This
+ * requires that this operation be slightly different
+ * from the object get used by the Classic and POSIX APIs.
+ */
+
+#define _ITRON_Objects_Get( _the_information, _id, _the_object ) \
+ _Objects_Get_by_index( (_the_information), (_id), (_the_object) )
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/itron/include/rtems/itron/port.h b/cpukit/itron/include/rtems/itron/port.h
new file mode 100644
index 0000000000..149ede2247
--- /dev/null
+++ b/cpukit/itron/include/rtems/itron/port.h
@@ -0,0 +1,60 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_ITRON_PORT_h_
+#define __RTEMS_ITRON_PORT_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/itron/object.h>
+
+/*
+ * The following defines the control block used to manage each port.
+ */
+
+typedef struct {
+ ITRON_Objects_Control Object;
+ uint32_t XXX_more_stuff_goes_here;
+} ITRON_Port_Control;
+
+/*
+ * The following defines the information control block used to manage
+ * this class of objects.
+ */
+
+ITRON_EXTERN Objects_Information _ITRON_Port_Information;
+
+/*
+ * _ITRON_Port_Manager_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this manager.
+ */
+
+void _ITRON_Port_Manager_initialization(
+ uint32_t maximum_ports
+);
+
+/*
+ * XXX insert private stuff here
+ */
+
+#include <rtems/itron/port.inl>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/itron/include/rtems/itron/semaphore.h b/cpukit/itron/include/rtems/itron/semaphore.h
new file mode 100644
index 0000000000..b8e4f0f1ae
--- /dev/null
+++ b/cpukit/itron/include/rtems/itron/semaphore.h
@@ -0,0 +1,58 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_ITRON_SEMAPHORE_h_
+#define __RTEMS_ITRON_SEMAPHORE_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/itron/object.h>
+#include <rtems/score/coresem.h>
+
+/*
+ * The following defines the control block used to manage each semaphore.
+ */
+
+typedef struct {
+ ITRON_Objects_Control Object;
+ boolean is_priority_blocking;
+ CORE_semaphore_Control semaphore;
+} ITRON_Semaphore_Control;
+
+/*
+ * The following defines the information control block used to manage
+ * this class of objects.
+ */
+
+ITRON_EXTERN Objects_Information _ITRON_Semaphore_Information;
+
+/*
+ * _ITRON_Semaphore_Manager_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this manager.
+ */
+
+void _ITRON_Semaphore_Manager_initialization(
+ uint32_t maximum_semaphores
+);
+
+#include <rtems/itron/semaphore.inl>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/itron/include/rtems/itron/sysmgmt.h b/cpukit/itron/include/rtems/itron/sysmgmt.h
new file mode 100644
index 0000000000..0444b3d7f9
--- /dev/null
+++ b/cpukit/itron/include/rtems/itron/sysmgmt.h
@@ -0,0 +1,30 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_ITRON_TIME_h_
+#define __RTEMS_ITRON_TIME_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * XXX insert private stuff here
+ */
+
+#include <rtems/itron/sysmgmt.inl>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/itron/include/rtems/itron/task.h b/cpukit/itron/include/rtems/itron/task.h
new file mode 100644
index 0000000000..f884bebfae
--- /dev/null
+++ b/cpukit/itron/include/rtems/itron/task.h
@@ -0,0 +1,101 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_ITRON_TASK_h_
+#define __RTEMS_ITRON_TASK_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/itron/object.h>
+#include <rtems/itron/config.h>
+#include <rtems/score/thread.h>
+
+/*
+ * This macro evaluates to TRUE if there should be a "context error."
+ * This is defined as a blocking directive being issed from
+ * task-independent portions or a task in dispatch disabled state.
+ *
+ * NOTE: Dispatching is disabled in interrupts so this should cover
+ * both cases.
+ */
+
+#define _ITRON_Is_in_non_task_state() \
+ (_Thread_Dispatch_disable_level != 0)
+
+/*
+ * This is the API specific information required by each thread for
+ * the ITRON API to function correctly.
+ */
+
+
+typedef struct {
+ uint32_t unused; /* no use for the API extension */
+ /* structure for ITRON identified yet */
+} ITRON_API_Control;
+
+/*
+ * The following defines the information control block used to
+ * manage this class of objects.
+ */
+
+ITRON_EXTERN Objects_Information _ITRON_Task_Information;
+
+/*
+ * These are used to manage the user initialization tasks.
+ */
+
+ITRON_EXTERN itron_initialization_tasks_table
+ *_ITRON_Task_User_initialization_tasks;
+ITRON_EXTERN uint32_t _ITRON_Task_Number_of_initialization_tasks;
+
+
+/*
+ * _ITRON_Task_Manager_initialization
+ *
+ * This routine initializes the ITRON Task Manager.
+ */
+
+void _ITRON_Task_Manager_initialization(
+ uint32_t maximum_tasks,
+ uint32_t number_of_initialization_tasks,
+ itron_initialization_tasks_table *user_tasks
+);
+
+/*
+ *
+ * _ITRON_Delete_task
+ */
+
+ER _ITRON_Delete_task(
+ Thread_Control *the_thread
+);
+
+/* XXX remove the need for this. Enable dispatch should not be hidden */
+
+#define _ITRON_return_errorno( _errno ) \
+do { \
+ _Thread_Enable_dispatch(); \
+ return _errno; \
+} while (0);
+
+
+#ifndef __RTEMS_APPLICATION__
+#include <rtems/itron/task.inl>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/itron/include/rtems/itron/time.h b/cpukit/itron/include/rtems/itron/time.h
new file mode 100644
index 0000000000..f0d1278982
--- /dev/null
+++ b/cpukit/itron/include/rtems/itron/time.h
@@ -0,0 +1,30 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_ITRON_TIME_h_
+#define __RTEMS_ITRON_TIME_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * XXX insert private stuff here
+ */
+
+#include <rtems/itron/time.inl>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/itron/include/rtems/itron/vmempool.h b/cpukit/itron/include/rtems/itron/vmempool.h
new file mode 100644
index 0000000000..1658dacbe4
--- /dev/null
+++ b/cpukit/itron/include/rtems/itron/vmempool.h
@@ -0,0 +1,61 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_ITRON_VARIABLE_MEMORYPOOL_h_
+#define __RTEMS_ITRON_VARIABLE_MEMORYPOOL_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/itron/object.h>
+
+/*
+ * The following defines the control block used to manage each variable
+ * memory pool.
+ */
+
+typedef struct {
+ ITRON_Objects_Control Object;
+ uint32_t XXX_more_stuff_goes_here;
+} ITRON_Variable_memory_pool_Control;
+
+/*
+ * The following defines the information control block used to manage
+ * this class of objects.
+ */
+
+ITRON_EXTERN Objects_Information _ITRON_Variable_memory_pool_Information;
+
+/*
+ * _ITRON_Variable_memory_pool_Manager_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this manager.
+ */
+
+void _ITRON_Variable_memory_pool_Manager_initialization(
+ uint32_t maximum_variable_memory_pools
+);
+
+/*
+ * XXX insert private stuff here
+ */
+
+#include <rtems/itron/vmempool.inl>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/itron/inline/rtems/itron/eventflags.inl b/cpukit/itron/inline/rtems/itron/eventflags.inl
new file mode 100644
index 0000000000..1ed33e1383
--- /dev/null
+++ b/cpukit/itron/inline/rtems/itron/eventflags.inl
@@ -0,0 +1,151 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_EVENTFLAGS_inl_
+#define __ITRON_EVENTFLAGS_inl_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * _ITRON_Eventflags_Allocate
+ *
+ * DESCRIPTION:
+ *
+ * This routine allocates the eventflags associated with the specified
+ * eventflags ID from the pool of inactive eventflagss.
+ *
+ * Input parameters:
+ * flgid - id of eventflags to allocate
+ * status - pointer to status variable
+ *
+ * Output parameters:
+ * returns - pointer to the eventflags control block
+ * *status - status
+ */
+
+RTEMS_INLINE_ROUTINE ITRON_Eventflags_Control *_ITRON_Eventflags_Allocate(
+ ID flgid
+)
+{
+ return (ITRON_Eventflags_Control *)_ITRON_Objects_Allocate_by_index(
+ &_ITRON_Eventflags_Information,
+ flgid,
+ sizeof(ITRON_Eventflags_Control)
+ );
+}
+
+/*
+ * _ITRON_Eventflags_Clarify_allocation_id_error
+ *
+ * This function is invoked when an object allocation ID error
+ * occurs to determine the specific ITRON error code to return.
+ */
+
+#define _ITRON_Eventflags_Clarify_allocation_id_error( _id ) \
+ _ITRON_Objects_Clarify_allocation_id_error( \
+ &_ITRON_Eventflags_Information, (_id) )
+
+/*
+ * _ITRON_Eventflags_Clarify_get_id_error
+ *
+ * This function is invoked when an object get ID error
+ * occurs to determine the specific ITRON error code to return.
+ */
+
+#define _ITRON_Eventflags_Clarify_get_id_error( _id ) \
+ _ITRON_Objects_Clarify_get_id_error( &_ITRON_Eventflags_Information, (_id) )
+
+/*
+ * _ITRON_Eventflags_Free
+ *
+ * DESCRIPTION:
+ *
+ * This routine frees a eventflags control block to the
+ * inactive chain of free eventflags control blocks.
+ *
+ * Input parameters:
+ * the_eventflags - pointer to eventflags control block
+ *
+ * Output parameters: NONE
+ */
+
+RTEMS_INLINE_ROUTINE void _ITRON_Eventflags_Free (
+ ITRON_Eventflags_Control *the_eventflags
+)
+{
+ _ITRON_Objects_Free( &_ITRON_Eventflags_Information, &the_eventflags->Object );
+}
+
+/*PAGE
+ *
+ * _ITRON_Eventflags_Get
+ *
+ * DESCRIPTION:
+ *
+ * This function maps eventflags IDs to eventflags control blocks.
+ * If ID corresponds to a local eventflags, then it returns
+ * the_eventflags control pointer which maps to ID and location
+ * is set to OBJECTS_LOCAL. if the eventflags ID is global and
+ * resides on a remote node, then location is set to OBJECTS_REMOTE,
+ * and the_eventflags is undefined. Otherwise, location is set
+ * to OBJECTS_ERROR and the_eventflags is undefined.
+ *
+ * Input parameters:
+ * id - ITRON eventflags ID.
+ * the_location - pointer to a location variable
+ *
+ * Output parameters:
+ * *the_location - location of the object
+ */
+
+RTEMS_INLINE_ROUTINE ITRON_Eventflags_Control *_ITRON_Eventflags_Get (
+ ID id,
+ Objects_Locations *location
+)
+{
+ return (ITRON_Eventflags_Control *)
+ _ITRON_Objects_Get( &_ITRON_Eventflags_Information, id, location );
+}
+
+/*PAGE
+ *
+ * _ITRON_Eventflags_Is_null
+ *
+ * This function returns TRUE if the_eventflags is NULL and FALSE otherwise.
+ *
+ * Input parameters:
+ * the_eventflags - pointer to eventflags control block
+ *
+ * Output parameters:
+ * TRUE - if the_eventflags is NULL
+ * FALSE - otherwise
+ */
+
+RTEMS_INLINE_ROUTINE boolean _ITRON_Eventflags_Is_null (
+ ITRON_Eventflags_Control *the_eventflags
+)
+{
+ return ( the_eventflags == NULL );
+}
+
+/*
+ * XXX insert inline routines here
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/itron/inline/rtems/itron/fmempool.inl b/cpukit/itron/inline/rtems/itron/fmempool.inl
new file mode 100644
index 0000000000..4f743c5dc3
--- /dev/null
+++ b/cpukit/itron/inline/rtems/itron/fmempool.inl
@@ -0,0 +1,158 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_FIXED_MEMORY_POOL_inl_
+#define __ITRON_FIXED_MEMORY_POOL_inl_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * _ITRON_Fixed_memory_pool_Allocate
+ *
+ * DESCRIPTION:
+ *
+ * This routine allocates the fixed_memory_pool associated with the specified
+ * fixed_memory_pool ID from the pool of inactive fixed_memory_pools.
+ *
+ * Input parameters:
+ * mpfid - id of fixed_memory_pool to allocate
+ * status - pointer to status variable
+ *
+ * Output parameters:
+ * returns - pointer to the fixed_memory_pool control block
+ * *status - status
+ */
+
+RTEMS_INLINE_ROUTINE ITRON_Fixed_memory_pool_Control
+ *_ITRON_Fixed_memory_pool_Allocate(
+ ID mpfid
+)
+{
+ return (ITRON_Fixed_memory_pool_Control *)_ITRON_Objects_Allocate_by_index(
+ &_ITRON_Fixed_memory_pool_Information,
+ mpfid,
+ sizeof(ITRON_Fixed_memory_pool_Control)
+ );
+}
+
+/*
+ * _ITRON_Fixed_memory_pool_Clarify_allocation_id_error
+ *
+ * This function is invoked when an object allocation ID error
+ * occurs to determine the specific ITRON error code to return.
+ */
+
+#define _ITRON_Fixed_memory_pool_Clarify_allocation_id_error( _id ) \
+ _ITRON_Objects_Clarify_allocation_id_error( \
+ &_ITRON_Fixed_memory_pool_Information, (_id) )
+
+/*
+ * _ITRON_Fixed_memory_pool_Clarify_get_id_error
+ *
+ * This function is invoked when an object get ID error
+ * occurs to determine the specific ITRON error code to return.
+ */
+
+#define _ITRON_Fixed_memory_pool_Clarify_get_id_error( _id ) \
+ _ITRON_Objects_Clarify_get_id_error( \
+ &_ITRON_Fixed_memory_pool_Information, (_id) )
+
+/*
+ * _ITRON_Fixed_memory_pool_Free
+ *
+ * DESCRIPTION:
+ *
+ * This routine frees a fixed_memory_pool control block to the
+ * inactive chain of free fixed_memory_pool control blocks.
+ *
+ * Input parameters:
+ * the_fixed_memory_pool - pointer to fixed_memory_pool control block
+ *
+ * Output parameters: NONE
+ */
+
+RTEMS_INLINE_ROUTINE void _ITRON_Fixed_memory_pool_Free (
+ ITRON_Fixed_memory_pool_Control *the_fixed_memory_pool
+)
+{
+ _ITRON_Objects_Free(
+ &_ITRON_Fixed_memory_pool_Information,
+ &the_fixed_memory_pool->Object
+ );
+}
+
+/*PAGE
+ *
+ * _ITRON_Fixed_memory_pool_Get
+ *
+ * DESCRIPTION:
+ *
+ * This function maps fixed memory pool IDs to control blocks.
+ * If ID corresponds to a local fixed memory pool, then it returns
+ * the_fixed memory pool control pointer which maps to ID and location
+ * is set to OBJECTS_LOCAL. if the fixed memory pool ID is global and
+ * resides on a remote node, then location is set to OBJECTS_REMOTE,
+ * and the fixed memory pool is undefined. Otherwise, location is set
+ * to OBJECTS_ERROR and the fixed memory pool is undefined.
+ *
+ * Input parameters:
+ * id - ITRON fixed memory pool ID.
+ * the_location - pointer to a location variable
+ *
+ * Output parameters:
+ * *the_location - location of the object
+ */
+
+RTEMS_INLINE_ROUTINE ITRON_Fixed_memory_pool_Control
+ *_ITRON_Fixed_memory_pool_Get (
+ ID id,
+ Objects_Locations *location
+)
+{
+ return (ITRON_Fixed_memory_pool_Control *)
+ _ITRON_Objects_Get( &_ITRON_Fixed_memory_pool_Information, id, location );
+}
+
+/*PAGE
+ *
+ * _ITRON_Fixed_memory_pool_Is_null
+ *
+ * This function returns TRUE if the_fixed_memory_pool is NULL
+ * and FALSE otherwise.
+ *
+ * Input parameters:
+ * the_fixed_memory_pool - pointer to fixed_memory_pool control block
+ *
+ * Output parameters:
+ * TRUE - if the_fixed_memory_pool is NULL
+ * FALSE - otherwise
+ */
+
+RTEMS_INLINE_ROUTINE boolean _ITRON_Fixed_memory_pool_Is_null (
+ ITRON_Fixed_memory_pool_Control *the_fixed_memory_pool
+)
+{
+ return ( the_fixed_memory_pool == NULL );
+}
+
+/*
+ * XXX insert inline routines here
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/itron/inline/rtems/itron/intr.inl b/cpukit/itron/inline/rtems/itron/intr.inl
new file mode 100644
index 0000000000..e85bea259f
--- /dev/null
+++ b/cpukit/itron/inline/rtems/itron/intr.inl
@@ -0,0 +1,30 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_INTERRUPT_inl_
+#define __ITRON_INTERRUPT_inl_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * XXX insert inline routines here
+ */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/itron/inline/rtems/itron/mbox.inl b/cpukit/itron/inline/rtems/itron/mbox.inl
new file mode 100644
index 0000000000..d5b1935511
--- /dev/null
+++ b/cpukit/itron/inline/rtems/itron/mbox.inl
@@ -0,0 +1,151 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_MAILBOX_inl_
+#define __ITRON_MAILBOX_inl_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * _ITRON_Mailbox_Allocate
+ *
+ * DESCRIPTION:
+ *
+ * This routine allocates the mailbox associated with the specified
+ * mailbox ID from the pool of inactive mailboxs.
+ *
+ * Input parameters:
+ * mbxid - id of mailbox to allocate
+ * status - pointer to status variable
+ *
+ * Output parameters:
+ * returns - pointer to the mailbox control block
+ * *status - status
+ */
+
+RTEMS_INLINE_ROUTINE ITRON_Mailbox_Control *_ITRON_Mailbox_Allocate(
+ ID mbxid
+)
+{
+ return (ITRON_Mailbox_Control *)_ITRON_Objects_Allocate_by_index(
+ &_ITRON_Mailbox_Information,
+ mbxid,
+ sizeof(ITRON_Mailbox_Control)
+ );
+}
+
+/*
+ * _ITRON_Mailbox_Clarify_allocation_id_error
+ *
+ * This function is invoked when an object allocation ID error
+ * occurs to determine the specific ITRON error code to return.
+ */
+
+#define _ITRON_Mailbox_Clarify_allocation_id_error( _id ) \
+ _ITRON_Objects_Clarify_allocation_id_error( \
+ &_ITRON_Mailbox_Information, (_id) )
+
+/*
+ * _ITRON_Mailbox_Clarify_get_id_error
+ *
+ * This function is invoked when an object get ID error
+ * occurs to determine the specific ITRON error code to return.
+ */
+
+#define _ITRON_Mailbox_Clarify_get_id_error( _id ) \
+ _ITRON_Objects_Clarify_get_id_error( &_ITRON_Mailbox_Information, (_id) )
+
+/*
+ * _ITRON_Mailbox_Free
+ *
+ * DESCRIPTION:
+ *
+ * This routine frees a mailbox control block to the
+ * inactive chain of free mailbox control blocks.
+ *
+ * Input parameters:
+ * the_mailbox - pointer to mailbox control block
+ *
+ * Output parameters: NONE
+ */
+
+RTEMS_INLINE_ROUTINE void _ITRON_Mailbox_Free (
+ ITRON_Mailbox_Control *the_mailbox
+)
+{
+ _ITRON_Objects_Free( &_ITRON_Mailbox_Information, &the_mailbox->Object );
+}
+
+/*PAGE
+ *
+ * _ITRON_Mailbox_Get
+ *
+ * DESCRIPTION:
+ *
+ * This function maps mailbox IDs to mailbox control blocks.
+ * If ID corresponds to a local mailbox, then it returns
+ * the_mailbox control pointer which maps to ID and location
+ * is set to OBJECTS_LOCAL. if the mailbox ID is global and
+ * resides on a remote node, then location is set to OBJECTS_REMOTE,
+ * and the_mailbox is undefined. Otherwise, location is set
+ * to OBJECTS_ERROR and the_mailbox is undefined.
+ *
+ * Input parameters:
+ * id - ITRON mailbox ID.
+ * the_location - pointer to a location variable
+ *
+ * Output parameters:
+ * *the_location - location of the object
+ */
+
+RTEMS_INLINE_ROUTINE ITRON_Mailbox_Control *_ITRON_Mailbox_Get (
+ ID id,
+ Objects_Locations *location
+)
+{
+ return (ITRON_Mailbox_Control *)
+ _ITRON_Objects_Get( &_ITRON_Mailbox_Information, id, location );
+}
+
+/*PAGE
+ *
+ * _ITRON_Mailbox_Is_null
+ *
+ * This function returns TRUE if the_mailbox is NULL and FALSE otherwise.
+ *
+ * Input parameters:
+ * the_mailbox - pointer to mailbox control block
+ *
+ * Output parameters:
+ * TRUE - if the_mailbox is NULL
+ * FALSE - otherwise
+ */
+
+RTEMS_INLINE_ROUTINE boolean _ITRON_Mailbox_Is_null (
+ ITRON_Mailbox_Control *the_mailbox
+)
+{
+ return ( the_mailbox == NULL );
+}
+
+/*
+ * XXX insert inline routines here
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/itron/inline/rtems/itron/msgbuffer.inl b/cpukit/itron/inline/rtems/itron/msgbuffer.inl
new file mode 100644
index 0000000000..0c482e0ebc
--- /dev/null
+++ b/cpukit/itron/inline/rtems/itron/msgbuffer.inl
@@ -0,0 +1,156 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_MESSAGE_BUFFER_inl_
+#define __ITRON_MESSAGE_BUFFER_inl_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * _ITRON_Message_buffer_Allocate
+ *
+ * DESCRIPTION:
+ *
+ * This routine allocates the message buffer associated with the specified
+ * message buffer ID from the pool of inactive message buffers.
+ *
+ * Input parameters:
+ * mbfid - id of message buffer to allocate
+ * status - pointer to status variable
+ *
+ * Output parameters:
+ * returns - pointer to the message buffer control block
+ * *status - status
+ */
+
+RTEMS_INLINE_ROUTINE ITRON_Message_buffer_Control
+ *_ITRON_Message_buffer_Allocate(
+ ID mbfid
+)
+{
+ return (ITRON_Message_buffer_Control *)_ITRON_Objects_Allocate_by_index(
+ &_ITRON_Message_buffer_Information,
+ mbfid,
+ sizeof(ITRON_Message_buffer_Control)
+ );
+}
+
+/*
+ * _ITRON_Message_buffer_Clarify_allocation_id_error
+ *
+ * This function is invoked when an object allocation ID error
+ * occurs to determine the specific ITRON error code to return.
+ */
+
+#define _ITRON_Message_buffer_Clarify_allocation_id_error( _id ) \
+ _ITRON_Objects_Clarify_allocation_id_error( \
+ &_ITRON_Message_buffer_Information, (_id) )
+
+/*
+ * _ITRON_Message_buffer_Clarify_get_id_error
+ *
+ * This function is invoked when an object get ID error
+ * occurs to determine the specific ITRON error code to return.
+ */
+
+#define _ITRON_Message_buffer_Clarify_get_id_error( _id ) \
+ _ITRON_Objects_Clarify_get_id_error( &_ITRON_Message_buffer_Information, (_id) )
+
+/*
+ * _ITRON_Message_buffer_Free
+ *
+ * DESCRIPTION:
+ *
+ * This routine frees a message buffer control block to the
+ * inactive chain of free message buffer control blocks.
+ *
+ * Input parameters:
+ * the_message_buffer - pointer to message_buffer control block
+ *
+ * Output parameters: NONE
+ */
+
+RTEMS_INLINE_ROUTINE void _ITRON_Message_buffer_Free (
+ ITRON_Message_buffer_Control *the_message_buffer
+)
+{
+ _ITRON_Objects_Free(
+ &_ITRON_Message_buffer_Information,
+ &the_message_buffer->Object
+ );
+}
+
+/*PAGE
+ *
+ * _ITRON_Message_buffer_Get
+ *
+ * DESCRIPTION:
+ *
+ * This function maps message buffer IDs to message buffer control blocks.
+ * If ID corresponds to a local message buffer, then it returns
+ * the message buffer control pointer which maps to ID and location
+ * is set to OBJECTS_LOCAL. if the message buffer ID is global and
+ * resides on a remote node, then location is set to OBJECTS_REMOTE,
+ * and the message buffer is undefined. Otherwise, location is set
+ * to OBJECTS_ERROR and the message buffer is undefined.
+ *
+ * Input parameters:
+ * id - ITRON message_buffer ID.
+ * the_location - pointer to a location variable
+ *
+ * Output parameters:
+ * *the_location - location of the object
+ */
+
+RTEMS_INLINE_ROUTINE ITRON_Message_buffer_Control *_ITRON_Message_buffer_Get (
+ ID id,
+ Objects_Locations *location
+)
+{
+ return (ITRON_Message_buffer_Control *)
+ _ITRON_Objects_Get( &_ITRON_Message_buffer_Information, id, location );
+}
+
+/*PAGE
+ *
+ * _ITRON_Message_buffer_Is_null
+ *
+ * This function returns TRUE if the_message_buffer is NULL
+ * and FALSE otherwise.
+ *
+ * Input parameters:
+ * the_message_buffer - pointer to message buffer control block
+ *
+ * Output parameters:
+ * TRUE - if the_message_buffer is NULL
+ * FALSE - otherwise
+ */
+
+RTEMS_INLINE_ROUTINE boolean _ITRON_Message_buffer_Is_null (
+ ITRON_Message_buffer_Control *the_message_buffer
+)
+{
+ return ( the_message_buffer == NULL );
+}
+
+/*
+ * XXX insert inline routines here
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/itron/inline/rtems/itron/network.inl b/cpukit/itron/inline/rtems/itron/network.inl
new file mode 100644
index 0000000000..3b46855c55
--- /dev/null
+++ b/cpukit/itron/inline/rtems/itron/network.inl
@@ -0,0 +1,30 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_NETWORK_inl_
+#define __ITRON_NETWORK_inl_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * XXX insert inline routines here
+ */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/itron/inline/rtems/itron/port.inl b/cpukit/itron/inline/rtems/itron/port.inl
new file mode 100644
index 0000000000..a80000c00c
--- /dev/null
+++ b/cpukit/itron/inline/rtems/itron/port.inl
@@ -0,0 +1,151 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_PORT_inl_
+#define __ITRON_PORT_inl_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * _ITRON_Port_Allocate
+ *
+ * DESCRIPTION:
+ *
+ * This routine allocates the port associated with the specified
+ * port ID from the pool of inactive ports.
+ *
+ * Input parameters:
+ * porid - id of port to allocate
+ * status - pointer to status variable
+ *
+ * Output parameters:
+ * returns - pointer to the port control block
+ * *status - status
+ */
+
+RTEMS_INLINE_ROUTINE ITRON_Port_Control *_ITRON_Port_Allocate(
+ ID porid
+)
+{
+ return (ITRON_Port_Control *)_ITRON_Objects_Allocate_by_index(
+ &_ITRON_Port_Information,
+ porid,
+ sizeof(ITRON_Port_Control)
+ );
+}
+
+/*
+ * _ITRON_Port_Clarify_allocation_id_error
+ *
+ * This function is invoked when an object allocation ID error
+ * occurs to determine the specific ITRON error code to return.
+ */
+
+#define _ITRON_Port_Clarify_allocation_id_error( _id ) \
+ _ITRON_Objects_Clarify_allocation_id_error( \
+ &_ITRON_Port_Information, (_id) )
+
+/*
+ * _ITRON_Port_Clarify_get_id_error
+ *
+ * This function is invoked when an object get ID error
+ * occurs to determine the specific ITRON error code to return.
+ */
+
+#define _ITRON_Port_Clarify_get_id_error( _id ) \
+ _ITRON_Objects_Clarify_get_id_error( &_ITRON_Port_Information, (_id) )
+
+/*
+ * _ITRON_Port_Free
+ *
+ * DESCRIPTION:
+ *
+ * This routine frees a port control block to the
+ * inactive chain of free port control blocks.
+ *
+ * Input parameters:
+ * the_port - pointer to port control block
+ *
+ * Output parameters: NONE
+ */
+
+RTEMS_INLINE_ROUTINE void _ITRON_Port_Free (
+ ITRON_Port_Control *the_port
+)
+{
+ _ITRON_Objects_Free( &_ITRON_Port_Information, &the_port->Object );
+}
+
+/*PAGE
+ *
+ * _ITRON_Port_Get
+ *
+ * DESCRIPTION:
+ *
+ * This function maps port IDs to port control blocks.
+ * If ID corresponds to a local port, then it returns
+ * the_port control pointer which maps to ID and location
+ * is set to OBJECTS_LOCAL. if the port ID is global and
+ * resides on a remote node, then location is set to OBJECTS_REMOTE,
+ * and the_port is undefined. Otherwise, location is set
+ * to OBJECTS_ERROR and the_port is undefined.
+ *
+ * Input parameters:
+ * id - ITRON port ID.
+ * the_location - pointer to a location variable
+ *
+ * Output parameters:
+ * *the_location - location of the object
+ */
+
+RTEMS_INLINE_ROUTINE ITRON_Port_Control *_ITRON_Port_Get (
+ ID id,
+ Objects_Locations *location
+)
+{
+ return (ITRON_Port_Control *)
+ _ITRON_Objects_Get( &_ITRON_Port_Information, id, location );
+}
+
+/*PAGE
+ *
+ * _ITRON_Port_Is_null
+ *
+ * This function returns TRUE if the_port is NULL and FALSE otherwise.
+ *
+ * Input parameters:
+ * the_port - pointer to port control block
+ *
+ * Output parameters:
+ * TRUE - if the_port is NULL
+ * FALSE - otherwise
+ */
+
+RTEMS_INLINE_ROUTINE boolean _ITRON_Port_Is_null (
+ ITRON_Port_Control *the_port
+)
+{
+ return ( the_port == NULL );
+}
+
+/*
+ * XXX insert inline routines here
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/itron/inline/rtems/itron/semaphore.inl b/cpukit/itron/inline/rtems/itron/semaphore.inl
new file mode 100644
index 0000000000..97c58e48a4
--- /dev/null
+++ b/cpukit/itron/inline/rtems/itron/semaphore.inl
@@ -0,0 +1,183 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_SEMAPHORE_inl_
+#define __ITRON_SEMAPHORE_inl_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * _ITRON_Semaphore_Allocate
+ *
+ * DESCRIPTION:
+ *
+ * This routine allocates the semaphore associated with the specified
+ * semaphore ID from the pool of inactive semaphores.
+ *
+ * Input parameters:
+ * semid - id of semaphore to allocate
+ * status - pointer to status variable
+ *
+ * Output parameters:
+ * returns - pointer to the semaphore control block
+ * *status - status
+ */
+
+RTEMS_INLINE_ROUTINE ITRON_Semaphore_Control *_ITRON_Semaphore_Allocate(
+ ID semid
+)
+{
+ return (ITRON_Semaphore_Control *)_ITRON_Objects_Allocate_by_index(
+ &_ITRON_Semaphore_Information,
+ semid,
+ sizeof(ITRON_Semaphore_Control)
+ );
+}
+
+/*
+ * _ITRON_Semaphore_Clarify_allocation_id_error
+ *
+ * This function is invoked when an object allocation ID error
+ * occurs to determine the specific ITRON error code to return.
+ */
+
+#define _ITRON_Semaphore_Clarify_allocation_id_error( _id ) \
+ _ITRON_Objects_Clarify_allocation_id_error( \
+ &_ITRON_Semaphore_Information, (_id) )
+
+/*
+ * _ITRON_Semaphore_Clarify_get_id_error
+ *
+ * This function is invoked when an object get ID error
+ * occurs to determine the specific ITRON error code to return.
+ */
+
+#define _ITRON_Semaphore_Clarify_get_id_error( _id ) \
+ _ITRON_Objects_Clarify_get_id_error( &_ITRON_Semaphore_Information, (_id) )
+
+/*
+ * _ITRON_Semaphore_Free
+ *
+ * DESCRIPTION:
+ *
+ * This routine frees a semaphore control block to the
+ * inactive chain of free semaphore control blocks.
+ *
+ * Input parameters:
+ * the_semaphore - pointer to semaphore control block
+ *
+ * Output parameters: NONE
+ */
+
+RTEMS_INLINE_ROUTINE void _ITRON_Semaphore_Free (
+ ITRON_Semaphore_Control *the_semaphore
+)
+{
+ _ITRON_Objects_Free( &_ITRON_Semaphore_Information, &the_semaphore->Object );
+}
+
+/*PAGE
+ *
+ * _ITRON_Semaphore_Get
+ *
+ * DESCRIPTION:
+ *
+ * This function maps semaphore IDs to semaphore control blocks.
+ * If ID corresponds to a local semaphore, then it returns
+ * the_semaphore control pointer which maps to ID and location
+ * is set to OBJECTS_LOCAL. if the semaphore ID is global and
+ * resides on a remote node, then location is set to OBJECTS_REMOTE,
+ * and the_semaphore is undefined. Otherwise, location is set
+ * to OBJECTS_ERROR and the_semaphore is undefined.
+ *
+ * Input parameters:
+ * id - ITRON semaphore ID.
+ * the_location - pointer to a location variable
+ *
+ * Output parameters:
+ * *the_location - location of the object
+ */
+
+RTEMS_INLINE_ROUTINE ITRON_Semaphore_Control *_ITRON_Semaphore_Get (
+ ID id,
+ Objects_Locations *location
+)
+{
+ return (ITRON_Semaphore_Control *)
+ _ITRON_Objects_Get( &_ITRON_Semaphore_Information, id, location );
+}
+
+/*PAGE
+ *
+ * _ITRON_Semaphore_Is_null
+ *
+ * This function returns TRUE if the_semaphore is NULL and FALSE otherwise.
+ *
+ * Input parameters:
+ * the_semaphore - pointer to semaphore control block
+ *
+ * Output parameters:
+ * TRUE - if the_semaphore is NULL
+ * FALSE - otherwise
+ */
+
+RTEMS_INLINE_ROUTINE boolean _ITRON_Semaphore_Is_null (
+ ITRON_Semaphore_Control *the_semaphore
+)
+{
+ return ( the_semaphore == NULL );
+}
+
+/*
+ * _ITRON_Semaphore_Translate_core_semaphore_return_code
+ *
+ * This function returns a ITRON status code based on the semaphore
+ * status code specified.
+ *
+ * Input parameters:
+ * the_semaphore_status - semaphore status code to translate
+ *
+ * Output parameters:
+ * ITRON status code - translated ITRON status code
+ *
+ */
+
+RTEMS_INLINE_ROUTINE ER _ITRON_Semaphore_Translate_core_semaphore_return_code (
+ uint32_t the_semaphore_status
+)
+{
+/* XXX need to be able to return "E_RLWAI" */
+ switch ( the_semaphore_status ) {
+ case CORE_SEMAPHORE_STATUS_SUCCESSFUL:
+ return E_OK;
+ case CORE_SEMAPHORE_STATUS_UNSATISFIED_NOWAIT:
+ return E_TMOUT;
+ case CORE_SEMAPHORE_WAS_DELETED:
+ return E_DLT;
+ case CORE_SEMAPHORE_TIMEOUT:
+ return E_TMOUT;
+ case CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED:
+ return E_QOVR;
+ case THREAD_STATUS_PROXY_BLOCKING:
+ return THREAD_STATUS_PROXY_BLOCKING;
+ }
+ return E_OK; /* unreached - only to remove warnings */
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/itron/inline/rtems/itron/sysmgmt.inl b/cpukit/itron/inline/rtems/itron/sysmgmt.inl
new file mode 100644
index 0000000000..da04d0352d
--- /dev/null
+++ b/cpukit/itron/inline/rtems/itron/sysmgmt.inl
@@ -0,0 +1,30 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_TIME_inl_
+#define __ITRON_TIME_inl_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * XXX insert inline routines here
+ */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/itron/inline/rtems/itron/task.inl b/cpukit/itron/inline/rtems/itron/task.inl
new file mode 100644
index 0000000000..cc8cc4a222
--- /dev/null
+++ b/cpukit/itron/inline/rtems/itron/task.inl
@@ -0,0 +1,181 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_TASK_inl_
+#define __ITRON_TASK_inl_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * _ITRON_Task_Allocate
+ *
+ * DESCRIPTION:
+ *
+ * This routine allocates the task associated with the specified
+ * task ID from the pool of inactive tasks.
+ *
+ * Input parameters:
+ * tskid - id of task to allocate
+ * status - pointer to status variable
+ *
+ * Output parameters:
+ * returns - pointer to the task control block
+ * *status - status
+ */
+
+RTEMS_INLINE_ROUTINE Thread_Control *_ITRON_Task_Allocate(
+ ID tskid
+)
+{
+ return (Thread_Control *)_ITRON_Objects_Allocate_by_index(
+ &_ITRON_Task_Information,
+ tskid,
+ sizeof(Thread_Control)
+ );
+}
+
+/*
+ * _ITRON_Task_Clarify_allocation_id_error
+ *
+ * This function is invoked when an object allocation ID error
+ * occurs to determine the specific ITRON error code to return.
+ */
+
+#define _ITRON_Task_Clarify_allocation_id_error( _id ) \
+ _ITRON_Objects_Clarify_allocation_id_error( \
+ &_ITRON_Task_Information, (_id) )
+
+/*
+ * _ITRON_Task_Clarify_get_id_error
+ *
+ * This function is invoked when an object get ID error
+ * occurs to determine the specific ITRON error code to return.
+ */
+
+#define _ITRON_Task_Clarify_get_id_error( _id ) \
+ _ITRON_Objects_Clarify_get_id_error( &_ITRON_Task_Information, (_id) )
+
+/*
+ * _ITRON_Task_Free
+ *
+ * DESCRIPTION:
+ *
+ * This routine frees a task control block to the
+ * inactive chain of free task control blocks.
+ *
+ * Input parameters:
+ * the_task - pointer to task control block
+ *
+ * Output parameters: NONE
+ */
+
+RTEMS_INLINE_ROUTINE void _ITRON_Task_Free (
+ Thread_Control *the_task
+)
+{
+ _ITRON_Objects_Free( &_ITRON_Task_Information, &the_task->Object );
+}
+
+/*PAGE
+ *
+ * _ITRON_Task_Get
+ *
+ * DESCRIPTION:
+ *
+ * This function maps task IDs to task control blocks.
+ * If ID corresponds to a local task, then it returns
+ * the_task control pointer which maps to ID and location
+ * is set to OBJECTS_LOCAL. if the task ID is global and
+ * resides on a remote node, then location is set to OBJECTS_REMOTE,
+ * and the_task is undefined. Otherwise, location is set
+ * to OBJECTS_ERROR and the_task is undefined.
+ *
+ * Input parameters:
+ * id - ITRON task ID.
+ * the_location - pointer to a location variable
+ *
+ * Output parameters:
+ * *the_location - location of the object
+ */
+
+RTEMS_INLINE_ROUTINE Thread_Control *_ITRON_Task_Get (
+ ID id,
+ Objects_Locations *location
+)
+{
+ if ( id == 0 ) {
+ _Thread_Disable_dispatch();
+ *location = OBJECTS_LOCAL;
+ return _Thread_Executing;
+ }
+
+ return (Thread_Control *)
+ _ITRON_Objects_Get( &_ITRON_Task_Information, id, location );
+}
+
+/*PAGE
+ *
+ * _ITRON_Task_Is_null
+ *
+ * This function returns TRUE if the_task is NULL and FALSE otherwise.
+ *
+ * Input parameters:
+ * the_task - pointer to task control block
+ *
+ * Output parameters:
+ * TRUE - if the_task is NULL
+ * FALSE - otherwise
+ */
+
+RTEMS_INLINE_ROUTINE boolean _ITRON_Task_Is_null (
+ Thread_Control *the_task
+)
+{
+ return ( the_task == NULL );
+}
+
+/*
+ * XXX insert inline routines here
+ */
+
+/*PAGE
+ *
+ * _ITRON_tasks_Priority_to_Core
+ */
+
+RTEMS_INLINE_ROUTINE _ITRON_Task_Priority_to_Core(
+ PRI ITRON_priority
+)
+{
+ return (Priority_Control) ITRON_priority;
+}
+
+/*PAGE
+ *
+ * _ITRON_tasks_Core_to_Priority
+ */
+
+RTEMS_INLINE_ROUTINE _ITRON_Task_Core_to_Priority(
+ Priority_Control core_priority
+)
+{
+ return (PRI) core_priority;
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/itron/inline/rtems/itron/time.inl b/cpukit/itron/inline/rtems/itron/time.inl
new file mode 100644
index 0000000000..da04d0352d
--- /dev/null
+++ b/cpukit/itron/inline/rtems/itron/time.inl
@@ -0,0 +1,30 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_TIME_inl_
+#define __ITRON_TIME_inl_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * XXX insert inline routines here
+ */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/itron/inline/rtems/itron/vmempool.inl b/cpukit/itron/inline/rtems/itron/vmempool.inl
new file mode 100644
index 0000000000..ef941cfc0d
--- /dev/null
+++ b/cpukit/itron/inline/rtems/itron/vmempool.inl
@@ -0,0 +1,161 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_VARIABLE_MEMORY_POOL_inl_
+#define __ITRON_VARIABLE_MEMORY_POOL_inl_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * _ITRON_Variable_memory_pool_Allocate
+ *
+ * DESCRIPTION:
+ *
+ * This routine allocates the variable memory pool associated with
+ * the specified variable memory pool ID from the pool of inactive
+ * variable memory pools.
+ *
+ * Input parameters:
+ * mplid - id of variable memory pool to allocate
+ * status - pointer to status variable
+ *
+ * Output parameters:
+ * returns - pointer to the variable memory pool control block
+ * *status - status
+ */
+
+RTEMS_INLINE_ROUTINE ITRON_Variable_memory_pool_Control
+ *_ITRON_Variable_memory_pool_Allocate(
+ ID mplid
+)
+{
+ return (ITRON_Variable_memory_pool_Control *)_ITRON_Objects_Allocate_by_index(
+ &_ITRON_Variable_memory_pool_Information,
+ mplid,
+ sizeof(ITRON_Variable_memory_pool_Control)
+ );
+}
+
+/*
+ * _ITRON_Variable_memory_pool_Clarify_allocation_id_error
+ *
+ * This function is invoked when an object allocation ID error
+ * occurs to determine the specific ITRON error code to return.
+ */
+
+#define _ITRON_Variable_memory_pool_Clarify_allocation_id_error( _id ) \
+ _ITRON_Objects_Clarify_allocation_id_error( \
+ &_ITRON_Variable_memory_pool_Information, (_id) )
+
+/*
+ * _ITRON_Variable_memory_pool_Clarify_get_id_error
+ *
+ * This function is invoked when an object get ID error
+ * occurs to determine the specific ITRON error code to return.
+ */
+
+#define _ITRON_Variable_memory_pool_Clarify_get_id_error( _id ) \
+ _ITRON_Objects_Clarify_get_id_error( &_ITRON_Variable_memory_pool_Information, (_id) )
+
+/*
+ * _ITRON_Variable_memory_pool_Free
+ *
+ * DESCRIPTION:
+ *
+ * This routine frees a variable memory pool control block to the
+ * inactive chain of free variable memory pool control blocks.
+ *
+ * Input parameters:
+ * the_variable_memory_pool - pointer to variable memory pool control block
+ *
+ * Output parameters: NONE
+ */
+
+RTEMS_INLINE_ROUTINE void _ITRON_Variable_memory_pool_Free (
+ ITRON_Variable_memory_pool_Control *the_variable_memory_pool
+)
+{
+ _ITRON_Objects_Free(
+ &_ITRON_Variable_memory_pool_Information,
+ &the_variable_memory_pool->Object
+ );
+}
+
+/*PAGE
+ *
+ * _ITRON_Variable_memory_pool_Get
+ *
+ * DESCRIPTION:
+ *
+ * This function maps variable memory pool IDs to variable memory pool
+ * control blocks. If ID corresponds to a local variable memory pool,
+ * then it returns the variable memory pool control pointer which maps
+ * to ID and location is set to OBJECTS_LOCAL. if the variable memory
+ * pool ID is global and resides on a remote node, then location is set
+ * to OBJECTS_REMOTE, and the variable memory pool is undefined. Otherwise,
+ * location is set to OBJECTS ERROR and the variable memory pool is undefined.
+ *
+ * Input parameters:
+ * id - ITRON variable memory pool ID.
+ * the_location - pointer to a location variable
+ *
+ * Output parameters:
+ * *the_location - location of the object
+ */
+
+RTEMS_INLINE_ROUTINE ITRON_Variable_memory_pool_Control
+ *_ITRON_Variable_memory_pool_Get (
+ ID id,
+ Objects_Locations *location
+)
+{
+ return (ITRON_Variable_memory_pool_Control *) _ITRON_Objects_Get(
+ &_ITRON_Variable_memory_pool_Information,
+ id,
+ location
+ );
+}
+
+/*PAGE
+ *
+ * _ITRON_Variable_memory_pool_Is_null
+ *
+ * This function returns TRUE if the_variable_memory_pool is NULL
+ * and FALSE otherwise.
+ *
+ * Input parameters:
+ * the_variable_memory_pool - pointer to variable memory pool control block
+ *
+ * Output parameters:
+ * TRUE - if the_variable_memory_pool is NULL
+ * FALSE - otherwise
+ */
+
+RTEMS_INLINE_ROUTINE boolean _ITRON_Variable_memory_pool_Is_null (
+ ITRON_Variable_memory_pool_Control *the_variable_memory_pool
+)
+{
+ return ( the_variable_memory_pool == NULL );
+}
+
+/*
+ * XXX insert inline routines here
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/itron/macros/rtems/itron/eventflags.inl b/cpukit/itron/macros/rtems/itron/eventflags.inl
new file mode 100644
index 0000000000..647d9855ab
--- /dev/null
+++ b/cpukit/itron/macros/rtems/itron/eventflags.inl
@@ -0,0 +1,76 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_EVENTFLAGS_inl_
+#define __ITRON_EVENTFLAGS_inl_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * _ITRON_Eventflags_Allocate
+ */
+
+#define _ITRON_Eventflags_Allocate( _flgid ) \
+ (ITRON_Eventflags_Control *)_ITRON_Objects_Allocate_by_index( \
+ &_ITRON_Eventflags_Information, \
+ (_flgid), \
+ sizeof(ITRON_Eventflags_Control) \
+ )
+
+/*
+ * _ITRON_Eventflags_Clarify_allocation_id_error
+ */
+
+#define _ITRON_Eventflags_Clarify_allocation_id_error( _id ) \
+ _ITRON_Objects_Clarify_allocation_id_error( \
+ &_ITRON_Eventflags_Information, (_id) )
+
+/*
+ * _ITRON_Eventflags_Clarify_get_id_error
+ */
+
+#define _ITRON_Eventflags_Clarify_get_id_error( _id ) \
+ _ITRON_Objects_Clarify_get_id_error( &_ITRON_Eventflags_Information, (_id) )
+
+/*
+ * _ITRON_Eventflags_Free
+ */
+
+#define _ITRON_Eventflags_Free( _the_eventflags ) \
+ _ITRON_Objects_Free( &_ITRON_Eventflags_Information, \
+ &(_the_eventflags)->Object )
+
+
+/*
+ * _ITRON_Eventflags_Get
+ */
+
+#define _ITRON_Eventflags_Get( _id, _location ) \
+ (ITRON_Eventflags_Control *) \
+ _ITRON_Objects_Get( &_ITRON_Eventflags_Information, (_id), (_location) )
+
+/*PAGE
+ *
+ * _ITRON_Eventflags_Is_null
+ */
+
+#define _ITRON_Eventflags_Is_null( _the_eventflags ) \
+ ( (_the_eventflags) == NULL );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/itron/macros/rtems/itron/fmempool.inl b/cpukit/itron/macros/rtems/itron/fmempool.inl
new file mode 100644
index 0000000000..2e313e6d0b
--- /dev/null
+++ b/cpukit/itron/macros/rtems/itron/fmempool.inl
@@ -0,0 +1,78 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_FIXED_MEMORY_POOL_inl_
+#define __ITRON_FIXED_MEMORY_POOL_inl_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * _ITRON_Fixed_memory_pool_Allocate
+ */
+
+#define _ITRON_Fixed_memory_pool_Allocate( _mpfid ) \
+ (ITRON_Fixed_memory_pool_Control *)_ITRON_Objects_Allocate_by_index( \
+ &_ITRON_Fixed_memory_pool_Information, \
+ (_mpfid), \
+ sizeof(ITRON_Fixed_memory_pool_Control) \
+ )
+
+/*
+ * _ITRON_Fixed_memory_pool_Clarify_allocation_id_error
+ */
+
+#define _ITRON_Fixed_memory_pool_Clarify_allocation_id_error( _id ) \
+ _ITRON_Objects_Clarify_allocation_id_error( \
+ &_ITRON_Fixed_memory_pool_Information, (_id) )
+
+/*
+ * _ITRON_Fixed_memory_pool_Clarify_get_id_error
+ */
+
+#define _ITRON_Fixed_memory_pool_Clarify_get_id_error( _id ) \
+ _ITRON_Objects_Clarify_get_id_error( \
+ &_ITRON_Fixed_memory_pool_Information, (_id) )
+
+/*
+ * _ITRON_Fixed_memory_pool_Free
+ */
+
+#define _ITRON_Fixed_memory_pool_Free( _the_fixed_memory_pool ) \
+ _ITRON_Objects_Free( \
+ &_ITRON_Fixed_memory_pool_Information, \
+ &(_the_fixed_memory_pool)->Object \
+ )
+
+/*
+ * _ITRON_Fixed_memory_pool_Get
+ */
+
+#define _ITRON_Fixed_memory_pool_Get( _id, _location ) \
+ (ITRON_Fixed_memory_pool_Control *) \
+ _ITRON_Objects_Get( &_ITRON_Fixed_memory_pool_Information, \
+ (_id), (_location) )
+
+/*
+ * _ITRON_Fixed_memory_pool_Is_null
+ */
+
+#define _ITRON_Fixed_memory_pool_Is_null( _the_fixed_memory_pool ) \
+ ( (_the_fixed_memory_pool) == NULL )
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/itron/macros/rtems/itron/intr.inl b/cpukit/itron/macros/rtems/itron/intr.inl
new file mode 100644
index 0000000000..e85bea259f
--- /dev/null
+++ b/cpukit/itron/macros/rtems/itron/intr.inl
@@ -0,0 +1,30 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_INTERRUPT_inl_
+#define __ITRON_INTERRUPT_inl_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * XXX insert inline routines here
+ */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/itron/macros/rtems/itron/mbox.inl b/cpukit/itron/macros/rtems/itron/mbox.inl
new file mode 100644
index 0000000000..d9aff14f7d
--- /dev/null
+++ b/cpukit/itron/macros/rtems/itron/mbox.inl
@@ -0,0 +1,75 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_MAILBOX_inl_
+#define __ITRON_MAILBOX_inl_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * _ITRON_Mailbox_Allocate
+ */
+
+#define _ITRON_Mailbox_Allocate( _mbxid ) \
+ (ITRON_Mailbox_Control *)_ITRON_Objects_Allocate_by_index( \
+ &_ITRON_Mailbox_Information, \
+ (_mbxid), \
+ sizeof(ITRON_Mailbox_Control) \
+ )
+
+/*
+ * _ITRON_Mailbox_Clarify_allocation_id_error
+ */
+
+#define _ITRON_Mailbox_Clarify_allocation_id_error( _id ) \
+ _ITRON_Objects_Clarify_allocation_id_error( \
+ &_ITRON_Mailbox_Information, (_id) )
+
+/*
+ * _ITRON_Mailbox_Clarify_get_id_error
+ */
+
+#define _ITRON_Mailbox_Clarify_get_id_error( _id ) \
+ _ITRON_Objects_Clarify_get_id_error( &_ITRON_Mailbox_Information, (_id) )
+
+/*
+ * _ITRON_Mailbox_Free
+ */
+
+#define _ITRON_Mailbox_Free( _the_mailbox ) \
+ _ITRON_Objects_Free( &_ITRON_Mailbox_Information, &(_the_mailbox)->Object )
+
+/*PAGE
+ *
+ * _ITRON_Mailbox_Get
+ */
+
+#define _ITRON_Mailbox_Get( _id, _location ) \
+ (ITRON_Mailbox_Control *) \
+ _ITRON_Objects_Get( &_ITRON_Mailbox_Information, (_id), (_location) )
+
+/*PAGE
+ *
+ * _ITRON_Mailbox_Is_null
+ */
+
+#define _ITRON_Mailbox_Is_null( _the_mailbox ) \
+ ( (_the_mailbox) == NULL )
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/itron/macros/rtems/itron/msgbuffer.inl b/cpukit/itron/macros/rtems/itron/msgbuffer.inl
new file mode 100644
index 0000000000..39a3b164ee
--- /dev/null
+++ b/cpukit/itron/macros/rtems/itron/msgbuffer.inl
@@ -0,0 +1,78 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_MESSAGE_BUFFER_inl_
+#define __ITRON_MESSAGE_BUFFER_inl_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * _ITRON_Message_buffer_Allocate
+ */
+
+#define _ITRON_Message_buffer_Allocate( _mbfid ) \
+ (ITRON_Message_buffer_Control *)_ITRON_Objects_Allocate_by_index( \
+ &_ITRON_Message_buffer_Information, \
+ (_mbfid), \
+ sizeof(ITRON_Message_buffer_Control) \
+ )
+
+/*
+ * _ITRON_Message_buffer_Clarify_allocation_id_error
+ */
+
+#define _ITRON_Message_buffer_Clarify_allocation_id_error( _id ) \
+ _ITRON_Objects_Clarify_allocation_id_error( \
+ &_ITRON_Message_buffer_Information, (_id) )
+
+/*
+ * _ITRON_Message_buffer_Clarify_get_id_error
+ */
+
+#define _ITRON_Message_buffer_Clarify_get_id_error( _id ) \
+ _ITRON_Objects_Clarify_get_id_error( &_ITRON_Message_buffer_Information, (_id) )
+
+/*
+ * _ITRON_Message_buffer_Free
+ */
+
+#define _ITRON_Message_buffer_Free( _the_message_buffer ) \
+ _ITRON_Objects_Free( \
+ &_ITRON_Message_buffer_Information, \
+ &(_the_message_buffer)->Object \
+ )
+
+/*PAGE
+ *
+ * _ITRON_Message_buffer_Get
+ */
+
+#define _ITRON_Message_buffer_Get( _id, _location ) \
+ (ITRON_Message_buffer_Control *) \
+ _ITRON_Objects_Get( &_ITRON_Message_buffer_Information, (_id), (_location) )
+
+/*PAGE
+ *
+ * _ITRON_Message_buffer_Is_null
+ */
+
+#define _ITRON_Message_buffer_Is_null( _the_message_buffer ) \
+ ( (_the_message_buffer) == NULL )
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/itron/macros/rtems/itron/network.inl b/cpukit/itron/macros/rtems/itron/network.inl
new file mode 100644
index 0000000000..3b46855c55
--- /dev/null
+++ b/cpukit/itron/macros/rtems/itron/network.inl
@@ -0,0 +1,30 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_NETWORK_inl_
+#define __ITRON_NETWORK_inl_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * XXX insert inline routines here
+ */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/itron/macros/rtems/itron/port.inl b/cpukit/itron/macros/rtems/itron/port.inl
new file mode 100644
index 0000000000..70cd1c8550
--- /dev/null
+++ b/cpukit/itron/macros/rtems/itron/port.inl
@@ -0,0 +1,75 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_PORT_inl_
+#define __ITRON_PORT_inl_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * _ITRON_Port_Allocate
+ */
+
+#define _ITRON_Port_Allocate( _porid ) \
+ (ITRON_Port_Control *)_ITRON_Objects_Allocate_by_index( \
+ &_ITRON_Port_Information, \
+ (_porid), \
+ sizeof(ITRON_Port_Control) \
+ )
+
+/*
+ * _ITRON_Port_Clarify_allocation_id_error
+ */
+
+#define _ITRON_Port_Clarify_allocation_id_error( _id ) \
+ _ITRON_Objects_Clarify_allocation_id_error( \
+ &_ITRON_Port_Information, (_id) )
+
+/*
+ * _ITRON_Port_Clarify_get_id_error
+ */
+
+#define _ITRON_Port_Clarify_get_id_error( _id ) \
+ _ITRON_Objects_Clarify_get_id_error( &_ITRON_Port_Information, (_id) )
+
+/*
+ * _ITRON_Port_Free
+ */
+
+#define _ITRON_Port_Free( _the_port ) \
+ _ITRON_Objects_Free( &_ITRON_Port_Information, &(_the_port)->Object )
+
+/*PAGE
+ *
+ * _ITRON_Port_Get
+ */
+
+#define _ITRON_Port_Get( _id, _location ) \
+ (ITRON_Port_Control *) \
+ _ITRON_Objects_Get( &_ITRON_Port_Information, (_id), (_location) )
+
+/*PAGE
+ *
+ * _ITRON_Port_Is_null
+ */
+
+#define _ITRON_Port_Is_null( _the_port ) \
+ ( (_the_port) == NULL )
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/itron/macros/rtems/itron/semaphore.inl b/cpukit/itron/macros/rtems/itron/semaphore.inl
new file mode 100644
index 0000000000..05c4c9840e
--- /dev/null
+++ b/cpukit/itron/macros/rtems/itron/semaphore.inl
@@ -0,0 +1,102 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_SEMAPHORE_inl_
+#define __ITRON_SEMAPHORE_inl_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * _ITRON_Semaphore_Allocate
+ */
+
+#define _ITRON_Semaphore_Allocate( _semid ) \
+ (ITRON_Semaphore_Control *)_ITRON_Objects_Allocate_by_index( \
+ &_ITRON_Semaphore_Information, \
+ (_semid), \
+ sizeof(ITRON_Semaphore_Control) \
+ )
+
+/*
+ * _ITRON_Semaphore_Clarify_allocation_id_error
+ */
+
+#define _ITRON_Semaphore_Clarify_allocation_id_error( _id ) \
+ _ITRON_Objects_Clarify_allocation_id_error( \
+ &_ITRON_Semaphore_Information, (_id) )
+
+/*
+ * _ITRON_Semaphore_Clarify_get_id_error
+ */
+
+#define _ITRON_Semaphore_Clarify_get_id_error( _id ) \
+ _ITRON_Objects_Clarify_get_id_error( &_ITRON_Semaphore_Information, (_id) )
+
+/*
+ * _ITRON_Semaphore_Free
+ */
+
+#define _ITRON_Semaphore_Free( _the_semaphore ) \
+ _ITRON_Objects_Free( &_ITRON_Semaphore_Information, &(_the_semaphore)->Object )
+
+/*PAGE
+ *
+ * _ITRON_Semaphore_Get
+ */
+
+#define _ITRON_Semaphore_Get( _id, _location ) \
+ (ITRON_Semaphore_Control *) \
+ _ITRON_Objects_Get( &_ITRON_Semaphore_Information, (_id), (_location) )
+
+/*PAGE
+ *
+ * _ITRON_Semaphore_Is_null
+ */
+
+#define _ITRON_Semaphore_Is_null( _the_semaphore ) \
+ ( (_the_semaphore) == NULL )
+
+/*
+ * _ITRON_Semaphore_Translate_core_semaphore_return_code
+ */
+
+/* XXX fix me */
+static ER _ITRON_Semaphore_Translate_core_semaphore_return_code (
+ uint32_t the_semaphore_status
+)
+{
+/* XXX need to be able to return "E_RLWAI" */
+ switch ( the_semaphore_status ) {
+ case CORE_SEMAPHORE_STATUS_SUCCESSFUL:
+ return E_OK;
+ case CORE_SEMAPHORE_STATUS_UNSATISFIED_NOWAIT:
+ return E_TMOUT;
+ case CORE_SEMAPHORE_WAS_DELETED:
+ return E_DLT;
+ case CORE_SEMAPHORE_TIMEOUT:
+ return E_TMOUT;
+ case CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED:
+ return E_QOVR;
+ case THREAD_STATUS_PROXY_BLOCKING:
+ return THREAD_STATUS_PROXY_BLOCKING;
+ }
+ return E_OK; /* unreached - only to remove warnings */
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/itron/macros/rtems/itron/sysmgmt.inl b/cpukit/itron/macros/rtems/itron/sysmgmt.inl
new file mode 100644
index 0000000000..da04d0352d
--- /dev/null
+++ b/cpukit/itron/macros/rtems/itron/sysmgmt.inl
@@ -0,0 +1,30 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_TIME_inl_
+#define __ITRON_TIME_inl_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * XXX insert inline routines here
+ */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/itron/macros/rtems/itron/task.inl b/cpukit/itron/macros/rtems/itron/task.inl
new file mode 100644
index 0000000000..90444102db
--- /dev/null
+++ b/cpukit/itron/macros/rtems/itron/task.inl
@@ -0,0 +1,102 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_TASK_inl_
+#define __ITRON_TASK_inl_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * _ITRON_Task_Allocate
+ */
+
+#define _ITRON_Task_Allocate( _tskid ) \
+ (Thread_Control *)_ITRON_Objects_Allocate_by_index( \
+ &_ITRON_Task_Information, \
+ (_tskid), \
+ sizeof(Thread_Control) \
+ )
+
+/*
+ * _ITRON_Task_Clarify_allocation_id_error
+ */
+
+#define _ITRON_Task_Clarify_allocation_id_error( _id ) \
+ _ITRON_Objects_Clarify_allocation_id_error( \
+ &_ITRON_Task_Information, (_id) )
+
+/*
+ * _ITRON_Task_Clarify_get_id_error
+ */
+
+#define _ITRON_Task_Clarify_get_id_error( _id ) \
+ _ITRON_Objects_Clarify_get_id_error( &_ITRON_Task_Information, (_id) )
+
+/*
+ * _ITRON_Task_Free
+ */
+
+#define _ITRON_Task_Free( _the_task ) \
+ _ITRON_Objects_Free( &_ITRON_Task_Information, &(_the_task)->Object )
+
+/*PAGE
+ *
+ * _ITRON_Task_Get
+ */
+
+/* XXX fix me */
+static Thread_Control *_ITRON_Task_Get (
+ ID id,
+ Objects_Locations *location
+)
+{
+ if ( id == 0 ) {
+ _Thread_Disable_dispatch();
+ *location = OBJECTS_LOCAL;
+ return _Thread_Executing;
+ }
+
+ return (Thread_Control *)
+ _ITRON_Objects_Get( &_ITRON_Task_Information, id, location );
+}
+
+/*PAGE
+ *
+ * _ITRON_Task_Is_null
+ */
+
+#define _ITRON_Task_Is_null( _the_task ) \
+ ( (_the_task) == NULL )
+
+/*PAGE
+ *
+ * _ITRON_tasks_Priority_to_Core
+ */
+
+#define _ITRON_Task_Priority_to_Core( _ITRON_priority ) \
+ ((Priority_Control) (_ITRON_priority))
+
+/*PAGE
+ *
+ * _ITRON_tasks_Core_to_Priority
+ */
+
+#define _ITRON_Task_Core_to_Priority( _core_priority ) \
+ ((PRI) (_core_priority))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/itron/macros/rtems/itron/time.inl b/cpukit/itron/macros/rtems/itron/time.inl
new file mode 100644
index 0000000000..da04d0352d
--- /dev/null
+++ b/cpukit/itron/macros/rtems/itron/time.inl
@@ -0,0 +1,30 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_TIME_inl_
+#define __ITRON_TIME_inl_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * XXX insert inline routines here
+ */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/itron/macros/rtems/itron/vmempool.inl b/cpukit/itron/macros/rtems/itron/vmempool.inl
new file mode 100644
index 0000000000..71a54b0e3e
--- /dev/null
+++ b/cpukit/itron/macros/rtems/itron/vmempool.inl
@@ -0,0 +1,81 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ITRON_VARIABLE_MEMORY_POOL_inl_
+#define __ITRON_VARIABLE_MEMORY_POOL_inl_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * _ITRON_Variable_memory_pool_Allocate
+ */
+
+#define _ITRON_Variable_memory_pool_Allocate( _mplid ) \
+ (ITRON_Variable_memory_pool_Control *)_ITRON_Objects_Allocate_by_index( \
+ &_ITRON_Variable_memory_pool_Information, \
+ (_mplid), \
+ sizeof(ITRON_Variable_memory_pool_Control) \
+ )
+
+/*
+ * _ITRON_Variable_memory_pool_Clarify_allocation_id_error
+ */
+
+#define _ITRON_Variable_memory_pool_Clarify_allocation_id_error( _id ) \
+ _ITRON_Objects_Clarify_allocation_id_error( \
+ &_ITRON_Variable_memory_pool_Information, (_id) )
+
+/*
+ * _ITRON_Variable_memory_pool_Clarify_get_id_error
+ */
+
+#define _ITRON_Variable_memory_pool_Clarify_get_id_error( _id ) \
+ _ITRON_Objects_Clarify_get_id_error( &_ITRON_Variable_memory_pool_Information, (_id) )
+
+/*
+ * _ITRON_Variable_memory_pool_Free
+ */
+
+#define _ITRON_Variable_memory_pool_Free( _the_variable_memory_pool ) \
+ _ITRON_Objects_Free( \
+ &_ITRON_Variable_memory_pool_Information, \
+ &(_the_variable_memory_pool)->Object \
+ )
+
+/*PAGE
+ *
+ * _ITRON_Variable_memory_pool_Get
+ */
+
+#define _ITRON_Variable_memory_pool_Get( _id, _location ) \
+ (ITRON_Variable_memory_pool_Control *) _ITRON_Objects_Get( \
+ &_ITRON_Variable_memory_pool_Information, \
+ (_id), \
+ (_location) \
+ )
+
+/*PAGE
+ *
+ * _ITRON_Variable_memory_pool_Is_null
+ */
+
+#define _ITRON_Variable_memory_pool_Is_null( _the_variable_memory_pool ) \
+ ( (_the_variable_memory_pool) == NULL )
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/itron/src/.cvsignore b/cpukit/itron/src/.cvsignore
new file mode 100644
index 0000000000..000074c626
--- /dev/null
+++ b/cpukit/itron/src/.cvsignore
@@ -0,0 +1,4 @@
+stamp-h
+stamp-h.in
+config.h
+config.h.in
diff --git a/cpukit/itron/src/TODO b/cpukit/itron/src/TODO
new file mode 100644
index 0000000000..8b87f58c8a
--- /dev/null
+++ b/cpukit/itron/src/TODO
@@ -0,0 +1,13 @@
+#
+# $Id$
+#
+
+The overall status including a major item todo list is in the Status
+chapter of the RTEMS ITRON API User's Guide. This file contains very
+short things that need to be addressed.
+
++ unlimited object not support for allocate by index. Support either
+ needs to be added for this type of object or the manager initialization
+ code needs to consider it a fatal error to configure the object class
+ in this mode.
+
diff --git a/cpukit/itron/src/can_wup.c b/cpukit/itron/src/can_wup.c
new file mode 100644
index 0000000000..4a7efc639d
--- /dev/null
+++ b/cpukit/itron/src/can_wup.c
@@ -0,0 +1,52 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/score/thread.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+#include <rtems/itron/task.h>
+
+/*
+ * can_wup - Cancel Wakeup Request
+ */
+
+ER can_wup(
+ INT *p_wupcnt,
+ ID tskid
+)
+{
+ register Thread_Control *the_thread;
+ Objects_Locations location;
+
+ the_thread = _ITRON_Task_Get( tskid, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE:
+ case OBJECTS_ERROR:
+ return _ITRON_Task_Clarify_get_id_error( tskid );
+
+ case OBJECTS_LOCAL:
+ /*
+ * XXX - FILL ME IN.
+ */
+ break;
+ }
+
+ _ITRON_return_errorno( E_OK );
+}
diff --git a/cpukit/itron/src/chg_pri.c b/cpukit/itron/src/chg_pri.c
new file mode 100644
index 0000000000..a548535db4
--- /dev/null
+++ b/cpukit/itron/src/chg_pri.c
@@ -0,0 +1,68 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/score/thread.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+#include <rtems/itron/task.h>
+
+/*
+ * chg_pri - Change Task Priority
+ */
+
+ER chg_pri(
+ ID tskid,
+ PRI tskpri
+)
+{
+ register Thread_Control *the_thread;
+ Objects_Locations location;
+ Priority_Control new_priority;
+
+ the_thread = _ITRON_Task_Get( tskid, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE:
+ case OBJECTS_ERROR:
+ return _ITRON_Task_Clarify_get_id_error( tskid );
+
+ case OBJECTS_LOCAL:
+ if (_States_Is_dormant( the_thread->current_state ))
+ _ITRON_return_errorno( E_OBJ );
+
+ if (( tskpri <= 0 ) || ( tskpri >= 256 ))
+ _ITRON_return_errorno( E_PAR );
+
+ new_priority = _ITRON_Task_Priority_to_Core( tskpri );
+ the_thread->real_priority = new_priority;
+
+ /*
+ * The priority should not be changed until later if priority
+ * inheratance has occured.
+ */
+
+ if ( the_thread->resource_count == 0 ||
+ the_thread->current_priority > new_priority )
+ _Thread_Change_priority( the_thread, new_priority, FALSE );
+
+ break;
+ }
+
+ _ITRON_return_errorno( E_OK );
+}
diff --git a/cpukit/itron/src/cre_mbf.c b/cpukit/itron/src/cre_mbf.c
new file mode 100644
index 0000000000..0275be2cc5
--- /dev/null
+++ b/cpukit/itron/src/cre_mbf.c
@@ -0,0 +1,89 @@
+/*
+ * ITRON Message Buffer Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/msgbuffer.h>
+#include <rtems/itron/task.h>
+
+/*
+ * cre_mbf - Create MessageBuffer
+ */
+
+ER cre_mbf(
+ ID mbfid,
+ T_CMBF *pk_cmbf
+)
+{
+ CORE_message_queue_Attributes the_msgq_attributes;
+ ITRON_Message_buffer_Control *the_message_buffer;
+
+ /*
+ * Bad pointer to the attributes structure
+ */
+
+ if ( !pk_cmbf )
+ return E_PAR;
+
+ /*
+ * Bits were set that were note defined.
+ */
+
+ if (pk_cmbf->mbfatr & ~(TA_TPRI))
+ return E_RSATR;
+
+ if (pk_cmbf->bufsz < 0 || pk_cmbf->maxmsz < 0)
+ return E_PAR;
+
+ if (pk_cmbf->bufsz < pk_cmbf->maxmsz)
+ return E_PAR;
+
+ _Thread_Disable_dispatch(); /* prevents deletion */
+
+ the_message_buffer = _ITRON_Message_buffer_Allocate(mbfid);
+ if ( !the_message_buffer ) {
+ _Thread_Enable_dispatch();
+ return _ITRON_Message_buffer_Clarify_allocation_id_error(mbfid);
+ }
+
+ if ( pk_cmbf->mbfatr & TA_TPRI )
+ the_msgq_attributes.discipline = CORE_MESSAGE_QUEUE_DISCIPLINES_PRIORITY;
+ else
+ the_msgq_attributes.discipline = CORE_MESSAGE_QUEUE_DISCIPLINES_FIFO;
+
+ _CORE_message_queue_Initialize(
+ &the_message_buffer->message_queue,
+ &the_msgq_attributes,
+ pk_cmbf->bufsz / pk_cmbf->maxmsz,
+ pk_cmbf->maxmsz
+ );
+
+ _ITRON_Objects_Open( &_ITRON_Message_buffer_Information,
+ &the_message_buffer->Object );
+
+ /*
+ * If multiprocessing were supported, this is where we would announce
+ * the existence of the semaphore to the rest of the system.
+ */
+
+#if defined(RTEMS_MULTIPROCESSING)
+#endif
+
+ _Thread_Enable_dispatch();
+
+ return E_OK;
+}
diff --git a/cpukit/itron/src/cre_mbx.c b/cpukit/itron/src/cre_mbx.c
new file mode 100644
index 0000000000..bc4d766814
--- /dev/null
+++ b/cpukit/itron/src/cre_mbx.c
@@ -0,0 +1,107 @@
+/*
+ * ITRON 3.0 Mailbox Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/mbox.h>
+#include <rtems/itron/task.h>
+
+/*
+ * cre_mbx - Create Mailbox
+ *
+ * Creates a Mailbox according to the following spec:
+ *
+ * ------Parameters-------------------------
+ * ID mbxid MailboxID
+ * T_CMBX *pk_cmbx Packet to Create Mailbox
+ * -----------------------------------------
+ * -*pk_cmbx members*-
+ * VP exinf ExtendedInformation
+ * ATR mbxatr MailboxAttributes
+ * (the use of the following information
+ * is implementation dependent)
+ * INT bufcnt BufferMessageCount
+ * (CPU and/or implementation-dependent information
+ * may also be included)
+ *
+ * ----Return Parameters--------------------
+ * ER ercd ErrorCode
+ * -----------------------------------------
+ *
+ *
+ * ----C Language Interface-----------------
+ * ER ercd = cre_mbx ( ID mbxid, T_CMBX *pk_cmbx ) ;
+ * -----------------------------------------
+ *
+ */
+
+ER cre_mbx(
+ ID mbxid,
+ T_CMBX *pk_cmbx
+)
+{
+ register ITRON_Mailbox_Control *the_mailbox;
+ CORE_message_queue_Attributes the_mailbox_attributes;
+
+ if ( !pk_cmbx )
+ return E_PAR;
+
+ if ((pk_cmbx->mbxatr & (TA_TPRI | TA_MPRI)) != 0 )
+ return E_RSATR;
+
+ _Thread_Disable_dispatch(); /* protects object pointer */
+
+ the_mailbox = _ITRON_Mailbox_Allocate( mbxid );
+ if ( !the_mailbox ) {
+ _Thread_Enable_dispatch();
+ return _ITRON_Mailbox_Clarify_allocation_id_error( mbxid );
+ }
+
+ the_mailbox->count = pk_cmbx->bufcnt;
+ if (pk_cmbx->mbxatr & TA_MPRI)
+ the_mailbox->do_message_priority = TRUE;
+ else
+ the_mailbox->do_message_priority = FALSE;
+
+ if (pk_cmbx->mbxatr & TA_TPRI)
+ the_mailbox_attributes.discipline = CORE_MESSAGE_QUEUE_DISCIPLINES_PRIORITY;
+ else
+ the_mailbox_attributes.discipline = CORE_MESSAGE_QUEUE_DISCIPLINES_FIFO;
+
+ if ( !_CORE_message_queue_Initialize(
+ &the_mailbox->message_queue,
+ OBJECTS_ITRON_MAILBOXES,
+ &the_mailbox_attributes,
+ the_mailbox->count,
+ sizeof(T_MSG *),
+ NULL ) ) { /* Multiprocessing not supported */
+ _ITRON_Mailbox_Free(the_mailbox);
+ _ITRON_return_errorno( E_OBJ );
+ }
+
+ _ITRON_Objects_Open( &_ITRON_Mailbox_Information, &the_mailbox->Object );
+
+ /*
+ * If multiprocessing were supported, this is where we would announce
+ * the existence of the semaphore to the rest of the system.
+ */
+
+#if defined(RTEMS_MULTIPROCESSING)
+#endif
+
+ _ITRON_return_errorno( E_OK );
+}
diff --git a/cpukit/itron/src/cre_sem.c b/cpukit/itron/src/cre_sem.c
new file mode 100644
index 0000000000..3e6e005728
--- /dev/null
+++ b/cpukit/itron/src/cre_sem.c
@@ -0,0 +1,98 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/semaphore.h>
+#include <rtems/itron/task.h>
+#include <rtems/score/tod.h>
+
+/*
+ * cre_sem - Create Semaphore
+ *
+ * This function implements the ITRON 3.0 cre_sem() service.
+ */
+
+ER cre_sem(
+ ID semid,
+ T_CSEM *pk_csem
+)
+{
+ CORE_semaphore_Attributes the_semaphore_attributes;
+ ITRON_Semaphore_Control *the_semaphore;
+
+ /*
+ * Bad pointer to the attributes structure
+ */
+
+ if ( !pk_csem )
+ return E_PAR;
+
+ /*
+ * Bits were set that were note defined.
+ */
+
+ if ( pk_csem->sematr & _ITRON_SEMAPHORE_UNUSED_ATTRIBUTES )
+ return E_RSATR;
+
+ /*
+ * Initial semaphore count exceeds the maximum.
+ */
+
+ if ( pk_csem->isemcnt > pk_csem->maxsem )
+ return E_PAR;
+
+ /*
+ * This error is not in the specification but this condition
+ * does not make sense.
+ */
+
+ if ( pk_csem->maxsem == 0 )
+ return E_PAR;
+
+ _Thread_Disable_dispatch(); /* prevents deletion */
+
+ the_semaphore = _ITRON_Semaphore_Allocate( semid );
+ if ( !the_semaphore ) {
+ _Thread_Enable_dispatch();
+ return _ITRON_Semaphore_Clarify_allocation_id_error( semid );
+ }
+
+ if ( pk_csem->sematr & TA_TPRI )
+ the_semaphore_attributes.discipline = CORE_SEMAPHORE_DISCIPLINES_PRIORITY;
+ else
+ the_semaphore_attributes.discipline = CORE_SEMAPHORE_DISCIPLINES_FIFO;
+
+ the_semaphore_attributes.maximum_count = pk_csem->maxsem;
+
+ _CORE_semaphore_Initialize(
+ &the_semaphore->semaphore,
+ &the_semaphore_attributes,
+ pk_csem->isemcnt
+ );
+
+ _ITRON_Objects_Open( &_ITRON_Semaphore_Information, &the_semaphore->Object );
+
+ /*
+ * If multiprocessing were supported, this is where we would announce
+ * the existence of the semaphore to the rest of the system.
+ */
+
+#if defined(RTEMS_MULTIPROCESSING)
+#endif
+
+ _Thread_Enable_dispatch();
+ return E_OK;
+}
diff --git a/cpukit/itron/src/cre_tsk.c b/cpukit/itron/src/cre_tsk.c
new file mode 100644
index 0000000000..85a24e52d9
--- /dev/null
+++ b/cpukit/itron/src/cre_tsk.c
@@ -0,0 +1,120 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/score/thread.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+#include <rtems/itron/task.h>
+
+
+/*
+ * cre_tsk - Create Task
+ */
+
+ER cre_tsk(
+ ID tskid,
+ T_CTSK *pk_ctsk
+)
+{
+ register Thread_Control *the_thread;
+ boolean status;
+ Priority_Control core_priority;
+
+ /*
+ * Validate Parameters.
+ */
+
+ if ( pk_ctsk == NULL )
+ return E_PAR;
+
+ if ((pk_ctsk->tskatr != TA_ASM ) &&
+ (pk_ctsk->tskatr != TA_HLNG) &&
+ (pk_ctsk->tskatr != TA_COP0) &&
+ (pk_ctsk->tskatr != TA_COP1) &&
+ (pk_ctsk->tskatr != TA_COP2) &&
+ (pk_ctsk->tskatr != TA_COP3) &&
+ (pk_ctsk->tskatr != TA_COP4) &&
+ (pk_ctsk->tskatr != TA_COP5) &&
+ (pk_ctsk->tskatr != TA_COP6) &&
+ (pk_ctsk->tskatr != TA_COP7))
+ return E_RSATR;
+
+ if (( pk_ctsk->itskpri <= 0 ) || ( pk_ctsk->itskpri >= 256 ))
+ return E_PAR;
+ if ( pk_ctsk->task == NULL )
+ return E_PAR;
+ if ( pk_ctsk->stksz < 0 )
+ return E_PAR;
+
+ /*
+ * Disable dispatching.
+ */
+
+ _Thread_Disable_dispatch();
+
+ /*
+ * allocate the thread.
+ */
+
+ the_thread = _ITRON_Task_Allocate( tskid );
+ if ( !the_thread )
+ _ITRON_return_errorno( _ITRON_Task_Clarify_allocation_id_error( tskid ) );
+
+ /*
+ * Initialize the core thread for this task.
+ */
+
+ core_priority = _ITRON_Task_Priority_to_Core( pk_ctsk->itskpri );
+ status = _Thread_Initialize(
+ &_ITRON_Task_Information,
+ the_thread,
+ NULL,
+ pk_ctsk->stksz,
+#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+ TRUE, /* XXX - All tasks FP (if the HW supports it) for now */
+#else
+ FALSE,
+#endif
+ core_priority,
+ TRUE, /* preemptible */
+ THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE,
+ NULL, /* no budget algorithm callout */
+ 0,
+ NULL
+ );
+
+ if ( !status ) {
+ _ITRON_Task_Free( the_thread );
+ _ITRON_return_errorno( E_NOMEM );
+ }
+
+ /*
+ * This insures we evaluate the process-wide signals pending when we
+ * first run.
+ *
+ * NOTE: Since the thread starts with all unblocked, this is necessary.
+ */
+
+ the_thread->do_post_task_switch_extension = TRUE;
+
+ the_thread->Start.entry_point = (Thread_Entry) pk_ctsk->task;
+
+ _ITRON_return_errorno( E_OK );
+}
diff --git a/cpukit/itron/src/del_mbf.c b/cpukit/itron/src/del_mbf.c
new file mode 100644
index 0000000000..0fea912942
--- /dev/null
+++ b/cpukit/itron/src/del_mbf.c
@@ -0,0 +1,58 @@
+/*
+ * ITRON Message Buffer Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/msgbuffer.h>
+#include <rtems/itron/task.h>
+
+/*
+ * del_mbf - Delete MessageBuffer
+ */
+
+ER del_mbf(
+ ID mbfid
+)
+{
+ ITRON_Message_buffer_Control *the_message_buffer;
+ Objects_Locations location;
+
+ the_message_buffer = _ITRON_Message_buffer_Get(mbfid, &location);
+ switch (location) {
+ case OBJECTS_REMOTE:
+ case OBJECTS_ERROR: /* Multiprocessing not supported */
+ return _ITRON_Message_buffer_Clarify_get_id_error(mbfid);
+
+ case OBJECTS_LOCAL:
+ _CORE_message_queue_Flush(&the_message_buffer->message_queue);
+ _ITRON_Objects_Close( &_ITRON_Message_buffer_Information,
+ &the_message_buffer->Object);
+ _ITRON_Message_buffer_Free(the_message_buffer);
+
+ /*
+ * If multiprocessing were supported, this is where we would announce
+ * the existence of the semaphore to the rest of the system.
+ */
+
+#if defined(RTEMS_MULTIPROCESSING)
+#endif
+ _Thread_Enable_dispatch();
+ return E_OK;
+ }
+
+ return E_OK;
+}
diff --git a/cpukit/itron/src/del_mbx.c b/cpukit/itron/src/del_mbx.c
new file mode 100644
index 0000000000..e06bea2fb5
--- /dev/null
+++ b/cpukit/itron/src/del_mbx.c
@@ -0,0 +1,68 @@
+/*
+ * ITRON 3.0 Mailbox Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/mbox.h>
+#include <rtems/itron/task.h>
+
+/*
+ * del_mbx - Delete Mailbox
+ *
+ *
+ * ------Parameters--------------
+ * ID mbxid The Mailbox's ID
+ * ------------------------------
+ *
+ * -----Return Parameters-------
+ * ER ercd Itron Error Code
+ * -----------------------------
+ *
+ * -----C Language Interface----
+ * ER ercd = del_mbx(ID mbxid);
+ * -----------------------------
+ *
+ */
+
+ER del_mbx(
+ ID mbxid
+)
+{
+ register ITRON_Mailbox_Control *the_mailbox;
+ Objects_Locations location;
+
+ the_mailbox= _ITRON_Mailbox_Get( mbxid, &location );
+ switch ( location ) {
+ case OBJECTS_ERROR:
+ case OBJECTS_REMOTE:
+ return _ITRON_Mailbox_Clarify_get_id_error( mbxid );
+
+ case OBJECTS_LOCAL:
+ _Objects_Close( &_ITRON_Mailbox_Information, &the_mailbox->Object );
+
+ _CORE_message_queue_Close(
+ &the_mailbox->message_queue,
+ NULL, /* Multiprocessing not supported */
+ CORE_MESSAGE_QUEUE_STATUS_WAS_DELETED
+ );
+
+ _ITRON_Mailbox_Free(the_mailbox);
+ break;
+ }
+
+ _ITRON_return_errorno( E_OK );
+}
diff --git a/cpukit/itron/src/del_sem.c b/cpukit/itron/src/del_sem.c
new file mode 100644
index 0000000000..94368c4a41
--- /dev/null
+++ b/cpukit/itron/src/del_sem.c
@@ -0,0 +1,68 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/semaphore.h>
+#include <rtems/itron/task.h>
+#include <rtems/score/tod.h>
+
+/*
+ * del_sem - Delete Semaphore
+ *
+ * This function implements the ITRON 3.0 del_sem() service.
+ */
+
+ER del_sem(
+ ID semid
+)
+{
+ ITRON_Semaphore_Control *the_semaphore;
+ Objects_Locations location;
+
+ the_semaphore = _ITRON_Semaphore_Get( semid, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE: /* Multiprocessing not supported */
+ case OBJECTS_ERROR:
+ return _ITRON_Semaphore_Clarify_get_id_error( semid );
+
+ case OBJECTS_LOCAL:
+ _CORE_semaphore_Flush(
+ &the_semaphore->semaphore,
+ NULL, /* Multiprocessing not supported */
+ CORE_SEMAPHORE_WAS_DELETED
+ );
+
+ _ITRON_Objects_Close(
+ &_ITRON_Semaphore_Information,
+ &the_semaphore->Object
+ );
+
+ _ITRON_Semaphore_Free( the_semaphore );
+
+ /*
+ * If multiprocessing were supported, this is where we would announce
+ * the destruction of the semaphore to the rest of the system.
+ */
+
+#if defined(RTEMS_MULTIPROCESSING)
+#endif
+
+ _Thread_Enable_dispatch();
+ return E_OK;
+
+ }
+ return E_OK;
+}
diff --git a/cpukit/itron/src/del_tsk.c b/cpukit/itron/src/del_tsk.c
new file mode 100644
index 0000000000..9d1ddb72b5
--- /dev/null
+++ b/cpukit/itron/src/del_tsk.c
@@ -0,0 +1,58 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/score/thread.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+#include <rtems/itron/task.h>
+
+
+/*
+ * del_tsk - Delete Task
+ */
+
+ER del_tsk(
+ ID tskid
+)
+{
+ register Thread_Control *the_thread;
+ Objects_Locations location;
+ ER result = E_OK; /* to avoid warning */
+
+ the_thread = _ITRON_Task_Get( tskid, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE:
+ case OBJECTS_ERROR:
+ return _ITRON_Task_Clarify_get_id_error( tskid );
+
+ case OBJECTS_LOCAL:
+
+ if ( _Thread_Is_executing( the_thread ) )
+ _ITRON_return_errorno( E_OBJ );
+
+ if ( !_States_Is_dormant( the_thread->current_state ) )
+ _ITRON_return_errorno( E_OBJ );
+
+ result = _ITRON_Delete_task( the_thread );
+ break;
+ }
+
+ _ITRON_return_errorno( result );
+}
diff --git a/cpukit/itron/src/dis_dsp.c b/cpukit/itron/src/dis_dsp.c
new file mode 100644
index 0000000000..0f1561abaa
--- /dev/null
+++ b/cpukit/itron/src/dis_dsp.c
@@ -0,0 +1,40 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/score/thread.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+#include <rtems/itron/task.h>
+
+
+/*
+ * dis_dsp - Disable Dispatch
+ */
+
+ER dis_dsp( void )
+{
+ /*
+ * Disable dispatch for protection
+ */
+
+ _Thread_Disable_dispatch();
+
+ return E_OK;
+}
diff --git a/cpukit/itron/src/ena_dsp.c b/cpukit/itron/src/ena_dsp.c
new file mode 100644
index 0000000000..da25d99206
--- /dev/null
+++ b/cpukit/itron/src/ena_dsp.c
@@ -0,0 +1,36 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/score/thread.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+#include <rtems/itron/task.h>
+
+
+/*
+ * ena_dsp - Enable Dispatch
+ */
+
+ER ena_dsp( void )
+{
+ _Thread_Enable_dispatch();
+
+ return E_OK;
+}
diff --git a/cpukit/itron/src/eventflags.c b/cpukit/itron/src/eventflags.c
new file mode 100644
index 0000000000..11039cc78d
--- /dev/null
+++ b/cpukit/itron/src/eventflags.c
@@ -0,0 +1,159 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/eventflags.h>
+
+/*
+ * _ITRON_Eventflags_Manager_initialization
+ *
+ * This routine initializes all event flags manager related data structures.
+ *
+ * Input parameters:
+ * maximum_eventflags - maximum configured eventflags
+ *
+ * Output parameters: NONE
+ */
+
+void _ITRON_Eventflags_Manager_initialization(
+ uint32_t maximum_eventflags
+)
+{
+ _Objects_Initialize_information(
+ &_ITRON_Eventflags_Information, /* object information table */
+ OBJECTS_ITRON_API, /* object API */
+ OBJECTS_ITRON_EVENTFLAGS, /* object class */
+ maximum_eventflags, /* maximum objects of this class */
+ sizeof( ITRON_Eventflags_Control ),
+ /* size of this object's control block */
+ FALSE, /* TRUE if names for this object are strings */
+ ITRON_MAXIMUM_NAME_LENGTH /* maximum length of each object's name */
+#if defined(RTEMS_MULTIPROCESSING)
+ ,
+ FALSE, /* TRUE if this is a global object class */
+ NULL /* Proxy extraction support callout */
+#endif
+ );
+
+ /*
+ * Register the MP Process Packet routine.
+ *
+ * NOTE: No MP Support YET in RTEMS ITRON implementation.
+ */
+
+}
+
+/*
+ * cre_flg - Create Eventflag
+ */
+
+ER cre_flg(
+ ID flgid,
+ T_CFLG *pk_cflg
+)
+{
+ return E_OK;
+}
+
+/*
+ * del_flg - Delete Eventflag
+ */
+
+ER del_flg(
+ ID flgid
+)
+{
+ return E_OK;
+}
+
+/*
+ * set_flg - Set Eventflag
+ */
+
+ER set_flg(
+ ID flgid,
+ UINT setptn
+)
+{
+ return E_OK;
+}
+
+/*
+ * clr_flg - Clear Eventflag
+ */
+
+ER clr_flg(
+ ID flgid,
+ UINT clrptn
+)
+{
+ return E_OK;
+}
+
+/*
+ * wai_flg - Wait on Eventflag
+ */
+
+ER wai_flg(
+ UINT *p_flgptn,
+ ID flgid,
+ UINT waiptn,
+ UINT wfmode
+)
+{
+ return E_OK;
+}
+
+/*
+ * pol_flg - Wait for Eventflag(Polling)
+ */
+
+ER pol_flg(
+ UINT *p_flgptn,
+ ID flgid,
+ UINT waiptn,
+ UINT wfmode
+)
+{
+ return E_OK;
+}
+
+/*
+ * twai_flg - Wait on Eventflag with Timeout
+ */
+
+ER twai_flg(
+ UINT *p_flgptn,
+ ID flgid,
+ UINT waiptn,
+ UINT wfmode,
+ TMO tmout
+)
+{
+ return E_OK;
+}
+
+/*
+ * ref_flg - Reference Eventflag Status
+ */
+
+ER ref_flg(
+ T_RFLG *pk_rflg,
+ ID flgid
+)
+{
+ return E_OK;
+}
diff --git a/cpukit/itron/src/exd_tsk.c b/cpukit/itron/src/exd_tsk.c
new file mode 100644
index 0000000000..c99282f4d8
--- /dev/null
+++ b/cpukit/itron/src/exd_tsk.c
@@ -0,0 +1,46 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+#include <assert.h>
+
+#include <rtems/score/thread.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+#include <rtems/itron/task.h>
+
+/*
+ * exd_tsk - Exit and Delete Task
+ */
+
+void exd_tsk( void )
+{
+ Objects_Information *the_information;
+
+ _Thread_Disable_dispatch();
+
+ the_information = _Objects_Get_information( _Thread_Executing->Object.id );
+
+ /* This should never happen if _Thread_Get() works right */
+ assert( the_information );
+
+ _Thread_Set_state( _Thread_Executing, STATES_DORMANT );
+ _ITRON_Delete_task( _Thread_Executing );
+
+ _Thread_Enable_dispatch();
+}
diff --git a/cpukit/itron/src/ext_tsk.c b/cpukit/itron/src/ext_tsk.c
new file mode 100644
index 0000000000..20b83ff471
--- /dev/null
+++ b/cpukit/itron/src/ext_tsk.c
@@ -0,0 +1,46 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/score/thread.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+#include <rtems/itron/task.h>
+
+
+/*
+ * ext_tsk - Exit Issuing Task
+ */
+
+void ext_tsk( void )
+{
+ /*
+ * Figure out what to do if this happens.
+ * We can not return regardless
+ if ( _ITRON_Is_in_non_task_state() )
+ return E_CTX;
+ */
+
+ _Thread_Disable_dispatch();
+
+ _Thread_Set_state( _Thread_Executing, STATES_DORMANT );
+ _Thread_Reset( _Thread_Executing, NULL, 0 );
+
+ _Thread_Enable_dispatch();
+}
diff --git a/cpukit/itron/src/fmempool.c b/cpukit/itron/src/fmempool.c
new file mode 100644
index 0000000000..567b7cb358
--- /dev/null
+++ b/cpukit/itron/src/fmempool.c
@@ -0,0 +1,142 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/fmempool.h>
+
+/*
+ * _ITRON_Fixed_memory_pool_Manager_initialization
+ *
+ * This routine initializes all fixed memory pool manager related
+ * data structures.
+ *
+ * Input parameters:
+ * maximum_fixed_memory_pools - maximum configured fixed memory pools
+ *
+ * Output parameters: NONE
+ */
+
+void _ITRON_Fixed_memory_pool_Manager_initialization(
+ uint32_t maximum_fixed_memory_pools
+)
+{
+ _Objects_Initialize_information(
+ &_ITRON_Fixed_memory_pool_Information, /* object information table */
+ OBJECTS_ITRON_API, /* object API */
+ OBJECTS_ITRON_FIXED_MEMORY_POOLS, /* object class */
+ maximum_fixed_memory_pools, /* maximum objects of this class */
+ sizeof( ITRON_Fixed_memory_pool_Control ),
+ /* size of this object's control block */
+ FALSE, /* TRUE if names for this object are strings */
+ ITRON_MAXIMUM_NAME_LENGTH /* maximum length of each object's name */
+#if defined(RTEMS_MULTIPROCESSING)
+ ,
+ FALSE, /* TRUE if this is a global object class */
+ NULL /* Proxy extraction support callout */
+#endif
+ );
+
+ /*
+ * Register the MP Process Packet routine.
+ *
+ * NOTE: No MP Support YET in RTEMS ITRON implementation.
+ */
+
+}
+
+/*
+ * cre_mpf - Create Fixed-Size Memorypool
+ */
+
+ER cre_mpf(
+ ID mpfid,
+ T_CMPF *pk_cmpf
+)
+{
+ return E_OK;
+}
+
+/*
+ * del_mpf - Delete Fixed-Size Memorypool
+ */
+
+ER del_mpf(
+ ID mpfid
+)
+{
+ return E_OK;
+}
+
+/*
+ * get_blf - Get Fixed-Size Memory Block
+ */
+
+ER get_blf(
+ VP *p_blf,
+ ID mpfid
+)
+{
+ return E_OK;
+}
+
+/*
+ * pget_blf - Poll and Get Fixed-Size Memory Block
+ */
+
+ER pget_blf(
+ VP *p_blf,
+ ID mpfid
+)
+{
+ return E_OK;
+}
+
+/*
+ * tget_blf - Get Fixed-Size Memory Block with Timeout
+ */
+
+ER tget_blf(
+ VP *p_blf,
+ ID mpfid,
+ TMO tmout
+)
+{
+ return E_OK;
+}
+
+/*
+ * rel_blf - Release Fixed-Size Memory Block
+ */
+
+ER rel_blf(
+ ID mpfid,
+ VP blf
+)
+{
+ return E_OK;
+}
+
+/*
+ * ref_mpf - Reference Fixed-Size Memorypool Status
+ */
+
+ER ref_mpf(
+ T_RMPF *pk_rmpf,
+ ID mpfid
+)
+{
+ return E_OK;
+}
diff --git a/cpukit/itron/src/frsm_tsk.c b/cpukit/itron/src/frsm_tsk.c
new file mode 100644
index 0000000000..7df43bce44
--- /dev/null
+++ b/cpukit/itron/src/frsm_tsk.c
@@ -0,0 +1,60 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/score/thread.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+#include <rtems/itron/task.h>
+
+
+/*
+ * frsm_tsk - Forcibly Resume Suspended Task
+ */
+
+ER frsm_tsk(
+ ID tskid
+)
+{
+ register Thread_Control *the_thread;
+ Objects_Locations location;
+
+ the_thread = _ITRON_Task_Get( tskid, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE:
+ case OBJECTS_ERROR:
+ return _ITRON_Task_Clarify_get_id_error( tskid );
+
+ case OBJECTS_LOCAL:
+ if ( _Thread_Is_executing( the_thread ) )
+ _ITRON_return_errorno( E_OBJ );
+
+ if (_States_Is_dormant( the_thread->current_state ))
+ _ITRON_return_errorno( E_OBJ );
+
+ if ( ! _States_Is_suspended(the_thread->current_state) )
+ _ITRON_return_errorno( E_OK );
+
+ _Thread_Resume( the_thread, TRUE );
+ break;
+ }
+
+ _ITRON_return_errorno( E_OK );
+
+}
diff --git a/cpukit/itron/src/get_tid.c b/cpukit/itron/src/get_tid.c
new file mode 100644
index 0000000000..e455179fe1
--- /dev/null
+++ b/cpukit/itron/src/get_tid.c
@@ -0,0 +1,41 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/score/thread.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+#include <rtems/itron/task.h>
+
+/*
+ * get_tid - Get Task Identifier
+ */
+
+ER get_tid(
+ ID *p_tskid
+)
+{
+ /*
+ * This does not support multiprocessing. The id handling will have
+ * to be enhanced to support multiprocessing.
+ */
+
+ *p_tskid = _Objects_Get_index( _Thread_Executing->Object.id );
+ return E_OK;
+}
diff --git a/cpukit/itron/src/itronintr.c b/cpukit/itron/src/itronintr.c
new file mode 100644
index 0000000000..13520cf5f0
--- /dev/null
+++ b/cpukit/itron/src/itronintr.c
@@ -0,0 +1,110 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/intr.h>
+
+/*
+ * def_int - Define Interrupt Handler
+ */
+
+ER def_int(
+ UINT dintno,
+ T_DINT *pk_dint
+)
+{
+ return E_OK;
+}
+
+/*
+ * ret_int - Return from Interrupt Handler
+ */
+
+void ret_int( void )
+{
+}
+
+/*
+ * ret_wup - Return and Wakeup Task
+ */
+
+void ret_wup(
+ ID tskid
+)
+{
+}
+
+/*
+ * loc_cpu - Lock CPU
+ */
+
+ER loc_cpu( void )
+{
+ return E_OK;
+}
+
+/*
+ * unl_cpu - Unlock CPU
+ */
+
+ER unl_cpu( void )
+{
+ return E_OK;
+}
+
+/*
+ * dis_int - Disable Interrupt
+ */
+
+ER dis_int(
+ UINT eintno
+)
+{
+ return E_OK;
+}
+
+/*
+ * ena_int - Enable Interrupt
+ */
+
+ER ena_int(
+ UINT eintno
+)
+{
+ return E_OK;
+}
+
+/*
+ * chg_iXX - Change Interrupt Mask(Level or Priority)
+ */
+
+ER chg_iXX(
+ UINT iXXXX
+)
+{
+ return E_OK;
+}
+
+/*
+ * ref_iXX - Reference Interrupt Mask(Level or Priority)
+ */
+
+ER ref_iXX(
+ UINT *p_iXXXX
+)
+{
+ return E_OK;
+}
diff --git a/cpukit/itron/src/itronsem.c b/cpukit/itron/src/itronsem.c
new file mode 100644
index 0000000000..755b3fe840
--- /dev/null
+++ b/cpukit/itron/src/itronsem.c
@@ -0,0 +1,60 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/semaphore.h>
+#include <rtems/itron/task.h>
+#include <rtems/score/tod.h>
+
+/*
+ * _ITRON_Semaphore_Manager_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine initializes all semaphore manager related data structures.
+ *
+ * Input parameters:
+ * maximum_semaphores - maximum configured semaphores
+ *
+ * Output parameters: NONE
+ */
+
+void _ITRON_Semaphore_Manager_initialization(
+ uint32_t maximum_semaphores
+)
+{
+ _Objects_Initialize_information(
+ &_ITRON_Semaphore_Information, /* object information table */
+ OBJECTS_ITRON_API, /* object API */
+ OBJECTS_ITRON_SEMAPHORES, /* object class */
+ maximum_semaphores, /* maximum objects of this class */
+ sizeof( ITRON_Semaphore_Control ), /* size of this object's control block */
+ FALSE, /* TRUE if names for this object are strings */
+ ITRON_MAXIMUM_NAME_LENGTH /* maximum length of each object's name */
+#if defined(RTEMS_MULTIPROCESSING)
+ ,
+ FALSE, /* TRUE if this is a global object class */
+ NULL /* Proxy extraction support callout */
+#endif
+ );
+
+ /*
+ * Register the MP Process Packet routine.
+ *
+ * NOTE: No MP Support YET in RTEMS ITRON implementation.
+ */
+
+}
diff --git a/cpukit/itron/src/itrontime.c b/cpukit/itron/src/itrontime.c
new file mode 100644
index 0000000000..a2971dbdb5
--- /dev/null
+++ b/cpukit/itron/src/itrontime.c
@@ -0,0 +1,247 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/score/thread.h>
+#include <rtems/score/tod.h>
+
+#include <rtems/itron/time.h>
+
+/*
+ * set_tim - Set System Clock
+ */
+
+void converTime(SYSTIME ms, TOD_Control *time)
+{
+ int millisecond;
+
+/* XXX need to dereference structure */
+#if 0
+ milisecond = ms % 1000;
+ tempSecond = ms / 1000;
+#else
+ millisecond = 0;
+#endif
+}
+
+
+/*
+ * set_tim - Set System Clock
+ */
+
+ER set_tim(
+ SYSTIME *pk_tim
+)
+{
+ Watchdog_Interval temp; /* an integer in seconds after conversion from SYSTIME */
+ TOD_Control the_tod;
+
+/* convert *pk_tim which is 48 bits integer in binary into an ordinary
+ integer in milliseconds */
+
+/* XXX */ temp = 0;
+ if(temp > 0) {
+ _Thread_Disable_dispatch();
+ _TOD_Set(&the_tod, temp);
+ _Thread_Enable_dispatch();
+ if(_TOD_Validate(&the_tod)){
+ return E_OK;
+ }
+ }
+ return E_SYS;
+}
+
+/*
+ * get_tim - Get System Clock
+ */
+
+ER get_tim(
+ SYSTIME *pk_tim
+)
+{
+ return E_OK;
+}
+
+/*
+ * dly_tsk - Delay Task
+ */
+
+ER dly_tsk(
+ DLYTIME dlytim
+)
+{
+ Watchdog_Interval ticks;
+
+ ticks = TOD_MILLISECONDS_TO_TICKS(dlytim);
+
+ _Thread_Disable_dispatch();
+ if ( ticks == 0 ) {
+ _Thread_Yield_processor();
+ } else {
+ _Thread_Set_state( _Thread_Executing, STATES_DELAYING );
+ _Watchdog_Initialize(
+ &_Thread_Executing->Timer,
+ _Thread_Delay_ended,
+ _Thread_Executing->Object.id,
+ NULL
+ );
+ _Watchdog_Insert_ticks( &_Thread_Executing->Timer, ticks );
+ }
+ _Thread_Enable_dispatch();
+ return E_OK;
+}
+
+/*
+ * def_cyc - Define Cyclic Handler
+ */
+
+ER def_cyc(
+ HNO cycno,
+ T_DCYC *pk_dcyc
+)
+{
+ Watchdog_Control *object;
+#if 0
+ Watchdog_Interval timeInterval;
+#endif
+
+/* XXX */ object = 0;
+ if ( pk_dcyc->cycatr != TA_HLNG)
+ return E_RSATR;
+#if 0
+ timeInterval = pk_dcyc->cyctim / 1000;
+ object->delta_interval = timeInterval;
+#endif
+ _Watchdog_Initialize(
+ object,
+ pk_dcyc->cychdr,
+ cycno,
+ pk_dcyc->exinf);
+ _Watchdog_Deactivate(object);
+
+ return E_OK;
+}
+
+/*
+ * act_cyc - Activate Cyclic Handler
+ */
+
+ER act_cyc(
+ HNO cycno,
+ UINT cycact
+)
+{
+ Watchdog_Control *object;
+
+ if(cycact != TCY_OFF || cycact != TCY_ON)
+ return E_PAR;
+
+#if 0
+ if( object->Object_ID != cycno)
+ return E_NOEXS;
+#endif
+
+ _Watchdog_Activate(object);
+
+ return E_OK;
+}
+
+/*
+ * ref_cyc - Reference Cyclic Handler Status
+ */
+
+ER ref_cyc(
+ T_RCYC *pk_rcyc,
+ HNO cycno
+)
+{
+#if 0
+ int timeElapse_since_actCyclic;
+#endif
+ T_DCYC *pk_dcyc;
+#if 0
+ Watchdog_Control *object;
+#endif
+
+/* XXX */ pk_dcyc = 0;
+
+/* XXX will to use a "get" routine to map from id to object pointer */
+/* XXX and the object pointer should be of type specific to this manager */
+#if 0
+ if( object->Object_ID == cycno))
+#else
+ if ( 1 )
+#endif
+ {
+ pk_rcyc->exinf = pk_dcyc->exinf;
+ pk_rcyc->cycact = pk_dcyc->cycact;
+#if 0
+ pk_rcyc->lfttim = pk_dcyc->cyctim - timeElapse_since_actCyclic;
+#endif
+
+ return E_OK;
+ }
+ else
+ return E_NOEXS;
+}
+
+/*
+ * def_alm - Define Alarm Handler
+ */
+
+ER def_alm(
+ HNO almno,
+ T_DALM *pk_dalm
+)
+{
+#if 0
+ Objects_Control *objectAlrm;
+ Watchdog_Interval timeInterval;
+
+ timeInterval = pk_dalm->almtim / 1000;
+ (void) _Watchdog_Remove(&objectAlrm);
+ _Watchdog_Initialize(
+ objectAlrm,
+ pk_dalm->almhdr,
+ almno,
+ pk_dalm->exinf);
+ _Watchdong_Insert_seconds(objectAlrm,timeInterval);
+ _Thread_Enable_dispatch();
+#endif
+
+ return E_OK;
+}
+
+/*
+ * ref_alm - Reference Alarm Handler Status
+ */
+
+ER ref_alm(
+ T_RALM *pk_ralm,
+ HNO almno
+)
+{
+
+ return E_OK;
+}
+
+/*
+ * ret_tmr - Return from Timer Handler
+ */
+
+void ret_tmr( void )
+{
+}
diff --git a/cpukit/itron/src/mbox.c b/cpukit/itron/src/mbox.c
new file mode 100644
index 0000000000..19a4ca1257
--- /dev/null
+++ b/cpukit/itron/src/mbox.c
@@ -0,0 +1,59 @@
+/*
+ * ITRON 3.0 Mailbox Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/mbox.h>
+#include <rtems/itron/task.h>
+
+/*
+ * _ITRON_Mailbox_Manager_initialization
+ *
+ * This routine initializes all mailboxes manager related data structures.
+ *
+ * Input parameters:
+ * maximum_mailboxes - maximum configured mailboxes
+ *
+ * Output parameters: NONE
+ */
+
+void _ITRON_Mailbox_Manager_initialization(
+ uint32_t maximum_mailboxes
+)
+{
+ _Objects_Initialize_information(
+ &_ITRON_Mailbox_Information, /* object information table */
+ OBJECTS_ITRON_API, /* object API */
+ OBJECTS_ITRON_MAILBOXES, /* object class */
+ maximum_mailboxes, /* maximum objects of this class */
+ sizeof( ITRON_Mailbox_Control ), /* size of this object's control block */
+ FALSE, /* TRUE if names for this object are strings */
+ ITRON_MAXIMUM_NAME_LENGTH /* maximum length of each object's name */
+#if defined(RTEMS_MULTIPROCESSING)
+ ,
+ FALSE, /* TRUE if this is a global object class */
+ NULL /* Proxy extraction support callout */
+#endif
+ );
+
+ /*
+ * Register the MP Process Packet routine.
+ *
+ * NOTE: No MP Support YET in RTEMS ITRON implementation.
+ */
+
+}
diff --git a/cpukit/itron/src/mboxtranslatereturncode.c b/cpukit/itron/src/mboxtranslatereturncode.c
new file mode 100644
index 0000000000..acd34f8b24
--- /dev/null
+++ b/cpukit/itron/src/mboxtranslatereturncode.c
@@ -0,0 +1,48 @@
+/*
+ * ITRON 3.0 Mailbox Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/mbox.h>
+#include <rtems/itron/task.h>
+
+/*
+ * _ITRON_Mailbox_Translate_core_message_queue_return_code
+ *
+ * This routine translates a core message queue object status
+ * into the appropriate ITRON status code.
+ */
+
+ER _ITRON_Mailbox_Translate_core_message_queue_return_code(
+ CORE_message_queue_Status status
+)
+{
+ switch (status) {
+ case CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL:
+ return E_OK;
+ case CORE_MESSAGE_QUEUE_STATUS_TOO_MANY:
+ return E_TMOUT;
+ case CORE_MESSAGE_QUEUE_STATUS_INVALID_SIZE:
+ return E_PAR;
+ case CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_NOWAIT:
+ return E_TMOUT;
+ case CORE_MESSAGE_QUEUE_STATUS_TIMEOUT:
+ return E_TMOUT;
+ default:
+ return E_ID;
+ }
+}
diff --git a/cpukit/itron/src/msgbuffer.c b/cpukit/itron/src/msgbuffer.c
new file mode 100644
index 0000000000..fdf714ec1f
--- /dev/null
+++ b/cpukit/itron/src/msgbuffer.c
@@ -0,0 +1,60 @@
+/*
+ * ITRON Message Buffer Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/msgbuffer.h>
+#include <rtems/itron/task.h>
+
+/*
+ * _ITRON_Message_buffer_Manager_initialization
+ *
+ * This routine initializes all message buffer manager related data
+ * structures.
+ *
+ * Input parameters:
+ * maximum_message_buffers - maximum configured message buffers
+ *
+ * Output parameters: NONE
+ */
+
+void _ITRON_Message_buffer_Manager_initialization(
+ uint32_t maximum_message_buffers
+)
+{
+ _Objects_Initialize_information(
+ &_ITRON_Message_buffer_Information, /* object information table */
+ OBJECTS_ITRON_API, /* object API */
+ OBJECTS_ITRON_MESSAGE_BUFFERS, /* object class */
+ maximum_message_buffers, /* maximum objects of this class */
+ sizeof( ITRON_Message_buffer_Control ),
+ /* size of this object's control block */
+ FALSE, /* TRUE if names for this object are strings */
+ ITRON_MAXIMUM_NAME_LENGTH /* maximum length of each object's name */
+#if defined(RTEMS_MULTIPROCESSING)
+ ,
+ FALSE, /* TRUE if this is a global object class */
+ NULL /* Proxy extraction support callout */
+#endif
+ );
+
+ /*
+ * Register the MP Process Packet routine.
+ *
+ * NOTE: No MP Support YET in RTEMS ITRON implementation.
+ */
+}
diff --git a/cpukit/itron/src/msgbuffertranslatereturncode.c b/cpukit/itron/src/msgbuffertranslatereturncode.c
new file mode 100644
index 0000000000..4623f2742a
--- /dev/null
+++ b/cpukit/itron/src/msgbuffertranslatereturncode.c
@@ -0,0 +1,48 @@
+/*
+ * ITRON Message Buffer Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/msgbuffer.h>
+#include <rtems/itron/task.h>
+
+/*
+ * _ITRON_Message_buffer_Translate_core_message_buffer_return_code
+ *
+ * This routine translates a core message buffer object status
+ * into the appropriate ITRON status code.
+ */
+
+ER _ITRON_Message_buffer_Translate_core_message_buffer_return_code(
+ CORE_message_queue_Status status
+)
+{
+ switch (status) {
+ case CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL:
+ return E_OK;
+ case CORE_MESSAGE_QUEUE_STATUS_TOO_MANY:
+ return E_TMOUT;
+ case CORE_MESSAGE_QUEUE_STATUS_INVALID_SIZE:
+ return E_PAR;
+ case CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_NOWAIT:
+ return E_TMOUT;
+ case CORE_MESSAGE_QUEUE_STATUS_TIMEOUT:
+ return E_TMOUT;
+ default:
+ return E_ID;
+ }
+}
diff --git a/cpukit/itron/src/network.c b/cpukit/itron/src/network.c
new file mode 100644
index 0000000000..2922d3af9e
--- /dev/null
+++ b/cpukit/itron/src/network.c
@@ -0,0 +1,71 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/network.h>
+
+/*
+ * nrea_dat - Read Data from another Node
+ */
+
+ER nrea_dat(
+ INT *p_reasz,
+ VP dstadr,
+ NODE srcnode,
+ VP srcadr,
+ INT datsz
+)
+{
+ return E_OK;
+}
+
+/*
+ * nwri_dat - Write Data to another Node
+ */
+
+ER nwri_dat(
+ INT *p_wrisz,
+ NODE dstnode,
+ VP dstadr,
+ VP srcadr,
+ INT datsz
+)
+{
+ return E_OK;
+}
+
+/*
+ * nget_nod - Get Local Node Number
+ */
+
+ER nget_nod(
+ NODE *p_node
+)
+{
+ return E_OK;
+}
+
+/*
+ * nget_ver - Get Version Information of another Node
+ */
+
+ER nget_ver(
+ T_VER *pk_ver,
+ NODE node
+)
+{
+ return E_OK;
+}
diff --git a/cpukit/itron/src/port.c b/cpukit/itron/src/port.c
new file mode 100644
index 0000000000..7f5693c385
--- /dev/null
+++ b/cpukit/itron/src/port.c
@@ -0,0 +1,211 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/port.h>
+
+/*
+ * _ITRON_Port_Manager_initialization
+ *
+ * This routine initializes all ports manager related data structures.
+ *
+ * Input parameters:
+ * maximum_ports - maximum configured ports
+ *
+ * Output parameters: NONE
+ */
+
+void _ITRON_Port_Manager_initialization(
+ uint32_t maximum_ports
+)
+{
+ _Objects_Initialize_information(
+ &_ITRON_Port_Information, /* object information table */
+ OBJECTS_ITRON_API, /* object API */
+ OBJECTS_ITRON_PORTS, /* object class */
+ maximum_ports, /* maximum objects of this class */
+ sizeof( ITRON_Port_Control ), /* size of this object's control block */
+ FALSE, /* TRUE if names for this object are strings */
+ ITRON_MAXIMUM_NAME_LENGTH /* maximum length of each object's name */
+#if defined(RTEMS_MULTIPROCESSING)
+ ,
+ FALSE, /* TRUE if this is a global object class */
+ NULL /* Proxy extraction support callout */
+#endif
+ );
+
+ /*
+ * Register the MP Process Packet routine.
+ *
+ * NOTE: No MP Support YET in RTEMS ITRON implementation.
+ */
+
+}
+
+/*
+ * cre_por - Create Port for Rendezvous
+ */
+
+ER cre_por(
+ ID porid,
+ T_CPOR *pk_cpor
+)
+{
+ return E_OK;
+}
+
+/*
+ * del_por - Delete Port for Rendezvous
+ */
+
+ER del_por(
+ ID porid
+)
+{
+ return E_OK;
+}
+
+/*
+ * cal_por - Call Port for Rendezvous Poll
+ */
+
+ER cal_por(
+ VP msg,
+ INT *p_rmsgsz,
+ ID porid,
+ UINT calptn,
+ INT cmsgsz
+)
+{
+ return E_OK;
+}
+
+/*
+ * pcal_por - Poll and Call Port for Rendezvous
+ */
+
+ER pcal_por(
+ VP msg,
+ INT *p_rmsgsz,
+ ID porid,
+ UINT calptn,
+ INT cmsgsz
+)
+{
+ return E_OK;
+}
+
+/*
+ * tcal_por - Call Port for Rendezvous with Timeout
+ */
+
+ER tcal_por(
+ VP msg,
+ INT *p_rmsgsz,
+ ID porid,
+ UINT calptn,
+ INT cmsgsz,
+ TMO tmout
+)
+{
+ return E_OK;
+}
+
+/*
+ * acp_por - Accept Port for Rendezvous Poll
+ */
+
+ER acp_por(
+ RNO *p_rdvno,
+ VP msg,
+ INT *p_cmsgsz,
+ ID porid,
+ UINT acpptn
+)
+{
+ return E_OK;
+}
+
+/*
+ * pacp_por - Poll and Accept Port for Rendezvous
+ */
+
+ER pacp_por(
+ RNO *p_rdvno,
+ VP msg,
+ INT *p_cmsgsz,
+ ID porid,
+ UINT acpptn
+)
+{
+ return E_OK;
+}
+
+/*
+ * tacp_por - Accept Port for Rendezvous with Timeout
+ */
+
+ER tacp_por(
+ RNO *p_rdvno,
+ VP msg,
+ INT *p_cmsgsz,
+ ID porid,
+ UINT acpptn,
+ TMO tmout
+)
+{
+ return E_OK;
+}
+
+/*
+ * fwd_por - Forward Rendezvous to Other Port
+ */
+
+ER fwd_por(
+ ID porid,
+ UINT calptn,
+ RNO rdvno,
+ VP msg,
+ INT cmsgsz
+)
+{
+ return E_OK;
+}
+
+/*
+ * rpl_rdv - Reply Rendezvous
+ */
+
+ER rpl_rdv(
+ RNO rdvno,
+ VP msg,
+ INT rmsgsz
+)
+{
+ return E_OK;
+}
+
+/*
+ * ref_por - Reference Port Status
+ */
+
+ER ref_por(
+ T_RPOR *pk_rpor,
+ ID porid
+)
+{
+ return E_OK;
+}
diff --git a/cpukit/itron/src/prcv_mbf.c b/cpukit/itron/src/prcv_mbf.c
new file mode 100644
index 0000000000..e095d2ccb4
--- /dev/null
+++ b/cpukit/itron/src/prcv_mbf.c
@@ -0,0 +1,34 @@
+/*
+ * ITRON Message Buffer Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/msgbuffer.h>
+#include <rtems/itron/task.h>
+
+/*
+ * prcv_mbf - Poll and Receive Message from MessageBuffer
+ */
+
+ER prcv_mbf(
+ VP msg,
+ INT *p_msgsz,
+ ID mbfid
+)
+{
+ return trcv_mbf(msg, p_msgsz, mbfid, TMO_POL);
+}
diff --git a/cpukit/itron/src/prcv_mbx.c b/cpukit/itron/src/prcv_mbx.c
new file mode 100644
index 0000000000..4986ae3744
--- /dev/null
+++ b/cpukit/itron/src/prcv_mbx.c
@@ -0,0 +1,33 @@
+/*
+ * ITRON 3.0 Mailbox Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/mbox.h>
+#include <rtems/itron/task.h>
+
+/*
+ * prcv_msg - Poll and Receive Message from Mailbox
+ */
+
+ER prcv_msg(
+ T_MSG **ppk_msg,
+ ID mbxid
+)
+{
+ return trcv_msg( ppk_msg, mbxid, TMO_POL );
+}
diff --git a/cpukit/itron/src/preq_sem.c b/cpukit/itron/src/preq_sem.c
new file mode 100644
index 0000000000..e68f92b5de
--- /dev/null
+++ b/cpukit/itron/src/preq_sem.c
@@ -0,0 +1,33 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/semaphore.h>
+#include <rtems/itron/task.h>
+#include <rtems/score/tod.h>
+
+/*
+ * preq_sem - Poll and Request Semaphore
+ *
+ * This function implements the ITRON 3.0 preq_sem() service.
+ */
+
+ER preq_sem(
+ ID semid
+)
+{
+ return twai_sem( semid, TMO_POL );
+}
diff --git a/cpukit/itron/src/psnd_mbf.c b/cpukit/itron/src/psnd_mbf.c
new file mode 100644
index 0000000000..bac72feb2a
--- /dev/null
+++ b/cpukit/itron/src/psnd_mbf.c
@@ -0,0 +1,34 @@
+/*
+ * ITRON Message Buffer Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/msgbuffer.h>
+#include <rtems/itron/task.h>
+
+/*
+ * psnd_mbf - Poll and Send Message to MessageBuffer
+ */
+
+ER psnd_mbf(
+ ID mbfid,
+ VP msg,
+ INT msgsz
+)
+{
+ return tsnd_mbf( mbfid, msg, msgsz, TMO_POL );
+}
diff --git a/cpukit/itron/src/rcv_mbf.c b/cpukit/itron/src/rcv_mbf.c
new file mode 100644
index 0000000000..6427f36250
--- /dev/null
+++ b/cpukit/itron/src/rcv_mbf.c
@@ -0,0 +1,34 @@
+/*
+ * ITRON Message Buffer Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/msgbuffer.h>
+#include <rtems/itron/task.h>
+
+/*
+ * rcv_mbf - Receive Message from MessageBuffer
+ */
+
+ER rcv_mbf(
+ VP msg,
+ INT *p_msgsz,
+ ID mbfid
+)
+{
+ return trcv_mbf(msg, p_msgsz, mbfid, TMO_FEVR);
+}
diff --git a/cpukit/itron/src/rcv_mbx.c b/cpukit/itron/src/rcv_mbx.c
new file mode 100644
index 0000000000..dde0f2697e
--- /dev/null
+++ b/cpukit/itron/src/rcv_mbx.c
@@ -0,0 +1,33 @@
+/*
+ * ITRON 3.0 Mailbox Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/mbox.h>
+#include <rtems/itron/task.h>
+
+/*
+ * rcv_msg - Receive Message from Mailbox
+ */
+
+ER rcv_msg(
+ T_MSG **ppk_msg,
+ ID mbxid
+)
+{
+ return trcv_msg( ppk_msg, mbxid, TMO_FEVR );
+}
diff --git a/cpukit/itron/src/ref_mbf.c b/cpukit/itron/src/ref_mbf.c
new file mode 100644
index 0000000000..f7f076e65b
--- /dev/null
+++ b/cpukit/itron/src/ref_mbf.c
@@ -0,0 +1,83 @@
+/*
+ * ITRON Message Buffer Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/msgbuffer.h>
+#include <rtems/itron/task.h>
+
+/*
+ * ref_mbf - Reference Message Buffer Status
+ */
+
+ER ref_mbf(
+ T_RMBF *pk_rmbf,
+ ID mbfid
+)
+{
+ ITRON_Message_buffer_Control *the_message_buffer;
+ Objects_Locations location;
+ CORE_message_queue_Control *the_core_msgq;
+
+ if ( !pk_rmbf )
+ return E_PAR; /* XXX check this error code */
+
+ the_message_buffer = _ITRON_Message_buffer_Get( mbfid, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE: /* Multiprocessing not supported */
+ case OBJECTS_ERROR:
+ return _ITRON_Message_buffer_Clarify_get_id_error( mbfid );
+
+ case OBJECTS_LOCAL:
+ the_core_msgq = &the_message_buffer->message_queue;
+
+ /*
+ * Fill in the size of message to be sent
+ */
+
+ if (the_core_msgq->number_of_pending_messages == 0) {
+ pk_rmbf->msgsz = 0;
+ } else {
+ pk_rmbf->msgsz = ((CORE_message_queue_Buffer_control *)
+ the_core_msgq->Pending_messages.first)->Contents.size;
+ }
+
+ /*
+ * Fill in the size of free buffer
+ */
+
+ pk_rmbf->frbufsz =
+ (the_core_msgq->maximum_pending_messages -
+ the_core_msgq->number_of_pending_messages) *
+ the_core_msgq->maximum_message_size;
+
+
+ /*
+ * Fill in whether or not there is a waiting task
+ */
+
+ if ( !_Thread_queue_First(&the_core_msgq->Wait_queue ) )
+ pk_rmbf->wtsk = FALSE;
+ else
+ pk_rmbf->wtsk = TRUE;
+
+ pk_rmbf->stsk = FALSE;
+ _Thread_Enable_dispatch();
+ return E_OK;
+ }
+ return E_OK;
+}
diff --git a/cpukit/itron/src/ref_mbx.c b/cpukit/itron/src/ref_mbx.c
new file mode 100644
index 0000000000..6e100e011e
--- /dev/null
+++ b/cpukit/itron/src/ref_mbx.c
@@ -0,0 +1,65 @@
+/*
+ * ITRON 3.0 Mailbox Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/mbox.h>
+#include <rtems/itron/task.h>
+
+/*
+ * ref_mbx - Reference Mailbox Status
+ */
+
+ER ref_mbx(
+ T_RMBX *pk_rmbx,
+ ID mbxid
+)
+{
+ register ITRON_Mailbox_Control *the_mailbox;
+ Objects_Locations location;
+ Chain_Control *pending;
+
+ if ( !pk_rmbx )
+ return E_PAR;
+
+ the_mailbox = _ITRON_Mailbox_Get( mbxid, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE:
+ case OBJECTS_ERROR:
+ return _ITRON_Mailbox_Clarify_get_id_error( mbxid );
+
+ case OBJECTS_LOCAL:
+
+ pending = &the_mailbox->message_queue.Pending_messages;
+ if ( _Chain_Is_empty( pending ) )
+ pk_rmbx->pk_msg = NULL;
+ else
+ pk_rmbx->pk_msg = (T_MSG *) pending->first;
+
+ /*
+ * Fill in whether or not there is a waiting task
+ */
+
+ if ( !_Thread_queue_First( &the_mailbox->message_queue.Wait_queue ) )
+ pk_rmbx->wtsk = FALSE;
+ else
+ pk_rmbx->wtsk = TRUE;
+
+ break;
+ }
+ _ITRON_return_errorno( E_OK );
+}
diff --git a/cpukit/itron/src/ref_sem.c b/cpukit/itron/src/ref_sem.c
new file mode 100644
index 0000000000..9a46cca38d
--- /dev/null
+++ b/cpukit/itron/src/ref_sem.c
@@ -0,0 +1,65 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/semaphore.h>
+#include <rtems/itron/task.h>
+#include <rtems/score/tod.h>
+
+/*
+ * ref_sem - Reference Semaphore Status
+ *
+ * This function implements the ITRON 3.0 ref_sem() service.
+ */
+
+ER ref_sem(
+ ID semid,
+ T_RSEM *pk_rsem
+)
+{
+ ITRON_Semaphore_Control *the_semaphore;
+ Objects_Locations location;
+
+ if ( !pk_rsem )
+ return E_PAR; /* XXX check this error code */
+
+ the_semaphore = _ITRON_Semaphore_Get( semid, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE: /* Multiprocessing not supported */
+ case OBJECTS_ERROR:
+ return _ITRON_Semaphore_Clarify_get_id_error( semid );
+
+ case OBJECTS_LOCAL:
+ /*
+ * Fill in the current semaphore count
+ */
+
+ pk_rsem->semcnt = _CORE_semaphore_Get_count( &the_semaphore->semaphore );
+
+ /*
+ * Fill in whether or not there is a waiting task
+ */
+
+ if ( !_Thread_queue_First( &the_semaphore->semaphore.Wait_queue ) )
+ pk_rsem->wtsk = FALSE;
+ else
+ pk_rsem->wtsk = TRUE;
+
+ _Thread_Enable_dispatch();
+ return E_OK;
+ }
+ return E_OK;
+}
diff --git a/cpukit/itron/src/ref_tsk.c b/cpukit/itron/src/ref_tsk.c
new file mode 100644
index 0000000000..6b951a5c8a
--- /dev/null
+++ b/cpukit/itron/src/ref_tsk.c
@@ -0,0 +1,99 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/score/thread.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+#include <rtems/itron/task.h>
+
+
+/*
+ * ref_tsk - Reference Task Status
+ */
+
+ER ref_tsk(
+ T_RTSK *pk_rtsk,
+ ID tskid
+)
+{
+ register Thread_Control *the_thread;
+ Objects_Locations location;
+ Priority_Control core_priority;
+
+ if (!pk_rtsk)
+ return E_PAR;
+
+ the_thread = _ITRON_Task_Get( tskid, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE:
+ case OBJECTS_ERROR:
+ return _ITRON_Task_Clarify_get_id_error( tskid );
+
+ case OBJECTS_LOCAL:
+
+ if ( location != OBJECTS_LOCAL )
+ return _ITRON_Task_Clarify_get_id_error( tskid );
+
+ /*
+ * The following are extended functions [level X ].
+ * XXX - tskwait, wid, wupcnt, and tskatr are presently not implemented.
+ */
+
+ pk_rtsk->tskwait = 0;
+ pk_rtsk->wid = 0;
+ pk_rtsk->wupcnt = 0;
+ pk_rtsk->suscnt = the_thread->suspend_count;
+ pk_rtsk->tskatr = 0; /* XXX - Not correctly implemented */
+ pk_rtsk->task = (FP) the_thread->Start.entry_point;
+ core_priority = the_thread->Start.initial_priority;
+ pk_rtsk->itskpri = _ITRON_Task_Core_to_Priority( core_priority );
+ pk_rtsk->stksz = the_thread->Start.Initial_stack.size;
+
+ /*
+ * The following are required.
+ */
+
+ pk_rtsk->exinf = NULL; /* extended information */
+ pk_rtsk->tskpri =
+ _ITRON_Task_Core_to_Priority(the_thread->current_priority);
+
+ /*
+ * Mask in the tskstat information
+ * Convert the task state XXX double check this
+ */
+
+ pk_rtsk->tskstat = 0;
+ if ( the_thread == _Thread_Executing )
+ pk_rtsk->tskstat |= TTS_RUN;
+ if ( _States_Is_ready(the_thread->current_state) )
+ pk_rtsk->tskstat |= TTS_RDY;
+ if ( _States_Is_dormant( the_thread->current_state) )
+ pk_rtsk->tskstat |= TTS_DMT;
+ if ( _States_Is_suspended(the_thread->current_state) )
+ pk_rtsk->tskstat |= TTS_SUS;
+ if ( _States_Is_blocked(the_thread->current_state) )
+ pk_rtsk->tskstat |= TTS_WAI;
+
+ break;
+ }
+
+ _ITRON_return_errorno( E_OK );
+
+}
diff --git a/cpukit/itron/src/rel_wai.c b/cpukit/itron/src/rel_wai.c
new file mode 100644
index 0000000000..49b247d660
--- /dev/null
+++ b/cpukit/itron/src/rel_wai.c
@@ -0,0 +1,52 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/score/thread.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+#include <rtems/itron/task.h>
+
+/*
+ * rel_wai - Release Wait of Other Task
+ */
+
+ER rel_wai(
+ ID tskid
+)
+{
+ register Thread_Control *the_thread;
+ Objects_Locations location;
+
+ the_thread = _ITRON_Task_Get( tskid, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE:
+ case OBJECTS_ERROR:
+ return _ITRON_Task_Clarify_get_id_error( tskid );
+
+ case OBJECTS_LOCAL:
+ /*
+ * XXX - FILL ME IN.
+ */
+
+ break;
+ }
+
+ _ITRON_return_errorno( E_OK );
+}
diff --git a/cpukit/itron/src/rot_rdq.c b/cpukit/itron/src/rot_rdq.c
new file mode 100644
index 0000000000..80e9e5c95e
--- /dev/null
+++ b/cpukit/itron/src/rot_rdq.c
@@ -0,0 +1,55 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/score/thread.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+#include <rtems/itron/task.h>
+
+/*
+ * rot_rdq - Rotate Tasks on the Ready Queue
+ */
+
+ER rot_rdq(
+ PRI tskpri
+)
+{
+ PRI priority;
+
+
+ if (( tskpri <= 0 ) || ( tskpri >= 256 ))
+ return E_PAR;
+
+ _Thread_Disable_dispatch();
+
+ /*
+ * Yield of processor will rotate the queue for this processor.
+ */
+
+ priority = _ITRON_Task_Core_to_Priority(_Thread_Executing->current_priority);
+ if ( priority == tskpri )
+ _Thread_Yield_processor();
+ else {
+ _Thread_Rotate_Ready_Queue( _ITRON_Task_Core_to_Priority( tskpri ) );
+ }
+ _Thread_Enable_dispatch();
+
+ return E_OK;
+}
diff --git a/cpukit/itron/src/rsm_tsk.c b/cpukit/itron/src/rsm_tsk.c
new file mode 100644
index 0000000000..a41fbfe5e6
--- /dev/null
+++ b/cpukit/itron/src/rsm_tsk.c
@@ -0,0 +1,60 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/score/thread.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+#include <rtems/itron/task.h>
+
+
+/*
+ * rsm_tsk - Resume Suspended Task
+ */
+
+ER rsm_tsk(
+ ID tskid
+)
+{
+ register Thread_Control *the_thread;
+ Objects_Locations location;
+
+ the_thread = _ITRON_Task_Get( tskid, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE:
+ case OBJECTS_ERROR:
+ return _ITRON_Task_Clarify_get_id_error( tskid );
+
+ case OBJECTS_LOCAL:
+
+ if ( _Thread_Is_executing( the_thread ) )
+ _ITRON_return_errorno( E_OBJ );
+
+ if ( _States_Is_dormant( the_thread->current_state ))
+ _ITRON_return_errorno( E_OBJ );
+
+ if ( ! _States_Is_suspended(the_thread->current_state) )
+ _ITRON_return_errorno( E_OK );
+
+ _Thread_Resume( the_thread, FALSE );
+ break;
+ }
+
+ _ITRON_return_errorno( E_OK );
+}
diff --git a/cpukit/itron/src/sig_sem.c b/cpukit/itron/src/sig_sem.c
new file mode 100644
index 0000000000..cde504891c
--- /dev/null
+++ b/cpukit/itron/src/sig_sem.c
@@ -0,0 +1,56 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/semaphore.h>
+#include <rtems/itron/task.h>
+#include <rtems/score/tod.h>
+
+/*
+ * sig_sem - Signal Semaphore
+ *
+ * This function implements the ITRON 3.0 sig_sem() service.
+ */
+
+ER sig_sem(
+ ID semid
+)
+{
+ ITRON_Semaphore_Control *the_semaphore;
+ Objects_Locations location;
+ CORE_semaphore_Status status;
+
+ the_semaphore = _ITRON_Semaphore_Get( semid, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE: /* Multiprocessing not supported */
+ case OBJECTS_ERROR:
+ return _ITRON_Semaphore_Clarify_get_id_error( semid );
+
+ case OBJECTS_LOCAL:
+ /*
+ * XXX maxsemcnt
+ */
+
+ status = _CORE_semaphore_Surrender(
+ &the_semaphore->semaphore,
+ the_semaphore->Object.id,
+ NULL /* Multiprocessing not supported */
+ );
+ _Thread_Enable_dispatch();
+ return _ITRON_Semaphore_Translate_core_semaphore_return_code( status );
+ }
+ return E_OK;
+}
diff --git a/cpukit/itron/src/slp_tsk.c b/cpukit/itron/src/slp_tsk.c
new file mode 100644
index 0000000000..917ef11157
--- /dev/null
+++ b/cpukit/itron/src/slp_tsk.c
@@ -0,0 +1,35 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/score/thread.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+#include <rtems/itron/task.h>
+
+
+
+/*
+ * slp_tsk - Sleep Task
+ */
+
+ER slp_tsk( void )
+{
+ return E_OK;
+}
diff --git a/cpukit/itron/src/snd_mbf.c b/cpukit/itron/src/snd_mbf.c
new file mode 100644
index 0000000000..3c46aad75e
--- /dev/null
+++ b/cpukit/itron/src/snd_mbf.c
@@ -0,0 +1,34 @@
+/*
+ * ITRON Message Buffer Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/msgbuffer.h>
+#include <rtems/itron/task.h>
+
+/*
+ * snd_mbf - Send Message to MessageBuffer
+ */
+
+ER snd_mbf(
+ ID mbfid,
+ VP msg,
+ INT msgsz
+)
+{
+ return tsnd_mbf( mbfid, msg, msgsz, TMO_FEVR );
+}
diff --git a/cpukit/itron/src/snd_mbx.c b/cpukit/itron/src/snd_mbx.c
new file mode 100644
index 0000000000..f257ab3b41
--- /dev/null
+++ b/cpukit/itron/src/snd_mbx.c
@@ -0,0 +1,70 @@
+/*
+ * ITRON 3.0 Mailbox Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/mbox.h>
+#include <rtems/itron/task.h>
+
+/*
+ * snd_msg - Send Message to Mailbox
+ */
+
+ER snd_msg(
+ ID mbxid,
+ T_MSG *pk_msg
+)
+{
+ register ITRON_Mailbox_Control *the_mailbox;
+ Objects_Locations location;
+ uint32_t message_priority;
+ void *message_contents;
+ CORE_message_queue_Status msg_status;
+
+ if ( !pk_msg )
+ return E_PAR;
+
+ the_mailbox = _ITRON_Mailbox_Get( mbxid, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE:
+ case OBJECTS_ERROR:
+ return _ITRON_Mailbox_Clarify_get_id_error( mbxid );
+
+ case OBJECTS_LOCAL:
+ if ( the_mailbox->do_message_priority )
+ message_priority = pk_msg->msgpri;
+ else
+ message_priority = CORE_MESSAGE_QUEUE_SEND_REQUEST;
+
+ message_contents = pk_msg;
+ msg_status = _CORE_message_queue_Submit(
+ &the_mailbox->message_queue,
+ &message_contents,
+ sizeof(T_MSG *),
+ the_mailbox->Object.id,
+ NULL, /* multiprocessing not supported */
+ message_priority,
+ FALSE, /* do not allow sender to block */
+ 0 /* no timeout */
+ );
+ break;
+ }
+
+ _ITRON_return_errorno(
+ _ITRON_Mailbox_Translate_core_message_queue_return_code( msg_status )
+ );
+}
diff --git a/cpukit/itron/src/sta_tsk.c b/cpukit/itron/src/sta_tsk.c
new file mode 100644
index 0000000000..a1beeade23
--- /dev/null
+++ b/cpukit/itron/src/sta_tsk.c
@@ -0,0 +1,69 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/score/thread.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+#include <rtems/itron/task.h>
+
+
+/*
+ * sta_tsk - Start Task
+ */
+
+ER sta_tsk(
+ ID tskid,
+ INT stacd
+)
+{
+ register Thread_Control *the_thread;
+ Objects_Locations location;
+ boolean status;
+
+ the_thread = _ITRON_Task_Get( tskid, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE:
+ case OBJECTS_ERROR:
+ return _ITRON_Task_Clarify_get_id_error( tskid );
+
+ case OBJECTS_LOCAL:
+
+ if ( !_States_Is_dormant( the_thread->current_state ) )
+ _ITRON_return_errorno( E_OBJ );
+
+ status = _Thread_Start(
+ the_thread,
+ THREAD_START_NUMERIC, /* XXX should be able to say we have no arg */
+ the_thread->Start.entry_point,
+ 0, /* XXX supercore forces us to have an arg */
+ 0 /* unused */
+ );
+
+ /*
+ * This error can not happen entry_point is checked in create.
+ if ( !status )
+ _ITRON_return_errorno( E_OBJ );
+ */
+
+ break;
+ }
+
+ _ITRON_return_errorno( E_OK );
+}
diff --git a/cpukit/itron/src/sus_tsk.c b/cpukit/itron/src/sus_tsk.c
new file mode 100644
index 0000000000..7261a171df
--- /dev/null
+++ b/cpukit/itron/src/sus_tsk.c
@@ -0,0 +1,62 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <limits.h>
+#include <rtems/itron.h>
+
+#include <rtems/score/thread.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+#include <rtems/itron/task.h>
+
+
+/*
+ * Task-Dependent Synchronization Functions
+ */
+
+/*
+ * sus_tsk - Suspend Other Task
+ */
+
+ER sus_tsk(
+ ID tskid
+)
+{
+ register Thread_Control *the_thread;
+ Objects_Locations location;
+
+ the_thread = _ITRON_Task_Get( tskid, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE:
+ case OBJECTS_ERROR:
+ return _ITRON_Task_Clarify_get_id_error( tskid );
+
+ case OBJECTS_LOCAL:
+
+ if ( _Thread_Is_executing( the_thread ) )
+ _ITRON_return_errorno( E_OBJ );
+
+ if (the_thread->suspend_count == INT_MAX )
+ _ITRON_return_errorno( E_QOVR );
+
+ _Thread_Suspend( the_thread );
+ break;
+ }
+
+ _ITRON_return_errorno( E_OK );
+}
diff --git a/cpukit/itron/src/sysmgmt.c b/cpukit/itron/src/sysmgmt.c
new file mode 100644
index 0000000000..b997c3fd74
--- /dev/null
+++ b/cpukit/itron/src/sysmgmt.c
@@ -0,0 +1,75 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/sysmgmt.h>
+
+/*
+ * get_ver - Get Version Information
+ */
+
+ER get_ver(
+ T_VER *pk_ver
+)
+{
+ return E_OK;
+}
+
+/*
+ * ref_sys - Reference System Status
+ */
+
+ER ref_sys(
+ T_RSYS *pk_rsys
+)
+{
+ return E_OK;
+}
+
+/*
+ * ref_cfg - Reference Configuration Information
+ */
+
+ER ref_cfg(
+ T_RCFG *pk_rcfg
+)
+{
+ return E_OK;
+}
+
+/*
+ * def_svc - Define Extended SVC Handler
+ */
+
+ER def_svc(
+ FN s_fncd,
+ T_DSVC *pk_dsvc
+)
+{
+ return E_OK;
+}
+
+/*
+ * def_exc - Define Exception Handler
+ */
+
+ER def_exc(
+ UINT exckind,
+ T_DEXC *pk_dexc
+)
+{
+ return E_OK;
+}
diff --git a/cpukit/itron/src/task.c b/cpukit/itron/src/task.c
new file mode 100644
index 0000000000..2fcb3a3a0a
--- /dev/null
+++ b/cpukit/itron/src/task.c
@@ -0,0 +1,227 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/score/thread.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+#include <rtems/itron/task.h>
+
+/*
+ * _ITRON_Task_Create_extension
+ *
+ * This routine is an extension routine that is invoked as part
+ * of creating any type of task or thread in the system. If the
+ * task is created via another API, then this routine is invoked
+ * and this API given the opportunity to initialize its extension
+ * area.
+ */
+
+boolean _ITRON_Task_Create_extension(
+ Thread_Control *executing,
+ Thread_Control *created
+)
+{
+ ITRON_API_Control *api;
+
+ api = _Workspace_Allocate( sizeof( ITRON_API_Control ) );
+
+ if ( !api )
+ return FALSE;
+
+ created->API_Extensions[ THREAD_API_ITRON ] = api;
+
+ /*
+ * Initialize the ITRON API extension
+ */
+
+ return TRUE;
+}
+
+/*
+ * _ITRON_Task_Delete_extension
+ *
+ * This extension routine is invoked when a task is deleted.
+ */
+
+User_extensions_routine _ITRON_Task_Delete_extension(
+ Thread_Control *executing,
+ Thread_Control *deleted
+)
+{
+ (void) _Workspace_Free( deleted->API_Extensions[ THREAD_API_ITRON ] );
+
+ deleted->API_Extensions[ THREAD_API_ITRON ] = NULL;
+}
+
+/*
+ * _ITRON_Task_Initialize_user_tasks
+ *
+ * This routine creates and starts all configured user
+ * initialzation threads.
+ */
+
+void _ITRON_Task_Initialize_user_tasks( void )
+{
+ uint32_t index;
+ uint32_t maximum;
+ ER return_value;
+ itron_initialization_tasks_table *user_tasks;
+
+ /*
+ * NOTE: This is slightly different from the Ada implementation.
+ */
+
+ user_tasks = _ITRON_Task_User_initialization_tasks;
+ maximum = _ITRON_Task_Number_of_initialization_tasks;
+
+ if ( !user_tasks || maximum == 0 )
+ return;
+
+ for ( index=0 ; index < maximum ; index++ ) {
+
+ return_value = cre_tsk(
+ user_tasks[ index ].id,
+ &user_tasks[ index ].attributes
+ );
+
+ if ( return_value != E_OK )
+ _Internal_error_Occurred( INTERNAL_ERROR_ITRON_API, TRUE, return_value );
+
+ return_value = sta_tsk( user_tasks[ index ].id, 0 );
+
+ if ( return_value != E_OK )
+ _Internal_error_Occurred( INTERNAL_ERROR_ITRON_API, TRUE, return_value );
+
+ }
+}
+
+/*PAGE
+ *
+ * _ITRON_Delete_task
+ */
+
+ER _ITRON_Delete_task(
+ Thread_Control *the_thread
+)
+{
+ Objects_Information *the_information;
+
+ the_information = _Objects_Get_information( the_thread->Object.id );
+ if ( !the_information ) {
+ return E_OBJ; /* XXX - should never happen */
+ }
+
+ _Thread_Close( the_information, the_thread );
+
+ _ITRON_Task_Free( the_thread );
+
+ return E_OK;
+}
+
+/*
+ * At this point in time, the ITRON API does not need any other
+ * extensions. See the POSIX and RTEMS API extensions for
+ * examples of how they can be used.
+ */
+
+/*
+ * Extension Tables
+ */
+
+API_extensions_Control _ITRON_Task_API_extensions = {
+ { NULL, NULL },
+ NULL, /* predriver */
+ _ITRON_Task_Initialize_user_tasks, /* postdriver */
+ NULL /* post switch */
+};
+
+User_extensions_Control _ITRON_Task_User_extensions = {
+ { NULL, NULL },
+ { { NULL, NULL }, NULL },
+ { _ITRON_Task_Create_extension, /* create */
+ NULL, /* start */
+ NULL, /* restart */
+ _ITRON_Task_Delete_extension, /* delete */
+ NULL, /* switch */
+ NULL, /* begin */
+ NULL, /* exitted */
+ NULL /* fatal */
+ }
+};
+
+/*
+ * _ITRON_Task_Manager_initialization
+ *
+ * This routine initializes all Task Manager related data structures.
+ *
+ * Input parameters:
+ * maximum_tasks - number of tasks to initialize
+ *
+ * Output parameters: NONE
+ */
+
+void _ITRON_Task_Manager_initialization(
+ uint32_t maximum_tasks,
+ uint32_t number_of_initialization_tasks,
+ itron_initialization_tasks_table *user_tasks
+)
+{
+
+ _ITRON_Task_Number_of_initialization_tasks = number_of_initialization_tasks;
+ _ITRON_Task_User_initialization_tasks = user_tasks;
+
+ /*
+ * There may not be any ITRON_initialization tasks configured.
+ */
+
+#if 0
+ if ( user_tasks == NULL || number_of_initialization_tasks == 0 )
+ _Internal_error_Occurred( INTERNAL_ERROR_ITRON_API, TRUE, -1 );
+#endif
+
+ _Objects_Initialize_information(
+ &_ITRON_Task_Information, /* object information table */
+ OBJECTS_ITRON_API, /* object API */
+ OBJECTS_ITRON_TASKS, /* object class */
+ maximum_tasks, /* maximum objects of this class */
+ sizeof( Thread_Control ), /* size of this object's control block */
+ FALSE, /* TRUE if names for this object are strings */
+ ITRON_MAXIMUM_NAME_LENGTH /* maximum length of each object's name */
+#if defined(RTEMS_MULTIPROCESSING)
+ ,
+ FALSE, /* TRUE if this is a global object class */
+ NULL /* Proxy extraction support callout */
+#endif
+ );
+
+ /*
+ * Add all the extensions for this API
+ */
+
+ _User_extensions_Add_API_set( &_ITRON_Task_User_extensions );
+
+ _API_extensions_Add( &_ITRON_Task_API_extensions );
+
+ /*
+ * XXX MP not supported
+ * Register the MP Process Packet routine.
+ */
+
+}
diff --git a/cpukit/itron/src/ter_tsk.c b/cpukit/itron/src/ter_tsk.c
new file mode 100644
index 0000000000..f3111f5d46
--- /dev/null
+++ b/cpukit/itron/src/ter_tsk.c
@@ -0,0 +1,58 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/score/thread.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+#include <rtems/itron/task.h>
+
+
+/*
+ * ter_tsk - Terminate Other Task - Set State to DORMANT
+ */
+
+ER ter_tsk(
+ ID tskid
+)
+{
+ register Thread_Control *the_thread;
+ Objects_Locations location;
+
+ the_thread = _ITRON_Task_Get( tskid, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE:
+ case OBJECTS_ERROR:
+ return _ITRON_Task_Clarify_get_id_error( tskid );
+
+ case OBJECTS_LOCAL:
+
+ if ( _Thread_Is_executing( the_thread ) )
+ _ITRON_return_errorno( E_OBJ );
+
+ if ( _States_Is_dormant( the_thread->current_state ) )
+ _ITRON_return_errorno( E_OBJ );
+
+ _Thread_Restart( the_thread, NULL, 0 );
+ _Thread_Set_state( the_thread, STATES_DORMANT );
+ break;
+ }
+
+ _ITRON_return_errorno( E_OK );
+}
diff --git a/cpukit/itron/src/trcv_mbf.c b/cpukit/itron/src/trcv_mbf.c
new file mode 100644
index 0000000000..9e05334433
--- /dev/null
+++ b/cpukit/itron/src/trcv_mbf.c
@@ -0,0 +1,84 @@
+/*
+ * ITRON Message Buffer Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/msgbuffer.h>
+#include <rtems/itron/task.h>
+
+/*
+ * trcv_mbf - Receive Message from MessageBuffer with Timeout
+ */
+
+ER trcv_mbf(
+ VP msg,
+ INT *p_msgsz,
+ ID mbfid,
+ TMO tmout
+)
+{
+ ITRON_Message_buffer_Control *the_message_buffer;
+ Objects_Locations location;
+ CORE_message_queue_Status status;
+ boolean wait;
+ Watchdog_Interval interval;
+
+ interval = 0;
+ if (tmout == TMO_POL) {
+ wait = FALSE;
+ } else {
+ wait = TRUE;
+ if (tmout != TMO_FEVR)
+ interval = TOD_MILLISECONDS_TO_TICKS(tmout);
+ }
+
+ if (wait && _ITRON_Is_in_non_task_state() )
+ return E_CTX;
+
+ if (!p_msgsz || !msg || tmout <= -2)
+ return E_PAR;
+
+ the_message_buffer = _ITRON_Message_buffer_Get(mbfid, &location);
+ switch (location) {
+ case OBJECTS_REMOTE:
+ case OBJECTS_ERROR: /* Multiprocessing not supported */
+ return _ITRON_Message_buffer_Clarify_get_id_error(mbfid);
+
+ case OBJECTS_LOCAL:
+ _CORE_message_queue_Seize(
+ &the_message_buffer->message_queue,
+ the_message_buffer->Object.id,
+ msg,
+ p_msgsz,
+ wait,
+ interval
+ );
+ _Thread_Enable_dispatch();
+ status = (CORE_message_queue_Status)_Thread_Executing->Wait.return_code;
+ return
+ _ITRON_Message_buffer_Translate_core_message_buffer_return_code(status);
+ }
+
+ /*
+ * If multiprocessing were supported, this is where we would announce
+ * the existence of the semaphore to the rest of the system.
+ */
+
+#if defined(RTEMS_MULTIPROCESSING)
+#endif
+ return E_OK;
+}
diff --git a/cpukit/itron/src/trcv_mbx.c b/cpukit/itron/src/trcv_mbx.c
new file mode 100644
index 0000000000..62a3098140
--- /dev/null
+++ b/cpukit/itron/src/trcv_mbx.c
@@ -0,0 +1,76 @@
+/*
+ * ITRON 3.0 Mailbox Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/mbox.h>
+#include <rtems/itron/task.h>
+
+/*
+ * trcv_msg - Receive Message from Mailbox with Timeout
+ */
+
+ER trcv_msg(
+ T_MSG **ppk_msg,
+ ID mbxid,
+ TMO tmout
+)
+{
+ register ITRON_Mailbox_Control *the_mailbox;
+ Watchdog_Interval interval;
+ boolean wait;
+ Objects_Locations location;
+ uint32_t size;
+
+ if (!ppk_msg)
+ return E_PAR;
+
+ interval = 0;
+ if ( tmout == TMO_POL ) {
+ wait = FALSE;
+ } else {
+ wait = TRUE;
+ if ( tmout != TMO_FEVR )
+ interval = TOD_MILLISECONDS_TO_TICKS(tmout);
+ }
+
+ if ( wait && _ITRON_Is_in_non_task_state() )
+ return E_CTX;
+
+ the_mailbox = _ITRON_Mailbox_Get( mbxid, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE:
+ case OBJECTS_ERROR:
+ return _ITRON_Mailbox_Clarify_get_id_error( mbxid );
+
+ case OBJECTS_LOCAL:
+
+ _CORE_message_queue_Seize(
+ &the_mailbox->message_queue,
+ the_mailbox->Object.id,
+ ppk_msg,
+ &size,
+ wait,
+ interval
+ );
+ break;
+ }
+
+ _ITRON_return_errorno(
+ _ITRON_Mailbox_Translate_core_message_queue_return_code(
+ _Thread_Executing->Wait.return_code ) );
+}
diff --git a/cpukit/itron/src/tslp_tsk.c b/cpukit/itron/src/tslp_tsk.c
new file mode 100644
index 0000000000..54fe83cf45
--- /dev/null
+++ b/cpukit/itron/src/tslp_tsk.c
@@ -0,0 +1,36 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/score/thread.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+#include <rtems/itron/task.h>
+
+
+/*
+ * tslp_tsk - Sleep Task with Timeout
+ */
+
+ER tslp_tsk(
+ TMO tmout
+)
+{
+ return E_OK;
+}
diff --git a/cpukit/itron/src/tsnd_mbf.c b/cpukit/itron/src/tsnd_mbf.c
new file mode 100644
index 0000000000..841d0b8756
--- /dev/null
+++ b/cpukit/itron/src/tsnd_mbf.c
@@ -0,0 +1,90 @@
+/*
+ * ITRON Message Buffer Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/msgbuffer.h>
+#include <rtems/itron/task.h>
+
+#include <assert.h> /* only for blocking */
+
+/*
+ * tsnd_mbf - Send Message to MessageBuffer with Timeout
+ */
+
+ER tsnd_mbf(
+ ID mbfid,
+ VP msg,
+ INT msgsz,
+ TMO tmout
+)
+{
+ ITRON_Message_buffer_Control *the_message_buffer;
+ Objects_Locations location;
+ Watchdog_Interval interval;
+ boolean wait;
+ CORE_message_queue_Status msg_status;
+
+ if (msgsz <= 0 || !msg)
+ return E_PAR;
+
+ interval = 0;
+ if ( tmout == TMO_POL ) {
+ wait = FALSE;
+ } else {
+ wait = TRUE;
+ if ( tmout != TMO_FEVR )
+ interval = TOD_MILLISECONDS_TO_TICKS(tmout);
+ }
+
+ if ( wait && _ITRON_Is_in_non_task_state() )
+ return E_CTX;
+
+ the_message_buffer = _ITRON_Message_buffer_Get(mbfid, &location);
+ switch (location) {
+ case OBJECTS_REMOTE:
+ case OBJECTS_ERROR: /* Multiprocessing not supported */
+ return _ITRON_Message_buffer_Clarify_get_id_error(mbfid);
+
+ case OBJECTS_LOCAL:
+ /* XXX Submit needs to take into account blocking */
+ msg_status = _CORE_message_queue_Submit(
+ &the_message_buffer->message_queue,
+ msg,
+ msgsz,
+ the_message_buffer->Object.id,
+ NULL,
+ CORE_MESSAGE_QUEUE_SEND_REQUEST,
+ wait, /* sender may block */
+ interval /* timeout interval */
+ );
+ _Thread_Enable_dispatch();
+ return _ITRON_Message_buffer_Translate_core_message_buffer_return_code(
+ msg_status
+ );
+ }
+
+ /*
+ * If multiprocessing were supported, this is where we would announce
+ * the existence of the semaphore to the rest of the system.
+ */
+
+#if defined(RTEMS_MULTIPROCESSING)
+#endif
+
+ return E_OK;
+}
diff --git a/cpukit/itron/src/twai_sem.c b/cpukit/itron/src/twai_sem.c
new file mode 100644
index 0000000000..133d0647be
--- /dev/null
+++ b/cpukit/itron/src/twai_sem.c
@@ -0,0 +1,69 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/semaphore.h>
+#include <rtems/itron/task.h>
+#include <rtems/score/tod.h>
+
+/*
+ * twai_sem - Wait on Semaphore with Timeout
+ *
+ * This function implements the ITRON 3.0 twai_sem() service.
+ */
+
+ER twai_sem(
+ ID semid,
+ TMO tmout
+)
+{
+ ITRON_Semaphore_Control *the_semaphore;
+ Objects_Locations location;
+ Watchdog_Interval interval;
+ boolean wait;
+ CORE_semaphore_Status status;
+
+ interval = 0;
+ if ( tmout == TMO_POL ) {
+ wait = FALSE;
+ } else {
+ wait = TRUE;
+ if ( tmout != TMO_FEVR )
+ interval = TOD_MILLISECONDS_TO_TICKS(tmout);
+ }
+
+ if ( wait && _ITRON_Is_in_non_task_state() )
+ return E_CTX;
+
+ the_semaphore = _ITRON_Semaphore_Get( semid, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE: /* Multiprocessing not supported */
+ case OBJECTS_ERROR:
+ return _ITRON_Semaphore_Clarify_get_id_error( semid );
+
+ case OBJECTS_LOCAL:
+ _CORE_semaphore_Seize(
+ &the_semaphore->semaphore,
+ the_semaphore->Object.id,
+ wait, /* wait for a timeout */
+ interval /* timeout value */
+ );
+ _Thread_Enable_dispatch();
+ status = (CORE_semaphore_Status) _Thread_Executing->Wait.return_code;
+ return _ITRON_Semaphore_Translate_core_semaphore_return_code( status );
+ }
+ return E_OK;
+}
diff --git a/cpukit/itron/src/vmempool.c b/cpukit/itron/src/vmempool.c
new file mode 100644
index 0000000000..916c9d5e61
--- /dev/null
+++ b/cpukit/itron/src/vmempool.c
@@ -0,0 +1,145 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/vmempool.h>
+
+/*
+ * _ITRON_Variable_memory_pool_Manager_initialization
+ *
+ * This routine initializes all variable memory pool manager related
+ * data structures.
+ *
+ * Input parameters:
+ * maximum_variable_memory_pools - maximum configured variable memory pools
+ *
+ * Output parameters: NONE
+ */
+
+void _ITRON_Variable_memory_pool_Manager_initialization(
+ uint32_t maximum_variable_memory_pools
+)
+{
+ _Objects_Initialize_information(
+ &_ITRON_Variable_memory_pool_Information, /* object information table */
+ OBJECTS_ITRON_API, /* object API */
+ OBJECTS_ITRON_VARIABLE_MEMORY_POOLS, /* object class */
+ maximum_variable_memory_pools, /* maximum objects of this class */
+ sizeof( ITRON_Variable_memory_pool_Control ),
+ /* size of this object's control block */
+ FALSE, /* TRUE if names for this object are strings */
+ ITRON_MAXIMUM_NAME_LENGTH /* maximum length of each object's name */
+#if defined(RTEMS_MULTIPROCESSING)
+ ,
+ FALSE, /* TRUE if this is a global object class */
+ NULL /* Proxy extraction support callout */
+#endif
+ );
+
+ /*
+ * Register the MP Process Packet routine.
+ *
+ * NOTE: No MP Support YET in RTEMS ITRON implementation.
+ */
+
+}
+
+/*
+ * cre_mpl - Create Variable-Size Memorypool
+ */
+
+ER cre_mpl(
+ ID mplid,
+ T_CMPL *pk_cmpl
+)
+{
+ return E_OK;
+}
+
+/*
+ * del_mpl - Delete Variable-Size Memorypool
+ */
+
+ER del_mpl(
+ ID mplid
+)
+{
+ return E_OK;
+}
+
+/*
+ * get_blk - Get Variable-Size Memory Block
+ */
+
+ER get_blk(
+ VP *p_blk,
+ ID mplid,
+ INT blksz
+)
+{
+ return E_OK;
+}
+
+/*
+ * pget_blk - Poll and Get Variable-Size Memory Block
+ */
+
+ER pget_blk(
+ VP *p_blk,
+ ID mplid,
+ INT blksz
+)
+{
+ return E_OK;
+}
+
+/*
+ * tget_blk - Get Variable-Size Memory Block with Timeout
+ */
+
+ER tget_blk(
+ VP *p_blk,
+ ID mplid,
+ INT blksz,
+ TMO tmout
+)
+{
+ return E_OK;
+}
+
+/*
+ * rel_blk - Release Variable-Size Memory Block
+ */
+
+ER rel_blk(
+ ID mplid,
+ VP blk
+)
+{
+ return E_OK;
+}
+
+/*
+ * ref_mpl - Reference Variable-Size Memorypool Status
+ */
+
+ER ref_mpl(
+ T_RMPL *pk_rmpl,
+ ID mplid
+)
+{
+ return E_OK;
+}
diff --git a/cpukit/itron/src/wai_sem.c b/cpukit/itron/src/wai_sem.c
new file mode 100644
index 0000000000..7c4364b594
--- /dev/null
+++ b/cpukit/itron/src/wai_sem.c
@@ -0,0 +1,33 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/itron/semaphore.h>
+#include <rtems/itron/task.h>
+#include <rtems/score/tod.h>
+
+/*
+ * wai_sem - Wait on Semaphore
+ *
+ * This function implements the ITRON 3.0 wai_sem() service.
+ */
+
+ER wai_sem(
+ ID semid
+)
+{
+ return twai_sem( semid, TMO_FEVR );
+}
diff --git a/cpukit/itron/src/wup_tsk.c b/cpukit/itron/src/wup_tsk.c
new file mode 100644
index 0000000000..bec817c0ba
--- /dev/null
+++ b/cpukit/itron/src/wup_tsk.c
@@ -0,0 +1,36 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/itron.h>
+
+#include <rtems/score/thread.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+#include <rtems/itron/task.h>
+
+
+/*
+ * wup_tsk - Wakeup Other Task
+ */
+
+ER wup_tsk(
+ ID tskid
+)
+{
+ return E_OK;
+}
diff --git a/cpukit/libblock/.cvsignore b/cpukit/libblock/.cvsignore
new file mode 100644
index 0000000000..282522db03
--- /dev/null
+++ b/cpukit/libblock/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/cpukit/libblock/Makefile.am b/cpukit/libblock/Makefile.am
new file mode 100644
index 0000000000..d79be4e589
--- /dev/null
+++ b/cpukit/libblock/Makefile.am
@@ -0,0 +1,68 @@
+##
+## $Id$
+##
+
+include $(top_srcdir)/automake/multilib.am
+include $(top_srcdir)/automake/compile.am
+
+AM_CPPFLAGS += -I$(top_builddir)
+
+CLEANFILES =
+
+if !UNIX
+include_rtemsdir = $(includedir)/rtems
+
+EXTRA_LIBRARIES = libblock.a
+CLEANFILES += libblock.a
+libblock_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libblock_g.a
+CLEANFILES += libblock_g.a
+libblock_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+include_rtems_HEADERS = include/rtems/bdbuf.h include/rtems/blkdev.h \
+ include/rtems/diskdevs.h include/rtems/ramdisk.h \
+ include/rtems/ide_part_table.h
+
+libblock_a_SOURCES = src/bdbuf.c src/blkdev.c src/diskdevs.c src/ramdisk.c \
+ src/ide_part_table.c
+
+libblock_g_a_SOURCES = $(libblock_a_SOURCES)
+
+all-local: $(PREINSTALL_FILES) libblock$(LIB_VARIANT).a
+endif
+
+PREINSTALL_DIRS =
+PREINSTALL_FILES =
+
+if !UNIX
+$(PROJECT_INCLUDE)/rtems/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems
+ @: > $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/bdbuf.h: include/rtems/bdbuf.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/bdbuf.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/bdbuf.h
+
+$(PROJECT_INCLUDE)/rtems/blkdev.h: include/rtems/blkdev.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/blkdev.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/blkdev.h
+
+$(PROJECT_INCLUDE)/rtems/diskdevs.h: include/rtems/diskdevs.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/diskdevs.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/diskdevs.h
+
+$(PROJECT_INCLUDE)/rtems/ramdisk.h: include/rtems/ramdisk.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/ramdisk.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/ramdisk.h
+
+$(PROJECT_INCLUDE)/rtems/ide_part_table.h: include/rtems/ide_part_table.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/ide_part_table.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/ide_part_table.h
+endif
+
+CLEANFILES += $(PREINSTALL_FILES)
+DISTCLEANFILES = $(PREINSTALL_DIRS)
+
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/libblock/README b/cpukit/libblock/README
new file mode 100644
index 0000000000..671cc7f645
--- /dev/null
+++ b/cpukit/libblock/README
@@ -0,0 +1,14 @@
+#
+# $Id$
+#
+
+This directory contains the block device (HDD, CDROMs, etc) support code.
+It includes:
+ - block device driver interface
+ - generic open/close/read/write/ioctl primitives for block device drivers
+ - disk I/O buffering
+ - logical disk support
+ - RAM disk block device driver
+
+Victor V. Vengerov, <vvv@oktet.ru>
+November, 7 2001
diff --git a/cpukit/libblock/include/rtems/bdbuf.h b/cpukit/libblock/include/rtems/bdbuf.h
new file mode 100644
index 0000000000..f2c2bfa567
--- /dev/null
+++ b/cpukit/libblock/include/rtems/bdbuf.h
@@ -0,0 +1,275 @@
+/* bdbuf.h -- block device buffer management
+ *
+ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Victor V. Vengerov <vvv@oktet.ru>
+ *
+ * @(#) $Id$
+ */
+
+#ifndef __RTEMS_LIBBLOCK_BDBUF_H__
+#define __RTEMS_LIBBLOCK_BDBUF_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <rtems/chain.h>
+
+#include "rtems/blkdev.h"
+#include "rtems/diskdevs.h"
+
+
+/*
+ * To manage buffers we using Buffer Descriptors.
+ * To speed-up buffer lookup descriptors are organized in AVL-Tree.
+ * The fields 'dev' and 'block' are search key.
+ */
+
+/* Buffer descriptors
+ * Descriptors organized in AVL-tree to speedup buffer lookup.
+ * dev and block fields are search key in AVL-tree.
+ * Modified buffers, free buffers and used buffers linked in 'mod', 'free' and
+ * 'lru' chains appropriately.
+ */
+
+typedef struct bdbuf_buffer {
+ Chain_Node link; /* Link in the lru, mod or free chains */
+
+ struct bdbuf_avl_node {
+ signed char cache; /* Cache */
+
+ struct bdbuf_buffer* left; /* Left Child */
+ struct bdbuf_buffer* right; /* Right Child */
+
+ signed char bal; /* The balance of the sub-tree */
+ } avl;
+
+ dev_t dev; /* device number */
+ blkdev_bnum block; /* block number on the device */
+
+ char *buffer; /* Pointer to the buffer memory area */
+ rtems_status_code status; /* Last I/O operation completion status */
+ int error; /* If status != RTEMS_SUCCESSFUL, this field contains
+ errno value which can be used by user later */
+ boolean modified:1; /* =1 if buffer was modified */
+ boolean in_progress:1; /* =1 if exchange with disk is in progress;
+ need to wait on semaphore */
+ boolean actual:1; /* Buffer contains actual data */
+ int use_count; /* Usage counter; incremented when somebody use
+ this buffer; decremented when buffer released
+ without modification or when buffer is flushed
+ by swapout task */
+
+ rtems_bdpool_id pool; /* Identifier of buffer pool to which this buffer
+ belongs */
+ CORE_mutex_Control transfer_sema;
+ /* Transfer operation semaphore */
+} bdbuf_buffer;
+
+
+
+/* bdbuf_config structure describes block configuration (size,
+ * amount, memory location) for buffering layer
+ */
+typedef struct rtems_bdbuf_config {
+ int size; /* Size of block */
+ int num; /* Number of blocks of appropriate size */
+ char *mem_area; /* Pointer to the blocks location or NULL, in this
+ case memory for blocks will be allocated by
+ Buffering Layer with the help of RTEMS partition
+ manager */
+} rtems_bdbuf_config;
+
+extern rtems_bdbuf_config rtems_bdbuf_configuration[];
+extern int rtems_bdbuf_configuration_size;
+
+/* rtems_bdbuf_init --
+ * Prepare buffering layer to work - initialize buffer descritors
+ * and (if it is neccessary) buffers. Buffers will be allocated accoriding
+ * to the configuration table, each entry describes kind of block and
+ * amount requested. After initialization all blocks is placed into
+ * free elements lists.
+ *
+ * PARAMETERS:
+ * conf_table - pointer to the buffers configuration table
+ * size - number of entries in configuration table
+ *
+ * RETURNS:
+ * RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
+ * or error code if error is occured)
+ */
+rtems_status_code
+rtems_bdbuf_init(rtems_bdbuf_config *conf_table, int size);
+
+
+/* rtems_bdbuf_get --
+ * Obtain block buffer. If specified block already cached (i.e. there's
+ * block in the _modified_, or _recently_used_), return address
+ * of appropriate buffer descriptor and increment reference counter to 1.
+ * If block is not cached, allocate new buffer and return it. Data
+ * shouldn't be read to the buffer from media; buffer may contains
+ * arbitrary data. This primitive may be blocked if there are no free
+ * buffer descriptors available and there are no unused non-modified
+ * (or synchronized with media) buffers available.
+ *
+ * PARAMETERS:
+ * device - device number (constructed of major and minor device number)
+ * block - linear media block number
+ * bd - address of variable to store pointer to the buffer descriptor
+ *
+ * RETURNS:
+ * RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
+ * or error code if error is occured)
+ *
+ * SIDE EFFECTS:
+ * bufget_sema semaphore obtained by this primitive.
+ */
+rtems_status_code
+rtems_bdbuf_get(dev_t device, blkdev_bnum block, bdbuf_buffer **bdb_ptr);
+
+/* rtems_bdbuf_read --
+ * (Similar to the rtems_bdbuf_get, except reading data from media)
+ * Obtain block buffer. If specified block already cached, return address
+ * of appropriate buffer and increment reference counter to 1. If block is
+ * not cached, allocate new buffer and read data to it from the media.
+ * This primitive may be blocked on waiting until data to be read from
+ * media, if there are no free buffer descriptors available and there are
+ * no unused non-modified (or synchronized with media) buffers available.
+ *
+ * PARAMETERS:
+ * device - device number (consists of major and minor device number)
+ * block - linear media block number
+ * bd - address of variable to store pointer to the buffer descriptor
+ *
+ * RETURNS:
+ * RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
+ * or error code if error is occured)
+ *
+ * SIDE EFFECTS:
+ * bufget_sema and transfer_sema semaphores obtained by this primitive.
+ */
+rtems_status_code
+rtems_bdbuf_read(dev_t device, blkdev_bnum block, bdbuf_buffer **bdb_ptr);
+
+/* rtems_bdbuf_release --
+ * Release buffer allocated before. This primitive decrease the
+ * usage counter. If it is zero, further destiny of buffer depends on
+ * 'modified' status. If buffer was modified, it is placed to the end of
+ * mod list and flush task waken up. If buffer was not modified,
+ * it is placed to the end of lru list, and bufget_sema released, allowing
+ * to reuse this buffer.
+ *
+ * PARAMETERS:
+ * bd_buf - pointer to the bdbuf_buffer structure previously obtained using
+ * get/read primitive.
+ *
+ * RETURNS:
+ * RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
+ * or error code if error is occured)
+ *
+ * SIDE EFFECTS:
+ * flush_sema and bufget_sema semaphores may be released by this primitive.
+ */
+rtems_status_code
+rtems_bdbuf_release(bdbuf_buffer *bd_buf);
+
+/* rtems_bdbuf_release_modified --
+ * Release buffer allocated before, assuming that it is _modified_ by
+ * it's owner. This primitive decrease usage counter for buffer, mark
+ * buffer descriptor as modified. If usage counter is 0, insert it at
+ * end of mod chain and release flush_sema semaphore to activate the
+ * flush task.
+ *
+ * PARAMETERS:
+ * bd_buf - pointer to the bdbuf_buffer structure previously obtained using
+ * get/read primitive.
+ *
+ * RETURNS:
+ * RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
+ * or error code if error is occured)
+ *
+ * SIDE EFFECTS:
+ * flush_sema semaphore may be released by this primitive.
+ */
+rtems_status_code
+rtems_bdbuf_release_modified(bdbuf_buffer *bd_buf);
+
+/* rtems_bdbuf_sync --
+ * Wait until specified buffer synchronized with disk. Invoked on exchanges
+ * critical for data consistency on the media. This primitive mark owned
+ * block as modified, decrease usage counter. If usage counter is 0,
+ * block inserted to the mod chain and flush_sema semaphore released.
+ * Finally, primitives blocked on transfer_sema semaphore.
+ *
+ * PARAMETERS:
+ * bd_buf - pointer to the bdbuf_buffer structure previously obtained using
+ * get/read primitive.
+ *
+ * RETURNS:
+ * RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
+ * or error code if error is occured)
+ *
+ * SIDE EFFECTS:
+ * Primitive may be blocked on transfer_sema semaphore.
+ */
+rtems_status_code
+rtems_bdbuf_sync(bdbuf_buffer *bd_buf);
+
+/* rtems_bdbuf_syncdev --
+ * Synchronize with disk all buffers containing the blocks belonging to
+ * specified device.
+ *
+ * PARAMETERS:
+ * dev - block device number
+ *
+ * RETURNS:
+ * RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
+ * or error code if error is occured)
+ */
+rtems_status_code
+rtems_bdbuf_syncdev(dev_t dev);
+
+/* rtems_bdbuf_find_pool --
+ * Find first appropriate buffer pool. This primitive returns the index
+ * of first buffer pool which block size is greater than or equal to
+ * specified size.
+ *
+ * PARAMETERS:
+ * block_size - requested block size
+ * pool - placeholder for result
+ *
+ * RETURNS:
+ * RTEMS status code: RTEMS_SUCCESSFUL if operation completed successfully,
+ * RTEMS_INVALID_SIZE if specified block size is invalid (not a power
+ * of 2), RTEMS_NOT_DEFINED if buffer pool for this or greater block size
+ * is not configured.
+ */
+rtems_status_code
+rtems_bdbuf_find_pool(int block_size, rtems_bdpool_id *pool);
+
+/* rtems_bdbuf_get_pool_info --
+ * Obtain characteristics of buffer pool with specified number.
+ *
+ * PARAMETERS:
+ * pool - buffer pool number
+ * block_size - block size for which buffer pool is configured returned
+ * there
+ * blocks - number of buffers in buffer pool returned there
+ *
+ * RETURNS:
+ * RTEMS status code: RTEMS_SUCCESSFUL if operation completed successfully,
+ * RTEMS_INVALID_NUMBER if appropriate buffer pool is not configured.
+ *
+ * NOTE:
+ * Buffer pools enumerated contiguously starting from 0.
+ */
+rtems_status_code
+rtems_bdbuf_get_pool_info(rtems_bdpool_id pool, int *block_size, int *blocks);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/libblock/include/rtems/blkdev.h b/cpukit/libblock/include/rtems/blkdev.h
new file mode 100644
index 0000000000..fac71522b6
--- /dev/null
+++ b/cpukit/libblock/include/rtems/blkdev.h
@@ -0,0 +1,151 @@
+/*
+ * blkdev.h - block device driver interface definitions
+ *
+ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Victor V. Vengerov <vvv@oktet.ru>
+ *
+ * @(#) $Id$
+ */
+
+#ifndef __RTEMS_LIBBLOCK_BLKDEV_H__
+#define __RTEMS_LIBBLOCK_BLKDEV_H__
+
+#include <rtems.h>
+#include <sys/ioctl.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Interface with device drivers
+ * Block device looks, initialized and behaves like traditional RTEMS device
+ * driver. Heart of the block device driver is in BIOREQUEST ioctl. This call
+ * puts I/O request to the block device queue, in priority order, for
+ * asynchronous processing. When driver executes request, req_done
+ * function invoked, so callee knows about it. Look for details below.
+ */
+
+
+/* Block device block number datatype */
+typedef uint32_t blkdev_bnum;
+
+/* Block device request type */
+typedef enum blkdev_request_op {
+ BLKDEV_REQ_READ, /* Read operation */
+ BLKDEV_REQ_WRITE /* Write operation */
+} blkdev_request_op;
+
+/* Type for block device request done callback function.
+ *
+ * PARAMETERS:
+ * arg - argument supplied in blkdev_request
+ * status - rtems status code for this operation
+ * errno - errno value to be passed to the user when
+ * status != RTEMS_SUCCESSFUL
+ */
+typedef void (* blkdev_request_cb)(void *arg,
+ rtems_status_code status,
+ int error);
+
+/* blkdev_sg_buffer
+ * Block device scatter/gather buffer structure
+ */
+typedef struct blkdev_sg_buffer {
+ uint32_t length; /* Buffer length */
+ void *buffer; /* Buffer pointer */
+} blkdev_sg_buffer;
+
+/* blkdev_request (Block Device Request) structure is
+ * used to read/write a number of blocks from/to device.
+ */
+typedef struct blkdev_request {
+ blkdev_request_op req; /* Block device operation (read or write) */
+ blkdev_request_cb req_done; /* Callback function */
+ void *done_arg; /* Argument to be passed to callback function*/
+ rtems_status_code status; /* Last I/O operation completion status */
+ int error; /* If status != RTEMS_SUCCESSFUL, this field
+ * contains error code
+ */
+ blkdev_bnum start; /* Start block number */
+ uint32_t count; /* Number of blocks to be exchanged */
+ uint32_t bufnum; /* Number of buffers provided */
+
+ blkdev_sg_buffer bufs[0];/* List of scatter/gather buffers */
+} blkdev_request;
+
+/* Block device IOCTL request codes */
+#define BLKIO_REQUEST _IOWR('B', 1, blkdev_request)
+#define BLKIO_GETBLKSIZE _IO('B', 2)
+#define BLKIO_GETSIZE _IO('B', 3)
+#define BLKIO_SYNCDEV _IO('B', 4)
+
+/* Device driver interface conventions suppose that driver may
+ * contain initialize/open/close/read/write/ioctl entry points. These
+ * primitives (except initialize) can be implemented in generic fashion,
+ * based upon supplied block device driver ioctl handler. Every block
+ * device driver should provide initialize entry point, which is register
+ * all block devices and appropriate ioctl handlers.
+ */
+
+#define GENERIC_BLOCK_DEVICE_DRIVER_ENTRIES \
+ rtems_blkdev_generic_open, rtems_blkdev_generic_close, \
+ rtems_blkdev_generic_read, rtems_blkdev_generic_write, \
+ rtems_blkdev_generic_ioctl
+
+/* blkdev_generic_read --
+ * Generic block device read primitive. Implemented using block device
+ * buffer management primitives.
+ */
+rtems_device_driver
+rtems_blkdev_generic_read(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+);
+
+/* blkdev_generic_write --
+ * Generic block device driver write primitive. Implemented using block
+ * device buffer management primitives.
+ */
+rtems_device_driver
+rtems_blkdev_generic_write(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+);
+
+/* blkdev_generic_open --
+ * Generic block device open primitive.
+ */
+rtems_device_driver
+rtems_blkdev_generic_open(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+);
+
+/* blkdev_generic_close --
+ * Generic block device close primitive.
+ */
+rtems_device_driver
+rtems_blkdev_generic_close(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+);
+
+/* blkdev_generic_ioctl --
+ * Generic block device ioctl primitive.
+ */
+rtems_device_driver
+rtems_blkdev_generic_ioctl(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/libblock/include/rtems/diskdevs.h b/cpukit/libblock/include/rtems/diskdevs.h
new file mode 100644
index 0000000000..b2bf652b1d
--- /dev/null
+++ b/cpukit/libblock/include/rtems/diskdevs.h
@@ -0,0 +1,206 @@
+/*
+ * logdisk.h - Physical and logical block devices (disks) support
+ *
+ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Victor V. Vengerov <vvv@oktet.ru>
+ *
+ * @(#) $Id$
+ */
+
+#ifndef __RTEMS_LIBBLOCK_LOGDISK_H__
+#define __RTEMS_LIBBLOCK_LOGDISK_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <stdlib.h>
+
+#include "rtems/blkdev.h"
+
+/* Buffer pool identifier */
+typedef int rtems_bdpool_id;
+
+/* Block device ioctl handler */
+typedef int (* block_device_ioctl) (dev_t dev, int req, void *argp);
+
+/* disk_device: Entry of this type created for every disk device (both for
+ * logical and physical disks).
+ * Array of arrays of pointers to disk_device structures maintained. First
+ * table indexed by major number and second table indexed by minor number.
+ * Such data organization allow quick lookup using data structure of
+ * moderated size.
+ */
+typedef struct disk_device {
+ dev_t dev; /* Device ID (major + minor) */
+ struct disk_device *phys_dev; /* Physical device ID (the same
+ as dev if this entry specifies
+ the physical device) */
+ char *name; /* Disk device name */
+ int uses; /* Use counter. Device couldn't be
+ removed if it is in use. */
+ int start; /* Starting block number (0 for
+ physical devices, block offset
+ on the related physical device
+ for logical device) */
+ int size; /* Size of physical or logical disk
+ in disk blocks */
+ int block_size; /* Size of device block (minimum
+ transfer unit) in bytes
+ (must be power of 2) */
+ int block_size_log2; /* log2 of block_size */
+ rtems_bdpool_id pool; /* Buffer pool assigned to this
+ device */
+ block_device_ioctl ioctl; /* ioctl handler for this block
+ device */
+} disk_device;
+
+/* rtems_disk_create_phys --
+ * Create physical disk entry. This function usually invoked from
+ * block device driver initialization code when physical device
+ * detected in the system. Device driver should provide ioctl handler
+ * to allow block device access operations. This primitive will register
+ * device in rtems (invoke rtems_io_register_name).
+ *
+ * PARAMETERS:
+ * dev - device identifier (major, minor numbers)
+ * block_size - size of disk block (minimum data transfer unit); must be
+ * power of 2
+ * disk_size - number of blocks on device
+ * handler - IOCTL handler (function providing basic block input/output
+ * request handling BIOREQUEST and other device management
+ * operations)
+ * name - character name of device (e.g. /dev/hda)
+ *
+ * RETURNS:
+ * RTEMS_SUCCESSFUL if information about new physical disk added, or
+ * error code if error occured (device already registered, wrong block
+ * size value, no memory available).
+ */
+rtems_status_code
+rtems_disk_create_phys(dev_t dev, int block_size, int disk_size,
+ block_device_ioctl handler,
+ char *name);
+
+/* rtems_disk_create_log --
+ * Create logical disk entry. Logical disk is contiguous area on physical
+ * disk. Disk may be splitted to several logical disks in several ways:
+ * manually or using information stored in blocks on physical disk
+ * (DOS-like partition table, BSD disk label, etc). This function usually
+ * invoked from application when application-specific splitting are in use,
+ * or from generic code which handle different logical disk organizations.
+ * This primitive will register device in rtems (invoke
+ * rtems_io_register_name).
+ *
+ * PARAMETERS:
+ * dev - logical device identifier (major, minor numbers)
+ * phys - physical device (block device which holds this logical disk)
+ * identifier
+ * start - starting block number on the physical device
+ * size - logical disk size in blocks
+ * name - logical disk name
+ *
+ * RETURNS:
+ * RTEMS_SUCCESSFUL if logical device successfully added, or error code
+ * if error occured (device already registered, no physical device
+ * exists, logical disk is out of physical disk boundaries, no memory
+ * available).
+ */
+rtems_status_code
+rtems_disk_create_log(dev_t dev, dev_t phys, int start, int size, char *name);
+
+/* rtems_disk_delete --
+ * Delete physical or logical disk device. Device may be deleted if its
+ * use counter (and use counters of all logical devices - if it is
+ * physical device) equal to 0. When physical device deleted,
+ * all logical devices deleted inherently. Appropriate devices removed
+ * from "/dev" filesystem.
+ *
+ * PARAMETERS:
+ * dev - device identifier (major, minor numbers)
+ *
+ * RETURNS:
+ * RTEMS_SUCCESSFUL if block device successfully deleted, or error code
+ * if error occured (device is not defined, device is in use).
+ */
+rtems_status_code
+rtems_disk_delete(dev_t dev);
+
+/* rtems_disk_lookup --
+ * Find block device descriptor by its device identifier. This function
+ * increment usage counter to 1. User should release disk_device structure
+ * by invoking rtems_disk_release primitive.
+ *
+ * PARAMETERS:
+ * dev - device identifier (major, minor numbers)
+ *
+ * RETURNS:
+ * pointer to the block device descriptor, or NULL if no such device
+ * exists.
+ */
+disk_device *
+rtems_disk_lookup(dev_t dev);
+
+/* rtems_disk_release --
+ * Release disk_device structure (decrement usage counter to 1).
+ *
+ * PARAMETERS:
+ * dd - pointer to disk device structure
+ *
+ * RETURNS:
+ * RTEMS_SUCCESSFUL
+ *
+ * NOTE:
+ * It should be implemented as inline function.
+ */
+rtems_status_code
+rtems_disk_release(disk_device *dd);
+
+/* rtems_disk_next --
+ * Disk device enumerator. Looking for device having device number larger
+ * than dev and return disk device descriptor for it. If there are no
+ * such device, NULL value returned.
+ *
+ * PARAMETERS:
+ * dev - device number (use -1 to start search)
+ *
+ * RETURNS:
+ * Pointer to the disk descriptor for next disk device, or NULL if all
+ * devices enumerated. */
+disk_device *
+rtems_disk_next(dev_t dev);
+
+/* rtems_diskio_initialize --
+ * Initialization of disk device library (initialize all data structures,
+ * etc.)
+ *
+ * PARAMETERS:
+ * none
+ *
+ * RETURNS:
+ * RTEMS_SUCCESSFUL if library initialized, or error code if error
+ * occured.
+ */
+rtems_status_code
+rtems_disk_io_initialize(void);
+
+/* rtems_diskio_done --
+ * Release all resources allocated for disk device interface.
+ *
+ * PARAMETERS:
+ * none
+ *
+ * RETURNS:
+ * RTEMS_SUCCESSFUL if all resources released, or error code if error
+ * occured.
+ */
+rtems_status_code
+rtems_disk_io_done(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/libblock/include/rtems/ide_part_table.h b/cpukit/libblock/include/rtems/ide_part_table.h
new file mode 100644
index 0000000000..e00f610e40
--- /dev/null
+++ b/cpukit/libblock/include/rtems/ide_part_table.h
@@ -0,0 +1,193 @@
+/*****************************************************************************
+ *
+ * ide_part_table.h
+ *
+ * The header file for library supporting "MS-DOS-style" partition table
+ *
+ *
+ * Copyright (C) 2002 OKTET Ltd., St.-Petersburg, Russia
+ *
+ * Author: Konstantin Abramenko <Konstantin.Abramenko@oktet.ru>
+ * Alexander Kukuta <Alexander.Kukuta@oktet.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ *
+ *****************************************************************************/
+
+#ifndef __RTEMS_IDE_PART_TABLE_H__
+#define __RTEMS_IDE_PART_TABLE_H__
+
+#include <assert.h>
+#include <rtems/chain.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <rtems.h>
+#include <rtems/blkdev.h>
+#include <rtems/libio.h>
+#include <rtems/libio_.h>
+#include <rtems/bdbuf.h>
+#include <rtems/seterr.h>
+
+/* Minor base number for all logical devices */
+#define RTEMS_IDE_SECTOR_BITS 9
+#define RTEMS_IDE_SECTOR_SIZE 512
+#define RTEMS_IDE_PARTITION_DESCRIPTOR_SIZE 16
+#define RTEMS_IDE_PARTITION_MAX_PARTITION_NUMBER 63
+#define RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER 4
+#define RTEMS_IDE_PARTITION_DEV_NAME_LENGTH_MAX 16
+
+#define RTEMS_IDE_PARTITION_MSDOS_SIGNATURE_DATA1 0x55
+#define RTEMS_IDE_PARTITION_MSDOS_SIGNATURE_DATA2 0xaa
+#define RTEMS_IDE_PARTITION_MSDOS_SIGNATURE_OFFSET 0x1fe
+#define RTEMS_IDE_PARTITION_TABLE_OFFSET 0x1be
+#define RTEMS_IDE_PARTITION_BOOTABLE_OFFSET 0
+#define RTEMS_IDE_PARTITION_SYS_TYPE_OFFSET 4
+#define RTEMS_IDE_PARTITION_START_OFFSET 8
+#define RTEMS_IDE_PARTITION_SIZE_OFFSET 12
+
+/*
+ * Conversion from and to little-endian byte order. (no-op on i386/i486)
+ */
+
+#if (CPU_BIG_ENDIAN == TRUE)
+# define LE_TO_CPU_U16(v) CPU_swap_u16(v)
+# define LE_TO_CPU_U32(v) CPU_swap_u32(v)
+# define CPU_TO_LE_U16(v) CPU_swap_u16(v)
+# define CPU_TO_LE_U32(v) CPU_swap_u32(v)
+#else
+# define LE_TO_CPU_U16(v) (v)
+# define LE_TO_CPU_U32(v) (v)
+# define CPU_TO_LE_U16(v) (v)
+# define CPU_TO_LE_U32(v) (v)
+#endif
+
+
+/*
+ * sector_data_t --
+ * corresponds to the sector on the device
+ */
+typedef struct sector_data_s
+{
+ uint32_t sector_num; /* sector number on the device */
+ uint8_t data[0]; /* raw sector data */
+} sector_data_t;
+
+
+/*
+ * Enum partition types
+ * see list at http://ata-atapi.com/hiwtab.htm
+ */
+enum {
+ EMPTY_PARTITION = 0x00,
+ DOS_FAT12_PARTITION = 0x01,
+ DOS_FAT16_PARTITION = 0x04,
+ EXTENDED_PARTITION = 0x05,
+ DOS_P32MB_PARTITION = 0x06,
+ FAT32_PARTITION = 0x0B,
+ FAT32_LBA_PARTITION = 0x0C,
+ FAT16_LBA_PARTITION = 0x0E,
+ DM6_PARTITION = 0x54,
+ EZD_PARTITION = 0x55,
+ DM6_AUX1PARTITION = 0x51,
+ DM6_AUX3PARTITION = 0x53,
+ LINUX_SWAP = 0x82,
+ LINUX_NATIVE = 0x83,
+ LINUX_EXTENDED = 0x85
+};
+
+
+/* Forward declaration */
+struct disk_desc_s;
+
+/*
+ * part_desc_t --
+ * contains all neccessary information about partition
+ */
+typedef struct part_desc_s {
+ uint8_t bootable; /* is the partition active */
+ uint8_t sys_type; /* type of partition */
+ uint8_t log_id; /* logical number of partition */
+ uint32_t start; /* first partition sector, in absolute numeration */
+ uint32_t size; /* size in sectors */
+ uint32_t end; /* last partition sector, end = start + size - 1 */
+ struct disk_desc_s *disk_desc; /* descriptor of disk, partition contains in */
+ struct part_desc_s *ext_part; /* extended partition containing this one */
+
+ /* partitions, containing in this one */
+ struct part_desc_s *sub_part[RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER];
+} part_desc_t;
+
+
+
+typedef struct disk_desc_s {
+ dev_t dev; /* device number */
+
+ /* device name in /dev filesystem */
+ uint8_t dev_name[RTEMS_IDE_PARTITION_DEV_NAME_LENGTH_MAX];
+
+ uint32_t sector_size; /* size of sector */
+ uint32_t sector_bits; /* the base-2 logarithm of sector_size */
+ uint32_t lba_size; /* total amount of sectors in lba address mode */
+ int last_log_id; /* used for logical disks enumerating */
+
+ /* primary partition descriptors */
+ part_desc_t *partitions[RTEMS_IDE_PARTITION_MAX_PARTITION_NUMBER];
+} disk_desc_t;
+
+
+/*
+ * rtems_ide_part_table_free --
+ * frees disk descriptor structure
+ *
+ * PARAMETERS:
+ * disk_desc - disc descriptor structure to free
+ *
+ * RETURNS:
+ * N/A
+ */
+void
+rtems_ide_part_table_free(disk_desc_t *disk_desc);
+
+
+/*
+ * rtems_ide_part_table_get --
+ * reads partition table structure from the device
+ * and creates disk description structure
+ *
+ * PARAMETERS:
+ * dev_name - path to physical device in /dev filesystem
+ * disk_desc - returned disc description structure
+ *
+ * RETURNS:
+ * RTEMS_SUCCESSFUL if success, or -1 and corresponding errno else
+ */
+rtems_status_code
+rtems_ide_part_table_get(const char *dev_name, disk_desc_t *disk_desc);
+
+
+/*
+ * rtems_ide_part_table_initialize --
+ * initializes logical devices on the physical IDE drive
+ *
+ * PARAMETERS:
+ * dev_name - path to physical device in /dev filesystem
+ *
+ * RETURNS:
+ * RTEMS_SUCCESSFUL if success, or -1 and corresponding errno else
+ */
+rtems_status_code
+rtems_ide_part_table_initialize(char *dev_name);
+
+
+#endif /* __RTEMS_IDE_PART_TABLE_H__ */
diff --git a/cpukit/libblock/include/rtems/ramdisk.h b/cpukit/libblock/include/rtems/ramdisk.h
new file mode 100644
index 0000000000..b9e8c238b8
--- /dev/null
+++ b/cpukit/libblock/include/rtems/ramdisk.h
@@ -0,0 +1,52 @@
+/* ramdisk.c -- RAM disk block device implementation
+ *
+ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Victor V. Vengerov <vvv@oktet.ru>
+ *
+ * @(#) $Id$
+ */
+
+#ifndef __RTEMS_LIBBLOCK_RAMDISK_H__
+#define __RTEMS_LIBBLOCK_RAMDISK_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems.h>
+
+#include "rtems/blkdev.h"
+
+/* RAM disk configuration table entry */
+typedef struct rtems_ramdisk_config {
+ int block_size; /* RAM disk block size */
+ int block_num; /* Number of blocks on this RAM disk */
+ void *location; /* RAM disk permanent location (out of RTEMS controlled
+ memory), or NULL if RAM disk memory should be
+ allocated dynamically */
+} rtems_ramdisk_config;
+
+/* If application want to use RAM disk, it should specify configuration of
+ * available RAM disks.
+ * The following is definitions for RAM disk configuration table
+ */
+extern rtems_ramdisk_config rtems_ramdisk_configuration[];
+extern int rtems_ramdisk_configuration_size;
+
+/* ramdisk_initialize --
+ * RAM disk driver initialization entry point.
+ */
+rtems_device_driver
+ramdisk_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg);
+
+#define RAMDISK_DRIVER_TABLE_ENTRY \
+ { ramdisk_initialize, GENERIC_BLOCK_DEVICE_DRIVER_ENTRIES }
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/libblock/src/bdbuf.c b/cpukit/libblock/src/bdbuf.c
new file mode 100644
index 0000000000..dd0cdbe83c
--- /dev/null
+++ b/cpukit/libblock/src/bdbuf.c
@@ -0,0 +1,1653 @@
+/*
+ * Disk I/O buffering
+ * Buffer managment
+ *
+ * Copyright (C) 2001 OKTET Ltd., St.-Peterburg, Russia
+ * Author: Andrey G. Ivanov <Andrey.Ivanov@oktet.ru>
+ * Victor V. Vengerov <vvv@oktet.ru>
+ * Alexander Kukuta <kam@oktet.ru>
+ *
+ * @(#) $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#include <rtems.h>
+#include <limits.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "rtems/bdbuf.h"
+
+/* Fatal errors: */
+#define BLKDEV_FATAL_ERROR(n) (((uint32_t)'B' << 24) | ((uint32_t)(n) & (uint32_t)0x00FFFFFF))
+#define BLKDEV_FATAL_BDBUF_CONSISTENCY BLKDEV_FATAL_ERROR(1)
+#define BLKDEV_FATAL_BDBUF_SWAPOUT BLKDEV_FATAL_ERROR(2)
+
+
+#define SWAPOUT_PRIORITY 15
+#define SWAPOUT_STACK_SIZE (RTEMS_MINIMUM_STACK_SIZE * 2)
+
+static rtems_task bdbuf_swapout_task(rtems_task_argument unused);
+
+/*
+ * The groups of the blocks with the same size are collected in the
+ * bd_pool. Note that a several of the buffer's groups with the
+ * same size can exists.
+ */
+typedef struct bdbuf_pool
+{
+ bdbuf_buffer *tree; /* Buffer descriptor lookup AVL tree root */
+
+ Chain_Control free; /* Free buffers list */
+ Chain_Control lru; /* Last recently used list */
+
+ int blksize; /* The size of the blocks (in bytes) */
+ int nblks; /* Number of blocks in this pool */
+ rtems_id bufget_sema; /* Buffer obtain counting semaphore */
+ void *mallocd_bufs; /* Pointer to the malloc'd buffer memory,
+ or NULL, if buffer memory provided in
+ buffer configuration */
+ bdbuf_buffer *bdbufs; /* Pointer to table of buffer descriptors
+ allocated for this buffer pool. */
+} bdbuf_pool;
+
+/* Buffering layer context definition */
+struct bdbuf_context {
+ bdbuf_pool *pool; /* Table of buffer pools */
+ int npools; /* Number of entries in pool table */
+
+ Chain_Control mod; /* Modified buffers list */
+ rtems_id flush_sema; /* Buffer flush semaphore; counting
+ semaphore; incremented when buffer
+ flushed to the disk; decremented when
+ buffer modified */
+ rtems_id swapout_task; /* Swapout task ID */
+};
+
+/* Block device request with a single buffer provided */
+typedef struct blkdev_request1 {
+ blkdev_request req;
+ blkdev_sg_buffer sg[1];
+} blkdev_request1;
+
+/* The static context of buffering layer */
+static struct bdbuf_context bd_ctx;
+
+#define SAFE
+#ifdef SAFE
+typedef rtems_mode preemption_key;
+
+#define DISABLE_PREEMPTION(key) \
+ do { \
+ rtems_task_mode(RTEMS_NO_PREEMPT, RTEMS_PREEMPT_MASK, &(key)); \
+ } while (0)
+
+#define ENABLE_PREEMPTION(key) \
+ do { \
+ rtems_mode temp; \
+ rtems_task_mode((key), RTEMS_PREEMPT_MASK, &temp); \
+ } while (0)
+
+#else
+
+typedef boolean preemption_key;
+
+#define DISABLE_PREEMPTION(key) \
+ do { \
+ (key) = _Thread_Executing->is_preemptible; \
+ _Thread_Executing->is_preemptible = 0; \
+ } while (0)
+
+#define ENABLE_PREEMPTION(key) \
+ do { \
+ _Thread_Executing->is_preemptible = (key); \
+ if (_Thread_Evaluate_mode()) \
+ _Thread_Dispatch(); \
+ } while (0)
+
+#endif
+
+
+/* The default maximum height of 32 allows for AVL trees having
+ between 5,704,880 and 4,294,967,295 nodes, depending on order of
+ insertion. You may change this compile-time constant as you
+ wish. */
+#ifndef AVL_MAX_HEIGHT
+#define AVL_MAX_HEIGHT 32
+#endif
+
+/*
+ * avl_search --
+ * Searches for the node with specified dev/block.
+ *
+ * PARAMETERS:
+ * root - pointer to the root node of the AVL-Tree.
+ * dev, block - search key
+ *
+ * RETURNS:
+ * NULL if node with specified dev/block not found
+ * non-NULL - pointer to the node with specified dev/block
+ */
+static bdbuf_buffer *
+avl_search(bdbuf_buffer **root, dev_t dev, blkdev_bnum block)
+{
+ bdbuf_buffer *p = *root;
+
+ while ((p != NULL) && ((p->dev != dev) || (p->block != block)))
+ {
+ if ((p->dev < dev) || ((p->dev == dev) && (p->block < block)))
+ {
+ p = p->avl.right;
+ }
+ else
+ {
+ p = p->avl.left;
+ }
+ }
+
+ return p;
+}
+
+
+/* avl_search_for_sync --
+ * Search in AVL tree for first modified buffer belongs to specified
+ * disk device.
+ *
+ * PARAMETERS:
+ * root - pointer to tree root
+ * dd - disk device descriptor
+ *
+ * RETURNS:
+ * Block buffer, or NULL if no modified blocks on specified device
+ * exists.
+ */
+static bdbuf_buffer *
+avl_search_for_sync(bdbuf_buffer **root, disk_device *dd)
+{
+ dev_t dev = dd->phys_dev->dev;
+ blkdev_bnum block_start = dd->start;
+ blkdev_bnum block_end = dd->start + dd->size - 1;
+
+ bdbuf_buffer *buf_stack[AVL_MAX_HEIGHT];
+ bdbuf_buffer **buf_prev = buf_stack;
+ bdbuf_buffer *p = *root;
+
+ while (p != NULL)
+ {
+ if ((p->dev < dev) || ((p->dev == dev) && (p->block < block_start)))
+ {
+ p = p->avl.right;
+ }
+ else if ((p->dev > dev) || ((p->dev == dev) && (p->block > block_end)))
+ {
+ p = p->avl.left;
+ }
+ else if (p->modified)
+ {
+ return p;
+ }
+ else
+ {
+ if (p->avl.right != NULL)
+ {
+ *buf_prev++ = p->avl.right;
+ }
+ p = p->avl.left;
+ }
+
+ if ((p == NULL) && (buf_prev > buf_stack))
+ {
+ p = *--buf_prev;
+ }
+ }
+
+ return p;
+}
+
+
+/*
+ * avl_insert --
+ * Inserts the specified node to the AVl-Tree.
+ *
+ * PARAMETERS:
+ * root - Pointer to pointer to the root node
+ * node - Pointer to the node to add.
+ *
+ * RETURNS:
+ * 0 - The node added successfully
+ * -1 - An error occured
+ */
+static int
+avl_insert(bdbuf_buffer **root, bdbuf_buffer *node)
+{
+ dev_t dev = node->dev;
+ blkdev_bnum block = node->block;
+
+ bdbuf_buffer *p = *root;
+ bdbuf_buffer *q = NULL;
+ bdbuf_buffer *p1, *p2;
+ bdbuf_buffer *buf_stack[AVL_MAX_HEIGHT];
+ bdbuf_buffer **buf_prev = buf_stack;
+
+ boolean modified = FALSE;
+
+ if (p == NULL)
+ {
+ *root = node;
+ node->avl.left = NULL;
+ node->avl.right = NULL;
+ node->avl.bal = 0;
+ return 0;
+ }
+
+ while (p != NULL)
+ {
+ *buf_prev++ = p;
+
+ if ((p->dev < dev) || ((p->dev == dev) && (p->block < block)))
+ {
+ p->avl.cache = 1;
+ q = p->avl.right;
+ if (q == NULL)
+ {
+ q = node;
+ p->avl.right = q = node;
+ break;
+ }
+ }
+ else if ((p->dev != dev) || (p->block != block))
+ {
+ p->avl.cache = -1;
+ q = p->avl.left;
+ if (q == NULL)
+ {
+ q = node;
+ p->avl.left = q;
+ break;
+ }
+ }
+ else
+ {
+ return -1;
+ }
+
+ p = q;
+ }
+
+ q->avl.left = q->avl.right = NULL;
+ q->avl.bal = 0;
+ modified = TRUE;
+ buf_prev--;
+
+ while (modified)
+ {
+ if (p->avl.cache == -1)
+ {
+ switch (p->avl.bal)
+ {
+ case 1:
+ p->avl.bal = 0;
+ modified = FALSE;
+ break;
+
+ case 0:
+ p->avl.bal = -1;
+ break;
+
+ case -1:
+ p1 = p->avl.left;
+ if (p1->avl.bal == -1) /* simple LL-turn */
+ {
+ p->avl.left = p1->avl.right;
+ p1->avl.right = p;
+ p->avl.bal = 0;
+ p = p1;
+ }
+ else /* double LR-turn */
+ {
+ p2 = p1->avl.right;
+ p1->avl.right = p2->avl.left;
+ p2->avl.left = p1;
+ p->avl.left = p2->avl.right;
+ p2->avl.right = p;
+ if (p2->avl.bal == -1) p->avl.bal = +1; else p->avl.bal = 0;
+ if (p2->avl.bal == +1) p1->avl.bal = -1; else p1->avl.bal = 0;
+ p = p2;
+ }
+ p->avl.bal = 0;
+ modified = FALSE;
+ break;
+
+ default:
+ break;
+ }
+ }
+ else
+ {
+ switch (p->avl.bal)
+ {
+ case -1:
+ p->avl.bal = 0;
+ modified = FALSE;
+ break;
+
+ case 0:
+ p->avl.bal = 1;
+ break;
+
+ case 1:
+ p1 = p->avl.right;
+ if (p1->avl.bal == 1) /* simple RR-turn */
+ {
+ p->avl.right = p1->avl.left;
+ p1->avl.left = p;
+ p->avl.bal = 0;
+ p = p1;
+ }
+ else /* double RL-turn */
+ {
+ p2 = p1->avl.left;
+ p1->avl.left = p2->avl.right;
+ p2->avl.right = p1;
+ p->avl.right = p2->avl.left;
+ p2->avl.left = p;
+ if (p2->avl.bal == +1) p->avl.bal = -1; else p->avl.bal = 0;
+ if (p2->avl.bal == -1) p1->avl.bal = +1; else p1->avl.bal = 0;
+ p = p2;
+ }
+ p->avl.bal = 0;
+ modified = FALSE;
+ break;
+
+ default:
+ break;
+ }
+ }
+ q = p;
+ if (buf_prev > buf_stack)
+ {
+ p = *--buf_prev;
+
+ if (p->avl.cache == -1)
+ {
+ p->avl.left = q;
+ }
+ else
+ {
+ p->avl.right = q;
+ }
+ }
+ else
+ {
+ *root = p;
+ break;
+ }
+ };
+
+ return 0;
+}
+
+
+/* avl_remove --
+ * removes the node from the tree.
+ *
+ * PARAMETERS:
+ * root_addr - Pointer to pointer to the root node
+ * node - Pointer to the node to remove
+ *
+ * RETURNS:
+ * 0 - Item removed
+ * -1 - No such item found
+ */
+static int
+avl_remove(bdbuf_buffer **root, const bdbuf_buffer *node)
+{
+ dev_t dev = node->dev;
+ blkdev_bnum block = node->block;
+
+ bdbuf_buffer *p = *root;
+ bdbuf_buffer *q, *r, *s, *p1, *p2;
+ bdbuf_buffer *buf_stack[AVL_MAX_HEIGHT];
+ bdbuf_buffer **buf_prev = buf_stack;
+
+ boolean modified = FALSE;
+
+ memset(buf_stack, 0, sizeof(buf_stack));
+
+ while (p != NULL)
+ {
+ *buf_prev++ = p;
+
+ if ((p->dev < dev) || ((p->dev == dev) && (p->block < block)))
+ {
+ p->avl.cache = 1;
+ p = p->avl.right;
+ }
+ else if ((p->dev != dev) || (p->block != block))
+ {
+ p->avl.cache = -1;
+ p = p->avl.left;
+ }
+ else
+ {
+ /* node found */
+ break;
+ }
+ }
+
+ if (p == NULL)
+ {
+ /* there is no such node */
+ return -1;
+ }
+
+ q = p;
+
+ buf_prev--;
+ if (buf_prev > buf_stack)
+ {
+ p = *(buf_prev - 1);
+ }
+ else
+ {
+ p = NULL;
+ }
+
+ /* at this moment q - is a node to delete, p is q's parent */
+ if (q->avl.right == NULL)
+ {
+ r = q->avl.left;
+ if (r != NULL)
+ {
+ r->avl.bal = 0;
+ }
+ q = r;
+ }
+ else
+ {
+ bdbuf_buffer **t;
+
+ r = q->avl.right;
+
+ if (r->avl.left == NULL)
+ {
+ r->avl.left = q->avl.left;
+ r->avl.bal = q->avl.bal;
+ r->avl.cache = 1;
+ *buf_prev++ = q = r;
+ }
+ else
+ {
+ t = buf_prev++;
+ s = r;
+
+ while (s->avl.left != NULL)
+ {
+ *buf_prev++ = r = s;
+ s = r->avl.left;
+ r->avl.cache = -1;
+ }
+
+ s->avl.left = q->avl.left;
+ r->avl.left = s->avl.right;
+ s->avl.right = q->avl.right;
+ s->avl.bal = q->avl.bal;
+ s->avl.cache = 1;
+
+ *t = q = s;
+ }
+ }
+
+ if (p != NULL)
+ {
+ if (p->avl.cache == -1)
+ {
+ p->avl.left = q;
+ }
+ else
+ {
+ p->avl.right = q;
+ }
+ }
+ else
+ {
+ *root = q;
+ }
+
+ modified = TRUE;
+
+ while (modified)
+ {
+ if (buf_prev > buf_stack)
+ {
+ p = *--buf_prev;
+ }
+ else
+ {
+ break;
+ }
+
+ if (p->avl.cache == -1)
+ {
+ /* rebalance left branch */
+ switch (p->avl.bal)
+ {
+ case -1:
+ p->avl.bal = 0;
+ break;
+ case 0:
+ p->avl.bal = 1;
+ modified = FALSE;
+ break;
+
+ case +1:
+ p1 = p->avl.right;
+
+ if (p1->avl.bal >= 0) /* simple RR-turn */
+ {
+ p->avl.right = p1->avl.left;
+ p1->avl.left = p;
+
+ if (p1->avl.bal == 0)
+ {
+ p1->avl.bal = -1;
+ modified = FALSE;
+ }
+ else
+ {
+ p->avl.bal = 0;
+ p1->avl.bal = 0;
+ }
+ p = p1;
+ }
+ else /* double RL-turn */
+ {
+ p2 = p1->avl.left;
+
+ p1->avl.left = p2->avl.right;
+ p2->avl.right = p1;
+ p->avl.right = p2->avl.left;
+ p2->avl.left = p;
+
+ if (p2->avl.bal == +1) p->avl.bal = -1; else p->avl.bal = 0;
+ if (p2->avl.bal == -1) p1->avl.bal = 1; else p1->avl.bal = 0;
+
+ p = p2;
+ p2->avl.bal = 0;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ else
+ {
+ /* rebalance right branch */
+ switch (p->avl.bal)
+ {
+ case +1:
+ p->avl.bal = 0;
+ break;
+
+ case 0:
+ p->avl.bal = -1;
+ modified = FALSE;
+ break;
+
+ case -1:
+ p1 = p->avl.left;
+
+ if (p1->avl.bal <= 0) /* simple LL-turn */
+ {
+ p->avl.left = p1->avl.right;
+ p1->avl.right = p;
+ if (p1->avl.bal == 0)
+ {
+ p1->avl.bal = 1;
+ modified = FALSE;
+ }
+ else
+ {
+ p->avl.bal = 0;
+ p1->avl.bal = 0;
+ }
+ p = p1;
+ }
+ else /* double LR-turn */
+ {
+ p2 = p1->avl.right;
+
+ p1->avl.right = p2->avl.left;
+ p2->avl.left = p1;
+ p->avl.left = p2->avl.right;
+ p2->avl.right = p;
+
+ if (p2->avl.bal == -1) p->avl.bal = 1; else p->avl.bal = 0;
+ if (p2->avl.bal == +1) p1->avl.bal = -1; else p1->avl.bal = 0;
+
+ p = p2;
+ p2->avl.bal = 0;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (buf_prev > buf_stack)
+ {
+ q = *(buf_prev - 1);
+
+ if (q->avl.cache == -1)
+ {
+ q->avl.left = p;
+ }
+ else
+ {
+ q->avl.right = p;
+ }
+ }
+ else
+ {
+ *root = p;
+ break;
+ }
+
+ }
+
+ return 0;
+}
+
+/* bdbuf_initialize_pool --
+ * Initialize single buffer pool.
+ *
+ * PARAMETERS:
+ * config - buffer pool configuration
+ * pool - pool number
+ *
+ * RETURNS:
+ * RTEMS_SUCCESSFUL, if buffer pool initialized successfully, or error
+ * code if error occured.
+ */
+static rtems_status_code
+bdbuf_initialize_pool(rtems_bdbuf_config *config, int pool)
+{
+ bdbuf_pool *p = bd_ctx.pool + pool;
+ unsigned char *bufs;
+ bdbuf_buffer *b;
+ rtems_status_code rc;
+ int i;
+
+ p->blksize = config->size;
+ p->nblks = config->num;
+ p->tree = NULL;
+
+ Chain_Initialize_empty(&p->free);
+ Chain_Initialize_empty(&p->lru);
+
+ /* Allocate memory for buffer descriptors */
+ p->bdbufs = calloc(config->num, sizeof(bdbuf_buffer));
+ if (p->bdbufs == NULL)
+ {
+ return RTEMS_NO_MEMORY;
+ }
+
+ /* Allocate memory for buffers if required */
+ if (config->mem_area == NULL)
+ {
+ bufs = p->mallocd_bufs = malloc(config->num * config->size);
+ if (bufs == NULL)
+ {
+ free(p->bdbufs);
+ return RTEMS_NO_MEMORY;
+ }
+ }
+ else
+ {
+ bufs = config->mem_area;
+ p->mallocd_bufs = NULL;
+ }
+
+ for (i = 0, b = p->bdbufs; i < p->nblks; i++, b++, bufs += p->blksize)
+ {
+ b->dev = -1; b->block = 0;
+ b->buffer = bufs;
+ b->actual = b->modified = b->in_progress = FALSE;
+ b->use_count = 0;
+ b->pool = pool;
+ _Chain_Append(&p->free, &b->link);
+ }
+
+ rc = rtems_semaphore_create(
+ rtems_build_name('B', 'U', 'F', 'G'),
+ p->nblks,
+ RTEMS_FIFO | RTEMS_COUNTING_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY |
+ RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL,
+ 0,
+ &p->bufget_sema);
+
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ free(p->bdbufs);
+ free(p->mallocd_bufs);
+ return rc;
+ }
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/* bdbuf_release_pool --
+ * Free resources allocated for buffer pool with specified number.
+ *
+ * PARAMETERS:
+ * pool - buffer pool number
+ *
+ * RETURNS:
+ * RTEMS_SUCCESSFUL
+ */
+static rtems_status_code
+bdbuf_release_pool(rtems_bdpool_id pool)
+{
+ bdbuf_pool *p = bd_ctx.pool + pool;
+ rtems_semaphore_delete(p->bufget_sema);
+ free(p->bdbufs);
+ free(p->mallocd_bufs);
+ return RTEMS_SUCCESSFUL;
+}
+
+/* rtems_bdbuf_init --
+ * Prepare buffering layer to work - initialize buffer descritors
+ * and (if it is neccessary)buffers. Buffers will be allocated accoriding
+ * to the configuration table, each entry describes kind of block and
+ * amount requested. After initialization all blocks is placed into
+ * free elements lists.
+ *
+ * PARAMETERS:
+ * conf_table - pointer to the buffers configuration table
+ * size - number of entries in configuration table
+ *
+ * RETURNS:
+ * RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
+ * or error code if error is occured)
+ */
+rtems_status_code
+rtems_bdbuf_init(rtems_bdbuf_config *conf_table, int size)
+{
+ rtems_bdpool_id i;
+ rtems_status_code rc;
+
+ if (size <= 0)
+ return RTEMS_INVALID_SIZE;
+
+ bd_ctx.npools = size;
+
+ /*
+ * Allocate memory for buffer pool descriptors
+ */
+ bd_ctx.pool = calloc(size, sizeof(bdbuf_pool));
+ if (bd_ctx.pool == NULL)
+ {
+ return RTEMS_NO_MEMORY;
+ }
+
+ Chain_Initialize_empty(&bd_ctx.mod);
+
+ /* Initialize buffer pools and roll out if something failed */
+ for (i = 0; i < size; i++)
+ {
+ rc = bdbuf_initialize_pool(conf_table + i, i);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ rtems_bdpool_id j;
+ for (j = 0; j < i - 1; j++)
+ {
+ bdbuf_release_pool(j);
+ }
+ return rc;
+ }
+ }
+
+ /* Create buffer flush semaphore */
+ rc = rtems_semaphore_create(
+ rtems_build_name('B', 'F', 'L', 'U'), 0,
+ RTEMS_FIFO | RTEMS_COUNTING_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY |
+ RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL, 0,
+ &bd_ctx.flush_sema);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ for (i = 0; i < size; i++)
+ bdbuf_release_pool(i);
+ free(bd_ctx.pool);
+ return rc;
+ }
+
+ /* Create and start swapout task */
+ rc = rtems_task_create(
+ rtems_build_name('B', 'S', 'W', 'P'),
+ SWAPOUT_PRIORITY,
+ SWAPOUT_STACK_SIZE,
+ RTEMS_DEFAULT_MODES | RTEMS_NO_PREEMPT,
+ RTEMS_DEFAULT_ATTRIBUTES,
+ &bd_ctx.swapout_task);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ rtems_semaphore_delete(bd_ctx.flush_sema);
+ for (i = 0; i < size; i++)
+ bdbuf_release_pool(i);
+ free(bd_ctx.pool);
+ return rc;
+ }
+
+ rc = rtems_task_start(bd_ctx.swapout_task, bdbuf_swapout_task, 0);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ rtems_task_delete(bd_ctx.swapout_task);
+ rtems_semaphore_delete(bd_ctx.flush_sema);
+ for (i = 0; i < size; i++)
+ bdbuf_release_pool(i);
+ free(bd_ctx.pool);
+ return rc;
+ }
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/* find_or_assign_buffer --
+ * Looks for buffer already assigned for this dev/block. If one is found
+ * obtain block buffer. If specified block already cached (i.e. there's
+ * block in the _modified_, or _recently_used_), return address
+ * of appropriate buffer descriptor and increment reference counter to 1.
+ * If block is not cached, allocate new buffer and return it. Data
+ * shouldn't be read to the buffer from media; buffer contains arbitrary
+ * data. This primitive may be blocked if there are no free buffer
+ * descriptors available and there are no unused non-modified (or
+ * synchronized with media) buffers available.
+ *
+ * PARAMETERS:
+ * device - device number (constructed of major and minor device number
+ * block - linear media block number
+ * ret_buf - address of the variable to store address of found descriptor
+ *
+ * RETURNS:
+ * RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
+ * or error code if error is occured)
+ *
+ * SIDE EFFEECTS:
+ * bufget_sema may be obtained by this primitive
+ *
+ * NOTE:
+ * It is assumed that primitive invoked when thread preemption is disabled.
+ */
+static rtems_status_code
+find_or_assign_buffer(disk_device *dd,
+ blkdev_bnum block,
+ bdbuf_buffer **ret_buf)
+{
+ bdbuf_buffer *bd_buf;
+ bdbuf_pool *bd_pool;
+ rtems_status_code rc;
+ dev_t device;
+ ISR_Level level;
+
+ int blksize;
+
+ device = dd->dev;
+ bd_pool = bd_ctx.pool + dd->pool;
+ blksize = dd->block_size;
+
+again:
+ /* Looking for buffer descriptor used for this dev/block. */
+ bd_buf = avl_search(&bd_pool->tree, device, block);
+
+ if (bd_buf == NULL)
+ {
+ /* Try to obtain semaphore without waiting first. It is the most
+ frequent case when reasonable number of buffers configured. If
+ it is failed, obtain semaphore blocking on it. In this case
+ it should be checked that appropriate buffer hasn't been loaded
+ by another thread, because this thread is preempted */
+ rc = rtems_semaphore_obtain(bd_pool->bufget_sema, RTEMS_NO_WAIT, 0);
+ if (rc == RTEMS_UNSATISFIED)
+ {
+ rc = rtems_semaphore_obtain(bd_pool->bufget_sema,
+ RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ bd_buf = avl_search(&bd_pool->tree, device, block);
+ if (bd_buf != NULL)
+ rtems_semaphore_release(bd_pool->bufget_sema);
+ }
+ }
+
+ if (bd_buf == NULL)
+ {
+ /* Assign new buffer descriptor */
+ if (_Chain_Is_empty(&bd_pool->free))
+ {
+ bd_buf = (bdbuf_buffer *)Chain_Get(&bd_pool->lru);
+ if (bd_buf != NULL)
+ {
+ int avl_result;
+ avl_result = avl_remove(&bd_pool->tree, bd_buf);
+ if (avl_result != 0)
+ {
+ rtems_fatal_error_occurred(BLKDEV_FATAL_BDBUF_CONSISTENCY);
+ return RTEMS_INTERNAL_ERROR;
+ }
+ }
+ }
+ else
+ {
+ bd_buf = (bdbuf_buffer *)Chain_Get(&(bd_pool->free));
+ }
+
+ if (bd_buf == NULL)
+ {
+ goto again;
+ }
+ else
+ {
+ bd_buf->dev = device;
+ bd_buf->block = block;
+#ifdef AVL_GPL
+ bd_buf->avl.link[0] = NULL;
+ bd_buf->avl.link[1] = NULL;
+#else
+ bd_buf->avl.left = NULL;
+ bd_buf->avl.right = NULL;
+#endif
+ bd_buf->use_count = 1;
+ bd_buf->modified = bd_buf->actual = bd_buf->in_progress = FALSE;
+ bd_buf->status = RTEMS_SUCCESSFUL;
+
+ if (avl_insert(&bd_pool->tree, bd_buf) != 0)
+ {
+ rtems_fatal_error_occurred(BLKDEV_FATAL_BDBUF_CONSISTENCY);
+ return RTEMS_INTERNAL_ERROR;
+ }
+
+ *ret_buf = bd_buf;
+
+ return RTEMS_SUCCESSFUL;
+ }
+ }
+ else
+ {
+ /* Buffer descriptor already assigned for this dev/block */
+ if (bd_buf->use_count == 0)
+ {
+ /* If we are removing from lru list, obtain the bufget_sema
+ * first. If we are removing from mod list, obtain flush sema.
+ * It should be obtained without blocking because we know
+ * that our buffer descriptor is in the list. */
+ if (bd_buf->modified)
+ {
+ rc = rtems_semaphore_obtain(bd_ctx.flush_sema,
+ RTEMS_NO_WAIT, 0);
+ }
+ else
+ {
+ rc = rtems_semaphore_obtain(bd_pool->bufget_sema,
+ RTEMS_NO_WAIT, 0);
+ }
+ /* It is possible that we couldn't obtain flush or bufget sema
+ * although buffer in the appropriate chain is available:
+ * semaphore may be released to swapout task, but this task
+ * actually did not start to process it. */
+ if (rc == RTEMS_UNSATISFIED)
+ rc = RTEMS_SUCCESSFUL;
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ rtems_fatal_error_occurred(BLKDEV_FATAL_BDBUF_CONSISTENCY);
+ return RTEMS_INTERNAL_ERROR;
+ }
+
+ /* Buffer descriptor is linked to the lru or mod chain. Remove
+ it from there. */
+ Chain_Extract(&bd_buf->link);
+ }
+ bd_buf->use_count++;
+ while (bd_buf->in_progress != 0)
+ {
+ rtems_interrupt_disable(level);
+ _CORE_mutex_Seize(&bd_buf->transfer_sema, 0, TRUE,
+ WATCHDOG_NO_TIMEOUT, level);
+ }
+
+ *ret_buf = bd_buf;
+ return RTEMS_SUCCESSFUL;
+ }
+}
+
+/* rtems_bdbuf_get --
+ * Obtain block buffer. If specified block already cached (i.e. there's
+ * block in the _modified_, or _recently_used_), return address
+ * of appropriate buffer descriptor and increment reference counter to 1.
+ * If block is not cached, allocate new buffer and return it. Data
+ * shouldn't be read to the buffer from media; buffer may contains
+ * arbitrary data. This primitive may be blocked if there are no free
+ * buffer descriptors available and there are no unused non-modified
+ * (or synchronized with media) buffers available.
+ *
+ * PARAMETERS:
+ * device - device number (constructed of major and minor device number)
+ * block - linear media block number
+ * bd - address of variable to store pointer to the buffer descriptor
+ *
+ * RETURNS:
+ * RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
+ * or error code if error is occured)
+ *
+ * SIDE EFFECTS:
+ * bufget_sema semaphore obtained by this primitive.
+ */
+rtems_status_code
+rtems_bdbuf_get(dev_t device, blkdev_bnum block, bdbuf_buffer **bd)
+{
+ rtems_status_code rc;
+ disk_device *dd;
+ disk_device *pdd;
+ preemption_key key;
+
+ /*
+ * Convert logical dev/block to physical one
+ */
+ dd = rtems_disk_lookup(device);
+ if (dd == NULL)
+ return RTEMS_INVALID_ID;
+
+ if (block >= dd->size)
+ {
+ rtems_disk_release(dd);
+ return RTEMS_INVALID_NUMBER;
+ }
+
+ pdd = dd->phys_dev;
+ block += dd->start;
+ rtems_disk_release(dd);
+
+ DISABLE_PREEMPTION(key);
+ rc = find_or_assign_buffer(pdd, block, bd);
+ ENABLE_PREEMPTION(key);
+
+ if (rc != RTEMS_SUCCESSFUL)
+ return rc;
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/* bdbuf_initialize_transfer_sema --
+ * Initialize transfer_sema mutex semaphore associated with buffer
+ * descriptor.
+ */
+static inline void
+bdbuf_initialize_transfer_sema(bdbuf_buffer *bd_buf)
+{
+ CORE_mutex_Attributes mutex_attr;
+ mutex_attr.lock_nesting_behavior = CORE_MUTEX_NESTING_BLOCKS;
+ mutex_attr.only_owner_release = FALSE;
+ mutex_attr.discipline = CORE_MUTEX_DISCIPLINES_FIFO;
+ mutex_attr.priority_ceiling = 0;
+
+ _CORE_mutex_Initialize(&bd_buf->transfer_sema,
+ &mutex_attr, CORE_MUTEX_LOCKED);
+}
+
+/* bdbuf_write_transfer_done --
+ * Callout function. Invoked by block device driver when data transfer
+ * to device (write) is completed. This function may be invoked from
+ * interrupt handler.
+ *
+ * PARAMETERS:
+ * arg - arbitrary argument specified in block device request
+ * structure (in this case - pointer to the appropriate
+ * bdbuf_buffer buffer descriptor structure).
+ * status - I/O completion status
+ * error - errno error code if status != RTEMS_SUCCESSFUL
+ *
+ * RETURNS:
+ * none
+ */
+static void
+bdbuf_write_transfer_done(void *arg, rtems_status_code status, int error)
+{
+ bdbuf_buffer *bd_buf = arg;
+ bd_buf->status = status;
+ bd_buf->error = RTEMS_IO_ERROR;
+ bd_buf->in_progress = bd_buf->modified = FALSE;
+ _CORE_mutex_Surrender(&bd_buf->transfer_sema, 0, NULL);
+ _CORE_mutex_Flush(&bd_buf->transfer_sema, NULL,
+ CORE_MUTEX_STATUS_SUCCESSFUL);
+}
+
+/* bdbuf_read_transfer_done --
+ * Callout function. Invoked by block device driver when data transfer
+ * from device (read) is completed. This function may be invoked from
+ * interrupt handler.
+ *
+ * PARAMETERS:
+ * arg - arbitrary argument specified in block device request
+ * structure (in this case - pointer to the appropriate
+ * bdbuf_buffer buffer descriptor structure).
+ * status - I/O completion status
+ * error - errno error code if status != RTEMS_SUCCESSFUL
+ *
+ * RETURNS:
+ * none
+ */
+static void
+bdbuf_read_transfer_done(void *arg, rtems_status_code status, int error)
+{
+ bdbuf_buffer *bd_buf = arg;
+ bd_buf->status = status;
+ bd_buf->error = RTEMS_IO_ERROR;
+ _CORE_mutex_Surrender(&bd_buf->transfer_sema, 0, NULL);
+ _CORE_mutex_Flush(&bd_buf->transfer_sema, NULL,
+ CORE_MUTEX_STATUS_SUCCESSFUL);
+}
+
+/* rtems_bdbuf_read --
+ * (Similar to the rtems_bdbuf_get, except reading data from media)
+ * Obtain block buffer. If specified block already cached, return address
+ * of appropriate buffer and increment reference counter to 1. If block is
+ * not cached, allocate new buffer and read data to it from the media.
+ * This primitive may be blocked on waiting until data to be read from
+ * media, if there are no free buffer descriptors available and there are
+ * no unused non-modified (or synchronized with media) buffers available.
+ *
+ * PARAMETERS:
+ * device - device number (consists of major and minor device number)
+ * block - linear media block number
+ * bd - address of variable to store pointer to the buffer descriptor
+ *
+ * RETURNS:
+ * RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
+ * or error code if error is occured)
+ *
+ * SIDE EFFECTS:
+ * bufget_sema and transfer_sema semaphores obtained by this primitive.
+ */
+rtems_status_code
+rtems_bdbuf_read(dev_t device,
+ blkdev_bnum block,
+ bdbuf_buffer **bd)
+{
+ preemption_key key;
+ ISR_Level level;
+
+ bdbuf_buffer *bd_buf;
+ rtems_status_code rc;
+ int result;
+ disk_device *dd;
+ disk_device *pdd;
+ blkdev_request1 req;
+
+ dd = rtems_disk_lookup(device);
+ if (dd == NULL)
+ return RTEMS_INVALID_ID;
+
+ if (block >= dd->size)
+ {
+ rtems_disk_release(dd);
+ return RTEMS_INVALID_NUMBER;
+ }
+
+ pdd = dd->phys_dev;
+ block += dd->start;
+
+ DISABLE_PREEMPTION(key);
+ rc = find_or_assign_buffer(pdd, block, &bd_buf);
+
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ ENABLE_PREEMPTION(key);
+ rtems_disk_release(dd);
+ return rc;
+ }
+
+ if (!bd_buf->actual)
+ {
+ bd_buf->in_progress = 1;
+
+ req.req.req = BLKDEV_REQ_READ;
+ req.req.req_done = bdbuf_read_transfer_done;
+ req.req.done_arg = bd_buf;
+ req.req.start = block;
+ req.req.count = 1;
+ req.req.bufnum = 1;
+ req.req.bufs[0].length = dd->block_size;
+ req.req.bufs[0].buffer = bd_buf->buffer;
+
+ bdbuf_initialize_transfer_sema(bd_buf);
+ result = dd->ioctl(pdd->dev, BLKIO_REQUEST, &req);
+ if (result == -1)
+ {
+ bd_buf->status = RTEMS_IO_ERROR;
+ bd_buf->error = errno;
+ bd_buf->actual = FALSE;
+ }
+ else
+ {
+ rtems_interrupt_disable(level);
+ _CORE_mutex_Seize(&bd_buf->transfer_sema, 0, TRUE,
+ WATCHDOG_NO_TIMEOUT, level);
+ bd_buf->actual = TRUE;
+ }
+ bd_buf->in_progress = FALSE;
+ }
+ rtems_disk_release(dd);
+
+ ENABLE_PREEMPTION(key);
+
+ *bd = bd_buf;
+
+ return RTEMS_SUCCESSFUL;
+}
+
+
+/* bdbuf_release --
+ * Release buffer. Decrease buffer usage counter. If it is zero, further
+ * processing depends on modified attribute. If buffer was modified, it
+ * is inserted into mod chain and swapout task waken up. If buffer was
+ * not modified, it is returned to the end of lru chain making it available
+ * for further use.
+ *
+ * PARAMETERS:
+ * bd_buf - pointer to the released buffer descriptor.
+ *
+ * RETURNS:
+ * RTEMS_SUCCESSFUL if buffer released successfully, or error code if
+ * error occured.
+ *
+ * NOTE:
+ * This is internal function. It is assumed that task made non-preemptive
+ * before its invocation.
+ */
+static rtems_status_code
+bdbuf_release(bdbuf_buffer *bd_buf)
+{
+ bdbuf_pool *bd_pool;
+ rtems_status_code rc = RTEMS_SUCCESSFUL;
+
+ if (bd_buf->use_count <= 0)
+ return RTEMS_INTERNAL_ERROR;
+
+ bd_pool = bd_ctx.pool + bd_buf->pool;
+
+ bd_buf->use_count--;
+
+ if (bd_buf->use_count == 0)
+ {
+ if (bd_buf->modified)
+ {
+
+ /* Buffer was modified. Insert buffer to the modified buffers
+ * list and initiate flushing. */
+ Chain_Append(&bd_ctx.mod, &bd_buf->link);
+
+ /* Release the flush_sema */
+ rc = rtems_semaphore_release(bd_ctx.flush_sema);
+ }
+ else
+ {
+ /* Buffer was not modified. Add this descriptor to the
+ * end of lru chain and make it available for reuse. */
+ Chain_Append(&bd_pool->lru, &bd_buf->link);
+ rc = rtems_semaphore_release(bd_pool->bufget_sema);
+ }
+ }
+ return rc;
+}
+
+
+/* rtems_bdbuf_release --
+ * Release buffer allocated before. This primitive decrease the
+ * usage counter. If it is zero, further destiny of buffer depends on
+ * 'modified' status. If buffer was modified, it is placed to the end of
+ * mod list and flush task waken up. If buffer was not modified,
+ * it is placed to the end of lru list, and bufget_sema released, allowing
+ * to reuse this buffer.
+ *
+ * PARAMETERS:
+ * bd_buf - pointer to the bdbuf_buffer structure previously obtained using
+ * get/read primitive.
+ *
+ * RETURNS:
+ * RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
+ * or error code if error is occured)
+ *
+ * SIDE EFFECTS:
+ * flush_sema and bufget_sema semaphores may be released by this primitive.
+ */
+rtems_status_code
+rtems_bdbuf_release(bdbuf_buffer *bd_buf)
+{
+ preemption_key key;
+ rtems_status_code rc = RTEMS_SUCCESSFUL;
+
+ if (bd_buf == NULL)
+ return RTEMS_INVALID_ADDRESS;
+
+ DISABLE_PREEMPTION(key);
+
+ rc = bdbuf_release(bd_buf);
+
+ ENABLE_PREEMPTION(key);
+
+ return rc;
+}
+
+/* rtems_bdbuf_release_modified --
+ * Release buffer allocated before, assuming that it is _modified_ by
+ * it's owner. This primitive decrease usage counter for buffer, mark
+ * buffer descriptor as modified. If usage counter is 0, insert it at
+ * end of mod chain and release flush_sema semaphore to activate the
+ * flush task.
+ *
+ * PARAMETERS:
+ * bd_buf - pointer to the bdbuf_buffer structure previously obtained using
+ * get/read primitive.
+ *
+ * RETURNS:
+ * RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
+ * or error code if error is occured)
+ *
+ * SIDE EFFECTS:
+ * flush_sema semaphore may be released by this primitive.
+ */
+rtems_status_code
+rtems_bdbuf_release_modified(bdbuf_buffer *bd_buf)
+{
+ preemption_key key;
+ rtems_status_code rc = RTEMS_SUCCESSFUL;
+
+ if (bd_buf == NULL)
+ return RTEMS_INVALID_ADDRESS;
+
+ DISABLE_PREEMPTION(key);
+
+ if (!bd_buf->modified)
+ {
+ bdbuf_initialize_transfer_sema(bd_buf);
+ }
+ bd_buf->modified = TRUE;
+ bd_buf->actual = TRUE;
+ rc = bdbuf_release(bd_buf);
+
+ ENABLE_PREEMPTION(key);
+
+ return rc;
+}
+
+/* rtems_bdbuf_sync --
+ * Wait until specified buffer synchronized with disk. Invoked on exchanges
+ * critical for data consistency on the media. This primitive mark owned
+ * block as modified, decrease usage counter. If usage counter is 0,
+ * block inserted to the mod chain and flush_sema semaphore released.
+ * Finally, primitives blocked on transfer_sema semaphore.
+ *
+ * PARAMETERS:
+ * bd_buf - pointer to the bdbuf_buffer structure previously obtained using
+ * get/read primitive.
+ *
+ * RETURNS:
+ * RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
+ * or error code if error is occured)
+ *
+ * SIDE EFFECTS:
+ * Primitive may be blocked on transfer_sema semaphore.
+ */
+rtems_status_code
+rtems_bdbuf_sync(bdbuf_buffer *bd_buf)
+{
+ preemption_key key;
+ ISR_Level level;
+ rtems_status_code rc = RTEMS_SUCCESSFUL;
+
+ if (bd_buf == NULL)
+ return RTEMS_INVALID_ADDRESS;
+
+ DISABLE_PREEMPTION(key);
+
+ if (!bd_buf->modified)
+ {
+ bdbuf_initialize_transfer_sema(bd_buf);
+ }
+ bd_buf->modified = TRUE;
+ bd_buf->actual = TRUE;
+
+ rc = bdbuf_release(bd_buf);
+
+ if (rc == RTEMS_SUCCESSFUL)
+ {
+ rtems_interrupt_disable(level);
+ _CORE_mutex_Seize(&bd_buf->transfer_sema, 0, TRUE,
+ WATCHDOG_NO_TIMEOUT, level);
+ }
+
+ ENABLE_PREEMPTION(key);
+
+ return rc;
+}
+
+/* rtems_bdbuf_syncdev --
+ * Synchronize with disk all buffers containing the blocks belonging to
+ * specified device.
+ *
+ * PARAMETERS:
+ * dev - block device number
+ *
+ * RETURNS:
+ * RTEMS status code (RTEMS_SUCCESSFUL if operation completed successfully
+ * or error code if error is occured)
+ */
+rtems_status_code
+rtems_bdbuf_syncdev(dev_t dev)
+{
+ preemption_key key;
+ ISR_Level level;
+
+ bdbuf_buffer *bd_buf;
+ disk_device *dd;
+ bdbuf_pool *pool;
+
+ dd = rtems_disk_lookup(dev);
+ if (dd == NULL)
+ return RTEMS_INVALID_ID;
+
+ pool = bd_ctx.pool + dd->pool;
+
+ DISABLE_PREEMPTION(key);
+ do {
+ bd_buf = avl_search_for_sync(&pool->tree, dd);
+ if (bd_buf != NULL /* && bd_buf->modified */)
+ {
+ rtems_interrupt_disable(level);
+ _CORE_mutex_Seize(&bd_buf->transfer_sema, 0, TRUE,
+ WATCHDOG_NO_TIMEOUT, level);
+ }
+ } while (bd_buf != NULL);
+ ENABLE_PREEMPTION(key);
+ return rtems_disk_release(dd);
+}
+
+/* bdbuf_swapout_task --
+ * Body of task which take care on flushing modified buffers to the
+ * disk.
+ */
+static rtems_task
+bdbuf_swapout_task(rtems_task_argument unused)
+{
+ rtems_status_code rc;
+ int result;
+ ISR_Level level;
+ bdbuf_buffer *bd_buf;
+ bdbuf_pool *bd_pool;
+ disk_device *dd;
+ blkdev_request1 req;
+
+ while (1)
+ {
+ rc = rtems_semaphore_obtain(bd_ctx.flush_sema, RTEMS_WAIT, 0);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ rtems_fatal_error_occurred(BLKDEV_FATAL_BDBUF_SWAPOUT);
+ }
+
+ bd_buf = (bdbuf_buffer *)Chain_Get(&bd_ctx.mod);
+ if (bd_buf == NULL)
+ {
+ /* It is possible that flush_sema semaphore will be released, but
+ * buffer to be removed from mod chain before swapout task start
+ * its processing. */
+ continue;
+ }
+
+ bd_buf->in_progress = TRUE;
+ bd_buf->use_count++;
+ bd_pool = bd_ctx.pool + bd_buf->pool;
+ dd = rtems_disk_lookup(bd_buf->dev);
+
+ req.req.req = BLKDEV_REQ_WRITE;
+ req.req.req_done = bdbuf_write_transfer_done;
+ req.req.done_arg = bd_buf;
+ req.req.start = bd_buf->block + dd->start;
+ req.req.count = 1;
+ req.req.bufnum = 1;
+ req.req.bufs[0].length = dd->block_size;
+ req.req.bufs[0].buffer = bd_buf->buffer;
+
+ /* transfer_sema initialized when bd_buf inserted in the mod chain
+ first time */
+ result = dd->ioctl(dd->phys_dev->dev, BLKIO_REQUEST, &req);
+
+ rtems_disk_release(dd);
+
+ if (result == -1)
+ {
+ bd_buf->status = RTEMS_IO_ERROR;
+ bd_buf->error = errno;
+ /* Release tasks waiting on syncing this buffer */
+ _CORE_mutex_Flush(&bd_buf->transfer_sema, NULL,
+ CORE_MUTEX_STATUS_SUCCESSFUL);
+ }
+ else
+ {
+ if (bd_buf->in_progress)
+ {
+ rtems_interrupt_disable(level);
+ _CORE_mutex_Seize(&bd_buf->transfer_sema, 0, TRUE, 0, level);
+ }
+ }
+ bd_buf->use_count--;
+
+ /* Another task have chance to use this buffer, or even
+ * modify it. If buffer is not in use, insert it in appropriate chain
+ * and release semaphore */
+ if (bd_buf->use_count == 0)
+ {
+ if (bd_buf->modified)
+ {
+ Chain_Append(&bd_ctx.mod, &bd_buf->link);
+ rc = rtems_semaphore_release(bd_ctx.flush_sema);
+ }
+ else
+ {
+ Chain_Append(&bd_pool->lru, &bd_buf->link);
+ rc = rtems_semaphore_release(bd_pool->bufget_sema);
+ }
+ }
+ }
+}
+
+/* rtems_bdbuf_find_pool --
+ * Find first appropriate buffer pool. This primitive returns the index
+ * of first buffer pool which block size is greater than or equal to
+ * specified size.
+ *
+ * PARAMETERS:
+ * block_size - requested block size
+ * pool - placeholder for result
+ *
+ * RETURNS:
+ * RTEMS status code: RTEMS_SUCCESSFUL if operation completed successfully,
+ * RTEMS_INVALID_SIZE if specified block size is invalid (not a power
+ * of 2), RTEMS_NOT_DEFINED if buffer pool for this or greater block size
+ * is not configured.
+ */
+rtems_status_code
+rtems_bdbuf_find_pool(int block_size, rtems_bdpool_id *pool)
+{
+ rtems_bdpool_id i;
+ bdbuf_pool *p;
+ int cursize = INT_MAX;
+ rtems_bdpool_id curid = -1;
+ rtems_boolean found = FALSE;
+ int j;
+
+ for (j = block_size; (j != 0) && ((j & 1) == 0); j >>= 1);
+ if (j != 1)
+ return RTEMS_INVALID_SIZE;
+
+ for (i = 0, p = bd_ctx.pool; i < bd_ctx.npools; i++, p++)
+ {
+ if ((p->blksize >= block_size) &&
+ (p->blksize < cursize))
+ {
+ curid = i;
+ cursize = p->blksize;
+ found = TRUE;
+ }
+ }
+
+ if (found)
+ {
+ if (pool != NULL)
+ *pool = curid;
+ return RTEMS_SUCCESSFUL;
+ }
+ else
+ {
+ return RTEMS_NOT_DEFINED;
+ }
+}
+
+/* rtems_bdbuf_get_pool_info --
+ * Obtain characteristics of buffer pool with specified number.
+ *
+ * PARAMETERS:
+ * pool - buffer pool number
+ * block_size - block size for which buffer pool is configured returned
+ * there
+ * blocks - number of buffers in buffer pool returned there
+ *
+ * RETURNS:
+ * RTEMS status code: RTEMS_SUCCESSFUL if operation completed successfully,
+ * RTEMS_INVALID_NUMBER if appropriate buffer pool is not configured.
+ *
+ * NOTE:
+ * Buffer pools enumerated contiguously starting from 0.
+ */
+rtems_status_code
+rtems_bdbuf_get_pool_info(rtems_bdpool_id pool, int *block_size,
+ int *blocks)
+{
+ if (pool >= bd_ctx.npools)
+ return RTEMS_INVALID_NUMBER;
+
+ if (block_size != NULL)
+ {
+ *block_size = bd_ctx.pool[pool].blksize;
+ }
+
+ if (blocks != NULL)
+ {
+ *blocks = bd_ctx.pool[pool].nblks;
+ }
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/libblock/src/blkdev.c b/cpukit/libblock/src/blkdev.c
new file mode 100644
index 0000000000..bc6ec4b7f2
--- /dev/null
+++ b/cpukit/libblock/src/blkdev.c
@@ -0,0 +1,249 @@
+/*
+ * blkdev.h - block device driver generic support
+ *
+ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Victor V. Vengerov <vvv@oktet.ru>
+ *
+ * @(#) $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <sys/ioctl.h>
+
+#include "rtems/diskdevs.h"
+#include "rtems/bdbuf.h"
+
+/* rtems_blkdev_generic_read --
+ * Generic block device read primitive. Implemented using block device
+ * buffer management primitives.
+ */
+rtems_device_driver
+rtems_blkdev_generic_read(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg)
+{
+ rtems_libio_rw_args_t *args = arg;
+ int block_size_log2;
+ int block_size;
+ char *buf;
+ unsigned int count;
+ unsigned int block;
+ unsigned int blkofs;
+ dev_t dev;
+ disk_device *dd;
+
+ dev = rtems_filesystem_make_dev_t(major, minor);
+ dd = rtems_disk_lookup(dev);
+ if (dd == NULL)
+ return RTEMS_INVALID_NUMBER;
+
+ block_size_log2 = dd->block_size_log2;
+ block_size = dd->block_size;
+
+ buf = args->buffer;
+ count = args->count;
+ args->bytes_moved = 0;
+
+ block = args->offset >> block_size_log2;
+ blkofs = args->offset & (block_size - 1);
+
+ while (count > 0)
+ {
+ bdbuf_buffer *diskbuf;
+ int copy;
+ rtems_status_code rc;
+
+ rc = rtems_bdbuf_read(dev, block, &diskbuf);
+ if (rc != RTEMS_SUCCESSFUL)
+ return rc;
+ copy = block_size - blkofs;
+ if (copy > count)
+ copy = count;
+ memcpy(buf, (char *)diskbuf->buffer + blkofs, copy);
+ rc = rtems_bdbuf_release(diskbuf);
+ args->bytes_moved += copy;
+ if (rc != RTEMS_SUCCESSFUL)
+ return rc;
+ count -= copy;
+ buf += copy;
+ blkofs = 0;
+ block++;
+ }
+ return RTEMS_SUCCESSFUL;
+}
+
+/* rtems_blkdev_generic_write --
+ * Generic block device write primitive. Implemented using block device
+ * buffer management primitives.
+ */
+rtems_device_driver
+rtems_blkdev_generic_write(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg)
+{
+ rtems_libio_rw_args_t *args = arg;
+ int block_size_log2;
+ int block_size;
+ char *buf;
+ unsigned int count;
+ unsigned int block;
+ unsigned int blkofs;
+ dev_t dev;
+ rtems_status_code rc;
+ disk_device *dd;
+
+ dev = rtems_filesystem_make_dev_t(major, minor);
+ dd = rtems_disk_lookup(dev);
+ if (dd == NULL)
+ return RTEMS_INVALID_NUMBER;
+
+ block_size_log2 = dd->block_size_log2;
+ block_size = dd->block_size;
+
+ buf = args->buffer;
+ count = args->count;
+ args->bytes_moved = 0;
+
+ block = args->offset >> block_size_log2;
+ blkofs = args->offset & (block_size - 1);
+
+ while (count > 0)
+ {
+ bdbuf_buffer *diskbuf;
+ int copy;
+
+ if ((blkofs == 0) && (count >= block_size))
+ rc = rtems_bdbuf_get(dev, block, &diskbuf);
+ else
+ rc = rtems_bdbuf_read(dev, block, &diskbuf);
+ if (rc != RTEMS_SUCCESSFUL)
+ return rc;
+
+ copy = block_size - blkofs;
+ if (copy > count)
+ copy = count;
+ memcpy((char *)diskbuf->buffer + blkofs, buf, copy);
+ args->bytes_moved += copy;
+
+ rc = rtems_bdbuf_release_modified(diskbuf);
+ if (rc != RTEMS_SUCCESSFUL)
+ return rc;
+
+ count -= copy;
+ buf += copy;
+ blkofs = 0;
+ block++;
+ }
+ return RTEMS_SUCCESSFUL;
+}
+
+/* blkdev_generic_open --
+ * Generic block device open primitive.
+ */
+rtems_device_driver
+rtems_blkdev_generic_open(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg)
+{
+ dev_t dev;
+ disk_device *dd;
+
+ dev = rtems_filesystem_make_dev_t(major, minor);
+ dd = rtems_disk_lookup(dev);
+ if (dd == NULL)
+ return RTEMS_INVALID_NUMBER;
+
+ dd->uses++;
+
+ rtems_disk_release(dd);
+
+ return RTEMS_SUCCESSFUL;
+}
+
+
+/* blkdev_generic_close --
+ * Generic block device close primitive.
+ */
+rtems_device_driver
+rtems_blkdev_generic_close(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg)
+{
+ dev_t dev;
+ disk_device *dd;
+
+ dev = rtems_filesystem_make_dev_t(major, minor);
+ dd = rtems_disk_lookup(dev);
+ if (dd == NULL)
+ return RTEMS_INVALID_NUMBER;
+
+ dd->uses--;
+
+ rtems_disk_release(dd);
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/* blkdev_generic_ioctl --
+ * Generic block device ioctl primitive.
+ */
+rtems_device_driver
+rtems_blkdev_generic_ioctl(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg)
+{
+ rtems_libio_ioctl_args_t *args = arg;
+ dev_t dev;
+ disk_device *dd;
+ int rc;
+
+ dev = rtems_filesystem_make_dev_t(major, minor);
+ dd = rtems_disk_lookup(dev);
+ if (dd == NULL)
+ return RTEMS_INVALID_NUMBER;
+
+ switch (args->command)
+ {
+ case BLKIO_GETBLKSIZE:
+ args->ioctl_return = dd->block_size;
+ break;
+
+ case BLKIO_GETSIZE:
+ args->ioctl_return = dd->size;
+ break;
+
+ case BLKIO_SYNCDEV:
+ rc = rtems_bdbuf_syncdev(dd->dev);
+ args->ioctl_return = (rc == RTEMS_SUCCESSFUL ? 0 : -1);
+ break;
+
+ case BLKIO_REQUEST:
+ {
+ blkdev_request *req = args->buffer;
+ req->start += dd->start;
+ args->ioctl_return = dd->ioctl(dd->phys_dev->dev, args->command,
+ req);
+ break;
+ }
+
+ default:
+ args->ioctl_return = dd->ioctl(dd->phys_dev->dev, args->command,
+ args->buffer);
+ break;
+ }
+ rtems_disk_release(dd);
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/libblock/src/diskdevs.c b/cpukit/libblock/src/diskdevs.c
new file mode 100644
index 0000000000..3e7f9fd598
--- /dev/null
+++ b/cpukit/libblock/src/diskdevs.c
@@ -0,0 +1,635 @@
+/*
+ * diskdevs.c - Physical and logical block devices (disks) support
+ *
+ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Victor V. Vengerov <vvv@oktet.ru>
+ *
+ * @(#) $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <stdlib.h>
+#include <unistd.h> /* unlink */
+#include <string.h>
+
+#include "rtems/diskdevs.h"
+#include "rtems/bdbuf.h"
+
+#define DISKTAB_INITIAL_SIZE 32
+
+/* Table of disk devices having the same major number */
+struct disk_device_table {
+ disk_device **minor; /* minor-indexed disk device table */
+ int size; /* Number of entries in the table */
+};
+
+/* Pointer to [major].minor[minor] indexed array of disk devices */
+static struct disk_device_table *disktab;
+
+/* Number of allocated entries in disktab table */
+static int disktab_size;
+
+/* Mutual exclusion semaphore for disk devices table */
+static rtems_id diskdevs_mutex;
+
+/* Flag meaning that disk I/O, buffering etc. already has been initialized. */
+static boolean disk_io_initialized = FALSE;
+
+/* diskdevs data structures protection flag.
+ * Normally, only table lookup operations performed. It is quite fast, so
+ * it is possible to done lookups when interrupts are disabled, avoiding
+ * obtaining the semaphore. This flags sets immediately after entering in
+ * mutex-protected section and cleared before leaving this section in
+ * "big" primitives like add/delete new device etc. Lookup function first
+ * disable interrupts and check this flag. If it is set, lookup function
+ * will be blocked on semaphore and lookup operation will be performed in
+ * semaphore-protected code. If it is not set (very-very frequent case),
+ * we can do lookup safely, enable interrupts and return result.
+ */
+static volatile rtems_boolean diskdevs_protected;
+
+/* create_disk_entry --
+ * Return pointer to the disk_entry structure for the specified device, or
+ * create one if it is not exists.
+ *
+ * PARAMETERS:
+ * dev - device id (major, minor)
+ *
+ * RETURNS:
+ * pointer to the disk device descirptor entry, or NULL if no memory
+ * available for its creation.
+ */
+static disk_device *
+create_disk_entry(dev_t dev)
+{
+ rtems_device_major_number major;
+ rtems_device_minor_number minor;
+ struct disk_device **d;
+
+ rtems_filesystem_split_dev_t (dev, major, minor);
+
+ if (major >= disktab_size)
+ {
+ struct disk_device_table *p;
+ int newsize;
+ int i;
+ newsize = disktab_size * 2;
+ if (major >= newsize)
+ newsize = major + 1;
+ p = realloc(disktab, sizeof(struct disk_device_table) * newsize);
+ if (p == NULL)
+ return NULL;
+ p += disktab_size;
+ for (i = disktab_size; i < newsize; i++, p++)
+ {
+ p->minor = NULL;
+ p->size = 0;
+ }
+ disktab_size = newsize;
+ }
+
+ if ((disktab[major].minor == NULL) ||
+ (minor >= disktab[major].size))
+ {
+ int newsize;
+ disk_device **p;
+ int i;
+ int s = disktab[major].size;
+
+ if (s == 0)
+ newsize = DISKTAB_INITIAL_SIZE;
+ else
+ newsize = s * 2;
+ if (minor >= newsize)
+ newsize = minor + 1;
+
+ p = realloc(disktab[major].minor, sizeof(disk_device *) * newsize);
+ if (p == NULL)
+ return NULL;
+ disktab[major].minor = p;
+ p += s;
+ for (i = s; i < newsize; i++, p++)
+ *p = NULL;
+ disktab[major].size = newsize;
+ }
+
+ d = disktab[major].minor + minor;
+ if (*d == NULL)
+ {
+ *d = calloc(1, sizeof(disk_device));
+ }
+ return *d;
+}
+
+/* get_disk_entry --
+ * Get disk device descriptor by device number.
+ *
+ * PARAMETERS:
+ * dev - block device number
+ *
+ * RETURNS:
+ * Pointer to the disk device descriptor corresponding to the specified
+ * device number, or NULL if disk device with such number not exists.
+ */
+static inline disk_device *
+get_disk_entry(dev_t dev)
+{
+ rtems_device_major_number major;
+ rtems_device_minor_number minor;
+ struct disk_device_table *dtab;
+
+ rtems_filesystem_split_dev_t (dev, major, minor);
+
+ if ((major >= disktab_size) || (disktab == NULL))
+ return NULL;
+
+ dtab = disktab + major;
+
+ if ((minor >= dtab->size) || (dtab->minor == NULL))
+ return NULL;
+
+ return dtab->minor[minor];
+}
+
+/* create_disk --
+ * Check that disk entry for specified device number is not defined
+ * and create it.
+ *
+ * PARAMETERS:
+ * dev - device identifier (major, minor numbers)
+ * name - character name of device (e.g. /dev/hda)
+ * disdev - placeholder for pointer to created disk descriptor
+ *
+ * RETURNS:
+ * RTEMS_SUCCESSFUL if disk entry successfully created, or
+ * error code if error occured (device already registered,
+ * no memory available).
+ */
+static rtems_status_code
+create_disk(dev_t dev, char *name, disk_device **diskdev)
+{
+ disk_device *dd;
+ char *n;
+
+ dd = get_disk_entry(dev);
+ if (dd != NULL)
+ {
+ return RTEMS_RESOURCE_IN_USE;
+ }
+
+ if (name == NULL)
+ {
+ n = NULL;
+ }
+ else
+ {
+ int nlen = strlen(name) + 1;
+ n = malloc(nlen);
+ if (n == NULL)
+ return RTEMS_NO_MEMORY;
+ strncpy(n, name, nlen);
+ }
+
+ dd = create_disk_entry(dev);
+ if (dd == NULL)
+ {
+ free(n);
+ return RTEMS_NO_MEMORY;
+ }
+
+ dd->dev = dev;
+ dd->name = n;
+
+ *diskdev = dd;
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/* rtems_disk_create_phys --
+ * Create physical disk entry. This function usually invoked from
+ * block device driver initialization code when physical device
+ * detected in the system. Device driver should provide ioctl handler
+ * to allow block device access operations. This primitive will register
+ * device in rtems (invoke rtems_io_register_name).
+ *
+ * PARAMETERS:
+ * dev - device identifier (major, minor numbers)
+ * block_size - size of disk block (minimum data transfer unit); must be
+ * power of 2
+ * disk_size - number of blocks on device
+ * handler - IOCTL handler (function providing basic block input/output
+ * request handling BIOREQUEST and other device management
+ * operations)
+ * name - character name of device (e.g. /dev/hda)
+ *
+ * RETURNS:
+ * RTEMS_SUCCESSFUL if information about new physical disk added, or
+ * error code if error occured (device already registered, wrong block
+ * size value, no memory available).
+ */
+rtems_status_code
+rtems_disk_create_phys(dev_t dev, int block_size, int disk_size,
+ block_device_ioctl handler,
+ char *name)
+{
+ int bs_log2;
+ int i;
+ disk_device *dd;
+ rtems_status_code rc;
+ rtems_bdpool_id pool;
+ rtems_device_major_number major;
+ rtems_device_minor_number minor;
+
+ rtems_filesystem_split_dev_t (dev, major, minor);
+
+
+ for (bs_log2 = 0, i = block_size; (i & 1) == 0; i >>= 1, bs_log2++);
+ if ((bs_log2 < 9) || (i != 1)) /* block size < 512 or not power of 2 */
+ return RTEMS_INVALID_NUMBER;
+
+ rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ if (rc != RTEMS_SUCCESSFUL)
+ return rc;
+ diskdevs_protected = TRUE;
+
+ rc = rtems_bdbuf_find_pool(block_size, &pool);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ diskdevs_protected = FALSE;
+ rtems_semaphore_release(diskdevs_mutex);
+ return rc;
+ }
+
+ rc = create_disk(dev, name, &dd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ diskdevs_protected = FALSE;
+ rtems_semaphore_release(diskdevs_mutex);
+ return rc;
+ }
+
+ dd->phys_dev = dd;
+ dd->uses = 0;
+ dd->start = 0;
+ dd->size = disk_size;
+ dd->block_size = block_size;
+ dd->block_size_log2 = bs_log2;
+ dd->ioctl = handler;
+ dd->pool = pool;
+
+ rc = rtems_io_register_name(name, major, minor);
+
+ diskdevs_protected = FALSE;
+ rtems_semaphore_release(diskdevs_mutex);
+
+ return rc;
+}
+
+/* rtems_disk_create_log --
+ * Create logical disk entry. Logical disk is contiguous area on physical
+ * disk. Disk may be splitted to several logical disks in several ways:
+ * manually or using information stored in blocks on physical disk
+ * (DOS-like partition table, BSD disk label, etc). This function usually
+ * invoked from application when application-specific splitting are in use,
+ * or from generic code which handle different logical disk organizations.
+ * This primitive will register device in rtems (invoke
+ * rtems_io_register_name).
+ *
+ * PARAMETERS:
+ * dev - logical device identifier (major, minor numbers)
+ * phys - physical device (block device which holds this logical disk)
+ * identifier
+ * start - starting block number on the physical device
+ * size - logical disk size in blocks
+ * name - logical disk name
+ *
+ * RETURNS:
+ * RTEMS_SUCCESSFUL if logical device successfully added, or error code
+ * if error occured (device already registered, no physical device
+ * exists, logical disk is out of physical disk boundaries, no memory
+ * available).
+ */
+rtems_status_code
+rtems_disk_create_log(dev_t dev, dev_t phys, int start, int size, char *name)
+{
+ disk_device *dd;
+ disk_device *pdd;
+ rtems_status_code rc;
+ rtems_device_major_number major;
+ rtems_device_minor_number minor;
+
+ rtems_filesystem_split_dev_t (dev, major, minor);
+
+ rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ if (rc != RTEMS_SUCCESSFUL)
+ return rc;
+ diskdevs_protected = TRUE;
+
+ pdd = get_disk_entry(phys);
+ if (pdd == NULL)
+ {
+ diskdevs_protected = FALSE;
+ rtems_semaphore_release(diskdevs_mutex);
+ return RTEMS_INVALID_NUMBER;
+ }
+
+ rc = create_disk(dev, name, &dd);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ diskdevs_protected = FALSE;
+ rtems_semaphore_release(diskdevs_mutex);
+ return rc;
+ }
+
+ dd->phys_dev = pdd;
+ dd->uses = 0;
+ dd->start = start;
+ dd->size = size;
+ dd->block_size = pdd->block_size;
+ dd->block_size_log2 = pdd->block_size_log2;
+ dd->ioctl = pdd->ioctl;
+
+ rc = rtems_io_register_name(name, major, minor);
+
+ diskdevs_protected = FALSE;
+ rc = rtems_semaphore_release(diskdevs_mutex);
+
+ return rc;
+}
+
+/* rtems_disk_delete --
+ * Delete physical or logical disk device. Device may be deleted if its
+ * use counter (and use counters of all logical devices - if it is
+ * physical device) equal to 0. When physical device deleted,
+ * all logical devices deleted inherently. Appropriate devices removed
+ * from "/dev" filesystem.
+ *
+ * PARAMETERS:
+ * dev - device identifier (major, minor numbers)
+ *
+ * RETURNS:
+ * RTEMS_SUCCESSFUL if block device successfully deleted, or error code
+ * if error occured (device is not defined, device is in use).
+ */
+rtems_status_code
+rtems_disk_delete(dev_t dev)
+{
+ rtems_status_code rc;
+ int used;
+ rtems_device_major_number maj;
+ rtems_device_minor_number min;
+
+ rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ if (rc != RTEMS_SUCCESSFUL)
+ return rc;
+ diskdevs_protected = TRUE;
+
+ /* Check if this device is in use -- calculate usage counter */
+ used = 0;
+ for (maj = 0; maj < disktab_size; maj++)
+ {
+ struct disk_device_table *dtab = disktab + maj;
+ if (dtab != NULL)
+ {
+ for (min = 0; min < dtab->size; min++)
+ {
+ disk_device *dd = dtab->minor[min];
+ if ((dd != NULL) && (dd->phys_dev->dev == dev))
+ used += dd->uses;
+ }
+ }
+ }
+
+ if (used != 0)
+ {
+ diskdevs_protected = FALSE;
+ rtems_semaphore_release(diskdevs_mutex);
+ return RTEMS_RESOURCE_IN_USE;
+ }
+
+ /* Delete this device and all of its logical devices */
+ for (maj = 0; maj < disktab_size; maj++)
+ {
+ struct disk_device_table *dtab = disktab +maj;
+ if (dtab != NULL)
+ {
+ for (min = 0; min < dtab->size; min++)
+ {
+ disk_device *dd = dtab->minor[min];
+ if ((dd != NULL) && (dd->phys_dev->dev == dev))
+ {
+ unlink(dd->name);
+ free(dd->name);
+ free(dd);
+ dtab->minor[min] = NULL;
+ }
+ }
+ }
+ }
+
+ diskdevs_protected = FALSE;
+ rc = rtems_semaphore_release(diskdevs_mutex);
+ return rc;
+}
+
+/* rtems_disk_lookup --
+ * Find block device descriptor by its device identifier.
+ *
+ * PARAMETERS:
+ * dev - device identifier (major, minor numbers)
+ *
+ * RETURNS:
+ * pointer to the block device descriptor, or NULL if no such device
+ * exists.
+ */
+disk_device *
+rtems_disk_lookup(dev_t dev)
+{
+ rtems_interrupt_level level;
+ disk_device *dd;
+ rtems_status_code rc;
+
+ rtems_interrupt_disable(level);
+ if (diskdevs_protected)
+ {
+ rtems_interrupt_enable(level);
+ rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT,
+ RTEMS_NO_TIMEOUT);
+ if (rc != RTEMS_SUCCESSFUL)
+ return NULL;
+ diskdevs_protected = TRUE;
+ dd = get_disk_entry(dev);
+ dd->uses++;
+ diskdevs_protected = FALSE;
+ rtems_semaphore_release(diskdevs_mutex);
+ return dd;
+ }
+ else
+ {
+ /* Frequent and quickest case */
+ dd = get_disk_entry(dev);
+ dd->uses++;
+ rtems_interrupt_enable(level);
+ return dd;
+ }
+}
+
+/* rtems_disk_release --
+ * Release disk_device structure (decrement usage counter to 1).
+ *
+ * PARAMETERS:
+ * dd - pointer to disk device structure
+ *
+ * RETURNS:
+ * RTEMS_SUCCESSFUL
+ */
+rtems_status_code
+rtems_disk_release(disk_device *dd)
+{
+ rtems_interrupt_level level;
+ rtems_interrupt_disable(level);
+ dd->uses--;
+ rtems_interrupt_enable(level);
+ return RTEMS_SUCCESSFUL;
+}
+
+/* rtems_disk_next --
+ * Disk device enumerator. Looking for device having device number larger
+ * than dev and return disk device descriptor for it. If there are no
+ * such device, NULL value returned.
+ *
+ * PARAMETERS:
+ * dev - device number (use -1 to start search)
+ *
+ * RETURNS:
+ * Pointer to the disk descriptor for next disk device, or NULL if all
+ * devices enumerated.
+ */
+disk_device *
+rtems_disk_next(dev_t dev)
+{
+ rtems_device_major_number major;
+ rtems_device_minor_number minor;
+ struct disk_device_table *dtab;
+
+ dev++;
+ rtems_filesystem_split_dev_t (dev, major, minor);
+
+ if (major >= disktab_size)
+ return NULL;
+
+ dtab = disktab + major;
+ while (TRUE)
+ {
+ if ((dtab == NULL) || (minor > dtab->size))
+ {
+ major++; minor = 0;
+ if (major >= disktab_size)
+ return NULL;
+ dtab = disktab + major;
+ }
+ else if (dtab->minor[minor] == NULL)
+ {
+ minor++;
+ }
+ else
+ return dtab->minor[minor];
+ }
+}
+
+/* rtems_disk_initialize --
+ * Initialization of disk device library (initialize all data structures,
+ * etc.)
+ *
+ * PARAMETERS:
+ * none
+ *
+ * RETURNS:
+ * RTEMS_SUCCESSFUL if library initialized, or error code if error
+ * occured.
+ */
+rtems_status_code
+rtems_disk_io_initialize(void)
+{
+ rtems_status_code rc;
+
+ if (disk_io_initialized)
+ return RTEMS_SUCCESSFUL;
+
+ disktab_size = DISKTAB_INITIAL_SIZE;
+ disktab = calloc(disktab_size, sizeof(struct disk_device_table));
+ if (disktab == NULL)
+ return RTEMS_NO_MEMORY;
+
+ diskdevs_protected = FALSE;
+ rc = rtems_semaphore_create(
+ rtems_build_name('D', 'D', 'E', 'V'), 1,
+ RTEMS_FIFO | RTEMS_BINARY_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY |
+ RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL, 0, &diskdevs_mutex);
+
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ free(disktab);
+ return rc;
+ }
+
+ rc = rtems_bdbuf_init(rtems_bdbuf_configuration,
+ rtems_bdbuf_configuration_size);
+
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ rtems_semaphore_delete(diskdevs_mutex);
+ free(disktab);
+ return rc;
+ }
+
+ disk_io_initialized = 1;
+ return RTEMS_SUCCESSFUL;
+}
+
+/* rtems_disk_io_done --
+ * Release all resources allocated for disk device interface.
+ *
+ * PARAMETERS:
+ * none
+ *
+ * RETURNS:
+ * RTEMS_SUCCESSFUL if all resources released, or error code if error
+ * occured.
+ */
+rtems_status_code
+rtems_disk_io_done(void)
+{
+ rtems_device_major_number maj;
+ rtems_device_minor_number min;
+ rtems_status_code rc;
+
+ /* Free data structures */
+ for (maj = 0; maj < disktab_size; maj++)
+ {
+ struct disk_device_table *dtab = disktab + maj;
+ if (dtab != NULL)
+ {
+ for (min = 0; min < dtab->size; min++)
+ {
+ disk_device *dd = dtab->minor[min];
+ unlink(dd->name);
+ free(dd->name);
+ free(dd);
+ }
+ free(dtab);
+ }
+ }
+ free(disktab);
+
+ rc = rtems_semaphore_release(diskdevs_mutex);
+
+ /* XXX bdbuf should be released too! */
+ disk_io_initialized = 0;
+ return rc;
+}
diff --git a/cpukit/libblock/src/ide_part_table.c b/cpukit/libblock/src/ide_part_table.c
new file mode 100644
index 0000000000..2b5b46138b
--- /dev/null
+++ b/cpukit/libblock/src/ide_part_table.c
@@ -0,0 +1,550 @@
+/*****************************************************************************
+ *
+ * ide_part_table.c
+ *
+ * The implementation of library supporting "MS-DOS-style" partition table
+ *
+ *
+ * Copyright (C) 2002 OKTET Ltd., St.-Petersburg, Russia
+ *
+ * Author: Konstantin Abramenko <Konstantin.Abramenko@oktet.ru>
+ * Alexander Kukuta <Alexander.Kukuta@oktet.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ *
+ *****************************************************************************/
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include <rtems/ide_part_table.h>
+
+/*
+ * get_sector --
+ * gets sector from the disk
+ *
+ * PARAMETERS:
+ * dev - device number
+ * sector_num - number of sector to read
+ * sector - returned pointer to pointer to allocated
+ * sector_data_t structure
+ *
+ * RETURNS:
+ * RTEMS_SUCCESSFUL, if success;
+ * RTEMS_NO_MEMORY, if canot allocate memory for sector data;
+ * other error codes returned by rtems_bdbuf_read().
+ *
+ * NOTES:
+ * get_sector() operates with device via bdbuf library,
+ * and does not support devices with sector size other than 512 bytes
+ */
+static rtems_status_code
+get_sector(dev_t dev, uint32_t sector_num, sector_data_t **sector)
+{
+ sector_data_t *s;
+ bdbuf_buffer *buf;
+ rtems_status_code rc;
+
+ if (sector == NULL)
+ {
+ return RTEMS_INTERNAL_ERROR;
+ }
+
+ s = (sector_data_t *) malloc(sizeof(sector_data_t) + RTEMS_IDE_SECTOR_SIZE);
+ if (s == NULL)
+ {
+ return RTEMS_NO_MEMORY;
+ }
+
+ rc = rtems_bdbuf_read(dev, sector_num, &buf);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ free(s);
+ return rc;
+ }
+
+ memcpy(s->data, buf->buffer, RTEMS_IDE_SECTOR_SIZE);
+ s->sector_num = sector_num;
+
+ *sector = s;
+
+ rtems_bdbuf_release(buf);
+
+ return RTEMS_SUCCESSFUL;
+}
+
+
+/*
+ * msdos_signature_check --
+ * checks if the partition table sector has msdos signature
+ *
+ * PARAMETERS:
+ * sector - sector to check
+ *
+ * RETURNS:
+ * TRUE if sector has msdos signature, FALSE otherwise
+ */
+static rtems_boolean
+msdos_signature_check (sector_data_t *sector)
+{
+ uint8_t *p = sector->data + RTEMS_IDE_PARTITION_MSDOS_SIGNATURE_OFFSET;
+
+ return ((p[0] == RTEMS_IDE_PARTITION_MSDOS_SIGNATURE_DATA1) &&
+ (p[1] == RTEMS_IDE_PARTITION_MSDOS_SIGNATURE_DATA2));
+}
+
+
+/*
+ * is_extended --
+ * checks if the partition type is extended
+ *
+ * PARAMETERS:
+ * type - type of partition to check
+ *
+ * RETURNS:
+ * TRUE if partition type is extended, FALSE otherwise
+ */
+static rtems_boolean
+is_extended(uint8_t type)
+{
+ return ((type == EXTENDED_PARTITION) || (type == LINUX_EXTENDED));
+}
+
+/*
+ * is_fat_partition --
+ * checks if the partition type is defined for FAT
+ *
+ * PARAMETERS:
+ * type - type of partition to check
+ *
+ * RETURNS:
+ * TRUE if partition type is extended, FALSE otherwise
+ */
+static rtems_boolean
+is_fat_partition(uint8_t type)
+{
+ static const uint8_t fat_part_types[] = {
+ DOS_FAT12_PARTITION,DOS_FAT16_PARTITION,
+ DOS_P32MB_PARTITION,
+ FAT32_PARTITION ,FAT32_LBA_PARTITION,
+ FAT16_LBA_PARTITION
+ };
+
+ return (NULL != memchr(fat_part_types,type,sizeof(fat_part_types)));
+}
+
+
+/*
+ * data_to_part_desc --
+ * parses raw partition table sector data
+ * to partition description structure
+ *
+ * PARAMETERS:
+ * data - raw partition table sector data
+ * new_part_desc - pointer to returned partition description structure
+ *
+ * RETURNS:
+ * RTEMS_SUCCESSFUL, if success;
+ * RTEMS_NO_MEMOTY, if cannot allocate memory for part_desc_t strucure;
+ * RTEMS_INTERNAL_ERROR, if other error occurs.
+ */
+static rtems_status_code
+data_to_part_desc(uint8_t *data, part_desc_t **new_part_desc)
+{
+ part_desc_t *part_desc;
+ uint32_t temp;
+
+ if (new_part_desc == NULL)
+ {
+ return RTEMS_INTERNAL_ERROR;
+ }
+
+ *new_part_desc = NULL;
+
+ if ((part_desc = calloc(1, sizeof(part_desc_t))) == NULL)
+ {
+ return RTEMS_NO_MEMORY;
+ }
+
+ part_desc->bootable = *(data + RTEMS_IDE_PARTITION_BOOTABLE_OFFSET);
+ part_desc->sys_type = *(data + RTEMS_IDE_PARTITION_SYS_TYPE_OFFSET);
+
+ /* read the offset start position and partition size in sectors */
+
+ /* due to incorrect data alignment one have to align data first */
+ memcpy(&temp, data + RTEMS_IDE_PARTITION_START_OFFSET, sizeof(uint32_t));
+ part_desc->start = LE_TO_CPU_U32(temp);
+
+ memcpy(&temp, data + RTEMS_IDE_PARTITION_SIZE_OFFSET, sizeof(uint32_t));
+ part_desc->size = LE_TO_CPU_U32(temp);
+
+ /*
+ * use partitions that are
+ * - extended
+ * or
+ * - FAT type and non-zero
+ */
+ if (is_extended(part_desc->sys_type) ||
+ ((is_fat_partition(part_desc->sys_type)) && (part_desc->size != 0))) {
+ *new_part_desc = part_desc;
+ }
+ else {
+ /* empty partition */
+ free(part_desc);
+ }
+ return RTEMS_SUCCESSFUL;
+}
+
+
+/*
+ * read_extended_partition --
+ * recursively reads extended partition sector from the device
+ * and constructs the partition table tree
+ *
+ * PARAMETERS:
+ * start - start sector of primary extended partition, used for
+ * calculation of absolute partition sector address
+ * ext_part - description of extended partition to process
+ *
+ * RETURNS:
+ * RTEMS_SUCCESSFUL if success,
+ * RTEMS_NO_MEMOTY if cannot allocate memory for part_desc_t strucure,
+ * RTEMS_INTERNAL_ERROR if other error occurs.
+ */
+static rtems_status_code
+read_extended_partition(uint32_t start, part_desc_t *ext_part)
+{
+ int i;
+ dev_t dev;
+ sector_data_t *sector;
+ uint32_t here;
+ uint8_t *data;
+ part_desc_t *new_part_desc;
+ rtems_status_code rc;
+
+ if ((ext_part == NULL) || (ext_part->disk_desc == NULL))
+ {
+ return RTEMS_INTERNAL_ERROR;
+ }
+
+ dev = ext_part->disk_desc->dev;
+
+ /* get start sector of current extended partition */
+ here = ext_part->start;
+
+ /* get first extended partition sector */
+
+ rc = get_sector(dev, here, &sector);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ return rc;
+ }
+
+ if (!msdos_signature_check(sector))
+ {
+ return RTEMS_INTERNAL_ERROR;
+ }
+
+ /* read and process up to 4 logical partition descriptors */
+
+ data = sector->data + RTEMS_IDE_PARTITION_TABLE_OFFSET;
+
+ for (i = 0; i < RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER; i++)
+ {
+ /* if data_to_part_desc fails skip this partition
+ * and parse the next one
+ */
+ rc = data_to_part_desc(data, &new_part_desc);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ free(sector);
+ return rc;
+ }
+
+ if (new_part_desc == NULL)
+ {
+ data += RTEMS_IDE_PARTITION_DESCRIPTOR_SIZE;
+ continue;
+ }
+
+ ext_part->sub_part[i] = new_part_desc;
+ new_part_desc->ext_part = ext_part;
+ new_part_desc->disk_desc = ext_part->disk_desc;
+
+ if (is_extended(new_part_desc->sys_type))
+ {
+ new_part_desc->log_id = EMPTY_PARTITION;
+ new_part_desc->start += start;
+ read_extended_partition(start, new_part_desc);
+ }
+ else
+ {
+ disk_desc_t *disk_desc = new_part_desc->disk_desc;
+ disk_desc->partitions[disk_desc->last_log_id] = new_part_desc;
+ new_part_desc->log_id = ++disk_desc->last_log_id;
+ new_part_desc->start += here;
+ new_part_desc->end = new_part_desc->start + new_part_desc->size - 1;
+ }
+ data += RTEMS_IDE_PARTITION_DESCRIPTOR_SIZE;
+ }
+
+ free(sector);
+
+ return RTEMS_SUCCESSFUL;
+}
+
+
+/*
+ * read_mbr --
+ * reads Master Boot Record (sector 0) of physical device and
+ * constructs disk description structure
+ *
+ * PARAMETERS:
+ * disk_desc - returned disc description structure
+ *
+ * RETURNS:
+ * RTEMS_SUCCESSFUL if success,
+ * RTEMS_INTERNAL_ERROR otherwise
+ */
+static rtems_status_code
+read_mbr(disk_desc_t *disk_desc)
+{
+ int part_num;
+ sector_data_t *sector;
+ part_desc_t *part_desc;
+ uint8_t *data;
+ rtems_status_code rc;
+ dev_t dev = disk_desc->dev;
+
+ /* get MBR sector */
+ rc = get_sector(dev, 0, &sector);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ return rc;
+ }
+
+ /* check if the partition table structure is MS-DOS style */
+ if (!msdos_signature_check(sector))
+ {
+ return RTEMS_INTERNAL_ERROR;
+ }
+
+ /* read and process 4 primary partition descriptors */
+
+ data = sector->data + RTEMS_IDE_PARTITION_TABLE_OFFSET;
+
+ for (part_num = 0;
+ part_num < RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER;
+ part_num++)
+ {
+ rc = data_to_part_desc(data, &part_desc);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ free(sector);
+ return rc;
+ }
+
+ if (part_desc != NULL)
+ {
+ part_desc->log_id = part_num + 1;
+ part_desc->disk_desc = disk_desc;
+ part_desc->end = part_desc->start + part_desc->size - 1;
+ disk_desc->partitions[part_num] = part_desc;
+ }
+ else
+ {
+ disk_desc->partitions[part_num] = NULL;
+ }
+
+ data += RTEMS_IDE_PARTITION_DESCRIPTOR_SIZE;
+ }
+
+ free(sector);
+
+ disk_desc->last_log_id = RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER;
+
+ /* There cannot be more than one extended partition,
+ but we are to process each primary partition */
+ for (part_num = 0;
+ part_num < RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER;
+ part_num++)
+ {
+ if (is_extended(disk_desc->partitions[part_num]->sys_type))
+ {
+ read_extended_partition(disk_desc->partitions[part_num]->start,
+ disk_desc->partitions[part_num]);
+ }
+ }
+
+ return RTEMS_SUCCESSFUL;
+}
+
+
+/*
+ * partition free --
+ * frees partition description structure
+ *
+ * PARAMETERS:
+ * part_desc - returned disc description structure
+ *
+ * RETURNS:
+ * N/A
+ */
+static void
+partition_free(part_desc_t *part_desc)
+{
+ int part_num;
+
+ if (part_desc == NULL)
+ return;
+
+ if (is_extended(part_desc->sys_type))
+ {
+ for (part_num = 0;
+ part_num < RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER;
+ part_num++)
+ {
+ partition_free(part_desc->sub_part[part_num]);
+ }
+ }
+
+ free(part_desc);
+}
+
+
+/*
+ * rtems_ide_part_table_free - frees disk descriptor structure
+ *
+ * PARAMETERS:
+ * disk_desc - disc descriptor structure to free
+ *
+ * RETURNS:
+ * N/A
+ */
+void
+rtems_ide_part_table_free(disk_desc_t *disk_desc)
+{
+ int part_num;
+
+ for (part_num = 0; part_num < RTEMS_IDE_PARTITION_MAX_SUB_PARTITION_NUMBER; part_num++)
+ {
+ partition_free(disk_desc->partitions[part_num]);
+ }
+
+ free(disk_desc);
+}
+
+
+/*
+ * rtems_ide_part_table_get - reads partition table structure from the device
+ * and creates disk description structure
+ *
+ * PARAMETERS:
+ * dev_name - path to physical device in /dev filesystem
+ * disk_desc - returned disc description structure
+ *
+ * RETURNS:
+ * RTEMS_SUCCESSFUL if success,
+ * RTEMS_INTERNAL_ERROR otherwise
+ */
+rtems_status_code
+rtems_ide_part_table_get(const char *dev_name, disk_desc_t *disk_desc)
+{
+ struct stat dev_stat;
+ rtems_status_code rc;
+
+ rc = stat(dev_name, &dev_stat);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ return RTEMS_INTERNAL_ERROR;
+ }
+
+ strncpy (disk_desc->dev_name, dev_name, 15);
+ disk_desc->dev = dev_stat.st_dev;
+ disk_desc->sector_size = (dev_stat.st_blksize) ? dev_stat.st_blksize :
+ RTEMS_IDE_SECTOR_SIZE;
+
+ rc = read_mbr(disk_desc);
+
+ return rc;
+}
+
+
+/*
+ * rtems_ide_part_table_initialize - initializes logical devices
+ * on the physical IDE drive
+ *
+ * PARAMETERS:
+ * dev_name - path to physical device in /dev filesystem
+ *
+ * RETURNS:
+ * RTEMS_SUCCESSFUL if success,
+ * RTEMS_NO_MEMOTY if cannot have not enough memory,
+ * RTEMS_INTERNAL_ERROR if other error occurs.
+ */
+rtems_status_code
+rtems_ide_part_table_initialize(char *dev_name)
+{
+ int part_num;
+ dev_t dev;
+ disk_desc_t *disk_desc;
+ rtems_device_major_number major;
+ rtems_device_minor_number minor;
+ rtems_status_code rc;
+ part_desc_t *part_desc;
+
+ /* logical device name /dev/hdxyy */
+ char name[RTEMS_IDE_PARTITION_DEV_NAME_LENGTH_MAX];
+
+ disk_desc = (disk_desc_t *) calloc(1, sizeof(disk_desc_t));
+ if (disk_desc == NULL)
+ {
+ return RTEMS_NO_MEMORY;
+ }
+
+ /* get partition table */
+ rc = rtems_ide_part_table_get(dev_name, disk_desc);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ return rc;
+ }
+
+ /* To avoid device numbers conflicts we have to use for logic disk the same
+ * device major number as ATA device has, and minor number that equals to
+ * sum of logic disk partition number and the minor number of physical disk
+ */
+
+ rtems_filesystem_split_dev_t (disk_desc->dev, major, minor);
+
+ /* create logical disks on the physical one */
+ for (part_num = 0; part_num < disk_desc->last_log_id; part_num++)
+ {
+ sprintf(name, "%s%d", dev_name, part_num + 1);
+ dev = rtems_filesystem_make_dev_t(major, ++minor);
+
+ part_desc = disk_desc->partitions[part_num];
+ if (part_desc == NULL)
+ {
+ continue;
+ }
+
+ rc = rtems_disk_create_log(dev, disk_desc->dev, part_desc->start,
+ part_desc->size, name);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"Cannot create device %s, error code %d\n", name, rc);
+ continue;
+ }
+ }
+
+ rtems_ide_part_table_free(disk_desc);
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/libblock/src/ramdisk.c b/cpukit/libblock/src/ramdisk.c
new file mode 100644
index 0000000000..7d3c8987f5
--- /dev/null
+++ b/cpukit/libblock/src/ramdisk.c
@@ -0,0 +1,231 @@
+/* ramdisk.c -- RAM disk block device implementation
+ *
+ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Victor V. Vengerov <vvv@oktet.ru>
+ *
+ * @(#) $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "rtems/blkdev.h"
+#include "rtems/diskdevs.h"
+#include "rtems/ramdisk.h"
+
+#define RAMDISK_DEVICE_BASE_NAME "/dev/ramdisk"
+
+/* Internal RAM disk descriptor */
+struct ramdisk {
+ int block_size; /* RAM disk block size */
+ int block_num; /* Number of blocks on this RAM disk */
+ void *area; /* RAM disk memory area */
+ rtems_boolean initialized;/* RAM disk is initialized */
+ rtems_boolean malloced; /* != 0, if memory allocated by malloc for this
+ RAM disk */
+};
+
+static struct ramdisk *ramdisk;
+static int nramdisks;
+
+/* ramdisk_read --
+ * RAM disk READ request handler. This primitive copies data from RAM
+ * disk to supplied buffer and invoke the callout function to inform
+ * upper layer that reading is completed.
+ *
+ * PARAMETERS:
+ * req - pointer to the READ block device request info
+ *
+ * RETURNS:
+ * ioctl return value
+ */
+static int
+ramdisk_read(struct ramdisk *rd, blkdev_request *req)
+{
+ char *from;
+ uint32_t i;
+ blkdev_sg_buffer *sg;
+ uint32_t remains;
+
+ from = (char *)rd->area + (req->start * rd->block_size);
+ remains = rd->block_size * req->count;
+ sg = req->bufs;
+ for (i = 0; (remains > 0) && (i < req->bufnum); i++, sg++)
+ {
+ int count = sg->length;
+ if (count > remains)
+ count = remains;
+ memcpy(sg->buffer, from, count);
+ remains -= count;
+ from += count;
+ }
+ req->req_done(req->done_arg, RTEMS_SUCCESSFUL, 0);
+ return 0;
+}
+
+/* ramdisk_write --
+ * RAM disk WRITE request handler. This primitive copies data from
+ * supplied buffer to RAM disk and invoke the callout function to inform
+ * upper layer that writing is completed.
+ *
+ * PARAMETERS:
+ * req - pointer to the WRITE block device request info
+ *
+ * RETURNS:
+ * ioctl return value
+ */
+static int
+ramdisk_write(struct ramdisk *rd, blkdev_request *req)
+{
+ char *to;
+ uint32_t i;
+ blkdev_sg_buffer *sg;
+ uint32_t remains;
+
+ to = (char *)rd->area + (req->start * rd->block_size);
+ remains = rd->block_size * req->count;
+ sg = req->bufs;
+ for (i = 0; (remains > 0) && (i < req->bufnum); i++, sg++)
+ {
+ int count = sg->length;
+ if (count > remains)
+ count = remains;
+ memcpy(to, sg->buffer, count);
+ remains -= count;
+ to += count;
+ }
+ req->req_done(req->done_arg, RTEMS_SUCCESSFUL, 0);
+ return 0;
+}
+
+/* ramdisk_ioctl --
+ * IOCTL handler for RAM disk device.
+ *
+ * PARAMETERS:
+ * dev - device number (major, minor number)
+ * req - IOCTL request code
+ * argp - IOCTL argument
+ *
+ * RETURNS:
+ * IOCTL return value
+ */
+static int
+ramdisk_ioctl(dev_t dev, int req, void *argp)
+{
+ switch (req)
+ {
+ case BLKIO_REQUEST:
+ {
+ rtems_device_minor_number minor;
+ blkdev_request *r = argp;
+ struct ramdisk *rd;
+
+ minor = rtems_filesystem_dev_minor_t(dev);
+ if ((minor >= nramdisks) || !ramdisk[minor].initialized)
+ {
+ errno = ENODEV;
+ return -1;
+ }
+
+ rd = ramdisk + minor;
+
+ switch (r->req)
+ {
+ case BLKDEV_REQ_READ:
+ return ramdisk_read(rd, r);
+
+ case BLKDEV_REQ_WRITE:
+ return ramdisk_write(rd, r);
+
+ default:
+ errno = EBADRQC;
+ return -1;
+ }
+ break;
+ }
+
+ default:
+ errno = EBADRQC;
+ return -1;
+ }
+}
+
+/* ramdisk_initialize --
+ * RAM disk device driver initialization. Run through RAM disk
+ * configuration information and configure appropriate RAM disks.
+ *
+ * PARAMETERS:
+ * major - RAM disk major device number
+ * minor - minor device number, not applicable
+ * arg - initialization argument, not applicable
+ *
+ * RETURNS:
+ * none
+ */
+rtems_device_driver
+ramdisk_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg)
+{
+ rtems_device_minor_number i;
+ rtems_ramdisk_config *c = rtems_ramdisk_configuration;
+ struct ramdisk *r;
+ rtems_status_code rc;
+
+ rc = rtems_disk_io_initialize();
+ if (rc != RTEMS_SUCCESSFUL)
+ return rc;
+
+ r = ramdisk = calloc(rtems_ramdisk_configuration_size,
+ sizeof(struct ramdisk));
+
+ for (i = 0; i < rtems_ramdisk_configuration_size; i++, c++, r++)
+ {
+ dev_t dev = rtems_filesystem_make_dev_t(major, i);
+ char name[sizeof(RAMDISK_DEVICE_BASE_NAME "0123456789")];
+ snprintf(name, sizeof(name), RAMDISK_DEVICE_BASE_NAME "%d", i);
+ r->block_size = c->block_size;
+ r->block_num = c->block_num;
+ if (c->location == NULL)
+ {
+ r->malloced = TRUE;
+ r->area = malloc(r->block_size * r->block_num);
+ if (r->area == NULL) /* No enough memory for this disk */
+ {
+ r->initialized = FALSE;
+ continue;
+ }
+ else
+ {
+ r->initialized = TRUE;
+ }
+ }
+ else
+ {
+ r->malloced = FALSE;
+ r->initialized = TRUE;
+ r->area = c->location;
+ }
+ rc = rtems_disk_create_phys(dev, c->block_size, c->block_num,
+ ramdisk_ioctl, name);
+ if (rc != RTEMS_SUCCESSFUL)
+ {
+ if (r->malloced)
+ {
+ free(r->area);
+ }
+ r->initialized = FALSE;
+ }
+ }
+ nramdisks = rtems_ramdisk_configuration_size;
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/libcsupport/.cvsignore b/cpukit/libcsupport/.cvsignore
new file mode 100644
index 0000000000..282522db03
--- /dev/null
+++ b/cpukit/libcsupport/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/cpukit/libcsupport/Makefile.am b/cpukit/libcsupport/Makefile.am
new file mode 100644
index 0000000000..91c33808ae
--- /dev/null
+++ b/cpukit/libcsupport/Makefile.am
@@ -0,0 +1,282 @@
+##
+## $Id$
+##
+
+include $(top_srcdir)/automake/multilib.am
+include $(top_srcdir)/automake/compile.am
+
+AM_CPPFLAGS += -I$(top_builddir)
+
+EXTRA_LIBRARIES = libcsupport.a
+CLEANFILES = libcsupport.a
+libcsupport_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libcsupport_g.a
+CLEANFILES += libcsupport_g.a
+libcsupport_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+include_rtemsdir = $(includedir)/rtems
+include_rtems_HEADERS = include/chain.h include/console.h include/clockdrv.h \
+ include/iosupp.h include/ringbuf.h include/rtc.h include/spurious.h \
+ include/timerdrv.h include/vmeintr.h
+
+include_HEADERS =
+
+if NEWLIB
+include_HEADERS += include/stdint.h
+include_HEADERS += include/inttypes.h
+endif
+
+## motorola
+
+include_rtems_motoroladir = $(includedir)/rtems/motorola
+
+include_rtems_motorola_HEADERS = include/motorola/mc68230.h \
+ include/motorola/mc68681.h
+
+## rtems
+include_rtems_HEADERS += include/rtems/assoc.h include/rtems/error.h \
+ include/rtems/libcsupport.h include/rtems/libio.h include/rtems/libio_.h \
+ include/rtems/termiostypes.h include/rtems/cdefs.h
+
+## sys
+
+if NEWLIB
+include_sysdir = $(includedir)/sys
+include_sys_HEADERS = include/sys/ioccom.h include/sys/filio.h \
+ include/sys/ioctl.h include/sys/sockio.h include/sys/ttycom.h \
+ include/sys/termios.h include/sys/utsname.h include/sys/cdefs.h
+endif
+
+## zilog
+
+include_rtems_zilogdir = $(includedir)/rtems/zilog
+
+include_rtems_zilog_HEADERS = include/zilog/z8036.h include/zilog/z8530.h \
+ include/zilog/z8536.h
+
+## General stuff
+all-local: $(PREINSTALL_FILES) libcsupport$(LIB_VARIANT).a
+
+ERROR_C_FILES = src/error.c
+
+ASSOCIATION_C_FILES = src/assoc.c src/assocnamebad.c
+
+BASE_FS_C_FILES = src/base_fs.c src/mount.c src/unmount.c src/libio.c \
+ src/libio_sockets.c src/eval.c src/fs_null_handlers.c src/privateenv.c
+
+TERMIOS_C_FILES = src/cfgetispeed.c src/cfgetospeed.c src/cfsetispeed.c \
+ src/cfsetospeed.c src/tcgetattr.c src/tcsetattr.c src/tcdrain.c \
+ src/tcflow.c src/tcflush.c src/tcgetprgrp.c src/tcsendbreak.c \
+ src/tcsetpgrp.c src/termios.c src/termiosinitialize.c \
+ src/termiosreserveresources.c
+
+SYSTEM_CALL_C_FILES = src/open.c src/close.c src/read.c src/write.c \
+ src/lseek.c src/ioctl.c src/mkdir.c src/mknod.c src/mkfifo.c src/rmdir.c \
+ src/chdir.c src/chmod.c src/fchdir.c src/fchmod.c src/chown.c src/link.c \
+ src/unlink.c src/umask.c src/ftruncate.c src/utime.c src/fstat.c \
+ src/fcntl.c src/fpathconf.c src/getdents.c src/fsync.c src/fdatasync.c \
+ src/pipe.c src/dup.c src/dup2.c src/symlink.c src/readlink.c src/creat.c \
+ src/chroot.c src/sync.c
+
+DIRECTORY_SCAN_C_FILES = src/opendir.c src/closedir.c src/readdir.c \
+ src/readdir_r.c src/rewinddir.c src/scandir.c src/seekdir.c \
+ src/telldir.c src/getcwd.c
+
+ID_C_FILES = src/getegid.c src/geteuid.c src/getgid.c src/getgroups.c \
+ src/getlogin.c src/getpgrp.c src/getpid.c src/getppid.c src/getuid.c \
+ src/setpgid.c src/setsid.c
+
+MALLOC_C_FILES = src/malloc.c src/mallocfreespace.c src/__brk.c \
+ src/__sbrk.c
+
+PASSWORD_GROUP_C_FILES = src/getpwent.c
+
+TERMINAL_IDENTIFICATION_C_FILES = src/ctermid.c src/isatty.c src/ttyname.c \
+ src/ttyname_r.c
+
+LIBC_GLUE_C_FILES = src/__getpid.c src/__gettod.c src/__times.c \
+ src/truncate.c src/access.c src/stat.c src/lstat.c src/pathconf.c \
+ src/newlibc.c src/no_posix.c src/no_libc.c src/utsname.c
+
+BSD_LIBC_C_FILES = src/strlcpy.c src/strlcat.c
+
+libcsupport_a_SOURCES = src/gxx_wrappers.c src/printk.c $(BSD_LIBC_C_FILES) \
+ $(BASE_FS_C_FILES) $(MALLOC_C_FILES) $(ERROR_C_FILES) \
+ $(ASSOCIATION_C_FILES)
+
+if UNIX
+libcsupport_a_SOURCES += src/unixlibc.c src/hosterr.c
+else
+libcsupport_a_SOURCES += $(LIBC_GLUE_C_FILES) $(PASSWORD_GROUP_C_FILES) \
+ $(TERMINAL_IDENTIFICATION_C_FILES) $(SYSTEM_CALL_C_FILES) \
+ $(DIRECTORY_SCAN_C_FILES) $(ID_C_FILES) src/envlock.c \
+ $(TERMIOS_C_FILES)
+endif
+
+libcsupport_g_a_SOURCES = $(libcsupport_a_SOURCES)
+
+EXTRA_DIST = src/TODO src/CASES src/README
+
+DISTCLEANFILES =
+
+PREINSTALL_DIRS =
+PREINSTALL_FILES =
+
+$(PROJECT_INCLUDE)/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)
+ @: > $(PROJECT_INCLUDE)/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems
+ @: > $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/chain.h: include/chain.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/chain.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/chain.h
+
+$(PROJECT_INCLUDE)/rtems/console.h: include/console.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/console.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/console.h
+
+$(PROJECT_INCLUDE)/rtems/clockdrv.h: include/clockdrv.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/clockdrv.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/clockdrv.h
+
+$(PROJECT_INCLUDE)/rtems/iosupp.h: include/iosupp.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/iosupp.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/iosupp.h
+
+$(PROJECT_INCLUDE)/rtems/ringbuf.h: include/ringbuf.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/ringbuf.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/ringbuf.h
+
+$(PROJECT_INCLUDE)/rtems/rtc.h: include/rtc.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtc.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtc.h
+
+$(PROJECT_INCLUDE)/rtems/spurious.h: include/spurious.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/spurious.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/spurious.h
+
+$(PROJECT_INCLUDE)/rtems/timerdrv.h: include/timerdrv.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/timerdrv.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/timerdrv.h
+
+$(PROJECT_INCLUDE)/rtems/vmeintr.h: include/vmeintr.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/vmeintr.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/vmeintr.h
+
+if NEWLIB
+$(PROJECT_INCLUDE)/stdint.h: include/stdint.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/stdint.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/stdint.h
+
+$(PROJECT_INCLUDE)/inttypes.h: include/inttypes.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/inttypes.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/inttypes.h
+endif
+
+$(PROJECT_INCLUDE)/rtems/motorola/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems/motorola
+ @: > $(PROJECT_INCLUDE)/rtems/motorola/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/motorola/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/motorola/mc68230.h: include/motorola/mc68230.h $(PROJECT_INCLUDE)/rtems/motorola/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/motorola/mc68230.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/motorola/mc68230.h
+
+$(PROJECT_INCLUDE)/rtems/motorola/mc68681.h: include/motorola/mc68681.h $(PROJECT_INCLUDE)/rtems/motorola/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/motorola/mc68681.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/motorola/mc68681.h
+
+$(PROJECT_INCLUDE)/rtems/assoc.h: include/rtems/assoc.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/assoc.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/assoc.h
+
+$(PROJECT_INCLUDE)/rtems/error.h: include/rtems/error.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/error.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/error.h
+
+$(PROJECT_INCLUDE)/rtems/libcsupport.h: include/rtems/libcsupport.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/libcsupport.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/libcsupport.h
+
+$(PROJECT_INCLUDE)/rtems/libio.h: include/rtems/libio.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/libio.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/libio.h
+
+$(PROJECT_INCLUDE)/rtems/libio_.h: include/rtems/libio_.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/libio_.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/libio_.h
+
+$(PROJECT_INCLUDE)/rtems/termiostypes.h: include/rtems/termiostypes.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/termiostypes.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/termiostypes.h
+
+$(PROJECT_INCLUDE)/rtems/cdefs.h: include/rtems/cdefs.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/cdefs.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/cdefs.h
+
+if NEWLIB
+$(PROJECT_INCLUDE)/sys/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/sys
+ @: > $(PROJECT_INCLUDE)/sys/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/sys/$(dirstamp)
+
+$(PROJECT_INCLUDE)/sys/ioccom.h: include/sys/ioccom.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/ioccom.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/ioccom.h
+
+$(PROJECT_INCLUDE)/sys/filio.h: include/sys/filio.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/filio.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/filio.h
+
+$(PROJECT_INCLUDE)/sys/ioctl.h: include/sys/ioctl.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/ioctl.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/ioctl.h
+
+$(PROJECT_INCLUDE)/sys/sockio.h: include/sys/sockio.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/sockio.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/sockio.h
+
+$(PROJECT_INCLUDE)/sys/ttycom.h: include/sys/ttycom.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/ttycom.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/ttycom.h
+
+$(PROJECT_INCLUDE)/sys/termios.h: include/sys/termios.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/termios.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/termios.h
+
+$(PROJECT_INCLUDE)/sys/utsname.h: include/sys/utsname.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/utsname.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/utsname.h
+
+$(PROJECT_INCLUDE)/sys/cdefs.h: include/sys/cdefs.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/cdefs.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/cdefs.h
+endif
+
+$(PROJECT_INCLUDE)/rtems/zilog/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems/zilog
+ @: > $(PROJECT_INCLUDE)/rtems/zilog/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/zilog/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/zilog/z8036.h: include/zilog/z8036.h $(PROJECT_INCLUDE)/rtems/zilog/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/zilog/z8036.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/zilog/z8036.h
+
+$(PROJECT_INCLUDE)/rtems/zilog/z8530.h: include/zilog/z8530.h $(PROJECT_INCLUDE)/rtems/zilog/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/zilog/z8530.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/zilog/z8530.h
+
+$(PROJECT_INCLUDE)/rtems/zilog/z8536.h: include/zilog/z8536.h $(PROJECT_INCLUDE)/rtems/zilog/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/zilog/z8536.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/zilog/z8536.h
+
+CLEANFILES += $(PREINSTALL_FILES)
+DISTCLEANFILES += $(PREINSTALL_DIRS)
+
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/libcsupport/include/chain.h b/cpukit/libcsupport/include/chain.h
new file mode 100644
index 0000000000..36c526a614
--- /dev/null
+++ b/cpukit/libcsupport/include/chain.h
@@ -0,0 +1,361 @@
+/* chain.h
+ *
+ * This include file contains all the constants and structures associated
+ * with doubly linked chains. This file actually just provides an
+ * interface to the chain object in rtems.
+ *
+ * COPYRIGHT (c) 1989-1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may in
+ * the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $ld:
+ */
+
+#ifndef __CHAIN_h
+#define __CHAIN_h
+
+#include <rtems.h>
+
+/*
+ * Chain_Initialize
+ *
+ * This routine initializes the_chain structure to manage the
+ * contiguous array of number_nodes nodes which starts at
+ * starting_address. Each node is of node_size bytes.
+ *
+ * Chain_Control *the_chain, * IN *
+ * void *starting_address, * IN *
+ * uint32_t number_nodes, * IN *
+ * uint32_t node_size * IN *
+ */
+
+#define Chain_Initialize( the_chain, starting_address, \
+ number_nodes, node_size ) \
+ _Chain_Initialize( the_chain, starting_address, \
+ number_nodes, node_size ) \
+
+
+/*
+ * Chain_Initialize_empty
+ *
+ * This routine initializes the specified chain to contain zero nodes.
+ *
+ * Chain_Control *the_chain * IN *
+ */
+
+#define Chain_Initialize_empty( the_chain ) \
+ _Chain_Initialize_empty( the_chain )
+
+
+/*
+ * Chain_Are_nodes_equal
+ *
+ * This function returns TRUE if LEFT and RIGHT are equal,
+ * and FALSE otherwise.
+ *
+ * Chain_Node *left, * IN *
+ * Chain_Node *right * IN *
+ */
+
+#define Chain_Are_nodes_equal( left, right ) \
+ _Chain_Are_nodes_equal( left, right )
+
+
+/*
+ * Chain_Extract_unprotected
+ *
+ * This routine extracts the_node from the chain on which it resides.
+ * It does NOT disable interrupts to insure the atomicity of the
+ * extract operation.
+ *
+ * Chain_Node *the_node * IN *
+ */
+
+#define Chain_Extract_unprotected( the_node ) \
+ _Chain_Extract_unprotected( the_node )
+
+
+/*
+ * Chain_Extract
+ *
+ * This routine extracts the_node from the chain on which it resides.
+ * It disables interrupts to insure the atomicity of the
+ * extract operation.
+ *
+ * Chain_Node *the_node * IN *
+ */
+
+#define Chain_Extract( the_node ) \
+ _Chain_Extract( the_node )
+
+
+/*
+ * Chain_Get_unprotected
+ *
+ * This function removes the first node from the_chain and returns
+ * a pointer to that node. If the_chain is empty, then NULL is returned.
+ * It does NOT disable interrupts to insure the atomicity of the
+ * get operation.
+ *
+ * Chain_Control *the_chain * IN *
+ */
+
+#define Chain_Get_unprotected( the_chain ) \
+ _Chain_Get_unprotected( the_chain )
+
+
+/*
+ * Chain_Get
+ *
+ * This function removes the first node from the_chain and returns
+ * a pointer to that node. If the_chain is empty, then NULL is returned.
+ * It disables interrupts to insure the atomicity of the
+ * get operation.
+ *
+ * Chain_Control *the_chain * IN *
+ */
+
+#define Chain_Get( the_chain ) \
+ _Chain_Get( the_chain )
+
+
+/*
+ * Chain_Get_first_unprotected
+ *
+ * This function removes the first node from the_chain and returns
+ * a pointer to that node. It does NOT disable interrupts to insure
+ * the atomicity of the get operation.
+ *
+ * Chain_Control *the_chain * IN *
+ */
+
+#define Chain_Get_first_unprotected( the_chain ) \
+ _Chain_Get_first_unprotected( the_chain )
+
+
+/*
+ * Chain_Insert_unprotected
+ *
+ * This routine inserts the_node on a chain immediately following
+ * after_node. It does NOT disable interrupts to insure the atomicity
+ * of the extract operation.
+ *
+ * Chain_Node *after_node, * IN *
+ * Chain_Node *the_node * IN *
+ */
+
+#define Chain_Insert_unprotected( after_node, the_node ) \
+ _Chain_Insert_unprotected( after_node, the_node )
+
+
+/*
+ * Chain_Insert
+ *
+ * This routine inserts the_node on a chain immediately following
+ * after_node. It disables interrupts to insure the atomicity
+ * of the extract operation.
+ *
+ * Chain_Node *after_node, * IN *
+ * Chain_Node *the_node * IN *
+ */
+
+#define Chain_Insert( after_node, the_node ) \
+ _Chain_Insert( after_node, the_node )
+
+
+/*
+ * Chain_Append_unprotected
+ *
+ * This routine appends the_node onto the end of the_chain.
+ * It does NOT disable interrupts to insure the atomicity of the
+ * append operation.
+ *
+ * Chain_Control *the_chain, * IN *
+ * Chain_Node *the_node * IN *
+ */
+
+#define Chain_Append_unprotected( the_chain, the_node ) \
+ _Chain_Append_unprotected( the_chain, the_node )
+
+
+/*
+ * Chain_Append
+ *
+ * This routine appends the_node onto the end of the_chain.
+ * It disables interrupts to insure the atomicity of the
+ * append operation.
+ *
+ * Chain_Control *the_chain, * IN *
+ * Chain_Node *the_node * IN *
+ */
+
+#define Chain_Append( the_chain, the_node ) \
+ _Chain_Append( the_chain, the_node )
+
+
+/*
+ * Chain_Prepend_unprotected
+ *
+ * This routine prepends the_node onto the front of the_chain.
+ * It does NOT disable interrupts to insure the atomicity of the
+ * prepend operation.
+ *
+ * Chain_Control *the_chain, * IN *
+ * Chain_Node *the_node * IN *
+ */
+
+#define Chain_Prepend_unprotected( the_chain, the_node ) \
+ _Chain_Prepend_unprotected( the_chain, the_node )
+
+
+/*
+ * Chain_Prepend
+ *
+ * This routine prepends the_node onto the front of the_chain.
+ * It disables interrupts to insure the atomicity of the
+ * prepend operation.
+ *
+ * Chain_Control *the_chain, * IN *
+ * Chain_Node *the_node * IN *
+ */
+
+#define Chain_Prepend( the_chain, the_node ) \
+ _Chain_Prepend( the_chain, the_node )
+
+
+/*
+ * Chain_Head
+ *
+ * This function returns a pointer to the first node on the chain.
+ *
+ * Chain_Control *the_chain * IN *
+ */
+
+#define Chain_Head( the_chain ) \
+ _Chain_Head( the_chain )
+
+
+/*
+ * Chain_Tail
+ *
+ * This function returns a pointer to the last node on the chain.
+ *
+ * Chain_Control *the_chain * IN *
+ */
+
+#define Chain_Tail( the_chain ) \
+ _Chain_Tail( the_chain )
+
+
+/*
+ * Chain_Is_head
+ *
+ * This function returns TRUE if the_node is the head of the_chain and
+ * FALSE otherwise.
+ *
+ * Chain_Control *the_chain, * IN *
+ * Chain_Node *the_node * IN *
+ */
+
+#define Chain_Is_head( the_chain, the_node ) \
+ _Chain_Is_head( the_chain, the_node )
+
+
+/*
+ * Chain_Is_tail
+ *
+ * This function returns TRUE if the_node is the tail of the_chain and
+ * FALSE otherwise.
+ *
+ * Chain_Control *the_chain, * IN *
+ * Chain_Node *the_node * IN *
+ */
+
+#define Chain_Is_tail( the_chain, the_node ) \
+ _Chain_Is_tail( the_chain, the_node )
+
+
+/*
+ * Chain_Is_first
+ *
+ * This function returns TRUE if the_node is the first node on a chain and
+ * FALSE otherwise.
+ *
+ * Chain_Node *the_node * IN *
+ */
+
+#define Chain_Is_first( the_node ) \
+ _Chain_Is_first( the_node )
+
+
+/*
+ * Chain_Is_last
+ *
+ * This function returns TRUE if the_node is the last node on a chain and
+ * FALSE otherwise.
+ *
+ * Chain_Node *the_node * IN *
+ */
+
+#define Chain_Is_last( the_node ) \
+ _Chain_Is_last( the_node )
+
+
+/*
+ * Chain_Is_empty
+ *
+ * This function returns TRUE if there are no nodes on the_chain and
+ * FALSE otherwise.
+ *
+ * Chain_Control *the_chain * IN *
+ */
+
+#define Chain_Is_empty( the_chain ) \
+ _Chain_Is_empty( the_chain )
+
+
+/*
+ * Chain_Has_only_one_node
+ *
+ * This function returns TRUE if there is only one node on the_chain and
+ * FALSE otherwise.
+ *
+ * Chain_Control *the_chain * IN *
+ */
+
+#define Chain_Has_only_one_node( the_chain ) \
+ _Chain_Has_only_one_node( the_chain )
+
+
+/*
+ * Chain_Is_null
+ *
+ * This function returns TRUE if the_chain is NULL and FALSE otherwise.
+ *
+ * Chain_Control *the_chain * IN *
+ */
+
+#define Chain_Is_null( the_chain ) \
+ _Chain_Is_null( the_chain )
+
+
+/*
+ * Chain_Is_null_node
+ *
+ * This function returns TRUE if the_node is NULL and FALSE otherwise.
+ *
+ * Chain_Node *the_node * IN *
+ */
+
+#define Chain_Is_null_node( the_node ) \
+ _Chain_Is_null_node( the_node )
+
+
+#undef __RTEMS_APPLICATION__
+#include <rtems/score/chain.inl>
+#define __RTEMS_APPLICATION__
+#endif
+/* end of include file */
diff --git a/cpukit/libcsupport/include/clockdrv.h b/cpukit/libcsupport/include/clockdrv.h
new file mode 100644
index 0000000000..1bec3362b0
--- /dev/null
+++ b/cpukit/libcsupport/include/clockdrv.h
@@ -0,0 +1,50 @@
+/* clock.h
+ *
+ * This file describes the Clock Driver for all boards.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __CLOCK_DRIVER_h
+#define __CLOCK_DRIVER_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* variables */
+
+extern volatile uint32_t Clock_driver_ticks;
+extern rtems_device_major_number rtems_clock_major;
+extern rtems_device_minor_number rtems_clock_minor;
+
+/* default clock driver entry */
+
+#define CLOCK_DRIVER_TABLE_ENTRY \
+ { Clock_initialize, NULL, NULL, NULL, NULL, Clock_control }
+
+rtems_device_driver Clock_initialize(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *
+);
+
+rtems_device_driver Clock_control(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *pargp
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/libcsupport/include/console.h b/cpukit/libcsupport/include/console.h
new file mode 100644
index 0000000000..4c04dde842
--- /dev/null
+++ b/cpukit/libcsupport/include/console.h
@@ -0,0 +1,68 @@
+/* console.h
+ *
+ * This file describes the Console Device Driver for all boards.
+ * This driver provides support for the standard C Library.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef _CONSOLE_DRIVER_h
+#define _CONSOLE_DRIVER_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define CONSOLE_DRIVER_TABLE_ENTRY \
+ { console_initialize, console_open, console_close, \
+ console_read, console_write, console_control }
+
+rtems_device_driver console_initialize(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *
+);
+
+rtems_device_driver console_open(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *
+);
+
+rtems_device_driver console_close(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *
+);
+
+rtems_device_driver console_read(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *
+);
+
+rtems_device_driver console_write(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *
+);
+
+rtems_device_driver console_control(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/libcsupport/include/inttypes.h b/cpukit/libcsupport/include/inttypes.h
new file mode 100644
index 0000000000..dad6c67c7d
--- /dev/null
+++ b/cpukit/libcsupport/include/inttypes.h
@@ -0,0 +1,22 @@
+/*
+ * inttypes.h
+ *
+ * ISO C99 Format conversion of integer types.
+ *
+ * $Id$
+ */
+
+#ifndef __INTTYPES_H
+#define __INTTYPES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/libcsupport/include/iosupp.h b/cpukit/libcsupport/include/iosupp.h
new file mode 100644
index 0000000000..e8f19d1d8e
--- /dev/null
+++ b/cpukit/libcsupport/include/iosupp.h
@@ -0,0 +1,43 @@
+/* iosupp.h
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __IOSUPP_h
+#define __IOSUPP_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* character constants */
+
+#define BS 0x08 /* backspace */
+#define LF 0x0a /* line feed */
+#define CR 0x0d /* carriage return */
+#define XON 0x11 /* control-Q */
+#define XOFF 0x13 /* control-S */
+
+/* structures */
+
+#ifdef IOSUPP_INIT
+#define IOSUPP_EXTERN
+#else
+#undef IOSUPP_EXTERN
+#define IOSUPP_EXTERN extern
+#endif
+
+/* functions */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/libcsupport/include/motorola/mc68230.h b/cpukit/libcsupport/include/motorola/mc68230.h
new file mode 100644
index 0000000000..952c1cdb3c
--- /dev/null
+++ b/cpukit/libcsupport/include/motorola/mc68230.h
@@ -0,0 +1,70 @@
+/*
+ * mc68230.h -- Low level support code for the Motorola 68230 Parallel
+ * Interface/Timer (PIT)
+ *
+ * Modified by Doug McBride, Colorado Space Grant College
+ *
+ * Format taken partly from RTEMS code and mostly from Motorola IDP user's
+ * manual. RTEMS copyright information below.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __MC68230_H__
+#define __MC68230_H__
+
+/* Some Motorola IDP User manual defines: */
+#define PIT_ADDR 0x00c01003 /* base address of the PIT */
+#define REGOFF 0x04 /* Difference between addresses */
+#define VECT 64
+#define H1VECT 0x00
+#define H2VECT 0x01
+#define H3VECT 0x02
+#define H4VECT 0x03
+
+/*
+ * mc68230 register offsets
+ */
+#define PGCR 0x00
+#define PSRR 1*REGOFF
+#define PADDR 2*REGOFF
+#define PBDDR 3*REGOFF
+#define PCDDR 4*REGOFF
+#define PIVR 5*REGOFF
+#define PACR 6*REGOFF
+#define PBCR 7*REGOFF
+#define PADR 8*REGOFF
+#define PBDR 9*REGOFF
+#define PAAR 10*REGOFF
+#define PBAR 11*REGOFF
+#define PCDR 12*REGOFF
+#define PITSR 13*REGOFF
+#define TCR 16*REGOFF
+#define TIVR 17*REGOFF
+#define CPRH 19*REGOFF
+#define CPRM 20*REGOFF
+#define CPRL 21*REGOFF
+#define CNTRH 23*REGOFF
+#define CNTRM 24*REGOFF
+#define CNTRL 25*REGOFF
+#define TSR 26*REGOFF
+
+/* Some RTEMS style defines: */
+#ifndef VOL8
+#define VOL8( ptr ) ((volatile uint8_t *)(ptr))
+#endif
+
+#define MC68230_WRITE( reg, data ) \
+ *(VOL8(PIT_ADDR+reg)) = (data)
+
+#define MC68230_READ( reg, data ) \
+ (data) = *(VOL8(PIT_ADDR+reg))
+
+#endif
diff --git a/cpukit/libcsupport/include/motorola/mc68681.h b/cpukit/libcsupport/include/motorola/mc68681.h
new file mode 100644
index 0000000000..5196f7ff75
--- /dev/null
+++ b/cpukit/libcsupport/include/motorola/mc68681.h
@@ -0,0 +1,303 @@
+/*
+ * mc68681-duart.h -- Low level support code for the Motorola mc68681
+ * DUART.
+ *
+ * Originally written by rob@cygnus.com (Rob Savoye) for the libgloss
+ * IDP support.
+ *
+ * $Id$
+ */
+
+#ifndef __MC68681_H__
+#define __MC68681_H__
+
+/*
+ * In the dark ages when this controller was designed, it was actually
+ * possible to access data on unaligned byte boundaries with no penalty.
+ * Now we find this chip in configurations in which the registers are
+ * at 16-bit, 32-bit, and 64-bit boundaries at the whim of the board
+ * designer. If the registers are not at byte addresses, then
+ * set this multiplier before including this file to correct the offsets.
+ */
+
+#ifndef MC68681_OFFSET_MULTIPLIER
+#define MC68681_OFFSET_MULTIPLIER 1
+#endif
+
+#define __MC68681_REG(_R) ((_R) * MC68681_OFFSET_MULTIPLIER)
+
+/*
+ * mc68681 register offsets Read/Write Addresses
+ */
+#define MC68681_MODE_REG_1A __MC68681_REG(0) /* MR1A-MR Prior to Read */
+#define MC68681_MODE_REG_2A __MC68681_REG(0) /* MR2A-MR After Read */
+
+#define MC68681_COUNT_MODE_CURRENT_MSB __MC68681_REG(6) /* CTU */
+#define MC68681_COUNTER_TIMER_UPPER_REG __MC68681_REG(6) /* CTU */
+#define MC68681_COUNT_MODE_CURRENT_LSB __MC68681_REG(7) /* CTL */
+#define MC68681_COUNTER_TIMER_LOWER_REG __MC68681_REG(7) /* CTL */
+#define MC68681_INTERRUPT_VECTOR_REG __MC68681_REG(12) /* IVR */
+
+#define MC68681_MODE_REG_1B __MC68681_REG(8) /* MR1B-MR Prior to Read */
+#define MC68681_MODE_REG_2B __MC68681_REG(8) /* MR2BA-MR After Read */
+
+/*
+ * mc68681 register offsets Read Only Addresses
+ */
+#define MC68681_STATUS_REG_A __MC68681_REG(1) /* SRA */
+#define MC68681_MASK_ISR_REG __MC68681_REG(2) /* MISR */
+#define MC68681_RECEIVE_BUFFER_A __MC68681_REG(3) /* RHRA */
+#define MC68681_INPUT_PORT_CHANGE_REG __MC68681_REG(4) /* IPCR */
+#define MC68681_INTERRUPT_STATUS_REG __MC68681_REG(5) /* ISR */
+#define MC68681_STATUS_REG_B __MC68681_REG(9) /* SRB */
+#define MC68681_RECEIVE_BUFFER_B __MC68681_REG(11) /* RHRB */
+#define MC68681_INPUT_PORT __MC68681_REG(13) /* IP */
+#define MC68681_START_COUNT_CMD __MC68681_REG(14) /* SCC */
+#define MC68681_STOP_COUNT_CMD __MC68681_REG(15) /* STC */
+
+/*
+ * mc68681 register offsets Write Only Addresses
+ */
+#define MC68681_CLOCK_SELECT_REG_A __MC68681_REG(1) /* CSRA */
+#define MC68681_COMMAND_REG_A __MC68681_REG(2) /* CRA */
+#define MC68681_TRANSMIT_BUFFER_A __MC68681_REG(3) /* THRA */
+#define MC68681_AUX_CTRL_REG __MC68681_REG(4) /* ACR */
+#define MC68681_INTERRUPT_MASK_REG __MC68681_REG(5) /* IMR */
+#define MC68681_CLOCK_SELECT_REG_B __MC68681_REG(9) /* CSRB */
+#define MC68681_COMMAND_REG_B __MC68681_REG(10) /* CRB */
+#define MC68681_TRANSMIT_BUFFER_B __MC68681_REG(11) /* THRB */
+#define MC68681_OUTPUT_PORT_CONFIG_REG __MC68681_REG(13) /* OPCR */
+#define MC68681_OUTPUT_PORT_SET_REG __MC68681_REG(14) /* SOPBC */
+#define MC68681_OUTPUT_PORT_RESET_BITS __MC68681_REG(15) /* COPBC */
+
+
+#ifndef MC6681_VOL
+#define MC6681_VOL( ptr ) ((volatile unsigned char *)(ptr))
+#endif
+
+#define MC68681_WRITE( _base, _reg, _data ) \
+ *((volatile unsigned char *)_base+_reg) = (_data)
+
+#define MC68681_READ( _base, _reg ) \
+ *(((volatile unsigned char *)_base+_reg))
+
+
+
+#define MC68681_CLEAR 0x00
+
+#define MC68681_PORT_A 0
+#define MC68681_PORT_B 1
+
+/*
+ * DUART Command Register Definitions:
+ *
+ * MC68681_COMMAND_REG_A,MC68681_COMMAND_REG_B
+ */
+#define MC68681_MODE_REG_ENABLE_RX 0x01
+#define MC68681_MODE_REG_DISABLE_RX 0x02
+#define MC68681_MODE_REG_ENABLE_TX 0x04
+#define MC68681_MODE_REG_DISABLE_TX 0x08
+#define MC68681_MODE_REG_RESET_MR_PTR 0x10
+#define MC68681_MODE_REG_RESET_RX 0x20
+#define MC68681_MODE_REG_RESET_TX 0x30
+#define MC68681_MODE_REG_RESET_ERROR 0x40
+#define MC68681_MODE_REG_RESET_BREAK 0x50
+#define MC68681_MODE_REG_START_BREAK 0x60
+#define MC68681_MODE_REG_STOP_BREAK 0x70
+#define MC68681_MODE_REG_SET_RX_BRG 0x80
+#define MC68681_MODE_REG_CLEAR_RX_BRG 0x90
+#define MC68681_MODE_REG_SET_TX_BRG 0xa0
+#define MC68681_MODE_REG_CLEAR_TX_BRG 0xb0
+#define MC68681_MODE_REG_SET_STANDBY 0xc0
+#define MC68681_MODE_REG_SET_ACTIVE 0xd0
+
+/*
+ * Mode Register Definitions
+ *
+ * MC68681_MODE_REG_1A
+ * MC68681_MODE_REG_1B
+ */
+#define MC68681_5BIT_CHARS 0x00
+#define MC68681_6BIT_CHARS 0x01
+#define MC68681_7BIT_CHARS 0x02
+#define MC68681_8BIT_CHARS 0x03
+
+#define MC68681_ODD_PARITY 0x00
+#define MC68681_EVEN_PARITY 0x04
+
+#define MC68681_WITH_PARITY 0x00
+#define MC68681_FORCE_PARITY 0x08
+#define MC68681_NO_PARITY 0x10
+#define MC68681_MULTI_DROP 0x18
+
+#define MC68681_ERR_MODE_CHAR 0x00
+#define MC68681_ERR_MODE_BLOCK 0x20
+
+#define MC68681_RX_INTR_RX_READY 0x00
+#define MC68681_RX_INTR_FFULL 0x40
+
+#define MC68681_NO_RX_RTS_CTL 0x00
+#define MC68681_RX_RTS_CTRL 0x80
+
+
+/*
+ * Mode Register Definitions
+ *
+ * MC68681_MODE_REG_2A
+ * MC68681_MODE_REG_2B
+ */
+#define MC68681_STOP_BIT_LENGTH__563 0x00
+#define MC68681_STOP_BIT_LENGTH__625 0x01
+#define MC68681_STOP_BIT_LENGTH__688 0x02
+#define MC68681_STOP_BIT_LENGTH__75 0x03
+#define MC68681_STOP_BIT_LENGTH__813 0x04
+#define MC68681_STOP_BIT_LENGTH__875 0x05
+#define MC68681_STOP_BIT_LENGTH__938 0x06
+#define MC68681_STOP_BIT_LENGTH_1 0x07
+#define MC68681_STOP_BIT_LENGTH_1_563 0x08
+#define MC68681_STOP_BIT_LENGTH_1_625 0x09
+#define MC68681_STOP_BIT_LENGTH_1_688 0x0a
+#define MC68681_STOP_BIT_LENGTH_1_75 0x0b
+#define MC68681_STOP_BIT_LENGTH_1_813 0x0c
+#define MC68681_STOP_BIT_LENGTH_1_875 0x0d
+#define MC68681_STOP_BIT_LENGTH_1_938 0x0e
+#define MC68681_STOP_BIT_LENGTH_2 0x0f
+
+#define MC68681_CTS_ENABLE_TX 0x10
+#define MC68681_TX_RTS_CTRL 0x20
+
+#define MC68681_CHANNEL_MODE_NORMAL 0x00
+#define MC68681_CHANNEL_MODE_ECHO 0x40
+#define MC68681_CHANNEL_MODE_LOCAL_LOOP 0x80
+#define MC68681_CHANNEL_MODE_REMOTE_LOOP 0xc0
+
+/*
+ * Status Register Definitions
+ *
+ * MC68681_STATUS_REG_A, MC68681_STATUS_REG_B
+ */
+#define MC68681_RX_READY 0x01
+#define MC68681_FFULL 0x02
+#define MC68681_TX_READY 0x04
+#define MC68681_TX_EMPTY 0x08
+#define MC68681_OVERRUN_ERROR 0x10
+#define MC68681_PARITY_ERROR 0x20
+#define MC68681_FRAMING_ERROR 0x40
+#define MC68681_RECEIVED_BREAK 0x80
+
+
+/*
+ * Interupt Status Register Definitions.
+ *
+ * MC68681_INTERRUPT_STATUS_REG
+ */
+
+
+/*
+ * Interupt Mask Register Definitions
+ *
+ * MC68681_INTERRUPT_MASK_REG
+ */
+#define MC68681_IR_TX_READY_A 0x01
+#define MC68681_IR_RX_READY_A 0x02
+#define MC68681_IR_BREAK_A 0x04
+#define MC68681_IR_COUNTER_READY 0x08
+#define MC68681_IR_TX_READY_B 0x10
+#define MC68681_IR_RX_READY_B 0x20
+#define MC68681_IR_BREAK_B 0x40
+#define MC68681_IR_INPUT_PORT_CHANGE 0x80
+
+/*
+ * Status Register Definitions.
+ *
+ * MC68681_STATUS_REG_A,MC68681_STATUS_REG_B
+ */
+#define MC68681_STATUS_RXRDY 0x01
+#define MC68681_STATUS_FFULL 0x02
+#define MC68681_STATUS_TXRDY 0x04
+#define MC68681_STATUS_TXEMT 0x08
+#define MC68681_STATUS_OVERRUN_ERROR 0x10
+#define MC68681_STATUS_PARITY_ERROR 0x20
+#define MC68681_STATUS_FRAMING_ERROR 0x40
+#define MC68681_STATUS_RECEIVED_BREAK 0x80
+
+/*
+ * Definitions for the Interrupt Vector Register:
+ *
+ * MC68681_INTERRUPT_VECTOR_REG
+ */
+#define MC68681_INTERRUPT_VECTOR_INIT 0x0f
+
+/*
+ * Definitions for the Auxiliary Control Register
+ *
+ * MC68681_AUX_CTRL_REG
+ */
+#define MC68681_AUX_BRG_SET1 0x00
+#define MC68681_AUX_BRG_SET2 0x80
+
+
+/*
+ * The following Baud rates assume the X1 clock pin is driven with a
+ * 3.6864 MHz signal. If a different frequency is used the DUART channel
+ * is running at the follwoing baud rate:
+ * ((Table Baud Rate)*frequency)/3.6864 MHz
+ */
+
+/*
+ * Definitions for the Clock Select Register:
+ *
+ * MC68681_CLOCK_SELECT_REG_A,MC68681_CLOCK_SELECT_REG_A
+ *
+ * Note: ACR[7] is the MSB of the Auxiliary Control register
+ * X is the extend bit.
+ * CRA - 0x08 Set Rx BRG Select Extend Bit (X=1)
+ * CRA - 0x09 Clear Rx BRG Select Extend Bit (X=0)
+ * CRB - 0x0a Set Tx BRG Select Extend Bit (X=1)
+ * CRB - 0x0b Clear Tx BRG Select Extend Bit (x=1)
+ */
+#define MC68681_BAUD_RATE_MASK_50 0x00 /* ACR[7]=0,X=0 */
+ /* ARC[7]=1,X=1 */
+#define MC68681_BAUD_RATE_MASK_75 0x00 /* ACR[7]=0,X=0 */
+ /* ARC[7]=1,X=1 */
+#define MC68681_BAUD_RATE_MASK_110 0x01
+#define MC68681_BAUD_RATE_MASK_134_5 0x02
+#define MC68681_BAUD_RATE_MASK_150 0x03 /* ACR[7]=0,X=0 */
+ /* ARC[7]=1,X=1 */
+#define MC68681_BAUD_RATE_MASK_200 0x03 /* ACR[7]=0,X=0 */
+ /* ARC[7]=1,X=1 */
+#define MC68681_BAUD_RATE_MASK_300 0x04 /* ACR[7]=0,X=0 */
+ /* ARC[7]=1,X=1 */
+#define MC68681_BAUD_RATE_MASK_600 0x05 /* ACR[7]=0,X=0 */
+ /* ARC[7]=1,X=1 */
+#define MC68681_BAUD_RATE_MASK_1050 0x07 /* ACR[7]=0,X=0 */
+ /* ARC[7]=1,X=1 */
+#define MC68681_BAUD_RATE_MASK_1200 0x06 /* ACR[7]=0,X=0 */
+ /* ARC[7]=1,X=1 */
+#define MC68681_BAUD_RATE_MASK_1800 0x0a /* ACR[7]=0,X=0 */
+ /* ARC[7]=1,X=1 */
+#define MC68681_BAUD_RATE_MASK_2400 0x08 /* ACR[7]=0,X=0 */
+ /* ARC[7]=1,X=1 */
+#define MC68681_BAUD_RATE_MASK_3600 0x04 /* ACR[7]=0,X=0 */
+ /* ARC[7]=1,X=1 */
+#define MC68681_BAUD_RATE_MASK_4800 0x09
+#define MC68681_BAUD_RATE_MASK_7200 0x0a /* ACR[7]=0,X=0 */
+ /* ARC[7]=1,X=1 */
+#define MC68681_BAUD_RATE_MASK_9600 0xbb
+
+#define MC68681_BAUD_RATE_MASK_14_4K 0x05 /* ACR[7]=0,X=0 */
+ /* ARC[7]=1,X=1 */
+#define MC68681_BAUD_RATE_MASK_19_2K 0xcc /* ACR[7]=1,X=0 */
+ /* ARC[7]=0,X=1 */
+#define MC68681_BAUD_RATE_MASK_28_8K 0x06 /* ACR[7]=0,X=0 */
+ /* ARC[7]=1,X=1 */
+#define MC68681_BAUD_RATE_MASK_38_4K 0xcc /* ACR[7]=0,X=0 */
+ /* ARC[7]=1,X=1 */
+#define MC68681_BAUD_RATE_MASK_57_6K 0x07 /* ACR[7]=0,X=0 */
+ /* ARC[7]=1,X=1 */
+#define MC68681_BAUD_RATE_MASK_115_5K 0x08
+#define MC68681_BAUD_RATE_MASK_TIMER 0xdd
+#define MC68681_BAUD_RATE_MASK_TIMER_16X 0xee
+#define MC68681_BAUD_RATE_MASK_TIMER_1X 0xff
+
+#endif
diff --git a/cpukit/libcsupport/include/ringbuf.h b/cpukit/libcsupport/include/ringbuf.h
new file mode 100644
index 0000000000..3895b82274
--- /dev/null
+++ b/cpukit/libcsupport/include/ringbuf.h
@@ -0,0 +1,53 @@
+/*
+ * ringbuf.h
+ *
+ * This file provides simple ring buffer functionality.
+ *
+ * $Id$
+ */
+
+#ifndef __RINGBUF_H__
+#define __RINGBUF_H__
+
+#ifndef RINGBUF_QUEUE_LENGTH
+#define RINGBUF_QUEUE_LENGTH 128
+#endif
+
+typedef struct {
+ char buffer[RINGBUF_QUEUE_LENGTH];
+ volatile int head;
+ volatile int tail;
+} Ring_buffer_t;
+
+#define Ring_buffer_Initialize( _buffer ) \
+ do { \
+ (_buffer)->head = (_buffer)->tail = 0; \
+ } while ( 0 )
+
+#define Ring_buffer_Is_empty( _buffer ) \
+ ( (_buffer)->head == (_buffer)->tail )
+
+#define Ring_buffer_Is_full( _buffer ) \
+ ( (_buffer)->head == ((_buffer)->tail + 1) % RINGBUF_QUEUE_LENGTH )
+
+#define Ring_buffer_Add_character( _buffer, _ch ) \
+ do { \
+ uint32_t isrlevel; \
+ \
+ rtems_interrupt_disable( isrlevel ); \
+ (_buffer)->tail = ((_buffer)->tail+1) % RINGBUF_QUEUE_LENGTH; \
+ (_buffer)->buffer[ (_buffer)->tail ] = (_ch); \
+ rtems_interrupt_enable( isrlevel ); \
+ } while ( 0 )
+
+#define Ring_buffer_Remove_character( _buffer, _ch ) \
+ do { \
+ uint32_t isrlevel; \
+ \
+ rtems_interrupt_disable( isrlevel ); \
+ (_buffer)->head = ((_buffer)->head+1) % RINGBUF_QUEUE_LENGTH; \
+ (_ch) = (_buffer)->buffer[ (_buffer)->head ]; \
+ rtems_interrupt_enable( isrlevel ); \
+ } while ( 0 )
+
+#endif
diff --git a/cpukit/libcsupport/include/rtc.h b/cpukit/libcsupport/include/rtc.h
new file mode 100644
index 0000000000..15a089dbd4
--- /dev/null
+++ b/cpukit/libcsupport/include/rtc.h
@@ -0,0 +1,38 @@
+/* rtc.h
+ *
+ * This file describes the Real-Time Clock driver for all boards.
+ * This driver provides support for the standard RTEMS routines
+ * that set the tod based on an RTC.
+ *
+ * COPYRIGHT (c) 1989-2001.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef _RTC_DRIVER_h
+#define _RTC_DRIVER_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define RTC_DRIVER_TABLE_ENTRY \
+ { rtc_initialize, NULL, NULL, NULL, NULL, NULL }
+
+rtems_device_driver rtc_initialize(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/libcsupport/include/rtems/assoc.h b/cpukit/libcsupport/include/rtems/assoc.h
new file mode 100644
index 0000000000..7c5ebe7f6a
--- /dev/null
+++ b/cpukit/libcsupport/include/rtems/assoc.h
@@ -0,0 +1,42 @@
+/*
+ *
+ * Rtems associativity routines. Mainly used to convert a value from
+ * one space to another (eg: our errno's to host errno's and v.v)
+ *
+ *
+ * $Id$
+ */
+
+#ifndef _INCLUDE_ASSOC_H
+#define _INCLUDE_ASSOC_H
+
+typedef struct {
+ const char *name;
+ uint32_t local_value;
+ uint32_t remote_value;
+} rtems_assoc_t;
+
+/*
+ * Flag/marker for optional default value in each table
+ */
+
+#define RTEMS_ASSOC_DEFAULT_NAME "(default)"
+
+const rtems_assoc_t *rtems_assoc_ptr_by_name(const rtems_assoc_t *, const char *);
+const rtems_assoc_t *rtems_assoc_ptr_by_value(const rtems_assoc_t *, uint32_t );
+const rtems_assoc_t *rtems_assoc_ptr_by_remote(const rtems_assoc_t *, uint32_t );
+
+uint32_t rtems_assoc_remote_by_local(const rtems_assoc_t *, uint32_t );
+uint32_t rtems_assoc_local_by_remote(const rtems_assoc_t *, uint32_t );
+uint32_t rtems_assoc_remote_by_name(const rtems_assoc_t *, const char *);
+uint32_t rtems_assoc_local_by_name(const rtems_assoc_t *, const char *);
+const char *rtems_assoc_name_by_local(const rtems_assoc_t *, uint32_t );
+const char *rtems_assoc_name_by_remote(const rtems_assoc_t *, uint32_t );
+
+uint32_t rtems_assoc_remote_by_local_bitfield(const rtems_assoc_t *, uint32_t );
+char *rtems_assoc_name_by_local_bitfield(const rtems_assoc_t *, uint32_t , char *);
+char *rtems_assoc_name_by_remote_bitfield(const rtems_assoc_t *, uint32_t , char *);
+uint32_t rtems_assoc_local_by_remote_bitfield(const rtems_assoc_t *, uint32_t );
+
+
+#endif /* ! _INCLUDE_ASSOC_H */
diff --git a/cpukit/libcsupport/include/rtems/cdefs.h b/cpukit/libcsupport/include/rtems/cdefs.h
new file mode 100644
index 0000000000..6abf3234ca
--- /dev/null
+++ b/cpukit/libcsupport/include/rtems/cdefs.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Berkeley Software Design, Inc.
+ *
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)cdefs.h 8.8 (Berkeley) 1/9/95
+ * $Id$
+ */
+
+#ifndef _RTEMS_CDEFS_H_
+#define _RTEMS_CDEFS_H_
+
+#if defined(__cplusplus)
+#define __BEGIN_DECLS extern "C" {
+#define __END_DECLS };
+#else
+#define __BEGIN_DECLS
+#define __END_DECLS
+#endif
+
+/*
+ * The __CONCAT macro is used to concatenate parts of symbol names, e.g.
+ * with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo.
+ * The __CONCAT macro is a bit tricky -- make sure you don't put spaces
+ * in between its arguments. __CONCAT can also concatenate double-quoted
+ * strings produced by the __STRING macro, but this only works with ANSI C.
+ *
+ * __XSTRING is like __STRING, but it expands any macros in its argument
+ * first. It is only available with ANSI C.
+ */
+#if defined(__STDC__) || defined(__cplusplus)
+#define __P(protos) protos /* full-blown ANSI C */
+#define __CONCAT1(x,y) x ## y
+#define __CONCAT(x,y) __CONCAT1(x,y)
+#define __STRING(x) #x /* stringify without expanding x */
+#define __XSTRING(x) __STRING(x) /* expand x, then stringify */
+
+#define __const const /* define reserved names to standard */
+#define __signed signed
+#define __volatile volatile
+#if defined(__cplusplus)
+#define __inline inline /* convert to C++ keyword */
+#else
+#ifndef __GNUC__
+#define __inline /* delete GCC keyword */
+#endif /* !__GNUC__ */
+#endif /* !__cplusplus */
+
+#else /* !(__STDC__ || __cplusplus) */
+#define __P(protos) () /* traditional C preprocessor */
+#define __CONCAT(x,y) x/**/y
+#define __STRING(x) "x"
+
+#ifndef __GNUC__
+#define __const /* delete pseudo-ANSI C keywords */
+#define __inline
+#define __signed
+#define __volatile
+/*
+ * In non-ANSI C environments, new programs will want ANSI-only C keywords
+ * deleted from the program and old programs will want them left alone.
+ * When using a compiler other than gcc, programs using the ANSI C keywords
+ * const, inline etc. as normal identifiers should define -DNO_ANSI_KEYWORDS.
+ * When using "gcc -traditional", we assume that this is the intent; if
+ * __GNUC__ is defined but __STDC__ is not, we leave the new keywords alone.
+ */
+#ifndef NO_ANSI_KEYWORDS
+#define const /* delete ANSI C keywords */
+#define inline
+#define signed
+#define volatile
+#endif /* !NO_ANSI_KEYWORDS */
+#endif /* !__GNUC__ */
+#endif /* !(__STDC__ || __cplusplus) */
+
+/*
+ * GCC1 and some versions of GCC2 declare dead (non-returning) and
+ * pure (no side effects) functions using "volatile" and "const";
+ * unfortunately, these then cause warnings under "-ansi -pedantic".
+ * GCC2.5 uses a new, peculiar __attribute__((attrs)) style. All of
+ * these work for GNU C++ (modulo a slight glitch in the C++ grammar
+ * in the distribution version of 2.5.5).
+ */
+#if __GNUC__ < 2
+#define __dead
+#define __dead2
+#define __pure
+#define __pure2
+#define __unused
+#define __attribute__(x)
+#endif
+#if __GNUC__ == 2 && __GNUC_MINOR__ < 5
+#define __dead __volatile
+#define __dead2
+#define __pure __const
+#define __pure2
+#define __unused
+#endif
+#if __GNUC__ == 2 && __GNUC_MINOR__ >= 5 && __GNUC_MINOR__ < 7
+#define __dead
+#define __dead2 __attribute__((__noreturn__))
+#define __pure
+#define __pure2 __attribute__((__const__))
+#define __unused
+#endif
+#if __GNUC__ == 2 && __GNUC_MINOR__ >= 7 || __GNUC__ >= 3
+#define __dead
+#define __dead2 __attribute__((__noreturn__))
+#define __pure
+#define __pure2 __attribute__((__const__))
+#define __unused __attribute__((__unused__))
+#endif
+
+#ifdef __GNUC__
+#ifdef __STDC__
+#define __weak_reference(sym,alias) \
+ __asm__(".stabs \"_" #alias "\",11,0,0,0"); \
+ __asm__(".stabs \"_" #sym "\",1,0,0,0")
+#define __warn_references(sym,msg) \
+ __asm__(".stabs \"" msg "\",30,0,0,0"); \
+ __asm__(".stabs \"_" #sym "\",1,0,0,0")
+#else
+#define __weak_reference(sym,alias) \
+ __asm__(".stabs \"_/**/alias\",11,0,0,0"); \
+ __asm__(".stabs \"_/**/sym\",1,0,0,0")
+#define __warn_references(sym,msg) \
+ __asm__(".stabs msg,30,0,0,0"); \
+ __asm__(".stabs \"_/**/sym\",1,0,0,0")
+#endif
+#endif
+
+#define __IDSTRING(name,string) \
+ static const char name[] __attribute__((__unused__)) = string
+
+#ifndef __RCSID
+#define __RCSID(s) __IDSTRING(rcsid,s)
+#endif
+
+#ifndef __RCSID_SOURCE
+#define __RCSID_SOURCE(s) __IDSTRING(rcsid_source,s)
+#endif
+
+#ifndef __COPYRIGHT
+#define __COPYRIGHT(s) __IDSTRING(copyright,s)
+#endif
+
+#endif /* !_RTEMS_CDEFS_H_ */
diff --git a/cpukit/libcsupport/include/rtems/error.h b/cpukit/libcsupport/include/rtems/error.h
new file mode 100644
index 0000000000..de6e1715db
--- /dev/null
+++ b/cpukit/libcsupport/include/rtems/error.h
@@ -0,0 +1,47 @@
+/*
+ * Defines and externs for rtems error reporting
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_ERROR_h
+#define __RTEMS_ERROR_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * rtems_error() and rtems_panic() support
+ */
+
+#define RTEMS_ERROR_ERRNO (1<<((sizeof(int) * 8) - 2)) /* hi bit; use 'errno' */
+#define RTEMS_ERROR_PANIC (RTEMS_ERROR_ERRNO / 2) /* err fatal; no return */
+#define RTEMS_ERROR_ABORT (RTEMS_ERROR_ERRNO / 4) /* err is fatal; panic */
+
+#define RTEMS_ERROR_MASK (RTEMS_ERROR_ERRNO | RTEMS_ERROR_ABORT | \
+ RTEMS_ERROR_PANIC) /* all */
+
+const char *rtems_status_text(rtems_status_code);
+int rtems_error(int error_code, const char *printf_format, ...);
+#ifdef __GNUC__
+void rtems_panic(const char *printf_format, ...);
+/*
+ * We should be able to use this attribute but gcc complains that
+ * rtems_panic does in fact return. :(
+ *
+ * __attribute__ ((__noreturn__));
+ */
+#else
+void rtems_panic(const char *printf_format, ...);
+#endif
+
+extern int rtems_panic_in_progress;
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
+/* end of include file */
diff --git a/cpukit/libcsupport/include/rtems/libcsupport.h b/cpukit/libcsupport/include/rtems/libcsupport.h
new file mode 100644
index 0000000000..8b2223ae9d
--- /dev/null
+++ b/cpukit/libcsupport/include/rtems/libcsupport.h
@@ -0,0 +1,43 @@
+/* libcsupport.h
+ *
+ * This include file contains the information regarding the
+ * RTEMS specific support for the standard C library.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __LIBC_SUPPORT_h
+#define __LIBC_SUPPORT_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+
+void RTEMS_Malloc_Initialize(
+ void *start,
+ size_t length,
+ size_t sbrk_amount
+);
+
+extern void malloc_dump(void);
+extern void malloc_walk(size_t source, size_t printf_enabled);
+extern void libc_init(int reentrant);
+extern int host_errno(void);
+extern void fix_syscall_errno(void);
+extern size_t malloc_free_space();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/libcsupport/include/rtems/libio.h b/cpukit/libcsupport/include/rtems/libio.h
new file mode 100644
index 0000000000..4819be4868
--- /dev/null
+++ b/cpukit/libcsupport/include/rtems/libio.h
@@ -0,0 +1,633 @@
+/*
+ * System call and file system interface definition
+ *
+ * General purpose communication channel for RTEMS to allow UNIX/POSIX
+ * system call behavior under RTEMS. Initially this supported only
+ * IO to devices but has since been enhanced to support networking
+ * and support for mounted file systems.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef _RTEMS_LIBIO_H
+#define _RTEMS_LIBIO_H
+
+#include <rtems.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+
+/*
+ * Define data types which must be constructed using forward references.
+ */
+
+#include <rtems/fs.h>
+
+/*
+ * Valid RTEMS file types.
+ */
+
+#define RTEMS_FILESYSTEM_DIRECTORY 1
+#define RTEMS_FILESYSTEM_DEVICE 2
+#define RTEMS_FILESYSTEM_HARD_LINK 3
+#define RTEMS_FILESYSTEM_SYM_LINK 4
+#define RTEMS_FILESYSTEM_MEMORY_FILE 5
+typedef int rtems_filesystem_node_types_t;
+
+/*
+ * File Handler Operations Table
+ */
+
+typedef int (*rtems_filesystem_open_t)(
+ rtems_libio_t *iop,
+ const char *pathname,
+ uint32_t flag,
+ uint32_t mode
+);
+
+typedef int (*rtems_filesystem_close_t)(
+ rtems_libio_t *iop
+);
+
+typedef ssize_t (*rtems_filesystem_read_t)(
+ rtems_libio_t *iop,
+ void *buffer,
+ uint32_t count
+);
+
+typedef ssize_t (*rtems_filesystem_write_t)(
+ rtems_libio_t *iop,
+ const void *buffer,
+ uint32_t count
+);
+
+typedef int (*rtems_filesystem_ioctl_t)(
+ rtems_libio_t *iop,
+ uint32_t command,
+ void *buffer
+);
+
+typedef int (*rtems_filesystem_lseek_t)(
+ rtems_libio_t *iop,
+ off_t length,
+ int whence
+);
+
+typedef int (*rtems_filesystem_fstat_t)(
+ rtems_filesystem_location_info_t *loc,
+ struct stat *buf
+);
+
+typedef int (*rtems_filesystem_fchmod_t)(
+ rtems_filesystem_location_info_t *loc,
+ mode_t mode
+);
+
+typedef int (*rtems_filesystem_ftruncate_t)(
+ rtems_libio_t *iop,
+ off_t length
+);
+
+typedef int (*rtems_filesystem_fpathconf_t)(
+ rtems_libio_t *iop,
+ int name
+);
+
+typedef int (*rtems_filesystem_fsync_t)(
+ rtems_libio_t *iop
+);
+
+typedef int (*rtems_filesystem_fdatasync_t)(
+ rtems_libio_t *iop
+);
+
+typedef int (*rtems_filesystem_fcntl_t)(
+ int cmd,
+ rtems_libio_t *iop
+);
+
+typedef int (*rtems_filesystem_rmnod_t)(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+struct _rtems_filesystem_file_handlers_r {
+ rtems_filesystem_open_t open_h;
+ rtems_filesystem_close_t close_h;
+ rtems_filesystem_read_t read_h;
+ rtems_filesystem_write_t write_h;
+ rtems_filesystem_ioctl_t ioctl_h;
+ rtems_filesystem_lseek_t lseek_h;
+ rtems_filesystem_fstat_t fstat_h;
+ rtems_filesystem_fchmod_t fchmod_h;
+ rtems_filesystem_ftruncate_t ftruncate_h;
+ rtems_filesystem_fpathconf_t fpathconf_h;
+ rtems_filesystem_fsync_t fsync_h;
+ rtems_filesystem_fdatasync_t fdatasync_h;
+ rtems_filesystem_fcntl_t fcntl_h;
+ rtems_filesystem_rmnod_t rmnod_h;
+};
+
+/*
+ * File System Operations Table
+ */
+
+/*
+ * XXX
+ * This routine does not allocate any space and rtems_filesystem_freenode_t
+ * is not called by the generic after calling this routine.
+ * ie. node_access does not have to contain valid data when the
+ * routine returns.
+ */
+
+typedef int (*rtems_filesystem_mknod_t)(
+ const char *path, /* IN */
+ mode_t mode, /* IN */
+ dev_t dev, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+);
+
+/*
+ * rtems_filesystem_freenode_t must be called by the generic after
+ * calling this routine
+ */
+
+typedef int (*rtems_filesystem_evalpath_t)(
+ const char *pathname, /* IN */
+ int flags, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+);
+
+typedef int (*rtems_filesystem_evalmake_t)(
+ const char *path, /* IN */
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ const char **name /* OUT */
+);
+
+typedef int (*rtems_filesystem_link_t)(
+ rtems_filesystem_location_info_t *to_loc, /* IN */
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ const char *name /* IN */
+);
+
+typedef int (*rtems_filesystem_unlink_t)(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+typedef int (*rtems_filesystem_chown_t)(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ uid_t owner, /* IN */
+ gid_t group /* IN */
+);
+
+typedef int (*rtems_filesystem_freenode_t)(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+typedef int (* rtems_filesystem_mount_t ) (
+ rtems_filesystem_mount_table_entry_t *mt_entry /* in */
+);
+
+typedef int (* rtems_filesystem_fsmount_me_t )(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+typedef int (* rtems_filesystem_unmount_t ) (
+ rtems_filesystem_mount_table_entry_t *mt_entry /* in */
+);
+
+typedef int (* rtems_filesystem_fsunmount_me_t ) (
+ rtems_filesystem_mount_table_entry_t *mt_entry /* in */
+);
+
+typedef rtems_filesystem_node_types_t (* rtems_filesystem_node_type_t) (
+ rtems_filesystem_location_info_t *pathloc /* in */
+);
+
+typedef int (* rtems_filesystem_utime_t)(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ time_t actime, /* IN */
+ time_t modtime /* IN */
+);
+
+typedef int (*rtems_filesystem_evaluate_link_t)(
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ int flags /* IN */
+);
+
+typedef int (*rtems_filesystem_symlink_t)(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ const char *link_name, /* IN */
+ const char *node_name
+);
+
+typedef int (*rtems_filesystem_readlink_t)(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ char *buf, /* OUT */
+ size_t bufsize
+);
+
+/*
+ * operations table that must be defined for every file system.
+ */
+
+/*
+ * File system types
+ */
+struct _rtems_filesystem_operations_table {
+ rtems_filesystem_evalpath_t evalpath_h;
+ rtems_filesystem_evalmake_t evalformake_h;
+ rtems_filesystem_link_t link_h;
+ rtems_filesystem_unlink_t unlink_h;
+ rtems_filesystem_node_type_t node_type_h;
+ rtems_filesystem_mknod_t mknod_h;
+ rtems_filesystem_chown_t chown_h;
+ rtems_filesystem_freenode_t freenod_h;
+ rtems_filesystem_mount_t mount_h;
+ rtems_filesystem_fsmount_me_t fsmount_me_h;
+ rtems_filesystem_unmount_t unmount_h;
+ rtems_filesystem_fsunmount_me_t fsunmount_me_h;
+ rtems_filesystem_utime_t utime_h;
+ rtems_filesystem_evaluate_link_t eval_link_h;
+ rtems_filesystem_symlink_t symlink_h;
+ rtems_filesystem_readlink_t readlink_h;
+};
+
+#if 0
+/* Now in exec/include/rtems/fs.h */
+
+/*
+ * Structure used to determine a location/filesystem in the tree.
+ */
+
+struct rtems_filesystem_location_info_tt
+{
+ void *node_access;
+ rtems_filesystem_file_handlers_r *handlers;
+ rtems_filesystem_operations_table *ops;
+ rtems_filesystem_mount_table_entry_t *mt_entry;
+};
+#endif
+
+/*
+ * Structure used to contain file system specific information which
+ * is required to support fpathconf().
+ */
+
+typedef struct {
+ int link_max;
+ int max_canon;
+ int max_input;
+ int name_max;
+ int path_max;
+ int pipe_buf;
+ int posix_async_io;
+ int posix_chown_restrictions;
+ int posix_no_trunc;
+ int posix_prio_io;
+ int posix_sync_io;
+ int posix_vdisable;
+} rtems_filesystem_limits_and_options_t;
+
+/*
+ * Structure for a mount table entry.
+ */
+
+struct rtems_filesystem_mount_table_entry_tt {
+ Chain_Node Node;
+ rtems_filesystem_location_info_t mt_point_node;
+ rtems_filesystem_location_info_t mt_fs_root;
+ int options;
+ void *fs_info;
+
+ rtems_filesystem_limits_and_options_t pathconf_limits_and_options;
+
+ /*
+ * When someone adds a mounted filesystem on a real device,
+ * this will need to be used.
+ *
+ * The best option long term for this is probably an open file descriptor.
+ */
+ char *dev;
+};
+
+/*
+ * Valid RTEMS file systems options
+ */
+
+typedef enum
+{
+ RTEMS_FILESYSTEM_READ_ONLY,
+ RTEMS_FILESYSTEM_READ_WRITE,
+ RTEMS_FILESYSTEM_BAD_OPTIONS
+} rtems_filesystem_options_t;
+
+
+/*
+ * An open file data structure, indexed by 'fd'
+ * TODO:
+ * should really have a separate per/file data structure that this
+ * points to (eg: size, offset, driver, pathname should be in that)
+ */
+
+struct rtems_libio_tt {
+ rtems_driver_name_t *driver;
+ off_t size; /* size of file */
+ off_t offset; /* current offset into file */
+ uint32_t flags;
+ rtems_filesystem_location_info_t pathinfo;
+ Objects_Id sem;
+ uint32_t data0; /* private to "driver" */
+ void *data1; /* ... */
+ void *file_info; /* used by file handlers */
+ rtems_filesystem_file_handlers_r *handlers; /* type specific handlers */
+};
+
+/*
+ * param block for read/write
+ * Note: it must include 'offset' instead of using iop's offset since
+ * we can have multiple outstanding i/o's on a device.
+ */
+
+typedef struct {
+ rtems_libio_t *iop;
+ off_t offset;
+ uint8_t *buffer;
+ uint32_t count;
+ uint32_t flags;
+ uint32_t bytes_moved;
+} rtems_libio_rw_args_t;
+
+/*
+ * param block for open/close
+ */
+
+typedef struct {
+ rtems_libio_t *iop;
+ uint32_t flags;
+ uint32_t mode;
+} rtems_libio_open_close_args_t;
+
+/*
+ * param block for ioctl
+ */
+
+typedef struct {
+ rtems_libio_t *iop;
+ uint32_t command;
+ void *buffer;
+ uint32_t ioctl_return;
+} rtems_libio_ioctl_args_t;
+
+/*
+ * Values for 'flag'
+ */
+
+#define LIBIO_FLAGS_NO_DELAY 0x0001 /* return immediately if no data */
+#define LIBIO_FLAGS_READ 0x0002 /* reading */
+#define LIBIO_FLAGS_WRITE 0x0004 /* writing */
+#define LIBIO_FLAGS_OPEN 0x0100 /* device is open */
+#define LIBIO_FLAGS_APPEND 0x0200 /* all writes append */
+#define LIBIO_FLAGS_CREATE 0x0400 /* create file */
+#define LIBIO_FLAGS_CLOSE_ON_EXEC 0x0800 /* close on process exec() */
+#define LIBIO_FLAGS_READ_WRITE (LIBIO_FLAGS_READ | LIBIO_FLAGS_WRITE)
+
+void rtems_libio_init(void);
+
+/*
+ * External I/O handlers
+ */
+
+typedef int (*rtems_libio_open_t)(
+ const char *pathname,
+ uint32_t flag,
+ uint32_t mode
+);
+
+typedef int (*rtems_libio_close_t)(
+ int fd
+);
+
+typedef int (*rtems_libio_read_t)(
+ int fd,
+ void *buffer,
+ uint32_t count
+);
+
+typedef int (*rtems_libio_write_t)(
+ int fd,
+ const void *buffer,
+ uint32_t count
+);
+
+typedef int (*rtems_libio_ioctl_t)(
+ int fd,
+ uint32_t command,
+ void *buffer
+);
+
+typedef int (*rtems_libio_lseek_t)(
+ int fd,
+ off_t offset,
+ int whence
+);
+
+/*
+ * The following macros are used to build up the permissions sets
+ * used to check permissions. These are similar in style to the
+ * mode_t bits and should stay compatible with them.
+ */
+
+#define RTEMS_LIBIO_PERMS_READ S_IROTH
+#define RTEMS_LIBIO_PERMS_WRITE S_IWOTH
+#define RTEMS_LIBIO_PERMS_RDWR (S_IROTH|S_IWOTH)
+#define RTEMS_LIBIO_PERMS_EXEC S_IXOTH
+#define RTEMS_LIBIO_PERMS_SEARCH RTEMS_LIBIO_PERMS_EXEC
+#define RTEMS_LIBIO_PERMS_RWX S_IRWXO
+
+/*
+ * Macros
+ */
+
+#if 0
+#define rtems_filesystem_make_dev_t( _major, _minor ) \
+ ((((dev_t)(_major)) << 32) | (dev_t)(_minor))
+
+#define rtems_filesystem_dev_major_t( _dev ) \
+ (rtems_device_major_number) ((_dev) >> 32)
+
+#define rtems_filesystem_dev_minor_t( _dev ) \
+ (rtems_device_minor_number) ((_dev) & 0xFFFFFFFF)
+#else
+
+#include <unistd.h>
+
+union __rtems_dev_t {
+ dev_t device;
+ struct {
+ rtems_device_major_number major;
+ rtems_device_minor_number minor;
+ } __overlay;
+};
+
+static inline dev_t rtems_filesystem_make_dev_t(
+ rtems_device_major_number _major,
+ rtems_device_minor_number _minor
+)
+{
+ union __rtems_dev_t temp;
+
+ temp.__overlay.major = _major;
+ temp.__overlay.minor = _minor;
+ return temp.device;
+}
+
+static inline rtems_device_major_number rtems_filesystem_dev_major_t(
+ dev_t device
+)
+{
+ union __rtems_dev_t temp;
+
+ temp.device = device;
+ return temp.__overlay.major;
+}
+
+
+static inline rtems_device_minor_number rtems_filesystem_dev_minor_t(
+ dev_t device
+)
+{
+ union __rtems_dev_t temp;
+
+ temp.device = device;
+ return temp.__overlay.minor;
+}
+
+#endif
+
+#define rtems_filesystem_split_dev_t( _dev, _major, _minor ) \
+ do { \
+ (_major) = rtems_filesystem_dev_major_t ( _dev ); \
+ (_minor) = rtems_filesystem_dev_minor_t( _dev ); \
+ } while(0)
+
+/*
+ * Verifies that the permission flag is valid.
+ */
+#define rtems_libio_is_valid_perms( _perm ) \
+ (~ ((~RTEMS_LIBIO_PERMS_RWX) & _perm ))
+
+
+/*
+ * Prototypes for filesystem
+ */
+
+void rtems_filesystem_initialize( void );
+
+
+/*
+ * Callbacks from TERMIOS routines to device-dependent code
+ */
+
+#include <termios.h>
+
+typedef struct rtems_termios_callbacks {
+ int (*firstOpen)(int major, int minor, void *arg);
+ int (*lastClose)(int major, int minor, void *arg);
+ int (*pollRead)(int minor);
+ int (*write)(int minor, const char *buf, int len);
+ int (*setAttributes)(int minor, const struct termios *t);
+ int (*stopRemoteTx)(int minor);
+ int (*startRemoteTx)(int minor);
+ int outputUsesInterrupts;
+} rtems_termios_callbacks;
+
+/*
+ * Device-independent TERMIOS routines
+ */
+
+void rtems_termios_initialize (void);
+
+/*
+ * CCJ: Change before opening a tty. Newer code from Eric is coming
+ * so extra work to handle an open tty is not worth it. If the tty
+ * is open, close then open it again.
+ */
+rtems_status_code rtems_termios_bufsize (
+ int cbufsize, /* cooked buffer size */
+ int raw_input, /* raw input buffer size */
+ int raw_output /* raw output buffer size */
+);
+
+rtems_status_code rtems_termios_open (
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg,
+ const rtems_termios_callbacks *callbacks
+);
+
+rtems_status_code rtems_termios_close(
+ void *arg
+);
+
+rtems_status_code rtems_termios_read(
+ void *arg
+);
+
+rtems_status_code rtems_termios_write(
+ void *arg
+);
+
+rtems_status_code rtems_termios_ioctl(
+ void *arg
+);
+
+int rtems_termios_enqueue_raw_characters(
+ void *ttyp,
+ char *buf,
+ int len
+);
+
+int rtems_termios_dequeue_characters(
+ void *ttyp,
+ int len
+);
+
+void rtems_termios_reserve_resources(
+ rtems_configuration_table *configuration,
+ uint32_t number_of_devices
+);
+
+int unmount(
+ const char *mount_path
+);
+
+int mount(
+ rtems_filesystem_mount_table_entry_t **mt_entry,
+ rtems_filesystem_operations_table *fs_ops,
+ rtems_filesystem_options_t fsoptions,
+ char *device,
+ char *mount_point
+);
+
+/*
+ * Boot Time Mount Table Structure
+ */
+
+typedef struct {
+ rtems_filesystem_operations_table *fs_ops;
+ rtems_filesystem_options_t fsoptions;
+ char *device;
+ char *mount_point;
+} rtems_filesystem_mount_table_t;
+
+extern rtems_filesystem_mount_table_t *rtems_filesystem_mount_table;
+extern int rtems_filesystem_mount_table_size;
+
+#endif /* _RTEMS_LIBIO_H */
diff --git a/cpukit/libcsupport/include/rtems/libio_.h b/cpukit/libcsupport/include/rtems/libio_.h
new file mode 100644
index 0000000000..3662202e2e
--- /dev/null
+++ b/cpukit/libcsupport/include/rtems/libio_.h
@@ -0,0 +1,254 @@
+/*
+ * Libio Internal Information
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_LIBIO_INTERNAL__h
+#define __RTEMS_LIBIO_INTERNAL__h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems.h>
+#include <rtems/libio.h> /* include before standard IO */
+
+#include <sys/types.h>
+
+#include <errno.h>
+
+/*
+ * Semaphore to protect the io table
+ */
+
+#define RTEMS_LIBIO_SEM rtems_build_name('L', 'B', 'I', 'O')
+#define RTEMS_LIBIO_IOP_SEM(n) rtems_build_name('L', 'B', 'I', n)
+
+extern rtems_id rtems_libio_semaphore;
+extern rtems_filesystem_file_handlers_r rtems_filesystem_null_handlers;
+
+/*
+ * File descriptor Table Information
+ */
+
+extern uint32_t rtems_libio_number_iops;
+extern rtems_libio_t *rtems_libio_iops;
+extern rtems_libio_t *rtems_libio_last_iop;
+extern rtems_libio_t *rtems_libio_iop_freelist;
+
+/*
+ * rtems_libio_iop
+ *
+ * Macro to return the file descriptor pointer.
+ */
+
+#define rtems_libio_iop(_fd) \
+ ((((uint32_t )(_fd)) < rtems_libio_number_iops) ? \
+ &rtems_libio_iops[_fd] : 0)
+
+/*
+ * rtems_libio_iop_to_descriptor
+ *
+ * Macro to convert an internal file descriptor pointer (iop) into
+ * the integer file descriptor used by the "section 2" system calls.
+ */
+
+#define rtems_libio_iop_to_descriptor(_iop) \
+ ((!(_iop)) ? -1 : (_iop - rtems_libio_iops))
+
+/*
+ * rtems_libio_check_is_open
+ *
+ * Macro to check if a file descriptor is actually open.
+ */
+
+#define rtems_libio_check_is_open(_iop) \
+ do { \
+ if (((_iop)->flags & LIBIO_FLAGS_OPEN) == 0) { \
+ errno = EBADF; \
+ return -1; \
+ } \
+ } while (0)
+
+/*
+ * rtems_libio_check_fd
+ *
+ * Macro to check if a file descriptor number is valid.
+ */
+
+#define rtems_libio_check_fd(_fd) \
+ do { \
+ if ((uint32_t ) (_fd) >= rtems_libio_number_iops) { \
+ errno = EBADF; \
+ return -1; \
+ } \
+ } while (0)
+
+/*
+ * rtems_libio_check_buffer
+ *
+ * Macro to check if a buffer pointer is valid.
+ */
+
+#define rtems_libio_check_buffer(_buffer) \
+ do { \
+ if ((_buffer) == 0) { \
+ errno = EINVAL; \
+ return -1; \
+ } \
+ } while (0)
+
+/*
+ * rtems_libio_check_count
+ *
+ * Macro to check if a count or length is valid.
+ */
+
+#define rtems_libio_check_count(_count) \
+ do { \
+ if ((_count) == 0) { \
+ return 0; \
+ } \
+ } while (0)
+
+/*
+ * rtems_libio_check_permissions
+ *
+ * Macro to check if a file descriptor is open for this operation.
+ */
+
+#define rtems_libio_check_permissions(_iop, _flag) \
+ do { \
+ if (((_iop)->flags & (_flag)) == 0) { \
+ rtems_set_errno_and_return_minus_one( EINVAL ); \
+ return -1; \
+ } \
+ } while (0)
+
+/*
+ * rtems_filesystem_freenode
+ *
+ * Macro to free a node.
+ */
+
+#define rtems_filesystem_freenode( _node ) \
+ do { \
+ if ( (_node)->ops )\
+ if ( (_node)->ops->freenod_h ) \
+ (*(_node)->ops->freenod_h)( (_node) ); \
+ } while (0)
+
+/*
+ * rtems_filesystem_is_separator
+ *
+ * Macro to determine if a character is a path name separator.
+ *
+ * NOTE: This macro handles MS-DOS and UNIX style names.
+ */
+
+#define rtems_filesystem_is_separator( _ch ) \
+ ( ((_ch) == '/') || ((_ch) == '\\') || ((_ch) == '\0'))
+
+/*
+ * rtems_filesystem_get_start_loc
+ *
+ * Macro to determine if path is absolute or relative.
+ */
+
+#define rtems_filesystem_get_start_loc( _path, _index, _loc ) \
+ do { \
+ if ( rtems_filesystem_is_separator( (_path)[ 0 ] ) ) { \
+ *(_loc) = rtems_filesystem_root; \
+ *(_index) = 1; \
+ } else { \
+ *(_loc) = rtems_filesystem_current; \
+ *(_index) = 0; \
+ } \
+ } while (0)
+
+#define rtems_filesystem_get_sym_start_loc( _path, _index, _loc ) \
+ do { \
+ if ( rtems_filesystem_is_separator( (_path)[ 0 ] ) ) { \
+ *(_loc) = rtems_filesystem_root; \
+ *(_index) = 1; \
+ } else { \
+ *(_index) = 0; \
+ } \
+ } while (0)
+
+
+/*
+ * External structures
+ */
+#include <rtems/userenv.h>
+
+extern rtems_user_env_t * rtems_current_user_env;
+extern rtems_user_env_t rtems_global_user_env;
+
+/*
+ * Instantiate a private copy of the per user information for the calling task.
+ */
+
+rtems_status_code rtems_libio_set_private_env(void);
+rtems_status_code rtems_libio_share_private_env(rtems_id task_id) ;
+
+/*
+ * File Descriptor Routine Prototypes
+ */
+
+rtems_libio_t *rtems_libio_allocate(void);
+
+uint32_t rtems_libio_fcntl_flags(
+ uint32_t fcntl_flags
+);
+
+uint32_t rtems_libio_to_fcntl_flags(
+ uint32_t flags
+);
+
+void rtems_libio_free(
+ rtems_libio_t *iop
+);
+
+int rtems_libio_is_open_files_in_fs(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+int rtems_libio_is_file_open(
+ void *node_access
+);
+
+/*
+ * File System Routine Prototypes
+ */
+
+int rtems_filesystem_evaluate_path(
+ const char *pathname,
+ int flags,
+ rtems_filesystem_location_info_t *pathloc,
+ int follow_link
+);
+
+int rtems_filesystem_evaluate_parent(
+ int flags,
+ rtems_filesystem_location_info_t *pathloc
+);
+
+void rtems_filesystem_initialize();
+
+int init_fs_mount_table();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/libcsupport/include/rtems/termiostypes.h b/cpukit/libcsupport/include/rtems/termiostypes.h
new file mode 100644
index 0000000000..92f8c97b1c
--- /dev/null
+++ b/cpukit/libcsupport/include/rtems/termiostypes.h
@@ -0,0 +1,177 @@
+/*
+ * RTEMS termios device support internal data structures
+ *
+ * COPYRIGHT (c) 1989-2000.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef TERMIOSTYPES_H
+#define TERMIOSTYPES_H
+
+#include <rtems.h>
+#include <rtems/libio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Wakeup callback data structure
+ */
+struct ttywakeup {
+ void (*sw_pfn)(struct termios *tty, void *arg);
+ void *sw_arg;
+};
+
+/*
+ * Variables associated with the character buffer
+ */
+struct rtems_termios_rawbuf {
+ char *theBuf;
+ volatile unsigned int Head;
+ volatile unsigned int Tail;
+ volatile unsigned int Size;
+ rtems_id Semaphore;
+};
+/*
+ * Variables associated with each termios instance.
+ * One structure for each hardware I/O device.
+ */
+struct rtems_termios_tty {
+ /*
+ * Linked-list of active TERMIOS devices
+ */
+ struct rtems_termios_tty *forw;
+ struct rtems_termios_tty *back;
+
+ /*
+ * How many times has this device been opened
+ */
+ int refcount;
+
+ /*
+ * This device
+ */
+ rtems_device_major_number major;
+ rtems_device_major_number minor;
+
+ /*
+ * Mutual-exclusion semaphores
+ */
+ rtems_id isem;
+ rtems_id osem;
+
+ /*
+ * The canonical (cooked) character buffer
+ */
+ char *cbuf;
+ int ccount;
+ int cindex;
+
+ /*
+ * Keep track of cursor (printhead) position
+ */
+ int column;
+ int read_start_column;
+
+ /*
+ * The ioctl settings
+ */
+ struct termios termios;
+ rtems_interval vtimeTicks;
+
+ /*
+ * Raw input character buffer
+ */
+ struct rtems_termios_rawbuf rawInBuf;
+ uint32_t rawInBufSemaphoreOptions;
+ rtems_interval rawInBufSemaphoreTimeout;
+ rtems_interval rawInBufSemaphoreFirstTimeout;
+ unsigned int rawInBufDropped; /* Statistics */
+
+ /*
+ * Raw output character buffer
+ */
+ struct rtems_termios_rawbuf rawOutBuf;
+ int t_dqlen; /* count of characters dequeued from device */
+ enum {rob_idle, rob_busy, rob_wait } rawOutBufState;
+
+ /*
+ * Callbacks to device-specific routines
+ */
+ rtems_termios_callbacks device;
+ volatile unsigned int flow_ctrl;
+ unsigned int lowwater,highwater;
+
+ /*
+ * I/O task IDs (for task-driven drivers)
+ */
+ rtems_id rxTaskId;
+ rtems_id txTaskId;
+ /*
+ * line discipline related stuff
+ */
+ int t_line; /* id of line discipline */
+ void *t_sc; /* hook for discipline-specific data structure */
+ /*
+ * Wakeup callback variables
+ */
+ struct ttywakeup tty_snd;
+ struct ttywakeup tty_rcv;
+ int tty_rcvwakeup;
+};
+
+struct linesw {
+ int (*l_open) (struct rtems_termios_tty *tp);
+ int (*l_close)(struct rtems_termios_tty *tp);
+ int (*l_read )(struct rtems_termios_tty *tp,rtems_libio_rw_args_t *args);
+ int (*l_write)(struct rtems_termios_tty *tp,rtems_libio_rw_args_t *args);
+ int (*l_rint )(int c,struct rtems_termios_tty *tp);
+ int (*l_start)(struct rtems_termios_tty *tp);
+ int (*l_ioctl)(struct rtems_termios_tty *tp,rtems_libio_ioctl_args_t *args);
+ int (*l_modem)(struct rtems_termios_tty *tp,int flags);
+};
+
+/*
+ * FIXME: this should move to libio.h!
+ * values for rtems_termios_callbacks.outputUsesInterrupts
+ */
+#define TERMIOS_POLLED 0
+#define TERMIOS_IRQ_DRIVEN 1
+#define TERMIOS_TASK_DRIVEN 2
+
+
+/*
+ * FIXME: this should move to termios.h!
+ */
+void rtems_termios_rxirq_occured(struct rtems_termios_tty *tty);
+/*
+ * FIXME: this should move to termios.h!
+ * put a string to output ring buffer
+ */
+void rtems_termios_puts (const char *buf,
+ int len,
+ struct rtems_termios_tty *tty);
+/*
+ * global hooks for line disciplines
+ */
+extern struct linesw linesw[];
+extern int nlinesw;
+
+#define TTYDISC 0 /* termios tty line discipline */
+#define TABLDISC 3 /* tablet discipline */
+#define SLIPDISC 4 /* serial IP discipline */
+#define PPPDISC 5 /* PPP discipline */
+#define MAXLDISC 8
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TERMIOSTYPES_H */
diff --git a/cpukit/libcsupport/include/spurious.h b/cpukit/libcsupport/include/spurious.h
new file mode 100644
index 0000000000..729245fb95
--- /dev/null
+++ b/cpukit/libcsupport/include/spurious.h
@@ -0,0 +1,38 @@
+/* spurious.h
+ *
+ * This file describes the Spurious Interrupt Driver for all boards.
+ *
+ * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __SPURIOUS_h
+#define __SPURIOUS_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SPURIOUS_DRIVER_TABLE_ENTRY \
+ { Spurious_Initialize, NULL, NULL, NULL, NULL, NULL }
+
+rtems_device_driver Spurious_Initialize(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *,
+ rtems_id,
+ uint32_t *
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/libcsupport/include/stdint.h b/cpukit/libcsupport/include/stdint.h
new file mode 100644
index 0000000000..1c2652a5a0
--- /dev/null
+++ b/cpukit/libcsupport/include/stdint.h
@@ -0,0 +1,35 @@
+/*
+ * stdint.h
+ *
+ * ISO C99 integer types
+ *
+ * $Id$
+ */
+
+#ifndef __STDINT_H
+#define __STDINT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/types.h>
+
+/*
+ * map RTEMS internal types onto C99 types
+ */
+typedef signed8 int8_t;
+typedef signed16 int16_t;
+typedef signed32 int32_t;
+typedef signed64 int64_t;
+
+typedef unsigned8 uint8_t;
+typedef unsigned16 uint16_t;
+typedef unsigned32 uint32_t;
+typedef unsigned64 uint64_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/libcsupport/include/sys/cdefs.h b/cpukit/libcsupport/include/sys/cdefs.h
new file mode 100644
index 0000000000..d089dc5894
--- /dev/null
+++ b/cpukit/libcsupport/include/sys/cdefs.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Berkeley Software Design, Inc.
+ *
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)cdefs.h 8.8 (Berkeley) 1/9/95
+ * $Id$
+ */
+
+#ifndef _SYS_CDEFS_H_
+#define _SYS_CDEFS_H_
+
+#if defined(__cplusplus)
+#define __BEGIN_DECLS extern "C" {
+#define __END_DECLS };
+#else
+#define __BEGIN_DECLS
+#define __END_DECLS
+#endif
+
+/*
+ * The __CONCAT macro is used to concatenate parts of symbol names, e.g.
+ * with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo.
+ * The __CONCAT macro is a bit tricky -- make sure you don't put spaces
+ * in between its arguments. __CONCAT can also concatenate double-quoted
+ * strings produced by the __STRING macro, but this only works with ANSI C.
+ *
+ * __XSTRING is like __STRING, but it expands any macros in its argument
+ * first. It is only available with ANSI C.
+ */
+#if defined(__STDC__) || defined(__cplusplus)
+#define __P(protos) protos /* full-blown ANSI C */
+#define __CONCAT1(x,y) x ## y
+#define __CONCAT(x,y) __CONCAT1(x,y)
+#define __STRING(x) #x /* stringify without expanding x */
+#define __XSTRING(x) __STRING(x) /* expand x, then stringify */
+
+#define __const const /* define reserved names to standard */
+#define __signed signed
+#define __volatile volatile
+#if defined(__cplusplus)
+#define __inline inline /* convert to C++ keyword */
+#else
+#ifndef __GNUC__
+#define __inline /* delete GCC keyword */
+#endif /* !__GNUC__ */
+#endif /* !__cplusplus */
+
+#else /* !(__STDC__ || __cplusplus) */
+#define __P(protos) () /* traditional C preprocessor */
+#define __CONCAT(x,y) x/**/y
+#define __STRING(x) "x"
+
+#ifndef __GNUC__
+#define __const /* delete pseudo-ANSI C keywords */
+#define __inline
+#define __signed
+#define __volatile
+/*
+ * In non-ANSI C environments, new programs will want ANSI-only C keywords
+ * deleted from the program and old programs will want them left alone.
+ * When using a compiler other than gcc, programs using the ANSI C keywords
+ * const, inline etc. as normal identifiers should define -DNO_ANSI_KEYWORDS.
+ * When using "gcc -traditional", we assume that this is the intent; if
+ * __GNUC__ is defined but __STDC__ is not, we leave the new keywords alone.
+ */
+#ifndef NO_ANSI_KEYWORDS
+#define const /* delete ANSI C keywords */
+#define inline
+#define signed
+#define volatile
+#endif /* !NO_ANSI_KEYWORDS */
+#endif /* !__GNUC__ */
+#endif /* !(__STDC__ || __cplusplus) */
+
+/*
+ * GCC1 and some versions of GCC2 declare dead (non-returning) and
+ * pure (no side effects) functions using "volatile" and "const";
+ * unfortunately, these then cause warnings under "-ansi -pedantic".
+ * GCC2.5 uses a new, peculiar __attribute__((attrs)) style. All of
+ * these work for GNU C++ (modulo a slight glitch in the C++ grammar
+ * in the distribution version of 2.5.5).
+ */
+#if __GNUC__ < 2
+#define __dead
+#define __dead2
+#define __pure
+#define __pure2
+#define __unused
+#define __attribute__(x)
+#endif
+#if __GNUC__ == 2 && __GNUC_MINOR__ < 5
+#define __dead __volatile
+#define __dead2
+#define __pure __const
+#define __pure2
+#define __unused
+#endif
+#if __GNUC__ == 2 && __GNUC_MINOR__ >= 5 && __GNUC_MINOR__ < 7
+#define __dead
+#define __dead2 __attribute__((__noreturn__))
+#define __pure
+#define __pure2 __attribute__((__const__))
+#define __unused
+#endif
+#if __GNUC__ == 2 && __GNUC_MINOR__ >= 7 || __GNUC__ >= 3
+#define __dead
+#define __dead2 __attribute__((__noreturn__))
+#define __pure
+#define __pure2 __attribute__((__const__))
+#define __unused __attribute__((__unused__))
+#endif
+
+#ifdef __GNUC__
+#ifdef __STDC__
+#define __weak_reference(sym,alias) \
+ __asm__(".stabs \"_" #alias "\",11,0,0,0"); \
+ __asm__(".stabs \"_" #sym "\",1,0,0,0")
+#define __warn_references(sym,msg) \
+ __asm__(".stabs \"" msg "\",30,0,0,0"); \
+ __asm__(".stabs \"_" #sym "\",1,0,0,0")
+#else
+#define __weak_reference(sym,alias) \
+ __asm__(".stabs \"_/**/alias\",11,0,0,0"); \
+ __asm__(".stabs \"_/**/sym\",1,0,0,0")
+#define __warn_references(sym,msg) \
+ __asm__(".stabs msg,30,0,0,0"); \
+ __asm__(".stabs \"_/**/sym\",1,0,0,0")
+#endif
+#endif
+
+#define __IDSTRING(name,string) \
+ static const char name[] __attribute__((__unused__)) = string
+
+#ifndef __RCSID
+#define __RCSID(s) __IDSTRING(rcsid,s)
+#endif
+
+#ifndef __RCSID_SOURCE
+#define __RCSID_SOURCE(s) __IDSTRING(rcsid_source,s)
+#endif
+
+#ifndef __COPYRIGHT
+#define __COPYRIGHT(s) __IDSTRING(copyright,s)
+#endif
+
+#endif /* !_SYS_CDEFS_H_ */
diff --git a/cpukit/libcsupport/include/sys/filio.h b/cpukit/libcsupport/include/sys/filio.h
new file mode 100644
index 0000000000..5a8b7e4bbb
--- /dev/null
+++ b/cpukit/libcsupport/include/sys/filio.h
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c) 1982, 1986, 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)filio.h 8.1 (Berkeley) 3/28/94
+ * $Id$
+ */
+
+#ifndef _SYS_FILIO_H_
+#define _SYS_FILIO_H_
+
+#include <sys/ioccom.h>
+
+/* RTEMS defines all of these in sys/ioccom.h */
+#if 0
+/* Generic file-descriptor ioctl's. */
+#define FIOCLEX _IO('f', 1) /* set close on exec on fd */
+#define FIONCLEX _IO('f', 2) /* remove close on exec */
+#define FIONREAD _IOR('f', 127, int) /* get # bytes to read */
+#define FIONBIO _IOW('f', 126, int) /* set/clear non-blocking i/o */
+#define FIOASYNC _IOW('f', 125, int) /* set/clear async i/o */
+#define FIOSETOWN _IOW('f', 124, int) /* set owner */
+#define FIOGETOWN _IOR('f', 123, int) /* get owner */
+#endif
+
+#endif /* !_SYS_FILIO_H_ */
diff --git a/cpukit/libcsupport/include/sys/ioccom.h b/cpukit/libcsupport/include/sys/ioccom.h
new file mode 100644
index 0000000000..4ebffd19cd
--- /dev/null
+++ b/cpukit/libcsupport/include/sys/ioccom.h
@@ -0,0 +1,100 @@
+/*-
+ * Copyright (c) 1982, 1986, 1990, 1993, 1994
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)ioccom.h 8.2 (Berkeley) 3/28/94
+ * $Id$
+ */
+
+#ifndef _SYS_IOCCOM_H_
+#define _SYS_IOCCOM_H_
+
+#include <sys/types.h>
+
+/*
+ * Ioctl's have the command encoded in the lower word, and the size of
+ * any in or out parameters in the upper word. The high 3 bits of the
+ * upper word are used to encode the in/out status of the parameter.
+ */
+#define IOCPARM_MASK 0x1fff /* parameter length, at most 13 bits */
+#define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
+#define IOCBASECMD(x) ((x) & ~(IOCPARM_MASK << 16))
+#define IOCGROUP(x) (((x) >> 8) & 0xff)
+
+#define IOCPARM_MAX PAGE_SIZE /* max size of ioctl, mult. of PAGE_SIZE */
+#define IOC_VOID 0x20000000 /* no parameters */
+#define IOC_OUT 0x40000000 /* copy out parameters */
+#define IOC_IN 0x80000000 /* copy in parameters */
+#define IOC_INOUT (IOC_IN|IOC_OUT)
+#define IOC_DIRMASK 0xe0000000 /* mask for IN/OUT/VOID */
+
+#define _IOC(inout,group,num,len) \
+ ((u_int32_t)inout | \
+ (u_int32_t) ((u_int32_t)((u_int32_t)len & IOCPARM_MASK) << 16) | \
+ (u_int32_t)((group) << 8) | \
+ (u_int32_t)(num))
+#define _IO(g,n) _IOC(IOC_VOID, (g), (n), 0)
+#define _IOR(g,n,t) _IOC(IOC_OUT, (g), (n), sizeof(t))
+#define _IOW(g,n,t) _IOC(IOC_IN, (g), (n), sizeof(t))
+/* this should be _IORW, but stdio got there first */
+#define _IOWR(g,n,t) _IOC(IOC_INOUT, (g), (n), sizeof(t))
+
+/*
+ * IOCTL values
+ */
+
+#define RTEMS_IO_GET_ATTRIBUTES 1
+#define RTEMS_IO_SET_ATTRIBUTES 2
+#define RTEMS_IO_TCDRAIN 3
+#define RTEMS_IO_RCVWAKEUP 4
+#define RTEMS_IO_SNDWAKEUP 5
+
+/* copied from libnetworking/sys/filio.h and commented out there */
+/* Generic file-descriptor ioctl's. */
+#define FIOCLEX _IO('f', 1) /* set close on exec on fd */
+#define FIONCLEX _IO('f', 2) /* remove close on exec */
+#define FIONREAD _IOR('f', 127, int) /* get # bytes to read */
+#define FIONBIO _IOW('f', 126, int) /* set/clear non-blocking i/o */
+#define FIOASYNC _IOW('f', 125, int) /* set/clear async i/o */
+#define FIOSETOWN _IOW('f', 124, int) /* set owner */
+#define FIOGETOWN _IOR('f', 123, int) /* get owner */
+
+#ifndef KERNEL
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+int ioctl __P((int, int, ...));
+__END_DECLS
+
+#endif /* !KERNEL */
+
+#endif /* !_SYS_IOCCOM_H_ */
diff --git a/cpukit/libcsupport/include/sys/ioctl.h b/cpukit/libcsupport/include/sys/ioctl.h
new file mode 100644
index 0000000000..e3a69a5a7f
--- /dev/null
+++ b/cpukit/libcsupport/include/sys/ioctl.h
@@ -0,0 +1,77 @@
+/*-
+ * Copyright (c) 1982, 1986, 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)ioctl.h 8.6 (Berkeley) 3/28/94
+ * $Id$
+ */
+
+#ifndef _SYS_IOCTL_H_
+#define _SYS_IOCTL_H_
+
+#include <sys/ttycom.h>
+
+/*
+ * Pun for SunOS prior to 3.2. SunOS 3.2 and later support TIOCGWINSZ
+ * and TIOCSWINSZ (yes, even 3.2-3.5, the fact that it wasn't documented
+ * notwithstanding).
+ */
+struct ttysize {
+ unsigned short ts_lines;
+ unsigned short ts_cols;
+ unsigned short ts_xxx;
+ unsigned short ts_yyy;
+};
+#define TIOCGSIZE TIOCGWINSZ
+#define TIOCSSIZE TIOCSWINSZ
+
+#include <sys/ioccom.h>
+
+#include <sys/filio.h>
+#include <sys/sockio.h>
+
+#endif /* !_SYS_IOCTL_H_ */
+
+/*
+ * Keep outside _SYS_IOCTL_H_
+ * Compatibility with old terminal driver
+ *
+ * Source level -> #define USE_OLD_TTY
+ * Kernel level -> options COMPAT_43 or COMPAT_SUNOS
+ */
+#if defined(USE_OLD_TTY) || defined(COMPAT_43) || defined(COMPAT_SUNOS)
+#include <sys/ioctl_compat.h>
+#endif
diff --git a/cpukit/libcsupport/include/sys/sockio.h b/cpukit/libcsupport/include/sys/sockio.h
new file mode 100644
index 0000000000..5e54baffe8
--- /dev/null
+++ b/cpukit/libcsupport/include/sys/sockio.h
@@ -0,0 +1,92 @@
+/*-
+ * Copyright (c) 1982, 1986, 1990, 1993, 1994
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)sockio.h 8.1 (Berkeley) 3/28/94
+ * $Id$
+ */
+
+#ifndef _SYS_SOCKIO_H_
+#define _SYS_SOCKIO_H_
+
+#include <sys/ioccom.h>
+
+/* Socket ioctl's. */
+#define SIOCSHIWAT _IOW('s', 0, int) /* set high watermark */
+#define SIOCGHIWAT _IOR('s', 1, int) /* get high watermark */
+#define SIOCSLOWAT _IOW('s', 2, int) /* set low watermark */
+#define SIOCGLOWAT _IOR('s', 3, int) /* get low watermark */
+#define SIOCATMARK _IOR('s', 7, int) /* at oob mark? */
+#define SIOCSPGRP _IOW('s', 8, int) /* set process group */
+#define SIOCGPGRP _IOR('s', 9, int) /* get process group */
+
+#define SIOCADDRT _IOW('r', 10, struct ortentry) /* add route */
+#define SIOCDELRT _IOW('r', 11, struct ortentry) /* delete route */
+#define SIOCGETVIFCNT _IOWR('r', 15, struct sioc_vif_req)/* get vif pkt cnt */
+#define SIOCGETSGCNT _IOWR('r', 16, struct sioc_sg_req) /* get s,g pkt cnt */
+
+#define SIOCSIFADDR _IOW('i', 12, struct ifreq) /* set ifnet address */
+#define OSIOCGIFADDR _IOWR('i', 13, struct ifreq) /* get ifnet address */
+#define SIOCGIFADDR _IOWR('i', 33, struct ifreq) /* get ifnet address */
+#define SIOCSIFDSTADDR _IOW('i', 14, struct ifreq) /* set p-p address */
+#define OSIOCGIFDSTADDR _IOWR('i', 15, struct ifreq) /* get p-p address */
+#define SIOCGIFDSTADDR _IOWR('i', 34, struct ifreq) /* get p-p address */
+#define SIOCSIFFLAGS _IOW('i', 16, struct ifreq) /* set ifnet flags */
+#define SIOCGIFFLAGS _IOWR('i', 17, struct ifreq) /* get ifnet flags */
+#define OSIOCGIFBRDADDR _IOWR('i', 18, struct ifreq) /* get broadcast addr */
+#define SIOCGIFBRDADDR _IOWR('i', 35, struct ifreq) /* get broadcast addr */
+#define SIOCSIFBRDADDR _IOW('i', 19, struct ifreq) /* set broadcast addr */
+#define OSIOCGIFCONF _IOWR('i', 20, struct ifconf) /* get ifnet list */
+#define SIOCGIFCONF _IOWR('i', 36, struct ifconf) /* get ifnet list */
+#define OSIOCGIFNETMASK _IOWR('i', 21, struct ifreq) /* get net addr mask */
+#define SIOCGIFNETMASK _IOWR('i', 37, struct ifreq) /* get net addr mask */
+#define SIOCSIFNETMASK _IOW('i', 22, struct ifreq) /* set net addr mask */
+#define SIOCGIFMETRIC _IOWR('i', 23, struct ifreq) /* get IF metric */
+#define SIOCSIFMETRIC _IOW('i', 24, struct ifreq) /* set IF metric */
+#define SIOCDIFADDR _IOW('i', 25, struct ifreq) /* delete IF addr */
+#define SIOCAIFADDR _IOW('i', 26, struct ifaliasreq)/* add/chg IF alias */
+
+#define SIOCADDMULTI _IOW('i', 49, struct ifreq) /* add m'cast addr */
+#define SIOCDELMULTI _IOW('i', 50, struct ifreq) /* del m'cast addr */
+#define SIOCGIFMTU _IOWR('i', 51, struct ifreq) /* get IF mtu */
+#define SIOCSIFMTU _IOW('i', 52, struct ifreq) /* set IF mtu */
+#define SIOCGIFPHYS _IOWR('i', 53, struct ifreq) /* get IF wire */
+#define SIOCSIFPHYS _IOW('i', 54, struct ifreq) /* set IF wire */
+#define SIOCSIFMEDIA _IOWR('i', 55, struct ifreq) /* set net media */
+#define SIOCGIFMEDIA _IOWR('i', 56, struct ifmediareq) /* get net media */
+
+/*
+ * RTEMS additions for setting/getting `tap' function on incoming packets.
+ */
+#define SIOCSIFTAP _IOW('i', 80, struct ifreq) /* set tap function */
+#define SIOCGIFTAP _IOW('i', 81, struct ifreq) /* get tap function */
+
+#endif /* !_SYS_SOCKIO_H_ */
diff --git a/cpukit/libcsupport/include/sys/termios.h b/cpukit/libcsupport/include/sys/termios.h
new file mode 100644
index 0000000000..f619c95709
--- /dev/null
+++ b/cpukit/libcsupport/include/sys/termios.h
@@ -0,0 +1,198 @@
+/*
+ * POSIX termios implementation for RTEMS console device driver.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef TERMIOS_H
+#define TERMIOS_H
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef unsigned char cc_t;
+typedef unsigned int speed_t;
+typedef unsigned int tcflag_t;
+
+#define NCCS 19
+struct termios {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[NCCS]; /* control characters */
+};
+
+/* c_cc characters */
+#define VINTR 0
+#define VQUIT 1
+#define VERASE 2
+#define VKILL 3
+#define VEOF 4
+#define VTIME 5
+#define VMIN 6
+#define VSWTC 7
+#define VSTART 8
+#define VSTOP 9
+#define VSUSP 10
+#define VEOL 11
+#define VREPRINT 12
+#define VDISCARD 13
+#define VWERASE 14
+#define VLNEXT 15
+#define VEOL2 16
+
+/* c_iflag bits */
+#define IGNBRK 0000001
+#define BRKINT 0000002
+#define IGNPAR 0000004
+#define PARMRK 0000010
+#define INPCK 0000020
+#define ISTRIP 0000040
+#define INLCR 0000100
+#define IGNCR 0000200
+#define ICRNL 0000400
+#define IUCLC 0001000
+#define IXON 0002000
+#define IXANY 0004000
+#define IXOFF 0010000
+#define IMAXBEL 0020000
+
+/* c_oflag bits */
+#define OPOST 0000001
+#define OLCUC 0000002
+#define ONLCR 0000004
+#define OCRNL 0000010
+#define ONOCR 0000020
+#define ONLRET 0000040
+#define OFILL 0000100
+#define OFDEL 0000200
+#define NLDLY 0000400
+#define NL0 0000000
+#define NL1 0000400
+#define CRDLY 0003000
+#define CR0 0000000
+#define CR1 0001000
+#define CR2 0002000
+#define CR3 0003000
+#define TABDLY 0014000
+#define TAB0 0000000
+#define TAB1 0004000
+#define TAB2 0010000
+#define TAB3 0014000
+#define XTABS 0014000
+#define BSDLY 0020000
+#define BS0 0000000
+#define BS1 0020000
+#define VTDLY 0040000
+#define VT0 0000000
+#define VT1 0040000
+#define FFDLY 0100000
+#define FF0 0000000
+#define FF1 0100000
+
+/* c_cflag bit meaning */
+#define CBAUD 0010017
+#define B0 0000000 /* hang up */
+#define B50 0000001
+#define B75 0000002
+#define B110 0000003
+#define B134 0000004
+#define B150 0000005
+#define B200 0000006
+#define B300 0000007
+#define B600 0000010
+#define B1200 0000011
+#define B1800 0000012
+#define B2400 0000013
+#define B4800 0000014
+#define B9600 0000015
+#define B19200 0000016
+#define B38400 0000017
+#define EXTA B19200
+#define EXTB B38400
+#define CSIZE 0000060
+#define CS5 0000000
+#define CS6 0000020
+#define CS7 0000040
+#define CS8 0000060
+#define CSTOPB 0000100
+#define CREAD 0000200
+#define PARENB 0000400
+#define PARODD 0001000
+#define HUPCL 0002000
+#define CLOCAL 0004000
+#define CBAUDEX 0010000
+#define B57600 0010001
+#define B115200 0010002
+#define B230400 0010003
+#define B460800 0010004
+#define CIBAUD 002003600000 /* input baud rate (not used) */
+#define CRTSCTS 020000000000 /* flow control */
+
+#define RTEMS_TERMIOS_NUMBER_BAUD_RATES 20
+
+/* c_lflag bits */
+#define ISIG 0000001
+#define ICANON 0000002
+#define XCASE 0000004
+#define ECHO 0000010
+#define ECHOE 0000020
+#define ECHOK 0000040
+#define ECHONL 0000100
+#define NOFLSH 0000200
+#define TOSTOP 0000400
+#define ECHOCTL 0001000
+#define ECHOPRT 0002000
+#define ECHOKE 0004000
+#define FLUSHO 0010000
+#define PENDIN 0040000
+#define IEXTEN 0100000
+
+/* tcflow() and TCXONC use these */
+#define TCOOFF 0
+#define TCOON 1
+#define TCIOFF 2
+#define TCION 3
+
+/* tcflush() and TCFLSH use these */
+#define TCIFLUSH 0
+#define TCOFLUSH 1
+#define TCIOFLUSH 2
+
+/* tcsetattr uses these */
+#define TCSANOW 0
+#define TCSADRAIN 1
+#define TCSAFLUSH 2
+
+int tcdrain(int);
+int tcflow(int, int);
+int tcflush(int, int);
+int tcgetattr(int, struct termios *);
+int tcsetattr(int, int, struct termios *);
+int tcdrain(int);
+pid_t tcgetprgrp(int);
+int tcsetprgrp(int, pid_t);
+int tcsendbreak(int, int);
+
+speed_t cfgetospeed(const struct termios *tp);
+int cfsetospeed(struct termios *tp, speed_t speed);
+speed_t cfgetispeed(const struct termios *tp);
+int cfsetispeed(struct termios *tp, speed_t speed);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TERMIOS_H */
diff --git a/cpukit/libcsupport/include/sys/ttycom.h b/cpukit/libcsupport/include/sys/ttycom.h
new file mode 100644
index 0000000000..f2e491bc50
--- /dev/null
+++ b/cpukit/libcsupport/include/sys/ttycom.h
@@ -0,0 +1,141 @@
+/*-
+ * Copyright (c) 1982, 1986, 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)ttycom.h 8.1 (Berkeley) 3/28/94
+ * $Id$
+ */
+
+#ifndef _SYS_TTYCOM_H_
+#define _SYS_TTYCOM_H_
+
+#include <sys/ioccom.h>
+
+/*
+ * Tty ioctl's except for those supported only for backwards compatibility
+ * with the old tty driver.
+ */
+
+/*
+ * Window/terminal size structure. This information is stored by the kernel
+ * in order to provide a consistent interface, but is not used by the kernel.
+ */
+struct winsize {
+ unsigned short ws_row; /* rows, in characters */
+ unsigned short ws_col; /* columns, in characters */
+ unsigned short ws_xpixel; /* horizontal size, pixels */
+ unsigned short ws_ypixel; /* vertical size, pixels */
+};
+
+#define TIOCMODG _IOR('t', 3, int) /* get modem control state */
+#define TIOCMODS _IOW('t', 4, int) /* set modem control state */
+#define TIOCM_LE 0001 /* line enable */
+#define TIOCM_DTR 0002 /* data terminal ready */
+#define TIOCM_RTS 0004 /* request to send */
+#define TIOCM_ST 0010 /* secondary transmit */
+#define TIOCM_SR 0020 /* secondary receive */
+#define TIOCM_CTS 0040 /* clear to send */
+#define TIOCM_CAR 0100 /* carrier detect */
+#define TIOCM_CD TIOCM_CAR
+#define TIOCM_RNG 0200 /* ring */
+#define TIOCM_RI TIOCM_RNG
+#define TIOCM_DSR 0400 /* data set ready */
+ /* 8-10 compat */
+#define TIOCEXCL _IO('t', 13) /* set exclusive use of tty */
+#define TIOCNXCL _IO('t', 14) /* reset exclusive use of tty */
+ /* 15 unused */
+#define TIOCFLUSH _IOW('t', 16, int) /* flush buffers */
+ /* 17-18 compat */
+#define TIOCGETA _IOR('t', 19, struct termios) /* get termios struct */
+#define TIOCSETA _IOW('t', 20, struct termios) /* set termios struct */
+#define TIOCSETAW _IOW('t', 21, struct termios) /* drain output, set */
+#define TIOCSETAF _IOW('t', 22, struct termios) /* drn out, fls in, set */
+#define TIOCGETD _IOR('t', 26, int) /* get line discipline */
+#define TIOCSETD _IOW('t', 27, int) /* set line discipline */
+ /* 127-124 compat */
+#define TIOCSBRK _IO('t', 123) /* set break bit */
+#define TIOCCBRK _IO('t', 122) /* clear break bit */
+#define TIOCSDTR _IO('t', 121) /* set data terminal ready */
+#define TIOCCDTR _IO('t', 120) /* clear data terminal ready */
+#define TIOCGPGRP _IOR('t', 119, int) /* get pgrp of tty */
+#define TIOCSPGRP _IOW('t', 118, int) /* set pgrp of tty */
+ /* 117-116 compat */
+#define TIOCOUTQ _IOR('t', 115, int) /* output queue size */
+#define TIOCSTI _IOW('t', 114, char) /* simulate terminal input */
+#define TIOCNOTTY _IO('t', 113) /* void tty association */
+#define TIOCPKT _IOW('t', 112, int) /* pty: set/clear packet mode */
+#define TIOCPKT_DATA 0x00 /* data packet */
+#define TIOCPKT_FLUSHREAD 0x01 /* flush packet */
+#define TIOCPKT_FLUSHWRITE 0x02 /* flush packet */
+#define TIOCPKT_STOP 0x04 /* stop output */
+#define TIOCPKT_START 0x08 /* start output */
+#define TIOCPKT_NOSTOP 0x10 /* no more ^S, ^Q */
+#define TIOCPKT_DOSTOP 0x20 /* now do ^S ^Q */
+#define TIOCPKT_IOCTL 0x40 /* state change of pty driver */
+#define TIOCSTOP _IO('t', 111) /* stop output, like ^S */
+#define TIOCSTART _IO('t', 110) /* start output, like ^Q */
+#define TIOCMSET _IOW('t', 109, int) /* set all modem bits */
+#define TIOCMBIS _IOW('t', 108, int) /* bis modem bits */
+#define TIOCMBIC _IOW('t', 107, int) /* bic modem bits */
+#define TIOCMGET _IOR('t', 106, int) /* get all modem bits */
+#define TIOCREMOTE _IOW('t', 105, int) /* remote input editing */
+#define TIOCGWINSZ _IOR('t', 104, struct winsize) /* get window size */
+#define TIOCSWINSZ _IOW('t', 103, struct winsize) /* set window size */
+#define TIOCUCNTL _IOW('t', 102, int) /* pty: set/clr usr cntl mode */
+#define TIOCSTAT _IO('t', 101) /* simulate ^T status message */
+#define UIOCCMD(n) _IO('u', n) /* usr cntl op "n" */
+#define TIOCCONS _IOW('t', 98, int) /* become virtual console */
+#define TIOCSCTTY _IO('t', 97) /* become controlling tty */
+#define TIOCEXT _IOW('t', 96, int) /* pty: external processing */
+#define TIOCSIG _IO('t', 95) /* pty: generate signal */
+#define TIOCDRAIN _IO('t', 94) /* wait till output drained */
+#define TIOCMSDTRWAIT _IOW('t', 91, int) /* modem: set wait on close */
+#define TIOCMGDTRWAIT _IOR('t', 90, int) /* modem: get wait on close */
+#define TIOCTIMESTAMP _IOR('t', 89, struct timeval) /* enable/get timestamp
+ * of last input event */
+#define TIOCDCDTIMESTAMP _IOR('t', 88, struct timeval) /* enable/get timestamp
+ * of last DCd rise */
+#define TIOCSDRAINWAIT _IOW('t', 87, int) /* set ttywait timeout */
+#define TIOCGDRAINWAIT _IOR('t', 86, int) /* get ttywait timeout */
+#define TIOCDSIMICROCODE _IO('t', 85) /* download microcode to
+ * DSI Softmodem */
+
+#define TTYDISC 0 /* termios tty line discipline */
+#define TABLDISC 3 /* tablet discipline */
+#define SLIPDISC 4 /* serial IP discipline */
+#define PPPDISC 5 /* PPP discipline */
+
+#endif /* !_SYS_TTYCOM_H_ */
diff --git a/cpukit/libcsupport/include/sys/utsname.h b/cpukit/libcsupport/include/sys/utsname.h
new file mode 100644
index 0000000000..ebe2f52785
--- /dev/null
+++ b/cpukit/libcsupport/include/sys/utsname.h
@@ -0,0 +1,55 @@
+/* sys/utsname.h
+ *
+ * $Id$
+ */
+
+#ifndef __POSIX_SYS_UTSNAME_h
+#define __POSIX_SYS_UTSNAME_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/times.h>
+#include <sys/types.h>
+
+/*
+ * 4.4.1 Get System Name (Table 4-1), P1003.1b-1993, p. 90
+ *
+ * NOTE: The lengths of the strings in this structure are
+ * just long enough to reliably contain the RTEMS information.
+ * For example, the fields are not long enough to support
+ * Internet hostnames.
+ */
+
+struct utsname {
+ char sysname[ 32 ]; /* Name of this implementation of the operating system */
+ char nodename[ 32 ]; /* Name of this node within an implementation */
+ /* specified communication network */
+ char release[ 32 ]; /* Current release level of this implementation */
+ char version[ 32 ]; /* Current version level of this release */
+ char machine[ 32 ]; /* Name of the hardware type on which the system */
+ /* is running */
+};
+
+/*
+ * 4.4.1 Get System Name, P1003.1b-1993, p. 90
+ */
+
+int uname(
+ struct utsname *name
+);
+
+/*
+ * 4.5.2 Get Process Times, P1003.1b-1993, p. 92
+ */
+
+clock_t times(
+ struct tms *buffer
+);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* end of include file */
diff --git a/cpukit/libcsupport/include/timerdrv.h b/cpukit/libcsupport/include/timerdrv.h
new file mode 100644
index 0000000000..9b1772201e
--- /dev/null
+++ b/cpukit/libcsupport/include/timerdrv.h
@@ -0,0 +1,39 @@
+/* timerdrv.h
+ *
+ * This file describes the Timer Driver for all boards.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __TIMER_DRIVER_h
+#define __TIMER_DRIVER_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* functions */
+
+void Timer_initialize( void );
+
+uint32_t Read_timer( void );
+
+rtems_status_code Empty_function( void );
+
+void Set_find_average_overhead(
+ rtems_boolean find_flag
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/libcsupport/include/vmeintr.h b/cpukit/libcsupport/include/vmeintr.h
new file mode 100644
index 0000000000..95d53db263
--- /dev/null
+++ b/cpukit/libcsupport/include/vmeintr.h
@@ -0,0 +1,57 @@
+/*
+ * vmeintr.h
+ *
+ * This file is the specification for the VMEbus interface library
+ * which should be provided by all BSPs for VMEbus Single Board
+ * Computers but currently only a few do so.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __VME_INTERRUPT_h
+#define __VME_INTERRUPT_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This defines the mask which is used to determine which
+ * interrupt levels are affected by a call to this package.
+ * The LSB corresponds to VME interrupt 0 and the MSB
+ * to VME interrupt 7.
+ *
+ */
+
+typedef uint8_t VME_interrupt_Mask;
+
+/*
+ * VME_interrupt_Disable
+ *
+ */
+
+void VME_interrupt_Disable (
+ VME_interrupt_Mask mask /* IN */
+);
+
+/*
+ * VME_interrupt_Disable
+ *
+ */
+
+void VME_interrupt_Enable (
+ VME_interrupt_Mask mask /* IN */
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of include file */
diff --git a/cpukit/libcsupport/include/zilog/z8036.h b/cpukit/libcsupport/include/zilog/z8036.h
new file mode 100644
index 0000000000..b15725a978
--- /dev/null
+++ b/cpukit/libcsupport/include/zilog/z8036.h
@@ -0,0 +1,107 @@
+/* z8036.h
+ *
+ * This include file defines information related to a Zilog Z8036
+ * Counter/Timer/IO Chip. It is a memory mapped part.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * NOTE: This file shares as much as possible with the include
+ * file for the Z8536 via z8x36.h.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __Z8036_h
+#define __Z8036_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* macros */
+
+#define Z8036( ptr ) ((volatile struct z8036_map *)(ptr))
+
+#define Z8x36_STATE0 ( z8036 ) \
+ { /*char *garbage = *(Z8036(z8036))->???; */ }
+
+
+#define Z8x36_WRITE( z8036, reg, data ) \
+ (Z8036(z8036))->reg = (data)
+
+
+#define Z8x36_READ( z8036, reg, data ) \
+ (Z8036(z8036))->reg = (data)
+
+/* structures */
+
+struct z8036_map {
+/* MAIN CONTROL REGISTERS (0x00-0x07) */
+ uint8_t MASTER_INTR; /* Master Interrupt Ctl Reg */
+ uint8_t MASTER_CFG; /* Master Configuration Ctl Reg */
+ uint8_t PORTA_VECTOR; /* Port A - Interrupt Vector */
+ uint8_t PORTB_VECTOR; /* Port B - Interrupt Vector */
+ uint8_t CNT_TMR_VECTOR; /* Counter/Timer Interrupt Vector */
+ uint8_t PORTC_DATA_POLARITY; /* Port C - Data Path Polarity */
+ uint8_t PORTC_DIRECTION; /* Port C - Data Direction */
+ uint8_t PORTC_SPECIAL_IO_CTL; /* Port C - Special IO Control */
+/* MOST OFTEN ACCESSED REGISTERS (0x08 - 0x0f) */
+ uint8_t PORTA_CMD_STATUS; /* Port A - Command Status Reg */
+ uint8_t PORTB_CMD_STATUS; /* Port B - Command Status Reg */
+ uint8_t CT1_CMD_STATUS; /* Ctr/Timer 1 - Command Status Reg */
+ uint8_t CT2_CMD_STATUS; /* Ctr/Timer 2 - Command Status Reg */
+ uint8_t CT3_CMD_STATUS; /* Ctr/Timer 3 - Command Status Reg */
+ uint8_t PORTA_DATA; /* Port A - Data */
+ uint8_t PORTB_DATA; /* Port B - Data */
+ uint8_t PORTC_DATA; /* Port C - Data */
+/* COUNTER/TIMER RELATED REGISTERS (0x10-0x1f) */
+ uint8_t CT1_CUR_CNT_MSB; /* Ctr/Timer 1 - Current Count (MSB) */
+ uint8_t CT1_CUR_CNT_LSB; /* Ctr/Timer 1 - Current Count (LSB) */
+ uint8_t CT2_CUR_CNT_MSB; /* Ctr/Timer 2 - Current Count (MSB) */
+ uint8_t CT2_CUR_CNT_LSB; /* Ctr/Timer 2 - Current Count (LSB) */
+ uint8_t CT3_CUR_CNT_MSB; /* Ctr/Timer 3 - Current Count (MSB) */
+ uint8_t CT3_CUR_CNT_LSB; /* Ctr/Timer 3 - Current Count (LSB) */
+ uint8_t CT1_TIME_CONST_MSB; /* Ctr/Timer 1 - Time Constant (MSB) */
+ uint8_t CT1_TIME_CONST_LSB; /* Ctr/Timer 1 - Time Constant (LSB) */
+ uint8_t CT2_TIME_CONST_MSB; /* Ctr/Timer 2 - Time Constant (MSB) */
+ uint8_t CT2_TIME_CONST_LSB; /* Ctr/Timer 2 - Time Constant (LSB) */
+ uint8_t CT3_TIME_CONST_MSB; /* Ctr/Timer 3 - Time Constant (MSB) */
+ uint8_t CT3_TIME_CONST_LSB; /* Ctr/Timer 3 - Time Constant (LSB) */
+ uint8_t CT1_MODE_SPEC; /* Ctr/Timer 1 - Mode Specification */
+ uint8_t CT2_MODE_SPEC; /* Ctr/Timer 2 - Mode Specification */
+ uint8_t CT3_MODE_SPEC; /* Ctr/Timer 3 - Mode Specification */
+ uint8_t CURRENT_VECTOR; /* Current Vector */
+/* PORT A SPECIFICATION REGISTERS (0x20 -0x27) */
+ uint8_t PORTA_MODE; /* Port A - Mode Specification */
+ uint8_t PORTA_HANDSHAKE; /* Port A - Handshake Specification */
+ uint8_t PORTA_DATA_POLARITY; /* Port A - Data Path Polarity */
+ uint8_t PORTA_DIRECTION; /* Port A - Data Direction */
+ uint8_t PORTA_SPECIAL_IO_CTL; /* Port A - Special IO Control */
+ uint8_t PORTA_PATT_POLARITY; /* Port A - Pattern Polarity */
+ uint8_t PORTA_PATT_TRANS; /* Port A - Pattern Transition */
+ uint8_t PORTA_PATT_MASK; /* Port A - Pattern Mask */
+/* PORT B SPECIFICATION REGISTERS (0x28-0x2f) */
+ uint8_t PORTB_MODE; /* Port B - Mode Specification */
+ uint8_t PORTB_HANDSHAKE; /* Port B - Handshake Specification */
+ uint8_t PORTB_DATA_POLARITY; /* Port B - Data Path Polarity */
+ uint8_t PORTB_DIRECTION; /* Port B - Data Direction */
+ uint8_t PORTB_SPECIAL_IO_CTL; /* Port B - Special IO Control */
+ uint8_t PORTB_PATT_POLARITY; /* Port B - Pattern Polarity */
+ uint8_t PORTB_PATT_TRANS; /* Port B - Pattern Transition */
+ uint8_t PORTB_PATT_MASK; /* Port B - Pattern Mask */
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/libcsupport/include/zilog/z8530.h b/cpukit/libcsupport/include/zilog/z8530.h
new file mode 100644
index 0000000000..f77178f8ef
--- /dev/null
+++ b/cpukit/libcsupport/include/zilog/z8530.h
@@ -0,0 +1,98 @@
+/* z8530.h
+ *
+ * This include file defines information related to a Zilog Z8530
+ * SCC Chip. It is a IO mapped part.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __Z8530_h
+#define __Z8530_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* macros */
+
+#define VOL8( ptr ) ((volatile uint8_t *)(ptr))
+
+#define Z8x30_STATE0 ( z8530 ) \
+ { char *garbage; \
+ (garbage) = *(VOL8(z8530)) \
+ }
+
+#define Z8x30_WRITE_CONTROL( z8530, reg, data ) \
+ *(VOL8(z8530)) = (reg); \
+ *(VOL8(z8530)) = (data)
+
+#define Z8x30_READ_CONTROL( z8530, reg, data ) \
+ *(VOL8(z8530)) = (reg); \
+ (data) = *(VOL8(z8530))
+
+#define Z8x30_WRITE_DATA( z8530, data ) \
+ *(VOL8(z8530)) = (data);
+
+#define Z8x30_READ_DATA( z8530, data ) \
+ (data) = *(VOL8(z8530));
+
+
+/* RR_0 Bit Definitions */
+
+#define RR_0_TX_BUFFER_EMPTY 0x04
+#define RR_0_RX_DATA_AVAILABLE 0x01
+
+/* read registers */
+
+#define RR_0 0x00
+#define RR_1 0x01
+#define RR_2 0x02
+#define RR_3 0x03
+#define RR_4 0x04
+#define RR_5 0x05
+#define RR_6 0x06
+#define RR_7 0x07
+#define RR_8 0x08
+#define RR_9 0x09
+#define RR_10 0x0A
+#define RR_11 0x0B
+#define RR_12 0x0C
+#define RR_13 0x0D
+#define RR_14 0x0E
+#define RR_15 0x0F
+
+/* write registers */
+
+#define WR_0 0x00
+#define WR_1 0x01
+#define WR_2 0x02
+#define WR_3 0x03
+#define WR_4 0x04
+#define WR_5 0x05
+#define WR_6 0x06
+#define WR_7 0x07
+#define WR_8 0x08
+#define WR_9 0x09
+#define WR_10 0x0A
+#define WR_11 0x0B
+#define WR_12 0x0C
+#define WR_13 0x0D
+#define WR_14 0x0E
+#define WR_15 0x0F
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/libcsupport/include/zilog/z8536.h b/cpukit/libcsupport/include/zilog/z8536.h
new file mode 100644
index 0000000000..22457c8bca
--- /dev/null
+++ b/cpukit/libcsupport/include/zilog/z8536.h
@@ -0,0 +1,111 @@
+/* z8536.h
+ *
+ * This include file defines information related to a Zilog Z8536
+ * Counter/Timer/IO Chip. It is a IO mapped part.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * NOTE: This file shares as much as possible with the include
+ * file for the Z8036 via z8x36.h.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __Z8536_h
+#define __Z8536_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* macros */
+
+#define VOL8( ptr ) ((volatile uint8_t *)(ptr))
+
+#define Z8x36_STATE0 ( z8536 ) \
+ { char *garbage; \
+ (garbage) = *(VOL8(z8536+0xC)) \
+ }
+
+#define Z8x36_WRITE( z8536, reg, data ) \
+ *(VOL8(z8536+0xC)) = (reg); \
+ *(VOL8(z8536+0xC)) = (data)
+
+#define Z8x36_READ( z8536, reg, data ) \
+ *(VOL8(z8536+0xC)) = (reg); \
+ (data) = *(VOL8(z8536+0xC))
+
+/* structures */
+
+/* MAIN CONTROL REGISTERS (0x00-0x07) */
+#define MASTER_INTR 0x00 /* Master Interrupt Ctl Reg */
+#define MASTER_CFG 0x01 /* Master Configuration Ctl Reg */
+#define PORTA_VECTOR 0x02 /* Port A - Interrupt Vector */
+#define PORTB_VECTOR 0x03 /* Port B - Interrupt Vector */
+#define CNT_TMR_VECTOR 0x04 /* Counter/Timer Interrupt Vector */
+#define PORTC_DATA_POLARITY 0x05 /* Port C - Data Path Polarity */
+#define PORTC_DIRECTION 0x06 /* Port C - Data Direction */
+#define PORTC_SPECIAL_IO_CTL 0x07 /* Port C - Special IO Control */
+
+/* MOST OFTEN ACCESSED REGISTERS (0x08 - 0x0f) */
+#define PORTA_CMD_STATUS 0x08 /* Port A - Command Status Reg */
+#define PORTB_CMD_STATUS 0x09 /* Port B - Command Status Reg */
+#define CT1_CMD_STATUS 0x0a /* Ctr/Timer 1 - Command Status Reg */
+#define CT2_CMD_STATUS 0x0b /* Ctr/Timer 2 - Command Status Reg */
+#define CT3_CMD_STATUS 0x0c /* Ctr/Timer 3 - Command Status Reg */
+#define PORTA_DATA 0x0d /* Port A - Data */
+#define PORTB_DATA 0x0e /* Port B - Data */
+#define PORTC_DATA 0x0f /* Port C - Data */
+
+/* COUNTER/TIMER RELATED REGISTERS (0x10-0x1f) */
+#define CT1_CUR_CNT_MSB 0x10 /* Ctr/Timer 1 - Current Count (MSB) */
+#define CT1_CUR_CNT_LSB 0x11 /* Ctr/Timer 1 - Current Count (LSB) */
+#define CT2_CUR_CNT_MSB 0x12 /* Ctr/Timer 2 - Current Count (MSB) */
+#define CT2_CUR_CNT_LSB 0x13 /* Ctr/Timer 2 - Current Count (LSB) */
+#define CT3_CUR_CNT_MSB 0x14 /* Ctr/Timer 3 - Current Count (MSB) */
+#define CT3_CUR_CNT_LSB 0x15 /* Ctr/Timer 3 - Current Count (LSB) */
+#define CT1_TIME_CONST_MSB 0x16 /* Ctr/Timer 1 - Time Constant (MSB) */
+#define CT1_TIME_CONST_LSB 0x17 /* Ctr/Timer 1 - Time Constant (LSB) */
+#define CT2_TIME_CONST_MSB 0x18 /* Ctr/Timer 2 - Time Constant (MSB) */
+#define CT2_TIME_CONST_LSB 0x19 /* Ctr/Timer 2 - Time Constant (LSB) */
+#define CT3_TIME_CONST_MSB 0x1a /* Ctr/Timer 3 - Time Constant (MSB) */
+#define CT3_TIME_CONST_LSB 0x1b /* Ctr/Timer 3 - Time Constant (LSB) */
+#define CT1_MODE_SPEC 0x1c /* Ctr/Timer 1 - Mode Specification */
+#define CT2_MODE_SPEC 0x1d /* Ctr/Timer 2 - Mode Specification */
+#define CT3_MODE_SPEC 0x1e /* Ctr/Timer 3 - Mode Specification */
+#define CURRENT_VECTOR 0x1f /* Current Vector */
+
+/* PORT A SPECIFICATION REGISTERS (0x20 -0x27) */
+#define PORTA_MODE 0x20 /* Port A - Mode Specification */
+#define PORTA_HANDSHAKE 0x21 /* Port A - Handshake Specification */
+#define PORTA_DATA_POLARITY 0x22 /* Port A - Data Path Polarity */
+#define PORTA_DIRECTION 0x23 /* Port A - Data Direction */
+#define PORTA_SPECIAL_IO_CTL 0x24 /* Port A - Special IO Control */
+#define PORTA_PATT_POLARITY 0x25 /* Port A - Pattern Polarity */
+#define PORTA_PATT_TRANS 0x26 /* Port A - Pattern Transition */
+#define PORTA_PATT_MASK 0x27 /* Port A - Pattern Mask */
+
+/* PORT B SPECIFICATION REGISTERS (0x28-0x2f) */
+#define PORTB_MODE 0x28 /* Port B - Mode Specification */
+#define PORTB_HANDSHAKE 0x29 /* Port B - Handshake Specification */
+#define PORTB_DATA_POLARITY 0x2a /* Port B - Data Path Polarity */
+#define PORTB_DIRECTION 0x2b /* Port B - Data Direction */
+#define PORTB_SPECIAL_IO_CTL 0x2c /* Port B - Special IO Control */
+#define PORTB_PATT_POLARITY 0x2d /* Port B - Pattern Polarity */
+#define PORTB_PATT_TRANS 0x2e /* Port B - Pattern Transition */
+#define PORTB_PATT_MASK 0x2f /* Port B - Pattern Mask */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/libcsupport/src/.cvsignore b/cpukit/libcsupport/src/.cvsignore
new file mode 100644
index 0000000000..000074c626
--- /dev/null
+++ b/cpukit/libcsupport/src/.cvsignore
@@ -0,0 +1,4 @@
+stamp-h
+stamp-h.in
+config.h
+config.h.in
diff --git a/cpukit/libcsupport/src/CASES b/cpukit/libcsupport/src/CASES
new file mode 100644
index 0000000000..4578ae5009
--- /dev/null
+++ b/cpukit/libcsupport/src/CASES
@@ -0,0 +1,23 @@
+#
+# $Id$
+#
+
+This is a list of cases to consider when implementing a file system:
+
+
++ Given a tree of this form:
+
+ a ----- b
+ /
+ c
+
+ Where a and b are directories and c is a link to directory b. Consider
+ this sequence:
+
+ - rmdir a/b
+ - mknod c/b/x
+ - unlink c
+
+
+
+
diff --git a/cpukit/libcsupport/src/README b/cpukit/libcsupport/src/README
new file mode 100644
index 0000000000..ee7a90501e
--- /dev/null
+++ b/cpukit/libcsupport/src/README
@@ -0,0 +1,37 @@
+--
+-- $Id$
+--
+
+Overview of newlib support (newlib is from CYGNUS)
+ Each task can have its own libc state including:
+ open stdio files
+ strtok
+ multi precision arithmetic state
+ etc.
+
+ This is implemented by a reentrancy data structure for each task.
+
+ When a task is "started" (in RTEMS sense) the reentrancy structure
+ is allocated. Its address is stored in notepad[NOTEPAD_LAST].
+
+ When task is switched to, the value of global variable _impure_ptr
+ is changed to the value of the new tasks reentrancy structure.
+
+ When a task is deleted
+ atexit() processing (for that task) happens
+ task's stdio buffers are flushed
+
+ When exit(3) is called
+ calling task's atexit processing done
+ global libc state atexit processing done
+ (this will include any atexit routines installed by drivers)
+ executive is shutdown
+ causes a context switch back to bsp land
+
+
+NOTE:
+ libc extension are installed by bsp_libc_init()
+ iff we are using clock interrupts.
+ This hack is necessary to allow the tmtests to avoid
+ timing the extensions.
+
diff --git a/cpukit/libcsupport/src/TODO b/cpukit/libcsupport/src/TODO
new file mode 100644
index 0000000000..38cb012326
--- /dev/null
+++ b/cpukit/libcsupport/src/TODO
@@ -0,0 +1,14 @@
+#
+# $Id$
+#
+
++ newlib 1.8.0 has the wrong prototype for at least read() and write().
+
++ There should be a "eat it" stub for all system calls which are
+ available to make filling out an operations table easier.
+ See device_lseek() for an example of where this would be nice.
+
++ Fix strerror() so it prints all error numbers.
+
++ Check the node allocation coment in the fchdir call.
++ Add an interface somewhere for this call. \ No newline at end of file
diff --git a/cpukit/libcsupport/src/__brk.c b/cpukit/libcsupport/src/__brk.c
new file mode 100644
index 0000000000..9082f3ab70
--- /dev/null
+++ b/cpukit/libcsupport/src/__brk.c
@@ -0,0 +1,32 @@
+/*
+ * RTEMS "Broken" __brk Implementation
+ *
+ * NOTE: sbrk() is provided by each BSP.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#if !defined(RTEMS_UNIX)
+
+#include <errno.h>
+
+int __brk(
+ const void *endds
+)
+{
+ errno = EINVAL;
+ return -1;
+}
+#endif
diff --git a/cpukit/libcsupport/src/__getpid.c b/cpukit/libcsupport/src/__getpid.c
new file mode 100644
index 0000000000..85a4c0b013
--- /dev/null
+++ b/cpukit/libcsupport/src/__getpid.c
@@ -0,0 +1,17 @@
+/*
+ * Some C Libraries reference this routine since they think getpid is
+ * a real system call.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+
+pid_t __getpid(void)
+{
+ return getpid();
+}
diff --git a/cpukit/libcsupport/src/__gettod.c b/cpukit/libcsupport/src/__gettod.c
new file mode 100644
index 0000000000..918c2d3109
--- /dev/null
+++ b/cpukit/libcsupport/src/__gettod.c
@@ -0,0 +1,120 @@
+/*
+ * gettimeofday() - SVR4 and BSD4.3 extension required by Newlib
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+
+#include <rtems.h>
+
+#if !defined(RTEMS_UNIX)
+#ifdef RTEMS_NEWLIB
+#include <sys/reent.h>
+#endif
+
+#include <sys/time.h>
+#include <time.h>
+
+#include <errno.h>
+#include <assert.h>
+
+/*
+ * Seconds from January 1, 1970 to January 1, 1988. Used to account for
+ * differences between POSIX API and RTEMS core.
+ */
+
+#define POSIX_TIME_SECONDS_1970_THROUGH_1988 \
+ (((1987 - 1970 + 1) * TOD_SECONDS_PER_NON_LEAP_YEAR) + \
+ (4 * TOD_SECONDS_PER_DAY))
+
+/*
+ * NOTE: The solaris gettimeofday does not have a second parameter.
+ */
+
+int gettimeofday(
+ struct timeval *tp,
+ struct timezone *tzp
+)
+{
+ rtems_interrupt_level level;
+ uint32_t seconds;
+ uint32_t microseconds;
+
+ if ( !tp ) {
+ errno = EFAULT;
+ return -1;
+ }
+
+ /*
+ * POSIX does not seem to allow for not having a TOD so we just
+ * grab the time of day.
+ *
+ * NOTE: XXX this routine should really be in the executive proper.
+ */
+
+ rtems_interrupt_disable(level);
+ seconds = _TOD_Seconds_since_epoch;
+ microseconds = _TOD_Current.ticks;
+ rtems_interrupt_enable(level);
+
+ tp->tv_sec = seconds + POSIX_TIME_SECONDS_1970_THROUGH_1988;
+ tp->tv_usec = microseconds * _TOD_Microseconds_per_tick;
+
+ /*
+ * newlib does not have timezone and daylight savings time
+ * yet. When it does this needs to be fixed.
+ */
+
+#if 0
+ if ( tzp ) {
+ tzp->tz_minuteswest = 0; /* at UTC */
+ tzp->tz_dsttime = 0; /* no daylight savings */
+ tzp->minuteswest = timezone / 60; /* from seconds to minutes */
+ tzp->dsttime = daylight;
+ }
+#endif
+ return 0;
+}
+
+#if defined(RTEMS_NEWLIB)
+
+/*
+ * "Reentrant" version
+ */
+
+int _gettimeofday_r(
+ struct _reent *ignored_reentrancy_stuff,
+ struct timeval *tp,
+ struct timezone *tzp
+)
+{
+ return gettimeofday( tp, tzp );
+}
+
+/*
+ * "System call" version
+ */
+
+int _gettimeofday(
+ struct timeval *tp,
+ struct timezone *tzp
+)
+{
+ return gettimeofday( tp, tzp );
+}
+
+#endif /* defined(RTEMS_NEWLIB) */
+
+#endif
diff --git a/cpukit/libcsupport/src/__sbrk.c b/cpukit/libcsupport/src/__sbrk.c
new file mode 100644
index 0000000000..91260f1b24
--- /dev/null
+++ b/cpukit/libcsupport/src/__sbrk.c
@@ -0,0 +1,32 @@
+/*
+ * RTEMS "Broken" __sbrk Implementation
+ *
+ * NOTE: sbrk is provided by the BSP.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#if !defined(RTEMS_UNIX)
+
+#include <errno.h>
+
+void * __sbrk(
+ int incr
+)
+{
+ errno = EINVAL;
+ return (void *)0;
+}
+#endif
diff --git a/cpukit/libcsupport/src/__times.c b/cpukit/libcsupport/src/__times.c
new file mode 100644
index 0000000000..733befe8c9
--- /dev/null
+++ b/cpukit/libcsupport/src/__times.c
@@ -0,0 +1,89 @@
+/*
+ * times() - POSIX 1003.1b 4.5.2 - Get Process Times
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+
+#include <sys/times.h>
+#include <time.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <assert.h>
+
+clock_t _times(
+ struct tms *ptms
+)
+{
+ rtems_interval ticks;
+
+ if ( !ptms ) {
+ errno = EFAULT;
+ return -1;
+ }
+
+ /*
+ * This call does not depend on TOD being initialized and can't fail.
+ */
+
+ (void) rtems_clock_get( RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &ticks );
+
+ /*
+ * RTEMS technically has no notion of system versus user time
+ * since there is no separation of OS from application tasks.
+ * But we can at least make a distinction between the number
+ * of ticks since boot and the number of ticks executed by this
+ * this thread.
+ */
+
+ ptms->tms_utime = _Thread_Executing->ticks_executed;
+ ptms->tms_stime = ticks;
+ ptms->tms_cutime = 0;
+ ptms->tms_cstime = 0;
+
+ return ticks;
+}
+
+/*
+ * times()
+ *
+ * times() system call wrapper for _times() above.
+ */
+
+clock_t times(
+ struct tms *ptms
+)
+{
+ return _times( ptms );
+}
+
+/*
+ * _times_r
+ *
+ * This is the Newlib dependent reentrant version of times().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+clock_t _times_r(
+ struct _reent *ptr,
+ struct tms *ptms
+)
+{
+ return _times( ptms );
+}
+#endif
diff --git a/cpukit/libcsupport/src/access.c b/cpukit/libcsupport/src/access.c
new file mode 100644
index 0000000000..7365d6db7d
--- /dev/null
+++ b/cpukit/libcsupport/src/access.c
@@ -0,0 +1,48 @@
+/*
+ * access() - POSIX 1003.1b 5.6.3 - File Accessibility
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+int access(
+ const char *path,
+ int amode
+)
+{
+ struct stat statbuf;
+
+ if ( stat(path, &statbuf) )
+ return -1;
+
+ if ( amode & R_OK ) {
+ if (!( statbuf.st_mode & S_IREAD ))
+ return -1;
+ }
+
+ if ( amode & W_OK ) {
+ if ( !( statbuf.st_mode & S_IWRITE ) )
+ return -1;
+ }
+
+ if ( amode & X_OK ) {
+ if ( !( statbuf.st_mode & S_IEXEC ) )
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/cpukit/libcsupport/src/assoc.c b/cpukit/libcsupport/src/assoc.c
new file mode 100644
index 0000000000..58c0b2e73f
--- /dev/null
+++ b/cpukit/libcsupport/src/assoc.c
@@ -0,0 +1,254 @@
+/*
+ * assoc.c
+ * rtems assoc routines
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/assoc.h>
+
+#include <string.h> /* strcat, strcmp */
+
+#define STREQ(a,b) (strcmp((a), (b)) == 0)
+#define rtems_assoc_is_default(ap) ((ap)->name && STREQ(ap->name, RTEMS_ASSOC_DEFAULT_NAME))
+
+const rtems_assoc_t *
+rtems_assoc_ptr_by_name(
+ const rtems_assoc_t *ap,
+ const char *name
+ )
+{
+ const rtems_assoc_t *default_ap = 0;
+
+ if (rtems_assoc_is_default(ap))
+ default_ap = ap++;
+
+ for ( ; ap->name; ap++)
+ if (strcmp(ap->name, name) == 0)
+ return ap;
+
+ return default_ap;
+}
+
+const rtems_assoc_t *
+rtems_assoc_ptr_by_local(
+ const rtems_assoc_t *ap,
+ uint32_t local_value
+ )
+{
+ const rtems_assoc_t *default_ap = 0;
+
+ if (rtems_assoc_is_default(ap))
+ default_ap = ap++;
+
+ for ( ; ap->name; ap++)
+ if (ap->local_value == local_value)
+ return ap;
+
+ return default_ap;
+}
+
+
+const rtems_assoc_t *
+rtems_assoc_ptr_by_remote(
+ const rtems_assoc_t *ap,
+ uint32_t remote_value
+ )
+{
+ const rtems_assoc_t *default_ap = 0;
+
+ if (rtems_assoc_is_default(ap))
+ default_ap = ap++;
+
+ for ( ; ap->name; ap++)
+ if (ap->remote_value == remote_value)
+ return ap;
+
+ return default_ap;
+}
+
+
+/*
+ * Get values
+ */
+
+uint32_t
+rtems_assoc_remote_by_local(
+ const rtems_assoc_t *ap,
+ uint32_t local_value
+ )
+{
+ const rtems_assoc_t *nap;
+ nap = rtems_assoc_ptr_by_local(ap, local_value);
+ if (nap)
+ return nap->remote_value;
+
+ return 0;
+}
+
+uint32_t
+rtems_assoc_local_by_remote(
+ const rtems_assoc_t *ap,
+ uint32_t remote_value
+ )
+{
+ const rtems_assoc_t *nap;
+ nap = rtems_assoc_ptr_by_remote(ap, remote_value);
+ if (nap)
+ return nap->local_value;
+
+ return 0;
+}
+
+uint32_t
+rtems_assoc_remote_by_name(
+ const rtems_assoc_t *ap,
+ const char *name
+ )
+{
+ const rtems_assoc_t *nap;
+ nap = rtems_assoc_ptr_by_name(ap, name);
+ if (nap)
+ return nap->remote_value;
+
+ return 0;
+}
+
+uint32_t
+rtems_assoc_local_by_name(
+ const rtems_assoc_t *ap,
+ const char *name
+ )
+{
+ const rtems_assoc_t *nap;
+ nap = rtems_assoc_ptr_by_name(ap, name);
+ if (nap)
+ return nap->local_value;
+
+ return 0;
+}
+
+/*
+ * what to return if a value is not found
+ * this is not reentrant, but it really shouldn't be invoked anyway
+ */
+
+const char *rtems_assoc_name_bad(
+ uint32_t bad_value
+);
+
+/* body in separate file to reduce dependency on printf */
+
+
+const char *
+rtems_assoc_name_by_local(
+ const rtems_assoc_t *ap,
+ uint32_t local_value
+ )
+{
+ const rtems_assoc_t *nap;
+ nap = rtems_assoc_ptr_by_local(ap, local_value);
+ if (nap)
+ return nap->name;
+
+ return rtems_assoc_name_bad(local_value);
+}
+
+const char *
+rtems_assoc_name_by_remote(
+ const rtems_assoc_t *ap,
+ uint32_t remote_value
+ )
+{
+ const rtems_assoc_t *nap;
+ nap = rtems_assoc_ptr_by_remote(ap, remote_value);
+ if (nap)
+ return nap->name;
+
+ return rtems_assoc_name_bad(remote_value);
+}
+
+/*
+ * Bitfield functions assume just 1 bit set in each of remote and local
+ * entries; they do not check for this.
+ */
+
+uint32_t rtems_assoc_remote_by_local_bitfield(
+ const rtems_assoc_t *ap,
+ uint32_t local_value
+ )
+{
+ uint32_t b;
+ uint32_t remote_value = 0;
+
+ for (b = 1; b; b <<= 1)
+ if (b & local_value)
+ remote_value |= rtems_assoc_remote_by_local(ap, b);
+
+ return remote_value;
+}
+
+
+uint32_t rtems_assoc_local_by_remote_bitfield(
+ const rtems_assoc_t *ap,
+ uint32_t remote_value
+ )
+{
+ uint32_t b;
+ uint32_t local_value = 0;
+
+ for (b = 1; b; b <<= 1)
+ if (b & remote_value)
+ local_value |= rtems_assoc_local_by_remote(ap, b);
+
+ return local_value;
+}
+
+char *
+rtems_assoc_name_by_remote_bitfield(
+ const rtems_assoc_t *ap,
+ uint32_t value,
+ char *buffer
+ )
+{
+ uint32_t b;
+
+ *buffer = 0;
+
+ for (b = 1; b; b <<= 1)
+ if (b & value)
+ {
+ if (*buffer)
+ strcat(buffer, " ");
+ strcat(buffer, rtems_assoc_name_by_remote(ap, b));
+ }
+
+ return buffer;
+}
+
+char *
+rtems_assoc_name_by_local_bitfield(
+ const rtems_assoc_t *ap,
+ uint32_t value,
+ char *buffer
+ )
+{
+ uint32_t b;
+
+ *buffer = 0;
+
+ for (b = 1; b; b <<= 1)
+ if (b & value)
+ {
+ if (*buffer)
+ strcat(buffer, " ");
+ strcat(buffer, rtems_assoc_name_by_local(ap, b));
+ }
+
+ return buffer;
+}
diff --git a/cpukit/libcsupport/src/assocnamebad.c b/cpukit/libcsupport/src/assocnamebad.c
new file mode 100644
index 0000000000..d1e7191342
--- /dev/null
+++ b/cpukit/libcsupport/src/assocnamebad.c
@@ -0,0 +1,39 @@
+/*
+ * assoc.c
+ * rtems assoc routines
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/assoc.h>
+
+#include <stdio.h> /* sprintf */
+#include <string.h> /* strcat, strcmp */
+
+#define STREQ(a,b) (strcmp((a), (b)) == 0)
+#define rtems_assoc_is_default(ap) ((ap)->name && STREQ(ap->name, RTEMS_ASSOC_DEFAULT_NAME))
+
+/*
+ * what to return if a value is not found
+ * this is not reentrant, but it really shouldn't be invoked anyway
+ */
+
+const char *
+rtems_assoc_name_bad(
+ uint32_t bad_value
+)
+{
+#ifdef RTEMS_DEBUG
+ static char bad_buffer[32];
+
+ sprintf(bad_buffer, "< %d [0x%x] >", bad_value, bad_value);
+#else
+ static char bad_buffer[32] = "<assoc.c: BAD NAME>";
+#endif
+ return bad_buffer;
+}
diff --git a/cpukit/libcsupport/src/base_fs.c b/cpukit/libcsupport/src/base_fs.c
new file mode 100644
index 0000000000..dedafc8d1c
--- /dev/null
+++ b/cpukit/libcsupport/src/base_fs.c
@@ -0,0 +1,150 @@
+/*
+ * Base file system initialization
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <rtems/libio_.h>
+
+/*
+ * Global information for the base file system.
+ */
+
+rtems_user_env_t rtems_global_user_env;
+rtems_user_env_t * rtems_current_user_env = &rtems_global_user_env;
+
+/*
+ * Default mode for created files.
+ */
+
+
+/*
+ * rtems_filesystem_initialize
+ *
+ * Initialize the foundation of the file system. This is specified
+ * by the structure rtems_filesystem_mount_table. The usual
+ * configuration is a single instantiation of the IMFS or miniIMFS with
+ * a single "/dev" directory in it.
+ */
+
+void rtems_filesystem_initialize( void )
+{
+#if !defined(RTEMS_UNIX)
+#if 0
+ int i;
+#endif
+ int status;
+ rtems_filesystem_mount_table_entry_t *entry;
+ rtems_filesystem_mount_table_t *mt;
+ rtems_filesystem_location_info_t loc;
+
+ /*
+ * Set the default umask to "022".
+ */
+
+ rtems_filesystem_umask = 022;
+
+
+ init_fs_mount_table();
+
+ /*
+ * mount the first filesystem.
+ */
+
+ if ( rtems_filesystem_mount_table_size == 0 )
+ rtems_fatal_error_occurred( 0xABCD0001 );
+
+ mt = &rtems_filesystem_mount_table[0];
+
+ status = mount(
+ &entry, mt->fs_ops, mt->fsoptions, mt->device, mt->mount_point );
+
+ if ( status == -1 )
+ rtems_fatal_error_occurred( 0xABCD0002 );
+
+ rtems_filesystem_link_counts = 0;
+
+ /* setup the 'current' and 'root' directories
+ *
+ * NOTE: cloning the pathlocs is not strictly
+ * necessary. Since we implicitely let
+ * all threads that don't call
+ * libio_set_private_env() share the same
+ * (initial) 'root' and 'current' locs,
+ * we (also implicitely) assume that the
+ * root filesystem doesn't care about
+ * reference counts.
+ * I just inserted the code snippet below
+ * to remind everybody of the fact by
+ * making it more explicit...
+ * Ideally, every thread would have to
+ * call either share_private_env() or
+ * set_private_env() - but then: that's
+ * gonna hit performance.
+ *
+ * Till Straumann, 10/25/2002
+ */
+ rtems_filesystem_root = entry->mt_fs_root;
+ /* Clone the root pathloc */
+ rtems_filesystem_evaluate_path("/", 0, &loc, 0);
+ rtems_filesystem_root = loc;
+ /* One more clone for the current node */
+ rtems_filesystem_evaluate_path("/", 0, &loc, 0);
+ rtems_filesystem_current = loc;
+
+ /* Note: the global_env's refcnt doesn't matter
+ * as the global env is never released
+ */
+
+
+ /*
+ * Traditionally RTEMS devices are under "/dev" so install this directory.
+ *
+ * If the mkdir() fails, we can't print anything so just fatal error.
+ *
+ * NOTE: UNIX root is 755 and owned by root/root (0/0). It is actually
+ * created that way by the IMFS.
+ */
+
+ status = mkdir( "/dev", 0777);
+ if ( status != 0 )
+ rtems_fatal_error_occurred( 0xABCD0003 );
+
+ /*
+ * This code if if'ed 0 out because you can't mount another
+ * filesystem properly until the mount point it will be
+ * mounted onto is created. Moreover, if it is going to
+ * use a device, then it is REALLY unfair to attempt this
+ * before device drivers are initialized.
+ */
+
+#if 0
+ /*
+ * Now if there are other filesystems to mount, go for it.
+ */
+
+ for ( i=1 ; i < rtems_filesystem_mount_table_size ; i++ ) {
+ mt = &rtems_filesystem_mount_table[0];
+
+ status = mount(
+ &entry, mt->fs_ops, mt->fsoptions, mt->device, mt->mount_point );
+
+ if ( status == -1 )
+ rtems_fatal_error_occurred( 0xABCD0003 );
+ }
+#endif
+#endif
+}
diff --git a/cpukit/libcsupport/src/cfgetispeed.c b/cpukit/libcsupport/src/cfgetispeed.c
new file mode 100644
index 0000000000..225c7311cc
--- /dev/null
+++ b/cpukit/libcsupport/src/cfgetispeed.c
@@ -0,0 +1,32 @@
+/*
+ * cfgetispeed() - POSIX 1003.1b 7.1.3 - Baud Rate Functions
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+
+speed_t cfgetispeed(
+ const struct termios *tp
+)
+{
+ return (tp->c_cflag / (CIBAUD / CBAUD)) & CBAUD;
+}
+#endif
diff --git a/cpukit/libcsupport/src/cfgetospeed.c b/cpukit/libcsupport/src/cfgetospeed.c
new file mode 100644
index 0000000000..e239e54758
--- /dev/null
+++ b/cpukit/libcsupport/src/cfgetospeed.c
@@ -0,0 +1,32 @@
+/*
+ * cfgetospeed() - POSIX 1003.1b 7.1.3 - Baud Rate Functions
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+
+speed_t cfgetospeed(
+ const struct termios *tp
+)
+{
+ return tp->c_cflag & CBAUD;
+}
+#endif
diff --git a/cpukit/libcsupport/src/cfsetispeed.c b/cpukit/libcsupport/src/cfsetispeed.c
new file mode 100644
index 0000000000..383762bee1
--- /dev/null
+++ b/cpukit/libcsupport/src/cfsetispeed.c
@@ -0,0 +1,40 @@
+/*
+ * cfsetispeed() - POSIX 1003.1b 7.1.3 - Baud Rate Functions
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int cfsetispeed(
+ struct termios *tp,
+ speed_t speed
+)
+{
+ if ( speed & ~CBAUD )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ tp->c_cflag = (tp->c_cflag & ~CIBAUD) | (speed * (CIBAUD / CBAUD));
+ return 0;
+}
+#endif
diff --git a/cpukit/libcsupport/src/cfsetospeed.c b/cpukit/libcsupport/src/cfsetospeed.c
new file mode 100644
index 0000000000..0badcbbdc7
--- /dev/null
+++ b/cpukit/libcsupport/src/cfsetospeed.c
@@ -0,0 +1,40 @@
+/*
+ * cfsetospeed() - POSIX 1003.1b 7.1.3 - Baud Rate Functions
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int cfsetospeed(
+ struct termios *tp,
+ speed_t speed
+)
+{
+ if ( speed & ~CBAUD )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ tp->c_cflag = (tp->c_cflag & ~CBAUD) | speed;
+ return 0;
+}
+#endif
diff --git a/cpukit/libcsupport/src/chdir.c b/cpukit/libcsupport/src/chdir.c
new file mode 100644
index 0000000000..b508ea20ed
--- /dev/null
+++ b/cpukit/libcsupport/src/chdir.c
@@ -0,0 +1,61 @@
+/*
+ * chdir() - POSIX 1003.1b - 5.2.1 - Change Current Working Directory
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+
+#include <unistd.h>
+#include <errno.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int chdir(
+ const char *pathname
+)
+{
+ rtems_filesystem_location_info_t loc;
+ int result;
+
+ /*
+ * Get the node where we wish to go.
+ */
+
+ result = rtems_filesystem_evaluate_path(
+ pathname, RTEMS_LIBIO_PERMS_SEARCH, &loc, TRUE );
+ if ( result != 0 )
+ return -1;
+
+ /*
+ * Verify you can change directory into this node.
+ */
+
+ if ( !loc.ops->node_type_h ) {
+ rtems_filesystem_freenode( &loc );
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+ }
+
+ if ( (*loc.ops->node_type_h)( &loc ) != RTEMS_FILESYSTEM_DIRECTORY ) {
+ rtems_filesystem_freenode( &loc );
+ rtems_set_errno_and_return_minus_one( ENOTDIR );
+ }
+
+ rtems_filesystem_freenode( &rtems_filesystem_current );
+
+ rtems_filesystem_current = loc;
+
+ return 0;
+}
diff --git a/cpukit/libcsupport/src/chmod.c b/cpukit/libcsupport/src/chmod.c
new file mode 100644
index 0000000000..1007be6b26
--- /dev/null
+++ b/cpukit/libcsupport/src/chmod.c
@@ -0,0 +1,56 @@
+/*
+ * chmod() - POSIX 1003.1b 5.6.4 - Change File Modes
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int chmod(
+ const char *path,
+ mode_t mode
+)
+{
+ int status;
+ rtems_filesystem_location_info_t loc;
+ int result;
+
+ status = rtems_filesystem_evaluate_path( path, 0, &loc, TRUE );
+ if ( status != 0 )
+ return -1;
+
+ if ( !loc.handlers ){
+ rtems_filesystem_freenode( &loc );
+ rtems_set_errno_and_return_minus_one( EBADF );
+ }
+
+ if ( !loc.handlers->fchmod_h ){
+ rtems_filesystem_freenode( &loc );
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+ }
+
+ result = (*loc.handlers->fchmod_h)( &loc, mode );
+
+ rtems_filesystem_freenode( &loc );
+
+ return result;
+}
diff --git a/cpukit/libcsupport/src/chown.c b/cpukit/libcsupport/src/chown.c
new file mode 100644
index 0000000000..8ac0a91979
--- /dev/null
+++ b/cpukit/libcsupport/src/chown.c
@@ -0,0 +1,49 @@
+/*
+ * chown() - POSIX 1003.1b 5.6.5 - Change Owner and Group of a File
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/stat.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int chown(
+ const char *path,
+ uid_t owner,
+ gid_t group
+)
+{
+ rtems_filesystem_location_info_t loc;
+ int result;
+
+ if ( rtems_filesystem_evaluate_path( path, 0x00, &loc, TRUE ) )
+ return -1;
+
+ if ( !loc.ops->chown_h ) {
+ rtems_filesystem_freenode( &loc );
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+ }
+
+ result = (*loc.ops->chown_h)( &loc, owner, group );
+
+ rtems_filesystem_freenode( &loc );
+
+ return result;
+}
diff --git a/cpukit/libcsupport/src/chroot.c b/cpukit/libcsupport/src/chroot.c
new file mode 100644
index 0000000000..648b0b872d
--- /dev/null
+++ b/cpukit/libcsupport/src/chroot.c
@@ -0,0 +1,54 @@
+/*
+ * chroot() - Change Root Directory
+ * Author: fernando.ruiz@ctv.es
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+
+#include <unistd.h>
+#include <errno.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int chroot(
+ const char *pathname
+)
+{
+ int result;
+ rtems_filesystem_location_info_t loc;
+
+ /* an automatic call to new private env the first time */
+ if (rtems_current_user_env == &rtems_global_user_env) {
+ rtems_libio_set_private_env(); /* try to set a new private env*/
+ if (rtems_current_user_env == &rtems_global_user_env) /* not ok */
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+ };
+
+ result = chdir(pathname);
+ if (result) {
+ rtems_set_errno_and_return_minus_one( errno );
+ };
+ /* clone the new root location */
+ if (rtems_filesystem_evaluate_path(".", 0, &loc, 0)) {
+ /* our cwd has changed, though - but there is no easy way of return :-( */
+ rtems_set_errno_and_return_minus_one( errno );
+ }
+ rtems_filesystem_freenode(&rtems_filesystem_root);
+ rtems_filesystem_root = loc;
+
+ return 0;
+}
diff --git a/cpukit/libcsupport/src/close.c b/cpukit/libcsupport/src/close.c
new file mode 100644
index 0000000000..b9114f81e7
--- /dev/null
+++ b/cpukit/libcsupport/src/close.c
@@ -0,0 +1,58 @@
+/*
+ * close() - POSIX 1003.1b 6.3.1 - Close a File
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/libio_.h>
+
+int close(
+ int fd
+)
+{
+ rtems_libio_t *iop;
+ rtems_status_code rc;
+
+ rtems_libio_check_fd(fd);
+ iop = rtems_libio_iop(fd);
+ rtems_libio_check_is_open(iop);
+
+ rc = RTEMS_SUCCESSFUL;
+ if ( iop->handlers->close_h )
+ rc = (*iop->handlers->close_h)( iop );
+
+ rtems_filesystem_freenode( &iop->pathinfo );
+ rtems_libio_free( iop );
+
+ return rc;
+}
+
+/*
+ * _close_r
+ *
+ * This is the Newlib dependent reentrant version of close().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+int _close_r(
+ struct _reent *ptr,
+ int fd
+)
+{
+ return close( fd );
+}
+#endif
diff --git a/cpukit/libcsupport/src/closedir.c b/cpukit/libcsupport/src/closedir.c
new file mode 100644
index 0000000000..2204768a08
--- /dev/null
+++ b/cpukit/libcsupport/src/closedir.c
@@ -0,0 +1,74 @@
+/*
+ * closedir() - POSIX 1003.1b - XXX
+ *
+ * This was copied from Newlib 1.8.0.
+ *
+ *
+ * Copyright (c) 1983 Regents of the University of California.
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)closedir.c 5.9 (Berkeley) 2/23/91";
+#endif /* LIBC_SCCS and not lint */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+/*
+ * close a directory.
+ */
+int
+closedir(dirp)
+ register DIR *dirp;
+{
+ int fd;
+
+ if ( !dirp )
+ rtems_set_errno_and_return_minus_one( EBADF );
+
+ fd = dirp->dd_fd;
+ dirp->dd_fd = -1;
+ dirp->dd_loc = 0;
+ (void)free((void *)dirp->dd_buf);
+ (void)free((void *)dirp);
+ return(close(fd));
+}
diff --git a/cpukit/libcsupport/src/creat.c b/cpukit/libcsupport/src/creat.c
new file mode 100644
index 0000000000..ed7a872d4a
--- /dev/null
+++ b/cpukit/libcsupport/src/creat.c
@@ -0,0 +1,19 @@
+/*
+ * $Id$
+ */
+
+/* creat() "system call" */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* This is needed by f2c and therefore the SPEC benchmarks. */
+
+#include <fcntl.h>
+
+int
+creat (const char *path, mode_t mode)
+{
+ return open (path, O_WRONLY | O_CREAT | O_TRUNC, mode);
+}
diff --git a/cpukit/libcsupport/src/ctermid.c b/cpukit/libcsupport/src/ctermid.c
new file mode 100644
index 0000000000..f0e2310fea
--- /dev/null
+++ b/cpukit/libcsupport/src/ctermid.c
@@ -0,0 +1,37 @@
+/*
+ * ctermid() - POSIX 1003.1b 4.7.1 - Generate Terminal Pathname
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#if defined(RTEMS_NEWLIB)
+
+#include <stdio.h>
+#include <string.h>
+
+static char *ctermid_name = "/dev/console";
+
+char *ctermid(
+ char *s
+)
+{
+ if ( !s )
+ return ctermid_name;
+
+ strcpy( s, ctermid_name );
+ return s;
+}
+
+#endif
diff --git a/cpukit/libcsupport/src/dup.c b/cpukit/libcsupport/src/dup.c
new file mode 100644
index 0000000000..684d72d92f
--- /dev/null
+++ b/cpukit/libcsupport/src/dup.c
@@ -0,0 +1,26 @@
+/*
+ * dup() - POSIX 1003.1b 6.2.1 Duplicate an Open File Descriptor
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+#include <fcntl.h>
+
+int dup(
+ int fildes
+)
+{
+ return fcntl( fildes, F_DUPFD, 0 );
+}
diff --git a/cpukit/libcsupport/src/dup2.c b/cpukit/libcsupport/src/dup2.c
new file mode 100644
index 0000000000..15998f797c
--- /dev/null
+++ b/cpukit/libcsupport/src/dup2.c
@@ -0,0 +1,52 @@
+/*
+ * dup2() - POSIX 1003.1b 6.2.1 Duplicate an Open File Descriptor
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <rtems/libio_.h>
+
+int dup2(
+ int fildes,
+ int fildes2
+)
+{
+ int status;
+ struct stat buf;
+
+ /*
+ * If fildes is not valid, then fildes2 should not be closed.
+ */
+
+ status = fstat( fildes, &buf );
+ if ( status == -1 )
+ return -1;
+
+ /*
+ * If fildes2 is not valid, then we should not do anything either.
+ */
+
+ status = fstat( fildes2, &buf );
+ if ( status == -1 )
+ return -1;
+
+ /*
+ * This fcntl handles everything else.
+ */
+
+ return fcntl( fildes, F_DUPFD, fildes2 );
+}
diff --git a/cpukit/libcsupport/src/envlock.c b/cpukit/libcsupport/src/envlock.c
new file mode 100644
index 0000000000..687eb32753
--- /dev/null
+++ b/cpukit/libcsupport/src/envlock.c
@@ -0,0 +1,108 @@
+/*
+ * Author: Till Straumann <strauman@slac.stanford.edu>, 3/2002
+ *
+ * $Id$
+ */
+
+/* provide locking for the global environment 'environ' */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <sys/reent.h>
+
+#include <assert.h>
+
+/*
+ * NOTES:
+ * - although it looks like a classical multiple-readers / single writer (MRSW)
+ * locking problem, we still use a single lock for the following reasons:
+ * 1) newlib has no provision / hook for calling different locking routines
+ * from setenv/putenv and getenv, respectively.
+ * 2) MRSW involves calling several semaphore-primitives, even in the most
+ * likely case of a first-reader's access. This probably takes more CPU
+ * time than just waiting until another reader is done; environment
+ * access is fast.
+ * - the lock implementation must allow nesting (same thread may call
+ * lock-lock-unlock-unlock).
+ * - NEWLIB-1.8.2 has an ugly BUG: if environ is NULL, _findenv_r() bails
+ * out leaving the lock held :-(
+ *
+ * Used by the following functions:
+ * findenv_r(), setenv_r(), and unsetenv_r() which are called by
+ * getenv(), getenv_r(), setenv(), and unsetenv().
+ *
+ */
+
+#if defined(ENVLOCK_DEDIDCATED_MUTEX)
+static rtems_id envLock=0;
+
+static void
+__rtems_envlock_init(void)
+{
+ extern char **environ;
+ rtems_status_code rc;
+
+ if (envLock) /* already initialized */
+ return;
+
+ assert(environ && "MUST have non-NULL 'environ' due to newlib bug");
+
+ rc = rtems_semaphore_create(
+ rtems_build_name('E','N','V','S'),
+ 1,
+ RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY,
+ 0,
+ &envLock);
+ if (RTEMS_SUCCESSFUL!=rc)
+ rtems_fatal_error_occurred(rc);
+}
+
+void
+__env_lock(struct _reent *r)
+{
+ /* Do lazy init */
+ if (!envLock)
+ __rtems_envlock_init();
+ /*
+ * Must not use a semaphore before pre-tasking hook is called.
+ * - it will corrupt memory :-(
+ */
+
+ if (_Thread_Executing)
+ rtems_semaphore_obtain(envLock, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+}
+
+void
+__env_unlock(struct _reent *r)
+{
+ /*
+ * Must not use a semaphore before pre-tasking hook is called.
+ * - it will corrupt memory :-(
+ */
+ if (_Thread_Executing)
+ rtems_semaphore_release(envLock);
+}
+#else
+
+/*
+ * Reuse the libio mutex -- it is always initialized before we
+ * could possibly run.
+ */
+
+#include <rtems/libio_.h>
+
+void
+__env_lock(struct _reent *r)
+{
+ rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
+}
+
+void
+__env_unlock(struct _reent *r)
+{
+ rtems_semaphore_release( rtems_libio_semaphore );
+}
+#endif
diff --git a/cpukit/libcsupport/src/error.c b/cpukit/libcsupport/src/error.c
new file mode 100644
index 0000000000..c004c3a63f
--- /dev/null
+++ b/cpukit/libcsupport/src/error.c
@@ -0,0 +1,213 @@
+/*
+ * report errors and panics to RTEMS' stderr.
+ * Currently just used by RTEMS monitor.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ * These routines provide general purpose error reporting.
+ * rtems_error reports an error to stderr and allows use of
+ * printf style formatting. A newline is appended to all messages.
+ *
+ * error_flag can be specified as any of the following:
+ *
+ * RTEMS_ERROR_ERRNO -- include errno text in output
+ * RTEMS_ERROR_PANIC -- halts local system after output
+ * RTEMS_ERROR_ABORT -- abort after output
+ *
+ * It can also include a rtems_status value which can be OR'd
+ * with the above flags. *
+ *
+ * EXAMPLE
+ * #include <rtems.h>
+ * #include <rtems/error.h>
+ * rtems_error(0, "stray interrupt %d", intr);
+ *
+ * EXAMPLE
+ * if ((status = rtems_task_create(...)) != RTEMS_SUCCCESSFUL)
+ * {
+ * rtems_error(status | RTEMS_ERROR_ABORT,
+ * "could not create task");
+ * }
+ *
+ * EXAMPLE
+ * if ((fd = open(pathname, O_RDNLY)) < 0)
+ * {
+ * rtems_error(RTEMS_ERROR_ERRNO, "open of '%s' failed", pathname);
+ * goto failed;
+ * }
+ */
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#include <rtems.h>
+
+#include <rtems/error.h>
+#include <rtems/assoc.h>
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h> /* _exit() */
+
+/* bug in hpux <errno.h>: no prototypes unless you are C++ */
+#ifdef hpux9
+char *strerror(int);
+#endif
+
+extern char *rtems_progname;
+int rtems_panic_in_progress;
+
+rtems_assoc_t rtems_status_assoc[] = {
+ { "successful completion", RTEMS_SUCCESSFUL, },
+ { "returned from a thread", RTEMS_TASK_EXITTED, },
+ { "multiprocessing not configured", RTEMS_MP_NOT_CONFIGURED, },
+ { "invalid object name", RTEMS_INVALID_NAME, },
+ { "invalid object id", RTEMS_INVALID_ID, },
+ { "too many", RTEMS_TOO_MANY, },
+ { "timed out waiting", RTEMS_TIMEOUT, },
+ { "object deleted while waiting", RTEMS_OBJECT_WAS_DELETED, },
+ { "specified size was invalid", RTEMS_INVALID_SIZE, },
+ { "address specified is invalid", RTEMS_INVALID_ADDRESS, },
+ { "number was invalid", RTEMS_INVALID_NUMBER, },
+ { "item has not been initialized", RTEMS_NOT_DEFINED, },
+ { "resources still outstanding", RTEMS_RESOURCE_IN_USE, },
+ { "request not satisfied", RTEMS_UNSATISFIED, },
+ { "thread is in wrong state", RTEMS_INCORRECT_STATE, },
+ { "thread already in state", RTEMS_ALREADY_SUSPENDED, },
+ { "illegal on calling thread", RTEMS_ILLEGAL_ON_SELF, },
+ { "illegal for remote object", RTEMS_ILLEGAL_ON_REMOTE_OBJECT, },
+ { "called from wrong environment", RTEMS_CALLED_FROM_ISR, },
+ { "invalid thread priority", RTEMS_INVALID_PRIORITY, },
+ { "invalid date/time", RTEMS_INVALID_CLOCK, },
+ { "invalid node id", RTEMS_INVALID_NODE, },
+ { "directive not configured", RTEMS_NOT_CONFIGURED, },
+ { "not owner of resource", RTEMS_NOT_OWNER_OF_RESOURCE , },
+ { "directive not implemented", RTEMS_NOT_IMPLEMENTED, },
+ { "RTEMS inconsistency detected", RTEMS_INTERNAL_ERROR, },
+ { "could not get enough memory", RTEMS_NO_MEMORY, },
+ { "driver IO error", RTEMS_IO_ERROR, },
+ { "internal multiprocessing only", THREAD_STATUS_PROXY_BLOCKING, },
+ { 0, 0, 0 },
+};
+
+
+const char *
+rtems_status_text(
+ rtems_status_code status
+)
+{
+ return rtems_assoc_name_by_local(rtems_status_assoc, status);
+}
+
+
+static int rtems_verror(
+ uint32_t error_flag,
+ const char *printf_format,
+ va_list arglist
+)
+{
+ int local_errno = 0;
+ int chars_written = 0;
+ rtems_status_code status;
+
+ if (error_flag & RTEMS_ERROR_PANIC)
+ {
+ if (rtems_panic_in_progress++)
+ _Thread_Disable_dispatch(); /* disable task switches */
+
+ /* don't aggravate things */
+ if (rtems_panic_in_progress > 2)
+ return 0;
+ }
+
+ (void) fflush(stdout); /* in case stdout/stderr same */
+
+ status = error_flag & ~RTEMS_ERROR_MASK;
+ if (error_flag & RTEMS_ERROR_ERRNO) /* include errno? */
+ local_errno = errno;
+
+ if (_System_state_Is_multiprocessing)
+ fprintf(stderr, "[%d] ", _Configuration_MP_table->node);
+
+ if (rtems_progname && *rtems_progname)
+ chars_written += fprintf(stderr, "%s: ", rtems_progname);
+ chars_written += vfprintf(stderr, printf_format, arglist);
+
+ if (status)
+ chars_written += fprintf(stderr, " (status: %s)", rtems_status_text(status));
+
+ if (local_errno)
+ {
+ if ((local_errno > 0) && *strerror(local_errno))
+ chars_written += fprintf(stderr, " (errno: %s)", strerror(local_errno));
+ else
+ chars_written += fprintf(stderr, " (unknown errno=%d)", local_errno);
+ }
+
+ chars_written += fprintf(stderr, "\n");
+
+ (void) fflush(stderr);
+
+ if (error_flag & (RTEMS_ERROR_PANIC | RTEMS_ERROR_ABORT))
+ {
+ if (error_flag & RTEMS_ERROR_PANIC)
+ {
+ rtems_error(0, "fatal error, exiting");
+ _exit(local_errno);
+ }
+ else
+ {
+ rtems_error(0, "fatal error, aborting");
+ abort();
+ }
+ }
+ return chars_written;
+}
+
+
+/*
+ * Report an error.
+ * error_flag is as above; printf_format is a normal
+ * printf(3) format string, with its concommitant arguments.
+ *
+ * Returns the number of characters written.
+ */
+
+int rtems_error(
+ int error_flag,
+ const char *printf_format,
+ ...
+ )
+{
+ va_list arglist;
+ int chars_written;
+
+ va_start(arglist, printf_format);
+ chars_written = rtems_verror(error_flag, printf_format, arglist);
+ va_end(arglist);
+
+ return chars_written;
+}
+
+/*
+ * rtems_panic is shorthand for rtems_error(RTEMS_ERROR_PANIC, ...)
+ */
+
+void rtems_panic(
+ const char *printf_format,
+ ...
+ )
+{
+ va_list arglist;
+
+ va_start(arglist, printf_format);
+ (void) rtems_verror(RTEMS_ERROR_PANIC, printf_format, arglist);
+ va_end(arglist);
+}
diff --git a/cpukit/libcsupport/src/eval.c b/cpukit/libcsupport/src/eval.c
new file mode 100644
index 0000000000..7c9c0a7e47
--- /dev/null
+++ b/cpukit/libcsupport/src/eval.c
@@ -0,0 +1,123 @@
+/*
+ * rtems_filesystem_evaluate_path()
+ *
+ * Routine to seed the evaluate path routine.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int rtems_filesystem_evaluate_path(
+ const char *pathname,
+ int flags,
+ rtems_filesystem_location_info_t *pathloc,
+ int follow_link
+)
+{
+ int i;
+ int result;
+ rtems_filesystem_node_types_t type;
+
+ /*
+ * Verify Input parameters.
+ */
+
+ if ( !pathname )
+ rtems_set_errno_and_return_minus_one( EFAULT );
+
+ if ( !pathloc )
+ rtems_set_errno_and_return_minus_one( EIO ); /* should never happen */
+
+ /*
+ * Evaluate the path using the optable evalpath.
+ */
+
+ rtems_filesystem_get_start_loc( pathname, &i, pathloc );
+
+ if ( !pathloc->ops->evalpath_h )
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+
+ result = (*pathloc->ops->evalpath_h)( &pathname[i], flags, pathloc );
+
+ /*
+ * Get the Node type and determine if you need to follow the link or
+ * not.
+ */
+
+ if ( (result == 0) && follow_link ) {
+
+ if ( !pathloc->ops->node_type_h ){
+ rtems_filesystem_freenode( pathloc );
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+ }
+
+ type = (*pathloc->ops->node_type_h)( pathloc );
+
+ if ( ( type == RTEMS_FILESYSTEM_HARD_LINK ) ||
+ ( type == RTEMS_FILESYSTEM_SYM_LINK ) ) {
+
+ if ( !pathloc->ops->eval_link_h ){
+ rtems_filesystem_freenode( pathloc );
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+ }
+
+ /* what to do with the valid node pathloc points to
+ * if eval_link_h fails?
+ * Let the FS implementation deal with this case. It
+ * should probably free pathloc in either case:
+ * - if the link evaluation fails, it must free the
+ * original (valid) pathloc because we are going
+ * to return -1 and hence the FS generics won't
+ * cleanup pathloc.
+ * - if the link evaluation is successful, the updated
+ * pathloc will be passed up (and eventually released).
+ * Hence, the (valid) originial node that we submit to
+ * eval_link_h() should be released by the handler.
+ */
+
+ result = (*pathloc->ops->eval_link_h)( pathloc, flags );
+
+ }
+ }
+
+ return result;
+}
+
+
+int rtems_filesystem_evaluate_parent(
+ int flags,
+ rtems_filesystem_location_info_t *pathloc
+)
+{
+ rtems_filesystem_location_info_t parent;
+ int result;
+
+ if ( !pathloc )
+ rtems_set_errno_and_return_minus_one( EIO ); /* should never happen */
+
+ if ( !pathloc->ops->evalpath_h )
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+
+ parent = *pathloc;
+ result = (*pathloc->ops->evalpath_h)( "..", flags, &parent );
+ if (result != 0){
+ return -1;
+ }
+ rtems_filesystem_freenode( &parent );
+
+ return result;
+}
diff --git a/cpukit/libcsupport/src/fchdir.c b/cpukit/libcsupport/src/fchdir.c
new file mode 100644
index 0000000000..603288614d
--- /dev/null
+++ b/cpukit/libcsupport/src/fchdir.c
@@ -0,0 +1,90 @@
+/*
+ * fchdir() - compatible with SVr4, 4.4BSD and X/OPEN - Change Directory
+ *
+ * COPYRIGHT (c) 1989-2000.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int fchdir(
+ int fd
+)
+{
+ rtems_libio_t *iop;
+ rtems_filesystem_location_info_t loc, saved;
+
+ rtems_libio_check_fd( fd );
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_is_open(iop);
+
+ /*
+ * Now process the fchmod().
+ */
+
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_READ );
+
+ /*
+ * Verify you can change directory into this node.
+ */
+
+ if ( !iop->pathinfo.ops ) {
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+ }
+
+ if ( !iop->pathinfo.ops->node_type_h ) {
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+ }
+
+ if ( (*iop->pathinfo.ops->node_type_h)( &iop->pathinfo ) !=
+ RTEMS_FILESYSTEM_DIRECTORY ) {
+ rtems_set_errno_and_return_minus_one( ENOTDIR );
+ }
+
+
+ /*
+ * FIXME : I feel there should be another call to
+ * actually take into account the extra reference to
+ * this node which we are making here. I can
+ * see the freenode interface but do not see
+ * allocnode node interface. It maybe node_type.
+ *
+ * FIXED: T.Straumann: it is evaluate_path()
+ * but note the race condition. Threads who
+ * share their rtems_filesystem_current better
+ * be synchronized!
+ */
+
+ saved = rtems_filesystem_current;
+ rtems_filesystem_current = iop->pathinfo;
+
+ /* clone the current node */
+ if (rtems_filesystem_evaluate_path(".", 0, &loc, 0)) {
+ /* cloning failed; restore original and bail out */
+ rtems_filesystem_current = saved;
+ return -1;
+ }
+ /* release the old one */
+ rtems_filesystem_freenode( &saved );
+
+ rtems_filesystem_current = loc;
+
+ return 0;
+}
diff --git a/cpukit/libcsupport/src/fchmod.c b/cpukit/libcsupport/src/fchmod.c
new file mode 100644
index 0000000000..11d9c0e723
--- /dev/null
+++ b/cpukit/libcsupport/src/fchmod.c
@@ -0,0 +1,48 @@
+/*
+ * fchmod() - POSIX 1003.1b 5.6.4 - Change File Modes
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int fchmod(
+ int fd,
+ mode_t mode
+)
+{
+ rtems_libio_t *iop;
+
+ rtems_libio_check_fd( fd );
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_is_open(iop);
+
+ /*
+ * Now process the fchmod().
+ */
+
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ if ( !iop->handlers->fchmod_h )
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->pathinfo.handlers->fchmod_h)( &iop->pathinfo, mode );
+}
diff --git a/cpukit/libcsupport/src/fcntl.c b/cpukit/libcsupport/src/fcntl.c
new file mode 100644
index 0000000000..641c25b1ae
--- /dev/null
+++ b/cpukit/libcsupport/src/fcntl.c
@@ -0,0 +1,188 @@
+/*
+ * fcntl() - POSIX 1003.1b 6.5.2 - File Control
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/libio_.h>
+
+static int vfcntl(
+ int fd,
+ int cmd,
+ va_list ap
+)
+{
+ rtems_libio_t *iop;
+ rtems_libio_t *diop;
+ int fd2;
+ int flags;
+ int mask;
+ int ret = 0;
+
+ rtems_libio_check_fd( fd );
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_is_open(iop);
+
+ /*
+ * Now process the fcntl().
+ */
+
+ /*
+ * This switch should contain all the cases from POSIX.
+ */
+
+ switch ( cmd ) {
+ case F_DUPFD: /* dup */
+ fd2 = va_arg( ap, int );
+ if ( fd2 )
+ diop = rtems_libio_iop( fd2 );
+ else {
+ /* allocate a file control block */
+ diop = rtems_libio_allocate();
+ if ( diop == 0 ) {
+ ret = -1;
+ break;
+ }
+ }
+
+ diop->handlers = iop->handlers;
+ diop->file_info = iop->file_info;
+ diop->flags = iop->flags;
+ diop->pathinfo = iop->pathinfo;
+ ret = (int) (diop - rtems_libio_iops);
+ break;
+
+ case F_GETFD: /* get f_flags */
+ ret = ((iop->flags & LIBIO_FLAGS_CLOSE_ON_EXEC) != 0);
+ break;
+
+ case F_SETFD: /* set f_flags */
+ /*
+ * Interpret the third argument as the "close on exec()" flag.
+ * If this argument is 1, then the file descriptor is to be closed
+ * if a new process is exec()'ed. Since RTEMS does not support
+ * processes, then we can ignore this one except to make
+ * F_GETFD work.
+ */
+
+ if ( va_arg( ap, int ) )
+ iop->flags |= LIBIO_FLAGS_CLOSE_ON_EXEC;
+ else
+ iop->flags &= ~LIBIO_FLAGS_CLOSE_ON_EXEC;
+ break;
+
+ case F_GETFL: /* more flags (cloexec) */
+ ret = rtems_libio_to_fcntl_flags( iop->flags );
+ break;
+
+ case F_SETFL:
+ flags = rtems_libio_fcntl_flags( va_arg( ap, int ) );
+ mask = LIBIO_FLAGS_NO_DELAY | LIBIO_FLAGS_APPEND;
+
+ /*
+ * XXX If we are turning on append, should we seek to the end?
+ */
+
+ iop->flags = (iop->flags & ~mask) | (flags & mask);
+ break;
+
+ case F_GETLK:
+ errno = ENOTSUP;
+ ret = -1;
+ break;
+
+ case F_SETLK:
+ errno = ENOTSUP;
+ ret = -1;
+ break;
+
+ case F_SETLKW:
+ errno = ENOTSUP;
+ ret = -1;
+ break;
+
+ case F_SETOWN: /* for sockets. */
+ errno = ENOTSUP;
+ ret = -1;
+ break;
+
+ case F_GETOWN: /* for sockets. */
+ errno = ENOTSUP;
+ ret = -1;
+ break;
+
+ default:
+ errno = EINVAL;
+ ret = -1;
+ break;
+ }
+
+ /*
+ * If we got this far successfully, then we give the optional
+ * filesystem specific handler a chance to process this.
+ */
+
+ if (ret >= 0) {
+ if (iop->handlers->fcntl_h) {
+ int err = (*iop->handlers->fcntl_h)( cmd, iop );
+ if (err) {
+ errno = err;
+ ret = -1;
+ }
+ }
+ }
+ return ret;
+}
+
+int fcntl(
+ int fd,
+ int cmd,
+ ...
+)
+{
+ int ret;
+ va_list ap;
+ va_start( ap, cmd );
+ ret = vfcntl(fd,cmd,ap);
+ va_end(ap);
+ return ret;
+}
+
+
+/*
+ * _fcntl_r
+ *
+ * This is the Newlib dependent reentrant version of fcntl().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+int _fcntl_r(
+ struct _reent *ptr,
+ int fd,
+ int cmd,
+ int arg
+)
+{
+ return fcntl( fd, cmd, arg );
+}
+#endif
diff --git a/cpukit/libcsupport/src/fdatasync.c b/cpukit/libcsupport/src/fdatasync.c
new file mode 100644
index 0000000000..c2b4db43ae
--- /dev/null
+++ b/cpukit/libcsupport/src/fdatasync.c
@@ -0,0 +1,42 @@
+/*
+ * fdatasync() - POSIX 1003.1b 6.6.2 - Synchronize the Data of a File
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int fdatasync(
+ int fd
+)
+{
+ rtems_libio_t *iop;
+
+ rtems_libio_check_fd( fd );
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_is_open(iop);
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ /*
+ * Now process the fdatasync().
+ */
+
+ if ( !iop->handlers->fdatasync_h )
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->handlers->fdatasync_h)( iop );
+}
diff --git a/cpukit/libcsupport/src/fpathconf.c b/cpukit/libcsupport/src/fpathconf.c
new file mode 100644
index 0000000000..accaae1585
--- /dev/null
+++ b/cpukit/libcsupport/src/fpathconf.c
@@ -0,0 +1,87 @@
+/*
+ * fpathconf() - POSIX 1003.1b - 5.7.1 - Configurable Pathname Varables
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+#include <unistd.h>
+#include <errno.h>
+
+long fpathconf(
+ int fd,
+ int name
+)
+{
+ long return_value;
+ rtems_libio_t *iop;
+ rtems_filesystem_limits_and_options_t *the_limits;
+
+ rtems_libio_check_fd(fd);
+ iop = rtems_libio_iop(fd);
+ rtems_libio_check_is_open(iop);
+ rtems_libio_check_permissions(iop, LIBIO_FLAGS_READ);
+
+ /*
+ * Now process the information request.
+ */
+
+ the_limits = &iop->pathinfo.mt_entry->pathconf_limits_and_options;
+
+ switch ( name ) {
+ case _PC_LINK_MAX:
+ return_value = the_limits->link_max;
+ break;
+ case _PC_MAX_CANON:
+ return_value = the_limits->max_canon;
+ break;
+ case _PC_MAX_INPUT:
+ return_value = the_limits->max_input;
+ break;
+ case _PC_NAME_MAX:
+ return_value = the_limits->name_max;
+ break;
+ case _PC_PATH_MAX:
+ return_value = the_limits->path_max;
+ break;
+ case _PC_PIPE_BUF:
+ return_value = the_limits->pipe_buf;
+ break;
+ case _PC_CHOWN_RESTRICTED:
+ return_value = the_limits->posix_chown_restrictions;
+ break;
+ case _PC_NO_TRUNC:
+ return_value = the_limits->posix_no_trunc;
+ break;
+ case _PC_VDISABLE:
+ return_value = the_limits->posix_vdisable;
+ break;
+ case _PC_ASYNC_IO:
+ return_value = the_limits->posix_async_io;
+ break;
+ case _PC_PRIO_IO:
+ return_value = the_limits->posix_prio_io;
+ break;
+ case _PC_SYNC_IO:
+ return_value = the_limits->posix_sync_io;
+ break;
+ default:
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ break;
+ }
+
+ return return_value;
+}
diff --git a/cpukit/libcsupport/src/fs_null_handlers.c b/cpukit/libcsupport/src/fs_null_handlers.c
new file mode 100644
index 0000000000..fb323d7452
--- /dev/null
+++ b/cpukit/libcsupport/src/fs_null_handlers.c
@@ -0,0 +1,41 @@
+/*
+ * Null Filesystem Operations Tables
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+
+#include <rtems/libio.h>
+
+/*
+ * Set of null operations handlers.
+ */
+
+rtems_filesystem_file_handlers_r rtems_filesystem_null_handlers = {
+ NULL, /* open */
+ NULL, /* close */
+ NULL, /* read */
+ NULL, /* write */
+ NULL, /* ioctl */
+ NULL, /* lseek */
+ NULL, /* fstat */
+ NULL, /* fchmod */
+ NULL, /* ftruncate */
+ NULL, /* fpathconf */
+ NULL, /* fsync */
+ NULL, /* fdatasync */
+ NULL, /* fcntl */
+ NULL /* rmnod */
+};
diff --git a/cpukit/libcsupport/src/fstat.c b/cpukit/libcsupport/src/fstat.c
new file mode 100644
index 0000000000..e388544f93
--- /dev/null
+++ b/cpukit/libcsupport/src/fstat.c
@@ -0,0 +1,80 @@
+/*
+ * fstat() - POSIX 1003.1b 5.6.2 - Get File Status
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int fstat(
+ int fd,
+ struct stat *sbuf
+)
+{
+ rtems_libio_t *iop;
+
+ /*
+ * Check to see if we were passed a valid pointer.
+ */
+
+ if ( !sbuf )
+ rtems_set_errno_and_return_minus_one( EFAULT );
+
+ /*
+ * Now process the stat() request.
+ */
+
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_fd( fd );
+ rtems_libio_check_is_open(iop);
+
+ if ( !iop->handlers )
+ rtems_set_errno_and_return_minus_one( EBADF );
+
+ if ( !iop->handlers->fstat_h )
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+
+ /*
+ * Zero out the stat structure so the various support
+ * versions of stat don't have to.
+ */
+ memset( sbuf, 0, sizeof(struct stat) );
+
+ return (*iop->handlers->fstat_h)( &iop->pathinfo, sbuf );
+}
+
+/*
+ * _fstat_r
+ *
+ * This is the Newlib dependent reentrant version of fstat().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+int _fstat_r(
+ struct _reent *ptr,
+ int fd,
+ struct stat *buf
+)
+{
+ return fstat( fd, buf );
+}
+#endif
diff --git a/cpukit/libcsupport/src/fsync.c b/cpukit/libcsupport/src/fsync.c
new file mode 100644
index 0000000000..cfd8e8d49b
--- /dev/null
+++ b/cpukit/libcsupport/src/fsync.c
@@ -0,0 +1,45 @@
+/*
+ * fsync() - POSIX 1003.1b 6.6.1 - Synchronize the State of a File
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int fsync(
+ int fd
+)
+{
+ rtems_libio_t *iop;
+
+ rtems_libio_check_fd( fd );
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_is_open(iop);
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ /*
+ * Now process the fsync().
+ */
+
+ if ( !iop->handlers )
+ rtems_set_errno_and_return_minus_one( EBADF );
+
+ if ( !iop->handlers->fsync_h )
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->handlers->fsync_h)( iop );
+}
diff --git a/cpukit/libcsupport/src/ftruncate.c b/cpukit/libcsupport/src/ftruncate.c
new file mode 100644
index 0000000000..6619ca5f74
--- /dev/null
+++ b/cpukit/libcsupport/src/ftruncate.c
@@ -0,0 +1,57 @@
+/*
+ * ftruncate() - Truncate a File to the Specified Length
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+#include <errno.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int ftruncate(
+ int fd,
+ off_t length
+)
+{
+ rtems_libio_t *iop;
+ rtems_filesystem_location_info_t loc;
+
+ rtems_libio_check_fd( fd );
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_is_open(iop);
+
+ /*
+ * Now process the ftruncate() request.
+ */
+
+ /*
+ * Make sure we are not working on a directory
+ */
+
+ loc = iop->pathinfo;
+ if ( !loc.ops->node_type_h )
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+
+ if ( (*loc.ops->node_type_h)( &loc ) == RTEMS_FILESYSTEM_DIRECTORY )
+ rtems_set_errno_and_return_minus_one( EISDIR );
+
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ if ( !iop->handlers->ftruncate_h )
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->handlers->ftruncate_h)( iop, length );
+}
diff --git a/cpukit/libcsupport/src/getcwd.c b/cpukit/libcsupport/src/getcwd.c
new file mode 100644
index 0000000000..fdde4eea81
--- /dev/null
+++ b/cpukit/libcsupport/src/getcwd.c
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 1989, 1991 The Regents of the University of California.
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * Copied from newlib 1.8.1. RTEMS can not build all of the contents
+ * of the UNIX directory but we need this routine.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ * Added these when moved to RTEMS
+ */
+
+#define _stat stat
+#define _opendir opendir
+#define _fstat fstat
+#define _readdir readdir
+#define _closedir closedir
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getcwd.c 5.11 (Berkeley) 2/24/91";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/stat.h>
+#include <errno.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <reent.h>
+#include <_syslist.h>
+
+#define bcopy(a,b,c) memmove (b,a,c)
+
+#define ISDOT(dp) \
+ (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || \
+ (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
+
+#ifndef _REENT_ONLY
+
+char *
+getcwd (pt, size)
+ char *pt;
+ size_t size;
+{
+ register struct dirent *dp;
+ register DIR *dir = 0;
+ register dev_t dev;
+ register ino_t ino;
+ register int first;
+ register char *bpt, *bup;
+ struct stat s;
+ dev_t root_dev;
+ ino_t root_ino;
+ size_t ptsize, upsize;
+ int save_errno;
+ char *ept, *eup, *up;
+
+ /*
+ * If no buffer specified by the user, allocate one as necessary.
+ * If a buffer is specified, the size has to be non-zero. The path
+ * is built from the end of the buffer backwards.
+ */
+
+ if (pt)
+ {
+ ptsize = 0;
+ if (!size)
+ {
+ errno = EINVAL;
+ return (char *) NULL;
+ }
+ ept = pt + size;
+ }
+ else
+ {
+ if (!(pt = (char *) malloc (ptsize = 1024 - 4)))
+ {
+ return (char *) NULL;
+ }
+ ept = pt + ptsize;
+ }
+ bpt = ept - 1;
+ *bpt = '\0';
+
+ /*
+ * Allocate bytes (1024 - malloc space) for the string of "../"'s.
+ * Should always be enough (it's 340 levels). If it's not, allocate
+ * as necessary. Special * case the first stat, it's ".", not "..".
+ */
+
+ if (!(up = (char *) malloc (upsize = 1024 - 4)))
+ {
+ goto err;
+ }
+ eup = up + MAXPATHLEN;
+ bup = up;
+ up[0] = '.';
+ up[1] = '\0';
+
+ /* Save root values, so know when to stop. */
+ if (stat ("/", &s))
+ goto err;
+ root_dev = s.st_dev;
+ root_ino = s.st_ino;
+
+ errno = 0; /* XXX readdir has no error return. */
+
+ for (first = 1;; first = 0)
+ {
+ /* Stat the current level. */
+ if (_stat (up, &s))
+ goto err;
+
+ /* Save current node values. */
+ ino = s.st_ino;
+ dev = s.st_dev;
+
+ /* Check for reaching root. */
+ if (root_dev == dev && root_ino == ino)
+ {
+ *--bpt = '/';
+ /*
+ * It's unclear that it's a requirement to copy the
+ * path to the beginning of the buffer, but it's always
+ * been that way and stuff would probably break.
+ */
+ (void) bcopy (bpt, pt, ept - bpt);
+ free (up);
+ return pt;
+ }
+
+ /*
+ * Build pointer to the parent directory, allocating memory
+ * as necessary. Max length is 3 for "../", the largest
+ * possible component name, plus a trailing NULL.
+ */
+
+ if (bup + 3 + MAXNAMLEN + 1 >= eup)
+ {
+ if (!(up = (char *) realloc (up, upsize *= 2)))
+ {
+ goto err;
+ }
+ bup = up;
+ eup = up + upsize;
+ }
+ *bup++ = '.';
+ *bup++ = '.';
+ *bup = '\0';
+
+ /* Open and stat parent directory. */
+ if (!(dir = _opendir (up)) || _fstat (__dirfd (dir), &s))
+ goto err;
+
+ /* Add trailing slash for next directory. */
+ *bup++ = '/';
+
+ /*
+ * If it's a mount point, have to stat each element because
+ * the inode number in the directory is for the entry in the
+ * parent directory, not the inode number of the mounted file.
+ */
+
+ save_errno = 0;
+ if (s.st_dev == dev)
+ {
+ for (;;)
+ {
+ if (!(dp = _readdir (dir)))
+ goto notfound;
+ if (dp->d_ino == ino)
+ break;
+ }
+ }
+ else
+ for (;;)
+ {
+ if (!(dp = _readdir (dir)))
+ goto notfound;
+ if (ISDOT (dp))
+ continue;
+ bcopy (dp->d_name, bup, strlen (dp->d_name) + 1);
+
+ /* Save the first error for later. */
+ if (stat (up, &s))
+ {
+ if (!save_errno)
+ save_errno = errno;
+ errno = 0;
+ continue;
+ }
+ if (s.st_dev == dev && s.st_ino == ino)
+ break;
+ }
+
+ /*
+ * Check for length of the current name, preceding slash,
+ * leading slash.
+ */
+
+ if (bpt - pt <= strlen (dp->d_name) + (first ? 1 : 2))
+ {
+ size_t len, off;
+
+ if (!ptsize)
+ {
+ errno = ERANGE;
+ goto err;
+ }
+ off = bpt - pt;
+ len = ept - bpt;
+ if (!(pt = (char *) realloc (pt, ptsize *= 2)))
+ {
+ goto err;
+ }
+ bpt = pt + off;
+ ept = pt + ptsize;
+ (void) bcopy (bpt, ept - len, len);
+ bpt = ept - len;
+ }
+ if (!first)
+ *--bpt = '/';
+ bpt -= strlen (dp->d_name);
+ bcopy (dp->d_name, bpt, strlen (dp->d_name));
+ (void) _closedir (dir);
+ dir = 0;
+
+ /* Truncate any file name. */
+ *bup = '\0';
+ }
+
+notfound:
+ /*
+ * If readdir set errno, use it, not any saved error; otherwise,
+ * didn't find the current directory in its parent directory, set
+ * errno to ENOENT.
+ */
+
+ if (!errno)
+ errno = save_errno ? save_errno : ENOENT;
+ /* FALLTHROUGH */
+
+err:
+ if(dir)
+ (void) _closedir (dir);
+ if (ptsize)
+ free (pt);
+ free (up);
+ return (char *) NULL;
+}
+
+#endif /* _REENT_ONLY */
diff --git a/cpukit/libcsupport/src/getdents.c b/cpukit/libcsupport/src/getdents.c
new file mode 100644
index 0000000000..ca4c36727f
--- /dev/null
+++ b/cpukit/libcsupport/src/getdents.c
@@ -0,0 +1,63 @@
+/*
+ * getdents() - Get Directory Entries
+ *
+ * SVR4 and SVID extension required by Newlib readdir() family.
+ *
+ * This routine will dd_len / (sizeof dirent) directory entries relative to
+ * the current directory position index. These entries will be placed in
+ * character array pointed to by -dd_buf-
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int getdents(
+ int dd_fd,
+ char *dd_buf,
+ int dd_len
+)
+{
+ rtems_libio_t *iop;
+ rtems_filesystem_location_info_t loc;
+
+ /*
+ * Get the file control block structure associated with the file descriptor
+ */
+
+ iop = rtems_libio_iop( dd_fd );
+
+ /*
+ * Make sure we are working on a directory
+ */
+ loc = iop->pathinfo;
+ if ( !loc.ops->node_type_h )
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+
+ if ( (*loc.ops->node_type_h)( &loc ) != RTEMS_FILESYSTEM_DIRECTORY )
+ rtems_set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Return the number of bytes that were actually transfered as a result
+ * of the read attempt.
+ */
+
+ if ( !iop->handlers->read_h )
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+
+ return (*iop->handlers->read_h)( iop, dd_buf, dd_len );
+}
diff --git a/cpukit/libcsupport/src/getegid.c b/cpukit/libcsupport/src/getegid.c
new file mode 100644
index 0000000000..4da7ba8d5b
--- /dev/null
+++ b/cpukit/libcsupport/src/getegid.c
@@ -0,0 +1,32 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <limits.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/seterr.h>
+#include <rtems/userenv.h>
+
+/*
+ * MACRO in userenv.h
+gid_t _POSIX_types_Egid = 0;
+*/
+
+/*PAGE
+ *
+ * 4.2.1 Get Real User, Effective User, Ral Group, and Effective Group IDs,
+ * P1003.1b-1993, p. 84
+ */
+
+gid_t getegid( void )
+{
+ return _POSIX_types_Egid;
+}
diff --git a/cpukit/libcsupport/src/geteuid.c b/cpukit/libcsupport/src/geteuid.c
new file mode 100644
index 0000000000..cb5b5add79
--- /dev/null
+++ b/cpukit/libcsupport/src/geteuid.c
@@ -0,0 +1,33 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <limits.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/seterr.h>
+
+#include <rtems/userenv.h>
+
+/*
+ * MACRO in userenv.h
+uid_t _POSIX_types_Euid = 0;
+*/
+
+/*PAGE
+ *
+ * 4.2.1 Get Real User, Effective User, Ral Group, and Effective Group IDs,
+ * P1003.1b-1993, p. 84
+ */
+
+uid_t geteuid( void )
+{
+ return _POSIX_types_Euid;
+}
diff --git a/cpukit/libcsupport/src/getgid.c b/cpukit/libcsupport/src/getgid.c
new file mode 100644
index 0000000000..653445a99c
--- /dev/null
+++ b/cpukit/libcsupport/src/getgid.c
@@ -0,0 +1,47 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <limits.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/seterr.h>
+
+#include <rtems/userenv.h>
+
+/*
+ * MACRO in userenv.h
+ *
+gid_t _POSIX_types_Gid = 0;
+*/
+
+/*PAGE
+ *
+ * 4.2.1 Get Real User, Effective User, Ral Group, and Effective Group IDs,
+ * P1003.1b-1993, p. 84
+ */
+
+gid_t getgid( void )
+{
+ return _POSIX_types_Gid;
+}
+
+/*PAGE
+ *
+ * 4.2.2 Set User and Group IDs, P1003.1b-1993, p. 84
+ */
+
+int setgid(
+ gid_t gid
+)
+{
+ _POSIX_types_Gid = gid;
+ return 0;
+}
diff --git a/cpukit/libcsupport/src/getgroups.c b/cpukit/libcsupport/src/getgroups.c
new file mode 100644
index 0000000000..c902c1f79d
--- /dev/null
+++ b/cpukit/libcsupport/src/getgroups.c
@@ -0,0 +1,29 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <limits.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/seterr.h>
+
+/*PAGE
+ *
+ * 4.2.3 Get Supplementary IDs, P1003.1b-1993, p. 86
+ */
+
+int getgroups(
+ int gidsetsize,
+ gid_t grouplist[]
+)
+{
+ return 0; /* no supplemental group ids */
+}
diff --git a/cpukit/libcsupport/src/getlogin.c b/cpukit/libcsupport/src/getlogin.c
new file mode 100644
index 0000000000..06b576f234
--- /dev/null
+++ b/cpukit/libcsupport/src/getlogin.c
@@ -0,0 +1,64 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <limits.h>
+#include <string.h>
+#include <sys/types.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/seterr.h>
+#include <rtems/userenv.h>
+
+#include <unistd.h>
+#include <pwd.h>
+
+/*PAGE
+ *
+ * 4.2.4 Get User Name, P1003.1b-1993, p. 87
+ *
+ * NOTE: P1003.1c/D10, p. 49 adds getlogin_r().
+ */
+
+/*
+ * MACRO in userenv.h
+ *
+static char _POSIX_types_Getlogin_buffer[ LOGIN_NAME_MAX ];
+*/
+
+char *getlogin( void )
+{
+ (void) getlogin_r( _POSIX_types_Getlogin_buffer, LOGIN_NAME_MAX );
+ return _POSIX_types_Getlogin_buffer;
+}
+
+/*PAGE
+ *
+ * 4.2.4 Get User Name, P1003.1b-1993, p. 87
+ *
+ * NOTE: P1003.1c/D10, p. 49 adds getlogin_r().
+ */
+
+int getlogin_r(
+ char *name,
+ size_t namesize
+)
+{
+ struct passwd *pw;
+ if ( namesize < LOGIN_NAME_MAX )
+ return ERANGE;
+
+ pw=getpwuid(getuid());
+ if (!pw) {
+ strcpy(name,"");
+ } else {
+ strncpy(name,pw->pw_name,LOGIN_NAME_MAX);
+ };
+ return 0;
+}
diff --git a/cpukit/libcsupport/src/getpgrp.c b/cpukit/libcsupport/src/getpgrp.c
new file mode 100644
index 0000000000..0904d23883
--- /dev/null
+++ b/cpukit/libcsupport/src/getpgrp.c
@@ -0,0 +1,31 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <limits.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/seterr.h>
+
+/*PAGE
+ *
+ * 4.3.1 Get Process Group IDs, P1003.1b-1993, p. 89
+ */
+
+pid_t getpgrp( void )
+{
+ /*
+ * This always succeeds and returns the process group id. For rtems,
+ * this will always be the local node;
+ */
+
+ return _Objects_Local_node;
+}
diff --git a/cpukit/libcsupport/src/getpid.c b/cpukit/libcsupport/src/getpid.c
new file mode 100644
index 0000000000..0def44f140
--- /dev/null
+++ b/cpukit/libcsupport/src/getpid.c
@@ -0,0 +1,44 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <limits.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/seterr.h>
+
+/*PAGE
+ *
+ * 4.1.1 Get Process and Parent Process IDs, P1003.1b-1993, p. 83
+ */
+
+pid_t getpid( void )
+{
+ return _Objects_Local_node;
+}
+
+/*
+ * _getpid_r
+ *
+ * This is the Newlib dependent reentrant version of getpid().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+pid_t _getpid_r(
+ struct _reent *ptr
+)
+{
+ return getpid();
+}
+#endif
diff --git a/cpukit/libcsupport/src/getppid.c b/cpukit/libcsupport/src/getppid.c
new file mode 100644
index 0000000000..193d17e9da
--- /dev/null
+++ b/cpukit/libcsupport/src/getppid.c
@@ -0,0 +1,28 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <limits.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/seterr.h>
+
+pid_t _POSIX_types_Ppid = 0;
+
+/*PAGE
+ *
+ * 4.1.1 Get Process and Parent Process IDs, P1003.1b-1993, p. 83
+ */
+
+pid_t getppid( void )
+{
+ return _POSIX_types_Ppid;
+}
diff --git a/cpukit/libcsupport/src/getpwent.c b/cpukit/libcsupport/src/getpwent.c
new file mode 100644
index 0000000000..1236ccacca
--- /dev/null
+++ b/cpukit/libcsupport/src/getpwent.c
@@ -0,0 +1,443 @@
+/*
+ * POSIX 1003.1b - 9.2.2 - User Database Access Routines
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <ctype.h>
+
+#include <rtems/libio_.h>
+
+/*
+ * Static, thread-unsafe, buffers
+ */
+static FILE *passwd_fp;
+static char pwbuf[200];
+static struct passwd pwent;
+static FILE *group_fp;
+static char grbuf[200];
+static struct group grent;
+
+/*
+ * Initialize useable but dummy databases
+ */
+void init_etc_passwd_group(void)
+{
+ FILE *fp;
+ static char etc_passwd_initted = 0;
+
+ if (etc_passwd_initted)
+ return;
+ etc_passwd_initted = 1;
+ mkdir("/etc", 0777);
+
+ /*
+ * Initialize /etc/passwd
+ */
+ if ((fp = fopen("/etc/passwd", "r")) != NULL) {
+ fclose(fp);
+ }
+ else if ((fp = fopen("/etc/passwd", "w")) != NULL) {
+ fprintf(fp, "root:*:0:0:root::/:/bin/sh\n"
+ "rtems:*:1:1:RTEMS Application::/:/bin/sh\n"
+ "tty:!:2:2:tty owner::/:/bin/false\n" );
+ fclose(fp);
+ }
+
+ /*
+ * Initialize /etc/group
+ */
+ if ((fp = fopen("/etc/group", "r")) != NULL) {
+ fclose(fp);
+ }
+ else if ((fp = fopen("/etc/group", "w")) != NULL) {
+ fprintf( fp, "root:x:0:root\n"
+ "rtems:x:1:rtems\n"
+ "tty:x:2:tty\n" );
+ fclose(fp);
+ }
+}
+
+/*
+ * Extract a string value from the database
+ */
+static int
+scanString(FILE *fp, char **name, char **bufp, size_t *nleft, int nlFlag)
+{
+ int c;
+
+ *name = *bufp;
+ for (;;) {
+ c = getc(fp);
+ if (c == ':') {
+ if (nlFlag)
+ return 0;
+ break;
+ }
+ if (c == '\n') {
+ if (!nlFlag)
+ return 0;
+ break;
+ }
+ if (c == EOF)
+ return 0;
+ if (*nleft < 2)
+ return 0;
+ **bufp = c;
+ ++(*bufp);
+ --(*nleft);
+ }
+ **bufp = '\0';
+ ++(*bufp);
+ --(*nleft);
+ return 1;
+}
+
+/*
+ * Extract an integer value from the database
+ */
+static int
+scanInt(FILE *fp, int *val)
+{
+ int c;
+ unsigned int i = 0;
+ unsigned int limit = INT_MAX;
+ int sign = 0;
+ int d;
+
+ for (;;) {
+ c = getc(fp);
+ if (c == ':')
+ break;
+ if (sign == 0) {
+ if (c == '-') {
+ sign = -1;
+ limit++;
+ continue;
+ }
+ sign = 1;
+ }
+ if (!isdigit(c))
+ return 0;
+ d = c - '0';
+ if ((i > (limit / 10))
+ || ((i == (limit / 10)) && (d > (limit % 10))))
+ return 0;
+ i = i * 10 + d;
+ }
+ if (sign == 0)
+ return 0;
+ *val = i * sign;
+ return 1;
+}
+
+/*
+ * Extract a single password record from the database
+ */
+static int scanpw(
+ FILE *fp,
+ struct passwd *pwd,
+ char *buffer,
+ size_t bufsize
+)
+{
+ int pwuid, pwgid;
+
+ if (!scanString(fp, &pwd->pw_name, &buffer, &bufsize, 0)
+ || !scanString(fp, &pwd->pw_passwd, &buffer, &bufsize, 0)
+ || !scanInt(fp, &pwuid)
+ || !scanInt(fp, &pwgid)
+ || !scanString(fp, &pwd->pw_comment, &buffer, &bufsize, 0)
+ || !scanString(fp, &pwd->pw_gecos, &buffer, &bufsize, 0)
+ || !scanString(fp, &pwd->pw_dir, &buffer, &bufsize, 0)
+ || !scanString(fp, &pwd->pw_shell, &buffer, &bufsize, 1))
+ return 0;
+ pwd->pw_uid = pwuid;
+ pwd->pw_gid = pwgid;
+ return 1;
+}
+
+static int getpw_r(
+ const char *name,
+ int uid,
+ struct passwd *pwd,
+ char *buffer,
+ size_t bufsize,
+ struct passwd **result
+)
+{
+ FILE *fp;
+ int match;
+
+ init_etc_passwd_group();
+
+ if ((fp = fopen("/etc/passwd", "r")) == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+ for(;;) {
+ if (!scanpw(fp, pwd, buffer, bufsize)) {
+ errno = EINVAL;
+ fclose(fp);
+ return -1;
+ }
+ if (name) {
+ match = (strcmp(pwd->pw_name, name) == 0);
+ }
+ else {
+ match = (pwd->pw_uid == uid);
+ }
+ if (match) {
+ fclose(fp);
+ *result = pwd;
+ return 0;
+ }
+ }
+ fclose(fp);
+ errno = EINVAL;
+ return -1;
+}
+
+int getpwnam_r(
+ const char *name,
+ struct passwd *pwd,
+ char *buffer,
+ size_t bufsize,
+ struct passwd **result
+)
+{
+ return getpw_r(name, 0, pwd, buffer, bufsize, result);
+}
+
+struct passwd *getpwnam(
+ const char *name
+)
+{
+ struct passwd *p;
+
+ if(getpwnam_r(name, &pwent, pwbuf, sizeof pwbuf, &p))
+ return NULL;
+ return p;
+}
+
+int getpwuid_r(
+ uid_t uid,
+ struct passwd *pwd,
+ char *buffer,
+ size_t bufsize,
+ struct passwd **result
+)
+{
+ return getpw_r(NULL, uid, pwd, buffer, bufsize, result);
+}
+
+struct passwd *getpwuid(
+ uid_t uid
+)
+{
+ struct passwd *p;
+
+ if(getpwuid_r(uid, &pwent, pwbuf, sizeof pwbuf, &p))
+ return NULL;
+ return p;
+}
+
+struct passwd *getpwent()
+{
+ if (passwd_fp == NULL)
+ return NULL;
+ if (!scanpw(passwd_fp, &pwent, pwbuf, sizeof pwbuf))
+ return NULL;
+ return &pwent;
+}
+
+void setpwent(void)
+{
+ init_etc_passwd_group();
+
+ if (passwd_fp != NULL)
+ fclose(passwd_fp);
+ passwd_fp = fopen("/etc/passwd", "r");
+}
+
+void endpwent(void)
+{
+ if (passwd_fp != NULL)
+ fclose(passwd_fp);
+}
+
+/*
+ * Extract a single group record from the database
+ */
+static int scangr(
+ FILE *fp,
+ struct group *grp,
+ char *buffer,
+ size_t bufsize
+)
+{
+ int grgid;
+ char *grmem, *cp;
+ int memcount;
+
+ if (!scanString(fp, &grp->gr_name, &buffer, &bufsize, 0)
+ || !scanString(fp, &grp->gr_passwd, &buffer, &bufsize, 0)
+ || !scanInt(fp, &grgid)
+ || !scanString(fp, &grmem, &buffer, &bufsize, 1))
+ return 0;
+ grp->gr_gid = grgid;
+
+ /*
+ * Determine number of members
+ */
+ for (cp = grmem, memcount = 1 ; *cp != 0 ; cp++) {
+ if(*cp == ',')
+ memcount++;
+ }
+
+ /*
+ * Hack to produce (hopefully) a suitably-aligned array of pointers
+ */
+ if (bufsize < (((memcount+1)*sizeof(char *)) + 15))
+ return 0;
+ grp->gr_mem = (char **)(((unsigned long)buffer + 15) & ~15);
+
+ /*
+ * Fill in pointer array
+ */
+ grp->gr_mem[0] = grmem;
+ for (cp = grmem, memcount = 1 ; *cp != 0 ; cp++) {
+ if(*cp == ',') {
+ *cp = '\0';
+ grp->gr_mem[memcount++] = cp + 1;
+ }
+ }
+ grp->gr_mem[memcount] = NULL;
+ return 1;
+}
+
+static int getgr_r(
+ const char *name,
+ int gid,
+ struct group *grp,
+ char *buffer,
+ size_t bufsize,
+ struct group **result
+)
+{
+ FILE *fp;
+ int match;
+
+ init_etc_passwd_group();
+
+ if ((fp = fopen("/etc/group", "r")) == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+ for(;;) {
+ if (!scangr(fp, grp, buffer, bufsize)) {
+ errno = EINVAL;
+ fclose(fp);
+ return -1;
+ }
+ if (name) {
+ match = (strcmp(grp->gr_name, name) == 0);
+ }
+ else {
+ match = (grp->gr_gid == gid);
+ }
+ if (match) {
+ fclose(fp);
+ *result = grp;
+ return 0;
+ }
+ }
+ fclose(fp);
+ errno = EINVAL;
+ return -1;
+}
+
+int getgrnam_r(
+ const char *name,
+ struct group *grp,
+ char *buffer,
+ size_t bufsize,
+ struct group **result
+)
+{
+ return getgr_r(name, 0, grp, buffer, bufsize, result);
+}
+
+struct group *getgrnam(
+ const char *name
+)
+{
+ struct group *p;
+
+ if(getgrnam_r(name, &grent, grbuf, sizeof grbuf, &p))
+ return NULL;
+ return p;
+}
+
+int getgrgid_r(
+ gid_t gid,
+ struct group *grp,
+ char *buffer,
+ size_t bufsize,
+ struct group **result
+)
+{
+ return getgr_r(NULL, gid, grp, buffer, bufsize, result);
+}
+
+struct group *getgrgid(
+ gid_t gid
+)
+{
+ struct group *p;
+
+ if(getgrgid_r(gid, &grent, grbuf, sizeof grbuf, &p))
+ return NULL;
+ return p;
+}
+
+struct group *getgrent()
+{
+ if (group_fp == NULL)
+ return NULL;
+ if (!scangr(group_fp, &grent, grbuf, sizeof grbuf))
+ return NULL;
+ return &grent;
+}
+
+void setgrent(void)
+{
+ init_etc_passwd_group();
+
+ if (group_fp != NULL)
+ fclose(group_fp);
+ group_fp = fopen("/etc/group", "r");
+}
+
+void endgrent(void)
+{
+ if (group_fp != NULL)
+ fclose(group_fp);
+}
diff --git a/cpukit/libcsupport/src/getuid.c b/cpukit/libcsupport/src/getuid.c
new file mode 100644
index 0000000000..65e3184005
--- /dev/null
+++ b/cpukit/libcsupport/src/getuid.c
@@ -0,0 +1,47 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <limits.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/seterr.h>
+
+#include <rtems/userenv.h>
+
+/*
+ * MACRO in userenv.h
+ *
+uid_t _POSIX_types_Uid = 0;
+*/
+
+/*PAGE
+ *
+ * 4.2.1 Get Real User, Effective User, Ral Group, and Effective Group IDs,
+ * P1003.1b-1993, p. 84
+ */
+
+uid_t getuid( void )
+{
+ return _POSIX_types_Uid;
+}
+
+/*PAGE
+ *
+ * 4.2.2 Set User and Group IDs, P1003.1b-1993, p. 84
+ */
+
+int setuid(
+ uid_t uid
+)
+{
+ _POSIX_types_Uid = uid;
+ return 0;
+}
diff --git a/cpukit/libcsupport/src/gxx_wrappers.c b/cpukit/libcsupport/src/gxx_wrappers.c
new file mode 100644
index 0000000000..d500f3fb5e
--- /dev/null
+++ b/cpukit/libcsupport/src/gxx_wrappers.c
@@ -0,0 +1,217 @@
+/*
+ * RTEMS threads compatibily routines for libgcc2.
+ *
+ * by: Rosimildo da Silva ( rdasilva@connecttel.com
+ *
+ * Used ideas from:
+ * W. Eric Norum
+ * Canadian Light Source
+ * University of Saskatchewan
+ * Saskatoon, Saskatchewan, CANADA
+ * eric@cls.usask.ca
+ *
+ * Eric sent some e-mail in the rtems-list as a start point for this
+ * module implementation.
+ *
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* We might not need, defined just in case */
+#define __RTEMS_INSIDE__ 1
+
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <rtems.h>
+#include <rtems/system.h>
+#include <rtems/error.h> /* rtems_panic */
+#include <rtems/rtems/tasks.h>
+
+/*
+ * These typedefs should match with the ones defined in the file
+ * gcc/gthr-rtems.h in the gcc distribution.
+ */
+typedef void *__gthread_key_t;
+typedef int __gthread_once_t;
+typedef void *__gthread_mutex_t;
+
+
+/* uncomment this if you need to debug this interface */
+
+/*
+#define DEBUG_GXX_WRAPPERS 1
+*/
+
+#ifdef DEBUG_GXX_WRAPPERS
+/* local function to return the ID of the calling thread */
+static rtems_id get_tid( void )
+{
+ rtems_id id = 0;
+ rtems_task_ident( RTEMS_SELF, 0, &id );
+ return id;
+}
+#endif
+
+
+int rtems_gxx_once(__gthread_once_t *once, void (*func) (void))
+{
+#ifdef DEBUG_GXX_WRAPPERS
+ printk( "gxx_wrappers: once=%x, func=%x\n", *once, func );
+#endif
+ if( *(volatile __gthread_once_t *)once == 0 )
+ {
+ rtems_mode saveMode;
+ rtems_task_mode(RTEMS_NO_PREEMPT, RTEMS_PREEMPT_MASK, &saveMode);
+ if( *(volatile __gthread_once_t *)once == 0 )
+ {
+ *(volatile __gthread_once_t *)once = 1;
+ (*func)();
+ }
+ rtems_task_mode(saveMode, RTEMS_PREEMPT_MASK, &saveMode);
+ }
+ return 0;
+}
+
+
+int rtems_gxx_key_create (__gthread_key_t *key, void (*dtor) (void *))
+{
+ /* Ok, this can be a bit tricky. We are going to return a "key" as a
+ * pointer to the buffer that will hold the value of the key itself.
+ * We have to to this, becuase the others functions on this interface
+ * deal with the value of the key, as used with the POSIX API.
+ */
+ /* Do not pull your hair, trust me this works. :-) */
+ __gthread_key_t *new_key = ( __gthread_key_t * )malloc( sizeof( __gthread_key_t ) );
+ *key = ( __gthread_key_t )new_key;
+ *new_key = NULL;
+
+#ifdef DEBUG_GXX_WRAPPERS
+ printk( "gxx_wrappers: create key=%x, dtor=%x, new_key=%x\n", key, dtor, new_key );
+#endif
+ /* register with RTEMS the buffer that will hold the key values */
+ if( rtems_task_variable_add( RTEMS_SELF, (void **)new_key, NULL ) == RTEMS_SUCCESSFUL )
+ return 0;
+ return -1;
+}
+
+int rtems_gxx_key_dtor (__gthread_key_t key, void *ptr)
+{
+#ifdef DEBUG_GXX_WRAPPERS
+ printk( "gxx_wrappers: dtor key=%x, ptr=%x\n", key, ptr );
+#endif
+ *(void **)key = 0;
+ return 0;
+}
+
+int rtems_gxx_key_delete (__gthread_key_t key)
+{
+#ifdef DEBUG_GXX_WRAPPERS
+ printk( "gxx_wrappers: delete key=%x\n", key );
+#endif
+ /* register with RTEMS the buffer that will hold the key values */
+ if( rtems_task_variable_delete( RTEMS_SELF, (void **)key ) == RTEMS_SUCCESSFUL )
+ {
+ if( key ) free( (void *)key );
+ return 0;
+ }
+ return 0;
+}
+
+
+void *rtems_gxx_getspecific(__gthread_key_t key)
+{
+ void *p= 0;
+
+ /* register with RTEMS the buffer that will hold the key values */
+ if( rtems_task_variable_get( RTEMS_SELF, (void **)key, &p ) == RTEMS_SUCCESSFUL )
+ {
+ /* We do not have to do this, but what the heck ! */
+ p= *( void **)key;
+ }
+ else
+ {
+ /* fisrt time, always set to zero, it is unknown the value that the others
+ * threads are using at the moment of this call
+ */
+ if( rtems_task_variable_add( RTEMS_SELF, (void **)key, NULL ) != RTEMS_SUCCESSFUL )
+ {
+ rtems_panic ("rtems_gxx_getspecific");
+ }
+ *( void ** )key = (void *)0;
+ }
+
+#ifdef DEBUG_GXX_WRAPPERS
+ printk( "gxx_wrappers: getspecific key=%x, ptr=%x, id=%x\n", key, p, get_tid() );
+#endif
+ return p;
+}
+
+
+int rtems_gxx_setspecific(__gthread_key_t key, const void *ptr)
+{
+#ifdef DEBUG_GXX_WRAPPERS
+ printk( "gxx_wrappers: setspecific key=%x, ptr=%x, id=%x\n", key, ptr, get_tid() );
+#endif
+ /* register with RTEMS the buffer that will hold the key values */
+ if( rtems_task_variable_add( RTEMS_SELF, (void **)key, NULL ) == RTEMS_SUCCESSFUL )
+ {
+ /* now let's set the proper value */
+ *( void ** )key = (void *)ptr;
+ return 0;
+ }
+ return -1;
+}
+
+
+/*
+ * MUTEX support
+ */
+void rtems_gxx_mutex_init (__gthread_mutex_t *mutex)
+{
+#ifdef DEBUG_GXX_WRAPPERS
+ printk( "gxx_wrappers: mutex init =%X\n", *mutex );
+#endif
+ if( rtems_semaphore_create( rtems_build_name ('G', 'C', 'C', '2'),
+ 1,
+ RTEMS_PRIORITY|RTEMS_BINARY_SEMAPHORE
+ |RTEMS_INHERIT_PRIORITY | RTEMS_NO_PRIORITY_CEILING|RTEMS_LOCAL,
+ 0,
+ (rtems_id *)mutex ) != RTEMS_SUCCESSFUL )
+ {
+ rtems_panic ("rtems_gxx_mutex_init");
+ }
+#ifdef DEBUG_GXX_WRAPPERS
+ printk( "gxx_wrappers: mutex init complete =%X\n", *mutex );
+#endif
+}
+
+int rtems_gxx_mutex_lock (__gthread_mutex_t *mutex)
+{
+#ifdef DEBUG_GXX_WRAPPERS
+ printk( "gxx_wrappers: lock mutex=%X\n", *mutex );
+#endif
+ return ( rtems_semaphore_obtain( (rtems_id)*mutex,
+ RTEMS_WAIT, RTEMS_NO_TIMEOUT ) == RTEMS_SUCCESSFUL) ? 0 : -1;
+}
+
+int rtems_gxx_mutex_trylock (__gthread_mutex_t *mutex)
+{
+#ifdef DEBUG_GXX_WRAPPERS
+ printk( "gxx_wrappers: trylock mutex=%X\n", *mutex );
+#endif
+ return (rtems_semaphore_obtain ((rtems_id)*mutex,
+ RTEMS_NO_WAIT, 0) == RTEMS_SUCCESSFUL) ? 0 : -1;
+}
+
+int rtems_gxx_mutex_unlock (__gthread_mutex_t *mutex)
+{
+#ifdef DEBUG_GXX_WRAPPERS
+ printk( "gxx_wrappers: unlock mutex=%X\n", *mutex );
+#endif
+ return (rtems_semaphore_release( (rtems_id)*mutex ) == RTEMS_SUCCESSFUL) ? 0 :-1;
+}
diff --git a/cpukit/libcsupport/src/hosterr.c b/cpukit/libcsupport/src/hosterr.c
new file mode 100644
index 0000000000..e5023a8a23
--- /dev/null
+++ b/cpukit/libcsupport/src/hosterr.c
@@ -0,0 +1,51 @@
+/*
+ * Routines to access a host errno
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#if defined(RTEMS_UNIX)
+#include <errno.h>
+
+int host_errno( void );
+
+/*
+ * fix_syscall_errno
+ *
+ * copy host errno, if any to thread aware errno, if any
+ */
+
+void fix_syscall_errno( void )
+{
+ errno = host_errno();
+}
+
+/*
+ * host_errno
+ *
+ * Get the host system errno, if any
+ * When using newlib (or possibly other libc's) on top of UNIX
+ * the errno returned by system calls may be unavailable due
+ * to trickery of making errno thread aware.
+ * This provides a kludge of getting at it.
+ */
+
+#undef errno
+extern int errno;
+int host_errno(void)
+{
+ return errno;
+}
+#endif
diff --git a/cpukit/libcsupport/src/ioctl.c b/cpukit/libcsupport/src/ioctl.c
new file mode 100644
index 0000000000..ea05340a9d
--- /dev/null
+++ b/cpukit/libcsupport/src/ioctl.c
@@ -0,0 +1,60 @@
+/*
+ * ioctl() system call
+ *
+ * This routine is not defined in the POSIX 1003.1b standard but is
+ * commonly supported on most UNIX and POSIX systems.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+#include <unistd.h>
+
+int ioctl(
+ int fd,
+ int command,
+ ...
+)
+{
+ va_list ap;
+ rtems_status_code rc;
+ rtems_libio_t *iop;
+ void *buffer;
+
+ rtems_libio_check_fd( fd );
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_is_open(iop);
+
+ va_start(ap, command);
+
+ buffer = va_arg(ap, void *);
+
+ /*
+ * Now process the ioctl().
+ */
+
+ if ( !iop->handlers )
+ rtems_set_errno_and_return_minus_one( EBADF );
+
+ if ( !iop->handlers->ioctl_h )
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+
+ rc = (*iop->handlers->ioctl_h)( iop, command, buffer );
+
+ return rc;
+}
diff --git a/cpukit/libcsupport/src/isatty.c b/cpukit/libcsupport/src/isatty.c
new file mode 100644
index 0000000000..d1ee06ee97
--- /dev/null
+++ b/cpukit/libcsupport/src/isatty.c
@@ -0,0 +1,31 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/stat.h>
+
+int isatty(
+ int fd
+)
+{
+ struct stat buf;
+
+ if (fstat (fd, &buf) < 0)
+ return 0;
+
+ if (S_ISCHR (buf.st_mode))
+ return 1;
+
+ return 0;
+}
diff --git a/cpukit/libcsupport/src/libio.c b/cpukit/libcsupport/src/libio.c
new file mode 100644
index 0000000000..c30c54e2b3
--- /dev/null
+++ b/cpukit/libcsupport/src/libio.c
@@ -0,0 +1,333 @@
+/*
+ * This file contains the support infrastructure used to manage the
+ * table of integer style file descriptors used by the low level
+ * POSIX system calls like open(), read, fstat(), etc.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/libio_.h> /* libio_.h pulls in rtems */
+#include <rtems.h>
+#include <rtems/assoc.h> /* assoc.h not included by rtems.h */
+
+#include <stdio.h> /* O_RDONLY, et.al. */
+#include <fcntl.h> /* O_RDONLY, et.al. */
+#include <assert.h>
+#include <errno.h>
+
+#if ! defined(O_NDELAY)
+# if defined(solaris2)
+# define O_NDELAY O_NONBLOCK
+# elif defined(__CYGWIN__)
+# define O_NDELAY _FNBIO
+# elif defined(RTEMS_NEWLIB)
+# define O_NDELAY _FNBIO
+# endif
+#endif
+
+
+#include <errno.h>
+#include <string.h> /* strcmp */
+#include <unistd.h>
+#include <stdlib.h> /* calloc() */
+
+#include <rtems/libio.h> /* libio.h not pulled in by rtems */
+
+/*
+ * File descriptor Table Information
+ */
+
+extern uint32_t rtems_libio_number_iops;
+rtems_id rtems_libio_semaphore;
+rtems_libio_t *rtems_libio_iops;
+rtems_libio_t *rtems_libio_iop_freelist;
+
+/*
+ * rtems_libio_init
+ *
+ * Called by BSP startup code to initialize the libio subsystem.
+ */
+
+void rtems_libio_init( void )
+{
+ rtems_status_code rc;
+ int i;
+ rtems_libio_t *iop;
+
+ if (rtems_libio_number_iops > 0)
+ {
+ rtems_libio_iops = (rtems_libio_t *) calloc(rtems_libio_number_iops,
+ sizeof(rtems_libio_t));
+ if (rtems_libio_iops == NULL)
+ rtems_fatal_error_occurred(RTEMS_NO_MEMORY);
+
+ iop = rtems_libio_iop_freelist = rtems_libio_iops;
+ for (i = 0 ; i < (rtems_libio_number_iops - 1) ; i++, iop++)
+ iop->data1 = iop + 1;
+ iop->data1 = NULL;
+ }
+
+ /*
+ * Create the binary semaphore used to provide mutual exclusion
+ * on the IOP Table.
+ */
+
+ rc = rtems_semaphore_create(
+ RTEMS_LIBIO_SEM,
+ 1,
+ RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
+ RTEMS_NO_PRIORITY,
+ &rtems_libio_semaphore
+ );
+ if ( rc != RTEMS_SUCCESSFUL )
+ rtems_fatal_error_occurred( rc );
+
+ /*
+ * Initialize the base file system infrastructure.
+ */
+
+ rtems_filesystem_initialize();
+}
+
+/*
+ * rtems_libio_fcntl_flags
+ *
+ * Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand
+ */
+
+rtems_assoc_t access_modes_assoc[] = {
+ { "READ", LIBIO_FLAGS_READ, O_RDONLY },
+ { "WRITE", LIBIO_FLAGS_WRITE, O_WRONLY },
+ { "READ/WRITE", LIBIO_FLAGS_READ_WRITE, O_RDWR },
+ { 0, 0, 0 },
+};
+
+rtems_assoc_t status_flags_assoc[] = {
+ { "NO DELAY", LIBIO_FLAGS_NO_DELAY, O_NDELAY },
+ { "NONBLOCK", LIBIO_FLAGS_NO_DELAY, O_NONBLOCK },
+ { "APPEND", LIBIO_FLAGS_APPEND, O_APPEND },
+ { "CREATE", LIBIO_FLAGS_CREATE, O_CREAT },
+ { 0, 0, 0 },
+};
+
+uint32_t rtems_libio_fcntl_flags(
+ uint32_t fcntl_flags
+)
+{
+ uint32_t flags = 0;
+ uint32_t access_modes;
+
+ /*
+ * Access mode is a small integer
+ */
+
+ access_modes = fcntl_flags & O_ACCMODE;
+ fcntl_flags &= ~O_ACCMODE;
+ flags = rtems_assoc_local_by_remote( access_modes_assoc, access_modes );
+
+ /*
+ * Everything else is single bits
+ */
+
+ flags |=
+ rtems_assoc_local_by_remote_bitfield(status_flags_assoc, fcntl_flags);
+ return flags;
+}
+
+/*
+ * rtems_libio_to_fcntl_flags
+ *
+ * Convert RTEMS internal flags to UNIX fnctl(2) flags
+ */
+
+uint32_t rtems_libio_to_fcntl_flags(
+ uint32_t flags
+)
+{
+ uint32_t fcntl_flags = 0;
+
+ if ( (flags & LIBIO_FLAGS_READ_WRITE) == LIBIO_FLAGS_READ_WRITE ) {
+ fcntl_flags |= O_RDWR;
+ } else if ( (flags & LIBIO_FLAGS_READ) == LIBIO_FLAGS_READ) {
+ fcntl_flags |= O_RDONLY;
+ } else if ( (flags & LIBIO_FLAGS_WRITE) == LIBIO_FLAGS_WRITE) {
+ fcntl_flags |= O_WRONLY;
+ }
+
+ if ( (flags & LIBIO_FLAGS_NO_DELAY) == LIBIO_FLAGS_NO_DELAY ) {
+ fcntl_flags |= O_NDELAY;
+ }
+
+ if ( (flags & LIBIO_FLAGS_APPEND) == LIBIO_FLAGS_APPEND ) {
+ fcntl_flags |= O_APPEND;
+ }
+
+ if ( (flags & LIBIO_FLAGS_CREATE) == LIBIO_FLAGS_CREATE ) {
+ fcntl_flags |= O_CREAT;
+ }
+
+ return fcntl_flags;
+}
+
+/*
+ * rtems_libio_allocate
+ *
+ * This routine searches the IOP Table for an unused entry. If it
+ * finds one, it returns it. Otherwise, it returns NULL.
+ */
+
+rtems_libio_t *rtems_libio_allocate( void )
+{
+ rtems_libio_t *iop, *next;
+ rtems_status_code rc;
+
+ rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
+
+ if (rtems_libio_iop_freelist) {
+ iop = rtems_libio_iop_freelist;
+ next = iop->data1;
+ (void) memset( iop, 0, sizeof(rtems_libio_t) );
+ iop->flags = LIBIO_FLAGS_OPEN;
+ rc = rtems_semaphore_create(
+ RTEMS_LIBIO_IOP_SEM(iop - rtems_libio_iops),
+ 1,
+ RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
+ RTEMS_NO_PRIORITY,
+ &iop->sem
+ );
+ if (rc != RTEMS_SUCCESSFUL)
+ goto failed;
+ rtems_libio_iop_freelist = next;
+ goto done;
+ }
+
+failed:
+ iop = 0;
+
+done:
+ rtems_semaphore_release( rtems_libio_semaphore );
+ return iop;
+}
+
+/*
+ * rtems_libio_free
+ *
+ * This routine frees the resources associated with an IOP (file descriptor)
+ * and clears the slot in the IOP Table.
+ */
+
+void rtems_libio_free(
+ rtems_libio_t *iop
+)
+{
+ rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
+
+ if (iop->sem)
+ rtems_semaphore_delete(iop->sem);
+
+ iop->flags &= ~LIBIO_FLAGS_OPEN;
+ iop->data1 = rtems_libio_iop_freelist;
+ rtems_libio_iop_freelist = iop;
+
+ rtems_semaphore_release(rtems_libio_semaphore);
+}
+
+/*
+ * rtems_libio_is_open_files_in_fs
+ *
+ * This routine scans the entire file descriptor table to determine if the
+ * are any active file descriptors that refer to the at least one node in the
+ * file system that we are trying to dismount.
+ *
+ * If there is at least one node in the file system referenced by the mount
+ * table entry a 1 is returned, otherwise a 0 is returned.
+ */
+
+int rtems_libio_is_open_files_in_fs(
+ rtems_filesystem_mount_table_entry_t * fs_mt_entry
+)
+{
+ rtems_libio_t *iop;
+ int result = 0;
+ int i;
+
+ rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
+
+ /*
+ * Look for any active file descriptor entry.
+ */
+
+ for (iop=rtems_libio_iops,i=0; i < rtems_libio_number_iops; iop++, i++){
+
+ if ((iop->flags & LIBIO_FLAGS_OPEN) != 0) {
+
+ /*
+ * Check if this node is under the file system that we
+ * are trying to dismount.
+ */
+
+ if ( iop->pathinfo.mt_entry == fs_mt_entry ) {
+ result = 1;
+ break;
+ }
+ }
+ }
+
+ rtems_semaphore_release( rtems_libio_semaphore );
+
+ return result;
+}
+
+/*
+ * rtems_libio_is_file_open
+ *
+ * This routine scans the entire file descriptor table to determine if the
+ * given file refers to an active file descriptor.
+ *
+ * If the given file is open a 1 is returned, otherwise a 0 is returned.
+ */
+
+int rtems_libio_is_file_open(
+ void *node_access
+)
+{
+ rtems_libio_t *iop;
+ int result=0;
+ int i;
+
+ rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
+
+ /*
+ * Look for any active file descriptor entry.
+ */
+
+ for (iop=rtems_libio_iops,i=0; i < rtems_libio_number_iops; iop++, i++){
+ if ((iop->flags & LIBIO_FLAGS_OPEN) != 0) {
+
+ /*
+ * Check if this node is under the file system that we
+ * are trying to dismount.
+ */
+
+ if ( iop->pathinfo.node_access == node_access ) {
+ result = 1;
+ break;
+ }
+ }
+ }
+
+ rtems_semaphore_release( rtems_libio_semaphore );
+
+ return result;
+}
diff --git a/cpukit/libcsupport/src/libio_sockets.c b/cpukit/libcsupport/src/libio_sockets.c
new file mode 100644
index 0000000000..88db941083
--- /dev/null
+++ b/cpukit/libcsupport/src/libio_sockets.c
@@ -0,0 +1,75 @@
+/*
+ * This file contains the support infrastructure used to manage the
+ * table of integer style file descriptors used by the socket calls.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/libio_.h> /* libio_.h pulls in rtems */
+#include <rtems.h>
+
+#include <errno.h>
+
+/*
+ * Convert an RTEMS file descriptor to a BSD socket pointer.
+ */
+
+struct socket *rtems_bsdnet_fdToSocket(
+ int fd
+)
+{
+ rtems_libio_t *iop;
+
+ /* same as rtems_libio_check_fd(_fd) but different return */
+ if ((uint32_t )fd >= rtems_libio_number_iops) {
+ errno = EBADF;
+ return NULL;
+ }
+ iop = &rtems_libio_iops[fd];
+
+ /* same as rtems_libio_check_is_open(iop) but different return */
+ if ((iop->flags & LIBIO_FLAGS_OPEN) == 0) {
+ errno = EBADF;
+ return NULL;
+ }
+
+ if (iop->data1 == NULL)
+ errno = EBADF;
+ return iop->data1;
+}
+
+/*
+ * Create an RTEMS file descriptor for a socket
+ */
+
+int rtems_bsdnet_makeFdForSocket(
+ void *so,
+ const rtems_filesystem_file_handlers_r *h
+)
+{
+ rtems_libio_t *iop;
+ int fd;
+
+ iop = rtems_libio_allocate();
+ if (iop == 0) {
+ errno = ENFILE;
+ return -1;
+ }
+ fd = iop - rtems_libio_iops;
+ iop->flags |= LIBIO_FLAGS_WRITE | LIBIO_FLAGS_READ;
+ iop->data0 = fd;
+ iop->data1 = so;
+ iop->handlers = (rtems_filesystem_file_handlers_r *) h;
+ return fd;
+}
diff --git a/cpukit/libcsupport/src/link.c b/cpukit/libcsupport/src/link.c
new file mode 100644
index 0000000000..217342e844
--- /dev/null
+++ b/cpukit/libcsupport/src/link.c
@@ -0,0 +1,104 @@
+/*
+ * link() - POSIX 1003.1b - 5.3.4 - Create a new link
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <errno.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int link(
+ const char *existing,
+ const char *new
+)
+{
+ rtems_filesystem_location_info_t existing_loc;
+ rtems_filesystem_location_info_t parent_loc;
+ int i;
+ int result;
+ const char *name_start;
+
+ /*
+ * Get the node we are linking to.
+ */
+
+ result = rtems_filesystem_evaluate_path( existing, 0, &existing_loc, TRUE );
+ if ( result != 0 )
+ return -1;
+
+ /*
+ * Get the parent of the node we are creating.
+ */
+
+ rtems_filesystem_get_start_loc( new, &i, &parent_loc );
+
+ if ( !parent_loc.ops->evalformake_h ) {
+ rtems_filesystem_freenode( &existing_loc );
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+ }
+
+ result = (*parent_loc.ops->evalformake_h)( &new[i], &parent_loc, &name_start );
+ if ( result != 0 ) {
+ rtems_filesystem_freenode( &existing_loc );
+ rtems_set_errno_and_return_minus_one( result );
+ }
+
+ /*
+ * Check to see if the caller is trying to link across file system
+ * boundaries.
+ */
+
+ if ( parent_loc.mt_entry != existing_loc.mt_entry ) {
+ rtems_filesystem_freenode( &existing_loc );
+ rtems_filesystem_freenode( &parent_loc );
+ rtems_set_errno_and_return_minus_one( EXDEV );
+ }
+
+ if ( !parent_loc.ops->link_h ) {
+ rtems_filesystem_freenode( &existing_loc );
+ rtems_filesystem_freenode( &parent_loc );
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+ }
+
+ result = (*parent_loc.ops->link_h)( &existing_loc, &parent_loc, name_start );
+
+ rtems_filesystem_freenode( &existing_loc );
+ rtems_filesystem_freenode( &parent_loc );
+
+ return result;
+}
+
+/*
+ * _link_r
+ *
+ * This is the Newlib dependent reentrant version of link().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+int _link_r(
+ struct _reent *ptr,
+ const char *existing,
+ const char *new
+)
+{
+ return link( existing, new );
+}
+#endif
diff --git a/cpukit/libcsupport/src/lseek.c b/cpukit/libcsupport/src/lseek.c
new file mode 100644
index 0000000000..7146ae80e9
--- /dev/null
+++ b/cpukit/libcsupport/src/lseek.c
@@ -0,0 +1,101 @@
+/*
+ * lseek() - POSIX 1003.1b 6.5.3 - Reposition Read/Write File Offset
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+off_t lseek(
+ int fd,
+ off_t offset,
+ int whence
+)
+{
+ rtems_libio_t *iop;
+ off_t old_offset;
+ off_t status;
+
+ rtems_libio_check_fd( fd );
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_is_open(iop);
+
+ /*
+ * Check as many errors as possible before touching iop->offset.
+ */
+
+ if ( !iop->handlers->lseek_h )
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+
+ /*
+ * Now process the lseek().
+ */
+
+ old_offset = iop->offset;
+ switch ( whence ) {
+ case SEEK_SET:
+ iop->offset = offset;
+ break;
+
+ case SEEK_CUR:
+ iop->offset += offset;
+ break;
+
+ case SEEK_END:
+ iop->offset = iop->size + offset;
+ break;
+
+ default:
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ }
+
+ /*
+ * At this time, handlers assume iop->offset has the desired
+ * new offset.
+ */
+
+ status = (*iop->handlers->lseek_h)( iop, offset, whence );
+ if ( status == (off_t) -1 )
+ iop->offset = old_offset;
+
+ /*
+ * So if the operation failed, we have to restore iop->offset.
+ */
+
+ return status;
+}
+
+/*
+ * _lseek_r
+ *
+ * This is the Newlib dependent reentrant version of lseek().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+off_t _lseek_r(
+ struct _reent *ptr,
+ int fd,
+ off_t offset,
+ int whence
+)
+{
+ return lseek( fd, offset, whence );
+}
+#endif
diff --git a/cpukit/libcsupport/src/lstat.c b/cpukit/libcsupport/src/lstat.c
new file mode 100644
index 0000000000..66dca78338
--- /dev/null
+++ b/cpukit/libcsupport/src/lstat.c
@@ -0,0 +1,18 @@
+/*
+ * lstat() - BSD 4.3 and SVR4 - Get File Status
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#define _STAT_NAME lstat
+#define _STAT_R_NAME _lstat_r
+#define _STAT_FOLLOW_LINKS FALSE
+
+#include "stat.c"
diff --git a/cpukit/libcsupport/src/malloc.c b/cpukit/libcsupport/src/malloc.c
new file mode 100644
index 0000000000..64d3a715e7
--- /dev/null
+++ b/cpukit/libcsupport/src/malloc.c
@@ -0,0 +1,487 @@
+/*
+ * RTEMS Malloc Family Implementation
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#include <rtems.h>
+#include <rtems/libcsupport.h>
+#include <rtems/score/apimutex.h>
+#ifdef RTEMS_NEWLIB
+#include <sys/reent.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include <unistd.h> /* sbrk(2) */
+
+#include <rtems/chain.h>
+
+Chain_Control RTEMS_Malloc_GC_list;
+
+rtems_id RTEMS_Malloc_Heap;
+size_t RTEMS_Malloc_Sbrk_amount;
+
+#ifdef RTEMS_DEBUG
+#define MALLOC_STATS
+#define MALLOC_DIRTY
+#endif
+
+#ifdef MALLOC_STATS
+#define MSBUMP(f,n) rtems_malloc_stats.f += (n)
+
+struct {
+ uint32_t space_available; /* current size of malloc area */
+ uint32_t malloc_calls; /* # calls to malloc */
+ uint32_t free_calls;
+ uint32_t realloc_calls;
+ uint32_t calloc_calls;
+ uint32_t max_depth; /* most ever malloc'd at 1 time */
+ uint64_t lifetime_allocated;
+ uint64_t lifetime_freed;
+} rtems_malloc_stats;
+
+#else /* No rtems_malloc_stats */
+#define MSBUMP(f,n)
+#endif
+
+void RTEMS_Malloc_Initialize(
+ void *start,
+ size_t length,
+ size_t sbrk_amount
+)
+{
+ rtems_status_code status;
+ void *starting_address;
+ uint32_t old_address;
+ uint32_t u32_address;
+
+ /*
+ * Initialize the garbage collection list to start with nothing on it.
+ */
+ Chain_Initialize_empty(&RTEMS_Malloc_GC_list);
+
+ /*
+ * If the starting address is 0 then we are to attempt to
+ * get length worth of memory using sbrk. Make sure we
+ * align the address that we get back.
+ */
+
+ starting_address = start;
+ RTEMS_Malloc_Sbrk_amount = sbrk_amount;
+
+ if (!starting_address) {
+ u32_address = (unsigned int)sbrk(length);
+
+ if (u32_address == (uint32_t ) -1) {
+ rtems_fatal_error_occurred( RTEMS_NO_MEMORY );
+ /* DOES NOT RETURN!!! */
+ }
+
+ if (u32_address & (CPU_HEAP_ALIGNMENT-1)) {
+ old_address = u32_address;
+ u32_address = (u32_address + CPU_HEAP_ALIGNMENT) & ~(CPU_HEAP_ALIGNMENT-1);
+
+ /*
+ * adjust the length by whatever we aligned by
+ */
+
+ length -= u32_address - old_address;
+ }
+
+ starting_address = (void *)u32_address;
+ }
+
+ /*
+ * If the BSP is not clearing out the workspace, then it is most likely
+ * not clearing out the initial memory for the heap. There is no
+ * standard supporting zeroing out the heap memory. But much code
+ * with UNIX history seems to assume that memory malloc'ed during
+ * initialization (before any free's) is zero'ed. This is true most
+ * of the time under UNIX because zero'ing memory when it is first
+ * given to a process eliminates the chance of a process seeing data
+ * left over from another process. This would be a security violation.
+ */
+
+ if ( rtems_cpu_configuration_get_do_zero_of_workspace() )
+ memset( starting_address, 0, length );
+
+ /*
+ * Unfortunately we cannot use assert if this fails because if this
+ * has failed we do not have a heap and if we do not have a heap
+ * STDIO cannot work because there will be no buffers.
+ */
+
+ status = rtems_region_create(
+ rtems_build_name( 'H', 'E', 'A', 'P' ),
+ starting_address,
+ length,
+ CPU_HEAP_ALIGNMENT,
+ RTEMS_DEFAULT_ATTRIBUTES,
+ &RTEMS_Malloc_Heap
+ );
+ if ( status != RTEMS_SUCCESSFUL )
+ rtems_fatal_error_occurred( status );
+
+#ifdef MALLOC_STATS
+ /* zero all the stats */
+ (void) memset( &rtems_malloc_stats, 0, sizeof(rtems_malloc_stats) );
+#endif
+
+ MSBUMP(space_available, length);
+}
+
+#ifdef RTEMS_NEWLIB
+void *malloc(
+ size_t size
+)
+{
+ void *return_this;
+ void *starting_address;
+ uint32_t the_size;
+ uint32_t sbrk_amount;
+ rtems_status_code status;
+ Chain_Node *to_be_freed;
+
+ MSBUMP(malloc_calls, 1);
+
+ if ( !size )
+ return (void *) 0;
+
+ /*
+ * Do not attempt to allocate memory if in a critical section or ISR.
+ */
+
+ if (_System_state_Is_up(_System_state_Get())) {
+ if (_Thread_Dispatch_disable_level > 0)
+ return (void *) 0;
+
+ if (_ISR_Nest_level > 0)
+ return (void *) 0;
+ }
+
+ /*
+ * If some free's have been deferred, then do them now.
+ */
+ while ((to_be_freed = Chain_Get(&RTEMS_Malloc_GC_list)) != NULL)
+ free(to_be_freed);
+
+ /*
+ * Try to give a segment in the current region if there is not
+ * enough space then try to grow the region using rtems_region_extend().
+ * If this fails then return a NULL pointer.
+ */
+
+ status = rtems_region_get_segment(
+ RTEMS_Malloc_Heap,
+ size,
+ RTEMS_NO_WAIT,
+ RTEMS_NO_TIMEOUT,
+ &return_this
+ );
+
+ if ( status != RTEMS_SUCCESSFUL ) {
+ /*
+ * Round to the "requested sbrk amount" so hopefully we won't have
+ * to grow again for a while. This effectively does sbrk() calls
+ * in "page" amounts.
+ */
+
+ sbrk_amount = RTEMS_Malloc_Sbrk_amount;
+
+ if ( sbrk_amount == 0 )
+ return (void *) 0;
+
+ the_size = ((size + sbrk_amount) / sbrk_amount * sbrk_amount);
+
+ if ((starting_address = (void *)sbrk(the_size))
+ == (void*) -1)
+ return (void *) 0;
+
+ status = rtems_region_extend(
+ RTEMS_Malloc_Heap,
+ starting_address,
+ the_size
+ );
+ if ( status != RTEMS_SUCCESSFUL ) {
+ sbrk(-the_size);
+ errno = ENOMEM;
+ return (void *) 0;
+ }
+
+ MSBUMP(space_available, the_size);
+
+ status = rtems_region_get_segment(
+ RTEMS_Malloc_Heap,
+ size,
+ RTEMS_NO_WAIT,
+ RTEMS_NO_TIMEOUT,
+ &return_this
+ );
+ if ( status != RTEMS_SUCCESSFUL ) {
+ errno = ENOMEM;
+ return (void *) 0;
+ }
+ }
+
+#ifdef MALLOC_STATS
+ if (return_this)
+ {
+ size_t actual_size;
+ uint32_t current_depth;
+ status = rtems_region_get_segment_size(
+ RTEMS_Malloc_Heap, return_this, &actual_size);
+ MSBUMP(lifetime_allocated, actual_size);
+ current_depth = rtems_malloc_stats.lifetime_allocated -
+ rtems_malloc_stats.lifetime_freed;
+ if (current_depth > rtems_malloc_stats.max_depth)
+ rtems_malloc_stats.max_depth = current_depth;
+ }
+#endif
+
+#ifdef MALLOC_DIRTY
+ (void) memset(return_this, 0xCF, size);
+#endif
+
+ return return_this;
+}
+
+void *calloc(
+ size_t nelem,
+ size_t elsize
+)
+{
+ register char *cptr;
+ int length;
+
+ MSBUMP(calloc_calls, 1);
+
+ length = nelem * elsize;
+ cptr = malloc( length );
+ if ( cptr )
+ memset( cptr, '\0', length );
+
+ MSBUMP(malloc_calls, -1); /* subtract off the malloc */
+
+ return cptr;
+}
+
+void *realloc(
+ void *ptr,
+ size_t size
+)
+{
+ size_t old_size;
+ rtems_status_code status;
+ char *new_area;
+
+ MSBUMP(realloc_calls, 1);
+
+ /*
+ * Do not attempt to allocate memory if in a critical section or ISR.
+ */
+
+ if (_System_state_Is_up(_System_state_Get())) {
+ if (_Thread_Dispatch_disable_level > 0)
+ return (void *) 0;
+
+ if (_ISR_Nest_level > 0)
+ return (void *) 0;
+ }
+
+ /*
+ * Continue with calloc().
+ */
+ if ( !ptr )
+ return malloc( size );
+
+ if ( !size ) {
+ free( ptr );
+ return (void *) 0;
+ }
+
+ new_area = malloc( size );
+
+ MSBUMP(malloc_calls, -1); /* subtract off the malloc */
+
+ /*
+ * There used to be a free on this error case but it is wrong to
+ * free the memory per OpenGroup Single UNIX Specification V2
+ * and the C Standard.
+ */
+
+ if ( !new_area ) {
+ return (void *) 0;
+ }
+
+ status = rtems_region_get_segment_size( RTEMS_Malloc_Heap, ptr, &old_size );
+ if ( status != RTEMS_SUCCESSFUL ) {
+ errno = EINVAL;
+ return (void *) 0;
+ }
+
+ memcpy( new_area, ptr, (size < old_size) ? size : old_size );
+ free( ptr );
+
+ return new_area;
+
+}
+
+void free(
+ void *ptr
+)
+{
+ rtems_status_code status;
+
+ MSBUMP(free_calls, 1);
+
+ if ( !ptr )
+ return;
+
+ /*
+ * Do not attempt to free memory if in a critical section or ISR.
+ */
+
+ if (_System_state_Is_up(_System_state_Get())) {
+ if ((_Thread_Dispatch_disable_level > 0) || (_ISR_Nest_level > 0)) {
+ Chain_Append(&RTEMS_Malloc_GC_list, (Chain_Node *)ptr);
+ return;
+ }
+ }
+
+#ifdef MALLOC_STATS
+ {
+ size_t size;
+ status = rtems_region_get_segment_size( RTEMS_Malloc_Heap, ptr, &size );
+ if ( status == RTEMS_SUCCESSFUL ) {
+ MSBUMP(lifetime_freed, size);
+ }
+ }
+#endif
+
+ status = rtems_region_return_segment( RTEMS_Malloc_Heap, ptr );
+ if ( status != RTEMS_SUCCESSFUL ) {
+ errno = EINVAL;
+ assert( 0 );
+ }
+}
+/* end if RTEMS_NEWLIB */
+#endif
+
+#ifdef MALLOC_STATS
+/*
+ * Dump the malloc statistics
+ * May be called via atexit() (installable by our bsp) or
+ * at any time by user
+ */
+
+void malloc_dump(void)
+{
+ uint32_t allocated = rtems_malloc_stats.lifetime_allocated -
+ rtems_malloc_stats.lifetime_freed;
+
+ printf("Malloc stats\n");
+ printf(" avail:%uk allocated:%uk (%d%%) "
+ "max:%uk (%d%%) lifetime:%Luk freed:%Luk\n",
+ (unsigned int) rtems_malloc_stats.space_available / 1024,
+ (unsigned int) allocated / 1024,
+ /* avoid float! */
+ (allocated * 100) / rtems_malloc_stats.space_available,
+ (unsigned int) rtems_malloc_stats.max_depth / 1024,
+ (rtems_malloc_stats.max_depth * 100) / rtems_malloc_stats.space_available,
+ (uint64_t ) rtems_malloc_stats.lifetime_allocated / 1024,
+ (uint64_t ) rtems_malloc_stats.lifetime_freed / 1024);
+ printf(" Call counts: malloc:%d free:%d realloc:%d calloc:%d\n",
+ rtems_malloc_stats.malloc_calls,
+ rtems_malloc_stats.free_calls,
+ rtems_malloc_stats.realloc_calls,
+ rtems_malloc_stats.calloc_calls);
+}
+
+
+void malloc_walk(size_t source, size_t printf_enabled)
+{
+ register Region_Control *the_region;
+ Objects_Locations location;
+
+ _RTEMS_Lock_allocator(); /* to prevent deletion */
+ the_region = _Region_Get( RTEMS_Malloc_Heap, &location );
+ if ( location == OBJECTS_LOCAL )
+ {
+ _Heap_Walk( &the_region->Memory, source, printf_enabled );
+ }
+ _RTEMS_Unlock_allocator();
+}
+
+#else
+
+void malloc_dump(void)
+{
+ return;
+}
+
+void malloc_walk(size_t source, size_t printf_enabled)
+{
+ return;
+}
+
+#endif
+
+/*
+ * "Reentrant" versions of the above routines implemented above.
+ */
+
+#ifdef RTEMS_NEWLIB
+void *_malloc_r(
+ struct _reent *ignored,
+ size_t size
+)
+{
+ return malloc( size );
+}
+
+void *_calloc_r(
+ struct _reent *ignored,
+ size_t nelem,
+ size_t elsize
+)
+{
+ return calloc( nelem, elsize );
+}
+
+void *_realloc_r(
+ struct _reent *ignored,
+ void *ptr,
+ size_t size
+)
+{
+ return realloc( ptr, size );
+}
+
+void _free_r(
+ struct _reent *ignored,
+ void *ptr
+)
+{
+ free( ptr );
+}
+
+#endif
diff --git a/cpukit/libcsupport/src/mallocfreespace.c b/cpukit/libcsupport/src/mallocfreespace.c
new file mode 100644
index 0000000000..bbf4a78e16
--- /dev/null
+++ b/cpukit/libcsupport/src/mallocfreespace.c
@@ -0,0 +1,44 @@
+/*
+ * RTEMS Malloc Get Status Information
+ *
+ *
+ * COPYRIGHT (c) 1989-2000.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#include <rtems.h>
+#include <rtems/libcsupport.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+extern rtems_id RTEMS_Malloc_Heap;
+
+/*
+ * Find amount of free heap remaining
+ */
+
+size_t malloc_free_space( void )
+{
+ region_information_block heap_info;
+
+ if ( !rtems_region_get_information( RTEMS_Malloc_Heap, &heap_info ) ) {
+ return (size_t) heap_info.free_size;
+ }
+ return (size_t) -1;
+}
diff --git a/cpukit/libcsupport/src/mkdir.c b/cpukit/libcsupport/src/mkdir.c
new file mode 100644
index 0000000000..2fae8a733a
--- /dev/null
+++ b/cpukit/libcsupport/src/mkdir.c
@@ -0,0 +1,30 @@
+/*
+ * mkdir() - POSIX 1003.1b 5.4.1 - Make a Directory
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+
+int mkdir(
+ const char *pathname,
+ mode_t mode
+)
+{
+ return mknod( pathname, mode | S_IFDIR, 0LL);
+}
diff --git a/cpukit/libcsupport/src/mkfifo.c b/cpukit/libcsupport/src/mkfifo.c
new file mode 100644
index 0000000000..efe6207bf8
--- /dev/null
+++ b/cpukit/libcsupport/src/mkfifo.c
@@ -0,0 +1,28 @@
+/*
+ * mkfifo() - POSIX 1003.1b 5.4.1 - Make a FIFO Special File
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+int mkfifo(
+ const char *path,
+ mode_t mode
+)
+{
+ return mknod( path, mode | S_IFIFO, 0LL );
+}
diff --git a/cpukit/libcsupport/src/mknod.c b/cpukit/libcsupport/src/mknod.c
new file mode 100644
index 0000000000..c786c6d756
--- /dev/null
+++ b/cpukit/libcsupport/src/mknod.c
@@ -0,0 +1,73 @@
+/*
+ * mknod()
+ *
+ * This routine is not defined in the POSIX 1003.1b standard but is
+ * commonly supported on most UNIX and POSIX systems. It is the
+ * foundation for creating file system objects.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int mknod(
+ const char *pathname,
+ mode_t mode,
+ dev_t dev
+)
+{
+ rtems_filesystem_location_info_t temp_loc;
+ int i;
+ const char *name_start;
+ int result;
+
+ if ( !(mode & (S_IFREG|S_IFCHR|S_IFBLK|S_IFIFO) ) )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ if ( S_ISFIFO(mode) )
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+
+ rtems_filesystem_get_start_loc( pathname, &i, &temp_loc );
+
+ if ( !temp_loc.ops->evalformake_h ) {
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+ }
+
+ result = (*temp_loc.ops->evalformake_h)(
+ &pathname[i],
+ &temp_loc,
+ &name_start
+ );
+ if ( result != 0 )
+ return -1;
+
+ if ( !temp_loc.ops->mknod_h ) {
+ rtems_filesystem_freenode( &temp_loc );
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+ }
+
+ result = (*temp_loc.ops->mknod_h)( name_start, mode, dev, &temp_loc );
+
+ rtems_filesystem_freenode( &temp_loc );
+
+ return result;
+}
diff --git a/cpukit/libcsupport/src/mount.c b/cpukit/libcsupport/src/mount.c
new file mode 100644
index 0000000000..bec64eb701
--- /dev/null
+++ b/cpukit/libcsupport/src/mount.c
@@ -0,0 +1,291 @@
+/*
+ * mount()
+ *
+ * XXX
+ *
+ * XXX make sure no required ops are NULL
+ * XXX make sure no optional ops you are using are NULL
+ * XXX unmount should be required.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <rtems/chain.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <rtems/libio_.h>
+
+Chain_Control rtems_filesystem_mount_table_control;
+
+/*
+ * Prototypes that probably should be somewhere else.
+ */
+
+int init_fs_mount_table( void );
+static int Is_node_fs_root(
+ rtems_filesystem_location_info_t *loc
+);
+
+
+/*
+ * XXX
+ */
+
+#define FOUND 0
+#define NOT_FOUND -1
+
+/*
+ * mount
+ *
+ * This routine will attempt to mount a new file system at the specified
+ * mount point. A series of tests will be run to determine if any of the
+ * following reasons exist to prevent the mount operation:
+ *
+ * 1) The file system type or options are not valid
+ * 2) No new file system root node is specified
+ * 3) The selected file system has already been mounted
+ * 4) The mount point exists with the proper permissions to allow mounting
+ * 5) The selected mount point already has a file system mounted to it
+ *
+ */
+
+int mount(
+ rtems_filesystem_mount_table_entry_t **mt_entry,
+ rtems_filesystem_operations_table *fs_ops,
+ rtems_filesystem_options_t options,
+ char *device,
+ char *mount_point
+)
+{
+ rtems_filesystem_location_info_t loc;
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry = NULL;
+ rtems_filesystem_location_info_t *loc_to_free = NULL;
+ size_t size;
+
+/* XXX add code to check for required operations */
+
+ /*
+ * Is there a file system operations table?
+ */
+
+ if ( fs_ops == NULL ) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /*
+ * Are the file system options valid?
+ */
+
+ if ( options != RTEMS_FILESYSTEM_READ_ONLY &&
+ options != RTEMS_FILESYSTEM_READ_WRITE ) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* Do they support being mounted at all ? */
+ if ( !fs_ops->fsmount_me_h ) {
+ errno = ENOTSUP;
+ goto cleanup_and_bail;
+ }
+
+
+ /*
+ * Allocate a mount table entry
+ */
+
+ size = sizeof(rtems_filesystem_mount_table_entry_t);
+ if ( device )
+ size += strlen( device ) + 1;
+ temp_mt_entry = malloc( size );
+
+ if ( !temp_mt_entry ) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ temp_mt_entry->mt_fs_root.mt_entry = temp_mt_entry;
+ temp_mt_entry->options = options;
+ if ( device ) {
+ temp_mt_entry->dev =
+ (char *)temp_mt_entry + sizeof( rtems_filesystem_mount_table_entry_t );
+ strcpy( temp_mt_entry->dev, device );
+ } else
+ temp_mt_entry->dev = 0;
+
+ /*
+ * The mount_point should be a directory with read/write/execute
+ * permissions in the existing tree.
+ */
+
+ if ( mount_point ) {
+
+ if ( rtems_filesystem_evaluate_path(
+ mount_point, RTEMS_LIBIO_PERMS_RWX, &loc, TRUE ) == -1 )
+ goto cleanup_and_bail;
+
+ loc_to_free = &loc;
+
+ /*
+ * Test for node_type_h
+ */
+
+ if (!loc.ops->node_type_h) {
+ errno = ENOTSUP;
+ goto cleanup_and_bail;
+ }
+
+ /*
+ * Test to see if it is a directory
+ */
+
+ if ( loc.ops->node_type_h( &loc ) != RTEMS_FILESYSTEM_DIRECTORY ) {
+ errno = ENOTDIR;
+ goto cleanup_and_bail;
+ }
+
+ /*
+ * You can only mount one file system onto a single mount point.
+ */
+
+ if ( Is_node_fs_root( &loc ) ){
+ errno = EBUSY;
+ goto cleanup_and_bail;
+ }
+
+ /*
+ * This must be a good mount point, so move the location information
+ * into the allocated mount entry. Note: the information that
+ * may have been allocated in loc should not be sent to freenode
+ * until the system is unmounted. It may be needed to correctly
+ * traverse the tree.
+ */
+
+ temp_mt_entry->mt_point_node.node_access = loc.node_access;
+ temp_mt_entry->mt_point_node.handlers = loc.handlers;
+ temp_mt_entry->mt_point_node.ops = loc.ops;
+ temp_mt_entry->mt_point_node.mt_entry = loc.mt_entry;
+
+ /*
+ * This link to the parent is only done when we are dealing with system
+ * below the base file system
+ */
+
+ if ( !loc.ops->mount_h ){
+ errno = ENOTSUP;
+ goto cleanup_and_bail;
+ }
+
+ if ( loc.ops->mount_h( temp_mt_entry ) ) {
+ goto cleanup_and_bail;
+ }
+ } else {
+
+ /*
+ * This is a mount of the base file system --> The
+ * mt_point_node.node_access will be set to null to indicate that this
+ * is the root of the entire file system.
+ */
+
+ temp_mt_entry->mt_fs_root.node_access = NULL;
+ temp_mt_entry->mt_fs_root.handlers = NULL;
+ temp_mt_entry->mt_fs_root.ops = NULL;
+
+ temp_mt_entry->mt_point_node.node_access = NULL;
+ temp_mt_entry->mt_point_node.handlers = NULL;
+ temp_mt_entry->mt_point_node.ops = NULL;
+ temp_mt_entry->mt_point_node.mt_entry = NULL;
+ }
+
+ if ( fs_ops->fsmount_me_h( temp_mt_entry ) ) {
+ /* try to undo the mount operation */
+ if ( loc.ops->unmount_h ) {
+ loc.ops->unmount_h( temp_mt_entry );
+ }
+ goto cleanup_and_bail;
+ }
+
+ /*
+ * Add the mount table entry to the mount table chain
+ */
+
+ Chain_Append( &rtems_filesystem_mount_table_control, &temp_mt_entry->Node );
+
+ *mt_entry = temp_mt_entry;
+
+ return 0;
+
+cleanup_and_bail:
+
+ free( temp_mt_entry );
+
+ if ( loc_to_free )
+ rtems_filesystem_freenode( loc_to_free );
+
+ return -1;
+}
+
+
+
+/*
+ * init_fs_mount_table
+ *
+ * This routine will initialize the chain control element that manages the
+ * mount table chain.
+ */
+
+int init_fs_mount_table()
+{
+ Chain_Initialize_empty ( &rtems_filesystem_mount_table_control );
+ return 0;
+}
+
+/*
+ * Is_node_fs_root
+ *
+ * This routine will run through the entries that currently exist in the
+ * mount table chain. For each entry in the mount table chain it will
+ * compare the mount tables root node to the node describing the selected
+ * mount point. If any match is found true is returned else false is
+ * returned.
+ *
+ */
+
+static int Is_node_fs_root(
+ rtems_filesystem_location_info_t *loc
+)
+{
+ Chain_Node *the_node;
+ rtems_filesystem_mount_table_entry_t *the_mount_entry;
+
+ /*
+ * For each mount table entry
+ */
+
+ for ( the_node = rtems_filesystem_mount_table_control.first;
+ !Chain_Is_tail( &rtems_filesystem_mount_table_control, the_node );
+ the_node = the_node->next ) {
+ the_mount_entry = (rtems_filesystem_mount_table_entry_t *) the_node;
+ if ( the_mount_entry->mt_fs_root.node_access == loc->node_access )
+ return TRUE;
+ }
+ return FALSE;
+}
diff --git a/cpukit/libcsupport/src/newlibc.c b/cpukit/libcsupport/src/newlibc.c
new file mode 100644
index 0000000000..ef151c6e81
--- /dev/null
+++ b/cpukit/libcsupport/src/newlibc.c
@@ -0,0 +1,386 @@
+/*
+ * Implementation of hooks for the CYGNUS newlib libc
+ * These hooks set things up so that:
+ * + '_REENT' is switched at task switch time.
+ *
+ * COPYRIGHT (c) 1994 by Division Incorporated
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#include <rtems.h>
+
+#if defined(RTEMS_NEWLIB)
+#include <rtems/libcsupport.h>
+
+/* Since we compile with strict ANSI we need to undef it to get
+ * prototypes for extensions
+ */
+#undef __STRICT_ANSI__
+
+#include <stdlib.h> /* for free() */
+#include <string.h> /* for memset() */
+
+#include <sys/reent.h> /* for extern of _REENT (aka _impure_ptr) */
+#include <errno.h>
+
+/*
+ * NOTE:
+ * There is some problem with doing this on the hpux version
+ * of the UNIX simulator (symptom is printf core dumps), so
+ * we just don't for now.
+ * Not sure if this is a problem with hpux, newlib, or something else.
+ */
+
+#if defined(RTEMS_UNIX) && !defined(hpux)
+#define NEED_SETVBUF
+#endif
+
+#include <stdio.h>
+
+int _fwalk(struct _reent *ptr, int (*function) (FILE *) );
+
+int libc_reentrant; /* do we think we are reentrant? */
+struct _reent libc_global_reent;
+
+/*
+ * CYGNUS newlib routine that does atexit() processing and flushes
+ * stdio streams
+ * undocumented
+ */
+
+extern void _wrapup_reent(struct _reent *);
+extern void _reclaim_reent(struct _reent *);
+
+void libc_wrapup(void)
+{
+ /*
+ * In case RTEMS is already down, don't do this. It could be
+ * dangerous.
+ */
+
+ if (!_System_state_Is_up(_System_state_Get()))
+ return;
+
+ /*
+ * This was already done if the user called exit() directly .
+ _wrapup_reent(0);
+ */
+
+ if (_REENT != &libc_global_reent) {
+ _wrapup_reent(&libc_global_reent);
+#if 0
+ /* Don't reclaim this one, just in case we do printfs
+ * on the way out to ROM.
+ */
+ _reclaim_reent(&libc_global_reent);
+#endif
+ _REENT = &libc_global_reent;
+ }
+
+ /*
+ * Try to drain output buffers.
+ *
+ * Should this be changed to do *all* file streams?
+ * _fwalk (_REENT, fclose);
+ */
+
+ fclose (stdin);
+ fclose (stdout);
+ fclose (stderr);
+}
+
+/*
+ * reent struct allocation moved here from libc_start_hook() to avoid
+ * mutual exclusion problems when memory is allocated from the start hook.
+ *
+ * Memory is also now allocated from the workspace rather than the heap.
+ * -- ptorre 9/30/03
+ */
+rtems_boolean libc_create_hook(
+ rtems_tcb *current_task,
+ rtems_tcb *creating_task
+)
+{
+ struct _reent *ptr;
+
+ /* NOTE: The RTEMS malloc is reentrant without a reent ptr since
+ * it is based on the Classic API Region Manager.
+ */
+
+#define REENT_MALLOCED 0
+#if REENT_MALLOCED
+ ptr = (struct _reent *) calloc(1, sizeof(struct _reent));
+#else
+ /* It is OK to allocate from the workspace because these
+ * hooks run with thread dispatching disabled.
+ */
+ ptr = (struct _reent *) _Workspace_Allocate(sizeof(struct _reent));
+#endif
+
+ if (ptr)
+ {
+
+#ifdef __GNUC__
+ /* GCC extension: structure constants */
+ _REENT_INIT_PTR((ptr));
+#else
+ /*
+ * WARNING: THIS IS VERY DEPENDENT ON NEWLIB!!!
+ * Last visual check was against newlib 1.8.2 but last known
+ * use was against 1.7.0. This is basically an exansion of
+ * REENT_INIT() in <sys/reent.h>.
+ */
+ memset(ptr, 0, sizeof(*ptr));
+ ptr->_stdin = &ptr->__sf[0];
+ ptr->_stdout = &ptr->__sf[1];
+ ptr->_stderr = &ptr->__sf[2];
+ ptr->_current_locale = "C";
+ ptr->_new._reent._rand_next = 1;
+#endif
+
+ creating_task->libc_reent = ptr;
+ return TRUE;
+ }
+ else
+ return FALSE;
+
+}
+
+/*
+ * Called for all user TASKS (system tasks are MPCI Receive Server and IDLE)
+ */
+
+rtems_extension libc_start_hook(
+ rtems_tcb *current_task,
+ rtems_tcb *starting_task
+)
+{
+}
+
+/*
+ * Called for all user TASKS (system tasks are MPCI Receive Server and IDLE)
+ */
+
+#ifdef NEED_SETVBUF
+rtems_extension libc_begin_hook(rtems_tcb *current_task)
+{
+ setvbuf( stdout, NULL, _IOLBF, BUFSIZ );
+}
+#endif
+
+/*
+ * Function: libc_delete_hook
+ * Created: 94/12/10
+ *
+ * Description:
+ * Called when a task is deleted.
+ * Must restore the new lib reentrancy state for the new current
+ * task.
+ *
+ * Parameters:
+ *
+ *
+ * Returns:
+ *
+ *
+ * Side Effects:
+ *
+ * Notes:
+ *
+ *
+ * Deficiencies/ToDo:
+ *
+ *
+ */
+
+int newlib_free_buffers(
+ FILE *fp
+)
+{
+ switch ( fileno(fp) ) {
+ case 0:
+ case 1:
+ case 2:
+ if (fp->_flags & __SMBF) {
+ free( fp->_bf._base );
+ fp->_flags &= ~__SMBF;
+ fp->_bf._base = fp->_p = (unsigned char *) NULL;
+ }
+ break;
+ default:
+ fclose(fp);
+ }
+ return 0;
+}
+
+rtems_extension libc_delete_hook(
+ rtems_tcb *current_task,
+ rtems_tcb *deleted_task
+)
+{
+ struct _reent *ptr;
+
+ /*
+ * The reentrancy structure was allocated by newlib using malloc()
+ */
+
+ if (current_task == deleted_task) {
+ ptr = _REENT;
+ } else {
+ ptr = deleted_task->libc_reent;
+ }
+
+ if (ptr && ptr != &libc_global_reent) {
+/*
+ _wrapup_reent(ptr);
+ _reclaim_reent(ptr);
+*/
+ /*
+ * Just in case there are some buffers lying around.
+ */
+ _fwalk(ptr, newlib_free_buffers);
+#if REENT_MALLOCED
+ free(ptr);
+#else
+ _Workspace_Free(ptr);
+#endif
+ }
+
+ deleted_task->libc_reent = NULL;
+
+ /*
+ * Require the switch back to another task to install its own
+ */
+
+ if ( current_task == deleted_task ) {
+ _REENT = 0;
+ }
+}
+
+/*
+ * Function: libc_init
+ * Created: 94/12/10
+ *
+ * Description:
+ * Init libc for CYGNUS newlib
+ * Set up _REENT to use our global libc_global_reent.
+ * (newlib provides a global of its own, but we prefer our
+ * own name for it)
+ *
+ * If reentrancy is desired (which it should be), then
+ * we install the task extension hooks to maintain the
+ * newlib reentrancy global variable _REENT on task
+ * create, delete, switch, exit, etc.
+ *
+ * Parameters:
+ * reentrant non-zero if reentrant library desired.
+ *
+ * Returns:
+ *
+ * Side Effects:
+ * installs libc extensions if reentrant.
+ *
+ * Notes:
+ *
+ *
+ * Deficiencies/ToDo:
+ *
+ */
+
+void
+libc_init(int reentrant)
+{
+ rtems_extensions_table libc_extension;
+ rtems_status_code rc;
+ rtems_id extension_id;
+
+ libc_global_reent = (struct _reent) _REENT_INIT((libc_global_reent));
+ _REENT = &libc_global_reent;
+
+ if (reentrant) {
+ memset(&libc_extension, 0, sizeof(libc_extension));
+
+ libc_extension.thread_create = libc_create_hook;
+ libc_extension.thread_start = libc_start_hook;
+#ifdef NEED_SETVBUF
+ libc_extension.thread_begin = libc_begin_hook;
+#endif
+ libc_extension.thread_delete = libc_delete_hook;
+
+ _Thread_Set_libc_reent (&_REENT);
+
+ rc = rtems_extension_create(rtems_build_name('L', 'I', 'B', 'C'),
+ &libc_extension, &extension_id);
+ if (rc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred( rc );
+
+ libc_reentrant = reentrant;
+ }
+}
+
+/*
+ * Function: _exit
+ * Created: 94/12/10
+ *
+ * Description:
+ * Called from exit() after it does atexit() processing and stdio fflush's
+ *
+ * called from bottom of exit() to really delete the task.
+ * If we are using reentrant libc, then let the delete extension
+ * do all the work, otherwise if a shutdown is in progress,
+ * then just do it.
+ *
+ * Parameters:
+ * exit status
+ *
+ * Returns:
+ * does not return
+ *
+ * Side Effects:
+ *
+ * Notes:
+ *
+ *
+ * Deficiencies/ToDo:
+ *
+ *
+ */
+
+#include <unistd.h>
+
+#if !defined(RTEMS_UNIX)
+void _exit(int status)
+{
+ /*
+ * We need to do the exit processing on the global reentrancy structure.
+ * This has already been done on the per task reentrancy structure
+ * associated with this task.
+ */
+
+ libc_wrapup();
+ rtems_shutdown_executive(status);
+ for (;;) ; /* to avoid warnings */
+}
+
+#else
+
+void exit(int status)
+{
+ libc_wrapup();
+ rtems_shutdown_executive(status);
+ for (;;) ; /* to avoid warnings */
+}
+#endif
+
+#endif
diff --git a/cpukit/libcsupport/src/no_libc.c b/cpukit/libcsupport/src/no_libc.c
new file mode 100644
index 0000000000..afcc30b49c
--- /dev/null
+++ b/cpukit/libcsupport/src/no_libc.c
@@ -0,0 +1,59 @@
+/*
+ * This file contains stubs for the reentrancy hooks when
+ * an unknown C library is used.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#if !defined(RTEMS_NEWLIB) && !defined(RTEMS_UNIX)
+
+#include <rtems/libcsupport.h>
+
+#include <stdlib.h> /* for free() */
+
+void libc_init(
+ int reentrant
+)
+{
+}
+
+void libc_suspend_main(void)
+{
+}
+
+
+void libc_global_exit(
+ uint32_t code
+)
+{
+}
+
+void _exit(
+ int status
+)
+{
+}
+
+#else
+
+/* remove ANSI errors.
+ * A program must contain at least one external-declaration
+ * (X3.159-1989 p.82,L3).
+ */
+void no_libc_dummy_function( void )
+{
+}
+
+#endif
diff --git a/cpukit/libcsupport/src/no_posix.c b/cpukit/libcsupport/src/no_posix.c
new file mode 100644
index 0000000000..1b3bf35c21
--- /dev/null
+++ b/cpukit/libcsupport/src/no_posix.c
@@ -0,0 +1,87 @@
+/*
+ * Marginal implementations of some POSIX API routines
+ * to be used when POSIX is disabled.
+ *
+ * + kill
+ * + _kill_r
+ * + __kill
+ * + sleep
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+
+#include <unistd.h>
+
+/*
+ * These are directly supported (and completely correct) in the posix api.
+ */
+
+#if !defined(RTEMS_POSIX_API)
+int kill( pid_t pid, int sig )
+{
+ return 0;
+}
+
+#if defined(RTEMS_NEWLIB)
+#include <reent.h>
+
+int _kill_r( struct _reent *ptr, pid_t pid, int sig )
+{
+ return 0;
+}
+#endif
+#endif
+
+int __kill( pid_t pid, int sig )
+{
+ return 0;
+}
+
+
+/*
+ * 3.4.3 Delay Process Execution, P1003.1b-1993, p. 81
+ *
+ * $Id$
+ */
+
+#include <time.h>
+#include <unistd.h>
+
+#include <rtems.h>
+
+#if !defined(RTEMS_POSIX_API)
+unsigned int sleep(
+ unsigned int seconds
+)
+{
+ rtems_status_code status;
+ rtems_interval ticks_per_second;
+ rtems_interval ticks;
+
+ status = rtems_clock_get(
+ RTEMS_CLOCK_GET_TICKS_PER_SECOND,
+ &ticks_per_second
+ );
+
+ ticks = seconds * ticks_per_second;
+
+ status = rtems_task_wake_after( ticks );
+
+ /*
+ * Returns the "unslept" amount of time. In RTEMS signals are not
+ * interruptable, so tasks really sleep all of the requested time.
+ */
+
+ return 0;
+}
+#endif
diff --git a/cpukit/libcsupport/src/open.c b/cpukit/libcsupport/src/open.c
new file mode 100644
index 0000000000..66c5367f76
--- /dev/null
+++ b/cpukit/libcsupport/src/open.c
@@ -0,0 +1,221 @@
+/*
+ * open() - POSIX 1003.1 5.3.1 - Open a File
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+#include <fcntl.h>
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+#include <unistd.h>
+
+/*
+ * Returns file descriptor on success or -1 and errno set to one of the
+ * following:
+ *
+ * EACCESS - Seach permission is denied on a component of the path prefix,
+ * or the file exists and the permissions specified by the
+ * flags are denied, or the file does not exist and write
+ * permission is denied for the parent directory of the file
+ * to be created, or O_TRUNC is specified and write permission
+ * is denied.
+ * EEXIST - O_CREAT and O_EXCL are set and the named file exists.
+ * EINTR - The open( operation was interrupted by a signal.
+ * EINVAL - This implementation does not support synchronized IO for this
+ * file.
+ * EISDIR - The named file is a directory and the flags argument
+ * specified write or read/write access.
+ * EMFILE - Too many file descriptors are in used by this process.
+ * ENAMETOOLONG -
+ * The length of the path exceeds PATH_MAX or a pathname
+ * component is longer than NAME_MAX while POSIX_NO_TRUNC
+ * is in effect.
+ * ENFILE - Too many files are open in the system.
+ * ENOENT - O_CREAT is not set and and the anmed file does not exist,
+ * or O_CREAT is set and either the path prefix does not exist
+ * or the path argument points to an empty string.
+ * ENOSPC - The directory or file system that would contain the new file
+ * cannot be extended.
+ * ENOTDIR - A component of the path prefix is not a directory.
+ * ENXIO - O_NONBLOCK is set, the named file is a FIFO, O_WRONLY is
+ * set, and no process has the file open for reading.
+ * EROFS - The named file resides on a read-only file system and either
+ * O_WRONLY, O_RDWR, O_CREAT (if the file does not exist), or
+ * O_TRUNC is set in the flags argument.
+ */
+
+int open(
+ const char *pathname,
+ int flags,
+ ...
+)
+{
+ va_list ap;
+ int mode;
+ int rc;
+ rtems_libio_t *iop = 0;
+ int status;
+ rtems_filesystem_location_info_t loc;
+ rtems_filesystem_location_info_t *loc_to_free = NULL;
+ int eval_flags;
+
+
+ /*
+ * Set the Evaluation flags
+ */
+
+ eval_flags = 0;
+ status = flags + 1;
+ if ( ( status & _FREAD ) == _FREAD )
+ eval_flags |= RTEMS_LIBIO_PERMS_READ;
+ if ( ( status & _FWRITE ) == _FWRITE )
+ eval_flags |= RTEMS_LIBIO_PERMS_WRITE;
+
+
+ va_start(ap, flags);
+
+ mode = va_arg( ap, int );
+
+ /*
+ * NOTE: This comment is OBSOLETE. The proper way to do this now
+ * would be to support a magic mounted file system.
+ *
+ * Additional external I/O handlers would be supported by adding
+ * code to pick apart the pathname appropriately. The networking
+ * code does not require changes here since network file
+ * descriptors are obtained using socket(), not open().
+ */
+
+ /* allocate a file control block */
+ iop = rtems_libio_allocate();
+ if ( iop == 0 ) {
+ rc = ENFILE;
+ goto done;
+ }
+
+ /*
+ * See if the file exists.
+ */
+
+ status = rtems_filesystem_evaluate_path(
+ pathname, eval_flags, &loc, TRUE );
+
+ if ( status == -1 ) {
+ if ( errno != ENOENT ) {
+ rc = errno;
+ goto done;
+ }
+
+ /* If the file does not exist and we are not trying to create it--> error */
+ if ( !(flags & O_CREAT) ) {
+ rc = ENOENT;
+ goto done;
+ }
+
+ /* Create the node for the new regular file */
+ rc = mknod( pathname, S_IFREG | mode, 0LL );
+ if ( rc ) {
+ rc = errno;
+ goto done;
+ }
+
+ /* Sanity check to see if the file name exists after the mknod() */
+ status = rtems_filesystem_evaluate_path( pathname, 0x0, &loc, TRUE );
+ if ( status != 0 ) { /* The file did not exist */
+ rc = EACCES;
+ goto done;
+ }
+
+ } else if ((flags & (O_EXCL|O_CREAT)) == (O_EXCL|O_CREAT)) {
+ /* We were trying to create a file that already exists */
+ rc = EEXIST;
+ loc_to_free = &loc;
+ goto done;
+ }
+
+ loc_to_free = &loc;
+
+ /*
+ * Fill in the file control block based on the loc structure
+ * returned by successful path evaluation.
+ */
+
+ iop->handlers = loc.handlers;
+ iop->file_info = loc.node_access;
+ iop->flags |= rtems_libio_fcntl_flags( flags );
+ iop->pathinfo = loc;
+
+ if ( !iop->handlers->open_h ) {
+ rc = ENOTSUP;
+ goto done;
+ }
+
+ rc = (*iop->handlers->open_h)( iop, pathname, flags, mode );
+ if ( rc )
+ goto done;
+
+ /*
+ * Optionally truncate the file.
+ */
+
+ if ( (flags & O_TRUNC) == O_TRUNC ) {
+ rc = ftruncate( iop - rtems_libio_iops, 0 );
+ if ( rc ) {
+ close( iop - rtems_libio_iops );
+ /* those are released by close(): */
+ iop = 0;
+ loc_to_free = NULL;
+ }
+ }
+
+ /*
+ * Single exit and clean up path.
+ */
+
+done:
+ va_end(ap);
+
+ if ( rc ) {
+ if ( iop )
+ rtems_libio_free( iop );
+ if ( loc_to_free )
+ rtems_filesystem_freenode( loc_to_free );
+ rtems_set_errno_and_return_minus_one( rc );
+ }
+
+ return iop - rtems_libio_iops;
+}
+
+/*
+ * _open_r
+ *
+ * This is the Newlib dependent reentrant version of open().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+int _open_r(
+ struct _reent *ptr,
+ const char *buf,
+ int flags,
+ int mode
+)
+{
+ return open( buf, flags, mode );
+}
+#endif
diff --git a/cpukit/libcsupport/src/opendir.c b/cpukit/libcsupport/src/opendir.c
new file mode 100644
index 0000000000..98129bc294
--- /dev/null
+++ b/cpukit/libcsupport/src/opendir.c
@@ -0,0 +1,89 @@
+/*
+ * opendir() - POSIX 1003.1b - XXX
+ *
+ * This was copied from Newlib 1.8.0.
+ *
+ *
+ * Copyright (c) 1983 Regents of the University of California.
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)opendir.c 5.11 (Berkeley) 2/23/91";
+#endif /* LIBC_SCCS and not lint */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+/*
+ * open a directory.
+ */
+DIR *
+opendir(name)
+ const char *name;
+{
+ register DIR *dirp;
+ register int fd;
+
+ if ((fd = open(name, 0)) == -1)
+ return NULL;
+ if (fcntl(fd, F_SETFD, 1) == -1 ||
+ (dirp = (DIR *)malloc(sizeof(DIR))) == NULL) {
+ close (fd);
+ return NULL;
+ }
+ /*
+ * If CLSIZE is an exact multiple of DIRBLKSIZ, use a CLSIZE
+ * buffer that it cluster boundary aligned.
+ * Hopefully this can be a big win someday by allowing page trades
+ * to user space to be done by getdirentries()
+ */
+ dirp->dd_buf = malloc (512);
+ dirp->dd_len = 512;
+
+ if (dirp->dd_buf == NULL) {
+ close (fd);
+ return NULL;
+ }
+ dirp->dd_fd = fd;
+ dirp->dd_loc = 0;
+ dirp->dd_seek = 0;
+ /*
+ * Set up seek point for rewinddir.
+ */
+ return dirp;
+}
diff --git a/cpukit/libcsupport/src/pathconf.c b/cpukit/libcsupport/src/pathconf.c
new file mode 100644
index 0000000000..d16f899e95
--- /dev/null
+++ b/cpukit/libcsupport/src/pathconf.c
@@ -0,0 +1,41 @@
+/*
+ * pathconf() - POSIX 1003.1b - 5.7.1 - Configurable Pathname Varables
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+long pathconf(
+ const char *path,
+ int name
+)
+{
+ int status;
+ int fd;
+
+ fd = open( path, O_RDONLY );
+ if ( fd == -1 )
+ return -1;
+
+ status = fpathconf( fd, name );
+
+ (void) close( fd );
+
+ return status;
+}
diff --git a/cpukit/libcsupport/src/pipe.c b/cpukit/libcsupport/src/pipe.c
new file mode 100644
index 0000000000..57a682e55b
--- /dev/null
+++ b/cpukit/libcsupport/src/pipe.c
@@ -0,0 +1,26 @@
+/*
+ * pipe() - POSIX 1003.1b 6.1.1 Create an Inter-Process Channel
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+
+int pipe(
+ int filsdes[2]
+)
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/cpukit/libcsupport/src/printk.c b/cpukit/libcsupport/src/printk.c
new file mode 100644
index 0000000000..2db31f0bd9
--- /dev/null
+++ b/cpukit/libcsupport/src/printk.c
@@ -0,0 +1,157 @@
+/*-------------------------------------------------------------------------+
+| printk.c v1.1 - PC386 BSP - 1997/08/07
++--------------------------------------------------------------------------+
+| (C) Copyright 1997 -
+| - NavIST Group - Real-Time Distributed Systems and Industrial Automation
+|
+| http://pandora.ist.utl.pt
+|
+| Instituto Superior Tecnico * Lisboa * PORTUGAL
++--------------------------------------------------------------------------+
+| Disclaimer:
+|
+| This file is provided "AS IS" without warranty of any kind, either
+| expressed or implied.
++--------------------------------------------------------------------------+
+| This code is based on code by: Jose Rufino - IST
+|
+| $Id$
++--------------------------------------------------------------------------*/
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <rtems/bspIo.h>
+
+/*-------------------------------------------------------------------------+
+| Function: printNum
+| Description: print number in a given base.
+| Global Variables: None.
+| Arguments: num - number to print, base - base used to print the number.
+| Returns: Nothing.
++--------------------------------------------------------------------------*/
+static void
+printNum(long unsigned int num, int base, int sign, int maxwidth, int lead)
+{
+ long unsigned int n;
+ int count;
+ char toPrint[20];
+
+ if ( (sign == 1) && ((long)num < 0) ) {
+ BSP_output_char('-');
+ num = -num;
+ if (maxwidth) maxwidth--;
+ }
+
+ count = 0;
+ while ((n = num / base) > 0) {
+ toPrint[count++] = (num - (n*base));
+ num = n ;
+ }
+ toPrint[count++] = num;
+
+ if (maxwidth) {
+ for (n=maxwidth-count ; n ; n-- )
+ BSP_output_char(lead);
+ }
+
+ for (n = 0; n < count; n++){
+ BSP_output_char("0123456789ABCDEF"[(int)(toPrint[count-(n+1)])]);
+ }
+} /* printNum */
+
+
+/*-------------------------------------------------------------------------+
+| Function: printk
+| Description: a simplified version of printf intended for use when the
+ console is not yet initialized or in ISR's.
+| Global Variables: None.
+| Arguments: as in printf: fmt - format string, ... - unnamed arguments.
+| Returns: Nothing.
++--------------------------------------------------------------------------*/
+void
+vprintk(char *fmt, va_list ap)
+{
+ char c, *str;
+ int lflag, base, sign, width, lead;
+ /* unsigned int level; */
+
+ /* _CPU_ISR_Disable(level); */
+
+ for (; *fmt != '\0'; fmt++)
+ {
+ lflag = 0;
+ base = 0;
+ sign = 0;
+ width = 0;
+ lead = ' ';
+ if (*fmt == '%')
+ {
+ fmt++;
+ if (*fmt == '0' ) {
+ lead = '0';
+ fmt++;
+ }
+ while (*fmt >= '0' && *fmt <= '9' ) {
+ width *= 10;
+ width += (*fmt - '0');
+ fmt++;
+ }
+
+ if ((c = *fmt) == 'l')
+ {
+ lflag = 1;
+ c = *++fmt;
+ }
+ switch (c)
+ {
+ case 'o': case 'O': base = 8; sign = 0; break;
+ case 'i': case 'I':
+ case 'd': case 'D': base = 10; sign = 1; break;
+ case 'u': case 'U': base = 10; sign = 0; break;
+ case 'x': case 'X': base = 16; sign = 0; break;
+ case 's':
+ for (str = va_arg(ap, char *); *str; str++)
+ BSP_output_char(*str);
+ break;
+ case 'c':
+#if 0
+#if defined(_TMS320C3x) || defined(_TMS320C4x)
+ BSP_output_char(va_arg(ap, int));
+#else
+ BSP_output_char(va_arg(ap, char));
+#endif
+#else
+ BSP_output_char(va_arg(ap, int));
+#endif
+ break;
+ default:
+ BSP_output_char(c);
+ break;
+ } /* switch*/
+
+ if (base)
+ printNum(lflag ? va_arg(ap, long int) : (long int)va_arg(ap, int),
+ base, sign, width, lead);
+ }
+ else
+ {
+ BSP_output_char(*fmt);
+ }
+ }
+ /* _CPU_ISR_Enable(level); */
+
+} /* vprintk */
+
+void
+printk(char *fmt, ...)
+{
+ va_list ap; /* points to each unnamed argument in turn */
+
+ va_start(ap, fmt); /* make ap point to 1st unnamed arg */
+ vprintk(fmt, ap);
+ va_end(ap); /* clean up when done */
+} /* printk */
diff --git a/cpukit/libcsupport/src/privateenv.c b/cpukit/libcsupport/src/privateenv.c
new file mode 100644
index 0000000000..e1a5e674e3
--- /dev/null
+++ b/cpukit/libcsupport/src/privateenv.c
@@ -0,0 +1,163 @@
+/*
+ * Instantatiate a private user environment for the calling thread.
+ *
+ * Submitted by: fernando.ruiz@ctv.es (correo@fernando-ruiz.com)
+ *
+ * COPYRIGHT (c) 1989-2000.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h> /* free */
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <rtems/libio_.h>
+
+extern Chain_Control rtems_filesystem_mount_table_control;
+
+#define THE_ROOT_FS_LOC \
+ (((rtems_filesystem_mount_table_entry_t*)\
+ rtems_filesystem_mount_table_control.first)->mt_fs_root)
+
+/* cleanup a user environment
+ * NOTE: this must be called with
+ * thread dispatching disabled!
+ */
+static void
+free_user_env(void *venv)
+{
+ rtems_user_env_t *env = (rtems_user_env_t*) venv ;
+
+ if (env != &rtems_global_user_env
+#ifdef HAVE_USERENV_REFCNT
+ && --env->refcnt <= 0
+#endif
+ ) {
+ rtems_filesystem_freenode( &env->current_directory);
+ rtems_filesystem_freenode( &env->root_directory);
+ free(env);
+ }
+}
+
+rtems_status_code rtems_libio_set_private_env(void) {
+ rtems_status_code sc;
+ rtems_id task_id;
+ rtems_filesystem_location_info_t loc;
+
+ sc=rtems_task_ident(RTEMS_SELF,0,&task_id);
+ if (sc != RTEMS_SUCCESSFUL) return sc;
+
+ /* Only for the first time a malloc is necesary */
+ if (rtems_current_user_env==&rtems_global_user_env) {
+ rtems_user_env_t *tmp = malloc(sizeof(rtems_user_env_t));
+ if (!tmp)
+ return RTEMS_NO_MEMORY;
+
+#ifdef HAVE_USERENV_REFCNT
+ tmp->refcnt = 1;
+#endif
+
+ sc = rtems_task_variable_add(RTEMS_SELF,(void*)&rtems_current_user_env,(void(*)(void *))free_user_env);
+ if (sc != RTEMS_SUCCESSFUL) {
+ /* don't use free_user_env because the pathlocs are
+ * not initialized yet
+ */
+ free(tmp);
+ return sc;
+ }
+ rtems_current_user_env = tmp;
+ };
+
+ *rtems_current_user_env = rtems_global_user_env; /* get the global values*/
+ rtems_current_user_env->task_id=task_id; /* mark the local values*/
+
+ /* get a clean root */
+ rtems_filesystem_root = THE_ROOT_FS_LOC;
+
+ /* Clone the pathlocs. In contrast to most other
+ * code we must _not_ free the original locs because
+ * what we are trying to do here is forking off
+ * clones.
+ */
+
+ rtems_filesystem_evaluate_path("/", 0, &loc, 0);
+ rtems_filesystem_root = loc;
+ rtems_filesystem_evaluate_path("/", 0, &loc, 0);
+ rtems_filesystem_current = loc;
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * Share a same private environment beetween two task:
+ * Task_id (remote) and RTEMS_SELF(current).
+ */
+
+/* NOTE:
+ *
+ * THIS CODE HAS NO PROTECTION IMPLEMENTED
+ *
+ * Tasks who wish to share their environments must
+ *
+ * a) assert that no participants are concurrently
+ * executing
+ * libio_share_private_env() and/or libio_set_private_env()
+ *
+ * b) mutex access to rtems_filesystem_current, rtems_filesytem_root
+ * while changing any of those (chdir(), chroot()).
+ */
+
+#ifndef HAVE_USERENV_REFCNT
+rtems_status_code rtems_libio_share_private_env(rtems_id task_id) {
+ rtems_status_code sc;
+ rtems_user_env_t * shared_user_env;
+ rtems_id current_task_id;
+
+ sc=rtems_task_ident(RTEMS_SELF,0,&current_task_id);
+ if (sc != RTEMS_SUCCESSFUL) return sc;
+
+ if (rtems_current_user_env->task_id==current_task_id) {
+ /* kill the current user env & task_var*/
+ rtems_user_env_t *tmp = rtems_current_user_env;
+ sc = rtems_task_variable_delete(RTEMS_SELF,(void*)&rtems_current_user_env);
+ if (sc != RTEMS_SUCCESSFUL) return sc;
+ free_user_env(tmp);
+ };
+
+ /* AT THIS POINT, rtems_current_user_env is DANGLING */
+
+ sc = rtems_task_variable_get(task_id,(void*)&rtems_current_user_env,
+ (void*)&shared_user_env );
+ if (sc != RTEMS_SUCCESSFUL)
+ goto bailout;
+
+ sc = rtems_task_variable_add(RTEMS_SELF,(void*)&rtems_current_user_env,free_user_env);
+ if (sc != RTEMS_SUCCESSFUL)
+ goto bailout;
+
+ /* the current_user_env is the same pointer that remote env */
+ rtems_current_user_env = shared_user_env;
+
+ /* increase the reference count */
+#ifdef HAVE_USERENV_REFCNT
+ rtems_current_user_env->refcnt++;
+#endif
+
+ return RTEMS_SUCCESSFUL;
+
+bailout:
+ /* fallback to the global env */
+ rtems_current_user_env = &rtems_global_user_env;
+ return sc;
+}
+#endif
diff --git a/cpukit/libcsupport/src/read.c b/cpukit/libcsupport/src/read.c
new file mode 100644
index 0000000000..a57426666c
--- /dev/null
+++ b/cpukit/libcsupport/src/read.c
@@ -0,0 +1,71 @@
+/*
+ * read() - POSIX 1003.1b 6.4.1 - Read From a File
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+ssize_t read(
+ int fd,
+ void *buffer,
+ size_t count
+)
+{
+ int rc; /* XXX change to a size_t when prototype is fixed */
+ rtems_libio_t *iop;
+
+ rtems_libio_check_fd( fd );
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_is_open(iop);
+ rtems_libio_check_buffer( buffer );
+ rtems_libio_check_count( count );
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_READ );
+
+ /*
+ * Now process the read().
+ */
+
+ if ( !iop->handlers->read_h )
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+
+ rc = (*iop->handlers->read_h)( iop, buffer, count );
+
+ if ( rc > 0 )
+ iop->offset += rc;
+
+ return rc;
+}
+
+/*
+ * _read_r
+ *
+ * This is the Newlib dependent reentrant version of read().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+_ssize_t _read_r(
+ struct _reent *ptr,
+ int fd,
+ void *buf,
+ size_t nbytes
+)
+{
+ return read( fd, buf, nbytes );
+}
+#endif
diff --git a/cpukit/libcsupport/src/readdir.c b/cpukit/libcsupport/src/readdir.c
new file mode 100644
index 0000000000..bcff3d951a
--- /dev/null
+++ b/cpukit/libcsupport/src/readdir.c
@@ -0,0 +1,90 @@
+/*
+ * readdir() - POSIX 1003.1b - XXX
+ *
+ * This was copied from Newlib 1.8.0.
+ *
+ *
+ * Copyright (c) 1983 Regents of the University of California.
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)readdir.c 5.7 (Berkeley) 6/1/90";
+#endif /* LIBC_SCCS and not lint */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <dirent.h>
+
+int getdents(
+ int dd_fd,
+ char *dd_buf,
+ int dd_len
+);
+
+/*
+ * get next entry in a directory.
+ */
+struct dirent *
+readdir(dirp)
+register DIR *dirp; {
+ register struct dirent *dp;
+
+ if ( !dirp )
+ return NULL;
+
+ for (;;) {
+ if (dirp->dd_loc == 0) {
+ dirp->dd_size = getdents (dirp->dd_fd,
+ dirp->dd_buf,
+ dirp->dd_len);
+
+ if (dirp->dd_size <= 0)
+ return NULL;
+ }
+ if (dirp->dd_loc >= dirp->dd_size) {
+ dirp->dd_loc = 0;
+ continue;
+ }
+ dp = (struct dirent *)(dirp->dd_buf + dirp->dd_loc);
+ if ((int)dp & 03) /* bogus pointer check */
+ return NULL;
+ if (dp->d_reclen <= 0 ||
+ dp->d_reclen > dirp->dd_len + 1 - dirp->dd_loc)
+ return NULL;
+ dirp->dd_loc += dp->d_reclen;
+ if (dp->d_ino == 0)
+ continue;
+ return (dp);
+ }
+}
diff --git a/cpukit/libcsupport/src/readdir_r.c b/cpukit/libcsupport/src/readdir_r.c
new file mode 100644
index 0000000000..9ddb84f97c
--- /dev/null
+++ b/cpukit/libcsupport/src/readdir_r.c
@@ -0,0 +1,22 @@
+/*
+ * readdir_r - reentrant version of readdir()
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <dirent.h>
+#include <errno.h>
+#include <stdio.h>
+
+/*
+ * The RTEMS version of readdir is already thread-safe.
+ */
+
+int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
+{
+ *result = readdir(dirp);
+ if (*result)
+ *entry = **result;
+ return *result ? 0 : errno;
+}
diff --git a/cpukit/libcsupport/src/readlink.c b/cpukit/libcsupport/src/readlink.c
new file mode 100644
index 0000000000..f2ec9781c5
--- /dev/null
+++ b/cpukit/libcsupport/src/readlink.c
@@ -0,0 +1,57 @@
+/*
+ * readlink() - POSIX 1003.1b - X.X.X - XXX
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int readlink(
+ const char *pathname,
+ char *buf,
+ int bufsize
+)
+{
+ rtems_filesystem_location_info_t loc;
+ int result;
+
+ if (!buf)
+ rtems_set_errno_and_return_minus_one( EFAULT );
+
+ result = rtems_filesystem_evaluate_path( pathname, 0, &loc, FALSE );
+ if ( result != 0 )
+ return -1;
+
+ if ( !loc.ops->node_type_h ){
+ rtems_filesystem_freenode( &loc );
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+ }
+
+ if ( (*loc.ops->node_type_h)( &loc ) != RTEMS_FILESYSTEM_SYM_LINK ){
+ rtems_filesystem_freenode( &loc );
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ }
+
+ if ( !loc.ops->readlink_h ){
+ rtems_filesystem_freenode( &loc );
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+ }
+
+ result = (*loc.ops->readlink_h)( &loc, buf, bufsize );
+
+ rtems_filesystem_freenode( &loc );
+
+ return result;
+}
diff --git a/cpukit/libcsupport/src/rewinddir.c b/cpukit/libcsupport/src/rewinddir.c
new file mode 100644
index 0000000000..f4542d2db6
--- /dev/null
+++ b/cpukit/libcsupport/src/rewinddir.c
@@ -0,0 +1,39 @@
+/*
+ * rewinddir() - POSIX 1003.1b - XXX
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <assert.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+
+void rewinddir(
+ DIR *dirp
+)
+{
+ off_t status;
+
+ if ( !dirp )
+ return;
+
+ status = lseek( dirp->dd_fd, 0, SEEK_SET );
+
+ if( status == -1 )
+ return;
+
+ dirp->dd_loc = 0;
+}
diff --git a/cpukit/libcsupport/src/rmdir.c b/cpukit/libcsupport/src/rmdir.c
new file mode 100644
index 0000000000..59d43ff278
--- /dev/null
+++ b/cpukit/libcsupport/src/rmdir.c
@@ -0,0 +1,76 @@
+/*
+ * rmdir() - POSIX 1003.1b - 5.2.2 - Remove a Directory
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int rmdir(
+ const char *pathname
+)
+{
+ rtems_filesystem_location_info_t loc;
+ int result;
+
+ /*
+ * Get the node where we wish to go.
+ */
+
+ result = rtems_filesystem_evaluate_path( pathname, 0, &loc, FALSE );
+ if ( result != 0 )
+ return -1;
+
+ result = rtems_filesystem_evaluate_parent(RTEMS_LIBIO_PERMS_WRITE, &loc );
+ if (result != 0){
+ rtems_filesystem_freenode( &loc );
+ return -1;
+ }
+
+ /*
+ * Verify you can remove this node as a directory.
+ */
+
+ if ( !loc.ops->node_type_h ){
+ rtems_filesystem_freenode( &loc );
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+ }
+
+ if ( (*loc.ops->node_type_h)( &loc ) != RTEMS_FILESYSTEM_DIRECTORY ){
+ rtems_filesystem_freenode( &loc );
+ rtems_set_errno_and_return_minus_one( ENOTDIR );
+ }
+
+ /*
+ * Use the filesystems rmnod to remove the node.
+ */
+
+ if ( !loc.handlers->rmnod_h ){
+ rtems_filesystem_freenode( &loc );
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+ }
+
+ result = (*loc.handlers->rmnod_h)( &loc );
+
+ rtems_filesystem_freenode( &loc );
+
+ return result;
+}
diff --git a/cpukit/libcsupport/src/scandir.c b/cpukit/libcsupport/src/scandir.c
new file mode 100644
index 0000000000..a17c070cc9
--- /dev/null
+++ b/cpukit/libcsupport/src/scandir.c
@@ -0,0 +1,168 @@
+/*
+ * scandir() - POSIX 1003.1b - XXX
+ *
+ * This was copied from Newlib 1.8.0.
+ *
+ *
+ * Copyright (c) 1983 Regents of the University of California.
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)scandir.c 5.10 (Berkeley) 2/23/91";
+#endif /* LIBC_SCCS and not lint */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ * Scan the directory dirname calling select to make a list of selected
+ * directory entries then sort using qsort and compare routine dcomp.
+ * Returns the number of entries and a pointer to a list of pointers to
+ * struct dirent (through namelist). Returns -1 if there were any errors.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * The DIRSIZ macro gives the minimum record length which will hold
+ * the directory entry. This requires the amount of space in struct dirent
+ * without the d_name field, plus enough space for the name with a terminating
+ * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
+ */
+#undef DIRSIZ
+/*
+#define DIRSIZ(dp) \
+ ((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
+*/
+
+#define DIRSIZ(dp) \
+ ((sizeof (struct dirent) - (NAME_MAX+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
+
+#ifndef __P
+#define __P(args) ()
+#endif
+
+int
+scandir(dirname, namelist, select, dcomp)
+ const char *dirname;
+ struct dirent ***namelist;
+ int (*select) __P((struct dirent *));
+ int (*dcomp) __P((const void *, const void *));
+{
+ register struct dirent *d = NULL;
+ register struct dirent *p = NULL;
+ register struct dirent **names = NULL;
+ register size_t nitems = 0;
+ struct stat stb;
+ long arraysz;
+ DIR *dirp = NULL;
+ int i;
+
+ if ((dirp = opendir(dirname)) == NULL)
+ return(-1);
+ if (fstat(dirp->dd_fd, &stb) < 0)
+ goto cleanup_and_bail;
+
+ /*
+ * estimate the array size by taking the size of the directory file
+ * and dividing it by a multiple of the minimum size entry.
+ */
+ arraysz = (stb.st_size / 24);
+ names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *));
+ if (names == NULL)
+ goto cleanup_and_bail;
+
+ while ((d = readdir(dirp)) != NULL) {
+ if (select != NULL && !(*select)(d))
+ continue; /* just selected names */
+ /*
+ * Make a minimum size copy of the data
+ */
+ p = (struct dirent *)malloc(DIRSIZ(d));
+ if (p == NULL)
+ goto cleanup_and_bail;
+ p->d_ino = d->d_ino;
+ p->d_reclen = d->d_reclen;
+ p->d_namlen = d->d_namlen;
+ strncpy(p->d_name, d->d_name, p->d_namlen + 1);
+ /*
+ * Check to make sure the array has space left and
+ * realloc the maximum size.
+ */
+ if (++nitems >= arraysz) {
+ if (fstat(dirp->dd_fd, &stb) < 0)
+ goto cleanup_and_bail; /* just might have grown */
+ arraysz = stb.st_size / 12;
+ names = (struct dirent **)realloc((char *)names,
+ arraysz * sizeof(struct dirent *));
+ if (names == NULL)
+ goto cleanup_and_bail;
+ }
+ names[nitems-1] = p;
+ }
+ closedir(dirp);
+ if (nitems && dcomp != NULL){
+ qsort(names, nitems, sizeof(struct dirent *), dcomp);
+ }
+ *namelist = names;
+ return(nitems);
+
+cleanup_and_bail:
+
+ if ( dirp )
+ closedir( dirp );
+
+ if ( names ) {
+ for (i=0; i < nitems; i++ )
+ free( names[i] );
+ free( names );
+ }
+
+ return(-1);
+}
+
+/*
+ * Alphabetic order comparison routine for those who want it.
+ */
+int
+alphasort(d1, d2)
+ const void *d1;
+ const void *d2;
+{
+ return(strcmp((*(struct dirent **)d1)->d_name,
+ (*(struct dirent **)d2)->d_name));
+}
diff --git a/cpukit/libcsupport/src/seekdir.c b/cpukit/libcsupport/src/seekdir.c
new file mode 100644
index 0000000000..be96bb50d3
--- /dev/null
+++ b/cpukit/libcsupport/src/seekdir.c
@@ -0,0 +1,44 @@
+/*
+ * seekdir() - POSIX 1003.1b - XXX
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/param.h>
+#include <assert.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+
+void seekdir(
+ DIR *dirp,
+ long loc
+)
+{
+ off_t status;
+
+ if ( !dirp )
+ return;
+
+ status = lseek( dirp->dd_fd, loc, SEEK_SET );
+
+ /*
+ * This is not a nice way to error out, but we have no choice here.
+ */
+
+ if ( status == -1 )
+ return;
+
+ dirp->dd_loc = 0;
+}
diff --git a/cpukit/libcsupport/src/setpgid.c b/cpukit/libcsupport/src/setpgid.c
new file mode 100644
index 0000000000..26786cc552
--- /dev/null
+++ b/cpukit/libcsupport/src/setpgid.c
@@ -0,0 +1,29 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <limits.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/seterr.h>
+
+/*PAGE
+ *
+ * 4.3.3 Set Process Group ID for Job Control, P1003.1b-1993, p. 89
+ */
+
+int setpgid(
+ pid_t pid,
+ pid_t pgid
+)
+{
+ rtems_set_errno_and_return_minus_one( ENOSYS );
+}
diff --git a/cpukit/libcsupport/src/setsid.c b/cpukit/libcsupport/src/setsid.c
new file mode 100644
index 0000000000..ae8cdbbd62
--- /dev/null
+++ b/cpukit/libcsupport/src/setsid.c
@@ -0,0 +1,26 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <limits.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/seterr.h>
+
+/*PAGE
+ *
+ * 4.3.2 Create Session and Set Process Group ID, P1003.1b-1993, p. 88
+ */
+
+pid_t setsid( void )
+{
+ rtems_set_errno_and_return_minus_one( EPERM );
+}
diff --git a/cpukit/libcsupport/src/stat.c b/cpukit/libcsupport/src/stat.c
new file mode 100644
index 0000000000..a39deda79e
--- /dev/null
+++ b/cpukit/libcsupport/src/stat.c
@@ -0,0 +1,104 @@
+/*
+ * stat() - POSIX 1003.1b 5.6.2 - Get File Status
+ *
+ * Reused from lstat().
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ * lstat() and stat() share the same implementation with a minor
+ * difference on how links are evaluated.
+ */
+
+#ifndef _STAT_NAME
+#define _STAT_NAME stat
+#define _STAT_R_NAME _stat_r
+#define _STAT_FOLLOW_LINKS TRUE
+#endif
+
+
+#include <rtems.h>
+
+#if !defined(RTEMS_UNIX)
+
+#include <rtems/libio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int _STAT_NAME(
+ const char *path,
+ struct stat *buf
+)
+{
+ int status;
+ rtems_filesystem_location_info_t loc;
+
+ /*
+ * Check to see if we were passed a valid pointer.
+ */
+
+ if ( !buf )
+ rtems_set_errno_and_return_minus_one( EFAULT );
+
+ status = rtems_filesystem_evaluate_path( path, 0, &loc, _STAT_FOLLOW_LINKS );
+ if ( status != 0 )
+ return -1;
+
+ if ( !loc.handlers->fstat_h ){
+ rtems_filesystem_freenode( &loc );
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+ }
+
+ /*
+ * Zero out the stat structure so the various support
+ * versions of stat don't have to.
+ */
+
+ memset( buf, 0, sizeof(struct stat) );
+
+ status = (*loc.handlers->fstat_h)( &loc, buf );
+
+ rtems_filesystem_freenode( &loc );
+
+ return status;
+}
+#endif
+
+/*
+ * _stat_r, _lstat_r
+ *
+ * This is the Newlib dependent reentrant version of stat() and lstat().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+int _STAT_R_NAME(
+ struct _reent *ptr,
+ const char *path,
+ struct stat *buf
+)
+{
+ return _STAT_NAME( path, buf );
+}
+#endif
diff --git a/cpukit/libcsupport/src/strlcat.c b/cpukit/libcsupport/src/strlcat.c
new file mode 100644
index 0000000000..e0424eef7b
--- /dev/null
+++ b/cpukit/libcsupport/src/strlcat.c
@@ -0,0 +1,41 @@
+/*
+ * utils.c - various utility functions used in pppd.
+ *
+ * Copyright (c) 1999 The Australian National University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the Australian National University. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#ifndef HAVE_STRLCAT
+/*
+ * strlcat - like strcat/strncat, doesn't overflow destination buffer,
+ * always leaves destination null-terminated (for len > 0).
+ */
+size_t
+strlcat(dest, src, len)
+ char *dest;
+ const char *src;
+ size_t len;
+{
+ size_t dlen = strlen(dest);
+
+ return dlen + strlcpy(dest + dlen, src, (len > dlen? len - dlen: 0));
+}
+#endif
diff --git a/cpukit/libcsupport/src/strlcpy.c b/cpukit/libcsupport/src/strlcpy.c
new file mode 100644
index 0000000000..2773e877cb
--- /dev/null
+++ b/cpukit/libcsupport/src/strlcpy.c
@@ -0,0 +1,49 @@
+/*
+ * utils.c - various utility functions used in pppd.
+ *
+ * Copyright (c) 1999 The Australian National University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the Australian National University. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#ifndef HAVE_STRLCPY
+/*
+ * strlcpy - like strcpy/strncpy, doesn't overflow destination buffer,
+ * always leaves destination null-terminated (for len > 0).
+ */
+size_t
+strlcpy(dest, src, len)
+ char *dest;
+ const char *src;
+ size_t len;
+{
+ size_t ret = strlen(src);
+
+ if (len != 0) {
+ if (ret < len)
+ strcpy(dest, src);
+ else {
+ strncpy(dest, src, len - 1);
+ dest[len-1] = 0;
+ }
+ }
+ return ret;
+}
+#endif
diff --git a/cpukit/libcsupport/src/symlink.c b/cpukit/libcsupport/src/symlink.c
new file mode 100644
index 0000000000..59c15787bd
--- /dev/null
+++ b/cpukit/libcsupport/src/symlink.c
@@ -0,0 +1,46 @@
+/*
+ * symlink() - POSIX 1003.1b - X.X.X - XXX
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int symlink(
+ const char *actualpath,
+ const char *sympath
+)
+{
+ rtems_filesystem_location_info_t loc;
+ int i;
+ const char *name_start;
+ int result;
+
+ rtems_filesystem_get_start_loc( sympath, &i, &loc );
+ result = (*loc.ops->evalformake_h)( &sympath[i], &loc, &name_start );
+ if ( result != 0 )
+ return -1;
+
+ if ( !loc.ops->symlink_h ) {
+ rtems_filesystem_freenode( &loc );
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+ }
+
+ result = (*loc.ops->symlink_h)( &loc, actualpath, name_start);
+
+ rtems_filesystem_freenode( &loc );
+
+ return result;
+}
diff --git a/cpukit/libcsupport/src/sync.c b/cpukit/libcsupport/src/sync.c
new file mode 100644
index 0000000000..8d1f52e725
--- /dev/null
+++ b/cpukit/libcsupport/src/sync.c
@@ -0,0 +1,89 @@
+/*
+ * sync() - XXX ??? where is this defined
+ *
+ * This function operates by as follows:
+ * for all threads
+ * for all FILE *
+ * fsync()
+ * fdatasync()
+ *
+ * COPYRIGHT (c) 1989-2003.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* Since we compile with strict ANSI we need to undef it to get
+ * prototypes for extensions
+ */
+#undef __STRICT_ANSI__
+int fdatasync(int); /* still not always prototyped */
+
+
+#include <unistd.h>
+#include <stdio.h>
+
+#include <rtems.h>
+/*
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+*/
+
+/* XXX check standards -- Linux version appears to be void */
+void _fwalk(struct _reent *, void *);
+
+
+static void sync_wrapper(FILE *f)
+{
+ int fn = fileno(f);
+
+ fsync(fn);
+ fdatasync(fn);
+}
+
+/* iterate over all FILE *'s for this thread */
+static void sync_per_thread(Thread_Control *t)
+{
+ struct _reent *current_reent;
+
+ /*
+ * The sync_wrapper() function will operate on the current thread's
+ * reent structure so we will temporarily use that.
+ */
+ current_reent = _Thread_Executing->libc_reent;
+ _Thread_Executing->libc_reent = t->libc_reent;
+ _fwalk (t->libc_reent, sync_wrapper);
+ _Thread_Executing->libc_reent = current_reent;
+}
+
+int sync(void)
+{
+ extern struct _reent libc_global_reent;
+
+ /*
+ * Walk the one used initially by RTEMS.
+ */
+ _fwalk(&libc_global_reent, sync_wrapper);
+
+ /*
+ * XXX Do we walk the one used globally by newlib?
+ * XXX Do we need the RTEMS global one?
+ */
+
+ /*
+ * Now walk all the per-thread reentrancy structures.
+ */
+ rtems_iterate_over_all_threads(sync_per_thread);
+
+ return 0;
+}
diff --git a/cpukit/libcsupport/src/tcdrain.c b/cpukit/libcsupport/src/tcdrain.c
new file mode 100644
index 0000000000..c2e9d5e2ee
--- /dev/null
+++ b/cpukit/libcsupport/src/tcdrain.c
@@ -0,0 +1,36 @@
+/*
+ * tcdrain() - POSIX 1003.1b 7.2.2 - Line Control Functions
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+/* #include <sys/ioctl.h> */
+
+#include <rtems/libio.h>
+
+int tcdrain(
+ int fd
+)
+{
+ return ioctl( fd, RTEMS_IO_TCDRAIN, 0 );
+}
+
+#endif
diff --git a/cpukit/libcsupport/src/tcflow.c b/cpukit/libcsupport/src/tcflow.c
new file mode 100644
index 0000000000..a1e054482c
--- /dev/null
+++ b/cpukit/libcsupport/src/tcflow.c
@@ -0,0 +1,34 @@
+/*
+ * tcflow() - POSIX 1003.1b 7.2.2 - Line Control Functions
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+/* #include <sys/ioctl.h> */
+
+#include <rtems/libio.h>
+
+int tcflow (int fd, int action)
+{
+ return 0;
+}
+
+#endif
diff --git a/cpukit/libcsupport/src/tcflush.c b/cpukit/libcsupport/src/tcflush.c
new file mode 100644
index 0000000000..0335b94e8a
--- /dev/null
+++ b/cpukit/libcsupport/src/tcflush.c
@@ -0,0 +1,34 @@
+/*
+ * tcflush() - POSIX 1003.1b 7.2.2 - Line Control Functions
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+/* #include <sys/ioctl.h> */
+
+#include <rtems/libio.h>
+
+int tcflush (int fd, int queue)
+{
+ return 0;
+}
+
+#endif
diff --git a/cpukit/libcsupport/src/tcgetattr.c b/cpukit/libcsupport/src/tcgetattr.c
new file mode 100644
index 0000000000..8d4eb0618b
--- /dev/null
+++ b/cpukit/libcsupport/src/tcgetattr.c
@@ -0,0 +1,36 @@
+/*
+ * tcgetattr() - POSIX 1003.1b 7.2.1 - Get and Set State
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+/* #include <sys/ioctl.h> */
+
+#include <rtems/libio.h>
+
+int tcgetattr(
+ int fd,
+ struct termios *tp
+)
+{
+ return ioctl( fd, RTEMS_IO_GET_ATTRIBUTES, tp );
+}
+#endif
diff --git a/cpukit/libcsupport/src/tcgetprgrp.c b/cpukit/libcsupport/src/tcgetprgrp.c
new file mode 100644
index 0000000000..769883d46d
--- /dev/null
+++ b/cpukit/libcsupport/src/tcgetprgrp.c
@@ -0,0 +1,34 @@
+/*
+ * tcgetprgrp() - POSIX 1003.1b 7.2.3 - Get Foreground Process Group ID
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+/* #include <sys/ioctl.h> */
+
+#include <rtems/libio.h>
+
+pid_t tcgetprgrp(int fd)
+{
+ return getpid();
+}
+
+#endif
diff --git a/cpukit/libcsupport/src/tcsendbreak.c b/cpukit/libcsupport/src/tcsendbreak.c
new file mode 100644
index 0000000000..af7ea4c85b
--- /dev/null
+++ b/cpukit/libcsupport/src/tcsendbreak.c
@@ -0,0 +1,34 @@
+/*
+ * tcsendbreak() - POSIX 1003.1b 7.2.2 - Line Control Functions
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+/* #include <sys/ioctl.h> */
+
+#include <rtems/libio.h>
+
+int tcsendbreak ( int fd, int duration )
+{
+ return 0;
+}
+
+#endif
diff --git a/cpukit/libcsupport/src/tcsetattr.c b/cpukit/libcsupport/src/tcsetattr.c
new file mode 100644
index 0000000000..187c1df584
--- /dev/null
+++ b/cpukit/libcsupport/src/tcsetattr.c
@@ -0,0 +1,51 @@
+/*
+ * tcsetattr() - POSIX 1003.1b 7.2.1 - Get and Set State
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+/* #include <sys/ioctl.h> */
+
+#include <rtems/libio.h>
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int tcsetattr(
+ int fd,
+ int opt,
+ struct termios *tp
+)
+{
+ switch (opt) {
+ default:
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+
+ case TCSADRAIN:
+ if (ioctl( fd, RTEMS_IO_TCDRAIN, NULL ) < 0)
+ return -1;
+ /*
+ * Fall through to....
+ */
+ case TCSANOW:
+ return ioctl( fd, RTEMS_IO_SET_ATTRIBUTES, tp );
+ }
+}
+#endif
diff --git a/cpukit/libcsupport/src/tcsetpgrp.c b/cpukit/libcsupport/src/tcsetpgrp.c
new file mode 100644
index 0000000000..be3c900ad4
--- /dev/null
+++ b/cpukit/libcsupport/src/tcsetpgrp.c
@@ -0,0 +1,34 @@
+/*
+ * tcsetprgrp() - POSIX 1003.1b 7.2.4 - Set Foreground Process Group ID
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#if defined(RTEMS_NEWLIB)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <termios.h>
+/* #include <sys/ioctl.h> */
+
+#include <rtems/libio.h>
+
+int tcsetprgrp(int fd, pid_t pid)
+{
+ return 0;
+}
+
+#endif
diff --git a/cpukit/libcsupport/src/telldir.c b/cpukit/libcsupport/src/telldir.c
new file mode 100644
index 0000000000..d7b9f23b4d
--- /dev/null
+++ b/cpukit/libcsupport/src/telldir.c
@@ -0,0 +1,47 @@
+/*
+ * telldir() - XXX
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/param.h>
+#include <assert.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+long telldir(
+ DIR *dirp
+)
+{
+ rtems_libio_t *iop;
+
+ if ( !dirp )
+ rtems_set_errno_and_return_minus_one( EBADF );
+
+ /*
+ * Get the file control block structure associated with the
+ * file descriptor
+ */
+
+ iop = rtems_libio_iop( dirp->dd_fd );
+
+ if (iop == NULL)
+ assert(0);
+
+ return (long)( iop->offset );
+}
diff --git a/cpukit/libcsupport/src/termios.c b/cpukit/libcsupport/src/termios.c
new file mode 100644
index 0000000000..045f4003ab
--- /dev/null
+++ b/cpukit/libcsupport/src/termios.c
@@ -0,0 +1,1495 @@
+/*
+ * TERMIOS serial line support
+ *
+ * Author:
+ * W. Eric Norum
+ * Saskatchewan Accelerator Laboratory
+ * University of Saskatchewan
+ * Saskatoon, Saskatchewan, CANADA
+ * eric@skatter.usask.ca
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <unistd.h>
+#include <sys/ttycom.h>
+
+#include <rtems/termiostypes.h>
+
+/*
+ * The size of the cooked buffer
+ */
+#define CBUFSIZE (rtems_termios_cbufsize)
+
+/*
+ * The sizes of the raw message buffers.
+ * On most architectures it is quite a bit more
+ * efficient if these are powers of two.
+ */
+#define RAW_INPUT_BUFFER_SIZE (rtems_termios_raw_input_size)
+#define RAW_OUTPUT_BUFFER_SIZE (rtems_termios_raw_output_size)
+
+/* fields for "flow_ctrl" status */
+#define FL_IREQXOF 1 /* input queue requests stop of incoming data */
+#define FL_ISNTXOF 2 /* XOFF has been sent to other side of line */
+#define FL_IRTSOFF 4 /* RTS has been turned off for other side.. */
+
+#define FL_ORCVXOF 0x10 /* XOFF has been received */
+#define FL_OSTOP 0x20 /* output has been stopped due to XOFF */
+
+#define FL_MDRTS 0x100 /* input controlled with RTS/CTS handshake */
+#define FL_MDXON 0x200 /* input controlled with XON/XOFF protocol */
+#define FL_MDXOF 0x400 /* output controlled with XON/XOFF protocol */
+
+#define NODISC(n) \
+ { NULL, NULL, NULL, NULL, \
+ NULL, NULL, NULL, NULL }
+/*
+ * FIXME: change linesw entries consistant with linesw entry usage...
+ */
+struct linesw linesw[MAXLDISC] =
+{
+ NODISC(0), /* 0- termios-built-in */
+ NODISC(1), /* 1- defunct */
+ NODISC(2), /* 2- NTTYDISC */
+ NODISC(3), /* TABLDISC */
+ NODISC(4), /* SLIPDISC */
+ NODISC(5), /* PPPDISC */
+ NODISC(6), /* loadable */
+ NODISC(7), /* loadable */
+};
+
+int nlinesw = sizeof (linesw) / sizeof (linesw[0]);
+
+extern struct rtems_termios_tty *rtems_termios_ttyHead;
+extern struct rtems_termios_tty *rtems_termios_ttyTail;
+extern rtems_id rtems_termios_ttyMutex;
+
+static int rtems_termios_cbufsize = 256;
+static int rtems_termios_raw_input_size = 128;
+static int rtems_termios_raw_output_size = 64;
+
+static rtems_task rtems_termios_rxdaemon(rtems_task_argument argument);
+static rtems_task rtems_termios_txdaemon(rtems_task_argument argument);
+/*
+ * some constants for I/O daemon task creation
+ */
+#define TERMIOS_TXTASK_PRIO 10
+#define TERMIOS_RXTASK_PRIO 9
+#define TERMIOS_TXTASK_STACKSIZE 1024
+#define TERMIOS_RXTASK_STACKSIZE 1024
+/*
+ * some events to be sent to the I/O tasks
+ */
+#define TERMIOS_TX_START_EVENT RTEMS_EVENT_1
+#define TERMIOS_TX_TERMINATE_EVENT RTEMS_EVENT_0
+
+#define TERMIOS_RX_PROC_EVENT RTEMS_EVENT_1
+#define TERMIOS_RX_TERMINATE_EVENT RTEMS_EVENT_0
+
+/*
+ * Open a termios device
+ */
+rtems_status_code
+rtems_termios_open (
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg,
+ const rtems_termios_callbacks *callbacks
+ )
+{
+ rtems_status_code sc;
+ rtems_libio_open_close_args_t *args = arg;
+ struct rtems_termios_tty *tty;
+
+ /*
+ * See if the device has already been opened
+ */
+ sc = rtems_semaphore_obtain (rtems_termios_ttyMutex,
+ RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ return sc;
+ for (tty = rtems_termios_ttyHead ; tty != NULL ; tty = tty->forw) {
+ if ((tty->major == major) && (tty->minor == minor))
+ break;
+ }
+ if (tty == NULL) {
+ static char c = 'a';
+
+ /*
+ * Create a new device
+ */
+ tty = calloc (1, sizeof (struct rtems_termios_tty));
+ if (tty == NULL) {
+ rtems_semaphore_release (rtems_termios_ttyMutex);
+ return RTEMS_NO_MEMORY;
+ }
+ /*
+ * allocate raw input buffer
+ */
+ tty->rawInBuf.Size = RAW_INPUT_BUFFER_SIZE;
+ tty->rawInBuf.theBuf = malloc (tty->rawInBuf.Size);
+ if (tty->rawInBuf.theBuf == NULL) {
+ free(tty);
+ rtems_semaphore_release (rtems_termios_ttyMutex);
+ return RTEMS_NO_MEMORY;
+ }
+ /*
+ * allocate raw output buffer
+ */
+ tty->rawOutBuf.Size = RAW_OUTPUT_BUFFER_SIZE;
+ tty->rawOutBuf.theBuf = malloc (tty->rawOutBuf.Size);
+ if (tty->rawOutBuf.theBuf == NULL) {
+ free((void *)(tty->rawInBuf.theBuf));
+ free(tty);
+ rtems_semaphore_release (rtems_termios_ttyMutex);
+ return RTEMS_NO_MEMORY;
+ }
+ /*
+ * allocate cooked buffer
+ */
+ tty->cbuf = malloc (CBUFSIZE);
+ if (tty->cbuf == NULL) {
+ free((void *)(tty->rawOutBuf.theBuf));
+ free((void *)(tty->rawInBuf.theBuf));
+ free(tty);
+ rtems_semaphore_release (rtems_termios_ttyMutex);
+ return RTEMS_NO_MEMORY;
+ }
+ /*
+ * Initialize wakeup callbacks
+ */
+ tty->tty_snd.sw_pfn = NULL;
+ tty->tty_snd.sw_arg = NULL;
+ tty->tty_rcv.sw_pfn = NULL;
+ tty->tty_rcv.sw_arg = NULL;
+ tty->tty_rcvwakeup = 0;
+
+ /*
+ * link tty
+ */
+ tty->forw = rtems_termios_ttyHead;
+ tty->back = NULL;
+ if (rtems_termios_ttyHead != NULL)
+ rtems_termios_ttyHead->back = tty;
+ rtems_termios_ttyHead = tty;
+ if (rtems_termios_ttyTail == NULL)
+ rtems_termios_ttyTail = tty;
+
+ tty->minor = minor;
+ tty->major = major;
+
+ /*
+ * Set up mutex semaphores
+ */
+ sc = rtems_semaphore_create (
+ rtems_build_name ('T', 'R', 'i', c),
+ 1,
+ RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
+ RTEMS_NO_PRIORITY,
+ &tty->isem);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+ sc = rtems_semaphore_create (
+ rtems_build_name ('T', 'R', 'o', c),
+ 1,
+ RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
+ RTEMS_NO_PRIORITY,
+ &tty->osem);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+ sc = rtems_semaphore_create (
+ rtems_build_name ('T', 'R', 'x', c),
+ 0,
+ RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_FIFO,
+ RTEMS_NO_PRIORITY,
+ &tty->rawOutBuf.Semaphore);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+ tty->rawOutBufState = rob_idle;
+
+ /*
+ * Set callbacks
+ */
+ tty->device = *callbacks;
+
+ /*
+ * Create I/O tasks
+ */
+ if (tty->device.outputUsesInterrupts == TERMIOS_TASK_DRIVEN) {
+ sc = rtems_task_create (
+ rtems_build_name ('T', 'x', 'T', c),
+ TERMIOS_TXTASK_PRIO,
+ TERMIOS_TXTASK_STACKSIZE,
+ RTEMS_NO_PREEMPT | RTEMS_NO_TIMESLICE |
+ RTEMS_NO_ASR,
+ RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL,
+ &tty->txTaskId);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+ sc = rtems_task_create (
+ rtems_build_name ('R', 'x', 'T', c),
+ TERMIOS_RXTASK_PRIO,
+ TERMIOS_RXTASK_STACKSIZE,
+ RTEMS_NO_PREEMPT | RTEMS_NO_TIMESLICE |
+ RTEMS_NO_ASR,
+ RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL,
+ &tty->rxTaskId);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+
+ }
+ if ((tty->device.pollRead == NULL) ||
+ (tty->device.outputUsesInterrupts == TERMIOS_TASK_DRIVEN)){
+ sc = rtems_semaphore_create (
+ rtems_build_name ('T', 'R', 'r', c),
+ 0,
+ RTEMS_COUNTING_SEMAPHORE | RTEMS_PRIORITY,
+ RTEMS_NO_PRIORITY,
+ &tty->rawInBuf.Semaphore);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+ }
+
+ /*
+ * Set default parameters
+ */
+ tty->termios.c_iflag = BRKINT | ICRNL | IXON | IMAXBEL;
+ tty->termios.c_oflag = OPOST | ONLCR | XTABS;
+ tty->termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL;
+ tty->termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOK | ECHOE | ECHOCTL;
+
+ tty->termios.c_cc[VINTR] = '\003';
+ tty->termios.c_cc[VQUIT] = '\034';
+ tty->termios.c_cc[VERASE] = '\177';
+ tty->termios.c_cc[VKILL] = '\025';
+ tty->termios.c_cc[VEOF] = '\004';
+ tty->termios.c_cc[VEOL] = '\000';
+ tty->termios.c_cc[VEOL2] = '\000';
+ tty->termios.c_cc[VSTART] = '\021';
+ tty->termios.c_cc[VSTOP] = '\023';
+ tty->termios.c_cc[VSUSP] = '\032';
+ tty->termios.c_cc[VREPRINT] = '\022';
+ tty->termios.c_cc[VDISCARD] = '\017';
+ tty->termios.c_cc[VWERASE] = '\027';
+ tty->termios.c_cc[VLNEXT] = '\026';
+
+ /* start with no flow control, clear flow control flags */
+ tty->flow_ctrl = 0;
+ /*
+ * set low/highwater mark for XON/XOFF support
+ */
+ tty->lowwater = tty->rawInBuf.Size * 1/2;
+ tty->highwater = tty->rawInBuf.Size * 3/4;
+ /*
+ * Bump name characer
+ */
+ if (c++ == 'z')
+ c = 'a';
+
+ }
+ args->iop->data1 = tty;
+ if (!tty->refcount++) {
+ if (tty->device.firstOpen)
+ (*tty->device.firstOpen)(major, minor, arg);
+ /*
+ * start I/O tasks, if needed
+ */
+ if (tty->device.outputUsesInterrupts == TERMIOS_TASK_DRIVEN) {
+ sc = rtems_task_start(tty->rxTaskId,
+ rtems_termios_rxdaemon,
+ (rtems_task_argument)tty);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+
+ sc = rtems_task_start(tty->txTaskId,
+ rtems_termios_txdaemon,
+ (rtems_task_argument)tty);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+ }
+ }
+ rtems_semaphore_release (rtems_termios_ttyMutex);
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * Drain output queue
+ */
+static void
+drainOutput (struct rtems_termios_tty *tty)
+{
+ rtems_interrupt_level level;
+ rtems_status_code sc;
+
+ if (tty->device.outputUsesInterrupts != TERMIOS_POLLED) {
+ rtems_interrupt_disable (level);
+ while (tty->rawOutBuf.Tail != tty->rawOutBuf.Head) {
+ tty->rawOutBufState = rob_wait;
+ rtems_interrupt_enable (level);
+ sc = rtems_semaphore_obtain (tty->rawOutBuf.Semaphore,
+ RTEMS_WAIT,
+ RTEMS_NO_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+ rtems_interrupt_disable (level);
+ }
+ rtems_interrupt_enable (level);
+ }
+}
+
+rtems_status_code
+rtems_termios_close (void *arg)
+{
+ rtems_libio_open_close_args_t *args = arg;
+ struct rtems_termios_tty *tty = args->iop->data1;
+ rtems_status_code sc;
+
+ sc = rtems_semaphore_obtain (rtems_termios_ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+ if (--tty->refcount == 0) {
+ if (linesw[tty->t_line].l_close != NULL) {
+ /*
+ * call discipline-specific close
+ */
+ sc = linesw[tty->t_line].l_close(tty);
+ }
+ else {
+ /*
+ * default: just flush output buffer
+ */
+ drainOutput (tty);
+ }
+
+ if (tty->device.outputUsesInterrupts
+ == TERMIOS_TASK_DRIVEN) {
+ /*
+ * send "terminate" to I/O tasks
+ */
+ sc = rtems_event_send(
+ tty->rxTaskId,
+ TERMIOS_RX_TERMINATE_EVENT);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+ sc = rtems_event_send(
+ tty->txTaskId,
+ TERMIOS_TX_TERMINATE_EVENT);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+ }
+ if (tty->device.lastClose)
+ (*tty->device.lastClose)(tty->major, tty->minor, arg);
+ if (tty->forw == NULL) {
+ rtems_termios_ttyTail = tty->back;
+ if ( rtems_termios_ttyTail != NULL ) {
+ rtems_termios_ttyTail->forw = NULL;
+ }
+ }
+ else {
+ tty->forw->back = tty->back;
+ }
+ if (tty->back == NULL) {
+ rtems_termios_ttyHead = tty->forw;
+ if ( rtems_termios_ttyHead != NULL ) {
+ rtems_termios_ttyHead->back = NULL;
+ }
+ }
+ else {
+ tty->back->forw = tty->forw;
+ }
+ rtems_semaphore_delete (tty->isem);
+ rtems_semaphore_delete (tty->osem);
+ rtems_semaphore_delete (tty->rawOutBuf.Semaphore);
+ if ((tty->device.pollRead == NULL) ||
+ (tty->device.outputUsesInterrupts == TERMIOS_TASK_DRIVEN))
+ rtems_semaphore_delete (tty->rawInBuf.Semaphore);
+ free (tty->rawInBuf.theBuf);
+ free (tty->rawOutBuf.theBuf);
+ free (tty->cbuf);
+ free (tty);
+ }
+ rtems_semaphore_release (rtems_termios_ttyMutex);
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code rtems_termios_bufsize (
+ int cbufsize,
+ int raw_input,
+ int raw_output
+)
+{
+ rtems_termios_cbufsize = cbufsize;
+ rtems_termios_raw_input_size = raw_input;
+ rtems_termios_raw_output_size = raw_output;
+ return RTEMS_SUCCESSFUL;
+}
+
+static void
+termios_set_flowctrl(struct rtems_termios_tty *tty)
+{
+ rtems_interrupt_level level;
+ /*
+ * check for flow control options to be switched off
+ */
+
+ /* check for outgoing XON/XOFF flow control switched off */
+ if (( tty->flow_ctrl & FL_MDXON) &&
+ !(tty->termios.c_iflag & IXON)) {
+ /* clear related flags in flow_ctrl */
+ tty->flow_ctrl &= ~(FL_MDXON | FL_ORCVXOF);
+
+ /* has output been stopped due to received XOFF? */
+ if (tty->flow_ctrl & FL_OSTOP) {
+ /* disable interrupts */
+ rtems_interrupt_disable(level);
+ tty->flow_ctrl &= ~FL_OSTOP;
+ /* check for chars in output buffer (or rob_state?) */
+ if (tty->rawOutBufState != rob_idle) {
+ /* if chars available, call write function... */
+ (*tty->device.write)(tty->minor,
+ (char *)&tty->rawOutBuf.theBuf[tty->rawOutBuf.Tail],1);
+ }
+ /* reenable interrupts */
+ rtems_interrupt_enable(level);
+ }
+ }
+ /* check for incoming XON/XOFF flow control switched off */
+ if (( tty->flow_ctrl & FL_MDXOF) &&
+ !(tty->termios.c_iflag & IXOFF)) {
+ /* clear related flags in flow_ctrl */
+ tty->flow_ctrl &= ~(FL_MDXOF);
+ /* FIXME: what happens, if we had sent XOFF but not yet XON? */
+ tty->flow_ctrl &= ~(FL_ISNTXOF);
+ }
+
+ /* check for incoming RTS/CTS flow control switched off */
+ if (( tty->flow_ctrl & FL_MDRTS) &&
+ !(tty->termios.c_cflag & CRTSCTS)) {
+ /* clear related flags in flow_ctrl */
+ tty->flow_ctrl &= ~(FL_MDRTS);
+
+ /* restart remote Tx, if it was stopped */
+ if ((tty->flow_ctrl & FL_IRTSOFF) &&
+ (tty->device.startRemoteTx != NULL)) {
+ tty->device.startRemoteTx(tty->minor);
+ }
+ tty->flow_ctrl &= ~(FL_IRTSOFF);
+ }
+
+ /*
+ * check for flow control options to be switched on
+ */
+ /* check for incoming RTS/CTS flow control switched on */
+ if (tty->termios.c_cflag & CRTSCTS) {
+ tty->flow_ctrl |= FL_MDRTS;
+ }
+ /* check for incoming XON/XOF flow control switched on */
+ if (tty->termios.c_iflag & IXOFF) {
+ tty->flow_ctrl |= FL_MDXOF;
+ }
+ /* check for outgoing XON/XOF flow control switched on */
+ if (tty->termios.c_iflag & IXON) {
+ tty->flow_ctrl |= FL_MDXON;
+ }
+}
+
+rtems_status_code
+rtems_termios_ioctl (void *arg)
+{
+ rtems_libio_ioctl_args_t *args = arg;
+ struct rtems_termios_tty *tty = args->iop->data1;
+ struct ttywakeup *wakeup = (struct ttywakeup *)args->buffer;
+ rtems_status_code sc;
+
+ args->ioctl_return = 0;
+ sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL) {
+ args->ioctl_return = sc;
+ return sc;
+ }
+ switch (args->command) {
+ default:
+ if (linesw[tty->t_line].l_ioctl != NULL) {
+ sc = linesw[tty->t_line].l_ioctl(tty,args);
+ }
+ else {
+ sc = RTEMS_INVALID_NUMBER;
+ }
+ break;
+
+ case RTEMS_IO_GET_ATTRIBUTES:
+ *(struct termios *)args->buffer = tty->termios;
+ break;
+
+ case RTEMS_IO_SET_ATTRIBUTES:
+ tty->termios = *(struct termios *)args->buffer;
+
+ /* check for and process change in flow control options */
+ termios_set_flowctrl(tty);
+
+ if (tty->termios.c_lflag & ICANON) {
+ tty->rawInBufSemaphoreOptions = RTEMS_WAIT;
+ tty->rawInBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
+ tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
+ }
+ else {
+ rtems_interval ticksPerSecond;
+ rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticksPerSecond);
+ tty->vtimeTicks = tty->termios.c_cc[VTIME] * ticksPerSecond / 10;
+ if (tty->termios.c_cc[VTIME]) {
+ tty->rawInBufSemaphoreOptions = RTEMS_WAIT;
+ tty->rawInBufSemaphoreTimeout = tty->vtimeTicks;
+ if (tty->termios.c_cc[VMIN])
+ tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
+ else
+ tty->rawInBufSemaphoreFirstTimeout = tty->vtimeTicks;
+ }
+ else {
+ if (tty->termios.c_cc[VMIN]) {
+ tty->rawInBufSemaphoreOptions = RTEMS_WAIT;
+ tty->rawInBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
+ tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
+ }
+ else {
+ tty->rawInBufSemaphoreOptions = RTEMS_NO_WAIT;
+ }
+ }
+ }
+ if (tty->device.setAttributes)
+ (*tty->device.setAttributes)(tty->minor, &tty->termios);
+ break;
+
+ case RTEMS_IO_TCDRAIN:
+ drainOutput (tty);
+ break;
+
+ case RTEMS_IO_SNDWAKEUP:
+ tty->tty_snd = *wakeup;
+ break;
+
+ case RTEMS_IO_RCVWAKEUP:
+ tty->tty_rcv = *wakeup;
+ break;
+
+ /*
+ * FIXME: add various ioctl code handlers
+ */
+
+#if 1 /* FIXME */
+ case TIOCSETD:
+ /*
+ * close old line discipline
+ */
+ if (linesw[tty->t_line].l_close != NULL) {
+ sc = linesw[tty->t_line].l_close(tty);
+ }
+ tty->t_line=*(int*)(args->buffer);
+ tty->t_sc = NULL; /* ensure that no more valid data */
+ /*
+ * open new line discipline
+ */
+ if (linesw[tty->t_line].l_open != NULL) {
+ sc = linesw[tty->t_line].l_open(tty);
+ }
+ break;
+ case TIOCGETD:
+ *(int*)(args->buffer)=tty->t_line;
+ break;
+#endif
+ case FIONREAD:
+ /* Half guess that this is the right operation */
+ *(int *)args->buffer = tty->ccount - tty->cindex;
+ break;
+ }
+ rtems_semaphore_release (tty->osem);
+ args->ioctl_return = sc;
+ return sc;
+}
+
+/*
+ * Send characters to device-specific code
+ */
+void
+rtems_termios_puts (const char *buf, int len, struct rtems_termios_tty *tty)
+{
+ unsigned int newHead;
+ rtems_interrupt_level level;
+ rtems_status_code sc;
+
+ if (tty->device.outputUsesInterrupts == TERMIOS_POLLED) {
+ (*tty->device.write)(tty->minor, buf, len);
+ return;
+ }
+ newHead = tty->rawOutBuf.Head;
+ while (len) {
+ /*
+ * Performance improvement could be made here.
+ * Copy multiple bytes to raw buffer:
+ * if (len > 1) && (space to buffer end, or tail > 1)
+ * ncopy = MIN (len, space to buffer end or tail)
+ * memcpy (raw buffer, buf, ncopy)
+ * buf += ncopy
+ * len -= ncopy
+ *
+ * To minimize latency, the memcpy should be done
+ * with interrupts enabled.
+ */
+ newHead = (newHead + 1) % tty->rawOutBuf.Size;
+ rtems_interrupt_disable (level);
+ while (newHead == tty->rawOutBuf.Tail) {
+ tty->rawOutBufState = rob_wait;
+ rtems_interrupt_enable (level);
+ sc = rtems_semaphore_obtain (tty->rawOutBuf.Semaphore,
+ RTEMS_WAIT,
+ RTEMS_NO_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+ rtems_interrupt_disable (level);
+ }
+ tty->rawOutBuf.theBuf[tty->rawOutBuf.Head] = *buf++;
+ tty->rawOutBuf.Head = newHead;
+ if (tty->rawOutBufState == rob_idle) {
+ /* check, whether XOFF has been received */
+ if (!(tty->flow_ctrl & FL_ORCVXOF)) {
+ (*tty->device.write)(tty->minor,
+ (char *)&tty->rawOutBuf.theBuf[tty->rawOutBuf.Tail],1);
+ }
+ else {
+ /* remember that output has been stopped due to flow ctrl*/
+ tty->flow_ctrl |= FL_OSTOP;
+ }
+ tty->rawOutBufState = rob_busy;
+ }
+ rtems_interrupt_enable (level);
+ len--;
+ }
+}
+
+/*
+ * Handle output processing
+ */
+static void
+oproc (unsigned char c, struct rtems_termios_tty *tty)
+{
+ int i;
+
+ if (tty->termios.c_oflag & OPOST) {
+ switch (c) {
+ case '\n':
+ if (tty->termios.c_oflag & ONLRET)
+ tty->column = 0;
+ if (tty->termios.c_oflag & ONLCR) {
+ rtems_termios_puts ("\r", 1, tty);
+ tty->column = 0;
+ }
+ break;
+
+ case '\r':
+ if ((tty->termios.c_oflag & ONOCR) && (tty->column == 0))
+ return;
+ if (tty->termios.c_oflag & OCRNL) {
+ c = '\n';
+ if (tty->termios.c_oflag & ONLRET)
+ tty->column = 0;
+ break;
+ }
+ tty->column = 0;
+ break;
+
+ case '\t':
+ i = 8 - (tty->column & 7);
+ if ((tty->termios.c_oflag & TABDLY) == XTABS) {
+ tty->column += i;
+ rtems_termios_puts ( " ", i, tty);
+ return;
+ }
+ tty->column += i;
+ break;
+
+ case '\b':
+ if (tty->column > 0)
+ tty->column--;
+ break;
+
+ default:
+ if (tty->termios.c_oflag & OLCUC)
+ c = toupper(c);
+ if (!iscntrl(c))
+ tty->column++;
+ break;
+ }
+ }
+ rtems_termios_puts (&c, 1, tty);
+}
+
+rtems_status_code
+rtems_termios_write (void *arg)
+{
+ rtems_libio_rw_args_t *args = arg;
+ struct rtems_termios_tty *tty = args->iop->data1;
+ rtems_status_code sc;
+
+ sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ return sc;
+ if (linesw[tty->t_line].l_write != NULL) {
+ sc = linesw[tty->t_line].l_write(tty,args);
+ rtems_semaphore_release (tty->osem);
+ return sc;
+ }
+ if (tty->termios.c_oflag & OPOST) {
+ uint32_t count = args->count;
+ uint8_t *buffer = args->buffer;
+ while (count--)
+ oproc (*buffer++, tty);
+ args->bytes_moved = args->count;
+ }
+ else {
+ rtems_termios_puts (args->buffer, args->count, tty);
+ args->bytes_moved = args->count;
+ }
+ rtems_semaphore_release (tty->osem);
+ return sc;
+}
+
+/*
+ * Echo a typed character
+ */
+static void
+echo (unsigned char c, struct rtems_termios_tty *tty)
+{
+ if ((tty->termios.c_lflag & ECHOCTL) && iscntrl(c) && (c != '\t') && (c != '\n')) {
+ char echobuf[2];
+
+ echobuf[0] = '^';
+ echobuf[1] = c ^ 0x40;
+ rtems_termios_puts (echobuf, 2, tty);
+ tty->column += 2;
+ }
+ else {
+ oproc (c, tty);
+ }
+}
+
+/*
+ * Erase a character or line
+ * FIXME: Needs support for WERASE and ECHOPRT.
+ * FIXME: Some of the tests should check for IEXTEN, too.
+ */
+static void
+erase (struct rtems_termios_tty *tty, int lineFlag)
+{
+ if (tty->ccount == 0)
+ return;
+ if (lineFlag) {
+ if (!(tty->termios.c_lflag & ECHO)) {
+ tty->ccount = 0;
+ return;
+ }
+ if (!(tty->termios.c_lflag & ECHOE)) {
+ tty->ccount = 0;
+ echo (tty->termios.c_cc[VKILL], tty);
+ if (tty->termios.c_lflag & ECHOK)
+ echo ('\n', tty);
+ return;
+ }
+ }
+ while (tty->ccount) {
+ unsigned char c = tty->cbuf[--tty->ccount];
+
+ if (tty->termios.c_lflag & ECHO) {
+ if (!lineFlag && !(tty->termios.c_lflag & ECHOE)) {
+ echo (tty->termios.c_cc[VERASE], tty);
+ }
+ else if (c == '\t') {
+ int col = tty->read_start_column;
+ int i = 0;
+
+ /*
+ * Find the character before the tab
+ */
+ while (i != tty->ccount) {
+ c = tty->cbuf[i++];
+ if (c == '\t') {
+ col = (col | 7) + 1;
+ }
+ else if (iscntrl (c)) {
+ if (tty->termios.c_lflag & ECHOCTL)
+ col += 2;
+ }
+ else {
+ col++;
+ }
+ }
+
+ /*
+ * Back up over the tab
+ */
+ while (tty->column > col) {
+ rtems_termios_puts ("\b", 1, tty);
+ tty->column--;
+ }
+ }
+ else {
+ if (iscntrl (c) && (tty->termios.c_lflag & ECHOCTL)) {
+ rtems_termios_puts ("\b \b", 3, tty);
+ if (tty->column)
+ tty->column--;
+ }
+ if (!iscntrl (c) || (tty->termios.c_lflag & ECHOCTL)) {
+ rtems_termios_puts ("\b \b", 3, tty);
+ if (tty->column)
+ tty->column--;
+ }
+ }
+ }
+ if (!lineFlag)
+ break;
+ }
+}
+
+/*
+ * Process a single input character
+ */
+static int
+iproc (unsigned char c, struct rtems_termios_tty *tty)
+{
+ if (tty->termios.c_iflag & ISTRIP)
+ c &= 0x7f;
+ if (tty->termios.c_iflag & IUCLC)
+ c = tolower (c);
+ if (c == '\r') {
+ if (tty->termios.c_iflag & IGNCR)
+ return 0;
+ if (tty->termios.c_iflag & ICRNL)
+ c = '\n';
+ }
+ else if ((c == '\n') && (tty->termios.c_iflag & INLCR)) {
+ c = '\r';
+ }
+ if ((c != '\0') && (tty->termios.c_lflag & ICANON)) {
+ if (c == tty->termios.c_cc[VERASE]) {
+ erase (tty, 0);
+ return 0;
+ }
+ else if (c == tty->termios.c_cc[VKILL]) {
+ erase (tty, 1);
+ return 0;
+ }
+ else if (c == tty->termios.c_cc[VEOF]) {
+ return 1;
+ }
+ else if (c == '\n') {
+ if (tty->termios.c_lflag & (ECHO | ECHONL))
+ echo (c, tty);
+ tty->cbuf[tty->ccount++] = c;
+ return 1;
+ }
+ else if ((c == tty->termios.c_cc[VEOL])
+ || (c == tty->termios.c_cc[VEOL2])) {
+ if (tty->termios.c_lflag & ECHO)
+ echo (c, tty);
+ tty->cbuf[tty->ccount++] = c;
+ return 1;
+ }
+ }
+
+ /*
+ * FIXME: Should do IMAXBEL handling somehow
+ */
+ if (tty->ccount < (CBUFSIZE-1)) {
+ if (tty->termios.c_lflag & ECHO)
+ echo (c, tty);
+ tty->cbuf[tty->ccount++] = c;
+ }
+ return 0;
+}
+
+/*
+ * Process input character, with semaphore.
+ */
+static int
+siproc (unsigned char c, struct rtems_termios_tty *tty)
+{
+ int i;
+
+ /*
+ * Obtain output semaphore if character will be echoed
+ */
+ if (tty->termios.c_lflag & (ECHO|ECHOE|ECHOK|ECHONL|ECHOPRT|ECHOCTL|ECHOKE)) {
+ rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ i = iproc (c, tty);
+ rtems_semaphore_release (tty->osem);
+ }
+ else {
+ i = iproc (c, tty);
+ }
+ return i;
+}
+
+/*
+ * Fill the input buffer by polling the device
+ */
+static rtems_status_code
+fillBufferPoll (struct rtems_termios_tty *tty)
+{
+ int n;
+
+ if (tty->termios.c_lflag & ICANON) {
+ for (;;) {
+ n = (*tty->device.pollRead)(tty->minor);
+ if (n < 0) {
+ rtems_task_wake_after (1);
+ }
+ else {
+ if (siproc (n, tty))
+ break;
+ }
+ }
+ }
+ else {
+ rtems_interval then, now;
+ if (!tty->termios.c_cc[VMIN] && tty->termios.c_cc[VTIME])
+ rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then);
+ for (;;) {
+ n = (*tty->device.pollRead)(tty->minor);
+ if (n < 0) {
+ if (tty->termios.c_cc[VMIN]) {
+ if (tty->termios.c_cc[VTIME] && tty->ccount) {
+ rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
+ if ((now - then) > tty->vtimeTicks) {
+ break;
+ }
+ }
+ }
+ else {
+ if (!tty->termios.c_cc[VTIME])
+ break;
+ rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
+ if ((now - then) > tty->vtimeTicks) {
+ break;
+ }
+ }
+ rtems_task_wake_after (1);
+ }
+ else {
+ siproc (n, tty);
+ if (tty->ccount >= tty->termios.c_cc[VMIN])
+ break;
+ if (tty->termios.c_cc[VMIN] && tty->termios.c_cc[VTIME])
+ rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then);
+ }
+ }
+ }
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * Fill the input buffer from the raw input queue
+ */
+static rtems_status_code
+fillBufferQueue (struct rtems_termios_tty *tty)
+{
+ rtems_interval timeout = tty->rawInBufSemaphoreFirstTimeout;
+ rtems_status_code sc;
+ int wait = (int)1;
+
+ while ( wait ) {
+ /*
+ * Process characters read from raw queue
+ */
+ while (tty->rawInBuf.Head != tty->rawInBuf.Tail) {
+ unsigned char c;
+ unsigned int newHead;
+
+ newHead = (tty->rawInBuf.Head + 1) % tty->rawInBuf.Size;
+ c = tty->rawInBuf.theBuf[newHead];
+ tty->rawInBuf.Head = newHead;
+ if(((tty->rawInBuf.Tail-newHead+tty->rawInBuf.Size)
+ % tty->rawInBuf.Size)
+ < tty->lowwater) {
+ tty->flow_ctrl &= ~FL_IREQXOF;
+ /* if tx stopped and XON should be sent... */
+ if (((tty->flow_ctrl & (FL_MDXON | FL_ISNTXOF))
+ == (FL_MDXON | FL_ISNTXOF))
+ && ((tty->rawOutBufState == rob_idle)
+ || (tty->flow_ctrl & FL_OSTOP))) {
+ /* XON should be sent now... */
+ (*tty->device.write)(tty->minor,
+ &(tty->termios.c_cc[VSTART]),
+ 1);
+ }
+ else if (tty->flow_ctrl & FL_MDRTS) {
+ tty->flow_ctrl &= ~FL_IRTSOFF;
+ /* activate RTS line */
+ if (tty->device.startRemoteTx != NULL) {
+ tty->device.startRemoteTx(tty->minor);
+ }
+ }
+ }
+
+ /* continue processing new character */
+ if (tty->termios.c_lflag & ICANON) {
+ if (siproc (c, tty))
+ wait = 0;
+ }
+ else {
+ siproc (c, tty);
+ if (tty->ccount >= tty->termios.c_cc[VMIN])
+ wait = 0;
+ }
+ timeout = tty->rawInBufSemaphoreTimeout;
+ }
+
+ /*
+ * Wait for characters
+ */
+ if ( wait ) {
+ sc = rtems_semaphore_obtain (tty->rawInBuf.Semaphore,
+ tty->rawInBufSemaphoreOptions,
+ timeout);
+ if (sc != RTEMS_SUCCESSFUL)
+ break;
+ }
+ }
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code
+rtems_termios_read (void *arg)
+{
+ rtems_libio_rw_args_t *args = arg;
+ struct rtems_termios_tty *tty = args->iop->data1;
+ uint32_t count = args->count;
+ uint8_t *buffer = args->buffer;
+ rtems_status_code sc;
+
+ sc = rtems_semaphore_obtain (tty->isem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ return sc;
+ if (linesw[tty->t_line].l_read != NULL) {
+ sc = linesw[tty->t_line].l_read(tty,args);
+ tty->tty_rcvwakeup = 0;
+ rtems_semaphore_release (tty->isem);
+ return sc;
+ }
+ if (tty->cindex == tty->ccount) {
+ tty->cindex = tty->ccount = 0;
+ tty->read_start_column = tty->column;
+ if (tty->device.pollRead != NULL
+ && tty->device.outputUsesInterrupts == TERMIOS_POLLED)
+ sc = fillBufferPoll (tty);
+ else
+ sc = fillBufferQueue (tty);
+ if (sc != RTEMS_SUCCESSFUL)
+ tty->cindex = tty->ccount = 0;
+ }
+ while (count && (tty->cindex < tty->ccount)) {
+ *buffer++ = tty->cbuf[tty->cindex++];
+ count--;
+ }
+ args->bytes_moved = args->count - count;
+ tty->tty_rcvwakeup = 0;
+ rtems_semaphore_release (tty->isem);
+ return sc;
+}
+
+/*
+ * signal receive interrupt to rx daemon
+ * NOTE: This routine runs in the context of the
+ * device receive interrupt handler.
+ */
+void rtems_termios_rxirq_occured(struct rtems_termios_tty *tty)
+{
+ /*
+ * send event to rx daemon task
+ */
+ rtems_event_send(tty->rxTaskId,TERMIOS_RX_PROC_EVENT);
+}
+
+/*
+ * Place characters on raw queue.
+ * NOTE: This routine runs in the context of the
+ * device receive interrupt handler.
+ * Returns the number of characters dropped because of overflow.
+ */
+int
+rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len)
+{
+ struct rtems_termios_tty *tty = ttyp;
+ unsigned int newTail;
+ char c;
+ int dropped = 0;
+ boolean flow_rcv = FALSE; /* TRUE, if flow control char received */
+ rtems_interrupt_level level;
+
+ if (linesw[tty->t_line].l_rint != NULL) {
+ while (len--) {
+ c = *buf++;
+ linesw[tty->t_line].l_rint(c,tty);
+ }
+
+ /*
+ * check to see if rcv wakeup callback was set
+ */
+ if (( !tty->tty_rcvwakeup ) && ( tty->tty_rcv.sw_pfn != NULL )) {
+ (*tty->tty_rcv.sw_pfn)(&tty->termios, tty->tty_rcv.sw_arg);
+ tty->tty_rcvwakeup = 1;
+ }
+ return 0;
+ }
+
+ while (len--) {
+ c = *buf++;
+ /* FIXME: implement IXANY: any character restarts output */
+ /* if incoming XON/XOFF controls outgoing stream: */
+ if (tty->flow_ctrl & FL_MDXON) {
+ /* if received char is V_STOP and V_START (both are equal value) */
+ if (c == tty->termios.c_cc[VSTOP]) {
+ if (c == tty->termios.c_cc[VSTART]) {
+ /* received VSTOP and VSTART==VSTOP? */
+ /* then toggle "stop output" status */
+ tty->flow_ctrl = tty->flow_ctrl ^ FL_ORCVXOF;
+ }
+ else {
+ /* VSTOP received (other code than VSTART) */
+ /* stop output */
+ tty->flow_ctrl |= FL_ORCVXOF;
+ }
+ flow_rcv = TRUE;
+ }
+ else if (c == tty->termios.c_cc[VSTART]) {
+ /* VSTART received */
+ /* restart output */
+ tty->flow_ctrl &= ~FL_ORCVXOF;
+ flow_rcv = TRUE;
+ }
+ }
+ if (flow_rcv) {
+ /* restart output according to FL_ORCVXOF flag */
+ if ((tty->flow_ctrl & (FL_ORCVXOF | FL_OSTOP)) == FL_OSTOP) {
+ /* disable interrupts */
+ rtems_interrupt_disable(level);
+ tty->flow_ctrl &= ~FL_OSTOP;
+ /* check for chars in output buffer (or rob_state?) */
+ if (tty->rawOutBufState != rob_idle) {
+ /* if chars available, call write function... */
+ (*tty->device.write)(tty->minor,
+ (char *)&tty->rawOutBuf.theBuf[tty->rawOutBuf.Tail], 1);
+ }
+ /* reenable interrupts */
+ rtems_interrupt_enable(level);
+ }
+ }
+ else {
+ newTail = (tty->rawInBuf.Tail + 1) % tty->rawInBuf.Size;
+ /* if chars_in_buffer > highwater */
+ rtems_interrupt_disable(level);
+ if ((((newTail - tty->rawInBuf.Head + tty->rawInBuf.Size)
+ % tty->rawInBuf.Size)
+ > tty->highwater) &&
+ !(tty->flow_ctrl & FL_IREQXOF)) {
+ /* incoming data stream should be stopped */
+ tty->flow_ctrl |= FL_IREQXOF;
+ if ((tty->flow_ctrl & (FL_MDXOF | FL_ISNTXOF))
+ == (FL_MDXOF ) ){
+ if ((tty->flow_ctrl & FL_OSTOP) ||
+ (tty->rawOutBufState == rob_idle)) {
+ /* if tx is stopped due to XOFF or out of data */
+ /* call write function here */
+ tty->flow_ctrl |= FL_ISNTXOF;
+ (*tty->device.write)(tty->minor,
+ &(tty->termios.c_cc[VSTOP]),
+ 1);
+ }
+ }
+ else if ((tty->flow_ctrl & (FL_MDRTS | FL_IRTSOFF))
+ == (FL_MDRTS ) ) {
+ tty->flow_ctrl |= FL_IRTSOFF;
+ /* deactivate RTS line */
+ if (tty->device.stopRemoteTx != NULL) {
+ tty->device.stopRemoteTx(tty->minor);
+ }
+ }
+ }
+ /* reenable interrupts */
+ rtems_interrupt_enable(level);
+
+ if (newTail == tty->rawInBuf.Head) {
+ dropped++;
+ }
+ else {
+ tty->rawInBuf.theBuf[newTail] = c;
+ tty->rawInBuf.Tail = newTail;
+
+ /*
+ * check to see if rcv wakeup callback was set
+ */
+ if (( !tty->tty_rcvwakeup ) && ( tty->tty_rcv.sw_pfn != NULL )) {
+ (*tty->tty_rcv.sw_pfn)(&tty->termios, tty->tty_rcv.sw_arg);
+ tty->tty_rcvwakeup = 1;
+ }
+ }
+ }
+ }
+ tty->rawInBufDropped += dropped;
+ rtems_semaphore_release (tty->rawInBuf.Semaphore);
+ return dropped;
+}
+
+/*
+ * in task-driven mode, this function is called in Tx task context
+ * in interrupt-driven mode, this function is called in TxIRQ context
+ */
+int
+rtems_termios_refill_transmitter (struct rtems_termios_tty *tty)
+{
+ unsigned int newTail;
+ int nToSend;
+ rtems_interrupt_level level;
+ int len;
+
+ /* check for XOF/XON to send */
+ if ((tty->flow_ctrl & (FL_MDXOF | FL_IREQXOF | FL_ISNTXOF))
+ == (FL_MDXOF | FL_IREQXOF)) {
+ /* XOFF should be sent now... */
+ (*tty->device.write)(tty->minor,
+ &(tty->termios.c_cc[VSTOP]), 1);
+
+ rtems_interrupt_disable(level);
+ tty->t_dqlen--;
+ tty->flow_ctrl |= FL_ISNTXOF;
+ rtems_interrupt_enable(level);
+
+ nToSend = 1;
+ }
+ else if ((tty->flow_ctrl & (FL_IREQXOF | FL_ISNTXOF))
+ == FL_ISNTXOF) {
+ /* NOTE: send XON even, if no longer in XON/XOFF mode... */
+ /* XON should be sent now... */
+ /*
+ * FIXME: this .write call will generate another
+ * dequeue callback. This will advance the "Tail" in the data
+ * buffer, although the corresponding data is not yet out!
+ * Therefore the dequeue "length" should be reduced by 1
+ */
+ (*tty->device.write)(tty->minor,
+ &(tty->termios.c_cc[VSTART]), 1);
+
+ rtems_interrupt_disable(level);
+ tty->t_dqlen--;
+ tty->flow_ctrl &= ~FL_ISNTXOF;
+ rtems_interrupt_enable(level);
+
+ nToSend = 1;
+ }
+ else {
+ if ( tty->rawOutBuf.Head == tty->rawOutBuf.Tail ) {
+ /*
+ * buffer was empty
+ */
+ if (tty->rawOutBufState == rob_wait) {
+ /*
+ * this should never happen...
+ */
+ rtems_semaphore_release (tty->rawOutBuf.Semaphore);
+ }
+ return 0;
+ }
+
+ rtems_interrupt_disable(level);
+ len = tty->t_dqlen;
+ tty->t_dqlen = 0;
+ rtems_interrupt_enable(level);
+
+ newTail = (tty->rawOutBuf.Tail + len) % tty->rawOutBuf.Size;
+ tty->rawOutBuf.Tail = newTail;
+ if (tty->rawOutBufState == rob_wait) {
+ /*
+ * wake up any pending writer task
+ */
+ rtems_semaphore_release (tty->rawOutBuf.Semaphore);
+ }
+ if (newTail == tty->rawOutBuf.Head) {
+ /*
+ * Buffer has become empty
+ */
+ tty->rawOutBufState = rob_idle;
+ nToSend = 0;
+
+ /*
+ * check to see if snd wakeup callback was set
+ */
+ if ( tty->tty_snd.sw_pfn != NULL) {
+ (*tty->tty_snd.sw_pfn)(&tty->termios, tty->tty_snd.sw_arg);
+ }
+ }
+ /* check, whether output should stop due to received XOFF */
+ else if ((tty->flow_ctrl & (FL_MDXON | FL_ORCVXOF))
+ == (FL_MDXON | FL_ORCVXOF)) {
+ /* Buffer not empty, but output stops due to XOFF */
+ /* set flag, that output has been stopped */
+ rtems_interrupt_disable(level);
+ tty->flow_ctrl |= FL_OSTOP;
+ tty->rawOutBufState = rob_busy; /*apm*/
+ rtems_interrupt_enable(level);
+ nToSend = 0;
+ }
+ else {
+ /*
+ * Buffer not empty, start tranmitter
+ */
+ if (newTail > tty->rawOutBuf.Head)
+ nToSend = tty->rawOutBuf.Size - newTail;
+ else
+ nToSend = tty->rawOutBuf.Head - newTail;
+ /* when flow control XON or XOF, don't send blocks of data */
+ /* to allow fast reaction on incoming flow ctrl and low latency*/
+ /* for outgoing flow control */
+ if (tty->flow_ctrl & (FL_MDXON | FL_MDXOF)) {
+ nToSend = 1;
+ }
+ tty->rawOutBufState = rob_busy; /*apm*/
+ (*tty->device.write)(tty->minor,
+ (char *)&tty->rawOutBuf.theBuf[newTail],
+ nToSend);
+ }
+ tty->rawOutBuf.Tail = newTail; /*apm*/
+ }
+ return nToSend;
+}
+
+/*
+ * Characters have been transmitted
+ * NOTE: This routine runs in the context of the
+ * device transmit interrupt handler.
+ * The second argument is the number of characters transmitted so far.
+ * This value will always be 1 for devices which generate an interrupt
+ * for each transmitted character.
+ * It returns number of characters left to transmit
+ */
+int
+rtems_termios_dequeue_characters (void *ttyp, int len)
+{
+ struct rtems_termios_tty *tty = ttyp;
+ rtems_status_code sc;
+
+ /*
+ * sum up character count already sent
+ */
+ tty->t_dqlen += len;
+
+ if (tty->device.outputUsesInterrupts == TERMIOS_TASK_DRIVEN) {
+ /*
+ * send wake up to transmitter task
+ */
+ sc = rtems_event_send(tty->txTaskId,
+ TERMIOS_TX_START_EVENT);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+ return 0; /* nothing to output in IRQ... */
+ }
+ else if (tty->t_line == PPPDISC ) {
+ /*
+ * call any line discipline start function
+ */
+ if (linesw[tty->t_line].l_start != NULL) {
+ linesw[tty->t_line].l_start(tty);
+ }
+ return 0; /* nothing to output in IRQ... */
+ }
+ else {
+ return rtems_termios_refill_transmitter(tty);
+ }
+}
+
+/*
+ * this task actually processes any transmit events
+ */
+static rtems_task rtems_termios_txdaemon(rtems_task_argument argument)
+{
+ struct rtems_termios_tty *tty = (struct rtems_termios_tty *)argument;
+ rtems_event_set the_event;
+
+ while (1) {
+ /*
+ * wait for rtems event
+ */
+ rtems_event_receive((TERMIOS_TX_START_EVENT |
+ TERMIOS_TX_TERMINATE_EVENT),
+ RTEMS_EVENT_ANY | RTEMS_WAIT,
+ RTEMS_NO_TIMEOUT,
+ &the_event);
+ if ((the_event & TERMIOS_TX_TERMINATE_EVENT) != 0) {
+ tty->txTaskId = 0;
+ rtems_task_delete(RTEMS_SELF);
+ }
+ else {
+ /*
+ * call any line discipline start function
+ */
+ if (linesw[tty->t_line].l_start != NULL) {
+ linesw[tty->t_line].l_start(tty);
+ }
+ /*
+ * try to push further characters to device
+ */
+ rtems_termios_refill_transmitter(tty);
+ }
+ }
+}
+
+/*
+ * this task actually processes any receive events
+ */
+static rtems_task rtems_termios_rxdaemon(rtems_task_argument argument)
+{
+ struct rtems_termios_tty *tty = (struct rtems_termios_tty *)argument;
+ rtems_event_set the_event;
+ int c;
+ char c_buf;
+ while (1) {
+ /*
+ * wait for rtems event
+ */
+ rtems_event_receive((TERMIOS_RX_PROC_EVENT |
+ TERMIOS_RX_TERMINATE_EVENT),
+ RTEMS_EVENT_ANY | RTEMS_WAIT,
+ RTEMS_NO_TIMEOUT,
+ &the_event);
+ if ((the_event & TERMIOS_RX_TERMINATE_EVENT) != 0) {
+ tty->rxTaskId = 0;
+ rtems_task_delete(RTEMS_SELF);
+ }
+ else {
+ /*
+ * do something
+ */
+ c = tty->device.pollRead(tty->minor);
+ if (c != EOF) {
+ /*
+ * pollRead did call enqueue on its own
+ */
+ c_buf = c;
+ rtems_termios_enqueue_raw_characters (
+ tty,&c_buf,1);
+ }
+ }
+ }
+}
diff --git a/cpukit/libcsupport/src/termiosinitialize.c b/cpukit/libcsupport/src/termiosinitialize.c
new file mode 100644
index 0000000000..b6660fe342
--- /dev/null
+++ b/cpukit/libcsupport/src/termiosinitialize.c
@@ -0,0 +1,54 @@
+/*
+ * Termios initialization routine
+ *
+ * Author:
+ * W. Eric Norum
+ * Saskatchewan Accelerator Laboratory
+ * University of Saskatchewan
+ * Saskatoon, Saskatchewan, CANADA
+ * eric@skatter.usask.ca
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <unistd.h>
+
+struct rtems_termios_tty *rtems_termios_ttyHead;
+struct rtems_termios_tty *rtems_termios_ttyTail;
+rtems_id rtems_termios_ttyMutex;
+
+void
+rtems_termios_initialize (void)
+{
+ rtems_status_code sc;
+
+ /*
+ * Create the mutex semaphore for the tty list
+ */
+ if (!rtems_termios_ttyMutex) {
+ sc = rtems_semaphore_create (
+ rtems_build_name ('T', 'R', 'm', 'i'),
+ 1,
+ RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
+ RTEMS_NO_PRIORITY,
+ &rtems_termios_ttyMutex);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (sc);
+ }
+}
diff --git a/cpukit/libcsupport/src/termiosreserveresources.c b/cpukit/libcsupport/src/termiosreserveresources.c
new file mode 100644
index 0000000000..6637cfd2d9
--- /dev/null
+++ b/cpukit/libcsupport/src/termiosreserveresources.c
@@ -0,0 +1,36 @@
+/*
+ * Reserve enough resources to open every physical device once.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+
+#if 0
+static int first_time; /* assumed to be zeroed by BSS initialization */
+#endif
+
+void rtems_termios_reserve_resources (
+ rtems_configuration_table *configuration,
+ uint32_t number_of_devices
+)
+{
+#if 0
+ rtems_api_configuration_table *rtems_config;
+
+
+ if (!configuration)
+ rtems_fatal_error_occurred (0xFFF0F001);
+ rtems_config = configuration->RTEMS_api_configuration;
+ if (!rtems_config)
+ rtems_fatal_error_occurred (0xFFF0F002);
+ if (!first_time)
+ rtems_config->maximum_semaphores += 1;
+ first_time = 1;
+ rtems_config->maximum_semaphores += (4 * number_of_devices);
+#endif
+}
diff --git a/cpukit/libcsupport/src/truncate.c b/cpukit/libcsupport/src/truncate.c
new file mode 100644
index 0000000000..7a0a98b4bd
--- /dev/null
+++ b/cpukit/libcsupport/src/truncate.c
@@ -0,0 +1,43 @@
+/*
+ * truncate() - Truncate a File to the Specified Length
+ *
+ * This routine is not defined in the POSIX 1003.1b standard but is
+ * commonly supported on most UNIX and POSIX systems. It is provided
+ * for compatibility.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+int truncate(
+ const char *path,
+ off_t length
+)
+{
+ int status;
+ int fd;
+
+ fd = open( path, O_WRONLY );
+ if ( fd == -1 )
+ return -1;
+
+ status = ftruncate( fd, length );
+
+ (void) close( fd );
+
+ return status;
+}
diff --git a/cpukit/libcsupport/src/ttyname.c b/cpukit/libcsupport/src/ttyname.c
new file mode 100644
index 0000000000..fe0dd35dee
--- /dev/null
+++ b/cpukit/libcsupport/src/ttyname.c
@@ -0,0 +1,77 @@
+/*
+ * ttyname_r() - POSIX 1003.1b 4.7.2 - Demetermine Terminal Device Name
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <termios.h>
+#include <unistd.h>
+#include <string.h>
+#include <paths.h>
+#include <_syslist.h>
+#include <errno.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int ttyname_r(
+ int fd,
+ char *name,
+ int namesize
+)
+{
+ struct stat sb;
+ struct termios tty;
+ struct dirent *dirp;
+ DIR *dp;
+ struct stat dsb;
+ char *rval;
+
+ /* Must be a terminal. */
+ if (tcgetattr (fd, &tty) < 0)
+ rtems_set_errno_and_return_minus_one(EBADF);
+
+ /* Must be a character device. */
+ if (fstat (fd, &sb) || !S_ISCHR (sb.st_mode))
+ rtems_set_errno_and_return_minus_one(EBADF);
+
+ if ((dp = opendir (_PATH_DEV)) == NULL)
+ rtems_set_errno_and_return_minus_one(EBADF);
+
+ for (rval = NULL; (dirp = readdir (dp)) != NULL ;)
+ {
+ if (dirp->d_ino != sb.st_ino)
+ continue;
+ strcpy (name + sizeof (_PATH_DEV) - 1, dirp->d_name);
+ if (stat (name, &dsb) || sb.st_dev != dsb.st_dev ||
+ sb.st_ino != dsb.st_ino)
+ continue;
+ rval = name;
+ break;
+ }
+ (void) closedir (dp);
+ return 0;
+}
+
+static char buf[sizeof (_PATH_DEV) + MAXNAMLEN] = _PATH_DEV;
+
+/*
+ * ttyname() - POSIX 1003.1b 4.7.2 - Demetermine Terminal Device Name
+ */
+
+char *ttyname(
+ int fd
+)
+{
+ if ( !ttyname_r( fd, buf, sizeof(buf) ) )
+ return buf;
+ return NULL;
+}
diff --git a/cpukit/libcsupport/src/ttyname_r.c b/cpukit/libcsupport/src/ttyname_r.c
new file mode 100644
index 0000000000..18bbd6c184
--- /dev/null
+++ b/cpukit/libcsupport/src/ttyname_r.c
@@ -0,0 +1,118 @@
+/*
+ * This file was copied from newlib-1.8.2/newlib/unix/ttyname.c
+ * and transformed into ttyname_r().
+ *
+ * Copyright (c) 1988 The Regents of the University of California.
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)ttyname.c 5.10 (Berkeley) 5/6/91";
+#endif /* LIBC_SCCS and not lint */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <termios.h>
+#include <unistd.h>
+#include <string.h>
+#include <paths.h>
+#include <_syslist.h>
+#include <errno.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+/*
+ * ttyname_r() - POSIX 1003.1b 4.7.2 - Demetermine Terminal Device Name
+ */
+
+int ttyname_r(
+ int fd,
+ char *name,
+ int namesize
+)
+{
+ struct stat sb;
+ struct termios tty;
+ struct dirent *dirp;
+ DIR *dp;
+ struct stat dsb;
+ char *rval;
+
+ /* Must be a terminal. */
+ if (tcgetattr (fd, &tty) < 0)
+ rtems_set_errno_and_return_minus_one(EBADF);
+
+ /* Must be a character device. */
+ if (_fstat (fd, &sb) || !S_ISCHR (sb.st_mode))
+ rtems_set_errno_and_return_minus_one(EBADF);
+
+ if ((dp = opendir (_PATH_DEV)) == NULL)
+ rtems_set_errno_and_return_minus_one(EBADF);
+
+ for (rval = NULL; (dirp = readdir (dp)) != NULL ;)
+ {
+ if (dirp->d_ino != sb.st_ino)
+ continue;
+ strcpy (name + sizeof (_PATH_DEV) - 1, dirp->d_name);
+ if (stat (name, &dsb) || sb.st_dev != dsb.st_dev ||
+ sb.st_ino != dsb.st_ino)
+ continue;
+ (void) closedir (dp);
+ rval = name;
+ break;
+ }
+ (void) closedir (dp);
+ return 0;
+}
+
+static char buf[sizeof (_PATH_DEV) + MAXNAMLEN] = _PATH_DEV;
+
+/*
+ * ttyname() - POSIX 1003.1b 4.7.2 - Demetermine Terminal Device Name
+ */
+
+char *ttyname(
+ int fd
+)
+{
+ if ( !ttyname_r( fd, buf, sizeof(buf) ) )
+ return buf;
+ return NULL;
+}
diff --git a/cpukit/libcsupport/src/umask.c b/cpukit/libcsupport/src/umask.c
new file mode 100644
index 0000000000..32bf79e2b9
--- /dev/null
+++ b/cpukit/libcsupport/src/umask.c
@@ -0,0 +1,33 @@
+/*
+ * umask() - POSIX 1003.1b 5.3.3 - Set File Creation Mask
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <rtems/libio_.h>
+
+mode_t umask(
+ mode_t cmask
+)
+{
+ mode_t old_mask;
+
+ old_mask = rtems_filesystem_umask;
+ rtems_filesystem_umask = cmask;
+
+ return old_mask;
+}
diff --git a/cpukit/libcsupport/src/unixlibc.c b/cpukit/libcsupport/src/unixlibc.c
new file mode 100644
index 0000000000..67d2d4f509
--- /dev/null
+++ b/cpukit/libcsupport/src/unixlibc.c
@@ -0,0 +1,53 @@
+/*
+ * $Id$
+ * UNIX Port C Library Support
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+
+rtems_status_code rtems_io_register_name(
+ char *device_name,
+ rtems_device_major_number major,
+ rtems_device_minor_number minor
+)
+{
+ return 0; /* not supported */
+}
+
+rtems_status_code rtems_io_lookup_name(
+ const char *name,
+ rtems_driver_name_t *device_info
+)
+{
+ return 0; /* not supported */
+}
+
+#if defined(RTEMS_UNIXLIB)
+
+void libc_init(int reentrant)
+{
+}
+
+#else
+
+/* remove ANSI errors.
+ * A program must contain at least one external-declaration
+ * (X3.159-1989 p.82,L3).
+ */
+void unixlibc_dummy_function( void )
+{
+}
+
+#endif
diff --git a/cpukit/libcsupport/src/unlink.c b/cpukit/libcsupport/src/unlink.c
new file mode 100644
index 0000000000..5b5f17c02a
--- /dev/null
+++ b/cpukit/libcsupport/src/unlink.c
@@ -0,0 +1,83 @@
+/*
+ * unlink() - POSIX 1003.1b - 5.5.1 - Remove an existing link
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int unlink(
+ const char *path
+)
+{
+ rtems_filesystem_location_info_t loc;
+ int result;
+
+ /*
+ * Get the node to be unlinked.
+ */
+
+ result = rtems_filesystem_evaluate_path( path, 0, &loc, FALSE );
+ if ( result != 0 )
+ return -1;
+
+ result = rtems_filesystem_evaluate_parent(RTEMS_LIBIO_PERMS_WRITE, &loc );
+ if (result != 0){
+ rtems_filesystem_freenode( &loc );
+ return -1;
+ }
+
+ if ( !loc.ops->node_type_h ) {
+ rtems_filesystem_freenode( &loc );
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+ }
+
+ if ( (*loc.ops->node_type_h)( &loc ) == RTEMS_FILESYSTEM_DIRECTORY ) {
+ rtems_filesystem_freenode( &loc );
+ rtems_set_errno_and_return_minus_one( EISDIR );
+ }
+
+ if ( !loc.ops->unlink_h ) {
+ rtems_filesystem_freenode( &loc );
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+ }
+
+ result = (*loc.ops->unlink_h)( &loc );
+
+ rtems_filesystem_freenode( &loc );
+
+ return result;
+}
+
+/*
+ * _unlink_r
+ *
+ * This is the Newlib dependent reentrant version of unlink().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+int _unlink_r(
+ struct _reent *ptr,
+ const char *path
+)
+{
+ return unlink( path );
+}
+#endif
diff --git a/cpukit/libcsupport/src/unmount.c b/cpukit/libcsupport/src/unmount.c
new file mode 100644
index 0000000000..f37d3f2e56
--- /dev/null
+++ b/cpukit/libcsupport/src/unmount.c
@@ -0,0 +1,219 @@
+/*
+ * unmount() - Unmount a File System
+ *
+ * This routine is not defined in the POSIX 1003.1b standard but
+ * in some form is supported on most UNIX and POSIX systems. This
+ * routine is necessary to mount instantiations of a file system
+ * into the file system name space.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <rtems/chain.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+/*
+ * Data structures and routines private to mount/unmount pair.
+ */
+
+extern Chain_Control rtems_filesystem_mount_table_control;
+
+int search_mt_for_mount_point(
+ rtems_filesystem_location_info_t *location_of_mount_point
+);
+
+rtems_boolean rtems_filesystem_nodes_equal(
+ const rtems_filesystem_location_info_t *loc1,
+ const rtems_filesystem_location_info_t *loc2
+){
+ return ( loc1->node_access == loc2->node_access );
+}
+
+
+/*
+ * file_systems_below_this_mountpoint
+ *
+ * This routine will run through the entries that currently exist in the
+ * mount table chain. For each entry in the mount table chain it will
+ * compare the mount tables mt_fs_root to the new_fs_root_node. If any of the
+ * mount table file system root nodes matches the new file system root node
+ * this indicates that we are trying to mount a file system that has already
+ * been mounted. This is not a permitted operation. temp_loc is set to
+ * the root node of the file system being unmounted.
+ */
+
+rtems_boolean file_systems_below_this_mountpoint(
+ const char *path,
+ rtems_filesystem_location_info_t *fs_root_loc,
+ rtems_filesystem_mount_table_entry_t *fs_to_unmount
+)
+{
+ Chain_Node *the_node;
+ rtems_filesystem_mount_table_entry_t *the_mount_entry;
+
+ /*
+ * Search the mount table for any mount entries referencing this
+ * mount entry.
+ */
+
+ for ( the_node = rtems_filesystem_mount_table_control.first;
+ !Chain_Is_tail( &rtems_filesystem_mount_table_control, the_node );
+ the_node = the_node->next ) {
+ the_mount_entry = ( rtems_filesystem_mount_table_entry_t * )the_node;
+ if (the_mount_entry->mt_point_node.mt_entry == fs_root_loc->mt_entry ) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/*
+ * unmount
+ *
+ * This routine will attempt to unmount the file system that has been
+ * is mounted a path. If the operation is successful, 0 will
+ * be returned to the calling routine. Otherwise, 1 will be returned.
+ */
+
+int unmount(
+ const char *path
+)
+{
+ rtems_filesystem_location_info_t loc;
+ rtems_filesystem_location_info_t *fs_root_loc;
+ rtems_filesystem_location_info_t *fs_mount_loc;
+ rtems_filesystem_mount_table_entry_t *mt_entry;
+
+ /*
+ * Get
+ * The root node of the mounted filesytem.
+ * The node for the directory that the fileystem is mounted on.
+ * The mount entry that is being refered to.
+ */
+
+ if ( rtems_filesystem_evaluate_path( path, 0x0, &loc, TRUE ) )
+ return -1;
+
+ mt_entry = loc.mt_entry;
+ fs_mount_loc = &mt_entry->mt_point_node;
+ fs_root_loc = &mt_entry->mt_fs_root;
+
+ /*
+ * Verify this is the root node for the file system to be unmounted.
+ */
+
+ if ( !rtems_filesystem_nodes_equal( fs_root_loc, &loc) ){
+ rtems_filesystem_freenode( &loc );
+ rtems_set_errno_and_return_minus_one( EACCES );
+ }
+
+ /*
+ * Free the loc node and just use the nodes from the mt_entry .
+ */
+
+ rtems_filesystem_freenode( &loc );
+
+ /*
+ * Verify Unmount is supported by both filesystems.
+ */
+
+ if ( !fs_mount_loc->ops->unmount_h )
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+
+ if ( !fs_root_loc->ops->fsunmount_me_h )
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+
+
+ /*
+ * Verify the current node is not in this filesystem.
+ * XXX - Joel I have a question here wasn't code added
+ * that made the current node thread based instead
+ * of system based? I thought it was but it doesn't
+ * look like it in this version.
+ */
+
+ if ( rtems_filesystem_current.mt_entry == mt_entry )
+ rtems_set_errno_and_return_minus_one( EBUSY );
+
+ /*
+ * Verify there are no file systems below the path specified
+ */
+
+ if ( file_systems_below_this_mountpoint( path, fs_root_loc, mt_entry ) != 0 )
+ rtems_set_errno_and_return_minus_one( EBUSY );
+
+ /*
+ * Run the file descriptor table to determine if there are any file
+ * descriptors that are currently active and reference nodes in the
+ * file system that we are trying to unmount
+ */
+
+ if ( rtems_libio_is_open_files_in_fs( mt_entry ) == 1 )
+ rtems_set_errno_and_return_minus_one( EBUSY );
+
+ /*
+ * Allow the file system being unmounted on to do its cleanup.
+ * If it fails it will set the errno to the approprate value
+ * and the fileystem will not be modified.
+ */
+
+ if (( fs_mount_loc->ops->unmount_h )( mt_entry ) != 0 )
+ return -1;
+
+ /*
+ * Allow the mounted filesystem to unmark the use of the root node.
+ *
+ * Run the unmount function for the subordinate file system.
+ *
+ * If we fail to unmount the filesystem remount it on the base filesystems
+ * directory node.
+ *
+ * NOTE: Fatal error is called in a case which should never happen
+ * This was response was questionable but the best we could
+ * come up with.
+ */
+
+ if ((fs_root_loc->ops->fsunmount_me_h )( mt_entry ) != 0){
+ if (( fs_mount_loc->ops->mount_h )( mt_entry ) != 0 )
+ rtems_fatal_error_occurred( 0 );
+ return -1;
+ }
+
+ /*
+ * Extract the mount table entry from the chain
+ */
+
+ Chain_Extract( ( Chain_Node * ) mt_entry );
+
+ /*
+ * Free the memory node that was allocated in mount
+ * Free the memory associated with the extracted mount table entry.
+ */
+
+ rtems_filesystem_freenode( fs_mount_loc );
+ free( mt_entry );
+
+ return 0;
+}
diff --git a/cpukit/libcsupport/src/utime.c b/cpukit/libcsupport/src/utime.c
new file mode 100644
index 0000000000..3af884a5bb
--- /dev/null
+++ b/cpukit/libcsupport/src/utime.c
@@ -0,0 +1,46 @@
+/*
+ * utime() - POSIX 1003.1b 5.5.6 - Set File Access and Modification Times
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <utime.h>
+#include <errno.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int utime(
+ const char *path,
+ const struct utimbuf *times
+)
+{
+ rtems_filesystem_location_info_t temp_loc;
+ int result;
+
+ if ( rtems_filesystem_evaluate_path( path, 0x00, &temp_loc, TRUE ) )
+ return -1;
+
+ if ( !temp_loc.ops->utime_h ){
+ rtems_filesystem_freenode( &temp_loc );
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+ }
+
+ result = (*temp_loc.ops->utime_h)( &temp_loc, times->actime, times->modtime );
+
+ rtems_filesystem_freenode( &temp_loc );
+
+ return result;
+}
diff --git a/cpukit/libcsupport/src/utsname.c b/cpukit/libcsupport/src/utsname.c
new file mode 100644
index 0000000000..cc114434bf
--- /dev/null
+++ b/cpukit/libcsupport/src/utsname.c
@@ -0,0 +1,53 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include <errno.h>
+#include <sys/utsname.h>
+
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/sptables.h>
+
+#include <rtems/seterr.h>
+
+/*PAGE
+ *
+ * 4.4.1 Get System Name, P1003.1b-1993, p. 90
+ */
+
+int uname(
+ struct utsname *name
+)
+{
+ /* XXX: Here is what Solaris returns...
+ sysname = SunOS
+ nodename = node_name
+ release = 5.3
+ version = Generic_101318-12
+ machine = sun4m
+ */
+
+ if ( !name )
+ rtems_set_errno_and_return_minus_one( EFAULT );
+
+ strcpy( name->sysname, "RTEMS" );
+
+ sprintf( name->nodename, "Node %d", _Objects_Local_node );
+
+ strcpy( name->release, RTEMS_VERSION );
+
+ strcpy( name->version, "" );
+
+ sprintf( name->machine, "%s/%s", CPU_NAME, CPU_MODEL_NAME );
+
+ return 0;
+}
diff --git a/cpukit/libcsupport/src/write.c b/cpukit/libcsupport/src/write.c
new file mode 100644
index 0000000000..4e08918ffb
--- /dev/null
+++ b/cpukit/libcsupport/src/write.c
@@ -0,0 +1,78 @@
+/*
+ * write() - POSIX 1003.1b 6.4.2 - Write to a File
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+/*
+ * write
+ *
+ * This routine writes count bytes from from buffer pointed to by buffer
+ * to the file associated with the open file descriptor, fildes.
+ */
+
+ssize_t write(
+ int fd,
+ const void *buffer,
+ size_t count
+)
+{
+ ssize_t rc;
+ rtems_libio_t *iop;
+
+ rtems_libio_check_fd( fd );
+ iop = rtems_libio_iop( fd );
+ rtems_libio_check_is_open(iop);
+ rtems_libio_check_buffer( buffer );
+ rtems_libio_check_count( count );
+ rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE );
+
+ /*
+ * Now process the write() request.
+ */
+
+ if ( !iop->handlers->write_h )
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+
+ rc = (*iop->handlers->write_h)( iop, buffer, count );
+
+ if ( rc > 0 )
+ iop->offset += rc;
+
+ return rc;
+}
+
+/*
+ * _write_r
+ *
+ * This is the Newlib dependent reentrant version of write().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+_ssize_t _write_r(
+ struct _reent *ptr,
+ int fd,
+ const void *buf,
+ size_t nbytes
+)
+{
+ return write( fd, buf, nbytes );
+}
+#endif
diff --git a/cpukit/libfs/.cvsignore b/cpukit/libfs/.cvsignore
new file mode 100644
index 0000000000..b52c5e8c77
--- /dev/null
+++ b/cpukit/libfs/.cvsignore
@@ -0,0 +1,3 @@
+Makefile
+Makefile.in
+stamp-h*
diff --git a/cpukit/libfs/Makefile.am b/cpukit/libfs/Makefile.am
new file mode 100644
index 0000000000..c2953e6ba0
--- /dev/null
+++ b/cpukit/libfs/Makefile.am
@@ -0,0 +1,110 @@
+##
+## $Id$
+##
+
+include $(top_srcdir)/automake/multilib.am
+include $(top_srcdir)/automake/compile.am
+
+AM_CPPFLAGS += -I$(top_builddir)
+
+EXTRA_DIST = README
+
+include_rtemsdir = $(includedir)/rtems
+include_rtems_HEADERS =
+
+EXTRA_LIBRARIES = libimfs.a
+CLEANFILES = libimfs.a
+libimfs_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libimfs_g.a
+CLEANFILES += libimfs_g.a
+libimfs_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+UNUSED_FILES = src/imfs/imfs_load_tar.c
+
+libimfs_a_SOURCES =
+
+if UNIX
+libimfs_a_SOURCES += src/imfs/imfs_unixstub.c
+else
+libimfs_a_SOURCES += src/imfs/imfs_chown.c src/imfs/imfs_config.c \
+ src/imfs/imfs_creat.c src/imfs/imfs_directory.c src/imfs/imfs_eval.c \
+ src/imfs/imfs_free.c src/imfs/imfs_fsunmount.c src/imfs/imfs_gtkn.c \
+ src/imfs/imfs_init.c src/imfs/imfs_initsupp.c src/imfs/imfs_link.c \
+ src/imfs/imfs_mknod.c src/imfs/imfs_mount.c src/imfs/imfs_fchmod.c \
+ src/imfs/imfs_unlink.c src/imfs/imfs_unmount.c src/imfs/imfs_utime.c \
+ src/imfs/imfs_ntype.c src/imfs/imfs_stat.c src/imfs/imfs_getchild.c \
+ src/imfs/memfile.c src/imfs/linearfile.c src/imfs/deviceio.c \
+ src/imfs/imfs_handlers_device.c src/imfs/imfs_handlers_directory.c \
+ src/imfs/imfs_handlers_link.c src/imfs/imfs_handlers_memfile.c \
+ src/imfs/imfs_debug.c src/imfs/imfs_rmnod.c src/imfs/imfs_symlink.c \
+ src/imfs/imfs_readlink.c src/imfs/imfs_fdatasync.c src/imfs/imfs_fcntl.c \
+ src/imfs/ioman.c src/imfs/miniimfs_init.c
+endif
+
+libimfs_g_a_SOURCES = $(libimfs_a_SOURCES)
+
+include_rtems_HEADERS += src/imfs/imfs.h
+
+IMFSLIB = libimfs$(LIB_VARIANT).a
+
+# dosfs
+
+if !UNIX
+EXTRA_LIBRARIES += libdosfs.a
+CLEANFILES += libdosfs.a
+libdosfs_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libdosfs_g.a
+CLEANFILES += libdosfs_g.a
+libdosfs_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+# libdosfs_FATFS_C_FILES
+libdosfs_a_SOURCES = src/dosfs/fat.c src/dosfs/fat.h \
+ src/dosfs/fat_fat_operations.c src/dosfs/fat_fat_operations.h \
+ src/dosfs/fat_file.c src/dosfs/fat_file.h
+
+# libdosfs_DOSFS_C_FILES
+libdosfs_a_SOURCES += src/dosfs/msdos_create.c src/dosfs/msdos_dir.c \
+ src/dosfs/msdos_eval.c src/dosfs/msdos_file.c src/dosfs/msdos_free.c \
+ src/dosfs/msdos_fsunmount.c src/dosfs/msdos_handlers_dir.c \
+ src/dosfs/msdos_handlers_file.c src/dosfs/msdos_init.c \
+ src/dosfs/msdos_initsupp.c src/dosfs/msdos_misc.c \
+ src/dosfs/msdos_mknod.c src/dosfs/msdos_node_type.c \
+ src/dosfs/msdos_conv.c src/dosfs/msdos.h
+
+libdosfs_g_a_SOURCES = $(libdosfs_a_SOURCES)
+
+include_rtems_HEADERS += src/dosfs/dosfs.h
+
+DOSFSLIB = libdosfs$(LIB_VARIANT).a
+endif
+
+EXTRA_DIST += $(UNUSED_FILES)
+
+all-local: $(PREINSTALL_FILES) $(IMFSLIB) $(DOSFSLIB)
+
+# ---
+
+PREINSTALL_DIRS =
+PREINSTALL_FILES =
+
+$(PROJECT_INCLUDE)/rtems/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems
+ @: > $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/imfs.h: src/imfs/imfs.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/imfs.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/imfs.h
+
+if !UNIX
+$(PROJECT_INCLUDE)/rtems/dosfs.h: src/dosfs/dosfs.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/dosfs.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/dosfs.h
+endif
+
+CLEANFILES += $(PREINSTALL_FILES)
+DISTCLEANFILES = $(PREINSTALL_DIRS)
+
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/libfs/README b/cpukit/libfs/README
new file mode 100644
index 0000000000..7409b93dca
--- /dev/null
+++ b/cpukit/libfs/README
@@ -0,0 +1,13 @@
+#
+# $Id$
+#
+
+This directory contains for the "file system" library. All supported
+file systems live under this tree.
+
+Currently the only supported file systems in this library are the IMFS
+and miniIMFS. The TFTP client filesystem is part of the libnetworking
+library.
+
+--Chris Johns and Joel Sherrill
+18 October 2000
diff --git a/cpukit/libfs/src/dosfs/.cvsignore b/cpukit/libfs/src/dosfs/.cvsignore
new file mode 100644
index 0000000000..4b0640c9c5
--- /dev/null
+++ b/cpukit/libfs/src/dosfs/.cvsignore
@@ -0,0 +1,4 @@
+config.h
+config.h.in
+stamp-h
+stamp-h.in
diff --git a/cpukit/libfs/src/dosfs/dosfs.h b/cpukit/libfs/src/dosfs/dosfs.h
new file mode 100644
index 0000000000..2524690aec
--- /dev/null
+++ b/cpukit/libfs/src/dosfs/dosfs.h
@@ -0,0 +1,31 @@
+/*
+ * dosfs.h
+ *
+ * Application interface to MSDOS filesystem.
+ *
+ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * @(#) $Id$
+ */
+#ifndef __DOSFS_DOSFS_H__
+#define __DOSFS_DOSFS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems.h>
+#include <rtems/libio.h>
+
+extern rtems_filesystem_operations_table msdos_ops;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DOSFS_DOSFS_H__ */
diff --git a/cpukit/libfs/src/dosfs/fat.c b/cpukit/libfs/src/dosfs/fat.c
new file mode 100644
index 0000000000..e0bcdb2cc0
--- /dev/null
+++ b/cpukit/libfs/src/dosfs/fat.c
@@ -0,0 +1,708 @@
+/*
+ * fat.c
+ *
+ * Low-level operations on a volume with FAT filesystem
+ *
+ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
+ *
+ * @(#) $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include <rtems/libio_.h>
+
+#include "fat.h"
+#include "fat_fat_operations.h"
+
+/* _fat_block_read --
+ * This function reads 'count' bytes from device filesystem is mounted on,
+ * starts at 'start+offset' position where 'start' computed in sectors
+ * and 'offset' is offset inside sector (reading may cross sectors
+ * boundary; in this case assumed we want to read sequential sector(s))
+ *
+ * PARAMETERS:
+ * mt_entry - mount table entry
+ * start - sector num to start read from
+ * offset - offset inside sector 'start'
+ * count - count of bytes to read
+ * buff - buffer provided by user
+ *
+ * RETURNS:
+ * bytes read on success, or -1 if error occured
+ * and errno set appropriately
+ */
+ssize_t
+_fat_block_read(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ uint32_t start,
+ uint32_t offset,
+ uint32_t count,
+ void *buff
+ )
+{
+ int rc = RC_OK;
+ register fat_fs_info_t *fs_info = mt_entry->fs_info;
+ ssize_t cmpltd = 0;
+ uint32_t blk = start;
+ uint32_t ofs = offset;
+ bdbuf_buffer *block = NULL;
+ uint32_t c = 0;
+
+ while (count > 0)
+ {
+ rc = fat_buf_access(fs_info, blk, FAT_OP_TYPE_READ, &block);
+ if (rc != RC_OK)
+ return -1;
+
+ c = MIN(count, (fs_info->vol.bps - ofs));
+ memcpy((buff + cmpltd), (block->buffer + ofs), c);
+
+ count -= c;
+ cmpltd += c;
+ blk++;
+ ofs = 0;
+ }
+ return cmpltd;
+}
+
+/* _fat_block_write --
+ * This function write 'count' bytes to device filesystem is mounted on,
+ * starts at 'start+offset' position where 'start' computed in sectors
+ * and 'offset' is offset inside sector (writing may cross sectors
+ * boundary; in this case assumed we want to write sequential sector(s))
+ *
+ * PARAMETERS:
+ * mt_entry - mount table entry
+ * start - sector num to start read from
+ * offset - offset inside sector 'start'
+ * count - count of bytes to write
+ * buff - buffer provided by user
+ *
+ * RETURNS:
+ * bytes written on success, or -1 if error occured
+ * and errno set appropriately
+ */
+ssize_t
+_fat_block_write(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ uint32_t start,
+ uint32_t offset,
+ uint32_t count,
+ const void *buff)
+{
+ int rc = RC_OK;
+ fat_fs_info_t *fs_info = mt_entry->fs_info;
+ ssize_t cmpltd = 0;
+ uint32_t blk = start;
+ uint32_t ofs = offset;
+ bdbuf_buffer *block = NULL;
+ uint32_t c = 0;
+
+ while(count > 0)
+ {
+ c = MIN(count, (fs_info->vol.bps - ofs));
+
+ if (c == fs_info->vol.bps)
+ rc = fat_buf_access(fs_info, blk, FAT_OP_TYPE_GET, &block);
+ else
+ rc = fat_buf_access(fs_info, blk, FAT_OP_TYPE_READ, &block);
+ if (rc != RC_OK)
+ return -1;
+
+ memcpy((block->buffer + ofs), (buff + cmpltd), c);
+
+ fat_buf_mark_modified(fs_info);
+
+ count -= c;
+ cmpltd +=c;
+ blk++;
+ ofs = 0;
+ }
+ return cmpltd;
+}
+
+
+
+
+/* fat_cluster_read --
+ * wrapper for reading a whole cluster at once
+ *
+ * PARAMETERS:
+ * mt_entry - mount table entry
+ * cln - number of cluster to read
+ * buff - buffer provided by user
+ *
+ * RETURNS:
+ * bytes read on success, or -1 if error occured
+ * and errno set appropriately
+ */
+ssize_t
+fat_cluster_read(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ uint32_t cln,
+ void *buff
+ )
+{
+ fat_fs_info_t *fs_info = mt_entry->fs_info;
+ uint32_t fsec = 0;
+
+ fsec = fat_cluster_num_to_sector_num(mt_entry, cln);
+
+ return _fat_block_read(mt_entry, fsec, 0,
+ fs_info->vol.spc << fs_info->vol.sec_log2, buff);
+}
+
+/* fat_cluster_write --
+ * wrapper for writting a whole cluster at once
+ *
+ * PARAMETERS:
+ * mt_entry - mount table entry
+ * cln - number of cluster to write
+ * buff - buffer provided by user
+ *
+ * RETURNS:
+ * bytes written on success, or -1 if error occured
+ * and errno set appropriately
+ */
+ssize_t
+fat_cluster_write(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ uint32_t cln,
+ const void *buff
+ )
+{
+ fat_fs_info_t *fs_info = mt_entry->fs_info;
+ uint32_t fsec = 0;
+
+ fsec = fat_cluster_num_to_sector_num(mt_entry, cln);
+
+ return _fat_block_write(mt_entry, fsec, 0,
+ fs_info->vol.spc << fs_info->vol.sec_log2, buff);
+}
+
+/* fat_init_volume_info --
+ * Get inforamtion about volume on which filesystem is mounted on
+ *
+ * PARAMETERS:
+ * mt_entry - mount table entry
+ *
+ * RETURNS:
+ * RC_OK on success, or -1 if error occured
+ * and errno set appropriately
+ */
+int
+fat_init_volume_info(rtems_filesystem_mount_table_entry_t *mt_entry)
+{
+ int rc = RC_OK;
+ fat_fs_info_t *fs_info = mt_entry->fs_info;
+ register fat_vol_t *vol = &fs_info->vol;
+ uint32_t data_secs = 0;
+ char boot_rec[FAT_MAX_BPB_SIZE];
+ char fs_info_sector[FAT_USEFUL_INFO_SIZE];
+ ssize_t ret = 0;
+ int fd;
+ struct stat stat_buf;
+ int i = 0;
+
+ rc = stat(mt_entry->dev, &stat_buf);
+ if (rc == -1)
+ return rc;
+
+ /* rtmes feature: no block devices, all are character devices */
+ if (!S_ISCHR(stat_buf.st_mode))
+ set_errno_and_return_minus_one(ENOTBLK);
+
+ /* check that device is registred as block device and lock it */
+ vol->dd = rtems_disk_lookup(stat_buf.st_dev);
+ if (vol->dd == NULL)
+ set_errno_and_return_minus_one(ENOTBLK);
+
+ vol->dev = stat_buf.st_dev;
+
+ fd = open(mt_entry->dev, O_RDONLY);
+ if (fd == -1)
+ {
+ rtems_disk_release(vol->dd);
+ return -1;
+ }
+
+ ret = read(fd, (void *)boot_rec, FAT_MAX_BPB_SIZE);
+ if ( ret != FAT_MAX_BPB_SIZE )
+ {
+ close(fd);
+ rtems_disk_release(vol->dd);
+ set_errno_and_return_minus_one( EIO );
+ }
+ close(fd);
+
+ vol->bps = FAT_BR_BYTES_PER_SECTOR(boot_rec);
+
+ if ( (vol->bps != 512) &&
+ (vol->bps != 1024) &&
+ (vol->bps != 2048) &&
+ (vol->bps != 4096))
+ {
+ rtems_disk_release(vol->dd);
+ set_errno_and_return_minus_one( EINVAL );
+ }
+
+ for (vol->sec_mul = 0, i = (vol->bps >> FAT_SECTOR512_BITS); (i & 1) == 0;
+ i >>= 1, vol->sec_mul++);
+ for (vol->sec_log2 = 0, i = vol->bps; (i & 1) == 0;
+ i >>= 1, vol->sec_log2++);
+
+ vol->spc = FAT_BR_SECTORS_PER_CLUSTER(boot_rec);
+ /*
+ * "sectors per cluster" of zero is invalid
+ * (and would hang the following loop)
+ */
+ if (vol->spc == 0)
+ {
+ rtems_disk_release(vol->dd);
+ set_errno_and_return_minus_one(EINVAL);
+ }
+
+ for (vol->spc_log2 = 0, i = vol->spc; (i & 1) == 0;
+ i >>= 1, vol->spc_log2++);
+
+ /*
+ * "bytes per cluster" value greater than 32K is invalid
+ */
+ if ((vol->bpc = vol->bps << vol->spc_log2) > MS_BYTES_PER_CLUSTER_LIMIT)
+ {
+ rtems_disk_release(vol->dd);
+ set_errno_and_return_minus_one(EINVAL);
+ }
+
+ for (vol->bpc_log2 = 0, i = vol->bpc; (i & 1) == 0;
+ i >>= 1, vol->bpc_log2++);
+
+ vol->fats = FAT_BR_FAT_NUM(boot_rec);
+ vol->fat_loc = FAT_BR_RESERVED_SECTORS_NUM(boot_rec);
+
+ vol->rdir_entrs = FAT_BR_FILES_PER_ROOT_DIR(boot_rec);
+
+ /* calculate the count of sectors occupied by the root directory */
+ vol->rdir_secs = ((vol->rdir_entrs * FAT_DIRENTRY_SIZE) + (vol->bps - 1)) /
+ vol->bps;
+
+ vol->rdir_size = vol->rdir_secs << vol->sec_log2;
+
+ if ( (FAT_BR_SECTORS_PER_FAT(boot_rec)) != 0)
+ vol->fat_length = FAT_BR_SECTORS_PER_FAT(boot_rec);
+ else
+ vol->fat_length = FAT_BR_SECTORS_PER_FAT32(boot_rec);
+
+ vol->data_fsec = vol->fat_loc + vol->fats * vol->fat_length +
+ vol->rdir_secs;
+
+ /* for FAT12/16 root dir starts at(sector) */
+ vol->rdir_loc = vol->fat_loc + vol->fats * vol->fat_length;
+
+ if ( (FAT_BR_TOTAL_SECTORS_NUM16(boot_rec)) != 0)
+ vol->tot_secs = FAT_BR_TOTAL_SECTORS_NUM16(boot_rec);
+ else
+ vol->tot_secs = FAT_BR_TOTAL_SECTORS_NUM32(boot_rec);
+
+ data_secs = vol->tot_secs - vol->data_fsec;
+
+ vol->data_cls = data_secs / vol->spc;
+
+ /* determine FAT type at least */
+ if ( vol->data_cls < FAT_FAT12_MAX_CLN)
+ {
+ vol->type = FAT_FAT12;
+ vol->mask = FAT_FAT12_MASK;
+ vol->eoc_val = FAT_FAT12_EOC;
+ }
+ else
+ {
+ if ( vol->data_cls < FAT_FAT16_MAX_CLN)
+ {
+ vol->type = FAT_FAT16;
+ vol->mask = FAT_FAT16_MASK;
+ vol->eoc_val = FAT_FAT16_EOC;
+ }
+ else
+ {
+ vol->type = FAT_FAT32;
+ vol->mask = FAT_FAT32_MASK;
+ vol->eoc_val = FAT_FAT32_EOC;
+ }
+ }
+
+ if (vol->type == FAT_FAT32)
+ {
+ vol->rdir_cl = FAT_BR_FAT32_ROOT_CLUSTER(boot_rec);
+
+ vol->mirror = FAT_BR_EXT_FLAGS(boot_rec) & FAT_BR_EXT_FLAGS_MIRROR;
+ if (vol->mirror)
+ vol->afat = FAT_BR_EXT_FLAGS(boot_rec) & FAT_BR_EXT_FLAGS_FAT_NUM;
+ else
+ vol->afat = 0;
+
+ vol->info_sec = FAT_BR_FAT32_FS_INFO_SECTOR(boot_rec);
+ if( vol->info_sec == 0 )
+ {
+ rtems_disk_release(vol->dd);
+ set_errno_and_return_minus_one( EINVAL );
+ }
+ else
+ {
+ ret = _fat_block_read(mt_entry, vol->info_sec , 0,
+ FAT_FSI_LEADSIG_SIZE, fs_info_sector);
+ if ( ret < 0 )
+ {
+ rtems_disk_release(vol->dd);
+ return -1;
+ }
+
+ if (FAT_FSINFO_LEAD_SIGNATURE(fs_info_sector) !=
+ FAT_FSINFO_LEAD_SIGNATURE_VALUE)
+ {
+ rtems_disk_release(vol->dd);
+ set_errno_and_return_minus_one( EINVAL );
+ }
+ else
+ {
+ ret = _fat_block_read(mt_entry, vol->info_sec , FAT_FSI_INFO,
+ FAT_USEFUL_INFO_SIZE, fs_info_sector);
+ if ( ret < 0 )
+ {
+ rtems_disk_release(vol->dd);
+ return -1;
+ }
+
+ vol->free_cls = FAT_FSINFO_FREE_CLUSTER_COUNT(fs_info_sector);
+ vol->next_cl = FAT_FSINFO_NEXT_FREE_CLUSTER(fs_info_sector);
+ rc = fat_fat32_update_fsinfo_sector(mt_entry, 0xFFFFFFFF,
+ 0xFFFFFFFF);
+ if ( rc != RC_OK )
+ {
+ rtems_disk_release(vol->dd);
+ return rc;
+ }
+ }
+ }
+ }
+ else
+ {
+ vol->rdir_cl = 0;
+ vol->mirror = 0;
+ vol->afat = 0;
+ vol->free_cls = 0xFFFFFFFF;
+ vol->next_cl = 0xFFFFFFFF;
+ }
+ vol->afat_loc = vol->fat_loc + vol->fat_length * vol->afat;
+
+ /* set up collection of fat-files fd */
+ fs_info->vhash = calloc(FAT_HASH_SIZE, sizeof(Chain_Control));
+ if ( fs_info->vhash == NULL )
+ {
+ rtems_disk_release(vol->dd);
+ set_errno_and_return_minus_one( ENOMEM );
+ }
+
+ for (i = 0; i < FAT_HASH_SIZE; i++)
+ _Chain_Initialize_empty(fs_info->vhash + i);
+
+ fs_info->rhash = calloc(FAT_HASH_SIZE, sizeof(Chain_Control));
+ if ( fs_info->rhash == NULL )
+ {
+ rtems_disk_release(vol->dd);
+ free(fs_info->vhash);
+ set_errno_and_return_minus_one( ENOMEM );
+ }
+ for (i = 0; i < FAT_HASH_SIZE; i++)
+ _Chain_Initialize_empty(fs_info->rhash + i);
+
+ fs_info->uino_pool_size = FAT_UINO_POOL_INIT_SIZE;
+ fs_info->uino_base = (vol->tot_secs << vol->sec_mul) << 4;
+ fs_info->index = 0;
+ fs_info->uino = (char *)calloc(fs_info->uino_pool_size, sizeof(char));
+ if ( fs_info->uino == NULL )
+ {
+ rtems_disk_release(vol->dd);
+ free(fs_info->vhash);
+ free(fs_info->rhash);
+ set_errno_and_return_minus_one( ENOMEM );
+ }
+ fs_info->sec_buf = (char *)calloc(vol->bps, sizeof(char));
+ if (fs_info->sec_buf == NULL)
+ {
+ rtems_disk_release(vol->dd);
+ free(fs_info->vhash);
+ free(fs_info->rhash);
+ free(fs_info->uino);
+ set_errno_and_return_minus_one( ENOMEM );
+ }
+
+ return RC_OK;
+}
+
+/* fat_shutdown_drive --
+ * Free all allocated resources and synchronize all necessary data
+ *
+ * PARAMETERS:
+ * mt_entry - mount table entry
+ *
+ * RETURNS:
+ * RC_OK on success, or -1 if error occured
+ * and errno set appropriately
+ */
+int
+fat_shutdown_drive(rtems_filesystem_mount_table_entry_t *mt_entry)
+{
+ int rc = RC_OK;
+ fat_fs_info_t *fs_info = mt_entry->fs_info;
+ int i = 0;
+
+ if (fs_info->vol.type & FAT_FAT32)
+ {
+ rc = fat_fat32_update_fsinfo_sector(mt_entry, fs_info->vol.free_cls,
+ fs_info->vol.next_cl);
+ if ( rc != RC_OK )
+ rc = -1;
+ }
+
+ fat_buf_release(fs_info);
+
+ if (rtems_bdbuf_syncdev(fs_info->vol.dev) != RTEMS_SUCCESSFUL)
+ rc = -1;
+
+ for (i = 0; i < FAT_HASH_SIZE; i++)
+ {
+ Chain_Node *node = NULL;
+ Chain_Control *the_chain = fs_info->vhash + i;
+
+ while ( (node = _Chain_Get(the_chain)) != NULL )
+ free(node);
+ }
+
+ for (i = 0; i < FAT_HASH_SIZE; i++)
+ {
+ Chain_Node *node = NULL;
+ Chain_Control *the_chain = fs_info->rhash + i;
+
+ while ( (node = _Chain_Get(the_chain)) != NULL )
+ free(node);
+ }
+
+ free(fs_info->vhash);
+ free(fs_info->rhash);
+
+ free(fs_info->uino);
+ free(fs_info->sec_buf);
+ rtems_disk_release(fs_info->vol.dd);
+
+ if (rc)
+ errno = EIO;
+ return rc;
+}
+
+/* fat_init_clusters_chain --
+ * Zeroing contents of all clusters in the chain
+ *
+ * PARAMETERS:
+ * mt_entry - mount table entry
+ * start_cluster_num - num of first cluster in the chain
+ *
+ * RETURNS:
+ * RC_OK on success, or -1 if error occured
+ * and errno set appropriately
+ */
+int
+fat_init_clusters_chain(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ uint32_t start_cln
+ )
+{
+ int rc = RC_OK;
+ ssize_t ret = 0;
+ register fat_fs_info_t *fs_info = mt_entry->fs_info;
+ uint32_t cur_cln = start_cln;
+ char *buf;
+
+ buf = calloc(fs_info->vol.bpc, sizeof(char));
+ if ( buf == NULL )
+ set_errno_and_return_minus_one( EIO );
+
+ while ((cur_cln & fs_info->vol.mask) < fs_info->vol.eoc_val)
+ {
+ ret = fat_cluster_write(mt_entry, cur_cln, buf);
+ if ( ret == -1 )
+ {
+ free(buf);
+ return -1;
+ }
+
+ rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);
+ if ( rc != RC_OK )
+ {
+ free(buf);
+ return rc;
+ }
+
+ }
+ free(buf);
+ return rc;
+}
+
+#define FAT_UNIQ_INO_BASE 0x0FFFFF00
+
+#define FAT_UNIQ_INO_IS_BUSY(index, arr) \
+ (((arr)[((index)>>3)]>>((index) & (8-1))) & 0x01)
+
+#define FAT_SET_UNIQ_INO_BUSY(index, arr) \
+ ((arr)[((index)>>3)] |= (0x01<<((index) & (8-1))))
+
+#define FAT_SET_UNIQ_INO_FREE(index, arr) \
+ ((arr)[((index)>>3)] &= (~(0x01<<((index) & (8-1)))))
+
+/* fat_get_unique_ino --
+ * Allocate unique ino from unique ino pool
+ *
+ * PARAMETERS:
+ * mt_entry - mount table entry
+ *
+ * RETURNS:
+ * unique inode number on success, or 0 if there is no free unique inode
+ * number in the pool
+ *
+ * ATTENTION:
+ * 0 means FAILED !!!
+ *
+ */
+uint32_t
+fat_get_unique_ino(rtems_filesystem_mount_table_entry_t *mt_entry)
+{
+ register fat_fs_info_t *fs_info = mt_entry->fs_info;
+ uint32_t j = 0;
+ rtems_boolean resrc_unsuff = FALSE;
+
+ while (!resrc_unsuff)
+ {
+ for (j = 0; j < fs_info->uino_pool_size; j++)
+ {
+ if (!FAT_UNIQ_INO_IS_BUSY(fs_info->index, fs_info->uino))
+ {
+ FAT_SET_UNIQ_INO_BUSY(fs_info->index, fs_info->uino);
+ return (fs_info->uino_base + fs_info->index);
+ }
+ fs_info->index++;
+ if (fs_info->index >= fs_info->uino_pool_size)
+ fs_info->index = 0;
+ }
+
+ if ((fs_info->uino_pool_size << 1) < (0x0FFFFFFF - fs_info->uino_base))
+ {
+ fs_info->uino_pool_size <<= 1;
+ fs_info->uino = realloc(fs_info->uino, fs_info->uino_pool_size);
+ if (fs_info->uino != NULL)
+ fs_info->index = fs_info->uino_pool_size;
+ else
+ resrc_unsuff = TRUE;
+ }
+ else
+ resrc_unsuff = TRUE;
+ }
+ return 0;
+}
+
+/* fat_free_unique_ino --
+ * Return unique ino to unique ino pool
+ *
+ * PARAMETERS:
+ * mt_entry - mount table entry
+ * ino - inode number to free
+ *
+ * RETURNS:
+ * None
+ */
+void
+fat_free_unique_ino(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ uint32_t ino
+ )
+{
+ fat_fs_info_t *fs_info = mt_entry->fs_info;
+
+ FAT_SET_UNIQ_INO_FREE((ino - fs_info->uino_base), fs_info->uino);
+}
+
+/* fat_ino_is_unique --
+ * Test whether ino is from unique ino pool
+ *
+ * PARAMETERS:
+ * mt_entry - mount table entry
+ * ino - ino to be tested
+ *
+ * RETURNS:
+ * TRUE if ino is allocated from unique ino pool, FALSE otherwise
+ */
+inline rtems_boolean
+fat_ino_is_unique(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ uint32_t ino
+ )
+{
+ fat_fs_info_t *fs_info = mt_entry->fs_info;
+
+ return (ino >= fs_info->uino_base);
+}
+
+/* fat_fat32_update_fsinfo_sector --
+ * Synchronize fsinfo sector for FAT32 volumes
+ *
+ * PARAMETERS:
+ * mt_entry - mount table entry
+ * free_count - count of free clusters
+ * next_free - the next free cluster num
+ *
+ * RETURNS:
+ * RC_OK on success, or -1 if error occured (errno set appropriately)
+ */
+int
+fat_fat32_update_fsinfo_sector(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ uint32_t free_count,
+ uint32_t next_free
+ )
+{
+ ssize_t ret1 = 0, ret2 = 0;
+ register fat_fs_info_t *fs_info = mt_entry->fs_info;
+ uint32_t le_free_count = 0;
+ uint32_t le_next_free = 0;
+
+ le_free_count = CT_LE_L(free_count);
+ le_next_free = CT_LE_L(next_free);
+
+ ret1 = _fat_block_write(mt_entry,
+ fs_info->vol.info_sec,
+ FAT_FSINFO_FREE_CLUSTER_COUNT_OFFSET,
+ 4,
+ (char *)(&le_free_count));
+
+ ret2 = _fat_block_write(mt_entry,
+ fs_info->vol.info_sec,
+ FAT_FSINFO_NEXT_FREE_CLUSTER_OFFSET,
+ 4,
+ (char *)(&le_next_free));
+
+ if ( (ret1 < 0) || (ret2 < 0) )
+ return -1;
+
+ return RC_OK;
+}
diff --git a/cpukit/libfs/src/dosfs/fat.h b/cpukit/libfs/src/dosfs/fat.h
new file mode 100644
index 0000000000..43f56b7393
--- /dev/null
+++ b/cpukit/libfs/src/dosfs/fat.h
@@ -0,0 +1,492 @@
+/*
+ * fat.h
+ *
+ * Constants/data structures/prototypes for low-level operations on a volume
+ * with FAT filesystem
+ *
+ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * @(#) $Id$
+ */
+
+#ifndef __DOSFS_FAT_H__
+#define __DOSFS_FAT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <string.h>
+
+#include <rtems/seterr.h>
+
+/* XXX: temporary hack :(( */
+#ifndef set_errno_and_return_minus_one
+#define set_errno_and_return_minus_one rtems_set_errno_and_return_minus_one
+#endif /* set_errno_and_return_minus_one */
+
+#include <rtems/score/cpu.h>
+#include <errno.h>
+#include <rtems/bdbuf.h>
+
+#ifndef RC_OK
+#define RC_OK 0x00000000
+#endif
+
+/*
+ * Remember that all FAT file system on disk data structure is
+ * "little endian"!
+ * (derived from linux)
+ */
+/*
+ * Conversion from and to little-endian byte order. (no-op on i386/i486)
+ *
+ * Naming: Ca_b_c, where a: F = from, T = to, b: LE = little-endian,
+ * BE = big-endian, c: W = word (16 bits), L = longword (32 bits)
+ */
+
+#if (CPU_BIG_ENDIAN == TRUE)
+# define CF_LE_W(v) CPU_swap_u16((uint16_t )v)
+# define CF_LE_L(v) CPU_swap_u32((uint32_t )v)
+# define CT_LE_W(v) CPU_swap_u16((uint16_t )v)
+# define CT_LE_L(v) CPU_swap_u32((uint32_t )v)
+#else
+# define CF_LE_W(v) (v)
+# define CF_LE_L(v) (v)
+# define CT_LE_W(v) (v)
+# define CT_LE_L(v) (v)
+#endif
+
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+#define FAT_HASH_SIZE 2
+#define FAT_HASH_MODULE FAT_HASH_SIZE
+
+
+#define FAT_SECTOR512_SIZE 512 /* sector size (bytes) */
+#define FAT_SECTOR512_BITS 9 /* log2(SECTOR_SIZE) */
+
+/* maximum + 1 number of clusters for FAT12 */
+#define FAT_FAT12_MAX_CLN 4085
+
+/* maximum + 1 number of clusters for FAT16 */
+#define FAT_FAT16_MAX_CLN 65525
+
+#define FAT_FAT12 0x01
+#define FAT_FAT16 0x02
+#define FAT_FAT32 0x04
+
+#define FAT_UNDEFINED_VALUE (uint32_t )0xFFFFFFFF
+
+#define FAT_FAT12_EOC 0x0FF8
+#define FAT_FAT16_EOC 0xFFF8
+#define FAT_FAT32_EOC (uint32_t )0x0FFFFFF8
+
+#define FAT_FAT12_FREE 0x0000
+#define FAT_FAT16_FREE 0x0000
+#define FAT_FAT32_FREE 0x00000000
+
+#define FAT_GENFAT_EOC (uint32_t )0xFFFFFFFF
+#define FAT_GENFAT_FREE (uint32_t )0x00000000
+
+#define FAT_FAT12_SHIFT 0x04
+
+#define FAT_FAT12_MASK 0x00000FFF
+#define FAT_FAT16_MASK 0x0000FFFF
+#define FAT_FAT32_MASK (uint32_t )0x0FFFFFFF
+
+#define FAT_MAX_BPB_SIZE 90
+
+/* size of useful information in FSInfo sector */
+#define FAT_USEFUL_INFO_SIZE 12
+
+#define FAT_VAL8(x, ofs) (uint8_t )(*((uint8_t *)(x) + (ofs)))
+
+#define FAT_VAL16(x, ofs) \
+ (uint16_t )( (*((uint8_t *)(x) + (ofs))) | \
+ ((*((uint8_t *)(x) + (ofs) + 1)) << 8) )
+
+#define FAT_VAL32(x, ofs) \
+ (uint32_t )( (uint32_t )(*((uint8_t *)(x) + (ofs))) | \
+ ((uint32_t )(*((uint8_t *)(x) + (ofs) + 1)) << 8) | \
+ ((uint32_t )(*((uint8_t *)(x) + (ofs) + 2)) << 16) | \
+ ((uint32_t )(*((uint8_t *)(x) + (ofs) + 3)) << 24) )
+
+/* macros to access boot sector fields */
+#define FAT_BR_BYTES_PER_SECTOR(x) FAT_VAL16(x, 11)
+#define FAT_BR_SECTORS_PER_CLUSTER(x) FAT_VAL8(x, 13)
+#define FAT_BR_RESERVED_SECTORS_NUM(x) FAT_VAL16(x, 14)
+#define FAT_BR_FAT_NUM(x) FAT_VAL8(x, 16)
+#define FAT_BR_FILES_PER_ROOT_DIR(x) FAT_VAL16(x, 17)
+#define FAT_BR_TOTAL_SECTORS_NUM16(x) FAT_VAL16(x, 19)
+#define FAT_BR_MEDIA(x) FAT_VAL8(x, 21)
+#define FAT_BR_SECTORS_PER_FAT(x) FAT_VAL16(x, 22)
+#define FAT_BR_TOTAL_SECTORS_NUM32(x) FAT_VAL32(x, 32)
+#define FAT_BR_SECTORS_PER_FAT32(x) FAT_VAL32(x, 36)
+#define FAT_BR_EXT_FLAGS(x) FAT_VAL16(x, 40)
+#define FAT_BR_FAT32_ROOT_CLUSTER(x) FAT_VAL32(x, 44)
+#define FAT_BR_FAT32_FS_INFO_SECTOR(x) FAT_VAL16(x, 48)
+#define FAT_FSINFO_LEAD_SIGNATURE(x) FAT_VAL32(x, 0)
+/*
+ * I read FSInfo sector from offset 484 to access the information, so offsets
+ * of these fields a relative
+ */
+#define FAT_FSINFO_FREE_CLUSTER_COUNT(x) FAT_VAL32(x, 4)
+#define FAT_FSINFO_NEXT_FREE_CLUSTER(x) FAT_VAL32(x, 8)
+
+#define FAT_FSINFO_FREE_CLUSTER_COUNT_OFFSET 488
+
+#define FAT_FSINFO_NEXT_FREE_CLUSTER_OFFSET 492
+
+#define FAT_RSRVD_CLN 0x02
+
+#define FAT_FSINFO_LEAD_SIGNATURE_VALUE 0x41615252
+
+#define FAT_FSI_LEADSIG_SIZE 0x04
+
+#define FAT_FSI_INFO 484
+
+#define MS_BYTES_PER_CLUSTER_LIMIT 0x8000 /* 32K */
+
+#define FAT_BR_EXT_FLAGS_MIRROR 0x0080
+
+#define FAT_BR_EXT_FLAGS_FAT_NUM 0x000F
+
+
+#define FAT_DIRENTRY_SIZE 32
+
+#define FAT_DIRENTRIES_PER_SEC512 16
+
+/*
+ * Volume descriptor
+ * Description of the volume the FAT filesystem is located on - generally
+ * the fields of the structure corresponde to Boot Sector and BPB Srtucture
+ * fields
+ */
+typedef struct fat_vol_s
+{
+ uint16_t bps; /* bytes per sector */
+ uint8_t sec_log2; /* log2 of bps */
+ uint8_t sec_mul; /* log2 of 512bts sectors number per sector */
+ uint8_t spc; /* sectors per cluster */
+ uint8_t spc_log2; /* log2 of spc */
+ uint16_t bpc; /* bytes per cluster */
+ uint8_t bpc_log2; /* log2 of bytes per cluster */
+ uint8_t fats; /* number of FATs */
+ uint8_t type; /* FAT type */
+ uint32_t mask;
+ uint32_t eoc_val;
+ uint16_t fat_loc; /* FAT start */
+ uint32_t fat_length; /* sectors per FAT */
+ uint32_t rdir_loc; /* root directory start */
+ uint16_t rdir_entrs; /* files per root directory */
+ uint32_t rdir_secs; /* sectors per root directory */
+ uint32_t rdir_size; /* root directory size in bytes */
+ uint32_t tot_secs; /* total count of sectors */
+ uint32_t data_fsec; /* first data sector */
+ uint32_t data_cls; /* count of data clusters */
+ uint32_t rdir_cl; /* first cluster of the root directory */
+ uint16_t info_sec; /* FSInfo Sector Structure location */
+ uint32_t free_cls; /* last known free clusters count */
+ uint32_t next_cl; /* next free cluster number */
+ uint8_t mirror; /* mirroring enabla/disable */
+ uint32_t afat_loc; /* active FAT location */
+ uint8_t afat; /* the number of active FAT */
+ dev_t dev; /* device ID */
+ disk_device *dd; /* disk device (see libblock) */
+ void *private_data; /* reserved */
+} fat_vol_t;
+
+
+typedef struct fat_cache_s
+{
+ uint32_t blk_num;
+ rtems_boolean modified;
+ uint8_t state;
+ bdbuf_buffer *buf;
+} fat_cache_t;
+
+/*
+ * This structure identifies the instance of the filesystem on the FAT
+ * ("fat-file") level.
+ */
+typedef struct fat_fs_info_s
+{
+ fat_vol_t vol; /* volume descriptor */
+ Chain_Control *vhash; /* "vhash" of fat-file descriptors */
+ Chain_Control *rhash; /* "rhash" of fat-file descriptors */
+ char *uino; /* array of unique ino numbers */
+ uint32_t index;
+ uint32_t uino_pool_size; /* size */
+ uint32_t uino_base;
+ fat_cache_t c; /* cache */
+ uint8_t *sec_buf; /* just placeholder for anything */
+} fat_fs_info_t;
+
+/*
+ * if the name we looking for is file we store not only first data cluster
+ * number, but and cluster number and offset for directory entry for this
+ * name
+ */
+typedef struct fat_auxiliary_s
+{
+ uint32_t cln;
+ uint32_t ofs;
+} fat_auxiliary_t;
+
+#define FAT_FAT_OFFSET(fat_type, cln) \
+ ((fat_type) & FAT_FAT12 ? ((cln) + ((cln) >> 1)) : \
+ (fat_type) & FAT_FAT16 ? ((cln) << 1) : \
+ ((cln) << 2))
+
+#define FAT_CLUSTER_IS_ODD(n) ((n) & 0x0001)
+
+#define FAT12_SHIFT 0x4 /* half of a byte */
+
+/* initial size of array of unique ino */
+#define FAT_UINO_POOL_INIT_SIZE 0x100
+
+/* cache support */
+#define FAT_CACHE_EMPTY 0x0
+#define FAT_CACHE_ACTUAL 0x1
+
+#define FAT_OP_TYPE_READ 0x1
+#define FAT_OP_TYPE_GET 0x2
+
+static inline uint32_t
+fat_cluster_num_to_sector_num(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ uint32_t cln
+ )
+{
+ register fat_fs_info_t *fs_info = mt_entry->fs_info;
+
+ if ( (cln == 0) && (fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)) )
+ return fs_info->vol.rdir_loc;
+
+ return (((cln - FAT_RSRVD_CLN) << fs_info->vol.spc_log2) +
+ fs_info->vol.data_fsec);
+}
+
+static inline uint32_t
+fat_cluster_num_to_sector512_num(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ uint32_t cln
+ )
+{
+ fat_fs_info_t *fs_info = mt_entry->fs_info;
+
+ if (cln == 1)
+ return 1;
+
+ return (fat_cluster_num_to_sector_num(mt_entry, cln) <<
+ fs_info->vol.sec_mul);
+}
+
+static inline int
+fat_buf_access(fat_fs_info_t *fs_info, uint32_t blk, int op_type,
+ bdbuf_buffer **buf)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ uint8_t i;
+ rtems_boolean sec_of_fat;
+
+
+ if (fs_info->c.state == FAT_CACHE_EMPTY)
+ {
+ if (op_type == FAT_OP_TYPE_READ)
+ sc = rtems_bdbuf_read(fs_info->vol.dev, blk, &fs_info->c.buf);
+ else
+ sc = rtems_bdbuf_get(fs_info->vol.dev, blk, &fs_info->c.buf);
+ if (sc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one(EIO);
+ fs_info->c.blk_num = blk;
+ fs_info->c.modified = 0;
+ fs_info->c.state = FAT_CACHE_ACTUAL;
+ }
+
+ sec_of_fat = ((fs_info->c.blk_num >= fs_info->vol.fat_loc) &&
+ (fs_info->c.blk_num < fs_info->vol.rdir_loc));
+
+ if (fs_info->c.blk_num != blk)
+ {
+ if (fs_info->c.modified)
+ {
+ if (sec_of_fat && !fs_info->vol.mirror)
+ memcpy(fs_info->sec_buf, fs_info->c.buf->buffer,
+ fs_info->vol.bps);
+
+ sc = rtems_bdbuf_release_modified(fs_info->c.buf);
+ fs_info->c.state = FAT_CACHE_EMPTY;
+ fs_info->c.modified = 0;
+ if (sc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one(EIO);
+
+ if (sec_of_fat && !fs_info->vol.mirror)
+ {
+ bdbuf_buffer *b;
+
+ for (i = 1; i < fs_info->vol.fats; i++)
+ {
+ sc = rtems_bdbuf_get(fs_info->vol.dev,
+ fs_info->c.blk_num +
+ fs_info->vol.fat_length * i,
+ &b);
+ if ( sc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one(ENOMEM);
+ memcpy(b->buffer, fs_info->sec_buf, fs_info->vol.bps);
+ sc = rtems_bdbuf_release_modified(b);
+ if ( sc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one(ENOMEM);
+ }
+ }
+ }
+ else
+ {
+ sc = rtems_bdbuf_release(fs_info->c.buf);
+ fs_info->c.state = FAT_CACHE_EMPTY;
+ if (sc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one(EIO);
+
+ }
+ if (op_type == FAT_OP_TYPE_READ)
+ sc = rtems_bdbuf_read(fs_info->vol.dev, blk, &fs_info->c.buf);
+ else
+ sc = rtems_bdbuf_get(fs_info->vol.dev, blk, &fs_info->c.buf);
+ if (sc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one(EIO);
+ fs_info->c.blk_num = blk;
+ fs_info->c.state = FAT_CACHE_ACTUAL;
+ }
+ *buf = fs_info->c.buf;
+ return RC_OK;
+}
+
+
+static inline int
+fat_buf_release(fat_fs_info_t *fs_info)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ uint8_t i;
+ rtems_boolean sec_of_fat;
+
+ if (fs_info->c.state == FAT_CACHE_EMPTY)
+ return RC_OK;
+
+ sec_of_fat = ((fs_info->c.blk_num >= fs_info->vol.fat_loc) &&
+ (fs_info->c.blk_num < fs_info->vol.rdir_loc));
+
+ if (fs_info->c.modified)
+ {
+ if (sec_of_fat && !fs_info->vol.mirror)
+ memcpy(fs_info->sec_buf, fs_info->c.buf->buffer, fs_info->vol.bps);
+
+ sc = rtems_bdbuf_release_modified(fs_info->c.buf);
+ if (sc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one(EIO);
+ fs_info->c.modified = 0;
+
+ if (sec_of_fat && !fs_info->vol.mirror)
+ {
+ bdbuf_buffer *b;
+
+ for (i = 1; i < fs_info->vol.fats; i++)
+ {
+ sc = rtems_bdbuf_get(fs_info->vol.dev,
+ fs_info->c.blk_num +
+ fs_info->vol.fat_length * i,
+ &b);
+ if ( sc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one(ENOMEM);
+ memcpy(b->buffer, fs_info->sec_buf, fs_info->vol.bps);
+ sc = rtems_bdbuf_release_modified(b);
+ if ( sc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one(ENOMEM);
+ }
+ }
+ }
+ else
+ {
+ sc = rtems_bdbuf_release(fs_info->c.buf);
+ if (sc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one(EIO);
+ }
+ fs_info->c.state = FAT_CACHE_EMPTY;
+ return RC_OK;
+}
+
+static inline void
+fat_buf_mark_modified(fat_fs_info_t *fs_info)
+{
+ fs_info->c.modified = TRUE;
+}
+
+
+
+ssize_t
+_fat_block_read(rtems_filesystem_mount_table_entry_t *mt_entry,
+ uint32_t start,
+ uint32_t offset,
+ uint32_t count,
+ void *buff);
+
+ssize_t
+_fat_block_write(rtems_filesystem_mount_table_entry_t *mt_entry,
+ uint32_t start,
+ uint32_t offset,
+ uint32_t count,
+ const void *buff);
+
+ssize_t
+fat_cluster_read(rtems_filesystem_mount_table_entry_t *mt_entry,
+ uint32_t cln,
+ void *buff);
+
+ssize_t
+fat_cluster_write(rtems_filesystem_mount_table_entry_t *mt_entry,
+ uint32_t cln,
+ const void *buff);
+
+int
+fat_init_volume_info(rtems_filesystem_mount_table_entry_t *mt_entry);
+
+int
+fat_init_clusters_chain(rtems_filesystem_mount_table_entry_t *mt_entry,
+ uint32_t start_cln);
+
+uint32_t
+fat_cluster_num_to_sector_num(rtems_filesystem_mount_table_entry_t *mt_entry,
+ uint32_t cln);
+
+int
+fat_shutdown_drive(rtems_filesystem_mount_table_entry_t *mt_entry);
+
+
+uint32_t
+fat_get_unique_ino(rtems_filesystem_mount_table_entry_t *mt_entry);
+
+rtems_boolean
+fat_ino_is_unique(rtems_filesystem_mount_table_entry_t *mt_entry,
+ uint32_t ino);
+
+void
+fat_free_unique_ino(rtems_filesystem_mount_table_entry_t *mt_entry,
+ uint32_t ino);
+
+int
+fat_fat32_update_fsinfo_sector(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ uint32_t free_count,
+ uint32_t next_free
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DOSFS_FAT_H__ */
diff --git a/cpukit/libfs/src/dosfs/fat_fat_operations.c b/cpukit/libfs/src/dosfs/fat_fat_operations.c
new file mode 100644
index 0000000000..0e6411f799
--- /dev/null
+++ b/cpukit/libfs/src/dosfs/fat_fat_operations.c
@@ -0,0 +1,437 @@
+/*
+ * fat_fat_operations.c
+ *
+ * General operations on File Allocation Table
+ *
+ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
+ *
+ * @(#) $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include <rtems/libio_.h>
+
+#include "fat.h"
+#include "fat_fat_operations.h"
+
+/* fat_scan_fat_for_free_clusters --
+ * Allocate chain of free clusters from Files Allocation Table
+ *
+ * PARAMETERS:
+ * mt_entry - mount table entry
+ * chain - the number of the first allocated cluster (first cluster
+ * in the chain)
+ * count - count of clusters to allocate (chain length)
+ *
+ * RETURNS:
+ * RC_OK on success, or error code if error occured (errno set
+ * appropriately)
+ *
+ *
+ */
+int
+fat_scan_fat_for_free_clusters(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ uint32_t *chain,
+ uint32_t count,
+ uint32_t *cls_added,
+ uint32_t *last_cl
+ )
+{
+ int rc = RC_OK;
+ fat_fs_info_t *fs_info = mt_entry->fs_info;
+ uint32_t cl4find = 2;
+ uint32_t next_cln = 0;
+ uint32_t save_cln = 0;
+ uint32_t data_cls_val = fs_info->vol.data_cls + 2;
+ uint32_t i = 2;
+
+ *cls_added = 0;
+
+ if (count == 0)
+ return rc;
+
+ if (fs_info->vol.next_cl != FAT_UNDEFINED_VALUE)
+ cl4find = fs_info->vol.next_cl;
+
+ /*
+ * fs_info->vol.data_cls is exactly the count of data clusters
+ * starting at cluster 2, so the maximum valid cluster number is
+ * (fs_info->vol.data_cls + 1)
+ */
+ while (i < data_cls_val)
+ {
+ rc = fat_get_fat_cluster(mt_entry, cl4find, &next_cln);
+ if ( rc != RC_OK )
+ {
+ if (*cls_added != 0)
+ fat_free_fat_clusters_chain(mt_entry, (*chain));
+ return rc;
+ }
+
+ if (next_cln == FAT_GENFAT_FREE)
+ {
+ /*
+ * We are enforced to process allocation of the first free cluster
+ * by separate 'if' statement because otherwise undo function
+ * wouldn't work properly
+ */
+ if (*cls_added == 0)
+ {
+ *chain = cl4find;
+ rc = fat_set_fat_cluster(mt_entry, cl4find, FAT_GENFAT_EOC);
+ if ( rc != RC_OK )
+ {
+ /*
+ * this is the first cluster we tried to allocate so no
+ * cleanup activity needed
+ */
+ return rc;
+ }
+ }
+ else
+ {
+ /* set EOC value to new allocated cluster */
+ rc = fat_set_fat_cluster(mt_entry, cl4find, FAT_GENFAT_EOC);
+ if ( rc != RC_OK )
+ {
+ /* cleanup activity */
+ fat_free_fat_clusters_chain(mt_entry, (*chain));
+ return rc;
+ }
+
+ rc = fat_set_fat_cluster(mt_entry, save_cln, cl4find);
+ if ( rc != RC_OK )
+ {
+ /* cleanup activity */
+ fat_free_fat_clusters_chain(mt_entry, (*chain));
+ /* trying to save last allocated cluster for future use */
+ fat_set_fat_cluster(mt_entry, cl4find, FAT_GENFAT_FREE);
+ fat_buf_release(fs_info);
+ return rc;
+ }
+ }
+
+ save_cln = cl4find;
+ (*cls_added)++;
+
+ /* have we satisfied request ? */
+ if (*cls_added == count)
+ {
+ fs_info->vol.next_cl = save_cln;
+ if (fs_info->vol.free_cls != 0xFFFFFFFF)
+ fs_info->vol.free_cls -= (*cls_added);
+ *last_cl = save_cln;
+ fat_buf_release(fs_info);
+ return rc;
+ }
+ }
+ i++;
+ cl4find++;
+ if (cl4find >= data_cls_val)
+ cl4find = 2;
+ }
+
+ fs_info->vol.next_cl = save_cln;
+ if (fs_info->vol.free_cls != 0xFFFFFFFF)
+ fs_info->vol.free_cls -= (*cls_added);
+
+ *last_cl = save_cln;
+ fat_buf_release(fs_info);
+ return RC_OK;
+}
+
+/* fat_free_fat_clusters_chain --
+ * Free chain of clusters in Files Allocation Table.
+ *
+ * PARAMETERS:
+ * mt_entry - mount table entry
+ * chain - number of the first cluster in the chain
+ *
+ * RETURNS:
+ * RC_OK on success, or -1 if error occured (errno set appropriately)
+ */
+int
+fat_free_fat_clusters_chain(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ uint32_t chain
+ )
+{
+ int rc = RC_OK, rc1 = RC_OK;
+ fat_fs_info_t *fs_info = mt_entry->fs_info;
+ uint32_t cur_cln = chain;
+ uint32_t next_cln = 0;
+ uint32_t freed_cls_cnt = 0;
+
+ while ((cur_cln & fs_info->vol.mask) < fs_info->vol.eoc_val)
+ {
+ rc = fat_get_fat_cluster(mt_entry, cur_cln, &next_cln);
+ if ( rc != RC_OK )
+ {
+ if(fs_info->vol.free_cls != FAT_UNDEFINED_VALUE)
+ fs_info->vol.free_cls += freed_cls_cnt;
+
+ fat_buf_release(fs_info);
+ return rc;
+ }
+
+ rc = fat_set_fat_cluster(mt_entry, cur_cln, FAT_GENFAT_FREE);
+ if ( rc != RC_OK )
+ rc1 = rc;
+
+ freed_cls_cnt++;
+ cur_cln = next_cln;
+ }
+
+ fs_info->vol.next_cl = chain;
+ if (fs_info->vol.free_cls != FAT_UNDEFINED_VALUE)
+ fs_info->vol.free_cls += freed_cls_cnt;
+
+ fat_buf_release(fs_info);
+ if (rc1 != RC_OK)
+ return rc1;
+
+ return RC_OK;
+}
+
+/* fat_get_fat_cluster --
+ * Fetches the contents of the cluster (link to next cluster in the chain)
+ * from Files Allocation Table.
+ *
+ * PARAMETERS:
+ * mt_entry - mount table entry
+ * cln - number of cluster to fetch the contents from
+ * ret_val - contents of the cluster 'cln' (link to next cluster in
+ * the chain)
+ *
+ * RETURNS:
+ * RC_OK on success, or -1 if error occured
+ * and errno set appropriately
+ */
+int
+fat_get_fat_cluster(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ uint32_t cln,
+ uint32_t *ret_val
+ )
+{
+ int rc = RC_OK;
+ register fat_fs_info_t *fs_info = mt_entry->fs_info;
+ bdbuf_buffer *block0 = NULL;
+ uint32_t sec = 0;
+ uint32_t ofs = 0;
+
+ /* sanity check */
+ if ( (cln < 2) || (cln > (fs_info->vol.data_cls + 1)) )
+ set_errno_and_return_minus_one(EIO);
+
+ sec = (FAT_FAT_OFFSET(fs_info->vol.type, cln) >> fs_info->vol.sec_log2) +
+ fs_info->vol.afat_loc;
+ ofs = FAT_FAT_OFFSET(fs_info->vol.type, cln) & (fs_info->vol.bps - 1);
+
+ rc = fat_buf_access(fs_info, sec, FAT_OP_TYPE_READ, &block0);
+ if (rc != RC_OK)
+ return rc;
+
+ switch ( fs_info->vol.type )
+ {
+ case FAT_FAT12:
+ /*
+ * we are enforced in complex computations for FAT12 to escape CPU
+ * align problems for some architectures
+ */
+ *ret_val = (*((uint8_t *)(block0->buffer + ofs)));
+ if ( ofs == (fs_info->vol.bps - 1) )
+ {
+ rc = fat_buf_access(fs_info, sec + 1, FAT_OP_TYPE_READ,
+ &block0);
+ if (rc != RC_OK)
+ return rc;
+
+ *ret_val |= (*((uint8_t *)(block0->buffer)))<<8;
+ }
+ else
+ {
+ *ret_val |= (*((uint8_t *)(block0->buffer + ofs + 1)))<<8;
+ }
+
+ if ( FAT_CLUSTER_IS_ODD(cln) )
+ *ret_val = (*ret_val) >> FAT12_SHIFT;
+ else
+ *ret_val = (*ret_val) & FAT_FAT12_MASK;
+ break;
+
+ case FAT_FAT16:
+ *ret_val = *((uint16_t *)(block0->buffer + ofs));
+ *ret_val = CF_LE_W(*ret_val);
+ break;
+
+ case FAT_FAT32:
+ *ret_val = *((uint32_t *)(block0->buffer + ofs));
+ *ret_val = CF_LE_L(*ret_val);
+ break;
+
+ default:
+ set_errno_and_return_minus_one(EIO);
+ break;
+ }
+
+ return RC_OK;
+}
+
+/* fat_set_fat_cluster --
+ * Set the contents of the cluster (link to next cluster in the chain)
+ * from Files Allocation Table.
+ *
+ * PARAMETERS:
+ * mt_entry - mount table entry
+ * cln - number of cluster to set contents to
+ * in_val - value to set
+ *
+ * RETURNS:
+ * RC_OK on success, or -1 if error occured
+ * and errno set appropriately
+ */
+int
+fat_set_fat_cluster(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ uint32_t cln,
+ uint32_t in_val
+ )
+{
+ int rc = RC_OK;
+ fat_fs_info_t *fs_info = mt_entry->fs_info;
+ uint32_t sec = 0;
+ uint32_t ofs = 0;
+ uint16_t fat16_clv = 0;
+ uint32_t fat32_clv = 0;
+ bdbuf_buffer *block0 = NULL;
+
+ /* sanity check */
+ if ( (cln < 2) || (cln > (fs_info->vol.data_cls + 1)) )
+ set_errno_and_return_minus_one(EIO);
+
+ sec = (FAT_FAT_OFFSET(fs_info->vol.type, cln) >> fs_info->vol.sec_log2) +
+ fs_info->vol.afat_loc;
+ ofs = FAT_FAT_OFFSET(fs_info->vol.type, cln) & (fs_info->vol.bps - 1);
+
+ rc = fat_buf_access(fs_info, sec, FAT_OP_TYPE_READ, &block0);
+ if (rc != RC_OK)
+ return rc;
+
+ switch ( fs_info->vol.type )
+ {
+ case FAT_FAT12:
+ if ( FAT_CLUSTER_IS_ODD(cln) )
+ {
+ fat16_clv = ((uint16_t )in_val) << FAT_FAT12_SHIFT;
+ *((uint8_t *)(block0->buffer + ofs)) =
+ (*((uint8_t *)(block0->buffer + ofs))) & 0x0F;
+
+ *((uint8_t *)(block0->buffer + ofs)) =
+ (*((uint8_t *)(block0->buffer + ofs))) |
+ (uint8_t )(fat16_clv & 0x00FF);
+
+ fat_buf_mark_modified(fs_info);
+
+ if ( ofs == (fs_info->vol.bps - 1) )
+ {
+ rc = fat_buf_access(fs_info, sec + 1, FAT_OP_TYPE_READ,
+ &block0);
+ if (rc != RC_OK)
+ return rc;
+
+ *((uint8_t *)(block0->buffer)) &= 0x00;
+
+ *((uint8_t *)(block0->buffer)) =
+ (*((uint8_t *)(block0->buffer))) |
+ (uint8_t )((fat16_clv & 0xFF00)>>8);
+
+ fat_buf_mark_modified(fs_info);
+ }
+ else
+ {
+ *((uint8_t *)(block0->buffer + ofs + 1)) &= 0x00;
+
+ *((uint8_t *)(block0->buffer + ofs + 1)) =
+ (*((uint8_t *)(block0->buffer + ofs + 1))) |
+ (uint8_t )((fat16_clv & 0xFF00)>>8);
+ }
+ }
+ else
+ {
+ fat16_clv = ((uint16_t )in_val) & FAT_FAT12_MASK;
+ *((uint8_t *)(block0->buffer + ofs)) &= 0x00;
+
+ *((uint8_t *)(block0->buffer + ofs)) =
+ (*((uint8_t *)(block0->buffer + ofs))) |
+ (uint8_t )(fat16_clv & 0x00FF);
+
+ fat_buf_mark_modified(fs_info);
+
+ if ( ofs == (fs_info->vol.bps - 1) )
+ {
+ rc = fat_buf_access(fs_info, sec + 1, FAT_OP_TYPE_READ,
+ &block0);
+ if (rc != RC_OK)
+ return rc;
+
+ *((uint8_t *)(block0->buffer)) =
+ (*((uint8_t *)(block0->buffer))) & 0xF0;
+
+ *((uint8_t *)(block0->buffer)) =
+ (*((uint8_t *)(block0->buffer))) |
+ (uint8_t )((fat16_clv & 0xFF00)>>8);
+
+ fat_buf_mark_modified(fs_info);
+ }
+ else
+ {
+ *((uint8_t *)(block0->buffer + ofs + 1)) =
+ (*((uint8_t *)(block0->buffer + ofs + 1))) & 0xF0;
+
+ *((uint8_t *)(block0->buffer + ofs+1)) =
+ (*((uint8_t *)(block0->buffer + ofs+1))) |
+ (uint8_t )((fat16_clv & 0xFF00)>>8);
+ }
+ }
+ break;
+
+ case FAT_FAT16:
+ *((uint16_t *)(block0->buffer + ofs)) =
+ (uint16_t )(CT_LE_W(in_val));
+ fat_buf_mark_modified(fs_info);
+ break;
+
+ case FAT_FAT32:
+ fat32_clv = CT_LE_L((in_val & FAT_FAT32_MASK));
+
+ *((uint32_t *)(block0->buffer + ofs)) =
+ (*((uint32_t *)(block0->buffer + ofs))) & (CT_LE_L(0xF0000000));
+
+ *((uint32_t *)(block0->buffer + ofs)) =
+ fat32_clv | (*((uint32_t *)(block0->buffer + ofs)));
+
+ fat_buf_mark_modified(fs_info);
+ break;
+
+ default:
+ set_errno_and_return_minus_one(EIO);
+ break;
+
+ }
+
+ return RC_OK;
+}
diff --git a/cpukit/libfs/src/dosfs/fat_fat_operations.h b/cpukit/libfs/src/dosfs/fat_fat_operations.h
new file mode 100644
index 0000000000..bf5cf04564
--- /dev/null
+++ b/cpukit/libfs/src/dosfs/fat_fat_operations.h
@@ -0,0 +1,58 @@
+/*
+ * fat_fat_operations.h
+ *
+ * Constants/data structures/prototypes for operations on Files Allocation
+ * Table
+ *
+ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * @(#) $Id$
+ */
+#ifndef __DOSFS_FAT_FAT_OPERATIONS_H__
+#define __DOSFS_FAT_FAT_OPERATIONS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems.h>
+#include <rtems/libio_.h>
+
+#include <rtems/bdbuf.h>
+#include "fat.h"
+
+int
+fat_get_fat_cluster(rtems_filesystem_mount_table_entry_t *mt_entry,
+ uint32_t cln,
+ uint32_t *ret_val);
+
+int
+fat_set_fat_cluster(rtems_filesystem_mount_table_entry_t *mt_entry,
+ uint32_t cln,
+ uint32_t in_val);
+
+int
+fat_scan_fat_for_free_clusters(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ uint32_t *chain,
+ uint32_t count,
+ uint32_t *cls_added,
+ uint32_t *last_cl
+);
+
+int
+fat_free_fat_clusters_chain(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ uint32_t chain
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DOSFS_FAT_FAT_OPERATIONS_H__ */
diff --git a/cpukit/libfs/src/dosfs/fat_file.c b/cpukit/libfs/src/dosfs/fat_file.c
new file mode 100644
index 0000000000..de9a064ddc
--- /dev/null
+++ b/cpukit/libfs/src/dosfs/fat_file.c
@@ -0,0 +1,987 @@
+/*
+ * fat_file.c
+ *
+ * General operations on "fat-file"
+ *
+ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
+ *
+ * @(#) $Id$
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <time.h>
+
+#include <rtems/libio_.h>
+
+#include "fat.h"
+#include "fat_fat_operations.h"
+#include "fat_file.h"
+
+static inline void
+_hash_insert(Chain_Control *hash, uint32_t key1, uint32_t key2,
+ fat_file_fd_t *el);
+
+static inline void
+_hash_delete(Chain_Control *hash, uint32_t key1, uint32_t key2,
+ fat_file_fd_t *el);
+
+static inline int
+_hash_search(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ Chain_Control *hash,
+ uint32_t key1,
+ uint32_t key2,
+ fat_file_fd_t **ret
+);
+
+static int
+fat_file_lseek(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ fat_file_fd_t *fat_fd,
+ uint32_t file_cln,
+ uint32_t *disk_cln
+);
+
+/* fat_file_open --
+ * Open fat-file. Two hash tables are accessed by key
+ * constructed from cluster num and offset of the node (i.e.
+ * files/directories are distinguished by location on the disk).
+ * First, hash table("vhash") consists of fat-file descriptors corresponded
+ * to "valid" files is accessed. Search is made by 2 fields equal to key
+ * constructed. If descriptor is found in the "vhash" - return it.
+ * Otherwise search is made in hash table("rhash") consits of fat-file
+ * descriptors corresponded to "removed-but-still-open" files with the
+ * same keys.
+ * If search failed, new fat-file descriptor is added to "vhash"
+ * with both key fields equal to constructed key. Otherwise new fat-file
+ * descriptor is added to "vhash" with first key field equal to key
+ * constructed and the second equal to an unique (unique among all values
+ * of second key fields) value.
+ *
+ * PARAMETERS:
+ * mt_entry - mount table entry
+ * cln - cluster num of the node
+ * ofs - offset of the node
+ * fat_fd - placeholder for returned fat-file descriptor
+ *
+ * RETURNS:
+ * RC_OK and pointer to opened descriptor on success, or -1 if error
+ * occured (errno set appropriately)
+ */
+int
+fat_file_open(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ uint32_t cln,
+ uint32_t ofs,
+ fat_file_fd_t **fat_fd
+ )
+{
+ int rc = RC_OK;
+ fat_fs_info_t *fs_info = mt_entry->fs_info;
+ fat_file_fd_t *lfat_fd = NULL;
+ uint32_t key = 0;
+
+ /* construct key */
+ key = fat_construct_key(mt_entry, cln, ofs);
+
+ /* access "valid" hash table */
+ rc = _hash_search(mt_entry, fs_info->vhash, key, 0, &lfat_fd);
+ if ( rc == RC_OK )
+ {
+ /* return pointer to fat_file_descriptor allocated before */
+ (*fat_fd) = lfat_fd;
+ lfat_fd->links_num++;
+ return rc;
+ }
+
+ /* access "removed-but-still-open" hash table */
+ rc = _hash_search(mt_entry, fs_info->rhash, key, key, &lfat_fd);
+
+ lfat_fd = (*fat_fd) = (fat_file_fd_t*)malloc(sizeof(fat_file_fd_t));
+ if ( lfat_fd == NULL )
+ set_errno_and_return_minus_one( ENOMEM );
+
+ lfat_fd->links_num = 1;
+ lfat_fd->flags &= ~FAT_FILE_REMOVED;
+ lfat_fd->map.last_cln = FAT_UNDEFINED_VALUE;
+
+ if ( rc != RC_OK )
+ lfat_fd->ino = key;
+ else
+ {
+ lfat_fd->ino = fat_get_unique_ino(mt_entry);
+
+ if ( lfat_fd->ino == 0 )
+ {
+ free((*fat_fd));
+ /*
+ * XXX: kernel resource is unsufficient, but not the memory,
+ * but there is no suitable errno :(
+ */
+ set_errno_and_return_minus_one( ENOMEM );
+ }
+ }
+ _hash_insert(fs_info->vhash, key, lfat_fd->ino, lfat_fd);
+
+
+ /*
+ * other fields of fat-file descriptor will be initialized on upper
+ * level
+ */
+
+ return RC_OK;
+}
+
+
+/* fat_file_reopen --
+ * Increment by 1 number of links
+ *
+ * PARAMETERS:
+ * fat_fd - fat-file descriptor
+ *
+ * RETURNS:
+ * RC_OK
+ */
+int
+fat_file_reopen(fat_file_fd_t *fat_fd)
+{
+ fat_fd->links_num++;
+ return RC_OK;
+}
+
+/* fat_file_close --
+ * Close fat-file. If count of links to fat-file
+ * descriptor is greater than 1 (i.e. somebody esle holds pointer
+ * to this descriptor) just decrement it. Otherwise
+ * do the following. If this descriptor corresponded to removed fat-file
+ * then free clusters contained fat-file data, delete descriptor from
+ * "rhash" table and free memory allocated by descriptor. If descriptor
+ * correspondes to non-removed fat-file and 'ino' field has value from
+ * unique inode numbers pool then set count of links to descriptor to zero
+ * and leave it in hash, otherwise delete descriptor from "vhash" and free
+ * memory allocated by the descriptor
+ *
+ * PARAMETERS:
+ * mt_entry - mount table entry
+ * fat_fd - fat-file descriptor
+ *
+ * RETURNS:
+ * RC_OK, or -1 if error occured (errno set appropriately)
+ */
+int
+fat_file_close(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ fat_file_fd_t *fat_fd
+ )
+{
+ int rc = RC_OK;
+ fat_fs_info_t *fs_info = mt_entry->fs_info;
+ uint32_t key = 0;
+
+ /*
+ * if links_num field of fat-file descriptor is greater than 1
+ * decrement the count of links and return
+ */
+ if (fat_fd->links_num > 1)
+ {
+ fat_fd->links_num--;
+ return rc;
+ }
+
+ key = fat_construct_key(mt_entry, fat_fd->info_cln, fat_fd->info_ofs);
+
+ if (fat_fd->flags & FAT_FILE_REMOVED)
+ {
+ rc = fat_file_truncate(mt_entry, fat_fd, 0);
+ if ( rc != RC_OK )
+ return rc;
+
+ _hash_delete(fs_info->rhash, key, fat_fd->ino, fat_fd);
+
+ if ( fat_ino_is_unique(mt_entry, fat_fd->ino) )
+ fat_free_unique_ino(mt_entry, fat_fd->ino);
+
+ free(fat_fd);
+ }
+ else
+ {
+ if (fat_ino_is_unique(mt_entry, fat_fd->ino))
+ {
+ fat_fd->links_num = 0;
+ }
+ else
+ {
+ _hash_delete(fs_info->vhash, key, fat_fd->ino, fat_fd);
+ free(fat_fd);
+ }
+ }
+ /*
+ * flush any modified "cached" buffer back to disk
+ */
+ rc = fat_buf_release(fs_info);
+
+ return rc;
+}
+
+/* fat_file_read --
+ * Read 'count' bytes from 'start' position from fat-file. This
+ * interface hides the architecture of fat-file, represents it as
+ * linear file
+ *
+ * PARAMETERS:
+ * mt_entry - mount table entry
+ * fat_fd - fat-file descriptor
+ * start - offset in fat-file (in bytes) to read from
+ * count - count of bytes to read
+ * buf - buffer provided by user
+ *
+ * RETURNS:
+ * the number of bytes read on success, or -1 if error occured (errno
+ * set appropriately)
+ */
+ssize_t
+fat_file_read(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ fat_file_fd_t *fat_fd,
+ uint32_t start,
+ uint32_t count,
+ char *buf
+ )
+{
+ int rc = RC_OK;
+ ssize_t ret = 0;
+ fat_fs_info_t *fs_info = mt_entry->fs_info;
+ uint32_t cmpltd = 0;
+ uint32_t cur_cln = 0;
+ uint32_t cl_start = 0;
+ uint32_t save_cln = 0;
+ uint32_t ofs = 0;
+ uint32_t save_ofs;
+ uint32_t sec = 0;
+ uint32_t byte = 0;
+ uint32_t c = 0;
+
+ /* it couldn't be removed - otherwise cache update will be broken */
+ if (count == 0)
+ return cmpltd;
+
+ /*
+ * >= because start is offset and computed from 0 and file_size
+ * computed from 1
+ */
+ if ( start >= fat_fd->fat_file_size )
+ return FAT_EOF;
+
+ if ((count > fat_fd->fat_file_size) ||
+ (start > fat_fd->fat_file_size - count))
+ count = fat_fd->fat_file_size - start;
+
+ if ((FAT_FD_OF_ROOT_DIR(fat_fd)) &&
+ (fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)))
+ {
+ sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->cln);
+ sec += (start >> fs_info->vol.sec_log2);
+ byte = start & (fs_info->vol.bps - 1);
+
+ ret = _fat_block_read(mt_entry, sec, byte, count, buf);
+ if ( ret < 0 )
+ return -1;
+
+ return ret;
+ }
+
+ cl_start = start >> fs_info->vol.bpc_log2;
+ save_ofs = ofs = start & (fs_info->vol.bpc - 1);
+
+ rc = fat_file_lseek(mt_entry, fat_fd, cl_start, &cur_cln);
+ if (rc != RC_OK)
+ return rc;
+
+ while (count > 0)
+ {
+ c = MIN(count, (fs_info->vol.bpc - ofs));
+
+ sec = fat_cluster_num_to_sector_num(mt_entry, cur_cln);
+ sec += (ofs >> fs_info->vol.sec_log2);
+ byte = ofs & (fs_info->vol.bps - 1);
+
+ ret = _fat_block_read(mt_entry, sec, byte, c, buf + cmpltd);
+ if ( ret < 0 )
+ return -1;
+
+ count -= c;
+ cmpltd += c;
+ save_cln = cur_cln;
+ rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);
+ if ( rc != RC_OK )
+ return rc;
+
+ ofs = 0;
+ }
+
+ /* update cache */
+ /* XXX: check this - I'm not sure :( */
+ fat_fd->map.file_cln = cl_start +
+ ((save_ofs + cmpltd - 1) >> fs_info->vol.bpc_log2);
+ fat_fd->map.disk_cln = save_cln;
+
+ return cmpltd;
+}
+
+/* fat_file_write --
+ * Write 'count' bytes of data from user supplied buffer to fat-file
+ * starting at offset 'start'. This interface hides the architecture
+ * of fat-file, represents it as linear file
+ *
+ * PARAMETERS:
+ * mt_entry - mount table entry
+ * fat_fd - fat-file descriptor
+ * start - offset(in bytes) to write from
+ * count - count
+ * buf - buffer provided by user
+ *
+ * RETURNS:
+ * number of bytes actually written to the file on success, or -1 if
+ * error occured (errno set appropriately)
+ */
+ssize_t
+fat_file_write(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ fat_file_fd_t *fat_fd,
+ uint32_t start,
+ uint32_t count,
+ const char *buf
+ )
+{
+ int rc = 0;
+ ssize_t ret = 0;
+ fat_fs_info_t *fs_info = mt_entry->fs_info;
+ uint32_t cmpltd = 0;
+ uint32_t cur_cln = 0;
+ uint32_t save_cln = 0; /* FIXME: This might be incorrect, cf. below */
+ uint32_t cl_start = 0;
+ uint32_t ofs = 0;
+ uint32_t save_ofs;
+ uint32_t sec = 0;
+ uint32_t byte = 0;
+ uint32_t c = 0;
+
+ if ( count == 0 )
+ return cmpltd;
+
+ if ( start > fat_fd->fat_file_size )
+ set_errno_and_return_minus_one( EIO );
+
+ if ((count > fat_fd->size_limit) ||
+ (start > fat_fd->size_limit - count))
+ set_errno_and_return_minus_one( EIO );
+
+ rc = fat_file_extend(mt_entry, fat_fd, start + count, &c);
+ if (rc != RC_OK)
+ return rc;
+
+ /*
+ * check whether there was enough room on device to locate
+ * file of 'start + count' bytes
+ */
+ if (c != (start + count))
+ count = c - start;
+
+ if ((FAT_FD_OF_ROOT_DIR(fat_fd)) &&
+ (fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)))
+ {
+ sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->cln);
+ sec += (start >> fs_info->vol.sec_log2);
+ byte = start & (fs_info->vol.bps - 1);
+
+ ret = _fat_block_write(mt_entry, sec, byte, count, buf);
+ if ( ret < 0 )
+ return -1;
+
+ return ret;
+ }
+
+ cl_start = start >> fs_info->vol.bpc_log2;
+ save_ofs = ofs = start & (fs_info->vol.bpc - 1);
+
+ rc = fat_file_lseek(mt_entry, fat_fd, cl_start, &cur_cln);
+ if (rc != RC_OK)
+ return rc;
+
+ while (count > 0)
+ {
+ c = MIN(count, (fs_info->vol.bpc - ofs));
+
+ sec = fat_cluster_num_to_sector_num(mt_entry, cur_cln);
+ sec += (ofs >> fs_info->vol.sec_log2);
+ byte = ofs & (fs_info->vol.bps - 1);
+
+ ret = _fat_block_write(mt_entry, sec, byte, c, buf + cmpltd);
+ if ( ret < 0 )
+ return -1;
+
+ count -= c;
+ cmpltd += c;
+ save_cln = cur_cln;
+ rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);
+ if ( rc != RC_OK )
+ return rc;
+
+ ofs = 0;
+ }
+
+ /* update cache */
+ /* XXX: check this - I'm not sure :( */
+ fat_fd->map.file_cln = cl_start +
+ ((save_ofs + cmpltd - 1) >> fs_info->vol.bpc_log2);
+ fat_fd->map.disk_cln = save_cln;
+
+ return cmpltd;
+}
+
+/* fat_file_extend --
+ * Extend fat-file. If new length less than current fat-file size -
+ * do nothing. Otherwise calculate necessary count of clusters to add,
+ * allocate it and add new clusters chain to the end of
+ * existing clusters chain.
+ *
+ * PARAMETERS:
+ * mt_entry - mount table entry
+ * fat_fd - fat-file descriptor
+ * new_length - new length
+ * a_length - placeholder for result - actual new length of file
+ *
+ * RETURNS:
+ * RC_OK and new length of file on success, or -1 if error occured (errno
+ * set appropriately)
+ */
+int
+fat_file_extend(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ fat_file_fd_t *fat_fd,
+ uint32_t new_length,
+ uint32_t *a_length
+ )
+{
+ int rc = RC_OK;
+ fat_fs_info_t *fs_info = mt_entry->fs_info;
+ uint32_t chain = 0;
+ uint32_t bytes2add = 0;
+ uint32_t cls2add = 0;
+ uint32_t old_last_cl;
+ uint32_t last_cl = 0;
+ uint32_t bytes_remain = 0;
+ uint32_t cls_added;
+
+ *a_length = new_length;
+
+ if (new_length <= fat_fd->fat_file_size)
+ return RC_OK;
+
+ if ((FAT_FD_OF_ROOT_DIR(fat_fd)) &&
+ (fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)))
+ set_errno_and_return_minus_one( ENOSPC );
+
+ bytes_remain = (fs_info->vol.bpc -
+ (fat_fd->fat_file_size & (fs_info->vol.bpc - 1))) &
+ (fs_info->vol.bpc - 1);
+
+ bytes2add = new_length - fat_fd->fat_file_size;
+
+ if (bytes2add > bytes_remain)
+ bytes2add -= bytes_remain;
+ else
+ bytes2add = 0;
+
+ /*
+ * if in last cluster allocated for the file there is enough room to
+ * handle extention (hence we don't need to add even one cluster to the
+ * file ) - return
+ */
+ if (bytes2add == 0)
+ return RC_OK;
+
+ cls2add = ((bytes2add - 1) >> fs_info->vol.bpc_log2) + 1;
+
+ rc = fat_scan_fat_for_free_clusters(mt_entry, &chain, cls2add,
+ &cls_added, &last_cl);
+
+ /* this means that low level I/O error occured */
+ if (rc != RC_OK)
+ return rc;
+
+ /* this means that no space left on device */
+ if ((cls_added == 0) && (bytes_remain == 0))
+ set_errno_and_return_minus_one(ENOSPC);
+
+ /* check wether we satisfied request for 'cls2add' clusters */
+ if (cls2add != cls_added)
+ *a_length = new_length -
+ ((cls2add - cls_added - 1) << fs_info->vol.bpc_log2) -
+ (bytes2add & (fs_info->vol.bpc - 1));
+
+ /* add new chain to the end of existed */
+ if ( fat_fd->fat_file_size == 0 )
+ {
+ fat_fd->map.disk_cln = fat_fd->cln = chain;
+ fat_fd->map.file_cln = 0;
+ }
+ else
+ {
+ if (fat_fd->map.last_cln != FAT_UNDEFINED_VALUE)
+ {
+ old_last_cl = fat_fd->map.last_cln;
+ }
+ else
+ {
+ rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM,
+ (fat_fd->fat_file_size - 1), &old_last_cl);
+ if ( rc != RC_OK )
+ {
+ fat_free_fat_clusters_chain(mt_entry, chain);
+ return rc;
+ }
+ }
+
+ rc = fat_set_fat_cluster(mt_entry, old_last_cl, chain);
+ if ( rc != RC_OK )
+ {
+ fat_free_fat_clusters_chain(mt_entry, chain);
+ return rc;
+ }
+ fat_buf_release(fs_info);
+ }
+
+ /* update number of the last cluster of the file if it changed */
+ if (cls_added != 0)
+ {
+ fat_fd->map.last_cln = last_cl;
+ if (fat_fd->fat_file_type == FAT_DIRECTORY)
+ {
+ rc = fat_init_clusters_chain(mt_entry, chain);
+ if ( rc != RC_OK )
+ {
+ fat_free_fat_clusters_chain(mt_entry, chain);
+ return rc;
+ }
+ }
+ }
+
+ return RC_OK;
+}
+
+/* fat_file_truncate --
+ * Truncate fat-file. If new length greater than current fat-file size -
+ * do nothing. Otherwise find first cluster to free and free all clusters
+ * in the chain starting from this cluster.
+ *
+ * PARAMETERS:
+ * mt_entry - mount table entry
+ * fat_fd - fat-file descriptor
+ * new_length - new length
+ *
+ * RETURNS:
+ * RC_OK on success, or -1 if error occured (errno set appropriately)
+ */
+int
+fat_file_truncate(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ fat_file_fd_t *fat_fd,
+ uint32_t new_length
+ )
+{
+ int rc = RC_OK;
+ fat_fs_info_t *fs_info = mt_entry->fs_info;
+ uint32_t cur_cln = 0;
+ uint32_t cl_start = 0;
+ uint32_t new_last_cln = FAT_UNDEFINED_VALUE;
+
+
+ if ( new_length >= fat_fd->fat_file_size )
+ return rc;
+
+ assert(fat_fd->fat_file_size);
+
+ cl_start = (new_length + fs_info->vol.bpc - 1) >> fs_info->vol.bpc_log2;
+
+ if ((cl_start << fs_info->vol.bpc_log2) >= fat_fd->fat_file_size)
+ return RC_OK;
+
+ if (cl_start != 0)
+ {
+ rc = fat_file_lseek(mt_entry, fat_fd, cl_start - 1, &new_last_cln);
+ if (rc != RC_OK)
+ return rc;
+
+ }
+
+ rc = fat_file_lseek(mt_entry, fat_fd, cl_start, &cur_cln);
+ if (rc != RC_OK)
+ return rc;
+
+ rc = fat_free_fat_clusters_chain(mt_entry, cur_cln);
+ if (rc != RC_OK)
+ return rc;
+
+ if (cl_start != 0)
+ {
+ rc = fat_set_fat_cluster(mt_entry, new_last_cln, FAT_GENFAT_EOC);
+ if ( rc != RC_OK )
+ return rc;
+ fat_fd->map.file_cln = cl_start - 1;
+ fat_fd->map.disk_cln = new_last_cln;
+ fat_fd->map.last_cln = new_last_cln;
+ }
+ return RC_OK;
+}
+
+/* fat_file_ioctl --
+ * F_CLU_NUM:
+ * make mapping between serial number of the cluster in fat-file and
+ * its real number on the volume
+ *
+ * PARAMETERS:
+ * fat_fd - fat-file descriptor
+ * mt_entry - mount table entry
+ * cmd - command
+ * ...
+ *
+ * RETURNS:
+ * RC_OK on success, or -1 if error occured and errno set appropriately
+ */
+int
+fat_file_ioctl(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ fat_file_fd_t *fat_fd,
+ int cmd,
+ ...)
+{
+ int rc = RC_OK;
+ fat_fs_info_t *fs_info = mt_entry->fs_info;
+ uint32_t cur_cln = 0;
+ uint32_t cl_start = 0;
+ uint32_t pos = 0;
+ uint32_t *ret;
+ va_list ap;
+
+ va_start(ap, cmd);
+
+ switch (cmd)
+ {
+ case F_CLU_NUM:
+ pos = va_arg(ap, uint32_t );
+ ret = va_arg(ap, uint32_t *);
+
+ /* sanity check */
+ if ( pos >= fat_fd->fat_file_size )
+ set_errno_and_return_minus_one( EIO );
+
+ if ((FAT_FD_OF_ROOT_DIR(fat_fd)) &&
+ (fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)))
+ {
+ /* cluster 0 (zero) reserved for root dir */
+ *ret = 0;
+ return RC_OK;
+ }
+
+ cl_start = pos >> fs_info->vol.bpc_log2;
+
+ rc = fat_file_lseek(mt_entry, fat_fd, cl_start, &cur_cln);
+ if ( rc != RC_OK )
+ return rc;
+
+ *ret = cur_cln;
+ break;
+
+ default:
+ errno = EINVAL;
+ rc = -1;
+ break;
+ }
+ return rc;
+}
+
+/* fat_file_mark_removed --
+ * Remove the fat-file descriptor from "valid" hash table, insert it
+ * into "removed-but-still-open" hash table and set up "removed" bit.
+ *
+ * PARAMETERS:
+ * fat_fd - fat-file descriptor
+ * mt_entry - mount table entry
+ *
+ * RETURNS:
+ * None
+ */
+void
+fat_file_mark_removed(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ fat_file_fd_t *fat_fd
+ )
+{
+ fat_fs_info_t *fs_info = mt_entry->fs_info;
+ uint32_t key = 0;
+
+ key = fat_construct_key(mt_entry, fat_fd->info_cln, fat_fd->info_ofs);
+
+ _hash_delete(fs_info->vhash, key, fat_fd->ino, fat_fd);
+
+ _hash_insert(fs_info->rhash, key, fat_fd->ino, fat_fd);
+
+ fat_fd->flags |= FAT_FILE_REMOVED;
+}
+
+/* fat_file_datasync --
+ * Synchronize fat-file - flush all buffered data to the media.
+ *
+ * PARAMETERS:
+ * mt_entry - mount table entry
+ * fat_fd - fat-file descriptor
+ *
+ * RETURNS:
+ * RC_OK on success, or -1 if error occured and errno set appropriately
+ */
+int
+fat_file_datasync(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ fat_file_fd_t *fat_fd
+ )
+{
+ int rc = RC_OK;
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ fat_fs_info_t *fs_info = mt_entry->fs_info;
+ uint32_t cur_cln = fat_fd->cln;
+ bdbuf_buffer *block = NULL;
+ uint32_t sec = 0;
+ uint32_t i = 0;
+
+ if (fat_fd->fat_file_size == 0)
+ return RC_OK;
+
+ /*
+ * we can use only one bdbuf :( and we also know that cache is useless
+ * for sync operation, so don't use it
+ */
+ rc = fat_buf_release(fs_info);
+ if (rc != RC_OK)
+ return rc;
+
+ /* for each cluster of the file ... */
+ while ((cur_cln & fs_info->vol.mask) < fs_info->vol.eoc_val)
+ {
+ sec = fat_cluster_num_to_sector_num(mt_entry, cur_cln);
+ /* for each sector in cluster ... */
+ for ( i = 0; i < fs_info->vol.spc; i++ )
+ {
+ /* ... sync it */
+ sc = rtems_bdbuf_read(fs_info->vol.dev, (sec + i), &block);
+ if (sc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one( EIO );
+
+ sc = rtems_bdbuf_sync(block);
+ if ( sc != RTEMS_SUCCESSFUL )
+ set_errno_and_return_minus_one( EIO );
+ }
+
+ rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);
+ if ( rc != RC_OK )
+ return rc;
+ }
+ return rc;
+}
+
+/* fat_file_size --
+ * Calculate fat-file size - fat-file is nothing that clusters chain, so
+ * go through all clusters in the chain and count it. Only
+ * special case is root directory for FAT12/16 volumes.
+ * This function is used only for directories which are fat-files with
+ * non-zero length, hence 'fat_fd->cln' always contains valid data.
+ * Calculated size is stored in 'fat_file_size' field of fat-file
+ * descriptor.
+ *
+ * PARAMETERS:
+ * mt_entry - mount table entry
+ * fat_fd - fat-file descriptor
+ *
+ * RETURNS:
+ * RC_OK on success, or -1 if error occured (errno set appropriately)
+ */
+int
+fat_file_size(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ fat_file_fd_t *fat_fd
+ )
+{
+ int rc = RC_OK;
+ fat_fs_info_t *fs_info = mt_entry->fs_info;
+ uint32_t cur_cln = fat_fd->cln;
+ uint32_t save_cln = 0;
+
+ /* Have we requested root dir size for FAT12/16? */
+ if ((FAT_FD_OF_ROOT_DIR(fat_fd)) &&
+ (fs_info->vol.type & (FAT_FAT12 | FAT_FAT16)))
+ {
+ fat_fd->fat_file_size = fs_info->vol.rdir_size;
+ return rc;
+ }
+
+ fat_fd->fat_file_size = 0;
+
+ while ((cur_cln & fs_info->vol.mask) < fs_info->vol.eoc_val)
+ {
+ save_cln = cur_cln;
+ rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);
+ if ( rc != RC_OK )
+ return rc;
+
+ fat_fd->fat_file_size += fs_info->vol.bpc;
+ }
+ fat_fd->map.last_cln = save_cln;
+ return rc;
+}
+
+/* hash support routines */
+
+/* _hash_insert --
+ * Insert elemnt into hash based on key 'key1'
+ *
+ * PARAMETERS:
+ * hash - hash element will be inserted into
+ * key1 - key on which insertion is based on
+ * key2 - not used during insertion
+ * el - element to insert
+ *
+ * RETURNS:
+ * None
+ */
+static inline void
+_hash_insert(Chain_Control *hash, uint32_t key1, uint32_t key2,
+ fat_file_fd_t *el)
+{
+ _Chain_Append((hash) + ((key1) % FAT_HASH_MODULE), &(el)->link);
+}
+
+
+/* _hash_delete --
+ * Remove element from hash
+ *
+ * PARAMETERS:
+ * hash - hash element will be removed from
+ * key1 - not used
+ * key2 - not used
+ * el - element to delete
+ *
+ * RETURNS:
+ * None
+ */
+static inline void
+_hash_delete(Chain_Control *hash, uint32_t key1, uint32_t key2,
+ fat_file_fd_t *el)
+{
+ _Chain_Extract(&(el)->link);
+}
+
+/* _hash_search --
+ * Search element in hash. If both keys match pointer to found element
+ * is returned
+ *
+ * PARAMETERS:
+ * mt_entry - mount table entry
+ * hash - hash element will be removed from
+ * key1 - search key
+ * key2 - search key
+ * ret - placeholder for result
+ *
+ * RETURNS:
+ * 0 and pointer to found element on success, -1 otherwise
+ */
+static inline int
+_hash_search(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ Chain_Control *hash,
+ uint32_t key1,
+ uint32_t key2,
+ fat_file_fd_t **ret
+ )
+{
+ uint32_t mod = (key1) % FAT_HASH_MODULE;
+ Chain_Node *the_node = ((Chain_Control *)((hash) + mod))->first;
+
+ for ( ; !_Chain_Is_tail((hash) + mod, the_node) ; )
+ {
+ fat_file_fd_t *ffd = (fat_file_fd_t *)the_node;
+ uint32_t ck =
+ fat_construct_key(mt_entry, ffd->info_cln, ffd->info_ofs);
+
+ if ( (key1) == ck)
+ {
+ if ( ((key2) == 0) || ((key2) == ffd->ino) )
+ {
+ *ret = (void *)the_node;
+ return 0;
+ }
+ }
+ the_node = the_node->next;
+ }
+ return -1;
+}
+
+static int
+fat_file_lseek(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ fat_file_fd_t *fat_fd,
+ uint32_t file_cln,
+ uint32_t *disk_cln
+ )
+{
+ int rc = RC_OK;
+/*
+ assert(fat_fd->fat_file_size);
+ */
+ if (file_cln == fat_fd->map.file_cln)
+ *disk_cln = fat_fd->map.disk_cln;
+ else
+ {
+ uint32_t cur_cln;
+ uint32_t count;
+ uint32_t i;
+
+ if (file_cln > fat_fd->map.file_cln)
+ {
+ cur_cln = fat_fd->map.disk_cln;
+ count = file_cln - fat_fd->map.file_cln;
+ }
+ else
+ {
+ cur_cln = fat_fd->cln;
+ count = file_cln;
+ }
+
+ /* skip over the clusters */
+ for (i = 0; i < count; i++)
+ {
+ rc = fat_get_fat_cluster(mt_entry, cur_cln, &cur_cln);
+ if ( rc != RC_OK )
+ return rc;
+ }
+
+ /* update cache */
+ fat_fd->map.file_cln = file_cln;
+ fat_fd->map.disk_cln = cur_cln;
+
+ *disk_cln = cur_cln;
+ }
+ return RC_OK;
+}
diff --git a/cpukit/libfs/src/dosfs/fat_file.h b/cpukit/libfs/src/dosfs/fat_file.h
new file mode 100644
index 0000000000..fcde2e620e
--- /dev/null
+++ b/cpukit/libfs/src/dosfs/fat_file.h
@@ -0,0 +1,195 @@
+/*
+ * fat_file.h
+ *
+ * Constants/data structures/prototypes for operations on "fat-file"
+ *
+ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * @(#) $Id$
+ */
+#ifndef __DOSFS_FAT_FILE_H__
+#define __DOSFS_FAT_FILE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems.h>
+#include <rtems/libio_.h>
+
+#include <time.h>
+
+/* "fat-file" representation
+ *
+ * the idea is: fat-file is nothing but a cluster chain, any open fat-file is
+ * represented in system by fat-file descriptor and has well-known
+ * file interface:
+ *
+ * fat_file_open()
+ * fat_file_close()
+ * fat_file_read()
+ * fat_file_write()
+ *
+ * Such interface hides the architecture of fat-file and represents it like
+ * linear file
+ */
+
+typedef rtems_filesystem_node_types_t fat_file_type_t;
+
+#define FAT_DIRECTORY RTEMS_FILESYSTEM_DIRECTORY
+#define FAT_FILE RTEMS_FILESYSTEM_MEMORY_FILE
+
+typedef struct fat_file_map_s
+{
+ uint32_t file_cln;
+ uint32_t disk_cln;
+ uint32_t last_cln;
+} fat_file_map_t;
+/*
+ * descriptor of a fat-file
+ *
+ * To each particular clusters chain
+ */
+typedef struct fat_file_fd_s
+{
+ Chain_Node link; /*
+ * fat-file descriptors organized into hash;
+ * collision lists are handled via link
+ * field
+ */
+ uint32_t links_num; /*
+ * the number of fat_file_open call on
+ * this fat-file
+ */
+ uint32_t ino; /* inode, file serial number :)))) */
+ fat_file_type_t fat_file_type;
+ uint32_t size_limit;
+ uint32_t fat_file_size; /* length */
+ uint32_t info_cln;
+ uint32_t cln;
+ uint16_t info_ofs;
+ unsigned char first_char;
+ uint8_t flags;
+ fat_file_map_t map;
+ time_t mtime;
+
+} fat_file_fd_t;
+
+
+#define FAT_FILE_REMOVED 0x01
+
+#define FAT_FILE_IS_REMOVED(p)\
+ (((p)->flags & FAT_FILE_REMOVED) ? 1 : 0)
+
+/* ioctl macros */
+#define F_CLU_NUM 0x01
+
+/*
+ * Each file and directory on a MSDOS volume is unique identified by it
+ * location, i.e. location of it 32 Bytes Directory Entry Structure. We can
+ * distinguish them by cluster number it locates on and offset inside this
+ * cluster. But root directory on any volumes (FAT12/16/32) has no 32 Bytes
+ * Directory Entry Structure corresponded to it. So we assume 32 Bytes
+ * Directory Entry Structure of root directory locates at cluster 1 (invalid
+ * cluaster number) and offset 0
+ */
+#define FAT_ROOTDIR_CLUSTER_NUM 0x01
+
+#define FAT_FD_OF_ROOT_DIR(fat_fd) \
+ ((fat_fd->info_cln == FAT_ROOTDIR_CLUSTER_NUM ) && \
+ (fat_fd->info_ofs == 0))
+
+#define FAT_EOF 0x00
+
+/* fat_construct_key --
+ * Construct key for hash access: convert (cluster num, offset) to
+ * (sector512 num, new offset) and than construct key as
+ * key = (sector512 num) << 4 | (new offset)
+ *
+ * PARAMETERS:
+ * cl - cluster number
+ * ofs - offset inside cluster 'cl'
+ * mt_entry - mount table entry
+ *
+ * RETURNS:
+ * constructed key
+ */
+static inline uint32_t
+fat_construct_key(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ uint32_t cl,
+ uint32_t ofs)
+{
+ return ( ((fat_cluster_num_to_sector512_num(mt_entry, cl) +
+ (ofs >> FAT_SECTOR512_BITS)) << 4) +
+ ((ofs >> 5) & (FAT_DIRENTRIES_PER_SEC512 - 1)) );
+}
+
+/* Prototypes for "fat-file" operations */
+int
+fat_file_open(rtems_filesystem_mount_table_entry_t *mt_entry,
+ uint32_t cln,
+ uint32_t ofs,
+ fat_file_fd_t **fat_fd);
+
+int
+fat_file_reopen(fat_file_fd_t *fat_fd);
+
+int
+fat_file_close(rtems_filesystem_mount_table_entry_t *mt_entry,
+ fat_file_fd_t *fat_fd);
+
+ssize_t
+fat_file_read(rtems_filesystem_mount_table_entry_t *mt_entry,
+ fat_file_fd_t *fat_fd,
+ uint32_t start,
+ uint32_t count,
+ char *buf);
+
+ssize_t
+fat_file_write(rtems_filesystem_mount_table_entry_t *mt_entry,
+ fat_file_fd_t *fat_fd,
+ uint32_t start,
+ uint32_t count,
+ const char *buf);
+
+int
+fat_file_extend(rtems_filesystem_mount_table_entry_t *mt_entry,
+ fat_file_fd_t *fat_fd,
+ uint32_t new_length,
+ uint32_t *a_length);
+
+int
+fat_file_truncate(rtems_filesystem_mount_table_entry_t *mt_entry,
+ fat_file_fd_t *fat_fd,
+ uint32_t new_length);
+
+int
+fat_file_datasync(rtems_filesystem_mount_table_entry_t *mt_entry,
+ fat_file_fd_t *fat_fd);
+
+
+int
+fat_file_ioctl(rtems_filesystem_mount_table_entry_t *mt_entry,
+ fat_file_fd_t *fat_fd,
+ int cmd,
+ ...);
+
+int
+fat_file_size(rtems_filesystem_mount_table_entry_t *mt_entry,
+ fat_file_fd_t *fat_fd);
+
+void
+fat_file_mark_removed(rtems_filesystem_mount_table_entry_t *mt_entry,
+ fat_file_fd_t *fat_fd);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DOSFS_FAT_FILE_H__ */
diff --git a/cpukit/libfs/src/dosfs/msdos.h b/cpukit/libfs/src/dosfs/msdos.h
new file mode 100644
index 0000000000..3c6caef224
--- /dev/null
+++ b/cpukit/libfs/src/dosfs/msdos.h
@@ -0,0 +1,436 @@
+/*
+ * msdos.h
+ *
+ * The MSDOS filesystem constants/data structures/prototypes
+ *
+ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * @(#) $Id$
+ */
+#ifndef __DOSFS_MSDOS_H__
+#define __DOSFS_MSDOS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems.h>
+#include <rtems/libio_.h>
+
+#include "fat.h"
+#include "fat_file.h"
+
+#ifndef RC_OK
+#define RC_OK 0x00000000
+#endif
+
+#define MSDOS_NAME_NOT_FOUND_ERR 0xDD000001
+
+/*
+ * This structure identifies the instance of the filesystem on the MSDOS
+ * level.
+ */
+typedef struct msdos_fs_info_s
+{
+ fat_fs_info_t fat; /*
+ * volume
+ * description
+ */
+ rtems_filesystem_file_handlers_r *directory_handlers; /*
+ * a set of routines
+ * that handles the
+ * nodes of directory
+ * type
+ */
+ rtems_filesystem_file_handlers_r *file_handlers; /*
+ * a set of routines
+ * that handles the
+ * nodes of file
+ * type
+ */
+ rtems_id vol_sema; /*
+ * semaphore
+ * associated with
+ * the volume
+ */
+ uint8_t *cl_buf; /*
+ * just placeholder
+ * for anything
+ */
+} msdos_fs_info_t;
+
+/* a set of routines that handle the nodes which are directories */
+extern rtems_filesystem_file_handlers_r msdos_dir_handlers;
+
+/* a set of routines that handle the nodes which are files */
+extern rtems_filesystem_file_handlers_r msdos_file_handlers;
+
+/* Volume semaphore timeout value. This value can be changed to a number
+ * of ticks to help debugging or if you need such a */
+#define MSDOS_VOLUME_SEMAPHORE_TIMEOUT RTEMS_NO_TIMEOUT
+
+/* Node types */
+#define MSDOS_DIRECTORY RTEMS_FILESYSTEM_DIRECTORY
+#define MSDOS_REGULAR_FILE RTEMS_FILESYSTEM_MEMORY_FILE
+#define MSDOS_HARD_LINK RTEMS_FILESYSTEM_HARD_LINK /* pseudo type */
+
+typedef rtems_filesystem_node_types_t msdos_node_type_t;
+
+/*
+ * Macros for fetching fields from 32 bytes long FAT Directory Entry
+ * Structure
+ */
+#define MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE 32 /* 32 bytes */
+
+#define MSDOS_DIR_NAME(x) (uint8_t *)((x) + 0)
+#define MSDOS_DIR_ATTR(x) (uint8_t *)((x) + 11)
+#define MSDOS_DIR_NT_RES(x) (uint8_t *)((x) + 12)
+#define MSDOS_DIR_CRT_TIME_TENTH(x) (uint8_t *)((x) + 13)
+#define MSDOS_DIR_CRT_TIME(x) (uint16_t *)((x) + 14)
+#define MSDOS_DIR_CRT_DATE(x) (uint16_t *)((x) + 16)
+#define MSDOS_DIR_LAST_ACCESS_DATE(x) (uint16_t *)((x) + 18)
+#define MSDOS_DIR_FIRST_CLUSTER_HI(x) (uint16_t *)((x) + 20)
+#define MSDOS_DIR_WRITE_TIME(x) (uint16_t *)((x) + 22)
+#define MSDOS_DIR_WRITE_DATE(x) (uint16_t *)((x) + 24)
+#define MSDOS_DIR_FIRST_CLUSTER_LOW(x) (uint16_t *)((x) + 26)
+#define MSDOS_DIR_FILE_SIZE(x) (uint32_t *)((x) + 28)
+
+#define MSDOS_EXTRACT_CLUSTER_NUM(p) \
+ (uint32_t )( (CF_LE_W(*MSDOS_DIR_FIRST_CLUSTER_LOW(p))) | \
+ ((uint32_t )(CF_LE_W((*MSDOS_DIR_FIRST_CLUSTER_HI(p))))<<16) )
+
+/*
+ * Fields offset in 32 bytes long FAT Directory Entry
+ * Structure
+ */
+#define MSDOS_FILE_SIZE_OFFSET 28
+#define MSDOS_FILE_NAME_OFFSET 0
+#define MSDOS_FIRST_CLUSTER_HI_OFFSET 20
+#define MSDOS_FIRST_CLUSTER_LOW_OFFSET 26
+#define MSDOS_FILE_WDATE_OFFSET 24
+#define MSDOS_FILE_WTIME_OFFSET 22
+
+/*
+ * Possible values of DIR_Attr field of 32 bytes long FAT Directory Entry
+ * Structure
+ */
+#define MSDOS_ATTR_READ_ONLY 0x01
+#define MSDOS_ATTR_HIDDEN 0x02
+#define MSDOS_ATTR_SYSTEM 0x04
+#define MSDOS_ATTR_VOLUME_ID 0x08
+#define MSDOS_ATTR_DIRECTORY 0x10
+#define MSDOS_ATTR_ARCHIVE 0x20
+
+#define MSDOS_DT_2SECONDS_MASK 0x1F /* seconds divided by 2 */
+#define MSDOS_DT_2SECONDS_SHIFT 0
+#define MSDOS_DT_MINUTES_MASK 0x7E0 /* minutes */
+#define MSDOS_DT_MINUTES_SHIFT 5
+#define MSDOS_DT_HOURS_MASK 0xF800 /* hours */
+#define MSDOS_DT_HOURS_SHIFT 11
+
+#define MSDOS_DD_DAY_MASK 0x1F /* day of month */
+#define MSDOS_DD_DAY_SHIFT 0
+#define MSDOS_DD_MONTH_MASK 0x1E0 /* month */
+#define MSDOS_DD_MONTH_SHIFT 5
+#define MSDOS_DD_YEAR_MASK 0xFE00 /* year - 1980 */
+#define MSDOS_DD_YEAR_SHIFT 9
+
+
+/*
+ * Possible values of DIR_Name[0] field of 32 bytes long FAT Directory Entry
+ * Structure
+ */
+#define MSDOS_THIS_DIR_ENTRY_EMPTY 0xE5
+#define MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY 0x00
+
+
+/*
+ * Macros for names parsing and formatting
+ */
+#define msdos_is_valid_name_char(_ch) (1)
+#define msdos_is_separator(_ch) rtems_filesystem_is_separator(_ch)
+
+#define MSDOS_SHORT_BASE_LEN 8 /* 8 characters */
+#define MSDOS_SHORT_EXT_LEN 3 /* 3 characters */
+#define MSDOS_SHORT_NAME_LEN (MSDOS_SHORT_BASE_LEN+\
+ MSDOS_SHORT_EXT_LEN) /* 11 chars */
+#define MSDOS_NAME_MAX MSDOS_SHORT_NAME_LEN
+#define MSDOS_NAME_MAX_WITH_DOT (MSDOS_NAME_MAX + 1)
+
+#define MSDOS_DOT_NAME ". " /* ".", padded to MSDOS_NAME chars */
+#define MSDOS_DOTDOT_NAME ".. " /* "..", padded to MSDOS_NAME chars */
+
+typedef enum msdos_token_types_e
+{
+ MSDOS_NO_MORE_PATH,
+ MSDOS_CURRENT_DIR,
+ MSDOS_UP_DIR,
+ MSDOS_NAME,
+ MSDOS_INVALID_TOKEN
+} msdos_token_types_t;
+
+/* Others macros */
+#define MSDOS_RES_NT_VALUE 0x00
+#define MSDOS_INIT_DIR_SIZE 0x00
+
+/* "dot" entry offset in a directory */
+#define MSDOS_DOT_DIR_ENTRY_OFFSET 0x00 /* first entry in directory */
+
+/* "dotdot" entry offset in a directory */
+#define MSDOS_DOTDOT_DIR_ENTRY_OFFSET 0x20 /* second entry in directory */
+
+/* 'p' should be char* */
+#define DOT_NODE_P(p) ((char *)(p))
+#define DOTDOT_NODE_P(p) ((char *)((p) + MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE))
+
+/* Size limits for files and directories */
+#define MSDOS_MAX_DIR_LENGHT 0x200000 /* 2,097,152 bytes */
+#define MSDOS_MAX_FILE_SIZE 0xFFFFFFFF /* 4 Gb */
+
+/*
+ * The number of 32 bytes long FAT Directory Entry
+ * Structures per 512 bytes sector
+ */
+#define MSDOS_DPS512_NUM 16
+
+/* Prototypes */
+int
+msdos_initialize(rtems_filesystem_mount_table_entry_t *temp_mt_entry);
+
+int
+msdos_shut_down(rtems_filesystem_mount_table_entry_t *temp_mt_entry);
+
+int
+msdos_eval_path(const char *pathname, /* IN */
+ int flags, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */);
+
+int
+msdos_eval4make(const char *path, /* IN */
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ const char **name /* OUT */);
+
+int
+msdos_unlink(rtems_filesystem_location_info_t *pathloc /* IN */);
+
+int
+msdos_free_node_info(rtems_filesystem_location_info_t *pathloc /* IN */);
+
+rtems_filesystem_node_types_t
+msdos_node_type(rtems_filesystem_location_info_t *pathloc);
+
+int
+msdos_mknod(const char *path, /* IN */
+ mode_t mode, /* IN */
+ dev_t dev, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */);
+
+int
+msdos_utime(rtems_filesystem_location_info_t *pathloc, /* IN */
+ time_t actime, /* IN */
+ time_t modtime /* IN */);
+
+int
+msdos_initialize_support(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry,
+ rtems_filesystem_operations_table *op_table,
+ rtems_filesystem_file_handlers_r *file_handlers,
+ rtems_filesystem_file_handlers_r *directory_handlers
+);
+
+int
+msdos_file_open(
+ rtems_libio_t *iop, /* IN */
+ const char *pathname, /* IN */
+ uint32_t flag, /* IN */
+ uint32_t mode /* IN */
+);
+
+int
+msdos_file_close(rtems_libio_t *iop /* IN */);
+
+ssize_t
+msdos_file_read(
+ rtems_libio_t *iop, /* IN */
+ void *buffer, /* IN */
+ uint32_t count /* IN */
+);
+
+ssize_t
+msdos_file_write(
+ rtems_libio_t *iop, /* IN */
+ const void *buffer, /* IN */
+ uint32_t count /* IN */
+);
+
+int
+msdos_file_lseek(
+ rtems_libio_t *iop, /* IN */
+ off_t offset, /* IN */
+ int whence /* IN */
+);
+
+int
+msdos_file_stat(rtems_filesystem_location_info_t *loc, /* IN */
+ struct stat *buf /* OUT */);
+
+int
+msdos_file_ftruncate(
+ rtems_libio_t *iop, /* IN */
+ off_t length /* IN */
+);
+
+int
+msdos_file_sync(rtems_libio_t *iop);
+
+int
+msdos_file_datasync(rtems_libio_t *iop);
+
+int
+msdos_file_ioctl(
+ rtems_libio_t *iop, /* IN */
+ uint32_t command, /* IN */
+ void *buffer /* IN */
+);
+
+int
+msdos_file_rmnod(rtems_filesystem_location_info_t *pathloc /* IN */);
+
+int
+msdos_file_link(rtems_filesystem_location_info_t *to_loc,
+ rtems_filesystem_location_info_t *pa_loc,
+ const char *token);
+
+int
+msdos_dir_open(
+ rtems_libio_t *iop, /* IN */
+ const char *pathname, /* IN */
+ uint32_t flag, /* IN */
+ uint32_t mode /* IN */
+);
+
+int
+msdos_dir_close(rtems_libio_t *iop /* IN */);
+
+ssize_t
+msdos_dir_read(
+ rtems_libio_t *iop, /* IN */
+ void *buffer, /* IN */
+ uint32_t count /* IN */
+);
+
+int
+msdos_dir_lseek(
+ rtems_libio_t *iop, /* IN */
+ off_t offset, /* IN */
+ int whence /* IN */
+);
+
+int
+msdos_dir_rmnod(rtems_filesystem_location_info_t *pathloc /* IN */);
+
+int
+msdos_dir_sync(rtems_libio_t *iop);
+
+int
+msdos_dir_stat(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ struct stat *buf /* OUT */
+);
+
+int
+msdos_creat_node(rtems_filesystem_location_info_t *parent_loc,
+ msdos_node_type_t type,
+ char *name,
+ mode_t mode,
+ const fat_file_fd_t *link_fd);
+
+/* Misc prototypes */
+msdos_token_types_t msdos_get_token(const char *path,
+ char *token,
+ int *token_len);
+
+int
+msdos_find_name(rtems_filesystem_location_info_t *parent_loc,
+ char *name);
+
+int
+msdos_get_name_node(rtems_filesystem_location_info_t *parent_loc,
+ char *name,
+ fat_auxiliary_t *paux,
+ char *name_dir_entry);
+
+int
+msdos_dir_info_remove(rtems_filesystem_location_info_t *pathloc);
+
+int
+msdos_filename_unix2dos(char *un, int unlen, char *dn);
+
+void
+msdos_date_unix2dos(unsigned int tsp, unsigned short *ddp,
+ unsigned short *dtp);
+
+unsigned int
+msdos_date_dos2unix(unsigned int dd, unsigned int dt);
+
+int
+msdos_set_first_cluster_num(rtems_filesystem_mount_table_entry_t *mt_entry,
+ fat_file_fd_t *fat_fd);
+
+int
+msdos_set_file_size(rtems_filesystem_mount_table_entry_t *mt_entry,
+ fat_file_fd_t *fat_fd);
+
+int
+msdos_set_first_char4file_name(rtems_filesystem_mount_table_entry_t *mt_entry,
+ uint32_t cl,
+ uint32_t ofs,
+ unsigned char first_char);
+
+int
+msdos_set_dir_wrt_time_and_date(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ fat_file_fd_t *fat_fd
+);
+
+
+int
+msdos_dir_is_empty(rtems_filesystem_mount_table_entry_t *mt_entry,
+ fat_file_fd_t *fat_fd,
+ rtems_boolean *ret_val);
+
+int
+msdos_find_name_in_fat_file(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ fat_file_fd_t *fat_fd,
+ char *name,
+ fat_auxiliary_t *paux,
+ char *name_dir_entry);
+
+int
+msdos_find_node_by_cluster_num_in_fat_file(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ fat_file_fd_t *fat_fd,
+ uint32_t cl4find,
+ fat_auxiliary_t *paux,
+ char *dir_entry
+);
+
+int
+msdos_get_dotdot_dir_info_cluster_num_and_offset(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ uint32_t cln,
+ fat_auxiliary_t *paux,
+ char *dir_entry
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DOSFS_MSDOS_H__ */
diff --git a/cpukit/libfs/src/dosfs/msdos_conv.c b/cpukit/libfs/src/dosfs/msdos_conv.c
new file mode 100644
index 0000000000..732558b146
--- /dev/null
+++ b/cpukit/libfs/src/dosfs/msdos_conv.c
@@ -0,0 +1,268 @@
+/*
+ * Adaptation of NetBSD code for RTEMS by Victor V. Vengerov <vvv@oktet.ru>
+ */
+/* $NetBSD: msdosfs_conv.c,v 1.10 1994/12/27 18:36:24 mycroft Exp $ */
+/*
+ * Written by Paul Popelka (paulp@uts.amdahl.com)
+ *
+ * You can do anything you want with this software, just don't say you wrote
+ * it, and don't remove this notice.
+ *
+ * This software is provided "as is".
+ *
+ * The author supplies this software to be publicly redistributed on the
+ * understanding that the author is not responsible for the correct
+ * functioning of this software in any circumstances and is not liable for
+ * any damages caused by this software.
+ *
+ * October 1992
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include "msdos.h"
+/*
+ * Days in each month in a regular year.
+ */
+static u_short regyear[] = {
+ 31, 28, 31, 30, 31, 30,
+ 31, 31, 30, 31, 30, 31
+};
+
+/*
+ * Days in each month in a leap year.
+ */
+static u_short leapyear[] = {
+ 31, 29, 31, 30, 31, 30,
+ 31, 31, 30, 31, 30, 31
+};
+
+/*
+ * Variables used to remember parts of the last time conversion. Maybe we
+ * can avoid a full conversion.
+ */
+static u_long lasttime;
+static u_long lastday;
+static u_short lastddate;
+static u_short lastdtime;
+
+/*
+ * Convert the unix version of time to dos's idea of time to be used in
+ * file timestamps. The passed in unix time is assumed to be in GMT.
+ */
+void
+msdos_date_unix2dos(unsigned int t, unsigned short *ddp,
+ unsigned short *dtp)
+{
+ u_long days;
+ u_long inc;
+ u_long year;
+ u_long month;
+ u_short *months;
+
+ /*
+ * If the time from the last conversion is the same as now, then
+ * skip the computations and use the saved result.
+ */
+ if (lasttime != t) {
+ lasttime = t;
+ lastdtime = (((t % 60) >> 1) << MSDOS_DT_2SECONDS_SHIFT)
+ + (((t / 60) % 60) << MSDOS_DT_MINUTES_SHIFT)
+ + (((t / 3600) % 24) << MSDOS_DT_HOURS_SHIFT);
+
+ /*
+ * If the number of days since 1970 is the same as the last
+ * time we did the computation then skip all this leap year
+ * and month stuff.
+ */
+ days = t / (24 * 60 * 60);
+ if (days != lastday) {
+ lastday = days;
+ for (year = 1970;; year++) {
+ inc = year & 0x03 ? 365 : 366;
+ if (days < inc)
+ break;
+ days -= inc;
+ }
+ months = year & 0x03 ? regyear : leapyear;
+ for (month = 0; month < 12; month++) {
+ if (days < months[month])
+ break;
+ days -= months[month];
+ }
+ lastddate = ((days + 1) << MSDOS_DD_DAY_SHIFT)
+ + ((month + 1) << MSDOS_DD_MONTH_SHIFT);
+ /*
+ * Remember dos's idea of time is relative to 1980.
+ * unix's is relative to 1970. If somehow we get a
+ * time before 1980 then don't give totally crazy
+ * results.
+ */
+ if (year > 1980)
+ lastddate += (year - 1980) <<
+ MSDOS_DD_YEAR_SHIFT;
+ }
+ }
+ *dtp = lastdtime;
+ *ddp = lastddate;
+}
+
+/*
+ * The number of seconds between Jan 1, 1970 and Jan 1, 1980. In that
+ * interval there were 8 regular years and 2 leap years.
+ */
+#define SECONDSTO1980 (((8 * 365) + (2 * 366)) * (24 * 60 * 60))
+
+static u_short lastdosdate;
+static u_long lastseconds;
+
+/*
+ * Convert from dos' idea of time to unix'. This will probably only be
+ * called from the stat(), and fstat() system calls and so probably need
+ * not be too efficient.
+ */
+unsigned int
+msdos_date_dos2unix(unsigned int dd, unsigned int dt)
+{
+ u_long seconds;
+ u_long m, month;
+ u_long y, year;
+ u_long days;
+ u_short *months;
+
+ seconds = ((dt & MSDOS_DT_2SECONDS_MASK) >> MSDOS_DT_2SECONDS_SHIFT)
+ + ((dt & MSDOS_DT_MINUTES_MASK) >> MSDOS_DT_MINUTES_SHIFT) * 60
+ + ((dt & MSDOS_DT_HOURS_MASK) >> MSDOS_DT_HOURS_SHIFT) * 3600;
+ /*
+ * If the year, month, and day from the last conversion are the
+ * same then use the saved value.
+ */
+ if (lastdosdate != dd) {
+ lastdosdate = dd;
+ days = 0;
+ year = (dd & MSDOS_DD_YEAR_MASK) >> MSDOS_DD_YEAR_SHIFT;
+ for (y = 0; y < year; y++)
+ days += y & 0x03 ? 365 : 366;
+ months = year & 0x03 ? regyear : leapyear;
+ /*
+ * Prevent going from 0 to 0xffffffff in the following
+ * loop.
+ */
+ month = (dd & MSDOS_DD_MONTH_MASK) >> MSDOS_DD_MONTH_SHIFT;
+ if (month == 0) {
+ month = 1;
+ }
+ for (m = 0; m < month - 1; m++)
+ days += months[m];
+ days += ((dd & MSDOS_DD_DAY_MASK) >> MSDOS_DD_DAY_SHIFT) - 1;
+ lastseconds = (days * 24 * 60 * 60) + SECONDSTO1980;
+ }
+ return seconds + lastseconds;
+}
+
+static const u_char msdos_map[] = {
+/* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 08 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 18 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 20 */ 0x00, 0x21, 0x00, 0x23, 0x24, 0x25, 0x26, 0x27, /* !"#$%&' */
+/* 28 */ 0x28, 0x29, 0x00, 0x00, 0x00, 0x2D, 0x2E, 0x00, /* ()*+,-./ */
+/* 30 */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 01234567 */
+/* 38 */ 0x38, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 89:;<=>? */
+/* 40 */ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* @ABCDEFG */
+/* 48 */ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, /* HIJKLMNO */
+/* 50 */ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* PQRSTUVW */
+/* 58 */ 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x00, 0x5E, 0x5F, /* XYZ[\]^_ */
+/* 60 */ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* `abcdefg */
+/* 68 */ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, /* hijklmno */
+/* 70 */ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* pqrstuvw */
+/* 78 */ 0x58, 0x59, 0x5A, 0x5B, 0x7C, 0x00, 0x7E, 0x00, /* xyz{|}~ */
+/* 80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 88 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 98 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* A0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* A8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* B0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* B8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* C0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* C8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* D0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* D8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* E0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* E8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* F0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* F8 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+/*
+ * Convert a unix filename to a DOS filename. Return -1 if wrong name is
+ * supplied.
+ */
+int
+msdos_filename_unix2dos(char *un, int unlen, char *dn)
+{
+ int i;
+ u_char c;
+
+ /*
+ * Fill the dos filename string with blanks. These are DOS's pad
+ * characters.
+ */
+ for (i = 0; i <= 10; i++)
+ dn[i] = ' ';
+
+ /*
+ * The filenames "." and ".." are handled specially, since they
+ * don't follow dos filename rules.
+ */
+ if (un[0] == '.' && unlen == 1) {
+ dn[0] = '.';
+ return 0;
+ }
+ if (un[0] == '.' && un[1] == '.' && unlen == 2) {
+ dn[0] = '.';
+ dn[1] = '.';
+ return 0;
+ }
+
+ /*
+ * Copy the unix filename into the dos filename string upto the end
+ * of string, a '.', or 8 characters. Whichever happens first stops
+ * us. This forms the name portion of the dos filename. Fold to
+ * upper case.
+ */
+ for (i = 0; i <= 7 && unlen && (c = *un) && c != '.'; i++) {
+ if ((dn[i] = msdos_map[c]) == 0)
+ return -1;
+ un++;
+ unlen--;
+ }
+
+ /*
+ * Strip any further characters up to a '.' or the end of the
+ * string.
+ */
+ while (unlen && (c = *un)) {
+ un++;
+ unlen--;
+ /* Make sure we've skipped over the dot before stopping. */
+ if (c == '.')
+ break;
+ }
+
+ /*
+ * Copy in the extension part of the name, if any. Force to upper
+ * case. Note that the extension is allowed to contain '.'s.
+ * Filenames in this form are probably inaccessable under dos.
+ */
+ for (i = 8; i <= 10 && unlen && (c = *un); i++) {
+ if ((dn[i] = msdos_map[c]) == 0)
+ return -1;
+ un++;
+ unlen--;
+ }
+ return 0;
+}
diff --git a/cpukit/libfs/src/dosfs/msdos_create.c b/cpukit/libfs/src/dosfs/msdos_create.c
new file mode 100644
index 0000000000..49cf56917d
--- /dev/null
+++ b/cpukit/libfs/src/dosfs/msdos_create.c
@@ -0,0 +1,345 @@
+/*
+ * Routine to create a new MSDOS filesystem node
+ *
+ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * @(#) $Id$
+ *
+ */
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <rtems/libio_.h>
+#include <time.h>
+
+#include "fat.h"
+#include "fat_fat_operations.h"
+#include "fat_file.h"
+
+#include "msdos.h"
+
+/* msdos_creat_node --
+ * Create a new node. If a new node is file, FAT 32 Bytes Directory
+ * Entry Structure is initialized, free space is found in parent
+ * directory and structure is written to the disk. In case of directory,
+ * all above steps present and also new cluster is allocated for a
+ * new directory and dot and dotdot nodes are created in alloceted cluster.
+ *
+ * PARAMETERS:
+ * parent_loc - parent (directory we are going to create node in)
+ * type - new node type (file or directory)
+ * name - new node name
+ * mode - mode
+ * link_info - fs_info of existing node for a pseudo "hard-link"
+ * (see msdos_file.c, msdos_link for documentation)
+ *
+ * RETURNS:
+ * RC_OK on success, or -1 if error occured (errno set appropriately).
+ *
+ */
+int
+msdos_creat_node(
+ rtems_filesystem_location_info_t *parent_loc,
+ msdos_node_type_t type,
+ char *name,
+ mode_t mode,
+ const fat_file_fd_t *link_fd
+ )
+{
+ int rc = RC_OK;
+ ssize_t ret = 0;
+ msdos_fs_info_t *fs_info = parent_loc->mt_entry->fs_info;
+ fat_file_fd_t *parent_fat_fd = parent_loc->node_access;
+ fat_file_fd_t *fat_fd = NULL;
+ time_t time_ret = 0;
+ uint16_t time_val = 0;
+ uint16_t date = 0;
+ fat_auxiliary_t aux;
+ unsigned char new_node [MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
+ unsigned char dot_dotdot[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2];
+ unsigned char link_node [MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
+ uint32_t sec = 0;
+ uint32_t byte = 0;
+
+ memset(new_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
+ memset(dot_dotdot, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2);
+
+ /* set up name */
+ strncpy(MSDOS_DIR_NAME(new_node), name, MSDOS_NAME_MAX);
+
+ /* fill reserved field */
+ *MSDOS_DIR_NT_RES(new_node) = MSDOS_RES_NT_VALUE;
+
+ /* set up last write date and time */
+ time_ret = time(NULL);
+ if ( time_ret == -1 )
+ return -1;
+
+ msdos_date_unix2dos(time_ret, &time_val, &date);
+ *MSDOS_DIR_WRITE_TIME(new_node) = CT_LE_W(time_val);
+ *MSDOS_DIR_WRITE_DATE(new_node) = CT_LE_W(date);
+
+ /* initialize directory/file size */
+ *MSDOS_DIR_FILE_SIZE(new_node) = MSDOS_INIT_DIR_SIZE;
+
+ if (type == MSDOS_DIRECTORY){
+ *MSDOS_DIR_ATTR(new_node) |= MSDOS_ATTR_DIRECTORY;
+ }
+ else if (type == MSDOS_HARD_LINK) {
+ /*
+ * when we establish a (temporary) hard link,
+ * we must copy some information from the original
+ * node to the newly created
+ */
+ /*
+ * read the original directory entry
+ */
+ sec = fat_cluster_num_to_sector_num(parent_loc->mt_entry,
+ link_fd->info_cln);
+ sec += (link_fd->info_ofs >> fs_info->fat.vol.sec_log2);
+ byte = (link_fd->info_ofs & (fs_info->fat.vol.bps - 1));
+
+ ret = _fat_block_read(parent_loc->mt_entry,
+ sec, byte, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE,
+ link_node);
+ if (ret < 0) {
+ return -1;
+ }
+ /*
+ * copy various attributes
+ */
+ *MSDOS_DIR_ATTR(new_node) =*MSDOS_DIR_ATTR(link_node);
+ *MSDOS_DIR_CRT_TIME_TENTH(new_node)=*MSDOS_DIR_CRT_TIME_TENTH(link_node);
+ *MSDOS_DIR_CRT_TIME(new_node) =*MSDOS_DIR_CRT_TIME(link_node);
+ *MSDOS_DIR_CRT_DATE(new_node) =*MSDOS_DIR_CRT_DATE(link_node);
+
+ /*
+ * copy/set "file size", "first cluster"
+ */
+ *MSDOS_DIR_FILE_SIZE(new_node) =*MSDOS_DIR_FILE_SIZE(link_node);
+
+ *MSDOS_DIR_FIRST_CLUSTER_LOW(new_node) =
+ *MSDOS_DIR_FIRST_CLUSTER_LOW(link_node);
+ *MSDOS_DIR_FIRST_CLUSTER_HI(new_node) =
+ *MSDOS_DIR_FIRST_CLUSTER_HI(link_node);
+ /*
+ * set "archive bit" due to changes
+ */
+ *MSDOS_DIR_ATTR(new_node) |= MSDOS_ATTR_ARCHIVE;
+ /*
+ * set "last access" date to today
+ */
+ *MSDOS_DIR_LAST_ACCESS_DATE(new_node) = CT_LE_W(date);
+ }
+ else { /* regular file... */
+ *MSDOS_DIR_ATTR(new_node) |= MSDOS_ATTR_ARCHIVE;
+ }
+
+ /*
+ * find free space in the parent directory and write new initialized
+ * FAT 32 Bytes Directory Entry Structure to the disk
+ */
+ rc = msdos_get_name_node(parent_loc, NULL, &aux, new_node);
+ if ( rc != RC_OK )
+ return rc;
+
+ /*
+ * if we create a new file we are done, if directory there are more steps
+ * to do
+ */
+ if (type == MSDOS_DIRECTORY)
+ {
+ /* open new directory as fat-file */
+ rc = fat_file_open(parent_loc->mt_entry, aux.cln, aux.ofs, &fat_fd);
+ if (rc != RC_OK)
+ goto err;
+
+ /*
+ * we opened fat-file for node we just created, so initialize fat-file
+ * descritor
+ */
+ fat_fd->info_cln = aux.cln;
+ fat_fd->info_ofs = aux.ofs;
+ fat_fd->fat_file_size = 0;
+ fat_fd->fat_file_type = FAT_DIRECTORY;
+ fat_fd->size_limit = MSDOS_MAX_DIR_LENGHT;
+
+ /*
+ * dot and dotdot entries are identical to new node except the
+ * names
+ */
+ memcpy(DOT_NODE_P(dot_dotdot), new_node,
+ MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
+ memcpy(DOTDOT_NODE_P(dot_dotdot), new_node,
+ MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
+ memcpy(MSDOS_DIR_NAME(DOT_NODE_P(dot_dotdot)), MSDOS_DOT_NAME,
+ MSDOS_NAME_MAX);
+ memcpy(MSDOS_DIR_NAME(DOTDOT_NODE_P(dot_dotdot)), MSDOS_DOTDOT_NAME,
+ MSDOS_NAME_MAX);
+
+ /* set up cluster num for dotdot entry */
+ /*
+ * here we can ommit FAT32 condition because for all FAT types dirs
+ * right under root dir should contain 0 in dotdot entry but for
+ * FAT12/16 parent_fat_fd->cluster_num always contains such value
+ */
+ if ((FAT_FD_OF_ROOT_DIR(parent_fat_fd)) &&
+ (fs_info->fat.vol.type & FAT_FAT32))
+ {
+ *MSDOS_DIR_FIRST_CLUSTER_LOW(DOTDOT_NODE_P(dot_dotdot)) = 0x0000;
+ *MSDOS_DIR_FIRST_CLUSTER_HI(DOTDOT_NODE_P(dot_dotdot)) = 0x0000;
+ }
+ else
+ {
+ *MSDOS_DIR_FIRST_CLUSTER_LOW(DOTDOT_NODE_P(dot_dotdot)) =
+ CT_LE_W((uint16_t )((parent_fat_fd->cln) & 0x0000FFFF));
+ *MSDOS_DIR_FIRST_CLUSTER_HI(DOTDOT_NODE_P(dot_dotdot)) =
+ CT_LE_W((uint16_t )(((parent_fat_fd->cln) & 0xFFFF0000)>>16));
+ }
+
+ /*
+ * write dot and dotdot entries to new fat-file: currently fat-file
+ * correspondes to a new node is zero length, so it will be extended
+ * by one cluster and entries will be written
+ */
+ ret = fat_file_write(parent_loc->mt_entry, fat_fd, 0,
+ MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE * 2,
+ dot_dotdot);
+ if (ret < 0)
+ {
+ rc = -1;
+ goto error;
+ }
+
+ /* increment fat-file size by cluster size */
+ fat_fd->fat_file_size += fs_info->fat.vol.bpc;
+
+ /* set up cluster num for dot entry */
+ *MSDOS_DIR_FIRST_CLUSTER_LOW(DOT_NODE_P(dot_dotdot)) =
+ CT_LE_W((uint16_t )((fat_fd->cln) & 0x0000FFFF));
+ *MSDOS_DIR_FIRST_CLUSTER_HI(DOT_NODE_P(dot_dotdot)) =
+ CT_LE_W((uint16_t )(((fat_fd->cln) & 0xFFFF0000) >> 16));
+
+ /* rewrite dot entry */
+ ret = fat_file_write(parent_loc->mt_entry, fat_fd, 0,
+ MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE,
+ DOT_NODE_P(dot_dotdot));
+ if (ret < 0)
+ {
+ rc = -1;
+ goto error;
+ }
+
+ /* write first cluster num of a new directory to disk */
+ rc = msdos_set_first_cluster_num(parent_loc->mt_entry, fat_fd);
+ if (rc != RC_OK)
+ goto error;
+
+ fat_file_close(parent_loc->mt_entry, fat_fd);
+ }
+ return RC_OK;
+
+error:
+ fat_file_close(parent_loc->mt_entry, fat_fd);
+
+err:
+ /* mark 32bytes structure on the disk as free */
+ msdos_set_first_char4file_name(parent_loc->mt_entry, aux.cln, aux.ofs,
+ 0xE5);
+ return rc;
+}
+
+/* msdos_file_link --
+ * Replacement for a file "link" operation.
+ * MSDOS FAT FS does not support links, but this call is needed to
+ * allow "rename" operations. The current NEWLIB rename performs a link
+ * from the old to the new name and then deletes the old filename.
+ *
+ * This pseudo-"link" operation will create a new directory entry,
+ * copy the file size and cluster information from the "old"
+ * to the "new" directory entry and then clear the file size and cluster
+ * info from the "old" filename, leaving this file as
+ * a valid, but empty entry.
+ *
+ * When this "link" call is part of a "rename" sequence, the "old"
+ * entry will be deleted in a subsequent "rmnod" call
+ *
+ * This function has been implemented by Thomas Doerfler,
+ * <Thomas.Doerfler@imd-systems.de>
+ *
+ * PARAMETERS:
+ * to_loc - node description for "existing" node
+ * par_loc - node description for "new" node
+ * token - name of new node
+ *
+ * RETURNS:
+ * RC_OK on success, or -1 if error occured (errno set appropriately)
+ */
+int
+msdos_file_link(rtems_filesystem_location_info_t *to_loc,
+ rtems_filesystem_location_info_t *par_loc,
+ const char *token
+)
+{
+ int rc = RC_OK;
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ msdos_fs_info_t *fs_info = to_loc->mt_entry->fs_info;
+ fat_file_fd_t *to_fat_fd = to_loc->node_access;
+ char new_name[ MSDOS_NAME_MAX + 1 ];
+ int len;
+
+ /*
+ * check spelling and format new node name
+ */
+ if (MSDOS_NAME != msdos_get_token(token, new_name, &len)) {
+ set_errno_and_return_minus_one(ENAMETOOLONG);
+ }
+ /*
+ * verify, that the existing node can be linked to
+ * check that nodes are in same FS/volume?
+ */
+ if (to_loc->mt_entry->fs_info != par_loc->mt_entry->fs_info) {
+ set_errno_and_return_minus_one(EXDEV);
+ }
+ /*
+ * lock volume
+ */
+ sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
+ MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one(EIO);
+
+
+ /*
+ * create new directory entry as "hard link",
+ * copying relevant info from existing file
+ */
+ rc = msdos_creat_node(par_loc,MSDOS_HARD_LINK,new_name,S_IFREG,
+ to_loc->node_access);
+ /*
+ * set file size and first cluster number of old entry to 0
+ */
+ if (rc == RC_OK) {
+ to_fat_fd->fat_file_size = 0;
+ to_fat_fd->cln = FAT_EOF;
+ rc = msdos_set_first_cluster_num(to_loc->mt_entry, to_fat_fd);
+ if (rc == RC_OK) {
+ rc = msdos_set_file_size(par_loc->mt_entry, to_fat_fd);
+ }
+ }
+ /*
+ * FIXME: check error/abort handling
+ */
+ rtems_semaphore_release(fs_info->vol_sema);
+ return rc;
+}
diff --git a/cpukit/libfs/src/dosfs/msdos_dir.c b/cpukit/libfs/src/dosfs/msdos_dir.c
new file mode 100644
index 0000000000..4afc404592
--- /dev/null
+++ b/cpukit/libfs/src/dosfs/msdos_dir.c
@@ -0,0 +1,553 @@
+/*
+ * MSDOS directory handlers implementation
+ *
+ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * @(#) $Id$
+ */
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <assert.h>
+#include <errno.h>
+#include <rtems/libio_.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <dirent.h>
+
+#include "fat.h"
+#include "fat_fat_operations.h"
+#include "fat_file.h"
+
+#include "msdos.h"
+
+/* msdos_dir_open --
+ * Open fat-file which correspondes to the directory being opened and
+ * set offset field of file control block to zero.
+ *
+ * PARAMETERS:
+ * iop - file control block
+ * pathname - name
+ * flag - flags
+ * mode - mode
+ *
+ * RETURNS:
+ * RC_OK, if directory opened successfully, or -1 if error occured (errno
+ * set apropriately)
+ */
+int
+msdos_dir_open(rtems_libio_t *iop, const char *pathname, uint32_t flag,
+ uint32_t mode)
+{
+ int rc = RC_OK;
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info;
+ fat_file_fd_t *fat_fd = iop->file_info;
+
+ sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
+ MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one( EIO );
+
+ rc = fat_file_reopen(fat_fd);
+ if (rc != RC_OK)
+ {
+ rtems_semaphore_release(fs_info->vol_sema);
+ return rc;
+ }
+
+ iop->offset = 0;
+ rtems_semaphore_release(fs_info->vol_sema);
+ return RC_OK;
+}
+
+/* msdos_dir_close --
+ * Close fat-file which correspondes to the directory being closed
+ *
+ * PARAMETERS:
+ * iop - file control block
+ *
+ * RETURNS:
+ * RC_OK, if directory closed successfully, or -1 if error occured (errno
+ * set apropriately.
+ */
+int
+msdos_dir_close(rtems_libio_t *iop)
+{
+ int rc = RC_OK;
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info;
+ fat_file_fd_t *fat_fd = iop->file_info;
+
+ sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
+ MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one( EIO );
+
+ rc = fat_file_close(iop->pathinfo.mt_entry, fat_fd);
+ if (rc != RC_OK)
+ {
+ rtems_semaphore_release(fs_info->vol_sema);
+ return rc;
+ }
+
+ rtems_semaphore_release(fs_info->vol_sema);
+ return RC_OK;
+}
+
+/* msdos_format_dirent_with_dot --
+ * This routine convert a (short) MSDOS filename as present on disk
+ * (fixed 8+3 characters, filled with blanks, without separator dot)
+ * to a "normal" format, with between 0 and 8 name chars,
+ * a separating dot and up to 3 extension characters
+ * Rules to work:
+ * - copy any (0-8) "name" part characters that are non-blank
+ * - if an extension exists, append a dot
+ * - copy any (0-3) non-blank extension characters
+ * - append a '\0' (dont count it for the rturn code
+ *
+ * PARAMETERS:
+ * dst: pointer to destination char array (must be big enough)
+ * src: pointer to source characters
+ *
+ *
+ * RETURNS:
+ * the number of bytes (without trailing '\0'(written to destination
+ */
+static ssize_t
+msdos_format_dirent_with_dot(char *dst,const char *src)
+{
+ ssize_t len;
+ int i;
+ const char *src_tmp;
+
+ /*
+ * find last non-blank character of base name
+ */
+ for ((i = MSDOS_SHORT_BASE_LEN ,
+ src_tmp = src + MSDOS_SHORT_BASE_LEN-1);
+ ((i > 0) &&
+ (*src_tmp == ' '));
+ i--,src_tmp--)
+ {};
+ /*
+ * copy base name to destination
+ */
+ src_tmp = src;
+ len = i;
+ while (i-- > 0) {
+ *dst++ = *src_tmp++;
+ }
+ /*
+ * find last non-blank character of extension
+ */
+ for ((i = MSDOS_SHORT_EXT_LEN ,
+ src_tmp = src + MSDOS_SHORT_BASE_LEN+MSDOS_SHORT_EXT_LEN-1);
+ ((i > 0) &&
+ (*src_tmp == ' '));
+ i--,src_tmp--)
+ {};
+ /*
+ * extension is not empty
+ */
+ if (i > 0) {
+ *dst++ = '.'; /* append dot */
+ len += i + 1; /* extension + dot */
+ src_tmp = src + MSDOS_SHORT_BASE_LEN;
+ while (i-- > 0) {
+ *dst++ = *src_tmp++;
+ len++;
+ }
+ }
+ *dst = '\0'; /* terminate string */
+
+ return len;
+}
+
+/* msdos_dir_read --
+ * This routine will read the next directory entry based on the directory
+ * offset. The offset should be equal to -n- time the size of an
+ * individual dirent structure. If n is not an integer multiple of the
+ * sizeof a dirent structure, an integer division will be performed to
+ * determine directory entry that will be returned in the buffer. Count
+ * should reflect -m- times the sizeof dirent bytes to be placed in the
+ * buffer.
+ * If there are not -m- dirent elements from the current directory
+ * position to the end of the exisiting file, the remaining entries will
+ * be placed in the buffer and the returned value will be equal to
+ * -m actual- times the size of a directory entry.
+ *
+ * PARAMETERS:
+ * iop - file control block
+ * buffer - buffer provided by user
+ * count - count of bytes to read
+ *
+ * RETURNS:
+ * the number of bytes read on success, or -1 if error occured (errno
+ * set apropriately).
+ */
+ssize_t
+msdos_dir_read(rtems_libio_t *iop, void *buffer, uint32_t count)
+{
+ int rc = RC_OK;
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info;
+ fat_file_fd_t *fat_fd = iop->file_info;
+ fat_file_fd_t *tmp_fat_fd = NULL;
+ struct dirent tmp_dirent;
+ uint32_t start = 0;
+ ssize_t ret = 0;
+ uint32_t cmpltd = 0;
+ uint32_t j = 0, i = 0;
+ uint32_t bts2rd = 0;
+ uint32_t cur_cln = 0;
+
+ /*
+ * cast start and count - protect against using sizes that are not exact
+ * multiples of the -dirent- size. These could result in unexpected
+ * results
+ */
+ start = iop->offset / sizeof(struct dirent);
+ count = (count / sizeof(struct dirent)) * sizeof(struct dirent);
+
+ /*
+ * optimization: we know that root directory for FAT12/16 volumes is
+ * sequential set of sectors and any cluster is sequential set of sectors
+ * too, so read such set of sectors is quick operation for low-level IO
+ * layer.
+ */
+ bts2rd = (FAT_FD_OF_ROOT_DIR(fat_fd) &&
+ (fs_info->fat.vol.type & (FAT_FAT12 | FAT_FAT16))) ?
+ fat_fd->fat_file_size :
+ fs_info->fat.vol.bpc;
+
+ sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
+ MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one(EIO);
+
+ while (count > 0)
+ {
+ /*
+ * fat-file is already opened by open call, so read it
+ * Always read directory fat-file from the beggining because of MSDOS
+ * directories feature :( - we should count elements currently
+ * present in the directory because there may be holes :)
+ */
+ ret = fat_file_read(iop->pathinfo.mt_entry, fat_fd, (j * bts2rd),
+ bts2rd, fs_info->cl_buf);
+ if (ret < MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
+ {
+ rtems_semaphore_release(fs_info->vol_sema);
+ set_errno_and_return_minus_one(EIO);
+ }
+
+ for (i = 0; i < ret; i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
+ {
+ if ((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
+ MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY)
+ {
+ rtems_semaphore_release(fs_info->vol_sema);
+ return cmpltd;
+ }
+
+ if ((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
+ MSDOS_THIS_DIR_ENTRY_EMPTY)
+ continue;
+
+ /*
+ * skip active entries until get the entry to start from
+ */
+ if (start)
+ {
+ start--;
+ continue;
+ }
+
+ /*
+ * Move the entry to the return buffer
+ *
+ * unfortunately there is no method to extract ino except to
+ * open fat-file descriptor :( ... so, open it
+ */
+
+ /* get number of cluster we are working with */
+ rc = fat_file_ioctl(iop->pathinfo.mt_entry, fat_fd, F_CLU_NUM,
+ j * bts2rd, &cur_cln);
+ if (rc != RC_OK)
+ {
+ rtems_semaphore_release(fs_info->vol_sema);
+ return rc;
+ }
+
+ rc = fat_file_open(iop->pathinfo.mt_entry, cur_cln, i,
+ &tmp_fat_fd);
+ if (rc != RC_OK)
+ {
+ rtems_semaphore_release(fs_info->vol_sema);
+ return rc;
+ }
+
+ tmp_fat_fd->info_cln = cur_cln;
+ tmp_fat_fd->info_ofs = i;
+
+ /* fill in dirent structure */
+ /* XXX: from what and in what d_off should be computed ?! */
+ tmp_dirent.d_off = start + cmpltd;
+ tmp_dirent.d_reclen = sizeof(struct dirent);
+ tmp_dirent.d_ino = tmp_fat_fd->ino;
+ /*
+ * convert dir entry from fixed 8+3 format (without dot)
+ * to 0..8 + 1dot + 0..3 format
+ */
+ tmp_dirent.d_namlen =
+ msdos_format_dirent_with_dot(tmp_dirent.d_name,
+ fs_info->cl_buf + i); /* src text */
+ memcpy(buffer + cmpltd, &tmp_dirent, sizeof(struct dirent));
+
+ iop->offset = iop->offset + sizeof(struct dirent);
+ cmpltd += (sizeof(struct dirent));
+ count -= (sizeof(struct dirent));
+
+ /* inode number extracted, close fat-file */
+ rc = fat_file_close(iop->pathinfo.mt_entry, tmp_fat_fd);
+ if (rc != RC_OK)
+ {
+ rtems_semaphore_release(fs_info->vol_sema);
+ return rc;
+ }
+
+ if (count <= 0)
+ break;
+ }
+ j++;
+ }
+
+ rtems_semaphore_release(fs_info->vol_sema);
+ return cmpltd;
+}
+
+/* msdos_dir_write --
+ * no write for directory
+ */
+
+/* msdos_dir_lseek --
+ *
+ * This routine will behave in one of three ways based on the state of
+ * argument whence. Based on the state of its value the offset argument will
+ * be interpreted using one of the following methods:
+ *
+ * SEEK_SET - offset is the absolute byte offset from the start of the
+ * logical start of the dirent sequence that represents the
+ * directory
+ * SEEK_CUR - offset is used as the relative byte offset from the current
+ * directory position index held in the iop structure
+ * SEEK_END - N/A --> This will cause an assert.
+ *
+ * PARAMETERS:
+ * iop - file control block
+ * offset - offset
+ * whence - predefine directive
+ *
+ * RETURNS:
+ * RC_OK on success, or -1 if error occured (errno
+ * set apropriately).
+ */
+int
+msdos_dir_lseek(rtems_libio_t *iop, off_t offset, int whence)
+{
+ switch (whence)
+ {
+ case SEEK_SET:
+ case SEEK_CUR:
+ break;
+ /*
+ * Movement past the end of the directory via lseek is not a
+ * permitted operation
+ */
+ case SEEK_END:
+ default:
+ set_errno_and_return_minus_one( EINVAL );
+ break;
+ }
+ return RC_OK;
+}
+
+/* msdos_dir_stat --
+ *
+ * This routine will obtain the following information concerning the current
+ * directory:
+ * st_dev device id
+ * st_ino node serial number :)
+ * st_mode mode extracted from the node
+ * st_size total size in bytes
+ * st_blksize blocksize for filesystem I/O
+ * st_blocks number of blocks allocated
+ * stat_mtime time of last modification
+ *
+ * PARAMETERS:
+ * loc - this directory
+ * buf - stat buffer provided by user
+ *
+ * RETURNS:
+ * RC_OK and filled stat buffer on success, or -1 if error occured (errno
+ * set apropriately).
+ */
+int
+msdos_dir_stat(
+ rtems_filesystem_location_info_t *loc,
+ struct stat *buf
+ )
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ msdos_fs_info_t *fs_info = loc->mt_entry->fs_info;
+ fat_file_fd_t *fat_fd = loc->node_access;
+
+ sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
+ MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one(EIO);
+
+ buf->st_dev = fs_info->fat.vol.dev;
+ buf->st_ino = fat_fd->ino;
+ buf->st_mode = S_IFDIR;
+ buf->st_rdev = 0ll;
+ buf->st_size = fat_fd->fat_file_size;
+ buf->st_blocks = fat_fd->fat_file_size >> FAT_SECTOR512_BITS;
+ buf->st_blksize = fs_info->fat.vol.bps;
+ buf->st_mtime = fat_fd->mtime;
+
+ rtems_semaphore_release(fs_info->vol_sema);
+ return RC_OK;
+}
+
+/* msdos_dir_truncate --
+ * No truncate for directory.
+ *
+ * PARAMETERS:
+ *
+ * RETURNS:
+ *
+ */
+
+/* msdos_dir_sync --
+ * The following routine does a syncronization on a MSDOS directory node.
+ * DIR_WrtTime, DIR_WrtDate and DIR_fileSize fields of 32 Bytes Directory
+ * Entry Structure should not be updated for directories, so only call
+ * to corresponding fat-file routine.
+ *
+ * PARAMETERS:
+ * iop - file control block
+ *
+ * RETURNS:
+ * RC_OK on success, or -1 if error occured (errno set apropriately).
+ */
+int
+msdos_dir_sync(rtems_libio_t *iop)
+{
+ int rc = RC_OK;
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ fat_file_fd_t *fat_fd = iop->file_info;
+ msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info;
+
+ sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
+ MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one(EIO);
+
+ rc = fat_file_datasync(iop->pathinfo.mt_entry, fat_fd);
+
+ rtems_semaphore_release(fs_info->vol_sema);
+ return rc;
+}
+
+/* msdos_dir_rmnod --
+ * Remove directory node.
+ *
+ * Check that this directory node is not opened as fat-file, is empty and
+ * not filesystem root node. If all this conditions met then delete.
+ *
+ * PARAMETERS:
+ * pathloc - node description
+ *
+ * RETURNS:
+ * RC_OK on success, or -1 if error occured (errno set apropriately).
+ */
+int
+msdos_dir_rmnod(rtems_filesystem_location_info_t *pathloc)
+{
+ int rc = RC_OK;
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info;
+ fat_file_fd_t *fat_fd = pathloc->node_access;
+ rtems_boolean is_empty = FALSE;
+
+ sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
+ MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one(EIO);
+
+ /*
+ * We deny attemp to delete open directory (if directory is current
+ * directory we assume it is open one)
+ */
+ if (fat_fd->links_num > 1)
+ {
+ rtems_semaphore_release(fs_info->vol_sema);
+ set_errno_and_return_minus_one(EBUSY);
+ }
+
+ /*
+ * You cannot remove a node that still has children
+ */
+ rc = msdos_dir_is_empty(pathloc->mt_entry, fat_fd, &is_empty);
+ if (rc != RC_OK)
+ {
+ rtems_semaphore_release(fs_info->vol_sema);
+ return rc;
+ }
+
+ if (!is_empty)
+ {
+ rtems_semaphore_release(fs_info->vol_sema);
+ set_errno_and_return_minus_one(ENOTEMPTY);
+ }
+
+ /*
+ * You cannot remove the file system root node.
+ */
+ if (pathloc->mt_entry->mt_fs_root.node_access == pathloc->node_access)
+ {
+ rtems_semaphore_release(fs_info->vol_sema);
+ set_errno_and_return_minus_one(EBUSY);
+ }
+
+ /*
+ * You cannot remove a mountpoint.
+ * not used - mount() not implemenetd yet.
+ */
+
+ /* mark file removed */
+ rc = msdos_set_first_char4file_name(pathloc->mt_entry, fat_fd->info_cln,
+ fat_fd->info_ofs,
+ MSDOS_THIS_DIR_ENTRY_EMPTY);
+ if (rc != RC_OK)
+ {
+ rtems_semaphore_release(fs_info->vol_sema);
+ return rc;
+ }
+
+ fat_file_mark_removed(pathloc->mt_entry, fat_fd);
+
+ rtems_semaphore_release(fs_info->vol_sema);
+ return rc;
+}
diff --git a/cpukit/libfs/src/dosfs/msdos_eval.c b/cpukit/libfs/src/dosfs/msdos_eval.c
new file mode 100644
index 0000000000..0bba0c0a5e
--- /dev/null
+++ b/cpukit/libfs/src/dosfs/msdos_eval.c
@@ -0,0 +1,435 @@
+/*
+ * MSDOS evaluation routines
+ *
+ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * @(#) $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include <rtems/libio_.h>
+
+#include "fat.h"
+#include "fat_fat_operations.h"
+#include "fat_file.h"
+
+#include "msdos.h"
+
+/* msdos_set_handlers --
+ * Set handlers for the node with specified type(i.e. handlers for file
+ * or directory).
+ *
+ * PARAMETERS:
+ * loc - node description
+ *
+ * RETURNS:
+ * None
+ */
+static void
+msdos_set_handlers(rtems_filesystem_location_info_t *loc)
+{
+ msdos_fs_info_t *fs_info = loc->mt_entry->fs_info;
+ fat_file_fd_t *fat_fd = loc->node_access;
+
+ if (fat_fd->fat_file_type == FAT_DIRECTORY)
+ loc->handlers = fs_info->directory_handlers;
+ else
+ loc->handlers = fs_info->file_handlers;
+}
+
+/* msdos_eval_path --
+ *
+ * The following routine evaluate path for a node that wishes to be
+ * accessed. Structure 'pathloc' is returned with a pointer to the
+ * node to be accessed.
+ *
+ * PARAMETERS:
+ * pathname - path for evaluation
+ * flags - flags
+ * pathloc - node description (IN/OUT)
+ *
+ * RETURNS:
+ * RC_OK and filled pathloc on success, or -1 if error occured
+ * (errno set appropriately)
+ *
+ */
+int
+msdos_eval_path(
+ const char *pathname,
+ int flags,
+ rtems_filesystem_location_info_t *pathloc
+ )
+{
+ int rc = RC_OK;
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info;
+ fat_file_fd_t *fat_fd = NULL;
+ rtems_filesystem_location_info_t newloc;
+ int i = 0;
+ int len = 0;
+ msdos_token_types_t type = MSDOS_CURRENT_DIR;
+ char token[MSDOS_NAME_MAX + 1];
+
+ sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
+ MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one(EIO);
+
+ if (!pathloc->node_access)
+ {
+ errno = ENOENT;
+ rc = -1;
+ goto err;
+ }
+
+ fat_fd = pathloc->node_access;
+
+ rc = fat_file_reopen(fat_fd);
+ if (rc != RC_OK)
+ goto err;
+
+ while ((type != MSDOS_NO_MORE_PATH) && (type != MSDOS_INVALID_TOKEN))
+ {
+ type = msdos_get_token(&pathname[i], token, &len);
+ i += len;
+
+ fat_fd = pathloc->node_access;
+
+ switch (type)
+ {
+ case MSDOS_UP_DIR:
+ /*
+ * Only a directory can be decended into.
+ */
+ if (fat_fd->fat_file_type != FAT_DIRECTORY)
+ {
+ errno = ENOTDIR;
+ rc = -1;
+ goto error;
+ }
+
+ /*
+ * Am I at the root of this mounted filesystem?
+ */
+ if (pathloc->node_access ==
+ pathloc->mt_entry->mt_fs_root.node_access)
+ {
+ /*
+ * Am I at the root of all filesystems?
+ * XXX: MSDOS is not supposed to be base fs.
+ */
+ if (pathloc->node_access ==
+ rtems_filesystem_root.node_access)
+ {
+ break; /* Throw out the .. in this case */
+ }
+ else
+ {
+ newloc = pathloc->mt_entry->mt_point_node;
+ *pathloc = newloc;
+
+ rc = fat_file_close(pathloc->mt_entry, fat_fd);
+ if (rc != RC_OK)
+ goto err;
+
+ rtems_semaphore_release(fs_info->vol_sema);
+ return (*pathloc->ops->evalpath_h)(&(pathname[i-len]),
+ flags, pathloc);
+ }
+ }
+ else
+ {
+ rc = msdos_find_name(pathloc, token);
+ if (rc != RC_OK)
+ {
+ if (rc == MSDOS_NAME_NOT_FOUND_ERR)
+ {
+ errno = ENOENT;
+ rc = -1;
+ }
+ goto error;
+ }
+ }
+ break;
+
+ case MSDOS_NAME:
+ /*
+ * Only a directory can be decended into.
+ */
+ if (fat_fd->fat_file_type != FAT_DIRECTORY)
+ {
+ errno = ENOTDIR;
+ rc = -1;
+ goto error;
+ }
+
+ /*
+ * Otherwise find the token name in the present location and
+ * set the node access to the point we have found.
+ */
+ rc = msdos_find_name(pathloc, token);
+ if (rc != RC_OK)
+ {
+ if (rc == MSDOS_NAME_NOT_FOUND_ERR)
+ {
+ errno = ENOENT;
+ rc = -1;
+ }
+ goto error;
+ }
+ break;
+
+ case MSDOS_NO_MORE_PATH:
+ case MSDOS_CURRENT_DIR:
+ break;
+
+ case MSDOS_INVALID_TOKEN:
+ errno = ENAMETOOLONG;
+ rc = -1;
+ goto error;
+ break;
+
+ }
+ }
+
+ /*
+ * Always return the root node.
+ *
+ * If we are at a node that is a mount point. Set loc to the
+ * new fs root node and let let the mounted filesystem set the handlers.
+ *
+ * NOTE: The behavior of stat() on a mount point appears to be
+ * questionable.
+ * NOTE: MSDOS filesystem currently doesn't support mount functionality ->
+ * action not implemented
+ */
+ fat_fd = pathloc->node_access;
+
+ msdos_set_handlers(pathloc);
+
+ rtems_semaphore_release(fs_info->vol_sema);
+ return RC_OK;
+
+error:
+ fat_file_close(pathloc->mt_entry, fat_fd);
+
+err:
+ rtems_semaphore_release(fs_info->vol_sema);
+ return rc;
+}
+
+/* msdos_eval4make --
+ * The following routine evaluate path for a new node to be created.
+ * 'pathloc' is returned with a pointer to the parent of the new node.
+ * 'name' is returned with a pointer to the first character in the
+ * new node name. The parent node is verified to be a directory.
+ *
+ * PARAMETERS:
+ * path - path for evaluation
+ * pathloc - IN/OUT (start point for evaluation/parent directory for
+ * creation)
+ * name - new node name
+ *
+ * RETURNS:
+ * RC_OK, filled pathloc for parent directory and name of new node on
+ * success, or -1 if error occured (errno set appropriately)
+ */
+int
+msdos_eval4make(
+ const char *path,
+ rtems_filesystem_location_info_t *pathloc,
+ const char **name
+ )
+{
+ int rc = RC_OK;
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info;
+ fat_file_fd_t *fat_fd = NULL;
+ rtems_filesystem_location_info_t newloc;
+ msdos_token_types_t type;
+ int i = 0;
+ int len;
+ char token[ MSDOS_NAME_MAX + 1 ];
+ rtems_boolean done = 0;
+
+ sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
+ MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one(EIO);
+
+ if (!pathloc->node_access)
+ {
+ errno = ENOENT;
+ rc = -1;
+ goto err;
+ }
+
+ fat_fd = pathloc->node_access;
+
+ rc = fat_file_reopen(fat_fd);
+ if (rc != RC_OK)
+ goto err;
+
+ while (!done)
+ {
+ type = msdos_get_token(&path[i], token, &len);
+ i += len;
+ fat_fd = pathloc->node_access;
+
+ switch (type)
+ {
+ case MSDOS_UP_DIR:
+ /*
+ * Only a directory can be decended into.
+ */
+ if (fat_fd->fat_file_type != FAT_DIRECTORY)
+ {
+ errno = ENOTDIR;
+ rc = -1;
+ goto error;
+ }
+
+ /*
+ * Am I at the root of this mounted filesystem?
+ */
+ if (pathloc->node_access ==
+ pathloc->mt_entry->mt_fs_root.node_access)
+ {
+ /*
+ * Am I at the root of all filesystems?
+ * XXX: MSDOS is not supposed to be base fs.
+ */
+ if (pathloc->node_access ==
+ rtems_filesystem_root.node_access)
+ {
+ break; /* Throw out the .. in this case */
+ }
+ else
+ {
+ newloc = pathloc->mt_entry->mt_point_node;
+ *pathloc = newloc;
+
+ rc = fat_file_close(pathloc->mt_entry, fat_fd);
+ if (rc != RC_OK)
+ goto err;
+
+ rtems_semaphore_release(fs_info->vol_sema);
+ return (*pathloc->ops->evalformake_h)(&path[i-len],
+ pathloc, name);
+ }
+ }
+ else
+ {
+ rc = msdos_find_name(pathloc, token);
+ if (rc != RC_OK)
+ {
+ if (rc == MSDOS_NAME_NOT_FOUND_ERR)
+ {
+ errno = ENOENT;
+ rc = -1;
+ }
+ goto error;
+ }
+ }
+ break;
+
+ case MSDOS_NAME:
+ /*
+ * Only a directory can be decended into.
+ */
+ if (fat_fd->fat_file_type != FAT_DIRECTORY)
+ {
+ errno = ENOTDIR;
+ rc = -1;
+ goto error;
+ }
+
+ /*
+ * Otherwise find the token name in the present location and
+ * set the node access to the point we have found.
+ */
+ rc = msdos_find_name(pathloc, token);
+ if (rc)
+ {
+ if (rc != MSDOS_NAME_NOT_FOUND_ERR)
+ {
+ errno = ENOENT;
+ rc = -1;
+ goto error;
+ }
+ else
+ done = TRUE;
+ }
+ break;
+
+ case MSDOS_NO_MORE_PATH:
+ errno = EEXIST;
+ rc = -1;
+ goto error;
+ break;
+
+ case MSDOS_CURRENT_DIR:
+ break;
+
+ case MSDOS_INVALID_TOKEN:
+ errno = ENAMETOOLONG;
+ rc = -1;
+ goto error;
+ break;
+
+ }
+ }
+
+ *name = &path[i - len];
+
+ /*
+ * We have evaluated the path as far as we can.
+ * Verify there is not any invalid stuff at the end of the name.
+ */
+ for( ; path[i] != '\0'; i++)
+ {
+ if (!msdos_is_separator(path[i]))
+ {
+ errno = ENOENT;
+ rc = -1;
+ goto error;
+ }
+ }
+
+ fat_fd = pathloc->node_access;
+
+ if (fat_fd->fat_file_type != FAT_DIRECTORY)
+ {
+ errno = ENOTDIR;
+ rc = -1;
+ goto error;
+ }
+
+ msdos_set_handlers(pathloc);
+
+ rtems_semaphore_release(fs_info->vol_sema);
+ return RC_OK;
+
+error:
+ fat_file_close(pathloc->mt_entry, fat_fd);
+
+err:
+ rtems_semaphore_release(fs_info->vol_sema);
+ return rc;
+}
diff --git a/cpukit/libfs/src/dosfs/msdos_file.c b/cpukit/libfs/src/dosfs/msdos_file.c
new file mode 100644
index 0000000000..14bd96b325
--- /dev/null
+++ b/cpukit/libfs/src/dosfs/msdos_file.c
@@ -0,0 +1,485 @@
+/*
+ * MSDOS file handlers implementation
+ *
+ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * @(#) $Id$
+ */
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <rtems/libio_.h>
+
+#include "fat.h"
+#include "fat_fat_operations.h"
+#include "fat_file.h"
+
+#include "msdos.h"
+
+/* msdos_file_open --
+ * Open fat-file which correspondes to the file
+ *
+ * PARAMETERS:
+ * iop - file control block
+ * pathname - name
+ * flag - flags
+ * mode - mode
+ *
+ * RETURNS:
+ * RC_OK, if file opened successfully, or -1 if error occured
+ * and errno set appropriately
+ */
+int
+msdos_file_open(rtems_libio_t *iop, const char *pathname, uint32_t flag,
+ uint32_t mode)
+{
+ int rc = RC_OK;
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info;
+ fat_file_fd_t *fat_fd = iop->file_info;
+
+ sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
+ MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one(EIO);
+
+ rc = fat_file_reopen(fat_fd);
+ if (rc != RC_OK)
+ {
+ rtems_semaphore_release(fs_info->vol_sema);
+ return rc;
+ }
+
+ if (iop->flags & LIBIO_FLAGS_APPEND)
+ iop->offset = fat_fd->fat_file_size;
+
+ iop->size = fat_fd->fat_file_size;
+
+ rtems_semaphore_release(fs_info->vol_sema);
+ return RC_OK;
+}
+
+/* msdos_file_close --
+ * Close fat-file which correspondes to the file. If fat-file descriptor
+ * which correspondes to the file is not marked "removed", synchronize
+ * size, first cluster number, write time and date fields of the file.
+ *
+ * PARAMETERS:
+ * iop - file control block
+ *
+ * RETURNS:
+ * RC_OK, if file closed successfully, or -1 if error occured (errno set
+ * appropriately)
+ */
+int
+msdos_file_close(rtems_libio_t *iop)
+{
+ int rc = RC_OK;
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info;
+ fat_file_fd_t *fat_fd = iop->file_info;
+
+ sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
+ MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one(EIO);
+
+ /*
+ * if fat-file descriptor is not marked as "removed", synchronize
+ * size, first cluster number, write time and date fields of the file
+ */
+ if (!FAT_FILE_IS_REMOVED(fat_fd))
+ {
+ rc = msdos_set_first_cluster_num(iop->pathinfo.mt_entry, fat_fd);
+ if (rc != RC_OK)
+ {
+ rtems_semaphore_release(fs_info->vol_sema);
+ return rc;
+ }
+
+ rc = msdos_set_file_size(iop->pathinfo.mt_entry, fat_fd);
+ if (rc != RC_OK)
+ {
+ rtems_semaphore_release(fs_info->vol_sema);
+ return rc;
+ }
+
+ rc = msdos_set_dir_wrt_time_and_date(iop->pathinfo.mt_entry, fat_fd);
+ if (rc != RC_OK)
+ {
+ rtems_semaphore_release(fs_info->vol_sema);
+ return rc;
+ }
+ }
+
+ rc = fat_file_close(iop->pathinfo.mt_entry, fat_fd);
+
+ rtems_semaphore_release(fs_info->vol_sema);
+ return rc;
+}
+
+/* msdos_file_read --
+ * This routine read from file pointed to by file control block into
+ * the specified data buffer provided by user
+ *
+ * PARAMETERS:
+ * iop - file control block
+ * buffer - buffer provided by user
+ * count - the number of bytes to read
+ *
+ * RETURNS:
+ * the number of bytes read on success, or -1 if error occured (errno set
+ * appropriately)
+ */
+ssize_t
+msdos_file_read(rtems_libio_t *iop, void *buffer, uint32_t count)
+{
+ ssize_t ret = 0;
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info;
+ fat_file_fd_t *fat_fd = iop->file_info;
+
+ sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
+ MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one(EIO);
+
+ ret = fat_file_read(iop->pathinfo.mt_entry, fat_fd, iop->offset, count,
+ buffer);
+
+ rtems_semaphore_release(fs_info->vol_sema);
+ return ret;
+}
+
+/* msdos_file_write --
+ * This routine writes the specified data buffer into the file pointed to
+ * by file control block.
+ *
+ * PARAMETERS:
+ * iop - file control block
+ * buffer - data to write
+ * count - count of bytes to write
+ *
+ * RETURNS:
+ * the number of bytes written on success, or -1 if error occured
+ * and errno set appropriately
+ */
+ssize_t
+msdos_file_write(rtems_libio_t *iop,const void *buffer, uint32_t count)
+{
+ ssize_t ret = 0;
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info;
+ fat_file_fd_t *fat_fd = iop->file_info;
+
+ sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
+ MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one(EIO);
+
+ ret = fat_file_write(iop->pathinfo.mt_entry, fat_fd, iop->offset, count,
+ buffer);
+ if (ret < 0)
+ {
+ rtems_semaphore_release(fs_info->vol_sema);
+ return -1;
+ }
+
+ /*
+ * update file size in both fat-file descriptor and file control block if
+ * file was extended
+ */
+ if (iop->offset + ret > fat_fd->fat_file_size)
+ fat_fd->fat_file_size = iop->offset + ret;
+
+ iop->size = fat_fd->fat_file_size;
+
+ rtems_semaphore_release(fs_info->vol_sema);
+ return ret;
+}
+
+/* msdos_file_lseek --
+ * Process lseek call to the file: extend file if lseek is up to the end
+ * of the file.
+ *
+ * PARAMETERS:
+ * iop - file control block
+ * offset - new offset
+ * whence - predefine directive
+ *
+ * RETURNS:
+ * new offset on success, or -1 if error occured (errno set
+ * appropriately).
+ */
+int
+msdos_file_lseek(rtems_libio_t *iop, off_t offset, int whence)
+{
+ int rc = RC_OK;
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info;
+ fat_file_fd_t *fat_fd = iop->file_info;
+ uint32_t real_size = 0;
+
+ sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
+ MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one(EIO);
+
+ rc = fat_file_extend(iop->pathinfo.mt_entry, fat_fd, iop->offset,
+ &real_size);
+ if (rc != RC_OK)
+ {
+ rtems_semaphore_release(fs_info->vol_sema);
+ return rc;
+ }
+
+ if (real_size > fat_fd->fat_file_size)
+ fat_fd->fat_file_size = iop->offset = real_size;
+
+ iop->size = fat_fd->fat_file_size;
+
+ rtems_semaphore_release(fs_info->vol_sema);
+ return iop->offset;
+}
+
+/* msdos_file_stat --
+ *
+ * PARAMETERS:
+ * loc - node description
+ * buf - stat buffer provided by user
+ *
+ * RETURNS:
+ * RC_OK on success, or -1 if error occured (errno set appropriately)
+ */
+int
+msdos_file_stat(
+ rtems_filesystem_location_info_t *loc,
+ struct stat *buf
+ )
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ msdos_fs_info_t *fs_info = loc->mt_entry->fs_info;
+ fat_file_fd_t *fat_fd = loc->node_access;
+
+ sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
+ MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one(EIO);
+
+ buf->st_dev = fs_info->fat.vol.dev;
+ buf->st_ino = fat_fd->ino;
+ buf->st_mode = S_IFREG;
+ buf->st_rdev = 0ll;
+ buf->st_size = fat_fd->fat_file_size;
+ buf->st_blocks = fat_fd->fat_file_size >> FAT_SECTOR512_BITS;
+ buf->st_blksize = fs_info->fat.vol.bps;
+ buf->st_mtime = fat_fd->mtime;
+
+ rtems_semaphore_release(fs_info->vol_sema);
+ return RC_OK;
+}
+
+/* msdos_file_ftruncate --
+ * Truncate the file (if new length is greater then current do nothing).
+ *
+ * PARAMETERS:
+ * iop - file control block
+ * length - new length
+ *
+ * RETURNS:
+ * RC_OK on success, or -1 if error occured (errno set appropriately).
+ */
+int
+msdos_file_ftruncate(rtems_libio_t *iop, off_t length)
+{
+ int rc = RC_OK;
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info;
+ fat_file_fd_t *fat_fd = iop->file_info;
+
+ if (length >= fat_fd->fat_file_size)
+ return RC_OK;
+
+ sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
+ MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one(EIO);
+
+ rc = fat_file_truncate(iop->pathinfo.mt_entry, fat_fd, length);
+ if (rc != RC_OK)
+ {
+ rtems_semaphore_release(fs_info->vol_sema);
+ return rc;
+ }
+
+ /*
+ * fat_file_truncate do nothing if new length >= fat-file size, so update
+ * file size only if length < fat-file size
+ */
+ if (length < fat_fd->fat_file_size)
+ iop->size = fat_fd->fat_file_size = length;
+
+ rtems_semaphore_release(fs_info->vol_sema);
+ return RC_OK;
+}
+
+/* msdos_file_sync --
+ * Synchronize file - synchronize file data and if file is not removed
+ * synchronize file metadata.
+ *
+ * PARAMETERS:
+ * iop - file control block
+ *
+ * RETURNS:
+ * RC_OK on success, or -1 if error occured (errno set appropriately)
+ */
+int
+msdos_file_sync(rtems_libio_t *iop)
+{
+ int rc = RC_OK;
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ fat_file_fd_t *fat_fd = iop->file_info;
+ msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info;
+
+ sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
+ MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one(EIO);
+
+ /* synchronize file data */
+ rc = fat_file_datasync(iop->pathinfo.mt_entry, fat_fd);
+ if (rc != RC_OK)
+ {
+ rtems_semaphore_release(fs_info->vol_sema);
+ return rc;
+ }
+
+ /*
+ * if fat-file descriptor is not marked "removed" - synchronize file
+ * metadata
+ */
+ if (!FAT_FILE_IS_REMOVED(fat_fd))
+ {
+ rc = msdos_set_first_cluster_num(iop->pathinfo.mt_entry, fat_fd);
+ if (rc != RC_OK)
+ {
+ rtems_semaphore_release(fs_info->vol_sema);
+ return rc;
+ }
+ rc = msdos_set_file_size(iop->pathinfo.mt_entry, fat_fd);
+ if (rc != RC_OK)
+ {
+ rtems_semaphore_release(fs_info->vol_sema);
+ return rc;
+ }
+ rc = msdos_set_dir_wrt_time_and_date(iop->pathinfo.mt_entry, fat_fd);
+ if (rc != RC_OK)
+ {
+ rtems_semaphore_release(fs_info->vol_sema);
+ return rc;
+ }
+ }
+
+ rtems_semaphore_release(fs_info->vol_sema);
+ return RC_OK;
+}
+
+/* msdos_file_datasync --
+ * Synchronize file - synchronize only file data (metadata is letf intact).
+ *
+ * PARAMETERS:
+ * iop - file control block
+ *
+ * RETURNS:
+ * RC_OK on success, or -1 if error occured (errno set appropriately)
+ */
+int
+msdos_file_datasync(rtems_libio_t *iop)
+{
+ int rc = RC_OK;
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ fat_file_fd_t *fat_fd = iop->file_info;
+ msdos_fs_info_t *fs_info = iop->pathinfo.mt_entry->fs_info;
+
+ sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
+ MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one(EIO);
+
+ /* synchronize file data */
+ rc = fat_file_datasync(iop->pathinfo.mt_entry, fat_fd);
+
+ rtems_semaphore_release(fs_info->vol_sema);
+ return RC_OK;
+}
+
+
+/* msdos_file_ioctl --
+ *
+ *
+ * PARAMETERS:
+ * iop - file control block
+ * ...
+ *
+ * RETURNS:
+ *
+ */
+int
+msdos_file_ioctl(rtems_libio_t *iop,uint32_t command, void *buffer)
+{
+ int rc = RC_OK;
+
+ return rc;
+}
+
+/* msdos_file_rmnod --
+ * Remove node associated with a file - set up first name character to
+ * predefined value(and write it to the disk), and mark fat-file which
+ * correspondes to the file as "removed"
+ *
+ * PARAMETERS:
+ * pathloc - node description
+ *
+ * RETURNS:
+ * RC_OK on success, or -1 if error occured (errno set appropriately)
+ */
+int
+msdos_file_rmnod(rtems_filesystem_location_info_t *pathloc)
+{
+ int rc = RC_OK;
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info;
+ fat_file_fd_t *fat_fd = pathloc->node_access;
+
+ sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
+ MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one(EIO);
+
+ /* mark file removed */
+ rc = msdos_set_first_char4file_name(pathloc->mt_entry, fat_fd->info_cln,
+ fat_fd->info_ofs,
+ MSDOS_THIS_DIR_ENTRY_EMPTY);
+ if (rc != RC_OK)
+ {
+ rtems_semaphore_release(fs_info->vol_sema);
+ return rc;
+ }
+
+ fat_file_mark_removed(pathloc->mt_entry, fat_fd);
+
+ rtems_semaphore_release(fs_info->vol_sema);
+ return RC_OK;
+}
diff --git a/cpukit/libfs/src/dosfs/msdos_free.c b/cpukit/libfs/src/dosfs/msdos_free.c
new file mode 100644
index 0000000000..2fb74e2387
--- /dev/null
+++ b/cpukit/libfs/src/dosfs/msdos_free.c
@@ -0,0 +1,56 @@
+/*
+ * Free node handler implementation for the filesystem
+ * operations table.
+ *
+ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * @(#) $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/libio_.h>
+
+#include <errno.h>
+
+#include "fat.h"
+#include "fat_fat_operations.h"
+#include "fat_file.h"
+
+#include "msdos.h"
+
+/* msdos_free_node_info --
+ * Call fat-file close routine.
+ *
+ * PARAMETERS:
+ * pathloc - node description
+ *
+ * RETURNS:
+ * RC_OK on success, or -1 code if error occured
+ *
+ */
+int
+msdos_free_node_info(rtems_filesystem_location_info_t *pathloc)
+{
+ int rc = RC_OK;
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info;
+
+ sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
+ MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one(EIO);
+
+ rc = fat_file_close(pathloc->mt_entry, pathloc->node_access);
+
+ rtems_semaphore_release(fs_info->vol_sema);
+ return rc;
+}
diff --git a/cpukit/libfs/src/dosfs/msdos_fsunmount.c b/cpukit/libfs/src/dosfs/msdos_fsunmount.c
new file mode 100644
index 0000000000..bd978179e2
--- /dev/null
+++ b/cpukit/libfs/src/dosfs/msdos_fsunmount.c
@@ -0,0 +1,71 @@
+/*
+ * MSDOS shut down handler implementation
+ *
+ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * @(#) $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <assert.h>
+#include <rtems.h>
+#include <rtems/libio_.h>
+
+#include "fat.h"
+#include "fat_fat_operations.h"
+#include "fat_file.h"
+
+#include "msdos.h"
+
+/* msdos_shut_down --
+ * Shut down MSDOS filesystem - free all allocated resources (don't
+ * return if deallocation of some resource failed - free as much as
+ * possible).
+ *
+ * PARAMETERS:
+ * temp_mt_entry - mount table entry
+ *
+ * RETURNS:
+ * RC_OK on success, or -1 if error occured (errno set apropriately).
+ *
+ */
+int
+msdos_shut_down(rtems_filesystem_mount_table_entry_t *temp_mt_entry)
+{
+ int rc = RC_OK;
+ msdos_fs_info_t *fs_info = temp_mt_entry->fs_info;
+ fat_file_fd_t *fat_fd = temp_mt_entry->mt_fs_root.node_access;
+
+ /* close fat-file which correspondes to root directory */
+ if (fat_file_close(temp_mt_entry, fat_fd) != RC_OK)
+ {
+ /* no return - try to free as much as possible */
+ rc = -1;
+ }
+
+ if (fat_shutdown_drive(temp_mt_entry) != RC_OK)
+ {
+ /* no return - try to free as much as possible */
+ rc = -1;
+ }
+
+ rtems_semaphore_delete(fs_info->vol_sema);
+ free(fs_info->cl_buf);
+ free(temp_mt_entry->fs_info);
+
+ return rc;
+}
diff --git a/cpukit/libfs/src/dosfs/msdos_handlers_dir.c b/cpukit/libfs/src/dosfs/msdos_handlers_dir.c
new file mode 100644
index 0000000000..4a6d098b8e
--- /dev/null
+++ b/cpukit/libfs/src/dosfs/msdos_handlers_dir.c
@@ -0,0 +1,36 @@
+/*
+ * Directory Handlers Table for MSDOS filesystem
+ *
+ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * @(#) $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/libio.h>
+#include "msdos.h"
+
+rtems_filesystem_file_handlers_r msdos_dir_handlers = {
+ msdos_dir_open,
+ msdos_dir_close,
+ msdos_dir_read,
+ NULL, /* msdos_dir_write */
+ NULL, /* msdos_dir_ioctl */
+ msdos_dir_lseek,
+ msdos_dir_stat,
+ NULL,
+ NULL, /* msdos_dir_ftruncate */
+ NULL,
+ msdos_dir_sync,
+ msdos_dir_sync,
+ NULL, /* msdos_dir_fcntl */
+ msdos_dir_rmnod
+};
diff --git a/cpukit/libfs/src/dosfs/msdos_handlers_file.c b/cpukit/libfs/src/dosfs/msdos_handlers_file.c
new file mode 100644
index 0000000000..857c5ad7a6
--- /dev/null
+++ b/cpukit/libfs/src/dosfs/msdos_handlers_file.c
@@ -0,0 +1,36 @@
+/*
+ * File Operations Table for MSDOS filesystem
+ *
+ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * @(#) $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/libio.h>
+#include "msdos.h"
+
+rtems_filesystem_file_handlers_r msdos_file_handlers = {
+ msdos_file_open,
+ msdos_file_close,
+ msdos_file_read,
+ msdos_file_write,
+ msdos_file_ioctl,
+ msdos_file_lseek,
+ msdos_file_stat,
+ NULL,
+ msdos_file_ftruncate,
+ NULL,
+ msdos_file_sync,
+ msdos_file_datasync,
+ NULL, /* msdos_file_fcntl */
+ msdos_file_rmnod
+};
diff --git a/cpukit/libfs/src/dosfs/msdos_init.c b/cpukit/libfs/src/dosfs/msdos_init.c
new file mode 100644
index 0000000000..f09f8d7291
--- /dev/null
+++ b/cpukit/libfs/src/dosfs/msdos_init.c
@@ -0,0 +1,64 @@
+/*
+ * Init routine for MSDOS
+ *
+ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * @(#) $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/libio_.h>
+#include "msdos.h"
+
+rtems_filesystem_operations_table msdos_ops = {
+ msdos_eval_path,
+ msdos_eval4make,
+#if 0
+ NULL, /* msdos_link */
+#else
+ msdos_file_link, /* msdos_link (pseudo-functionality) */
+#endif
+ msdos_file_rmnod,
+ msdos_node_type,
+ msdos_mknod,
+ NULL, /* msdos_chown */
+ msdos_free_node_info,
+ NULL,
+ msdos_initialize,
+ NULL,
+ msdos_shut_down, /* msdos_shut_down */
+ NULL, /* msdos_utime */
+ NULL,
+ NULL,
+ NULL
+};
+
+/* msdos_initialize --
+ * MSDOS filesystem initialization
+ *
+ * PARAMETERS:
+ * temp_mt_entry - mount table entry
+ *
+ * RETURNS:
+ * RC_OK on success, or -1 if error occured (errno set apropriately).
+ *
+ */
+int
+msdos_initialize(rtems_filesystem_mount_table_entry_t *temp_mt_entry)
+{
+ int rc = RC_OK;
+
+ rc = msdos_initialize_support(temp_mt_entry,
+ &msdos_ops,
+ &msdos_file_handlers,
+ &msdos_dir_handlers);
+ return rc;
+}
diff --git a/cpukit/libfs/src/dosfs/msdos_initsupp.c b/cpukit/libfs/src/dosfs/msdos_initsupp.c
new file mode 100644
index 0000000000..006fb38d09
--- /dev/null
+++ b/cpukit/libfs/src/dosfs/msdos_initsupp.c
@@ -0,0 +1,149 @@
+/*
+ * MSDOS Initialization support routine implementation
+ *
+ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * @(#) $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <assert.h>
+#include <rtems.h>
+#include <rtems/libio_.h>
+
+#include "fat.h"
+#include "fat_fat_operations.h"
+#include "fat_file.h"
+
+#include "msdos.h"
+
+/* msdos_initialize_support --
+ * MSDOS filesystem initialization
+ *
+ * PARAMETERS:
+ * temp_mt_entry - mount table entry
+ * op_table - filesystem operations table
+ * file_handlers - file operations table
+ * directory_handlers - directory operations table
+ *
+ * RETURNS:
+ * RC_OK and filled temp_mt_entry on success, or -1 if error occured
+ * (errno set apropriately)
+ *
+ */
+int
+msdos_initialize_support(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry,
+ rtems_filesystem_operations_table *op_table,
+ rtems_filesystem_file_handlers_r *file_handlers,
+ rtems_filesystem_file_handlers_r *directory_handlers
+ )
+{
+ int rc = RC_OK;
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ msdos_fs_info_t *fs_info = NULL;
+ fat_file_fd_t *fat_fd = NULL;
+ uint32_t cl_buf_size;
+
+ fs_info = (msdos_fs_info_t *)calloc(1, sizeof(msdos_fs_info_t));
+ if (!fs_info)
+ set_errno_and_return_minus_one(ENOMEM);
+
+ temp_mt_entry->fs_info = fs_info;
+
+ rc = fat_init_volume_info(temp_mt_entry);
+ if (rc != RC_OK)
+ {
+ free(fs_info);
+ return rc;
+ }
+
+ fs_info->file_handlers = file_handlers;
+ fs_info->directory_handlers = directory_handlers;
+
+ /*
+ * open fat-file which correspondes to root directory
+ * (so inode number 0x00000010 is always used for root directory)
+ */
+ rc = fat_file_open(temp_mt_entry, FAT_ROOTDIR_CLUSTER_NUM, 0, &fat_fd);
+ if (rc != RC_OK)
+ {
+ fat_shutdown_drive(temp_mt_entry);
+ free(fs_info);
+ return rc;
+ }
+
+ /* again: unfortunately "fat-file" is just almost fat file :( */
+ fat_fd->fat_file_type = FAT_DIRECTORY;
+ fat_fd->size_limit = MSDOS_MAX_DIR_LENGHT;
+ fat_fd->info_cln = FAT_ROOTDIR_CLUSTER_NUM;
+ fat_fd->info_ofs = 0;
+ fat_fd->cln = fs_info->fat.vol.rdir_cl;
+
+ fat_fd->map.file_cln = 0;
+ fat_fd->map.disk_cln = fat_fd->cln;
+
+ /* if we have FAT12/16 */
+ if ( fat_fd->cln == 0 )
+ {
+ fat_fd->fat_file_size = fs_info->fat.vol.rdir_size;
+ cl_buf_size = (fs_info->fat.vol.bpc > fs_info->fat.vol.rdir_size) ?
+ fs_info->fat.vol.bpc :
+ fs_info->fat.vol.rdir_size;
+ }
+ else
+ {
+ rc = fat_file_size(temp_mt_entry, fat_fd);
+ if ( rc != RC_OK )
+ {
+ fat_file_close(temp_mt_entry, fat_fd);
+ fat_shutdown_drive(temp_mt_entry);
+ free(fs_info);
+ return rc;
+ }
+ cl_buf_size = fs_info->fat.vol.bpc;
+ }
+
+ fs_info->cl_buf = (char *)calloc(cl_buf_size, sizeof(char));
+ if (fs_info->cl_buf == NULL)
+ {
+ fat_file_close(temp_mt_entry, fat_fd);
+ fat_shutdown_drive(temp_mt_entry);
+ free(fs_info);
+ set_errno_and_return_minus_one(ENOMEM);
+ }
+
+ sc = rtems_semaphore_create(3,
+ 1,
+ RTEMS_BINARY_SEMAPHORE | RTEMS_FIFO,
+ 0,
+ &fs_info->vol_sema);
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fat_file_close(temp_mt_entry, fat_fd);
+ fat_shutdown_drive(temp_mt_entry);
+ free(fs_info->cl_buf);
+ free(fs_info);
+ set_errno_and_return_minus_one( EIO );
+ }
+
+ temp_mt_entry->mt_fs_root.node_access = fat_fd;
+ temp_mt_entry->mt_fs_root.handlers = directory_handlers;
+ temp_mt_entry->mt_fs_root.ops = op_table;
+
+ return rc;
+}
diff --git a/cpukit/libfs/src/dosfs/msdos_misc.c b/cpukit/libfs/src/dosfs/msdos_misc.c
new file mode 100644
index 0000000000..7274fddaef
--- /dev/null
+++ b/cpukit/libfs/src/dosfs/msdos_misc.c
@@ -0,0 +1,942 @@
+/*
+ * Miscellaneous routines implementation for MSDOS filesystem
+ *
+ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * @(#) $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <string.h>
+#include <assert.h>
+#include <rtems/libio_.h>
+
+#include "fat.h"
+#include "fat_fat_operations.h"
+#include "fat_file.h"
+
+#include "msdos.h"
+
+/* msdos_get_token --
+ * Routine to get a token (name or separator) from the path.
+ *
+ * PARAMETERS:
+ * path - path to get token from
+ * ret_token - returned token
+ * token_len - length of returned token
+ *
+ * RETURNS:
+ * token type, token and token length
+ *
+ */
+msdos_token_types_t
+msdos_get_token(const char *path, char *ret_token, int *token_len)
+{
+ int rc = RC_OK;
+ register int i = 0;
+ msdos_token_types_t type = MSDOS_NAME;
+ char token[MSDOS_NAME_MAX_WITH_DOT+1];
+ register char c;
+
+ /*
+ * Copy a name into token. (Remember NULL is a token.)
+ */
+ c = path[i];
+ while ( (!msdos_is_separator(c)) && (i <= MSDOS_NAME_MAX_WITH_DOT) )
+ {
+ token[i] = c;
+ if ( i == MSDOS_NAME_MAX_WITH_DOT )
+ return MSDOS_INVALID_TOKEN;
+ if ( !msdos_is_valid_name_char(c) )
+ return MSDOS_INVALID_TOKEN;
+ c = path [++i];
+ }
+
+ /*
+ * Copy a seperator into token.
+ */
+ if ( i == 0 )
+ {
+ token[i] = c;
+ if ( token[i] != '\0' )
+ {
+ i++;
+ type = MSDOS_CURRENT_DIR;
+ }
+ else
+ type = MSDOS_NO_MORE_PATH;
+ }
+ else if (token[ i-1 ] != '\0')
+ token[i] = '\0';
+
+ /*
+ * Set token_len to the number of characters copied.
+ */
+ *token_len = i;
+
+ /*
+ * If we copied something that was not a seperator see if
+ * it was a special name.
+ */
+ if ( type == MSDOS_NAME )
+ {
+ if ( strcmp( token, "..") == 0 )
+ {
+ strcpy(ret_token, MSDOS_DOTDOT_NAME);
+ type = MSDOS_UP_DIR;
+ return type;
+ }
+
+ if ( strcmp( token, "." ) == 0 )
+ {
+ strcpy(ret_token, MSDOS_DOT_NAME);
+ type = MSDOS_CURRENT_DIR;
+ return type;
+ }
+
+ rc = msdos_filename_unix2dos(token, *token_len, ret_token);
+ if ( rc != RC_OK )
+ return MSDOS_INVALID_TOKEN;
+ }
+ ret_token[MSDOS_NAME_MAX] = '\0';
+ return type;
+}
+
+
+/* msdos_find_name --
+ * Find the node which correspondes to the name, open fat-file which
+ * correspondes to the found node and close fat-file which correspondes
+ * to the node we searched in.
+ *
+ * PARAMETERS:
+ * parent_loc - parent node description
+ * name - name to find
+ *
+ * RETURNS:
+ * RC_OK and updated 'parent_loc' on success, or -1 if error
+ * occured (errno set apropriately)
+ *
+ */
+int
+msdos_find_name(
+ rtems_filesystem_location_info_t *parent_loc,
+ char *name
+ )
+{
+ int rc = RC_OK;
+ msdos_fs_info_t *fs_info = parent_loc->mt_entry->fs_info;
+ fat_file_fd_t *fat_fd = NULL;
+ fat_auxiliary_t aux;
+ unsigned short time_val = 0;
+ unsigned short date = 0;
+ unsigned char node_entry[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
+
+ memset(node_entry, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
+
+ /*
+ * find the node which correspondes to the name in the directory pointed by
+ * 'parent_loc'
+ */
+ rc = msdos_get_name_node(parent_loc, name, &aux, node_entry);
+ if (rc != RC_OK)
+ return rc;
+
+ /* open fat-file corresponded to the found node */
+ rc = fat_file_open(parent_loc->mt_entry, aux.cln, aux.ofs, &fat_fd);
+ if (rc != RC_OK)
+ return rc;
+
+ /*
+ * I don't like this if, but: we should do it , or should write new file
+ * size and first cluster num to the disk after each write operation
+ * (even if one byte is written - that is TOO non-optimize) because
+ * otherwise real values of these fields stored in fat-file descriptor
+ * may be accidentely rewritten with wrong values stored on the disk
+ */
+ if (fat_fd->links_num == 1)
+ {
+ fat_fd->info_cln = aux.cln;
+ fat_fd->info_ofs = aux.ofs;
+ fat_fd->cln = MSDOS_EXTRACT_CLUSTER_NUM(node_entry);
+ fat_fd->first_char = *MSDOS_DIR_NAME(node_entry);
+
+ time_val = *MSDOS_DIR_WRITE_TIME(node_entry);
+ date = *MSDOS_DIR_WRITE_DATE(node_entry);
+
+ fat_fd->mtime = msdos_date_dos2unix(CF_LE_W(time_val), CF_LE_W(date));
+
+ if ((*MSDOS_DIR_ATTR(node_entry)) & MSDOS_ATTR_DIRECTORY)
+ {
+ fat_fd->fat_file_type = FAT_DIRECTORY;
+ fat_fd->size_limit = MSDOS_MAX_DIR_LENGHT;
+
+ rc = fat_file_size(parent_loc->mt_entry, fat_fd);
+ if (rc != RC_OK)
+ {
+ fat_file_close(parent_loc->mt_entry, fat_fd);
+ return rc;
+ }
+ }
+ else
+ {
+ fat_fd->fat_file_size = CF_LE_L(*MSDOS_DIR_FILE_SIZE(node_entry));
+ fat_fd->fat_file_type = FAT_FILE;
+ fat_fd->size_limit = MSDOS_MAX_FILE_SIZE;
+ }
+
+ /* these data is not actual for zero-length fat-file */
+ fat_fd->map.file_cln = 0;
+ fat_fd->map.disk_cln = fat_fd->cln;
+
+ if ((fat_fd->fat_file_size != 0) &&
+ (fat_fd->fat_file_size <= fs_info->fat.vol.bpc))
+ {
+ fat_fd->map.last_cln = fat_fd->cln;
+ }
+ else
+ {
+ fat_fd->map.last_cln = FAT_UNDEFINED_VALUE;
+ }
+ }
+
+ /* close fat-file corresponded to the node we searched in */
+ rc = fat_file_close(parent_loc->mt_entry, parent_loc->node_access);
+ if (rc != RC_OK)
+ {
+ fat_file_close(parent_loc->mt_entry, fat_fd);
+ return rc;
+ }
+
+ /* update node_info_ptr field */
+ parent_loc->node_access = fat_fd;
+
+ return rc;
+}
+
+/* msdos_get_name_node --
+ * This routine is used in two ways: for a new mode creation (a) or for
+ * search the node which correspondes to the name parameter (b).
+ * In case (a) 'name' should be set up to NULL and 'name_dir_entry' should
+ * point to initialized 32 bytes structure described a new node.
+ * In case (b) 'name' should contain a valid string.
+ *
+ * (a): reading fat-file which correspondes to directory we are going to
+ * create node in. If free slot is found write contents of
+ * 'name_dir_entry' into it. If reach end of fat-file and no free
+ * slot found, write 32 bytes to the end of fat-file.
+ *
+ * (b): reading fat-file which correspondes to directory and trying to
+ * find slot with the name field == 'name' parameter
+ *
+ *
+ * PARAMETERS:
+ * parent_loc - node description to create node in or to find name in
+ * name - NULL or name to find
+ * paux - identify a node location on the disk -
+ * cluster num and offset inside the cluster
+ * name_dir_entry - node to create/placeholder for found node (IN/OUT)
+ *
+ * RETURNS:
+ * RC_OK, filled aux_struct_ptr and name_dir_entry on success, or -1 if
+ * error occured (errno set apropriately)
+ *
+ */
+int
+msdos_get_name_node(
+ rtems_filesystem_location_info_t *parent_loc,
+ char *name,
+ fat_auxiliary_t *paux,
+ char *name_dir_entry
+ )
+{
+ int rc = RC_OK;
+ ssize_t ret = 0;
+ msdos_fs_info_t *fs_info = parent_loc->mt_entry->fs_info;
+ fat_file_fd_t *fat_fd = parent_loc->node_access;
+ uint32_t dotdot_cln = 0;
+
+ /* find name in fat-file which correspondes to the directory */
+ rc = msdos_find_name_in_fat_file(parent_loc->mt_entry, fat_fd, name, paux,
+ name_dir_entry);
+ if ((rc != RC_OK) && (rc != MSDOS_NAME_NOT_FOUND_ERR))
+ return rc;
+
+ /* if we search for valid name and name not found -> return */
+ if ((rc == MSDOS_NAME_NOT_FOUND_ERR) && (name != NULL))
+ return rc;
+
+ /*
+ * if we try to create new entry and the directory is not big enough
+ * currently - try to enlarge directory
+ */
+ if ((rc == MSDOS_NAME_NOT_FOUND_ERR) && (name == NULL))
+ {
+ ret = fat_file_write(parent_loc->mt_entry, fat_fd,
+ fat_fd->fat_file_size,
+ MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE,
+ name_dir_entry);
+ if (ret == -1)
+ return -1;
+
+ /* on success directory is enlarged by a new cluster */
+ fat_fd->fat_file_size += fs_info->fat.vol.bpc;
+
+ /* get cluster num where a new node located */
+ rc = fat_file_ioctl(parent_loc->mt_entry, fat_fd, F_CLU_NUM,
+ fat_fd->fat_file_size - 1, &paux->cln);
+
+ if (rc != RC_OK)
+ return rc;
+
+ /*
+ * if new cluster allocated succesfully then new node is at very
+ * beginning of the cluster (offset is computed in bytes)
+ */
+ paux->ofs = 0;
+ return RC_OK;
+ }
+
+ /*
+ * if we have deal with ".." - it is a special case :(((
+ *
+ * Really, we should return cluster num and offset not of ".." slot, but
+ * slot which correspondes to real directory name.
+ */
+ if ((rc == RC_OK) && (name != NULL))
+ {
+ if (strncmp(name, MSDOS_DOTDOT_NAME, MSDOS_SHORT_NAME_LEN) == 0)
+ {
+ dotdot_cln = MSDOS_EXTRACT_CLUSTER_NUM((name_dir_entry));
+
+ /* are we right under root dir ? */
+ if (dotdot_cln == 0)
+ {
+ /*
+ * we can relax about first_char field - it never should be
+ * used for root dir
+ */
+ paux->cln = FAT_ROOTDIR_CLUSTER_NUM;
+ paux->ofs = 0;
+ }
+ else
+ {
+ rc = msdos_get_dotdot_dir_info_cluster_num_and_offset(
+ parent_loc->mt_entry,
+ dotdot_cln,
+ paux,
+ name_dir_entry
+ );
+ if (rc != RC_OK)
+ return rc;
+ }
+ }
+ }
+ return rc;
+}
+
+/*
+ * msdos_get_dotdot_dir_info_cluster_num_and_offset
+ *
+ * Unfortunately, in general, we cann't work here in fat-file ideologic
+ * (open fat_file "..", get ".." and ".", open "..", find an entry ...)
+ * because if we open
+ * fat-file ".." it may happend that we have two different fat-file
+ * descriptors ( for real name of directory and ".." name ) for a single
+ * file ( cluster num of both pointers to the same cluster )
+ * But...we do it because we protected by semaphore
+ *
+ */
+
+/* msdos_get_dotdot_dir_info_cluster_num_and_offset --
+ * Get cluster num and offset not of ".." slot, but slot which correspondes
+ * to real directory name.
+ *
+ * PARAMETERS:
+ * mt_entry - mount table entry
+ * cln - data cluster num extracted drom ".." slot
+ * paux - identify a node location on the disk -
+ * number of cluster and offset inside the cluster
+ * dir_entry - placeholder for found node
+ *
+ * RETURNS:
+ * RC_OK, filled 'paux' and 'dir_entry' on success, or -1 if error occured
+ * (errno set apropriately)
+ *
+ */
+int
+msdos_get_dotdot_dir_info_cluster_num_and_offset(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ uint32_t cln,
+ fat_auxiliary_t *paux,
+ char *dir_entry
+ )
+{
+ int rc = RC_OK;
+ msdos_fs_info_t *fs_info = mt_entry->fs_info;
+ fat_file_fd_t *fat_fd = NULL;
+ unsigned char dot_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
+ unsigned char dotdot_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
+ unsigned char cur_node[MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE];
+ uint32_t cl4find = 0;
+
+ memset(dot_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
+ memset(dotdot_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
+ memset(cur_node, 0, MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
+
+ /*
+ * open fat-file corresponded to ".."
+ */
+ rc = fat_file_open(mt_entry, paux->cln, paux->ofs, &fat_fd);
+ if (rc != RC_OK)
+ return rc;
+
+ fat_fd->info_cln = paux->cln;
+ fat_fd->info_ofs = paux->ofs;
+ fat_fd->cln = cln;
+ fat_fd->fat_file_type = FAT_DIRECTORY;
+ fat_fd->size_limit = MSDOS_MAX_DIR_LENGHT;
+
+ fat_fd->map.file_cln = 0;
+ fat_fd->map.disk_cln = fat_fd->cln;
+
+ rc = fat_file_size(mt_entry, fat_fd);
+ if (rc != RC_OK)
+ {
+ fat_file_close(mt_entry, fat_fd);
+ return rc;
+ }
+
+ /* find "." node in opened directory */
+ rc = msdos_find_name_in_fat_file(mt_entry, fat_fd, MSDOS_DOT_NAME, paux,
+ dot_node);
+
+ if (rc != RC_OK)
+ {
+ fat_file_close(mt_entry, fat_fd);
+ return rc;
+ }
+
+ /* find ".." node in opened directory */
+ rc = msdos_find_name_in_fat_file(mt_entry, fat_fd, MSDOS_DOTDOT_NAME, paux,
+ dotdot_node);
+
+ if (rc != RC_OK)
+ {
+ fat_file_close(mt_entry, fat_fd);
+ return rc;
+ }
+
+ cl4find = MSDOS_EXTRACT_CLUSTER_NUM(dot_node);
+
+ /* close fat-file corresponded to ".." directory */
+ rc = fat_file_close(mt_entry, fat_fd);
+ if ( rc != RC_OK )
+ return rc;
+
+ if ( (MSDOS_EXTRACT_CLUSTER_NUM(dotdot_node)) == 0)
+ {
+ /*
+ * we handle root dir for all FAT types in the same way with the
+ * ordinary directories ( through fat_file_* calls )
+ */
+ paux->cln = FAT_ROOTDIR_CLUSTER_NUM;
+ paux->ofs = 0;
+ }
+
+ /* open fat-file corresponded to second ".." */
+ rc = fat_file_open(mt_entry, paux->cln, paux->ofs, &fat_fd);
+ if (rc != RC_OK)
+ return rc;
+
+ fat_fd->info_cln = paux->cln;
+ fat_fd->info_ofs = paux->ofs;
+
+ if ((MSDOS_EXTRACT_CLUSTER_NUM(dotdot_node)) == 0)
+ fat_fd->cln = fs_info->fat.vol.rdir_cl;
+ else
+ fat_fd->cln = MSDOS_EXTRACT_CLUSTER_NUM(dotdot_node);
+
+ fat_fd->fat_file_type = FAT_DIRECTORY;
+ fat_fd->size_limit = MSDOS_MAX_DIR_LENGHT;
+
+ fat_fd->map.file_cln = 0;
+ fat_fd->map.disk_cln = fat_fd->cln;
+
+ rc = fat_file_size(mt_entry, fat_fd);
+ if (rc != RC_OK)
+ {
+ fat_file_close(mt_entry, fat_fd);
+ return rc;
+ }
+
+ /* in this directory find slot with specified cluster num */
+ rc = msdos_find_node_by_cluster_num_in_fat_file(mt_entry, fat_fd, cl4find,
+ paux, dir_entry);
+ if (rc != RC_OK)
+ {
+ fat_file_close(mt_entry, fat_fd);
+ return rc;
+ }
+ rc = fat_file_close(mt_entry, fat_fd);
+ return rc;
+}
+
+
+/* msdos_set_dir_wrt_time_and_date --
+ * Write last write date and time for a file to the disk (to corresponded
+ * 32bytes node)
+ *
+ * PARAMETERS:
+ * mt_entry - mount table entry
+ * fat_fd - fat-file descriptor
+ *
+ * RETURNS:
+ * RC_OK on success, or -1 if error occured (errno set apropriately).
+ *
+ */
+int
+msdos_set_dir_wrt_time_and_date(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ fat_file_fd_t *fat_fd
+ )
+{
+ ssize_t ret1 = 0, ret2 = 0;
+ msdos_fs_info_t *fs_info = mt_entry->fs_info;
+ unsigned short time_val;
+ unsigned short date;
+ uint32_t sec = 0;
+ uint32_t byte = 0;
+
+ msdos_date_unix2dos(fat_fd->mtime, &time_val, &date);
+
+ /*
+ * calculate input for _fat_block_write: convert (cluster num, offset) to
+ * (sector num, new offset)
+ */
+ sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->info_cln);
+ sec += (fat_fd->info_ofs >> fs_info->fat.vol.sec_log2);
+ /* byte points to start of 32bytes structure */
+ byte = fat_fd->info_ofs & (fs_info->fat.vol.bps - 1);
+
+ time_val = CT_LE_W(time_val);
+ ret1 = _fat_block_write(mt_entry, sec, byte + MSDOS_FILE_WTIME_OFFSET,
+ 2, (char *)(&time_val));
+ date = CT_LE_W(date);
+ ret2 = _fat_block_write(mt_entry, sec, byte + MSDOS_FILE_WDATE_OFFSET,
+ 2, (char *)(&date));
+
+ if ( (ret1 < 0) || (ret2 < 0) )
+ return -1;
+
+ return RC_OK;
+}
+
+/* msdos_set_first_cluster_num --
+ * Write number of first cluster of the file to the disk (to corresponded
+ * 32bytes slot)
+ *
+ * PARAMETERS:
+ * mt_entry - mount table entry
+ * fat_fd - fat-file descriptor
+ *
+ * RETURNS:
+ * RC_OK on success, or -1 if error occured
+ *
+ */
+int
+msdos_set_first_cluster_num(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ fat_file_fd_t *fat_fd
+ )
+{
+ ssize_t ret1 = 0, ret2 = 0;
+ msdos_fs_info_t *fs_info = mt_entry->fs_info;
+ uint32_t new_cln = fat_fd->cln;
+ uint16_t le_cl_low = 0;
+ uint16_t le_cl_hi = 0;
+ uint32_t sec = 0;
+ uint32_t byte = 0;
+
+ /*
+ * calculate input for _fat_block_write: convert (cluster num, offset) to
+ * (sector num, new offset)
+ */
+ sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->info_cln);
+ sec += (fat_fd->info_ofs >> fs_info->fat.vol.sec_log2);
+ /* byte from points to start of 32bytes structure */
+ byte = fat_fd->info_ofs & (fs_info->fat.vol.bps - 1);
+
+ le_cl_low = CT_LE_W((uint16_t )(new_cln & 0x0000FFFF));
+ ret1 = _fat_block_write(mt_entry, sec,
+ byte + MSDOS_FIRST_CLUSTER_LOW_OFFSET, 2,
+ (char *)(&le_cl_low));
+ le_cl_hi = CT_LE_W((uint16_t )((new_cln & 0xFFFF0000) >> 16));
+ ret2 = _fat_block_write(mt_entry, sec,
+ byte + MSDOS_FIRST_CLUSTER_HI_OFFSET, 2,
+ (char *)(&le_cl_hi));
+ if ( (ret1 < 0) || (ret2 < 0) )
+ return -1;
+
+ return RC_OK;
+}
+
+
+/* msdos_set_file size --
+ * Write file size of the file to the disk (to corresponded 32bytes slot)
+ *
+ * PARAMETERS:
+ * mt_entry - mount table entry
+ * fat_fd - fat-file descriptor
+ *
+ * RETURNS:
+ * RC_OK on success, or -1 if error occured (errno set apropriately).
+ *
+ */
+int
+msdos_set_file_size(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ fat_file_fd_t *fat_fd
+ )
+{
+ ssize_t ret = 0;
+ msdos_fs_info_t *fs_info = mt_entry->fs_info;
+ uint32_t le_new_length = 0;
+ uint32_t sec = 0;
+ uint32_t byte = 0;
+
+ sec = fat_cluster_num_to_sector_num(mt_entry, fat_fd->info_cln);
+ sec += (fat_fd->info_ofs >> fs_info->fat.vol.sec_log2);
+ byte = (fat_fd->info_ofs & (fs_info->fat.vol.bps - 1));
+
+ le_new_length = CT_LE_L((fat_fd->fat_file_size));
+ ret = _fat_block_write(mt_entry, sec, byte + MSDOS_FILE_SIZE_OFFSET, 4,
+ (char *)(&le_new_length));
+ if ( ret < 0 )
+ return -1;
+
+ return RC_OK;
+}
+
+/*
+ * We should not check whether this routine is called for root dir - it
+ * never can happend
+ */
+
+/* msdos_set_first_char4file_name --
+ * Write first character of the name of the file to the disk (to
+ * corresponded 32bytes slot)
+ *
+ * PARAMETERS:
+ * mt_entry - mount table entry
+ * cl - number of cluster
+ * ofs - offset inside cluster
+ * fchar - character to set up
+ *
+ * RETURNS:
+ * RC_OK on success, or -1 if error occured (errno set apropriately)
+ *
+ */
+int
+msdos_set_first_char4file_name(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ uint32_t cl,
+ uint32_t ofs,
+ unsigned char fchar
+ )
+{
+ ssize_t ret = 0;
+ msdos_fs_info_t *fs_info = mt_entry->fs_info;
+ uint32_t sec = 0;
+ uint32_t byte = 0;
+
+ sec = fat_cluster_num_to_sector_num(mt_entry, cl);
+ sec += (ofs >> fs_info->fat.vol.sec_log2);
+ byte = (ofs & (fs_info->fat.vol.bps - 1));
+
+ ret = _fat_block_write(mt_entry, sec, byte + MSDOS_FILE_NAME_OFFSET, 1,
+ &fchar);
+ if ( ret < 0)
+ return -1;
+
+ return RC_OK;
+}
+
+/* msdos_dir_is_empty --
+ * Check whether directory which correspondes to the fat-file descriptor is
+ * empty.
+ *
+ * PARAMETERS:
+ * mt_entry - mount table entry
+ * fat_fd - fat-file descriptor
+ * ret_val - placeholder for result
+ *
+ * RETURNS:
+ * RC_OK on success, or -1 if error occured
+ *
+ */
+int
+msdos_dir_is_empty(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ fat_file_fd_t *fat_fd,
+ rtems_boolean *ret_val
+ )
+{
+ ssize_t ret = 0;
+ msdos_fs_info_t *fs_info = mt_entry->fs_info;
+ uint32_t j = 0, i = 0;
+
+ /* dir is not empty */
+ *ret_val = FALSE;
+
+ while ((ret = fat_file_read(mt_entry, fat_fd, j * fs_info->fat.vol.bps,
+ fs_info->fat.vol.bps,
+ fs_info->cl_buf)) != FAT_EOF)
+ {
+ if (ret < MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
+ return -1;
+
+ assert(ret == fs_info->fat.vol.bps);
+
+ for (i = 0;
+ i < fs_info->fat.vol.bps;
+ i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
+ {
+ if (((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
+ MSDOS_THIS_DIR_ENTRY_EMPTY) ||
+ (strncmp(MSDOS_DIR_NAME((fs_info->cl_buf + i)), MSDOS_DOT_NAME,
+ MSDOS_SHORT_NAME_LEN) == 0) ||
+ (strncmp(MSDOS_DIR_NAME((fs_info->cl_buf + i)),
+ MSDOS_DOTDOT_NAME,
+ MSDOS_SHORT_NAME_LEN) == 0))
+ continue;
+
+ if ((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
+ MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY)
+ {
+ *ret_val = TRUE;
+ return RC_OK;
+ }
+ return RC_OK;
+ }
+ j++;
+ }
+ *ret_val = TRUE;
+ return RC_OK;
+}
+
+
+/* msdos_find_name_in_fat_file --
+ * This routine is used in two ways: for a new mode creation (a) or for
+ * search the node which correspondes to the 'name' parameter (b).
+ * In case (a) name should be set up to NULL and 'name_dir_entry' should
+ * point to initialized 32 bytes structure described a new node.
+ * In case (b) 'name' should contain a valid string.
+ *
+ * (a): reading fat-file corresponded to directory we are going to create
+ * node in. If found free slot write contents of name_dir_entry into
+ * it.
+ *
+ * (b): reading fat-file corresponded to directory and trying to find slot
+ * with the name field == name parameter
+ *
+ * PARAMETERS:
+ * mt_entry - mount table entry
+ * fat_fd - fat-file descriptor
+ * name - NULL or name to find
+ * paux - identify a node location on the disk -
+ * number of cluster and offset inside the cluster
+ * name_dir_entry - node to create/placeholder for found node
+ *
+ * RETURNS:
+ * RC_OK on success, or error code if error occured (errno set
+ * appropriately)
+ *
+ */
+int
+msdos_find_name_in_fat_file(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ fat_file_fd_t *fat_fd,
+ char *name,
+ fat_auxiliary_t *paux,
+ char *name_dir_entry
+ )
+{
+ int rc = RC_OK;
+ ssize_t ret = 0;
+ msdos_fs_info_t *fs_info = mt_entry->fs_info;
+ uint32_t i = 0, j = 0;
+ uint32_t bts2rd = 0;
+
+ if (FAT_FD_OF_ROOT_DIR(fat_fd) &&
+ (fs_info->fat.vol.type & (FAT_FAT12 | FAT_FAT16)))
+ bts2rd = fat_fd->fat_file_size;
+ else
+ bts2rd = fs_info->fat.vol.bpc;
+
+ while ((ret = fat_file_read(mt_entry, fat_fd, (j * bts2rd), bts2rd,
+ fs_info->cl_buf)) != FAT_EOF)
+ {
+ if (ret < MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
+ set_errno_and_return_minus_one(EIO);
+
+ assert(ret == bts2rd);
+
+ for (i = 0; i < bts2rd; i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
+ {
+ /* is the entry empty ? */
+ if (((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
+ MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY) ||
+ ((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
+ MSDOS_THIS_DIR_ENTRY_EMPTY))
+ {
+ /* whether we are looking for an empty entry */
+ if (name == NULL)
+ {
+ /* get current cluster number */
+ rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM,
+ j * bts2rd, &paux->cln);
+ if (rc != RC_OK)
+ return rc;
+
+ /* offset is computed in bytes */
+ paux->ofs = i;
+
+ /* write new node entry */
+ ret = fat_file_write(mt_entry, fat_fd, j * bts2rd + i,
+ MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE,
+ name_dir_entry);
+ if (ret != MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
+ return -1;
+
+ /*
+ * we don't update fat_file_size here - it should not
+ * increase
+ */
+ return RC_OK;
+ }
+
+ /*
+ * if name != NULL and there is no more entries in the
+ * directory - return name-not-found
+ */
+ if (((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
+ MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY))
+ return MSDOS_NAME_NOT_FOUND_ERR;
+ }
+ else
+ {
+ /* entry not empty and name != NULL -> compare names */
+ if (name != NULL)
+ {
+ if (strncmp(MSDOS_DIR_NAME((fs_info->cl_buf + i)), name,
+ MSDOS_SHORT_NAME_LEN) == 0)
+ {
+ /*
+ * we get the entry we looked for - fill auxiliary
+ * structure and copy all 32 bytes of the entry
+ */
+ rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM,
+ j * bts2rd, &paux->cln);
+ if (rc != RC_OK)
+ return rc;
+
+ /* offset is computed in bytes */
+ paux->ofs = i;
+ memcpy(name_dir_entry,(fs_info->cl_buf + i),
+ MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
+ return RC_OK;
+ }
+ }
+ }
+ }
+ j++;
+ }
+ return MSDOS_NAME_NOT_FOUND_ERR;
+}
+
+/* msdos_find_node_by_cluster_num_in_fat_file --
+ * Find node with specified number of cluster in fat-file.
+ *
+ * PARAMETERS:
+ * mt_entry - mount table entry
+ * fat_fd - fat-file descriptor
+ * cl4find - number of cluster to find
+ * paux - identify a node location on the disk -
+ * cluster num and offset inside the cluster
+ * dir_entry - placeholder for found node
+ *
+ * RETURNS:
+ * RC_OK on success, or error code if error occured
+ *
+ */
+int
+msdos_find_node_by_cluster_num_in_fat_file(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ fat_file_fd_t *fat_fd,
+ uint32_t cl4find,
+ fat_auxiliary_t *paux,
+ char *dir_entry
+ )
+{
+ int rc = RC_OK;
+ ssize_t ret = 0;
+ msdos_fs_info_t *fs_info = mt_entry->fs_info;
+ uint32_t bts2rd = 0;
+ uint32_t i = 0, j = 0;
+
+ if (FAT_FD_OF_ROOT_DIR(fat_fd) &&
+ (fs_info->fat.vol.type & (FAT_FAT12 | FAT_FAT16)))
+ bts2rd = fat_fd->fat_file_size;
+ else
+ bts2rd = fs_info->fat.vol.bpc;
+
+ while ((ret = fat_file_read(mt_entry, fat_fd, j * bts2rd, bts2rd,
+ fs_info->cl_buf)) != FAT_EOF)
+ {
+ if ( ret < MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE )
+ set_errno_and_return_minus_one( EIO );
+
+ assert(ret == bts2rd);
+
+ for (i = 0; i < bts2rd; i += MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE)
+ {
+ /* if this and all rest entries are empty - return not-found */
+ if ((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
+ MSDOS_THIS_DIR_ENTRY_AND_REST_EMPTY)
+ return MSDOS_NAME_NOT_FOUND_ERR;
+
+ /* if this entry is empty - skip it */
+ if ((*MSDOS_DIR_NAME(fs_info->cl_buf + i)) ==
+ MSDOS_THIS_DIR_ENTRY_EMPTY)
+ continue;
+
+ /* if get a non-empty entry - compare clusters num */
+ if (MSDOS_EXTRACT_CLUSTER_NUM((fs_info->cl_buf + i)) == cl4find)
+ {
+ /* on success fill aux structure and copy all 32 bytes */
+ rc = fat_file_ioctl(mt_entry, fat_fd, F_CLU_NUM, j * bts2rd,
+ &paux->cln);
+ if (rc != RC_OK)
+ return rc;
+
+ paux->ofs = i;
+ memcpy(dir_entry, fs_info->cl_buf + i,
+ MSDOS_DIRECTORY_ENTRY_STRUCT_SIZE);
+ return RC_OK;
+ }
+ }
+ j++;
+ }
+ return MSDOS_NAME_NOT_FOUND_ERR;
+}
diff --git a/cpukit/libfs/src/dosfs/msdos_mknod.c b/cpukit/libfs/src/dosfs/msdos_mknod.c
new file mode 100644
index 0000000000..a17de1ade1
--- /dev/null
+++ b/cpukit/libfs/src/dosfs/msdos_mknod.c
@@ -0,0 +1,90 @@
+/*
+ * Routine for node creation in MSDOS filesystem.
+ *
+ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * @(#) $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <rtems.h>
+
+#include <rtems/libio_.h>
+
+#include "fat.h"
+#include "fat_fat_operations.h"
+#include "fat_file.h"
+
+#include "msdos.h"
+
+/* msdos_mknod --
+ * The following function checks spelling and formats name for a new node,
+ * determines type of the node to be created and creates it.
+ *
+ * PARAMETERS:
+ * token - non-formatted name of a new node
+ * mode - node type
+ * dev - dev
+ * pathloc - parent directory description
+ *
+ * RETURNS:
+ * RC_OK on succes, or -1 if error occured and set errno
+ *
+ */
+int
+msdos_mknod(
+ const char *token,
+ mode_t mode,
+ dev_t dev,
+ rtems_filesystem_location_info_t *pathloc
+ )
+{
+ int rc = RC_OK;
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ msdos_fs_info_t *fs_info = pathloc->mt_entry->fs_info;
+ msdos_token_types_t type = 0;
+ char new_name[ MSDOS_NAME_MAX + 1 ];
+ int len;
+
+ /* check spelling and format new node name */
+ msdos_get_token(token, new_name, &len);
+
+ /*
+ * Figure out what type of msdos node this is.
+ */
+ if (S_ISDIR(mode))
+ {
+ type = MSDOS_DIRECTORY;
+ }
+ else if (S_ISREG(mode))
+ {
+ type = MSDOS_REGULAR_FILE;
+ }
+ else
+ set_errno_and_return_minus_one(EINVAL);
+
+ sc = rtems_semaphore_obtain(fs_info->vol_sema, RTEMS_WAIT,
+ MSDOS_VOLUME_SEMAPHORE_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one(EIO);
+
+ /* Create an MSDOS node */
+ rc = msdos_creat_node(pathloc, type, new_name, mode, NULL);
+
+ rtems_semaphore_release(fs_info->vol_sema);
+ return rc;
+}
diff --git a/cpukit/libfs/src/dosfs/msdos_node_type.c b/cpukit/libfs/src/dosfs/msdos_node_type.c
new file mode 100644
index 0000000000..877cf60492
--- /dev/null
+++ b/cpukit/libfs/src/dosfs/msdos_node_type.c
@@ -0,0 +1,58 @@
+/*
+ * The following returns the type of node that the loc refers to.
+ *
+ * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Eugeny S. Mints <Eugeny.Mints@oktet.ru>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * @(#) $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <rtems.h>
+
+#include <rtems/libio_.h>
+
+#include "fat.h"
+#include "fat_fat_operations.h"
+#include "fat_file.h"
+
+#include "msdos.h"
+
+/* msdos_node_type --
+ * Determine type of the node that the pathloc refers to.
+ *
+ * PARAMETERS:
+ * pathloc - node description
+ *
+ * RETURNS:
+ * node type
+ *
+ */
+rtems_filesystem_node_types_t
+msdos_node_type(rtems_filesystem_location_info_t *pathloc)
+{
+ fat_file_fd_t *fat_fd;
+
+ /*
+ * we don't need to obtain the volume semaphore here because node_type_h
+ * call always follows evalpath_h call(hence link increment occured) and
+ * hence node_access memory can't be freed during processing node_type_h
+ * call
+ */
+ fat_fd = pathloc->node_access;
+
+ return fat_fd->fat_file_type;
+}
diff --git a/cpukit/libfs/src/imfs/.cvsignore b/cpukit/libfs/src/imfs/.cvsignore
new file mode 100644
index 0000000000..c62d89f265
--- /dev/null
+++ b/cpukit/libfs/src/imfs/.cvsignore
@@ -0,0 +1,5 @@
+config.h
+config.h.in
+stamp-h
+stamp-h.in
+stamp-h1.in
diff --git a/cpukit/libfs/src/imfs/deviceio.c b/cpukit/libfs/src/imfs/deviceio.c
new file mode 100644
index 0000000000..c0758396e3
--- /dev/null
+++ b/cpukit/libfs/src/imfs/deviceio.c
@@ -0,0 +1,257 @@
+/*
+ * IMFS Device Node Handlers
+ *
+ * This file contains the set of handlers used to map operations on
+ * IMFS device nodes onto calls to the RTEMS Classic API IO Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <rtems/assoc.h> /* assoc.h not included by rtems.h */
+#include <errno.h>
+
+#include "imfs.h"
+
+/*
+ * Convert RTEMS status to a UNIX errno
+ */
+
+rtems_assoc_t errno_assoc[] = {
+ { "OK", RTEMS_SUCCESSFUL, 0 },
+ { "BUSY", RTEMS_RESOURCE_IN_USE, EBUSY },
+ { "INVALID NAME", RTEMS_INVALID_NAME, EINVAL },
+ { "NOT IMPLEMENTED", RTEMS_NOT_IMPLEMENTED, ENOSYS },
+ { "TIMEOUT", RTEMS_TIMEOUT, ETIMEDOUT },
+ { "NO MEMORY", RTEMS_NO_MEMORY, ENOMEM },
+ { "NO DEVICE", RTEMS_UNSATISFIED, ENODEV },
+ { "INVALID NUMBER", RTEMS_INVALID_NUMBER, EBADF},
+ { "NOT RESOURCE OWNER", RTEMS_NOT_OWNER_OF_RESOURCE, EPERM},
+ { "IO ERROR", RTEMS_IO_ERROR, EIO},
+ { 0, 0, 0 },
+};
+
+static int
+rtems_deviceio_errno(rtems_status_code code)
+{
+ int rc;
+
+ if ((rc = rtems_assoc_remote_by_local(errno_assoc, (uint32_t ) code)))
+ {
+ errno = rc;
+ return -1;
+ }
+ return -1;
+}
+
+/*
+ * device_open
+ *
+ * This handler maps an open() operation onto rtems_io_open().
+ */
+
+int device_open(
+ rtems_libio_t *iop,
+ const char *pathname,
+ uint32_t flag,
+ uint32_t mode
+)
+{
+ rtems_libio_open_close_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ args.iop = iop;
+ args.flags = iop->flags;
+ args.mode = mode;
+
+ status = rtems_io_open(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+ if ( status )
+ return rtems_deviceio_errno(status);
+
+ return 0;
+}
+
+/*
+ * device_close
+ *
+ * This handler maps a close() operation onto rtems_io_close().
+ */
+
+int device_close(
+ rtems_libio_t *iop
+)
+{
+ rtems_libio_open_close_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ args.iop = iop;
+ args.flags = 0;
+ args.mode = 0;
+
+ status = rtems_io_close(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+ if ( status ) {
+ return rtems_deviceio_errno(status);
+ }
+ return 0;
+}
+
+/*
+ * device_read
+ *
+ * This handler maps a read() operation onto rtems_io_read().
+ */
+
+ssize_t device_read(
+ rtems_libio_t *iop,
+ void *buffer,
+ uint32_t count
+)
+{
+ rtems_libio_rw_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ args.iop = iop;
+ args.offset = iop->offset;
+ args.buffer = buffer;
+ args.count = count;
+ args.flags = iop->flags;
+ args.bytes_moved = 0;
+
+ status = rtems_io_read(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+
+ if ( status )
+ return rtems_deviceio_errno(status);
+
+ return (ssize_t) args.bytes_moved;
+}
+
+/*
+ * device_write
+ *
+ * This handler maps a write() operation onto rtems_io_write().
+ */
+
+ssize_t device_write(
+ rtems_libio_t *iop,
+ const void *buffer,
+ uint32_t count
+)
+{
+ rtems_libio_rw_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ args.iop = iop;
+ args.offset = iop->offset;
+ args.buffer = (void *) buffer;
+ args.count = count;
+ args.flags = iop->flags;
+ args.bytes_moved = 0;
+
+ status = rtems_io_write(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+
+ if ( status )
+ return rtems_deviceio_errno(status);
+
+ return (ssize_t) args.bytes_moved;
+}
+
+/*
+ * device_ioctl
+ *
+ * This handler maps an ioctl() operation onto rtems_io_ioctl().
+ */
+
+int device_ioctl(
+ rtems_libio_t *iop,
+ uint32_t command,
+ void *buffer
+)
+{
+ rtems_libio_ioctl_args_t args;
+ rtems_status_code status;
+ IMFS_jnode_t *the_jnode;
+
+ args.iop = iop;
+ args.command = command;
+ args.buffer = buffer;
+
+ the_jnode = iop->file_info;
+
+ status = rtems_io_control(
+ the_jnode->info.device.major,
+ the_jnode->info.device.minor,
+ (void *) &args
+ );
+
+ if ( status )
+ return rtems_deviceio_errno(status);
+
+ return args.ioctl_return;
+}
+
+/*
+ * device_lseek
+ *
+ * This handler eats all lseek() operations.
+ */
+
+int device_lseek(
+ rtems_libio_t *iop,
+ off_t offset,
+ int whence
+)
+{
+ return 0;
+}
+
+/*
+ * device_stat
+ *
+ * The IMFS_stat() is used.
+ */
+
+/*
+ * device_rmnod
+ *
+ * The IMFS_rmnod() is used.
+ */
diff --git a/cpukit/libfs/src/imfs/imfs.h b/cpukit/libfs/src/imfs/imfs.h
new file mode 100644
index 0000000000..eb41abd03d
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs.h
@@ -0,0 +1,546 @@
+/*
+ * Header file for the In-Memory File System
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __IMFS_h
+#define __IMFS_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems.h>
+#include <rtems/chain.h>
+
+#include <sys/types.h>
+#include <limits.h>
+#include <rtems/libio.h>
+
+/*
+ * File name macros
+ */
+
+#define IMFS_is_valid_name_char( _ch ) ( 1 )
+
+#define IMFS_is_separator( _ch ) \
+ rtems_filesystem_is_separator( _ch )
+
+/*
+ * Data types
+ */
+
+struct IMFS_jnode_tt;
+typedef struct IMFS_jnode_tt IMFS_jnode_t;
+
+typedef struct {
+ Chain_Control Entries;
+ rtems_filesystem_mount_table_entry_t *mt_fs;
+} IMFS_directory_t;
+
+typedef struct {
+ rtems_device_major_number major;
+ rtems_device_minor_number minor;
+} IMFS_device_t;
+
+typedef struct {
+ IMFS_jnode_t *link_node;
+} IMFS_link_t;
+
+typedef struct {
+ const char *name;
+} IMFS_sym_link_t;
+
+/*
+ * IMFS "memfile" information
+ *
+ * The data structure for the in-memory "memfiles" is based on classic UNIX.
+ *
+ * block_ptr is a pointer to a block of IMFS_MEMFILE_BYTES_PER_BLOCK in
+ * length which could be data or a table of pointers to blocks.
+ *
+ * Setting IMFS_MEMFILE_BYTES_PER_BLOCK to different values has a significant
+ * impact on the maximum file size supported as well as the amount of
+ * memory wasted due to internal file fragmentation. The following
+ * is a list of maximum file sizes based on various settings
+ *
+ * max_filesize with blocks of 16 is 1,328
+ * max_filesize with blocks of 32 is 18,656
+ * max_filesize with blocks of 64 is 279,488
+ * max_filesize with blocks of 128 is 4,329,344
+ * max_filesize with blocks of 256 is 68,173,568
+ * max_filesize with blocks of 512 is 1,082,195,456
+ */
+
+#define IMFS_MEMFILE_BYTES_PER_BLOCK 128
+#define IMFS_MEMFILE_BLOCK_SLOTS \
+ (IMFS_MEMFILE_BYTES_PER_BLOCK / sizeof(void *))
+
+typedef unsigned char * block_p;
+typedef block_p *block_ptr;
+
+typedef struct {
+ off_t size; /* size of file in bytes */
+ block_ptr indirect; /* array of 128 data blocks pointers */
+ block_ptr doubly_indirect; /* 128 indirect blocks */
+ block_ptr triply_indirect; /* 128 doubly indirect blocks */
+} IMFS_memfile_t;
+
+typedef struct {
+ off_t size; /* size of file in bytes */
+ block_p direct; /* pointer to file image */
+} IMFS_linearfile_t;
+
+/*
+ * Important block numbers for "memfiles"
+ */
+
+#define FIRST_INDIRECT (0)
+#define LAST_INDIRECT (IMFS_MEMFILE_BLOCK_SLOTS - 1)
+
+#define FIRST_DOUBLY_INDIRECT (LAST_INDIRECT + 1)
+#define LAST_DOUBLY_INDIRECT \
+ (LAST_INDIRECT + \
+ (IMFS_MEMFILE_BLOCK_SLOTS * IMFS_MEMFILE_BLOCK_SLOTS))
+
+#define FIRST_TRIPLY_INDIRECT (LAST_DOUBLY_INDIRECT + 1)
+#define LAST_TRIPLY_INDIRECT \
+ (LAST_DOUBLY_INDIRECT +\
+ (IMFS_MEMFILE_BLOCK_SLOTS * \
+ IMFS_MEMFILE_BLOCK_SLOTS * IMFS_MEMFILE_BLOCK_SLOTS))
+
+#define IMFS_MEMFILE_MAXIMUM_SIZE \
+ (LAST_TRIPLY_INDIRECT * IMFS_MEMFILE_BYTES_PER_BLOCK)
+
+/*
+ * What types of IMFS file systems entities there can be.
+ */
+
+#define IMFS_jnode_types_t rtems_filesystem_node_types_t
+#define IMFS_DIRECTORY RTEMS_FILESYSTEM_DIRECTORY
+#define IMFS_DEVICE RTEMS_FILESYSTEM_DEVICE
+#define IMFS_HARD_LINK RTEMS_FILESYSTEM_HARD_LINK
+#define IMFS_SYM_LINK RTEMS_FILESYSTEM_SYM_LINK
+#define IMFS_MEMORY_FILE RTEMS_FILESYSTEM_MEMORY_FILE
+#define IMFS_LINEAR_FILE (IMFS_MEMORY_FILE + 1)
+
+#define IMFS_NUMBER_OF_TYPES (IMFS_LINEAR_FILE + 1)
+
+typedef union {
+ IMFS_directory_t directory;
+ IMFS_device_t device;
+ IMFS_link_t hard_link;
+ IMFS_sym_link_t sym_link;
+ IMFS_memfile_t file;
+ IMFS_linearfile_t linearfile;
+} IMFS_types_union;
+
+/*
+ * Maximum length of a "basename" of an IMFS file/node.
+ */
+
+#define IMFS_NAME_MAX 32
+
+/*
+ * The control structure for an IMFS jnode.
+ */
+
+struct IMFS_jnode_tt {
+ Chain_Node Node; /* for chaining them together */
+ IMFS_jnode_t *Parent; /* Parent node */
+ char name[IMFS_NAME_MAX+1]; /* "basename" */
+ mode_t st_mode; /* File mode */
+ nlink_t st_nlink; /* Link count */
+ ino_t st_ino; /* inode */
+
+ uid_t st_uid; /* User ID of owner */
+ gid_t st_gid; /* Group ID of owner */
+
+ time_t stat_atime; /* Time of last access */
+ time_t stat_mtime; /* Time of last modification */
+ time_t stat_ctime; /* Time of last status change */
+ IMFS_jnode_types_t type; /* Type of this entry */
+ IMFS_types_union info;
+};
+
+#define IMFS_update_atime( _jnode ) \
+ do { \
+ struct timeval tv; \
+ gettimeofday( &tv, 0 ); \
+ _jnode->stat_atime = (time_t) tv.tv_sec; \
+ } while (0)
+
+#define IMFS_update_mtime( _jnode ) \
+ do { \
+ struct timeval tv; \
+ gettimeofday( &tv, 0 ); \
+ _jnode->stat_mtime = (time_t) tv.tv_sec; \
+ } while (0)
+
+#define IMFS_update_ctime( _jnode ) \
+ do { \
+ struct timeval tv; \
+ gettimeofday( &tv, 0 ); \
+ _jnode->stat_ctime = (time_t) tv.tv_sec; \
+ } while (0)
+
+#define IMFS_atime_mtime_update( _jnode ) \
+ do { \
+ struct timeval tv; \
+ gettimeofday( &tv, 0 ); \
+ _jnode->stat_mtime = (time_t) tv.tv_sec; \
+ _jnode->stat_atime = (time_t) tv.tv_sec; \
+ } while (0)
+
+typedef struct {
+ ino_t ino_count;
+ rtems_filesystem_file_handlers_r *linearfile_handlers;
+ rtems_filesystem_file_handlers_r *memfile_handlers;
+ rtems_filesystem_file_handlers_r *directory_handlers;
+} IMFS_fs_info_t;
+
+#if UNUSED
+/* FIXME: Unused, we might want to remove it */
+#define increment_and_check_linkcounts( _fs_info ) \
+ ((IMFS_fs_info_t * )_fs_info)->link_counts++; \
+ if ( ((IMFS_fs_info_t * )_fs_info)->link_counts > MAXSYMLINKS ) \
+ rtems_set_errno_and_return_minus_one( ELOOP )
+#endif
+
+#define decrement_linkcounts( _fs_info ) \
+ ((IMFS_fs_info_t * )_fs_info)->link_counts--;
+
+/*
+ * Type defination for tokens returned from IMFS_get_token
+ */
+
+typedef enum {
+ IMFS_NO_MORE_PATH,
+ IMFS_CURRENT_DIR,
+ IMFS_UP_DIR,
+ IMFS_NAME,
+ IMFS_INVALID_TOKEN
+} IMFS_token_types;
+
+/*
+ * Shared Data
+ */
+
+extern rtems_filesystem_file_handlers_r IMFS_directory_handlers;
+extern rtems_filesystem_file_handlers_r IMFS_device_handlers;
+extern rtems_filesystem_file_handlers_r IMFS_link_handlers;
+extern rtems_filesystem_file_handlers_r IMFS_linearfile_handlers;
+extern rtems_filesystem_file_handlers_r IMFS_memfile_handlers;
+extern rtems_filesystem_operations_table IMFS_ops;
+extern rtems_filesystem_operations_table miniIMFS_ops;
+extern rtems_filesystem_limits_and_options_t IMFS_LIMITS_AND_OPTIONS;
+
+/*
+ * Routines
+ */
+
+int IMFS_initialize(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+int miniIMFS_initialize(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+int IMFS_initialize_support(
+ rtems_filesystem_mount_table_entry_t *mt_entry,
+ rtems_filesystem_operations_table *op_table,
+ rtems_filesystem_file_handlers_r *linearfile_handlers,
+ rtems_filesystem_file_handlers_r *memfile_handlers,
+ rtems_filesystem_file_handlers_r *directory_handlers
+);
+
+int IMFS_fsunmount(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+);
+
+int rtems_tarfs_load(
+ char *mountpoint,
+ unsigned char *addr,
+ unsigned long length
+);
+
+/*
+ * Returns the number of characters copied from path to token.
+ */
+IMFS_token_types IMFS_get_token(
+ const char *path,
+ char *token,
+ int *token_len
+);
+
+void IMFS_dump( void );
+
+void IMFS_initialize_jnode(
+ IMFS_jnode_t *the_jnode,
+ IMFS_jnode_types_t type,
+ IMFS_jnode_t *the_parent,
+ char *name,
+ mode_t mode
+);
+
+IMFS_jnode_t *IMFS_find_match_in_dir(
+ IMFS_jnode_t *directory, /* IN */
+ char *name /* IN */
+);
+
+rtems_filesystem_node_types_t IMFS_node_type(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+int IMFS_stat(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ struct stat *buf /* OUT */
+);
+
+int IMFS_Set_handlers(
+ rtems_filesystem_location_info_t *loc
+);
+
+int IMFS_evaluate_link(
+ rtems_filesystem_location_info_t *node, /* IN/OUT */
+ int flags /* IN */
+);
+
+int IMFS_eval_path(
+ const char *pathname, /* IN */
+ int flags, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+);
+
+
+int IMFS_link(
+ rtems_filesystem_location_info_t *to_loc, /* IN */
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ const char *token /* IN */
+);
+
+int IMFS_unlink(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+int IMFS_chown(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ uid_t owner, /* IN */
+ gid_t group /* IN */
+);
+
+int IMFS_freenodinfo(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+int IMFS_mknod(
+ const char *path, /* IN */
+ mode_t mode, /* IN */
+ dev_t dev, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+);
+
+IMFS_jnode_t *IMFS_create_node(
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ IMFS_jnode_types_t type, /* IN */
+ char *name, /* IN */
+ mode_t mode, /* IN */
+ IMFS_types_union *info /* IN */
+);
+
+int IMFS_evaluate_for_make(
+ const char *path, /* IN */
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ const char **name /* OUT */
+);
+
+int IMFS_mount(
+ rtems_filesystem_mount_table_entry_t *mt_entry /* IN */
+);
+
+int IMFS_unmount(
+ rtems_filesystem_mount_table_entry_t *mt_entry /* IN */
+);
+
+int IMFS_freenod(
+ rtems_filesystem_location_info_t *node /* IN/OUT */
+);
+
+int IMFS_memfile_remove(
+ IMFS_jnode_t *the_jnode /* IN/OUT */
+);
+
+int memfile_ftruncate(
+ rtems_libio_t *iop, /* IN */
+ off_t length /* IN */
+);
+
+int imfs_dir_open(
+ rtems_libio_t *iop, /* IN */
+ const char *pathname, /* IN */
+ uint32_t flag, /* IN */
+ uint32_t mode /* IN */
+);
+
+int imfs_dir_close(
+ rtems_libio_t *iop /* IN */
+);
+
+ssize_t imfs_dir_read(
+ rtems_libio_t *iop, /* IN */
+ void *buffer, /* IN */
+ uint32_t count /* IN */
+);
+
+int imfs_dir_lseek(
+ rtems_libio_t *iop, /* IN */
+ off_t offset, /* IN */
+ int whence /* IN */
+);
+
+int imfs_dir_fstat(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ struct stat *buf /* OUT */
+);
+
+int imfs_dir_rmnod(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+int linearfile_read(
+ rtems_libio_t *iop, /* IN */
+ void *buffer, /* IN */
+ uint32_t count /* IN */
+);
+
+int linearfile_lseek(
+ rtems_libio_t *iop, /* IN */
+ off_t offset, /* IN */
+ int whence /* IN */
+);
+
+int memfile_open(
+ rtems_libio_t *iop, /* IN */
+ const char *pathname, /* IN */
+ uint32_t flag, /* IN */
+ uint32_t mode /* IN */
+);
+
+int memfile_close(
+ rtems_libio_t *iop /* IN */
+);
+
+ssize_t memfile_read(
+ rtems_libio_t *iop, /* IN */
+ void *buffer, /* IN */
+ uint32_t count /* IN */
+);
+
+ssize_t memfile_write(
+ rtems_libio_t *iop, /* IN */
+ const void *buffer, /* IN */
+ uint32_t count /* IN */
+);
+
+int memfile_ioctl(
+ rtems_libio_t *iop, /* IN */
+ uint32_t command, /* IN */
+ void *buffer /* IN */
+);
+
+int memfile_lseek(
+ rtems_libio_t *iop, /* IN */
+ off_t offset, /* IN */
+ int whence /* IN */
+);
+
+int memfile_rmnod(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+int device_open(
+ rtems_libio_t *iop, /* IN */
+ const char *pathname, /* IN */
+ uint32_t flag, /* IN */
+ uint32_t mode /* IN */
+);
+
+int device_close(
+ rtems_libio_t *iop /* IN */
+);
+
+ssize_t device_read(
+ rtems_libio_t *iop, /* IN */
+ void *buffer, /* IN */
+ uint32_t count /* IN */
+);
+
+ssize_t device_write(
+ rtems_libio_t *iop, /* IN */
+ const void *buffer, /* IN */
+ uint32_t count /* IN */
+);
+
+int device_ioctl(
+ rtems_libio_t *iop, /* IN */
+ uint32_t command, /* IN */
+ void *buffer /* IN */
+);
+
+int device_lseek(
+ rtems_libio_t *iop, /* IN */
+ off_t offset, /* IN */
+ int whence /* IN */
+);
+
+int IMFS_utime(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ time_t actime, /* IN */
+ time_t modtime /* IN */
+);
+
+int IMFS_fchmod(
+ rtems_filesystem_location_info_t *loc,
+ mode_t mode
+);
+
+int IMFS_symlink(
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ const char *link_name,
+ const char *node_name
+);
+
+int IMFS_readlink(
+ rtems_filesystem_location_info_t *loc, /* IN */
+ char *buf, /* OUT */
+ size_t bufsize
+);
+
+int IMFS_fdatasync(
+ rtems_libio_t *iop
+);
+
+int IMFS_fcntl(
+ int cmd,
+ rtems_libio_t *iop
+);
+
+int IMFS_rmnod(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/libfs/src/imfs/imfs_chown.c b/cpukit/libfs/src/imfs/imfs_chown.c
new file mode 100644
index 0000000000..7f0c7b5688
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_chown.c
@@ -0,0 +1,56 @@
+/*
+ * IMFS_chown
+ *
+ * This routine is the implementation of the chown() system
+ * call for the IMFS.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+#include "imfs.h"
+
+int IMFS_chown(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ uid_t owner, /* IN */
+ gid_t group /* IN */
+)
+{
+ IMFS_jnode_t *jnode;
+#if defined(RTEMS_POSIX_API)
+ uid_t st_uid;
+#endif
+
+ jnode = (IMFS_jnode_t *) pathloc->node_access;
+
+ /*
+ * Verify I am the owner of the node or the super user.
+ */
+
+#if defined(RTEMS_POSIX_API)
+ st_uid = geteuid();
+
+ if ( ( st_uid != jnode->st_uid ) && ( st_uid != 0 ) )
+ rtems_set_errno_and_return_minus_one( EPERM );
+#endif
+
+ jnode->st_uid = owner;
+ jnode->st_gid = group;
+
+ IMFS_update_ctime( jnode );
+
+ return 0;
+}
diff --git a/cpukit/libfs/src/imfs/imfs_config.c b/cpukit/libfs/src/imfs/imfs_config.c
new file mode 100644
index 0000000000..20da389fa2
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_config.c
@@ -0,0 +1,35 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/libio_.h>
+#include "imfs.h"
+
+/* XXX this structure should use real constants */
+
+rtems_filesystem_limits_and_options_t IMFS_LIMITS_AND_OPTIONS = {
+ 5, /* link_max */
+ 6, /* max_canon */
+ 7, /* max_input */
+ IMFS_NAME_MAX, /* name_max */
+ 255, /* path_max */
+ 2, /* pipe_buf */
+ 1, /* posix_async_io */
+ 2, /* posix_chown_restrictions */
+ 3, /* posix_no_trunc */
+ 4, /* posix_prio_io */
+ 5, /* posix_sync_io */
+ 6 /* posix_vdisable */
+};
diff --git a/cpukit/libfs/src/imfs/imfs_creat.c b/cpukit/libfs/src/imfs/imfs_creat.c
new file mode 100644
index 0000000000..94d9dac9c1
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_creat.c
@@ -0,0 +1,137 @@
+/*
+ * IMFS_create_node()
+ *
+ * Routine to create a new in memory file system node.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include "imfs.h"
+#include <rtems/libio_.h>
+
+IMFS_jnode_t *IMFS_create_node(
+ rtems_filesystem_location_info_t *parent_loc,
+ IMFS_jnode_types_t type,
+ char *name,
+ mode_t mode,
+ IMFS_types_union *info
+)
+{
+ IMFS_jnode_t *node;
+ struct timeval tv;
+ IMFS_jnode_t *parent = NULL;
+ IMFS_fs_info_t *fs_info;
+ char *sym_name;
+
+ if ( parent_loc != NULL )
+ parent = parent_loc->node_access;
+
+ /*
+ * Allocate an IMFS jnode
+ */
+
+ node = calloc( 1, sizeof( IMFS_jnode_t ) );
+ if ( !node )
+ return NULL;
+
+ /*
+ * Fill in the basic information
+ */
+
+ node->st_nlink = 1;
+ node->type = type;
+ strncpy( node->name, name, IMFS_NAME_MAX );
+
+ /*
+ * Fill in the mode and permission information for the jnode structure.
+ */
+
+ node->st_mode = mode & ~rtems_filesystem_umask;
+
+#if defined(RTEMS_POSIX_API)
+ node->st_uid = geteuid();
+ node->st_gid = getegid();
+#else
+ node->st_uid = 0;
+ node->st_gid = 0;
+#endif
+
+ /*
+ * Now set all the times.
+ */
+
+ gettimeofday( &tv, 0 );
+
+ node->stat_atime = (time_t) tv.tv_sec;
+ node->stat_mtime = (time_t) tv.tv_sec;
+ node->stat_ctime = (time_t) tv.tv_sec;
+
+ /*
+ * Set the type specific information
+ */
+
+ switch (type) {
+ case IMFS_DIRECTORY:
+ Chain_Initialize_empty(&node->info.directory.Entries);
+ break;
+
+ case IMFS_HARD_LINK:
+ node->info.hard_link.link_node = info->hard_link.link_node;
+ break;
+
+ case IMFS_SYM_LINK:
+ sym_name = calloc( 1, strlen( info->sym_link.name ) + 1 );
+ strcpy( sym_name, info->sym_link.name );
+ node->info.sym_link.name = sym_name;
+ break;
+
+ case IMFS_DEVICE:
+ node->info.device.major = info->device.major;
+ node->info.device.minor = info->device.minor;
+ break;
+
+ case IMFS_LINEAR_FILE:
+ node->info.linearfile.size = 0;
+ node->info.linearfile.direct = 0;
+
+ case IMFS_MEMORY_FILE:
+ node->info.file.size = 0;
+ node->info.file.indirect = 0;
+ node->info.file.doubly_indirect = 0;
+ node->info.file.triply_indirect = 0;
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+
+ /*
+ * If this node has a parent, then put it in that directory list.
+ */
+
+ if ( parent ) {
+ Chain_Append( &parent->info.directory.Entries, &node->Node );
+ node->Parent = parent;
+
+ fs_info = parent_loc->mt_entry->fs_info;
+ node->st_ino = ++fs_info->ino_count;
+ }
+
+
+ return node;
+}
diff --git a/cpukit/libfs/src/imfs/imfs_debug.c b/cpukit/libfs/src/imfs/imfs_debug.c
new file mode 100644
index 0000000000..e42198a4b8
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_debug.c
@@ -0,0 +1,176 @@
+/*
+ * IMFS debug support routines
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h> /* for close */
+
+#include <stdio.h>
+#include <sys/stat.h>
+
+#include "imfs.h"
+#include <rtems/libio_.h>
+
+/*
+ * IMFS_types
+ *
+ * Printable names for each of the IMFS file system types.
+ */
+
+char *IMFS_types[ IMFS_NUMBER_OF_TYPES ] = {
+ "directory",
+ "device",
+ "link",
+ "memory file",
+ "linear file"
+};
+
+/*
+ * IMFS_print_jnode
+ *
+ * This routine prints the contents of the specified jnode.
+ */
+
+void IMFS_print_jnode(
+ IMFS_jnode_t *the_jnode
+)
+{
+ assert( the_jnode );
+
+ fprintf(stdout, "%s", the_jnode->name );
+ switch( the_jnode->type ) {
+ case IMFS_DIRECTORY:
+ fprintf(stdout, "/" );
+ break;
+
+ case IMFS_DEVICE:
+ fprintf(stdout, " (device %d, %d)",
+ the_jnode->info.device.major, the_jnode->info.device.minor );
+ break;
+
+ case IMFS_LINEAR_FILE:
+ fprintf(stdout, " (file %d %p)",
+ (int)the_jnode->info.linearfile.size,
+ the_jnode->info.linearfile.direct
+ );
+ break;
+
+ case IMFS_MEMORY_FILE:
+ /* Useful when debugging .. varies between targets */
+#if 0
+ fprintf(stdout, " (file %d %p %p %p)",
+ (int)the_jnode->info.file.size,
+ the_jnode->info.file.indirect,
+ the_jnode->info.file.doubly_indirect,
+ the_jnode->info.file.triply_indirect
+ );
+#else
+ fprintf(stdout, " (file %d)", (int)the_jnode->info.file.size );
+#endif
+ break;
+
+ case IMFS_HARD_LINK:
+ fprintf(stdout, " links not printed\n" );
+ assert(0);
+ break;
+
+ case IMFS_SYM_LINK:
+ fprintf(stdout, " links not printed\n" );
+ assert(0);
+ break;
+
+ default:
+ fprintf(stdout, " bad type %d\n", the_jnode->type );
+ assert(0);
+ break;
+ }
+ puts("");
+}
+
+/*
+ * IMFS_dump_directory
+ *
+ * This routine prints the contents of a directory in the IMFS. If a
+ * directory is encountered, then this routine will recurse to process
+ * the subdirectory.
+ */
+
+void IMFS_dump_directory(
+ IMFS_jnode_t *the_directory,
+ int level
+)
+{
+ Chain_Node *the_node;
+ Chain_Control *the_chain;
+ IMFS_jnode_t *the_jnode;
+ int i;
+
+ assert( the_directory );
+
+ assert( level >= 0 );
+
+ assert( the_directory->type == IMFS_DIRECTORY );
+
+ the_chain = &the_directory->info.directory.Entries;
+
+ for ( the_node = the_chain->first;
+ !_Chain_Is_tail( the_chain, the_node );
+ the_node = the_node->next ) {
+
+ the_jnode = (IMFS_jnode_t *) the_node;
+
+ for ( i=0 ; i<=level ; i++ )
+ fprintf(stdout, "...." );
+ IMFS_print_jnode( the_jnode );
+ if ( the_jnode->type == IMFS_DIRECTORY )
+ IMFS_dump_directory( the_jnode, level + 1 );
+ }
+}
+
+/*
+ * IMFS_dump
+ *
+ * This routine dumps the entire IMFS that is mounted at the root
+ * directory.
+ *
+ * NOTE: Assuming the "/" directory is bad.
+ * Not checking that the starting directory is in an IMFS is bad.
+ */
+
+void IMFS_dump( void )
+{
+ fprintf(stdout, "*************** Dump of Entire IMFS ***************\n" );
+ fprintf(stdout, "/\n" );
+ IMFS_dump_directory( rtems_filesystem_root.node_access, 0 );
+ fprintf(stdout, "*************** End of Dump ***************\n" );
+}
+
+/*
+ * IMFS_memfile_maximum_size()
+ *
+ * This routine returns the size of the largest file which can be created
+ * using the IMFS memory file type.
+ *
+ */
+
+int IMFS_memfile_maximum_size( void )
+{
+ return IMFS_MEMFILE_MAXIMUM_SIZE;
+}
diff --git a/cpukit/libfs/src/imfs/imfs_directory.c b/cpukit/libfs/src/imfs/imfs_directory.c
new file mode 100644
index 0000000000..b5ce125321
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_directory.c
@@ -0,0 +1,351 @@
+/*
+ * IMFS Directory Access Routines
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <rtems/chain.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <dirent.h>
+
+#include "imfs.h"
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+/*
+ * imfs_dir_open
+ *
+ * This rountine will verify that the node being opened as a directory is
+ * in fact a directory node. If it is then the offset into the directory
+ * will be set to 0 to position to the first directory entry.
+ */
+
+int imfs_dir_open(
+ rtems_libio_t *iop,
+ const char *pathname,
+ uint32_t flag,
+ uint32_t mode
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ /* Is the node a directory ? */
+ the_jnode = (IMFS_jnode_t *) iop->file_info;
+
+ if ( the_jnode->type != IMFS_DIRECTORY )
+ return -1; /* It wasn't a directory --> return error */
+
+ iop->offset = 0;
+ return 0;
+}
+
+/*
+ * imfs_dir_read
+ *
+ * This routine will read the next directory entry based on the directory
+ * offset. The offset should be equal to -n- time the size of an individual
+ * dirent structure. If n is not an integer multiple of the sizeof a
+ * dirent structure, an integer division will be performed to determine
+ * directory entry that will be returned in the buffer. Count should reflect
+ * -m- times the sizeof dirent bytes to be placed in the buffer.
+ * If there are not -m- dirent elements from the current directory position
+ * to the end of the exisiting file, the remaining entries will be placed in
+ * the buffer and the returned value will be equal to -m actual- times the
+ * size of a directory entry.
+ */
+
+ssize_t imfs_dir_read(
+ rtems_libio_t *iop,
+ void *buffer,
+ uint32_t count
+)
+{
+ /*
+ * Read up to element iop->offset in the directory chain of the
+ * imfs_jnode_t struct for this file descriptor.
+ */
+ Chain_Node *the_node;
+ Chain_Control *the_chain;
+ IMFS_jnode_t *the_jnode;
+ int bytes_transferred;
+ int current_entry;
+ int first_entry;
+ int last_entry;
+ struct dirent tmp_dirent;
+
+ the_jnode = (IMFS_jnode_t *)iop->file_info;
+ the_chain = &the_jnode->info.directory.Entries;
+
+ if ( Chain_Is_empty( the_chain ) )
+ return 0;
+
+ /* Move to the first of the desired directory entries */
+ the_node = the_chain->first;
+
+ bytes_transferred = 0;
+ first_entry = iop->offset;
+ /* protect against using sizes that are not exact multiples of the */
+ /* -dirent- size. These could result in unexpected results */
+ last_entry = first_entry + (count/sizeof(struct dirent)) * sizeof(struct dirent);
+
+ /* The directory was not empty so try to move to the desired entry in chain*/
+ for (
+ current_entry = 0;
+ current_entry < last_entry;
+ current_entry = current_entry + sizeof(struct dirent) ){
+
+ if ( Chain_Is_tail( the_chain, the_node ) ){
+ /* We hit the tail of the chain while trying to move to the first */
+ /* entry in the read */
+ return bytes_transferred; /* Indicate that there are no more */
+ /* entries to return */
+ }
+
+ if( current_entry >= first_entry ) {
+ /* Move the entry to the return buffer */
+ tmp_dirent.d_off = current_entry;
+ tmp_dirent.d_reclen = sizeof( struct dirent );
+ the_jnode = (IMFS_jnode_t *) the_node;
+ tmp_dirent.d_ino = the_jnode->st_ino;
+ tmp_dirent.d_namlen = strlen( the_jnode->name );
+ strcpy( tmp_dirent.d_name, the_jnode->name );
+ memcpy(
+ buffer + bytes_transferred,
+ (void *)&tmp_dirent,
+ sizeof( struct dirent )
+ );
+ iop->offset = iop->offset + sizeof(struct dirent);
+ bytes_transferred = bytes_transferred + sizeof( struct dirent );
+ }
+
+ the_node = the_node->next;
+ }
+
+ /* Success */
+ return bytes_transferred;
+}
+
+
+
+/*
+ * imfs_dir_close
+ *
+ * This routine will be called by the generic close routine to cleanup any
+ * resources that have been allocated for the management of the file
+ */
+
+int imfs_dir_close(
+ rtems_libio_t *iop
+)
+{
+ /*
+ * The generic close routine handles the deallocation of the file control
+ * and associated memory. At present the imfs_dir_close simply
+ * returns a successful completion status.
+ */
+
+ return 0;
+}
+
+
+
+/*
+ * imfs_dir_lseek
+ *
+ * This routine will behave in one of three ways based on the state of
+ * argument whence. Based on the state of its value the offset argument will
+ * be interpreted using one of the following methods:
+ *
+ * SEEK_SET - offset is the absolute byte offset from the start of the
+ * logical start of the dirent sequence that represents the
+ * directory
+ * SEEK_CUR - offset is used as the relative byte offset from the current
+ * directory position index held in the iop structure
+ * SEEK_END - N/A --> This will cause an assert.
+ */
+
+int imfs_dir_lseek(
+ rtems_libio_t *iop,
+ off_t offset,
+ int whence
+)
+{
+ switch( whence ) {
+ case SEEK_SET: /* absolute move from the start of the file */
+ case SEEK_CUR: /* relative move */
+ iop->offset = (iop->offset/sizeof(struct dirent)) *
+ sizeof(struct dirent);
+ break;
+
+ case SEEK_END: /* Movement past the end of the directory via lseek */
+ /* is not a permitted operation */
+ default:
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ break;
+ }
+
+ return 0;
+}
+
+
+
+/*
+ * imfs_dir_fstat
+ *
+ * This routine will obtain the following information concerning the current
+ * directory:
+ * st_dev 0ll
+ * st_ino 1
+ * st_mode mode extracted from the jnode
+ * st_nlink number of links to this node
+ * st_uid uid extracted from the jnode
+ * st_gid gid extracted from the jnode
+ * st_rdev 0ll
+ * st_size the number of bytes in the directory
+ * This is calculated by taking the number of entries
+ * in the directory and multiplying by the size of a
+ * dirent structure
+ * st_blksize 0
+ * st_blocks 0
+ * stat_atime time of last access
+ * stat_mtime time of last modification
+ * stat_ctime time of the last change
+ *
+ * This information will be returned to the calling function in a -stat- struct
+ *
+ */
+
+int imfs_dir_fstat(
+ rtems_filesystem_location_info_t *loc,
+ struct stat *buf
+)
+{
+ Chain_Node *the_node;
+ Chain_Control *the_chain;
+ IMFS_jnode_t *the_jnode;
+
+
+ the_jnode = (IMFS_jnode_t *) loc->node_access;
+
+ buf->st_dev = 0ll;
+ buf->st_ino = the_jnode->st_ino;
+ buf->st_mode = the_jnode->st_mode;
+ buf->st_nlink = the_jnode->st_nlink;
+ buf->st_uid = the_jnode->st_uid;
+ buf->st_gid = the_jnode->st_gid;
+ buf->st_rdev = 0ll;
+ buf->st_blksize = 0;
+ buf->st_blocks = 0;
+ buf->st_atime = the_jnode->stat_atime;
+ buf->st_mtime = the_jnode->stat_mtime;
+ buf->st_ctime = the_jnode->stat_ctime;
+
+ buf->st_size = 0;
+
+ the_chain = &the_jnode->info.directory.Entries;
+
+ /* Run through the chain and count the number of directory entries */
+ /* that are subordinate to this directory node */
+ for ( the_node = the_chain->first ;
+ !_Chain_Is_tail( the_chain, the_node ) ;
+ the_node = the_node->next ) {
+
+ buf->st_size = buf->st_size + sizeof( struct dirent );
+ }
+
+ return 0;
+}
+
+/*
+ * IMFS_dir_rmnod
+ *
+ * This routine is available from the optable to remove a node
+ * from the IMFS file system.
+ */
+
+int imfs_dir_rmnod(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = (IMFS_jnode_t *) pathloc->node_access;
+
+ /*
+ * You cannot remove a node that still has children
+ */
+
+ if ( ! Chain_Is_empty( &the_jnode->info.directory.Entries ) )
+ rtems_set_errno_and_return_minus_one( ENOTEMPTY );
+
+ /*
+ * You cannot remove the file system root node.
+ */
+
+ if ( pathloc->mt_entry->mt_fs_root.node_access == pathloc->node_access )
+ rtems_set_errno_and_return_minus_one( EBUSY );
+
+ /*
+ * You cannot remove a mountpoint.
+ */
+
+ if ( the_jnode->info.directory.mt_fs != NULL )
+ rtems_set_errno_and_return_minus_one( EBUSY );
+
+ /*
+ * Take the node out of the parent's chain that contains this node
+ */
+
+ if ( the_jnode->Parent != NULL ) {
+ Chain_Extract( (Chain_Node *) the_jnode );
+ the_jnode->Parent = NULL;
+ }
+
+ /*
+ * Decrement the link counter and see if we can free the space.
+ */
+
+ the_jnode->st_nlink--;
+ IMFS_update_ctime( the_jnode );
+
+ /*
+ * The file cannot be open and the link must be less than 1 to free.
+ */
+
+ if ( !rtems_libio_is_file_open( the_jnode ) && (the_jnode->st_nlink < 1) ) {
+
+ /*
+ * Is the rtems_filesystem_current is this node?
+ */
+
+ if ( rtems_filesystem_current.node_access == pathloc->node_access )
+ rtems_filesystem_current.node_access = NULL;
+
+ /*
+ * Free memory associated with a memory file.
+ */
+
+ free( the_jnode );
+ }
+
+ return 0;
+
+}
diff --git a/cpukit/libfs/src/imfs/imfs_eval.c b/cpukit/libfs/src/imfs/imfs_eval.c
new file mode 100644
index 0000000000..b2bac3f4da
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_eval.c
@@ -0,0 +1,660 @@
+/*
+ * Evaluation IMFS Node Support Routines
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "imfs.h"
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+#define RTEMS_LIBIO_PERMS_RX (RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_READ)
+#define RTEMS_LIBIO_PERMS_WX (RTEMS_LIBIO_PERMS_SEARCH | RTEMS_LIBIO_PERMS_WRITE)
+
+#define MAXSYMLINK 5
+
+int IMFS_Set_handlers(
+ rtems_filesystem_location_info_t *loc
+)
+{
+ IMFS_jnode_t *node = loc->node_access;
+ IMFS_fs_info_t *fs_info;
+
+ fs_info = loc->mt_entry->fs_info;
+ switch( node->type ) {
+ case IMFS_DIRECTORY:
+ loc->handlers = fs_info->directory_handlers;
+ break;
+ case IMFS_DEVICE:
+ loc->handlers = &IMFS_device_handlers;
+ break;
+ case IMFS_SYM_LINK:
+ case IMFS_HARD_LINK:
+ loc->handlers = &IMFS_link_handlers;
+ break;
+ case IMFS_LINEAR_FILE:
+ loc->handlers = fs_info->linearfile_handlers;
+ break;
+ case IMFS_MEMORY_FILE:
+ loc->handlers = fs_info->memfile_handlers;
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * IMFS_evaluate_permission
+ *
+ * The following routine evaluates that we have permission
+ * to do flags on the node.
+ */
+
+int IMFS_evaluate_permission(
+ rtems_filesystem_location_info_t *node,
+ int flags
+)
+{
+ uid_t st_uid;
+ gid_t st_gid;
+ IMFS_jnode_t *jnode;
+ int flags_to_test;
+
+ if ( !rtems_libio_is_valid_perms( flags ) ) {
+ assert( 0 );
+ rtems_set_errno_and_return_minus_one( EIO );
+ }
+
+ jnode = node->node_access;
+
+#if defined(RTEMS_POSIX_API)
+ st_uid = geteuid();
+ st_gid = getegid();
+#else
+ st_uid = jnode->st_uid;
+ st_gid = jnode->st_gid;
+#endif
+
+ /*
+ * Check if I am owner or a group member or someone else.
+ */
+
+ flags_to_test = flags;
+
+ if ( st_uid == jnode->st_uid )
+ flags_to_test <<= 6;
+ else if ( st_gid == jnode->st_gid )
+ flags_to_test <<= 3;
+ else
+ /* must be other - do nothing */;
+
+ /*
+ * If all of the flags are set we have permission
+ * to do this.
+ */
+ if ( ( flags_to_test & jnode->st_mode) == flags_to_test )
+ return 1;
+
+ return 0;
+}
+
+/*
+ * IMFS_evaluate_hard_link
+ *
+ * The following routine evaluates a hardlink to the actual node.
+ */
+
+int IMFS_evaluate_hard_link(
+ rtems_filesystem_location_info_t *node, /* IN/OUT */
+ int flags /* IN */
+)
+{
+ IMFS_jnode_t *jnode = node->node_access;
+ int result = 0;
+
+ /*
+ * Check for things that should never happen.
+ */
+
+ if ( jnode->type != IMFS_HARD_LINK )
+ rtems_fatal_error_occurred (0xABCD0000);
+
+ /*
+ * Set the hard link value and the handlers.
+ */
+
+ node->node_access = jnode->info.hard_link.link_node;
+
+ IMFS_Set_handlers( node );
+
+ /*
+ * Verify we have the correct permissions for this node.
+ */
+
+ if ( !IMFS_evaluate_permission( node, flags ) )
+ rtems_set_errno_and_return_minus_one( EACCES );
+
+ return result;
+}
+
+
+/*
+ * IMFS_evaluate_sym_link
+ *
+ * The following routine evaluates a symbolic link to the actual node.
+ */
+
+int IMFS_evaluate_sym_link(
+ rtems_filesystem_location_info_t *node, /* IN/OUT */
+ int flags /* IN */
+)
+{
+ IMFS_jnode_t *jnode = node->node_access;
+ int result = 0;
+ int i;
+
+ /*
+ * Check for things that should never happen.
+ */
+
+ if ( jnode->type != IMFS_SYM_LINK )
+ rtems_fatal_error_occurred (0xABCD0000);
+
+ if ( !jnode->Parent )
+ rtems_fatal_error_occurred( 0xBAD00000 );
+
+
+ /*
+ * Move the node_access to either the symbolic links parent or
+ * root depending on the symbolic links path.
+ */
+
+ node->node_access = jnode->Parent;
+
+ rtems_filesystem_get_sym_start_loc(
+ jnode->info.sym_link.name,
+ &i,
+ node
+ );
+
+ /*
+ * Use eval path to evaluate the path of the symbolic link.
+ */
+
+ result = IMFS_eval_path(
+ &jnode->info.sym_link.name[i],
+ flags,
+ node
+ );
+
+ IMFS_Set_handlers( node );
+
+ /*
+ * Verify we have the correct permissions for this node.
+ */
+
+ if ( !IMFS_evaluate_permission( node, flags ) )
+ rtems_set_errno_and_return_minus_one( EACCES );
+
+ return result;
+}
+
+/*
+ * IMFS_evaluate_link
+ *
+ * The following routine returns the real node pointed to by a link.
+ */
+
+int IMFS_evaluate_link(
+ rtems_filesystem_location_info_t *node, /* IN/OUT */
+ int flags /* IN */
+)
+{
+ IMFS_jnode_t *jnode;
+ int result = 0;
+
+ do {
+ jnode = node->node_access;
+
+ /*
+ * Increment and check the link counter.
+ */
+
+ rtems_filesystem_link_counts ++;
+ if ( rtems_filesystem_link_counts > MAXSYMLINK ) {
+ rtems_filesystem_link_counts = 0;
+ rtems_set_errno_and_return_minus_one( ELOOP );
+ }
+
+ /*
+ * Follow the Link node.
+ */
+
+ if ( jnode->type == IMFS_HARD_LINK )
+ result = IMFS_evaluate_hard_link( node, flags );
+
+ else if (jnode->type == IMFS_SYM_LINK )
+ result = IMFS_evaluate_sym_link( node, flags );
+
+ } while ( ( result == 0 ) && ( ( jnode->type == IMFS_SYM_LINK ) ||
+ ( jnode->type == IMFS_HARD_LINK ) ) );
+
+ /*
+ * Clear link counter.
+ */
+
+ rtems_filesystem_link_counts = 0;
+
+ return result;
+}
+
+
+/*
+ * IMFS_evaluate_for_make
+ *
+ * The following routine evaluate path for a new node to be created.
+ * pathloc is returned with a pointer to the parent of the new node.
+ * name is returned with a pointer to the first character in the
+ * new node name. The parent node is verified to be a directory.
+ */
+
+int IMFS_evaluate_for_make(
+ const char *path, /* IN */
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ const char **name /* OUT */
+)
+{
+ int i = 0;
+ int len;
+ IMFS_token_types type;
+ char token[ IMFS_NAME_MAX + 1 ];
+ rtems_filesystem_location_info_t newloc;
+ IMFS_jnode_t *node;
+ int done = 0;
+ int result;
+
+ /*
+ * This was filled in by the caller and is valid in the
+ * mount table.
+ */
+ node = pathloc->node_access;
+
+ /*
+ * Evaluate all tokens until we are done or an error occurs.
+ */
+
+ while( !done ) {
+
+ type = IMFS_get_token( &path[i], token, &len );
+ i += len;
+
+ if ( !pathloc->node_access )
+ rtems_set_errno_and_return_minus_one( ENOENT );
+
+ /*
+ * I cannot move out of this directory without execute permission.
+ */
+
+ if ( type != IMFS_NO_MORE_PATH )
+ if ( node->type == IMFS_DIRECTORY )
+ if ( !IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_SEARCH ) )
+ rtems_set_errno_and_return_minus_one( EACCES );
+
+ node = pathloc->node_access;
+
+ switch( type ) {
+
+ case IMFS_UP_DIR:
+ /*
+ * Am I at the root of all filesystems? (chroot'ed?)
+ */
+
+ if ( pathloc->node_access == rtems_filesystem_root.node_access )
+ break; /* Throw out the .. in this case */
+
+
+ /*
+ * Am I at the root of this mounted filesystem?
+ */
+
+ if (pathloc->node_access == pathloc->mt_entry->mt_fs_root.node_access){
+
+ /*
+ * Am I at the root of all filesystems?
+ */
+
+ if ( pathloc->node_access == rtems_filesystem_root.node_access ) {
+ break;
+
+ } else {
+ newloc = pathloc->mt_entry->mt_point_node;
+ *pathloc = newloc;
+ return (*pathloc->ops->evalformake_h)( &path[i-len], pathloc, name );
+ }
+ } else {
+
+ if ( !node->Parent )
+ rtems_set_errno_and_return_minus_one( ENOENT );
+
+ node = node->Parent;
+ }
+
+ pathloc->node_access = node;
+ break;
+
+ case IMFS_NAME:
+
+ if ( node->type == IMFS_HARD_LINK ) {
+
+ result = IMFS_evaluate_link( pathloc, 0 );
+ if ( result == -1 )
+ return -1;
+
+ } else if ( node->type == IMFS_SYM_LINK ) {
+
+ result = IMFS_evaluate_link( pathloc, 0 );
+
+ if ( result == -1 )
+ return -1;
+ }
+
+ node = pathloc->node_access;
+ if ( !node )
+ rtems_set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Only a directory can be decended into.
+ */
+
+ if ( node->type != IMFS_DIRECTORY )
+ rtems_set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * If we are at a node that is a mount point. Set loc to the
+ * new fs root node and let them finish evaluating the path.
+ */
+
+ if ( node->info.directory.mt_fs != NULL ) {
+ newloc = node->info.directory.mt_fs->mt_fs_root;
+ *pathloc = newloc;
+ return (*pathloc->ops->evalformake_h)( &path[i-len], pathloc, name );
+ }
+
+ /*
+ * Otherwise find the token name in the present location.
+ */
+
+ node = IMFS_find_match_in_dir( node, token );
+
+ /*
+ * If there is no node we have found the name of the node we
+ * wish to create.
+ */
+
+ if ( ! node )
+ done = TRUE;
+ else
+ pathloc->node_access = node;
+
+ break;
+
+ case IMFS_NO_MORE_PATH:
+ rtems_set_errno_and_return_minus_one( EEXIST );
+ break;
+
+ case IMFS_INVALID_TOKEN:
+ rtems_set_errno_and_return_minus_one( ENAMETOOLONG );
+ break;
+
+ case IMFS_CURRENT_DIR:
+ break;
+ }
+ }
+
+ *name = &path[ i - len ];
+
+ /*
+ * We have evaluated the path as far as we can.
+ * Verify there is not any invalid stuff at the end of the name.
+ */
+
+ for( ; path[i] != '\0'; i++) {
+ if ( !IMFS_is_separator( path[ i ] ) )
+ rtems_set_errno_and_return_minus_one( ENOENT );
+ }
+
+ /*
+ * Verify we can execute and write to this directory.
+ */
+
+ result = IMFS_Set_handlers( pathloc );
+
+ /*
+ * The returned node must be a directory
+ */
+ node = pathloc->node_access;
+ if ( node->type != IMFS_DIRECTORY )
+ rtems_set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * We must have Write and execute permission on the returned node.
+ */
+
+ if ( !IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_WX ) )
+ rtems_set_errno_and_return_minus_one( EACCES );
+
+ return result;
+}
+
+
+/*
+ * IMFS_eval_path
+ *
+ * The following routine evaluate path for a node that wishes to be
+ * accessed with mode. pathloc is returned with a pointer to the
+ * node to be accessed.
+ */
+
+int IMFS_eval_path(
+ const char *pathname, /* IN */
+ int flags, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+)
+{
+ int i = 0;
+ int len;
+ IMFS_token_types type = IMFS_CURRENT_DIR;
+ char token[ IMFS_NAME_MAX + 1 ];
+ rtems_filesystem_location_info_t newloc;
+ IMFS_jnode_t *node;
+ int result;
+
+ if ( !rtems_libio_is_valid_perms( flags ) ) {
+ assert( 0 );
+ rtems_set_errno_and_return_minus_one( EIO );
+ }
+
+ /*
+ * This was filled in by the caller and is valid in the
+ * mount table.
+ */
+
+ node = pathloc->node_access;
+
+ /*
+ * Evaluate all tokens until we are done or an error occurs.
+ */
+
+ while( (type != IMFS_NO_MORE_PATH) && (type != IMFS_INVALID_TOKEN) ) {
+
+ type = IMFS_get_token( &pathname[i], token, &len );
+ i += len;
+
+ if ( !pathloc->node_access )
+ rtems_set_errno_and_return_minus_one( ENOENT );
+
+ /*
+ * I cannot move out of this directory without execute permission.
+ */
+ if ( type != IMFS_NO_MORE_PATH )
+ if ( node->type == IMFS_DIRECTORY )
+ if ( !IMFS_evaluate_permission( pathloc, RTEMS_LIBIO_PERMS_SEARCH ) )
+ rtems_set_errno_and_return_minus_one( EACCES );
+
+ node = pathloc->node_access;
+
+ switch( type ) {
+ case IMFS_UP_DIR:
+ /*
+ * Am I at the root of all filesystems? (chroot'ed?)
+ */
+
+ if ( pathloc->node_access == rtems_filesystem_root.node_access )
+ break; /* Throw out the .. in this case */
+
+ /*
+ * Am I at the root of this mounted filesystem?
+ */
+
+ if (pathloc->node_access ==
+ pathloc->mt_entry->mt_fs_root.node_access) {
+
+ /*
+ * Am I at the root of all filesystems?
+ */
+
+ if ( pathloc->node_access == rtems_filesystem_root.node_access ) {
+ break; /* Throw out the .. in this case */
+ } else {
+ newloc = pathloc->mt_entry->mt_point_node;
+ *pathloc = newloc;
+ return (*pathloc->ops->evalpath_h)(&(pathname[i-len]),flags,pathloc);
+ }
+ } else {
+
+ if ( !node->Parent )
+ rtems_set_errno_and_return_minus_one( ENOENT );
+
+ node = node->Parent;
+ pathloc->node_access = node;
+
+ }
+
+ pathloc->node_access = node;
+ break;
+
+ case IMFS_NAME:
+ /*
+ * If we are at a link follow it.
+ */
+
+ if ( node->type == IMFS_HARD_LINK ) {
+
+ IMFS_evaluate_hard_link( pathloc, 0 );
+
+ node = pathloc->node_access;
+ if ( !node )
+ rtems_set_errno_and_return_minus_one( ENOTDIR );
+
+ } else if ( node->type == IMFS_SYM_LINK ) {
+
+ result = IMFS_evaluate_sym_link( pathloc, 0 );
+
+ node = pathloc->node_access;
+ if ( result == -1 )
+ return -1;
+ }
+
+ /*
+ * Only a directory can be decended into.
+ */
+
+ if ( node->type != IMFS_DIRECTORY )
+ rtems_set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * If we are at a node that is a mount point. Set loc to the
+ * new fs root node and let them finish evaluating the path.
+ */
+
+ if ( node->info.directory.mt_fs != NULL ) {
+ newloc = node->info.directory.mt_fs->mt_fs_root;
+ *pathloc = newloc;
+ return (*pathloc->ops->evalpath_h)( &pathname[i-len], flags, pathloc );
+ }
+
+ /*
+ * Otherwise find the token name in the present location.
+ */
+
+ node = IMFS_find_match_in_dir( node, token );
+ if ( !node )
+ rtems_set_errno_and_return_minus_one( ENOENT );
+
+ /*
+ * Set the node access to the point we have found.
+ */
+
+ pathloc->node_access = node;
+ break;
+
+ case IMFS_NO_MORE_PATH:
+ case IMFS_CURRENT_DIR:
+ break;
+
+ case IMFS_INVALID_TOKEN:
+ rtems_set_errno_and_return_minus_one( ENAMETOOLONG );
+ break;
+
+ }
+ }
+
+ /*
+ * Always return the root node.
+ *
+ * If we are at a node that is a mount point. Set loc to the
+ * new fs root node and let let the mounted filesystem set the handlers.
+ *
+ * NOTE: The behavior of stat() on a mount point appears to be questionable.
+ */
+
+ if ( node->type == IMFS_DIRECTORY ) {
+ if ( node->info.directory.mt_fs != NULL ) {
+ newloc = node->info.directory.mt_fs->mt_fs_root;
+ *pathloc = newloc;
+ return (*pathloc->ops->evalpath_h)( &pathname[i-len], flags, pathloc );
+ } else {
+ result = IMFS_Set_handlers( pathloc );
+ }
+ } else {
+ result = IMFS_Set_handlers( pathloc );
+ }
+
+ /*
+ * Verify we have the correct permissions for this node.
+ */
+
+ if ( !IMFS_evaluate_permission( pathloc, flags ) )
+ rtems_set_errno_and_return_minus_one( EACCES );
+
+ return result;
+}
diff --git a/cpukit/libfs/src/imfs/imfs_fchmod.c b/cpukit/libfs/src/imfs/imfs_fchmod.c
new file mode 100644
index 0000000000..4d30b98781
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_fchmod.c
@@ -0,0 +1,84 @@
+/*
+ * IMFS file change mode routine.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+#include "imfs.h"
+
+int IMFS_fchmod(
+ rtems_filesystem_location_info_t *loc,
+ mode_t mode
+)
+{
+ IMFS_jnode_t *jnode;
+#if defined(RTEMS_POSIX_API)
+ uid_t st_uid;
+#endif
+ int IMFS_memfile_write(
+ IMFS_jnode_t *the_jnode,
+ off_t start,
+ const unsigned char *source,
+ unsigned int length
+ );
+
+
+ jnode = loc->node_access;
+
+ /*
+ * Verify I am the owner of the node or the super user.
+ */
+#if defined(RTEMS_POSIX_API)
+ st_uid = geteuid();
+
+ if ( ( st_uid != jnode->st_uid ) && ( st_uid != 0 ) )
+ rtems_set_errno_and_return_minus_one( EPERM );
+#endif
+
+ /*
+ * Change only the RWX permissions on the jnode to mode.
+ */
+ if ( mode & (~ (S_IRWXU | S_IRWXG | S_IRWXO ) ) )
+ rtems_set_errno_and_return_minus_one( EPERM );
+
+ /*
+ * If we make a linear-file writeable, construct a block file
+ * from it first.
+ */
+ if ( (jnode->type == IMFS_LINEAR_FILE) &&
+ (mode & (S_IWUSR | S_IWGRP | S_IWOTH)) )
+ {
+ uint32_t count = jnode->info.linearfile.size;
+ const unsigned char *buffer = jnode->info.linearfile.direct;
+
+ jnode->type = IMFS_MEMORY_FILE;
+ jnode->info.file.size = 0;
+ jnode->info.file.indirect = 0;
+ jnode->info.file.doubly_indirect = 0;
+ jnode->info.file.triply_indirect = 0;
+ if (IMFS_memfile_write(jnode, 0, buffer, count) == -1)
+ return(-1);
+ }
+
+ jnode->st_mode &= ~(S_IRWXU | S_IRWXG | S_IRWXO);
+ jnode->st_mode |= mode;
+
+ IMFS_update_ctime( jnode );
+
+ return 0;
+}
diff --git a/cpukit/libfs/src/imfs/imfs_fcntl.c b/cpukit/libfs/src/imfs/imfs_fcntl.c
new file mode 100644
index 0000000000..ca802b8331
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_fcntl.c
@@ -0,0 +1,28 @@
+/*
+ * IMFS_fcntl
+ *
+ * The following routine does a fcntl on an IMFS node.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "imfs.h"
+
+int IMFS_fcntl(
+ int cmd,
+ rtems_libio_t *iop
+)
+{
+ return 0;
+}
diff --git a/cpukit/libfs/src/imfs/imfs_fdatasync.c b/cpukit/libfs/src/imfs/imfs_fdatasync.c
new file mode 100644
index 0000000000..6b107bfaf8
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_fdatasync.c
@@ -0,0 +1,29 @@
+/*
+ * IMFS_fdatasync
+ *
+ * The following routine does a sync on an IMFS node. The In Memory
+ * File System is always in sync, therefore this routine always returns
+ * pass.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "imfs.h"
+
+int IMFS_fdatasync(
+ rtems_libio_t *iop
+)
+{
+ return 0;
+}
diff --git a/cpukit/libfs/src/imfs/imfs_free.c b/cpukit/libfs/src/imfs/imfs_free.c
new file mode 100644
index 0000000000..affbcaa044
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_free.c
@@ -0,0 +1,39 @@
+/*
+ * Free IMFS Node Support Routines
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+
+#include <rtems/libio_.h>
+#include "imfs.h"
+
+/*
+ * IMFS_freenodinfo
+ *
+ * This routine is the IMFS free node handler for the file system
+ * operations table.
+ *
+ * The In Memory File System keeps its nodes in memory. This routine
+ * is for file sytems that do not.
+ */
+
+int IMFS_freenodinfo(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+)
+{
+ return 0;
+}
diff --git a/cpukit/libfs/src/imfs/imfs_fsunmount.c b/cpukit/libfs/src/imfs/imfs_fsunmount.c
new file mode 100644
index 0000000000..c87b2e665b
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_fsunmount.c
@@ -0,0 +1,96 @@
+/*
+ * IMFS Initialization
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h> /* for mkdir */
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <assert.h>
+
+#include "imfs.h"
+#include <rtems/libio_.h>
+
+#if defined(IMFS_DEBUG)
+#include <stdio.h>
+#endif
+
+/*
+ * IMFS_fsunmount
+ */
+
+#define jnode_get_control( jnode ) \
+ (&jnode->info.directory.Entries)
+
+#define jnode_has_no_children( jnode ) \
+ Chain_Is_empty( jnode_get_control( jnode ) )
+
+#define jnode_has_children( jnode ) \
+ ( ! jnode_has_no_children( jnode ) )
+
+#define jnode_get_first_child( jnode ) \
+ ((IMFS_jnode_t *)( Chain_Head( jnode_get_control( jnode ) )->next))
+
+int IMFS_fsunmount(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ IMFS_jnode_t *jnode;
+ IMFS_jnode_t *next;
+ rtems_filesystem_location_info_t loc;
+ int result = 0;
+
+ /*
+ * Traverse tree that starts at the mt_fs_root and deallocate memory
+ * associated memory space
+ */
+
+ jnode = (IMFS_jnode_t *)temp_mt_entry->mt_fs_root.node_access;
+ loc = temp_mt_entry->mt_fs_root;
+
+ /*
+ * Set this to null to indicate that it is being unmounted.
+ */
+
+ temp_mt_entry->mt_fs_root.node_access = NULL;
+
+ do {
+ next = jnode->Parent;
+ loc.node_access = (void *)jnode;
+ IMFS_Set_handlers( &loc );
+
+ if ( jnode->type != IMFS_DIRECTORY ) {
+ result = IMFS_unlink( &loc );
+ if (result != 0)
+ return -1;
+ jnode = next;
+ } else if ( jnode_has_no_children( jnode ) ) {
+ result = IMFS_unlink( &loc );
+ if (result != 0)
+ return -1;
+ jnode = next;
+ }
+ if ( jnode != NULL ) {
+ if ( jnode->type == IMFS_DIRECTORY ) {
+ if ( jnode_has_children( jnode ) )
+ jnode = jnode_get_first_child( jnode );
+ }
+ }
+ } while (jnode != NULL);
+
+ return 0;
+}
diff --git a/cpukit/libfs/src/imfs/imfs_getchild.c b/cpukit/libfs/src/imfs/imfs_getchild.c
new file mode 100644
index 0000000000..67663db8ea
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_getchild.c
@@ -0,0 +1,73 @@
+/*
+ * IMFS_find_match_in_dir()
+ *
+ * This routine returns the child name in the given directory.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <assert.h>
+#include <string.h>
+#include "imfs.h"
+
+static char dotname[2] = ".";
+static char dotdotname[3] = "..";
+
+IMFS_jnode_t *IMFS_find_match_in_dir(
+ IMFS_jnode_t *directory,
+ char *name
+)
+{
+ Chain_Node *the_node;
+ Chain_Control *the_chain;
+ IMFS_jnode_t *the_jnode;
+
+ /*
+ * Check for fatal errors. A NULL directory show a problem in the
+ * the IMFS code.
+ */
+
+ assert( directory );
+ if ( !name )
+ return 0;
+
+ assert( name );
+ if ( !directory )
+ return 0;
+
+ /*
+ * Check for "." and ".."
+ */
+
+ if ( !strcmp( name, dotname ) )
+ return directory;
+
+ if ( !strcmp( name, dotdotname ) )
+ return directory->Parent;
+
+ the_chain = &directory->info.directory.Entries;
+
+ for ( the_node = the_chain->first;
+ !_Chain_Is_tail( the_chain, the_node );
+ the_node = the_node->next ) {
+
+ the_jnode = (IMFS_jnode_t *) the_node;
+
+ if ( !strcmp( name, the_jnode->name ) )
+ return the_jnode;
+ }
+
+ return 0;
+}
diff --git a/cpukit/libfs/src/imfs/imfs_gtkn.c b/cpukit/libfs/src/imfs/imfs_gtkn.c
new file mode 100644
index 0000000000..09f1ab0174
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_gtkn.c
@@ -0,0 +1,90 @@
+/*
+ * IMFS_get_token
+ *
+ * Routine to get a token (name or separator) from the path
+ * the length of the token is returned in token_len.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "imfs.h"
+#include <rtems/libio_.h>
+
+IMFS_token_types IMFS_get_token(
+ const char *path,
+ char *token,
+ int *token_len
+)
+{
+ register int i = 0;
+ IMFS_token_types type = IMFS_NAME;
+ register char c;
+
+ /*
+ * Copy a name into token. (Remember NULL is a token.)
+ */
+ c = path[i];
+ while ( (!IMFS_is_separator(c)) && (i <= IMFS_NAME_MAX) ) {
+
+ token[i] = c;
+
+ if ( i == IMFS_NAME_MAX )
+ return IMFS_INVALID_TOKEN;
+
+ if ( !IMFS_is_valid_name_char(c) )
+ type = IMFS_INVALID_TOKEN;
+
+ c = path [++i];
+ }
+
+ /*
+ * Copy a seperator into token.
+ */
+
+ if ( i == 0 ) {
+ token[i] = c;
+
+ if ( token[i] != '\0' ) {
+ i++;
+ type = IMFS_CURRENT_DIR;
+ } else {
+ type = IMFS_NO_MORE_PATH;
+ }
+ } else if (token[ i-1 ] != '\0') {
+ token[i] = '\0';
+ }
+
+ /*
+ * Set token_len to the number of characters copied.
+ */
+
+ *token_len = i;
+
+ /*
+ * If we copied something that was not a seperator see if
+ * it was a special name.
+ */
+
+ if ( type == IMFS_NAME ) {
+ if ( strcmp( token, "..") == 0 )
+ type = IMFS_UP_DIR;
+ else if ( strcmp( token, "." ) == 0 )
+ type = IMFS_CURRENT_DIR;
+ }
+
+ return type;
+}
diff --git a/cpukit/libfs/src/imfs/imfs_handlers_device.c b/cpukit/libfs/src/imfs/imfs_handlers_device.c
new file mode 100644
index 0000000000..fa373b8b91
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_handlers_device.c
@@ -0,0 +1,41 @@
+/*
+ * Device Operations Table for the IMFS
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+
+#include "imfs.h"
+
+/*
+ * Handler table for IMFS device nodes
+ */
+
+rtems_filesystem_file_handlers_r IMFS_device_handlers = {
+ device_open,
+ device_close,
+ device_read,
+ device_write,
+ device_ioctl,
+ device_lseek,
+ IMFS_stat,
+ IMFS_fchmod,
+ NULL, /* ftruncate */
+ NULL, /* fpathconf */
+ NULL, /* fsync */
+ NULL, /* fdatasync */
+ NULL, /* fcntl */
+ IMFS_rmnod
+};
diff --git a/cpukit/libfs/src/imfs/imfs_handlers_directory.c b/cpukit/libfs/src/imfs/imfs_handlers_directory.c
new file mode 100644
index 0000000000..b9453a0725
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_handlers_directory.c
@@ -0,0 +1,41 @@
+/*
+ * Operations Table for Directories for the IMFS
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+
+#include "imfs.h"
+
+/*
+ * Set of operations handlers for operations on directories.
+ */
+
+rtems_filesystem_file_handlers_r IMFS_directory_handlers = {
+ imfs_dir_open,
+ imfs_dir_close,
+ imfs_dir_read,
+ NULL, /* write */
+ NULL, /* ioctl */
+ imfs_dir_lseek,
+ imfs_dir_fstat,
+ IMFS_fchmod,
+ NULL, /* ftruncate */
+ NULL, /* fpathconf */
+ NULL, /* fsync */
+ IMFS_fdatasync,
+ IMFS_fcntl,
+ imfs_dir_rmnod
+};
diff --git a/cpukit/libfs/src/imfs/imfs_handlers_link.c b/cpukit/libfs/src/imfs/imfs_handlers_link.c
new file mode 100644
index 0000000000..f4b926dcab
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_handlers_link.c
@@ -0,0 +1,41 @@
+/*
+ * Link Operations Table for the IMFS
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+
+#include "imfs.h"
+
+/*
+ * Handler table for IMFS device nodes
+ */
+
+rtems_filesystem_file_handlers_r IMFS_link_handlers = {
+ NULL, /* open */
+ NULL, /* close */
+ NULL, /* read */
+ NULL, /* write */
+ NULL, /* ioctl */
+ NULL, /* lseek */
+ IMFS_stat, /* stat */
+ NULL, /* fchmod */
+ NULL, /* ftruncate */
+ NULL, /* fpathconf */
+ NULL, /* fsync */
+ NULL, /* fdatasync */
+ NULL, /* fcntl */
+ IMFS_rmnod
+};
diff --git a/cpukit/libfs/src/imfs/imfs_handlers_memfile.c b/cpukit/libfs/src/imfs/imfs_handlers_memfile.c
new file mode 100644
index 0000000000..1764544e69
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_handlers_memfile.c
@@ -0,0 +1,58 @@
+/*
+ * Memfile Operations Tables for the IMFS
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+
+#include "imfs.h"
+
+/*
+ * Set of operations handlers for operations on memfile entities.
+ */
+
+rtems_filesystem_file_handlers_r IMFS_linearfile_handlers = {
+ memfile_open,
+ memfile_close,
+ memfile_read,
+ NULL, /* write */
+ memfile_ioctl,
+ memfile_lseek,
+ IMFS_stat,
+ IMFS_fchmod,
+ NULL, /* ftruncate */
+ NULL, /* fpathconf */
+ IMFS_fdatasync, /* fsync */
+ IMFS_fdatasync,
+ IMFS_fcntl,
+ memfile_rmnod
+};
+
+rtems_filesystem_file_handlers_r IMFS_memfile_handlers = {
+ memfile_open,
+ memfile_close,
+ memfile_read,
+ memfile_write,
+ memfile_ioctl,
+ memfile_lseek,
+ IMFS_stat,
+ IMFS_fchmod,
+ memfile_ftruncate,
+ NULL, /* fpathconf */
+ IMFS_fdatasync, /* fsync */
+ IMFS_fdatasync,
+ IMFS_fcntl,
+ memfile_rmnod
+};
diff --git a/cpukit/libfs/src/imfs/imfs_init.c b/cpukit/libfs/src/imfs/imfs_init.c
new file mode 100644
index 0000000000..6582e72614
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_init.c
@@ -0,0 +1,70 @@
+/*
+ * IMFS Initialization
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h> /* for mkdir */
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <assert.h>
+
+#include "imfs.h"
+#include <rtems/libio_.h>
+
+#if defined(IMFS_DEBUG)
+#include <stdio.h>
+#endif
+
+/*
+ * IMFS file system operations table
+ */
+
+rtems_filesystem_operations_table IMFS_ops = {
+ IMFS_eval_path,
+ IMFS_evaluate_for_make,
+ IMFS_link,
+ IMFS_unlink,
+ IMFS_node_type,
+ IMFS_mknod,
+ IMFS_chown,
+ IMFS_freenodinfo,
+ IMFS_mount,
+ IMFS_initialize,
+ IMFS_unmount,
+ IMFS_fsunmount,
+ IMFS_utime,
+ IMFS_evaluate_link,
+ IMFS_symlink,
+ IMFS_readlink
+};
+
+/*
+ * IMFS_initialize
+ */
+
+int IMFS_initialize(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ return IMFS_initialize_support(
+ temp_mt_entry,
+ &IMFS_ops,
+ &IMFS_linearfile_handlers,
+ &IMFS_memfile_handlers,
+ &IMFS_directory_handlers
+ );
+}
diff --git a/cpukit/libfs/src/imfs/imfs_initsupp.c b/cpukit/libfs/src/imfs/imfs_initsupp.c
new file mode 100644
index 0000000000..070434343e
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_initsupp.c
@@ -0,0 +1,89 @@
+/*
+ * IMFS Initialization
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h> /* for mkdir */
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <assert.h>
+
+#include "imfs.h"
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+#if defined(IMFS_DEBUG)
+#include <stdio.h>
+#endif
+
+/*
+ * IMFS_initialize
+ */
+
+int IMFS_initialize_support(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry,
+ rtems_filesystem_operations_table *op_table,
+ rtems_filesystem_file_handlers_r *linearfile_handlers,
+ rtems_filesystem_file_handlers_r *memfile_handlers,
+ rtems_filesystem_file_handlers_r *directory_handlers
+)
+{
+ IMFS_fs_info_t *fs_info;
+ IMFS_jnode_t *jnode;
+
+ /*
+ * Create the root node
+ *
+ * NOTE: UNIX root is 755 and owned by root/root (0/0).
+ */
+
+ temp_mt_entry->mt_fs_root.node_access = IMFS_create_node(
+ NULL,
+ IMFS_DIRECTORY,
+ "",
+ ( S_IFDIR | 0755 ),
+ NULL
+ );
+
+ temp_mt_entry->mt_fs_root.handlers = directory_handlers;
+ temp_mt_entry->mt_fs_root.ops = op_table;
+ temp_mt_entry->pathconf_limits_and_options = IMFS_LIMITS_AND_OPTIONS;
+
+ /*
+ * Create custom file system data.
+ */
+ fs_info = calloc( 1, sizeof( IMFS_fs_info_t ) );
+ if ( !fs_info ){
+ free(temp_mt_entry->mt_fs_root.node_access);
+ rtems_set_errno_and_return_minus_one(ENOMEM);
+ }
+ temp_mt_entry->fs_info = fs_info;
+
+ /*
+ * Set st_ino for the root to 1.
+ */
+
+ fs_info->ino_count = 1;
+ fs_info->linearfile_handlers = linearfile_handlers;
+ fs_info->memfile_handlers = memfile_handlers;
+ fs_info->directory_handlers = directory_handlers;
+
+ jnode = temp_mt_entry->mt_fs_root.node_access;
+ jnode->st_ino = fs_info->ino_count;
+
+ return 0;
+}
diff --git a/cpukit/libfs/src/imfs/imfs_link.c b/cpukit/libfs/src/imfs/imfs_link.c
new file mode 100644
index 0000000000..43c1613cfc
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_link.c
@@ -0,0 +1,75 @@
+/*
+ * IMFS_link
+ *
+ * The following rouine creates a new link node under parent with the
+ * name given in name. The link node is set to point to the node at
+ * to_loc.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include "imfs.h"
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int IMFS_link(
+ rtems_filesystem_location_info_t *to_loc, /* IN */
+ rtems_filesystem_location_info_t *parent_loc, /* IN */
+ const char *token /* IN */
+)
+{
+ IMFS_types_union info;
+ IMFS_jnode_t *new_node;
+ char new_name[ IMFS_NAME_MAX + 1 ];
+ int i;
+
+ /*
+ * Verify this node can be linked to.
+ */
+
+ info.hard_link.link_node = to_loc->node_access;
+ if ( info.hard_link.link_node->st_nlink >= LINK_MAX )
+ rtems_set_errno_and_return_minus_one( EMLINK );
+
+ /*
+ * Remove any separators at the end of the string.
+ */
+
+ IMFS_get_token( token, new_name, &i );
+
+ /*
+ * Create a new link node.
+ */
+
+ new_node = IMFS_create_node(
+ parent_loc,
+ IMFS_HARD_LINK,
+ new_name,
+ ( S_IFLNK | ( S_IRWXU | S_IRWXG | S_IRWXO )),
+ &info
+ );
+
+ if ( !new_node )
+ rtems_set_errno_and_return_minus_one( ENOMEM );
+
+ /*
+ * Increment the link count of the node being pointed to.
+ */
+
+ info.hard_link.link_node->st_nlink++;
+ IMFS_update_ctime( info.hard_link.link_node );
+
+ return 0;
+}
diff --git a/cpukit/libfs/src/imfs/imfs_load_tar.c b/cpukit/libfs/src/imfs/imfs_load_tar.c
new file mode 100644
index 0000000000..fd9d226003
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_load_tar.c
@@ -0,0 +1,260 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/**************************************************************************
+ * This file implements the "mount" procedure for tar-based IMFS
+ * extensions. The TAR is not actually mounted under the IMFS.
+ * Directories from the TAR file are created as usual in the IMFS.
+ * File entries are created as IMFS_LINEAR_FILE nodes with their nods
+ * pointing to addresses in the TAR image.
+ *************************************************************************/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <string.h>
+
+#include <rtems.h>
+#include <rtems/libio_.h>
+#include <rtems/chain.h>
+#include <rtems/imfs.h>
+
+
+/**************************************************************************
+ * TAR file format:
+ *
+ * Offset Length Contents
+ * 0 100 bytes File name ('\0' terminated, 99 maxmum length)
+ * 100 8 bytes File mode (in octal ascii)
+ * 108 8 bytes User ID (in octal ascii)
+ * 116 8 bytes Group ID (in octal ascii)
+ * 124 12 bytes File size (s) (in octal ascii)
+ * 136 12 bytes Modify time (in octal ascii)
+ * 148 8 bytes Header checksum (in octal ascii)
+ * 156 1 bytes Link flag
+ * 157 100 bytes Linkname ('\0' terminated, 99 maxmum length)
+ * 257 8 bytes Magic ("ustar \0")
+ * 265 32 bytes User name ('\0' terminated, 31 maxmum length)
+ * 297 32 bytes Group name ('\0' terminated, 31 maxmum length)
+ * 329 8 bytes Major device ID (in octal ascii)
+ * 337 8 bytes Minor device ID (in octal ascii)
+ * 345 167 bytes Padding
+ * 512 (s+p)bytes File contents (s+p) := (((s) + 511) & ~511),
+ * round up to 512 bytes
+ *
+ * Checksum:
+ * int i, sum;
+ * char* header = tar_header_pointer;
+ * sum = 0;
+ * for(i = 0; i < 512; i++)
+ * sum += 0xFF & header[i];
+ *************************************************************************/
+
+#define LF_OLDNORMAL '\0' /* Normal disk file, Unix compatible */
+#define LF_NORMAL '0' /* Normal disk file */
+#define LF_LINK '1' /* Link to previously dumped file */
+#define LF_SYMLINK '2' /* Symbolic link */
+#define LF_CHR '3' /* Character special file */
+#define LF_BLK '4' /* Block special file */
+#define LF_DIR '5' /* Directory */
+#define LF_FIFO '6' /* FIFO special file */
+#define LF_CONFIG '7' /* Contiguous file */
+
+#define MAX_NAME_FIELD_SIZE 99
+
+#define MIN(a,b) ((a)>(b)?(b):(a))
+
+static unsigned long octal2ulong(char *octascii, int len);
+static int compute_tar_header_checksum(char *bufr);
+
+/**************************************************************************
+ * rtems_tarfs_load
+ *
+ * Here we create the mountpoint directory and load the tarfs at
+ * that node. Once the IMFS has been mounted, we work through the
+ * tar image and perform as follows:
+ * - For directories, simply call mkdir(). The IMFS creates nodes as
+ * needed.
+ * - For files, we make our own calls to IMFS eval_for_make and
+ * create_node.
+ *************************************************************************/
+int
+rtems_tarfs_load(char *mountpoint,
+ unsigned char *tar_image,
+ unsigned long tar_size)
+{
+ rtems_filesystem_location_info_t root_loc;
+ rtems_filesystem_location_info_t loc;
+ char *hdr_ptr;
+ char filename[100];
+ char full_filename[256];
+ int hdr_chksum;
+ unsigned char linkflag;
+ unsigned long file_size;
+ unsigned long file_mode;
+ int offset;
+ unsigned long nblocks;
+ IMFS_jnode_t *node;
+ int status;
+
+
+ status = rtems_filesystem_evaluate_path(mountpoint, 0, &root_loc, 0);
+ if (status != 0)
+ return(-1);
+
+ if (root_loc.ops != &IMFS_ops)
+ return(-1);
+
+ /***********************************************************************
+ * Create an IMFS node structure pointing to tar image memory.
+ **********************************************************************/
+ offset = 0;
+ while (1)
+ {
+ if (offset + 512 > tar_size)
+ break;
+
+ /******************************************************************
+ * Read a header.
+ ******************************************************************/
+ hdr_ptr = &tar_image[offset];
+ offset += 512;
+ if (strncmp(&hdr_ptr[257], "ustar ", 7))
+ break;
+
+ strncpy(filename, hdr_ptr, MAX_NAME_FIELD_SIZE);
+ filename[MAX_NAME_FIELD_SIZE] = '\0';
+
+ linkflag = hdr_ptr[156];
+ file_mode = octal2ulong(&hdr_ptr[100], 8);
+ file_size = octal2ulong(&hdr_ptr[124], 12);
+ hdr_chksum = (int)octal2ulong(&hdr_ptr[148], 8);
+
+ if (compute_tar_header_checksum(hdr_ptr) != hdr_chksum)
+ break;
+
+ /******************************************************************
+ * Generate an IMFS node depending on the file type.
+ * - For directories, just create directories as usual. IMFS
+ * will take care of the rest.
+ * - For files, create a file node with special tarfs properties.
+ *****************************************************************/
+ if (linkflag == LF_DIR)
+ {
+ strcpy(full_filename, mountpoint);
+ if (full_filename[strlen(full_filename)-1] != '/')
+ strcat(full_filename, "/");
+ strcat(full_filename, filename);
+ mkdir(full_filename, S_IRWXU | S_IRWXG | S_IRWXO);
+ }
+ /******************************************************************
+ * Create a LINEAR_FILE node if no user write permission.
+ *****************************************************************/
+ else if ((linkflag == LF_NORMAL) &&
+ ((file_mode & 0200) == 0000))
+ {
+ const char *name;
+
+ loc = root_loc;
+ if (IMFS_evaluate_for_make(filename, &loc, &name) == 0)
+ {
+ node = IMFS_create_node(&loc,
+ IMFS_LINEAR_FILE, (char *)name,
+ (S_IRUSR | S_IRGRP | S_IROTH) | S_IFREG,
+ NULL);
+ node->info.linearfile.size = file_size;
+ node->info.linearfile.direct = &tar_image[offset];
+ }
+
+ nblocks = (((file_size) + 511) & ~511) / 512;
+ offset += 512 * nblocks;
+ }
+ /******************************************************************
+ * Create a regular MEMORY_FILE if write permission exists.
+ *****************************************************************/
+ else if ((linkflag == LF_NORMAL) &&
+ ((file_mode & 0200) == 0200))
+ {
+ int fd;
+ int n, left, ptr;
+
+ strcpy(full_filename, mountpoint);
+ if (full_filename[strlen(full_filename)-1] != '/')
+ strcat(full_filename, "/");
+ strcat(full_filename, filename);
+
+ fd = creat(full_filename, S_IRUSR|S_IWUSR | S_IRGRP|S_IWGRP);
+ if (fd != -1)
+ {
+ left = file_size;
+ ptr = offset;
+ while ((n = write(fd, &tar_image[ptr], left)) > 0)
+ {
+ left -= n;
+ ptr += n;
+ }
+ close(fd);
+ }
+
+ nblocks = (((file_size) + 511) & ~511) / 512;
+ offset += 512 * nblocks;
+ }
+ }
+
+ return(status);
+}
+
+/**************************************************************************
+ * This converts octal ASCII number representations into an
+ * unsigned long. Only support 32-bit numbers for now.
+ *************************************************************************/
+static unsigned long
+octal2ulong(char *octascii, int len)
+{
+ int i;
+ unsigned long num;
+ unsigned long mult;
+
+ num = 0;
+ mult = 1;
+ for (i=len-1; i>=0; i--)
+ {
+ if (octascii[i] < '0')
+ continue;
+ if (octascii[i] > '9')
+ continue;
+
+ num += mult*((unsigned long)(octascii[i] - '0'));
+ mult *= 8;
+ }
+ return(num);
+}
+
+
+/************************************************************************
+ * Compute the TAR checksum and check with the value in
+ * the archive. The checksum is computed over the entire
+ * header, but the checksum field is substituted with blanks.
+ ************************************************************************/
+static int
+compute_tar_header_checksum(char *bufr)
+{
+ int i, sum;
+
+
+ sum = 0;
+ for (i=0; i<512; i++)
+ {
+ if ((i >= 148) && (i < 156))
+ sum += 0xff & ' ';
+ else
+ sum += 0xff & bufr[i];
+ }
+ return(sum);
+}
diff --git a/cpukit/libfs/src/imfs/imfs_mknod.c b/cpukit/libfs/src/imfs/imfs_mknod.c
new file mode 100644
index 0000000000..abb9ab4052
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_mknod.c
@@ -0,0 +1,77 @@
+/*
+ * IMFS_mknod
+ *
+ * Routine to create a node in the IMFS file system.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "imfs.h"
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int IMFS_mknod(
+ const char *token, /* IN */
+ mode_t mode, /* IN */
+ dev_t dev, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+)
+{
+ IMFS_token_types type = 0;
+ IMFS_jnode_t *new_node;
+ int result;
+ char new_name[ IMFS_NAME_MAX + 1 ];
+ IMFS_types_union info;
+
+ IMFS_get_token( token, new_name, &result );
+
+ /*
+ * Figure out what type of IMFS node this is.
+ */
+
+ if ( S_ISDIR(mode) )
+ type = IMFS_DIRECTORY;
+ else if ( S_ISREG(mode) )
+ type = IMFS_MEMORY_FILE;
+ else if ( S_ISBLK(mode) || S_ISCHR(mode) ) {
+ type = IMFS_DEVICE;
+ rtems_filesystem_split_dev_t( dev, info.device.major, info.device.minor );
+ } else {
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ }
+
+ /*
+ * Allocate and fill in an IMFS jnode
+ */
+
+ new_node = IMFS_create_node(
+ pathloc,
+ type,
+ new_name,
+ mode,
+ &info
+ );
+
+ if ( !new_node )
+ rtems_set_errno_and_return_minus_one( ENOMEM );
+
+ return 0;
+}
diff --git a/cpukit/libfs/src/imfs/imfs_mount.c b/cpukit/libfs/src/imfs/imfs_mount.c
new file mode 100644
index 0000000000..3ec16da3f7
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_mount.c
@@ -0,0 +1,53 @@
+/*
+ * IMFS_mount
+ *
+ * This routine will look at a mount table entry that we are going to
+ * add to the mount table. If the mount point rtems_filesystem
+ * location_info_t struct refers to a node that is a directory,
+ * the node will be marked as a mount point by setting its directory.mt_fs
+ * pointer to point to the mount table entry that we are about to add
+ * to the mount table chain.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+
+#include "imfs.h"
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int IMFS_mount(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+)
+{
+ IMFS_jnode_t *node;
+
+ node = mt_entry->mt_point_node.node_access;
+
+ /*
+ * Is the node that we are mounting onto a directory node ?
+ */
+
+ if ( node->type != IMFS_DIRECTORY )
+ rtems_set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Set mt_fs pointer to point to the mount table entry for
+ * the mounted file system.
+ */
+
+ node->info.directory.mt_fs = mt_entry;
+ return 0;
+}
diff --git a/cpukit/libfs/src/imfs/imfs_ntype.c b/cpukit/libfs/src/imfs/imfs_ntype.c
new file mode 100644
index 0000000000..f80182b144
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_ntype.c
@@ -0,0 +1,32 @@
+/*
+ * IMFS_node_type
+ *
+ * The following verifies that returns the type of node that the
+ * loc refers to.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include "imfs.h"
+
+rtems_filesystem_node_types_t IMFS_node_type(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+)
+{
+ IMFS_jnode_t *node;
+
+ node = pathloc->node_access;
+ return node->type;
+}
diff --git a/cpukit/libfs/src/imfs/imfs_readlink.c b/cpukit/libfs/src/imfs/imfs_readlink.c
new file mode 100644
index 0000000000..6b3d1acafe
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_readlink.c
@@ -0,0 +1,44 @@
+/*
+ * IMFS_readlink
+ *
+ * The following rouine puts the symblic links destination name into
+ * buff.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include "imfs.h"
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int IMFS_readlink(
+ rtems_filesystem_location_info_t *loc,
+ char *buf, /* OUT */
+ size_t bufsize
+)
+{
+ IMFS_jnode_t *node;
+ int i;
+
+ node = loc->node_access;
+
+ if ( node->type != IMFS_SYM_LINK )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ for( i=0; ((i<bufsize) && (node->info.sym_link.name[i] != '\0')); i++ )
+ buf[i] = node->info.sym_link.name[i];
+
+ return i;
+}
diff --git a/cpukit/libfs/src/imfs/imfs_rmnod.c b/cpukit/libfs/src/imfs/imfs_rmnod.c
new file mode 100644
index 0000000000..d5e32378ad
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_rmnod.c
@@ -0,0 +1,79 @@
+/*
+ * IMFS Node Removal Handler
+ *
+ * This file contains the handler used to remove a node when a file type
+ * does not require special actions.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <rtems/libio_.h>
+
+#include "imfs.h"
+
+/*
+ * IMFS_rmnod
+ */
+
+int IMFS_rmnod(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = (IMFS_jnode_t *) pathloc->node_access;
+
+ /*
+ * Take the node out of the parent's chain that contains this node
+ */
+
+ if ( the_jnode->Parent != NULL ) {
+ Chain_Extract( (Chain_Node *) the_jnode );
+ the_jnode->Parent = NULL;
+ }
+
+ /*
+ * Decrement the link counter and see if we can free the space.
+ */
+
+ the_jnode->st_nlink--;
+ IMFS_update_ctime( the_jnode );
+
+ /*
+ * The file cannot be open and the link must be less than 1 to free.
+ */
+
+ if ( !rtems_libio_is_file_open( the_jnode ) && (the_jnode->st_nlink < 1) ) {
+
+ /*
+ * Is rtems_filesystem_current this node?
+ */
+
+ if ( rtems_filesystem_current.node_access == pathloc->node_access )
+ rtems_filesystem_current.node_access = NULL;
+
+ /*
+ * Free memory associated with a memory file.
+ */
+
+ free( the_jnode );
+ }
+
+ return 0;
+
+}
diff --git a/cpukit/libfs/src/imfs/imfs_stat.c b/cpukit/libfs/src/imfs/imfs_stat.c
new file mode 100644
index 0000000000..422e954ed1
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_stat.c
@@ -0,0 +1,68 @@
+/*
+ * IMFS_stat
+ *
+ * This routine provides a stat for the IMFS file system.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include "imfs.h"
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int IMFS_stat(
+ rtems_filesystem_location_info_t *loc,
+ struct stat *buf
+)
+{
+ IMFS_jnode_t *the_jnode;
+ IMFS_device_t *io;
+
+ the_jnode = loc->node_access;
+
+
+ switch ( the_jnode->type ) {
+
+ case IMFS_DEVICE:
+ io = &the_jnode->info.device;
+ buf->st_dev = rtems_filesystem_make_dev_t( io->major, io->minor );
+ break;
+
+ case IMFS_LINEAR_FILE:
+ case IMFS_MEMORY_FILE:
+ buf->st_size = the_jnode->info.file.size;
+ break;
+
+ case IMFS_SYM_LINK:
+ buf->st_size = 0;
+ break;
+
+ default:
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+ break;
+ }
+
+ buf->st_mode = the_jnode->st_mode;
+ buf->st_nlink = the_jnode->st_nlink;
+ buf->st_ino = the_jnode->st_ino;
+ buf->st_uid = the_jnode->st_uid;
+ buf->st_gid = the_jnode->st_gid;
+
+ buf->st_atime = the_jnode->stat_atime;
+ buf->st_mtime = the_jnode->stat_mtime;
+ buf->st_ctime = the_jnode->stat_ctime;
+
+ return 0;
+}
diff --git a/cpukit/libfs/src/imfs/imfs_symlink.c b/cpukit/libfs/src/imfs/imfs_symlink.c
new file mode 100644
index 0000000000..38072b9f69
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_symlink.c
@@ -0,0 +1,62 @@
+/*
+ * IMFS_symlink
+ *
+ * The following rouine creates a new symbolic link node under parent
+ * with the name given in name. The node is set to point to the node at
+ * to_loc.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include "imfs.h"
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int IMFS_symlink(
+ rtems_filesystem_location_info_t *parent_loc,
+ const char *link_name,
+ const char *node_name
+)
+{
+ IMFS_types_union info;
+ IMFS_jnode_t *new_node;
+ char new_name[ IMFS_NAME_MAX + 1 ];
+ int i;
+
+ /*
+ * Remove any separators at the end of the string.
+ */
+
+ IMFS_get_token( node_name, new_name, &i );
+
+ info.sym_link.name = link_name;
+
+ /*
+ * Create a new link node.
+ */
+
+ new_node = IMFS_create_node(
+ parent_loc,
+ IMFS_SYM_LINK,
+ new_name,
+ ( S_IFLNK | ( S_IRWXU | S_IRWXG | S_IRWXO )),
+ &info
+ );
+
+ if ( !new_node )
+ rtems_set_errno_and_return_minus_one( ENOMEM );
+
+ return 0;
+}
diff --git a/cpukit/libfs/src/imfs/imfs_unixstub.c b/cpukit/libfs/src/imfs/imfs_unixstub.c
new file mode 100644
index 0000000000..d642b260d5
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_unixstub.c
@@ -0,0 +1,74 @@
+/*
+ * IMFS Stub for UNIX configuration
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h> /* for mkdir */
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <assert.h>
+
+#include "imfs.h"
+#include <rtems/libio_.h>
+
+#include <stdio.h>
+
+/*
+ * IMFS file system operations table
+ */
+
+rtems_filesystem_operations_table IMFS_ops = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+/*
+ * IMFS file system operations table
+ */
+
+rtems_filesystem_operations_table miniIMFS_ops = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
diff --git a/cpukit/libfs/src/imfs/imfs_unlink.c b/cpukit/libfs/src/imfs/imfs_unlink.c
new file mode 100644
index 0000000000..b416a09b8e
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_unlink.c
@@ -0,0 +1,81 @@
+/*
+ * IMFS_unlink
+ *
+ * Routine to remove a link node from the tree.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <stdlib.h>
+
+#include "imfs.h"
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int IMFS_unlink(
+ rtems_filesystem_location_info_t *loc /* IN */
+)
+{
+ IMFS_jnode_t *node;
+ rtems_filesystem_location_info_t the_link;
+ int result = 0;
+
+ node = loc->node_access;
+
+ /*
+ * Decrement the link counter of node pointed to and free the
+ * space.
+ */
+
+ /*
+ * If this is the last last pointer to the node
+ * free the node.
+ */
+
+ if ( node->type == IMFS_HARD_LINK ) {
+
+ if ( !node->info.hard_link.link_node )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ the_link = *loc;
+ the_link.node_access = node->info.hard_link.link_node;
+ IMFS_Set_handlers( &the_link );
+
+ /*
+ * If removing the last hard link to a node, then we need
+ * to remove the node that is a link and the node itself.
+ */
+
+ if ( node->info.hard_link.link_node->st_nlink == 1)
+ {
+ result = (*the_link.handlers->rmnod_h)( &the_link );
+ if ( result != 0 )
+ return -1;
+ }
+ else
+ {
+ node->info.hard_link.link_node->st_nlink --;
+ IMFS_update_ctime( node->info.hard_link.link_node );
+ }
+ }
+
+ /*
+ * Now actually free the node we were asked to free.
+ */
+
+ result = (*loc->handlers->rmnod_h)( loc );
+
+ return result;
+}
diff --git a/cpukit/libfs/src/imfs/imfs_unmount.c b/cpukit/libfs/src/imfs/imfs_unmount.c
new file mode 100644
index 0000000000..ee1482bfa5
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_unmount.c
@@ -0,0 +1,62 @@
+/*
+ * IMFS_unmount
+ *
+ * This routine will look at a mount table entry that we are going to
+ * add to the mount table. If the mount point
+ * rtems_filesystem_location_info_t struct refers to a node that is a
+ * directory that has a file system mounted on it, the node will be
+ * marked as a mount point by * setting its directory.mt_fs pointer
+ * to NULL. This indicates that a directory is no longer mounted on
+ * this node.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+
+#include "imfs.h"
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+int IMFS_unmount(
+ rtems_filesystem_mount_table_entry_t *mt_entry
+)
+{
+ IMFS_jnode_t *node;
+
+ node = mt_entry->mt_point_node.node_access;
+
+ /*
+ * Is the node that we are mounting onto a directory node ?
+ */
+
+ if ( node->type != IMFS_DIRECTORY )
+ rtems_set_errno_and_return_minus_one( ENOTDIR );
+
+ /*
+ * Did the node indicate that there was a directory mounted here?
+ */
+
+ if ( node->info.directory.mt_fs == NULL )
+ rtems_set_errno_and_return_minus_one( EINVAL ); /* XXX */
+
+ /*
+ * Set the mt_fs pointer to indicate that there is no longer
+ * a file system mounted to this point.
+ */
+
+ node->info.directory.mt_fs = NULL;
+
+ return 0;
+}
diff --git a/cpukit/libfs/src/imfs/imfs_utime.c b/cpukit/libfs/src/imfs/imfs_utime.c
new file mode 100644
index 0000000000..0a120f02d3
--- /dev/null
+++ b/cpukit/libfs/src/imfs/imfs_utime.c
@@ -0,0 +1,41 @@
+/*
+ * IMFS_utime
+ *
+ * This routine is the implementation of the utime() system
+ * call for the IMFS.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <sys/time.h>
+
+#include <rtems/libio_.h>
+#include "imfs.h"
+
+int IMFS_utime(
+ rtems_filesystem_location_info_t *pathloc, /* IN */
+ time_t actime, /* IN */
+ time_t modtime /* IN */
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = (IMFS_jnode_t *) pathloc->node_access;
+
+ the_jnode->stat_atime = actime;
+ the_jnode->stat_mtime = modtime;
+
+ return 0;
+}
diff --git a/cpukit/libfs/src/imfs/ioman.c b/cpukit/libfs/src/imfs/ioman.c
new file mode 100644
index 0000000000..08e56292c1
--- /dev/null
+++ b/cpukit/libfs/src/imfs/ioman.c
@@ -0,0 +1,107 @@
+/*
+ * This file emulates the old Classic RTEMS IO manager directives
+ * which register and lookup names using the in-memory filesystem.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <assert.h>
+
+#include <rtems.h>
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+#include "imfs.h"
+
+#if defined(__linux__)
+#define S_IFCHR __S_IFCHR
+#endif
+
+/*
+ * rtems_io_register_name
+ *
+ * This assumes that all registered devices are character devices.
+ */
+
+rtems_status_code rtems_io_register_name(
+ char *device_name,
+ rtems_device_major_number major,
+ rtems_device_minor_number minor
+)
+{
+#if !defined(RTEMS_UNIX)
+ int status;
+ dev_t dev;
+
+ dev = rtems_filesystem_make_dev_t( major, minor );
+ status = mknod( device_name, 0777 | S_IFCHR, dev );
+
+ /* this is the only error returned by the old version */
+ if ( status )
+ return RTEMS_TOO_MANY;
+
+#endif
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_io_lookup_name
+ *
+ * This version is reentrant.
+ *
+ * XXX - This is dependent upon IMFS and should not be.
+ * Suggest adding a filesystem routine to fill in the device_info.
+ */
+
+rtems_status_code rtems_io_lookup_name(
+ const char *name,
+ rtems_driver_name_t *device_info
+)
+{
+#if !defined(RTEMS_UNIX)
+ IMFS_jnode_t *the_jnode;
+ rtems_filesystem_location_info_t loc;
+ int result;
+ rtems_filesystem_node_types_t node_type;
+
+ result = rtems_filesystem_evaluate_path( name, 0x00, &loc, TRUE );
+ the_jnode = loc.node_access;
+
+ if ( !loc.ops->node_type_h ) {
+ rtems_filesystem_freenode( &loc );
+ rtems_set_errno_and_return_minus_one( ENOTSUP );
+ }
+
+ node_type = (*loc.ops->node_type_h)( &loc );
+
+ if ( (result != 0) || node_type != RTEMS_FILESYSTEM_DEVICE ) {
+ rtems_filesystem_freenode( &loc );
+ return RTEMS_UNSATISFIED;
+ }
+
+ device_info->device_name = (char *) name;
+ device_info->device_name_length = strlen( name );
+ device_info->major = the_jnode->info.device.major;
+ device_info->minor = the_jnode->info.device.minor;
+
+ rtems_filesystem_freenode( &loc );
+
+#endif
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/libfs/src/imfs/linearfile.c b/cpukit/libfs/src/imfs/linearfile.c
new file mode 100644
index 0000000000..1fc0db3ae7
--- /dev/null
+++ b/cpukit/libfs/src/imfs/linearfile.c
@@ -0,0 +1,115 @@
+/*
+ * IMFS Linear File Handlers
+ *
+ * This file contains the set of handlers used to process operations on
+ * IMFS linear memory file nodes. Linear memory files are contiguous
+ * blocks of memory created from a TAR or other filesystem image.
+ * The blocks are nonwriteable and nonresizeable.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include "imfs.h"
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+/*
+ * linearfile_read
+ *
+ * This routine processes the read() system call.
+ */
+
+int linearfile_read(
+ rtems_libio_t *iop,
+ void *buffer,
+ uint32_t count
+)
+{
+ IMFS_jnode_t *the_jnode;
+ unsigned char *dest;
+ unsigned char *file_ptr;
+ int file_offset;
+
+
+ the_jnode = iop->file_info;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ rtems_set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_LINEAR_FILE );
+ if ( the_jnode->type != IMFS_LINEAR_FILE )
+ rtems_set_errno_and_return_minus_one( EIO );
+
+ /*
+ * Error checks on arguments
+ */
+
+ dest = (unsigned char *)buffer;
+ assert( dest );
+ if ( !dest )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ /*
+ * Perform a simple memory copy.
+ */
+
+ if (count == 0)
+ return(0);
+
+ the_jnode = iop->file_info;
+ file_ptr = (unsigned char *)the_jnode->info.linearfile.direct;
+ file_offset = (unsigned long)iop->offset;
+
+ if (count > (the_jnode->info.linearfile.size - file_offset))
+ count = the_jnode->info.linearfile.size - file_offset;
+
+ memcpy(dest, &file_ptr[file_offset], count);
+
+ return(count);
+}
+
+
+/*
+ * linearfile_lseek
+ *
+ * This routine processes the lseek() system call.
+ */
+
+int linearfile_lseek(
+ rtems_libio_t *iop,
+ off_t offset,
+ int whence
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ if (iop->offset > the_jnode->info.linearfile.size)
+ iop->offset = the_jnode->info.linearfile.size;
+
+ return iop->offset;
+}
diff --git a/cpukit/libfs/src/imfs/memfile.c b/cpukit/libfs/src/imfs/memfile.c
new file mode 100644
index 0000000000..1a68531c38
--- /dev/null
+++ b/cpukit/libfs/src/imfs/memfile.c
@@ -0,0 +1,1143 @@
+/*
+ * IMFS Device Node Handlers
+ *
+ * This file contains the set of handlers used to process operations on
+ * IMFS memory file nodes. The memory files are created in memory using
+ * malloc'ed memory. Thus any data stored in one of these files is lost
+ * at system shutdown unless special arrangements to copy the data to
+ * some type of non-volailte storage are made by the application.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include "imfs.h"
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+
+#define MEMFILE_STATIC
+
+/*
+ * Prototypes of private routines
+ */
+
+MEMFILE_STATIC int IMFS_memfile_extend(
+ IMFS_jnode_t *the_jnode,
+ off_t new_length
+);
+
+MEMFILE_STATIC int IMFS_memfile_addblock(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block
+);
+
+MEMFILE_STATIC int IMFS_memfile_remove_block(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block
+);
+
+MEMFILE_STATIC block_p *IMFS_memfile_get_block_pointer(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block,
+ int malloc_it
+);
+
+MEMFILE_STATIC ssize_t IMFS_memfile_read(
+ IMFS_jnode_t *the_jnode,
+ off_t start,
+ unsigned char *destination,
+ unsigned int length
+);
+
+ssize_t IMFS_memfile_write( /* cannot be static as used in imfs_fchmod.c */
+ IMFS_jnode_t *the_jnode,
+ off_t start,
+ const unsigned char *source,
+ unsigned int length
+);
+
+int memfile_check_rmnod( IMFS_jnode_t *the_jnode );
+
+void *memfile_alloc_block(void);
+
+void memfile_free_block(
+ void *memory
+);
+
+/*
+ * memfile_open
+ *
+ * This routine processes the open() system call. Note that there is
+ * nothing special to be done at open() time.
+ */
+
+int memfile_open(
+ rtems_libio_t *iop,
+ const char *pathname,
+ uint32_t flag,
+ uint32_t mode
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ if (iop->flags & LIBIO_FLAGS_APPEND)
+ iop->offset = the_jnode->info.file.size;
+
+ iop->size = the_jnode->info.file.size;
+ return 0;
+}
+
+/*
+ * memfile_close
+ *
+ * This routine processes the close() system call. Note that there is
+ * nothing to flush or memory to free at this point.
+ */
+
+int memfile_close(
+ rtems_libio_t *iop
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ if (iop->flags & LIBIO_FLAGS_APPEND)
+ iop->offset = the_jnode->info.file.size;
+
+ memfile_check_rmnod( the_jnode );
+ return 0;
+}
+
+/*
+ * memfile_read
+ *
+ * This routine processes the read() system call.
+ */
+
+ssize_t memfile_read(
+ rtems_libio_t *iop,
+ void *buffer,
+ uint32_t count
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return IMFS_memfile_read( the_jnode, iop->offset, buffer, count );
+}
+
+/*
+ * memfile_write
+ *
+ * This routine processes the write() system call.
+ */
+
+ssize_t memfile_write(
+ rtems_libio_t *iop,
+ const void *buffer,
+ uint32_t count
+)
+{
+ IMFS_jnode_t *the_jnode;
+ ssize_t status;
+
+ the_jnode = iop->file_info;
+
+ status = IMFS_memfile_write( the_jnode, iop->offset, buffer, count );
+ iop->size = the_jnode->info.file.size;
+
+ return status;
+}
+
+/*
+ * memfile_ioctl
+ *
+ * This routine processes the ioctl() system call.
+ *
+ * NOTE: No ioctl()'s are supported for in-memory files.
+ */
+
+int memfile_ioctl(
+ rtems_libio_t *iop,
+ uint32_t command,
+ void *buffer
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ return 0;
+}
+
+/*
+ * memfile_lseek
+ *
+ * This routine processes the lseek() system call.
+ */
+
+int memfile_lseek(
+ rtems_libio_t *iop,
+ off_t offset,
+ int whence
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ if (the_jnode->type == IMFS_LINEAR_FILE) {
+ if (iop->offset > the_jnode->info.linearfile.size)
+ iop->offset = the_jnode->info.linearfile.size;
+ }
+ else { /* Must be a block file (IMFS_MEMORY_FILE). */
+ if (IMFS_memfile_extend( the_jnode, iop->offset ))
+ rtems_set_errno_and_return_minus_one( ENOSPC );
+
+ iop->size = the_jnode->info.file.size;
+ }
+ return iop->offset;
+}
+
+/*
+ * memfile_stat
+ *
+ * This IMFS_stat() can be used.
+ */
+
+/*
+ * memfile_ftruncate
+ *
+ * This routine processes the ftruncate() system call.
+ */
+
+int memfile_ftruncate(
+ rtems_libio_t *iop,
+ off_t length
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = iop->file_info;
+
+ /*
+ * POSIX 1003.1b does not specify what happens if you truncate a file
+ * and the new length is greater than the current size. We treat this
+ * as an extend operation.
+ */
+
+ if ( length > the_jnode->info.file.size )
+ return IMFS_memfile_extend( the_jnode, length );
+
+ /*
+ * The in-memory files do not currently reclaim memory until the file is
+ * deleted. So we leave the previously allocated blocks in place for
+ * future use and just set the length.
+ */
+
+ the_jnode->info.file.size = length;
+ iop->size = the_jnode->info.file.size;
+
+ IMFS_update_atime( the_jnode );
+
+ return 0;
+}
+
+/*
+ * IMFS_memfile_extend
+ *
+ * This routine insures that the in-memory file is of the length
+ * specified. If necessary, it will allocate memory blocks to
+ * extend the file.
+ */
+
+MEMFILE_STATIC int IMFS_memfile_extend(
+ IMFS_jnode_t *the_jnode,
+ off_t new_length
+)
+{
+ unsigned int block;
+ unsigned int new_blocks;
+ unsigned int old_blocks;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ rtems_set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ rtems_set_errno_and_return_minus_one( EIO );
+
+ if ( new_length >= IMFS_MEMFILE_MAXIMUM_SIZE )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ if ( new_length <= the_jnode->info.file.size )
+ return 0;
+
+ /*
+ * Calculate the number of range of blocks to allocate
+ */
+
+ new_blocks = new_length / IMFS_MEMFILE_BYTES_PER_BLOCK;
+ old_blocks = the_jnode->info.file.size / IMFS_MEMFILE_BYTES_PER_BLOCK;
+
+ /*
+ * Now allocate each of those blocks.
+ */
+
+ for ( block=old_blocks ; block<=new_blocks ; block++ ) {
+ if ( IMFS_memfile_addblock( the_jnode, block ) ) {
+ for ( ; block>=old_blocks ; block-- ) {
+ IMFS_memfile_remove_block( the_jnode, block );
+ }
+ rtems_set_errno_and_return_minus_one( ENOSPC );
+ }
+ }
+
+ /*
+ * Set the new length of the file.
+ */
+
+ the_jnode->info.file.size = new_length;
+ return 0;
+}
+
+/*
+ * IMFS_memfile_addblock
+ *
+ * This routine adds a single block to the specified in-memory file.
+ */
+
+MEMFILE_STATIC int IMFS_memfile_addblock(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block
+)
+{
+ block_p memory;
+ block_p *block_entry_ptr;
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ rtems_set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ rtems_set_errno_and_return_minus_one( EIO );
+
+ block_entry_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 1 );
+ if ( *block_entry_ptr )
+ return 0;
+
+#if 0
+ fprintf(stdout, "%d %p", block, block_entry_ptr );
+ fflush(stdout);
+#endif
+
+ memory = memfile_alloc_block();
+ if ( !memory )
+ return 1;
+ *block_entry_ptr = memory;
+
+ return 0;
+}
+
+/*
+ * IMFS_memfile_remove_block
+ *
+ * This routine removes the specified block from the in-memory file.
+ *
+ * NOTE: This is a support routine and is called only to remove
+ * the last block or set of blocks in a file. Removing a
+ * block from the middle of a file would be exceptionally
+ * dangerous and the results unpredictable.
+ */
+
+MEMFILE_STATIC int IMFS_memfile_remove_block(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block
+)
+{
+ block_p *block_entry_ptr;
+ block_p ptr;
+
+ block_entry_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ ptr = *block_entry_ptr;
+ *block_entry_ptr = 0;
+
+ memfile_free_block( ptr );
+
+ return 1;
+}
+
+/*
+ * memfile_free_blocks_in_table
+ *
+ * This is a support routine for IMFS_memfile_remove. It frees all the
+ * blocks in one of the indirection tables.
+ */
+
+void memfile_free_blocks_in_table(
+ block_p **block_table,
+ int entries
+)
+{
+ int i;
+ block_p *b;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( block_table );
+ if ( !block_table )
+ return;
+
+ /*
+ * Now go through all the slots in the table and free the memory.
+ */
+
+ b = *block_table;
+
+ for ( i=0 ; i<entries ; i++ ) {
+ if ( b[i] ) {
+ memfile_free_block( b[i] );
+ b[i] = 0;
+ }
+ }
+
+ /*
+ * Now that all the blocks in the block table are free, we can
+ * free the block table itself.
+ */
+
+ memfile_free_block( *block_table );
+ *block_table = 0;
+}
+
+/*
+ * IMFS_memfile_remove
+ *
+ * This routine frees all memory associated with an in memory file.
+ *
+ * NOTE: This is an exceptionally conservative implementation.
+ * It will check EVERY pointer which is non-NULL and insure
+ * any child non-NULL pointers are freed. Optimistically, all that
+ * is necessary is to scan until a NULL pointer is found. There
+ * should be no allocated data past that point.
+ *
+ * In experimentation on the powerpc simulator, it was noted
+ * that using blocks which held 128 slots versus 16 slots made
+ * a significant difference in the performance of this routine.
+ *
+ * Regardless until the IMFS implementation is proven, it
+ * is better to stick to simple, easy to understand algorithms.
+ */
+
+int IMFS_memfile_remove(
+ IMFS_jnode_t *the_jnode
+)
+{
+ IMFS_memfile_t *info;
+ int i;
+ int j;
+ unsigned int to_free;
+ block_p *p;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ rtems_set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ rtems_set_errno_and_return_minus_one( EIO );
+
+ /*
+ * Eventually this could be set smarter at each call to
+ * memfile_free_blocks_in_table to greatly speed this up.
+ */
+
+ to_free = IMFS_MEMFILE_BLOCK_SLOTS;
+
+ /*
+ * Now start freeing blocks in this order:
+ * + indirect
+ * + doubly indirect
+ * + triply indirect
+ */
+
+ info = &the_jnode->info.file;
+
+ if ( info->indirect ) {
+ memfile_free_blocks_in_table( &info->indirect, to_free );
+ }
+
+ if ( info->doubly_indirect ) {
+
+ for ( i=0 ; i<IMFS_MEMFILE_BLOCK_SLOTS ; i++ ) {
+ if ( info->doubly_indirect[i] ) {
+ memfile_free_blocks_in_table(
+ (block_p **)&info->doubly_indirect[i], to_free );
+ }
+ }
+ memfile_free_blocks_in_table( &info->doubly_indirect, to_free );
+
+ }
+
+ if ( info->triply_indirect ) {
+ for ( i=0 ; i<IMFS_MEMFILE_BLOCK_SLOTS ; i++ ) {
+ p = (block_p *) info->triply_indirect[i];
+ if ( !p ) /* ensure we have a valid pointer */
+ break;
+ for ( j=0 ; j<IMFS_MEMFILE_BLOCK_SLOTS ; j++ ) {
+ if ( p[j] ) {
+ memfile_free_blocks_in_table( (block_p **)&p[j], to_free);
+ }
+ }
+ memfile_free_blocks_in_table(
+ (block_p **)&info->triply_indirect[i], to_free );
+ }
+ memfile_free_blocks_in_table(
+ (block_p **)&info->triply_indirect, to_free );
+ }
+
+ return 0;
+}
+
+/*
+ * IMFS_memfile_read
+ *
+ * This routine read from memory file pointed to by the_jnode into
+ * the specified data buffer specified by destination. The file
+ * is NOT extended. An offset greater than the length of the file
+ * is considered an error. Read from an offset for more bytes than
+ * are between the offset and the end of the file will result in
+ * reading the data between offset and the end of the file (truncated
+ * read).
+ */
+
+MEMFILE_STATIC ssize_t IMFS_memfile_read(
+ IMFS_jnode_t *the_jnode,
+ off_t start,
+ unsigned char *destination,
+ unsigned int length
+)
+{
+ block_p *block_ptr;
+ unsigned int block;
+ unsigned int my_length;
+ unsigned int to_copy = 0;
+ unsigned int last_byte;
+ unsigned int copied;
+ unsigned int start_offset;
+ unsigned char *dest;
+
+ dest = destination;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ rtems_set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE ||
+ the_jnode->type == IMFS_LINEAR_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE &&
+ the_jnode->type != IMFS_LINEAR_FILE )
+ rtems_set_errno_and_return_minus_one( EIO );
+
+ /*
+ * Error checks on arguments
+ */
+
+ assert( dest );
+ if ( !dest )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ /*
+ * If there is nothing to read, then quick exit.
+ */
+
+ my_length = length;
+ if ( !my_length )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ /*
+ * Linear files (as created from a tar file are easier to handle
+ * than block files).
+ */
+ if (the_jnode->type == IMFS_LINEAR_FILE) {
+ unsigned char *file_ptr;
+
+ file_ptr = (unsigned char *)the_jnode->info.linearfile.direct;
+
+ if (my_length > (the_jnode->info.linearfile.size - start))
+ my_length = the_jnode->info.linearfile.size - start;
+
+ memcpy(dest, &file_ptr[start], my_length);
+
+ IMFS_update_atime( the_jnode );
+
+ return my_length;
+ }
+
+ /*
+ * If the last byte we are supposed to read is past the end of this
+ * in memory file, then shorten the length to read.
+ */
+
+ last_byte = start + length;
+ if ( last_byte > the_jnode->info.file.size )
+ my_length = the_jnode->info.file.size - start;
+
+ copied = 0;
+
+ /*
+ * Three phases to the read:
+ * + possibly the last part of one block
+ * + all of zero of more blocks
+ * + possibly the first part of one block
+ */
+
+ /*
+ * Phase 1: possibly the last part of one block
+ */
+
+ start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK;
+ block = start / IMFS_MEMFILE_BYTES_PER_BLOCK;
+ if ( start_offset ) {
+ to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset;
+ if ( to_copy > my_length )
+ to_copy = my_length;
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( dest, &(*block_ptr)[ start_offset ], to_copy );
+ dest += to_copy;
+ block++;
+ my_length -= to_copy;
+ copied += to_copy;
+ }
+
+ /*
+ * Phase 2: all of zero of more blocks
+ */
+
+ to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK;
+ while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) {
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( dest, &(*block_ptr)[ 0 ], to_copy );
+ dest += to_copy;
+ block++;
+ my_length -= to_copy;
+ copied += to_copy;
+ }
+
+ /*
+ * Phase 3: possibly the first part of one block
+ */
+
+ assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK );
+
+ if ( my_length ) {
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+ memcpy( dest, &(*block_ptr)[ 0 ], my_length );
+ copied += my_length;
+ }
+
+ IMFS_update_atime( the_jnode );
+
+ return copied;
+}
+
+/*
+ * IMFS_memfile_write
+ *
+ * This routine writes the specified data buffer into the in memory
+ * file pointed to by the_jnode. The file is extended as needed.
+ */
+
+MEMFILE_STATIC ssize_t IMFS_memfile_write(
+ IMFS_jnode_t *the_jnode,
+ off_t start,
+ const unsigned char *source,
+ unsigned int length
+)
+{
+ block_p *block_ptr;
+ unsigned int block;
+ int status;
+ unsigned int my_length;
+ unsigned int to_copy = 0;
+ unsigned int last_byte;
+ unsigned int start_offset;
+ int copied;
+ const unsigned char *src;
+
+ src = source;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ rtems_set_errno_and_return_minus_one( EIO );
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ rtems_set_errno_and_return_minus_one( EIO );
+
+ /*
+ * Error check arguments
+ */
+
+ assert( source );
+ if ( !source )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+
+ /*
+ * If there is nothing to write, then quick exit.
+ */
+
+ my_length = length;
+ if ( !my_length )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ /*
+ * If the last byte we are supposed to write is past the end of this
+ * in memory file, then extend the length.
+ */
+
+ last_byte = start + length;
+ if ( last_byte > the_jnode->info.file.size ) {
+ status = IMFS_memfile_extend( the_jnode, last_byte );
+ if ( status )
+ rtems_set_errno_and_return_minus_one( ENOSPC );
+ }
+
+ copied = 0;
+
+ /*
+ * Three phases to the write:
+ * + possibly the last part of one block
+ * + all of zero of more blocks
+ * + possibly the first part of one block
+ */
+
+ /*
+ * Phase 1: possibly the last part of one block
+ */
+
+ start_offset = start % IMFS_MEMFILE_BYTES_PER_BLOCK;
+ block = start / IMFS_MEMFILE_BYTES_PER_BLOCK;
+ if ( start_offset ) {
+ to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK - start_offset;
+ if ( to_copy > my_length )
+ to_copy = my_length;
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+#if 0
+fprintf(stdout, "write %d at %d in %d: %*s\n", to_copy, start_offset, block, to_copy, src );
+#endif
+ memcpy( &(*block_ptr)[ start_offset ], src, to_copy );
+ src += to_copy;
+ block++;
+ my_length -= to_copy;
+ copied += to_copy;
+ }
+
+ /*
+ * Phase 2: all of zero of more blocks
+ */
+
+ to_copy = IMFS_MEMFILE_BYTES_PER_BLOCK;
+ while ( my_length >= IMFS_MEMFILE_BYTES_PER_BLOCK ) {
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+#if 0
+fprintf(stdout, "write %d in %d: %*s\n", to_copy, block, to_copy, src );
+#endif
+ memcpy( &(*block_ptr)[ 0 ], src, to_copy );
+ src += to_copy;
+ block++;
+ my_length -= to_copy;
+ copied += to_copy;
+ }
+
+ /*
+ * Phase 3: possibly the first part of one block
+ */
+
+ assert( my_length < IMFS_MEMFILE_BYTES_PER_BLOCK );
+
+ to_copy = my_length;
+ if ( my_length ) {
+ block_ptr = IMFS_memfile_get_block_pointer( the_jnode, block, 0 );
+ assert( block_ptr );
+ if ( !block_ptr )
+ return copied;
+#if 0
+fprintf(stdout, "write %d in %d: %*s\n", to_copy, block, to_copy, src );
+#endif
+ memcpy( &(*block_ptr)[ 0 ], src, my_length );
+ my_length = 0;
+ copied += to_copy;
+ }
+
+ IMFS_atime_mtime_update( the_jnode );
+
+ return copied;
+}
+
+/*
+ * IMFS_memfile_get_block_pointer
+ *
+ * This routine looks up the block pointer associated with the given block
+ * number. If that block has not been allocated and "malloc_it" is
+ * TRUE, then the block is allocated. Otherwise, it is an error.
+ */
+
+#if 0
+block_p *IMFS_memfile_get_block_pointer_DEBUG(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block,
+ int malloc_it
+);
+
+block_p *IMFS_memfile_get_block_pointer(
+ IMFS_jnode_t *the_jnode,
+ unsigned int block,
+ int malloc_it
+)
+{
+ block_p *p;
+
+ p = IMFS_memfile_get_block_pointer_DEBUG( the_jnode, block, malloc_it );
+ fprintf(stdout, "(%d -> %p) ", block, p );
+ return p;
+}
+
+block_p *IMFS_memfile_get_block_pointer_DEBUG(
+#else
+block_p *IMFS_memfile_get_block_pointer(
+#endif
+ IMFS_jnode_t *the_jnode,
+ unsigned int block,
+ int malloc_it
+)
+{
+ unsigned int my_block;
+ IMFS_memfile_t *info;
+ unsigned int singly;
+ unsigned int doubly;
+ unsigned int triply;
+ block_p *p;
+ block_p *p1;
+ block_p *p2;
+
+ /*
+ * Perform internal consistency checks
+ */
+
+ assert( the_jnode );
+ if ( !the_jnode )
+ return NULL;
+
+ assert( the_jnode->type == IMFS_MEMORY_FILE );
+ if ( the_jnode->type != IMFS_MEMORY_FILE )
+ return NULL;
+
+ info = &the_jnode->info.file;
+
+ my_block = block;
+
+ /*
+ * Is the block number in the simple indirect portion?
+ */
+
+ if ( my_block <= LAST_INDIRECT ) {
+#if 0
+fprintf(stdout, "(s %d) ", block );
+fflush(stdout);
+#endif
+ p = info->indirect;
+
+ if ( malloc_it ) {
+
+ if ( !p ) {
+ p = memfile_alloc_block();
+ if ( !p )
+ return 0;
+ info->indirect = p;
+ }
+ return &info->indirect[ my_block ];
+ }
+
+ if ( !p )
+ return 0;
+
+ return &info->indirect[ my_block ];
+ }
+
+ /*
+ * Is the block number in the doubly indirect portion?
+ */
+
+ if ( my_block <= LAST_DOUBLY_INDIRECT ) {
+#if 0
+fprintf(stdout, "(d %d) ", block );
+fflush(stdout);
+#endif
+
+ my_block -= FIRST_DOUBLY_INDIRECT;
+
+ singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS;
+ doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS;
+
+ p = info->doubly_indirect;
+ if ( malloc_it ) {
+
+ if ( !p ) {
+ p = memfile_alloc_block();
+ if ( !p )
+ return 0;
+ info->doubly_indirect = p;
+ }
+
+ p1 = (block_p *)p[ doubly ];
+ if ( !p1 ) {
+ p1 = memfile_alloc_block();
+ if ( !p1 )
+ return 0;
+ p[ doubly ] = (block_p) p1;
+ }
+
+ return (block_p *)&p1[ singly ];
+ }
+
+ if ( !p )
+ return 0;
+
+ p = (block_p *)p[ doubly ];
+ if ( !p )
+ return 0;
+
+#if 0
+fprintf(stdout, "(d %d %d %d %d %p %p) ", block, my_block, doubly,
+ singly, p, &p[singly] );
+fflush(stdout);
+#endif
+ return (block_p *)&p[ singly ];
+ }
+
+#if 0
+fprintf(stdout, "(t %d) ", block );
+fflush(stdout);
+#endif
+ /*
+ * Is the block number in the triply indirect portion?
+ */
+
+ if ( my_block <= LAST_TRIPLY_INDIRECT ) {
+ my_block -= FIRST_TRIPLY_INDIRECT;
+
+ singly = my_block % IMFS_MEMFILE_BLOCK_SLOTS;
+ doubly = my_block / IMFS_MEMFILE_BLOCK_SLOTS;
+ triply = doubly / IMFS_MEMFILE_BLOCK_SLOTS;
+ doubly %= IMFS_MEMFILE_BLOCK_SLOTS;
+
+ p = info->triply_indirect;
+
+ if ( malloc_it ) {
+ if ( !p ) {
+ p = memfile_alloc_block();
+ if ( !p )
+ return 0;
+ info->triply_indirect = p;
+ }
+
+ p1 = (block_p *) p[ triply ];
+ if ( !p1 ) {
+ p1 = memfile_alloc_block();
+ if ( !p1 )
+ return 0;
+ p[ triply ] = (block_p) p1;
+ }
+
+ p2 = (block_p *)p1[ doubly ];
+ if ( !p2 ) {
+ p2 = memfile_alloc_block();
+ if ( !p2 )
+ return 0;
+ p1[ doubly ] = (block_p) p2;
+ }
+ return (block_p *)&p2[ singly ];
+ }
+
+ if ( !p )
+ return 0;
+
+#if 0
+fprintf(stdout, "(t %d %d %d %d %d) ", block, my_block, triply, doubly, singly );
+fflush(stdout);
+#endif
+ p1 = (block_p *) p[ triply ];
+ if ( !p1 )
+ return 0;
+
+ p2 = (block_p *)p1[ doubly ];
+ if ( !p )
+ return 0;
+
+ return (block_p *)&p2[ singly ];
+ }
+
+ /*
+ * This means the requested block number is out of range.
+ */
+
+ return 0;
+}
+
+/*
+ * memfile_alloc_block
+ *
+ * Allocate a block for an in-memory file.
+ */
+
+int memfile_blocks_allocated = 0;
+
+void *memfile_alloc_block(void)
+{
+ void *memory;
+
+ memory = (void *)calloc(1, IMFS_MEMFILE_BYTES_PER_BLOCK);
+ if ( memory )
+ memfile_blocks_allocated++;
+
+ return memory;
+}
+
+/*
+ * memfile_free_block
+ *
+ * Free a block from an in-memory file.
+ */
+
+void memfile_free_block(
+ void *memory
+)
+{
+#if 0
+fprintf(stdout, "(d %p) ", memory );
+fflush(stdout);
+#endif
+ free(memory);
+ memfile_blocks_allocated--;
+}
+
+
+/*
+ * memfile_rmnod
+ *
+ * This routine is available from the optable to remove a node
+ * from the IMFS file system.
+ */
+
+int memfile_rmnod(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+)
+{
+ IMFS_jnode_t *the_jnode;
+
+ the_jnode = (IMFS_jnode_t *) pathloc->node_access;
+
+ /*
+ * Take the node out of the parent's chain that contains this node
+ */
+
+ if ( the_jnode->Parent != NULL ) {
+ Chain_Extract( (Chain_Node *) the_jnode );
+ the_jnode->Parent = NULL;
+ }
+
+ /*
+ * Decrement the link counter and see if we can free the space.
+ */
+
+ the_jnode->st_nlink--;
+ IMFS_update_ctime( the_jnode );
+
+ return memfile_check_rmnod( the_jnode );
+}
+
+
+int memfile_check_rmnod( IMFS_jnode_t *the_jnode ){
+
+ /*
+ * The file cannot be open and the link must be less than 1 to free.
+ */
+
+ if ( !rtems_libio_is_file_open( the_jnode ) && (the_jnode->st_nlink < 1) ) {
+
+ /*
+ * Is the rtems_filesystem_current is this node?
+ */
+
+ if ( rtems_filesystem_current.node_access == the_jnode )
+ rtems_filesystem_current.node_access = NULL;
+
+ /*
+ * Free memory associated with a memory file.
+ */
+ if (the_jnode->type != IMFS_LINEAR_FILE)
+ IMFS_memfile_remove( the_jnode );
+
+ free( the_jnode );
+ }
+
+ return 0;
+}
diff --git a/cpukit/libfs/src/imfs/miniimfs_init.c b/cpukit/libfs/src/imfs/miniimfs_init.c
new file mode 100644
index 0000000000..cf4492541b
--- /dev/null
+++ b/cpukit/libfs/src/imfs/miniimfs_init.c
@@ -0,0 +1,70 @@
+/*
+ * Mini-IMFS Initialization
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h> /* for mkdir */
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <assert.h>
+
+#include "imfs.h"
+#include <rtems/libio_.h>
+
+#if defined(IMFS_DEBUG)
+#include <stdio.h>
+#endif
+
+/*
+ * miniIMFS file system operations table
+ */
+
+rtems_filesystem_operations_table miniIMFS_ops = {
+ IMFS_eval_path,
+ IMFS_evaluate_for_make,
+ NULL, /* XXX IMFS_link, */
+ NULL, /* XXX IMFS_unlink, */
+ IMFS_node_type,
+ IMFS_mknod,
+ NULL, /* XXX IMFS_chown, */
+ NULL, /* XXX IMFS_freenodinfo, */
+ NULL, /* XXX IMFS_mount, */
+ miniIMFS_initialize,
+ NULL, /* XXX IMFS_unmount, */
+ NULL, /* XXX IMFS_fsunmount, */
+ NULL, /* XXX IMFS_utime, */
+ NULL, /* XXX IMFS_evaluate_link, */
+ NULL, /* XXX IMFS_symlink, */
+ NULL /* XXX IMFS_readlink */
+};
+
+/*
+ * miniIMFS_initialize
+ */
+
+int miniIMFS_initialize(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ return IMFS_initialize_support(
+ temp_mt_entry,
+ &miniIMFS_ops,
+ &rtems_filesystem_null_handlers, /* for linearfiles */
+ &rtems_filesystem_null_handlers, /* for memfiles */
+ &rtems_filesystem_null_handlers /* for directories */
+ );
+}
diff --git a/cpukit/libmisc/.cvsignore b/cpukit/libmisc/.cvsignore
new file mode 100644
index 0000000000..282522db03
--- /dev/null
+++ b/cpukit/libmisc/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/cpukit/libmisc/Makefile.am b/cpukit/libmisc/Makefile.am
new file mode 100644
index 0000000000..1d1cd18209
--- /dev/null
+++ b/cpukit/libmisc/Makefile.am
@@ -0,0 +1,331 @@
+##
+## $Id$
+##
+
+include $(top_srcdir)/automake/compile.am
+
+EXTRA_DIST = README
+
+AM_CPPFLAGS += -I$(top_builddir)
+
+include_rtemsdir = $(includedir)/rtems
+include_rtems_HEADERS =
+EXTRA_LIBRARIES =
+TMP_LIBS =
+CLEANFILES =
+
+## capture
+EXTRA_DIST += capture/README
+include_rtems_HEADERS += capture/capture.h capture/capture-cli.h
+
+EXTRA_LIBRARIES += libcapture.a
+CLEANFILES += libcapture.a
+libcapture_a_SOURCES = capture/capture.c capture/capture-cli.c
+libcapture_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libcapture_g.a
+CLEANFILES += libcapture_g.a
+libcapture_g_a_SOURCES = $(libcapture_a_SOURCES)
+libcapture_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+TMP_LIBS += libcapture$(LIB_VARIANT).a
+
+## cpuuse
+EXTRA_DIST += cpuuse/README
+include_rtems_HEADERS += cpuuse/cpuuse.h
+
+EXTRA_LIBRARIES += libcpuuse.a
+CLEANFILES += libcpuuse.a
+libcpuuse_a_SOURCES = cpuuse/cpuuse.c
+libcpuuse_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libcpuuse_g.a
+CLEANFILES += libcpuuse_g.a
+libcpuuse_g_a_SOURCES = $(libcpuuse_a_SOURCES)
+libcpuuse_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+TMP_LIBS += libcpuuse$(LIB_VARIANT).a
+
+## devnull
+include_rtems_HEADERS += devnull/devnull.h
+
+EXTRA_LIBRARIES += libdevnull.a
+CLEANFILES += libdevnull.a
+libdevnull_a_SOURCES = devnull/devnull.c
+libdevnull_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libdevnull_g.a
+CLEANFILES += libdevnull_g.a
+libdevnull_g_a_SOURCES = $(libdevnull_a_SOURCES)
+libdevnull_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+TMP_LIBS += libdevnull$(LIB_VARIANT).a
+
+## dummy
+EXTRA_DIST += dummy/README
+
+EXTRA_LIBRARIES += libdummy.a
+CLEANFILES += libdummy.a
+libdummy_a_SOURCES = dummy/dummy.c
+libdummy_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libdummy_g.a
+CLEANFILES += libdummy_g.a
+libdummy_g_a_SOURCES = $(libdummy_a_SOURCES)
+libdummy_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+TMP_LIBS += libdummy$(LIB_VARIANT).a
+
+## dumpbuf
+include_rtems_HEADERS += dumpbuf/dumpbuf.h
+
+EXTRA_LIBRARIES += libdumpbuf.a
+CLEANFILES += libdumpbuf.a
+libdumpbuf_a_SOURCES = dumpbuf/dumpbuf.c
+libdumpbuf_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libdumpbuf_g.a
+CLEANFILES += libdumpbuf_g.a
+libdumpbuf_g_a_SOURCES = $(libdumpbuf_a_SOURCES)
+libdumpbuf_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+TMP_LIBS += libdumpbuf$(LIB_VARIANT).a
+
+## monitor
+
+include_rtems_HEADERS += monitor/monitor.h
+libmonitor_a_SOURCES = monitor/mon-command.c monitor/mon-symbols.c \
+ monitor/mon-prmisc.c monitor/mon-monitor.c monitor/mon-object.c \
+ monitor/mon-server.c monitor/mon-task.c monitor/mon-queue.c \
+ monitor/mon-driver.c monitor/mon-dname.c monitor/mon-itask.c \
+ monitor/mon-extension.c monitor/mon-manager.c monitor/mon-config.c \
+ monitor/symbols.h
+if HAS_MP
+libmonitor_a_SOURCES += monitor/mon-mpci.c
+endif
+
+EXTRA_LIBRARIES += libmonitor.a
+CLEANFILES += libmonitor.a
+libmonitor_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libmonitor_g.a
+CLEANFILES += libmonitor_g.a
+libmonitor_g_a_SOURCES = $(libmonitor_a_SOURCES)
+libmonitor_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+EXTRA_DIST += monitor/README
+
+TMP_LIBS += libmonitor$(LIB_VARIANT).a
+
+## mw-fb
+include_rtems_HEADERS += mw-fb/mw_fb.h mw-fb/mw_uid.h
+
+EXTRA_LIBRARIES += libmw-fb.a
+CLEANFILES += libmw-fb.a
+libmw_fb_a_SOURCES = mw-fb/mw_fb.c mw-fb/mw_uid.c
+libmw_fb_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libmw-fb_g.a
+CLEANFILES += libmw-fb_g.a
+libmw_fb_g_a_SOURCES = $(libmw_fb_a_SOURCES)
+libmw_fb_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+TMP_LIBS += libmw-fb$(LIB_VARIANT).a
+
+## shell
+
+if LIBSHELL
+include_rtems_HEADERS += shell/shell.h
+
+EXTRA_LIBRARIES += libshell.a
+CLEANFILES += libshell.a
+libshell_a_SOURCES = shell/cmds.c shell/shell.c
+libshell_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libshell_g.a
+CLEANFILES += libshell_g.a
+libshell_g_a_SOURCES = $(libshell_a_SOURCES)
+libshell_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+TMP_LIBS += libshell$(LIB_VARIANT).a
+endif
+
+EXTRA_DIST += shell/README
+
+## rtmonuse
+include_rtems_HEADERS += rtmonuse/rtmonuse.h
+
+EXTRA_LIBRARIES += librtmonuse.a
+CLEANFILES += librtmonuse.a
+librtmonuse_a_SOURCES = rtmonuse/rtmonuse.c
+librtmonuse_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += librtmonuse_g.a
+CLEANFILES += librtmonuse_g.a
+librtmonuse_g_a_SOURCES = $(librtmonuse_a_SOURCES)
+librtmonuse_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+TMP_LIBS += librtmonuse$(LIB_VARIANT).a
+
+## serdbg
+
+if LIBSERDBG
+include_rtems_HEADERS += serdbg/serdbgcnf.h serdbg/serdbg.h \
+ serdbg/termios_printk_cnf.h serdbg/termios_printk.h
+
+EXTRA_LIBRARIES += libserdbg.a
+CLEANFILES += libserdbg.a
+libserdbg_a_SOURCES = serdbg/serdbg.c serdbg/serdbgio.c \
+ serdbg/termios_printk.c
+libserdbg_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libserdbg_g.a
+CLEANFILES += libserdbg_g.a
+libserdbg_g_a_SOURCES = $(libserdbg_a_SOURCES)
+libserdbg_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+TMP_LIBS += libserdbg$(LIB_VARIANT).a
+endif
+
+EXTRA_DIST += serdbg/README
+
+## stackchk
+
+include_rtems_HEADERS += stackchk/stackchk.h
+
+EXTRA_LIBRARIES += libstackchk.a
+CLEANFILES += libstackchk.a
+libstackchk_a_SOURCES = stackchk/check.c stackchk/internal.h
+libstackchk_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libstackchk_g.a
+CLEANFILES += libstackchk_g.a
+libstackchk_g_a_SOURCES = $(libstackchk_a_SOURCES)
+libstackchk_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+TMP_LIBS += libstackchk$(LIB_VARIANT).a
+EXTRA_DIST += stackchk/README
+
+## libuntar
+
+include_rtems_HEADERS += untar/untar.h
+
+EXTRA_LIBRARIES += libuntar.a
+CLEANFILES += libuntar.a
+libuntar_a_SOURCES = untar/untar.c
+libuntar_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libuntar_g.a
+CLEANFILES += libuntar_g.a
+libuntar_g_a_SOURCES = $(libuntar_a_SOURCES)
+libuntar_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+TMP_LIBS += libuntar$(LIB_VARIANT).a
+
+EXTRA_DIST += untar/README
+
+## fsmount
+include_rtems_HEADERS += fsmount/fsmount.h
+
+EXTRA_LIBRARIES += libfsmount.a
+CLEANFILES += libfsmount.a
+libfsmount_a_SOURCES = fsmount/fsmount.c
+libfsmount_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libfsmount_g.a
+CLEANFILES += libfsmount_g.a
+libfsmount_g_a_SOURCES = $(libfsmount_a_SOURCES)
+libfsmount_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+TMP_LIBS += libfsmount$(LIB_VARIANT).a
+
+EXTRA_DIST += fsmount/README
+
+## ---
+
+all-local: $(PREINSTALL_FILES) $(TMP_LIBS)
+
+PREINSTALL_DIRS =
+PREINSTALL_FILES =
+
+$(PROJECT_INCLUDE)/rtems/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems
+ @: > $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/capture.h: capture/capture.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/capture.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/capture.h
+
+$(PROJECT_INCLUDE)/rtems/capture-cli.h: capture/capture-cli.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/capture-cli.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/capture-cli.h
+
+$(PROJECT_INCLUDE)/rtems/cpuuse.h: cpuuse/cpuuse.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/cpuuse.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/cpuuse.h
+
+$(PROJECT_INCLUDE)/rtems/devnull.h: devnull/devnull.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/devnull.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/devnull.h
+
+$(PROJECT_INCLUDE)/rtems/dumpbuf.h: dumpbuf/dumpbuf.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/dumpbuf.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/dumpbuf.h
+
+$(PROJECT_INCLUDE)/rtems/monitor.h: monitor/monitor.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/monitor.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/monitor.h
+
+$(PROJECT_INCLUDE)/rtems/mw_fb.h: mw-fb/mw_fb.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/mw_fb.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/mw_fb.h
+
+$(PROJECT_INCLUDE)/rtems/mw_uid.h: mw-fb/mw_uid.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/mw_uid.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/mw_uid.h
+
+if LIBSHELL
+$(PROJECT_INCLUDE)/rtems/shell.h: shell/shell.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/shell.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/shell.h
+endif
+
+$(PROJECT_INCLUDE)/rtems/rtmonuse.h: rtmonuse/rtmonuse.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtmonuse.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtmonuse.h
+
+if LIBSERDBG
+$(PROJECT_INCLUDE)/rtems/serdbgcnf.h: serdbg/serdbgcnf.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/serdbgcnf.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/serdbgcnf.h
+
+$(PROJECT_INCLUDE)/rtems/serdbg.h: serdbg/serdbg.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/serdbg.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/serdbg.h
+
+$(PROJECT_INCLUDE)/rtems/termios_printk_cnf.h: serdbg/termios_printk_cnf.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/termios_printk_cnf.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/termios_printk_cnf.h
+
+$(PROJECT_INCLUDE)/rtems/termios_printk.h: serdbg/termios_printk.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/termios_printk.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/termios_printk.h
+endif
+
+$(PROJECT_INCLUDE)/rtems/stackchk.h: stackchk/stackchk.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/stackchk.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/stackchk.h
+
+$(PROJECT_INCLUDE)/rtems/untar.h: untar/untar.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/untar.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/untar.h
+
+$(PROJECT_INCLUDE)/rtems/fsmount.h: fsmount/fsmount.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/fsmount.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/fsmount.h
+
+CLEANFILES += $(PREINSTALL_FILES)
+DISTCLEANFILES = $(PREINSTALL_DIRS)
+
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/libmisc/README b/cpukit/libmisc/README
new file mode 100644
index 0000000000..bbde4feeae
--- /dev/null
+++ b/cpukit/libmisc/README
@@ -0,0 +1,23 @@
+#
+# $Id$
+#
+
+This directory contains for the "miscellaneous" library. Currently
+this library contains a number of useful support libraries:
+
+ + Task Stack Overflow Checker
+ + Workspace Consistency Checker
+ + Task Execution Time Monitor
+ + Period Statistics Monitor
+ + Debug Monitor
+
+The following ideas have been mentioned for items which could go
+in this library, but this list is not all inclusive:
+
+ + there are no outstanding suggestions.
+
+The intent of this library is to provide a home for useful utility routines
+which are dependent upon RTEMS.
+
+--joel
+16 Sept 97
diff --git a/cpukit/libmisc/capture/README b/cpukit/libmisc/capture/README
new file mode 100644
index 0000000000..2ea76a4cfe
--- /dev/null
+++ b/cpukit/libmisc/capture/README
@@ -0,0 +1,255 @@
+#
+# $Id$
+#
+
+ RTEMS Performance Monitoring and Measurement Framework
+
+ Copyright 2002 Chris Johns (ccj@acm.org)
+ 23 April 2002
+
+This directory contains the source code for the performance monitoring and
+measurement framework. It is more commonly know as the capture engine.
+
+The capture engine is in an early phase of development. Please review the Status
+section of this document for the current status.
+
+Performance.
+
+The capture engine is designed to not effect the system it is
+monitoring. Resources such as memory are used as well as a small performance
+hit in task creation, deletion and context switch. The overhead is small and
+will not be noticed unless the system is operating close to the performance
+limit of the target.
+
+Structure.
+
+The capture engine is implemented in a couple of layers. This lowest layer is
+the capture engine. Its interface is in the file 'capture.h'. Typically this
+interface is directly used unless you are implementing a target interface. The
+user interface is via a target interface.
+
+Command Line Interface (CLI).
+
+This is a target interface that provides a number of user commands via the
+RTEMS monitor. To use you need to provide the following in your
+application initialisation:
+
+ #include <rtems/monitor.h>
+ #include <rtems/capture-cli.h>
+
+ rtems_monitor_init (0);
+ rtems_capture_cli_init (0);
+
+Check the file capture-cli.h for documentation of the interface. The parameter
+is a pointer to your board support package's time stamp handler. The time stamp
+handler is yet to be tested so it is recommended this is left as 0, unless you
+wish to test this part of the engine.
+
+The commands are:
+
+ copen - Open the capture engine.
+ cclose - Close the capture engine.
+ cenable - Enable the capture engine.
+ cdisable - Disable the capture engine.
+ ctlist - List the tasks known to the capture engine.
+ ctload - Display the current load (sort of top).
+ cwlist - List the watch and trigger controls.
+ cwadd - Add a watch.
+ cwdel - Delete a watch.
+ cwctl - Enable or disable a watch.
+ cwglob - Enable or disable the global watch.
+ cwceil - Set the watch ceiling.
+ cwfloor - Set the watch floor.
+ ctrace - Dump the trace records.
+ ctrig - Define a trigger.
+
+Open
+
+ usage: copen [-i] size
+
+Open the capture engine. The size parameter is the size of the capture engine
+trace buffer. A single record hold a single event, for example a task create or
+a context in or out. The option '-i' will enable the capture engine after it is
+opened.
+
+Close
+
+ usage: cclose
+
+Close the capture engine and release all resources held by the capture engine.
+
+Enable
+
+ usage: cenable
+
+Enable the capture engine if it has been opened.
+
+Disable
+
+ usage: cdisable
+
+Disable the capture engine. The enable and disable commands provide a means of
+removing the overhead of the capture engine from the context switch. This may
+be needed when testing if it is felt the capture engines overhead is effecting
+the system.
+
+Task List
+
+ usage: ctlist
+
+List the tasks the capture engine knows about. This may contain tasks that have
+been deleted.
+
+Task Load
+
+ usage: ctload
+
+List the tasks in the order of load in a similar way top does on Unix. The
+command sends ANSI terminal codes. You press enter to stop the update. The
+update period is fixed at 5 seconds. The output looks like:
+
+ Press ENTER to exit.
+
+ PID NAME RPRI CPRI STATE %CPU %STK FLGS EXEC TIME
+04010001 IDLE 255 255 READY 96.012% 0% a-----g 1
+08010009 CPlt 1 1 READY 3.815% 15% a------ 0
+08010003 ntwk 20 20 Wevnt 0.072% 0% at----g 0
+08010004 CSr0 20 20 Wevnt 0.041% 0% at----g 0
+08010001 main 250 250 DELAY 0.041% 0% a-----g 0
+08010008 test 100 100 Wevnt 0.000% 20% at-T-+g 0
+08010007 test 100 100 Wevnt 0.000% 0% at-T-+g 0
+08010005 CSt0 20 20 Wevnt 0.000% 0% at----g 0
+08010006 RMON 1 1 Wsem 0.000% 0% a------ 0
+
+There are 7 flags and from left to right are:
+
+1) 'a' the task is active, and 'd' the task has been deleted.
+2) 't' the task has been traced.
+3) 'F' the task has a from (TO_ANY) trigger.
+4) 'T' the task has a to (FROM_ANY) trigger.
+5) 'E' the task has an edge (FROM_TO) trigger.
+6) '+' the task as a watch control attached, 'w' a watch is enabled.
+7) 'g' the task is part of a global trigger.
+
+The %STK is the percentage of stack used by a task. Currently only tasks
+created while the capture engine is enabled can be monitored.
+
+The RPRI is the real priority. This is the priority set for the task. The
+current priority is the executing priority that may reflect a level set as a
+result of priority inversion.
+
+Watch List
+
+ usage: cwlist
+
+This command lists the watch and trigger controls the capture engine has. A
+control is a structure used by the capture engine to determine if a task is
+watched or triggers capturing.
+
+Watch Add
+
+ usage: cwadd [task name] [id]
+
+Add a watch for a task. You can provide a name or id or both. A name will cause
+all tasks with that name to have the watch added. An id results in a watch
+being for a specific task.
+
+Using a name is useful when the task is not yet created.
+
+Watch Delete
+
+ usage: cwdel [task name] [id]
+
+Delete a watch that has been added.
+
+Watch Control
+
+ usage: cwctl [task name] [id] on/off
+
+Enable or disable a watch. The name and id parameters are the same as the watch
+add command.
+
+Global Watch
+
+ usage: cwglob on/off
+
+Enable or disable the global watch. A global watch is an easy way to enable
+watches for all tasks with real priorities between the watch ceiling and floor
+priorities.
+
+Watch Priority Ceiling
+
+ usage: cwceil priority
+
+Set the watch priority ceiling. All tasks with a priority less than the ceiling
+priority are not watched. This allow you to ignore high priority system and
+driver tasks.
+
+Watch Priority Floor
+
+ usage: cwfloor priority
+
+Set the watch priority floor. All tasks with a priority greater than the floor
+priority level are not watched. This allows you to remove tasks such as IDLE
+from being monitored.
+
+Trace
+
+ usage: ctrace [-c] [-r records]
+
+Dump the trace record. The option '-c' will output the records in comma
+separated variables (CSV). The '-r' option controls the number of records
+dumped. This can help stop the command looping for-ever.
+
+Trigger
+
+ usage: ctrig type [from name] [from id] [to name] [to id]
+
+Set a trigger. The types of triggers are :
+
+ from : trigger on a context switch from a task
+ to : trigger on a context switch to a task
+ edge : trigger on a context switch from a task to a task
+
+The from and to trigger types requires a task name or task id or both be
+provided. The edge requires a from name and/or id and a to name and/or id be
+provided.
+
+Flush
+
+ usage: cflush [-n]
+
+Flush the trace record. The option '-n' stops the capture engine be
+primed. This means an exising trigger state will not be cleared and tracing
+will continue.
+
+Status.
+
+The following is a list of outstanding issues or bugs.
+
+1) The capture engine does not scan the existing list of tasks in the kernel
+ when initialised. This means tasks that exist but are not active are not
+ seen. Not sure how to implement this one.
+
+2) The blocking read of trace records has not been completely implemented or
+ tested. This will wait until I complete the csv support for the cli for a
+ serial UI or the tcp server is implemented.
+
+3) Task control block clean up is not implemented. The control block should be
+ dumped to the trace buffer. This requires extended record formats. This can
+ be implemented using an event flag to indicate an extended record follows
+ the trace record. This would allow a task delete record to be directly
+ followed by the task information.
+
+4) Complete csv (comma separated variable) support for the CLI.
+
+5) Implement a tcp server interface.
+
+6) Complete the capture engine API documentation.
+
+7) Test the user supplied time stamp handler.
+
+8) Task name support is only for the rtems_name type. This means the only the
+ classic API tasks are currently supported. Partial support for the different
+ task names is provided how-ever this is not clean and does not support the
+ variable length task name such as found in the POSIX tasks.
diff --git a/cpukit/libmisc/capture/capture-cli.c b/cpukit/libmisc/capture/capture-cli.c
new file mode 100644
index 0000000000..ca5041d768
--- /dev/null
+++ b/cpukit/libmisc/capture/capture-cli.c
@@ -0,0 +1,1470 @@
+/*
+ ------------------------------------------------------------------------
+ $Id$
+ ------------------------------------------------------------------------
+
+ Copyright Objective Design Systems Pty Ltd, 2002
+ All rights reserved Objective Design Systems Pty Ltd, 2002
+ Chris Johns (ccj@acm.org)
+
+ COPYRIGHT (c) 1989-1998.
+ On-Line Applications Research Corporation (OAR).
+
+ The license and distribution terms for this file may be
+ found in the file LICENSE in this distribution.
+
+ This software with is provided ``as is'' and with NO WARRANTY.
+
+ ------------------------------------------------------------------------
+
+ RTEMS Performance Monitoring and Measurement Framework.
+
+ This is the Target Interface Command Line Interface. You need
+ start the RTEMS monitor.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <rtems.h>
+#include <rtems/capture-cli.h>
+#include <rtems/monitor.h>
+
+#define RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS (32)
+
+/*
+ * The user capture timestamper.
+ */
+static rtems_capture_timestamp capture_timestamp;
+
+/*
+ * Common variable to sync the load monitor task.
+ */
+static volatile int cli_load_thread_active;
+
+/*
+ * rtems_capture_cli_open
+ *
+ * DESCRIPTION:
+ *
+ * This function opens the capture engine. We need the size of the
+ * capture buffer.
+ *
+ */
+
+static const char* open_usage = "usage: copen [-i] size\n";
+
+static void
+rtems_capture_cli_open (
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose )
+{
+ uint32_t size = 0;
+ rtems_boolean enable = 0;
+ rtems_status_code sc;
+ int arg;
+
+ if (argc <= 1)
+ {
+ fprintf(stdout,open_usage);
+ return;
+ }
+
+ for (arg = 1; arg < argc; arg++)
+ {
+ if (argv[arg][0] == '-')
+ {
+ if (argv[arg][1] == 'i')
+ enable = 1;
+ else
+ fprintf(stdout,"warning: option -%c ignored\n", argv[arg][1]);
+ }
+ else
+ {
+ size = strtoul (argv[arg], 0, 0);
+
+ if (size < 100)
+ {
+ fprintf(stdout,"error: size must be greater than or equal to 100\n");
+ return;
+ }
+ }
+ }
+
+ sc = rtems_capture_open (size, capture_timestamp);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"error: open failed: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ fprintf(stdout,"capture engine opened.\n");
+
+ if (!enable)
+ return;
+
+ sc = rtems_capture_control (enable);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"error: open enable failed: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ fprintf(stdout,"capture engine enabled.\n");
+}
+
+/*
+ * rtems_capture_cli_close
+ *
+ * DESCRIPTION:
+ *
+ * This function closes the capture engine.
+ *
+ */
+
+static void
+rtems_capture_cli_close (
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose )
+{
+ rtems_status_code sc;
+
+ sc = rtems_capture_close ();
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"error: close failed: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ fprintf(stdout,"capture engine closed.\n");
+}
+
+/*
+ * rtems_capture_cli_enable
+ *
+ * DESCRIPTION:
+ *
+ * This function enables the capture engine.
+ *
+ */
+
+static void
+rtems_capture_cli_enable (
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose )
+{
+ rtems_status_code sc;
+
+ sc = rtems_capture_control (1);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"error: enable failed: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ fprintf(stdout,"capture engine enabled.\n");
+}
+
+/*
+ * rtems_capture_cli_disable
+ *
+ * DESCRIPTION:
+ *
+ * This function disables the capture engine.
+ *
+ */
+
+static void
+rtems_capture_cli_disable (
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose )
+{
+ rtems_status_code sc;
+
+ sc = rtems_capture_control (0);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"error: disable failed: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ fprintf(stdout,"capture engine disabled.\n");
+}
+
+/*
+ * rtems_capture_cli_task_list
+ *
+ * DESCRIPTION:
+ *
+ * This function lists the tasks the capture engine knows about.
+ *
+ */
+
+static void
+rtems_capture_cli_task_list (
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose )
+{
+ rtems_task_priority ceiling = rtems_capture_watch_get_ceiling ();
+ rtems_task_priority floor = rtems_capture_watch_get_floor ();
+ rtems_capture_task_t* task = rtems_capture_get_task_list ();
+ uint32_t ticks;
+ uint32_t tick_offset;
+ unsigned long long total_time;
+ int count = rtems_capture_task_count ();
+
+ if (capture_timestamp)
+ capture_timestamp (&ticks, &tick_offset);
+ else
+ {
+ ticks = _Watchdog_Ticks_since_boot;
+ tick_offset = 0;
+ }
+
+ total_time = (ticks * rtems_capture_task_time (task)) + tick_offset;
+
+ fprintf(stdout,"total %i\n", count);
+
+ while (task)
+ {
+ rtems_task_priority priority;
+ int stack_used;
+ int time_used;
+
+ stack_used = rtems_capture_task_stack_usage (task) * 100;
+ stack_used /= rtems_capture_task_stack_size (task);
+
+ if (stack_used > 100)
+ stack_used = 100;
+
+ time_used = (rtems_capture_task_time (task) * 100) / total_time;
+
+ if (time_used > 100)
+ time_used = 100;
+
+ priority = rtems_capture_task_real_priority (task);
+
+ fprintf(stdout," ");
+ rtems_monitor_dump_id (rtems_capture_task_id (task));
+ fprintf(stdout," ");
+ rtems_monitor_dump_name (rtems_capture_task_name (task));
+ fprintf(stdout," ");
+ rtems_monitor_dump_priority (rtems_capture_task_start_priority (task));
+ fprintf(stdout," ");
+ rtems_monitor_dump_priority (rtems_capture_task_real_priority (task));
+ fprintf(stdout," ");
+ rtems_monitor_dump_priority (rtems_capture_task_curr_priority (task));
+ fprintf(stdout," ");
+ rtems_monitor_dump_state (rtems_capture_task_state (task));
+ fprintf(stdout," %c%c%c%c%c",
+ rtems_capture_task_valid (task) ? 'a' : 'd',
+ rtems_capture_task_flags (task) & RTEMS_CAPTURE_TRACED ? 't' : '-',
+ rtems_capture_task_control_flags (task) & RTEMS_CAPTURE_TO_ANY ? 'F' : '-',
+ rtems_capture_task_control_flags (task) & RTEMS_CAPTURE_FROM_ANY ? 'T' : '-',
+ rtems_capture_task_control_flags (task) & RTEMS_CAPTURE_FROM_TO ? 'E' : '-');
+ if ((floor > ceiling) && (ceiling > priority))
+ fprintf(stdout,"--");
+ else
+ fprintf(stdout,"%c%c",
+ rtems_capture_task_control (task) ?
+ (rtems_capture_task_control_flags (task) & RTEMS_CAPTURE_WATCH ? 'w' : '+') : '-',
+ rtems_capture_watch_global_on () ? 'g' : '-');
+ fprintf(stdout," %3i%% %3i%% (%i)\n",
+ stack_used, time_used, rtems_capture_task_ticks (task));
+
+ task = rtems_capture_next_task (task);
+ }
+}
+
+/*
+ * rtems_capture_cli_task_load_thread
+ *
+ * DESCRIPTION:
+ *
+ * This function displays the load of the tasks on an ANSI terminal.
+ *
+ */
+
+static void
+rtems_capture_cli_task_load_thread (rtems_task_argument arg)
+{
+ rtems_task_priority ceiling = rtems_capture_watch_get_ceiling ();
+ rtems_task_priority floor = rtems_capture_watch_get_floor ();
+ int last_count = 0;
+
+ fprintf(stdout,"\x1b[2J Press ENTER to exit.\n\n");
+ fprintf(stdout," PID NAME RPRI CPRI STATE %%CPU %%STK FLGS EXEC TIME\n");
+
+ for (;;)
+ {
+ rtems_capture_task_t* tasks[RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS + 1];
+ unsigned long long load[RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS + 1];
+ rtems_capture_task_t* task;
+ unsigned long long total_time;
+ int count = 0;
+ int i;
+ int j;
+
+ cli_load_thread_active = 1;
+
+ /*
+ * Iterate over the tasks and sort the highest load tasks
+ * into our local arrays. We only handle a limited number of
+ * tasks.
+ */
+
+ memset (tasks, 0, sizeof (tasks));
+ memset (load, 0, sizeof (load));
+
+ task = rtems_capture_get_task_list ();
+
+ while (task)
+ {
+ if (rtems_capture_task_valid (task))
+ {
+ unsigned long long l = rtems_capture_task_delta_time (task);
+
+ count++;
+
+ for (i = 0; i < RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS; i++)
+ {
+ if (tasks[i])
+ {
+ if ((l == 0) || (l < load[i]))
+ continue;
+
+ for (j = (RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS - 1); j >= i; j--)
+ {
+ tasks[j + 1] = tasks[j];
+ load[j + 1] = load[j];
+ }
+ }
+
+ tasks[i] = task;
+ load[i] = l;
+ break;
+ }
+ }
+ task = rtems_capture_next_task (task);
+ }
+
+ fprintf(stdout,"\x1b[4;0H");
+
+ total_time = 0;
+
+ for (i = 0; i < RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS; i++)
+ total_time += load[i];
+
+ if (count > last_count)
+ j = count;
+ else
+ j = last_count;
+
+ for (i = 0; i < RTEMS_CAPTURE_CLI_MAX_LOAD_TASKS; i++)
+ {
+ rtems_task_priority priority;
+ int stack_used;
+ int task_load;
+ int k;
+
+ if (!tasks[i])
+ break;
+
+ j--;
+
+ stack_used = rtems_capture_task_stack_usage (tasks[i]) * 100;
+ stack_used /= rtems_capture_task_stack_size (tasks[i]);
+
+ if (stack_used > 100)
+ stack_used = 100;
+
+ task_load = (int) ((load[i] * 100000) / total_time);
+
+ priority = rtems_capture_task_real_priority (tasks[i]);
+
+ fprintf(stdout,"\x1b[K");
+ rtems_monitor_dump_id (rtems_capture_task_id (tasks[i]));
+ fprintf(stdout," ");
+ rtems_monitor_dump_name (rtems_capture_task_name (tasks[i]));
+ fprintf(stdout," ");
+ rtems_monitor_dump_priority (priority);
+ fprintf(stdout," ");
+ rtems_monitor_dump_priority (rtems_capture_task_curr_priority (tasks[i]));
+ fprintf(stdout," ");
+ k = rtems_monitor_dump_state (rtems_capture_task_state (tasks[i]));
+ fprintf(stdout,"%*c %3i.%03i%% ", 6 - k, ' ', task_load / 1000, task_load % 1000);
+ fprintf(stdout,"%3i%% %c%c%c%c%c", stack_used,
+ rtems_capture_task_valid (tasks[i]) ? 'a' : 'd',
+ rtems_capture_task_flags (tasks[i]) & RTEMS_CAPTURE_TRACED ? 't' : '-',
+ rtems_capture_task_control_flags (tasks[i]) & RTEMS_CAPTURE_TO_ANY ? 'F' : '-',
+ rtems_capture_task_control_flags (tasks[i]) & RTEMS_CAPTURE_FROM_ANY ? 'T' : '-',
+ rtems_capture_task_control_flags (tasks[i]) & RTEMS_CAPTURE_FROM_TO ? 'E' : '-');
+ if ((floor > ceiling) && (ceiling > priority))
+ fprintf(stdout,"--");
+ else
+ fprintf(stdout,"%c%c",
+ rtems_capture_task_control (tasks[i]) ?
+ (rtems_capture_task_control_flags (tasks[i]) &
+ RTEMS_CAPTURE_WATCH ? 'w' : '+') : '-',
+ rtems_capture_watch_global_on () ? 'g' : '-');
+
+ fprintf(stdout," %qi\n", rtems_capture_task_time (tasks[i]));
+ }
+
+ while (j)
+ {
+ fprintf(stdout,"\x1b[K\n");
+ j--;
+ }
+
+ last_count = count;
+
+ cli_load_thread_active = 0;
+
+ rtems_task_wake_after (TOD_MICROSECONDS_TO_TICKS (5000000));
+ }
+}
+
+/*
+ * rtems_capture_cli_task_load
+ *
+ * DESCRIPTION:
+ *
+ * This function is a monitor command.
+ *
+ */
+
+static void
+rtems_capture_cli_task_load (
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose )
+{
+ rtems_status_code sc;
+ rtems_task_priority priority;
+ rtems_name name;
+ rtems_id id;
+
+ sc = rtems_task_set_priority (RTEMS_SELF, RTEMS_CURRENT_PRIORITY, &priority);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"error: cannot obtain the current priority: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ memcpy (&name, "CPlt", 4);
+
+ sc = rtems_task_create (name, priority, 1024,
+ RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL,
+ RTEMS_PREEMPT | RTEMS_TIMESLICE | RTEMS_NO_ASR,
+ &id);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"error: cannot create helper thread: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ sc = rtems_task_start (id, rtems_capture_cli_task_load_thread, 0);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"error: cannot start helper thread: %s\n", rtems_status_text (sc));
+ rtems_task_delete (id);
+ return;
+ }
+
+ for (;;)
+ {
+ int c = getchar ();
+
+ if ((c == '\r') || (c == '\n'))
+ {
+ int loops = 20;
+
+ while (loops && cli_load_thread_active)
+ rtems_task_wake_after (TOD_MICROSECONDS_TO_TICKS (100000));
+
+ rtems_task_delete (id);
+
+ fprintf(stdout,"load monitoring stopped.\n");
+
+ return;
+ }
+ }
+}
+
+/*
+ * rtems_capture_cli_watch_list
+ *
+ * DESCRIPTION:
+ *
+ * This function lists the controls in the capture engine.
+ *
+ */
+
+static void
+rtems_capture_cli_watch_list (
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose )
+{
+ rtems_capture_control_t* control = rtems_capture_get_control_list ();
+ rtems_task_priority ceiling = rtems_capture_watch_get_ceiling ();
+ rtems_task_priority floor = rtems_capture_watch_get_floor ();
+
+ fprintf(stdout,"watch priority ceiling is %i\n", ceiling);
+ fprintf(stdout,"watch priority floor is %i\n", floor);
+ fprintf(stdout,"global watch is %s\n",
+ rtems_capture_watch_global_on () ? "enabled" : "disabled");
+ fprintf(stdout,"total %d\n", rtems_capture_control_count ());
+
+ while (control)
+ {
+ int f;
+ int fshowed;
+ int lf;
+
+ fprintf(stdout," ");
+ rtems_monitor_dump_id (rtems_capture_control_id (control));
+ fprintf(stdout," ");
+ rtems_monitor_dump_name (rtems_capture_control_name (control));
+ fprintf(stdout," %c%c%c%c%c",
+ rtems_capture_control_flags (control) & RTEMS_CAPTURE_WATCH ? 'w' : '-',
+ rtems_capture_watch_global_on () ? 'g' : '-',
+ rtems_capture_control_flags (control) & RTEMS_CAPTURE_TO_ANY ? 'F' : '-',
+ rtems_capture_control_flags (control) & RTEMS_CAPTURE_FROM_ANY ? 'T' : '-',
+ rtems_capture_control_flags (control) & RTEMS_CAPTURE_FROM_TO ? 'E' : '-');
+
+ for (f = 0, fshowed = 0, lf = 1; f < RTEMS_CAPTURE_TRIGGER_TASKS; f++)
+ {
+ if (lf && ((fshowed % 16) == 0))
+ {
+ fprintf(stdout,"\n");
+ lf = 0;
+ }
+
+ /*
+ * FIXME: name test.
+ */
+ if (rtems_capture_control_from_name (control, f))
+ {
+ fprintf(stdout," %2i:", f);
+ rtems_monitor_dump_name (rtems_capture_control_from_name (control, f));
+ fprintf(stdout,"/");
+ rtems_monitor_dump_id (rtems_capture_control_from_id (control, f));
+ fshowed++;
+ lf = 1;
+ }
+ }
+
+ if (lf)
+ fprintf(stdout,"\n");
+
+ control = rtems_capture_next_control (control);
+ }
+}
+
+/*
+ * rtems_capture_cli_get_name_id
+ *
+ * DESCRIPTION:
+ *
+ * This function checks arguments for a name or an id.
+ *
+ */
+
+static rtems_boolean
+rtems_capture_cli_get_name_id (char* arg,
+ rtems_boolean* valid_name,
+ rtems_boolean* valid_id,
+ rtems_name* name,
+ rtems_id* id)
+{
+ uint32_t objclass;
+ int l;
+ int i;
+
+ if (*valid_name && *valid_id)
+ {
+ fprintf(stdout,"error: too many arguments\n");
+ return 0;
+ }
+
+ /*
+ * See if the arg is all hex digits.
+ */
+
+ l = strlen (arg);
+
+ for (i = 0; i < l; i++)
+ if (!isxdigit (arg[i]))
+ break;
+
+ *id = strtoul (arg, 0, 16);
+
+ objclass = _Objects_Get_class (*id);
+
+ if ((i == l))
+ *valid_id = 1;
+ else
+ {
+ memcpy (name, arg, sizeof (rtems_name));
+ *valid_name = 1;
+ }
+
+ return 1;
+}
+
+/*
+ * rtems_capture_cli_watch_add
+ *
+ * DESCRIPTION:
+ *
+ * This function is a monitor command that add a watch to the capture
+ * engine.
+ *
+ */
+
+static char const * watch_add_usage = "usage: cwadd [task name] [id]\n";
+
+static void
+rtems_capture_cli_watch_add (
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose )
+{
+ rtems_status_code sc;
+ int arg;
+ rtems_name name = 0;
+ rtems_id id = 0;
+ rtems_boolean valid_name = 0;
+ rtems_boolean valid_id = 0;
+
+ if (argc <= 1)
+ {
+ fprintf(stdout,watch_add_usage);
+ return;
+ }
+
+ for (arg = 1; arg < argc; arg++)
+ {
+ if (argv[arg][0] == '-')
+ {
+ fprintf(stdout,"warning: option -%c ignored\n", argv[arg][1]);
+ }
+ else
+ {
+ if (!rtems_capture_cli_get_name_id (argv[arg], &valid_name, &valid_id, &name, &id))
+ return;
+ }
+ }
+
+ if (!valid_name && !valid_id)
+ {
+ fprintf(stdout,"error: no valid name or task id located\n");
+ return;
+ }
+
+ sc = rtems_capture_watch_add (name, id);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"error: watch add failed: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ fprintf(stdout,"watch added.\n");
+}
+
+/*
+ * rtems_capture_cli_watch_del
+ *
+ * DESCRIPTION:
+ *
+ * This function is a monitor command that deletes a watch from the capture
+ * engine.
+ *
+ */
+
+static char const * watch_del_usage = "usage: cwdel [task name] [id]\n";
+
+static void
+rtems_capture_cli_watch_del (
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose )
+{
+ rtems_status_code sc;
+ int arg;
+ rtems_name name = 0;
+ rtems_id id = 0;
+ rtems_boolean valid_name = 0;
+ rtems_boolean valid_id = 0;
+
+ if (argc <= 1)
+ {
+ fprintf(stdout,watch_del_usage);
+ return;
+ }
+
+ for (arg = 1; arg < argc; arg++)
+ {
+ if (argv[arg][0] == '-')
+ {
+ fprintf(stdout,"warning: option -%c ignored\n", argv[arg][1]);
+ }
+ else
+ {
+ if (!rtems_capture_cli_get_name_id (argv[arg], &valid_name, &valid_id, &name, &id))
+ return;
+ }
+ }
+
+ if (!valid_name && !valid_id)
+ {
+ fprintf(stdout,"error: no valid name or task id located\n");
+ return;
+ }
+
+ sc = rtems_capture_watch_del (name, id);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"error: watch delete failed: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ fprintf(stdout,"watch delete.\n");
+}
+
+/*
+ * rtems_capture_cli_watch_control
+ *
+ * DESCRIPTION:
+ *
+ * This function is a monitor command that controls a watch.
+ *
+ */
+
+static char const * watch_control_usage = "usage: cwctl [task name] [id] on/off\n";
+
+static void
+rtems_capture_cli_watch_control (
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose )
+{
+ rtems_status_code sc;
+ int arg;
+ rtems_name name = 0;
+ rtems_id id = 0;
+ rtems_boolean valid_name = 0;
+ rtems_boolean valid_id = 0;
+ rtems_boolean enable = 0;
+
+ if (argc <= 2)
+ {
+ fprintf(stdout,watch_control_usage);
+ return;
+ }
+
+ for (arg = 1; arg < argc; arg++)
+ {
+ if (argv[arg][0] == '-')
+ {
+ fprintf(stdout,"warning: option -%c ignored\n", argv[arg][1]);
+ }
+ else
+ {
+ if (strcmp (argv[arg], "on") == 0)
+ enable = 1;
+ else if (strcmp (argv[arg], "off") == 0)
+ enable = 0;
+ else if (!rtems_capture_cli_get_name_id (argv[arg], &valid_name, &valid_id, &name, &id))
+ return;
+ }
+ }
+
+ if (!valid_name && !valid_id)
+ {
+ fprintf(stdout,"error: no valid name or task id located\n");
+ return;
+ }
+
+ sc = rtems_capture_watch_ctrl (name, id, enable);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"error: watch control failed: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ fprintf(stdout,"watch %s.\n", enable ? "enabled" : "disabled");
+}
+
+/*
+ * rtems_capture_cli_watch_global
+ *
+ * DESCRIPTION:
+ *
+ * This function is a monitor command that sets a global watch.
+ *
+ */
+
+static char const * watch_global_usage = "usage: cwglob on/off\n";
+
+static void
+rtems_capture_cli_watch_global (
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose )
+{
+ rtems_status_code sc;
+ int arg;
+ rtems_boolean enable = 0;
+
+ if (argc <= 1)
+ {
+ fprintf(stdout,watch_global_usage);
+ return;
+ }
+
+ for (arg = 1; arg < argc; arg++)
+ {
+ if (argv[arg][0] == '-')
+ {
+ fprintf(stdout,"warning: option -%c ignored\n", argv[arg][1]);
+ }
+ else
+ {
+ if (strcmp (argv[arg], "on") == 0)
+ enable = 1;
+ else if (strcmp (argv[arg], "off") == 0)
+ enable = 0;
+ }
+ }
+
+ sc = rtems_capture_watch_global (enable);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"error: global watch failed: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ fprintf(stdout,"global watch %s.\n", enable ? "enabled" : "disabled");
+}
+
+/*
+ * rtems_capture_cli_watch_ceiling
+ *
+ * DESCRIPTION:
+ *
+ * This function is a monitor command that sets watch ceiling.
+ *
+ */
+
+static char const * watch_ceiling_usage = "usage: cwceil priority\n";
+
+static void
+rtems_capture_cli_watch_ceiling (
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose )
+{
+ rtems_status_code sc;
+ int arg;
+ rtems_task_priority priority = 0;
+
+ if (argc <= 1)
+ {
+ fprintf(stdout,watch_ceiling_usage);
+ return;
+ }
+
+ for (arg = 1; arg < argc; arg++)
+ {
+ if (argv[arg][0] == '-')
+ {
+ fprintf(stdout,"warning: option -%c ignored\n", argv[arg][1]);
+ }
+ else
+ {
+ priority = strtoul (argv[arg], 0, 0);
+ }
+ }
+
+ sc = rtems_capture_watch_ceiling (priority);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"error: watch ceiling failed: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ fprintf(stdout,"watch ceiling is %i.\n", priority);
+}
+
+/*
+ * rtems_capture_cli_watch_floor
+ *
+ * DESCRIPTION:
+ *
+ * This function is a monitor command that sets watch floor.
+ *
+ */
+
+static char const * watch_floor_usage = "usage: cwfloor priority\n";
+
+static void
+rtems_capture_cli_watch_floor (
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose )
+{
+ rtems_status_code sc;
+ int arg;
+ rtems_task_priority priority = 0;
+
+ if (argc <= 1)
+ {
+ fprintf(stdout,watch_floor_usage);
+ return;
+ }
+
+ for (arg = 1; arg < argc; arg++)
+ {
+ if (argv[arg][0] == '-')
+ {
+ fprintf(stdout,"warning: option -%c ignored\n", argv[arg][1]);
+ }
+ else
+ {
+ priority = strtoul (argv[arg], 0, 0);
+ }
+ }
+
+ sc = rtems_capture_watch_floor (priority);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"error: watch floor failed: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ fprintf(stdout,"watch floor is %i.\n", priority);
+}
+
+/*
+ * rtems_capture_cli_trigger_set
+ *
+ * DESCRIPTION:
+ *
+ * This function is a monitor command that sets a trigger.
+ *
+ */
+
+static char const *trigger_set_usage = "usage: ctrig type [from] [fromid] [to] [to id]\n";
+
+static void
+rtems_capture_cli_trigger_set (
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose )
+{
+ rtems_status_code sc;
+ int arg;
+ rtems_capture_trigger_t trigger = rtems_capture_from_to;
+ rtems_boolean trigger_set = 0;
+ rtems_name name = 0;
+ rtems_id id = 0;
+ rtems_boolean valid_name = 0;
+ rtems_boolean valid_id = 0;
+ rtems_name from_name = 0;
+ rtems_id from_id = 0;
+ rtems_boolean from_valid_name = 0;
+ rtems_boolean from_valid_id = 0;
+ rtems_name to_name = 0;
+ rtems_id to_id = 0;
+ rtems_boolean to_valid_name = 0;
+ rtems_boolean to_valid_id = 0;
+
+ if (argc <= 2)
+ {
+ fprintf(stdout,trigger_set_usage);
+ return;
+ }
+
+ for (arg = 1; arg < argc; arg++)
+ {
+ if (argv[arg][0] == '-')
+ {
+ fprintf(stdout,"warning: option -%c ignored\n", argv[arg][1]);
+ }
+ else
+ {
+ if (!trigger_set)
+ {
+ if (strcmp (argv[arg], "from") == 0)
+ trigger = rtems_capture_to_any;
+ else if (strcmp (argv[arg], "to") == 0)
+ trigger = rtems_capture_from_any;
+ else if (strcmp (argv[arg], "edge") == 0)
+ trigger = rtems_capture_from_any;
+ else
+ {
+ fprintf(stdout,"error: the first argument is the trigger type (from/to/edge)\n");
+ return;
+ }
+ trigger_set = 1;
+ }
+ else
+ {
+ if (trigger == rtems_capture_to_any)
+ {
+ if (from_valid_name && from_valid_id)
+ fprintf(stdout,"warning: extra arguments ignored\n");
+ else if (!rtems_capture_cli_get_name_id (argv[arg], &from_valid_name, &from_valid_id,
+ &from_name, &from_id))
+ return;
+ }
+ else if (trigger == rtems_capture_from_any)
+ {
+ if (to_valid_name && to_valid_id)
+ fprintf(stdout,"warning: extra arguments ignored\n");
+ else if (!rtems_capture_cli_get_name_id (argv[arg], &to_valid_name, &to_valid_id,
+ &to_name, &to_id))
+ return;
+ }
+ else if (trigger == rtems_capture_from_to)
+ {
+ if (from_valid_name && from_valid_id && to_valid_name && to_valid_id)
+ fprintf(stdout,"warning: extra arguments ignored\n");
+ else
+ {
+ if (!rtems_capture_cli_get_name_id (argv[arg], &valid_name, &valid_id,
+ &name, &id))
+ return;
+
+ if (valid_name)
+ {
+ if (!from_valid_name && !from_valid_id)
+ {
+ from_valid_name = 1;
+ from_name = name;
+ }
+ else if (to_valid_name)
+ fprintf(stdout,"warning: extra arguments ignored\n");
+ else
+ {
+ to_valid_name = 1;
+ to_name = name;
+ }
+ }
+ if (valid_id)
+ {
+ if (!from_valid_id && !to_valid_name)
+ {
+ from_valid_id = 1;
+ from_id = id;
+ }
+ else if (to_valid_id)
+ fprintf(stdout,"warning: extra arguments ignored\n");
+ else
+ {
+ to_valid_id = 1;
+ to_id = id;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if ((trigger == rtems_capture_to_any) && !from_valid_name && !from_valid_id)
+ {
+ fprintf(stdout,"error: a from trigger need a to name or id\n");
+ return;
+ }
+
+ if ((trigger == rtems_capture_from_any) && !to_valid_name && !to_valid_id)
+ {
+ fprintf(stdout,"error: a to trigger need a from name or id\n");
+ return;
+ }
+
+ if ((trigger == rtems_capture_from_to) &&
+ ((!from_valid_name && !from_valid_id) || (!to_valid_name && !to_valid_id)))
+ {
+ fprintf(stdout,"error: an edge trigger need a from and to name or id\n");
+ return;
+ }
+
+ sc = rtems_capture_set_trigger (from_name, from_id, to_name, to_id, trigger);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"error: setting the trigger failed: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ fprintf(stdout,"trigger set.\n");
+}
+
+/*
+ * rtems_capture_cli_trace_records
+ *
+ * DESCRIPTION:
+ *
+ * This function is a monitor command that dumps trace records.
+ *
+ */
+
+static void
+rtems_capture_cli_trace_records (
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose )
+{
+ rtems_status_code sc;
+ rtems_boolean csv = 0;
+ static int dump_total = 32;
+ int total;
+ int count;
+ uint32_t read;
+ rtems_capture_record_t* rec;
+ int arg;
+
+ for (arg = 1; arg < argc; arg++)
+ {
+ if (argv[arg][0] == '-')
+ {
+ if (argv[arg][1] == 'c')
+ csv = 1;
+ else if (argv[arg][1] == 'r')
+ {
+ int i;
+ int l;
+
+ arg++;
+ if (arg == argc)
+ {
+ fprintf(stdout,"error: option -r requires number\n");
+ return;
+ }
+
+ l = strlen (argv[arg]);
+
+ for (i = 0; i < l; i++)
+ if (!isdigit (argv[arg][i]))
+ {
+ fprintf(stdout,"error: option -r requires number and currently it is not\n");
+ return;
+ }
+
+ dump_total = strtoul (argv[arg], 0, 0);
+ }
+ else
+ fprintf(stdout,"warning: option -%c ignored\n", argv[arg][1]);
+ }
+ }
+
+ total = dump_total;
+
+ while (total)
+ {
+ sc = rtems_capture_read (0, 0, &read, &rec);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"error: trace read failed: %s\n", rtems_status_text (sc));
+ rtems_capture_flush (0);
+ return;
+ }
+
+ if (read == 0)
+ break;
+
+ for (count = 0; count < read; count++, rec++)
+ {
+ if (csv)
+ fprintf(stdout,"%08x,%03d,%03d,%04x,%d,%d\n",
+ (uint32_t ) rec->task,
+ (rec->events >> RTEMS_CAPTURE_REAL_PRIORITY_EVENT) & 0xff,
+ (rec->events >> RTEMS_CAPTURE_CURR_PRIORITY_EVENT) & 0xff,
+ (rec->events >> RTEMS_CAPTURE_EVENT_START),
+ rec->ticks, rec->tick_offset);
+ else
+ {
+ unsigned long long t;
+ uint32_t event;
+ int e;
+
+ event = rec->events >> RTEMS_CAPTURE_EVENT_START;
+
+ t = rec->ticks;
+ t *= rtems_capture_tick_time ();
+ t += rec->tick_offset;
+
+ for (e = RTEMS_CAPTURE_EVENT_START; e < RTEMS_CAPTURE_EVENT_END; e++)
+ {
+ if (event & 1)
+ {
+ fprintf(stdout,"%9li.%06li ", (unsigned long) (t / 1000000),
+ (unsigned long) (t % 1000000));
+ rtems_monitor_dump_id (rtems_capture_task_id (rec->task));
+ fprintf(stdout," ");
+ rtems_monitor_dump_name (rtems_capture_task_name (rec->task));
+ fprintf(stdout," %3i %3i %s\n",
+ (rec->events >> RTEMS_CAPTURE_REAL_PRIORITY_EVENT) & 0xff,
+ (rec->events >> RTEMS_CAPTURE_CURR_PRIORITY_EVENT) & 0xff,
+ rtems_capture_event_text (e));
+ }
+ event >>= 1;
+ }
+ }
+ }
+
+ if (read < total)
+ total -= read;
+ else
+ total = 0;
+
+ rtems_capture_release (read);
+ }
+}
+
+/*
+ * rtems_capture_cli_flush
+ *
+ * DESCRIPTION:
+ *
+ * This function is a monitor command that flushes and primes the capture
+ * engine.
+ *
+ */
+
+static void
+rtems_capture_cli_flush (
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose )
+{
+ rtems_status_code sc;
+ rtems_boolean prime = 1;
+ int arg;
+
+ for (arg = 1; arg < argc; arg++)
+ {
+ if (argv[arg][0] == '-')
+ {
+ if (argv[arg][1] == 'n')
+ prime = 0;
+ else
+ fprintf(stdout,"warning: option -%c ignored\n", argv[arg][1]);
+ }
+ }
+
+ sc = rtems_capture_flush (prime);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ fprintf(stdout,"error: flush failed: %s\n", rtems_status_text (sc));
+ return;
+ }
+
+ fprintf(stdout,"trace buffer flushed and %s.\n", prime ? "primed" : "not primed");
+}
+
+static rtems_monitor_command_entry_t rtems_capture_cli_cmds[] =
+{
+ {
+ "copen",
+ "usage: copen [-i] size\n",
+ 0,
+ rtems_capture_cli_open,
+ { 0 },
+ 0
+ },
+ {
+ "cclose",
+ "usage: cclose\n",
+ 0,
+ rtems_capture_cli_close,
+ { 0 },
+ 0
+ },
+ {
+ "cenable",
+ "usage: cenable\n",
+ 0,
+ rtems_capture_cli_enable,
+ { 0 },
+ 0
+ },
+ {
+ "cdisable",
+ "usage: cdisable\n",
+ 0,
+ rtems_capture_cli_disable,
+ { 0 },
+ 0
+ },
+ {
+ "ctlist",
+ "usage: ctlist \n",
+ 0,
+ rtems_capture_cli_task_list,
+ { 0 },
+ 0
+ },
+ {
+ "ctload",
+ "usage: ctload \n",
+ 0,
+ rtems_capture_cli_task_load,
+ { 0 },
+ 0
+ },
+ {
+ "cwlist",
+ "usage: cwlist\n",
+ 0,
+ rtems_capture_cli_watch_list,
+ { 0 },
+ 0
+ },
+ {
+ "cwadd",
+ "usage: cwadd [task name] [id]\n",
+ 0,
+ rtems_capture_cli_watch_add,
+ { 0 },
+ 0
+ },
+ {
+ "cwdel",
+ "usage: cwdel [task name] [id]\n",
+ 0,
+ rtems_capture_cli_watch_del,
+ { 0 },
+ 0
+ },
+ {
+ "cwctl",
+ "usage: cwctl [task name] [id] on/off\n",
+ 0,
+ rtems_capture_cli_watch_control,
+ { 0 },
+ 0
+ },
+ {
+ "cwglob",
+ "usage: cwglob on/off\n",
+ 0,
+ rtems_capture_cli_watch_global,
+ { 0 },
+ 0
+ },
+ {
+ "cwceil",
+ "usage: cwceil priority\n",
+ 0,
+ rtems_capture_cli_watch_ceiling,
+ { 0 },
+ 0
+ },
+ {
+ "cwfloor",
+ "usage: cwfloor priority\n",
+ 0,
+ rtems_capture_cli_watch_floor,
+ { 0 },
+ 0
+ },
+ {
+ "ctrace",
+ "usage: ctrace [-c] [-r records]\n",
+ 0,
+ rtems_capture_cli_trace_records,
+ { 0 },
+ 0
+ },
+ {
+ "ctrig",
+ "usage: ctrig type [from name] [from id] [to name] [to id]\n",
+ 0,
+ rtems_capture_cli_trigger_set,
+ { 0 },
+ 0
+ },
+ {
+ "cflush",
+ "usage: cflush [-n]\n",
+ 0,
+ rtems_capture_cli_flush,
+ { 0 },
+ 0
+ }
+};
+
+/*
+ * rtems_capture_cli_init
+ *
+ * DESCRIPTION:
+ *
+ * This function initialises the command line interface to the capture
+ * engine.
+ *
+ */
+
+rtems_status_code
+rtems_capture_cli_init (rtems_capture_timestamp timestamp)
+{
+ int cmd;
+
+ capture_timestamp = timestamp;
+
+ for (cmd = 0;
+ cmd < sizeof (rtems_capture_cli_cmds) / sizeof (rtems_monitor_command_entry_t);
+ cmd++)
+ rtems_monitor_insert_cmd (&rtems_capture_cli_cmds[cmd]);
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/libmisc/capture/capture-cli.h b/cpukit/libmisc/capture/capture-cli.h
new file mode 100644
index 0000000000..519cad0d56
--- /dev/null
+++ b/cpukit/libmisc/capture/capture-cli.h
@@ -0,0 +1,52 @@
+/*
+ ------------------------------------------------------------------------
+ $Id$
+ ------------------------------------------------------------------------
+
+ Copyright Objective Design Systems Pty Ltd, 2002
+ All rights reserved Objective Design Systems Pty Ltd, 2002
+ Chris Johns (ccj@acm.org)
+
+ COPYRIGHT (c) 1989-1998.
+ On-Line Applications Research Corporation (OAR).
+
+ The license and distribution terms for this file may be
+ found in the file LICENSE in this distribution.
+
+ This software with is provided ``as is'' and with NO WARRANTY.
+
+ ------------------------------------------------------------------------
+
+ RTEMS Performance Monitoring and Measurement Framework.
+
+ This is the Target Interface Command Line Interface. You need
+ start the RTEMS monitor.
+
+*/
+
+#ifndef __CAPTURE_CLI_H_
+#define __CAPTURE_CLI_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/capture.h>
+
+/*
+ * rtems_capture_cli_init
+ *
+ * DESCRIPTION:
+ *
+ * This function initialises the command line interface to the capture
+ * engine.
+ *
+ */
+rtems_status_code
+rtems_capture_cli_init (rtems_capture_timestamp timestamp);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/libmisc/capture/capture.c b/cpukit/libmisc/capture/capture.c
new file mode 100644
index 0000000000..c8fd751918
--- /dev/null
+++ b/cpukit/libmisc/capture/capture.c
@@ -0,0 +1,1569 @@
+/*
+ ------------------------------------------------------------------------
+ $Id$
+ ------------------------------------------------------------------------
+
+ Copyright Objective Design Systems Pty Ltd, 2002
+ All rights reserved Objective Design Systems Pty Ltd, 2002
+ Chris Johns (ccj@acm.org)
+
+ COPYRIGHT (c) 1989-1998.
+ On-Line Applications Research Corporation (OAR).
+
+ The license and distribution terms for this file may be
+ found in the file LICENSE in this distribution.
+
+ This software with is provided ``as is'' and with NO WARRANTY.
+
+ ------------------------------------------------------------------------
+
+ RTEMS Performance Monitoring and Measurement Framework.
+
+ This is the Capture Engine component.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "capture.h"
+#include <rtems/score/states.inl>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/wkspace.inl>
+
+/*
+ * These events are always recorded and are not part of the
+ * watch filters.
+ */
+#define RTEMS_CAPTURE_RECORD_EVENTS (RTEMS_CAPTURE_CREATED_BY_EVENT | \
+ RTEMS_CAPTURE_CREATED_EVENT | \
+ RTEMS_CAPTURE_STARTED_BY_EVENT | \
+ RTEMS_CAPTURE_STARTED_EVENT | \
+ RTEMS_CAPTURE_RESTARTED_BY_EVENT | \
+ RTEMS_CAPTURE_RESTARTED_EVENT | \
+ RTEMS_CAPTURE_DELETED_BY_EVENT | \
+ RTEMS_CAPTURE_DELETED_EVENT | \
+ RTEMS_CAPTURE_BEGIN_EVENT | \
+ RTEMS_CAPTURE_EXITTED_EVENT)
+
+/*
+ * Global capture flags.
+ */
+#define RTEMS_CAPTURE_ON (1 << 0)
+#define RTEMS_CAPTURE_NO_MEMORY (1 << 1)
+#define RTEMS_CAPTURE_OVERFLOW (1 << 2)
+#define RTEMS_CAPTURE_TRIGGERED (1 << 3)
+#define RTEMS_CAPTURE_READER_ACTIVE (1 << 4)
+#define RTEMS_CAPTURE_READER_WAITING (1 << 5)
+#define RTEMS_CAPTURE_GLOBAL_WATCH (1 << 6)
+
+/*
+ * RTEMS Capture Data.
+ */
+static rtems_capture_record_t* capture_records;
+static uint32_t capture_size;
+static uint32_t capture_count;
+static rtems_capture_record_t* capture_in;
+static uint32_t capture_out;
+static uint32_t capture_flags;
+static rtems_capture_task_t* capture_tasks;
+static rtems_capture_control_t* capture_controls;
+static int capture_extension_index;
+static rtems_id capture_id;
+static rtems_capture_timestamp capture_timestamp;
+static rtems_task_priority capture_ceiling;
+static rtems_task_priority capture_floor;
+static uint32_t capture_tick_period;
+static rtems_id capture_reader;
+
+/*
+ * RTEMS Event text.
+ */
+static const char* capture_event_text[] =
+{
+ "CREATED_BY",
+ "CREATED",
+ "STARTED_BY",
+ "STARTED",
+ "RESTARTED_BY",
+ "RESTARTED",
+ "DELETED_BY",
+ "DELETED",
+ "BEGIN",
+ "EXITTED",
+ "SWITCHED_OUT",
+ "SWITCHED_IN",
+ "TIMESTAMP"
+};
+
+/*
+ * rtems_capture_get_time
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the current time. If a handler is provided
+ * by the user get the time from that.
+ */
+static inline void rtems_capture_get_time (uint32_t * ticks,
+ uint32_t * tick_offset)
+{
+ if (capture_timestamp)
+ capture_timestamp (ticks, tick_offset);
+ else
+ {
+ *ticks = _Watchdog_Ticks_since_boot;
+ *tick_offset = 0;
+ }
+}
+
+/*
+ * rtems_capture_match_names
+ *
+ * DESCRIPTION:
+ *
+ * This function compares rtems_names. It protects the
+ * capture engine from a change to the way names are supported
+ * in RTEMS.
+ *
+ */
+static inline rtems_boolean
+rtems_capture_match_names (rtems_name lhs, rtems_name rhs)
+{
+ return lhs == rhs;
+}
+
+/*
+ * rtems_capture_dup_name
+ *
+ * DESCRIPTION:
+ *
+ * This function duplicates an rtems_names. It protects the
+ * cpature engine from a change to the way names are supported
+ * in RTEMS.
+ *
+ */
+static inline void
+rtems_capture_dup_name (rtems_name* dst, rtems_name src)
+{
+ *dst = src;
+}
+
+/*
+ * rtems_capture_name_in_group
+ *
+ * DESCRIPTION:
+ *
+ * This function sees if a name is in a group of names.
+ *
+ */
+static inline rtems_boolean
+rtems_capture_name_in_group (rtems_name task, rtems_name* tasks)
+{
+ if (tasks)
+ {
+ int i;
+ for (i = 0; i < RTEMS_CAPTURE_TRIGGER_TASKS; i++)
+ if (rtems_capture_match_names (task, *tasks++))
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * rtems_capture_match_name_id
+ *
+ * DESCRIPTION:
+ *
+ * This function matches a name and/or id.
+ */
+static inline rtems_boolean
+rtems_capture_match_name_id (rtems_name lhs_name,
+ rtems_id lhs_id,
+ rtems_name rhs_name,
+ rtems_id rhs_id)
+{
+ /*
+ * The left hand side name or id could be 0 which means a wildcard.
+ */
+ if ((lhs_name == 0) && (lhs_id == rhs_id))
+ return 1;
+ else if ((lhs_id == 0) || (lhs_id == rhs_id))
+ {
+ if (rtems_capture_match_names (lhs_name, rhs_name))
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * rtems_capture_init_stack_usage
+ *
+ * DESCRIPTION:
+ *
+ * This function setups a stack so its usage can be monitored.
+ */
+static inline void
+rtems_capture_init_stack_usage (rtems_capture_task_t* task)
+{
+ if (task->tcb)
+ {
+ uint32_t * s;
+ uint32_t i;
+
+ task->stack_size = task->tcb->Start.Initial_stack.size;
+ task->stack_clean = task->stack_size;
+
+ s = task->tcb->Start.Initial_stack.area;
+
+ for (i = 0; i < (task->stack_size - 128); i += 4)
+ *(s++) = 0xdeaddead;
+ }
+}
+
+/*
+ * rtems_capture_find_control
+ *
+ * DESCRIPTION:
+ *
+ * This function searches for a trigger given a name.
+ *
+ */
+static inline rtems_capture_control_t*
+rtems_capture_find_control (rtems_name name, rtems_id id)
+{
+ rtems_capture_control_t* control;
+
+ for (control = capture_controls; control != NULL; control = control->next)
+ if (rtems_capture_match_name_id (name, id, control->name, control->id))
+ break;
+ return control;
+}
+
+/*
+ * rtems_capture_create_control
+ *
+ * DESCRIPTION:
+ *
+ * This function creates a capture control for the capture engine.
+ *
+ */
+static inline rtems_capture_control_t*
+rtems_capture_create_control (rtems_name name, rtems_id id)
+{
+ rtems_interrupt_level level;
+ rtems_capture_control_t* control;
+ rtems_capture_task_t* task;
+
+ if ((name == 0) && (id == 0))
+ return NULL;
+
+ control = rtems_capture_find_control (name, id);
+
+ if (control == NULL)
+ {
+ control = _Workspace_Allocate (sizeof (rtems_capture_control_t));
+
+ if (control == NULL)
+ {
+ capture_flags |= RTEMS_CAPTURE_NO_MEMORY;
+ return NULL;
+ }
+
+ control->name = name;
+ control->id = id;
+ control->flags = 0;
+
+ memset (control->from, 0, sizeof (control->from));
+ memset (control->from_id, 0, sizeof (control->from_id));
+
+ rtems_interrupt_disable (level);
+
+ control->next = capture_controls;
+ capture_controls = control;
+
+ /*
+ * We need to scan the task list as set the control to the
+ * tasks.
+ */
+ for (task = capture_tasks; task != NULL; task = task->next)
+ if (rtems_capture_match_name_id (name, id, task->name, task->id))
+ task->control = control;
+
+ rtems_interrupt_enable (level);
+ }
+
+ return control;
+}
+
+/*
+ * rtems_capture_create_capture_task
+ *
+ * DESCRIPTION:
+ *
+ * This function create the task control.
+ *
+ */
+static inline rtems_capture_task_t*
+rtems_capture_create_capture_task (rtems_tcb* new_task)
+{
+ rtems_interrupt_level level;
+ rtems_capture_task_t* task;
+ rtems_capture_control_t* control;
+
+ task = _Workspace_Allocate (sizeof (rtems_capture_task_t));
+
+ if (task == NULL)
+ {
+ capture_flags |= RTEMS_CAPTURE_NO_MEMORY;
+ return NULL;
+ }
+
+ rtems_capture_dup_name (&task->name, ((rtems_name) new_task->Object.name));
+
+ task->id = new_task->Object.id;
+ task->flags = 0;
+ task->in = 0;
+ task->out = 0;
+ task->tcb = new_task;
+ task->ticks = 0;
+ task->tick_offset = 0;
+ task->ticks_in = 0;
+ task->tick_offset_in = 0;
+ task->control = 0;
+ task->last_ticks = 0;
+ task->last_tick_offset = 0;
+
+ task->tcb->extensions[capture_extension_index] = task;
+
+ task->start_priority = new_task->Start.initial_priority;
+ task->stack_size = new_task->Start.Initial_stack.size;
+ task->stack_clean = task->stack_size;
+
+ rtems_interrupt_disable (level);
+
+ task->next = capture_tasks;
+ capture_tasks = task;
+
+ rtems_interrupt_enable (level);
+
+ /*
+ * We need to scan the default control list to initialise
+ * this control.
+ */
+
+ for (control = capture_controls; control != NULL; control = control->next)
+ if (rtems_capture_match_name_id (control->name, control->id,
+ task->name, task->id))
+ task->control = control;
+
+ return task;
+}
+
+/*
+ * rtems_capture_record
+ *
+ * DESCRIPTION:
+ *
+ * This function records a capture record into the capture buffer.
+ *
+ */
+static inline void
+rtems_capture_record (rtems_capture_task_t* task,
+ uint32_t events)
+{
+ /*
+ * Check the watch state if we have a task control, and
+ * the task's real priority is lower or equal to the ceiling.
+ */
+ if (task)
+ {
+ rtems_capture_control_t* control;
+
+ control = task->control;
+
+ /*
+ * Capure the record if we have an event that is always
+ * captured, or the task's real priority is greater than the
+ * watch ceiling, and the global watch or task watch is enabled.
+ */
+
+ if ((events & RTEMS_CAPTURE_RECORD_EVENTS) ||
+ ((task->tcb->real_priority >= capture_ceiling) &&
+ (task->tcb->real_priority <= capture_floor) &&
+ ((capture_flags & RTEMS_CAPTURE_GLOBAL_WATCH) ||
+ (control && (control->flags & RTEMS_CAPTURE_WATCH)))))
+ {
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable (level);
+
+ if (capture_count < capture_size)
+ {
+ capture_count++;
+ capture_in->task = task;
+ capture_in->events = (events |
+ (task->tcb->real_priority) |
+ (task->tcb->current_priority << 8));
+
+ if ((events & RTEMS_CAPTURE_RECORD_EVENTS) == 0)
+ task->flags |= RTEMS_CAPTURE_TRACED;
+
+ rtems_capture_get_time (&capture_in->ticks, &capture_in->tick_offset);
+
+ if (capture_in == &capture_records[capture_size - 1])
+ capture_in = capture_records;
+ else
+ capture_in++;
+ }
+ else
+ capture_flags |= RTEMS_CAPTURE_OVERFLOW;
+ rtems_interrupt_enable (level);
+ }
+ }
+}
+
+/*
+ * rtems_capture_create_task
+ *
+ * DESCRIPTION:
+ *
+ * This function is called when a task is created.
+ *
+ */
+static rtems_boolean
+rtems_capture_create_task (rtems_tcb* current_task,
+ rtems_tcb* new_task)
+{
+ rtems_capture_task_t* ct;
+ rtems_capture_task_t* nt;
+
+ ct = current_task->extensions[capture_extension_index];
+
+ /*
+ * The task ponters may not be known as the task may have
+ * been created before the capture engine was open. Add them.
+ */
+
+ if (ct == NULL)
+ ct = rtems_capture_create_capture_task (current_task);
+
+ /*
+ * Create the new task's capture control block.
+ */
+ nt = rtems_capture_create_capture_task (new_task);
+
+ /*
+ * If we are logging then record this fact.
+ */
+ rtems_capture_record (ct, RTEMS_CAPTURE_CREATED_BY_EVENT);
+ rtems_capture_record (nt, RTEMS_CAPTURE_CREATED_EVENT);
+
+ return 1 == 1;
+}
+
+/*
+ * rtems_capture_start_task
+ *
+ * DESCRIPTION:
+ *
+ * This function is called when a task is started.
+ *
+ */
+static rtems_extension
+rtems_capture_start_task (rtems_tcb* current_task,
+ rtems_tcb* started_task)
+{
+ /*
+ * Get the capture task control block so we can trace this
+ * event.
+ */
+ rtems_capture_task_t* ct;
+ rtems_capture_task_t* st;
+
+ ct = current_task->extensions[capture_extension_index];
+ st = started_task->extensions[capture_extension_index];
+
+ /*
+ * The task ponters may not be known as the task may have
+ * been created before the capture engine was open. Add them.
+ */
+
+ if (ct == NULL)
+ ct = rtems_capture_create_capture_task (current_task);
+
+ if (st == NULL)
+ st = rtems_capture_create_capture_task (started_task);
+
+ rtems_capture_record (ct, RTEMS_CAPTURE_STARTED_BY_EVENT);
+ rtems_capture_record (st, RTEMS_CAPTURE_STARTED_EVENT);
+
+ rtems_capture_init_stack_usage (st);
+}
+
+/*
+ * rtems_capture_restart_task
+ *
+ * DESCRIPTION:
+ *
+ * This function is called when a task is restarted.
+ *
+ */
+static rtems_extension
+rtems_capture_restart_task (rtems_tcb* current_task,
+ rtems_tcb* restarted_task)
+{
+ /*
+ * Get the capture task control block so we can trace this
+ * event.
+ */
+ rtems_capture_task_t* ct;
+ rtems_capture_task_t* rt;
+
+ ct = current_task->extensions[capture_extension_index];
+ rt = restarted_task->extensions[capture_extension_index];
+
+ /*
+ * The task ponters may not be known as the task may have
+ * been created before the capture engine was open. Add them.
+ */
+
+ if (ct == NULL)
+ ct = rtems_capture_create_capture_task (current_task);
+
+ if (rt == NULL)
+ rt = rtems_capture_create_capture_task (restarted_task);
+
+ rtems_capture_record (ct, RTEMS_CAPTURE_RESTARTED_BY_EVENT);
+ rtems_capture_record (rt, RTEMS_CAPTURE_RESTARTED_EVENT);
+
+ rtems_capture_task_stack_usage (rt);
+ rtems_capture_init_stack_usage (rt);
+}
+
+/*
+ * rtems_capture_delete_task
+ *
+ * DESCRIPTION:
+ *
+ * This function is called when a task is deleted.
+ *
+ */
+static rtems_extension
+rtems_capture_delete_task (rtems_tcb* current_task,
+ rtems_tcb* deleted_task)
+{
+ /*
+ * Get the capture task control block so we can trace this
+ * event.
+ */
+ rtems_capture_task_t* ct;
+ rtems_capture_task_t* dt;
+
+ /*
+ * The task ponters may not be known as the task may have
+ * been created before the capture engine was open. Add them.
+ */
+
+ ct = current_task->extensions[capture_extension_index];
+ dt = deleted_task->extensions[capture_extension_index];
+
+ if (ct == NULL)
+ ct = rtems_capture_create_capture_task (current_task);
+
+ if (dt == NULL)
+ dt = rtems_capture_create_capture_task (deleted_task);
+
+ rtems_capture_record (ct, RTEMS_CAPTURE_DELETED_BY_EVENT);
+ rtems_capture_record (dt, RTEMS_CAPTURE_DELETED_EVENT);
+
+ rtems_capture_task_stack_usage (dt);
+
+ /*
+ * This task's tcb will be invalid.
+ */
+ dt->tcb = 0;
+}
+
+/*
+ * rtems_capture_begin_task
+ *
+ * DESCRIPTION:
+ *
+ * This function is called when a task is begun.
+ *
+ */
+static rtems_extension
+rtems_capture_begin_task (rtems_tcb* begin_task)
+{
+ /*
+ * Get the capture task control block so we can trace this
+ * event.
+ */
+ rtems_capture_task_t* bt;
+
+ bt = begin_task->extensions[capture_extension_index];
+
+ /*
+ * The task ponters may not be known as the task may have
+ * been created before the capture engine was open. Add them.
+ */
+
+ if (bt == NULL)
+ bt = rtems_capture_create_capture_task (begin_task);
+
+ rtems_capture_record (bt, RTEMS_CAPTURE_BEGIN_EVENT);
+}
+
+/*
+ * rtems_capture_exitted_task
+ *
+ * DESCRIPTION:
+ *
+ * This function is called when a task is exitted. That is
+ * returned rather than was deleted.
+ *
+ */
+static rtems_extension
+rtems_capture_exitted_task (rtems_tcb* exitted_task)
+{
+ /*
+ * Get the capture task control block so we can trace this
+ * event.
+ */
+ rtems_capture_task_t* et;
+
+ et = exitted_task->extensions[capture_extension_index];
+
+ /*
+ * The task ponters may not be known as the task may have
+ * been created before the capture engine was open. Add them.
+ */
+
+ if (et == NULL)
+ et = rtems_capture_create_capture_task (exitted_task);
+
+ rtems_capture_record (et, RTEMS_CAPTURE_EXITTED_EVENT);
+
+ rtems_capture_task_stack_usage (et);
+}
+
+/*
+ * rtems_capture_switch_task
+ *
+ * DESCRIPTION:
+ *
+ * This function is called when a context is switched.
+ *
+ */
+static rtems_extension
+rtems_capture_switch_task (rtems_tcb* current_task,
+ rtems_tcb* heir_task)
+{
+ /*
+ * Only perform context switch trace processing if tracing is
+ * enabled.
+ */
+ if (capture_flags & RTEMS_CAPTURE_ON)
+ {
+ uint32_t ticks;
+ uint32_t tick_offset;
+
+ /*
+ * Get the cpature task control block so we can update the
+ * reference anbd perform any watch or trigger functions.
+ * The task ponters may not be known as the task may have
+ * been created before the capture engine was open. Add them.
+ */
+ rtems_capture_task_t* ct;
+ rtems_capture_task_t* ht;
+
+ if (_States_Is_transient (current_task->current_state))
+ {
+ rtems_id ct_id = current_task->Object.id;
+
+ for (ct = capture_tasks; ct; ct = ct->next)
+ if (ct->id == ct_id)
+ break;
+ }
+ else
+ {
+ ct = current_task->extensions[capture_extension_index];
+
+ if (ct == NULL)
+ ct = rtems_capture_create_capture_task (current_task);
+ }
+
+ ht = heir_task->extensions[capture_extension_index];
+
+ if (ht == NULL)
+ ht = rtems_capture_create_capture_task (heir_task);
+
+ /*
+ * Update the execution time. Assume the tick will not overflow
+ * for now. This may need to change.
+ */
+ rtems_capture_get_time (&ticks, &tick_offset);
+
+ /*
+ * We could end up with null pointers for both the current task
+ * and the heir task.
+ */
+
+ if (ht)
+ {
+ ht->in++;
+ ht->ticks_in = ticks;
+ ht->tick_offset_in = tick_offset;
+ }
+
+ if (ct)
+ {
+ ct->out++;
+ ct->ticks += ticks - ct->ticks_in;
+
+ if (capture_timestamp)
+ {
+ tick_offset += capture_tick_period - ct->tick_offset_in;
+
+ if (tick_offset < capture_tick_period)
+ ct->tick_offset = tick_offset;
+ else
+ {
+ ct->ticks++;
+ ct->tick_offset = tick_offset - capture_tick_period;
+ }
+ }
+ else
+ {
+ ct->tick_offset += 100;
+ }
+ }
+
+ /*
+ * If we have not triggered then see if this is a trigger condition.
+ */
+ if (!(capture_flags & RTEMS_CAPTURE_TRIGGERED))
+ {
+ rtems_capture_control_t* cc = NULL;
+ rtems_capture_control_t* hc = NULL;
+
+ if (ct)
+ {
+ cc = ct->control;
+
+ /*
+ * Check the current task for a TO_ANY trigger.
+ */
+ if (cc && (cc->flags & RTEMS_CAPTURE_TO_ANY))
+ {
+ capture_flags |= RTEMS_CAPTURE_TRIGGERED;
+ goto triggered;
+ }
+ }
+
+ if (ht)
+ {
+ hc = ht->control;
+
+ /*
+ * Check the next task for a FROM_ANY.
+ */
+ if (hc && (hc->flags & RTEMS_CAPTURE_FROM_ANY))
+ {
+ capture_flags |= RTEMS_CAPTURE_TRIGGERED;
+ goto triggered;
+ }
+ }
+
+ /*
+ * Check is the trigger is from the current task
+ * to the next task.
+ */
+ if (cc && hc && (hc->flags & RTEMS_CAPTURE_FROM_TO))
+ if (rtems_capture_name_in_group (cc->name, hc->from))
+ {
+ capture_flags |= RTEMS_CAPTURE_TRIGGERED;
+ goto triggered;
+ }
+ }
+ else
+ {
+triggered:
+
+ rtems_capture_record (ct, RTEMS_CAPTURE_SWITCHED_OUT_EVENT);
+ rtems_capture_record (ht, RTEMS_CAPTURE_SWITCHED_IN_EVENT);
+ }
+ }
+}
+
+/*
+ * rtems_capture_open
+ *
+ * DESCRIPTION:
+ *
+ * This function initialises the realtime capture engine allocating the trace
+ * buffer. It is assumed we have a working heap at stage of initialisation.
+ *
+ */
+rtems_status_code
+rtems_capture_open (uint32_t size, rtems_capture_timestamp timestamp)
+{
+ rtems_extensions_table capture_extensions;
+ rtems_name name;
+ rtems_status_code sc;
+
+ /*
+ * See if the capture engine is already open.
+ */
+
+ if (capture_records)
+ return RTEMS_RESOURCE_IN_USE;
+
+ capture_records = malloc (size * sizeof (rtems_capture_record_t));
+
+ if (capture_records == NULL)
+ return RTEMS_NO_MEMORY;
+
+ capture_size = size;
+ capture_count = 0;
+ capture_in = capture_records;
+ capture_out = 0;
+ capture_flags = 0;
+ capture_tasks = NULL;
+ capture_ceiling = 0;
+ capture_floor = 255;
+
+ /*
+ * Create the extension table. This is copied so we
+ * can create it as a local.
+ */
+ capture_extensions.thread_create = rtems_capture_create_task;
+ capture_extensions.thread_start = rtems_capture_start_task;
+ capture_extensions.thread_restart = rtems_capture_restart_task;
+ capture_extensions.thread_delete = rtems_capture_delete_task;
+ capture_extensions.thread_switch = rtems_capture_switch_task;
+ capture_extensions.thread_begin = rtems_capture_begin_task;
+ capture_extensions.thread_exitted = rtems_capture_exitted_task;
+ capture_extensions.fatal = NULL;
+
+ /*
+ * Get the tick period from the BSP Configuration Table.
+ */
+ capture_tick_period = _Configuration_Table->microseconds_per_tick;
+
+ /*
+ * Register the user extension handlers for the CAPture Engine.
+ */
+ name = rtems_build_name ('C', 'A', 'P', 'E');
+ sc = rtems_extension_create (name, &capture_extensions, &capture_id);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ {
+ capture_id = 0;
+ free (capture_records);
+ capture_records = NULL;
+ }
+ else
+ {
+ capture_extension_index = rtems_get_index (capture_id);;
+ }
+
+ /*
+ * Iterate over the list of existing tasks.
+ */
+
+ return sc;
+}
+
+/*
+ * rtems_capture_close
+ *
+ * DESCRIPTION:
+ *
+ * This function shutdowns the capture engine and release any claimed
+ * resources.
+ */
+rtems_status_code
+rtems_capture_close ()
+{
+ rtems_interrupt_level level;
+ rtems_capture_task_t* task;
+ rtems_capture_control_t* control;
+ rtems_capture_record_t* records;
+ rtems_status_code sc;
+
+ rtems_interrupt_disable (level);
+
+ if (!capture_records)
+ {
+ rtems_interrupt_enable (level);
+ return RTEMS_SUCCESSFUL;
+ }
+
+ capture_flags &= ~RTEMS_CAPTURE_ON;
+
+ records = capture_records;
+ capture_records = NULL;
+
+ rtems_interrupt_enable (level);
+
+ /*
+ * Delete the extension first. This means we are now able to
+ * release the resources we have without them being used.
+ */
+
+ sc = rtems_extension_delete (capture_id);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ return sc;
+
+ task = capture_tasks;
+
+ while (task)
+ {
+ rtems_capture_task_t* delete = task;
+ task = task->next;
+ _Workspace_Free (delete);
+ }
+
+ capture_tasks = NULL;
+
+ control = capture_controls;
+
+ while (control)
+ {
+ rtems_capture_control_t* delete = control;
+ control = control->next;
+ _Workspace_Free (delete);
+ }
+
+ capture_controls = NULL;
+
+ if (capture_records)
+ {
+ free (capture_records);
+ capture_records = NULL;
+ }
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_capture_control
+ *
+ * DESCRIPTION:
+ *
+ * This function allows control of tracing at a global level.
+ */
+rtems_status_code
+rtems_capture_control (rtems_boolean enable)
+{
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable (level);
+
+ if (!capture_records)
+ {
+ rtems_interrupt_enable (level);
+ return RTEMS_UNSATISFIED;
+ }
+
+ if (enable)
+ capture_flags |= RTEMS_CAPTURE_ON;
+ else
+ capture_flags &= ~RTEMS_CAPTURE_ON;
+
+ rtems_interrupt_enable (level);
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_capture_flush
+ *
+ * DESCRIPTION:
+ *
+ * This function flushes the capture buffer. The prime parameter allows the
+ * capture engine to also be primed again.
+ */
+rtems_status_code
+rtems_capture_flush (rtems_boolean prime)
+{
+ rtems_interrupt_level level;
+ rtems_capture_task_t* task;
+
+ rtems_interrupt_disable (level);
+
+ for (task = capture_tasks; task != NULL; task = task->next)
+ task->flags &= ~RTEMS_CAPTURE_TRACED;
+
+ if (prime)
+ capture_flags &= ~(RTEMS_CAPTURE_TRIGGERED | RTEMS_CAPTURE_OVERFLOW);
+ else
+ capture_flags &= ~RTEMS_CAPTURE_OVERFLOW;
+
+ capture_in = capture_records;
+ capture_out = 0;
+
+ rtems_interrupt_enable (level);
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_capture_watch_add
+ *
+ * DESCRIPTION:
+ *
+ * This function defines a watch for a specific task given a name. A watch
+ * causes it to be traced either in or out of context. The watch can be
+ * optionally enabled or disabled with the set routine. It is disabled by
+ * default.
+ */
+rtems_status_code
+rtems_capture_watch_add (rtems_name name, rtems_id id)
+{
+ rtems_capture_control_t* control;
+
+ if ((name == 0) && (id == 0))
+ return RTEMS_UNSATISFIED;
+
+ control = rtems_capture_find_control (name, id);
+
+ if (control && !id)
+ return RTEMS_TOO_MANY;
+
+ if (!control)
+ control = rtems_capture_create_control (name, id);
+
+ if (!control)
+ return RTEMS_NO_MEMORY;
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_capture_watch_del
+ *
+ * DESCRIPTION:
+ *
+ * This function removes a watch for a specific task given a name. The task
+ * description will still exist if referenced by a trace record in the trace
+ * buffer or a global watch is defined.
+ */
+rtems_status_code
+rtems_capture_watch_del (rtems_name name, rtems_id id)
+{
+ rtems_interrupt_level level;
+ rtems_capture_control_t* control;
+ rtems_capture_control_t** prev_control;
+ rtems_capture_task_t* task;
+ rtems_boolean found = 0;
+
+ /*
+ * Should this test be for wildcards ?
+ */
+
+ for (prev_control = &capture_controls, control = capture_controls;
+ control != NULL; )
+ {
+ if (rtems_capture_match_name_id (name, id, control->name, control->id))
+ {
+ rtems_interrupt_disable (level);
+
+ for (task = capture_tasks; task != NULL; task = task->next)
+ if (task->control == control)
+ task->control = 0;
+
+ *prev_control = control->next;
+
+ rtems_interrupt_enable (level);
+
+ _Workspace_Free (control);
+
+ control = *prev_control;
+
+ found = 1;
+ }
+ else
+ {
+ prev_control = &control->next;
+ control = control->next;
+ }
+ }
+
+ if (found)
+ return RTEMS_SUCCESSFUL;
+
+ return RTEMS_INVALID_NAME;
+}
+
+/*
+ * rtems_capture_watch_set
+ *
+ * DESCRIPTION:
+ *
+ * This function allows control of a watch. The watch can be enabled or
+ * disabled.
+ */
+rtems_status_code
+rtems_capture_watch_ctrl (rtems_name name, rtems_id id, rtems_boolean enable)
+{
+ rtems_interrupt_level level;
+ rtems_capture_control_t* control;
+ rtems_boolean found = 0;
+
+ /*
+ * Find the control and then set the watch. It must exist before it can
+ * be controlled.
+ */
+ for (control = capture_controls; control != NULL; control = control->next)
+ {
+ if (rtems_capture_match_name_id (name, id, control->name, control->id))
+ {
+ rtems_interrupt_disable (level);
+
+ if (enable)
+ control->flags |= RTEMS_CAPTURE_WATCH;
+ else
+ control->flags &= ~RTEMS_CAPTURE_WATCH;
+
+ rtems_interrupt_enable (level);
+
+ found = 1;
+ }
+ }
+
+ if (found)
+ return RTEMS_SUCCESSFUL;
+
+ return RTEMS_INVALID_NAME;
+}
+
+/*
+ * rtems_capture_watch_global
+ *
+ * DESCRIPTION:
+ *
+ * This function allows control of a global watch. The watch can be enabled or
+ * disabled. A global watch configures all tasks below the ceiling and above
+ * the floor to be traced.
+ */
+rtems_status_code
+rtems_capture_watch_global (rtems_boolean enable)
+{
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable (level);
+
+ /*
+ * We need to keep specific and global watches separate so
+ * a global enable/disable does not lose a specific watch.
+ */
+ if (enable)
+ capture_flags |= RTEMS_CAPTURE_GLOBAL_WATCH;
+ else
+ capture_flags &= ~RTEMS_CAPTURE_GLOBAL_WATCH;
+
+ rtems_interrupt_enable (level);
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_capture_watch_global_on
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the global watch state.
+ */
+rtems_boolean
+rtems_capture_watch_global_on ()
+{
+ return capture_flags & RTEMS_CAPTURE_GLOBAL_WATCH ? 1 : 0;
+}
+
+/*
+ * rtems_capture_watch_ceiling
+ *
+ * DESCRIPTION:
+ *
+ * This function sets a watch ceiling. Tasks at or greating that the
+ * ceiling priority are not watched. This is a simple way to monitor
+ * an application and exclude system tasks running at a higher
+ * priority level.
+ */
+rtems_status_code
+rtems_capture_watch_ceiling (rtems_task_priority ceiling)
+{
+ capture_ceiling = ceiling;
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_capture_watch_get_ceiling
+ *
+ * DESCRIPTION:
+ *
+ * This function gets the watch ceiling.
+ */
+rtems_task_priority
+rtems_capture_watch_get_ceiling ()
+{
+ return capture_ceiling;
+}
+
+/*
+ * rtems_capture_watch_floor
+ *
+ * DESCRIPTION:
+ *
+ * This function sets a watch floor. Tasks at or less that the
+ * floor priority are not watched. This is a simple way to monitor
+ * an application and exclude system tasks running at a lower
+ * priority level.
+ */
+rtems_status_code
+rtems_capture_watch_floor (rtems_task_priority floor)
+{
+ capture_floor = floor;
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_capture_watch_get_floor
+ *
+ * DESCRIPTION:
+ *
+ * This function gets the watch floor.
+ */
+rtems_task_priority
+rtems_capture_watch_get_floor ()
+{
+ return capture_floor;
+}
+
+/*
+ * rtems_capture_set_trigger
+ *
+ * DESCRIPTION:
+ *
+ * This function sets an edge trigger. Left is the left side of
+ * the edge and right is right side of the edge. The trigger type
+ * can be -
+ *
+ * FROM_ANY : a switch from any task to the right side of the edge.
+ * TO_ANY : a switch from the left side of the edge to any task.
+ * FROM_TO : a switch from the left side of the edge to the right
+ * side of the edge.
+ *
+ * This set trigger routine will create a capture control for the
+ * target task. The task list is searched and any existing tasks
+ * are linked to the new control.
+ *
+ * We can have a number of tasks that have the same name so we
+ * search using names. This means a number of tasks can be
+ * linked to single control.
+ */
+rtems_status_code
+rtems_capture_set_trigger (rtems_name from,
+ rtems_id from_id,
+ rtems_name to,
+ rtems_id to_id,
+ rtems_capture_trigger_t trigger)
+{
+ rtems_capture_control_t* control;
+ int i;
+
+ /*
+ * Find the capture control blocks for the from and to
+ * tasks.
+ */
+ if (trigger == rtems_capture_to_any)
+ {
+ control = rtems_capture_create_control (from, from_id);
+ if (control == NULL)
+ return RTEMS_NO_MEMORY;
+ control->flags |= RTEMS_CAPTURE_TO_ANY;
+ }
+
+ if ((trigger == rtems_capture_from_to) ||
+ (trigger == rtems_capture_from_any))
+ {
+ control = rtems_capture_create_control (to, to_id);
+ if (control == NULL)
+ return RTEMS_NO_MEMORY;
+
+ if (trigger == rtems_capture_from_any)
+ control->flags |= RTEMS_CAPTURE_FROM_ANY;
+ else
+ {
+ control->flags |= RTEMS_CAPTURE_FROM_TO;
+ for (i = 0; i < RTEMS_CAPTURE_TRIGGER_TASKS; i++)
+ {
+ if (control->from[i] == 0)
+ {
+ control->from[i] = from;
+ control->from_id[i] = from_id;
+ break;
+ }
+ }
+ }
+ }
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_capture_read
+ *
+ * DESCRIPTION:
+ *
+ * This function reads a number of records from the capture buffer.
+ * The user can optionally block and wait until the buffer as a
+ * specific number of records available or a specific time has
+ * elasped.
+ *
+ * The function returns the number of record that is has that are
+ * in a continous block of memory. If the number of available records
+ * wrap then only those records are provided. This removes the need for
+ * caller to be concerned about buffer wrappings. If the number of
+ * requested records cannot be met due to the wrapping of the records
+ * less than the specified number will be returned.
+ *
+ * The user must release the records. This is achieved with a call to
+ * rtems_capture_release. Calls this function without a release will
+ * result in at least the same number of records being released.
+ *
+ * The 'threshold' parameter is the number of records that must be
+ * captured before returning. If a timeout period is specified (non-0)
+ * any captured records will be returned. These parameters stop
+ * thrashing occuring for a small number of records, yet allows
+ * a user configured latiency to be applied for single events.
+ *
+ * The 'timeout' parameter is in micro-seconds. A value of 0 will disable
+ * the timeout.
+ *
+ */
+rtems_status_code
+rtems_capture_read (uint32_t threshold,
+ uint32_t timeout,
+ uint32_t * read,
+ rtems_capture_record_t** recs)
+{
+ rtems_interrupt_level level;
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ uint32_t count;
+
+ *read = 0;
+ *recs = NULL;
+
+ rtems_interrupt_disable (level);
+
+ /*
+ * Only one reader is allowed.
+ */
+
+ if (capture_flags & RTEMS_CAPTURE_READER_ACTIVE)
+ {
+ rtems_interrupt_enable (level);
+ return RTEMS_RESOURCE_IN_USE;
+ }
+
+ capture_flags |= RTEMS_CAPTURE_READER_ACTIVE;
+ *read = count = capture_count;
+
+ rtems_interrupt_enable (level);
+
+ *recs = &capture_records[capture_out];
+
+ for (;;)
+ {
+ /*
+ * See if the count wraps the end of the record buffer.
+ */
+ if (count && ((capture_out + count) >= capture_size))
+ *read = capture_size - capture_out;
+
+ /*
+ * Do we have a threshold and the current count has not wrapped
+ * around the end of the capture record buffer ?
+ */
+ if ((*read == count) && threshold)
+ {
+ /*
+ * Do we have enough records ?
+ */
+ if (*read < threshold)
+ {
+ rtems_event_set event_out;
+
+ rtems_task_ident (RTEMS_SELF, RTEMS_LOCAL, &capture_reader);
+
+ rtems_interrupt_disable (level);
+
+ capture_flags |= RTEMS_CAPTURE_READER_WAITING;
+
+ rtems_interrupt_enable (level);
+
+ sc = rtems_event_receive (RTEMS_EVENT_0,
+ RTEMS_WAIT | RTEMS_EVENT_ANY,
+ TOD_MICROSECONDS_TO_TICKS (timeout),
+ &event_out);
+
+ /*
+ * Let the user handle all other sorts of errors. This may
+ * not be the best solution, but oh well, it will do for
+ * now.
+ */
+ if ((sc != RTEMS_SUCCESSFUL) && (sc != RTEMS_TIMEOUT))
+ break;
+
+ rtems_interrupt_disable (level);
+
+ *read = count = capture_count;
+
+ rtems_interrupt_enable (level);
+
+ continue;
+ }
+ }
+
+ /*
+ * Always out if we reach here. To loop use continue.
+ */
+ break;
+ }
+
+ rtems_interrupt_disable (level);
+
+ capture_flags &= ~RTEMS_CAPTURE_READER_ACTIVE;
+
+ rtems_interrupt_enable (level);
+
+ return sc;
+}
+
+/*
+ * rtems_capture_release
+ *
+ * DESCRIPTION:
+ *
+ * This function releases the requested number of record slots back
+ * to the capture engine. The count must match the number read.
+ */
+rtems_status_code
+rtems_capture_release (uint32_t count)
+{
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable (level);
+
+ if (count > capture_count)
+ count = capture_count;
+
+ capture_count -= count;
+
+ capture_out = (capture_count + count) % capture_size;
+
+ rtems_interrupt_enable (level);
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * rtems_capture_tick_time
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the tick period in nano-seconds.
+ */
+uint32_t
+rtems_capture_tick_time ()
+{
+ return capture_tick_period;
+}
+
+/*
+ * rtems_capture_event_text
+ *
+ * DESCRIPTION:
+ *
+ * This function returns a string for an event based on the bit in the
+ * event. The functions takes the bit offset as a number not the bit
+ * set in a bit map.
+ */
+const char*
+rtems_capture_event_text (int event)
+{
+ if ((event < RTEMS_CAPTURE_EVENT_START) || (event > RTEMS_CAPTURE_EVENT_END))
+ return "invalid event id";
+ return capture_event_text[event - RTEMS_CAPTURE_EVENT_START];
+}
+
+/*
+ * rtems_capture_get_task_list
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the head of the list of tasks that the
+ * capture engine has detected.
+ */
+rtems_capture_task_t*
+rtems_capture_get_task_list ()
+{
+ return capture_tasks;
+}
+
+/*
+ * rtems_capture_task_stack_usage
+ *
+ * DESCRIPTION:
+ *
+ * This function updates the stack usage. The task control block
+ * is updated.
+ */
+uint32_t
+rtems_capture_task_stack_usage (rtems_capture_task_t* task)
+{
+ if (task->tcb)
+ {
+ uint32_t * st;
+ uint32_t * s;
+
+ /*
+ * @todo: Assumes all stacks move the same way.
+ */
+ st = task->tcb->Start.Initial_stack.area + task->stack_size;
+ s = task->tcb->Start.Initial_stack.area;
+
+ while (s < st)
+ {
+ if (*s != 0xdeaddead)
+ break;
+ s++;
+ }
+
+ task->stack_clean =
+ s - (uint32_t *) task->tcb->Start.Initial_stack.area;
+ }
+
+ return task->stack_clean;
+}
+
+/*
+ * rtems_capture_get_control_list
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the head of the list of control in the
+ * capture engine.
+ */
+rtems_capture_control_t*
+rtems_capture_get_control_list ()
+{
+ return capture_controls;
+}
diff --git a/cpukit/libmisc/capture/capture.h b/cpukit/libmisc/capture/capture.h
new file mode 100644
index 0000000000..6e040efa0e
--- /dev/null
+++ b/cpukit/libmisc/capture/capture.h
@@ -0,0 +1,869 @@
+/*
+ ------------------------------------------------------------------------
+ $Id$
+ ------------------------------------------------------------------------
+
+ Copyright Objective Design Systems Pty Ltd, 2002
+ All rights reserved Objective Design Systems Pty Ltd, 2002
+ Chris Johns (ccj@acm.org)
+
+ COPYRIGHT (c) 1989-1998.
+ On-Line Applications Research Corporation (OAR).
+
+ The license and distribution terms for this file may be
+ found in the file LICENSE in this distribution.
+
+ This software with is provided ``as is'' and with NO WARRANTY.
+
+ ------------------------------------------------------------------------
+
+ RTEMS Performance Monitoring and Measurement Framework.
+
+ This is the Capture Engine component.
+
+*/
+
+#ifndef __CAPTURE_H_
+#define __CAPTURE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems.h>
+
+/*
+ * The number of tasks in a trigger group.
+ */
+#define RTEMS_CAPTURE_TRIGGER_TASKS (32)
+
+/*
+ * rtems_capture_control_t
+ *
+ * DESCRIPTION:
+ *
+ * RTEMS control holds the trigger and watch configuration for a group of
+ * tasks with the same name.
+ */
+typedef struct rtems_capture_control_s
+{
+ rtems_name name;
+ rtems_id id;
+ uint32_t flags;
+ rtems_name from[RTEMS_CAPTURE_TRIGGER_TASKS];
+ rtems_id from_id[RTEMS_CAPTURE_TRIGGER_TASKS];
+ struct rtems_capture_control_s* next;
+} rtems_capture_control_t;
+
+/*
+ * Control flags.
+ */
+#define RTEMS_CAPTURE_WATCH (1 << 0)
+#define RTEMS_CAPTURE_FROM_ANY (1 << 1)
+#define RTEMS_CAPTURE_TO_ANY (1 << 2)
+#define RTEMS_CAPTURE_FROM_TO (1 << 3)
+
+/*
+ * rtems_capture_control_t
+ *
+ * DESCRIPTION:
+ *
+ * RTEMS capture control provdes the information about a task, along
+ * with its trigger state. The control is referenced by each
+ * capture record. This is* information neeed by the decoder. The
+ * capture record cannot assume the task will exist when the record is
+ * dumped via the target interface so task info needed for tracing is
+ * copied and held here.
+ *
+ * The inline heper functions provide more details about the info
+ * contained in this structure.
+ *
+ * Note, the tracer code exploits the fact an rtems_name is a
+ * 32bit value.
+ */
+typedef struct rtems_capture_task_s
+{
+ rtems_name name;
+ rtems_id id;
+ uint32_t flags;
+ rtems_tcb* tcb;
+ uint32_t in;
+ uint32_t out;
+ rtems_task_priority start_priority;
+ uint32_t stack_size;
+ uint32_t stack_clean;
+ uint32_t ticks;
+ uint32_t tick_offset;
+ uint32_t ticks_in;
+ uint32_t tick_offset_in;
+ uint32_t last_ticks;
+ uint32_t last_tick_offset;
+ rtems_capture_control_t* control;
+ struct rtems_capture_task_s* next;
+} rtems_capture_task_t;
+
+/*
+ * Task flags.
+ */
+#define RTEMS_CAPTURE_TRACED (1 << 0)
+
+/*
+ * rtems_capture_record_t
+ *
+ * DESCRIPTION:
+ *
+ * RTEMS capture record. This is a record that is written into
+ * the buffer. The events includes the priority of the task
+ * at the time of the context switch.
+ */
+typedef struct rtems_capture_record_s
+{
+ rtems_capture_task_t* task;
+ uint32_t events;
+ uint32_t ticks;
+ uint32_t tick_offset;
+} rtems_capture_record_t;
+
+/*
+ * The capture record event flags.
+ */
+#define RTEMS_CAPTURE_REAL_PRI_EVENT_MASK (0x000000ff)
+#define RTEMS_CAPTURE_CURR_PRI_EVENT_MASK (0x0000ff00)
+#define RTEMS_CAPTURE_REAL_PRIORITY_EVENT (0)
+#define RTEMS_CAPTURE_CURR_PRIORITY_EVENT (8)
+#define RTEMS_CAPTURE_EVENT_START (16)
+#define RTEMS_CAPTURE_CREATED_BY_EVENT (1 << 16)
+#define RTEMS_CAPTURE_CREATED_EVENT (1 << 17)
+#define RTEMS_CAPTURE_STARTED_BY_EVENT (1 << 18)
+#define RTEMS_CAPTURE_STARTED_EVENT (1 << 19)
+#define RTEMS_CAPTURE_RESTARTED_BY_EVENT (1 << 20)
+#define RTEMS_CAPTURE_RESTARTED_EVENT (1 << 21)
+#define RTEMS_CAPTURE_DELETED_BY_EVENT (1 << 22)
+#define RTEMS_CAPTURE_DELETED_EVENT (1 << 23)
+#define RTEMS_CAPTURE_BEGIN_EVENT (1 << 24)
+#define RTEMS_CAPTURE_EXITTED_EVENT (1 << 25)
+#define RTEMS_CAPTURE_SWITCHED_OUT_EVENT (1 << 26)
+#define RTEMS_CAPTURE_SWITCHED_IN_EVENT (1 << 27)
+#define RTEMS_CAPTURE_TIMESTAMP (1 << 28)
+#define RTEMS_CAPTURE_EVENT_END (28)
+
+/*
+ * rtems_capture_trigger_t
+ *
+ * DESCRIPTION:
+ *
+ * The types of triggers that exist. FIXME: add more here.
+ */
+typedef enum rtems_capture_trigger_t
+{
+ rtems_capture_to_any,
+ rtems_capture_from_any,
+ rtems_capture_from_to
+} rtems_capture_trigger_t;
+
+/*
+ * rtems_capture_timestamp
+ *
+ * DESCRIPTION:
+ *
+ * This defines the callout handler to obtain a time stamp. The
+ * value returned is time count since the last read.
+ *
+ */
+
+typedef void (*rtems_capture_timestamp)
+ (uint32_t * ticks, uint32_t * micro);
+
+/*
+ * rtems_capture_open
+ *
+ * DESCRIPTION:
+ *
+ * This function initialises the realtime trace manager allocating the capture
+ * buffer. It is assumed we have a working heap at stage of initialisation.
+ *
+ */
+rtems_status_code
+rtems_capture_open (uint32_t size,
+ rtems_capture_timestamp timestamp);
+
+/*
+ * rtems_capture_close
+ *
+ * DESCRIPTION:
+ *
+ * This function shutdowns the tracer and release any claimed
+ * resources.
+ */
+rtems_status_code
+rtems_capture_close ();
+
+/*
+ * rtems_capture_control
+ *
+ * DESCRIPTION:
+ *
+ * This function allows control of tracing at a global level.
+ */
+rtems_status_code
+rtems_capture_control (rtems_boolean enable);
+
+/*
+ * rtems_capture_flush
+ *
+ * DESCRIPTION:
+ *
+ * This function flushes the trace buffer. The prime parameter allows the
+ * capture engine to also be primed again.
+ */
+rtems_status_code
+rtems_capture_flush (rtems_boolean prime);
+
+/*
+ * rtems_capture_watch_add
+ *
+ * DESCRIPTION:
+ *
+ * This function defines a watch for a specific task given a name. A watch
+ * causes it to be traced either in or out of context. The watch can be
+ * optionally enabled or disabled with the set routine. It is disabled by
+ * default.
+ */
+rtems_status_code
+rtems_capture_watch_add (rtems_name name, rtems_id id);
+
+/*
+ * rtems_capture_watch_del
+ *
+ * DESCRIPTION:
+ *
+ * This function removes a watch for a specific task given a name. The task
+ * description will still exist if referenced by a trace record in the trace
+ * buffer or a global watch is defined.
+ */
+rtems_status_code
+rtems_capture_watch_del (rtems_name name, rtems_id id);
+
+/*
+ * rtems_capture_watch_set
+ *
+ * DESCRIPTION:
+ *
+ * This function allows control of a watch. The watch can be enabled or
+ * disabled.
+ */
+rtems_status_code
+rtems_capture_watch_ctrl (rtems_name name, rtems_id id, rtems_boolean enable);
+
+/*
+ * rtems_capture_watch_global
+ *
+ * DESCRIPTION:
+ *
+ * This function allows control of a global watch. The watch can be enabled or
+ * disabled. A global watch configures all tasks below the ceiling and above
+ * the floor to be traced.
+ */
+rtems_status_code
+rtems_capture_watch_global (rtems_boolean enable);
+
+/*
+ * rtems_capture_watch_global_on
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the global watch state.
+ */
+rtems_boolean
+rtems_capture_watch_global_on ();
+
+/*
+ * rtems_capture_watch_ceiling
+ *
+ * DESCRIPTION:
+ *
+ * This function sets a watch ceiling. Tasks at or greating that the
+ * ceiling priority are not watched. This is a simple way to monitor
+ * an application and exclude system tasks running at a higher
+ * priority level.
+ */
+rtems_status_code
+rtems_capture_watch_ceiling (rtems_task_priority ceiling);
+
+/*
+ * rtems_capture_watch_get_ceiling
+ *
+ * DESCRIPTION:
+ *
+ * This function gets the watch ceiling.
+ */
+rtems_task_priority
+rtems_capture_watch_get_ceiling ();
+
+/*
+ * rtems_capture_watch_floor
+ *
+ * DESCRIPTION:
+ *
+ * This function sets a watch floor. Tasks at or less that the
+ * floor priority are not watched. This is a simple way to monitor
+ * an application and exclude system tasks running at a lower
+ * priority level.
+ */
+rtems_status_code
+rtems_capture_watch_floor (rtems_task_priority floor);
+
+/*
+ * rtems_capture_watch_get_floor
+ *
+ * DESCRIPTION:
+ *
+ * This function gets the watch floor.
+ */
+rtems_task_priority
+rtems_capture_watch_get_floor ();
+
+/*
+ * rtems_capture_set_trigger
+ *
+ * DESCRIPTION:
+ *
+ * This function sets an edge trigger. Left is the left side of
+ * the edge and right is right side of the edge. The trigger type
+ * can be -
+ *
+ * FROM_ANY : a switch from any task to the right side of the edge.
+ * TO_ANY : a switch from the left side of the edge to any task.
+ * FROM_TO : a switch from the left side of the edge to the right
+ * side of the edge.
+ *
+ * This set trigger routine will create a trace control for the
+ * target task. The task list is searched and any existing tasks
+ * are linked to the new control.
+ *
+ * We can have a number of tasks that have the same name so we
+ * search using names. This means a number of tasks can be
+ * linked to single control.
+ */
+rtems_status_code
+rtems_capture_set_trigger (rtems_name from,
+ rtems_id from_id,
+ rtems_name to,
+ rtems_id to_id,
+ rtems_capture_trigger_t trigger);
+
+/*
+ * rtems_capture_read
+ *
+ * DESCRIPTION:
+ *
+ * This function reads a number of records from the capture buffer.
+ * The user can optionally block and wait until the buffer as a
+ * specific number of records available or a specific time has
+ * elasped.
+ *
+ * The function returns the number of record that is has that are
+ * in a continous block of memory. If the number of available records
+ * wrap then only those records are provided. This removes the need for
+ * caller to be concerned about buffer wrappings. If the number of
+ * requested records cannot be met due to the wrapping of the records
+ * less than the specified number will be returned.
+ *
+ * The user must release the records. This is achieved with a call to
+ * rtems_capture_release. Calls this function without a release will
+ * result in at least the same number of records being released.
+ *
+ * The 'threshold' parameter is the number of records that must be
+ * captured before returning. If a timeout period is specified (non-0)
+ * any captured records will be returned. These parameters stop
+ * thrashing occuring for a small number of records, yet allows
+ * a user configured latiency to be applied for single events.
+ *
+ * The 'timeout' parameter is in micro-seconds. A value of 0 will disable
+ * the timeout.
+ *
+ */
+rtems_status_code
+rtems_capture_read (uint32_t threshold,
+ uint32_t timeout,
+ uint32_t * read,
+ rtems_capture_record_t** recs);
+
+/*
+ * rtems_capture_release
+ *
+ * DESCRIPTION:
+ *
+ * This function releases the requested number of record slots back
+ * to the capture engine. The count must match the number read.
+ */
+rtems_status_code
+rtems_capture_release (uint32_t count);
+
+/*
+ * rtems_capture_tick_time
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the tick period in micro-seconds.
+ */
+uint32_t
+rtems_capture_tick_time ();
+
+/*
+ * rtems_capture_tick_time
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the tick period in micro-seconds.
+ */
+uint32_t
+rtems_capture_tick_time ();
+
+/*
+ * rtems_capture_event_text
+ *
+ * DESCRIPTION:
+ *
+ * This function returns a string for an event based on the bit in the
+ * event. The functions takes the bit offset as a number not the bit
+ * set in a bit map.
+ */
+const char*
+rtems_capture_event_text (int event);
+
+/*
+ * rtems_capture_get_task_list
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the head of the list of tasks that the
+ * capture engine has detected.
+ */
+rtems_capture_task_t*
+rtems_capture_get_task_list ();
+
+/*
+ * rtems_capture_next_task
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the pointer to the next task in the list. The
+ * pointer NULL terminates the list.
+ */
+static inline rtems_capture_task_t*
+rtems_capture_next_task (rtems_capture_task_t* task)
+{
+ return task->next;
+}
+
+/*
+ * rtems_capture_task_valid
+ *
+ * DESCRIPTION:
+ *
+ * This function returns true if the task control block points to
+ * a valid task.
+ */
+static inline rtems_boolean
+rtems_capture_task_valid (rtems_capture_task_t* task)
+{
+ return task->tcb != NULL;
+}
+
+/*
+ * rtems_capture_task_id
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the task id.
+ */
+static inline rtems_id
+rtems_capture_task_id (rtems_capture_task_t* task)
+{
+ return task->id;
+}
+
+/*
+ * rtems_capture_task_state
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the task state.
+ */
+static inline States_Control
+rtems_capture_task_state (rtems_capture_task_t* task)
+{
+ if (rtems_capture_task_valid (task))
+ return task->tcb->current_state;
+ return 0;
+}
+
+/*
+ * rtems_capture_task_name
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the task name.
+ */
+static inline rtems_name
+rtems_capture_task_name (rtems_capture_task_t* task)
+{
+ return task->name;
+}
+
+/*
+ * rtems_capture_task_flags
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the task flags.
+ */
+static inline uint32_t
+rtems_capture_task_flags (rtems_capture_task_t* task)
+{
+ return task->flags;
+}
+
+/*
+ * rtems_capture_task_control
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the task control if present.
+ */
+static inline rtems_capture_control_t*
+rtems_capture_task_control (rtems_capture_task_t* task)
+{
+ return task->control;
+}
+
+/*
+ * rtems_capture_task_control_flags
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the task control flags if a control is present.
+ */
+static inline uint32_t
+rtems_capture_task_control_flags (rtems_capture_task_t* task)
+{
+ if (!task->control)
+ return 0;
+ return task->control->flags;
+}
+
+/*
+ * rtems_capture_task_switched_in
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the number of times the task has
+ * been switched into context.
+ */
+static inline uint32_t
+rtems_capture_task_switched_in (rtems_capture_task_t* task)
+{
+ return task->in;
+}
+
+/*
+ * rtems_capture_task_switched_out
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the number of times the task has
+ * been switched out of context.
+ */
+static inline uint32_t
+rtems_capture_task_switched_out (rtems_capture_task_t* task)
+{
+ return task->out;
+}
+
+/*
+ * rtems_capture_task_curr_priority
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the tasks start priority. The tracer needs this
+ * to track where the task's priority goes.
+ */
+static inline rtems_task_priority
+rtems_capture_task_start_priority (rtems_capture_task_t* task)
+{
+ return task->start_priority;
+}
+
+/*
+ * rtems_capture_task_real_priority
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the tasks real priority.
+ */
+static inline rtems_task_priority
+rtems_capture_task_real_priority (rtems_capture_task_t* task)
+{
+ if (rtems_capture_task_valid (task))
+ return task->tcb->real_priority;
+ return 0;
+}
+
+/*
+ * rtems_capture_task_curr_priority
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the tasks current priority.
+ */
+static inline rtems_task_priority
+rtems_capture_task_curr_priority (rtems_capture_task_t* task)
+{
+ if (rtems_capture_task_valid (task))
+ return task->tcb->current_priority;
+ return 0;
+}
+
+/*
+ * rtems_capture_task_stack_usage
+ *
+ * DESCRIPTION:
+ *
+ * This function updates the stack usage. The task control block
+ * is updated.
+ */
+uint32_t
+rtems_capture_task_stack_usage (rtems_capture_task_t* task);
+
+/*
+ * rtems_capture_task_stack_size
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the task's stack size.
+ */
+static inline uint32_t
+rtems_capture_task_stack_size (rtems_capture_task_t* task)
+{
+ return task->stack_size;
+}
+
+/*
+ * rtems_capture_task_stack_used
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the amount of stack used.
+ */
+static inline uint32_t
+rtems_capture_task_stack_used (rtems_capture_task_t* task)
+{
+ return task->stack_size - task->stack_clean;
+}
+
+/*
+ * rtems_capture_task_ticks
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the current execution time as ticks.
+ */
+static inline uint32_t
+rtems_capture_task_ticks (rtems_capture_task_t* task)
+{
+ return task->ticks;
+}
+
+/*
+ * rtems_capture_task_tick_offset
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the current execution time tick offset.
+ */
+static inline uint32_t
+rtems_capture_task_tick_offset (rtems_capture_task_t* task)
+{
+ return task->tick_offset;
+}
+
+/*
+ * rtems_capture_task_time
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the current execution time.
+ */
+static inline unsigned long long
+rtems_capture_task_time (rtems_capture_task_t* task)
+{
+ unsigned long long t = task->ticks;
+ return (t * rtems_capture_tick_time ()) + task->tick_offset;;
+}
+
+/*
+ * rtems_capture_task_delta_time
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the execution time as a different between the
+ * last time the detla time was and now.
+ */
+static inline unsigned long long
+rtems_capture_task_delta_time (rtems_capture_task_t* task)
+{
+ unsigned long long t = task->ticks - task->last_ticks;
+ uint32_t o = task->tick_offset - task->last_tick_offset;
+
+ task->last_ticks = task->ticks;
+ task->last_tick_offset = task->tick_offset;
+
+ return (t * rtems_capture_tick_time ()) + o;
+}
+
+/*
+ * rtems_capture_task_count
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the number of tasks the capture
+ * engine knows about.
+ */
+static inline uint32_t
+rtems_capture_task_count ()
+{
+ rtems_capture_task_t* task = rtems_capture_get_task_list ();
+ uint32_t count = 0;
+
+ while (task)
+ {
+ count++;
+ task = rtems_capture_next_task (task);
+ }
+
+ return count;
+}
+
+/*
+ * rtems_capture_get_control_list
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the head of the list of controls in the
+ * capture engine.
+ */
+rtems_capture_control_t*
+rtems_capture_get_control_list ();
+
+/*
+ * rtems_capture_next_control
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the pointer to the next control in the list. The
+ * pointer NULL terminates the list.
+ */
+static inline rtems_capture_control_t*
+rtems_capture_next_control (rtems_capture_control_t* control)
+{
+ return control->next;
+}
+
+/*
+ * rtems_capture_control_id
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the control id.
+ */
+static inline rtems_id
+rtems_capture_control_id (rtems_capture_control_t* control)
+{
+ return control->id;
+}
+
+/*
+ * rtems_capture_control_name
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the control name.
+ */
+static inline rtems_name
+rtems_capture_control_name (rtems_capture_control_t* control)
+{
+ return control->name;
+}
+
+/*
+ * rtems_capture_control_flags
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the control flags.
+ */
+static inline uint32_t
+rtems_capture_control_flags (rtems_capture_control_t* control)
+{
+ return control->flags;
+}
+
+/*
+ * rtems_capture_control_from_name
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the control from task name.
+ */
+static inline rtems_name
+rtems_capture_control_from_name (rtems_capture_control_t* control, int from)
+{
+ if (from < RTEMS_CAPTURE_TRIGGER_TASKS)
+ return control->from[from];
+ return control->from[0];
+}
+
+/*
+ * rtems_capture_control_from_id
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the control from task id.
+ */
+static inline rtems_id
+rtems_capture_control_from_id (rtems_capture_control_t* control, int from)
+{
+ if (from < RTEMS_CAPTURE_TRIGGER_TASKS)
+ return control->from_id[from];
+ return control->from_id[0];
+}
+
+/*
+ * rtems_capture_control_count
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the number of controls the capture
+ * engine has.
+ */
+static inline uint32_t
+rtems_capture_control_count ()
+{
+ rtems_capture_control_t* control = rtems_capture_get_control_list ();
+ uint32_t count = 0;
+
+ while (control)
+ {
+ count++;
+ control = rtems_capture_next_control (control);
+ }
+
+ return count;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/libmisc/cpuuse/README b/cpukit/libmisc/cpuuse/README
new file mode 100644
index 0000000000..20e76f07bc
--- /dev/null
+++ b/cpukit/libmisc/cpuuse/README
@@ -0,0 +1,41 @@
+#
+# $Id$
+#
+
+This directory contains a stack bounds checker. It provides two
+primary features:
+
+ + check for stack overflow at each context switch
+ + provides an educated guess at each task's stack usage
+
+The stack overflow check at context switch works by looking for
+a 16 byte pattern at the logical end of the stack to be corrupted.
+The "guesser" assumes that the entire stack was prefilled with a known
+pattern and assumes that the pattern is still in place if the memory
+has not been used as a stack.
+
+Both of these can be fooled by pushing large holes onto the stack
+and not writing to them... or (much more unlikely) writing the
+magic patterns into memory.
+
+This code has not been extensively tested. It is provided as a tool
+for RTEMS users to catch the most common mistake in multitasking
+systems ... too little stack space. Suggestions and comments are appreciated.
+
+NOTES:
+
+1. Stack usage information is questionable on CPUs which push
+ large holes on stack.
+
+2. The stack checker has a tendency to generate a fault when
+ trying to print the helpful diagnostic message. If it comes
+ out, congratulations. If not, then the variable Stack_check_Blown_task
+ contains a pointer to the TCB of the offending task. This
+ is usually enough to go on.
+
+FUTURE:
+
+1. Determine how/if gcc will generate stack probe calls and support that.
+
+2. Get accurate stack usage numbers on i960.. it pushes very large
+ holes on the stack.
diff --git a/cpukit/libmisc/cpuuse/cpuuse.c b/cpukit/libmisc/cpuuse/cpuuse.c
new file mode 100644
index 0000000000..189b542644
--- /dev/null
+++ b/cpukit/libmisc/cpuuse/cpuuse.c
@@ -0,0 +1,148 @@
+/*
+ * CPU Usage Reporter
+ *
+ * COPYRIGHT (c) 1989-1999. 1996.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <rtems/cpuuse.h>
+
+uint32_t CPU_usage_Ticks_at_last_reset;
+
+/*PAGE
+ *
+ * CPU_usage_Dump
+ */
+
+void CPU_usage_Dump( void )
+{
+ uint32_t i;
+ uint32_t api_index;
+ Thread_Control *the_thread;
+ Objects_Information *information;
+ uint32_t u32_name;
+ char *cname;
+ char name[5];
+ uint32_t total_units = 0;
+
+ for ( api_index = 1 ;
+ api_index <= OBJECTS_APIS_LAST ;
+ api_index++ ) {
+ if ( !_Objects_Information_table[ api_index ] )
+ continue;
+ information = _Objects_Information_table[ api_index ][ 1 ];
+ if ( information ) {
+ for ( i=1 ; i <= information->maximum ; i++ ) {
+ the_thread = (Thread_Control *)information->local_table[ i ];
+
+ if ( the_thread )
+ total_units += the_thread->ticks_executed;
+ }
+ }
+ }
+
+ fprintf(stdout,"CPU Usage by thread\n");
+#if defined(unix) || ( CPU_HARDWARE_FP == TRUE )
+ fprintf(stdout, " ID NAME TICKS PERCENT\n" );
+#else
+ fprintf(stdout, " ID NAME TICKS\n" );
+#endif
+
+ for ( api_index = 1 ;
+ api_index <= OBJECTS_APIS_LAST ;
+ api_index++ ) {
+ if ( !_Objects_Information_table[ api_index ] )
+ continue;
+ information = _Objects_Information_table[ api_index ][ 1 ];
+ if ( information ) {
+ for ( i=1 ; i <= information->maximum ; i++ ) {
+ the_thread = (Thread_Control *)information->local_table[ i ];
+
+ if ( !the_thread )
+ continue;
+
+ if ( information->is_string ) {
+ cname = the_thread->Object.name;
+ name[ 0 ] = cname[0];
+ name[ 1 ] = cname[1];
+ name[ 2 ] = cname[2];
+ name[ 3 ] = cname[3];
+ name[ 4 ] = '\0';
+ } else {
+ u32_name = (uint32_t )the_thread->Object.name;
+ name[ 0 ] = (u32_name >> 24) & 0xff;
+ name[ 1 ] = (u32_name >> 16) & 0xff;
+ name[ 2 ] = (u32_name >> 8) & 0xff;
+ name[ 3 ] = (u32_name >> 0) & 0xff;
+ name[ 4 ] = '\0';
+ }
+
+ if ( !isprint(name[0]) ) name[0] = '*';
+ if ( !isprint(name[1]) ) name[1] = '*';
+ if ( !isprint(name[2]) ) name[2] = '*';
+ if ( !isprint(name[3]) ) name[3] = '*';
+
+#if defined(unix) || ( CPU_HARDWARE_FP == TRUE )
+ fprintf(stdout, "0x%08x %4s %8d %5.3f\n",
+ the_thread->Object.id,
+ name,
+ the_thread->ticks_executed,
+ (total_units) ?
+ (double)the_thread->ticks_executed / (double)total_units :
+ (double)total_units
+ );
+#else
+ fprintf(stdout, "0x%08x %4s %8d\n",
+ the_thread->Object.id,
+ name,
+ the_thread->ticks_executed
+ );
+#endif
+ }
+ }
+ }
+
+ fprintf(stdout,
+ "\nTicks since last reset = %d\n",
+ _Watchdog_Ticks_since_boot - CPU_usage_Ticks_at_last_reset
+ );
+ fprintf(stdout, "\nTotal Units = %d\n", total_units );
+}
+
+/*PAGE
+ *
+ * CPU_usage_Reset
+ */
+
+static void CPU_usage_Per_thread_handler(
+ Thread_Control *the_thread
+)
+{
+ the_thread->ticks_executed = 0;
+}
+
+void CPU_usage_Reset( void )
+{
+ CPU_usage_Ticks_at_last_reset = _Watchdog_Ticks_since_boot;
+
+ rtems_iterate_over_all_threads(CPU_usage_Per_thread_handler);
+}
diff --git a/cpukit/libmisc/cpuuse/cpuuse.h b/cpukit/libmisc/cpuuse/cpuuse.h
new file mode 100644
index 0000000000..de874e0fcd
--- /dev/null
+++ b/cpukit/libmisc/cpuuse/cpuuse.h
@@ -0,0 +1,40 @@
+/* cpuuse.h
+ *
+ * This include file contains information necessary to utilize
+ * and install the cpu usage reporting mechanism.
+ *
+ * COPYRIGHT (c) 1989-1999. 1996.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __CPU_USE_h
+#define __CPU_USE_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * CPU_usage_Dump
+ */
+
+void CPU_usage_Dump( void );
+
+/*
+ * CPU_usage_Reset
+ */
+
+void CPU_usage_Reset( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/libmisc/devnull/devnull.c b/cpukit/libmisc/devnull/devnull.c
new file mode 100644
index 0000000000..cfc8a750ce
--- /dev/null
+++ b/cpukit/libmisc/devnull/devnull.c
@@ -0,0 +1,184 @@
+/* /dev/null
+ *
+ * Derived from rtems' stub driver.
+ *
+ * Author: Ralf Corsepius (corsepiu@faw.uni-ulm.de)
+ *
+ * COPYRIGHT (c) 1989-2000.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/devnull.h>
+#include <rtems/libio.h>
+
+/* null_initialize
+ *
+ * This routine is the null device driver init routine.
+ *
+ * Input parameters:
+ * major - device major number
+ * minor - device minor number
+ * pargp - pointer to parameter block
+ *
+ * Output parameters:
+ * rval - NULL_SUCCESSFUL
+ */
+
+uint32_t NULL_major;
+static char initialized;
+
+rtems_device_driver null_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *pargp
+)
+{
+ rtems_device_driver status;
+
+ if ( !initialized ) {
+ initialized = 1;
+
+ status = rtems_io_register_name(
+ "/dev/null",
+ major,
+ (rtems_device_minor_number) 0
+ );
+
+ if (status != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred(status);
+
+ NULL_major = major;
+ }
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/* null_open
+ *
+ * This routine is the null device driver open routine.
+ *
+ * Input parameters:
+ * major - device major number
+ * minor - device minor number
+ * pargb - pointer to open parameter block
+ *
+ * Output parameters:
+ * rval - NULL_SUCCESSFUL
+ */
+
+rtems_device_driver null_open(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *pargp
+)
+{
+ return NULL_SUCCESSFUL;
+}
+
+
+/* null_close
+ *
+ * This routine is the null device driver close routine.
+ *
+ * Input parameters:
+ * major - device major number
+ * minor - device minor number
+ * pargb - pointer to close parameter block
+ *
+ * Output parameters:
+ * rval - NULL_SUCCESSFUL
+ */
+
+rtems_device_driver null_close(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *pargp
+)
+{
+ return NULL_SUCCESSFUL;
+}
+
+
+/* null_read
+ *
+ * This routine is the null device driver read routine.
+ *
+ * Input parameters:
+ * major - device major number
+ * minor - device minor number
+ * pargp - pointer to read parameter block
+ *
+ * Output parameters:
+ * rval - NULL_SUCCESSFUL
+ */
+
+rtems_device_driver null_read(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *pargp
+)
+{
+ return NULL_SUCCESSFUL;
+}
+
+
+/* null_write
+ *
+ * This routine is the null device driver write routine.
+ *
+ * Input parameters:
+ * major - device major number
+ * minor - device minor number
+ * pargp - pointer to write parameter block
+ *
+ * Output parameters:
+ * rval - NULL_SUCCESSFUL
+ */
+
+rtems_device_driver null_write(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *pargp
+)
+{
+ rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *) pargp;
+
+ if ( rw_args )
+ rw_args->bytes_moved = rw_args->count;
+
+ return NULL_SUCCESSFUL;
+}
+
+
+/* null_control
+ *
+ * This routine is the null device driver control routine.
+ *
+ * Input parameters:
+ * major - device major number
+ * minor - device minor number
+ * pargp - pointer to cntrl parameter block
+ *
+ * Output parameters:
+ * rval - NULL_SUCCESSFUL
+ */
+
+rtems_device_driver null_control(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *pargp
+)
+{
+ return NULL_SUCCESSFUL;
+}
diff --git a/cpukit/libmisc/devnull/devnull.h b/cpukit/libmisc/devnull/devnull.h
new file mode 100644
index 0000000000..6fdf3b6850
--- /dev/null
+++ b/cpukit/libmisc/devnull/devnull.h
@@ -0,0 +1,71 @@
+/* devnull.h
+ *
+ * Null device driver, derived from rtems' stub driver.
+ *
+ * Author: Ralf Corsepius (corsepiu@faw.uni-ulm.de)
+ *
+ * COPYRIGHT (c) 1989-2000.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __NULL_DRIVER_h
+#define __NULL_DRIVER_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DEVNULL_DRIVER_TABLE_ENTRY \
+ { null_initialize, null_open, null_close, null_read, \
+ null_write, null_control }
+
+#define NULL_SUCCESSFUL RTEMS_SUCCESSFUL
+
+rtems_device_driver null_initialize(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *
+);
+
+rtems_device_driver null_open(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *
+);
+
+rtems_device_driver null_close(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *
+);
+
+rtems_device_driver null_read(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *
+);
+
+rtems_device_driver null_write(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *
+);
+
+rtems_device_driver null_control(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/libmisc/dummy/README b/cpukit/libmisc/dummy/README
new file mode 100644
index 0000000000..03bb30834d
--- /dev/null
+++ b/cpukit/libmisc/dummy/README
@@ -0,0 +1,23 @@
+dummy.rel
+=========
+
+A relocatible objects which contains a dummy configuration for RTEMS.
+
+Helps linking standard c-program code with RTEMS, which shall *not* be run
+on a target, such as configure script code fragments generated by autoconf's
+AC_TRY_LINK.
+
+Example:
+
+tar xzvf somepkg.tar.gz
+cd somepkg
+
+LDFLAGS=/usr/local/rtems/<cpu>-rtems/<bsp>/lib/dummy.rel \
+CC="<cpu>-rtems-gcc \
+-B/usr/local/rtems/<cpu>-rtems/<bsp>/lib/ -specs bsp_specs -qrtems" \
+CC_FOR_BUILD="gcc" \
+configure --host=<cpu>-rtems --build=i686-pc-linux-gnu
+make
+
+History:
+Starting dummy.c with a copy of rtems-19990528/c/src/tests/samples/minimum/init.c
diff --git a/cpukit/libmisc/dummy/dummy.c b/cpukit/libmisc/dummy/dummy.c
new file mode 100644
index 0000000000..c59114375c
--- /dev/null
+++ b/cpukit/libmisc/dummy/dummy.c
@@ -0,0 +1,45 @@
+/* Init
+ *
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+
+rtems_task Init(
+ rtems_task_argument ignored
+)
+{
+}
+
+int main( int, char **, char **);
+
+/* configuration information */
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+#define CONFIGURE_MAXIMUM_TASKS 10
+#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM
+#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 20
+#define CONFIGURE_INIT_TASK_ENTRY_POINT (void *)main
+
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+#define CONFIGURE_INIT
+
+#include <rtems/confdefs.h>
+
+/* global variables */
diff --git a/cpukit/libmisc/dumpbuf/dumpbuf.c b/cpukit/libmisc/dumpbuf/dumpbuf.c
new file mode 100644
index 0000000000..120a464a90
--- /dev/null
+++ b/cpukit/libmisc/dumpbuf/dumpbuf.c
@@ -0,0 +1,79 @@
+/*
+ * COPYRIGHT (c) 1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may in
+ * the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <rtems/dumpbuf.h>
+
+/*
+ * Put the body below Dump_Buffer so it won't get inlined.
+ */
+
+static inline void Dump_Line(
+ unsigned char *buffer,
+ int length
+);
+
+void Dump_Buffer(
+ unsigned char *buffer,
+ int length
+)
+{
+
+ int i, mod, max;
+
+ if ( !length ) return;
+
+ mod = length % 16;
+
+ max = length - mod;
+
+ for ( i=0 ; i<max ; i+=16 )
+ Dump_Line( &buffer[ i ], 16 );
+
+ if ( mod )
+ Dump_Line( &buffer[ max ], mod );
+}
+
+static inline void Dump_Line(
+ unsigned char *buffer,
+ int length
+)
+{
+
+ int i;
+ char line_buffer[120];
+
+ line_buffer[0] = '\0';
+
+ for( i=0 ; i<length ; i++ )
+ sprintf( line_buffer, "%s%02x ", line_buffer, buffer[ i ] );
+
+ for( ; i<16 ; i++ )
+ strcat( line_buffer, " " );
+
+ strcat( line_buffer, "|" );
+ for( i=0 ; i<length ; i++ )
+ sprintf( line_buffer, "%s%c", line_buffer,
+ isprint( buffer[ i ] ) ? buffer[ i ] : '.' );
+
+ for( ; i<16 ; i++ )
+ strcat( line_buffer, " " );
+
+ strcat( line_buffer, "|\n" );
+
+ fprintf(stdout, line_buffer );
+}
diff --git a/cpukit/libmisc/dumpbuf/dumpbuf.h b/cpukit/libmisc/dumpbuf/dumpbuf.h
new file mode 100644
index 0000000000..bcdf4d56ee
--- /dev/null
+++ b/cpukit/libmisc/dumpbuf/dumpbuf.h
@@ -0,0 +1,21 @@
+/*
+ * COPYRIGHT (c) 1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may in
+ * the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __DUMP_BUFFER_h
+#define __DUMP_BUFFER_h
+
+void Dump_Buffer(
+ unsigned char *buffer,
+ int length
+);
+
+#endif
+/* end of include file */
diff --git a/cpukit/libmisc/fsmount/README b/cpukit/libmisc/fsmount/README
new file mode 100644
index 0000000000..88bfda62e7
--- /dev/null
+++ b/cpukit/libmisc/fsmount/README
@@ -0,0 +1,24 @@
+#
+#
+# fsmount information
+#
+# Author: Thomas Doerfler 02/07/2003
+#
+# README,v 1.1 1999/07/09 17:23:15 joel Exp
+#
+
+fsmount.c contains the function fsmount. It processes the
+fs table given as an parameter to create the listed mount points
+and mount the corresponding file systems to their mount points.
+See "c/src/tests/samples/fileio" for a sample on how to use this
+function.
+
+The field "report_reasons" specifies, what results of the mount point
+creation/mount operations should print to the console.
+
+The field "abort_reasons" specifies, what results of the mount point
+creation/mount operations should abort the function. Do not set the
+"abort_reasons" bit, unless you want to stop the processing of the
+fsmount table after the first successful mount.
+
+
diff --git a/cpukit/libmisc/fsmount/fsmount.c b/cpukit/libmisc/fsmount/fsmount.c
new file mode 100644
index 0000000000..0d5e388f62
--- /dev/null
+++ b/cpukit/libmisc/fsmount/fsmount.c
@@ -0,0 +1,195 @@
+/*===============================================================*\
+| Project: RTEMS fsmount |
++-----------------------------------------------------------------+
+| File: fsmount.c |
++-----------------------------------------------------------------+
+| Copyright (c) 2003 IMD |
+| Ingenieurbuero fuer Microcomputertechnik Th. Doerfler |
+| <Thomas.Doerfler@imd-systems.de> |
+| all rights reserved |
++-----------------------------------------------------------------+
+| this file contains the fsmount functions. These functions |
+| are used to mount a list of filesystems (and create their mount |
+| points before) |
+| |
+| The license and distribution terms for this file may be |
+| found in the file LICENSE in this distribution or at |
+| http://www.rtems.com/license/LICENSE. |
+| |
++-----------------------------------------------------------------+
+| date history ID |
+| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
+| 02.07.03 creation doe |
+\*===============================================================*/
+#include <rtems.h>
+#include <rtems/fsmount.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <rtems/imfs.h>
+#include <sys/stat.h>
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int rtems_fsmount_create_mountpoint
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| This function will create the mount point given |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ const char *mount_point
+ )
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| 0, if success, -1 and errno if failed |
+\*=========================================================================*/
+{
+ int rc = 0;
+ char *tok_buffer = NULL;
+ char *token = NULL;
+ int token_len;
+ size_t total_len;
+ IMFS_token_types token_type;
+ struct stat file_info;
+ /*
+ * allocate temp memory to rebuild path name
+ */
+ tok_buffer = calloc(strlen(mount_point)+1,sizeof(char));
+ token = tok_buffer;
+ total_len = 0;
+ do {
+ /*
+ * scan through given string, one segment at a time
+ */
+ token_type = IMFS_get_token(mount_point+total_len,token,&token_len);
+ total_len += token_len;
+ strncpy(tok_buffer,mount_point,total_len);
+ tok_buffer[total_len] = '\0';
+
+ if ((token_type != IMFS_NO_MORE_PATH) &&
+ (token_type != IMFS_CURRENT_DIR) &&
+ (token_type != IMFS_INVALID_TOKEN)) {
+ /*
+ * check, whether segment exists
+ */
+ if (0 != stat(tok_buffer,&file_info)) {
+ /*
+ * if not, create directory
+ */
+ rc = mknod(tok_buffer,S_IRWXU | S_IRWXG | S_IRWXO | S_IFDIR,0);
+ }
+ }
+ } while ((rc == 0) &&
+ (token_type != IMFS_NO_MORE_PATH) &&
+ (token_type != IMFS_INVALID_TOKEN));
+
+ /*
+ * return token buffer to heap
+ */
+ if (tok_buffer != NULL) {
+ free(tok_buffer);
+ }
+ return rc;
+}
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int rtems_fsmount
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| This function will create the mount points listed and mount the file |
+| systems listed in the calling parameters |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ const fstab_t *fstab_ptr,
+ int fstab_count,
+ int *fail_idx
+ )
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| 0, if success, -1 and errno if failed |
+\*=========================================================================*/
+{
+ int rc = 0;
+ int tmp_rc;
+ int fstab_idx = 0;
+ rtems_filesystem_mount_table_entry_t *tmp_mt_entry;
+ boolean terminate = FALSE;
+
+ /*
+ * scan through all fstab entries;
+ */
+ while (!terminate &&
+ (fstab_idx < fstab_count)) {
+ tmp_rc = 0;
+ /*
+ * create mount point
+ */
+ if (tmp_rc == 0) {
+ tmp_rc = rtems_fsmount_create_mountpoint(fstab_ptr->mount_point);
+ if (tmp_rc != 0) {
+ if (0 != (fstab_ptr->report_reasons & FSMOUNT_MNTPNT_CRTERR)) {
+ fprintf(stdout,"fsmount: creation of mount point \"%s\" failed: %s\n",
+ fstab_ptr->mount_point,
+ strerror(errno));
+ }
+ if (0 != (fstab_ptr->abort_reasons & FSMOUNT_MNTPNT_CRTERR)) {
+ terminate = TRUE;
+ rc = tmp_rc;
+ }
+ }
+ }
+ /*
+ * mount device to given mount point
+ */
+ if (tmp_rc == RTEMS_SUCCESSFUL) {
+ tmp_rc = mount(&tmp_mt_entry,
+ fstab_ptr->fs_ops,
+ fstab_ptr->mount_options,
+ fstab_ptr->dev,
+ fstab_ptr->mount_point);
+ if (tmp_rc != RTEMS_SUCCESSFUL) {
+ if (0 != (fstab_ptr->report_reasons & FSMOUNT_MNT_FAILED)) {
+ fprintf(stdout,"fsmount: mounting of \"%s\" to"
+ " \"%s\" failed: %s\n",
+ fstab_ptr->dev,
+ fstab_ptr->mount_point,
+ strerror(errno));
+ }
+ if (0 != (fstab_ptr->abort_reasons & FSMOUNT_MNT_FAILED)) {
+ terminate = TRUE;
+ rc = tmp_rc;
+ }
+ }
+ else {
+ if (0 != (fstab_ptr->report_reasons & FSMOUNT_MNT_OK)) {
+ fprintf(stdout,"fsmount: mounting of \"%s\" to"
+ " \"%s\" succeeded\n",
+ fstab_ptr->dev,
+ fstab_ptr->mount_point);
+ }
+ if (0 != (fstab_ptr->abort_reasons & FSMOUNT_MNT_OK)) {
+ terminate = TRUE;
+ }
+ }
+ }
+ /*
+ * proceed to next entry
+ */
+ if (!terminate) {
+ fstab_ptr++;
+ fstab_idx++;
+ }
+ }
+ if (fail_idx != NULL) {
+ *fail_idx = fstab_idx;
+ }
+ return rc;
+}
diff --git a/cpukit/libmisc/fsmount/fsmount.h b/cpukit/libmisc/fsmount/fsmount.h
new file mode 100644
index 0000000000..1b876e6f81
--- /dev/null
+++ b/cpukit/libmisc/fsmount/fsmount.h
@@ -0,0 +1,71 @@
+/*===============================================================*\
+| Project: RTEMS fsmount |
++-----------------------------------------------------------------+
+| File: fsmount.h |
++-----------------------------------------------------------------+
+| Copyright (c) 2003 IMD |
+| Ingenieurbuero fuer Microcomputertechnik Th. Doerfler |
+| <Thomas.Doerfler@imd-systems.de> |
+| all rights reserved |
++-----------------------------------------------------------------+
+| this file contains the fsmount functions. These functions |
+| are used to mount a list of filesystems (and create their mount |
+| points before) |
+| |
+| The license and distribution terms for this file may be |
+| found in the file LICENSE in this distribution or at |
+| http://www.rtems.com/license/LICENSE. |
+| |
++-----------------------------------------------------------------+
+| date history ID |
+| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
+| 02.07.03 creation doe |
+\*===============================================================*/
+#ifndef _FSMOUNT_H
+#define _FSMOUNT_H
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <rtems/libcsupport.h>
+
+/*
+ * bits to define, what errors will cause reporting (via printf) and
+ * abort of mount processing
+ * Use a combination of these bits
+ * for the fields "report_reasons" and "abort_reasons"
+ */
+#define FSMOUNT_MNT_OK 0x0001 /* mounted ok */
+#define FSMOUNT_MNTPNT_CRTERR 0x0002 /* cannot create mount point */
+#define FSMOUNT_MNT_FAILED 0x0004 /* mounting failed */
+
+typedef struct {
+ char *dev;
+ char *mount_point;
+ rtems_filesystem_operations_table *fs_ops;
+ rtems_filesystem_options_t mount_options;
+ uint16_t report_reasons;
+ uint16_t abort_reasons;
+} fstab_t;
+
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int rtems_fsmount
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| This function will create the mount points listed and mount the file |
+| systems listed in the calling parameters |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ const fstab_t *fstab_ptr, /* Ptr to filesystem mount table */
+ int fstab_count, /* number of entries in mount table*/
+ int *fail_idx /* return: index of failed entry */
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| 0, if success, -1 and errno if failed |
+\*=========================================================================*/
+
+#endif /* _FSMOUNT_H */
diff --git a/cpukit/libmisc/monitor/README b/cpukit/libmisc/monitor/README
new file mode 100644
index 0000000000..d5a73da140
--- /dev/null
+++ b/cpukit/libmisc/monitor/README
@@ -0,0 +1,97 @@
+#
+# $Id$
+#
+
+monitor task
+
+The monitor task is an optional task that knows about RTEMS
+data structures and can print out information about them.
+It is a work-in-progress and needs many more commands, but
+is useful now.
+
+The monitor works best when it is the highest priority task,
+so all your other tasks should ideally be at some priority
+greater than 1.
+
+To use the monitor:
+-------------------
+
+ #include <rtems/monitor.h>
+
+ ...
+
+ rtems_monitor_init(0);
+
+ The parameter to rtems_monitor_init() tells the monitor whether
+ to suspend itself on startup. A value of 0 causes the monitor
+ to immediately enter command mode; a non-zero value causes the
+ monitor to suspend itself after creation and wait for explicit
+ wakeup.
+
+
+ rtems_monitor_wakeup();
+
+ wakes up a suspended monitor and causes it to reenter command mode.
+
+Monitor commands
+----------------
+
+ The monitor prompt is 'rtems> '.
+ Can abbreviate commands to "uniquity"
+ There is a 'help' command. Here is the output from various
+ help commands:
+
+ Commands (may be abbreviated)
+
+ help -- get this message or command specific help
+ task -- show task information
+ queue -- show message queue information
+ symbol -- show entries from symbol table
+ pause -- pause monitor for a specified number of ticks
+ fatal -- invoke a fatal RTEMS error
+
+ task [id [id ...] ]
+ display information about the specified tasks.
+ Default is to display information about all tasks on this node
+
+ queue [id [id ... ] ]
+ display information about the specified message queues
+ Default is to display information about all queues on this node
+
+ symbol [ symbolname [symbolname ... ] ]
+ display value associated with specified symbol.
+ Defaults to displaying all known symbols.
+
+ pause [ticks]
+ monitor goes to "sleep" for specified ticks (default is 1)
+ monitor will resume at end of period or if explicitly awakened
+
+ fatal [status]
+ Invoke 'rtems_fatal_error_occurred' with 'status'
+ (default is RTEMS_INTERNAL_ERROR)
+
+ continue
+ put the monitor to sleep waiting for an explicit wakeup from the
+ program running.
+
+
+Sample output from 'task' command
+---------------------------------
+
+ rtems> task
+ ID NAME PRIO STAT MODES EVENTS WAITID WAITARG NOTES
+ ------------------------------------------------------------------------
+ 00010001 UI1 2 READY P:T:nA NONE15: 0x40606348
+ 00010002 RMON 1 READY nP NONE15: 0x40604110
+
+ 'RMON' is the monitor itself, so we have 1 "user" task.
+ Its modes are P:T:nA which translate to:
+
+ preemptable
+ timesliced
+ no ASRS
+
+ It has no events.
+ It has a notepad value for notepad 15 which is 0x40606348
+ (this is the libc thread state)
+
diff --git a/cpukit/libmisc/monitor/mon-command.c b/cpukit/libmisc/monitor/mon-command.c
new file mode 100644
index 0000000000..dc20dcb203
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-command.c
@@ -0,0 +1,745 @@
+/*
+ * Command parsing routines for RTEMS monitor
+ *
+ * TODO:
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+
+#include <rtems/monitor.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifndef MONITOR_PROMPT
+#define MONITOR_PROMPT "rtems" /* will have '> ' appended */
+#endif
+
+/*
+ * 2001-01-30 KJO (vac4050@cae597.rsc.raytheon.com):
+ * Fixed rtems_monitor_command_lookup() to accept partial
+ * commands to uniqeness. Added support for setting
+ * the monitor prompt via an environment variable:
+ * RTEMS_MONITOR_PROMPT
+ *
+ * CCJ: 26-3-2000, adding command history and command line
+ * editing. This code is donated from My Right Boot and not
+ * covered by GPL, only the RTEMS license.
+ */
+
+/*
+ * Some key labels to define special keys.
+ */
+
+#define KEYS_EXTENDED (0x8000)
+#define KEYS_NORMAL_MASK (0x00ff)
+#define KEYS_INS (0)
+#define KEYS_DEL (1)
+#define KEYS_UARROW (2)
+#define KEYS_DARROW (3)
+#define KEYS_LARROW (4)
+#define KEYS_RARROW (5)
+#define KEYS_HOME (6)
+#define KEYS_END (7)
+#define KEYS_F1 (8)
+#define KEYS_F2 (9)
+#define KEYS_F3 (10)
+#define KEYS_F4 (11)
+#define KEYS_F5 (12)
+#define KEYS_F6 (13)
+#define KEYS_F7 (14)
+#define KEYS_F8 (15)
+#define KEYS_F9 (16)
+#define KEYS_F10 (17)
+
+#define RTEMS_COMMAND_BUFFER_SIZE (75)
+
+static char monitor_prompt[32];
+#ifndef RTEMS_UNIX
+static char buffer[RTEMS_COMMAND_BUFFER_SIZE];
+static int pos;
+static int logged_in;
+#endif
+/*
+ * History data.
+ */
+
+#define RTEMS_COMMAND_HISTORIES (20)
+
+#ifndef RTEMS_UNIX
+static char history_buffer[RTEMS_COMMAND_HISTORIES][RTEMS_COMMAND_BUFFER_SIZE];
+static int history_pos[RTEMS_COMMAND_HISTORIES];
+static int history;
+static int history_next;
+#endif
+
+/*
+ * Translation tables. Not sure if this is the best way to
+ * handle this, how-ever I wish to avoid the overhead of
+ * including a more complete and standard environment such
+ * as ncurses.
+ */
+
+struct translation_table
+{
+ char expecting;
+ struct translation_table *branch;
+ unsigned int key;
+};
+
+#ifndef RTEMS_UNIX
+static struct translation_table trans_two[] =
+{
+ { '~', 0, KEYS_INS },
+ { 0, 0, 0 }
+};
+
+static struct translation_table trans_three[] =
+{
+ { '~', 0, KEYS_DEL },
+ { 0, 0, 0 }
+};
+
+static struct translation_table trans_tab_csi[] =
+{
+ { '2', trans_two, 0 },
+ { '3', trans_three, 0 },
+ { 'A', 0, KEYS_UARROW },
+ { 'B', 0, KEYS_DARROW },
+ { 'D', 0, KEYS_LARROW },
+ { 'C', 0, KEYS_RARROW },
+ { 'F', 0, KEYS_END },
+ { 'H', 0, KEYS_HOME },
+ { 0, 0, 0 }
+};
+
+static struct translation_table trans_tab_O[] =
+{
+ { '1', 0, KEYS_F1 },
+ { '2', 0, KEYS_F2 },
+ { '3', 0, KEYS_F3 },
+ { '4', 0, KEYS_F4 },
+ { '5', 0, KEYS_F5 },
+ { '6', 0, KEYS_F6 },
+ { '7', 0, KEYS_F7 },
+ { '8', 0, KEYS_F8 },
+ { '9', 0, KEYS_F9 },
+ { ':', 0, KEYS_F10 },
+ { 'P', 0, KEYS_F1 },
+ { 'Q', 0, KEYS_F2 },
+ { 'R', 0, KEYS_F3 },
+ { 'S', 0, KEYS_F4 },
+ { 'T', 0, KEYS_F5 },
+ { 'U', 0, KEYS_F6 },
+ { 'V', 0, KEYS_F7 },
+ { 'W', 0, KEYS_F8 },
+ { 'X', 0, KEYS_F9 },
+ { 'Y', 0, KEYS_F10 },
+ { 0, 0, 0 }
+};
+
+static struct translation_table trans_tab[] =
+{
+ { '[', trans_tab_csi, 0 }, /* CSI command sequences */
+ { 'O', trans_tab_O, 0 }, /* O are the fuction keys */
+ { 0, 0, 0 }
+};
+#endif
+
+/*
+ * Perform a basic tranlation for some ANSI/VT100 key codes.
+ * This code could do with a timeout on the ESC as it is
+ * now lost from the input stream. It is not* used by the
+ * line editor below so considiered not worth the effort.
+ */
+
+#ifndef RTEMS_UNIX
+static unsigned int
+rtems_monitor_getchar (
+)
+{
+ struct translation_table *translation = 0;
+ for (;;)
+ {
+ char c = getchar ();
+ if (c == 27)
+ translation = trans_tab;
+ else
+ {
+ /*
+ * If no translation happing just pass through
+ * and return the key.
+ */
+ if (translation)
+ {
+ /*
+ * Scan the current table for the key, and if found
+ * see if this key is a fork. If so follow it and
+ * wait else return the extended key.
+ */
+ int index = 0;
+ int branched = 0;
+ while ((translation[index].expecting != '\0') ||
+ (translation[index].key != '\0'))
+ {
+ if (translation[index].expecting == c)
+ {
+ /*
+ * A branch is take if more keys are to come.
+ */
+ if (translation[index].branch == 0)
+ return KEYS_EXTENDED | translation[index].key;
+ else
+ {
+ translation = translation[index].branch;
+ branched = 1;
+ break;
+ }
+ }
+ index++;
+ }
+ /*
+ * Who knows what these keys are, just drop them.
+ */
+ if (!branched)
+ translation = 0;
+ }
+ else
+ return c;
+ }
+ }
+}
+#endif
+
+#ifndef RTEMS_UNIX
+/*
+ * The line editor with history.
+ */
+
+static int
+rtems_monitor_line_editor (
+ char *command
+)
+{
+ int repeating = 0;
+
+ memset (buffer, 0, RTEMS_COMMAND_BUFFER_SIZE);
+ history = history_next;
+ pos = 0;
+
+ if (!logged_in)
+ fprintf(stdout,"\nMonitor ready, press enter to login.\n\n");
+ else
+ fprintf(stdout,"%s $ ", monitor_prompt);
+
+ while (1)
+ {
+ unsigned int extended_key = rtems_monitor_getchar ();
+ char c = extended_key & KEYS_NORMAL_MASK;
+
+ /*
+ * Make the extended_key usable as a boolean.
+ */
+ extended_key &= ~KEYS_NORMAL_MASK;
+
+ if (!extended_key && !logged_in)
+ {
+ if (c == '\n')
+ {
+ logged_in = 1;
+ /*
+ * The prompt has changed from `>' to `$' to help know
+ * which version of the monitor code people are using.
+ */
+ fprintf(stdout,"%s $ ", monitor_prompt);
+ }
+ }
+ else
+ {
+ if (extended_key)
+ {
+ switch (c)
+ {
+ case KEYS_END:
+ fprintf(stdout,buffer + pos);
+ pos = (int) strlen (buffer);
+ break;
+
+ case KEYS_HOME:
+ fprintf(stdout,"\r%s $ ", monitor_prompt);
+ pos = 0;
+ break;
+
+ case KEYS_LARROW:
+ if (pos > 0)
+ {
+ pos--;
+ putchar ('\b');
+ }
+ break;
+
+ case KEYS_RARROW:
+ if ((pos < RTEMS_COMMAND_BUFFER_SIZE) && (buffer[pos] != '\0'))
+ {
+ putchar (buffer[pos]);
+ pos++;
+ }
+ break;
+
+ case KEYS_UARROW:
+ /*
+ * If we are moving up the histories then we need to save the working
+ * buffer.
+ */
+ if (history)
+ {
+ int end;
+ int bs;
+ if (history == history_next)
+ {
+ memcpy (history_buffer[history_next], buffer,
+ RTEMS_COMMAND_BUFFER_SIZE);
+ history_pos[history_next] = pos;
+ }
+ history--;
+ memcpy (buffer, history_buffer[history],
+ RTEMS_COMMAND_BUFFER_SIZE);
+ pos = history_pos[history];
+ fprintf(stdout,"\r%*c", RTEMS_COMMAND_BUFFER_SIZE, ' ');
+ fprintf(stdout,"\r%s $ %s", monitor_prompt, buffer);
+ end = (int) strlen (buffer);
+ for (bs = 0; bs < (end - pos); bs++)
+ putchar ('\b');
+ }
+ break;
+
+ case KEYS_DARROW:
+ if (history < history_next)
+ {
+ int end;
+ int bs;
+ history++;
+ memcpy (buffer, history_buffer[history],
+ RTEMS_COMMAND_BUFFER_SIZE);
+ pos = history_pos[history];
+ fprintf(stdout,"\r%*c", RTEMS_COMMAND_BUFFER_SIZE, ' ');
+ fprintf(stdout,"\r%s $ %s", monitor_prompt, buffer);
+ end = (int) strlen (buffer);
+ for (bs = 0; bs < (end - pos); bs++)
+ putchar ('\b');
+ }
+ break;
+
+ case KEYS_DEL:
+ if (buffer[pos] != '\0')
+ {
+ int end;
+ int bs;
+ strcpy (&buffer[pos], &buffer[pos + 1]);
+ fprintf(stdout,"\r%s $ %s", monitor_prompt, buffer);
+ end = (int) strlen (buffer);
+ for (bs = 0; bs < (end - pos); bs++)
+ putchar ('\b');
+ }
+ break;
+ }
+ }
+ else
+ {
+ switch (c)
+ {
+ case '\b':
+ case '\x7e':
+ case '\x7f':
+ if (pos > 0)
+ {
+ int bs;
+ pos--;
+ strcpy (buffer + pos, buffer + pos + 1);
+ fprintf(stdout,"\b%s \b", buffer + pos);
+ for (bs = 0; bs < ((int) strlen (buffer) - pos); bs++)
+ putchar ('\b');
+ }
+ break;
+
+ case '\n':
+ /*
+ * Process the command.
+ */
+ fprintf(stdout,"\n");
+ repeating = 1;
+ /*
+ * Only process the history if we have a command and
+ *a history.
+ */
+ if (strlen (buffer))
+ {
+ if (history_next && (history == history_next))
+ {
+ /*
+ * Do not place the last command into the history
+ *if the same.
+ */
+ if (strcmp (history_buffer[history_next - 1], buffer))
+ repeating = 0;
+ }
+ else
+ repeating = 0;
+ }
+ if (!repeating)
+ {
+ memcpy (history_buffer[history_next], buffer,
+ RTEMS_COMMAND_BUFFER_SIZE);
+ history_pos[history_next] = pos;
+ if (history_next < (RTEMS_COMMAND_HISTORIES - 1))
+ history_next++;
+ else
+ {
+ memmove (history_buffer[0], history_buffer[1],
+ RTEMS_COMMAND_BUFFER_SIZE * (RTEMS_COMMAND_HISTORIES - 1));
+ memmove (&history_pos[0], &history_pos[1],
+ sizeof (history_pos[0]) * (RTEMS_COMMAND_HISTORIES - 1));
+ }
+ }
+ else
+ {
+#ifdef ENABLE_ENTER_REPEATS
+ if (history_next)
+ memcpy (buffer, history_buffer[history_next - 1],
+ RTEMS_COMMAND_BUFFER_SIZE);
+#endif
+ }
+ memmove (command, buffer, RTEMS_COMMAND_BUFFER_SIZE);
+ return repeating;
+ break;
+
+ default:
+ if ((pos < (RTEMS_COMMAND_BUFFER_SIZE - 1)) &&
+ (c >= ' ') && (c <= 'z'))
+ {
+ int end;
+ end = strlen (buffer);
+ if ((pos < end) && (end < RTEMS_COMMAND_BUFFER_SIZE))
+ {
+ int ch, bs;
+ for (ch = end + 1; ch > pos; ch--)
+ buffer[ch] = buffer[ch - 1];
+ fprintf(stdout,buffer + pos);
+ for (bs = 0; bs < (end - pos + 1); bs++)
+ putchar ('\b');
+ }
+ buffer[pos++] = c;
+ if (pos > end)
+ buffer[pos] = '\0';
+ putchar (c);
+ }
+ break;
+ }
+ }
+ }
+ }
+}
+#endif
+
+/*
+ * make_argv(cp): token-count
+ * Break up the command line in 'cp' into global argv[] and argc (return
+ * value).
+ */
+
+int
+rtems_monitor_make_argv(
+ char *cp,
+ int *argc_p,
+ char **argv)
+{
+ int argc = 0;
+
+ while ((cp = strtok(cp, " \t\n\r")))
+ {
+ argv[argc++] = cp;
+ cp = (char *) NULL;
+ }
+ argv[argc] = (char *) NULL; /* end of argv */
+
+ return *argc_p = argc;
+}
+
+
+/*
+ * Read and break up a monitor command
+ *
+ * We have to loop on the gets call, since it will return NULL under UNIX
+ * RTEMS when we get a signal (eg: SIGALRM).
+ */
+
+int
+rtems_monitor_command_read(char *command,
+ int *argc,
+ char **argv)
+{
+ char *env_prompt;
+
+ env_prompt = getenv("RTEMS_MONITOR_PROMPT");
+
+ /*
+ * put node number in the prompt if we are multiprocessing
+ */
+ if (!rtems_configuration_get_user_multiprocessing_table ())
+ sprintf (monitor_prompt, "%s",
+ (env_prompt == NULL) ? MONITOR_PROMPT: env_prompt);
+ else if (rtems_monitor_default_node != rtems_monitor_node)
+ sprintf (monitor_prompt, "%d-%s-%d", rtems_monitor_node,
+ (env_prompt == NULL) ? MONITOR_PROMPT : env_prompt,
+ rtems_monitor_default_node);
+ else
+ sprintf (monitor_prompt, "%d-%s", rtems_monitor_node,
+ (env_prompt == NULL) ? MONITOR_PROMPT : env_prompt);
+
+#if defined(RTEMS_UNIX)
+ /* RTEMS on unix gets so many interrupt system calls this is hosed */
+ fprintf(stdout,"%s> ", monitor_prompt);
+ fflush (stdout);
+ while (gets(command) == (char *) 0)
+ ;
+#else
+ rtems_monitor_line_editor (command);
+#endif
+
+ return rtems_monitor_make_argv (command, argc, argv);
+}
+
+/*
+ * Look up a command in a command table
+ *
+ */
+
+rtems_monitor_command_entry_t *
+rtems_monitor_command_lookup(
+ rtems_monitor_command_entry_t *table,
+ int argc,
+ char **argv
+)
+{
+ int command_length;
+ rtems_monitor_command_entry_t *found_it = NULL;
+
+ command_length = strlen (argv[0]);
+
+ if ((table == 0) || (argv[0] == 0))
+ return 0;
+
+ while (table)
+ {
+ if (table->command)
+ {
+
+ /*
+ * Check for ambiguity
+ */
+ if (!strncmp (table->command, argv[0], command_length))
+ {
+ if (found_it)
+ {
+ return 0;
+ }
+
+ else
+ found_it = table;
+ }
+ }
+ table = table->next;
+ }
+
+ /*
+ * No ambiguity (the possible partial command was unique after all)
+ */
+ if (found_it)
+ {
+ if (found_it->command_function == 0)
+ return 0;
+
+ return found_it;
+ }
+
+ return 0;
+}
+
+static void
+rtems_monitor_show_help (
+ rtems_monitor_command_entry_t *help_cmd,
+ int max_cmd_len
+)
+{
+#define MAX_HELP_LINE_LENGTH (75 - max_cmd_len - 2)
+
+ if (help_cmd && help_cmd->command)
+ {
+ const char *help = help_cmd->usage;
+ int help_len = strlen (help);
+ int spaces = max_cmd_len - strlen (help_cmd->command);
+ int show_this_line = 0;
+ int line_one = 1;
+ int c;
+
+ fprintf(stdout,"%s", help_cmd->command);
+
+ if (help_len == 0)
+ {
+ fprintf(stdout," - No help associated.\n");
+ return;
+ }
+
+ while (help_len)
+ {
+ fprintf(stdout,"%*c", spaces, ' ');
+
+ if (line_one)
+ fprintf(stdout," - ");
+
+ spaces = max_cmd_len + 2;
+ line_one = 0;
+
+ /*
+ * See if greater then the line length if so, work back
+ * from the end for a space, tab or lf or cr.
+ */
+
+ if (help_len > MAX_HELP_LINE_LENGTH)
+ {
+ for (show_this_line = MAX_HELP_LINE_LENGTH - 1;
+ show_this_line;
+ show_this_line--)
+ if ((help[show_this_line] == ' ') ||
+ (help[show_this_line] == '\n') ||
+ (help[show_this_line] == '\r'))
+ break;
+
+ /*
+ * If show_this_line is 0, it is a very long word !!
+ */
+
+ if (show_this_line == 0)
+ show_this_line = MAX_HELP_LINE_LENGTH - 1;
+ }
+ else
+ show_this_line = help_len;
+
+ for (c = 0; c < show_this_line; c++)
+ if ((help[c] == '\r') || (help[c] == '\n'))
+ show_this_line = c;
+ else
+ putchar (help[c]);
+
+ fprintf(stdout,"\n");
+
+ help += show_this_line;
+ help_len -= show_this_line;
+
+ /*
+ * Move past the line feeds or what ever else is being skipped.
+ */
+
+ while (help_len)
+ {
+ if ((*help != '\r') && (*help != '\n'))
+ break;
+
+ if (*help != ' ')
+ {
+ help++;
+ help_len--;
+ break;
+ }
+ help++;
+ help_len--;
+ }
+ }
+ }
+}
+
+void
+rtems_monitor_command_usage(
+ rtems_monitor_command_entry_t *table,
+ char *command_string
+)
+{
+ rtems_monitor_command_entry_t *command = table;
+ int max_cmd_len = 0;
+
+ /* if first entry in table is a usage, then print it out */
+
+ if (command_string && (*command_string != '\0'))
+ {
+ char *argv[2];
+
+ argv[0] = command_string;
+ argv[1] = 0;
+
+ command = rtems_monitor_command_lookup (table, 1, argv);
+
+ if (command)
+ rtems_monitor_show_help (command, strlen (command_string));
+ else
+ fprintf(stdout,"Unrecognised command; try just 'help'\n");
+ return;
+ }
+
+ /*
+ * Find the largest command size.
+ */
+
+ while (command)
+ {
+ int len = command->command ? strlen (command->command) : 0 ;
+
+ if (len > max_cmd_len)
+ max_cmd_len = len;
+
+ command = command->next;
+ }
+
+ max_cmd_len++;
+
+ command = table;
+
+ /*
+ * Now some nice formatting for the help.
+ */
+
+ while (command)
+ {
+ rtems_monitor_show_help (command, max_cmd_len);
+ command = command->next;
+ }
+}
+
+
+void
+rtems_monitor_help_cmd(
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose
+)
+{
+ int arg;
+ rtems_monitor_command_entry_t *command;
+
+ command = command_arg->monitor_command_entry;
+
+ if (argc == 1)
+ rtems_monitor_command_usage(command, 0);
+ else
+ {
+ for (arg = 1; argv[arg]; arg++)
+ rtems_monitor_command_usage(command, argv[arg]);
+ }
+}
diff --git a/cpukit/libmisc/monitor/mon-config.c b/cpukit/libmisc/monitor/mon-config.c
new file mode 100644
index 0000000000..0928eca7e1
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-config.c
@@ -0,0 +1,134 @@
+/*
+ * RTEMS Config display support
+ *
+ * TODO
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#include <rtems.h>
+#include <rtems/monitor.h>
+
+#include <stdio.h>
+#include <stdlib.h> /* strtoul() */
+
+#define DATACOL 15
+#define CONTCOL DATACOL /* continued col */
+
+/*
+ * Fill in entire monitor config table
+ * for sending to a remote monitor or printing on the local system
+ */
+
+void
+rtems_monitor_config_canonical(
+ rtems_monitor_config_t *canonical_config,
+ void *config_void
+)
+{
+ rtems_configuration_table *c = (rtems_configuration_table *) config_void;
+ rtems_api_configuration_table *r = c->RTEMS_api_configuration;
+
+ canonical_config->work_space_start = c->work_space_start;
+ canonical_config->work_space_size = c->work_space_size;
+ canonical_config->maximum_tasks = r->maximum_tasks;
+ canonical_config->maximum_timers = r->maximum_timers;
+ canonical_config->maximum_semaphores = r->maximum_semaphores;
+ canonical_config->maximum_message_queues = r->maximum_message_queues;
+ canonical_config->maximum_partitions = r->maximum_partitions;
+ canonical_config->maximum_regions = r->maximum_regions;
+ canonical_config->maximum_ports = r->maximum_ports;
+ canonical_config->maximum_periods = r->maximum_periods;
+ canonical_config->maximum_extensions = c->maximum_extensions;
+ canonical_config->microseconds_per_tick = c->microseconds_per_tick;
+ canonical_config->ticks_per_timeslice = c->ticks_per_timeslice;
+ canonical_config->number_of_initialization_tasks = r->number_of_initialization_tasks;
+}
+
+/*
+ * This is easy, since there is only 1 (altho we could get them from
+ * other nodes...)
+ */
+
+void *
+rtems_monitor_config_next(
+ void *object_info,
+ rtems_monitor_config_t *canonical_config,
+ rtems_id *next_id
+)
+{
+ rtems_configuration_table *c = _Configuration_Table;
+ int n = rtems_get_index(*next_id);
+
+ if (n >= 1)
+ goto failed;
+
+ _Thread_Disable_dispatch();
+
+ *next_id += 1;
+ return (void *) c;
+
+failed:
+ *next_id = RTEMS_OBJECT_ID_FINAL;
+ return 0;
+}
+
+
+void
+rtems_monitor_config_dump_header(
+ boolean verbose
+)
+{
+ fprintf(stdout,"\
+INITIAL (startup) Configuration Info\n");
+/*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
+0 1 2 3 4 5 6 7 */
+ rtems_monitor_separator();
+}
+
+
+void
+rtems_monitor_config_dump(
+ rtems_monitor_config_t *monitor_config,
+ boolean verbose
+)
+{
+ uint32_t length = 0;
+
+ length = 0;
+ length += fprintf(stdout,"WORKSPACE");
+ length += rtems_monitor_pad(DATACOL, length);
+ length += fprintf(stdout,"start: %p; size: 0x%x\n",
+ monitor_config->work_space_start,
+ monitor_config->work_space_size);
+
+ length = 0;
+ length += fprintf(stdout,"TIME");
+ length += rtems_monitor_pad(DATACOL, length);
+ length += fprintf(stdout,"usec/tick: %d; tick/timeslice: %d; tick/sec: %d\n",
+ monitor_config->microseconds_per_tick,
+ monitor_config->ticks_per_timeslice,
+ 1000000 / monitor_config->microseconds_per_tick);
+
+ length = 0;
+ length += fprintf(stdout,"MAXIMUMS");
+ length += rtems_monitor_pad(DATACOL, length);
+ length += fprintf(stdout,"tasks: %d; timers: %d; sems: %d; que's: %d; ext's: %d\n",
+ monitor_config->maximum_tasks,
+ monitor_config->maximum_timers,
+ monitor_config->maximum_semaphores,
+ monitor_config->maximum_message_queues,
+ monitor_config->maximum_extensions);
+ length = 0;
+ length += rtems_monitor_pad(CONTCOL, length);
+ length += fprintf(stdout,"partitions: %d; regions: %d; ports: %d; periods: %d\n",
+ monitor_config->maximum_partitions,
+ monitor_config->maximum_regions,
+ monitor_config->maximum_ports,
+ monitor_config->maximum_periods);
+}
diff --git a/cpukit/libmisc/monitor/mon-dname.c b/cpukit/libmisc/monitor/mon-dname.c
new file mode 100644
index 0000000000..4f9cc1aef2
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-dname.c
@@ -0,0 +1,116 @@
+/*
+ * RTEMS monitor driver names support.
+ *
+ * There are 2 "driver" things the monitor knows about.
+ *
+ * 1. Regular RTEMS drivers.
+ * This is a table indexed by major device number and
+ * containing driver entry points only.
+ *
+ * 2. Driver name table.
+ * A separate table of names for drivers.
+ * The table converts driver names to a major number
+ * as index into the driver table and a minor number
+ * for an argument to driver.
+ *
+ * Drivers are displayed with 'driver' command.
+ * Names are displayed with 'dname' command.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#include <rtems.h>
+
+#include <rtems/monitor.h>
+
+#include <stdio.h>
+#include <stdlib.h> /* strtoul() */
+#include <string.h> /* strncpy() */
+
+#define DATACOL 15
+#define CONTCOL DATACOL /* continued col */
+
+void
+rtems_monitor_dname_canonical(
+ rtems_monitor_dname_t *canonical_dname,
+ void *dname_void
+)
+{
+ rtems_driver_name_t *np = (rtems_driver_name_t *) dname_void;
+
+ (void) strncpy(canonical_dname->name_string, np->device_name, sizeof(canonical_dname->name_string));
+ canonical_dname->major = np->major;
+ canonical_dname->minor = np->minor;
+}
+
+void *
+rtems_monitor_dname_next(
+ void *object_information,
+ rtems_monitor_dname_t *canonical_dname,
+ rtems_id *next_id
+)
+{
+ uint32_t n = rtems_get_index(*next_id);
+ rtems_driver_name_t *table = _IO_Driver_name_table;
+ rtems_driver_name_t *np = 0;
+
+/* XXX should we be using _IO_Number_of_devices */
+ for (np = table + n ; n<_IO_Number_of_devices; n++, np++)
+ if (np->device_name)
+ goto done;
+
+ *next_id = RTEMS_OBJECT_ID_FINAL;
+ return 0;
+
+done:
+ _Thread_Disable_dispatch();
+
+ /*
+ * dummy up a fake id and name for this item
+ */
+
+ canonical_dname->id = n;
+ canonical_dname->name = rtems_build_name('-', '-', '-', '-');
+
+ *next_id += 1;
+ return np;
+}
+
+void
+rtems_monitor_dname_dump_header(
+ boolean verbose
+)
+{
+ fprintf(stdout,"\
+ Major:Minor Name\n");
+/*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
+0 1 2 3 4 5 6 7 */
+ rtems_monitor_separator();
+}
+
+void
+rtems_monitor_dname_dump(
+ rtems_monitor_dname_t *monitor_dname,
+ boolean verbose
+)
+{
+ uint32_t length = 0;
+
+ length += rtems_monitor_pad(6, length);
+ length += rtems_monitor_dump_hex(monitor_dname->major);
+ length += fprintf(stdout,":");
+ length += rtems_monitor_dump_hex(monitor_dname->minor);
+
+ length += rtems_monitor_pad(16, length);
+ length += fprintf(stdout,"%.*s",
+ (int) sizeof(monitor_dname->name_string),
+ (char *) monitor_dname->name_string);
+
+ length += fprintf(stdout,"\n");
+ length = 0;
+}
diff --git a/cpukit/libmisc/monitor/mon-driver.c b/cpukit/libmisc/monitor/mon-driver.c
new file mode 100644
index 0000000000..12e84f414e
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-driver.c
@@ -0,0 +1,140 @@
+/*
+ * RTEMS monitor IO (device drivers) support
+ *
+ * There are 2 "driver" things the monitor knows about.
+ *
+ * 1. Regular RTEMS drivers.
+ * This is a table indexed by major device number and
+ * containing driver entry points only.
+ *
+ * 2. Driver name table.
+ * A separate table of names for drivers.
+ * The table converts driver names to a major number
+ * as index into the driver table and a minor number
+ * for an argument to driver.
+ *
+ * Drivers are displayed with 'driver' command.
+ * Names are displayed with 'name' command.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#include <rtems.h>
+
+#include <rtems/monitor.h>
+
+#include <stdio.h>
+#include <stdlib.h> /* strtoul() */
+
+#define DATACOL 15
+#define CONTCOL DATACOL /* continued col */
+
+
+void
+rtems_monitor_driver_canonical(
+ rtems_monitor_driver_t *canonical_driver,
+ void *driver_void
+)
+{
+ rtems_driver_address_table *d = (rtems_driver_address_table *) driver_void;
+
+ rtems_monitor_symbol_canonical_by_value(&canonical_driver->initialization,
+ (void *) d->initialization_entry);
+
+ rtems_monitor_symbol_canonical_by_value(&canonical_driver->open,
+ (void *) d->open_entry);
+ rtems_monitor_symbol_canonical_by_value(&canonical_driver->close,
+ (void *) d->close_entry);
+ rtems_monitor_symbol_canonical_by_value(&canonical_driver->read,
+ (void *) d->read_entry);
+ rtems_monitor_symbol_canonical_by_value(&canonical_driver->write,
+ (void *) d->write_entry);
+ rtems_monitor_symbol_canonical_by_value(&canonical_driver->control,
+ (void *) d->control_entry);
+}
+
+
+void *
+rtems_monitor_driver_next(
+ void *object_info,
+ rtems_monitor_driver_t *canonical_driver,
+ rtems_id *next_id
+)
+{
+ rtems_configuration_table *c = _Configuration_Table;
+ uint32_t n = rtems_get_index(*next_id);
+
+ if (n >= c->number_of_device_drivers)
+ goto failed;
+
+ _Thread_Disable_dispatch();
+
+ /*
+ * dummy up a fake id and name for this item
+ */
+
+ canonical_driver->id = n;
+ canonical_driver->name = rtems_build_name('-', '-', '-', '-');
+
+ *next_id += 1;
+ return (void *) (c->Device_driver_table + n);
+
+failed:
+ *next_id = RTEMS_OBJECT_ID_FINAL;
+ return 0;
+}
+
+
+void
+rtems_monitor_driver_dump_header(
+ boolean verbose
+)
+{
+ fprintf(stdout,"\
+ Major Entry points\n");
+/*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
+0 1 2 3 4 5 6 7 */
+ rtems_monitor_separator();
+}
+
+void
+rtems_monitor_driver_dump(
+ rtems_monitor_driver_t *monitor_driver,
+ boolean verbose
+)
+{
+ uint32_t length = 0;
+
+ length += fprintf(stdout," %d", monitor_driver->id);
+
+ length += rtems_monitor_pad(13, length);
+ length += fprintf(stdout,"init: ");
+ length += rtems_monitor_symbol_dump(&monitor_driver->initialization, verbose);
+ length += fprintf(stdout,"; control: ");
+ length += rtems_monitor_symbol_dump(&monitor_driver->control, verbose);
+ length += fprintf(stdout,"\n");
+ length = 0;
+
+ length += rtems_monitor_pad(13, length);
+
+ length += fprintf(stdout,"open: ");
+ length += rtems_monitor_symbol_dump(&monitor_driver->open, verbose);
+ length += fprintf(stdout,"; close: ");
+ length += rtems_monitor_symbol_dump(&monitor_driver->close, verbose);
+ length += fprintf(stdout,"\n");
+ length = 0;
+
+ length += rtems_monitor_pad(13, length);
+
+ length += fprintf(stdout,"read: ");
+ length += rtems_monitor_symbol_dump(&monitor_driver->read, verbose);
+ length += fprintf(stdout,"; write: ");
+ length += rtems_monitor_symbol_dump(&monitor_driver->write, verbose);
+ length += fprintf(stdout,"\n");
+ length = 0;
+}
diff --git a/cpukit/libmisc/monitor/mon-extension.c b/cpukit/libmisc/monitor/mon-extension.c
new file mode 100644
index 0000000000..900fee5b87
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-extension.c
@@ -0,0 +1,102 @@
+/*
+ * RTEMS Monitor extension support
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/monitor.h>
+
+#include <stdio.h>
+
+void
+rtems_monitor_extension_canonical(
+ rtems_monitor_extension_t *canonical_extension,
+ void *extension_void
+)
+{
+ Extension_Control *rtems_extension = (Extension_Control *) extension_void;
+ rtems_extensions_table *e = &rtems_extension->Extension.Callouts;
+
+ rtems_monitor_symbol_canonical_by_value(&canonical_extension->e_create,
+ (void *) e->thread_create);
+
+ rtems_monitor_symbol_canonical_by_value(&canonical_extension->e_start,
+ (void *) e->thread_start);
+ rtems_monitor_symbol_canonical_by_value(&canonical_extension->e_restart,
+ (void *) e->thread_restart);
+ rtems_monitor_symbol_canonical_by_value(&canonical_extension->e_delete,
+ (void *) e->thread_delete);
+ rtems_monitor_symbol_canonical_by_value(&canonical_extension->e_tswitch,
+ (void *) e->thread_switch);
+ rtems_monitor_symbol_canonical_by_value(&canonical_extension->e_begin,
+ (void *) e->thread_begin);
+ rtems_monitor_symbol_canonical_by_value(&canonical_extension->e_exitted,
+ (void *) e->thread_exitted);
+ rtems_monitor_symbol_canonical_by_value(&canonical_extension->e_fatal,
+ (void *) e->fatal);
+}
+
+void
+rtems_monitor_extension_dump_header(
+ boolean verbose
+)
+{
+ fprintf(stdout,"\
+ ID NAME\n");
+/*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
+0 1 2 3 4 5 6 7 */
+
+ rtems_monitor_separator();
+}
+
+
+/*
+ * Dump out the canonical form
+ */
+
+void
+rtems_monitor_extension_dump(
+ rtems_monitor_extension_t *monitor_extension,
+ boolean verbose
+)
+{
+ uint32_t length = 0;
+
+ length += rtems_monitor_dump_id(monitor_extension->id);
+ length += rtems_monitor_pad(11, length);
+ length += rtems_monitor_dump_name(monitor_extension->name);
+
+ length += rtems_monitor_pad(18, length);
+ length += fprintf(stdout,"create: ");
+ length += rtems_monitor_symbol_dump(&monitor_extension->e_create, verbose);
+ length += fprintf(stdout,"; start: ");
+ length += rtems_monitor_symbol_dump(&monitor_extension->e_start, verbose);
+ length += fprintf(stdout,"; restart: ");
+ length += rtems_monitor_symbol_dump(&monitor_extension->e_restart, verbose);
+ length += fprintf(stdout,"\n");
+ length = 0;
+
+ length += rtems_monitor_pad(18, length);
+ length += fprintf(stdout,"delete: ");
+ length += rtems_monitor_symbol_dump(&monitor_extension->e_delete, verbose);
+ length += fprintf(stdout,"; switch: ");
+ length += rtems_monitor_symbol_dump(&monitor_extension->e_tswitch, verbose);
+ length += fprintf(stdout,"; begin: ");
+ length += rtems_monitor_symbol_dump(&monitor_extension->e_begin, verbose);
+ length += fprintf(stdout,"\n");
+ length = 0;
+
+ length += rtems_monitor_pad(18, length);
+ length += fprintf(stdout,"exitted: ");
+ length += rtems_monitor_symbol_dump(&monitor_extension->e_exitted, verbose);
+ length += fprintf(stdout,"; fatal: ");
+ length += rtems_monitor_symbol_dump(&monitor_extension->e_fatal, verbose);
+ length += fprintf(stdout,"\n");
+ length = 0;
+ fprintf(stdout,"\n");
+}
diff --git a/cpukit/libmisc/monitor/mon-itask.c b/cpukit/libmisc/monitor/mon-itask.c
new file mode 100644
index 0000000000..f83d0e8561
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-itask.c
@@ -0,0 +1,119 @@
+/*
+ * RTEMS Monitor init task support
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#include <rtems.h>
+#include <rtems/monitor.h>
+
+#include <stdio.h>
+
+/*
+ * As above, but just for init tasks
+ */
+void
+rtems_monitor_init_task_canonical(
+ rtems_monitor_init_task_t *canonical_itask,
+ void *itask_void
+)
+{
+ rtems_initialization_tasks_table *rtems_itask = itask_void;
+
+ rtems_monitor_symbol_canonical_by_value(&canonical_itask->entry,
+ (void *) rtems_itask->entry_point);
+
+ canonical_itask->argument = rtems_itask->argument;
+ canonical_itask->stack_size = rtems_itask->stack_size;
+ canonical_itask->priority = rtems_itask->initial_priority;
+ canonical_itask->modes = rtems_itask->mode_set;
+ canonical_itask->attributes = rtems_itask->attribute_set;
+}
+
+void *
+rtems_monitor_init_task_next(
+ void *object_info,
+ rtems_monitor_init_task_t *canonical_init_task,
+ rtems_id *next_id
+)
+{
+ rtems_configuration_table *c = _Configuration_Table;
+ rtems_initialization_tasks_table *itask;
+ uint32_t n = rtems_get_index(*next_id);
+
+ if (n >= c->RTEMS_api_configuration->number_of_initialization_tasks)
+ goto failed;
+
+ _Thread_Disable_dispatch();
+
+ itask = c->RTEMS_api_configuration->User_initialization_tasks_table + n;
+
+ /*
+ * dummy up a fake id and name for this item
+ */
+
+ canonical_init_task->id = n;
+ canonical_init_task->name = itask->name;
+
+ *next_id += 1;
+ return (void *) itask;
+
+failed:
+ *next_id = RTEMS_OBJECT_ID_FINAL;
+ return 0;
+}
+
+
+void
+rtems_monitor_init_task_dump_header(
+ boolean verbose
+)
+{
+ fprintf(stdout,"\
+ # NAME ENTRY ARGUMENT PRIO MODES ATTRIBUTES STACK SIZE\n");
+/*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
+0 1 2 3 4 5 6 7 */
+ rtems_monitor_separator();
+}
+
+/*
+ */
+
+void
+rtems_monitor_init_task_dump(
+ rtems_monitor_init_task_t *monitor_itask,
+ boolean verbose
+)
+{
+ int length = 0;
+
+ length += rtems_monitor_dump_decimal(monitor_itask->id);
+
+ length += rtems_monitor_pad(7, length);
+ length += rtems_monitor_dump_name(monitor_itask->name);
+
+ length += rtems_monitor_pad(14, length);
+ length += rtems_monitor_symbol_dump(&monitor_itask->entry, verbose);
+
+ length += rtems_monitor_pad(25, length);
+ length += fprintf(stdout,"%d [0x%x]", monitor_itask->argument, monitor_itask->argument);
+
+ length += rtems_monitor_pad(39, length);
+ length += rtems_monitor_dump_priority(monitor_itask->priority);
+
+ length += rtems_monitor_pad(46, length);
+ length += rtems_monitor_dump_modes(monitor_itask->modes);
+
+ length += rtems_monitor_pad(54, length);
+ length += rtems_monitor_dump_attributes(monitor_itask->attributes);
+
+ length += rtems_monitor_pad(66, length);
+ length += fprintf(stdout,"%d [0x%x]", monitor_itask->stack_size, monitor_itask->stack_size);
+
+ fprintf(stdout,"\n");
+}
diff --git a/cpukit/libmisc/monitor/mon-manager.c b/cpukit/libmisc/monitor/mon-manager.c
new file mode 100644
index 0000000000..7e7a269cd6
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-manager.c
@@ -0,0 +1,54 @@
+/*
+ * RTEMS Monitor "manager" support.
+ * Used to traverse object (chain) lists and print them out.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/monitor.h>
+
+#include <stdio.h>
+
+/*
+ * "next" routine for all objects that are RTEMS manager objects
+ */
+
+void *
+rtems_monitor_manager_next(
+ void *table_void,
+ void *canonical,
+ rtems_id *next_id
+)
+{
+ Objects_Information *table = table_void;
+ rtems_monitor_generic_t *copy;
+ Objects_Control *object = 0;
+ Objects_Locations location;
+
+ /*
+ * When we are called, it must be local
+ */
+
+ if ( ! _Objects_Is_local_id(*next_id))
+ goto done;
+
+ object = _Objects_Get_next(table, *next_id, &location, next_id);
+
+ if (object)
+ {
+ copy = (rtems_monitor_generic_t *) canonical;
+ copy->id = object->id;
+ if(table->is_string)
+ _Objects_Copy_name_raw(object->name, &copy->name, sizeof(copy->name));
+ else
+ _Objects_Copy_name_raw(&object->name, &copy->name, sizeof(copy->name));
+ }
+
+done:
+ return object;
+}
diff --git a/cpukit/libmisc/monitor/mon-monitor.c b/cpukit/libmisc/monitor/mon-monitor.c
new file mode 100644
index 0000000000..d45df2dfc0
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-monitor.c
@@ -0,0 +1,591 @@
+/*
+ * RTEMS monitor main body
+ *
+ * TODO:
+ * add stuff to RTEMS api
+ * rtems_get_name(id)
+ * rtems_get_type(id)
+ * rtems_build_id(node, type, num)
+ * Add a command to dump out info about an arbitrary id when
+ * types are added to id's
+ * rtems> id idnum
+ * idnum: node n, object: whatever, id: whatever
+ * allow id's to be specified as n:t:id, where 'n:t' is optional
+ * should have a separate monitor FILE stream (ala the debugger)
+ * remote request/response stuff should be cleaned up
+ * maybe we can use real rpc??
+ * 'info' command to print out:
+ * interrupt stack location, direction and size
+ * floating point config stuff
+ * interrupt config stuff
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include <rtems/monitor.h>
+
+#define STREQ(a,b) (strcmp(a,b) == 0)
+
+/* set by trap handler */
+extern rtems_tcb *debugger_interrupted_task;
+extern rtems_context *debugger_interrupted_task_context;
+extern uint32_t debugger_trap;
+
+/*
+ * Various id's for the monitor
+ * They need to be public variables for access by other agencies
+ * such as debugger and remote servers'
+ */
+
+rtems_id rtems_monitor_task_id;
+
+uint32_t rtems_monitor_node; /* our node number */
+uint32_t rtems_monitor_default_node; /* current default for commands */
+
+/*
+ * The rtems symbol table
+ */
+
+rtems_symbol_table_t *rtems_monitor_symbols;
+
+/*
+ * User registered commands.
+ */
+
+rtems_monitor_command_entry_t rtems_registered_commands;
+
+/*
+ * The top-level commands
+ */
+
+rtems_monitor_command_entry_t rtems_monitor_commands[] = {
+ { "config",
+ "Show the system configuration.",
+ 0,
+ rtems_monitor_object_cmd,
+ { RTEMS_MONITOR_OBJECT_CONFIG },
+ &rtems_monitor_commands[1],
+ },
+ { "itask",
+ "List init tasks for the system",
+ 0,
+ rtems_monitor_object_cmd,
+ { RTEMS_MONITOR_OBJECT_INIT_TASK },
+ &rtems_monitor_commands[2],
+ },
+ { "mpci",
+ "Show the MPCI system configuration, if configured.",
+ 0,
+ rtems_monitor_object_cmd,
+ { RTEMS_MONITOR_OBJECT_MPCI },
+ &rtems_monitor_commands[3],
+ },
+ { "pause",
+ "Monitor goes to \"sleep\" for specified ticks (default is 1). "
+ "Monitor will resume at end of period or if explicitly awakened\n"
+ " pause [ticks]",
+ 0,
+ rtems_monitor_pause_cmd,
+ { 0 },
+ &rtems_monitor_commands[4],
+ },
+ { "continue",
+ "Put the monitor to sleep waiting for an explicit wakeup from the "
+ "program running.\n",
+ 0,
+ rtems_monitor_continue_cmd,
+ { 0 },
+ &rtems_monitor_commands[5],
+ },
+ { "go",
+ "Alias for 'continue'",
+ 0,
+ rtems_monitor_continue_cmd,
+ { 0 },
+ &rtems_monitor_commands[6],
+ },
+ { "node",
+ "Specify default node number for commands that take id's.\n"
+ " node [ node number ]",
+ 0,
+ rtems_monitor_node_cmd,
+ { 0 },
+ &rtems_monitor_commands[7],
+ },
+ { "symbol",
+ "Display value associated with specified symbol. "
+ "Defaults to displaying all known symbols.\n"
+ " symbol [ symbolname [symbolname ... ] ]",
+ 0,
+ rtems_monitor_symbol_cmd,
+ { .symbol_table = &rtems_monitor_symbols },
+ &rtems_monitor_commands[8],
+ },
+ { "extension",
+ "Display information about specified extensions. "
+ "Default is to display information about all extensions on this node.\n"
+ " extension [id [id ...] ]",
+ 0,
+ rtems_monitor_object_cmd,
+ { RTEMS_MONITOR_OBJECT_EXTENSION },
+ &rtems_monitor_commands[9],
+ },
+ { "task",
+ "Display information about the specified tasks. "
+ "Default is to display information about all tasks on this node.\n"
+ " task [id [id ...] ]",
+ 0,
+ rtems_monitor_object_cmd,
+ { RTEMS_MONITOR_OBJECT_TASK },
+ &rtems_monitor_commands[10],
+ },
+ { "queue",
+ "Display information about the specified message queues. "
+ "Default is to display information about all queues on this node.\n"
+ " queue [id [id ... ] ]",
+ 0,
+ rtems_monitor_object_cmd,
+ { RTEMS_MONITOR_OBJECT_QUEUE },
+ &rtems_monitor_commands[11],
+ },
+ { "object",
+ "Display information about specified RTEMS objects. "
+ "Object id's must include 'type' information. "
+ "(which may normally be defaulted)\n"
+ " object [id [id ...] ]",
+ 0,
+ rtems_monitor_object_cmd,
+ { RTEMS_MONITOR_OBJECT_INVALID },
+ &rtems_monitor_commands[12],
+ },
+ { "driver",
+ "Display the RTEMS device driver table.\n"
+ " driver [ major [ major ... ] ]",
+ 0,
+ rtems_monitor_object_cmd,
+ { RTEMS_MONITOR_OBJECT_DRIVER },
+ &rtems_monitor_commands[13],
+ },
+ { "dname",
+ "Displays information about named drivers.\n",
+ 0,
+ rtems_monitor_object_cmd,
+ { RTEMS_MONITOR_OBJECT_DNAME },
+ &rtems_monitor_commands[14],
+ },
+ { "exit",
+ "Invoke 'rtems_fatal_error_occurred' with 'status' "
+ "(default is RTEMS_SUCCESSFUL)\n"
+ " exit [status]",
+ 0,
+ rtems_monitor_fatal_cmd,
+ { .status_code = RTEMS_SUCCESSFUL },
+ &rtems_monitor_commands[15],
+ },
+ { "fatal",
+ "'exit' with fatal error; default error is RTEMS_TASK_EXITTED\n"
+ " fatal [status]",
+ 0,
+ rtems_monitor_fatal_cmd,
+ { .status_code = RTEMS_TASK_EXITTED }, /* exit value */
+ &rtems_monitor_commands[16],
+ },
+ { "quit",
+ "Alias for 'exit'\n",
+ 0,
+ rtems_monitor_fatal_cmd,
+ { .status_code = RTEMS_SUCCESSFUL }, /* exit value */
+ &rtems_monitor_commands[17],
+ },
+ { "help",
+ "Provide information about commands. "
+ "Default is show basic command summary.\n"
+ "help [ command [ command ] ]",
+ 0,
+ rtems_monitor_help_cmd,
+ { .monitor_command_entry = rtems_monitor_commands },
+ &rtems_monitor_commands[18],
+ },
+#ifdef CPU_INVOKE_DEBUGGER
+ { "debugger",
+ "Enter the debugger, if possible. "
+ "A continue from the debugger will return to the monitor.\n",
+ 0,
+ rtems_monitor_debugger_cmd,
+ { 0 },
+ &rtems_monitor_commands[19],
+ },
+#endif
+ { 0, 0, 0, 0, { 0 }, &rtems_registered_commands },
+};
+
+
+rtems_status_code
+rtems_monitor_suspend(rtems_interval timeout)
+{
+ rtems_event_set event_set;
+ rtems_status_code status;
+
+ status = rtems_event_receive(MONITOR_WAKEUP_EVENT,
+ RTEMS_DEFAULT_OPTIONS,
+ timeout,
+ &event_set);
+ return status;
+}
+
+void
+rtems_monitor_wakeup(void)
+{
+ rtems_status_code status;
+
+ status = rtems_event_send(rtems_monitor_task_id, MONITOR_WAKEUP_EVENT);
+}
+
+void
+rtems_monitor_debugger_cmd(
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t* command_arg,
+ boolean verbose
+)
+{
+#ifdef CPU_INVOKE_DEBUGGER
+ CPU_INVOKE_DEBUGGER;
+#endif
+}
+
+void
+rtems_monitor_pause_cmd(
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t* command_arg,
+ boolean verbose
+)
+{
+ if (argc == 1)
+ rtems_monitor_suspend(1);
+ else
+ rtems_monitor_suspend(strtoul(argv[1], 0, 0));
+}
+
+void
+rtems_monitor_fatal_cmd(
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t* command_arg,
+ boolean verbose
+)
+{
+ if (argc == 1)
+ rtems_fatal_error_occurred(command_arg->status_code);
+ else
+ rtems_fatal_error_occurred(strtoul(argv[1], 0, 0));
+}
+
+void
+rtems_monitor_continue_cmd(
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t* command_arg,
+ boolean verbose
+)
+{
+ rtems_monitor_suspend(RTEMS_NO_TIMEOUT);
+}
+
+void
+rtems_monitor_node_cmd(
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t* command_arg,
+ boolean verbose
+)
+{
+ uint32_t new_node = rtems_monitor_default_node;
+
+ switch (argc)
+ {
+ case 1: /* no node, just set back to ours */
+ new_node = rtems_monitor_node;
+ break;
+
+ case 2:
+ new_node = strtoul(argv[1], 0, 0);
+ break;
+
+ default:
+ fprintf(stdout,"invalid syntax, try 'help node'\n");
+ break;
+ }
+
+ if ((new_node >= 1) &&
+ _Configuration_MP_table &&
+ (new_node <= _Configuration_MP_table->maximum_nodes))
+ rtems_monitor_default_node = new_node;
+}
+
+
+/*
+ * Function: rtems_monitor_symbols_loadup
+ *
+ * Description:
+ * Create and load the monitor's symbol table.
+ * We are reading the output format of 'gnm' which looks like this:
+ *
+ * 400a7068 ? _Rate_monotonic_Information
+ * 400a708c ? _Thread_Dispatch_disable_level
+ * 400a7090 ? _Configuration_Table
+ *
+ * We ignore the type field.
+ *
+ * Side Effects:
+ * Creates and fills in 'rtems_monitor_symbols' table
+ *
+ * TODO
+ * there should be a BSP #define or something like that
+ * to do this; Assuming stdio is crazy.
+ * Someday this should know BFD
+ * Maybe we could get objcopy to just copy the symbol areas
+ * and copy that down.
+ *
+ */
+
+void
+rtems_monitor_symbols_loadup(void)
+{
+ FILE *fp;
+ char buffer[128];
+
+ if (rtems_monitor_symbols)
+ rtems_symbol_table_destroy(rtems_monitor_symbols);
+
+ rtems_monitor_symbols = rtems_symbol_table_create(10);
+ if (rtems_monitor_symbols == 0)
+ return;
+
+ fp = fopen("symbols", "r");
+
+ if (fp == 0)
+ return;
+
+ while (fgets(buffer, sizeof(buffer) - 1, fp))
+ {
+ char *symbol;
+ char *value;
+ char *ignored_type;
+
+ value = strtok(buffer, " \t\n");
+ ignored_type = strtok(0, " \t\n");
+ symbol = strtok(0, " \t\n");
+
+ if (symbol && ignored_type && value)
+ {
+ rtems_symbol_t *sp;
+ sp = rtems_symbol_create(rtems_monitor_symbols,
+ symbol,
+ (uint32_t ) strtoul(value, 0, 16));
+ if (sp == 0)
+ {
+ fprintf(stdout,"could not define symbol '%s'\n", symbol);
+ goto done;
+ }
+ }
+ else
+ {
+ fprintf(stdout,"parsing error on '%s'\n", buffer);
+ goto done;
+ }
+ }
+
+done:
+ return;
+}
+
+/*
+ * User registered commands.
+ */
+
+int
+rtems_monitor_insert_cmd (
+ rtems_monitor_command_entry_t *command
+)
+{
+ rtems_monitor_command_entry_t **p = &rtems_registered_commands.next;
+
+ command->next = 0;
+
+ while (*p) {
+ if ( STREQ(command->command, (*p)->command) )
+ return 0;
+ p = & (*p)->next;
+ }
+ *p = command;
+ return 1;
+}
+
+int
+rtems_monitor_erase_cmd (
+ rtems_monitor_command_entry_t *command
+)
+{
+ rtems_monitor_command_entry_t **p = & rtems_registered_commands.next;
+
+ while (*p) {
+ if ( STREQ(command->command, (*p)->command) ) {
+ *p = (*p)->next;
+ command->next = 0;
+ return 1;
+ }
+ p = & (*p)->next;
+ }
+ return 0;
+
+}
+
+/*
+ * Main monitor command loop
+ */
+
+void
+rtems_monitor_task(
+ rtems_task_argument monitor_flags
+)
+{
+ rtems_tcb *debugee = 0;
+ rtems_context *rp;
+ rtems_context_fp *fp;
+ char command_buffer[513];
+ int argc;
+ char *argv[64];
+ boolean verbose = FALSE;
+ struct termios term;
+
+ /*
+ * Make the stdin stream characte not line based.
+ */
+
+ if (tcgetattr (STDIN_FILENO, &term) < 0)
+ {
+ fprintf(stdout,"rtems-monitor: cannot get terminal attributes.\n");
+ }
+ else
+ {
+ /*
+ * No echo, no canonical processing.
+ */
+
+ term.c_lflag &= ~(ECHO | ICANON | IEXTEN);
+
+ /*
+ * No sigint on BREAK, CR-to-NL off, input parity off,
+ * don't strip 8th bit on input, output flow control off
+ */
+
+ term.c_lflag &= ~(INPCK | ISTRIP | IXON);
+ term.c_cc[VMIN] = 1;
+ term.c_cc[VTIME] = 0;
+
+ if (tcsetattr (STDIN_FILENO, TCSANOW, &term) < 0)
+ {
+ fprintf(stdout,"cannot set terminal attributes\n");
+ }
+ }
+
+ if (monitor_flags & RTEMS_MONITOR_SUSPEND)
+ (void) rtems_monitor_suspend(RTEMS_NO_TIMEOUT);
+
+ for (;;)
+ {
+ extern rtems_tcb * _Thread_Executing;
+ rtems_monitor_command_entry_t *command;
+
+ debugee = _Thread_Executing;
+ rp = &debugee->Registers;
+#if (CPU_HARDWARE_FP == TRUE) || (CPU_SOFTWARE_FP == TRUE)
+ fp = debugee->fp_context; /* possibly 0 */
+#else
+ fp = 0;
+#endif
+
+ if (0 == rtems_monitor_command_read(command_buffer, &argc, argv))
+ continue;
+ if ((command = rtems_monitor_command_lookup(rtems_monitor_commands,
+ argc,
+ argv)) == 0)
+ {
+ /* no command */
+ fprintf(stdout,"Unrecognised command; try 'help'\n");
+ continue;
+ }
+
+ command->command_function(argc, argv, &command->command_arg, verbose);
+
+ fflush(stdout);
+ }
+}
+
+
+void
+rtems_monitor_kill(void)
+{
+ if (rtems_monitor_task_id)
+ rtems_task_delete(rtems_monitor_task_id);
+ rtems_monitor_task_id = 0;
+
+ rtems_monitor_server_kill();
+}
+
+void
+rtems_monitor_init(
+ uint32_t monitor_flags
+)
+{
+ rtems_status_code status;
+
+ rtems_monitor_kill();
+
+ status = rtems_task_create(RTEMS_MONITOR_NAME,
+ 1,
+ RTEMS_MINIMUM_STACK_SIZE * 2,
+ RTEMS_INTERRUPT_LEVEL(0),
+ RTEMS_DEFAULT_ATTRIBUTES,
+ &rtems_monitor_task_id);
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ rtems_error(status, "could not create monitor task");
+ return;
+ }
+
+ rtems_monitor_node = rtems_get_node(rtems_monitor_task_id);
+ rtems_monitor_default_node = rtems_monitor_node;
+
+ rtems_monitor_symbols_loadup();
+
+ if (monitor_flags & RTEMS_MONITOR_GLOBAL)
+ rtems_monitor_server_init(monitor_flags);
+
+ /*
+ * Start the monitor task itself
+ */
+
+ status = rtems_task_start(rtems_monitor_task_id,
+ rtems_monitor_task,
+ monitor_flags);
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ rtems_error(status, "could not start monitor");
+ return;
+ }
+}
diff --git a/cpukit/libmisc/monitor/mon-mpci.c b/cpukit/libmisc/monitor/mon-mpci.c
new file mode 100644
index 0000000000..2cbd48eb3c
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-mpci.c
@@ -0,0 +1,162 @@
+/*
+ * RTEMS MPCI Config display support
+ *
+ * TODO
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#include <rtems.h>
+#include <rtems/monitor.h>
+
+#include <stdio.h>
+#include <stdlib.h> /* strtoul() */
+
+#define DATACOL 15
+
+/*
+ * Fill in entire monitor config table
+ * for sending to a remote monitor or printing on the local system
+ */
+
+void
+rtems_monitor_mpci_canonical(
+ rtems_monitor_mpci_t *canonical_mpci,
+ void *config_void
+)
+{
+ rtems_configuration_table *c = _Configuration_Table;
+ rtems_multiprocessing_table *m;
+ rtems_mpci_table *mt;
+
+ m = c->User_multiprocessing_table;
+ if (m == 0)
+ return;
+ mt = m->User_mpci_table;
+
+ canonical_mpci->node = m->node;
+ canonical_mpci->maximum_nodes = m->maximum_nodes;
+ canonical_mpci->maximum_global_objects = m->maximum_global_objects;
+ canonical_mpci->maximum_proxies = m->maximum_proxies;
+
+ canonical_mpci->default_timeout = mt->default_timeout;
+ canonical_mpci->maximum_packet_size = mt->maximum_packet_size;
+
+ rtems_monitor_symbol_canonical_by_value(&canonical_mpci->initialization,
+ (void *) mt->initialization);
+
+ rtems_monitor_symbol_canonical_by_value(&canonical_mpci->get_packet,
+ (void *) mt->get_packet);
+ rtems_monitor_symbol_canonical_by_value(&canonical_mpci->return_packet,
+ (void *) mt->return_packet);
+ rtems_monitor_symbol_canonical_by_value(&canonical_mpci->send_packet,
+ (void *) mt->send_packet);
+ rtems_monitor_symbol_canonical_by_value(&canonical_mpci->receive_packet,
+ (void *) mt->receive_packet);
+}
+
+/*
+ * This is easy, since there is only 1 (altho we could get them from
+ * other nodes...)
+ */
+
+void *
+rtems_monitor_mpci_next(
+ void *object_info,
+ rtems_monitor_mpci_t *canonical_mpci,
+ rtems_id *next_id
+)
+{
+ rtems_configuration_table *c = _Configuration_Table;
+ int n = rtems_get_index(*next_id);
+
+ if (n >= 1)
+ goto failed;
+
+ if ( ! c->User_multiprocessing_table)
+ goto failed;
+
+ _Thread_Disable_dispatch();
+
+ *next_id += 1;
+ return (void *) c;
+
+failed:
+ *next_id = RTEMS_OBJECT_ID_FINAL;
+ return 0;
+}
+
+
+void
+rtems_monitor_mpci_dump_header(
+ boolean verbose
+)
+{
+ fprintf(stdout,"\
+ max max max default max\n\
+ node nodes globals proxies timeout pktsize\n");
+/*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
+0 1 2 3 4 5 6 7 */
+
+ rtems_monitor_separator();
+}
+
+
+void
+rtems_monitor_mpci_dump(
+ rtems_monitor_mpci_t *monitor_mpci,
+ boolean verbose
+)
+{
+ uint32_t length = 0;
+
+ length += rtems_monitor_pad(2, length);
+ length += fprintf(stdout," %d", monitor_mpci->node);
+ length += rtems_monitor_pad(11, length);
+ length += fprintf(stdout,"%d", monitor_mpci->maximum_nodes);
+
+ length += rtems_monitor_pad(18, length);
+ length += rtems_monitor_dump_decimal(monitor_mpci->maximum_global_objects);
+
+ length += rtems_monitor_pad(28, length);
+ length += rtems_monitor_dump_decimal(monitor_mpci->maximum_proxies);
+
+ length += rtems_monitor_pad(37, length);
+ length += rtems_monitor_dump_decimal(monitor_mpci->default_timeout);
+
+ length += rtems_monitor_pad(46, length);
+ length += rtems_monitor_dump_decimal(monitor_mpci->maximum_packet_size);
+
+ fprintf(stdout,"\n");
+ length = 0;
+ length += rtems_monitor_pad(DATACOL, length);
+
+ length += fprintf(stdout,"init: ");
+ length += rtems_monitor_symbol_dump(&monitor_mpci->initialization, verbose);
+
+ fprintf(stdout,"\n");
+ length = 0;
+ length += rtems_monitor_pad(DATACOL, length);
+
+ length += fprintf(stdout,"get: ");
+ length += rtems_monitor_symbol_dump(&monitor_mpci->get_packet, verbose);
+ length += fprintf(stdout,"; return: ");
+ length += rtems_monitor_symbol_dump(&monitor_mpci->return_packet, verbose);
+
+ fprintf(stdout,"\n");
+ length = 0;
+ length += rtems_monitor_pad(DATACOL, length);
+
+ length += fprintf(stdout,"send: ");
+ length += rtems_monitor_symbol_dump(&monitor_mpci->send_packet, verbose);
+ length += fprintf(stdout,"; receive: ");
+ length += rtems_monitor_symbol_dump(&monitor_mpci->receive_packet, verbose);
+
+ fprintf(stdout,"\n");
+ length = 0;
+}
diff --git a/cpukit/libmisc/monitor/mon-object.c b/cpukit/libmisc/monitor/mon-object.c
new file mode 100644
index 0000000000..4428234220
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-object.c
@@ -0,0 +1,387 @@
+/*
+ * RTEMS Monitor "object" support.
+ *
+ * Used to traverse object lists and print them out.
+ * An object can be an RTEMS object (chain based stuff) or
+ * a "misc" object such as a device driver.
+ *
+ * Each object has its own file in this directory (eg: extension.c)
+ * That file provides routines to convert a "native" structure
+ * to its canonical form, print a canonical structure, etc.
+ *
+ * TODO:
+ * should allow for non-numeric id's???
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#include <rtems.h>
+#include <rtems/monitor.h>
+
+#include <stdio.h>
+#include <stdlib.h> /* strtoul() */
+#include <string.h> /* memcpy() */
+
+#define NUMELEMS(arr) (sizeof(arr) / sizeof(arr[0]))
+
+/*
+ * add:
+ * next
+ */
+
+rtems_monitor_object_info_t rtems_monitor_object_info[] =
+{
+ { RTEMS_MONITOR_OBJECT_CONFIG,
+ (void *) 0,
+ sizeof(rtems_monitor_config_t),
+ (rtems_monitor_object_next_fn) rtems_monitor_config_next,
+ (rtems_monitor_object_canonical_fn) rtems_monitor_config_canonical,
+ (rtems_monitor_object_dump_header_fn) rtems_monitor_config_dump_header,
+ (rtems_monitor_object_dump_fn) rtems_monitor_config_dump,
+ },
+ { RTEMS_MONITOR_OBJECT_MPCI,
+ (void *) 0,
+#if defined(RTEMS_MULTIPROCESSING)
+ sizeof(rtems_monitor_mpci_t),
+ (rtems_monitor_object_next_fn) rtems_monitor_mpci_next,
+ (rtems_monitor_object_canonical_fn) rtems_monitor_mpci_canonical,
+ (rtems_monitor_object_dump_header_fn) rtems_monitor_mpci_dump_header,
+ (rtems_monitor_object_dump_fn) rtems_monitor_mpci_dump,
+#else
+ 0,
+ (rtems_monitor_object_next_fn) 0,
+ (rtems_monitor_object_canonical_fn) 0,
+ (rtems_monitor_object_dump_header_fn) 0,
+ (rtems_monitor_object_dump_fn) 0,
+#endif
+ },
+ { RTEMS_MONITOR_OBJECT_INIT_TASK,
+ (void *) 0,
+ sizeof(rtems_monitor_init_task_t),
+ (rtems_monitor_object_next_fn) rtems_monitor_init_task_next,
+ (rtems_monitor_object_canonical_fn) rtems_monitor_init_task_canonical,
+ (rtems_monitor_object_dump_header_fn) rtems_monitor_init_task_dump_header,
+ (rtems_monitor_object_dump_fn) rtems_monitor_init_task_dump,
+ },
+ { RTEMS_MONITOR_OBJECT_TASK,
+ (void *) &_RTEMS_tasks_Information,
+ sizeof(rtems_monitor_task_t),
+ (rtems_monitor_object_next_fn) rtems_monitor_manager_next,
+ (rtems_monitor_object_canonical_fn) rtems_monitor_task_canonical,
+ (rtems_monitor_object_dump_header_fn) rtems_monitor_task_dump_header,
+ (rtems_monitor_object_dump_fn) rtems_monitor_task_dump,
+ },
+ { RTEMS_MONITOR_OBJECT_QUEUE,
+ (void *) &_Message_queue_Information,
+ sizeof(rtems_monitor_queue_t),
+ (rtems_monitor_object_next_fn) rtems_monitor_manager_next,
+ (rtems_monitor_object_canonical_fn) rtems_monitor_queue_canonical,
+ (rtems_monitor_object_dump_header_fn) rtems_monitor_queue_dump_header,
+ (rtems_monitor_object_dump_fn) rtems_monitor_queue_dump,
+ },
+ { RTEMS_MONITOR_OBJECT_EXTENSION,
+ (void *) &_Extension_Information,
+ sizeof(rtems_monitor_extension_t),
+ (rtems_monitor_object_next_fn) rtems_monitor_manager_next,
+ (rtems_monitor_object_canonical_fn) rtems_monitor_extension_canonical,
+ (rtems_monitor_object_dump_header_fn) rtems_monitor_extension_dump_header,
+ (rtems_monitor_object_dump_fn) rtems_monitor_extension_dump,
+ },
+ { RTEMS_MONITOR_OBJECT_DRIVER,
+ (void *) 0,
+ sizeof(rtems_monitor_driver_t),
+ (rtems_monitor_object_next_fn) rtems_monitor_driver_next,
+ (rtems_monitor_object_canonical_fn) rtems_monitor_driver_canonical,
+ (rtems_monitor_object_dump_header_fn) rtems_monitor_driver_dump_header,
+ (rtems_monitor_object_dump_fn) rtems_monitor_driver_dump,
+ },
+ { RTEMS_MONITOR_OBJECT_DNAME,
+ /* XXX now that the driver name table is allocated from the */
+ /* XXX Workspace, this does not work */
+ (void *) 0,
+ /* (void *) _IO_Driver_name_table, */
+ sizeof(rtems_monitor_dname_t),
+ (rtems_monitor_object_next_fn) rtems_monitor_dname_next,
+ (rtems_monitor_object_canonical_fn) rtems_monitor_dname_canonical,
+ (rtems_monitor_object_dump_header_fn) rtems_monitor_dname_dump_header,
+ (rtems_monitor_object_dump_fn) rtems_monitor_dname_dump,
+ },
+};
+
+/*
+ * Allow id's to be specified without the node number or
+ * type for convenience.
+ */
+
+rtems_id
+rtems_monitor_id_fixup(
+ rtems_id id,
+ uint32_t default_node,
+ rtems_monitor_object_type_t type
+)
+{
+ uint32_t node;
+
+ node = rtems_get_node(id);
+ if (node == 0)
+ {
+ if (rtems_get_class(id) != OBJECTS_NO_CLASS)
+ type = rtems_get_class(id);
+
+ id = _Objects_Build_id(
+ OBJECTS_CLASSIC_API, type, default_node, rtems_get_index(id));
+ }
+ return id;
+}
+
+
+rtems_monitor_object_info_t *
+rtems_monitor_object_lookup(
+ rtems_monitor_object_type_t type
+)
+{
+ rtems_monitor_object_info_t *p;
+ for (p = &rtems_monitor_object_info[0];
+ p < &rtems_monitor_object_info[NUMELEMS(rtems_monitor_object_info)];
+ p++)
+ {
+ if (p->type == type)
+ return p;
+ }
+ return 0;
+}
+
+rtems_id
+rtems_monitor_object_canonical_next_remote(
+ rtems_monitor_object_type_t type,
+ rtems_id id,
+ void *canonical
+)
+{
+ rtems_id next_id;
+ rtems_status_code status;
+ rtems_monitor_server_request_t request;
+ rtems_monitor_server_response_t response;
+
+ /*
+ * Send request
+ */
+
+ request.command = RTEMS_MONITOR_SERVER_CANONICAL;
+ request.argument0 = (uint32_t ) type;
+ request.argument1 = (uint32_t ) id;
+
+ status = rtems_monitor_server_request(rtems_get_node(id), &request, &response);
+ if (status != RTEMS_SUCCESSFUL)
+ goto failed;
+
+ /*
+ * process response
+ */
+
+ next_id = (rtems_id) response.result0;
+ if (next_id != RTEMS_OBJECT_ID_FINAL)
+ (void) memcpy(canonical, &response.payload, response.result1);
+
+ return next_id;
+
+failed:
+ return RTEMS_OBJECT_ID_FINAL;
+
+}
+
+
+rtems_id
+rtems_monitor_object_canonical_next(
+ rtems_monitor_object_info_t *info,
+ rtems_id id,
+ void *canonical
+)
+{
+ rtems_id next_id;
+ void *raw_item;
+
+ if ( ! _Objects_Is_local_id(id))
+ next_id = rtems_monitor_object_canonical_next_remote(info->type,
+ id,
+ canonical);
+ else
+ {
+ next_id = id;
+
+ raw_item = (void *) info->next(info->object_information,
+ canonical,
+ &next_id);
+
+ if (raw_item)
+ {
+ info->canonical(canonical, raw_item);
+ _Thread_Enable_dispatch();
+ }
+ }
+ return next_id;
+}
+
+
+/*
+ * this is routine server invokes locally to get the type
+ */
+
+rtems_id
+rtems_monitor_object_canonical_get(
+ rtems_monitor_object_type_t type,
+ rtems_id id,
+ void *canonical,
+ uint32_t *size_p
+)
+{
+ rtems_monitor_object_info_t *info;
+ rtems_id next_id;
+
+ *size_p = 0;
+
+ info = rtems_monitor_object_lookup(type);
+
+ if (info == 0)
+ return RTEMS_OBJECT_ID_FINAL;
+
+ next_id = rtems_monitor_object_canonical_next(info, id, canonical);
+ *size_p = info->size;
+
+ return next_id;
+}
+
+
+void
+rtems_monitor_object_dump_1(
+ rtems_monitor_object_info_t *info,
+ rtems_id id,
+ boolean verbose
+)
+{
+ rtems_id next_id;
+ rtems_monitor_union_t canonical;
+
+ if ((next_id = rtems_monitor_object_canonical_next(
+ info,
+ id,
+ &canonical)) != RTEMS_OBJECT_ID_FINAL)
+ {
+ /*
+ * If the one we actually got is the one we wanted, then
+ * print it out.
+ * For ones that have an id field, this works fine,
+ * for all others, always dump it out.
+ *
+ * HACK: the way we determine whether there is an id is a hack.
+ *
+ * by the way: the reason we try to not have an id, is that some
+ * of the canonical structures are almost too big for shared
+ * memory driver (eg: mpci)
+ */
+
+ if ((info->next != rtems_monitor_manager_next) ||
+ (id == canonical.generic.id))
+ info->dump(&canonical, verbose);
+ }
+}
+
+void
+rtems_monitor_object_dump_all(
+ rtems_monitor_object_info_t *info,
+ boolean verbose
+)
+{
+ rtems_id next_id;
+ rtems_monitor_union_t canonical;
+
+ next_id = RTEMS_OBJECT_ID_INITIAL(OBJECTS_CLASSIC_API, info->type, rtems_monitor_default_node);
+
+ while ((next_id = rtems_monitor_object_canonical_next(
+ info,
+ next_id,
+ &canonical)) != RTEMS_OBJECT_ID_FINAL)
+ {
+ info->dump(&canonical, verbose);
+ }
+}
+
+void
+rtems_monitor_object_cmd(
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose
+)
+{
+ int arg;
+ rtems_monitor_object_info_t *info = 0;
+ rtems_monitor_object_type_t type ;
+
+ /* what is the default type? */
+ type = command_arg->monitor_object;
+
+ if (argc == 1)
+ {
+ if (type == RTEMS_MONITOR_OBJECT_INVALID)
+ {
+ fprintf(stdout,"A type must be specified to \"dump all\"\n");
+ goto done;
+ }
+
+ info = rtems_monitor_object_lookup(type);
+ if (info == 0)
+ goto not_found;
+
+ if (info->dump_header)
+ info->dump_header(verbose);
+ rtems_monitor_object_dump_all(info, verbose);
+ }
+ else
+ {
+ uint32_t default_node = rtems_monitor_default_node;
+ rtems_monitor_object_type_t last_type = RTEMS_MONITOR_OBJECT_INVALID;
+ rtems_id id;
+
+ for (arg=1; argv[arg]; arg++)
+ {
+ id = (rtems_id) strtoul(argv[arg], 0, 16);
+ id = rtems_monitor_id_fixup(id, default_node, type);
+ type = (rtems_monitor_object_type_t) rtems_get_class(id);
+
+ /*
+ * Allow the item type to change in the middle
+ * of the command. If the type changes, then
+ * just dump out a new header and keep on going.
+ */
+ if (type != last_type)
+ {
+ info = rtems_monitor_object_lookup(type);
+ if (info == 0)
+ goto not_found;
+
+ if (info->dump_header)
+ info->dump_header(verbose);
+ }
+
+ if (info == 0)
+ {
+not_found: fprintf(stdout,"Invalid or unsupported type %d\n", type);
+ goto done;
+ }
+
+ rtems_monitor_object_dump_1(info, id, verbose);
+
+ default_node = rtems_get_node(id);
+
+ last_type = type;
+ }
+ }
+done:
+ return;
+}
diff --git a/cpukit/libmisc/monitor/mon-prmisc.c b/cpukit/libmisc/monitor/mon-prmisc.c
new file mode 100644
index 0000000000..5104962650
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-prmisc.c
@@ -0,0 +1,268 @@
+/*
+ * Print misc stuff for the monitor dump routines
+ * Each routine returns the number of characters it output.
+ *
+ * TODO:
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/monitor.h>
+
+#include <rtems/assoc.h>
+
+#include <stdio.h>
+#include <ctype.h>
+
+void
+rtems_monitor_separator(void)
+{
+ fprintf(stdout,"------------------------------------------------------------------------------\n");
+}
+
+uint32_t
+rtems_monitor_pad(
+ uint32_t destination_column,
+ uint32_t current_column
+)
+{
+ int pad_length;
+
+ if (destination_column <= current_column)
+ pad_length = 1;
+ else
+ pad_length = destination_column - current_column;
+
+ return fprintf(stdout,"%*s", pad_length, "");
+}
+
+uint32_t
+rtems_monitor_dump_char(uint8_t ch)
+{
+ if (isprint(ch))
+ return fprintf(stdout,"%c", ch);
+ else
+ return fprintf(stdout,"%02x", ch);
+}
+
+uint32_t
+rtems_monitor_dump_decimal(uint32_t num)
+{
+ return fprintf(stdout,"%4d", num);
+}
+
+uint32_t
+rtems_monitor_dump_hex(uint32_t num)
+{
+ return fprintf(stdout,"0x%x", num);
+}
+
+uint32_t
+rtems_monitor_dump_assoc_bitfield(
+ rtems_assoc_t *ap,
+ char *separator,
+ uint32_t value
+ )
+{
+ uint32_t b;
+ uint32_t length = 0;
+ const char *name;
+
+ for (b = 1; b; b <<= 1)
+ if (b & value)
+ {
+ if (length)
+ length += fprintf(stdout,"%s", separator);
+
+ name = rtems_assoc_name_by_local(ap, b);
+
+ if (name)
+ length += fprintf(stdout,"%s", name);
+ else
+ length += fprintf(stdout,"0x%x", b);
+ }
+
+ return length;
+}
+
+uint32_t
+rtems_monitor_dump_id(rtems_id id)
+{
+ return fprintf(stdout,"%08x", id);
+}
+
+uint32_t
+rtems_monitor_dump_name(rtems_name name)
+{
+ uint32_t i;
+ uint32_t length = 0;
+ union {
+ uint32_t ui;
+ char c[4];
+ } u;
+
+ u.ui = (uint32_t ) name;
+
+#if (CPU_BIG_ENDIAN == TRUE)
+ for (i=0; i<sizeof(u.c); i++)
+ length += rtems_monitor_dump_char(u.c[i]);
+#else
+ for (i=0; i<sizeof(u.c); i++)
+ length += rtems_monitor_dump_char(u.c[sizeof(u.c)-1-i]);
+#endif
+ return length;
+}
+
+uint32_t
+rtems_monitor_dump_priority(rtems_task_priority priority)
+{
+ return fprintf(stdout,"%3d", priority);
+}
+
+
+rtems_assoc_t rtems_monitor_state_assoc[] = {
+ { "DORM", STATES_DORMANT },
+ { "SUSP", STATES_SUSPENDED },
+ { "TRANS", STATES_TRANSIENT },
+ { "DELAY", STATES_DELAYING },
+ { "Wbuf", STATES_WAITING_FOR_BUFFER },
+ { "Wseg", STATES_WAITING_FOR_SEGMENT },
+ { "Wmsg" , STATES_WAITING_FOR_MESSAGE },
+ { "Wevnt", STATES_WAITING_FOR_EVENT },
+ { "Wsem", STATES_WAITING_FOR_SEMAPHORE },
+ { "Wtime", STATES_WAITING_FOR_TIME },
+ { "Wrpc", STATES_WAITING_FOR_RPC_REPLY },
+ { "Wmutex", STATES_WAITING_FOR_MUTEX },
+ { "Wcvar", STATES_WAITING_FOR_CONDITION_VARIABLE },
+ { "Wjatx", STATES_WAITING_FOR_JOIN_AT_EXIT },
+ { "Wsig", STATES_WAITING_FOR_SIGNAL },
+ { "WRATE", STATES_WAITING_FOR_PERIOD },
+ { "Wisig", STATES_INTERRUPTIBLE_BY_SIGNAL },
+ { 0, 0, 0 },
+};
+
+uint32_t
+rtems_monitor_dump_state(States_Control state)
+{
+ uint32_t length = 0;
+
+ if (state == STATES_READY) /* assoc doesn't deal with this as it is 0 */
+ length += fprintf(stdout,"READY");
+
+ length += rtems_monitor_dump_assoc_bitfield(rtems_monitor_state_assoc,
+ ":",
+ state);
+ return length;
+}
+
+rtems_assoc_t rtems_monitor_attribute_assoc[] = {
+ { "FL", RTEMS_FLOATING_POINT },
+ { "GL", RTEMS_GLOBAL },
+ { "PR", RTEMS_PRIORITY },
+ { "BI", RTEMS_BINARY_SEMAPHORE },
+ { "IN", RTEMS_INHERIT_PRIORITY },
+ { 0, 0, 0 },
+};
+
+uint32_t
+rtems_monitor_dump_attributes(rtems_attribute attributes)
+{
+ uint32_t length = 0;
+
+ if (attributes == RTEMS_DEFAULT_ATTRIBUTES) /* value is 0 */
+ length += fprintf(stdout,"DEFAULT");
+
+ length += rtems_monitor_dump_assoc_bitfield(rtems_monitor_attribute_assoc,
+ ":",
+ attributes);
+ return length;
+}
+
+rtems_assoc_t rtems_monitor_modes_assoc[] = {
+ { "nP", RTEMS_NO_PREEMPT },
+ { "T", RTEMS_TIMESLICE },
+ { "nA", RTEMS_NO_ASR },
+ { 0, 0, 0 },
+};
+
+uint32_t
+rtems_monitor_dump_modes(rtems_mode modes)
+{
+ uint32_t length = 0;
+
+ if (modes == RTEMS_DEFAULT_MODES) /* value is 0 */
+ length += fprintf(stdout,"P:T:nA");
+
+ length += rtems_monitor_dump_assoc_bitfield(rtems_monitor_modes_assoc,
+ ":",
+ modes);
+ return length;
+}
+
+rtems_assoc_t rtems_monitor_events_assoc[] = {
+ { "0", RTEMS_EVENT_0 },
+ { "1", RTEMS_EVENT_1 },
+ { "2", RTEMS_EVENT_2 },
+ { "3", RTEMS_EVENT_3 },
+ { "4", RTEMS_EVENT_4 },
+ { "5", RTEMS_EVENT_5 },
+ { "6", RTEMS_EVENT_6 },
+ { "7", RTEMS_EVENT_7 },
+ { "8", RTEMS_EVENT_8 },
+ { "9", RTEMS_EVENT_9 },
+ { "10", RTEMS_EVENT_10 },
+ { "11", RTEMS_EVENT_11 },
+ { "12", RTEMS_EVENT_12 },
+ { "13", RTEMS_EVENT_13 },
+ { "14", RTEMS_EVENT_14 },
+ { "15", RTEMS_EVENT_15 },
+ { "16", RTEMS_EVENT_16 },
+ { "17", RTEMS_EVENT_17 },
+ { "18", RTEMS_EVENT_18 },
+ { "19", RTEMS_EVENT_19 },
+ { "20", RTEMS_EVENT_20 },
+ { "21", RTEMS_EVENT_21 },
+ { "22", RTEMS_EVENT_22 },
+ { "23", RTEMS_EVENT_23 },
+ { "24", RTEMS_EVENT_24 },
+ { "25", RTEMS_EVENT_25 },
+ { "26", RTEMS_EVENT_26 },
+ { "27", RTEMS_EVENT_27 },
+ { "28", RTEMS_EVENT_28 },
+ { "29", RTEMS_EVENT_29 },
+ { "30", RTEMS_EVENT_30 },
+ { "31", RTEMS_EVENT_31 },
+ { 0, 0, 0 },
+};
+
+uint32_t
+rtems_monitor_dump_events(rtems_event_set events)
+{
+ uint32_t length = 0;
+
+ if (events == EVENT_SETS_NONE_PENDING) /* value is 0 */
+ length += fprintf(stdout,"NONE");
+
+ length += rtems_monitor_dump_assoc_bitfield(rtems_monitor_events_assoc,
+ ":",
+ events);
+ return length;
+}
+
+uint32_t
+rtems_monitor_dump_notepad(uint32_t *notepad)
+{
+ uint32_t length = 0;
+ int i;
+
+ for (i=0; i < RTEMS_NUMBER_NOTEPADS; i++)
+ if (notepad[i])
+ length += fprintf(stdout,"%d: 0x%x ", i, notepad[i]);
+
+ return length;
+}
diff --git a/cpukit/libmisc/monitor/mon-queue.c b/cpukit/libmisc/monitor/mon-queue.c
new file mode 100644
index 0000000000..1714808fd8
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-queue.c
@@ -0,0 +1,68 @@
+/*
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/monitor.h>
+
+#include <stdio.h>
+
+void
+rtems_monitor_queue_canonical(
+ rtems_monitor_queue_t *canonical_queue,
+ void *queue_void
+)
+{
+ Message_queue_Control *rtems_queue = (Message_queue_Control *) queue_void;
+
+ canonical_queue->attributes = rtems_queue->attribute_set;
+ canonical_queue->maximum_message_size = rtems_queue->message_queue.maximum_message_size;
+ canonical_queue->maximum_pending_messages = rtems_queue->message_queue.maximum_pending_messages;
+ canonical_queue->number_of_pending_messages = rtems_queue->message_queue.number_of_pending_messages;
+}
+
+void
+rtems_monitor_queue_dump_header(
+ boolean verbose
+)
+{
+ fprintf(stdout,"\
+ ID NAME ATTRIBUTES PEND MAXPEND MAXSIZE\n");
+/*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
+0 1 2 3 4 5 6 7 */
+ rtems_monitor_separator();
+}
+
+
+/*
+ * Dump out the "next" queue indicated by 'id'.
+ * Returns next one to check.
+ * Returns RTEMS_OBJECT_ID_FINAL when all done
+ */
+
+void
+rtems_monitor_queue_dump(
+ rtems_monitor_queue_t *monitor_queue,
+ boolean verbose
+)
+{
+ uint32_t length = 0;
+
+ length += rtems_monitor_dump_id(monitor_queue->id);
+ length += rtems_monitor_pad(11, length);
+ length += rtems_monitor_dump_name(monitor_queue->name);
+ length += rtems_monitor_pad(19, length);
+ length += rtems_monitor_dump_attributes(monitor_queue->attributes);
+ length += rtems_monitor_pad(31, length);
+ length += rtems_monitor_dump_decimal(monitor_queue->number_of_pending_messages);
+ length += rtems_monitor_pad(39, length);
+ length += rtems_monitor_dump_decimal(monitor_queue->maximum_pending_messages);
+ length += rtems_monitor_pad(48, length);
+ length += rtems_monitor_dump_decimal(monitor_queue->maximum_message_size);
+
+ fprintf(stdout,"\n");
+}
diff --git a/cpukit/libmisc/monitor/mon-server.c b/cpukit/libmisc/monitor/mon-server.c
new file mode 100644
index 0000000000..b04e5f2390
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-server.c
@@ -0,0 +1,307 @@
+/*
+ * RTEMS monitor server (handles requests for info from RTEMS monitors
+ * running on other nodes)
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <rtems/monitor.h>
+
+/*
+ * Various id's for the server
+ */
+
+rtems_id rtems_monitor_server_task_id;
+rtems_id rtems_monitor_server_request_queue_id; /* our server */
+rtems_id *rtems_monitor_server_request_queue_ids; /* all servers */
+rtems_id rtems_monitor_server_response_queue_id; /* our server */
+
+
+/*
+ * Send a request to a server task
+ */
+
+rtems_status_code
+rtems_monitor_server_request(
+ uint32_t server_node,
+ rtems_monitor_server_request_t *request,
+ rtems_monitor_server_response_t *response
+)
+{
+ rtems_id server_id;
+ rtems_status_code status;
+ uint32_t size;
+
+ /*
+ * What is id of monitor on target node?
+ * Look it up if we don't know it yet.
+ */
+
+ server_id = rtems_monitor_server_request_queue_ids[server_node];
+ if (server_id == 0)
+ {
+ status = rtems_message_queue_ident(RTEMS_MONITOR_QUEUE_NAME,
+ server_node,
+ &server_id);
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ rtems_error(status, "ident of remote server failed");
+ goto done;
+ }
+
+ rtems_monitor_server_request_queue_ids[server_node] = server_id;
+ }
+
+ request->return_id = rtems_monitor_server_response_queue_id;
+
+ status = rtems_message_queue_send(server_id, request, sizeof(*request));
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ rtems_error(status, "monitor server request send failed");
+ goto done;
+ }
+
+ /*
+ * Await response, if requested
+ */
+
+ if (response)
+ {
+ status = rtems_message_queue_receive(rtems_monitor_server_response_queue_id,
+ response,
+ &size,
+ RTEMS_WAIT,
+ 100);
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ rtems_error(status, "server did not respond");
+
+ /* maybe server task was restarted; look it up again next time */
+ rtems_monitor_server_request_queue_ids[server_node] = 0;
+
+ goto done;
+ }
+
+ if (response->command != RTEMS_MONITOR_SERVER_RESPONSE)
+ {
+ status = RTEMS_INCORRECT_STATE;
+ goto done;
+ }
+ }
+
+done:
+ return status;
+}
+
+
+
+/*
+ * monitor server task
+ */
+
+void
+rtems_monitor_server_task(
+ rtems_task_argument monitor_flags
+)
+{
+ rtems_monitor_server_request_t request;
+ rtems_monitor_server_response_t response;
+ rtems_status_code status;
+ uint32_t size;
+
+ for (;;)
+ {
+ status = rtems_message_queue_receive(
+ rtems_monitor_server_request_queue_id,
+ &request,
+ &size,
+ RTEMS_WAIT,
+ (rtems_interval) 0);
+
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ rtems_error(status, "monitor server msg queue receive error");
+ goto failed;
+ }
+
+ if (size != sizeof(request))
+ {
+ rtems_error(0, "monitor server bad size on receive");
+ goto failed;
+ }
+
+ switch (request.command)
+ {
+ case RTEMS_MONITOR_SERVER_CANONICAL:
+ {
+ rtems_monitor_object_type_t object_type;
+ rtems_id id;
+ rtems_id next_id;
+
+ object_type = (rtems_monitor_object_type_t) request.argument0;
+ id = (rtems_id) request.argument1;
+ next_id = rtems_monitor_object_canonical_get(object_type,
+ id,
+ &response.payload,
+ &size);
+
+ response.command = RTEMS_MONITOR_SERVER_RESPONSE;
+ response.result0 = next_id;
+ response.result1 = size;
+
+#define SERVER_OVERHEAD (RTEMS_offsetof(rtems_monitor_server_response_t, \
+ payload))
+
+ status = rtems_message_queue_send(request.return_id,
+ &response,
+ size + SERVER_OVERHEAD);
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ rtems_error(status, "response send failed");
+ goto failed;
+ }
+ break;
+ }
+
+ default:
+ {
+ rtems_error(0, "invalid command to monitor server: %d", request.command);
+ goto failed;
+ }
+ }
+ }
+
+failed:
+ rtems_task_delete(RTEMS_SELF);
+}
+
+
+/*
+ * Kill off any old server
+ * Not sure if this is useful, but it doesn't help
+ */
+
+void
+rtems_monitor_server_kill(void)
+{
+ if (rtems_monitor_server_task_id)
+ rtems_task_delete(rtems_monitor_server_task_id);
+ rtems_monitor_server_task_id = 0;
+
+ if (rtems_monitor_server_request_queue_id)
+ rtems_message_queue_delete(rtems_monitor_server_request_queue_id);
+ rtems_monitor_server_request_queue_ids = 0;
+
+ if (rtems_monitor_server_response_queue_id)
+ rtems_message_queue_delete(rtems_monitor_server_response_queue_id);
+ rtems_monitor_server_response_queue_id = 0;
+
+ if (rtems_monitor_server_request_queue_ids)
+ free(rtems_monitor_server_request_queue_ids);
+ rtems_monitor_server_request_queue_ids = 0;
+}
+
+
+void
+rtems_monitor_server_init(
+ uint32_t monitor_flags
+)
+{
+ rtems_status_code status;
+
+ if (_System_state_Is_multiprocessing &&
+ (_Configuration_MP_table->maximum_nodes > 1))
+ {
+ uint32_t maximum_nodes = _Configuration_MP_table->maximum_nodes;
+
+ /*
+ * create the msg que our server will listen
+ * Since we only get msgs from other RTEMS monitors, we just
+ * need reserve space for 1 msg from each node.
+ */
+
+ status = rtems_message_queue_create(
+ RTEMS_MONITOR_QUEUE_NAME,
+ maximum_nodes,
+ sizeof(rtems_monitor_server_request_t),
+ RTEMS_GLOBAL,
+ &rtems_monitor_server_request_queue_id);
+
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ rtems_error(status, "could not create monitor server message queue");
+ goto done;
+ }
+
+ /*
+ * create the msg que our responses will come on
+ * Since monitor just does one thing at a time, we only need 1 item
+ * message queue.
+ */
+
+ status = rtems_message_queue_create(
+ RTEMS_MONITOR_RESPONSE_QUEUE_NAME,
+ 1, /* depth */
+ sizeof(rtems_monitor_server_response_t),
+ RTEMS_GLOBAL,
+ &rtems_monitor_server_response_queue_id);
+
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ rtems_error(status, "could not create monitor response message queue");
+ goto done;
+ }
+
+ /* need an id for queue of each other server we might talk to */
+ /* indexed by node, so add 1 to maximum_nodes */
+ rtems_monitor_server_request_queue_ids =
+ (rtems_id *) malloc((maximum_nodes + 1) * sizeof(rtems_id));
+ (void) memset(rtems_monitor_server_request_queue_ids,
+ 0,
+ (maximum_nodes + 1) * sizeof(rtems_id));
+
+ rtems_monitor_server_request_queue_ids[rtems_monitor_node] =
+ rtems_monitor_server_request_queue_id;
+
+ /*
+ * create the server task
+ */
+ status = rtems_task_create(RTEMS_MONITOR_SERVER_NAME,
+ 1,
+ 0 /* default stack */,
+ RTEMS_INTERRUPT_LEVEL(0),
+ RTEMS_DEFAULT_ATTRIBUTES,
+ &rtems_monitor_server_task_id);
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ rtems_error(status, "could not create monitor server task");
+ goto done;
+ }
+
+ /*
+ * Start the server task
+ */
+ status = rtems_task_start(rtems_monitor_server_task_id,
+ rtems_monitor_server_task,
+ monitor_flags);
+ if (status != RTEMS_SUCCESSFUL)
+ {
+ rtems_error(status, "could not start monitor server");
+ goto done;
+ }
+ }
+
+done:
+ return;
+}
diff --git a/cpukit/libmisc/monitor/mon-symbols.c b/cpukit/libmisc/monitor/mon-symbols.c
new file mode 100644
index 0000000000..b83d0243e3
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-symbols.c
@@ -0,0 +1,486 @@
+/*
+ * File: symbols.c
+ *
+ * Description:
+ * Symbol table manager for the RTEMS monitor.
+ * These routines may be used by other system resources also.
+ *
+ *
+ * TODO:
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
+#include <rtems.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <rtems/monitor.h>
+#include "symbols.h"
+
+
+rtems_symbol_table_t *
+rtems_symbol_table_create()
+{
+ rtems_symbol_table_t *table;
+
+ table = (rtems_symbol_table_t *) malloc(sizeof(rtems_symbol_table_t));
+ memset((void *) table, 0, sizeof(*table));
+
+ table->growth_factor = 30; /* 30 percent */
+
+ return table;
+}
+
+void
+rtems_symbol_table_destroy(rtems_symbol_table_t *table)
+{
+ rtems_symbol_string_block_t *p, *pnext;
+
+ if (table)
+ {
+ if (table->addresses)
+ (void) free(table->addresses);
+ table->addresses = 0;
+ p = table->string_buffer_head;
+ while (p)
+ {
+ pnext = p->next;
+ free(p);
+ p = pnext;
+ }
+ table->string_buffer_head = 0;
+ table->string_buffer_current = 0;
+
+ free(table);
+ }
+}
+
+rtems_symbol_t *
+rtems_symbol_create(
+ rtems_symbol_table_t *table,
+ char *name,
+ uint32_t value
+ )
+{
+ int symbol_length;
+ size_t newsize;
+ rtems_symbol_t *sp;
+
+ symbol_length = strlen(name) + 1; /* include '\000' in length */
+
+ /* need to grow the table? */
+ if (table->next >= table->size)
+ {
+ if (table->size == 0)
+ newsize = 100;
+ else
+ newsize = table->size + (table->size / (100 / table->growth_factor));
+
+ table->addresses = (rtems_symbol_t *) realloc((void *) table->addresses, newsize * sizeof(rtems_symbol_t));
+ if (table->addresses == 0) /* blew it; lost orig */
+ goto failed;
+ table->size = newsize;
+ }
+
+ sp = &table->addresses[table->next];
+ sp->value = value;
+
+ /* Have to add it to string pool */
+ /* need to grow pool? */
+
+ if ((table->string_buffer_head == 0) ||
+ (table->strings_next + symbol_length) >= SYMBOL_STRING_BLOCK_SIZE)
+ {
+ rtems_symbol_string_block_t *p;
+
+ p = (rtems_symbol_string_block_t *) malloc(sizeof(rtems_symbol_string_block_t));
+ if (p == 0)
+ goto failed;
+ p->next = 0;
+ if (table->string_buffer_head == 0)
+ table->string_buffer_head = p;
+ else
+ table->string_buffer_current->next = p;
+ table->string_buffer_current = p;
+
+ table->strings_next = 0;
+ }
+
+ sp->name = table->string_buffer_current->buffer + table->strings_next;
+ (void) strcpy(sp->name, name);
+
+ table->strings_next += symbol_length;
+ table->sorted = 0;
+ table->next++;
+
+ return sp;
+
+/* XXX Not sure what to do here. We've possibly destroyed the initial
+ symbol table due to realloc failure */
+failed:
+ return 0;
+}
+
+/*
+ * Qsort entry point for compare by address
+ */
+
+static int
+rtems_symbol_compare(const void *e1,
+ const void *e2)
+{
+ rtems_symbol_t *s1, *s2;
+ s1 = (rtems_symbol_t *) e1;
+ s2 = (rtems_symbol_t *) e2;
+
+ if (s1->value < s2->value)
+ return -1;
+ if (s1->value > s2->value)
+ return 1;
+ return 0;
+}
+
+
+/*
+ * Sort the symbol table using qsort
+ */
+
+static void
+rtems_symbol_sort(rtems_symbol_table_t *table)
+{
+ qsort((void *) table->addresses, (size_t) table->next,
+ sizeof(rtems_symbol_t), rtems_symbol_compare);
+ table->sorted = 1;
+}
+
+
+/*
+ * Search the symbol table by address
+ * This code based on CYGNUS newlib bsearch, but changed
+ * to allow for finding closest symbol <= key
+ */
+
+rtems_symbol_t *
+rtems_symbol_value_lookup(
+ rtems_symbol_table_t *table,
+ uint32_t value
+ )
+{
+ rtems_symbol_t *sp;
+ rtems_symbol_t *base;
+ rtems_symbol_t *best = 0;
+ uint32_t distance;
+ uint32_t best_distance = ~0;
+ uint32_t elements;
+
+ if (table == 0)
+ table = rtems_monitor_symbols;
+
+ if ((table == 0) || (table->size == 0))
+ return 0;
+
+ if (table->sorted == 0)
+ rtems_symbol_sort(table);
+
+ base = table->addresses;
+ elements = table->next;
+
+ while (elements)
+ {
+ sp = base + (elements / 2);
+ if (value < sp->value)
+ elements /= 2;
+ else if (value > sp->value)
+ {
+ distance = value - sp->value;
+ if (distance < best_distance)
+ {
+ best_distance = distance;
+ best = sp;
+ }
+ base = sp + 1;
+ elements = (elements / 2) - (elements % 2 ? 0 : 1);
+ }
+ else
+ return sp;
+ }
+
+ if (value == base->value)
+ return base;
+
+ return best;
+}
+
+/*
+ * Search the symbol table for the exact matching address.
+ * If the symbol table has already been sorted, then
+ * call the regular symbol value lookup, however, it it
+ * has not yet been sorted, search it sequentially.
+ * This routine is primarily used for low level symbol
+ * lookups (eg. from exception handler and interrupt routines)
+ * where the penality of sorted is not wanted and where
+ * an exact match is needed such that symbol table order
+ * is not important.
+ */
+const rtems_symbol_t *
+rtems_symbol_value_lookup_exact(
+ rtems_symbol_table_t *table,
+ uint32_t value
+ )
+{
+ uint32_t s;
+ rtems_symbol_t *sp;
+
+ if (table == 0)
+ {
+ table = rtems_monitor_symbols;
+ if (table == 0)
+ return NULL;
+ }
+
+ if (table->sorted)
+ {
+ sp = rtems_symbol_value_lookup(table, value);
+ if ( rtems_symbol_value(sp) == value )
+ return sp;
+ else
+ return NULL; /* not an exact match */
+ }
+
+ for (s = 0, sp = table->addresses; s < table->next; s++, sp++)
+ {
+ if ( sp->value == value )
+ return sp;
+ }
+
+ return NULL;
+
+}
+
+
+/*
+ * Search the symbol table by string name (case independent)
+ */
+
+rtems_symbol_t *
+rtems_symbol_name_lookup(
+ rtems_symbol_table_t *table,
+ char *name
+ )
+{
+ uint32_t s;
+ rtems_symbol_t *sp;
+
+ if (table == 0)
+ {
+ table = rtems_monitor_symbols;
+ if (table == 0)
+ return NULL;
+ }
+
+ for (s = 0, sp = table->addresses; s < table->next; s++, sp++)
+ {
+ if ( strcasecmp(sp->name, name) == 0 )
+ return sp;
+ }
+
+ return NULL;
+}
+
+void *
+rtems_monitor_symbol_next(
+ void *object_info,
+ rtems_monitor_symbol_t *canonical,
+ rtems_id *next_id
+)
+{
+ rtems_symbol_table_t *table;
+ uint32_t n = rtems_get_index(*next_id);
+
+ table = *(rtems_symbol_table_t **) object_info;
+ if (table == 0)
+ goto failed;
+
+ if (n >= table->next)
+ goto failed;
+
+ /* NOTE: symbols do not have id and name fields */
+
+ if (table->sorted == 0)
+ rtems_symbol_sort(table);
+
+ _Thread_Disable_dispatch();
+
+ *next_id += 1;
+ return (void *) (table->addresses + n);
+
+failed:
+ *next_id = RTEMS_OBJECT_ID_FINAL;
+ return 0;
+}
+
+void
+rtems_monitor_symbol_canonical(
+ rtems_monitor_symbol_t *canonical_symbol,
+ rtems_symbol_t *sp
+)
+{
+ canonical_symbol->value = sp->value;
+ canonical_symbol->offset = 0;
+ strncpy(canonical_symbol->name, sp->name, sizeof(canonical_symbol->name));
+}
+
+
+void
+rtems_monitor_symbol_canonical_by_name(
+ rtems_monitor_symbol_t *canonical_symbol,
+ char *name
+)
+{
+ rtems_symbol_t *sp;
+
+ sp = rtems_symbol_name_lookup(0, name);
+
+ canonical_symbol->value = sp ? sp->value : 0;
+
+ strncpy(canonical_symbol->name, name, sizeof(canonical_symbol->name));
+ canonical_symbol->offset = 0;
+}
+
+void
+rtems_monitor_symbol_canonical_by_value(
+ rtems_monitor_symbol_t *canonical_symbol,
+ void *value_void_p
+)
+{
+ uint32_t value = (uint32_t ) value_void_p;
+ rtems_symbol_t *sp;
+
+ sp = rtems_symbol_value_lookup(0, value);
+ if (sp)
+ {
+ canonical_symbol->value = sp->value;
+ canonical_symbol->offset = value - sp->value;
+ strncpy(canonical_symbol->name, sp->name, sizeof(canonical_symbol->name));
+ }
+ else
+ {
+ canonical_symbol->value = value;
+ canonical_symbol->offset = 0;
+ canonical_symbol->name[0] = '\0';
+ }
+}
+
+
+uint32_t
+rtems_monitor_symbol_dump(
+ rtems_monitor_symbol_t *canonical_symbol,
+ boolean verbose
+)
+{
+ uint32_t length = 0;
+
+ /*
+ * print the name if it exists AND if value is non-zero
+ * Ie: don't print some garbage symbol for address 0
+ */
+
+ if (canonical_symbol->name[0] && (canonical_symbol->value != 0))
+ {
+ if (canonical_symbol->offset == 0)
+ length += fprintf(stdout,"%.*s",
+ (int) sizeof(canonical_symbol->name),
+ canonical_symbol->name);
+ else
+ length += fprintf(stdout,"<%.*s+0x%x>",
+ (int) sizeof(canonical_symbol->name),
+ canonical_symbol->name,
+ canonical_symbol->offset);
+ if (verbose)
+ length += fprintf(stdout," [0x%x]", canonical_symbol->value);
+ }
+ else
+ length += fprintf(stdout,"[0x%x]", canonical_symbol->value);
+
+ return length;
+}
+
+
+void
+rtems_monitor_symbol_dump_all(
+ rtems_symbol_table_t *table,
+ boolean verbose
+)
+{
+ uint32_t s;
+ rtems_symbol_t *sp;
+
+ if (table == 0)
+ {
+ table = rtems_monitor_symbols;
+ if (table == 0)
+ return;
+ }
+
+ if (table->sorted == 0)
+ rtems_symbol_sort(table);
+
+ for (s = 0, sp = table->addresses; s < table->next; s++, sp++)
+ {
+ rtems_monitor_symbol_t canonical_symbol;
+
+ rtems_monitor_symbol_canonical(&canonical_symbol, sp);
+ rtems_monitor_symbol_dump(&canonical_symbol, TRUE);
+ fprintf(stdout,"\n");
+ }
+}
+
+
+/*
+ * 'symbol' command
+ */
+
+void
+rtems_monitor_symbol_cmd(
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t* command_arg,
+ boolean verbose
+)
+{
+ int arg;
+ rtems_symbol_table_t *table;
+
+ table = *command_arg->symbol_table;
+ if (table == 0)
+ {
+ table = rtems_monitor_symbols;
+ if (table == 0)
+ return;
+ }
+
+ /*
+ * Use object command to dump out whole symbol table
+ */
+ if (argc == 1)
+ rtems_monitor_symbol_dump_all(table, verbose);
+ else
+ {
+ rtems_monitor_symbol_t canonical_symbol;
+
+ for (arg=1; argv[arg]; arg++)
+ {
+ rtems_monitor_symbol_canonical_by_name(&canonical_symbol, argv[arg]);
+ rtems_monitor_symbol_dump(&canonical_symbol, verbose);
+ fprintf(stdout,"\n");
+ }
+ }
+}
diff --git a/cpukit/libmisc/monitor/mon-task.c b/cpukit/libmisc/monitor/mon-task.c
new file mode 100644
index 0000000000..98e097dc71
--- /dev/null
+++ b/cpukit/libmisc/monitor/mon-task.c
@@ -0,0 +1,96 @@
+/*
+ * RTEMS Monitor task support
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/monitor.h>
+
+#include <stdio.h>
+#include <string.h> /* memcpy() */
+
+void
+rtems_monitor_task_canonical(
+ rtems_monitor_task_t *canonical_task,
+ void *thread_void
+)
+{
+ Thread_Control *rtems_thread = (Thread_Control *) thread_void;
+ RTEMS_API_Control *api;
+
+ api = rtems_thread->API_Extensions[ THREAD_API_RTEMS ];
+
+ canonical_task->entry = rtems_thread->Start.entry_point;
+ canonical_task->argument = rtems_thread->Start.numeric_argument;
+ canonical_task->stack = rtems_thread->Start.Initial_stack.area;
+ canonical_task->stack_size = rtems_thread->Start.Initial_stack.size;
+ canonical_task->priority = rtems_thread->current_priority;
+ canonical_task->state = rtems_thread->current_state;
+ canonical_task->wait_id = rtems_thread->Wait.id;
+ canonical_task->events = api->pending_events;
+
+/* XXX modes and attributes only exist in the RTEMS API .. */
+/* XXX not directly in the core thread.. they will have to be derived */
+/* XXX if they are important enough to include anymore. */
+ canonical_task->modes = 0; /* XXX FIX ME.... rtems_thread->current_modes; */
+ canonical_task->attributes = 0 /* XXX FIX ME rtems_thread->API_Extensions[ THREAD_API_RTEMS ]->attribute_set */;
+ (void) memcpy(canonical_task->notepad, api ->Notepads, sizeof(canonical_task->notepad));
+/* XXX more to fix */
+/*
+ (void) memcpy(&canonical_task->wait_args, &rtems_thread->Wait.Extra, sizeof(canonical_task->wait_args));
+*/
+}
+
+
+void
+rtems_monitor_task_dump_header(
+ boolean verbose
+)
+{
+ fprintf(stdout,"\
+ ID NAME PRIO STAT MODES EVENTS WAITID WAITARG NOTES\n");
+/*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
+0 1 2 3 4 5 6 7 */
+
+ rtems_monitor_separator();
+}
+
+/*
+ */
+
+void
+rtems_monitor_task_dump(
+ rtems_monitor_task_t *monitor_task,
+ boolean verbose
+)
+{
+ int length = 0;
+
+ length += rtems_monitor_dump_id(monitor_task->id);
+ length += rtems_monitor_pad(11, length);
+ length += rtems_monitor_dump_name(monitor_task->name);
+ length += rtems_monitor_pad(18, length);
+ length += rtems_monitor_dump_priority(monitor_task->priority);
+ length += rtems_monitor_pad(24, length);
+ length += rtems_monitor_dump_state(monitor_task->state);
+ length += rtems_monitor_pad(31, length);
+ length += rtems_monitor_dump_modes(monitor_task->modes);
+ length += rtems_monitor_pad(39, length);
+ length += rtems_monitor_dump_events(monitor_task->events);
+ if (monitor_task->wait_id)
+ {
+ length += rtems_monitor_pad(47, length);
+ length += rtems_monitor_dump_id(monitor_task->wait_id);
+ length += rtems_monitor_pad(57, length);
+ length += rtems_monitor_dump_hex(monitor_task->wait_args);
+ }
+
+ length += rtems_monitor_pad(65, length);
+ length += rtems_monitor_dump_notepad(monitor_task->notepad);
+ fprintf(stdout,"\n");
+}
diff --git a/cpukit/libmisc/monitor/monitor.h b/cpukit/libmisc/monitor/monitor.h
new file mode 100644
index 0000000000..b12f07a012
--- /dev/null
+++ b/cpukit/libmisc/monitor/monitor.h
@@ -0,0 +1,459 @@
+/*
+ * File: monitor.h
+ *
+ * Description:
+ * The RTEMS monitor task include file.
+ *
+ * TODO:
+ *
+ * $Id$
+ */
+
+#ifndef __MONITOR_H
+#define __MONITOR_H
+
+#include <rtems/error.h> /* rtems_error() */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Forward decls from symbols.h */
+typedef struct _rtems_symbol_t rtems_symbol_t ;
+typedef struct _rtems_symbol_table_t rtems_symbol_table_t;
+
+/*
+ * Monitor types are derived from rtems object classes
+ */
+
+typedef enum {
+ RTEMS_MONITOR_OBJECT_INVALID = OBJECTS_NO_CLASS,
+ RTEMS_MONITOR_OBJECT_TASK = OBJECTS_RTEMS_TASKS,
+ RTEMS_MONITOR_OBJECT_EXTENSION = OBJECTS_RTEMS_EXTENSIONS,
+ RTEMS_MONITOR_OBJECT_QUEUE = OBJECTS_RTEMS_MESSAGE_QUEUES,
+ RTEMS_MONITOR_OBJECT_SEMAPHORE = OBJECTS_RTEMS_SEMAPHORES,
+ RTEMS_MONITOR_OBJECT_PARTITION = OBJECTS_RTEMS_PARTITIONS,
+ RTEMS_MONITOR_OBJECT_REGION = OBJECTS_RTEMS_REGIONS,
+ RTEMS_MONITOR_OBJECT_PORT = OBJECTS_RTEMS_PORTS,
+
+ /* following monitor objects are not known to RTEMS, but
+ * we like to have "types" for them anyway */
+
+ RTEMS_MONITOR_OBJECT_DRIVER = OBJECTS_RTEMS_CLASSES_LAST+1,
+ RTEMS_MONITOR_OBJECT_DNAME,
+ RTEMS_MONITOR_OBJECT_CONFIG,
+ RTEMS_MONITOR_OBJECT_INIT_TASK,
+ RTEMS_MONITOR_OBJECT_MPCI,
+ RTEMS_MONITOR_OBJECT_SYMBOL
+} rtems_monitor_object_type_t;
+
+/*
+ * rtems_monitor_init() flags
+ */
+
+#define RTEMS_MONITOR_SUSPEND 0x0001 /* suspend monitor on startup */
+#define RTEMS_MONITOR_GLOBAL 0x0002 /* monitor should be global */
+
+
+/*
+ * Public interfaces for RTEMS data structures monitor is aware of.
+ * These are only used by the monitor.
+ *
+ * NOTE:
+ * All the canonical objects that correspond to RTEMS managed "objects"
+ * must have an identical first portion with 'id' and 'name' fields.
+ *
+ * Others do not have that restriction, even tho we would like them to.
+ * This is because some of the canonical structures are almost too big
+ * for shared memory driver (eg: mpci) and we are nickel and diming it.
+ */
+
+/*
+ * Type of a pointer that may be a symbol
+ */
+
+#define MONITOR_SYMBOL_LEN 20
+typedef struct {
+ char name[MONITOR_SYMBOL_LEN];
+ uint32_t value;
+ uint32_t offset;
+} rtems_monitor_symbol_t;
+
+typedef struct {
+ rtems_id id;
+ rtems_name name;
+ /* end of common portion */
+} rtems_monitor_generic_t;
+
+/*
+ * Task
+ */
+typedef struct {
+ rtems_id id;
+ rtems_name name;
+ /* end of common portion */
+ Thread_Entry entry;
+ uint32_t argument;
+ void *stack;
+ uint32_t stack_size;
+ rtems_task_priority priority;
+ States_Control state;
+ rtems_event_set events;
+ rtems_mode modes;
+ rtems_attribute attributes;
+ uint32_t notepad[RTEMS_NUMBER_NOTEPADS];
+ rtems_id wait_id;
+ uint32_t wait_args;
+} rtems_monitor_task_t;
+
+/*
+ * Init task
+ */
+
+typedef struct {
+ rtems_id id; /* not really an id */
+ rtems_name name;
+ /* end of common portion */
+ rtems_monitor_symbol_t entry;
+ uint32_t argument;
+ uint32_t stack_size;
+ rtems_task_priority priority;
+ rtems_mode modes;
+ rtems_attribute attributes;
+} rtems_monitor_init_task_t;
+
+
+/*
+ * Message queue
+ */
+typedef struct {
+ rtems_id id;
+ rtems_name name;
+ /* end of common portion */
+ rtems_attribute attributes;
+ uint32_t number_of_pending_messages;
+ uint32_t maximum_pending_messages;
+ uint32_t maximum_message_size;
+} rtems_monitor_queue_t;
+
+/*
+ * Extension
+ */
+typedef struct {
+ rtems_id id;
+ rtems_name name;
+ /* end of common portion */
+ rtems_monitor_symbol_t e_create;
+ rtems_monitor_symbol_t e_start;
+ rtems_monitor_symbol_t e_restart;
+ rtems_monitor_symbol_t e_delete;
+ rtems_monitor_symbol_t e_tswitch;
+ rtems_monitor_symbol_t e_begin;
+ rtems_monitor_symbol_t e_exitted;
+ rtems_monitor_symbol_t e_fatal;
+} rtems_monitor_extension_t;
+
+/*
+ * Device driver
+ */
+
+typedef struct {
+ rtems_id id; /* not really an id (should be tho) */
+ rtems_name name; /* ditto */
+ /* end of common portion */
+ rtems_monitor_symbol_t initialization; /* initialization procedure */
+ rtems_monitor_symbol_t open; /* open request procedure */
+ rtems_monitor_symbol_t close; /* close request procedure */
+ rtems_monitor_symbol_t read; /* read request procedure */
+ rtems_monitor_symbol_t write; /* write request procedure */
+ rtems_monitor_symbol_t control; /* special functions procedure */
+} rtems_monitor_driver_t;
+
+typedef struct {
+ rtems_id id; /* not used for drivers (yet) */
+ rtems_name name; /* not used for drivers (yet) */
+ /* end of common portion */
+ uint32_t major;
+ uint32_t minor;
+ char name_string[64];
+} rtems_monitor_dname_t;
+
+/*
+ * System config
+ */
+
+typedef struct {
+ void *work_space_start;
+ uint32_t work_space_size;
+ uint32_t maximum_tasks;
+ uint32_t maximum_timers;
+ uint32_t maximum_semaphores;
+ uint32_t maximum_message_queues;
+ uint32_t maximum_partitions;
+ uint32_t maximum_regions;
+ uint32_t maximum_ports;
+ uint32_t maximum_periods;
+ uint32_t maximum_extensions;
+ uint32_t microseconds_per_tick;
+ uint32_t ticks_per_timeslice;
+ uint32_t number_of_initialization_tasks;
+} rtems_monitor_config_t;
+
+/*
+ * MPCI config
+ */
+
+#if defined(RTEMS_MULTIPROCESSING)
+typedef struct {
+ uint32_t node; /* local node number */
+ uint32_t maximum_nodes; /* maximum # nodes in system */
+ uint32_t maximum_global_objects; /* maximum # global objects */
+ uint32_t maximum_proxies; /* maximum # proxies */
+
+ uint32_t default_timeout; /* in ticks */
+ uint32_t maximum_packet_size;
+ rtems_monitor_symbol_t initialization;
+ rtems_monitor_symbol_t get_packet;
+ rtems_monitor_symbol_t return_packet;
+ rtems_monitor_symbol_t send_packet;
+ rtems_monitor_symbol_t receive_packet;
+} rtems_monitor_mpci_t;
+#endif
+
+/*
+ * The generic canonical information union
+ */
+
+typedef union {
+ rtems_monitor_generic_t generic;
+ rtems_monitor_task_t task;
+ rtems_monitor_queue_t queue;
+ rtems_monitor_extension_t extension;
+ rtems_monitor_driver_t driver;
+ rtems_monitor_dname_t dname;
+ rtems_monitor_config_t config;
+#if defined(RTEMS_MULTIPROCESSING)
+ rtems_monitor_mpci_t mpci;
+#endif
+ rtems_monitor_init_task_t itask;
+} rtems_monitor_union_t;
+
+/*
+ * Support for talking to other monitors
+ */
+
+/*
+ * Names of other monitors
+ */
+
+#define RTEMS_MONITOR_NAME (rtems_build_name('R', 'M', 'O', 'N'))
+#define RTEMS_MONITOR_SERVER_NAME (rtems_build_name('R', 'M', 'S', 'V'))
+#define RTEMS_MONITOR_QUEUE_NAME (rtems_build_name('R', 'M', 'S', 'Q'))
+#define RTEMS_MONITOR_RESPONSE_QUEUE_NAME (rtems_build_name('R', 'M', 'R', 'Q'))
+
+#define RTEMS_MONITOR_SERVER_RESPONSE 0x0001
+#define RTEMS_MONITOR_SERVER_CANONICAL 0x0002
+
+typedef struct
+{
+ uint32_t command;
+ rtems_id return_id;
+ uint32_t argument0;
+ uint32_t argument1;
+ uint32_t argument2;
+ uint32_t argument3;
+ uint32_t argument4;
+ uint32_t argument5;
+} rtems_monitor_server_request_t;
+
+typedef struct
+{
+ uint32_t command;
+ uint32_t result0;
+ uint32_t result1;
+ rtems_monitor_union_t payload;
+} rtems_monitor_server_response_t;
+
+extern rtems_id rtems_monitor_task_id;
+
+extern uint32_t rtems_monitor_node; /* our node number */
+extern uint32_t rtems_monitor_default_node; /* current default for commands */
+
+/*
+ * Monitor command function and table entry
+ */
+
+typedef struct rtems_monitor_command_entry_s rtems_monitor_command_entry_t;
+typedef union _rtems_monitor_command_arg_t rtems_monitor_command_arg_t;
+
+typedef void ( *rtems_monitor_command_function_t )(
+ int argc,
+ char **argv,
+ rtems_monitor_command_arg_t *command_arg,
+ boolean verbose
+ );
+
+union _rtems_monitor_command_arg_t {
+ rtems_monitor_object_type_t monitor_object ;
+ rtems_status_code status_code ;
+ rtems_symbol_table_t **symbol_table ;
+ rtems_monitor_command_entry_t *monitor_command_entry ;
+};
+
+struct rtems_monitor_command_entry_s {
+ char *command; /* command name */
+ char *usage; /* usage string for the command */
+ uint32_t arguments_required; /* # of required args */
+ rtems_monitor_command_function_t command_function;
+ /* Some argument for the command */
+ rtems_monitor_command_arg_t command_arg;
+ rtems_monitor_command_entry_t *next;
+};
+
+
+typedef void *(*rtems_monitor_object_next_fn)(void *, void *, rtems_id *);
+typedef void (*rtems_monitor_object_canonical_fn)(void *, void *);
+typedef void (*rtems_monitor_object_dump_header_fn)(boolean);
+typedef void (*rtems_monitor_object_dump_fn)(void *, boolean);
+
+typedef struct {
+ rtems_monitor_object_type_t type;
+ void *object_information;
+ int size; /* of canonical object */
+ rtems_monitor_object_next_fn next;
+ rtems_monitor_object_canonical_fn canonical;
+ rtems_monitor_object_dump_header_fn dump_header;
+ rtems_monitor_object_dump_fn dump;
+} rtems_monitor_object_info_t;
+
+
+/* monitor.c */
+void rtems_monitor_kill(void);
+void rtems_monitor_init(uint32_t );
+void rtems_monitor_wakeup(void);
+void rtems_monitor_pause_cmd(int, char **, rtems_monitor_command_arg_t*, boolean);
+void rtems_monitor_fatal_cmd(int, char **, rtems_monitor_command_arg_t*, boolean);
+void rtems_monitor_continue_cmd(int, char **, rtems_monitor_command_arg_t*, boolean);
+void rtems_monitor_debugger_cmd(int, char **, rtems_monitor_command_arg_t*, boolean);
+void rtems_monitor_node_cmd(int, char **, rtems_monitor_command_arg_t*, boolean);
+void rtems_monitor_symbols_loadup(void);
+int rtems_monitor_insert_cmd(rtems_monitor_command_entry_t *);
+int rtems_monitor_erase_cmd(rtems_monitor_command_entry_t *);
+
+void rtems_monitor_task(rtems_task_argument);
+
+/* server.c */
+void rtems_monitor_server_kill(void);
+rtems_status_code rtems_monitor_server_request(uint32_t , rtems_monitor_server_request_t *, rtems_monitor_server_response_t *);
+void rtems_monitor_server_task(rtems_task_argument);
+void rtems_monitor_server_init(uint32_t );
+
+/* command.c */
+int rtems_monitor_make_argv(char *, int *, char **);
+int rtems_monitor_command_read(char *, int *, char **);
+rtems_monitor_command_entry_t *rtems_monitor_command_lookup(
+ rtems_monitor_command_entry_t * table, int argc, char **argv);
+void rtems_monitor_command_usage(rtems_monitor_command_entry_t *, char *);
+void rtems_monitor_help_cmd(int, char **, rtems_monitor_command_arg_t *, boolean);
+
+/* prmisc.c */
+void rtems_monitor_separator(void);
+uint32_t rtems_monitor_pad(uint32_t dest_col, uint32_t curr_col);
+uint32_t rtems_monitor_dump_char(uint8_t ch);
+uint32_t rtems_monitor_dump_decimal(uint32_t num);
+uint32_t rtems_monitor_dump_hex(uint32_t num);
+uint32_t rtems_monitor_dump_id(rtems_id id);
+uint32_t rtems_monitor_dump_name(rtems_name name);
+uint32_t rtems_monitor_dump_priority(rtems_task_priority priority);
+uint32_t rtems_monitor_dump_state(States_Control state);
+uint32_t rtems_monitor_dump_modes(rtems_mode modes);
+uint32_t rtems_monitor_dump_attributes(rtems_attribute attributes);
+uint32_t rtems_monitor_dump_events(rtems_event_set events);
+uint32_t rtems_monitor_dump_notepad(uint32_t *notepad);
+
+/* object.c */
+rtems_id rtems_monitor_id_fixup(rtems_id, uint32_t , rtems_monitor_object_type_t);
+rtems_id rtems_monitor_object_canonical_get(rtems_monitor_object_type_t, rtems_id, void *, uint32_t *size_p);
+rtems_id rtems_monitor_object_canonical_next(rtems_monitor_object_info_t *, rtems_id, void *);
+void *rtems_monitor_object_next(void *, void *, rtems_id, rtems_id *);
+rtems_id rtems_monitor_object_canonical(rtems_id, void *);
+void rtems_monitor_object_cmd(int, char **, rtems_monitor_command_arg_t*, boolean);
+
+/* manager.c */
+void *rtems_monitor_manager_next(void *, void *, rtems_id *);
+
+/* config.c */
+void rtems_monitor_config_canonical(rtems_monitor_config_t *, void *);
+void *rtems_monitor_config_next(void *, rtems_monitor_config_t *, rtems_id *);
+void rtems_monitor_config_dump_header(boolean);
+void rtems_monitor_config_dump(rtems_monitor_config_t *, boolean verbose);
+
+/* mpci.c */
+#if defined(RTEMS_MULTIPROCESSING)
+void rtems_monitor_mpci_canonical(rtems_monitor_mpci_t *, void *);
+void *rtems_monitor_mpci_next(void *, rtems_monitor_mpci_t *, rtems_id *);
+void rtems_monitor_mpci_dump_header(boolean);
+void rtems_monitor_mpci_dump(rtems_monitor_mpci_t *, boolean verbose);
+#endif
+
+/* itask.c */
+void rtems_monitor_init_task_canonical(rtems_monitor_init_task_t *, void *);
+void *rtems_monitor_init_task_next(void *, rtems_monitor_init_task_t *, rtems_id *);
+void rtems_monitor_init_task_dump_header(boolean);
+void rtems_monitor_init_task_dump(rtems_monitor_init_task_t *, boolean verbose);
+
+/* extension.c */
+void rtems_monitor_extension_canonical(rtems_monitor_extension_t *, void *);
+void rtems_monitor_extension_dump_header(boolean verbose);
+void rtems_monitor_extension_dump(rtems_monitor_extension_t *, boolean);
+
+/* task.c */
+void rtems_monitor_task_canonical(rtems_monitor_task_t *, void *);
+void rtems_monitor_task_dump_header(boolean verbose);
+void rtems_monitor_task_dump(rtems_monitor_task_t *, boolean);
+
+/* queue.c */
+void rtems_monitor_queue_canonical(rtems_monitor_queue_t *, void *);
+void rtems_monitor_queue_dump_header(boolean verbose);
+void rtems_monitor_queue_dump(rtems_monitor_queue_t *, boolean);
+
+/* driver.c */
+void *rtems_monitor_driver_next(void *, rtems_monitor_driver_t *, rtems_id *);
+void rtems_monitor_driver_canonical(rtems_monitor_driver_t *, void *);
+void rtems_monitor_driver_dump_header(boolean);
+void rtems_monitor_driver_dump(rtems_monitor_driver_t *, boolean);
+
+/* dname.c */
+void *rtems_monitor_dname_next(void *, rtems_monitor_dname_t *, rtems_id *);
+void rtems_monitor_dname_canonical(rtems_monitor_dname_t *, void *);
+void rtems_monitor_dname_dump_header(boolean);
+void rtems_monitor_dname_dump(rtems_monitor_dname_t *, boolean);
+
+/* symbols.c */
+rtems_symbol_table_t *rtems_symbol_table_create();
+void rtems_symbol_table_destroy(rtems_symbol_table_t *table);
+
+rtems_symbol_t *rtems_symbol_create(rtems_symbol_table_t *, char *, uint32_t );
+rtems_symbol_t *rtems_symbol_value_lookup(rtems_symbol_table_t *, uint32_t );
+const rtems_symbol_t *rtems_symbol_value_lookup_exact(rtems_symbol_table_t *, uint32_t );
+rtems_symbol_t *rtems_symbol_name_lookup(rtems_symbol_table_t *, char *);
+void *rtems_monitor_symbol_next(void *object_info, rtems_monitor_symbol_t *, rtems_id *);
+void rtems_monitor_symbol_canonical(rtems_monitor_symbol_t *, rtems_symbol_t *);
+void rtems_monitor_symbol_canonical_by_name(rtems_monitor_symbol_t *, char *);
+void rtems_monitor_symbol_canonical_by_value(rtems_monitor_symbol_t *, void *);
+uint32_t rtems_monitor_symbol_dump(rtems_monitor_symbol_t *, boolean);
+void rtems_monitor_symbol_cmd(int, char **, rtems_monitor_command_arg_t*, boolean);
+
+
+extern rtems_symbol_table_t *rtems_monitor_symbols;
+
+/* FIXME: This should not be here */
+extern rtems_monitor_command_entry_t rtems_monitor_commands[];
+
+#define MONITOR_WAKEUP_EVENT RTEMS_EVENT_0
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ! __MONITOR_H */
diff --git a/cpukit/libmisc/monitor/symbols.h b/cpukit/libmisc/monitor/symbols.h
new file mode 100644
index 0000000000..6246379a94
--- /dev/null
+++ b/cpukit/libmisc/monitor/symbols.h
@@ -0,0 +1,64 @@
+/*
+ * RTEMS monitor symbol table functions
+ *
+ * Description:
+ * Entry points for symbol table routines.
+ *
+ *
+ *
+ * TODO:
+ *
+ * $Id$
+ */
+
+#ifndef _INCLUDE_SYMBOLS_H
+#define _INCLUDE_SYMBOLS_H
+
+#include <rtems/monitor.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct _rtems_symbol_t {
+ uint32_t value;
+ char *name;
+} ;
+
+#define SYMBOL_STRING_BLOCK_SIZE 4080
+typedef struct rtems_symbol_string_block_s {
+ struct rtems_symbol_string_block_s *next;
+ char buffer[SYMBOL_STRING_BLOCK_SIZE];
+} rtems_symbol_string_block_t;
+
+struct _rtems_symbol_table_t {
+
+ uint32_t sorted; /* are symbols sorted right now? */
+ uint32_t growth_factor; /* % to grow by when needed */
+ uint32_t next; /* next symbol slot to use when adding */
+ uint32_t size; /* max # of symbols */
+
+ /*
+ * Symbol list -- sorted by address (when we do a lookup)
+ */
+
+ rtems_symbol_t *addresses; /* symbol array by address */
+
+ /*
+ * String pool, unsorted, a list of blocks of string data
+ */
+
+ rtems_symbol_string_block_t *string_buffer_head;
+ rtems_symbol_string_block_t *string_buffer_current;
+ uint32_t strings_next; /* next byte to use in this block */
+
+} ;
+
+#define rtems_symbol_name(sp) ((sp)->name)
+#define rtems_symbol_value(sp) ((sp)->value)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ! _INCLUDE_SYMBOLS_H */
diff --git a/cpukit/libmisc/mw-fb/mw_fb.c b/cpukit/libmisc/mw-fb/mw_fb.c
new file mode 100644
index 0000000000..7ea715a18f
--- /dev/null
+++ b/cpukit/libmisc/mw-fb/mw_fb.c
@@ -0,0 +1,194 @@
+/*
+/////////////////////////////////////////////////////////////////////////////
+// $Header$
+//
+// Copyright (c) 2000 - Rosimildo da Silva
+//
+// MODULE DESCRIPTION:
+// Wrapper API around the ioctls calls for the Micro FrameBuffer
+// interface for Embedded Systems
+//
+// All functions returns 0 on success. Any other value should be
+// decoded as an error. A list of errors will be created over time.
+//
+// MODIFICATION/HISTORY:
+//
+// $Log$
+// Revision 1.3 2004/04/15 13:24:46 ralf
+// Remove stray white spaces.
+//
+// Revision 1.2 2003/07/08 08:38:48 ralf
+// 2003-07-08 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+//
+// * capture/capture-cli.c: Add config-header support.
+// * capture/capture.c: Add config-header support.
+// * cpuuse/cpuuse.c: Add config-header support.
+// * devnull/devnull.c: Add config-header support.
+// * dummy/dummy.c: Add config-header support.
+// * dumpbuf/dumpbuf.c: Add config-header support.
+// * monitor/mon-command.c: Add config-header support.
+// * monitor/mon-config.c: Add config-header support.
+// * monitor/mon-dname.c: Add config-header support.
+// * monitor/mon-driver.c: Add config-header support.
+// * monitor/mon-extension.c: Add config-header support.
+// * monitor/mon-itask.c: Add config-header support.
+// * monitor/mon-manager.c: Add config-header support.
+// * monitor/mon-monitor.c: Add config-header support.
+// * monitor/mon-mpci.c: Add config-header support.
+// * monitor/mon-object.c: Add config-header support.
+// * monitor/mon-prmisc.c: Add config-header support.
+// * monitor/mon-queue.c: Add config-header support.
+// * monitor/mon-server.c: Add config-header support.
+// * monitor/mon-symbols.c: Add config-header support.
+// * monitor/mon-task.c: Add config-header support.
+// * mw-fb/mw_fb.c: Add config-header support.
+// * mw-fb/mw_uid.c: Add config-header support.
+// * rtmonuse/rtmonuse.c: Add config-header support.
+// * serdbg/serdbg.c: Add config-header support.
+// * serdbg/serdbgio.c: Add config-header support.
+// * serdbg/termios_printk.c: Add config-header support.
+// * shell/cmds.c: Add config-header support.
+// * stackchk/check.c: Add config-header support.
+// * untar/untar.c: Add config-header support.
+//
+// Revision 1.1 2000/08/30 08:21:24 joel
+// 2000-08-26 Rosimildo da Silva <rdasilva@connecttel.com>
+//
+// * Added generic Micro FrameBuffer interface for MicroWindows.
+// This interface allows MicroWindows to under RTEMS. A sample
+// driver has been developed for the pc386 BSP. See
+// pc386/fb_vga.c as a sample.
+// * Added Uniform Input Device interface for MicroWindows.
+// See PC386 bsp for sample drivers for mouse and keyboard (console).
+// * mw-bf: New directory.
+// * Makefile.am, configure.in, wrapup/Makefile.am: Account for mw-fb.
+// * mw-fb/Makefile.am: New file.
+// * mw-fb/mw_fb.c: New file.
+// * mw-fb/mw_fb.h: New file.
+// * mw-fb/mw_uid.c: New file.
+// * mw-fb/mw_uid.h: New file.
+//
+//
+/////////////////////////////////////////////////////////////////////////////
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/ioctl.h>
+#include <rtems/mw_fb.h>
+
+
+/*
+ * This function returns the information regarding the display.
+ * It is called just after the driver be opened to get all needed
+ * information about the driver. No change in the mode of operation
+ * of the driver is done with this call.
+ */
+ int ufb_get_screen_info( int fd, struct fb_screeninfo *info )
+ {
+ return ioctl( fd, FB_SCREENINFO, ( void *)info);
+ }
+
+
+
+/*
+ * Returns the mode of the graphics subsystem
+ */
+ int ufb_get_mode( int fd, int *mode )
+ {
+ struct fb_exec_function exec;
+ exec.func_no = FB_FUNC_GET_MODE;
+ exec.param = ( void *)mode;
+ return ioctl( fd, FB_EXEC_FUNCTION , ( void *)&exec );
+ }
+
+
+/*
+ * Returns the current collor pallete
+ */
+ int ufb_get_palette( int fd, struct fb_cmap *color )
+ {
+ return ioctl( fd, FB_GETPALETTE, ( void *)color );
+ }
+
+
+/*
+ * Set the current collor pallete
+ */
+ int ufb_set_palette( int fd, struct fb_cmap *color )
+ {
+ return ioctl( fd, FB_SETPALETTE, ( void *)color );
+ }
+
+/*
+ * Does all necessary initialization to put the device in
+ * graphics mode
+ */
+ int ufb_enter_graphics( int fd, int mode )
+ {
+ struct fb_exec_function exec;
+ exec.func_no = FB_FUNC_ENTER_GRAPHICS;
+ exec.param = ( void *)mode;
+ return ioctl( fd, FB_EXEC_FUNCTION , ( void *)&exec );
+ }
+
+
+/*
+ * Switch the device back to the default mode of operation.
+ * In most cases it put the device back to plain text mode.
+ */
+ int ufb_exit_graphics( int fd )
+ {
+ struct fb_exec_function exec;
+ exec.func_no = FB_FUNC_EXIT_GRAPHICS;
+ exec.param = 0;
+ return ioctl( fd, FB_EXEC_FUNCTION , ( void *)&exec );
+ }
+
+/*
+ * Tell the driver that the "virtual buffer" is dirty, and an update
+ * of it to the real device, maybe a serial/parallel LCD or whatever
+ * is required
+ */
+ int ufb_buffer_is_dirty( int fd )
+ {
+ struct fb_exec_function exec;
+ exec.func_no = FB_FUNC_IS_DIRTY;
+ exec.param = 0;
+ return ioctl( fd, FB_EXEC_FUNCTION , ( void *)&exec );
+ }
+
+
+
+/*
+ * This function maps the physical ( kernel mode ) address of the framebuffer device
+ * and maps it to the user space address.
+ */
+ int ufb_mmap_to_user_space( int fd, void **fb_addr, void *physical_addr, unsigned long size )
+ {
+ #ifdef __rtems__
+ /* RTEMS runs in ring 0, and there is no distinction between
+ user space and kernel space, so we just return the same
+ pointer to the caller.
+ */
+ *fb_addr = physical_addr;
+ return 0;
+ #else
+ /* other kernels might want to map it to the user space,
+ maybe using mmap()
+ */
+ return 0;
+ #endif
+
+ }
+
+
+/*
+ * This function unmaps memory of the FB from the user's space
+ */
+ int ufb_unmmap_from_user_space( int fd, void *addr )
+ {
+ return 0;
+ }
diff --git a/cpukit/libmisc/mw-fb/mw_fb.h b/cpukit/libmisc/mw-fb/mw_fb.h
new file mode 100644
index 0000000000..fb7b6f6170
--- /dev/null
+++ b/cpukit/libmisc/mw-fb/mw_fb.h
@@ -0,0 +1,170 @@
+/*
+/////////////////////////////////////////////////////////////////////////////
+// $Header$
+//
+// Copyright (c) 2000 - Rosimildo da Silva
+//
+// MODULE DESCRIPTION:
+// Micro FrameBuffer interface for Embedded Systems.
+//
+// MODIFICATION/HISTORY:
+//
+// $Log$
+// Revision 1.1 2000/08/30 08:21:24 joel
+// 2000-08-26 Rosimildo da Silva <rdasilva@connecttel.com>
+//
+// * Added generic Micro FrameBuffer interface for MicroWindows.
+// This interface allows MicroWindows to under RTEMS. A sample
+// driver has been developed for the pc386 BSP. See
+// pc386/fb_vga.c as a sample.
+// * Added Uniform Input Device interface for MicroWindows.
+// See PC386 bsp for sample drivers for mouse and keyboard (console).
+// * mw-bf: New directory.
+// * Makefile.am, configure.in, wrapup/Makefile.am: Account for mw-fb.
+// * mw-fb/Makefile.am: New file.
+// * mw-fb/mw_fb.c: New file.
+// * mw-fb/mw_fb.h: New file.
+// * mw-fb/mw_uid.c: New file.
+// * mw-fb/mw_uid.h: New file.
+//
+//
+/////////////////////////////////////////////////////////////////////////////
+*/
+#ifndef _MW_FB_H
+#define _MW_FB_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ioctls
+ 0x46 is 'F' */
+#define FB_SCREENINFO 0x4601
+#define FB_GETPALETTE 0x4602
+#define FB_SETPALETTE 0x4603
+#define FB_EXEC_FUNCTION 0x4604
+
+
+#define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */
+#define FB_TYPE_PLANES 1 /* Non interleaved planes */
+#define FB_TYPE_INTERLEAVED_PLANES 2 /* Interleaved planes */
+#define FB_TYPE_TEXT 3 /* Text/attributes */
+#define FB_TYPE_VGA_PLANES 4 /* EGA/VGA planes */
+#define FB_TYPE_VIRTUAL_BUFFER 5 /* Virtual Buffer */
+
+
+#define FB_VISUAL_MONO01 0 /* Monochr. 1=Black 0=White */
+#define FB_VISUAL_MONO10 1 /* Monochr. 1=White 0=Black */
+#define FB_VISUAL_TRUECOLOR 2 /* True color */
+#define FB_VISUAL_PSEUDOCOLOR 3 /* Pseudo color (like atari) */
+#define FB_VISUAL_DIRECTCOLOR 4 /* Direct color */
+#define FB_VISUAL_STATIC_PSEUDOCOLOR 5 /* Pseudo color readonly */
+
+#define FB_ACCEL_NONE 0 /* no hardware accelerator */
+
+/* no dependency on any other header file */
+typedef unsigned long __u32;
+typedef unsigned short __u16;
+
+struct fb_screeninfo {
+ __u32 xres; /* visible resolution */
+ __u32 yres;
+ __u32 bits_per_pixel; /* guess what */
+ __u32 line_length; /* number of chars per line */
+ volatile char *smem_start; /* Start of frame buffer mem */
+ /* (physical address) */
+ __u32 smem_len; /* Length of frame buffer mem */
+ __u32 type; /* see FB_TYPE_* */
+ __u32 visual; /* see FB_VISUAL_* */
+
+};
+
+struct fb_cmap {
+ __u32 start; /* First entry */
+ __u32 len; /* Number of entries */
+ __u16 *red; /* Red values */
+ __u16 *green;
+ __u16 *blue;
+ __u16 *transp; /* transparency, can be NULL */
+};
+
+/* type of function to be executed at the driver level */
+#define FB_FUNC_ENTER_GRAPHICS 0
+#define FB_FUNC_EXIT_GRAPHICS 1
+#define FB_FUNC_IS_DIRTY 2
+#define FB_FUNC_GET_MODE 3
+
+struct fb_exec_function
+{
+ int func_no;
+ void *param;
+};
+
+
+/* Micro Framebuffer API Wrapper */
+
+/*
+ * This function returns the information regarding the display.
+ * It is called just after the driver be opened to get all needed
+ * information about the driver. No change in the mode of operation
+ * of the driver is done with this call.
+ */
+extern int ufb_get_screen_info( int fd, struct fb_screeninfo *info );
+
+
+/*
+ * Returns the mode of the graphics subsystem
+ */
+extern int ufb_get_mode( int fd, int *mode );
+
+
+/*
+ * Returns the current collor pallete
+ */
+extern int ufb_get_palette( int fd, struct fb_cmap *color );
+
+/*
+ * Set the current collor pallete
+ */
+extern int ufb_set_palette( int fd, struct fb_cmap *color );
+
+/*
+ * Does all necessary initialization to put the device in
+ * graphics mode
+ */
+extern int ufb_enter_graphics( int fd, int mode );
+
+
+/*
+ * Switch the device back to the default mode of operation.
+ * In most cases it put the device back to plain text mode.
+ */
+extern int ufb_exit_graphics( int fd );
+
+
+/*
+ * Tell the driver that the "virtual buffer" is dirty, and an update
+ * of it to the real device, maybe a serial/parallel LCD or whatever
+ * is required
+ */
+extern int ufb_buffer_is_dirty( int fd );
+
+
+/*
+ * This function maps the physical ( kernel mode ) address of the framebuffer device
+ * and maps it to the user space address.
+ */
+ int ufb_mmap_to_user_space( int fd, void **fb_addr, void *physical_addr, unsigned long size );
+
+
+
+/*
+ * This function unmaps memory of the FB from the user's space
+ */
+ int ufb_unmmap_from_user_space( int fd, void *addr );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MW_FB_H */
diff --git a/cpukit/libmisc/mw-fb/mw_uid.c b/cpukit/libmisc/mw-fb/mw_uid.c
new file mode 100644
index 0000000000..07cfca5571
--- /dev/null
+++ b/cpukit/libmisc/mw-fb/mw_uid.c
@@ -0,0 +1,248 @@
+/*
+/////////////////////////////////////////////////////////////////////////////
+// $Header$
+//
+// Copyright (c) 2000 - Rosimildo da Silva
+//
+// MODULE DESCRIPTION:
+// This module implements the input devices interface used by MicroWindows
+// in an embedded system environment.
+// It uses the RTEMS message queue as the repository for the messages posted
+// by the devices registered.
+//
+// MODIFICATION/HISTORY:
+//
+// $Log$
+// Revision 1.6 2004/03/26 06:59:18 ralf
+// 2004-03-26 Ralf Corsepius <ralf_corsepius@rtems.org>
+//
+// * libmisc/capture/capture-cli.c, libmisc/capture/capture.c,
+// libmisc/capture/capture.h, libmisc/cpuuse/cpuuse.c,
+// libmisc/devnull/devnull.c, libmisc/fsmount/fsmount.h,
+// libmisc/monitor/mon-config.c, libmisc/monitor/mon-dname.c,
+// libmisc/monitor/mon-driver.c, libmisc/monitor/mon-extension.c,
+// libmisc/monitor/mon-itask.c, libmisc/monitor/mon-monitor.c,
+// libmisc/monitor/mon-mpci.c, libmisc/monitor/mon-object.c,
+// libmisc/monitor/mon-prmisc.c, libmisc/monitor/mon-queue.c,
+// libmisc/monitor/mon-server.c, libmisc/monitor/mon-symbols.c,
+// libmisc/monitor/monitor.h, libmisc/monitor/symbols.h,
+// libmisc/mw-fb/mw_uid.c, libmisc/rtmonuse/rtmonuse.c,
+// libmisc/serdbg/serdbg.h, libmisc/serdbg/serdbgio.c,
+// libmisc/serdbg/termios_printk.c, libmisc/serdbg/termios_printk.h,
+// libmisc/shell/shell.c, libmisc/shell/shell.h, libmisc/stackchk/check.c,
+// libmisc/stackchk/internal.h: Convert to using c99 fixed size types.
+//
+// Revision 1.5 2003/07/08 08:38:48 ralf
+// 2003-07-08 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+//
+// * capture/capture-cli.c: Add config-header support.
+// * capture/capture.c: Add config-header support.
+// * cpuuse/cpuuse.c: Add config-header support.
+// * devnull/devnull.c: Add config-header support.
+// * dummy/dummy.c: Add config-header support.
+// * dumpbuf/dumpbuf.c: Add config-header support.
+// * monitor/mon-command.c: Add config-header support.
+// * monitor/mon-config.c: Add config-header support.
+// * monitor/mon-dname.c: Add config-header support.
+// * monitor/mon-driver.c: Add config-header support.
+// * monitor/mon-extension.c: Add config-header support.
+// * monitor/mon-itask.c: Add config-header support.
+// * monitor/mon-manager.c: Add config-header support.
+// * monitor/mon-monitor.c: Add config-header support.
+// * monitor/mon-mpci.c: Add config-header support.
+// * monitor/mon-object.c: Add config-header support.
+// * monitor/mon-prmisc.c: Add config-header support.
+// * monitor/mon-queue.c: Add config-header support.
+// * monitor/mon-server.c: Add config-header support.
+// * monitor/mon-symbols.c: Add config-header support.
+// * monitor/mon-task.c: Add config-header support.
+// * mw-fb/mw_fb.c: Add config-header support.
+// * mw-fb/mw_uid.c: Add config-header support.
+// * rtmonuse/rtmonuse.c: Add config-header support.
+// * serdbg/serdbg.c: Add config-header support.
+// * serdbg/serdbgio.c: Add config-header support.
+// * serdbg/termios_printk.c: Add config-header support.
+// * shell/cmds.c: Add config-header support.
+// * stackchk/check.c: Add config-header support.
+// * untar/untar.c: Add config-header support.
+//
+// Revision 1.4 2002/01/04 18:32:48 joel
+// 2002-01-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+//
+// * mw-fb/mw_uid.c: Apply rtems_set_errno_and_return_minus_one.
+//
+// Revision 1.3 2000/11/30 14:36:46 joel
+// 2000-11-30 Joel Sherrill <joel@OARcorp.com>
+//
+// * mw-fb/mw_uid.c: Removed unnecessary dependency on <bsp.h>.
+//
+// Revision 1.2 2000/08/30 17:12:55 joel
+// 2000-08-30 Joel Sherrill <joel@OARcorp.com>
+//
+// * Many files: Moved posix/include/rtems/posix/seterr.h to
+// score/include/rtems/seterr.h so it would be available within
+// all APIs.
+//
+// Revision 1.1 2000/08/30 08:21:24 joel
+// 2000-08-26 Rosimildo da Silva <rdasilva@connecttel.com>
+//
+// * Added generic Micro FrameBuffer interface for MicroWindows.
+// This interface allows MicroWindows to under RTEMS. A sample
+// driver has been developed for the pc386 BSP. See
+// pc386/fb_vga.c as a sample.
+// * Added Uniform Input Device interface for MicroWindows.
+// See PC386 bsp for sample drivers for mouse and keyboard (console).
+// * mw-bf: New directory.
+// * Makefile.am, configure.in, wrapup/Makefile.am: Account for mw-fb.
+// * mw-fb/Makefile.am: New file.
+// * mw-fb/mw_fb.c: New file.
+// * mw-fb/mw_fb.h: New file.
+// * mw-fb/mw_uid.c: New file.
+// * mw-fb/mw_uid.h: New file.
+//
+//
+/////////////////////////////////////////////////////////////////////////////
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <rtems.h>
+
+#include <rtems/mw_uid.h>
+#include <rtems/seterr.h>
+
+static rtems_id queue_id = 0;
+static int open_count = 0;
+
+/*
+#define MW_DEBUG_ON 1
+*/
+
+/* open a message queue with the kernel */
+int uid_open_queue( const char *q_name, int flags, size_t max_msgs )
+{
+ static rtems_name queue_name;
+
+ /*
+ * For the first device calling this function we would create the queue.
+ * It is assumed that this call is done at initialization, and no concerns
+ * regarding multi-threading is taken in consideration here.
+ */
+ if( !open_count )
+ {
+ rtems_status_code status;
+ queue_name = rtems_build_name( q_name[0],
+ q_name[1],
+ q_name[2],
+ q_name[3] );
+ status = rtems_message_queue_create( queue_name,
+ max_msgs,
+ sizeof( struct MW_UID_MESSAGE ),
+ RTEMS_FIFO | RTEMS_LOCAL,
+ &queue_id );
+ if( status != RTEMS_SUCCESSFUL )
+ {
+#ifdef MW_DEBUG_ON
+ printk( "UID_Queue: error creating queue: %d\n", status );
+#endif
+ return -1;
+ }
+#ifdef MW_DEBUG_ON
+ printk( "UID_Queue: id=%X\n", queue_id );
+#endif
+ }
+ open_count++;
+ return 0;
+}
+
+
+/* close message queue */
+int uid_close_queue( void )
+{
+ if( open_count == 1 )
+ {
+ rtems_message_queue_delete( queue_id );
+ queue_id = 0;
+ }
+ open_count--;
+ return 0;
+}
+
+/* reads for a message from the device */
+int uid_read_message( struct MW_UID_MESSAGE *m, unsigned long timeout )
+{
+ rtems_status_code status;
+ uint32_t size = 0;
+ unsigned long micro_secs = timeout*1000;
+ int wait = ( timeout != 0 );
+
+ status = rtems_message_queue_receive( queue_id,
+ (void*)m,
+ &size,
+ wait ? RTEMS_WAIT : RTEMS_NO_WAIT,
+ TOD_MICROSECONDS_TO_TICKS(micro_secs ) );
+
+ if( status == RTEMS_SUCCESSFUL )
+ {
+ return size;
+ }
+ else if( ( status == RTEMS_UNSATISFIED ) || ( status == RTEMS_TIMEOUT ) )
+ {
+ /* this macro returns -1 */
+ rtems_set_errno_and_return_minus_one( ETIMEDOUT );
+ }
+ /* Here we have one error condition */
+#ifdef MW_DEBUG_ON
+ printk( "UID_Queue: error reading queue: %d\n", status );
+#endif
+ return -1;
+}
+
+
+/*
+ * add a message to the queue of events. This method cna be used to
+ * simulate hardware events, and it can be very handy during development
+ * a new interface.
+ */
+int uid_send_message( struct MW_UID_MESSAGE *m )
+{
+ rtems_status_code status;
+ status = rtems_message_queue_send( queue_id, ( void * )m,
+ sizeof( struct MW_UID_MESSAGE ) );
+ return status == RTEMS_SUCCESSFUL ? 0 : -1;
+}
+
+/*
+ * register the device to insert events to the message
+ * queue named as the value passed in q_name
+ */
+int uid_register_device( int fd, const char *q_name )
+{
+ return ioctl( fd, MW_UID_REGISTER_DEVICE, q_name );
+}
+
+/* tell this device to stop adding events to the queue */
+int uid_unregister_device( int fd )
+{
+ return ioctl( fd, MW_UID_UNREGISTER_DEVICE, NULL );
+}
+
+/* set the keyboard */
+int uid_set_kbd_mode( int fd, int mode, int *old_mode )
+{
+ if (ioctl( fd, MV_KDGKBMODE, old_mode) < 0)
+ {
+ return -1;
+ }
+ if (ioctl(fd, MV_KDSKBMODE, mode ) < 0 )
+ {
+ return -1;
+ }
+ return 0;
+}
diff --git a/cpukit/libmisc/mw-fb/mw_uid.h b/cpukit/libmisc/mw-fb/mw_uid.h
new file mode 100644
index 0000000000..2bfc258057
--- /dev/null
+++ b/cpukit/libmisc/mw-fb/mw_uid.h
@@ -0,0 +1,160 @@
+/*
+/////////////////////////////////////////////////////////////////////////////
+// $Header$
+//
+// Copyright (c) 2000 - Rosimildo da Silva
+//
+// MODULE DESCRIPTION:
+// This module defines the interface for input devices used by MicroWindows
+// in an embedded system environment.
+//
+// MODIFICATION/HISTORY:
+//
+// $Log$
+// Revision 1.1 2000/08/30 08:21:24 joel
+// 2000-08-26 Rosimildo da Silva <rdasilva@connecttel.com>
+//
+// * Added generic Micro FrameBuffer interface for MicroWindows.
+// This interface allows MicroWindows to under RTEMS. A sample
+// driver has been developed for the pc386 BSP. See
+// pc386/fb_vga.c as a sample.
+// * Added Uniform Input Device interface for MicroWindows.
+// See PC386 bsp for sample drivers for mouse and keyboard (console).
+// * mw-bf: New directory.
+// * Makefile.am, configure.in, wrapup/Makefile.am: Account for mw-fb.
+// * mw-fb/Makefile.am: New file.
+// * mw-fb/mw_fb.c: New file.
+// * mw-fb/mw_fb.h: New file.
+// * mw-fb/mw_uid.c: New file.
+// * mw-fb/mw_uid.h: New file.
+//
+//
+/////////////////////////////////////////////////////////////////////////////
+*/
+#ifndef _MW_UID_H
+#define _MW_UID_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 0x41XX -- IOCLT functions for the Micro Input Devices commands */
+#define MW_UID_REGISTER_DEVICE 0x4100
+#define MW_UID_UNREGISTER_DEVICE 0x4101
+
+
+/* devices supported by MicroWindows */
+enum MW_INPUT_DEVICE_TYPE
+{
+ MV_UID_INVALID = 0,
+ MV_UID_REL_POS = 1, /* mouse */
+ MV_UID_ABS_POS = 2, /* touch-screen */
+ MV_UID_KBD = 3, /* keyboard */
+ MV_UID_TIMER = 4 /* timer -- not used */
+};
+
+
+/* matching MicroWindows */
+#define MV_BUTTON_RIGHT 0x01
+#define MV_BUTTON_CENTER 0x02
+#define MV_BUTTON_LEFT 0x04
+
+/* modifiers of the keyboard type devices */
+#define MV_KEY_MODIFIER_SHIFT_DOWN 0x10
+#define MV_KEY_MODIFIER_ALT_DOWN 0x20
+
+/* indication of the LEDS */
+#define MV_KEY_MODIFIER_CAPS_ON 0x04
+#define MV_KEY_MODIFIER_NUN_LOCK_ON 0x02
+#define MV_KEY_SCROLL_LOCK_ON 0x01
+
+/* keyboard modes -- default ASCII */
+#define MV_KEY_MODE_ASCII 0x01
+/*
+ * This mode one event is sent when a key is pressed,
+ * and another one is send when a key is released.
+ */
+#define MV_KEY_MODE_SCANCODE 0x00
+
+
+/* these defines match with the linux keyboard range
+ for ioctls functions for the keyboard interface.
+ 0x4BXX --- keyboard related functions
+ */
+#define MV_KDGKBMODE 0x4B44 /* gets current keyboard mode */
+#define MV_KDSKBMODE 0x4B45 /* sets current keyboard mode */
+
+/*
+ * Message generated by input devices controlled by MicroWindows.
+ */
+struct MW_UID_MESSAGE
+{
+ enum MW_INPUT_DEVICE_TYPE type; /* device type */
+ union
+ {
+ /* fired when keyboard events are raised */
+ struct kbd_t {
+ unsigned short code; /* keycode or scancode */
+ unsigned char modifiers; /* key modifiers */
+ unsigned char mode; /* current Kbd mode */
+ } kbd;
+
+ /* fired when position events are raised, mouse, touch screen, etc */
+ struct pos_t {
+ unsigned short btns; /* indicates which buttons are pressed */
+ short x; /* x location */
+ short y; /* y location */
+ short z; /* z location, 0 for 2D */
+ } pos;
+
+ /* fired by a timer device periodically */
+ struct timer_t {
+ unsigned long frt; /* free running timer */
+ unsigned long seq; /* sequence number */
+ } tmr;
+
+ } m;
+};
+
+
+/*
+ * API for creating/closing/accessing the message queue used by the micro
+ * input device interface. All functions in this interface returns a
+ * zero ( 0 ) on success. One exception for that is the "read" routine
+ * that returns the number of bytes read. Negaive numbers indicate errors
+ *
+ * The implementation of the message queue for RTEMS uses a POSIX message
+ * queue interface. It should be very portable among systems with a POSIX
+ * support.
+ */
+
+/* creates the message queue that holds events from the input devices */
+extern int uid_open_queue( const char *q_name, int flags, size_t max_msgs );
+
+/* closes message queue */
+extern int uid_close_queue( void );
+
+/*
+ * reads a message from the queue. It waits up to the specified
+ * timeout in mili-seconds.
+ */
+extern int uid_read_message( struct MW_UID_MESSAGE *m, unsigned long timeout );
+
+/* write a message to the queue */
+extern int uid_write_message( struct MW_UID_MESSAGE *m );
+
+
+/* register device to insert data to the queue */
+extern int uid_register_device( int fd, const char *q_name );
+
+/* unregister device to stop adding messages to the queue */
+extern int uid_unregister_device( int fd );
+
+/* set the keyboard */
+extern int uid_set_kbd_mode( int fd, int mode, int *old_mode );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MW_UID_H */
diff --git a/cpukit/libmisc/rtmonuse/rtmonuse.c b/cpukit/libmisc/rtmonuse/rtmonuse.c
new file mode 100644
index 0000000000..14fca3b0eb
--- /dev/null
+++ b/cpukit/libmisc/rtmonuse/rtmonuse.c
@@ -0,0 +1,208 @@
+/*
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include <rtems/rtmonuse.h>
+
+typedef struct {
+ rtems_id id;
+ uint32_t count;
+ uint32_t missed_count;
+ uint32_t min_cpu_time;
+ uint32_t max_cpu_time;
+ uint32_t total_cpu_time;
+ uint32_t min_wall_time;
+ uint32_t max_wall_time;
+ uint32_t total_wall_time;
+} Period_usage_t;
+
+Period_usage_t *Period_usage_Information;
+
+/*PAGE
+ *
+ * Period_usage_Initialize
+ */
+
+void Period_usage_Initialize( void )
+{
+ int maximum;
+
+ maximum = _Configuration_Table->RTEMS_api_configuration->maximum_periods;
+
+ Period_usage_Information = malloc( sizeof(Period_usage_t) * (maximum+1) );
+
+ Period_usage_Reset();
+}
+
+/*PAGE
+ *
+ * Period_usage_Reset
+ */
+
+void Period_usage_Reset( void )
+{
+ uint32_t i;
+ Period_usage_t *the_usage;
+
+ for ( i=0 ;
+ i<_Configuration_Table->RTEMS_api_configuration->maximum_periods ;
+ i++ ) {
+ the_usage = &Period_usage_Information[ i ];
+
+ the_usage->count = 0;
+ the_usage->missed_count = 0;
+ the_usage->min_cpu_time = 0xFFFFFFFF;
+ the_usage->max_cpu_time = 0;
+ the_usage->total_cpu_time = 0;
+ the_usage->min_wall_time = 0xFFFFFFFF;
+ the_usage->max_wall_time = 0;
+ the_usage->total_wall_time = 0;
+
+ }
+}
+
+/*PAGE
+ *
+ * Period_usage_Update
+ */
+
+void Period_usage_Update(
+ rtems_id id
+)
+{
+ rtems_rate_monotonic_period_status rm_status;
+ rtems_status_code status;
+ Period_usage_t *the_usage;
+
+ assert( Period_usage_Information );
+
+ status = rtems_rate_monotonic_get_status( id, &rm_status );
+ assert( status == RTEMS_SUCCESSFUL );
+
+ the_usage = &Period_usage_Information[ rtems_get_index( id ) ];
+
+ the_usage->id = id;
+ the_usage->count++;
+ if ( rm_status.state == RATE_MONOTONIC_EXPIRED )
+ the_usage->missed_count++;
+ the_usage->total_cpu_time += rm_status.ticks_executed_since_last_period;
+ the_usage->total_wall_time += rm_status.ticks_since_last_period;
+
+ /*
+ * Update CPU time
+ */
+
+ if ( rm_status.ticks_executed_since_last_period < the_usage->min_cpu_time )
+ the_usage->min_cpu_time = rm_status.ticks_executed_since_last_period;
+
+ if ( rm_status.ticks_executed_since_last_period > the_usage->max_cpu_time )
+ the_usage->max_cpu_time = rm_status.ticks_executed_since_last_period;
+
+ /*
+ * Update Wall time
+ */
+
+ if ( rm_status.ticks_since_last_period < the_usage->min_wall_time )
+ the_usage->min_wall_time = rm_status.ticks_since_last_period;
+
+ if ( rm_status.ticks_since_last_period > the_usage->max_wall_time )
+ the_usage->max_wall_time = rm_status.ticks_since_last_period;
+
+}
+
+/*PAGE
+ *
+ * Period_usage_Dump
+ */
+
+void Period_usage_Dump( void )
+{
+ uint32_t i;
+ Period_usage_t *the_usage;
+ Rate_monotonic_Control *the_period;
+ uint32_t u32_name;
+ char *cname;
+ char name[5];
+ uint32_t api_index;
+ Objects_Information *information;
+
+ if ( !Period_usage_Information ) {
+ fprintf(stdout, "Period statistics library is not initialized\n" );
+ return;
+ }
+
+ fprintf(stdout, "Period information by period\n" );
+ fprintf(stdout, " ID OWNER PERIODS MISSED CPU TIME WALL TIME\n" );
+
+ /*
+ * RTEMS does not use an index of zero for object ids.
+ */
+
+ for ( i=1 ;
+ i<=_Configuration_Table->RTEMS_api_configuration->maximum_periods ;
+ i++ ) {
+ the_usage = &Period_usage_Information[ i ];
+ if ( the_usage->count == 0 )
+ continue;
+
+ the_period =
+ (Rate_monotonic_Control *)_Rate_monotonic_Information.local_table[ i ];
+
+ name[ 0 ] = ' ';
+ name[ 1 ] = ' ';
+ name[ 2 ] = ' ';
+ name[ 3 ] = ' ';
+ name[ 4 ] = '\0';
+
+ if ( the_period->owner ) {
+ api_index = _Objects_Get_API(the_period->owner->Object.id);
+ information = _Objects_Information_table[ api_index ][ 1 ];
+
+ if ( information->is_string ) {
+ cname = the_period->owner->Object.name;
+ name[ 0 ] = cname[0];
+ name[ 1 ] = cname[1];
+ name[ 2 ] = cname[2];
+ name[ 3 ] = cname[3];
+ name[ 4 ] = '\0';
+ } else {
+ u32_name = (uint32_t )the_period->owner->Object.name;
+ name[ 0 ] = (u32_name >> 24) & 0xff;
+ name[ 1 ] = (u32_name >> 16) & 0xff;
+ name[ 2 ] = (u32_name >> 8) & 0xff;
+ name[ 3 ] = (u32_name >> 0) & 0xff;
+ name[ 4 ] = '\0';
+ }
+ }
+
+ if ( !isprint(name[0]) ) name[0] = '*';
+ if ( !isprint(name[1]) ) name[1] = '*';
+ if ( !isprint(name[2]) ) name[2] = '*';
+ if ( !isprint(name[3]) ) name[3] = '*';
+
+
+ fprintf(stdout,
+ "0x%08x %4s %6d %3d %d/%d/%5.2f %d/%d/%3.2f\n",
+ the_usage->id,
+ name,
+ the_usage->count,
+ the_usage->missed_count,
+ the_usage->min_cpu_time,
+ the_usage->max_cpu_time,
+ (double) the_usage->total_cpu_time / (double) the_usage->count,
+ the_usage->min_wall_time,
+ the_usage->max_wall_time,
+ (double) the_usage->total_wall_time / (double) the_usage->count
+ );
+ }
+}
diff --git a/cpukit/libmisc/rtmonuse/rtmonuse.h b/cpukit/libmisc/rtmonuse/rtmonuse.h
new file mode 100644
index 0000000000..2741698738
--- /dev/null
+++ b/cpukit/libmisc/rtmonuse/rtmonuse.h
@@ -0,0 +1,18 @@
+/*
+ * $Id$
+ */
+
+#ifndef __RATE_MONOTONIC_USAGE_h
+#define __RATE_MONOTONIC_USAGE_h
+
+void Period_usage_Initialize( void );
+
+void Period_usage_Reset( void );
+
+void Period_usage_Update(
+ rtems_id id
+);
+
+void Period_usage_Dump( void );
+
+#endif
diff --git a/cpukit/libmisc/serdbg/README b/cpukit/libmisc/serdbg/README
new file mode 100644
index 0000000000..338249c928
--- /dev/null
+++ b/cpukit/libmisc/serdbg/README
@@ -0,0 +1,138 @@
+#
+# $Id$
+#
+
+This directory contains three useful packages related to the termios I/O
+system:
+
+PACKAGE SERDBGIO
+================
+"serdbgio" provides the "serial gdb" standard I/O functions "getDebugChar"
+and "putDebugChar" for any device driver supporting polled termios mode.
+
+The initialization function "serdbg_open" opens the v.24 port intended
+for the serial debug connection, and sets the desired baud rate. The
+"getDebugChar" and "putDebugChar" functions then interact with the
+corresponding driver using the calls intended for polled termios
+operation.
+
+Specification for the debug device, baud rate and other parameters is
+done in a global structure of type "serdbg_conf_t". A configuration
+mechanism quite similar to the overall RTEMS configuration is available.
+
+PACKAGE SERDBG
+==============
+"serdbg" provides a means to optionally initialize and/or start a
+serial gdb session as soon as possible, this means as soon as all
+drivers have been initialized. The serial debug I/O functions can
+either be integrated as special routines of the BSP drivers, or using
+the package "serdbgio"
+
+PACKAGE TERMIOS_PRINTK
+======================
+"termios_printk" provides a standard output function suitable to use
+with "printk". It uses the same technique as serdbgio, hooking the
+interface between a polled device driver and the termios system.
+
+
+REQUIREMENTS
+============
+
+- These two packages can be used with any polled termios device
+driver.
+- For standard initialization, they need a modified "bsppost.c"
+to perform the initialization calls.
+
+USAGE
+=====
+
+For using these packages add the following to your "init" module or
+your "system.h" file (Note: most macro settings fall back to a
+default, if not set.):
+
+/*
+ * CONFIGURE_USE_SERDBG
+ * set this macro, if you want to connect gdb over a serial line
+ * when set, the debug stub will be connected after driver
+ * initialization in "bsppost.c"
+ */
+#define CONFIGURE_USE_SERDBG
+
+
+/*
+ * CONFIGURE_SERDBG_SKIP_INIT_BKPT
+ * set this macro, if you do not want the gdb interface to wait for a
+ * debugger connection directly after initialization
+ * If you set this macro, the gdb stub will only hook various
+ * exception vectors when called from "bsppost.c".
+ */
+/* #define CONFIGURE_SERDBG_SKIP_INIT_BKPT */
+
+/*
+ * CONFIGURE_SERDBG_USE_POLLED_TERMIOS
+ * set this macro, if you want "serdbgio" to provide the I/O
+ * functions for the serial gdb connection
+ */
+#define CONFIGURE_SERDBG_USE_POLLED_TERMIOS
+
+/*
+ * CONFIGURE_SERDBG_DEVNAME
+ * use this macro to specify the serial device to use
+ * for "serdbgio".
+ * Only used, when CONFIGURE_SERDBG_USE_POLLED_TERMIOS is set
+ */
+#define CONFIGURE_SERDBG_DEVNAME "/dev/tty03"
+
+/*
+ * CONFIGURE_SERDBG_BAUDRATE
+ * use this macro to specify the baud rate to use
+ * for "serdbgio".
+ * Only used, when CONFIGURE_SERDBG_USE_POLLED_TERMIOS is set
+ */
+#define CONFIGURE_SERDBG_BAUDRATE 57600
+
+/*
+ * CONFIGURE_SERDBG_CALLOUT
+ * use this macro to specify a routine that will called during I/O polling
+ * Only used, when CONFIGURE_SERDBG_USE_POLLED_TERMIOS is set
+ * This function of type "void pollfnc(void)" can be used for e.g.
+ * tickling a watchdog
+ */
+/* #define CONFIGURE_SERDBG_CALLOUT tickle_my_watchdog_fnc */
+
+#include <serdbgcnf.h>
+
+/*
+ * CONFIGURE_USE_TERMIOS_PRINTK
+ * set this macro, if you want printk output to be sent to a serial
+ * driver using the polled termios interface
+ * when set, the printk output function will be connected after driver
+ * initialization in "bsppost.c"
+ */
+#define CONFIGURE_USE_TERMIOS_PRINTK
+
+/*
+ * CONFIGURE_TERMIOS_PRINTK_DEVNAME
+ * use this macro to specify the serial device to use
+ * for printk output.
+ * Only used, when CONFIGURE_USE_TERMIOS_PRINTK is set
+ */
+#define CONFIGURE_TERMIOS_PRINTK_DEVNAME "/dev/console"
+
+/*
+ * CONFIGURE_TERMIOS_PRINTK_BAUDRATE
+ * use this macro to specify the baudrate to use
+ * for printk output.
+ * Only used, when CONFIGURE_USE_TERMIOS_PRINTK is set
+ */
+#define CONFIGURE_TERMIOS_PRINTK_BAUDRATE 9600
+
+/*
+ * CONFIGURE_TERMIOS_PRINTK_CALLOUT
+ * use this macro to specify a routine that will called during I/O polling
+ * This function of type "void pollfnc(void)" can be used for e.g.
+ * tickling a watchdog
+ */
+/* #define CONFIGURE_TERMIOS_PRINTK_CALLOUT tickle_my_watchdog_fnc */
+
+#include <termios_printk_cnf.h>
diff --git a/cpukit/libmisc/serdbg/serdbg.c b/cpukit/libmisc/serdbg/serdbg.c
new file mode 100644
index 0000000000..4bca324934
--- /dev/null
+++ b/cpukit/libmisc/serdbg/serdbg.c
@@ -0,0 +1,94 @@
+/*===============================================================*\
+| Project: RTEMS remote gdb over serial line |
++-----------------------------------------------------------------+
+| File: serdbg.c |
++-----------------------------------------------------------------+
+| Copyright (c) 2002 IMD |
+| Ingenieurbuero fuer Microcomputertechnik Th. Doerfler |
+| <Thomas.Doerfler@imd-systems.de> |
+| all rights reserved |
++-----------------------------------------------------------------+
+| this file contains intialization and utility functions to add |
+| a gdb remote debug stub to an RTEMS system |
+| |
++-----------------------------------------------------------------+
+| date history ID |
+| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
+| 04.04.02 creation doe |
+\*===============================================================*/
+/*
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <rtems/serdbg.h>
+
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int serdbg_init_dbg
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| initialize remote gdb session over serial line |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ void
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| rtems_status_code |
+\*=========================================================================*/
+{
+ static boolean is_initialized = FALSE;
+
+ rtems_status_code rc = RTEMS_SUCCESSFUL;
+ extern void set_debug_traps(void);
+ extern void breakpoint(void);
+
+ if (is_initialized) {
+ return RTEMS_SUCCESSFUL;
+ }
+ is_initialized = TRUE;
+ /*
+ * try to open serial device
+ */
+ if (rc == RTEMS_SUCCESSFUL) {
+ if ((serdbg_conf.open_io != NULL) &&
+ (0 > serdbg_conf.open_io(serdbg_conf.devname,serdbg_conf.baudrate))) {
+ fprintf(stderr,
+ "remote_gdb_init: cannot open device %s "
+ "for gdb connection:%s\n",serdbg_conf.devname,strerror(errno));
+ rc = RTEMS_IO_ERROR;
+ }
+ }
+ /*
+ * initialize gdb stub
+ */
+ if (rc == RTEMS_SUCCESSFUL) {
+ set_debug_traps();
+ }
+ /*
+ * now activate gdb stub
+ */
+ if ((rc == RTEMS_SUCCESSFUL) &&
+ !serdbg_conf.skip_init_bkpt) {
+ breakpoint();
+ }
+
+ /*
+ * return to original function
+ * this may be already unter gdb control
+ */
+ return rc;
+}
diff --git a/cpukit/libmisc/serdbg/serdbg.h b/cpukit/libmisc/serdbg/serdbg.h
new file mode 100644
index 0000000000..00d5d827e1
--- /dev/null
+++ b/cpukit/libmisc/serdbg/serdbg.h
@@ -0,0 +1,174 @@
+/*===============================================================*\
+| Project: RTEMS remote gdb over serial line |
++-----------------------------------------------------------------+
+| File: serdbg.h |
++-----------------------------------------------------------------+
+| Copyright (c) 2002 IMD |
+| Ingenieurbuero fuer Microcomputertechnik Th. Doerfler |
+| <Thomas.Doerfler@imd-systems.de> |
+| all rights reserved |
++-----------------------------------------------------------------+
+| this file declares intialization functions to add |
+| a gdb remote debug stub to an RTEMS system |
+| |
++-----------------------------------------------------------------+
+| date history ID |
+| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
+| 04.04.02 creation doe |
+\*===============================================================*/
+/*
+ * $Id$
+ */
+#ifndef _SERDBG_H
+#define _SERDBG_H
+
+#include <rtems.h>
+#include <termios.h>
+
+typedef struct {
+ uint32_t baudrate; /* debug baud rate, e.g. 57600 */
+ void (*callout)(void); /* callout pointer during polling */
+ int (*open_io)(const char *dev_name,uint32_t baudrate); /* I/O open fnc */
+ const char *devname; /* debug device, e.g. "/dev/tty01" */
+ uint8_t skip_init_bkpt; /* if TRUE, do not stop when initializing */
+} serdbg_conf_t;
+
+/*
+ * must be defined in init module...
+ */
+extern serdbg_conf_t serdbg_conf;
+
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+void putDebugChar
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| send character to remote debugger |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ char c /* char to send */
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| <none> |
+\*=========================================================================*/
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int getDebugChar
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| get character from remote debugger |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ void /* <none> */
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| <none> |
+\*=========================================================================*/
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+void serdbg_exceptionHandler
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| hook directly to an exception vector |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ int vecnum, /* vector index to hook at */
+ void *vector /* address of handler function */
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| <none> |
+\*=========================================================================*/
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int serdbg_init
+(
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| initialize remote gdb session over serial line |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+ void
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| rtems_status_code |
+\*=========================================================================*/
+
+/*
+ * stuff from serdbgio.c
+ */
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int serdbg_open
+
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| try to open given serial debug port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ const char *dev_name, /* name of device to open */
+ uint32_t baudrate /* baud rate to use */
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| 0 on success, -1 and errno otherwise |
+\*=========================================================================*/
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+void putDebugChar
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| send one character to serial port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ char c /* character to print */
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| <none> |
+\*=========================================================================*/
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int getDebugChar
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| wait for one character from serial port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ void /* none */
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| received character |
+\*=========================================================================*/
+
+#endif /* _SERDBG_H */
diff --git a/cpukit/libmisc/serdbg/serdbgcnf.h b/cpukit/libmisc/serdbg/serdbgcnf.h
new file mode 100644
index 0000000000..024e545d5c
--- /dev/null
+++ b/cpukit/libmisc/serdbg/serdbgcnf.h
@@ -0,0 +1,81 @@
+/*===============================================================*\
+| Project: RTEMS configure remote gdb over serial line |
++-----------------------------------------------------------------+
+| File: serdbgcnf.h |
++-----------------------------------------------------------------+
+| Copyright (c) 2002 IMD |
+| Ingenieurbuero fuer Microcomputertechnik Th. Doerfler |
+| <Thomas.Doerfler@imd-systems.de> |
+| all rights reserved |
++-----------------------------------------------------------------+
+| this file declares intialization functions to add |
+| a gdb remote debug stub to an RTEMS system |
+| |
++-----------------------------------------------------------------+
+| date history ID |
+| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
+| 13.05.02 creation doe |
+\*===============================================================*/
+/*
+ * $Id$
+ */
+#ifndef _SERDBGCNF_H
+#define _SERDBGCNF_H
+
+#include <rtems/serdbg.h>
+
+#ifdef CONFIGURE_INIT
+
+/*
+ * fallback for baud rate to use
+ */
+#ifndef CONFIGURE_SERDBG_BAUDRATE
+#define CONFIGURE_SERDBG_BAUDRATE 9600
+#endif
+
+/*
+ * fallback for device name to use
+ */
+#ifndef CONFIGURE_SERDBG_DEVNAME
+#define CONFIGURE_SERDBG_DEVNAME "/dev/tty01"
+#endif
+
+/*
+ * fill in serdbg_conf structure
+ */
+serdbg_conf_t serdbg_conf = {
+ CONFIGURE_SERDBG_BAUDRATE,
+
+#ifdef CONFIGURE_SERDBG_CALLOUT
+ CONFIGURE_SERDBG_CALLOUT,
+#else
+ NULL,
+#endif
+
+#ifdef CONFIGURE_SERDBG_USE_POLLED_TERMIOS
+ serdbg_open,
+#else
+ NULL,
+#endif
+
+ CONFIGURE_SERDBG_DEVNAME,
+
+#ifdef CONFIGURE_SERDBG_SKIP_INIT_BKPT
+ TRUE,
+#else
+ FALSE,
+#endif
+};
+
+int serdbg_init(void) {
+#ifdef CONFIGURE_USE_SERDBG
+ extern int serdbg_init_dbg(void);
+ return serdbg_init_dbg();
+#else
+ return 0;
+#endif
+}
+
+#endif /* CONFIGURE_INIT */
+
+#endif /* _SERDBGCNF_H */
diff --git a/cpukit/libmisc/serdbg/serdbgio.c b/cpukit/libmisc/serdbg/serdbgio.c
new file mode 100644
index 0000000000..494a2fab0b
--- /dev/null
+++ b/cpukit/libmisc/serdbg/serdbgio.c
@@ -0,0 +1,256 @@
+/*===============================================================*\
+| File: serdbgio.c |
++-----------------------------------------------------------------+
+| Copyright (c) 2002 IMD |
+| Ingenieurbuero fuer Microcomputertechnik Th. Doerfler |
+| Hebststr. 8, 82178 Puchheim, Germany |
+| <Thomas.Doerfler@imd-systems.de> |
+| The license and distribution terms for this file may be |
+| found in the file LICENSE in this distribution or at |
+| http://www.rtems.com/license/LICENSE. |
+| all rights reserved |
++-----------------------------------------------------------------+
+| TERMIOS serial gdb interface support |
+| the functions in this file allow the standard gdb stubs like |
+| "m68k-stub.c" to access any serial interfaces that work with |
+| RTEMS termios in polled mode |
+| |
++-----------------------------------------------------------------+
+| date history ID |
+| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
+| 10.05.02 creation doe |
+|*****************************************************************|
+|* $Id$
+ *
+|*****************************************************************|
+\*===============================================================*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/libio_.h>
+#include <errno.h>
+#include <unistd.h> /* close */
+#include <stdio.h>
+#include <fcntl.h>
+#include <termios.h>
+
+#include <rtems/termiostypes.h>
+#include <rtems/serdbg.h>
+
+
+/*
+ * internal variables
+ */
+int serdbg_fd = -1;
+struct rtems_termios_tty *serdbg_tty;
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int serdbg_open
+
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| try to open given serial debug port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ const char *dev_name, /* name of device to open */
+ uint32_t baudrate /* baud rate to use */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| 0 on success, -1 and errno otherwise |
+\*=========================================================================*/
+{
+ boolean err_occurred = FALSE;
+ rtems_libio_t *iop = NULL;
+ struct termios act_termios;
+ tcflag_t baudcode = B0;
+
+#define FD_STORE_CNT 3
+ int fd_store[FD_STORE_CNT];
+ int fd_store_used = 0;
+
+ /*
+ * translate baudrate into baud code
+ */
+ switch(baudrate) {
+ case 50: baudcode = B50; break;
+ case 75: baudcode = B75; break;
+ case 110: baudcode = B110; break;
+ case 134: baudcode = B134; break;
+ case 150: baudcode = B150; break;
+ case 200: baudcode = B200; break;
+ case 300: baudcode = B300; break;
+ case 600: baudcode = B600; break;
+ case 1200: baudcode = B1200; break;
+ case 1800: baudcode = B1800; break;
+ case 2400: baudcode = B2400; break;
+ case 4800: baudcode = B4800; break;
+ case 9600: baudcode = B9600; break;
+ case 19200: baudcode = B19200; break;
+ case 38400: baudcode = B38400; break;
+ case 57600: baudcode = B57600; break;
+ case 115200: baudcode = B115200; break;
+ case 230400: baudcode = B230400; break;
+ case 460800: baudcode = B460800; break;
+ default : err_occurred = TRUE; errno = EINVAL; break;
+ }
+
+ /*
+ * open device for serdbg operation
+ * skip any fds that are between 0..2, because they are
+ * reserved for stdin/out/err
+ */
+ if (!err_occurred &&
+ (dev_name != NULL) &&
+ (dev_name[0] != '\0')) {
+ do {
+ serdbg_fd = open(dev_name,O_RDWR);
+ if (serdbg_fd < 0) {
+ err_occurred = TRUE;
+ }
+ else {
+ if (serdbg_fd < 3) {
+ if (fd_store_used >= FD_STORE_CNT) {
+ err_occurred = TRUE;
+ }
+ else {
+ fd_store[fd_store_used++] = serdbg_fd;
+ }
+ }
+ }
+ } while (!err_occurred &&
+ (serdbg_fd < 3));
+ }
+ /*
+ * close any fds, that have been placed in fd_store
+ * so fd 0..2 are reusable again
+ */
+ while (--fd_store_used >= 0) {
+ close(fd_store[fd_store_used]);
+ }
+
+ /*
+ * capture tty structure
+ */
+ if (!err_occurred) {
+ iop = &rtems_libio_iops[serdbg_fd];
+ serdbg_tty = iop->data1;
+ }
+ /*
+ * set device baudrate
+ * (and transp mode, this is not really needed)
+ * ...
+ */
+ /*
+ * ... get fd settings
+ */
+ if (!err_occurred &&
+ (0 != tcgetattr(serdbg_fd,&act_termios))) {
+ err_occurred = TRUE;
+ }
+ if (!err_occurred) {
+ act_termios.c_iflag
+ &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
+ |INLCR|IGNCR|ICRNL|IXON);
+ act_termios.c_oflag
+ &= ~OPOST;
+
+ act_termios.c_lflag
+ &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+
+ cfsetospeed(&act_termios,baudcode);
+ cfsetispeed(&act_termios,baudcode);
+
+ if (0 != tcsetattr(serdbg_fd,TCSANOW,&act_termios)) {
+ err_occurred = TRUE;
+ }
+ }
+ return (err_occurred
+ ? -1
+ : 0);
+}
+
+void putDebugChar(char c) __attribute__ ((__weak__));
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+void putDebugChar
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| send one character to serial port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ char c /* character to print */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| <none> |
+\*=========================================================================*/
+{
+ /*
+ * call serdbg polling callout, if available
+ */
+ if (serdbg_conf.callout != NULL) {
+ serdbg_conf.callout();
+ }
+ /*
+ * check, whether debug serial port is available
+ */
+ if ((serdbg_tty != NULL) &&
+ (serdbg_tty->device.write != NULL)) {
+ /*
+ * send character to debug serial port
+ */
+ serdbg_tty->device.write(serdbg_tty->minor,&c,1);
+ }
+}
+
+int getDebugChar(void) __attribute__ ((__weak__));
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int getDebugChar
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| wait for one character from serial port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ void /* none */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| received character |
+\*=========================================================================*/
+{
+ int c = -1;
+ /*
+ * check, whether debug serial port is available
+ */
+ if ((serdbg_tty != NULL) &&
+ (serdbg_tty->device.pollRead != NULL)) {
+ do {
+ /*
+ * call serdbg polling callout, if available
+ */
+ if (serdbg_conf.callout != NULL) {
+ serdbg_conf.callout();
+ }
+ /*
+ * get character from debug serial port
+ */
+ c = serdbg_tty->device.pollRead(serdbg_tty->minor);
+ } while (c < 0);
+ }
+ return c;
+}
diff --git a/cpukit/libmisc/serdbg/termios_printk.c b/cpukit/libmisc/serdbg/termios_printk.c
new file mode 100644
index 0000000000..6e31bbcfd0
--- /dev/null
+++ b/cpukit/libmisc/serdbg/termios_printk.c
@@ -0,0 +1,237 @@
+/*===============================================================*\
+| File: termios_printk.c |
++-----------------------------------------------------------------+
+| Copyright (c) 2002 IMD |
+| Ingenieurbuero fuer Microcomputertechnik Th. Doerfler |
+| Hebststr. 8, 82178 Puchheim, Germany |
+| <Thomas.Doerfler@imd-systems.de> |
+| The license and distribution terms for this file may be |
+| found in the file LICENSE in this distribution or at |
+| http://www.rtems.com/license/LICENSE. |
+| all rights reserved |
++-----------------------------------------------------------------+
+| TERMIOS printk support |
+| this module performs low-level printk output using |
+| a polled termios driver |
+| |
++-----------------------------------------------------------------+
+| date history ID |
+| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
+| 13.05.02 creation doe |
+|*****************************************************************|
+|* $Id$
+ *
+|*****************************************************************|
+\*===============================================================*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/libio_.h>
+#include <errno.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <termios.h>
+
+#include <rtems/termiostypes.h>
+#include <rtems/bspIo.h>
+#include <rtems/termios_printk.h>
+
+/*
+ * internal variables
+ */
+int termios_printk_fd = -1;
+struct rtems_termios_tty *termios_printk_tty;
+
+static void _termios_printk_null_char( char c ) {return;}
+
+BSP_output_char_function_type BSP_output_char = _termios_printk_null_char;
+BSP_polling_getchar_function_type BSP_poll_char;
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+void termios_printk_outputchar
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| send one character to serial port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ char c /* character to print */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| <none> |
+\*=========================================================================*/
+{
+ static const char cr = '\r';
+ /*
+ * check, whether printk serial port is available
+ */
+
+ if ((termios_printk_tty != NULL) &&
+ (termios_printk_tty->device.write != NULL)) {
+ /*
+ * call termios_printk polling callout, if available
+ */
+ if (termios_printk_conf.callout != NULL) {
+ termios_printk_conf.callout();
+ }
+ /*
+ * send character to debug serial port
+ */
+ if (c == '\n') {
+ termios_printk_tty->device.write(termios_printk_tty->minor,&cr,1);
+ }
+ termios_printk_tty->device.write(termios_printk_tty->minor,&c,1);
+ }
+}
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+char termios_printk_inputchar
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| wait for one character from serial port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ void /* none */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| received character |
+\*=========================================================================*/
+{
+ int c = -1;
+ /*
+ * check, whether debug serial port is available
+ */
+ if ((termios_printk_tty != NULL) &&
+ (termios_printk_tty->device.pollRead != NULL)) {
+ do {
+ /*
+ * call termios_printk polling callout, if available
+ */
+ if (termios_printk_conf.callout != NULL) {
+ termios_printk_conf.callout();
+ }
+ /*
+ * get character from debug serial port
+ */
+ c = termios_printk_tty->device.pollRead(termios_printk_tty->minor);
+ } while (c < 0);
+ }
+ return c;
+}
+
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int termios_printk_open
+
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| try to open given serial debug port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ const char *dev_name, /* name of device to open */
+ uint32_t baudrate /* baud rate to use */
+)
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| 0 on success, -1 and errno otherwise |
+\*=========================================================================*/
+{
+ boolean err_occurred = FALSE;
+ rtems_libio_t *iop = NULL;
+ struct termios act_termios;
+ tcflag_t baudcode = B0;
+
+ if (termios_printk_fd >= 0) {
+ /*
+ * already initialized
+ */
+ return 0;
+ }
+ /*
+ * translate baudrate into baud code
+ */
+ switch(baudrate) {
+ case 50: baudcode = B50; break;
+ case 75: baudcode = B75; break;
+ case 110: baudcode = B110; break;
+ case 134: baudcode = B134; break;
+ case 150: baudcode = B150; break;
+ case 200: baudcode = B200; break;
+ case 300: baudcode = B300; break;
+ case 600: baudcode = B600; break;
+ case 1200: baudcode = B1200; break;
+ case 1800: baudcode = B1800; break;
+ case 2400: baudcode = B2400; break;
+ case 4800: baudcode = B4800; break;
+ case 9600: baudcode = B9600; break;
+ case 19200: baudcode = B19200; break;
+ case 38400: baudcode = B38400; break;
+ case 57600: baudcode = B57600; break;
+ case 115200: baudcode = B115200; break;
+ case 230400: baudcode = B230400; break;
+ case 460800: baudcode = B460800; break;
+ default : err_occurred = TRUE; errno = EINVAL; break;
+ }
+ /*
+ * open device for serdbg operation
+ */
+ if (!err_occurred &&
+ (dev_name != NULL) &&
+ (dev_name[0] != '\0')) {
+ termios_printk_fd = open(dev_name,O_RDWR);
+ if (termios_printk_fd < 0) {
+ err_occurred = TRUE;
+ }
+ }
+ /*
+ * capture tty structure
+ */
+ if (!err_occurred) {
+ iop = &rtems_libio_iops[termios_printk_fd];
+ termios_printk_tty = iop->data1;
+ }
+ /*
+ * set device baudrate
+ * (and transp mode, this is not really needed)
+ * ...
+ */
+ /*
+ * ... get fd settings
+ */
+ if (!err_occurred &&
+ (0 != tcgetattr(termios_printk_fd,&act_termios))) {
+ err_occurred = TRUE;
+ }
+ if (!err_occurred) {
+
+ cfsetospeed(&act_termios,baudcode);
+ cfsetispeed(&act_termios,baudcode);
+
+ if (0 != tcsetattr(termios_printk_fd,TCSANOW,&act_termios)) {
+ err_occurred = TRUE;
+ }
+ }
+ if (!err_occurred) {
+ BSP_output_char = termios_printk_outputchar;
+ BSP_poll_char = termios_printk_inputchar;
+ }
+ return (err_occurred
+ ? -1
+ : 0);
+}
diff --git a/cpukit/libmisc/serdbg/termios_printk.h b/cpukit/libmisc/serdbg/termios_printk.h
new file mode 100644
index 0000000000..d3a3703b11
--- /dev/null
+++ b/cpukit/libmisc/serdbg/termios_printk.h
@@ -0,0 +1,95 @@
+/*===============================================================*\
+| Project: RTEMS remote gdb over serial line |
++-----------------------------------------------------------------+
+| File: termios_printk.h |
++-----------------------------------------------------------------+
+| Copyright (c) 2002 IMD |
+| Ingenieurbuero fuer Microcomputertechnik Th. Doerfler |
+| <Thomas.Doerfler@imd-systems.de> |
+| all rights reserved |
++-----------------------------------------------------------------+
+| this file declares intialization functions to add |
+| printk polled output via termios polled drivers |
+| |
++-----------------------------------------------------------------+
+| date history ID |
+| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
+| 13.04.02 creation doe |
+\*===============================================================*/
+/*
+ * $Id$
+ */
+#ifndef _TERMIOS_PRINTK_H
+#define _TERMIOS_PRINTK_H
+
+#include <rtems.h>
+#include <termios.h>
+
+typedef struct {
+ uint32_t baudrate; /* debug baud rate, e.g. 57600 */
+ void (*callout)(void); /* callout pointer during polling */
+ const char *devname; /* debug device, e.g. "/dev/tty01" */
+} termios_printk_conf_t;
+
+/*
+ * must be defined in init module...
+ */
+extern termios_printk_conf_t termios_printk_conf;
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+void termios_printk_outputchar
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| send one character to serial port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ char c /* character to print */
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| <none> |
+\*=========================================================================*/
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+char termios_printk_inputchar
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| wait for one character from serial port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ void /* none */
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| received character |
+\*=========================================================================*/
+
+
+/*=========================================================================*\
+| Function: |
+\*-------------------------------------------------------------------------*/
+int termios_printk_open
+
+/*-------------------------------------------------------------------------*\
+| Purpose: |
+| try to open given serial debug port |
++---------------------------------------------------------------------------+
+| Input Parameters: |
+\*-------------------------------------------------------------------------*/
+(
+ const char *dev_name, /* name of device to open */
+ uint32_t baudrate /* baud rate to use */
+ );
+/*-------------------------------------------------------------------------*\
+| Return Value: |
+| 0 on success, -1 and errno otherwise |
+\*=========================================================================*/
+#endif /* _TERMIOS_PRINTK_H */
diff --git a/cpukit/libmisc/serdbg/termios_printk_cnf.h b/cpukit/libmisc/serdbg/termios_printk_cnf.h
new file mode 100644
index 0000000000..55aea94d03
--- /dev/null
+++ b/cpukit/libmisc/serdbg/termios_printk_cnf.h
@@ -0,0 +1,70 @@
+/*===============================================================*\
+| Project: RTEMS configure remote gdb over serial line |
++-----------------------------------------------------------------+
+| File: termios_printk_cnf.h |
++-----------------------------------------------------------------+
+| Copyright (c) 2002 IMD |
+| Ingenieurbuero fuer Microcomputertechnik Th. Doerfler |
+| <Thomas.Doerfler@imd-systems.de> |
+| all rights reserved |
++-----------------------------------------------------------------+
+| this file declares intialization functions to add |
+| printk support via polled termios |
+| |
++-----------------------------------------------------------------+
+| date history ID |
+| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
+| 13.05.02 creation doe |
+\*===============================================================*/
+/*
+ * $Id$
+ */
+#ifndef _TERMIOS_PRINTK_CNF_H
+#define _TERMIOS_PRINTK_CNF_H
+
+#include <rtems/termios_printk.h>
+
+#ifdef CONFIGURE_INIT
+
+/*
+ * fallback for baud rate to use
+ */
+#ifndef CONFIGURE_TERMIOS_PRINTK_BAUDRATE
+#define CONFIGURE_TERMIOS_PRINTK_BAUDRATE 9600
+#endif
+
+/*
+ * fallback for device name to use
+ */
+#ifndef CONFIGURE_TERMIOS_PRINTK_DEVNAME
+#define CONFIGURE_TERMIOS_PRINTK_DEVNAME "/dev/console"
+#endif
+
+#ifdef CONFIGURE_USE_TERMIOS_PRINTK
+/*
+ * fill in termios_printk_conf structure
+ */
+termios_printk_conf_t termios_printk_conf = {
+ CONFIGURE_TERMIOS_PRINTK_BAUDRATE,
+
+#ifdef CONFIGURE_TERMIOS_PRINTK_CALLOUT
+ CONFIGURE_TERMIOS_PRINTK_CALLOUT,
+#else
+ NULL,
+#endif
+ CONFIGURE_TERMIOS_PRINTK_DEVNAME,
+};
+#endif
+
+int termios_printk_init(void) {
+#ifdef CONFIGURE_USE_TERMIOS_PRINTK
+ return termios_printk_open(termios_printk_conf.devname,
+ termios_printk_conf.baudrate);
+#else
+ return 0;
+#endif
+}
+
+#endif /* CONFIGURE_INIT */
+
+#endif /* _TERMIOS_PRINTK_CNF_H */
diff --git a/cpukit/libmisc/shell/README b/cpukit/libmisc/shell/README
new file mode 100644
index 0000000000..9798becc37
--- /dev/null
+++ b/cpukit/libmisc/shell/README
@@ -0,0 +1,27 @@
+#
+# $Id$
+#
+
+This directory contains a shell user extension
+primary features:
+
+ + create a user shell terminal task.
+
+This code has not been extensively tested. It is provided as a tool
+for RTEMS users to open more shell terminal.
+Suggestions and comments are appreciated.
+
+NOTES:
+
+1. printf() & getchar() works but you can't use
+ 0,1,2 like fildes. You need to use fileno(stdin),fileno(stdout),...
+
+2. You only need a termios dev to start a new session, add your new commands
+ and enjoy it.
+
+3. Telnetd daemon uses this (browse libnetworking/rtems_telnetd)
+ Enjoy it.
+
+FUTURE:
+
+1. Adding new commands in cmds.c to give file manegement to shell.
diff --git a/cpukit/libmisc/shell/cmds.c b/cpukit/libmisc/shell/cmds.c
new file mode 100644
index 0000000000..ba3a4b030e
--- /dev/null
+++ b/cpukit/libmisc/shell/cmds.c
@@ -0,0 +1,526 @@
+/*
+ * Author: Fernando RUIZ CASAS
+ *
+ * Work: fernando.ruiz@ctv.es
+ * Home: correo@fernando-ruiz.com
+ *
+ * This file is inspired in rtems_monitor & Chris John MyRightBoot
+ *
+ * But I want to make it more user friendly
+ * A 'monitor' command is added to adapt the call rtems monitor commands
+ * at my call procedure
+ *
+ * TODO: A lot of improvements of course.
+ * cp, mv, ...
+ * hexdump,
+ *
+ * More? Say me it, please...
+ *
+ * The BSP Specific are not welcome here.
+ *
+ * C&S welcome...
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <termios.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <time.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <stddef.h>
+
+#include <rtems.h>
+#include <rtems/monitor.h>
+#include <rtems/score/tod.h>
+
+#include <rtems/imfs.h>
+#include <rtems/shell.h>
+
+/* ----------------------------------------------- *
+ - str to int "0xaffe" "0b010010" "0123" "192939"
+ * ----------------------------------------------- */
+int str2int(char * s) {
+ int sign=1;
+ int base=10;
+ int value=0;
+ int digit;
+ if (!s) return 0;
+ if (*s) {
+ if (*s=='-') {
+ sign=-1;
+ s++;
+ if (!*s) return 0;
+ };
+ if (*s=='0') {
+ s++;
+ switch(*s) {
+ case 'x':
+ case 'X':s++;
+ base=16;
+ break;
+ case 'b':
+ case 'B':s++;
+ base=2;
+ break;
+ default :base=8;
+ break;
+ }
+ };
+ while (*s) {
+ switch(*s) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':digit=*s-'0';
+ break;
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':digit=*s-'A'+10;
+ break;
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':digit=*s-'a'+10;
+ break;
+ default:return value*sign;
+ };
+ if (digit>base) return value*sign;
+ value=value*base+digit;
+ s++;
+ };
+ };
+ return value*sign;
+}
+/*----------------------------------------------------------------------------*
+ * RAM MEMORY COMMANDS
+ *----------------------------------------------------------------------------*/
+
+#define mdump_adr (current_shell_env->mdump_adr) /* static value */
+
+int main_mdump(int argc,char * argv[]) {
+ unsigned char n,m,max=0;
+ int adr=mdump_adr;
+ unsigned char * pb;
+ if (argc>1) adr=str2int(argv[1]);
+ if (argc>2) max=str2int(argv[2]);
+ max/=16;
+ if (!max) max=20;
+ for (m=0;m<max;m++) {
+ fprintf(stdout,"0x%08X ",adr);
+ pb=(unsigned char*) adr;
+ for (n=0;n<16;n++)
+ fprintf(stdout,"%02X%c",pb[n],n==7?'-':' ');
+ for (n=0;n<16;n++) {
+ fprintf(stdout,"%c",isprint(pb[n])?pb[n]:'.');
+ };
+ fprintf(stdout,"\n");
+ adr+=16;
+ };
+ mdump_adr=adr;
+ return 0;
+}
+/*----------------------------------------------------------------------------*/
+int main_mwdump(int argc,char * argv[]) {
+ unsigned char n,m,max=0;
+ int adr=mdump_adr;
+ unsigned short * pw;
+ if (argc>1) adr=str2int(argv[1]);
+ if (argc>2) max=str2int(argv[2]);
+ max/=16;
+ if (!max) max=20;
+ for (m=0;m<max;m++) {
+ fprintf(stdout,"0x%08X ",adr);
+ pw=(unsigned short*) adr;
+ for (n=0;n<8;n++)
+ fprintf(stdout,"%02X %02X%c",pw[n]/0x100,pw[n]%0x100,n==3?'-':' ');
+ for (n=0;n<8;n++) {
+ fprintf(stdout,"%c",isprint(pw[n]/0x100)?pw[n]/0x100:'.');
+ fprintf(stdout,"%c",isprint(pw[n]%0x100)?pw[n]%0x100:'.');
+ };
+ fprintf(stdout,"\n");
+ adr+=16;
+ };
+ mdump_adr=adr;
+ return 0;
+}
+/*----------------------------------------------------------------------------*/
+int main_medit(int argc,char * argv[]) {
+ unsigned char * pb;
+ int n,i;
+ if (argc<3) {
+ fprintf(stdout,"too few arguments\n");
+ return 0;
+ };
+ pb=(unsigned char*)str2int(argv[1]);
+ i=2;
+ n=0;
+ while (i<=argc) {
+ pb[n++]=str2int(argv[i++])%0x100;
+ }
+ mdump_adr=(int)pb;
+ return main_mdump(0,NULL);
+}
+/*----------------------------------------------------------------------------*/
+int main_mfill(int argc,char * argv[]) {
+ int adr;
+ int size;
+ unsigned char value;
+ if (argc<4) {
+ fprintf(stdout,"too few arguments\n");
+ return 0;
+ };
+ adr =str2int(argv[1]);
+ size =str2int(argv[2]);
+ value=str2int(argv[3])%0x100;
+ memset((unsigned char*)adr,size,value);
+ mdump_adr=adr;
+ return main_mdump(0,NULL);
+}
+/*----------------------------------------------------------------------------*/
+int main_mmove(int argc,char * argv[]) {
+ int src;
+ int dst;
+ int size;
+ if (argc<4) {
+ fprintf(stdout,"too few arguments\n");
+ return 0;
+ };
+ dst =str2int(argv[1]);
+ src =str2int(argv[2]);
+ size =str2int(argv[3]);
+ memcpy((unsigned char*)dst,(unsigned char*)src,size);
+ mdump_adr=dst;
+ return main_mdump(0,NULL);
+}
+/*----------------------------------------------------------------------------*/
+#ifdef MALLOC_STATS /* /rtems/s/src/lib/libc/malloc.c */
+int main_malloc_dump(int argc,char * argv[]) {
+ void malloc_dump(void);
+ malloc_dump();
+ return 0;
+}
+#endif
+/*----------------------------------------------------------------------------
+ * Reset. Assumes that the watchdog is present.
+ *----------------------------------------------------------------------------*/
+int main_reset (int argc, char **argv)
+{
+ rtems_interrupt_level level;
+ fprintf(stdout,"Waiting for watchdog ... ");
+ tcdrain(fileno(stdout));
+
+ rtems_interrupt_disable (level);
+ for (;;)
+ ;
+ return 0;
+}
+/*----------------------------------------------------------------------------
+ * Alias. make an alias
+ *----------------------------------------------------------------------------*/
+int main_alias (int argc, char **argv)
+{
+ if (argc<3) {
+ fprintf(stdout,"too few arguments\n");
+ return 1;
+ };
+ if (!shell_alias_cmd(argv[1],argv[2])) {
+ fprintf(stdout,"unable to make an alias(%s,%s)\n",argv[1],argv[2]);
+ };
+ return 0;
+}
+/*-----------------------------------------------------------*
+ * Directory commands
+ *-----------------------------------------------------------*/
+int main_ls(int argc, char *argv[])
+{
+ char * fname;
+ DIR *dirp;
+ struct dirent *dp;
+ struct stat stat_buf;
+ struct passwd * pwd;
+ struct group * grp;
+ char * user;
+ char * group;
+ char sbuf[256];
+ char nbuf[1024];
+ int n,size;
+
+ fname=".";
+ if (argc>1) fname=argv[1];
+
+ if ((dirp = opendir(fname)) == NULL)
+ {
+ fprintf(stdout,"%s: No such file or directory.\n", fname);
+ return errno;
+ }
+ n=0;
+ size=0;
+ while ((dp = readdir(dirp)) != NULL)
+ {
+ strcpy(nbuf,fname);
+ if (nbuf[strlen(nbuf)-1]!='/') strcat(nbuf,"/");
+ strcat(nbuf,dp->d_name); /* always the fullpathname. Avoid ftpd problem.*/
+ if (stat(nbuf, &stat_buf) == 0)
+ { /* AWFUL buts works...*/
+ strftime(sbuf,sizeof(sbuf)-1,"%b %d %H:%M",gmtime(&stat_buf.st_mtime));
+ pwd=getpwuid(stat_buf.st_uid);
+ user=pwd?pwd->pw_name:"nouser";
+ grp=getgrgid(stat_buf.st_gid);
+ group=grp?grp->gr_name:"nogrp";
+ fprintf(stdout,"%c%c%c%c%c%c%c%c%c%c %3d %6.6s %6.6s %11d %s %s%c\n",
+ (S_ISLNK(stat_buf.st_mode)?('l'):
+ (S_ISDIR(stat_buf.st_mode)?('d'):('-'))),
+ (stat_buf.st_mode & S_IRUSR)?('r'):('-'),
+ (stat_buf.st_mode & S_IWUSR)?('w'):('-'),
+ (stat_buf.st_mode & S_IXUSR)?('x'):('-'),
+ (stat_buf.st_mode & S_IRGRP)?('r'):('-'),
+ (stat_buf.st_mode & S_IWGRP)?('w'):('-'),
+ (stat_buf.st_mode & S_IXGRP)?('x'):('-'),
+ (stat_buf.st_mode & S_IROTH)?('r'):('-'),
+ (stat_buf.st_mode & S_IWOTH)?('w'):('-'),
+ (stat_buf.st_mode & S_IXOTH)?('x'):('-'),
+ (int)stat_buf.st_nlink,
+ user,group,
+ (int)stat_buf.st_size,
+ sbuf,
+ dp->d_name,
+ S_ISDIR(stat_buf.st_mode)?'/':' ');
+ n++;
+ size+=stat_buf.st_size;
+ }
+ }
+ fprintf(stdout,"%d files %d bytes occupied\n",n,size);
+ closedir(dirp);
+ return 0;
+}
+/*-----------------------------------------------------------*/
+int main_pwd (int argc, char *argv[]) {
+ char dir[1024];
+ getcwd(dir,1024);
+ fprintf(stdout,"%s\n",dir);
+ return 0;
+}
+/*-----------------------------------------------------------*/
+int main_chdir (int argc, char *argv[]) {
+ char *dir;
+ dir="/";
+ if (argc>1) dir=argv[1];
+ if (chdir(dir)) {
+ fprintf(stdout,"chdir to '%s' failed:%s\n",dir,strerror(errno));
+ return errno;
+ };
+ return 0;
+}
+/*-----------------------------------------------------------*/
+int main_mkdir (int argc, char *argv[]) {
+ char *dir;
+ int n;
+ n=1;
+ while (n<argc) {
+ dir=argv[n++];
+ if (mkdir(dir,S_IRWXU|S_IRWXG|S_IRWXO)) {
+ fprintf(stdout,"mkdir '%s' failed:%s\n",dir,strerror(errno));
+ };
+ };
+ return errno;
+}
+/*-----------------------------------------------------------*/
+int main_rmdir (int argc, char *argv[])
+{
+ char *dir;
+ int n;
+ n=1;
+ while (n<argc) {
+ dir=argv[n++];
+ if (rmdir(dir)) fprintf(stdout,"rmdir '%s' failed:%s\n",dir,strerror(errno));
+ };
+ return errno;
+}
+/*-----------------------------------------------------------*/
+int main_chroot(int argc,char * argv[]) {
+ char * new_root="/";
+ if (argc==2) new_root=argv[1];
+ if (chroot(new_root)<0) {
+ fprintf(stdout,"error %s:chroot(%s);\n",strerror(errno),new_root);
+ return -1;
+ };
+ return 0;
+}
+/*-----------------------------------------------------------*/
+int main_cat (int argc, char *argv[])
+{
+ int n;
+ n=1;
+ while (n<argc) cat_file(stdout,argv[n++]);
+ return 0;
+}
+/*-----------------------------------------------------------*/
+int main_rm (int argc, char *argv[])
+{
+ int n;
+ n=1;
+ while (n<argc) {
+ if (unlink(argv[n])) {
+ fprintf(stdout,"error %s:rm %s\n",strerror(errno),argv[n]);
+ return -1;
+ };
+ n++;
+ };
+ return 0;
+}
+/*-----------------------------------------------------------*/
+/* date - print time and date */
+
+int main_date(int argc,char *argv[])
+{
+ time_t t;
+ time(&t);
+ fprintf(stdout,"%s", ctime(&t));
+ return 0;
+}
+/*-----------------------------------------------------------*/
+int main_logoff(int argc,char *argv[])
+{
+ fprintf(stdout,"logoff from the system...");
+ current_shell_env->exit_shell=TRUE;
+ return 0;
+}
+/*-----------------------------------------------------------*/
+int main_tty (int argc,char *argv[])
+{
+ fprintf(stdout,"%s\n",ttyname(fileno(stdin)));
+ return 0;
+}
+/*-----------------------------------------------------------*/
+int main_whoami(int argc,char *argv[])
+{
+ struct passwd * pwd;
+ pwd=getpwuid(getuid());
+ fprintf(stdout,"%s\n",pwd?pwd->pw_name:"nobody");
+ return 0;
+}
+/*-----------------------------------------------------------*/
+int main_id (int argc,char *argv[])
+{
+ struct passwd * pwd;
+ struct group * grp;
+ pwd=getpwuid(getuid());
+ grp=getgrgid(getgid());
+ fprintf(stdout,"uid=%d(%s),gid=%d(%s),",
+ getuid(),pwd?pwd->pw_name:"",
+ getgid(),grp?grp->gr_name:"");
+ pwd=getpwuid(geteuid());
+ grp=getgrgid(getegid());
+ fprintf(stdout,"euid=%d(%s),egid=%d(%s)\n",
+ geteuid(),pwd?pwd->pw_name:"",
+ getegid(),grp?grp->gr_name:"");
+ return 0;
+}
+/*-----------------------------------------------------------*/
+int main_umask(int argc,char *argv[])
+{
+ mode_t msk=umask(0);
+ if (argc == 2) msk=str2int(argv[1]);
+ umask(msk);
+ msk=umask(0);
+ fprintf(stdout,"0%o\n", (unsigned int) msk);
+ umask(msk);
+ return 0;
+}
+/*-----------------------------------------------------------*/
+int main_chmod(int argc,char *argv[])
+{
+ int n;
+ mode_t mode;
+ if (argc > 2){
+ mode=str2int(argv[1])&0777;
+ n=2;
+ while (n<argc) chmod(argv[n++],mode);
+ };
+ return 0;
+}
+/*-----------------------------------------------------------*
+ * with this you can call at all the rtems monitor commands.
+ * Not all work fine but you can show the rtems status and more.
+ *-----------------------------------------------------------*/
+int main_monitor(int argc,char * argv[]) {
+ rtems_monitor_command_entry_t *command;
+ rtems_task_ident(RTEMS_SELF,0,&rtems_monitor_task_id);
+ rtems_monitor_node = rtems_get_node(rtems_monitor_task_id);
+ rtems_monitor_default_node = rtems_monitor_node;
+ if ((command=rtems_monitor_command_lookup(rtems_monitor_commands,argc,argv)))
+ command->command_function(argc, argv, &command->command_arg, 0);
+ return 0;
+}
+/*-----------------------------------------------------------*/
+void register_cmds(void) {
+ rtems_monitor_command_entry_t *command;
+ /* monitor topic */
+ command=rtems_monitor_commands;
+ while (command) {
+ if (strcmp("exit",command->command)) /*Exclude EXIT (alias quit)*/
+ shell_add_cmd(command->command,"monitor",
+ command->usage ,main_monitor);
+ command=command->next;
+ };
+ /* dir[ectories] topic */
+ shell_add_cmd ("ls" ,"dir","ls [dir] # list files in the directory" ,main_ls );
+ shell_add_cmd ("chdir" ,"dir","chdir [dir] # change the current directory",main_chdir);
+ shell_add_cmd ("rmdir" ,"dir","rmdir dir # remove directory" ,main_rmdir);
+ shell_add_cmd ("mkdir" ,"dir","mkdir dir # make a directory" ,main_mkdir);
+ shell_add_cmd ("pwd" ,"dir","pwd # print work directory" ,main_pwd );
+ shell_add_cmd ("chroot","dir","chroot [dir] # change the root directory" ,main_chroot);
+ shell_add_cmd ("cat" ,"dir","cat n1 [n2 [n3...]]# show the ascii contents",main_cat );
+ shell_add_cmd ("rm" ,"dir","rm n1 [n2 [n3...]]# remove files" ,main_rm );
+ shell_add_cmd ("chmod" ,"dir","chmod 0777 n1 n2... #change filemode" ,main_chmod);
+
+ shell_alias_cmd("ls" ,"dir");
+ shell_alias_cmd("chdir" ,"cd");
+
+ /* misc. topic */
+ shell_add_cmd ("logoff","misc","logoff from the system" ,main_logoff);
+ shell_alias_cmd("logoff","exit");
+ shell_add_cmd ("date" ,"misc","date" ,main_date);
+ shell_add_cmd ("reset","misc","reset the BSP" ,main_reset);
+ shell_add_cmd ("alias","misc","alias old new" ,main_alias);
+ shell_add_cmd ("tty" ,"misc","show ttyname" ,main_tty );
+ shell_add_cmd ("whoami","misc","show current user" ,main_whoami);
+ shell_add_cmd ("id" ,"misc","show uid,gid,euid,egid" ,main_id );
+ shell_add_cmd ("umask" ,"misc","umask [new_umask]" ,main_umask );
+
+
+ /* memory topic */
+ shell_add_cmd ("mdump","mem" ,"mdump [adr [size]]" ,main_mdump);
+ shell_add_cmd ("wdump","mem" ,"wdump [adr [size]]" ,main_mwdump);
+ shell_add_cmd ("medit","mem" ,"medit adr value [value ...]" ,main_medit);
+ shell_add_cmd ("mfill","mem" ,"mfill adr size value" ,main_mfill);
+ shell_add_cmd ("mmove","mem" ,"mmove dst src size" ,main_mmove);
+#ifdef MALLOC_STATS /* /rtems/s/src/lib/libc/malloc.c */
+ shell_add_cmd ("malloc","mem","mem show memory malloc'ed" ,main_mem);
+#endif
+}
+/*-----------------------------------------------------------*/
diff --git a/cpukit/libmisc/shell/shell.c b/cpukit/libmisc/shell/shell.c
new file mode 100644
index 0000000000..01a9c36ec8
--- /dev/null
+++ b/cpukit/libmisc/shell/shell.c
@@ -0,0 +1,682 @@
+/*
+ *
+ * Instantatiate a new terminal shell.
+ *
+ * Author:
+ *
+ * WORK: fernando.ruiz@ctv.es
+ * HOME: correo@fernando-ruiz.com
+ *
+ * Thanks at:
+ * Chris John
+ *
+ * $Id$
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <time.h>
+
+#include <rtems.h>
+#include <rtems/error.h>
+#include <rtems/libio.h>
+#include <rtems/libio_.h>
+#include <rtems/system.h>
+#include <rtems/shell.h>
+
+#include <termios.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pwd.h>
+
+/* ----------------------------------------------- *
+ * This is a stupidity but is cute.
+ * ----------------------------------------------- */
+uint32_t new_rtems_name(char * rtems_name) {
+ static char b[5];
+ sprintf(b,"%-4.4s",rtems_name);
+ return rtems_build_name(b[0],b[1],b[2],b[3]);
+}
+/* **************************************************************
+ * common linked list of shell commands.
+ * Because the help report is very long
+ * I have a topic for each command.
+ * Help list the topics
+ * help [topic] list the commands for the topic
+ * help [command] help for the command
+ * Can you see help rtems monitor report?
+ * ************************************************************** */
+
+struct shell_topic_tt;
+typedef struct shell_topic_tt shell_topic_t;
+
+struct shell_topic_tt {
+ char * topic;
+ shell_topic_t * next;
+};
+
+
+static shell_cmd_t * shell_first_cmd;
+static shell_topic_t * shell_first_topic;
+/* ----------------------------------------------- *
+ * Using Chain I can reuse the rtems code.
+ * I am more comfortable with this, sorry.
+ * ----------------------------------------------- */
+shell_topic_t * shell_lookup_topic(char * topic) {
+ shell_topic_t * shell_topic;
+ shell_topic=shell_first_topic;
+ while (shell_topic) {
+ if (!strcmp(shell_topic->topic,topic)) return shell_topic;
+ shell_topic=shell_topic->next;
+ };
+ return (shell_topic_t *) NULL;
+}
+/* ----------------------------------------------- */
+shell_topic_t * shell_add_topic(char * topic) {
+ shell_topic_t * current,*aux;
+ if (!shell_first_topic) {
+ aux=malloc(sizeof(shell_topic_t));
+ aux->topic=topic;
+ aux->next=(shell_topic_t*)NULL;
+ return shell_first_topic=aux;
+ } else {
+ current=shell_first_topic;
+ if (!strcmp(topic,current->topic)) return current;
+ while (current->next) {
+ if (!strcmp(topic,current->next->topic)) return current->next;
+ current=current->next;
+ };
+ aux=malloc(sizeof(shell_topic_t));
+ aux->topic=topic;
+ aux->next=(shell_topic_t*)NULL;
+ current->next=aux;
+ return aux;
+ };
+}
+/* ----------------------------------------------- */
+shell_cmd_t * shell_lookup_cmd(char * cmd) {
+ shell_cmd_t * shell_cmd;
+ shell_cmd=shell_first_cmd;
+ while (shell_cmd) {
+ if (!strcmp(shell_cmd->name,cmd)) return shell_cmd;
+ shell_cmd=shell_cmd->next;
+ };
+ return (shell_cmd_t *) NULL;
+}
+/* ----------------------------------------------- */
+shell_cmd_t * shell_add_cmd(char * cmd,
+ char * topic,
+ char * usage,
+ shell_command_t command) {
+ int shell_help(int argc,char * argv[]);
+ shell_cmd_t * shell_cmd,*shell_pvt;
+ if (!shell_first_cmd) {
+ shell_first_cmd=(shell_cmd_t *) malloc(sizeof(shell_cmd_t));
+ shell_first_cmd->name ="help";
+ shell_first_cmd->topic ="help";
+ shell_first_cmd->usage ="help [topic] # list of usage of commands";
+ shell_first_cmd->command=shell_help;
+ shell_first_cmd->alias =(shell_cmd_t *) NULL;
+ shell_first_cmd->next =(shell_cmd_t *) NULL;
+ shell_add_topic(shell_first_cmd->topic);
+ register_cmds();
+ };
+ if (!cmd) return (shell_cmd_t *) NULL;
+ if (!command) return (shell_cmd_t *) NULL;
+ shell_cmd=(shell_cmd_t *) malloc(sizeof(shell_cmd_t));
+ shell_cmd->name =cmd;
+ shell_cmd->topic =topic;
+ shell_cmd->usage =usage;
+ shell_cmd->command=command;
+ shell_cmd->alias =(shell_cmd_t *) NULL;
+ shell_cmd->next =(shell_cmd_t *) NULL;
+ shell_add_topic(shell_cmd->topic);
+ shell_pvt=shell_first_cmd;
+ while (shell_pvt->next) shell_pvt=shell_pvt->next;
+ return shell_pvt->next=shell_cmd;
+}
+/* ----------------------------------------------- *
+ * you can make an alias for every command.
+ * ----------------------------------------------- */
+shell_cmd_t * shell_alias_cmd(char * cmd, char * alias) {
+ shell_cmd_t * shell_cmd,* shell_aux;
+ shell_aux=(shell_cmd_t *) NULL;
+ if (alias) {
+ if ((shell_aux=shell_lookup_cmd(alias))!=NULL) {
+ return NULL;
+ };
+ if ((shell_cmd=shell_lookup_cmd(cmd))!=NULL) {
+ shell_aux=shell_add_cmd(alias,shell_cmd->topic,
+ shell_cmd->usage,shell_cmd->command);
+ if (shell_aux) shell_aux->alias=shell_cmd;
+ };
+ };
+ return shell_aux;
+}
+/* ----------------------------------------------- *
+ * Poor but enough..
+ * TODO: Redirection capture. "" evaluate, ... C&S welcome.
+ * ----------------------------------------------- */
+int shell_make_args(char * cmd,
+ int * pargc,
+ char * argv[]) {
+ int argc=0;
+ while ((cmd=strtok(cmd," \t\r\n"))!=NULL) {
+ argv[argc++]=cmd;
+ cmd=(char*)NULL;
+ };
+ argv[argc]=(char*)NULL;
+ return *pargc=argc;
+}
+/* ----------------------------------------------- *
+ * show the help for one command.
+ * ----------------------------------------------- */
+int shell_help_cmd(shell_cmd_t * shell_cmd) {
+ char * pc;
+ int col,line;
+ fprintf(stdout,"%-10.10s -",shell_cmd->name);
+ col=12;
+ line=1;
+ if (shell_cmd->alias) {
+ fprintf(stdout,"is an <alias> for command '%s'",shell_cmd->alias->name);
+ } else
+ if (shell_cmd->usage) {
+ pc=shell_cmd->usage;
+ while (*pc) {
+ switch(*pc) {
+ case '\r':break;
+ case '\n':putchar('\n');
+ col=0;
+ break;
+ default :putchar(*pc);
+ col++;
+ break;
+ };
+ pc++;
+ if(col>78) { /* What daring... 78?*/
+ if (*pc) {
+ putchar('\n');
+ col=0;
+ };
+ };
+ if (!col && *pc) {
+ fprintf(stdout," ");
+ col=12;line++;
+ };
+ };
+ };
+ puts("");
+ return line;
+}
+/* ----------------------------------------------- *
+ * show the help. The first command implemented.
+ * Can you see the header of routine? Known?
+ * The same with all the commands....
+ * ----------------------------------------------- */
+int shell_help(int argc,char * argv[]) {
+ int col,line,arg;
+ shell_topic_t *topic;
+ shell_cmd_t * shell_cmd=shell_first_cmd;
+ if (argc<2) {
+ fprintf(stdout,"help: ('r' repeat last cmd - 'e' edit last cmd)\n"
+ " TOPIC? The topics are\n");
+ topic=shell_first_topic;
+ col=0;
+ while (topic) {
+ if (!col){
+ col=fprintf(stdout," %s",topic->topic);
+ } else {
+ if ((col+strlen(topic->topic)+2)>78){
+ fprintf(stdout,"\n");
+ col=fprintf(stdout," %s",topic->topic);
+ } else {
+ col+=fprintf(stdout,", %s",topic->topic);
+ };
+ };
+ topic=topic->next;
+ };
+ fprintf(stdout,"\n");
+ return 1;
+ };
+ line=0;
+ for (arg=1;arg<argc;arg++) {
+ if (line>16) {
+ fprintf(stdout,"Press any key to continue...");getchar();
+ fprintf(stdout,"\n");
+ line=0;
+ };
+ topic=shell_lookup_topic(argv[arg]);
+ if (!topic){
+ if ((shell_cmd=shell_lookup_cmd(argv[arg]))==NULL) {
+ fprintf(stdout,"help: topic or cmd '%s' not found. Try <help> alone for a list\n",argv[arg]);
+ line++;
+ } else {
+ line+=shell_help_cmd(shell_cmd);
+ }
+ continue;
+ };
+ fprintf(stdout,"help: list for the topic '%s'\n",argv[arg]);
+ line++;
+ while (shell_cmd) {
+ if (!strcmp(topic->topic,shell_cmd->topic))
+ line+=shell_help_cmd(shell_cmd);
+ if (line>16) {
+ fprintf(stdout,"Press any key to continue...");getchar();
+ fprintf(stdout,"\n");
+ line=0;
+ };
+ shell_cmd=shell_cmd->next;
+ };
+ };
+ puts("");
+ return 0;
+}
+/* ----------------------------------------------- *
+ * TODO: Add improvements. History, edit vi or emacs, ...
+ * ----------------------------------------------- */
+int shell_scanline(char * line,int size,FILE * in,FILE * out) {
+ int c,col;
+ col=0;
+ if (*line) {
+ col=strlen(line);
+ if (out) fprintf(out,"%s",line);
+ };
+ tcdrain(fileno(in ));
+ if (out) tcdrain(fileno(out));
+ for (;;) {
+ line[col]=0;
+ c=fgetc(in);
+ switch (c) {
+ case 0x04:/*Control-d*/
+ if (col) break;
+ case EOF :return 0;
+ case '\n':break;
+ case '\f':if (out) fputc('\f',out);
+ case 0x03:/*Control-C*/
+ line[0]=0;
+ case '\r':if (out) fputc('\n',out);
+ return 1;
+ case 127:
+ case '\b':if (col) {
+ if (out) {
+ fputc('\b',out);
+ fputc(' ',out);
+ fputc('\b',out);
+ };
+ col--;
+ } else {
+ if (out) fputc('\a',out);
+ };
+ break;
+ default :if (!iscntrl(c)) {
+ if (col<size-1) {
+ line[col++]=c;
+ if (out) fputc(c,out);
+ } else {
+ if (out) fputc('\a',out);
+ };
+ } else {
+ if (out)
+ if (c=='\a') fputc('\a',out);
+ };
+ break;
+ };
+ };
+}
+/* ----------------------------------------------- *
+ * - The shell TASK
+ * Poor but enough..
+ * TODO: Redirection. Tty Signals. ENVVARs. Shell language.
+ * ----------------------------------------------- */
+shell_env_t global_shell_env ,
+ * current_shell_env=&global_shell_env;
+
+extern char **environ;
+
+void cat_file(FILE * out,char * name) {
+ FILE * fd;
+ int c;
+ if (out) {
+ fd=fopen(name,"r");
+ if (fd) {
+ while ((c=fgetc(fd))!=EOF) fputc(c,out);
+ fclose(fd);
+ };
+ };
+}
+
+void write_file(char * name,char * content) {
+ FILE * fd;
+ fd=fopen(name,"w");
+ if (fd) {
+ fwrite(content,1,strlen(content),fd);
+ fclose(fd);
+ };
+}
+
+void init_issue(void) {
+ static char issue_inited=FALSE;
+ struct stat buf;
+ if (issue_inited) return;
+ issue_inited=TRUE;
+ getpwnam("root"); /* dummy call to init /etc dir */
+ if (stat("/etc/issue",&buf))
+ write_file("/etc/issue",
+ "Welcome to @V\\n"
+ "Login into @S(@L)\\n");
+ if (stat("/etc/issue.net",&buf))
+ write_file("/etc/issue.net",
+ "Welcome to %v\n"
+ "running on %m\n");
+}
+
+int shell_login(FILE * in,FILE * out) {
+ FILE * fd;
+ int c;
+ time_t t;
+ int times;
+ char name[128];
+ char pass[128];
+ struct passwd * passwd;
+ init_issue();
+ setuid(0);
+ setgid(0);
+ rtems_current_user_env->euid=
+ rtems_current_user_env->egid=0;
+ if (out) {
+ if((current_shell_env->devname[5]!='p')||
+ (current_shell_env->devname[6]!='t')||
+ (current_shell_env->devname[7]!='y')) {
+ fd=fopen("/etc/issue","r");
+ if (fd) {
+ while ((c=fgetc(fd))!=EOF) {
+ if (c=='@') {
+ switch(c=fgetc(fd)) {
+ case 'L':fprintf(out,"%s",current_shell_env->devname);
+ break;
+ case 'B':fprintf(out,"0");
+ break;
+ case 'T':
+ case 'D':time(&t);
+ fprintf(out,"%s",ctime(&t));
+ break;
+ case 'S':fprintf(out,"RTEMS");
+ break;
+ case 'V':fprintf(out,"%s\n%s",_RTEMS_version,_Copyright_Notice);
+ break;
+ case '@':fprintf(out,"@");
+ break;
+ default :fprintf(out,"@%c",c);
+ break;
+ };
+ } else
+ if (c=='\\') {
+ switch(c=fgetc(fd)) {
+ case '\\':fprintf(out,"\\");
+ break;
+ case 'b':fprintf(out,"\b"); break;
+ case 'f':fprintf(out,"\f"); break;
+ case 'n':fprintf(out,"\n"); break;
+ case 'r':fprintf(out,"\r"); break;
+ case 's':fprintf(out," "); break;
+ case 't':fprintf(out,"\t"); break;
+ case '@':fprintf(out,"@"); break;
+ };
+ } else {
+ fputc(c,out);
+ };
+ };
+ fclose(fd);
+ }
+ } else {
+ fd=fopen("/etc/issue.net","r");
+ if (fd) {
+ while ((c=fgetc(fd))!=EOF) {
+ if (c=='%') {
+ switch(c=fgetc(fd)) {
+ case 't':fprintf(out,"%s",current_shell_env->devname);
+ break;
+ case 'h':fprintf(out,"0");
+ break;
+ case 'D':fprintf(out," ");
+ break;
+ case 'd':time(&t);
+ fprintf(out,"%s",ctime(&t));
+ break;
+ case 's':fprintf(out,"RTEMS");
+ break;
+ case 'm':fprintf(out,"(" CPU_NAME "/" CPU_MODEL_NAME ")");
+ break;
+ case 'r':fprintf(out,_RTEMS_version);
+ break;
+ case 'v':fprintf(out,"%s\n%s",_RTEMS_version,_Copyright_Notice);
+ break;
+ case '%':fprintf(out,"%%");
+ break;
+ default :fprintf(out,"%%%c",c);
+ break;
+ };
+ } else {
+ fputc(c,out);
+ };
+ };
+ fclose(fd);
+ }
+ };
+ };
+ times=0;
+ strcpy(name,"");
+ strcpy(pass,"");
+ for (;;) {
+ times++;
+ if (times>3) break;
+ if (out) fprintf(out,"\nlogin: ");
+ if (!shell_scanline(name,sizeof(name),in,out )) break;
+ if (out) fprintf(out,"Password: ");
+ if (!shell_scanline(pass,sizeof(pass),in,NULL)) break;
+ if (out) fprintf(out,"\n");
+ if ((passwd=getpwnam(name))) {
+ if (strcmp(passwd->pw_passwd,"!")) { /* valid user */
+ setuid(passwd->pw_uid);
+ setgid(passwd->pw_gid);
+ rtems_current_user_env->euid=
+ rtems_current_user_env->egid=0;
+ chown(current_shell_env->devname,passwd->pw_uid,0);
+ rtems_current_user_env->euid=passwd->pw_uid;
+ rtems_current_user_env->egid=passwd->pw_gid;
+ if (!strcmp(passwd->pw_passwd,"*")) {
+ /* /etc/shadow */
+ return 0;
+ } else {
+ /* crypt() */
+ return 0;
+ };
+ };
+ };
+ if (out) fprintf(out,"Login incorrect\n");
+ strcpy(name,"");
+ strcpy(pass,"");
+ };
+ return -1;
+}
+
+rtems_task shell_shell(rtems_task_argument task_argument) {
+
+ shell_env_t * shell_env =(shell_env_t*) task_argument;
+ shell_cmd_t * shell_cmd;
+
+ rtems_status_code sc;
+
+ struct termios term;
+ char * devname;
+
+ char curdir[256];
+ char cmd[256];
+ char last_cmd[256]; /* to repeat 'r' */
+ int argc;
+ char * argv[128];
+
+ sc=rtems_task_variable_add(RTEMS_SELF,(void*)&current_shell_env,free);
+ if (sc!=RTEMS_SUCCESSFUL) {
+ rtems_error(sc,"rtems_task_variable_add(current_shell_env):");
+ rtems_task_delete(RTEMS_SELF);
+ };
+
+ current_shell_env=shell_env;
+
+ sc=rtems_libio_set_private_env();
+ if (sc!=RTEMS_SUCCESSFUL) {
+ rtems_error(sc,"rtems_libio_set_private_env():");
+ rtems_task_delete(RTEMS_SELF);
+ };
+
+
+ devname=shell_env->devname;
+ setuid(0);
+ setgid(0);
+ rtems_current_user_env->euid=
+ rtems_current_user_env->egid=0;
+
+ stdin =fopen(devname,"r+");
+
+ if (!stdin) {
+ fprintf(stderr,"shell:unable to open stdin.%s:%s\n",devname,strerror(errno));
+ rtems_task_delete(RTEMS_SELF);
+ };
+ setvbuf(stdin,NULL,_IONBF,0); /* Not buffered*/
+ /* make a raw terminal,Linux MANuals */
+ if (tcgetattr (fileno(stdin), &term)>=0) {
+ term.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
+ term.c_oflag &= ~OPOST;
+ term.c_oflag |= (OPOST|ONLCR); /* But with cr+nl on output */
+ term.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+ term.c_cflag = CLOCAL | CREAD |(shell_env->tcflag);
+ term.c_cc[VMIN] = 1;
+ term.c_cc[VTIME] = 0;
+ if (tcsetattr (fileno(stdin), TCSADRAIN, &term) < 0) {
+ fprintf(stderr,"shell:cannot set terminal attributes(%s)\n",devname);
+ };
+ stdout=fopen(devname,"r+");
+ if (!stdout) {
+ fprintf(stderr,"shell:unable to open stdout.%s:%s\n",devname,strerror(errno));
+ };
+ setvbuf(stdout,NULL,_IONBF,0); /* Not buffered*/
+ stderr=fopen(devname,"r+");
+ if (!stderr) {
+ fprintf(stdout,"shell:unable to open stderr.%s:%s\n",devname,strerror(errno));
+ };
+ /* when the future user environment runs ok
+ * a freopen() reopens the terminals. Now this don't work
+ * (sorry but you can't use because FILENO_STDIN!=0. Better fileno(stdin))
+ */
+ };
+ shell_add_cmd(NULL,NULL,NULL,NULL); /* init the chain list*/
+ do {
+ /* Set again root user and root filesystem, side effect of set_priv..*/
+ sc=rtems_libio_set_private_env();
+ if (sc!=RTEMS_SUCCESSFUL) {
+ rtems_error(sc,"rtems_libio_set_private_env():");
+ rtems_task_delete(RTEMS_SELF);
+ };
+ if (!shell_login(stdin,stdout)) {
+ cat_file(stdout,"/etc/motd");
+ strcpy(last_cmd,"");
+ strcpy(cmd,"");
+ fprintf(stdout,"\n"
+ "RTEMS SHELL (Ver.1.0-FRC):%s. "__DATE__". 'help' to list commands.\n",devname);
+ chdir("/"); /* XXX: chdir to getpwent homedir */
+ shell_env->exit_shell=FALSE;
+ for (;;) {
+ /* Prompt section */
+ /* XXX: show_prompt user adjustable */
+ getcwd(curdir,sizeof(curdir));
+ fprintf(stdout,"%s [%s] %c ",shell_env->taskname,curdir,geteuid()?'$':'#');
+ /* getcmd section */
+ if (!shell_scanline(cmd,sizeof(cmd),stdin,stdout)) break; /*EOF*/
+ /* evaluate cmd section */
+ if (!strcmp(cmd,"e")) { /* edit last command */
+ strcpy(cmd,last_cmd);
+ continue;
+ } else
+ if (!strcmp(cmd,"r")) { /* repeat last command */
+ strcpy(cmd,last_cmd);
+ } else
+ if (strcmp(cmd,"")) { /* only for get a new prompt */
+ strcpy(last_cmd,cmd);
+ };
+ /* exec cmd section */
+ /* TODO:
+ * To avoid user crash catch the signals.
+ * Open a new stdio files with posibility of redirection *
+ * Run in a new shell task background. (unix &)
+ * Resuming. A little bash.
+ */
+ if (shell_make_args(cmd,&argc,argv)) {
+ if ((shell_cmd=shell_lookup_cmd(argv[0]))!=NULL) {
+ shell_env->errorlevel=shell_cmd->command(argc,argv);
+ } else {
+ fprintf(stdout,"shell:%s command not found\n",argv[0]);
+ shell_env->errorlevel=-1;
+ };
+ };
+ /* end exec cmd section */
+ if (shell_env->exit_shell) break;
+ cmd[0]=0;
+ };
+ fprintf(stdout,"\nGoodbye from RTEMS SHELL :-(\n");
+ };
+ } while (shell_env->forever);
+ fclose(stdin );
+ fclose(stdout);
+ fclose(stderr);
+ rtems_task_delete(RTEMS_SELF);
+}
+/* ----------------------------------------------- */
+rtems_status_code shell_init (char * task_name,
+ uint32_t task_stacksize,
+ rtems_task_priority task_priority,
+ char * devname,
+ tcflag_t tcflag,
+ int forever) {
+ rtems_id task_id;
+ rtems_status_code sc;
+ shell_env_t * shell_env;
+ sc=rtems_task_create(new_rtems_name(task_name),
+ task_priority,
+ task_stacksize?task_stacksize:RTEMS_MINIMUM_STACK_SIZE,
+ RTEMS_DEFAULT_MODES,
+ RTEMS_LOCAL | RTEMS_FLOATING_POINT,
+ &task_id);
+ if (sc!=RTEMS_SUCCESSFUL) {
+ rtems_error(sc,"creating task %s in shell_init()",task_name);
+ return sc;
+ };
+ shell_env=malloc(sizeof(shell_env_t));
+ if (!shell_env) {
+ rtems_task_delete(task_id);
+ sc=RTEMS_NO_MEMORY;
+ rtems_error(sc,"allocating shell_env %s in shell_init()",task_name);
+ return sc;
+ };
+ if (global_shell_env.magic!=new_rtems_name("SENV")) {
+ global_shell_env.magic =new_rtems_name("SENV");
+ global_shell_env.devname ="/dev/console";
+ global_shell_env.taskname ="GLOBAL";
+ global_shell_env.tcflag =0;
+ global_shell_env.exit_shell=0;
+ global_shell_env.forever =TRUE;
+ };
+ shell_env->magic =global_shell_env.magic;
+ shell_env->devname =devname;
+ shell_env->taskname =task_name;
+ shell_env->tcflag =tcflag;
+ shell_env->exit_shell=FALSE;
+ shell_env->forever =forever;
+ return rtems_task_start(task_id,shell_shell,(rtems_task_argument) shell_env);
+}
diff --git a/cpukit/libmisc/shell/shell.h b/cpukit/libmisc/shell/shell.h
new file mode 100644
index 0000000000..c95bef5436
--- /dev/null
+++ b/cpukit/libmisc/shell/shell.h
@@ -0,0 +1,88 @@
+/*
+ *
+ * Instantatiate a new terminal shell.
+ *
+ * Author:
+ *
+ * WORK: fernando.ruiz@ctv.es
+ * HOME: correo@fernando-ruiz.com
+ *
+ * Thanks at:
+ * Chris John
+ *
+ * $Id$
+ */
+
+#ifndef __SHELL_H__
+#define __SHELL_H__
+
+#include <rtems.h>
+#include <stdio.h>
+#include <termios.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef int (*shell_command_t)(int argc,char * argv[]);
+
+struct shell_cmd_tt ;
+typedef struct shell_cmd_tt shell_cmd_t;
+
+struct shell_cmd_tt {
+ char * name;
+ char * usage;
+ char * topic;
+ shell_command_t command;
+ shell_cmd_t * alias;
+ shell_cmd_t * next;
+};
+
+uint32_t new_rtems_name(char * rtems_name);
+shell_cmd_t * shell_lookup_cmd(char * cmd);
+shell_cmd_t * shell_add_cmd(char * cmd,
+ char * topic,
+ char * usage,
+ shell_command_t command);
+shell_cmd_t * shell_alias_cmd(char * cmd, char * alias);
+
+int shell_make_args(char * cmd,
+ int * pargc,
+ char * argv[]);
+
+typedef struct {
+ rtems_name magic; /* 'S','E','N','V': Shell Environment */
+ char * devname;
+ char * taskname;
+ tcflag_t tcflag;
+ /* user extensions */
+ int exit_shell; /* logout */
+ int forever ; /* repeat login */
+ int errorlevel;
+ int mdump_adr;
+} shell_env_t;
+
+int shell_scanline(char * line,int size,FILE * in,FILE * out) ;
+void cat_file(FILE * out,char *name);
+void write_file(char *name,char * content);
+
+rtems_status_code shell_init(char * task_name ,
+ uint32_t task_stacksize,/*0 default*/
+ rtems_task_priority task_priority ,
+ char * devname ,
+ tcflag_t tcflag ,
+ int forever );
+
+extern shell_env_t global_shell_env,
+ * current_shell_env;
+/*--------*/
+/* cmds.c */
+/*--------*/
+int str2int(char * s);
+void register_cmds(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/libmisc/stackchk/README b/cpukit/libmisc/stackchk/README
new file mode 100644
index 0000000000..0f6e2f2b10
--- /dev/null
+++ b/cpukit/libmisc/stackchk/README
@@ -0,0 +1,56 @@
+#
+# $Id$
+#
+
+Introduction
+============
+
+This directory contains a stack bounds checker. It provides two
+primary features:
+
+ + check for stack overflow at each context switch
+ + provides an educated guess at each task's stack usage
+
+Enabling
+========
+
+Add the stack checker extension to the initial user extension set.
+If using confdefs.h to build your configuration table, this is
+as simple as adding -DSTACK_CHECK_ON to the gcc command line which
+compiles the file defining the configuration table. In the RTEMS
+test suites and samples, this is always init.c
+
+Background
+==========
+
+The stack overflow check at context switch works by looking for
+a 16 byte pattern at the logical end of the stack to be corrupted.
+The "guesser" assumes that the entire stack was prefilled with a known
+pattern and assumes that the pattern is still in place if the memory
+has not been used as a stack.
+
+Both of these can be fooled by pushing large holes onto the stack
+and not writing to them... or (much more unlikely) writing the
+magic patterns into memory.
+
+This code has not been extensively tested. It is provided as a tool
+for RTEMS users to catch the most common mistake in multitasking
+systems ... too little stack space. Suggestions and comments are appreciated.
+
+NOTES:
+
+1. Stack usage information is questionable on CPUs which push
+ large holes on stack.
+
+2. The stack checker has a tendency to generate a fault when
+ trying to print the helpful diagnostic message. If it comes
+ out, congratulations. If not, then the variable Stack_check_Blown_task
+ contains a pointer to the TCB of the offending task. This
+ is usually enough to go on.
+
+FUTURE:
+
+1. Determine how/if gcc will generate stack probe calls and support that.
+
+2. Get accurate stack usage numbers on i960.. it pushes very large
+ holes on the stack.
diff --git a/cpukit/libmisc/stackchk/check.c b/cpukit/libmisc/stackchk/check.c
new file mode 100644
index 0000000000..e5ae3c7970
--- /dev/null
+++ b/cpukit/libmisc/stackchk/check.c
@@ -0,0 +1,553 @@
+/*
+ * Stack Overflow Check User Extension Set
+ *
+ * NOTE: This extension set automatically determines at
+ * initialization time whether the stack for this
+ * CPU grows up or down and installs the correct
+ * extension routines for that direction.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+
+/*
+ * HACK
+ * the stack dump information should be printed by a "fatal" extension.
+ * Fatal extensions only get called via rtems_fatal_error_occurred()
+ * and not when rtems_shutdown_executive() is called.
+ * I hope/think this is changing so that fatal extensions are renamed
+ * to "shutdown" extensions.
+ * When that happens, this #define should be deleted and all the code
+ * it marks.
+ */
+#define DONT_USE_FATAL_EXTENSION
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <rtems/stackchk.h>
+#include "internal.h"
+
+/*
+ * This variable contains the name of the task which "blew" the stack.
+ * It is NULL if the system is all right.
+ */
+
+Thread_Control *Stack_check_Blown_task;
+
+/*
+ * The extension table for the stack checker.
+ */
+
+rtems_extensions_table Stack_check_Extension_table = {
+ Stack_check_Create_extension, /* rtems_task_create */
+ 0, /* rtems_task_start */
+ 0, /* rtems_task_restart */
+ 0, /* rtems_task_delete */
+ Stack_check_Switch_extension, /* task_switch */
+ Stack_check_Begin_extension, /* task_begin */
+ 0, /* task_exitted */
+#ifdef DONT_USE_FATAL_EXTENSION
+ 0, /* fatal */
+#else
+ Stack_check_Fatal_extension, /* fatal */
+#endif
+};
+
+/*
+ * The "magic pattern" used to mark the end of the stack.
+ */
+
+Stack_check_Control Stack_check_Pattern;
+
+/*
+ * Where the pattern goes in the stack area is dependent upon
+ * whether the stack grow to the high or low area of the memory.
+ *
+ */
+
+#if ( CPU_STACK_GROWS_UP == TRUE )
+
+#define Stack_check_Get_pattern_area( _the_stack ) \
+ ((Stack_check_Control *) ((char *)(_the_stack)->area + \
+ (_the_stack)->size - sizeof( Stack_check_Control ) ))
+
+#define Stack_check_Calculate_used( _low, _size, _high_water ) \
+ ((char *)(_high_water) - (char *)(_low))
+
+#define Stack_check_usable_stack_start(_the_stack) \
+ ((_the_stack)->area)
+
+#else
+
+#define Stack_check_Get_pattern_area( _the_stack ) \
+ ((Stack_check_Control *) ((char *)(_the_stack)->area + HEAP_OVERHEAD))
+
+#define Stack_check_Calculate_used( _low, _size, _high_water) \
+ ( ((char *)(_low) + (_size)) - (char *)(_high_water) )
+
+#define Stack_check_usable_stack_start(_the_stack) \
+ ((char *)(_the_stack)->area + sizeof(Stack_check_Control))
+
+#endif
+
+#define Stack_check_usable_stack_size(_the_stack) \
+ ((_the_stack)->size - sizeof(Stack_check_Control))
+
+
+/*
+ * Do we have an interrupt stack?
+ * XXX it would sure be nice if the interrupt stack were also
+ * stored in a "stack" structure!
+ */
+
+
+Stack_Control stack_check_interrupt_stack;
+
+/*
+ * Prototypes necessary for forward references
+ */
+
+void Stack_check_Dump_usage( void );
+
+/*
+ * Fill an entire stack area with BYTE_PATTERN.
+ * This will be used by a Fatal extension to check for
+ * amount of actual stack used
+ */
+
+void
+stack_check_dope_stack(Stack_Control *stack)
+{
+ memset(stack->area, BYTE_PATTERN, stack->size);
+}
+
+
+/*PAGE
+ *
+ * Stack_check_Initialize
+ */
+
+uint32_t stack_check_initialized = 0;
+
+void Stack_check_Initialize( void )
+{
+#if 0
+ rtems_status_code status;
+ Objects_Id id_ignored;
+#endif
+ uint32_t *p;
+#if 0
+ uint32_t i;
+ uint32_t api_index;
+ Thread_Control *the_thread;
+ Objects_Information *information;
+#endif
+
+ if (stack_check_initialized)
+ return;
+
+ /*
+ * Dope the pattern and fill areas
+ */
+
+ for ( p = Stack_check_Pattern.pattern;
+ p < &Stack_check_Pattern.pattern[PATTERN_SIZE_WORDS];
+ p += 4
+ )
+ {
+ p[0] = 0xFEEDF00D; /* FEED FOOD to BAD DOG */
+ p[1] = 0x0BAD0D06;
+ p[2] = 0xDEADF00D; /* DEAD FOOD GOOD DOG */
+ p[3] = 0x600D0D06;
+ };
+
+#if 0
+ status = rtems_extension_create(
+ rtems_build_name( 'S', 'T', 'C', 'K' ),
+ &Stack_check_Extension_table,
+ &id_ignored
+ );
+ assert ( status == RTEMS_SUCCESSFUL );
+#endif
+
+ Stack_check_Blown_task = 0;
+
+ /*
+ * If installed by a task, that task will not get setup properly
+ * since it missed out on the create hook. This will cause a
+ * failure on first switch out of that task.
+ * So pretend here that we actually ran create and begin extensions.
+ */
+
+ /* XXX
+ *
+ * Technically this has not been done for any task created before this
+ * happened. So just run through them and fix the situation.
+ */
+#if 0
+ if (_Thread_Executing)
+ {
+ Stack_check_Create_extension(_Thread_Executing, _Thread_Executing);
+ }
+#endif
+
+#if 0
+ for ( api_index = 1;
+ api_index <= OBJECTS_APIS_LAST ;
+ api_index++ ) {
+ if ( !_Objects_Information_table[ api_index ] )
+ continue;
+ information = _Objects_Information_table[ api_index ][ 1 ];
+ if ( information ) {
+ for ( i=1 ; i <= information->maximum ; i++ ) {
+ the_thread = (Thread_Control *)information->local_table[ i ];
+ Stack_check_Create_extension( the_thread, the_thread );
+ }
+ }
+ }
+#endif
+
+ /*
+ * If appropriate, setup the interrupt stack for high water testing
+ * also.
+ */
+#if (CPU_ALLOCATE_INTERRUPT_STACK == TRUE)
+ if (_CPU_Interrupt_stack_low && _CPU_Interrupt_stack_high)
+ {
+ stack_check_interrupt_stack.area = _CPU_Interrupt_stack_low;
+ stack_check_interrupt_stack.size = (char *) _CPU_Interrupt_stack_high -
+ (char *) _CPU_Interrupt_stack_low;
+
+ stack_check_dope_stack(&stack_check_interrupt_stack);
+ }
+#endif
+
+#ifdef DONT_USE_FATAL_EXTENSION
+#ifdef RTEMS_DEBUG
+ /*
+ * this would normally be called by a fatal extension
+ * handler, but we don't run fatal extensions unless
+ * we fatal error.
+ */
+ atexit(Stack_check_Dump_usage);
+#endif
+#endif
+
+ stack_check_initialized = 1;
+}
+
+/*PAGE
+ *
+ * Stack_check_Create_extension
+ */
+
+boolean Stack_check_Create_extension(
+ Thread_Control *running,
+ Thread_Control *the_thread
+)
+{
+ if (!stack_check_initialized)
+ Stack_check_Initialize();
+
+ if (the_thread /* XXX && (the_thread != _Thread_Executing) */ )
+ stack_check_dope_stack(&the_thread->Start.Initial_stack);
+
+ return TRUE;
+}
+
+/*PAGE
+ *
+ * Stack_check_Begin_extension
+ */
+
+void Stack_check_Begin_extension(
+ Thread_Control *the_thread
+)
+{
+ Stack_check_Control *the_pattern;
+
+ if (!stack_check_initialized)
+ Stack_check_Initialize();
+
+ if ( the_thread->Object.id == 0 ) /* skip system tasks */
+ return;
+
+ the_pattern = Stack_check_Get_pattern_area(&the_thread->Start.Initial_stack);
+
+ *the_pattern = Stack_check_Pattern;
+}
+
+/*PAGE
+ *
+ * Stack_check_report_blown_task
+ * Report a blown stack. Needs to be a separate routine
+ * so that interrupt handlers can use this too.
+ *
+ * Caller must have set the Stack_check_Blown_task.
+ *
+ * NOTE: The system is in a questionable state... we may not get
+ * the following message out.
+ */
+
+void Stack_check_report_blown_task(void)
+{
+ Stack_Control *stack;
+ Thread_Control *running;
+
+ running = Stack_check_Blown_task;
+ stack = &running->Start.Initial_stack;
+
+ fprintf(
+ stderr,
+ "BLOWN STACK!!! Offending task(%p): id=0x%08x; name=0x%08x",
+ running,
+ running->Object.id,
+ (uint32_t )running->Object.name
+ );
+ fflush(stderr);
+
+ if (rtems_configuration_get_user_multiprocessing_table())
+ fprintf(
+ stderr,
+ "; node=%d\n",
+ rtems_configuration_get_user_multiprocessing_table()->node
+ );
+ else
+ fprintf(stderr, "\n");
+ fflush(stderr);
+
+ fprintf(
+ stderr,
+ " stack covers range 0x%08x - 0x%08x (%d bytes)\n",
+ (uint32_t ) stack->area,
+ (uint32_t ) stack->area + stack->size - 1,
+ (uint32_t ) stack->size);
+ fflush(stderr);
+
+ fprintf(
+ stderr,
+ " Damaged pattern begins at 0x%08lx and is %ld bytes long\n",
+ (unsigned long) Stack_check_Get_pattern_area(stack),
+ (long) PATTERN_SIZE_BYTES);
+ fflush(stderr);
+
+ rtems_fatal_error_occurred( (uint32_t ) "STACK BLOWN" );
+}
+
+/*PAGE
+ *
+ * Stack_check_Switch_extension
+ */
+
+void Stack_check_Switch_extension(
+ Thread_Control *running,
+ Thread_Control *heir
+)
+{
+ if ( running->Object.id == 0 ) /* skip system tasks */
+ return;
+
+ if (0 != memcmp( (void *) Stack_check_Get_pattern_area( &running->Start.Initial_stack)->pattern,
+ (void *) Stack_check_Pattern.pattern,
+ PATTERN_SIZE_BYTES))
+ {
+ Stack_check_Blown_task = running;
+ Stack_check_report_blown_task();
+ }
+}
+
+void *Stack_check_find_high_water_mark(
+ const void *s,
+ size_t n
+)
+{
+ const uint32_t *base, *ebase;
+ uint32_t length;
+
+ base = s;
+ length = n/4;
+
+#if ( CPU_STACK_GROWS_UP == TRUE )
+ /*
+ * start at higher memory and find first word that does not
+ * match pattern
+ */
+
+ base += length - 1;
+ for (ebase = s; base > ebase; base--)
+ if (*base != U32_PATTERN)
+ return (void *) base;
+#else
+ /*
+ * start at lower memory and find first word that does not
+ * match pattern
+ */
+
+ base += PATTERN_SIZE_WORDS;
+ for (ebase = base + length; base < ebase; base++)
+ if (*base != U32_PATTERN)
+ return (void *) base;
+#endif
+
+ return (void *)0;
+}
+
+/*PAGE
+ *
+ * Stack_check_Dump_threads_usage
+ * Try to print out how much stack was actually used by the task.
+ *
+ */
+
+void Stack_check_Dump_threads_usage(
+ Thread_Control *the_thread
+)
+{
+ uint32_t size, used;
+ void *low;
+ void *high_water_mark;
+ Stack_Control *stack;
+ uint32_t u32_name;
+ char name_str[5];
+ char *name;
+ Objects_Information *info;
+
+ if ( !the_thread )
+ return;
+
+ /*
+ * XXX HACK to get to interrupt stack
+ */
+
+ if (the_thread == (Thread_Control *) -1)
+ {
+ if (stack_check_interrupt_stack.area)
+ {
+ stack = &stack_check_interrupt_stack;
+ the_thread = 0;
+ }
+ else
+ return;
+ }
+ else
+ stack = &the_thread->Start.Initial_stack;
+
+ low = Stack_check_usable_stack_start(stack);
+ size = Stack_check_usable_stack_size(stack);
+
+ high_water_mark = Stack_check_find_high_water_mark(low, size);
+
+ if ( high_water_mark )
+ used = Stack_check_Calculate_used( low, size, high_water_mark );
+ else
+ used = 0;
+
+ name = name_str;
+ if ( the_thread ) {
+ info = _Objects_Get_information(the_thread->Object.id);
+ if ( info->is_string ) {
+ name = (char *) the_thread->Object.name;
+ } else {
+ u32_name = (uint32_t )the_thread->Object.name;
+ name[ 0 ] = (u32_name >> 24) & 0xff;
+ name[ 1 ] = (u32_name >> 16) & 0xff;
+ name[ 2 ] = (u32_name >> 8) & 0xff;
+ name[ 3 ] = (u32_name >> 0) & 0xff;
+ name[ 4 ] = '\0';
+ }
+ } else {
+ u32_name = rtems_build_name('I', 'N', 'T', 'R');
+ name[ 0 ] = (u32_name >> 24) & 0xff;
+ name[ 1 ] = (u32_name >> 16) & 0xff;
+ name[ 2 ] = (u32_name >> 8) & 0xff;
+ name[ 3 ] = (u32_name >> 0) & 0xff;
+ name[ 4 ] = '\0';
+ }
+
+ fprintf(stdout, "0x%08x %4s 0x%08x 0x%08x %8d %8d\n",
+ the_thread ? the_thread->Object.id : ~0,
+ name,
+ (uint32_t ) stack->area,
+ (uint32_t ) stack->area + (uint32_t ) stack->size - 1,
+ size,
+ used
+ );
+}
+
+/*PAGE
+ *
+ * Stack_check_Fatal_extension
+ */
+
+void Stack_check_Fatal_extension(
+ Internal_errors_Source source,
+ boolean is_internal,
+ uint32_t status
+)
+{
+#ifndef DONT_USE_FATAL_EXTENSION
+ if (status == 0)
+ Stack_check_Dump_usage();
+#endif
+}
+
+
+/*PAGE
+ *
+ * Stack_check_Dump_usage
+ */
+
+void Stack_check_Dump_usage( void )
+{
+ uint32_t i;
+ uint32_t api_index;
+ Thread_Control *the_thread;
+ uint32_t hit_running = 0;
+ Objects_Information *information;
+
+ if (stack_check_initialized == 0)
+ return;
+
+ fprintf(stdout,"Stack usage by thread\n");
+ fprintf(stdout,
+ " ID NAME LOW HIGH AVAILABLE USED\n"
+ );
+
+ for ( api_index = 1 ;
+ api_index <= OBJECTS_APIS_LAST ;
+ api_index++ ) {
+ if ( !_Objects_Information_table[ api_index ] )
+ continue;
+ information = _Objects_Information_table[ api_index ][ 1 ];
+ if ( information ) {
+ for ( i=1 ; i <= information->maximum ; i++ ) {
+ the_thread = (Thread_Control *)information->local_table[ i ];
+ Stack_check_Dump_threads_usage( the_thread );
+ if ( the_thread == _Thread_Executing )
+ hit_running = 1;
+ }
+ }
+ }
+
+ if ( !hit_running )
+ Stack_check_Dump_threads_usage( _Thread_Executing );
+
+ /* dump interrupt stack info if any */
+ Stack_check_Dump_threads_usage((Thread_Control *) -1);
+}
diff --git a/cpukit/libmisc/stackchk/internal.h b/cpukit/libmisc/stackchk/internal.h
new file mode 100644
index 0000000000..c437eb94c1
--- /dev/null
+++ b/cpukit/libmisc/stackchk/internal.h
@@ -0,0 +1,95 @@
+/* internal.h
+ *
+ * This include file contains internal information
+ * for the RTEMS stack checker.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __INTERNAL_STACK_CHECK_h
+#define __INTERNAL_STACK_CHECK_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This structure is used to fill in and compare the "end of stack"
+ * marker pattern.
+ * pattern area must be a multiple of 4 words.
+ */
+
+#ifdef CPU_STACK_CHECK_SIZE
+#define PATTERN_SIZE_WORDS (((CPU_STACK_CHECK_SIZE / 4) + 3) & ~0x3)
+#else
+#define PATTERN_SIZE_WORDS (4)
+#endif
+
+#define PATTERN_SIZE_BYTES (PATTERN_SIZE_WORDS * sizeof(uint32_t ))
+
+typedef struct {
+ uint32_t pattern[ PATTERN_SIZE_WORDS ];
+} Stack_check_Control;
+
+/*
+ * The pattern used to fill the entire stack.
+ */
+
+#define BYTE_PATTERN 0xA5
+#define U32_PATTERN 0xA5A5A5A5
+
+/*
+ * Stack_check_Create_extension
+ */
+
+boolean Stack_check_Create_extension(
+ Thread_Control *running,
+ Thread_Control *the_thread
+);
+
+/*
+ * Stack_check_Begin_extension
+ */
+
+void Stack_check_Begin_extension(
+ Thread_Control *the_thread
+);
+
+/*
+ * Stack_check_Switch_extension
+ */
+
+void Stack_check_Switch_extension(
+ Thread_Control *running,
+ Thread_Control *heir
+);
+
+/*
+ * Stack_check_Fatal_extension
+ */
+
+void Stack_check_Fatal_extension(
+ Internal_errors_Source source,
+ boolean is_internal,
+ uint32_t status
+);
+
+/*
+ * Stack_check_Dump_usage
+ */
+
+void Stack_check_Dump_usage( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/libmisc/stackchk/stackchk.h b/cpukit/libmisc/stackchk/stackchk.h
new file mode 100644
index 0000000000..efe4ce9803
--- /dev/null
+++ b/cpukit/libmisc/stackchk/stackchk.h
@@ -0,0 +1,82 @@
+/* stackchk.h
+ *
+ * This include file contains information necessary to utilize
+ * and install the stack checker mechanism.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __STACK_CHECK_h
+#define __STACK_CHECK_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Stack_check_Initialize
+ */
+
+void Stack_check_Initialize( void );
+
+/*
+ * Stack_check_Dump_usage
+ */
+
+void Stack_check_Dump_usage( void );
+
+/*
+ * Stack_check_Create_extension
+ */
+
+boolean Stack_check_Create_extension(
+ Thread_Control *running,
+ Thread_Control *the_thread
+);
+
+/*
+ * Stack_check_Begin_extension
+ */
+
+void Stack_check_Begin_extension(
+ Thread_Control *the_thread
+);
+
+/*
+ * Stack_check_Switch_extension
+ */
+
+void Stack_check_Switch_extension(
+ Thread_Control *running,
+ Thread_Control *heir
+);
+
+/*
+ * Extension set definition
+ */
+
+#define STACK_CHECKER_EXTENSION \
+{ \
+ Stack_check_Create_extension, /* rtems_task_create */ \
+ 0, /* rtems_task_start */ \
+ 0, /* rtems_task_restart */ \
+ 0, /* rtems_task_delete */ \
+ Stack_check_Switch_extension, /* task_switch */ \
+ Stack_check_Begin_extension, /* task_begin */ \
+ 0, /* task_exitted */ \
+ 0 /* Stack_check_Fatal_extension */, /* fatal */ \
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/libmisc/untar/README b/cpukit/libmisc/untar/README
new file mode 100644
index 0000000000..24c9e7fa62
--- /dev/null
+++ b/cpukit/libmisc/untar/README
@@ -0,0 +1,26 @@
+#
+#
+# untar information
+#
+# Author: Jake Janovetz 7.6.1999
+#
+# $Id$
+#
+
+untar.c contains two procedures for extracting files from a UNIX
+tar file:
+
+ int Untar_FromMemory(unsigned char *tar_buf, unsigned long size);
+ int Untar_FromFile(char *tar_name);
+
+Untar_FromMemory(...) takes its input from a chunk of allocated memory.
+This is particularly useful when the tar is stored in Flash memory or
+comes from the FTP daemon by way of a hook.
+
+Untar_FromFile(...) is identical except the source is from an existing
+file. The fully qualified filename is passed through char *tar_name.
+
+
+
+BUGS: Please email janovetz@uiuc.edu
+-----
diff --git a/cpukit/libmisc/untar/untar.c b/cpukit/libmisc/untar/untar.c
new file mode 100644
index 0000000000..ad3b789f08
--- /dev/null
+++ b/cpukit/libmisc/untar/untar.c
@@ -0,0 +1,385 @@
+/* FIXME:
+ * 1. Symbolic links are not created.
+ * 2. Untar_FromMemory has printfs.
+ * 3. Untar_FromMemory uses FILE *fp.
+ * 4. How to determine end of archive?
+ *
+ * Written by: Jake Janovetz <janovetz@tempest.ece.uiuc.edu>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "untar.h"
+
+
+/**************************************************************************
+ * TAR file format:
+ *
+ * Offset Length Contents
+ * 0 100 bytes File name ('\0' terminated, 99 maxmum length)
+ * 100 8 bytes File mode (in octal ascii)
+ * 108 8 bytes User ID (in octal ascii)
+ * 116 8 bytes Group ID (in octal ascii)
+ * 124 12 bytes File size (s) (in octal ascii)
+ * 136 12 bytes Modify time (in octal ascii)
+ * 148 8 bytes Header checksum (in octal ascii)
+ * 156 1 bytes Link flag
+ * 157 100 bytes Linkname ('\0' terminated, 99 maxmum length)
+ * 257 8 bytes Magic ("ustar \0")
+ * 265 32 bytes User name ('\0' terminated, 31 maxmum length)
+ * 297 32 bytes Group name ('\0' terminated, 31 maxmum length)
+ * 329 8 bytes Major device ID (in octal ascii)
+ * 337 8 bytes Minor device ID (in octal ascii)
+ * 345 167 bytes Padding
+ * 512 (s+p)bytes File contents (s+p) := (((s) + 511) & ~511),
+ * round up to 512 bytes
+ *
+ * Checksum:
+ * int i, sum;
+ * char* header = tar_header_pointer;
+ * sum = 0;
+ * for(i = 0; i < 512; i++)
+ * sum += 0xFF & header[i];
+ *************************************************************************/
+
+#define LF_OLDNORMAL '\0' /* Normal disk file, Unix compatible */
+#define LF_NORMAL '0' /* Normal disk file */
+#define LF_LINK '1' /* Link to previously dumped file */
+#define LF_SYMLINK '2' /* Symbolic link */
+#define LF_CHR '3' /* Character special file */
+#define LF_BLK '4' /* Block special file */
+#define LF_DIR '5' /* Directory */
+#define LF_FIFO '6' /* FIFO special file */
+#define LF_CONFIG '7' /* Contiguous file */
+
+#define MAX_NAME_FIELD_SIZE 99
+
+#define MIN(a,b) ((a)>(b)?(b):(a))
+
+
+/**************************************************************************
+ * This converts octal ASCII number representations into an
+ * unsigned long. Only support 32-bit numbers for now.
+ *************************************************************************/
+static unsigned long
+octal2ulong(char *octascii, int len)
+{
+ int i;
+ unsigned long num;
+ unsigned long mult;
+
+ num = 0;
+ mult = 1;
+ for (i=len-1; i>=0; i--)
+ {
+ if ((octascii[i] < '0') || (octascii[i] > '9'))
+ {
+ continue;
+ }
+ num += mult*((unsigned long)(octascii[i] - '0'));
+ mult *= 8;
+ }
+ return(num);
+}
+
+
+/**************************************************************************
+ * Function: Untar_FromMemory *
+ **************************************************************************
+ * Description: *
+ * *
+ * This is a simple subroutine used to rip links, directories, and *
+ * files out of a block of memory. *
+ * *
+ * *
+ * Inputs: *
+ * *
+ * unsigned char *tar_buf - Pointer to TAR buffer. *
+ * unsigned long size - Length of TAR buffer. *
+ * *
+ * *
+ * Output: *
+ * *
+ * int - UNTAR_SUCCESSFUL (0) on successful completion. *
+ * UNTAR_INVALID_CHECKSUM for an invalid header checksum. *
+ * UNTAR_INVALID_HEADER for an invalid header. *
+ * *
+ **************************************************************************
+ * Change History: *
+ * 12/30/1998 - Creation (JWJ) *
+ *************************************************************************/
+int
+Untar_FromMemory(unsigned char *tar_buf, unsigned long size)
+{
+ FILE *fp;
+ char *bufr;
+ size_t n;
+ char fname[100];
+ char linkname[100];
+ int sum;
+ int hdr_chksum;
+ int retval;
+ unsigned long ptr;
+ unsigned long i;
+ unsigned long nblocks;
+ unsigned long file_size;
+ unsigned char linkflag;
+
+
+ ptr = 0;
+ while (1)
+ {
+ if (ptr + 512 > size)
+ {
+ retval = UNTAR_SUCCESSFUL;
+ break;
+ }
+
+ /* Read the header */
+ bufr = &tar_buf[ptr];
+ ptr += 512;
+ if (strncmp(&bufr[257], "ustar ", 7))
+ {
+ retval = UNTAR_SUCCESSFUL;
+ break;
+ }
+
+ strncpy(fname, bufr, MAX_NAME_FIELD_SIZE);
+ fname[MAX_NAME_FIELD_SIZE] = '\0';
+
+ linkflag = bufr[156];
+ file_size = octal2ulong(&bufr[124], 12);
+
+ /******************************************************************
+ * Compute the TAR checksum and check with the value in
+ * the archive. The checksum is computed over the entire
+ * header, but the checksum field is substituted with blanks.
+ ******************************************************************/
+ hdr_chksum = (int)octal2ulong(&bufr[148], 8);
+ sum = 0;
+ for (i=0; i<512; i++)
+ {
+ if ((i >= 148) && (i < 156))
+ {
+ sum += 0xff & ' ';
+ }
+ else
+ {
+ sum += 0xff & bufr[i];
+ }
+ }
+ if (sum != hdr_chksum)
+ {
+ retval = UNTAR_INVALID_CHECKSUM;
+ break;
+ }
+
+
+ /******************************************************************
+ * We've decoded the header, now figure out what it contains and
+ * do something with it.
+ *****************************************************************/
+ if (linkflag == LF_SYMLINK)
+ {
+ strncpy(linkname, &bufr[157], MAX_NAME_FIELD_SIZE);
+ linkname[MAX_NAME_FIELD_SIZE] = '\0';
+ /* symlink(fname, linkname); */
+ }
+ else if (linkflag == LF_NORMAL)
+ {
+ nblocks = (((file_size) + 511) & ~511) / 512;
+ if ((fp = fopen(fname, "w")) == NULL)
+ {
+ fprintf(stdout,"Untar failed to create file %s\n", fname);
+ ptr += 512 * nblocks;
+ }
+ else
+ {
+ unsigned long sizeToGo = file_size;
+ unsigned long len;
+
+ /***************************************************************
+ * Read out the data. There are nblocks of data where nblocks
+ * is the file_size rounded to the nearest 512-byte boundary.
+ **************************************************************/
+ for (i=0; i<nblocks; i++)
+ {
+ len = ((sizeToGo < 512L)?(sizeToGo):(512L));
+ n = fwrite(&tar_buf[ptr], 1, len, fp);
+ if (n != len)
+ {
+ fprintf(stdout,"Error during write\n");
+ break;
+ }
+ ptr += 512;
+ sizeToGo -= n;
+ }
+ fclose(fp);
+ }
+ }
+ else if (linkflag == LF_DIR)
+ {
+ mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO);
+ }
+ }
+
+ return(retval);
+}
+
+
+/**************************************************************************
+ * Function: Untar_FromFile *
+ **************************************************************************
+ * Description: *
+ * *
+ * This is a simple subroutine used to rip links, directories, and *
+ * files out of a TAR file. *
+ * *
+ * *
+ * Inputs: *
+ * *
+ * char *tar_name - TAR filename. *
+ * *
+ * *
+ * Output: *
+ * *
+ * int - UNTAR_SUCCESSFUL (0) on successful completion. *
+ * UNTAR_INVALID_CHECKSUM for an invalid header checksum. *
+ * UNTAR_INVALID_HEADER for an invalid header. *
+ * *
+ **************************************************************************
+ * Change History: *
+ * 12/30/1998 - Creation (JWJ) *
+ *************************************************************************/
+int
+Untar_FromFile(char *tar_name)
+{
+ int fd;
+ char *bufr;
+ size_t n;
+ char fname[100];
+ char linkname[100];
+ int sum;
+ int hdr_chksum;
+ int retval;
+ unsigned long i;
+ unsigned long nblocks;
+ unsigned long size;
+ unsigned char linkflag;
+
+
+ retval = UNTAR_SUCCESSFUL;
+ bufr = (char *)malloc(512);
+ if (bufr == NULL)
+ {
+ return(UNTAR_FAIL);
+ }
+
+ fd = open(tar_name, O_RDONLY);
+ while (1)
+ {
+ /* Read the header */
+ /* If the header read fails, we just consider it the end
+ of the tarfile. */
+ if ((n = read(fd, bufr, 512)) != 512)
+ {
+ break;
+ }
+
+ if (strncmp(&bufr[257], "ustar ", 7))
+ {
+ break;
+ }
+
+ strncpy(fname, bufr, MAX_NAME_FIELD_SIZE);
+ fname[MAX_NAME_FIELD_SIZE] = '\0';
+
+ linkflag = bufr[156];
+ size = octal2ulong(&bufr[124], 12);
+
+ /******************************************************************
+ * Compute the TAR checksum and check with the value in
+ * the archive. The checksum is computed over the entire
+ * header, but the checksum field is substituted with blanks.
+ ******************************************************************/
+ hdr_chksum = (int)octal2ulong(&bufr[148], 8);
+ sum = 0;
+ for (i=0; i<512; i++)
+ {
+ if ((i >= 148) && (i < 156))
+ {
+ sum += 0xff & ' ';
+ }
+ else
+ {
+ sum += 0xff & bufr[i];
+ }
+ }
+ if (sum != hdr_chksum)
+ {
+ retval = UNTAR_INVALID_CHECKSUM;
+ break;
+ }
+
+
+ /******************************************************************
+ * We've decoded the header, now figure out what it contains and
+ * do something with it.
+ *****************************************************************/
+ if (linkflag == LF_SYMLINK)
+ {
+ strncpy(linkname, &bufr[157], MAX_NAME_FIELD_SIZE);
+ linkname[MAX_NAME_FIELD_SIZE] = '\0';
+ }
+ else if (linkflag == LF_NORMAL)
+ {
+ int out_fd;
+
+ /******************************************************************
+ * Read out the data. There are nblocks of data where nblocks
+ * is the size rounded to the nearest 512-byte boundary.
+ *****************************************************************/
+ nblocks = (((size) + 511) & ~511) / 512;
+
+ if ((out_fd = creat(fname, 0644)) == -1)
+ {
+ for (i=0; i<nblocks; i++)
+ {
+ n = read(fd, bufr, 512);
+ }
+ }
+ else
+ {
+ for (i=0; i<nblocks; i++)
+ {
+ n = read(fd, bufr, 512);
+ n = MIN(n, size - i*512);
+ write(out_fd, bufr, n);
+ }
+ close(out_fd);
+ }
+ }
+ else if (linkflag == LF_DIR)
+ {
+ mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO);
+ }
+ }
+ free(bufr);
+ close(fd);
+
+ return(retval);
+}
diff --git a/cpukit/libmisc/untar/untar.h b/cpukit/libmisc/untar/untar.h
new file mode 100644
index 0000000000..69c4d41ddf
--- /dev/null
+++ b/cpukit/libmisc/untar/untar.h
@@ -0,0 +1,25 @@
+/*
+ * Written by: Jake Janovetz <janovetz@tempest.ece.uiuc.edu>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __UNTAR_H__
+#define __UNTAR_H__
+
+
+#define UNTAR_SUCCESSFUL 0
+#define UNTAR_FAIL 1
+#define UNTAR_INVALID_CHECKSUM 2
+#define UNTAR_INVALID_HEADER 3
+
+
+int Untar_FromMemory(unsigned char *tar_buf, unsigned long size);
+int Untar_FromFile(char *tar_name);
+
+
+#endif /* __UNTAR_H__ */
diff --git a/cpukit/libnetworking/.cvsignore b/cpukit/libnetworking/.cvsignore
new file mode 100644
index 0000000000..282522db03
--- /dev/null
+++ b/cpukit/libnetworking/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/cpukit/libnetworking/Makefile.am b/cpukit/libnetworking/Makefile.am
new file mode 100644
index 0000000000..26ff067c5e
--- /dev/null
+++ b/cpukit/libnetworking/Makefile.am
@@ -0,0 +1,654 @@
+##
+## $Id$
+##
+
+include $(top_srcdir)/automake/multilib.am
+include $(top_srcdir)/automake/compile.am
+
+AM_CPPFLAGS += -I$(srcdir)
+
+EXTRA_DIST = README
+CLEANFILES =
+
+# poll is not supported
+UNUSED_FILES = poll.h
+# Original FreeBSD file
+UNUSED_FILES += sys/poll.h
+
+UNUSED_FILES += net/zlib.c net/zlib.h
+UNUSED_FILES += net/ppp.h net/ppp-deflate.c net/bsd-comp.c
+
+if HAS_NETWORKING
+# Add -DFORWARD_PROTOCOL to enable UDP forwarding -- requires missing net/pf.h
+libnetworking_CPPFLAGS = -D_COMPILING_BSD_KERNEL_ -DKERNEL -DINET -DNFS \
+ -DDIAGNOSTIC -DBOOTP_COMPAT -D_KERNEL
+
+EXTRA_LIBRARIES = libnetworking.a
+CLEANFILES += libnetworking.a
+libnetworking_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V) \
+ $(libnetworking_CPPFLAGS)
+
+EXTRA_LIBRARIES += libnetworking_g.a
+CLEANFILES += libnetworking_g.a
+libnetworking_g_a_SOURCES = $(libnetworking_a_SOURCES)
+libnetworking_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V) \
+ $(libnetworking_CPPFLAGS)
+
+TMP_LIBS = libnetworking$(LIB_VARIANT).a
+
+## poll.h is not in the list because RTEMS does not have poll()
+## and installing poll.h confuses autoconf.
+include_HEADERS = bpfilter.h loop.h netdb.h
+include_HEADERS += resolv.h syslog.h memory.h
+
+libnetworking_a_SOURCES = opt_ipfw.h opt_mrouting.h opt_tcpdebug.h
+
+# arpa
+
+include_arpadir = $(includedir)/arpa
+
+include_arpa_HEADERS = arpa/ftp.h arpa/inet.h arpa/nameser.h \
+ arpa/nameser_compat.h arpa/telnet.h
+
+## kern
+
+libnetworking_a_SOURCES += kern/kern_mib.c kern/kern_subr.c \
+ kern/kern_sysctl.c kern/uipc_domain.c kern/uipc_mbuf.c \
+ kern/uipc_socket.c kern/uipc_socket2.c
+
+## machine
+
+include_machinedir = $(includedir)/machine
+
+include_machine_HEADERS = machine/conf.h machine/cpu.h machine/cpufunc.h \
+ machine/endian.h machine/in_cksum.h machine/vmparam.h
+
+libnetworking_a_SOURCES += machine/limits.h
+
+## net
+
+include_netdir = $(includedir)/net
+
+include_net_HEADERS = net/bpf.h net/ethernet.h net/if.h net/if_arp.h \
+ net/if_dl.h net/if_llc.h net/if_ppp.h net/if_types.h net/netisr.h \
+ net/ppp-comp.h net/ppp_defs.h net/radix.h net/raw_cb.h net/route.h \
+ net/if_pppvar.h net/pppcompress.h
+
+libnetworking_a_SOURCES += net/if.c net/if_ethersubr.c net/if_loop.c \
+ net/radix.c net/route.c net/rtsock.c net/raw_cb.c net/raw_usrreq.c \
+ net/if_ppp.c net/ppp_tty.c net/pppcompress.c
+
+## netinet
+
+include_netinetdir = $(includedir)/netinet
+
+include_netinet_HEADERS = netinet/icmp_var.h netinet/if_ether.h \
+ netinet/igmp.h netinet/igmp_var.h netinet/in.h netinet/in_pcb.h \
+ netinet/in_systm.h netinet/in_var.h netinet/ip.h netinet/ip_fw.h \
+ netinet/ip_icmp.h netinet/ip_mroute.h netinet/ip_var.h netinet/tcp.h \
+ netinet/tcp_debug.h netinet/tcp_fsm.h netinet/tcp_seq.h \
+ netinet/tcp_timer.h netinet/tcp_var.h netinet/tcpip.h netinet/udp.h \
+ netinet/udp_var.h
+
+libnetworking_a_SOURCES += netinet/if_ether.c netinet/igmp.c netinet/in.c \
+ netinet/in_cksum.c netinet/in_pcb.c netinet/in_proto.c netinet/in_rmx.c \
+ netinet/ip_divert.c netinet/ip_fw.c netinet/ip_icmp.c netinet/ip_input.c \
+ netinet/ip_mroute.c netinet/ip_output.c netinet/raw_ip.c \
+ netinet/tcp_debug.c netinet/tcp_input.c netinet/tcp_output.c \
+ netinet/tcp_subr.c netinet/tcp_timer.c netinet/tcp_usrreq.c \
+ netinet/udp_usrreq.c netinet/in_cksum_arm.h netinet/in_cksum_i386.h \
+ netinet/in_cksum_m68k.h netinet/in_cksum_powerpc.h
+
+## nfs
+
+include_nfsdir = $(includedir)/nfs
+
+include_nfs_HEADERS = nfs/krpc.h nfs/nfs.h nfs/nfsdiskless.h nfs/nfsproto.h \
+ nfs/rpcv2.h nfs/xdr_subs.h
+
+libnetworking_a_SOURCES += nfs/bootp_subr.c
+
+## rtems
+
+include_rtemsdir = $(includedir)/rtems
+
+include_rtems_HEADERS = rtems/rtems_bsdnet.h rtems/rtems_bsdnet_internal.h \
+ rtems/tftp.h rtems/ftpfs.h rtems/mkrootfs.h
+
+libnetworking_a_SOURCES += rtems/sghostname.c rtems/issetugid.c \
+ rtems/rtems_glue.c rtems/rtems_syscall.c rtems/rtems_bootp.c \
+ rtems/rtems_showmbuf.c rtems/rtems_showroute.c rtems/rtems_showifstat.c \
+ rtems/rtems_showipstat.c rtems/rtems_showicmpstat.c \
+ rtems/rtems_showtcpstat.c rtems/rtems_showudpstat.c rtems/rtems_select.c \
+ rtems/mkrootfs.c rtems/rtems_bsdnet_malloc_starvation.c
+
+## sys
+
+include_sysdir = $(includedir)/sys
+
+include_sys_HEADERS = sys/buf.h sys/callout.h sys/conf.h sys/domain.h \
+ sys/kernel.h sys/libkern.h sys/linker_set.h sys/malloc.h sys/mbuf.h \
+ sys/mount.h sys/proc.h sys/protosw.h sys/queue.h sys/reboot.h \
+ sys/resourcevar.h sys/rtprio.h sys/select.h sys/signalvar.h sys/socket.h \
+ sys/socketvar.h sys/sysctl.h sys/syslog.h sys/systm.h sys/ttydefaults.h \
+ sys/ucred.h sys/uio.h sys/un.h
+
+# vm
+
+include_vmdir = $(includedir)/vm
+
+include_vm_HEADERS = vm/vm.h vm/vm_extern.h vm/vm_kern.h vm/vm_param.h
+
+## libc
+
+libc_CPPFLAGS = -DNOPOLL -DNOSELECT
+
+EXTRA_LIBRARIES += libc.a
+CLEANFILES += libc.a
+libc_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V) $(libc_CPPFLAGS)
+
+EXTRA_LIBRARIES += libc_g.a
+CLEANFILES += libc_g.a
+libc_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V) $(libc_CPPFLAGS)
+
+libc_a_SOURCES = libc/addr2ascii.c libc/ascii2addr.c libc/base64.c \
+ libc/gethostbydns.c libc/gethostbyht.c libc/gethostbynis.c \
+ libc/gethostnamadr.c libc/getnetbydns.c libc/getnetbyht.c \
+ libc/getnetbynis.c libc/getnetnamadr.c libc/getproto.c \
+ libc/getprotoent.c libc/getprotoname.c libc/getservbyname.c \
+ libc/getservbyport.c libc/getservent.c libc/herror.c libc/inet_addr.c \
+ libc/inet_lnaof.c libc/inet_makeaddr.c libc/inet_netof.c \
+ libc/inet_network.c libc/inet_ntoa.c libc/inet_ntop.c libc/inet_pton.c \
+ libc/linkaddr.c libc/map_v4v6.c libc/nsap_addr.c libc/ns_name.c \
+ libc/ns_netint.c libc/ns_parse.c libc/ns_print.c libc/ns_ttl.c \
+ libc/res_comp.c libc/res_data.c libc/res_debug.c libc/res_init.c \
+ libc/res_mkquery.c libc/res_mkupdate.c libc/res_query.c libc/res_send.c \
+ libc/res_stubs.c libc/res_update.c libc/strsep.c libc/rcmd.c
+libc_g_a_SOURCES = $(libc_a_SOURCES)
+endif
+
+UNUSED_FILES += libc/ether_addr.c libc/gethostname.c libc/inet_neta.c \
+ libc/inet_net_ntop.c libc/inet_net_pton.c libc/iso_addr.c libc/ns_addr.c \
+ libc/ns_ntoa.c libc/recv.c libc/res_config.h libc/send.c
+
+libc_mans = libc/addr2ascii.3 libc/byteorder.3 libc/ethers.3 \
+ libc/gethostbyname.3 libc/getnetent.3 libc/getprotoent.3 \
+ libc/getservent.3 libc/inet.3 libc/iso_addr.3 libc/linkaddr.3 libc/ns.3 \
+ libc/rcmd.3 libc/resolver.3
+EXTRA_DIST += $(libc_mans)
+
+if HAS_NETWORKING
+man_MANS = $(libc_MANS)
+TMP_LIBS += libc$(LIB_VARIANT).a
+
+## lib
+
+EXTRA_DIST += lib/README
+
+lib_CPPFLAGS = -DNOPOLL -DNOSELECT
+
+EXTRA_LIBRARIES += lib.a
+CLEANFILES += lib.a
+lib_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V) $(lib_CPPFLAGS)
+
+EXTRA_LIBRARIES += lib_g.a
+CLEANFILES += lib_g.a
+lib_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V) $(lib_CPPFLAGS)
+
+lib_a_SOURCES = lib/getprotoby.c lib/rtems_bsdnet_ntp.c lib/ftpfs.c \
+ lib/syslog.c lib/tftpDriver.c
+lib_g_a_SOURCES = $(lib_a_SOURCES)
+
+TMP_LIBS += lib$(LIB_VARIANT).a
+
+# ---
+all-local: $(PREINSTALL_FILES) $(TMP_LIBS)
+endif
+
+EXTRA_DIST += $(UNUSED_FILES)
+
+DISTCLEANFILES =
+
+PREINSTALL_DIRS =
+PREINSTALL_FILES =
+
+$(PROJECT_INCLUDE)/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)
+ @: > $(PROJECT_INCLUDE)/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/$(dirstamp)
+
+if HAS_NETWORKING
+$(PROJECT_INCLUDE)/bpfilter.h: bpfilter.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bpfilter.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bpfilter.h
+
+$(PROJECT_INCLUDE)/loop.h: loop.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/loop.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/loop.h
+
+$(PROJECT_INCLUDE)/netdb.h: netdb.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/netdb.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/netdb.h
+
+$(PROJECT_INCLUDE)/resolv.h: resolv.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/resolv.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/resolv.h
+
+$(PROJECT_INCLUDE)/syslog.h: syslog.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/syslog.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/syslog.h
+
+$(PROJECT_INCLUDE)/memory.h: memory.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/memory.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/memory.h
+
+$(PROJECT_INCLUDE)/arpa/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/arpa
+ @: > $(PROJECT_INCLUDE)/arpa/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/arpa/$(dirstamp)
+
+$(PROJECT_INCLUDE)/arpa/ftp.h: arpa/ftp.h $(PROJECT_INCLUDE)/arpa/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/arpa/ftp.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/arpa/ftp.h
+
+$(PROJECT_INCLUDE)/arpa/inet.h: arpa/inet.h $(PROJECT_INCLUDE)/arpa/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/arpa/inet.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/arpa/inet.h
+
+$(PROJECT_INCLUDE)/arpa/nameser.h: arpa/nameser.h $(PROJECT_INCLUDE)/arpa/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/arpa/nameser.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/arpa/nameser.h
+
+$(PROJECT_INCLUDE)/arpa/nameser_compat.h: arpa/nameser_compat.h $(PROJECT_INCLUDE)/arpa/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/arpa/nameser_compat.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/arpa/nameser_compat.h
+
+$(PROJECT_INCLUDE)/arpa/telnet.h: arpa/telnet.h $(PROJECT_INCLUDE)/arpa/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/arpa/telnet.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/arpa/telnet.h
+
+$(PROJECT_INCLUDE)/machine/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/machine
+ @: > $(PROJECT_INCLUDE)/machine/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/machine/$(dirstamp)
+
+$(PROJECT_INCLUDE)/machine/conf.h: machine/conf.h $(PROJECT_INCLUDE)/machine/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/machine/conf.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/machine/conf.h
+
+$(PROJECT_INCLUDE)/machine/cpu.h: machine/cpu.h $(PROJECT_INCLUDE)/machine/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/machine/cpu.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/machine/cpu.h
+
+$(PROJECT_INCLUDE)/machine/cpufunc.h: machine/cpufunc.h $(PROJECT_INCLUDE)/machine/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/machine/cpufunc.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/machine/cpufunc.h
+
+$(PROJECT_INCLUDE)/machine/endian.h: machine/endian.h $(PROJECT_INCLUDE)/machine/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/machine/endian.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/machine/endian.h
+
+$(PROJECT_INCLUDE)/machine/in_cksum.h: machine/in_cksum.h $(PROJECT_INCLUDE)/machine/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/machine/in_cksum.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/machine/in_cksum.h
+
+$(PROJECT_INCLUDE)/machine/vmparam.h: machine/vmparam.h $(PROJECT_INCLUDE)/machine/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/machine/vmparam.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/machine/vmparam.h
+
+$(PROJECT_INCLUDE)/net/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/net
+ @: > $(PROJECT_INCLUDE)/net/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/net/$(dirstamp)
+
+$(PROJECT_INCLUDE)/net/bpf.h: net/bpf.h $(PROJECT_INCLUDE)/net/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/net/bpf.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/net/bpf.h
+
+$(PROJECT_INCLUDE)/net/ethernet.h: net/ethernet.h $(PROJECT_INCLUDE)/net/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/net/ethernet.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/net/ethernet.h
+
+$(PROJECT_INCLUDE)/net/if.h: net/if.h $(PROJECT_INCLUDE)/net/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/net/if.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/net/if.h
+
+$(PROJECT_INCLUDE)/net/if_arp.h: net/if_arp.h $(PROJECT_INCLUDE)/net/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/net/if_arp.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/net/if_arp.h
+
+$(PROJECT_INCLUDE)/net/if_dl.h: net/if_dl.h $(PROJECT_INCLUDE)/net/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/net/if_dl.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/net/if_dl.h
+
+$(PROJECT_INCLUDE)/net/if_llc.h: net/if_llc.h $(PROJECT_INCLUDE)/net/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/net/if_llc.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/net/if_llc.h
+
+$(PROJECT_INCLUDE)/net/if_ppp.h: net/if_ppp.h $(PROJECT_INCLUDE)/net/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/net/if_ppp.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/net/if_ppp.h
+
+$(PROJECT_INCLUDE)/net/if_types.h: net/if_types.h $(PROJECT_INCLUDE)/net/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/net/if_types.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/net/if_types.h
+
+$(PROJECT_INCLUDE)/net/netisr.h: net/netisr.h $(PROJECT_INCLUDE)/net/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/net/netisr.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/net/netisr.h
+
+$(PROJECT_INCLUDE)/net/ppp-comp.h: net/ppp-comp.h $(PROJECT_INCLUDE)/net/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/net/ppp-comp.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/net/ppp-comp.h
+
+$(PROJECT_INCLUDE)/net/ppp_defs.h: net/ppp_defs.h $(PROJECT_INCLUDE)/net/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/net/ppp_defs.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/net/ppp_defs.h
+
+$(PROJECT_INCLUDE)/net/radix.h: net/radix.h $(PROJECT_INCLUDE)/net/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/net/radix.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/net/radix.h
+
+$(PROJECT_INCLUDE)/net/raw_cb.h: net/raw_cb.h $(PROJECT_INCLUDE)/net/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/net/raw_cb.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/net/raw_cb.h
+
+$(PROJECT_INCLUDE)/net/route.h: net/route.h $(PROJECT_INCLUDE)/net/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/net/route.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/net/route.h
+
+$(PROJECT_INCLUDE)/net/if_pppvar.h: net/if_pppvar.h $(PROJECT_INCLUDE)/net/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/net/if_pppvar.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/net/if_pppvar.h
+
+$(PROJECT_INCLUDE)/net/pppcompress.h: net/pppcompress.h $(PROJECT_INCLUDE)/net/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/net/pppcompress.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/net/pppcompress.h
+
+$(PROJECT_INCLUDE)/netinet/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/netinet
+ @: > $(PROJECT_INCLUDE)/netinet/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/netinet/$(dirstamp)
+
+$(PROJECT_INCLUDE)/netinet/icmp_var.h: netinet/icmp_var.h $(PROJECT_INCLUDE)/netinet/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/netinet/icmp_var.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/netinet/icmp_var.h
+
+$(PROJECT_INCLUDE)/netinet/if_ether.h: netinet/if_ether.h $(PROJECT_INCLUDE)/netinet/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/netinet/if_ether.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/netinet/if_ether.h
+
+$(PROJECT_INCLUDE)/netinet/igmp.h: netinet/igmp.h $(PROJECT_INCLUDE)/netinet/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/netinet/igmp.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/netinet/igmp.h
+
+$(PROJECT_INCLUDE)/netinet/igmp_var.h: netinet/igmp_var.h $(PROJECT_INCLUDE)/netinet/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/netinet/igmp_var.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/netinet/igmp_var.h
+
+$(PROJECT_INCLUDE)/netinet/in.h: netinet/in.h $(PROJECT_INCLUDE)/netinet/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/netinet/in.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/netinet/in.h
+
+$(PROJECT_INCLUDE)/netinet/in_pcb.h: netinet/in_pcb.h $(PROJECT_INCLUDE)/netinet/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/netinet/in_pcb.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/netinet/in_pcb.h
+
+$(PROJECT_INCLUDE)/netinet/in_systm.h: netinet/in_systm.h $(PROJECT_INCLUDE)/netinet/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/netinet/in_systm.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/netinet/in_systm.h
+
+$(PROJECT_INCLUDE)/netinet/in_var.h: netinet/in_var.h $(PROJECT_INCLUDE)/netinet/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/netinet/in_var.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/netinet/in_var.h
+
+$(PROJECT_INCLUDE)/netinet/ip.h: netinet/ip.h $(PROJECT_INCLUDE)/netinet/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/netinet/ip.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/netinet/ip.h
+
+$(PROJECT_INCLUDE)/netinet/ip_fw.h: netinet/ip_fw.h $(PROJECT_INCLUDE)/netinet/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/netinet/ip_fw.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/netinet/ip_fw.h
+
+$(PROJECT_INCLUDE)/netinet/ip_icmp.h: netinet/ip_icmp.h $(PROJECT_INCLUDE)/netinet/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/netinet/ip_icmp.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/netinet/ip_icmp.h
+
+$(PROJECT_INCLUDE)/netinet/ip_mroute.h: netinet/ip_mroute.h $(PROJECT_INCLUDE)/netinet/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/netinet/ip_mroute.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/netinet/ip_mroute.h
+
+$(PROJECT_INCLUDE)/netinet/ip_var.h: netinet/ip_var.h $(PROJECT_INCLUDE)/netinet/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/netinet/ip_var.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/netinet/ip_var.h
+
+$(PROJECT_INCLUDE)/netinet/tcp.h: netinet/tcp.h $(PROJECT_INCLUDE)/netinet/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/netinet/tcp.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/netinet/tcp.h
+
+$(PROJECT_INCLUDE)/netinet/tcp_debug.h: netinet/tcp_debug.h $(PROJECT_INCLUDE)/netinet/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/netinet/tcp_debug.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/netinet/tcp_debug.h
+
+$(PROJECT_INCLUDE)/netinet/tcp_fsm.h: netinet/tcp_fsm.h $(PROJECT_INCLUDE)/netinet/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/netinet/tcp_fsm.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/netinet/tcp_fsm.h
+
+$(PROJECT_INCLUDE)/netinet/tcp_seq.h: netinet/tcp_seq.h $(PROJECT_INCLUDE)/netinet/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/netinet/tcp_seq.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/netinet/tcp_seq.h
+
+$(PROJECT_INCLUDE)/netinet/tcp_timer.h: netinet/tcp_timer.h $(PROJECT_INCLUDE)/netinet/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/netinet/tcp_timer.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/netinet/tcp_timer.h
+
+$(PROJECT_INCLUDE)/netinet/tcp_var.h: netinet/tcp_var.h $(PROJECT_INCLUDE)/netinet/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/netinet/tcp_var.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/netinet/tcp_var.h
+
+$(PROJECT_INCLUDE)/netinet/tcpip.h: netinet/tcpip.h $(PROJECT_INCLUDE)/netinet/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/netinet/tcpip.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/netinet/tcpip.h
+
+$(PROJECT_INCLUDE)/netinet/udp.h: netinet/udp.h $(PROJECT_INCLUDE)/netinet/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/netinet/udp.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/netinet/udp.h
+
+$(PROJECT_INCLUDE)/netinet/udp_var.h: netinet/udp_var.h $(PROJECT_INCLUDE)/netinet/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/netinet/udp_var.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/netinet/udp_var.h
+
+$(PROJECT_INCLUDE)/nfs/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/nfs
+ @: > $(PROJECT_INCLUDE)/nfs/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/nfs/$(dirstamp)
+
+$(PROJECT_INCLUDE)/nfs/krpc.h: nfs/krpc.h $(PROJECT_INCLUDE)/nfs/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/nfs/krpc.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/nfs/krpc.h
+
+$(PROJECT_INCLUDE)/nfs/nfs.h: nfs/nfs.h $(PROJECT_INCLUDE)/nfs/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/nfs/nfs.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/nfs/nfs.h
+
+$(PROJECT_INCLUDE)/nfs/nfsdiskless.h: nfs/nfsdiskless.h $(PROJECT_INCLUDE)/nfs/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/nfs/nfsdiskless.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/nfs/nfsdiskless.h
+
+$(PROJECT_INCLUDE)/nfs/nfsproto.h: nfs/nfsproto.h $(PROJECT_INCLUDE)/nfs/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/nfs/nfsproto.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/nfs/nfsproto.h
+
+$(PROJECT_INCLUDE)/nfs/rpcv2.h: nfs/rpcv2.h $(PROJECT_INCLUDE)/nfs/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/nfs/rpcv2.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/nfs/rpcv2.h
+
+$(PROJECT_INCLUDE)/nfs/xdr_subs.h: nfs/xdr_subs.h $(PROJECT_INCLUDE)/nfs/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/nfs/xdr_subs.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/nfs/xdr_subs.h
+
+$(PROJECT_INCLUDE)/rtems/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems
+ @: > $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/rtems_bsdnet.h: rtems/rtems_bsdnet.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems_bsdnet.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems_bsdnet.h
+
+$(PROJECT_INCLUDE)/rtems/rtems_bsdnet_internal.h: rtems/rtems_bsdnet_internal.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems_bsdnet_internal.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems_bsdnet_internal.h
+
+$(PROJECT_INCLUDE)/rtems/tftp.h: rtems/tftp.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/tftp.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/tftp.h
+
+$(PROJECT_INCLUDE)/rtems/ftpfs.h: rtems/ftpfs.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/ftpfs.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/ftpfs.h
+
+$(PROJECT_INCLUDE)/rtems/mkrootfs.h: rtems/mkrootfs.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/mkrootfs.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/mkrootfs.h
+
+$(PROJECT_INCLUDE)/sys/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/sys
+ @: > $(PROJECT_INCLUDE)/sys/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/sys/$(dirstamp)
+
+$(PROJECT_INCLUDE)/sys/buf.h: sys/buf.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/buf.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/buf.h
+
+$(PROJECT_INCLUDE)/sys/callout.h: sys/callout.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/callout.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/callout.h
+
+$(PROJECT_INCLUDE)/sys/conf.h: sys/conf.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/conf.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/conf.h
+
+$(PROJECT_INCLUDE)/sys/domain.h: sys/domain.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/domain.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/domain.h
+
+$(PROJECT_INCLUDE)/sys/kernel.h: sys/kernel.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/kernel.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/kernel.h
+
+$(PROJECT_INCLUDE)/sys/libkern.h: sys/libkern.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/libkern.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/libkern.h
+
+$(PROJECT_INCLUDE)/sys/linker_set.h: sys/linker_set.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/linker_set.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/linker_set.h
+
+$(PROJECT_INCLUDE)/sys/malloc.h: sys/malloc.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/malloc.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/malloc.h
+
+$(PROJECT_INCLUDE)/sys/mbuf.h: sys/mbuf.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/mbuf.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/mbuf.h
+
+$(PROJECT_INCLUDE)/sys/mount.h: sys/mount.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/mount.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/mount.h
+
+$(PROJECT_INCLUDE)/sys/proc.h: sys/proc.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/proc.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/proc.h
+
+$(PROJECT_INCLUDE)/sys/protosw.h: sys/protosw.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/protosw.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/protosw.h
+
+$(PROJECT_INCLUDE)/sys/queue.h: sys/queue.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/queue.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/queue.h
+
+$(PROJECT_INCLUDE)/sys/reboot.h: sys/reboot.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/reboot.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/reboot.h
+
+$(PROJECT_INCLUDE)/sys/resourcevar.h: sys/resourcevar.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/resourcevar.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/resourcevar.h
+
+$(PROJECT_INCLUDE)/sys/rtprio.h: sys/rtprio.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/rtprio.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/rtprio.h
+
+$(PROJECT_INCLUDE)/sys/select.h: sys/select.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/select.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/select.h
+
+$(PROJECT_INCLUDE)/sys/signalvar.h: sys/signalvar.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/signalvar.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/signalvar.h
+
+$(PROJECT_INCLUDE)/sys/socket.h: sys/socket.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/socket.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/socket.h
+
+$(PROJECT_INCLUDE)/sys/socketvar.h: sys/socketvar.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/socketvar.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/socketvar.h
+
+$(PROJECT_INCLUDE)/sys/sysctl.h: sys/sysctl.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/sysctl.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/sysctl.h
+
+$(PROJECT_INCLUDE)/sys/syslog.h: sys/syslog.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/syslog.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/syslog.h
+
+$(PROJECT_INCLUDE)/sys/systm.h: sys/systm.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/systm.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/systm.h
+
+$(PROJECT_INCLUDE)/sys/ttydefaults.h: sys/ttydefaults.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/ttydefaults.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/ttydefaults.h
+
+$(PROJECT_INCLUDE)/sys/ucred.h: sys/ucred.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/ucred.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/ucred.h
+
+$(PROJECT_INCLUDE)/sys/uio.h: sys/uio.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/uio.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/uio.h
+
+$(PROJECT_INCLUDE)/sys/un.h: sys/un.h $(PROJECT_INCLUDE)/sys/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sys/un.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sys/un.h
+
+$(PROJECT_INCLUDE)/vm/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/vm
+ @: > $(PROJECT_INCLUDE)/vm/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/vm/$(dirstamp)
+
+$(PROJECT_INCLUDE)/vm/vm.h: vm/vm.h $(PROJECT_INCLUDE)/vm/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/vm/vm.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/vm/vm.h
+
+$(PROJECT_INCLUDE)/vm/vm_extern.h: vm/vm_extern.h $(PROJECT_INCLUDE)/vm/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/vm/vm_extern.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/vm/vm_extern.h
+
+$(PROJECT_INCLUDE)/vm/vm_kern.h: vm/vm_kern.h $(PROJECT_INCLUDE)/vm/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/vm/vm_kern.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/vm/vm_kern.h
+
+$(PROJECT_INCLUDE)/vm/vm_param.h: vm/vm_param.h $(PROJECT_INCLUDE)/vm/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/vm/vm_param.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/vm/vm_param.h
+endif
+
+CLEANFILES += $(PREINSTALL_FILES)
+DISTCLEANFILES += $(PREINSTALL_DIRS)
+
+include $(top_srcdir)/automake/subdirs.am
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/libnetworking/README b/cpukit/libnetworking/README
new file mode 100644
index 0000000000..ed76f94183
--- /dev/null
+++ b/cpukit/libnetworking/README
@@ -0,0 +1,72 @@
+#
+# $Id$
+#
+
+This is a snapshot of my attempt to fit the FreeBSD networking code into
+RTEMS. Things seem to be working!
+
+Things that need to be done:
+ 1) More documentation!
+ 2) Figure out what's still not working :-)
+ 3) Rationalize the include files. Right now I have a special
+ hack in the Makefile to ensure that I pick up the FreeBSD versions
+ of the include files that are duplicated between RTEMS
+ and FreeBSD.
+ The network device driver source should move to the BSP source tree.
+ 4) Have a look at all the FIXME comments.
+ 5) Go through and make sure that all the source files are
+ free of undesired copyright restrictions.
+
+Initial Changes
+===============
+
+19-AUG-1998 snapshot
+ - Pulled BOOTP initialization out of rtems_glue. Applications which
+ don't used BOOTP are now about 5k smaller.
+ - Loopback interface is not installed by default, rather it is
+ attached like any other interface. Saves about 0.5 kbytes.
+ - Add rtems_bsdnet_show_if_stats();
+ - Moved test programs from below freebsd directory.
+
+18-AUG-1998 snapshot
+ - Removed some include files that were already part of RTEMS.
+ - Cleaned up machine/types.h to prepare for inclusion in RTEMS source.
+ - Added syslog library routines -- much simpler than KA9Q version.
+ Sockets can be shared among tasks (as long as the send is
+ protected by a mutex) so there's no need for a Syslog Daemon.
+
+16-AUG-1998 snapshot
+ - Table-driven configuration (networkconfig.h).
+ - Cleaned up rtems_bsdnet.h.
+ - BOOTP now retries properly -- Note to Joel:
+ The dichotomy between RTEMS and UNIX error codes is
+ a real pain!
+
+14-AUG-1998 snapshot
+ - Added dummy getprotobyname() and getprotobynum() functions.
+ - Added socket ioctl.
+ - Added application-level entry to manipulate routing tables.
+ - Added non-BOOTP network initialization.
+
+13-AUG-1998 snapshot
+ - Changed some BOOTP addresses from sockaddr_in to inaddr;
+ - Get DNS information from BOOTP reply.
+ - Got DNS lookups working.
+ Bloatware comes to RTEMS -- invoking gethostbyname() drags in
+ and extra 40 kbytes of code!
+ - Added hostname lookup program.
+
+12-AUG-1998 snapshot
+ - Added startup delay to network initialization.
+ - More statistic-printing routines.
+ - Added TFTP driver and test program
+ - Modified TFTP test program to use networkconfig.h.
+ - Removed unused include files.
+ - Added from ftp://ftp.ca.FreeBSD.ORG/pub/FreeBSD/FreeBSD-current/src/lib/libc/net.
+
+11-AUG-1998 snapshot.
+ - Added getpeername()
+ - Added M68k versions of IP checksum code
+ - Added TCP timing program to snapshot.
+
+02-AUG-1998 snapshot.
diff --git a/cpukit/libnetworking/arpa/ftp.h b/cpukit/libnetworking/arpa/ftp.h
new file mode 100644
index 0000000000..584d290bc9
--- /dev/null
+++ b/cpukit/libnetworking/arpa/ftp.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 1983, 1989, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)ftp.h 8.1 (Berkeley) 6/2/93
+ *
+ * $Id$
+ */
+
+#ifndef _ARPA_FTP_H_
+#define _ARPA_FTP_H_
+
+/* Definitions for FTP; see RFC-765. */
+
+/*
+ * Reply codes.
+ */
+#define PRELIM 1 /* positive preliminary */
+#define COMPLETE 2 /* positive completion */
+#define CONTINUE 3 /* positive intermediate */
+#define TRANSIENT 4 /* transient negative completion */
+#define ERROR 5 /* permanent negative completion */
+
+/*
+ * Type codes
+ */
+#define TYPE_A 1 /* ASCII */
+#define TYPE_E 2 /* EBCDIC */
+#define TYPE_I 3 /* image */
+#define TYPE_L 4 /* local byte size */
+
+#ifdef FTP_NAMES
+char *typenames[] = {"0", "ASCII", "EBCDIC", "Image", "Local" };
+#endif
+
+/*
+ * Form codes
+ */
+#define FORM_N 1 /* non-print */
+#define FORM_T 2 /* telnet format effectors */
+#define FORM_C 3 /* carriage control (ASA) */
+#ifdef FTP_NAMES
+char *formnames[] = {"0", "Nonprint", "Telnet", "Carriage-control" };
+#endif
+
+/*
+ * Structure codes
+ */
+#define STRU_F 1 /* file (no record structure) */
+#define STRU_R 2 /* record structure */
+#define STRU_P 3 /* page structure */
+#ifdef FTP_NAMES
+char *strunames[] = {"0", "File", "Record", "Page" };
+#endif
+
+/*
+ * Mode types
+ */
+#define MODE_S 1 /* stream */
+#define MODE_B 2 /* block */
+#define MODE_C 3 /* compressed */
+#ifdef FTP_NAMES
+char *modenames[] = {"0", "Stream", "Block", "Compressed" };
+#endif
+
+/*
+ * Record Tokens
+ */
+#define REC_ESC '\377' /* Record-mode Escape */
+#define REC_EOR '\001' /* Record-mode End-of-Record */
+#define REC_EOF '\002' /* Record-mode End-of-File */
+
+/*
+ * Block Header
+ */
+#define BLK_EOR 0x80 /* Block is End-of-Record */
+#define BLK_EOF 0x40 /* Block is End-of-File */
+#define BLK_ERRORS 0x20 /* Block is suspected of containing errors */
+#define BLK_RESTART 0x10 /* Block is Restart Marker */
+
+#define BLK_BYTECOUNT 2 /* Bytes in this block */
+
+#endif /* !_FTP_H_ */
diff --git a/cpukit/libnetworking/arpa/inet.h b/cpukit/libnetworking/arpa/inet.h
new file mode 100644
index 0000000000..ad5332e7ab
--- /dev/null
+++ b/cpukit/libnetworking/arpa/inet.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ */
+
+/*
+ * @(#)inet.h 8.1 (Berkeley) 6/2/93
+ * From: Id: inet.h,v 8.5 1997/01/29 08:48:09 vixie Exp $
+ * $Id$
+ */
+
+#ifndef _ARPA_INET_H_
+#define _ARPA_INET_H_
+
+/* External definitions for functions in inet(3), addr2ascii(3) */
+
+#include <sys/types.h>
+#include <sys/cdefs.h>
+
+struct in_addr;
+
+#if 0 /* RTEMS -- Why rename these? */
+/* XXX all new diversions!! argh!! */
+#define inet_addr __inet_addr
+#define inet_aton __inet_aton
+#define inet_lnaof __inet_lnaof
+#define inet_makeaddr __inet_makeaddr
+#define inet_neta __inet_neta
+#define inet_netof __inet_netof
+#define inet_network __inet_network
+#define inet_net_ntop __inet_net_ntop
+#define inet_net_pton __inet_net_pton
+#define inet_ntoa __inet_ntoa
+#define inet_pton __inet_pton
+#define inet_ntop __inet_ntop
+#define inet_nsap_addr __inet_nsap_addr
+#define inet_nsap_ntoa __inet_nsap_ntoa
+#endif
+
+__BEGIN_DECLS
+int ascii2addr __P((int, const char *, void *));
+char *addr2ascii __P((int, const void *, int, char *));
+unsigned long inet_addr __P((const char *));
+int inet_aton __P((const char *, struct in_addr *));
+unsigned long inet_lnaof __P((struct in_addr));
+struct in_addr inet_makeaddr __P((u_long , u_long));
+char * inet_neta __P((u_long, char *, size_t));
+unsigned long inet_netof __P((struct in_addr));
+unsigned long inet_network __P((const char *));
+char *inet_net_ntop __P((int, const void *, int, char *, size_t));
+int inet_net_pton __P((int, const char *, void *, size_t));
+char *inet_ntoa __P((struct in_addr));
+int inet_pton __P((int, const char *, void *));
+const char *inet_ntop __P((int, const void *, char *, size_t));
+u_int inet_nsap_addr __P((const char *, u_char *, int));
+char *inet_nsap_ntoa __P((int, const u_char *, char *));
+__END_DECLS
+
+#endif /* !_INET_H_ */
diff --git a/cpukit/libnetworking/arpa/nameser.h b/cpukit/libnetworking/arpa/nameser.h
new file mode 100644
index 0000000000..634dece37b
--- /dev/null
+++ b/cpukit/libnetworking/arpa/nameser.h
@@ -0,0 +1,448 @@
+/*
+ * Copyright (c) 1983, 1989, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ */
+
+/*
+ * Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ */
+
+/*
+ * From: Id: nameser.h,v 8.16 1998/02/06 00:35:58 halley Exp
+ * $Id$
+ */
+
+#ifndef _ARPA_NAMESER_H_
+#define _ARPA_NAMESER_H_
+
+#define BIND_4_COMPAT
+
+#include <sys/types.h>
+#include <sys/cdefs.h>
+
+/*
+ * revision information. this is the release date in YYYYMMDD format.
+ * it can change every day so the right thing to do with it is use it
+ * in preprocessor commands such as "#if (__NAMESER > 19931104)". do not
+ * compare for equality; rather, use it to determine whether your libnameser.a
+ * is new enough to contain a certain feature.
+ */
+
+/* XXXRTH I made this bigger than __BIND in 4.9.5 T6B */
+#define __NAMESER 19961001 /* New interface version stamp. */
+
+/*
+ * Define constants based on RFC 883, RFC 1034, RFC 1035
+ */
+#define NS_PACKETSZ 512 /* maximum packet size */
+#define NS_MAXDNAME 1025 /* maximum domain name */
+#define NS_MAXCDNAME 255 /* maximum compressed domain name */
+#define NS_MAXLABEL 63 /* maximum length of domain label */
+#define NS_HFIXEDSZ 12 /* #/bytes of fixed data in header */
+#define NS_QFIXEDSZ 4 /* #/bytes of fixed data in query */
+#define NS_RRFIXEDSZ 10 /* #/bytes of fixed data in r record */
+#define NS_INT32SZ 4 /* #/bytes of data in a u_int32_t */
+#define NS_INT16SZ 2 /* #/bytes of data in a u_int16_t */
+#define NS_INT8SZ 1 /* #/bytes of data in a u_int8_t */
+#define NS_INADDRSZ 4 /* IPv4 T_A */
+#define NS_IN6ADDRSZ 16 /* IPv6 T_AAAA */
+#define NS_CMPRSFLGS 0xc0 /* Flag bits indicating name compression. */
+#define NS_DEFAULTPORT 53 /* For both TCP and UDP. */
+
+/*
+ * These can be expanded with synonyms, just keep ns_parse.c:ns_parserecord()
+ * in synch with it.
+ */
+typedef enum __ns_sect {
+ ns_s_qd = 0, /* Query: Question. */
+ ns_s_zn = 0, /* Update: Zone. */
+ ns_s_an = 1, /* Query: Answer. */
+ ns_s_pr = 1, /* Update: Prerequisites. */
+ ns_s_ns = 2, /* Query: Name servers. */
+ ns_s_ud = 2, /* Update: Update. */
+ ns_s_ar = 3, /* Query|Update: Additional records. */
+ ns_s_max = 4
+} ns_sect;
+
+/*
+ * This is a message handle. It is caller allocated and has no dynamic data.
+ * This structure is intended to be opaque to all but ns_parse.c, thus the
+ * leading _'s on the member names. Use the accessor functions, not the _'s.
+ */
+typedef struct __ns_msg {
+ const u_char *_msg, *_eom;
+ u_int16_t _id, _flags, _counts[ns_s_max];
+ const u_char *_sections[ns_s_max];
+ ns_sect _sect;
+ int _rrnum;
+ const u_char *_ptr;
+} ns_msg;
+
+/* Private data structure - do not use from outside library. */
+struct _ns_flagdata { int mask, shift; };
+extern struct _ns_flagdata _ns_flagdata[];
+
+/* Accessor macros - this is part of the public interface. */
+#define ns_msg_getflag(handle, flag) ( \
+ ((handle)._flags & _ns_flagdata[flag].mask) \
+ >> _ns_flagdata[flag].shift \
+ )
+#define ns_msg_id(handle) ((handle)._id + 0)
+#define ns_msg_base(handle) ((handle)._msg + 0)
+#define ns_msg_end(handle) ((handle)._eom + 0)
+#define ns_msg_size(handle) ((handle)._eom - (handle)._msg)
+#define ns_msg_count(handle, section) ((handle)._counts[section] + 0)
+
+/*
+ * This is a parsed record. It is caller allocated and has no dynamic data.
+ */
+typedef struct __ns_rr {
+ char name[NS_MAXDNAME]; /* XXX need to malloc */
+ u_int16_t type;
+ u_int16_t class;
+ u_int32_t ttl;
+ u_int16_t rdlength;
+ const u_char *rdata;
+} ns_rr;
+
+/* Accessor macros - this is part of the public interface. */
+#define ns_rr_name(rr) (((rr).name[0] != '\0') ? (rr).name : ".")
+#define ns_rr_type(rr) ((rr).type + 0)
+#define ns_rr_class(rr) ((rr).class + 0)
+#define ns_rr_ttl(rr) ((rr).ttl + 0)
+#define ns_rr_rdlen(rr) ((rr).rdlength + 0)
+#define ns_rr_rdata(rr) ((rr).rdata + 0)
+
+/*
+ * These don't have to be in the same order as in the packet flags word,
+ * and they can even overlap in some cases, but they will need to be kept
+ * in synch with ns_parse.c:ns_flagdata[].
+ */
+typedef enum __ns_flag {
+ ns_f_qr, /* Question/Response. */
+ ns_f_opcode, /* Operation code. */
+ ns_f_aa, /* Authoritative Answer. */
+ ns_f_tc, /* Truncation occurred. */
+ ns_f_rd, /* Recursion Desired. */
+ ns_f_ra, /* Recursion Available. */
+ ns_f_z, /* MBZ. */
+ ns_f_ad, /* Authentic Data (DNSSEC). */
+ ns_f_cd, /* Checking Disabled (DNSSEC). */
+ ns_f_rcode, /* Response code. */
+ ns_f_max
+} ns_flag;
+
+/*
+ * Currently defined opcodes.
+ */
+typedef enum __ns_opcode {
+ ns_o_query = 0, /* Standard query. */
+ ns_o_iquery = 1, /* Inverse query (deprecated/unsupported). */
+ ns_o_status = 2, /* Name server status query (unsupported). */
+ /* Opcode 3 is undefined/reserved. */
+ ns_o_notify = 4, /* Zone change notification. */
+ ns_o_update = 5, /* Zone update message. */
+ ns_o_max = 6
+} ns_opcode;
+
+/*
+ * Currently defined response codes.
+ */
+typedef enum __ns_rcode {
+ ns_r_noerror = 0, /* No error occurred. */
+ ns_r_formerr = 1, /* Format error. */
+ ns_r_servfail = 2, /* Server failure. */
+ ns_r_nxdomain = 3, /* Name error. */
+ ns_r_notimpl = 4, /* Unimplemented. */
+ ns_r_refused = 5, /* Operation refused. */
+ /* these are for BIND_UPDATE */
+ ns_r_yxdomain = 6, /* Name exists */
+ ns_r_yxrrset = 7, /* RRset exists */
+ ns_r_nxrrset = 8, /* RRset does not exist */
+ ns_r_notauth = 9, /* Not authoritative for zone */
+ ns_r_notzone = 10, /* Zone of record different from zone section */
+ ns_r_max = 11
+} ns_rcode;
+
+/* BIND_UPDATE */
+typedef enum __ns_update_operation {
+ ns_uop_delete = 0,
+ ns_uop_add = 1,
+ ns_uop_max = 2
+} ns_update_operation;
+
+/*
+ * This RR-like structure is particular to UPDATE.
+ */
+struct ns_updrec {
+ struct ns_updrec *r_prev; /* prev record */
+ struct ns_updrec *r_next; /* next record */
+ u_int8_t r_section; /* ZONE/PREREQUISITE/UPDATE */
+ char * r_dname; /* owner of the RR */
+ u_int16_t r_class; /* class number */
+ u_int16_t r_type; /* type number */
+ u_int32_t r_ttl; /* time to live */
+ u_char * r_data; /* rdata fields as text string */
+ u_int16_t r_size; /* size of r_data field */
+ int r_opcode; /* type of operation */
+ /* following fields for private use by the resolver/server routines */
+ struct ns_updrec *r_grpnext; /* next record when grouped */
+ struct databuf *r_dp; /* databuf to process */
+ struct databuf *r_deldp; /* databuf's deleted/overwritten */
+ u_int16_t r_zone; /* zone number on server */
+};
+typedef struct ns_updrec ns_updrec;
+
+/*
+ * Currently defined type values for resources and queries.
+ */
+typedef enum __ns_type {
+ ns_t_a = 1, /* Host address. */
+ ns_t_ns = 2, /* Authoritative server. */
+ ns_t_md = 3, /* Mail destination. */
+ ns_t_mf = 4, /* Mail forwarder. */
+ ns_t_cname = 5, /* Canonical name. */
+ ns_t_soa = 6, /* Start of authority zone. */
+ ns_t_mb = 7, /* Mailbox domain name. */
+ ns_t_mg = 8, /* Mail group member. */
+ ns_t_mr = 9, /* Mail rename name. */
+ ns_t_null = 10, /* Null resource record. */
+ ns_t_wks = 11, /* Well known service. */
+ ns_t_ptr = 12, /* Domain name pointer. */
+ ns_t_hinfo = 13, /* Host information. */
+ ns_t_minfo = 14, /* Mailbox information. */
+ ns_t_mx = 15, /* Mail routing information. */
+ ns_t_txt = 16, /* Text strings. */
+ ns_t_rp = 17, /* Responsible person. */
+ ns_t_afsdb = 18, /* AFS cell database. */
+ ns_t_x25 = 19, /* X_25 calling address. */
+ ns_t_isdn = 20, /* ISDN calling address. */
+ ns_t_rt = 21, /* Router. */
+ ns_t_nsap = 22, /* NSAP address. */
+ ns_t_nsap_ptr = 23, /* Reverse NSAP lookup (deprecated). */
+ ns_t_sig = 24, /* Security signature. */
+ ns_t_key = 25, /* Security key. */
+ ns_t_px = 26, /* X.400 mail mapping. */
+ ns_t_gpos = 27, /* Geographical position (withdrawn). */
+ ns_t_aaaa = 28, /* Ip6 Address. */
+ ns_t_loc = 29, /* Location Information. */
+ ns_t_nxt = 30, /* Next domain (security). */
+ ns_t_eid = 31, /* Endpoint identifier. */
+ ns_t_nimloc = 32, /* Nimrod Locator. */
+ ns_t_srv = 33, /* Server Selection. */
+ ns_t_atma = 34, /* ATM Address */
+ ns_t_naptr = 35, /* Naming Authority PoinTeR */
+ /* Query type values which do not appear in resource records. */
+ ns_t_ixfr = 251, /* Incremental zone transfer. */
+ ns_t_axfr = 252, /* Transfer zone of authority. */
+ ns_t_mailb = 253, /* Transfer mailbox records. */
+ ns_t_maila = 254, /* Transfer mail agent records. */
+ ns_t_any = 255, /* Wildcard match. */
+ ns_t_max = 65536
+} ns_type;
+
+/*
+ * Values for class field
+ */
+typedef enum __ns_class {
+ ns_c_in = 1, /* Internet. */
+ /* Class 2 unallocated/unsupported. */
+ ns_c_chaos = 3, /* MIT Chaos-net. */
+ ns_c_hs = 4, /* MIT Hesiod. */
+ /* Query class values which do not appear in resource records */
+ ns_c_none = 254, /* for prereq. sections in update requests */
+ ns_c_any = 255, /* Wildcard match. */
+ ns_c_max = 65536
+} ns_class;
+
+/*
+ * Flags field of the KEY RR rdata
+ */
+#define NS_KEY_TYPEMASK 0xC000 /* Mask for "type" bits */
+#define NS_KEY_TYPE_AUTH_CONF 0x0000 /* Key usable for both */
+#define NS_KEY_TYPE_CONF_ONLY 0x8000 /* Key usable for confidentiality */
+#define NS_KEY_TYPE_AUTH_ONLY 0x4000 /* Key usable for authentication */
+#define NS_KEY_TYPE_NO_KEY 0xC000 /* No key usable for either; no key */
+/* The type bits can also be interpreted independently, as single bits: */
+#define NS_KEY_NO_AUTH 0x8000 /* Key unusable for authentication */
+#define NS_KEY_NO_CONF 0x4000 /* Key unusable for confidentiality */
+#define NS_KEY_EXPERIMENTAL 0x2000 /* Security is *mandatory* if bit=0 */
+#define NS_KEY_RESERVED3 0x1000 /* reserved - must be zero */
+#define NS_KEY_RESERVED4 0x0800 /* reserved - must be zero */
+#define NS_KEY_USERACCOUNT 0x0400 /* key is assoc. with a user acct */
+#define NS_KEY_ENTITY 0x0200 /* key is assoc. with entity eg host */
+#define NS_KEY_ZONEKEY 0x0100 /* key is zone key */
+#define NS_KEY_IPSEC 0x0080 /* key is for IPSEC (host or user)*/
+#define NS_KEY_EMAIL 0x0040 /* key is for email (MIME security) */
+#define NS_KEY_RESERVED10 0x0020 /* reserved - must be zero */
+#define NS_KEY_RESERVED11 0x0010 /* reserved - must be zero */
+#define NS_KEY_SIGNATORYMASK 0x000F /* key can sign RR's of same name */
+
+#define NS_KEY_RESERVED_BITMASK ( NS_KEY_RESERVED3 | \
+ NS_KEY_RESERVED4 | \
+ NS_KEY_RESERVED10 | \
+ NS_KEY_RESERVED11 )
+
+/* The Algorithm field of the KEY and SIG RR's is an integer, {1..254} */
+#define NS_ALG_MD5RSA 1 /* MD5 with RSA */
+#define NS_ALG_EXPIRE_ONLY 253 /* No alg, no security */
+#define NS_ALG_PRIVATE_OID 254 /* Key begins with OID giving alg */
+
+/* Signatures */
+#define NS_MD5RSA_MIN_BITS 512 /* Size of a mod or exp in bits */
+#define NS_MD5RSA_MAX_BITS 2552
+ /* Total of binary mod and exp */
+#define NS_MD5RSA_MAX_BYTES ((NS_MD5RSA_MAX_BITS+7/8)*2+3)
+ /* Max length of text sig block */
+#define NS_MD5RSA_MAX_BASE64 (((NS_MD5RSA_MAX_BYTES+2)/3)*4)
+
+/* Offsets into SIG record rdata to find various values */
+#define NS_SIG_TYPE 0 /* Type flags */
+#define NS_SIG_ALG 2 /* Algorithm */
+#define NS_SIG_LABELS 3 /* How many labels in name */
+#define NS_SIG_OTTL 4 /* Original TTL */
+#define NS_SIG_EXPIR 8 /* Expiration time */
+#define NS_SIG_SIGNED 12 /* Signature time */
+#define NS_SIG_FOOT 16 /* Key footprint */
+#define NS_SIG_SIGNER 18 /* Domain name of who signed it */
+
+/* How RR types are represented as bit-flags in NXT records */
+#define NS_NXT_BITS 8
+#define NS_NXT_BIT_SET( n,p) (p[(n)/NS_NXT_BITS] |= (0x80>>((n)%NS_NXT_BITS)))
+#define NS_NXT_BIT_CLEAR(n,p) (p[(n)/NS_NXT_BITS] &= ~(0x80>>((n)%NS_NXT_BITS)))
+#define NS_NXT_BIT_ISSET(n,p) (p[(n)/NS_NXT_BITS] & (0x80>>((n)%NS_NXT_BITS)))
+
+
+/*
+ * Inline versions of get/put short/long. Pointer is advanced.
+ */
+#define NS_GET16(s, cp) { \
+ register u_char *t_cp = (u_char *)(cp); \
+ (s) = ((u_int16_t)t_cp[0] << 8) \
+ | ((u_int16_t)t_cp[1]) \
+ ; \
+ (cp) += NS_INT16SZ; \
+}
+
+#define NS_GET32(l, cp) { \
+ register u_char *t_cp = (u_char *)(cp); \
+ (l) = ((u_int32_t)t_cp[0] << 24) \
+ | ((u_int32_t)t_cp[1] << 16) \
+ | ((u_int32_t)t_cp[2] << 8) \
+ | ((u_int32_t)t_cp[3]) \
+ ; \
+ (cp) += NS_INT32SZ; \
+}
+
+#define NS_PUT16(s, cp) { \
+ register u_int16_t t_s = (u_int16_t)(s); \
+ register u_char *t_cp = (u_char *)(cp); \
+ *t_cp++ = t_s >> 8; \
+ *t_cp = t_s; \
+ (cp) += NS_INT16SZ; \
+}
+
+#define NS_PUT32(l, cp) { \
+ register u_int32_t t_l = (u_int32_t)(l); \
+ register u_char *t_cp = (u_char *)(cp); \
+ *t_cp++ = t_l >> 24; \
+ *t_cp++ = t_l >> 16; \
+ *t_cp++ = t_l >> 8; \
+ *t_cp = t_l; \
+ (cp) += NS_INT32SZ; \
+}
+
+/*
+ * ANSI C identifier hiding.
+ */
+#define ns_get16 __ns_get16
+#define ns_get32 __ns_get32
+#define ns_put16 __ns_put16
+#define ns_put32 __ns_put32
+#define ns_initparse __ns_initparse
+#define ns_parserr __ns_parserr
+#define ns_sprintrr __ns_sprintrr
+#define ns_sprintrrf __ns_sprintrrf
+#define ns_format_ttl __ns_format_ttl
+#define ns_parse_ttl __ns_parse_ttl
+#define ns_name_ntop __ns_name_ntop
+#define ns_name_pton __ns_name_pton
+#define ns_name_unpack __ns_name_unpack
+#define ns_name_pack __ns_name_pack
+#define ns_name_compress __ns_name_compress
+#define ns_name_uncompress __ns_name_uncompress
+
+__BEGIN_DECLS
+u_int ns_get16 __P((const u_char *));
+u_long ns_get32 __P((const u_char *));
+void ns_put16 __P((u_int, u_char *));
+void ns_put32 __P((u_long, u_char *));
+int ns_initparse __P((const u_char *, int, ns_msg *));
+int ns_parserr __P((ns_msg *, ns_sect, int, ns_rr *));
+int ns_sprintrr __P((const ns_msg *, const ns_rr *,
+ const char *, const char *, char *, size_t));
+int ns_sprintrrf __P((const u_char *, size_t, const char *,
+ ns_class, ns_type, u_long, const u_char *,
+ size_t, const char *, const char *,
+ char *, size_t));
+int ns_format_ttl __P((u_long, char *, size_t));
+int ns_parse_ttl __P((const char *, u_long *));
+int ns_name_ntop __P((const u_char *, char *, size_t));
+int ns_name_pton __P((const char *, u_char *, size_t));
+int ns_name_unpack __P((const u_char *, const u_char *,
+ const u_char *, u_char *, size_t));
+int ns_name_pack __P((const u_char *, u_char *, int,
+ const u_char **, const u_char **));
+int ns_name_uncompress __P((const u_char *, const u_char *,
+ const u_char *, char *, size_t));
+int ns_name_compress __P((const char *, u_char *, size_t,
+ const u_char **, const u_char **));
+int ns_name_skip __P((const u_char **, const u_char *));
+__END_DECLS
+
+#ifdef BIND_4_COMPAT
+#include <arpa/nameser_compat.h>
+#endif
+
+#endif /* !_ARPA_NAMESER_H_ */
diff --git a/cpukit/libnetworking/arpa/nameser_compat.h b/cpukit/libnetworking/arpa/nameser_compat.h
new file mode 100644
index 0000000000..2ab5b47386
--- /dev/null
+++ b/cpukit/libnetworking/arpa/nameser_compat.h
@@ -0,0 +1,194 @@
+/* Copyright (c) 1983, 1989
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ */
+
+/*
+ * from nameser.h 8.1 (Berkeley) 6/2/93
+ * From: Id: nameser_compat.h,v 8.9 1998/03/20 23:25:10 halley Exp
+ * $Id$
+ */
+
+#ifndef _ARPA_NAMESER_COMPAT_
+#define _ARPA_NAMESER_COMPAT_
+
+#define __BIND 19950621 /* (DEAD) interface version stamp. */
+
+#include <machine/endian.h>
+
+#if !defined(BYTE_ORDER) || \
+ (BYTE_ORDER != BIG_ENDIAN && BYTE_ORDER != LITTLE_ENDIAN && \
+ BYTE_ORDER != PDP_ENDIAN)
+ /* you must determine what the correct bit order is for
+ * your compiler - the next line is an intentional error
+ * which will force your compiles to bomb until you fix
+ * the above macros.
+ */
+ error "Undefined or invalid BYTE_ORDER";
+#endif
+
+/*
+ * Structure for query header. The order of the fields is machine- and
+ * compiler-dependent, depending on the byte/bit order and the layout
+ * of bit fields. We use bit fields only in int variables, as this
+ * is all ANSI requires. This requires a somewhat confusing rearrangement.
+ */
+
+typedef struct {
+ unsigned id :16; /* query identification number */
+#if BYTE_ORDER == BIG_ENDIAN
+ /* fields in third byte */
+ unsigned qr: 1; /* response flag */
+ unsigned opcode: 4; /* purpose of message */
+ unsigned aa: 1; /* authoritive answer */
+ unsigned tc: 1; /* truncated message */
+ unsigned rd: 1; /* recursion desired */
+ /* fields in fourth byte */
+ unsigned ra: 1; /* recursion available */
+ unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */
+ unsigned ad: 1; /* authentic data from named */
+ unsigned cd: 1; /* checking disabled by resolver */
+ unsigned rcode :4; /* response code */
+#endif
+#if BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN
+ /* fields in third byte */
+ unsigned rd :1; /* recursion desired */
+ unsigned tc :1; /* truncated message */
+ unsigned aa :1; /* authoritive answer */
+ unsigned opcode :4; /* purpose of message */
+ unsigned qr :1; /* response flag */
+ /* fields in fourth byte */
+ unsigned rcode :4; /* response code */
+ unsigned cd: 1; /* checking disabled by resolver */
+ unsigned ad: 1; /* authentic data from named */
+ unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */
+ unsigned ra :1; /* recursion available */
+#endif
+ /* remaining bytes */
+ unsigned qdcount :16; /* number of question entries */
+ unsigned ancount :16; /* number of answer entries */
+ unsigned nscount :16; /* number of authority entries */
+ unsigned arcount :16; /* number of resource entries */
+} HEADER;
+
+#define PACKETSZ NS_PACKETSZ
+#define MAXDNAME NS_MAXDNAME
+#define MAXCDNAME NS_MAXCDNAME
+#define MAXLABEL NS_MAXLABEL
+#define HFIXEDSZ NS_HFIXEDSZ
+#define QFIXEDSZ NS_QFIXEDSZ
+#define RRFIXEDSZ NS_RRFIXEDSZ
+#define INT32SZ NS_INT32SZ
+#define INT16SZ NS_INT16SZ
+#define INADDRSZ NS_INADDRSZ
+#define IN6ADDRSZ NS_IN6ADDRSZ
+#define INDIR_MASK NS_CMPRSFLGS
+#define NAMESERVER_PORT NS_DEFAULTPORT
+
+#define S_ZONE ns_s_zn
+#define S_PREREQ ns_s_pr
+#define S_UPDATE ns_s_ud
+#define S_ADDT ns_s_ar
+
+#define QUERY ns_o_query
+#define IQUERY ns_o_iquery
+#define STATUS ns_o_status
+#define NS_NOTIFY_OP ns_o_notify
+#define NS_UPDATE_OP ns_o_update
+
+#define NOERROR ns_r_noerror
+#define FORMERR ns_r_formerr
+#define SERVFAIL ns_r_servfail
+#define NXDOMAIN ns_r_nxdomain
+#define NOTIMP ns_r_notimpl
+#define REFUSED ns_r_refused
+#define YXDOMAIN ns_r_yxdomain
+#define YXRRSET ns_r_yxrrset
+#define NXRRSET ns_r_nxrrset
+#define NOTAUTH ns_r_notauth
+#define NOTZONE ns_r_notzone
+
+#define DELETE ns_uop_delete
+#define ADD ns_uop_add
+
+#define T_A ns_t_a
+#define T_NS ns_t_ns
+#define T_MD ns_t_md
+#define T_MF ns_t_mf
+#define T_CNAME ns_t_cname
+#define T_SOA ns_t_soa
+#define T_MB ns_t_mb
+#define T_MG ns_t_mg
+#define T_MR ns_t_mr
+#define T_NULL ns_t_null
+#define T_WKS ns_t_wks
+#define T_PTR ns_t_ptr
+#define T_HINFO ns_t_hinfo
+#define T_MINFO ns_t_minfo
+#define T_MX ns_t_mx
+#define T_TXT ns_t_txt
+#define T_RP ns_t_rp
+#define T_AFSDB ns_t_afsdb
+#define T_X25 ns_t_x25
+#define T_ISDN ns_t_isdn
+#define T_RT ns_t_rt
+#define T_NSAP ns_t_nsap
+#define T_NSAP_PTR ns_t_nsap_ptr
+#define T_SIG ns_t_sig
+#define T_KEY ns_t_key
+#define T_PX ns_t_px
+#define T_GPOS ns_t_gpos
+#define T_AAAA ns_t_aaaa
+#define T_LOC ns_t_loc
+#define T_NXT ns_t_nxt
+#define T_EID ns_t_eid
+#define T_NIMLOC ns_t_nimloc
+#define T_SRV ns_t_srv
+#define T_ATMA ns_t_atma
+#define T_NAPTR ns_t_naptr
+#define T_IXFR ns_t_ixfr
+#define T_AXFR ns_t_axfr
+#define T_MAILB ns_t_mailb
+#define T_MAILA ns_t_maila
+#define T_ANY ns_t_any
+
+#define C_IN ns_c_in
+#define C_CHAOS ns_c_chaos
+#define C_HS ns_c_hs
+/* BIND_UPDATE */
+#define C_NONE ns_c_none
+#define C_ANY ns_c_any
+
+#define GETSHORT NS_GET16
+#define GETLONG NS_GET32
+#define PUTSHORT NS_PUT16
+#define PUTLONG NS_PUT32
+
+#endif /* _ARPA_NAMESER_COMPAT_ */
diff --git a/cpukit/libnetworking/arpa/telnet.h b/cpukit/libnetworking/arpa/telnet.h
new file mode 100644
index 0000000000..09b85692da
--- /dev/null
+++ b/cpukit/libnetworking/arpa/telnet.h
@@ -0,0 +1,342 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)telnet.h 8.2 (Berkeley) 12/15/93
+ *
+ * $Id$
+ */
+
+#ifndef _ARPA_TELNET_H_
+#define _ARPA_TELNET_H_
+
+/*
+ * Definitions for the TELNET protocol.
+ */
+#define IAC 255 /* interpret as command: */
+#define DONT 254 /* you are not to use option */
+#define DO 253 /* please, you use option */
+#define WONT 252 /* I won't use option */
+#define WILL 251 /* I will use option */
+#define SB 250 /* interpret as subnegotiation */
+#define GA 249 /* you may reverse the line */
+#define EL 248 /* erase the current line */
+#define EC 247 /* erase the current character */
+#define AYT 246 /* are you there */
+#define AO 245 /* abort output--but let prog finish */
+#define IP 244 /* interrupt process--permanently */
+#define BREAK 243 /* break */
+#define DM 242 /* data mark--for connect. cleaning */
+#define NOP 241 /* nop */
+#define SE 240 /* end sub negotiation */
+#define EOR 239 /* end of record (transparent mode) */
+#define ABORT 238 /* Abort process */
+#define SUSP 237 /* Suspend process */
+#define xEOF 236 /* End of file: EOF is already used... */
+
+#define SYNCH 242 /* for telfunc calls */
+
+#ifdef TELCMDS
+char *telcmds[] = {
+ "EOF", "SUSP", "ABORT", "EOR",
+ "SE", "NOP", "DMARK", "BRK", "IP", "AO", "AYT", "EC",
+ "EL", "GA", "SB", "WILL", "WONT", "DO", "DONT", "IAC",
+ 0
+};
+#else
+extern char *telcmds[];
+#endif
+
+#define TELCMD_FIRST xEOF
+#define TELCMD_LAST IAC
+#define TELCMD_OK(x) ((unsigned int)(x) <= TELCMD_LAST && \
+ (unsigned int)(x) >= TELCMD_FIRST)
+#define TELCMD(x) telcmds[(x)-TELCMD_FIRST]
+
+/* telnet options */
+#define TELOPT_BINARY 0 /* 8-bit data path */
+#define TELOPT_ECHO 1 /* echo */
+#define TELOPT_RCP 2 /* prepare to reconnect */
+#define TELOPT_SGA 3 /* suppress go ahead */
+#define TELOPT_NAMS 4 /* approximate message size */
+#define TELOPT_STATUS 5 /* give status */
+#define TELOPT_TM 6 /* timing mark */
+#define TELOPT_RCTE 7 /* remote controlled transmission and echo */
+#define TELOPT_NAOL 8 /* negotiate about output line width */
+#define TELOPT_NAOP 9 /* negotiate about output page size */
+#define TELOPT_NAOCRD 10 /* negotiate about CR disposition */
+#define TELOPT_NAOHTS 11 /* negotiate about horizontal tabstops */
+#define TELOPT_NAOHTD 12 /* negotiate about horizontal tab disposition */
+#define TELOPT_NAOFFD 13 /* negotiate about formfeed disposition */
+#define TELOPT_NAOVTS 14 /* negotiate about vertical tab stops */
+#define TELOPT_NAOVTD 15 /* negotiate about vertical tab disposition */
+#define TELOPT_NAOLFD 16 /* negotiate about output LF disposition */
+#define TELOPT_XASCII 17 /* extended ascic character set */
+#define TELOPT_LOGOUT 18 /* force logout */
+#define TELOPT_BM 19 /* byte macro */
+#define TELOPT_DET 20 /* data entry terminal */
+#define TELOPT_SUPDUP 21 /* supdup protocol */
+#define TELOPT_SUPDUPOUTPUT 22 /* supdup output */
+#define TELOPT_SNDLOC 23 /* send location */
+#define TELOPT_TTYPE 24 /* terminal type */
+#define TELOPT_EOR 25 /* end or record */
+#define TELOPT_TUID 26 /* TACACS user identification */
+#define TELOPT_OUTMRK 27 /* output marking */
+#define TELOPT_TTYLOC 28 /* terminal location number */
+#define TELOPT_3270REGIME 29 /* 3270 regime */
+#define TELOPT_X3PAD 30 /* X.3 PAD */
+#define TELOPT_NAWS 31 /* window size */
+#define TELOPT_TSPEED 32 /* terminal speed */
+#define TELOPT_LFLOW 33 /* remote flow control */
+#define TELOPT_LINEMODE 34 /* Linemode option */
+#define TELOPT_XDISPLOC 35 /* X Display Location */
+#define TELOPT_OLD_ENVIRON 36 /* Old - Environment variables */
+#define TELOPT_AUTHENTICATION 37/* Authenticate */
+#define TELOPT_ENCRYPT 38 /* Encryption option */
+#define TELOPT_NEW_ENVIRON 39 /* New - Environment variables */
+#define TELOPT_EXOPL 255 /* extended-options-list */
+
+
+#define NTELOPTS (1+TELOPT_NEW_ENVIRON)
+#ifdef TELOPTS
+char *telopts[NTELOPTS+1] = {
+ "BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME",
+ "STATUS", "TIMING MARK", "RCTE", "NAOL", "NAOP",
+ "NAOCRD", "NAOHTS", "NAOHTD", "NAOFFD", "NAOVTS",
+ "NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO",
+ "DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT",
+ "SEND LOCATION", "TERMINAL TYPE", "END OF RECORD",
+ "TACACS UID", "OUTPUT MARKING", "TTYLOC",
+ "3270 REGIME", "X.3 PAD", "NAWS", "TSPEED", "LFLOW",
+ "LINEMODE", "XDISPLOC", "OLD-ENVIRON", "AUTHENTICATION",
+ "ENCRYPT", "NEW-ENVIRON",
+ 0
+};
+#define TELOPT_FIRST TELOPT_BINARY
+#define TELOPT_LAST TELOPT_NEW_ENVIRON
+#define TELOPT_OK(x) ((unsigned int)(x) <= TELOPT_LAST)
+#define TELOPT(x) telopts[(x)-TELOPT_FIRST]
+#endif
+
+/* sub-option qualifiers */
+#define TELQUAL_IS 0 /* option is... */
+#define TELQUAL_SEND 1 /* send option */
+#define TELQUAL_INFO 2 /* ENVIRON: informational version of IS */
+#define TELQUAL_REPLY 2 /* AUTHENTICATION: client version of IS */
+#define TELQUAL_NAME 3 /* AUTHENTICATION: client version of IS */
+
+#define LFLOW_OFF 0 /* Disable remote flow control */
+#define LFLOW_ON 1 /* Enable remote flow control */
+#define LFLOW_RESTART_ANY 2 /* Restart output on any char */
+#define LFLOW_RESTART_XON 3 /* Restart output only on XON */
+
+/*
+ * LINEMODE suboptions
+ */
+
+#define LM_MODE 1
+#define LM_FORWARDMASK 2
+#define LM_SLC 3
+
+#define MODE_EDIT 0x01
+#define MODE_TRAPSIG 0x02
+#define MODE_ACK 0x04
+#define MODE_SOFT_TAB 0x08
+#define MODE_LIT_ECHO 0x10
+
+#define MODE_MASK 0x1f
+
+/* Not part of protocol, but needed to simplify things... */
+#define MODE_FLOW 0x0100
+#define MODE_ECHO 0x0200
+#define MODE_INBIN 0x0400
+#define MODE_OUTBIN 0x0800
+#define MODE_FORCE 0x1000
+
+#define SLC_SYNCH 1
+#define SLC_BRK 2
+#define SLC_IP 3
+#define SLC_AO 4
+#define SLC_AYT 5
+#define SLC_EOR 6
+#define SLC_ABORT 7
+#define SLC_EOF 8
+#define SLC_SUSP 9
+#define SLC_EC 10
+#define SLC_EL 11
+#define SLC_EW 12
+#define SLC_RP 13
+#define SLC_LNEXT 14
+#define SLC_XON 15
+#define SLC_XOFF 16
+#define SLC_FORW1 17
+#define SLC_FORW2 18
+#define SLC_MCL 19
+#define SLC_MCR 20
+#define SLC_MCWL 21
+#define SLC_MCWR 22
+#define SLC_MCBOL 23
+#define SLC_MCEOL 24
+#define SLC_INSRT 25
+#define SLC_OVER 26
+#define SLC_ECR 27
+#define SLC_EWR 28
+#define SLC_EBOL 29
+#define SLC_EEOL 30
+
+#define NSLC 30
+
+/*
+ * For backwards compatability, we define SLC_NAMES to be the
+ * list of names if SLC_NAMES is not defined.
+ */
+#define SLC_NAMELIST "0", "SYNCH", "BRK", "IP", "AO", "AYT", "EOR", \
+ "ABORT", "EOF", "SUSP", "EC", "EL", "EW", "RP", \
+ "LNEXT", "XON", "XOFF", "FORW1", "FORW2", \
+ "MCL", "MCR", "MCWL", "MCWR", "MCBOL", \
+ "MCEOL", "INSRT", "OVER", "ECR", "EWR", \
+ "EBOL", "EEOL", \
+ 0
+
+#ifdef SLC_NAMES
+char *slc_names[] = {
+ SLC_NAMELIST
+};
+#else
+extern char *slc_names[];
+#define SLC_NAMES SLC_NAMELIST
+#endif
+
+#define SLC_NAME_OK(x) ((unsigned int)(x) <= NSLC)
+#define SLC_NAME(x) slc_names[x]
+
+#define SLC_NOSUPPORT 0
+#define SLC_CANTCHANGE 1
+#define SLC_VARIABLE 2
+#define SLC_DEFAULT 3
+#define SLC_LEVELBITS 0x03
+
+#define SLC_FUNC 0
+#define SLC_FLAGS 1
+#define SLC_VALUE 2
+
+#define SLC_ACK 0x80
+#define SLC_FLUSHIN 0x40
+#define SLC_FLUSHOUT 0x20
+
+#define OLD_ENV_VAR 1
+#define OLD_ENV_VALUE 0
+#define NEW_ENV_VAR 0
+#define NEW_ENV_VALUE 1
+#define ENV_ESC 2
+#define ENV_USERVAR 3
+
+/*
+ * AUTHENTICATION suboptions
+ */
+
+/*
+ * Who is authenticating who ...
+ */
+#define AUTH_WHO_CLIENT 0 /* Client authenticating server */
+#define AUTH_WHO_SERVER 1 /* Server authenticating client */
+#define AUTH_WHO_MASK 1
+
+/*
+ * amount of authentication done
+ */
+#define AUTH_HOW_ONE_WAY 0
+#define AUTH_HOW_MUTUAL 2
+#define AUTH_HOW_MASK 2
+
+#define AUTHTYPE_NULL 0
+#define AUTHTYPE_KERBEROS_V4 1
+#define AUTHTYPE_KERBEROS_V5 2
+#define AUTHTYPE_SPX 3
+#define AUTHTYPE_MINK 4
+#define AUTHTYPE_CNT 5
+
+#define AUTHTYPE_TEST 99
+
+#ifdef AUTH_NAMES
+char *authtype_names[] = {
+ "NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK",
+ 0
+};
+#else
+extern char *authtype_names[];
+#endif
+
+#define AUTHTYPE_NAME_OK(x) ((unsigned int)(x) < AUTHTYPE_CNT)
+#define AUTHTYPE_NAME(x) authtype_names[x]
+
+/*
+ * ENCRYPTion suboptions
+ */
+#define ENCRYPT_IS 0 /* I pick encryption type ... */
+#define ENCRYPT_SUPPORT 1 /* I support encryption types ... */
+#define ENCRYPT_REPLY 2 /* Initial setup response */
+#define ENCRYPT_START 3 /* Am starting to send encrypted */
+#define ENCRYPT_END 4 /* Am ending encrypted */
+#define ENCRYPT_REQSTART 5 /* Request you start encrypting */
+#define ENCRYPT_REQEND 6 /* Request you end encrypting */
+#define ENCRYPT_ENC_KEYID 7
+#define ENCRYPT_DEC_KEYID 8
+#define ENCRYPT_CNT 9
+
+#define ENCTYPE_ANY 0
+#define ENCTYPE_DES_CFB64 1
+#define ENCTYPE_DES_OFB64 2
+#define ENCTYPE_CNT 3
+
+#ifdef ENCRYPT_NAMES
+char *encrypt_names[] = {
+ "IS", "SUPPORT", "REPLY", "START", "END",
+ "REQUEST-START", "REQUEST-END", "ENC-KEYID", "DEC-KEYID",
+ 0
+};
+char *enctype_names[] = {
+ "ANY", "DES_CFB64", "DES_OFB64",
+ 0
+};
+#else
+extern char *encrypt_names[];
+extern char *enctype_names[];
+#endif
+
+
+#define ENCRYPT_NAME_OK(x) ((unsigned int)(x) < ENCRYPT_CNT)
+#define ENCRYPT_NAME(x) encrypt_names[x]
+
+#define ENCTYPE_NAME_OK(x) ((unsigned int)(x) < ENCTYPE_CNT)
+#define ENCTYPE_NAME(x) enctype_names[x]
+
+#endif /* !_TELNET_H_ */
diff --git a/cpukit/libnetworking/bpfilter.h b/cpukit/libnetworking/bpfilter.h
new file mode 100644
index 0000000000..2b4c47e48f
--- /dev/null
+++ b/cpukit/libnetworking/bpfilter.h
@@ -0,0 +1,5 @@
+/*
+ * $Id$
+ */
+
+/* intentionally empty file */
diff --git a/cpukit/libnetworking/kern/kern_mib.c b/cpukit/libnetworking/kern/kern_mib.c
new file mode 100644
index 0000000000..8d0185e053
--- /dev/null
+++ b/cpukit/libnetworking/kern/kern_mib.c
@@ -0,0 +1,382 @@
+/*-
+ * Copyright (c) 1982, 1986, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Karels at Berkeley Software Design, Inc.
+ *
+ * Quite extensively rewritten by Poul-Henning Kamp of the FreeBSD
+ * project, to make these variables more userfriendly.
+ *
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94
+ * $FreeBSD: src/sys/kern/kern_mib.c,v 1.62 2002/11/07 23:57:17 tmm Exp $
+ */
+
+#ifndef __rtems__
+#include "opt_posix.h"
+#endif
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/sysctl.h>
+#include <sys/proc.h>
+#ifndef __rtems__
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/jail.h>
+#include <sys/smp.h>
+#endif
+#include <sys/unistd.h>
+
+#ifdef __rtems__
+char machine[] = "SET ME";
+char osrelease[] = RTEMS_VERSION;
+char ostype[] = "RTEMS";
+#endif
+
+SYSCTL_NODE(, 0, sysctl, CTLFLAG_RW, 0,
+ "Sysctl internal magic");
+SYSCTL_NODE(, CTL_KERN, kern, CTLFLAG_RW, 0,
+ "High kernel, proc, limits &c");
+#ifndef __rtems__
+SYSCTL_NODE(, CTL_VM, vm, CTLFLAG_RW, 0,
+ "Virtual memory");
+SYSCTL_NODE(, CTL_VFS, vfs, CTLFLAG_RW, 0,
+ "File system");
+#endif
+SYSCTL_NODE(, CTL_NET, net, CTLFLAG_RW, 0,
+ "Network, (see socket.h)");
+#ifndef __rtems__
+SYSCTL_NODE(, CTL_DEBUG, debug, CTLFLAG_RW, 0,
+ "Debugging");
+SYSCTL_NODE(_debug, OID_AUTO, sizeof, CTLFLAG_RW, 0,
+ "Sizeof various things");
+SYSCTL_NODE(, CTL_HW, hw, CTLFLAG_RW, 0,
+ "hardware");
+SYSCTL_NODE(, CTL_MACHDEP, machdep, CTLFLAG_RW, 0,
+ "machine dependent");
+SYSCTL_NODE(, CTL_USER, user, CTLFLAG_RW, 0,
+ "user-level");
+SYSCTL_NODE(, CTL_P1003_1B, p1003_1b, CTLFLAG_RW, 0,
+ "p1003_1b, (see p1003_1b.h)");
+
+SYSCTL_NODE(, OID_AUTO, compat, CTLFLAG_RW, 0,
+ "Compatibility code");
+SYSCTL_NODE(, OID_AUTO, security, CTLFLAG_RW, 0,
+ "Security");
+#ifdef REGRESSION
+SYSCTL_NODE(, OID_AUTO, regression, CTLFLAG_RW, 0,
+ "Regression test MIB");
+#endif
+#endif
+
+SYSCTL_STRING(_kern, KERN_OSRELEASE, osrelease, CTLFLAG_RD,
+ osrelease, 0, "Operating system release");
+
+SYSCTL_INT(_kern, KERN_OSREV, osrevision, CTLFLAG_RD,
+ 0, BSD, "Operating system revision");
+
+#ifndef __rtems__
+SYSCTL_STRING(_kern, KERN_VERSION, version, CTLFLAG_RD,
+ version, 0, "Kernel version");
+#endif
+
+SYSCTL_STRING(_kern, KERN_OSTYPE, ostype, CTLFLAG_RD,
+ ostype, 0, "Operating system type");
+
+#ifndef __rtems__
+extern int osreldate;
+SYSCTL_INT(_kern, KERN_OSRELDATE, osreldate, CTLFLAG_RD,
+ &osreldate, 0, "Operating system release date");
+
+SYSCTL_INT(_kern, KERN_MAXPROC, maxproc, CTLFLAG_RD,
+ &maxproc, 0, "Maximum number of processes");
+
+SYSCTL_INT(_kern, KERN_MAXPROCPERUID, maxprocperuid, CTLFLAG_RW,
+ &maxprocperuid, 0, "Maximum processes allowed per userid");
+
+SYSCTL_INT(_kern, OID_AUTO, maxusers, CTLFLAG_RD,
+ &maxusers, 0, "Hint for kernel tuning");
+
+SYSCTL_INT(_kern, KERN_ARGMAX, argmax, CTLFLAG_RD,
+ 0, ARG_MAX, "Maximum bytes of argument to execve(2)");
+
+SYSCTL_INT(_kern, KERN_POSIX1, posix1version, CTLFLAG_RD,
+ 0, _POSIX_VERSION, "Version of POSIX attempting to comply to");
+
+SYSCTL_INT(_kern, KERN_NGROUPS, ngroups, CTLFLAG_RD,
+ 0, NGROUPS_MAX, "Maximum number of groups a user can belong to");
+
+SYSCTL_INT(_kern, KERN_JOB_CONTROL, job_control, CTLFLAG_RD,
+ 0, 1, "Whether job control is available");
+
+#ifdef _POSIX_SAVED_IDS
+SYSCTL_INT(_kern, KERN_SAVED_IDS, saved_ids, CTLFLAG_RD,
+ 0, 1, "Whether saved set-group/user ID is available");
+#else
+SYSCTL_INT(_kern, KERN_SAVED_IDS, saved_ids, CTLFLAG_RD,
+ 0, 0, "Whether saved set-group/user ID is available");
+#endif
+
+char kernelname[MAXPATHLEN] = "/kernel"; /* XXX bloat */
+
+SYSCTL_STRING(_kern, KERN_BOOTFILE, bootfile, CTLFLAG_RW,
+ kernelname, sizeof kernelname, "Name of kernel file booted");
+
+#ifdef SMP
+SYSCTL_INT(_hw, HW_NCPU, ncpu, CTLFLAG_RD,
+ &mp_ncpus, 0, "Number of active CPUs");
+#else
+SYSCTL_INT(_hw, HW_NCPU, ncpu, CTLFLAG_RD,
+ 0, 1, "Number of active CPUs");
+#endif
+
+SYSCTL_INT(_hw, HW_BYTEORDER, byteorder, CTLFLAG_RD,
+ 0, BYTE_ORDER, "System byte order");
+
+SYSCTL_INT(_hw, HW_PAGESIZE, pagesize, CTLFLAG_RD,
+ 0, PAGE_SIZE, "System memory page size");
+
+static int
+sysctl_hw_physmem(SYSCTL_HANDLER_ARGS)
+{
+ u_long val;
+
+ val = ctob(physmem);
+ return (sysctl_handle_long(oidp, &val, 0, req));
+}
+
+SYSCTL_PROC(_hw, HW_PHYSMEM, physmem, CTLTYPE_ULONG | CTLFLAG_RD,
+ 0, 0, sysctl_hw_physmem, "LU", "");
+
+static int
+sysctl_hw_usermem(SYSCTL_HANDLER_ARGS)
+{
+ u_long val;
+
+ val = ctob(physmem - cnt.v_wire_count);
+ return (sysctl_handle_long(oidp, &val, 0, req));
+}
+
+SYSCTL_PROC(_hw, HW_USERMEM, usermem, CTLTYPE_ULONG | CTLFLAG_RD,
+ 0, 0, sysctl_hw_usermem, "LU", "");
+
+SYSCTL_ULONG(_hw, OID_AUTO, availpages, CTLFLAG_RD, &physmem, 0, "");
+
+static char machine_arch[] = MACHINE_ARCH;
+SYSCTL_STRING(_hw, HW_MACHINE_ARCH, machine_arch, CTLFLAG_RD,
+ machine_arch, 0, "System architecture");
+
+char hostname[MAXHOSTNAMELEN];
+
+static int
+sysctl_hostname(SYSCTL_HANDLER_ARGS)
+{
+ struct prison *pr;
+ char tmphostname[MAXHOSTNAMELEN];
+ int error;
+
+ pr = req->td->td_ucred->cr_prison;
+ if (pr != NULL) {
+ if (!jail_set_hostname_allowed && req->newptr)
+ return (EPERM);
+ /*
+ * Process is in jail, so make a local copy of jail
+ * hostname to get/set so we don't have to hold the jail
+ * mutex during the sysctl copyin/copyout activities.
+ */
+ mtx_lock(&pr->pr_mtx);
+ bcopy(pr->pr_host, tmphostname, MAXHOSTNAMELEN);
+ mtx_unlock(&pr->pr_mtx);
+
+ error = sysctl_handle_string(oidp, tmphostname,
+ sizeof pr->pr_host, req);
+
+ if (req->newptr != NULL && error == 0) {
+ /*
+ * Copy the locally set hostname to the jail, if
+ * appropriate.
+ */
+ mtx_lock(&pr->pr_mtx);
+ bcopy(tmphostname, pr->pr_host, MAXHOSTNAMELEN);
+ mtx_unlock(&pr->pr_mtx);
+ }
+ } else
+ error = sysctl_handle_string(oidp,
+ hostname, sizeof hostname, req);
+ return (error);
+}
+
+SYSCTL_PROC(_kern, KERN_HOSTNAME, hostname,
+ CTLTYPE_STRING|CTLFLAG_RW|CTLFLAG_PRISON,
+ 0, 0, sysctl_hostname, "A", "Hostname");
+
+static int regression_securelevel_nonmonotonic = 0;
+
+#ifdef REGRESSION
+SYSCTL_INT(_regression, OID_AUTO, securelevel_nonmonotonic, CTLFLAG_RW,
+ &regression_securelevel_nonmonotonic, 0, "securelevel may be lowered");
+#endif
+
+int securelevel = -1;
+struct mtx securelevel_mtx;
+
+MTX_SYSINIT(securelevel_lock, &securelevel_mtx, "securelevel mutex lock",
+ MTX_DEF);
+
+static int
+sysctl_kern_securelvl(SYSCTL_HANDLER_ARGS)
+{
+ struct prison *pr;
+ int error, level;
+
+ pr = req->td->td_ucred->cr_prison;
+
+ /*
+ * If the process is in jail, return the maximum of the global and
+ * local levels; otherwise, return the global level.
+ */
+ if (pr != NULL) {
+ mtx_lock(&pr->pr_mtx);
+ level = imax(securelevel, pr->pr_securelevel);
+ mtx_unlock(&pr->pr_mtx);
+ } else
+ level = securelevel;
+ error = sysctl_handle_int(oidp, &level, 0, req);
+ if (error || !req->newptr)
+ return (error);
+ /*
+ * Permit update only if the new securelevel exceeds the
+ * global level, and local level if any.
+ */
+ if (pr != NULL) {
+ mtx_lock(&pr->pr_mtx);
+ if (!regression_securelevel_nonmonotonic &&
+ (level < imax(securelevel, pr->pr_securelevel))) {
+ mtx_unlock(&pr->pr_mtx);
+ return (EPERM);
+ }
+ pr->pr_securelevel = level;
+ mtx_unlock(&pr->pr_mtx);
+ } else {
+ mtx_lock(&securelevel_mtx);
+ if (!regression_securelevel_nonmonotonic &&
+ (level < securelevel)) {
+ mtx_unlock(&securelevel_mtx);
+ return (EPERM);
+ }
+ securelevel = level;
+ mtx_unlock(&securelevel_mtx);
+ }
+ return (error);
+}
+
+SYSCTL_PROC(_kern, KERN_SECURELVL, securelevel,
+ CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_PRISON, 0, 0, sysctl_kern_securelvl,
+ "I", "Current secure level");
+
+char domainname[MAXHOSTNAMELEN];
+SYSCTL_STRING(_kern, KERN_NISDOMAINNAME, domainname, CTLFLAG_RW,
+ &domainname, sizeof(domainname), "Name of the current YP/NIS domain");
+
+u_long hostid;
+SYSCTL_ULONG(_kern, KERN_HOSTID, hostid, CTLFLAG_RW, &hostid, 0, "Host ID");
+
+/*
+ * This is really cheating. These actually live in the libc, something
+ * which I'm not quite sure is a good idea anyway, but in order for
+ * getnext and friends to actually work, we define dummies here.
+ */
+SYSCTL_STRING(_user, USER_CS_PATH, cs_path, CTLFLAG_RD,
+ "", 0, "PATH that finds all the standard utilities");
+SYSCTL_INT(_user, USER_BC_BASE_MAX, bc_base_max, CTLFLAG_RD,
+ 0, 0, "Max ibase/obase values in bc(1)");
+SYSCTL_INT(_user, USER_BC_DIM_MAX, bc_dim_max, CTLFLAG_RD,
+ 0, 0, "Max array size in bc(1)");
+SYSCTL_INT(_user, USER_BC_SCALE_MAX, bc_scale_max, CTLFLAG_RD,
+ 0, 0, "Max scale value in bc(1)");
+SYSCTL_INT(_user, USER_BC_STRING_MAX, bc_string_max, CTLFLAG_RD,
+ 0, 0, "Max string length in bc(1)");
+SYSCTL_INT(_user, USER_COLL_WEIGHTS_MAX, coll_weights_max, CTLFLAG_RD,
+ 0, 0, "Maximum number of weights assigned to an LC_COLLATE locale entry");
+SYSCTL_INT(_user, USER_EXPR_NEST_MAX, expr_nest_max, CTLFLAG_RD, 0, 0, "");
+SYSCTL_INT(_user, USER_LINE_MAX, line_max, CTLFLAG_RD,
+ 0, 0, "Max length (bytes) of a text-processing utility's input line");
+SYSCTL_INT(_user, USER_RE_DUP_MAX, re_dup_max, CTLFLAG_RD,
+ 0, 0, "Maximum number of repeats of a regexp permitted");
+SYSCTL_INT(_user, USER_POSIX2_VERSION, posix2_version, CTLFLAG_RD,
+ 0, 0,
+ "The version of POSIX 1003.2 with which the system attempts to comply");
+SYSCTL_INT(_user, USER_POSIX2_C_BIND, posix2_c_bind, CTLFLAG_RD,
+ 0, 0, "Whether C development supports the C bindings option");
+SYSCTL_INT(_user, USER_POSIX2_C_DEV, posix2_c_dev, CTLFLAG_RD,
+ 0, 0, "Whether system supports the C development utilities option");
+SYSCTL_INT(_user, USER_POSIX2_CHAR_TERM, posix2_char_term, CTLFLAG_RD,
+ 0, 0, "");
+SYSCTL_INT(_user, USER_POSIX2_FORT_DEV, posix2_fort_dev, CTLFLAG_RD,
+ 0, 0, "Whether system supports FORTRAN development utilities");
+SYSCTL_INT(_user, USER_POSIX2_FORT_RUN, posix2_fort_run, CTLFLAG_RD,
+ 0, 0, "Whether system supports FORTRAN runtime utilities");
+SYSCTL_INT(_user, USER_POSIX2_LOCALEDEF, posix2_localedef, CTLFLAG_RD,
+ 0, 0, "Whether system supports creation of locales");
+SYSCTL_INT(_user, USER_POSIX2_SW_DEV, posix2_sw_dev, CTLFLAG_RD,
+ 0, 0, "Whether system supports software development utilities");
+SYSCTL_INT(_user, USER_POSIX2_UPE, posix2_upe, CTLFLAG_RD,
+ 0, 0, "Whether system supports the user portability utilities");
+SYSCTL_INT(_user, USER_STREAM_MAX, stream_max, CTLFLAG_RD,
+ 0, 0, "Min Maximum number of streams a process may have open at one time");
+SYSCTL_INT(_user, USER_TZNAME_MAX, tzname_max, CTLFLAG_RD,
+ 0, 0, "Min Maximum number of types supported for timezone names");
+
+#include <sys/vnode.h>
+SYSCTL_INT(_debug_sizeof, OID_AUTO, vnode, CTLFLAG_RD,
+ 0, sizeof(struct vnode), "sizeof(struct vnode)");
+
+SYSCTL_INT(_debug_sizeof, OID_AUTO, proc, CTLFLAG_RD,
+ 0, sizeof(struct proc), "sizeof(struct proc)");
+
+#include <sys/conf.h>
+SYSCTL_INT(_debug_sizeof, OID_AUTO, cdev, CTLFLAG_RD,
+ 0, sizeof(struct cdev), "sizeof(struct cdev)");
+
+#include <sys/bio.h>
+#include <sys/buf.h>
+SYSCTL_INT(_debug_sizeof, OID_AUTO, bio, CTLFLAG_RD,
+ 0, sizeof(struct bio), "sizeof(struct bio)");
+SYSCTL_INT(_debug_sizeof, OID_AUTO, buf, CTLFLAG_RD,
+ 0, sizeof(struct buf), "sizeof(struct buf)");
+
+#include <sys/user.h>
+SYSCTL_INT(_debug_sizeof, OID_AUTO, kinfo_proc, CTLFLAG_RD,
+ 0, sizeof(struct kinfo_proc), "sizeof(struct kinfo_proc)");
+
+#endif /* __rtems__ */
diff --git a/cpukit/libnetworking/kern/kern_subr.c b/cpukit/libnetworking/kern/kern_subr.c
new file mode 100644
index 0000000000..71e51fc442
--- /dev/null
+++ b/cpukit/libnetworking/kern/kern_subr.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 1982, 1986, 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)kern_subr.c 8.3 (Berkeley) 1/21/94
+ * $Id$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#include <sys/queue.h>
+
+int
+uiomove(cp, n, uio)
+ register caddr_t cp;
+ register int n;
+ register struct uio *uio;
+{
+ register struct iovec *iov;
+ u_int cnt;
+ int error;
+
+#ifdef DIAGNOSTIC
+ if (uio->uio_rw != UIO_READ && uio->uio_rw != UIO_WRITE)
+ panic("uiomove: mode");
+#endif
+ while (n > 0 && uio->uio_resid) {
+ iov = uio->uio_iov;
+ cnt = iov->iov_len;
+ if (cnt == 0) {
+ uio->uio_iov++;
+ uio->uio_iovcnt--;
+ continue;
+ }
+ if (cnt > n)
+ cnt = n;
+
+ switch (uio->uio_segflg) {
+
+ case UIO_USERSPACE:
+ case UIO_USERISPACE:
+ if (uio->uio_rw == UIO_READ)
+ error = copyout(cp, iov->iov_base, cnt);
+ else
+ error = copyin(iov->iov_base, cp, cnt);
+ if (error)
+ return (error);
+ break;
+
+ case UIO_SYSSPACE:
+ if (uio->uio_rw == UIO_READ)
+ bcopy((caddr_t)cp, iov->iov_base, cnt);
+ else
+ bcopy(iov->iov_base, (caddr_t)cp, cnt);
+ break;
+ case UIO_NOCOPY:
+ break;
+ }
+ iov->iov_base += cnt;
+ iov->iov_len -= cnt;
+ uio->uio_resid -= cnt;
+ uio->uio_offset += cnt;
+ cp += cnt;
+ n -= cnt;
+ }
+ return (0);
+}
+
+#ifdef vax /* unused except by ct.c, other oddities XXX */
+/*
+ * Get next character written in by user from uio.
+ */
+int
+uwritec(uio)
+ struct uio *uio;
+{
+ register struct iovec *iov;
+ register int c;
+
+ if (uio->uio_resid <= 0)
+ return (-1);
+again:
+ if (uio->uio_iovcnt <= 0)
+ panic("uwritec");
+ iov = uio->uio_iov;
+ if (iov->iov_len == 0) {
+ uio->uio_iov++;
+ if (--uio->uio_iovcnt == 0)
+ return (-1);
+ goto again;
+ }
+ switch (uio->uio_segflg) {
+
+ case UIO_USERSPACE:
+ c = fubyte(iov->iov_base);
+ break;
+
+ case UIO_SYSSPACE:
+ c = *(u_char *) iov->iov_base;
+ break;
+
+ case UIO_USERISPACE:
+ c = fuibyte(iov->iov_base);
+ break;
+ }
+ if (c < 0)
+ return (-1);
+ iov->iov_base++;
+ iov->iov_len--;
+ uio->uio_resid--;
+ uio->uio_offset++;
+ return (c);
+}
+#endif /* vax */
+
+/*
+ * General routine to allocate a hash table.
+ */
+void *
+hashinit(elements, type, hashmask)
+ int elements, type;
+ u_long *hashmask;
+{
+ long hashsize;
+ LIST_HEAD(generic, generic) *hashtbl;
+ int i;
+
+ if (elements <= 0)
+ panic("hashinit: bad elements");
+ for (hashsize = 1; hashsize <= elements; hashsize <<= 1)
+ continue;
+ hashsize >>= 1;
+ hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, M_WAITOK);
+ for (i = 0; i < hashsize; i++)
+ LIST_INIT(&hashtbl[i]);
+ *hashmask = hashsize - 1;
+ return (hashtbl);
+}
+
+#define NPRIMES 27
+static int primes[] = { 1, 13, 31, 61, 127, 251, 509, 761, 1021, 1531, 2039,
+ 2557, 3067, 3583, 4093, 4603, 5119, 5623, 6143, 6653,
+ 7159, 7673, 8191, 12281, 16381, 24571, 32749 };
+
+/*
+ * General routine to allocate a prime number sized hash table.
+ */
+void *
+phashinit(elements, type, nentries)
+ int elements, type;
+ u_long *nentries;
+{
+ long hashsize;
+ LIST_HEAD(generic, generic) *hashtbl;
+ int i;
+
+ if (elements <= 0)
+ panic("phashinit: bad elements");
+ for (i = 1, hashsize = primes[1]; hashsize <= elements;) {
+ i++;
+ if (i == NPRIMES)
+ break;
+ hashsize = primes[i];
+ }
+ hashsize = primes[i - 1];
+ hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, M_WAITOK);
+ for (i = 0; i < hashsize; i++)
+ LIST_INIT(&hashtbl[i]);
+ *nentries = hashsize;
+ return (hashtbl);
+}
diff --git a/cpukit/libnetworking/kern/kern_sysctl.c b/cpukit/libnetworking/kern/kern_sysctl.c
new file mode 100644
index 0000000000..effb0fa271
--- /dev/null
+++ b/cpukit/libnetworking/kern/kern_sysctl.c
@@ -0,0 +1,1543 @@
+/*-
+ * Copyright (c) 1982, 1986, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Karels at Berkeley Software Design, Inc.
+ *
+ * Quite extensively rewritten by Poul-Henning Kamp of the FreeBSD
+ * project, to make these variables more userfriendly.
+ *
+ * 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94
+ * $FreeBSD: src/sys/kern/kern_sysctl.c,v 1.135 2002/10/27 07:12:34 rwatson Exp $
+ */
+
+#ifndef __rtems__
+#include "opt_compat.h"
+#include "opt_mac.h"
+#endif
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#ifndef __rtems__
+#include <sys/mac.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/sx.h>
+#include <sys/sysproto.h>
+#else
+#include <sys/buf.h>
+
+#include <stdio.h> /* for snprintf() */
+size_t strlcpy(char *, const char *, size_t);
+#endif
+#include <vm/vm.h>
+#include <vm/vm_extern.h>
+
+#ifndef __rtems__
+static MALLOC_DEFINE(M_SYSCTL, "sysctl", "sysctl internal magic");
+static MALLOC_DEFINE(M_SYSCTLOID, "sysctloid", "sysctl dynamic oids");
+static MALLOC_DEFINE(M_SYSCTLTMP, "sysctltmp", "sysctl temp output buffer");
+#else
+/*
+ * Currently these mean nothing on RTEMS.
+ */
+#define M_SYSCTLOID 1
+#define M_SYSCTLTMP 2
+#define M_ZERO 0
+
+typedef unsigned long *uintptr_t;
+
+#define mtx_lock(l)
+#define mtx_unlock(l)
+
+#endif
+
+#ifndef __rtems__
+/*
+ * Locking - this locks the sysctl tree in memory.
+ */
+static struct sx sysctllock;
+#endif
+
+#ifdef __rtems__
+#define SYSCTL_LOCK()
+#define SYSCTL_UNLOCK()
+#define SYSCTL_INIT()
+#else
+#define SYSCTL_LOCK() sx_xlock(&sysctllock)
+#define SYSCTL_UNLOCK() sx_xunlock(&sysctllock)
+#define SYSCTL_INIT() sx_init(&sysctllock, "sysctl lock")
+#endif
+
+static int sysctl_root(SYSCTL_HANDLER_ARGS);
+
+struct sysctl_oid_list sysctl__children; /* root list */
+
+static struct sysctl_oid *
+sysctl_find_oidname(const char *name, struct sysctl_oid_list *list)
+{
+ struct sysctl_oid *oidp;
+
+ SLIST_FOREACH(oidp, list, oid_link) {
+ if (strcmp(oidp->oid_name, name) == 0) {
+ return (oidp);
+ }
+ }
+ return (NULL);
+}
+
+/*
+ * Initialization of the MIB tree.
+ *
+ * Order by number in each list.
+ */
+
+void
+sysctl_register_oid(struct sysctl_oid *oidp)
+{
+ struct sysctl_oid_list *parent = oidp->oid_parent;
+ struct sysctl_oid *p;
+ struct sysctl_oid *q;
+
+ /*
+ * First check if another oid with the same name already
+ * exists in the parent's list.
+ */
+ p = sysctl_find_oidname(oidp->oid_name, parent);
+ if (p != NULL) {
+ if ((p->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
+ p->oid_refcnt++;
+ return;
+ } else {
+ printf("can't re-use a leaf (%s)!\n", p->oid_name);
+ return;
+ }
+ }
+ /*
+ * If this oid has a number OID_AUTO, give it a number which
+ * is greater than any current oid.
+ * NOTE: DO NOT change the starting value here, change it in
+ * <sys/sysctl.h>, and make sure it is at least 256 to
+ * accomodate e.g. net.inet.raw as a static sysctl node.
+ */
+ if (oidp->oid_number == OID_AUTO) {
+ static int newoid = CTL_AUTO_START;
+
+ oidp->oid_number = newoid++;
+ if (newoid == 0x7fffffff)
+ panic("out of oids");
+ }
+#if 0
+ else if (oidp->oid_number >= CTL_AUTO_START) {
+ /* do not panic; this happens when unregistering sysctl sets */
+ printf("static sysctl oid too high: %d", oidp->oid_number);
+ }
+#endif
+
+ /*
+ * Insert the oid into the parent's list in order.
+ */
+ q = NULL;
+ SLIST_FOREACH(p, parent, oid_link) {
+ if (oidp->oid_number < p->oid_number)
+ break;
+ q = p;
+ }
+ if (q)
+ SLIST_INSERT_AFTER(q, oidp, oid_link);
+ else
+ SLIST_INSERT_HEAD(parent, oidp, oid_link);
+}
+
+void
+sysctl_unregister_oid(struct sysctl_oid *oidp)
+{
+ SLIST_REMOVE(oidp->oid_parent, oidp, sysctl_oid, oid_link);
+}
+
+/* Initialize a new context to keep track of dynamically added sysctls. */
+int
+sysctl_ctx_init(struct sysctl_ctx_list *c)
+{
+
+ if (c == NULL) {
+ return (EINVAL);
+ }
+ TAILQ_INIT(c);
+ return (0);
+}
+
+/* Free the context, and destroy all dynamic oids registered in this context */
+int
+sysctl_ctx_free(struct sysctl_ctx_list *clist)
+{
+ struct sysctl_ctx_entry *e, *e1;
+ int error;
+
+ error = 0;
+ /*
+ * First perform a "dry run" to check if it's ok to remove oids.
+ * XXX FIXME
+ * XXX This algorithm is a hack. But I don't know any
+ * XXX better solution for now...
+ */
+ TAILQ_FOREACH(e, clist, link) {
+ error = sysctl_remove_oid(e->entry, 0, 0);
+ if (error)
+ break;
+ }
+ /*
+ * Restore deregistered entries, either from the end,
+ * or from the place where error occured.
+ * e contains the entry that was not unregistered
+ */
+ if (error)
+ e1 = TAILQ_PREV(e, sysctl_ctx_list, link);
+ else
+ e1 = TAILQ_LAST(clist, sysctl_ctx_list);
+ while (e1 != NULL) {
+ sysctl_register_oid(e1->entry);
+ e1 = TAILQ_PREV(e1, sysctl_ctx_list, link);
+ }
+ if (error)
+ return(EBUSY);
+ /* Now really delete the entries */
+ e = TAILQ_FIRST(clist);
+ while (e != NULL) {
+ e1 = TAILQ_NEXT(e, link);
+ error = sysctl_remove_oid(e->entry, 1, 0);
+ if (error)
+ panic("sysctl_remove_oid: corrupt tree, entry: %s",
+ e->entry->oid_name);
+ free(e, M_SYSCTLOID);
+ e = e1;
+ }
+ return (error);
+}
+
+/* Add an entry to the context */
+struct sysctl_ctx_entry *
+sysctl_ctx_entry_add(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp)
+{
+ struct sysctl_ctx_entry *e;
+
+ if (clist == NULL || oidp == NULL)
+ return(NULL);
+ e = malloc(sizeof(struct sysctl_ctx_entry), M_SYSCTLOID, M_WAITOK);
+ e->entry = oidp;
+ TAILQ_INSERT_HEAD(clist, e, link);
+ return (e);
+}
+
+/* Find an entry in the context */
+struct sysctl_ctx_entry *
+sysctl_ctx_entry_find(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp)
+{
+ struct sysctl_ctx_entry *e;
+
+ if (clist == NULL || oidp == NULL)
+ return(NULL);
+ TAILQ_FOREACH(e, clist, link) {
+ if(e->entry == oidp)
+ return(e);
+ }
+ return (e);
+}
+
+/*
+ * Delete an entry from the context.
+ * NOTE: this function doesn't free oidp! You have to remove it
+ * with sysctl_remove_oid().
+ */
+int
+sysctl_ctx_entry_del(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp)
+{
+ struct sysctl_ctx_entry *e;
+
+ if (clist == NULL || oidp == NULL)
+ return (EINVAL);
+ e = sysctl_ctx_entry_find(clist, oidp);
+ if (e != NULL) {
+ TAILQ_REMOVE(clist, e, link);
+ free(e, M_SYSCTLOID);
+ return (0);
+ } else
+ return (ENOENT);
+}
+
+/*
+ * Remove dynamically created sysctl trees.
+ * oidp - top of the tree to be removed
+ * del - if 0 - just deregister, otherwise free up entries as well
+ * recurse - if != 0 traverse the subtree to be deleted
+ */
+int
+sysctl_remove_oid(struct sysctl_oid *oidp, int del, int recurse)
+{
+ struct sysctl_oid *p;
+ int error;
+
+ if (oidp == NULL)
+ return(EINVAL);
+ if ((oidp->oid_kind & CTLFLAG_DYN) == 0) {
+ printf("can't remove non-dynamic nodes!\n");
+ return (EINVAL);
+ }
+ /*
+ * WARNING: normal method to do this should be through
+ * sysctl_ctx_free(). Use recursing as the last resort
+ * method to purge your sysctl tree of leftovers...
+ * However, if some other code still references these nodes,
+ * it will panic.
+ */
+ if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
+ if (oidp->oid_refcnt == 1) {
+ SLIST_FOREACH(p, SYSCTL_CHILDREN(oidp), oid_link) {
+ if (!recurse)
+ return (ENOTEMPTY);
+ error = sysctl_remove_oid(p, del, recurse);
+ if (error)
+ return (error);
+ }
+ if (del)
+ free(SYSCTL_CHILDREN(oidp), M_SYSCTLOID);
+ }
+ }
+ if (oidp->oid_refcnt > 1 ) {
+ oidp->oid_refcnt--;
+ } else {
+ if (oidp->oid_refcnt == 0) {
+ printf("Warning: bad oid_refcnt=%u (%s)!\n",
+ oidp->oid_refcnt, oidp->oid_name);
+ return (EINVAL);
+ }
+ sysctl_unregister_oid(oidp);
+ if (del) {
+ if (oidp->descr)
+ free((void *)(uintptr_t)(const void *)oidp->descr, M_SYSCTLOID);
+ free((void *)(uintptr_t)(const void *)oidp->oid_name,
+ M_SYSCTLOID);
+ free(oidp, M_SYSCTLOID);
+ }
+ }
+ return (0);
+}
+
+/*
+ * Create new sysctls at run time.
+ * clist may point to a valid context initialized with sysctl_ctx_init().
+ */
+struct sysctl_oid *
+sysctl_add_oid(struct sysctl_ctx_list *clist, struct sysctl_oid_list *parent,
+ int number, const char *name, int kind, void *arg1, int arg2,
+ int (*handler)(SYSCTL_HANDLER_ARGS), const char *fmt, const char *descr)
+{
+ struct sysctl_oid *oidp;
+ ssize_t len;
+ char *newname;
+
+ /* You have to hook up somewhere.. */
+ if (parent == NULL)
+ return(NULL);
+ /* Check if the node already exists, otherwise create it */
+ oidp = sysctl_find_oidname(name, parent);
+ if (oidp != NULL) {
+ if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
+ oidp->oid_refcnt++;
+ /* Update the context */
+ if (clist != NULL)
+ sysctl_ctx_entry_add(clist, oidp);
+ return (oidp);
+ } else {
+ printf("can't re-use a leaf (%s)!\n", name);
+ return (NULL);
+ }
+ }
+ oidp = malloc(sizeof(struct sysctl_oid), M_SYSCTLOID, M_WAITOK|M_ZERO);
+ oidp->oid_parent = parent;
+ SLIST_NEXT(oidp, oid_link) = NULL;
+ oidp->oid_number = number;
+ oidp->oid_refcnt = 1;
+ len = strlen(name);
+ newname = malloc(len + 1, M_SYSCTLOID, M_WAITOK);
+ bcopy(name, newname, len + 1);
+ newname[len] = '\0';
+ oidp->oid_name = newname;
+ oidp->oid_handler = handler;
+ oidp->oid_kind = CTLFLAG_DYN | kind;
+ if ((kind & CTLTYPE) == CTLTYPE_NODE) {
+ /* Allocate space for children */
+ SYSCTL_CHILDREN(oidp) = malloc(sizeof(struct sysctl_oid_list),
+ M_SYSCTLOID, M_WAITOK);
+ SLIST_INIT(SYSCTL_CHILDREN(oidp));
+ } else {
+ oidp->oid_arg1 = arg1;
+ oidp->oid_arg2 = arg2;
+ }
+ oidp->oid_fmt = fmt;
+ if (descr) {
+ int len = strlen(descr) + 1;
+ oidp->descr = malloc(len, M_SYSCTLOID, M_WAITOK);
+ if (oidp->descr)
+ strcpy((char *)(uintptr_t)(const void *)oidp->descr, descr);
+ }
+ /* Update the context, if used */
+ if (clist != NULL)
+ sysctl_ctx_entry_add(clist, oidp);
+ /* Register this oid */
+ sysctl_register_oid(oidp);
+ return (oidp);
+}
+
+/*
+ * Register the kernel's oids on startup.
+ */
+SET_DECLARE(sysctl_set, struct sysctl_oid);
+
+#if defined(__rtems__)
+void
+#else
+static void
+#endif
+sysctl_register_all(void *arg)
+{
+ struct sysctl_oid **oidp;
+
+ SYSCTL_INIT();
+ SET_FOREACH(oidp, sysctl_set)
+ sysctl_register_oid(*oidp);
+}
+SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_ANY, sysctl_register_all, 0);
+
+/*
+ * "Staff-functions"
+ *
+ * These functions implement a presently undocumented interface
+ * used by the sysctl program to walk the tree, and get the type
+ * so it can print the value.
+ * This interface is under work and consideration, and should probably
+ * be killed with a big axe by the first person who can find the time.
+ * (be aware though, that the proper interface isn't as obvious as it
+ * may seem, there are various conflicting requirements.
+ *
+ * {0,0} printf the entire MIB-tree.
+ * {0,1,...} return the name of the "..." OID.
+ * {0,2,...} return the next OID.
+ * {0,3} return the OID of the name in "new"
+ * {0,4,...} return the kind & format info for the "..." OID.
+ * {0,5,...} return the description the "..." OID.
+ */
+
+static void
+sysctl_sysctl_debug_dump_node(struct sysctl_oid_list *l, int i)
+{
+ int k;
+ struct sysctl_oid *oidp;
+
+ SLIST_FOREACH(oidp, l, oid_link) {
+
+ for (k=0; k<i; k++)
+ printf(" ");
+
+ printf("%d %s ", oidp->oid_number, oidp->oid_name);
+
+ printf("%c%c",
+ oidp->oid_kind & CTLFLAG_RD ? 'R':' ',
+ oidp->oid_kind & CTLFLAG_WR ? 'W':' ');
+
+ if (oidp->oid_handler)
+ printf(" *Handler");
+
+ switch (oidp->oid_kind & CTLTYPE) {
+ case CTLTYPE_NODE:
+ printf(" Node\n");
+ if (!oidp->oid_handler) {
+ sysctl_sysctl_debug_dump_node(
+ oidp->oid_arg1, i+2);
+ }
+ break;
+ case CTLTYPE_INT: printf(" Int\n"); break;
+ case CTLTYPE_STRING: printf(" String\n"); break;
+ case CTLTYPE_QUAD: printf(" Quad\n"); break;
+ case CTLTYPE_OPAQUE: printf(" Opaque/struct\n"); break;
+ default: printf("\n");
+ }
+
+ }
+}
+
+static int
+sysctl_sysctl_debug(SYSCTL_HANDLER_ARGS)
+{
+#ifndef __rtems__
+ int error;
+
+ error = suser(req->td);
+ if (error)
+ return error;
+#endif
+ sysctl_sysctl_debug_dump_node(&sysctl__children, 0);
+ return ENOENT;
+}
+
+SYSCTL_PROC(_sysctl, 0, debug, CTLTYPE_STRING|CTLFLAG_RD,
+ 0, 0, sysctl_sysctl_debug, "-", "");
+
+static int
+sysctl_sysctl_name(SYSCTL_HANDLER_ARGS)
+{
+ int *name = (int *) arg1;
+ u_int namelen = arg2;
+ int error = 0;
+ struct sysctl_oid *oid;
+ struct sysctl_oid_list *lsp = &sysctl__children, *lsp2;
+ char buf[10];
+
+ while (namelen) {
+ if (!lsp) {
+ snprintf(buf,sizeof(buf),"%d",*name);
+ if (req->oldidx)
+ error = SYSCTL_OUT(req, ".", 1);
+ if (!error)
+ error = SYSCTL_OUT(req, buf, strlen(buf));
+ if (error)
+ return (error);
+ namelen--;
+ name++;
+ continue;
+ }
+ lsp2 = 0;
+ SLIST_FOREACH(oid, lsp, oid_link) {
+ if (oid->oid_number != *name)
+ continue;
+
+ if (req->oldidx)
+ error = SYSCTL_OUT(req, ".", 1);
+ if (!error)
+ error = SYSCTL_OUT(req, oid->oid_name,
+ strlen(oid->oid_name));
+ if (error)
+ return (error);
+
+ namelen--;
+ name++;
+
+ if ((oid->oid_kind & CTLTYPE) != CTLTYPE_NODE)
+ break;
+
+ if (oid->oid_handler)
+ break;
+
+ lsp2 = (struct sysctl_oid_list *)oid->oid_arg1;
+ break;
+ }
+ lsp = lsp2;
+ }
+ return (SYSCTL_OUT(req, "", 1));
+}
+
+SYSCTL_NODE(_sysctl, 1, name, CTLFLAG_RD, sysctl_sysctl_name, "");
+
+static int
+sysctl_sysctl_next_ls(struct sysctl_oid_list *lsp, int *name, u_int namelen,
+ int *next, int *len, int level, struct sysctl_oid **oidpp)
+{
+ struct sysctl_oid *oidp;
+
+ *len = level;
+ SLIST_FOREACH(oidp, lsp, oid_link) {
+ *next = oidp->oid_number;
+ *oidpp = oidp;
+
+ if (oidp->oid_kind & CTLFLAG_SKIP)
+ continue;
+
+ if (!namelen) {
+ if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)
+ return 0;
+ if (oidp->oid_handler)
+ /* We really should call the handler here...*/
+ return 0;
+ lsp = (struct sysctl_oid_list *)oidp->oid_arg1;
+ if (!sysctl_sysctl_next_ls(lsp, 0, 0, next+1,
+ len, level+1, oidpp))
+ return 0;
+ goto emptynode;
+ }
+
+ if (oidp->oid_number < *name)
+ continue;
+
+ if (oidp->oid_number > *name) {
+ if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)
+ return 0;
+ if (oidp->oid_handler)
+ return 0;
+ lsp = (struct sysctl_oid_list *)oidp->oid_arg1;
+ if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1,
+ next+1, len, level+1, oidpp))
+ return (0);
+ goto next;
+ }
+ if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)
+ continue;
+
+ if (oidp->oid_handler)
+ continue;
+
+ lsp = (struct sysctl_oid_list *)oidp->oid_arg1;
+ if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1, next+1,
+ len, level+1, oidpp))
+ return (0);
+ next:
+ namelen = 1;
+ emptynode:
+ *len = level;
+ }
+ return 1;
+}
+
+static int
+sysctl_sysctl_next(SYSCTL_HANDLER_ARGS)
+{
+ int *name = (int *) arg1;
+ u_int namelen = arg2;
+ int i, j, error;
+ struct sysctl_oid *oid;
+ struct sysctl_oid_list *lsp = &sysctl__children;
+ int newoid[CTL_MAXNAME];
+
+ i = sysctl_sysctl_next_ls(lsp, name, namelen, newoid, &j, 1, &oid);
+ if (i)
+ return ENOENT;
+ error = SYSCTL_OUT(req, newoid, j * sizeof (int));
+ return (error);
+}
+
+SYSCTL_NODE(_sysctl, 2, next, CTLFLAG_RD, sysctl_sysctl_next, "");
+
+static int
+name2oid (char *name, int *oid, int *len, struct sysctl_oid **oidpp)
+{
+ int i;
+ struct sysctl_oid *oidp;
+ struct sysctl_oid_list *lsp = &sysctl__children;
+ char *p;
+
+ if (!*name)
+ return ENOENT;
+
+ p = name + strlen(name) - 1 ;
+ if (*p == '.')
+ *p = '\0';
+
+ *len = 0;
+
+ for (p = name; *p && *p != '.'; p++)
+ ;
+ i = *p;
+ if (i == '.')
+ *p = '\0';
+
+ oidp = SLIST_FIRST(lsp);
+
+ while (oidp && *len < CTL_MAXNAME) {
+ if (strcmp(name, oidp->oid_name)) {
+ oidp = SLIST_NEXT(oidp, oid_link);
+ continue;
+ }
+ *oid++ = oidp->oid_number;
+ (*len)++;
+
+ if (!i) {
+ if (oidpp)
+ *oidpp = oidp;
+ return (0);
+ }
+
+ if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)
+ break;
+
+ if (oidp->oid_handler)
+ break;
+
+ lsp = (struct sysctl_oid_list *)oidp->oid_arg1;
+ oidp = SLIST_FIRST(lsp);
+ name = p+1;
+ for (p = name; *p && *p != '.'; p++)
+ ;
+ i = *p;
+ if (i == '.')
+ *p = '\0';
+ }
+ return ENOENT;
+}
+
+static int
+sysctl_sysctl_name2oid(SYSCTL_HANDLER_ARGS)
+{
+ char *p;
+ int error, oid[CTL_MAXNAME], len;
+ struct sysctl_oid *op = 0;
+
+ if (!req->newlen)
+ return ENOENT;
+ if (req->newlen >= MAXPATHLEN) /* XXX arbitrary, undocumented */
+ return (ENAMETOOLONG);
+
+ p = malloc(req->newlen+1, M_SYSCTL, M_WAITOK);
+
+ error = SYSCTL_IN(req, p, req->newlen);
+ if (error) {
+ free(p, M_SYSCTL);
+ return (error);
+ }
+
+ p [req->newlen] = '\0';
+
+ error = name2oid(p, oid, &len, &op);
+
+ free(p, M_SYSCTL);
+
+ if (error)
+ return (error);
+
+ error = SYSCTL_OUT(req, oid, len * sizeof *oid);
+ return (error);
+}
+
+SYSCTL_PROC(_sysctl, 3, name2oid, CTLFLAG_RW|CTLFLAG_ANYBODY, 0, 0,
+ sysctl_sysctl_name2oid, "I", "");
+
+static int
+sysctl_sysctl_oidfmt(SYSCTL_HANDLER_ARGS)
+{
+ struct sysctl_oid *oid;
+ int error;
+
+ error = sysctl_find_oid(arg1, arg2, &oid, NULL, req);
+ if (error)
+ return (error);
+
+ if (!oid->oid_fmt)
+ return (ENOENT);
+ error = SYSCTL_OUT(req, &oid->oid_kind, sizeof(oid->oid_kind));
+ if (error)
+ return (error);
+ error = SYSCTL_OUT(req, oid->oid_fmt, strlen(oid->oid_fmt) + 1);
+ return (error);
+}
+
+
+SYSCTL_NODE(_sysctl, 4, oidfmt, CTLFLAG_RD, sysctl_sysctl_oidfmt, "");
+
+static int
+sysctl_sysctl_oiddescr(SYSCTL_HANDLER_ARGS)
+{
+ struct sysctl_oid *oid;
+ int error;
+
+ error = sysctl_find_oid(arg1, arg2, &oid, NULL, req);
+ if (error)
+ return (error);
+
+ if (!oid->descr)
+ return (ENOENT);
+ error = SYSCTL_OUT(req, oid->descr, strlen(oid->descr) + 1);
+ return (error);
+}
+
+SYSCTL_NODE(_sysctl, 5, oiddescr, CTLFLAG_RD, sysctl_sysctl_oiddescr, "");
+
+/*
+ * Default "handler" functions.
+ */
+
+/*
+ * Handle an int, signed or unsigned.
+ * Two cases:
+ * a variable: point arg1 at it.
+ * a constant: pass it in arg2.
+ */
+
+int
+sysctl_handle_int(SYSCTL_HANDLER_ARGS)
+{
+ int tmpout, error = 0;
+
+ /*
+ * Attempt to get a coherent snapshot by making a copy of the data.
+ */
+ if (arg1)
+ tmpout = *(int *)arg1;
+ else
+ tmpout = arg2;
+ error = SYSCTL_OUT(req, &tmpout, sizeof(int));
+
+ if (error || !req->newptr)
+ return (error);
+
+ if (!arg1)
+ error = EPERM;
+ else
+ error = SYSCTL_IN(req, arg1, sizeof(int));
+ return (error);
+}
+
+/*
+ * Handle a long, signed or unsigned. arg1 points to it.
+ */
+
+int
+sysctl_handle_long(SYSCTL_HANDLER_ARGS)
+{
+ int error = 0;
+ long tmpout;
+
+ /*
+ * Attempt to get a coherent snapshot by making a copy of the data.
+ */
+ if (!arg1)
+ return (EINVAL);
+ tmpout = *(long *)arg1;
+ error = SYSCTL_OUT(req, &tmpout, sizeof(long));
+
+ if (error || !req->newptr)
+ return (error);
+
+ error = SYSCTL_IN(req, arg1, sizeof(long));
+ return (error);
+}
+
+/*
+ * Handle our generic '\0' terminated 'C' string.
+ * Two cases:
+ * a variable string: point arg1 at it, arg2 is max length.
+ * a constant string: point arg1 at it, arg2 is zero.
+ */
+
+int
+sysctl_handle_string(SYSCTL_HANDLER_ARGS)
+{
+ int error=0;
+ char *tmparg;
+ size_t outlen;
+
+ /*
+ * Attempt to get a coherent snapshot by copying to a
+ * temporary kernel buffer.
+ */
+retry:
+ outlen = strlen((char *)arg1)+1;
+ tmparg = malloc(outlen, M_SYSCTLTMP, M_WAITOK);
+
+ if (strlcpy(tmparg, (char *)arg1, outlen) >= outlen) {
+ free(tmparg, M_SYSCTLTMP);
+ goto retry;
+ }
+
+ error = SYSCTL_OUT(req, tmparg, outlen);
+ free(tmparg, M_SYSCTLTMP);
+
+ if (error || !req->newptr)
+ return (error);
+
+ if ((req->newlen - req->newidx) >= arg2) {
+ error = EINVAL;
+ } else {
+ arg2 = (req->newlen - req->newidx);
+ error = SYSCTL_IN(req, arg1, arg2);
+ ((char *)arg1)[arg2] = '\0';
+ }
+
+ return (error);
+}
+
+/*
+ * Handle any kind of opaque data.
+ * arg1 points to it, arg2 is the size.
+ */
+
+int
+sysctl_handle_opaque(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+ void *tmparg;
+
+ /*
+ * Attempt to get a coherent snapshot, either by wiring the
+ * user space buffer or copying to a temporary kernel buffer
+ * depending on the size of the data.
+ */
+ if (arg2 > PAGE_SIZE) {
+ sysctl_wire_old_buffer(req, arg2);
+ error = SYSCTL_OUT(req, arg1, arg2);
+ } else {
+ tmparg = malloc(arg2, M_SYSCTLTMP, M_WAITOK);
+ bcopy(arg1, tmparg, arg2);
+ error = SYSCTL_OUT(req, tmparg, arg2);
+ free(tmparg, M_SYSCTLTMP);
+ }
+
+ if (error || !req->newptr)
+ return (error);
+
+ error = SYSCTL_IN(req, arg1, arg2);
+
+ return (error);
+}
+
+/*
+ * Transfer functions to/from kernel space.
+ * XXX: rather untested at this point
+ */
+static int
+sysctl_old_kernel(struct sysctl_req *req, const void *p, size_t l)
+{
+ size_t i = 0;
+
+ if (req->oldptr) {
+ i = l;
+ if (req->oldlen <= req->oldidx)
+ i = 0;
+ else
+ if (i > req->oldlen - req->oldidx)
+ i = req->oldlen - req->oldidx;
+ if (i > 0)
+ bcopy(p, (char *)req->oldptr + req->oldidx, i);
+ }
+ req->oldidx += l;
+ if (req->oldptr && i != l)
+ return (ENOMEM);
+ return (0);
+}
+
+static int
+sysctl_new_kernel(struct sysctl_req *req, void *p, size_t l)
+{
+ if (!req->newptr)
+ return 0;
+ if (req->newlen - req->newidx < l)
+ return (EINVAL);
+ bcopy((char *)req->newptr + req->newidx, p, l);
+ req->newidx += l;
+ return (0);
+}
+
+int
+kernel_sysctl(struct thread *td, int *name, u_int namelen, void *old,
+ size_t *oldlenp, void *new, size_t newlen, size_t *retval)
+{
+ int error = 0;
+ struct sysctl_req req;
+
+ bzero(&req, sizeof req);
+
+ req.td = td;
+
+ if (oldlenp) {
+ req.oldlen = *oldlenp;
+ }
+
+ if (old) {
+ req.oldptr= old;
+ }
+
+ if (new != NULL) {
+ req.newlen = newlen;
+ req.newptr = new;
+ }
+
+ req.oldfunc = sysctl_old_kernel;
+ req.newfunc = sysctl_new_kernel;
+ req.lock = REQ_LOCKED;
+
+ SYSCTL_LOCK();
+
+ error = sysctl_root(0, name, namelen, &req);
+
+ if (req.lock == REQ_WIRED)
+#ifdef __rtems__
+ printf ("kern_sysctl: vsunlock needs to be called!\n");
+#else
+ vsunlock(req.oldptr, req.oldlen);
+#endif
+
+ SYSCTL_UNLOCK();
+
+ if (error && error != ENOMEM)
+ return (error);
+
+ if (retval) {
+ if (req.oldptr && req.oldidx > req.oldlen)
+ *retval = req.oldlen;
+ else
+ *retval = req.oldidx;
+ }
+ return (error);
+}
+
+int
+kernel_sysctlbyname(struct thread *td, char *name, void *old, size_t *oldlenp,
+ void *new, size_t newlen, size_t *retval)
+{
+ int oid[CTL_MAXNAME];
+ size_t oidlen, plen;
+ int error;
+
+ oid[0] = 0; /* sysctl internal magic */
+ oid[1] = 3; /* name2oid */
+ oidlen = sizeof(oid);
+
+ error = kernel_sysctl(td, oid, 2, oid, &oidlen,
+ (void *)name, strlen(name), &plen);
+ if (error)
+ return (error);
+
+ error = kernel_sysctl(td, oid, plen / sizeof(int), old, oldlenp,
+ new, newlen, retval);
+ return (error);
+}
+
+/*
+ * Transfer function to/from user space.
+ */
+static int
+sysctl_old_user(struct sysctl_req *req, const void *p, size_t l)
+{
+ int error = 0;
+ size_t i = 0;
+
+#ifndef __rtems__
+ if (req->lock == 1 && req->oldptr)
+ WITNESS_SLEEP(1, NULL);
+#endif
+ if (req->oldptr) {
+ i = l;
+ if (req->oldlen <= req->oldidx)
+ i = 0;
+ else
+ if (i > req->oldlen - req->oldidx)
+ i = req->oldlen - req->oldidx;
+ if (i > 0)
+ error = copyout(p, (char *)req->oldptr + req->oldidx,
+ i);
+ }
+ req->oldidx += l;
+ if (error)
+ return (error);
+ if (req->oldptr && i < l)
+ return (ENOMEM);
+ return (0);
+}
+
+static int
+sysctl_new_user(struct sysctl_req *req, void *p, size_t l)
+{
+ int error;
+
+ if (!req->newptr)
+ return 0;
+ if (req->newlen - req->newidx < l)
+ return (EINVAL);
+ error = copyin((char *)req->newptr + req->newidx, p, l);
+ req->newidx += l;
+ return (error);
+}
+
+/*
+ * Wire the user space destination buffer. If set to a value greater than
+ * zero, the len parameter limits the maximum amount of wired memory.
+ *
+ * XXX - The len parameter is currently ignored due to the lack of
+ * a place to save it in the sysctl_req structure so that the matching
+ * amount of memory can be unwired in the sysctl exit code.
+ */
+int
+sysctl_wire_old_buffer(struct sysctl_req *req, size_t len)
+{
+ if (req->lock == REQ_LOCKED && req->oldptr &&
+ req->oldfunc == sysctl_old_user) {
+#ifndef __rtems__
+ vslock(req->oldptr, req->oldlen);
+#endif
+ req->lock = REQ_WIRED;
+ }
+ return (0);
+}
+
+int
+sysctl_find_oid(int *name, u_int namelen, struct sysctl_oid **noid,
+ int *nindx, struct sysctl_req *req)
+{
+ struct sysctl_oid *oid;
+ int indx;
+
+ oid = SLIST_FIRST(&sysctl__children);
+ indx = 0;
+ while (oid && indx < CTL_MAXNAME) {
+ if (oid->oid_number == name[indx]) {
+ indx++;
+ if (oid->oid_kind & CTLFLAG_NOLOCK)
+ req->lock = REQ_UNLOCKED;
+ if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
+ if (oid->oid_handler != NULL ||
+ indx == namelen) {
+ *noid = oid;
+ if (nindx != NULL)
+ *nindx = indx;
+ return (0);
+ }
+ oid = SLIST_FIRST(
+ (struct sysctl_oid_list *)oid->oid_arg1);
+ } else if (indx == namelen) {
+ *noid = oid;
+ if (nindx != NULL)
+ *nindx = indx;
+ return (0);
+ } else {
+ return (ENOTDIR);
+ }
+ } else {
+ oid = SLIST_NEXT(oid, oid_link);
+ }
+ }
+ return (ENOENT);
+}
+
+/*
+ * Traverse our tree, and find the right node, execute whatever it points
+ * to, and return the resulting error code.
+ */
+
+static int
+sysctl_root(SYSCTL_HANDLER_ARGS)
+{
+ struct sysctl_oid *oid;
+ int error, indx;
+
+ error = sysctl_find_oid(arg1, arg2, &oid, &indx, req);
+ if (error)
+ return (error);
+
+ if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
+ /*
+ * You can't call a sysctl when it's a node, but has
+ * no handler. Inform the user that it's a node.
+ * The indx may or may not be the same as namelen.
+ */
+ if (oid->oid_handler == NULL)
+ return (EISDIR);
+ }
+
+ /* Is this sysctl writable? */
+ if (req->newptr && !(oid->oid_kind & CTLFLAG_WR))
+ return (EPERM);
+
+#ifndef __rtems__
+ KASSERT(req->td != NULL, ("sysctl_root(): req->td == NULL"));
+
+ /* Is this sysctl sensitive to securelevels? */
+ if (req->newptr && (oid->oid_kind & CTLFLAG_SECURE)) {
+ error = securelevel_gt(req->td->td_ucred, 0);
+ if (error)
+ return (error);
+ }
+
+ /* Is this sysctl writable by only privileged users? */
+ if (req->newptr && !(oid->oid_kind & CTLFLAG_ANYBODY)) {
+ int flags;
+
+ if (oid->oid_kind & CTLFLAG_PRISON)
+ flags = PRISON_ROOT;
+ else
+ flags = 0;
+ error = suser_cred(req->td->td_ucred, flags);
+ if (error)
+ return (error);
+ }
+#endif
+
+ if (!oid->oid_handler)
+ return EINVAL;
+
+ if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE)
+ error = oid->oid_handler(oid, (int *)arg1 + indx, arg2 - indx,
+ req);
+ else
+ error = oid->oid_handler(oid, oid->oid_arg1, oid->oid_arg2,
+ req);
+ return (error);
+}
+
+#ifndef _SYS_SYSPROTO_H_
+struct sysctl_args {
+ int *name;
+ u_int namelen;
+ void *old;
+ size_t *oldlenp;
+ void *new;
+ size_t newlen;
+};
+#endif
+
+/*
+ * MPSAFE
+ */
+int
+__sysctl(struct thread *td, struct sysctl_args *uap)
+{
+ int error, name[CTL_MAXNAME];
+ size_t j;
+
+ if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
+ return (EINVAL);
+
+ error = copyin(uap->name, &name, uap->namelen * sizeof(int));
+ if (error)
+ return (error);
+
+ mtx_lock(&Giant);
+
+ error = userland_sysctl(td, name, uap->namelen,
+ uap->old, uap->oldlenp, 0,
+ uap->new, uap->newlen, &j);
+ if (error && error != ENOMEM)
+ goto done2;
+ if (uap->oldlenp) {
+ int i = copyout(&j, uap->oldlenp, sizeof(j));
+ if (i)
+ error = i;
+ }
+done2:
+ mtx_unlock(&Giant);
+ return (error);
+}
+
+/*
+ * This is used from various compatibility syscalls too. That's why name
+ * must be in kernel space.
+ */
+int
+userland_sysctl(struct thread *td, int *name, u_int namelen, void *old,
+ size_t *oldlenp, int inkernel, void *new, size_t newlen, size_t *retval)
+{
+ int error = 0;
+ struct sysctl_req req, req2;
+
+ bzero(&req, sizeof req);
+
+ req.td = td;
+
+ if (oldlenp) {
+ if (inkernel) {
+ req.oldlen = *oldlenp;
+ } else {
+ error = copyin(oldlenp, &req.oldlen, sizeof(*oldlenp));
+ if (error)
+ return (error);
+ }
+ }
+
+ if (old) {
+#ifndef __rtems__
+ if (!useracc(old, req.oldlen, VM_PROT_WRITE))
+ return (EFAULT);
+#endif
+ req.oldptr= old;
+ }
+
+ if (new != NULL) {
+#ifndef __rtems__
+ if (!useracc(new, req.newlen, VM_PROT_READ))
+ return (EFAULT);
+#endif
+ req.newlen = newlen;
+ req.newptr = new;
+ }
+
+ req.oldfunc = sysctl_old_user;
+ req.newfunc = sysctl_new_user;
+ req.lock = REQ_LOCKED;
+
+ SYSCTL_LOCK();
+
+#ifdef MAC
+ error = mac_check_system_sysctl(td->td_ucred, name, namelen, old,
+ oldlenp, inkernel, new, newlen);
+ if (error) {
+ SYSCTL_UNLOCK();
+ return (error);
+ }
+#endif
+
+ do {
+ req2 = req;
+ error = sysctl_root(0, name, namelen, &req2);
+ } while (error == EAGAIN);
+
+ req = req2;
+#ifndef __rtems__
+ if (req.lock == REQ_WIRED)
+ vsunlock(req.oldptr, req.oldlen);
+#endif
+
+ SYSCTL_UNLOCK();
+
+ if (error && error != ENOMEM)
+ return (error);
+
+ if (retval) {
+ if (req.oldptr && req.oldidx > req.oldlen)
+ *retval = req.oldlen;
+ else
+ *retval = req.oldidx;
+ }
+ return (error);
+}
+
+#ifdef COMPAT_43
+#include <sys/socket.h>
+#include <vm/vm_param.h>
+
+#define KINFO_PROC (0<<8)
+#define KINFO_RT (1<<8)
+#define KINFO_VNODE (2<<8)
+#define KINFO_FILE (3<<8)
+#define KINFO_METER (4<<8)
+#define KINFO_LOADAVG (5<<8)
+#define KINFO_CLOCKRATE (6<<8)
+
+/* Non-standard BSDI extension - only present on their 4.3 net-2 releases */
+#define KINFO_BSDI_SYSINFO (101<<8)
+
+/*
+ * XXX this is bloat, but I hope it's better here than on the potentially
+ * limited kernel stack... -Peter
+ */
+
+static struct {
+ int bsdi_machine; /* "i386" on BSD/386 */
+/* ^^^ this is an offset to the string, relative to the struct start */
+ char *pad0;
+ long pad1;
+ long pad2;
+ long pad3;
+ u_long pad4;
+ u_long pad5;
+ u_long pad6;
+
+ int bsdi_ostype; /* "BSD/386" on BSD/386 */
+ int bsdi_osrelease; /* "1.1" on BSD/386 */
+ long pad7;
+ long pad8;
+ char *pad9;
+
+ long pad10;
+ long pad11;
+ int pad12;
+ long pad13;
+ quad_t pad14;
+ long pad15;
+
+ struct timeval pad16;
+ /* we dont set this, because BSDI's uname used gethostname() instead */
+ int bsdi_hostname; /* hostname on BSD/386 */
+
+ /* the actual string data is appended here */
+
+} bsdi_si;
+/*
+ * this data is appended to the end of the bsdi_si structure during copyout.
+ * The "char *" offsets are relative to the base of the bsdi_si struct.
+ * This contains "FreeBSD\02.0-BUILT-nnnnnn\0i386\0", and these strings
+ * should not exceed the length of the buffer here... (or else!! :-)
+ */
+static char bsdi_strings[80]; /* It had better be less than this! */
+
+#ifndef _SYS_SYSPROTO_H_
+struct getkerninfo_args {
+ int op;
+ char *where;
+ size_t *size;
+ int arg;
+};
+#endif
+
+/*
+ * MPSAFE
+ */
+int
+ogetkerninfo(struct thread *td, struct getkerninfo_args *uap)
+{
+ int error, name[6];
+ size_t size;
+ u_int needed = 0;
+
+ mtx_lock(&Giant);
+
+ switch (uap->op & 0xff00) {
+
+ case KINFO_RT:
+ name[0] = CTL_NET;
+ name[1] = PF_ROUTE;
+ name[2] = 0;
+ name[3] = (uap->op & 0xff0000) >> 16;
+ name[4] = uap->op & 0xff;
+ name[5] = uap->arg;
+ error = userland_sysctl(td, name, 6, uap->where, uap->size,
+ 0, 0, 0, &size);
+ break;
+
+ case KINFO_VNODE:
+ name[0] = CTL_KERN;
+ name[1] = KERN_VNODE;
+ error = userland_sysctl(td, name, 2, uap->where, uap->size,
+ 0, 0, 0, &size);
+ break;
+
+ case KINFO_PROC:
+ name[0] = CTL_KERN;
+ name[1] = KERN_PROC;
+ name[2] = uap->op & 0xff;
+ name[3] = uap->arg;
+ error = userland_sysctl(td, name, 4, uap->where, uap->size,
+ 0, 0, 0, &size);
+ break;
+
+ case KINFO_FILE:
+ name[0] = CTL_KERN;
+ name[1] = KERN_FILE;
+ error = userland_sysctl(td, name, 2, uap->where, uap->size,
+ 0, 0, 0, &size);
+ break;
+
+ case KINFO_METER:
+ name[0] = CTL_VM;
+ name[1] = VM_TOTAL;
+ error = userland_sysctl(td, name, 2, uap->where, uap->size,
+ 0, 0, 0, &size);
+ break;
+
+ case KINFO_LOADAVG:
+ name[0] = CTL_VM;
+ name[1] = VM_LOADAVG;
+ error = userland_sysctl(td, name, 2, uap->where, uap->size,
+ 0, 0, 0, &size);
+ break;
+
+ case KINFO_CLOCKRATE:
+ name[0] = CTL_KERN;
+ name[1] = KERN_CLOCKRATE;
+ error = userland_sysctl(td, name, 2, uap->where, uap->size,
+ 0, 0, 0, &size);
+ break;
+
+ case KINFO_BSDI_SYSINFO: {
+ /*
+ * this is pretty crude, but it's just enough for uname()
+ * from BSDI's 1.x libc to work.
+ *
+ * *size gives the size of the buffer before the call, and
+ * the amount of data copied after a successful call.
+ * If successful, the return value is the amount of data
+ * available, which can be larger than *size.
+ *
+ * BSDI's 2.x product apparently fails with ENOMEM if *size
+ * is too small.
+ */
+
+ u_int left;
+ char *s;
+
+ bzero((char *)&bsdi_si, sizeof(bsdi_si));
+ bzero(bsdi_strings, sizeof(bsdi_strings));
+
+ s = bsdi_strings;
+
+ bsdi_si.bsdi_ostype = (s - bsdi_strings) + sizeof(bsdi_si);
+ strcpy(s, ostype);
+ s += strlen(s) + 1;
+
+ bsdi_si.bsdi_osrelease = (s - bsdi_strings) + sizeof(bsdi_si);
+ strcpy(s, osrelease);
+ s += strlen(s) + 1;
+
+ bsdi_si.bsdi_machine = (s - bsdi_strings) + sizeof(bsdi_si);
+ strcpy(s, machine);
+ s += strlen(s) + 1;
+
+ needed = sizeof(bsdi_si) + (s - bsdi_strings);
+
+ if ((uap->where == NULL) || (uap->size == NULL)) {
+ /* process is asking how much buffer to supply.. */
+ size = needed;
+ error = 0;
+ break;
+ }
+
+ if ((error = copyin(uap->size, &size, sizeof(size))) != 0)
+ break;
+
+ /* if too much buffer supplied, trim it down */
+ if (size > needed)
+ size = needed;
+
+ /* how much of the buffer is remaining */
+ left = size;
+
+ if ((error = copyout((char *)&bsdi_si, uap->where, left)) != 0)
+ break;
+
+ /* is there any point in continuing? */
+ if (left > sizeof(bsdi_si)) {
+ left -= sizeof(bsdi_si);
+ error = copyout(&bsdi_strings,
+ uap->where + sizeof(bsdi_si), left);
+ }
+ break;
+ }
+
+ default:
+ error = EOPNOTSUPP;
+ break;
+ }
+ if (error == 0) {
+ td->td_retval[0] = needed ? needed : size;
+ if (uap->size) {
+ error = copyout(&size, uap->size, sizeof(size));
+ }
+ }
+ mtx_unlock(&Giant);
+ return (error);
+}
+#endif /* COMPAT_43 */
diff --git a/cpukit/libnetworking/kern/uipc_domain.c b/cpukit/libnetworking/kern/uipc_domain.c
new file mode 100644
index 0000000000..81d741fe37
--- /dev/null
+++ b/cpukit/libnetworking/kern/uipc_domain.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)uipc_domain.c 8.2 (Berkeley) 10/18/93
+ * $Id$
+ */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/protosw.h>
+#include <sys/domain.h>
+#include <sys/mbuf.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+
+/*
+ * System initialization
+ *
+ * Note: domain initialization wants to take place on a per domain basis
+ * as a result of traversing a linker set. Most likely, each domain
+ * want to call a registration function rather than being handled here
+ * in domaininit(). Probably this will look like:
+ *
+ * SYSINIT(unique, SI_SUB_PROTO_DOMAI, SI_ORDER_ANY, domain_add, xxx)
+ *
+ * Where 'xxx' is replaced by the address of a parameter struct to be
+ * passed to the doamin_add() function.
+ */
+
+#if !defined(__rtems__)
+static int x_save_spl; /* used by kludge*/
+static void kludge_splimp __P((void *));
+static void kludge_splx __P((void *));
+ void domaininit __P((void *));
+SYSINIT(splimp, SI_SUB_PROTO_BEGIN, SI_ORDER_FIRST, kludge_splimp, &x_save_spl)
+SYSINIT(domain, SI_SUB_PROTO_DOMAIN, SI_ORDER_FIRST, domaininit, NULL)
+SYSINIT(splx, SI_SUB_PROTO_END, SI_ORDER_FIRST, kludge_splx, &x_save_spl)
+#endif
+
+static void pffasttimo __P((void *));
+static void pfslowtimo __P((void *));
+
+struct domain *domains;
+
+#define ADDDOMAIN(x) { \
+ __CONCAT(x,domain.dom_next) = domains; \
+ domains = &__CONCAT(x,domain); \
+}
+
+extern struct linker_set domain_set;
+
+/* ARGSUSED*/
+void
+domaininit(dummy)
+ void *dummy;
+{
+ register struct domain *dp;
+ register struct protosw *pr;
+
+/* - not in our sources
+#ifdef ISDN
+ ADDDOMAIN(isdn);
+#endif
+*/
+
+ for (dp = domains; dp; dp = dp->dom_next) {
+ if (dp->dom_init)
+ (*dp->dom_init)();
+ for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++){
+#ifdef PRU_OLDSTYLE
+ /* See comments in uipc_socket2.c. */
+ if (pr->pr_usrreqs == 0 && pr->pr_ousrreq)
+ pr->pr_usrreqs = &pru_oldstyle;
+#endif
+ if (pr->pr_init)
+ (*pr->pr_init)();
+ }
+ }
+
+ if (max_linkhdr < 16) /* XXX */
+ max_linkhdr = 16;
+ max_hdr = max_linkhdr + max_protohdr;
+ max_datalen = MHLEN - max_hdr;
+ timeout(pffasttimo, (void *)0, 1);
+ timeout(pfslowtimo, (void *)0, 1);
+}
+
+
+#if !defined(__rtems__)
+/*
+ * The following two operations are kludge code. Most likely, they should
+ * be done as a "domainpreinit()" for the first function and then rolled
+ * in as the last act of "domaininit()" for the second.
+ *
+ * In point of fact, it is questionable why other initialization prior
+ * to this does not also take place at splimp by default.
+ */
+static void
+kludge_splimp(udata)
+ void *udata;
+{
+ int *savesplp = udata;
+
+ *savesplp = splimp();
+}
+
+static void
+kludge_splx(udata)
+ void *udata;
+{
+ int *savesplp = udata;
+
+ splx( *savesplp);
+}
+#endif /* !defined(__rtems__) */
+
+struct protosw *
+pffindtype(int family, int type)
+{
+ register struct domain *dp;
+ register struct protosw *pr;
+
+ for (dp = domains; dp; dp = dp->dom_next)
+ if (dp->dom_family == family)
+ goto found;
+ return (0);
+found:
+ for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
+ if (pr->pr_type && pr->pr_type == type)
+ return (pr);
+ return (0);
+}
+
+struct protosw *
+pffindproto(int family, int protocol, int type)
+{
+ register struct domain *dp;
+ register struct protosw *pr;
+ struct protosw *maybe = 0;
+
+ if (family == 0)
+ return (0);
+ for (dp = domains; dp; dp = dp->dom_next)
+ if (dp->dom_family == family)
+ goto found;
+ return (0);
+found:
+ for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
+ if ((pr->pr_protocol == protocol) && (pr->pr_type == type))
+ return (pr);
+
+ if (type == SOCK_RAW && pr->pr_type == SOCK_RAW &&
+ pr->pr_protocol == 0 && maybe == (struct protosw *)0)
+ maybe = pr;
+ }
+ return (maybe);
+}
+
+void
+pfctlinput(cmd, sa)
+ int cmd;
+ struct sockaddr *sa;
+{
+ register struct domain *dp;
+ register struct protosw *pr;
+
+ for (dp = domains; dp; dp = dp->dom_next)
+ for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
+ if (pr->pr_ctlinput)
+ (*pr->pr_ctlinput)(cmd, sa, (void *)0);
+}
+
+static void
+pfslowtimo(arg)
+ void *arg;
+{
+ register struct domain *dp;
+ register struct protosw *pr;
+
+ for (dp = domains; dp; dp = dp->dom_next)
+ for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
+ if (pr->pr_slowtimo)
+ (*pr->pr_slowtimo)();
+ timeout(pfslowtimo, (void *)0, hz/2);
+}
+
+static void
+pffasttimo(arg)
+ void *arg;
+{
+ register struct domain *dp;
+ register struct protosw *pr;
+
+ for (dp = domains; dp; dp = dp->dom_next)
+ for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
+ if (pr->pr_fasttimo)
+ (*pr->pr_fasttimo)();
+ timeout(pffasttimo, (void *)0, hz/5);
+}
diff --git a/cpukit/libnetworking/kern/uipc_mbuf.c b/cpukit/libnetworking/kern/uipc_mbuf.c
new file mode 100644
index 0000000000..a0e54ac94b
--- /dev/null
+++ b/cpukit/libnetworking/kern/uipc_mbuf.c
@@ -0,0 +1,777 @@
+/*
+ * Copyright (c) 1982, 1986, 1988, 1991, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94
+ * $Id$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/malloc.h>
+#define MBTYPES
+#include <sys/mbuf.h>
+#include <sys/kernel.h>
+#include <sys/syslog.h>
+#include <sys/domain.h>
+#include <sys/protosw.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_extern.h>
+
+#if !defined(__rtems__)
+static void mbinit __P((void *)) __attribute__ ((unused));
+SYSINIT(mbuf, SI_SUB_MBUF, SI_ORDER_FIRST, mbinit, NULL)
+#endif
+
+struct mbuf *mbutl;
+char *mclrefcnt;
+struct mbstat mbstat;
+struct mbuf *mmbfree;
+union mcluster *mclfree;
+int max_linkhdr;
+int max_protohdr;
+int max_hdr;
+int max_datalen;
+
+/* "number of clusters of pages" */
+#define NCL_INIT 1
+
+#define NMB_INIT 16
+
+/*
+ * When MGET failes, ask protocols to free space when short of memory,
+ * then re-attempt to allocate an mbuf.
+ */
+struct mbuf *
+m_retry(i, t)
+ int i, t;
+{
+ register struct mbuf *m;
+
+ m_reclaim();
+#define m_retry(i, t) (struct mbuf *)0
+ MGET(m, i, t);
+#undef m_retry
+ if (m != NULL)
+ mbstat.m_wait++;
+ else
+ mbstat.m_drops++;
+ return (m);
+}
+
+/*
+ * As above; retry an MGETHDR.
+ */
+struct mbuf *
+m_retryhdr(i, t)
+ int i, t;
+{
+ register struct mbuf *m;
+
+ m_reclaim();
+#define m_retryhdr(i, t) (struct mbuf *)0
+ MGETHDR(m, i, t);
+#undef m_retryhdr
+ if (m != NULL)
+ mbstat.m_wait++;
+ else
+ mbstat.m_drops++;
+ return (m);
+}
+
+void
+m_reclaim(void)
+{
+ register struct domain *dp;
+ register struct protosw *pr;
+ int s = splimp();
+
+ for (dp = domains; dp; dp = dp->dom_next)
+ for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
+ if (pr->pr_drain)
+ (*pr->pr_drain)();
+ splx(s);
+ mbstat.m_drain++;
+}
+
+/*
+ * Space allocation routines.
+ * These are also available as macros
+ * for critical paths.
+ */
+struct mbuf *
+m_get(nowait, type)
+ int nowait, type;
+{
+ register struct mbuf *m;
+
+ MGET(m, nowait, type);
+ return (m);
+}
+
+struct mbuf *
+m_gethdr(nowait, type)
+ int nowait, type;
+{
+ register struct mbuf *m;
+
+ MGETHDR(m, nowait, type);
+ return (m);
+}
+
+struct mbuf *
+m_getclr(nowait, type)
+ int nowait, type;
+{
+ register struct mbuf *m;
+
+ MGET(m, nowait, type);
+ if (m == 0)
+ return (0);
+ bzero(mtod(m, caddr_t), MLEN);
+ return (m);
+}
+
+struct mbuf *
+m_free(m)
+ struct mbuf *m;
+{
+ register struct mbuf *n;
+
+ MFREE(m, n);
+ return (n);
+}
+
+void
+m_freem(m)
+ register struct mbuf *m;
+{
+ register struct mbuf *n;
+
+ if (m == NULL)
+ return;
+ do {
+ MFREE(m, n);
+ m = n;
+ } while (m);
+}
+
+/*
+ * Mbuffer utility routines.
+ */
+
+/*
+ * Lesser-used path for M_PREPEND:
+ * allocate new mbuf to prepend to chain,
+ * copy junk along.
+ */
+struct mbuf *
+m_prepend(m, len, how)
+ register struct mbuf *m;
+ int len, how;
+{
+ struct mbuf *mn;
+
+ MGET(mn, how, m->m_type);
+ if (mn == (struct mbuf *)NULL) {
+ m_freem(m);
+ return ((struct mbuf *)NULL);
+ }
+ if (m->m_flags & M_PKTHDR) {
+ M_COPY_PKTHDR(mn, m);
+ m->m_flags &= ~M_PKTHDR;
+ }
+ mn->m_next = m;
+ m = mn;
+ if (len < MHLEN)
+ MH_ALIGN(m, len);
+ m->m_len = len;
+ return (m);
+}
+
+/*
+ * Make a copy of an mbuf chain starting "off0" bytes from the beginning,
+ * continuing for "len" bytes. If len is M_COPYALL, copy to end of mbuf.
+ * The wait parameter is a choice of M_WAIT/M_DONTWAIT from caller.
+ */
+static int MCFail;
+
+struct mbuf *
+m_copym(m, off0, len, wait)
+ register struct mbuf *m;
+ int off0, wait;
+ register int len;
+{
+ register struct mbuf *n, **np;
+ register int off = off0;
+ struct mbuf *top;
+ int copyhdr = 0;
+
+ if (off < 0 || len < 0)
+ panic("m_copym");
+ if (off == 0 && m->m_flags & M_PKTHDR)
+ copyhdr = 1;
+ while (off > 0) {
+ if (m == 0)
+ panic("m_copym");
+ if (off < m->m_len)
+ break;
+ off -= m->m_len;
+ m = m->m_next;
+ }
+ np = &top;
+ top = 0;
+ while (len > 0) {
+ if (m == 0) {
+ if (len != M_COPYALL)
+ panic("m_copym");
+ break;
+ }
+ MGET(n, wait, m->m_type);
+ *np = n;
+ if (n == 0)
+ goto nospace;
+ if (copyhdr) {
+ M_COPY_PKTHDR(n, m);
+ if (len == M_COPYALL)
+ n->m_pkthdr.len -= off0;
+ else
+ n->m_pkthdr.len = len;
+ copyhdr = 0;
+ }
+ n->m_len = min(len, m->m_len - off);
+ if (m->m_flags & M_EXT) {
+ n->m_data = m->m_data + off;
+ if(!m->m_ext.ext_ref)
+ mclrefcnt[mtocl(m->m_ext.ext_buf)]++;
+ else
+ (*(m->m_ext.ext_ref))(m->m_ext.ext_buf,
+ m->m_ext.ext_size);
+ n->m_ext = m->m_ext;
+ n->m_flags |= M_EXT;
+ } else
+ bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t),
+ (unsigned)n->m_len);
+ if (len != M_COPYALL)
+ len -= n->m_len;
+ off = 0;
+ m = m->m_next;
+ np = &n->m_next;
+ }
+ if (top == 0)
+ MCFail++;
+ return (top);
+nospace:
+ m_freem(top);
+ MCFail++;
+ return (0);
+}
+
+/*
+ * Copy an entire packet, including header (which must be present).
+ * An optimization of the common case `m_copym(m, 0, M_COPYALL, how)'.
+ */
+struct mbuf *
+m_copypacket(m, how)
+ struct mbuf *m;
+ int how;
+{
+ struct mbuf *top, *n, *o;
+
+ MGET(n, how, m->m_type);
+ top = n;
+ if (!n)
+ goto nospace;
+
+ M_COPY_PKTHDR(n, m);
+ n->m_len = m->m_len;
+ if (m->m_flags & M_EXT) {
+ n->m_data = m->m_data;
+ mclrefcnt[mtocl(m->m_ext.ext_buf)]++;
+ n->m_ext = m->m_ext;
+ n->m_flags |= M_EXT;
+ } else {
+ bcopy(mtod(m, char *), mtod(n, char *), n->m_len);
+ }
+
+ m = m->m_next;
+ while (m) {
+ MGET(o, how, m->m_type);
+ if (!o)
+ goto nospace;
+
+ n->m_next = o;
+ n = n->m_next;
+
+ n->m_len = m->m_len;
+ if (m->m_flags & M_EXT) {
+ n->m_data = m->m_data;
+ mclrefcnt[mtocl(m->m_ext.ext_buf)]++;
+ n->m_ext = m->m_ext;
+ n->m_flags |= M_EXT;
+ } else {
+ bcopy(mtod(m, char *), mtod(n, char *), n->m_len);
+ }
+
+ m = m->m_next;
+ }
+ return top;
+nospace:
+ m_freem(top);
+ MCFail++;
+ return 0;
+}
+
+/*
+ * Copy data from an mbuf chain starting "off" bytes from the beginning,
+ * continuing for "len" bytes, into the indicated buffer. Return -1 if requested
+ * size is bigger than available
+ */
+int
+m_copydata(m, off, len, cp)
+ register struct mbuf *m;
+ register int off;
+ register int len;
+ caddr_t cp;
+{
+ register unsigned count;
+/* struct mbuf *m0 = m; */
+
+ if (off < 0 || len < 0)
+ panic("m_copydata");
+ while (off > 0) {
+ if (m == 0) {
+ /*printf("m_copydata: offset > mbuf length (");
+ while(m0) {
+ printf("[%d] ",m0->m_len);
+ m0 = m0->m_next;
+ }
+ printf(")\n");*/
+ return -1;
+ }
+ if (off < m->m_len)
+ break;
+ off -= m->m_len;
+ m = m->m_next;
+ }
+ while (len > 0) {
+ if (m == 0) {
+ /*printf("m_copydata: length > mbuf length (");
+ while(m0) {
+ printf("[%d] ",m0->m_len);
+ m0 = m0->m_next;
+ }
+ printf(")\n");*/
+
+ return -1;
+ }
+ count = min(m->m_len - off, len);
+ bcopy(mtod(m, caddr_t) + off, cp, count);
+ len -= count;
+ cp += count;
+ off = 0;
+ m = m->m_next;
+ }
+ return 0;
+}
+
+/*
+ * Concatenate mbuf chain n to m.
+ * Both chains must be of the same type (e.g. MT_DATA).
+ * Any m_pkthdr is not updated.
+ */
+void
+m_cat(m, n)
+ register struct mbuf *m, *n;
+{
+ while (m->m_next)
+ m = m->m_next;
+ while (n) {
+ if (m->m_flags & M_EXT ||
+ m->m_data + m->m_len + n->m_len >= &m->m_dat[MLEN]) {
+ /* just join the two chains */
+ m->m_next = n;
+ return;
+ }
+ /* splat the data from one into the other */
+ bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
+ (u_int)n->m_len);
+ m->m_len += n->m_len;
+ n = m_free(n);
+ }
+}
+
+void
+m_adj(mp, req_len)
+ struct mbuf *mp;
+ int req_len;
+{
+ register int len = req_len;
+ register struct mbuf *m;
+ register int count;
+
+ if ((m = mp) == NULL)
+ return;
+ if (len >= 0) {
+ /*
+ * Trim from head.
+ */
+ while (m != NULL && len > 0) {
+ if (m->m_len <= len) {
+ len -= m->m_len;
+ m->m_len = 0;
+ m = m->m_next;
+ } else {
+ m->m_len -= len;
+ m->m_data += len;
+ len = 0;
+ }
+ }
+ m = mp;
+ if (mp->m_flags & M_PKTHDR)
+ m->m_pkthdr.len -= (req_len - len);
+ } else {
+ /*
+ * Trim from tail. Scan the mbuf chain,
+ * calculating its length and finding the last mbuf.
+ * If the adjustment only affects this mbuf, then just
+ * adjust and return. Otherwise, rescan and truncate
+ * after the remaining size.
+ */
+ len = -len;
+ count = 0;
+ for (;;) {
+ count += m->m_len;
+ if (m->m_next == (struct mbuf *)0)
+ break;
+ m = m->m_next;
+ }
+ if (m->m_len >= len) {
+ m->m_len -= len;
+ if (mp->m_flags & M_PKTHDR)
+ mp->m_pkthdr.len -= len;
+ return;
+ }
+ count -= len;
+ if (count < 0)
+ count = 0;
+ /*
+ * Correct length for chain is "count".
+ * Find the mbuf with last data, adjust its length,
+ * and toss data from remaining mbufs on chain.
+ */
+ m = mp;
+ if (m->m_flags & M_PKTHDR)
+ m->m_pkthdr.len = count;
+ for (; m; m = m->m_next) {
+ if (m->m_len >= count) {
+ m->m_len = count;
+ break;
+ }
+ count -= m->m_len;
+ }
+ while (m->m_next)
+ (m = m->m_next) ->m_len = 0;
+ }
+}
+
+/*
+ * Rearange an mbuf chain so that len bytes are contiguous
+ * and in the data area of an mbuf (so that mtod and dtom
+ * will work for a structure of size len). Returns the resulting
+ * mbuf chain on success, frees it and returns null on failure.
+ * If there is room, it will add up to max_protohdr-len extra bytes to the
+ * contiguous region in an attempt to avoid being called next time.
+ */
+static int MPFail;
+
+struct mbuf *
+m_pullup(n, len)
+ register struct mbuf *n;
+ int len;
+{
+ register struct mbuf *m;
+ register int count;
+ int space;
+
+ /*
+ * If first mbuf has no cluster, and has room for len bytes
+ * without shifting current data, pullup into it,
+ * otherwise allocate a new mbuf to prepend to the chain.
+ */
+ if ((n->m_flags & M_EXT) == 0 &&
+ n->m_data + len < &n->m_dat[MLEN] && n->m_next) {
+ if (n->m_len >= len)
+ return (n);
+ m = n;
+ n = n->m_next;
+ len -= m->m_len;
+ } else {
+ if (len > MHLEN)
+ goto bad;
+ MGET(m, M_DONTWAIT, n->m_type);
+ if (m == 0)
+ goto bad;
+ m->m_len = 0;
+ if (n->m_flags & M_PKTHDR) {
+ M_COPY_PKTHDR(m, n);
+ n->m_flags &= ~M_PKTHDR;
+ }
+ }
+ space = &m->m_dat[MLEN] - (m->m_data + m->m_len);
+ do {
+ count = min(min(max(len, max_protohdr), space), n->m_len);
+ bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
+ (unsigned)count);
+ len -= count;
+ m->m_len += count;
+ n->m_len -= count;
+ space -= count;
+ if (n->m_len)
+ n->m_data += count;
+ else
+ n = m_free(n);
+ } while (len > 0 && n);
+ if (len > 0) {
+ (void) m_free(m);
+ goto bad;
+ }
+ m->m_next = n;
+ return (m);
+bad:
+ m_freem(n);
+ MPFail++;
+ return (0);
+}
+
+/*
+ * Partition an mbuf chain in two pieces, returning the tail --
+ * all but the first len0 bytes. In case of failure, it returns NULL and
+ * attempts to restore the chain to its original state.
+ */
+struct mbuf *
+m_split(m0, len0, wait)
+ register struct mbuf *m0;
+ int len0, wait;
+{
+ register struct mbuf *m, *n;
+ unsigned len = len0, remain;
+
+ for (m = m0; m && len > m->m_len; m = m->m_next)
+ len -= m->m_len;
+ if (m == 0)
+ return (0);
+ remain = m->m_len - len;
+ if (m0->m_flags & M_PKTHDR) {
+ MGETHDR(n, wait, m0->m_type);
+ if (n == 0)
+ return (0);
+ n->m_pkthdr.rcvif = m0->m_pkthdr.rcvif;
+ n->m_pkthdr.len = m0->m_pkthdr.len - len0;
+ m0->m_pkthdr.len = len0;
+ if (m->m_flags & M_EXT)
+ goto extpacket;
+ if (remain > MHLEN) {
+ /* m can't be the lead packet */
+ MH_ALIGN(n, 0);
+ n->m_next = m_split(m, len, wait);
+ if (n->m_next == 0) {
+ (void) m_free(n);
+ return (0);
+ } else
+ return (n);
+ } else
+ MH_ALIGN(n, remain);
+ } else if (remain == 0) {
+ n = m->m_next;
+ m->m_next = 0;
+ return (n);
+ } else {
+ MGET(n, wait, m->m_type);
+ if (n == 0)
+ return (0);
+ M_ALIGN(n, remain);
+ }
+extpacket:
+ if (m->m_flags & M_EXT) {
+ n->m_flags |= M_EXT;
+ n->m_ext = m->m_ext;
+ if(!m->m_ext.ext_ref)
+ mclrefcnt[mtocl(m->m_ext.ext_buf)]++;
+ else
+ (*(m->m_ext.ext_ref))(m->m_ext.ext_buf,
+ m->m_ext.ext_size);
+ m->m_ext.ext_size = 0; /* For Accounting XXXXXX danger */
+ n->m_data = m->m_data + len;
+ } else {
+ bcopy(mtod(m, caddr_t) + len, mtod(n, caddr_t), remain);
+ }
+ n->m_len = remain;
+ m->m_len = len;
+ n->m_next = m->m_next;
+ m->m_next = 0;
+ return (n);
+}
+/*
+ * Routine to copy from device local memory into mbufs.
+ */
+struct mbuf *
+m_devget(buf, totlen, off0, ifp, copy)
+ char *buf;
+ int totlen, off0;
+ struct ifnet *ifp;
+ void (*copy) __P((char *from, caddr_t to, u_int len));
+{
+ register struct mbuf *m;
+ struct mbuf *top = 0, **mp = &top;
+ register int off = off0, len;
+ register char *cp;
+ char *epkt;
+
+ cp = buf;
+ epkt = cp + totlen;
+ if (off) {
+ cp += off + 2 * sizeof(u_short);
+ totlen -= 2 * sizeof(u_short);
+ }
+ MGETHDR(m, M_DONTWAIT, MT_DATA);
+ if (m == 0)
+ return (0);
+ m->m_pkthdr.rcvif = ifp;
+ m->m_pkthdr.len = totlen;
+ m->m_len = MHLEN;
+
+ while (totlen > 0) {
+ if (top) {
+ MGET(m, M_DONTWAIT, MT_DATA);
+ if (m == 0) {
+ m_freem(top);
+ return (0);
+ }
+ m->m_len = MLEN;
+ }
+ len = min(totlen, epkt - cp);
+ if (len >= MINCLSIZE) {
+ MCLGET(m, M_DONTWAIT);
+ if (m->m_flags & M_EXT)
+ m->m_len = len = min(len, MCLBYTES);
+ else
+ len = m->m_len;
+ } else {
+ /*
+ * Place initial small packet/header at end of mbuf.
+ */
+ if (len < m->m_len) {
+ if (top == 0 && len + max_linkhdr <= m->m_len)
+ m->m_data += max_linkhdr;
+ m->m_len = len;
+ } else
+ len = m->m_len;
+ }
+ if (copy)
+ copy(cp, mtod(m, caddr_t), (unsigned)len);
+ else
+ bcopy(cp, mtod(m, caddr_t), (unsigned)len);
+ cp += len;
+ *mp = m;
+ mp = &m->m_next;
+ totlen -= len;
+ if (cp == epkt)
+ cp = buf;
+ }
+ return (top);
+}
+
+/*
+ * Copy data from a buffer back into the indicated mbuf chain,
+ * starting "off" bytes from the beginning, extending the mbuf
+ * chain if necessary.
+ */
+int
+m_copyback(m0, off, len, cp)
+ struct mbuf *m0;
+ register int off;
+ register int len;
+ caddr_t cp;
+{
+ register int mlen;
+ register struct mbuf *m = m0, *n;
+ int totlen = 0;
+
+ if (m0 == 0)
+ return 0;
+ while (off > (mlen = m->m_len)) {
+ off -= mlen;
+ totlen += mlen;
+ if (m->m_next == 0) {
+ n = m_getclr(M_DONTWAIT, m->m_type);
+ if (n == 0) {
+ /*panic("m_copyback() : malformed chain\n");*/
+ return -1;
+ }
+ n->m_len = min(MLEN, len + off);
+ m->m_next = n;
+ }
+ m = m->m_next;
+ }
+ while (len > 0) {
+ mlen = min (m->m_len - off, len);
+ bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen);
+ cp += mlen;
+ len -= mlen;
+ mlen += off;
+ off = 0;
+ totlen += mlen;
+ if (len == 0) {
+ /* m->m_len = mlen; */
+ break;
+ }
+ if (m->m_next == 0) {
+ n = m_get(M_DONTWAIT, m->m_type);
+ if (n == 0) {
+ /*panic("m_copyback() : malformed chain 2\n");*/
+ return -1;
+ };
+ n->m_len = min(MLEN, len);
+ m->m_next = n;
+ }
+ /* m->m_len = mlen; */
+ m = m->m_next;
+ }
+/*out:*/
+ if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
+ m->m_pkthdr.len = totlen;
+ return 0;
+}
diff --git a/cpukit/libnetworking/kern/uipc_socket.c b/cpukit/libnetworking/kern/uipc_socket.c
new file mode 100644
index 0000000000..8ce3f0ef95
--- /dev/null
+++ b/cpukit/libnetworking/kern/uipc_socket.c
@@ -0,0 +1,1142 @@
+/*
+ * Copyright (c) 1982, 1986, 1988, 1990, 1993
+ * The Regents of the University of California. 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)uipc_socket.c 8.3 (Berkeley) 4/15/94
+ * $Id$
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/file.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/domain.h>
+#include <sys/kernel.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/resourcevar.h>
+#include <sys/signalvar.h>
+#include <sys/sysctl.h>
+#include <limits.h>
+
+static int somaxconn = SOMAXCONN;
+SYSCTL_INT(_kern, KIPC_SOMAXCONN, somaxconn, CTLFLAG_RW, &somaxconn, 0, "");
+
+/*
+ * Socket operation routines.
+ * These routines are called by the routines in
+ * sys_socket.c or from a system process, and
+ * implement the semantics of socket operations by
+ * switching out to the protocol specific routines.
+ */
+/*ARGSUSED*/
+int
+socreate(dom, aso, type, proto, p)
+ int dom;
+ struct socket **aso;
+ register int type;
+ int proto;
+ struct proc *p;
+{
+ register struct protosw *prp;
+ register struct socket *so;
+ register int error;
+
+ if (proto)
+ prp = pffindproto(dom, proto, type);
+ else
+ prp = pffindtype(dom, type);
+ if (prp == 0 || prp->pr_usrreqs == 0)
+ return (EPROTONOSUPPORT);
+ if (prp->pr_type != type)
+ return (EPROTOTYPE);
+ MALLOC(so, struct socket *, sizeof(*so), M_SOCKET, M_WAIT);
+ bzero((caddr_t)so, sizeof(*so));
+ TAILQ_INIT(&so->so_incomp);
+ TAILQ_INIT(&so->so_comp);
+ so->so_type = type;
+ so->so_state = SS_PRIV;
+ so->so_uid = 0;
+ so->so_proto = prp;
+ error = (*prp->pr_usrreqs->pru_attach)(so, proto);
+ if (error) {
+ so->so_state |= SS_NOFDREF;
+ sofree(so);
+ return (error);
+ }
+ *aso = so;
+ return (0);
+}
+
+int
+sobind(so, nam)
+ struct socket *so;
+ struct mbuf *nam;
+{
+ int s = splnet();
+ int error;
+
+ error = (*so->so_proto->pr_usrreqs->pru_bind)(so, nam);
+ splx(s);
+ return (error);
+}
+
+int
+solisten(so, backlog)
+ register struct socket *so;
+ int backlog;
+{
+ int s = splnet(), error;
+
+ error = (*so->so_proto->pr_usrreqs->pru_listen)(so);
+ if (error) {
+ splx(s);
+ return (error);
+ }
+ if (so->so_comp.tqh_first == NULL)
+ so->so_options |= SO_ACCEPTCONN;
+ if (backlog < 0 || backlog > somaxconn)
+ backlog = somaxconn;
+ so->so_qlimit = backlog;
+ splx(s);
+ return (0);
+}
+
+void
+sofree(so)
+ register struct socket *so;
+{
+ struct socket *head = so->so_head;
+
+ if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0)
+ return;
+ if (head != NULL) {
+ if (so->so_state & SS_INCOMP) {
+ TAILQ_REMOVE(&head->so_incomp, so, so_list);
+ head->so_incqlen--;
+ } else if (so->so_state & SS_COMP) {
+ TAILQ_REMOVE(&head->so_comp, so, so_list);
+ } else {
+ panic("sofree: not queued");
+ }
+ head->so_qlen--;
+ so->so_state &= ~(SS_INCOMP|SS_COMP);
+ so->so_head = NULL;
+ }
+ sbrelease(&so->so_snd);
+ sorflush(so);
+ FREE(so, M_SOCKET);
+}
+
+/*
+ * Close a socket on last file table reference removal.
+ * Initiate disconnect if connected.
+ * Free socket when disconnect complete.
+ */
+int
+soclose(so)
+ register struct socket *so;
+{
+ int s = splnet(); /* conservative */
+ int error = 0;
+
+ if (so->so_options & SO_ACCEPTCONN) {
+ struct socket *sp, *sonext;
+
+ for (sp = so->so_incomp.tqh_first; sp != NULL; sp = sonext) {
+ sonext = sp->so_list.tqe_next;
+ (void) soabort(sp);
+ }
+ for (sp = so->so_comp.tqh_first; sp != NULL; sp = sonext) {
+ sonext = sp->so_list.tqe_next;
+ (void) soabort(sp);
+ }
+ }
+ if (so->so_pcb == 0)
+ goto discard;
+ if (so->so_state & SS_ISCONNECTED) {
+ if ((so->so_state & SS_ISDISCONNECTING) == 0) {
+ error = sodisconnect(so);
+ if (error)
+ goto drop;
+ }
+ if (so->so_options & SO_LINGER) {
+ if ((so->so_state & SS_ISDISCONNECTING) &&
+ (so->so_state & SS_NBIO))
+ goto drop;
+ while (so->so_state & SS_ISCONNECTED) {
+ soconnsleep (so);
+ }
+ }
+ }
+drop:
+ if (so->so_pcb) {
+ int error2 = (*so->so_proto->pr_usrreqs->pru_detach)(so);
+ if (error == 0)
+ error = error2;
+ }
+discard:
+ if (so->so_state & SS_NOFDREF)
+ panic("soclose: NOFDREF");
+ so->so_state |= SS_NOFDREF;
+ sofree(so);
+ splx(s);
+ return (error);
+}
+
+/*
+ * Must be called at splnet...
+ */
+int
+soabort(so)
+ struct socket *so;
+{
+
+ return (*so->so_proto->pr_usrreqs->pru_abort)(so);
+}
+
+int
+soaccept(so, nam)
+ register struct socket *so;
+ struct mbuf *nam;
+{
+ int s = splnet();
+ int error;
+
+ if ((so->so_state & SS_NOFDREF) == 0)
+ panic("soaccept: !NOFDREF");
+ so->so_state &= ~SS_NOFDREF;
+ error = (*so->so_proto->pr_usrreqs->pru_accept)(so, nam);
+ splx(s);
+ return (error);
+}
+
+int
+soconnect(so, nam)
+ register struct socket *so;
+ struct mbuf *nam;
+{
+ int s;
+ int error;
+
+ if (so->so_options & SO_ACCEPTCONN)
+ return (EOPNOTSUPP);
+ s = splnet();
+ /*
+ * If protocol is connection-based, can only connect once.
+ * Otherwise, if connected, try to disconnect first.
+ * This allows user to disconnect by connecting to, e.g.,
+ * a null address.
+ */
+ if (so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING) &&
+ ((so->so_proto->pr_flags & PR_CONNREQUIRED) ||
+ (error = sodisconnect(so))))
+ error = EISCONN;
+ else
+ error = (*so->so_proto->pr_usrreqs->pru_connect)(so, nam);
+ splx(s);
+ return (error);
+}
+
+int
+soconnect2(so1, so2)
+ register struct socket *so1;
+ struct socket *so2;
+{
+ int s = splnet();
+ int error;
+
+ error = (*so1->so_proto->pr_usrreqs->pru_connect2)(so1, so2);
+ splx(s);
+ return (error);
+}
+
+int
+sodisconnect(so)
+ register struct socket *so;
+{
+ int s = splnet();
+ int error;
+
+ if ((so->so_state & SS_ISCONNECTED) == 0) {
+ error = ENOTCONN;
+ goto bad;
+ }
+ if (so->so_state & SS_ISDISCONNECTING) {
+ error = EALREADY;
+ goto bad;
+ }
+ error = (*so->so_proto->pr_usrreqs->pru_disconnect)(so);
+bad:
+ splx(s);
+ return (error);
+}
+
+#define SBLOCKWAIT(f) (((f) & MSG_DONTWAIT) ? M_NOWAIT : M_WAITOK)
+/*
+ * Send on a socket.
+ * If send must go all at once and message is larger than
+ * send buffering, then hard error.
+ * Lock against other senders.
+ * If must go all at once and not enough room now, then
+ * inform user that this would block and do nothing.
+ * Otherwise, if nonblocking, send as much as possible.
+ * The data to be sent is described by "uio" if nonzero,
+ * otherwise by the mbuf chain "top" (which must be null
+ * if uio is not). Data provided in mbuf chain must be small
+ * enough to send all at once.
+ *
+ * Returns nonzero on error, timeout or signal; callers
+ * must check for short counts if EINTR/ERESTART are returned.
+ * Data and control buffers are freed on return.
+ */
+int
+sosend(so, addr, uio, top, control, flags)
+ register struct socket *so;
+ struct mbuf *addr;
+ struct uio *uio;
+ struct mbuf *top;
+ struct mbuf *control;
+ int flags;
+{
+ struct mbuf **mp;
+ register struct mbuf *m;
+ register long space, len, resid;
+ int clen = 0, error, s, dontroute, mlen;
+ int atomic = sosendallatonce(so) || top;
+
+ if (uio)
+ resid = uio->uio_resid;
+ else
+ resid = top->m_pkthdr.len;
+ /*
+ * In theory resid should be unsigned.
+ * However, space must be signed, as it might be less than 0
+ * if we over-committed, and we must use a signed comparison
+ * of space and resid. On the other hand, a negative resid
+ * causes us to loop sending 0-length segments to the protocol.
+ *
+ * Also check to make sure that MSG_EOR isn't used on SOCK_STREAM
+ * type sockets since that's an error.
+ */
+ if ((resid < 0) || (so->so_type == SOCK_STREAM && (flags & MSG_EOR))) {
+ error = EINVAL;
+ goto out;
+ }
+
+ dontroute =
+ (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 &&
+ (so->so_proto->pr_flags & PR_ATOMIC);
+ if (control)
+ clen = control->m_len;
+#define snderr(errno) { error = errno; splx(s); goto release; }
+
+restart:
+ error = sblock(&so->so_snd, SBLOCKWAIT(flags));
+ if (error)
+ goto out;
+ do {
+ s = splnet();
+ if (so->so_state & SS_CANTSENDMORE)
+ snderr(EPIPE);
+ if (so->so_error) {
+ error = so->so_error;
+ so->so_error = 0;
+ splx(s);
+ goto release;
+ }
+ if ((so->so_state & SS_ISCONNECTED) == 0) {
+ /*
+ * `sendto' and `sendmsg' is allowed on a connection-
+ * based socket if it supports implied connect.
+ * Return ENOTCONN if not connected and no address is
+ * supplied.
+ */
+ if ((so->so_proto->pr_flags & PR_CONNREQUIRED) &&
+ (so->so_proto->pr_flags & PR_IMPLOPCL) == 0) {
+ if ((so->so_state & SS_ISCONFIRMING) == 0 &&
+ !(resid == 0 && clen != 0))
+ snderr(ENOTCONN);
+ } else if (addr == 0)
+ snderr(so->so_proto->pr_flags & PR_CONNREQUIRED ?
+ ENOTCONN : EDESTADDRREQ);
+ }
+ space = sbspace(&so->so_snd);
+ if (flags & MSG_OOB)
+ space += 1024;
+ if ((atomic && resid > so->so_snd.sb_hiwat) ||
+ clen > so->so_snd.sb_hiwat)
+ snderr(EMSGSIZE);
+ if (space < resid + clen && uio &&
+ (atomic || space < so->so_snd.sb_lowat || space < clen)) {
+ if (so->so_state & SS_NBIO)
+ snderr(EWOULDBLOCK);
+ sbunlock(&so->so_snd);
+ error = sbwait(&so->so_snd);
+ splx(s);
+ if (error)
+ goto out;
+ goto restart;
+ }
+ splx(s);
+ mp = &top;
+ space -= clen;
+ do {
+ if (uio == NULL) {
+ /*
+ * Data is prepackaged in "top".
+ */
+ resid = 0;
+ if (flags & MSG_EOR)
+ top->m_flags |= M_EOR;
+ } else do {
+ if (top == 0) {
+ MGETHDR(m, M_WAIT, MT_DATA);
+ mlen = MHLEN;
+ m->m_pkthdr.len = 0;
+ m->m_pkthdr.rcvif = (struct ifnet *)0;
+ } else {
+ MGET(m, M_WAIT, MT_DATA);
+ mlen = MLEN;
+ }
+ if (resid >= MINCLSIZE) {
+ MCLGET(m, M_WAIT);
+ if ((m->m_flags & M_EXT) == 0)
+ goto nopages;
+ mlen = MCLBYTES;
+ len = min(min(mlen, resid), space);
+ } else {
+nopages:
+ len = min(min(mlen, resid), space);
+ /*
+ * For datagram protocols, leave room
+ * for protocol headers in first mbuf.
+ */
+ if (atomic && top == 0 && len < mlen)
+ MH_ALIGN(m, len);
+ }
+ space -= len;
+ error = uiomove(mtod(m, caddr_t), (int)len, uio);
+ resid = uio->uio_resid;
+ m->m_len = len;
+ *mp = m;
+ top->m_pkthdr.len += len;
+ if (error)
+ goto release;
+ mp = &m->m_next;
+ if (resid <= 0) {
+ if (flags & MSG_EOR)
+ top->m_flags |= M_EOR;
+ break;
+ }
+ } while (space > 0 && atomic);
+ if (dontroute)
+ so->so_options |= SO_DONTROUTE;
+ s = splnet(); /* XXX */
+ error = (*so->so_proto->pr_usrreqs->pru_send)(so,
+ (flags & MSG_OOB) ? PRUS_OOB :
+ /*
+ * If the user set MSG_EOF, the protocol
+ * understands this flag and nothing left to
+ * send then use PRU_SEND_EOF instead of PRU_SEND.
+ */
+ ((flags & MSG_EOF) &&
+ (so->so_proto->pr_flags & PR_IMPLOPCL) &&
+ (resid <= 0)) ?
+ PRUS_EOF : 0,
+ top, addr, control);
+ splx(s);
+ if (dontroute)
+ so->so_options &= ~SO_DONTROUTE;
+ clen = 0;
+ control = 0;
+ top = 0;
+ mp = &top;
+ if (error)
+ goto release;
+ } while (resid && space > 0);
+ } while (resid);
+
+release:
+ sbunlock(&so->so_snd);
+out:
+ if (top)
+ m_freem(top);
+ if (control)
+ m_freem(control);
+ return (error);
+}
+
+/*
+ * Implement receive operations on a socket.
+ * We depend on the way that records are added to the sockbuf
+ * by sbappend*. In particular, each record (mbufs linked through m_next)
+ * must begin with an address if the protocol so specifies,
+ * followed by an optional mbuf or mbufs containing ancillary data,
+ * and then zero or more mbufs of data.
+ * In order to avoid blocking network interrupts for the entire time here,
+ * we splx() while doing the actual copy to user space.
+ * Although the sockbuf is locked, new data may still be appended,
+ * and thus we must maintain consistency of the sockbuf during that time.
+ *
+ * The caller may receive the data as a single mbuf chain by supplying
+ * an mbuf **mp0 for use in returning the chain. The uio is then used
+ * only for the count in uio_resid.
+ */
+int
+soreceive(so, paddr, uio, mp0, controlp, flagsp)
+ register struct socket *so;
+ struct mbuf **paddr;
+ struct uio *uio;
+ struct mbuf **mp0;
+ struct mbuf **controlp;
+ int *flagsp;
+{
+ register struct mbuf *m, **mp;
+ register int flags, len, error, s, offset;
+ struct protosw *pr = so->so_proto;
+ struct mbuf *nextrecord;
+ int moff, type = 0;
+ int orig_resid = uio->uio_resid;
+
+ mp = mp0;
+ if (paddr)
+ *paddr = 0;
+ if (controlp)
+ *controlp = 0;
+ if (flagsp)
+ flags = *flagsp &~ MSG_EOR;
+ else
+ flags = 0;
+ if (flags & MSG_OOB) {
+ m = m_get(M_WAIT, MT_DATA);
+ error = (*pr->pr_usrreqs->pru_rcvoob)(so, m, flags & MSG_PEEK);
+ if (error)
+ goto bad;
+ do {
+ error = uiomove(mtod(m, caddr_t),
+ (int) min(uio->uio_resid, m->m_len), uio);
+ m = m_free(m);
+ } while (uio->uio_resid && error == 0 && m);
+bad:
+ if (m)
+ m_freem(m);
+ return (error);
+ }
+ if (mp)
+ *mp = (struct mbuf *)0;
+ if (so->so_state & SS_ISCONFIRMING && uio->uio_resid)
+ (*pr->pr_usrreqs->pru_rcvd)(so, 0);
+
+restart:
+ error = sblock(&so->so_rcv, SBLOCKWAIT(flags));
+ if (error)
+ return (error);
+ s = splnet();
+
+ m = so->so_rcv.sb_mb;
+ /*
+ * If we have less data than requested, block awaiting more
+ * (subject to any timeout) if:
+ * 1. the current count is less than the low water mark, or
+ * 2. MSG_WAITALL is set, and it is possible to do the entire
+ * receive operation at once if we block (resid <= hiwat).
+ * 3. MSG_DONTWAIT is not set
+ * If MSG_WAITALL is set but resid is larger than the receive buffer,
+ * we have to do the receive in sections, and thus risk returning
+ * a short count if a timeout or signal occurs after we start.
+ */
+ if (m == 0 || (((flags & MSG_DONTWAIT) == 0 &&
+ so->so_rcv.sb_cc < uio->uio_resid) &&
+ (so->so_rcv.sb_cc < so->so_rcv.sb_lowat ||
+ ((flags & MSG_WAITALL) && uio->uio_resid <= so->so_rcv.sb_hiwat)) &&
+ m->m_nextpkt == 0 && (pr->pr_flags & PR_ATOMIC) == 0)) {
+#ifdef DIAGNOSTIC
+ if (m == 0 && so->so_rcv.sb_cc)
+ panic("receive 1");
+#endif
+ if (so->so_error) {
+ if (m)
+ goto dontblock;
+ error = so->so_error;
+ if ((flags & MSG_PEEK) == 0)
+ so->so_error = 0;
+ goto release;
+ }
+ if (so->so_state & SS_CANTRCVMORE) {
+ if (m)
+ goto dontblock;
+ else
+ goto release;
+ }
+ for (; m; m = m->m_next)
+ if (m->m_type == MT_OOBDATA || (m->m_flags & M_EOR)) {
+ m = so->so_rcv.sb_mb;
+ goto dontblock;
+ }
+ if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 &&
+ (so->so_proto->pr_flags & PR_CONNREQUIRED)) {
+ error = ENOTCONN;
+ goto release;
+ }
+ if (uio->uio_resid == 0)
+ goto release;
+ if ((so->so_state & SS_NBIO) || (flags & MSG_DONTWAIT)) {
+ error = EWOULDBLOCK;
+ goto release;
+ }
+ sbunlock(&so->so_rcv);
+ error = sbwait(&so->so_rcv);
+ splx(s);
+ if (error)
+ return (error);
+ goto restart;
+ }
+dontblock:
+ nextrecord = m->m_nextpkt;
+ if (pr->pr_flags & PR_ADDR) {
+#ifdef DIAGNOSTIC
+ if (m->m_type != MT_SONAME)
+ panic("receive 1a");
+#endif
+ orig_resid = 0;
+ if (flags & MSG_PEEK) {
+ if (paddr)
+ *paddr = m_copy(m, 0, m->m_len);
+ m = m->m_next;
+ } else {
+ sbfree(&so->so_rcv, m);
+ if (paddr) {
+ *paddr = m;
+ so->so_rcv.sb_mb = m->m_next;
+ m->m_next = 0;
+ m = so->so_rcv.sb_mb;
+ } else {
+ MFREE(m, so->so_rcv.sb_mb);
+ m = so->so_rcv.sb_mb;
+ }
+ }
+ }
+ while (m && m->m_type == MT_CONTROL && error == 0) {
+ if (flags & MSG_PEEK) {
+ if (controlp)
+ *controlp = m_copy(m, 0, m->m_len);
+ m = m->m_next;
+ } else {
+ sbfree(&so->so_rcv, m);
+ if (controlp) {
+ if (pr->pr_domain->dom_externalize &&
+ mtod(m, struct cmsghdr *)->cmsg_type ==
+ SCM_RIGHTS)
+ error = (*pr->pr_domain->dom_externalize)(m);
+ *controlp = m;
+ so->so_rcv.sb_mb = m->m_next;
+ m->m_next = 0;
+ m = so->so_rcv.sb_mb;
+ } else {
+ MFREE(m, so->so_rcv.sb_mb);
+ m = so->so_rcv.sb_mb;
+ }
+ }
+ if (controlp) {
+ orig_resid = 0;
+ controlp = &(*controlp)->m_next;
+ }
+ }
+ if (m) {
+ if ((flags & MSG_PEEK) == 0)
+ m->m_nextpkt = nextrecord;
+ type = m->m_type;
+ if (type == MT_OOBDATA)
+ flags |= MSG_OOB;
+ }
+ moff = 0;
+ offset = 0;
+ while (m && uio->uio_resid > 0 && error == 0) {
+ if (m->m_type == MT_OOBDATA) {
+ if (type != MT_OOBDATA)
+ break;
+ } else if (type == MT_OOBDATA)
+ break;
+#ifdef DIAGNOSTIC
+ else if (m->m_type != MT_DATA && m->m_type != MT_HEADER)
+ panic("receive 3");
+#endif
+ so->so_state &= ~SS_RCVATMARK;
+ len = uio->uio_resid;
+ if (so->so_oobmark && len > so->so_oobmark - offset)
+ len = so->so_oobmark - offset;
+ if (len > m->m_len - moff)
+ len = m->m_len - moff;
+ /*
+ * If mp is set, just pass back the mbufs.
+ * Otherwise copy them out via the uio, then free.
+ * Sockbuf must be consistent here (points to current mbuf,
+ * it points to next record) when we drop priority;
+ * we must note any additions to the sockbuf when we
+ * block interrupts again.
+ */
+ if (mp == 0) {
+ splx(s);
+ error = uiomove(mtod(m, caddr_t) + moff, (int)len, uio);
+ s = splnet();
+ if (error)
+ goto release;
+ } else
+ uio->uio_resid -= len;
+ if (len == m->m_len - moff) {
+ if (m->m_flags & M_EOR)
+ flags |= MSG_EOR;
+ if (flags & MSG_PEEK) {
+ m = m->m_next;
+ moff = 0;
+ } else {
+ nextrecord = m->m_nextpkt;
+ sbfree(&so->so_rcv, m);
+ if (mp) {
+ *mp = m;
+ mp = &m->m_next;
+ so->so_rcv.sb_mb = m = m->m_next;
+ *mp = (struct mbuf *)0;
+ } else {
+ MFREE(m, so->so_rcv.sb_mb);
+ m = so->so_rcv.sb_mb;
+ }
+ if (m)
+ m->m_nextpkt = nextrecord;
+ }
+ } else {
+ if (flags & MSG_PEEK)
+ moff += len;
+ else {
+ if (mp)
+ *mp = m_copym(m, 0, len, M_WAIT);
+ m->m_data += len;
+ m->m_len -= len;
+ so->so_rcv.sb_cc -= len;
+ }
+ }
+ if (so->so_oobmark) {
+ if ((flags & MSG_PEEK) == 0) {
+ so->so_oobmark -= len;
+ if (so->so_oobmark == 0) {
+ so->so_state |= SS_RCVATMARK;
+ break;
+ }
+ } else {
+ offset += len;
+ if (offset == so->so_oobmark)
+ break;
+ }
+ }
+ if (flags & MSG_EOR)
+ break;
+ /*
+ * If the MSG_WAITALL flag is set (for non-atomic socket),
+ * we must not quit until "uio->uio_resid == 0" or an error
+ * termination. If a signal/timeout occurs, return
+ * with a short count but without error.
+ * Keep sockbuf locked against other readers.
+ */
+ while (flags & MSG_WAITALL && m == 0 && uio->uio_resid > 0 &&
+ !sosendallatonce(so) && !nextrecord) {
+ if (so->so_error || so->so_state & SS_CANTRCVMORE)
+ break;
+ error = sbwait(&so->so_rcv);
+ if (error) {
+ sbunlock(&so->so_rcv);
+ splx(s);
+ return (0);
+ }
+ m = so->so_rcv.sb_mb;
+ if (m)
+ nextrecord = m->m_nextpkt;
+ }
+ }
+
+ if (m && pr->pr_flags & PR_ATOMIC) {
+ flags |= MSG_TRUNC;
+ if ((flags & MSG_PEEK) == 0)
+ (void) sbdroprecord(&so->so_rcv);
+ }
+ if ((flags & MSG_PEEK) == 0) {
+ if (m == 0)
+ so->so_rcv.sb_mb = nextrecord;
+ if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)
+ (*pr->pr_usrreqs->pru_rcvd)(so, flags);
+ }
+ if (orig_resid == uio->uio_resid && orig_resid &&
+ (flags & MSG_EOR) == 0 && (so->so_state & SS_CANTRCVMORE) == 0) {
+ sbunlock(&so->so_rcv);
+ splx(s);
+ goto restart;
+ }
+
+ if (flagsp)
+ *flagsp |= flags;
+release:
+ sbunlock(&so->so_rcv);
+ splx(s);
+ return (error);
+}
+
+int
+soshutdown(so, how)
+ register struct socket *so;
+ register int how;
+{
+ register struct protosw *pr = so->so_proto;
+
+ how++;
+ if (how & FREAD)
+ sorflush(so);
+ if (how & FWRITE)
+ return ((*pr->pr_usrreqs->pru_shutdown)(so));
+ return (0);
+}
+
+void
+sorflush(so)
+ register struct socket *so;
+{
+ register struct sockbuf *sb = &so->so_rcv;
+ register struct protosw *pr = so->so_proto;
+ register int s;
+ struct sockbuf asb;
+
+ sb->sb_flags |= SB_NOINTR;
+ (void) sblock(sb, M_WAITOK);
+ s = splimp();
+ socantrcvmore(so);
+ sbunlock(sb);
+ asb = *sb;
+ bzero((caddr_t)sb, sizeof (*sb));
+ splx(s);
+ if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose)
+ (*pr->pr_domain->dom_dispose)(asb.sb_mb);
+ sbrelease(&asb);
+}
+
+int
+sosetopt(so, level, optname, m0)
+ register struct socket *so;
+ int level, optname;
+ struct mbuf *m0;
+{
+ int error = 0;
+ register struct mbuf *m = m0;
+
+ if (level != SOL_SOCKET) {
+ if (so->so_proto && so->so_proto->pr_ctloutput)
+ return ((*so->so_proto->pr_ctloutput)
+ (PRCO_SETOPT, so, level, optname, &m0));
+ error = ENOPROTOOPT;
+ } else {
+ switch (optname) {
+
+ case SO_LINGER:
+ if (m == NULL || m->m_len != sizeof (struct linger)) {
+ error = EINVAL;
+ goto bad;
+ }
+ so->so_linger = mtod(m, struct linger *)->l_linger;
+ /* fall thru... */
+
+ case SO_DEBUG:
+ case SO_KEEPALIVE:
+ case SO_DONTROUTE:
+ case SO_USELOOPBACK:
+ case SO_BROADCAST:
+ case SO_REUSEADDR:
+ case SO_REUSEPORT:
+ case SO_OOBINLINE:
+ case SO_TIMESTAMP:
+ if (m == NULL || m->m_len < sizeof (int)) {
+ error = EINVAL;
+ goto bad;
+ }
+ if (*mtod(m, int *))
+ so->so_options |= optname;
+ else
+ so->so_options &= ~optname;
+ break;
+
+ case SO_SNDBUF:
+ case SO_RCVBUF:
+ case SO_SNDLOWAT:
+ case SO_RCVLOWAT:
+ {
+ int optval;
+
+ if (m == NULL || m->m_len < sizeof (int)) {
+ error = EINVAL;
+ goto bad;
+ }
+
+ /*
+ * Values < 1 make no sense for any of these
+ * options, so disallow them.
+ */
+ optval = *mtod(m, int *);
+ if (optval < 1) {
+ error = EINVAL;
+ goto bad;
+ }
+
+ switch (optname) {
+
+ case SO_SNDBUF:
+ case SO_RCVBUF:
+ if (sbreserve(optname == SO_SNDBUF ?
+ &so->so_snd : &so->so_rcv,
+ (u_long) optval) == 0) {
+ error = ENOBUFS;
+ goto bad;
+ }
+ break;
+
+ /*
+ * Make sure the low-water is never greater than
+ * the high-water.
+ */
+ case SO_SNDLOWAT:
+ so->so_snd.sb_lowat =
+ (optval > so->so_snd.sb_hiwat) ?
+ so->so_snd.sb_hiwat : optval;
+ break;
+ case SO_RCVLOWAT:
+ so->so_rcv.sb_lowat =
+ (optval > so->so_rcv.sb_hiwat) ?
+ so->so_rcv.sb_hiwat : optval;
+ break;
+ }
+ break;
+ }
+
+ case SO_SNDTIMEO:
+ case SO_RCVTIMEO:
+ {
+ struct timeval *tv;
+ unsigned long val;
+
+ if (m == NULL || m->m_len < sizeof (*tv)) {
+ error = EINVAL;
+ goto bad;
+ }
+ tv = mtod(m, struct timeval *);
+ if (tv->tv_sec >= (ULONG_MAX - hz) / hz) {
+ error = EDOM;
+ goto bad;
+ }
+
+ val = tv->tv_sec * hz + tv->tv_usec / tick;
+ if ((val == 0) && (tv->tv_sec || tv->tv_usec))
+ val = 1;
+
+ switch (optname) {
+
+ case SO_SNDTIMEO:
+ so->so_snd.sb_timeo = val;
+ break;
+ case SO_RCVTIMEO:
+ so->so_rcv.sb_timeo = val;
+ break;
+ }
+ break;
+ }
+
+ case SO_PRIVSTATE:
+ /* we don't care what the parameter is... */
+ so->so_state &= ~SS_PRIV;
+ break;
+
+ case SO_SNDWAKEUP:
+ case SO_RCVWAKEUP:
+ {
+ /* RTEMS addition. */
+ struct sockwakeup *sw;
+ struct sockbuf *sb;
+
+ if (m == NULL
+ || m->m_len != sizeof (struct sockwakeup)) {
+ error = EINVAL;
+ goto bad;
+ }
+ sw = mtod(m, struct sockwakeup *);
+ sb = (optname == SO_SNDWAKEUP
+ ? &so->so_snd
+ : &so->so_rcv);
+ sb->sb_wakeup = sw->sw_pfn;
+ sb->sb_wakeuparg = sw->sw_arg;
+ if (sw->sw_pfn)
+ sb->sb_flags |= SB_ASYNC;
+ else
+ sb->sb_flags &=~ SB_ASYNC;
+ break;
+ }
+
+ default:
+ error = ENOPROTOOPT;
+ break;
+ }
+ if (error == 0 && so->so_proto && so->so_proto->pr_ctloutput) {
+ (void) ((*so->so_proto->pr_ctloutput)
+ (PRCO_SETOPT, so, level, optname, &m0));
+ m = NULL; /* freed by protocol */
+ }
+ }
+bad:
+ if (m)
+ (void) m_free(m);
+ return (error);
+}
+
+int
+sogetopt(so, level, optname, mp)
+ register struct socket *so;
+ int level, optname;
+ struct mbuf **mp;
+{
+ register struct mbuf *m;
+
+ if (level != SOL_SOCKET) {
+ if (so->so_proto && so->so_proto->pr_ctloutput) {
+ return ((*so->so_proto->pr_ctloutput)
+ (PRCO_GETOPT, so, level, optname, mp));
+ } else
+ return (ENOPROTOOPT);
+ } else {
+ m = m_get(M_WAIT, MT_SOOPTS);
+ m->m_len = sizeof (int);
+
+ switch (optname) {
+
+ case SO_LINGER:
+ m->m_len = sizeof (struct linger);
+ mtod(m, struct linger *)->l_onoff =
+ so->so_options & SO_LINGER;
+ mtod(m, struct linger *)->l_linger = so->so_linger;
+ break;
+
+ case SO_USELOOPBACK:
+ case SO_DONTROUTE:
+ case SO_DEBUG:
+ case SO_KEEPALIVE:
+ case SO_REUSEADDR:
+ case SO_REUSEPORT:
+ case SO_BROADCAST:
+ case SO_OOBINLINE:
+ case SO_TIMESTAMP:
+ *mtod(m, int *) = so->so_options & optname;
+ break;
+
+ case SO_PRIVSTATE:
+ *mtod(m, int *) = so->so_state & SS_PRIV;
+ break;
+
+ case SO_TYPE:
+ *mtod(m, int *) = so->so_type;
+ break;
+
+ case SO_ERROR:
+ *mtod(m, int *) = so->so_error;
+ so->so_error = 0;
+ break;
+
+ case SO_SNDBUF:
+ *mtod(m, int *) = so->so_snd.sb_hiwat;
+ break;
+
+ case SO_RCVBUF:
+ *mtod(m, int *) = so->so_rcv.sb_hiwat;
+ break;
+
+ case SO_SNDLOWAT:
+ *mtod(m, int *) = so->so_snd.sb_lowat;
+ break;
+
+ case SO_RCVLOWAT:
+ *mtod(m, int *) = so->so_rcv.sb_lowat;
+ break;
+
+ case SO_SNDTIMEO:
+ case SO_RCVTIMEO:
+ {
+ unsigned long val = (optname == SO_SNDTIMEO ?
+ so->so_snd.sb_timeo : so->so_rcv.sb_timeo);
+
+ m->m_len = sizeof(struct timeval);
+ mtod(m, struct timeval *)->tv_sec = val / hz;
+ mtod(m, struct timeval *)->tv_usec =
+ (val % hz) * tick;
+ break;
+ }
+
+ case SO_SNDWAKEUP:
+ case SO_RCVWAKEUP:
+ {
+ struct sockbuf *sb;
+ struct sockwakeup *sw;
+
+ /* RTEMS additions. */
+ sb = (optname == SO_SNDWAKEUP
+ ? &so->so_snd
+ : &so->so_rcv);
+ m->m_len = sizeof (struct sockwakeup);
+ sw = mtod(m, struct sockwakeup *);
+ sw->sw_pfn = sb->sb_wakeup;
+ sw->sw_arg = sb->sb_wakeuparg;
+ break;
+ }
+
+ default:
+ (void)m_free(m);
+ return (ENOPROTOOPT);
+ }
+ *mp = m;
+ return (0);
+ }
+}
+
+void
+sohasoutofband(so)
+ register struct socket *so;
+{
+#if 0 /* FIXME: For now we just ignore out of band data */
+ struct proc *p;
+
+ if (so->so_pgid < 0)
+ gsignal(-so->so_pgid, SIGURG);
+ else if (so->so_pgid > 0 && (p = pfind(so->so_pgid)) != 0)
+ psignal(p, SIGURG);
+ selwakeup(&so->so_rcv.sb_sel);
+#endif
+}
diff --git a/cpukit/libnetworking/kern/uipc_socket2.c b/cpukit/libnetworking/kern/uipc_socket2.c
new file mode 100644
index 0000000000..ab1ee2439f
--- /dev/null
+++ b/cpukit/libnetworking/kern/uipc_socket2.c
@@ -0,0 +1,964 @@
+/*
+ * This file has undergone several changes to reflect the
+ * differences between the RTEMS and FreeBSD kernels.
+ */
+
+/*
+ * Copyright (c) 1982, 1986, 1988, 1990, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)uipc_socket2.c 8.1 (Berkeley) 6/10/93
+ * $Id$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/file.h>
+#include <sys/buf.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/protosw.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/signalvar.h>
+#include <sys/sysctl.h>
+
+/*
+ * Primitive routines for operating on sockets and socket buffers
+ */
+
+u_long sb_max = SB_MAX; /* XXX should be static */
+SYSCTL_INT(_kern, KIPC_MAXSOCKBUF, maxsockbuf, CTLFLAG_RW, &sb_max, 0, "");
+
+static u_long sb_efficiency = 8; /* parameter for sbreserve() */
+SYSCTL_INT(_kern, OID_AUTO, sockbuf_waste_factor, CTLFLAG_RW, &sb_efficiency,
+ 0, "");
+
+/*
+ * Procedures to manipulate state flags of socket
+ * and do appropriate wakeups. Normal sequence from the
+ * active (originating) side is that soisconnecting() is
+ * called during processing of connect() call,
+ * resulting in an eventual call to soisconnected() if/when the
+ * connection is established. When the connection is torn down
+ * soisdisconnecting() is called during processing of disconnect() call,
+ * and soisdisconnected() is called when the connection to the peer
+ * is totally severed. The semantics of these routines are such that
+ * connectionless protocols can call soisconnected() and soisdisconnected()
+ * only, bypassing the in-progress calls when setting up a ``connection''
+ * takes no time.
+ *
+ * From the passive side, a socket is created with
+ * two queues of sockets: so_q0 for connections in progress
+ * and so_q for connections already made and awaiting user acceptance.
+ * As a protocol is preparing incoming connections, it creates a socket
+ * structure queued on so_q0 by calling sonewconn(). When the connection
+ * is established, soisconnected() is called, and transfers the
+ * socket structure to so_q, making it available to accept().
+ *
+ * If a socket is closed with sockets on either
+ * so_q0 or so_q, these sockets are dropped.
+ *
+ * If higher level protocols are implemented in
+ * the kernel, the wakeups done here will sometimes
+ * cause software-interrupt process scheduling.
+ */
+
+void
+soisconnecting(so)
+ register struct socket *so;
+{
+
+ so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING);
+ so->so_state |= SS_ISCONNECTING;
+}
+
+void
+soisconnected(so)
+ register struct socket *so;
+{
+ register struct socket *head = so->so_head;
+
+ so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING|SS_ISCONFIRMING);
+ so->so_state |= SS_ISCONNECTED;
+ if (head && (so->so_state & SS_INCOMP)) {
+ TAILQ_REMOVE(&head->so_incomp, so, so_list);
+ head->so_incqlen--;
+ so->so_state &= ~SS_INCOMP;
+ TAILQ_INSERT_TAIL(&head->so_comp, so, so_list);
+ so->so_state |= SS_COMP;
+ sorwakeup(head);
+ soconnwakeup(head);
+ } else {
+ soconnwakeup(so);
+ sorwakeup(so);
+ sowwakeup(so);
+ }
+}
+
+void
+soisdisconnecting(so)
+ register struct socket *so;
+{
+
+ so->so_state &= ~SS_ISCONNECTING;
+ so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE);
+ soconnwakeup(so);
+ sowwakeup(so);
+ sorwakeup(so);
+}
+
+void
+soisdisconnected(so)
+ register struct socket *so;
+{
+
+ so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING);
+ so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE);
+ soconnwakeup(so);
+ sowwakeup(so);
+ sorwakeup(so);
+}
+
+/*
+ * Return a random connection that hasn't been serviced yet and
+ * is eligible for discard. There is a one in qlen chance that
+ * we will return a null, saying that there are no dropable
+ * requests. In this case, the protocol specific code should drop
+ * the new request. This insures fairness.
+ *
+ * This may be used in conjunction with protocol specific queue
+ * congestion routines.
+ */
+struct socket *
+sodropablereq(head)
+ register struct socket *head;
+{
+ register struct socket *so;
+ unsigned int i, j, qlen, m;
+
+ static int rnd;
+ static long old_mono_secs;
+ static unsigned int cur_cnt, old_cnt;
+
+ if ((i = (m = rtems_bsdnet_seconds_since_boot()) - old_mono_secs) != 0) {
+ old_mono_secs = m;
+ old_cnt = cur_cnt / i;
+ cur_cnt = 0;
+ }
+
+ so = TAILQ_FIRST(&head->so_incomp);
+ if (!so)
+ return (so);
+
+ qlen = head->so_incqlen;
+ if (++cur_cnt > qlen || old_cnt > qlen) {
+ rnd = (314159 * rnd + 66329) & 0xffff;
+ j = ((qlen + 1) * rnd) >> 16;
+
+ while (j-- && so)
+ so = TAILQ_NEXT(so, so_list);
+ }
+
+ return (so);
+}
+
+/*
+ * When an attempt at a new connection is noted on a socket
+ * which accepts connections, sonewconn is called. If the
+ * connection is possible (subject to space constraints, etc.)
+ * then we allocate a new structure, propoerly linked into the
+ * data structure of the original socket, and return this.
+ * Connstatus may be 0, or SO_ISCONFIRMING, or SO_ISCONNECTED.
+ *
+ * Currently, sonewconn() is defined as sonewconn1() in socketvar.h
+ * to catch calls that are missing the (new) second parameter.
+ */
+struct socket *
+sonewconn1(head, connstatus)
+ register struct socket *head;
+ int connstatus;
+{
+ register struct socket *so;
+
+ if (head->so_qlen > 3 * head->so_qlimit / 2)
+ return ((struct socket *)0);
+ MALLOC(so, struct socket *, sizeof(*so), M_SOCKET, M_DONTWAIT);
+ if (so == NULL)
+ return ((struct socket *)0);
+ bzero((caddr_t)so, sizeof(*so));
+ so->so_head = head;
+ so->so_type = head->so_type;
+ so->so_options = head->so_options &~ SO_ACCEPTCONN;
+ so->so_linger = head->so_linger;
+ so->so_state = head->so_state | SS_NOFDREF;
+ so->so_proto = head->so_proto;
+ so->so_timeo = head->so_timeo;
+ so->so_pgid = head->so_pgid;
+ so->so_uid = head->so_uid;
+ (void) soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat);
+ if (connstatus) {
+ TAILQ_INSERT_TAIL(&head->so_comp, so, so_list);
+ so->so_state |= SS_COMP;
+ } else {
+ TAILQ_INSERT_TAIL(&head->so_incomp, so, so_list);
+ so->so_state |= SS_INCOMP;
+ head->so_incqlen++;
+ }
+ head->so_qlen++;
+ if ((*so->so_proto->pr_usrreqs->pru_attach)(so, 0)) {
+ if (so->so_state & SS_COMP) {
+ TAILQ_REMOVE(&head->so_comp, so, so_list);
+ } else {
+ TAILQ_REMOVE(&head->so_incomp, so, so_list);
+ head->so_incqlen--;
+ }
+ head->so_qlen--;
+ (void) free((caddr_t)so, M_SOCKET);
+ return ((struct socket *)0);
+ }
+ if (connstatus) {
+ sorwakeup(head);
+ soconnwakeup(head);
+ so->so_state |= connstatus;
+ }
+ return (so);
+}
+
+/*
+ * Socantsendmore indicates that no more data will be sent on the
+ * socket; it would normally be applied to a socket when the user
+ * informs the system that no more data is to be sent, by the protocol
+ * code (in case PRU_SHUTDOWN). Socantrcvmore indicates that no more data
+ * will be received, and will normally be applied to the socket by a
+ * protocol when it detects that the peer will send no more data.
+ * Data queued for reading in the socket may yet be read.
+ */
+
+void
+socantsendmore(so)
+ struct socket *so;
+{
+
+ so->so_state |= SS_CANTSENDMORE;
+ sowwakeup(so);
+}
+
+void
+socantrcvmore(so)
+ struct socket *so;
+{
+
+ so->so_state |= SS_CANTRCVMORE;
+ sorwakeup(so);
+}
+
+/*
+ * Socket buffer (struct sockbuf) utility routines.
+ *
+ * Each socket contains two socket buffers: one for sending data and
+ * one for receiving data. Each buffer contains a queue of mbufs,
+ * information about the number of mbufs and amount of data in the
+ * queue, and other fields allowing select() statements and notification
+ * on data availability to be implemented.
+ *
+ * Data stored in a socket buffer is maintained as a list of records.
+ * Each record is a list of mbufs chained together with the m_next
+ * field. Records are chained together with the m_nextpkt field. The upper
+ * level routine soreceive() expects the following conventions to be
+ * observed when placing information in the receive buffer:
+ *
+ * 1. If the protocol requires each message be preceded by the sender's
+ * name, then a record containing that name must be present before
+ * any associated data (mbuf's must be of type MT_SONAME).
+ * 2. If the protocol supports the exchange of ``access rights'' (really
+ * just additional data associated with the message), and there are
+ * ``rights'' to be received, then a record containing this data
+ * should be present (mbuf's must be of type MT_RIGHTS).
+ * 3. If a name or rights record exists, then it must be followed by
+ * a data record, perhaps of zero length.
+ *
+ * Before using a new socket structure it is first necessary to reserve
+ * buffer space to the socket, by calling sbreserve(). This should commit
+ * some of the available buffer space in the system buffer pool for the
+ * socket (currently, it does nothing but enforce limits). The space
+ * should be released by calling sbrelease() when the socket is destroyed.
+ */
+
+int
+soreserve(so, sndcc, rcvcc)
+ register struct socket *so;
+ u_long sndcc, rcvcc;
+{
+
+ if (sbreserve(&so->so_snd, sndcc) == 0)
+ goto bad;
+ if (sbreserve(&so->so_rcv, rcvcc) == 0)
+ goto bad2;
+ if (so->so_rcv.sb_lowat == 0)
+ so->so_rcv.sb_lowat = 1;
+ if (so->so_snd.sb_lowat == 0)
+ so->so_snd.sb_lowat = MCLBYTES;
+ if (so->so_snd.sb_lowat > so->so_snd.sb_hiwat)
+ so->so_snd.sb_lowat = so->so_snd.sb_hiwat;
+ return (0);
+bad2:
+ sbrelease(&so->so_snd);
+bad:
+ return (ENOBUFS);
+}
+
+/*
+ * Allot mbufs to a sockbuf.
+ * Attempt to scale mbmax so that mbcnt doesn't become limiting
+ * if buffering efficiency is near the normal case.
+ */
+int
+sbreserve(sb, cc)
+ struct sockbuf *sb;
+ u_long cc;
+{
+
+ if (cc > sb_max * MCLBYTES / (MSIZE + MCLBYTES))
+ return (0);
+ sb->sb_hiwat = cc;
+ sb->sb_mbmax = min(cc * sb_efficiency, sb_max);
+ if (sb->sb_lowat > sb->sb_hiwat)
+ sb->sb_lowat = sb->sb_hiwat;
+ return (1);
+}
+
+/*
+ * Free mbufs held by a socket, and reserved mbuf space.
+ */
+void
+sbrelease(sb)
+ struct sockbuf *sb;
+{
+
+ sbflush(sb);
+ sb->sb_hiwat = sb->sb_mbmax = 0;
+}
+
+/*
+ * Routines to add and remove
+ * data from an mbuf queue.
+ *
+ * The routines sbappend() or sbappendrecord() are normally called to
+ * append new mbufs to a socket buffer, after checking that adequate
+ * space is available, comparing the function sbspace() with the amount
+ * of data to be added. sbappendrecord() differs from sbappend() in
+ * that data supplied is treated as the beginning of a new record.
+ * To place a sender's address, optional access rights, and data in a
+ * socket receive buffer, sbappendaddr() should be used. To place
+ * access rights and data in a socket receive buffer, sbappendrights()
+ * should be used. In either case, the new data begins a new record.
+ * Note that unlike sbappend() and sbappendrecord(), these routines check
+ * for the caller that there will be enough space to store the data.
+ * Each fails if there is not enough space, or if it cannot find mbufs
+ * to store additional information in.
+ *
+ * Reliable protocols may use the socket send buffer to hold data
+ * awaiting acknowledgement. Data is normally copied from a socket
+ * send buffer in a protocol with m_copy for output to a peer,
+ * and then removing the data from the socket buffer with sbdrop()
+ * or sbdroprecord() when the data is acknowledged by the peer.
+ */
+
+/*
+ * Append mbuf chain m to the last record in the
+ * socket buffer sb. The additional space associated
+ * the mbuf chain is recorded in sb. Empty mbufs are
+ * discarded and mbufs are compacted where possible.
+ */
+void
+sbappend(sb, m)
+ struct sockbuf *sb;
+ struct mbuf *m;
+{
+ register struct mbuf *n;
+
+ if (m == 0)
+ return;
+ n = sb->sb_mb;
+ if (n) {
+ while (n->m_nextpkt)
+ n = n->m_nextpkt;
+ do {
+ if (n->m_flags & M_EOR) {
+ sbappendrecord(sb, m); /* XXXXXX!!!! */
+ return;
+ }
+ } while (n->m_next && (n = n->m_next));
+ }
+ sbcompress(sb, m, n);
+}
+
+#ifdef SOCKBUF_DEBUG
+void
+sbcheck(sb)
+ register struct sockbuf *sb;
+{
+ register struct mbuf *m;
+ register int len = 0, mbcnt = 0;
+
+ for (m = sb->sb_mb; m; m = m->m_next) {
+ len += m->m_len;
+ mbcnt += MSIZE;
+ if (m->m_flags & M_EXT) /*XXX*/ /* pretty sure this is bogus */
+ mbcnt += m->m_ext.ext_size;
+ if (m->m_nextpkt)
+ panic("sbcheck nextpkt");
+ }
+ if (len != sb->sb_cc || mbcnt != sb->sb_mbcnt) {
+ printf("cc %d != %d || mbcnt %d != %d\n", len, sb->sb_cc,
+ mbcnt, sb->sb_mbcnt);
+ panic("sbcheck");
+ }
+}
+#endif
+
+/*
+ * As above, except the mbuf chain
+ * begins a new record.
+ */
+void
+sbappendrecord(sb, m0)
+ register struct sockbuf *sb;
+ register struct mbuf *m0;
+{
+ register struct mbuf *m;
+
+ if (m0 == 0)
+ return;
+ m = sb->sb_mb;
+ if (m)
+ while (m->m_nextpkt)
+ m = m->m_nextpkt;
+ /*
+ * Put the first mbuf on the queue.
+ * Note this permits zero length records.
+ */
+ sballoc(sb, m0);
+ if (m)
+ m->m_nextpkt = m0;
+ else
+ sb->sb_mb = m0;
+ m = m0->m_next;
+ m0->m_next = 0;
+ if (m && (m0->m_flags & M_EOR)) {
+ m0->m_flags &= ~M_EOR;
+ m->m_flags |= M_EOR;
+ }
+ sbcompress(sb, m, m0);
+}
+
+/*
+ * As above except that OOB data
+ * is inserted at the beginning of the sockbuf,
+ * but after any other OOB data.
+ */
+void
+sbinsertoob(sb, m0)
+ register struct sockbuf *sb;
+ register struct mbuf *m0;
+{
+ register struct mbuf *m;
+ register struct mbuf **mp;
+
+ if (m0 == 0)
+ return;
+ for (mp = &sb->sb_mb; *mp ; mp = &((*mp)->m_nextpkt)) {
+ m = *mp;
+ again:
+ switch (m->m_type) {
+
+ case MT_OOBDATA:
+ continue; /* WANT next train */
+
+ case MT_CONTROL:
+ m = m->m_next;
+ if (m)
+ goto again; /* inspect THIS train further */
+ }
+ break;
+ }
+ /*
+ * Put the first mbuf on the queue.
+ * Note this permits zero length records.
+ */
+ sballoc(sb, m0);
+ m0->m_nextpkt = *mp;
+ *mp = m0;
+ m = m0->m_next;
+ m0->m_next = 0;
+ if (m && (m0->m_flags & M_EOR)) {
+ m0->m_flags &= ~M_EOR;
+ m->m_flags |= M_EOR;
+ }
+ sbcompress(sb, m, m0);
+}
+
+/*
+ * Append address and data, and optionally, control (ancillary) data
+ * to the receive queue of a socket. If present,
+ * m0 must include a packet header with total length.
+ * Returns 0 if no space in sockbuf or insufficient mbufs.
+ */
+int
+sbappendaddr(sb, asa, m0, control)
+ register struct sockbuf *sb;
+ struct sockaddr *asa;
+ struct mbuf *m0, *control;
+{
+ register struct mbuf *m, *n;
+ int space = asa->sa_len;
+
+if (m0 && (m0->m_flags & M_PKTHDR) == 0)
+panic("sbappendaddr");
+ if (m0)
+ space += m0->m_pkthdr.len;
+ for (n = control; n; n = n->m_next) {
+ space += n->m_len;
+ if (n->m_next == 0) /* keep pointer to last control buf */
+ break;
+ }
+ if (space > sbspace(sb))
+ return (0);
+ if (asa->sa_len > MLEN)
+ return (0);
+ MGET(m, M_DONTWAIT, MT_SONAME);
+ if (m == 0)
+ return (0);
+ m->m_len = asa->sa_len;
+ bcopy((caddr_t)asa, mtod(m, caddr_t), asa->sa_len);
+ if (n)
+ n->m_next = m0; /* concatenate data to control */
+ else
+ control = m0;
+ m->m_next = control;
+ for (n = m; n; n = n->m_next)
+ sballoc(sb, n);
+ n = sb->sb_mb;
+ if (n) {
+ while (n->m_nextpkt)
+ n = n->m_nextpkt;
+ n->m_nextpkt = m;
+ } else
+ sb->sb_mb = m;
+ return (1);
+}
+
+int
+sbappendcontrol(sb, m0, control)
+ struct sockbuf *sb;
+ struct mbuf *control, *m0;
+{
+ register struct mbuf *m, *n;
+ int space = 0;
+
+ if (control == 0)
+ panic("sbappendcontrol");
+ for (m = control; ; m = m->m_next) {
+ space += m->m_len;
+ if (m->m_next == 0)
+ break;
+ }
+ n = m; /* save pointer to last control buffer */
+ for (m = m0; m; m = m->m_next)
+ space += m->m_len;
+ if (space > sbspace(sb))
+ return (0);
+ n->m_next = m0; /* concatenate data to control */
+ for (m = control; m; m = m->m_next)
+ sballoc(sb, m);
+ n = sb->sb_mb;
+ if (n) {
+ while (n->m_nextpkt)
+ n = n->m_nextpkt;
+ n->m_nextpkt = control;
+ } else
+ sb->sb_mb = control;
+ return (1);
+}
+
+/*
+ * Compress mbuf chain m into the socket
+ * buffer sb following mbuf n. If n
+ * is null, the buffer is presumed empty.
+ */
+void
+sbcompress(sb, m, n)
+ register struct sockbuf *sb;
+ register struct mbuf *m, *n;
+{
+ register int eor = 0;
+ register struct mbuf *o;
+
+ while (m) {
+ eor |= m->m_flags & M_EOR;
+ if (m->m_len == 0 &&
+ (eor == 0 ||
+ (((o = m->m_next) || (o = n)) &&
+ o->m_type == m->m_type))) {
+ m = m_free(m);
+ continue;
+ }
+ if (n && (n->m_flags & (M_EXT | M_EOR)) == 0 &&
+ (n->m_data + n->m_len + m->m_len) < &n->m_dat[MLEN] &&
+ n->m_type == m->m_type) {
+ bcopy(mtod(m, caddr_t), mtod(n, caddr_t) + n->m_len,
+ (unsigned)m->m_len);
+ n->m_len += m->m_len;
+ sb->sb_cc += m->m_len;
+ m = m_free(m);
+ continue;
+ }
+ if (n)
+ n->m_next = m;
+ else
+ sb->sb_mb = m;
+ sballoc(sb, m);
+ n = m;
+ m->m_flags &= ~M_EOR;
+ m = m->m_next;
+ n->m_next = 0;
+ }
+ if (eor) {
+ if (n)
+ n->m_flags |= eor;
+ else
+ printf("semi-panic: sbcompress\n");
+ }
+}
+
+/*
+ * Free all mbufs in a sockbuf.
+ * Check that all resources are reclaimed.
+ */
+void
+sbflush(sb)
+ register struct sockbuf *sb;
+{
+
+ if (sb->sb_flags & SB_LOCK)
+ panic("sbflush");
+ while (sb->sb_mbcnt)
+ sbdrop(sb, (int)sb->sb_cc);
+ if (sb->sb_cc || sb->sb_mb)
+ panic("sbflush 2");
+}
+
+/*
+ * Drop data from (the front of) a sockbuf.
+ */
+void
+sbdrop(sb, len)
+ register struct sockbuf *sb;
+ register int len;
+{
+ register struct mbuf *m, *mn;
+ struct mbuf *next;
+
+ next = (m = sb->sb_mb) ? m->m_nextpkt : 0;
+ while (len > 0) {
+ if (m == 0) {
+ if (next == 0)
+ panic("sbdrop");
+ m = next;
+ next = m->m_nextpkt;
+ continue;
+ }
+ if (m->m_len > len) {
+ m->m_len -= len;
+ m->m_data += len;
+ sb->sb_cc -= len;
+ break;
+ }
+ len -= m->m_len;
+ sbfree(sb, m);
+ MFREE(m, mn);
+ m = mn;
+ }
+ while (m && m->m_len == 0) {
+ sbfree(sb, m);
+ MFREE(m, mn);
+ m = mn;
+ }
+ if (m) {
+ sb->sb_mb = m;
+ m->m_nextpkt = next;
+ } else
+ sb->sb_mb = next;
+}
+
+/*
+ * Drop a record off the front of a sockbuf
+ * and move the next record to the front.
+ */
+void
+sbdroprecord(sb)
+ register struct sockbuf *sb;
+{
+ register struct mbuf *m, *mn;
+
+ m = sb->sb_mb;
+ if (m) {
+ sb->sb_mb = m->m_nextpkt;
+ do {
+ sbfree(sb, m);
+ MFREE(m, mn);
+ m = mn;
+ } while (m);
+ }
+}
+
+/*
+ * Create a "control" mbuf containing the specified data
+ * with the specified type for presentation on a socket buffer.
+ */
+struct mbuf *
+sbcreatecontrol(p, size, type, level)
+ caddr_t p;
+ register int size;
+ int type, level;
+{
+ register struct cmsghdr *cp;
+ struct mbuf *m;
+
+ if ((m = m_get(M_DONTWAIT, MT_CONTROL)) == NULL)
+ return ((struct mbuf *) NULL);
+ cp = mtod(m, struct cmsghdr *);
+ /* XXX check size? */
+ (void)memcpy(CMSG_DATA(cp), p, size);
+ size += sizeof(*cp);
+ m->m_len = size;
+ cp->cmsg_len = size;
+ cp->cmsg_level = level;
+ cp->cmsg_type = type;
+ return (m);
+}
+
+#ifdef PRU_OLDSTYLE
+/*
+ * The following routines mediate between the old-style `pr_usrreq'
+ * protocol implementations and the new-style `struct pr_usrreqs'
+ * calling convention.
+ */
+
+/* syntactic sugar */
+#define nomb (struct mbuf *)0
+
+static int
+old_abort(struct socket *so)
+{
+ return so->so_proto->pr_ousrreq(so, PRU_ABORT, nomb, nomb, nomb);
+}
+
+static int
+old_accept(struct socket *so, struct mbuf *nam)
+{
+ return so->so_proto->pr_ousrreq(so, PRU_ACCEPT, nomb, nam, nomb);
+}
+
+static int
+old_attach(struct socket *so, int proto)
+{
+ return so->so_proto->pr_ousrreq(so, PRU_ATTACH, nomb,
+ (struct mbuf *)proto, /* XXX */
+ nomb);
+}
+
+static int
+old_bind(struct socket *so, struct mbuf *nam)
+{
+ return so->so_proto->pr_ousrreq(so, PRU_BIND, nomb, nam, nomb);
+}
+
+static int
+old_connect(struct socket *so, struct mbuf *nam)
+{
+ return so->so_proto->pr_ousrreq(so, PRU_CONNECT, nomb, nam, nomb);
+}
+
+static int
+old_connect2(struct socket *so1, struct socket *so2)
+{
+ return so1->so_proto->pr_ousrreq(so1, PRU_CONNECT2, nomb,
+ (struct mbuf *)so2, nomb);
+}
+
+static int
+old_control(struct socket *so, int cmd, caddr_t data, struct ifnet *ifp)
+{
+ return so->so_proto->pr_ousrreq(so, PRU_CONTROL, (struct mbuf *)cmd,
+ (struct mbuf *)data,
+ (struct mbuf *)ifp);
+}
+
+static int
+old_detach(struct socket *so)
+{
+ return so->so_proto->pr_ousrreq(so, PRU_DETACH, nomb, nomb, nomb);
+}
+
+static int
+old_disconnect(struct socket *so)
+{
+ return so->so_proto->pr_ousrreq(so, PRU_DISCONNECT, nomb, nomb, nomb);
+}
+
+static int
+old_listen(struct socket *so)
+{
+ return so->so_proto->pr_ousrreq(so, PRU_LISTEN, nomb, nomb, nomb);
+}
+
+static int
+old_peeraddr(struct socket *so, struct mbuf *nam)
+{
+ return so->so_proto->pr_ousrreq(so, PRU_PEERADDR, nomb, nam, nomb);
+}
+
+static int
+old_rcvd(struct socket *so, int flags)
+{
+ return so->so_proto->pr_ousrreq(so, PRU_RCVD, nomb,
+ (struct mbuf *)flags, /* XXX */
+ nomb);
+}
+
+static int
+old_rcvoob(struct socket *so, struct mbuf *m, int flags)
+{
+ return so->so_proto->pr_ousrreq(so, PRU_RCVOOB, m,
+ (struct mbuf *)flags, /* XXX */
+ nomb);
+}
+
+static int
+old_send(struct socket *so, int flags, struct mbuf *m, struct mbuf *addr,
+ struct mbuf *control)
+{
+ int req;
+
+ if (flags & PRUS_OOB) {
+ req = PRU_SENDOOB;
+ } else if(flags & PRUS_EOF) {
+ req = PRU_SEND_EOF;
+ } else {
+ req = PRU_SEND;
+ }
+ return so->so_proto->pr_ousrreq(so, req, m, addr, control);
+}
+
+static int
+old_sense(struct socket *so, struct stat *sb)
+{
+ return so->so_proto->pr_ousrreq(so, PRU_SENSE, (struct mbuf *)sb,
+ nomb, nomb);
+}
+
+static int
+old_shutdown(struct socket *so)
+{
+ return so->so_proto->pr_ousrreq(so, PRU_SHUTDOWN, nomb, nomb, nomb);
+}
+
+static int
+old_sockaddr(struct socket *so, struct mbuf *nam)
+{
+ return so->so_proto->pr_ousrreq(so, PRU_SOCKADDR, nomb, nam, nomb);
+}
+
+struct pr_usrreqs pru_oldstyle = {
+ old_abort, old_accept, old_attach, old_bind, old_connect,
+ old_connect2, old_control, old_detach, old_disconnect,
+ old_listen, old_peeraddr, old_rcvd, old_rcvoob, old_send,
+ old_sense, old_shutdown, old_sockaddr
+};
+
+#endif /* PRU_OLDSTYLE */
+
+/*
+ * Some routines that return EOPNOTSUPP for entry points that are not
+ * supported by a protocol. Fill in as needed.
+ */
+int
+pru_accept_notsupp(struct socket *so, struct mbuf *nam)
+{
+ return EOPNOTSUPP;
+}
+
+int
+pru_connect2_notsupp(struct socket *so1, struct socket *so2)
+{
+ return EOPNOTSUPP;
+}
+
+int
+pru_control_notsupp(struct socket *so, int cmd, caddr_t data,
+ struct ifnet *ifp)
+{
+ return EOPNOTSUPP;
+}
+
+int
+pru_listen_notsupp(struct socket *so)
+{
+ return EOPNOTSUPP;
+}
+
+int
+pru_rcvd_notsupp(struct socket *so, int flags)
+{
+ return EOPNOTSUPP;
+}
+
+int
+pru_rcvoob_notsupp(struct socket *so, struct mbuf *m, int flags)
+{
+ return EOPNOTSUPP;
+}
+
+/*
+ * This isn't really a ``null'' operation, but it's the default one
+ * and doesn't do anything destructive.
+ */
+int
+pru_sense_null(struct socket *so, struct stat *sb)
+{
+ sb->st_blksize = so->so_snd.sb_hiwat;
+ return 0;
+}
diff --git a/cpukit/libnetworking/lib/README b/cpukit/libnetworking/lib/README
new file mode 100644
index 0000000000..998bd5e708
--- /dev/null
+++ b/cpukit/libnetworking/lib/README
@@ -0,0 +1,5 @@
+#
+# $Id$
+#
+
+Sources from application-level (as opposed to kernel-level) libraries.
diff --git a/cpukit/libnetworking/lib/ftpfs.c b/cpukit/libnetworking/lib/ftpfs.c
new file mode 100644
index 0000000000..a89a316e76
--- /dev/null
+++ b/cpukit/libnetworking/lib/ftpfs.c
@@ -0,0 +1,1159 @@
+/*
+ * File Transfer Protocol client
+ *
+ * Transfer file to/from remote host
+ *
+ * This driver can be added to the RTEMS file system with a call to
+ * "rtems_bsdnet_initialize_ftp_filesystem () ".
+ * From then on, you can open, read and close files on a remote FTP server
+ * using the following syntax:
+ * To open a file "myfile.txt" in the directory "mydir" (relative to home
+ * directory) on a server named "myserver" using the user id
+ * "myuserid" and the password "my_very_secret_password" you must
+ * specify the following path:
+ *
+ * /FTP/myuserid:my_very_secret_password/@myserver/mydirectory/myfile.txt
+ *
+ * If the server is the default server specified in BOOTP, it can be ommitted:
+ *
+ * /FTP/myuserid:my_very_secret_password/mydirectory/myfile.txt
+ *
+ * WARNING: write accesses have not yet been tested.
+ *
+ *
+ * (c) Copyright 2002
+ * Thomas Doerfler
+ * IMD Ingenieurbuero fuer Microcomputertechnik
+ * Herbststr. 8
+ * 82178 Puchheim, Germany
+ * <Thomas.Doerfler@imd-systems.de>
+ *
+ * This code has been created after closly inspecting
+ * "tftpdriver.c" from Eric Norum.
+ *
+ * $Id$
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <malloc.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <rtems/rtems_bsdnet.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <rtems/ftpfs.h>
+
+
+#ifndef set_errno_and_return_minus_one
+#define set_errno_and_return_minus_one( _error ) \
+ do { errno = (_error); return -1; } while(0)
+#endif
+
+/* #define DEBUG_OUT */
+
+/*
+ * Well-known port for FTP
+ */
+#define FTP_PORT_NUM 21
+
+/*
+ * Pathname prefix
+ */
+#define FTP_PATHNAME_PREFIX "/FTP/"
+/*
+ * reply codes
+ */
+#define FTP_REPLY_CONNECT 220 /* Connection established */
+#define FTP_REPLY_PASSREQ 331 /* user ok, password required */
+#define FTP_REPLY_LOGIN 230 /* login finished */
+#define FTP_REPLY_SUCCESS 200 /* xxx successful */
+#define FTP_REPLY_OPENCONN 150 /* opening connection for tfer */
+#define FTP_REPLY_TFERCMPL 226 /* transfer complete */
+
+extern rtems_filesystem_operations_table rtems_ftp_ops;
+extern rtems_filesystem_file_handlers_r rtems_ftp_handlers;
+
+/*
+ * FTP command strings
+ */
+#define FTP_USER_CMD "USER "
+#define FTP_PASS_CMD "PASS "
+#define FTP_BINARY_CMD "TYPE I"
+#define FTP_PORT_CMD "PORT "
+#define FTP_STOR_CMD "STOR "
+#define FTP_RETR_CMD "RETR "
+#define FTP_QUIT_CMD "QUIT"
+
+/*
+ * State of each FTP stream
+ */
+struct ftpStream {
+ /*
+ * Control connection socket
+ */
+ int ctrl_socket;
+ struct sockaddr_in myCtrlAddress;
+ struct sockaddr_in farCtrlAddress;
+ /*
+ * Data transfer socket
+ */
+ int port_socket;
+ int data_socket;
+ struct sockaddr_in myDataAddress;
+ struct sockaddr_in farDataAddress;
+ /*
+ * other stuff to remember
+ */
+ boolean eof_reached;
+};
+
+/*
+ * Number of streams open at the same time
+ */
+static rtems_id ftp_mutex;
+static int nStreams;
+static struct ftpStream ** volatile ftpStreams;
+
+extern rtems_filesystem_operations_table rtems_tftp_ops;
+extern rtems_filesystem_file_handlers_r rtems_tftp_handlers;
+
+/*
+ * Direct copy from the IMFS/TFTP. Look at this.
+ */
+
+rtems_filesystem_limits_and_options_t rtems_ftp_limits_and_options = {
+ 5, /* link_max */
+ 6, /* max_canon */
+ 7, /* max_input */
+ 255, /* name_max */
+ 255, /* path_max */
+ 2, /* pipe_buf */
+ 1, /* posix_async_io */
+ 2, /* posix_chown_restrictions */
+ 3, /* posix_no_trunc */
+ 4, /* posix_prio_io */
+ 5, /* posix_sync_io */
+ 6 /* posix_vdisable */
+};
+
+int rtems_ftp_mount_me(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ rtems_status_code sc;
+
+ temp_mt_entry->mt_fs_root.handlers = &rtems_ftp_handlers;
+ temp_mt_entry->mt_fs_root.ops = &rtems_ftp_ops;
+
+ /*
+ * We have no ftp filesystem specific data to maintain. This
+ * filesystem may only be mounted ONCE.
+ *
+ * And we maintain no real filesystem nodes, so there is no real root.
+ */
+
+ temp_mt_entry->fs_info = NULL;
+ temp_mt_entry->mt_fs_root.node_access = NULL;
+
+ /*
+ * These need to be looked at for full POSIX semantics.
+ */
+
+ temp_mt_entry->pathconf_limits_and_options = rtems_ftp_limits_and_options;
+
+
+ /*
+ * Now allocate a semaphore for mutual exclusion.
+ *
+ * NOTE: This could be in an fsinfo for this filesystem type.
+ */
+
+ sc = rtems_semaphore_create (rtems_build_name('F','T','P',' '),
+ 1,
+ RTEMS_FIFO |
+ RTEMS_BINARY_SEMAPHORE |
+ RTEMS_NO_INHERIT_PRIORITY |
+ RTEMS_NO_PRIORITY_CEILING |
+ RTEMS_LOCAL,
+ 0,
+ &ftp_mutex);
+
+ if (sc != RTEMS_SUCCESSFUL)
+ set_errno_and_return_minus_one( ENOMEM );
+
+ return 0;
+}
+
+/*
+ * Initialize the FTP driver
+ */
+
+int rtems_bsdnet_initialize_ftp_filesystem ()
+{
+ int status;
+ rtems_filesystem_mount_table_entry_t *entry;
+
+ status = mkdir( FTP_PATHNAME_PREFIX, S_IRWXU | S_IRWXG | S_IRWXO );
+ if ( status == -1 )
+ return status;
+
+ status = mount(
+ &entry,
+ &rtems_ftp_ops,
+ RTEMS_FILESYSTEM_READ_ONLY,
+ NULL,
+ FTP_PATHNAME_PREFIX
+ );
+
+ if ( status )
+ perror( "FTP mount failed" );
+
+ return status;
+}
+
+/*
+ * read and return message code from ftp control connection
+ */
+int rtems_ftp_get_message
+(
+ const struct ftpStream *fsp, /* ptr to ftp control structure */
+ int *msg_code /* ptr to return message code */
+)
+{
+ char rd_buffer[4];
+ size_t rd_size;
+ size_t tmp_size;
+ int eno = 0;
+ rtems_boolean finished = FALSE;
+ do {
+ /*
+ * fetch (at least) 4 characters from control connection
+ * FIXME: how about a timeout?
+ */
+ rd_size = 0;
+ while ((eno == 0) &&
+ (rd_size < sizeof(rd_buffer))) {
+ tmp_size = read(fsp->ctrl_socket,
+ (&rd_buffer)+rd_size,
+ sizeof(rd_buffer)-rd_size);
+ if (tmp_size < 0) {
+ eno = EIO;
+ }
+ else {
+#ifdef DEBUG_OUT
+ write(1,(&rd_buffer)+rd_size,tmp_size);
+#endif
+ rd_size += tmp_size;
+ }
+ }
+ /*
+ * check for 3 digits and space, otherwise not finished
+ */
+ if ((eno == 0) &&
+ (isdigit((unsigned int)rd_buffer[0])) &&
+ (isdigit((unsigned int)rd_buffer[1])) &&
+ (isdigit((unsigned int)rd_buffer[2])) &&
+ (rd_buffer[3] == ' ')) {
+ finished = TRUE;
+ rd_buffer[3] = '\0';
+ *msg_code = atol(rd_buffer);
+ }
+ /*
+ * skip rest until end-of-line
+ */
+ do {
+ tmp_size = read(fsp->ctrl_socket,
+ &rd_buffer,
+ 1);
+ if (tmp_size < 0) {
+ eno = EIO;
+ }
+#ifdef DEBUG_OUT
+ else {
+ write(1,(&rd_buffer),tmp_size);
+ }
+#endif
+ } while ((eno == 0) &&
+ (rd_buffer[0] != '\n'));
+ } while ((eno == 0) && !finished);
+ return eno;
+}
+
+/*
+ * split a pseudo file name into host, user, password, filename
+ * NOTE: this function will allocate space for these strings,
+ * the calling function should free the space, when no longer needed
+ * exception: when we return any error, we will also cleanup
+ * the strings
+ * valid forms:
+ * /FTP/user:pass/filepath
+ * /FTP/user:pass@hostname/filepath
+
+ * /FTP/user:pass/filepath
+ * /FTP/user:pass/@hostname/filepath
+ * NOTE: /FTP is already stripped from the name
+ */
+int rtems_ftp_split_names
+( const char *pathname, /* total path name (including prefix) */
+ char **usernamep, /* ptr to ptr to user name */
+ char **passwordp, /* ptr to ptr to password */
+ char **hostnamep, /* ptr to ptr to host name */
+ char **filenamep) /* ptr to ptr to hostremaining file name */
+{
+ const char *chunk_start;
+ const char *chunk_end;
+ size_t chunk_len;
+ int rc = 0;
+
+ /*
+ * ensure, that result pointers are NULL...
+ */
+ *usernamep = NULL;
+ *passwordp = NULL;
+ *hostnamep = NULL;
+ *filenamep = NULL;
+
+#if 1
+ chunk_start = pathname;
+#else /* no longer needed with IMFS */
+ /*
+ * check, that total path is long enough, skip prefix
+ */
+ if (rc == 0) {
+ if (strlen (pathname) <= strlen (FTP_PATHNAME_PREFIX)) {
+ rc = ENOENT;
+ }
+ else {
+ chunk_start = pathname + strlen (FTP_PATHNAME_PREFIX);
+ }
+ }
+#endif
+ /*
+ * fetch user name: terminated with ":"
+ */
+ if (rc == 0) {
+ chunk_end = strchr(chunk_start,':');
+ if ((chunk_end == NULL) || /* No ':' found or */
+ (chunk_end == chunk_start)) { /* ':' is first character-> no name */
+ rc = ENOENT;
+ }
+ else {
+ chunk_len = chunk_end-chunk_start;
+ *usernamep = malloc(chunk_len+1);
+ if (*usernamep == NULL) {
+ rc = ENOMEM;
+ }
+ else {
+ memcpy(*usernamep,chunk_start,chunk_len);
+ (*usernamep)[chunk_len] = '\0';
+ }
+ }
+ }
+ /*
+ * fetch password: terminated with "/" or "@"
+ */
+ if (rc == 0) {
+ chunk_start = chunk_end + 1; /* skip ":" after user name */
+ chunk_end = strchr(chunk_start,'/');
+ if ((chunk_end == NULL) || /* No '/' found or */
+ (chunk_end == chunk_start)) { /* '/' is first character-> no pwd */
+ rc = ENOENT;
+ }
+ else {
+ /*
+ * we have found a proper '/'
+ * this is the end of the password
+ */
+ chunk_len = chunk_end-chunk_start;
+ *passwordp = malloc(chunk_len+1);
+ if (*passwordp == NULL) {
+ rc = ENOMEM;
+ }
+ else {
+ memcpy(*passwordp,chunk_start,chunk_len);
+ (*passwordp)[chunk_len] = '\0';
+ }
+ }
+ }
+ /*
+ * if first char after '/' is '@', then this is the hostname
+ * fetch hostname terminated with "/"
+ * if exists at all. otherwise take default server from bootp
+ */
+ if (rc == 0) {
+ chunk_start = chunk_end+1;
+ if (*chunk_start == '@') {
+ /*
+ * hostname follows
+ */
+ chunk_start = chunk_start + 1; /* skip "@" after password */
+ chunk_end = strchr(chunk_start,'/');
+ if ((chunk_end == NULL) || /* No '/' found or */
+ (chunk_end == chunk_start)) { /* '/' is first character-> no host */
+ rc = ENOENT;
+ }
+ else {
+ /*
+ * we have found a proper '/'
+ */
+ chunk_len = chunk_end-chunk_start;
+ *hostnamep = malloc(chunk_len+1);
+ if (*hostnamep == NULL) {
+ rc = ENOMEM;
+ }
+ else {
+ memcpy(*hostnamep,chunk_start,chunk_len);
+ (*hostnamep)[chunk_len] = '\0';
+ }
+ }
+ }
+ else { /* chunk_start != '@' */
+ /*
+ * no host name given, keep string empty
+ */
+ *hostnamep = malloc(1);
+ if (*hostnamep == NULL) {
+ rc = ENOMEM;
+ }
+ else {
+ (*hostnamep)[0] = '\0';
+ }
+ }
+ }
+ /*
+ * fetch filename. This is all the rest...
+ */
+ if (rc == 0) {
+ chunk_start = chunk_end+1;
+ if (*chunk_start == '\0') { /* nothing left for filename */
+ rc = ENOENT;
+ }
+ else {
+ chunk_len = strlen(chunk_start);
+ *filenamep = malloc(chunk_len+1);
+ if (*filenamep == NULL) {
+ rc = ENOMEM;
+ }
+ else {
+ memcpy(*filenamep,chunk_start,chunk_len);
+ (*filenamep)[chunk_len] = '\0';
+ }
+ }
+ }
+
+ /*
+ * cleanup anything, if error occured
+ */
+ if (rc != 0) {
+ if (*hostnamep != NULL) {
+ free(*hostnamep);
+ *hostnamep = NULL;
+ }
+ if (*usernamep != NULL) {
+ free(*usernamep);
+ *usernamep = NULL;
+ }
+ if (*passwordp != NULL) {
+ free(*passwordp);
+ *passwordp = NULL;
+ }
+ if (*filenamep != NULL) {
+ free(*filenamep);
+ *filenamep = NULL;
+ }
+ }
+ return rc;
+}
+
+int rtems_ftp_evaluate_for_make(
+ const char *path, /* IN */
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ const char **name /* OUT */
+)
+{
+ set_errno_and_return_minus_one( EIO );
+}
+
+/*
+ * XXX - Fix return values.
+ */
+
+int rtems_ftp_eval_path(
+ const char *pathname, /* IN */
+ int flags, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+)
+{
+
+ /*
+ * Read-only for now
+ */
+
+ if ( ((flags & O_RDONLY) != O_RDONLY ) &&
+ ((flags & O_WRONLY) != O_WRONLY )) {
+ set_errno_and_return_minus_one( ENOENT );
+ }
+ /*
+ * The File system is mounted at FTP_PATHNAME_PREFIX
+ * the caller of this routine has striped off this part of the
+ * name. Save the remainder of the name for use by the open routine.
+ */
+
+ pathloc->node_access = (void * ) pathname;
+ pathloc->handlers = &rtems_ftp_handlers;
+
+ return 0;
+}
+
+/*
+ * Open a FTP stream
+ */
+int rtems_ftp_open(
+ rtems_libio_t *iop,
+ const char *new_name,
+ uint32_t flag,
+ uint32_t mode
+)
+{
+ int s = 0;
+ char *filename = NULL;
+ char *uname = NULL;
+ char *upass = NULL;
+ char *hostname = NULL;
+ char port_buffer[sizeof(FTP_PORT_CMD)+6*4+1+1];
+ uint32_t my_ip;
+ uint16_t my_port;
+ int eno = 0;
+ rtems_status_code rc;
+ rtems_boolean is_write = FALSE;
+ rtems_boolean sema_obtained = FALSE;
+ struct ftpStream *fsp = NULL;
+ int msg_tmp;
+ int sockaddr_size;
+ /*
+ * check for R/O or W/O flags
+ */
+ if (eno == 0) {
+ if ((0 != (iop->flags & LIBIO_FLAGS_WRITE)) &&
+ (0 != (iop->flags & LIBIO_FLAGS_READ))) {
+ eno = ENOTSUP;
+ }
+ else {
+ is_write = (0 != (iop->flags & LIBIO_FLAGS_WRITE));
+ }
+ }
+ /*
+ * split pathname into parts
+ */
+ if (eno == 0) {
+ eno = rtems_ftp_split_names(iop->file_info,
+ &uname,
+ &upass,
+ &hostname,
+ &filename);
+ }
+
+ /*
+ * Find a free stream
+ */
+ if (eno == 0) {
+ rc = rtems_semaphore_obtain (ftp_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ if (rc == RTEMS_SUCCESSFUL) {
+ sema_obtained = TRUE;
+ }
+ else {
+ eno = EBUSY;
+ }
+ }
+ if (eno == 0) {
+ for (s = 0 ; s < nStreams ; s++) {
+ if (ftpStreams[s] == NULL)
+ break;
+ }
+ if (s == nStreams) {
+ /*
+ * Reallocate stream pointers
+ * Guard against the case where realloc() returns NULL.
+ */
+ struct ftpStream **np;
+
+ np = realloc (ftpStreams, ++nStreams * sizeof *ftpStreams);
+ if (np == NULL) {
+ eno = ENOMEM;
+ }
+ else {
+ ftpStreams = np;
+ }
+ }
+ }
+ if (eno == 0) {
+ fsp = ftpStreams[s] = malloc (sizeof (struct ftpStream));
+ rtems_semaphore_release (ftp_mutex);
+ sema_obtained = FALSE;
+ if (fsp == NULL) {
+ eno = ENOMEM;
+ }
+ else {
+ iop->data0 = s;
+ iop->data1 = fsp;
+ fsp->ctrl_socket = -1; /* mark, that sockets not yet created */
+ fsp->port_socket = -1;
+ fsp->data_socket = -1;
+ fsp->eof_reached = FALSE;
+ }
+ }
+ if (eno == 0) {
+ /*
+ * Create the socket for control connection
+ */
+ if ((fsp->ctrl_socket = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
+ eno = ENOMEM;
+ }
+ }
+
+ if (eno == 0) {
+ /*
+ * Set the destination to the FTP server
+ * port on the remote machine.
+ */
+ memset(&(fsp->farCtrlAddress),sizeof(fsp->farCtrlAddress),0);
+ fsp->farCtrlAddress.sin_family = AF_INET;
+ if (*hostname == '\0') {
+ fsp->farCtrlAddress.sin_addr.s_addr = rtems_bsdnet_bootp_server_address.s_addr;
+ }
+ else if (1 != inet_aton(hostname,&(fsp->farCtrlAddress.sin_addr))) {
+ struct hostent *hent;
+ struct hostent *gethostbyname(const char *name);
+
+ hent = gethostbyname(hostname);
+ if (hent != NULL) {
+ memcpy((char *)(&(fsp->farCtrlAddress.sin_addr)),
+ hent->h_addr,
+ sizeof(fsp->farCtrlAddress.sin_addr));
+ }
+ else {
+ eno = ENOENT;
+ }
+ }
+ if (eno == 0) {
+ fsp->farCtrlAddress.sin_port = htons (FTP_PORT_NUM);
+ fsp->farCtrlAddress.sin_len = sizeof(fsp->farCtrlAddress);
+ if (0 > connect(fsp->ctrl_socket,
+ (struct sockaddr *)&(fsp->farCtrlAddress),
+ sizeof(fsp->farCtrlAddress))) {
+ eno = ENOENT;
+ }
+ }
+ if (eno == 0) {
+ /*
+ * fetch IP address of interface used
+ */
+ memset(&(fsp->myCtrlAddress),sizeof(fsp->myCtrlAddress),0);
+ fsp->myCtrlAddress.sin_family = AF_INET;
+ fsp->myCtrlAddress.sin_addr.s_addr = INADDR_ANY;
+ fsp->myCtrlAddress.sin_port = 0;
+ fsp->myCtrlAddress.sin_len = sizeof(fsp->myDataAddress);
+ sockaddr_size = sizeof(fsp->myCtrlAddress);
+ if (0 > getsockname(fsp->ctrl_socket,
+ (struct sockaddr *)&(fsp->myCtrlAddress),
+ &sockaddr_size)) {
+ eno = ENOMEM;
+ }
+ }
+ }
+ if (eno == 0) {
+ /*
+ * now we should get a connect message from the FTP server
+ */
+ eno = rtems_ftp_get_message(fsp,&msg_tmp);
+ if ((eno == 0) &&
+ (msg_tmp != FTP_REPLY_CONNECT)) {
+ eno = ENOENT;
+ }
+ }
+ if (eno == 0) {
+ /*
+ * send user ID to server
+ * NOTE: the following lines will be executed in order
+ * and will be aborted whenever an error occures... (see your ANSI C book)
+ */
+ if ((0 > send(fsp->ctrl_socket,FTP_USER_CMD,strlen(FTP_USER_CMD),0)) ||
+ (0 > send(fsp->ctrl_socket,uname, strlen(uname), 0)) ||
+ (0 > send(fsp->ctrl_socket,"\n", 1, 0))) {
+ eno = EIO;
+ }
+ }
+ if (eno == 0) {
+ /*
+ * now we should get a request for the password or a login...
+ */
+ eno = rtems_ftp_get_message(fsp,&msg_tmp);
+ if (eno == 0) {
+ if (msg_tmp == FTP_REPLY_PASSREQ) {
+ /*
+ * send password to server
+ */
+#ifdef DEBUG_OUT
+ write(1,FTP_PASS_CMD,strlen(FTP_PASS_CMD));
+ write(1,upass, strlen(upass) );
+ write(1,"\n", 1 );
+#endif
+ if ((0 > send(fsp->ctrl_socket,FTP_PASS_CMD,strlen(FTP_PASS_CMD),0)) ||
+ (0 > send(fsp->ctrl_socket,upass, strlen(upass), 0)) ||
+ (0 > send(fsp->ctrl_socket,"\n", 1, 0))) {
+ eno = EIO;
+ }
+ /*
+ * at least now a login reply should come up...
+ * this is checked some lines downwards the code
+ */
+ if (eno == 0) {
+ eno = rtems_ftp_get_message(fsp,&msg_tmp);
+ }
+ }
+ }
+ }
+ if (eno == 0) {
+ /*
+ * check for a login reply. this should be present now...
+ */
+ if (msg_tmp != FTP_REPLY_LOGIN) {
+ eno = EACCES; /* pseudo for wrong user/pass */
+ }
+ }
+ if (eno == 0) {
+ /*
+ * set binary mode for all transfers
+ */
+#ifdef DEBUG_OUT
+ write(1,FTP_BINARY_CMD,strlen(FTP_BINARY_CMD));
+ write(1,"\n", 1 );
+#endif
+ if ((0 > send(fsp->ctrl_socket,FTP_BINARY_CMD,strlen(FTP_BINARY_CMD),0)) ||
+ (0 > send(fsp->ctrl_socket,"\n", 1, 0))) {
+ eno = EIO;
+ }
+ else {
+ eno = rtems_ftp_get_message(fsp,&msg_tmp);
+ }
+ }
+ if (eno == 0) {
+ /*
+ * check for a "BINARY TYPE command successful" reply
+ */
+ if (msg_tmp != FTP_REPLY_SUCCESS) {
+ eno = EIO;
+ }
+ }
+ if (eno == 0) {
+ /*
+ * create and bind socket for data connection
+ */
+ if ((fsp->port_socket = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
+ eno = ENOMEM;
+ }
+ else {
+ memset(&(fsp->myDataAddress),sizeof(fsp->myDataAddress),0);
+ fsp->myDataAddress.sin_family = AF_INET;
+ fsp->myDataAddress.sin_addr.s_addr = INADDR_ANY;
+ fsp->myDataAddress.sin_port = 0; /* unique port will be assigned */
+ fsp->myDataAddress.sin_len = sizeof(fsp->myDataAddress);
+ if (0 > bind(fsp->port_socket,
+ (struct sockaddr *)&(fsp->myDataAddress),
+ sizeof(fsp->myDataAddress))) {
+ eno = EBUSY;
+ }
+ else {
+ /*
+ * fetch port number of data socket
+ */
+ memset(&(fsp->myDataAddress),sizeof(fsp->myDataAddress),0);
+ fsp->myDataAddress.sin_family = AF_INET;
+ fsp->myDataAddress.sin_addr.s_addr = INADDR_ANY;
+ fsp->myDataAddress.sin_port = 0;
+ fsp->myDataAddress.sin_len = sizeof(fsp->myDataAddress);
+ sockaddr_size = sizeof(fsp->myDataAddress);
+ if (0 > getsockname(fsp->port_socket,
+ (struct sockaddr *)&(fsp->myDataAddress),
+ &sockaddr_size)) {
+ eno = ENOMEM;
+ }
+ }
+ }
+ }
+ if (eno == 0) {
+ /*
+ * propagate data connection port to server
+ */
+ my_ip = ntohl(fsp->myCtrlAddress.sin_addr.s_addr);
+ my_port = ntohs(fsp->myDataAddress.sin_port);
+ sprintf(port_buffer,"%s%u,%u,%u,%u,%u,%u\n",
+ FTP_PORT_CMD,
+ (my_ip >> 24) & 0x00ff,
+ (my_ip >> 16) & 0x00ff,
+ (my_ip >> 8) & 0x00ff,
+ (my_ip >> 0) & 0x00ff,
+ (my_port>> 8) & 0x00ff,
+ (my_port>> 0) & 0x00ff);
+#ifdef DEBUG_OUT
+ write(1,port_buffer,strlen(port_buffer));
+#endif
+ if (0 > send(fsp->ctrl_socket,port_buffer,strlen(port_buffer),0)) {
+ eno = EIO;
+ }
+ else {
+ eno = rtems_ftp_get_message(fsp,&msg_tmp);
+ }
+ }
+ if (eno == 0) {
+ /*
+ * check for a "PORT command successful" reply
+ */
+ if (msg_tmp != FTP_REPLY_SUCCESS) {
+ eno = EBUSY;
+ }
+ }
+ /*
+ * prepare port socket to listen for incoming connections
+ */
+ if (eno == 0) {
+ if (0 > listen(fsp->port_socket,1)) {
+ eno = EBUSY;
+ }
+ }
+ if (eno == 0) {
+ /*
+ * send retrive/store command with filename
+ */
+ if (is_write) {
+#ifdef DEBUG_OUT
+ write(1,FTP_STOR_CMD,strlen(FTP_STOR_CMD));
+ write(1,filename ,strlen(filename) );
+ write(1,"\n",1);
+#endif
+ if ((0 > send(fsp->ctrl_socket,FTP_STOR_CMD,strlen(FTP_STOR_CMD),0)) ||
+ (0 > send(fsp->ctrl_socket,filename, strlen(filename), 0)) ||
+ (0 > send(fsp->ctrl_socket,"\n", 1, 0))) {
+ eno = EIO;
+ }
+ }
+ else {
+#ifdef DEBUG_OUT
+ write(1,FTP_RETR_CMD,strlen(FTP_RETR_CMD));
+ write(1,filename ,strlen(filename) );
+ write(1,"\n",1);
+#endif
+ if ((0 > send(fsp->ctrl_socket,FTP_RETR_CMD,strlen(FTP_RETR_CMD),0)) ||
+ (0 > send(fsp->ctrl_socket,filename, strlen(filename), 0)) ||
+ (0 > send(fsp->ctrl_socket,"\n", 1, 0))) {
+ eno = EIO;
+ }
+ }
+ }
+#if 1
+ if (eno == 0) {
+ eno = rtems_ftp_get_message(fsp,&msg_tmp);
+ }
+ if (eno == 0) {
+ /*
+ * check for a "OPENING binary connection" reply
+ */
+ if (msg_tmp != FTP_REPLY_OPENCONN) {
+ eno = EACCES;
+ }
+ }
+#endif
+ /*
+ * wait for connect on data connection
+ * FIXME: this should become a select instead with a timeout
+ */
+ if (eno == 0) {
+ sockaddr_size = sizeof(fsp->farDataAddress);
+ fsp->data_socket = accept(fsp->port_socket,
+ (struct sockaddr *)&(fsp->farDataAddress),
+ &sockaddr_size);
+ if (0 > fsp->data_socket) {
+ eno = EIO;
+ }
+ }
+ /*
+ * FIXME: check, that fardataAddr is really from our ftp server
+ */
+
+ /*
+ * clean up temp strings...
+ */
+ if (uname != NULL) {
+ free(uname);
+ uname = NULL;
+ }
+ if (upass != NULL) {
+ free(upass);
+ upass = NULL;
+ }
+ if (hostname != NULL) {
+ free(hostname);
+ hostname = NULL;
+ }
+ if (filename != NULL) {
+ free(filename);
+ filename = NULL;
+ }
+ /*
+ * close part socket, no longer needed
+ */
+ if (fsp->port_socket != -1) {
+ close(fsp->port_socket);
+ fsp->port_socket = -1;
+ }
+ /*
+ * if error, clean up everything
+ */
+ if (eno != 0) {
+ if (fsp != NULL) {
+ /*
+ * check and close ctrl/data connection
+ */
+ if (fsp->data_socket != -1) {
+ close(fsp->data_socket);
+ fsp->data_socket = -1;
+ }
+ if (fsp->ctrl_socket != -1) {
+ close(fsp->ctrl_socket);
+ fsp->ctrl_socket = -1;
+ }
+ /*
+ * free ftpStream structure
+ */
+ ftpStreams[s] = NULL;
+ free(fsp);
+ fsp = NULL;
+ }
+ }
+ /*
+ * return sema, if still occupied
+ */
+ if (sema_obtained) {
+ rtems_semaphore_release (ftp_mutex);
+ sema_obtained = FALSE;
+ }
+#if 0
+ if (eno != 0) {
+ set_errno_and_return_minus_one(eno);
+ }
+ return 0;
+#else
+ return eno;
+#endif
+}
+
+/*
+ * Read from a FTP stream
+ */
+ssize_t rtems_ftp_read(
+ rtems_libio_t *iop,
+ void *buffer,
+ uint32_t count
+)
+{
+ int eno = 0;
+ struct ftpStream *fsp;
+ size_t want_cnt;
+ ssize_t rd_cnt;
+ int msg_tmp;
+
+ fsp = iop->data1;
+ want_cnt = count;
+ /*
+ * check, that data connection present
+ */
+ if (eno == 0) {
+ if ((fsp == NULL) ||
+ (fsp->data_socket < 0)) {
+ eno = EBADF;
+ }
+ }
+
+ /*
+ * perform read from data socket
+ * read multiple junks, if smaller than wanted
+ */
+ while ((eno == 0) &&
+ (want_cnt > 0) &&
+ !(fsp->eof_reached) ) {
+ rd_cnt = read(fsp->data_socket,buffer,want_cnt);
+ if (rd_cnt > 0) {
+ buffer += rd_cnt;
+ want_cnt -= rd_cnt;
+ }
+ else {
+ eno = rtems_ftp_get_message(fsp,&msg_tmp);
+ fsp->eof_reached = TRUE;
+ if ((eno == 0) &&
+ (msg_tmp != FTP_REPLY_TFERCMPL)) {
+ eno = EIO;
+ }
+ if (rd_cnt < 0) {
+ eno = EIO;
+ }
+ }
+ }
+ if (eno != 0) {
+ set_errno_and_return_minus_one(eno);
+ }
+ return count - want_cnt;
+}
+
+ssize_t rtems_ftp_write(
+ rtems_libio_t *iop,
+ const void *buffer,
+ uint32_t count
+)
+{
+ int eno = EIO;
+ struct ftpStream *fsp;
+ size_t want_cnt;
+ ssize_t wr_cnt;
+ int msg_tmp;
+
+ fsp = iop->data1;
+ want_cnt = count;
+ /*
+ * check, that data connection present
+ */
+ if (eno == 0) {
+ if ((fsp == NULL) ||
+ (fsp->data_socket < 0)) {
+ eno = EBADF;
+ }
+ }
+
+ /*
+ * perform write to data socket
+ */
+ if (eno == 0) {
+ wr_cnt = write(fsp->data_socket,buffer,want_cnt);
+ if (wr_cnt > 0) {
+ buffer += wr_cnt;
+ want_cnt -= wr_cnt;
+ }
+ else {
+ eno = rtems_ftp_get_message(fsp,&msg_tmp);
+ if ((eno == 0) &&
+ (msg_tmp != FTP_REPLY_TFERCMPL)) {
+ eno = EIO;
+ }
+ if (wr_cnt < 0) {
+ eno = EIO;
+ }
+ }
+ }
+ if (eno != 0) {
+ set_errno_and_return_minus_one(eno);
+ }
+ return count - want_cnt;
+}
+
+/*
+ * Close a FTP stream
+ */
+int rtems_ftp_close(
+ rtems_libio_t *iop
+)
+{
+ int s = iop->data0;
+ struct ftpStream *fsp = iop->data1;
+
+ /*
+ * close ctrl/data connection, if needed
+ */
+ if (fsp->data_socket >= 0) {
+ close(fsp->data_socket);
+ fsp->data_socket = -1;
+ }
+ if (fsp->ctrl_socket >= 0) {
+ close(fsp->ctrl_socket);
+ fsp->ctrl_socket = -1;
+ }
+ /*
+ * free any used space...
+ */
+ rtems_semaphore_obtain (ftp_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ free (ftpStreams[s]);
+ ftpStreams[s] = NULL;
+ rtems_semaphore_release (ftp_mutex);
+
+ return 0;
+}
+
+rtems_device_driver rtems_ftp_control(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *pargp
+)
+{
+ return RTEMS_NOT_CONFIGURED;
+}
+
+/*
+ * Dummy version to let fopen(xxxx,"w") work properly.
+ */
+static int rtems_ftp_ftruncate(
+ rtems_libio_t *iop,
+ off_t count
+)
+{
+ return 0;
+}
+
+rtems_filesystem_node_types_t rtems_ftp_node_type(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+)
+{
+ return RTEMS_FILESYSTEM_MEMORY_FILE;
+}
+
+rtems_filesystem_operations_table rtems_ftp_ops = {
+ rtems_ftp_eval_path, /* eval_path */
+ rtems_ftp_evaluate_for_make, /* evaluate_for_make */
+ NULL, /* link */
+ NULL, /* unlink */
+ rtems_ftp_node_type, /* node_type */
+ NULL, /* mknod */
+ NULL, /* chown */
+ NULL, /* freenodinfo */
+ NULL, /* mount */
+ rtems_ftp_mount_me, /* initialize */
+ NULL, /* unmount */
+ NULL, /* fsunmount */
+ NULL, /* utime, */
+ NULL, /* evaluate_link */
+ NULL, /* symlink */
+ NULL, /* readlin */
+};
+
+rtems_filesystem_file_handlers_r rtems_ftp_handlers = {
+ rtems_ftp_open, /* open */
+ rtems_ftp_close, /* close */
+ rtems_ftp_read, /* read */
+ rtems_ftp_write, /* write */
+ NULL, /* ioctl */
+ NULL, /* lseek */
+ NULL, /* fstat */
+ NULL, /* fchmod */
+ rtems_ftp_ftruncate, /* ftruncate */
+ NULL, /* fpathconf */
+ NULL, /* fsync */
+ NULL, /* fdatasync */
+ NULL, /* fcntl */
+ NULL /* rmnod */
+};
diff --git a/cpukit/libnetworking/lib/getprotoby.c b/cpukit/libnetworking/lib/getprotoby.c
new file mode 100644
index 0000000000..cefa5c1ff2
--- /dev/null
+++ b/cpukit/libnetworking/lib/getprotoby.c
@@ -0,0 +1,46 @@
+/*
+ * $Id$
+ */
+
+#include <netdb.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+static const struct protoent prototab[] = {
+ { "ip", NULL, IPPROTO_IP },
+ { "icmp", NULL, IPPROTO_ICMP },
+ { "tcp", NULL, IPPROTO_TCP },
+ { "udp", NULL, IPPROTO_UDP },
+ };
+
+/*
+ * Dummy version of BSD getprotobyname()
+ */
+struct protoent *
+getprotobyname_static (const char *name)
+{
+ int i;
+
+ for (i = 0 ; i < (sizeof prototab / sizeof prototab[0]) ; i++) {
+ if (strcmp (name, prototab[i].p_name) == 0)
+ return (struct protoent *) &prototab[i];
+ }
+ return NULL;
+}
+
+/*
+ * Dummy version of BSD getprotobynumber()
+ */
+struct protoent *
+getprotobynumber_static (int proto)
+{
+ int i;
+
+ for (i = 0 ; i < (sizeof prototab / sizeof prototab[0]) ; i++) {
+ if (proto == prototab[i].p_proto)
+ return (struct protoent *) &prototab[i];
+ }
+ return NULL;
+}
diff --git a/cpukit/libnetworking/lib/rtems_bsdnet_ntp.c b/cpukit/libnetworking/lib/rtems_bsdnet_ntp.c
new file mode 100644
index 0000000000..50386a2376
--- /dev/null
+++ b/cpukit/libnetworking/lib/rtems_bsdnet_ntp.c
@@ -0,0 +1,187 @@
+/*
+ * Synchronize with an NTP server
+ *
+ * This program may be distributed and used for any purpose.
+ * I ask only that you:
+ * 1. Leave this author information intact.
+ * 2. Document any changes you make.
+ *
+ * W. Eric Norum
+ * Canadian Light Source
+ * University of Saskatchewan
+ * Saskatoon, Saskatchewan, CANADA
+ * eric@cls.usask.ca
+ *
+ * $Id$
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <limits.h>
+#include <rtems.h>
+#include <rtems/rtems_bsdnet.h>
+#include <rtems/error.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+/*
+ * RTEMS base: 1988, January 1
+ * UNIX base: 1970, January 1
+ * NTP base: 1900, January 1
+ */
+#define UNIX_BASE_TO_NTP_BASE (((70UL*365UL)+17UL) * (24*60*60))
+
+struct timestamp {
+ uint32_t integer;
+ uint32_t fraction;
+};
+
+struct ntpPacketSmall {
+ uint8_t li_vn_mode;
+ uint8_t stratum;
+ int8_t poll_interval;
+ int8_t precision;
+ int32_t root_delay;
+ int32_t root_dispersion;
+ char reference_identifier[4];
+ struct timestamp reference_timestamp;
+ struct timestamp originate_timestamp;
+ struct timestamp receive_timestamp;
+ struct timestamp transmit_timestamp;
+};
+
+struct ntpPacket {
+ struct ntpPacketSmall ntp;
+ char authenticator[96];
+};
+
+static int
+processPacket (struct ntpPacketSmall *p)
+{
+ time_t tbuf;
+ struct tm *lt;
+ rtems_time_of_day rt;
+ rtems_interval ticks_per_second;
+
+ if (((p->li_vn_mode & (0x7 << 3)) != (3 << 3))
+ || ((p->transmit_timestamp.integer == 0) && (p->transmit_timestamp.fraction == 0)))
+ return 0;
+ rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticks_per_second);
+ tbuf = ntohl (p->transmit_timestamp.integer) - UNIX_BASE_TO_NTP_BASE - rtems_bsdnet_timeoffset;
+ lt = gmtime (&tbuf);
+ rt.year = lt->tm_year + 1900;
+ rt.month = lt->tm_mon + 1;
+ rt.day = lt->tm_mday;
+ rt.hour = lt->tm_hour;
+ rt.minute = lt->tm_min;
+ rt.second = lt->tm_sec;
+ rt.ticks = ntohl (p->transmit_timestamp.fraction) / (ULONG_MAX / ticks_per_second);
+ if (rt.ticks >= ticks_per_second)
+ rt.ticks = ticks_per_second - 1;
+ rtems_clock_set (&rt);
+ return 1;
+}
+
+static int
+tryServer (int i, int s)
+{
+ int l;
+ struct timeval tv;
+ int farlen;
+ struct sockaddr_in farAddr;
+ struct ntpPacketSmall packet;
+
+ if (i < 0)
+ tv.tv_sec = 80;
+ else
+ tv.tv_sec = 5;
+ tv.tv_usec = 0;
+ if (setsockopt (s, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof tv) < 0) {
+ printf ("Can't set socket receive timeout: %s\n", strerror (errno));
+ close (s);
+ return -1;
+ }
+ if (i >= 0) {
+ memset (&farAddr, 0, sizeof farAddr);
+ farAddr.sin_family = AF_INET;
+ farAddr.sin_port = htons (123);
+ farAddr.sin_addr = rtems_bsdnet_ntpserver[i];
+ memset (&packet, 0, sizeof packet);
+ packet.li_vn_mode = (3 << 3) | 3; /* NTP version 3, client */
+ l = sendto (s, &packet, sizeof packet, 0, (struct sockaddr *)&farAddr, sizeof farAddr);
+ if (l != sizeof packet) {
+ printf ("Can't send: %s\n", strerror (errno));
+ return -1;
+ }
+ }
+ farlen = sizeof farAddr;
+ i = recvfrom (s, &packet, sizeof packet, 0, (struct sockaddr *)&farAddr, &farlen);
+ if (i == 0)
+ printf ("Unexpected EOF");
+ if (i < 0) {
+ if ((errno == EWOULDBLOCK) || (errno == EAGAIN))
+ return -1;
+ printf ("Can't receive: %s\n", strerror (errno));
+ }
+ if ((i >= sizeof packet) && processPacket (&packet))
+ return 0;
+ return -1;
+}
+
+int
+rtems_bsdnet_synchronize_ntp (int interval, rtems_task_priority priority)
+{
+ int s;
+ int i;
+ int retry;
+ struct sockaddr_in myAddr;
+ int reuseFlag;
+ int ret;
+
+ if (interval != 0) {
+ printf ("Daemon-mode note yet supported.\n");
+ errno = EINVAL;
+ return -1;
+ }
+ s = socket (AF_INET, SOCK_DGRAM, 0);
+ if (s < 0) {
+ printf ("Can't create socket: %s\n", strerror (errno));
+ return -1;
+ }
+ reuseFlag = 1;
+ if (setsockopt (s, SOL_SOCKET, SO_REUSEADDR, (char *)&reuseFlag, sizeof reuseFlag) < 0) {
+ printf ("Can't set socket reuse: %s\n", strerror (errno));
+ close (s);
+ return -1;
+ }
+ memset (&myAddr, 0, sizeof myAddr);
+ myAddr.sin_family = AF_INET;
+ myAddr.sin_port = htons (123);
+ myAddr.sin_addr.s_addr = htonl (INADDR_ANY);
+ if (bind (s, (struct sockaddr *)&myAddr, sizeof myAddr) < 0) {
+ printf ("Can't bind socket: %s\n", strerror (errno));
+ close (s);
+ return -1;
+ }
+ ret = -1;
+ for (retry = 0 ; (ret == -1) && (retry < 5) ; retry++) {
+ /*
+ * If there's no server we just have to wait
+ * and hope that there's an NTP broadcast
+ * server out there somewhere.
+ */
+ if (rtems_bsdnet_ntpserver_count < 0) {
+ ret = tryServer (-1, s);
+ }
+ else {
+ for (i = 0 ; (ret == -1) && (i < rtems_bsdnet_ntpserver_count) ; i++) {
+ ret = tryServer (i, s);
+ }
+ }
+ }
+ close (s);
+ return ret;
+}
diff --git a/cpukit/libnetworking/lib/syslog.c b/cpukit/libnetworking/lib/syslog.c
new file mode 100644
index 0000000000..087dff7cfa
--- /dev/null
+++ b/cpukit/libnetworking/lib/syslog.c
@@ -0,0 +1,190 @@
+/*
+ * RTEMS version of syslog and associated routines
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <syslog.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <string.h>
+
+#include <unistd.h>
+
+static int LogStatus = LOG_CONS;
+static const char *LogTag = "syslog";
+static int LogFacility = LOG_USER;
+static int LogMask = 0xff;
+
+static int LogFd = -1;
+static rtems_id LogSemaphore;
+extern struct in_addr rtems_bsdnet_log_host_address;
+
+#define SYSLOG_PORT 514
+
+void
+syslog (int pri, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start (ap, fmt);
+ vsyslog (pri, fmt, ap);
+ va_end (ap);
+}
+
+/*
+ * FIXME: Should cbuf be static? It could be if we put the mutex
+ * around the entire body of this routine. Then we wouldn't
+ * have to worry about blowing stacks with a local variable
+ * that large. Could make cbuf bigger, too.
+ */
+void
+vsyslog (int pri, const char *fmt, va_list ap)
+{
+ int cnt;
+ char *cp;
+ char *msgp, cbuf[200];
+ int sent;
+
+ if (pri & ~(LOG_PRIMASK|LOG_FACMASK)) {
+ syslog (LOG_ERR|LOG_CONS|LOG_PERROR|LOG_PID,
+ "syslog: unknown facility/priority: %#x", pri);
+ pri &= LOG_PRIMASK|LOG_FACMASK;
+ }
+
+ if (!LOG_MASK(LOG_PRI(pri)) & LogMask)
+ return;
+
+ if ((pri & LOG_FACMASK) == 0)
+ pri |= LogFacility;
+
+ cnt = sprintf (cbuf, "<%d>", pri);
+ cp = msgp = cbuf + cnt;
+ if (LogTag) {
+ const char *lp = LogTag;
+ while ((*cp = *lp++) != '\0')
+ cp++;
+ }
+ if (LogStatus & LOG_PID) {
+ rtems_id tid;
+ rtems_task_ident (RTEMS_SELF, 0, &tid);
+ cnt = sprintf (cp, "[%#lx]", (unsigned long)tid);
+ cp += cnt;
+ }
+ if (LogTag) {
+ *cp++ = ':';
+ *cp++ = ' ';
+ }
+ cnt = vsprintf (cp, fmt, ap);
+ cnt += cp - cbuf;
+ if (cbuf[cnt-1] == '\n')
+ cbuf[--cnt] = '\0';
+
+ if (LogStatus & LOG_PERROR)
+ printf ("%s\n", cbuf);
+
+ /*
+ * Grab the mutex
+ */
+ sent = 0;
+ if ((rtems_bsdnet_log_host_address.s_addr != INADDR_ANY)
+ && (LogFd >= 0)
+ && (rtems_semaphore_obtain (LogSemaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT) == RTEMS_SUCCESSFUL)) {
+ /*
+ * Set the destination address/port
+ */
+ struct sockaddr_in farAddress;
+ farAddress.sin_family = AF_INET;
+ farAddress.sin_port = htons (SYSLOG_PORT);
+ farAddress.sin_addr = rtems_bsdnet_log_host_address;
+ memset (farAddress.sin_zero, '\0', sizeof farAddress.sin_zero);
+
+ /*
+ * Send the message
+ */
+ if (sendto (LogFd, cbuf, cnt, 0, (struct sockaddr *)&farAddress, sizeof farAddress) >= 0)
+ sent = 1;
+ rtems_semaphore_release (LogSemaphore);
+ }
+ if (!sent && (LogStatus & LOG_CONS) && !(LogStatus & LOG_PERROR))
+ printf ("%s\n", msgp);
+}
+
+void
+openlog (const char *ident, int logstat, int logfac)
+{
+ rtems_status_code sc;
+ struct sockaddr_in myAddress;
+
+ if (ident != NULL)
+ LogTag = ident;
+ LogStatus = logstat;
+ if (logfac != 0 && (logfac & ~LOG_FACMASK) == 0)
+ LogFacility = logfac;
+
+ /*
+ * Create the socket
+ */
+ if ((LogFd = socket (AF_INET, SOCK_DGRAM, 0)) < 0) {
+ printf ("Can't create syslog socket: %d\n", errno);
+ return;
+ }
+
+ /*
+ * Bind socket to name
+ */
+ myAddress.sin_family = AF_INET;
+ myAddress.sin_addr.s_addr = INADDR_ANY;
+ myAddress.sin_port = 0;
+ memset (myAddress.sin_zero, '\0', sizeof myAddress.sin_zero);
+ if (bind (LogFd, (struct sockaddr *)&myAddress, sizeof (myAddress)) < 0) {
+ close (LogFd);
+ LogFd = -1;
+ printf ("Can't bind syslog socket: %d\n", errno);
+ return;
+ }
+
+ /*
+ * Create the mutex
+ */
+ sc = rtems_semaphore_create (rtems_build_name('s', 'L', 'o', 'g'),
+ 1,
+ RTEMS_PRIORITY |
+ RTEMS_BINARY_SEMAPHORE |
+ RTEMS_INHERIT_PRIORITY |
+ RTEMS_NO_PRIORITY_CEILING |
+ RTEMS_LOCAL,
+ 0,
+ &LogSemaphore);
+ if (sc != RTEMS_SUCCESSFUL) {
+ printf ("Can't create syslog seamphore: %d\n", sc);
+ close (LogFd);
+ LogFd = -1;
+ }
+}
+
+void
+closelog(void)
+{
+ if (LogFd >= 0) {
+ close (LogFd);
+ LogFd = -1;
+ rtems_semaphore_delete (LogSemaphore);
+ }
+}
+
+int
+setlogmask (int pmask)
+{
+ int omask;
+
+ omask = LogMask;
+ if (pmask != 0)
+ LogMask = pmask;
+ return (omask);
+}
diff --git a/cpukit/libnetworking/lib/tftpDriver.c b/cpukit/libnetworking/lib/tftpDriver.c
new file mode 100644
index 0000000000..9b60eafc90
--- /dev/null
+++ b/cpukit/libnetworking/lib/tftpDriver.c
@@ -0,0 +1,1049 @@
+/*
+ * vim: set expandtab tabstop=4 shiftwidth=4 ai :
+ *
+ * Trivial File Transfer Protocol (RFC 1350)
+ *
+ * Transfer file to/from remote host
+ *
+ * W. Eric Norum
+ * Saskatchewan Accelerator Laboratory
+ * University of Saskatchewan
+ * Saskatoon, Saskatchewan, CANADA
+ * eric@skatter.usask.ca
+ *
+ * $Id$
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <malloc.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+#include <rtems/rtems_bsdnet.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#ifdef RTEMS_TFTP_DRIVER_DEBUG
+int rtems_tftp_driver_debug = 1;
+#endif
+
+/*
+ * Range of UDP ports to try
+ */
+#define UDP_PORT_BASE 3180
+
+/*
+ * Pathname prefix
+ */
+#define TFTP_PATHNAME_PREFIX "/TFTP/"
+
+/*
+ * Root node_access value
+ * By using the address of a local static variable
+ * we ensure a unique value for this identifier.
+ */
+#define ROOT_NODE_ACCESS (&tftp_mutex)
+
+/*
+ * Default limits
+ */
+#define PACKET_FIRST_TIMEOUT_MILLISECONDS 400
+#define PACKET_TIMEOUT_MILLISECONDS 6000
+#define OPEN_RETRY_LIMIT 10
+#define IO_RETRY_LIMIT 10
+
+/*
+ * TFTP opcodes
+ */
+#define TFTP_OPCODE_RRQ 1
+#define TFTP_OPCODE_WRQ 2
+#define TFTP_OPCODE_DATA 3
+#define TFTP_OPCODE_ACK 4
+#define TFTP_OPCODE_ERROR 5
+
+/*
+ * Largest data transfer
+ */
+#define TFTP_BUFSIZE 512
+
+/*
+ * Packets transferred between machines
+ */
+union tftpPacket {
+ /*
+ * RRQ/WRQ packet
+ */
+ struct tftpRWRQ {
+ uint16_t opcode;
+ char filename_mode[TFTP_BUFSIZE];
+ } tftpRWRQ;
+
+ /*
+ * DATA packet
+ */
+ struct tftpDATA {
+ uint16_t opcode;
+ uint16_t blocknum;
+ uint8_t data[TFTP_BUFSIZE];
+ } tftpDATA;
+
+ /*
+ * ACK packet
+ */
+ struct tftpACK {
+ uint16_t opcode;
+ uint16_t blocknum;
+ } tftpACK;
+
+ /*
+ * ERROR packet
+ */
+ struct tftpERROR {
+ uint16_t opcode;
+ uint16_t errorCode;
+ char errorMessage[TFTP_BUFSIZE];
+ } tftpERROR;
+};
+
+/*
+ * State of each TFTP stream
+ */
+struct tftpStream {
+ /*
+ * Buffer for storing most recently-received packet
+ */
+ union tftpPacket pkbuf;
+
+ /*
+ * Last block number transferred
+ */
+ uint16_t blocknum;
+
+ /*
+ * Data transfer socket
+ */
+ int socket;
+ struct sockaddr_in myAddress;
+ struct sockaddr_in farAddress;
+
+ /*
+ * Indices into buffer
+ */
+ int nleft;
+ int nused;
+
+ /*
+ * Flags
+ */
+ int firstReply;
+ int eof;
+ int writing;
+};
+
+/*
+ * Number of streams open at the same time
+ */
+static rtems_id tftp_mutex;
+static int nStreams;
+static struct tftpStream ** volatile tftpStreams;
+
+typedef const char *tftp_node;
+extern rtems_filesystem_operations_table rtems_tftp_ops;
+extern rtems_filesystem_file_handlers_r rtems_tftp_handlers;
+
+/*
+ * Direct copy from the IMFS. Look at this.
+ */
+
+rtems_filesystem_limits_and_options_t rtems_tftp_limits_and_options = {
+ 5, /* link_max */
+ 6, /* max_canon */
+ 7, /* max_input */
+ 255, /* name_max */
+ 255, /* path_max */
+ 2, /* pipe_buf */
+ 1, /* posix_async_io */
+ 2, /* posix_chown_restrictions */
+ 3, /* posix_no_trunc */
+ 4, /* posix_prio_io */
+ 5, /* posix_sync_io */
+ 6 /* posix_vdisable */
+};
+
+static int rtems_tftp_mount_me(
+ rtems_filesystem_mount_table_entry_t *temp_mt_entry
+)
+{
+ rtems_status_code sc;
+
+ temp_mt_entry->mt_fs_root.handlers = &rtems_tftp_handlers;
+ temp_mt_entry->mt_fs_root.ops = &rtems_tftp_ops;
+
+ /*
+ * We have no tftp filesystem specific data to maintain. This
+ * filesystem may only be mounted ONCE.
+ *
+ * And we maintain no real filesystem nodes, so there is no real root.
+ */
+
+ temp_mt_entry->fs_info = NULL;
+ temp_mt_entry->mt_fs_root.node_access = ROOT_NODE_ACCESS;
+
+ /*
+ * These need to be looked at for full POSIX semantics.
+ */
+
+ temp_mt_entry->pathconf_limits_and_options = rtems_tftp_limits_and_options;
+
+
+ /*
+ * Now allocate a semaphore for mutual exclusion.
+ *
+ * NOTE: This could be in an fsinfo for this filesystem type.
+ */
+
+ sc = rtems_semaphore_create (
+ rtems_build_name('T', 'F', 'T', 'P'),
+ 1,
+ RTEMS_FIFO |
+ RTEMS_BINARY_SEMAPHORE |
+ RTEMS_NO_INHERIT_PRIORITY |
+ RTEMS_NO_PRIORITY_CEILING |
+ RTEMS_LOCAL,
+ 0,
+ &tftp_mutex
+ );
+
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_set_errno_and_return_minus_one( ENOMEM );
+
+ return 0;
+}
+
+/*
+ * Initialize the TFTP driver
+ */
+
+int rtems_bsdnet_initialize_tftp_filesystem ()
+{
+ int status;
+ rtems_filesystem_mount_table_entry_t *entry;
+
+ status = mkdir( TFTP_PATHNAME_PREFIX, S_IRWXU | S_IRWXG | S_IRWXO );
+ if ( status == -1 )
+ return status;
+
+ status = mount(
+ &entry,
+ &rtems_tftp_ops,
+ RTEMS_FILESYSTEM_READ_WRITE,
+ NULL,
+ TFTP_PATHNAME_PREFIX
+ );
+
+ if ( status )
+ perror( "TFTP mount failed" );
+
+ return status;
+}
+
+/*
+ * Map error message
+ */
+static int
+tftpErrno (struct tftpStream *tp)
+{
+ unsigned int tftpError;
+ static const int errorMap[] = {
+ EINVAL,
+ ENOENT,
+ EPERM,
+ ENOSPC,
+ EINVAL,
+ ENXIO,
+ EEXIST,
+ ESRCH,
+ };
+
+ tftpError = ntohs (tp->pkbuf.tftpERROR.errorCode);
+ if (tftpError < (sizeof errorMap / sizeof errorMap[0]))
+ return errorMap[tftpError];
+ else
+ return 1000 + tftpError;
+}
+
+/*
+ * Send a message to make the other end shut up
+ */
+static void
+sendStifle (struct tftpStream *tp, struct sockaddr_in *to)
+{
+ int len;
+ struct {
+ uint16_t opcode;
+ uint16_t errorCode;
+ char errorMessage[12];
+ } msg;
+
+ /*
+ * Create the error packet (Unknown transfer ID).
+ */
+ msg.opcode = htons (TFTP_OPCODE_ERROR);
+ msg.errorCode = htons (5);
+ len = sizeof msg.opcode + sizeof msg.errorCode + 1;
+ len += sprintf (msg.errorMessage, "GO AWAY");
+
+ /*
+ * Send it
+ */
+ sendto (tp->socket, (char *)&msg, len, 0, (struct sockaddr *)to, sizeof *to);
+}
+
+/*
+ * Wait for a data packet
+ */
+static int
+getPacket (struct tftpStream *tp, int retryCount)
+{
+ int len;
+ struct timeval tv;
+
+ if (retryCount == 0) {
+ tv.tv_sec = PACKET_FIRST_TIMEOUT_MILLISECONDS / 1000;
+ tv.tv_usec = (PACKET_FIRST_TIMEOUT_MILLISECONDS % 1000) * 1000;
+ }
+ else {
+ tv.tv_sec = PACKET_TIMEOUT_MILLISECONDS / 1000;
+ tv.tv_usec = (PACKET_TIMEOUT_MILLISECONDS % 1000) * 1000;
+ }
+ setsockopt (tp->socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof tv);
+ for (;;) {
+ union {
+ struct sockaddr s;
+ struct sockaddr_in i;
+ } from;
+ int fromlen = sizeof from;
+ len = recvfrom (tp->socket, (char *)&tp->pkbuf,
+ sizeof tp->pkbuf, 0,
+ &from.s, &fromlen);
+ if (len < 0)
+ break;
+ if (from.i.sin_addr.s_addr == tp->farAddress.sin_addr.s_addr) {
+ if (tp->firstReply) {
+ tp->firstReply = 0;
+ tp->farAddress.sin_port = from.i.sin_port;
+ }
+ if (tp->farAddress.sin_port == from.i.sin_port)
+ break;
+ }
+
+ /*
+ * Packet is from someone with whom we are
+ * not interested. Tell them to go away.
+ */
+ sendStifle (tp, &from.i);
+ }
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ setsockopt (tp->socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof tv);
+#ifdef RTEMS_TFTP_DRIVER_DEBUG
+ if (rtems_tftp_driver_debug) {
+ if (len >= (int) sizeof tp->pkbuf.tftpACK) {
+ int opcode = ntohs (tp->pkbuf.tftpDATA.opcode);
+ switch (opcode) {
+ default:
+ printf ("TFTP: OPCODE %d\n", opcode);
+ break;
+
+ case TFTP_OPCODE_DATA:
+ printf ("TFTP: RECV %d\n", ntohs (tp->pkbuf.tftpDATA.blocknum));
+ break;
+
+ case TFTP_OPCODE_ACK:
+ printf ("TFTP: GOT ACK %d\n", ntohs (tp->pkbuf.tftpACK.blocknum));
+ break;
+ }
+ }
+ else {
+ printf ("TFTP: %d-byte packet\n", len);
+ }
+ }
+#endif
+ return len;
+}
+
+/*
+ * Send an acknowledgement
+ */
+static int
+sendAck (struct tftpStream *tp)
+{
+#ifdef RTEMS_TFTP_DRIVER_DEBUG
+ if (rtems_tftp_driver_debug)
+ printf ("TFTP: ACK %d\n", tp->blocknum);
+#endif
+
+ /*
+ * Create the acknowledgement
+ */
+ tp->pkbuf.tftpACK.opcode = htons (TFTP_OPCODE_ACK);
+ tp->pkbuf.tftpACK.blocknum = htons (tp->blocknum);
+
+ /*
+ * Send it
+ */
+ if (sendto (tp->socket, (char *)&tp->pkbuf, sizeof tp->pkbuf.tftpACK, 0,
+ (struct sockaddr *)&tp->farAddress,
+ sizeof tp->farAddress) < 0)
+ return errno;
+ return 0;
+}
+
+/*
+ * Release a stream and clear the pointer to it
+ */
+static void
+releaseStream (int s)
+{
+ rtems_semaphore_obtain (tftp_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ free (tftpStreams[s]);
+ tftpStreams[s] = NULL;
+ rtems_semaphore_release (tftp_mutex);
+}
+
+static int rtems_tftp_evaluate_for_make(
+ const char *path, /* IN */
+ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
+ const char **name /* OUT */
+)
+{
+ pathloc->node_access = NULL;
+ rtems_set_errno_and_return_minus_one( EIO );
+}
+
+/*
+ * Convert a path to canonical form
+ */
+static void
+fixPath (char *path)
+{
+ char *inp, *outp, *base;
+
+ outp = inp = path;
+ base = NULL;
+ for (;;) {
+ if (inp[0] == '.') {
+ if (inp[1] == '\0')
+ break;
+ if (inp[1] == '/') {
+ inp += 2;
+ continue;
+ }
+ if (inp[1] == '.') {
+ if (inp[2] == '\0') {
+ if ((base != NULL) && (outp > base)) {
+ outp--;
+ while ((outp > base) && (outp[-1] != '/'))
+ outp--;
+ }
+ break;
+ }
+ if (inp[2] == '/') {
+ inp += 3;
+ if (base == NULL)
+ continue;
+ if (outp > base) {
+ outp--;
+ while ((outp > base) && (outp[-1] != '/'))
+ outp--;
+ }
+ continue;
+ }
+ }
+ }
+ if (base == NULL)
+ base = inp;
+ while (inp[0] != '/') {
+ if ((*outp++ = *inp++) == '\0')
+ return;
+ }
+ *outp++ = '/';
+ while (inp[0] == '/')
+ inp++;
+ }
+ *outp = '\0';
+ return;
+}
+
+static int rtems_tftp_eval_path(
+ const char *pathname, /* IN */
+ int flags, /* IN */
+ rtems_filesystem_location_info_t *pathloc /* IN/OUT */
+)
+{
+ pathloc->handlers = &rtems_tftp_handlers;
+
+ /*
+ * Hack to provide the illusion of directories inside the TFTP file system.
+ * Paths ending in a / are assumed to be directories.
+ */
+ if (pathname[strlen(pathname)-1] == '/') {
+ int isRelative = (pathloc->node_access != ROOT_NODE_ACCESS);
+ char *cp;
+
+ /*
+ * Reject attempts to open() directories
+ */
+ if (flags & RTEMS_LIBIO_PERMS_RDWR)
+ rtems_set_errno_and_return_minus_one( EISDIR );
+ if (isRelative) {
+ cp = malloc (strlen(pathloc->node_access)+strlen(pathname)+1);
+ if (cp == NULL)
+ rtems_set_errno_and_return_minus_one( ENOMEM );
+ strcpy (cp, pathloc->node_access);
+ strcat (cp, pathname);
+ }
+ else {
+ cp = strdup (pathname);
+ if (cp == NULL)
+ rtems_set_errno_and_return_minus_one( ENOMEM );
+ }
+ fixPath (cp);
+ pathloc->node_access = cp;
+ return 0;
+ }
+ if (pathloc->node_access != ROOT_NODE_ACCESS)
+ pathloc->node_access = 0;
+
+ /*
+ * Reject it if it's not read-only or write-only.
+ */
+ flags &= RTEMS_LIBIO_PERMS_READ | RTEMS_LIBIO_PERMS_WRITE;
+ if ((flags != RTEMS_LIBIO_PERMS_READ) && (flags != RTEMS_LIBIO_PERMS_WRITE) )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ return 0;
+}
+
+/*
+ * The routine which does most of the work for the IMFS open handler
+ */
+static int rtems_tftp_open_worker(
+ rtems_libio_t *iop,
+ char *full_path_name,
+ uint32_t flags,
+ uint32_t mode
+)
+{
+ struct tftpStream *tp;
+ int retryCount;
+ struct in_addr farAddress;
+ int s;
+ int len;
+ char *cp1;
+ char *cp2;
+ char *remoteFilename;
+ rtems_interval now;
+ rtems_status_code sc;
+ char *hostname;
+
+ /*
+ * Extract the host name component
+ */
+ cp2 = full_path_name;
+ while (*cp2 == '/')
+ cp2++;
+ hostname = cp2;
+ while (*cp2 != '/') {
+ if (*cp2 == '\0')
+ return ENOENT;
+ cp2++;
+ }
+ *cp2++ = '\0';
+
+ /*
+ * Convert hostname to Internet address
+ */
+ if (strcmp (hostname, "BOOTP_HOST") == 0)
+ farAddress = rtems_bsdnet_bootp_server_address;
+ else
+ farAddress.s_addr = inet_addr (hostname);
+ if ((farAddress.s_addr == 0) || (farAddress.s_addr == ~0))
+ return ENOENT;
+
+ /*
+ * Extract file pathname component
+ */
+ while (*cp2 == '/')
+ cp2++;
+ if (strcmp (cp2, "BOOTP_FILE") == 0) {
+ cp2 = rtems_bsdnet_bootp_boot_file_name;
+ while (*cp2 == '/')
+ cp2++;
+ }
+ if (*cp2 == '\0')
+ return ENOENT;
+ remoteFilename = cp2;
+ if (strlen (remoteFilename) > (TFTP_BUFSIZE - 10))
+ return ENOENT;
+
+ /*
+ * Find a free stream
+ */
+ sc = rtems_semaphore_obtain (tftp_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ return EBUSY;
+ for (s = 0 ; s < nStreams ; s++) {
+ if (tftpStreams[s] == NULL)
+ break;
+ }
+ if (s == nStreams) {
+ /*
+ * Reallocate stream pointers
+ * Guard against the case where realloc() returns NULL.
+ */
+ struct tftpStream **np;
+
+ np = realloc (tftpStreams, ++nStreams * sizeof *tftpStreams);
+ if (np == NULL) {
+ rtems_semaphore_release (tftp_mutex);
+ return ENOMEM;
+ }
+ tftpStreams = np;
+ }
+ tp = tftpStreams[s] = malloc (sizeof (struct tftpStream));
+ rtems_semaphore_release (tftp_mutex);
+ if (tp == NULL)
+ return ENOMEM;
+ iop->data0 = s;
+ iop->data1 = tp;
+
+ /*
+ * Create the socket
+ */
+ if ((tp->socket = socket (AF_INET, SOCK_DGRAM, 0)) < 0) {
+ releaseStream (s);
+ return ENOMEM;
+ }
+
+ /*
+ * Bind the socket to a local address
+ */
+ retryCount = 0;
+ rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
+ for (;;) {
+ int try = (now + retryCount) % 10;
+
+ tp->myAddress.sin_family = AF_INET;
+ tp->myAddress.sin_port = htons (UDP_PORT_BASE + nStreams * try + s);
+ tp->myAddress.sin_addr.s_addr = htonl (INADDR_ANY);
+ if (bind (tp->socket, (struct sockaddr *)&tp->myAddress, sizeof tp->myAddress) >= 0)
+ break;
+ if (++retryCount == 10) {
+ close (tp->socket);
+ releaseStream (s);
+ return EBUSY;
+ }
+ }
+
+ /*
+ * Set the UDP destination to the TFTP server
+ * port on the remote machine.
+ */
+ tp->farAddress.sin_family = AF_INET;
+ tp->farAddress.sin_addr = farAddress;
+ tp->farAddress.sin_port = htons (69);
+
+ /*
+ * Start the transfer
+ */
+ tp->firstReply = 1;
+ retryCount = 0;
+ for (;;) {
+ /*
+ * Create the request
+ */
+ if ((flags & O_ACCMODE) == O_RDONLY) {
+ tp->writing = 0;
+ tp->pkbuf.tftpRWRQ.opcode = htons (TFTP_OPCODE_RRQ);
+ }
+ else {
+ tp->writing = 1;
+ tp->pkbuf.tftpRWRQ.opcode = htons (TFTP_OPCODE_WRQ);
+ }
+ cp1 = (char *) tp->pkbuf.tftpRWRQ.filename_mode;
+ cp2 = (char *) remoteFilename;
+ while ((*cp1++ = *cp2++) != '\0')
+ continue;
+ cp2 = "octet";
+ while ((*cp1++ = *cp2++) != '\0')
+ continue;
+ len = cp1 - (char *)&tp->pkbuf.tftpRWRQ;
+
+ /*
+ * Send the request
+ */
+ if (sendto (tp->socket, (char *)&tp->pkbuf, len, 0,
+ (struct sockaddr *)&tp->farAddress,
+ sizeof tp->farAddress) < 0) {
+ close (tp->socket);
+ releaseStream (s);
+ return EIO;
+ }
+
+ /*
+ * Get reply
+ */
+ len = getPacket (tp, retryCount);
+ if (len >= (int) sizeof tp->pkbuf.tftpACK) {
+ int opcode = ntohs (tp->pkbuf.tftpDATA.opcode);
+ if (!tp->writing
+ && (opcode == TFTP_OPCODE_DATA)
+ && (ntohs (tp->pkbuf.tftpDATA.blocknum) == 1)) {
+ tp->nused = 0;
+ tp->blocknum = 1;
+ tp->nleft = len - 2 * sizeof (uint16_t );
+ tp->eof = (tp->nleft < TFTP_BUFSIZE);
+ if (sendAck (tp) != 0) {
+ close (tp->socket);
+ releaseStream (s);
+ return EIO;
+ }
+ break;
+ }
+ if (tp->writing
+ && (opcode == TFTP_OPCODE_ACK)
+ && (ntohs (tp->pkbuf.tftpACK.blocknum) == 0)) {
+ tp->nused = 0;
+ tp->blocknum = 1;
+ break;
+ }
+ if (opcode == TFTP_OPCODE_ERROR) {
+ int e = tftpErrno (tp);
+ close (tp->socket);
+ releaseStream (s);
+ return e;
+ }
+ }
+
+ /*
+ * Keep trying
+ */
+ if (++retryCount >= OPEN_RETRY_LIMIT) {
+ close (tp->socket);
+ releaseStream (s);
+ return EIO;
+ }
+ }
+ return 0;
+}
+
+/*
+ * The IMFS open handler
+ */
+static int rtems_tftp_open(
+ rtems_libio_t *iop,
+ const char *new_name,
+ uint32_t flags,
+ uint32_t mode
+)
+{
+ char *full_path_name;
+ char *s1;
+ int err;
+
+ /*
+ * Tack the `current directory' on to relative paths.
+ * We know that the current directory ends in a / character.
+ */
+ if (*new_name == '/') {
+ /*
+ * Skip the TFTP filesystem prefix.
+ */
+ int len = strlen (TFTP_PATHNAME_PREFIX);
+ if (strncmp (new_name, TFTP_PATHNAME_PREFIX, len))
+ return ENOENT;
+ new_name += len;
+ s1 = "";
+ }
+ else {
+ s1 = rtems_filesystem_current.node_access;
+ }
+ full_path_name = malloc (strlen (s1) + strlen (new_name) + 1);
+ if (full_path_name == NULL)
+ return ENOMEM;
+ strcpy (full_path_name, s1);
+ strcat (full_path_name, new_name);
+ fixPath (full_path_name);
+ err = rtems_tftp_open_worker (iop, full_path_name, flags, mode);
+ free (full_path_name);
+ return err;
+}
+
+/*
+ * Read from a TFTP stream
+ */
+static ssize_t rtems_tftp_read(
+ rtems_libio_t *iop,
+ void *buffer,
+ uint32_t count
+)
+{
+ char *bp;
+ struct tftpStream *tp = iop->data1;
+ int retryCount;
+ int nwant;
+
+
+ /*
+ * Read till user request is satisfied or EOF is reached
+ */
+ bp = buffer;
+ nwant = count;
+ while (nwant) {
+ if (tp->nleft) {
+ int ncopy;
+ if (nwant < tp->nleft)
+ ncopy = nwant;
+ else
+ ncopy = tp->nleft;
+ memcpy (bp, &tp->pkbuf.tftpDATA.data[tp->nused], ncopy);
+ tp->nused += ncopy;
+ tp->nleft -= ncopy;
+ bp += ncopy;
+ nwant -= ncopy;
+ if (nwant == 0)
+ break;
+ }
+ if (tp->eof)
+ break;
+
+ /*
+ * Wait for the next packet
+ */
+ retryCount = 0;
+ for (;;) {
+ int len = getPacket (tp, retryCount);
+ if (len >= (int)sizeof tp->pkbuf.tftpACK) {
+ int opcode = ntohs (tp->pkbuf.tftpDATA.opcode);
+ uint16_t nextBlock = tp->blocknum + 1;
+ if ((opcode == TFTP_OPCODE_DATA)
+ && (ntohs (tp->pkbuf.tftpDATA.blocknum) == nextBlock)) {
+ tp->nused = 0;
+ tp->nleft = len - 2 * sizeof (uint16_t );
+ tp->eof = (tp->nleft < TFTP_BUFSIZE);
+ tp->blocknum++;
+ if (sendAck (tp) != 0)
+ rtems_set_errno_and_return_minus_one( EIO );
+ break;
+ }
+ if (opcode == TFTP_OPCODE_ERROR)
+ rtems_set_errno_and_return_minus_one( tftpErrno (tp) );
+ }
+
+ /*
+ * Keep trying?
+ */
+ if (++retryCount == IO_RETRY_LIMIT)
+ rtems_set_errno_and_return_minus_one( EIO );
+ if (sendAck (tp) != 0)
+ rtems_set_errno_and_return_minus_one( EIO );
+ }
+ }
+ return count - nwant;
+}
+
+/*
+ * Flush a write buffer and wait for acknowledgement
+ */
+static int rtems_tftp_flush ( struct tftpStream *tp )
+{
+ int wlen, rlen;
+ int retryCount = 0;
+
+ wlen = tp->nused + 2 * sizeof (uint16_t );
+ for (;;) {
+ tp->pkbuf.tftpDATA.opcode = htons (TFTP_OPCODE_DATA);
+ tp->pkbuf.tftpDATA.blocknum = htons (tp->blocknum);
+#ifdef RTEMS_TFTP_DRIVER_DEBUG
+ if (rtems_tftp_driver_debug)
+ printf ("TFTP: SEND %d (%d)\n", tp->blocknum, tp->nused);
+#endif
+ if (sendto (tp->socket, (char *)&tp->pkbuf, wlen, 0,
+ (struct sockaddr *)&tp->farAddress,
+ sizeof tp->farAddress) < 0)
+ return EIO;
+ rlen = getPacket (tp, retryCount);
+ /*
+ * Our last packet won't necessarily be acknowledged!
+ */
+ if ((rlen < 0) && (tp->nused < sizeof tp->pkbuf.tftpDATA.data))
+ return 0;
+ if (rlen >= (int)sizeof tp->pkbuf.tftpACK) {
+ int opcode = ntohs (tp->pkbuf.tftpACK.opcode);
+ if ((opcode == TFTP_OPCODE_ACK)
+ && (ntohs (tp->pkbuf.tftpACK.blocknum) == tp->blocknum)) {
+ tp->nused = 0;
+ tp->blocknum++;
+ return 0;
+ }
+ if (opcode == TFTP_OPCODE_ERROR)
+ return tftpErrno (tp);
+ }
+
+ /*
+ * Keep trying?
+ */
+ if (++retryCount == IO_RETRY_LIMIT)
+ return EIO;
+ }
+}
+
+/*
+ * Close a TFTP stream
+ */
+static int rtems_tftp_close(
+ rtems_libio_t *iop
+)
+{
+ struct tftpStream *tp = iop->data1;;
+
+ if (tp->writing)
+ rtems_tftp_flush (tp);
+ if (!tp->eof && !tp->firstReply) {
+ /*
+ * Tell the other end to stop
+ */
+ rtems_interval ticksPerSecond;
+ sendStifle (tp, &tp->farAddress);
+ rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticksPerSecond);
+ rtems_task_wake_after (1 + ticksPerSecond / 10);
+ }
+ close (tp->socket);
+ releaseStream (iop->data0);
+ return RTEMS_SUCCESSFUL;
+}
+
+static ssize_t rtems_tftp_write(
+ rtems_libio_t *iop,
+ const void *buffer,
+ uint32_t count
+)
+{
+ const char *bp;
+ struct tftpStream *tp = iop->data1;
+ int nleft, nfree, ncopy;
+
+ /*
+ * Bail out if an error has occurred
+ */
+ if (!tp->writing)
+ return EIO;
+
+
+ /*
+ * Write till user request is satisfied
+ * Notice that the buffer is flushed as soon as it is filled rather
+ * than waiting for the next write or a close. This ensures that
+ * the flush in close writes a less than full buffer so the far
+ * end can detect the end-of-file condition.
+ */
+ bp = buffer;
+ nleft = count;
+ while (nleft) {
+ nfree = sizeof tp->pkbuf.tftpDATA.data - tp->nused;
+ if (nleft < nfree)
+ ncopy = nleft;
+ else
+ ncopy = nfree;
+ memcpy (&tp->pkbuf.tftpDATA.data[tp->nused], bp, ncopy);
+ tp->nused += ncopy;
+ nleft -= ncopy;
+ bp += ncopy;
+ if (tp->nused == sizeof tp->pkbuf.tftpDATA.data) {
+ int e = rtems_tftp_flush (tp);
+ if (e) {
+ tp->writing = 0;
+ rtems_set_errno_and_return_minus_one (e);
+ }
+ }
+ }
+ return count;
+}
+
+/*
+ * Dummy version to let fopen(xxxx,"w") work properly.
+ */
+static int rtems_tftp_ftruncate(
+ rtems_libio_t *iop,
+ off_t count
+)
+{
+ return 0;
+}
+
+static rtems_filesystem_node_types_t rtems_tftp_node_type(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+)
+{
+ if ((pathloc->node_access == NULL)
+ || (pathloc->node_access == ROOT_NODE_ACCESS))
+ return RTEMS_FILESYSTEM_MEMORY_FILE;
+ return RTEMS_FILESYSTEM_DIRECTORY;
+}
+
+static int rtems_tftp_free_node_info(
+ rtems_filesystem_location_info_t *pathloc /* IN */
+)
+{
+ if (pathloc->node_access && (pathloc->node_access != ROOT_NODE_ACCESS)) {
+ free (pathloc->node_access);
+ pathloc->node_access = NULL;
+ }
+ return 0;
+}
+
+
+rtems_filesystem_operations_table rtems_tftp_ops = {
+ rtems_tftp_eval_path, /* eval_path */
+ rtems_tftp_evaluate_for_make, /* evaluate_for_make */
+ NULL, /* link */
+ NULL, /* unlink */
+ rtems_tftp_node_type, /* node_type */
+ NULL, /* mknod */
+ NULL, /* chown */
+ rtems_tftp_free_node_info, /* freenodinfo */
+ NULL, /* mount */
+ rtems_tftp_mount_me, /* initialize */
+ NULL, /* unmount */
+ NULL, /* fsunmount */
+ NULL, /* utime, */
+ NULL, /* evaluate_link */
+ NULL, /* symlink */
+ NULL, /* readlin */
+};
+
+rtems_filesystem_file_handlers_r rtems_tftp_handlers = {
+ rtems_tftp_open, /* open */
+ rtems_tftp_close, /* close */
+ rtems_tftp_read, /* read */
+ rtems_tftp_write, /* write */
+ NULL, /* ioctl */
+ NULL, /* lseek */
+ NULL, /* fstat */
+ NULL, /* fchmod */
+ rtems_tftp_ftruncate, /* ftruncate */
+ NULL, /* fpathconf */
+ NULL, /* fsync */
+ NULL, /* fdatasync */
+ NULL, /* fcntl */
+ NULL /* rmnod */
+};
diff --git a/cpukit/libnetworking/libc/addr2ascii.3 b/cpukit/libnetworking/libc/addr2ascii.3
new file mode 100644
index 0000000000..10c839ea74
--- /dev/null
+++ b/cpukit/libnetworking/libc/addr2ascii.3
@@ -0,0 +1,217 @@
+.\"
+.\" Copyright 1996 Massachusetts Institute of Technology
+.\"
+.\" Permission to use, copy, modify, and distribute this software and
+.\" its documentation for any purpose and without fee is hereby
+.\" granted, provided that both the above copyright notice and this
+.\" permission notice appear in all copies, that both the above
+.\" copyright notice and this permission notice appear in all
+.\" supporting documentation, and that the name of M.I.T. not be used
+.\" in advertising or publicity pertaining to distribution of the
+.\" software without specific, written prior permission. M.I.T. makes
+.\" no representations about the suitability of this software for any
+.\" purpose. It is provided "as is" without express or implied
+.\" warranty.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
+.\" ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
+.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
+.\" SHALL M.I.T. 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.
+.\"
+.\" $ANA: addr2ascii.3,v 1.1 1996/06/13 18:41:46 wollman Exp $
+.\" $Id$
+.\"
+.Dd June 13, 1996
+.Dt ADDR2ASCII 3
+.Os
+.Sh NAME
+.Nm addr2ascii ,
+.Nm ascii2addr
+.Nd Generic address formatting routines
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <netinet/in.h>
+.Fd #include <arpa/inet.h>
+.Ft "char *"
+.Fn addr2ascii "int af" "const void *addrp" "int len" "char *buf"
+.Ft int
+.Fn ascii2addr "int af" "const char *ascii" "void *result"
+.Sh DESCRIPTION
+The routines
+.Fn addr2ascii
+and
+.Fn ascii2addr
+are used to convert network addresses between binary form and a
+printable form appropriate to the address family. Both functions take
+an
+.Fa af
+argument, specifying the address family to be used in the conversion
+process.
+(Currently, only the
+.Dv AF_INET
+and
+.Dv AF_LINK
+address families are supported.)
+.Pp
+The
+.Fn addr2ascii
+function
+is used to convert binary, network-format addresses into printable
+form. In addition to
+.Fa af ,
+there are three other arguments. The
+.Fa addrp
+argument is a pointer to the network address to be converted.
+The
+.Fa len
+argument is the length of the address. The
+.Fa buf
+argument is an optional pointer to a caller-allocated buffer to hold
+the result; if a null pointer is passed,
+.Fn addr2ascii
+uses a statically-allocated buffer.
+.Pp
+The
+.Fn ascii2addr
+function performs the inverse operation to
+.Fn addr2ascii .
+In addition to
+.Fa af ,
+it takes two parameters,
+.Fa ascii
+and
+.Fa result .
+The
+.Fa ascii
+parameter is a pointer to the string which is to be converted into
+binary. The
+.Fa result
+parameter is a pointer to an appropriate network address structure for
+the specified family.
+.Pp
+The following gives the appropriate structure to use for binary
+addresses in the specified family:
+.Pp
+.Bl -tag -width AF_INETxxxx -compact
+.It Dv AF_INET
+.Li struct in_addr
+.Pq in Aq Pa netinet/in.h
+.It Dv AF_LINK
+.Li struct sockaddr_dl
+.Pq in Aq Pa net/if_dl.h
+.\" .It Dv AF_INET6
+.\" .Li struct in6_addr
+.\" .Pq in Aq Pa netinet6/in6.h
+.El
+.Sh RETURN VALUES
+The
+.Fn addr2ascii
+function returns the address of the buffer it was passed, or a static
+buffer if the a null pointer was passed; on failure, it returns a null
+pointer.
+The
+.Fn ascii2addr
+function returns the length of the binary address in bytes, or -1 on
+failure.
+.Sh EXAMPLES
+The
+.Xr inet 3
+functions
+.Fn inet_ntoa
+and
+.Fn inet_aton
+could be implemented thusly:
+.Bd -literal -offset indent
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+char *
+inet_ntoa(struct in_addr addr)
+{
+ return addr2ascii(AF_INET, &addr, sizeof addr, 0);
+}
+
+int
+inet_aton(const char *ascii, struct in_addr *addr)
+{
+ return (ascii2addr(AF_INET, ascii, addr)
+ == sizeof(*addr));
+}
+.Ed
+.Pp
+In actuality, this cannot be done because
+.Fn addr2ascii
+and
+.Fn ascii2addr
+are implemented in terms of the
+.Xr inet 3
+functions, rather than the other way around.
+.Sh ERRORS
+When a failure is returned,
+.Li errno
+is set to one of the following values:
+.Bl -tag -width [EPROTONOSUPPORT]
+.It Bq Er ENAMETOOLONG
+The
+.Fn addr2ascii
+routine was passed a
+.Fa len
+parameter which was inappropriate for the address family given by
+.Fa af .
+.It Bq Er EPROTONOSUPPORT
+Either routine was passed an
+.Fa af
+parameter other than
+.Dv AF_INET
+or
+.Dv AF_LINK .
+.It Bq Er EINVAL
+The string passed to
+.Fn ascii2addr
+was improperly formatted for address family
+.Fa af .
+.El
+.Sh SEE ALSO
+.Xr inet 3 ,
+.Xr linkaddr 3 ,
+.Xr inet 4
+.Sh HISTORY
+An interface close to this one was originally suggested by Craig
+Partridge. This particular interface originally appeared in the
+.Tn INRIA
+.Tn IPv6
+implementation.
+.Sh AUTHORS
+Code and documentation by
+.An Garrett A. Wollman ,
+MIT Laboratory for Computer Science.
+.Sh BUGS
+The original implementations supported IPv6. This support should
+eventually be resurrected. The
+.Tn NRL
+implementation also included support for the
+.Dv AF_ISO
+and
+.Dv AF_NS
+address families.
+.Pp
+The genericity of this interface is somewhat questionable. A truly
+generic interface would provide a means for determining the length of
+the buffer to be used so that it could be dynamically allocated, and
+would always require a
+.Dq Li "struct sockaddr"
+to hold the binary address. Unfortunately, this is incompatible with existing
+practice. This limitation means that a routine for printing network
+addresses from arbitrary address families must still have internal
+knowledge of the maximum buffer length needed and the appropriate part
+of the address to use as the binary address.
diff --git a/cpukit/libnetworking/libc/addr2ascii.c b/cpukit/libnetworking/libc/addr2ascii.c
new file mode 100644
index 0000000000..dc651743b6
--- /dev/null
+++ b/cpukit/libnetworking/libc/addr2ascii.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright 1996 Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that both the above copyright notice and this
+ * permission notice appear in all copies, that both the above
+ * copyright notice and this permission notice appear in all
+ * supporting documentation, and that the name of M.I.T. not be used
+ * in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. M.I.T. makes
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
+ * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
+ * SHALL M.I.T. 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.
+ *
+ * $ANA: addr2ascii.c,v 1.1 1996/06/13 18:41:46 wollman Exp $
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <errno.h>
+#include <string.h>
+
+#include <net/if_dl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+/*-
+ * Convert a network address from binary to printable numeric format.
+ * This API is copied from INRIA's IPv6 implementation, but it is a
+ * bit bogus in two ways:
+ *
+ * 1) There is no value in passing both an address family and
+ * an address length; either one should imply the other,
+ * or we should be passing sockaddrs instead.
+ * 2) There should by contrast be /added/ a length for the buffer
+ * that we pass in, so that programmers are spared the need to
+ * manually calculate (read: ``guess'') the maximum length.
+ *
+ * Flash: the API is also the same in the NRL implementation, and seems to
+ * be some sort of standard, so we appear to be stuck with both the bad
+ * naming and the poor choice of arguments.
+ */
+char *
+addr2ascii(af, addrp, len, buf)
+ int af;
+ const void *addrp;
+ int len; /* should be size_t XXX */
+ char *buf; /* XXX should pass length of buffer */
+{
+ static char staticbuf[64]; /* 64 for AF_LINK > 16 for AF_INET */
+
+ if (!buf)
+ buf = staticbuf;
+
+ switch(af) {
+ case AF_INET:
+ if (len != sizeof(struct in_addr)) {
+ errno = ENAMETOOLONG;
+ return 0;
+ }
+ strcpy(buf, inet_ntoa(*(const struct in_addr *)addrp));
+ break;
+
+ case AF_LINK:
+ if (len != sizeof(struct sockaddr_dl)) {
+ errno = ENAMETOOLONG;
+ return 0;
+ }
+ strcpy(buf, link_ntoa((const struct sockaddr_dl *)addrp));
+ break;
+
+ default:
+ errno = EPROTONOSUPPORT;
+ return 0;
+ }
+ return buf;
+}
diff --git a/cpukit/libnetworking/libc/ascii2addr.c b/cpukit/libnetworking/libc/ascii2addr.c
new file mode 100644
index 0000000000..e140244737
--- /dev/null
+++ b/cpukit/libnetworking/libc/ascii2addr.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright 1996 Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that both the above copyright notice and this
+ * permission notice appear in all copies, that both the above
+ * copyright notice and this permission notice appear in all
+ * supporting documentation, and that the name of M.I.T. not be used
+ * in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. M.I.T. makes
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
+ * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
+ * SHALL M.I.T. 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.
+ *
+ * $ANA: ascii2addr.c,v 1.2 1996/06/13 18:46:02 wollman Exp $
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <errno.h>
+#include <string.h>
+
+#include <net/if_dl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+int
+ascii2addr(af, ascii, result)
+ int af;
+ const char *ascii;
+ void *result;
+{
+ struct in_addr *ina;
+ char strbuf[4*sizeof("123")]; /* long enough for V4 only */
+
+ switch(af) {
+ case AF_INET:
+ ina = result;
+ strbuf[0] = '\0';
+ strncat(strbuf, ascii, (sizeof strbuf)-1);
+ if (inet_aton(strbuf, ina))
+ return sizeof(struct in_addr);
+ errno = EINVAL;
+ break;
+
+ case AF_LINK:
+ link_addr(ascii, result);
+ /* oops... no way to detect failure */
+ return sizeof(struct sockaddr_dl);
+
+ default:
+ errno = EPROTONOSUPPORT;
+ break;
+ }
+
+ return -1;
+}
diff --git a/cpukit/libnetworking/libc/base64.c b/cpukit/libnetworking/libc/base64.c
new file mode 100644
index 0000000000..3017ccc01c
--- /dev/null
+++ b/cpukit/libnetworking/libc/base64.c
@@ -0,0 +1,318 @@
+/*
+ * Copyright (c) 1996, 1998 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ */
+
+/*
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software. No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#if !defined(__rtems__)
+#if !defined(LINT) && !defined(CODECENTER)
+static char rcsid[] = "$Id$";
+#endif /* not lint */
+#endif /* not rtems */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define Assert(Cond) if (!(Cond)) abort()
+
+static const char Base64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static const char Pad64 = '=';
+
+/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
+ The following encoding technique is taken from RFC 1521 by Borenstein
+ and Freed. It is reproduced here in a slightly edited form for
+ convenience.
+
+ A 65-character subset of US-ASCII is used, enabling 6 bits to be
+ represented per printable character. (The extra 65th character, "=",
+ is used to signify a special processing function.)
+
+ The encoding process represents 24-bit groups of input bits as output
+ strings of 4 encoded characters. Proceeding from left to right, a
+ 24-bit input group is formed by concatenating 3 8-bit input groups.
+ These 24 bits are then treated as 4 concatenated 6-bit groups, each
+ of which is translated into a single digit in the base64 alphabet.
+
+ Each 6-bit group is used as an index into an array of 64 printable
+ characters. The character referenced by the index is placed in the
+ output string.
+
+ Table 1: The Base64 Alphabet
+
+ Value Encoding Value Encoding Value Encoding Value Encoding
+ 0 A 17 R 34 i 51 z
+ 1 B 18 S 35 j 52 0
+ 2 C 19 T 36 k 53 1
+ 3 D 20 U 37 l 54 2
+ 4 E 21 V 38 m 55 3
+ 5 F 22 W 39 n 56 4
+ 6 G 23 X 40 o 57 5
+ 7 H 24 Y 41 p 58 6
+ 8 I 25 Z 42 q 59 7
+ 9 J 26 a 43 r 60 8
+ 10 K 27 b 44 s 61 9
+ 11 L 28 c 45 t 62 +
+ 12 M 29 d 46 u 63 /
+ 13 N 30 e 47 v
+ 14 O 31 f 48 w (pad) =
+ 15 P 32 g 49 x
+ 16 Q 33 h 50 y
+
+ Special processing is performed if fewer than 24 bits are available
+ at the end of the data being encoded. A full encoding quantum is
+ always completed at the end of a quantity. When fewer than 24 input
+ bits are available in an input group, zero bits are added (on the
+ right) to form an integral number of 6-bit groups. Padding at the
+ end of the data is performed using the '=' character.
+
+ Since all base64 input is an integral number of octets, only the
+ -------------------------------------------------
+ following cases can arise:
+
+ (1) the final quantum of encoding input is an integral
+ multiple of 24 bits; here, the final unit of encoded
+ output will be an integral multiple of 4 characters
+ with no "=" padding,
+ (2) the final quantum of encoding input is exactly 8 bits;
+ here, the final unit of encoded output will be two
+ characters followed by two "=" padding characters, or
+ (3) the final quantum of encoding input is exactly 16 bits;
+ here, the final unit of encoded output will be three
+ characters followed by one "=" padding character.
+ */
+
+int
+b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) {
+ size_t datalength = 0;
+ u_char input[3];
+ u_char output[4];
+ size_t i;
+
+ while (2 < srclength) {
+ input[0] = *src++;
+ input[1] = *src++;
+ input[2] = *src++;
+ srclength -= 3;
+
+ output[0] = input[0] >> 2;
+ output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
+ output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+ output[3] = input[2] & 0x3f;
+ Assert(output[0] < 64);
+ Assert(output[1] < 64);
+ Assert(output[2] < 64);
+ Assert(output[3] < 64);
+
+ if (datalength + 4 > targsize)
+ return (-1);
+ target[datalength++] = Base64[output[0]];
+ target[datalength++] = Base64[output[1]];
+ target[datalength++] = Base64[output[2]];
+ target[datalength++] = Base64[output[3]];
+ }
+
+ /* Now we worry about padding. */
+ if (0 != srclength) {
+ /* Get what's left. */
+ input[0] = input[1] = input[2] = '\0';
+ for (i = 0; i < srclength; i++)
+ input[i] = *src++;
+
+ output[0] = input[0] >> 2;
+ output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
+ output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+ Assert(output[0] < 64);
+ Assert(output[1] < 64);
+ Assert(output[2] < 64);
+
+ if (datalength + 4 > targsize)
+ return (-1);
+ target[datalength++] = Base64[output[0]];
+ target[datalength++] = Base64[output[1]];
+ if (srclength == 1)
+ target[datalength++] = Pad64;
+ else
+ target[datalength++] = Base64[output[2]];
+ target[datalength++] = Pad64;
+ }
+ if (datalength >= targsize)
+ return (-1);
+ target[datalength] = '\0'; /* Returned value doesn't count \0. */
+ return (datalength);
+}
+
+/* skips all whitespace anywhere.
+ converts characters, four at a time, starting at (or after)
+ src from base - 64 numbers into three 8 bit bytes in the target area.
+ it returns the number of data bytes stored at the target, or -1 on error.
+ */
+
+int
+b64_pton(src, target, targsize)
+ char const *src;
+ u_char *target;
+ size_t targsize;
+{
+ int tarindex, state, ch;
+ char *pos;
+
+ state = 0;
+ tarindex = 0;
+
+ while ((ch = *src++) != '\0') {
+ if (isspace(ch)) /* Skip whitespace anywhere. */
+ continue;
+
+ if (ch == Pad64)
+ break;
+
+ pos = strchr(Base64, ch);
+ if (pos == 0) /* A non-base64 character. */
+ return (-1);
+
+ switch (state) {
+ case 0:
+ if (target) {
+ if ((size_t)tarindex >= targsize)
+ return (-1);
+ target[tarindex] = (pos - Base64) << 2;
+ }
+ state = 1;
+ break;
+ case 1:
+ if (target) {
+ if ((size_t)tarindex + 1 >= targsize)
+ return (-1);
+ target[tarindex] |= (pos - Base64) >> 4;
+ target[tarindex+1] = ((pos - Base64) & 0x0f)
+ << 4 ;
+ }
+ tarindex++;
+ state = 2;
+ break;
+ case 2:
+ if (target) {
+ if ((size_t)tarindex + 1 >= targsize)
+ return (-1);
+ target[tarindex] |= (pos - Base64) >> 2;
+ target[tarindex+1] = ((pos - Base64) & 0x03)
+ << 6;
+ }
+ tarindex++;
+ state = 3;
+ break;
+ case 3:
+ if (target) {
+ if ((size_t)tarindex >= targsize)
+ return (-1);
+ target[tarindex] |= (pos - Base64);
+ }
+ tarindex++;
+ state = 0;
+ break;
+ default:
+ abort();
+ }
+ }
+
+ /*
+ * We are done decoding Base-64 chars. Let's see if we ended
+ * on a byte boundary, and/or with erroneous trailing characters.
+ */
+
+ if (ch == Pad64) { /* We got a pad char. */
+ ch = *src++; /* Skip it, get next. */
+ switch (state) {
+ case 0: /* Invalid = in first position */
+ case 1: /* Invalid = in second position */
+ return (-1);
+
+ case 2: /* Valid, means one byte of info */
+ /* Skip any number of spaces. */
+ for ((void)NULL; ch != '\0'; ch = *src++)
+ if (!isspace(ch))
+ break;
+ /* Make sure there is another trailing = sign. */
+ if (ch != Pad64)
+ return (-1);
+ ch = *src++; /* Skip the = */
+ /* Fall through to "single trailing =" case. */
+ /* FALLTHROUGH */
+
+ case 3: /* Valid, means two bytes of info */
+ /*
+ * We know this char is an =. Is there anything but
+ * whitespace after it?
+ */
+ for ((void)NULL; ch != '\0'; ch = *src++)
+ if (!isspace(ch))
+ return (-1);
+
+ /*
+ * Now make sure for cases 2 and 3 that the "extra"
+ * bits that slopped past the last full byte were
+ * zeros. If we don't check them, they become a
+ * subliminal channel.
+ */
+ if (target && target[tarindex] != 0)
+ return (-1);
+ }
+ } else {
+ /*
+ * We ended by seeing the end of the string. Make sure we
+ * have no partial bytes lying around.
+ */
+ if (state != 0)
+ return (-1);
+ }
+
+ return (tarindex);
+}
diff --git a/cpukit/libnetworking/libc/byteorder.3 b/cpukit/libnetworking/libc/byteorder.3
new file mode 100644
index 0000000000..81bf604867
--- /dev/null
+++ b/cpukit/libnetworking/libc/byteorder.3
@@ -0,0 +1,77 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. 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 the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+.\"
+.\" @(#)byteorder.3 8.1 (Berkeley) 6/4/93
+.\" $Id$
+.\"
+.Dd June 4, 1993
+.Dt BYTEORDER 3
+.Os BSD 4.2
+.Sh NAME
+.Nm htonl ,
+.Nm htons ,
+.Nm ntohl ,
+.Nm ntohs
+.Nd convert values between host and network byte order
+.Sh SYNOPSIS
+.Fd #include <sys/param.h>
+.Ft u_long
+.Fn htonl "u_long hostlong"
+.Ft u_short
+.Fn htons "u_short hostshort"
+.Ft u_long
+.Fn ntohl "u_long netlong"
+.Ft u_short
+.Fn ntohs "u_short netshort"
+.Sh DESCRIPTION
+These routines convert 16 and 32 bit quantities between network
+byte order and host byte order.
+On machines which have a byte order which is the same as the network
+order, routines are defined as null macros.
+.Pp
+These routines are most often used in conjunction with Internet
+addresses and ports as returned by
+.Xr gethostbyname 3
+and
+.Xr getservent 3 .
+.Sh SEE ALSO
+.Xr gethostbyname 3 ,
+.Xr getservent 3
+.Sh HISTORY
+The
+.Nm byteorder
+functions appeared in
+.Bx 4.2 .
+.Sh BUGS
+On the
+.Tn VAX
+bytes are handled backwards from most everyone else in
+the world. This is not expected to be fixed in the near future.
diff --git a/cpukit/libnetworking/libc/ether_addr.c b/cpukit/libnetworking/libc/ether_addr.c
new file mode 100644
index 0000000000..9b7a9abf44
--- /dev/null
+++ b/cpukit/libnetworking/libc/ether_addr.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 1995
+ * Bill Paul <wpaul@ctr.columbia.edu>. 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 Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 REGENTS 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.
+ *
+ * ethernet address conversion and lookup routines
+ *
+ * Written by Bill Paul <wpaul@ctr.columbia.edu>
+ * Center for Telecommunications Research
+ * Columbia University, New York City
+ *
+ * $Id$
+ */
+
+
+#include <stdio.h>
+#include <paths.h>
+#include <sys/types.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <net/ethernet.h>
+#ifdef YP
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+
+#ifndef _PATH_ETHERS
+#define _PATH_ETHERS "/etc/ethers"
+#endif
+
+/*
+ * Parse a string of text containing an ethernet address and hostname
+ * and separate it into its component parts.
+ */
+int ether_line(l, e, hostname)
+ char *l;
+ struct ether_addr *e;
+ char *hostname;
+{
+ int i, o[6];
+
+ i = sscanf(l, "%x:%x:%x:%x:%x:%x %s", &o[0], &o[1], &o[2],
+ &o[3], &o[4], &o[5],
+ hostname);
+ if (i != 7)
+ return (i);
+
+ for (i=0; i<6; i++)
+ e->octet[i] = o[i];
+ return (0);
+}
+
+/*
+ * Convert an ASCII representation of an ethernet address to
+ * binary form.
+ */
+struct ether_addr *ether_aton(a)
+ char *a;
+{
+ int i;
+ static struct ether_addr o;
+ unsigned int o0, o1, o2, o3, o4, o5;
+
+ i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o0, &o1, &o2, &o3, &o4, &o5);
+
+ if (i != 6)
+ return (NULL);
+
+ o.octet[0]=o0;
+ o.octet[1]=o1;
+ o.octet[2]=o2;
+ o.octet[3]=o3;
+ o.octet[4]=o4;
+ o.octet[5]=o5;
+
+ return ((struct ether_addr *)&o);
+}
+
+/*
+ * Convert a binary representation of an ethernet address to
+ * an ASCII string.
+ */
+char *ether_ntoa(n)
+ struct ether_addr *n;
+{
+ int i;
+ static char a[18];
+
+ i = sprintf(a,"%x:%x:%x:%x:%x:%x",n->octet[0],n->octet[1],n->octet[2],
+ n->octet[3],n->octet[4],n->octet[5]);
+ if (i < 11)
+ return (NULL);
+ return ((char *)&a);
+}
+
+/*
+ * Map an ethernet address to a hostname. Use either /etc/ethers or
+ * NIS/YP.
+ */
+
+int ether_ntohost(hostname, e)
+ char *hostname;
+ struct ether_addr *e;
+{
+ FILE *fp;
+ char buf[BUFSIZ + 2];
+ struct ether_addr local_ether;
+ char local_host[MAXHOSTNAMELEN];
+#ifdef YP
+ char *result;
+ int resultlen;
+ char *ether_a;
+ char *yp_domain;
+#endif
+ if ((fp = fopen(_PATH_ETHERS, "r")) == NULL)
+ return (1);
+
+ while (fgets(buf,BUFSIZ,fp)) {
+ if (buf[0] == '#')
+ continue;
+#ifdef YP
+ if (buf[0] == '+') {
+ if (yp_get_default_domain(&yp_domain))
+ continue;
+ ether_a = ether_ntoa(e);
+ if (yp_match(yp_domain, "ethers.byaddr", ether_a,
+ strlen(ether_a), &result, &resultlen)) {
+ continue;
+ }
+ strncpy(buf, result, resultlen);
+ buf[resultlen] = '\0';
+ free(result);
+ }
+#endif
+ if (!ether_line(buf, &local_ether, local_host)) {
+ if (!bcmp((char *)&local_ether.octet[0],
+ (char *)&e->octet[0], 6)) {
+ /* We have a match */
+ strcpy(hostname, local_host);
+ fclose(fp);
+ return(0);
+ }
+ }
+ }
+ fclose(fp);
+ return (1);
+}
+
+/*
+ * Map a hostname to an ethernet address using /etc/ethers or
+ * NIS/YP.
+ */
+int ether_hostton(hostname, e)
+ char *hostname;
+ struct ether_addr *e;
+{
+ FILE *fp;
+ char buf[BUFSIZ + 2];
+ struct ether_addr local_ether;
+ char local_host[MAXHOSTNAMELEN];
+#ifdef YP
+ char *result;
+ int resultlen;
+ char *yp_domain;
+#endif
+ if ((fp = fopen(_PATH_ETHERS, "r")) == NULL)
+ return (1);
+
+ while (fgets(buf,BUFSIZ,fp)) {
+ if (buf[0] == '#')
+ continue;
+#ifdef YP
+ if (buf[0] == '+') {
+ if (yp_get_default_domain(&yp_domain))
+ continue;
+ if (yp_match(yp_domain, "ethers.byname", hostname,
+ strlen(hostname), &result, &resultlen)) {
+ continue;
+ }
+ strncpy(buf, result, resultlen);
+ buf[resultlen] = '\0';
+ free(result);
+ }
+#endif
+ if (!ether_line(buf, &local_ether, local_host)) {
+ if (!strcmp(hostname, local_host)) {
+ /* We have a match */
+ bcopy((char *)&local_ether.octet[0],
+ (char *)&e->octet[0], 6);
+ fclose(fp);
+ return(0);
+ }
+ }
+ }
+ fclose(fp);
+ return (1);
+}
diff --git a/cpukit/libnetworking/libc/ethers.3 b/cpukit/libnetworking/libc/ethers.3
new file mode 100644
index 0000000000..afea48320a
--- /dev/null
+++ b/cpukit/libnetworking/libc/ethers.3
@@ -0,0 +1,193 @@
+.\" Copyright (c) 1995
+.\" Bill Paul <wpaul@ctr.columbia.edu>. 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 Bill Paul.
+.\" 4. Neither the name of the author nor the names of any co-contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY Bill Paul 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 REGENTS 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.
+.\"
+.\" $Id$
+.\"
+.Dd April 12, 1995
+.Dt ETHERS 3
+.Os FreeBSD 2.1
+.Sh NAME
+.Nm ethers ,
+.Nm ether_line ,
+.Nm ether_aton ,
+.Nm ether_ntoa ,
+.Nm ether_ntohost ,
+.Nm ether_hostton
+.Nd Ethernet address conversion and lookup routines
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/socket.h>
+.Fd #include <net/ethernet.h>
+.Ft int
+.Fn ether_line "char *l" "struct ether_addr *e" "char *hostname"
+.Ft struct ether_addr *
+.Fn ether_aton "char *a"
+.Ft char *
+.Fn ether_ntoa "struct ether_addr *n"
+.Ft int
+.Fn ether_ntohost "char *hostname" "struct ether_addr *e"
+.Ft int
+.Fn ether_hostton "char *hostname" "struct ether_addr *e"
+.Sh DESCRIPTION
+These functions operate on ethernet addresses using an
+.Ar ether_addr
+structure, which is defined in the header file
+.Aq Pa netinet/if_ether.h :
+.Bd -literal -offset indent
+/*
+ * The number of bytes in an ethernet (MAC) address.
+ */
+#define ETHER_ADDR_LEN 6
+
+/*
+ * Structure of a 48-bit Ethernet address.
+ */
+struct ether_addr {
+ u_char octet[ETHER_ADDR_LEN];
+};
+.Ed
+.Pp
+The function
+.Fn ether_line
+scans
+.Ar l ,
+an
+.Tn ASCII
+string in
+.Xr ethers 5
+format and sets
+.Ar e
+to the ethernet address specified in the string and
+.Ar h
+to the hostname. This function is used to parse lines from
+.Pa /etc/ethers
+into their component parts.
+.Pp
+The
+.Fn ether_aton
+function converts an
+.Tn ASCII
+representation of an ethernet address into an
+.Ar ether_addr
+structure. Likewise,
+.Fn ether_ntoa
+converts an ethernet address specified as an
+.Ar ether_addr
+structure into an
+.Tn ASCII
+string.
+.Pp
+The
+.Fn ether_ntohost
+and
+.Fn ether_hostton
+functions map ethernet addresses to their corresponding hostnames
+as specified in the
+.Pa /etc/ethers
+database.
+.Fn ether_ntohost
+converts from ethernet address to hostname, and
+.Fn ether_hostton
+converts from hostname to ethernet address.
+.Sh RETURN VALUES
+.Fn ether_line
+returns zero on success and non-zero if it was unable to parse
+any part of the supplied line
+.Ar l .
+It returns the extracted ethernet address in the supplied
+.Ar ether_addr
+structure
+.Ar e
+and the hostname in the supplied string
+.Ar h .
+.Pp
+On success,
+.Fn ether_ntoa
+returns a pointer to a string containing an
+.Tn ASCII
+representation of an ethernet address. If it is unable to convert
+the supplied
+.Ar ether_addr
+structure, it returns a
+.Dv NULL
+pointer. Likewise,
+.Fn ether_aton
+returns a pointer to an
+.Ar ether_addr
+structure on success and a
+.Dv NULL
+pointer on failure.
+.Pp
+The
+.Fn ether_ntohost
+and
+.Fn ether_hostton
+functions both return zero on success or non-zero if they were
+unable to find a match in the
+.Pa /etc/ethers
+database.
+.Sh NOTES
+The user must insure that the hostname strings passed to the
+the
+.Fn ether_line ,
+.Fn ether_ntohost
+and
+.Fn ether_hostton
+functions are large enough to contain the returned hostnames.
+.Sh NIS INTERACTION
+If the
+.Pa /etc/ethers
+contains a line with a single + in it, the
+.Fn ether_ntohost
+and
+.Fn ether_hostton
+functions will attempt to consult the NIS
+.Pa ethers.byname
+and
+.Pa ethers.byaddr
+maps in addition to the data in the
+.Pa /etc/ethers
+file.
+.Sh SEE ALSO
+.Xr yp 4 ,
+.Xr ethers 5
+.Sh BUGS
+.Pp
+The
+.Fn ether_aton
+and
+.Fn ether_ntoa
+functions returns values that are stored in static memory areas
+which may be overwritten the next time they are called.
+.Sh HISTORY
+This particular implementation of the
+.Nm ethers
+library functions were written for and first appeared in
+.Fx 2.1 .
diff --git a/cpukit/libnetworking/libc/gethostbydns.c b/cpukit/libnetworking/libc/gethostbydns.c
new file mode 100644
index 0000000000..4991ccad22
--- /dev/null
+++ b/cpukit/libnetworking/libc/gethostbydns.c
@@ -0,0 +1,775 @@
+/*
+ * ++Copyright++ 1985, 1988, 1993
+ * -
+ * Copyright (c) 1985, 1988, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ * -
+ * --Copyright--
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
+static char fromrcsid[] = "From: Id: gethnamaddr.c,v 8.23 1998/04/07 04:59:46 vixie Exp $";
+static char rcsid[] = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <ctype.h>
+#include <errno.h>
+#include <syslog.h>
+
+#include "res_config.h"
+
+void abort(void); /* to avoid warning */
+
+#define SPRINTF(x) ((size_t)sprintf x)
+
+#define MAXALIASES 35
+#define MAXADDRS 35
+
+static const char AskedForGot[] =
+ "gethostby*.gethostanswer: asked for \"%s\", got \"%s\"";
+
+static char *h_addr_ptrs[MAXADDRS + 1];
+
+static struct hostent host;
+static char *host_aliases[MAXALIASES];
+static char hostbuf[8*1024];
+static u_char host_addr[16]; /* IPv4 or IPv6 */
+
+#ifdef RESOLVSORT
+static void addrsort __P((char **, int));
+#endif
+
+#if PACKETSZ > 1024
+#define MAXPACKET PACKETSZ
+#else
+#define MAXPACKET 1024
+#endif
+
+typedef union {
+ HEADER hdr;
+ u_char buf[MAXPACKET];
+} querybuf;
+
+typedef union {
+ int32_t al;
+ char ac;
+} align;
+
+extern int h_errno;
+int _dns_ttl_;
+
+#ifdef DEBUG
+static void
+dprintf(msg, num)
+ char *msg;
+ int num;
+{
+ if (_res.options & RES_DEBUG) {
+ int save = errno;
+
+ printf(msg, num);
+ errno = save;
+ }
+}
+#else
+# define dprintf(msg, num) /*nada*/
+#endif
+
+#define BOUNDED_INCR(x) \
+ do { \
+ cp += x; \
+ if (cp > eom) { \
+ h_errno = NO_RECOVERY; \
+ return (NULL); \
+ } \
+ } while (0)
+
+#define BOUNDS_CHECK(ptr, count) \
+ do { \
+ if ((ptr) + (count) > eom) { \
+ h_errno = NO_RECOVERY; \
+ return (NULL); \
+ } \
+ } while (0)
+
+static struct hostent *
+gethostanswer(answer, anslen, qname, qtype)
+ const querybuf *answer;
+ int anslen;
+ const char *qname;
+ int qtype;
+{
+ register const HEADER *hp;
+ register const u_char *cp;
+ register int n;
+ const u_char *eom, *erdata;
+ char *bp, **ap, **hap;
+ int type, class, buflen, ancount, qdcount;
+ int haveanswer, had_error;
+ int toobig = 0;
+ char tbuf[MAXDNAME];
+ const char *tname;
+ int (*name_ok) __P((const char *));
+
+ tname = qname;
+ host.h_name = NULL;
+ eom = answer->buf + anslen;
+ switch (qtype) {
+ case T_A:
+ case T_AAAA:
+ name_ok = res_hnok;
+ break;
+ case T_PTR:
+ name_ok = res_dnok;
+ break;
+ default:
+ h_errno = NO_RECOVERY;
+ return (NULL); /* XXX should be abort(); */
+ }
+ /*
+ * find first satisfactory answer
+ */
+ hp = &answer->hdr;
+ ancount = ntohs(hp->ancount);
+ qdcount = ntohs(hp->qdcount);
+ bp = hostbuf;
+ buflen = sizeof hostbuf;
+ cp = answer->buf;
+ BOUNDED_INCR(HFIXEDSZ);
+ if (qdcount != 1) {
+ h_errno = NO_RECOVERY;
+ return (NULL);
+ }
+ n = dn_expand(answer->buf, eom, cp, bp, buflen);
+ if ((n < 0) || !(*name_ok)(bp)) {
+ h_errno = NO_RECOVERY;
+ return (NULL);
+ }
+ BOUNDED_INCR(n + QFIXEDSZ);
+ if (qtype == T_A || qtype == T_AAAA) {
+ /* res_send() has already verified that the query name is the
+ * same as the one we sent; this just gets the expanded name
+ * (i.e., with the succeeding search-domain tacked on).
+ */
+ n = strlen(bp) + 1; /* for the \0 */
+ if (n >= MAXHOSTNAMELEN) {
+ h_errno = NO_RECOVERY;
+ return (NULL);
+ }
+ host.h_name = bp;
+ bp += n;
+ buflen -= n;
+ /* The qname can be abbreviated, but h_name is now absolute. */
+ qname = host.h_name;
+ }
+ ap = host_aliases;
+ *ap = NULL;
+ host.h_aliases = host_aliases;
+ hap = h_addr_ptrs;
+ *hap = NULL;
+ host.h_addr_list = h_addr_ptrs;
+ haveanswer = 0;
+ had_error = 0;
+ _dns_ttl_ = -1;
+ while (ancount-- > 0 && cp < eom && !had_error) {
+ n = dn_expand(answer->buf, eom, cp, bp, buflen);
+ if ((n < 0) || !(*name_ok)(bp)) {
+ had_error++;
+ continue;
+ }
+ cp += n; /* name */
+ BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
+ type = _getshort(cp);
+ cp += INT16SZ; /* type */
+ class = _getshort(cp);
+ cp += INT16SZ; /* class */
+ if (qtype == T_A && type == T_A)
+ _dns_ttl_ = _getlong(cp);
+ cp += INT32SZ; /* TTL */
+ n = _getshort(cp);
+ cp += INT16SZ; /* len */
+ BOUNDS_CHECK(cp, n);
+ erdata = cp + n;
+ if (class != C_IN) {
+ /* XXX - debug? syslog? */
+ cp += n;
+ continue; /* XXX - had_error++ ? */
+ }
+ if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
+ if (ap >= &host_aliases[MAXALIASES-1])
+ continue;
+ n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
+ if ((n < 0) || !(*name_ok)(tbuf)) {
+ had_error++;
+ continue;
+ }
+ cp += n;
+ if (cp != erdata) {
+ h_errno = NO_RECOVERY;
+ return (NULL);
+ }
+ /* Store alias. */
+ *ap++ = bp;
+ n = strlen(bp) + 1; /* for the \0 */
+ if (n >= MAXHOSTNAMELEN) {
+ had_error++;
+ continue;
+ }
+ bp += n;
+ buflen -= n;
+ /* Get canonical name. */
+ n = strlen(tbuf) + 1; /* for the \0 */
+ if (n > buflen || n >= MAXHOSTNAMELEN) {
+ had_error++;
+ continue;
+ }
+ strcpy(bp, tbuf);
+ host.h_name = bp;
+ bp += n;
+ buflen -= n;
+ continue;
+ }
+ if (qtype == T_PTR && type == T_CNAME) {
+ n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
+ if (n < 0 || !res_dnok(tbuf)) {
+ had_error++;
+ continue;
+ }
+ cp += n;
+ if (cp != erdata) {
+ h_errno = NO_RECOVERY;
+ return (NULL);
+ }
+ /* Get canonical name. */
+ n = strlen(tbuf) + 1; /* for the \0 */
+ if (n > buflen || n >= MAXHOSTNAMELEN) {
+ had_error++;
+ continue;
+ }
+ strcpy(bp, tbuf);
+ tname = bp;
+ bp += n;
+ buflen -= n;
+ continue;
+ }
+ if (type != qtype) {
+ syslog(LOG_NOTICE|LOG_AUTH,
+ "gethostby*.gethostanswer: asked for \"%s %s %s\", got type \"%s\"",
+ qname, p_class(C_IN), p_type(qtype),
+ p_type(type));
+ cp += n;
+ continue; /* XXX - had_error++ ? */
+ }
+ switch (type) {
+ case T_PTR:
+ if (strcasecmp(tname, bp) != 0) {
+ syslog(LOG_NOTICE|LOG_AUTH,
+ AskedForGot, qname, bp);
+ cp += n;
+ continue; /* XXX - had_error++ ? */
+ }
+ n = dn_expand(answer->buf, eom, cp, bp, buflen);
+ if ((n < 0) || !res_hnok(bp)) {
+ had_error++;
+ break;
+ }
+#if MULTI_PTRS_ARE_ALIASES
+ cp += n;
+ if (cp != erdata) {
+ h_errno = NO_RECOVERY;
+ return (NULL);
+ }
+ if (!haveanswer)
+ host.h_name = bp;
+ else if (ap < &host_aliases[MAXALIASES-1])
+ *ap++ = bp;
+ else
+ n = -1;
+ if (n != -1) {
+ n = strlen(bp) + 1; /* for the \0 */
+ if (n >= MAXHOSTNAMELEN) {
+ had_error++;
+ break;
+ }
+ bp += n;
+ buflen -= n;
+ }
+ break;
+#else
+ host.h_name = bp;
+ if (_res.options & RES_USE_INET6) {
+ n = strlen(bp) + 1; /* for the \0 */
+ if (n >= MAXHOSTNAMELEN) {
+ had_error++;
+ break;
+ }
+ bp += n;
+ buflen -= n;
+ _map_v4v6_hostent(&host, &bp, &buflen);
+ }
+ h_errno = NETDB_SUCCESS;
+ return (&host);
+#endif
+ case T_A:
+ case T_AAAA:
+ if (strcasecmp(host.h_name, bp) != 0) {
+ syslog(LOG_NOTICE|LOG_AUTH,
+ AskedForGot, host.h_name, bp);
+ cp += n;
+ continue; /* XXX - had_error++ ? */
+ }
+ if (n != host.h_length) {
+ cp += n;
+ continue;
+ }
+ if (!haveanswer) {
+ register int nn;
+
+ host.h_name = bp;
+ nn = strlen(bp) + 1; /* for the \0 */
+ bp += nn;
+ buflen -= nn;
+ }
+
+ bp += sizeof(align) - ((u_long)bp % sizeof(align));
+
+ if (bp + n >= &hostbuf[sizeof hostbuf]) {
+ dprintf("size (%d) too big\n", n);
+ had_error++;
+ continue;
+ }
+ if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
+ if (!toobig++)
+ dprintf("Too many addresses (%d)\n",
+ MAXADDRS);
+ cp += n;
+ continue;
+ }
+ bcopy(cp, *hap++ = bp, n);
+ bp += n;
+ buflen -= n;
+ cp += n;
+ if (cp != erdata) {
+ h_errno = NO_RECOVERY;
+ return (NULL);
+ }
+ break;
+ default:
+ dprintf("Impossible condition (type=%d)\n", type);
+ h_errno = NO_RECOVERY;
+ return (NULL);
+ /* BIND has abort() here, too risky on bad data */
+ }
+ if (!had_error)
+ haveanswer++;
+ }
+ if (haveanswer) {
+ *ap = NULL;
+ *hap = NULL;
+# if defined(RESOLVSORT)
+ /*
+ * Note: we sort even if host can take only one address
+ * in its return structures - should give it the "best"
+ * address in that case, not some random one
+ */
+ if (_res.nsort && haveanswer > 1 && qtype == T_A)
+ addrsort(h_addr_ptrs, haveanswer);
+# endif /*RESOLVSORT*/
+ if (!host.h_name) {
+ n = strlen(qname) + 1; /* for the \0 */
+ if (n > buflen || n >= MAXHOSTNAMELEN)
+ goto no_recovery;
+ strcpy(bp, qname);
+ host.h_name = bp;
+ bp += n;
+ buflen -= n;
+ }
+ if (_res.options & RES_USE_INET6)
+ _map_v4v6_hostent(&host, &bp, &buflen);
+ h_errno = NETDB_SUCCESS;
+ return (&host);
+ }
+ no_recovery:
+ h_errno = NO_RECOVERY;
+ return (NULL);
+}
+
+struct hostent *
+__dns_getanswer(answer, anslen, qname, qtype)
+ const char *answer;
+ int anslen;
+ const char *qname;
+ int qtype;
+{
+ switch(qtype) {
+ case T_AAAA:
+ host.h_addrtype = AF_INET6;
+ host.h_length = IN6ADDRSZ;
+ break;
+ case T_A:
+ default:
+ host.h_addrtype = AF_INET;
+ host.h_length = INADDRSZ;
+ break;
+ }
+
+ return(gethostanswer((const querybuf *)answer, anslen, qname, qtype));
+}
+
+struct hostent *
+_gethostbydnsname(name, af)
+ const char *name;
+ int af;
+{
+ querybuf buf;
+ register const char *cp;
+ char *bp;
+ int n, size, type, len;
+
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ h_errno = NETDB_INTERNAL;
+ return (NULL);
+ }
+
+ switch (af) {
+ case AF_INET:
+ size = INADDRSZ;
+ type = T_A;
+ break;
+ case AF_INET6:
+ size = IN6ADDRSZ;
+ type = T_AAAA;
+ break;
+ default:
+ h_errno = NETDB_INTERNAL;
+ errno = EAFNOSUPPORT;
+ return (NULL);
+ }
+
+ host.h_addrtype = af;
+ host.h_length = size;
+
+ /*
+ * if there aren't any dots, it could be a user-level alias.
+ * this is also done in res_query() since we are not the only
+ * function that looks up host names.
+ */
+ if (!strchr(name, '.') && (cp = __hostalias(name)))
+ name = cp;
+
+ /*
+ * disallow names consisting only of digits/dots, unless
+ * they end in a dot.
+ */
+ if (isdigit((int)name[0]))
+ for (cp = name;; ++cp) {
+ if (!*cp) {
+ if (*--cp == '.')
+ break;
+ /*
+ * All-numeric, no dot at the end.
+ * Fake up a hostent as if we'd actually
+ * done a lookup.
+ */
+ if (inet_pton(af, name, host_addr) <= 0) {
+ h_errno = HOST_NOT_FOUND;
+ return (NULL);
+ }
+ strncpy(hostbuf, name, MAXDNAME);
+ hostbuf[MAXDNAME] = '\0';
+ bp = hostbuf + MAXDNAME;
+ len = sizeof hostbuf - MAXDNAME;
+ host.h_name = hostbuf;
+ host.h_aliases = host_aliases;
+ host_aliases[0] = NULL;
+ h_addr_ptrs[0] = (char *)host_addr;
+ h_addr_ptrs[1] = NULL;
+ host.h_addr_list = h_addr_ptrs;
+ if (_res.options & RES_USE_INET6)
+ _map_v4v6_hostent(&host, &bp, &len);
+ h_errno = NETDB_SUCCESS;
+ return (&host);
+ }
+ if (!isdigit((int)*cp) && *cp != '.')
+ break;
+ }
+ if ((isxdigit((int)name[0]) && strchr(name, ':') != NULL) ||
+ name[0] == ':')
+ for (cp = name;; ++cp) {
+ if (!*cp) {
+ if (*--cp == '.')
+ break;
+ /*
+ * All-IPv6-legal, no dot at the end.
+ * Fake up a hostent as if we'd actually
+ * done a lookup.
+ */
+ if (inet_pton(af, name, host_addr) <= 0) {
+ h_errno = HOST_NOT_FOUND;
+ return (NULL);
+ }
+ strncpy(hostbuf, name, MAXDNAME);
+ hostbuf[MAXDNAME] = '\0';
+ bp = hostbuf + MAXDNAME;
+ len = sizeof hostbuf - MAXDNAME;
+ host.h_name = hostbuf;
+ host.h_aliases = host_aliases;
+ host_aliases[0] = NULL;
+ h_addr_ptrs[0] = (char *)host_addr;
+ h_addr_ptrs[1] = NULL;
+ host.h_addr_list = h_addr_ptrs;
+ h_errno = NETDB_SUCCESS;
+ return (&host);
+ }
+ if (!isxdigit((int)*cp) && *cp != ':' && *cp != '.')
+ break;
+ }
+
+ if ((n = res_search(name, C_IN, type, buf.buf, sizeof(buf))) < 0) {
+ dprintf("res_search failed (%d)\n", n);
+ return (NULL);
+ }
+ return (gethostanswer(&buf, n, name, type));
+}
+
+struct hostent *
+_gethostbydnsaddr(addr, len, af)
+ const char *addr; /* XXX should have been def'd as u_char! */
+ int len, af;
+{
+ const u_char *uaddr = (const u_char *)addr;
+ static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
+ static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
+ int n, size;
+ querybuf buf;
+ register struct hostent *hp;
+ char qbuf[MAXDNAME+1], *qp;
+#ifdef SUNSECURITY
+ register struct hostent *rhp;
+ char **haddr;
+ u_long old_options;
+ char hname2[MAXDNAME+1];
+#endif /*SUNSECURITY*/
+
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ h_errno = NETDB_INTERNAL;
+ return (NULL);
+ }
+ if (af == AF_INET6 && len == IN6ADDRSZ &&
+ (!bcmp(uaddr, mapped, sizeof mapped) ||
+ !bcmp(uaddr, tunnelled, sizeof tunnelled))) {
+ /* Unmap. */
+ addr += sizeof mapped;
+ uaddr += sizeof mapped;
+ af = AF_INET;
+ len = INADDRSZ;
+ }
+ switch (af) {
+ case AF_INET:
+ size = INADDRSZ;
+ break;
+ case AF_INET6:
+ size = IN6ADDRSZ;
+ break;
+ default:
+ errno = EAFNOSUPPORT;
+ h_errno = NETDB_INTERNAL;
+ return (NULL);
+ }
+ if (size != len) {
+ errno = EINVAL;
+ h_errno = NETDB_INTERNAL;
+ return (NULL);
+ }
+ switch (af) {
+ case AF_INET:
+ (void) sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
+ (uaddr[3] & 0xff),
+ (uaddr[2] & 0xff),
+ (uaddr[1] & 0xff),
+ (uaddr[0] & 0xff));
+ break;
+ case AF_INET6:
+ qp = qbuf;
+ for (n = IN6ADDRSZ - 1; n >= 0; n--) {
+ qp += SPRINTF((qp, "%x.%x.",
+ uaddr[n] & 0xf,
+ (uaddr[n] >> 4) & 0xf));
+ }
+ strcpy(qp, "ip6.int");
+ break;
+ default:
+ abort();
+ }
+ n = res_query(qbuf, C_IN, T_PTR, (u_char *)buf.buf, sizeof buf.buf);
+ if (n < 0) {
+ dprintf("res_query failed (%d)\n", n);
+ return (NULL);
+ }
+ if (!(hp = gethostanswer(&buf, n, qbuf, T_PTR)))
+ return (NULL); /* h_errno was set by gethostanswer() */
+#ifdef SUNSECURITY
+ if (af == AF_INET) {
+ /*
+ * turn off search as the name should be absolute,
+ * 'localhost' should be matched by defnames
+ */
+ strncpy(hname2, hp->h_name, MAXDNAME);
+ hname2[MAXDNAME] = '\0';
+ old_options = _res.options;
+ _res.options &= ~RES_DNSRCH;
+ _res.options |= RES_DEFNAMES;
+ if (!(rhp = gethostbyname(hname2))) {
+ syslog(LOG_NOTICE|LOG_AUTH,
+ "gethostbyaddr: No A record for %s (verifying [%s])",
+ hname2, inet_ntoa(*((struct in_addr *)addr)));
+ _res.options = old_options;
+ h_errno = HOST_NOT_FOUND;
+ return (NULL);
+ }
+ _res.options = old_options;
+ for (haddr = rhp->h_addr_list; *haddr; haddr++)
+ if (!memcmp(*haddr, addr, INADDRSZ))
+ break;
+ if (!*haddr) {
+ syslog(LOG_NOTICE|LOG_AUTH,
+ "gethostbyaddr: A record of %s != PTR record [%s]",
+ hname2, inet_ntoa(*((struct in_addr *)addr)));
+ h_errno = HOST_NOT_FOUND;
+ return (NULL);
+ }
+ }
+#endif /*SUNSECURITY*/
+ hp->h_addrtype = af;
+ hp->h_length = len;
+ bcopy(addr, host_addr, len);
+ h_addr_ptrs[0] = (char *)host_addr;
+ h_addr_ptrs[1] = NULL;
+ if (af == AF_INET && (_res.options & RES_USE_INET6)) {
+ _map_v4v6_address((char*)host_addr, (char*)host_addr);
+ hp->h_addrtype = AF_INET6;
+ hp->h_length = IN6ADDRSZ;
+ }
+ h_errno = NETDB_SUCCESS;
+ return (hp);
+}
+
+#ifdef RESOLVSORT
+static void
+addrsort(ap, num)
+ char **ap;
+ int num;
+{
+ int i, j;
+ char **p;
+ short aval[MAXADDRS];
+ int needsort = 0;
+
+ p = ap;
+ for (i = 0; i < num; i++, p++) {
+ for (j = 0 ; (unsigned)j < _res.nsort; j++)
+ if (_res.sort_list[j].addr.s_addr ==
+ (((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask))
+ break;
+ aval[i] = j;
+ if (needsort == 0 && i > 0 && j < aval[i-1])
+ needsort = i;
+ }
+ if (!needsort)
+ return;
+
+ while (needsort < num) {
+ for (j = needsort - 1; j >= 0; j--) {
+ if (aval[j] > aval[j+1]) {
+ char *hp;
+
+ i = aval[j];
+ aval[j] = aval[j+1];
+ aval[j+1] = i;
+
+ hp = ap[j];
+ ap[j] = ap[j+1];
+ ap[j+1] = hp;
+
+ } else
+ break;
+ }
+ needsort++;
+ }
+}
+#endif
+void
+_sethostdnsent(stayopen)
+ int stayopen;
+{
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+ return;
+ if (stayopen)
+ _res.options |= RES_STAYOPEN | RES_USEVC;
+}
+
+void
+_endhostdnsent()
+{
+ _res.options &= ~(RES_STAYOPEN | RES_USEVC);
+ res_close();
+}
diff --git a/cpukit/libnetworking/libc/gethostbyht.c b/cpukit/libnetworking/libc/gethostbyht.c
new file mode 100644
index 0000000000..29f2805367
--- /dev/null
+++ b/cpukit/libnetworking/libc/gethostbyht.c
@@ -0,0 +1,202 @@
+/*-
+ * Copyright (c) 1985, 1988, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ * -
+ * --Copyright--
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
+static char rcsid[] = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <arpa/nameser.h> /* XXX */
+#include <resolv.h> /* XXX */
+
+#define MAXALIASES 35
+
+static struct hostent host;
+static char *host_aliases[MAXALIASES];
+static char hostbuf[BUFSIZ+1];
+static FILE *hostf = NULL;
+static u_char host_addr[16]; /* IPv4 or IPv6 */
+static char *h_addr_ptrs[2];
+static int stayopen = 0;
+
+void
+_sethosthtent(f)
+ int f;
+{
+ if (!hostf)
+ hostf = fopen(_PATH_HOSTS, "r" );
+ else
+ rewind(hostf);
+ stayopen = f;
+}
+
+void
+_endhosthtent()
+{
+ if (hostf && !stayopen) {
+ (void) fclose(hostf);
+ hostf = NULL;
+ }
+}
+
+struct hostent *
+gethostent()
+{
+ char *p;
+ register char *cp, **q;
+ int af, len;
+
+ if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) {
+ h_errno = NETDB_INTERNAL;
+ return (NULL);
+ }
+ again:
+ if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) {
+ h_errno = HOST_NOT_FOUND;
+ return (NULL);
+ }
+ if (*p == '#')
+ goto again;
+ if (!(cp = strpbrk(p, "#\n")))
+ goto again;
+ *cp = '\0';
+ if (!(cp = strpbrk(p, " \t")))
+ goto again;
+ *cp++ = '\0';
+ if (inet_pton(AF_INET6, p, host_addr) > 0) {
+ af = AF_INET6;
+ len = IN6ADDRSZ;
+ } else if (inet_pton(AF_INET, p, host_addr) > 0) {
+ if (_res.options & RES_USE_INET6) {
+ _map_v4v6_address((char*)host_addr, (char*)host_addr);
+ af = AF_INET6;
+ len = IN6ADDRSZ;
+ } else {
+ af = AF_INET;
+ len = INADDRSZ;
+ }
+ } else {
+ goto again;
+ }
+ h_addr_ptrs[0] = (char *)host_addr;
+ h_addr_ptrs[1] = NULL;
+ host.h_addr_list = h_addr_ptrs;
+ host.h_length = len;
+ host.h_addrtype = af;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ host.h_name = cp;
+ q = host.h_aliases = host_aliases;
+ if ((cp = strpbrk(cp, " \t")) != NULL)
+ *cp++ = '\0';
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q < &host_aliases[MAXALIASES - 1])
+ *q++ = cp;
+ if ((cp = strpbrk(cp, " \t")) != NULL)
+ *cp++ = '\0';
+ }
+ *q = NULL;
+ h_errno = NETDB_SUCCESS;
+ return (&host);
+}
+
+struct hostent *
+_gethostbyhtname(name, af)
+ const char *name;
+ int af;
+{
+ register struct hostent *p;
+ register char **cp;
+
+ sethostent(0);
+ while ((p = gethostent()) != NULL) {
+ if (p->h_addrtype != af)
+ continue;
+ if (strcasecmp(p->h_name, name) == 0)
+ break;
+ for (cp = p->h_aliases; *cp != 0; cp++)
+ if (strcasecmp(*cp, name) == 0)
+ goto found;
+ }
+found:
+ endhostent();
+ return (p);
+}
+
+struct hostent *
+_gethostbyhtaddr(addr, len, af)
+ const char *addr;
+ int len, af;
+{
+ register struct hostent *p;
+
+ sethostent(0);
+ while ((p = gethostent()) != NULL)
+ if (p->h_addrtype == af && !bcmp(p->h_addr, addr, len))
+ break;
+ endhostent();
+ return (p);
+}
diff --git a/cpukit/libnetworking/libc/gethostbyname.3 b/cpukit/libnetworking/libc/gethostbyname.3
new file mode 100644
index 0000000000..e21dc79f1d
--- /dev/null
+++ b/cpukit/libnetworking/libc/gethostbyname.3
@@ -0,0 +1,305 @@
+.\" Copyright (c) 1983, 1987, 1991, 1993
+.\" The Regents of the University of California. 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 the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+.\"
+.\" From: @(#)gethostbyname.3 8.4 (Berkeley) 5/25/95
+.\" $Id$
+.\"
+.Dd May 25, 1995
+.Dt GETHOSTBYNAME 3
+.Os BSD 4.2
+.Sh NAME
+.Nm gethostbyname ,
+.Nm gethostbyname2 ,
+.Nm gethostbyaddr ,
+.Nm gethostent ,
+.Nm sethostent ,
+.Nm endhostent ,
+.Nm herror ,
+.Nm hstrerror
+.Nd get network host entry
+.Sh SYNOPSIS
+.Fd #include <netdb.h>
+.Vt extern int h_errno;
+.Ft struct hostent *
+.Fn gethostbyname "const char *name"
+.Ft struct hostent *
+.Fn gethostbyname2 "const char *name" "int af"
+.Ft struct hostent *
+.Fn gethostbyaddr "const char *addr" "int len" "int type"
+.Ft struct hostent *
+.Fn gethostent void
+.Ft void
+.Fn sethostent "int stayopen"
+.Ft void
+.Fn endhostent void
+.Ft void
+.Fn herror "const char *string"
+.Ft const char *
+.Fn hstrerror "int err"
+.Sh DESCRIPTION
+The
+.Fn gethostbyname ,
+.Fn gethostbyname2
+and
+.Fn gethostbyaddr
+functions
+each return a pointer to an object with the
+following structure describing an internet host
+referenced by name or by address, respectively.
+This structure contains either the information obtained from the name server,
+.Xr named 8 ,
+or broken-out fields from a line in
+.Pa /etc/hosts .
+If the local name server is not running these routines do a lookup in
+.Pa /etc/hosts .
+.Bd -literal
+struct hostent {
+ char *h_name; /* official name of host */
+ char **h_aliases; /* alias list */
+ int h_addrtype; /* host address type */
+ int h_length; /* length of address */
+ char **h_addr_list; /* list of addresses from name server */
+};
+#define h_addr h_addr_list[0] /* address, for backward compatibility */
+.Ed
+.Pp
+The members of this structure are:
+.Bl -tag -width h_addr_list
+.It Fa h_name
+Official name of the host.
+.It Fa h_aliases
+A NULL-terminated array of alternate names for the host.
+.It Fa h_addrtype
+The type of address being returned; usually
+.Dv AF_INET .
+.It Fa h_length
+The length, in bytes, of the address.
+.It Fa h_addr_list
+A NULL-terminated array of network addresses for the host.
+Host addresses are returned in network byte order.
+.It Fa h_addr
+The first address in
+.Fa h_addr_list ;
+this is for backward compatibility.
+.El
+.Pp
+When using the nameserver,
+.Fn gethostbyname
+and
+.Fn gethostbyname
+will search for the named host in the current domain and its parents
+unless the name ends in a dot.
+If the name contains no dot, and if the environment variable
+.Dq Ev HOSTALIASES
+contains the name of an alias file, the alias file will first be searched
+for an alias matching the input name.
+See
+.Xr hostname 7
+for the domain search procedure and the alias file format.
+.Pp
+The
+.Fn gethostbyname2
+function is an evolution of
+.Fn gethostbyname
+which is intended to allow lookups in address families other than
+.Dv AF_INET ,
+for example
+.Dv AF_INET6 .
+Currently the
+.Fa af
+argument must be specified as
+.Dv AF_INET
+else the function will return
+.Dv NULL
+after having set
+.Va h_errno
+to
+.Dv NETDB_INTERNAL
+.Pp
+The
+.Fn sethostent
+function
+may be used to request the use of a connected
+.Tn TCP
+socket for queries.
+If the
+.Fa stayopen
+flag is non-zero,
+this sets the option to send all queries to the name server using
+.Tn TCP
+and to retain the connection after each call to
+.Fn gethostbyname ,
+.Fn gethostbyname2
+or
+.Fn gethostbyaddr .
+Otherwise, queries are performed using
+.Tn UDP
+datagrams.
+.Pp
+The
+.Fn endhostent
+function
+closes the
+.Tn TCP
+connection.
+.Pp
+The
+.Fn herror
+function writes a message to the diagnostic output consisting of the
+string parameter
+.Fa s ,
+the constant string ": ", and a message corresponding to the value of
+.Va h_errno .
+.Pp
+The
+.Fn hstrerror
+function returns a string which is the message text corresponding to the
+value of the
+.Fa err
+parameter.
+.Sh FILES
+.Bl -tag -width /etc/resolv.conf -compact
+.It Pa /etc/hosts
+.It Pa /etc/host.conf
+.It Pa /etc/resolv.conf
+.El
+.Sh DIAGNOSTICS
+Error return status from
+.Fn gethostbyname ,
+.Fn gethostbyname2
+and
+.Fn gethostbyaddr
+is indicated by return of a null pointer.
+The external integer
+.Va h_errno
+may then be checked to see whether this is a temporary failure
+or an invalid or unknown host.
+The routine
+.Fn herror
+can be used to print an error message describing the failure.
+If its argument
+.Fa string
+is
+.Pf non Dv -NULL ,
+it is printed, followed by a colon and a space.
+The error message is printed with a trailing newline.
+.Pp
+The variable
+.Va h_errno
+can have the following values:
+.Bl -tag -width HOST_NOT_FOUND
+.It Dv HOST_NOT_FOUND
+No such host is known.
+.It Dv TRY_AGAIN
+This is usually a temporary error
+and means that the local server did not receive
+a response from an authoritative server.
+A retry at some later time may succeed.
+.It Dv NO_RECOVERY
+Some unexpected server failure was encountered.
+This is a non-recoverable error.
+.It Dv NO_DATA
+The requested name is valid but does not have an IP address;
+this is not a temporary error.
+This means that the name is known to the name server but there is no address
+associated with this name.
+Another type of request to the name server using this domain name
+will result in an answer;
+for example, a mail-forwarder may be registered for this domain.
+.El
+.Sh SEE ALSO
+.Xr resolver 3 ,
+.Xr hosts 5 ,
+.Xr hostname 7 ,
+.Xr named 8
+.Sh CAVEAT
+The
+.Fn gethostent
+function
+is defined, and
+.Fn sethostent
+and
+.Fn endhostent
+are redefined,
+when
+.Xr libc 3
+is built to use only the routines to lookup in
+.Pa /etc/hosts
+and not the name server.
+.Pp
+The
+.Fn gethostent
+function
+reads the next line of
+.Pa /etc/hosts ,
+opening the file if necessary.
+.Pp
+The
+.Fn sethostent
+function
+opens and/or rewinds the file
+.Pa /etc/hosts .
+If the
+.Fa stayopen
+argument is non-zero,
+the file will not be closed after each call to
+.Fn gethostbyname ,
+.Fn gethostbyname2
+or
+.Fn gethostbyaddr .
+.Pp
+The
+.Fn endhostent
+function
+closes the file.
+.Sh HISTORY
+The
+.Fn herror
+function appeared in
+.Bx 4.3 .
+The
+.Fn endhostent ,
+.Fn gethostbyaddr ,
+.Fn gethostbyname ,
+.Fn gethostent ,
+and
+.Fn sethostent
+functions appeared in
+.Bx 4.2 .
+The
+.Fn gethostbyname2
+function first appeared in bind-4.9.4.
+.Sh BUGS
+These functions use static data storage;
+if the data is needed for future use, it should be
+copied before any subsequent calls overwrite it.
+Only the Internet
+address format is currently understood.
diff --git a/cpukit/libnetworking/libc/gethostbynis.c b/cpukit/libnetworking/libc/gethostbynis.c
new file mode 100644
index 0000000000..45dbe5a85d
--- /dev/null
+++ b/cpukit/libnetworking/libc/gethostbynis.c
@@ -0,0 +1,142 @@
+/*-
+ * Copyright (c) 1994, Garrett Wollman
+ *
+ * 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 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 REGENTS 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)$Id$";
+static char rcsid[] = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#ifdef YP
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+
+#define MAXALIASES 35
+#define MAXADDRS 35
+
+#ifdef YP
+static char *host_aliases[MAXALIASES];
+static char hostaddr[MAXADDRS];
+static char *host_addrs[2];
+#endif /* YP */
+
+static struct hostent *
+_gethostbynis(name, map, af)
+ const char *name;
+ char *map;
+ int af;
+{
+#ifdef YP
+ register char *cp, **q;
+ char *result;
+ int resultlen;
+ static struct hostent h;
+ static char *domain = (char *)NULL;
+ static char ypbuf[YPMAXRECORD + 2];
+
+ switch(af) {
+ case AF_INET:
+ break;
+ default:
+ case AF_INET6:
+ errno = EAFNOSUPPORT;
+ return NULL;
+ }
+
+ if (domain == (char *)NULL)
+ if (yp_get_default_domain (&domain))
+ return ((struct hostent *)NULL);
+
+ if (yp_match(domain, map, name, strlen(name), &result, &resultlen))
+ return ((struct hostent *)NULL);
+
+ /* avoid potential memory leak */
+ bcopy((char *)result, (char *)&ypbuf, resultlen);
+ ypbuf[resultlen] = '\0';
+ free(result);
+ result = (char *)&ypbuf;
+
+ if ((cp = index(result, '\n')))
+ *cp = '\0';
+
+ cp = strpbrk(result, " \t");
+ *cp++ = '\0';
+ h.h_addr_list = host_addrs;
+ h.h_addr = hostaddr;
+ *((u_long *)h.h_addr) = inet_addr(result);
+ h.h_length = sizeof(u_long);
+ h.h_addrtype = AF_INET;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ h.h_name = cp;
+ q = h.h_aliases = host_aliases;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q < &host_aliases[MAXALIASES - 1])
+ *q++ = cp;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ }
+ *q = NULL;
+ return (&h);
+#else
+ return (NULL);
+#endif /* YP */
+}
+
+struct hostent *
+_gethostbynisname(name, af)
+ const char *name;
+ int af;
+{
+ return _gethostbynis(name, "hosts.byname", af);
+}
+
+struct hostent *
+_gethostbynisaddr(addr, len, af)
+ const char *addr;
+ int len;
+ int af;
+{
+ return _gethostbynis(inet_ntoa(*(struct in_addr *)addr),"hosts.byaddr", af);
+}
diff --git a/cpukit/libnetworking/libc/gethostnamadr.c b/cpukit/libnetworking/libc/gethostnamadr.c
new file mode 100644
index 0000000000..92f7a21014
--- /dev/null
+++ b/cpukit/libnetworking/libc/gethostnamadr.c
@@ -0,0 +1,224 @@
+/*-
+ * Copyright (c) 1994, Garrett Wollman
+ *
+ * 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 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 REGENTS 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)$Id$";
+static char rcsid[] = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <arpa/nameser.h> /* XXX hack for _res */
+#include <resolv.h> /* XXX hack for _res */
+
+#define _PATH_HOSTCONF "/etc/host.conf"
+
+enum service_type {
+ SERVICE_NONE = 0,
+ SERVICE_BIND,
+ SERVICE_HOSTS,
+ SERVICE_NIS };
+#define SERVICE_MAX SERVICE_NIS
+
+static struct {
+ const char *name;
+ enum service_type type;
+} service_names[] = {
+ { "hosts", SERVICE_HOSTS },
+ { "/etc/hosts", SERVICE_HOSTS },
+ { "hosttable", SERVICE_HOSTS },
+ { "htable", SERVICE_HOSTS },
+ { "bind", SERVICE_BIND },
+ { "dns", SERVICE_BIND },
+ { "domain", SERVICE_BIND },
+ { "yp", SERVICE_NIS },
+ { "yellowpages", SERVICE_NIS },
+ { "nis", SERVICE_NIS },
+ { 0, SERVICE_NONE }
+};
+
+static enum service_type service_order[SERVICE_MAX + 1];
+static int service_done = 0;
+
+static enum service_type
+get_service_name(const char *name) {
+ int i;
+ for(i = 0; service_names[i].type != SERVICE_NONE; i++) {
+ if(!strcasecmp(name, service_names[i].name)) {
+ return service_names[i].type;
+ }
+ }
+ return SERVICE_NONE;
+}
+
+static void
+init_services()
+{
+ char *cp, *p, buf[BUFSIZ];
+ register int cc = 0;
+ FILE *fd;
+
+ if ((fd = (FILE *)fopen(_PATH_HOSTCONF, "r")) == NULL) {
+ /* make some assumptions */
+ service_order[0] = SERVICE_BIND;
+ service_order[1] = SERVICE_HOSTS;
+ service_order[2] = SERVICE_NONE;
+ } else {
+ while (fgets(buf, BUFSIZ, fd) != NULL && cc < SERVICE_MAX) {
+ if(buf[0] == '#')
+ continue;
+
+ p = buf;
+ while ((cp = strsep(&p, "\n \t,:;")) != NULL && *cp == '\0')
+ ;
+ if (cp == NULL)
+ continue;
+ do {
+ if (isalpha((int)cp[0])) {
+ service_order[cc] = get_service_name(cp);
+ if(service_order[cc] != SERVICE_NONE)
+ cc++;
+ }
+ while ((cp = strsep(&p, "\n \t,:;")) != NULL && *cp == '\0')
+ ;
+ } while(cp != NULL && cc < SERVICE_MAX);
+ }
+ service_order[cc] = SERVICE_NONE;
+ fclose(fd);
+ }
+ service_done = 1;
+}
+
+struct hostent *
+gethostbyname(const char *name)
+{
+ struct hostent *hp;
+
+ if (_res.options & RES_USE_INET6) { /* XXX */
+ hp = gethostbyname2(name, AF_INET6); /* XXX */
+ if (hp) /* XXX */
+ return (hp); /* XXX */
+ } /* XXX */
+ return (gethostbyname2(name, AF_INET));
+}
+
+struct hostent *
+gethostbyname2(const char *name, int type)
+{
+ struct hostent *hp = 0;
+ int nserv = 0;
+
+ if (!service_done)
+ init_services();
+
+ while (!hp) {
+ switch (service_order[nserv]) {
+ case SERVICE_NONE:
+ return NULL;
+ case SERVICE_HOSTS:
+ hp = _gethostbyhtname(name, type);
+ break;
+ case SERVICE_BIND:
+ hp = _gethostbydnsname(name, type);
+ break;
+ case SERVICE_NIS:
+ hp = _gethostbynisname(name, type);
+ break;
+ }
+ nserv++;
+ }
+ return hp;
+}
+
+struct hostent *
+gethostbyaddr(const char *addr, int len, int type)
+{
+ struct hostent *hp = 0;
+ int nserv = 0;
+
+ if (!service_done)
+ init_services();
+
+ while (!hp) {
+ switch (service_order[nserv]) {
+ case SERVICE_NONE:
+ return 0;
+ case SERVICE_HOSTS:
+ hp = _gethostbyhtaddr(addr, len, type);
+ break;
+ case SERVICE_BIND:
+ hp = _gethostbydnsaddr(addr, len, type);
+ break;
+ case SERVICE_NIS:
+ hp = _gethostbynisaddr(addr, len, type);
+ break;
+ }
+ nserv++;
+ }
+ return hp;
+}
+
+#ifdef _THREAD_SAFE
+struct hostent_data;
+
+/*
+ * Temporary function (not thread safe)
+ */
+int gethostbyaddr_r(const char *addr, int len, int type,
+ struct hostent *result, struct hostent_data *buffer)
+{
+ struct hostent *hp;
+ int ret;
+ if ((hp = gethostbyaddr(addr, len, type)) == NULL) {
+ ret = -1;
+ } else {
+ memcpy(result, hp, sizeof(struct hostent));
+ ret = 0;
+ }
+ return(ret);
+}
+#endif
+
+void
+sethostent(stayopen)
+ int stayopen;
+{
+ _sethosthtent(stayopen);
+ _sethostdnsent(stayopen);
+}
+
+void
+endhostent()
+{
+ _endhosthtent();
+ _endhostdnsent();
+}
diff --git a/cpukit/libnetworking/libc/gethostname.c b/cpukit/libnetworking/libc/gethostname.c
new file mode 100644
index 0000000000..81dc2267c2
--- /dev/null
+++ b/cpukit/libnetworking/libc/gethostname.c
@@ -0,0 +1,26 @@
+/*
+ * $Id$
+ */
+
+#include "config.h"
+
+/*
+ * Solaris doesn't include the gethostname call by default.
+ */
+#include <sys/utsname.h>
+#include <sys/systeminfo.h>
+
+#include <netdb.h>
+
+/*
+ * PUBLIC: #ifndef HAVE_GETHOSTNAME
+ * PUBLIC: int gethostname __P((char *, int));
+ * PUBLIC: #endif
+ */
+int
+gethostname(host, len)
+ char *host;
+ int len;
+{
+ return (sysinfo(SI_HOSTNAME, host, len) == -1 ? -1 : 0);
+}
diff --git a/cpukit/libnetworking/libc/getnetbydns.c b/cpukit/libnetworking/libc/getnetbydns.c
new file mode 100644
index 0000000000..8f8c576332
--- /dev/null
+++ b/cpukit/libnetworking/libc/getnetbydns.c
@@ -0,0 +1,313 @@
+/*-
+ * Copyright (c) 1985, 1988, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ * -
+ * --Copyright--
+ */
+/* Portions Copyright (c) 1993 Carlos Leandro and Rui Salgueiro
+ * Dep. Matematica Universidade de Coimbra, Portugal, Europe
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
+static char rcsid[] = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <stdio.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <syslog.h>
+
+#include "res_config.h"
+
+extern int h_errno;
+
+#define BYADDR 0
+#define BYNAME 1
+#define MAXALIASES 35
+
+#if PACKETSZ > 1024
+#define MAXPACKET PACKETSZ
+#else
+#define MAXPACKET 1024
+#endif
+
+typedef union {
+ HEADER hdr;
+ u_char buf[MAXPACKET];
+} querybuf;
+
+typedef union {
+ long al;
+ char ac;
+} align;
+
+static struct netent *
+getnetanswer(answer, anslen, net_i)
+ querybuf *answer;
+ int anslen;
+ int net_i;
+{
+
+ register HEADER *hp;
+ register u_char *cp;
+ register int n;
+ u_char *eom;
+ int type, class, buflen, ancount, qdcount, haveanswer, i, nchar;
+ char aux1[MAXHOSTNAMELEN], aux2[MAXHOSTNAMELEN], ans[MAXHOSTNAMELEN];
+ char *in, *st, *pauxt, *bp, **ap;
+ char *paux1 = &aux1[0], *paux2 = &aux2[0], flag = 0;
+static struct netent net_entry;
+static char *net_aliases[MAXALIASES], netbuf[PACKETSZ];
+
+ /*
+ * find first satisfactory answer
+ *
+ * answer --> +------------+ ( MESSAGE )
+ * | Header |
+ * +------------+
+ * | Question | the question for the name server
+ * +------------+
+ * | Answer | RRs answering the question
+ * +------------+
+ * | Authority | RRs pointing toward an authority
+ * | Additional | RRs holding additional information
+ * +------------+
+ */
+ eom = answer->buf + anslen;
+ hp = &answer->hdr;
+ ancount = ntohs(hp->ancount); /* #/records in the answer section */
+ qdcount = ntohs(hp->qdcount); /* #/entries in the question section */
+ bp = netbuf;
+ buflen = sizeof(netbuf);
+ cp = answer->buf + HFIXEDSZ;
+ if (!qdcount) {
+ if (hp->aa)
+ h_errno = HOST_NOT_FOUND;
+ else
+ h_errno = TRY_AGAIN;
+ return (NULL);
+ }
+ while (qdcount-- > 0)
+ cp += __dn_skipname(cp, eom) + QFIXEDSZ;
+ ap = net_aliases;
+ *ap = NULL;
+ net_entry.n_aliases = net_aliases;
+ haveanswer = 0;
+ while (--ancount >= 0 && cp < eom) {
+ n = dn_expand(answer->buf, eom, cp, bp, buflen);
+ if ((n < 0) || !res_dnok(bp))
+ break;
+ cp += n;
+ ans[0] = '\0';
+ (void)strncpy(&ans[0], bp, sizeof(ans) - 1);
+ ans[sizeof(ans) - 1] = '\0';
+ GETSHORT(type, cp);
+ GETSHORT(class, cp);
+ cp += INT32SZ; /* TTL */
+ GETSHORT(n, cp);
+ if (class == C_IN && type == T_PTR) {
+ n = dn_expand(answer->buf, eom, cp, bp, buflen);
+ if ((n < 0) || !res_hnok(bp)) {
+ cp += n;
+ return (NULL);
+ }
+ cp += n;
+ *ap++ = bp;
+ bp += strlen(bp) + 1;
+ net_entry.n_addrtype =
+ (class == C_IN) ? AF_INET : AF_UNSPEC;
+ haveanswer++;
+ }
+ }
+ if (haveanswer) {
+ *ap = NULL;
+ switch (net_i) {
+ case BYADDR:
+ net_entry.n_name = *net_entry.n_aliases;
+ net_entry.n_net = 0L;
+ break;
+ case BYNAME:
+ in = *net_entry.n_aliases;
+ net_entry.n_name = &ans[0];
+ aux2[0] = '\0';
+ for (i = 0; i < 4; i++) {
+ for (st = in, nchar = 0;
+ *st != '.';
+ st++, nchar++)
+ ;
+ if (nchar != 1 || *in != '0' || flag) {
+ flag = 1;
+ (void)strncpy(paux1,
+ (i==0) ? in : in-1,
+ (i==0) ?nchar : nchar+1);
+ paux1[(i==0) ? nchar : nchar+1] = '\0';
+ pauxt = paux2;
+ paux2 = strcat(paux1, paux2);
+ paux1 = pauxt;
+ }
+ in = ++st;
+ }
+ net_entry.n_net = inet_network(paux2);
+ break;
+ }
+ net_entry.n_aliases++;
+ return (&net_entry);
+ }
+ h_errno = TRY_AGAIN;
+ return (NULL);
+}
+
+struct netent *
+_getnetbydnsaddr(net, net_type)
+ register unsigned long net;
+ register int net_type;
+{
+ unsigned int netbr[4];
+ int nn, anslen;
+ querybuf buf;
+ char qbuf[MAXDNAME];
+ unsigned long net2;
+ struct netent *net_entry;
+
+ if (net_type != AF_INET)
+ return (NULL);
+
+ for (nn = 4, net2 = net; net2; net2 >>= 8)
+ netbr[--nn] = net2 & 0xff;
+ switch (nn) {
+ case 3: /* Class A */
+ sprintf(qbuf, "0.0.0.%u.in-addr.arpa", netbr[3]);
+ break;
+ case 2: /* Class B */
+ sprintf(qbuf, "0.0.%u.%u.in-addr.arpa", netbr[3], netbr[2]);
+ break;
+ case 1: /* Class C */
+ sprintf(qbuf, "0.%u.%u.%u.in-addr.arpa", netbr[3], netbr[2],
+ netbr[1]);
+ break;
+ case 0: /* Class D - E */
+ sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", netbr[3], netbr[2],
+ netbr[1], netbr[0]);
+ break;
+ }
+ anslen = res_query(qbuf, C_IN, T_PTR, (u_char *)&buf, sizeof(buf));
+ if (anslen < 0) {
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ printf("res_query failed\n");
+#endif
+ return (NULL);
+ }
+ net_entry = getnetanswer(&buf, anslen, BYADDR);
+ if (net_entry) {
+ unsigned u_net = net; /* maybe net should be unsigned ? */
+
+ /* Strip trailing zeros */
+ while ((u_net & 0xff) == 0 && u_net != 0)
+ u_net >>= 8;
+ net_entry->n_net = u_net;
+ return (net_entry);
+ }
+ return (NULL);
+}
+
+struct netent *
+_getnetbydnsname(net)
+ register const char *net;
+{
+ int anslen;
+ querybuf buf;
+ char qbuf[MAXDNAME];
+
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ h_errno = NETDB_INTERNAL;
+ return (NULL);
+ }
+ strncpy(qbuf, net, sizeof(qbuf) - 1);
+ qbuf[sizeof(qbuf) - 1] = '\0';
+ anslen = res_search(qbuf, C_IN, T_PTR, (u_char *)&buf, sizeof(buf));
+ if (anslen < 0) {
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ printf("res_query failed\n");
+#endif
+ return (NULL);
+ }
+ return getnetanswer(&buf, anslen, BYNAME);
+}
+
+void
+_setnetdnsent(stayopen)
+ int stayopen;
+{
+ if (stayopen)
+ _res.options |= RES_STAYOPEN | RES_USEVC;
+}
+
+void
+_endnetdnsent()
+{
+ _res.options &= ~(RES_STAYOPEN | RES_USEVC);
+ res_close();
+}
diff --git a/cpukit/libnetworking/libc/getnetbyht.c b/cpukit/libnetworking/libc/getnetbyht.c
new file mode 100644
index 0000000000..f7b7b1091d
--- /dev/null
+++ b/cpukit/libnetworking/libc/getnetbyht.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ */
+
+/* Portions Copyright (c) 1993 Carlos Leandro and Rui Salgueiro
+ * Dep. Matematica Universidade de Coimbra, Portugal, Europe
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * from getnetent.c 1.1 (Coimbra) 93/06/02
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getnetent.c 8.1 (Berkeley) 6/4/93";
+static char orig_rcsid[] = "From: Id: getnetent.c,v 8.4 1997/06/01 20:34:37 vixie Exp";
+static chat rcsid[] = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <string.h>
+
+#define MAXALIASES 35
+
+static FILE *netf;
+static char line[BUFSIZ+1];
+static struct netent net;
+static char *net_aliases[MAXALIASES];
+static int _net_stayopen;
+
+void
+_setnethtent(f)
+ int f;
+{
+
+ if (netf == NULL)
+ netf = fopen(_PATH_NETWORKS, "r" );
+ else
+ rewind(netf);
+ _net_stayopen |= f;
+}
+
+void
+_endnethtent()
+{
+
+ if (netf) {
+ fclose(netf);
+ netf = NULL;
+ }
+ _net_stayopen = 0;
+}
+
+struct netent *
+getnetent()
+{
+ char *p;
+ register char *cp, **q;
+
+ if (netf == NULL && (netf = fopen(_PATH_NETWORKS, "r" )) == NULL)
+ return (NULL);
+again:
+ p = fgets(line, sizeof line, netf);
+ if (p == NULL)
+ return (NULL);
+ if (*p == '#')
+ goto again;
+ cp = strpbrk(p, "#\n");
+ if (cp == NULL)
+ goto again;
+ *cp = '\0';
+ net.n_name = p;
+ cp = strpbrk(p, " \t");
+ if (cp == NULL)
+ goto again;
+ *cp++ = '\0';
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ p = strpbrk(cp, " \t");
+ if (p != NULL)
+ *p++ = '\0';
+ net.n_net = inet_network(cp);
+ net.n_addrtype = AF_INET;
+ q = net.n_aliases = net_aliases;
+ if (p != NULL)
+ cp = p;
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q < &net_aliases[MAXALIASES - 1])
+ *q++ = cp;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ }
+ *q = NULL;
+ return (&net);
+}
+
+struct netent *
+_getnetbyhtname(name)
+ register const char *name;
+{
+ register struct netent *p;
+ register char **cp;
+
+ setnetent(_net_stayopen);
+ while ( (p = getnetent()) ) {
+ if (strcasecmp(p->n_name, name) == 0)
+ break;
+ for (cp = p->n_aliases; *cp != 0; cp++)
+ if (strcasecmp(*cp, name) == 0)
+ goto found;
+ }
+found:
+ if (!_net_stayopen)
+ endnetent();
+ return (p);
+}
+
+struct netent *
+_getnetbyhtaddr(net, type)
+ register unsigned long net;
+ register int type;
+{
+ register struct netent *p;
+
+ setnetent(_net_stayopen);
+ while ( (p = getnetent()) )
+ if (p->n_addrtype == type && p->n_net == net)
+ break;
+ if (!_net_stayopen)
+ endnetent();
+ return (p);
+}
diff --git a/cpukit/libnetworking/libc/getnetbynis.c b/cpukit/libnetworking/libc/getnetbynis.c
new file mode 100644
index 0000000000..0549016ba2
--- /dev/null
+++ b/cpukit/libnetworking/libc/getnetbynis.c
@@ -0,0 +1,177 @@
+/*-
+ * Copyright (c) 1994, Garrett Wollman
+ *
+ * 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 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 REGENTS 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)$Id$";
+static char rcsid[] = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <arpa/nameser.h>
+#ifdef YP
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+
+#define MAXALIASES 35
+#define MAXADDRS 35
+
+#ifdef YP
+static char *host_aliases[MAXALIASES];
+#endif /* YP */
+
+static struct netent *
+_getnetbynis(name, map, af)
+ const char *name;
+ char *map;
+ int af;
+{
+#ifdef YP
+ register char *cp, **q;
+ static char *result;
+ int resultlen;
+ static struct netent h;
+ static char *domain = (char *)NULL;
+ static char ypbuf[YPMAXRECORD + 2];
+
+ switch(af) {
+ case AF_INET:
+ break;
+ default:
+ case AF_INET6:
+ errno = EAFNOSUPPORT;
+ return NULL;
+ }
+
+ if (domain == (char *)NULL)
+ if (yp_get_default_domain (&domain))
+ return (NULL);
+
+ if (yp_match(domain, map, name, strlen(name), &result, &resultlen))
+ return (NULL);
+
+ bcopy((char *)result, (char *)&ypbuf, resultlen);
+ ypbuf[resultlen] = '\0';
+ free(result);
+ result = (char *)&ypbuf;
+
+ if ((cp = index(result, '\n')))
+ *cp = '\0';
+
+ cp = strpbrk(result, " \t");
+ *cp++ = '\0';
+ h.n_name = result;
+
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+
+ h.n_net = inet_network(cp);
+ h.n_addrtype = AF_INET;
+
+ q = h.n_aliases = host_aliases;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q < &host_aliases[MAXALIASES - 1])
+ *q++ = cp;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ }
+ *q = NULL;
+ return (&h);
+#else
+ return (NULL);
+#endif
+}
+
+struct netent *
+_getnetbynisname(name)
+ const char *name;
+{
+ return _getnetbynis(name, "networks.byname", AF_INET);
+}
+
+struct netent *
+_getnetbynisaddr(addr, af)
+ unsigned long addr;
+ int af;
+{
+ char *str, *cp;
+ unsigned long net2;
+ int nn;
+ unsigned int netbr[4];
+ char buf[MAXDNAME];
+
+ if (af != AF_INET) {
+ errno = EAFNOSUPPORT;
+ return (NULL);
+ }
+
+ for (nn = 4, net2 = addr; net2; net2 >>= 8) {
+ netbr[--nn] = net2 & 0xff;
+ }
+
+ switch (nn) {
+ case 3: /* Class A */
+ sprintf(buf, "%u", netbr[3]);
+ break;
+ case 2: /* Class B */
+ sprintf(buf, "%u.%u", netbr[2], netbr[3]);
+ break;
+ case 1: /* Class C */
+ sprintf(buf, "%u.%u.%u", netbr[1], netbr[2], netbr[3]);
+ break;
+ case 0: /* Class D - E */
+ sprintf(buf, "%u.%u.%u.%u", netbr[0], netbr[1],
+ netbr[2], netbr[3]);
+ break;
+ }
+
+ str = (char *)&buf;
+ cp = str + (strlen(str) - 2);
+
+ while(!strcmp(cp, ".0")) {
+ *cp = '\0';
+ cp = str + (strlen(str) - 2);
+ }
+
+ return _getnetbynis(str, "networks.byaddr", af);
+}
diff --git a/cpukit/libnetworking/libc/getnetent.3 b/cpukit/libnetworking/libc/getnetent.3
new file mode 100644
index 0000000000..aec93b5876
--- /dev/null
+++ b/cpukit/libnetworking/libc/getnetent.3
@@ -0,0 +1,159 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. 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 the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+.\"
+.\" @(#)getnetent.3 8.1 (Berkeley) 6/4/93
+.\" $Id$
+.\"
+.Dd June 4, 1993
+.Dt GETNETENT 3
+.Os BSD 4.2
+.Sh NAME
+.Nm getnetent ,
+.Nm getnetbyaddr ,
+.Nm getnetbyname ,
+.Nm setnetent ,
+.Nm endnetent
+.Nd get network entry
+.Sh SYNOPSIS
+.Fd #include <netdb.h>
+.Ft struct netent *
+.Fn getnetent void
+.Ft struct netent *
+.Fn getnetbyname "const char *name"
+.Ft struct netent *
+.Fn getnetbyaddr "unsigned long net" "int type"
+.Ft void
+.Fn setnetent "int stayopen"
+.Ft void
+.Fn endnetent void
+.Sh DESCRIPTION
+The
+.Fn getnetent ,
+.Fn getnetbyname ,
+and
+.Fn getnetbyaddr
+functions
+each return a pointer to an object with the
+following structure
+containing the broken-out
+fields of a line in the network data base,
+.Pa /etc/networks .
+.Bd -literal -offset indent
+struct netent {
+ char *n_name; /* official name of net */
+ char **n_aliases; /* alias list */
+ int n_addrtype; /* net number type */
+ unsigned long n_net; /* net number */
+};
+.Ed
+.Pp
+The members of this structure are:
+.Bl -tag -width n_addrtype
+.It Fa n_name
+The official name of the network.
+.It Fa n_aliases
+A zero terminated list of alternate names for the network.
+.It Fa n_addrtype
+The type of the network number returned; currently only AF_INET.
+.It Fa n_net
+The network number. Network numbers are returned in machine byte
+order.
+.El
+.Pp
+The
+.Fn getnetent
+function
+reads the next line of the file, opening the file if necessary.
+.Pp
+The
+.Fn setnetent
+function
+opens and rewinds the file. If the
+.Fa stayopen
+flag is non-zero,
+the net data base will not be closed after each call to
+.Fn getnetbyname
+or
+.Fn getnetbyaddr .
+.Pp
+The
+.Fn endnetent
+function
+closes the file.
+.Pp
+The
+.Fn getnetbyname
+function
+and
+.Fn getnetbyaddr
+sequentially search from the beginning
+of the file until a matching
+net name or
+net address and type is found,
+or until
+.Dv EOF
+is encountered. The
+.Fa type
+must be
+.Dv AF_INET .
+Network numbers are supplied in host order.
+.Sh FILES
+.Bl -tag -width /etc/networks -compact
+.It Pa /etc/networks
+.El
+.Sh DIAGNOSTICS
+Null pointer
+(0) returned on
+.Dv EOF
+or error.
+.Sh SEE ALSO
+.Xr networks 5
+.Pp
+.%T RFC 1101
+.Sh HISTORY
+The
+.Fn getnetent ,
+.Fn getnetbyaddr ,
+.Fn getnetbyname ,
+.Fn setnetent ,
+and
+.Fn endnetent
+functions appeared in
+.Bx 4.2 .
+.Sh BUGS
+The data space used by
+these functions is static; if future use requires the data, it should be
+copied before any subsequent calls to these functions overwrite it.
+Only Internet network
+numbers are currently understood.
+Expecting network numbers to fit
+in no more than 32 bits is probably
+naive.
diff --git a/cpukit/libnetworking/libc/getnetnamadr.c b/cpukit/libnetworking/libc/getnetnamadr.c
new file mode 100644
index 0000000000..4d6597f98c
--- /dev/null
+++ b/cpukit/libnetworking/libc/getnetnamadr.c
@@ -0,0 +1,190 @@
+/*-
+ * Copyright (c) 1994, Garrett Wollman
+ *
+ * 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 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 REGENTS 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 defined(LIBC_SCCS) && !defined(lint)
+static char rcsid[] = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+
+#ifndef _PATH_NETCONF
+#define _PATH_NETCONF "/etc/host.conf"
+#endif
+
+enum service_type {
+ SERVICE_NONE = 0,
+ SERVICE_BIND,
+ SERVICE_TABLE,
+ SERVICE_NIS };
+#define SERVICE_MAX SERVICE_NIS
+
+static struct {
+ const char *name;
+ enum service_type type;
+} service_names[] = {
+ { "hosts", SERVICE_TABLE },
+ { "/etc/hosts", SERVICE_TABLE },
+ { "hosttable", SERVICE_TABLE },
+ { "htable", SERVICE_TABLE },
+ { "bind", SERVICE_BIND },
+ { "dns", SERVICE_BIND },
+ { "domain", SERVICE_BIND },
+ { "yp", SERVICE_NIS },
+ { "yellowpages", SERVICE_NIS },
+ { "nis", SERVICE_NIS },
+ { 0, SERVICE_NONE }
+};
+
+static enum service_type service_order[SERVICE_MAX + 1];
+static int service_done = 0;
+
+static enum service_type
+get_service_name(const char *name) {
+ int i;
+ for(i = 0; service_names[i].type != SERVICE_NONE; i++) {
+ if(!strcasecmp(name, service_names[i].name)) {
+ return service_names[i].type;
+ }
+ }
+ return SERVICE_NONE;
+}
+
+static void
+init_services()
+{
+ char *cp, *p, buf[BUFSIZ];
+ register int cc = 0;
+ FILE *fd;
+
+ if ((fd = (FILE *)fopen(_PATH_NETCONF, "r")) == NULL) {
+ /* make some assumptions */
+ service_order[0] = SERVICE_TABLE;
+ service_order[1] = SERVICE_NONE;
+ } else {
+ while (fgets(buf, BUFSIZ, fd) != NULL && cc < SERVICE_MAX) {
+ if(buf[0] == '#')
+ continue;
+
+ p = buf;
+ while ((cp = strsep(&p, "\n \t,:;")) != NULL && *cp == '\0')
+ ;
+ if (cp == NULL)
+ continue;
+ do {
+ if (isalpha(cp[0])) {
+ service_order[cc] = get_service_name(cp);
+ if(service_order[cc] != SERVICE_NONE)
+ cc++;
+ }
+ while ((cp = strsep(&p, "\n \t,:;")) != NULL && *cp == '\0')
+ ;
+ } while(cp != NULL && cc < SERVICE_MAX);
+ }
+ service_order[cc] = SERVICE_NONE;
+ fclose(fd);
+ }
+ service_done = 1;
+}
+
+struct netent *
+getnetbyname(const char *name)
+{
+ struct netent *hp = 0;
+ int nserv = 0;
+
+ if (!service_done)
+ init_services();
+
+ while (!hp) {
+ switch (service_order[nserv]) {
+ case SERVICE_NONE:
+ return NULL;
+ case SERVICE_TABLE:
+ hp = _getnetbyhtname(name);
+ break;
+ case SERVICE_BIND:
+ hp = _getnetbydnsname(name);
+ break;
+ case SERVICE_NIS:
+ hp = _getnetbynisname(name);
+ break;
+ }
+ nserv++;
+ }
+ return hp;
+}
+
+struct netent *
+getnetbyaddr(addr, af)
+ u_long addr;
+ int af;
+{
+ struct netent *hp = 0;
+ int nserv = 0;
+
+ if (!service_done)
+ init_services();
+
+ while (!hp) {
+ switch (service_order[nserv]) {
+ case SERVICE_NONE:
+ return 0;
+ case SERVICE_TABLE:
+ hp = _getnetbyhtaddr(addr, af);
+ break;
+ case SERVICE_BIND:
+ hp = _getnetbydnsaddr(addr, af);
+ break;
+ case SERVICE_NIS:
+ hp = _getnetbynisaddr(addr, af);
+ break;
+ }
+ nserv++;
+ }
+ return hp;
+}
+
+void
+setnetent(stayopen)
+ int stayopen;
+{
+ _setnethtent(stayopen);
+ _setnetdnsent(stayopen);
+}
+
+void
+endnetent()
+{
+ _endnethtent();
+ _endnetdnsent();
+}
diff --git a/cpukit/libnetworking/libc/getproto.c b/cpukit/libnetworking/libc/getproto.c
new file mode 100644
index 0000000000..67f59b4e86
--- /dev/null
+++ b/cpukit/libnetworking/libc/getproto.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getproto.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <netdb.h>
+
+extern int _proto_stayopen;
+
+extern struct protoent * getprotobynumber_static(int);
+
+struct protoent *
+getprotobynumber(proto)
+ register int proto;
+{
+ register struct protoent *p;
+
+ setprotoent(_proto_stayopen);
+ while ( (p = getprotoent()) )
+ if (p->p_proto == proto)
+ break;
+ if (!_proto_stayopen)
+ endprotoent();
+
+ if ( !p )
+ p = getprotobynumber_static(proto);
+ return (p);
+}
diff --git a/cpukit/libnetworking/libc/getprotoent.3 b/cpukit/libnetworking/libc/getprotoent.3
new file mode 100644
index 0000000000..784461d7e3
--- /dev/null
+++ b/cpukit/libnetworking/libc/getprotoent.3
@@ -0,0 +1,147 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. 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 the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+.\"
+.\" @(#)getprotoent.3 8.1 (Berkeley) 6/4/93
+.\" $Id$
+.\"
+.Dd June 4, 1993
+.Dt GETPROTOENT 3
+.Os BSD 4.2
+.Sh NAME
+.Nm getprotoent ,
+.Nm getprotobynumber ,
+.Nm getprotobyname ,
+.Nm setprotoent ,
+.Nm endprotoent
+.Nd get protocol entry
+.Sh SYNOPSIS
+.Fd #include <netdb.h>
+.Ft struct protoent *
+.Fn getprotoent void
+.Ft struct protoent *
+.Fn getprotobyname "const char *name"
+.Ft struct protoent *
+.Fn getprotobynumber "int proto"
+.Ft void
+.Fn setprotoent "int stayopen"
+.Ft void
+.Fn endprotoent void
+.Sh DESCRIPTION
+The
+.Fn getprotoent ,
+.Fn getprotobyname ,
+and
+.Fn getprotobynumber
+functions
+each return a pointer to an object with the
+following structure
+containing the broken-out
+fields of a line in the network protocol data base,
+.Pa /etc/protocols .
+.Bd -literal -offset indent
+.Pp
+struct protoent {
+ char *p_name; /* official name of protocol */
+ char **p_aliases; /* alias list */
+ int p_proto; /* protocol number */
+};
+.Ed
+.Pp
+The members of this structure are:
+.Bl -tag -width p_aliases
+.It Fa p_name
+The official name of the protocol.
+.It Fa p_aliases
+A zero terminated list of alternate names for the protocol.
+.It Fa p_proto
+The protocol number.
+.El
+.Pp
+The
+.Fn getprotoent
+function
+reads the next line of the file, opening the file if necessary.
+.Pp
+The
+.Fn setprotoent
+function
+opens and rewinds the file. If the
+.Fa stayopen
+flag is non-zero,
+the net data base will not be closed after each call to
+.Fn getprotobyname
+or
+.Fn getprotobynumber .
+.Pp
+The
+.Fn endprotoent
+function
+closes the file.
+.Pp
+The
+.Fn getprotobyname
+function
+and
+.Fn getprotobynumber
+sequentially search from the beginning
+of the file until a matching
+protocol name or
+protocol number is found,
+or until
+.Dv EOF
+is encountered.
+.Sh RETURN VALUES
+Null pointer
+(0) returned on
+.Dv EOF
+or error.
+.Sh FILES
+.Bl -tag -width /etc/protocols -compact
+.It Pa /etc/protocols
+.El
+.Sh SEE ALSO
+.Xr protocols 5
+.Sh HISTORY
+The
+.Fn getprotoent ,
+.Fn getprotobynumber ,
+.Fn getprotobyname ,
+.Fn setprotoent ,
+and
+.Fn endprotoent
+functions appeared in
+.Bx 4.2 .
+.Sh BUGS
+These functions use a static data space;
+if the data is needed for future use, it should be
+copied before any subsequent calls overwrite it.
+Only the Internet
+protocols are currently understood.
diff --git a/cpukit/libnetworking/libc/getprotoent.c b/cpukit/libnetworking/libc/getprotoent.c
new file mode 100644
index 0000000000..0b9cefec68
--- /dev/null
+++ b/cpukit/libnetworking/libc/getprotoent.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getprotoent.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define MAXALIASES 35
+
+static FILE *protof = NULL;
+static char line[BUFSIZ+1];
+static struct protoent proto;
+static char *proto_aliases[MAXALIASES];
+int _proto_stayopen;
+
+void
+setprotoent(f)
+ int f;
+{
+ if (protof == NULL)
+ protof = fopen(_PATH_PROTOCOLS, "r" );
+ else
+ rewind(protof);
+ _proto_stayopen |= f;
+}
+
+void
+endprotoent()
+{
+ if (protof) {
+ fclose(protof);
+ protof = NULL;
+ }
+ _proto_stayopen = 0;
+}
+
+struct protoent *
+getprotoent()
+{
+ char *p;
+ register char *cp, **q;
+
+ if (protof == NULL && (protof = fopen(_PATH_PROTOCOLS, "r" )) == NULL)
+ return (NULL);
+again:
+ if ((p = fgets(line, BUFSIZ, protof)) == NULL)
+ return (NULL);
+ if (*p == '#')
+ goto again;
+ cp = strpbrk(p, "#\n");
+ if (cp == NULL)
+ goto again;
+ *cp = '\0';
+ proto.p_name = p;
+ cp = strpbrk(p, " \t");
+ if (cp == NULL)
+ goto again;
+ *cp++ = '\0';
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ p = strpbrk(cp, " \t");
+ if (p != NULL)
+ *p++ = '\0';
+ proto.p_proto = atoi(cp);
+ q = proto.p_aliases = proto_aliases;
+ if (p != NULL) {
+ cp = p;
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q < &proto_aliases[MAXALIASES - 1])
+ *q++ = cp;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ }
+ }
+ *q = NULL;
+ return (&proto);
+}
diff --git a/cpukit/libnetworking/libc/getprotoname.c b/cpukit/libnetworking/libc/getprotoname.c
new file mode 100644
index 0000000000..e21e4c4f2a
--- /dev/null
+++ b/cpukit/libnetworking/libc/getprotoname.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getprotoname.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <netdb.h>
+#include <string.h>
+
+extern int _proto_stayopen;
+
+extern struct protoent *getprotobyname_static(const char *);
+
+struct protoent *
+getprotobyname(name)
+ register const char *name;
+{
+ register struct protoent *p;
+ register char **cp;
+
+ setprotoent(_proto_stayopen);
+ while ( (p = getprotoent()) ) {
+ if (strcmp(p->p_name, name) == 0)
+ break;
+ for (cp = p->p_aliases; *cp != 0; cp++)
+ if (strcmp(*cp, name) == 0)
+ goto found;
+ }
+found:
+ if (!_proto_stayopen)
+ endprotoent();
+
+ if ( !p )
+ p = getprotobyname_static(name);
+ return (p);
+}
diff --git a/cpukit/libnetworking/libc/getservbyname.c b/cpukit/libnetworking/libc/getservbyname.c
new file mode 100644
index 0000000000..19936907d3
--- /dev/null
+++ b/cpukit/libnetworking/libc/getservbyname.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getservbyname.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <netdb.h>
+#include <string.h>
+
+extern int _serv_stayopen;
+
+struct servent *
+getservbyname(name, proto)
+ const char *name, *proto;
+{
+ register struct servent *p;
+ register char **cp;
+
+#ifdef YP
+ extern char *___getservbyname_yp;
+ extern char *___getservbyproto_yp;
+
+ ___getservbyname_yp = (char *)name;
+ ___getservbyproto_yp = (char *)proto;
+#endif
+
+ setservent(_serv_stayopen);
+ while ( (p = getservent()) ) {
+ if (strcmp(name, p->s_name) == 0)
+ goto gotname;
+ for (cp = p->s_aliases; *cp; cp++)
+ if (strcmp(name, *cp) == 0)
+ goto gotname;
+ continue;
+gotname:
+ if (proto == 0 || strcmp(p->s_proto, proto) == 0)
+ break;
+ }
+ if (!_serv_stayopen)
+ endservent();
+
+#ifdef YP
+ ___getservbyname_yp = NULL;
+ ___getservbyproto_yp = NULL;
+#endif
+
+ return (p);
+}
diff --git a/cpukit/libnetworking/libc/getservbyport.c b/cpukit/libnetworking/libc/getservbyport.c
new file mode 100644
index 0000000000..c8433954e1
--- /dev/null
+++ b/cpukit/libnetworking/libc/getservbyport.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getservbyport.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <netdb.h>
+#include <string.h>
+
+extern int _serv_stayopen;
+
+struct servent *
+getservbyport(port, proto)
+ int port;
+ const char *proto;
+{
+ register struct servent *p;
+
+#ifdef YP
+ extern int ___getservbyport_yp;
+ extern char *___getservbyproto_yp;
+
+ ___getservbyport_yp = port;
+ ___getservbyproto_yp = (char *)proto;
+#endif
+
+ setservent(_serv_stayopen);
+ while ( (p = getservent()) ) {
+ if (p->s_port != port)
+ continue;
+ if (proto == 0 || strcmp(p->s_proto, proto) == 0)
+ break;
+ }
+ if (!_serv_stayopen)
+ endservent();
+
+#ifdef YP
+ ___getservbyport_yp = 0;
+ ___getservbyproto_yp = NULL;
+#endif
+
+ return (p);
+}
diff --git a/cpukit/libnetworking/libc/getservent.3 b/cpukit/libnetworking/libc/getservent.3
new file mode 100644
index 0000000000..79c18a3beb
--- /dev/null
+++ b/cpukit/libnetworking/libc/getservent.3
@@ -0,0 +1,156 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. 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 the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+.\"
+.\" From: @(#)getservent.3 8.3 (Berkeley) 1/12/94
+.\" $Id$
+.\"
+.Dd July 9, 1995
+.Dt GETSERVENT 3
+.Os BSD 4.2
+.Sh NAME
+.Nm getservent ,
+.Nm getservbyport ,
+.Nm getservbyname ,
+.Nm setservent ,
+.Nm endservent
+.Nd get service entry
+.Sh SYNOPSIS
+.Fd #include <netdb.h>
+.Ft struct servent *
+.Fn getservent
+.Ft struct servent *
+.Fn getservbyname "const char *name" "const char *proto"
+.Ft struct servent *
+.Fn getservbyport "int port" "const char *proto"
+.Ft void
+.Fn setservent "int stayopen"
+.Ft void
+.Fn endservent void
+.Sh DESCRIPTION
+The
+.Fn getservent ,
+.Fn getservbyname ,
+and
+.Fn getservbyport
+functions
+each return a pointer to an object with the
+following structure
+containing the broken-out
+fields of a line in the network services data base,
+.Pa /etc/services .
+.Bd -literal -offset indent
+struct servent {
+ char *s_name; /* official name of service */
+ char **s_aliases; /* alias list */
+ int s_port; /* port service resides at */
+ char *s_proto; /* protocol to use */
+};
+.Ed
+.Pp
+The members of this structure are:
+.Bl -tag -width s_aliases
+.It Fa s_name
+The official name of the service.
+.It Fa s_aliases
+A zero terminated list of alternate names for the service.
+.It Fa s_port
+The port number at which the service resides.
+Port numbers are returned in network byte order.
+.It Fa s_proto
+The name of the protocol to use when contacting the
+service.
+.El
+.Pp
+The
+.Fn getservent
+function
+reads the next line of the file, opening the file if necessary.
+.Pp
+The
+.Fn setservent
+function
+opens and rewinds the file. If the
+.Fa stayopen
+flag is non-zero,
+the net data base will not be closed after each call to
+.Fn getservbyname
+or
+.Fn getservbyport .
+.Pp
+The
+.Fn endservent
+function
+closes the file.
+.Pp
+The
+.Fn getservbyname
+and
+.Fn getservbyport
+functions
+sequentially search from the beginning
+of the file until a matching
+protocol name or
+port number is found,
+or until
+.Dv EOF
+is encountered.
+If a protocol name is also supplied (non-
+.Dv NULL ) ,
+searches must also match the protocol.
+.ne 1i
+.Sh FILES
+.Bl -tag -width /etc/services -compact
+.It Pa /etc/services
+.El
+.Sh DIAGNOSTICS
+Null pointer
+(0) returned on
+.Dv EOF
+or error.
+.Sh SEE ALSO
+.Xr getprotoent 3 ,
+.Xr services 5
+.Sh HISTORY
+The
+.Fn getservent ,
+.Fn getservbyport ,
+.Fn getservbyname ,
+.Fn setservent ,
+and
+.Fn endservent
+functions appeared in
+.Bx 4.2 .
+.Sh BUGS
+These functions use static data storage;
+if the data is needed for future use, it should be
+copied before any subsequent calls overwrite it.
+Expecting port numbers to fit in a 32 bit
+quantity is probably naive.
diff --git a/cpukit/libnetworking/libc/getservent.c b/cpukit/libnetworking/libc/getservent.c
new file mode 100644
index 0000000000..4619e47795
--- /dev/null
+++ b/cpukit/libnetworking/libc/getservent.c
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getservent.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#ifdef YP
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+static int serv_stepping_yp = 0;
+extern int _yp_check __P(( char ** ));
+#endif
+
+
+#define MAXALIASES 35
+
+static FILE *servf = NULL;
+static char line[BUFSIZ+1];
+static struct servent serv;
+static char *serv_aliases[MAXALIASES];
+int _serv_stayopen;
+
+#ifdef YP
+char *___getservbyname_yp = NULL;
+char *___getservbyproto_yp = NULL;
+int ___getservbyport_yp = 0;
+static char *yp_domain = NULL;
+
+static int
+_getservbyport_yp(line)
+ char *line;
+{
+ char *result;
+ int resultlen;
+ char buf[YPMAXRECORD + 2];
+ int rv;
+
+ snprintf(buf, sizeof(buf), "%d/%s", ntohs(___getservbyport_yp),
+ ___getservbyproto_yp);
+
+ ___getservbyport_yp = 0;
+ ___getservbyproto_yp = NULL;
+
+ if(!yp_domain) {
+ if(yp_get_default_domain(&yp_domain))
+ return (0);
+ }
+
+ /*
+ * We have to be a little flexible here. Ideally you're supposed
+ * to have both a services.byname and a services.byport map, but
+ * some systems have only services.byname. FreeBSD cheats a little
+ * by putting the services.byport information in the same map as
+ * services.byname so that either case will work. We allow for both
+ * possibilities here: if there is no services.byport map, we try
+ * services.byname instead.
+ */
+ if ((rv = yp_match(yp_domain, "services.byport", buf, strlen(buf),
+ &result, &resultlen))) {
+ if (rv == YPERR_MAP) {
+ if (yp_match(yp_domain, "services.byname", buf,
+ strlen(buf), &result, &resultlen))
+ return(0);
+ } else
+ return(0);
+ }
+
+ /* getservent() expects lines terminated with \n -- make it happy */
+ snprintf(line, BUFSIZ, "%.*s\n", resultlen, result);
+
+ free(result);
+ return(1);
+}
+
+static int
+_getservbyname_yp(line)
+ char *line;
+{
+ char *result;
+ int resultlen;
+ char buf[YPMAXRECORD + 2];
+
+ if(!yp_domain) {
+ if(yp_get_default_domain(&yp_domain))
+ return (0);
+ }
+
+ snprintf(buf, sizeof(buf), "%s/%s", ___getservbyname_yp,
+ ___getservbyproto_yp);
+
+ ___getservbyname_yp = 0;
+ ___getservbyproto_yp = NULL;
+
+ if (yp_match(yp_domain, "services.byname", buf, strlen(buf),
+ &result, &resultlen)) {
+ return(0);
+ }
+
+ /* getservent() expects lines terminated with \n -- make it happy */
+ snprintf(line, BUFSIZ, "%.*s\n", resultlen, result);
+
+ free(result);
+ return(1);
+}
+
+static int
+_getservent_yp(line)
+ char *line;
+{
+ static char *key = NULL;
+ static int keylen;
+ char *lastkey, *result;
+ int resultlen;
+ int rv;
+
+ if(!yp_domain) {
+ if(yp_get_default_domain(&yp_domain))
+ return (0);
+ }
+
+ if (!serv_stepping_yp) {
+ if (key)
+ free(key);
+ if ((rv = yp_first(yp_domain, "services.byname", &key, &keylen,
+ &result, &resultlen))) {
+ serv_stepping_yp = 0;
+ return(0);
+ }
+ serv_stepping_yp = 1;
+ } else {
+ lastkey = key;
+ rv = yp_next(yp_domain, "services.byname", key, keylen, &key,
+ &keylen, &result, &resultlen);
+ free(lastkey);
+ if (rv) {
+ serv_stepping_yp = 0;
+ return (0);
+ }
+ }
+
+ /* getservent() expects lines terminated with \n -- make it happy */
+ snprintf(line, BUFSIZ, "%.*s\n", resultlen, result);
+
+ free(result);
+
+ return(1);
+}
+#endif
+
+void
+setservent(f)
+ int f;
+{
+ if (servf == NULL)
+ servf = fopen(_PATH_SERVICES, "r" );
+ else
+ rewind(servf);
+ _serv_stayopen |= f;
+}
+
+void
+endservent()
+{
+ if (servf) {
+ fclose(servf);
+ servf = NULL;
+ }
+ _serv_stayopen = 0;
+}
+
+struct servent *
+getservent()
+{
+ char *p;
+ register char *cp, **q;
+
+#ifdef YP
+ if (serv_stepping_yp && _getservent_yp(line)) {
+ p = (char *)&line;
+ goto unpack;
+ }
+tryagain:
+#endif
+ if (servf == NULL && (servf = fopen(_PATH_SERVICES, "r" )) == NULL)
+ return (NULL);
+again:
+ if ((p = fgets(line, BUFSIZ, servf)) == NULL)
+ return (NULL);
+#ifdef YP
+ if (*p == '+' && _yp_check(NULL)) {
+ if (___getservbyname_yp != NULL) {
+ if (!_getservbyname_yp(line))
+ goto tryagain;
+ }
+ else if (___getservbyport_yp != 0) {
+ if (!_getservbyport_yp(line))
+ goto tryagain;
+ }
+ else if (!_getservent_yp(line))
+ goto tryagain;
+ }
+unpack:
+#endif
+ if (*p == '#')
+ goto again;
+ cp = strpbrk(p, "#\n");
+ if (cp == NULL)
+ goto again;
+ *cp = '\0';
+ serv.s_name = p;
+ p = strpbrk(p, " \t");
+ if (p == NULL)
+ goto again;
+ *p++ = '\0';
+ while (*p == ' ' || *p == '\t')
+ p++;
+ cp = strpbrk(p, ",/");
+ if (cp == NULL)
+ goto again;
+ *cp++ = '\0';
+ serv.s_port = htons((u_short)atoi(p));
+ serv.s_proto = cp;
+ q = serv.s_aliases = serv_aliases;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q < &serv_aliases[MAXALIASES - 1])
+ *q++ = cp;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ }
+ *q = NULL;
+ return (&serv);
+}
diff --git a/cpukit/libnetworking/libc/herror.c b/cpukit/libnetworking/libc/herror.c
new file mode 100644
index 0000000000..ba1dae934d
--- /dev/null
+++ b/cpukit/libnetworking/libc/herror.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 1987, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ */
+
+/*
+ * Portions Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)herror.c 8.1 (Berkeley) 6/4/93";
+static char rcsid[] = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <netdb.h>
+#include <string.h>
+#include <unistd.h>
+
+const char *h_errlist[] = {
+ "Resolver Error 0 (no error)",
+ "Unknown host", /* 1 HOST_NOT_FOUND */
+ "Host name lookup failure", /* 2 TRY_AGAIN */
+ "Unknown server error", /* 3 NO_RECOVERY */
+ "No address associated with name", /* 4 NO_ADDRESS */
+};
+int h_nerr = { sizeof h_errlist / sizeof h_errlist[0] };
+
+int h_errno;
+
+/*
+ * herror --
+ * print the error indicated by the h_errno value.
+ */
+void
+herror(s)
+ const char *s;
+{
+#if 0
+ struct iovec iov[4];
+ register struct iovec *v = iov;
+
+ if (s && *s) {
+ v->iov_base = (char *)s;
+ v->iov_len = strlen(s);
+ v++;
+ v->iov_base = ": ";
+ v->iov_len = 2;
+ v++;
+ }
+ v->iov_base = (char *)hstrerror(h_errno);
+ v->iov_len = strlen(v->iov_base);
+ v++;
+ v->iov_base = "\n";
+ v->iov_len = 1;
+ writev(STDERR_FILENO, iov, (v - iov) + 1);
+#else
+ /*
+ * RTEMS: no writev yet
+ */
+ if (s && *s) {
+ write (2, s, strlen (s));
+ write (2, ": ", 2);
+ }
+ s = (char *)hstrerror(h_errno);
+ write (2, s, strlen (s));
+ write (2, "\n", 1);
+#endif
+}
+
+const char *
+hstrerror(err)
+ int err;
+{
+ if (err < 0)
+ return ("Resolver internal error");
+ else if (err < h_nerr)
+ return (h_errlist[err]);
+ return ("Unknown resolver error");
+}
diff --git a/cpukit/libnetworking/libc/inet.3 b/cpukit/libnetworking/libc/inet.3
new file mode 100644
index 0000000000..1052f538f2
--- /dev/null
+++ b/cpukit/libnetworking/libc/inet.3
@@ -0,0 +1,210 @@
+.\" Copyright (c) 1983, 1990, 1991, 1993
+.\" The Regents of the University of California. 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 the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+.\"
+.\" From: @(#)inet.3 8.1 (Berkeley) 6/4/93
+.\" $Id$
+.\"
+.Dd June 17, 1996
+.Dt INET 3
+.Os BSD 4.2
+.Sh NAME
+.Nm inet_aton ,
+.Nm inet_addr ,
+.Nm inet_network ,
+.Nm inet_ntoa ,
+.Nm inet_makeaddr ,
+.Nm inet_lnaof ,
+.Nm inet_netof
+.Nd Internet address manipulation routines
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/socket.h>
+.Fd #include <netinet/in.h>
+.Fd #include <arpa/inet.h>
+.Ft int
+.Fn inet_aton "const char *cp" "struct in_addr *pin"
+.Ft unsigned long
+.Fn inet_addr "const char *cp"
+.Ft unsigned long
+.Fn inet_network "const char *cp"
+.Ft char *
+.Fn inet_ntoa "struct in_addr in"
+.Ft struct in_addr
+.Fn inet_makeaddr "unsigned long net" "unsigned long lna"
+.Ft unsigned long
+.Fn inet_lnaof "struct in_addr in"
+.Ft unsigned long
+.Fn inet_netof "struct in_addr in"
+.Sh DESCRIPTION
+The routines
+.Fn inet_aton ,
+.Fn inet_addr
+and
+.Fn inet_network
+interpret character strings representing
+numbers expressed in the Internet standard
+.Ql \&.
+notation.
+The
+.Fn inet_aton
+routine interprets the specified character string as an Internet address,
+placing the address into the structure provided.
+It returns 1 if the string was successfully interpreted,
+or 0 if the string is invalid.
+The
+.Fn inet_addr
+and
+.Fn inet_network
+functions return numbers suitable for use
+as Internet addresses and Internet network
+numbers, respectively.
+The routine
+.Fn inet_ntoa
+takes an Internet address and returns an
+.Tn ASCII
+string representing the address in
+.Ql \&.
+notation. The routine
+.Fn inet_makeaddr
+takes an Internet network number and a local
+network address and constructs an Internet address
+from it. The routines
+.Fn inet_netof
+and
+.Fn inet_lnaof
+break apart Internet host addresses, returning
+the network number and local network address part,
+respectively.
+.Pp
+All Internet addresses are returned in network
+order (bytes ordered from left to right).
+All network numbers and local address parts are
+returned as machine format integer values.
+.Sh INTERNET ADDRESSES
+Values specified using the
+.Ql \&.
+notation take one
+of the following forms:
+.Bd -literal -offset indent
+a.b.c.d
+a.b.c
+a.b
+a
+.Ed
+.Pp
+When four parts are specified, each is interpreted
+as a byte of data and assigned, from left to right,
+to the four bytes of an Internet address. Note
+that when an Internet address is viewed as a 32-bit
+integer quantity on the
+.Tn VAX
+the bytes referred to
+above appear as
+.Dq Li d.c.b.a .
+That is,
+.Tn VAX
+bytes are
+ordered from right to left.
+.Pp
+When a three part address is specified, the last
+part is interpreted as a 16-bit quantity and placed
+in the right-most two bytes of the network address.
+This makes the three part address format convenient
+for specifying Class B network addresses as
+.Dq Li 128.net.host .
+.Pp
+When a two part address is supplied, the last part
+is interpreted as a 24-bit quantity and placed in
+the right most three bytes of the network address.
+This makes the two part address format convenient
+for specifying Class A network addresses as
+.Dq Li net.host .
+.Pp
+When only one part is given, the value is stored
+directly in the network address without any byte
+rearrangement.
+.Pp
+All numbers supplied as
+.Dq parts
+in a
+.Ql \&.
+notation
+may be decimal, octal, or hexadecimal, as specified
+in the C language (i.e., a leading 0x or 0X implies
+hexadecimal; otherwise, a leading 0 implies octal;
+otherwise, the number is interpreted as decimal).
+.Pp
+The
+.Fn inet_aton
+and
+.Fn inet_ntoa
+functions are semi-deprecated in favor of the
+.Xr addr2ascii 3
+family. However, since those functions are not yet widely implemented,
+portable programs cannot rely on their presence and will continue
+to use the
+.Xr inet 3
+functions for some time.
+.Sh DIAGNOSTICS
+The constant
+.Dv INADDR_NONE
+is returned by
+.Fn inet_addr
+and
+.Fn inet_network
+for malformed requests.
+.Sh SEE ALSO
+.Xr addr2ascii 3 ,
+.Xr gethostbyname 3 ,
+.Xr getnetent 3 ,
+.Xr hosts 5 ,
+.Xr networks 5
+.Sh HISTORY
+These
+functions appeared in
+.Bx 4.2 .
+.Sh BUGS
+The value
+.Dv INADDR_NONE
+(0xffffffff) is a valid broadcast address, but
+.Fn inet_addr
+cannot return that value without indicating failure.
+The newer
+.Fn inet_aton
+function does not share this problem.
+The problem of host byte ordering versus network byte ordering is
+confusing.
+The string returned by
+.Fn inet_ntoa
+resides in a static memory area.
+.Pp
+Inet_addr should return a
+.Fa struct in_addr .
diff --git a/cpukit/libnetworking/libc/inet_addr.c b/cpukit/libnetworking/libc/inet_addr.c
new file mode 100644
index 0000000000..225ccc1269
--- /dev/null
+++ b/cpukit/libnetworking/libc/inet_addr.c
@@ -0,0 +1,180 @@
+/*
+ * ++Copyright++ 1983, 1990, 1993
+ * -
+ * Copyright (c) 1983, 1990, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ * -
+ * --Copyright--
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93";
+static char rcsid[] = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <ctype.h>
+
+/*
+ * Ascii internet address interpretation routine.
+ * The value returned is in network order.
+ */
+u_long
+inet_addr(cp)
+ register const char *cp;
+{
+ struct in_addr val;
+
+ if (inet_aton(cp, &val))
+ return (val.s_addr);
+ return (INADDR_NONE);
+}
+
+/*
+ * Check whether "cp" is a valid ascii representation
+ * of an Internet address and convert to a binary address.
+ * Returns 1 if the address is valid, 0 if not.
+ * This replaces inet_addr, the return value from which
+ * cannot distinguish between failure and a local broadcast address.
+ */
+int
+inet_aton(cp, addr)
+ register const char *cp;
+ struct in_addr *addr;
+{
+ register u_long val;
+ register int base, n;
+ register char c;
+ u_int parts[4];
+ register u_int *pp = parts;
+
+ c = *cp;
+ for (;;) {
+ /*
+ * Collect number up to ``.''.
+ * Values are specified as for C:
+ * 0x=hex, 0=octal, isdigit=decimal.
+ */
+ if (!isdigit((int)c))
+ return (0);
+ val = 0; base = 10;
+ if (c == '0') {
+ c = *++cp;
+ if (c == 'x' || c == 'X')
+ base = 16, c = *++cp;
+ else
+ base = 8;
+ }
+ for (;;) {
+ if (isascii((int)c) && isdigit((int)c)) {
+ val = (val * base) + (c - '0');
+ c = *++cp;
+ } else if (base == 16 && isascii((int)c) && isxdigit((int)c)) {
+ val = (val << 4) |
+ (c + 10 - (islower((int)c) ? 'a' : 'A'));
+ c = *++cp;
+ } else
+ break;
+ }
+ if (c == '.') {
+ /*
+ * Internet format:
+ * a.b.c.d
+ * a.b.c (with c treated as 16 bits)
+ * a.b (with b treated as 24 bits)
+ */
+ if (pp >= parts + 3)
+ return (0);
+ *pp++ = val;
+ c = *++cp;
+ } else
+ break;
+ }
+ /*
+ * Check for trailing characters.
+ */
+ if (c != '\0' && (!isascii((int)c) || !isspace((int)c)))
+ return (0);
+ /*
+ * Concoct the address according to
+ * the number of parts specified.
+ */
+ n = pp - parts + 1;
+ switch (n) {
+
+ case 0:
+ return (0); /* initial nondigit */
+
+ case 1: /* a -- 32 bits */
+ break;
+
+ case 2: /* a.b -- 8.24 bits */
+ if (val > 0xffffff)
+ return (0);
+ val |= parts[0] << 24;
+ break;
+
+ case 3: /* a.b.c -- 8.8.16 bits */
+ if (val > 0xffff)
+ return (0);
+ val |= (parts[0] << 24) | (parts[1] << 16);
+ break;
+
+ case 4: /* a.b.c.d -- 8.8.8.8 bits */
+ if (val > 0xff)
+ return (0);
+ val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
+ break;
+ }
+ if (addr)
+ addr->s_addr = htonl(val);
+ return (1);
+}
diff --git a/cpukit/libnetworking/libc/inet_lnaof.c b/cpukit/libnetworking/libc/inet_lnaof.c
new file mode 100644
index 0000000000..6ec6a9aef1
--- /dev/null
+++ b/cpukit/libnetworking/libc/inet_lnaof.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)inet_lnaof.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+/*
+ * Return the local network address portion of an
+ * internet address; handles class a/b/c network
+ * number formats.
+ */
+u_long
+inet_lnaof(in)
+ struct in_addr in;
+{
+ register u_long i = ntohl(in.s_addr);
+
+ if (IN_CLASSA(i))
+ return ((i)&IN_CLASSA_HOST);
+ else if (IN_CLASSB(i))
+ return ((i)&IN_CLASSB_HOST);
+ else
+ return ((i)&IN_CLASSC_HOST);
+}
diff --git a/cpukit/libnetworking/libc/inet_makeaddr.c b/cpukit/libnetworking/libc/inet_makeaddr.c
new file mode 100644
index 0000000000..ce84170ed9
--- /dev/null
+++ b/cpukit/libnetworking/libc/inet_makeaddr.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)inet_makeaddr.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+/*
+ * Formulate an Internet address from network + host. Used in
+ * building addresses stored in the ifnet structure.
+ */
+struct in_addr
+inet_makeaddr(net, host)
+ u_long net, host;
+{
+ u_long addr;
+
+ if (net < 128)
+ addr = (net << IN_CLASSA_NSHIFT) | (host & IN_CLASSA_HOST);
+ else if (net < 65536)
+ addr = (net << IN_CLASSB_NSHIFT) | (host & IN_CLASSB_HOST);
+ else if (net < 16777216L)
+ addr = (net << IN_CLASSC_NSHIFT) | (host & IN_CLASSC_HOST);
+ else
+ addr = net | host;
+ addr = htonl(addr);
+ return (*(struct in_addr *)&addr);
+}
diff --git a/cpukit/libnetworking/libc/inet_net_ntop.c b/cpukit/libnetworking/libc/inet_net_ntop.c
new file mode 100644
index 0000000000..4c7893d417
--- /dev/null
+++ b/cpukit/libnetworking/libc/inet_net_ntop.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char orig_rcsid[] = "From Id: inet_net_ntop.c,v 8.2 1996/08/08 06:54:44 vixie Exp";
+static const char rcsid[] = "$Id$";
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+static char * inet_net_ntop_ipv4 __P((const u_char *src, int bits,
+ char *dst, size_t size));
+
+/*
+ * char *
+ * inet_net_ntop(af, src, bits, dst, size)
+ * convert network number from network to presentation format.
+ * generates CIDR style result always.
+ * return:
+ * pointer to dst, or NULL if an error occurred (check errno).
+ * author:
+ * Paul Vixie (ISC), July 1996
+ */
+char *
+inet_net_ntop(af, src, bits, dst, size)
+ int af;
+ const void *src;
+ int bits;
+ char *dst;
+ size_t size;
+{
+ switch (af) {
+ case AF_INET:
+ return (inet_net_ntop_ipv4(src, bits, dst, size));
+ default:
+ errno = EAFNOSUPPORT;
+ return (NULL);
+ }
+}
+
+/*
+ * static char *
+ * inet_net_ntop_ipv4(src, bits, dst, size)
+ * convert IPv4 network number from network to presentation format.
+ * generates CIDR style result always.
+ * return:
+ * pointer to dst, or NULL if an error occurred (check errno).
+ * note:
+ * network byte order assumed. this means 192.5.5.240/28 has
+ * 0x11110000 in its fourth octet.
+ * author:
+ * Paul Vixie (ISC), July 1996
+ */
+static char *
+inet_net_ntop_ipv4(src, bits, dst, size)
+ const u_char *src;
+ int bits;
+ char *dst;
+ size_t size;
+{
+ char *odst = dst;
+ char *t;
+ u_int m;
+ int b;
+
+ if (bits < 0 || bits > 32) {
+ errno = EINVAL;
+ return (NULL);
+ }
+ if (bits == 0) {
+ if (size < sizeof "0")
+ goto emsgsize;
+ *dst++ = '0';
+ *dst = '\0';
+ }
+
+ /* Format whole octets. */
+ for (b = bits / 8; b > 0; b--) {
+ if (size < sizeof "255.")
+ goto emsgsize;
+ t = dst;
+ dst += SPRINTF((dst, "%u", *src++));
+ if (b > 1) {
+ *dst++ = '.';
+ *dst = '\0';
+ }
+ size -= (size_t)(dst - t);
+ }
+
+ /* Format partial octet. */
+ b = bits % 8;
+ if (b > 0) {
+ if (size < sizeof ".255")
+ goto emsgsize;
+ t = dst;
+ if (dst != odst)
+ *dst++ = '.';
+ m = ((1 << b) - 1) << (8 - b);
+ dst += SPRINTF((dst, "%u", *src & m));
+ size -= (size_t)(dst - t);
+ }
+
+ /* Format CIDR /width. */
+ if (size < sizeof "/32")
+ goto emsgsize;
+ dst += SPRINTF((dst, "/%u", bits));
+ return (odst);
+
+ emsgsize:
+ errno = EMSGSIZE;
+ return (NULL);
+}
diff --git a/cpukit/libnetworking/libc/inet_net_pton.c b/cpukit/libnetworking/libc/inet_net_pton.c
new file mode 100644
index 0000000000..8915c2a5be
--- /dev/null
+++ b/cpukit/libnetworking/libc/inet_net_pton.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char orig_rcsid[] = "From Id: inet_net_pton.c,v 1.8 1996/11/21 10:28:12 vixie Exp $";
+static const char rcsid[] = "$Id$";
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+static int inet_net_pton_ipv4 __P((const char *src, u_char *dst,
+ size_t size));
+
+/*
+ * static int
+ * inet_net_pton(af, src, dst, size)
+ * convert network number from presentation to network format.
+ * accepts hex octets, hex strings, decimal octets, and /CIDR.
+ * "size" is in bytes and describes "dst".
+ * return:
+ * number of bits, either imputed classfully or specified with /CIDR,
+ * or -1 if some failure occurred (check errno). ENOENT means it was
+ * not a valid network specification.
+ * author:
+ * Paul Vixie (ISC), June 1996
+ */
+int
+inet_net_pton(af, src, dst, size)
+ int af;
+ const char *src;
+ void *dst;
+ size_t size;
+{
+ switch (af) {
+ case AF_INET:
+ return (inet_net_pton_ipv4(src, dst, size));
+ default:
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+}
+
+/*
+ * static int
+ * inet_net_pton_ipv4(src, dst, size)
+ * convert IPv4 network number from presentation to network format.
+ * accepts hex octets, hex strings, decimal octets, and /CIDR.
+ * "size" is in bytes and describes "dst".
+ * return:
+ * number of bits, either imputed classfully or specified with /CIDR,
+ * or -1 if some failure occurred (check errno). ENOENT means it was
+ * not an IPv4 network specification.
+ * note:
+ * network byte order assumed. this means 192.5.5.240/28 has
+ * 0x11110000 in its fourth octet.
+ * author:
+ * Paul Vixie (ISC), June 1996
+ */
+static int
+inet_net_pton_ipv4(src, dst, size)
+ const char *src;
+ u_char *dst;
+ size_t size;
+{
+ static const char
+ xdigits[] = "0123456789abcdef",
+ digits[] = "0123456789";
+ int n, ch, tmp, dirty, bits;
+ const u_char *odst = dst;
+
+ ch = *src++;
+ if (ch == '0' && (src[0] == 'x' || src[0] == 'X')
+ && isascii(src[1]) && isxdigit(src[1])) {
+ /* Hexadecimal: Eat nybble string. */
+ if (size <= 0)
+ goto emsgsize;
+ *dst = 0, dirty = 0;
+ src++; /* skip x or X. */
+ while ((ch = *src++) != '\0' &&
+ isascii(ch) && isxdigit(ch)) {
+ if (isupper(ch))
+ ch = tolower(ch);
+ n = strchr(xdigits, ch) - xdigits;
+ assert(n >= 0 && n <= 15);
+ *dst |= n;
+ if (!dirty++)
+ *dst <<= 4;
+ else if (size-- > 0)
+ *++dst = 0, dirty = 0;
+ else
+ goto emsgsize;
+ }
+ if (dirty)
+ size--;
+ } else if (isascii(ch) && isdigit(ch)) {
+ /* Decimal: eat dotted digit string. */
+ for (;;) {
+ tmp = 0;
+ do {
+ n = strchr(digits, ch) - digits;
+ assert(n >= 0 && n <= 9);
+ tmp *= 10;
+ tmp += n;
+ if (tmp > 255)
+ goto enoent;
+ } while ((ch = *src++) != '\0' &&
+ isascii(ch) && isdigit(ch));
+ if (size-- <= 0)
+ goto emsgsize;
+ *dst++ = (u_char) tmp;
+ if (ch == '\0' || ch == '/')
+ break;
+ if (ch != '.')
+ goto enoent;
+ ch = *src++;
+ if (!isascii(ch) || !isdigit(ch))
+ goto enoent;
+ }
+ } else
+ goto enoent;
+
+ bits = -1;
+ if (ch == '/' && isascii(src[0]) && isdigit(src[0]) && dst > odst) {
+ /* CIDR width specifier. Nothing can follow it. */
+ ch = *src++; /* Skip over the /. */
+ bits = 0;
+ do {
+ n = strchr(digits, ch) - digits;
+ assert(n >= 0 && n <= 9);
+ bits *= 10;
+ bits += n;
+ } while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch));
+ if (ch != '\0')
+ goto enoent;
+ if (bits > 32)
+ goto emsgsize;
+ }
+
+ /* Firey death and destruction unless we prefetched EOS. */
+ if (ch != '\0')
+ goto enoent;
+
+ /* If nothing was written to the destination, we found no address. */
+ if (dst == odst)
+ goto enoent;
+ /* If no CIDR spec was given, infer width from net class. */
+ if (bits == -1) {
+ if (*odst >= 240) /* Class E */
+ bits = 32;
+ else if (*odst >= 224) /* Class D */
+ bits = 4;
+ else if (*odst >= 192) /* Class C */
+ bits = 24;
+ else if (*odst >= 128) /* Class B */
+ bits = 16;
+ else /* Class A */
+ bits = 8;
+ /* If imputed mask is narrower than specified octets, widen. */
+ if (bits >= 8 && bits < ((dst - odst) * 8))
+ bits = (dst - odst) * 8;
+ }
+ /* Extend network to cover the actual mask. */
+ while (bits > ((dst - odst) * 8)) {
+ if (size-- <= 0)
+ goto emsgsize;
+ *dst++ = '\0';
+ }
+ return (bits);
+
+ enoent:
+ errno = ENOENT;
+ return (-1);
+
+ emsgsize:
+ errno = EMSGSIZE;
+ return (-1);
+}
diff --git a/cpukit/libnetworking/libc/inet_neta.c b/cpukit/libnetworking/libc/inet_neta.c
new file mode 100644
index 0000000000..59b156f7f6
--- /dev/null
+++ b/cpukit/libnetworking/libc/inet_neta.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char orig_rcsid[] = "From Id: inet_neta.c,v 8.2 1996/08/08 06:54:44 vixie Exp";
+static const char rcsid[] = "$Id$";
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+/*
+ * char *
+ * inet_neta(src, dst, size)
+ * format a u_long network number into presentation format.
+ * return:
+ * pointer to dst, or NULL if an error occurred (check errno).
+ * note:
+ * format of ``src'' is as for inet_network().
+ * author:
+ * Paul Vixie (ISC), July 1996
+ */
+char *
+inet_neta(src, dst, size)
+ u_long src;
+ char *dst;
+ size_t size;
+{
+ char *odst = dst;
+ char *tp;
+
+ while (src & 0xffffffff) {
+ u_char b = (src & 0xff000000) >> 24;
+
+ src <<= 8;
+ if (b) {
+ if (size < sizeof "255.")
+ goto emsgsize;
+ tp = dst;
+ dst += SPRINTF((dst, "%u", b));
+ if (src != 0L) {
+ *dst++ = '.';
+ *dst = '\0';
+ }
+ size -= (size_t)(dst - tp);
+ }
+ }
+ if (dst == odst) {
+ if (size < sizeof "0.0.0.0")
+ goto emsgsize;
+ strcpy(dst, "0.0.0.0");
+ }
+ return (odst);
+
+ emsgsize:
+ errno = EMSGSIZE;
+ return (NULL);
+}
diff --git a/cpukit/libnetworking/libc/inet_netof.c b/cpukit/libnetworking/libc/inet_netof.c
new file mode 100644
index 0000000000..179731efc3
--- /dev/null
+++ b/cpukit/libnetworking/libc/inet_netof.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)inet_netof.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+/*
+ * Return the network number from an internet
+ * address; handles class a/b/c network #'s.
+ */
+u_long
+inet_netof(in)
+ struct in_addr in;
+{
+ register u_long i = ntohl(in.s_addr);
+
+ if (IN_CLASSA(i))
+ return (((i)&IN_CLASSA_NET) >> IN_CLASSA_NSHIFT);
+ else if (IN_CLASSB(i))
+ return (((i)&IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
+ else
+ return (((i)&IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
+}
diff --git a/cpukit/libnetworking/libc/inet_network.c b/cpukit/libnetworking/libc/inet_network.c
new file mode 100644
index 0000000000..ac0073bf0a
--- /dev/null
+++ b/cpukit/libnetworking/libc/inet_network.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)inet_network.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <ctype.h>
+
+/*
+ * Internet network address interpretation routine.
+ * The library routines call this routine to interpret
+ * network numbers.
+ */
+u_long
+inet_network(cp)
+ register const char *cp;
+{
+ register u_long val, base, n, i;
+ register char c;
+ u_long parts[4], *pp = parts;
+
+again:
+ val = 0; base = 10;
+ if (*cp == '0')
+ base = 8, cp++;
+ if (*cp == 'x' || *cp == 'X')
+ base = 16, cp++;
+ while ((c = *cp) != 0) {
+ if (isdigit(c)) {
+ val = (val * base) + (c - '0');
+ cp++;
+ continue;
+ }
+ if (base == 16 && isxdigit(c)) {
+ val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A'));
+ cp++;
+ continue;
+ }
+ break;
+ }
+ if (*cp == '.') {
+ if (pp >= parts + 3)
+ return (INADDR_NONE);
+ *pp++ = val, cp++;
+ goto again;
+ }
+ if (*cp && !isspace(*cp))
+ return (INADDR_NONE);
+ *pp++ = val;
+ n = pp - parts;
+ for (val = 0, i = 0; i < n; i++) {
+ val <<= 8;
+ val |= parts[i] & 0xff;
+ }
+ return (val);
+}
diff --git a/cpukit/libnetworking/libc/inet_ntoa.c b/cpukit/libnetworking/libc/inet_ntoa.c
new file mode 100644
index 0000000000..0844b6c5ad
--- /dev/null
+++ b/cpukit/libnetworking/libc/inet_ntoa.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)inet_ntoa.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+
+/*
+ * Convert network-format internet address
+ * to base 256 d.d.d.d representation.
+ */
+char *
+inet_ntoa(in)
+ struct in_addr in;
+{
+ static char ret[18];
+ char *strcpy(char *dest, const char *src);
+
+ strcpy(ret, "[inet_ntoa error]");
+ (void) inet_ntop(AF_INET, &in, ret, sizeof ret);
+ return (ret);
+}
diff --git a/cpukit/libnetworking/libc/inet_ntop.c b/cpukit/libnetworking/libc/inet_ntop.c
new file mode 100644
index 0000000000..76a538755a
--- /dev/null
+++ b/cpukit/libnetworking/libc/inet_ntop.c
@@ -0,0 +1,191 @@
+/* Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char rcsid[] = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#define SPRINTF(x) ((size_t)sprintf x)
+
+/*
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static const char *inet_ntop4 __P((const u_char *src, char *dst, size_t size));
+static const char *inet_ntop6 __P((const u_char *src, char *dst, size_t size));
+
+/* char *
+ * inet_ntop(af, src, dst, size)
+ * convert a network format address to presentation format.
+ * return:
+ * pointer to presentation format address (`dst'), or NULL (see errno).
+ * author:
+ * Paul Vixie, 1996.
+ */
+const char *
+inet_ntop(af, src, dst, size)
+ int af;
+ const void *src;
+ char *dst;
+ size_t size;
+{
+ switch (af) {
+ case AF_INET:
+ return (inet_ntop4(src, dst, size));
+ case AF_INET6:
+ return (inet_ntop6(src, dst, size));
+ default:
+ errno = EAFNOSUPPORT;
+ return (NULL);
+ }
+ /* NOTREACHED */
+}
+
+/* const char *
+ * inet_ntop4(src, dst, size)
+ * format an IPv4 address, more or less like inet_ntoa()
+ * return:
+ * `dst' (as a const)
+ * notes:
+ * (1) uses no statics
+ * (2) takes a u_char* not an in_addr as input
+ * author:
+ * Paul Vixie, 1996.
+ */
+static const char *
+inet_ntop4(src, dst, size)
+ const u_char *src;
+ char *dst;
+ size_t size;
+{
+ static const char fmt[] = "%u.%u.%u.%u";
+ char tmp[sizeof "255.255.255.255"];
+
+ if (SPRINTF((tmp, fmt, src[0], src[1], src[2], src[3])) > size) {
+ errno = ENOSPC;
+ return (NULL);
+ }
+ strcpy(dst, tmp);
+ return (dst);
+}
+
+/* const char *
+ * inet_ntop6(src, dst, size)
+ * convert IPv6 binary address into presentation (printable) format
+ * author:
+ * Paul Vixie, 1996.
+ */
+static const char *
+inet_ntop6(src, dst, size)
+ const u_char *src;
+ char *dst;
+ size_t size;
+{
+ /*
+ * Note that int32_t and int16_t need only be "at least" large enough
+ * to contain a value of the specified size. On some systems, like
+ * Crays, there is no such thing as an integer variable with 16 bits.
+ * Keep this in mind if you think this function should have been coded
+ * to use pointer overlays. All the world's not a VAX.
+ */
+ char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
+ struct { int base, len; } best, cur;
+ u_int words[NS_IN6ADDRSZ / NS_INT16SZ];
+ int i;
+
+ /*
+ * Preprocess:
+ * Copy the input (bytewise) array into a wordwise array.
+ * Find the longest run of 0x00's in src[] for :: shorthanding.
+ */
+ memset(words, '\0', sizeof words);
+ for (i = 0; i < NS_IN6ADDRSZ; i++)
+ words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
+ best.base = -1;
+ cur.base = -1;
+ for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
+ if (words[i] == 0) {
+ if (cur.base == -1)
+ cur.base = i, cur.len = 1;
+ else
+ cur.len++;
+ } else {
+ if (cur.base != -1) {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ cur.base = -1;
+ }
+ }
+ }
+ if (cur.base != -1) {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ }
+ if (best.base != -1 && best.len < 2)
+ best.base = -1;
+
+ /*
+ * Format the result.
+ */
+ tp = tmp;
+ for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
+ /* Are we inside the best run of 0x00's? */
+ if (best.base != -1 && i >= best.base &&
+ i < (best.base + best.len)) {
+ if (i == best.base)
+ *tp++ = ':';
+ continue;
+ }
+ /* Are we following an initial run of 0x00s or any real hex? */
+ if (i != 0)
+ *tp++ = ':';
+ /* Is this address an encapsulated IPv4? */
+ if (i == 6 && best.base == 0 &&
+ (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
+ if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
+ return (NULL);
+ tp += strlen(tp);
+ break;
+ }
+ tp += SPRINTF((tp, "%x", words[i]));
+ }
+ /* Was it a trailing run of 0x00's? */
+ if (best.base != -1 && (best.base + best.len) ==
+ (NS_IN6ADDRSZ / NS_INT16SZ))
+ *tp++ = ':';
+ *tp++ = '\0';
+
+ /*
+ * Check for overflow, copy, and we're done.
+ */
+ if ((size_t)(tp - tmp) > size) {
+ errno = ENOSPC;
+ return (NULL);
+ }
+ strcpy(dst, tmp);
+ return (dst);
+}
diff --git a/cpukit/libnetworking/libc/inet_pton.c b/cpukit/libnetworking/libc/inet_pton.c
new file mode 100644
index 0000000000..8d21111cfa
--- /dev/null
+++ b/cpukit/libnetworking/libc/inet_pton.c
@@ -0,0 +1,214 @@
+/* Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char rcsid[] = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <string.h>
+#include <errno.h>
+
+/*
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static int inet_pton4 __P((const char *src, u_char *dst));
+static int inet_pton6 __P((const char *src, u_char *dst));
+
+/* int
+ * inet_pton(af, src, dst)
+ * convert from presentation format (which usually means ASCII printable)
+ * to network format (which is usually some kind of binary format).
+ * return:
+ * 1 if the address was valid for the specified address family
+ * 0 if the address wasn't valid (`dst' is untouched in this case)
+ * -1 if some other error occurred (`dst' is untouched in this case, too)
+ * author:
+ * Paul Vixie, 1996.
+ */
+int
+inet_pton(af, src, dst)
+ int af;
+ const char *src;
+ void *dst;
+{
+ switch (af) {
+ case AF_INET:
+ return (inet_pton4(src, dst));
+ case AF_INET6:
+ return (inet_pton6(src, dst));
+ default:
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+ /* NOTREACHED */
+}
+
+/* int
+ * inet_pton4(src, dst)
+ * like inet_aton() but without all the hexadecimal and shorthand.
+ * return:
+ * 1 if `src' is a valid dotted quad, else 0.
+ * notice:
+ * does not touch `dst' unless it's returning 1.
+ * author:
+ * Paul Vixie, 1996.
+ */
+static int
+inet_pton4(src, dst)
+ const char *src;
+ u_char *dst;
+{
+ static const char digits[] = "0123456789";
+ int saw_digit, octets, ch;
+ u_char tmp[NS_INADDRSZ], *tp;
+
+ saw_digit = 0;
+ octets = 0;
+ *(tp = tmp) = 0;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ if ((pch = strchr(digits, ch)) != NULL) {
+ u_int new = *tp * 10 + (pch - digits);
+
+ if (new > 255)
+ return (0);
+ *tp = new;
+ if (! saw_digit) {
+ if (++octets > 4)
+ return (0);
+ saw_digit = 1;
+ }
+ } else if (ch == '.' && saw_digit) {
+ if (octets == 4)
+ return (0);
+ *++tp = 0;
+ saw_digit = 0;
+ } else
+ return (0);
+ }
+ if (octets < 4)
+ return (0);
+
+ memcpy(dst, tmp, NS_INADDRSZ);
+ return (1);
+}
+
+/* int
+ * inet_pton6(src, dst)
+ * convert presentation level address to network order binary form.
+ * return:
+ * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
+ * notice:
+ * (1) does not touch `dst' unless it's returning 1.
+ * (2) :: in a full address is silently ignored.
+ * credit:
+ * inspired by Mark Andrews.
+ * author:
+ * Paul Vixie, 1996.
+ */
+static int
+inet_pton6(src, dst)
+ const char *src;
+ u_char *dst;
+{
+ static const char xdigits_l[] = "0123456789abcdef",
+ xdigits_u[] = "0123456789ABCDEF";
+ u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
+ const char *xdigits, *curtok;
+ int ch, saw_xdigit;
+ u_int val;
+
+ memset((tp = tmp), '\0', NS_IN6ADDRSZ);
+ endp = tp + NS_IN6ADDRSZ;
+ colonp = NULL;
+ /* Leading :: requires some special handling. */
+ if (*src == ':')
+ if (*++src != ':')
+ return (0);
+ curtok = src;
+ saw_xdigit = 0;
+ val = 0;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+ pch = strchr((xdigits = xdigits_u), ch);
+ if (pch != NULL) {
+ val <<= 4;
+ val |= (pch - xdigits);
+ if (val > 0xffff)
+ return (0);
+ saw_xdigit = 1;
+ continue;
+ }
+ if (ch == ':') {
+ curtok = src;
+ if (!saw_xdigit) {
+ if (colonp)
+ return (0);
+ colonp = tp;
+ continue;
+ }
+ if (tp + NS_INT16SZ > endp)
+ return (0);
+ *tp++ = (u_char) (val >> 8) & 0xff;
+ *tp++ = (u_char) val & 0xff;
+ saw_xdigit = 0;
+ val = 0;
+ continue;
+ }
+ if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
+ inet_pton4(curtok, tp) > 0) {
+ tp += NS_INADDRSZ;
+ saw_xdigit = 0;
+ break; /* '\0' was seen by inet_pton4(). */
+ }
+ return (0);
+ }
+ if (saw_xdigit) {
+ if (tp + NS_INT16SZ > endp)
+ return (0);
+ *tp++ = (u_char) (val >> 8) & 0xff;
+ *tp++ = (u_char) val & 0xff;
+ }
+ if (colonp != NULL) {
+ /*
+ * Since some memmove()'s erroneously fail to handle
+ * overlapping regions, we'll do the shift by hand.
+ */
+ const int n = tp - colonp;
+ int i;
+
+ for (i = 1; i <= n; i++) {
+ endp[- i] = colonp[n - i];
+ colonp[n - i] = 0;
+ }
+ tp = endp;
+ }
+ if (tp != endp)
+ return (0);
+ memcpy(dst, tmp, NS_IN6ADDRSZ);
+ return (1);
+}
diff --git a/cpukit/libnetworking/libc/iso_addr.3 b/cpukit/libnetworking/libc/iso_addr.3
new file mode 100644
index 0000000000..0c9973bef4
--- /dev/null
+++ b/cpukit/libnetworking/libc/iso_addr.3
@@ -0,0 +1,111 @@
+.\" Copyright (c) 1993
+.\" The Regents of the University of California. 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 the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+.\"
+.\" @(#)iso_addr.3 8.1 (Berkeley) 6/4/93
+.\" $Id$
+.\"
+.Dd June 4, 1993
+.Dt ISO_ADDR 3
+.Os
+.Sh NAME
+.Nm iso_addr ,
+.Nm iso_ntoa
+.Nd "elementary network address conversion routines for Open System Interconnection
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <netiso/iso.h>
+.Ft struct iso_addr *
+.Fn iso_addr "char *cp"
+.Ft char *
+.Fn iso_ntoa "struct iso_addr *isoa"
+.Sh DESCRIPTION
+The routine
+.Fn iso_addr
+interprets character strings representing
+.Tn OSI
+addresses, returning binary information suitable
+for use in system calls.
+The routine
+.Fn iso_ntoa
+takes
+.Tn OSI
+addresses and returns
+.Tn ASCII
+strings representing NSAPs (network service
+access points) in a
+notation inverse to that accepted by
+.Fn iso_addr .
+.Pp
+Unfortunately, no universal standard exists for representing
+.Tn OSI
+network addresses.
+.Pp
+The format employed by
+.Fn iso_addr
+is a sequence of hexadecimal
+.Dq digits
+(optionally separated by periods),
+of the form:
+.Bd -filled -offset indent
+<hex digits>.<hex digits>.<hex digits>
+.Ed
+.Pp
+Each pair of hexadecimal digits represents a byte
+with the leading digit indicating the higher-ordered bits.
+A period following an even number of bytes has no
+effect (but may be used to increase legibility).
+A period following an odd number of bytes has the
+effect of causing the byte of address being translated
+to have its higher order bits filled with zeros.
+.Sh RETURN VALUES
+.Fn iso_ntoa
+always returns a null terminated string.
+.Fn iso_addr
+always returns a pointer to a struct iso_addr.
+(See
+.Sx BUGS . )
+.Sh SEE ALSO
+.Xr iso 4
+.Sh HISTORY
+The
+.Fn iso_addr
+and
+.Fn iso_ntoa
+functions appeared in
+.Bx 4.3 Reno .
+.Sh BUGS
+The returned values
+reside in a static memory area.
+.Pp
+The function
+.Fn iso_addr
+should diagnose improperly formed input, and there should be an unambiguous
+way to recognize this.
diff --git a/cpukit/libnetworking/libc/iso_addr.c b/cpukit/libnetworking/libc/iso_addr.c
new file mode 100644
index 0000000000..eb14e8a72b
--- /dev/null
+++ b/cpukit/libnetworking/libc/iso_addr.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)iso_addr.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <netiso/iso.h>
+#include <string.h>
+
+/* States*/
+#define VIRGIN 0
+#define GOTONE 1
+#define GOTTWO 2
+/* Inputs */
+#define DIGIT (4*0)
+#define END (4*1)
+#define DELIM (4*2)
+
+struct iso_addr *
+iso_addr(addr)
+ register const char *addr;
+{
+ static struct iso_addr out_addr;
+ register char *cp = out_addr.isoa_genaddr;
+ char *cplim = cp + sizeof(out_addr.isoa_genaddr);
+ register int byte = 0, state = VIRGIN, new;
+
+ bzero((char *)&out_addr, sizeof(out_addr));
+ do {
+ if ((*addr >= '0') && (*addr <= '9')) {
+ new = *addr - '0';
+ } else if ((*addr >= 'a') && (*addr <= 'f')) {
+ new = *addr - 'a' + 10;
+ } else if ((*addr >= 'A') && (*addr <= 'F')) {
+ new = *addr - 'A' + 10;
+ } else if (*addr == 0)
+ state |= END;
+ else
+ state |= DELIM;
+ addr++;
+ switch (state /* | INPUT */) {
+ case GOTTWO | DIGIT:
+ *cp++ = byte; /*FALLTHROUGH*/
+ case VIRGIN | DIGIT:
+ state = GOTONE; byte = new; continue;
+ case GOTONE | DIGIT:
+ state = GOTTWO; byte = new + (byte << 4); continue;
+ default: /* | DELIM */
+ state = VIRGIN; *cp++ = byte; byte = 0; continue;
+ case GOTONE | END:
+ case GOTTWO | END:
+ *cp++ = byte; /* FALLTHROUGH */
+ case VIRGIN | END:
+ break;
+ }
+ break;
+ } while (cp < cplim);
+ out_addr.isoa_len = cp - out_addr.isoa_genaddr;
+ return (&out_addr);
+}
+
+static char hexlist[] = "0123456789abcdef";
+
+char *
+iso_ntoa(isoa)
+ const struct iso_addr *isoa;
+{
+ static char tmpbuf[sizeof(isoa->isoa_genaddr)*3];
+ const u_char *binary;
+ char *cp;
+ int i;
+
+ binary = isoa->isoa_genaddr;
+ cp = tmpbuf;
+
+ for (i = 0; i < isoa->isoa_len; i++) {
+ *cp++ = hexlist[*binary >> 4];
+ *cp++ = hexlist[*binary++ & 0xf];
+
+ if ((((i % 2) == 0) && ((i + 1) < isoa->isoa_len)))
+ *cp++ = '.';
+ }
+ *cp = '\0';
+ return tmpbuf;
+}
diff --git a/cpukit/libnetworking/libc/linkaddr.3 b/cpukit/libnetworking/libc/linkaddr.3
new file mode 100644
index 0000000000..6999add0e8
--- /dev/null
+++ b/cpukit/libnetworking/libc/linkaddr.3
@@ -0,0 +1,138 @@
+.\" Copyright (c) 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Donn Seeley at BSDI.
+.\"
+.\" 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 the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+.\"
+.\" From: @(#)linkaddr.3 8.1 (Berkeley) 7/28/93
+.\" $Id$
+.\"
+.Dd June 17, 1996
+.Dt LINK_ADDR 3
+.Os BSD 4.4
+.Sh NAME
+.Nm link_addr ,
+.Nm link_ntoa
+.Nd elementary address specification routines for link level access
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/socket.h>
+.Fd #include <net/if_dl.h>
+.Ft void
+.Fn link_addr "const char *addr" "struct sockaddr_dl *sdl"
+.Ft char *
+.Fn link_ntoa "const struct sockaddr_dl *sdl"
+.Sh DESCRIPTION
+The routine
+.Fn link_addr
+interprets character strings representing
+link-level addresses, returning binary information suitable
+for use in system calls.
+The routine
+.Fn link_ntoa
+takes
+a link-level
+address and returns an
+.Tn ASCII
+string representing some of the information present,
+including the link level address itself, and the interface name
+or number, if present.
+This facility is experimental and is
+still subject to change.
+.Pp
+For
+.Fn link_addr ,
+the string
+.Fa addr
+may contain
+an optional network interface identifier of the form
+.Dq "name unit-number" ,
+suitable for the first argument to
+.Xr ifconfig 8 ,
+followed in all cases by a colon and
+an interface address in the form of
+groups of hexadecimal digits
+separated by periods.
+Each group represents a byte of address;
+address bytes are filled left to right from
+low order bytes through high order bytes.
+.Pp
+.\" A regular expression may make this format clearer:
+.\" .Bd -literal -offset indent
+.\" ([a-z]+[0-9]+:)?[0-9a-f]+(\e.[0-9a-f]+)*
+.\" .Ed
+.\" .Pp
+Thus
+.Li le0:8.0.9.13.d.30
+represents an ethernet address
+to be transmitted on the first Lance ethernet interface.
+.Pp
+The direct use of these functions is deprecated in favor of the
+.Xr addr2ascii 3
+interface; however, portable programs cannot rely on the latter as it is
+not yet widely implemented.
+.Sh RETURN VALUES
+.Fn link_ntoa
+always returns a null terminated string.
+.Fn link_addr
+has no return value.
+(See
+.Sx BUGS . )
+.Sh SEE ALSO
+.Xr addr2ascii 3
+.\" .Xr iso 4
+.Sh HISTORY
+The
+.Fn link_addr
+and
+.Fn link_ntoa
+functions appeared in
+.Bx 4.3 Reno .
+.Sh BUGS
+The returned values for link_ntoa
+reside in a static memory area.
+.Pp
+The function
+.Fn link_addr
+should diagnose improperly formed input, and there should be an unambiguous
+way to recognize this.
+.Pp
+If the
+.Va sdl_len
+field of the link socket address
+.Fa sdl
+is 0,
+.Fn link_ntoa
+will not insert a colon before the interface address bytes.
+If this translated address is given to
+.Fn link_addr
+without inserting an initial colon,
+the latter will not interpret it correctly.
diff --git a/cpukit/libnetworking/libc/linkaddr.c b/cpukit/libnetworking/libc/linkaddr.c
new file mode 100644
index 0000000000..2bad464b12
--- /dev/null
+++ b/cpukit/libnetworking/libc/linkaddr.c
@@ -0,0 +1,161 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)linkaddr.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if_dl.h>
+#include <string.h>
+
+/* States*/
+#define NAMING 0
+#define GOTONE 1
+#define GOTTWO 2
+#define RESET 3
+/* Inputs */
+#define DIGIT (4*0)
+#define END (4*1)
+#define DELIM (4*2)
+#define LETTER (4*3)
+
+void
+link_addr(addr, sdl)
+ register const char *addr;
+ register struct sockaddr_dl *sdl;
+{
+ register char *cp = sdl->sdl_data;
+ char *cplim = sdl->sdl_len + (char *)sdl;
+ register int byte = 0, state = NAMING,
+ new=0; /* new=0 to avoid warning */
+
+ bzero((char *)&sdl->sdl_family, sdl->sdl_len - 1);
+ sdl->sdl_family = AF_LINK;
+ do {
+ state &= ~LETTER;
+ if ((*addr >= '0') && (*addr <= '9')) {
+ new = *addr - '0';
+ } else if ((*addr >= 'a') && (*addr <= 'f')) {
+ new = *addr - 'a' + 10;
+ } else if ((*addr >= 'A') && (*addr <= 'F')) {
+ new = *addr - 'A' + 10;
+ } else if (*addr == 0) {
+ state |= END;
+ } else if (state == NAMING &&
+ (((*addr >= 'A') && (*addr <= 'Z')) ||
+ ((*addr >= 'a') && (*addr <= 'z'))))
+ state |= LETTER;
+ else
+ state |= DELIM;
+ addr++;
+ switch (state /* | INPUT */) {
+ case NAMING | DIGIT:
+ case NAMING | LETTER:
+ *cp++ = addr[-1];
+ continue;
+ case NAMING | DELIM:
+ state = RESET;
+ sdl->sdl_nlen = cp - sdl->sdl_data;
+ continue;
+ case GOTTWO | DIGIT:
+ *cp++ = byte;
+ /* FALLTHROUGH */
+ case RESET | DIGIT:
+ state = GOTONE;
+ byte = new;
+ continue;
+ case GOTONE | DIGIT:
+ state = GOTTWO;
+ byte = new + (byte << 4);
+ continue;
+ default: /* | DELIM */
+ state = RESET;
+ *cp++ = byte;
+ byte = 0;
+ continue;
+ case GOTONE | END:
+ case GOTTWO | END:
+ *cp++ = byte;
+ /* FALLTHROUGH */
+ case RESET | END:
+ break;
+ }
+ break;
+ } while (cp < cplim);
+ sdl->sdl_alen = cp - LLADDR(sdl);
+ new = cp - (char *)sdl;
+ if (new > sizeof(*sdl))
+ sdl->sdl_len = new;
+ return;
+}
+
+static char hexlist[] = "0123456789abcdef";
+
+char *
+link_ntoa(sdl)
+ register const struct sockaddr_dl *sdl;
+{
+ static char obuf[64];
+ register char *out = obuf;
+ register int i;
+ register u_char *in = (u_char *)LLADDR(sdl);
+ u_char *inlim = in + sdl->sdl_alen;
+ int firsttime = 1;
+
+ if (sdl->sdl_nlen) {
+ bcopy(sdl->sdl_data, obuf, sdl->sdl_nlen);
+ out += sdl->sdl_nlen;
+ if (sdl->sdl_alen)
+ *out++ = ':';
+ }
+ while (in < inlim) {
+ if (firsttime)
+ firsttime = 0;
+ else
+ *out++ = '.';
+ i = *in++;
+ if (i > 0xf) {
+ out[1] = hexlist[i & 0xf];
+ i >>= 4;
+ out[0] = hexlist[i];
+ out += 2;
+ } else
+ *out++ = hexlist[i];
+ }
+ *out = 0;
+ return (obuf);
+}
diff --git a/cpukit/libnetworking/libc/map_v4v6.c b/cpukit/libnetworking/libc/map_v4v6.c
new file mode 100644
index 0000000000..0f8658e117
--- /dev/null
+++ b/cpukit/libnetworking/libc/map_v4v6.c
@@ -0,0 +1,128 @@
+/*
+ * ++Copyright++ 1985, 1988, 1993
+ * -
+ * Copyright (c) 1985, 1988, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ * -
+ * --Copyright--
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
+static char rcsid[] = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <ctype.h>
+#include <errno.h>
+#include <syslog.h>
+
+typedef union {
+ int32_t al;
+ char ac;
+} align;
+
+void
+_map_v4v6_address(src, dst)
+ const char *src;
+ char *dst;
+{
+ u_char *p = (u_char *)dst;
+ char tmp[INADDRSZ];
+ int i;
+
+ /* Stash a temporary copy so our caller can update in place. */
+ bcopy(src, tmp, INADDRSZ);
+ /* Mark this ipv6 addr as a mapped ipv4. */
+ for (i = 0; i < 10; i++)
+ *p++ = 0x00;
+ *p++ = 0xff;
+ *p++ = 0xff;
+ /* Retrieve the saved copy and we're done. */
+ bcopy(tmp, (void*)p, INADDRSZ);
+}
+
+void
+_map_v4v6_hostent(hp, bpp, lenp)
+ struct hostent *hp;
+ char **bpp;
+ int *lenp;
+{
+ char **ap;
+
+ if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)
+ return;
+ hp->h_addrtype = AF_INET6;
+ hp->h_length = IN6ADDRSZ;
+ for (ap = hp->h_addr_list; *ap; ap++) {
+ int i = sizeof(align) - ((u_long)*bpp % sizeof(align));
+
+ if (*lenp < (i + IN6ADDRSZ)) {
+ /* Out of memory. Truncate address list here. XXX */
+ *ap = NULL;
+ return;
+ }
+ *bpp += i;
+ *lenp -= i;
+ _map_v4v6_address(*ap, *bpp);
+ *ap = *bpp;
+ *bpp += IN6ADDRSZ;
+ *lenp -= IN6ADDRSZ;
+ }
+}
diff --git a/cpukit/libnetworking/libc/ns.3 b/cpukit/libnetworking/libc/ns.3
new file mode 100644
index 0000000000..e621ad2d90
--- /dev/null
+++ b/cpukit/libnetworking/libc/ns.3
@@ -0,0 +1,131 @@
+.\" Copyright (c) 1986, 1991, 1993
+.\" The Regents of the University of California. 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 the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+.\"
+.\" @(#)ns.3 8.1 (Berkeley) 6/4/93
+.\" $Id$
+.\"
+.Dd June 4, 1993
+.Dt NS 3
+.Os BSD 4.3
+.Sh NAME
+.Nm ns_addr ,
+.Nm ns_ntoa
+.Nd Xerox
+.Tn NS Ns (tm)
+address conversion routines
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <netns/ns.h>
+.Ft struct ns_addr
+.Fn ns_addr "char *cp"
+.Ft char *
+.Fn ns_ntoa "struct ns_addr ns"
+.Sh DESCRIPTION
+The routine
+.Fn ns_addr
+interprets character strings representing
+.Tn XNS
+addresses, returning binary information suitable
+for use in system calls.
+The routine
+.Fn ns_ntoa
+takes
+.Tn XNS
+addresses and returns
+.Tn ASCII
+strings representing the address in a
+notation in common use in the Xerox Development Environment:
+.Bd -filled -offset indent
+<network number>.<host number>.<port number>
+.Ed
+.Pp
+Trailing zero fields are suppressed, and each number is printed in hexadecimal,
+in a format suitable for input to
+.Fn ns_addr .
+Any fields lacking super-decimal digits will have a
+trailing
+.Ql H
+appended.
+.Pp
+Unfortunately, no universal standard exists for representing
+.Tn XNS
+addresses.
+An effort has been made to insure that
+.Fn ns_addr
+be compatible with most formats in common use.
+It will first separate an address into 1 to 3 fields using a single delimiter
+chosen from
+period
+.Ql \&. ,
+colon
+.Ql \&:
+or pound-sign
+.Ql \&# .
+Each field is then examined for byte separators (colon or period).
+If there are byte separators, each subfield separated is taken to be
+a small hexadecimal number, and the entirety is taken as a network-byte-ordered
+quantity to be zero extended in the high-network-order bytes.
+Next, the field is inspected for hyphens, in which case
+the field is assumed to be a number in decimal notation
+with hyphens separating the millenia.
+Next, the field is assumed to be a number:
+It is interpreted
+as hexadecimal if there is a leading
+.Ql 0x
+(as in C),
+a trailing
+.Ql H
+(as in Mesa), or there are any super-decimal digits present.
+It is interpreted as octal is there is a leading
+.Ql 0
+and there are no super-octal digits.
+Otherwise, it is converted as a decimal number.
+.Sh RETURN VALUES
+None. (See
+.Sx BUGS . )
+.Sh SEE ALSO
+.Xr hosts 5 ,
+.Xr networks 5
+.Sh HISTORY
+The
+.Fn ns_addr
+and
+.Fn ns_toa
+functions appeared in
+.Bx 4.3 .
+.Sh BUGS
+The string returned by
+.Fn ns_ntoa
+resides in a static memory area.
+The function
+.Fn ns_addr
+should diagnose improperly formed input, and there should be an unambiguous
+way to recognize this.
diff --git a/cpukit/libnetworking/libc/ns_addr.c b/cpukit/libnetworking/libc/ns_addr.c
new file mode 100644
index 0000000000..18fabe91f1
--- /dev/null
+++ b/cpukit/libnetworking/libc/ns_addr.c
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 1986, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * J.Q. Johnson.
+ *
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)ns_addr.c 8.1 (Berkeley) 6/7/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <netns/ns.h>
+#include <stdio.h>
+#include <string.h>
+
+static struct ns_addr addr, zero_addr;
+
+static void Field(), cvtbase();
+
+struct ns_addr
+ns_addr(name)
+ const char *name;
+{
+ char separator;
+ char *hostname, *socketname, *cp;
+ char buf[50];
+
+ (void)strncpy(buf, name, sizeof(buf) - 1);
+ buf[sizeof(buf) - 1] = '\0';
+
+ /*
+ * First, figure out what he intends as a field separtor.
+ * Despite the way this routine is written, the prefered
+ * form 2-272.AA001234H.01777, i.e. XDE standard.
+ * Great efforts are made to insure backward compatability.
+ */
+ if ((hostname = strchr(buf, '#')) != NULL)
+ separator = '#';
+ else {
+ hostname = strchr(buf, '.');
+ if ((cp = strchr(buf, ':')) &&
+ ((hostname && cp < hostname) || (hostname == 0))) {
+ hostname = cp;
+ separator = ':';
+ } else
+ separator = '.';
+ }
+ if (hostname)
+ *hostname++ = 0;
+
+ addr = zero_addr;
+ Field(buf, addr.x_net.c_net, 4);
+ if (hostname == 0)
+ return (addr); /* No separator means net only */
+
+ socketname = strchr(hostname, separator);
+ if (socketname) {
+ *socketname++ = 0;
+ Field(socketname, (u_char *)&addr.x_port, 2);
+ }
+
+ Field(hostname, addr.x_host.c_host, 6);
+
+ return (addr);
+}
+
+static void
+Field(buf, out, len)
+ char *buf;
+ u_char *out;
+ int len;
+{
+ register char *bp = buf;
+ int i, ibase, base16 = 0, base10 = 0, clen = 0;
+ int hb[6], *hp;
+ char *fmt;
+
+ /*
+ * first try 2-273#2-852-151-014#socket
+ */
+ if ((*buf != '-') &&
+ (1 < (i = sscanf(buf, "%d-%d-%d-%d-%d",
+ &hb[0], &hb[1], &hb[2], &hb[3], &hb[4])))) {
+ cvtbase(1000L, 256, hb, i, out, len);
+ return;
+ }
+ /*
+ * try form 8E1#0.0.AA.0.5E.E6#socket
+ */
+ if (1 < (i = sscanf(buf,"%x.%x.%x.%x.%x.%x",
+ &hb[0], &hb[1], &hb[2], &hb[3], &hb[4], &hb[5]))) {
+ cvtbase(256L, 256, hb, i, out, len);
+ return;
+ }
+ /*
+ * try form 8E1#0:0:AA:0:5E:E6#socket
+ */
+ if (1 < (i = sscanf(buf,"%x:%x:%x:%x:%x:%x",
+ &hb[0], &hb[1], &hb[2], &hb[3], &hb[4], &hb[5]))) {
+ cvtbase(256L, 256, hb, i, out, len);
+ return;
+ }
+ /*
+ * This is REALLY stretching it but there was a
+ * comma notation separting shorts -- definitely non standard
+ */
+ if (1 < (i = sscanf(buf,"%x,%x,%x",
+ &hb[0], &hb[1], &hb[2]))) {
+ hb[0] = htons(hb[0]); hb[1] = htons(hb[1]);
+ hb[2] = htons(hb[2]);
+ cvtbase(65536L, 256, hb, i, out, len);
+ return;
+ }
+
+ /* Need to decide if base 10, 16 or 8 */
+ while (*bp) switch (*bp++) {
+
+ case '0': case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7': case '-':
+ break;
+
+ case '8': case '9':
+ base10 = 1;
+ break;
+
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ base16 = 1;
+ break;
+
+ case 'x': case 'X':
+ *--bp = '0';
+ base16 = 1;
+ break;
+
+ case 'h': case 'H':
+ base16 = 1;
+ /* fall into */
+
+ default:
+ *--bp = 0; /* Ends Loop */
+ }
+ if (base16) {
+ fmt = "%3x";
+ ibase = 4096;
+ } else if (base10 == 0 && *buf == '0') {
+ fmt = "%3o";
+ ibase = 512;
+ } else {
+ fmt = "%3d";
+ ibase = 1000;
+ }
+
+ for (bp = buf; *bp++; ) clen++;
+ if (clen == 0) clen++;
+ if (clen > 18) clen = 18;
+ i = ((clen - 1) / 3) + 1;
+ bp = clen + buf - 3;
+ hp = hb + i - 1;
+
+ while (hp > hb) {
+ (void)sscanf(bp, fmt, hp);
+ bp[0] = 0;
+ hp--;
+ bp -= 3;
+ }
+ (void)sscanf(buf, fmt, hp);
+ cvtbase((long)ibase, 256, hb, i, out, len);
+}
+
+static void
+cvtbase(oldbase,newbase,input,inlen,result,reslen)
+ long oldbase;
+ int newbase;
+ int input[];
+ int inlen;
+ unsigned char result[];
+ int reslen;
+{
+ int d, e;
+ long sum;
+
+ e = 1;
+ while (e > 0 && reslen > 0) {
+ d = 0; e = 0; sum = 0;
+ /* long division: input=input/newbase */
+ while (d < inlen) {
+ sum = sum*oldbase + (long) input[d];
+ e += (sum > 0);
+ input[d++] = sum / newbase;
+ sum %= newbase;
+ }
+ result[--reslen] = sum; /* accumulate remainder */
+ }
+ for (d=0; d < reslen; d++)
+ result[d] = 0;
+}
diff --git a/cpukit/libnetworking/libc/ns_name.c b/cpukit/libnetworking/libc/ns_name.c
new file mode 100644
index 0000000000..af10d2f062
--- /dev/null
+++ b/cpukit/libnetworking/libc/ns_name.c
@@ -0,0 +1,595 @@
+/*
+ * Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ */
+
+#if !defined(__rtems__)
+#if !defined(LINT) && !defined(CODECENTER)
+static char rcsid[] = "$Id$";
+#endif /* not lint */
+#endif /* not rtems */
+
+#include <sys/types.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <resolv.h>
+#include <string.h>
+
+/* Data. */
+
+static char digits[] = "0123456789";
+
+/* Forward. */
+
+static int special(int);
+static int printable(int);
+static int dn_find(const u_char *, const u_char *,
+ const u_char * const *,
+ const u_char * const *);
+
+/* Public. */
+
+/*
+ * ns_name_ntop(src, dst, dstsiz)
+ * Convert an encoded domain name to printable ascii as per RFC1035.
+ * return:
+ * Number of bytes written to buffer, or -1 (with errno set)
+ * notes:
+ * The root is returned as "."
+ * All other domains are returned in non absolute form
+ */
+int
+ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) {
+ const u_char *cp;
+ char *dn, *eom;
+ u_char c;
+ u_int n;
+
+ cp = src;
+ dn = dst;
+ eom = dst + dstsiz;
+
+ while ((n = *cp++) != 0) {
+ if ((n & NS_CMPRSFLGS) != 0) {
+ /* Some kind of compression pointer. */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ if (dn != dst) {
+ if (dn >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dn++ = '.';
+ }
+ if (dn + n >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ for ((void)NULL; n > 0; n--) {
+ c = *cp++;
+ if (special(c)) {
+ if (dn + 1 >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dn++ = '\\';
+ *dn++ = (char)c;
+ } else if (!printable(c)) {
+ if (dn + 3 >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dn++ = '\\';
+ *dn++ = digits[c / 100];
+ *dn++ = digits[(c % 100) / 10];
+ *dn++ = digits[c % 10];
+ } else {
+ if (dn >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dn++ = (char)c;
+ }
+ }
+ }
+ if (dn == dst) {
+ if (dn >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dn++ = '.';
+ }
+ if (dn >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dn++ = '\0';
+ return (dn - dst);
+}
+
+/*
+ * ns_name_pton(src, dst, dstsiz)
+ * Convert a ascii string into an encoded domain name as per RFC1035.
+ * return:
+ * -1 if it fails
+ * 1 if string was fully qualified
+ * 0 is string was not fully qualified
+ * notes:
+ * Enforces label and domain length limits.
+ */
+
+int
+ns_name_pton(const char *src, u_char *dst, size_t dstsiz) {
+ u_char *label, *bp, *eom;
+ int c, n, escaped;
+ char *cp;
+
+ escaped = 0;
+ bp = dst;
+ eom = dst + dstsiz;
+ label = bp++;
+
+ while ((c = *src++) != 0) {
+ if (escaped) {
+ if ((cp = strchr(digits, c)) != NULL) {
+ n = (cp - digits) * 100;
+ if ((c = *src++) == 0 ||
+ (cp = strchr(digits, c)) == NULL) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ n += (cp - digits) * 10;
+ if ((c = *src++) == 0 ||
+ (cp = strchr(digits, c)) == NULL) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ n += (cp - digits);
+ if (n > 255) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ c = n;
+ }
+ escaped = 0;
+ } else if (c == '\\') {
+ escaped = 1;
+ continue;
+ } else if (c == '.') {
+ c = (bp - label - 1);
+ if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ if (label >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *label = c;
+ /* Fully qualified ? */
+ if (*src == '\0') {
+ if (c != 0) {
+ if (bp >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *bp++ = '\0';
+ }
+ if ((bp - dst) > MAXCDNAME) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ return (1);
+ }
+ if (c == 0) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ label = bp++;
+ continue;
+ }
+ if (bp >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *bp++ = (u_char)c;
+ }
+ c = (bp - label - 1);
+ if ((c & NS_CMPRSFLGS) != 0) { /* Label too big. */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ if (label >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *label = c;
+ if (c != 0) {
+ if (bp >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *bp++ = 0;
+ }
+ if ((bp - dst) > MAXCDNAME) { /* src too big */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ return (0);
+}
+
+/*
+ * ns_name_unpack(msg, eom, src, dst, dstsiz)
+ * Unpack a domain name from a message, source may be compressed.
+ * return:
+ * -1 if it fails, or consumed octets if it succeeds.
+ */
+int
+ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
+ u_char *dst, size_t dstsiz)
+{
+ const u_char *srcp, *dstlim;
+ u_char *dstp;
+ int n, len, checked;
+
+ len = -1;
+ checked = 0;
+ dstp = dst;
+ srcp = src;
+ dstlim = dst + dstsiz;
+ if (srcp < msg || srcp >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ /* Fetch next label in domain name. */
+ while ((n = *srcp++) != 0) {
+ /* Check for indirection. */
+ switch (n & NS_CMPRSFLGS) {
+ case 0:
+ /* Limit checks. */
+ if (dstp + n + 1 >= dstlim || srcp + n >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ checked += n + 1;
+ *dstp++ = n;
+ memcpy(dstp, srcp, n);
+ dstp += n;
+ srcp += n;
+ break;
+
+ case NS_CMPRSFLGS:
+ if (srcp >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ if (len < 0)
+ len = srcp - src + 1;
+ srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff));
+ if (srcp < msg || srcp >= eom) { /* Out of range. */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ checked += 2;
+ /*
+ * Check for loops in the compressed name;
+ * if we've looked at the whole message,
+ * there must be a loop.
+ */
+ if (checked >= eom - msg) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ break;
+
+ default:
+ errno = EMSGSIZE;
+ return (-1); /* flag error */
+ }
+ }
+ *dstp = '\0';
+ if (len < 0)
+ len = srcp - src;
+ return (len);
+}
+
+/*
+ * ns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr)
+ * Pack domain name 'domain' into 'comp_dn'.
+ * return:
+ * Size of the compressed name, or -1.
+ * notes:
+ * 'dnptrs' is an array of pointers to previous compressed names.
+ * dnptrs[0] is a pointer to the beginning of the message. The array
+ * ends with NULL.
+ * 'lastdnptr' is a pointer to the end of the array pointed to
+ * by 'dnptrs'.
+ * Side effects:
+ * The list of pointers in dnptrs is updated for labels inserted into
+ * the message as we compress the name. If 'dnptr' is NULL, we don't
+ * try to compress names. If 'lastdnptr' is NULL, we don't update the
+ * list.
+ */
+int
+ns_name_pack(const u_char *src, u_char *dst, int dstsiz,
+ const u_char **dnptrs, const u_char **lastdnptr)
+{
+ u_char *dstp;
+ const u_char **cpp, **lpp, *eob, *msg;
+ const u_char *srcp;
+ int n, l;
+
+ srcp = src;
+ dstp = dst;
+ eob = dstp + dstsiz;
+ lpp = cpp = NULL;
+ if (dnptrs != NULL) {
+ if ((msg = *dnptrs++) != NULL) {
+ for (cpp = dnptrs; *cpp != NULL; cpp++)
+ (void)NULL;
+ lpp = cpp; /* end of list to search */
+ }
+ } else
+ msg = NULL;
+
+ /* make sure the domain we are about to add is legal */
+ l = 0;
+ do {
+ n = *srcp;
+ if ((n & NS_CMPRSFLGS) != 0) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ l += n + 1;
+ if (l > MAXCDNAME) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ srcp += n + 1;
+ } while (n != 0);
+
+ srcp = src;
+ do {
+ /* Look to see if we can use pointers. */
+ n = *srcp;
+ if (n != 0 && msg != NULL) {
+ l = dn_find(srcp, msg, (const u_char * const *)dnptrs,
+ (const u_char * const *)lpp);
+ if (l >= 0) {
+ if (dstp + 1 >= eob) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dstp++ = (l >> 8) | NS_CMPRSFLGS;
+ *dstp++ = l % 256;
+ return (dstp - dst);
+ }
+ /* Not found, save it. */
+ if (lastdnptr != NULL && cpp < lastdnptr - 1 &&
+ (dstp - msg) < 0x4000) {
+ *cpp++ = dstp;
+ *cpp = NULL;
+ }
+ }
+ /* copy label to buffer */
+ if (n & NS_CMPRSFLGS) { /* Should not happen. */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ if (dstp + 1 + n >= eob) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ memcpy(dstp, srcp, n + 1);
+ srcp += n + 1;
+ dstp += n + 1;
+ } while (n != 0);
+
+ if (dstp > eob) {
+ if (msg != NULL)
+ *lpp = NULL;
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ return (dstp - dst);
+}
+
+/*
+ * ns_name_uncompress(msg, eom, src, dst, dstsiz)
+ * Expand compressed domain name to presentation format.
+ * return:
+ * Number of bytes read out of `src', or -1 (with errno set).
+ * note:
+ * Root domain returns as "." not "".
+ */
+int
+ns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src,
+ char *dst, size_t dstsiz)
+{
+ u_char tmp[NS_MAXCDNAME];
+ int n;
+
+ if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1)
+ return (-1);
+ if (ns_name_ntop(tmp, dst, dstsiz) == -1)
+ return (-1);
+ return (n);
+}
+
+/*
+ * ns_name_compress(src, dst, dstsiz, dnptrs, lastdnptr)
+ * Compress a domain name into wire format, using compression pointers.
+ * return:
+ * Number of bytes consumed in `dst' or -1 (with errno set).
+ * notes:
+ * 'dnptrs' is an array of pointers to previous compressed names.
+ * dnptrs[0] is a pointer to the beginning of the message.
+ * The list ends with NULL. 'lastdnptr' is a pointer to the end of the
+ * array pointed to by 'dnptrs'. Side effect is to update the list of
+ * pointers for labels inserted into the message as we compress the name.
+ * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
+ * is NULL, we don't update the list.
+ */
+int
+ns_name_compress(const char *src, u_char *dst, size_t dstsiz,
+ const u_char **dnptrs, const u_char **lastdnptr)
+{
+ u_char tmp[NS_MAXCDNAME];
+
+ if (ns_name_pton(src, tmp, sizeof tmp) == -1)
+ return (-1);
+ return (ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr));
+}
+
+/*
+ * ns_name_skip(ptrptr, eom)
+ * Advance *ptrptr to skip over the compressed name it points at.
+ * return:
+ * 0 on success, -1 (with errno set) on failure.
+ */
+int
+ns_name_skip(const u_char **ptrptr, const u_char *eom) {
+ const u_char *cp;
+ u_int n;
+
+ cp = *ptrptr;
+ while (cp < eom && (n = *cp++) != 0) {
+ /* Check for indirection. */
+ switch (n & NS_CMPRSFLGS) {
+ case 0: /* normal case, n == len */
+ cp += n;
+ continue;
+ case NS_CMPRSFLGS: /* indirection */
+ cp++;
+ break;
+ default: /* illegal type */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ break;
+ }
+ if (cp > eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *ptrptr = cp;
+ return (0);
+}
+
+/* Private. */
+
+/*
+ * special(ch)
+ * Thinking in noninternationalized USASCII (per the DNS spec),
+ * is this characted special ("in need of quoting") ?
+ * return:
+ * boolean.
+ */
+static int
+special(int ch) {
+ switch (ch) {
+ case 0x22: /* '"' */
+ case 0x2E: /* '.' */
+ case 0x3B: /* ';' */
+ case 0x5C: /* '\\' */
+ /* Special modifiers in zone files. */
+ case 0x40: /* '@' */
+ case 0x24: /* '$' */
+ return (1);
+ default:
+ return (0);
+ }
+}
+
+/*
+ * printable(ch)
+ * Thinking in noninternationalized USASCII (per the DNS spec),
+ * is this character visible and not a space when printed ?
+ * return:
+ * boolean.
+ */
+static int
+printable(int ch) {
+ return (ch > 0x20 && ch < 0x7f);
+}
+
+/*
+ * Thinking in noninternationalized USASCII (per the DNS spec),
+ * convert this character to lower case if it's upper case.
+ */
+static int
+mklower(int ch) {
+ if (ch >= 0x41 && ch <= 0x5A)
+ return (ch + 0x20);
+ return (ch);
+}
+
+/*
+ * dn_find(domain, msg, dnptrs, lastdnptr)
+ * Search for the counted-label name in an array of compressed names.
+ * return:
+ * offset from msg if found, or -1.
+ * notes:
+ * dnptrs is the pointer to the first name on the list,
+ * not the pointer to the start of the message.
+ */
+static int
+dn_find(const u_char *domain, const u_char *msg,
+ const u_char * const *dnptrs,
+ const u_char * const *lastdnptr)
+{
+ const u_char *dn, *cp, *sp;
+ const u_char * const *cpp;
+ u_int n;
+
+ for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
+ dn = domain;
+ sp = cp = *cpp;
+ while ((n = *cp++) != 0) {
+ /*
+ * check for indirection
+ */
+ switch (n & NS_CMPRSFLGS) {
+ case 0: /* normal case, n == len */
+ if (n != *dn++)
+ goto next;
+ for ((void)NULL; n > 0; n--)
+ if (mklower(*dn++) != mklower(*cp++))
+ goto next;
+ /* Is next root for both ? */
+ if (*dn == '\0' && *cp == '\0')
+ return (sp - msg);
+ if (*dn)
+ continue;
+ goto next;
+
+ case NS_CMPRSFLGS: /* indirection */
+ cp = msg + (((n & 0x3f) << 8) | *cp);
+ break;
+
+ default: /* illegal type */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ }
+ next: ;
+ }
+ errno = ENOENT;
+ return (-1);
+}
diff --git a/cpukit/libnetworking/libc/ns_netint.c b/cpukit/libnetworking/libc/ns_netint.c
new file mode 100644
index 0000000000..3c09da8f8c
--- /dev/null
+++ b/cpukit/libnetworking/libc/ns_netint.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ */
+
+#if !defined(__rtems__)
+#if !defined(LINT) && !defined(CODECENTER)
+static char rcsid[] = "$Id$";
+#endif /* not lint */
+#endif /* not rtems */
+
+/* Import. */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
+u_int
+ns_get16(const u_char *src) {
+ u_int dst;
+
+ NS_GET16(dst, src);
+ return (dst);
+}
+
+u_long
+ns_get32(const u_char *src) {
+ u_long dst;
+
+ NS_GET32(dst, src);
+ return (dst);
+}
+
+void
+ns_put16(u_int src, u_char *dst) {
+ NS_PUT16(src, dst);
+}
+
+void
+ns_put32(u_long src, u_char *dst) {
+ NS_PUT32(src, dst);
+}
diff --git a/cpukit/libnetworking/libc/ns_ntoa.c b/cpukit/libnetworking/libc/ns_ntoa.c
new file mode 100644
index 0000000000..9d0be2e1dc
--- /dev/null
+++ b/cpukit/libnetworking/libc/ns_ntoa.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 1986, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)ns_ntoa.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <netns/ns.h>
+#include <stdio.h>
+
+char *
+ns_ntoa(addr)
+ struct ns_addr addr;
+{
+ static char obuf[40];
+ union { union ns_net net_e; u_long long_e; } net;
+ u_short port = htons(addr.x_port);
+ register char *cp;
+ char *cp2;
+ register u_char *up = addr.x_host.c_host;
+ u_char *uplim = up + 6;
+ static char *spectHex();
+
+ net.net_e = addr.x_net;
+ sprintf(obuf, "%lx", (u_long)ntohl(net.long_e));
+ cp = spectHex(obuf);
+ cp2 = cp + 1;
+ while (*up==0 && up < uplim) up++;
+ if (up == uplim) {
+ if (port) {
+ sprintf(cp, ".0");
+ cp += 2;
+ }
+ } else {
+ sprintf(cp, ".%x", *up++);
+ while (up < uplim) {
+ while (*cp) cp++;
+ sprintf(cp, "%02x", *up++);
+ }
+ cp = spectHex(cp2);
+ }
+ if (port) {
+ sprintf(cp, ".%x", port);
+ spectHex(cp + 1);
+ }
+ return (obuf);
+}
+
+static char *
+spectHex(p0)
+ char *p0;
+{
+ int ok = 0;
+ int nonzero = 0;
+ register char *p = p0;
+ for (; *p; p++) switch (*p) {
+
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ *p += ('A' - 'a');
+ /* fall into . . . */
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ ok = 1;
+ case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7': case '8': case '9':
+ nonzero = 1;
+ }
+ if (nonzero && !ok) { *p++ = 'H'; *p = 0; }
+ return (p);
+}
diff --git a/cpukit/libnetworking/libc/ns_parse.c b/cpukit/libnetworking/libc/ns_parse.c
new file mode 100644
index 0000000000..cc1f070156
--- /dev/null
+++ b/cpukit/libnetworking/libc/ns_parse.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ */
+
+#if !defined(__rtems__)
+#if !defined(LINT) && !defined(CODECENTER)
+static char rcsid[] = "$Id$";
+#endif /* not lint */
+#endif /* not rtems */
+
+#include <sys/types.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <resolv.h>
+#include <string.h>
+
+/* These need to be in the same order as the nres.h:ns_flag enum. */
+struct _ns_flagdata _ns_flagdata[16] = {
+ { 0x8000, 15 }, /* qr. */
+ { 0x7800, 11 }, /* opcode. */
+ { 0x0400, 10 }, /* aa. */
+ { 0x0200, 9 }, /* tc. */
+ { 0x0100, 8 }, /* rd. */
+ { 0x0080, 7 }, /* ra. */
+ { 0x0040, 6 }, /* z. */
+ { 0x0020, 5 }, /* ad. */
+ { 0x0010, 4 }, /* cd. */
+ { 0x000f, 0 }, /* rcode. */
+ { 0x0000, 0 }, /* expansion (1/6). */
+ { 0x0000, 0 }, /* expansion (2/6). */
+ { 0x0000, 0 }, /* expansion (3/6). */
+ { 0x0000, 0 }, /* expansion (4/6). */
+ { 0x0000, 0 }, /* expansion (5/6). */
+ { 0x0000, 0 }, /* expansion (6/6). */
+};
+
+static int
+skiprr(const u_char *ptr, const u_char *eom, ns_sect section, int count) {
+ const u_char *optr = ptr;
+
+ for ((void)NULL; count > 0; count--) {
+ int b, rdlength;
+
+ b = dn_skipname(ptr, eom);
+ if (b < 0)
+ goto emsgsize;
+ ptr += b/*Name*/ + NS_INT16SZ/*Type*/ + NS_INT16SZ/*Class*/;
+ if (section != ns_s_qd) {
+ if (ptr + NS_INT32SZ > eom)
+ goto emsgsize;
+ ptr += NS_INT32SZ/*TTL*/;
+ if (ptr + NS_INT16SZ > eom)
+ goto emsgsize;
+ NS_GET16(rdlength, ptr);
+ ptr += rdlength/*RData*/;
+ }
+ }
+ if (ptr > eom)
+ goto emsgsize;
+ return (ptr - optr);
+ emsgsize:
+ errno = EMSGSIZE;
+ return (-1);
+}
+
+int
+ns_initparse(const u_char *msg, int msglen, ns_msg *handle) {
+ const u_char *eom = msg + msglen;
+ int i;
+
+ memset(handle, 0x5e, sizeof *handle);
+ handle->_msg = msg;
+ handle->_eom = eom;
+ if (msg + NS_INT16SZ > eom)
+ goto emsgsize;
+ NS_GET16(handle->_id, msg);
+ if (msg + NS_INT16SZ > eom)
+ goto emsgsize;
+ NS_GET16(handle->_flags, msg);
+ for (i = 0; i < ns_s_max; i++) {
+ if (msg + NS_INT16SZ > eom)
+ goto emsgsize;
+ NS_GET16(handle->_counts[i], msg);
+ }
+ for (i = 0; i < ns_s_max; i++)
+ if (handle->_counts[i] == 0)
+ handle->_sections[i] = NULL;
+ else {
+ int b = skiprr(msg, eom, (ns_sect)i,
+ handle->_counts[i]);
+
+ if (b < 0)
+ return (-1);
+ handle->_sections[i] = msg;
+ msg += b;
+ }
+ if (msg != eom)
+ goto emsgsize;
+ handle->_sect = ns_s_max;
+ handle->_rrnum = -1;
+ handle->_ptr = NULL;
+ return (0);
+ emsgsize:
+ errno = EMSGSIZE;
+ return (-1);
+}
+
+int
+ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) {
+ int b;
+
+ /* Make section right. */
+ if (section < 0 || section >= ns_s_max)
+ goto enodev;
+ if ((int)section != (int)handle->_sect) {
+ handle->_sect = section;
+ handle->_rrnum = 0;
+ handle->_ptr = handle->_sections[(int)section];
+ }
+
+ /* Make rrnum right. */
+ if (rrnum == -1)
+ rrnum = handle->_rrnum;
+ if (rrnum < 0 || rrnum >= handle->_counts[(int)section])
+ goto enodev;
+ if (rrnum < handle->_rrnum) {
+ handle->_rrnum = 0;
+ handle->_ptr = handle->_sections[(int)section];
+ }
+
+ b = skiprr(handle->_msg, handle->_eom, section,
+ rrnum - handle->_rrnum);
+ if (b < 0)
+ return (-1);
+ handle->_ptr += b;
+ handle->_rrnum = rrnum;
+
+ /* Do the parse. */
+ b = dn_expand(handle->_msg, handle->_eom,
+ handle->_ptr, rr->name, NS_MAXDNAME);
+ if (b < 0)
+ return (-1);
+ handle->_ptr += b;
+ if (handle->_ptr + NS_INT16SZ > handle->_eom)
+ goto emsgsize;
+ NS_GET16(rr->type, handle->_ptr);
+ if (handle->_ptr + NS_INT16SZ > handle->_eom)
+ goto emsgsize;
+ NS_GET16(rr->class, handle->_ptr);
+ if (section == ns_s_qd) {
+ rr->ttl = 0;
+ rr->rdlength = 0;
+ rr->rdata = NULL;
+ } else {
+ if (handle->_ptr + NS_INT32SZ > handle->_eom)
+ goto emsgsize;
+ NS_GET32(rr->ttl, handle->_ptr);
+ if (handle->_ptr + NS_INT16SZ > handle->_eom)
+ goto emsgsize;
+ NS_GET16(rr->rdlength, handle->_ptr);
+ if (handle->_ptr + rr->rdlength > handle->_eom)
+ goto emsgsize;
+ rr->rdata = handle->_ptr;
+ handle->_ptr += rr->rdlength;
+ }
+ handle->_rrnum++;
+
+ /* All done. */
+ return (0);
+ enodev:
+ errno = ENODEV;
+ return (-1);
+ emsgsize:
+ errno = EMSGSIZE;
+ return (-1);
+}
diff --git a/cpukit/libnetworking/libc/ns_print.c b/cpukit/libnetworking/libc/ns_print.c
new file mode 100644
index 0000000000..f7d7d16c64
--- /dev/null
+++ b/cpukit/libnetworking/libc/ns_print.c
@@ -0,0 +1,745 @@
+/*
+ * Copyright (c) 1996, 1998 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ */
+
+#if !defined(__rtems__)
+#if !defined(LINT) && !defined(CODECENTER)
+static char rcsid[] = "$Id$";
+#endif /* not lint */
+#endif /* not rtems */
+
+/* Import. */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <resolv.h>
+#include <string.h>
+#include <ctype.h>
+
+#define SPRINTF(x) ((size_t)sprintf x)
+
+/* Forward. */
+
+static size_t prune_origin(const char *name, const char *origin);
+static int charstr(const u_char *rdata, const u_char *edata,
+ char **buf, size_t *buflen);
+static int addname(const u_char *msg, size_t msglen,
+ const u_char **p, const char *origin,
+ char **buf, size_t *buflen);
+static void addlen(size_t len, char **buf, size_t *buflen);
+static int addstr(const char *src, size_t len,
+ char **buf, size_t *buflen);
+static int addtab(size_t len, size_t target, int spaced,
+ char **buf, size_t *buflen);
+
+/* Macros. */
+
+#define T(x) \
+ do { \
+ if ((x) < 0) \
+ return (-1); \
+ } while (0)
+
+/* Public. */
+
+/*
+ * int
+ * ns_sprintrr(handle, rr, name_ctx, origin, buf, buflen)
+ * Convert an RR to presentation format.
+ * return:
+ * Number of characters written to buf, or -1 (check errno).
+ */
+int
+ns_sprintrr(const ns_msg *handle, const ns_rr *rr,
+ const char *name_ctx, const char *origin,
+ char *buf, size_t buflen)
+{
+ int n;
+
+ n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle),
+ ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr),
+ ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr),
+ name_ctx, origin, buf, buflen);
+ return (n);
+}
+
+/*
+ * int
+ * ns_sprintrrf(msg, msglen, name, class, type, ttl, rdata, rdlen,
+ * name_ctx, origin, buf, buflen)
+ * Convert the fields of an RR into presentation format.
+ * return:
+ * Number of characters written to buf, or -1 (check errno).
+ */
+int
+ns_sprintrrf(const u_char *msg, size_t msglen,
+ const char *name, ns_class class, ns_type type,
+ u_long ttl, const u_char *rdata, size_t rdlen,
+ const char *name_ctx, const char *origin,
+ char *buf, size_t buflen)
+{
+ const char *obuf = buf;
+ const u_char *edata = rdata + rdlen;
+ int spaced = 0;
+
+ const char *comment;
+ char tmp[100];
+ int len, x;
+
+ /*
+ * Owner.
+ */
+ if (name_ctx != NULL && strcasecmp(name_ctx, name) == 0) {
+ T(addstr("\t\t\t", 3, &buf, &buflen));
+ } else {
+ len = prune_origin(name, origin);
+ if (len == 0) {
+ T(addstr("@\t\t\t", 4, &buf, &buflen));
+ } else {
+ T(addstr(name, len, &buf, &buflen));
+ /* Origin not used and no trailing dot? */
+ if ((!origin || !origin[0] || name[len] == '\0') &&
+ name[len - 1] != '.') {
+ T(addstr(".", 1, &buf, &buflen));
+ len++;
+ }
+ T(spaced = addtab(len, 24, spaced, &buf, &buflen));
+ }
+ }
+
+ /*
+ * TTL, Class, Type.
+ */
+ T(x = ns_format_ttl(ttl, buf, buflen));
+ addlen(x, &buf, &buflen);
+ len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type)));
+ T(addstr(tmp, len, &buf, &buflen));
+ T(spaced = addtab(x + len, 16, spaced, &buf, &buflen));
+
+ /*
+ * RData.
+ */
+ switch (type) {
+ case ns_t_a:
+ if (rdlen != NS_INADDRSZ)
+ goto formerr;
+ (void) inet_ntop(AF_INET, rdata, buf, buflen);
+ addlen(strlen(buf), &buf, &buflen);
+ break;
+
+ case ns_t_cname:
+ case ns_t_mb:
+ case ns_t_mg:
+ case ns_t_mr:
+ case ns_t_ns:
+ case ns_t_ptr:
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ break;
+
+ case ns_t_hinfo:
+ case ns_t_isdn:
+ /* First word. */
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Second word. */
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ break;
+
+ case ns_t_soa: {
+ u_long t;
+
+ /* Server name. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Administrator name. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ T(addstr(" (\n", 3, &buf, &buflen));
+ spaced = 0;
+
+ if ((edata - rdata) != 5*NS_INT32SZ)
+ goto formerr;
+
+ /* Serial number. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
+ len = SPRINTF((tmp, "%lu", t));
+ T(addstr(tmp, len, &buf, &buflen));
+ T(spaced = addtab(len, 16, spaced, &buf, &buflen));
+ T(addstr("; serial\n", 9, &buf, &buflen));
+ spaced = 0;
+
+ /* Refresh interval. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
+ T(len = ns_format_ttl(t, buf, buflen));
+ addlen(len, &buf, &buflen);
+ T(spaced = addtab(len, 16, spaced, &buf, &buflen));
+ T(addstr("; refresh\n", 10, &buf, &buflen));
+ spaced = 0;
+
+ /* Retry interval. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
+ T(len = ns_format_ttl(t, buf, buflen));
+ addlen(len, &buf, &buflen);
+ T(spaced = addtab(len, 16, spaced, &buf, &buflen));
+ T(addstr("; retry\n", 8, &buf, &buflen));
+ spaced = 0;
+
+ /* Expiry. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
+ T(len = ns_format_ttl(t, buf, buflen));
+ addlen(len, &buf, &buflen);
+ T(spaced = addtab(len, 16, spaced, &buf, &buflen));
+ T(addstr("; expiry\n", 9, &buf, &buflen));
+ spaced = 0;
+
+ /* Minimum TTL. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
+ T(len = ns_format_ttl(t, buf, buflen));
+ addlen(len, &buf, &buflen);
+ T(addstr(" )", 2, &buf, &buflen));
+ T(spaced = addtab(len, 16, spaced, &buf, &buflen));
+ T(addstr("; minimum\n", 10, &buf, &buflen));
+
+ break;
+ }
+
+ case ns_t_mx:
+ case ns_t_afsdb:
+ case ns_t_rt: {
+ u_int t;
+
+ if (rdlen < NS_INT16SZ)
+ goto formerr;
+
+ /* Priority. */
+ t = ns_get16(rdata);
+ rdata += NS_INT16SZ;
+ len = SPRINTF((tmp, "%u ", t));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Target. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+
+ break;
+ }
+
+ case ns_t_px: {
+ u_int t;
+
+ if (rdlen < NS_INT16SZ)
+ goto formerr;
+
+ /* Priority. */
+ t = ns_get16(rdata);
+ rdata += NS_INT16SZ;
+ len = SPRINTF((tmp, "%u ", t));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Name1. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Name2. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+
+ break;
+ }
+
+ case ns_t_x25:
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ break;
+
+ case ns_t_txt:
+ while (rdata < edata) {
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ if (rdata < edata)
+ T(addstr(" ", 1, &buf, &buflen));
+ }
+ break;
+
+ case ns_t_nsap: {
+ char t[255*3];
+
+ (void) inet_nsap_ntoa(rdlen, rdata, t);
+ T(addstr(t, strlen(t), &buf, &buflen));
+ break;
+ }
+
+ case ns_t_aaaa:
+ if (rdlen != NS_IN6ADDRSZ)
+ goto formerr;
+ (void) inet_ntop(AF_INET6, rdata, buf, buflen);
+ addlen(strlen(buf), &buf, &buflen);
+ break;
+
+ case ns_t_loc: {
+ char t[255];
+
+ /* XXX protocol format checking? */
+ (void) loc_ntoa(rdata, t);
+ T(addstr(t, strlen(t), &buf, &buflen));
+ break;
+ }
+
+ case ns_t_naptr: {
+ u_int order, preference;
+ char t[50];
+
+ if (rdlen < 2*NS_INT16SZ)
+ goto formerr;
+
+ /* Order, Precedence. */
+ order = ns_get16(rdata); rdata += NS_INT16SZ;
+ preference = ns_get16(rdata); rdata += NS_INT16SZ;
+ len = SPRINTF((t, "%u %u ", order, preference));
+ T(addstr(t, len, &buf, &buflen));
+
+ /* Flags. */
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Service. */
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Regexp. */
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len < 0)
+ return (-1);
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Server. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ break;
+ }
+
+ case ns_t_srv: {
+ u_int priority, weight, port;
+ char t[50];
+
+ if (rdlen < NS_INT16SZ*3)
+ goto formerr;
+
+ /* Priority, Weight, Port. */
+ priority = ns_get16(rdata); rdata += NS_INT16SZ;
+ weight = ns_get16(rdata); rdata += NS_INT16SZ;
+ port = ns_get16(rdata); rdata += NS_INT16SZ;
+ len = SPRINTF((t, "%u %u %u ", priority, weight, port));
+ T(addstr(t, len, &buf, &buflen));
+
+ /* Server. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ break;
+ }
+
+ case ns_t_minfo:
+ case ns_t_rp:
+ /* Name1. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Name2. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+
+ break;
+
+ case ns_t_wks: {
+ int n, lcnt;
+
+ if (rdlen < NS_INT32SZ + 1)
+ goto formerr;
+
+ /* Address. */
+ (void) inet_ntop(AF_INET, rdata, buf, buflen);
+ addlen(strlen(buf), &buf, &buflen);
+ rdata += NS_INADDRSZ;
+
+ /* Protocol. */
+ len = SPRINTF((tmp, " %u ( ", *rdata));
+ T(addstr(tmp, len, &buf, &buflen));
+ rdata += NS_INT8SZ;
+
+ /* Bit map. */
+ n = 0;
+ lcnt = 0;
+ while (rdata < edata) {
+ u_int c = *rdata++;
+ do {
+ if (c & 0200) {
+ if (lcnt == 0) {
+ T(addstr("\n\t\t\t\t", 5,
+ &buf, &buflen));
+ lcnt = 10;
+ spaced = 0;
+ }
+ len = SPRINTF((tmp, "%d ", n));
+ T(addstr(tmp, len, &buf, &buflen));
+ lcnt--;
+ }
+ c <<= 1;
+ } while (++n & 07);
+ }
+ T(addstr(")", 1, &buf, &buflen));
+
+ break;
+ }
+
+ case ns_t_key: {
+ char base64_key[NS_MD5RSA_MAX_BASE64];
+ u_int keyflags, protocol, algorithm;
+ const char *leader;
+ int n;
+
+ if (rdlen < NS_INT16SZ + NS_INT8SZ + NS_INT8SZ)
+ goto formerr;
+
+ /* Key flags, Protocol, Algorithm. */
+ keyflags = ns_get16(rdata); rdata += NS_INT16SZ;
+ protocol = *rdata++;
+ algorithm = *rdata++;
+ len = SPRINTF((tmp, "0x%04x %u %u",
+ keyflags, protocol, algorithm));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Public key data. */
+ len = b64_ntop(rdata, edata - rdata,
+ base64_key, sizeof base64_key);
+ if (len < 0)
+ goto formerr;
+ if (len > 15) {
+ T(addstr(" (", 2, &buf, &buflen));
+ leader = "\n\t\t";
+ spaced = 0;
+ } else
+ leader = " ";
+ for (n = 0; n < len; n += 48) {
+ T(addstr(leader, strlen(leader), &buf, &buflen));
+ T(addstr(base64_key + n, MIN(len - n, 48),
+ &buf, &buflen));
+ }
+ if (len > 15)
+ T(addstr(" )", 2, &buf, &buflen));
+
+ break;
+ }
+
+ case ns_t_sig: {
+ char base64_key[NS_MD5RSA_MAX_BASE64];
+ u_int type, algorithm, labels, footprint;
+ const char *leader;
+ u_long t;
+ int n;
+
+ if (rdlen < 22)
+ goto formerr;
+
+ /* Type covered, Algorithm, Label count, Original TTL. */
+ type = ns_get16(rdata); rdata += NS_INT16SZ;
+ algorithm = *rdata++;
+ labels = *rdata++;
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ len = SPRINTF((tmp, " %s %d %lu ",
+ p_type(type), algorithm, t));
+ T(addstr(tmp, len, &buf, &buflen));
+ if (labels != (u_int)dn_count_labels(name))
+ goto formerr;
+
+ /* Signature expiry. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ len = SPRINTF((tmp, "%s ", p_secstodate(t)));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Time signed. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ len = SPRINTF((tmp, "%s ", p_secstodate(t)));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Signature Footprint. */
+ footprint = ns_get16(rdata); rdata += NS_INT16SZ;
+ len = SPRINTF((tmp, "%u ", footprint));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Signer's name. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+
+ /* Signature. */
+ len = b64_ntop(rdata, edata - rdata,
+ base64_key, sizeof base64_key);
+ if (len > 15) {
+ T(addstr(" (", 2, &buf, &buflen));
+ leader = "\n\t\t";
+ spaced = 0;
+ } else
+ leader = " ";
+ if (len < 0)
+ goto formerr;
+ for (n = 0; n < len; n += 48) {
+ T(addstr(leader, strlen(leader), &buf, &buflen));
+ T(addstr(base64_key + n, MIN(len - n, 48),
+ &buf, &buflen));
+ }
+ if (len > 15)
+ T(addstr(" )", 2, &buf, &buflen));
+
+ break;
+ }
+
+ case ns_t_nxt: {
+ int n, c;
+
+ /* Next domain name. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+
+ /* Type bit map. */
+ n = edata - rdata;
+ for (c = 0; c < n*8; c++)
+ if (NS_NXT_BIT_ISSET(c, rdata)) {
+ len = SPRINTF((tmp, " %s", p_type(c)));
+ T(addstr(tmp, len, &buf, &buflen));
+ }
+ break;
+ }
+
+ default:
+ comment = "unknown RR type";
+ goto hexify;
+ }
+ return (buf - obuf);
+ formerr:
+ comment = "RR format error";
+ hexify: {
+ int n, m;
+ char *p;
+
+ len = SPRINTF((tmp, "\\#(\t\t; %s", comment));
+ T(addstr(tmp, len, &buf, &buflen));
+ while (rdata < edata) {
+ p = tmp;
+ p += SPRINTF((p, "\n\t"));
+ spaced = 0;
+ n = MIN(16, edata - rdata);
+ for (m = 0; m < n; m++)
+ p += SPRINTF((p, "%02x ", rdata[m]));
+ T(addstr(tmp, p - tmp, &buf, &buflen));
+ if (n < 16) {
+ T(addstr(")", 1, &buf, &buflen));
+ T(addtab(p - tmp + 1, 48, spaced, &buf, &buflen));
+ }
+ p = tmp;
+ p += SPRINTF((p, "; "));
+ for (m = 0; m < n; m++)
+ *p++ = (isascii(rdata[m]) && isprint(rdata[m]))
+ ? rdata[m]
+ : '.';
+ T(addstr(tmp, p - tmp, &buf, &buflen));
+ rdata += n;
+ }
+ return (buf - obuf);
+ }
+}
+
+/* Private. */
+
+/*
+ * size_t
+ * prune_origin(name, origin)
+ * Find out if the name is at or under the current origin.
+ * return:
+ * Number of characters in name before start of origin,
+ * or length of name if origin does not match.
+ * notes:
+ * This function should share code with samedomain().
+ */
+static size_t
+prune_origin(const char *name, const char *origin) {
+ const char *oname = name;
+
+ while (*name != '\0') {
+ if (origin != NULL && strcasecmp(name, origin) == 0)
+ return (name - oname - (name > oname));
+ while (*name != '\0') {
+ if (*name == '\\') {
+ name++;
+ /* XXX need to handle \nnn form. */
+ if (*name == '\0')
+ break;
+ } else if (*name == '.') {
+ name++;
+ break;
+ }
+ name++;
+ }
+ }
+ return (name - oname);
+}
+
+/*
+ * int
+ * charstr(rdata, edata, buf, buflen)
+ * Format a <character-string> into the presentation buffer.
+ * return:
+ * Number of rdata octets consumed
+ * 0 for protocol format error
+ * -1 for output buffer error
+ * side effects:
+ * buffer is advanced on success.
+ */
+static int
+charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) {
+ const u_char *odata = rdata;
+ size_t save_buflen = *buflen;
+ char *save_buf = *buf;
+
+ if (addstr("\"", 1, buf, buflen) < 0)
+ goto enospc;
+ if (rdata < edata) {
+ int n = *rdata;
+
+ if (rdata + 1 + n <= edata) {
+ rdata++;
+ while (n-- > 0) {
+ if (strchr("\n\"\\", *rdata) != NULL)
+ if (addstr("\\", 1, buf, buflen) < 0)
+ goto enospc;
+ if (addstr((const char *)rdata, 1,
+ buf, buflen) < 0)
+ goto enospc;
+ rdata++;
+ }
+ }
+ }
+ if (addstr("\"", 1, buf, buflen) < 0)
+ goto enospc;
+ return (rdata - odata);
+ enospc:
+ errno = ENOSPC;
+ *buf = save_buf;
+ *buflen = save_buflen;
+ return (-1);
+}
+
+static int
+addname(const u_char *msg, size_t msglen,
+ const u_char **pp, const char *origin,
+ char **buf, size_t *buflen)
+{
+ size_t newlen, save_buflen = *buflen;
+ char *save_buf = *buf;
+ int n;
+
+ n = dn_expand(msg, msg + msglen, *pp, *buf, *buflen);
+ if (n < 0)
+ goto enospc; /* Guess. */
+ newlen = prune_origin(*buf, origin);
+ if ((origin == NULL || origin[0] == '\0' || (*buf)[newlen] == '\0') &&
+ (newlen == 0 || (*buf)[newlen - 1] != '.')) {
+ /* No trailing dot. */
+ if (newlen + 2 > *buflen)
+ goto enospc; /* No room for ".\0". */
+ (*buf)[newlen++] = '.';
+ (*buf)[newlen] = '\0';
+ }
+ if (newlen == 0) {
+ /* Use "@" instead of name. */
+ if (newlen + 2 > *buflen)
+ goto enospc; /* No room for "@\0". */
+ (*buf)[newlen++] = '@';
+ (*buf)[newlen] = '\0';
+ }
+ *pp += n;
+ addlen(newlen, buf, buflen);
+ **buf = '\0';
+ return (newlen);
+ enospc:
+ errno = ENOSPC;
+ *buf = save_buf;
+ *buflen = save_buflen;
+ return (-1);
+}
+
+static void
+addlen(size_t len, char **buf, size_t *buflen) {
+ assert(len <= *buflen);
+ *buf += len;
+ *buflen -= len;
+}
+
+static int
+addstr(const char *src, size_t len, char **buf, size_t *buflen) {
+ if (len > *buflen) {
+ errno = ENOSPC;
+ return (-1);
+ }
+ memcpy(*buf, src, len);
+ addlen(len, buf, buflen);
+ **buf = '\0';
+ return (0);
+}
+
+static int
+addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) {
+ size_t save_buflen = *buflen;
+ char *save_buf = *buf;
+ int t;
+
+ if (spaced || len >= target - 1) {
+ T(addstr(" ", 2, buf, buflen));
+ spaced = 1;
+ } else {
+ for (t = (target - len - 1) / 8; t >= 0; t--)
+ if (addstr("\t", 1, buf, buflen) < 0) {
+ *buflen = save_buflen;
+ *buf = save_buf;
+ return (-1);
+ }
+ spaced = 0;
+ }
+ return (spaced);
+}
diff --git a/cpukit/libnetworking/libc/ns_ttl.c b/cpukit/libnetworking/libc/ns_ttl.c
new file mode 100644
index 0000000000..75093c1dbc
--- /dev/null
+++ b/cpukit/libnetworking/libc/ns_ttl.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ */
+
+#if !defined(__rtems__)
+#if !defined(LINT) && !defined(CODECENTER)
+static char rcsid[] = "$Id$";
+#endif /* not lint */
+#endif /* not rtems */
+
+/* Import. */
+
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#define SPRINTF(x) ((size_t)sprintf x)
+
+/* Forward. */
+
+static int fmt1(int t, char s, char **buf, size_t *buflen);
+
+/* Macros. */
+
+#define T(x) if ((x) < 0) return (-1); else (void)NULL
+
+/* Public. */
+
+int
+ns_format_ttl(u_long src, char *dst, size_t dstlen) {
+ char *odst = dst;
+ int secs, mins, hours, days, weeks, x;
+ char *p;
+
+ secs = src % 60; src /= 60;
+ mins = src % 60; src /= 60;
+ hours = src % 24; src /= 24;
+ days = src % 7; src /= 7;
+ weeks = src; src = 0;
+
+ x = 0;
+ if (weeks) {
+ T(fmt1(weeks, 'W', &dst, &dstlen));
+ x++;
+ }
+ if (days) {
+ T(fmt1(days, 'D', &dst, &dstlen));
+ x++;
+ }
+ if (hours) {
+ T(fmt1(hours, 'H', &dst, &dstlen));
+ x++;
+ }
+ if (mins) {
+ T(fmt1(mins, 'M', &dst, &dstlen));
+ x++;
+ }
+ if (secs || !(weeks || days || hours || mins)) {
+ T(fmt1(secs, 'S', &dst, &dstlen));
+ x++;
+ }
+
+ if (x > 1) {
+ int ch;
+
+ for (p = odst; (ch = *p) != '\0'; p++)
+ if (isascii(ch) && isupper(ch))
+ *p = tolower(ch);
+ }
+
+ return (dst - odst);
+}
+
+int
+ns_parse_ttl(const char *src, u_long *dst) {
+ u_long ttl, tmp;
+ int ch, digits, dirty;
+
+ ttl = 0;
+ tmp = 0;
+ digits = 0;
+ dirty = 0;
+ while ((ch = *src++) != '\0') {
+ if (!isascii(ch) || !isprint(ch))
+ goto einval;
+ if (isdigit(ch)) {
+ tmp *= 10;
+ tmp += (ch - '0');
+ digits++;
+ continue;
+ }
+ if (digits == 0)
+ goto einval;
+ if (islower(ch))
+ ch = toupper(ch);
+ switch (ch) {
+ case 'W': tmp *= 7;
+ case 'D': tmp *= 24;
+ case 'H': tmp *= 60;
+ case 'M': tmp *= 60;
+ case 'S': break;
+ default: goto einval;
+ }
+ ttl += tmp;
+ tmp = 0;
+ digits = 0;
+ dirty = 1;
+ }
+ if (digits > 0) {
+ if (dirty)
+ goto einval;
+ else
+ ttl += tmp;
+ }
+ *dst = ttl;
+ return (0);
+
+ einval:
+ errno = EINVAL;
+ return (-1);
+}
+
+/* Private. */
+
+static int
+fmt1(int t, char s, char **buf, size_t *buflen) {
+ char tmp[50];
+ size_t len;
+
+ len = SPRINTF((tmp, "%d%c", t, s));
+ if (len + 1 > *buflen)
+ return (-1);
+ strcpy(*buf, tmp);
+ *buf += len;
+ *buflen -= len;
+ return (0);
+}
diff --git a/cpukit/libnetworking/libc/nsap_addr.c b/cpukit/libnetworking/libc/nsap_addr.c
new file mode 100644
index 0000000000..a7af57a266
--- /dev/null
+++ b/cpukit/libnetworking/libc/nsap_addr.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 1996, 1998 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char rcsid[] = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <ctype.h>
+#include <resolv.h>
+
+static char
+xtob(c)
+ register int c;
+{
+ return (c - (((c >= '0') && (c <= '9')) ? '0' : '7'));
+}
+
+u_int
+inet_nsap_addr(ascii, binary, maxlen)
+ const char *ascii;
+ u_char *binary;
+ int maxlen;
+{
+ u_char c, nib;
+ u_int len = 0;
+
+ while ((c = *ascii++) != '\0' && len < (u_int)maxlen) {
+ if (c == '.' || c == '+' || c == '/')
+ continue;
+ if (!isascii(c))
+ return (0);
+ if (islower(c))
+ c = toupper(c);
+ if (isxdigit(c)) {
+ nib = xtob(c);
+ c = *ascii++;
+ if (c != '\0') {
+ c = toupper(c);
+ if (isxdigit(c)) {
+ *binary++ = (nib << 4) | xtob(c);
+ len++;
+ } else
+ return (0);
+ }
+ else
+ return (0);
+ }
+ else
+ return (0);
+ }
+ return (len);
+}
+
+char *
+inet_nsap_ntoa(binlen, binary, ascii)
+ int binlen;
+ register const u_char *binary;
+ register char *ascii;
+{
+ register int nib;
+ int i;
+ static char tmpbuf[255*3];
+ char *start;
+
+ if (ascii)
+ start = ascii;
+ else {
+ ascii = tmpbuf;
+ start = tmpbuf;
+ }
+
+ if (binlen > 255)
+ binlen = 255;
+
+ for (i = 0; i < binlen; i++) {
+ nib = *binary >> 4;
+ *ascii++ = nib + (nib < 10 ? '0' : '7');
+ nib = *binary++ & 0x0f;
+ *ascii++ = nib + (nib < 10 ? '0' : '7');
+ if (((i % 2) == 0 && (i + 1) < binlen))
+ *ascii++ = '.';
+ }
+ *ascii = '\0';
+ return (start);
+}
diff --git a/cpukit/libnetworking/libc/rcmd.3 b/cpukit/libnetworking/libc/rcmd.3
new file mode 100644
index 0000000000..e25057fa4e
--- /dev/null
+++ b/cpukit/libnetworking/libc/rcmd.3
@@ -0,0 +1,204 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. 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 the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+.\"
+.\" From: @(#)rcmd.3 8.1 (Berkeley) 6/4/93
+.\" $Id$
+.\"
+.Dd February 15, 1996
+.Dt RCMD 3
+.Os BSD 4.2
+.Sh NAME
+.Nm rcmd ,
+.Nm rresvport ,
+.Nm iruserok ,
+.Nm ruserok
+.Nd routines for returning a stream to a remote command
+.Sh SYNOPSIS
+.Fd #include <unistd.h>
+.Ft int
+.Fn rcmd "char **ahost" "int inport" "const char *locuser" "const char *remuser" "const char *cmd" "int *fd2p"
+.Ft int
+.Fn rresvport "int *port"
+.Ft int
+.Fn iruserok "u_long raddr" "int superuser" "const char *ruser" "const char *luser"
+.Ft int
+.Fn ruserok "const char *rhost" "int superuser" "const char *ruser" "const char *luser"
+.Sh DESCRIPTION
+The
+.Fn rcmd
+function
+is used by the super-user to execute a command on
+a remote machine using an authentication scheme based
+on reserved port numbers.
+The
+.Fn rresvport
+function
+returns a descriptor to a socket
+with an address in the privileged port space.
+The
+.Fn ruserok
+function
+is used by servers
+to authenticate clients requesting service with
+.Fn rcmd .
+All three functions are present in the same file and are used
+by the
+.Xr rshd 8
+server (among others).
+.Pp
+The
+.Fn rcmd
+function
+looks up the host
+.Fa *ahost
+using
+.Xr gethostbyname 3 ,
+returning \-1 if the host does not exist.
+Otherwise
+.Fa *ahost
+is set to the standard name of the host
+and a connection is established to a server
+residing at the well-known Internet port
+.Fa inport .
+.Pp
+If the connection succeeds,
+a socket in the Internet domain of type
+.Dv SOCK_STREAM
+is returned to the caller, and given to the remote
+command as
+.Em stdin
+and
+.Em stdout .
+If
+.Fa fd2p
+is non-zero, then an auxiliary channel to a control
+process will be set up, and a descriptor for it will be placed
+in
+.Fa *fd2p .
+The control process will return diagnostic
+output from the command (unit 2) on this channel, and will also
+accept bytes on this channel as being
+.Tn UNIX
+signal numbers, to be
+forwarded to the process group of the command.
+If
+.Fa fd2p
+is 0, then the
+.Em stderr
+(unit 2 of the remote
+command) will be made the same as the
+.Em stdout
+and no
+provision is made for sending arbitrary signals to the remote process,
+although you may be able to get its attention by using out-of-band data.
+.Pp
+The protocol is described in detail in
+.Xr rshd 8 .
+.Pp
+The
+.Fn rresvport
+function is used to obtain a socket with a privileged
+address bound to it. This socket is suitable for use
+by
+.Fn rcmd
+and several other functions. Privileged Internet ports are those
+in the range 0 to 1023. Only the super-user
+is allowed to bind an address of this sort to a socket.
+.Pp
+The
+.Fn iruserok
+and
+.Fn ruserok
+functions take a remote host's IP address or name, as returned by the
+.Xr gethostbyname 3
+routines, two user names and a flag indicating whether the local user's
+name is that of the super-user.
+Then, if the user is
+.Em NOT
+the super-user, it checks the
+.Pa /etc/hosts.equiv
+file.
+If that lookup is not done, or is unsuccessful, the
+.Pa .rhosts
+in the local user's home directory is checked to see if the request for
+service is allowed.
+.Pp
+If this file does not exist, is not a regular file, is owned by anyone
+other than the user or the super-user, or is writable by anyone other
+than the owner, the check automatically fails.
+Zero is returned if the machine name is listed in the
+.Dq Pa hosts.equiv
+file, or the host and remote user name are found in the
+.Dq Pa .rhosts
+file; otherwise
+.Fn iruserok
+and
+.Fn ruserok
+return \-1.
+If the local domain (as obtained from
+.Xr gethostname 3 )
+is the same as the remote domain, only the machine name need be specified.
+.Pp
+The
+.Fn iruserok
+function is strongly preferred for security reasons.
+It requires trusting the local DNS at most, while the
+.Fn ruserok
+function requires trusting the entire DNS, which can be spoofed.
+.Sh DIAGNOSTICS
+The
+.Fn rcmd
+function
+returns a valid socket descriptor on success.
+It returns \-1 on error and prints a diagnostic message on the standard error.
+.Pp
+The
+.Fn rresvport
+function
+returns a valid, bound socket descriptor on success.
+It returns \-1 on error with the global value
+.Va errno
+set according to the reason for failure.
+The error code
+.Dv EAGAIN
+is overloaded to mean ``All network ports in use.''
+.Sh SEE ALSO
+.Xr rlogin 1 ,
+.Xr rsh 1 ,
+.Xr intro 2 ,
+.Xr rexec 3 ,
+.Xr rexecd 8 ,
+.Xr rlogind 8 ,
+.Xr rshd 8
+.Sh HISTORY
+These
+functions appeared in
+.Bx 4.2 .
diff --git a/cpukit/libnetworking/libc/rcmd.c b/cpukit/libnetworking/libc/rcmd.c
new file mode 100644
index 0000000000..c588172434
--- /dev/null
+++ b/cpukit/libnetworking/libc/rcmd.c
@@ -0,0 +1,547 @@
+/*
+ * Copyright (c) 1983, 1993, 1994
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rcmd.c 8.3 (Berkeley) 3/26/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <signal.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#ifdef YP
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+
+#include <sys/select.h>
+
+
+#define max(a, b) ((a > b) ? a : b)
+
+#ifdef __rtems__
+int rresvport();
+#define bzero(a,s) memset((a),0,(s))
+#define bcmp memcmp
+#define bcopy(s,d,i) memcpy(d,s,i)
+int bindresvport(int, struct sockaddr_in *);
+#else /* __rtems__ */
+
+extern int innetgr __P(( const char *, const char *, const char *, const char * ));
+
+int __ivaliduser __P((FILE *, u_long, const char *, const char *));
+static int __icheckhost __P((u_long, char *));
+
+#endif
+
+int
+rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
+ char **ahost;
+ u_short rport;
+ const char *locuser, *remuser, *cmd;
+ int *fd2p;
+{
+ struct hostent *hp;
+ struct sockaddr_in sin, from;
+ fd_set reads;
+#ifndef __rtems__
+ long oldmask;
+#endif
+ pid_t pid;
+ int s, lport, timo;
+ char c;
+
+ pid = getpid();
+ hp = gethostbyname(*ahost);
+ if (hp == NULL) {
+ herror(*ahost);
+ return (-1);
+ }
+ *ahost = hp->h_name;
+#ifndef __rtems__
+ oldmask = sigblock(sigmask(SIGURG));
+#endif
+ for (timo = 1, lport = IPPORT_RESERVED - 1;;) {
+ s = rresvport(&lport);
+ if (s < 0) {
+ if (errno == EAGAIN)
+ (void)fprintf(stderr,
+ "rcmd: socket: All ports in use\n");
+ else
+ (void)fprintf(stderr, "rcmd: socket: %s\n",
+ strerror(errno));
+#ifndef __rtems__
+ sigsetmask(oldmask);
+#endif
+ return (-1);
+ }
+ fcntl(s, F_SETOWN, pid);
+ bzero(&sin, sizeof sin);
+ sin.sin_len = sizeof(struct sockaddr_in);
+ sin.sin_family = hp->h_addrtype;
+ sin.sin_port = rport;
+ bcopy(hp->h_addr_list[0], &sin.sin_addr, MIN(hp->h_length, sizeof sin.sin_addr));
+ if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
+ break;
+ (void)close(s);
+ if (errno == EADDRINUSE) {
+ lport--;
+ continue;
+ }
+ if (errno == ECONNREFUSED && timo <= 16) {
+ (void)sleep(timo);
+ timo *= 2;
+ continue;
+ }
+ if (hp->h_addr_list[1] != NULL) {
+ int oerrno = errno;
+
+ (void)fprintf(stderr, "connect to address %s: ",
+ inet_ntoa(sin.sin_addr));
+ errno = oerrno;
+ perror(0);
+ hp->h_addr_list++;
+ bcopy(hp->h_addr_list[0], &sin.sin_addr, MIN(hp->h_length, sizeof sin.sin_addr));
+ (void)fprintf(stderr, "Trying %s...\n",
+ inet_ntoa(sin.sin_addr));
+ continue;
+ }
+ (void)fprintf(stderr, "%s: %s\n", hp->h_name, strerror(errno));
+#ifndef __rtems__
+ sigsetmask(oldmask);
+#endif
+ return (-1);
+ }
+ lport--;
+ if (fd2p == 0) {
+ write(s, "", 1);
+ lport = 0;
+ } else {
+ char num[8];
+ int s2 = rresvport(&lport), s3;
+ int len = sizeof(from);
+ int nfds;
+
+ if (s2 < 0)
+ goto bad;
+ listen(s2, 1);
+ (void)snprintf(num, sizeof(num), "%d", lport);
+ if (write(s, num, strlen(num)+1) != strlen(num)+1) {
+ (void)fprintf(stderr,
+ "rcmd: write (setting up stderr): %s\n",
+ strerror(errno));
+ (void)close(s2);
+ goto bad;
+ }
+ nfds = max(s, s2)+1;
+ if(nfds > FD_SETSIZE) {
+ fprintf(stderr, "rcmd: too many files\n");
+ (void)close(s2);
+ goto bad;
+ }
+again:
+ FD_ZERO(&reads);
+ FD_SET(s, &reads);
+ FD_SET(s2, &reads);
+ errno = 0;
+ if (select(nfds, &reads, 0, 0, 0) < 1 || !FD_ISSET(s2, &reads)){
+ if (errno != 0)
+ (void)fprintf(stderr,
+ "rcmd: select (setting up stderr): %s\n",
+ strerror(errno));
+ else
+ (void)fprintf(stderr,
+ "select: protocol failure in circuit setup\n");
+ (void)close(s2);
+ goto bad;
+ }
+ s3 = accept(s2, (struct sockaddr *)&from, &len);
+ /*
+ * XXX careful for ftp bounce attacks. If discovered, shut them
+ * down and check for the real auxiliary channel to connect.
+ */
+ if (from.sin_family == AF_INET && from.sin_port == htons(20)) {
+ close(s3);
+ goto again;
+ }
+ (void)close(s2);
+ if (s3 < 0) {
+ (void)fprintf(stderr,
+ "rcmd: accept: %s\n", strerror(errno));
+ lport = 0;
+ goto bad;
+ }
+ *fd2p = s3;
+ from.sin_port = ntohs((u_short)from.sin_port);
+ if (from.sin_family != AF_INET ||
+ from.sin_port >= IPPORT_RESERVED ||
+ from.sin_port < IPPORT_RESERVED / 2) {
+ (void)fprintf(stderr,
+ "socket: protocol failure in circuit setup.\n");
+ goto bad2;
+ }
+ }
+ (void)write(s, locuser, strlen(locuser)+1);
+ (void)write(s, remuser, strlen(remuser)+1);
+ (void)write(s, cmd, strlen(cmd)+1);
+ if (read(s, &c, 1) != 1) {
+ (void)fprintf(stderr,
+ "rcmd: %s: %s\n", *ahost, strerror(errno));
+ goto bad2;
+ }
+ if (c != 0) {
+ while (read(s, &c, 1) == 1) {
+ (void)write(STDERR_FILENO, &c, 1);
+ if (c == '\n')
+ break;
+ }
+ goto bad2;
+ }
+#ifndef __rtems__
+ sigsetmask(oldmask);
+#endif
+ return (s);
+bad2:
+ if (lport)
+ (void)close(*fd2p);
+bad:
+ (void)close(s);
+#ifndef __rtems__
+ sigsetmask(oldmask);
+#endif
+ return (-1);
+}
+
+int
+rresvport(alport)
+ int *alport;
+{
+ struct sockaddr_in sin;
+ int s;
+
+ bzero(&sin, sizeof sin);
+ sin.sin_len = sizeof(struct sockaddr_in);
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = INADDR_ANY;
+ s = socket(AF_INET, SOCK_STREAM, 0);
+ if (s < 0)
+ return (-1);
+#if 0 /* compat_exact_traditional_rresvport_semantics */
+ sin.sin_port = htons((u_short)*alport);
+ if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
+ return (s);
+ if (errno != EADDRINUSE) {
+ (void)close(s);
+ return (-1);
+ }
+#endif
+ sin.sin_port = 0;
+ if (bindresvport(s, &sin) == -1) {
+ (void)close(s);
+ return (-1);
+ }
+ *alport = (int)ntohs(sin.sin_port);
+ return (s);
+}
+
+#ifndef __rtems__
+int __check_rhosts_file = 1;
+char *__rcmd_errstr;
+
+int
+ruserok(rhost, superuser, ruser, luser)
+ const char *rhost, *ruser, *luser;
+ int superuser;
+{
+ struct hostent *hp;
+ u_long addr;
+ char **ap;
+
+ if ((hp = gethostbyname(rhost)) == NULL)
+ return (-1);
+ for (ap = hp->h_addr_list; *ap; ++ap) {
+ bcopy(*ap, &addr, sizeof(addr));
+ if (iruserok(addr, superuser, ruser, luser) == 0)
+ return (0);
+ }
+ return (-1);
+}
+
+/*
+ * New .rhosts strategy: We are passed an ip address. We spin through
+ * hosts.equiv and .rhosts looking for a match. When the .rhosts only
+ * has ip addresses, we don't have to trust a nameserver. When it
+ * contains hostnames, we spin through the list of addresses the nameserver
+ * gives us and look for a match.
+ *
+ * Returns 0 if ok, -1 if not ok.
+ */
+int
+iruserok(raddr, superuser, ruser, luser)
+ u_long raddr;
+ int superuser;
+ const char *ruser, *luser;
+{
+ register char *cp;
+ struct stat sbuf;
+ struct passwd *pwd;
+ FILE *hostf;
+ uid_t uid;
+ int first;
+ char pbuf[MAXPATHLEN];
+
+ first = 1;
+ hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "r");
+again:
+ if (hostf) {
+ if (__ivaliduser(hostf, raddr, luser, ruser) == 0) {
+ (void)fclose(hostf);
+ return (0);
+ }
+ (void)fclose(hostf);
+ }
+ if (first == 1 && (__check_rhosts_file || superuser)) {
+ first = 0;
+ if ((pwd = getpwnam(luser)) == NULL)
+ return (-1);
+ (void)strcpy(pbuf, pwd->pw_dir);
+ (void)strcat(pbuf, "/.rhosts");
+
+ /*
+ * Change effective uid while opening .rhosts. If root and
+ * reading an NFS mounted file system, can't read files that
+ * are protected read/write owner only.
+ */
+ uid = geteuid();
+ (void)seteuid(pwd->pw_uid);
+ hostf = fopen(pbuf, "r");
+ (void)seteuid(uid);
+
+ if (hostf == NULL)
+ return (-1);
+ /*
+ * If not a regular file, or is owned by someone other than
+ * user or root or if writeable by anyone but the owner, quit.
+ */
+ cp = NULL;
+ if (lstat(pbuf, &sbuf) < 0)
+ cp = ".rhosts lstat failed";
+ else if (!S_ISREG(sbuf.st_mode))
+ cp = ".rhosts not regular file";
+ else if (fstat(fileno(hostf), &sbuf) < 0)
+ cp = ".rhosts fstat failed";
+ else if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid)
+ cp = "bad .rhosts owner";
+ else if (sbuf.st_mode & (S_IWGRP|S_IWOTH))
+ cp = ".rhosts writeable by other than owner";
+ /* If there were any problems, quit. */
+ if (cp) {
+ __rcmd_errstr = cp;
+ (void)fclose(hostf);
+ return (-1);
+ }
+ goto again;
+ }
+ return (-1);
+}
+
+/*
+ * XXX
+ * Don't make static, used by lpd(8).
+ *
+ * Returns 0 if ok, -1 if not ok.
+ */
+int
+__ivaliduser(hostf, raddr, luser, ruser)
+ FILE *hostf;
+ u_long raddr;
+ const char *luser, *ruser;
+{
+ register char *user, *p;
+ int ch;
+ char buf[MAXHOSTNAMELEN + 128]; /* host + login */
+ char hname[MAXHOSTNAMELEN];
+ struct hostent *hp;
+ /* Presumed guilty until proven innocent. */
+ int userok = 0, hostok = 0;
+#ifdef YP
+ char *ypdomain;
+
+ if (yp_get_default_domain(&ypdomain))
+ ypdomain = NULL;
+#else
+#define ypdomain NULL
+#endif
+ /* We need to get the damn hostname back for netgroup matching. */
+ if ((hp = gethostbyaddr((char *)&raddr, sizeof(u_long),
+ AF_INET)) == NULL)
+ return (-1);
+ strncpy(hname, hp->h_name, sizeof(hname));
+ hname[sizeof(hname) - 1] = '\0';
+
+ while (fgets(buf, sizeof(buf), hostf)) {
+ p = buf;
+ /* Skip lines that are too long. */
+ if (strchr(p, '\n') == NULL) {
+ while ((ch = getc(hostf)) != '\n' && ch != EOF);
+ continue;
+ }
+ if (*p == '\n' || *p == '#') {
+ /* comment... */
+ continue;
+ }
+ while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') {
+ *p = isupper(*p) ? tolower(*p) : *p;
+ p++;
+ }
+ if (*p == ' ' || *p == '\t') {
+ *p++ = '\0';
+ while (*p == ' ' || *p == '\t')
+ p++;
+ user = p;
+ while (*p != '\n' && *p != ' ' &&
+ *p != '\t' && *p != '\0')
+ p++;
+ } else
+ user = p;
+ *p = '\0';
+ /*
+ * Do +/- and +@/-@ checking. This looks really nasty,
+ * but it matches SunOS's behavior so far as I can tell.
+ */
+ switch(buf[0]) {
+ case '+':
+ if (!buf[1]) { /* '+' matches all hosts */
+ hostok = 1;
+ break;
+ }
+ if (buf[1] == '@') /* match a host by netgroup */
+ hostok = innetgr((char *)&buf[2],
+ (char *)&hname, NULL, ypdomain);
+ else /* match a host by addr */
+ hostok = __icheckhost(raddr,(char *)&buf[1]);
+ break;
+ case '-': /* reject '-' hosts and all their users */
+ if (buf[1] == '@') {
+ if (innetgr((char *)&buf[2],
+ (char *)&hname, NULL, ypdomain))
+ return(-1);
+ } else {
+ if (__icheckhost(raddr,(char *)&buf[1]))
+ return(-1);
+ }
+ break;
+ default: /* if no '+' or '-', do a simple match */
+ hostok = __icheckhost(raddr, buf);
+ break;
+ }
+ switch(*user) {
+ case '+':
+ if (!*(user+1)) { /* '+' matches all users */
+ userok = 1;
+ break;
+ }
+ if (*(user+1) == '@') /* match a user by netgroup */
+ userok = innetgr(user+2, NULL, ruser, ypdomain);
+ else /* match a user by direct specification */
+ userok = !(strcmp(ruser, user+1));
+ break;
+ case '-': /* if we matched a hostname, */
+ if (hostok) { /* check for user field rejections */
+ if (!*(user+1))
+ return(-1);
+ if (*(user+1) == '@') {
+ if (innetgr(user+2, NULL,
+ ruser, ypdomain))
+ return(-1);
+ } else {
+ if (!strcmp(ruser, user+1))
+ return(-1);
+ }
+ }
+ break;
+ default: /* no rejections: try to match the user */
+ if (hostok)
+ userok = !(strcmp(ruser,*user ? user : luser));
+ break;
+ }
+ if (hostok && userok)
+ return(0);
+ }
+ return (-1);
+}
+
+/*
+ * Returns "true" if match, 0 if no match.
+ */
+static int
+__icheckhost(raddr, lhost)
+ u_long raddr;
+ register char *lhost;
+{
+ register struct hostent *hp;
+ register u_long laddr;
+ register char **pp;
+
+ /* Try for raw ip address first. */
+ if (isdigit(*lhost) && (long)(laddr = inet_addr(lhost)) != -1)
+ return (raddr == laddr);
+
+ /* Better be a hostname. */
+ if ((hp = gethostbyname(lhost)) == NULL)
+ return (0);
+
+ /* Spin through ip addresses. */
+ for (pp = hp->h_addr_list; *pp; ++pp)
+ if (!bcmp(&raddr, *pp, sizeof(u_long)))
+ return (1);
+
+ /* No match. */
+ return (0);
+}
+#endif
diff --git a/cpukit/libnetworking/libc/recv.c b/cpukit/libnetworking/libc/recv.c
new file mode 100644
index 0000000000..a842244caf
--- /dev/null
+++ b/cpukit/libnetworking/libc/recv.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)recv.c 8.2 (Berkeley) 2/21/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <stddef.h>
+
+ssize_t
+recv(s, buf, len, flags)
+ int s, flags;
+ size_t len;
+ void *buf;
+{
+ return (recvfrom(s, buf, len, flags, NULL, 0));
+}
diff --git a/cpukit/libnetworking/libc/res_comp.c b/cpukit/libnetworking/libc/res_comp.c
new file mode 100644
index 0000000000..93043276f2
--- /dev/null
+++ b/cpukit/libnetworking/libc/res_comp.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ */
+
+/*
+ * Portions Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_comp.c 8.1 (Berkeley) 6/4/93";
+static char orig_rcsid[] = "From: Id: res_comp.c,v 8.11 1997/05/21 19:31:04 halley Exp $";
+static char rcsid[] = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <ctype.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#define BIND_4_COMPAT
+
+/*
+ * Expand compressed domain name 'comp_dn' to full domain name.
+ * 'msg' is a pointer to the begining of the message,
+ * 'eomorig' points to the first location after the message,
+ * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
+ * Return size of compressed name or -1 if there was an error.
+ */
+int
+dn_expand(const u_char *msg, const u_char *eom, const u_char *src,
+ char *dst, int dstsiz)
+{
+ int n = ns_name_uncompress(msg, eom, src, dst, (size_t)dstsiz);
+
+ if (n > 0 && dst[0] == '.')
+ dst[0] = '\0';
+ return (n);
+}
+
+/*
+ * Pack domain name 'exp_dn' in presentation form into 'comp_dn'.
+ * Return the size of the compressed name or -1.
+ * 'length' is the size of the array pointed to by 'comp_dn'.
+ */
+int
+dn_comp(const char *src, u_char *dst, int dstsiz,
+ u_char **dnptrs, u_char **lastdnptr)
+{
+ return (ns_name_compress(src, dst, (size_t)dstsiz,
+ (const u_char **)dnptrs,
+ (const u_char **)lastdnptr));
+}
+
+/*
+ * Skip over a compressed domain name. Return the size or -1.
+ */
+int
+dn_skipname(const u_char *ptr, const u_char *eom) {
+ const u_char *saveptr = ptr;
+
+ if (ns_name_skip(&ptr, eom) == -1)
+ return (-1);
+ return (ptr - saveptr);
+}
+
+/*
+ * Verify that a domain name uses an acceptable character set.
+ */
+
+/*
+ * Note the conspicuous absence of ctype macros in these definitions. On
+ * non-ASCII hosts, we can't depend on string literals or ctype macros to
+ * tell us anything about network-format data. The rest of the BIND system
+ * is not careful about this, but for some reason, we're doing it right here.
+ */
+#define PERIOD 0x2e
+#define hyphenchar(c) ((c) == 0x2d)
+#define bslashchar(c) ((c) == 0x5c)
+#define periodchar(c) ((c) == PERIOD)
+#define asterchar(c) ((c) == 0x2a)
+#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \
+ || ((c) >= 0x61 && (c) <= 0x7a))
+#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
+
+#define borderchar(c) (alphachar(c) || digitchar(c))
+#define middlechar(c) (borderchar(c) || hyphenchar(c))
+#define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
+
+int
+res_hnok(dn)
+ const char *dn;
+{
+ int ppch = '\0', pch = PERIOD, ch = *dn++;
+
+ while (ch != '\0') {
+ int nch = *dn++;
+
+ if (periodchar(ch)) {
+ (void)NULL;
+ } else if (periodchar(pch)) {
+ if (!borderchar(ch))
+ return (0);
+ } else if (periodchar(nch) || nch == '\0') {
+ if (!borderchar(ch))
+ return (0);
+ } else {
+ if (!middlechar(ch))
+ return (0);
+ }
+ ppch = pch, pch = ch, ch = nch;
+ }
+ return (1);
+}
+
+/*
+ * hostname-like (A, MX, WKS) owners can have "*" as their first label
+ * but must otherwise be as a host name.
+ */
+int
+res_ownok(dn)
+ const char *dn;
+{
+ if (asterchar(dn[0])) {
+ if (periodchar(dn[1]))
+ return (res_hnok(dn+2));
+ if (dn[1] == '\0')
+ return (1);
+ }
+ return (res_hnok(dn));
+}
+
+/*
+ * SOA RNAMEs and RP RNAMEs can have any printable character in their first
+ * label, but the rest of the name has to look like a host name.
+ */
+int
+res_mailok(dn)
+ const char *dn;
+{
+ int ch, escaped = 0;
+
+ /* "." is a valid missing representation */
+ if (*dn == '\0')
+ return (1);
+
+ /* otherwise <label>.<hostname> */
+ while ((ch = *dn++) != '\0') {
+ if (!domainchar(ch))
+ return (0);
+ if (!escaped && periodchar(ch))
+ break;
+ if (escaped)
+ escaped = 0;
+ else if (bslashchar(ch))
+ escaped = 1;
+ }
+ if (periodchar(ch))
+ return (res_hnok(dn));
+ return (0);
+}
+
+/*
+ * This function is quite liberal, since RFC 1034's character sets are only
+ * recommendations.
+ */
+int
+res_dnok(dn)
+ const char *dn;
+{
+ int ch;
+
+ while ((ch = *dn++) != '\0')
+ if (!domainchar(ch))
+ return (0);
+ return (1);
+}
+
+#ifdef BIND_4_COMPAT
+/*
+ * This module must export the following externally-visible symbols:
+ * ___putlong
+ * ___putshort
+ * __getlong
+ * __getshort
+ * Note that one _ comes from C and the others come from us.
+ */
+void __putlong(u_int32_t src, u_char *dst) { ns_put32(src, dst); }
+void __putshort(u_int16_t src, u_char *dst) { ns_put16(src, dst); }
+u_int32_t _getlong(const u_char *src) { return (ns_get32(src)); }
+u_int16_t _getshort(const u_char *src) { return (ns_get16(src)); }
+#endif /*BIND_4_COMPAT*/
diff --git a/cpukit/libnetworking/libc/res_config.h b/cpukit/libnetworking/libc/res_config.h
new file mode 100644
index 0000000000..fbd1d694f7
--- /dev/null
+++ b/cpukit/libnetworking/libc/res_config.h
@@ -0,0 +1,20 @@
+/*
+ * $Id$
+ */
+
+#define DEBUG 1 /* enable debugging code (needed for dig) */
+#define RESOLVSORT /* allow sorting of addresses in gethostbyname */
+#define RFC1535 /* comply with RFC1535 (STRONGLY reccomended by vixie)*/
+#undef USELOOPBACK /* res_init() bind to localhost */
+#undef SUNSECURITY /* verify gethostbyaddr() calls - WE DONT NEED IT */
+#define MULTI_PTRS_ARE_ALIASES 1 /* fold multiple PTR records into aliases */
+#define CHECK_SRVR_ADDR 1 /* confirm that the server requested sent the reply */
+#define BIND_UPDATE 1 /* update support */
+
+#if defined(__rtems__)
+u_int16_t _getshort(const u_char *src);
+u_int32_t _getlong(const u_char *src);
+int gethostname (char *name, size_t namelen);
+int sethostname (char *name, size_t namelen);
+int issetugid (void);
+#endif
diff --git a/cpukit/libnetworking/libc/res_data.c b/cpukit/libnetworking/libc/res_data.c
new file mode 100644
index 0000000000..fb7d2c66eb
--- /dev/null
+++ b/cpukit/libnetworking/libc/res_data.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1995,1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char rcsid[] = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <ctype.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "res_config.h"
+
+const char *_res_opcodes[] = {
+ "QUERY",
+ "IQUERY",
+ "CQUERYM",
+ "CQUERYU", /* experimental */
+ "NOTIFY", /* experimental */
+ "UPDATE",
+ "6",
+ "7",
+ "8",
+ "9",
+ "10",
+ "11",
+ "12",
+ "13",
+ "ZONEINIT",
+ "ZONEREF",
+};
+
+const char *_res_resultcodes[] = {
+ "NOERROR",
+ "FORMERR",
+ "SERVFAIL",
+ "NXDOMAIN",
+ "NOTIMP",
+ "REFUSED",
+ "YXDOMAIN",
+ "YXRRSET",
+ "NXRRSET",
+ "NOTAUTH",
+ "ZONEERR",
+ "11",
+ "12",
+ "13",
+ "14",
+ "NOCHANGE",
+};
+
+#ifdef BIND_UPDATE
+const char *_res_sectioncodes[] = {
+ "ZONE",
+ "PREREQUISITES",
+ "UPDATE",
+ "ADDITIONAL",
+};
+#endif
diff --git a/cpukit/libnetworking/libc/res_debug.c b/cpukit/libnetworking/libc/res_debug.c
new file mode 100644
index 0000000000..b747b6e6d2
--- /dev/null
+++ b/cpukit/libnetworking/libc/res_debug.c
@@ -0,0 +1,966 @@
+/*
+ * Copyright (c) 1985
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ */
+
+/*
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software. No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+/*
+ * Portions Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93";
+static char rcsid[] = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <math.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#define SPRINTF(x) sprintf x
+
+extern const char *_res_opcodes[];
+extern const char *_res_resultcodes[];
+extern const char *_res_sectioncodes[];
+
+/*
+ * Print the current options.
+ */
+void
+fp_resstat(struct __res_state *statp, FILE *file) {
+ u_long mask;
+
+ fprintf(file, ";; res options:");
+ if (!statp)
+ statp = &_res;
+ for (mask = 1; mask != 0; mask <<= 1)
+ if (statp->options & mask)
+ fprintf(file, " %s", p_option(mask));
+ putc('\n', file);
+}
+
+static void
+do_section(ns_msg *handle, ns_sect section, int pflag, FILE *file) {
+ int n, sflag, rrnum;
+ char buf[2048]; /* XXX need to malloc */
+ ns_opcode opcode;
+ ns_rr rr;
+
+ /*
+ * Print answer records.
+ */
+ sflag = (_res.pfcode & pflag);
+ if (_res.pfcode && !sflag)
+ return;
+
+ opcode = ns_msg_getflag(*handle, ns_f_opcode);
+ rrnum = 0;
+ for (;;) {
+ if (ns_parserr(handle, section, rrnum, &rr)) {
+ if (errno != ENODEV)
+ fprintf(file, ";; ns_parserr: %s\n",
+ strerror(errno));
+ else if (rrnum > 0 && sflag != 0 &&
+ (_res.pfcode & RES_PRF_HEAD1))
+ putc('\n', file);
+ return;
+ }
+ if (rrnum == 0 && sflag != 0 && (_res.pfcode & RES_PRF_HEAD1))
+ fprintf(file, ";; %s SECTION:\n",
+ p_section(section, opcode));
+ if (section == ns_s_qd)
+ fprintf(file, ";;\t%s, type = %s, class = %s\n",
+ ns_rr_name(rr),
+ p_type(ns_rr_type(rr)),
+ p_class(ns_rr_class(rr)));
+ else {
+ n = ns_sprintrr(handle, &rr, NULL, NULL,
+ buf, sizeof buf);
+ if (n < 0) {
+ fprintf(file, ";; ns_sprintrr: %s\n",
+ strerror(errno));
+ return;
+ }
+ fputs(buf, file);
+ fputc('\n', file);
+ }
+ rrnum++;
+ }
+}
+
+void
+p_query(const u_char *msg) {
+ fp_query(msg, stdout);
+}
+
+void
+fp_query(const u_char *msg, FILE *file) {
+ fp_nquery(msg, PACKETSZ, file);
+}
+
+/*
+ * Print the contents of a query.
+ * This is intended to be primarily a debugging routine.
+ */
+void
+fp_nquery(const u_char *msg, int len, FILE *file) {
+ ns_msg handle;
+ int qdcount, ancount, nscount, arcount;
+ u_int opcode, rcode, id;
+
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+ return;
+
+ if (ns_initparse(msg, len, &handle) < 0) {
+ fprintf(file, ";; ns_initparse: %s\n", strerror(errno));
+ return;
+ }
+ opcode = ns_msg_getflag(handle, ns_f_opcode);
+ rcode = ns_msg_getflag(handle, ns_f_rcode);
+ id = ns_msg_id(handle);
+ qdcount = ns_msg_count(handle, ns_s_qd);
+ ancount = ns_msg_count(handle, ns_s_an);
+ nscount = ns_msg_count(handle, ns_s_ns);
+ arcount = ns_msg_count(handle, ns_s_ar);
+
+ /*
+ * Print header fields.
+ */
+ if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || rcode)
+ fprintf(file,
+ ";; ->>HEADER<<- opcode: %s, status: %s, id: %d\n",
+ _res_opcodes[opcode], _res_resultcodes[rcode], id);
+ if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX))
+ putc(';', file);
+ if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) {
+ fprintf(file, "; flags:");
+ if (ns_msg_getflag(handle, ns_f_qr))
+ fprintf(file, " qr");
+ if (ns_msg_getflag(handle, ns_f_aa))
+ fprintf(file, " aa");
+ if (ns_msg_getflag(handle, ns_f_tc))
+ fprintf(file, " tc");
+ if (ns_msg_getflag(handle, ns_f_rd))
+ fprintf(file, " rd");
+ if (ns_msg_getflag(handle, ns_f_ra))
+ fprintf(file, " ra");
+ if (ns_msg_getflag(handle, ns_f_z))
+ fprintf(file, " ??");
+ if (ns_msg_getflag(handle, ns_f_ad))
+ fprintf(file, " ad");
+ if (ns_msg_getflag(handle, ns_f_cd))
+ fprintf(file, " cd");
+ }
+ if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) {
+ fprintf(file, "; %s: %d",
+ p_section(ns_s_qd, opcode), qdcount);
+ fprintf(file, ", %s: %d",
+ p_section(ns_s_an, opcode), ancount);
+ fprintf(file, ", %s: %d",
+ p_section(ns_s_ns, opcode), nscount);
+ fprintf(file, ", %s: %d",
+ p_section(ns_s_ar, opcode), arcount);
+ }
+ if ((!_res.pfcode) || (_res.pfcode &
+ (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
+ putc('\n',file);
+ }
+ /*
+ * Print the various sections.
+ */
+ do_section(&handle, ns_s_qd, RES_PRF_QUES, file);
+ do_section(&handle, ns_s_an, RES_PRF_ANS, file);
+ do_section(&handle, ns_s_ns, RES_PRF_AUTH, file);
+ do_section(&handle, ns_s_ar, RES_PRF_ADD, file);
+ if (qdcount == 0 && ancount == 0 &&
+ nscount == 0 && arcount == 0)
+ putc('\n', file);
+}
+
+const u_char *
+p_cdnname(const u_char *cp, const u_char *msg, int len, FILE *file) {
+ char name[MAXDNAME];
+ int n;
+
+ if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0)
+ return (NULL);
+ if (name[0] == '\0')
+ putc('.', file);
+ else
+ fputs(name, file);
+ return (cp + n);
+}
+
+const u_char *
+p_cdname(const u_char *cp, const u_char *msg, FILE *file) {
+ return (p_cdnname(cp, msg, PACKETSZ, file));
+}
+
+/* Return a fully-qualified domain name from a compressed name (with
+ length supplied). */
+
+const u_char *
+p_fqnname(cp, msg, msglen, name, namelen)
+ const u_char *cp, *msg;
+ int msglen;
+ char *name;
+ int namelen;
+{
+ int n, newlen;
+
+ if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0)
+ return (NULL);
+ newlen = strlen(name);
+ if (newlen == 0 || name[newlen - 1] != '.') {
+ if (newlen + 1 >= namelen) /* Lack space for final dot */
+ return (NULL);
+ else
+ strcpy(name + newlen, ".");
+ }
+ return (cp + n);
+}
+
+/* XXX: the rest of these functions need to become length-limited, too. */
+
+const u_char *
+p_fqname(const u_char *cp, const u_char *msg, FILE *file) {
+ char name[MAXDNAME];
+ const u_char *n;
+
+ n = p_fqnname(cp, msg, MAXCDNAME, name, sizeof name);
+ if (n == NULL)
+ return (NULL);
+ fputs(name, file);
+ return (n);
+}
+
+/*
+ * Names of RR classes and qclasses. Classes and qclasses are the same, except
+ * that C_ANY is a qclass but not a class. (You can ask for records of class
+ * C_ANY, but you can't have any records of that class in the database.)
+ */
+const struct res_sym __p_class_syms[] = {
+ {C_IN, "IN"},
+ {C_CHAOS, "CHAOS"},
+ {C_HS, "HS"},
+ {C_HS, "HESIOD"},
+ {C_ANY, "ANY"},
+ {C_NONE, "NONE"},
+ {C_IN, (char *)0}
+};
+
+/*
+ * Names of message sections.
+ */
+const struct res_sym __p_default_section_syms[] = {
+ {ns_s_qd, "QUERY"},
+ {ns_s_an, "ANSWER"},
+ {ns_s_ns, "AUTHORITY"},
+ {ns_s_ar, "ADDITIONAL"},
+ {0, (char *)0}
+};
+
+const struct res_sym __p_update_section_syms[] = {
+ {S_ZONE, "ZONE"},
+ {S_PREREQ, "PREREQUISITE"},
+ {S_UPDATE, "UPDATE"},
+ {S_ADDT, "ADDITIONAL"},
+ {0, (char *)0}
+};
+
+/*
+ * Names of RR types and qtypes. Types and qtypes are the same, except
+ * that T_ANY is a qtype but not a type. (You can ask for records of type
+ * T_ANY, but you can't have any records of that type in the database.)
+ */
+const struct res_sym __p_type_syms[] = {
+ {T_A, "A", "address"},
+ {T_NS, "NS", "name server"},
+ {T_MD, "MD", "mail destination (deprecated)"},
+ {T_MF, "MF", "mail forwarder (deprecated)"},
+ {T_CNAME, "CNAME", "canonical name"},
+ {T_SOA, "SOA", "start of authority"},
+ {T_MB, "MB", "mailbox"},
+ {T_MG, "MG", "mail group member"},
+ {T_MR, "MR", "mail rename"},
+ {T_NULL, "NULL", "null"},
+ {T_WKS, "WKS", "well-known service (deprecated)"},
+ {T_PTR, "PTR", "domain name pointer"},
+ {T_HINFO, "HINFO", "host information"},
+ {T_MINFO, "MINFO", "mailbox information"},
+ {T_MX, "MX", "mail exchanger"},
+ {T_TXT, "TXT", "text"},
+ {T_RP, "RP", "responsible person"},
+ {T_AFSDB, "AFSDB", "DCE or AFS server"},
+ {T_X25, "X25", "X25 address"},
+ {T_ISDN, "ISDN", "ISDN address"},
+ {T_RT, "RT", "router"},
+ {T_NSAP, "NSAP", "nsap address"},
+ {T_NSAP_PTR, "NSAP_PTR", "domain name pointer"},
+ {T_SIG, "SIG", "signature"},
+ {T_KEY, "KEY", "key"},
+ {T_PX, "PX", "mapping information"},
+ {T_GPOS, "GPOS", "geographical position (withdrawn)"},
+ {T_AAAA, "AAAA", "IPv6 address"},
+ {T_LOC, "LOC", "location"},
+ {T_NXT, "NXT", "next valid name (unimplemented)"},
+ {T_EID, "EID", "endpoint identifier (unimplemented)"},
+ {T_NIMLOC, "NIMLOC", "NIMROD locator (unimplemented)"},
+ {T_SRV, "SRV", "server selection"},
+ {T_ATMA, "ATMA", "ATM address (unimplemented)"},
+ {T_IXFR, "IXFR", "incremental zone transfer"},
+ {T_AXFR, "AXFR", "zone transfer"},
+ {T_MAILB, "MAILB", "mailbox-related data (deprecated)"},
+ {T_MAILA, "MAILA", "mail agent (deprecated)"},
+ {T_NAPTR, "NAPTR", "URN Naming Authority"},
+ {T_ANY, "ANY", "\"any\""},
+ {0, NULL, NULL}
+};
+
+int
+sym_ston(const struct res_sym *syms, const char *name, int *success) {
+ for ((void)NULL; syms->name != 0; syms++) {
+ if (strcasecmp (name, syms->name) == 0) {
+ if (success)
+ *success = 1;
+ return (syms->number);
+ }
+ }
+ if (success)
+ *success = 0;
+ return (syms->number); /* The default value. */
+}
+
+const char *
+sym_ntos(const struct res_sym *syms, int number, int *success) {
+ static char unname[20];
+
+ for ((void)NULL; syms->name != 0; syms++) {
+ if (number == syms->number) {
+ if (success)
+ *success = 1;
+ return (syms->name);
+ }
+ }
+
+ sprintf(unname, "%d", number);
+ if (success)
+ *success = 0;
+ return (unname);
+}
+
+const char *
+sym_ntop(const struct res_sym *syms, int number, int *success) {
+ static char unname[20];
+
+ for ((void)NULL; syms->name != 0; syms++) {
+ if (number == syms->number) {
+ if (success)
+ *success = 1;
+ return (syms->humanname);
+ }
+ }
+ sprintf(unname, "%d", number);
+ if (success)
+ *success = 0;
+ return (unname);
+}
+
+/*
+ * Return a string for the type.
+ */
+const char *
+p_type(int type) {
+ return (sym_ntos(__p_type_syms, type, (int *)0));
+}
+
+/*
+ * Return a string for the type.
+ */
+const char *
+p_section(int section, int opcode) {
+ const struct res_sym *symbols;
+
+ switch (opcode) {
+ case ns_o_update:
+ symbols = __p_update_section_syms;
+ break;
+ default:
+ symbols = __p_default_section_syms;
+ break;
+ }
+ return (sym_ntos(symbols, section, (int *)0));
+}
+
+/*
+ * Return a mnemonic for class.
+ */
+const char *
+p_class(int class) {
+ return (sym_ntos(__p_class_syms, class, (int *)0));
+}
+
+/*
+ * Return a mnemonic for an option
+ */
+const char *
+p_option(u_long option) {
+ static char nbuf[40];
+
+ switch (option) {
+ case RES_INIT: return "init";
+ case RES_DEBUG: return "debug";
+ case RES_AAONLY: return "aaonly(unimpl)";
+ case RES_USEVC: return "usevc";
+ case RES_PRIMARY: return "primry(unimpl)";
+ case RES_IGNTC: return "igntc";
+ case RES_RECURSE: return "recurs";
+ case RES_DEFNAMES: return "defnam";
+ case RES_STAYOPEN: return "styopn";
+ case RES_DNSRCH: return "dnsrch";
+ case RES_INSECURE1: return "insecure1";
+ case RES_INSECURE2: return "insecure2";
+ default: sprintf(nbuf, "?0x%lx?", (u_long)option);
+ return (nbuf);
+ }
+}
+
+/*
+ * Return a mnemonic for a time to live.
+ */
+const char *
+p_time(u_int32_t value) {
+ static char nbuf[40];
+
+ if (ns_format_ttl(value, nbuf, sizeof nbuf) < 0)
+ sprintf(nbuf, "%u", value);
+ return (nbuf);
+}
+
+
+/*
+ * routines to convert between on-the-wire RR format and zone file format.
+ * Does not contain conversion to/from decimal degrees; divide or multiply
+ * by 60*60*1000 for that.
+ */
+
+static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
+ 1000000,10000000,100000000,1000000000};
+
+/* takes an XeY precision/size value, returns a string representation. */
+static const char *
+precsize_ntoa(prec)
+ u_int8_t prec;
+{
+ static char retbuf[sizeof "90000000.00"];
+ unsigned long val;
+ int mantissa, exponent;
+
+ mantissa = (int)((prec >> 4) & 0x0f) % 10;
+ exponent = (int)((prec >> 0) & 0x0f) % 10;
+
+ val = mantissa * poweroften[exponent];
+
+ (void) sprintf(retbuf, "%ld.%.2ld", val/100, val%100);
+ return (retbuf);
+}
+
+/* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */
+static u_int8_t
+precsize_aton(strptr)
+ char **strptr;
+{
+ unsigned int mval = 0, cmval = 0;
+ u_int8_t retval = 0;
+ char *cp;
+ int exponent;
+ int mantissa;
+
+ cp = *strptr;
+
+ while (isdigit((int)*cp))
+ mval = mval * 10 + (*cp++ - '0');
+
+ if (*cp == '.') { /* centimeters */
+ cp++;
+ if (isdigit((int)*cp)) {
+ cmval = (*cp++ - '0') * 10;
+ if (isdigit((int)*cp)) {
+ cmval += (*cp++ - '0');
+ }
+ }
+ }
+ cmval = (mval * 100) + cmval;
+
+ for (exponent = 0; exponent < 9; exponent++)
+ if (cmval < poweroften[exponent+1])
+ break;
+
+ mantissa = cmval / poweroften[exponent];
+ if (mantissa > 9)
+ mantissa = 9;
+
+ retval = (mantissa << 4) | exponent;
+
+ *strptr = cp;
+
+ return (retval);
+}
+
+/* converts ascii lat/lon to unsigned encoded 32-bit number. moves pointer. */
+static u_int32_t
+latlon2ul(latlonstrptr,which)
+ char **latlonstrptr;
+ int *which;
+{
+ char *cp;
+ u_int32_t retval;
+ int deg = 0, min = 0, secs = 0, secsfrac = 0;
+
+ cp = *latlonstrptr;
+
+ while (isdigit((int)*cp))
+ deg = deg * 10 + (*cp++ - '0');
+
+ while (isspace((int)*cp))
+ cp++;
+
+ if (!(isdigit((int)*cp)))
+ goto fndhemi;
+
+ while (isdigit((int)*cp))
+ min = min * 10 + (*cp++ - '0');
+
+ while (isspace((int)*cp))
+ cp++;
+
+ if (!(isdigit((int)*cp)))
+ goto fndhemi;
+
+ while (isdigit((int)*cp))
+ secs = secs * 10 + (*cp++ - '0');
+
+ if (*cp == '.') { /* decimal seconds */
+ cp++;
+ if (isdigit((int)*cp)) {
+ secsfrac = (*cp++ - '0') * 100;
+ if (isdigit((int)*cp)) {
+ secsfrac += (*cp++ - '0') * 10;
+ if (isdigit((int)*cp)) {
+ secsfrac += (*cp++ - '0');
+ }
+ }
+ }
+ }
+
+ while (!isspace((int)*cp)) /* if any trailing garbage */
+ cp++;
+
+ while (isspace((int)*cp))
+ cp++;
+
+ fndhemi:
+ switch (*cp) {
+ case 'N': case 'n':
+ case 'E': case 'e':
+ retval = ((unsigned)1<<31)
+ + (((((deg * 60) + min) * 60) + secs) * 1000)
+ + secsfrac;
+ break;
+ case 'S': case 's':
+ case 'W': case 'w':
+ retval = ((unsigned)1<<31)
+ - (((((deg * 60) + min) * 60) + secs) * 1000)
+ - secsfrac;
+ break;
+ default:
+ retval = 0; /* invalid value -- indicates error */
+ break;
+ }
+
+ switch (*cp) {
+ case 'N': case 'n':
+ case 'S': case 's':
+ *which = 1; /* latitude */
+ break;
+ case 'E': case 'e':
+ case 'W': case 'w':
+ *which = 2; /* longitude */
+ break;
+ default:
+ *which = 0; /* error */
+ break;
+ }
+
+ cp++; /* skip the hemisphere */
+
+ while (!isspace((int)*cp)) /* if any trailing garbage */
+ cp++;
+
+ while (isspace((int)*cp)) /* move to next field */
+ cp++;
+
+ *latlonstrptr = cp;
+
+ return (retval);
+}
+
+/* converts a zone file representation in a string to an RDATA on-the-wire
+ * representation. */
+int
+loc_aton(ascii, binary)
+ const char *ascii;
+ u_char *binary;
+{
+ const char *cp, *maxcp;
+ u_char *bcp;
+
+ u_int32_t latit = 0, longit = 0, alt = 0;
+ u_int32_t lltemp1 = 0, lltemp2 = 0;
+ int altmeters = 0, altfrac = 0, altsign = 1;
+ u_int8_t hp = 0x16; /* default = 1e6 cm = 10000.00m = 10km */
+ u_int8_t vp = 0x13; /* default = 1e3 cm = 10.00m */
+ u_int8_t siz = 0x12; /* default = 1e2 cm = 1.00m */
+ int which1 = 0, which2 = 0;
+
+ cp = ascii;
+ maxcp = cp + strlen(ascii);
+
+ lltemp1 = latlon2ul(&cp, &which1);
+
+ lltemp2 = latlon2ul(&cp, &which2);
+
+ switch (which1 + which2) {
+ case 3: /* 1 + 2, the only valid combination */
+ if ((which1 == 1) && (which2 == 2)) { /* normal case */
+ latit = lltemp1;
+ longit = lltemp2;
+ } else if ((which1 == 2) && (which2 == 1)) { /* reversed */
+ longit = lltemp1;
+ latit = lltemp2;
+ } else { /* some kind of brokenness */
+ return (0);
+ }
+ break;
+ default: /* we didn't get one of each */
+ return (0);
+ }
+
+ /* altitude */
+ if (*cp == '-') {
+ altsign = -1;
+ cp++;
+ }
+
+ if (*cp == '+')
+ cp++;
+
+ while (isdigit((int)*cp))
+ altmeters = altmeters * 10 + (*cp++ - '0');
+
+ if (*cp == '.') { /* decimal meters */
+ cp++;
+ if (isdigit((int)*cp)) {
+ altfrac = (*cp++ - '0') * 10;
+ if (isdigit((int)*cp)) {
+ altfrac += (*cp++ - '0');
+ }
+ }
+ }
+
+ alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
+
+ while (!isspace((int)*cp) && (cp < maxcp)) /* if trailing garbage or m */
+ cp++;
+
+ while (isspace((int)*cp) && (cp < maxcp))
+ cp++;
+
+ if (cp >= maxcp)
+ goto defaults;
+
+ siz = precsize_aton(&cp);
+
+ while (!isspace((int)*cp) && (cp < maxcp)) /* if trailing garbage or m */
+ cp++;
+
+ while (isspace((int)*cp) && (cp < maxcp))
+ cp++;
+
+ if (cp >= maxcp)
+ goto defaults;
+
+ hp = precsize_aton(&cp);
+
+ while (!isspace((int)*cp) && (cp < maxcp)) /* if trailing garbage or m */
+ cp++;
+
+ while (isspace((int)*cp) && (cp < maxcp))
+ cp++;
+
+ if (cp >= maxcp)
+ goto defaults;
+
+ vp = precsize_aton(&cp);
+
+ defaults:
+
+ bcp = binary;
+ *bcp++ = (u_int8_t) 0; /* version byte */
+ *bcp++ = siz;
+ *bcp++ = hp;
+ *bcp++ = vp;
+ PUTLONG(latit,bcp);
+ PUTLONG(longit,bcp);
+ PUTLONG(alt,bcp);
+
+ return (16); /* size of RR in octets */
+}
+
+/* takes an on-the-wire LOC RR and formats it in a human readable format. */
+const char *
+loc_ntoa(binary, ascii)
+ const u_char *binary;
+ char *ascii;
+{
+ static char *error = "?";
+ const u_char *cp = binary;
+
+ int latdeg, latmin, latsec, latsecfrac;
+ int longdeg, longmin, longsec, longsecfrac;
+ char northsouth, eastwest;
+ int altmeters, altfrac, altsign;
+
+ const u_int32_t referencealt = 100000 * 100;
+
+ int32_t latval, longval, altval;
+ u_int32_t templ;
+ u_int8_t sizeval, hpval, vpval, versionval;
+
+ char *sizestr, *hpstr, *vpstr;
+
+ versionval = *cp++;
+
+ if (versionval) {
+ (void) sprintf(ascii, "; error: unknown LOC RR version");
+ return (ascii);
+ }
+
+ sizeval = *cp++;
+
+ hpval = *cp++;
+ vpval = *cp++;
+
+ GETLONG(templ, cp);
+ latval = (templ - ((unsigned)1<<31));
+
+ GETLONG(templ, cp);
+ longval = (templ - ((unsigned)1<<31));
+
+ GETLONG(templ, cp);
+ if (templ < referencealt) { /* below WGS 84 spheroid */
+ altval = referencealt - templ;
+ altsign = -1;
+ } else {
+ altval = templ - referencealt;
+ altsign = 1;
+ }
+
+ if (latval < 0) {
+ northsouth = 'S';
+ latval = -latval;
+ } else
+ northsouth = 'N';
+
+ latsecfrac = latval % 1000;
+ latval = latval / 1000;
+ latsec = latval % 60;
+ latval = latval / 60;
+ latmin = latval % 60;
+ latval = latval / 60;
+ latdeg = latval;
+
+ if (longval < 0) {
+ eastwest = 'W';
+ longval = -longval;
+ } else
+ eastwest = 'E';
+
+ longsecfrac = longval % 1000;
+ longval = longval / 1000;
+ longsec = longval % 60;
+ longval = longval / 60;
+ longmin = longval % 60;
+ longval = longval / 60;
+ longdeg = longval;
+
+ altfrac = altval % 100;
+ altmeters = (altval / 100) * altsign;
+
+ if ((sizestr = strdup(precsize_ntoa(sizeval))) == NULL)
+ sizestr = error;
+ if ((hpstr = strdup(precsize_ntoa(hpval))) == NULL)
+ hpstr = error;
+ if ((vpstr = strdup(precsize_ntoa(vpval))) == NULL)
+ vpstr = error;
+
+ sprintf(ascii,
+ "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm",
+ latdeg, latmin, latsec, latsecfrac, northsouth,
+ longdeg, longmin, longsec, longsecfrac, eastwest,
+ altmeters, altfrac, sizestr, hpstr, vpstr);
+
+ if (sizestr != error)
+ free(sizestr);
+ if (hpstr != error)
+ free(hpstr);
+ if (vpstr != error)
+ free(vpstr);
+
+ return (ascii);
+}
+
+
+/* Return the number of DNS hierarchy levels in the name. */
+int
+dn_count_labels(const char *name) {
+ int i, len, count;
+
+ len = strlen(name);
+ for (i = 0, count = 0; i < len; i++) {
+ /* XXX need to check for \. or use named's nlabels(). */
+ if (name[i] == '.')
+ count++;
+ }
+
+ /* don't count initial wildcard */
+ if (name[0] == '*')
+ if (count)
+ count--;
+
+ /* don't count the null label for root. */
+ /* if terminating '.' not found, must adjust */
+ /* count to include last label */
+ if (len > 0 && name[len-1] != '.')
+ count++;
+ return (count);
+}
+
+
+/*
+ * Make dates expressed in seconds-since-Jan-1-1970 easy to read.
+ * SIG records are required to be printed like this, by the Secure DNS RFC.
+ */
+char *
+p_secstodate (u_long secs) {
+ static char output[15]; /* YYYYMMDDHHMMSS and null */
+ time_t clock = secs;
+ struct tm *time;
+
+ time = gmtime(&clock);
+ time->tm_year += 1900;
+ time->tm_mon += 1;
+ sprintf(output, "%04d%02d%02d%02d%02d%02d",
+ time->tm_year, time->tm_mon, time->tm_mday,
+ time->tm_hour, time->tm_min, time->tm_sec);
+ return (output);
+}
diff --git a/cpukit/libnetworking/libc/res_init.c b/cpukit/libnetworking/libc/res_init.c
new file mode 100644
index 0000000000..b762a8ec0c
--- /dev/null
+++ b/cpukit/libnetworking/libc/res_init.c
@@ -0,0 +1,501 @@
+/*
+ * Copyright (c) 1985, 1989, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ */
+
+/*
+ * Portions Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93";
+static char orig_rcsid[] = "From: Id: res_init.c,v 8.7 1996/11/18 09:10:04 vixie Exp $";
+static char rcsid[] = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <ctype.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "res_config.h"
+
+/*
+ * RTEMS -- set up name servers from global variable
+ */
+#include <rtems/rtems_bsdnet_internal.h>
+
+static void res_setoptions __P((char *, char *));
+
+#ifdef RESOLVSORT
+static const char sort_mask[] = "/&";
+#define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL)
+static u_int32_t net_mask __P((struct in_addr));
+#endif
+
+#if !defined(isascii) /* XXX - could be a function */
+# define isascii(c) (!(c & 0200))
+#endif
+
+/*
+ * Resolver state default settings.
+ */
+
+struct __res_state _res
+# if defined(__BIND_RES_TEXT)
+ = { RES_TIMEOUT, } /* Motorola, et al. */
+# endif
+ ;
+
+
+/*
+ * Set up default settings. If the configuration file exist, the values
+ * there will have precedence. Otherwise, the server address is set to
+ * INADDR_ANY and the default domain name comes from the gethostname().
+ *
+ * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1
+ * rather than INADDR_ANY ("0.0.0.0") as the default name server address
+ * since it was noted that INADDR_ANY actually meant ``the first interface
+ * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface,
+ * it had to be "up" in order for you to reach your own name server. It
+ * was later decided that since the recommended practice is to always
+ * install local static routes through 127.0.0.1 for all your network
+ * interfaces, that we could solve this problem without a code change.
+ *
+ * The configuration file should always be used, since it is the only way
+ * to specify a default domain. If you are running a server on your local
+ * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1"
+ * in the configuration file.
+ *
+ * Return 0 if completes successfully, -1 on error
+ */
+int
+res_init()
+{
+ register FILE *fp;
+ register char *cp, **pp;
+ register int n;
+ char buf[MAXDNAME];
+ int nserv = 0; /* number of nameserver records read from file */
+ int haveenv = 0;
+ int havesearch = 0;
+#ifdef RESOLVSORT
+ int nsort = 0;
+ char *net;
+#endif
+#ifndef RFC1535
+ int dots;
+#endif
+
+ /*
+ * These three fields used to be statically initialized. This made
+ * it hard to use this code in a shared library. It is necessary,
+ * now that we're doing dynamic initialization here, that we preserve
+ * the old semantics: if an application modifies one of these three
+ * fields of _res before res_init() is called, res_init() will not
+ * alter them. Of course, if an application is setting them to
+ * _zero_ before calling res_init(), hoping to override what used
+ * to be the static default, we can't detect it and unexpected results
+ * will follow. Zero for any of these fields would make no sense,
+ * so one can safely assume that the applications were already getting
+ * unexpected results.
+ *
+ * _res.options is tricky since some apps were known to diddle the bits
+ * before res_init() was first called. We can't replicate that semantic
+ * with dynamic initialization (they may have turned bits off that are
+ * set in RES_DEFAULT). Our solution is to declare such applications
+ * "broken". They could fool us by setting RES_INIT but none do (yet).
+ */
+ if (!_res.retrans)
+ _res.retrans = RES_TIMEOUT;
+ if (!_res.retry)
+ _res.retry = 4;
+ if (!(_res.options & RES_INIT))
+ _res.options = RES_DEFAULT;
+
+ /*
+ * This one used to initialize implicitly to zero, so unless the app
+ * has set it to something in particular, we can randomize it now.
+ */
+ if (!_res.id)
+ _res.id = res_randomid();
+
+#ifdef USELOOPBACK
+ _res.nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
+#else
+ _res.nsaddr.sin_addr.s_addr = INADDR_ANY;
+#endif
+ _res.nsaddr.sin_family = AF_INET;
+ _res.nsaddr.sin_port = htons(NAMESERVER_PORT);
+ _res.nscount = 1;
+ _res.ndots = 1;
+ _res.pfcode = 0;
+
+ /*
+ * RTEMS -- Set up name servers
+ */
+ {
+ int n = 0;
+ while ((n < rtems_bsdnet_nameserver_count) && (nserv < MAXNS)) {
+ _res.nsaddr_list[nserv].sin_addr = rtems_bsdnet_nameserver[n];
+ _res.nsaddr_list[nserv].sin_family = AF_INET;
+ _res.nsaddr_list[nserv].sin_port = htons(NAMESERVER_PORT);
+ nserv++;
+ n++;
+ }
+ if (rtems_bsdnet_domain_name)
+ (void)strncpy(_res.defdname, rtems_bsdnet_domain_name, sizeof(_res.defdname) - 1);
+ }
+
+ /* Allow user to override the local domain definition */
+ if ((cp = getenv("LOCALDOMAIN")) != NULL) {
+ (void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
+ haveenv++;
+
+ /*
+ * Set search list to be blank-separated strings
+ * from rest of env value. Permits users of LOCALDOMAIN
+ * to still have a search list, and anyone to set the
+ * one that they want to use as an individual (even more
+ * important now that the rfc1535 stuff restricts searches)
+ */
+ cp = _res.defdname;
+ pp = _res.dnsrch;
+ *pp++ = cp;
+ for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) {
+ if (*cp == '\n') /* silly backwards compat */
+ break;
+ else if (*cp == ' ' || *cp == '\t') {
+ *cp = 0;
+ n = 1;
+ } else if (n) {
+ *pp++ = cp;
+ n = 0;
+ havesearch = 1;
+ }
+ }
+ /* null terminate last domain if there are excess */
+ while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n')
+ cp++;
+ *cp = '\0';
+ *pp++ = 0;
+ }
+
+#define MATCH(line, name) \
+ (!strncmp(line, name, sizeof(name) - 1) && \
+ (line[sizeof(name) - 1] == ' ' || \
+ line[sizeof(name) - 1] == '\t'))
+
+ if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
+ /* read the config file */
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ /* skip comments */
+ if (*buf == ';' || *buf == '#')
+ continue;
+ /* read default domain name */
+ if (MATCH(buf, "domain")) {
+ if (haveenv) /* skip if have from environ */
+ continue;
+ cp = buf + sizeof("domain") - 1;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ if ((*cp == '\0') || (*cp == '\n'))
+ continue;
+ strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
+ if ((cp = strpbrk(_res.defdname, " \t\n")) != NULL)
+ *cp = '\0';
+ havesearch = 0;
+ continue;
+ }
+ /* set search list */
+ if (MATCH(buf, "search")) {
+ if (haveenv) /* skip if have from environ */
+ continue;
+ cp = buf + sizeof("search") - 1;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ if ((*cp == '\0') || (*cp == '\n'))
+ continue;
+ strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
+ if ((cp = strchr(_res.defdname, '\n')) != NULL)
+ *cp = '\0';
+ /*
+ * Set search list to be blank-separated strings
+ * on rest of line.
+ */
+ cp = _res.defdname;
+ pp = _res.dnsrch;
+ *pp++ = cp;
+ for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) {
+ if (*cp == ' ' || *cp == '\t') {
+ *cp = 0;
+ n = 1;
+ } else if (n) {
+ *pp++ = cp;
+ n = 0;
+ }
+ }
+ /* null terminate last domain if there are excess */
+ while (*cp != '\0' && *cp != ' ' && *cp != '\t')
+ cp++;
+ *cp = '\0';
+ *pp++ = 0;
+ havesearch = 1;
+ continue;
+ }
+ /* read nameservers to query */
+ if (MATCH(buf, "nameserver") && nserv < MAXNS) {
+ struct in_addr a;
+
+ cp = buf + sizeof("nameserver") - 1;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ if ((*cp != '\0') && (*cp != '\n') && inet_aton(cp, &a)) {
+ _res.nsaddr_list[nserv].sin_addr = a;
+ _res.nsaddr_list[nserv].sin_family = AF_INET;
+ _res.nsaddr_list[nserv].sin_port =
+ htons(NAMESERVER_PORT);
+ nserv++;
+ }
+ continue;
+ }
+#ifdef RESOLVSORT
+ if (MATCH(buf, "sortlist")) {
+ struct in_addr a;
+
+ cp = buf + sizeof("sortlist") - 1;
+ while (nsort < MAXRESOLVSORT) {
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ if (*cp == '\0' || *cp == '\n' || *cp == ';')
+ break;
+ net = cp;
+ while (*cp && !ISSORTMASK(*cp) && *cp != ';' &&
+ isascii((int)*cp) && !isspace((int)*cp))
+ cp++;
+ n = *cp;
+ *cp = 0;
+ if (inet_aton(net, &a)) {
+ _res.sort_list[nsort].addr = a;
+ if (ISSORTMASK(n)) {
+ *cp++ = n;
+ net = cp;
+ while (*cp && *cp != ';' &&
+ isascii((int)*cp) && !isspace((int)*cp))
+ cp++;
+ n = *cp;
+ *cp = 0;
+ if (inet_aton(net, &a)) {
+ _res.sort_list[nsort].mask = a.s_addr;
+ } else {
+ _res.sort_list[nsort].mask =
+ net_mask(_res.sort_list[nsort].addr);
+ }
+ } else {
+ _res.sort_list[nsort].mask =
+ net_mask(_res.sort_list[nsort].addr);
+ }
+ nsort++;
+ }
+ *cp = n;
+ }
+ continue;
+ }
+#endif
+ if (MATCH(buf, "options")) {
+ res_setoptions(buf + sizeof("options") - 1, "conf");
+ continue;
+ }
+ }
+ if (nserv > 1)
+ _res.nscount = nserv;
+#ifdef RESOLVSORT
+ _res.nsort = nsort;
+#endif
+ (void) fclose(fp);
+ }
+ if (_res.defdname[0] == 0 &&
+ gethostname(buf, sizeof(_res.defdname) - 1) == 0 &&
+ (cp = strchr(buf, '.')) != NULL)
+ strcpy(_res.defdname, cp + 1);
+
+ /* find components of local domain that might be searched */
+ if (havesearch == 0) {
+ pp = _res.dnsrch;
+ *pp++ = _res.defdname;
+ *pp = NULL;
+
+#ifndef RFC1535
+ dots = 0;
+ for (cp = _res.defdname; *cp; cp++)
+ dots += (*cp == '.');
+
+ cp = _res.defdname;
+ while (pp < _res.dnsrch + MAXDFLSRCH) {
+ if (dots < LOCALDOMAINPARTS)
+ break;
+ cp = strchr(cp, '.') + 1; /* we know there is one */
+ *pp++ = cp;
+ dots--;
+ }
+ *pp = NULL;
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG) {
+ printf(";; res_init()... default dnsrch list:\n");
+ for (pp = _res.dnsrch; *pp; pp++)
+ printf(";;\t%s\n", *pp);
+ printf(";;\t..END..\n");
+ }
+#endif
+#endif /* !RFC1535 */
+ }
+
+ if ((cp = getenv("RES_OPTIONS")) != NULL)
+ res_setoptions(cp, "env");
+ _res.options |= RES_INIT;
+ return (0);
+}
+
+static void
+res_setoptions(options, source)
+ char *options, *source;
+{
+ char *cp = options;
+ int i;
+
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ printf(";; res_setoptions(\"%s\", \"%s\")...\n",
+ options, source);
+#endif
+ while (*cp) {
+ /* skip leading and inner runs of spaces */
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ /* search for and process individual options */
+ if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) {
+ i = atoi(cp + sizeof("ndots:") - 1);
+ if (i <= RES_MAXNDOTS)
+ _res.ndots = i;
+ else
+ _res.ndots = RES_MAXNDOTS;
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ printf(";;\tndots=%d\n", _res.ndots);
+#endif
+ } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) {
+#ifdef DEBUG
+ if (!(_res.options & RES_DEBUG)) {
+ printf(";; res_setoptions(\"%s\", \"%s\")..\n",
+ options, source);
+ _res.options |= RES_DEBUG;
+ }
+ printf(";;\tdebug\n");
+#endif
+ } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) {
+ _res.options |= RES_USE_INET6;
+ } else if (!strncmp(cp, "no_tld_query", sizeof("no_tld_query") - 1)) {
+ _res.options |= RES_NOTLDQUERY;
+ } else {
+ /* XXX - print a warning here? */
+ }
+ /* skip to next run of spaces */
+ while (*cp && *cp != ' ' && *cp != '\t')
+ cp++;
+ }
+}
+
+#ifdef RESOLVSORT
+/* XXX - should really support CIDR which means explicit masks always. */
+static u_int32_t
+net_mask(in) /* XXX - should really use system's version of this */
+ struct in_addr in;
+{
+ register u_int32_t i = ntohl(in.s_addr);
+
+ if (IN_CLASSA(i))
+ return (htonl(IN_CLASSA_NET));
+ else if (IN_CLASSB(i))
+ return (htonl(IN_CLASSB_NET));
+ return (htonl(IN_CLASSC_NET));
+}
+#endif
+
+u_int
+res_randomid()
+{
+ struct timeval now;
+
+ gettimeofday(&now, NULL);
+ return (0xffff & (now.tv_sec ^ now.tv_usec ^ getpid()));
+}
diff --git a/cpukit/libnetworking/libc/res_mkquery.c b/cpukit/libnetworking/libc/res_mkquery.c
new file mode 100644
index 0000000000..d3fabfa5ab
--- /dev/null
+++ b/cpukit/libnetworking/libc/res_mkquery.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ */
+
+/*
+ * Portions Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93";
+static char orig_rcsid[] = "From: Id: res_mkquery.c,v 8.9 1997/04/24 22:22:36 vixie Exp $";
+static char rcsid[] = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "res_config.h"
+
+/*
+ * Form all types of queries.
+ * Returns the size of the result or -1.
+ */
+int
+res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
+ int op; /* opcode of query */
+ const char *dname; /* domain name */
+ int class, type; /* class and type of query */
+ const u_char *data; /* resource record data */
+ int datalen; /* length of data */
+ const u_char *newrr_in; /* new rr for modify or append */
+ u_char *buf; /* buffer to put query */
+ int buflen; /* size of buffer */
+{
+ register HEADER *hp;
+ register u_char *cp;
+ register int n;
+ u_char *dnptrs[20], **dpp, **lastdnptr;
+
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ h_errno = NETDB_INTERNAL;
+ return (-1);
+ }
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ printf(";; res_mkquery(%d, %s, %d, %d)\n",
+ op, dname, class, type);
+#endif
+ /*
+ * Initialize header fields.
+ */
+ if ((buf == NULL) || (buflen < HFIXEDSZ))
+ return (-1);
+ memset(buf, 0, HFIXEDSZ);
+ hp = (HEADER *) buf;
+ hp->id = htons(++_res.id);
+ hp->opcode = op;
+ hp->rd = (_res.options & RES_RECURSE) != 0;
+ hp->rcode = NOERROR;
+ cp = buf + HFIXEDSZ;
+ buflen -= HFIXEDSZ;
+ dpp = dnptrs;
+ *dpp++ = buf;
+ *dpp++ = NULL;
+ lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
+ /*
+ * perform opcode specific processing
+ */
+ switch (op) {
+ case QUERY: /*FALLTHROUGH*/
+ case NS_NOTIFY_OP:
+ if ((buflen -= QFIXEDSZ) < 0)
+ return (-1);
+ if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
+ return (-1);
+ cp += n;
+ buflen -= n;
+ __putshort(type, cp);
+ cp += INT16SZ;
+ __putshort(class, cp);
+ cp += INT16SZ;
+ hp->qdcount = htons(1);
+ if (op == QUERY || data == NULL)
+ break;
+ /*
+ * Make an additional record for completion domain.
+ */
+ buflen -= RRFIXEDSZ;
+ n = dn_comp((char *)data, cp, buflen, dnptrs, lastdnptr);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ buflen -= n;
+ __putshort(T_NULL, cp);
+ cp += INT16SZ;
+ __putshort(class, cp);
+ cp += INT16SZ;
+ __putlong(0, cp);
+ cp += INT32SZ;
+ __putshort(0, cp);
+ cp += INT16SZ;
+ hp->arcount = htons(1);
+ break;
+
+ case IQUERY:
+ /*
+ * Initialize answer section
+ */
+ if (buflen < 1 + RRFIXEDSZ + datalen)
+ return (-1);
+ *cp++ = '\0'; /* no domain name */
+ __putshort(type, cp);
+ cp += INT16SZ;
+ __putshort(class, cp);
+ cp += INT16SZ;
+ __putlong(0, cp);
+ cp += INT32SZ;
+ __putshort(datalen, cp);
+ cp += INT16SZ;
+ if (datalen) {
+ memcpy(cp, data, datalen);
+ cp += datalen;
+ }
+ hp->ancount = htons(1);
+ break;
+
+ default:
+ return (-1);
+ }
+ return (cp - buf);
+}
diff --git a/cpukit/libnetworking/libc/res_mkupdate.c b/cpukit/libnetworking/libc/res_mkupdate.c
new file mode 100644
index 0000000000..56362f650b
--- /dev/null
+++ b/cpukit/libnetworking/libc/res_mkupdate.c
@@ -0,0 +1,415 @@
+/*
+ * Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ */
+
+/*
+ * Based on the Dynamic DNS reference implementation by Viraj Bais
+ * <viraj_bais@ccm.fm.intel.com>
+ */
+
+#if !defined(__rtems__)
+#if !defined(lint) && !defined(SABER)
+static char rcsid[] = "$Id$";
+#endif /* not lint */
+#endif /* not rtems */
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#include "res_config.h"
+
+static int getnum_str(u_char **, u_char *);
+static int getword_str(char *, int, u_char **, u_char *);
+
+#define ShrinkBuffer(x) if ((buflen -= x) < 0) return (-2);
+
+/*
+ * Form update packets.
+ * Returns the size of the resulting packet if no error
+ * On error,
+ * returns -1 if error in reading a word/number in rdata
+ * portion for update packets
+ * -2 if length of buffer passed is insufficient
+ * -3 if zone section is not the first section in
+ * the linked list, or section order has a problem
+ * -4 on a number overflow
+ * -5 unknown operation or no records
+ */
+int
+res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) {
+ ns_updrec *rrecp_start = rrecp_in;
+ HEADER *hp;
+ u_char *cp, *sp1, *sp2, *startp, *endp;
+ int n, i, soanum, multiline;
+ ns_updrec *rrecp;
+ struct in_addr ina;
+ char buf2[MAXDNAME];
+ int section, numrrs = 0, counts[ns_s_max];
+ u_int16_t rtype, rclass;
+ u_int32_t n1, rttl;
+ u_char *dnptrs[20], **dpp, **lastdnptr;
+
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ h_errno = NETDB_INTERNAL;
+ return (-1);
+ }
+
+ /*
+ * Initialize header fields.
+ */
+ if ((buf == NULL) || (buflen < HFIXEDSZ))
+ return (-1);
+ memset(buf, 0, HFIXEDSZ);
+ hp = (HEADER *) buf;
+ hp->id = htons(++_res.id);
+ hp->opcode = ns_o_update;
+ hp->rcode = NOERROR;
+ sp1 = buf + 2*INT16SZ; /* save pointer to zocount */
+ cp = buf + HFIXEDSZ;
+ buflen -= HFIXEDSZ;
+ dpp = dnptrs;
+ *dpp++ = buf;
+ *dpp++ = NULL;
+ lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
+
+ if (rrecp_start == NULL)
+ return (-5);
+ else if (rrecp_start->r_section != S_ZONE)
+ return (-3);
+
+ memset(counts, 0, sizeof counts);
+ for (rrecp = rrecp_start; rrecp; rrecp = rrecp->r_grpnext) {
+ numrrs++;
+ section = rrecp->r_section;
+ if (section < 0 || section >= ns_s_max)
+ return (-1);
+ counts[section]++;
+ for (i = section + 1; i < ns_s_max; i++)
+ if (counts[i])
+ return (-3);
+ rtype = rrecp->r_type;
+ rclass = rrecp->r_class;
+ rttl = rrecp->r_ttl;
+ /* overload class and type */
+ if (section == S_PREREQ) {
+ rttl = 0;
+ switch (rrecp->r_opcode) {
+ case YXDOMAIN:
+ rclass = C_ANY;
+ rtype = T_ANY;
+ rrecp->r_size = 0;
+ break;
+ case NXDOMAIN:
+ rclass = C_NONE;
+ rtype = T_ANY;
+ rrecp->r_size = 0;
+ break;
+ case NXRRSET:
+ rclass = C_NONE;
+ rrecp->r_size = 0;
+ break;
+ case YXRRSET:
+ if (rrecp->r_size == 0)
+ rclass = C_ANY;
+ break;
+ default:
+ fprintf(stderr,
+ "res_mkupdate: incorrect opcode: %d\n",
+ rrecp->r_opcode);
+ fflush(stderr);
+ return (-1);
+ }
+ } else if (section == S_UPDATE) {
+ switch (rrecp->r_opcode) {
+ case DELETE:
+ rclass = rrecp->r_size == 0 ? C_ANY : C_NONE;
+ break;
+ case ADD:
+ break;
+ default:
+ fprintf(stderr,
+ "res_mkupdate: incorrect opcode: %d\n",
+ rrecp->r_opcode);
+ fflush(stderr);
+ return (-1);
+ }
+ }
+
+ /*
+ * XXX appending default domain to owner name is omitted,
+ * fqdn must be provided
+ */
+ if ((n = dn_comp(rrecp->r_dname, cp, buflen, dnptrs,
+ lastdnptr)) < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n + 2*INT16SZ);
+ PUTSHORT(rtype, cp);
+ PUTSHORT(rclass, cp);
+ if (section == S_ZONE) {
+ if (numrrs != 1 || rrecp->r_type != T_SOA)
+ return (-3);
+ continue;
+ }
+ ShrinkBuffer(INT32SZ + INT16SZ);
+ PUTLONG(rttl, cp);
+ sp2 = cp; /* save pointer to length byte */
+ cp += INT16SZ;
+ if (rrecp->r_size == 0) {
+ if (section == S_UPDATE && rclass != C_ANY)
+ return (-1);
+ else {
+ PUTSHORT(0, sp2);
+ continue;
+ }
+ }
+ startp = rrecp->r_data;
+ endp = startp + rrecp->r_size - 1;
+ /* XXX this should be done centrally. */
+ switch (rrecp->r_type) {
+ case T_A:
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ if (!inet_aton(buf2, &ina))
+ return (-1);
+ n1 = ntohl(ina.s_addr);
+ ShrinkBuffer(INT32SZ);
+ PUTLONG(n1, cp);
+ break;
+ case T_CNAME:
+ case T_MB:
+ case T_MG:
+ case T_MR:
+ case T_NS:
+ case T_PTR:
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ break;
+ case T_MINFO:
+ case T_SOA:
+ case T_RP:
+ for (i = 0; i < 2; i++) {
+ if (!getword_str(buf2, sizeof buf2, &startp,
+ endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen,
+ dnptrs, lastdnptr);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ }
+ if (rrecp->r_type == T_SOA) {
+ ShrinkBuffer(5 * INT32SZ);
+ while (isspace(*startp) || !*startp)
+ startp++;
+ if (*startp == '(') {
+ multiline = 1;
+ startp++;
+ } else
+ multiline = 0;
+ /* serial, refresh, retry, expire, minimum */
+ for (i = 0; i < 5; i++) {
+ soanum = getnum_str(&startp, endp);
+ if (soanum < 0)
+ return (-1);
+ PUTLONG(soanum, cp);
+ }
+ if (multiline) {
+ while (isspace(*startp) || !*startp)
+ startp++;
+ if (*startp != ')')
+ return (-1);
+ }
+ }
+ break;
+ case T_MX:
+ case T_AFSDB:
+ case T_RT:
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ PUTSHORT(n, cp);
+ ShrinkBuffer(INT16SZ);
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ break;
+ case T_PX:
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ PUTSHORT(n, cp);
+ ShrinkBuffer(INT16SZ);
+ for (i = 0; i < 2; i++) {
+ if (!getword_str(buf2, sizeof buf2, &startp,
+ endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen, dnptrs,
+ lastdnptr);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ }
+ break;
+ case T_WKS:
+ case T_HINFO:
+ case T_TXT:
+ case T_X25:
+ case T_ISDN:
+ case T_NSAP:
+ case T_LOC:
+ /* XXX - more fine tuning needed here */
+ ShrinkBuffer(rrecp->r_size);
+ memcpy(cp, rrecp->r_data, rrecp->r_size);
+ cp += rrecp->r_size;
+ break;
+ default:
+ return (-1);
+ } /*switch*/
+ n = (u_int16_t)((cp - sp2) - INT16SZ);
+ PUTSHORT(n, sp2);
+ } /*for*/
+
+ hp->qdcount = htons(counts[0]);
+ hp->ancount = htons(counts[1]);
+ hp->nscount = htons(counts[2]);
+ hp->arcount = htons(counts[3]);
+ return (cp - buf);
+}
+
+/*
+ * Get a whitespace delimited word from a string (not file)
+ * into buf. modify the start pointer to point after the
+ * word in the string.
+ */
+static int
+getword_str(char *buf, int size, u_char **startpp, u_char *endp) {
+ char *cp;
+ int c;
+
+ for (cp = buf; *startpp <= endp; ) {
+ c = **startpp;
+ if (isspace(c) || c == '\0') {
+ if (cp != buf) /* trailing whitespace */
+ break;
+ else { /* leading whitespace */
+ (*startpp)++;
+ continue;
+ }
+ }
+ (*startpp)++;
+ if (cp >= buf+size-1)
+ break;
+ *cp++ = (u_char)c;
+ }
+ *cp = '\0';
+ return (cp != buf);
+}
+
+/*
+ * Get a whitespace delimited number from a string (not file) into buf
+ * update the start pointer to point after the number in the string.
+ */
+static int
+getnum_str(u_char **startpp, u_char *endp) {
+ int c, n;
+ int seendigit = 0;
+ int m = 0;
+
+ for (n = 0; *startpp <= endp; ) {
+ c = **startpp;
+ if (isspace(c) || c == '\0') {
+ if (seendigit) /* trailing whitespace */
+ break;
+ else { /* leading whitespace */
+ (*startpp)++;
+ continue;
+ }
+ }
+ if (c == ';') {
+ while ((*startpp <= endp) &&
+ ((c = **startpp) != '\n'))
+ (*startpp)++;
+ if (seendigit)
+ break;
+ continue;
+ }
+ if (!isdigit(c)) {
+ if (c == ')' && seendigit) {
+ (*startpp)--;
+ break;
+ }
+ return (-1);
+ }
+ (*startpp)++;
+ n = n * 10 + (c - '0');
+ seendigit = 1;
+ }
+ return (n + m);
+}
+
+/*
+ * Allocate a resource record buffer & save rr info.
+ */
+ns_updrec *
+res_mkupdrec(int section, const char *dname,
+ u_int class, u_int type, u_long ttl) {
+ ns_updrec *rrecp = (ns_updrec *)calloc(1, sizeof(ns_updrec));
+
+ if (!rrecp || !(rrecp->r_dname = strdup(dname)))
+ return (NULL);
+ rrecp->r_class = class;
+ rrecp->r_type = type;
+ rrecp->r_ttl = ttl;
+ rrecp->r_section = section;
+ return (rrecp);
+}
+
+/*
+ * Free a resource record buffer created by res_mkupdrec.
+ */
+void
+res_freeupdrec(ns_updrec *rrecp) {
+ /* Note: freeing r_dp is the caller's responsibility. */
+ if (rrecp->r_dname != NULL)
+ free(rrecp->r_dname);
+ free(rrecp);
+}
diff --git a/cpukit/libnetworking/libc/res_query.c b/cpukit/libnetworking/libc/res_query.c
new file mode 100644
index 0000000000..784fa433bc
--- /dev/null
+++ b/cpukit/libnetworking/libc/res_query.c
@@ -0,0 +1,410 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ */
+
+/*
+ * Portions Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93";
+static char orig_rcsid = "From: Id: res_query.c,v 8.14 1997/06/09 17:47:05 halley Exp $";
+static char rcsid[] = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "res_config.h"
+
+#if PACKETSZ > 1024
+#define MAXPACKET PACKETSZ
+#else
+#define MAXPACKET 1024
+#endif
+
+/*
+ * Formulate a normal query, send, and await answer.
+ * Returned answer is placed in supplied buffer "answer".
+ * Perform preliminary check of answer, returning success only
+ * if no error is indicated and the answer count is nonzero.
+ * Return the size of the response on success, -1 on error.
+ * Error number is left in h_errno.
+ *
+ * Caller must parse answer and determine whether it answers the question.
+ */
+int
+res_query(name, class, type, answer, anslen)
+ const char *name; /* domain name */
+ int class, type; /* class and type of query */
+ u_char *answer; /* buffer to put answer */
+ int anslen; /* size of answer buffer */
+{
+ u_char buf[MAXPACKET];
+ HEADER *hp = (HEADER *) answer;
+ int n;
+
+ hp->rcode = NOERROR; /* default */
+
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ h_errno = NETDB_INTERNAL;
+ return (-1);
+ }
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ printf(";; res_query(%s, %d, %d)\n", name, class, type);
+#endif
+
+ n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
+ buf, sizeof(buf));
+ if (n <= 0) {
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ printf(";; res_query: mkquery failed\n");
+#endif
+ h_errno = NO_RECOVERY;
+ return (n);
+ }
+ n = res_send(buf, n, answer, anslen);
+ if (n < 0) {
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ printf(";; res_query: send error\n");
+#endif
+ h_errno = TRY_AGAIN;
+ return (n);
+ }
+
+ if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ printf(";; rcode = %d, ancount=%d\n", hp->rcode,
+ ntohs(hp->ancount));
+#endif
+ switch (hp->rcode) {
+ case NXDOMAIN:
+ h_errno = HOST_NOT_FOUND;
+ break;
+ case SERVFAIL:
+ h_errno = TRY_AGAIN;
+ break;
+ case NOERROR:
+ h_errno = NO_DATA;
+ break;
+ case FORMERR:
+ case NOTIMP:
+ case REFUSED:
+ default:
+ h_errno = NO_RECOVERY;
+ break;
+ }
+ return (-1);
+ }
+ return (n);
+}
+
+/*
+ * Formulate a normal query, send, and retrieve answer in supplied buffer.
+ * Return the size of the response on success, -1 on error.
+ * If enabled, implement search rules until answer or unrecoverable failure
+ * is detected. Error code, if any, is left in h_errno.
+ */
+int
+res_search(name, class, type, answer, anslen)
+ const char *name; /* domain name */
+ int class, type; /* class and type of query */
+ u_char *answer; /* buffer to put answer */
+ int anslen; /* size of answer */
+{
+ const char *cp, * const *domain;
+ HEADER *hp = (HEADER *) answer;
+ u_int dots;
+ int trailing_dot, ret, saved_herrno;
+ int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
+
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ h_errno = NETDB_INTERNAL;
+ return (-1);
+ }
+ errno = 0;
+ h_errno = HOST_NOT_FOUND; /* default, if we never query */
+ dots = 0;
+ for (cp = name; *cp; cp++)
+ dots += (*cp == '.');
+ trailing_dot = 0;
+ if (cp > name && *--cp == '.')
+ trailing_dot++;
+
+ /* If there aren't any dots, it could be a user-level alias */
+ if (!dots && (cp = hostalias(name)) != NULL)
+ return (res_query(cp, class, type, answer, anslen));
+
+ /*
+ * If there are dots in the name already, let's just give it a try
+ * 'as is'. The threshold can be set with the "ndots" option.
+ */
+ saved_herrno = -1;
+ if (dots >= _res.ndots) {
+ ret = res_querydomain(name, NULL, class, type, answer, anslen);
+ if (ret > 0)
+ return (ret);
+ saved_herrno = h_errno;
+ tried_as_is++;
+ }
+
+ /*
+ * We do at least one level of search if
+ * - there is no dot and RES_DEFNAME is set, or
+ * - there is at least one dot, there is no trailing dot,
+ * and RES_DNSRCH is set.
+ */
+ if ((!dots && (_res.options & RES_DEFNAMES)) ||
+ (dots && !trailing_dot && (_res.options & RES_DNSRCH))) {
+ int done = 0;
+
+ for (domain = (const char * const *)_res.dnsrch;
+ *domain && !done;
+ domain++) {
+
+ ret = res_querydomain(name, *domain, class, type,
+ answer, anslen);
+ if (ret > 0)
+ return (ret);
+
+ /*
+ * If no server present, give up.
+ * If name isn't found in this domain,
+ * keep trying higher domains in the search list
+ * (if that's enabled).
+ * On a NO_DATA error, keep trying, otherwise
+ * a wildcard entry of another type could keep us
+ * from finding this entry higher in the domain.
+ * If we get some other error (negative answer or
+ * server failure), then stop searching up,
+ * but try the input name below in case it's
+ * fully-qualified.
+ */
+ if (errno == ECONNREFUSED) {
+ h_errno = TRY_AGAIN;
+ return (-1);
+ }
+
+ switch (h_errno) {
+ case NO_DATA:
+ got_nodata++;
+ /* FALLTHROUGH */
+ case HOST_NOT_FOUND:
+ /* keep trying */
+ break;
+ case TRY_AGAIN:
+ if (hp->rcode == SERVFAIL) {
+ /* try next search element, if any */
+ got_servfail++;
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ /* anything else implies that we're done */
+ done++;
+ }
+
+ /* if we got here for some reason other than DNSRCH,
+ * we only wanted one iteration of the loop, so stop.
+ */
+ if (!(_res.options & RES_DNSRCH))
+ done++;
+ }
+ }
+
+ /*
+ * If we have not already tried the name "as is", do that now.
+ * note that we do this regardless of how many dots were in the
+ * name or whether it ends with a dot unless NOTLDQUERY is set.
+ */
+ if (!tried_as_is && (dots || !(_res.options & RES_NOTLDQUERY))) {
+ ret = res_querydomain(name, NULL, class, type, answer, anslen);
+ if (ret > 0)
+ return (ret);
+ }
+
+ /* if we got here, we didn't satisfy the search.
+ * if we did an initial full query, return that query's h_errno
+ * (note that we wouldn't be here if that query had succeeded).
+ * else if we ever got a nodata, send that back as the reason.
+ * else send back meaningless h_errno, that being the one from
+ * the last DNSRCH we did.
+ */
+ if (saved_herrno != -1)
+ h_errno = saved_herrno;
+ else if (got_nodata)
+ h_errno = NO_DATA;
+ else if (got_servfail)
+ h_errno = TRY_AGAIN;
+ return (-1);
+}
+
+/*
+ * Perform a call on res_query on the concatenation of name and domain,
+ * removing a trailing dot from name if domain is NULL.
+ */
+int
+res_querydomain(name, domain, class, type, answer, anslen)
+ const char *name, *domain;
+ int class, type; /* class and type of query */
+ u_char *answer; /* buffer to put answer */
+ int anslen; /* size of answer */
+{
+ char nbuf[MAXDNAME];
+ const char *longname = nbuf;
+ int n, d;
+
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ h_errno = NETDB_INTERNAL;
+ return (-1);
+ }
+#ifdef DEBUG
+ if (_res.options & RES_DEBUG)
+ printf(";; res_querydomain(%s, %s, %d, %d)\n",
+ name, domain?domain:"<Nil>", class, type);
+#endif
+ if (domain == NULL) {
+ /*
+ * Check for trailing '.';
+ * copy without '.' if present.
+ */
+ n = strlen(name);
+ if (n >= MAXDNAME) {
+ h_errno = NO_RECOVERY;
+ return (-1);
+ }
+ n--;
+ if (n >= 0 && name[n] == '.') {
+ strncpy(nbuf, name, n);
+ nbuf[n] = '\0';
+ } else
+ longname = name;
+ } else {
+ n = strlen(name);
+ d = strlen(domain);
+ if (n + d + 1 >= MAXDNAME) {
+ h_errno = NO_RECOVERY;
+ return (-1);
+ }
+ sprintf(nbuf, "%s.%s", name, domain);
+ }
+ return (res_query(longname, class, type, answer, anslen));
+}
+
+const char *
+hostalias(name)
+ const char *name;
+{
+ register char *cp1, *cp2;
+ FILE *fp;
+ char *file;
+ char buf[BUFSIZ];
+ static char abuf[MAXDNAME];
+
+ if (_res.options & RES_NOALIASES)
+ return (NULL);
+ if (issetugid())
+ return (NULL);
+ file = getenv("HOSTALIASES");
+ if (file == NULL || (fp = fopen(file, "r")) == NULL)
+ return (NULL);
+ setbuf(fp, NULL);
+ buf[sizeof(buf) - 1] = '\0';
+ while (fgets(buf, sizeof(buf), fp)) {
+ for (cp1 = buf; *cp1 && !isspace((int)*cp1); ++cp1)
+ ;
+ if (!*cp1)
+ break;
+ *cp1 = '\0';
+ if (!strcasecmp(buf, name)) {
+ while (isspace((int)*++cp1))
+ ;
+ if (!*cp1)
+ break;
+ for (cp2 = cp1 + 1; *cp2 && !isspace((int)*cp2); ++cp2)
+ ;
+ abuf[sizeof(abuf) - 1] = *cp2 = '\0';
+ strncpy(abuf, cp1, sizeof(abuf) - 1);
+ fclose(fp);
+ return (abuf);
+ }
+ }
+ fclose(fp);
+ return (NULL);
+}
diff --git a/cpukit/libnetworking/libc/res_send.c b/cpukit/libnetworking/libc/res_send.c
new file mode 100644
index 0000000000..fadc16c566
--- /dev/null
+++ b/cpukit/libnetworking/libc/res_send.c
@@ -0,0 +1,932 @@
+/*
+ * Copyright (c) 1985, 1989, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ */
+
+/*
+ * Portions Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
+static char orig_rcsid[] = "From: Id: res_send.c,v 8.20 1998/04/06 23:27:51 halley Exp $";
+static char rcsid[] = "$Id$";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * Send query to name server and wait for reply.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#if !defined(__rtems__)
+#include <poll.h>
+#endif
+
+#include "res_config.h"
+
+#if !defined(__rtems__)
+
+#ifdef NOPOLL /* libc_r doesn't wrap poll yet() */
+static int use_poll = 0;
+#else
+static int use_poll = 1; /* adapt to poll() syscall availability */
+ /* 0 = not present, 1 = try it, 2 = exists */
+#endif
+#endif
+
+static int s = -1; /* socket used for communications */
+static int connected = 0; /* is the socket connected */
+static int vc = 0; /* is the socket a virtual circuit? */
+static res_send_qhook Qhook = NULL;
+static res_send_rhook Rhook = NULL;
+
+
+#define CAN_RECONNECT 1
+
+#ifndef DEBUG
+# define Dprint(cond, args) /*empty*/
+# define DprintQ(cond, args, query, size) /*empty*/
+# define Aerror(file, string, error, address) /*empty*/
+# define Perror(file, string, error) /*empty*/
+#else
+# define Dprint(cond, args) if (cond) {fprintf args;} else {}
+# define DprintQ(cond, args, query, size) if (cond) {\
+ fprintf args;\
+ __fp_nquery(query, size, stdout);\
+ } else {}
+ static void
+ Aerror(file, string, error, address)
+ FILE *file;
+ char *string;
+ int error;
+ struct sockaddr_in address;
+ {
+ int save = errno;
+
+ if (_res.options & RES_DEBUG) {
+ fprintf(file, "res_send: %s ([%s].%u): %s\n",
+ string,
+ inet_ntoa(address.sin_addr),
+ ntohs(address.sin_port),
+ strerror(error));
+ }
+ errno = save;
+ }
+ static void
+ Perror(file, string, error)
+ FILE *file;
+ char *string;
+ int error;
+ {
+ int save = errno;
+
+ if (_res.options & RES_DEBUG) {
+ fprintf(file, "res_send: %s: %s\n",
+ string, strerror(error));
+ }
+ errno = save;
+ }
+#endif
+
+void
+res_send_setqhook(hook)
+ res_send_qhook hook;
+{
+
+ Qhook = hook;
+}
+
+void
+res_send_setrhook(hook)
+ res_send_rhook hook;
+{
+
+ Rhook = hook;
+}
+
+/* int
+ * res_isourserver(ina)
+ * looks up "ina" in _res.ns_addr_list[]
+ * returns:
+ * 0 : not found
+ * >0 : found
+ * author:
+ * paul vixie, 29may94
+ */
+int
+res_isourserver(inp)
+ const struct sockaddr_in *inp;
+{
+ struct sockaddr_in ina;
+ int ns, ret;
+
+ ina = *inp;
+ ret = 0;
+ for (ns = 0; ns < _res.nscount; ns++) {
+ const struct sockaddr_in *srv = &_res.nsaddr_list[ns];
+
+ if (srv->sin_family == ina.sin_family &&
+ srv->sin_port == ina.sin_port &&
+ (srv->sin_addr.s_addr == INADDR_ANY ||
+ srv->sin_addr.s_addr == ina.sin_addr.s_addr)) {
+ ret++;
+ break;
+ }
+ }
+ return (ret);
+}
+
+/* int
+ * res_nameinquery(name, type, class, buf, eom)
+ * look for (name,type,class) in the query section of packet (buf,eom)
+ * requires:
+ * buf + HFIXEDSZ <= eom
+ * returns:
+ * -1 : format error
+ * 0 : not found
+ * >0 : found
+ * author:
+ * paul vixie, 29may94
+ */
+int
+res_nameinquery(name, type, class, buf, eom)
+ const char *name;
+ int type, class;
+ const u_char *buf, *eom;
+{
+ const u_char *cp = buf + HFIXEDSZ;
+ int qdcount = ntohs(((HEADER*)buf)->qdcount);
+
+ while (qdcount-- > 0) {
+ char tname[MAXDNAME+1];
+ int n, ttype, tclass;
+
+ n = dn_expand(buf, eom, cp, tname, sizeof tname);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ if (cp + 2 * INT16SZ > eom)
+ return (-1);
+ ttype = ns_get16(cp); cp += INT16SZ;
+ tclass = ns_get16(cp); cp += INT16SZ;
+ if (ttype == type &&
+ tclass == class &&
+ strcasecmp(tname, name) == 0)
+ return (1);
+ }
+ return (0);
+}
+
+/* int
+ * res_queriesmatch(buf1, eom1, buf2, eom2)
+ * is there a 1:1 mapping of (name,type,class)
+ * in (buf1,eom1) and (buf2,eom2)?
+ * returns:
+ * -1 : format error
+ * 0 : not a 1:1 mapping
+ * >0 : is a 1:1 mapping
+ * author:
+ * paul vixie, 29may94
+ */
+int
+res_queriesmatch(buf1, eom1, buf2, eom2)
+ const u_char *buf1, *eom1;
+ const u_char *buf2, *eom2;
+{
+ const u_char *cp = buf1 + HFIXEDSZ;
+ int qdcount = ntohs(((HEADER*)buf1)->qdcount);
+
+ if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2)
+ return (-1);
+
+ /*
+ * Only header section present in replies to
+ * dynamic update packets.
+ */
+ if ( (((HEADER *)buf1)->opcode == ns_o_update) &&
+ (((HEADER *)buf2)->opcode == ns_o_update) )
+ return (1);
+
+ if (qdcount != ntohs(((HEADER*)buf2)->qdcount))
+ return (0);
+ while (qdcount-- > 0) {
+ char tname[MAXDNAME+1];
+ int n, ttype, tclass;
+
+ n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ if (cp + 2 * INT16SZ > eom1)
+ return (-1);
+ ttype = ns_get16(cp); cp += INT16SZ;
+ tclass = ns_get16(cp); cp += INT16SZ;
+ if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
+ return (0);
+ }
+ return (1);
+}
+
+int
+res_send(buf, buflen, ans, anssiz)
+ const u_char *buf;
+ int buflen;
+ u_char *ans;
+ int anssiz;
+{
+ HEADER *hp = (HEADER *) buf;
+ HEADER *anhp = (HEADER *) ans;
+ int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns, n;
+ u_int badns; /* XXX NSMAX can't exceed #/bits in this variable */
+
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ /* errno should have been set by res_init() in this case. */
+ return (-1);
+ }
+ if (anssiz < HFIXEDSZ) {
+ errno = EINVAL;
+ return (-1);
+ }
+ DprintQ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_QUERY),
+ (stdout, ";; res_send()\n"), buf, buflen);
+ v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ;
+ gotsomewhere = 0;
+ connreset = 0;
+ terrno = ETIMEDOUT;
+ badns = 0;
+
+ /*
+ * Send request, RETRY times, or until successful
+ */
+ for (try = 0; try < _res.retry; try++) {
+ for (ns = 0; ns < _res.nscount; ns++) {
+ struct sockaddr_in *nsap = &_res.nsaddr_list[ns];
+ same_ns:
+ if (badns & (1 << ns)) {
+ res_close();
+ goto next_ns;
+ }
+
+ if (Qhook) {
+ int done = 0, loops = 0;
+
+ do {
+ res_sendhookact act;
+
+ act = (*Qhook)(&nsap, &buf, &buflen,
+ ans, anssiz, &resplen);
+ switch (act) {
+ case res_goahead:
+ done = 1;
+ break;
+ case res_nextns:
+ res_close();
+ goto next_ns;
+ case res_done:
+ return (resplen);
+ case res_modified:
+ /* give the hook another try */
+ if (++loops < 42) /*doug adams*/
+ break;
+ /*FALLTHROUGH*/
+ case res_error:
+ /*FALLTHROUGH*/
+ default:
+ return (-1);
+ }
+ } while (!done);
+ }
+
+ Dprint(_res.options & RES_DEBUG,
+ (stdout, ";; Querying server (# %d) address = %s\n",
+ ns + 1, inet_ntoa(nsap->sin_addr)));
+
+ if (v_circuit) {
+ int truncated;
+#if !defined(__rtems__)
+ struct iovec iov[2];
+#endif
+ u_short len;
+ u_char *cp;
+
+ /*
+ * Use virtual circuit;
+ * at most one attempt per server.
+ */
+ try = _res.retry;
+ truncated = 0;
+ if (s < 0 || !vc || hp->opcode == ns_o_update) {
+ if (s >= 0)
+ res_close();
+
+ s = socket(PF_INET, SOCK_STREAM, 0);
+ if (s < 0) {
+ terrno = errno;
+ Perror(stderr, "socket(vc)", errno);
+ return (-1);
+ }
+ errno = 0;
+ if (connect(s, (struct sockaddr *)nsap,
+ sizeof *nsap) < 0) {
+ terrno = errno;
+ Aerror(stderr, "connect/vc",
+ errno, *nsap);
+ badns |= (1 << ns);
+ res_close();
+ goto next_ns;
+ }
+ vc = 1;
+ }
+ /*
+ * Send length & message
+ */
+ putshort((u_short)buflen, (u_char*)&len);
+#if !defined(__rtems__)
+ iov[0].iov_base = (caddr_t)&len;
+ iov[0].iov_len = INT16SZ;
+ iov[1].iov_base = (caddr_t)buf;
+ iov[1].iov_len = buflen;
+ if (writev(s, iov, 2) != (INT16SZ + buflen)) {
+#else
+ /*
+ * RTEMS doesn't have writev (yet)
+ */
+ if ((write (s, &len, INT16SZ) != INT16SZ)
+ || (write (s, buf, buflen) != buflen)) {
+#endif
+ terrno = errno;
+ Perror(stderr, "write failed", errno);
+ badns |= (1 << ns);
+ res_close();
+ goto next_ns;
+ }
+ /*
+ * Receive length & response
+ */
+read_len:
+ cp = ans;
+ len = INT16SZ;
+ while ((n = read(s, (char *)cp, (int)len)) > 0) {
+ cp += n;
+ if ((len -= n) <= 0)
+ break;
+ }
+ if (n <= 0) {
+ terrno = errno;
+ Perror(stderr, "read failed", errno);
+ res_close();
+ /*
+ * A long running process might get its TCP
+ * connection reset if the remote server was
+ * restarted. Requery the server instead of
+ * trying a new one. When there is only one
+ * server, this means that a query might work
+ * instead of failing. We only allow one reset
+ * per query to prevent looping.
+ */
+ if (terrno == ECONNRESET && !connreset) {
+ connreset = 1;
+ res_close();
+ goto same_ns;
+ }
+ res_close();
+ goto next_ns;
+ }
+ resplen = ns_get16(ans);
+ if (resplen > anssiz) {
+ Dprint(_res.options & RES_DEBUG,
+ (stdout, ";; response truncated\n")
+ );
+ truncated = 1;
+ len = anssiz;
+ } else
+ len = resplen;
+ if (len < HFIXEDSZ) {
+ /*
+ * Undersized message.
+ */
+ Dprint(_res.options & RES_DEBUG,
+ (stdout, ";; undersized: %d\n", len));
+ terrno = EMSGSIZE;
+ badns |= (1 << ns);
+ res_close();
+ goto next_ns;
+ }
+ cp = ans;
+ while (len != 0 &&
+ (n = read(s, (char *)cp, (int)len)) > 0) {
+ cp += n;
+ len -= n;
+ }
+ if (n <= 0) {
+ terrno = errno;
+ Perror(stderr, "read(vc)", errno);
+ res_close();
+ goto next_ns;
+ }
+ if (truncated) {
+ /*
+ * Flush rest of answer
+ * so connection stays in synch.
+ */
+ anhp->tc = 1;
+ len = resplen - anssiz;
+ while (len != 0) {
+ char junk[PACKETSZ];
+
+ n = (len > sizeof(junk)
+ ? sizeof(junk)
+ : len);
+ if ((n = read(s, junk, n)) > 0)
+ len -= n;
+ else
+ break;
+ }
+ }
+ /*
+ * The calling applicating has bailed out of
+ * a previous call and failed to arrange to have
+ * the circuit closed or the server has got
+ * itself confused. Anyway drop the packet and
+ * wait for the correct one.
+ */
+ if (hp->id != anhp->id) {
+ DprintQ((_res.options & RES_DEBUG) ||
+ (_res.pfcode & RES_PRF_REPLY),
+ (stdout, ";; old answer (unexpected):\n"),
+ ans, (resplen>anssiz)?anssiz:resplen);
+ goto read_len;
+ }
+ } else {
+ /*
+ * Use datagrams.
+ */
+#ifndef NOPOLL
+ struct pollfd pfd;
+ int msec;
+#endif
+ struct timeval timeout;
+#ifndef NOSELECT
+ fd_set dsmask, *dsmaskp;
+ int dsmasklen;
+#endif
+ struct sockaddr_in from;
+ int fromlen;
+
+ if ((s < 0) || vc) {
+ if (vc)
+ res_close();
+ s = socket(PF_INET, SOCK_DGRAM, 0);
+ if (s < 0) {
+#ifndef CAN_RECONNECT
+ bad_dg_sock:
+#endif
+ terrno = errno;
+ Perror(stderr, "socket(dg)", errno);
+ return (-1);
+ }
+ connected = 0;
+ }
+#ifndef CANNOT_CONNECT_DGRAM
+ /*
+ * On a 4.3BSD+ machine (client and server,
+ * actually), sending to a nameserver datagram
+ * port with no nameserver will cause an
+ * ICMP port unreachable message to be returned.
+ * If our datagram socket is "connected" to the
+ * server, we get an ECONNREFUSED error on the next
+ * socket operation, and select returns if the
+ * error message is received. We can thus detect
+ * the absence of a nameserver without timing out.
+ * If we have sent queries to at least two servers,
+ * however, we don't want to remain connected,
+ * as we wish to receive answers from the first
+ * server to respond.
+ */
+ if (_res.nscount == 1 || (try == 0 && ns == 0)) {
+ /*
+ * Connect only if we are sure we won't
+ * receive a response from another server.
+ */
+ if (!connected) {
+ if (connect(s, (struct sockaddr *)nsap,
+ sizeof *nsap
+ ) < 0) {
+ Aerror(stderr,
+ "connect(dg)",
+ errno, *nsap);
+ badns |= (1 << ns);
+ res_close();
+ goto next_ns;
+ }
+ connected = 1;
+ }
+ if (send(s, (char*)buf, buflen, 0) != buflen) {
+ Perror(stderr, "send", errno);
+ badns |= (1 << ns);
+ res_close();
+ goto next_ns;
+ }
+ } else {
+ /*
+ * Disconnect if we want to listen
+ * for responses from more than one server.
+ */
+ if (connected) {
+#ifdef CAN_RECONNECT
+ struct sockaddr_in no_addr;
+
+ no_addr.sin_family = AF_INET;
+ no_addr.sin_addr.s_addr = INADDR_ANY;
+ no_addr.sin_port = 0;
+ (void) connect(s,
+ (struct sockaddr *)
+ &no_addr,
+ sizeof no_addr);
+#else
+ int s1 = socket(PF_INET, SOCK_DGRAM,0);
+ if (s1 < 0)
+ goto bad_dg_sock;
+ (void) dup2(s1, s);
+ (void) close(s1);
+ Dprint(_res.options & RES_DEBUG,
+ (stdout, ";; new DG socket\n"))
+#endif /* CAN_RECONNECT */
+ connected = 0;
+ errno = 0;
+ }
+#endif /* !CANNOT_CONNECT_DGRAM */
+ if (sendto(s, (char*)buf, buflen, 0,
+ (struct sockaddr *)nsap,
+ sizeof *nsap)
+ != buflen) {
+ Aerror(stderr, "sendto", errno, *nsap);
+ badns |= (1 << ns);
+ res_close();
+ goto next_ns;
+ }
+#ifndef CANNOT_CONNECT_DGRAM
+ }
+#endif /* !CANNOT_CONNECT_DGRAM */
+
+ /*
+ * Wait for reply
+ */
+#ifndef NOPOLL
+ othersyscall:
+ if (use_poll) {
+ msec = (_res.retrans << try) * 1000;
+ if (try > 0)
+ msec /= _res.nscount;
+ if (msec <= 0)
+ msec = 1000;
+ } else {
+#endif
+ timeout.tv_sec = (_res.retrans << try);
+ if (try > 0)
+ timeout.tv_sec /= _res.nscount;
+ if ((long) timeout.tv_sec <= 0)
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
+#ifndef NOPOLL
+ }
+#endif
+ wait:
+ if (s < 0) {
+ Perror(stderr, "s out-of-bounds", EMFILE);
+ res_close();
+ goto next_ns;
+ }
+#ifndef NOPOLL
+ if (use_poll) {
+ struct sigaction sa, osa;
+ int sigsys_installed = 0;
+
+ pfd.fd = s;
+ pfd.events = POLLIN;
+ if (use_poll == 1) {
+ bzero(&sa, sizeof(sa));
+ sa.sa_handler = SIG_IGN;
+ if (sigaction(SIGSYS, &sa, &osa) >= 0)
+ sigsys_installed = 1;
+ }
+ n = poll(&pfd, 1, msec);
+ if (sigsys_installed == 1) {
+ int oerrno = errno;
+ sigaction(SIGSYS, &osa, NULL);
+ errno = oerrno;
+ }
+ /* XXX why does nosys() return EINVAL? */
+ if (n < 0 && (errno == ENOSYS ||
+ errno == EINVAL)) {
+ use_poll = 0;
+ goto othersyscall;
+ } else if (use_poll == 1)
+ use_poll = 2;
+ if (n < 0) {
+ if (errno == EINTR)
+ goto wait;
+ Perror(stderr, "poll", errno);
+ res_close();
+ goto next_ns;
+ }
+ } else {
+#endif
+#ifndef NOSELECT
+ dsmasklen = howmany(s + 1, NFDBITS) *
+ sizeof(fd_mask);
+ if (dsmasklen > sizeof(fd_set)) {
+ dsmaskp = (fd_set *)malloc(dsmasklen);
+ if (dsmaskp == NULL) {
+ res_close();
+ goto next_ns;
+ }
+ } else
+ dsmaskp = &dsmask;
+ /* only zero what we need */
+ bzero((char *)dsmaskp, dsmasklen);
+ FD_SET(s, dsmaskp);
+ n = select(s + 1, dsmaskp, (fd_set *)NULL,
+ (fd_set *)NULL, &timeout);
+ if (dsmaskp != &dsmask)
+ free(dsmaskp);
+ if (n < 0) {
+ if (errno == EINTR)
+ goto wait;
+ Perror(stderr, "select", errno);
+ res_close();
+ goto next_ns;
+ }
+#endif
+#ifndef NOPOLL
+ }
+#endif
+
+#ifdef NOSELECT
+ setsockopt (s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof timeout);
+#else
+ if (n == 0) {
+ /*
+ * timeout
+ */
+ Dprint(_res.options & RES_DEBUG,
+ (stdout, ";; timeout\n"));
+ gotsomewhere = 1;
+ res_close();
+ goto next_ns;
+ }
+#endif
+ errno = 0;
+ fromlen = sizeof(struct sockaddr_in);
+ resplen = recvfrom(s, (char*)ans, anssiz, 0,
+ (struct sockaddr *)&from, &fromlen);
+ if (resplen <= 0) {
+#ifdef NOSELECT
+ if (errno == ETIMEDOUT) {
+ Dprint(_res.options & RES_DEBUG,
+ (stdout, ";; timeout\n"));
+ gotsomewhere = 1;
+ res_close();
+ goto next_ns;
+ }
+#endif
+ Perror(stderr, "recvfrom", errno);
+ res_close();
+ goto next_ns;
+ }
+ gotsomewhere = 1;
+ if (resplen < HFIXEDSZ) {
+ /*
+ * Undersized message.
+ */
+ Dprint(_res.options & RES_DEBUG,
+ (stdout, ";; undersized: %d\n",
+ resplen));
+ terrno = EMSGSIZE;
+ badns |= (1 << ns);
+ res_close();
+ goto next_ns;
+ }
+ if (hp->id != anhp->id) {
+ /*
+ * response from old query, ignore it.
+ * XXX - potential security hazard could
+ * be detected here.
+ */
+ DprintQ((_res.options & RES_DEBUG) ||
+ (_res.pfcode & RES_PRF_REPLY),
+ (stdout, ";; old answer:\n"),
+ ans, (resplen>anssiz)?anssiz:resplen);
+ goto wait;
+ }
+#ifdef CHECK_SRVR_ADDR
+ if (!(_res.options & RES_INSECURE1) &&
+ !res_isourserver(&from)) {
+ /*
+ * response from wrong server? ignore it.
+ * XXX - potential security hazard could
+ * be detected here.
+ */
+ DprintQ((_res.options & RES_DEBUG) ||
+ (_res.pfcode & RES_PRF_REPLY),
+ (stdout, ";; not our server:\n"),
+ ans, (resplen>anssiz)?anssiz:resplen);
+ goto wait;
+ }
+#endif
+ if (!(_res.options & RES_INSECURE2) &&
+ !res_queriesmatch(buf, buf + buflen,
+ ans, ans + anssiz)) {
+ /*
+ * response contains wrong query? ignore it.
+ * XXX - potential security hazard could
+ * be detected here.
+ */
+ DprintQ((_res.options & RES_DEBUG) ||
+ (_res.pfcode & RES_PRF_REPLY),
+ (stdout, ";; wrong query name:\n"),
+ ans, (resplen>anssiz)?anssiz:resplen);
+ goto wait;
+ }
+ if (anhp->rcode == SERVFAIL ||
+ anhp->rcode == NOTIMP ||
+ anhp->rcode == REFUSED) {
+ DprintQ(_res.options & RES_DEBUG,
+ (stdout, "server rejected query:\n"),
+ ans, (resplen>anssiz)?anssiz:resplen);
+ badns |= (1 << ns);
+ res_close();
+ /* don't retry if called from dig */
+ if (!_res.pfcode)
+ goto next_ns;
+ }
+ if (!(_res.options & RES_IGNTC) && anhp->tc) {
+ /*
+ * get rest of answer;
+ * use TCP with same server.
+ */
+ Dprint(_res.options & RES_DEBUG,
+ (stdout, ";; truncated answer\n"));
+ v_circuit = 1;
+ res_close();
+ goto same_ns;
+ }
+ } /*if vc/dg*/
+ Dprint((_res.options & RES_DEBUG) ||
+ ((_res.pfcode & RES_PRF_REPLY) &&
+ (_res.pfcode & RES_PRF_HEAD1)),
+ (stdout, ";; got answer:\n"));
+ DprintQ((_res.options & RES_DEBUG) ||
+ (_res.pfcode & RES_PRF_REPLY),
+ (stdout, "%s", ""),
+ ans, (resplen>anssiz)?anssiz:resplen);
+ /*
+ * If using virtual circuits, we assume that the first server
+ * is preferred over the rest (i.e. it is on the local
+ * machine) and only keep that one open.
+ * If we have temporarily opened a virtual circuit,
+ * or if we haven't been asked to keep a socket open,
+ * close the socket.
+ */
+ if ((v_circuit && (!(_res.options & RES_USEVC) || ns != 0)) ||
+ !(_res.options & RES_STAYOPEN)) {
+ res_close();
+ }
+ if (Rhook) {
+ int done = 0, loops = 0;
+
+ do {
+ res_sendhookact act;
+
+ act = (*Rhook)(nsap, buf, buflen,
+ ans, anssiz, &resplen);
+ switch (act) {
+ case res_goahead:
+ case res_done:
+ done = 1;
+ break;
+ case res_nextns:
+ res_close();
+ goto next_ns;
+ case res_modified:
+ /* give the hook another try */
+ if (++loops < 42) /*doug adams*/
+ break;
+ /*FALLTHROUGH*/
+ case res_error:
+ /*FALLTHROUGH*/
+ default:
+ return (-1);
+ }
+ } while (!done);
+
+ }
+ return (resplen);
+ next_ns: ;
+ } /*foreach ns*/
+ } /*foreach retry*/
+ res_close();
+ if (!v_circuit) {
+ if (!gotsomewhere)
+ errno = ECONNREFUSED; /* no nameservers found */
+ else
+ errno = ETIMEDOUT; /* no answer obtained */
+ } else
+ errno = terrno;
+ return (-1);
+}
+
+/*
+ * This routine is for closing the socket if a virtual circuit is used and
+ * the program wants to close it. This provides support for endhostent()
+ * which expects to close the socket.
+ *
+ * This routine is not expected to be user visible.
+ */
+void
+res_close()
+{
+ if (s >= 0) {
+ (void) close(s);
+ s = -1;
+ connected = 0;
+ vc = 0;
+ }
+}
diff --git a/cpukit/libnetworking/libc/res_stubs.c b/cpukit/libnetworking/libc/res_stubs.c
new file mode 100644
index 0000000000..92cf0fac54
--- /dev/null
+++ b/cpukit/libnetworking/libc/res_stubs.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 1996 Peter Wemm <peter@freebsd.org>.
+ * 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.
+ *
+ * $Id$
+ */
+
+/*
+ * This file is for FreeBSD-3.0 that has a bind-4.9.5-P1 derived
+ * resolver in the libc. It provides aliases for functions that
+ * have moved since 4.9.4-P1.
+ *
+ * I'll save everybody the trouble and say it now: *THIS IS A HACK*!
+ *
+ * Yes, many of these are private functions to the resolver, but some are
+ * needed as there is no other way to provide the functionality and they've
+ * turned up all over the place. :-(
+ */
+
+#include <sys/types.h>
+#include <sys/cdefs.h>
+
+__weak_reference(__inet_addr, inet_addr);
+__weak_reference(__inet_aton, inet_aton);
+__weak_reference(__inet_lnaof, inet_lnaof);
+__weak_reference(__inet_makeaddr, inet_makeaddr);
+__weak_reference(__inet_neta, inet_neta);
+__weak_reference(__inet_netof, inet_netof);
+__weak_reference(__inet_network, inet_network);
+__weak_reference(__inet_net_ntop, inet_net_ntop);
+__weak_reference(__inet_net_pton, inet_net_pton);
+__weak_reference(__inet_ntoa, inet_ntoa);
+__weak_reference(__inet_pton, inet_pton);
+__weak_reference(__inet_ntop, inet_ntop);
+__weak_reference(__inet_nsap_addr, inet_nsap_addr);
+__weak_reference(__inet_nsap_ntoa, inet_nsap_ntoa);
+
+__weak_reference(__sym_ston, sym_ston);
+__weak_reference(__sym_ntos, sym_ntos);
+__weak_reference(__sym_ntop, sym_ntop);
+__weak_reference(__fp_resstat, fp_resstat);
+__weak_reference(__p_query, p_query);
+__weak_reference(__p_fqnname, p_fqnname);
+__weak_reference(__p_secstodate, p_secstodate);
+__weak_reference(__dn_count_labels, dn_count_labels);
+__weak_reference(__dn_comp, dn_comp);
+__weak_reference(__res_close, _res_close);
+__weak_reference(__dn_expand, dn_expand);
+__weak_reference(__res_init, res_init);
+__weak_reference(__res_query, res_query);
+__weak_reference(__res_search, res_search);
+__weak_reference(__res_querydomain, res_querydomain);
+__weak_reference(__res_mkquery, res_mkquery);
+__weak_reference(__res_send, res_send);
diff --git a/cpukit/libnetworking/libc/res_update.c b/cpukit/libnetworking/libc/res_update.c
new file mode 100644
index 0000000000..ef591e0674
--- /dev/null
+++ b/cpukit/libnetworking/libc/res_update.c
@@ -0,0 +1,518 @@
+#if !defined(__rtems__)
+#if !defined(lint) && !defined(SABER)
+static char rcsid[] = "$Id$";
+#endif /* not lint */
+#endif /* not rtems */
+
+/*
+ * Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ */
+
+/*
+ * Based on the Dynamic DNS reference implementation by Viraj Bais
+ * <viraj_bais@ccm.fm.intel.com>
+ */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <errno.h>
+#include <limits.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * Separate a linked list of records into groups so that all records
+ * in a group will belong to a single zone on the nameserver.
+ * Create a dynamic update packet for each zone and send it to the
+ * nameservers for that zone, and await answer.
+ * Abort if error occurs in updating any zone.
+ * Return the number of zones updated on success, < 0 on error.
+ *
+ * On error, caller must deal with the unsynchronized zones
+ * eg. an A record might have been successfully added to the forward
+ * zone but the corresponding PTR record would be missing if error
+ * was encountered while updating the reverse zone.
+ */
+
+#define NSMAX 16
+
+struct ns1 {
+ char nsname[MAXDNAME];
+ struct in_addr nsaddr1;
+};
+
+struct zonegrp {
+ char z_origin[MAXDNAME];
+ int16_t z_class;
+ char z_soardata[MAXDNAME + 5 * INT32SZ];
+ struct ns1 z_ns[NSMAX];
+ int z_nscount;
+ ns_updrec * z_rr;
+ struct zonegrp *z_next;
+};
+
+
+int
+res_update(ns_updrec *rrecp_in) {
+ ns_updrec *rrecp, *tmprrecp;
+ u_char buf[PACKETSZ], answer[PACKETSZ], packet[2*PACKETSZ];
+ char name[MAXDNAME], zname[MAXDNAME], primary[MAXDNAME],
+ mailaddr[MAXDNAME];
+ u_char soardata[2*MAXCDNAME+5*INT32SZ];
+ char *dname, *svdname, *cp1, *target;
+ u_char *cp, *eom;
+ HEADER *hp = (HEADER *) answer;
+ struct zonegrp *zptr = NULL, *tmpzptr, *prevzptr, *zgrp_start = NULL;
+ int i, j, k = 0, n, ancount, nscount, arcount, rcode, rdatasize,
+ newgroup, done, myzone, seen_before, numzones = 0;
+ u_int16_t dlen, class, qclass, type, qtype;
+ u_int32_t ttl;
+
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
+ h_errno = NETDB_INTERNAL;
+ return (-1);
+ }
+
+ for (rrecp = rrecp_in; rrecp; rrecp = rrecp->r_next) {
+ dname = rrecp->r_dname;
+ n = strlen(dname);
+ if (dname[n-1] == '.')
+ dname[n-1] = '\0';
+ qtype = T_SOA;
+ qclass = rrecp->r_class;
+ done = 0;
+ seen_before = 0;
+
+ while (!done && dname) {
+ if (qtype == T_SOA) {
+ for (tmpzptr = zgrp_start;
+ tmpzptr && !seen_before;
+ tmpzptr = tmpzptr->z_next) {
+ if (strcasecmp(dname,
+ tmpzptr->z_origin) == 0 &&
+ tmpzptr->z_class == qclass)
+ seen_before++;
+ for (tmprrecp = tmpzptr->z_rr;
+ tmprrecp && !seen_before;
+ tmprrecp = tmprrecp->r_grpnext)
+ if (strcasecmp(dname, tmprrecp->r_dname) == 0
+ && tmprrecp->r_class == qclass) {
+ seen_before++;
+ break;
+ }
+ if (seen_before) {
+ /*
+ * Append to the end of
+ * current group.
+ */
+ for (tmprrecp = tmpzptr->z_rr;
+ tmprrecp->r_grpnext;
+ tmprrecp = tmprrecp->r_grpnext)
+ (void)NULL;
+ tmprrecp->r_grpnext = rrecp;
+ rrecp->r_grpnext = NULL;
+ done = 1;
+ break;
+ }
+ }
+ } else if (qtype == T_A) {
+ for (tmpzptr = zgrp_start;
+ tmpzptr && !done;
+ tmpzptr = tmpzptr->z_next)
+ for (i = 0; i < tmpzptr->z_nscount; i++)
+ if (tmpzptr->z_class == qclass &&
+ strcasecmp(tmpzptr->z_ns[i].nsname,
+ dname) == 0 &&
+ tmpzptr->z_ns[i].nsaddr1.s_addr != 0) {
+ zptr->z_ns[k].nsaddr1.s_addr =
+ tmpzptr->z_ns[i].nsaddr1.s_addr;
+ done = 1;
+ break;
+ }
+ }
+ if (done)
+ break;
+ n = res_mkquery(QUERY, dname, qclass, qtype, NULL,
+ 0, NULL, buf, sizeof buf);
+ if (n <= 0) {
+ fprintf(stderr, "res_update: mkquery failed\n");
+ return (n);
+ }
+ n = res_send(buf, n, answer, sizeof answer);
+ if (n < 0) {
+ fprintf(stderr, "res_update: send error for %s\n",
+ rrecp->r_dname);
+ return (n);
+ }
+ if (n < HFIXEDSZ)
+ return (-1);
+ ancount = ntohs(hp->ancount);
+ nscount = ntohs(hp->nscount);
+ arcount = ntohs(hp->arcount);
+ rcode = hp->rcode;
+ cp = answer + HFIXEDSZ;
+ eom = answer + n;
+ /* skip the question section */
+ n = dn_skipname(cp, eom);
+ if (n < 0 || cp + n + 2 * INT16SZ > eom)
+ return (-1);
+ cp += n + 2 * INT16SZ;
+
+ if (qtype == T_SOA) {
+ if (ancount == 0 && nscount == 0 && arcount == 0) {
+ /*
+ * if (rcode == NOERROR) then the dname exists but
+ * has no soa record associated with it.
+ * if (rcode == NXDOMAIN) then the dname does not
+ * exist and the server is replying out of NCACHE.
+ * in either case, proceed with the next try
+ */
+ dname = strchr(dname, '.');
+ if (dname != NULL)
+ dname++;
+ continue;
+ } else if ((rcode == NOERROR || rcode == NXDOMAIN) &&
+ ancount == 0 &&
+ nscount == 1 && arcount == 0) {
+ /*
+ * name/data does not exist, soa record supplied in the
+ * authority section
+ */
+ /* authority section must contain the soa record */
+ if ((n = dn_expand(answer, eom, cp, zname,
+ sizeof zname)) < 0)
+ return (n);
+ cp += n;
+ if (cp + 2 * INT16SZ > eom)
+ return (-1);
+ GETSHORT(type, cp);
+ GETSHORT(class, cp);
+ if (type != T_SOA || class != qclass) {
+ fprintf(stderr, "unknown answer\n");
+ return (-1);
+ }
+ myzone = 0;
+ svdname = dname;
+ while (dname)
+ if (strcasecmp(dname, zname) == 0) {
+ myzone = 1;
+ break;
+ } else if ((dname = strchr(dname, '.')) != NULL)
+ dname++;
+ if (!myzone) {
+ dname = strchr(svdname, '.');
+ if (dname != NULL)
+ dname++;
+ continue;
+ }
+ nscount = 0;
+ /* fallthrough */
+ } else if (rcode == NOERROR && ancount == 1) {
+ /*
+ * found the zone name
+ * new servers will supply NS records for the zone
+ * in authority section and A records for those
+ * nameservers in the additional section
+ * older servers have to be explicitly queried for
+ * NS records for the zone
+ */
+ /* answer section must contain the soa record */
+ if ((n = dn_expand(answer, eom, cp, zname,
+ sizeof zname)) < 0)
+ return (n);
+ else
+ cp += n;
+ if (cp + 2 * INT16SZ > eom)
+ return (-1);
+ GETSHORT(type, cp);
+ GETSHORT(class, cp);
+ if (type == T_CNAME) {
+ dname = strchr(dname, '.');
+ if (dname != NULL)
+ dname++;
+ continue;
+ }
+ if (strcasecmp(dname, zname) != 0 ||
+ type != T_SOA ||
+ class != rrecp->r_class) {
+ fprintf(stderr, "unknown answer\n");
+ return (-1);
+ }
+ /* FALLTHROUGH */
+ } else {
+ fprintf(stderr,
+ "unknown response: ans=%d, auth=%d, add=%d, rcode=%d\n",
+ ancount, nscount, arcount, hp->rcode);
+ return (-1);
+ }
+ if (cp + INT32SZ + INT16SZ > eom)
+ return (-1);
+ /* continue processing the soa record */
+ GETLONG(ttl, cp);
+ GETSHORT(dlen, cp);
+ if (cp + dlen > eom)
+ return (-1);
+ newgroup = 1;
+ zptr = zgrp_start;
+ prevzptr = NULL;
+ while (zptr) {
+ if (strcasecmp(zname, zptr->z_origin) == 0 &&
+ type == T_SOA && class == qclass) {
+ newgroup = 0;
+ break;
+ }
+ prevzptr = zptr;
+ zptr = zptr->z_next;
+ }
+ if (!newgroup) {
+ for (tmprrecp = zptr->z_rr;
+ tmprrecp->r_grpnext;
+ tmprrecp = tmprrecp->r_grpnext)
+ ;
+ tmprrecp->r_grpnext = rrecp;
+ rrecp->r_grpnext = NULL;
+ done = 1;
+ cp += dlen;
+ break;
+ } else {
+ if ((n = dn_expand(answer, eom, cp, primary,
+ sizeof primary)) < 0)
+ return (n);
+ cp += n;
+ /*
+ * We don't have to bounds check here because the
+ * next use of 'cp' is in dn_expand().
+ */
+ cp1 = (char *)soardata;
+ strcpy(cp1, primary);
+ cp1 += strlen(cp1) + 1;
+ if ((n = dn_expand(answer, eom, cp, mailaddr,
+ sizeof mailaddr)) < 0)
+ return (n);
+ cp += n;
+ strcpy(cp1, mailaddr);
+ cp1 += strlen(cp1) + 1;
+ if (cp + 5*INT32SZ > eom)
+ return (-1);
+ memcpy(cp1, cp, 5*INT32SZ);
+ cp += 5*INT32SZ;
+ cp1 += 5*INT32SZ;
+ rdatasize = (u_char *)cp1 - soardata;
+ zptr = calloc(1, sizeof(struct zonegrp));
+ if (zptr == NULL)
+ return (-1);
+ if (zgrp_start == NULL)
+ zgrp_start = zptr;
+ else
+ prevzptr->z_next = zptr;
+ zptr->z_rr = rrecp;
+ rrecp->r_grpnext = NULL;
+ strcpy(zptr->z_origin, zname);
+ zptr->z_class = class;
+ memcpy(zptr->z_soardata, soardata, rdatasize);
+ /* fallthrough to process NS and A records */
+ }
+ } else if (qtype == T_NS) {
+ if (rcode == NOERROR && ancount > 0) {
+ strcpy(zname, dname);
+ for (zptr = zgrp_start; zptr; zptr = zptr->z_next) {
+ if (strcasecmp(zname, zptr->z_origin) == 0)
+ break;
+ }
+ if (zptr == NULL)
+ /* should not happen */
+ return (-1);
+ if (nscount > 0) {
+ /*
+ * answer and authority sections contain
+ * the same information, skip answer section
+ */
+ for (j = 0; j < ancount; j++) {
+ n = dn_skipname(cp, eom);
+ if (n < 0)
+ return (-1);
+ n += 2*INT16SZ + INT32SZ;
+ if (cp + n + INT16SZ > eom)
+ return (-1);
+ cp += n;
+ GETSHORT(dlen, cp);
+ cp += dlen;
+ }
+ } else
+ nscount = ancount;
+ /* fallthrough to process NS and A records */
+ } else {
+ fprintf(stderr, "cannot determine nameservers for %s:\
+ans=%d, auth=%d, add=%d, rcode=%d\n",
+ dname, ancount, nscount, arcount, hp->rcode);
+ return (-1);
+ }
+ } else if (qtype == T_A) {
+ if (rcode == NOERROR && ancount > 0) {
+ arcount = ancount;
+ ancount = nscount = 0;
+ /* fallthrough to process A records */
+ } else {
+ fprintf(stderr, "cannot determine address for %s:\
+ans=%d, auth=%d, add=%d, rcode=%d\n",
+ dname, ancount, nscount, arcount, hp->rcode);
+ return (-1);
+ }
+ }
+ /* process NS records for the zone */
+ j = 0;
+ for (i = 0; i < nscount; i++) {
+ if ((n = dn_expand(answer, eom, cp, name,
+ sizeof name)) < 0)
+ return (n);
+ cp += n;
+ if (cp + 3 * INT16SZ + INT32SZ > eom)
+ return (-1);
+ GETSHORT(type, cp);
+ GETSHORT(class, cp);
+ GETLONG(ttl, cp);
+ GETSHORT(dlen, cp);
+ if (cp + dlen > eom)
+ return (-1);
+ if (strcasecmp(name, zname) == 0 &&
+ type == T_NS && class == qclass) {
+ if ((n = dn_expand(answer, eom, cp,
+ name, sizeof name)) < 0)
+ return (n);
+ target = zptr->z_ns[j++].nsname;
+ strcpy(target, name);
+ }
+ cp += dlen;
+ }
+ if (zptr->z_nscount == 0)
+ zptr->z_nscount = j;
+ /* get addresses for the nameservers */
+ for (i = 0; i < arcount; i++) {
+ if ((n = dn_expand(answer, eom, cp, name,
+ sizeof name)) < 0)
+ return (n);
+ cp += n;
+ if (cp + 3 * INT16SZ + INT32SZ > eom)
+ return (-1);
+ GETSHORT(type, cp);
+ GETSHORT(class, cp);
+ GETLONG(ttl, cp);
+ GETSHORT(dlen, cp);
+ if (cp + dlen > eom)
+ return (-1);
+ if (type == T_A && dlen == INT32SZ && class == qclass) {
+ for (j = 0; j < zptr->z_nscount; j++)
+ if (strcasecmp(name, zptr->z_ns[j].nsname) == 0) {
+ memcpy(&zptr->z_ns[j].nsaddr1.s_addr, cp,
+ INT32SZ);
+ break;
+ }
+ }
+ cp += dlen;
+ }
+ if (zptr->z_nscount == 0) {
+ dname = zname;
+ qtype = T_NS;
+ continue;
+ }
+ done = 1;
+ for (k = 0; k < zptr->z_nscount; k++)
+ if (zptr->z_ns[k].nsaddr1.s_addr == 0) {
+ done = 0;
+ dname = zptr->z_ns[k].nsname;
+ qtype = T_A;
+ }
+
+ } /* while */
+ }
+
+ _res.options |= RES_DEBUG;
+ for (zptr = zgrp_start; zptr; zptr = zptr->z_next) {
+
+ /* append zone section */
+ rrecp = res_mkupdrec(ns_s_zn, zptr->z_origin,
+ zptr->z_class, ns_t_soa, 0);
+ if (rrecp == NULL) {
+ fprintf(stderr, "saverrec error\n");
+ fflush(stderr);
+ return (-1);
+ }
+ rrecp->r_grpnext = zptr->z_rr;
+ zptr->z_rr = rrecp;
+
+ n = res_mkupdate(zptr->z_rr, packet, sizeof packet);
+ if (n < 0) {
+ fprintf(stderr, "res_mkupdate error\n");
+ fflush(stderr);
+ return (-1);
+ } else
+ fprintf(stdout, "res_mkupdate: packet size = %d\n", n);
+
+ /*
+ * Override the list of NS records from res_init() with
+ * the authoritative nameservers for the zone being updated.
+ * Sort primary to be the first in the list of nameservers.
+ */
+ for (i = 0; i < zptr->z_nscount; i++) {
+ if (strcasecmp(zptr->z_ns[i].nsname,
+ zptr->z_soardata) == 0) {
+ struct in_addr tmpaddr;
+
+ if (i != 0) {
+ strcpy(zptr->z_ns[i].nsname,
+ zptr->z_ns[0].nsname);
+ strcpy(zptr->z_ns[0].nsname,
+ zptr->z_soardata);
+ tmpaddr = zptr->z_ns[i].nsaddr1;
+ zptr->z_ns[i].nsaddr1 =
+ zptr->z_ns[0].nsaddr1;
+ zptr->z_ns[0].nsaddr1 = tmpaddr;
+ }
+ break;
+ }
+ }
+ for (i = 0; i < MAXNS; i++) {
+ _res.nsaddr_list[i].sin_addr = zptr->z_ns[i].nsaddr1;
+ _res.nsaddr_list[i].sin_family = AF_INET;
+ _res.nsaddr_list[i].sin_port = htons(NAMESERVER_PORT);
+ }
+ _res.nscount = (zptr->z_nscount < MAXNS) ?
+ zptr->z_nscount : MAXNS;
+ n = res_send(packet, n, answer, sizeof(answer));
+ if (n < 0) {
+ fprintf(stderr, "res_send: send error, n=%d\n", n);
+ break;
+ } else
+ numzones++;
+ }
+
+ /* free malloc'ed memory */
+ while(zgrp_start) {
+ zptr = zgrp_start;
+ zgrp_start = zgrp_start->z_next;
+ res_freeupdrec(zptr->z_rr); /* Zone section we allocated. */
+ free((char *)zptr);
+ }
+
+ return (numzones);
+}
diff --git a/cpukit/libnetworking/libc/resolver.3 b/cpukit/libnetworking/libc/resolver.3
new file mode 100644
index 0000000000..8c6f18334f
--- /dev/null
+++ b/cpukit/libnetworking/libc/resolver.3
@@ -0,0 +1,352 @@
+.\" Copyright (c) 1985, 1991, 1993
+.\" The Regents of the University of California. 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 the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+.\"
+.\" @(#)resolver.3 8.1 (Berkeley) 6/4/93
+.\" $Id$
+.\"
+.Dd June 4, 1993
+.Dt RESOLVER 3
+.Os BSD 4.3
+.Sh NAME
+.Nm res_query ,
+.Nm res_search ,
+.Nm res_mkquery ,
+.Nm res_send ,
+.Nm res_init ,
+.Nm dn_comp ,
+.Nm dn_expand
+.Nd resolver routines
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <netinet/in.h>
+.Fd #include <arpa/nameser.h>
+.Fd #include <resolv.h>
+.Ft int
+.Fo res_query
+.Fa "const char *dname"
+.Fa "int class"
+.Fa "int type"
+.Fa "u_char *answer"
+.Fa "int anslen"
+.Fc
+.Ft int
+.Fo res_search
+.Fa "const char *dname"
+.Fa "int class"
+.Fa "int type"
+.Fa "u_char *answer"
+.Fa "int anslen"
+.Fc
+.Ft int
+.Fo res_mkquery
+.Fa "int op"
+.Fa "const char *dname"
+.Fa "int class"
+.Fa "int type"
+.Fa "const u_char *data"
+.Fa "int datalen"
+.Fa "const u_char *newrr_in"
+.Fa "u_char *buf"
+.Fa "int buflen"
+.Fc
+.Ft int
+.Fo res_send
+.Fa "const u_char *msg"
+.Fa "int msglen"
+.Fa "u_char *answer"
+.Fa "int anslen"
+.Fc
+.Ft int
+.Fn res_init
+.Fo dn_comp
+.Fa "const char *exp_dn"
+.Fa "u_char *comp_dn"
+.Fa "int length"
+.Fa "u_char **dnptrs"
+.Fa "u_char **lastdnptr"
+.Fc
+.Ft int
+.Fo dn_expand
+.Fa "const u_char *msg"
+.Fa "const u_char *eomorig"
+.Fa "const u_char *comp_dn"
+.Fa "char *exp_dn"
+.Fa "int length"
+.Fc
+.Sh DESCRIPTION
+These routines are used for making, sending and interpreting
+query and reply messages with Internet domain name servers.
+.Pp
+Global configuration and state information that is used by the
+resolver routines is kept in the structure
+.Em _res .
+Most of the values have reasonable defaults and can be ignored.
+Options
+stored in
+.Em _res.options
+are defined in
+.Pa resolv.h
+and are as follows.
+Options are stored as a simple bit mask containing the bitwise ``or''
+of the options enabled.
+.Bl -tag -width RES_DEFNAMES
+.It Dv RES_INIT
+True if the initial name server address and default domain name are
+initialized (i.e.,
+.Fn res_init
+has been called).
+.It Dv RES_DEBUG
+Print debugging messages.
+.It Dv RES_AAONLY
+Accept authoritative answers only.
+With this option,
+.Fn res_send
+should continue until it finds an authoritative answer or finds an error.
+Currently this is not implemented.
+.It Dv RES_USEVC
+Use
+.Tn TCP
+connections for queries instead of
+.Tn UDP
+datagrams.
+.It Dv RES_STAYOPEN
+Used with
+.Dv RES_USEVC
+to keep the
+.Tn TCP
+connection open between
+queries.
+This is useful only in programs that regularly do many queries.
+.Tn UDP
+should be the normal mode used.
+.It Dv RES_IGNTC
+Unused currently (ignore truncation errors, i.e., don't retry with
+.Tn TCP ) .
+.It Dv RES_RECURSE
+Set the recursion-desired bit in queries.
+This is the default.
+.Pf ( Fn res_send
+does not do iterative queries and expects the name server
+to handle recursion.)
+.It Dv RES_DEFNAMES
+If set,
+.Fn res_search
+will append the default domain name to single-component names
+(those that do not contain a dot).
+This option is enabled by default.
+.It Dv RES_DNSRCH
+If this option is set,
+.Fn res_search
+will search for host names in the current domain and in parent domains; see
+.Xr hostname 7 .
+This is used by the standard host lookup routine
+.Xr gethostbyname 3 .
+This option is enabled by default.
+.It Dv RES_NOALIASES
+This option turns off the user level aliasing feature controlled by the
+.Dq Ev HOSTALIASES
+environment variable. Network daemons should set this option.
+.El
+.Pp
+The
+.Fn res_init
+routine
+reads the configuration file (if any; see
+.Xr resolver 5 )
+to get the default domain name,
+search list and
+the Internet address of the local name server(s).
+If no server is configured, the host running
+the resolver is tried.
+The current domain name is defined by the hostname
+if not specified in the configuration file;
+it can be overridden by the environment variable
+.Ev LOCALDOMAIN .
+This environment variable may contain several blank-separated
+tokens if you wish to override the
+.Em "search list"
+on a per-process basis. This is similar to the
+.Em search
+command in the configuration file.
+Another environment variable (
+.Dq Ev RES_OPTIONS
+can be set to
+override certain internal resolver options which are otherwise
+set by changing fields in the
+.Em _res
+structure or are inherited from the configuration file's
+.Em options
+command. The syntax of the
+.Dq Ev RES_OPTIONS
+environment variable is explained in
+.Xr resolver 5 .
+Initialization normally occurs on the first call
+to one of the following routines.
+.Pp
+The
+.Fn res_query
+function provides an interface to the server query mechanism.
+It constructs a query, sends it to the local server,
+awaits a response, and makes preliminary checks on the reply.
+The query requests information of the specified
+.Fa type
+and
+.Fa class
+for the specified fully-qualified domain name
+.Fa dname .
+The reply message is left in the
+.Fa answer
+buffer with length
+.Fa anslen
+supplied by the caller.
+.Pp
+The
+.Fn res_search
+routine makes a query and awaits a response like
+.Fn res_query ,
+but in addition, it implements the default and search rules
+controlled by the
+.Dv RES_DEFNAMES
+and
+.Dv RES_DNSRCH
+options.
+It returns the first successful reply.
+.Pp
+The remaining routines are lower-level routines used by
+.Fn res_query .
+The
+.Fn res_mkquery
+function
+constructs a standard query message and places it in
+.Fa buf .
+It returns the size of the query, or \-1 if the query is
+larger than
+.Fa buflen .
+The query type
+.Fa op
+is usually
+.Dv QUERY ,
+but can be any of the query types defined in
+.Aq Pa arpa/nameser.h .
+The domain name for the query is given by
+.Fa dname .
+.Fa Newrr
+is currently unused but is intended for making update messages.
+.Pp
+The
+.Fn res_send
+routine
+sends a pre-formatted query and returns an answer.
+It will call
+.Fn res_init
+if
+.Dv RES_INIT
+is not set, send the query to the local name server, and
+handle timeouts and retries.
+The length of the reply message is returned, or
+\-1 if there were errors.
+.Pp
+The
+.Fn dn_comp
+function
+compresses the domain name
+.Fa exp_dn
+and stores it in
+.Fa comp_dn .
+The size of the compressed name is returned or \-1 if there were errors.
+The size of the array pointed to by
+.Fa comp_dn
+is given by
+.Fa length .
+The compression uses
+an array of pointers
+.Fa dnptrs
+to previously-compressed names in the current message.
+The first pointer points to
+to the beginning of the message and the list ends with
+.Dv NULL .
+The limit to the array is specified by
+.Fa lastdnptr .
+A side effect of
+.Fn dn_comp
+is to update the list of pointers for
+labels inserted into the message
+as the name is compressed.
+If
+.Em dnptr
+is
+.Dv NULL, names are not compressed.
+If
+.Fa lastdnptr
+is
+.Dv NULL ,
+the list of labels is not updated.
+.Pp
+The
+.Fn dn_expand
+entry
+expands the compressed domain name
+.Fa comp_dn
+to a full domain name
+The compressed name is contained in a query or reply message;
+.Fa msg
+is a pointer to the beginning of the message.
+The uncompressed name is placed in the buffer indicated by
+.Fa exp_dn
+which is of size
+.Fa length .
+The size of compressed name is returned or \-1 if there was an error.
+.Sh FILES
+.Bl -tag -width Pa
+/etc/resolv.conf
+The configuration file
+see
+.Xr resolver 5 .
+.El
+.Sh SEE ALSO
+.Xr gethostbyname 3 ,
+.Xr resolver 5 ,
+.Xr hostname 7 ,
+.Xr named 8
+.Pp
+.%T RFC1032 ,
+.%T RFC1033 ,
+.%T RFC1034 ,
+.%T RFC1035 ,
+.%T RFC974
+.Rs
+.%T "Name Server Operations Guide for BIND"
+.Re
+.Sh HISTORY
+The
+.Nm
+function appeared in
+.Bx 4.3 .
diff --git a/cpukit/libnetworking/libc/send.c b/cpukit/libnetworking/libc/send.c
new file mode 100644
index 0000000000..ad14bd3cd2
--- /dev/null
+++ b/cpukit/libnetworking/libc/send.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)send.c 8.2 (Berkeley) 2/21/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <stddef.h>
+
+ssize_t
+send(s, msg, len, flags)
+ int s, flags;
+ size_t len;
+ const void *msg;
+{
+ return (sendto(s, msg, len, flags, NULL, 0));
+}
diff --git a/cpukit/libnetworking/libc/strsep.c b/cpukit/libnetworking/libc/strsep.c
new file mode 100644
index 0000000000..182319493d
--- /dev/null
+++ b/cpukit/libnetworking/libc/strsep.c
@@ -0,0 +1,85 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * $Id$
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)strsep.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <string.h>
+#include <stdio.h>
+
+/*
+ * Get next token from string *stringp, where tokens are possibly-empty
+ * strings separated by characters from delim.
+ *
+ * Writes NULs into the string at *stringp to end tokens.
+ * delim need not remain constant from call to call.
+ * On return, *stringp points past the last NUL written (if there might
+ * be further tokens), or is NULL (if there are definitely no more tokens).
+ *
+ * If *stringp is NULL, strsep returns NULL.
+ *
+ * PUBLIC: #ifndef HAVE_STRSEP
+ * PUBLIC: char *strsep __P((char **, const char *));
+ * PUBLIC: #endif
+ */
+char *
+strsep(stringp, delim)
+ register char **stringp;
+ register const char *delim;
+{
+ register char *s;
+ register const char *spanp;
+ register int c, sc;
+ char *tok;
+
+ if ((s = *stringp) == NULL)
+ return (NULL);
+ for (tok = s;;) {
+ c = *s++;
+ spanp = delim;
+ do {
+ if ((sc = *spanp++) == c) {
+ if (c == 0)
+ s = NULL;
+ else
+ s[-1] = 0;
+ *stringp = s;
+ return (tok);
+ }
+ } while (sc != 0);
+ }
+ /* NOTREACHED */
+}
diff --git a/cpukit/libnetworking/loop.h b/cpukit/libnetworking/loop.h
new file mode 100644
index 0000000000..34e0b828e4
--- /dev/null
+++ b/cpukit/libnetworking/loop.h
@@ -0,0 +1,5 @@
+/*
+ * $Id$
+ */
+
+#define NLOOP 1
diff --git a/cpukit/libnetworking/machine/conf.h b/cpukit/libnetworking/machine/conf.h
new file mode 100644
index 0000000000..2b4c47e48f
--- /dev/null
+++ b/cpukit/libnetworking/machine/conf.h
@@ -0,0 +1,5 @@
+/*
+ * $Id$
+ */
+
+/* intentionally empty file */
diff --git a/cpukit/libnetworking/machine/cpu.h b/cpukit/libnetworking/machine/cpu.h
new file mode 100644
index 0000000000..2b4c47e48f
--- /dev/null
+++ b/cpukit/libnetworking/machine/cpu.h
@@ -0,0 +1,5 @@
+/*
+ * $Id$
+ */
+
+/* intentionally empty file */
diff --git a/cpukit/libnetworking/machine/cpufunc.h b/cpukit/libnetworking/machine/cpufunc.h
new file mode 100644
index 0000000000..2b4c47e48f
--- /dev/null
+++ b/cpukit/libnetworking/machine/cpufunc.h
@@ -0,0 +1,5 @@
+/*
+ * $Id$
+ */
+
+/* intentionally empty file */
diff --git a/cpukit/libnetworking/machine/endian.h b/cpukit/libnetworking/machine/endian.h
new file mode 100644
index 0000000000..34187dc93e
--- /dev/null
+++ b/cpukit/libnetworking/machine/endian.h
@@ -0,0 +1,64 @@
+/*
+ * $Id$
+ */
+
+#ifndef _MACHINE_ENDIAN_H_
+#define _MACHINE_ENDIAN_H_
+
+#include <rtems.h>
+
+/*
+ * BSD-style endian declaration
+ */
+#define BIG_ENDIAN 4321
+#define LITTLE_ENDIAN 1234
+
+#if CPU_BIG_ENDIAN
+# define BYTE_ORDER BIG_ENDIAN
+#elif CPU_LITTLE_ENDIAN
+# define BYTE_ORDER LITTLE_ENDIAN
+#else
+# error "Can't decide which end is which!"
+#endif
+
+#if ( CPU_HAS_OWN_HOST_TO_NETWORK_ROUTINES == FALSE )
+
+#if ( CPU_BIG_ENDIAN == TRUE )
+
+/*
+ * Very simply on big endian CPUs
+ */
+
+#define ntohl(_x) (_x)
+#define ntohs(_x) (_x)
+#define htonl(_x) (_x)
+#define htons(_x) (_x)
+
+#define NTOHS(x)
+#define HTONS(x)
+#define NTOHL(x)
+#define HTONL(x)
+
+#elif ( CPU_LITTLE_ENDIAN == TRUE )
+
+/*
+ * A little more complicated on little endian CPUs
+ */
+
+#define ntohl(_x) ((long) CPU_swap_u32((uint32_t )_x))
+#define ntohs(_x) ((short) CPU_swap_u16((uint16_t )_x))
+#define htonl(_x) ((long) CPU_swap_u32((uint32_t )_x))
+#define htons(_x) ((short) CPU_swap_u16((uint16_t )_x))
+
+#define NTOHS(x) (x) = ntohs(x)
+#define HTONS(x) (x) = htons(x)
+#define NTOHL(x) (x) = ntohl(x)
+#define HTONL(x) (x) = htonl(x)
+
+#else
+#error "Unknown endian-ness for this cpu"
+#endif
+
+#endif /* CPU_HAS_OWN_HOST_TO_NETWORK_ROUTINES */
+
+#endif /* _MACHINE_ENDIAN_H_ */
diff --git a/cpukit/libnetworking/machine/in_cksum.h b/cpukit/libnetworking/machine/in_cksum.h
new file mode 100644
index 0000000000..0ea8c9c493
--- /dev/null
+++ b/cpukit/libnetworking/machine/in_cksum.h
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 1990 The Regents of the University of California.
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * from tahoe: in_cksum.c 1.2 86/01/05
+ * from: @(#)in_cksum.c 1.3 (Berkeley) 1/19/91
+ * from: Id: in_cksum.c,v 1.8 1995/12/03 18:35:19 bde Exp
+ * $Id$
+ */
+
+#ifndef _MACHINE_IN_CKSUM_H_
+#define _MACHINE_IN_CKSUM_H_ 1
+
+#include <sys/cdefs.h>
+
+/*
+ * It it useful to have an Internet checksum routine which is inlineable
+ * and optimized specifically for the task of computing IP header checksums
+ * in the normal case (where there are no options and the header length is
+ * therefore always exactly five 32-bit words.
+ */
+
+/*
+ * Optimized version for the i386 family
+ */
+
+#if (defined(__GNUC__) && defined(__i386__))
+
+static __inline u_int
+in_cksum_hdr(const struct ip *ip)
+{
+ register u_int sum = 0;
+
+#define ADD(n) \
+ __asm__ volatile ("addl " #n "(%2), %0" : "=r" (sum) : "0" (sum), "r" (ip))
+#define ADDC(n) \
+ __asm__ volatile ("adcl " #n "(%2), %0" : "=r" (sum) : "0" (sum), "r" (ip))
+#define MOP \
+ __asm__ volatile ("adcl $0, %0" : "=r" (sum) : "0" (sum))
+
+ ADD(0);
+ ADDC(4);
+ ADDC(8);
+ ADDC(12);
+ ADDC(16);
+ MOP;
+ sum = (sum & 0xffff) + (sum >> 16);
+ if (sum > 0xffff)
+ sum -= 0xffff;
+
+ return ~sum & 0xffff;
+}
+
+static __inline void
+in_cksum_update(struct ip *ip)
+{
+ int __tmpsum;
+ __tmpsum = (int)ntohs(ip->ip_sum) + 256;
+ ip->ip_sum = htons(__tmpsum + (__tmpsum >> 16));
+}
+
+/*
+ * Optimized version for the MC68xxx and Coldfire families
+ */
+
+#elif (defined(__GNUC__) && (defined(__mc68000__) || defined(__m68k__)))
+
+static __inline__ u_int
+in_cksum_hdr(const struct ip *ip)
+{
+ register u_int *ap = (u_int *)ip;
+ register u_int sum = *ap++;
+ register u_int tmp;
+
+ __asm__("addl %2@+,%0\n\t"
+ "movel %2@+,%1\n\t"
+ "addxl %1,%0\n\t"
+ "movel %2@+,%1\n\t"
+ "addxl %1,%0\n\t"
+ "movel %2@,%1\n\t"
+ "addxl %1,%0\n\t"
+ "moveq #0,%1\n\t"
+ "addxl %1,%0\n" :
+ "=d" (sum), "=d" (tmp), "=a" (ap) :
+ "0" (sum), "2" (ap));
+ sum = (sum & 0xffff) + (sum >> 16);
+ if (sum > 0xffff)
+ sum -= 0xffff;
+ return ~sum & 0xffff;
+}
+
+/*
+ * Optimized version for the PowerPC family
+ */
+
+#elif (defined(__GNUC__) && (defined(__PPC__) || defined(__ppc__)))
+
+static __inline u_int
+in_cksum_hdr(const struct ip *ip)
+{
+ register u_int sum = 0;
+ register u_int tmp;
+
+#define ADD(n) \
+ __asm__ volatile ("addc %0,%0,%2" : "=r" (sum) : "0" (sum), "r" (n))
+#define ADDC(n) \
+ __asm__ volatile ("adde %0,%0,%2" : "=r" (sum) : "0" (sum), "r" (n))
+#define MOP \
+ __asm__ volatile ("addic %0,%0,0" : "=r" (sum) : "0" (sum))
+
+ tmp = *(((u_int *) ip)); ADD(tmp);
+ tmp = *(((u_int *) ip) + 1); ADDC(tmp);
+ tmp = *(((u_int *) ip) + 2); ADDC(tmp);
+ tmp = *(((u_int *) ip) + 3); ADDC(tmp);
+ tmp = *(((u_int *) ip) + 4); ADDC(tmp);
+ tmp = 0; ADDC(tmp);
+ sum = (sum & 0xffff) + (sum >> 16);
+ if (sum > 0xffff)
+ sum -= 0xffff;
+
+ return ~sum & 0xffff;
+}
+
+static __inline void
+in_cksum_update(struct ip *ip)
+{
+ int __tmpsum;
+ __tmpsum = (int)ntohs(ip->ip_sum) + 256;
+ ip->ip_sum = htons(__tmpsum + (__tmpsum >> 16));
+}
+
+/*
+ * SPARC Version
+ */
+
+#elif (defined(__GNUC__) && defined(sparc))
+
+static __inline u_int
+in_cksum_hdr(const struct ip *ip)
+{
+ register u_int sum = 0;
+ register u_int tmp_o2;
+ register u_int tmp_o3;
+
+ __asm__ volatile (" \
+ ld [%0], %1 ; \
+ ld [%0+4], %2 ; \
+ ld [%0+8], %3 ; \
+ addcc %1, %2, %1 ; \
+ ld [%0+12], %2 ; \
+ addxcc %1, %3, %1 ; \
+ ld [%0+16], %3 ; \
+ addxcc %1, %2, %1 ; \
+ addxcc %1, %3, %1 ; \
+ set 0x0ffff, %3 ; \
+ srl %1, 16, %2 ; \
+ and %1, %3, %1 ; \
+ addx %1, %2, %1 ; \
+ srl %1, 16, %2 ; \
+ add %1, %2, %1 ; \
+ not %1 ; \
+ and %1, %3, %1 ; \
+ " : "=r" (ip), "=r" (sum), "=r" (tmp_o2), "=r" (tmp_o3)
+ : "0" (ip), "1" (sum)
+ );
+ return sum;
+}
+
+#define in_cksum_update(ip) \
+ do { \
+ int __tmpsum; \
+ __tmpsum = (int)ntohs(ip->ip_sum) + 256; \
+ ip->ip_sum = htons(__tmpsum + (__tmpsum >> 16)); \
+ } while(0)
+/*
+ * Here is the generic, portable, inefficient algorithm.
+ */
+
+#else
+u_int in_cksum_hdr __P((const struct ip *));
+#define in_cksum_update(ip) \
+ do { \
+ int __tmpsum; \
+ __tmpsum = (int)ntohs(ip->ip_sum) + 256; \
+ ip->ip_sum = htons(__tmpsum + (__tmpsum >> 16)); \
+ } while(0)
+
+#endif
+
+#endif /* _MACHINE_IN_CKSUM_H_ */
diff --git a/cpukit/libnetworking/machine/limits.h b/cpukit/libnetworking/machine/limits.h
new file mode 100644
index 0000000000..2b4c47e48f
--- /dev/null
+++ b/cpukit/libnetworking/machine/limits.h
@@ -0,0 +1,5 @@
+/*
+ * $Id$
+ */
+
+/* intentionally empty file */
diff --git a/cpukit/libnetworking/machine/vmparam.h b/cpukit/libnetworking/machine/vmparam.h
new file mode 100644
index 0000000000..2b4c47e48f
--- /dev/null
+++ b/cpukit/libnetworking/machine/vmparam.h
@@ -0,0 +1,5 @@
+/*
+ * $Id$
+ */
+
+/* intentionally empty file */
diff --git a/cpukit/libnetworking/memory.h b/cpukit/libnetworking/memory.h
new file mode 100644
index 0000000000..7ef4cda388
--- /dev/null
+++ b/cpukit/libnetworking/memory.h
@@ -0,0 +1,5 @@
+/*
+ * Dummy include file for FreeBSD routines
+ */
+
+#include <string.h>
diff --git a/cpukit/libnetworking/net/bpf.h b/cpukit/libnetworking/net/bpf.h
new file mode 100644
index 0000000000..df21575640
--- /dev/null
+++ b/cpukit/libnetworking/net/bpf.h
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 1990, 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * Berkeley Laboratory.
+ *
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)bpf.h 8.1 (Berkeley) 6/10/93
+ * @(#)bpf.h 1.34 (LBL) 6/16/96
+ *
+ * $Id$
+ */
+
+#ifndef _NET_BPF_H_
+#define _NET_BPF_H_
+
+/* BSD style release date */
+#define BPF_RELEASE 199606
+
+typedef int32_t bpf_int32;
+typedef u_int32_t bpf_u_int32;
+
+/*
+ * Alignment macros. BPF_WORDALIGN rounds up to the next
+ * even multiple of BPF_ALIGNMENT.
+ */
+#define BPF_ALIGNMENT sizeof(bpf_int32)
+#define BPF_WORDALIGN(x) (((x)+(BPF_ALIGNMENT-1))&~(BPF_ALIGNMENT-1))
+
+#define BPF_MAXINSNS 512
+#define BPF_MAXBUFSIZE 0x8000
+#define BPF_MINBUFSIZE 32
+
+/*
+ * Structure for BIOCSETF.
+ */
+struct bpf_program {
+ u_int bf_len;
+ struct bpf_insn *bf_insns;
+};
+
+/*
+ * Struct returned by BIOCGSTATS.
+ */
+struct bpf_stat {
+ u_int bs_recv; /* number of packets received */
+ u_int bs_drop; /* number of packets dropped */
+};
+
+/*
+ * Struct return by BIOCVERSION. This represents the version number of
+ * the filter language described by the instruction encodings below.
+ * bpf understands a program iff kernel_major == filter_major &&
+ * kernel_minor >= filter_minor, that is, if the value returned by the
+ * running kernel has the same major number and a minor number equal
+ * equal to or less than the filter being downloaded. Otherwise, the
+ * results are undefined, meaning an error may be returned or packets
+ * may be accepted haphazardly.
+ * It has nothing to do with the source code version.
+ */
+struct bpf_version {
+ u_short bv_major;
+ u_short bv_minor;
+};
+/* Current version number of filter architecture. */
+#define BPF_MAJOR_VERSION 1
+#define BPF_MINOR_VERSION 1
+
+#define BIOCGBLEN _IOR('B',102, u_int)
+#define BIOCSBLEN _IOWR('B',102, u_int)
+#define BIOCSETF _IOW('B',103, struct bpf_program)
+#define BIOCFLUSH _IO('B',104)
+#define BIOCPROMISC _IO('B',105)
+#define BIOCGDLT _IOR('B',106, u_int)
+#define BIOCGETIF _IOR('B',107, struct ifreq)
+#define BIOCSETIF _IOW('B',108, struct ifreq)
+#define BIOCSRTIMEOUT _IOW('B',109, struct timeval)
+#define BIOCGRTIMEOUT _IOR('B',110, struct timeval)
+#define BIOCGSTATS _IOR('B',111, struct bpf_stat)
+#define BIOCIMMEDIATE _IOW('B',112, u_int)
+#define BIOCVERSION _IOR('B',113, struct bpf_version)
+#define BIOCGRSIG _IOR('B',114, u_int)
+#define BIOCSRSIG _IOW('B',115, u_int)
+
+/*
+ * Structure prepended to each packet.
+ */
+struct bpf_hdr {
+ struct timeval bh_tstamp; /* time stamp */
+ bpf_u_int32 bh_caplen; /* length of captured portion */
+ bpf_u_int32 bh_datalen; /* original length of packet */
+ u_short bh_hdrlen; /* length of bpf header (this struct
+ plus alignment padding) */
+};
+/*
+ * Because the structure above is not a multiple of 4 bytes, some compilers
+ * will insist on inserting padding; hence, sizeof(struct bpf_hdr) won't work.
+ * Only the kernel needs to know about it; applications use bh_hdrlen.
+ */
+#ifdef _KERNEL
+#define SIZEOF_BPF_HDR 18
+#endif
+
+/*
+ * Data-link level type codes.
+ */
+#define DLT_NULL 0 /* no link-layer encapsulation */
+#define DLT_EN10MB 1 /* Ethernet (10Mb) */
+#define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */
+#define DLT_AX25 3 /* Amateur Radio AX.25 */
+#define DLT_PRONET 4 /* Proteon ProNET Token Ring */
+#define DLT_CHAOS 5 /* Chaos */
+#define DLT_IEEE802 6 /* IEEE 802 Networks */
+#define DLT_ARCNET 7 /* ARCNET */
+#define DLT_SLIP 8 /* Serial Line IP */
+#define DLT_PPP 9 /* Point-to-point Protocol */
+#define DLT_FDDI 10 /* FDDI */
+#define DLT_ATM_RFC1483 11 /* LLC/SNAP encapsulated atm */
+
+/*
+ * The instruction encodings.
+ */
+/* instruction classes */
+#define BPF_CLASS(code) ((code) & 0x07)
+#define BPF_LD 0x00
+#define BPF_LDX 0x01
+#define BPF_ST 0x02
+#define BPF_STX 0x03
+#define BPF_ALU 0x04
+#define BPF_JMP 0x05
+#define BPF_RET 0x06
+#define BPF_MISC 0x07
+
+/* ld/ldx fields */
+#define BPF_SIZE(code) ((code) & 0x18)
+#define BPF_W 0x00
+#define BPF_H 0x08
+#define BPF_B 0x10
+#define BPF_MODE(code) ((code) & 0xe0)
+#define BPF_IMM 0x00
+#define BPF_ABS 0x20
+#define BPF_IND 0x40
+#define BPF_MEM 0x60
+#define BPF_LEN 0x80
+#define BPF_MSH 0xa0
+
+/* alu/jmp fields */
+#define BPF_OP(code) ((code) & 0xf0)
+#define BPF_ADD 0x00
+#define BPF_SUB 0x10
+#define BPF_MUL 0x20
+#define BPF_DIV 0x30
+#define BPF_OR 0x40
+#define BPF_AND 0x50
+#define BPF_LSH 0x60
+#define BPF_RSH 0x70
+#define BPF_NEG 0x80
+#define BPF_JA 0x00
+#define BPF_JEQ 0x10
+#define BPF_JGT 0x20
+#define BPF_JGE 0x30
+#define BPF_JSET 0x40
+#define BPF_SRC(code) ((code) & 0x08)
+#define BPF_K 0x00
+#define BPF_X 0x08
+
+/* ret - BPF_K and BPF_X also apply */
+#define BPF_RVAL(code) ((code) & 0x18)
+#define BPF_A 0x10
+
+/* misc */
+#define BPF_MISCOP(code) ((code) & 0xf8)
+#define BPF_TAX 0x00
+#define BPF_TXA 0x80
+
+/*
+ * The instruction data structure.
+ */
+struct bpf_insn {
+ u_short code;
+ u_char jt;
+ u_char jf;
+ bpf_u_int32 k;
+};
+
+/*
+ * Macros for insn array initializers.
+ */
+#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k }
+#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k }
+
+#ifdef _KERNEL
+int bpf_validate(struct bpf_insn *, int);
+void bpf_tap(struct ifnet *, u_char *, u_int);
+void bpf_mtap(struct ifnet *, struct mbuf *);
+void bpfattach(struct ifnet *, u_int, u_int);
+void bpfilterattach(int);
+u_int bpf_filter(const struct bpf_insn *, u_char *, u_int, u_int);
+#endif
+
+/*
+ * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST).
+ */
+#define BPF_MEMWORDS 16
+
+#endif /* _NET_BPF_H_ */
diff --git a/cpukit/libnetworking/net/bsd-comp.c b/cpukit/libnetworking/net/bsd-comp.c
new file mode 100644
index 0000000000..294457cc2c
--- /dev/null
+++ b/cpukit/libnetworking/net/bsd-comp.c
@@ -0,0 +1,1117 @@
+/* $Id$ */
+
+/* Because this code is derived from the 4.3BSD compress source:
+ *
+ *
+ * Copyright (c) 1985, 1986 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * James A. Woods, derived from original work by Spencer Thomas
+ * and Joseph Orost.
+ *
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ */
+
+/*
+ * This version is for use with mbufs on BSD-derived systems.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/if_types.h>
+#include <net/ppp_defs.h>
+#include <net/if_ppp.h>
+
+#define PACKETPTR struct mbuf *
+#include <net/ppp-comp.h>
+
+#if DO_BSD_COMPRESS
+/*
+ * PPP "BSD compress" compression
+ * The differences between this compression and the classic BSD LZW
+ * source are obvious from the requirement that the classic code worked
+ * with files while this handles arbitrarily long streams that
+ * are broken into packets. They are:
+ *
+ * When the code size expands, a block of junk is not emitted by
+ * the compressor and not expected by the decompressor.
+ *
+ * New codes are not necessarily assigned every time an old
+ * code is output by the compressor. This is because a packet
+ * end forces a code to be emitted, but does not imply that a
+ * new sequence has been seen.
+ *
+ * The compression ratio is checked at the first end of a packet
+ * after the appropriate gap. Besides simplifying and speeding
+ * things up, this makes it more likely that the transmitter
+ * and receiver will agree when the dictionary is cleared when
+ * compression is not going well.
+ */
+
+/*
+ * A dictionary for doing BSD compress.
+ */
+struct bsd_db {
+ int totlen; /* length of this structure */
+ u_int hsize; /* size of the hash table */
+ u_char hshift; /* used in hash function */
+ u_char n_bits; /* current bits/code */
+ u_char maxbits;
+ u_char debug;
+ u_char unit;
+ u_int16_t seqno; /* sequence # of next packet */
+ u_int hdrlen; /* header length to preallocate */
+ u_int mru;
+ u_int maxmaxcode; /* largest valid code */
+ u_int max_ent; /* largest code in use */
+ u_int in_count; /* uncompressed bytes, aged */
+ u_int bytes_out; /* compressed bytes, aged */
+ u_int ratio; /* recent compression ratio */
+ u_int checkpoint; /* when to next check the ratio */
+ u_int clear_count; /* times dictionary cleared */
+ u_int incomp_count; /* incompressible packets */
+ u_int incomp_bytes; /* incompressible bytes */
+ u_int uncomp_count; /* uncompressed packets */
+ u_int uncomp_bytes; /* uncompressed bytes */
+ u_int comp_count; /* compressed packets */
+ u_int comp_bytes; /* compressed bytes */
+ u_int16_t *lens; /* array of lengths of codes */
+ struct bsd_dict {
+ union { /* hash value */
+ u_int32_t fcode;
+ struct {
+#if BYTE_ORDER == LITTLE_ENDIAN
+ u_int16_t prefix; /* preceding code */
+ u_char suffix; /* last character of new code */
+ u_char pad;
+#else
+ u_char pad;
+ u_char suffix; /* last character of new code */
+ u_int16_t prefix; /* preceding code */
+#endif
+ } hs;
+ } f;
+ u_int16_t codem1; /* output of hash table -1 */
+ u_int16_t cptr; /* map code to hash table entry */
+ } dict[1];
+};
+
+#define BSD_OVHD 2 /* BSD compress overhead/packet */
+#define BSD_INIT_BITS BSD_MIN_BITS
+
+static void *bsd_comp_alloc __P((u_char *options, int opt_len));
+static void *bsd_decomp_alloc __P((u_char *options, int opt_len));
+static void bsd_free __P((void *state));
+static int bsd_comp_init __P((void *state, u_char *options, int opt_len,
+ int unit, int hdrlen, int debug));
+static int bsd_decomp_init __P((void *state, u_char *options, int opt_len,
+ int unit, int hdrlen, int mru, int debug));
+static int bsd_compress __P((void *state, struct mbuf **mret,
+ struct mbuf *mp, int slen, int maxolen));
+static void bsd_incomp __P((void *state, struct mbuf *dmsg));
+static int bsd_decompress __P((void *state, struct mbuf *cmp,
+ struct mbuf **dmpp));
+static void bsd_reset __P((void *state));
+static void bsd_comp_stats __P((void *state, struct compstat *stats));
+
+/*
+ * Procedures exported to if_ppp.c.
+ */
+struct compressor ppp_bsd_compress = {
+ CI_BSD_COMPRESS, /* compress_proto */
+ bsd_comp_alloc, /* comp_alloc */
+ bsd_free, /* comp_free */
+ bsd_comp_init, /* comp_init */
+ bsd_reset, /* comp_reset */
+ bsd_compress, /* compress */
+ bsd_comp_stats, /* comp_stat */
+ bsd_decomp_alloc, /* decomp_alloc */
+ bsd_free, /* decomp_free */
+ bsd_decomp_init, /* decomp_init */
+ bsd_reset, /* decomp_reset */
+ bsd_decompress, /* decompress */
+ bsd_incomp, /* incomp */
+ bsd_comp_stats, /* decomp_stat */
+};
+
+/*
+ * the next two codes should not be changed lightly, as they must not
+ * lie within the contiguous general code space.
+ */
+#define CLEAR 256 /* table clear output code */
+#define FIRST 257 /* first free entry */
+#define LAST 255
+
+#define MAXCODE(b) ((1 << (b)) - 1)
+#define BADCODEM1 MAXCODE(BSD_MAX_BITS)
+
+#define BSD_HASH(prefix,suffix,hshift) ((((u_int32_t)(suffix)) << (hshift)) \
+ ^ (u_int32_t)(prefix))
+#define BSD_KEY(prefix,suffix) ((((u_int32_t)(suffix)) << 16) \
+ + (u_int32_t)(prefix))
+
+#define CHECK_GAP 10000 /* Ratio check interval */
+
+#define RATIO_SCALE_LOG 8
+#define RATIO_SCALE (1<<RATIO_SCALE_LOG)
+#define RATIO_MAX (0x7fffffff>>RATIO_SCALE_LOG)
+
+static void bsd_clear __P((struct bsd_db *));
+static int bsd_check __P((struct bsd_db *));
+static void *bsd_alloc __P((u_char *, int, int));
+static int bsd_init __P((struct bsd_db *, u_char *, int, int, int, int,
+ int, int));
+
+/*
+ * clear the dictionary
+ */
+static void
+bsd_clear(db)
+ struct bsd_db *db;
+{
+ db->clear_count++;
+ db->max_ent = FIRST-1;
+ db->n_bits = BSD_INIT_BITS;
+ db->ratio = 0;
+ db->bytes_out = 0;
+ db->in_count = 0;
+ db->checkpoint = CHECK_GAP;
+}
+
+/*
+ * If the dictionary is full, then see if it is time to reset it.
+ *
+ * Compute the compression ratio using fixed-point arithmetic
+ * with 8 fractional bits.
+ *
+ * Since we have an infinite stream instead of a single file,
+ * watch only the local compression ratio.
+ *
+ * Since both peers must reset the dictionary at the same time even in
+ * the absence of CLEAR codes (while packets are incompressible), they
+ * must compute the same ratio.
+ */
+static int /* 1=output CLEAR */
+bsd_check(db)
+ struct bsd_db *db;
+{
+ u_int new_ratio;
+
+ if (db->in_count >= db->checkpoint) {
+ /* age the ratio by limiting the size of the counts */
+ if (db->in_count >= RATIO_MAX
+ || db->bytes_out >= RATIO_MAX) {
+ db->in_count -= db->in_count/4;
+ db->bytes_out -= db->bytes_out/4;
+ }
+
+ db->checkpoint = db->in_count + CHECK_GAP;
+
+ if (db->max_ent >= db->maxmaxcode) {
+ /* Reset the dictionary only if the ratio is worse,
+ * or if it looks as if it has been poisoned
+ * by incompressible data.
+ *
+ * This does not overflow, because
+ * db->in_count <= RATIO_MAX.
+ */
+ new_ratio = db->in_count << RATIO_SCALE_LOG;
+ if (db->bytes_out != 0)
+ new_ratio /= db->bytes_out;
+
+ if (new_ratio < db->ratio || new_ratio < 1 * RATIO_SCALE) {
+ bsd_clear(db);
+ return 1;
+ }
+ db->ratio = new_ratio;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Return statistics.
+ */
+static void
+bsd_comp_stats(state, stats)
+ void *state;
+ struct compstat *stats;
+{
+ struct bsd_db *db = (struct bsd_db *) state;
+ u_int out;
+
+ stats->unc_bytes = db->uncomp_bytes;
+ stats->unc_packets = db->uncomp_count;
+ stats->comp_bytes = db->comp_bytes;
+ stats->comp_packets = db->comp_count;
+ stats->inc_bytes = db->incomp_bytes;
+ stats->inc_packets = db->incomp_count;
+ stats->ratio = db->in_count;
+ out = db->bytes_out;
+ if (stats->ratio <= 0x7fffff)
+ stats->ratio <<= 8;
+ else
+ out >>= 8;
+ if (out != 0)
+ stats->ratio /= out;
+}
+
+/*
+ * Reset state, as on a CCP ResetReq.
+ */
+static void
+bsd_reset(state)
+ void *state;
+{
+ struct bsd_db *db = (struct bsd_db *) state;
+
+ db->seqno = 0;
+ bsd_clear(db);
+ db->clear_count = 0;
+}
+
+/*
+ * Allocate space for a (de) compressor.
+ */
+static void *
+bsd_alloc(options, opt_len, decomp)
+ u_char *options;
+ int opt_len, decomp;
+{
+ int bits;
+ u_int newlen, hsize, hshift, maxmaxcode;
+ struct bsd_db *db;
+
+ if (opt_len < CILEN_BSD_COMPRESS || options[0] != CI_BSD_COMPRESS
+ || options[1] != CILEN_BSD_COMPRESS
+ || BSD_VERSION(options[2]) != BSD_CURRENT_VERSION)
+ return NULL;
+ bits = BSD_NBITS(options[2]);
+ switch (bits) {
+ case 9: /* needs 82152 for both directions */
+ case 10: /* needs 84144 */
+ case 11: /* needs 88240 */
+ case 12: /* needs 96432 */
+ hsize = 5003;
+ hshift = 4;
+ break;
+ case 13: /* needs 176784 */
+ hsize = 9001;
+ hshift = 5;
+ break;
+ case 14: /* needs 353744 */
+ hsize = 18013;
+ hshift = 6;
+ break;
+ case 15: /* needs 691440 */
+ hsize = 35023;
+ hshift = 7;
+ break;
+ case 16: /* needs 1366160--far too much, */
+ /* hsize = 69001; */ /* and 69001 is too big for cptr */
+ /* hshift = 8; */ /* in struct bsd_db */
+ /* break; */
+ default:
+ return NULL;
+ }
+
+ maxmaxcode = MAXCODE(bits);
+ newlen = sizeof(*db) + (hsize-1) * (sizeof(db->dict[0]));
+ MALLOC(db, struct bsd_db *, newlen, M_DEVBUF, M_NOWAIT);
+ if (!db)
+ return NULL;
+ bzero(db, sizeof(*db) - sizeof(db->dict));
+
+ if (!decomp) {
+ db->lens = NULL;
+ } else {
+ MALLOC(db->lens, u_int16_t *, (maxmaxcode+1) * sizeof(db->lens[0]),
+ M_DEVBUF, M_NOWAIT);
+ if (!db->lens) {
+ FREE(db, M_DEVBUF);
+ return NULL;
+ }
+ }
+
+ db->totlen = newlen;
+ db->hsize = hsize;
+ db->hshift = hshift;
+ db->maxmaxcode = maxmaxcode;
+ db->maxbits = bits;
+
+ return (void *) db;
+}
+
+static void
+bsd_free(state)
+ void *state;
+{
+ struct bsd_db *db = (struct bsd_db *) state;
+
+ if (db->lens)
+ FREE(db->lens, M_DEVBUF);
+ FREE(db, M_DEVBUF);
+}
+
+static void *
+bsd_comp_alloc(options, opt_len)
+ u_char *options;
+ int opt_len;
+{
+ return bsd_alloc(options, opt_len, 0);
+}
+
+static void *
+bsd_decomp_alloc(options, opt_len)
+ u_char *options;
+ int opt_len;
+{
+ return bsd_alloc(options, opt_len, 1);
+}
+
+/*
+ * Initialize the database.
+ */
+static int
+bsd_init(db, options, opt_len, unit, hdrlen, mru, debug, decomp)
+ struct bsd_db *db;
+ u_char *options;
+ int opt_len, unit, hdrlen, mru, debug, decomp;
+{
+ int i;
+
+ if (opt_len < CILEN_BSD_COMPRESS || options[0] != CI_BSD_COMPRESS
+ || options[1] != CILEN_BSD_COMPRESS
+ || BSD_VERSION(options[2]) != BSD_CURRENT_VERSION
+ || BSD_NBITS(options[2]) != db->maxbits
+ || (decomp && db->lens == NULL))
+ return 0;
+
+ if (decomp) {
+ i = LAST+1;
+ while (i != 0)
+ db->lens[--i] = 1;
+ }
+ i = db->hsize;
+ while (i != 0) {
+ db->dict[--i].codem1 = BADCODEM1;
+ db->dict[i].cptr = 0;
+ }
+
+ db->unit = unit;
+ db->hdrlen = hdrlen;
+ db->mru = mru;
+#ifndef DEBUG
+ if (debug)
+#endif
+ db->debug = 1;
+
+ bsd_reset(db);
+
+ return 1;
+}
+
+static int
+bsd_comp_init(state, options, opt_len, unit, hdrlen, debug)
+ void *state;
+ u_char *options;
+ int opt_len, unit, hdrlen, debug;
+{
+ return bsd_init((struct bsd_db *) state, options, opt_len,
+ unit, hdrlen, 0, debug, 0);
+}
+
+static int
+bsd_decomp_init(state, options, opt_len, unit, hdrlen, mru, debug)
+ void *state;
+ u_char *options;
+ int opt_len, unit, hdrlen, mru, debug;
+{
+ return bsd_init((struct bsd_db *) state, options, opt_len,
+ unit, hdrlen, mru, debug, 1);
+}
+
+
+/*
+ * compress a packet
+ * One change from the BSD compress command is that when the
+ * code size expands, we do not output a bunch of padding.
+ */
+int /* new slen */
+bsd_compress(state, mret, mp, slen, maxolen)
+ void *state;
+ struct mbuf **mret; /* return compressed mbuf chain here */
+ struct mbuf *mp; /* from here */
+ int slen; /* uncompressed length */
+ int maxolen; /* max compressed length */
+{
+ struct bsd_db *db = (struct bsd_db *) state;
+ int hshift = db->hshift;
+ u_int max_ent = db->max_ent;
+ u_int n_bits = db->n_bits;
+ u_int bitno = 32;
+ u_int32_t accm = 0, fcode;
+ struct bsd_dict *dictp;
+ u_char c;
+ int hval, disp, ent, ilen;
+ u_char *rptr, *wptr;
+ u_char *cp_end;
+ int olen;
+ struct mbuf *m;
+
+#define PUTBYTE(v) { \
+ ++olen; \
+ if (wptr) { \
+ *wptr++ = (v); \
+ if (wptr >= cp_end) { \
+ m->m_len = wptr - mtod(m, u_char *); \
+ MGET(m->m_next, M_DONTWAIT, MT_DATA); \
+ m = m->m_next; \
+ if (m) { \
+ m->m_len = 0; \
+ if (maxolen - olen > MLEN) \
+ MCLGET(m, M_DONTWAIT); \
+ wptr = mtod(m, u_char *); \
+ cp_end = wptr + M_TRAILINGSPACE(m); \
+ } else \
+ wptr = NULL; \
+ } \
+ } \
+}
+
+#define OUTPUT(ent) { \
+ bitno -= n_bits; \
+ accm |= ((ent) << bitno); \
+ do { \
+ PUTBYTE(accm >> 24); \
+ accm <<= 8; \
+ bitno += 8; \
+ } while (bitno <= 24); \
+}
+
+ /*
+ * If the protocol is not in the range we're interested in,
+ * just return without compressing the packet. If it is,
+ * the protocol becomes the first byte to compress.
+ */
+ rptr = mtod(mp, u_char *);
+ ent = PPP_PROTOCOL(rptr);
+ if (ent < 0x21 || ent > 0xf9) {
+ *mret = NULL;
+ return slen;
+ }
+
+ /* Don't generate compressed packets which are larger than
+ the uncompressed packet. */
+ if (maxolen > slen)
+ maxolen = slen;
+
+ /* Allocate one mbuf to start with. */
+ MGET(m, M_DONTWAIT, MT_DATA);
+ *mret = m;
+ if (m != NULL) {
+ m->m_len = 0;
+ if (maxolen + db->hdrlen > MLEN)
+ MCLGET(m, M_DONTWAIT);
+ m->m_data += db->hdrlen;
+ wptr = mtod(m, u_char *);
+ cp_end = wptr + M_TRAILINGSPACE(m);
+ } else
+ wptr = cp_end = NULL;
+
+ /*
+ * Copy the PPP header over, changing the protocol,
+ * and install the 2-byte packet sequence number.
+ */
+ if (wptr) {
+ *wptr++ = PPP_ADDRESS(rptr); /* assumes the ppp header is */
+ *wptr++ = PPP_CONTROL(rptr); /* all in one mbuf */
+ *wptr++ = 0; /* change the protocol */
+ *wptr++ = PPP_COMP;
+ *wptr++ = db->seqno >> 8;
+ *wptr++ = db->seqno;
+ }
+ ++db->seqno;
+
+ olen = 0;
+ rptr += PPP_HDRLEN;
+ slen = mp->m_len - PPP_HDRLEN;
+ ilen = slen + 1;
+ for (;;) {
+ if (slen <= 0) {
+ mp = mp->m_next;
+ if (!mp)
+ break;
+ rptr = mtod(mp, u_char *);
+ slen = mp->m_len;
+ if (!slen)
+ continue; /* handle 0-length buffers */
+ ilen += slen;
+ }
+
+ slen--;
+ c = *rptr++;
+ fcode = BSD_KEY(ent, c);
+ hval = BSD_HASH(ent, c, hshift);
+ dictp = &db->dict[hval];
+
+ /* Validate and then check the entry. */
+ if (dictp->codem1 >= max_ent)
+ goto nomatch;
+ if (dictp->f.fcode == fcode) {
+ ent = dictp->codem1+1;
+ continue; /* found (prefix,suffix) */
+ }
+
+ /* continue probing until a match or invalid entry */
+ disp = (hval == 0) ? 1 : hval;
+ do {
+ hval += disp;
+ if (hval >= db->hsize)
+ hval -= db->hsize;
+ dictp = &db->dict[hval];
+ if (dictp->codem1 >= max_ent)
+ goto nomatch;
+ } while (dictp->f.fcode != fcode);
+ ent = dictp->codem1 + 1; /* finally found (prefix,suffix) */
+ continue;
+
+ nomatch:
+ OUTPUT(ent); /* output the prefix */
+
+ /* code -> hashtable */
+ if (max_ent < db->maxmaxcode) {
+ struct bsd_dict *dictp2;
+ /* expand code size if needed */
+ if (max_ent >= MAXCODE(n_bits))
+ db->n_bits = ++n_bits;
+
+ /* Invalidate old hash table entry using
+ * this code, and then take it over.
+ */
+ dictp2 = &db->dict[max_ent+1];
+ if (db->dict[dictp2->cptr].codem1 == max_ent)
+ db->dict[dictp2->cptr].codem1 = BADCODEM1;
+ dictp2->cptr = hval;
+ dictp->codem1 = max_ent;
+ dictp->f.fcode = fcode;
+
+ db->max_ent = ++max_ent;
+ }
+ ent = c;
+ }
+
+ OUTPUT(ent); /* output the last code */
+ db->bytes_out += olen;
+ db->in_count += ilen;
+ if (bitno < 32)
+ ++db->bytes_out; /* count complete bytes */
+
+ if (bsd_check(db))
+ OUTPUT(CLEAR); /* do not count the CLEAR */
+
+ /*
+ * Pad dribble bits of last code with ones.
+ * Do not emit a completely useless byte of ones.
+ */
+ if (bitno != 32)
+ PUTBYTE((accm | (0xff << (bitno-8))) >> 24);
+
+ if (m != NULL) {
+ m->m_len = wptr - mtod(m, u_char *);
+ m->m_next = NULL;
+ }
+
+ /*
+ * Increase code size if we would have without the packet
+ * boundary and as the decompressor will.
+ */
+ if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode)
+ db->n_bits++;
+
+ db->uncomp_bytes += ilen;
+ ++db->uncomp_count;
+ if (olen + PPP_HDRLEN + BSD_OVHD > maxolen) {
+ /* throw away the compressed stuff if it is longer than uncompressed */
+ if (*mret != NULL) {
+ m_freem(*mret);
+ *mret = NULL;
+ }
+ ++db->incomp_count;
+ db->incomp_bytes += ilen;
+ } else {
+ ++db->comp_count;
+ db->comp_bytes += olen + BSD_OVHD;
+ }
+
+ return olen + PPP_HDRLEN + BSD_OVHD;
+#undef OUTPUT
+#undef PUTBYTE
+}
+
+
+/*
+ * Update the "BSD Compress" dictionary on the receiver for
+ * incompressible data by pretending to compress the incoming data.
+ */
+static void
+bsd_incomp(state, dmsg)
+ void *state;
+ struct mbuf *dmsg;
+{
+ struct bsd_db *db = (struct bsd_db *) state;
+ u_int hshift = db->hshift;
+ u_int max_ent = db->max_ent;
+ u_int n_bits = db->n_bits;
+ struct bsd_dict *dictp;
+ u_int32_t fcode;
+ u_char c;
+ u_int32_t hval, disp;
+ int slen, ilen;
+ u_int bitno = 7;
+ u_char *rptr;
+ u_int ent;
+
+ /*
+ * If the protocol is not in the range we're interested in,
+ * just return without looking at the packet. If it is,
+ * the protocol becomes the first byte to "compress".
+ */
+ rptr = mtod(dmsg, u_char *);
+ ent = PPP_PROTOCOL(rptr);
+ if (ent < 0x21 || ent > 0xf9)
+ return;
+
+ db->seqno++;
+ ilen = 1; /* count the protocol as 1 byte */
+ rptr += PPP_HDRLEN;
+ slen = dmsg->m_len - PPP_HDRLEN;
+ for (;;) {
+ if (slen <= 0) {
+ dmsg = dmsg->m_next;
+ if (!dmsg)
+ break;
+ rptr = mtod(dmsg, u_char *);
+ slen = dmsg->m_len;
+ continue;
+ }
+ ilen += slen;
+
+ do {
+ c = *rptr++;
+ fcode = BSD_KEY(ent, c);
+ hval = BSD_HASH(ent, c, hshift);
+ dictp = &db->dict[hval];
+
+ /* validate and then check the entry */
+ if (dictp->codem1 >= max_ent)
+ goto nomatch;
+ if (dictp->f.fcode == fcode) {
+ ent = dictp->codem1+1;
+ continue; /* found (prefix,suffix) */
+ }
+
+ /* continue probing until a match or invalid entry */
+ disp = (hval == 0) ? 1 : hval;
+ do {
+ hval += disp;
+ if (hval >= db->hsize)
+ hval -= db->hsize;
+ dictp = &db->dict[hval];
+ if (dictp->codem1 >= max_ent)
+ goto nomatch;
+ } while (dictp->f.fcode != fcode);
+ ent = dictp->codem1+1;
+ continue; /* finally found (prefix,suffix) */
+
+ nomatch: /* output (count) the prefix */
+ bitno += n_bits;
+
+ /* code -> hashtable */
+ if (max_ent < db->maxmaxcode) {
+ struct bsd_dict *dictp2;
+ /* expand code size if needed */
+ if (max_ent >= MAXCODE(n_bits))
+ db->n_bits = ++n_bits;
+
+ /* Invalidate previous hash table entry
+ * assigned this code, and then take it over.
+ */
+ dictp2 = &db->dict[max_ent+1];
+ if (db->dict[dictp2->cptr].codem1 == max_ent)
+ db->dict[dictp2->cptr].codem1 = BADCODEM1;
+ dictp2->cptr = hval;
+ dictp->codem1 = max_ent;
+ dictp->f.fcode = fcode;
+
+ db->max_ent = ++max_ent;
+ db->lens[max_ent] = db->lens[ent]+1;
+ }
+ ent = c;
+ } while (--slen != 0);
+ }
+ bitno += n_bits; /* output (count) the last code */
+ db->bytes_out += bitno/8;
+ db->in_count += ilen;
+ (void)bsd_check(db);
+
+ ++db->incomp_count;
+ db->incomp_bytes += ilen;
+ ++db->uncomp_count;
+ db->uncomp_bytes += ilen;
+
+ /* Increase code size if we would have without the packet
+ * boundary and as the decompressor will.
+ */
+ if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode)
+ db->n_bits++;
+}
+
+
+/*
+ * Decompress "BSD Compress".
+ *
+ * Because of patent problems, we return DECOMP_ERROR for errors
+ * found by inspecting the input data and for system problems, but
+ * DECOMP_FATALERROR for any errors which could possibly be said to
+ * be being detected "after" decompression. For DECOMP_ERROR,
+ * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
+ * infringing a patent of Motorola's if we do, so we take CCP down
+ * instead.
+ *
+ * Given that the frame has the correct sequence number and a good FCS,
+ * errors such as invalid codes in the input most likely indicate a
+ * bug, so we return DECOMP_FATALERROR for them in order to turn off
+ * compression, even though they are detected by inspecting the input.
+ */
+int
+bsd_decompress(state, cmp, dmpp)
+ void *state;
+ struct mbuf *cmp, **dmpp;
+{
+ struct bsd_db *db = (struct bsd_db *) state;
+ u_int max_ent = db->max_ent;
+ u_int32_t accm = 0;
+ u_int bitno = 32; /* 1st valid bit in accm */
+ u_int n_bits = db->n_bits;
+ u_int tgtbitno = 32-n_bits; /* bitno when we have a code */
+ struct bsd_dict *dictp;
+ int explen, i, seq, len;
+ u_int incode, oldcode, finchar;
+ u_char *p, *rptr, *wptr;
+ struct mbuf *m, *dmp, *mret;
+ int adrs, ctrl, ilen;
+ int space, codelen, extra;
+
+ /*
+ * Save the address/control from the PPP header
+ * and then get the sequence number.
+ */
+ *dmpp = NULL;
+ rptr = mtod(cmp, u_char *);
+ adrs = PPP_ADDRESS(rptr);
+ ctrl = PPP_CONTROL(rptr);
+ rptr += PPP_HDRLEN;
+ len = cmp->m_len - PPP_HDRLEN;
+ seq = 0;
+ for (i = 0; i < 2; ++i) {
+ while (len <= 0) {
+ cmp = cmp->m_next;
+ if (cmp == NULL)
+ return DECOMP_ERROR;
+ rptr = mtod(cmp, u_char *);
+ len = cmp->m_len;
+ }
+ seq = (seq << 8) + *rptr++;
+ --len;
+ }
+
+ /*
+ * Check the sequence number and give up if it differs from
+ * the value we're expecting.
+ */
+ if (seq != db->seqno) {
+ if (db->debug)
+ printf("bsd_decomp%d: bad sequence # %d, expected %d\n",
+ db->unit, seq, db->seqno - 1);
+ return DECOMP_ERROR;
+ }
+ ++db->seqno;
+
+ /*
+ * Allocate one mbuf to start with.
+ */
+ MGETHDR(dmp, M_DONTWAIT, MT_DATA);
+ if (dmp == NULL)
+ return DECOMP_ERROR;
+ mret = dmp;
+ dmp->m_len = 0;
+ dmp->m_next = NULL;
+ MCLGET(dmp, M_DONTWAIT);
+ dmp->m_data += db->hdrlen;
+ wptr = mtod(dmp, u_char *);
+ space = M_TRAILINGSPACE(dmp) - PPP_HDRLEN + 1;
+
+ /*
+ * Fill in the ppp header, but not the last byte of the protocol
+ * (that comes from the decompressed data).
+ */
+ wptr[0] = adrs;
+ wptr[1] = ctrl;
+ wptr[2] = 0;
+ wptr += PPP_HDRLEN - 1;
+
+ ilen = len;
+ oldcode = CLEAR;
+ explen = 0;
+ for (;;) {
+ if (len == 0) {
+ cmp = cmp->m_next;
+ if (!cmp) /* quit at end of message */
+ break;
+ rptr = mtod(cmp, u_char *);
+ len = cmp->m_len;
+ ilen += len;
+ continue; /* handle 0-length buffers */
+ }
+
+ /*
+ * Accumulate bytes until we have a complete code.
+ * Then get the next code, relying on the 32-bit,
+ * unsigned accm to mask the result.
+ */
+ bitno -= 8;
+ accm |= *rptr++ << bitno;
+ --len;
+ if (tgtbitno < bitno)
+ continue;
+ incode = accm >> tgtbitno;
+ accm <<= n_bits;
+ bitno += n_bits;
+
+ if (incode == CLEAR) {
+ /*
+ * The dictionary must only be cleared at
+ * the end of a packet. But there could be an
+ * empty mbuf at the end.
+ */
+ if (len > 0 || cmp->m_next != NULL) {
+ while ((cmp = cmp->m_next) != NULL)
+ len += cmp->m_len;
+ if (len > 0) {
+ m_freem(mret);
+ if (db->debug)
+ printf("bsd_decomp%d: bad CLEAR\n", db->unit);
+ return DECOMP_FATALERROR; /* probably a bug */
+ }
+ }
+ bsd_clear(db);
+ explen = ilen = 0;
+ break;
+ }
+
+ if (incode > max_ent + 2 || incode > db->maxmaxcode
+ || (incode > max_ent && oldcode == CLEAR)) {
+ m_freem(mret);
+ if (db->debug) {
+ printf("bsd_decomp%d: bad code 0x%x oldcode=0x%x ",
+ db->unit, incode, oldcode);
+ printf("max_ent=0x%x explen=%d seqno=%d\n",
+ max_ent, explen, db->seqno);
+ }
+ return DECOMP_FATALERROR; /* probably a bug */
+ }
+
+ /* Special case for KwKwK string. */
+ if (incode > max_ent) {
+ finchar = oldcode;
+ extra = 1;
+ } else {
+ finchar = incode;
+ extra = 0;
+ }
+
+ codelen = db->lens[finchar];
+ explen += codelen + extra;
+ if (explen > db->mru + 1) {
+ m_freem(mret);
+ if (db->debug) {
+ printf("bsd_decomp%d: ran out of mru\n", db->unit);
+#ifdef DEBUG
+ while ((cmp = cmp->m_next) != NULL)
+ len += cmp->m_len;
+ printf(" len=%d, finchar=0x%x, codelen=%d, explen=%d\n",
+ len, finchar, codelen, explen);
+#endif
+ }
+ return DECOMP_FATALERROR;
+ }
+
+ /*
+ * For simplicity, the decoded characters go in a single mbuf,
+ * so we allocate a single extra cluster mbuf if necessary.
+ */
+ if ((space -= codelen + extra) < 0) {
+ dmp->m_len = wptr - mtod(dmp, u_char *);
+ MGET(m, M_DONTWAIT, MT_DATA);
+ if (m == NULL) {
+ m_freem(mret);
+ return DECOMP_ERROR;
+ }
+ m->m_len = 0;
+ m->m_next = NULL;
+ dmp->m_next = m;
+ MCLGET(m, M_DONTWAIT);
+ space = M_TRAILINGSPACE(m) - (codelen + extra);
+ if (space < 0) {
+ /* now that's what I call *compression*. */
+ m_freem(mret);
+ return DECOMP_ERROR;
+ }
+ dmp = m;
+ wptr = mtod(dmp, u_char *);
+ }
+
+ /*
+ * Decode this code and install it in the decompressed buffer.
+ */
+ p = (wptr += codelen);
+ while (finchar > LAST) {
+ dictp = &db->dict[db->dict[finchar].cptr];
+#ifdef DEBUG
+ if (--codelen <= 0 || dictp->codem1 != finchar-1)
+ goto bad;
+#endif
+ *--p = dictp->f.hs.suffix;
+ finchar = dictp->f.hs.prefix;
+ }
+ *--p = finchar;
+
+#ifdef DEBUG
+ if (--codelen != 0)
+ printf("bsd_decomp%d: short by %d after code 0x%x, max_ent=0x%x\n",
+ db->unit, codelen, incode, max_ent);
+#endif
+
+ if (extra) /* the KwKwK case again */
+ *wptr++ = finchar;
+
+ /*
+ * If not first code in a packet, and
+ * if not out of code space, then allocate a new code.
+ *
+ * Keep the hash table correct so it can be used
+ * with uncompressed packets.
+ */
+ if (oldcode != CLEAR && max_ent < db->maxmaxcode) {
+ struct bsd_dict *dictp2;
+ u_int32_t fcode;
+ u_int32_t hval, disp;
+
+ fcode = BSD_KEY(oldcode,finchar);
+ hval = BSD_HASH(oldcode,finchar,db->hshift);
+ dictp = &db->dict[hval];
+
+ /* look for a free hash table entry */
+ if (dictp->codem1 < max_ent) {
+ disp = (hval == 0) ? 1 : hval;
+ do {
+ hval += disp;
+ if (hval >= db->hsize)
+ hval -= db->hsize;
+ dictp = &db->dict[hval];
+ } while (dictp->codem1 < max_ent);
+ }
+
+ /*
+ * Invalidate previous hash table entry
+ * assigned this code, and then take it over
+ */
+ dictp2 = &db->dict[max_ent+1];
+ if (db->dict[dictp2->cptr].codem1 == max_ent) {
+ db->dict[dictp2->cptr].codem1 = BADCODEM1;
+ }
+ dictp2->cptr = hval;
+ dictp->codem1 = max_ent;
+ dictp->f.fcode = fcode;
+
+ db->max_ent = ++max_ent;
+ db->lens[max_ent] = db->lens[oldcode]+1;
+
+ /* Expand code size if needed. */
+ if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode) {
+ db->n_bits = ++n_bits;
+ tgtbitno = 32-n_bits;
+ }
+ }
+ oldcode = incode;
+ }
+ dmp->m_len = wptr - mtod(dmp, u_char *);
+
+ /*
+ * Keep the checkpoint right so that incompressible packets
+ * clear the dictionary at the right times.
+ */
+ db->bytes_out += ilen;
+ db->in_count += explen;
+ if (bsd_check(db) && db->debug) {
+ printf("bsd_decomp%d: peer should have cleared dictionary\n",
+ db->unit);
+ }
+
+ ++db->comp_count;
+ db->comp_bytes += ilen + BSD_OVHD;
+ ++db->uncomp_count;
+ db->uncomp_bytes += explen;
+
+ *dmpp = mret;
+ return DECOMP_OK;
+
+#ifdef DEBUG
+ bad:
+ if (codelen <= 0) {
+ printf("bsd_decomp%d: fell off end of chain ", db->unit);
+ printf("0x%x at 0x%x by 0x%x, max_ent=0x%x\n",
+ incode, finchar, db->dict[finchar].cptr, max_ent);
+ } else if (dictp->codem1 != finchar-1) {
+ printf("bsd_decomp%d: bad code chain 0x%x finchar=0x%x ",
+ db->unit, incode, finchar);
+ printf("oldcode=0x%x cptr=0x%x codem1=0x%x\n", oldcode,
+ db->dict[finchar].cptr, dictp->codem1);
+ }
+ m_freem(mret);
+ return DECOMP_FATALERROR;
+#endif /* DEBUG */
+}
+#endif /* DO_BSD_COMPRESS */
diff --git a/cpukit/libnetworking/net/ethernet.h b/cpukit/libnetworking/net/ethernet.h
new file mode 100644
index 0000000000..1f988d7b9e
--- /dev/null
+++ b/cpukit/libnetworking/net/ethernet.h
@@ -0,0 +1,65 @@
+/*
+ * Fundamental constants relating to ethernet.
+ *
+ * $Id$
+ *
+ */
+
+#ifndef _NET_ETHERNET_H_
+#define _NET_ETHERNET_H_
+
+#include <netinet/in.h>
+
+/*
+ * The number of bytes in an ethernet (MAC) address.
+ */
+#define ETHER_ADDR_LEN 6
+
+/*
+ * The number of bytes in the type field.
+ */
+#define ETHER_TYPE_LEN 2
+
+/*
+ * The number of bytes in the trailing CRC field.
+ */
+#define ETHER_CRC_LEN 4
+
+/*
+ * The length of the combined header.
+ */
+#define ETHER_HDR_LEN (ETHER_ADDR_LEN*2+ETHER_TYPE_LEN)
+
+/*
+ * The minimum packet length.
+ */
+#define ETHER_MIN_LEN 64
+
+/*
+ * The maximum packet length.
+ */
+#define ETHER_MAX_LEN 1518
+
+/*
+ * A macro to validate a length with
+ */
+#define ETHER_IS_VALID_LEN(foo) \
+ ((foo) >= ETHER_MIN_LEN && (foo) <= ETHER_MAX_LEN)
+
+/*
+ * Structure of a 10Mb/s Ethernet header.
+ */
+struct ether_header {
+ u_char ether_dhost[ETHER_ADDR_LEN];
+ u_char ether_shost[ETHER_ADDR_LEN];
+ u_short ether_type BYTE_PACK;
+};
+
+/*
+ * Structure of a 48-bit Ethernet address.
+ */
+struct ether_addr {
+ u_char octet[ETHER_ADDR_LEN];
+};
+
+#endif
diff --git a/cpukit/libnetworking/net/if.c b/cpukit/libnetworking/net/if.c
new file mode 100644
index 0000000000..6f42b29903
--- /dev/null
+++ b/cpukit/libnetworking/net/if.c
@@ -0,0 +1,794 @@
+/*
+ * Copyright (c) 1980, 1986, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.c 8.3 (Berkeley) 1/4/94
+ * $Id$
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/mbuf.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/protosw.h>
+#include <sys/kernel.h>
+#include <sys/ioctl.h>
+#include <sys/errno.h>
+#include <sys/syslog.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <net/radix.h>
+
+/*
+ * System initialization
+ */
+
+static int ifconf __P((int, caddr_t));
+ void ifinit __P((void *));
+static void if_qflush __P((struct ifqueue *));
+static void if_slowtimo __P((void *));
+static void link_rtrequest __P((int, struct rtentry *, struct sockaddr *));
+
+SYSINIT(interfaces, SI_SUB_PROTO_IF, SI_ORDER_FIRST, ifinit, NULL)
+
+
+int ifqmaxlen = IFQ_MAXLEN;
+struct ifnet *ifnet;
+
+/*
+ * Network interface utility routines.
+ *
+ * Routines with ifa_ifwith* names take sockaddr *'s as
+ * parameters.
+ *
+ * This routine assumes that it will be called at splimp() or higher.
+ */
+/* ARGSUSED*/
+void
+ifinit(dummy)
+ void *dummy;
+{
+ register struct ifnet *ifp;
+
+ for (ifp = ifnet; ifp; ifp = ifp->if_next)
+ if (ifp->if_snd.ifq_maxlen == 0)
+ ifp->if_snd.ifq_maxlen = ifqmaxlen;
+ if_slowtimo(0);
+}
+
+int if_index = 0;
+struct ifaddr **ifnet_addrs;
+
+
+/*
+ * Attach an interface to the
+ * list of "active" interfaces.
+ */
+void
+if_attach(ifp)
+ struct ifnet *ifp;
+{
+ unsigned socksize, ifasize;
+ int namelen, masklen;
+ char workbuf[64];
+ register struct ifnet **p = &ifnet;
+ register struct sockaddr_dl *sdl;
+ register struct ifaddr *ifa;
+ static int if_indexlim = 8;
+
+
+ while (*p)
+ p = &((*p)->if_next);
+ *p = ifp;
+ ifp->if_index = ++if_index;
+ microtime(&ifp->if_lastchange);
+ if (ifnet_addrs == 0 || if_index >= if_indexlim) {
+ unsigned n = (if_indexlim <<= 1) * sizeof(ifa);
+ struct ifaddr **q = (struct ifaddr **)
+ malloc(n, M_IFADDR, M_WAITOK);
+ bzero((caddr_t)q, n);
+ if (ifnet_addrs) {
+ bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2);
+ free((caddr_t)ifnet_addrs, M_IFADDR);
+ }
+ ifnet_addrs = q;
+ }
+ /*
+ * create a Link Level name for this device
+ */
+ namelen = sprintf(workbuf, "%s%d", ifp->if_name, ifp->if_unit);
+#define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
+ masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) + namelen;
+ socksize = masklen + ifp->if_addrlen;
+#define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
+ socksize = ROUNDUP(socksize);
+ if (socksize < sizeof(*sdl))
+ socksize = sizeof(*sdl);
+ ifasize = sizeof(*ifa) + 2 * socksize;
+ ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK);
+ if (ifa) {
+ bzero((caddr_t)ifa, ifasize);
+ sdl = (struct sockaddr_dl *)(ifa + 1);
+ sdl->sdl_len = socksize;
+ sdl->sdl_family = AF_LINK;
+ bcopy(workbuf, sdl->sdl_data, namelen);
+ sdl->sdl_nlen = namelen;
+ sdl->sdl_index = ifp->if_index;
+ sdl->sdl_type = ifp->if_type;
+ ifnet_addrs[if_index - 1] = ifa;
+ ifa->ifa_ifp = ifp;
+ ifa->ifa_next = ifp->if_addrlist;
+ ifa->ifa_rtrequest = link_rtrequest;
+ ifp->if_addrlist = ifa;
+ ifa->ifa_addr = (struct sockaddr *)sdl;
+
+ sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
+ ifa->ifa_netmask = (struct sockaddr *)sdl;
+ sdl->sdl_len = masklen;
+ while (namelen != 0)
+ sdl->sdl_data[--namelen] = 0xff;
+ }
+}
+/*
+ * Locate an interface based on a complete address.
+ */
+/*ARGSUSED*/
+struct ifaddr *
+ifa_ifwithaddr(addr)
+ register struct sockaddr *addr;
+{
+ register struct ifnet *ifp;
+ register struct ifaddr *ifa;
+
+#define equal(a1, a2) \
+ (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0)
+ for (ifp = ifnet; ifp; ifp = ifp->if_next)
+ for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
+ if (ifa->ifa_addr->sa_family != addr->sa_family)
+ continue;
+ if (equal(addr, ifa->ifa_addr))
+ return (ifa);
+ if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr &&
+ equal(ifa->ifa_broadaddr, addr))
+ return (ifa);
+ }
+ return ((struct ifaddr *)0);
+}
+/*
+ * Locate the point to point interface with a given destination address.
+ */
+/*ARGSUSED*/
+struct ifaddr *
+ifa_ifwithdstaddr(addr)
+ register struct sockaddr *addr;
+{
+ register struct ifnet *ifp;
+ register struct ifaddr *ifa;
+
+ for (ifp = ifnet; ifp; ifp = ifp->if_next)
+ if (ifp->if_flags & IFF_POINTOPOINT)
+ for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
+ if (ifa->ifa_addr->sa_family != addr->sa_family)
+ continue;
+ if (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr))
+ return (ifa);
+ }
+ return ((struct ifaddr *)0);
+}
+
+/*
+ * Find an interface on a specific network. If many, choice
+ * is most specific found.
+ */
+struct ifaddr *
+ifa_ifwithnet(addr)
+ struct sockaddr *addr;
+{
+ register struct ifnet *ifp;
+ register struct ifaddr *ifa;
+ struct ifaddr *ifa_maybe = (struct ifaddr *) 0;
+ u_int af = addr->sa_family;
+ char *addr_data = addr->sa_data, *cplim;
+
+ if (af == AF_LINK) {
+ register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr;
+ if (sdl->sdl_index && sdl->sdl_index <= if_index)
+ return (ifnet_addrs[sdl->sdl_index - 1]);
+ }
+ for (ifp = ifnet; ifp; ifp = ifp->if_next) {
+ for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
+ register char *cp, *cp2, *cp3;
+
+ if (ifa->ifa_addr->sa_family != af)
+ next: continue;
+ if (ifp->if_flags & IFF_POINTOPOINT) {
+ if (ifa->ifa_dstaddr != 0
+ && equal(addr, ifa->ifa_dstaddr))
+ return (ifa);
+ } else {
+ /*
+ * if we have a special address handler,
+ * then use it instead of the generic one.
+ */
+ if (ifa->ifa_claim_addr) {
+ if ((*ifa->ifa_claim_addr)(ifa, addr)) {
+ return (ifa);
+ } else {
+ continue;
+ }
+ }
+
+ /*
+ * Scan all the bits in the ifa's address.
+ * If a bit dissagrees with what we are
+ * looking for, mask it with the netmask
+ * to see if it really matters.
+ * (A byte at a time)
+ */
+ if (ifa->ifa_netmask == 0)
+ continue;
+ cp = addr_data;
+ cp2 = ifa->ifa_addr->sa_data;
+ cp3 = ifa->ifa_netmask->sa_data;
+ cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
+ while (cp3 < cplim)
+ if ((*cp++ ^ *cp2++) & *cp3++)
+ goto next;
+ if (ifa_maybe == 0 ||
+ rn_refines((caddr_t)ifa->ifa_netmask,
+ (caddr_t)ifa_maybe->ifa_netmask))
+ ifa_maybe = ifa;
+ }
+ }
+ }
+ return (ifa_maybe);
+}
+
+/*
+ * Find an interface address specific to an interface best matching
+ * a given address.
+ */
+struct ifaddr *
+ifaof_ifpforaddr(addr, ifp)
+ struct sockaddr *addr;
+ register struct ifnet *ifp;
+{
+ register struct ifaddr *ifa;
+ register char *cp, *cp2, *cp3;
+ register char *cplim;
+ struct ifaddr *ifa_maybe = 0;
+ u_int af = addr->sa_family;
+
+ if (af >= AF_MAX)
+ return (0);
+ for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
+ if (ifa->ifa_addr->sa_family != af)
+ continue;
+ if (ifa_maybe == 0)
+ ifa_maybe = ifa;
+ if (ifa->ifa_netmask == 0) {
+ if (equal(addr, ifa->ifa_addr) ||
+ (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)))
+ return (ifa);
+ continue;
+ }
+ if (ifp->if_flags & IFF_POINTOPOINT) {
+ if (equal(addr, ifa->ifa_dstaddr))
+ return (ifa);
+ } else {
+ cp = addr->sa_data;
+ cp2 = ifa->ifa_addr->sa_data;
+ cp3 = ifa->ifa_netmask->sa_data;
+ cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
+ for (; cp3 < cplim; cp3++)
+ if ((*cp++ ^ *cp2++) & *cp3)
+ break;
+ if (cp3 == cplim)
+ return (ifa);
+ }
+ }
+ return (ifa_maybe);
+}
+
+#include <net/route.h>
+
+/*
+ * Default action when installing a route with a Link Level gateway.
+ * Lookup an appropriate real ifa to point to.
+ * This should be moved to /sys/net/link.c eventually.
+ */
+static void
+link_rtrequest(cmd, rt, sa)
+ int cmd;
+ register struct rtentry *rt;
+ struct sockaddr *sa;
+{
+ register struct ifaddr *ifa;
+ struct sockaddr *dst;
+ struct ifnet *ifp;
+
+ if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
+ ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
+ return;
+ ifa = ifaof_ifpforaddr(dst, ifp);
+ if (ifa) {
+ IFAFREE(rt->rt_ifa);
+ rt->rt_ifa = ifa;
+ ifa->ifa_refcnt++;
+ if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
+ ifa->ifa_rtrequest(cmd, rt, sa);
+ }
+}
+
+/*
+ * Mark an interface down and notify protocols of
+ * the transition.
+ * NOTE: must be called at splnet or eqivalent.
+ */
+void
+if_down(ifp)
+ register struct ifnet *ifp;
+{
+ register struct ifaddr *ifa;
+
+ ifp->if_flags &= ~IFF_UP;
+ microtime(&ifp->if_lastchange);
+ for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
+ pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
+ if_qflush(&ifp->if_snd);
+ rt_ifmsg(ifp);
+}
+
+/*
+ * Mark an interface up and notify protocols of
+ * the transition.
+ * NOTE: must be called at splnet or eqivalent.
+ */
+void
+if_up(ifp)
+ register struct ifnet *ifp;
+{
+
+ ifp->if_flags |= IFF_UP;
+ microtime(&ifp->if_lastchange);
+#ifdef notyet
+ register struct ifaddr *ifa;
+ /* this has no effect on IP, and will kill all iso connections XXX */
+ for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
+ pfctlinput(PRC_IFUP, ifa->ifa_addr);
+#endif
+ rt_ifmsg(ifp);
+}
+
+/*
+ * Flush an interface queue.
+ */
+static void
+if_qflush(ifq)
+ register struct ifqueue *ifq;
+{
+ register struct mbuf *m, *n;
+
+ n = ifq->ifq_head;
+ while ((m = n) != 0) {
+ n = m->m_act;
+ m_freem(m);
+ }
+ ifq->ifq_head = 0;
+ ifq->ifq_tail = 0;
+ ifq->ifq_len = 0;
+}
+
+/*
+ * Handle interface watchdog timer routines. Called
+ * from softclock, we decrement timers (if set) and
+ * call the appropriate interface routine on expiration.
+ */
+static void
+if_slowtimo(arg)
+ void *arg;
+{
+ register struct ifnet *ifp;
+ int s = splimp();
+
+ for (ifp = ifnet; ifp; ifp = ifp->if_next) {
+ if (ifp->if_timer == 0 || --ifp->if_timer)
+ continue;
+ if (ifp->if_watchdog)
+ (*ifp->if_watchdog)(ifp);
+ }
+ splx(s);
+ timeout(if_slowtimo, (void *)0, hz / IFNET_SLOWHZ);
+}
+
+/*
+ * Map interface name to
+ * interface structure pointer.
+ */
+struct ifnet *
+ifunit(name)
+ register char *name;
+{
+ register char *cp;
+ register struct ifnet *ifp;
+ int unit;
+ unsigned len;
+ char *ep, c;
+
+ for (cp = name; cp < name + IFNAMSIZ && *cp; cp++)
+ if (*cp >= '0' && *cp <= '9')
+ break;
+ if (*cp == '\0' || cp == name + IFNAMSIZ)
+ return ((struct ifnet *)0);
+ /*
+ * Save first char of unit, and pointer to it,
+ * so we can put a null there to avoid matching
+ * initial substrings of interface names.
+ */
+ len = cp - name + 1;
+ c = *cp;
+ ep = cp;
+ for (unit = 0; *cp >= '0' && *cp <= '9'; )
+ unit = unit * 10 + *cp++ - '0';
+ if (*cp != '\0')
+ return 0; /* no trailing garbage allowed */
+ *ep = 0;
+ for (ifp = ifnet; ifp; ifp = ifp->if_next) {
+ if (bcmp(ifp->if_name, name, len))
+ continue;
+ if (unit == ifp->if_unit)
+ break;
+ }
+ *ep = c;
+ return (ifp);
+}
+
+/*
+ * Interface ioctls.
+ */
+int
+ifioctl(so, cmd, data, p)
+ struct socket *so;
+ int cmd;
+ caddr_t data;
+ struct proc *p;
+{
+ register struct ifnet *ifp;
+ register struct ifreq *ifr;
+ int error;
+
+ switch (cmd) {
+
+ case SIOCGIFCONF:
+ case OSIOCGIFCONF:
+ return (ifconf(cmd, data));
+ }
+ ifr = (struct ifreq *)data;
+ ifp = ifunit(ifr->ifr_name);
+ if (ifp == 0)
+ return (ENXIO);
+ switch (cmd) {
+
+ case SIOCGIFFLAGS:
+ ifr->ifr_flags = ifp->if_flags;
+ break;
+
+ case SIOCGIFMETRIC:
+ ifr->ifr_metric = ifp->if_metric;
+ break;
+
+ case SIOCGIFMTU:
+ ifr->ifr_mtu = ifp->if_mtu;
+ break;
+
+ case SIOCGIFPHYS:
+ ifr->ifr_phys = ifp->if_physical;
+ break;
+
+ case SIOCSIFFLAGS:
+ error = suser(p->p_ucred, &p->p_acflag);
+ if (error)
+ return (error);
+ if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
+ int s = splimp();
+ if_down(ifp);
+ splx(s);
+ }
+ if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) {
+ int s = splimp();
+ if_up(ifp);
+ splx(s);
+ }
+ ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
+ (ifr->ifr_flags &~ IFF_CANTCHANGE);
+ if (ifp->if_ioctl)
+ (void) (*ifp->if_ioctl)(ifp, cmd, data);
+ microtime(&ifp->if_lastchange);
+ break;
+
+ case SIOCSIFMETRIC:
+ error = suser(p->p_ucred, &p->p_acflag);
+ if (error)
+ return (error);
+ ifp->if_metric = ifr->ifr_metric;
+ microtime(&ifp->if_lastchange);
+ break;
+
+ case SIOCSIFPHYS:
+ error = suser(p->p_ucred, &p->p_acflag);
+ if (error)
+ return error;
+ if (!ifp->if_ioctl)
+ return EOPNOTSUPP;
+ error = (*ifp->if_ioctl)(ifp, cmd, data);
+ if (error == 0)
+ microtime(&ifp->if_lastchange);
+ return(error);
+
+ case SIOCSIFMTU:
+ error = suser(p->p_ucred, &p->p_acflag);
+ if (error)
+ return (error);
+ if (ifp->if_ioctl == NULL)
+ return (EOPNOTSUPP);
+ /*
+ * 72 was chosen below because it is the size of a TCP/IP
+ * header (40) + the minimum mss (32).
+ */
+ if (ifr->ifr_mtu < 72 || ifr->ifr_mtu > 65535)
+ return (EINVAL);
+ error = (*ifp->if_ioctl)(ifp, cmd, data);
+ if (error == 0)
+ microtime(&ifp->if_lastchange);
+ return(error);
+
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ error = suser(p->p_ucred, &p->p_acflag);
+ if (error)
+ return (error);
+ if (ifp->if_ioctl == NULL)
+ return (EOPNOTSUPP);
+ error = (*ifp->if_ioctl)(ifp, cmd, data);
+ if (error == 0 )
+ microtime(&ifp->if_lastchange);
+ return(error);
+
+ case SIOCSIFMEDIA:
+ error = suser(p->p_ucred, &p->p_acflag);
+ if (error)
+ return (error);
+ if (ifp->if_ioctl == 0)
+ return (EOPNOTSUPP);
+ error = (*ifp->if_ioctl)(ifp, cmd, data);
+ if (error == 0)
+ microtime(&ifp->if_lastchange);
+ return error;
+
+ case SIOCGIFMEDIA:
+ if (ifp->if_ioctl == 0)
+ return (EOPNOTSUPP);
+ return ((*ifp->if_ioctl)(ifp, cmd, data));
+
+ default:
+ if (so->so_proto == 0)
+ return (EOPNOTSUPP);
+#ifndef COMPAT_43
+ return ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd,
+ data,
+ ifp));
+#else
+ {
+ int ocmd = cmd;
+
+ switch (cmd) {
+
+ case SIOCSIFDSTADDR:
+ case SIOCSIFADDR:
+ case SIOCSIFBRDADDR:
+ case SIOCSIFNETMASK:
+#if BYTE_ORDER != BIG_ENDIAN
+ if (ifr->ifr_addr.sa_family == 0 &&
+ ifr->ifr_addr.sa_len < 16) {
+ ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
+ ifr->ifr_addr.sa_len = 16;
+ }
+#else
+ if (ifr->ifr_addr.sa_len == 0)
+ ifr->ifr_addr.sa_len = 16;
+#endif
+ break;
+
+ case OSIOCGIFADDR:
+ cmd = SIOCGIFADDR;
+ break;
+
+ case OSIOCGIFDSTADDR:
+ cmd = SIOCGIFDSTADDR;
+ break;
+
+ case OSIOCGIFBRDADDR:
+ cmd = SIOCGIFBRDADDR;
+ break;
+
+ case OSIOCGIFNETMASK:
+ cmd = SIOCGIFNETMASK;
+ }
+ error = ((*so->so_proto->pr_usrreqs->pru_control)(so,
+ cmd,
+ data,
+ ifp));
+ switch (ocmd) {
+
+ case OSIOCGIFADDR:
+ case OSIOCGIFDSTADDR:
+ case OSIOCGIFBRDADDR:
+ case OSIOCGIFNETMASK:
+ *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
+ }
+ return (error);
+
+ }
+#endif
+
+ /*
+ * RTEMS additions for setting/getting `tap' function
+ */
+ case SIOCSIFTAP:
+ ifp->if_tap = ifr->ifr_tap;
+ return 0;
+
+ case SIOCGIFTAP:
+ ifr->ifr_tap = ifp->if_tap;
+ return 0;
+ }
+ return (0);
+}
+
+/*
+ * Set/clear promiscuous mode on interface ifp based on the truth value
+ * of pswitch. The calls are reference counted so that only the first
+ * "on" request actually has an effect, as does the final "off" request.
+ * Results are undefined if the "off" and "on" requests are not matched.
+ */
+int
+ifpromisc(ifp, pswitch)
+ struct ifnet *ifp;
+ int pswitch;
+{
+ struct ifreq ifr;
+
+ if (pswitch) {
+ /*
+ * If the device is not configured up, we cannot put it in
+ * promiscuous mode.
+ */
+ if ((ifp->if_flags & IFF_UP) == 0)
+ return (ENETDOWN);
+ if (ifp->if_pcount++ != 0)
+ return (0);
+ ifp->if_flags |= IFF_PROMISC;
+ log(LOG_INFO, "%s%d: promiscuous mode enabled\n",
+ ifp->if_name, ifp->if_unit);
+ } else {
+ if (--ifp->if_pcount > 0)
+ return (0);
+ ifp->if_flags &= ~IFF_PROMISC;
+ }
+ ifr.ifr_flags = ifp->if_flags;
+ return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr));
+}
+
+/*
+ * Return interface configuration
+ * of system. List may be used
+ * in later ioctl's (above) to get
+ * other information.
+ */
+/*ARGSUSED*/
+static int
+ifconf(cmd, data)
+ int cmd;
+ caddr_t data;
+{
+ register struct ifconf *ifc = (struct ifconf *)data;
+ register struct ifnet *ifp = ifnet;
+ register struct ifaddr *ifa;
+ struct ifreq ifr, *ifrp;
+ int space = ifc->ifc_len, error = 0;
+
+ ifrp = ifc->ifc_req;
+ for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) {
+ char workbuf[64];
+ int ifnlen;
+
+ ifnlen = sprintf(workbuf, "%s%d", ifp->if_name, ifp->if_unit);
+ if(ifnlen + 1 > sizeof ifr.ifr_name) {
+ error = ENAMETOOLONG;
+ } else {
+ strcpy(ifr.ifr_name, workbuf);
+ }
+
+ if ((ifa = ifp->if_addrlist) == 0) {
+ bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
+ error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
+ sizeof (ifr));
+ if (error)
+ break;
+ space -= sizeof (ifr), ifrp++;
+ } else
+ for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) {
+ register struct sockaddr *sa = ifa->ifa_addr;
+#ifdef COMPAT_43
+ if (cmd == OSIOCGIFCONF) {
+ struct osockaddr *osa =
+ (struct osockaddr *)&ifr.ifr_addr;
+ ifr.ifr_addr = *sa;
+ osa->sa_family = sa->sa_family;
+ error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
+ sizeof (ifr));
+ ifrp++;
+ } else
+#endif
+ if (sa->sa_len <= sizeof(*sa)) {
+ ifr.ifr_addr = *sa;
+ error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
+ sizeof (ifr));
+ ifrp++;
+ } else {
+ space -= sa->sa_len - sizeof(*sa);
+ if (space < sizeof (ifr))
+ break;
+ error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
+ sizeof (ifr.ifr_name));
+ if (error == 0)
+ error = copyout((caddr_t)sa,
+ (caddr_t)&ifrp->ifr_addr, sa->sa_len);
+ ifrp = (struct ifreq *)
+ (sa->sa_len + (caddr_t)&ifrp->ifr_addr);
+ }
+ if (error)
+ break;
+ space -= sizeof (ifr);
+ }
+ }
+ ifc->ifc_len -= space;
+ return (error);
+}
+
+SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW, 0, "Link layers");
+SYSCTL_NODE(_net_link, 0, generic, CTLFLAG_RW, 0, "Generic link-management");
diff --git a/cpukit/libnetworking/net/if.h b/cpukit/libnetworking/net/if.h
new file mode 100644
index 0000000000..08a74953f0
--- /dev/null
+++ b/cpukit/libnetworking/net/if.h
@@ -0,0 +1,474 @@
+/*
+ * Copyright (c) 1982, 1986, 1989, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.h 8.1 (Berkeley) 6/10/93
+ * $Id$
+ */
+
+#ifndef _NET_IF_H_
+#define _NET_IF_H_
+
+/*
+ * Structures defining a network interface, providing a packet
+ * transport mechanism (ala level 0 of the PUP protocols).
+ *
+ * Each interface accepts output datagrams of a specified maximum
+ * length, and provides higher level routines with input datagrams
+ * received from its medium.
+ *
+ * Output occurs when the routine if_output is called, with three parameters:
+ * (*ifp->if_output)(ifp, m, dst, rt)
+ * Here m is the mbuf chain to be sent and dst is the destination address.
+ * The output routine encapsulates the supplied datagram if necessary,
+ * and then transmits it on its medium.
+ *
+ * On input, each interface unwraps the data received by it, and either
+ * places it on the input queue of a internetwork datagram routine
+ * and posts the associated software interrupt, or passes the datagram to a raw
+ * packet input routine.
+ *
+ * Routines exist for locating interfaces by their addresses
+ * or for locating a interface on a certain network, as well as more general
+ * routing and gateway routines maintaining information used to locate
+ * interfaces. These routines live in the files if.c and route.c
+ */
+
+#ifndef _TIME_ /* XXX fast fix for SNMP, going away soon */
+#include <sys/time.h>
+#endif
+
+#ifdef __STDC__
+/*
+ * Forward structure declarations for function prototypes [sic].
+ */
+struct mbuf;
+struct proc;
+struct rtentry;
+struct socket;
+struct ether_header;
+#endif
+
+/*
+ * Structure describing information about an interface
+ * which may be of interest to management entities.
+ */
+struct if_data {
+ /* generic interface information */
+ u_char ifi_type; /* ethernet, tokenring, etc */
+ u_char ifi_physical; /* e.g., AUI, Thinnet, 10base-T, etc */
+ u_char ifi_addrlen; /* media address length */
+ u_char ifi_hdrlen; /* media header length */
+ u_char ifi_recvquota; /* polling quota for receive intrs */
+ u_char ifi_xmitquota; /* polling quota for xmit intrs */
+ u_long ifi_mtu; /* maximum transmission unit */
+ u_long ifi_metric; /* routing metric (external only) */
+ u_long ifi_baudrate; /* linespeed */
+ /* volatile statistics */
+ u_long ifi_ipackets; /* packets received on interface */
+ u_long ifi_ierrors; /* input errors on interface */
+ u_long ifi_opackets; /* packets sent on interface */
+ u_long ifi_oerrors; /* output errors on interface */
+ u_long ifi_collisions; /* collisions on csma interfaces */
+ u_long ifi_ibytes; /* total number of octets received */
+ u_long ifi_obytes; /* total number of octets sent */
+ u_long ifi_imcasts; /* packets received via multicast */
+ u_long ifi_omcasts; /* packets sent via multicast */
+ u_long ifi_iqdrops; /* dropped on input, this interface */
+ u_long ifi_noproto; /* destined for unsupported protocol */
+ u_long ifi_recvtiming; /* usec spent receiving when timing */
+ u_long ifi_xmittiming; /* usec spent xmitting when timing */
+ struct timeval ifi_lastchange; /* time of last administrative change */
+};
+
+/*
+ * Structure defining a queue for a network interface.
+ */
+struct ifqueue {
+ struct mbuf *ifq_head;
+ struct mbuf *ifq_tail;
+ int ifq_len;
+ int ifq_maxlen;
+ int ifq_drops;
+};
+
+/*
+ * Structure defining a network interface.
+ *
+ * (Would like to call this struct ``if'', but C isn't PL/1.)
+ */
+struct ifnet {
+ void *if_softc; /* pointer to driver state */
+ char *if_name; /* name, e.g. ``en'' or ``lo'' */
+ struct ifnet *if_next; /* all struct ifnets are chained */
+ struct ifaddr *if_addrlist; /* linked list of addresses per if */
+ int if_pcount; /* number of promiscuous listeners */
+ struct bpf_if *if_bpf; /* packet filter structure */
+ u_short if_index; /* numeric abbreviation for this if */
+ short if_unit; /* sub-unit for lower level driver */
+ short if_timer; /* time 'til if_watchdog called */
+ short if_flags; /* up/down, broadcast, etc. */
+ int if_ipending; /* interrupts pending */
+ void *if_linkmib; /* link-type-specific MIB data */
+ size_t if_linkmiblen; /* length of above data */
+ struct if_data if_data;
+/* procedure handles */
+ int (*if_output) /* output routine (enqueue) */
+ __P((struct ifnet *, struct mbuf *, struct sockaddr *,
+ struct rtentry *));
+ void (*if_start) /* initiate output routine */
+ __P((struct ifnet *));
+ int (*if_done) /* output complete routine */
+ __P((struct ifnet *)); /* (XXX not used; fake prototype) */
+ int (*if_ioctl) /* ioctl routine */
+ __P((struct ifnet *, int, caddr_t));
+ void (*if_watchdog) /* timer routine */
+ __P((struct ifnet *));
+ int (*if_poll_recv) /* polled receive routine */
+ __P((struct ifnet *, int *));
+ int (*if_poll_xmit) /* polled transmit routine */
+ __P((struct ifnet *, int *));
+ void (*if_poll_intren) /* polled interrupt reenable routine */
+ __P((struct ifnet *));
+ void (*if_poll_slowinput) /* input routine for slow devices */
+ __P((struct ifnet *, struct mbuf *));
+ void (*if_init) /* Init routine */
+ __P((void *));
+ int (*if_tap) /* Packet filter routine */
+ (struct ifnet *, struct ether_header *, struct mbuf *);
+ struct ifqueue if_snd; /* output queue */
+ struct ifqueue *if_poll_slowq; /* input queue for slow devices */
+};
+typedef void if_init_f_t __P((void *));
+
+#define if_mtu if_data.ifi_mtu
+#define if_type if_data.ifi_type
+#define if_physical if_data.ifi_physical
+#define if_addrlen if_data.ifi_addrlen
+#define if_hdrlen if_data.ifi_hdrlen
+#define if_metric if_data.ifi_metric
+#define if_baudrate if_data.ifi_baudrate
+#define if_ipackets if_data.ifi_ipackets
+#define if_ierrors if_data.ifi_ierrors
+#define if_opackets if_data.ifi_opackets
+#define if_oerrors if_data.ifi_oerrors
+#define if_collisions if_data.ifi_collisions
+#define if_ibytes if_data.ifi_ibytes
+#define if_obytes if_data.ifi_obytes
+#define if_imcasts if_data.ifi_imcasts
+#define if_omcasts if_data.ifi_omcasts
+#define if_iqdrops if_data.ifi_iqdrops
+#define if_noproto if_data.ifi_noproto
+#define if_lastchange if_data.ifi_lastchange
+#define if_recvquota if_data.ifi_recvquota
+#define if_xmitquota if_data.ifi_xmitquota
+#define if_rawoutput(if, m, sa) if_output(if, m, sa, (struct rtentry *)0)
+
+#define IFF_UP 0x1 /* interface is up */
+#define IFF_BROADCAST 0x2 /* broadcast address valid */
+#define IFF_DEBUG 0x4 /* turn on debugging */
+#define IFF_LOOPBACK 0x8 /* is a loopback net */
+#define IFF_POINTOPOINT 0x10 /* interface is point-to-point link */
+/*#define IFF_NOTRAILERS 0x20 * obsolete: avoid use of trailers */
+#define IFF_RUNNING 0x40 /* resources allocated */
+#define IFF_NOARP 0x80 /* no address resolution protocol */
+#define IFF_PROMISC 0x100 /* receive all packets */
+#define IFF_ALLMULTI 0x200 /* receive all multicast packets */
+#define IFF_OACTIVE 0x400 /* transmission in progress */
+#define IFF_SIMPLEX 0x800 /* can't hear own transmissions */
+#define IFF_LINK0 0x1000 /* per link layer defined bit */
+#define IFF_LINK1 0x2000 /* per link layer defined bit */
+#define IFF_LINK2 0x4000 /* per link layer defined bit */
+#define IFF_ALTPHYS IFF_LINK2 /* use alternate physical connection */
+#define IFF_MULTICAST 0x8000 /* supports multicast */
+
+/* flags set internally only: */
+#define IFF_CANTCHANGE \
+ (IFF_BROADCAST|IFF_POINTOPOINT|IFF_RUNNING|IFF_OACTIVE|\
+ IFF_SIMPLEX|IFF_MULTICAST|IFF_ALLMULTI)
+
+
+/*
+ * These really don't belong here, but there's no other obviously appropriate
+ * location.
+ */
+#define IFP_AUI 0
+#define IFP_10BASE2 1
+#define IFP_10BASET 2
+/* etc. */
+
+/*
+ * Bit values in if_ipending
+ */
+#define IFI_RECV 1 /* I want to receive */
+#define IFI_XMIT 2 /* I want to transmit */
+
+/*
+ * Output queues (ifp->if_snd) and slow device input queues (*ifp->if_slowq)
+ * are queues of messages stored on ifqueue structures
+ * (defined above). Entries are added to and deleted from these structures
+ * by these macros, which should be called with ipl raised to splimp().
+ */
+#define IF_QFULL(ifq) ((ifq)->ifq_len >= (ifq)->ifq_maxlen)
+#define IF_DROP(ifq) ((ifq)->ifq_drops++)
+#define IF_ENQUEUE(ifq, m) { \
+/* printf(" IF_ENQUEUE: %p %p\n", ifq, m ); */ \
+ (m)->m_nextpkt = 0; \
+ if ((ifq)->ifq_tail == 0) \
+ (ifq)->ifq_head = m; \
+ else \
+ (ifq)->ifq_tail->m_nextpkt = m; \
+ (ifq)->ifq_tail = m; \
+ (ifq)->ifq_len++; \
+}
+#define IF_PREPEND(ifq, m) { \
+/* printf(" IF_PREPEND: %p %p\n", ifq, m ); */ \
+ (m)->m_nextpkt = (ifq)->ifq_head; \
+ if ((ifq)->ifq_tail == 0) \
+ (ifq)->ifq_tail = (m); \
+ (ifq)->ifq_head = (m); \
+ (ifq)->ifq_len++; \
+}
+#define IF_DEQUEUE(ifq, m) { \
+ (m) = (ifq)->ifq_head; \
+ if (m) { \
+/* printf(" IF_DEQUEUE: %p %p\n", ifq, m ); */ \
+ if (((ifq)->ifq_head = (m)->m_nextpkt) == 0) \
+ (ifq)->ifq_tail = 0; \
+ (m)->m_nextpkt = 0; \
+ (ifq)->ifq_len--; \
+ } \
+}
+
+#ifdef _KERNEL
+#define IF_ENQ_DROP(ifq, m) if_enq_drop(ifq, m)
+
+#if defined(__GNUC__) && defined(MT_HEADER)
+static inline int
+if_queue_drop(struct ifqueue *ifq, struct mbuf *m)
+{
+ IF_DROP(ifq);
+ return 0;
+}
+
+static inline int
+if_enq_drop(struct ifqueue *ifq, struct mbuf *m)
+{
+ if (IF_QFULL(ifq) &&
+ !if_queue_drop(ifq, m))
+ return 0;
+ IF_ENQUEUE(ifq, m);
+ return 1;
+}
+#else
+
+#ifdef MT_HEADER
+int if_enq_drop __P((struct ifqueue *, struct mbuf *));
+#endif
+
+#endif
+#endif /* _KERNEL */
+
+#define IFQ_MAXLEN 50
+#define IFNET_SLOWHZ 1 /* granularity is 1 second */
+
+/*
+ * The ifaddr structure contains information about one address
+ * of an interface. They are maintained by the different address families,
+ * are allocated and attached when an address is set, and are linked
+ * together so all addresses for an interface can be located.
+ */
+struct ifaddr {
+ struct sockaddr *ifa_addr; /* address of interface */
+ struct sockaddr *ifa_dstaddr; /* other end of p-to-p link */
+#define ifa_broadaddr ifa_dstaddr /* broadcast address interface */
+ struct sockaddr *ifa_netmask; /* used to determine subnet */
+ struct ifnet *ifa_ifp; /* back-pointer to interface */
+ struct ifaddr *ifa_next; /* next address for interface */
+ void (*ifa_rtrequest) /* check or clean routes (+ or -)'d */
+ __P((int, struct rtentry *, struct sockaddr *));
+ u_short ifa_flags; /* mostly rt_flags for cloning */
+ short ifa_refcnt; /* references to this structure */
+ int ifa_metric; /* cost of going out this interface */
+#ifdef notdef
+ struct rtentry *ifa_rt; /* XXXX for ROUTETOIF ????? */
+#endif
+ int (*ifa_claim_addr) /* check if an addr goes to this if */
+ __P((struct ifaddr *, struct sockaddr *));
+
+};
+#define IFA_ROUTE RTF_UP /* route installed */
+
+/*
+ * Message format for use in obtaining information about interfaces
+ * from getkerninfo and the routing socket
+ */
+struct if_msghdr {
+ u_short ifm_msglen; /* to skip over non-understood messages */
+ u_char ifm_version; /* future binary compatability */
+ u_char ifm_type; /* message type */
+ int ifm_addrs; /* like rtm_addrs */
+ int ifm_flags; /* value of if_flags */
+ u_short ifm_index; /* index for associated ifp */
+ struct if_data ifm_data;/* statistics and other data about if */
+};
+
+/*
+ * Message format for use in obtaining information about interface addresses
+ * from getkerninfo and the routing socket
+ */
+struct ifa_msghdr {
+ u_short ifam_msglen; /* to skip over non-understood messages */
+ u_char ifam_version; /* future binary compatability */
+ u_char ifam_type; /* message type */
+ int ifam_addrs; /* like rtm_addrs */
+ int ifam_flags; /* value of ifa_flags */
+ u_short ifam_index; /* index for associated ifp */
+ int ifam_metric; /* value of ifa_metric */
+};
+
+/*
+ * Interface request structure used for socket
+ * ioctl's. All interface ioctl's must have parameter
+ * definitions which begin with ifr_name. The
+ * remainder may be interface specific.
+ */
+struct ifreq {
+#define IFNAMSIZ 16
+ char ifr_name[IFNAMSIZ]; /* if name, e.g. "en0" */
+ union {
+ struct sockaddr ifru_addr;
+ struct sockaddr ifru_dstaddr;
+ struct sockaddr ifru_broadaddr;
+ short ifru_flags;
+ int ifru_metric;
+ int ifru_mtu;
+ int ifru_phys;
+ int ifru_media;
+ caddr_t ifru_data;
+ int (*ifru_tap)(struct ifnet *, struct ether_header *, struct mbuf *);
+ } ifr_ifru;
+#define ifr_addr ifr_ifru.ifru_addr /* address */
+#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-to-p link */
+#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */
+#define ifr_flags ifr_ifru.ifru_flags /* flags */
+#define ifr_metric ifr_ifru.ifru_metric /* metric */
+#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */
+#define ifr_phys ifr_ifru.ifru_phys /* physical wire */
+#define ifr_media ifr_ifru.ifru_media /* physical media */
+#define ifr_data ifr_ifru.ifru_data /* for use by interface */
+#define ifr_tap ifr_ifru.ifru_tap /* tap function */
+};
+
+struct ifaliasreq {
+ char ifra_name[IFNAMSIZ]; /* if name, e.g. "en0" */
+ struct sockaddr ifra_addr;
+ struct sockaddr ifra_broadaddr;
+ struct sockaddr ifra_mask;
+};
+
+struct ifmediareq {
+ char ifm_name[IFNAMSIZ]; /* if name, e.g. "en0" */
+ int ifm_current; /* current media options */
+ int ifm_mask; /* don't care mask */
+ int ifm_status; /* media status */
+ int ifm_active; /* active options */
+ int ifm_count; /* # entries in ifm_ulist array */
+ int *ifm_ulist; /* media words */
+};
+/*
+ * Structure used in SIOCGIFCONF request.
+ * Used to retrieve interface configuration
+ * for machine (useful for programs which
+ * must know all networks accessible).
+ */
+struct ifconf {
+ int ifc_len; /* size of associated buffer */
+ union {
+ caddr_t ifcu_buf;
+ struct ifreq *ifcu_req;
+ } ifc_ifcu;
+#define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */
+#define ifc_req ifc_ifcu.ifcu_req /* array of structures returned */
+};
+
+#include <net/if_arp.h>
+
+#ifdef _KERNEL
+#define IFAFREE(ifa) \
+ if ((ifa)->ifa_refcnt <= 0) \
+ ifafree(ifa); \
+ else \
+ (ifa)->ifa_refcnt--;
+
+extern struct ifnet *ifnet;
+extern int ifqmaxlen;
+extern struct ifnet loif[];
+extern int if_index;
+extern struct ifaddr **ifnet_addrs;
+
+void ether_ifattach __P((struct ifnet *));
+void ether_input __P((struct ifnet *, struct ether_header *, struct mbuf *));
+int ether_output __P((struct ifnet *,
+ struct mbuf *, struct sockaddr *, struct rtentry *));
+int ether_ioctl __P((struct ifnet *, int , caddr_t ));
+
+void if_attach __P((struct ifnet *));
+void if_down __P((struct ifnet *));
+void if_up __P((struct ifnet *));
+#ifdef vax
+void ifubareset __P((int));
+#endif
+/*void ifinit __P((void));*/ /* declared in systm.h for main() */
+int ifioctl __P((struct socket *, int, caddr_t, struct proc *));
+int ifpromisc __P((struct ifnet *, int));
+struct ifnet *ifunit __P((char *));
+
+int if_poll_recv_slow __P((struct ifnet *ifp, int *quotap));
+void if_poll_xmit_slow __P((struct ifnet *ifp, int *quotap));
+void if_poll_throttle __P((void));
+void if_poll_unthrottle __P((void *));
+void if_poll_init __P((void));
+void if_poll __P((void));
+
+struct ifaddr *ifa_ifwithaddr __P((struct sockaddr *));
+struct ifaddr *ifa_ifwithdstaddr __P((struct sockaddr *));
+struct ifaddr *ifa_ifwithnet __P((struct sockaddr *));
+struct ifaddr *ifa_ifwithroute __P((int, struct sockaddr *,
+ struct sockaddr *));
+struct ifaddr *ifaof_ifpforaddr __P((struct sockaddr *, struct ifnet *));
+void ifafree __P((struct ifaddr *));
+
+int looutput __P((struct ifnet *,
+ struct mbuf *, struct sockaddr *, struct rtentry *));
+#endif /* _KERNEL */
+
+#endif /* !_NET_IF_H_ */
diff --git a/cpukit/libnetworking/net/if_arp.h b/cpukit/libnetworking/net/if_arp.h
new file mode 100644
index 0000000000..a581c21558
--- /dev/null
+++ b/cpukit/libnetworking/net/if_arp.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 1986, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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_arp.h 8.1 (Berkeley) 6/10/93
+ * $Id$
+ */
+
+#ifndef _NET_IF_ARP_H_
+#define _NET_IF_ARP_H_
+
+#include <netinet/in.h>
+/*
+ * Address Resolution Protocol.
+ *
+ * See RFC 826 for protocol description. ARP packets are variable
+ * in size; the arphdr structure defines the fixed-length portion.
+ * Protocol type values are the same as those for 10 Mb/s Ethernet.
+ * It is followed by the variable-sized fields ar_sha, arp_spa,
+ * arp_tha and arp_tpa in that order, according to the lengths
+ * specified. Field names used correspond to RFC 826.
+ */
+struct arphdr {
+ u_short ar_hrd BYTE_PACK; /* format of hardware address */
+#define ARPHRD_ETHER 1 /* ethernet hardware format */
+#define ARPHRD_FRELAY 15 /* frame relay hardware format */
+ u_short ar_pro BYTE_PACK; /* format of protocol address */
+ u_char ar_hln BYTE_PACK; /* length of hardware address */
+ u_char ar_pln BYTE_PACK; /* length of protocol address */
+ u_short ar_op BYTE_PACK; /* one of: */
+#define ARPOP_REQUEST 1 /* request to resolve address */
+#define ARPOP_REPLY 2 /* response to previous request */
+#define ARPOP_REVREQUEST 3 /* request protocol address given hardware */
+#define ARPOP_REVREPLY 4 /* response giving protocol address */
+#define ARPOP_INVREQUEST 8 /* request to identify peer */
+#define ARPOP_INVREPLY 9 /* response identifying peer */
+/*
+ * The remaining fields are variable in size,
+ * according to the sizes above.
+ */
+#ifdef COMMENT_ONLY
+ u_char ar_sha[]; /* sender hardware address */
+ u_char ar_spa[]; /* sender protocol address */
+ u_char ar_tha[]; /* target hardware address */
+ u_char ar_tpa[]; /* target protocol address */
+#endif
+};
+
+/*
+ * ARP ioctl request
+ */
+struct arpreq {
+ struct sockaddr arp_pa; /* protocol address */
+ struct sockaddr arp_ha; /* hardware address */
+ int arp_flags; /* flags */
+};
+/* arp_flags and at_flags field values */
+#define ATF_INUSE 0x01 /* entry in use */
+#define ATF_COM 0x02 /* completed entry (enaddr valid) */
+#define ATF_PERM 0x04 /* permanent entry */
+#define ATF_PUBL 0x08 /* publish entry (respond for other host) */
+#define ATF_USETRAILERS 0x10 /* has requested trailers */
+
+#endif /* !_NET_IF_ARP_H_ */
diff --git a/cpukit/libnetworking/net/if_dl.h b/cpukit/libnetworking/net/if_dl.h
new file mode 100644
index 0000000000..d99d15097b
--- /dev/null
+++ b/cpukit/libnetworking/net/if_dl.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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_dl.h 8.1 (Berkeley) 6/10/93
+ * $Id$
+ */
+
+#ifndef _NET_IF_DL_H_
+#define _NET_IF_DL_H_
+
+/*
+ * A Link-Level Sockaddr may specify the interface in one of two
+ * ways: either by means of a system-provided index number (computed
+ * anew and possibly differently on every reboot), or by a human-readable
+ * string such as "il0" (for managerial convenience).
+ *
+ * Census taking actions, such as something akin to SIOCGCONF would return
+ * both the index and the human name.
+ *
+ * High volume transactions (such as giving a link-level ``from'' address
+ * in a recvfrom or recvmsg call) may be likely only to provide the indexed
+ * form, (which requires fewer copy operations and less space).
+ *
+ * The form and interpretation of the link-level address is purely a matter
+ * of convention between the device driver and its consumers; however, it is
+ * expected that all drivers for an interface of a given if_type will agree.
+ */
+
+/*
+ * Structure of a Link-Level sockaddr:
+ */
+struct sockaddr_dl {
+ u_char sdl_len; /* Total length of sockaddr */
+ u_char sdl_family; /* AF_DLI */
+ u_short sdl_index; /* if != 0, system given index for interface */
+ u_char sdl_type; /* interface type */
+ u_char sdl_nlen; /* interface name length, no trailing 0 reqd. */
+ u_char sdl_alen; /* link level address length */
+ u_char sdl_slen; /* link layer selector length */
+ char sdl_data[12]; /* minimum work area, can be larger;
+ contains both if name and ll address */
+};
+
+#define LLADDR(s) ((caddr_t)((s)->sdl_data + (s)->sdl_nlen))
+
+#ifndef _KERNEL
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+void link_addr __P((const char *, struct sockaddr_dl *));
+char *link_ntoa __P((const struct sockaddr_dl *));
+__END_DECLS
+
+#endif /* !_KERNEL */
+
+#endif
diff --git a/cpukit/libnetworking/net/if_ethersubr.c b/cpukit/libnetworking/net/if_ethersubr.c
new file mode 100644
index 0000000000..bff084b0f8
--- /dev/null
+++ b/cpukit/libnetworking/net/if_ethersubr.c
@@ -0,0 +1,998 @@
+/*
+ * Copyright (c) 1982, 1989, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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_ethersubr.c 8.1 (Berkeley) 6/10/93
+ * $Id$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/errno.h>
+#include <sys/syslog.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/netisr.h>
+#include <net/route.h>
+#include <net/if_llc.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <net/ethernet.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_var.h>
+#endif
+#include <netinet/if_ether.h>
+
+#ifdef IPX
+#include <netipx/ipx.h>
+#include <netipx/ipx_if.h>
+#endif
+
+#ifdef NS
+#include <netns/ns.h>
+#include <netns/ns_if.h>
+ushort ns_nettype;
+int ether_outputdebug = 0;
+int ether_inputdebug = 0;
+#endif
+
+#ifdef ISO
+#include <netiso/argo_debug.h>
+#include <netiso/iso.h>
+#include <netiso/iso_var.h>
+#include <netiso/iso_snpac.h>
+#endif
+
+/*#ifdef LLC
+#include <netccitt/dll.h>
+#include <netccitt/llc_var.h>
+#endif*/
+
+#if defined(LLC) && defined(CCITT)
+extern struct ifqueue pkintrq;
+#endif
+
+#ifdef NETATALK
+#include <netatalk/at.h>
+#include <netatalk/at_var.h>
+#include <netatalk/at_extern.h>
+
+#define llc_snap_org_code llc_un.type_snap.org_code
+#define llc_snap_ether_type llc_un.type_snap.ether_type
+
+extern u_char at_org_code[ 3 ];
+extern u_char aarp_org_code[ 3 ];
+#endif /* NETATALK */
+
+u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+#define senderr(e) { error = (e); goto bad;}
+
+/*
+ * Ethernet output routine.
+ * Encapsulate a packet of type family for the local net.
+ * Use trailer local net encapsulation if enough data in first
+ * packet leaves a multiple of 512 bytes of data in remainder.
+ * Assumes that ifp is actually pointer to arpcom structure.
+ */
+int
+ether_output(ifp, m0, dst, rt0)
+ register struct ifnet *ifp;
+ struct mbuf *m0;
+ struct sockaddr *dst;
+ struct rtentry *rt0;
+{
+ short type;
+ int s, error = 0;
+#ifdef NS
+ u_char *cp
+ register struct ifqueue *inq;
+ register struct mbuf *m2;
+#endif
+ u_char edst[6];
+ register struct mbuf *m = m0;
+ register struct rtentry *rt;
+ struct mbuf *mcopy = (struct mbuf *)0;
+ register struct ether_header *eh;
+ int off, len = m->m_pkthdr.len;
+ struct arpcom *ac = (struct arpcom *)ifp;
+#ifdef NETATALK
+ struct at_ifaddr *aa;
+#endif /* NETATALK */
+
+ if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
+ senderr(ENETDOWN);
+ rt = rt0;
+ if (rt) {
+ if ((rt->rt_flags & RTF_UP) == 0) {
+ rt0 = rt = rtalloc1(dst, 1, 0UL);
+ if (rt0)
+ rt->rt_refcnt--;
+ else
+ senderr(EHOSTUNREACH);
+ }
+ if (rt->rt_flags & RTF_GATEWAY) {
+ if (rt->rt_gwroute == 0)
+ goto lookup;
+ if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
+ rtfree(rt); rt = rt0;
+ lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1,
+ 0UL);
+ if ((rt = rt->rt_gwroute) == 0)
+ senderr(EHOSTUNREACH);
+ }
+ }
+ if (rt->rt_flags & RTF_REJECT)
+ if (rt->rt_rmx.rmx_expire == 0 ||
+ rtems_bsdnet_seconds_since_boot() < rt->rt_rmx.rmx_expire)
+ senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
+ }
+ switch (dst->sa_family) {
+
+#ifdef INET
+ case AF_INET:
+ if (!arpresolve(ac, rt, m, dst, edst, rt0))
+ return (0); /* if not yet resolved */
+ /* If broadcasting on a simplex interface, loopback a copy */
+ if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
+ mcopy = m_copy(m, 0, (int)M_COPYALL);
+ off = m->m_pkthdr.len - m->m_len;
+ type = htons(ETHERTYPE_IP);
+ break;
+#endif
+#ifdef IPX
+ case AF_IPX:
+ {
+ struct ifaddr *ia;
+
+ type = htons(ETHERTYPE_IPX);
+ bcopy((caddr_t)&(((struct sockaddr_ipx *)dst)->sipx_addr.x_host),
+ (caddr_t)edst, sizeof (edst));
+ for (ia = ifp->if_addrlist; ia != NULL; ia = ia->ifa_next)
+ if(ia->ifa_addr->sa_family == AF_IPX &&
+ !bcmp((caddr_t)edst,
+ (caddr_t)&((struct ipx_ifaddr *)ia)->ia_addr.sipx_addr.x_host,
+ sizeof(edst)))
+ return (looutput(ifp, m, dst, rt));
+ /* If broadcasting on a simplex interface, loopback a copy */
+ if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
+ mcopy = m_copy(m, 0, (int)M_COPYALL);
+ break;
+ }
+#endif
+#ifdef NETATALK
+ case AF_APPLETALK:
+ {
+ struct sockaddr_at *sat = (struct sockaddr_at *)dst;
+
+ /*
+ * super hack..
+ * Most of this loopback code should move into the appletalk
+ * code, but it's here for now.. remember to move it! [JRE]
+ * This may not get the same interface we started with
+ * fix asap. XXX
+ */
+ aa = at_ifawithnet( sat );
+ if (aa == NULL) {
+ goto bad;
+ }
+ if( aa->aa_ifa.ifa_ifp != ifp ) {
+ (*aa->aa_ifa.ifa_ifp->if_output)(aa->aa_ifa.ifa_ifp,
+ m,dst,rt);
+ }
+ if (((sat->sat_addr.s_net == ATADDR_ANYNET)
+ && (sat->sat_addr.s_node == ATADDR_ANYNODE))
+ || ((sat->sat_addr.s_net == aa->aa_addr.sat_addr.s_net )
+ && (sat->sat_addr.s_node == aa->aa_addr.sat_addr.s_node))) {
+ (void) looutput(ifp, m, dst, rt);
+ return(0);
+ }
+
+ if (!aarpresolve(ac, m, (struct sockaddr_at *)dst, edst)) {
+#ifdef NETATALKDEBUG
+ extern char *prsockaddr(struct sockaddr *);
+ printf("aarpresolv: failed for %s\n", prsockaddr(dst));
+#endif /* NETATALKDEBUG */
+ return (0);
+ }
+
+ /*
+ * If broadcasting on a simplex interface, loopback a copy
+ */
+ if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX))
+ mcopy = m_copy(m, 0, (int)M_COPYALL);
+ }
+ /*
+ * In the phase 2 case, we need to prepend an mbuf for the llc header.
+ * Since we must preserve the value of m, which is passed to us by
+ * value, we m_copy() the first mbuf, and use it for our llc header.
+ */
+ if ( aa->aa_flags & AFA_PHASE2 ) {
+ struct llc llc;
+
+ M_PREPEND(m, sizeof(struct llc), M_WAIT);
+ len += sizeof(struct llc);
+ llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP;
+ llc.llc_control = LLC_UI;
+ bcopy(at_org_code, llc.llc_snap_org_code, sizeof(at_org_code));
+ llc.llc_snap_ether_type = htons( ETHERTYPE_AT );
+ bcopy(&llc, mtod(m, caddr_t), sizeof(struct llc));
+ type = htons(m->m_pkthdr.len);
+ } else {
+ type = htons(ETHERTYPE_AT);
+ }
+ break;
+#endif /* NETATALK */
+#ifdef NS
+ case AF_NS:
+ switch(ns_nettype){
+ default:
+ case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */
+ type = 0x8137;
+ break;
+ case 0x0: /* Novell 802.3 */
+ type = htons( m->m_pkthdr.len);
+ break;
+ case 0xe0e0: /* Novell 802.2 and Token-Ring */
+ M_PREPEND(m, 3, M_WAIT);
+ type = htons( m->m_pkthdr.len);
+ cp = mtod(m, u_char *);
+ *cp++ = 0xE0;
+ *cp++ = 0xE0;
+ *cp++ = 0x03;
+ break;
+ }
+ bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host),
+ (caddr_t)edst, sizeof (edst));
+ if (!bcmp((caddr_t)edst, (caddr_t)&ns_thishost, sizeof(edst))){
+ m->m_pkthdr.rcvif = ifp;
+ schednetisr(NETISR_NS);
+ inq = &nsintrq;
+ s = splimp();
+ if (IF_QFULL(inq)) {
+ IF_DROP(inq);
+ m_freem(m);
+ } else
+ IF_ENQUEUE(inq, m);
+ splx(s);
+ return (error);
+ }
+ if (!bcmp((caddr_t)edst, (caddr_t)&ns_broadhost, sizeof(edst))){
+ m2 = m_copy(m, 0, (int)M_COPYALL);
+ m2->m_pkthdr.rcvif = ifp;
+ schednetisr(NETISR_NS);
+ inq = &nsintrq;
+ s = splimp();
+ if (IF_QFULL(inq)) {
+ IF_DROP(inq);
+ m_freem(m2);
+ } else
+ IF_ENQUEUE(inq, m2);
+ splx(s);
+ }
+ /* If broadcasting on a simplex interface, loopback a copy */
+ if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)){
+ mcopy = m_copy(m, 0, (int)M_COPYALL);
+ }
+ break;
+#endif /* NS */
+#ifdef ISO
+ case AF_ISO: {
+ int snpalen;
+ struct llc *l;
+ register struct sockaddr_dl *sdl;
+
+ if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway) &&
+ sdl->sdl_family == AF_LINK && sdl->sdl_alen > 0) {
+ bcopy(LLADDR(sdl), (caddr_t)edst, sizeof(edst));
+ } else if (error =
+ iso_snparesolve(ifp, (struct sockaddr_iso *)dst,
+ (char *)edst, &snpalen))
+ goto bad; /* Not Resolved */
+ /* If broadcasting on a simplex interface, loopback a copy */
+ if (*edst & 1)
+ m->m_flags |= (M_BCAST|M_MCAST);
+ if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX) &&
+ (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
+ M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
+ if (mcopy) {
+ eh = mtod(mcopy, struct ether_header *);
+ bcopy((caddr_t)edst,
+ (caddr_t)eh->ether_dhost, sizeof (edst));
+ bcopy((caddr_t)ac->ac_enaddr,
+ (caddr_t)eh->ether_shost, sizeof (edst));
+ }
+ }
+ M_PREPEND(m, 3, M_DONTWAIT);
+ if (m == NULL)
+ return (0);
+ type = htons(m->m_pkthdr.len);
+ l = mtod(m, struct llc *);
+ l->llc_dsap = l->llc_ssap = LLC_ISO_LSAP;
+ l->llc_control = LLC_UI;
+ len += 3;
+ IFDEBUG(D_ETHER)
+ int i;
+ printf("unoutput: sending pkt to: ");
+ for (i=0; i<6; i++)
+ printf("%x ", edst[i] & 0xff);
+ printf("\n");
+ ENDDEBUG
+ } break;
+#endif /* ISO */
+#ifdef LLC
+/* case AF_NSAP: */
+ case AF_CCITT: {
+ register struct sockaddr_dl *sdl =
+ (struct sockaddr_dl *) rt -> rt_gateway;
+
+ if (sdl && sdl->sdl_family == AF_LINK
+ && sdl->sdl_alen > 0) {
+ bcopy(LLADDR(sdl), (char *)edst,
+ sizeof(edst));
+ } else goto bad; /* Not a link interface ? Funny ... */
+ if ((ifp->if_flags & IFF_SIMPLEX) && (*edst & 1) &&
+ (mcopy = m_copy(m, 0, (int)M_COPYALL))) {
+ M_PREPEND(mcopy, sizeof (*eh), M_DONTWAIT);
+ if (mcopy) {
+ eh = mtod(mcopy, struct ether_header *);
+ bcopy((caddr_t)edst,
+ (caddr_t)eh->ether_dhost, sizeof (edst));
+ bcopy((caddr_t)ac->ac_enaddr,
+ (caddr_t)eh->ether_shost, sizeof (edst));
+ }
+ }
+ type = htons(m->m_pkthdr.len);
+#ifdef LLC_DEBUG
+ {
+ int i;
+ register struct llc *l = mtod(m, struct llc *);
+
+ printf("ether_output: sending LLC2 pkt to: ");
+ for (i=0; i<6; i++)
+ printf("%x ", edst[i] & 0xff);
+ printf(" len 0x%x dsap 0x%x ssap 0x%x control 0x%x\n",
+ type & 0xff, l->llc_dsap & 0xff, l->llc_ssap &0xff,
+ l->llc_control & 0xff);
+
+ }
+#endif /* LLC_DEBUG */
+ } break;
+#endif /* LLC */
+
+ case AF_UNSPEC:
+ eh = (struct ether_header *)dst->sa_data;
+ (void)memcpy(edst, eh->ether_dhost, sizeof (edst));
+ type = eh->ether_type;
+ break;
+
+ default:
+ printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,
+ dst->sa_family);
+ senderr(EAFNOSUPPORT);
+ }
+
+
+ if (mcopy)
+ (void) looutput(ifp, mcopy, dst, rt);
+ /*
+ * Add local net header. If no space in first mbuf,
+ * allocate another.
+ */
+ M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
+ if (m == 0)
+ senderr(ENOBUFS);
+ eh = mtod(m, struct ether_header *);
+ (void)memcpy(&eh->ether_type, &type,
+ sizeof(eh->ether_type));
+ (void)memcpy(eh->ether_dhost, edst, sizeof (edst));
+ (void)memcpy(eh->ether_shost, ac->ac_enaddr,
+ sizeof(eh->ether_shost));
+ s = splimp();
+ /*
+ * Queue message on interface, and start output if interface
+ * not yet active.
+ */
+ if (IF_QFULL(&ifp->if_snd)) {
+ IF_DROP(&ifp->if_snd);
+ splx(s);
+ senderr(ENOBUFS);
+ }
+ IF_ENQUEUE(&ifp->if_snd, m);
+ if ((ifp->if_flags & IFF_OACTIVE) == 0)
+ (*ifp->if_start)(ifp);
+ splx(s);
+ ifp->if_obytes += len + sizeof (struct ether_header);
+ if (m->m_flags & M_MCAST)
+ ifp->if_omcasts++;
+ return (error);
+
+bad:
+ if (m)
+ m_freem(m);
+ return (error);
+}
+
+/*
+ * Process a received Ethernet packet;
+ * the packet is in the mbuf chain m without
+ * the ether header, which is provided separately.
+ */
+void
+ether_input(ifp, eh, m)
+ struct ifnet *ifp;
+ register struct ether_header *eh;
+ struct mbuf *m;
+{
+ register struct ifqueue *inq;
+ u_short ether_type;
+#ifdef NS
+ u_short *checksum;
+#endif
+ int s;
+#if defined (ISO) || defined (LLC) || defined(NETATALK)
+ register struct llc *l;
+#endif
+
+ if ((ifp->if_flags & IFF_UP) == 0) {
+ m_freem(m);
+ return;
+ }
+ ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh);
+ if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
+ sizeof(etherbroadcastaddr)) == 0)
+ m->m_flags |= M_BCAST;
+ else if (eh->ether_dhost[0] & 1)
+ m->m_flags |= M_MCAST;
+ if (m->m_flags & (M_BCAST|M_MCAST))
+ ifp->if_imcasts++;
+
+ /*
+ * RTEMS addition -- allow application to `tap into'
+ * the incoming packet stream.
+ */
+ if (ifp->if_tap && (*ifp->if_tap)(ifp, eh, m)) {
+ m_freem(m);
+ return;
+ }
+
+ ether_type = ntohs(eh->ether_type);
+
+ switch (ether_type) {
+#ifdef INET
+ case ETHERTYPE_IP:
+ schednetisr(NETISR_IP);
+ inq = &ipintrq;
+ break;
+
+ case ETHERTYPE_ARP:
+ schednetisr(NETISR_ARP);
+ inq = &arpintrq;
+ break;
+#endif
+#ifdef IPX
+ case ETHERTYPE_IPX:
+ schednetisr(NETISR_IPX);
+ inq = &ipxintrq;
+ break;
+#endif
+#ifdef NS
+ case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */
+ schednetisr(NETISR_NS);
+ inq = &nsintrq;
+ break;
+
+#endif /* NS */
+#ifdef NETATALK
+ case ETHERTYPE_AT:
+ schednetisr(NETISR_ATALK);
+ inq = &atintrq1;
+ break;
+ case ETHERTYPE_AARP:
+ /* probably this should be done with a NETISR as well */
+ aarpinput((struct arpcom *)ifp, m); /* XXX */
+ return;
+#endif /* NETATALK */
+ default:
+#ifdef NS
+ checksum = mtod(m, ushort *);
+ /* Novell 802.3 */
+ if ((ether_type <= ETHERMTU) &&
+ ((*checksum == 0xffff) || (*checksum == 0xE0E0))){
+ if(*checksum == 0xE0E0) {
+ m->m_pkthdr.len -= 3;
+ m->m_len -= 3;
+ m->m_data += 3;
+ }
+ schednetisr(NETISR_NS);
+ inq = &nsintrq;
+ break;
+ }
+#endif /* NS */
+#if defined (ISO) || defined (LLC) || defined(NETATALK)
+ if (ether_type > ETHERMTU)
+ goto dropanyway;
+ l = mtod(m, struct llc *);
+ switch (l->llc_dsap) {
+#ifdef NETATALK
+ case LLC_SNAP_LSAP:
+ switch (l->llc_control) {
+ case LLC_UI:
+ if (l->llc_ssap != LLC_SNAP_LSAP)
+ goto dropanyway;
+
+ if (Bcmp(&(l->llc_snap_org_code)[0], at_org_code,
+ sizeof(at_org_code)) == 0 &&
+ ntohs(l->llc_snap_ether_type) == ETHERTYPE_AT) {
+ inq = &atintrq2;
+ m_adj( m, sizeof( struct llc ));
+ schednetisr(NETISR_ATALK);
+ break;
+ }
+
+ if (Bcmp(&(l->llc_snap_org_code)[0], aarp_org_code,
+ sizeof(aarp_org_code)) == 0 &&
+ ntohs(l->llc_snap_ether_type) == ETHERTYPE_AARP) {
+ m_adj( m, sizeof( struct llc ));
+ aarpinput((struct arpcom *)ifp, m); /* XXX */
+ return;
+ }
+
+ default:
+ goto dropanyway;
+ }
+ break;
+#endif /* NETATALK */
+#ifdef ISO
+ case LLC_ISO_LSAP:
+ switch (l->llc_control) {
+ case LLC_UI:
+ /* LLC_UI_P forbidden in class 1 service */
+ if ((l->llc_dsap == LLC_ISO_LSAP) &&
+ (l->llc_ssap == LLC_ISO_LSAP)) {
+ /* LSAP for ISO */
+ if (m->m_pkthdr.len > ether_type)
+ m_adj(m, ether_type - m->m_pkthdr.len);
+ m->m_data += 3; /* XXX */
+ m->m_len -= 3; /* XXX */
+ m->m_pkthdr.len -= 3; /* XXX */
+ M_PREPEND(m, sizeof *eh, M_DONTWAIT);
+ if (m == 0)
+ return;
+ *mtod(m, struct ether_header *) = *eh;
+ IFDEBUG(D_ETHER)
+ printf("clnp packet");
+ ENDDEBUG
+ schednetisr(NETISR_ISO);
+ inq = &clnlintrq;
+ break;
+ }
+ goto dropanyway;
+
+ case LLC_XID:
+ case LLC_XID_P:
+ if(m->m_len < 6)
+ goto dropanyway;
+ l->llc_window = 0;
+ l->llc_fid = 9;
+ l->llc_class = 1;
+ l->llc_dsap = l->llc_ssap = 0;
+ /* Fall through to */
+ case LLC_TEST:
+ case LLC_TEST_P:
+ {
+ struct sockaddr sa;
+ register struct ether_header *eh2;
+ int i;
+ u_char c = l->llc_dsap;
+
+ l->llc_dsap = l->llc_ssap;
+ l->llc_ssap = c;
+ if (m->m_flags & (M_BCAST | M_MCAST))
+ bcopy((caddr_t)ac->ac_enaddr,
+ (caddr_t)eh->ether_dhost, 6);
+ sa.sa_family = AF_UNSPEC;
+ sa.sa_len = sizeof(sa);
+ eh2 = (struct ether_header *)sa.sa_data;
+ for (i = 0; i < 6; i++) {
+ eh2->ether_shost[i] = c = eh->ether_dhost[i];
+ eh2->ether_dhost[i] =
+ eh->ether_dhost[i] = eh->ether_shost[i];
+ eh->ether_shost[i] = c;
+ }
+ ifp->if_output(ifp, m, &sa, NULL);
+ return;
+ }
+ default:
+ m_freem(m);
+ return;
+ }
+ break;
+#endif /* ISO */
+#ifdef LLC
+ case LLC_X25_LSAP:
+ {
+ if (m->m_pkthdr.len > ether_type)
+ m_adj(m, ether_type - m->m_pkthdr.len);
+ M_PREPEND(m, sizeof(struct sdl_hdr) , M_DONTWAIT);
+ if (m == 0)
+ return;
+ if ( !sdl_sethdrif(ifp, eh->ether_shost, LLC_X25_LSAP,
+ eh->ether_dhost, LLC_X25_LSAP, 6,
+ mtod(m, struct sdl_hdr *)))
+ panic("ETHER cons addr failure");
+ mtod(m, struct sdl_hdr *)->sdlhdr_len = ether_type;
+#ifdef LLC_DEBUG
+ printf("llc packet\n");
+#endif /* LLC_DEBUG */
+ schednetisr(NETISR_CCITT);
+ inq = &llcintrq;
+ break;
+ }
+#endif /* LLC */
+ dropanyway:
+ default:
+ m_freem(m);
+ return;
+ }
+#else /* ISO || LLC || NETATALK */
+ m_freem(m);
+ return;
+#endif /* ISO || LLC || NETATALK */
+ }
+
+ s = splimp();
+ if (IF_QFULL(inq)) {
+ IF_DROP(inq);
+ m_freem(m);
+ } else
+ IF_ENQUEUE(inq, m);
+ splx(s);
+}
+
+/*
+ * Perform common duties while attaching to interface list
+ */
+void
+ether_ifattach(ifp)
+ register struct ifnet *ifp;
+{
+ register struct ifaddr *ifa;
+ register struct sockaddr_dl *sdl;
+
+ ifp->if_type = IFT_ETHER;
+ ifp->if_addrlen = 6;
+ ifp->if_hdrlen = 14;
+ ifp->if_mtu = ETHERMTU;
+ if (ifp->if_baudrate == 0)
+ ifp->if_baudrate = 10000000;
+ for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
+ if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&
+ sdl->sdl_family == AF_LINK) {
+ sdl->sdl_type = IFT_ETHER;
+ sdl->sdl_alen = ifp->if_addrlen;
+ bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr,
+ LLADDR(sdl), ifp->if_addrlen);
+ break;
+ }
+}
+
+static u_char ether_ipmulticast_min[6] =
+ { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 };
+static u_char ether_ipmulticast_max[6] =
+ { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff };
+/*
+ * Add an Ethernet multicast address or range of addresses to the list for a
+ * given interface.
+ */
+int
+ether_addmulti(ifr, ac)
+ struct ifreq *ifr;
+ register struct arpcom *ac;
+{
+ register struct ether_multi *enm;
+ struct sockaddr_in *sin;
+ u_char addrlo[6];
+ u_char addrhi[6];
+ int set_allmulti = 0;
+ int s = splimp();
+
+ switch (ifr->ifr_addr.sa_family) {
+
+ case AF_UNSPEC:
+ bcopy(ifr->ifr_addr.sa_data, addrlo, 6);
+ bcopy(addrlo, addrhi, 6);
+ break;
+
+#ifdef INET
+ case AF_INET:
+ sin = (struct sockaddr_in *)&(ifr->ifr_addr);
+ if (sin->sin_addr.s_addr == INADDR_ANY) {
+ /*
+ * An IP address of INADDR_ANY means listen to all
+ * of the Ethernet multicast addresses used for IP.
+ * (This is for the sake of IP multicast routers.)
+ */
+ bcopy(ether_ipmulticast_min, addrlo, 6);
+ bcopy(ether_ipmulticast_max, addrhi, 6);
+ set_allmulti = 1;
+ }
+ else {
+ ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
+ bcopy(addrlo, addrhi, 6);
+ }
+ break;
+#endif
+
+ default:
+ splx(s);
+ return (EAFNOSUPPORT);
+ }
+
+ /*
+ * Verify that we have valid Ethernet multicast addresses.
+ */
+ if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) {
+ splx(s);
+ return (EINVAL);
+ }
+ /*
+ * See if the address range is already in the list.
+ */
+ ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
+ if (enm != NULL) {
+ /*
+ * Found it; just increment the reference count.
+ */
+ ++enm->enm_refcount;
+ splx(s);
+ return (0);
+ }
+ /*
+ * New address or range; malloc a new multicast record
+ * and link it into the interface's multicast list.
+ */
+ enm = (struct ether_multi *)malloc(sizeof(*enm), M_IFMADDR, M_NOWAIT);
+ if (enm == NULL) {
+ splx(s);
+ return (ENOBUFS);
+ }
+ bcopy(addrlo, enm->enm_addrlo, 6);
+ bcopy(addrhi, enm->enm_addrhi, 6);
+ enm->enm_ac = ac;
+ enm->enm_refcount = 1;
+ enm->enm_next = ac->ac_multiaddrs;
+ ac->ac_multiaddrs = enm;
+ ac->ac_multicnt++;
+ splx(s);
+ if (set_allmulti)
+ ac->ac_if.if_flags |= IFF_ALLMULTI;
+
+ /*
+ * Return ENETRESET to inform the driver that the list has changed
+ * and its reception filter should be adjusted accordingly.
+ */
+ return (ENETRESET);
+}
+
+/*
+ * Delete a multicast address record.
+ */
+int
+ether_delmulti(ifr, ac)
+ struct ifreq *ifr;
+ register struct arpcom *ac;
+{
+ register struct ether_multi *enm;
+ register struct ether_multi **p;
+ struct sockaddr_in *sin;
+ u_char addrlo[6];
+ u_char addrhi[6];
+ int unset_allmulti = 0;
+ int s = splimp();
+
+ switch (ifr->ifr_addr.sa_family) {
+
+ case AF_UNSPEC:
+ bcopy(ifr->ifr_addr.sa_data, addrlo, 6);
+ bcopy(addrlo, addrhi, 6);
+ break;
+
+#ifdef INET
+ case AF_INET:
+ sin = (struct sockaddr_in *)&(ifr->ifr_addr);
+ if (sin->sin_addr.s_addr == INADDR_ANY) {
+ /*
+ * An IP address of INADDR_ANY means stop listening
+ * to the range of Ethernet multicast addresses used
+ * for IP.
+ */
+ bcopy(ether_ipmulticast_min, addrlo, 6);
+ bcopy(ether_ipmulticast_max, addrhi, 6);
+ unset_allmulti = 1;
+ }
+ else {
+ ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo);
+ bcopy(addrlo, addrhi, 6);
+ }
+ break;
+#endif
+
+ default:
+ splx(s);
+ return (EAFNOSUPPORT);
+ }
+
+ /*
+ * Look up the address in our list.
+ */
+ ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm);
+ if (enm == NULL) {
+ splx(s);
+ return (ENXIO);
+ }
+ if (--enm->enm_refcount != 0) {
+ /*
+ * Still some claims to this record.
+ */
+ splx(s);
+ return (0);
+ }
+ /*
+ * No remaining claims to this record; unlink and free it.
+ */
+ for (p = &enm->enm_ac->ac_multiaddrs;
+ *p != enm;
+ p = &(*p)->enm_next)
+ continue;
+ *p = (*p)->enm_next;
+ free(enm, M_IFMADDR);
+ ac->ac_multicnt--;
+ splx(s);
+ if (unset_allmulti)
+ ac->ac_if.if_flags &= ~IFF_ALLMULTI;
+
+ /*
+ * Return ENETRESET to inform the driver that the list has changed
+ * and its reception filter should be adjusted accordingly.
+ */
+ return (ENETRESET);
+}
+
+SYSCTL_DECL(_net_link);
+SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet");
+
+int
+ether_ioctl(struct ifnet *ifp, int command, caddr_t data)
+{
+ struct ifaddr *ifa = (struct ifaddr *) data;
+ struct ifreq *ifr = (struct ifreq *) data;
+ int error = 0;
+
+ switch (command) {
+ case SIOCSIFADDR:
+ ifp->if_flags |= IFF_UP;
+
+ switch (ifa->ifa_addr->sa_family) {
+#ifdef INET
+ case AF_INET:
+ ifp->if_init(ifp->if_softc); /* before arpwhohas */
+ arp_ifinit((struct arpcom *)ifp, ifa);
+ break;
+#endif
+#ifdef IPX
+ /*
+ * XXX - This code is probably wrong
+ */
+ case AF_IPX:
+ {
+ register struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr);
+ struct arpcom *ac = (struct arpcom *) (ifp->if_softc);
+
+ if (ipx_nullhost(*ina))
+ ina->x_host =
+ *(union ipx_host *)
+ ac->ac_enaddr;
+ else {
+ bcopy((caddr_t) ina->x_host.c_host,
+ (caddr_t) ac->ac_enaddr,
+ sizeof(ac->ac_enaddr));
+ }
+
+ /*
+ * Set new address
+ */
+ ifp->if_init(ifp->if_softc);
+ break;
+ }
+#endif
+#ifdef NS
+ /*
+ * XXX - This code is probably wrong
+ */
+ case AF_NS:
+ {
+ register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
+ struct arpcom *ac = (struct arpcom *) (ifp->if_softc);
+
+ if (ns_nullhost(*ina))
+ ina->x_host =
+ *(union ns_host *) (ac->ac_enaddr);
+ else {
+ bcopy((caddr_t) ina->x_host.c_host,
+ (caddr_t) ac->ac_enaddr,
+ sizeof(ac->ac_enaddr));
+ }
+
+ /*
+ * Set new address
+ */
+ ifp->if_init(ifp->if_softc);
+ break;
+ }
+#endif
+ default:
+ ifp->if_init(ifp->if_softc);
+ break;
+ }
+ break;
+
+ case SIOCGIFADDR:
+ {
+ struct sockaddr *sa;
+
+ sa = (struct sockaddr *) & ifr->ifr_data;
+ bcopy(((struct arpcom *)ifp->if_softc)->ac_enaddr,
+ (caddr_t) sa->sa_data, ETHER_ADDR_LEN);
+ }
+ break;
+
+ case SIOCSIFMTU:
+ /*
+ * Set the interface MTU.
+ */
+ if (ifr->ifr_mtu > ETHERMTU) {
+ error = EINVAL;
+ } else {
+ ifp->if_mtu = ifr->ifr_mtu;
+ }
+ break;
+ }
+ return (error);
+}
diff --git a/cpukit/libnetworking/net/if_llc.h b/cpukit/libnetworking/net/if_llc.h
new file mode 100644
index 0000000000..3cdf652167
--- /dev/null
+++ b/cpukit/libnetworking/net/if_llc.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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_llc.h 8.1 (Berkeley) 6/10/93
+ * $Id$
+ */
+
+#ifndef _NET_IF_LLC_H_
+#define _NET_IF_LLC_H_
+
+/*
+ * IEEE 802.2 Link Level Control headers, for use in conjunction with
+ * 802.{3,4,5} media access control methods.
+ *
+ * Headers here do not use bit fields due to shortcomings in many
+ * compilers.
+ */
+
+struct llc {
+ u_char llc_dsap;
+ u_char llc_ssap;
+ union {
+ struct {
+ u_char control;
+ u_char format_id;
+ u_char class;
+ u_char window_x2;
+ } type_u;
+ struct {
+ u_char num_snd_x2;
+ u_char num_rcv_x2;
+ } type_i;
+ struct {
+ u_char control;
+ u_char num_rcv_x2;
+ } type_s;
+ struct {
+ u_char control;
+ struct frmrinfo {
+ u_char rej_pdu_0;
+ u_char rej_pdu_1;
+ u_char frmr_control;
+ u_char frmr_control_ext;
+ u_char frmr_cause;
+ } frmrinfo;
+ } type_frmr;
+ struct {
+ u_char control;
+ u_char org_code[3];
+ u_short ether_type;
+ } type_snap;
+ struct {
+ u_char control;
+ u_char control_ext;
+ } type_raw;
+ } llc_un;
+};
+#define llc_control llc_un.type_u.control
+#define llc_control_ext llc_un.type_raw.control_ext
+#define llc_fid llc_un.type_u.format_id
+#define llc_class llc_un.type_u.class
+#define llc_window llc_un.type_u.window_x2
+#define llc_frmrinfo llc_un.type_frmr.frmrinfo
+#define llc_frmr_pdu0 llc_un.type_frmr.frmrinfo.rej_pdu0
+#define llc_frmr_pdu1 llc_un.type_frmr.frmrinfo.rej_pdu1
+#define llc_frmr_control llc_un.type_frmr.frmrinfo.frmr_control
+#define llc_frmr_control_ext llc_un.type_frmr.frmrinfo.frmr_control_ext
+#define llc_frmr_cause llc_un.type_frmr.frmrinfo.frmr_control_ext
+
+/*
+ * Don't use sizeof(struct llc_un) for LLC header sizes
+ */
+#define LLC_ISFRAMELEN 4
+#define LLC_UFRAMELEN 3
+#define LLC_FRMRLEN 7
+
+/*
+ * Unnumbered LLC format commands
+ */
+#define LLC_UI 0x3
+#define LLC_UI_P 0x13
+#define LLC_DISC 0x43
+#define LLC_DISC_P 0x53
+#define LLC_UA 0x63
+#define LLC_UA_P 0x73
+#define LLC_TEST 0xe3
+#define LLC_TEST_P 0xf3
+#define LLC_FRMR 0x87
+#define LLC_FRMR_P 0x97
+#define LLC_DM 0x0f
+#define LLC_DM_P 0x1f
+#define LLC_XID 0xaf
+#define LLC_XID_P 0xbf
+#define LLC_SABME 0x6f
+#define LLC_SABME_P 0x7f
+
+/*
+ * Supervisory LLC commands
+ */
+#define LLC_RR 0x01
+#define LLC_RNR 0x05
+#define LLC_REJ 0x09
+
+/*
+ * Info format - dummy only
+ */
+#define LLC_INFO 0x00
+
+/*
+ * ISO PDTR 10178 contains among others
+ */
+#define LLC_X25_LSAP 0x7e
+#define LLC_SNAP_LSAP 0xaa
+#define LLC_ISO_LSAP 0xfe
+
+#endif
diff --git a/cpukit/libnetworking/net/if_loop.c b/cpukit/libnetworking/net/if_loop.c
new file mode 100644
index 0000000000..6ff6bdfe4d
--- /dev/null
+++ b/cpukit/libnetworking/net/if_loop.c
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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_loop.c 8.1 (Berkeley) 6/10/93
+ * $Id$
+ */
+
+/*
+ * Loopback interface driver for protocol testing and timing.
+ */
+#include "loop.h"
+#if NLOOP > 0
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/errno.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+
+#include <net/if.h>
+#include <net/if_types.h>
+#include <net/netisr.h>
+#include <net/route.h>
+#include <net/bpf.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#endif
+
+#ifdef IPX
+#include <netipx/ipx.h>
+#include <netipx/ipx_if.h>
+#endif
+
+#ifdef NS
+#include <netns/ns.h>
+#include <netns/ns_if.h>
+#endif
+
+#ifdef ISO
+#include <netiso/iso.h>
+#include <netiso/iso_var.h>
+#endif
+
+#ifdef NETATALK
+#include <netinet/if_ether.h>
+#include <netatalk/at.h>
+#include <netatalk/at_var.h>
+#endif /* NETATALK */
+
+#include "bpfilter.h"
+
+static int loioctl __P((struct ifnet *, int, caddr_t));
+static void lortrequest __P((int, struct rtentry *, struct sockaddr *));
+
+ void rtems_bsdnet_loopattach __P((void *));
+PSEUDO_SET(loopattach, if_loop);
+
+#ifdef TINY_LOMTU
+#define LOMTU (1024+512)
+#else
+#define LOMTU 16384
+#endif
+
+struct ifnet loif[NLOOP];
+
+/* ARGSUSED */
+void
+rtems_bsdnet_loopattach(dummy)
+ void *dummy;
+{
+ register struct ifnet *ifp;
+ register int i = 0;
+
+ for (ifp = loif; i < NLOOP; ifp++) {
+ ifp->if_name = "lo";
+ ifp->if_next = NULL;
+ ifp->if_unit = i++;
+ ifp->if_mtu = LOMTU;
+ ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST;
+ ifp->if_ioctl = loioctl;
+ ifp->if_output = looutput;
+ ifp->if_type = IFT_LOOP;
+ ifp->if_hdrlen = 0;
+ ifp->if_addrlen = 0;
+ ifp->if_snd.ifq_maxlen = ifqmaxlen;
+ if_attach(ifp);
+#if NBPFILTER > 0
+ bpfattach(ifp, DLT_NULL, sizeof(u_int));
+#endif
+ }
+}
+
+int
+looutput(ifp, m, dst, rt)
+ struct ifnet *ifp;
+ register struct mbuf *m;
+ struct sockaddr *dst;
+ register struct rtentry *rt;
+{
+ int s, isr;
+ register struct ifqueue *ifq = 0;
+
+ if ((m->m_flags & M_PKTHDR) == 0)
+ panic("looutput no HDR");
+#if NBPFILTER > 0
+ /* BPF write needs to be handled specially */
+ if (dst->sa_family == AF_UNSPEC) {
+ dst->sa_family = *(mtod(m, int *));
+ m->m_len -= sizeof(int);
+ m->m_pkthdr.len -= sizeof(int);
+ m->m_data += sizeof(int);
+ }
+
+ if (ifp->if_bpf) {
+ /*
+ * We need to prepend the address family as
+ * a four byte field. Cons up a dummy header
+ * to pacify bpf. This is safe because bpf
+ * will only read from the mbuf (i.e., it won't
+ * try to free it or keep a pointer a to it).
+ */
+ struct mbuf m0;
+ u_int af = dst->sa_family;
+
+ m0.m_next = m;
+ m0.m_len = 4;
+ m0.m_data = (char *)&af;
+
+ bpf_mtap(ifp, &m0);
+ }
+#endif
+ m->m_pkthdr.rcvif = ifp;
+
+ if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
+ m_freem(m);
+ return (rt->rt_flags & RTF_BLACKHOLE ? 0 :
+ rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
+ }
+ ifp->if_opackets++;
+ ifp->if_obytes += m->m_pkthdr.len;
+ switch (dst->sa_family) {
+
+#ifdef INET
+ case AF_INET:
+ ifq = &ipintrq;
+ isr = NETISR_IP;
+ break;
+#endif
+#ifdef IPX
+ case AF_IPX:
+ ifq = &ipxintrq;
+ isr = NETISR_IPX;
+ break;
+#endif
+#ifdef NS
+ case AF_NS:
+ ifq = &nsintrq;
+ isr = NETISR_NS;
+ break;
+#endif
+#ifdef ISO
+ case AF_ISO:
+ ifq = &clnlintrq;
+ isr = NETISR_ISO;
+ break;
+#endif
+#ifdef NETATALK
+ case AF_APPLETALK:
+ ifq = &atintrq2;
+ isr = NETISR_ATALK;
+ break;
+#endif /* NETATALK */
+ default:
+ printf("lo%d: can't handle af%d\n", ifp->if_unit,
+ dst->sa_family);
+ m_freem(m);
+ return (EAFNOSUPPORT);
+ }
+ s = splimp();
+ if (IF_QFULL(ifq)) {
+ IF_DROP(ifq);
+ m_freem(m);
+ splx(s);
+ return (ENOBUFS);
+ }
+ IF_ENQUEUE(ifq, m);
+ schednetisr(isr);
+ ifp->if_ipackets++;
+ ifp->if_ibytes += m->m_pkthdr.len;
+ splx(s);
+ return (0);
+}
+
+/* ARGSUSED */
+static void
+lortrequest(cmd, rt, sa)
+ int cmd;
+ struct rtentry *rt;
+ struct sockaddr *sa;
+{
+ if (rt) {
+ rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; /* for ISO */
+ /*
+ * For optimal performance, the send and receive buffers
+ * should be at least twice the MTU plus a little more for
+ * overhead.
+ */
+ rt->rt_rmx.rmx_recvpipe =
+ rt->rt_rmx.rmx_sendpipe = 3 * LOMTU;
+ }
+}
+
+/*
+ * Process an ioctl request.
+ */
+/* ARGSUSED */
+static int
+loioctl(ifp, cmd, data)
+ register struct ifnet *ifp;
+ int cmd;
+ caddr_t data;
+{
+ register struct ifaddr *ifa;
+ register struct ifreq *ifr = (struct ifreq *)data;
+ register int error = 0;
+
+ switch (cmd) {
+
+ case SIOCSIFADDR:
+ ifp->if_flags |= IFF_UP | IFF_RUNNING;
+ ifa = (struct ifaddr *)data;
+ ifa->ifa_rtrequest = lortrequest;
+ /*
+ * Everything else is done at a higher level.
+ */
+ break;
+
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ if (ifr == 0) {
+ error = EAFNOSUPPORT; /* XXX */
+ break;
+ }
+ switch (ifr->ifr_addr.sa_family) {
+
+#ifdef INET
+ case AF_INET:
+ break;
+#endif
+
+ default:
+ error = EAFNOSUPPORT;
+ break;
+ }
+ break;
+
+ case SIOCSIFMTU:
+ ifp->if_mtu = ifr->ifr_mtu;
+ break;
+
+ default:
+ error = EINVAL;
+ }
+ return (error);
+}
+#endif /* NLOOP > 0 */
diff --git a/cpukit/libnetworking/net/if_ppp.c b/cpukit/libnetworking/net/if_ppp.c
new file mode 100644
index 0000000000..64e5d88459
--- /dev/null
+++ b/cpukit/libnetworking/net/if_ppp.c
@@ -0,0 +1,1764 @@
+/*
+ * if_ppp.c - Point-to-Point Protocol (PPP) Asynchronous driver.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Drew D. Perkins
+ * Carnegie Mellon University
+ * 4910 Forbes Ave.
+ * Pittsburgh, PA 15213
+ * (412) 268-8576
+ * ddp@andrew.cmu.edu
+ *
+ * Based on:
+ * @(#)if_sl.c 7.6.1.2 (Berkeley) 2/15/89
+ *
+ * Copyright (c) 1987 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Serial Line interface
+ *
+ * Rick Adams
+ * Center for Seismic Studies
+ * 1300 N 17th Street, Suite 1450
+ * Arlington, Virginia 22209
+ * (703)276-7900
+ * rick@seismo.ARPA
+ * seismo!rick
+ *
+ * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris).
+ * Converted to 4.3BSD Beta by Chris Torek.
+ * Other changes made at Berkeley, based in part on code by Kirk Smith.
+ *
+ * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com)
+ * Added VJ tcp header compression; more unified ioctls
+ *
+ * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au).
+ * Cleaned up a lot of the mbuf-related code to fix bugs that
+ * caused system crashes and packet corruption. Changed pppstart
+ * so that it doesn't just give up with a collision if the whole
+ * packet doesn't fit in the output ring buffer.
+ *
+ * Added priority queueing for interactive IP packets, following
+ * the model of if_sl.c, plus hooks for bpf.
+ * Paul Mackerras (paulus@cs.anu.edu.au).
+ */
+
+/* $Id$ */
+/* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
+/* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */
+
+#include "ppp.h"
+#if NPPP > 0
+
+#include <termios.h>
+#include <rtems/termiostypes.h>
+#include <rtems/rtems_bsdnet.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/kernel.h>
+#include <sys/time.h>
+#include <sys/malloc.h>
+
+#include <net/if.h>
+#include <net/if_types.h>
+#include <net/netisr.h>
+#include <net/route.h>
+#ifdef PPP_FILTER
+#include <net/bpf.h>
+#endif
+
+#if INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#endif
+
+#include "bpfilter.h"
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#endif
+
+#ifdef VJC
+#include <net/pppcompress.h>
+#endif
+
+#include <net/ppp_defs.h>
+#include <net/if_ppp.h>
+#include <net/if_pppvar.h>
+#include <machine/cpu.h>
+
+#define splsoftnet splnet
+
+#ifdef PPP_COMPRESS
+#define PACKETPTR struct mbuf *
+#include <net/ppp-comp.h>
+#endif
+
+static int pppsioctl __P((struct ifnet *, int, caddr_t));
+static void ppp_requeue __P((struct ppp_softc *));
+#ifdef PPP_COMPRESS
+static void ppp_ccp __P((struct ppp_softc *, struct mbuf *m, int rcvd));
+static void ppp_ccp_closed __P((struct ppp_softc *));
+#endif
+static struct mbuf *ppp_inproc __P((struct ppp_softc *, struct mbuf *));
+static void pppdumpm __P((struct mbuf *m0));
+
+/*
+ * Some useful mbuf macros not in mbuf.h.
+ */
+#define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT)
+
+#define M_DATASTART(m) \
+ (M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \
+ (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
+
+#define M_DATASIZE(m) \
+ (M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \
+ (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
+
+/*
+ * We steal two bits in the mbuf m_flags, to mark high-priority packets
+ * for output, and received packets following lost/corrupted packets.
+ */
+#define M_HIGHPRI 0x2000 /* output packet for sc_fastq */
+#define M_ERRMARK 0x4000 /* steal a bit in mbuf m_flags */
+
+
+#ifdef PPP_COMPRESS
+/*
+ * List of compressors we know about.
+ * We leave some space so maybe we can modload compressors.
+ */
+
+extern struct compressor ppp_bsd_compress;
+extern struct compressor ppp_deflate, ppp_deflate_draft;
+
+struct compressor *ppp_compressors[8] = {
+#if DO_BSD_COMPRESS
+ &ppp_bsd_compress,
+#endif
+#if DO_DEFLATE
+ &ppp_deflate,
+ &ppp_deflate_draft,
+#endif
+ NULL
+};
+#endif /* PPP_COMPRESS */
+
+extern struct ifqueue ipintrq;
+static struct timeval ppp_time;
+
+#ifndef __rtems__
+TEXT_SET(pseudo_set, ppp_rxdaemon);
+#endif
+
+static rtems_task ppp_rxdaemon(rtems_task_argument arg)
+{
+ rtems_event_set events;
+ rtems_interrupt_level level;
+ struct ppp_softc *sc = (struct ppp_softc *)arg;
+ struct mbuf *mp = (struct mbuf *)0;
+ struct mbuf *m;
+
+ /* enter processing loop */
+ while ( 1 ) {
+ /* wait for event */
+ rtems_event_receive(RX_PACKET|RX_MBUF|RX_EMPTY,RTEMS_WAIT|RTEMS_EVENT_ANY,RTEMS_NO_TIMEOUT,&events);
+ if ( events & RX_EMPTY ) {
+ printf("RX: QUEUE is EMPTY\n");
+ events &= ~RX_EMPTY;
+ }
+
+ if ( events ) {
+ /* get the network semaphore */
+ rtems_bsdnet_semaphore_obtain();
+
+ /* check to see if new packet was received */
+ if ( events & RX_PACKET ) {
+ /* get received packet mbuf chain */
+ rtems_interrupt_disable(level);
+ IF_DEQUEUE(&sc->sc_rawq, m);
+ rtems_interrupt_enable(level);
+
+ /* ensure packet was retrieved */
+ if ( m != (struct mbuf *)0 ) {
+ /* process the received packet */
+ mp = ppp_inproc(sc, m);
+ }
+ }
+
+ /* allocate a new mbuf to replace one */
+ if ( mp == NULL ) {
+ pppallocmbuf(sc, &mp);
+ }
+
+ /* place mbuf on freeq */
+ rtems_interrupt_disable(level);
+ IF_ENQUEUE(&sc->sc_freeq, mp);
+ rtems_interrupt_enable(level);
+ mp = (struct mbuf *)0;
+
+ /* release the network semaphore */
+ rtems_bsdnet_semaphore_release();
+
+ /* check to see if queue is empty */
+ if ( sc->sc_rawq.ifq_head ) {
+ /* queue is not empty - post another event */
+ rtems_event_send(sc->sc_rxtask, RX_PACKET);
+ }
+ }
+ }
+}
+
+static rtems_task ppp_txdaemon(rtems_task_argument arg)
+{
+ rtems_event_set events;
+ int iprocess = (int )0;
+ struct ppp_softc *sc = (struct ppp_softc *)arg;
+ struct mbuf *mp;
+ struct mbuf *mf;
+ struct mbuf *m;
+ struct rtems_termios_tty *tp;
+
+ int frag;
+
+ /* enter processing loop */
+ while ( 1 ) {
+ /* wait for event */
+ rtems_event_receive(TX_PACKET|TX_TRANSMIT,RTEMS_WAIT|RTEMS_EVENT_ANY,RTEMS_NO_TIMEOUT,&events);
+ if ( events & TX_TRANSMIT ) {
+ /* received event from interrupt handler - free current mbuf */
+ rtems_bsdnet_semaphore_obtain();
+
+ m_freem(sc->sc_outm);
+
+ rtems_bsdnet_semaphore_release();
+
+ /* chain is done - clear the values */
+ sc->sc_outm = (struct mbuf *)0;
+ sc->sc_outmc = (struct mbuf *)0;
+
+ /* now set flag to fake receive of TX_PACKET event */
+ /* this will check to see if we have any pending packets */
+ events |= TX_PACKET;
+ }
+
+ /* received event from pppasyncstart */
+ if ( events & TX_PACKET ) {
+ /* ensure we are not busy */
+ if ( sc->sc_outm == (struct mbuf *)0 ) {
+ /* try dequeuing a packet */
+ sc->sc_outm = ppp_dequeue(sc);
+ if ( sc->sc_outm == NULL ) {
+ /* clear output flags */
+ sc->sc_outflag = 0;
+ sc->sc_if.if_flags &= ~IFF_OACTIVE;
+ }
+ else {
+ /* set flag to start process */
+ iprocess = 1;
+ sc->sc_outflag = SC_TX_BUSY;
+ sc->sc_if.if_flags |= IFF_OACTIVE;
+ }
+ }
+ }
+
+ /* check to see if there is any processing required */
+ if ( iprocess ) {
+ /* clear process flag */
+ iprocess = (int)0;
+ frag=0;
+
+ /* initialize output values */
+ sc->sc_outfcs = PPP_INITFCS;
+ sc->sc_outbuf = (u_char *)0;
+ sc->sc_outlen = (short )0;
+ sc->sc_outoff = (short )0;
+ sc->sc_outfcslen = (short )0;
+
+/* printf("Start Transmit Packet..\n"); */
+
+ /* loop over all mbufs in chain */
+ mf = NULL;
+ mp = NULL;
+ m = sc->sc_outm;
+
+ sc->sc_outmc = m;
+ sc->sc_outlen = m->m_len;
+ sc->sc_outbuf = mtod(m, u_char *);
+
+ while (( m != (struct mbuf *)0 ) && ( m->m_len > 0 )) {
+ frag++;
+
+ /* update the FCS value and then check next packet length */
+ if(m->m_len){
+ sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
+ }
+
+ if(( m->m_next != NULL ) && ( m->m_next->m_len == 0 )) {
+ if(mf){
+ printf(" if_ppp.c : MBUF Error !!!!\n");
+ }
+ else{
+ mf = m->m_next;
+ m->m_next = NULL;
+ }
+ }
+
+#ifdef LALL_X
+ /* check next packet to see if it is empty */
+ while (( m->m_next != NULL ) && ( m->m_next->m_len == 0 )) {
+ /* next mbuf is zero length */
+ /* add empty mbuf to free chain */
+ if ( mp == NULL ) {
+ /* item is head of free list */
+ mf = m->m_next;
+ mp = mf;
+ }
+ else {
+ /* add item to end of the free list */
+ mp->m_next = m->m_next;
+ mp = m->m_next;
+ }
+
+ /* remove empty item from process chain */
+ m->m_next = m->m_next->m_next;
+ mp->m_next = NULL;
+ }
+#endif
+ /* move to next packet */
+ m = m->m_next;
+ }
+
+ /* ensure there is data to be sent out */
+ tp = (struct rtems_termios_tty *)sc->sc_devp;
+ if (( tp != NULL ) && ( sc->sc_outmc != (struct mbuf *)0 )) {
+ /* place FCS value into buffer */
+ sc->sc_outfcsbuf[sc->sc_outfcslen++] = ~sc->sc_outfcs & 0xff;
+ sc->sc_outfcsbuf[sc->sc_outfcslen++] = (~sc->sc_outfcs >> 8) & 0xff;
+ microtime(&sc->sc_if.if_lastchange);
+
+ /* write out frame byte to start the transmission */
+ sc->sc_outchar = (u_char)PPP_FLAG;
+ (*tp->device.write)(tp->minor, &sc->sc_outchar, 1);
+ }
+
+ /* check to see if we need to free some empty mbufs */
+ if ( mf != (struct mbuf *)0 ) {
+ /* free empty mbufs */
+ rtems_bsdnet_semaphore_obtain();
+ m_freem(mf);
+ rtems_bsdnet_semaphore_release();
+ }
+ }
+ }
+}
+
+static void ppp_init(struct ppp_softc *sc)
+{
+ rtems_status_code status;
+ uint32_t priority = 100;
+
+ /* determine priority value */
+ if ( rtems_bsdnet_config.network_task_priority ) {
+ priority = rtems_bsdnet_config.network_task_priority;
+ }
+
+ /* check to see if we need to start up daemons */
+ if ( sc->sc_rxtask == 0 ) {
+ /* start rx daemon task */
+ status = rtems_task_create(rtems_build_name('R','x','P','0'+sc->sc_if.if_unit), priority, 2048,
+ RTEMS_PREEMPT|RTEMS_NO_TIMESLICE|RTEMS_NO_ASR|RTEMS_INTERRUPT_LEVEL(0),
+ RTEMS_NO_FLOATING_POINT|RTEMS_LOCAL,
+ &sc->sc_rxtask);
+ if (status != RTEMS_SUCCESSFUL) {
+ rtems_fatal_error_occurred(status);
+ }
+ else {
+ status = rtems_task_start(sc->sc_rxtask, ppp_rxdaemon, (rtems_task_argument)sc);
+ if (status != RTEMS_SUCCESSFUL) {
+ rtems_fatal_error_occurred(status);
+ }
+ }
+
+ /* start tx daemon task */
+ status = rtems_task_create(rtems_build_name('T','x','P','0'+sc->sc_if.if_unit), priority, 2048,
+ RTEMS_PREEMPT|RTEMS_NO_TIMESLICE|RTEMS_NO_ASR|RTEMS_INTERRUPT_LEVEL(0),
+ RTEMS_NO_FLOATING_POINT|RTEMS_LOCAL,
+ &sc->sc_txtask);
+ if (status != RTEMS_SUCCESSFUL) {
+ rtems_fatal_error_occurred(status);
+ }
+ else {
+ status = rtems_task_start(sc->sc_txtask, ppp_txdaemon, (rtems_task_argument)sc);
+ if (status != RTEMS_SUCCESSFUL) {
+ rtems_fatal_error_occurred(status);
+ }
+ }
+ }
+
+ /* mark driver running and output inactive */
+ /* ilya: IFF_RUNNING flag will be marked after the IPCP goes up */
+/* sc->sc_if.if_flags |= IFF_RUNNING; */
+}
+
+/*
+ * Called from boot code to establish ppp interfaces.
+ */
+int rtems_ppp_driver_attach(struct rtems_bsdnet_ifconfig *config, int attaching)
+{
+/* int i = (int)0; */
+ struct ppp_softc *sc;
+ char *name;
+ int number;
+
+
+ number = rtems_bsdnet_parse_driver_name (config, &name);
+
+ if (!attaching || (number >= NPPP))
+ return 0;
+
+ sc = &ppp_softc[number];
+
+ if (sc->sc_if.if_name != NULL)
+ return 0; /* interface is already attached */
+
+/* for (sc = ppp_softc; i < NPPP; sc++) { */
+ sc->sc_if.if_name = name /*"ppp"*/;
+ sc->sc_if.if_unit = number /*i++*/;
+ sc->sc_if.if_mtu = PPP_MTU;
+ sc->sc_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
+ sc->sc_if.if_type = IFT_PPP;
+ sc->sc_if.if_hdrlen = PPP_HDRLEN;
+ sc->sc_if.if_ioctl = pppsioctl;
+ sc->sc_if.if_output = pppoutput;
+ sc->sc_if.if_snd.ifq_maxlen = IFQ_MAXLEN;
+ sc->sc_inq.ifq_maxlen = IFQ_MAXLEN;
+ sc->sc_fastq.ifq_maxlen = IFQ_MAXLEN;
+ sc->sc_rawq.ifq_maxlen = IFQ_MAXLEN;
+ sc->sc_freeq.ifq_maxlen = NUM_MBUFQ;
+
+ /* initialize and attach */
+ ppp_init(sc);
+ if_attach(&sc->sc_if);
+#if NBPFILTER > 0
+ bpfattach(&sc->sc_bpf, &sc->sc_if, DLT_PPP, PPP_HDRLEN);
+#endif
+/* } */
+
+ return ( 1 );
+}
+
+/*
+ * Allocate a ppp interface unit and initialize it.
+ */
+struct ppp_softc *
+pppalloc(pid)
+ pid_t pid;
+{
+ int nppp, i;
+ struct ppp_softc *sc;
+
+ for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++)
+ if (sc->sc_xfer == pid) {
+ sc->sc_xfer = 0;
+ return sc;
+ }
+ for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++)
+ if (sc->sc_devp == NULL)
+ break;
+ if (nppp >= NPPP)
+ return NULL;
+
+ sc->sc_flags = 0;
+ sc->sc_mru = PPP_MRU;
+ sc->sc_relinq = NULL;
+ bzero((char *)&sc->sc_stats, sizeof(sc->sc_stats));
+#ifdef VJC
+ MALLOC(sc->sc_comp, struct vjcompress *, sizeof(struct vjcompress),
+ M_DEVBUF, M_NOWAIT);
+ if (sc->sc_comp)
+ vj_compress_init(sc->sc_comp, -1);
+#endif
+#ifdef PPP_COMPRESS
+ sc->sc_xc_state = NULL;
+ sc->sc_rc_state = NULL;
+#endif /* PPP_COMPRESS */
+ for (i = 0; i < NUM_NP; ++i)
+ sc->sc_npmode[i] = NPMODE_ERROR;
+ sc->sc_npqueue = NULL;
+ sc->sc_npqtail = &sc->sc_npqueue;
+ microtime(&ppp_time);
+ sc->sc_last_sent = sc->sc_last_recv = ppp_time.tv_sec;
+
+ return sc;
+}
+
+/*
+ * Deallocate a ppp unit. Must be called at splsoftnet or higher.
+ */
+void
+pppdealloc(sc)
+ struct ppp_softc *sc;
+{
+ struct mbuf *m;
+ rtems_interrupt_level level;
+
+ if_down(&sc->sc_if);
+ sc->sc_if.if_flags &= ~(IFF_UP|IFF_RUNNING);
+ sc->sc_devp = NULL;
+ sc->sc_xfer = 0;
+
+ rtems_interrupt_disable(level);
+ if ( sc->sc_m != NULL ) {
+ m_freem(sc->sc_m);
+ sc->sc_m = (struct mbuf *)0;
+ }
+ if ( sc->sc_outm != NULL ) {
+ m_freem(sc->sc_outm);
+ sc->sc_outm = (struct mbuf *)0;
+ sc->sc_outmc = (struct mbuf *)0;
+ sc->sc_outflag = 0;
+ }
+ do {
+ IF_DEQUEUE(&sc->sc_freeq, m);
+ if (m != NULL) {
+ m_freem(m);
+ }
+ } while ( m != NULL );
+ do {
+ IF_DEQUEUE(&sc->sc_rawq, m);
+ if (m != NULL) {
+ m_freem(m);
+ }
+ } while ( m != NULL );
+ rtems_interrupt_enable(level);
+
+ for (;;) {
+ IF_DEQUEUE(&sc->sc_inq, m);
+ if (m == NULL)
+ break;
+ m_freem(m);
+ }
+ for (;;) {
+ IF_DEQUEUE(&sc->sc_fastq, m);
+ if (m == NULL)
+ break;
+ m_freem(m);
+ }
+ while ((m = sc->sc_npqueue) != NULL) {
+ sc->sc_npqueue = m->m_nextpkt;
+ m_freem(m);
+ }
+#ifdef PPP_COMPRESS
+ ppp_ccp_closed(sc);
+ sc->sc_xc_state = NULL;
+ sc->sc_rc_state = NULL;
+#endif /* PPP_COMPRESS */
+#ifdef PPP_FILTER
+ if (sc->sc_pass_filt.bf_insns != 0) {
+ FREE(sc->sc_pass_filt.bf_insns, M_DEVBUF);
+ sc->sc_pass_filt.bf_insns = 0;
+ sc->sc_pass_filt.bf_len = 0;
+ }
+ if (sc->sc_active_filt.bf_insns != 0) {
+ FREE(sc->sc_active_filt.bf_insns, M_DEVBUF);
+ sc->sc_active_filt.bf_insns = 0;
+ sc->sc_active_filt.bf_len = 0;
+ }
+#endif /* PPP_FILTER */
+#ifdef VJC
+ if (sc->sc_comp != 0) {
+ FREE(sc->sc_comp, M_DEVBUF);
+ sc->sc_comp = 0;
+ }
+#endif
+}
+
+/*
+ * Ioctl routine for generic ppp devices.
+ */
+int
+pppioctl(sc, cmd, data, flag, p)
+ struct ppp_softc *sc;
+ int cmd;
+ caddr_t data;
+ int flag;
+ struct proc *p;
+{
+ int s, flags, mru, npx, taskid;
+ struct npioctl *npi;
+ time_t t;
+#ifdef PPP_FILTER
+ int error;
+ struct bpf_program *bp, *nbp;
+ struct bpf_insn *newcode, *oldcode;
+ int newcodelen;
+#endif /* PPP_FILTER */
+#ifdef PPP_COMPRESS
+ int nb;
+ struct ppp_option_data *odp;
+ struct compressor **cp;
+ u_char ccp_option[CCP_MAX_OPTION_LENGTH];
+#endif
+
+ switch (cmd) {
+ case FIONREAD:
+ *(int *)data = sc->sc_inq.ifq_len;
+ break;
+
+ case PPPIOCSTASK:
+ taskid = *(int *)data;
+ sc->sc_pppdtask = taskid;
+ break;
+
+ case PPPIOCGUNIT:
+ *(int *)data = sc->sc_if.if_unit;
+ break;
+
+ case PPPIOCGFLAGS:
+ *(u_int *)data = sc->sc_flags;
+ break;
+
+ case PPPIOCSFLAGS:
+ flags = *(int *)data & SC_MASK;
+ s = splsoftnet();
+#ifdef PPP_COMPRESS
+ if (sc->sc_flags & SC_CCP_OPEN && !(flags & SC_CCP_OPEN))
+ ppp_ccp_closed(sc);
+#endif
+ s = splimp();
+ sc->sc_flags = (sc->sc_flags & ~SC_MASK) | flags;
+ splx(s);
+ break;
+
+ case PPPIOCSMRU:
+ mru = *(int *)data;
+ if ( mru >= MCLBYTES ) {
+ /* error - currently only handle 1 culster sized MRU */
+ /* if we want to handle up to PPP_MAXMRU then we */
+ /* need to reallocate all mbufs on the freeq */
+ /* this can only be done with iterrupts disabled */
+ return ( -1 );
+ }
+ else if ( mru >= PPP_MRU ) {
+ /* update the size */
+ sc->sc_mru = mru;
+ }
+ break;
+
+ case PPPIOCGMRU:
+ *(int *)data = sc->sc_mru;
+ break;
+
+#ifdef VJC
+ case PPPIOCSMAXCID:
+ if (sc->sc_comp) {
+ s = splsoftnet();
+ vj_compress_init(sc->sc_comp, *(int *)data);
+ splx(s);
+ }
+ break;
+#endif
+
+ case PPPIOCXFERUNIT:
+ sc->sc_xfer = 0; /* Always root p->p_pid;*/
+ break;
+
+#ifdef PPP_COMPRESS
+ case PPPIOCSCOMPRESS:
+ odp = (struct ppp_option_data *) data;
+ nb = odp->length;
+ if (nb > sizeof(ccp_option))
+ nb = sizeof(ccp_option);
+ if ((error = copyin(odp->ptr, ccp_option, nb)) != 0)
+ return (error);
+ if (ccp_option[1] < 2) /* preliminary check on the length byte */
+ return (EINVAL);
+ for (cp = ppp_compressors; *cp != NULL; ++cp)
+ if ((*cp)->compress_proto == ccp_option[0]) {
+ /*
+ * Found a handler for the protocol - try to allocate
+ * a compressor or decompressor.
+ */
+ error = 0;
+ if (odp->transmit) {
+ s = splsoftnet();
+ if (sc->sc_xc_state != NULL)
+ (*sc->sc_xcomp->comp_free)(sc->sc_xc_state);
+ sc->sc_xcomp = *cp;
+ sc->sc_xc_state = (*cp)->comp_alloc(ccp_option, nb);
+ if (sc->sc_xc_state == NULL) {
+ if (sc->sc_flags & SC_DEBUG)
+ printf("ppp%d: comp_alloc failed\n",
+ sc->sc_if.if_unit);
+ error = ENOBUFS;
+ }
+ splimp();
+ sc->sc_flags &= ~SC_COMP_RUN;
+ splx(s);
+ } else {
+ s = splsoftnet();
+ if (sc->sc_rc_state != NULL)
+ (*sc->sc_rcomp->decomp_free)(sc->sc_rc_state);
+ sc->sc_rcomp = *cp;
+ sc->sc_rc_state = (*cp)->decomp_alloc(ccp_option, nb);
+ if (sc->sc_rc_state == NULL) {
+ if (sc->sc_flags & SC_DEBUG)
+ printf("ppp%d: decomp_alloc failed\n",
+ sc->sc_if.if_unit);
+ error = ENOBUFS;
+ }
+ splimp();
+ sc->sc_flags &= ~SC_DECOMP_RUN;
+ splx(s);
+ }
+ return (error);
+ }
+ if (sc->sc_flags & SC_DEBUG)
+ printf("ppp%d: no compressor for [%x %x %x], %x\n",
+ sc->sc_if.if_unit, ccp_option[0], ccp_option[1],
+ ccp_option[2], nb);
+ return (EINVAL); /* no handler found */
+#endif /* PPP_COMPRESS */
+
+ case PPPIOCGNPMODE:
+ case PPPIOCSNPMODE:
+ npi = (struct npioctl *) data;
+ switch (npi->protocol) {
+ case PPP_IP:
+ npx = NP_IP;
+ break;
+ default:
+ return EINVAL;
+ }
+ if (cmd == PPPIOCGNPMODE) {
+ npi->mode = sc->sc_npmode[npx];
+ } else {
+ if (npi->mode != sc->sc_npmode[npx]) {
+ s = splsoftnet();
+ sc->sc_npmode[npx] = npi->mode;
+ if (npi->mode != NPMODE_QUEUE) {
+ ppp_requeue(sc);
+ (*sc->sc_start)(sc);
+ }
+ splx(s);
+ }
+ }
+ break;
+
+ case PPPIOCGIDLE:
+ s = splsoftnet();
+ microtime(&ppp_time);
+ t = ppp_time.tv_sec;
+ ((struct ppp_idle *)data)->xmit_idle = t - sc->sc_last_sent;
+ ((struct ppp_idle *)data)->recv_idle = t - sc->sc_last_recv;
+ splx(s);
+ break;
+
+#ifdef PPP_FILTER
+ case PPPIOCSPASS:
+ case PPPIOCSACTIVE:
+ nbp = (struct bpf_program *) data;
+ if ((unsigned) nbp->bf_len > BPF_MAXINSNS)
+ return EINVAL;
+ newcodelen = nbp->bf_len * sizeof(struct bpf_insn);
+ if (newcodelen != 0) {
+ MALLOC(newcode, struct bpf_insn *, newcodelen, M_DEVBUF, M_WAITOK);
+ if (newcode == 0) {
+ return EINVAL; /* or sumpin */
+ }
+ if ((error = copyin((caddr_t)nbp->bf_insns, (caddr_t)newcode,
+ newcodelen)) != 0) {
+ FREE(newcode, M_DEVBUF);
+ return error;
+ }
+ if (!bpf_validate(newcode, nbp->bf_len)) {
+ FREE(newcode, M_DEVBUF);
+ return EINVAL;
+ }
+ } else
+ newcode = 0;
+ bp = (cmd == PPPIOCSPASS)? &sc->sc_pass_filt: &sc->sc_active_filt;
+ oldcode = bp->bf_insns;
+ s = splimp();
+ bp->bf_len = nbp->bf_len;
+ bp->bf_insns = newcode;
+ splx(s);
+ if (oldcode != 0)
+ FREE(oldcode, M_DEVBUF);
+ break;
+#endif
+
+ default:
+ return (-1);
+ }
+ return (0);
+}
+
+/*
+ * Process an ioctl request to the ppp network interface.
+ */
+static int
+pppsioctl(ifp, cmd, data)
+ register struct ifnet *ifp;
+ int cmd;
+ caddr_t data;
+{
+ /*struct proc *p = curproc;*/ /* XXX */
+ register struct ppp_softc *sc = &ppp_softc[ifp->if_unit];
+ register struct ifaddr *ifa = (struct ifaddr *)data;
+ register struct ifreq *ifr = (struct ifreq *)data;
+ struct ppp_stats *psp;
+#ifdef PPP_COMPRESS
+ struct ppp_comp_stats *pcp;
+#endif
+ int s = splimp(), error = 0;
+
+ switch (cmd) {
+ case SIOCSIFFLAGS:
+ if ((ifp->if_flags & IFF_RUNNING) == 0)
+ ifp->if_flags &= ~IFF_UP;
+ break;
+
+ case SIOCSIFADDR:
+ if (ifa->ifa_addr->sa_family != AF_INET)
+ error = EAFNOSUPPORT;
+ break;
+
+ case SIOCSIFDSTADDR:
+ if (ifa->ifa_addr->sa_family != AF_INET)
+ error = EAFNOSUPPORT;
+ break;
+
+ case SIOCSIFMTU:
+ sc->sc_if.if_mtu = ifr->ifr_mtu;
+ break;
+
+ case SIOCGIFMTU:
+ ifr->ifr_mtu = sc->sc_if.if_mtu;
+ break;
+
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ if (ifr == 0) {
+ error = EAFNOSUPPORT;
+ break;
+ }
+ switch(ifr->ifr_addr.sa_family) {
+#ifdef INET
+ case AF_INET:
+ break;
+#endif
+ default:
+ error = EAFNOSUPPORT;
+ break;
+ }
+ break;
+
+ case SIO_RTEMS_SHOW_STATS:
+ printf(" MRU:%-8u", sc->sc_mru);
+ printf(" Bytes received:%-8u", sc->sc_stats.ppp_ibytes);
+ printf(" Packets received:%-8u", sc->sc_stats.ppp_ipackets);
+ printf(" Receive errors:%-8u\n", sc->sc_stats.ppp_ierrors);
+ printf(" Bytes sent:%-8u", sc->sc_stats.ppp_obytes);
+ printf(" Packets sent:%-8u", sc->sc_stats.ppp_opackets);
+ printf(" Transmit errors:%-8u\n", sc->sc_stats.ppp_oerrors);
+ break;
+
+ case SIOCGPPPSTATS:
+ psp = &((struct ifpppstatsreq *) data)->stats;
+ bzero(psp, sizeof(*psp));
+ psp->p = sc->sc_stats;
+#if defined(VJC) && !defined(SL_NO_STATS)
+ if (sc->sc_comp) {
+ psp->vj.vjs_packets = sc->sc_comp->sls_packets;
+ psp->vj.vjs_compressed = sc->sc_comp->sls_compressed;
+ psp->vj.vjs_searches = sc->sc_comp->sls_searches;
+ psp->vj.vjs_misses = sc->sc_comp->sls_misses;
+ psp->vj.vjs_uncompressedin = sc->sc_comp->sls_uncompressedin;
+ psp->vj.vjs_compressedin = sc->sc_comp->sls_compressedin;
+ psp->vj.vjs_errorin = sc->sc_comp->sls_errorin;
+ psp->vj.vjs_tossed = sc->sc_comp->sls_tossed;
+ }
+#endif /* VJC */
+ break;
+
+#ifdef PPP_COMPRESS
+ case SIOCGPPPCSTATS:
+ pcp = &((struct ifpppcstatsreq *) data)->stats;
+ bzero(pcp, sizeof(*pcp));
+ if (sc->sc_xc_state != NULL)
+ (*sc->sc_xcomp->comp_stat)(sc->sc_xc_state, &pcp->c);
+ if (sc->sc_rc_state != NULL)
+ (*sc->sc_rcomp->decomp_stat)(sc->sc_rc_state, &pcp->d);
+ break;
+#endif /* PPP_COMPRESS */
+
+ default:
+ error = EINVAL;
+ }
+ splx(s);
+ return (error);
+}
+
+/*
+ * Queue a packet. Start transmission if not active.
+ * Packet is placed in Information field of PPP frame.
+ */
+int
+pppoutput(ifp, m0, dst, rtp)
+ struct ifnet *ifp;
+ struct mbuf *m0;
+ struct sockaddr *dst;
+ struct rtentry *rtp;
+{
+ register struct ppp_softc *sc = &ppp_softc[ifp->if_unit];
+ int protocol, address, control;
+ u_char *cp;
+ int s, error;
+ struct ip *ip;
+ struct ifqueue *ifq;
+ enum NPmode mode;
+ int len;
+ struct mbuf *m;
+
+ if (sc->sc_devp == NULL || (ifp->if_flags & IFF_RUNNING) == 0
+ || ((ifp->if_flags & IFF_UP) == 0 && dst->sa_family != AF_UNSPEC)) {
+ error = ENETDOWN; /* sort of */
+ goto bad;
+ }
+
+ /*
+ * Compute PPP header.
+ */
+ m0->m_flags &= ~M_HIGHPRI;
+ switch (dst->sa_family) {
+#ifdef INET
+ case AF_INET:
+ address = PPP_ALLSTATIONS;
+ control = PPP_UI;
+ protocol = PPP_IP;
+ mode = sc->sc_npmode[NP_IP];
+
+ /*
+ * If this packet has the "low delay" bit set in the IP header,
+ * put it on the fastq instead.
+ */
+ ip = mtod(m0, struct ip *);
+ if (ip->ip_tos & IPTOS_LOWDELAY)
+ m0->m_flags |= M_HIGHPRI;
+ break;
+#endif
+ case AF_UNSPEC:
+ address = PPP_ADDRESS(dst->sa_data);
+ control = PPP_CONTROL(dst->sa_data);
+ protocol = PPP_PROTOCOL(dst->sa_data);
+ mode = NPMODE_PASS;
+ break;
+ default:
+ printf("ppp%d: af%d not supported\n", ifp->if_unit, dst->sa_family);
+ error = EAFNOSUPPORT;
+ goto bad;
+ }
+
+ /*
+ * Drop this packet, or return an error, if necessary.
+ */
+ if (mode == NPMODE_ERROR) {
+ error = ENETDOWN;
+ goto bad;
+ }
+ if (mode == NPMODE_DROP) {
+ error = 0;
+ goto bad;
+ }
+
+ /*
+ * Add PPP header. If no space in first mbuf, allocate another.
+ * (This assumes M_LEADINGSPACE is always 0 for a cluster mbuf.)
+ */
+ if (M_LEADINGSPACE(m0) < PPP_HDRLEN) {
+ m0 = m_prepend(m0, PPP_HDRLEN, M_DONTWAIT);
+ if (m0 == 0) {
+ error = ENOBUFS;
+ goto bad;
+ }
+ m0->m_len = 0;
+ } else
+ m0->m_data -= PPP_HDRLEN;
+
+ cp = mtod(m0, u_char *);
+ *cp++ = address;
+ *cp++ = control;
+ *cp++ = protocol >> 8;
+ *cp++ = protocol & 0xff;
+ m0->m_len += PPP_HDRLEN;
+
+ len = 0;
+ for (m = m0; m != 0; m = m->m_next)
+ len += m->m_len;
+
+ if (sc->sc_flags & SC_LOG_OUTPKT) {
+ printf("ppp%d output: ", ifp->if_unit);
+ pppdumpm(m0);
+ }
+
+ if ((protocol & 0x8000) == 0) {
+#ifdef PPP_FILTER
+ /*
+ * Apply the pass and active filters to the packet,
+ * but only if it is a data packet.
+ */
+ *mtod(m0, u_char *) = 1; /* indicates outbound */
+ if (sc->sc_pass_filt.bf_insns != 0
+ && bpf_filter(sc->sc_pass_filt.bf_insns, (u_char *) m0,
+ len, 0) == 0) {
+ error = 0; /* drop this packet */
+ goto bad;
+ }
+
+ /*
+ * Update the time we sent the most recent packet.
+ */
+ if (sc->sc_active_filt.bf_insns == 0
+ || bpf_filter(sc->sc_active_filt.bf_insns, (u_char *) m0, len, 0))
+ sc->sc_last_sent = time.tv_sec;
+
+ *mtod(m0, u_char *) = address;
+#else
+ /*
+ * Update the time we sent the most recent data packet.
+ */
+ microtime(&ppp_time);
+ sc->sc_last_sent = ppp_time.tv_sec;
+#endif /* PPP_FILTER */
+ }
+
+#if NBPFILTER > 0
+ /*
+ * See if bpf wants to look at the packet.
+ */
+ if (sc->sc_bpf)
+ bpf_mtap(sc->sc_bpf, m0);
+#endif
+
+ /*
+ * Put the packet on the appropriate queue.
+ */
+ s = splsoftnet();
+ if (mode == NPMODE_QUEUE) {
+ /* XXX we should limit the number of packets on this queue */
+ *sc->sc_npqtail = m0;
+ m0->m_nextpkt = NULL;
+ sc->sc_npqtail = &m0->m_nextpkt;
+ } else {
+ ifq = (m0->m_flags & M_HIGHPRI)? &sc->sc_fastq: &ifp->if_snd;
+ if (IF_QFULL(ifq) && dst->sa_family != AF_UNSPEC) {
+ IF_DROP(ifq);
+ splx(s);
+ sc->sc_if.if_oerrors++;
+ sc->sc_stats.ppp_oerrors++;
+ error = ENOBUFS;
+ goto bad;
+ }
+ IF_ENQUEUE(ifq, m0);
+ (*sc->sc_start)(sc);
+ }
+ ifp->if_lastchange = ppp_time;
+ ifp->if_opackets++;
+ ifp->if_obytes += len;
+
+ splx(s);
+ return (0);
+
+bad:
+ m_freem(m0);
+ return (error);
+}
+
+/*
+ * After a change in the NPmode for some NP, move packets from the
+ * npqueue to the send queue or the fast queue as appropriate.
+ * Should be called at splsoftnet.
+ */
+static void
+ppp_requeue(sc)
+ struct ppp_softc *sc;
+{
+ struct mbuf *m, **mpp;
+ struct ifqueue *ifq;
+ enum NPmode mode;
+
+ for (mpp = &sc->sc_npqueue; (m = *mpp) != NULL; ) {
+ switch (PPP_PROTOCOL(mtod(m, u_char *))) {
+ case PPP_IP:
+ mode = sc->sc_npmode[NP_IP];
+ break;
+ default:
+ mode = NPMODE_PASS;
+ }
+
+ switch (mode) {
+ case NPMODE_PASS:
+ /*
+ * This packet can now go on one of the queues to be sent.
+ */
+ *mpp = m->m_nextpkt;
+ m->m_nextpkt = NULL;
+ ifq = (m->m_flags & M_HIGHPRI)? &sc->sc_fastq: &sc->sc_if.if_snd;
+ if (IF_QFULL(ifq)) {
+ IF_DROP(ifq);
+ sc->sc_if.if_oerrors++;
+ sc->sc_stats.ppp_oerrors++;
+ } else
+ IF_ENQUEUE(ifq, m);
+ break;
+
+ case NPMODE_DROP:
+ case NPMODE_ERROR:
+ *mpp = m->m_nextpkt;
+ m_freem(m);
+ break;
+
+ case NPMODE_QUEUE:
+ mpp = &m->m_nextpkt;
+ break;
+ }
+ }
+ sc->sc_npqtail = mpp;
+}
+
+/*
+ * Get a packet to send. This procedure is intended to be called at
+ * splsoftnet, since it may involve time-consuming operations such as
+ * applying VJ compression, packet compression, address/control and/or
+ * protocol field compression to the packet.
+ */
+struct mbuf *
+ppp_dequeue(sc)
+ struct ppp_softc *sc;
+{
+ struct mbuf *m;
+#ifdef VJC
+ struct mbuf *mp;
+#endif
+ u_char *cp;
+ int address, control, protocol;
+
+ /*
+ * Grab a packet to send: first try the fast queue, then the
+ * normal queue.
+ */
+ rtems_bsdnet_semaphore_obtain();
+ IF_DEQUEUE(&sc->sc_fastq, m);
+ if (m == NULL)
+ IF_DEQUEUE(&sc->sc_if.if_snd, m);
+ rtems_bsdnet_semaphore_release();
+
+ if (m == NULL)
+ return NULL;
+
+ ++sc->sc_stats.ppp_opackets;
+
+ /*
+ * Extract the ppp header of the new packet.
+ * The ppp header will be in one mbuf.
+ */
+ cp = mtod(m, u_char *);
+ address = PPP_ADDRESS(cp);
+ control = PPP_CONTROL(cp);
+ protocol = PPP_PROTOCOL(cp);
+
+ switch (protocol) {
+ case PPP_IP:
+#ifdef VJC
+ /*
+ * If the packet is a TCP/IP packet, see if we can compress it.
+ */
+ if ((sc->sc_flags & SC_COMP_TCP) && sc->sc_comp != NULL) {
+ struct ip *ip;
+ int type;
+
+ mp = m;
+ ip = (struct ip *) (cp + PPP_HDRLEN);
+ if (mp->m_len <= PPP_HDRLEN) {
+ mp = mp->m_next;
+ if (mp == NULL)
+ break;
+ ip = mtod(mp, struct ip *);
+ }
+ /* this code assumes the IP/TCP header is in one non-shared mbuf */
+ if (ip->ip_p == IPPROTO_TCP) {
+ type = vj_compress_tcp(mp, ip, sc->sc_comp,
+ !(sc->sc_flags & SC_NO_TCP_CCID));
+ switch (type) {
+ case TYPE_UNCOMPRESSED_TCP:
+ protocol = PPP_VJC_UNCOMP;
+ break;
+ case TYPE_COMPRESSED_TCP:
+ protocol = PPP_VJC_COMP;
+ cp = mtod(m, u_char *);
+ cp[0] = address; /* header has moved */
+ cp[1] = control;
+ cp[2] = 0;
+ break;
+ }
+ cp[3] = protocol; /* update protocol in PPP header */
+ }
+ }
+#endif /* VJC */
+ break;
+
+#ifdef PPP_COMPRESS
+ case PPP_CCP:
+ ppp_ccp(sc, m, 0);
+ break;
+#endif /* PPP_COMPRESS */
+ }
+
+#ifdef PPP_COMPRESS
+ if (protocol != PPP_LCP && protocol != PPP_CCP
+ && sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN)) {
+ struct mbuf *mcomp = NULL;
+ int slen, clen;
+
+ slen = 0;
+ for (mp = m; mp != NULL; mp = mp->m_next)
+ slen += mp->m_len;
+ clen = (*sc->sc_xcomp->compress)
+ (sc->sc_xc_state, &mcomp, m, slen, sc->sc_if.if_mtu + PPP_HDRLEN);
+ if (mcomp != NULL) {
+ if (sc->sc_flags & SC_CCP_UP) {
+ /* Send the compressed packet instead of the original. */
+ m_freem(m);
+ m = mcomp;
+ cp = mtod(m, u_char *);
+ protocol = cp[3];
+ } else {
+ /* Can't transmit compressed packets until CCP is up. */
+ m_freem(mcomp);
+ }
+ }
+ }
+#endif /* PPP_COMPRESS */
+
+ /*
+ * Compress the address/control and protocol, if possible.
+ */
+ if (sc->sc_flags & SC_COMP_AC && address == PPP_ALLSTATIONS &&
+ control == PPP_UI && protocol != PPP_ALLSTATIONS &&
+ protocol != PPP_LCP) {
+ /* can compress address/control */
+ m->m_data += 2;
+ m->m_len -= 2;
+ }
+ if (sc->sc_flags & SC_COMP_PROT && protocol < 0xFF) {
+ /* can compress protocol */
+ if (mtod(m, u_char *) == cp) {
+ cp[2] = cp[1]; /* move address/control up */
+ cp[1] = cp[0];
+ }
+ ++m->m_data;
+ --m->m_len;
+ }
+
+ return m;
+}
+
+/*
+ * Software interrupt routine, called at splsoftnet.
+ */
+void
+pppintr(void)
+{
+}
+
+#ifdef PPP_COMPRESS
+/*
+ * Handle a CCP packet. `rcvd' is 1 if the packet was received,
+ * 0 if it is about to be transmitted.
+ */
+static void
+ppp_ccp(sc, m, rcvd)
+ struct ppp_softc *sc;
+ struct mbuf *m;
+ int rcvd;
+{
+ u_char *dp, *ep;
+ struct mbuf *mp;
+ int slen, s;
+
+ /*
+ * Get a pointer to the data after the PPP header.
+ */
+ if (m->m_len <= PPP_HDRLEN) {
+ mp = m->m_next;
+ if (mp == NULL)
+ return;
+ dp = (mp != NULL)? mtod(mp, u_char *): NULL;
+ } else {
+ mp = m;
+ dp = mtod(mp, u_char *) + PPP_HDRLEN;
+ }
+
+ ep = mtod(mp, u_char *) + mp->m_len;
+ if (dp + CCP_HDRLEN > ep)
+ return;
+ slen = CCP_LENGTH(dp);
+ if (dp + slen > ep) {
+ if (sc->sc_flags & SC_DEBUG)
+ printf("if_ppp/ccp: not enough data in mbuf (%p+%x > %p+%x)\n",
+ dp, slen, mtod(mp, u_char *), mp->m_len);
+ return;
+ }
+
+ switch (CCP_CODE(dp)) {
+ case CCP_CONFREQ:
+ case CCP_TERMREQ:
+ case CCP_TERMACK:
+ /* CCP must be going down - disable compression */
+ if (sc->sc_flags & SC_CCP_UP) {
+ s = splimp();
+ sc->sc_flags &= ~(SC_CCP_UP | SC_COMP_RUN | SC_DECOMP_RUN);
+ splx(s);
+ }
+ break;
+
+ case CCP_CONFACK:
+ if (sc->sc_flags & SC_CCP_OPEN && !(sc->sc_flags & SC_CCP_UP)
+ && slen >= CCP_HDRLEN + CCP_OPT_MINLEN
+ && slen >= CCP_OPT_LENGTH(dp + CCP_HDRLEN) + CCP_HDRLEN) {
+ if (!rcvd) {
+ /* we're agreeing to send compressed packets. */
+ if (sc->sc_xc_state != NULL
+ && (*sc->sc_xcomp->comp_init)
+ (sc->sc_xc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN,
+ sc->sc_if.if_unit, 0, sc->sc_flags & SC_DEBUG)) {
+ s = splimp();
+ sc->sc_flags |= SC_COMP_RUN;
+ splx(s);
+ }
+ } else {
+ /* peer is agreeing to send compressed packets. */
+ if (sc->sc_rc_state != NULL
+ && (*sc->sc_rcomp->decomp_init)
+ (sc->sc_rc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN,
+ sc->sc_if.if_unit, 0, sc->sc_mru,
+ sc->sc_flags & SC_DEBUG)) {
+ s = splimp();
+ sc->sc_flags |= SC_DECOMP_RUN;
+ sc->sc_flags &= ~(SC_DC_ERROR | SC_DC_FERROR);
+ splx(s);
+ }
+ }
+ }
+ break;
+
+ case CCP_RESETACK:
+ if (sc->sc_flags & SC_CCP_UP) {
+ if (!rcvd) {
+ if (sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN))
+ (*sc->sc_xcomp->comp_reset)(sc->sc_xc_state);
+ } else {
+ if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) {
+ (*sc->sc_rcomp->decomp_reset)(sc->sc_rc_state);
+ s = splimp();
+ sc->sc_flags &= ~SC_DC_ERROR;
+ splx(s);
+ }
+ }
+ }
+ break;
+ }
+}
+
+/*
+ * CCP is down; free (de)compressor state if necessary.
+ */
+static void
+ppp_ccp_closed(sc)
+ struct ppp_softc *sc;
+{
+ if (sc->sc_xc_state) {
+ (*sc->sc_xcomp->comp_free)(sc->sc_xc_state);
+ sc->sc_xc_state = NULL;
+ }
+ if (sc->sc_rc_state) {
+ (*sc->sc_rcomp->decomp_free)(sc->sc_rc_state);
+ sc->sc_rc_state = NULL;
+ }
+}
+#endif /* PPP_COMPRESS */
+
+/*
+ * Process a received PPP packet, doing decompression as necessary.
+ * Should be called at splsoftnet.
+ */
+#define COMPTYPE(proto) ((proto) == PPP_VJC_COMP? TYPE_COMPRESSED_TCP: \
+ TYPE_UNCOMPRESSED_TCP)
+
+static struct mbuf *
+ppp_inproc(sc, m)
+ struct ppp_softc *sc;
+ struct mbuf *m;
+{
+ struct mbuf *mf = (struct mbuf *)0;
+ struct ifnet *ifp = &sc->sc_if;
+ struct ifqueue *inq;
+ int s, ilen, proto, rv;
+ u_char *cp, adrs, ctrl;
+ struct mbuf *mp;
+#ifdef PPP_COMPRESS
+ struct mbuf *dmp = NULL;
+#endif
+#ifdef VJC
+ u_char *iphdr;
+ u_int hlen;
+ int xlen;
+#endif
+
+ sc->sc_stats.ppp_ipackets++;
+
+ if (sc->sc_flags & SC_LOG_INPKT) {
+ ilen = 0;
+ for (mp = m; mp != NULL; mp = mp->m_next)
+ ilen += mp->m_len;
+ printf("ppp%d: got %d bytes\n", ifp->if_unit, ilen);
+ pppdumpm(m);
+ }
+
+ cp = mtod(m, u_char *);
+ adrs = PPP_ADDRESS(cp);
+ ctrl = PPP_CONTROL(cp);
+ proto = PPP_PROTOCOL(cp);
+
+ if (m->m_flags & M_ERRMARK) {
+ m->m_flags &= ~M_ERRMARK;
+ s = splimp();
+ sc->sc_flags |= SC_VJ_RESET;
+ splx(s);
+ }
+
+#ifdef PPP_COMPRESS
+ /*
+ * Decompress this packet if necessary, update the receiver's
+ * dictionary, or take appropriate action on a CCP packet.
+ */
+ if (proto == PPP_COMP && sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)
+ && !(sc->sc_flags & SC_DC_ERROR) && !(sc->sc_flags & SC_DC_FERROR)) {
+ /* decompress this packet */
+ rv = (*sc->sc_rcomp->decompress)(sc->sc_rc_state, m, &dmp);
+ if (rv == DECOMP_OK) {
+ m_freem(m);
+ if (dmp == NULL) {
+ /* no error, but no decompressed packet produced */
+ return mf;
+ }
+ m = dmp;
+ cp = mtod(m, u_char *);
+ proto = PPP_PROTOCOL(cp);
+
+ } else {
+ /*
+ * An error has occurred in decompression.
+ * Pass the compressed packet up to pppd, which may take
+ * CCP down or issue a Reset-Req.
+ */
+ if (sc->sc_flags & SC_DEBUG)
+ printf("ppp%d: decompress failed %d\n", ifp->if_unit, rv);
+ s = splimp();
+ sc->sc_flags |= SC_VJ_RESET;
+ if (rv == DECOMP_ERROR)
+ sc->sc_flags |= SC_DC_ERROR;
+ else
+ sc->sc_flags |= SC_DC_FERROR;
+ splx(s);
+ }
+
+ } else {
+ if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) {
+ (*sc->sc_rcomp->incomp)(sc->sc_rc_state, m);
+ }
+ if (proto == PPP_CCP) {
+ ppp_ccp(sc, m, 1);
+ }
+ }
+#endif
+
+ ilen = 0;
+ for (mp = m; mp != NULL; mp = mp->m_next)
+ ilen += mp->m_len;
+
+#ifdef VJC
+ if (sc->sc_flags & SC_VJ_RESET) {
+ /*
+ * If we've missed a packet, we must toss subsequent compressed
+ * packets which don't have an explicit connection ID.
+ */
+ if (sc->sc_comp)
+ vj_uncompress_tcp(NULL, 0, TYPE_ERROR, sc->sc_comp);
+ s = splimp();
+ sc->sc_flags &= ~SC_VJ_RESET;
+ splx(s);
+ }
+
+ /*
+ * See if we have a VJ-compressed packet to uncompress.
+ */
+ if (proto == PPP_VJC_COMP) {
+ if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0)
+ goto bad;
+
+ xlen = vj_uncompress_tcp_core(cp + PPP_HDRLEN, m->m_len - PPP_HDRLEN,
+ ilen - PPP_HDRLEN, TYPE_COMPRESSED_TCP,
+ sc->sc_comp, &iphdr, &hlen);
+
+ if (xlen <= 0) {
+ if (sc->sc_flags & SC_DEBUG)
+ printf("ppp%d: VJ uncompress failed on type comp\n",
+ ifp->if_unit);
+ goto bad;
+ }
+
+ /* Copy the PPP and IP headers into a new mbuf. */
+ MGETHDR(mp, M_DONTWAIT, MT_DATA);
+ if (mp == NULL)
+ goto bad;
+ mp->m_len = 0;
+ mp->m_next = NULL;
+ if (hlen + PPP_HDRLEN > MHLEN) {
+ MCLGET(mp, M_DONTWAIT);
+ if (M_TRAILINGSPACE(mp) < hlen + PPP_HDRLEN) {
+ m_freem(mp);
+ goto bad; /* lose if big headers and no clusters */
+ }
+ }
+ cp = mtod(mp, u_char *);
+ cp[0] = adrs;
+ cp[1] = ctrl;
+ cp[2] = 0;
+ cp[3] = PPP_IP;
+ proto = PPP_IP;
+ bcopy(iphdr, cp + PPP_HDRLEN, hlen);
+ mp->m_len = hlen + PPP_HDRLEN;
+
+ /*
+ * Trim the PPP and VJ headers off the old mbuf
+ * and stick the new and old mbufs together.
+ */
+ m->m_data += PPP_HDRLEN + xlen;
+ m->m_len -= PPP_HDRLEN + xlen;
+ if (m->m_len <= M_TRAILINGSPACE(mp)) {
+ bcopy(mtod(m, u_char *), mtod(mp, u_char *) + mp->m_len, m->m_len);
+ mp->m_len += m->m_len;
+ MFREE(m, mp->m_next);
+ } else
+ mp->m_next = m;
+ m = mp;
+ ilen += hlen - xlen;
+
+ } else if (proto == PPP_VJC_UNCOMP) {
+ if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0)
+ goto bad;
+
+ xlen = vj_uncompress_tcp_core(cp + PPP_HDRLEN, m->m_len - PPP_HDRLEN,
+ ilen - PPP_HDRLEN, TYPE_UNCOMPRESSED_TCP,
+ sc->sc_comp, &iphdr, &hlen);
+
+ if (xlen < 0) {
+ if (sc->sc_flags & SC_DEBUG)
+ printf("ppp%d: VJ uncompress failed on type uncomp\n",
+ ifp->if_unit);
+ goto bad;
+ }
+
+ proto = PPP_IP;
+ cp[3] = PPP_IP;
+ }
+#endif /* VJC */
+
+ /*
+ * If the packet will fit in a header mbuf, don't waste a
+ * whole cluster on it.
+ */
+ if (ilen <= MHLEN && M_IS_CLUSTER(m)) {
+ MGETHDR(mp, M_DONTWAIT, MT_DATA);
+ if (mp != NULL) {
+ m_copydata(m, 0, ilen, mtod(mp, caddr_t));
+ /* instead of freeing - return cluster mbuf so it can be reused */
+ /* m_freem(m); */
+ mf = m;
+ m = mp;
+ m->m_len = ilen;
+ }
+ }
+ m->m_pkthdr.len = ilen;
+ m->m_pkthdr.rcvif = ifp;
+
+ if ((proto & 0x8000) == 0) {
+#ifdef PPP_FILTER
+ /*
+ * See whether we want to pass this packet, and
+ * if it counts as link activity.
+ */
+ adrs = *mtod(m, u_char *); /* save address field */
+ *mtod(m, u_char *) = 0; /* indicate inbound */
+ if (sc->sc_pass_filt.bf_insns != 0
+ && bpf_filter(sc->sc_pass_filt.bf_insns, (u_char *) m,
+ ilen, 0) == 0) {
+ /* drop this packet */
+ m_freem(m);
+ return mf;
+ }
+ if (sc->sc_active_filt.bf_insns == 0
+ || bpf_filter(sc->sc_active_filt.bf_insns, (u_char *) m, ilen, 0))
+ sc->sc_last_recv = time.tv_sec;
+
+ *mtod(m, u_char *) = adrs;
+#else
+ /*
+ * Record the time that we received this packet.
+ */
+ microtime(&ppp_time);
+ sc->sc_last_recv = ppp_time.tv_sec;
+#endif /* PPP_FILTER */
+ }
+
+#if NBPFILTER > 0
+ /* See if bpf wants to look at the packet. */
+ if (sc->sc_bpf)
+ bpf_mtap(sc->sc_bpf, m);
+#endif
+
+ rv = 0;
+ switch (proto) {
+#ifdef INET
+ case PPP_IP:
+ /*
+ * IP packet - take off the ppp header and pass it up to IP.
+ */
+ if ((ifp->if_flags & IFF_UP) == 0
+ || sc->sc_npmode[NP_IP] != NPMODE_PASS) {
+ /* interface is down - drop the packet. */
+ m_freem(m);
+ return mf;
+ }
+ m->m_pkthdr.len -= PPP_HDRLEN;
+ m->m_data += PPP_HDRLEN;
+ m->m_len -= PPP_HDRLEN;
+ schednetisr(NETISR_IP);
+ inq = &ipintrq;
+ break;
+#endif
+
+ default:
+ /*
+ * Some other protocol - place on input queue for read().
+ */
+ inq = &sc->sc_inq;
+ rv = 1;
+ break;
+ }
+
+ /*
+ * Put the packet on the appropriate input queue.
+ */
+ s = splimp();
+ if (IF_QFULL(inq)) {
+ IF_DROP(inq);
+ splx(s);
+ if (sc->sc_flags & SC_DEBUG)
+ printf("ppp%d: input queue full\n", ifp->if_unit);
+ ifp->if_iqdrops++;
+ goto bad;
+ }
+ IF_ENQUEUE(inq, m);
+ splx(s);
+
+ ifp->if_ipackets++;
+ ifp->if_ibytes += ilen;
+ microtime(&ppp_time);
+ ifp->if_lastchange = ppp_time;
+
+ if (rv) {
+ (*sc->sc_ctlp)(sc);
+ }
+
+ return mf;
+
+ bad:
+ m_freem(m);
+ sc->sc_if.if_ierrors++;
+ sc->sc_stats.ppp_ierrors++;
+ return mf;
+}
+
+#define MAX_DUMP_BYTES 128
+
+static void
+pppdumpm(m0)
+ struct mbuf *m0;
+{
+ char buf[3*MAX_DUMP_BYTES+4];
+ char *bp = buf;
+ struct mbuf *m;
+ static char digits[] = "0123456789abcdef";
+
+ for (m = m0; m; m = m->m_next) {
+ int l = m->m_len;
+ u_char *rptr = (u_char *)m->m_data;
+
+ while (l--) {
+ if (bp > buf + sizeof(buf) - 4)
+ goto done;
+ *bp++ = digits[*rptr >> 4]; /* convert byte to ascii hex */
+ *bp++ = digits[*rptr++ & 0xf];
+ }
+
+ if (m->m_next) {
+ if (bp > buf + sizeof(buf) - 3)
+ goto done;
+ *bp++ = '|';
+ } else
+ *bp++ = ' ';
+ }
+done:
+ if (m)
+ *bp++ = '>';
+ *bp = 0;
+ printf("%s\n", buf);
+}
+
+#endif /* NPPP > 0 */
diff --git a/cpukit/libnetworking/net/if_ppp.h b/cpukit/libnetworking/net/if_ppp.h
new file mode 100644
index 0000000000..18b191c8e6
--- /dev/null
+++ b/cpukit/libnetworking/net/if_ppp.h
@@ -0,0 +1,134 @@
+/* $Id$ */
+
+/*
+ * if_ppp.h - Point-to-Point Protocol definitions.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef _IF_PPP_H_
+#define _IF_PPP_H_
+
+/*
+ * Bit definitions for flags.
+ */
+#define SC_COMP_PROT 0x00000001 /* protocol compression (output) */
+#define SC_COMP_AC 0x00000002 /* header compression (output) */
+#define SC_COMP_TCP 0x00000004 /* TCP (VJ) compression (output) */
+#define SC_NO_TCP_CCID 0x00000008 /* disable VJ connection-id comp. */
+#define SC_REJ_COMP_AC 0x00000010 /* reject adrs/ctrl comp. on input */
+#define SC_REJ_COMP_TCP 0x00000020 /* reject TCP (VJ) comp. on input */
+#define SC_CCP_OPEN 0x00000040 /* Look at CCP packets */
+#define SC_CCP_UP 0x00000080 /* May send/recv compressed packets */
+#define SC_DEBUG 0x00010000 /* enable debug messages */
+#define SC_LOG_INPKT 0x00020000 /* log contents of good pkts recvd */
+#define SC_LOG_OUTPKT 0x00040000 /* log contents of pkts sent */
+#define SC_LOG_RAWIN 0x00080000 /* log all chars received */
+#define SC_LOG_FLUSH 0x00100000 /* log all chars flushed */
+#define SC_RCV_B7_0 0x01000000 /* have rcvd char with bit 7 = 0 */
+#define SC_RCV_B7_1 0x02000000 /* have rcvd char with bit 7 = 1 */
+#define SC_RCV_EVNP 0x04000000 /* have rcvd char with even parity */
+#define SC_RCV_ODDP 0x08000000 /* have rcvd char with odd parity */
+#define SC_SYNC 0x00200000 /* use synchronous HDLC framing */
+#define SC_MASK 0x0fff00ff /* bits that user can change */
+
+/*
+ * State bits in sc_flags, not changeable by user.
+ */
+#define SC_TIMEOUT 0x00000400 /* timeout is currently pending */
+#define SC_VJ_RESET 0x00000800 /* need to reset VJ decomp */
+#define SC_COMP_RUN 0x00001000 /* compressor has been inited */
+#define SC_DECOMP_RUN 0x00002000 /* decompressor has been inited */
+#define SC_DC_ERROR 0x00004000 /* non-fatal decomp error detected */
+#define SC_DC_FERROR 0x00008000 /* fatal decomp error detected */
+#define SC_TBUSY 0x10000000 /* xmitter doesn't need a packet yet */
+#define SC_PKTLOST 0x20000000 /* have lost or dropped a packet */
+#define SC_FLUSH 0x40000000 /* flush input until next PPP_FLAG */
+#define SC_ESCAPED 0x80000000 /* saw a PPP_ESCAPE */
+
+/*
+ * Ioctl definitions.
+ */
+
+struct npioctl {
+ int protocol; /* PPP procotol, e.g. PPP_IP */
+ enum NPmode mode;
+};
+
+/* Structure describing a CCP configuration option, for PPPIOCSCOMPRESS */
+struct ppp_option_data {
+ u_char *ptr;
+ u_int length;
+ int transmit;
+};
+
+struct ifpppstatsreq {
+ char ifr_name[IFNAMSIZ];
+ struct ppp_stats stats;
+};
+
+struct ifpppcstatsreq {
+ char ifr_name[IFNAMSIZ];
+ struct ppp_comp_stats stats;
+};
+
+/*
+ * Ioctl definitions.
+ */
+
+#define PPPIOCSTASK _IOW('t', 91, int) /* set pppd task id */
+#define PPPIOCGFLAGS _IOR('t', 90, int) /* get configuration flags */
+#define PPPIOCSFLAGS _IOW('t', 89, int) /* set configuration flags */
+#define PPPIOCGASYNCMAP _IOR('t', 88, int) /* get async map */
+#define PPPIOCSASYNCMAP _IOW('t', 87, int) /* set async map */
+#define PPPIOCGUNIT _IOR('t', 86, int) /* get ppp unit number */
+#define PPPIOCGRASYNCMAP _IOR('t', 85, int) /* get receive async map */
+#define PPPIOCSRASYNCMAP _IOW('t', 84, int) /* set receive async map */
+#define PPPIOCGMRU _IOR('t', 83, int) /* get max receive unit */
+#define PPPIOCSMRU _IOW('t', 82, int) /* set max receive unit */
+#define PPPIOCSMAXCID _IOW('t', 81, int) /* set VJ max slot ID */
+#define PPPIOCGXASYNCMAP _IOR('t', 80, ext_accm) /* get extended ACCM */
+#define PPPIOCSXASYNCMAP _IOW('t', 79, ext_accm) /* set extended ACCM */
+#define PPPIOCXFERUNIT _IO('t', 78) /* transfer PPP unit */
+#define PPPIOCSCOMPRESS _IOW('t', 77, struct ppp_option_data)
+#define PPPIOCGNPMODE _IOWR('t', 76, struct npioctl) /* get NP mode */
+#define PPPIOCSNPMODE _IOW('t', 75, struct npioctl) /* set NP mode */
+#define PPPIOCGIDLE _IOR('t', 74, struct ppp_idle) /* get idle time */
+#ifdef PPP_FILTER
+#define PPPIOCSPASS _IOW('t', 71, struct bpf_program) /* set pass filter */
+#define PPPIOCSACTIVE _IOW('t', 70, struct bpf_program) /* set active filt */
+#endif /* PPP_FILTER */
+
+/* PPPIOC[GS]MTU are alternatives to SIOC[GS]IFMTU, used under Ultrix */
+#define PPPIOCGMTU _IOR('t', 73, int) /* get interface MTU */
+#define PPPIOCSMTU _IOW('t', 72, int) /* set interface MTU */
+
+/*
+ * These two are interface ioctls so that pppstats can do them on
+ * a socket without having to open the serial device.
+ */
+#define SIOCGPPPSTATS _IOWR('i', 123, struct ifpppstatsreq)
+#define SIOCGPPPCSTATS _IOWR('i', 122, struct ifpppcstatsreq)
+
+#if !defined(ifr_mtu)
+#define ifr_mtu ifr_ifru.ifru_metric
+#endif
+
+#if (defined(_KERNEL) || defined(_KERNEL)) && !defined(NeXT)
+void pppattach __P((void));
+void pppintr __P((void));
+#endif
+#endif /* _IF_PPP_H_ */
diff --git a/cpukit/libnetworking/net/if_pppvar.h b/cpukit/libnetworking/net/if_pppvar.h
new file mode 100644
index 0000000000..100b6b94e3
--- /dev/null
+++ b/cpukit/libnetworking/net/if_pppvar.h
@@ -0,0 +1,141 @@
+/* $Id$ */
+/*
+ * if_pppvar.h - private structures and declarations for PPP.
+ *
+ * Copyright (c) 1994 The Australian National University.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, provided that the above copyright
+ * notice appears in all copies. This software is provided without any
+ * warranty, express or implied. The Australian National University
+ * makes no representations about the suitability of this software for
+ * any purpose.
+ *
+ * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+ * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
+ * OR MODIFICATIONS.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ * Supported network protocols. These values are used for
+ * indexing sc_npmode.
+ */
+#define NP_IP 0 /* Internet Protocol */
+#define NUM_NP 1 /* Number of NPs. */
+#define NUM_MBUFQ 64
+
+
+/*
+ * Structure describing each ppp unit.
+ */
+struct ppp_softc {
+ struct ifnet sc_if; /* network-visible interface */
+ u_int sc_flags; /* control/status bits; see if_ppp.h */
+ void *sc_devp; /* pointer to device-dep structure */
+ void (*sc_start) __P((struct ppp_softc *)); /* start output proc */
+ void (*sc_ctlp) __P((struct ppp_softc *)); /* rcvd control pkt */
+ void (*sc_relinq) __P((struct ppp_softc *)); /* relinquish ifunit */
+ short sc_mru; /* max receive unit */
+ pid_t sc_xfer; /* used in transferring unit */
+ struct ifqueue sc_rawq; /* received packets */
+ struct ifqueue sc_inq; /* queue of input packets for daemon */
+ struct ifqueue sc_fastq; /* interactive output packet q */
+ struct mbuf *sc_npqueue; /* output packets not to be sent yet */
+ struct mbuf **sc_npqtail; /* ptr to last next ptr in npqueue */
+ struct pppstat sc_stats; /* count of bytes/pkts sent/rcvd */
+ caddr_t sc_bpf; /* hook for BPF */
+ enum NPmode sc_npmode[NUM_NP]; /* what to do with each NP */
+ struct compressor *sc_xcomp; /* transmit compressor */
+ void *sc_xc_state; /* transmit compressor state */
+ struct compressor *sc_rcomp; /* receive decompressor */
+ void *sc_rc_state; /* receive decompressor state */
+ time_t sc_last_sent; /* time (secs) last NP pkt sent */
+ time_t sc_last_recv; /* time (secs) last NP pkt rcvd */
+#ifdef PPP_FILTER
+ struct bpf_program sc_pass_filt; /* filter for packets to pass */
+ struct bpf_program sc_active_filt; /* filter for "non-idle" packets */
+#endif /* PPP_FILTER */
+#ifdef VJC
+ struct vjcompress *sc_comp; /* vjc control buffer */
+#endif
+
+ /* Device-dependent part for async lines. */
+ ext_accm sc_asyncmap; /* async control character map */
+ u_long sc_rasyncmap; /* receive async control char map */
+ struct mbuf *sc_outm; /* mbuf chain currently being output */
+ struct mbuf *sc_outmc; /* mbuf currently being output */
+ struct mbuf *sc_m; /* pointer to input mbuf chain */
+ struct mbuf *sc_mc; /* pointer to current input mbuf */
+ char *sc_mp; /* ptr to next char in input mbuf */
+ short sc_ilen; /* length of input packet so far */
+ u_short sc_fcs; /* FCS so far (input) */
+ u_char sc_rawin[16]; /* chars as received */
+ int sc_rawin_count; /* # in sc_rawin */
+ u_short sc_outfcs; /* FCS so far for output packet */
+
+ struct ifqueue sc_freeq; /* free packets */
+ short sc_outoff; /* output packet byte offset */
+ short sc_outflag; /* output status flag */
+ short sc_outlen; /* length of output packet */
+ short sc_outfcslen; /* length of output fcs data */
+ u_char sc_outfcsbuf[8]; /* output packet fcs buffer */
+ u_char *sc_outbuf; /* pointer to output data */
+ u_char sc_outchar;
+
+ rtems_id sc_rxtask;
+ rtems_id sc_txtask;
+ rtems_id sc_pppdtask;
+};
+
+struct ppp_softc ppp_softc[NPPP];
+
+struct ppp_softc *pppalloc __P((pid_t pid));
+void pppdealloc __P((struct ppp_softc *sc));
+int pppoutput __P((struct ifnet *, struct mbuf *,
+ struct sockaddr *, struct rtentry *));
+int pppioctl __P((struct ppp_softc *sc, int cmd, caddr_t data,
+ int flag, struct proc *p));
+struct mbuf *ppp_dequeue __P((struct ppp_softc *sc));
+u_short pppfcs __P((u_short fcs, u_char *cp, int len));
+void pppallocmbuf __P((struct ppp_softc *sc, struct mbuf **mp));
+
+
+/* define event values */
+#define RX_PACKET RTEMS_EVENT_1
+#define RX_MBUF RTEMS_EVENT_2
+#define RX_EMPTY RTEMS_EVENT_3
+#define TX_PACKET RTEMS_EVENT_1
+#define TX_TRANSMIT RTEMS_EVENT_2
+#define PPPD_EVENT RTEMS_EVENT_31
+
+/* define out flag values */
+#define SC_TX_BUSY 0x0001
+#define SC_TX_FCS 0x0002
+#define SC_TX_ESCAPE 0x0004
+#define SC_TX_LASTCHAR 0x0008
+#define SC_TX_PENDING 0x0010
diff --git a/cpukit/libnetworking/net/if_types.h b/cpukit/libnetworking/net/if_types.h
new file mode 100644
index 0000000000..833ba471c3
--- /dev/null
+++ b/cpukit/libnetworking/net/if_types.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 1989, 1993, 1994
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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_types.h 8.2 (Berkeley) 4/20/94
+ * $Id$
+ */
+
+#ifndef _NET_IF_TYPES_H_
+#define _NET_IF_TYPES_H_
+
+/*
+ * Interface types for benefit of parsing media address headers.
+ * This list is derived from the SNMP list of ifTypes, currently
+ * documented in RFC1573.
+ */
+
+#define IFT_OTHER 0x1 /* none of the following */
+#define IFT_1822 0x2 /* old-style arpanet imp */
+#define IFT_HDH1822 0x3 /* HDH arpanet imp */
+#define IFT_X25DDN 0x4 /* x25 to imp */
+#define IFT_X25 0x5 /* PDN X25 interface (RFC877) */
+#define IFT_ETHER 0x6 /* Ethernet CSMACD */
+#define IFT_ISO88023 0x7 /* CMSA CD */
+#define IFT_ISO88024 0x8 /* Token Bus */
+#define IFT_ISO88025 0x9 /* Token Ring */
+#define IFT_ISO88026 0xa /* MAN */
+#define IFT_STARLAN 0xb
+#define IFT_P10 0xc /* Proteon 10MBit ring */
+#define IFT_P80 0xd /* Proteon 80MBit ring */
+#define IFT_HY 0xe /* Hyperchannel */
+#define IFT_FDDI 0xf
+#define IFT_LAPB 0x10
+#define IFT_SDLC 0x11
+#define IFT_T1 0x12
+#define IFT_CEPT 0x13 /* E1 - european T1 */
+#define IFT_ISDNBASIC 0x14
+#define IFT_ISDNPRIMARY 0x15
+#define IFT_PTPSERIAL 0x16 /* Proprietary PTP serial */
+#define IFT_PPP 0x17 /* RFC 1331 */
+#define IFT_LOOP 0x18 /* loopback */
+#define IFT_EON 0x19 /* ISO over IP */
+#define IFT_XETHER 0x1a /* obsolete 3MB experimental ethernet */
+#define IFT_NSIP 0x1b /* XNS over IP */
+#define IFT_SLIP 0x1c /* IP over generic TTY */
+#define IFT_ULTRA 0x1d /* Ultra Technologies */
+#define IFT_DS3 0x1e /* Generic T3 */
+#define IFT_SIP 0x1f /* SMDS */
+#define IFT_FRELAY 0x20 /* Frame Relay DTE only */
+#define IFT_RS232 0x21
+#define IFT_PARA 0x22 /* parallel-port */
+#define IFT_ARCNET 0x23
+#define IFT_ARCNETPLUS 0x24
+#define IFT_ATM 0x25 /* ATM cells */
+#define IFT_MIOX25 0x26
+#define IFT_SONET 0x27 /* SONET or SDH */
+#define IFT_X25PLE 0x28
+#define IFT_ISO88022LLC 0x29
+#define IFT_LOCALTALK 0x2a
+#define IFT_SMDSDXI 0x2b
+#define IFT_FRELAYDCE 0x2c /* Frame Relay DCE */
+#define IFT_V35 0x2d
+#define IFT_HSSI 0x2e
+#define IFT_HIPPI 0x2f
+#define IFT_MODEM 0x30 /* Generic Modem */
+#define IFT_AAL5 0x31 /* AAL5 over ATM */
+#define IFT_SONETPATH 0x32
+#define IFT_SONETVT 0x33
+#define IFT_SMDSICIP 0x34 /* SMDS InterCarrier Interface */
+#define IFT_PROPVIRTUAL 0x35 /* Proprietary Virtual/internal */
+#define IFT_PROPMUX 0x36 /* Proprietary Multiplexing */
+
+#endif
diff --git a/cpukit/libnetworking/net/netisr.h b/cpukit/libnetworking/net/netisr.h
new file mode 100644
index 0000000000..c8fbbf861b
--- /dev/null
+++ b/cpukit/libnetworking/net/netisr.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 1980, 1986, 1989, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)netisr.h 8.1 (Berkeley) 6/10/93
+ * $Id$
+ */
+
+#ifndef _NET_NETISR_H_
+#define _NET_NETISR_H_
+
+/*
+ * The networking code runs off software interrupts.
+ *
+ * You can switch into the network by doing splnet() and return by splx().
+ * The software interrupt level for the network is higher than the software
+ * level for the clock (so you can enter the network in routines called
+ * at timeout time).
+ */
+#if defined(vax) || defined(tahoe)
+#define setsoftnet() mtpr(SIRR, 12)
+#endif
+
+/*
+ * Each ``pup-level-1'' input queue has a bit in a ``netisr'' status
+ * word which is used to de-multiplex a single software
+ * interrupt used for scheduling the network code to calls
+ * on the lowest level routine of each protocol.
+ */
+#define NETISR_RAW 0 /* same as AF_UNSPEC */
+#define NETISR_IP 2 /* same as AF_INET */
+#define NETISR_IMP 3 /* same as AF_IMPLINK */
+#define NETISR_NS 6 /* same as AF_NS */
+#define NETISR_ISO 7 /* same as AF_ISO */
+#define NETISR_CCITT 10 /* same as AF_CCITT */
+#define NETISR_ATALK 16 /* same as AF_APPLETALK */
+#define NETISR_ARP 18 /* same as AF_LINK */
+#define NETISR_IPX 23 /* same as AF_IPX */
+#define NETISR_ISDN 26 /* same as AF_E164 */
+#define NETISR_PPP 27 /* PPP soft interrupt */
+
+#define schednetisr(anisr) rtems_bsdnet_schednetisr(anisr)
+
+#ifndef LOCORE
+#ifdef _KERNEL
+extern volatile unsigned int netisr; /* scheduling bits for network */
+
+typedef void netisr_t(void);
+
+struct netisrtab {
+ int nit_num;
+ netisr_t *nit_isr;
+};
+
+#define NETISR_SET(num, isr)
+
+int register_netisr __P((int, netisr_t *));
+
+#endif
+#endif
+
+#endif
diff --git a/cpukit/libnetworking/net/ppp-comp.h b/cpukit/libnetworking/net/ppp-comp.h
new file mode 100644
index 0000000000..aa2f99b6d1
--- /dev/null
+++ b/cpukit/libnetworking/net/ppp-comp.h
@@ -0,0 +1,165 @@
+/*
+ * ppp-comp.h - Definitions for doing PPP packet compression.
+ *
+ * Copyright (c) 1994 The Australian National University.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, provided that the above copyright
+ * notice appears in all copies. This software is provided without any
+ * warranty, express or implied. The Australian National University
+ * makes no representations about the suitability of this software for
+ * any purpose.
+ *
+ * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+ * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
+ * OR MODIFICATIONS.
+ *
+ * $Id$
+ */
+
+#ifndef _NET_PPP_COMP_H
+#define _NET_PPP_COMP_H
+
+/*
+ * The following symbols control whether we include code for
+ * various compression methods.
+ */
+#ifndef DO_BSD_COMPRESS
+#define DO_BSD_COMPRESS 0 /* by default, include BSD-Compress */
+#endif
+#ifndef DO_DEFLATE
+#define DO_DEFLATE 0 /* by default, include Deflate */
+#endif
+#define DO_PREDICTOR_1 0
+#define DO_PREDICTOR_2 0
+
+/*
+ * Structure giving methods for compression/decompression.
+ */
+#ifdef PACKETPTR
+struct compressor {
+ int compress_proto; /* CCP compression protocol number */
+
+ /* Allocate space for a compressor (transmit side) */
+ void *(*comp_alloc) __P((u_char *options, int opt_len));
+ /* Free space used by a compressor */
+ void (*comp_free) __P((void *state));
+ /* Initialize a compressor */
+ int (*comp_init) __P((void *state, u_char *options, int opt_len,
+ int unit, int hdrlen, int debug));
+ /* Reset a compressor */
+ void (*comp_reset) __P((void *state));
+ /* Compress a packet */
+ int (*compress) __P((void *state, PACKETPTR *mret,
+ PACKETPTR mp, int orig_len, int max_len));
+ /* Return compression statistics */
+ void (*comp_stat) __P((void *state, struct compstat *stats));
+
+ /* Allocate space for a decompressor (receive side) */
+ void *(*decomp_alloc) __P((u_char *options, int opt_len));
+ /* Free space used by a decompressor */
+ void (*decomp_free) __P((void *state));
+ /* Initialize a decompressor */
+ int (*decomp_init) __P((void *state, u_char *options, int opt_len,
+ int unit, int hdrlen, int mru, int debug));
+ /* Reset a decompressor */
+ void (*decomp_reset) __P((void *state));
+ /* Decompress a packet. */
+ int (*decompress) __P((void *state, PACKETPTR mp,
+ PACKETPTR *dmpp));
+ /* Update state for an incompressible packet received */
+ void (*incomp) __P((void *state, PACKETPTR mp));
+ /* Return decompression statistics */
+ void (*decomp_stat) __P((void *state, struct compstat *stats));
+};
+#endif /* PACKETPTR */
+
+/*
+ * Return values for decompress routine.
+ * We need to make these distinctions so that we can disable certain
+ * useful functionality, namely sending a CCP reset-request as a result
+ * of an error detected after decompression. This is to avoid infringing
+ * a patent held by Motorola.
+ * Don't you just lurve software patents.
+ */
+#define DECOMP_OK 0 /* everything went OK */
+#define DECOMP_ERROR 1 /* error detected before decomp. */
+#define DECOMP_FATALERROR 2 /* error detected after decomp. */
+
+/*
+ * CCP codes.
+ */
+#define CCP_CONFREQ 1
+#define CCP_CONFACK 2
+#define CCP_TERMREQ 5
+#define CCP_TERMACK 6
+#define CCP_RESETREQ 14
+#define CCP_RESETACK 15
+
+/*
+ * Max # bytes for a CCP option
+ */
+#define CCP_MAX_OPTION_LENGTH 32
+
+/*
+ * Parts of a CCP packet.
+ */
+#define CCP_CODE(dp) ((dp)[0])
+#define CCP_ID(dp) ((dp)[1])
+#define CCP_LENGTH(dp) (((dp)[2] << 8) + (dp)[3])
+#define CCP_HDRLEN 4
+
+#define CCP_OPT_CODE(dp) ((dp)[0])
+#define CCP_OPT_LENGTH(dp) ((dp)[1])
+#define CCP_OPT_MINLEN 2
+
+/*
+ * Definitions for BSD-Compress.
+ */
+#define CI_BSD_COMPRESS 21 /* config. option for BSD-Compress */
+#define CILEN_BSD_COMPRESS 3 /* length of config. option */
+
+/* Macros for handling the 3rd byte of the BSD-Compress config option. */
+#define BSD_NBITS(x) ((x) & 0x1F) /* number of bits requested */
+#define BSD_VERSION(x) ((x) >> 5) /* version of option format */
+#define BSD_CURRENT_VERSION 1 /* current version number */
+#define BSD_MAKE_OPT(v, n) (((v) << 5) | (n))
+
+#define BSD_MIN_BITS 9 /* smallest code size supported */
+#define BSD_MAX_BITS 15 /* largest code size supported */
+
+/*
+ * Definitions for Deflate.
+ */
+#define CI_DEFLATE 26 /* config option for Deflate */
+#define CI_DEFLATE_DRAFT 24 /* value used in original draft RFC */
+#define CILEN_DEFLATE 4 /* length of its config option */
+
+#define DEFLATE_MIN_SIZE 8
+#define DEFLATE_MAX_SIZE 15
+#define DEFLATE_METHOD_VAL 8
+#define DEFLATE_SIZE(x) (((x) >> 4) + DEFLATE_MIN_SIZE)
+#define DEFLATE_METHOD(x) ((x) & 0x0F)
+#define DEFLATE_MAKE_OPT(w) ((((w) - DEFLATE_MIN_SIZE) << 4) \
+ + DEFLATE_METHOD_VAL)
+#define DEFLATE_CHK_SEQUENCE 0
+
+/*
+ * Definitions for other, as yet unsupported, compression methods.
+ */
+#define CI_PREDICTOR_1 1 /* config option for Predictor-1 */
+#define CILEN_PREDICTOR_1 2 /* length of its config option */
+#define CI_PREDICTOR_2 2 /* config option for Predictor-2 */
+#define CILEN_PREDICTOR_2 2 /* length of its config option */
+
+#endif /* _NET_PPP_COMP_H */
diff --git a/cpukit/libnetworking/net/ppp-deflate.c b/cpukit/libnetworking/net/ppp-deflate.c
new file mode 100644
index 0000000000..2023735b8b
--- /dev/null
+++ b/cpukit/libnetworking/net/ppp-deflate.c
@@ -0,0 +1,683 @@
+/* $Id$ */
+
+/*
+ * ppp_deflate.c - interface the zlib procedures for Deflate compression
+ * and decompression (as used by gzip) to the PPP code.
+ * This version is for use with mbufs on BSD-derived systems.
+ *
+ * Copyright (c) 1994 The Australian National University.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, provided that the above copyright
+ * notice appears in all copies. This software is provided without any
+ * warranty, express or implied. The Australian National University
+ * makes no representations about the suitability of this software for
+ * any purpose.
+ *
+ * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+ * THE AUSTRALIAN NATIONAL UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
+ * OR MODIFICATIONS.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <net/ppp_defs.h>
+#include <net/zlib.h>
+
+#define PACKETPTR struct mbuf *
+#include <net/ppp-comp.h>
+
+#if DO_DEFLATE
+
+#define DEFLATE_DEBUG 1
+
+/*
+ * State for a Deflate (de)compressor.
+ */
+struct deflate_state {
+ int seqno;
+ int w_size;
+ int unit;
+ int hdrlen;
+ int mru;
+ int debug;
+ z_stream strm;
+ struct compstat stats;
+};
+
+#define DEFLATE_OVHD 2 /* Deflate overhead/packet */
+
+static void *zalloc __P((void *, u_int items, u_int size));
+static void zfree __P((void *, void *ptr));
+static void *z_comp_alloc __P((u_char *options, int opt_len));
+static void *z_decomp_alloc __P((u_char *options, int opt_len));
+static void z_comp_free __P((void *state));
+static void z_decomp_free __P((void *state));
+static int z_comp_init __P((void *state, u_char *options, int opt_len,
+ int unit, int hdrlen, int debug));
+static int z_decomp_init __P((void *state, u_char *options, int opt_len,
+ int unit, int hdrlen, int mru, int debug));
+static int z_compress __P((void *state, struct mbuf **mret,
+ struct mbuf *mp, int slen, int maxolen));
+static void z_incomp __P((void *state, struct mbuf *dmsg));
+static int z_decompress __P((void *state, struct mbuf *cmp,
+ struct mbuf **dmpp));
+static void z_comp_reset __P((void *state));
+static void z_decomp_reset __P((void *state));
+static void z_comp_stats __P((void *state, struct compstat *stats));
+
+/*
+ * Procedures exported to if_ppp.c.
+ */
+struct compressor ppp_deflate = {
+ CI_DEFLATE, /* compress_proto */
+ z_comp_alloc, /* comp_alloc */
+ z_comp_free, /* comp_free */
+ z_comp_init, /* comp_init */
+ z_comp_reset, /* comp_reset */
+ z_compress, /* compress */
+ z_comp_stats, /* comp_stat */
+ z_decomp_alloc, /* decomp_alloc */
+ z_decomp_free, /* decomp_free */
+ z_decomp_init, /* decomp_init */
+ z_decomp_reset, /* decomp_reset */
+ z_decompress, /* decompress */
+ z_incomp, /* incomp */
+ z_comp_stats, /* decomp_stat */
+};
+
+struct compressor ppp_deflate = {
+ CI_DEFLATE_DRAFT, /* compress_proto */
+ z_comp_alloc, /* comp_alloc */
+ z_comp_free, /* comp_free */
+ z_comp_init, /* comp_init */
+ z_comp_reset, /* comp_reset */
+ z_compress, /* compress */
+ z_comp_stats, /* comp_stat */
+ z_decomp_alloc, /* decomp_alloc */
+ z_decomp_free, /* decomp_free */
+ z_decomp_init, /* decomp_init */
+ z_decomp_reset, /* decomp_reset */
+ z_decompress, /* decompress */
+ z_incomp, /* incomp */
+ z_comp_stats, /* decomp_stat */
+};
+
+/*
+ * Space allocation and freeing routines for use by zlib routines.
+ */
+void *
+zalloc(notused, items, size)
+ void *notused;
+ u_int items, size;
+{
+ void *ptr;
+
+ MALLOC(ptr, void *, items * size, M_DEVBUF, M_NOWAIT);
+ return ptr;
+}
+
+void
+zfree(notused, ptr)
+ void *notused;
+ void *ptr;
+{
+ FREE(ptr, M_DEVBUF);
+}
+
+/*
+ * Allocate space for a compressor.
+ */
+static void *
+z_comp_alloc(options, opt_len)
+ u_char *options;
+ int opt_len;
+{
+ struct deflate_state *state;
+ int w_size;
+
+ if (opt_len != CILEN_DEFLATE
+ || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
+ || options[1] != CILEN_DEFLATE
+ || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
+ || options[3] != DEFLATE_CHK_SEQUENCE)
+ return NULL;
+ w_size = DEFLATE_SIZE(options[2]);
+ if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
+ return NULL;
+
+ MALLOC(state, struct deflate_state *, sizeof(struct deflate_state),
+ M_DEVBUF, M_NOWAIT);
+ if (state == NULL)
+ return NULL;
+
+ state->strm.next_in = NULL;
+ state->strm.zalloc = zalloc;
+ state->strm.zfree = zfree;
+ if (deflateInit2(&state->strm, Z_DEFAULT_COMPRESSION, DEFLATE_METHOD_VAL,
+ -w_size, 8, Z_DEFAULT_STRATEGY) != Z_OK) {
+ FREE(state, M_DEVBUF);
+ return NULL;
+ }
+
+ state->w_size = w_size;
+ bzero(&state->stats, sizeof(state->stats));
+ return (void *) state;
+}
+
+static void
+z_comp_free(arg)
+ void *arg;
+{
+ struct deflate_state *state = (struct deflate_state *) arg;
+
+ deflateEnd(&state->strm);
+ FREE(state, M_DEVBUF);
+}
+
+static int
+z_comp_init(arg, options, opt_len, unit, hdrlen, debug)
+ void *arg;
+ u_char *options;
+ int opt_len, unit, hdrlen, debug;
+{
+ struct deflate_state *state = (struct deflate_state *) arg;
+
+ if (opt_len < CILEN_DEFLATE
+ || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
+ || options[1] != CILEN_DEFLATE
+ || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
+ || DEFLATE_SIZE(options[2]) != state->w_size
+ || options[3] != DEFLATE_CHK_SEQUENCE)
+ return 0;
+
+ state->seqno = 0;
+ state->unit = unit;
+ state->hdrlen = hdrlen;
+ state->debug = debug;
+
+ deflateReset(&state->strm);
+
+ return 1;
+}
+
+static void
+z_comp_reset(arg)
+ void *arg;
+{
+ struct deflate_state *state = (struct deflate_state *) arg;
+
+ state->seqno = 0;
+ deflateReset(&state->strm);
+}
+
+int
+z_compress(arg, mret, mp, orig_len, maxolen)
+ void *arg;
+ struct mbuf **mret; /* compressed packet (out) */
+ struct mbuf *mp; /* uncompressed packet (in) */
+ int orig_len, maxolen;
+{
+ struct deflate_state *state = (struct deflate_state *) arg;
+ u_char *rptr, *wptr;
+ int proto, olen, wspace, r, flush;
+ struct mbuf *m;
+
+ /*
+ * Check that the protocol is in the range we handle.
+ */
+ rptr = mtod(mp, u_char *);
+ proto = PPP_PROTOCOL(rptr);
+ if (proto > 0x3fff || proto == 0xfd || proto == 0xfb) {
+ *mret = NULL;
+ return orig_len;
+ }
+
+ /* Allocate one mbuf initially. */
+ if (maxolen > orig_len)
+ maxolen = orig_len;
+ MGET(m, M_DONTWAIT, MT_DATA);
+ *mret = m;
+ if (m != NULL) {
+ m->m_len = 0;
+ if (maxolen + state->hdrlen > MLEN)
+ MCLGET(m, M_DONTWAIT);
+ wspace = M_TRAILINGSPACE(m);
+ if (state->hdrlen + PPP_HDRLEN + 2 < wspace) {
+ m->m_data += state->hdrlen;
+ wspace -= state->hdrlen;
+ }
+ wptr = mtod(m, u_char *);
+
+ /*
+ * Copy over the PPP header and store the 2-byte sequence number.
+ */
+ wptr[0] = PPP_ADDRESS(rptr);
+ wptr[1] = PPP_CONTROL(rptr);
+ wptr[2] = PPP_COMP >> 8;
+ wptr[3] = PPP_COMP;
+ wptr += PPP_HDRLEN;
+ wptr[0] = state->seqno >> 8;
+ wptr[1] = state->seqno;
+ wptr += 2;
+ state->strm.next_out = wptr;
+ state->strm.avail_out = wspace - (PPP_HDRLEN + 2);
+ } else {
+ state->strm.next_out = NULL;
+ state->strm.avail_out = 1000000;
+ wptr = NULL;
+ wspace = 0;
+ }
+ ++state->seqno;
+
+ rptr += (proto > 0xff)? 2: 3; /* skip 1st proto byte if 0 */
+ state->strm.next_in = rptr;
+ state->strm.avail_in = mtod(mp, u_char *) + mp->m_len - rptr;
+ mp = mp->m_next;
+ flush = (mp == NULL)? Z_PACKET_FLUSH: Z_NO_FLUSH;
+ olen = 0;
+ for (;;) {
+ r = deflate(&state->strm, flush);
+ if (r != Z_OK) {
+ printf("z_compress: deflate returned %d (%s)\n",
+ r, (state->strm.msg? state->strm.msg: ""));
+ break;
+ }
+ if (flush != Z_NO_FLUSH && state->strm.avail_out != 0)
+ break; /* all done */
+ if (state->strm.avail_in == 0 && mp != NULL) {
+ state->strm.next_in = mtod(mp, u_char *);
+ state->strm.avail_in = mp->m_len;
+ mp = mp->m_next;
+ if (mp == NULL)
+ flush = Z_PACKET_FLUSH;
+ }
+ if (state->strm.avail_out == 0) {
+ if (m != NULL) {
+ m->m_len = wspace;
+ olen += wspace;
+ MGET(m->m_next, M_DONTWAIT, MT_DATA);
+ m = m->m_next;
+ if (m != NULL) {
+ m->m_len = 0;
+ if (maxolen - olen > MLEN)
+ MCLGET(m, M_DONTWAIT);
+ state->strm.next_out = mtod(m, u_char *);
+ state->strm.avail_out = wspace = M_TRAILINGSPACE(m);
+ }
+ }
+ if (m == NULL) {
+ state->strm.next_out = NULL;
+ state->strm.avail_out = 1000000;
+ }
+ }
+ }
+ if (m != NULL)
+ olen += (m->m_len = wspace - state->strm.avail_out);
+
+ /*
+ * See if we managed to reduce the size of the packet.
+ * If the compressor just gave us a single zero byte, it means
+ * the packet was incompressible.
+ */
+ if (m != NULL && olen < orig_len
+ && !(olen == PPP_HDRLEN + 3 && *wptr == 0)) {
+ state->stats.comp_bytes += olen;
+ state->stats.comp_packets++;
+ } else {
+ if (*mret != NULL) {
+ m_freem(*mret);
+ *mret = NULL;
+ }
+ state->stats.inc_bytes += orig_len;
+ state->stats.inc_packets++;
+ olen = orig_len;
+ }
+ state->stats.unc_bytes += orig_len;
+ state->stats.unc_packets++;
+
+ return olen;
+}
+
+static void
+z_comp_stats(arg, stats)
+ void *arg;
+ struct compstat *stats;
+{
+ struct deflate_state *state = (struct deflate_state *) arg;
+ u_int out;
+
+ *stats = state->stats;
+ stats->ratio = stats->unc_bytes;
+ out = stats->comp_bytes + stats->inc_bytes;
+ if (stats->ratio <= 0x7ffffff)
+ stats->ratio <<= 8;
+ else
+ out >>= 8;
+ if (out != 0)
+ stats->ratio /= out;
+}
+
+/*
+ * Allocate space for a decompressor.
+ */
+static void *
+z_decomp_alloc(options, opt_len)
+ u_char *options;
+ int opt_len;
+{
+ struct deflate_state *state;
+ int w_size;
+
+ if (opt_len != CILEN_DEFLATE
+ || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
+ || options[1] != CILEN_DEFLATE
+ || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
+ || options[3] != DEFLATE_CHK_SEQUENCE)
+ return NULL;
+ w_size = DEFLATE_SIZE(options[2]);
+ if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
+ return NULL;
+
+ MALLOC(state, struct deflate_state *, sizeof(struct deflate_state),
+ M_DEVBUF, M_NOWAIT);
+ if (state == NULL)
+ return NULL;
+
+ state->strm.next_out = NULL;
+ state->strm.zalloc = zalloc;
+ state->strm.zfree = zfree;
+ if (inflateInit2(&state->strm, -w_size) != Z_OK) {
+ FREE(state, M_DEVBUF);
+ return NULL;
+ }
+
+ state->w_size = w_size;
+ bzero(&state->stats, sizeof(state->stats));
+ return (void *) state;
+}
+
+static void
+z_decomp_free(arg)
+ void *arg;
+{
+ struct deflate_state *state = (struct deflate_state *) arg;
+
+ inflateEnd(&state->strm);
+ FREE(state, M_DEVBUF);
+}
+
+static int
+z_decomp_init(arg, options, opt_len, unit, hdrlen, mru, debug)
+ void *arg;
+ u_char *options;
+ int opt_len, unit, hdrlen, mru, debug;
+{
+ struct deflate_state *state = (struct deflate_state *) arg;
+
+ if (opt_len < CILEN_DEFLATE
+ || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
+ || options[1] != CILEN_DEFLATE
+ || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
+ || DEFLATE_SIZE(options[2]) != state->w_size
+ || options[3] != DEFLATE_CHK_SEQUENCE)
+ return 0;
+
+ state->seqno = 0;
+ state->unit = unit;
+ state->hdrlen = hdrlen;
+ state->debug = debug;
+ state->mru = mru;
+
+ inflateReset(&state->strm);
+
+ return 1;
+}
+
+static void
+z_decomp_reset(arg)
+ void *arg;
+{
+ struct deflate_state *state = (struct deflate_state *) arg;
+
+ state->seqno = 0;
+ inflateReset(&state->strm);
+}
+
+/*
+ * Decompress a Deflate-compressed packet.
+ *
+ * Because of patent problems, we return DECOMP_ERROR for errors
+ * found by inspecting the input data and for system problems, but
+ * DECOMP_FATALERROR for any errors which could possibly be said to
+ * be being detected "after" decompression. For DECOMP_ERROR,
+ * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
+ * infringing a patent of Motorola's if we do, so we take CCP down
+ * instead.
+ *
+ * Given that the frame has the correct sequence number and a good FCS,
+ * errors such as invalid codes in the input most likely indicate a
+ * bug, so we return DECOMP_FATALERROR for them in order to turn off
+ * compression, even though they are detected by inspecting the input.
+ */
+int
+z_decompress(arg, mi, mop)
+ void *arg;
+ struct mbuf *mi, **mop;
+{
+ struct deflate_state *state = (struct deflate_state *) arg;
+ struct mbuf *mo, *mo_head;
+ u_char *rptr, *wptr;
+ int rlen, olen, ospace;
+ int seq, i, flush, r, decode_proto;
+ u_char hdr[PPP_HDRLEN + DEFLATE_OVHD];
+
+ *mop = NULL;
+ rptr = mtod(mi, u_char *);
+ rlen = mi->m_len;
+ for (i = 0; i < PPP_HDRLEN + DEFLATE_OVHD; ++i) {
+ while (rlen <= 0) {
+ mi = mi->m_next;
+ if (mi == NULL)
+ return DECOMP_ERROR;
+ rptr = mtod(mi, u_char *);
+ rlen = mi->m_len;
+ }
+ hdr[i] = *rptr++;
+ --rlen;
+ }
+
+ /* Check the sequence number. */
+ seq = (hdr[PPP_HDRLEN] << 8) + hdr[PPP_HDRLEN+1];
+ if (seq != state->seqno) {
+ if (state->debug)
+ printf("z_decompress%d: bad seq # %d, expected %d\n",
+ state->unit, seq, state->seqno);
+ return DECOMP_ERROR;
+ }
+ ++state->seqno;
+
+ /* Allocate an output mbuf. */
+ MGETHDR(mo, M_DONTWAIT, MT_DATA);
+ if (mo == NULL)
+ return DECOMP_ERROR;
+ mo_head = mo;
+ mo->m_len = 0;
+ mo->m_next = NULL;
+ MCLGET(mo, M_DONTWAIT);
+ ospace = M_TRAILINGSPACE(mo);
+ if (state->hdrlen + PPP_HDRLEN < ospace) {
+ mo->m_data += state->hdrlen;
+ ospace -= state->hdrlen;
+ }
+
+ /*
+ * Fill in the first part of the PPP header. The protocol field
+ * comes from the decompressed data.
+ */
+ wptr = mtod(mo, u_char *);
+ wptr[0] = PPP_ADDRESS(hdr);
+ wptr[1] = PPP_CONTROL(hdr);
+ wptr[2] = 0;
+
+ /*
+ * Set up to call inflate. We set avail_out to 1 initially so we can
+ * look at the first byte of the output and decide whether we have
+ * a 1-byte or 2-byte protocol field.
+ */
+ state->strm.next_in = rptr;
+ state->strm.avail_in = rlen;
+ mi = mi->m_next;
+ flush = (mi == NULL)? Z_PACKET_FLUSH: Z_NO_FLUSH;
+ rlen += PPP_HDRLEN + DEFLATE_OVHD;
+ state->strm.next_out = wptr + 3;
+ state->strm.avail_out = 1;
+ decode_proto = 1;
+ olen = PPP_HDRLEN;
+
+ /*
+ * Call inflate, supplying more input or output as needed.
+ */
+ for (;;) {
+ r = inflate(&state->strm, flush);
+ if (r != Z_OK) {
+#if !DEFLATE_DEBUG
+ if (state->debug)
+#endif
+ printf("z_decompress%d: inflate returned %d (%s)\n",
+ state->unit, r, (state->strm.msg? state->strm.msg: ""));
+ m_freem(mo_head);
+ return DECOMP_FATALERROR;
+ }
+ if (flush != Z_NO_FLUSH && state->strm.avail_out != 0)
+ break; /* all done */
+ if (state->strm.avail_in == 0 && mi != NULL) {
+ state->strm.next_in = mtod(mi, u_char *);
+ state->strm.avail_in = mi->m_len;
+ rlen += mi->m_len;
+ mi = mi->m_next;
+ if (mi == NULL)
+ flush = Z_PACKET_FLUSH;
+ }
+ if (state->strm.avail_out == 0) {
+ if (decode_proto) {
+ state->strm.avail_out = ospace - PPP_HDRLEN;
+ if ((wptr[3] & 1) == 0) {
+ /* 2-byte protocol field */
+ wptr[2] = wptr[3];
+ --state->strm.next_out;
+ ++state->strm.avail_out;
+ --olen;
+ }
+ decode_proto = 0;
+ } else {
+ mo->m_len = ospace;
+ olen += ospace;
+ MGET(mo->m_next, M_DONTWAIT, MT_DATA);
+ mo = mo->m_next;
+ if (mo == NULL) {
+ m_freem(mo_head);
+ return DECOMP_ERROR;
+ }
+ MCLGET(mo, M_DONTWAIT);
+ state->strm.next_out = mtod(mo, u_char *);
+ state->strm.avail_out = ospace = M_TRAILINGSPACE(mo);
+ }
+ }
+ }
+ if (decode_proto) {
+ m_freem(mo_head);
+ return DECOMP_ERROR;
+ }
+ olen += (mo->m_len = ospace - state->strm.avail_out);
+#if DEFLATE_DEBUG
+ if (olen > state->mru + PPP_HDRLEN)
+ printf("ppp_deflate%d: exceeded mru (%d > %d)\n",
+ state->unit, olen, state->mru + PPP_HDRLEN);
+#endif
+
+ state->stats.unc_bytes += olen;
+ state->stats.unc_packets++;
+ state->stats.comp_bytes += rlen;
+ state->stats.comp_packets++;
+
+ *mop = mo_head;
+ return DECOMP_OK;
+}
+
+/*
+ * Incompressible data has arrived - add it to the history.
+ */
+static void
+z_incomp(arg, mi)
+ void *arg;
+ struct mbuf *mi;
+{
+ struct deflate_state *state = (struct deflate_state *) arg;
+ u_char *rptr;
+ int rlen, proto, r;
+
+ /*
+ * Check that the protocol is one we handle.
+ */
+ rptr = mtod(mi, u_char *);
+ proto = PPP_PROTOCOL(rptr);
+ if (proto > 0x3fff || proto == 0xfd || proto == 0xfb)
+ return;
+
+ ++state->seqno;
+
+ /*
+ * Iterate through the mbufs, adding the characters in them
+ * to the decompressor's history. For the first mbuf, we start
+ * at the either the 1st or 2nd byte of the protocol field,
+ * depending on whether the protocol value is compressible.
+ */
+ rlen = mi->m_len;
+ state->strm.next_in = rptr + 3;
+ state->strm.avail_in = rlen - 3;
+ if (proto > 0xff) {
+ --state->strm.next_in;
+ ++state->strm.avail_in;
+ }
+ for (;;) {
+ r = inflateIncomp(&state->strm);
+ if (r != Z_OK) {
+ /* gak! */
+#if !DEFLATE_DEBUG
+ if (state->debug)
+#endif
+ printf("z_incomp%d: inflateIncomp returned %d (%s)\n",
+ state->unit, r, (state->strm.msg? state->strm.msg: ""));
+ return;
+ }
+ mi = mi->m_next;
+ if (mi == NULL)
+ break;
+ state->strm.next_in = mtod(mi, u_char *);
+ state->strm.avail_in = mi->m_len;
+ rlen += mi->m_len;
+ }
+
+ /*
+ * Update stats.
+ */
+ state->stats.inc_bytes += rlen;
+ state->stats.inc_packets++;
+ state->stats.unc_bytes += rlen;
+ state->stats.unc_packets++;
+}
+
+#endif /* DO_DEFLATE */
diff --git a/cpukit/libnetworking/net/ppp.h b/cpukit/libnetworking/net/ppp.h
new file mode 100644
index 0000000000..d318f6a5f9
--- /dev/null
+++ b/cpukit/libnetworking/net/ppp.h
@@ -0,0 +1,11 @@
+
+#ifndef _PPP_H_
+#define _PPP_H_
+
+#define NPPP 1
+#define NBPFILTER 0
+#undef VJC
+#undef PPP_FILTER
+#undef PPP_COMPRESS
+
+#endif
diff --git a/cpukit/libnetworking/net/ppp_defs.h b/cpukit/libnetworking/net/ppp_defs.h
new file mode 100644
index 0000000000..c8367c1998
--- /dev/null
+++ b/cpukit/libnetworking/net/ppp_defs.h
@@ -0,0 +1,184 @@
+/* $Id$ */
+
+/*
+ * ppp_defs.h - PPP definitions.
+ *
+ * Copyright (c) 1994 The Australian National University.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, provided that the above copyright
+ * notice appears in all copies. This software is provided without any
+ * warranty, express or implied. The Australian National University
+ * makes no representations about the suitability of this software for
+ * any purpose.
+ *
+ * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+ * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
+ * OR MODIFICATIONS.
+ */
+
+#ifndef _PPP_DEFS_H_
+#define _PPP_DEFS_H_
+
+/*
+ * The basic PPP frame.
+ */
+#define PPP_HDRLEN 4 /* octets for standard ppp header */
+#define PPP_FCSLEN 2 /* octets for FCS */
+
+/*
+ * Packet sizes
+ *
+ * Note - lcp shouldn't be allowed to negotiate stuff outside these
+ * limits. See lcp.h in the pppd directory.
+ * (XXX - these constants should simply be shared by lcp.c instead
+ * of living in lcp.h)
+ */
+#define PPP_MTU 1500 /* Default MTU (size of Info field) */
+#define PPP_MAXMTU 65535 - (PPP_HDRLEN + PPP_FCSLEN)
+#define PPP_MINMTU 64
+#define PPP_MRU 1500 /* default MRU = max length of info field */
+#define PPP_MAXMRU 65000 /* Largest MRU we allow */
+#define PPP_MINMRU 128
+
+#define PPP_ADDRESS(p) (((u_char *)(p))[0])
+#define PPP_CONTROL(p) (((u_char *)(p))[1])
+#define PPP_PROTOCOL(p) ((((u_char *)(p))[2] << 8) + ((u_char *)(p))[3])
+
+/*
+ * Significant octet values.
+ */
+#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */
+#define PPP_UI 0x03 /* Unnumbered Information */
+#define PPP_FLAG 0x7e /* Flag Sequence */
+#define PPP_ESCAPE 0x7d /* Asynchronous Control Escape */
+#define PPP_TRANS 0x20 /* Asynchronous transparency modifier */
+
+/*
+ * Protocol field values.
+ */
+#define PPP_IP 0x21 /* Internet Protocol */
+#define PPP_AT 0x29 /* AppleTalk Protocol */
+#define PPP_IPX 0x2b /* IPX protocol */
+#define PPP_VJC_COMP 0x2d /* VJ compressed TCP */
+#define PPP_VJC_UNCOMP 0x2f /* VJ uncompressed TCP */
+#define PPP_IPV6 0x57 /* Internet Protocol Version 6 */
+#define PPP_COMP 0xfd /* compressed packet */
+#define PPP_IPCP 0x8021 /* IP Control Protocol */
+#define PPP_ATCP 0x8029 /* AppleTalk Control Protocol */
+#define PPP_IPXCP 0x802b /* IPX Control Protocol */
+#define PPP_IPV6CP 0x8057 /* IPv6 Control Protocol */
+#define PPP_CCP 0x80fd /* Compression Control Protocol */
+#define PPP_LCP 0xc021 /* Link Control Protocol */
+#define PPP_PAP 0xc023 /* Password Authentication Protocol */
+#define PPP_LQR 0xc025 /* Link Quality Report protocol */
+#define PPP_CHAP 0xc223 /* Cryptographic Handshake Auth. Protocol */
+#define PPP_CBCP 0xc029 /* Callback Control Protocol */
+
+/*
+ * Values for FCS calculations.
+ */
+#define PPP_INITFCS 0xffff /* Initial FCS value */
+#define PPP_GOODFCS 0xf0b8 /* Good final FCS value */
+#define PPP_FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
+
+/*
+ * A 32-bit unsigned integral type.
+ */
+
+#if !defined(__BIT_TYPES_DEFINED__) && !defined(_BITYPES) \
+ && !defined(__FreeBSD__) && (NS_TARGET < 40)
+#ifdef UINT32_T
+typedef UINT32_T u_int32_t;
+#else
+/*typedef unsigned int u_int32_t;*/
+/*typedef unsigned short u_int16_t;*/
+#endif
+#endif
+
+/*
+ * Extended asyncmap - allows any character to be escaped.
+ */
+typedef u_int32_t ext_accm[8];
+
+/*
+ * What to do with network protocol (NP) packets.
+ */
+enum NPmode {
+ NPMODE_PASS, /* pass the packet through */
+ NPMODE_DROP, /* silently drop the packet */
+ NPMODE_ERROR, /* return an error */
+ NPMODE_QUEUE /* save it up for later. */
+};
+
+/*
+ * Statistics.
+ */
+struct pppstat {
+ unsigned int ppp_ibytes; /* bytes received */
+ unsigned int ppp_ipackets; /* packets received */
+ unsigned int ppp_ierrors; /* receive errors */
+ unsigned int ppp_obytes; /* bytes sent */
+ unsigned int ppp_opackets; /* packets sent */
+ unsigned int ppp_oerrors; /* transmit errors */
+};
+
+struct vjstat {
+ unsigned int vjs_packets; /* outbound packets */
+ unsigned int vjs_compressed; /* outbound compressed packets */
+ unsigned int vjs_searches; /* searches for connection state */
+ unsigned int vjs_misses; /* times couldn't find conn. state */
+ unsigned int vjs_uncompressedin; /* inbound uncompressed packets */
+ unsigned int vjs_compressedin; /* inbound compressed packets */
+ unsigned int vjs_errorin; /* inbound unknown type packets */
+ unsigned int vjs_tossed; /* inbound packets tossed because of error */
+};
+
+struct ppp_stats {
+ struct pppstat p; /* basic PPP statistics */
+ struct vjstat vj; /* VJ header compression statistics */
+};
+
+struct compstat {
+ unsigned int unc_bytes; /* total uncompressed bytes */
+ unsigned int unc_packets; /* total uncompressed packets */
+ unsigned int comp_bytes; /* compressed bytes */
+ unsigned int comp_packets; /* compressed packets */
+ unsigned int inc_bytes; /* incompressible bytes */
+ unsigned int inc_packets; /* incompressible packets */
+ unsigned int ratio; /* recent compression ratio << 8 */
+};
+
+struct ppp_comp_stats {
+ struct compstat c; /* packet compression statistics */
+ struct compstat d; /* packet decompression statistics */
+};
+
+/*
+ * The following structure records the time in seconds since
+ * the last NP packet was sent or received.
+ */
+struct ppp_idle {
+ time_t xmit_idle; /* time since last NP packet sent */
+ time_t recv_idle; /* time since last NP packet received */
+};
+
+#ifndef __P
+#ifdef __STDC__
+#define __P(x) x
+#else
+#define __P(x) ()
+#endif
+#endif
+
+#endif /* _PPP_DEFS_H_ */
diff --git a/cpukit/libnetworking/net/ppp_tty.c b/cpukit/libnetworking/net/ppp_tty.c
new file mode 100644
index 0000000000..45e21362b3
--- /dev/null
+++ b/cpukit/libnetworking/net/ppp_tty.c
@@ -0,0 +1,954 @@
+/*
+ * ppp_tty.c - Point-to-Point Protocol (PPP) driver for asynchronous
+ * tty devices.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Drew D. Perkins
+ * Carnegie Mellon University
+ * 4910 Forbes Ave.
+ * Pittsburgh, PA 15213
+ * (412) 268-8576
+ * ddp@andrew.cmu.edu
+ *
+ * Based on:
+ * @(#)if_sl.c 7.6.1.2 (Berkeley) 2/15/89
+ *
+ * Copyright (c) 1987 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Serial Line interface
+ *
+ * Rick Adams
+ * Center for Seismic Studies
+ * 1300 N 17th Street, Suite 1450
+ * Arlington, Virginia 22209
+ * (703)276-7900
+ * rick@seismo.ARPA
+ * seismo!rick
+ *
+ * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris).
+ * Converted to 4.3BSD Beta by Chris Torek.
+ * Other changes made at Berkeley, based in part on code by Kirk Smith.
+ *
+ * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com)
+ * Added VJ tcp header compression; more unified ioctls
+ *
+ * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au).
+ * Cleaned up a lot of the mbuf-related code to fix bugs that
+ * caused system crashes and packet corruption. Changed pppstart
+ * so that it doesn't just give up with a "collision" if the whole
+ * packet doesn't fit in the output ring buffer.
+ *
+ * Added priority queueing for interactive IP packets, following
+ * the model of if_sl.c, plus hooks for bpf.
+ * Paul Mackerras (paulus@cs.anu.edu.au).
+ */
+
+/* $Id$ */
+/* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
+/* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */
+
+#include "ppp.h"
+#if NPPP > 0
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/file.h>
+#include <sys/kernel.h>
+
+#include <net/if.h>
+#include <net/if_types.h>
+
+#ifdef VJC
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <net/pppcompress.h>
+#endif
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <sys/ttycom.h>
+#include <termios.h>
+#include <rtems/termiostypes.h>
+
+#ifdef PPP_FILTER
+#include <net/bpf.h>
+#endif
+#include <net/ppp_defs.h>
+#include <net/if_ppp.h>
+#include <net/if_pppvar.h>
+
+
+void pppasyncattach __P((void));
+int pppopen __P((struct rtems_termios_tty *tty));
+int pppclose __P((struct rtems_termios_tty *tty));
+int pppread __P((struct rtems_termios_tty *tty, rtems_libio_rw_args_t *rw_args));
+int pppwrite __P((struct rtems_termios_tty *tty, rtems_libio_rw_args_t *rw_args));
+int ppptioctl __P((struct rtems_termios_tty *tty, rtems_libio_ioctl_args_t *args));
+int pppinput __P((int c, struct rtems_termios_tty *tty));
+int pppstart __P((struct rtems_termios_tty *tp));
+u_short pppfcs __P((u_short fcs, u_char *cp, int len));
+void pppallocmbuf __P((struct ppp_softc *sc, struct mbuf **mp));
+
+static void pppasyncstart __P((struct ppp_softc *));
+static void pppasyncctlp __P((struct ppp_softc *));
+static void pppasyncrelinq __P((struct ppp_softc *));
+/*static void ppp_timeout __P((void *)); */
+/*static void pppdumpb __P((u_char *b, int l)); */
+/*static void ppplogchar __P((struct ppp_softc *, int)); */
+
+/*
+ * Some useful mbuf macros not in mbuf.h.
+ */
+#define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT)
+
+#define M_DATASTART(m) \
+ (M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \
+ (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
+
+#define M_DATASIZE(m) \
+ (M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \
+ (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
+
+/*
+ * We steal two bits in the mbuf m_flags, to mark high-priority packets
+ * for output, and received packets following lost/corrupted packets.
+ */
+#define M_HIGHPRI 0x2000 /* output packet for sc_fastq */
+#define M_ERRMARK 0x4000 /* steal a bit in mbuf m_flags */
+
+/*
+ * Does c need to be escaped?
+ */
+#define ESCAPE_P(c) (sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
+
+/*
+ * Procedures for using an async tty interface for PPP.
+ */
+
+/* This is a FreeBSD-2.0 kernel. */
+#define CCOUNT(rb) (((rb).Size+(rb).Head-(rb).Tail) % (rb).Size)
+#define FCOUNT(rb) ((rb).Size-CCOUNT(rb)-1)
+#define PPP_LOWAT 100 /* Process more output when < LOWAT on queue */
+#define PPP_HIWAT 400 /* Don't start a new packet if HIWAT on que */
+
+/*
+ * Define the PPP line discipline.
+ */
+
+static struct linesw pppdisc = {
+ pppopen, pppclose, pppread, pppwrite,
+ pppinput, pppstart, ppptioctl, NULL
+};
+
+void
+pppasyncattach()
+{
+ linesw[PPPDISC] = pppdisc;
+}
+
+TEXT_SET(pseudo_set, pppasyncattach);
+
+/*
+ * Line specific open routine for async tty devices.
+ * Attach the given tty to the first available ppp unit.
+ * Called from device open routine or ttioctl.
+ */
+/* ARGSUSED */
+int
+pppopen(struct rtems_termios_tty *tty)
+{
+ int i;
+ register struct ppp_softc *sc;
+ struct mbuf *m = (struct mbuf *)0;
+ extern int termios_baud_to_number(int);
+
+ if (tty->t_line == PPPDISC) {
+ sc = (struct ppp_softc *)tty->t_sc;
+ if (sc != NULL && sc->sc_devp == (void *)tty) {
+ return (0);
+ }
+ }
+
+ if ((sc = pppalloc(1)) == NULL) {
+ return ENXIO;
+ }
+
+ if (sc->sc_relinq)
+ (*sc->sc_relinq)(sc); /* get previous owner to relinquish the unit */
+
+ sc->sc_ilen = 0;
+ sc->sc_m = NULL;
+ bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
+ sc->sc_asyncmap[0] = 0xffffffff;
+ sc->sc_asyncmap[3] = 0x60000000;
+ sc->sc_rasyncmap = 0;
+ sc->sc_devp = tty;
+ sc->sc_start = pppasyncstart;
+ sc->sc_ctlp = pppasyncctlp;
+ sc->sc_relinq = pppasyncrelinq;
+ sc->sc_outm = NULL;
+ sc->sc_outmc = NULL;
+
+ /* preallocate mbufs for free queue */
+ rtems_bsdnet_semaphore_obtain();
+ for (i=0; i<NUM_MBUFQ; i++) {
+ pppallocmbuf(sc, &m);
+ if ( i == 0 ) {
+ /* use first mbuf for rx iterrupt handling */
+ sc->sc_m = m;
+ }
+ else {
+ /* enqueue mbuf for later use */
+ IF_ENQUEUE(&sc->sc_freeq, m);
+ }
+ m = (struct mbuf *)0;
+ }
+ rtems_bsdnet_semaphore_release();
+
+ /* initialize values */
+ sc->sc_if.if_flags |= IFF_RUNNING;
+ sc->sc_if.if_baudrate =
+ termios_baud_to_number(tty->termios.c_cflag & CBAUD);
+
+ tty->t_sc = (void *)sc;
+
+ return ( RTEMS_SUCCESSFUL );
+}
+
+/*
+ * Line specific close routine, called from device close routine
+ * and from ttioctl.
+ * Detach the tty from the ppp unit.
+ * Mimics part of ttyclose().
+ */
+int
+pppclose(struct rtems_termios_tty *tty)
+{
+ register struct ppp_softc *sc;
+
+ tty->t_line = 0;
+ sc = (struct ppp_softc *)tty->t_sc;
+ if (sc != NULL) {
+ tty->t_sc = NULL;
+ if (tty == (struct rtems_termios_tty *)sc->sc_devp) {
+ rtems_bsdnet_semaphore_obtain();
+ pppasyncrelinq(sc);
+ pppdealloc(sc);
+ rtems_bsdnet_semaphore_release();
+ }
+ }
+ return ( RTEMS_SUCCESSFUL );
+}
+
+/*
+ * Relinquish the interface unit to another device.
+ */
+static void
+pppasyncrelinq(sc)
+ struct ppp_softc *sc;
+{
+#ifdef XXX_XXX
+ if (sc->sc_outm) {
+ m_freem(sc->sc_outm);
+ sc->sc_outm = NULL;
+ }
+ if (sc->sc_m) {
+ m_freem(sc->sc_m);
+ sc->sc_m = NULL;
+ }
+ if (sc->sc_flags & SC_TIMEOUT) {
+ untimeout(ppp_timeout, (void *) sc);
+ sc->sc_flags &= ~SC_TIMEOUT;
+ }
+#endif
+}
+
+/*
+ * Line specific (tty) read routine.
+ */
+int
+pppread(struct rtems_termios_tty *tty, rtems_libio_rw_args_t *rw_args)
+{
+ rtems_status_code status = RTEMS_UNSATISFIED;
+ int count = 0;
+ int maximum = rw_args->count;
+ char *buffer = rw_args->buffer;
+ register struct ppp_softc *sc = (struct ppp_softc *)tty->t_sc;
+ struct mbuf *m;
+ struct mbuf *m0;
+ u_char *p;
+
+ if (sc == NULL) {
+ return 0;
+ }
+
+ /*
+ * Loop waiting for input, checking that nothing disasterous
+ * happens in the meantime.
+ */
+ if (tty != (struct rtems_termios_tty *)sc->sc_devp || tty->t_line != PPPDISC) {
+ return ( status );
+ }
+ if (sc->sc_inq.ifq_head == NULL) {
+ return ( status );
+ }
+
+ /* Get the packet from the input queue */
+ rtems_bsdnet_semaphore_obtain();
+ IF_DEQUEUE(&sc->sc_inq, m0);
+
+ /* loop over mbuf chain */
+ m = m0;
+ while (( m != NULL ) && ( m->m_len > 0 ) && ( count+m->m_len < maximum )) {
+ /* copy data into buffer */
+ p = mtod(m, u_char *);
+ memcpy(buffer, p, m->m_len);
+ memset(p, 0, m->m_len);
+ count += m->m_len;
+ buffer += m->m_len;
+
+ /* increment loop index */
+ m = m->m_next;
+ }
+
+ /* free mbuf chain */
+ m_freem(m0);
+ rtems_bsdnet_semaphore_release();
+
+ /* update return values */
+ rw_args->bytes_moved = count;
+ if ( count >= 0 ) {
+ status = RTEMS_SUCCESSFUL;
+ }
+
+ /* check to see if queue is empty */
+ if (sc->sc_inq.ifq_head != NULL) {
+ /* queue is not empty - post another event to ourself */
+ rtems_event_send(sc->sc_pppdtask, PPPD_EVENT);
+ }
+
+ return ( status );
+}
+
+/*
+ * Line specific (tty) write routine.
+ */
+int
+pppwrite(struct rtems_termios_tty *tty, rtems_libio_rw_args_t *rw_args)
+{
+ struct sockaddr dst;
+ int n;
+ int len;
+ int maximum = rw_args->count;
+ char *out_buffer = rw_args->buffer;
+ register struct ppp_softc *sc = (struct ppp_softc *)tty->t_sc;
+ struct mbuf *m;
+ struct mbuf *m0;
+ struct mbuf **mp;
+
+ rtems_bsdnet_semaphore_obtain();
+ for (mp = &m0; maximum; mp = &m->m_next) {
+ MGET(m, M_WAIT, MT_DATA);
+ if ((*mp = m) == NULL) {
+ m_freem(m0);
+ return (ENOBUFS);
+ }
+ m->m_len = 0;
+ if (maximum >= MCLBYTES / 2) {
+ MCLGET(m, M_DONTWAIT);
+ }
+ len = M_TRAILINGSPACE(m);
+ if (len > maximum) {
+ memcpy(mtod(m, u_char *),out_buffer,maximum);
+ m->m_len = maximum;
+ maximum = 0;
+ }
+ else {
+ memcpy(mtod(m, u_char *),out_buffer,len);
+ m->m_len = len;
+ maximum -= len;
+ out_buffer += len;
+ }
+ }
+
+ dst.sa_family = AF_UNSPEC;
+ bcopy(mtod(m0, u_char *), dst.sa_data, PPP_HDRLEN);
+ m0->m_data += PPP_HDRLEN;
+ m0->m_len -= PPP_HDRLEN;
+
+ n = pppoutput(&sc->sc_if, m0, &dst, (struct rtentry *)0);
+ rtems_bsdnet_semaphore_release();
+
+ return ( n );
+}
+
+/*
+ * Line specific (tty) ioctl routine.
+ * This discipline requires that tty device drivers call
+ * the line specific l_ioctl routine from their ioctl routines.
+ */
+/* ARGSUSED */
+int
+ppptioctl(struct rtems_termios_tty *tty, rtems_libio_ioctl_args_t *args)
+{
+/* int i; */
+ int error = RTEMS_SUCCESSFUL;
+ int cmd = args->command;
+ caddr_t data = args->buffer;
+ struct ppp_softc *sc = tty->t_sc;
+
+ switch (cmd) {
+ case RTEMS_IO_GET_ATTRIBUTES:
+ case RTEMS_IO_SET_ATTRIBUTES:
+ case RTEMS_IO_TCDRAIN:
+ case RTEMS_IO_SNDWAKEUP:
+ case RTEMS_IO_RCVWAKEUP:
+ case TIOCGETD:
+ case TIOCSETD:
+ error = rtems_termios_ioctl(args);
+ break;
+
+ case PPPIOCSASYNCMAP:
+ sc->sc_asyncmap[0] = *(u_int *)data;
+ break;
+
+ case PPPIOCGASYNCMAP:
+ *(u_int *)data = sc->sc_asyncmap[0];
+ break;
+
+ case PPPIOCSRASYNCMAP:
+ sc->sc_rasyncmap = *(u_int *)data;
+ break;
+
+ case PPPIOCGRASYNCMAP:
+ *(u_int *)data = sc->sc_rasyncmap;
+ break;
+
+ case PPPIOCSXASYNCMAP:
+ bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
+ sc->sc_asyncmap[1] = 0; /* mustn't escape 0x20 - 0x3f */
+ sc->sc_asyncmap[2] &= ~0x40000000; /* mustn't escape 0x5e */
+ sc->sc_asyncmap[3] |= 0x60000000; /* must escape 0x7d, 0x7e */
+ break;
+
+ case PPPIOCGXASYNCMAP:
+ bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
+ break;
+
+ default:
+ rtems_bsdnet_semaphore_obtain();
+ error = pppioctl(sc, cmd, data, 0, NULL);
+ rtems_bsdnet_semaphore_release();
+ }
+ return error;
+}
+
+/*
+ * FCS lookup table as calculated by genfcstab.
+ */
+static u_short fcstab[256] = {
+ 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
+ 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
+ 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
+ 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
+ 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
+ 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
+ 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
+ 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
+ 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
+ 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
+ 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
+ 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
+ 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
+ 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
+ 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
+ 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
+ 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
+ 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
+ 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
+ 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
+ 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
+ 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
+ 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
+ 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
+ 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
+ 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
+ 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
+ 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
+ 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
+ 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
+ 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
+ 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
+};
+
+/*
+ * Calculate a new FCS given the current FCS and the new data.
+ */
+u_short
+pppfcs(u_short fcs, u_char *cp, int len)
+{
+ while (len--)
+ fcs = PPP_FCS(fcs, *cp++);
+ return (fcs);
+}
+
+/*
+ * This gets called at splsoftnet from if_ppp.c at various times
+ * when there is data ready to be sent.
+ */
+void pppasyncstart(struct ppp_softc *sc)
+{
+ /* check to see if output is not active */
+ if ( sc->sc_outflag == 0 ) {
+ /* mark active and post tx event to daemon */
+ sc->sc_outflag |= SC_TX_PENDING;
+ rtems_event_send(sc->sc_txtask, TX_PACKET);
+ }
+}
+
+/*
+ * This gets called when a received packet is placed on
+ * the inq, at splsoftnet.
+ */
+static void
+pppasyncctlp(sc)
+ struct ppp_softc *sc;
+{
+ /* check to see if task id was set */
+ if ( sc->sc_pppdtask != 0 ) {
+ /* post event to daemon */
+ rtems_event_send(sc->sc_pppdtask, PPPD_EVENT);
+ }
+}
+
+/*
+ * Start output on async tty interface. If the transmit queue
+ * has drained sufficiently, arrange for pppasyncstart to be
+ * called later at splsoftnet.
+ * Called at spltty or higher.
+ */
+int
+pppstart(struct rtems_termios_tty *tp)
+{
+ char *sendBegin;
+ u_long ioffset = (u_long )0;
+ struct mbuf *m = (struct mbuf *)0;
+ struct ppp_softc *sc = tp->t_sc;
+
+ /* ensure input is valid and we are busy */
+ if (( sc != NULL ) && ( sc->sc_outflag & SC_TX_BUSY )) {
+ /* check to see if we need to get the next buffer */
+
+ /* Ready with PPP_FLAG Character ? */
+ if(sc->sc_outflag & SC_TX_LASTCHAR){
+ sc->sc_outflag &= ~(SC_TX_BUSY | SC_TX_FCS | SC_TX_LASTCHAR);
+ rtems_event_send(sc->sc_txtask, TX_TRANSMIT); /* Ready for the next Packet */
+ return(0);
+ }
+
+ if ( sc->sc_outoff >= sc->sc_outlen ) {
+ /* loop to get next non-zero length buffer */
+ if ( sc->sc_outmc != NULL ) {
+ m = sc->sc_outmc->m_next;
+ }
+
+ /* check for next mbuf in chain */
+ if ( m != NULL ) {
+ /* update values to use this mbuf */
+ sc->sc_outmc = m;
+ sc->sc_outbuf = mtod(m, u_char *);
+ sc->sc_outlen = m->m_len;
+ sc->sc_outoff = (short)0;
+ }
+ else if ( (sc->sc_outflag & SC_TX_FCS) == 0 ) {
+ /* setup to use FCS buffer */
+ sc->sc_outflag |= SC_TX_FCS;
+ sc->sc_outbuf = sc->sc_outfcsbuf;
+ sc->sc_outlen = sc->sc_outfcslen;
+ sc->sc_outoff = (short)0;
+ }
+ else {
+ /* done with this packet */
+ sc->sc_outflag |= SC_TX_LASTCHAR;
+ sc->sc_outflag &=~(SC_TX_FCS);
+ sc->sc_outchar = (u_char)PPP_FLAG;
+ (*tp->device.write)(tp->minor, &sc->sc_outchar, 1);
+ return(0);
+ }
+ }
+
+ /* check to see if there is some data to write out */
+ if ( sc->sc_outoff < sc->sc_outlen ) {
+ /* check to see if character needs to be escaped */
+ sc->sc_outchar = sc->sc_outbuf[sc->sc_outoff];
+ if ( ESCAPE_P(sc->sc_outchar) ) {
+ if ( sc->sc_outflag & SC_TX_ESCAPE ) {
+ /* last sent character was the escape character */
+ sc->sc_outchar = sc->sc_outchar ^ PPP_TRANS;
+
+ /* clear the escape flag and increment the offset */
+ sc->sc_outflag &= ~SC_TX_ESCAPE;
+ ioffset++;
+ }
+ else {
+ /* need to send the escape character */
+ sc->sc_outchar = PPP_ESCAPE;
+
+ /* set the escape flag */
+ sc->sc_outflag |= SC_TX_ESCAPE;
+ }
+ sendBegin = &sc->sc_outchar;
+ }
+ else {
+ /* escape not needed - increment the offset as much as possible */
+ while ((!ESCAPE_P(sc->sc_outchar)) && ((sc->sc_outoff + ioffset) < sc->sc_outlen)) {
+ ioffset++;
+ sc->sc_outchar = sc->sc_outbuf[sc->sc_outoff + ioffset];
+ }
+ sendBegin = &sc->sc_outbuf[sc->sc_outoff];
+ }
+
+ /* write out the character(s) and update the stats */
+ (*tp->device.write)(tp->minor, sendBegin, (ioffset > 0) ? ioffset : 1);
+ sc->sc_stats.ppp_obytes += (ioffset > 0) ? ioffset : 1;
+ sc->sc_outoff += ioffset;
+ }
+ }
+
+ return ( 0 );
+}
+
+#ifdef XXX_XXX
+/*
+ * Timeout routine - try to start some more output.
+ */
+static void
+ppp_timeout(x)
+ void *x;
+{
+ struct rtems_termios_tty *tty = (struct rtems_termios_tty *)x;
+ struct ppp_softc *sc = tty->t_sc;
+/* struct rtems_termios_tty *tp = (struct rtems_termios_tty *)sc->sc_devp; */
+
+ sc->sc_flags &= ~SC_TIMEOUT;
+/* pppstart(tp); */
+}
+#endif
+
+/*
+ * Allocate enough mbuf to handle current MRU.
+ */
+#ifdef XXX_XXX
+static void
+pppgetm(sc)
+ register struct ppp_softc *sc;
+{
+ struct mbuf *m, **mp;
+ int len;
+
+ mp = &sc->sc_m;
+ for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
+ if ((m = *mp) == NULL) {
+ MGETHDR(m, M_DONTWAIT, MT_DATA);
+ if (m == NULL)
+ break;
+ *mp = m;
+ MCLGET(m, M_DONTWAIT);
+ }
+ len -= M_DATASIZE(m);
+ mp = &m->m_next;
+ }
+}
+#endif
+
+void
+pppallocmbuf(struct ppp_softc *sc, struct mbuf **mp)
+{
+ int ilen;
+ struct mbuf *m;
+
+ /* loop over length value */
+ ilen = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN;
+ while ( ilen > 0 ) {
+ /* see if this is end of the chain */
+ m = *mp;
+ if ( m == NULL ) {
+ /* get mbuf header */
+ MGETHDR(m, M_DONTWAIT, MT_DATA);
+ if ( m == NULL ) {
+ /* error - set condition to break out */
+ printf("pppallocmbuf: MGETHDR failed\n");
+ break;
+ }
+ MCLGET(m, M_DONTWAIT);
+ m->m_next = NULL;
+ *mp = m;
+ }
+
+ /* update loop variables */
+ mp = &m->m_next;
+ ilen -= M_DATASIZE(m);
+ }
+}
+
+/*
+ * tty interface receiver interrupt.
+ */
+static unsigned paritytab[8] = {
+ 0x96696996, 0x69969669, 0x69969669, 0x96696996,
+ 0x69969669, 0x96696996, 0x96696996, 0x69969669
+};
+
+int
+pppinput(int c, struct rtems_termios_tty *tp)
+{
+ register struct ppp_softc *sc = tp->t_sc;
+ struct mbuf *m;
+ int ilen;
+
+ if (sc == NULL || tp != (struct rtems_termios_tty *)sc->sc_devp)
+ return 0;
+ if (sc->sc_m == NULL) {
+ rtems_event_send(sc->sc_rxtask, RX_EMPTY);
+ IF_DEQUEUE(&sc->sc_freeq, sc->sc_m);
+ if ( sc->sc_m == NULL ) {
+ return 0;
+ }
+ }
+
+ ++sc->sc_stats.ppp_ibytes;
+
+ c &= 0xff;
+ if (c & 0x80)
+ sc->sc_flags |= SC_RCV_B7_1;
+ else
+ sc->sc_flags |= SC_RCV_B7_0;
+ if (paritytab[c >> 5] & (1 << (c & 0x1F)))
+ sc->sc_flags |= SC_RCV_ODDP;
+ else
+ sc->sc_flags |= SC_RCV_EVNP;
+
+ if (c == PPP_FLAG) {
+ ilen = sc->sc_ilen;
+ sc->sc_ilen = 0;
+
+ /*
+ * If SC_ESCAPED is set, then we've seen the packet
+ * abort sequence "}~".
+ */
+ if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
+ || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
+ sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */
+ if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
+ /* bad fcs error */
+ sc->sc_if.if_ierrors++;
+ sc->sc_stats.ppp_ierrors++;
+ } else
+ sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
+ return 0;
+ }
+
+ if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
+ if (ilen) {
+ /* too short error */
+ sc->sc_if.if_ierrors++;
+ sc->sc_stats.ppp_ierrors++;
+ sc->sc_flags |= SC_PKTLOST;
+ }
+ return 0;
+ }
+
+ /* Remove FCS trailer. Somewhat painful... */
+ ilen -= 2;
+ if (--sc->sc_mc->m_len == 0) {
+ for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next);
+ sc->sc_mc = m;
+ }
+ sc->sc_mc->m_len--;
+
+ /* excise this mbuf chain - place on raw queue */
+ m = sc->sc_m;
+ if ( sc->sc_flags & SC_PKTLOST ) {
+ m->m_flags |= M_ERRMARK;
+ sc->sc_flags &= ~SC_PKTLOST;
+ }
+ IF_ENQUEUE(&sc->sc_rawq, m);
+
+ /* setup next mbuf chain */
+ IF_DEQUEUE(&sc->sc_freeq, sc->sc_m);
+
+ /* send rx packet event */
+ rtems_event_send(sc->sc_rxtask, RX_PACKET);
+ return 0;
+ }
+
+ if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
+ return 0;
+
+ if (sc->sc_flags & SC_ESCAPED) {
+ sc->sc_flags &= ~SC_ESCAPED;
+ c ^= PPP_TRANS;
+ } else if (c == PPP_ESCAPE) {
+ sc->sc_flags |= SC_ESCAPED;
+ return 0;
+ }
+
+ /*
+ * Initialize buffer on first octet received.
+ * First octet could be address or protocol (when compressing
+ * address/control).
+ * Second octet is control.
+ * Third octet is first or second (when compressing protocol)
+ * octet of protocol.
+ * Fourth octet is second octet of protocol.
+ */
+ if (sc->sc_ilen == 0) {
+ m = sc->sc_m;
+ m->m_len = 0;
+ m->m_data = M_DATASTART(sc->sc_m);
+ sc->sc_mc = m;
+ sc->sc_mp = mtod(m, char *);
+ sc->sc_fcs = PPP_INITFCS;
+ if (c != PPP_ALLSTATIONS) {
+ if (sc->sc_flags & SC_REJ_COMP_AC) {
+ /* garbage received error */
+ goto flush;
+ }
+ *sc->sc_mp++ = PPP_ALLSTATIONS;
+ *sc->sc_mp++ = PPP_UI;
+ sc->sc_ilen += 2;
+ m->m_len += 2;
+ }
+ }
+ if (sc->sc_ilen == 1 && c != PPP_UI) {
+ /* missing UI error */
+ goto flush;
+ }
+ if (sc->sc_ilen == 2 && (c & 1) == 1) {
+ /* a compressed protocol */
+ *sc->sc_mp++ = 0;
+ sc->sc_ilen++;
+ sc->sc_mc->m_len++;
+ }
+ if (sc->sc_ilen == 3 && (c & 1) == 0) {
+ /* bad protocol error */
+ goto flush;
+ }
+
+ /* packet beyond configured mru? */
+ if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
+ /* packet too big error */
+ goto flush;
+ }
+
+ /* is this mbuf full? */
+ m = sc->sc_mc;
+ if (M_TRAILINGSPACE(m) <= 0) {
+ if (m->m_next == NULL) {
+ /* get next available mbuf for the chain */
+ IF_DEQUEUE(&sc->sc_freeq, m->m_next);
+ if (m->m_next == NULL) {
+ /* too few mbufs */
+ goto flush;
+ }
+ else {
+ /* send rx mbuf event */
+ rtems_event_send(sc->sc_rxtask, RX_MBUF);
+ }
+ }
+ sc->sc_mc = m = m->m_next;
+ m->m_len = 0;
+ m->m_next = 0;
+ m->m_data = M_DATASTART(m);
+ sc->sc_mp = mtod(m, char *);
+ }
+
+ ++m->m_len;
+ *sc->sc_mp++ = c;
+ sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
+ return 0;
+
+ flush:
+ if (!(sc->sc_flags & SC_FLUSH)) {
+ sc->sc_if.if_ierrors++;
+ sc->sc_stats.ppp_ierrors++;
+ sc->sc_flags |= SC_FLUSH;
+ }
+ return 0;
+}
+
+#ifdef XXX_XXX
+#define MAX_DUMP_BYTES 128
+
+static void
+ppplogchar(sc, c)
+ struct ppp_softc *sc;
+ int c;
+{
+ if (c >= 0)
+ sc->sc_rawin[sc->sc_rawin_count++] = c;
+ if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
+ || (c < 0 && sc->sc_rawin_count > 0)) {
+ printf("ppp%d input: ", sc->sc_if.if_unit);
+ pppdumpb(sc->sc_rawin, sc->sc_rawin_count);
+ sc->sc_rawin_count = 0;
+ }
+}
+
+static void
+pppdumpb(b, l)
+ u_char *b;
+ int l;
+{
+ char buf[3*MAX_DUMP_BYTES+4];
+ char *bp = buf;
+ static char digits[] = "0123456789abcdef";
+
+ while (l--) {
+ if (bp >= buf + sizeof(buf) - 3) {
+ *bp++ = '>';
+ break;
+ }
+ *bp++ = digits[*b >> 4]; /* convert byte to ascii hex */
+ *bp++ = digits[*b++ & 0xf];
+ *bp++ = ' ';
+ }
+
+ *bp = 0;
+ printf("%s\n", buf);
+}
+#endif
+
+#endif /* NPPP > 0 */
diff --git a/cpukit/libnetworking/net/pppcompress.c b/cpukit/libnetworking/net/pppcompress.c
new file mode 100644
index 0000000000..e68d7c4e91
--- /dev/null
+++ b/cpukit/libnetworking/net/pppcompress.c
@@ -0,0 +1,593 @@
+/*-
+ * Copyright (c) 1989 The Regents of the University of California.
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)slcompress.c 7.7 (Berkeley) 5/7/91
+ */
+
+/*
+ * Routines to compress and uncompess tcp packets (for transmission
+ * over low speed serial lines.
+ *
+ * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
+ * - Initial distribution.
+ *
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+
+#include <net/pppcompress.h>
+
+#ifndef SL_NO_STATS
+#define INCR(counter) ++comp->counter;
+#else
+#define INCR(counter)
+#endif
+
+#define BCMP(p1, p2, n) bcmp((char *)(p1), (char *)(p2), (int)(n))
+#define BCOPY(p1, p2, n) bcopy((char *)(p1), (char *)(p2), (int)(n))
+#ifndef _KERNEL
+#define ovbcopy bcopy
+#endif
+
+void
+vj_compress_init(comp, max_state)
+ struct vjcompress *comp;
+ int max_state;
+{
+ register u_int i;
+ register struct cstate *tstate = comp->tstate;
+
+ if ((unsigned) max_state > MAX_STATES - 1)
+ max_state = MAX_STATES - 1;
+ bzero((char *)comp, sizeof(*comp));
+ for (i = max_state; i > 0; --i) {
+ tstate[i].cs_id = i;
+ tstate[i].cs_next = &tstate[i - 1];
+ }
+ tstate[0].cs_next = &tstate[max_state];
+ tstate[0].cs_id = 0;
+ comp->last_cs = &tstate[0];
+ comp->last_recv = 255;
+ comp->last_xmit = 255;
+ comp->flags = SLF_TOSS;
+}
+
+
+/* ENCODE encodes a number that is known to be non-zero. ENCODEZ
+ * checks for zero (since zero has to be encoded in the long, 3 byte
+ * form).
+ */
+#define ENCODE(n) { \
+ if ((u_short)(n) >= 256) { \
+ *cp++ = 0; \
+ cp[1] = (n); \
+ cp[0] = (n) >> 8; \
+ cp += 2; \
+ } else { \
+ *cp++ = (n); \
+ } \
+}
+#define ENCODEZ(n) { \
+ if ((u_short)(n) >= 256 || (u_short)(n) == 0) { \
+ *cp++ = 0; \
+ cp[1] = (n); \
+ cp[0] = (n) >> 8; \
+ cp += 2; \
+ } else { \
+ *cp++ = (n); \
+ } \
+}
+
+#define DECODEL(f) { \
+ if (*cp == 0) {\
+ (f) = htonl(ntohl(f) + ((cp[1] << 8) | cp[2])); \
+ cp += 3; \
+ } else { \
+ (f) = htonl(ntohl(f) + (u_long)*cp++); \
+ } \
+}
+
+#define DECODES(f) { \
+ if (*cp == 0) {\
+ (f) = htons(ntohs(f) + ((cp[1] << 8) | cp[2])); \
+ cp += 3; \
+ } else { \
+ (f) = htons(ntohs(f) + (u_long)*cp++); \
+ } \
+}
+
+#define DECODEU(f) { \
+ if (*cp == 0) {\
+ (f) = htons((cp[1] << 8) | cp[2]); \
+ cp += 3; \
+ } else { \
+ (f) = htons((u_long)*cp++); \
+ } \
+}
+
+u_int
+vj_compress_tcp(m, ip, comp, compress_cid)
+ struct mbuf *m;
+ register struct ip *ip;
+ struct vjcompress *comp;
+ int compress_cid;
+{
+ register struct cstate *cs = comp->last_cs->cs_next;
+ register u_int hlen = ip->ip_hl;
+ register struct tcphdr *oth;
+ register struct tcphdr *th;
+ register u_int deltaS, deltaA;
+ register u_int changes = 0;
+ u_char new_seq[16];
+ register u_char *cp = new_seq;
+
+ /*
+ * Bail if this is an IP fragment or if the TCP packet isn't
+ * `compressible' (i.e., ACK isn't set or some other control bit is
+ * set). (We assume that the caller has already made sure the
+ * packet is IP proto TCP).
+ */
+ if ((ip->ip_off & htons(0x3fff)) || m->m_len < 40)
+ return (TYPE_IP);
+
+ th = (struct tcphdr *)&((int *)ip)[hlen];
+ if ((th->th_flags & (TH_SYN|TH_FIN|TH_RST|TH_ACK)) != TH_ACK)
+ return (TYPE_IP);
+ /*
+ * Packet is compressible -- we're going to send either a
+ * COMPRESSED_TCP or UNCOMPRESSED_TCP packet. Either way we need
+ * to locate (or create) the connection state. Special case the
+ * most recently used connection since it's most likely to be used
+ * again & we don't have to do any reordering if it's used.
+ */
+ INCR(sls_packets)
+ if (ip->ip_src.s_addr != cs->cs_ip.ip_src.s_addr ||
+ ip->ip_dst.s_addr != cs->cs_ip.ip_dst.s_addr ||
+ *(int *)th != ((int *)&cs->cs_ip)[cs->cs_ip.ip_hl]) {
+ /*
+ * Wasn't the first -- search for it.
+ *
+ * States are kept in a circularly linked list with
+ * last_cs pointing to the end of the list. The
+ * list is kept in lru order by moving a state to the
+ * head of the list whenever it is referenced. Since
+ * the list is short and, empirically, the connection
+ * we want is almost always near the front, we locate
+ * states via linear search. If we don't find a state
+ * for the datagram, the oldest state is (re-)used.
+ */
+ register struct cstate *lcs;
+ register struct cstate *lastcs = comp->last_cs;
+
+ do {
+ lcs = cs; cs = cs->cs_next;
+ INCR(sls_searches)
+ if (ip->ip_src.s_addr == cs->cs_ip.ip_src.s_addr
+ && ip->ip_dst.s_addr == cs->cs_ip.ip_dst.s_addr
+ && *(int *)th == ((int *)&cs->cs_ip)[cs->cs_ip.ip_hl])
+ goto found;
+ } while (cs != lastcs);
+
+ /*
+ * Didn't find it -- re-use oldest cstate. Send an
+ * uncompressed packet that tells the other side what
+ * connection number we're using for this conversation.
+ * Note that since the state list is circular, the oldest
+ * state points to the newest and we only need to set
+ * last_cs to update the lru linkage.
+ */
+ INCR(sls_misses)
+ comp->last_cs = lcs;
+ hlen += th->th_off;
+ hlen <<= 2;
+ goto uncompressed;
+
+ found:
+ /*
+ * Found it -- move to the front on the connection list.
+ */
+ if (cs == lastcs)
+ comp->last_cs = lcs;
+ else {
+ lcs->cs_next = cs->cs_next;
+ cs->cs_next = lastcs->cs_next;
+ lastcs->cs_next = cs;
+ }
+ }
+
+ /*
+ * Make sure that only what we expect to change changed. The first
+ * line of the `if' checks the IP protocol version, header length &
+ * type of service. The 2nd line checks the "Don't fragment" bit.
+ * The 3rd line checks the time-to-live and protocol (the protocol
+ * check is unnecessary but costless). The 4th line checks the TCP
+ * header length. The 5th line checks IP options, if any. The 6th
+ * line checks TCP options, if any. If any of these things are
+ * different between the previous & current datagram, we send the
+ * current datagram `uncompressed'.
+ */
+ oth = (struct tcphdr *)&((int *)&cs->cs_ip)[hlen];
+ deltaS = hlen;
+ hlen += th->th_off;
+ hlen <<= 2;
+
+ if (((u_short *)ip)[0] != ((u_short *)&cs->cs_ip)[0] ||
+ ((u_short *)ip)[3] != ((u_short *)&cs->cs_ip)[3] ||
+ ((u_short *)ip)[4] != ((u_short *)&cs->cs_ip)[4] ||
+ th->th_off != oth->th_off ||
+ (deltaS > 5 &&
+ BCMP(ip + 1, &cs->cs_ip + 1, (deltaS - 5) << 2)) ||
+ (th->th_off > 5 &&
+ BCMP(th + 1, oth + 1, (th->th_off - 5) << 2)))
+ goto uncompressed;
+
+ /*
+ * Figure out which of the changing fields changed. The
+ * receiver expects changes in the order: urgent, window,
+ * ack, seq (the order minimizes the number of temporaries
+ * needed in this section of code).
+ */
+ if (th->th_flags & TH_URG) {
+ deltaS = ntohs(th->th_urp);
+ ENCODEZ(deltaS);
+ changes |= NEW_U;
+ } else if (th->th_urp != oth->th_urp)
+ /* argh! URG not set but urp changed -- a sensible
+ * implementation should never do this but RFC793
+ * doesn't prohibit the change so we have to deal
+ * with it. */
+ goto uncompressed;
+
+ if ((deltaS = (u_short)(ntohs(th->th_win) - ntohs(oth->th_win)))) {
+ ENCODE(deltaS);
+ changes |= NEW_W;
+ }
+
+ if ((deltaA = ntohl(th->th_ack) - ntohl(oth->th_ack))) {
+ if (deltaA > 0xffff)
+ goto uncompressed;
+ ENCODE(deltaA);
+ changes |= NEW_A;
+ }
+
+ if ((deltaS = ntohl(th->th_seq) - ntohl(oth->th_seq))) {
+ if (deltaS > 0xffff)
+ goto uncompressed;
+ ENCODE(deltaS);
+ changes |= NEW_S;
+ }
+
+ switch(changes) {
+
+ case 0:
+ /*
+ * Nothing changed. If this packet contains data and the
+ * last one didn't, this is probably a data packet following
+ * an ack (normal on an interactive connection) and we send
+ * it compressed. Otherwise it's probably a retransmit,
+ * retransmitted ack or window probe. Send it uncompressed
+ * in case the other side missed the compressed version.
+ */
+ if (ip->ip_len != cs->cs_ip.ip_len &&
+ ntohs(cs->cs_ip.ip_len) == hlen)
+ break;
+
+ /* (fall through) */
+
+ case SPECIAL_I:
+ case SPECIAL_D:
+ /*
+ * actual changes match one of our special case encodings --
+ * send packet uncompressed.
+ */
+ goto uncompressed;
+
+ case NEW_S|NEW_A:
+ if (deltaS == deltaA &&
+ deltaS == ntohs(cs->cs_ip.ip_len) - hlen) {
+ /* special case for echoed terminal traffic */
+ changes = SPECIAL_I;
+ cp = new_seq;
+ }
+ break;
+
+ case NEW_S:
+ if (deltaS == ntohs(cs->cs_ip.ip_len) - hlen) {
+ /* special case for data xfer */
+ changes = SPECIAL_D;
+ cp = new_seq;
+ }
+ break;
+ }
+
+ deltaS = ntohs(ip->ip_id) - ntohs(cs->cs_ip.ip_id);
+ if (deltaS != 1) {
+ ENCODEZ(deltaS);
+ changes |= NEW_I;
+ }
+ if (th->th_flags & TH_PUSH)
+ changes |= TCP_PUSH_BIT;
+ /*
+ * Grab the cksum before we overwrite it below. Then update our
+ * state with this packet's header.
+ */
+ deltaA = ntohs(th->th_sum);
+ BCOPY(ip, &cs->cs_ip, hlen);
+
+ /*
+ * We want to use the original packet as our compressed packet.
+ * (cp - new_seq) is the number of bytes we need for compressed
+ * sequence numbers. In addition we need one byte for the change
+ * mask, one for the connection id and two for the tcp checksum.
+ * So, (cp - new_seq) + 4 bytes of header are needed. hlen is how
+ * many bytes of the original packet to toss so subtract the two to
+ * get the new packet size.
+ */
+ deltaS = cp - new_seq;
+ cp = (u_char *)ip;
+ if (compress_cid == 0 || comp->last_xmit != cs->cs_id) {
+ comp->last_xmit = cs->cs_id;
+ hlen -= deltaS + 4;
+ cp += hlen;
+ *cp++ = changes | NEW_C;
+ *cp++ = cs->cs_id;
+ } else {
+ hlen -= deltaS + 3;
+ cp += hlen;
+ *cp++ = changes;
+ }
+ m->m_len -= hlen;
+ m->m_data += hlen;
+ *cp++ = deltaA >> 8;
+ *cp++ = deltaA;
+ BCOPY(new_seq, cp, deltaS);
+ INCR(sls_compressed)
+ return (TYPE_COMPRESSED_TCP);
+
+ /*
+ * Update connection state cs & send uncompressed packet ('uncompressed'
+ * means a regular ip/tcp packet but with the 'conversation id' we hope
+ * to use on future compressed packets in the protocol field).
+ */
+uncompressed:
+ BCOPY(ip, &cs->cs_ip, hlen);
+ ip->ip_p = cs->cs_id;
+ comp->last_xmit = cs->cs_id;
+ return (TYPE_UNCOMPRESSED_TCP);
+}
+
+
+int
+vj_uncompress_tcp(bufp, len, type, comp)
+ u_char **bufp;
+ int len;
+ u_int type;
+ struct vjcompress *comp;
+{
+ u_char *hdr, *cp;
+ int hlen, vjlen;
+
+ cp = bufp? *bufp: NULL;
+ vjlen = vj_uncompress_tcp_core(cp, len, len, type, comp, &hdr, &hlen);
+ if (vjlen < 0)
+ return (0); /* error */
+ if (vjlen == 0)
+ return (len); /* was uncompressed already */
+
+ cp += vjlen;
+ len -= vjlen;
+
+ /*
+ * At this point, cp points to the first byte of data in the
+ * packet. If we're not aligned on a 4-byte boundary, copy the
+ * data down so the ip & tcp headers will be aligned. Then back up
+ * cp by the tcp/ip header length to make room for the reconstructed
+ * header (we assume the packet we were handed has enough space to
+ * prepend 128 bytes of header).
+ */
+ if ((int)cp & 3) {
+ if (len > 0)
+ (void) ovbcopy(cp, (caddr_t)((int)cp &~ 3), len);
+ cp = (u_char *)((int)cp &~ 3);
+ }
+ cp -= hlen;
+ len += hlen;
+ BCOPY(hdr, cp, hlen);
+
+ *bufp = cp;
+ return (len);
+}
+
+/*
+ * Uncompress a packet of total length total_len. The first buflen
+ * bytes are at buf; this must include the entire (compressed or
+ * uncompressed) TCP/IP header. This procedure returns the length
+ * of the VJ header, with a pointer to the uncompressed IP header
+ * in *hdrp and its length in *hlenp.
+ */
+int
+vj_uncompress_tcp_core(buf, buflen, total_len, type, comp, hdrp, hlenp)
+ u_char *buf;
+ int buflen, total_len;
+ u_int type;
+ struct vjcompress *comp;
+ u_char **hdrp;
+ u_int *hlenp;
+{
+ register u_char *cp;
+ register u_int hlen, changes;
+ register struct tcphdr *th;
+ register struct cstate *cs;
+ register struct ip *ip;
+ register u_short *bp;
+ register u_int vjlen;
+
+ switch (type) {
+
+ case TYPE_UNCOMPRESSED_TCP:
+ ip = (struct ip *) buf;
+ if (ip->ip_p >= MAX_STATES)
+ goto bad;
+ cs = &comp->rstate[comp->last_recv = ip->ip_p];
+ comp->flags &=~ SLF_TOSS;
+ ip->ip_p = IPPROTO_TCP;
+ /*
+ * Calculate the size of the TCP/IP header and make sure that
+ * we don't overflow the space we have available for it.
+ */
+ hlen = ip->ip_hl << 2;
+ if (hlen + sizeof(struct tcphdr) > buflen)
+ goto bad;
+ hlen += ((struct tcphdr *)&((char *)ip)[hlen])->th_off << 2;
+ if (hlen > MAX_HDR || hlen > buflen)
+ goto bad;
+ BCOPY(ip, &cs->cs_ip, hlen);
+ cs->cs_hlen = hlen;
+ INCR(sls_uncompressedin)
+ *hdrp = (u_char *) &cs->cs_ip;
+ *hlenp = hlen;
+ return (0);
+
+ default:
+ goto bad;
+
+ case TYPE_COMPRESSED_TCP:
+ break;
+ }
+ /* We've got a compressed packet. */
+ INCR(sls_compressedin)
+ cp = buf;
+ changes = *cp++;
+ if (changes & NEW_C) {
+ /* Make sure the state index is in range, then grab the state.
+ * If we have a good state index, clear the 'discard' flag. */
+ if (*cp >= MAX_STATES)
+ goto bad;
+
+ comp->flags &=~ SLF_TOSS;
+ comp->last_recv = *cp++;
+ } else {
+ /* this packet has an implicit state index. If we've
+ * had a line error since the last time we got an
+ * explicit state index, we have to toss the packet. */
+ if (comp->flags & SLF_TOSS) {
+ INCR(sls_tossed)
+ return (-1);
+ }
+ }
+ cs = &comp->rstate[comp->last_recv];
+ hlen = cs->cs_ip.ip_hl << 2;
+ th = (struct tcphdr *)&((u_char *)&cs->cs_ip)[hlen];
+ th->th_sum = htons((*cp << 8) | cp[1]);
+ cp += 2;
+ if (changes & TCP_PUSH_BIT)
+ th->th_flags |= TH_PUSH;
+ else
+ th->th_flags &=~ TH_PUSH;
+
+ switch (changes & SPECIALS_MASK) {
+ case SPECIAL_I:
+ {
+ register u_int i = ntohs(cs->cs_ip.ip_len) - cs->cs_hlen;
+ th->th_ack = htonl(ntohl(th->th_ack) + i);
+ th->th_seq = htonl(ntohl(th->th_seq) + i);
+ }
+ break;
+
+ case SPECIAL_D:
+ th->th_seq = htonl(ntohl(th->th_seq) + ntohs(cs->cs_ip.ip_len)
+ - cs->cs_hlen);
+ break;
+
+ default:
+ if (changes & NEW_U) {
+ th->th_flags |= TH_URG;
+ DECODEU(th->th_urp)
+ } else
+ th->th_flags &=~ TH_URG;
+ if (changes & NEW_W)
+ DECODES(th->th_win)
+ if (changes & NEW_A)
+ DECODEL(th->th_ack)
+ if (changes & NEW_S)
+ DECODEL(th->th_seq)
+ break;
+ }
+ if (changes & NEW_I) {
+ DECODES(cs->cs_ip.ip_id)
+ } else
+ cs->cs_ip.ip_id = htons(ntohs(cs->cs_ip.ip_id) + 1);
+
+ /*
+ * At this point, cp points to the first byte of data in the
+ * packet. Fill in the IP total length and update the IP
+ * header checksum.
+ */
+ vjlen = cp - buf;
+ buflen -= vjlen;
+ if (buflen < 0)
+ /* we must have dropped some characters (crc should detect
+ * this but the old slip framing won't) */
+ goto bad;
+
+ total_len += cs->cs_hlen - vjlen;
+ cs->cs_ip.ip_len = htons(total_len);
+
+ /* recompute the ip header checksum */
+ bp = (u_short *) &cs->cs_ip;
+ cs->cs_ip.ip_sum = 0;
+ for (changes = 0; hlen > 0; hlen -= 2)
+ changes += *bp++;
+ changes = (changes & 0xffff) + (changes >> 16);
+ changes = (changes & 0xffff) + (changes >> 16);
+ cs->cs_ip.ip_sum = ~ changes;
+
+ *hdrp = (u_char *) &cs->cs_ip;
+ *hlenp = cs->cs_hlen;
+ return vjlen;
+
+bad:
+ comp->flags |= SLF_TOSS;
+ INCR(sls_errorin)
+ return (-1);
+}
diff --git a/cpukit/libnetworking/net/pppcompress.h b/cpukit/libnetworking/net/pppcompress.h
new file mode 100644
index 0000000000..3f7687e6bb
--- /dev/null
+++ b/cpukit/libnetworking/net/pppcompress.h
@@ -0,0 +1,164 @@
+/*
+ * Definitions for tcp compression routines.
+ *
+ * Copyright (c) 1989 Regents of the University of California.
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * Van Jacobson (van@helios.ee.lbl.gov), Dec 31, 1989:
+ * - Initial distribution.
+ *
+ * From: slcompress.h 7.4 90/06/28
+ * $Id$
+ */
+
+#ifndef _NET_PPPCOMPRESS_H_
+#define _NET_PPPCOMPRESS_H_
+
+#define MAX_STATES 16 /* must be > 2 and < 256 */
+#define MAX_HDR MLEN /* XXX 4bsd-ism: should really be 128 */
+
+/*
+ * Compressed packet format:
+ *
+ * The first octet contains the packet type (top 3 bits), TCP
+ * 'push' bit, and flags that indicate which of the 4 TCP sequence
+ * numbers have changed (bottom 5 bits). The next octet is a
+ * conversation number that associates a saved IP/TCP header with
+ * the compressed packet. The next two octets are the TCP checksum
+ * from the original datagram. The next 0 to 15 octets are
+ * sequence number changes, one change per bit set in the header
+ * (there may be no changes and there are two special cases where
+ * the receiver implicitly knows what changed -- see below).
+ *
+ * There are 5 numbers which can change (they are always inserted
+ * in the following order): TCP urgent pointer, window,
+ * acknowlegement, sequence number and IP ID. (The urgent pointer
+ * is different from the others in that its value is sent, not the
+ * change in value.) Since typical use of SLIP links is biased
+ * toward small packets (see comments on MTU/MSS below), changes
+ * use a variable length coding with one octet for numbers in the
+ * range 1 - 255 and 3 octets (0, MSB, LSB) for numbers in the
+ * range 256 - 65535 or 0. (If the change in sequence number or
+ * ack is more than 65535, an uncompressed packet is sent.)
+ */
+
+/*
+ * Packet types (must not conflict with IP protocol version)
+ *
+ * The top nibble of the first octet is the packet type. There are
+ * three possible types: IP (not proto TCP or tcp with one of the
+ * control flags set); uncompressed TCP (a normal IP/TCP packet but
+ * with the 8-bit protocol field replaced by an 8-bit connection id --
+ * this type of packet syncs the sender & receiver); and compressed
+ * TCP (described above).
+ *
+ * LSB of 4-bit field is TCP "PUSH" bit (a worthless anachronism) and
+ * is logically part of the 4-bit "changes" field that follows. Top
+ * three bits are actual packet type. For backward compatibility
+ * and in the interest of conserving bits, numbers are chosen so the
+ * IP protocol version number (4) which normally appears in this nibble
+ * means "IP packet".
+ */
+
+/* packet types */
+#define TYPE_IP 0x40
+#define TYPE_UNCOMPRESSED_TCP 0x70
+#define TYPE_COMPRESSED_TCP 0x80
+#define TYPE_ERROR 0x00
+
+/* Bits in first octet of compressed packet */
+#define NEW_C 0x40 /* flag bits for what changed in a packet */
+#define NEW_I 0x20
+#define NEW_S 0x08
+#define NEW_A 0x04
+#define NEW_W 0x02
+#define NEW_U 0x01
+
+/* reserved, special-case values of above */
+#define SPECIAL_I (NEW_S|NEW_W|NEW_U) /* echoed interactive traffic */
+#define SPECIAL_D (NEW_S|NEW_A|NEW_W|NEW_U) /* unidirectional data */
+#define SPECIALS_MASK (NEW_S|NEW_A|NEW_W|NEW_U)
+
+#define TCP_PUSH_BIT 0x10
+
+
+/*
+ * "state" data for each active tcp conversation on the wire. This is
+ * basically a copy of the entire IP/TCP header from the last packet
+ * we saw from the conversation together with a small identifier
+ * the transmit & receive ends of the line use to locate saved header.
+ */
+struct cstate {
+ struct cstate *cs_next; /* next most recently used cstate (xmit only) */
+ u_short cs_hlen; /* size of hdr (receive only) */
+ u_char cs_id; /* connection # associated with this state */
+ u_char cs_filler;
+ union {
+ char csu_hdr[MAX_HDR];
+ struct ip csu_ip; /* ip/tcp hdr from most recent packet */
+ } slcs_u;
+};
+#define cs_ip slcs_u.csu_ip
+#define cs_hdr slcs_u.csu_hdr
+
+/*
+ * all the state data for one serial line (we need one of these
+ * per line).
+ */
+struct vjcompress {
+ struct cstate *last_cs; /* most recently used tstate */
+ u_char last_recv; /* last rcvd conn. id */
+ u_char last_xmit; /* last sent conn. id */
+ u_short flags;
+#ifndef SL_NO_STATS
+ int sls_packets; /* outbound packets */
+ int sls_compressed; /* outbound compressed packets */
+ int sls_searches; /* searches for connection state */
+ int sls_misses; /* times couldn't find conn. state */
+ int sls_uncompressedin; /* inbound uncompressed packets */
+ int sls_compressedin; /* inbound compressed packets */
+ int sls_errorin; /* inbound unknown type packets */
+ int sls_tossed; /* inbound packets tossed because of error */
+#endif
+ struct cstate tstate[MAX_STATES]; /* xmit connection states */
+ struct cstate rstate[MAX_STATES]; /* receive connection states */
+};
+/* flag values */
+#define SLF_TOSS 1 /* tossing rcvd frames because of input err */
+
+void vj_compress_init __P((struct vjcompress *, int));
+u_int vj_compress_tcp __P((struct mbuf *,
+ struct ip *, struct vjcompress *, int));
+int vj_uncompress_tcp __P((u_char **, int, u_int, struct vjcompress *));
+int vj_uncompress_tcp_core __P((u_char *, int, int, u_int,
+ struct vjcompress *, u_char **, u_int *));
+
+#endif /* _NET_PPPCOMPRESS_H_ */
diff --git a/cpukit/libnetworking/net/radix.c b/cpukit/libnetworking/net/radix.c
new file mode 100644
index 0000000000..e3a47b9095
--- /dev/null
+++ b/cpukit/libnetworking/net/radix.c
@@ -0,0 +1,1078 @@
+/*
+ * Copyright (c) 1988, 1989, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)radix.c 8.5 (Berkeley) 5/19/95
+ * $FreeBSD: src/sys/net/radix.c,v 1.32 2003/09/22 23:24:18 peter Exp $
+ */
+
+/*
+ * Routines to build and maintain radix trees for routing lookups.
+ */
+#ifndef _RADIX_H_
+#include <sys/param.h>
+#ifdef _KERNEL
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#define M_DONTWAIT M_NOWAIT
+#include <sys/domain.h>
+#else
+#include <stdlib.h>
+#endif
+#include <sys/syslog.h>
+#include <net/radix.h>
+#endif
+
+static int rn_walktree_from(struct radix_node_head *h, void *a, void *m,
+ walktree_f_t *f, void *w);
+static int rn_walktree(struct radix_node_head *, walktree_f_t *, void *);
+static struct radix_node
+ *rn_insert(void *, struct radix_node_head *, int *,
+ struct radix_node [2]),
+ *rn_newpair(void *, int, struct radix_node[2]),
+ *rn_search(void *, struct radix_node *),
+ *rn_search_m(void *, struct radix_node *, void *);
+
+static int max_keylen;
+static struct radix_mask *rn_mkfreelist;
+static struct radix_node_head *mask_rnhead;
+static char *addmask_key;
+static char normal_chars[] = {0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, -1};
+static char *rn_zeros, *rn_ones;
+
+#define rn_masktop (mask_rnhead->rnh_treetop)
+#undef Bcmp
+#define Bcmp(a, b, l) \
+ (l == 0 ? 0 : bcmp((caddr_t)(a), (caddr_t)(b), (u_long)l))
+
+static int rn_lexobetter(void *m_arg, void *n_arg);
+static struct radix_mask *
+ rn_new_radix_mask(struct radix_node *tt,
+ struct radix_mask *next);
+static int rn_satisfies_leaf(char *trial, struct radix_node *leaf,
+ int skip);
+
+/*
+ * The data structure for the keys is a radix tree with one way
+ * branching removed. The index rn_bit at an internal node n represents a bit
+ * position to be tested. The tree is arranged so that all descendants
+ * of a node n have keys whose bits all agree up to position rn_bit - 1.
+ * (We say the index of n is rn_bit.)
+ *
+ * There is at least one descendant which has a one bit at position rn_bit,
+ * and at least one with a zero there.
+ *
+ * A route is determined by a pair of key and mask. We require that the
+ * bit-wise logical and of the key and mask to be the key.
+ * We define the index of a route to associated with the mask to be
+ * the first bit number in the mask where 0 occurs (with bit number 0
+ * representing the highest order bit).
+ *
+ * We say a mask is normal if every bit is 0, past the index of the mask.
+ * If a node n has a descendant (k, m) with index(m) == index(n) == rn_bit,
+ * and m is a normal mask, then the route applies to every descendant of n.
+ * If the index(m) < rn_bit, this implies the trailing last few bits of k
+ * before bit b are all 0, (and hence consequently true of every descendant
+ * of n), so the route applies to all descendants of the node as well.
+ *
+ * Similar logic shows that a non-normal mask m such that
+ * index(m) <= index(n) could potentially apply to many children of n.
+ * Thus, for each non-host route, we attach its mask to a list at an internal
+ * node as high in the tree as we can go.
+ *
+ * The present version of the code makes use of normal routes in short-
+ * circuiting an explict mask and compare operation when testing whether
+ * a key satisfies a normal route, and also in remembering the unique leaf
+ * that governs a subtree.
+ */
+
+static struct radix_node *
+rn_search(v_arg, head)
+ void *v_arg;
+ struct radix_node *head;
+{
+ register struct radix_node *x;
+ register caddr_t v;
+
+ for (x = head, v = v_arg; x->rn_bit >= 0;) {
+ if (x->rn_bmask & v[x->rn_offset])
+ x = x->rn_right;
+ else
+ x = x->rn_left;
+ }
+ return (x);
+}
+
+static struct radix_node *
+rn_search_m(v_arg, head, m_arg)
+ struct radix_node *head;
+ void *v_arg, *m_arg;
+{
+ register struct radix_node *x;
+ register caddr_t v = v_arg, m = m_arg;
+
+ for (x = head; x->rn_bit >= 0;) {
+ if ((x->rn_bmask & m[x->rn_offset]) &&
+ (x->rn_bmask & v[x->rn_offset]))
+ x = x->rn_right;
+ else
+ x = x->rn_left;
+ }
+ return x;
+}
+
+int
+rn_refines(m_arg, n_arg)
+ void *m_arg, *n_arg;
+{
+ register caddr_t m = m_arg, n = n_arg;
+ register caddr_t lim, lim2 = lim = n + *(u_char *)n;
+ int longer = (*(u_char *)n++) - (int)(*(u_char *)m++);
+ int masks_are_equal = 1;
+
+ if (longer > 0)
+ lim -= longer;
+ while (n < lim) {
+ if (*n & ~(*m))
+ return 0;
+ if (*n++ != *m++)
+ masks_are_equal = 0;
+ }
+ while (n < lim2)
+ if (*n++)
+ return 0;
+ if (masks_are_equal && (longer < 0))
+ for (lim2 = m - longer; m < lim2; )
+ if (*m++)
+ return 1;
+ return (!masks_are_equal);
+}
+
+struct radix_node *
+rn_lookup(v_arg, m_arg, head)
+ void *v_arg, *m_arg;
+ struct radix_node_head *head;
+{
+ register struct radix_node *x;
+ caddr_t netmask = 0;
+
+ if (m_arg) {
+ x = rn_addmask(m_arg, 1, head->rnh_treetop->rn_offset);
+ if (x == 0)
+ return (0);
+ netmask = x->rn_key;
+ }
+ x = rn_match(v_arg, head);
+ if (x && netmask) {
+ while (x && x->rn_mask != netmask)
+ x = x->rn_dupedkey;
+ }
+ return x;
+}
+
+static int
+rn_satisfies_leaf(trial, leaf, skip)
+ char *trial;
+ register struct radix_node *leaf;
+ int skip;
+{
+ register char *cp = trial, *cp2 = leaf->rn_key, *cp3 = leaf->rn_mask;
+ char *cplim;
+ int length = min(*(u_char *)cp, *(u_char *)cp2);
+
+ if (cp3 == 0)
+ cp3 = rn_ones;
+ else
+ length = min(length, *(u_char *)cp3);
+ cplim = cp + length; cp3 += skip; cp2 += skip;
+ for (cp += skip; cp < cplim; cp++, cp2++, cp3++)
+ if ((*cp ^ *cp2) & *cp3)
+ return 0;
+ return 1;
+}
+
+struct radix_node *
+rn_match(v_arg, head)
+ void *v_arg;
+ struct radix_node_head *head;
+{
+ caddr_t v = v_arg;
+ register struct radix_node *t = head->rnh_treetop, *x;
+ register caddr_t cp = v, cp2;
+ caddr_t cplim;
+ struct radix_node *saved_t, *top = t;
+ int off = t->rn_offset, vlen = *(u_char *)cp, matched_off;
+ register int test, b, rn_bit;
+
+ /*
+ * Open code rn_search(v, top) to avoid overhead of extra
+ * subroutine call.
+ */
+ for (; t->rn_bit >= 0; ) {
+ if (t->rn_bmask & cp[t->rn_offset])
+ t = t->rn_right;
+ else
+ t = t->rn_left;
+ }
+ /*
+ * See if we match exactly as a host destination
+ * or at least learn how many bits match, for normal mask finesse.
+ *
+ * It doesn't hurt us to limit how many bytes to check
+ * to the length of the mask, since if it matches we had a genuine
+ * match and the leaf we have is the most specific one anyway;
+ * if it didn't match with a shorter length it would fail
+ * with a long one. This wins big for class B&C netmasks which
+ * are probably the most common case...
+ */
+ if (t->rn_mask)
+ vlen = *(u_char *)t->rn_mask;
+ cp += off; cp2 = t->rn_key + off; cplim = v + vlen;
+ for (; cp < cplim; cp++, cp2++)
+ if (*cp != *cp2)
+ goto on1;
+ /*
+ * This extra grot is in case we are explicitly asked
+ * to look up the default. Ugh!
+ *
+ * Never return the root node itself, it seems to cause a
+ * lot of confusion.
+ */
+ if (t->rn_flags & RNF_ROOT)
+ t = t->rn_dupedkey;
+ return t;
+on1:
+ test = (*cp ^ *cp2) & 0xff; /* find first bit that differs */
+ for (b = 7; (test >>= 1) > 0;)
+ b--;
+ matched_off = cp - v;
+ b += matched_off << 3;
+ rn_bit = -1 - b;
+ /*
+ * If there is a host route in a duped-key chain, it will be first.
+ */
+ if ((saved_t = t)->rn_mask == 0)
+ t = t->rn_dupedkey;
+ for (; t; t = t->rn_dupedkey)
+ /*
+ * Even if we don't match exactly as a host,
+ * we may match if the leaf we wound up at is
+ * a route to a net.
+ */
+ if (t->rn_flags & RNF_NORMAL) {
+ if (rn_bit <= t->rn_bit)
+ return t;
+ } else if (rn_satisfies_leaf(v, t, matched_off))
+ return t;
+ t = saved_t;
+ /* start searching up the tree */
+ do {
+ register struct radix_mask *m;
+ t = t->rn_parent;
+ m = t->rn_mklist;
+ if (m) {
+ /*
+ * If non-contiguous masks ever become important
+ * we can restore the masking and open coding of
+ * the search and satisfaction test and put the
+ * calculation of "off" back before the "do".
+ */
+ do {
+ if (m->rm_flags & RNF_NORMAL) {
+ if (rn_bit <= m->rm_bit)
+ return (m->rm_leaf);
+ } else {
+ off = min(t->rn_offset, matched_off);
+ x = rn_search_m(v, t, m->rm_mask);
+ while (x && x->rn_mask != m->rm_mask)
+ x = x->rn_dupedkey;
+ if (x && rn_satisfies_leaf(v, x, off))
+ return x;
+ }
+ m = m->rm_mklist;
+ } while (m);
+ }
+ } while (t != top);
+ return 0;
+}
+
+#ifdef RN_DEBUG
+int rn_nodenum;
+struct radix_node *rn_clist;
+int rn_saveinfo;
+int rn_debug = 1;
+#endif
+
+static struct radix_node *
+rn_newpair(v, b, nodes)
+ void *v;
+ int b;
+ struct radix_node nodes[2];
+{
+ register struct radix_node *tt = nodes, *t = tt + 1;
+ t->rn_bit = b;
+ t->rn_bmask = 0x80 >> (b & 7);
+ t->rn_left = tt;
+ t->rn_offset = b >> 3;
+ tt->rn_bit = -1;
+ tt->rn_key = (caddr_t)v;
+ tt->rn_parent = t;
+ tt->rn_flags = t->rn_flags = RNF_ACTIVE;
+#ifdef RN_DEBUG
+ tt->rn_info = rn_nodenum++; t->rn_info = rn_nodenum++;
+ tt->rn_twin = t;
+ tt->rn_ybro = rn_clist;
+ rn_clist = tt;
+#endif
+ return t;
+}
+
+static struct radix_node *
+rn_insert(v_arg, head, dupentry, nodes)
+ void *v_arg;
+ struct radix_node_head *head;
+ int *dupentry;
+ struct radix_node nodes[2];
+{
+ caddr_t v = v_arg;
+ struct radix_node *top = head->rnh_treetop;
+ int head_off = top->rn_offset, vlen = (int)*((u_char *)v);
+ register struct radix_node *t = rn_search(v_arg, top);
+ register caddr_t cp = v + head_off;
+ register int b;
+ struct radix_node *tt;
+ /*
+ * Find first bit at which v and t->rn_key differ
+ */
+ {
+ register caddr_t cp2 = t->rn_key + head_off;
+ register int cmp_res;
+ caddr_t cplim = v + vlen;
+
+ while (cp < cplim)
+ if (*cp2++ != *cp++)
+ goto on1;
+ *dupentry = 1;
+ return t;
+on1:
+ *dupentry = 0;
+ cmp_res = (cp[-1] ^ cp2[-1]) & 0xff;
+ for (b = (cp - v) << 3; cmp_res; b--)
+ cmp_res >>= 1;
+ }
+ {
+ register struct radix_node *p, *x = top;
+ cp = v;
+ do {
+ p = x;
+ if (cp[x->rn_offset] & x->rn_bmask)
+ x = x->rn_right;
+ else
+ x = x->rn_left;
+ } while (b > (unsigned) x->rn_bit);
+ /* x->rn_bit < b && x->rn_bit >= 0 */
+#ifdef RN_DEBUG
+ if (rn_debug)
+ log(LOG_DEBUG, "rn_insert: Going In:\n"), traverse(p);
+#endif
+ t = rn_newpair(v_arg, b, nodes);
+ tt = t->rn_left;
+ if ((cp[p->rn_offset] & p->rn_bmask) == 0)
+ p->rn_left = t;
+ else
+ p->rn_right = t;
+ x->rn_parent = t;
+ t->rn_parent = p; /* frees x, p as temp vars below */
+ if ((cp[t->rn_offset] & t->rn_bmask) == 0) {
+ t->rn_right = x;
+ } else {
+ t->rn_right = tt;
+ t->rn_left = x;
+ }
+#ifdef RN_DEBUG
+ if (rn_debug)
+ log(LOG_DEBUG, "rn_insert: Coming Out:\n"), traverse(p);
+#endif
+ }
+ return (tt);
+}
+
+struct radix_node *
+rn_addmask(n_arg, search, skip)
+ int search, skip;
+ void *n_arg;
+{
+ caddr_t netmask = (caddr_t)n_arg;
+ register struct radix_node *x;
+ register caddr_t cp, cplim;
+ register int b = 0, mlen, j;
+ int maskduplicated, m0, isnormal;
+ struct radix_node *saved_x;
+ static int last_zeroed = 0;
+
+ if ((mlen = *(u_char *)netmask) > max_keylen)
+ mlen = max_keylen;
+ if (skip == 0)
+ skip = 1;
+ if (mlen <= skip)
+ return (mask_rnhead->rnh_nodes);
+ if (skip > 1)
+ Bcopy(rn_ones + 1, addmask_key + 1, skip - 1);
+ if ((m0 = mlen) > skip)
+ Bcopy(netmask + skip, addmask_key + skip, mlen - skip);
+ /*
+ * Trim trailing zeroes.
+ */
+ for (cp = addmask_key + mlen; (cp > addmask_key) && cp[-1] == 0;)
+ cp--;
+ mlen = cp - addmask_key;
+ if (mlen <= skip) {
+ if (m0 >= last_zeroed)
+ last_zeroed = mlen;
+ return (mask_rnhead->rnh_nodes);
+ }
+ if (m0 < last_zeroed)
+ Bzero(addmask_key + m0, last_zeroed - m0);
+ *addmask_key = last_zeroed = mlen;
+ x = rn_search(addmask_key, rn_masktop);
+ if (Bcmp(addmask_key, x->rn_key, mlen) != 0)
+ x = 0;
+ if (x || search)
+ return (x);
+ R_Malloc(x, struct radix_node *, max_keylen + 2 * sizeof (*x));
+ if ((saved_x = x) == 0)
+ return (0);
+ Bzero(x, max_keylen + 2 * sizeof (*x));
+ netmask = cp = (caddr_t)(x + 2);
+ Bcopy(addmask_key, cp, mlen);
+ x = rn_insert(cp, mask_rnhead, &maskduplicated, x);
+ if (maskduplicated) {
+ log(LOG_ERR, "rn_addmask: mask impossibly already in tree");
+ Free(saved_x);
+ return (x);
+ }
+ /*
+ * Calculate index of mask, and check for normalcy.
+ */
+ cplim = netmask + mlen; isnormal = 1;
+ for (cp = netmask + skip; (cp < cplim) && *(u_char *)cp == 0xff;)
+ cp++;
+ if (cp != cplim) {
+ for (j = 0x80; (j & *cp) != 0; j >>= 1)
+ b++;
+ if (*cp != normal_chars[b] || cp != (cplim - 1))
+ isnormal = 0;
+ }
+ b += (cp - netmask) << 3;
+ x->rn_bit = -1 - b;
+ if (isnormal)
+ x->rn_flags |= RNF_NORMAL;
+ return (x);
+}
+
+static int /* XXX: arbitrary ordering for non-contiguous masks */
+rn_lexobetter(m_arg, n_arg)
+ void *m_arg, *n_arg;
+{
+ register u_char *mp = m_arg, *np = n_arg, *lim;
+
+ if (*mp > *np)
+ return 1; /* not really, but need to check longer one first */
+ if (*mp == *np)
+ for (lim = mp + *mp; mp < lim;)
+ if (*mp++ > *np++)
+ return 1;
+ return 0;
+}
+
+static struct radix_mask *
+rn_new_radix_mask(tt, next)
+ register struct radix_node *tt;
+ register struct radix_mask *next;
+{
+ register struct radix_mask *m;
+
+ MKGet(m);
+ if (m == 0) {
+ log(LOG_ERR, "Mask for route not entered\n");
+ return (0);
+ }
+ Bzero(m, sizeof *m);
+ m->rm_bit = tt->rn_bit;
+ m->rm_flags = tt->rn_flags;
+ if (tt->rn_flags & RNF_NORMAL)
+ m->rm_leaf = tt;
+ else
+ m->rm_mask = tt->rn_mask;
+ m->rm_mklist = next;
+ tt->rn_mklist = m;
+ return m;
+}
+
+struct radix_node *
+rn_addroute(v_arg, n_arg, head, treenodes)
+ void *v_arg, *n_arg;
+ struct radix_node_head *head;
+ struct radix_node treenodes[2];
+{
+ caddr_t v = (caddr_t)v_arg, netmask = (caddr_t)n_arg;
+ register struct radix_node *t, *x = 0, *tt;
+ struct radix_node *saved_tt, *top = head->rnh_treetop;
+ short b = 0, b_leaf = 0;
+ int keyduplicated;
+ caddr_t mmask;
+ struct radix_mask *m, **mp;
+
+ /*
+ * In dealing with non-contiguous masks, there may be
+ * many different routes which have the same mask.
+ * We will find it useful to have a unique pointer to
+ * the mask to speed avoiding duplicate references at
+ * nodes and possibly save time in calculating indices.
+ */
+ if (netmask) {
+ if ((x = rn_addmask(netmask, 0, top->rn_offset)) == 0)
+ return (0);
+ b_leaf = x->rn_bit;
+ b = -1 - x->rn_bit;
+ netmask = x->rn_key;
+ }
+ /*
+ * Deal with duplicated keys: attach node to previous instance
+ */
+ saved_tt = tt = rn_insert(v, head, &keyduplicated, treenodes);
+ if (keyduplicated) {
+ for (t = tt; tt; t = tt, tt = tt->rn_dupedkey) {
+ if (tt->rn_mask == netmask)
+ return (0);
+ if (netmask == 0 ||
+ (tt->rn_mask &&
+ ((b_leaf < tt->rn_bit) /* index(netmask) > node */
+ || rn_refines(netmask, tt->rn_mask)
+ || rn_lexobetter(netmask, tt->rn_mask))))
+ break;
+ }
+ /*
+ * If the mask is not duplicated, we wouldn't
+ * find it among possible duplicate key entries
+ * anyway, so the above test doesn't hurt.
+ *
+ * We sort the masks for a duplicated key the same way as
+ * in a masklist -- most specific to least specific.
+ * This may require the unfortunate nuisance of relocating
+ * the head of the list.
+ *
+ * We also reverse, or doubly link the list through the
+ * parent pointer.
+ */
+ if (tt == saved_tt) {
+ struct radix_node *xx = x;
+ /* link in at head of list */
+ (tt = treenodes)->rn_dupedkey = t;
+ tt->rn_flags = t->rn_flags;
+ tt->rn_parent = x = t->rn_parent;
+ t->rn_parent = tt; /* parent */
+ if (x->rn_left == t)
+ x->rn_left = tt;
+ else
+ x->rn_right = tt;
+ saved_tt = tt; x = xx;
+ } else {
+ (tt = treenodes)->rn_dupedkey = t->rn_dupedkey;
+ t->rn_dupedkey = tt;
+ tt->rn_parent = t; /* parent */
+ if (tt->rn_dupedkey) /* parent */
+ tt->rn_dupedkey->rn_parent = tt; /* parent */
+ }
+#ifdef RN_DEBUG
+ t=tt+1; tt->rn_info = rn_nodenum++; t->rn_info = rn_nodenum++;
+ tt->rn_twin = t; tt->rn_ybro = rn_clist; rn_clist = tt;
+#endif
+ tt->rn_key = (caddr_t) v;
+ tt->rn_bit = -1;
+ tt->rn_flags = RNF_ACTIVE;
+ }
+ /*
+ * Put mask in tree.
+ */
+ if (netmask) {
+ tt->rn_mask = netmask;
+ tt->rn_bit = x->rn_bit;
+ tt->rn_flags |= x->rn_flags & RNF_NORMAL;
+ }
+ t = saved_tt->rn_parent;
+ if (keyduplicated)
+ goto on2;
+ b_leaf = -1 - t->rn_bit;
+ if (t->rn_right == saved_tt)
+ x = t->rn_left;
+ else
+ x = t->rn_right;
+ /* Promote general routes from below */
+ if (x->rn_bit < 0) {
+ for (mp = &t->rn_mklist; x; x = x->rn_dupedkey)
+ if (x->rn_mask && (x->rn_bit >= b_leaf) && x->rn_mklist == 0) {
+ *mp = m = rn_new_radix_mask(x, 0);
+ if (m)
+ mp = &m->rm_mklist;
+ }
+ } else if (x->rn_mklist) {
+ /*
+ * Skip over masks whose index is > that of new node
+ */
+ for (mp = &x->rn_mklist; (m = *mp); mp = &m->rm_mklist)
+ if (m->rm_bit >= b_leaf)
+ break;
+ t->rn_mklist = m; *mp = 0;
+ }
+on2:
+ /* Add new route to highest possible ancestor's list */
+ if ((netmask == 0) || (b > t->rn_bit ))
+ return tt; /* can't lift at all */
+ b_leaf = tt->rn_bit;
+ do {
+ x = t;
+ t = t->rn_parent;
+ } while (b <= t->rn_bit && x != top);
+ /*
+ * Search through routes associated with node to
+ * insert new route according to index.
+ * Need same criteria as when sorting dupedkeys to avoid
+ * double loop on deletion.
+ */
+ for (mp = &x->rn_mklist; (m = *mp); mp = &m->rm_mklist) {
+ if (m->rm_bit < b_leaf)
+ continue;
+ if (m->rm_bit > b_leaf)
+ break;
+ if (m->rm_flags & RNF_NORMAL) {
+ mmask = m->rm_leaf->rn_mask;
+ if (tt->rn_flags & RNF_NORMAL) {
+ log(LOG_ERR,
+ "Non-unique normal route, mask not entered\n");
+ return tt;
+ }
+ } else
+ mmask = m->rm_mask;
+ if (mmask == netmask) {
+ m->rm_refs++;
+ tt->rn_mklist = m;
+ return tt;
+ }
+ if (rn_refines(netmask, mmask)
+ || rn_lexobetter(netmask, mmask))
+ break;
+ }
+ *mp = rn_new_radix_mask(tt, *mp);
+ return tt;
+}
+
+struct radix_node *
+rn_delete(v_arg, netmask_arg, head)
+ void *v_arg, *netmask_arg;
+ struct radix_node_head *head;
+{
+ register struct radix_node *t, *p, *x, *tt;
+ struct radix_mask *m, *saved_m, **mp;
+ struct radix_node *dupedkey, *saved_tt, *top;
+ caddr_t v, netmask;
+ int b, head_off, vlen;
+
+ v = v_arg;
+ netmask = netmask_arg;
+ x = head->rnh_treetop;
+ tt = rn_search(v, x);
+ head_off = x->rn_offset;
+ vlen = *(u_char *)v;
+ saved_tt = tt;
+ top = x;
+ if (tt == 0 ||
+ Bcmp(v + head_off, tt->rn_key + head_off, vlen - head_off))
+ return (0);
+ /*
+ * Delete our route from mask lists.
+ */
+ if (netmask) {
+ if ((x = rn_addmask(netmask, 1, head_off)) == 0)
+ return (0);
+ netmask = x->rn_key;
+ while (tt->rn_mask != netmask)
+ if ((tt = tt->rn_dupedkey) == 0)
+ return (0);
+ }
+ if (tt->rn_mask == 0 || (saved_m = m = tt->rn_mklist) == 0)
+ goto on1;
+ if (tt->rn_flags & RNF_NORMAL) {
+ if (m->rm_leaf != tt || m->rm_refs > 0) {
+ log(LOG_ERR, "rn_delete: inconsistent annotation\n");
+ return 0; /* dangling ref could cause disaster */
+ }
+ } else {
+ if (m->rm_mask != tt->rn_mask) {
+ log(LOG_ERR, "rn_delete: inconsistent annotation\n");
+ goto on1;
+ }
+ if (--m->rm_refs >= 0)
+ goto on1;
+ }
+ b = -1 - tt->rn_bit;
+ t = saved_tt->rn_parent;
+ if (b > t->rn_bit)
+ goto on1; /* Wasn't lifted at all */
+ do {
+ x = t;
+ t = t->rn_parent;
+ } while (b <= t->rn_bit && x != top);
+ for (mp = &x->rn_mklist; (m = *mp); mp = &m->rm_mklist)
+ if (m == saved_m) {
+ *mp = m->rm_mklist;
+ MKFree(m);
+ break;
+ }
+ if (m == 0) {
+ log(LOG_ERR, "rn_delete: couldn't find our annotation\n");
+ if (tt->rn_flags & RNF_NORMAL)
+ return (0); /* Dangling ref to us */
+ }
+on1:
+ /*
+ * Eliminate us from tree
+ */
+ if (tt->rn_flags & RNF_ROOT)
+ return (0);
+#ifdef RN_DEBUG
+ /* Get us out of the creation list */
+ for (t = rn_clist; t && t->rn_ybro != tt; t = t->rn_ybro) {}
+ if (t) t->rn_ybro = tt->rn_ybro;
+#endif
+ t = tt->rn_parent;
+ dupedkey = saved_tt->rn_dupedkey;
+ if (dupedkey) {
+ /*
+ * Here, tt is the deletion target and
+ * saved_tt is the head of the dupekey chain.
+ */
+ if (tt == saved_tt) {
+ /* remove from head of chain */
+ x = dupedkey; x->rn_parent = t;
+ if (t->rn_left == tt)
+ t->rn_left = x;
+ else
+ t->rn_right = x;
+ } else {
+ /* find node in front of tt on the chain */
+ for (x = p = saved_tt; p && p->rn_dupedkey != tt;)
+ p = p->rn_dupedkey;
+ if (p) {
+ p->rn_dupedkey = tt->rn_dupedkey;
+ if (tt->rn_dupedkey) /* parent */
+ tt->rn_dupedkey->rn_parent = p;
+ /* parent */
+ } else log(LOG_ERR, "rn_delete: couldn't find us\n");
+ }
+ t = tt + 1;
+ if (t->rn_flags & RNF_ACTIVE) {
+#ifndef RN_DEBUG
+ *++x = *t;
+ p = t->rn_parent;
+#else
+ b = t->rn_info;
+ *++x = *t;
+ t->rn_info = b;
+ p = t->rn_parent;
+#endif
+ if (p->rn_left == t)
+ p->rn_left = x;
+ else
+ p->rn_right = x;
+ x->rn_left->rn_parent = x;
+ x->rn_right->rn_parent = x;
+ }
+ goto out;
+ }
+ if (t->rn_left == tt)
+ x = t->rn_right;
+ else
+ x = t->rn_left;
+ p = t->rn_parent;
+ if (p->rn_right == t)
+ p->rn_right = x;
+ else
+ p->rn_left = x;
+ x->rn_parent = p;
+ /*
+ * Demote routes attached to us.
+ */
+ if (t->rn_mklist) {
+ if (x->rn_bit >= 0) {
+ for (mp = &x->rn_mklist; (m = *mp);)
+ mp = &m->rm_mklist;
+ *mp = t->rn_mklist;
+ } else {
+ /* If there are any key,mask pairs in a sibling
+ duped-key chain, some subset will appear sorted
+ in the same order attached to our mklist */
+ for (m = t->rn_mklist; m && x; x = x->rn_dupedkey)
+ if (m == x->rn_mklist) {
+ struct radix_mask *mm = m->rm_mklist;
+ x->rn_mklist = 0;
+ if (--(m->rm_refs) < 0)
+ MKFree(m);
+ m = mm;
+ }
+ if (m)
+ log(LOG_ERR,
+ "rn_delete: Orphaned Mask %p at %p\n",
+ (void *)m, (void *)x);
+ }
+ }
+ /*
+ * We may be holding an active internal node in the tree.
+ */
+ x = tt + 1;
+ if (t != x) {
+#ifndef RN_DEBUG
+ *t = *x;
+#else
+ b = t->rn_info;
+ *t = *x;
+ t->rn_info = b;
+#endif
+ t->rn_left->rn_parent = t;
+ t->rn_right->rn_parent = t;
+ p = x->rn_parent;
+ if (p->rn_left == x)
+ p->rn_left = t;
+ else
+ p->rn_right = t;
+ }
+out:
+ tt->rn_flags &= ~RNF_ACTIVE;
+ tt[1].rn_flags &= ~RNF_ACTIVE;
+ return (tt);
+}
+
+/*
+ * This is the same as rn_walktree() except for the parameters and the
+ * exit.
+ */
+static int
+rn_walktree_from(h, a, m, f, w)
+ struct radix_node_head *h;
+ void *a, *m;
+ walktree_f_t *f;
+ void *w;
+{
+ int error;
+ struct radix_node *base, *next;
+ u_char *xa = (u_char *)a;
+ u_char *xm = (u_char *)m;
+ register struct radix_node *rn, *last = 0 /* shut up gcc */;
+ int stopping = 0;
+ int lastb;
+
+ /*
+ * rn_search_m is sort-of-open-coded here.
+ */
+ /* printf("about to search\n"); */
+ for (rn = h->rnh_treetop; rn->rn_bit >= 0; ) {
+ last = rn;
+ /* printf("rn_bit %d, rn_bmask %x, xm[rn_offset] %x\n",
+ rn->rn_bit, rn->rn_bmask, xm[rn->rn_offset]); */
+ if (!(rn->rn_bmask & xm[rn->rn_offset])) {
+ break;
+ }
+ if (rn->rn_bmask & xa[rn->rn_offset]) {
+ rn = rn->rn_right;
+ } else {
+ rn = rn->rn_left;
+ }
+ }
+ /* printf("done searching\n"); */
+
+ /*
+ * Two cases: either we stepped off the end of our mask,
+ * in which case last == rn, or we reached a leaf, in which
+ * case we want to start from the last node we looked at.
+ * Either way, last is the node we want to start from.
+ */
+ rn = last;
+ lastb = rn->rn_bit;
+
+ /* printf("rn %p, lastb %d\n", rn, lastb);*/
+
+ /*
+ * This gets complicated because we may delete the node
+ * while applying the function f to it, so we need to calculate
+ * the successor node in advance.
+ */
+ while (rn->rn_bit >= 0)
+ rn = rn->rn_left;
+
+ while (!stopping) {
+ /* printf("node %p (%d)\n", rn, rn->rn_bit); */
+ base = rn;
+ /* If at right child go back up, otherwise, go right */
+ while (rn->rn_parent->rn_right == rn
+ && !(rn->rn_flags & RNF_ROOT)) {
+ rn = rn->rn_parent;
+
+ /* if went up beyond last, stop */
+ if (rn->rn_bit < lastb) {
+ stopping = 1;
+ /* printf("up too far\n"); */
+ }
+ }
+
+ /* Find the next *leaf* since next node might vanish, too */
+ for (rn = rn->rn_parent->rn_right; rn->rn_bit >= 0;)
+ rn = rn->rn_left;
+ next = rn;
+ /* Process leaves */
+ while ((rn = base) != 0) {
+ base = rn->rn_dupedkey;
+ /* printf("leaf %p\n", rn); */
+ if (!(rn->rn_flags & RNF_ROOT)
+ && (error = (*f)(rn, w)))
+ return (error);
+ }
+ rn = next;
+
+ if (rn->rn_flags & RNF_ROOT) {
+ /* printf("root, stopping"); */
+ stopping = 1;
+ }
+
+ }
+ return 0;
+}
+
+static int
+rn_walktree(h, f, w)
+ struct radix_node_head *h;
+ walktree_f_t *f;
+ void *w;
+{
+ int error;
+ struct radix_node *base, *next;
+ register struct radix_node *rn = h->rnh_treetop;
+ /*
+ * This gets complicated because we may delete the node
+ * while applying the function f to it, so we need to calculate
+ * the successor node in advance.
+ */
+ /* First time through node, go left */
+ while (rn->rn_bit >= 0)
+ rn = rn->rn_left;
+ for (;;) {
+ base = rn;
+ /* If at right child go back up, otherwise, go right */
+ while (rn->rn_parent->rn_right == rn
+ && (rn->rn_flags & RNF_ROOT) == 0)
+ rn = rn->rn_parent;
+ /* Find the next *leaf* since next node might vanish, too */
+ for (rn = rn->rn_parent->rn_right; rn->rn_bit >= 0;)
+ rn = rn->rn_left;
+ next = rn;
+ /* Process leaves */
+ while ((rn = base)) {
+ base = rn->rn_dupedkey;
+ if (!(rn->rn_flags & RNF_ROOT)
+ && (error = (*f)(rn, w)))
+ return (error);
+ }
+ rn = next;
+ if (rn->rn_flags & RNF_ROOT)
+ return (0);
+ }
+ /* NOTREACHED */
+}
+
+int
+rn_inithead(head, off)
+ void **head;
+ int off;
+{
+ register struct radix_node_head *rnh;
+ register struct radix_node *t, *tt, *ttt;
+ if (*head)
+ return (1);
+ R_Malloc(rnh, struct radix_node_head *, sizeof (*rnh));
+ if (rnh == 0)
+ return (0);
+ Bzero(rnh, sizeof (*rnh));
+ *head = rnh;
+ t = rn_newpair(rn_zeros, off, rnh->rnh_nodes);
+ ttt = rnh->rnh_nodes + 2;
+ t->rn_right = ttt;
+ t->rn_parent = t;
+ tt = t->rn_left;
+ tt->rn_flags = t->rn_flags = RNF_ROOT | RNF_ACTIVE;
+ tt->rn_bit = -1 - off;
+ *ttt = *tt;
+ ttt->rn_key = rn_ones;
+ rnh->rnh_addaddr = rn_addroute;
+ rnh->rnh_deladdr = rn_delete;
+ rnh->rnh_matchaddr = rn_match;
+ rnh->rnh_lookup = rn_lookup;
+ rnh->rnh_walktree = rn_walktree;
+ rnh->rnh_walktree_from = rn_walktree_from;
+ rnh->rnh_treetop = t;
+ return (1);
+}
+
+void
+rn_init()
+{
+ char *cp, *cplim;
+#ifdef _KERNEL
+ struct domain *dom;
+
+ for (dom = domains; dom; dom = dom->dom_next)
+ if (dom->dom_maxrtkey > max_keylen)
+ max_keylen = dom->dom_maxrtkey;
+#endif
+ if (max_keylen == 0) {
+ log(LOG_ERR,
+ "rn_init: radix functions require max_keylen be set\n");
+ return;
+ }
+ R_Malloc(rn_zeros, char *, 3 * max_keylen);
+ if (rn_zeros == NULL)
+ panic("rn_init");
+ Bzero(rn_zeros, 3 * max_keylen);
+ rn_ones = cp = rn_zeros + max_keylen;
+ addmask_key = cplim = rn_ones + max_keylen;
+ while (cp < cplim)
+ *cp++ = -1;
+ if (rn_inithead((void **)(void*)&mask_rnhead, 0) == 0)
+ panic("rn_init 2");
+}
diff --git a/cpukit/libnetworking/net/radix.h b/cpukit/libnetworking/net/radix.h
new file mode 100644
index 0000000000..d45dadb9ef
--- /dev/null
+++ b/cpukit/libnetworking/net/radix.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 1988, 1989, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)radix.h 8.2 (Berkeley) 10/31/94
+ * $FreeBSD: src/sys/net/radix.h,v 1.23 2003/08/19 17:23:07 sam Exp $
+ */
+
+#ifndef _RADIX_H_
+#define _RADIX_H_
+
+/*
+ * Radix search tree node layout.
+ */
+
+struct radix_node {
+ struct radix_mask *rn_mklist; /* list of masks contained in subtree */
+ struct radix_node *rn_parent; /* parent */
+ short rn_bit; /* bit offset; -1-index(netmask) */
+ char rn_bmask; /* node: mask for bit test*/
+ u_char rn_flags; /* enumerated next */
+#define RNF_NORMAL 1 /* leaf contains normal route */
+#define RNF_ROOT 2 /* leaf is root leaf for tree */
+#define RNF_ACTIVE 4 /* This node is alive (for rtfree) */
+ union {
+ struct { /* leaf only data: */
+ caddr_t rn_Key; /* object of search */
+ caddr_t rn_Mask; /* netmask, if present */
+ struct radix_node *rn_Dupedkey;
+ } rn_leaf;
+ struct { /* node only data: */
+ int rn_Off; /* where to start compare */
+ struct radix_node *rn_L;/* progeny */
+ struct radix_node *rn_R;/* progeny */
+ } rn_node;
+ } rn_u;
+#ifdef RN_DEBUG
+ int rn_info;
+ struct radix_node *rn_twin;
+ struct radix_node *rn_ybro;
+#endif
+};
+
+#define rn_dupedkey rn_u.rn_leaf.rn_Dupedkey
+#define rn_key rn_u.rn_leaf.rn_Key
+#define rn_mask rn_u.rn_leaf.rn_Mask
+#define rn_offset rn_u.rn_node.rn_Off
+#define rn_left rn_u.rn_node.rn_L
+#define rn_right rn_u.rn_node.rn_R
+
+/*
+ * Annotations to tree concerning potential routes applying to subtrees.
+ */
+
+struct radix_mask {
+ short rm_bit; /* bit offset; -1-index(netmask) */
+ char rm_unused; /* cf. rn_bmask */
+ u_char rm_flags; /* cf. rn_flags */
+ struct radix_mask *rm_mklist; /* more masks to try */
+ union {
+ caddr_t rmu_mask; /* the mask */
+ struct radix_node *rmu_leaf; /* for normal routes */
+ } rm_rmu;
+ int rm_refs; /* # of references to this struct */
+};
+
+#define rm_mask rm_rmu.rmu_mask
+#define rm_leaf rm_rmu.rmu_leaf /* extra field would make 32 bytes */
+
+#define MKGet(m) {\
+ if (rn_mkfreelist) {\
+ m = rn_mkfreelist; \
+ rn_mkfreelist = (m)->rm_mklist; \
+ } else \
+ R_Malloc(m, struct radix_mask *, sizeof (*(m))); }\
+
+#define MKFree(m) { (m)->rm_mklist = rn_mkfreelist; rn_mkfreelist = (m);}
+
+typedef int walktree_f_t(struct radix_node *, void *);
+
+struct radix_node_head {
+ struct radix_node *rnh_treetop;
+ int rnh_addrsize; /* permit, but not require fixed keys */
+ int rnh_pktsize; /* permit, but not require fixed keys */
+ struct radix_node *(*rnh_addaddr) /* add based on sockaddr */
+ (void *v, void *mask,
+ struct radix_node_head *head, struct radix_node nodes[]);
+ struct radix_node *(*rnh_addpkt) /* add based on packet hdr */
+ (void *v, void *mask,
+ struct radix_node_head *head, struct radix_node nodes[]);
+ struct radix_node *(*rnh_deladdr) /* remove based on sockaddr */
+ (void *v, void *mask, struct radix_node_head *head);
+ struct radix_node *(*rnh_delpkt) /* remove based on packet hdr */
+ (void *v, void *mask, struct radix_node_head *head);
+ struct radix_node *(*rnh_matchaddr) /* locate based on sockaddr */
+ (void *v, struct radix_node_head *head);
+ struct radix_node *(*rnh_lookup) /* locate based on sockaddr */
+ (void *v, void *mask, struct radix_node_head *head);
+ struct radix_node *(*rnh_matchpkt) /* locate based on packet hdr */
+ (void *v, struct radix_node_head *head);
+ int (*rnh_walktree) /* traverse tree */
+ (struct radix_node_head *head, walktree_f_t *f, void *w);
+ int (*rnh_walktree_from) /* traverse tree below a */
+ (struct radix_node_head *head, void *a, void *m,
+ walktree_f_t *f, void *w);
+ void (*rnh_close) /* do something when the last ref drops */
+ (struct radix_node *rn, struct radix_node_head *head);
+ struct radix_node rnh_nodes[3]; /* empty tree for common case */
+};
+
+#ifndef _KERNEL
+#define Bcmp(a, b, n) bcmp(((char *)(a)), ((char *)(b)), (n))
+#define Bcopy(a, b, n) bcopy(((char *)(a)), ((char *)(b)), (unsigned)(n))
+#define Bzero(p, n) bzero((char *)(p), (int)(n));
+#define R_Malloc(p, t, n) (p = (t) malloc((unsigned int)(n)))
+#define R_Zalloc(p, t, n) (p = (t) calloc(1,(unsigned int)(n)))
+#define Free(p) free((char *)p);
+#else
+#define Bcmp(a, b, n) bcmp(((caddr_t)(a)), ((caddr_t)(b)), (unsigned)(n))
+#define Bcopy(a, b, n) bcopy(((caddr_t)(a)), ((caddr_t)(b)), (unsigned)(n))
+#define Bzero(p, n) bzero((caddr_t)(p), (unsigned)(n));
+#define R_Malloc(p, t, n) (p = (t) malloc((unsigned long)(n), M_RTABLE, M_DONTWAIT))
+#define Free(p) free((caddr_t)p, M_RTABLE);
+#endif /*_KERNEL*/
+
+extern struct radix_node_head *mask_rnhead;
+
+void rn_init(void);
+int rn_inithead(void **, int);
+int rn_refines(void *, void *);
+struct radix_node
+ *rn_addmask(void *, int, int),
+ *rn_addroute (void *, void *, struct radix_node_head *,
+ struct radix_node [2]),
+ *rn_delete(void *, void *, struct radix_node_head *),
+ *rn_lookup (void *v_arg, void *m_arg,
+ struct radix_node_head *head),
+ *rn_match(void *, struct radix_node_head *);
+
+#endif /* _RADIX_H_ */
diff --git a/cpukit/libnetworking/net/raw_cb.c b/cpukit/libnetworking/net/raw_cb.c
new file mode 100644
index 0000000000..0676931cdc
--- /dev/null
+++ b/cpukit/libnetworking/net/raw_cb.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 1980, 1986, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)raw_cb.c 8.1 (Berkeley) 6/10/93
+ * $Id$
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/domain.h>
+#include <sys/protosw.h>
+#include <sys/errno.h>
+
+#include <net/if.h>
+#include <net/route.h>
+#include <net/raw_cb.h>
+#include <netinet/in.h>
+
+/*
+ * Routines to manage the raw protocol control blocks.
+ *
+ * TODO:
+ * hash lookups by protocol family/protocol + address family
+ * take care of unique address problems per AF?
+ * redo address binding to allow wildcards
+ */
+
+struct rawcb rawcb;
+static u_long raw_sendspace = RAWSNDQ;
+static u_long raw_recvspace = RAWRCVQ;
+
+/*
+ * Allocate a control block and a nominal amount
+ * of buffer space for the socket.
+ */
+int
+raw_attach(so, proto)
+ register struct socket *so;
+ int proto;
+{
+ register struct rawcb *rp = sotorawcb(so);
+ int error;
+
+ /*
+ * It is assumed that raw_attach is called
+ * after space has been allocated for the
+ * rawcb.
+ */
+ if (rp == 0)
+ return (ENOBUFS);
+ error = soreserve(so, raw_sendspace, raw_recvspace);
+ if (error)
+ return (error);
+ rp->rcb_socket = so;
+ rp->rcb_proto.sp_family = so->so_proto->pr_domain->dom_family;
+ rp->rcb_proto.sp_protocol = proto;
+ insque(rp, &rawcb);
+ return (0);
+}
+
+/*
+ * Detach the raw connection block and discard
+ * socket resources.
+ */
+void
+raw_detach(rp)
+ register struct rawcb *rp;
+{
+ struct socket *so = rp->rcb_socket;
+
+ so->so_pcb = 0;
+ sofree(so);
+ remque(rp);
+#ifdef notdef
+ if (rp->rcb_laddr)
+ m_freem(dtom(rp->rcb_laddr));
+ rp->rcb_laddr = 0;
+#endif
+ free((caddr_t)(rp), M_PCB);
+}
+
+/*
+ * Disconnect and possibly release resources.
+ */
+void
+raw_disconnect(rp)
+ struct rawcb *rp;
+{
+
+#ifdef notdef
+ if (rp->rcb_faddr)
+ m_freem(dtom(rp->rcb_faddr));
+ rp->rcb_faddr = 0;
+#endif
+ if (rp->rcb_socket->so_state & SS_NOFDREF)
+ raw_detach(rp);
+}
+
+#ifdef notdef
+int
+raw_bind(so, nam)
+ register struct socket *so;
+ struct mbuf *nam;
+{
+ struct sockaddr *addr = mtod(nam, struct sockaddr *);
+ register struct rawcb *rp;
+
+ if (ifnet == 0)
+ return (EADDRNOTAVAIL);
+ rp = sotorawcb(so);
+ nam = m_copym(nam, 0, M_COPYALL, M_WAITOK);
+ rp->rcb_laddr = mtod(nam, struct sockaddr *);
+ return (0);
+}
+#endif
diff --git a/cpukit/libnetworking/net/raw_cb.h b/cpukit/libnetworking/net/raw_cb.h
new file mode 100644
index 0000000000..ee8f14e822
--- /dev/null
+++ b/cpukit/libnetworking/net/raw_cb.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 1980, 1986, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)raw_cb.h 8.1 (Berkeley) 6/10/93
+ * $Id$
+ */
+
+#ifndef _NET_RAW_CB_H_
+#define _NET_RAW_CB_H_
+
+/*
+ * Raw protocol interface control block. Used
+ * to tie a socket to the generic raw interface.
+ */
+struct rawcb {
+ struct rawcb *rcb_next; /* doubly linked list */
+ struct rawcb *rcb_prev;
+ struct socket *rcb_socket; /* back pointer to socket */
+ struct sockaddr *rcb_faddr; /* destination address */
+ struct sockaddr *rcb_laddr; /* socket's address */
+ struct sockproto rcb_proto; /* protocol family, protocol */
+};
+
+#define sotorawcb(so) ((struct rawcb *)(so)->so_pcb)
+
+/*
+ * Nominal space allocated to a raw socket.
+ */
+#define RAWSNDQ 8192
+#define RAWRCVQ 8192
+
+#ifdef _KERNEL
+extern struct rawcb rawcb; /* head of list */
+
+int raw_attach __P((struct socket *, int));
+void raw_ctlinput __P((int, struct sockaddr *, void *));
+void raw_detach __P((struct rawcb *));
+void raw_disconnect __P((struct rawcb *));
+void raw_init __P((void));
+void raw_input __P((struct mbuf *,
+ struct sockproto *, struct sockaddr *, struct sockaddr *));
+int raw_usrreq __P((struct socket *,
+ int, struct mbuf *, struct mbuf *, struct mbuf *));
+#endif
+
+#endif
diff --git a/cpukit/libnetworking/net/raw_usrreq.c b/cpukit/libnetworking/net/raw_usrreq.c
new file mode 100644
index 0000000000..fb4faf4d6d
--- /dev/null
+++ b/cpukit/libnetworking/net/raw_usrreq.c
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 1980, 1986, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)raw_usrreq.c 8.1 (Berkeley) 6/10/93
+ * $Id$
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/domain.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/errno.h>
+
+#include <net/if.h>
+#include <net/route.h>
+#include <net/netisr.h>
+#include <net/raw_cb.h>
+
+/*
+ * Initialize raw connection block q.
+ */
+void
+raw_init()
+{
+
+ rawcb.rcb_next = rawcb.rcb_prev = &rawcb;
+}
+
+
+/*
+ * Raw protocol input routine. Find the socket
+ * associated with the packet(s) and move them over. If
+ * nothing exists for this packet, drop it.
+ */
+/*
+ * Raw protocol interface.
+ */
+void
+raw_input(m0, proto, src, dst)
+ struct mbuf *m0;
+ register struct sockproto *proto;
+ struct sockaddr *src, *dst;
+{
+ register struct rawcb *rp;
+ register struct mbuf *m = m0;
+ register int sockets = 0;
+ struct socket *last;
+
+ last = 0;
+ for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) {
+ if (rp->rcb_proto.sp_family != proto->sp_family)
+ continue;
+ if (rp->rcb_proto.sp_protocol &&
+ rp->rcb_proto.sp_protocol != proto->sp_protocol)
+ continue;
+ /*
+ * We assume the lower level routines have
+ * placed the address in a canonical format
+ * suitable for a structure comparison.
+ *
+ * Note that if the lengths are not the same
+ * the comparison will fail at the first byte.
+ */
+#define equal(a1, a2) \
+ (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0)
+ if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst))
+ continue;
+ if (rp->rcb_faddr && !equal(rp->rcb_faddr, src))
+ continue;
+ if (last) {
+ struct mbuf *n;
+ n = m_copy(m, 0, (int)M_COPYALL);
+ if (n) {
+ if (sbappendaddr(&last->so_rcv, src,
+ n, (struct mbuf *)0) == 0)
+ /* should notify about lost packet */
+ m_freem(n);
+ else {
+ sorwakeup(last);
+ sockets++;
+ }
+ }
+ }
+ last = rp->rcb_socket;
+ }
+ if (last) {
+ if (sbappendaddr(&last->so_rcv, src,
+ m, (struct mbuf *)0) == 0)
+ m_freem(m);
+ else {
+ sorwakeup(last);
+ sockets++;
+ }
+ } else
+ m_freem(m);
+}
+
+/*ARGSUSED*/
+void
+raw_ctlinput(cmd, arg, dummy)
+ int cmd;
+ struct sockaddr *arg;
+ void *dummy;
+{
+
+ if (cmd < 0 || cmd > PRC_NCMDS)
+ return;
+ /* INCOMPLETE */
+}
+
+/*ARGSUSED*/
+int
+raw_usrreq(so, req, m, nam, control)
+ struct socket *so;
+ int req;
+ struct mbuf *m, *nam, *control;
+{
+ register struct rawcb *rp = sotorawcb(so);
+ register int error = 0;
+ int len;
+
+ if (req == PRU_CONTROL)
+ return (EOPNOTSUPP);
+ if (control && control->m_len) {
+ error = EOPNOTSUPP;
+ goto release;
+ }
+ if (rp == 0) {
+ error = EINVAL;
+ goto release;
+ }
+ switch (req) {
+
+ /*
+ * Allocate a raw control block and fill in the
+ * necessary info to allow packets to be routed to
+ * the appropriate raw interface routine.
+ */
+ case PRU_ATTACH:
+ if ((so->so_state & SS_PRIV) == 0) {
+ error = EACCES;
+ break;
+ }
+ error = raw_attach(so, (int)nam);
+ break;
+
+ /*
+ * Destroy state just before socket deallocation.
+ * Flush data or not depending on the options.
+ */
+ case PRU_DETACH:
+ if (rp == 0) {
+ error = ENOTCONN;
+ break;
+ }
+ raw_detach(rp);
+ break;
+
+ /*
+ * If a socket isn't bound to a single address,
+ * the raw input routine will hand it anything
+ * within that protocol family (assuming there's
+ * nothing else around it should go to).
+ */
+ case PRU_CONNECT:
+ error = EINVAL;
+#if 0
+ if (rp->rcb_faddr) {
+ error = EISCONN;
+ break;
+ }
+ nam = m_copym(nam, 0, M_COPYALL, M_WAIT);
+ rp->rcb_faddr = mtod(nam, struct sockaddr *);
+ soisconnected(so);
+#endif
+ break;
+
+ case PRU_BIND:
+ error = EINVAL;
+#if 0
+ if (rp->rcb_laddr) {
+ error = EINVAL; /* XXX */
+ break;
+ }
+ error = raw_bind(so, nam);
+#endif
+ break;
+
+ case PRU_CONNECT2:
+ error = EOPNOTSUPP;
+ goto release;
+
+ case PRU_DISCONNECT:
+ if (rp->rcb_faddr == 0) {
+ error = ENOTCONN;
+ break;
+ }
+ raw_disconnect(rp);
+ soisdisconnected(so);
+ break;
+
+ /*
+ * Mark the connection as being incapable of further input.
+ */
+ case PRU_SHUTDOWN:
+ socantsendmore(so);
+ break;
+
+ /*
+ * Ship a packet out. The appropriate raw output
+ * routine handles any massaging necessary.
+ */
+ case PRU_SEND:
+ if (nam) {
+ if (rp->rcb_faddr) {
+ error = EISCONN;
+ break;
+ }
+ rp->rcb_faddr = mtod(nam, struct sockaddr *);
+ } else if (rp->rcb_faddr == 0) {
+ error = ENOTCONN;
+ break;
+ }
+ error = (*so->so_proto->pr_output)(m, so);
+ m = NULL;
+ if (nam)
+ rp->rcb_faddr = 0;
+ break;
+
+ case PRU_ABORT:
+ raw_disconnect(rp);
+ sofree(so);
+ soisdisconnected(so);
+ break;
+
+ case PRU_SENSE:
+ /*
+ * stat: don't bother with a blocksize.
+ */
+ return (0);
+
+ /*
+ * Not supported.
+ */
+ case PRU_RCVOOB:
+ case PRU_RCVD:
+ return(EOPNOTSUPP);
+
+ case PRU_LISTEN:
+ case PRU_ACCEPT:
+ case PRU_SENDOOB:
+ error = EOPNOTSUPP;
+ break;
+
+ case PRU_SOCKADDR:
+ if (rp->rcb_laddr == 0) {
+ error = EINVAL;
+ break;
+ }
+ len = rp->rcb_laddr->sa_len;
+ bcopy((caddr_t)rp->rcb_laddr, mtod(nam, caddr_t), (unsigned)len);
+ nam->m_len = len;
+ break;
+
+ case PRU_PEERADDR:
+ if (rp->rcb_faddr == 0) {
+ error = ENOTCONN;
+ break;
+ }
+ len = rp->rcb_faddr->sa_len;
+ bcopy((caddr_t)rp->rcb_faddr, mtod(nam, caddr_t), (unsigned)len);
+ nam->m_len = len;
+ break;
+
+ default:
+ panic("raw_usrreq");
+ }
+release:
+ if (m != NULL)
+ m_freem(m);
+ return (error);
+}
diff --git a/cpukit/libnetworking/net/route.c b/cpukit/libnetworking/net/route.c
new file mode 100644
index 0000000000..e9a6eabe8d
--- /dev/null
+++ b/cpukit/libnetworking/net/route.c
@@ -0,0 +1,959 @@
+/*
+ * Copyright (c) 1980, 1986, 1991, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)route.c 8.2 (Berkeley) 11/15/93
+ * $Id$
+ */
+
+#include "opt_mrouting.h"
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/domain.h>
+#include <sys/protosw.h>
+#include <sys/ioctl.h>
+
+#include <net/if.h>
+#include <net/route.h>
+#include <net/raw_cb.h>
+
+#include <netinet/in.h>
+#include <netinet/in_var.h>
+#include <netinet/ip_mroute.h>
+
+#define SA(p) ((struct sockaddr *)(p))
+
+struct route_cb route_cb;
+static struct rtstat rtstat;
+struct radix_node_head *rt_tables[AF_MAX+1];
+
+static int rttrash; /* routes not in table but not freed */
+
+static void rt_maskedcopy __P((struct sockaddr *,
+ struct sockaddr *, struct sockaddr *));
+static void rtable_init __P((void **));
+
+static void
+rtable_init(table)
+ void **table;
+{
+ struct domain *dom;
+ for (dom = domains; dom; dom = dom->dom_next)
+ if (dom->dom_rtattach)
+ dom->dom_rtattach(&table[dom->dom_family],
+ dom->dom_rtoffset);
+}
+
+void
+route_init()
+{
+ rn_init(); /* initialize all zeroes, all ones, mask table */
+ rtable_init((void **)rt_tables);
+}
+
+/*
+ * Packet routing routines.
+ */
+void
+rtalloc(ro)
+ register struct route *ro;
+{
+ if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP))
+ return; /* XXX */
+ ro->ro_rt = rtalloc1(&ro->ro_dst, 1, 0UL);
+}
+
+void
+rtalloc_ign(ro, ignore)
+ register struct route *ro;
+ u_long ignore;
+{
+ if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP))
+ return; /* XXX */
+ ro->ro_rt = rtalloc1(&ro->ro_dst, 1, ignore);
+}
+
+/*
+ * Look up the route that matches the address given
+ * Or, at least try.. Create a cloned route if needed.
+ */
+struct rtentry *
+rtalloc1(dst, report, ignflags)
+ register struct sockaddr *dst;
+ int report;
+ u_long ignflags;
+{
+ register struct radix_node_head *rnh = rt_tables[dst->sa_family];
+ register struct rtentry *rt;
+ register struct radix_node *rn;
+ struct rtentry *newrt = 0;
+ struct rt_addrinfo info;
+ u_long nflags;
+ int s = splnet(), err = 0, msgtype = RTM_MISS;
+
+ /*
+ * Look up the address in the table for that Address Family
+ */
+ if (rnh && (rn = rnh->rnh_matchaddr((caddr_t)dst, rnh)) &&
+ ((rn->rn_flags & RNF_ROOT) == 0)) {
+ /*
+ * If we find it and it's not the root node, then
+ * get a refernce on the rtentry associated.
+ */
+ newrt = rt = (struct rtentry *)rn;
+ nflags = rt->rt_flags & ~ignflags;
+ if (report && (nflags & (RTF_CLONING | RTF_PRCLONING))) {
+ /*
+ * We are apparently adding (report = 0 in delete).
+ * If it requires that it be cloned, do so.
+ * (This implies it wasn't a HOST route.)
+ */
+ err = rtrequest(RTM_RESOLVE, dst, SA(0),
+ SA(0), 0, &newrt);
+ if (err) {
+ /*
+ * If the cloning didn't succeed, maybe
+ * what we have will do. Return that.
+ */
+ newrt = rt;
+ rt->rt_refcnt++;
+ goto miss;
+ }
+ if ((rt = newrt) && (rt->rt_flags & RTF_XRESOLVE)) {
+ /*
+ * If the new route specifies it be
+ * externally resolved, then go do that.
+ */
+ msgtype = RTM_RESOLVE;
+ goto miss;
+ }
+ } else
+ rt->rt_refcnt++;
+ } else {
+ /*
+ * Either we hit the root or couldn't find any match,
+ * Which basically means
+ * "caint get there frm here"
+ */
+ rtstat.rts_unreach++;
+ miss: if (report) {
+ /*
+ * If required, report the failure to the supervising
+ * Authorities.
+ * For a delete, this is not an error. (report == 0)
+ */
+ bzero((caddr_t)&info, sizeof(info));
+ info.rti_info[RTAX_DST] = dst;
+ rt_missmsg(msgtype, &info, 0, err);
+ }
+ }
+ splx(s);
+ return (newrt);
+}
+
+void
+rtfree(rt)
+ register struct rtentry *rt;
+{
+ register struct radix_node_head *rnh =
+ rt_tables[rt_key(rt)->sa_family];
+ register struct ifaddr *ifa;
+
+ if (rt == 0 || rnh == 0)
+ panic("rtfree");
+ rt->rt_refcnt--;
+ if(rnh->rnh_close && rt->rt_refcnt == 0) {
+ rnh->rnh_close((struct radix_node *)rt, rnh);
+ }
+ if (rt->rt_refcnt <= 0 && (rt->rt_flags & RTF_UP) == 0) {
+ if (rt->rt_nodes->rn_flags & (RNF_ACTIVE | RNF_ROOT))
+ panic ("rtfree 2");
+ rttrash--;
+ if (rt->rt_refcnt < 0) {
+ printf("rtfree: %p not freed (neg refs)\n", rt);
+ return;
+ }
+ ifa = rt->rt_ifa;
+ IFAFREE(ifa);
+ if (rt->rt_parent) {
+ RTFREE(rt->rt_parent);
+ }
+ Free(rt_key(rt));
+ Free(rt);
+ }
+}
+
+void
+ifafree(ifa)
+ register struct ifaddr *ifa;
+{
+ if (ifa == NULL)
+ panic("ifafree");
+ if (ifa->ifa_refcnt == 0)
+ free(ifa, M_IFADDR);
+ else
+ ifa->ifa_refcnt--;
+}
+
+/*
+ * Force a routing table entry to the specified
+ * destination to go through the given gateway.
+ * Normally called as a result of a routing redirect
+ * message from the network layer.
+ *
+ * N.B.: must be called at splnet
+ *
+ */
+void
+rtredirect(dst, gateway, netmask, flags, src, rtp)
+ struct sockaddr *dst, *gateway, *netmask, *src;
+ int flags;
+ struct rtentry **rtp;
+{
+ register struct rtentry *rt;
+ int error = 0;
+ short *stat = 0;
+ struct rt_addrinfo info;
+ struct ifaddr *ifa;
+
+ /* verify the gateway is directly reachable */
+ if ((ifa = ifa_ifwithnet(gateway)) == 0) {
+ error = ENETUNREACH;
+ goto out;
+ }
+ rt = rtalloc1(dst, 0, 0UL);
+ /*
+ * If the redirect isn't from our current router for this dst,
+ * it's either old or wrong. If it redirects us to ourselves,
+ * we have a routing loop, perhaps as a result of an interface
+ * going down recently.
+ */
+#define equal(a1, a2) (bcmp((caddr_t)(a1), (caddr_t)(a2), (a1)->sa_len) == 0)
+ if (!(flags & RTF_DONE) && rt &&
+ (!equal(src, rt->rt_gateway) || rt->rt_ifa != ifa))
+ error = EINVAL;
+ else if (ifa_ifwithaddr(gateway))
+ error = EHOSTUNREACH;
+ if (error)
+ goto done;
+ /*
+ * Create a new entry if we just got back a wildcard entry
+ * or the the lookup failed. This is necessary for hosts
+ * which use routing redirects generated by smart gateways
+ * to dynamically build the routing tables.
+ */
+ if ((rt == 0) || (rt_mask(rt) && rt_mask(rt)->sa_len < 2))
+ goto create;
+ /*
+ * Don't listen to the redirect if it's
+ * for a route to an interface.
+ */
+ if (rt->rt_flags & RTF_GATEWAY) {
+ if (((rt->rt_flags & RTF_HOST) == 0) && (flags & RTF_HOST)) {
+ /*
+ * Changing from route to net => route to host.
+ * Create new route, rather than smashing route to net.
+ */
+ create:
+ flags |= RTF_GATEWAY | RTF_DYNAMIC;
+ error = rtrequest((int)RTM_ADD, dst, gateway,
+ netmask, flags,
+ (struct rtentry **)0);
+ stat = &rtstat.rts_dynamic;
+ } else {
+ /*
+ * Smash the current notion of the gateway to
+ * this destination. Should check about netmask!!!
+ */
+ rt->rt_flags |= RTF_MODIFIED;
+ flags |= RTF_MODIFIED;
+ stat = &rtstat.rts_newgateway;
+ rt_setgate(rt, rt_key(rt), gateway);
+ }
+ } else
+ error = EHOSTUNREACH;
+done:
+ if (rt) {
+ if (rtp && !error)
+ *rtp = rt;
+ else
+ rtfree(rt);
+ }
+out:
+ if (error)
+ rtstat.rts_badredirect++;
+ else if (stat != NULL)
+ (*stat)++;
+ bzero((caddr_t)&info, sizeof(info));
+ info.rti_info[RTAX_DST] = dst;
+ info.rti_info[RTAX_GATEWAY] = gateway;
+ info.rti_info[RTAX_NETMASK] = netmask;
+ info.rti_info[RTAX_AUTHOR] = src;
+ rt_missmsg(RTM_REDIRECT, &info, flags, error);
+}
+
+/*
+* Routing table ioctl interface.
+*/
+int
+rtioctl(req, data, p)
+ int req;
+ caddr_t data;
+ struct proc *p;
+{
+#ifdef INET
+ /* Multicast goop, grrr... */
+#ifdef MROUTING
+ return mrt_ioctl(req, data);
+#else
+ return mrt_ioctl(req, data, p);
+#endif
+#else /* INET */
+ return ENXIO;
+#endif /* INET */
+}
+
+struct ifaddr *
+ifa_ifwithroute(flags, dst, gateway)
+ int flags;
+ struct sockaddr *dst, *gateway;
+{
+ register struct ifaddr *ifa;
+ if ((flags & RTF_GATEWAY) == 0) {
+ /*
+ * If we are adding a route to an interface,
+ * and the interface is a pt to pt link
+ * we should search for the destination
+ * as our clue to the interface. Otherwise
+ * we can use the local address.
+ */
+ ifa = 0;
+ if (flags & RTF_HOST) {
+ ifa = ifa_ifwithdstaddr(dst);
+ }
+ if (ifa == 0)
+ ifa = ifa_ifwithaddr(gateway);
+ } else {
+ /*
+ * If we are adding a route to a remote net
+ * or host, the gateway may still be on the
+ * other end of a pt to pt link.
+ */
+ ifa = ifa_ifwithdstaddr(gateway);
+ }
+ if (ifa == 0)
+ ifa = ifa_ifwithnet(gateway);
+ if (ifa == 0) {
+ struct rtentry *rt = rtalloc1(dst, 0, 0UL);
+ if (rt == 0)
+ return (0);
+ rt->rt_refcnt--;
+ if ((ifa = rt->rt_ifa) == 0)
+ return (0);
+ }
+ if (ifa->ifa_addr->sa_family != dst->sa_family) {
+ struct ifaddr *oifa = ifa;
+ ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp);
+ if (ifa == 0)
+ ifa = oifa;
+ }
+ return (ifa);
+}
+
+#define ROUNDUP(a) (a>0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
+
+static int rt_fixdelete(struct radix_node *, void *);
+static int rt_fixchange(struct radix_node *, void *);
+
+struct rtfc_arg {
+ struct rtentry *rt0;
+ struct radix_node_head *rnh;
+};
+
+/*
+ * Do appropriate manipulations of a routing tree given
+ * all the bits of info needed
+ */
+int
+rtrequest(req, dst, gateway, netmask, flags, ret_nrt)
+ int req, flags;
+ struct sockaddr *dst, *gateway, *netmask;
+ struct rtentry **ret_nrt;
+{
+ int s = splnet(); int error = 0;
+ register struct rtentry *rt;
+ register struct radix_node *rn;
+ register struct radix_node_head *rnh;
+ struct ifaddr *ifa;
+ struct sockaddr *ndst;
+#define senderr(x) { error = x ; goto bad; }
+
+ /*
+ * Find the correct routing tree to use for this Address Family
+ */
+ if ((rnh = rt_tables[dst->sa_family]) == 0)
+ senderr(ESRCH);
+ /*
+ * If we are adding a host route then we don't want to put
+ * a netmask in the tree
+ */
+ if (flags & RTF_HOST)
+ netmask = 0;
+ switch (req) {
+ case RTM_DELETE:
+ /*
+ * Remove the item from the tree and return it.
+ * Complain if it is not there and do no more processing.
+ */
+ if ((rn = rnh->rnh_deladdr(dst, netmask, rnh)) == 0)
+ senderr(ESRCH);
+ if (rn->rn_flags & (RNF_ACTIVE | RNF_ROOT))
+ panic ("rtrequest delete");
+ rt = (struct rtentry *)rn;
+
+ /*
+ * Now search what's left of the subtree for any cloned
+ * routes which might have been formed from this node.
+ */
+ if ((rt->rt_flags & RTF_PRCLONING) && netmask) {
+ rnh->rnh_walktree_from(rnh, dst, netmask,
+ rt_fixdelete, rt);
+ }
+
+ /*
+ * Remove any external references we may have.
+ * This might result in another rtentry being freed if
+ * we held it's last reference.
+ */
+ if (rt->rt_gwroute) {
+ rt = rt->rt_gwroute;
+ RTFREE(rt);
+ (rt = (struct rtentry *)rn)->rt_gwroute = 0;
+ }
+
+ /*
+ * NB: RTF_UP must be set during the search above,
+ * because we might delete the last ref, causing
+ * rt to get freed prematurely.
+ */
+ rt->rt_flags &= ~RTF_UP;
+
+ /*
+ * If there is llinfo or similar associated with the
+ * route, give the interface a chance to deal with it..
+ */
+ if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest)
+ ifa->ifa_rtrequest(RTM_DELETE, rt, SA(0));
+ rttrash++;
+ /*
+ * If the caller wants it, then it can have it, but it's up to it
+ * to free the rtentry as we won't be doing it.
+ */
+ if (ret_nrt)
+ *ret_nrt = rt;
+ else if (rt->rt_refcnt <= 0) {
+ rt->rt_refcnt++; /* make a 1->0 transition */
+ rtfree(rt);
+ }
+ break;
+
+ case RTM_RESOLVE:
+ if (ret_nrt == 0 || (rt = *ret_nrt) == 0)
+ senderr(EINVAL);
+ ifa = rt->rt_ifa;
+ flags = rt->rt_flags &
+ ~(RTF_CLONING | RTF_PRCLONING | RTF_STATIC);
+ flags |= RTF_WASCLONED;
+ gateway = rt->rt_gateway;
+ if ((netmask = rt->rt_genmask) == 0)
+ flags |= RTF_HOST;
+ goto makeroute;
+
+ case RTM_ADD:
+ if ((flags & RTF_GATEWAY) && !gateway)
+ panic("rtrequest: GATEWAY but no gateway");
+
+ if ((ifa = ifa_ifwithroute(flags, dst, gateway)) == 0)
+ senderr(ENETUNREACH);
+
+ makeroute:
+ R_Malloc(rt, struct rtentry *, sizeof(*rt));
+ if (rt == 0)
+ senderr(ENOBUFS);
+ Bzero(rt, sizeof(*rt));
+ rt->rt_flags = RTF_UP | flags;
+ if ((error = rt_setgate(rt, dst, gateway))) {
+ Free(rt);
+ senderr(error);
+ }
+ ndst = rt_key(rt);
+ if (netmask) {
+ rt_maskedcopy(dst, ndst, netmask);
+ } else
+ Bcopy(dst, ndst, dst->sa_len);
+
+ /*
+ * This moved from below so that rnh->rnh_addaddr() can
+ * examine the ifa and ifp if it so desires.
+ */
+ ifa->ifa_refcnt++;
+ rt->rt_ifa = ifa;
+ rt->rt_ifp = ifa->ifa_ifp;
+
+ rn = rnh->rnh_addaddr((caddr_t)ndst, (caddr_t)netmask,
+ rnh, rt->rt_nodes);
+ if (rn == 0) {
+ struct rtentry *rt2;
+ /*
+ * Uh-oh, we already have one of these in the tree.
+ * We do a special hack: if the route that's already
+ * there was generated by the protocol-cloning
+ * mechanism, then we just blow it away and retry
+ * the insertion of the new one.
+ */
+ rt2 = rtalloc1(dst, 0, RTF_PRCLONING);
+ if (rt2 && rt2->rt_parent) {
+ rtrequest(RTM_DELETE,
+ (struct sockaddr *)rt_key(rt2),
+ rt2->rt_gateway,
+ rt_mask(rt2), rt2->rt_flags, 0);
+ RTFREE(rt2);
+ rn = rnh->rnh_addaddr((caddr_t)ndst,
+ (caddr_t)netmask,
+ rnh, rt->rt_nodes);
+ } else if (rt2) {
+ RTFREE(rt2);
+ }
+ }
+
+ if (rn == 0) {
+ if (rt->rt_gwroute)
+ rtfree(rt->rt_gwroute);
+ if (rt->rt_ifa) {
+ IFAFREE(rt->rt_ifa);
+ }
+ Free(rt_key(rt));
+ Free(rt);
+ senderr(EEXIST);
+ }
+ rt->rt_parent = 0;
+
+ if (req == RTM_RESOLVE) {
+ rt->rt_rmx = (*ret_nrt)->rt_rmx; /* copy metrics */
+ if ((*ret_nrt)->rt_flags & RTF_PRCLONING) {
+ rt->rt_parent = (*ret_nrt);
+ (*ret_nrt)->rt_refcnt++;
+ }
+ }
+ if (ifa->ifa_rtrequest)
+ ifa->ifa_rtrequest(req, rt, SA(ret_nrt ? *ret_nrt : 0));
+ /*
+ * We repeat the same procedure from rt_setgate() here because
+ * it doesn't fire when we call it there because the node
+ * hasn't been added to the tree yet.
+ */
+ if (!(rt->rt_flags & RTF_HOST) && rt_mask(rt) != 0) {
+ struct rtfc_arg arg;
+ arg.rnh = rnh;
+ arg.rt0 = rt;
+ rnh->rnh_walktree_from(rnh, rt_key(rt), rt_mask(rt),
+ rt_fixchange, &arg);
+ }
+
+ if (ret_nrt) {
+ *ret_nrt = rt;
+ rt->rt_refcnt++;
+ }
+ break;
+ }
+bad:
+ splx(s);
+ return (error);
+}
+
+/*
+ * Called from rtrequest(RTM_DELETE, ...) to fix up the route's ``family''
+ * (i.e., the routes related to it by the operation of cloning). This
+ * routine is iterated over all potential former-child-routes by way of
+ * rnh->rnh_walktree_from() above, and those that actually are children of
+ * the late parent (passed in as VP here) are themselves deleted.
+ */
+static int
+rt_fixdelete(struct radix_node *rn, void *vp)
+{
+ struct rtentry *rt = (struct rtentry *)rn;
+ struct rtentry *rt0 = vp;
+
+ if (rt->rt_parent == rt0 && !(rt->rt_flags & RTF_PINNED)) {
+ return rtrequest(RTM_DELETE, rt_key(rt),
+ (struct sockaddr *)0, rt_mask(rt),
+ rt->rt_flags, (struct rtentry **)0);
+ }
+ return 0;
+}
+
+/*
+ * This routine is called from rt_setgate() to do the analogous thing for
+ * adds and changes. There is the added complication in this case of a
+ * middle insert; i.e., insertion of a new network route between an older
+ * network route and (cloned) host routes. For this reason, a simple check
+ * of rt->rt_parent is insufficient; each candidate route must be tested
+ * against the (mask, value) of the new route (passed as before in vp)
+ * to see if the new route matches it. Unfortunately, this has the obnoxious
+ * property of also triggering for insertion /above/ a pre-existing network
+ * route and clones. Sigh. This may be fixed some day.
+ *
+ * XXX - it may be possible to do fixdelete() for changes and reserve this
+ * routine just for adds. I'm not sure why I thought it was necessary to do
+ * changes this way.
+ */
+#ifdef DEBUG
+int rtfcdebug = 0;
+#endif
+
+static int
+rt_fixchange(struct radix_node *rn, void *vp)
+{
+ struct rtentry *rt = (struct rtentry *)rn;
+ struct rtfc_arg *ap = vp;
+ struct rtentry *rt0 = ap->rt0;
+ struct radix_node_head *rnh = ap->rnh;
+ u_char *xk1, *xm1, *xk2;
+ int i, len;
+
+#ifdef DEBUG
+ if (rtfcdebug)
+ printf("rt_fixchange: rt %p, rt0 %p\n", rt, rt0);
+#endif
+
+ if (!rt->rt_parent || (rt->rt_flags & RTF_PINNED)) {
+#ifdef DEBUG
+ if(rtfcdebug) printf("no parent or pinned\n");
+#endif
+ return 0;
+ }
+
+ if (rt->rt_parent == rt0) {
+#ifdef DEBUG
+ if(rtfcdebug) printf("parent match\n");
+#endif
+ return rtrequest(RTM_DELETE, rt_key(rt),
+ (struct sockaddr *)0, rt_mask(rt),
+ rt->rt_flags, (struct rtentry **)0);
+ }
+
+ /*
+ * There probably is a function somewhere which does this...
+ * if not, there should be.
+ */
+ len = imin(((struct sockaddr *)rt_key(rt0))->sa_len,
+ ((struct sockaddr *)rt_key(rt))->sa_len);
+
+ xk1 = (u_char *)rt_key(rt0);
+ xm1 = (u_char *)rt_mask(rt0);
+ xk2 = (u_char *)rt_key(rt);
+
+ for (i = rnh->rnh_treetop->rn_offset; i < len; i++) {
+ if ((xk2[i] & xm1[i]) != xk1[i]) {
+#ifdef DEBUG
+ if(rtfcdebug) printf("no match\n");
+#endif
+ return 0;
+ }
+ }
+
+ /*
+ * OK, this node is a clone, and matches the node currently being
+ * changed/added under the node's mask. So, get rid of it.
+ */
+#ifdef DEBUG
+ if(rtfcdebug) printf("deleting\n");
+#endif
+ return rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0,
+ rt_mask(rt), rt->rt_flags, (struct rtentry **)0);
+}
+
+int
+rt_setgate(rt0, dst, gate)
+ struct rtentry *rt0;
+ struct sockaddr *dst, *gate;
+{
+ caddr_t new, old;
+ int dlen = ROUNDUP(dst->sa_len), glen = ROUNDUP(gate->sa_len);
+ register struct rtentry *rt = rt0;
+ struct radix_node_head *rnh = rt_tables[dst->sa_family];
+
+ /*
+ * A host route with the destination equal to the gateway
+ * will interfere with keeping LLINFO in the routing
+ * table, so disallow it.
+ */
+ if (((rt0->rt_flags & (RTF_HOST|RTF_GATEWAY|RTF_LLINFO)) ==
+ (RTF_HOST|RTF_GATEWAY)) &&
+ (dst->sa_len == gate->sa_len) &&
+ (bcmp(dst, gate, dst->sa_len) == 0)) {
+ /*
+ * The route might already exist if this is an RTM_CHANGE
+ * or a routing redirect, so try to delete it.
+ */
+ if (rt_key(rt0))
+ rtrequest(RTM_DELETE, (struct sockaddr *)rt_key(rt0),
+ rt0->rt_gateway, rt_mask(rt0), rt0->rt_flags, 0);
+ return EADDRNOTAVAIL;
+ }
+
+ if (rt->rt_gateway == 0 || glen > ROUNDUP(rt->rt_gateway->sa_len)) {
+ old = (caddr_t)rt_key(rt);
+ R_Malloc(new, caddr_t, dlen + glen);
+ if (new == 0)
+ return ENOBUFS;
+ rt->rt_nodes->rn_key = new;
+ } else {
+ new = rt->rt_nodes->rn_key;
+ old = 0;
+ }
+ Bcopy(gate, (rt->rt_gateway = (struct sockaddr *)(new + dlen)), glen);
+ if (old) {
+ Bcopy(dst, new, dlen);
+ Free(old);
+ }
+ if (rt->rt_gwroute) {
+ rt = rt->rt_gwroute; RTFREE(rt);
+ rt = rt0; rt->rt_gwroute = 0;
+ }
+ /*
+ * Cloning loop avoidance:
+ * In the presence of protocol-cloning and bad configuration,
+ * it is possible to get stuck in bottomless mutual recursion
+ * (rtrequest rt_setgate rtalloc1). We avoid this by not allowing
+ * protocol-cloning to operate for gateways (which is probably the
+ * correct choice anyway), and avoid the resulting reference loops
+ * by disallowing any route to run through itself as a gateway.
+ * This is obviuosly mandatory when we get rt->rt_output().
+ */
+ if (rt->rt_flags & RTF_GATEWAY) {
+ rt->rt_gwroute = rtalloc1(gate, 1, RTF_PRCLONING);
+ if (rt->rt_gwroute == rt) {
+ RTFREE(rt->rt_gwroute);
+ rt->rt_gwroute = 0;
+ return EDQUOT; /* failure */
+ }
+ }
+
+ /*
+ * This isn't going to do anything useful for host routes, so
+ * don't bother. Also make sure we have a reasonable mask
+ * (we don't yet have one during adds).
+ */
+ if (!(rt->rt_flags & RTF_HOST) && rt_mask(rt) != 0) {
+ struct rtfc_arg arg;
+ arg.rnh = rnh;
+ arg.rt0 = rt;
+ rnh->rnh_walktree_from(rnh, rt_key(rt), rt_mask(rt),
+ rt_fixchange, &arg);
+ }
+
+ return 0;
+}
+
+static void
+rt_maskedcopy(src, dst, netmask)
+ struct sockaddr *src, *dst, *netmask;
+{
+ register u_char *cp1 = (u_char *)src;
+ register u_char *cp2 = (u_char *)dst;
+ register u_char *cp3 = (u_char *)netmask;
+ u_char *cplim = cp2 + *cp3;
+ u_char *cplim2 = cp2 + *cp1;
+
+ *cp2++ = *cp1++; *cp2++ = *cp1++; /* copies sa_len & sa_family */
+ cp3 += 2;
+ if (cplim > cplim2)
+ cplim = cplim2;
+ while (cp2 < cplim)
+ *cp2++ = *cp1++ & *cp3++;
+ if (cp2 < cplim2)
+ bzero((caddr_t)cp2, (unsigned)(cplim2 - cp2));
+}
+
+/*
+ * Set up a routing table entry, normally
+ * for an interface.
+ */
+int
+rtinit(ifa, cmd, flags)
+ register struct ifaddr *ifa;
+ int cmd, flags;
+{
+ register struct rtentry *rt;
+ register struct sockaddr *dst;
+ register struct sockaddr *deldst;
+ struct mbuf *m = 0;
+ struct rtentry *nrt = 0;
+ int error;
+
+ dst = flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr;
+ /*
+ * If it's a delete, check that if it exists, it's on the correct
+ * interface or we might scrub a route to another ifa which would
+ * be confusing at best and possibly worse.
+ */
+ if (cmd == RTM_DELETE) {
+ /*
+ * It's a delete, so it should already exist..
+ * If it's a net, mask off the host bits
+ * (Assuming we have a mask)
+ */
+ if ((flags & RTF_HOST) == 0 && ifa->ifa_netmask) {
+ m = m_get(M_WAIT, MT_SONAME);
+ deldst = mtod(m, struct sockaddr *);
+ rt_maskedcopy(dst, deldst, ifa->ifa_netmask);
+ dst = deldst;
+ }
+ /*
+ * Get an rtentry that is in the routing tree and
+ * contains the correct info. (if this fails we can't get there).
+ * We set "report" to FALSE so that if it doesn't exist,
+ * it doesn't report an error or clone a route, etc. etc.
+ */
+ rt = rtalloc1(dst, 0, 0UL);
+ if (rt) {
+ /*
+ * Ok so we found the rtentry. it has an extra reference
+ * for us at this stage. we won't need that so
+ * lop that off now.
+ */
+ rt->rt_refcnt--;
+ if (rt->rt_ifa != ifa) {
+ /*
+ * If the interface in the rtentry doesn't match
+ * the interface we are using, then we don't
+ * want to delete it, so return an error.
+ * This seems to be the only point of
+ * this whole RTM_DELETE clause.
+ */
+ if (m)
+ (void) m_free(m);
+ return (flags & RTF_HOST ? EHOSTUNREACH
+ : ENETUNREACH);
+ }
+ }
+ /* XXX */
+#if 0
+ else {
+ /*
+ * One would think that as we are deleting, and we know
+ * it doesn't exist, we could just return at this point
+ * with an "ELSE" clause, but apparently not..
+ */
+ return (flags & RTF_HOST ? EHOSTUNREACH
+ : ENETUNREACH);
+ }
+#endif
+ }
+ /*
+ * Do the actual request
+ */
+ error = rtrequest(cmd, dst, ifa->ifa_addr, ifa->ifa_netmask,
+ flags | ifa->ifa_flags, &nrt);
+ if (m)
+ (void) m_free(m);
+ /*
+ * If we are deleting, and we found an entry, then
+ * it's been removed from the tree.. now throw it away.
+ */
+ if (cmd == RTM_DELETE && error == 0 && (rt = nrt)) {
+ /*
+ * notify any listenning routing agents of the change
+ */
+ rt_newaddrmsg(cmd, ifa, error, nrt);
+ if (rt->rt_refcnt <= 0) {
+ rt->rt_refcnt++; /* need a 1->0 transition to free */
+ rtfree(rt);
+ }
+ }
+
+ /*
+ * We are adding, and we have a returned routing entry.
+ * We need to sanity check the result.
+ */
+ if (cmd == RTM_ADD && error == 0 && (rt = nrt)) {
+ /*
+ * We just wanted to add it.. we don't actually need a reference
+ */
+ rt->rt_refcnt--;
+ /*
+ * If it came back with an unexpected interface, then it must
+ * have already existed or something. (XXX)
+ */
+ if (rt->rt_ifa != ifa) {
+ printf("rtinit: wrong ifa (%p) was (%p)\n", ifa,
+ rt->rt_ifa);
+ /*
+ * Ask that the route we got back be removed
+ * from the routing tables as we are trying
+ * to supersede it.
+ */
+ if (rt->rt_ifa->ifa_rtrequest)
+ rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt, SA(0));
+ /*
+ * Remove the referenve to the it's ifaddr.
+ */
+ IFAFREE(rt->rt_ifa);
+ /*
+ * And substitute in references to the ifaddr
+ * we are adding.
+ */
+ rt->rt_ifa = ifa;
+ rt->rt_ifp = ifa->ifa_ifp;
+ ifa->ifa_refcnt++;
+ /*
+ * Now add it to the routing table
+ * XXX could we have just left it?
+ * as it might have been in the right place..
+ */
+ if (ifa->ifa_rtrequest)
+ ifa->ifa_rtrequest(RTM_ADD, rt, SA(0));
+ }
+ /*
+ * notify any listenning routing agents of the change
+ */
+ rt_newaddrmsg(cmd, ifa, error, nrt);
+ }
+ return (error);
+}
diff --git a/cpukit/libnetworking/net/route.h b/cpukit/libnetworking/net/route.h
new file mode 100644
index 0000000000..2ab73bbbb0
--- /dev/null
+++ b/cpukit/libnetworking/net/route.h
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 1980, 1986, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)route.h 8.3 (Berkeley) 4/19/94
+ * $Id$
+ */
+
+#ifndef _NET_ROUTE_H_
+#define _NET_ROUTE_H_
+
+/*
+ * Kernel resident routing tables.
+ *
+ * The routing tables are initialized when interface addresses
+ * are set by making entries for all directly connected interfaces.
+ */
+
+/*
+ * A route consists of a destination address and a reference
+ * to a routing entry. These are often held by protocols
+ * in their control blocks, e.g. inpcb.
+ */
+struct route {
+ struct rtentry *ro_rt;
+ struct sockaddr ro_dst;
+};
+
+/*
+ * These numbers are used by reliable protocols for determining
+ * retransmission behavior and are included in the routing structure.
+ */
+struct rt_metrics {
+ u_long rmx_locks; /* Kernel must leave these values alone */
+ u_long rmx_mtu; /* MTU for this path */
+ u_long rmx_hopcount; /* max hops expected */
+ u_long rmx_expire; /* lifetime for route, e.g. redirect */
+ u_long rmx_recvpipe; /* inbound delay-bandwidth product */
+ u_long rmx_sendpipe; /* outbound delay-bandwidth product */
+ u_long rmx_ssthresh; /* outbound gateway buffer limit */
+ u_long rmx_rtt; /* estimated round trip time */
+ u_long rmx_rttvar; /* estimated rtt variance */
+ u_long rmx_pksent; /* packets sent using this route */
+ u_long rmx_filler[4]; /* will be used for T/TCP later */
+};
+
+/*
+ * rmx_rtt and rmx_rttvar are stored as microseconds;
+ * RTTTOPRHZ(rtt) converts to a value suitable for use
+ * by a protocol slowtimo counter.
+ */
+#define RTM_RTTUNIT 1000000 /* units for rtt, rttvar, as units per sec */
+#define RTTTOPRHZ(r) ((r) / (RTM_RTTUNIT / PR_SLOWHZ))
+
+/*
+ * XXX kernel function pointer `rt_output' is visible to applications.
+ */
+struct mbuf;
+
+/*
+ * We distinguish between routes to hosts and routes to networks,
+ * preferring the former if available. For each route we infer
+ * the interface to use from the gateway address supplied when
+ * the route was entered. Routes that forward packets through
+ * gateways are marked so that the output routines know to address the
+ * gateway rather than the ultimate destination.
+ */
+#ifndef RNF_NORMAL
+#include <net/radix.h>
+#endif
+struct rtentry {
+ struct radix_node rt_nodes[2]; /* tree glue, and other values */
+#define rt_key(r) ((struct sockaddr *)((r)->rt_nodes->rn_key))
+#define rt_mask(r) ((struct sockaddr *)((r)->rt_nodes->rn_mask))
+ struct sockaddr *rt_gateway; /* value */
+ short rt_filler; /* was short flags field */
+ short rt_refcnt; /* # held references */
+ u_long rt_flags; /* up/down?, host/net */
+ struct ifnet *rt_ifp; /* the answer: interface to use */
+ struct ifaddr *rt_ifa; /* the answer: interface to use */
+ struct sockaddr *rt_genmask; /* for generation of cloned routes */
+ caddr_t rt_llinfo; /* pointer to link level info cache */
+ struct rt_metrics rt_rmx; /* metrics used by rx'ing protocols */
+ struct rtentry *rt_gwroute; /* implied entry for gatewayed routes */
+ int (*rt_output) __P((struct ifnet *, struct mbuf *,
+ struct sockaddr *, struct rtentry *));
+ /* output routine for this (rt,if) */
+ struct rtentry *rt_parent; /* cloning parent of this route */
+ void *rt_filler2; /* more filler */
+};
+
+/*
+ * Following structure necessary for 4.3 compatibility;
+ * We should eventually move it to a compat file.
+ */
+struct ortentry {
+ u_long rt_hash; /* to speed lookups */
+ struct sockaddr rt_dst; /* key */
+ struct sockaddr rt_gateway; /* value */
+ short rt_flags; /* up/down?, host/net */
+ short rt_refcnt; /* # held references */
+ u_long rt_use; /* raw # packets forwarded */
+ struct ifnet *rt_ifp; /* the answer: interface to use */
+};
+
+#define rt_use rt_rmx.rmx_pksent
+
+#define RTF_UP 0x1 /* route usable */
+#define RTF_GATEWAY 0x2 /* destination is a gateway */
+#define RTF_HOST 0x4 /* host entry (net otherwise) */
+#define RTF_REJECT 0x8 /* host or net unreachable */
+#define RTF_DYNAMIC 0x10 /* created dynamically (by redirect) */
+#define RTF_MODIFIED 0x20 /* modified dynamically (by redirect) */
+#define RTF_DONE 0x40 /* message confirmed */
+/* 0x80 unused */
+#define RTF_CLONING 0x100 /* generate new routes on use */
+#define RTF_XRESOLVE 0x200 /* external daemon resolves name */
+#define RTF_LLINFO 0x400 /* generated by link layer (e.g. ARP) */
+#define RTF_STATIC 0x800 /* manually added */
+#define RTF_BLACKHOLE 0x1000 /* just discard pkts (during updates) */
+#define RTF_PROTO2 0x4000 /* protocol specific routing flag */
+#define RTF_PROTO1 0x8000 /* protocol specific routing flag */
+
+#define RTF_PRCLONING 0x10000 /* protocol requires cloning */
+#define RTF_WASCLONED 0x20000 /* route generated through cloning */
+#define RTF_PROTO3 0x40000 /* protocol specific routing flag */
+/* 0x80000 unused */
+#define RTF_PINNED 0x100000 /* future use */
+#define RTF_LOCAL 0x200000 /* route represents a local address */
+#define RTF_BROADCAST 0x400000 /* route represents a bcast address */
+#define RTF_MULTICAST 0x800000 /* route represents a mcast address */
+ /* 0x1000000 and up unassigned */
+
+/*
+ * Routing statistics.
+ */
+struct rtstat {
+ short rts_badredirect; /* bogus redirect calls */
+ short rts_dynamic; /* routes created by redirects */
+ short rts_newgateway; /* routes modified by redirects */
+ short rts_unreach; /* lookups which failed */
+ short rts_wildcard; /* lookups satisfied by a wildcard */
+};
+/*
+ * Structures for routing messages.
+ */
+struct rt_msghdr {
+ u_short rtm_msglen; /* to skip over non-understood messages */
+ u_char rtm_version; /* future binary compatibility */
+ u_char rtm_type; /* message type */
+ u_short rtm_index; /* index for associated ifp */
+ int rtm_flags; /* flags, incl. kern & message, e.g. DONE */
+ int rtm_addrs; /* bitmask identifying sockaddrs in msg */
+ pid_t rtm_pid; /* identify sender */
+ int rtm_seq; /* for sender to identify action */
+ int rtm_errno; /* why failed */
+ int rtm_use; /* from rtentry */
+ u_long rtm_inits; /* which metrics we are initializing */
+ struct rt_metrics rtm_rmx; /* metrics themselves */
+};
+
+#define RTM_VERSION 5 /* Up the ante and ignore older versions */
+
+#define RTM_ADD 0x1 /* Add Route */
+#define RTM_DELETE 0x2 /* Delete Route */
+#define RTM_CHANGE 0x3 /* Change Metrics or flags */
+#define RTM_GET 0x4 /* Report Metrics */
+#define RTM_LOSING 0x5 /* Kernel Suspects Partitioning */
+#define RTM_REDIRECT 0x6 /* Told to use different route */
+#define RTM_MISS 0x7 /* Lookup failed on this address */
+#define RTM_LOCK 0x8 /* fix specified metrics */
+#define RTM_OLDADD 0x9 /* caused by SIOCADDRT */
+#define RTM_OLDDEL 0xa /* caused by SIOCDELRT */
+#define RTM_RESOLVE 0xb /* req to resolve dst to LL addr */
+#define RTM_NEWADDR 0xc /* address being added to iface */
+#define RTM_DELADDR 0xd /* address being removed from iface */
+#define RTM_IFINFO 0xe /* iface going up/down etc. */
+
+#define RTV_MTU 0x1 /* init or lock _mtu */
+#define RTV_HOPCOUNT 0x2 /* init or lock _hopcount */
+#define RTV_EXPIRE 0x4 /* init or lock _hopcount */
+#define RTV_RPIPE 0x8 /* init or lock _recvpipe */
+#define RTV_SPIPE 0x10 /* init or lock _sendpipe */
+#define RTV_SSTHRESH 0x20 /* init or lock _ssthresh */
+#define RTV_RTT 0x40 /* init or lock _rtt */
+#define RTV_RTTVAR 0x80 /* init or lock _rttvar */
+
+/*
+ * Bitmask values for rtm_addr.
+ */
+#define RTA_DST 0x1 /* destination sockaddr present */
+#define RTA_GATEWAY 0x2 /* gateway sockaddr present */
+#define RTA_NETMASK 0x4 /* netmask sockaddr present */
+#define RTA_GENMASK 0x8 /* cloning mask sockaddr present */
+#define RTA_IFP 0x10 /* interface name sockaddr present */
+#define RTA_IFA 0x20 /* interface addr sockaddr present */
+#define RTA_AUTHOR 0x40 /* sockaddr for author of redirect */
+#define RTA_BRD 0x80 /* for NEWADDR, broadcast or p-p dest addr */
+
+/*
+ * Index offsets for sockaddr array for alternate internal encoding.
+ */
+#define RTAX_DST 0 /* destination sockaddr present */
+#define RTAX_GATEWAY 1 /* gateway sockaddr present */
+#define RTAX_NETMASK 2 /* netmask sockaddr present */
+#define RTAX_GENMASK 3 /* cloning mask sockaddr present */
+#define RTAX_IFP 4 /* interface name sockaddr present */
+#define RTAX_IFA 5 /* interface addr sockaddr present */
+#define RTAX_AUTHOR 6 /* sockaddr for author of redirect */
+#define RTAX_BRD 7 /* for NEWADDR, broadcast or p-p dest addr */
+#define RTAX_MAX 8 /* size of array to allocate */
+
+struct rt_addrinfo {
+ int rti_addrs;
+ struct sockaddr *rti_info[RTAX_MAX];
+};
+
+struct route_cb {
+ int ip_count;
+ int ipx_count;
+ int ns_count;
+ int iso_count;
+ int any_count;
+};
+
+#ifdef _KERNEL
+#define RTFREE(rt) \
+ do { \
+ if ((rt)->rt_refcnt <= 1) \
+ rtfree(rt); \
+ else \
+ (rt)->rt_refcnt--; \
+ } while (0)
+
+extern struct route_cb route_cb;
+extern struct rtstat rtstat;
+extern struct radix_node_head *rt_tables[AF_MAX+1];
+
+void route_init __P((void));
+void rt_ifmsg __P((struct ifnet *));
+void rt_missmsg __P((int, struct rt_addrinfo *, int, int));
+void rt_newaddrmsg __P((int, struct ifaddr *, int, struct rtentry *));
+int rt_setgate __P((struct rtentry *,
+ struct sockaddr *, struct sockaddr *));
+void rtalloc __P((struct route *));
+void rtalloc_ign __P((struct route *, unsigned long));
+struct rtentry *
+ rtalloc1 __P((struct sockaddr *, int, unsigned long));
+void rtfree __P((struct rtentry *));
+int rtinit __P((struct ifaddr *, int, int));
+int rtioctl __P((int, caddr_t, struct proc *));
+void rtredirect __P((struct sockaddr *, struct sockaddr *,
+ struct sockaddr *, int, struct sockaddr *, struct rtentry **));
+int rtrequest __P((int, struct sockaddr *,
+ struct sockaddr *, struct sockaddr *, int, struct rtentry **));
+#endif
+
+#endif
diff --git a/cpukit/libnetworking/net/rtsock.c b/cpukit/libnetworking/net/rtsock.c
new file mode 100644
index 0000000000..af45607a3e
--- /dev/null
+++ b/cpukit/libnetworking/net/rtsock.c
@@ -0,0 +1,829 @@
+/*
+ * Copyright (c) 1988, 1991, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)rtsock.c 8.5 (Berkeley) 11/2/94
+ * $Id$
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <sys/proc.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/domain.h>
+#include <sys/protosw.h>
+
+#include <net/if.h>
+#include <net/route.h>
+#include <net/raw_cb.h>
+
+static struct sockaddr route_dst = { 2, PF_ROUTE, };
+static struct sockaddr route_src = { 2, PF_ROUTE, };
+static struct sockaddr sa_zero = { sizeof(sa_zero), AF_INET, };
+static struct sockproto route_proto = { PF_ROUTE, };
+
+struct walkarg {
+ int w_tmemsize;
+ int w_op, w_arg;
+ caddr_t w_tmem;
+ struct sysctl_req *w_req;
+};
+
+static struct mbuf *
+ rt_msg1 __P((int, struct rt_addrinfo *));
+static int rt_msg2 __P((int,
+ struct rt_addrinfo *, caddr_t, struct walkarg *));
+static int rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *));
+static int sysctl_dumpentry __P((struct radix_node *rn, void *vw));
+static int sysctl_iflist __P((int af, struct walkarg *w));
+static int route_output __P((struct mbuf *, struct socket *));
+static int route_usrreq __P((struct socket *,
+ int, struct mbuf *, struct mbuf *, struct mbuf *));
+static void rt_setmetrics __P((u_long, struct rt_metrics *, struct rt_metrics *));
+
+/* Sleazy use of local variables throughout file, warning!!!! */
+#define dst info.rti_info[RTAX_DST]
+#define gate info.rti_info[RTAX_GATEWAY]
+#define netmask info.rti_info[RTAX_NETMASK]
+#define genmask info.rti_info[RTAX_GENMASK]
+#define ifpaddr info.rti_info[RTAX_IFP]
+#define ifaaddr info.rti_info[RTAX_IFA]
+#define brdaddr info.rti_info[RTAX_BRD]
+
+/*ARGSUSED*/
+static int
+route_usrreq(so, req, m, nam, control)
+ register struct socket *so;
+ int req;
+ struct mbuf *m, *nam, *control;
+{
+ register int error = 0;
+ register struct rawcb *rp = sotorawcb(so);
+ int s;
+
+ if (req == PRU_ATTACH) {
+ MALLOC(rp, struct rawcb *, sizeof(*rp), M_PCB, M_WAITOK);
+ so->so_pcb = (caddr_t)rp;
+ if (so->so_pcb)
+ bzero(so->so_pcb, sizeof(*rp));
+ }
+ if (req == PRU_DETACH && rp) {
+ int af = rp->rcb_proto.sp_protocol;
+ if (af == AF_INET)
+ route_cb.ip_count--;
+ else if (af == AF_IPX)
+ route_cb.ipx_count--;
+ else if (af == AF_NS)
+ route_cb.ns_count--;
+ else if (af == AF_ISO)
+ route_cb.iso_count--;
+ route_cb.any_count--;
+ }
+ s = splnet();
+ error = raw_usrreq(so, req, m, nam, control);
+ rp = sotorawcb(so);
+ if (req == PRU_ATTACH && rp) {
+ int af = rp->rcb_proto.sp_protocol;
+ if (error) {
+ free((caddr_t)rp, M_PCB);
+ splx(s);
+ return (error);
+ }
+ if (af == AF_INET)
+ route_cb.ip_count++;
+ else if (af == AF_IPX)
+ route_cb.ipx_count++;
+ else if (af == AF_NS)
+ route_cb.ns_count++;
+ else if (af == AF_ISO)
+ route_cb.iso_count++;
+ rp->rcb_faddr = &route_src;
+ route_cb.any_count++;
+ soisconnected(so);
+ so->so_options |= SO_USELOOPBACK;
+ }
+ splx(s);
+ return (error);
+}
+
+/*ARGSUSED*/
+static int
+route_output(m, so)
+ register struct mbuf *m;
+ struct socket *so;
+{
+ register struct rt_msghdr *rtm = 0;
+ register struct rtentry *rt = 0;
+ struct rtentry *saved_nrt = 0;
+ struct radix_node_head *rnh;
+ struct rt_addrinfo info;
+ int len, error = 0;
+ struct ifnet *ifp = 0;
+ struct ifaddr *ifa = 0;
+
+#define senderr(e) { error = e; goto flush;}
+ if (m == 0 || ((m->m_len < sizeof(long)) &&
+ (m = m_pullup(m, sizeof(long))) == 0))
+ return (ENOBUFS);
+ if ((m->m_flags & M_PKTHDR) == 0)
+ panic("route_output");
+ len = m->m_pkthdr.len;
+ if (len < sizeof(*rtm) ||
+ len != mtod(m, struct rt_msghdr *)->rtm_msglen) {
+ dst = 0;
+ senderr(EINVAL);
+ }
+ R_Malloc(rtm, struct rt_msghdr *, len);
+ if (rtm == 0) {
+ dst = 0;
+ senderr(ENOBUFS);
+ }
+ m_copydata(m, 0, len, (caddr_t)rtm);
+ if (rtm->rtm_version != RTM_VERSION) {
+ dst = 0;
+ senderr(EPROTONOSUPPORT);
+ }
+ info.rti_addrs = rtm->rtm_addrs;
+ if (rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info)) {
+ dst = 0;
+ senderr(EINVAL);
+ }
+ if (dst == 0 || (dst->sa_family >= AF_MAX)
+ || (gate != 0 && (gate->sa_family >= AF_MAX)))
+ senderr(EINVAL);
+ if (genmask) {
+ struct radix_node *t;
+ t = rn_addmask((caddr_t)genmask, 0, 1);
+ if (t && Bcmp(genmask, t->rn_key, *(u_char *)genmask) == 0)
+ genmask = (struct sockaddr *)(t->rn_key);
+ else
+ senderr(ENOBUFS);
+ }
+ switch (rtm->rtm_type) {
+
+ case RTM_ADD:
+ if (gate == 0)
+ senderr(EINVAL);
+ error = rtrequest(RTM_ADD, dst, gate, netmask,
+ rtm->rtm_flags, &saved_nrt);
+ if (error == 0 && saved_nrt) {
+ rt_setmetrics(rtm->rtm_inits,
+ &rtm->rtm_rmx, &saved_nrt->rt_rmx);
+ saved_nrt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
+ saved_nrt->rt_rmx.rmx_locks |=
+ (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
+ saved_nrt->rt_refcnt--;
+ saved_nrt->rt_genmask = genmask;
+ }
+ break;
+
+ case RTM_DELETE:
+ error = rtrequest(RTM_DELETE, dst, gate, netmask,
+ rtm->rtm_flags, &saved_nrt);
+ if (error == 0) {
+ if ((rt = saved_nrt))
+ rt->rt_refcnt++;
+ goto report;
+ }
+ break;
+
+ case RTM_GET:
+ case RTM_CHANGE:
+ case RTM_LOCK:
+ if ((rnh = rt_tables[dst->sa_family]) == 0) {
+ senderr(EAFNOSUPPORT);
+ } else if ((rt = (struct rtentry *)
+ rnh->rnh_lookup(dst, netmask, rnh)))
+ rt->rt_refcnt++;
+ else
+ senderr(ESRCH);
+ switch(rtm->rtm_type) {
+
+ case RTM_GET:
+ report:
+ dst = rt_key(rt);
+ gate = rt->rt_gateway;
+ netmask = rt_mask(rt);
+ genmask = rt->rt_genmask;
+ if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
+ ifp = rt->rt_ifp;
+ if (ifp) {
+ ifpaddr = ifp->if_addrlist->ifa_addr;
+ ifaaddr = rt->rt_ifa->ifa_addr;
+ rtm->rtm_index = ifp->if_index;
+ } else {
+ ifpaddr = 0;
+ ifaaddr = 0;
+ }
+ }
+ len = rt_msg2(rtm->rtm_type, &info, (caddr_t)0,
+ (struct walkarg *)0);
+ if (len > rtm->rtm_msglen) {
+ struct rt_msghdr *new_rtm;
+ R_Malloc(new_rtm, struct rt_msghdr *, len);
+ if (new_rtm == 0)
+ senderr(ENOBUFS);
+ Bcopy(rtm, new_rtm, rtm->rtm_msglen);
+ Free(rtm); rtm = new_rtm;
+ }
+ (void)rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm,
+ (struct walkarg *)0);
+ rtm->rtm_flags = rt->rt_flags;
+ rtm->rtm_rmx = rt->rt_rmx;
+ rtm->rtm_addrs = info.rti_addrs;
+ break;
+
+ case RTM_CHANGE:
+ if (gate && (error = rt_setgate(rt, rt_key(rt), gate)))
+ senderr(error);
+
+ /*
+ * If they tried to change things but didn't specify
+ * the required gateway, then just use the old one.
+ * This can happen if the user tries to change the
+ * flags on the default route without changing the
+ * default gateway. Changing flags still doesn't work.
+ */
+ if ((rt->rt_flags & RTF_GATEWAY) && !gate)
+ gate = rt->rt_gateway;
+
+ /* new gateway could require new ifaddr, ifp;
+ flags may also be different; ifp may be specified
+ by ll sockaddr when protocol address is ambiguous */
+ if (ifpaddr && (ifa = ifa_ifwithnet(ifpaddr)) &&
+ (ifp = ifa->ifa_ifp) && (ifaaddr || gate))
+ ifa = ifaof_ifpforaddr(ifaaddr ? ifaaddr : gate,
+ ifp);
+ else if ((ifaaddr && (ifa = ifa_ifwithaddr(ifaaddr))) ||
+ (gate && (ifa = ifa_ifwithroute(rt->rt_flags,
+ rt_key(rt), gate))))
+ ifp = ifa->ifa_ifp;
+ if (ifa) {
+ register struct ifaddr *oifa = rt->rt_ifa;
+ if (oifa != ifa) {
+ if (oifa && oifa->ifa_rtrequest)
+ oifa->ifa_rtrequest(RTM_DELETE,
+ rt, gate);
+ IFAFREE(rt->rt_ifa);
+ rt->rt_ifa = ifa;
+ ifa->ifa_refcnt++;
+ rt->rt_ifp = ifp;
+ }
+ }
+ rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
+ &rt->rt_rmx);
+ if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
+ rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, gate);
+ if (genmask)
+ rt->rt_genmask = genmask;
+ /*
+ * Fall into
+ */
+ case RTM_LOCK:
+ rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
+ rt->rt_rmx.rmx_locks |=
+ (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
+ break;
+ }
+ break;
+
+ default:
+ senderr(EOPNOTSUPP);
+ }
+
+flush:
+ if (rtm) {
+ if (error)
+ rtm->rtm_errno = error;
+ else
+ rtm->rtm_flags |= RTF_DONE;
+ }
+ if (rt)
+ rtfree(rt);
+ {
+ register struct rawcb *rp = 0;
+ /*
+ * Check to see if we don't want our own messages.
+ */
+ if ((so->so_options & SO_USELOOPBACK) == 0) {
+ if (route_cb.any_count <= 1) {
+ if (rtm)
+ Free(rtm);
+ m_freem(m);
+ return (error);
+ }
+ /* There is another listener, so construct message */
+ rp = sotorawcb(so);
+ }
+ if (rtm) {
+ m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm);
+ Free(rtm);
+ }
+ if (rp)
+ rp->rcb_proto.sp_family = 0; /* Avoid us */
+ if (dst)
+ route_proto.sp_protocol = dst->sa_family;
+ raw_input(m, &route_proto, &route_src, &route_dst);
+ if (rp)
+ rp->rcb_proto.sp_family = PF_ROUTE;
+ }
+ return (error);
+}
+
+static void
+rt_setmetrics(which, in, out)
+ u_long which;
+ register struct rt_metrics *in, *out;
+{
+#define metric(f, e) if (which & (f)) out->e = in->e;
+ metric(RTV_RPIPE, rmx_recvpipe);
+ metric(RTV_SPIPE, rmx_sendpipe);
+ metric(RTV_SSTHRESH, rmx_ssthresh);
+ metric(RTV_RTT, rmx_rtt);
+ metric(RTV_RTTVAR, rmx_rttvar);
+ metric(RTV_HOPCOUNT, rmx_hopcount);
+ metric(RTV_MTU, rmx_mtu);
+ metric(RTV_EXPIRE, rmx_expire);
+#undef metric
+}
+
+#define ROUNDUP(a) \
+ ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
+#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
+
+
+/*
+ * Extract the addresses of the passed sockaddrs.
+ * Do a little sanity checking so as to avoid bad memory references.
+ * This data is derived straight from userland.
+ */
+static int
+rt_xaddrs(cp, cplim, rtinfo)
+ register caddr_t cp, cplim;
+ register struct rt_addrinfo *rtinfo;
+{
+ register struct sockaddr *sa;
+ register int i;
+
+ bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info));
+ for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
+ if ((rtinfo->rti_addrs & (1 << i)) == 0)
+ continue;
+ sa = (struct sockaddr *)cp;
+ /*
+ * It won't fit.
+ */
+ if ( (cp + sa->sa_len) > cplim ) {
+ return (EINVAL);
+ }
+
+ /*
+ * there are no more.. quit now
+ * If there are more bits, they are in error.
+ * I've seen this. route(1) can evidently generate these.
+ * This causes kernel to core dump.
+ * for compatibility, If we see this, point to a safe address.
+ */
+ if (sa->sa_len == 0) {
+ rtinfo->rti_info[i] = &sa_zero;
+ return (0); /* should be EINVAL but for compat */
+ }
+
+ /* accept it */
+ rtinfo->rti_info[i] = sa;
+ ADVANCE(cp, sa);
+ }
+ return (0);
+}
+
+static struct mbuf *
+rt_msg1(type, rtinfo)
+ int type;
+ register struct rt_addrinfo *rtinfo;
+{
+ register struct rt_msghdr *rtm;
+ register struct mbuf *m;
+ register int i;
+ register struct sockaddr *sa;
+ int len, dlen;
+
+ m = m_gethdr(M_DONTWAIT, MT_DATA);
+ if (m == 0)
+ return (m);
+ switch (type) {
+
+ case RTM_DELADDR:
+ case RTM_NEWADDR:
+ len = sizeof(struct ifa_msghdr);
+ break;
+
+ case RTM_IFINFO:
+ len = sizeof(struct if_msghdr);
+ break;
+
+ default:
+ len = sizeof(struct rt_msghdr);
+ }
+ if (len > MHLEN)
+ panic("rt_msg1");
+ m->m_pkthdr.len = m->m_len = len;
+ m->m_pkthdr.rcvif = 0;
+ rtm = mtod(m, struct rt_msghdr *);
+ bzero((caddr_t)rtm, len);
+ for (i = 0; i < RTAX_MAX; i++) {
+ if ((sa = rtinfo->rti_info[i]) == NULL)
+ continue;
+ rtinfo->rti_addrs |= (1 << i);
+ dlen = ROUNDUP(sa->sa_len);
+ m_copyback(m, len, dlen, (caddr_t)sa);
+ len += dlen;
+ }
+ if (m->m_pkthdr.len != len) {
+ m_freem(m);
+ return (NULL);
+ }
+ rtm->rtm_msglen = len;
+ rtm->rtm_version = RTM_VERSION;
+ rtm->rtm_type = type;
+ return (m);
+}
+
+static int
+rt_msg2(type, rtinfo, cp, w)
+ int type;
+ register struct rt_addrinfo *rtinfo;
+ caddr_t cp;
+ struct walkarg *w;
+{
+ register int i;
+ int len, dlen, second_time = 0;
+ caddr_t cp0;
+
+ rtinfo->rti_addrs = 0;
+again:
+ switch (type) {
+
+ case RTM_DELADDR:
+ case RTM_NEWADDR:
+ len = sizeof(struct ifa_msghdr);
+ break;
+
+ case RTM_IFINFO:
+ len = sizeof(struct if_msghdr);
+ break;
+
+ default:
+ len = sizeof(struct rt_msghdr);
+ }
+ cp0 = cp;
+ if (cp0)
+ cp += len;
+ for (i = 0; i < RTAX_MAX; i++) {
+ register struct sockaddr *sa;
+
+ if ((sa = rtinfo->rti_info[i]) == 0)
+ continue;
+ rtinfo->rti_addrs |= (1 << i);
+ dlen = ROUNDUP(sa->sa_len);
+ if (cp) {
+ bcopy((caddr_t)sa, cp, (unsigned)dlen);
+ cp += dlen;
+ }
+ len += dlen;
+ }
+ if (cp == 0 && w != NULL && !second_time) {
+ register struct walkarg *rw = w;
+
+ if (rw->w_req) {
+ if (rw->w_tmemsize < len) {
+ if (rw->w_tmem)
+ free(rw->w_tmem, M_RTABLE);
+ rw->w_tmem = (caddr_t)
+ malloc(len, M_RTABLE, M_NOWAIT);
+ if (rw->w_tmem)
+ rw->w_tmemsize = len;
+ }
+ if (rw->w_tmem) {
+ cp = rw->w_tmem;
+ second_time = 1;
+ goto again;
+ }
+ }
+ }
+ if (cp) {
+ register struct rt_msghdr *rtm = (struct rt_msghdr *)cp0;
+
+ rtm->rtm_version = RTM_VERSION;
+ rtm->rtm_type = type;
+ rtm->rtm_msglen = len;
+ }
+ return (len);
+}
+
+/*
+ * This routine is called to generate a message from the routing
+ * socket indicating that a redirect has occured, a routing lookup
+ * has failed, or that a protocol has detected timeouts to a particular
+ * destination.
+ */
+void
+rt_missmsg(type, rtinfo, flags, error)
+ int type, flags, error;
+ register struct rt_addrinfo *rtinfo;
+{
+ register struct rt_msghdr *rtm;
+ register struct mbuf *m;
+ struct sockaddr *sa = rtinfo->rti_info[RTAX_DST];
+
+ if (route_cb.any_count == 0)
+ return;
+ m = rt_msg1(type, rtinfo);
+ if (m == 0)
+ return;
+ rtm = mtod(m, struct rt_msghdr *);
+ rtm->rtm_flags = RTF_DONE | flags;
+ rtm->rtm_errno = error;
+ rtm->rtm_addrs = rtinfo->rti_addrs;
+ route_proto.sp_protocol = sa ? sa->sa_family : 0;
+ raw_input(m, &route_proto, &route_src, &route_dst);
+}
+
+/*
+ * This routine is called to generate a message from the routing
+ * socket indicating that the status of a network interface has changed.
+ */
+void
+rt_ifmsg(ifp)
+ register struct ifnet *ifp;
+{
+ register struct if_msghdr *ifm;
+ struct mbuf *m;
+ struct rt_addrinfo info;
+
+ if (route_cb.any_count == 0)
+ return;
+ bzero((caddr_t)&info, sizeof(info));
+ m = rt_msg1(RTM_IFINFO, &info);
+ if (m == 0)
+ return;
+ ifm = mtod(m, struct if_msghdr *);
+ ifm->ifm_index = ifp->if_index;
+ ifm->ifm_flags = (u_short)ifp->if_flags;
+ ifm->ifm_data = ifp->if_data;
+ ifm->ifm_addrs = 0;
+ route_proto.sp_protocol = 0;
+ raw_input(m, &route_proto, &route_src, &route_dst);
+}
+
+/*
+ * This is called to generate messages from the routing socket
+ * indicating a network interface has had addresses associated with it.
+ * if we ever reverse the logic and replace messages TO the routing
+ * socket indicate a request to configure interfaces, then it will
+ * be unnecessary as the routing socket will automatically generate
+ * copies of it.
+ */
+void
+rt_newaddrmsg(cmd, ifa, error, rt)
+ int cmd, error;
+ register struct ifaddr *ifa;
+ register struct rtentry *rt;
+{
+ struct rt_addrinfo info;
+ struct sockaddr *sa = 0;
+ int pass;
+ struct mbuf *m = 0;
+ struct ifnet *ifp = ifa->ifa_ifp;
+
+ if (route_cb.any_count == 0)
+ return;
+ for (pass = 1; pass < 3; pass++) {
+ bzero((caddr_t)&info, sizeof(info));
+ if ((cmd == RTM_ADD && pass == 1) ||
+ (cmd == RTM_DELETE && pass == 2)) {
+ register struct ifa_msghdr *ifam;
+ int ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR;
+
+ ifaaddr = sa = ifa->ifa_addr;
+ ifpaddr = ifp->if_addrlist->ifa_addr;
+ netmask = ifa->ifa_netmask;
+ brdaddr = ifa->ifa_dstaddr;
+ if ((m = rt_msg1(ncmd, &info)) == NULL)
+ continue;
+ ifam = mtod(m, struct ifa_msghdr *);
+ ifam->ifam_index = ifp->if_index;
+ ifam->ifam_metric = ifa->ifa_metric;
+ ifam->ifam_flags = ifa->ifa_flags;
+ ifam->ifam_addrs = info.rti_addrs;
+ }
+ if ((cmd == RTM_ADD && pass == 2) ||
+ (cmd == RTM_DELETE && pass == 1)) {
+ register struct rt_msghdr *rtm;
+
+ if (rt == 0)
+ continue;
+ netmask = rt_mask(rt);
+ dst = sa = rt_key(rt);
+ gate = rt->rt_gateway;
+ if ((m = rt_msg1(cmd, &info)) == NULL)
+ continue;
+ rtm = mtod(m, struct rt_msghdr *);
+ rtm->rtm_index = ifp->if_index;
+ rtm->rtm_flags |= rt->rt_flags;
+ rtm->rtm_errno = error;
+ rtm->rtm_addrs = info.rti_addrs;
+ }
+ route_proto.sp_protocol = sa ? sa->sa_family : 0;
+ raw_input(m, &route_proto, &route_src, &route_dst);
+ }
+}
+
+
+/*
+ * This is used in dumping the kernel table via sysctl().
+ */
+int
+sysctl_dumpentry(rn, vw)
+ struct radix_node *rn;
+ void *vw;
+{
+ register struct walkarg *w = vw;
+ register struct rtentry *rt = (struct rtentry *)rn;
+ int error = 0, size;
+ struct rt_addrinfo info;
+
+ if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg))
+ return 0;
+ bzero((caddr_t)&info, sizeof(info));
+ dst = rt_key(rt);
+ gate = rt->rt_gateway;
+ netmask = rt_mask(rt);
+ genmask = rt->rt_genmask;
+ size = rt_msg2(RTM_GET, &info, 0, w);
+ if (w->w_req && w->w_tmem) {
+ register struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem;
+
+ rtm->rtm_flags = rt->rt_flags;
+ rtm->rtm_use = rt->rt_use;
+ rtm->rtm_rmx = rt->rt_rmx;
+ rtm->rtm_index = rt->rt_ifp->if_index;
+ rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0;
+ rtm->rtm_addrs = info.rti_addrs;
+ error = 0;
+ return (error);
+ }
+ return (error);
+}
+
+int
+sysctl_iflist(af, w)
+ int af;
+ register struct walkarg *w;
+{
+ register struct ifnet *ifp;
+ register struct ifaddr *ifa;
+ struct rt_addrinfo info;
+ int len, error = 0;
+
+ bzero((caddr_t)&info, sizeof(info));
+ for (ifp = ifnet; ifp; ifp = ifp->if_next) {
+ if (w->w_arg && w->w_arg != ifp->if_index)
+ continue;
+ ifa = ifp->if_addrlist;
+ ifpaddr = ifa->ifa_addr;
+ len = rt_msg2(RTM_IFINFO, &info, (caddr_t)0, w);
+ ifpaddr = 0;
+ if (w->w_req && w->w_tmem) {
+ register struct if_msghdr *ifm;
+
+ ifm = (struct if_msghdr *)w->w_tmem;
+ ifm->ifm_index = ifp->if_index;
+ ifm->ifm_flags = (u_short)ifp->if_flags;
+ ifm->ifm_data = ifp->if_data;
+ ifm->ifm_addrs = info.rti_addrs;
+ error = SYSCTL_OUT(w->w_req,(caddr_t)ifm, len);
+ if (error)
+ return (error);
+ }
+ while ((ifa = ifa->ifa_next) != 0) {
+ if (af && af != ifa->ifa_addr->sa_family)
+ continue;
+ ifaaddr = ifa->ifa_addr;
+ netmask = ifa->ifa_netmask;
+ brdaddr = ifa->ifa_dstaddr;
+ len = rt_msg2(RTM_NEWADDR, &info, 0, w);
+ if (w->w_req && w->w_tmem) {
+ register struct ifa_msghdr *ifam;
+
+ ifam = (struct ifa_msghdr *)w->w_tmem;
+ ifam->ifam_index = ifa->ifa_ifp->if_index;
+ ifam->ifam_flags = ifa->ifa_flags;
+ ifam->ifam_metric = ifa->ifa_metric;
+ ifam->ifam_addrs = info.rti_addrs;
+ error = SYSCTL_OUT(w->w_req, w->w_tmem, len);
+ if (error)
+ return (error);
+ }
+ }
+ ifaaddr = netmask = brdaddr = 0;
+ }
+ return (0);
+}
+
+static int
+sysctl_rtsock(SYSCTL_HANDLER_ARGS)
+{
+ int *name = (int *)arg1;
+ u_int namelen = arg2;
+ register struct radix_node_head *rnh;
+ int i, s, error = EINVAL;
+ u_char af;
+ struct walkarg w;
+
+ name ++;
+ namelen--;
+ if (req->newptr)
+ return (EPERM);
+ if (namelen != 3)
+ return (EINVAL);
+ af = name[0];
+ Bzero(&w, sizeof(w));
+ w.w_op = name[1];
+ w.w_arg = name[2];
+ w.w_req = req;
+
+ s = splnet();
+ switch (w.w_op) {
+
+ case NET_RT_DUMP:
+ case NET_RT_FLAGS:
+ for (i = 1; i <= AF_MAX; i++)
+ if ((rnh = rt_tables[i]) && (af == 0 || af == i) &&
+ (error = rnh->rnh_walktree(rnh,
+ sysctl_dumpentry, &w)))
+ break;
+ break;
+
+ case NET_RT_IFLIST:
+ error = sysctl_iflist(af, &w);
+ }
+ splx(s);
+ if (w.w_tmem)
+ free(w.w_tmem, M_RTABLE);
+ return (error);
+}
+
+SYSCTL_NODE(_net, PF_ROUTE, routetable, CTLFLAG_RD, sysctl_rtsock,"");
+
+/*
+ * Definitions of protocols supported in the ROUTE domain.
+ */
+
+extern struct domain routedomain; /* or at least forward */
+
+static struct protosw routesw[] = {
+{ SOCK_RAW, &routedomain, 0, PR_ATOMIC|PR_ADDR,
+ 0, route_output, raw_ctlinput, 0,
+ route_usrreq,
+ raw_init
+}
+};
+
+struct domain routedomain =
+ { PF_ROUTE, "route", route_init, 0, 0,
+ routesw, &routesw[sizeof(routesw)/sizeof(routesw[0])] };
+
+DOMAIN_SET(route);
diff --git a/cpukit/libnetworking/net/zlib.c b/cpukit/libnetworking/net/zlib.c
new file mode 100644
index 0000000000..5030768865
--- /dev/null
+++ b/cpukit/libnetworking/net/zlib.c
@@ -0,0 +1,5376 @@
+/*
+ * This file is derived from various .h and .c files from the zlib-1.0.4
+ * distribution by Jean-loup Gailly and Mark Adler, with some additions
+ * by Paul Mackerras to aid in implementing Deflate compression and
+ * decompression for PPP packets. See zlib.h for conditions of
+ * distribution and use.
+ *
+ * Changes that have been made include:
+ * - added Z_PACKET_FLUSH (see zlib.h for details)
+ * - added inflateIncomp and deflateOutputPending
+ * - allow strm->next_out to be NULL, meaning discard the output
+ *
+ * $Id$
+ */
+
+/*
+ * ==FILEVERSION 971210==
+ *
+ * This marker is used by the Linux installation script to determine
+ * whether an up-to-date version of this file is already installed.
+ */
+
+#define NO_DUMMY_DECL
+#define NO_ZCFUNCS
+#define MY_ZCALLOC
+
+#if defined(__FreeBSD__) && (defined(KERNEL) || defined(_KERNEL))
+#define inflate inflate_ppp /* FreeBSD already has an inflate :-( */
+#endif
+
+
+/* +++ zutil.h */
+/* zutil.h -- internal interface and configuration of the compression library
+ * Copyright (C) 1995-1996 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.
+ */
+
+/* From: zutil.h,v 1.16 1996/07/24 13:41:13 me Exp $ */
+
+#ifndef _Z_UTIL_H
+#define _Z_UTIL_H
+
+#include "zlib.h"
+
+#if defined(KERNEL) || defined(_KERNEL)
+/* Assume this is a *BSD or SVR4 kernel */
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/systm.h>
+#undef u
+# define HAVE_MEMCPY
+# define memcpy(d, s, n) bcopy((s), (d), (n))
+# define memset(d, v, n) bzero((d), (n))
+# define memcmp bcmp
+
+#else
+#if defined(__KERNEL__)
+/* Assume this is a Linux kernel */
+#include <linux/string.h>
+#define HAVE_MEMCPY
+
+#else /* not kernel */
+
+#if defined(MSDOS)||defined(VMS)||defined(CRAY)||defined(WIN32)||defined(RISCOS)
+# include <stddef.h>
+# include <errno.h>
+#else
+ extern int errno;
+#endif
+#ifdef STDC
+# include <string.h>
+# include <stdlib.h>
+#endif
+#endif /* __KERNEL__ */
+#endif /* _KERNEL || KERNEL */
+
+#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
+# ifdef __TURBOC__
+# include <alloc.h>
+# 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 FOPEN(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
+
+#ifdef MACOS
+# define OS_CODE 0x07
+#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
+
+ /* Common defaults */
+
+#ifndef OS_CODE
+# define OS_CODE 0x03 /* assume Unix */
+#endif
+
+#ifndef FOPEN
+# define FOPEN(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(M_I86SM) || defined(M_I86MM)) && !defined(_MSC_VER)
+ /* 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).
+ */
+# 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, Bytef* source, uInt len));
+ extern int zmemcmp OF((Bytef* s1, Bytef* s2, uInt len));
+ extern void zmemzero OF((Bytef* dest, uInt len));
+#endif
+
+/* Diagnostic functions */
+#ifdef DEBUG_ZLIB
+# include <stdio.h>
+# ifndef verbose
+# define verbose 0
+# endif
+ extern void z_error OF((char *m));
+# define Assert(cond,msg) {if(!(cond)) z_error(msg);}
+# define Trace(x) fprintf x
+# define Tracev(x) {if (verbose) fprintf x ;}
+# define Tracevv(x) {if (verbose>1) fprintf x ;}
+# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
+# define Tracecv(c,x) {if (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 (*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 */
+/* --- zutil.h */
+
+/* +++ deflate.h */
+/* deflate.h -- internal compression state
+ * Copyright (C) 1995-1996 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.
+ */
+
+/* From: deflate.h,v 1.10 1996/07/02 12:41:00 me 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 deflate_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 */
+ ulg compressed_len; /* total bit length of compressed file */
+ uInt matches; /* number of string matches in current block */
+ int last_eob_len; /* bit length of EOB code for last block */
+
+#ifdef DEBUG_ZLIB
+ ulg bits_sent; /* bit length of the compressed data */
+#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));
+ulg _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));
+void _tr_stored_type_only OF((deflate_state *));
+
+#endif
+/* --- deflate.h */
+
+/* +++ deflate.c */
+/* deflate.c -- compress data using the deflation algorithm
+ * Copyright (C) 1995-1996 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
+ *
+ */
+
+/* From: deflate.c,v 1.15 1996/07/24 13:40:58 me Exp $ */
+
+/* #include "deflate.h" */
+
+char deflate_copyright[] = " deflate 1.0.4 Copyright 1995-1996 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, charf *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_ZLIB
+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 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 */
+
+#ifndef NO_DUMMY_DECL
+struct static_tree_desc_s {int dummy;}; /* for buggy compilers */
+#endif
+
+/* ===========================================================================
+ * 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.
+ * 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).
+ */
+#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))
+
+/* ===========================================================================
+ * 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((charf *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));
+
+/* ========================================================================= */
+int 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 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 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;
+#ifndef NO_ZCFUNCS
+ if (strm->zalloc == Z_NULL) {
+ strm->zalloc = zcalloc;
+ strm->opaque = (voidpf)0;
+ }
+ if (strm->zfree == Z_NULL) strm->zfree = zcfree;
+#endif
+
+ if (level == Z_DEFAULT_COMPRESSION) level = 6;
+
+ 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 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)
+ return Z_STREAM_ERROR;
+
+ s = (deflate_state *) strm->state;
+ if (s->status != INIT_STATE) return Z_STREAM_ERROR;
+
+ 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((charf *)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 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 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 = (deflate_state *) 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;
+{
+ deflate_state *s = (deflate_state *) strm->state;
+ unsigned len = s->pending;
+
+ if (len > strm->avail_out) len = strm->avail_out;
+ if (len == 0) return;
+
+ if (strm->next_out != Z_NULL) {
+ zmemcpy(strm->next_out, s->pending_out, len);
+ strm->next_out += len;
+ }
+ s->pending_out += len;
+ strm->total_out += len;
+ strm->avail_out -= len;
+ s->pending -= len;
+ if (s->pending == 0) {
+ s->pending_out = s->pending_buf;
+ }
+}
+
+/* ========================================================================= */
+int 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 = (deflate_state *) strm->state;
+
+ if ((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 if (flush == Z_PACKET_FLUSH) {
+ /* Output just the 3-bit `stored' block type value,
+ but not a zero length. */
+ _tr_stored_type_only(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 deflateEnd (strm)
+ z_streamp strm;
+{
+ int status;
+ deflate_state *s;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ s = (deflate_state *) strm->state;
+
+ status = s->status;
+ if (status != INIT_STATE && status != BUSY_STATE &&
+ status != FINISH_STATE) {
+ return Z_STREAM_ERROR;
+ }
+
+ /* Deallocate in reverse order of allocations: */
+ TRY_FREE(strm, s->pending_buf);
+ TRY_FREE(strm, s->head);
+ TRY_FREE(strm, s->prev);
+ TRY_FREE(strm, s->window);
+
+ ZFREE(strm, s);
+ strm->state = Z_NULL;
+
+ return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
+}
+
+/* =========================================================================
+ * Copy the source state to the destination state.
+ */
+int deflateCopy (dest, source)
+ z_streamp dest;
+ z_streamp source;
+{
+ deflate_state *ds;
+ deflate_state *ss;
+ ushf *overlay;
+
+ if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL)
+ return Z_STREAM_ERROR;
+ ss = (deflate_state *) source->state;
+
+ zmemcpy(dest, source, sizeof(*dest));
+
+ ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
+ if (ds == Z_NULL) return Z_MEM_ERROR;
+ dest->state = (struct internal_state FAR *) ds;
+ zmemcpy(ds, ss, sizeof(*ds));
+ 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 doesn't work for 16-bit MSDOS */
+ zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
+ zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos));
+ zmemcpy(ds->head, 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;
+}
+
+/* ===========================================================================
+ * Return the number of bytes of output which are immediately available
+ * for output from the decompressor.
+ */
+int deflateOutputPending (strm)
+ z_streamp strm;
+{
+ if (strm == Z_NULL || strm->state == Z_NULL) return 0;
+
+ return ((deflate_state *)(strm->state))->pending;
+}
+
+/* ===========================================================================
+ * 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;
+ charf *buf;
+ unsigned size;
+{
+ unsigned len = strm->avail_in;
+
+ if (len > size) len = size;
+ if (len == 0) return 0;
+
+ strm->avail_in -= len;
+
+ if (!((deflate_state *)(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.
+ */
+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 best_len;
+ return s->lookahead;
+}
+#endif /* ASMV */
+
+#ifdef DEBUG_ZLIB
+/* ===========================================================================
+ * 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((charf *)s->window + match,
+ (charf *)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((charf *)s->window, (charf *)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;
+ 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);
+ 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, (charf *)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);
+
+ bflush = _tr_tally(s, s->strstart - s->match_start,
+ s->match_length - MIN_MATCH);
+
+ 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.
+ */
+ 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 {
+ 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]));
+ bflush = _tr_tally (s, 0, s->window[s->strstart]);
+ 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);
+
+ bflush = _tr_tally(s, s->strstart -1 - s->prev_match,
+ s->prev_length - MIN_MATCH);
+
+ /* 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]));
+ if (_tr_tally (s, 0, s->window[s->strstart-1])) {
+ 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 (s, 0, s->window[s->strstart-1]);
+ s->match_available = 0;
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
+/* --- deflate.c */
+
+/* +++ trees.c */
+/* trees.c -- output deflated data using Huffman coding
+ * Copyright (C) 1995-1996 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.
+ */
+
+/* From: trees.c,v 1.11 1996/07/24 13:41:06 me Exp $ */
+
+/* #include "deflate.h" */
+
+#ifdef DEBUG_ZLIB
+# 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 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 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 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 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.
+ */
+
+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.)
+ */
+
+local uch dist_code[512];
+/* 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.
+ */
+
+local 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) */
+
+struct static_tree_desc_s {
+ ct_data *static_tree; /* static tree or NULL */
+ 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 =
+{(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));
+
+#ifndef DEBUG_ZLIB
+# 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_ZLIB */
+# define send_code(s, c, tree) \
+ { if (verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \
+ send_bits(s, tree[c].Code, tree[c].Len); }
+#endif
+
+#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.
+ */
+
+/* ===========================================================================
+ * 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_ZLIB
+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_ZLIB */
+
+#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_ZLIB */
+
+
+#define MAX(a,b) (a >= b ? a : b)
+/* the arguments must not have side effects */
+
+/* ===========================================================================
+ * Initialize the various 'constant' tables. In a multi-threaded environment,
+ * this function may be called by two threads concurrently, but this is
+ * harmless since both invocations do exactly the same thing.
+ */
+local void tr_static_init()
+{
+ 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;
+
+ /* 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;
+}
+
+/* ===========================================================================
+ * Initialize the tree data structures for a new zlib stream.
+ */
+void _tr_init(s)
+ deflate_state *s;
+{
+ tr_static_init();
+
+ s->compressed_len = 0L;
+
+ 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_ZLIB
+ 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;
+ ct_data *stree = desc->stat_desc->static_tree;
+ 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;
+ 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 */
+ s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
+ s->compressed_len += (stored_len + 4) << 3;
+
+ copy_block(s, buf, (unsigned)stored_len, 1); /* with header */
+}
+
+/* Send just the `stored block' type code without any length bytes or data.
+ */
+void _tr_stored_type_only(s)
+ deflate_state *s;
+{
+ send_bits(s, (STORED_BLOCK << 1), 3);
+ bi_windup(s);
+ s->compressed_len = (s->compressed_len + 3) & ~7L;
+}
+
+
+/* ===========================================================================
+ * 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);
+ s->compressed_len += 10L; /* 3 for block type, 7 for EOB */
+ 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);
+ s->compressed_len += 10L;
+ 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. This function
+ * returns the total compressed length for the file so far.
+ */
+ulg _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 */
+ }
+
+ /* If compression failed and this is the first and last block,
+ * and if the .zip file can be seeked (to rewrite the local header),
+ * the whole file is transformed into a stored file:
+ */
+#ifdef STORED_FILE_OK
+# ifdef FORCE_STORED_FILE
+ if (eof && s->compressed_len == 0L) { /* force stored file */
+# else
+ if (stored_len <= opt_lenb && eof && s->compressed_len==0L && seekable()) {
+# endif
+ /* Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there: */
+ if (buf == (charf*)0) error ("block vanished");
+
+ copy_block(s, buf, (unsigned)stored_len, 0); /* without header */
+ s->compressed_len = stored_len << 3;
+ s->method = STORED;
+ } else
+#endif /* STORED_FILE_OK */
+
+#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);
+ s->compressed_len += 3 + s->static_len;
+ } 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);
+ s->compressed_len += 3 + s->opt_len;
+ }
+ Assert (s->compressed_len == s->bits_sent, "bad compressed size");
+ init_block(s);
+
+ if (eof) {
+ bi_windup(s);
+ s->compressed_len += 7; /* align on byte boundary */
+ }
+ Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
+ s->compressed_len-7*eof));
+
+ return s->compressed_len >> 3;
+}
+
+/* ===========================================================================
+ * 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++;
+ }
+
+ /* Try to guess if it is profitable to stop the current block here */
+ if (s->level > 2 && (s->last_lit & 0xfff) == 0) {
+ /* 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;
+ }
+ 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_ZLIB
+ 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_ZLIB
+ s->bits_sent += 2*16;
+#endif
+ }
+#ifdef DEBUG_ZLIB
+ s->bits_sent += (ulg)len<<3;
+#endif
+ /* bundle up the put_byte(s, *buf++) calls */
+ zmemcpy(&s->pending_buf[s->pending], buf, len);
+ s->pending += len;
+}
+/* --- trees.c */
+
+/* +++ inflate.c */
+/* inflate.c -- zlib interface to inflate modules
+ * Copyright (C) 1995-1996 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* #include "zutil.h" */
+
+/* +++ infblock.h */
+/* infblock.h -- header to use infblock.c
+ * Copyright (C) 1995-1996 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 ,
+ uLongf *)); /* check value on output */
+
+extern void inflate_set_dictionary OF((
+ inflate_blocks_statef *s,
+ const Bytef *d, /* dictionary */
+ uInt n)); /* dictionary length */
+
+extern int inflate_addhistory OF((
+ inflate_blocks_statef *,
+ z_streamp));
+
+extern int inflate_packet_flush OF((
+ inflate_blocks_statef *));
+/* --- infblock.h */
+
+#ifndef NO_DUMMY_DECL
+struct inflate_blocks_state {int dummy;}; /* for buggy compilers */
+#endif
+
+/* inflate private state */
+struct internal_state {
+
+ /* mode */
+ 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 */
+ 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 inflateReset(z)
+z_streamp z;
+{
+ uLong c;
+
+ 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, &c);
+ Trace((stderr, "inflate: reset\n"));
+ return Z_OK;
+}
+
+
+int inflateEnd(z)
+z_streamp z;
+{
+ uLong c;
+
+ 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, &c);
+ ZFREE(z, z->state);
+ z->state = Z_NULL;
+ Trace((stderr, "inflate: end\n"));
+ return Z_OK;
+}
+
+
+int 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;
+#ifndef NO_ZCFUNCS
+ if (z->zalloc == Z_NULL)
+ {
+ z->zalloc = zcalloc;
+ z->opaque = (voidpf)0;
+ }
+ if (z->zfree == Z_NULL) z->zfree = zcfree;
+#endif
+ 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;
+ }
+ Trace((stderr, "inflate: allocated\n"));
+
+ /* reset state */
+ inflateReset(z);
+ return Z_OK;
+}
+
+
+int 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)goto empty;r=Z_OK;}
+#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
+
+int 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 || f < 0)
+ return Z_STREAM_ERROR;
+ 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;
+ }
+ Trace((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 (f == Z_PACKET_FLUSH && z->avail_in == 0 && z->avail_out != 0)
+ r = inflate_packet_flush(z->state->blocks);
+ if (r == Z_DATA_ERROR)
+ {
+ z->state->mode = BAD;
+ z->state->sub.marker = 0; /* can try inflateSync */
+ break;
+ }
+ if (r != Z_STREAM_END)
+ return r;
+ r = Z_OK;
+ 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;
+ }
+ Trace((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;
+ }
+
+ empty:
+ if (f != Z_PACKET_FLUSH)
+ return r;
+ z->state->mode = BAD;
+ z->msg = (char *)"need more for packet flush";
+ z->state->sub.marker = 0; /* can try inflateSync */
+ return Z_DATA_ERROR;
+}
+
+
+int 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;
+}
+
+/*
+ * This subroutine adds the data at next_in/avail_in to the output history
+ * without performing any output. The output buffer must be "caught up";
+ * i.e. no pending output (hence s->read equals s->write), and the state must
+ * be BLOCKS (i.e. we should be willing to see the start of a series of
+ * BLOCKS). On exit, the output will also be caught up, and the checksum
+ * will have been updated if need be.
+ */
+
+int inflateIncomp(z)
+z_stream *z;
+{
+ if (z->state->mode != BLOCKS)
+ return Z_DATA_ERROR;
+ return inflate_addhistory(z->state->blocks, z);
+}
+
+
+int 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)
+ {
+ if (*p == (Byte)(m < 2 ? 0 : 0xff))
+ 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;
+}
+
+#undef NEEDBYTE
+#undef NEXTBYTE
+/* --- inflate.c */
+
+/* +++ infblock.c */
+/* infblock.c -- interpret and process block types to last block
+ * Copyright (C) 1995-1996 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* #include "zutil.h" */
+/* #include "infblock.h" */
+
+/* +++ inftrees.h */
+/* inftrees.h -- header to use inftrees.c
+ * Copyright (C) 1995-1996 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;
+ Bytef *pad; /* pad structure to a power of 2 (4 bytes for */
+ } word; /* 16-bit, 8 bytes for 32-bit machines) */
+ union {
+ uInt Base; /* literal, length base, or distance base */
+ inflate_huft *Next; /* pointer to next level of table */
+ } more;
+};
+
+#ifdef DEBUG_ZLIB
+ extern uInt inflate_hufts;
+#endif
+
+extern int inflate_trees_bits OF((
+ uIntf *, /* 19 code lengths */
+ uIntf *, /* bits tree desired/actual depth */
+ inflate_huft * FAR *, /* bits tree result */
+ z_streamp )); /* for zalloc, zfree functions */
+
+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 */
+ z_streamp )); /* for zalloc, zfree functions */
+
+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 */
+
+extern int inflate_trees_free OF((
+ inflate_huft *, /* tables to free */
+ z_streamp )); /* for zfree function */
+
+/* --- inftrees.h */
+
+/* +++ infcodes.h */
+/* infcodes.h -- header to use infcodes.c
+ * Copyright (C) 1995-1996 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 ));
+
+/* --- infcodes.h */
+
+/* +++ infutil.h */
+/* infutil.h -- types and macros common to blocks and codes
+ * Copyright (C) 1995-1996 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 */
+ DONEB, /* finished last block, done */
+ BADB} /* 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_huft *tl;
+ inflate_huft *td; /* trees to free */
+ 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 */
+ 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 WWRAP {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){WWRAP if(m==0){FLUSH WWRAP 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));
+
+#ifndef NO_DUMMY_DECL
+struct internal_state {int dummy;}; /* for buggy compilers */
+#endif
+
+#endif
+/* --- infutil.h */
+
+#ifndef NO_DUMMY_DECL
+struct inflate_codes_state {int dummy;}; /* for buggy compilers */
+#endif
+
+/* 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 (s->checkfn != 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);
+ inflate_trees_free(s->sub.decode.td, z);
+ inflate_trees_free(s->sub.decode.tl, 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, Z_NULL, 0);
+ Trace((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->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL)
+ {
+ ZFREE(z, s);
+ return Z_NULL;
+ }
+ s->end = s->window + w;
+ s->checkfn = c;
+ s->mode = TYPE;
+ Trace((stderr, "inflate: blocks allocated\n"));
+ inflate_blocks_reset(s, z, &s->check);
+ return s;
+}
+
+
+#ifdef DEBUG_ZLIB
+ extern uInt inflate_hufts;
+#endif
+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 */
+ Trace((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 */
+ Trace((stderr, "inflate: fixed codes block%s\n",
+ s->last ? " (last)" : ""));
+ {
+ uInt bl, bd;
+ inflate_huft *tl, *td;
+
+ inflate_trees_fixed(&bl, &bd, &tl, &td);
+ s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
+ if (s->sub.decode.codes == Z_NULL)
+ {
+ r = Z_MEM_ERROR;
+ LEAVE
+ }
+ s->sub.decode.tl = Z_NULL; /* don't try to free these */
+ s->sub.decode.td = Z_NULL;
+ }
+ DUMPBITS(3)
+ s->mode = CODES;
+ break;
+ case 2: /* dynamic */
+ Trace((stderr, "inflate: dynamic codes block%s\n",
+ s->last ? " (last)" : ""));
+ DUMPBITS(3)
+ s->mode = TABLE;
+ break;
+ case 3: /* illegal */
+ DUMPBITS(3)
+ s->mode = BADB;
+ z->msg = (char*)"invalid block type";
+ r = Z_DATA_ERROR;
+ LEAVE
+ }
+ break;
+ case LENS:
+ NEEDBITS(32)
+ if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
+ {
+ s->mode = BADB;
+ 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 = BADB;
+ z->msg = (char*)"too many length or distance symbols";
+ r = Z_DATA_ERROR;
+ LEAVE
+ }
+#endif
+ t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
+ if (t < 19)
+ t = 19;
+ 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, z);
+ if (t != Z_OK)
+ {
+ ZFREE(z, s->sub.trees.blens);
+ r = t;
+ if (r == Z_DATA_ERROR)
+ s->mode = BADB;
+ 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->word.what.Bits;
+ c = h->more.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))
+ {
+ inflate_trees_free(s->sub.trees.tb, z);
+ ZFREE(z, s->sub.trees.blens);
+ s->mode = BADB;
+ 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;
+ }
+ }
+ inflate_trees_free(s->sub.trees.tb, z);
+ 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;
+#ifdef DEBUG_ZLIB
+ inflate_hufts = 0;
+#endif
+ t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
+ s->sub.trees.blens, &bl, &bd, &tl, &td, z);
+ ZFREE(z, s->sub.trees.blens);
+ if (t != Z_OK)
+ {
+ if (t == (uInt)Z_DATA_ERROR)
+ s->mode = BADB;
+ r = t;
+ LEAVE
+ }
+ Tracev((stderr, "inflate: trees ok, %d * %d bytes used\n",
+ inflate_hufts, sizeof(inflate_huft)));
+ if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
+ {
+ inflate_trees_free(td, z);
+ inflate_trees_free(tl, z);
+ r = Z_MEM_ERROR;
+ LEAVE
+ }
+ s->sub.decode.codes = c;
+ s->sub.decode.tl = tl;
+ s->sub.decode.td = td;
+ }
+ 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);
+ inflate_trees_free(s->sub.decode.td, z);
+ inflate_trees_free(s->sub.decode.tl, 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;
+ }
+ 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 */
+ }
+ s->mode = DRY;
+ case DRY:
+ FLUSH
+ if (s->read != s->write)
+ LEAVE
+ s->mode = DONEB;
+ case DONEB:
+ r = Z_STREAM_END;
+ LEAVE
+ case BADB:
+ r = Z_DATA_ERROR;
+ LEAVE
+ default:
+ r = Z_STREAM_ERROR;
+ LEAVE
+ }
+}
+
+
+int inflate_blocks_free(s, z, c)
+inflate_blocks_statef *s;
+z_streamp z;
+uLongf *c;
+{
+ inflate_blocks_reset(s, z, c);
+ ZFREE(z, s->window);
+ ZFREE(z, s);
+ Trace((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((charf *)s->window, d, n);
+ s->read = s->write = s->window + n;
+}
+
+/*
+ * This subroutine adds the data at next_in/avail_in to the output history
+ * without performing any output. The output buffer must be "caught up";
+ * i.e. no pending output (hence s->read equals s->write), and the state must
+ * be BLOCKS (i.e. we should be willing to see the start of a series of
+ * BLOCKS). On exit, the output will also be caught up, and the checksum
+ * will have been updated if need be.
+ */
+int inflate_addhistory(s, z)
+inflate_blocks_statef *s;
+z_stream *z;
+{
+ uLong b; /* bit buffer */ /* NOT USED HERE */
+ uInt k; /* bits in bit buffer */ /* NOT USED HERE */
+ uInt t; /* temporary storage */
+ 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 */
+
+ if (s->read != s->write)
+ return Z_STREAM_ERROR;
+ if (s->mode != TYPE)
+ return Z_DATA_ERROR;
+
+ /* we're ready to rock */
+ LOAD
+ /* while there is input ready, copy to output buffer, moving
+ * pointers as needed.
+ */
+ while (n) {
+ t = n; /* how many to do */
+ /* is there room until end of buffer? */
+ if (t > m) t = m;
+ /* update check information */
+ if (s->checkfn != Z_NULL)
+ s->check = (*s->checkfn)(s->check, q, t);
+ zmemcpy(q, p, t);
+ q += t;
+ p += t;
+ n -= t;
+ z->total_out += t;
+ s->read = q; /* drag read pointer forward */
+/* WWRAP */ /* expand WWRAP macro by hand to handle s->read */
+ if (q == s->end) {
+ s->read = q = s->window;
+ m = WAVAIL;
+ }
+ }
+ UPDATE
+ return Z_OK;
+}
+
+
+/*
+ * At the end of a Deflate-compressed PPP packet, we expect to have seen
+ * a `stored' block type value but not the (zero) length bytes.
+ */
+int inflate_packet_flush(s)
+ inflate_blocks_statef *s;
+{
+ if (s->mode != LENS)
+ return Z_DATA_ERROR;
+ s->mode = TYPE;
+ return Z_OK;
+}
+/* --- infblock.c */
+
+/* +++ inftrees.c */
+/* inftrees.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995-1996 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* #include "zutil.h" */
+/* #include "inftrees.h" */
+
+char inflate_copyright[] = " inflate 1.0.4 Copyright 1995-1996 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.
+ */
+
+#ifndef NO_DUMMY_DECL
+struct internal_state {int dummy;}; /* for buggy compilers */
+#endif
+
+/* simplify the use of the inflate_huft type with some defines */
+#define base more.Base
+#define next more.Next
+#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) */
+ z_streamp )); /* for zalloc function */
+
+local voidpf falloc OF((
+ voidpf, /* opaque pointer (not used) */
+ uInt, /* number of items */
+ uInt)); /* size of item */
+
+/* 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 */
+#define N_MAX 288 /* maximum number of codes in any set */
+
+#ifdef DEBUG_ZLIB
+ uInt inflate_hufts;
+#endif
+
+local int huft_build(b, n, s, d, e, t, m, zs)
+uIntf *b; /* code lengths in bits (all assumed <= BMAX) */
+uInt n; /* number of codes (assumed <= N_MAX) */
+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 */
+z_streamp zs; /* for zalloc function */
+/* 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) */
+ 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 */
+ uInt v[N_MAX]; /* values in order of bit length */
+ 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 and link in new table */
+ if ((q = (inflate_huft *)ZALLOC
+ (zs,z + 1,sizeof(inflate_huft))) == Z_NULL)
+ {
+ if (h)
+ inflate_trees_free(u[0], zs);
+ return Z_MEM_ERROR; /* not enough memory */
+ }
+#ifdef DEBUG_ZLIB
+ inflate_hufts += z + 1;
+#endif
+ *t = q + 1; /* link to list for huft_free() */
+ *(t = &(q->next)) = Z_NULL;
+ u[h] = ++q; /* table starts after link */
+
+ /* 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 */
+ r.next = q; /* pointer to this table */
+ j = i >> (w - l); /* (get around Turbo C bug) */
+ u[h-1][j] = r; /* connect to last table */
+ }
+ }
+
+ /* 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 */
+ while ((i & ((1 << w) - 1)) != x[h])
+ {
+ h--; /* don't need to update q */
+ w -= l;
+ }
+ }
+ }
+
+
+ /* 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, z)
+uIntf *c; /* 19 code lengths */
+uIntf *bb; /* bits tree desired/actual depth */
+inflate_huft * FAR *tb; /* bits tree result */
+z_streamp z; /* for zfree function */
+{
+ int r;
+
+ r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, tb, bb, z);
+ if (r == Z_DATA_ERROR)
+ z->msg = (char*)"oversubscribed dynamic bit lengths tree";
+ else if (r == Z_BUF_ERROR || *bb == 0)
+ {
+ inflate_trees_free(*tb, z);
+ z->msg = (char*)"incomplete dynamic bit lengths tree";
+ r = Z_DATA_ERROR;
+ }
+ return r;
+}
+
+
+int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, 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 */
+z_streamp z; /* for zfree function */
+{
+ int r;
+
+ /* build literal/length tree */
+ r = huft_build(c, nl, 257, cplens, cplext, tl, bl, z);
+ if (r != Z_OK || *bl == 0)
+ {
+ if (r == Z_DATA_ERROR)
+ z->msg = (char*)"oversubscribed literal/length tree";
+ else if (r != Z_MEM_ERROR)
+ {
+ inflate_trees_free(*tl, z);
+ z->msg = (char*)"incomplete literal/length tree";
+ r = Z_DATA_ERROR;
+ }
+ return r;
+ }
+
+ /* build distance tree */
+ r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, z);
+ 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
+ inflate_trees_free(*td, z);
+ 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;
+ }
+ inflate_trees_free(*tl, z);
+ return r;
+#endif
+ }
+
+ /* done */
+ return Z_OK;
+}
+
+
+/* build fixed tables only once--keep them here */
+local int fixed_built = 0;
+#define FIXEDH 530 /* 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;
+
+
+local voidpf falloc(q, n, s)
+voidpf q; /* opaque pointer */
+uInt n; /* number of items */
+uInt s; /* size of item */
+{
+ Assert(s == sizeof(inflate_huft) && n <= *(intf *)q,
+ "inflate_trees falloc overflow");
+ *(intf *)q -= n+s-s; /* s-s to avoid warning */
+ return (voidpf)(fixed_mem + *(intf *)q);
+}
+
+
+int inflate_trees_fixed(bl, bd, tl, td)
+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 */
+{
+ /* build fixed tables if not already (multiple overlapped executions ok) */
+ if (!fixed_built)
+ {
+ int k; /* temporary variable */
+ unsigned c[288]; /* length list for huft_build */
+ z_stream z; /* for falloc function */
+ int f = FIXEDH; /* number of hufts left in fixed_mem */
+
+ /* set up fake z_stream for memory routines */
+ z.zalloc = falloc;
+ z.zfree = Z_NULL;
+ z.opaque = (voidpf)&f;
+
+ /* 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 = 7;
+ huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, &z);
+
+ /* 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, &z);
+
+ /* done */
+ Assert(f == 0, "invalid build of fixed tables");
+ fixed_built = 1;
+ }
+ *bl = fixed_bl;
+ *bd = fixed_bd;
+ *tl = fixed_tl;
+ *td = fixed_td;
+ return Z_OK;
+}
+
+
+int inflate_trees_free(t, z)
+inflate_huft *t; /* table to free */
+z_streamp z; /* for zfree function */
+/* Free the malloc'ed tables built by huft_build(), which makes a linked
+ list of the tables it made, with the links in a dummy first entry of
+ each table. */
+{
+ register inflate_huft *p, *q, *r;
+
+ /* Reverse linked list */
+ p = Z_NULL;
+ q = t;
+ while (q != Z_NULL)
+ {
+ r = (q - 1)->next;
+ (q - 1)->next = p;
+ p = q;
+ q = r;
+ }
+ /* Go through linked list, freeing from the malloced (t[-1]) address. */
+ while (p != Z_NULL)
+ {
+ q = (--p)->next;
+ ZFREE(z,p);
+ p = q;
+ }
+ return Z_OK;
+}
+/* --- inftrees.c */
+
+/* +++ infcodes.c */
+/* infcodes.c -- process literals and length/distance pairs
+ * Copyright (C) 1995-1996 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" */
+
+/* +++ inffast.h */
+/* inffast.h -- header to use inffast.c
+ * Copyright (C) 1995-1996 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 ));
+/* --- inffast.h */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define base more.Base
+#define next more.Next
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* inflate codes private state */
+struct inflate_codes_state {
+
+ /* mode */
+ 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 */
+ 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->next;
+ 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->next;
+ 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 */
+ 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
+ }
+}
+
+
+void inflate_codes_free(c, z)
+inflate_codes_statef *c;
+z_streamp z;
+{
+ ZFREE(z, c);
+ Tracev((stderr, "inflate: codes free\n"));
+}
+/* --- infcodes.c */
+
+/* +++ infutil.c */
+/* inflate_util.c -- data and routines common to blocks and codes
+ * Copyright (C) 1995-1996 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" */
+
+#ifndef NO_DUMMY_DECL
+struct inflate_codes_state {int dummy;}; /* for buggy compilers */
+#endif
+
+/* 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 */
+ if (p != Z_NULL) {
+ 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 */
+ if (p != Z_NULL) {
+ zmemcpy(p, q, n);
+ p += n;
+ }
+ q += n;
+ }
+
+ /* update pointers */
+ z->next_out = p;
+ s->read = q;
+
+ /* done */
+ return r;
+}
+/* --- infutil.c */
+
+/* +++ inffast.c */
+/* inffast.c -- process literals and length/distance pairs fast
+ * Copyright (C) 1995-1996 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" */
+
+#ifndef NO_DUMMY_DECL
+struct inflate_codes_state {int dummy;}; /* for buggy compilers */
+#endif
+
+/* simplify the use of the inflate_huft type with some defines */
+#define base more.Base
+#define next more.Next
+#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 {n+=(c=k>>3);p-=c;k&=7;}
+
+/* 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)
+ e = (t = t->next + ((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)
+ {
+ if ((e = (t = t->next + ((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;
+}
+/* --- inffast.c */
+
+/* +++ zutil.c */
+/* zutil.c -- target dependent utility functions for the compression library
+ * Copyright (C) 1995-1996 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* From: zutil.c,v 1.17 1996/07/24 13:41:12 me Exp $ */
+
+#ifdef DEBUG_ZLIB
+#include <stdio.h>
+#endif
+
+/* #include "zutil.h" */
+
+#ifndef NO_DUMMY_DECL
+struct internal_state {int dummy;}; /* for buggy compilers */
+#endif
+
+#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 *zlibVersion()
+{
+ return ZLIB_VERSION;
+}
+
+#ifdef DEBUG_ZLIB
+void z_error (m)
+ char *m;
+{
+ fprintf(stderr, "%s\n", m);
+ exit(1);
+}
+#endif
+
+#ifndef HAVE_MEMCPY
+
+void zmemcpy(dest, source, len)
+ Bytef* dest;
+ Bytef* source;
+ uInt len;
+{
+ if (len == 0) return;
+ do {
+ *dest++ = *source++; /* ??? to be unrolled */
+ } while (--len != 0);
+}
+
+int zmemcmp(s1, s2, len)
+ Bytef* s1;
+ 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 */
+/* --- zutil.c */
+
+/* +++ adler32.c */
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995-1996 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* From: adler32.c,v 1.10 1996/05/22 11:52:18 me 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 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;
+}
+/* --- adler32.c */
diff --git a/cpukit/libnetworking/net/zlib.h b/cpukit/libnetworking/net/zlib.h
new file mode 100644
index 0000000000..188ddaff9f
--- /dev/null
+++ b/cpukit/libnetworking/net/zlib.h
@@ -0,0 +1,1010 @@
+/* $Id$ */
+
+/*
+ * This file is derived from zlib.h and zconf.h from the zlib-1.0.4
+ * distribution by Jean-loup Gailly and Mark Adler, with some additions
+ * by Paul Mackerras to aid in implementing Deflate compression and
+ * decompression for PPP packets.
+ */
+
+/*
+ * ==FILEVERSION 971127==
+ *
+ * This marker is used by the Linux installation script to determine
+ * whether an up-to-date version of this file is already installed.
+ */
+
+
+/* +++ zlib.h */
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+ version 1.0.4, Jul 24th, 1996.
+
+ Copyright (C) 1995-1996 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
+ gzip@prep.ai.mit.edu 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
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* +++ zconf.h */
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-1996 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* From: zconf.h,v 1.20 1996/07/02 15:09:28 me 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 inflateReset z_inflateReset
+# define compress z_compress
+# 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(STDC)
+# define STDC
+#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
+
+/* 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 */
+#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 */
+# ifdef STDC
+# 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
+#ifndef FAR
+# define FAR
+#endif
+
+typedef unsigned char Byte; /* 8 bits */
+typedef unsigned int uInt; /* 16 bits or more */
+typedef unsigned long uLong; /* 32 bits or more */
+
+#if defined(__BORLANDC__) && defined(SMALL_MEDIUM)
+ /* Borland C/C++ ignores 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
+
+
+/* Compile with -DZLIB_DLL for Windows DLL support */
+#if (defined(_WINDOWS) || defined(WINDOWS)) && defined(ZLIB_DLL)
+# include <windows.h>
+# define EXPORT WINAPI
+#else
+# define EXPORT
+#endif
+
+#endif /* _ZCONF_H */
+/* --- zconf.h */
+
+#define ZLIB_VERSION "1.0.4P"
+
+/*
+ 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 may be added later and will have the same
+ stream interface.
+
+ For compression the application must provide the output buffer and
+ may optionally provide the input buffer for optimization. For decompression,
+ the application must provide the input buffer and may optionally provide
+ the output buffer for optimization.
+
+ 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 does not install any signal handler. It is recommended to
+ add at least a handler for SIGSEGV when decompressing; the library checks
+ the consistency of the input data whenever possible but may go nuts
+ for some forms 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.
+ 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
+#define Z_PACKET_FLUSH 2
+#define Z_SYNC_FLUSH 3
+#define Z_FULL_FLUSH 4
+#define Z_FINISH 5
+/* 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 */
+
+extern const char * EXPORT 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.
+ */
+
+/*
+extern int EXPORT 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().
+*/
+
+
+extern int EXPORT deflate OF((z_streamp strm, int flush));
+/*
+ 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_PARTIAL_FLUSH, the current compression
+ block is terminated and flushed to the output buffer so that the
+ decompressor can get all input data available so far. For method 9, a future
+ variant on method 8, the current block will be flushed but not terminated.
+ Z_SYNC_FLUSH has the same effect as partial flush except that the compressed
+ output is byte aligned (the compressor can clear its internal bit buffer)
+ and the current block is always terminated; this can be useful if the
+ compressor has to be restarted from scratch after an interruption (in which
+ case the internal state of the compressor may be lost).
+ If flush is set to Z_FULL_FLUSH, the compression block is terminated, a
+ special marker is output and the compression dictionary is discarded; this
+ is useful to allow the decompressor to synchronize if one compressed block
+ has been damaged (see inflateSync below). Flushing degrades compression and
+ so should be used only when necessary. 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_PACKET_FLUSH, the compression
+ block is terminated, and a zero-length stored block is output,
+ omitting the length bytes (the effect of this is that the 3-bit type
+ code 000 for a stored block is output, and the output is then
+ byte-aligned). This is designed for use at the end of a PPP packet.
+
+ 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() 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.
+*/
+
+
+extern int EXPORT 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).
+*/
+
+
+/*
+extern int EXPORT inflateInit OF((z_streamp strm));
+
+ Initializes the internal stream state for decompression. The fields
+ zalloc, zfree and opaque must be initialized before by the caller. 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: this will be
+ done by inflate().
+*/
+
+
+extern int EXPORT inflate OF((z_streamp strm, int flush));
+/*
+ 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_PARTIAL_FLUSH or Z_PACKET_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_PARTIAL_FLUSH, Z_PACKET_FLUSH or Z_FINISH, but the
+ current implementation actually flushes as much output as possible
+ anyway. For Z_PACKET_FLUSH, inflate checks that once all the input data
+ has been consumed, it is expecting to see the length field of a stored
+ block; if not, it returns Z_DATA_ERROR.
+
+ 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.
+
+ 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 (see
+ inflateSetDictionary below), Z_DATA_ERROR if the input data was corrupted,
+ 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.
+ In the Z_NEED_DICT case, strm->adler is set to the Adler32 value of the
+ dictionary chosen by the compressor.
+*/
+
+
+extern int EXPORT 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.
+*/
+
+/*
+extern int EXPORT 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. (Method 9 will allow a 64K history buffer and
+ partial block flushes.)
+
+ 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 (the value 16 will be allowed for method 9). 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.
+
+ If next_in is not null, the library will use this buffer to hold also
+ some history information; the buffer must either hold the entire input
+ data, or have at least 1<<(windowBits+1) bytes and be writable. If next_in
+ is null, the library will allocate its own history buffer (and leave next_in
+ null). next_out need not be provided here but must be provided by the
+ application for the next call of deflate().
+
+ If the history buffer is provided by the application, next_in must
+ must never be changed by the application since the compressor maintains
+ information inside this buffer from call to call; the application
+ must provide more input only by increasing avail_in. next_in is always
+ reset by the library in this case.
+
+ 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().
+*/
+
+extern int EXPORT deflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+/*
+ Initializes the compression dictionary (history buffer) from the given
+ byte sequence without producing any compressed output. This function must
+ be called immediately after deflateInit or deflateInit2, 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. In this version of the library,
+ only the last 32K bytes of the dictionary are used.
+ 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). deflateSetDictionary does not perform any compression: this will
+ be done by deflate().
+*/
+
+extern int EXPORT deflateCopy OF((z_streamp dest,
+ z_streamp source));
+/*
+ Sets the destination stream as a complete copy of the source stream. If
+ the source stream is using an application-supplied history buffer, a new
+ buffer is allocated for the destination stream. The compressed output
+ buffer is always application-supplied. It's the responsibility of the
+ application to provide the correct values of next_out and avail_out for the
+ next call of deflate.
+
+ 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.
+*/
+
+extern int EXPORT 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).
+*/
+
+extern int EXPORT deflateParams OF((z_streamp strm, int level, int strategy));
+/*
+ Dynamically update the compression level and compression strategy.
+ 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.
+*/
+
+extern int EXPORT deflateOutputPending OF((z_streamp strm));
+/*
+ Returns the number of bytes of output which are immediately
+ available from the compressor (i.e. without any further input
+ or flush).
+*/
+
+/*
+extern int EXPORT inflateInit2 OF((z_streamp strm,
+ int windowBits));
+
+ This is another version of inflateInit with more compression options. The
+ fields next_out, 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 value 16 will be allowed soon). 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.
+
+ If next_out is not null, the library will use this buffer for the history
+ buffer; the buffer must either be large enough to hold the entire output
+ data, or have at least 1<<windowBits bytes. If next_out is null, the
+ library will allocate its own buffer (and leave next_out null). next_in
+ need not be provided here but must be provided by the application for the
+ next call of inflate().
+
+ If the history buffer is provided by the application, next_out must
+ never be changed by the application since the decompressor maintains
+ history information inside this buffer from call to call; the application
+ can only reset next_out to the beginning of the history buffer when
+ avail_out is zero and all output has been consumed.
+
+ 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
+ windowBits < 8). msg is set to null if there is no error message.
+ inflateInit2 does not perform any decompression: this will be done by
+ inflate().
+*/
+
+extern int EXPORT inflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+/*
+ Initializes the decompression dictionary (history buffer) 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().
+*/
+
+extern int EXPORT inflateSync OF((z_streamp strm));
+/*
+ Skips invalid compressed data until the special marker (see deflate()
+ above) can be found, or until all available input is skipped. No output
+ is provided.
+
+ inflateSync returns Z_OK if the special marker has been found, Z_BUF_ERROR
+ if no more input was provided, Z_DATA_ERROR if no marker 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.
+*/
+
+extern int EXPORT 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).
+*/
+
+extern int inflateIncomp OF((z_stream *strm));
+/*
+ This function adds the data at next_in (avail_in bytes) to the output
+ history without performing any output. There must be no pending output,
+ and the decompressor must be expecting to see the start of a block.
+ Calling this function is equivalent to decompressing a stored block
+ containing the data at next_in (except that the data is not output).
+*/
+
+ /* 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, window size,
+ standard memory allocation functions). The source code of these
+ utility functions can easily be modified if you need special options.
+*/
+
+extern int EXPORT 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.
+*/
+
+extern int EXPORT 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;
+
+extern gzFile EXPORT 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"). 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).
+*/
+
+extern gzFile EXPORT 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.
+*/
+
+extern int EXPORT 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). */
+
+extern int EXPORT 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).
+*/
+
+extern int EXPORT 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.
+*/
+
+extern int EXPORT 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).
+*/
+
+extern const char * EXPORT 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.
+*/
+
+extern uLong EXPORT 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();
+*/
+
+extern uLong EXPORT 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:
+ */
+extern int EXPORT deflateInit_ OF((z_streamp strm, int level,
+ const char *version, int stream_size));
+extern int EXPORT inflateInit_ OF((z_streamp strm,
+ const char *version, int stream_size));
+extern int EXPORT deflateInit2_ OF((z_streamp strm, int level, int method,
+ int windowBits, int memLevel, int strategy,
+ const char *version, int stream_size));
+extern int EXPORT 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
+
+uLongf *get_crc_table OF((void)); /* can be used by asm versions of crc32() */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ZLIB_H */
+/* --- zlib.h */
diff --git a/cpukit/libnetworking/netdb.h b/cpukit/libnetworking/netdb.h
new file mode 100644
index 0000000000..ec274f851f
--- /dev/null
+++ b/cpukit/libnetworking/netdb.h
@@ -0,0 +1,182 @@
+/*-
+ * Copyright (c) 1980, 1983, 1988, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ * -
+ * --Copyright--
+ */
+
+/*
+ * @(#)netdb.h 8.1 (Berkeley) 6/2/93
+ * From: Id: netdb.h,v 8.9 1996/11/19 08:39:29 vixie Exp $
+ * $Id$
+ */
+
+#ifndef _NETDB_H_
+#define _NETDB_H_
+
+#include <sys/cdefs.h>
+
+#ifndef _PATH_HEQUIV
+# define _PATH_HEQUIV "/etc/hosts.equiv"
+#endif
+#define _PATH_HOSTS "/etc/hosts"
+#define _PATH_NETWORKS "/etc/networks"
+#define _PATH_PROTOCOLS "/etc/protocols"
+#define _PATH_SERVICES "/etc/services"
+
+extern int h_errno;
+
+/*
+ * Structures returned by network data base library. All addresses are
+ * supplied in host order, and returned in network order (suitable for
+ * use in system calls).
+ */
+struct hostent {
+ char *h_name; /* official name of host */
+ char **h_aliases; /* alias list */
+ int h_addrtype; /* host address type */
+ int h_length; /* length of address */
+ char **h_addr_list; /* list of addresses from name server */
+#define h_addr h_addr_list[0] /* address, for backward compatibility */
+};
+
+/*
+ * Assumption here is that a network number
+ * fits in an unsigned long -- probably a poor one.
+ */
+struct netent {
+ char *n_name; /* official name of net */
+ char **n_aliases; /* alias list */
+ int n_addrtype; /* net address type */
+ unsigned long n_net; /* network # */
+};
+
+struct servent {
+ char *s_name; /* official service name */
+ char **s_aliases; /* alias list */
+ int s_port; /* port # */
+ char *s_proto; /* protocol to use */
+};
+
+struct protoent {
+ char *p_name; /* official protocol name */
+ char **p_aliases; /* alias list */
+ int p_proto; /* protocol # */
+};
+
+/*
+ * Error return codes from gethostbyname() and gethostbyaddr()
+ * (left in extern int h_errno).
+ */
+
+#define NETDB_INTERNAL -1 /* see errno */
+#define NETDB_SUCCESS 0 /* no problem */
+#define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found */
+#define TRY_AGAIN 2 /* Non-Authoritative Host not found, or SERVERFAIL */
+#define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
+#define NO_DATA 4 /* Valid name, no data record of requested type */
+#define NO_ADDRESS NO_DATA /* no address, look for MX record */
+
+__BEGIN_DECLS
+void endhostent __P((void));
+void endnetent __P((void));
+void endprotoent __P((void));
+void endservent __P((void));
+struct hostent *gethostbyaddr __P((const char *, int, int));
+struct hostent *gethostbyname __P((const char *));
+struct hostent *gethostbyname2 __P((const char *, int));
+struct hostent *gethostent __P((void));
+struct netent *getnetbyaddr __P((unsigned long, int));
+struct netent *getnetbyname __P((const char *));
+struct netent *getnetent __P((void));
+struct protoent *getprotobyname __P((const char *));
+struct protoent *getprotobynumber __P((int));
+struct protoent *getprotoent __P((void));
+struct servent *getservbyname __P((const char *, const char *));
+struct servent *getservbyport __P((int, const char *));
+struct servent *getservent __P((void));
+void herror __P((const char *));
+__const char *hstrerror __P((int));
+void sethostent __P((int));
+/* void sethostfile __P((const char *)); */
+void setnetent __P((int));
+void setprotoent __P((int));
+void setservent __P((int));
+
+/*
+ * PRIVATE functions specific to the FreeBSD implementation
+ */
+
+/* DO NOT USE THESE, THEY ARE SUBJECT TO CHANGE AND ARE NOT PORTABLE!!! */
+void _sethosthtent __P((int));
+void _endhosthtent __P((void));
+void _sethostdnsent __P((int));
+void _endhostdnsent __P((void));
+void _setnethtent __P((int));
+void _endnethtent __P((void));
+void _setnetdnsent __P((int));
+void _endnetdnsent __P((void));
+struct hostent * _gethostbyhtname __P((const char *, int));
+struct hostent * _gethostbydnsname __P((const char *, int));
+struct hostent * _gethostbynisname __P((const char *, int));
+struct hostent * _gethostbyhtaddr __P((const char *, int, int));
+struct hostent * _gethostbydnsaddr __P((const char *, int, int));
+struct hostent * _gethostbynisaddr __P((const char *, int, int));
+struct netent * _getnetbyhtname __P((const char *));
+struct netent * _getnetbydnsname __P((const char *));
+struct netent * _getnetbynisname __P((const char *));
+struct netent * _getnetbyhtaddr __P((unsigned long, int));
+struct netent * _getnetbydnsaddr __P((unsigned long, int));
+struct netent * _getnetbynisaddr __P((unsigned long, int));
+void _map_v4v6_address __P((const char *src, char *dst));
+void _map_v4v6_hostent __P((struct hostent *hp, char **bp, int *len));
+__END_DECLS
+
+#endif /* !_NETDB_H_ */
diff --git a/cpukit/libnetworking/netinet/icmp_var.h b/cpukit/libnetworking/netinet/icmp_var.h
new file mode 100644
index 0000000000..8e005822ba
--- /dev/null
+++ b/cpukit/libnetworking/netinet/icmp_var.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)icmp_var.h 8.1 (Berkeley) 6/10/93
+ * $Id$
+ */
+
+#ifndef _NETINET_ICMP_VAR_H_
+#define _NETINET_ICMP_VAR_H_
+
+/*
+ * Variables related to this implementation
+ * of the internet control message protocol.
+ */
+struct icmpstat {
+/* statistics related to icmp packets generated */
+ u_long icps_error; /* # of calls to icmp_error */
+ u_long icps_oldshort; /* no error 'cuz old ip too short */
+ u_long icps_oldicmp; /* no error 'cuz old was icmp */
+ u_long icps_outhist[ICMP_MAXTYPE + 1];
+/* statistics related to input messages processed */
+ u_long icps_badcode; /* icmp_code out of range */
+ u_long icps_tooshort; /* packet < ICMP_MINLEN */
+ u_long icps_checksum; /* bad checksum */
+ u_long icps_badlen; /* calculated bound mismatch */
+ u_long icps_reflect; /* number of responses */
+ u_long icps_inhist[ICMP_MAXTYPE + 1];
+ u_long icps_bmcastecho; /* b/mcast echo requests dropped */
+ u_long icps_bmcasttstamp; /* b/mcast tstamp requests dropped */
+};
+
+/*
+ * Names for ICMP sysctl objects
+ */
+#define ICMPCTL_MASKREPL 1 /* allow replies to netmask requests */
+#define ICMPCTL_STATS 2 /* statistics (read-only) */
+#define ICMPCTL_MAXID 3
+
+#define ICMPCTL_NAMES { \
+ { 0, 0 }, \
+ { "maskrepl", CTLTYPE_INT }, \
+ { "stats", CTLTYPE_STRUCT }, \
+}
+
+#ifdef _KERNEL
+SYSCTL_DECL(_net_inet_icmp);
+extern struct icmpstat icmpstat;
+#endif
+
+#endif
diff --git a/cpukit/libnetworking/netinet/if_ether.c b/cpukit/libnetworking/netinet/if_ether.c
new file mode 100644
index 0000000000..c4b85aa38e
--- /dev/null
+++ b/cpukit/libnetworking/netinet/if_ether.c
@@ -0,0 +1,639 @@
+/*
+ * Copyright (c) 1982, 1986, 1988, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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_ether.c 8.1 (Berkeley) 6/10/93
+ * $Id$
+ */
+
+/*
+ * Ethernet address resolution protocol.
+ * TODO:
+ * add "inuse/lock" bit (or ref. count) along with valid bit
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <sys/queue.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/malloc.h>
+#include <sys/socket.h>
+#include <sys/syslog.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/route.h>
+#include <net/netisr.h>
+
+#include <netinet/in.h>
+#include <netinet/in_var.h>
+#include <netinet/if_ether.h>
+
+#define SIN(s) ((struct sockaddr_in *)s)
+#define SDL(s) ((struct sockaddr_dl *)s)
+
+SYSCTL_DECL(_net_link_ether);
+SYSCTL_NODE(_net_link_ether, PF_INET, inet, CTLFLAG_RW, 0, "");
+
+/* timer values */
+static int arpt_prune = (5*60*1); /* walk list every 5 minutes */
+static int arpt_keep = (20*60); /* once resolved, good for 20 more minutes */
+static int arpt_down = 20; /* once declared down, don't send for 20 sec */
+
+SYSCTL_INT(_net_link_ether_inet, OID_AUTO, prune_intvl, CTLFLAG_RW,
+ &arpt_prune, 0, "");
+SYSCTL_INT(_net_link_ether_inet, OID_AUTO, max_age, CTLFLAG_RW,
+ &arpt_keep, 0, "");
+SYSCTL_INT(_net_link_ether_inet, OID_AUTO, host_down_time, CTLFLAG_RW,
+ &arpt_down, 0, "");
+
+#define rt_expire rt_rmx.rmx_expire
+
+struct llinfo_arp {
+ LIST_ENTRY(llinfo_arp) la_le;
+ struct rtentry *la_rt;
+ struct mbuf *la_hold; /* last packet until resolved/timeout */
+ long la_asked; /* last time we QUERIED for this addr */
+#define la_timer la_rt->rt_rmx.rmx_expire /* deletion time in seconds */
+};
+
+static LIST_HEAD(, llinfo_arp) llinfo_arp;
+
+struct ifqueue arpintrq = {0, 0, 0, 50};
+static int arp_inuse, arp_allocated;
+
+static int arp_maxtries = 5;
+static int useloopback = 1; /* use loopback interface for local traffic */
+static int arp_proxyall = 0;
+
+SYSCTL_INT(_net_link_ether_inet, OID_AUTO, maxtries, CTLFLAG_RW,
+ &arp_maxtries, 0, "");
+SYSCTL_INT(_net_link_ether_inet, OID_AUTO, useloopback, CTLFLAG_RW,
+ &useloopback, 0, "");
+SYSCTL_INT(_net_link_ether_inet, OID_AUTO, proxyall, CTLFLAG_RW,
+ &arp_proxyall, 0, "");
+
+static void arp_rtrequest __P((int, struct rtentry *, struct sockaddr *));
+static void arprequest __P((struct arpcom *, u_long *, u_long *, u_char *));
+void arpintr __P((void));
+static void arptfree __P((struct llinfo_arp *));
+static void arptimer __P((void *));
+static struct llinfo_arp
+ *arplookup __P((u_long, int, int));
+static void in_arpinput __P((struct mbuf *));
+
+/*
+ * Timeout routine. Age arp_tab entries periodically.
+ */
+/* ARGSUSED */
+static void
+arptimer(ignored_arg)
+ void *ignored_arg;
+{
+ int s = splnet();
+ register struct llinfo_arp *la = llinfo_arp.lh_first;
+ struct llinfo_arp *ola;
+
+ timeout(arptimer, (caddr_t)0, arpt_prune * hz);
+ while ((ola = la) != 0) {
+ register struct rtentry *rt = la->la_rt;
+ la = la->la_le.le_next;
+ if (rt->rt_expire && rt->rt_expire <= rtems_bsdnet_seconds_since_boot())
+ arptfree(ola); /* timer has expired, clear */
+ }
+ splx(s);
+}
+
+/*
+ * Parallel to llc_rtrequest.
+ */
+static void
+arp_rtrequest(req, rt, sa)
+ int req;
+ register struct rtentry *rt;
+ struct sockaddr *sa;
+{
+ register struct sockaddr *gate = rt->rt_gateway;
+ register struct llinfo_arp *la = (struct llinfo_arp *)rt->rt_llinfo;
+ static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
+ static int arpinit_done;
+
+ if (!arpinit_done) {
+ arpinit_done = 1;
+ LIST_INIT(&llinfo_arp);
+ timeout(arptimer, (caddr_t)0, hz);
+ }
+ if (rt->rt_flags & RTF_GATEWAY)
+ return;
+ switch (req) {
+
+ case RTM_ADD:
+ /*
+ * XXX: If this is a manually added route to interface
+ * such as older version of routed or gated might provide,
+ * restore cloning bit.
+ */
+ if ((rt->rt_flags & RTF_HOST) == 0 &&
+ SIN(rt_mask(rt))->sin_addr.s_addr != 0xffffffff)
+ rt->rt_flags |= RTF_CLONING;
+ if (rt->rt_flags & RTF_CLONING) {
+ /*
+ * Case 1: This route should come from a route to iface.
+ */
+ rt_setgate(rt, rt_key(rt),
+ (struct sockaddr *)&null_sdl);
+ gate = rt->rt_gateway;
+ SDL(gate)->sdl_type = rt->rt_ifp->if_type;
+ SDL(gate)->sdl_index = rt->rt_ifp->if_index;
+ rt->rt_expire = rtems_bsdnet_seconds_since_boot();
+ break;
+ }
+ /* Announce a new entry if requested. */
+ if (rt->rt_flags & RTF_ANNOUNCE)
+ arprequest((struct arpcom *)rt->rt_ifp,
+ &SIN(rt_key(rt))->sin_addr.s_addr,
+ &SIN(rt_key(rt))->sin_addr.s_addr,
+ (u_char *)LLADDR(SDL(gate)));
+ /*FALLTHROUGH*/
+ case RTM_RESOLVE:
+ if (gate->sa_family != AF_LINK ||
+ gate->sa_len < sizeof(null_sdl)) {
+ log(LOG_DEBUG, "arp_rtrequest: bad gateway value\n");
+ break;
+ }
+ SDL(gate)->sdl_type = rt->rt_ifp->if_type;
+ SDL(gate)->sdl_index = rt->rt_ifp->if_index;
+ if (la != 0)
+ break; /* This happens on a route change */
+ /*
+ * Case 2: This route may come from cloning, or a manual route
+ * add with a LL address.
+ */
+ R_Malloc(la, struct llinfo_arp *, sizeof(*la));
+ rt->rt_llinfo = (caddr_t)la;
+ if (la == 0) {
+ log(LOG_DEBUG, "arp_rtrequest: malloc failed\n");
+ break;
+ }
+ arp_inuse++, arp_allocated++;
+ Bzero(la, sizeof(*la));
+ la->la_rt = rt;
+ rt->rt_flags |= RTF_LLINFO;
+ LIST_INSERT_HEAD(&llinfo_arp, la, la_le);
+
+ /*
+ * This keeps the multicast addresses from showing up
+ * in `arp -a' listings as unresolved. It's not actually
+ * functional. Then the same for broadcast.
+ */
+ if (IN_MULTICAST(ntohl(SIN(rt_key(rt))->sin_addr.s_addr))) {
+ ETHER_MAP_IP_MULTICAST(&SIN(rt_key(rt))->sin_addr,
+ LLADDR(SDL(gate)));
+ SDL(gate)->sdl_alen = 6;
+ rt->rt_expire = 0;
+ }
+ if (in_broadcast(SIN(rt_key(rt))->sin_addr, rt->rt_ifp)) {
+ memcpy(LLADDR(SDL(gate)), etherbroadcastaddr, 6);
+ SDL(gate)->sdl_alen = 6;
+ rt->rt_expire = 0;
+ }
+
+ if (SIN(rt_key(rt))->sin_addr.s_addr ==
+ (IA_SIN(rt->rt_ifa))->sin_addr.s_addr) {
+ /*
+ * This test used to be
+ * if (loif.if_flags & IFF_UP)
+ * It allowed local traffic to be forced
+ * through the hardware by configuring the loopback down.
+ * However, it causes problems during network configuration
+ * for boards that can't receive packets they send.
+ * It is now necessary to clear "useloopback" and remove
+ * the route to force traffic out to the hardware.
+ */
+ rt->rt_expire = 0;
+ Bcopy(((struct arpcom *)rt->rt_ifp)->ac_enaddr,
+ LLADDR(SDL(gate)), SDL(gate)->sdl_alen = 6);
+ if (useloopback)
+ rt->rt_ifp = loif;
+
+ }
+ break;
+
+ case RTM_DELETE:
+ if (la == 0)
+ break;
+ arp_inuse--;
+ LIST_REMOVE(la, la_le);
+ rt->rt_llinfo = 0;
+ rt->rt_flags &= ~RTF_LLINFO;
+ if (la->la_hold)
+ m_freem(la->la_hold);
+ Free((caddr_t)la);
+ }
+}
+
+/*
+ * Broadcast an ARP request. Caller specifies:
+ * - arp header source ip address
+ * - arp header target ip address
+ * - arp header source ethernet address
+ */
+static void
+arprequest(ac, sip, tip, enaddr)
+ register struct arpcom *ac;
+ register u_long *sip, *tip;
+ register u_char *enaddr;
+{
+ register struct mbuf *m;
+ register struct ether_header *eh;
+ register struct ether_arp *ea;
+ struct sockaddr sa;
+
+ if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL)
+ return;
+ m->m_len = sizeof(*ea);
+ m->m_pkthdr.len = sizeof(*ea);
+ MH_ALIGN(m, sizeof(*ea));
+ ea = mtod(m, struct ether_arp *);
+ eh = (struct ether_header *)sa.sa_data;
+ bzero((caddr_t)ea, sizeof (*ea));
+ (void)memcpy(eh->ether_dhost, etherbroadcastaddr, sizeof(eh->ether_dhost));
+ eh->ether_type = htons(ETHERTYPE_ARP); /* if_output will not swap */
+ ea->arp_hrd = htons(ARPHRD_ETHER);
+ ea->arp_pro = htons(ETHERTYPE_IP);
+ ea->arp_hln = sizeof(ea->arp_sha); /* hardware address length */
+ ea->arp_pln = sizeof(ea->arp_spa); /* protocol address length */
+ ea->arp_op = htons(ARPOP_REQUEST);
+ (void)memcpy(ea->arp_sha, enaddr, sizeof(ea->arp_sha));
+ (void)memcpy(ea->arp_spa, sip, sizeof(ea->arp_spa));
+ (void)memcpy(ea->arp_tpa, tip, sizeof(ea->arp_tpa));
+ sa.sa_family = AF_UNSPEC;
+ sa.sa_len = sizeof(sa);
+ (*ac->ac_if.if_output)(&ac->ac_if, m, &sa, (struct rtentry *)0);
+}
+
+/*
+ * Resolve an IP address into an ethernet address. If success,
+ * desten is filled in. If there is no entry in arptab,
+ * set one up and broadcast a request for the IP address.
+ * Hold onto this mbuf and resend it once the address
+ * is finally resolved. A return value of 1 indicates
+ * that desten has been filled in and the packet should be sent
+ * normally; a 0 return indicates that the packet has been
+ * taken over here, either now or for later transmission.
+ */
+int
+arpresolve(ac, rt, m, dst, desten, rt0)
+ register struct arpcom *ac;
+ register struct rtentry *rt;
+ struct mbuf *m;
+ register struct sockaddr *dst;
+ register u_char *desten;
+ struct rtentry *rt0;
+{
+ register struct llinfo_arp *la;
+ struct sockaddr_dl *sdl;
+
+ if (m->m_flags & M_BCAST) { /* broadcast */
+ (void)memcpy(desten, etherbroadcastaddr, sizeof(etherbroadcastaddr));
+ return (1);
+ }
+ if (m->m_flags & M_MCAST) { /* multicast */
+ ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr, desten);
+ return(1);
+ }
+ if (rt)
+ la = (struct llinfo_arp *)rt->rt_llinfo;
+ else {
+ la = arplookup(SIN(dst)->sin_addr.s_addr, 1, 0);
+ if (la)
+ rt = la->la_rt;
+ }
+ if (la == 0 || rt == 0) {
+ log(LOG_DEBUG, "arpresolve: can't allocate llinfo for %s\n",
+ inet_ntoa(SIN(dst)->sin_addr));
+ m_freem(m);
+ return (0);
+ }
+ sdl = SDL(rt->rt_gateway);
+ /*
+ * Check the address family and length is valid, the address
+ * is resolved; otherwise, try to resolve.
+ */
+ if ((rt->rt_expire == 0 || rt->rt_expire > rtems_bsdnet_seconds_since_boot()) &&
+ sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) {
+ bcopy(LLADDR(sdl), desten, sdl->sdl_alen);
+ return 1;
+ }
+ /*
+ * There is an arptab entry, but no ethernet address
+ * response yet. Replace the held mbuf with this
+ * latest one.
+ */
+ if (la->la_hold)
+ m_freem(la->la_hold);
+ la->la_hold = m;
+ if (rt->rt_expire) {
+ rt->rt_flags &= ~RTF_REJECT;
+ if (la->la_asked == 0 || rt->rt_expire != rtems_bsdnet_seconds_since_boot()) {
+ rt->rt_expire = rtems_bsdnet_seconds_since_boot();
+ if (la->la_asked++ < arp_maxtries)
+ arprequest(ac,
+ &(SIN(rt->rt_ifa->ifa_addr)->sin_addr.s_addr),
+ &(SIN(dst)->sin_addr.s_addr),
+ ac->ac_enaddr);
+ else {
+ rt->rt_flags |= RTF_REJECT;
+ rt->rt_expire += arpt_down;
+ la->la_asked = 0;
+ }
+
+ }
+ }
+ return (0);
+}
+
+/*
+ * Common length and type checks are done here,
+ * then the protocol-specific routine is called.
+ */
+void
+arpintr(void)
+{
+ register struct mbuf *m;
+ register struct arphdr *ar;
+ int s;
+
+ while (arpintrq.ifq_head) {
+ s = splimp();
+ IF_DEQUEUE(&arpintrq, m);
+ splx(s);
+ if (m == 0 || (m->m_flags & M_PKTHDR) == 0)
+ panic("arpintr");
+ if (m->m_len >= sizeof(struct arphdr) &&
+ (ar = mtod(m, struct arphdr *)) &&
+ ntohs(ar->ar_hrd) == ARPHRD_ETHER &&
+ m->m_len >=
+ sizeof(struct arphdr) + 2 * ar->ar_hln + 2 * ar->ar_pln)
+
+ switch (ntohs(ar->ar_pro)) {
+
+ case ETHERTYPE_IP:
+ in_arpinput(m);
+ continue;
+ }
+ m_freem(m);
+ }
+}
+
+NETISR_SET(NETISR_ARP, arpintr);
+
+/*
+ * ARP for Internet protocols on 10 Mb/s Ethernet.
+ * Algorithm is that given in RFC 826.
+ * In addition, a sanity check is performed on the sender
+ * protocol address, to catch impersonators.
+ * We no longer handle negotiations for use of trailer protocol:
+ * Formerly, ARP replied for protocol type ETHERTYPE_TRAIL sent
+ * along with IP replies if we wanted trailers sent to us,
+ * and also sent them in response to IP replies.
+ * This allowed either end to announce the desire to receive
+ * trailer packets.
+ * We no longer reply to requests for ETHERTYPE_TRAIL protocol either,
+ * but formerly didn't normally send requests.
+ */
+static void
+in_arpinput(m)
+ struct mbuf *m;
+{
+ register struct ether_arp *ea;
+ register struct arpcom *ac = (struct arpcom *)m->m_pkthdr.rcvif;
+ struct ether_header *eh;
+ register struct llinfo_arp *la = 0;
+ register struct rtentry *rt;
+ struct in_ifaddr *ia, *maybe_ia = 0;
+ struct sockaddr_dl *sdl;
+ struct sockaddr sa;
+ struct in_addr isaddr, itaddr, myaddr;
+ int op;
+
+ ea = mtod(m, struct ether_arp *);
+ op = ntohs(ea->arp_op);
+ (void)memcpy(&isaddr, ea->arp_spa, sizeof (isaddr));
+ (void)memcpy(&itaddr, ea->arp_tpa, sizeof (itaddr));
+ for (ia = in_ifaddr; ia; ia = ia->ia_next)
+ if (ia->ia_ifp == &ac->ac_if) {
+ maybe_ia = ia;
+ if ((itaddr.s_addr == ia->ia_addr.sin_addr.s_addr) ||
+ (isaddr.s_addr == ia->ia_addr.sin_addr.s_addr))
+ break;
+ }
+ if (maybe_ia == 0) {
+ m_freem(m);
+ return;
+ }
+ myaddr = ia ? ia->ia_addr.sin_addr : maybe_ia->ia_addr.sin_addr;
+ if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)ac->ac_enaddr,
+ sizeof (ea->arp_sha))) {
+ m_freem(m); /* it's from me, ignore it. */
+ return;
+ }
+ if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)etherbroadcastaddr,
+ sizeof (ea->arp_sha))) {
+ log(LOG_ERR,
+ "arp: ether address is broadcast for IP address %s!\n",
+ inet_ntoa(isaddr));
+ m_freem(m);
+ return;
+ }
+ if (isaddr.s_addr == myaddr.s_addr) {
+ log(LOG_ERR,
+ "arp: %6D is using my IP address %s!\n",
+ ea->arp_sha, ":", inet_ntoa(isaddr));
+ itaddr = myaddr;
+ goto reply;
+ }
+ la = arplookup(isaddr.s_addr, itaddr.s_addr == myaddr.s_addr, 0);
+ if (la && (rt = la->la_rt) && (sdl = SDL(rt->rt_gateway))) {
+ if (sdl->sdl_alen &&
+ bcmp((caddr_t)ea->arp_sha, LLADDR(sdl), sdl->sdl_alen))
+ log(LOG_INFO, "arp: %s moved from %6D to %6D\n",
+ inet_ntoa(isaddr), (u_char *)LLADDR(sdl), ":",
+ ea->arp_sha, ":");
+ (void)memcpy(LLADDR(sdl), ea->arp_sha, sizeof(ea->arp_sha));
+ sdl->sdl_alen = sizeof(ea->arp_sha);
+ if (rt->rt_expire)
+ rt->rt_expire = rtems_bsdnet_seconds_since_boot() + arpt_keep;
+ rt->rt_flags &= ~RTF_REJECT;
+ la->la_asked = 0;
+ if (la->la_hold) {
+ (*ac->ac_if.if_output)(&ac->ac_if, la->la_hold,
+ rt_key(rt), rt);
+ la->la_hold = 0;
+ }
+ }
+reply:
+ if (op != ARPOP_REQUEST) {
+ m_freem(m);
+ return;
+ }
+ if (itaddr.s_addr == myaddr.s_addr) {
+ /* I am the target */
+ (void)memcpy(ea->arp_tha, ea->arp_sha, sizeof(ea->arp_sha));
+ (void)memcpy(ea->arp_sha, ac->ac_enaddr, sizeof(ea->arp_sha));
+ } else {
+ la = arplookup(itaddr.s_addr, 0, SIN_PROXY);
+ if (la == NULL) {
+ struct sockaddr_in sin;
+
+ if (!arp_proxyall) {
+ m_freem(m);
+ return;
+ }
+
+ bzero(&sin, sizeof sin);
+ sin.sin_family = AF_INET;
+ sin.sin_len = sizeof sin;
+ sin.sin_addr = itaddr;
+
+ rt = rtalloc1((struct sockaddr *)&sin, 0, 0UL);
+ if (!rt) {
+ m_freem(m);
+ return;
+ }
+ /*
+ * Don't send proxies for nodes on the same interface
+ * as this one came out of, or we'll get into a fight
+ * over who claims what Ether address.
+ */
+ if (rt->rt_ifp == &ac->ac_if) {
+ rtfree(rt);
+ m_freem(m);
+ return;
+ }
+ (void)memcpy(ea->arp_tha, ea->arp_sha, sizeof(ea->arp_sha));
+ (void)memcpy(ea->arp_sha, ac->ac_enaddr, sizeof(ea->arp_sha));
+ rtfree(rt);
+#ifdef DEBUG_PROXY
+ printf("arp: proxying for %s\n",
+ inet_ntoa(itaddr));
+#endif
+ } else {
+ rt = la->la_rt;
+ (void)memcpy(ea->arp_tha, ea->arp_sha, sizeof(ea->arp_sha));
+ sdl = SDL(rt->rt_gateway);
+ (void)memcpy(ea->arp_sha, LLADDR(sdl), sizeof(ea->arp_sha));
+ }
+ }
+
+ (void)memcpy(ea->arp_tpa, ea->arp_spa, sizeof(ea->arp_spa));
+ (void)memcpy(ea->arp_spa, &itaddr, sizeof(ea->arp_spa));
+ ea->arp_op = htons(ARPOP_REPLY);
+ ea->arp_pro = htons(ETHERTYPE_IP); /* let's be sure! */
+ eh = (struct ether_header *)sa.sa_data;
+ (void)memcpy(eh->ether_dhost, ea->arp_tha, sizeof(eh->ether_dhost));
+ eh->ether_type = htons(ETHERTYPE_ARP);
+ sa.sa_family = AF_UNSPEC;
+ sa.sa_len = sizeof(sa);
+ (*ac->ac_if.if_output)(&ac->ac_if, m, &sa, (struct rtentry *)0);
+ return;
+}
+
+/*
+ * Free an arp entry.
+ */
+static void
+arptfree(la)
+ register struct llinfo_arp *la;
+{
+ register struct rtentry *rt = la->la_rt;
+ register struct sockaddr_dl *sdl;
+ if (rt == 0)
+ panic("arptfree");
+ if (rt->rt_refcnt > 0 && (sdl = SDL(rt->rt_gateway)) &&
+ sdl->sdl_family == AF_LINK) {
+ sdl->sdl_alen = 0;
+ la->la_asked = 0;
+ rt->rt_flags &= ~RTF_REJECT;
+ return;
+ }
+ rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0, rt_mask(rt),
+ 0, (struct rtentry **)0);
+}
+/*
+ * Lookup or enter a new address in arptab.
+ */
+static struct llinfo_arp *
+arplookup(addr, create, proxy)
+ u_long addr;
+ int create, proxy;
+{
+ register struct rtentry *rt;
+ static struct sockaddr_inarp sin = {sizeof(sin), AF_INET };
+ const char *why = 0;
+
+ sin.sin_addr.s_addr = addr;
+ sin.sin_other = proxy ? SIN_PROXY : 0;
+ rt = rtalloc1((struct sockaddr *)&sin, create, 0UL);
+ if (rt == 0)
+ return (0);
+ rt->rt_refcnt--;
+
+ if (rt->rt_flags & RTF_GATEWAY)
+ why = "host is not on local network";
+ else if ((rt->rt_flags & RTF_LLINFO) == 0)
+ why = "could not allocate llinfo";
+ else if (rt->rt_gateway->sa_family != AF_LINK)
+ why = "gateway route is not ours";
+
+ if (why && create) {
+ log(LOG_DEBUG, "arplookup %s failed: %s\n",
+ inet_ntoa(sin.sin_addr), why);
+ return 0;
+ } else if (why) {
+ return 0;
+ }
+ return ((struct llinfo_arp *)rt->rt_llinfo);
+}
+
+void
+arp_ifinit(ac, ifa)
+ struct arpcom *ac;
+ struct ifaddr *ifa;
+{
+ if (ntohl(IA_SIN(ifa)->sin_addr.s_addr) != INADDR_ANY)
+ arprequest(ac, &(IA_SIN(ifa)->sin_addr.s_addr),
+ &(IA_SIN(ifa)->sin_addr.s_addr), ac->ac_enaddr);
+ ifa->ifa_rtrequest = arp_rtrequest;
+ ifa->ifa_flags |= RTF_CLONING;
+}
diff --git a/cpukit/libnetworking/netinet/if_ether.h b/cpukit/libnetworking/netinet/if_ether.h
new file mode 100644
index 0000000000..d27f2e31f7
--- /dev/null
+++ b/cpukit/libnetworking/netinet/if_ether.h
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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_ether.h 8.3 (Berkeley) 5/2/95
+ * $Id$
+ */
+
+#ifndef _NETINET_IF_ETHER_H_
+#define _NETINET_IF_ETHER_H_
+
+#include <netinet/in.h>
+#include <net/ethernet.h>
+
+#define ETHERTYPE_PUP 0x0200 /* PUP protocol */
+#define ETHERTYPE_IP 0x0800 /* IP protocol */
+#define ETHERTYPE_ARP 0x0806 /* Addr. resolution protocol */
+#define ETHERTYPE_REVARP 0x8035 /* reverse Addr. resolution protocol */
+
+/*
+ * The ETHERTYPE_NTRAILER packet types starting at ETHERTYPE_TRAIL have
+ * (type-ETHERTYPE_TRAIL)*512 bytes of data followed
+ * by an ETHER type (as given above) and then the (variable-length) header.
+ */
+#define ETHERTYPE_TRAIL 0x1000 /* Trailer packet */
+#define ETHERTYPE_NTRAILER 16
+
+#define ETHERMTU (ETHER_MAX_LEN-ETHER_HDR_LEN-ETHER_CRC_LEN)
+#define ETHERMIN (ETHER_MIN_LEN-ETHER_HDR_LEN-ETHER_CRC_LEN)
+
+#ifdef _KERNEL
+/*
+ * Macro to map an IP multicast address to an Ethernet multicast address.
+ * The high-order 25 bits of the Ethernet address are statically assigned,
+ * and the low-order 23 bits are taken from the low end of the IP address.
+ */
+#define ETHER_MAP_IP_MULTICAST(ipaddr, enaddr) \
+ /* struct in_addr *ipaddr; */ \
+ /* u_char enaddr[ETHER_ADDR_LEN]; */ \
+{ \
+ (enaddr)[0] = 0x01; \
+ (enaddr)[1] = 0x00; \
+ (enaddr)[2] = 0x5e; \
+ (enaddr)[3] = ((u_char *)ipaddr)[1] & 0x7f; \
+ (enaddr)[4] = ((u_char *)ipaddr)[2]; \
+ (enaddr)[5] = ((u_char *)ipaddr)[3]; \
+}
+#endif
+
+/*
+ * Ethernet Address Resolution Protocol.
+ *
+ * See RFC 826 for protocol description. Structure below is adapted
+ * to resolving internet addresses. Field names used correspond to
+ * RFC 826.
+ */
+struct ether_arp {
+ struct arphdr ea_hdr BYTE_PACK; /* fixed-size header */
+ u_char arp_sha[ETHER_ADDR_LEN]; /* sender hardware address */
+ u_char arp_spa[4]; /* sender protocol address */
+ u_char arp_tha[ETHER_ADDR_LEN]; /* target hardware address */
+ u_char arp_tpa[4]; /* target protocol address */
+};
+#define arp_hrd ea_hdr.ar_hrd
+#define arp_pro ea_hdr.ar_pro
+#define arp_hln ea_hdr.ar_hln
+#define arp_pln ea_hdr.ar_pln
+#define arp_op ea_hdr.ar_op
+
+
+/*
+ * Structure shared between the ethernet driver modules and
+ * the address resolution code. For example, each ec_softc or il_softc
+ * begins with this structure.
+ */
+struct arpcom {
+ /*
+ * The ifnet struct _must_ be at the head of this structure.
+ */
+ struct ifnet ac_if; /* network-visible interface */
+ u_char ac_enaddr[ETHER_ADDR_LEN]; /* ethernet hardware address */
+ struct ether_multi *ac_multiaddrs; /* list of ether multicast addrs */
+ int ac_multicnt; /* length of ac_multiaddrs list */
+};
+
+struct sockaddr_inarp {
+ u_char sin_len;
+ u_char sin_family;
+ u_short sin_port;
+ struct in_addr sin_addr;
+ struct in_addr sin_srcaddr;
+ u_short sin_tos;
+ u_short sin_other;
+#define SIN_PROXY 1
+};
+/*
+ * IP and ethernet specific routing flags
+ */
+#define RTF_USETRAILERS RTF_PROTO1 /* use trailers */
+#define RTF_ANNOUNCE RTF_PROTO2 /* announce new arp entry */
+
+#ifdef _KERNEL
+extern u_char etherbroadcastaddr[ETHER_ADDR_LEN];
+extern u_char ether_ipmulticast_min[ETHER_ADDR_LEN];
+extern u_char ether_ipmulticast_max[ETHER_ADDR_LEN];
+extern struct ifqueue arpintrq;
+
+int arpresolve __P((struct arpcom *, struct rtentry *, struct mbuf *,
+ struct sockaddr *, u_char *, struct rtentry *));
+void arp_ifinit __P((struct arpcom *, struct ifaddr *));
+int ether_addmulti __P((struct ifreq *, struct arpcom *));
+int ether_delmulti __P((struct ifreq *, struct arpcom *));
+
+/*
+ * Ethernet multicast address structure. There is one of these for each
+ * multicast address or range of multicast addresses that we are supposed
+ * to listen to on a particular interface. They are kept in a linked list,
+ * rooted in the interface's arpcom structure. (This really has nothing to
+ * do with ARP, or with the Internet address family, but this appears to be
+ * the minimally-disrupting place to put it.)
+ */
+struct ether_multi {
+ u_char enm_addrlo[ETHER_ADDR_LEN]; /* low or only address of range */
+ u_char enm_addrhi[ETHER_ADDR_LEN]; /* high or only address of range */
+ struct arpcom *enm_ac; /* back pointer to arpcom */
+ u_int enm_refcount; /* no. claims to this addr/range */
+ struct ether_multi *enm_next; /* ptr to next ether_multi */
+};
+
+/*
+ * Structure used by macros below to remember position when stepping through
+ * all of the ether_multi records.
+ */
+struct ether_multistep {
+ struct ether_multi *e_enm;
+};
+
+/*
+ * Macro for looking up the ether_multi record for a given range of Ethernet
+ * multicast addresses connected to a given arpcom structure. If no matching
+ * record is found, "enm" returns NULL.
+ */
+#define ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm) \
+ /* u_char addrlo[ETHER_ADDR_LEN]; */ \
+ /* u_char addrhi[ETHER_ADDR_LEN]; */ \
+ /* struct arpcom *ac; */ \
+ /* struct ether_multi *enm; */ \
+{ \
+ for ((enm) = (ac)->ac_multiaddrs; \
+ (enm) != NULL && \
+ (bcmp((enm)->enm_addrlo, (addrlo), ETHER_ADDR_LEN) != 0 || \
+ bcmp((enm)->enm_addrhi, (addrhi), ETHER_ADDR_LEN) != 0); \
+ (enm) = (enm)->enm_next); \
+}
+
+/*
+ * Macro to step through all of the ether_multi records, one at a time.
+ * The current position is remembered in "step", which the caller must
+ * provide. ETHER_FIRST_MULTI(), below, must be called to initialize "step"
+ * and get the first record. Both macros return a NULL "enm" when there
+ * are no remaining records.
+ */
+#define ETHER_NEXT_MULTI(step, enm) \
+ /* struct ether_multistep step; */ \
+ /* struct ether_multi *enm; */ \
+{ \
+ if (((enm) = (step).e_enm) != NULL) \
+ (step).e_enm = (enm)->enm_next; \
+}
+
+#define ETHER_FIRST_MULTI(step, ac, enm) \
+ /* struct ether_multistep step; */ \
+ /* struct arpcom *ac; */ \
+ /* struct ether_multi *enm; */ \
+{ \
+ (step).e_enm = (ac)->ac_multiaddrs; \
+ ETHER_NEXT_MULTI((step), (enm)); \
+}
+
+#endif
+
+#endif
diff --git a/cpukit/libnetworking/netinet/igmp.c b/cpukit/libnetworking/netinet/igmp.c
new file mode 100644
index 0000000000..2af8b7038e
--- /dev/null
+++ b/cpukit/libnetworking/netinet/igmp.c
@@ -0,0 +1,479 @@
+/*
+ * Copyright (c) 1988 Stephen Deering.
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Stephen Deering of Stanford University.
+ *
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)igmp.c 8.1 (Berkeley) 7/19/93
+ * $Id$
+ */
+
+/*
+ * Internet Group Management Protocol (IGMP) routines.
+ *
+ * Written by Steve Deering, Stanford, May 1988.
+ * Modified by Rosen Sharma, Stanford, Aug 1994.
+ * Modified by Bill Fenner, Xerox PARC, Feb 1995.
+ * Modified to fully comply to IGMPv2 by Bill Fenner, Oct 1995.
+ *
+ * MULTICAST Revision: 3.5.1.4
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/protosw.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/route.h>
+
+#include <netinet/in.h>
+#include <netinet/in_var.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/igmp.h>
+#include <netinet/igmp_var.h>
+
+static struct router_info *
+ find_rti __P((struct ifnet *ifp));
+
+static struct igmpstat igmpstat;
+
+SYSCTL_STRUCT(_net_inet_igmp, IGMPCTL_STATS, stats, CTLFLAG_RD,
+ &igmpstat, igmpstat, "");
+
+static int igmp_timers_are_running;
+static u_long igmp_all_hosts_group;
+static u_long igmp_all_rtrs_group;
+static struct mbuf *router_alert;
+static struct router_info *Head;
+
+static void igmp_sendpkt(struct in_multi *, int, unsigned long);
+
+void
+igmp_init()
+{
+ struct ipoption *ra;
+
+ /*
+ * To avoid byte-swapping the same value over and over again.
+ */
+ igmp_all_hosts_group = htonl(INADDR_ALLHOSTS_GROUP);
+ igmp_all_rtrs_group = htonl(INADDR_ALLRTRS_GROUP);
+
+ igmp_timers_are_running = 0;
+
+ /*
+ * Construct a Router Alert option to use in outgoing packets
+ */
+ MGET(router_alert, M_DONTWAIT, MT_DATA);
+ ra = mtod(router_alert, struct ipoption *);
+ ra->ipopt_dst.s_addr = 0;
+ ra->ipopt_list[0] = IPOPT_RA; /* Router Alert Option */
+ ra->ipopt_list[1] = 0x04; /* 4 bytes long */
+ ra->ipopt_list[2] = 0x00;
+ ra->ipopt_list[3] = 0x00;
+ router_alert->m_len = sizeof(ra->ipopt_dst) + ra->ipopt_list[1];
+
+ Head = (struct router_info *) 0;
+}
+
+static struct router_info *
+find_rti(ifp)
+ struct ifnet *ifp;
+{
+ register struct router_info *rti = Head;
+
+#ifdef IGMP_DEBUG
+ printf("[igmp.c, _find_rti] --> entering \n");
+#endif
+ while (rti) {
+ if (rti->rti_ifp == ifp) {
+#ifdef IGMP_DEBUG
+ printf("[igmp.c, _find_rti] --> found old entry \n");
+#endif
+ return rti;
+ }
+ rti = rti->rti_next;
+ }
+ MALLOC(rti, struct router_info *, sizeof *rti, M_MRTABLE, M_NOWAIT);
+ rti->rti_ifp = ifp;
+ rti->rti_type = IGMP_V2_ROUTER;
+ rti->rti_time = 0;
+ rti->rti_next = Head;
+ Head = rti;
+#ifdef IGMP_DEBUG
+ printf("[igmp.c, _find_rti] --> created an entry \n");
+#endif
+ return rti;
+}
+
+void
+igmp_input(m, iphlen)
+ register struct mbuf *m;
+ register int iphlen;
+{
+ register struct igmp *igmp;
+ register struct ip *ip;
+ register int igmplen;
+ register struct ifnet *ifp = m->m_pkthdr.rcvif;
+ register int minlen;
+ register struct in_multi *inm;
+ register struct in_ifaddr *ia;
+ struct in_multistep step;
+ struct router_info *rti;
+
+ int timer; /** timer value in the igmp query header **/
+
+ ++igmpstat.igps_rcv_total;
+
+ ip = mtod(m, struct ip *);
+ igmplen = ip->ip_len;
+
+ /*
+ * Validate lengths
+ */
+ if (igmplen < IGMP_MINLEN) {
+ ++igmpstat.igps_rcv_tooshort;
+ m_freem(m);
+ return;
+ }
+ minlen = iphlen + IGMP_MINLEN;
+ if ((m->m_flags & M_EXT || m->m_len < minlen) &&
+ (m = m_pullup(m, minlen)) == 0) {
+ ++igmpstat.igps_rcv_tooshort;
+ return;
+ }
+
+ /*
+ * Validate checksum
+ */
+ m->m_data += iphlen;
+ m->m_len -= iphlen;
+ igmp = mtod(m, struct igmp *);
+ if (in_cksum(m, igmplen)) {
+ ++igmpstat.igps_rcv_badsum;
+ m_freem(m);
+ return;
+ }
+ m->m_data -= iphlen;
+ m->m_len += iphlen;
+
+ ip = mtod(m, struct ip *);
+ timer = igmp->igmp_code * PR_FASTHZ / IGMP_TIMER_SCALE;
+ rti = find_rti(ifp);
+
+ /*
+ * In the IGMPv2 specification, there are 3 states and a flag.
+ *
+ * In Non-Member state, we simply don't have a membership record.
+ * In Delaying Member state, our timer is running (inm->inm_timer)
+ * In Idle Member state, our timer is not running (inm->inm_timer==0)
+ *
+ * The flag is inm->inm_state, it is set to IGMP_OTHERMEMBER if
+ * we have heard a report from another member, or IGMP_IREPORTEDLAST
+ * if I sent the last report.
+ */
+ switch (igmp->igmp_type) {
+
+ case IGMP_MEMBERSHIP_QUERY:
+ ++igmpstat.igps_rcv_queries;
+
+ if (ifp->if_flags & IFF_LOOPBACK)
+ break;
+
+ if (igmp->igmp_code == 0) {
+ /*
+ * Old router. Remember that the querier on this
+ * interface is old, and set the timer to the
+ * value in RFC 1112.
+ */
+
+ rti->rti_type = IGMP_V1_ROUTER;
+ rti->rti_time = 0;
+
+ timer = IGMP_MAX_HOST_REPORT_DELAY * PR_FASTHZ;
+
+ if (ip->ip_dst.s_addr != igmp_all_hosts_group ||
+ igmp->igmp_group.s_addr != 0) {
+ ++igmpstat.igps_rcv_badqueries;
+ m_freem(m);
+ return;
+ }
+ } else {
+ /*
+ * New router. Simply do the new validity check.
+ */
+
+ if (igmp->igmp_group.s_addr != 0 &&
+ !IN_MULTICAST(ntohl(igmp->igmp_group.s_addr))) {
+ ++igmpstat.igps_rcv_badqueries;
+ m_freem(m);
+ return;
+ }
+ }
+
+ /*
+ * - Start the timers in all of our membership records
+ * that the query applies to for the interface on
+ * which the query arrived excl. those that belong
+ * to the "all-hosts" group (224.0.0.1).
+ * - Restart any timer that is already running but has
+ * a value longer than the requested timeout.
+ * - Use the value specified in the query message as
+ * the maximum timeout.
+ */
+ IN_FIRST_MULTI(step, inm);
+ while (inm != NULL) {
+ if (inm->inm_ifp == ifp &&
+ inm->inm_addr.s_addr != igmp_all_hosts_group &&
+ (igmp->igmp_group.s_addr == 0 ||
+ igmp->igmp_group.s_addr == inm->inm_addr.s_addr)) {
+ if (inm->inm_timer == 0 ||
+ inm->inm_timer > timer) {
+ inm->inm_timer =
+ IGMP_RANDOM_DELAY(timer);
+ igmp_timers_are_running = 1;
+ }
+ }
+ IN_NEXT_MULTI(step, inm);
+ }
+
+ break;
+
+ case IGMP_V1_MEMBERSHIP_REPORT:
+ case IGMP_V2_MEMBERSHIP_REPORT:
+ /*
+ * For fast leave to work, we have to know that we are the
+ * last person to send a report for this group. Reports
+ * can potentially get looped back if we are a multicast
+ * router, so discard reports sourced by me.
+ */
+ IFP_TO_IA(ifp, ia);
+ if (ia && ip->ip_src.s_addr == IA_SIN(ia)->sin_addr.s_addr)
+ break;
+
+ ++igmpstat.igps_rcv_reports;
+
+ if (ifp->if_flags & IFF_LOOPBACK)
+ break;
+
+ if (!IN_MULTICAST(ntohl(igmp->igmp_group.s_addr))) {
+ ++igmpstat.igps_rcv_badreports;
+ m_freem(m);
+ return;
+ }
+
+ /*
+ * KLUDGE: if the IP source address of the report has an
+ * unspecified (i.e., zero) subnet number, as is allowed for
+ * a booting host, replace it with the correct subnet number
+ * so that a process-level multicast routing demon can
+ * determine which subnet it arrived from. This is necessary
+ * to compensate for the lack of any way for a process to
+ * determine the arrival interface of an incoming packet.
+ */
+ if ((ntohl(ip->ip_src.s_addr) & IN_CLASSA_NET) == 0)
+ if (ia) ip->ip_src.s_addr = htonl(ia->ia_subnet);
+
+ /*
+ * If we belong to the group being reported, stop
+ * our timer for that group.
+ */
+ IN_LOOKUP_MULTI(igmp->igmp_group, ifp, inm);
+
+ if (inm != NULL) {
+ inm->inm_timer = 0;
+ ++igmpstat.igps_rcv_ourreports;
+
+ inm->inm_state = IGMP_OTHERMEMBER;
+ }
+
+ break;
+ }
+
+ /*
+ * Pass all valid IGMP packets up to any process(es) listening
+ * on a raw IGMP socket.
+ */
+ rip_input(m, iphlen);
+}
+
+void
+igmp_joingroup(inm)
+ struct in_multi *inm;
+{
+ int s = splnet();
+
+ if (inm->inm_addr.s_addr == igmp_all_hosts_group
+ || inm->inm_ifp->if_flags & IFF_LOOPBACK) {
+ inm->inm_timer = 0;
+ inm->inm_state = IGMP_OTHERMEMBER;
+ } else {
+ inm->inm_rti = find_rti(inm->inm_ifp);
+ igmp_sendpkt(inm, inm->inm_rti->rti_type, 0);
+ inm->inm_timer = IGMP_RANDOM_DELAY(
+ IGMP_MAX_HOST_REPORT_DELAY*PR_FASTHZ);
+ inm->inm_state = IGMP_IREPORTEDLAST;
+ igmp_timers_are_running = 1;
+ }
+ splx(s);
+}
+
+void
+igmp_leavegroup(inm)
+ struct in_multi *inm;
+{
+ if (inm->inm_state == IGMP_IREPORTEDLAST &&
+ inm->inm_addr.s_addr != igmp_all_hosts_group &&
+ !(inm->inm_ifp->if_flags & IFF_LOOPBACK) &&
+ inm->inm_rti->rti_type != IGMP_V1_ROUTER)
+ igmp_sendpkt(inm, IGMP_V2_LEAVE_GROUP, igmp_all_rtrs_group);
+}
+
+void
+igmp_fasttimo()
+{
+ register struct in_multi *inm;
+ struct in_multistep step;
+ int s;
+
+ /*
+ * Quick check to see if any work needs to be done, in order
+ * to minimize the overhead of fasttimo processing.
+ */
+
+ if (!igmp_timers_are_running)
+ return;
+
+ s = splnet();
+ igmp_timers_are_running = 0;
+ IN_FIRST_MULTI(step, inm);
+ while (inm != NULL) {
+ if (inm->inm_timer == 0) {
+ /* do nothing */
+ } else if (--inm->inm_timer == 0) {
+ igmp_sendpkt(inm, inm->inm_rti->rti_type, 0);
+ inm->inm_state = IGMP_IREPORTEDLAST;
+ } else {
+ igmp_timers_are_running = 1;
+ }
+ IN_NEXT_MULTI(step, inm);
+ }
+ splx(s);
+}
+
+void
+igmp_slowtimo()
+{
+ int s = splnet();
+ register struct router_info *rti = Head;
+
+#ifdef IGMP_DEBUG
+ printf("[igmp.c,_slowtimo] -- > entering \n");
+#endif
+ while (rti) {
+ if (rti->rti_type == IGMP_V1_ROUTER) {
+ rti->rti_time++;
+ if (rti->rti_time >= IGMP_AGE_THRESHOLD) {
+ rti->rti_type = IGMP_V2_ROUTER;
+ }
+ }
+ rti = rti->rti_next;
+ }
+#ifdef IGMP_DEBUG
+ printf("[igmp.c,_slowtimo] -- > exiting \n");
+#endif
+ splx(s);
+}
+
+static struct route igmprt;
+
+static void
+igmp_sendpkt(inm, type, addr)
+ struct in_multi *inm;
+ int type;
+ unsigned long addr;
+{
+ struct mbuf *m;
+ struct igmp *igmp;
+ struct ip *ip;
+ struct ip_moptions imo;
+
+ MGETHDR(m, M_DONTWAIT, MT_HEADER);
+ if (m == NULL)
+ return;
+
+ m->m_pkthdr.rcvif = loif;
+ m->m_pkthdr.len = sizeof(struct ip) + IGMP_MINLEN;
+ MH_ALIGN(m, IGMP_MINLEN + sizeof(struct ip));
+ m->m_data += sizeof(struct ip);
+ m->m_len = IGMP_MINLEN;
+ igmp = mtod(m, struct igmp *);
+ igmp->igmp_type = type;
+ igmp->igmp_code = 0;
+ igmp->igmp_group = inm->inm_addr;
+ igmp->igmp_cksum = 0;
+ igmp->igmp_cksum = in_cksum(m, IGMP_MINLEN);
+
+ m->m_data -= sizeof(struct ip);
+ m->m_len += sizeof(struct ip);
+ ip = mtod(m, struct ip *);
+ ip->ip_tos = 0;
+ ip->ip_len = sizeof(struct ip) + IGMP_MINLEN;
+ ip->ip_off = 0;
+ ip->ip_p = IPPROTO_IGMP;
+ ip->ip_src.s_addr = INADDR_ANY;
+ ip->ip_dst.s_addr = addr ? addr : igmp->igmp_group.s_addr;
+
+ imo.imo_multicast_ifp = inm->inm_ifp;
+ imo.imo_multicast_ttl = 1;
+ imo.imo_multicast_vif = -1;
+ /*
+ * Request loopback of the report if we are acting as a multicast
+ * router, so that the process-level routing demon can hear it.
+ */
+ imo.imo_multicast_loop = (ip_mrouter != NULL);
+
+ /*
+ * XXX
+ * Do we have to worry about reentrancy here? Don't think so.
+ */
+ ip_output(m, router_alert, &igmprt, 0, &imo);
+
+ ++igmpstat.igps_snd_reports;
+}
diff --git a/cpukit/libnetworking/netinet/igmp.h b/cpukit/libnetworking/netinet/igmp.h
new file mode 100644
index 0000000000..01d6d09179
--- /dev/null
+++ b/cpukit/libnetworking/netinet/igmp.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 1988 Stephen Deering.
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Stephen Deering of Stanford University.
+ *
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)igmp.h 8.1 (Berkeley) 6/10/93
+ * $Id$
+ */
+
+#ifndef _NETINET_IGMP_H_
+#define _NETINET_IGMP_H_
+
+/*
+ * Internet Group Management Protocol (IGMP) definitions.
+ *
+ * Written by Steve Deering, Stanford, May 1988.
+ *
+ * MULTICAST Revision: 3.5.1.2
+ */
+
+/*
+ * IGMP packet format.
+ */
+struct igmp {
+ u_char igmp_type; /* version & type of IGMP message */
+ u_char igmp_code; /* subtype for routing msgs */
+ u_short igmp_cksum; /* IP-style checksum */
+ struct in_addr igmp_group; /* group address being reported */
+}; /* (zero for queries) */
+
+#define IGMP_MINLEN 8
+
+/*
+ * Message types, including version number.
+ */
+#define IGMP_MEMBERSHIP_QUERY 0x11 /* membership query */
+#define IGMP_V1_MEMBERSHIP_REPORT 0x12 /* Ver. 1 membership report */
+#define IGMP_V2_MEMBERSHIP_REPORT 0x16 /* Ver. 2 membership report */
+#define IGMP_V2_LEAVE_GROUP 0x17 /* Leave-group message */
+
+#define IGMP_DVMRP 0x13 /* DVMRP routing message */
+#define IGMP_PIM 0x14 /* PIM routing message */
+
+#define IGMP_MTRACE_RESP 0x1e /* traceroute resp.(to sender)*/
+#define IGMP_MTRACE 0x1f /* mcast traceroute messages */
+
+#define IGMP_MAX_HOST_REPORT_DELAY 10 /* max delay for response to */
+ /* query (in seconds) according */
+ /* to RFC1112 */
+
+
+#define IGMP_TIMER_SCALE 10 /* denotes that the igmp code field */
+ /* specifies time in 10th of seconds*/
+
+/*
+ * The following four defininitions are for backwards compatibility.
+ * They should be removed as soon as all applications are updated to
+ * use the new constant names.
+ */
+#define IGMP_HOST_MEMBERSHIP_QUERY IGMP_MEMBERSHIP_QUERY
+#define IGMP_HOST_MEMBERSHIP_REPORT IGMP_V1_MEMBERSHIP_REPORT
+#define IGMP_HOST_NEW_MEMBERSHIP_REPORT IGMP_V2_MEMBERSHIP_REPORT
+#define IGMP_HOST_LEAVE_MESSAGE IGMP_V2_LEAVE_GROUP
+
+#endif /* _NETINET_IGMP_H_ */
diff --git a/cpukit/libnetworking/netinet/igmp_var.h b/cpukit/libnetworking/netinet/igmp_var.h
new file mode 100644
index 0000000000..d515d80199
--- /dev/null
+++ b/cpukit/libnetworking/netinet/igmp_var.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 1988 Stephen Deering.
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Stephen Deering of Stanford University.
+ *
+ * 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * from: @(#)igmp_var.h 8.1 (Berkeley) 7/19/93
+ * $FreeBSD: src/sys/netinet/igmp_var.h,v 1.20 2004/04/07 20:46:13 imp Exp $
+ */
+
+#ifndef _NETINET_IGMP_VAR_H_
+#define _NETINET_IGMP_VAR_H_
+
+/*
+ * Internet Group Management Protocol (IGMP),
+ * implementation-specific definitions.
+ *
+ * Written by Steve Deering, Stanford, May 1988.
+ *
+ * MULTICAST Revision: 3.5.1.3
+ */
+
+struct igmpstat {
+ u_int igps_rcv_total; /* total IGMP messages received */
+ u_int igps_rcv_tooshort; /* received with too few bytes */
+ u_int igps_rcv_badsum; /* received with bad checksum */
+ u_int igps_rcv_queries; /* received membership queries */
+ u_int igps_rcv_badqueries; /* received invalid queries */
+ u_int igps_rcv_reports; /* received membership reports */
+ u_int igps_rcv_badreports; /* received invalid reports */
+ u_int igps_rcv_ourreports; /* received reports for our groups */
+ u_int igps_snd_reports; /* sent membership reports */
+};
+
+#ifdef _KERNEL
+extern struct igmpstat igmpstat;
+
+#define IGMP_RANDOM_DELAY(X) (random() % (X) + 1)
+
+/*
+ * States for IGMPv2's leave processing
+ */
+#define IGMP_OTHERMEMBER 0
+#define IGMP_IREPORTEDLAST 1
+
+/*
+ * We must remember what version the subnet's querier is.
+ * We conveniently use the IGMP message type for the proper
+ * membership report to keep this state.
+ */
+#define IGMP_V1_ROUTER IGMP_V1_MEMBERSHIP_REPORT
+#define IGMP_V2_ROUTER IGMP_V2_MEMBERSHIP_REPORT
+
+/*
+ * Revert to new router if we haven't heard from an old router in
+ * this amount of time.
+ */
+#define IGMP_AGE_THRESHOLD 540
+
+void igmp_init(void);
+void igmp_input(struct mbuf *, int);
+void igmp_joingroup(struct in_multi *);
+void igmp_leavegroup(struct in_multi *);
+void igmp_fasttimo(void);
+void igmp_slowtimo(void);
+
+SYSCTL_DECL(_net_inet_igmp);
+
+#endif
+
+/*
+ * Names for IGMP sysctl objects
+ */
+#define IGMPCTL_STATS 1 /* statistics (read-only) */
+#define IGMPCTL_MAXID 2
+
+#define IGMPCTL_NAMES { \
+ { 0, 0 }, \
+ { "stats", CTLTYPE_STRUCT }, \
+}
+#endif
diff --git a/cpukit/libnetworking/netinet/in.c b/cpukit/libnetworking/netinet/in.c
new file mode 100644
index 0000000000..3b246fd210
--- /dev/null
+++ b/cpukit/libnetworking/netinet/in.c
@@ -0,0 +1,723 @@
+/*
+ * Copyright (c) 1982, 1986, 1991, 1993
+ * The Regents of the University of California. 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)in.c 8.4 (Berkeley) 1/9/95
+ * $FreeBSD: src/sys/netinet/in.c,v 1.75 2004/04/07 20:46:13 imp Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/systm.h>
+#include <sys/ioctl.h>
+#include <sys/errno.h>
+#include <sys/malloc.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/route.h>
+
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/in_var.h>
+#include <netinet/if_ether.h>
+
+#include <netinet/igmp_var.h>
+
+/*
+ * This structure is used to keep track of in_multi chains which belong to
+ * deleted interface addresses.
+ */
+static LIST_HEAD(, multi_kludge) in_mk; /* XXX BSS initialization */
+
+struct multi_kludge {
+ LIST_ENTRY(multi_kludge) mk_entry;
+ struct ifnet *mk_ifp;
+ struct in_multihead mk_head;
+};
+
+static void in_socktrim __P((struct sockaddr_in *));
+static int in_ifinit __P((struct ifnet *,
+ struct in_ifaddr *, struct sockaddr_in *, int));
+static void in_ifscrub __P((struct ifnet *, struct in_ifaddr *));
+
+static int subnetsarelocal = 0;
+SYSCTL_INT(_net_inet_ip, OID_AUTO, subnets_are_local, CTLFLAG_RW,
+ &subnetsarelocal, 0, "");
+/*
+ * Return 1 if an internet address is for a ``local'' host
+ * (one to which we have a connection). If subnetsarelocal
+ * is true, this includes other subnets of the local net.
+ * Otherwise, it includes only the directly-connected (sub)nets.
+ */
+int
+in_localaddr(in)
+ struct in_addr in;
+{
+ register u_long i = ntohl(in.s_addr);
+ register struct in_ifaddr *ia;
+
+ if (subnetsarelocal) {
+ for (ia = in_ifaddr; ia; ia = ia->ia_next)
+ if ((i & ia->ia_netmask) == ia->ia_net)
+ return (1);
+ } else {
+ for (ia = in_ifaddr; ia; ia = ia->ia_next)
+ if ((i & ia->ia_subnetmask) == ia->ia_subnet)
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * Determine whether an IP address is in a reserved set of addresses
+ * that may not be forwarded, or whether datagrams to that destination
+ * may be forwarded.
+ */
+int
+in_canforward(in)
+ struct in_addr in;
+{
+ register u_long i = ntohl(in.s_addr);
+ register u_long net;
+
+ if (IN_EXPERIMENTAL(i) || IN_MULTICAST(i))
+ return (0);
+ if (IN_CLASSA(i)) {
+ net = i & IN_CLASSA_NET;
+ if (net == 0 || net == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
+ return (0);
+ }
+ return (1);
+}
+
+/*
+ * Trim a mask in a sockaddr
+ */
+static void
+in_socktrim(ap)
+struct sockaddr_in *ap;
+{
+ register char *cplim = (char *) &ap->sin_addr;
+ register char *cp = (char *) (&ap->sin_addr + 1);
+
+ ap->sin_len = 0;
+ while (--cp >= cplim)
+ if (*cp) {
+ (ap)->sin_len = cp - (char *) (ap) + 1;
+ break;
+ }
+}
+
+static int in_interfaces; /* number of external internet interfaces */
+
+/*
+ * Generic internet control operations (ioctl's).
+ * Ifp is 0 if not an interface-specific ioctl.
+ */
+/* ARGSUSED */
+int
+in_control(so, cmd, data, ifp)
+ struct socket *so;
+ u_long cmd;
+ caddr_t data;
+ register struct ifnet *ifp;
+{
+ register struct ifreq *ifr = (struct ifreq *)data;
+ register struct in_ifaddr *ia = 0, *iap;
+ register struct ifaddr *ifa;
+ struct in_ifaddr *oia;
+ struct in_aliasreq *ifra = (struct in_aliasreq *)data;
+ struct sockaddr_in oldaddr;
+ int error, hostIsNew, maskIsNew, s;
+ struct multi_kludge *mk;
+
+ /*
+ * Find address for this interface, if it exists.
+ *
+ * If an alias address was specified, find that one instead of
+ * the first one on the interface.
+ */
+ if (ifp)
+ for (iap = in_ifaddr; iap; iap = iap->ia_next)
+ if (iap->ia_ifp == ifp) {
+ if (((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr.s_addr ==
+ iap->ia_addr.sin_addr.s_addr) {
+ ia = iap;
+ break;
+ } else if (ia == NULL) {
+ ia = iap;
+ if (ifr->ifr_addr.sa_family != AF_INET)
+ break;
+ }
+ }
+
+ switch (cmd) {
+
+ case SIOCAIFADDR:
+ case SIOCDIFADDR:
+ if (ifra->ifra_addr.sin_family == AF_INET) {
+ for (oia = ia; ia; ia = ia->ia_next) {
+ if (ia->ia_ifp == ifp &&
+ ia->ia_addr.sin_addr.s_addr ==
+ ifra->ifra_addr.sin_addr.s_addr)
+ break;
+ }
+ if ((ifp->if_flags & IFF_POINTOPOINT)
+ && (cmd == SIOCAIFADDR)
+ && (ifra->ifra_dstaddr.sin_addr.s_addr
+ == INADDR_ANY)) {
+ return EDESTADDRREQ;
+ }
+ }
+ if (cmd == SIOCDIFADDR && ia == 0)
+ return (EADDRNOTAVAIL);
+ /* FALLTHROUGH */
+ case SIOCSIFADDR:
+ case SIOCSIFNETMASK:
+ case SIOCSIFDSTADDR:
+ if ((so->so_state & SS_PRIV) == 0)
+ return (EPERM);
+
+ if (ifp == 0)
+ panic("in_control");
+ if (ia == (struct in_ifaddr *)0) {
+ oia = (struct in_ifaddr *)
+ malloc(sizeof *oia, M_IFADDR, M_WAITOK);
+ if (oia == (struct in_ifaddr *)NULL)
+ return (ENOBUFS);
+ bzero((caddr_t)oia, sizeof *oia);
+ ia = in_ifaddr;
+ /*
+ * Protect from ipintr() traversing address list
+ * while we're modifying it.
+ */
+ s = splnet();
+
+ if (ia) {
+ for ( ; ia->ia_next; ia = ia->ia_next)
+ continue;
+ ia->ia_next = oia;
+ } else
+ in_ifaddr = oia;
+ ia = oia;
+ ifa = ifp->if_addrlist;
+ if (ifa) {
+ for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
+ continue;
+ ifa->ifa_next = (struct ifaddr *) ia;
+ } else
+ ifp->if_addrlist = (struct ifaddr *) ia;
+ ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
+ ia->ia_ifa.ifa_dstaddr
+ = (struct sockaddr *)&ia->ia_dstaddr;
+ ia->ia_ifa.ifa_netmask
+ = (struct sockaddr *)&ia->ia_sockmask;
+ ia->ia_sockmask.sin_len = 8;
+ if (ifp->if_flags & IFF_BROADCAST) {
+ ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
+ ia->ia_broadaddr.sin_family = AF_INET;
+ }
+ ia->ia_ifp = ifp;
+ if (!(ifp->if_flags & IFF_LOOPBACK))
+ in_interfaces++;
+ splx(s);
+ }
+ break;
+
+ case SIOCSIFBRDADDR:
+ if ((so->so_state & SS_PRIV) == 0)
+ return (EPERM);
+ /* FALLTHROUGH */
+
+ case SIOCGIFADDR:
+ case SIOCGIFNETMASK:
+ case SIOCGIFDSTADDR:
+ case SIOCGIFBRDADDR:
+ if (ia == (struct in_ifaddr *)0)
+ return (EADDRNOTAVAIL);
+ break;
+ }
+ switch (cmd) {
+
+ case SIOCGIFADDR:
+ *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr;
+ break;
+
+ case SIOCGIFBRDADDR:
+ if ((ifp->if_flags & IFF_BROADCAST) == 0)
+ return (EINVAL);
+ *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr;
+ break;
+
+ case SIOCGIFDSTADDR:
+ if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
+ return (EINVAL);
+ *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr;
+ break;
+
+ case SIOCGIFNETMASK:
+ *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask;
+ break;
+
+ case SIOCSIFDSTADDR:
+ if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
+ return (EINVAL);
+ oldaddr = ia->ia_dstaddr;
+ ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr;
+ if (ifp->if_ioctl && (error = (*ifp->if_ioctl)
+ (ifp, SIOCSIFDSTADDR, (caddr_t)ia))) {
+ ia->ia_dstaddr = oldaddr;
+ return (error);
+ }
+ if (ia->ia_flags & IFA_ROUTE) {
+ ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr;
+ rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
+ ia->ia_ifa.ifa_dstaddr =
+ (struct sockaddr *)&ia->ia_dstaddr;
+ rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
+ }
+ break;
+
+ case SIOCSIFBRDADDR:
+ if ((ifp->if_flags & IFF_BROADCAST) == 0)
+ return (EINVAL);
+ ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr;
+ break;
+
+ case SIOCSIFADDR:
+ return (in_ifinit(ifp, ia,
+ (struct sockaddr_in *) &ifr->ifr_addr, 1));
+
+ case SIOCSIFNETMASK:
+ ia->ia_sockmask.sin_addr = ifra->ifra_addr.sin_addr;
+ ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr);
+ break;
+
+ case SIOCAIFADDR:
+ maskIsNew = 0;
+ hostIsNew = 1;
+ error = 0;
+ if (ia->ia_addr.sin_family == AF_INET) {
+ if (ifra->ifra_addr.sin_len == 0) {
+ ifra->ifra_addr = ia->ia_addr;
+ hostIsNew = 0;
+ } else if (ifra->ifra_addr.sin_addr.s_addr ==
+ ia->ia_addr.sin_addr.s_addr)
+ hostIsNew = 0;
+ }
+ if (ifra->ifra_mask.sin_len) {
+ in_ifscrub(ifp, ia);
+ ia->ia_sockmask = ifra->ifra_mask;
+ ia->ia_subnetmask =
+ ntohl(ia->ia_sockmask.sin_addr.s_addr);
+ maskIsNew = 1;
+ }
+ if ((ifp->if_flags & IFF_POINTOPOINT) &&
+ (ifra->ifra_dstaddr.sin_family == AF_INET)) {
+ in_ifscrub(ifp, ia);
+ ia->ia_dstaddr = ifra->ifra_dstaddr;
+ maskIsNew = 1; /* We lie; but the effect's the same */
+ }
+ if (ifra->ifra_addr.sin_family == AF_INET &&
+ (hostIsNew || maskIsNew))
+ error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
+ if ((ifp->if_flags & IFF_BROADCAST) &&
+ (ifra->ifra_broadaddr.sin_family == AF_INET))
+ ia->ia_broadaddr = ifra->ifra_broadaddr;
+ return (error);
+
+ case SIOCDIFADDR:
+ mk = malloc(sizeof *mk, M_IPMADDR, M_WAITOK);
+ if (!mk)
+ return ENOBUFS;
+
+ in_ifscrub(ifp, ia);
+ /*
+ * Protect from ipintr() traversing address list
+ * while we're modifying it.
+ */
+ s = splnet();
+
+ if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia)
+ ifp->if_addrlist = ifa->ifa_next;
+ else {
+ while (ifa->ifa_next &&
+ (ifa->ifa_next != (struct ifaddr *)ia))
+ ifa = ifa->ifa_next;
+ if (ifa->ifa_next)
+ ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next;
+ else
+ printf("Couldn't unlink inifaddr from ifp\n");
+ }
+ oia = ia;
+ if (oia == (ia = in_ifaddr))
+ in_ifaddr = ia->ia_next;
+ else {
+ while (ia->ia_next && (ia->ia_next != oia))
+ ia = ia->ia_next;
+ if (ia->ia_next)
+ ia->ia_next = oia->ia_next;
+ else
+ printf("Didn't unlink inifadr from list\n");
+ }
+
+ if (!oia->ia_multiaddrs.lh_first) {
+ IFAFREE(&oia->ia_ifa);
+ FREE(mk, M_IPMADDR);
+ splx(s);
+ break;
+ }
+
+ /*
+ * Multicast address kludge:
+ * If there were any multicast addresses attached to this
+ * interface address, either move them to another address
+ * on this interface, or save them until such time as this
+ * interface is reconfigured for IP.
+ */
+ IFP_TO_IA(oia->ia_ifp, ia);
+ if (ia) { /* there is another address */
+ struct in_multi *inm;
+ for(inm = oia->ia_multiaddrs.lh_first; inm;
+ inm = inm->inm_entry.le_next) {
+ IFAFREE(&inm->inm_ia->ia_ifa);
+ ia->ia_ifa.ifa_refcnt++;
+ inm->inm_ia = ia;
+ LIST_INSERT_HEAD(&ia->ia_multiaddrs, inm,
+ inm_entry);
+ }
+ FREE(mk, M_IPMADDR);
+ } else { /* last address on this if deleted, save */
+ struct in_multi *inm;
+
+ LIST_INIT(&mk->mk_head);
+ mk->mk_ifp = ifp;
+
+ for(inm = oia->ia_multiaddrs.lh_first; inm;
+ inm = inm->inm_entry.le_next) {
+ LIST_INSERT_HEAD(&mk->mk_head, inm, inm_entry);
+ }
+
+ if (mk->mk_head.lh_first) {
+ LIST_INSERT_HEAD(&in_mk, mk, mk_entry);
+ } else {
+ FREE(mk, M_IPMADDR);
+ }
+ }
+
+ IFAFREE((&oia->ia_ifa));
+ splx(s);
+ break;
+
+ default:
+ if (ifp == 0 || ifp->if_ioctl == 0)
+ return (EOPNOTSUPP);
+ return ((*ifp->if_ioctl)(ifp, cmd, data));
+ }
+ return (0);
+}
+
+/*
+ * Delete any existing route for an interface.
+ */
+static void
+in_ifscrub(ifp, ia)
+ register struct ifnet *ifp;
+ register struct in_ifaddr *ia;
+{
+
+ if ((ia->ia_flags & IFA_ROUTE) == 0)
+ return;
+ if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))
+ rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
+ else
+ rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
+ ia->ia_flags &= ~IFA_ROUTE;
+}
+
+/*
+ * Initialize an interface's internet address
+ * and routing table entry.
+ */
+static int
+in_ifinit(ifp, ia, sin, scrub)
+ register struct ifnet *ifp;
+ register struct in_ifaddr *ia;
+ struct sockaddr_in *sin;
+ int scrub;
+{
+ register u_long i = ntohl(sin->sin_addr.s_addr);
+ struct sockaddr_in oldaddr;
+ int s = splimp(), flags = RTF_UP, error;
+ struct multi_kludge *mk;
+
+ oldaddr = ia->ia_addr;
+ ia->ia_addr = *sin;
+ /*
+ * Give the interface a chance to initialize
+ * if this is its first address,
+ * and to validate the address if necessary.
+ */
+ if (ifp->if_ioctl &&
+ (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) {
+ splx(s);
+ ia->ia_addr = oldaddr;
+ return (error);
+ }
+ splx(s);
+ if (scrub) {
+ ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
+ in_ifscrub(ifp, ia);
+ ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
+ }
+ if (IN_CLASSA(i))
+ ia->ia_netmask = IN_CLASSA_NET;
+ else if (IN_CLASSB(i))
+ ia->ia_netmask = IN_CLASSB_NET;
+ else
+ ia->ia_netmask = IN_CLASSC_NET;
+ /*
+ * The subnet mask usually includes at least the standard network part,
+ * but may may be smaller in the case of supernetting.
+ * If it is set, we believe it.
+ */
+ if (ia->ia_subnetmask == 0) {
+ ia->ia_subnetmask = ia->ia_netmask;
+ ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
+ } else
+ ia->ia_netmask &= ia->ia_subnetmask;
+ ia->ia_net = i & ia->ia_netmask;
+ ia->ia_subnet = i & ia->ia_subnetmask;
+ in_socktrim(&ia->ia_sockmask);
+ /*
+ * Add route for the network.
+ */
+ ia->ia_ifa.ifa_metric = ifp->if_metric;
+ if (ifp->if_flags & IFF_BROADCAST) {
+ ia->ia_broadaddr.sin_addr.s_addr =
+ htonl(ia->ia_subnet | ~ia->ia_subnetmask);
+ ia->ia_netbroadcast.s_addr =
+ htonl(ia->ia_net | ~ ia->ia_netmask);
+ } else if (ifp->if_flags & IFF_LOOPBACK) {
+ ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
+ flags |= RTF_HOST;
+ } else if (ifp->if_flags & IFF_POINTOPOINT) {
+ if (ia->ia_dstaddr.sin_family != AF_INET)
+ return (0);
+ flags |= RTF_HOST;
+ }
+ if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0)
+ ia->ia_flags |= IFA_ROUTE;
+
+ LIST_INIT(&ia->ia_multiaddrs);
+ /*
+ * If the interface supports multicast, join the "all hosts"
+ * multicast group on that interface.
+ */
+ if (ifp->if_flags & IFF_MULTICAST) {
+ struct in_addr addr;
+
+ /*
+ * Continuation of multicast address hack:
+ * If there was a multicast group list previously saved
+ * for this interface, then we re-attach it to the first
+ * address configured on the i/f.
+ */
+ for(mk = in_mk.lh_first; mk; mk = mk->mk_entry.le_next) {
+ if(mk->mk_ifp == ifp) {
+ struct in_multi *inm;
+
+ for(inm = mk->mk_head.lh_first; inm;
+ inm = inm->inm_entry.le_next) {
+ IFAFREE(&inm->inm_ia->ia_ifa);
+ ia->ia_ifa.ifa_refcnt++;
+ inm->inm_ia = ia;
+ LIST_INSERT_HEAD(&ia->ia_multiaddrs,
+ inm, inm_entry);
+ }
+ LIST_REMOVE(mk, mk_entry);
+ free(mk, M_IPMADDR);
+ break;
+ }
+ }
+
+ addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
+ in_addmulti(&addr, ifp);
+ }
+ return (error);
+}
+
+
+/*
+ * Return 1 if the address might be a local broadcast address.
+ */
+int
+in_broadcast(in, ifp)
+ struct in_addr in;
+ struct ifnet *ifp;
+{
+ register struct ifaddr *ifa;
+ u_long t;
+
+ if (in.s_addr == INADDR_BROADCAST ||
+ in.s_addr == INADDR_ANY)
+ return 1;
+ if ((ifp->if_flags & IFF_BROADCAST) == 0)
+ return 0;
+ t = ntohl(in.s_addr);
+ /*
+ * Look through the list of addresses for a match
+ * with a broadcast address.
+ */
+#define ia ((struct in_ifaddr *)ifa)
+ for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
+ if (ifa->ifa_addr->sa_family == AF_INET &&
+ (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr ||
+ in.s_addr == ia->ia_netbroadcast.s_addr ||
+ /*
+ * Check for old-style (host 0) broadcast.
+ */
+ t == ia->ia_subnet || t == ia->ia_net) &&
+ /*
+ * Check for an all one subnetmask. These
+ * only exist when an interface gets a secondary
+ * address.
+ */
+ ia->ia_subnetmask != (u_long)0xffffffff)
+ return 1;
+ return (0);
+#undef ia
+}
+/*
+ * Add an address to the list of IP multicast addresses for a given interface.
+ */
+struct in_multi *
+in_addmulti(ap, ifp)
+ register struct in_addr *ap;
+ register struct ifnet *ifp;
+{
+ register struct in_multi *inm;
+ struct ifreq ifr;
+ struct in_ifaddr *ia;
+ int s = splnet();
+
+ /*
+ * See if address already in list.
+ */
+ IN_LOOKUP_MULTI(*ap, ifp, inm);
+ if (inm != NULL) {
+ /*
+ * Found it; just increment the reference count.
+ */
+ ++inm->inm_refcount;
+ }
+ else {
+ /*
+ * New address; allocate a new multicast record
+ * and link it into the interface's multicast list.
+ */
+ inm = (struct in_multi *)malloc(sizeof(*inm),
+ M_IPMADDR, M_NOWAIT);
+ if (inm == NULL) {
+ splx(s);
+ return (NULL);
+ }
+ inm->inm_addr = *ap;
+ inm->inm_ifp = ifp;
+ inm->inm_refcount = 1;
+ IFP_TO_IA(ifp, ia);
+ if (ia == NULL) {
+ free(inm, M_IPMADDR);
+ splx(s);
+ return (NULL);
+ }
+ inm->inm_ia = ia;
+ ia->ia_ifa.ifa_refcnt++; /* gain a reference */
+ LIST_INSERT_HEAD(&ia->ia_multiaddrs, inm, inm_entry);
+
+ /*
+ * Ask the network driver to update its multicast reception
+ * filter appropriately for the new address.
+ */
+ ((struct sockaddr_in *)&ifr.ifr_addr)->sin_family = AF_INET;
+ ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr = *ap;
+ if ((ifp->if_ioctl == NULL) ||
+ (*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr) != 0) {
+ LIST_REMOVE(inm, inm_entry);
+ IFAFREE(&ia->ia_ifa); /* release reference */
+ free(inm, M_IPMADDR);
+ splx(s);
+ return (NULL);
+ }
+ /*
+ * Let IGMP know that we have joined a new IP multicast group.
+ */
+ igmp_joingroup(inm);
+ }
+ splx(s);
+ return (inm);
+}
+
+/*
+ * Delete a multicast address record.
+ */
+void
+in_delmulti(inm)
+ register struct in_multi *inm;
+{
+ struct ifreq ifr;
+ int s = splnet();
+
+ if (--inm->inm_refcount == 0) {
+ /*
+ * No remaining claims to this record; let IGMP know that
+ * we are leaving the multicast group.
+ */
+ igmp_leavegroup(inm);
+ /*
+ * Unlink from list.
+ */
+ LIST_REMOVE(inm, inm_entry);
+ IFAFREE(&inm->inm_ia->ia_ifa); /* release reference */
+
+ /*
+ * Notify the network driver to update its multicast reception
+ * filter.
+ */
+ ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET;
+ ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr =
+ inm->inm_addr;
+ (*inm->inm_ifp->if_ioctl)(inm->inm_ifp, SIOCDELMULTI,
+ (caddr_t)&ifr);
+ free(inm, M_IPMADDR);
+ }
+ splx(s);
+}
diff --git a/cpukit/libnetworking/netinet/in.h b/cpukit/libnetworking/netinet/in.h
new file mode 100644
index 0000000000..7b3b0ca834
--- /dev/null
+++ b/cpukit/libnetworking/netinet/in.h
@@ -0,0 +1,443 @@
+/*
+ * Copyright (c) 1982, 1986, 1990, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)in.h 8.3 (Berkeley) 1/3/94
+ * $Id$
+ */
+
+#ifndef _NETINET_IN_H_
+#define _NETINET_IN_H_
+
+#include <machine/endian.h> /* for ntohx routines */
+
+/*
+ * Constants and structures defined by the internet system,
+ * Per RFC 790, September 1981, and numerous additions.
+ */
+
+/*
+ * Protocols (RFC 1700)
+ */
+#define IPPROTO_IP 0 /* dummy for IP */
+#define IPPROTO_ICMP 1 /* control message protocol */
+#define IPPROTO_IGMP 2 /* group mgmt protocol */
+#define IPPROTO_GGP 3 /* gateway^2 (deprecated) */
+#define IPPROTO_IPIP 4 /* IP encapsulation in IP */
+#define IPPROTO_TCP 6 /* tcp */
+#define IPPROTO_ST 7 /* Stream protocol II */
+#define IPPROTO_EGP 8 /* exterior gateway protocol */
+#define IPPROTO_PIGP 9 /* private interior gateway */
+#define IPPROTO_RCCMON 10 /* BBN RCC Monitoring */
+#define IPPROTO_NVPII 11 /* network voice protocol*/
+#define IPPROTO_PUP 12 /* pup */
+#define IPPROTO_ARGUS 13 /* Argus */
+#define IPPROTO_EMCON 14 /* EMCON */
+#define IPPROTO_XNET 15 /* Cross Net Debugger */
+#define IPPROTO_CHAOS 16 /* Chaos*/
+#define IPPROTO_UDP 17 /* user datagram protocol */
+#define IPPROTO_MUX 18 /* Multiplexing */
+#define IPPROTO_MEAS 19 /* DCN Measurement Subsystems */
+#define IPPROTO_HMP 20 /* Host Monitoring */
+#define IPPROTO_PRM 21 /* Packet Radio Measurement */
+#define IPPROTO_IDP 22 /* xns idp */
+#define IPPROTO_TRUNK1 23 /* Trunk-1 */
+#define IPPROTO_TRUNK2 24 /* Trunk-2 */
+#define IPPROTO_LEAF1 25 /* Leaf-1 */
+#define IPPROTO_LEAF2 26 /* Leaf-2 */
+#define IPPROTO_RDP 27 /* Reliable Data */
+#define IPPROTO_IRTP 28 /* Reliable Transaction */
+#define IPPROTO_TP 29 /* tp-4 w/ class negotiation */
+#define IPPROTO_BLT 30 /* Bulk Data Transfer */
+#define IPPROTO_NSP 31 /* Network Services */
+#define IPPROTO_INP 32 /* Merit Internodal */
+#define IPPROTO_SEP 33 /* Sequential Exchange */
+#define IPPROTO_3PC 34 /* Third Party Connect */
+#define IPPROTO_IDPR 35 /* InterDomain Policy Routing */
+#define IPPROTO_XTP 36 /* XTP */
+#define IPPROTO_DDP 37 /* Datagram Delivery */
+#define IPPROTO_CMTP 38 /* Control Message Transport */
+#define IPPROTO_TPXX 39 /* TP++ Transport */
+#define IPPROTO_IL 40 /* IL transport protocol */
+#define IPPROTO_SIP 41 /* Simple Internet Protocol */
+#define IPPROTO_SDRP 42 /* Source Demand Routing */
+#define IPPROTO_SIPSR 43 /* SIP Source Route */
+#define IPPROTO_SIPFRAG 44 /* SIP Fragment */
+#define IPPROTO_IDRP 45 /* InterDomain Routing*/
+#define IPPROTO_RSVP 46 /* resource reservation */
+#define IPPROTO_GRE 47 /* General Routing Encap. */
+#define IPPROTO_MHRP 48 /* Mobile Host Routing */
+#define IPPROTO_BHA 49 /* BHA */
+#define IPPROTO_ESP 50 /* SIPP Encap Sec. Payload */
+#define IPPROTO_AH 51 /* SIPP Auth Header */
+#define IPPROTO_INLSP 52 /* Integ. Net Layer Security */
+#define IPPROTO_SWIPE 53 /* IP with encryption */
+#define IPPROTO_NHRP 54 /* Next Hop Resolution */
+/* 55-60: Unassigned */
+#define IPPROTO_AHIP 61 /* any host internal protocol */
+#define IPPROTO_CFTP 62 /* CFTP */
+#define IPPROTO_HELLO 63 /* "hello" routing protocol */
+#define IPPROTO_SATEXPAK 64 /* SATNET/Backroom EXPAK */
+#define IPPROTO_KRYPTOLAN 65 /* Kryptolan */
+#define IPPROTO_RVD 66 /* Remote Virtual Disk */
+#define IPPROTO_IPPC 67 /* Pluribus Packet Core */
+#define IPPROTO_ADFS 68 /* Any distributed FS */
+#define IPPROTO_SATMON 69 /* Satnet Monitoring */
+#define IPPROTO_VISA 70 /* VISA Protocol */
+#define IPPROTO_IPCV 71 /* Packet Core Utility */
+#define IPPROTO_CPNX 72 /* Comp. Prot. Net. Executive */
+#define IPPROTO_CPHB 73 /* Comp. Prot. HeartBeat */
+#define IPPROTO_WSN 74 /* Wang Span Network */
+#define IPPROTO_PVP 75 /* Packet Video Protocol */
+#define IPPROTO_BRSATMON 76 /* BackRoom SATNET Monitoring */
+#define IPPROTO_ND 77 /* Sun net disk proto (temp.) */
+#define IPPROTO_WBMON 78 /* WIDEBAND Monitoring */
+#define IPPROTO_WBEXPAK 79 /* WIDEBAND EXPAK */
+#define IPPROTO_EON 80 /* ISO cnlp */
+#define IPPROTO_VMTP 81 /* VMTP */
+#define IPPROTO_SVMTP 82 /* Secure VMTP */
+#define IPPROTO_VINES 83 /* Banyon VINES */
+#define IPPROTO_TTP 84 /* TTP */
+#define IPPROTO_IGP 85 /* NSFNET-IGP */
+#define IPPROTO_DGP 86 /* dissimilar gateway prot. */
+#define IPPROTO_TCF 87 /* TCF */
+#define IPPROTO_IGRP 88 /* Cisco/GXS IGRP */
+#define IPPROTO_OSPFIGP 89 /* OSPFIGP */
+#define IPPROTO_SRPC 90 /* Strite RPC protocol */
+#define IPPROTO_LARP 91 /* Locus Address Resoloution */
+#define IPPROTO_MTP 92 /* Multicast Transport */
+#define IPPROTO_AX25 93 /* AX.25 Frames */
+#define IPPROTO_IPEIP 94 /* IP encapsulated in IP */
+#define IPPROTO_MICP 95 /* Mobile Int.ing control */
+#define IPPROTO_SCCSP 96 /* Semaphore Comm. security */
+#define IPPROTO_ETHERIP 97 /* Ethernet IP encapsulation */
+#define IPPROTO_ENCAP 98 /* encapsulation header */
+#define IPPROTO_APES 99 /* any private encr. scheme */
+#define IPPROTO_GMTP 100 /* GMTP*/
+/* 101-254: Unassigned */
+/* 255: Reserved */
+/* BSD Private, local use, namespace incursion */
+#define IPPROTO_DIVERT 254 /* divert pseudo-protocol */
+#define IPPROTO_RAW 255 /* raw IP packet */
+#define IPPROTO_MAX 256
+
+/*
+ * Merged from FreeBSD 1.78 of this file so Python compiles.
+ * This is a size value for functions such as inet_ntop().
+ */
+#define INET_ADDRSTRLEN 16
+
+/*
+ * Local port number conventions:
+ *
+ * When a user does a bind(2) or connect(2) with a port number of zero,
+ * a non-conflicting local port address is chosen.
+ * The default range is IPPORT_RESERVED through
+ * IPPORT_USERRESERVED, although that is settable by sysctl.
+ *
+ * A user may set the IPPROTO_IP option IP_PORTRANGE to change this
+ * default assignment range.
+ *
+ * The value IP_PORTRANGE_DEFAULT causes the default behavior.
+ *
+ * The value IP_PORTRANGE_HIGH changes the range of candidate port numbers
+ * into the "high" range. These are reserved for client outbound connections
+ * which do not want to be filtered by any firewalls.
+ *
+ * The value IP_PORTRANGE_LOW changes the range to the "low" are
+ * that is (by convention) restricted to privileged processes. This
+ * convention is based on "vouchsafe" principles only. It is only secure
+ * if you trust the remote host to restrict these ports.
+ *
+ * The default range of ports and the high range can be changed by
+ * sysctl(3). (net.inet.ip.port{hi,low}{first,last}_auto)
+ *
+ * Changing those values has bad security implications if you are
+ * using a a stateless firewall that is allowing packets outside of that
+ * range in order to allow transparent outgoing connections.
+ *
+ * Such a firewall configuration will generally depend on the use of these
+ * default values. If you change them, you may find your Security
+ * Administrator looking for you with a heavy object.
+ */
+
+/*
+ * Ports < IPPORT_RESERVED are reserved for
+ * privileged processes (e.g. root). (IP_PORTRANGE_LOW)
+ * Ports > IPPORT_USERRESERVED are reserved
+ * for servers, not necessarily privileged. (IP_PORTRANGE_DEFAULT)
+ */
+#define IPPORT_RESERVED 1024
+#define IPPORT_USERRESERVED 5000
+
+/*
+ * Default local port range to use by setting IP_PORTRANGE_HIGH
+ */
+#define IPPORT_HIFIRSTAUTO 40000
+#define IPPORT_HILASTAUTO 44999
+
+/*
+ * Scanning for a free reserved port return a value below IPPORT_RESERVED,
+ * but higher than IPPORT_RESERVEDSTART. Traditionally the start value was
+ * 512, but that conflicts with some well-known-services that firewalls may
+ * have a fit if we use.
+ */
+#define IPPORT_RESERVEDSTART 600
+#define BYTE_PACK __attribute__((packed))
+/*
+ * Internet address (a structure for historical reasons)
+ */
+struct in_addr {
+ u_long s_addr BYTE_PACK;
+};
+
+/*
+ * Definitions of bits in internet address integers.
+ * On subnets, the decomposition of addresses to host and net parts
+ * is done according to subnet mask, not the masks here.
+ */
+#define IN_CLASSA(i) (((long)(i) & 0x80000000) == 0)
+#define IN_CLASSA_NET 0xff000000
+#define IN_CLASSA_NSHIFT 24
+#define IN_CLASSA_HOST 0x00ffffff
+#define IN_CLASSA_MAX 128
+
+#define IN_CLASSB(i) (((long)(i) & 0xc0000000) == 0x80000000)
+#define IN_CLASSB_NET 0xffff0000
+#define IN_CLASSB_NSHIFT 16
+#define IN_CLASSB_HOST 0x0000ffff
+#define IN_CLASSB_MAX 65536
+
+#define IN_CLASSC(i) (((long)(i) & 0xe0000000) == 0xc0000000)
+#define IN_CLASSC_NET 0xffffff00
+#define IN_CLASSC_NSHIFT 8
+#define IN_CLASSC_HOST 0x000000ff
+
+#define IN_CLASSD(i) (((long)(i) & 0xf0000000) == 0xe0000000)
+#define IN_CLASSD_NET 0xf0000000 /* These ones aren't really */
+#define IN_CLASSD_NSHIFT 28 /* net and host fields, but */
+#define IN_CLASSD_HOST 0x0fffffff /* routing needn't know. */
+#define IN_MULTICAST(i) IN_CLASSD(i)
+
+#define IN_EXPERIMENTAL(i) (((long)(i) & 0xf0000000) == 0xf0000000)
+#define IN_BADCLASS(i) (((long)(i) & 0xf0000000) == 0xf0000000)
+
+#define INADDR_ANY (u_long)0x00000000
+#define INADDR_BROADCAST (u_long)0xffffffff /* must be masked */
+#ifndef _KERNEL
+#define INADDR_NONE 0xffffffff /* -1 return */
+#endif
+
+#define INADDR_UNSPEC_GROUP (u_long)0xe0000000 /* 224.0.0.0 */
+#define INADDR_ALLHOSTS_GROUP (u_long)0xe0000001 /* 224.0.0.1 */
+#define INADDR_ALLRTRS_GROUP (u_long)0xe0000002 /* 224.0.0.2 */
+#define INADDR_MAX_LOCAL_GROUP (u_long)0xe00000ff /* 224.0.0.255 */
+
+#define IN_LOOPBACKNET 127 /* official! */
+#ifndef INADDR_LOOPBACK
+#define INADDR_LOOPBACK (u_long)0x7F000001 /* 127.0.0.1 */
+#endif
+
+/*
+ * Socket address, internet style.
+ */
+struct sockaddr_in {
+ u_char sin_len;
+ u_char sin_family;
+ u_short sin_port;
+ struct in_addr sin_addr;
+ char sin_zero[8];
+};
+
+/*
+ * Structure used to describe IP options.
+ * Used to store options internally, to pass them to a process,
+ * or to restore options retrieved earlier.
+ * The ip_dst is used for the first-hop gateway when using a source route
+ * (this gets put into the header proper).
+ */
+struct ip_opts {
+ struct in_addr ip_dst; /* first hop, 0 w/o src rt */
+ char ip_opts[40]; /* actually variable in size */
+};
+
+/*
+ * Options for use with [gs]etsockopt at the IP level.
+ * First word of comment is data type; bool is stored in int.
+ */
+#define IP_OPTIONS 1 /* buf/ip_opts; set/get IP options */
+#define IP_HDRINCL 2 /* int; header is included with data */
+#define IP_TOS 3 /* int; IP type of service and preced. */
+#define IP_TTL 4 /* int; IP time to live */
+#define IP_RECVOPTS 5 /* bool; receive all IP opts w/dgram */
+#define IP_RECVRETOPTS 6 /* bool; receive IP opts for response */
+#define IP_RECVDSTADDR 7 /* bool; receive IP dst addr w/dgram */
+#define IP_RETOPTS 8 /* ip_opts; set/get IP options */
+#define IP_MULTICAST_IF 9 /* u_char; set/get IP multicast i/f */
+#define IP_MULTICAST_TTL 10 /* u_char; set/get IP multicast ttl */
+#define IP_MULTICAST_LOOP 11 /* u_char; set/get IP multicast loopback */
+#define IP_ADD_MEMBERSHIP 12 /* ip_mreq; add an IP group membership */
+#define IP_DROP_MEMBERSHIP 13 /* ip_mreq; drop an IP group membership */
+#define IP_MULTICAST_VIF 14 /* set/get IP mcast virt. iface */
+#define IP_RSVP_ON 15 /* enable RSVP in kernel */
+#define IP_RSVP_OFF 16 /* disable RSVP in kernel */
+#define IP_RSVP_VIF_ON 17 /* set RSVP per-vif socket */
+#define IP_RSVP_VIF_OFF 18 /* unset RSVP per-vif socket */
+#define IP_PORTRANGE 19 /* int; range to choose for unspec port */
+#define IP_RECVIF 20 /* bool; receive reception if w/dgram */
+
+#define IP_FW_ADD 50 /* add a firewall rule to chain */
+#define IP_FW_DEL 51 /* delete a firewall rule from chain */
+#define IP_FW_FLUSH 52 /* flush firewall rule chain */
+#define IP_FW_ZERO 53 /* clear single/all firewall counter(s) */
+#define IP_FW_GET 54 /* get entire firewall rule chain */
+#define IP_NAT 55 /* set/get NAT opts */
+
+/*
+ * Defaults and limits for options
+ */
+#define IP_DEFAULT_MULTICAST_TTL 1 /* normally limit m'casts to 1 hop */
+#define IP_DEFAULT_MULTICAST_LOOP 1 /* normally hear sends if a member */
+#define IP_MAX_MEMBERSHIPS 20 /* per socket */
+
+/*
+ * Argument structure for IP_ADD_MEMBERSHIP and IP_DROP_MEMBERSHIP.
+ */
+struct ip_mreq {
+ struct in_addr imr_multiaddr; /* IP multicast address of group */
+ struct in_addr imr_interface; /* local IP address of interface */
+};
+
+/*
+ * Argument for IP_PORTRANGE:
+ * - which range to search when port is unspecified at bind() or connect()
+ */
+#define IP_PORTRANGE_DEFAULT 0 /* default range */
+#define IP_PORTRANGE_HIGH 1 /* "high" - request firewall bypass */
+#define IP_PORTRANGE_LOW 2 /* "low" - vouchsafe security */
+
+/*
+ * Definitions for inet sysctl operations.
+ *
+ * Third level is protocol number.
+ * Fourth level is desired variable within that protocol.
+ */
+#define IPPROTO_MAXID (IPPROTO_IDP + 1) /* don't list to IPPROTO_MAX */
+
+#define CTL_IPPROTO_NAMES { \
+ { "ip", CTLTYPE_NODE }, \
+ { "icmp", CTLTYPE_NODE }, \
+ { "igmp", CTLTYPE_NODE }, \
+ { "ggp", CTLTYPE_NODE }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { "tcp", CTLTYPE_NODE }, \
+ { 0, 0 }, \
+ { "egp", CTLTYPE_NODE }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { "pup", CTLTYPE_NODE }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { "udp", CTLTYPE_NODE }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { 0, 0 }, \
+ { "idp", CTLTYPE_NODE }, \
+}
+
+/*
+ * Names for IP sysctl objects
+ */
+#define IPCTL_FORWARDING 1 /* act as router */
+#define IPCTL_SENDREDIRECTS 2 /* may send redirects when forwarding */
+#define IPCTL_DEFTTL 3 /* default TTL */
+#ifdef notyet
+#define IPCTL_DEFMTU 4 /* default MTU */
+#endif
+#define IPCTL_RTEXPIRE 5 /* cloned route expiration time */
+#define IPCTL_RTMINEXPIRE 6 /* min value for expiration time */
+#define IPCTL_RTMAXCACHE 7 /* trigger level for dynamic expire */
+#define IPCTL_SOURCEROUTE 8 /* may perform source routes */
+#define IPCTL_DIRECTEDBROADCAST 9 /* may re-broadcast received packets */
+#define IPCTL_INTRQMAXLEN 10 /* max length of netisr queue */
+#define IPCTL_INTRQDROPS 11 /* number of netisr q drops */
+#define IPCTL_ACCEPTSOURCEROUTE 13 /* may accept source routed packets */
+#define IPCTL_MAXID 13
+
+#define IPCTL_NAMES { \
+ { 0, 0 }, \
+ { "forwarding", CTLTYPE_INT }, \
+ { "redirect", CTLTYPE_INT }, \
+ { "ttl", CTLTYPE_INT }, \
+ { "mtu", CTLTYPE_INT }, \
+ { "rtexpire", CTLTYPE_INT }, \
+ { "rtminexpire", CTLTYPE_INT }, \
+ { "rtmaxcache", CTLTYPE_INT }, \
+ { "sourceroute", CTLTYPE_INT }, \
+ { "directed-broadcast", CTLTYPE_INT }, \
+ { "intr-queue-maxlen", CTLTYPE_INT }, \
+ { "intr-queue-drops", CTLTYPE_INT }, \
+ { "accept_sourceroute", CTLTYPE_INT }, \
+}
+
+
+#ifdef _KERNEL
+struct ifnet; struct mbuf; /* forward declarations for Standard C */
+
+int in_broadcast __P((struct in_addr, struct ifnet *));
+int in_canforward __P((struct in_addr));
+int in_cksum __P((struct mbuf *, int));
+int in_localaddr __P((struct in_addr));
+char *inet_ntoa __P((struct in_addr)); /* in libkern */
+
+/* Firewall hooks */
+struct ip;
+typedef int ip_fw_chk_t __P((struct ip**, int, struct ifnet*, int, struct mbuf**));
+typedef int ip_fw_ctl_t __P((int, struct mbuf**));
+extern ip_fw_chk_t *ip_fw_chk_ptr;
+extern ip_fw_ctl_t *ip_fw_ctl_ptr;
+
+/* IP NAT hooks */
+typedef int ip_nat_t __P((struct ip**, struct mbuf**, struct ifnet*, int));
+typedef int ip_nat_ctl_t __P((int, struct mbuf**));
+extern ip_nat_t *ip_nat_ptr;
+extern ip_nat_ctl_t *ip_nat_ctl_ptr;
+#define IP_NAT_IN 0x00000001
+#define IP_NAT_OUT 0x00000002
+
+#endif /* _KERNEL */
+
+#endif
diff --git a/cpukit/libnetworking/netinet/in_cksum.c b/cpukit/libnetworking/netinet/in_cksum.c
new file mode 100644
index 0000000000..a2728d04b0
--- /dev/null
+++ b/cpukit/libnetworking/netinet/in_cksum.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 1988, 1992, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93
+ * $Id$
+ */
+
+#include <sys/param.h>
+#include <sys/mbuf.h>
+
+/*
+ * Try to use a CPU specific version, then punt to the portable C one.
+ */
+
+
+#if (defined(__GNUC__) && defined(__arm__))
+
+#include "in_cksum_arm.h"
+
+#elif (defined(__GNUC__) && defined(__i386__))
+
+#include "in_cksum_i386.h"
+
+#elif (defined(__GNUC__) && (defined(__mc68000__) || defined(__m68k__)))
+
+#include "in_cksum_m68k.h"
+#elif (defined(__GNUC__) && defined(__PPC__))
+
+#include "in_cksum_powerpc.h"
+
+#else
+
+#include <stdio.h> /* for puts */
+
+/*
+ * Checksum routine for Internet Protocol family headers (Portable Version).
+ *
+ * This routine is very heavily used in the network
+ * code and should be modified for each CPU to be as fast as possible.
+ */
+
+#define ADDCARRY(x) (x > 65535 ? x -= 65535 : x)
+#define REDUCE \
+ {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);}
+
+int
+in_cksum(m, len)
+ register struct mbuf *m;
+ register int len;
+{
+ register u_short *w;
+ register int sum = 0;
+ register int mlen = 0;
+ int byte_swapped = 0;
+
+ union {
+ char c[2];
+ u_short s;
+ } s_util;
+ union {
+ u_short s[2];
+ long l;
+ } l_util;
+
+ for (;m && len; m = m->m_next) {
+ if (m->m_len == 0)
+ continue;
+ w = mtod(m, u_short *);
+ if (mlen == -1) {
+ /*
+ * The first byte of this mbuf is the continuation
+ * of a word spanning between this mbuf and the
+ * last mbuf.
+ *
+ * s_util.c[0] is already saved when scanning previous
+ * mbuf.
+ */
+ s_util.c[1] = *(char *)w;
+ sum += s_util.s;
+ w = (u_short *)((char *)w + 1);
+ mlen = m->m_len - 1;
+ len--;
+ } else
+ mlen = m->m_len;
+ if (len < mlen)
+ mlen = len;
+ len -= mlen;
+ /*
+ * Force to even boundary.
+ */
+ if ((1 & (int) w) && (mlen > 0)) {
+ REDUCE;
+ sum <<= 8;
+ s_util.c[0] = *(u_char *)w;
+ w = (u_short *)((char *)w + 1);
+ mlen--;
+ byte_swapped = 1;
+ }
+ /*
+ * Unroll the loop to make overhead from
+ * branches &c small.
+ */
+ while ((mlen -= 32) >= 0) {
+ sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
+ sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
+ sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
+ sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
+ w += 16;
+ }
+ mlen += 32;
+ while ((mlen -= 8) >= 0) {
+ sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
+ w += 4;
+ }
+ mlen += 8;
+ if (mlen == 0 && byte_swapped == 0)
+ continue;
+ REDUCE;
+ while ((mlen -= 2) >= 0) {
+ sum += *w++;
+ }
+ if (byte_swapped) {
+ REDUCE;
+ sum <<= 8;
+ byte_swapped = 0;
+ if (mlen == -1) {
+ s_util.c[1] = *(char *)w;
+ sum += s_util.s;
+ mlen = 0;
+ } else
+ mlen = -1;
+ } else if (mlen == -1)
+ s_util.c[0] = *(char *)w;
+ }
+ if (len)
+ puts("cksum: out of data");
+ if (mlen == -1) {
+ /* The last mbuf has odd # of bytes. Follow the
+ standard (the odd byte may be shifted left by 8 bits
+ or not as determined by endian-ness of the machine) */
+ s_util.c[1] = 0;
+ sum += s_util.s;
+ }
+ REDUCE;
+ return (~sum & 0xffff);
+}
+#endif
diff --git a/cpukit/libnetworking/netinet/in_cksum_arm.h b/cpukit/libnetworking/netinet/in_cksum_arm.h
new file mode 100644
index 0000000000..10d21ab2a6
--- /dev/null
+++ b/cpukit/libnetworking/netinet/in_cksum_arm.h
@@ -0,0 +1,276 @@
+/* $NetBSD: in_cksum_arm.c,v 1.3 2001/12/08 21:18:50 chris Exp $ */
+
+/*
+ * ARM version:
+ *
+ * Copyright (c) 1997 Mark Brinicome
+ * Copyright (c) 1997 Causality Limited
+ *
+ * Based on the sparc version.
+ */
+
+/*
+ * Sparc version:
+ *
+ * Copyright (c) 1995 Zubin Dittia.
+ * Copyright (c) 1995 Matthew R. Green.
+ * Copyright (c) 1994 Charles M. Hannum.
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)in_cksum.c 8.1 (Berkeley) 6/11/93
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+
+/*
+ * Checksum routine for Internet Protocol family headers.
+ *
+ * This routine is very heavily used in the network
+ * code and should be modified for each CPU to be as fast as possible.
+ *
+ * ARM version.
+ */
+
+#define ADD64 __asm __volatile(" \n\
+ ldmia %0!, {%2, %3, %4, %5} \n\
+ adds %1,%7,%2; adcs %1,%1,%3 \n\
+ adcs %1,%1,%4; adcs %1,%1,%5 \n\
+ ldmia %0!, {%2, %3, %4, %5} \n\
+ adcs %1,%1,%2; adcs %1,%1,%3 \n\
+ adcs %1,%1,%4; adcs %1,%1,%5 \n\
+ ldmia %0!, {%2, %3, %4, %5} \n\
+ adcs %1,%1,%2; adcs %1,%1,%3 \n\
+ adcs %1,%1,%4; adcs %1,%1,%5 \n\
+ ldmia %0!, {%2, %3, %4, %5} \n\
+ adcs %1,%1,%2; adcs %1,%1,%3 \n\
+ adcs %1,%1,%4; adcs %1,%1,%5 \n\
+ adcs %1,%1,#0\n" \
+ : "=r" (w), "=r" (sum), "=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3), "=&r" (tmp4) \
+ : "0" (w), "r" (sum) \
+ : "cc")
+
+#define ADD32 __asm __volatile(" \n\
+ ldmia %0!, {%2, %3, %4, %5} \n\
+ adds %1,%7,%2; adcs %1,%1,%3 \n\
+ adcs %1,%1,%4; adcs %1,%1,%5 \n\
+ ldmia %0!, {%2, %3, %4, %5} \n\
+ adcs %1,%1,%2; adcs %1,%1,%3 \n\
+ adcs %1,%1,%4; adcs %1,%1,%5 \n\
+ adcs %1,%1,#0\n" \
+ : "=r" (w), "=r" (sum), "=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3), "=&r" (tmp4) \
+ : "0" (w), "r" (sum) \
+ : "cc")
+
+#define ADD16 __asm __volatile(" \n\
+ ldmia %0!, {%2, %3, %4, %5} \n\
+ adds %1,%7,%2; adcs %1,%1,%3 \n\
+ adcs %1,%1,%4; adcs %1,%1,%5 \n\
+ adcs %1,%1,#0\n" \
+ : "=r" (w), "=r" (sum), "=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3), "=&r" (tmp4) \
+ : "0" (w), "r" (sum) \
+ : "cc")
+
+#define ADD8 __asm __volatile(" \n\
+ ldmia %0!, {%2, %3} \n\
+ adds %1,%5,%2; adcs %1,%1,%3 \n\
+ adcs %1,%1,#0\n" \
+ : "=r" (w), "=r" (sum), "=&r" (tmp1), "=&r" (tmp2) \
+ : "0" (w), "r" (sum) \
+ : "cc" )
+
+#define ADD4 __asm __volatile(" \n\
+ ldr %2,[%0],#4 \n\
+ adds %1,%4,%2 \n\
+ adcs %1,%1,#0\n" \
+ : "=r" (w), "=r" (sum), "=&r" (tmp1) \
+ : "0" (w), "r" (sum) \
+ : "cc")
+
+/*#define REDUCE {sum = (sum & 0xffff) + (sum >> 16);}*/
+#define REDUCE __asm __volatile(" \n\
+ mov %2, #0x00ff \n\
+ orr %2, %2, #0xff00 \n\
+ and %2, %0, %2 \n\
+ add %0, %2, %0, lsr #16\n" \
+ : "=r" (sum) \
+ : "0" (sum), "r" (tmp1))
+
+#define ADDCARRY {if (sum > 0xffff) sum -= 0xffff;}
+#define ROL {sum = sum << 8;} /* depends on recent REDUCE */
+#define ADDBYTE {ROL; sum += (*w << 8); byte_swapped ^= 1;}
+#define ADDSHORT {sum += *(u_short *)w;}
+#define ADVANCE(n) {w += n; mlen -= n;}
+#define ADVANCEML(n) {mlen -= n;}
+
+static __inline__ int
+in_cksum_internal(struct mbuf *m, int off, int len, u_int sum)
+{
+ u_char *w;
+ int mlen = 0;
+ int byte_swapped = 0;
+
+ /*
+ * Declare four temporary registers for use by the asm code. We
+ * allow the compiler to pick which specific machine registers to
+ * use, instead of hard-coding this in the asm code above.
+ */
+ register u_int tmp1=0, tmp2, tmp3, tmp4;
+
+ for (; m && len; m = m->m_next) {
+ if (m->m_len == 0)
+ continue;
+ w = mtod(m, u_char *) + off;
+ mlen = m->m_len - off;
+ off = 0;
+ if (len < mlen)
+ mlen = len;
+ len -= mlen;
+
+ /*
+ * Ensure that we're aligned on a word boundary here so
+ * that we can do 32 bit operations below.
+ */
+ if ((3 & (long)w) != 0) {
+ REDUCE;
+ if ((1 & (long)w) != 0 && mlen >= 1) {
+ ADDBYTE;
+ ADVANCE(1);
+ }
+ if ((2 & (long)w) != 0 && mlen >= 2) {
+ ADDSHORT;
+ ADVANCE(2);
+ }
+ }
+
+ /*
+ * Do as many 32 bit operations as possible using the
+ * 64/32/16/8/4 macro's above, using as many as possible of
+ * these.
+ */
+
+ while (mlen >= 64) {
+ ADD64;
+ ADVANCEML(64);
+ }
+ if (mlen >= 32) {
+ ADD32;
+ ADVANCEML(32);
+ }
+ if (mlen >= 16) {
+ ADD16;
+ ADVANCEML(16);
+ }
+ if (mlen >= 8) {
+ ADD8;
+ ADVANCEML(8);
+ }
+ if (mlen >= 4) {
+ ADD4;
+ ADVANCEML(4)
+ }
+ if (mlen == 0)
+ continue;
+
+ REDUCE;
+ if (mlen >= 2) {
+ ADDSHORT;
+ ADVANCE(2);
+ }
+ if (mlen == 1) {
+ ADDBYTE;
+ }
+ }
+ if (byte_swapped) {
+ REDUCE;
+ ROL;
+ }
+ REDUCE;
+ ADDCARRY;
+
+ return (0xffff ^ sum);
+}
+
+int
+in_cksum(m, len)
+ struct mbuf *m;
+ int len;
+{
+ int cksum;
+ cksum =in_cksum_internal(m, 0, len, 0);
+ return cksum;
+}
+
+int
+in4_cksum(m, nxt, off, len)
+ struct mbuf *m;
+ u_int8_t nxt;
+ int off, len;
+{
+ u_int sum = 0;
+
+ if (nxt != 0) {
+ /* for ADD macros */
+ register u_int tmp1, tmp2, tmp3, tmp4;
+ u_char *w;
+ struct ipovly ipov;
+ /* pseudo header */
+ if (off < sizeof(struct ipovly))
+ panic("in4_cksum: offset too short");
+ if (m->m_len < sizeof(struct ip))
+ panic("in4_cksum: bad mbuf chain");
+
+ bzero(&ipov, sizeof(ipov));
+ ipov.ih_len = htons(len);
+ ipov.ih_pr = nxt;
+ ipov.ih_src = mtod(m, struct ip *)->ip_src;
+ ipov.ih_dst = mtod(m, struct ip *)->ip_dst;
+ w = (u_char *)&ipov;
+
+ /* assumes sizeof(ipov) == 20 */
+ ADD16;
+ ADD4;
+ }
+ /* skip unnecessary part */
+ while (m && off > 0) {
+ if (m->m_len > off)
+ break;
+ off -= m->m_len;
+ m = m->m_next;
+ }
+ return (in_cksum_internal(m, off, len, sum));
+}
diff --git a/cpukit/libnetworking/netinet/in_cksum_i386.h b/cpukit/libnetworking/netinet/in_cksum_i386.h
new file mode 100644
index 0000000000..a64bd57832
--- /dev/null
+++ b/cpukit/libnetworking/netinet/in_cksum_i386.h
@@ -0,0 +1,204 @@
+/*
+ * Checksum routine for Internet Protocol family headers.
+ *
+ * This routine is very heavily used in the network
+ * code and should be modified for each CPU to be as fast as possible.
+ *
+ * This implementation is 386 version.
+ *
+ * $Id$
+ */
+
+#include <stdio.h> /* for puts */
+
+#undef ADDCARRY
+#define ADDCARRY(x) if ((x) > 0xffff) (x) -= 0xffff
+#define REDUCE {sum = (sum & 0xffff) + (sum >> 16); ADDCARRY(sum);}
+
+/*
+ * Thanks to gcc we don't have to guess
+ * which registers contain sum & w.
+ */
+#define ADD(n) __asm__ volatile \
+ ("addl " #n "(%2), %0" : "=r" (sum) : "0" (sum), "r" (w))
+#define ADDC(n) __asm__ volatile \
+ ("adcl " #n "(%2), %0" : "=r" (sum) : "0" (sum), "r" (w))
+#define LOAD(n) __asm__ volatile \
+ ("movb " #n "(%1), %0" : "=r" (junk) : "r" (w))
+#define MOP __asm__ volatile \
+ ("adcl $0, %0" : "=r" (sum) : "0" (sum))
+
+int
+in_cksum(m, len)
+ register struct mbuf *m;
+ register int len;
+{
+ register u_short *w;
+ register unsigned sum = 0;
+ register int mlen = 0;
+ int byte_swapped = 0;
+ union { char c[2]; u_short s; } su;
+
+ for (;m && len; m = m->m_next) {
+ if (m->m_len == 0)
+ continue;
+ w = mtod(m, u_short *);
+ if (mlen == -1) {
+ /*
+ * The first byte of this mbuf is the continuation
+ * of a word spanning between this mbuf and the
+ * last mbuf.
+ */
+
+ /* su.c[0] is already saved when scanning previous
+ * mbuf. sum was REDUCEd when we found mlen == -1
+ */
+ su.c[1] = *(u_char *)w;
+ sum += su.s;
+ w = (u_short *)((char *)w + 1);
+ mlen = m->m_len - 1;
+ len--;
+ } else
+ mlen = m->m_len;
+ if (len < mlen)
+ mlen = len;
+ len -= mlen;
+ /*
+ * Force to long boundary so we do longword aligned
+ * memory operations
+ */
+ if (3 & (int) w) {
+ REDUCE;
+ if ((1 & (int) w) && (mlen > 0)) {
+ sum <<= 8;
+ su.c[0] = *(char *)w;
+ w = (u_short *)((char *)w + 1);
+ mlen--;
+ byte_swapped = 1;
+ }
+ if ((2 & (int) w) && (mlen >= 2)) {
+ sum += *w++;
+ mlen -= 2;
+ }
+ }
+ /*
+ * Advance to a 486 cache line boundary.
+ */
+ if (4 & (int) w && mlen >= 4) {
+ ADD(0);
+ MOP;
+ w += 2;
+ mlen -= 4;
+ }
+ if (8 & (int) w && mlen >= 8) {
+ ADD(0);
+ ADDC(4);
+ MOP;
+ w += 4;
+ mlen -= 8;
+ }
+ /*
+ * Do as much of the checksum as possible 32 bits at at time.
+ * In fact, this loop is unrolled to make overhead from
+ * branches &c small.
+ */
+ mlen -= 1;
+ while ((mlen -= 32) >= 0) {
+ u_char junk;
+ /*
+ * Add with carry 16 words and fold in the last
+ * carry by adding a 0 with carry.
+ *
+ * The early ADD(16) and the LOAD(32) are to load
+ * the next 2 cache lines in advance on 486's. The
+ * 486 has a penalty of 2 clock cycles for loading
+ * a cache line, plus whatever time the external
+ * memory takes to load the first word(s) addressed.
+ * These penalties are unavoidable. Subsequent
+ * accesses to a cache line being loaded (and to
+ * other external memory?) are delayed until the
+ * whole load finishes. These penalties are mostly
+ * avoided by not accessing external memory for
+ * 8 cycles after the ADD(16) and 12 cycles after
+ * the LOAD(32). The loop terminates when mlen
+ * is initially 33 (not 32) to guaranteed that
+ * the LOAD(32) is within bounds.
+ */
+ ADD(16);
+ ADDC(0);
+ ADDC(4);
+ ADDC(8);
+ ADDC(12);
+ LOAD(32);
+ ADDC(20);
+ ADDC(24);
+ ADDC(28);
+ MOP;
+ w += 16;
+ }
+ mlen += 32 + 1;
+ if (mlen >= 32) {
+ ADD(16);
+ ADDC(0);
+ ADDC(4);
+ ADDC(8);
+ ADDC(12);
+ ADDC(20);
+ ADDC(24);
+ ADDC(28);
+ MOP;
+ w += 16;
+ mlen -= 32;
+ }
+ if (mlen >= 16) {
+ ADD(0);
+ ADDC(4);
+ ADDC(8);
+ ADDC(12);
+ MOP;
+ w += 8;
+ mlen -= 16;
+ }
+ if (mlen >= 8) {
+ ADD(0);
+ ADDC(4);
+ MOP;
+ w += 4;
+ mlen -= 8;
+ }
+ if (mlen == 0 && byte_swapped == 0)
+ continue; /* worth 1% maybe ?? */
+ REDUCE;
+ while ((mlen -= 2) >= 0) {
+ sum += *w++;
+ }
+ if (byte_swapped) {
+ sum <<= 8;
+ byte_swapped = 0;
+ if (mlen == -1) {
+ su.c[1] = *(char *)w;
+ sum += su.s;
+ mlen = 0;
+ } else
+ mlen = -1;
+ } else if (mlen == -1)
+ /*
+ * This mbuf has odd number of bytes.
+ * There could be a word split betwen
+ * this mbuf and the next mbuf.
+ * Save the last byte (to prepend to next mbuf).
+ */
+ su.c[0] = *(char *)w;
+ }
+
+ if (len)
+ puts("cksum: out of data");
+ if (mlen == -1) {
+ /* The last mbuf has odd # of bytes. Follow the
+ standard (the odd byte is shifted left by 8 bits) */
+ su.c[1] = 0;
+ sum += su.s;
+ }
+ REDUCE;
+ return (~sum & 0xffff);
+}
diff --git a/cpukit/libnetworking/netinet/in_cksum_m68k.h b/cpukit/libnetworking/netinet/in_cksum_m68k.h
new file mode 100644
index 0000000000..58199c3adf
--- /dev/null
+++ b/cpukit/libnetworking/netinet/in_cksum_m68k.h
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 1988, 1992, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93
+ * $Id$
+ */
+
+#include <sys/param.h>
+#include <sys/mbuf.h>
+
+#if (defined (__mcf5200__))
+# define IS_COLDFIRE 1
+#else
+# define IS_COLDFIRE 0
+#endif
+
+#define REDUCE { sum = (sum & 0xFFFF) + (sum >> 16); if (sum > 0xFFFF) sum -= 0xFFFF; }
+
+/*
+ * Motorola 68k version of Internet Protocol Checksum routine
+ * W. Eric Norum
+ * Saskatchewan Accelerator Laboratory
+ * August, 1998
+ */
+int
+in_cksum(m, len)
+ struct mbuf *m;
+ int len;
+{
+ unsigned short *w;
+ unsigned long sum = 0;
+ int mlen = 0;
+ int byte_swapped = 0;
+ union {
+ char c[2];
+ u_short s;
+ } s_util;
+
+ for ( ; m && len ; m = m->m_next) {
+ if (m->m_len == 0)
+ continue;
+ w = mtod(m, u_short *);
+ if (mlen == -1) {
+ /*
+ * The first byte of this mbuf is the continuation
+ * of a word spanning between this mbuf and the
+ * last mbuf.
+ *
+ * s_util.c[0] is already saved when scanning previous
+ * mbuf.
+ */
+ s_util.c[1] = *(char *)w;
+ sum += s_util.s;
+ w = (u_short *)((char *)w + 1);
+ mlen = m->m_len - 1;
+ len--;
+ } else
+ mlen = m->m_len;
+ if (len < mlen)
+ mlen = len;
+ len -= mlen;
+
+ /*
+ * Force to longword boundary.
+ */
+ if (3 & (int)w) {
+ REDUCE;
+ if ((1 & (int) w) && (mlen > 0)) {
+ sum <<= 8;
+ s_util.c[0] = *(u_char *)w;
+ w = (u_short *)((char *)w + 1);
+ mlen--;
+ byte_swapped = 1;
+ }
+ if ((2 & (int) w) && (mlen >= 2)) {
+ sum += *w++;
+ mlen -= 2;
+ }
+ }
+
+ /*
+ * Sum all the longwords in the buffer.
+ * See RFC 1071 -- Computing the Internet Checksum.
+ * It should work for all 68k family members.
+ */
+ {
+ unsigned long tcnt = mlen, t1;
+ __asm__ volatile (
+ "movel %2,%3\n\t"
+ "lsrl #6,%2 | count/64 = # loop traversals\n\t"
+ "andl #0x3c,%3 | Then find fractions of a chunk\n\t"
+ "negl %3\n\t | Each long uses 4 instruction bytes\n\t"
+#if IS_COLDFIRE
+ "addql #1,%2 | Clear X (extended carry flag)\n\t"
+ "subql #1,%2 | \n\t"
+#else
+ "andi #0xf,%%cc | Clear X (extended carry flag)\n\t"
+#endif
+ "jmp %%pc@(lcsum2_lbl-.-2:b,%3) | Jump into loop\n"
+ "lcsum1_lbl: | Begin inner loop...\n\t"
+ "movel %1@+,%3 | 0: Fetch 32-bit word\n\t"
+ "addxl %3,%0 | Add word + previous carry\n\t"
+ "movel %1@+,%3 | 1: Fetch 32-bit word\n\t"
+ "addxl %3,%0 | Add word + previous carry\n\t"
+ "movel %1@+,%3 | 2: Fetch 32-bit word\n\t"
+ "addxl %3,%0 | Add word + previous carry\n\t"
+ "movel %1@+,%3 | 3: Fetch 32-bit word\n\t"
+ "addxl %3,%0 | Add word + previous carry\n\t"
+ "movel %1@+,%3 | 4: Fetch 32-bit word\n\t"
+ "addxl %3,%0 | Add word + previous carry\n\t"
+ "movel %1@+,%3 | 5: Fetch 32-bit word\n\t"
+ "addxl %3,%0 | Add word + previous carry\n\t"
+ "movel %1@+,%3 | 6: Fetch 32-bit word\n\t"
+ "addxl %3,%0 | Add word + previous carry\n\t"
+ "movel %1@+,%3 | 7: Fetch 32-bit word\n\t"
+ "addxl %3,%0 | Add word + previous carry\n\t"
+ "movel %1@+,%3 | 8: Fetch 32-bit word\n\t"
+ "addxl %3,%0 | Add word + previous carry\n\t"
+ "movel %1@+,%3 | 9: Fetch 32-bit word\n\t"
+ "addxl %3,%0 | Add word + previous carry\n\t"
+ "movel %1@+,%3 | A: Fetch 32-bit word\n\t"
+ "addxl %3,%0 | Add word + previous carry\n\t"
+ "movel %1@+,%3 | B: Fetch 32-bit word\n\t"
+ "addxl %3,%0 | Add word + previous carry\n\t"
+ "movel %1@+,%3 | C: Fetch 32-bit word\n\t"
+ "addxl %3,%0 | Add word + previous carry\n\t"
+ "movel %1@+,%3 | D: Fetch 32-bit word\n\t"
+ "addxl %3,%0 | Add word + previous carry\n\t"
+ "movel %1@+,%3 | E: Fetch 32-bit word\n\t"
+ "addxl %3,%0 | Add word + previous carry\n\t"
+ "movel %1@+,%3 | F: Fetch 32-bit word\n\t"
+ "addxl %3,%0 | Add word + previous carry\n"
+ "lcsum2_lbl: | End of unrolled loop\n\t"
+#if IS_COLDFIRE
+ "moveq #0,%3 | Add in last carry\n\t"
+ "addxl %3,%0 |\n\t"
+ "subql #1,%2 | Update loop count\n\t"
+ "bplb lcsum1_lbl | Loop (with X clear) if not done\n\t"
+ "movel #0xffff,%2 | Get word mask\n\t"
+ "movel %0,%3 | Fold 32 bit sum to 16 bits\n\t"
+ "swap %3 |\n\t"
+ "andl %2,%0 | Mask to 16-bit sum\n\t"
+ "andl %2,%3 | Mask to 16-bit sum\n\t"
+ "addl %3,%0 |\n\t"
+ "movel %0,%3 | Add in last carry\n\t"
+ "swap %3 |\n\t"
+ "addl %3,%0 |\n\t"
+ "andl %2,%0 | Mask to 16-bit sum\n\t"
+#else
+ "dbf %2,lcsum1_lbl | (NB- dbf doesn't affect X)\n\t"
+ "movel %0,%3 | Fold 32 bit sum to 16 bits\n\t"
+ "swap %3 | (NB- swap doesn't affect X)\n\t"
+ "addxw %3,%0 |\n\t"
+ "moveq #0,%3 | Add in last carry\n\t"
+ "addxw %3,%0 |\n\t"
+ "andl #0xffff,%0 | Mask to 16-bit sum\n"
+#endif
+ :
+ "=d" (sum), "=a" (w), "=d" (tcnt) , "=d" (t1) :
+ "0" (sum), "1" (w), "2" (tcnt) :
+ "cc", "memory");
+ }
+ mlen &= 3;
+
+ /*
+ * Soak up the last 1, 2 or 3 bytes
+ */
+ while ((mlen -= 2) >= 0)
+ sum += *w++;
+ if (byte_swapped) {
+ REDUCE;
+ sum <<= 8;
+ byte_swapped = 0;
+ if (mlen == -1) {
+ s_util.c[1] = *(char *)w;
+ sum += s_util.s;
+ mlen = 0;
+ } else
+ mlen = -1;
+ } else if (mlen == -1)
+ s_util.c[0] = *(char *)w;
+ }
+ if (len)
+ sum = 0xDEAD;
+ if (mlen == -1) {
+ /* The last mbuf has odd # of bytes. Follow the
+ standard (the odd byte may be shifted left by 8 bits
+ or not as determined by endian-ness of the machine) */
+ s_util.c[1] = 0;
+ sum += s_util.s;
+ }
+ REDUCE;
+ return (~sum & 0xffff);
+}
diff --git a/cpukit/libnetworking/netinet/in_cksum_powerpc.h b/cpukit/libnetworking/netinet/in_cksum_powerpc.h
new file mode 100644
index 0000000000..fe2f04e246
--- /dev/null
+++ b/cpukit/libnetworking/netinet/in_cksum_powerpc.h
@@ -0,0 +1,173 @@
+/*
+ * Checksum routine for Internet Protocol family headers.
+ *
+ * This routine is very heavily used in the network
+ * code and should be modified for each CPU to be as fast as possible.
+ *
+ * This implementation is the PowerPC version.
+ *
+ * $Id$
+ */
+
+#include <stdio.h> /* for puts */
+
+#undef ADDCARRY
+#define ADDCARRY(x) if ((x) > 0xffff) (x) -= 0xffff
+#define REDUCE {sum = (sum & 0xffff) + (sum >> 16); ADDCARRY(sum);}
+
+/*
+ * Thanks to gcc we don't have to guess
+ * which registers contain sum & w.
+ */
+
+#define LDTMP(n) tmp = *((u_int *)((u_char *)w + n))
+
+#define ADD(n) \
+ LDTMP(n); \
+ __asm__ volatile("addc %0,%0,%2" : "=r" (sum) : "0" (sum), "r" (tmp))
+
+#define ADDC(n) \
+ LDTMP(n); \
+ __asm__ volatile("adde %0,%0,%2" : "=r" (sum) : "0" (sum), "r" (tmp))
+
+#define MOP \
+ tmp = 0; \
+ __asm__ volatile("adde %0,%0,%2" : "=r" (sum) : "0" (sum), "r" (tmp))
+
+#define LOAD(n) junk = (u_char) *((volatile u_char *) w + n)
+
+
+int
+in_cksum(m, len)
+ register struct mbuf *m;
+ register int len;
+{
+ u_char junk;
+ register u_short *w;
+ register unsigned sum = 0;
+ register unsigned tmp;
+ register int mlen = 0;
+ int byte_swapped = 0;
+ union { char c[2]; u_short s; } su;
+
+ for (;m && len; m = m->m_next) {
+ if (m->m_len == 0)
+ continue;
+ w = mtod(m, u_short *);
+ if (mlen == -1) {
+ /*
+ * The first byte of this mbuf is the continuation
+ * of a word spanning between this mbuf and the
+ * last mbuf.
+ */
+
+ /* su.c[0] is already saved when scanning previous
+ * mbuf. sum was REDUCEd when we found mlen == -1
+ */
+ su.c[1] = *(u_char *)w;
+ sum += su.s;
+ w = (u_short *)((char *)w + 1);
+ mlen = m->m_len - 1;
+ len--;
+ } else
+ mlen = m->m_len;
+ if (len < mlen)
+ mlen = len;
+ len -= mlen;
+ /*
+ * Force to long boundary so we do longword aligned
+ * memory operations
+ */
+ if (3 & (int) w) {
+ REDUCE;
+ if ((1 & (int) w) && (mlen > 0)) {
+ sum <<= 8;
+ su.c[0] = *(char *)w;
+ w = (u_short *)((char *)w + 1);
+ mlen--;
+ byte_swapped = 1;
+ }
+ if ((2 & (int) w) && (mlen >= 2)) {
+ sum += *w++;
+ mlen -= 2;
+ }
+ }
+
+ /*
+ * Do as much of the checksum as possible 32 bits at at time.
+ * In fact, this loop is unrolled to keep overhead from
+ * branches small.
+ */
+ while (mlen >= 32) {
+ /*
+ * Add with carry 16 words and fold in the last
+ * carry by adding a 0 with carry.
+ *
+ * The early ADD(16) and the LOAD(32) are intended
+ * to help get the data into the cache.
+ */
+ ADD(16);
+ ADDC(0);
+ ADDC(4);
+ ADDC(8);
+ ADDC(12);
+ LOAD(32);
+ ADDC(20);
+ ADDC(24);
+ ADDC(28);
+ MOP;
+ w += 16;
+ mlen -= 32;
+ }
+ if (mlen >= 16) {
+ ADD(0);
+ ADDC(4);
+ ADDC(8);
+ ADDC(12);
+ MOP;
+ w += 8;
+ mlen -= 16;
+ }
+ if (mlen >= 8) {
+ ADD(0);
+ ADDC(4);
+ MOP;
+ w += 4;
+ mlen -= 8;
+ }
+ if (mlen == 0 && byte_swapped == 0)
+ continue; /* worth 1% maybe ?? */
+ REDUCE;
+ while ((mlen -= 2) >= 0) {
+ sum += *w++;
+ }
+ if (byte_swapped) {
+ sum <<= 8;
+ byte_swapped = 0;
+ if (mlen == -1) {
+ su.c[1] = *(char *)w;
+ sum += su.s;
+ mlen = 0;
+ } else
+ mlen = -1;
+ } else if (mlen == -1)
+ /*
+ * This mbuf has odd number of bytes.
+ * There could be a word split betwen
+ * this mbuf and the next mbuf.
+ * Save the last byte (to prepend to next mbuf).
+ */
+ su.c[0] = *(char *)w;
+ }
+
+ if (len)
+ puts("cksum: out of data");
+ if (mlen == -1) {
+ /* The last mbuf has odd # of bytes. Follow the
+ standard (the odd byte is shifted left by 8 bits) */
+ su.c[1] = 0;
+ sum += su.s;
+ }
+ REDUCE;
+ return (~sum & 0xffff);
+}
diff --git a/cpukit/libnetworking/netinet/in_pcb.c b/cpukit/libnetworking/netinet/in_pcb.c
new file mode 100644
index 0000000000..312594dae2
--- /dev/null
+++ b/cpukit/libnetworking/netinet/in_pcb.c
@@ -0,0 +1,760 @@
+/*
+ * Copyright (c) 1982, 1986, 1991, 1993, 1995
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)in_pcb.c 8.4 (Berkeley) 5/24/95
+ * $Id$
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/ioctl.h>
+#include <sys/errno.h>
+#include <sys/time.h>
+#include <sys/proc.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/route.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/in_pcb.h>
+#include <netinet/in_var.h>
+#include <netinet/ip_var.h>
+
+struct in_addr zeroin_addr;
+
+static void in_pcbinshash __P((struct inpcb *));
+static void in_rtchange __P((struct inpcb *, int));
+
+/*
+ * These configure the range of local port addresses assigned to
+ * "unspecified" outgoing connections/packets/whatever.
+ */
+static int ipport_lowfirstauto = IPPORT_RESERVED - 1; /* 1023 */
+static int ipport_lowlastauto = IPPORT_RESERVEDSTART; /* 600 */
+static int ipport_firstauto = IPPORT_RESERVED; /* 1024 */
+static int ipport_lastauto = IPPORT_USERRESERVED; /* 5000 */
+static int ipport_hifirstauto = IPPORT_HIFIRSTAUTO; /* 40000 */
+static int ipport_hilastauto = IPPORT_HILASTAUTO; /* 44999 */
+
+#define RANGECHK(var, min, max) \
+ if ((var) < (min)) { (var) = (min); } \
+ else if ((var) > (max)) { (var) = (max); }
+
+static int
+sysctl_net_ipport_check(SYSCTL_HANDLER_ARGS)
+{
+ int error = sysctl_handle_int(oidp,
+ oidp->oid_arg1, oidp->oid_arg2, req);
+ if (!error) {
+ RANGECHK(ipport_lowfirstauto, 1, IPPORT_RESERVED - 1);
+ RANGECHK(ipport_lowlastauto, 1, IPPORT_RESERVED - 1);
+ RANGECHK(ipport_firstauto, IPPORT_RESERVED, USHRT_MAX);
+ RANGECHK(ipport_lastauto, IPPORT_RESERVED, USHRT_MAX);
+ RANGECHK(ipport_hifirstauto, IPPORT_RESERVED, USHRT_MAX);
+ RANGECHK(ipport_hilastauto, IPPORT_RESERVED, USHRT_MAX);
+ }
+ return error;
+}
+
+#undef RANGECHK
+
+SYSCTL_NODE(_net_inet_ip, IPPROTO_IP, portrange, CTLFLAG_RW, 0, "IP Ports");
+
+SYSCTL_PROC(_net_inet_ip_portrange, OID_AUTO, lowfirst, CTLTYPE_INT|CTLFLAG_RW,
+ &ipport_lowfirstauto, 0, &sysctl_net_ipport_check, "I", "");
+SYSCTL_PROC(_net_inet_ip_portrange, OID_AUTO, lowlast, CTLTYPE_INT|CTLFLAG_RW,
+ &ipport_lowlastauto, 0, &sysctl_net_ipport_check, "I", "");
+SYSCTL_PROC(_net_inet_ip_portrange, OID_AUTO, first, CTLTYPE_INT|CTLFLAG_RW,
+ &ipport_firstauto, 0, &sysctl_net_ipport_check, "I", "");
+SYSCTL_PROC(_net_inet_ip_portrange, OID_AUTO, last, CTLTYPE_INT|CTLFLAG_RW,
+ &ipport_lastauto, 0, &sysctl_net_ipport_check, "I", "");
+SYSCTL_PROC(_net_inet_ip_portrange, OID_AUTO, hifirst, CTLTYPE_INT|CTLFLAG_RW,
+ &ipport_hifirstauto, 0, &sysctl_net_ipport_check, "I", "");
+SYSCTL_PROC(_net_inet_ip_portrange, OID_AUTO, hilast, CTLTYPE_INT|CTLFLAG_RW,
+ &ipport_hilastauto, 0, &sysctl_net_ipport_check, "I", "");
+
+int
+in_pcballoc(so, pcbinfo)
+ struct socket *so;
+ struct inpcbinfo *pcbinfo;
+{
+ register struct inpcb *inp;
+ int s;
+
+ MALLOC(inp, struct inpcb *, sizeof(*inp), M_PCB, M_NOWAIT);
+ if (inp == NULL)
+ return (ENOBUFS);
+ bzero((caddr_t)inp, sizeof(*inp));
+ inp->inp_gencnt = ++pcbinfo->ipi_gencnt;
+ inp->inp_pcbinfo = pcbinfo;
+ inp->inp_socket = so;
+ s = splnet();
+ LIST_INSERT_HEAD(pcbinfo->listhead, inp, inp_list);
+ pcbinfo->ipi_count++;
+ in_pcbinshash(inp);
+ splx(s);
+ so->so_pcb = (caddr_t)inp;
+ return (0);
+}
+
+int
+in_pcbbind(inp, nam)
+ register struct inpcb *inp;
+ struct mbuf *nam;
+{
+ register struct socket *so = inp->inp_socket;
+ unsigned short *lastport;
+ struct sockaddr_in *sin;
+ u_short lport = 0;
+ int wild = 0, reuseport = (so->so_options & SO_REUSEPORT);
+ int error;
+
+ if (in_ifaddr == 0)
+ return (EADDRNOTAVAIL);
+ if (inp->inp_lport || inp->inp_laddr.s_addr != INADDR_ANY)
+ return (EINVAL);
+ if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0 &&
+ ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 ||
+ (so->so_options & SO_ACCEPTCONN) == 0))
+ wild = 1;
+ if (nam) {
+ sin = mtod(nam, struct sockaddr_in *);
+ if (nam->m_len != sizeof (*sin))
+ return (EINVAL);
+#ifdef notdef
+ /*
+ * We should check the family, but old programs
+ * incorrectly fail to initialize it.
+ */
+ if (sin->sin_family != AF_INET)
+ return (EAFNOSUPPORT);
+#endif
+ lport = sin->sin_port;
+ if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
+ /*
+ * Treat SO_REUSEADDR as SO_REUSEPORT for multicast;
+ * allow complete duplication of binding if
+ * SO_REUSEPORT is set, or if SO_REUSEADDR is set
+ * and a multicast address is bound on both
+ * new and duplicated sockets.
+ */
+ if (so->so_options & SO_REUSEADDR)
+ reuseport = SO_REUSEADDR|SO_REUSEPORT;
+ } else if (sin->sin_addr.s_addr != INADDR_ANY) {
+ sin->sin_port = 0; /* yech... */
+ if (ifa_ifwithaddr((struct sockaddr *)sin) == 0)
+ return (EADDRNOTAVAIL);
+ }
+ if (lport) {
+ struct inpcb *t;
+
+ /* GROSS */
+ if (ntohs(lport) < IPPORT_RESERVED &&
+ (error = suser(p->p_ucred, &p->p_acflag)))
+ return (EACCES);
+ if (so->so_uid) {
+ t = in_pcblookup(inp->inp_pcbinfo, zeroin_addr,
+ 0, sin->sin_addr, lport,
+ INPLOOKUP_WILDCARD);
+ if (t && (so->so_uid != t->inp_socket->so_uid))
+ return (EADDRINUSE);
+ }
+ t = in_pcblookup(inp->inp_pcbinfo, zeroin_addr, 0,
+ sin->sin_addr, lport, wild);
+ if (t && (reuseport & t->inp_socket->so_options) == 0)
+ return (EADDRINUSE);
+ }
+ inp->inp_laddr = sin->sin_addr;
+ }
+ if (lport == 0) {
+ ushort first, last;
+ int count;
+
+ inp->inp_flags |= INP_ANONPORT;
+
+ if (inp->inp_flags & INP_HIGHPORT) {
+ first = ipport_hifirstauto; /* sysctl */
+ last = ipport_hilastauto;
+ lastport = &inp->inp_pcbinfo->lasthi;
+ } else if (inp->inp_flags & INP_LOWPORT) {
+ if ((error = suser(p->p_ucred, &p->p_acflag)))
+ return (EACCES);
+ first = ipport_lowfirstauto; /* 1023 */
+ last = ipport_lowlastauto; /* 600 */
+ lastport = &inp->inp_pcbinfo->lastlow;
+ } else {
+ first = ipport_firstauto; /* sysctl */
+ last = ipport_lastauto;
+ lastport = &inp->inp_pcbinfo->lastport;
+ }
+ /*
+ * Simple check to ensure all ports are not used up causing
+ * a deadlock here.
+ *
+ * We split the two cases (up and down) so that the direction
+ * is not being tested on each round of the loop.
+ */
+ if (first > last) {
+ /*
+ * counting down
+ */
+ count = first - last;
+
+ do {
+ if (count-- <= 0) /* completely used? */
+ return (EADDRNOTAVAIL);
+ --*lastport;
+ if (*lastport > first || *lastport < last)
+ *lastport = first;
+ lport = htons(*lastport);
+ } while (in_pcblookup(inp->inp_pcbinfo,
+ zeroin_addr, 0, inp->inp_laddr, lport, wild));
+ } else {
+ /*
+ * counting up
+ */
+ count = last - first;
+
+ do {
+ if (count-- <= 0) /* completely used? */
+ return (EADDRNOTAVAIL);
+ ++*lastport;
+ if (*lastport < first || *lastport > last)
+ *lastport = first;
+ lport = htons(*lastport);
+ } while (in_pcblookup(inp->inp_pcbinfo,
+ zeroin_addr, 0, inp->inp_laddr, lport, wild));
+ }
+ }
+ inp->inp_lport = lport;
+ in_pcbrehash(inp);
+ return (0);
+}
+
+/*
+ * Transform old in_pcbconnect() into an inner subroutine for new
+ * in_pcbconnect(): Do some validity-checking on the remote
+ * address (in mbuf 'nam') and then determine local host address
+ * (i.e., which interface) to use to access that remote host.
+ *
+ * This preserves definition of in_pcbconnect(), while supporting a
+ * slightly different version for T/TCP. (This is more than
+ * a bit of a kludge, but cleaning up the internal interfaces would
+ * have forced minor changes in every protocol).
+ */
+
+int
+in_pcbladdr(inp, nam, plocal_sin)
+ register struct inpcb *inp;
+ struct mbuf *nam;
+ struct sockaddr_in **plocal_sin;
+{
+ struct in_ifaddr *ia;
+ register struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
+
+ if (nam->m_len != sizeof (*sin))
+ return (EINVAL);
+ if (sin->sin_family != AF_INET)
+ return (EAFNOSUPPORT);
+ if (sin->sin_port == 0)
+ return (EADDRNOTAVAIL);
+ if (in_ifaddr) {
+ /*
+ * If the destination address is INADDR_ANY,
+ * use the primary local address.
+ * If the supplied address is INADDR_BROADCAST,
+ * and the primary interface supports broadcast,
+ * choose the broadcast address for that interface.
+ */
+#define satosin(sa) ((struct sockaddr_in *)(sa))
+#define sintosa(sin) ((struct sockaddr *)(sin))
+#define ifatoia(ifa) ((struct in_ifaddr *)(ifa))
+ if (sin->sin_addr.s_addr == INADDR_ANY)
+ sin->sin_addr = IA_SIN(in_ifaddr)->sin_addr;
+ else if (sin->sin_addr.s_addr == (u_long)INADDR_BROADCAST &&
+ (in_ifaddr->ia_ifp->if_flags & IFF_BROADCAST))
+ sin->sin_addr = satosin(&in_ifaddr->ia_broadaddr)->sin_addr;
+ }
+ if (inp->inp_laddr.s_addr == INADDR_ANY) {
+ register struct route *ro;
+
+ ia = (struct in_ifaddr *)0;
+ /*
+ * If route is known or can be allocated now,
+ * our src addr is taken from the i/f, else punt.
+ */
+ ro = &inp->inp_route;
+ if (ro->ro_rt &&
+ (satosin(&ro->ro_dst)->sin_addr.s_addr !=
+ sin->sin_addr.s_addr ||
+ inp->inp_socket->so_options & SO_DONTROUTE)) {
+ RTFREE(ro->ro_rt);
+ ro->ro_rt = (struct rtentry *)0;
+ }
+ if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/
+ (ro->ro_rt == (struct rtentry *)0 ||
+ ro->ro_rt->rt_ifp == (struct ifnet *)0)) {
+ /* No route yet, so try to acquire one */
+ ro->ro_dst.sa_family = AF_INET;
+ ro->ro_dst.sa_len = sizeof(struct sockaddr_in);
+ ((struct sockaddr_in *) &ro->ro_dst)->sin_addr =
+ sin->sin_addr;
+ rtalloc(ro);
+ }
+ /*
+ * If we found a route, use the address
+ * corresponding to the outgoing interface
+ * unless it is the loopback (in case a route
+ * to our address on another net goes to loopback).
+ */
+ if (ro->ro_rt && !(ro->ro_rt->rt_ifp->if_flags & IFF_LOOPBACK))
+ ia = ifatoia(ro->ro_rt->rt_ifa);
+ if (ia == 0) {
+ u_short fport = sin->sin_port;
+
+ sin->sin_port = 0;
+ ia = ifatoia(ifa_ifwithdstaddr(sintosa(sin)));
+ if (ia == 0)
+ ia = ifatoia(ifa_ifwithnet(sintosa(sin)));
+ sin->sin_port = fport;
+ if (ia == 0)
+ ia = in_ifaddr;
+ if (ia == 0)
+ return (EADDRNOTAVAIL);
+ }
+ /*
+ * If the destination address is multicast and an outgoing
+ * interface has been set as a multicast option, use the
+ * address of that interface as our source address.
+ */
+ if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)) &&
+ inp->inp_moptions != NULL) {
+ struct ip_moptions *imo;
+ struct ifnet *ifp;
+
+ imo = inp->inp_moptions;
+ if (imo->imo_multicast_ifp != NULL) {
+ ifp = imo->imo_multicast_ifp;
+ for (ia = in_ifaddr; ia; ia = ia->ia_next)
+ if (ia->ia_ifp == ifp)
+ break;
+ if (ia == 0)
+ return (EADDRNOTAVAIL);
+ }
+ }
+ /*
+ * Don't do pcblookup call here; return interface in plocal_sin
+ * and exit to caller, that will do the lookup.
+ */
+ *plocal_sin = &ia->ia_addr;
+
+ }
+ return(0);
+}
+
+/*
+ * Outer subroutine:
+ * Connect from a socket to a specified address.
+ * Both address and port must be specified in argument sin.
+ * If don't have a local address for this socket yet,
+ * then pick one.
+ */
+int
+in_pcbconnect(inp, nam)
+ register struct inpcb *inp;
+ struct mbuf *nam;
+{
+ struct sockaddr_in *ifaddr;
+ register struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
+ int error;
+
+ /*
+ * Call inner routine, to assign local interface address.
+ */
+ if ((error = in_pcbladdr(inp, nam, &ifaddr)))
+ return(error);
+
+ if (in_pcblookuphash(inp->inp_pcbinfo, sin->sin_addr, sin->sin_port,
+ inp->inp_laddr.s_addr ? inp->inp_laddr : ifaddr->sin_addr,
+ inp->inp_lport, 0) != NULL)
+ return (EADDRINUSE);
+ if (inp->inp_laddr.s_addr == INADDR_ANY) {
+ if (inp->inp_lport == 0)
+ (void)in_pcbbind(inp, (struct mbuf *)0);
+ inp->inp_laddr = ifaddr->sin_addr;
+ }
+ inp->inp_faddr = sin->sin_addr;
+ inp->inp_fport = sin->sin_port;
+ in_pcbrehash(inp);
+ return (0);
+}
+
+void
+in_pcbdisconnect(inp)
+ struct inpcb *inp;
+{
+
+ inp->inp_faddr.s_addr = INADDR_ANY;
+ inp->inp_fport = 0;
+ in_pcbrehash(inp);
+ if (inp->inp_socket->so_state & SS_NOFDREF)
+ in_pcbdetach(inp);
+}
+
+void
+in_pcbdetach(inp)
+ struct inpcb *inp;
+{
+ struct socket *so = inp->inp_socket;
+ struct inpcbinfo *ipi = inp->inp_pcbinfo;
+ int s;
+
+ inp->inp_gencnt = ++ipi->ipi_gencnt;
+ so->so_pcb = 0;
+ sofree(so);
+ if (inp->inp_options)
+ (void)m_free(inp->inp_options);
+ if (inp->inp_route.ro_rt)
+ rtfree(inp->inp_route.ro_rt);
+ ip_freemoptions(inp->inp_moptions);
+ s = splnet();
+ LIST_REMOVE(inp, inp_hash);
+ LIST_REMOVE(inp, inp_list);
+ splx(s);
+ FREE(inp, M_PCB);
+}
+
+void
+in_setsockaddr(inp, nam)
+ register struct inpcb *inp;
+ struct mbuf *nam;
+{
+ register struct sockaddr_in *sin;
+
+ nam->m_len = sizeof (*sin);
+ sin = mtod(nam, struct sockaddr_in *);
+ bzero((caddr_t)sin, sizeof (*sin));
+ sin->sin_family = AF_INET;
+ sin->sin_len = sizeof(*sin);
+ sin->sin_port = inp->inp_lport;
+ sin->sin_addr = inp->inp_laddr;
+}
+
+void
+in_setpeeraddr(inp, nam)
+ struct inpcb *inp;
+ struct mbuf *nam;
+{
+ register struct sockaddr_in *sin;
+
+ nam->m_len = sizeof (*sin);
+ sin = mtod(nam, struct sockaddr_in *);
+ bzero((caddr_t)sin, sizeof (*sin));
+ sin->sin_family = AF_INET;
+ sin->sin_len = sizeof(*sin);
+ sin->sin_port = inp->inp_fport;
+ sin->sin_addr = inp->inp_faddr;
+}
+
+/*
+ * Pass some notification to all connections of a protocol
+ * associated with address dst. The local address and/or port numbers
+ * may be specified to limit the search. The "usual action" will be
+ * taken, depending on the ctlinput cmd. The caller must filter any
+ * cmds that are uninteresting (e.g., no error in the map).
+ * Call the protocol specific routine (if any) to report
+ * any errors for each matching socket.
+ *
+ * Must be called at splnet.
+ */
+void
+in_pcbnotify(head, dst, fport_arg, laddr, lport_arg, cmd, notify)
+ struct inpcbhead *head;
+ struct sockaddr *dst;
+ u_int fport_arg, lport_arg;
+ struct in_addr laddr;
+ int cmd;
+ void (*notify) __P((struct inpcb *, int));
+{
+ register struct inpcb *inp, *oinp;
+ struct in_addr faddr;
+ u_short fport = fport_arg, lport = lport_arg;
+ int errnum, s;
+
+ if ((unsigned)cmd > PRC_NCMDS || dst->sa_family != AF_INET)
+ return;
+ faddr = ((struct sockaddr_in *)dst)->sin_addr;
+ if (faddr.s_addr == INADDR_ANY)
+ return;
+
+ /*
+ * Redirects go to all references to the destination,
+ * and use in_rtchange to invalidate the route cache.
+ * Dead host indications: notify all references to the destination.
+ * Otherwise, if we have knowledge of the local port and address,
+ * deliver only to that socket.
+ */
+ if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) {
+ fport = 0;
+ lport = 0;
+ laddr.s_addr = 0;
+ if (cmd != PRC_HOSTDEAD)
+ notify = in_rtchange;
+ }
+ errnum = inetctlerrmap[cmd];
+ s = splnet();
+ for (inp = head->lh_first; inp != NULL;) {
+ if (inp->inp_faddr.s_addr != faddr.s_addr ||
+ inp->inp_socket == 0 ||
+ (lport && inp->inp_lport != lport) ||
+ (laddr.s_addr && inp->inp_laddr.s_addr != laddr.s_addr) ||
+ (fport && inp->inp_fport != fport)) {
+ inp = inp->inp_list.le_next;
+ continue;
+ }
+ oinp = inp;
+ inp = inp->inp_list.le_next;
+ if (notify)
+ (*notify)(oinp, errnum);
+ }
+ splx(s);
+}
+
+/*
+ * Check for alternatives when higher level complains
+ * about service problems. For now, invalidate cached
+ * routing information. If the route was created dynamically
+ * (by a redirect), time to try a default gateway again.
+ */
+void
+in_losing(inp)
+ struct inpcb *inp;
+{
+ register struct rtentry *rt;
+ struct rt_addrinfo info;
+
+ if ((rt = inp->inp_route.ro_rt)) {
+ inp->inp_route.ro_rt = 0;
+ bzero((caddr_t)&info, sizeof(info));
+ info.rti_info[RTAX_DST] =
+ (struct sockaddr *)&inp->inp_route.ro_dst;
+ info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
+ info.rti_info[RTAX_NETMASK] = rt_mask(rt);
+ rt_missmsg(RTM_LOSING, &info, rt->rt_flags, 0);
+ if (rt->rt_flags & RTF_DYNAMIC)
+ (void) rtrequest(RTM_DELETE, rt_key(rt),
+ rt->rt_gateway, rt_mask(rt), rt->rt_flags,
+ (struct rtentry **)0);
+ else
+ /*
+ * A new route can be allocated
+ * the next time output is attempted.
+ */
+ rtfree(rt);
+ }
+}
+
+/*
+ * After a routing change, flush old routing
+ * and allocate a (hopefully) better one.
+ */
+static void
+in_rtchange(inp, errnum)
+ register struct inpcb *inp;
+ int errnum;
+{
+ if (inp->inp_route.ro_rt) {
+ rtfree(inp->inp_route.ro_rt);
+ inp->inp_route.ro_rt = 0;
+ /*
+ * A new route can be allocated the next time
+ * output is attempted.
+ */
+ }
+}
+
+struct inpcb *
+in_pcblookup(pcbinfo, faddr, fport_arg, laddr, lport_arg, wild_okay)
+ struct inpcbinfo *pcbinfo;
+ struct in_addr faddr, laddr;
+ u_int fport_arg, lport_arg;
+ int wild_okay;
+{
+ register struct inpcb *inp, *match = NULL;
+ int matchwild = 3, wildcard;
+ u_short fport = fport_arg, lport = lport_arg;
+ int s;
+
+ s = splnet();
+
+ for (inp = pcbinfo->listhead->lh_first; inp != NULL; inp = inp->inp_list.le_next) {
+ if (inp->inp_lport != lport)
+ continue;
+ wildcard = 0;
+ if (inp->inp_faddr.s_addr != INADDR_ANY) {
+ if (faddr.s_addr == INADDR_ANY)
+ wildcard++;
+ else if (inp->inp_faddr.s_addr != faddr.s_addr ||
+ inp->inp_fport != fport)
+ continue;
+ } else {
+ if (faddr.s_addr != INADDR_ANY)
+ wildcard++;
+ }
+ if (inp->inp_laddr.s_addr != INADDR_ANY) {
+ if (laddr.s_addr == INADDR_ANY)
+ wildcard++;
+ else if (inp->inp_laddr.s_addr != laddr.s_addr)
+ continue;
+ } else {
+ if (laddr.s_addr != INADDR_ANY)
+ wildcard++;
+ }
+ if (wildcard && wild_okay == 0)
+ continue;
+ if (wildcard < matchwild) {
+ match = inp;
+ matchwild = wildcard;
+ if (matchwild == 0) {
+ break;
+ }
+ }
+ }
+ splx(s);
+ return (match);
+}
+
+/*
+ * Lookup PCB in hash list.
+ */
+struct inpcb *
+in_pcblookuphash(pcbinfo, faddr, fport_arg, laddr, lport_arg, wildcard)
+ struct inpcbinfo *pcbinfo;
+ struct in_addr faddr, laddr;
+ u_int fport_arg, lport_arg;
+ int wildcard;
+{
+ struct inpcbhead *head;
+ register struct inpcb *inp;
+ u_short fport = fport_arg, lport = lport_arg;
+ int s;
+
+ s = splnet();
+ /*
+ * First look for an exact match.
+ */
+ head = &pcbinfo->hashbase[INP_PCBHASH(faddr.s_addr, lport, fport, pcbinfo->hashmask)];
+ for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) {
+ if (inp->inp_faddr.s_addr == faddr.s_addr &&
+ inp->inp_laddr.s_addr == laddr.s_addr &&
+ inp->inp_fport == fport &&
+ inp->inp_lport == lport)
+ goto found;
+ }
+ if (wildcard) {
+ struct inpcb *local_wild = NULL;
+
+ head = &pcbinfo->hashbase[INP_PCBHASH(INADDR_ANY, lport, 0, pcbinfo->hashmask)];
+ for (inp = head->lh_first; inp != NULL; inp = inp->inp_hash.le_next) {
+ if (inp->inp_faddr.s_addr == INADDR_ANY &&
+ inp->inp_fport == 0 && inp->inp_lport == lport) {
+ if (inp->inp_laddr.s_addr == laddr.s_addr)
+ goto found;
+ else if (inp->inp_laddr.s_addr == INADDR_ANY)
+ local_wild = inp;
+ }
+ }
+ if (local_wild != NULL) {
+ inp = local_wild;
+ goto found;
+ }
+ }
+ splx(s);
+ return (NULL);
+
+found:
+ /*
+ * Move PCB to head of this hash chain so that it can be
+ * found more quickly in the future.
+ * XXX - this is a pessimization on machines with few
+ * concurrent connections.
+ */
+ if (inp != head->lh_first) {
+ LIST_REMOVE(inp, inp_hash);
+ LIST_INSERT_HEAD(head, inp, inp_hash);
+ }
+ splx(s);
+ return (inp);
+}
+
+/*
+ * Insert PCB into hash chain. Must be called at splnet.
+ */
+static void
+in_pcbinshash(inp)
+ struct inpcb *inp;
+{
+ struct inpcbhead *head;
+
+ head = &inp->inp_pcbinfo->hashbase[INP_PCBHASH(inp->inp_faddr.s_addr,
+ inp->inp_lport, inp->inp_fport, inp->inp_pcbinfo->hashmask)];
+
+ LIST_INSERT_HEAD(head, inp, inp_hash);
+}
+
+void
+in_pcbrehash(inp)
+ struct inpcb *inp;
+{
+ struct inpcbhead *head;
+ int s;
+
+ s = splnet();
+ LIST_REMOVE(inp, inp_hash);
+
+ head = &inp->inp_pcbinfo->hashbase[INP_PCBHASH(inp->inp_faddr.s_addr,
+ inp->inp_lport, inp->inp_fport, inp->inp_pcbinfo->hashmask)];
+
+ LIST_INSERT_HEAD(head, inp, inp_hash);
+ inp->inp_pcbinfo->ipi_count--;
+ splx(s);
+}
diff --git a/cpukit/libnetworking/netinet/in_pcb.h b/cpukit/libnetworking/netinet/in_pcb.h
new file mode 100644
index 0000000000..49a9c004bd
--- /dev/null
+++ b/cpukit/libnetworking/netinet/in_pcb.h
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 1982, 1986, 1990, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)in_pcb.h 8.1 (Berkeley) 6/10/93
+ * $Id$
+ */
+
+#ifndef _NETINET_IN_PCB_H_
+#define _NETINET_IN_PCB_H_
+
+#include <sys/queue.h>
+
+/*
+ * Common structure pcb for internet protocol implementation.
+ * Here are stored pointers to local and foreign host table
+ * entries, local and foreign socket numbers, and pointers
+ * up (to a socket structure) and down (to a protocol-specific)
+ * control block.
+ */
+LIST_HEAD(inpcbhead, inpcb);
+
+typedef u_int64_t inp_gen_t;
+
+struct inpcb {
+ LIST_ENTRY(inpcb) inp_list; /* list for all PCBs of this proto */
+ LIST_ENTRY(inpcb) inp_hash; /* hash list */
+ struct inpcbinfo *inp_pcbinfo; /* PCB list info */
+ struct in_addr inp_faddr; /* foreign host table entry */
+ struct in_addr inp_laddr; /* local host table entry */
+ u_short inp_fport; /* foreign port */
+ u_short inp_lport; /* local port */
+ caddr_t inp_ppcb; /* pointer to per-protocol pcb */
+ struct socket *inp_socket; /* back pointer to socket */
+ struct mbuf *inp_options; /* IP options */
+ struct route inp_route; /* placeholder for routing entry */
+ int inp_flags; /* generic IP/datagram flags */
+ u_char inp_ip_tos; /* type of service proto */
+ u_char inp_ip_ttl; /* time to live proto */
+ u_char inp_ip_p; /* protocol proto */
+ u_char pad[1]; /* alignment */
+ struct ip_moptions *inp_moptions; /* IP multicast options */
+ inp_gen_t inp_gencnt; /* generation count of this instance */
+#if 0 /* Someday, perhaps... */
+ struct ip inp_ip; /* header prototype; should have more */
+#endif
+};
+
+/*
+ * Interface exported to userland by various protocols which use
+ * inpcbs. Hack alert -- only define if struct xsocket is in scope.
+ *
+ * ccj - 20 Nov 2002
+ * Double hack alert. This is taken from the pre 5.0 sources and
+ * merged into RTEMS. This allows the TCPCTL_PCBLIST code in
+ * net-snmp to work.
+ */
+#ifdef _SYS_SOCKETVAR_H_
+typedef u_int64_t so_gen_t; /* should be in sys/sockvar.h */
+
+struct xinpcb {
+ size_t xi_len; /* length of this structure */
+ struct inpcb xi_inp;
+/* struct xsocket xi_socket; ccj removed */
+ u_int64_t xi_alignment_hack;
+};
+
+
+struct xinpgen {
+ size_t xig_len; /* length of this structure */
+ u_int xig_count; /* number of PCBs at this time */
+ inp_gen_t xig_gen; /* generation count at this time */
+ so_gen_t xig_sogen; /* socket generation count at this time */
+};
+#endif /* _SYS_SOCKETVAR_H_ */
+
+struct inpcbinfo {
+ struct inpcbhead *listhead;
+ struct inpcbhead *hashbase;
+ unsigned long hashmask;
+ unsigned short lastport;
+ unsigned short lastlow;
+ unsigned short lasthi;
+ u_int ipi_count; /* number of pcbs in this list */
+ u_int64_t ipi_gencnt; /* current generation count */
+};
+
+#define INP_PCBHASH(faddr, lport, fport, mask) \
+ (((faddr) ^ ((faddr) >> 16) ^ (lport) ^ (fport)) & (mask))
+
+/* flags in inp_flags: */
+#define INP_RECVOPTS 0x01 /* receive incoming IP options */
+#define INP_RECVRETOPTS 0x02 /* receive IP options for reply */
+#define INP_RECVDSTADDR 0x04 /* receive IP dst address */
+#define INP_HDRINCL 0x08 /* user supplies entire IP header */
+#define INP_HIGHPORT 0x10 /* user wants "high" port binding */
+#define INP_LOWPORT 0x20 /* user wants "low" port binding */
+#define INP_ANONPORT 0x40 /* port chosen for user */
+#define INP_RECVIF 0x80 /* receive incoming interface */
+#define INP_CONTROLOPTS (INP_RECVOPTS|INP_RECVRETOPTS|INP_RECVDSTADDR|\
+ INP_RECVIF)
+
+#define INPLOOKUP_WILDCARD 1
+
+#define sotoinpcb(so) ((struct inpcb *)(so)->so_pcb)
+
+#ifdef _KERNEL
+void in_losing __P((struct inpcb *));
+int in_pcballoc __P((struct socket *, struct inpcbinfo *));
+int in_pcbbind __P((struct inpcb *, struct mbuf *));
+int in_pcbconnect __P((struct inpcb *, struct mbuf *));
+void in_pcbdetach __P((struct inpcb *));
+void in_pcbdisconnect __P((struct inpcb *));
+int in_pcbladdr __P((struct inpcb *, struct mbuf *,
+ struct sockaddr_in **));
+struct inpcb *
+ in_pcblookup __P((struct inpcbinfo *,
+ struct in_addr, u_int, struct in_addr, u_int, int));
+struct inpcb *
+ in_pcblookuphash __P((struct inpcbinfo *,
+ struct in_addr, u_int, struct in_addr, u_int, int));
+void in_pcbnotify __P((struct inpcbhead *, struct sockaddr *,
+ u_int, struct in_addr, u_int, int, void (*)(struct inpcb *, int)));
+void in_pcbrehash __P((struct inpcb *));
+void in_setpeeraddr __P((struct inpcb *, struct mbuf *));
+void in_setsockaddr __P((struct inpcb *, struct mbuf *));
+#endif
+
+#endif
diff --git a/cpukit/libnetworking/netinet/in_proto.c b/cpukit/libnetworking/netinet/in_proto.c
new file mode 100644
index 0000000000..b59b7be884
--- /dev/null
+++ b/cpukit/libnetworking/netinet/in_proto.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)in_proto.c 8.2 (Berkeley) 2/9/95
+ * $Id$
+ */
+
+#include "opt_tcpdebug.h"
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/domain.h>
+#include <sys/mbuf.h>
+#include <sys/protosw.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/radix.h>
+#include <net/route.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/in_pcb.h>
+#include <netinet/igmp_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcp_fsm.h>
+#include <netinet/tcp_seq.h>
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_var.h>
+#include <netinet/tcpip.h>
+#ifdef TCPDEBUG
+#include <netinet/tcp_debug.h>
+#endif
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+/*
+ * TCP/IP protocol family: IP, ICMP, UDP, TCP.
+ */
+
+#ifdef IPXIP
+#include <netipx/ipx.h>
+#include <netipx/ipx_ip.h>
+#endif
+
+#ifdef NSIP
+#include <netns/ns.h>
+#include <netns/ns_if.h>
+#endif
+
+#ifdef TPIP
+void tpip_input(), tpip_ctlinput(), tp_init(), tp_slowtimo(), tp_drain();
+int tp_ctloutput(), tp_usrreq();
+#endif
+
+#ifdef EON
+void eoninput(), eonctlinput(), eonprotoinit();
+#endif /* EON */
+
+extern struct domain inetdomain;
+
+struct protosw inetsw[] = {
+{ 0, &inetdomain, 0, 0,
+ 0, 0, 0, 0,
+ 0,
+ ip_init, 0, ip_slowtimo, ip_drain
+},
+{ SOCK_DGRAM, &inetdomain, IPPROTO_UDP, PR_ATOMIC|PR_ADDR,
+ udp_input, 0, udp_ctlinput, ip_ctloutput,
+ udp_usrreq,
+ udp_init
+},
+{ SOCK_STREAM, &inetdomain, IPPROTO_TCP,
+ PR_CONNREQUIRED|PR_IMPLOPCL|PR_WANTRCVD,
+ tcp_input, 0, tcp_ctlinput, tcp_ctloutput,
+ 0,
+ tcp_init, tcp_fasttimo, tcp_slowtimo, tcp_drain,
+ &tcp_usrreqs
+},
+{ SOCK_RAW, &inetdomain, IPPROTO_RAW, PR_ATOMIC|PR_ADDR,
+ rip_input, 0, 0, rip_ctloutput,
+ rip_usrreq,
+ 0, 0, 0, 0,
+},
+{ SOCK_RAW, &inetdomain, IPPROTO_ICMP, PR_ATOMIC|PR_ADDR,
+ icmp_input, 0, 0, rip_ctloutput,
+ rip_usrreq
+},
+{ SOCK_RAW, &inetdomain, IPPROTO_IGMP, PR_ATOMIC|PR_ADDR,
+ igmp_input, 0, 0, rip_ctloutput,
+ rip_usrreq,
+ igmp_init, igmp_fasttimo, igmp_slowtimo
+},
+{ SOCK_RAW, &inetdomain, IPPROTO_RSVP, PR_ATOMIC|PR_ADDR,
+ rsvp_input, 0, 0, rip_ctloutput,
+ rip_usrreq,
+ 0, 0, 0, 0,
+},
+{ SOCK_RAW, &inetdomain, IPPROTO_IPIP, PR_ATOMIC|PR_ADDR,
+ ipip_input, 0, 0, rip_ctloutput,
+ rip_usrreq,
+ 0, 0, 0, 0,
+},
+#ifdef IPDIVERT
+{ SOCK_RAW, &inetdomain, IPPROTO_DIVERT, PR_ATOMIC|PR_ADDR,
+ div_input, 0, 0, ip_ctloutput,
+ div_usrreq,
+ div_init, 0, 0, 0,
+},
+#endif
+#ifdef TPIP
+{ SOCK_SEQPACKET,&inetdomain, IPPROTO_TP, PR_CONNREQUIRED|PR_WANTRCVD,
+ tpip_input, 0, tpip_ctlinput, tp_ctloutput,
+ tp_usrreq,
+ tp_init, 0, tp_slowtimo, tp_drain,
+},
+#endif
+/* EON (ISO CLNL over IP) */
+#ifdef EON
+{ SOCK_RAW, &inetdomain, IPPROTO_EON, 0,
+ eoninput, 0, eonctlinput, 0,
+ 0,
+ eonprotoinit, 0, 0, 0,
+},
+#endif
+#ifdef IPXIP
+{ SOCK_RAW, &inetdomain, IPPROTO_IDP, PR_ATOMIC|PR_ADDR,
+ ipxip_input, 0, ipxip_ctlinput, 0,
+ rip_usrreq,
+ 0, 0, 0, 0,
+},
+#endif
+#ifdef NSIP
+{ SOCK_RAW, &inetdomain, IPPROTO_IDP, PR_ATOMIC|PR_ADDR,
+ idpip_input, 0, nsip_ctlinput, 0,
+ rip_usrreq,
+ 0, 0, 0, 0,
+},
+#endif
+ /* raw wildcard */
+{ SOCK_RAW, &inetdomain, 0, PR_ATOMIC|PR_ADDR,
+ rip_input, 0, 0, rip_ctloutput,
+ rip_usrreq,
+ rip_init, 0, 0, 0,
+},
+};
+
+extern int in_inithead(void **, int);
+
+struct domain inetdomain =
+ { AF_INET, "internet", 0, 0, 0,
+ inetsw, &inetsw[sizeof(inetsw)/sizeof(inetsw[0])], 0,
+ in_inithead, 32, sizeof(struct sockaddr_in)
+ };
+
+DOMAIN_SET(inet);
+
+SYSCTL_NODE(_net, PF_INET, inet, CTLFLAG_RW, 0,
+ "Internet Family");
+
+SYSCTL_NODE(_net_inet, IPPROTO_IP, ip, CTLFLAG_RW, 0, "IP");
+SYSCTL_NODE(_net_inet, IPPROTO_ICMP, icmp, CTLFLAG_RW, 0, "ICMP");
+SYSCTL_NODE(_net_inet, IPPROTO_UDP, udp, CTLFLAG_RW, 0, "UDP");
+SYSCTL_NODE(_net_inet, IPPROTO_TCP, tcp, CTLFLAG_RW, 0, "TCP");
+SYSCTL_NODE(_net_inet, IPPROTO_IGMP, igmp, CTLFLAG_RW, 0, "IGMP");
+#ifdef IPDIVERT
+SYSCTL_NODE(_net_inet, IPPROTO_DIVERT, div, CTLFLAG_RW, 0, "DIVERT");
+#endif
diff --git a/cpukit/libnetworking/netinet/in_rmx.c b/cpukit/libnetworking/netinet/in_rmx.c
new file mode 100644
index 0000000000..bfdd1e1c8f
--- /dev/null
+++ b/cpukit/libnetworking/netinet/in_rmx.c
@@ -0,0 +1,383 @@
+/*
+ * Copyright 1994, 1995 Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that both the above copyright notice and this
+ * permission notice appear in all copies, that both the above
+ * copyright notice and this permission notice appear in all
+ * supporting documentation, and that the name of M.I.T. not be used
+ * in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. M.I.T. makes
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
+ * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
+ * SHALL M.I.T. 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.
+ *
+ * $Id$
+ */
+
+/*
+ * This code does two things necessary for the enhanced TCP metrics to
+ * function in a useful manner:
+ * 1) It marks all non-host routes as `cloning', thus ensuring that
+ * every actual reference to such a route actually gets turned
+ * into a reference to a host route to the specific destination
+ * requested.
+ * 2) When such routes lose all their references, it arranges for them
+ * to be deleted in some random collection of circumstances, so that
+ * a large quantity of stale routing data is not kept in kernel memory
+ * indefinitely. See in_rtqtimo() below for the exact mechanism.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/mbuf.h>
+#include <sys/syslog.h>
+
+#include <net/if.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+
+#include <netinet/tcp.h>
+#include <netinet/tcp_seq.h>
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_var.h>
+
+extern int in_inithead __P((void **head, int off));
+
+#define RTPRF_OURS RTF_PROTO3 /* set on routes we manage */
+
+/*
+ * Do what we need to do when inserting a route.
+ */
+static struct radix_node *
+in_addroute(void *v_arg, void *n_arg, struct radix_node_head *head,
+ struct radix_node *treenodes)
+{
+ struct rtentry *rt = (struct rtentry *)treenodes;
+ struct sockaddr_in *sin = (struct sockaddr_in *)rt_key(rt);
+ struct radix_node *ret;
+
+ /*
+ * For IP, all unicast non-host routes are automatically cloning.
+ */
+ if(IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
+ rt->rt_flags |= RTF_MULTICAST;
+
+ if(!(rt->rt_flags & (RTF_HOST | RTF_CLONING | RTF_MULTICAST))) {
+ rt->rt_flags |= RTF_PRCLONING;
+ }
+
+ /*
+ * A little bit of help for both IP output and input:
+ * For host routes, we make sure that RTF_BROADCAST
+ * is set for anything that looks like a broadcast address.
+ * This way, we can avoid an expensive call to in_broadcast()
+ * in ip_output() most of the time (because the route passed
+ * to ip_output() is almost always a host route).
+ *
+ * We also do the same for local addresses, with the thought
+ * that this might one day be used to speed up ip_input().
+ *
+ * We also mark routes to multicast addresses as such, because
+ * it's easy to do and might be useful (but this is much more
+ * dubious since it's so easy to inspect the address). (This
+ * is done above.)
+ */
+ if (rt->rt_flags & RTF_HOST) {
+ if (in_broadcast(sin->sin_addr, rt->rt_ifp)) {
+ rt->rt_flags |= RTF_BROADCAST;
+ } else {
+#define satosin(sa) ((struct sockaddr_in *)sa)
+ if (satosin(rt->rt_ifa->ifa_addr)->sin_addr.s_addr
+ == sin->sin_addr.s_addr)
+ rt->rt_flags |= RTF_LOCAL;
+#undef satosin
+ }
+ }
+
+ /*
+ * We also specify a send and receive pipe size for every
+ * route added, to help TCP a bit. TCP doesn't actually
+ * want a true pipe size, which would be prohibitive in memory
+ * costs and is hard to compute anyway; it simply uses these
+ * values to size its buffers. So, we fill them in with the
+ * same values that TCP would have used anyway, and allow the
+ * installing program or the link layer to override these values
+ * as it sees fit. This will hopefully allow TCP more
+ * opportunities to save its ssthresh value.
+ */
+ if (!rt->rt_rmx.rmx_sendpipe && !(rt->rt_rmx.rmx_locks & RTV_SPIPE))
+ rt->rt_rmx.rmx_sendpipe = tcp_sendspace;
+
+ if (!rt->rt_rmx.rmx_recvpipe && !(rt->rt_rmx.rmx_locks & RTV_RPIPE))
+ rt->rt_rmx.rmx_recvpipe = tcp_recvspace;
+
+ if (!rt->rt_rmx.rmx_mtu && !(rt->rt_rmx.rmx_locks & RTV_MTU)
+ && rt->rt_ifp)
+ rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu;
+
+ ret = rn_addroute(v_arg, n_arg, head, treenodes);
+ if (ret == NULL && rt->rt_flags & RTF_HOST) {
+ struct rtentry *rt2;
+ /*
+ * We are trying to add a host route, but can't.
+ * Find out if it is because of an
+ * ARP entry and delete it if so.
+ */
+ rt2 = rtalloc1((struct sockaddr *)sin, 0,
+ RTF_CLONING | RTF_PRCLONING);
+ if (rt2) {
+ if (rt2->rt_flags & RTF_LLINFO &&
+ rt2->rt_flags & RTF_HOST &&
+ rt2->rt_gateway &&
+ rt2->rt_gateway->sa_family == AF_LINK) {
+ rtrequest(RTM_DELETE,
+ (struct sockaddr *)rt_key(rt2),
+ rt2->rt_gateway,
+ rt_mask(rt2), rt2->rt_flags, 0);
+ ret = rn_addroute(v_arg, n_arg, head,
+ treenodes);
+ }
+ RTFREE(rt2);
+ }
+ }
+ return ret;
+}
+
+/*
+ * This code is the inverse of in_clsroute: on first reference, if we
+ * were managing the route, stop doing so and set the expiration timer
+ * back off again.
+ */
+static struct radix_node *
+in_matroute(void *v_arg, struct radix_node_head *head)
+{
+ struct radix_node *rn = rn_match(v_arg, head);
+ struct rtentry *rt = (struct rtentry *)rn;
+
+ if(rt && rt->rt_refcnt == 0) { /* this is first reference */
+ if(rt->rt_flags & RTPRF_OURS) {
+ rt->rt_flags &= ~RTPRF_OURS;
+ rt->rt_rmx.rmx_expire = 0;
+ }
+ }
+ return rn;
+}
+
+static int rtq_reallyold = 60*60;
+ /* one hour is ``really old'' */
+SYSCTL_INT(_net_inet_ip, IPCTL_RTEXPIRE, rtexpire,
+ CTLFLAG_RW, &rtq_reallyold , 0, "");
+
+static int rtq_minreallyold = 10;
+ /* never automatically crank down to less */
+SYSCTL_INT(_net_inet_ip, IPCTL_RTMINEXPIRE, rtminexpire,
+ CTLFLAG_RW, &rtq_minreallyold , 0, "");
+
+static int rtq_toomany = 128;
+ /* 128 cached routes is ``too many'' */
+SYSCTL_INT(_net_inet_ip, IPCTL_RTMAXCACHE, rtmaxcache,
+ CTLFLAG_RW, &rtq_toomany , 0, "");
+
+
+/*
+ * On last reference drop, mark the route as belong to us so that it can be
+ * timed out.
+ */
+static void
+in_clsroute(struct radix_node *rn, struct radix_node_head *head)
+{
+ struct rtentry *rt = (struct rtentry *)rn;
+
+ if(!(rt->rt_flags & RTF_UP))
+ return; /* prophylactic measures */
+
+ if((rt->rt_flags & (RTF_LLINFO | RTF_HOST)) != RTF_HOST)
+ return;
+
+ if((rt->rt_flags & (RTF_WASCLONED | RTPRF_OURS))
+ != RTF_WASCLONED)
+ return;
+
+ /*
+ * As requested by David Greenman:
+ * If rtq_reallyold is 0, just delete the route without
+ * waiting for a timeout cycle to kill it.
+ */
+ if(rtq_reallyold != 0) {
+ rt->rt_flags |= RTPRF_OURS;
+ rt->rt_rmx.rmx_expire = rtems_bsdnet_seconds_since_boot() + rtq_reallyold;
+ } else {
+ rtrequest(RTM_DELETE,
+ (struct sockaddr *)rt_key(rt),
+ rt->rt_gateway, rt_mask(rt),
+ rt->rt_flags, 0);
+ }
+}
+
+struct rtqk_arg {
+ struct radix_node_head *rnh;
+ int draining;
+ int killed;
+ int found;
+ int updating;
+ time_t nextstop;
+};
+
+/*
+ * Get rid of old routes. When draining, this deletes everything, even when
+ * the timeout is not expired yet. When updating, this makes sure that
+ * nothing has a timeout longer than the current value of rtq_reallyold.
+ */
+static int
+in_rtqkill(struct radix_node *rn, void *rock)
+{
+ struct rtqk_arg *ap = rock;
+ struct rtentry *rt = (struct rtentry *)rn;
+ int err;
+
+ if(rt->rt_flags & RTPRF_OURS) {
+ ap->found++;
+
+ if(ap->draining || rt->rt_rmx.rmx_expire <= rtems_bsdnet_seconds_since_boot()) {
+ if(rt->rt_refcnt > 0)
+ panic("rtqkill route really not free");
+
+ err = rtrequest(RTM_DELETE,
+ (struct sockaddr *)rt_key(rt),
+ rt->rt_gateway, rt_mask(rt),
+ rt->rt_flags, 0);
+ if(err) {
+ log(LOG_WARNING, "in_rtqkill: error %d\n", err);
+ } else {
+ ap->killed++;
+ }
+ } else {
+ if(ap->updating
+ && (rt->rt_rmx.rmx_expire - rtems_bsdnet_seconds_since_boot()
+ > rtq_reallyold)) {
+ rt->rt_rmx.rmx_expire = rtems_bsdnet_seconds_since_boot()
+ + rtq_reallyold;
+ }
+ ap->nextstop = lmin(ap->nextstop,
+ rt->rt_rmx.rmx_expire);
+ }
+ }
+
+ return 0;
+}
+
+#define RTQ_TIMEOUT 60*10 /* run no less than once every ten minutes */
+static int rtq_timeout = RTQ_TIMEOUT;
+
+static void
+in_rtqtimo(void *rock)
+{
+ struct radix_node_head *rnh = rock;
+ struct rtqk_arg arg;
+ struct timeval atv;
+ static time_t last_adjusted_timeout = 0;
+ int s;
+
+ arg.found = arg.killed = 0;
+ arg.rnh = rnh;
+ arg.nextstop = rtems_bsdnet_seconds_since_boot() + rtq_timeout;
+ arg.draining = arg.updating = 0;
+ s = splnet();
+ rnh->rnh_walktree(rnh, in_rtqkill, &arg);
+ splx(s);
+
+ /*
+ * Attempt to be somewhat dynamic about this:
+ * If there are ``too many'' routes sitting around taking up space,
+ * then crank down the timeout, and see if we can't make some more
+ * go away. However, we make sure that we will never adjust more
+ * than once in rtq_timeout seconds, to keep from cranking down too
+ * hard.
+ */
+ if((arg.found - arg.killed > rtq_toomany)
+ && (rtems_bsdnet_seconds_since_boot() - last_adjusted_timeout >= rtq_timeout)
+ && rtq_reallyold > rtq_minreallyold) {
+ rtq_reallyold = 2*rtq_reallyold / 3;
+ if(rtq_reallyold < rtq_minreallyold) {
+ rtq_reallyold = rtq_minreallyold;
+ }
+
+ last_adjusted_timeout = rtems_bsdnet_seconds_since_boot();
+#ifdef DIAGNOSTIC
+ log(LOG_DEBUG, "in_rtqtimo: adjusted rtq_reallyold to %d\n",
+ rtq_reallyold);
+#endif
+ arg.found = arg.killed = 0;
+ arg.updating = 1;
+ s = splnet();
+ rnh->rnh_walktree(rnh, in_rtqkill, &arg);
+ splx(s);
+ }
+
+ atv.tv_usec = 0;
+ atv.tv_sec = arg.nextstop;
+ timeout(in_rtqtimo, rock, hzto(&atv));
+}
+
+void
+in_rtqdrain(void)
+{
+ struct radix_node_head *rnh = rt_tables[AF_INET];
+ struct rtqk_arg arg;
+ int s;
+ arg.found = arg.killed = 0;
+ arg.rnh = rnh;
+ arg.nextstop = 0;
+ arg.draining = 1;
+ arg.updating = 0;
+ s = splnet();
+ rnh->rnh_walktree(rnh, in_rtqkill, &arg);
+ splx(s);
+}
+
+/*
+ * Initialize our routing tree.
+ */
+int
+in_inithead(void **head, int off)
+{
+ struct radix_node_head *rnh;
+
+ if(!rn_inithead(head, off))
+ return 0;
+
+ if(head != (void **)&rt_tables[AF_INET]) /* BOGUS! */
+ return 1; /* only do this for the real routing table */
+
+ rnh = *head;
+ rnh->rnh_addaddr = in_addroute;
+ rnh->rnh_matchaddr = in_matroute;
+ rnh->rnh_close = in_clsroute;
+ in_rtqtimo(rnh); /* kick off timeout first time */
+ return 1;
+}
diff --git a/cpukit/libnetworking/netinet/in_systm.h b/cpukit/libnetworking/netinet/in_systm.h
new file mode 100644
index 0000000000..6178a7bf5e
--- /dev/null
+++ b/cpukit/libnetworking/netinet/in_systm.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)in_systm.h 8.1 (Berkeley) 6/10/93
+ * $Id$
+ */
+
+#ifndef _NETINET_IN_SYSTM_H_
+#define _NETINET_IN_SYSTM_H_
+
+/*
+ * Miscellaneous internetwork
+ * definitions for kernel.
+ */
+
+/*
+ * Network types.
+ *
+ * Internally the system keeps counters in the headers with the bytes
+ * swapped so that VAX instructions will work on them. It reverses
+ * the bytes before transmission at each protocol level. The n_ types
+ * represent the types with the bytes in ``high-ender'' order.
+ */
+typedef u_short n_short; /* short as received from the net */
+typedef u_long n_long; /* long as received from the net */
+
+typedef u_long n_time; /* ms since 00:00 GMT, byte rev */
+
+#ifdef _KERNEL
+n_time iptime __P((void));
+#endif
+
+#endif
diff --git a/cpukit/libnetworking/netinet/in_var.h b/cpukit/libnetworking/netinet/in_var.h
new file mode 100644
index 0000000000..638d07737f
--- /dev/null
+++ b/cpukit/libnetworking/netinet/in_var.h
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 1985, 1986, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)in_var.h 8.2 (Berkeley) 1/9/95
+ * $Id$
+ */
+
+#ifndef _NETINET_IN_VAR_H_
+#define _NETINET_IN_VAR_H_
+
+#include <sys/queue.h>
+
+/*
+ * Interface address, Internet version. One of these structures
+ * is allocated for each interface with an Internet address.
+ * The ifaddr structure contains the protocol-independent part
+ * of the structure and is assumed to be first.
+ */
+struct in_ifaddr {
+ struct ifaddr ia_ifa; /* protocol-independent info */
+#define ia_ifp ia_ifa.ifa_ifp
+#define ia_flags ia_ifa.ifa_flags
+ /* ia_{,sub}net{,mask} in host order */
+ u_long ia_net; /* network number of interface */
+ u_long ia_netmask; /* mask of net part */
+ u_long ia_subnet; /* subnet number, including net */
+ u_long ia_subnetmask; /* mask of subnet part */
+ struct in_addr ia_netbroadcast; /* to recognize net broadcasts */
+ struct in_ifaddr *ia_next; /* next in list of internet addresses */
+ struct sockaddr_in ia_addr; /* reserve space for interface name */
+ struct sockaddr_in ia_dstaddr; /* reserve space for broadcast addr */
+#define ia_broadaddr ia_dstaddr
+ struct sockaddr_in ia_sockmask; /* reserve space for general netmask */
+ LIST_HEAD(in_multihead, in_multi) ia_multiaddrs;
+ /* list of multicast addresses */
+};
+
+struct in_aliasreq {
+ char ifra_name[IFNAMSIZ]; /* if name, e.g. "en0" */
+ struct sockaddr_in ifra_addr;
+ struct sockaddr_in ifra_broadaddr;
+#define ifra_dstaddr ifra_broadaddr
+ struct sockaddr_in ifra_mask;
+};
+/*
+ * Given a pointer to an in_ifaddr (ifaddr),
+ * return a pointer to the addr as a sockaddr_in.
+ */
+#define IA_SIN(ia) (&(((struct in_ifaddr *)(ia))->ia_addr))
+#define IA_DSTSIN(ia) (&(((struct in_ifaddr *)(ia))->ia_dstaddr))
+
+#define IN_LNAOF(in, ifa) \
+ ((ntohl((in).s_addr) & ~((struct in_ifaddr *)(ifa)->ia_subnetmask))
+
+
+#ifdef _KERNEL
+extern struct in_ifaddr *in_ifaddr;
+extern struct ifqueue ipintrq; /* ip packet input queue */
+extern struct in_addr zeroin_addr;
+extern u_char inetctlerrmap[];
+extern int rtq_reallyold; /* XXX */
+extern int rtq_minreallyold; /* XXX */
+extern int rtq_toomany; /* XXX */
+
+/*
+ * Macro for finding the interface (ifnet structure) corresponding to one
+ * of our IP addresses.
+ */
+#define INADDR_TO_IFP(addr, ifp) \
+ /* struct in_addr addr; */ \
+ /* struct ifnet *ifp; */ \
+{ \
+ register struct in_ifaddr *ia; \
+\
+ for (ia = in_ifaddr; \
+ ia != NULL && ((ia->ia_ifp->if_flags & IFF_POINTOPOINT)? \
+ IA_DSTSIN(ia):IA_SIN(ia))->sin_addr.s_addr != (addr).s_addr; \
+ ia = ia->ia_next) \
+ continue; \
+ if (ia == NULL) \
+ for (ia = in_ifaddr; \
+ ia != NULL; \
+ ia = ia->ia_next) \
+ if (ia->ia_ifp->if_flags & IFF_POINTOPOINT && \
+ IA_SIN(ia)->sin_addr.s_addr == (addr).s_addr) \
+ break; \
+ (ifp) = (ia == NULL) ? NULL : ia->ia_ifp; \
+}
+
+/*
+ * Macro for finding the internet address structure (in_ifaddr) corresponding
+ * to a given interface (ifnet structure).
+ */
+#define IFP_TO_IA(ifp, ia) \
+ /* struct ifnet *ifp; */ \
+ /* struct in_ifaddr *ia; */ \
+{ \
+ for ((ia) = in_ifaddr; \
+ (ia) != NULL && (ia)->ia_ifp != (ifp); \
+ (ia) = (ia)->ia_next) \
+ continue; \
+}
+#endif
+
+/*
+ * This information should be part of the ifnet structure but we don't wish
+ * to change that - as it might break a number of things
+ */
+
+struct router_info {
+ struct ifnet *rti_ifp;
+ int rti_type; /* type of router which is querier on this interface */
+ int rti_time; /* # of slow timeouts since last old query */
+ struct router_info *rti_next;
+};
+
+/*
+ * Internet multicast address structure. There is one of these for each IP
+ * multicast group to which this host belongs on a given network interface.
+ * They are kept in a linked list, rooted in the interface's in_ifaddr
+ * structure.
+ */
+struct in_multi {
+ LIST_ENTRY(in_multi) inm_entry; /* list glue */
+ struct in_addr inm_addr; /* IP multicast address */
+ struct ifnet *inm_ifp; /* back pointer to ifnet */
+ struct in_ifaddr *inm_ia; /* back pointer to in_ifaddr */
+ u_int inm_refcount; /* no. membership claims by sockets */
+ u_int inm_timer; /* IGMP membership report timer */
+ u_int inm_state; /* state of the membership */
+ struct router_info *inm_rti; /* router info*/
+};
+
+#ifdef _KERNEL
+
+#ifdef SYSCTL_DECL
+SYSCTL_DECL(_net_inet_ip);
+SYSCTL_DECL(_net_inet_raw);
+#endif
+
+/*
+ * Structure used by macros below to remember position when stepping through
+ * all of the in_multi records.
+ */
+struct in_multistep {
+ struct in_ifaddr *i_ia;
+ struct in_multi *i_inm;
+};
+
+/*
+ * Macro for looking up the in_multi record for a given IP multicast address
+ * on a given interface. If no matching record is found, "inm" returns NULL.
+ */
+#define IN_LOOKUP_MULTI(addr, ifp, inm) \
+ /* struct in_addr addr; */ \
+ /* struct ifnet *ifp; */ \
+ /* struct in_multi *inm; */ \
+{ \
+ register struct in_ifaddr *ia; \
+\
+ IFP_TO_IA((ifp), ia); \
+ if (ia == NULL) \
+ (inm) = NULL; \
+ else \
+ for ((inm) = ia->ia_multiaddrs.lh_first; \
+ (inm) != NULL && (inm)->inm_addr.s_addr != (addr).s_addr; \
+ (inm) = inm->inm_entry.le_next) \
+ continue; \
+}
+
+/*
+ * Macro to step through all of the in_multi records, one at a time.
+ * The current position is remembered in "step", which the caller must
+ * provide. IN_FIRST_MULTI(), below, must be called to initialize "step"
+ * and get the first record. Both macros return a NULL "inm" when there
+ * are no remaining records.
+ */
+#define IN_NEXT_MULTI(step, inm) \
+ /* struct in_multistep step; */ \
+ /* struct in_multi *inm; */ \
+{ \
+ if (((inm) = (step).i_inm) != NULL) \
+ (step).i_inm = (inm)->inm_entry.le_next; \
+ else \
+ while ((step).i_ia != NULL) { \
+ (inm) = (step).i_ia->ia_multiaddrs.lh_first; \
+ (step).i_ia = (step).i_ia->ia_next; \
+ if ((inm) != NULL) { \
+ (step).i_inm = (inm)->inm_entry.le_next; \
+ break; \
+ } \
+ } \
+}
+
+#define IN_FIRST_MULTI(step, inm) \
+ /* struct in_multistep step; */ \
+ /* struct in_multi *inm; */ \
+{ \
+ (step).i_ia = in_ifaddr; \
+ (step).i_inm = NULL; \
+ IN_NEXT_MULTI((step), (inm)); \
+}
+
+struct in_multi *in_addmulti __P((struct in_addr *, struct ifnet *));
+void in_delmulti __P((struct in_multi *));
+int in_control __P((struct socket *, u_long, caddr_t, struct ifnet *));
+void in_rtqdrain __P((void));
+void ip_input __P((struct mbuf *));
+
+#endif /* _KERNEL */
+
+#endif /* _NETINET_IN_VAR_H_ */
diff --git a/cpukit/libnetworking/netinet/ip.h b/cpukit/libnetworking/netinet/ip.h
new file mode 100644
index 0000000000..e6be7d305d
--- /dev/null
+++ b/cpukit/libnetworking/netinet/ip.h
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)ip.h 8.2 (Berkeley) 6/1/94
+ * $Id$
+ */
+
+#ifndef _NETINET_IP_H_
+#define _NETINET_IP_H_
+
+/*
+ * Definitions for internet protocol version 4.
+ * Per RFC 791, September 1981.
+ */
+#define IPVERSION 4
+
+/*
+ * Structure of an internet header, naked of options.
+ *
+ * We declare ip_len and ip_off to be short, rather than u_short
+ * pragmatically since otherwise unsigned comparisons can result
+ * against negative integers quite easily, and fail in subtle ways.
+ */
+struct ip {
+#ifdef _IP_VHL
+ u_char ip_vhl; /* version << 4 | header length >> 2 */
+#else
+#if BYTE_ORDER == LITTLE_ENDIAN
+ u_char ip_hl:4, /* header length */
+ ip_v:4; /* version */
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char ip_v:4, /* version */
+ ip_hl:4; /* header length */
+#endif
+#endif /* not _IP_VHL */
+ u_char ip_tos; /* type of service */
+ u_short ip_len BYTE_PACK; /* total length */
+ u_short ip_id BYTE_PACK; /* identification */
+ u_short ip_off BYTE_PACK; /* fragment offset field */
+#define IP_RF 0x8000 /* reserved fragment flag */
+#define IP_DF 0x4000 /* dont fragment flag */
+#define IP_MF 0x2000 /* more fragments flag */
+#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
+ u_char ip_ttl; /* time to live */
+ u_char ip_p; /* protocol */
+ u_short ip_sum BYTE_PACK; /* checksum */
+ struct in_addr ip_src BYTE_PACK; /* source address */
+ struct in_addr ip_dst BYTE_PACK; /* dest address */
+};
+
+#ifdef _IP_VHL
+#define IP_MAKE_VHL(v, hl) ((v) << 4 | (hl))
+#define IP_VHL_HL(vhl) ((vhl) & 0x0f)
+#define IP_VHL_V(vhl) ((vhl) >> 4)
+#define IP_VHL_BORING 0x45
+#endif
+
+#define IP_MAXPACKET 65535 /* maximum packet size */
+
+/*
+ * Definitions for IP type of service (ip_tos)
+ */
+#define IPTOS_LOWDELAY 0x10
+#define IPTOS_THROUGHPUT 0x08
+#define IPTOS_RELIABILITY 0x04
+#define IPTOS_MINCOST 0x02
+
+/*
+ * Definitions for IP precedence (also in ip_tos) (hopefully unused)
+ */
+#define IPTOS_PREC_NETCONTROL 0xe0
+#define IPTOS_PREC_INTERNETCONTROL 0xc0
+#define IPTOS_PREC_CRITIC_ECP 0xa0
+#define IPTOS_PREC_FLASHOVERRIDE 0x80
+#define IPTOS_PREC_FLASH 0x60
+#define IPTOS_PREC_IMMEDIATE 0x40
+#define IPTOS_PREC_PRIORITY 0x20
+#define IPTOS_PREC_ROUTINE 0x00
+
+/*
+ * Definitions for options.
+ */
+#define IPOPT_COPIED(o) ((o)&0x80)
+#define IPOPT_CLASS(o) ((o)&0x60)
+#define IPOPT_NUMBER(o) ((o)&0x1f)
+
+#define IPOPT_CONTROL 0x00
+#define IPOPT_RESERVED1 0x20
+#define IPOPT_DEBMEAS 0x40
+#define IPOPT_RESERVED2 0x60
+
+#define IPOPT_EOL 0 /* end of option list */
+#define IPOPT_NOP 1 /* no operation */
+
+#define IPOPT_RR 7 /* record packet route */
+#define IPOPT_TS 68 /* timestamp */
+#define IPOPT_SECURITY 130 /* provide s,c,h,tcc */
+#define IPOPT_LSRR 131 /* loose source route */
+#define IPOPT_SATID 136 /* satnet id */
+#define IPOPT_SSRR 137 /* strict source route */
+#define IPOPT_RA 148 /* router alert */
+
+/*
+ * Offsets to fields in options other than EOL and NOP.
+ */
+#define IPOPT_OPTVAL 0 /* option ID */
+#define IPOPT_OLEN 1 /* option length */
+#define IPOPT_OFFSET 2 /* offset within option */
+#define IPOPT_MINOFF 4 /* min value of above */
+
+/*
+ * Time stamp option structure.
+ */
+struct ip_timestamp {
+ u_char ipt_code; /* IPOPT_TS */
+ u_char ipt_len; /* size of structure (variable) */
+ u_char ipt_ptr; /* index of current entry */
+#if BYTE_ORDER == LITTLE_ENDIAN
+ u_char ipt_flg:4, /* flags, see below */
+ ipt_oflw:4; /* overflow counter */
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char ipt_oflw:4, /* overflow counter */
+ ipt_flg:4; /* flags, see below */
+#endif
+ union ipt_timestamp {
+ n_long ipt_time[1];
+ struct ipt_ta {
+ struct in_addr ipt_addr;
+ n_long ipt_time;
+ } ipt_ta[1];
+ } ipt_timestamp;
+};
+
+#include <machine/in_cksum.h>
+
+/* flag bits for ipt_flg */
+#define IPOPT_TS_TSONLY 0 /* timestamps only */
+#define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
+#define IPOPT_TS_PRESPEC 3 /* specified modules only */
+
+/* bits for security (not byte swapped) */
+#define IPOPT_SECUR_UNCLASS 0x0000
+#define IPOPT_SECUR_CONFID 0xf135
+#define IPOPT_SECUR_EFTO 0x789a
+#define IPOPT_SECUR_MMMM 0xbc4d
+#define IPOPT_SECUR_RESTR 0xaf13
+#define IPOPT_SECUR_SECRET 0xd788
+#define IPOPT_SECUR_TOPSECRET 0x6bc5
+
+/*
+ * Internet implementation parameters.
+ */
+#define MAXTTL 255 /* maximum time to live (seconds) */
+#define IPDEFTTL 64 /* default ttl, from RFC 1340 */
+#define IPFRAGTTL 60 /* time to live for frags, slowhz */
+#define IPTTLDEC 1 /* subtracted when forwarding */
+
+#define IP_MSS 576 /* default maximum segment size */
+
+#endif
diff --git a/cpukit/libnetworking/netinet/ip_divert.c b/cpukit/libnetworking/netinet/ip_divert.c
new file mode 100644
index 0000000000..2955e811ad
--- /dev/null
+++ b/cpukit/libnetworking/netinet/ip_divert.c
@@ -0,0 +1,382 @@
+/*
+ * Copyright (c) 1982, 1986, 1988, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * $Id$
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/protosw.h>
+#include <sys/socketvar.h>
+#include <sys/errno.h>
+#include <sys/systm.h>
+
+#include <net/if.h>
+#include <net/route.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/in_pcb.h>
+#include <netinet/in_var.h>
+#include <netinet/ip_var.h>
+
+/*
+ * Divert sockets
+ */
+
+/*
+ * Allocate enough space to hold a full IP packet
+ */
+#define DIVSNDQ (65536 + 100)
+#define DIVRCVQ (65536 + 100)
+
+/* Global variables */
+
+/*
+ * ip_input() and ip_output() set this secret value before calling us to
+ * let us know which divert port to divert a packet to; this is done so
+ * we can use the existing prototype for struct protosw's pr_input().
+ * This is stored in host order.
+ */
+u_short ip_divert_port;
+
+/*
+ * We set this value to a non-zero port number when we want the call to
+ * ip_fw_chk() in ip_input() or ip_output() to ignore ``divert <port>''
+ * chain entries. This is stored in host order.
+ */
+u_short ip_divert_ignore;
+
+/* Internal variables */
+
+static struct inpcbhead divcb;
+static struct inpcbinfo divcbinfo;
+
+static u_long div_sendspace = DIVSNDQ; /* XXX sysctl ? */
+static u_long div_recvspace = DIVRCVQ; /* XXX sysctl ? */
+
+/* Optimization: have this preinitialized */
+static struct sockaddr_in divsrc = { sizeof(divsrc), AF_INET };
+
+/* Internal functions */
+
+static int div_output(struct socket *so,
+ struct mbuf *m, struct mbuf *addr, struct mbuf *control);
+
+/*
+ * Initialize divert connection block queue.
+ */
+void
+div_init(void)
+{
+ LIST_INIT(&divcb);
+ divcbinfo.listhead = &divcb;
+ /*
+ * XXX We don't use the hash list for divert IP, but it's easier
+ * to allocate a one entry hash list than it is to check all
+ * over the place for hashbase == NULL.
+ */
+ divcbinfo.hashbase = hashinit(1, M_PCB, &divcbinfo.hashmask);
+}
+
+/*
+ * Setup generic address and protocol structures
+ * for div_input routine, then pass them along with
+ * mbuf chain. ip->ip_len is assumed to have had
+ * the header length (hlen) subtracted out already.
+ * We tell whether the packet was incoming or outgoing
+ * by seeing if hlen == 0, which is a hack.
+ */
+void
+div_input(struct mbuf *m, int hlen)
+{
+ struct ip *ip;
+ struct inpcb *inp;
+ struct socket *sa;
+
+ /* Sanity check */
+ if (ip_divert_port == 0)
+ panic("div_input: port is 0");
+
+ /* Assure header */
+ if (m->m_len < sizeof(struct ip) &&
+ (m = m_pullup(m, sizeof(struct ip))) == 0) {
+ return;
+ }
+ ip = mtod(m, struct ip *);
+
+ /* Record divert port */
+ divsrc.sin_port = htons(ip_divert_port);
+
+ /* Restore packet header fields */
+ ip->ip_len += hlen;
+ HTONS(ip->ip_len);
+ HTONS(ip->ip_off);
+
+ /* Record receive interface address, if any */
+ divsrc.sin_addr.s_addr = 0;
+ if (hlen) {
+ struct ifaddr *ifa;
+
+#ifdef DIAGNOSTIC
+ /* Sanity check */
+ if (!(m->m_flags & M_PKTHDR))
+ panic("div_input: no pkt hdr");
+#endif
+
+ /* More fields affected by ip_input() */
+ HTONS(ip->ip_id);
+
+ /* Find IP address for recieve interface */
+ for (ifa = m->m_pkthdr.rcvif->if_addrlist;
+ ifa != NULL; ifa = ifa->ifa_next) {
+ if (ifa->ifa_addr == NULL)
+ continue;
+ if (ifa->ifa_addr->sa_family != AF_INET)
+ continue;
+ divsrc.sin_addr =
+ ((struct sockaddr_in *) ifa->ifa_addr)->sin_addr;
+ break;
+ }
+ }
+
+ /* Put packet on socket queue, if any */
+ sa = NULL;
+ for (inp = divcb.lh_first; inp != NULL; inp = inp->inp_list.le_next) {
+ if (inp->inp_lport == htons(ip_divert_port))
+ sa = inp->inp_socket;
+ }
+ if (sa) {
+ if (sbappendaddr(&sa->so_rcv, (struct sockaddr *)&divsrc,
+ m, (struct mbuf *)0) == 0)
+ m_freem(m);
+ else
+ sorwakeup(sa);
+ } else {
+ m_freem(m);
+ ipstat.ips_noproto++;
+ ipstat.ips_delivered--;
+ }
+}
+
+/*
+ * Deliver packet back into the IP processing machinery.
+ *
+ * If no address specified, or address is 0.0.0.0, send to ip_output();
+ * otherwise, send to ip_input() and mark as having been received on
+ * the interface with that address.
+ *
+ * If no address specified, or dest port is 0, allow packet to divert
+ * back to this socket; otherwise, don't.
+ */
+static int
+div_output(so, m, addr, control)
+ struct socket *so;
+ register struct mbuf *m;
+ struct mbuf *addr, *control;
+{
+ register struct inpcb *const inp = sotoinpcb(so);
+ register struct ip *const ip = mtod(m, struct ip *);
+ struct sockaddr_in *sin = NULL;
+ int error = 0;
+
+ if (control)
+ m_freem(control); /* XXX */
+ if (addr)
+ sin = mtod(addr, struct sockaddr_in *);
+
+ /* Loopback avoidance option */
+ ip_divert_ignore = ntohs(inp->inp_lport);
+
+ /* Reinject packet into the system as incoming or outgoing */
+ if (!sin || sin->sin_addr.s_addr == 0) {
+ /* Don't allow both user specified and setsockopt options,
+ and don't allow packet length sizes that will crash */
+ if (((ip->ip_hl != (sizeof (*ip) >> 2)) && inp->inp_options) ||
+ ((u_short)ntohs(ip->ip_len) > m->m_pkthdr.len)) {
+ error = EINVAL;
+ goto cantsend;
+ }
+
+ /* Convert fields to host order for ip_output() */
+ NTOHS(ip->ip_len);
+ NTOHS(ip->ip_off);
+
+ /* Send packet to output processing */
+ ipstat.ips_rawout++; /* XXX */
+ error = ip_output(m, inp->inp_options, &inp->inp_route,
+ (so->so_options & SO_DONTROUTE) |
+ IP_ALLOWBROADCAST | IP_RAWOUTPUT, inp->inp_moptions);
+ } else {
+ struct ifaddr *ifa;
+
+ /* Find receive interface with the given IP address */
+ sin->sin_port = 0;
+ if ((ifa = ifa_ifwithaddr((struct sockaddr *) sin)) == 0) {
+ error = EADDRNOTAVAIL;
+ goto cantsend;
+ }
+ m->m_pkthdr.rcvif = ifa->ifa_ifp;
+
+ /* Send packet to input processing */
+ ip_input(m);
+ }
+
+ /* Reset for next time (and other packets) */
+ ip_divert_ignore = 0;
+ return error;
+
+cantsend:
+ ip_divert_ignore = 0;
+ m_freem(m);
+ return error;
+}
+
+/*ARGSUSED*/
+int
+div_usrreq(so, req, m, nam, control)
+ register struct socket *so;
+ int req;
+ struct mbuf *m, *nam, *control;
+{
+ register int error = 0;
+ register struct inpcb *inp = sotoinpcb(so);
+ int s;
+
+ if (inp == NULL && req != PRU_ATTACH) {
+ error = EINVAL;
+ goto release;
+ }
+ switch (req) {
+
+ case PRU_ATTACH:
+ if (inp)
+ panic("div_attach");
+ if ((so->so_state & SS_PRIV) == 0) {
+ error = EACCES;
+ break;
+ }
+ s = splnet();
+ error = in_pcballoc(so, &divcbinfo);
+ splx(s);
+ if (error)
+ break;
+ error = soreserve(so, div_sendspace, div_recvspace);
+ if (error)
+ break;
+ inp = (struct inpcb *)so->so_pcb;
+ inp->inp_ip_p = (int)nam; /* XXX */
+ inp->inp_flags |= INP_HDRINCL;
+ /* The socket is always "connected" because
+ we always know "where" to send the packet */
+ so->so_state |= SS_ISCONNECTED;
+ break;
+
+ case PRU_DISCONNECT:
+ if ((so->so_state & SS_ISCONNECTED) == 0) {
+ error = ENOTCONN;
+ break;
+ }
+ /* FALLTHROUGH */
+ case PRU_ABORT:
+ soisdisconnected(so);
+ /* FALLTHROUGH */
+ case PRU_DETACH:
+ if (inp == 0)
+ panic("div_detach");
+ in_pcbdetach(inp);
+ break;
+
+ case PRU_BIND:
+ s = splnet();
+ error = in_pcbbind(inp, nam);
+ splx(s);
+ break;
+
+ /*
+ * Mark the connection as being incapable of further input.
+ */
+ case PRU_SHUTDOWN:
+ socantsendmore(so);
+ break;
+
+ case PRU_SEND:
+ /* Packet must have a header (but that's about it) */
+ if (m->m_len < sizeof (struct ip) ||
+ (m = m_pullup(m, sizeof (struct ip))) == 0) {
+ ipstat.ips_toosmall++;
+ error = EINVAL;
+ break;
+ }
+
+ /* Send packet */
+ error = div_output(so, m, nam, control);
+ m = NULL;
+ break;
+
+ case PRU_SOCKADDR:
+ in_setsockaddr(inp, nam);
+ break;
+
+ case PRU_SENSE:
+ /*
+ * stat: don't bother with a blocksize.
+ */
+ return (0);
+
+ /*
+ * Not supported.
+ */
+ case PRU_CONNECT:
+ case PRU_CONNECT2:
+ case PRU_CONTROL:
+ case PRU_RCVOOB:
+ case PRU_RCVD:
+ case PRU_LISTEN:
+ case PRU_ACCEPT:
+ case PRU_SENDOOB:
+ case PRU_PEERADDR:
+ error = EOPNOTSUPP;
+ break;
+
+ default:
+ panic("div_usrreq");
+ }
+release:
+ if (m)
+ m_freem(m);
+ return (error);
+}
diff --git a/cpukit/libnetworking/netinet/ip_fw.c b/cpukit/libnetworking/netinet/ip_fw.c
new file mode 100644
index 0000000000..4bad293e7d
--- /dev/null
+++ b/cpukit/libnetworking/netinet/ip_fw.c
@@ -0,0 +1,1074 @@
+/*
+ * Copyright (c) 1996 Alex Nash
+ * Copyright (c) 1993 Daniel Boulet
+ * Copyright (c) 1994 Ugen J.S.Antsilevich
+ *
+ * Redistribution and use in source forms, with and without modification,
+ * are permitted provided that this entire comment appears intact.
+ *
+ * Redistribution in binary form may occur without any restrictions.
+ * Obviously, it would be nice if you gave credit where credit is due
+ * but requiring it would be too onerous.
+ *
+ * This software is provided ``AS IS'' without any warranties of any kind.
+ *
+ * $Id$
+ */
+
+/*
+ * Implement IP packet firewall
+ */
+
+#ifndef IPFIREWALL_MODULE
+#include "opt_ipfw.h"
+#endif
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/queue.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/sysctl.h>
+#include <net/if.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/ip_fw.h>
+#include <netinet/tcp.h>
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_var.h>
+#include <netinet/tcpip.h>
+#include <netinet/udp.h>
+
+static int fw_debug = 1;
+#ifdef IPFIREWALL_VERBOSE
+static int fw_verbose = 1;
+#else
+static int fw_verbose = 0;
+#endif
+#ifdef IPFIREWALL_VERBOSE_LIMIT
+static int fw_verbose_limit = IPFIREWALL_VERBOSE_LIMIT;
+#else
+static int fw_verbose_limit = 0;
+#endif
+
+LIST_HEAD (ip_fw_head, ip_fw_chain) ip_fw_chain;
+
+/*
+ * ccj - No current need for firewall so have provided the MIB.
+ */
+#if 0
+#ifdef SYSCTL_NODE
+SYSCTL_NODE(_net_inet_ip, OID_AUTO, fw, CTLFLAG_RW, 0, "Firewall");
+SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, debug, CTLFLAG_RW, &fw_debug, 0, "");
+SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, verbose, CTLFLAG_RW, &fw_verbose, 0, "");
+SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, verbose_limit, CTLFLAG_RW, &fw_verbose_limit, 0, "");
+#endif
+#endif
+
+#define dprintf(a) if (!fw_debug); else printf a
+
+#define print_ip(a) printf("%ld.%ld.%ld.%ld",(ntohl(a.s_addr)>>24)&0xFF,\
+ (ntohl(a.s_addr)>>16)&0xFF,\
+ (ntohl(a.s_addr)>>8)&0xFF,\
+ (ntohl(a.s_addr))&0xFF);
+
+#define dprint_ip(a) if (!fw_debug); else print_ip(a)
+
+static int add_entry __P((struct ip_fw_head *chainptr, struct ip_fw *frwl));
+static int del_entry __P((struct ip_fw_head *chainptr, u_short number));
+static int zero_entry __P((struct mbuf *m));
+static struct ip_fw *check_ipfw_struct __P((struct ip_fw *m));
+static struct ip_fw *check_ipfw_mbuf __P((struct mbuf *fw));
+static int ipopts_match __P((struct ip *ip, struct ip_fw *f));
+static int port_match __P((u_short *portptr, int nports, u_short port,
+ int range_flag));
+static int tcpflg_match __P((struct tcphdr *tcp, struct ip_fw *f));
+static int icmptype_match __P((struct icmp * icmp, struct ip_fw * f));
+static void ipfw_report __P((struct ip_fw *f, struct ip *ip,
+ struct ifnet *rif, struct ifnet *oif));
+
+#ifdef IPFIREWALL_MODULE
+static ip_fw_chk_t *old_chk_ptr;
+static ip_fw_ctl_t *old_ctl_ptr;
+#endif
+
+static int ip_fw_chk __P((struct ip **pip, int hlen,
+ struct ifnet *oif, int ignport, struct mbuf **m));
+static int ip_fw_ctl __P((int stage, struct mbuf **mm));
+
+static char err_prefix[] = "ip_fw_ctl:";
+
+/*
+ * Returns 1 if the port is matched by the vector, 0 otherwise
+ */
+static inline int
+port_match(u_short *portptr, int nports, u_short port, int range_flag)
+{
+ if (!nports)
+ return 1;
+ if (range_flag) {
+ if (portptr[0] <= port && port <= portptr[1]) {
+ return 1;
+ }
+ nports -= 2;
+ portptr += 2;
+ }
+ while (nports-- > 0) {
+ if (*portptr++ == port) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int
+tcpflg_match(struct tcphdr *tcp, struct ip_fw *f)
+{
+ u_char flg_set, flg_clr;
+
+ if ((f->fw_tcpf & IP_FW_TCPF_ESTAB) &&
+ (tcp->th_flags & (IP_FW_TCPF_RST | IP_FW_TCPF_ACK)))
+ return 1;
+
+ flg_set = tcp->th_flags & f->fw_tcpf;
+ flg_clr = tcp->th_flags & f->fw_tcpnf;
+
+ if (flg_set != f->fw_tcpf)
+ return 0;
+ if (flg_clr)
+ return 0;
+
+ return 1;
+}
+
+static int
+icmptype_match(struct icmp *icmp, struct ip_fw *f)
+{
+ int type;
+
+ if (!(f->fw_flg & IP_FW_F_ICMPBIT))
+ return(1);
+
+ type = icmp->icmp_type;
+
+ /* check for matching type in the bitmap */
+ if (type < IP_FW_ICMPTYPES_DIM * sizeof(unsigned) * 8 &&
+ (f->fw_icmptypes[type / (sizeof(unsigned) * 8)] &
+ (1U << (type % (8 * sizeof(unsigned))))))
+ return(1);
+
+ return(0); /* no match */
+}
+
+static int
+ipopts_match(struct ip *ip, struct ip_fw *f)
+{
+ register u_char *cp;
+ int opt, optlen, cnt;
+ u_char opts, nopts, nopts_sve;
+
+ cp = (u_char *)(ip + 1);
+ cnt = (ip->ip_hl << 2) - sizeof (struct ip);
+ opts = f->fw_ipopt;
+ nopts = nopts_sve = f->fw_ipnopt;
+
+ for (; cnt > 0; cnt -= optlen, cp += optlen) {
+ opt = cp[IPOPT_OPTVAL];
+ if (opt == IPOPT_EOL)
+ break;
+ if (opt == IPOPT_NOP)
+ optlen = 1;
+ else {
+ optlen = cp[IPOPT_OLEN];
+ if (optlen <= 0 || optlen > cnt) {
+ return 0; /*XXX*/
+ }
+ }
+ switch (opt) {
+
+ default:
+ break;
+
+ case IPOPT_LSRR:
+ opts &= ~IP_FW_IPOPT_LSRR;
+ nopts &= ~IP_FW_IPOPT_LSRR;
+ break;
+
+ case IPOPT_SSRR:
+ opts &= ~IP_FW_IPOPT_SSRR;
+ nopts &= ~IP_FW_IPOPT_SSRR;
+ break;
+
+ case IPOPT_RR:
+ opts &= ~IP_FW_IPOPT_RR;
+ nopts &= ~IP_FW_IPOPT_RR;
+ break;
+ case IPOPT_TS:
+ opts &= ~IP_FW_IPOPT_TS;
+ nopts &= ~IP_FW_IPOPT_TS;
+ break;
+ }
+ if (opts == nopts)
+ break;
+ }
+ if (opts == 0 && nopts == nopts_sve)
+ return 1;
+ else
+ return 0;
+}
+
+static inline int
+iface_match(struct ifnet *ifp, union ip_fw_if *ifu, int byname)
+{
+ /* Check by name or by IP address */
+ if (byname) {
+ /* Check unit number (-1 is wildcard) */
+ if (ifu->fu_via_if.unit != -1
+ && ifp->if_unit != ifu->fu_via_if.unit)
+ return(0);
+ /* Check name */
+ if (strncmp(ifp->if_name, ifu->fu_via_if.name, FW_IFNLEN))
+ return(0);
+ return(1);
+ } else if (ifu->fu_via_ip.s_addr != 0) { /* Zero == wildcard */
+ struct ifaddr *ia;
+
+ for (ia = ifp->if_addrlist; ia; ia = ia->ifa_next) {
+ if (ia->ifa_addr == NULL)
+ continue;
+ if (ia->ifa_addr->sa_family != AF_INET)
+ continue;
+ if (ifu->fu_via_ip.s_addr != ((struct sockaddr_in *)
+ (ia->ifa_addr))->sin_addr.s_addr)
+ continue;
+ return(1);
+ }
+ return(0);
+ }
+ return(1);
+}
+
+static void
+ipfw_report(struct ip_fw *f, struct ip *ip,
+ struct ifnet *rif, struct ifnet *oif)
+{
+ static int counter;
+ struct tcphdr *const tcp = (struct tcphdr *) ((u_long *) ip+ ip->ip_hl);
+ struct udphdr *const udp = (struct udphdr *) ((u_long *) ip+ ip->ip_hl);
+ struct icmp *const icmp = (struct icmp *) ((u_long *) ip + ip->ip_hl);
+ int count;
+
+ count = f ? f->fw_pcnt : ++counter;
+ if (fw_verbose_limit != 0 && count > fw_verbose_limit)
+ return;
+
+ /* Print command name */
+ printf("ipfw: %d ", f ? f->fw_number : -1);
+ if (!f)
+ printf("Refuse");
+ else
+ switch (f->fw_flg & IP_FW_F_COMMAND) {
+ case IP_FW_F_DENY:
+ printf("Deny");
+ break;
+ case IP_FW_F_REJECT:
+ if (f->fw_reject_code == IP_FW_REJECT_RST)
+ printf("Reset");
+ else
+ printf("Unreach");
+ break;
+ case IP_FW_F_ACCEPT:
+ printf("Accept");
+ break;
+ case IP_FW_F_COUNT:
+ printf("Count");
+ break;
+ case IP_FW_F_DIVERT:
+ printf("Divert %d", f->fw_divert_port);
+ break;
+ case IP_FW_F_TEE:
+ printf("Tee %d", f->fw_divert_port);
+ break;
+ case IP_FW_F_SKIPTO:
+ printf("SkipTo %d", f->fw_skipto_rule);
+ break;
+ default:
+ printf("UNKNOWN");
+ break;
+ }
+ printf(" ");
+
+ switch (ip->ip_p) {
+ case IPPROTO_TCP:
+ printf("TCP ");
+ print_ip(ip->ip_src);
+ if ((ip->ip_off & IP_OFFMASK) == 0)
+ printf(":%d ", ntohs(tcp->th_sport));
+ else
+ printf(" ");
+ print_ip(ip->ip_dst);
+ if ((ip->ip_off & IP_OFFMASK) == 0)
+ printf(":%d", ntohs(tcp->th_dport));
+ break;
+ case IPPROTO_UDP:
+ printf("UDP ");
+ print_ip(ip->ip_src);
+ if ((ip->ip_off & IP_OFFMASK) == 0)
+ printf(":%d ", ntohs(udp->uh_sport));
+ else
+ printf(" ");
+ print_ip(ip->ip_dst);
+ if ((ip->ip_off & IP_OFFMASK) == 0)
+ printf(":%d", ntohs(udp->uh_dport));
+ break;
+ case IPPROTO_ICMP:
+ printf("ICMP:%u.%u ", icmp->icmp_type, icmp->icmp_code);
+ print_ip(ip->ip_src);
+ printf(" ");
+ print_ip(ip->ip_dst);
+ break;
+ default:
+ printf("P:%d ", ip->ip_p);
+ print_ip(ip->ip_src);
+ printf(" ");
+ print_ip(ip->ip_dst);
+ break;
+ }
+ if (oif)
+ printf(" out via %s%d", oif->if_name, oif->if_unit);
+ else if (rif)
+ printf(" in via %s%d", rif->if_name, rif->if_unit);
+ if ((ip->ip_off & IP_OFFMASK))
+ printf(" Fragment = %d",ip->ip_off & IP_OFFMASK);
+ printf("\n");
+ if (fw_verbose_limit != 0 && count == fw_verbose_limit)
+ printf("ipfw: limit reached on rule #%d\n",
+ f ? f->fw_number : -1);
+}
+
+/*
+ * Parameters:
+ *
+ * ip Pointer to packet header (struct ip *)
+ * hlen Packet header length
+ * oif Outgoing interface, or NULL if packet is incoming
+ * ignport Ignore all divert/tee rules to this port (if non-zero)
+ * *m The packet; we set to NULL when/if we nuke it.
+ *
+ * Return value:
+ *
+ * 0 The packet is to be accepted and routed normally OR
+ * the packet was denied/rejected and has been dropped;
+ * in the latter case, *m is equal to NULL upon return.
+ * port Divert the packet to port.
+ */
+
+static int
+ip_fw_chk(struct ip **pip, int hlen,
+ struct ifnet *oif, int ignport, struct mbuf **m)
+{
+ struct ip_fw_chain *chain;
+ struct ip_fw *rule = NULL;
+ struct ip *ip = *pip;
+ struct ifnet *const rif = (*m)->m_pkthdr.rcvif;
+ u_short offset = (ip->ip_off & IP_OFFMASK);
+ u_short src_port, dst_port;
+
+ /*
+ * Go down the chain, looking for enlightment
+ */
+ for (chain=ip_fw_chain.lh_first; chain; chain = chain->chain.le_next) {
+ register struct ip_fw *const f = chain->rule;
+
+ /* Check direction inbound */
+ if (!oif && !(f->fw_flg & IP_FW_F_IN))
+ continue;
+
+ /* Check direction outbound */
+ if (oif && !(f->fw_flg & IP_FW_F_OUT))
+ continue;
+
+ /* Fragments */
+ if ((f->fw_flg & IP_FW_F_FRAG) && !(ip->ip_off & IP_OFFMASK))
+ continue;
+
+ /* If src-addr doesn't match, not this rule. */
+ if (((f->fw_flg & IP_FW_F_INVSRC) != 0) ^ ((ip->ip_src.s_addr
+ & f->fw_smsk.s_addr) != f->fw_src.s_addr))
+ continue;
+
+ /* If dest-addr doesn't match, not this rule. */
+ if (((f->fw_flg & IP_FW_F_INVDST) != 0) ^ ((ip->ip_dst.s_addr
+ & f->fw_dmsk.s_addr) != f->fw_dst.s_addr))
+ continue;
+
+ /* Interface check */
+ if ((f->fw_flg & IF_FW_F_VIAHACK) == IF_FW_F_VIAHACK) {
+ struct ifnet *const iface = oif ? oif : rif;
+
+ /* Backwards compatibility hack for "via" */
+ if (!iface || !iface_match(iface,
+ &f->fw_in_if, f->fw_flg & IP_FW_F_OIFNAME))
+ continue;
+ } else {
+ /* Check receive interface */
+ if ((f->fw_flg & IP_FW_F_IIFACE)
+ && (!rif || !iface_match(rif,
+ &f->fw_in_if, f->fw_flg & IP_FW_F_IIFNAME)))
+ continue;
+ /* Check outgoing interface */
+ if ((f->fw_flg & IP_FW_F_OIFACE)
+ && (!oif || !iface_match(oif,
+ &f->fw_out_if, f->fw_flg & IP_FW_F_OIFNAME)))
+ continue;
+ }
+
+ /* Check IP options */
+ if (f->fw_ipopt != f->fw_ipnopt && !ipopts_match(ip, f))
+ continue;
+
+ /* Check protocol; if wildcard, match */
+ if (f->fw_prot == IPPROTO_IP)
+ goto got_match;
+
+ /* If different, don't match */
+ if (ip->ip_p != f->fw_prot)
+ continue;
+
+#define PULLUP_TO(len) do { \
+ if ((*m)->m_len < (len) \
+ && (*m = m_pullup(*m, (len))) == 0) { \
+ goto bogusfrag; \
+ } \
+ *pip = ip = mtod(*m, struct ip *); \
+ offset = (ip->ip_off & IP_OFFMASK); \
+ } while (0)
+
+ /* Protocol specific checks */
+ switch (ip->ip_p) {
+ case IPPROTO_TCP:
+ {
+ struct tcphdr *tcp;
+
+ if (offset == 1) /* cf. RFC 1858 */
+ goto bogusfrag;
+ if (offset != 0) {
+ /*
+ * TCP flags and ports aren't available in this
+ * packet -- if this rule specified either one,
+ * we consider the rule a non-match.
+ */
+ if (f->fw_nports != 0 ||
+ f->fw_tcpf != f->fw_tcpnf)
+ continue;
+
+ break;
+ }
+ PULLUP_TO(hlen + 14);
+ tcp = (struct tcphdr *) ((u_long *)ip + ip->ip_hl);
+ if (f->fw_tcpf != f->fw_tcpnf && !tcpflg_match(tcp, f))
+ continue;
+ src_port = ntohs(tcp->th_sport);
+ dst_port = ntohs(tcp->th_dport);
+ goto check_ports;
+ }
+
+ case IPPROTO_UDP:
+ {
+ struct udphdr *udp;
+
+ if (offset != 0) {
+ /*
+ * Port specification is unavailable -- if this
+ * rule specifies a port, we consider the rule
+ * a non-match.
+ */
+ if (f->fw_nports != 0)
+ continue;
+
+ break;
+ }
+ PULLUP_TO(hlen + 4);
+ udp = (struct udphdr *) ((u_long *)ip + ip->ip_hl);
+ src_port = ntohs(udp->uh_sport);
+ dst_port = ntohs(udp->uh_dport);
+check_ports:
+ if (!port_match(&f->fw_pts[0],
+ IP_FW_GETNSRCP(f), src_port,
+ f->fw_flg & IP_FW_F_SRNG))
+ continue;
+ if (!port_match(&f->fw_pts[IP_FW_GETNSRCP(f)],
+ IP_FW_GETNDSTP(f), dst_port,
+ f->fw_flg & IP_FW_F_DRNG))
+ continue;
+ break;
+ }
+
+ case IPPROTO_ICMP:
+ {
+ struct icmp *icmp;
+
+ if (offset != 0) /* Type isn't valid */
+ break;
+ PULLUP_TO(hlen + 2);
+ icmp = (struct icmp *) ((u_long *)ip + ip->ip_hl);
+ if (!icmptype_match(icmp, f))
+ continue;
+ break;
+ }
+#undef PULLUP_TO
+
+bogusfrag:
+ if (fw_verbose)
+ ipfw_report(NULL, ip, rif, oif);
+ goto dropit;
+ }
+
+got_match:
+ /* Ignore divert/tee rule if socket port is "ignport" */
+ switch (f->fw_flg & IP_FW_F_COMMAND) {
+ case IP_FW_F_DIVERT:
+ case IP_FW_F_TEE:
+ if (f->fw_divert_port == ignport)
+ continue; /* ignore this rule */
+ break;
+ }
+
+ /* Update statistics */
+ f->fw_pcnt += 1;
+ f->fw_bcnt += ip->ip_len;
+ f->timestamp = rtems_bsdnet_seconds_since_boot();
+
+ /* Log to console if desired */
+ if ((f->fw_flg & IP_FW_F_PRN) && fw_verbose)
+ ipfw_report(f, ip, rif, oif);
+
+ /* Take appropriate action */
+ switch (f->fw_flg & IP_FW_F_COMMAND) {
+ case IP_FW_F_ACCEPT:
+ return(0);
+ case IP_FW_F_COUNT:
+ continue;
+ case IP_FW_F_DIVERT:
+ return(f->fw_divert_port);
+ case IP_FW_F_TEE:
+ /*
+ * XXX someday tee packet here, but beware that you
+ * can't use m_copym() or m_copypacket() because
+ * the divert input routine modifies the mbuf
+ * (and these routines only increment reference
+ * counts in the case of mbuf clusters), so need
+ * to write custom routine.
+ */
+ continue;
+ case IP_FW_F_SKIPTO:
+#ifdef DIAGNOSTIC
+ while (chain->chain.le_next
+ && chain->chain.le_next->rule->fw_number
+ < f->fw_skipto_rule)
+#else
+ while (chain->chain.le_next->rule->fw_number
+ < f->fw_skipto_rule)
+#endif
+ chain = chain->chain.le_next;
+ continue;
+ }
+
+ /* Deny/reject this packet using this rule */
+ rule = f;
+ break;
+ }
+
+#ifdef DIAGNOSTIC
+ /* Rule 65535 should always be there and should always match */
+ if (!chain)
+ panic("ip_fw: chain");
+#endif
+
+ /*
+ * At this point, we're going to drop the packet.
+ * Send a reject notice if all of the following are true:
+ *
+ * - The packet matched a reject rule
+ * - The packet is not an ICMP packet
+ * - The packet is not a multicast or broadcast packet
+ */
+ if ((rule->fw_flg & IP_FW_F_COMMAND) == IP_FW_F_REJECT
+ && ip->ip_p != IPPROTO_ICMP
+ && !((*m)->m_flags & (M_BCAST|M_MCAST))
+ && !IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
+ switch (rule->fw_reject_code) {
+ case IP_FW_REJECT_RST:
+ {
+ struct tcphdr *const tcp =
+ (struct tcphdr *) ((u_long *)ip + ip->ip_hl);
+ struct tcpiphdr ti, *const tip = (struct tcpiphdr *) ip;
+
+ if (offset != 0 || (tcp->th_flags & TH_RST))
+ break;
+ ti.ti_i = *((struct ipovly *) ip);
+ ti.ti_t = *tcp;
+ bcopy(&ti, ip, sizeof(ti));
+ NTOHL(tip->ti_seq);
+ NTOHL(tip->ti_ack);
+ tip->ti_len = ip->ip_len - hlen - (tip->ti_off << 2);
+ if (tcp->th_flags & TH_ACK) {
+ tcp_respond(NULL, tip, *m,
+ (tcp_seq)0, ntohl(tcp->th_ack), TH_RST);
+ } else {
+ if (tcp->th_flags & TH_SYN)
+ tip->ti_len++;
+ tcp_respond(NULL, tip, *m, tip->ti_seq
+ + tip->ti_len, (tcp_seq)0, TH_RST|TH_ACK);
+ }
+ *m = NULL;
+ break;
+ }
+ default: /* Send an ICMP unreachable using code */
+ icmp_error(*m, ICMP_UNREACH,
+ rule->fw_reject_code, 0L, 0);
+ *m = NULL;
+ break;
+ }
+ }
+
+dropit:
+ /*
+ * Finally, drop the packet.
+ */
+ if (*m) {
+ m_freem(*m);
+ *m = NULL;
+ }
+ return(0);
+}
+
+static int
+add_entry(struct ip_fw_head *chainptr, struct ip_fw *frwl)
+{
+ struct ip_fw *ftmp = 0;
+ struct ip_fw_chain *fwc = 0, *fcp, *fcpl = 0;
+ u_short nbr = 0;
+ int s;
+
+ fwc = malloc(sizeof *fwc, M_IPFW, M_DONTWAIT);
+ ftmp = malloc(sizeof *ftmp, M_IPFW, M_DONTWAIT);
+ if (!fwc || !ftmp) {
+ dprintf(("%s malloc said no\n", err_prefix));
+ if (fwc) free(fwc, M_IPFW);
+ if (ftmp) free(ftmp, M_IPFW);
+ return (ENOSPC);
+ }
+
+ bcopy(frwl, ftmp, sizeof(struct ip_fw));
+ ftmp->fw_in_if.fu_via_if.name[FW_IFNLEN - 1] = '\0';
+ ftmp->fw_pcnt = 0L;
+ ftmp->fw_bcnt = 0L;
+ fwc->rule = ftmp;
+
+ s = splnet();
+
+ if (!chainptr->lh_first) {
+ LIST_INSERT_HEAD(chainptr, fwc, chain);
+ splx(s);
+ return(0);
+ } else if (ftmp->fw_number == (u_short)-1) {
+ if (fwc) free(fwc, M_IPFW);
+ if (ftmp) free(ftmp, M_IPFW);
+ splx(s);
+ dprintf(("%s bad rule number\n", err_prefix));
+ return (EINVAL);
+ }
+
+ /* If entry number is 0, find highest numbered rule and add 100 */
+ if (ftmp->fw_number == 0) {
+ for (fcp = chainptr->lh_first; fcp; fcp = fcp->chain.le_next) {
+ if (fcp->rule->fw_number != (u_short)-1)
+ nbr = fcp->rule->fw_number;
+ else
+ break;
+ }
+ if (nbr < (u_short)-1 - 100)
+ nbr += 100;
+ ftmp->fw_number = nbr;
+ }
+
+ /* Got a valid number; now insert it, keeping the list ordered */
+ for (fcp = chainptr->lh_first; fcp; fcp = fcp->chain.le_next) {
+ if (fcp->rule->fw_number > ftmp->fw_number) {
+ if (fcpl) {
+ LIST_INSERT_AFTER(fcpl, fwc, chain);
+ } else {
+ LIST_INSERT_HEAD(chainptr, fwc, chain);
+ }
+ break;
+ } else {
+ fcpl = fcp;
+ }
+ }
+
+ splx(s);
+ return (0);
+}
+
+static int
+del_entry(struct ip_fw_head *chainptr, u_short number)
+{
+ struct ip_fw_chain *fcp;
+ int s;
+
+ s = splnet();
+
+ fcp = chainptr->lh_first;
+ if (number != (u_short)-1) {
+ for (; fcp; fcp = fcp->chain.le_next) {
+ if (fcp->rule->fw_number == number) {
+ LIST_REMOVE(fcp, chain);
+ splx(s);
+ free(fcp->rule, M_IPFW);
+ free(fcp, M_IPFW);
+ return 0;
+ }
+ }
+ }
+
+ splx(s);
+ return (EINVAL);
+}
+
+static int
+zero_entry(struct mbuf *m)
+{
+ struct ip_fw *frwl;
+ struct ip_fw_chain *fcp;
+ int s;
+
+ if (m) {
+ if (m->m_len != sizeof(struct ip_fw))
+ return(EINVAL);
+ frwl = mtod(m, struct ip_fw *);
+ }
+ else
+ frwl = NULL;
+
+ /*
+ * It's possible to insert multiple chain entries with the
+ * same number, so we don't stop after finding the first
+ * match if zeroing a specific entry.
+ */
+ s = splnet();
+ for (fcp = ip_fw_chain.lh_first; fcp; fcp = fcp->chain.le_next)
+ if (!frwl || frwl->fw_number == fcp->rule->fw_number) {
+ fcp->rule->fw_bcnt = fcp->rule->fw_pcnt = 0;
+ fcp->rule->timestamp = 0;
+ }
+ splx(s);
+
+ if (fw_verbose) {
+ if (frwl)
+ printf("ipfw: Entry %d cleared.\n", frwl->fw_number);
+ else
+ printf("ipfw: Accounting cleared.\n");
+ }
+
+ return(0);
+}
+
+static struct ip_fw *
+check_ipfw_mbuf(struct mbuf *m)
+{
+ /* Check length */
+ if (m->m_len != sizeof(struct ip_fw)) {
+ dprintf(("%s len=%d, want %d\n", err_prefix, m->m_len,
+ (int)sizeof(struct ip_fw)));
+ return (NULL);
+ }
+ return(check_ipfw_struct(mtod(m, struct ip_fw *)));
+}
+
+static struct ip_fw *
+check_ipfw_struct(struct ip_fw *frwl)
+{
+ /* Check for invalid flag bits */
+ if ((frwl->fw_flg & ~IP_FW_F_MASK) != 0) {
+ dprintf(("%s undefined flag bits set (flags=%x)\n",
+ err_prefix, frwl->fw_flg));
+ return (NULL);
+ }
+ /* Must apply to incoming or outgoing (or both) */
+ if (!(frwl->fw_flg & (IP_FW_F_IN | IP_FW_F_OUT))) {
+ dprintf(("%s neither in nor out\n", err_prefix));
+ return (NULL);
+ }
+ /* Empty interface name is no good */
+ if (((frwl->fw_flg & IP_FW_F_IIFNAME)
+ && !*frwl->fw_in_if.fu_via_if.name)
+ || ((frwl->fw_flg & IP_FW_F_OIFNAME)
+ && !*frwl->fw_out_if.fu_via_if.name)) {
+ dprintf(("%s empty interface name\n", err_prefix));
+ return (NULL);
+ }
+ /* Sanity check interface matching */
+ if ((frwl->fw_flg & IF_FW_F_VIAHACK) == IF_FW_F_VIAHACK) {
+ ; /* allow "via" backwards compatibility */
+ } else if ((frwl->fw_flg & IP_FW_F_IN)
+ && (frwl->fw_flg & IP_FW_F_OIFACE)) {
+ dprintf(("%s outgoing interface check on incoming\n",
+ err_prefix));
+ return (NULL);
+ }
+ /* Sanity check port ranges */
+ if ((frwl->fw_flg & IP_FW_F_SRNG) && IP_FW_GETNSRCP(frwl) < 2) {
+ dprintf(("%s src range set but n_src_p=%d\n",
+ err_prefix, IP_FW_GETNSRCP(frwl)));
+ return (NULL);
+ }
+ if ((frwl->fw_flg & IP_FW_F_DRNG) && IP_FW_GETNDSTP(frwl) < 2) {
+ dprintf(("%s dst range set but n_dst_p=%d\n",
+ err_prefix, IP_FW_GETNDSTP(frwl)));
+ return (NULL);
+ }
+ if (IP_FW_GETNSRCP(frwl) + IP_FW_GETNDSTP(frwl) > IP_FW_MAX_PORTS) {
+ dprintf(("%s too many ports (%d+%d)\n",
+ err_prefix, IP_FW_GETNSRCP(frwl), IP_FW_GETNDSTP(frwl)));
+ return (NULL);
+ }
+ /*
+ * Protocols other than TCP/UDP don't use port range
+ */
+ if ((frwl->fw_prot != IPPROTO_TCP) &&
+ (frwl->fw_prot != IPPROTO_UDP) &&
+ (IP_FW_GETNSRCP(frwl) || IP_FW_GETNDSTP(frwl))) {
+ dprintf(("%s port(s) specified for non TCP/UDP rule\n",
+ err_prefix));
+ return(NULL);
+ }
+
+ /*
+ * Rather than modify the entry to make such entries work,
+ * we reject this rule and require user level utilities
+ * to enforce whatever policy they deem appropriate.
+ */
+ if ((frwl->fw_src.s_addr & (~frwl->fw_smsk.s_addr)) ||
+ (frwl->fw_dst.s_addr & (~frwl->fw_dmsk.s_addr))) {
+ dprintf(("%s rule never matches\n", err_prefix));
+ return(NULL);
+ }
+
+ if ((frwl->fw_flg & IP_FW_F_FRAG) &&
+ (frwl->fw_prot == IPPROTO_UDP || frwl->fw_prot == IPPROTO_TCP)) {
+ if (frwl->fw_nports) {
+ dprintf(("%s cannot mix 'frag' and ports\n", err_prefix));
+ return(NULL);
+ }
+ if (frwl->fw_prot == IPPROTO_TCP &&
+ frwl->fw_tcpf != frwl->fw_tcpnf) {
+ dprintf(("%s cannot mix 'frag' with TCP flags\n", err_prefix));
+ return(NULL);
+ }
+ }
+
+ /* Check command specific stuff */
+ switch (frwl->fw_flg & IP_FW_F_COMMAND)
+ {
+ case IP_FW_F_REJECT:
+ if (frwl->fw_reject_code >= 0x100
+ && !(frwl->fw_prot == IPPROTO_TCP
+ && frwl->fw_reject_code == IP_FW_REJECT_RST)) {
+ dprintf(("%s unknown reject code\n", err_prefix));
+ return(NULL);
+ }
+ break;
+ case IP_FW_F_DIVERT: /* Diverting to port zero is invalid */
+ case IP_FW_F_TEE:
+ if (frwl->fw_divert_port == 0) {
+ dprintf(("%s can't divert to port 0\n", err_prefix));
+ return (NULL);
+ }
+ break;
+ case IP_FW_F_DENY:
+ case IP_FW_F_ACCEPT:
+ case IP_FW_F_COUNT:
+ case IP_FW_F_SKIPTO:
+ break;
+ default:
+ dprintf(("%s invalid command\n", err_prefix));
+ return(NULL);
+ }
+
+ return frwl;
+}
+
+static int
+ip_fw_ctl(int stage, struct mbuf **mm)
+{
+ int error;
+ struct mbuf *m;
+
+ if (stage == IP_FW_GET) {
+ struct ip_fw_chain *fcp = ip_fw_chain.lh_first;
+ *mm = m = m_get(M_WAIT, MT_SOOPTS);
+ for (; fcp; fcp = fcp->chain.le_next) {
+ memcpy(m->m_data, fcp->rule, sizeof *(fcp->rule));
+ m->m_len = sizeof *(fcp->rule);
+ m->m_next = m_get(M_WAIT, MT_SOOPTS);
+ m = m->m_next;
+ m->m_len = 0;
+ }
+ return (0);
+ }
+ m = *mm;
+ /* only allow get calls if secure mode > 2 */
+ if (securelevel > 2) {
+ if (m) (void)m_free(m);
+ return(EPERM);
+ }
+ if (stage == IP_FW_FLUSH) {
+ while (ip_fw_chain.lh_first != NULL &&
+ ip_fw_chain.lh_first->rule->fw_number != (u_short)-1) {
+ struct ip_fw_chain *fcp = ip_fw_chain.lh_first;
+ int s = splnet();
+ LIST_REMOVE(ip_fw_chain.lh_first, chain);
+ splx(s);
+ free(fcp->rule, M_IPFW);
+ free(fcp, M_IPFW);
+ }
+ if (m) (void)m_free(m);
+ return (0);
+ }
+ if (stage == IP_FW_ZERO) {
+ error = zero_entry(m);
+ if (m) (void)m_free(m);
+ return (error);
+ }
+ if (m == NULL) {
+ printf("%s NULL mbuf ptr\n", err_prefix);
+ return (EINVAL);
+ }
+
+ if (stage == IP_FW_ADD) {
+ struct ip_fw *frwl = check_ipfw_mbuf(m);
+
+ if (!frwl)
+ error = EINVAL;
+ else
+ error = add_entry(&ip_fw_chain, frwl);
+ if (m) (void)m_free(m);
+ return error;
+ }
+ if (stage == IP_FW_DEL) {
+ if (m->m_len != sizeof(struct ip_fw)) {
+ dprintf(("%s len=%d, want %d\n", err_prefix, m->m_len,
+ (int)sizeof(struct ip_fw)));
+ error = EINVAL;
+ } else if (mtod(m, struct ip_fw *)->fw_number == (u_short)-1) {
+ dprintf(("%s can't delete rule 65535\n", err_prefix));
+ error = EINVAL;
+ } else
+ error = del_entry(&ip_fw_chain,
+ mtod(m, struct ip_fw *)->fw_number);
+ if (m) (void)m_free(m);
+ return error;
+ }
+
+ dprintf(("%s unknown request %d\n", err_prefix, stage));
+ if (m) (void)m_free(m);
+ return (EINVAL);
+}
+
+void
+ip_fw_init(void)
+{
+ struct ip_fw default_rule;
+
+ ip_fw_chk_ptr = ip_fw_chk;
+ ip_fw_ctl_ptr = ip_fw_ctl;
+ LIST_INIT(&ip_fw_chain);
+
+ bzero(&default_rule, sizeof default_rule);
+ default_rule.fw_prot = IPPROTO_IP;
+ default_rule.fw_number = (u_short)-1;
+#ifdef IPFIREWALL_DEFAULT_TO_ACCEPT
+ default_rule.fw_flg |= IP_FW_F_ACCEPT;
+#else
+ default_rule.fw_flg |= IP_FW_F_DENY;
+#endif
+ default_rule.fw_flg |= IP_FW_F_IN | IP_FW_F_OUT;
+ if (check_ipfw_struct(&default_rule) == NULL ||
+ add_entry(&ip_fw_chain, &default_rule))
+ panic(__FUNCTION__);
+
+ printf("IP packet filtering initialized, "
+#ifdef IPDIVERT
+ "divert enabled, ");
+#else
+ "divert disabled, ");
+#endif
+#ifdef IPFIREWALL_DEFAULT_TO_ACCEPT
+ printf("default to accept, ");
+#endif
+#ifndef IPFIREWALL_VERBOSE
+ printf("logging disabled\n");
+#else
+ if (fw_verbose_limit == 0)
+ printf("unlimited logging\n");
+ else
+ printf("logging limited to %d packets/entry\n",
+ fw_verbose_limit);
+#endif
+}
+
+#ifdef IPFIREWALL_MODULE
+
+#include <sys/exec.h>
+#include <sys/sysent.h>
+#include <sys/lkm.h>
+
+MOD_MISC(ipfw);
+
+static int
+ipfw_load(struct lkm_table *lkmtp, int cmd)
+{
+ int s=splnet();
+
+ old_chk_ptr = ip_fw_chk_ptr;
+ old_ctl_ptr = ip_fw_ctl_ptr;
+
+ ip_fw_init();
+ splx(s);
+ return 0;
+}
+
+static int
+ipfw_unload(struct lkm_table *lkmtp, int cmd)
+{
+ int s=splnet();
+
+ ip_fw_chk_ptr = old_chk_ptr;
+ ip_fw_ctl_ptr = old_ctl_ptr;
+
+ while (ip_fw_chain.lh_first != NULL) {
+ struct ip_fw_chain *fcp = ip_fw_chain.lh_first;
+ LIST_REMOVE(ip_fw_chain.lh_first, chain);
+ free(fcp->rule, M_IPFW);
+ free(fcp, M_IPFW);
+ }
+
+ splx(s);
+ printf("IP firewall unloaded\n");
+ return 0;
+}
+
+int
+ipfw_mod(struct lkm_table *lkmtp, int cmd, int ver)
+{
+ DISPATCH(lkmtp, cmd, ver, ipfw_load, ipfw_unload, lkm_nullcmd);
+}
+#endif
diff --git a/cpukit/libnetworking/netinet/ip_fw.h b/cpukit/libnetworking/netinet/ip_fw.h
new file mode 100644
index 0000000000..f90deb96c2
--- /dev/null
+++ b/cpukit/libnetworking/netinet/ip_fw.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 1993 Daniel Boulet
+ * Copyright (c) 1994 Ugen J.S.Antsilevich
+ *
+ * Redistribution and use in source forms, with and without modification,
+ * are permitted provided that this entire comment appears intact.
+ *
+ * Redistribution in binary form may occur without any restrictions.
+ * Obviously, it would be nice if you gave credit where credit is due
+ * but requiring it would be too onerous.
+ *
+ * This software is provided ``AS IS'' without any warranties of any kind.
+ *
+ * $Id$
+ */
+
+#ifndef _IP_FW_H
+#define _IP_FW_H
+
+#include <net/if.h>
+
+/*
+ * This union structure identifies an interface, either explicitly
+ * by name or implicitly by IP address. The flags IP_FW_F_IIFNAME
+ * and IP_FW_F_OIFNAME say how to interpret this structure. An
+ * interface unit number of -1 matches any unit number, while an
+ * IP address of 0.0.0.0 indicates matches any interface.
+ *
+ * The receive and transmit interfaces are only compared against the
+ * the packet if the corresponding bit (IP_FW_F_IIFACE or IP_FW_F_OIFACE)
+ * is set. Note some packets lack a receive or transmit interface
+ * (in which case the missing "interface" never matches).
+ */
+
+union ip_fw_if {
+ struct in_addr fu_via_ip; /* Specified by IP address */
+ struct { /* Specified by interface name */
+#define FW_IFNLEN IFNAMSIZ
+ char name[FW_IFNLEN];
+ short unit; /* -1 means match any unit */
+ } fu_via_if;
+};
+
+/*
+ * Format of an IP firewall descriptor
+ *
+ * fw_src, fw_dst, fw_smsk, fw_dmsk are always stored in network byte order.
+ * fw_flg and fw_n*p are stored in host byte order (of course).
+ * Port numbers are stored in HOST byte order.
+ * Warning: setsockopt() will fail if sizeof(struct ip_fw) > MLEN (108)
+ */
+
+struct ip_fw {
+ u_long fw_pcnt,fw_bcnt; /* Packet and byte counters */
+ struct in_addr fw_src, fw_dst; /* Source and destination IP addr */
+ struct in_addr fw_smsk, fw_dmsk; /* Mask for src and dest IP addr */
+ u_short fw_number; /* Rule number */
+ u_short fw_flg; /* Flags word */
+#define IP_FW_MAX_PORTS 10 /* A reasonable maximum */
+ u_short fw_pts[IP_FW_MAX_PORTS]; /* Array of port numbers to match */
+ u_char fw_ipopt,fw_ipnopt; /* IP options set/unset */
+ u_char fw_tcpf,fw_tcpnf; /* TCP flags set/unset */
+#define IP_FW_ICMPTYPES_DIM (32 / (sizeof(unsigned) * 8))
+ unsigned fw_icmptypes[IP_FW_ICMPTYPES_DIM]; /* ICMP types bitmap */
+ long timestamp; /* timestamp (tv_sec) of last match */
+ union ip_fw_if fw_in_if, fw_out_if; /* Incoming and outgoing interfaces */
+ union {
+ u_short fu_divert_port; /* Divert/tee port (options IPDIVERT) */
+ u_short fu_skipto_rule; /* SKIPTO command rule number */
+ u_short fu_reject_code; /* REJECT response code */
+ } fw_un;
+ u_char fw_prot; /* IP protocol */
+ u_char fw_nports; /* N'of src ports and # of dst ports */
+ /* in ports array (dst ports follow */
+ /* src ports; max of 10 ports in all; */
+ /* count of 0 means match all ports) */
+};
+
+#define IP_FW_GETNSRCP(rule) ((rule)->fw_nports & 0x0f)
+#define IP_FW_SETNSRCP(rule, n) do { \
+ (rule)->fw_nports &= ~0x0f; \
+ (rule)->fw_nports |= (n); \
+ } while (0)
+#define IP_FW_GETNDSTP(rule) ((rule)->fw_nports >> 4)
+#define IP_FW_SETNDSTP(rule, n) do { \
+ (rule)->fw_nports &= ~0xf0; \
+ (rule)->fw_nports |= (n) << 4;\
+ } while (0)
+
+#define fw_divert_port fw_un.fu_divert_port
+#define fw_skipto_rule fw_un.fu_skipto_rule
+#define fw_reject_code fw_un.fu_reject_code
+
+struct ip_fw_chain {
+ LIST_ENTRY(ip_fw_chain) chain;
+ struct ip_fw *rule;
+};
+
+/*
+ * Values for "flags" field .
+ */
+#define IP_FW_F_IN 0x0001 /* Check inbound packets */
+#define IP_FW_F_OUT 0x0002 /* Check outbound packets */
+#define IP_FW_F_IIFACE 0x0004 /* Apply inbound interface test */
+#define IP_FW_F_OIFACE 0x0008 /* Apply outbound interface test */
+
+#define IP_FW_F_COMMAND 0x0070 /* Mask for type of chain entry: */
+#define IP_FW_F_DENY 0x0000 /* This is a deny rule */
+#define IP_FW_F_REJECT 0x0010 /* Deny and send a response packet */
+#define IP_FW_F_ACCEPT 0x0020 /* This is an accept rule */
+#define IP_FW_F_COUNT 0x0030 /* This is a count rule */
+#define IP_FW_F_DIVERT 0x0040 /* This is a divert rule */
+#define IP_FW_F_TEE 0x0050 /* This is a tee rule */
+#define IP_FW_F_SKIPTO 0x0060 /* This is a skipto rule */
+
+#define IP_FW_F_PRN 0x0080 /* Print if this rule matches */
+
+#define IP_FW_F_SRNG 0x0100 /* The first two src ports are a min *
+ * and max range (stored in host byte *
+ * order). */
+
+#define IP_FW_F_DRNG 0x0200 /* The first two dst ports are a min *
+ * and max range (stored in host byte *
+ * order). */
+
+#define IP_FW_F_IIFNAME 0x0400 /* In interface by name/unit (not IP) */
+#define IP_FW_F_OIFNAME 0x0800 /* Out interface by name/unit (not IP) */
+
+#define IP_FW_F_INVSRC 0x1000 /* Invert sense of src check */
+#define IP_FW_F_INVDST 0x2000 /* Invert sense of dst check */
+
+#define IP_FW_F_FRAG 0x4000 /* Fragment */
+
+#define IP_FW_F_ICMPBIT 0x8000 /* ICMP type bitmap is valid */
+
+#define IP_FW_F_MASK 0xFFFF /* All possible flag bits mask */
+
+/*
+ * For backwards compatibility with rules specifying "via iface" but
+ * not restricted to only "in" or "out" packets, we define this combination
+ * of bits to represent this configuration.
+ */
+
+#define IF_FW_F_VIAHACK (IP_FW_F_IN|IP_FW_F_OUT|IP_FW_F_IIFACE|IP_FW_F_OIFACE)
+
+/*
+ * Definitions for REJECT response codes.
+ * Values less than 256 correspond to ICMP unreachable codes.
+ */
+#define IP_FW_REJECT_RST 0x0100 /* TCP packets: send RST */
+
+/*
+ * Definitions for IP option names.
+ */
+#define IP_FW_IPOPT_LSRR 0x01
+#define IP_FW_IPOPT_SSRR 0x02
+#define IP_FW_IPOPT_RR 0x04
+#define IP_FW_IPOPT_TS 0x08
+
+/*
+ * Definitions for TCP flags.
+ */
+#define IP_FW_TCPF_FIN TH_FIN
+#define IP_FW_TCPF_SYN TH_SYN
+#define IP_FW_TCPF_RST TH_RST
+#define IP_FW_TCPF_PSH TH_PUSH
+#define IP_FW_TCPF_ACK TH_ACK
+#define IP_FW_TCPF_URG TH_URG
+#define IP_FW_TCPF_ESTAB 0x40
+
+/*
+ * Main firewall chains definitions and global var's definitions.
+ */
+#ifdef _KERNEL
+
+/*
+ * Function definitions.
+ */
+void ip_fw_init(void);
+
+#endif /* _KERNEL */
+
+#endif /* _IP_FW_H */
diff --git a/cpukit/libnetworking/netinet/ip_icmp.c b/cpukit/libnetworking/netinet/ip_icmp.c
new file mode 100644
index 0000000000..44088ab713
--- /dev/null
+++ b/cpukit/libnetworking/netinet/ip_icmp.c
@@ -0,0 +1,711 @@
+/*
+ * Copyright (c) 1982, 1986, 1988, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)ip_icmp.c 8.2 (Berkeley) 1/4/94
+ * $Id$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/route.h>
+
+#define _IP_VHL
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/ip_var.h>
+#include <netinet/icmp_var.h>
+
+/*
+ * ICMP routines: error generation, receive packet processing, and
+ * routines to turnaround packets back to the originator, and
+ * host table maintenance routines.
+ */
+
+ struct icmpstat icmpstat;
+SYSCTL_STRUCT(_net_inet_icmp, ICMPCTL_STATS, stats, CTLFLAG_RD,
+ &icmpstat, icmpstat, "");
+
+static int icmpmaskrepl = 0;
+SYSCTL_INT(_net_inet_icmp, ICMPCTL_MASKREPL, maskrepl, CTLFLAG_RW,
+ &icmpmaskrepl, 0, "");
+
+static int icmpbmcastecho = 1;
+SYSCTL_INT(_net_inet_icmp, OID_AUTO, bmcastecho, CTLFLAG_RW, &icmpbmcastecho,
+ 0, "");
+
+/* #define ICMPPRINTFS 1 */
+#ifdef ICMPPRINTFS
+int icmpprintfs = 0;
+#endif
+
+static void icmp_reflect __P((struct mbuf *));
+static void icmp_send __P((struct mbuf *, struct mbuf *));
+static int ip_next_mtu __P((int, int));
+
+extern struct protosw inetsw[];
+
+/*
+ * Generate an error packet of type error
+ * in response to bad packet ip.
+ */
+void
+icmp_error(n, type, code, dest, destifp)
+ struct mbuf *n;
+ int type, code;
+ n_long dest;
+ struct ifnet *destifp;
+{
+ register struct ip *oip = mtod(n, struct ip *), *nip;
+ register unsigned oiplen = IP_VHL_HL(oip->ip_vhl) << 2;
+ register struct icmp *icp;
+ register struct mbuf *m;
+ unsigned icmplen;
+
+#ifdef ICMPPRINTFS
+ if (icmpprintfs)
+ printf("icmp_error(%p, %x, %d)\n", oip, type, code);
+#endif
+ if (type != ICMP_REDIRECT)
+ icmpstat.icps_error++;
+ /*
+ * Don't send error if not the first fragment of message.
+ * Don't error if the old packet protocol was ICMP
+ * error message, only known informational types.
+ */
+ if (oip->ip_off &~ (IP_MF|IP_DF))
+ goto freeit;
+ if (oip->ip_p == IPPROTO_ICMP && type != ICMP_REDIRECT &&
+ n->m_len >= oiplen + ICMP_MINLEN &&
+ !ICMP_INFOTYPE(((struct icmp *)((caddr_t)oip + oiplen))->icmp_type)) {
+ icmpstat.icps_oldicmp++;
+ goto freeit;
+ }
+ /* Don't send error in response to a multicast or broadcast packet */
+ if (n->m_flags & (M_BCAST|M_MCAST))
+ goto freeit;
+ /*
+ * First, formulate icmp message
+ */
+ m = m_gethdr(M_DONTWAIT, MT_HEADER);
+ if (m == NULL)
+ goto freeit;
+ icmplen = oiplen + min(8, oip->ip_len);
+ m->m_len = icmplen + ICMP_MINLEN;
+ MH_ALIGN(m, m->m_len);
+ icp = mtod(m, struct icmp *);
+ if ((u_int)type > ICMP_MAXTYPE)
+ panic("icmp_error");
+ icmpstat.icps_outhist[type]++;
+ icp->icmp_type = type;
+ if (type == ICMP_REDIRECT)
+ icp->icmp_gwaddr.s_addr = dest;
+ else {
+ icp->icmp_void = 0;
+ /*
+ * The following assignments assume an overlay with the
+ * zeroed icmp_void field.
+ */
+ if (type == ICMP_PARAMPROB) {
+ icp->icmp_pptr = code;
+ code = 0;
+ } else if (type == ICMP_UNREACH &&
+ code == ICMP_UNREACH_NEEDFRAG && destifp) {
+ icp->icmp_nextmtu = htons(destifp->if_mtu);
+ }
+ }
+
+ icp->icmp_code = code;
+ bcopy((caddr_t)oip, (caddr_t)&icp->icmp_ip, icmplen);
+ nip = &icp->icmp_ip;
+ nip->ip_len = htons((u_short)(nip->ip_len + oiplen));
+
+ /*
+ * Now, copy old ip header (without options)
+ * in front of icmp message.
+ */
+ if (m->m_data - sizeof(struct ip) < m->m_pktdat)
+ panic("icmp len");
+ m->m_data -= sizeof(struct ip);
+ m->m_len += sizeof(struct ip);
+ m->m_pkthdr.len = m->m_len;
+ m->m_pkthdr.rcvif = n->m_pkthdr.rcvif;
+ nip = mtod(m, struct ip *);
+ bcopy((caddr_t)oip, (caddr_t)nip, sizeof(struct ip));
+ nip->ip_len = m->m_len;
+ nip->ip_vhl = IP_VHL_BORING;
+ nip->ip_p = IPPROTO_ICMP;
+ nip->ip_tos = 0;
+ icmp_reflect(m);
+
+freeit:
+ m_freem(n);
+}
+
+static struct sockaddr_in icmpsrc = { sizeof (struct sockaddr_in), AF_INET };
+static struct sockaddr_in icmpdst = { sizeof (struct sockaddr_in), AF_INET };
+static struct sockaddr_in icmpgw = { sizeof (struct sockaddr_in), AF_INET };
+
+/*
+ * Process a received ICMP message.
+ */
+void
+icmp_input(m, hlen)
+ register struct mbuf *m;
+ int hlen;
+{
+ register struct icmp *icp;
+ register struct ip *ip = mtod(m, struct ip *);
+ int icmplen = ip->ip_len;
+ register int i;
+ struct in_ifaddr *ia;
+ void (*ctlfunc) __P((int, struct sockaddr *, void *));
+ int code;
+
+ /*
+ * Locate icmp structure in mbuf, and check
+ * that not corrupted and of at least minimum length.
+ */
+#ifdef ICMPPRINTFS
+ if (icmpprintfs) {
+ char buf[4 * sizeof "123"];
+ strcpy(buf, inet_ntoa(ip->ip_src));
+ printf("icmp_input from %s to %s, len %d\n",
+ buf, inet_ntoa(ip->ip_dst), icmplen);
+ }
+#endif
+ if (icmplen < ICMP_MINLEN) {
+ icmpstat.icps_tooshort++;
+ goto freeit;
+ }
+ i = hlen + min(icmplen, ICMP_ADVLENMIN);
+ if (m->m_len < i && (m = m_pullup(m, i)) == 0) {
+ icmpstat.icps_tooshort++;
+ return;
+ }
+ ip = mtod(m, struct ip *);
+ m->m_len -= hlen;
+ m->m_data += hlen;
+ icp = mtod(m, struct icmp *);
+ if (in_cksum(m, icmplen)) {
+ icmpstat.icps_checksum++;
+ goto freeit;
+ }
+ m->m_len += hlen;
+ m->m_data -= hlen;
+
+#ifdef ICMPPRINTFS
+ if (icmpprintfs)
+ printf("icmp_input, type %d code %d\n", icp->icmp_type,
+ icp->icmp_code);
+#endif
+
+ /*
+ * Message type specific processing.
+ */
+ if (icp->icmp_type > ICMP_MAXTYPE)
+ goto raw;
+ icmpstat.icps_inhist[icp->icmp_type]++;
+ code = icp->icmp_code;
+ switch (icp->icmp_type) {
+
+ case ICMP_UNREACH:
+ switch (code) {
+ case ICMP_UNREACH_NET:
+ case ICMP_UNREACH_HOST:
+ case ICMP_UNREACH_PROTOCOL:
+ case ICMP_UNREACH_PORT:
+ case ICMP_UNREACH_SRCFAIL:
+ code += PRC_UNREACH_NET;
+ break;
+
+ case ICMP_UNREACH_NEEDFRAG:
+ code = PRC_MSGSIZE;
+ break;
+
+ case ICMP_UNREACH_NET_UNKNOWN:
+ case ICMP_UNREACH_NET_PROHIB:
+ case ICMP_UNREACH_TOSNET:
+ code = PRC_UNREACH_NET;
+ break;
+
+ case ICMP_UNREACH_HOST_UNKNOWN:
+ case ICMP_UNREACH_ISOLATED:
+ case ICMP_UNREACH_HOST_PROHIB:
+ case ICMP_UNREACH_TOSHOST:
+ code = PRC_UNREACH_HOST;
+ break;
+
+ case ICMP_UNREACH_FILTER_PROHIB:
+ case ICMP_UNREACH_HOST_PRECEDENCE:
+ case ICMP_UNREACH_PRECEDENCE_CUTOFF:
+ code = PRC_UNREACH_PORT;
+ break;
+
+ default:
+ goto badcode;
+ }
+ goto deliver;
+
+ case ICMP_TIMXCEED:
+ if (code > 1)
+ goto badcode;
+ code += PRC_TIMXCEED_INTRANS;
+ goto deliver;
+
+ case ICMP_PARAMPROB:
+ if (code > 1)
+ goto badcode;
+ code = PRC_PARAMPROB;
+ goto deliver;
+
+ case ICMP_SOURCEQUENCH:
+ if (code)
+ goto badcode;
+ code = PRC_QUENCH;
+ deliver:
+ /*
+ * Problem with datagram; advise higher level routines.
+ */
+ if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) ||
+ IP_VHL_HL(icp->icmp_ip.ip_vhl) < (sizeof(struct ip) >> 2)) {
+ icmpstat.icps_badlen++;
+ goto freeit;
+ }
+ NTOHS(icp->icmp_ip.ip_len);
+ /* Discard ICMP's in response to multicast packets */
+ if (IN_MULTICAST(ntohl(icp->icmp_ip.ip_dst.s_addr)))
+ goto badcode;
+#ifdef ICMPPRINTFS
+ if (icmpprintfs)
+ printf("deliver to protocol %d\n", icp->icmp_ip.ip_p);
+#endif
+ icmpsrc.sin_addr = icp->icmp_ip.ip_dst;
+#if 1
+ /*
+ * MTU discovery:
+ * If we got a needfrag and there is a host route to the
+ * original destination, and the MTU is not locked, then
+ * set the MTU in the route to the suggested new value
+ * (if given) and then notify as usual. The ULPs will
+ * notice that the MTU has changed and adapt accordingly.
+ * If no new MTU was suggested, then we guess a new one
+ * less than the current value. If the new MTU is
+ * unreasonably small (arbitrarily set at 296), then
+ * we reset the MTU to the interface value and enable the
+ * lock bit, indicating that we are no longer doing MTU
+ * discovery.
+ */
+ if (code == PRC_MSGSIZE) {
+ struct rtentry *rt;
+ int mtu;
+
+ rt = rtalloc1((struct sockaddr *)&icmpsrc, 0,
+ RTF_CLONING | RTF_PRCLONING);
+ if (rt && (rt->rt_flags & RTF_HOST)
+ && !(rt->rt_rmx.rmx_locks & RTV_MTU)) {
+ mtu = ntohs(icp->icmp_nextmtu);
+ if (!mtu)
+ mtu = ip_next_mtu(rt->rt_rmx.rmx_mtu,
+ 1);
+#ifdef DEBUG_MTUDISC
+ printf("MTU for %s reduced to %d\n",
+ inet_ntoa(icmpsrc.sin_addr), mtu);
+#endif
+ if (mtu < 296) {
+ /* rt->rt_rmx.rmx_mtu =
+ rt->rt_ifp->if_mtu; */
+ rt->rt_rmx.rmx_locks |= RTV_MTU;
+ } else if (rt->rt_rmx.rmx_mtu > mtu) {
+ rt->rt_rmx.rmx_mtu = mtu;
+ }
+ }
+ if (rt)
+ RTFREE(rt);
+ }
+
+#endif
+ ctlfunc = inetsw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput;
+ if (ctlfunc)
+ (*ctlfunc)(code, (struct sockaddr *)&icmpsrc,
+ (void *)&icp->icmp_ip);
+ break;
+
+ badcode:
+ icmpstat.icps_badcode++;
+ break;
+
+ case ICMP_ECHO:
+ if (!icmpbmcastecho
+ && (m->m_flags & (M_MCAST | M_BCAST)) != 0
+ && IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
+ icmpstat.icps_bmcastecho++;
+ break;
+ }
+ icp->icmp_type = ICMP_ECHOREPLY;
+ goto reflect;
+
+ case ICMP_TSTAMP:
+ if (!icmpbmcastecho
+ && (m->m_flags & (M_MCAST | M_BCAST)) != 0
+ && IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
+ icmpstat.icps_bmcasttstamp++;
+ break;
+ }
+ if (icmplen < ICMP_TSLEN) {
+ icmpstat.icps_badlen++;
+ break;
+ }
+ icp->icmp_type = ICMP_TSTAMPREPLY;
+ icp->icmp_rtime = iptime();
+ icp->icmp_ttime = icp->icmp_rtime; /* bogus, do later! */
+ goto reflect;
+
+ case ICMP_MASKREQ:
+#define satosin(sa) ((struct sockaddr_in *)(sa))
+ if (icmpmaskrepl == 0)
+ break;
+ /*
+ * We are not able to respond with all ones broadcast
+ * unless we receive it over a point-to-point interface.
+ */
+ if (icmplen < ICMP_MASKLEN)
+ break;
+ switch (ip->ip_dst.s_addr) {
+
+ case INADDR_BROADCAST:
+ case INADDR_ANY:
+ icmpdst.sin_addr = ip->ip_src;
+ break;
+
+ default:
+ icmpdst.sin_addr = ip->ip_dst;
+ }
+ ia = (struct in_ifaddr *)ifaof_ifpforaddr(
+ (struct sockaddr *)&icmpdst, m->m_pkthdr.rcvif);
+ if (ia == 0)
+ break;
+ if (ia->ia_ifp == 0)
+ break;
+ icp->icmp_type = ICMP_MASKREPLY;
+ icp->icmp_mask = ia->ia_sockmask.sin_addr.s_addr;
+ if (ip->ip_src.s_addr == 0) {
+ if (ia->ia_ifp->if_flags & IFF_BROADCAST)
+ ip->ip_src = satosin(&ia->ia_broadaddr)->sin_addr;
+ else if (ia->ia_ifp->if_flags & IFF_POINTOPOINT)
+ ip->ip_src = satosin(&ia->ia_dstaddr)->sin_addr;
+ }
+reflect:
+ ip->ip_len += hlen; /* since ip_input deducts this */
+ icmpstat.icps_reflect++;
+ icmpstat.icps_outhist[icp->icmp_type]++;
+ icmp_reflect(m);
+ return;
+
+ case ICMP_REDIRECT:
+ if (code > 3)
+ goto badcode;
+ if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) ||
+ IP_VHL_HL(icp->icmp_ip.ip_vhl) < (sizeof(struct ip) >> 2)) {
+ icmpstat.icps_badlen++;
+ break;
+ }
+ /*
+ * Short circuit routing redirects to force
+ * immediate change in the kernel's routing
+ * tables. The message is also handed to anyone
+ * listening on a raw socket (e.g. the routing
+ * daemon for use in updating its tables).
+ */
+ icmpgw.sin_addr = ip->ip_src;
+ icmpdst.sin_addr = icp->icmp_gwaddr;
+#ifdef ICMPPRINTFS
+ if (icmpprintfs) {
+ char buf[4 * sizeof "123"];
+ strcpy(buf, inet_ntoa(icp->icmp_ip.ip_dst));
+
+ printf("redirect dst %s to %s\n",
+ buf, inet_ntoa(icp->icmp_gwaddr));
+ }
+#endif
+ icmpsrc.sin_addr = icp->icmp_ip.ip_dst;
+ rtredirect((struct sockaddr *)&icmpsrc,
+ (struct sockaddr *)&icmpdst,
+ (struct sockaddr *)0, RTF_GATEWAY | RTF_HOST,
+ (struct sockaddr *)&icmpgw, (struct rtentry **)0);
+ pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&icmpsrc);
+ break;
+
+ /*
+ * No kernel processing for the following;
+ * just fall through to send to raw listener.
+ */
+ case ICMP_ECHOREPLY:
+ case ICMP_ROUTERADVERT:
+ case ICMP_ROUTERSOLICIT:
+ case ICMP_TSTAMPREPLY:
+ case ICMP_IREQREPLY:
+ case ICMP_MASKREPLY:
+ default:
+ break;
+ }
+
+raw:
+ rip_input(m, hlen);
+ return;
+
+freeit:
+ m_freem(m);
+}
+
+/*
+ * Reflect the ip packet back to the source
+ */
+static void
+icmp_reflect(m)
+ struct mbuf *m;
+{
+ register struct ip *ip = mtod(m, struct ip *);
+ register struct in_ifaddr *ia;
+ struct in_addr t;
+ struct mbuf *opts = 0;
+ int optlen = (IP_VHL_HL(ip->ip_vhl) << 2) - sizeof(struct ip);
+
+ if (!in_canforward(ip->ip_src) &&
+ ((ntohl(ip->ip_src.s_addr) & IN_CLASSA_NET) !=
+ (IN_LOOPBACKNET << IN_CLASSA_NSHIFT))) {
+ m_freem(m); /* Bad return address */
+ goto done; /* Ip_output() will check for broadcast */
+ }
+ t = ip->ip_dst;
+ ip->ip_dst = ip->ip_src;
+ /*
+ * If the incoming packet was addressed directly to us,
+ * use dst as the src for the reply. Otherwise (broadcast
+ * or anonymous), use the address which corresponds
+ * to the incoming interface.
+ */
+ for (ia = in_ifaddr; ia; ia = ia->ia_next) {
+ if (t.s_addr == IA_SIN(ia)->sin_addr.s_addr)
+ break;
+ if (ia->ia_ifp && (ia->ia_ifp->if_flags & IFF_BROADCAST) &&
+ t.s_addr == satosin(&ia->ia_broadaddr)->sin_addr.s_addr)
+ break;
+ }
+ icmpdst.sin_addr = t;
+ if ((ia == (struct in_ifaddr *)0) && m->m_pkthdr.rcvif)
+ ia = (struct in_ifaddr *)ifaof_ifpforaddr(
+ (struct sockaddr *)&icmpdst, m->m_pkthdr.rcvif);
+ /*
+ * The following happens if the packet was not addressed to us,
+ * and was received on an interface with no IP address.
+ */
+ if (ia == (struct in_ifaddr *)0)
+ ia = in_ifaddr;
+ t = IA_SIN(ia)->sin_addr;
+ ip->ip_src = t;
+ ip->ip_ttl = MAXTTL;
+
+ if (optlen > 0) {
+ register u_char *cp;
+ int opt, cnt;
+ u_int len;
+
+ /*
+ * Retrieve any source routing from the incoming packet;
+ * add on any record-route or timestamp options.
+ */
+ cp = (u_char *) (ip + 1);
+ if ((opts = ip_srcroute()) == 0 &&
+ (opts = m_gethdr(M_DONTWAIT, MT_HEADER))) {
+ opts->m_len = sizeof(struct in_addr);
+ mtod(opts, struct in_addr *)->s_addr = 0;
+ }
+ if (opts) {
+#ifdef ICMPPRINTFS
+ if (icmpprintfs)
+ printf("icmp_reflect optlen %d rt %d => ",
+ optlen, opts->m_len);
+#endif
+ for (cnt = optlen; cnt > 0; cnt -= len, cp += len) {
+ opt = cp[IPOPT_OPTVAL];
+ if (opt == IPOPT_EOL)
+ break;
+ if (opt == IPOPT_NOP)
+ len = 1;
+ else {
+ len = cp[IPOPT_OLEN];
+ if (len <= 0 || len > cnt)
+ break;
+ }
+ /*
+ * Should check for overflow, but it "can't happen"
+ */
+ if (opt == IPOPT_RR || opt == IPOPT_TS ||
+ opt == IPOPT_SECURITY) {
+ bcopy((caddr_t)cp,
+ mtod(opts, caddr_t) + opts->m_len, len);
+ opts->m_len += len;
+ }
+ }
+ /* Terminate & pad, if necessary */
+ cnt = opts->m_len % 4;
+ if (cnt) {
+ for (; cnt < 4; cnt++) {
+ *(mtod(opts, caddr_t) + opts->m_len) =
+ IPOPT_EOL;
+ opts->m_len++;
+ }
+ }
+#ifdef ICMPPRINTFS
+ if (icmpprintfs)
+ printf("%d\n", opts->m_len);
+#endif
+ }
+ /*
+ * Now strip out original options by copying rest of first
+ * mbuf's data back, and adjust the IP length.
+ */
+ ip->ip_len -= optlen;
+ ip->ip_vhl = IP_VHL_BORING;
+ m->m_len -= optlen;
+ if (m->m_flags & M_PKTHDR)
+ m->m_pkthdr.len -= optlen;
+ optlen += sizeof(struct ip);
+ bcopy((caddr_t)ip + optlen, (caddr_t)(ip + 1),
+ (unsigned)(m->m_len - sizeof(struct ip)));
+ }
+ m->m_flags &= ~(M_BCAST|M_MCAST);
+ icmp_send(m, opts);
+done:
+ if (opts)
+ (void)m_free(opts);
+}
+
+/*
+ * Send an icmp packet back to the ip level,
+ * after supplying a checksum.
+ */
+static void
+icmp_send(m, opts)
+ register struct mbuf *m;
+ struct mbuf *opts;
+{
+ register struct ip *ip = mtod(m, struct ip *);
+ register int hlen;
+ register struct icmp *icp;
+ struct route ro;
+
+ hlen = IP_VHL_HL(ip->ip_vhl) << 2;
+ m->m_data += hlen;
+ m->m_len -= hlen;
+ icp = mtod(m, struct icmp *);
+ icp->icmp_cksum = 0;
+ icp->icmp_cksum = in_cksum(m, ip->ip_len - hlen);
+ m->m_data -= hlen;
+ m->m_len += hlen;
+#ifdef ICMPPRINTFS
+ if (icmpprintfs) {
+ char buf[4 * sizeof "123"];
+ strcpy(buf, inet_ntoa(ip->ip_dst));
+ printf("icmp_send dst %s src %s\n",
+ buf, inet_ntoa(ip->ip_src));
+ }
+#endif
+ bzero(&ro, sizeof ro);
+ (void) ip_output(m, opts, &ro, 0, NULL);
+ if (ro.ro_rt)
+ RTFREE(ro.ro_rt);
+}
+
+n_time
+iptime()
+{
+ struct timeval atv;
+ u_long t;
+
+ microtime(&atv);
+ t = (atv.tv_sec % (24*60*60)) * 1000 + atv.tv_usec / 1000;
+ return (htonl(t));
+}
+
+#if 1
+/*
+ * Return the next larger or smaller MTU plateau (table from RFC 1191)
+ * given current value MTU. If DIR is less than zero, a larger plateau
+ * is returned; otherwise, a smaller value is returned.
+ */
+static int
+ip_next_mtu(mtu, dir)
+ int mtu;
+ int dir;
+{
+ static int mtutab[] = {
+ 65535, 32000, 17914, 8166, 4352, 2002, 1492, 1006, 508, 296,
+ 68, 0
+ };
+ int i;
+
+ for (i = 0; i < (sizeof mtutab) / (sizeof mtutab[0]); i++) {
+ if (mtu >= mtutab[i])
+ break;
+ }
+
+ if (dir < 0) {
+ if (i == 0) {
+ return 0;
+ } else {
+ return mtutab[i - 1];
+ }
+ } else {
+ if (mtutab[i] == 0) {
+ return 0;
+ } else if(mtu > mtutab[i]) {
+ return mtutab[i];
+ } else {
+ return mtutab[i + 1];
+ }
+ }
+}
+#endif
diff --git a/cpukit/libnetworking/netinet/ip_icmp.h b/cpukit/libnetworking/netinet/ip_icmp.h
new file mode 100644
index 0000000000..b99ae94521
--- /dev/null
+++ b/cpukit/libnetworking/netinet/ip_icmp.h
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)ip_icmp.h 8.1 (Berkeley) 6/10/93
+ * $Id$
+ */
+
+#ifndef _NETINET_IP_ICMP_H_
+#define _NETINET_IP_ICMP_H_
+
+/*
+ * Interface Control Message Protocol Definitions.
+ * Per RFC 792, September 1981.
+ */
+
+/*
+ * Internal of an ICMP Router Advertisement
+ */
+struct icmp_ra_addr {
+ u_int32_t ira_addr;
+ u_int32_t ira_preference;
+};
+
+/*
+ * Structure of an icmp header.
+ */
+struct icmp {
+ u_char icmp_type BYTE_PACK; /* type of message, see below */
+ u_char icmp_code BYTE_PACK; /* type sub code */
+ u_short icmp_cksum BYTE_PACK; /* ones complement cksum of struct */
+ union {
+ u_char ih_pptr BYTE_PACK; /* ICMP_PARAMPROB */
+ struct in_addr ih_gwaddr BYTE_PACK; /* ICMP_REDIRECT */
+ struct ih_idseq {
+ n_short icd_id BYTE_PACK;
+ n_short icd_seq BYTE_PACK;
+ } ih_idseq;
+ int ih_void BYTE_PACK;
+
+ /* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */
+ struct ih_pmtu {
+ n_short ipm_void BYTE_PACK;
+ n_short ipm_nextmtu BYTE_PACK;
+ } ih_pmtu;
+
+ struct ih_rtradv {
+ u_char irt_num_addrs BYTE_PACK;
+ u_char irt_wpa BYTE_PACK;
+ u_int16_t irt_lifetime BYTE_PACK;
+ } ih_rtradv;
+ } icmp_hun;
+#define icmp_pptr icmp_hun.ih_pptr
+#define icmp_gwaddr icmp_hun.ih_gwaddr
+#define icmp_id icmp_hun.ih_idseq.icd_id
+#define icmp_seq icmp_hun.ih_idseq.icd_seq
+#define icmp_void icmp_hun.ih_void
+#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void
+#define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu
+#define icmp_num_addrs icmp_hun.ih_rtradv.irt_num_addrs
+#define icmp_wpa icmp_hun.ih_rtradv.irt_wpa
+#define icmp_lifetime icmp_hun.ih_rtradv.irt_lifetime
+ union {
+ struct id_ts {
+ n_time its_otime BYTE_PACK;
+ n_time its_rtime BYTE_PACK;
+ n_time its_ttime BYTE_PACK;
+ } id_ts;
+ struct id_ip {
+ struct ip idi_ip BYTE_PACK;
+ /* options and then 64 bits of data */
+ } id_ip;
+ struct icmp_ra_addr id_radv BYTE_PACK;
+ u_long id_mask BYTE_PACK;
+ char id_data[1];
+ } icmp_dun;
+#define icmp_otime icmp_dun.id_ts.its_otime
+#define icmp_rtime icmp_dun.id_ts.its_rtime
+#define icmp_ttime icmp_dun.id_ts.its_ttime
+#define icmp_ip icmp_dun.id_ip.idi_ip
+#define icmp_radv icmp_dun.id_radv
+#define icmp_mask icmp_dun.id_mask
+#define icmp_data icmp_dun.id_data
+};
+
+/*
+ * Lower bounds on packet lengths for various types.
+ * For the error advice packets must first insure that the
+ * packet is large enough to contain the returned ip header.
+ * Only then can we do the check to see if 64 bits of packet
+ * data have been returned, since we need to check the returned
+ * ip header length.
+ */
+#define ICMP_MINLEN 8 /* abs minimum */
+#define ICMP_TSLEN (8 + 3 * sizeof (n_time)) /* timestamp */
+#define ICMP_MASKLEN 12 /* address mask */
+#define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) /* min */
+#ifndef _IP_VHL
+#define ICMP_ADVLEN(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 8)
+ /* N.B.: must separately check that ip_hl >= 5 */
+#else
+#define ICMP_ADVLEN(p) (8 + (IP_VHL_HL((p)->icmp_ip.ip_vhl) << 2) + 8)
+ /* N.B.: must separately check that header length >= 5 */
+#endif
+
+/*
+ * Definition of type and code field values.
+ */
+#define ICMP_ECHOREPLY 0 /* echo reply */
+#define ICMP_UNREACH 3 /* dest unreachable, codes: */
+#define ICMP_UNREACH_NET 0 /* bad net */
+#define ICMP_UNREACH_HOST 1 /* bad host */
+#define ICMP_UNREACH_PROTOCOL 2 /* bad protocol */
+#define ICMP_UNREACH_PORT 3 /* bad port */
+#define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */
+#define ICMP_UNREACH_SRCFAIL 5 /* src route failed */
+#define ICMP_UNREACH_NET_UNKNOWN 6 /* unknown net */
+#define ICMP_UNREACH_HOST_UNKNOWN 7 /* unknown host */
+#define ICMP_UNREACH_ISOLATED 8 /* src host isolated */
+#define ICMP_UNREACH_NET_PROHIB 9 /* prohibited access */
+#define ICMP_UNREACH_HOST_PROHIB 10 /* ditto */
+#define ICMP_UNREACH_TOSNET 11 /* bad tos for net */
+#define ICMP_UNREACH_TOSHOST 12 /* bad tos for host */
+#define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohib */
+#define ICMP_UNREACH_HOST_PRECEDENCE 14 /* host prec vio. */
+#define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 /* prec cutoff */
+#define ICMP_SOURCEQUENCH 4 /* packet lost, slow down */
+#define ICMP_REDIRECT 5 /* shorter route, codes: */
+#define ICMP_REDIRECT_NET 0 /* for network */
+#define ICMP_REDIRECT_HOST 1 /* for host */
+#define ICMP_REDIRECT_TOSNET 2 /* for tos and net */
+#define ICMP_REDIRECT_TOSHOST 3 /* for tos and host */
+#define ICMP_ECHO 8 /* echo service */
+#define ICMP_ROUTERADVERT 9 /* router advertisement */
+#define ICMP_ROUTERSOLICIT 10 /* router solicitation */
+#define ICMP_TIMXCEED 11 /* time exceeded, code: */
+#define ICMP_TIMXCEED_INTRANS 0 /* ttl==0 in transit */
+#define ICMP_TIMXCEED_REASS 1 /* ttl==0 in reass */
+#define ICMP_PARAMPROB 12 /* ip header bad */
+#define ICMP_PARAMPROB_OPTABSENT 1 /* req. opt. absent */
+#define ICMP_TSTAMP 13 /* timestamp request */
+#define ICMP_TSTAMPREPLY 14 /* timestamp reply */
+#define ICMP_IREQ 15 /* information request */
+#define ICMP_IREQREPLY 16 /* information reply */
+#define ICMP_MASKREQ 17 /* address mask request */
+#define ICMP_MASKREPLY 18 /* address mask reply */
+
+#define ICMP_MAXTYPE 18
+
+#define ICMP_INFOTYPE(type) \
+ ((type) == ICMP_ECHOREPLY || (type) == ICMP_ECHO || \
+ (type) == ICMP_ROUTERADVERT || (type) == ICMP_ROUTERSOLICIT || \
+ (type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY || \
+ (type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \
+ (type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY)
+
+#ifdef _KERNEL
+void icmp_error __P((struct mbuf *, int, int, n_long, struct ifnet *));
+void icmp_input __P((struct mbuf *, int));
+#endif
+
+#endif
diff --git a/cpukit/libnetworking/netinet/ip_input.c b/cpukit/libnetworking/netinet/ip_input.c
new file mode 100644
index 0000000000..f915fb7106
--- /dev/null
+++ b/cpukit/libnetworking/netinet/ip_input.c
@@ -0,0 +1,1488 @@
+/*
+ * Copyright (c) 1982, 1986, 1988, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)ip_input.c 8.2 (Berkeley) 1/4/94
+ * $Id$
+ * $ANA: ip_input.c,v 1.5 1996/09/18 14:34:59 wollman Exp $
+ */
+
+#define _IP_VHL
+
+#include "opt_ipfw.h"
+
+#include <stddef.h>
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/domain.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/errno.h>
+#include <sys/time.h>
+#include <sys/kernel.h>
+#include <sys/syslog.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/route.h>
+#include <net/netisr.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/in_pcb.h>
+#include <netinet/in_var.h>
+#include <netinet/ip_var.h>
+#include <netinet/ip_icmp.h>
+#include <machine/in_cksum.h>
+
+#include <sys/socketvar.h>
+
+#ifdef IPFIREWALL
+#include <netinet/ip_fw.h>
+#endif
+
+int rsvp_on = 0;
+static int ip_rsvp_on;
+struct socket *ip_rsvpd;
+
+int ipforwarding = 0;
+SYSCTL_INT(_net_inet_ip, IPCTL_FORWARDING, forwarding, CTLFLAG_RW,
+ &ipforwarding, 0, "");
+
+static int ipsendredirects = 1; /* XXX */
+SYSCTL_INT(_net_inet_ip, IPCTL_SENDREDIRECTS, redirect, CTLFLAG_RW,
+ &ipsendredirects, 0, "");
+
+int ip_defttl = IPDEFTTL;
+SYSCTL_INT(_net_inet_ip, IPCTL_DEFTTL, ttl, CTLFLAG_RW,
+ &ip_defttl, 0, "");
+
+static int ip_dosourceroute = 0;
+SYSCTL_INT(_net_inet_ip, IPCTL_SOURCEROUTE, sourceroute, CTLFLAG_RW,
+ &ip_dosourceroute, 0, "");
+
+static int ip_acceptsourceroute = 0;
+SYSCTL_INT(_net_inet_ip, IPCTL_ACCEPTSOURCEROUTE, accept_sourceroute,
+ CTLFLAG_RW, &ip_acceptsourceroute, 0, "");
+#ifdef DIAGNOSTIC
+static int ipprintfs = 0;
+#endif
+
+extern struct domain inetdomain;
+extern struct protosw inetsw[];
+u_char ip_protox[IPPROTO_MAX];
+static int ipqmaxlen = IFQ_MAXLEN;
+struct in_ifaddr *in_ifaddr; /* first inet address */
+struct ifqueue ipintrq;
+SYSCTL_INT(_net_inet_ip, IPCTL_INTRQMAXLEN, intr_queue_maxlen, CTLFLAG_RD,
+ &ipintrq.ifq_maxlen, 0, "");
+SYSCTL_INT(_net_inet_ip, IPCTL_INTRQDROPS, intr_queue_drops, CTLFLAG_RD,
+ &ipintrq.ifq_drops, 0, "");
+
+struct ipstat ipstat;
+
+/* Packet reassembly stuff */
+#define IPREASS_NHASH_LOG2 6
+#define IPREASS_NHASH (1 << IPREASS_NHASH_LOG2)
+#define IPREASS_HMASK (IPREASS_NHASH - 1)
+#define IPREASS_HASH(x,y) \
+ (((((x) & 0xF) | ((((x) >> 8) & 0xF) << 4)) ^ (y)) & IPREASS_HMASK)
+
+static struct ipq ipq[IPREASS_NHASH];
+static int nipq = 0; /* total # of reass queues */
+static int maxnipq;
+
+#ifdef IPCTL_DEFMTU
+SYSCTL_INT(_net_inet_ip, IPCTL_DEFMTU, mtu, CTLFLAG_RW,
+ &ip_mtu, 0, "");
+#endif
+
+#if !defined(COMPAT_IPFW) || COMPAT_IPFW == 1
+#undef COMPAT_IPFW
+#define COMPAT_IPFW 1
+#else
+#undef COMPAT_IPFW
+#endif
+
+#ifdef COMPAT_IPFW
+/* Firewall hooks */
+ip_fw_chk_t *ip_fw_chk_ptr;
+ip_fw_ctl_t *ip_fw_ctl_ptr;
+
+/* IP Network Address Translation (NAT) hooks */
+ip_nat_t *ip_nat_ptr;
+ip_nat_ctl_t *ip_nat_ctl_ptr;
+#endif
+
+/*
+ * We need to save the IP options in case a protocol wants to respond
+ * to an incoming packet over the same route if the packet got here
+ * using IP source routing. This allows connection establishment and
+ * maintenance when the remote end is on a network that is not known
+ * to us.
+ */
+static int ip_nhops = 0;
+static struct ip_srcrt {
+ struct in_addr dst; /* final destination */
+ char nop; /* one NOP to align */
+ char srcopt[IPOPT_OFFSET + 1]; /* OPTVAL, OLEN and OFFSET */
+ struct in_addr route[MAX_IPOPTLEN/sizeof(struct in_addr)];
+} ip_srcrt;
+
+#ifdef IPDIVERT
+/*
+ * Shared variable between ip_input() and ip_reass() to communicate
+ * about which packets, once assembled from fragments, get diverted,
+ * and to which port.
+ */
+static u_short frag_divert_port;
+#endif
+
+static void save_rte __P((u_char *, struct in_addr));
+static void ip_deq __P((struct ipasfrag *));
+static int ip_dooptions __P((struct mbuf *));
+static void ip_enq __P((struct ipasfrag *, struct ipasfrag *));
+static void ip_forward __P((struct mbuf *, int));
+static void ip_freef __P((struct ipq *));
+static struct ip *
+ ip_reass __P((struct ipasfrag *, struct ipq *, struct ipq *));
+static struct in_ifaddr *
+ ip_rtaddr __P((struct in_addr));
+void ipintr __P((void));
+/*
+ * IP initialization: fill in IP protocol switch table.
+ * All protocols not implemented in kernel go to raw IP protocol handler.
+ */
+void
+ip_init()
+{
+ register struct protosw *pr;
+ register int i;
+
+ pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW);
+ if (pr == 0)
+ panic("ip_init");
+ for (i = 0; i < IPPROTO_MAX; i++)
+ ip_protox[i] = pr - inetsw;
+ for (pr = inetdomain.dom_protosw;
+ pr < inetdomain.dom_protoswNPROTOSW; pr++)
+ if (pr->pr_domain->dom_family == PF_INET &&
+ pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
+ ip_protox[pr->pr_protocol] = pr - inetsw;
+
+ for (i = 0; i < IPREASS_NHASH; i++)
+ ipq[i].next = ipq[i].prev = &ipq[i];
+
+ maxnipq = nmbclusters/4;
+
+ ip_id = rtems_bsdnet_seconds_since_boot() & 0xffff;
+ ipintrq.ifq_maxlen = ipqmaxlen;
+#ifdef IPFIREWALL
+ ip_fw_init();
+#endif
+#ifdef IPNAT
+ ip_nat_init();
+#endif
+
+}
+
+static struct sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET };
+static struct route ipforward_rt;
+
+/*
+ * Ip input routine. Checksum and byte swap header. If fragmented
+ * try to reassemble. Process options. Pass to next level.
+ */
+void
+ip_input(struct mbuf *m)
+{
+ struct ip *ip;
+ struct ipq *fp;
+ struct in_ifaddr *ia;
+ int i, hlen;
+ u_short sum;
+
+#ifdef DIAGNOSTIC
+ if ((m->m_flags & M_PKTHDR) == 0)
+ panic("ip_input no HDR");
+#endif
+ /*
+ * If no IP addresses have been set yet but the interfaces
+ * are receiving, can't do anything with incoming packets yet.
+ */
+ if (in_ifaddr == NULL)
+ goto bad;
+ ipstat.ips_total++;
+
+ if (m->m_pkthdr.len < sizeof(struct ip))
+ goto tooshort;
+
+#if defined(DIAGNOSTIC) && defined(ORIGINAL_FREEBSD_CODE)
+ if (m->m_len < sizeof(struct ip))
+ panic("ipintr mbuf too short");
+#endif
+
+ if (m->m_len < sizeof (struct ip) &&
+ (m = m_pullup(m, sizeof (struct ip))) == 0) {
+ ipstat.ips_toosmall++;
+ return;
+ }
+ ip = mtod(m, struct ip *);
+
+ if (IP_VHL_V(ip->ip_vhl) != IPVERSION) {
+ ipstat.ips_badvers++;
+ goto bad;
+ }
+
+ hlen = IP_VHL_HL(ip->ip_vhl) << 2;
+ if (hlen < sizeof(struct ip)) { /* minimum header length */
+ ipstat.ips_badhlen++;
+ goto bad;
+ }
+ if (hlen > m->m_len) {
+ if ((m = m_pullup(m, hlen)) == 0) {
+ ipstat.ips_badhlen++;
+ return;
+ }
+ ip = mtod(m, struct ip *);
+ }
+ if (hlen == sizeof(struct ip)) {
+ sum = in_cksum_hdr(ip);
+ } else {
+ sum = in_cksum(m, hlen);
+ }
+ if (sum) {
+ ipstat.ips_badsum++;
+ goto bad;
+ }
+
+ /*
+ * Convert fields to host representation.
+ */
+ NTOHS(ip->ip_len);
+ if (ip->ip_len < hlen) {
+ ipstat.ips_badlen++;
+ goto bad;
+ }
+ NTOHS(ip->ip_id);
+ NTOHS(ip->ip_off);
+
+ /*
+ * Check that the amount of data in the buffers
+ * is as at least much as the IP header would have us expect.
+ * Trim mbufs if longer than we expect.
+ * Drop packet if shorter than we expect.
+ */
+ if (m->m_pkthdr.len < ip->ip_len) {
+tooshort:
+ ipstat.ips_tooshort++;
+ goto bad;
+ }
+ if (m->m_pkthdr.len > ip->ip_len) {
+ if (m->m_len == m->m_pkthdr.len) {
+ m->m_len = ip->ip_len;
+ m->m_pkthdr.len = ip->ip_len;
+ } else
+ m_adj(m, ip->ip_len - m->m_pkthdr.len);
+ }
+ /*
+ * IpHack's section.
+ * Right now when no processing on packet has done
+ * and it is still fresh out of network we do our black
+ * deals with it.
+ * - Firewall: deny/allow/divert
+ * - Xlate: translate packet's addr/port (NAT).
+ * - Wrap: fake packet's addr/port <unimpl.>
+ * - Encapsulate: put it in another IP and send out. <unimp.>
+ */
+
+#ifdef COMPAT_IPFW
+ if (ip_fw_chk_ptr) {
+#ifdef IPDIVERT
+ u_short port;
+
+ port = (*ip_fw_chk_ptr)(&ip, hlen, NULL, ip_divert_ignore, &m);
+ ip_divert_ignore = 0;
+ if (port) { /* Divert packet */
+ frag_divert_port = port;
+ goto ours;
+ }
+#else
+ /* If ipfw says divert, we have to just drop packet */
+ if ((*ip_fw_chk_ptr)(&ip, hlen, NULL, 0, &m)) {
+ m_freem(m);
+ m = NULL;
+ }
+#endif
+ if (!m)
+ return;
+ }
+
+ if (ip_nat_ptr && !(*ip_nat_ptr)(&ip, &m, m->m_pkthdr.rcvif, IP_NAT_IN))
+ return;
+#endif
+
+ /*
+ * Process options and, if not destined for us,
+ * ship it on. ip_dooptions returns 1 when an
+ * error was detected (causing an icmp message
+ * to be sent and the original packet to be freed).
+ */
+ ip_nhops = 0; /* for source routed packets */
+ if (hlen > sizeof (struct ip) && ip_dooptions(m))
+ return;
+
+ /* greedy RSVP, snatches any PATH packet of the RSVP protocol and no
+ * matter if it is destined to another node, or whether it is
+ * a multicast one, RSVP wants it! and prevents it from being forwarded
+ * anywhere else. Also checks if the rsvp daemon is running before
+ * grabbing the packet.
+ */
+ if (rsvp_on && ip->ip_p==IPPROTO_RSVP)
+ goto ours;
+
+ /*
+ * Check our list of addresses, to see if the packet is for us.
+ */
+ for (ia = in_ifaddr; ia; ia = ia->ia_next) {
+#define satosin(sa) ((struct sockaddr_in *)(sa))
+
+ if (IA_SIN(ia)->sin_addr.s_addr == ip->ip_dst.s_addr)
+ goto ours;
+#ifdef BOOTP_COMPAT
+ if (IA_SIN(ia)->sin_addr.s_addr == INADDR_ANY)
+ goto ours;
+#endif
+ if (ia->ia_ifp && ia->ia_ifp->if_flags & IFF_BROADCAST) {
+ if (satosin(&ia->ia_broadaddr)->sin_addr.s_addr ==
+ ip->ip_dst.s_addr)
+ goto ours;
+ if (ip->ip_dst.s_addr == ia->ia_netbroadcast.s_addr)
+ goto ours;
+ }
+ }
+ if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
+ struct in_multi *inm;
+ if (ip_mrouter) {
+ /*
+ * If we are acting as a multicast router, all
+ * incoming multicast packets are passed to the
+ * kernel-level multicast forwarding function.
+ * The packet is returned (relatively) intact; if
+ * ip_mforward() returns a non-zero value, the packet
+ * must be discarded, else it may be accepted below.
+ *
+ * (The IP ident field is put in the same byte order
+ * as expected when ip_mforward() is called from
+ * ip_output().)
+ */
+ ip->ip_id = htons(ip->ip_id);
+ if (ip_mforward(ip, m->m_pkthdr.rcvif, m, 0) != 0) {
+ ipstat.ips_cantforward++;
+ m_freem(m);
+ return;
+ }
+ ip->ip_id = ntohs(ip->ip_id);
+
+ /*
+ * The process-level routing demon needs to receive
+ * all multicast IGMP packets, whether or not this
+ * host belongs to their destination groups.
+ */
+ if (ip->ip_p == IPPROTO_IGMP)
+ goto ours;
+ ipstat.ips_forward++;
+ }
+ /*
+ * See if we belong to the destination multicast group on the
+ * arrival interface.
+ */
+ IN_LOOKUP_MULTI(ip->ip_dst, m->m_pkthdr.rcvif, inm);
+ if (inm == NULL) {
+ ipstat.ips_cantforward++;
+ m_freem(m);
+ return;
+ }
+ goto ours;
+ }
+ if (ip->ip_dst.s_addr == (u_long)INADDR_BROADCAST)
+ goto ours;
+ if (ip->ip_dst.s_addr == INADDR_ANY)
+ goto ours;
+
+ /*
+ * Not for us; forward if possible and desirable.
+ */
+ if (ipforwarding == 0) {
+ ipstat.ips_cantforward++;
+ m_freem(m);
+ } else
+ ip_forward(m, 0);
+ return;
+
+ours:
+
+ /*
+ * If offset or IP_MF are set, must reassemble.
+ * Otherwise, nothing need be done.
+ * (We could look in the reassembly queue to see
+ * if the packet was previously fragmented,
+ * but it's not worth the time; just let them time out.)
+ */
+ if (ip->ip_off &~ (IP_DF | IP_RF)) {
+ if (m->m_flags & M_EXT) { /* XXX */
+ if ((m = m_pullup(m, sizeof (struct ip))) == 0) {
+ ipstat.ips_toosmall++;
+#ifdef IPDIVERT
+ frag_divert_port = 0;
+#endif
+ return;
+ }
+ ip = mtod(m, struct ip *);
+ }
+ sum = IPREASS_HASH(ip->ip_src.s_addr, ip->ip_id);
+ /*
+ * Look for queue of fragments
+ * of this datagram.
+ */
+ for (fp = ipq[sum].next; fp != &ipq[sum]; fp = fp->next)
+ if (ip->ip_id == fp->ipq_id &&
+ ip->ip_src.s_addr == fp->ipq_src.s_addr &&
+ ip->ip_dst.s_addr == fp->ipq_dst.s_addr &&
+ ip->ip_p == fp->ipq_p)
+ goto found;
+
+ fp = 0;
+
+ /* check if there's a place for the new queue */
+ if (nipq > maxnipq) {
+ /*
+ * drop something from the tail of the current queue
+ * before proceeding further
+ */
+ if (ipq[sum].prev == &ipq[sum]) { /* gak */
+ for (i = 0; i < IPREASS_NHASH; i++) {
+ if (ipq[i].prev != &ipq[i]) {
+ ip_freef(ipq[i].prev);
+ break;
+ }
+ }
+ } else
+ ip_freef(ipq[sum].prev);
+ }
+found:
+ /*
+ * Adjust ip_len to not reflect header,
+ * set ip_mff if more fragments are expected,
+ * convert offset of this to bytes.
+ */
+ ip->ip_len -= hlen;
+ ((struct ipasfrag *)ip)->ipf_mff &= ~1;
+ if (ip->ip_off & IP_MF)
+ ((struct ipasfrag *)ip)->ipf_mff |= 1;
+ ip->ip_off <<= 3;
+
+ /*
+ * If datagram marked as having more fragments
+ * or if this is not the first fragment,
+ * attempt reassembly; if it succeeds, proceed.
+ */
+ if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) {
+ ipstat.ips_fragments++;
+ ip = ip_reass((struct ipasfrag *)ip, fp, &ipq[sum]);
+ if (ip == 0)
+ return;
+ ipstat.ips_reassembled++;
+ m = dtom(ip);
+#ifdef IPDIVERT
+ if (frag_divert_port) {
+ ip->ip_len += hlen;
+ HTONS(ip->ip_len);
+ HTONS(ip->ip_off);
+ HTONS(ip->ip_id);
+ ip->ip_sum = 0;
+ ip->ip_sum = in_cksum_hdr(ip);
+ NTOHS(ip->ip_id);
+ NTOHS(ip->ip_off);
+ NTOHS(ip->ip_len);
+ ip->ip_len -= hlen;
+ }
+#endif
+ } else
+ if (fp)
+ ip_freef(fp);
+ } else
+ ip->ip_len -= hlen;
+
+#ifdef IPDIVERT
+ /*
+ * Divert reassembled packets to the divert protocol if required
+ */
+ if (frag_divert_port) {
+ ipstat.ips_delivered++;
+ ip_divert_port = frag_divert_port;
+ frag_divert_port = 0;
+ (*inetsw[ip_protox[IPPROTO_DIVERT]].pr_input)(m, hlen);
+ return;
+ }
+
+ /* Don't let packets divert themselves */
+ if (ip->ip_p == IPPROTO_DIVERT) {
+ ipstat.ips_noproto++;
+ goto bad;
+ }
+#endif
+
+ /*
+ * Switch out to protocol's input routine.
+ */
+ ipstat.ips_delivered++;
+ (*inetsw[ip_protox[ip->ip_p]].pr_input)(m, hlen);
+ return;
+bad:
+ m_freem(m);
+}
+
+/*
+ * IP software interrupt routine - to go away sometime soon
+ */
+void
+ipintr(void)
+{
+ int s;
+ struct mbuf *m;
+
+ while(1) {
+ s = splimp();
+ IF_DEQUEUE(&ipintrq, m);
+ splx(s);
+ if (m == 0)
+ return;
+ ip_input(m);
+ }
+}
+
+NETISR_SET(NETISR_IP, ipintr);
+
+/*
+ * Take incoming datagram fragment and try to
+ * reassemble it into whole datagram. If a chain for
+ * reassembly of this datagram already exists, then it
+ * is given as fp; otherwise have to make a chain.
+ */
+static struct ip *
+ip_reass(ip, fp, where)
+ register struct ipasfrag *ip;
+ register struct ipq *fp;
+ struct ipq *where;
+{
+ register struct mbuf *m = dtom(ip);
+ register struct ipasfrag *q;
+ struct mbuf *t;
+ int hlen = ip->ip_hl << 2;
+ int i, next;
+
+ /*
+ * Presence of header sizes in mbufs
+ * would confuse code below.
+ */
+ m->m_data += hlen;
+ m->m_len -= hlen;
+
+ /*
+ * If first fragment to arrive, create a reassembly queue.
+ */
+ if (fp == 0) {
+ if ((t = m_get(M_DONTWAIT, MT_FTABLE)) == NULL)
+ goto dropfrag;
+ fp = mtod(t, struct ipq *);
+ insque(fp, where);
+ nipq++;
+ fp->ipq_ttl = IPFRAGTTL;
+ fp->ipq_p = ip->ip_p;
+ fp->ipq_id = ip->ip_id;
+ fp->ipq_next = fp->ipq_prev = (struct ipasfrag *)fp;
+ fp->ipq_src = ((struct ip *)ip)->ip_src;
+ fp->ipq_dst = ((struct ip *)ip)->ip_dst;
+#ifdef IPDIVERT
+ fp->ipq_divert = 0;
+#endif
+ q = (struct ipasfrag *)fp;
+ goto insert;
+ }
+
+ /*
+ * Find a segment which begins after this one does.
+ */
+ for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = q->ipf_next)
+ if (q->ip_off > ip->ip_off)
+ break;
+
+ /*
+ * If there is a preceding segment, it may provide some of
+ * our data already. If so, drop the data from the incoming
+ * segment. If it provides all of our data, drop us.
+ */
+ if (q->ipf_prev != (struct ipasfrag *)fp) {
+ i = q->ipf_prev->ip_off + q->ipf_prev->ip_len - ip->ip_off;
+ if (i > 0) {
+ if (i >= ip->ip_len)
+ goto dropfrag;
+ m_adj(dtom(ip), i);
+ ip->ip_off += i;
+ ip->ip_len -= i;
+ }
+ }
+
+ /*
+ * While we overlap succeeding segments trim them or,
+ * if they are completely covered, dequeue them.
+ */
+ while (q != (struct ipasfrag *)fp && ip->ip_off + ip->ip_len > q->ip_off) {
+ struct mbuf *m0;
+
+ i = (ip->ip_off + ip->ip_len) - q->ip_off;
+ if (i < q->ip_len) {
+ q->ip_len -= i;
+ q->ip_off += i;
+ m_adj(dtom(q), i);
+ break;
+ }
+ m0 = dtom(q);
+ q = q->ipf_next;
+ ip_deq(q->ipf_prev);
+ m_freem(m0);
+ }
+
+insert:
+
+#ifdef IPDIVERT
+ /*
+ * Any fragment diverting causes the whole packet to divert
+ */
+ if (frag_divert_port != 0)
+ fp->ipq_divert = frag_divert_port;
+ frag_divert_port = 0;
+#endif
+
+ /*
+ * Stick new segment in its place;
+ * check for complete reassembly.
+ */
+ ip_enq(ip, q->ipf_prev);
+ next = 0;
+ for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = q->ipf_next) {
+ if (q->ip_off != next)
+ return (0);
+ next += q->ip_len;
+ }
+ if (q->ipf_prev->ipf_mff & 1)
+ return (0);
+
+ /*
+ * Reassembly is complete. Make sure the packet is a sane size.
+ */
+ if (next + (IP_VHL_HL(((struct ip *)fp->ipq_next)->ip_vhl) << 2)
+ > IP_MAXPACKET) {
+ ipstat.ips_toolong++;
+ ip_freef(fp);
+ return (0);
+ }
+
+ /*
+ * Concatenate fragments.
+ */
+ q = fp->ipq_next;
+ m = dtom(q);
+ t = m->m_next;
+ m->m_next = 0;
+ m_cat(m, t);
+ q = q->ipf_next;
+ while (q != (struct ipasfrag *)fp) {
+ t = dtom(q);
+ q = q->ipf_next;
+ m_cat(m, t);
+ }
+
+#ifdef IPDIVERT
+ /*
+ * Record divert port for packet, if any
+ */
+ frag_divert_port = fp->ipq_divert;
+#endif
+
+ /*
+ * Create header for new ip packet by
+ * modifying header of first packet;
+ * dequeue and discard fragment reassembly header.
+ * Make header visible.
+ */
+ ip = fp->ipq_next;
+ ip->ip_len = next;
+ ip->ipf_mff &= ~1;
+ ((struct ip *)ip)->ip_src = fp->ipq_src;
+ ((struct ip *)ip)->ip_dst = fp->ipq_dst;
+ remque(fp);
+ nipq--;
+ (void) m_free(dtom(fp));
+ m = dtom(ip);
+ m->m_len += (ip->ip_hl << 2);
+ m->m_data -= (ip->ip_hl << 2);
+ /* some debugging cruft by sklower, below, will go away soon */
+ if (m->m_flags & M_PKTHDR) { /* XXX this should be done elsewhere */
+ register int plen = 0;
+ for (t = m; m; m = m->m_next)
+ plen += m->m_len;
+ t->m_pkthdr.len = plen;
+ }
+ return ((struct ip *)ip);
+
+dropfrag:
+ ipstat.ips_fragdropped++;
+ m_freem(m);
+ return (0);
+}
+
+/*
+ * Free a fragment reassembly header and all
+ * associated datagrams.
+ */
+static void
+ip_freef(fp)
+ struct ipq *fp;
+{
+ register struct ipasfrag *q, *p;
+
+ for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = p) {
+ p = q->ipf_next;
+ ip_deq(q);
+ m_freem(dtom(q));
+ }
+ remque(fp);
+ (void) m_free(dtom(fp));
+ nipq--;
+}
+
+/*
+ * Put an ip fragment on a reassembly chain.
+ * Like insque, but pointers in middle of structure.
+ */
+static void
+ip_enq(p, prev)
+ register struct ipasfrag *p, *prev;
+{
+
+ p->ipf_prev = prev;
+ p->ipf_next = prev->ipf_next;
+ prev->ipf_next->ipf_prev = p;
+ prev->ipf_next = p;
+}
+
+/*
+ * To ip_enq as remque is to insque.
+ */
+static void
+ip_deq(p)
+ register struct ipasfrag *p;
+{
+
+ p->ipf_prev->ipf_next = p->ipf_next;
+ p->ipf_next->ipf_prev = p->ipf_prev;
+}
+
+/*
+ * IP timer processing;
+ * if a timer expires on a reassembly
+ * queue, discard it.
+ */
+void
+ip_slowtimo()
+{
+ register struct ipq *fp;
+ int s = splnet();
+ int i;
+
+ for (i = 0; i < IPREASS_NHASH; i++) {
+ fp = ipq[i].next;
+ if (fp == 0)
+ continue;
+ while (fp != &ipq[i]) {
+ --fp->ipq_ttl;
+ fp = fp->next;
+ if (fp->prev->ipq_ttl == 0) {
+ ipstat.ips_fragtimeout++;
+ ip_freef(fp->prev);
+ }
+ }
+ }
+ splx(s);
+}
+
+/*
+ * Drain off all datagram fragments.
+ */
+void
+ip_drain()
+{
+ int i;
+
+ for (i = 0; i < IPREASS_NHASH; i++) {
+ while (ipq[i].next != &ipq[i]) {
+ ipstat.ips_fragdropped++;
+ ip_freef(ipq[i].next);
+ }
+ }
+ in_rtqdrain();
+}
+
+/*
+ * Do option processing on a datagram,
+ * possibly discarding it if bad options are encountered,
+ * or forwarding it if source-routed.
+ * Returns 1 if packet has been forwarded/freed,
+ * 0 if the packet should be processed further.
+ */
+static int
+ip_dooptions(m)
+ struct mbuf *m;
+{
+ register struct ip *ip = mtod(m, struct ip *);
+ register u_char *cp;
+ register struct ip_timestamp *ipt;
+ register struct in_ifaddr *ia;
+ int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0;
+ struct in_addr *sin, dst;
+ n_time ntime;
+
+ dst = ip->ip_dst;
+ cp = (u_char *)(ip + 1);
+ cnt = (IP_VHL_HL(ip->ip_vhl) << 2) - sizeof (struct ip);
+ for (; cnt > 0; cnt -= optlen, cp += optlen) {
+ opt = cp[IPOPT_OPTVAL];
+ if (opt == IPOPT_EOL)
+ break;
+ if (opt == IPOPT_NOP)
+ optlen = 1;
+ else {
+ optlen = cp[IPOPT_OLEN];
+ if (optlen <= 0 || optlen > cnt) {
+ code = &cp[IPOPT_OLEN] - (u_char *)ip;
+ goto bad;
+ }
+ }
+ switch (opt) {
+
+ default:
+ break;
+
+ /*
+ * Source routing with record.
+ * Find interface with current destination address.
+ * If none on this machine then drop if strictly routed,
+ * or do nothing if loosely routed.
+ * Record interface address and bring up next address
+ * component. If strictly routed make sure next
+ * address is on directly accessible net.
+ */
+ case IPOPT_LSRR:
+ case IPOPT_SSRR:
+ if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
+ code = &cp[IPOPT_OFFSET] - (u_char *)ip;
+ goto bad;
+ }
+ ipaddr.sin_addr = ip->ip_dst;
+ ia = (struct in_ifaddr *)
+ ifa_ifwithaddr((struct sockaddr *)&ipaddr);
+ if (ia == 0) {
+ if (opt == IPOPT_SSRR) {
+ type = ICMP_UNREACH;
+ code = ICMP_UNREACH_SRCFAIL;
+ goto bad;
+ }
+ if (!ip_dosourceroute)
+ goto nosourcerouting;
+ /*
+ * Loose routing, and not at next destination
+ * yet; nothing to do except forward.
+ */
+ break;
+ }
+ off--; /* 0 origin */
+ if (off > optlen - sizeof(struct in_addr)) {
+ /*
+ * End of source route. Should be for us.
+ */
+ if (!ip_acceptsourceroute)
+ goto nosourcerouting;
+ save_rte(cp, ip->ip_src);
+ break;
+ }
+
+ if (!ip_dosourceroute) {
+ char buf[4*sizeof "123"];
+
+nosourcerouting:
+ strcpy(buf, inet_ntoa(ip->ip_dst));
+ log(LOG_WARNING,
+ "attempted source route from %s to %s\n",
+ inet_ntoa(ip->ip_src), buf);
+ type = ICMP_UNREACH;
+ code = ICMP_UNREACH_SRCFAIL;
+ goto bad;
+ }
+
+ /*
+ * locate outgoing interface
+ */
+ (void)memcpy(&ipaddr.sin_addr, cp + off,
+ sizeof(ipaddr.sin_addr));
+
+ if (opt == IPOPT_SSRR) {
+#define INA struct in_ifaddr *
+#define SA struct sockaddr *
+ if ((ia = (INA)ifa_ifwithdstaddr((SA)&ipaddr)) == 0)
+ ia = (INA)ifa_ifwithnet((SA)&ipaddr);
+ } else
+ ia = ip_rtaddr(ipaddr.sin_addr);
+ if (ia == 0) {
+ type = ICMP_UNREACH;
+ code = ICMP_UNREACH_SRCFAIL;
+ goto bad;
+ }
+ ip->ip_dst = ipaddr.sin_addr;
+ (void)memcpy(cp + off, &(IA_SIN(ia)->sin_addr),
+ sizeof(struct in_addr));
+ cp[IPOPT_OFFSET] += sizeof(struct in_addr);
+ /*
+ * Let ip_intr's mcast routing check handle mcast pkts
+ */
+ forward = !IN_MULTICAST(ntohl(ip->ip_dst.s_addr));
+ break;
+
+ case IPOPT_RR:
+ if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
+ code = &cp[IPOPT_OFFSET] - (u_char *)ip;
+ goto bad;
+ }
+ /*
+ * If no space remains, ignore.
+ */
+ off--; /* 0 origin */
+ if (off > optlen - sizeof(struct in_addr))
+ break;
+ (void)memcpy(&ipaddr.sin_addr, &ip->ip_dst,
+ sizeof(ipaddr.sin_addr));
+ /*
+ * locate outgoing interface; if we're the destination,
+ * use the incoming interface (should be same).
+ */
+ if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) == 0 &&
+ (ia = ip_rtaddr(ipaddr.sin_addr)) == 0) {
+ type = ICMP_UNREACH;
+ code = ICMP_UNREACH_HOST;
+ goto bad;
+ }
+ (void)memcpy(cp + off, &(IA_SIN(ia)->sin_addr),
+ sizeof(struct in_addr));
+ cp[IPOPT_OFFSET] += sizeof(struct in_addr);
+ break;
+
+ case IPOPT_TS:
+ code = cp - (u_char *)ip;
+ ipt = (struct ip_timestamp *)cp;
+ if (ipt->ipt_len < 5)
+ goto bad;
+ if (ipt->ipt_ptr > ipt->ipt_len - sizeof (long)) {
+ if (++ipt->ipt_oflw == 0)
+ goto bad;
+ break;
+ }
+ sin = (struct in_addr *)(cp + ipt->ipt_ptr - 1);
+ switch (ipt->ipt_flg) {
+
+ case IPOPT_TS_TSONLY:
+ break;
+
+ case IPOPT_TS_TSANDADDR:
+ if (ipt->ipt_ptr + sizeof(n_time) +
+ sizeof(struct in_addr) > ipt->ipt_len)
+ goto bad;
+ ipaddr.sin_addr = dst;
+ ia = (INA)ifaof_ifpforaddr((SA)&ipaddr,
+ m->m_pkthdr.rcvif);
+ if (ia == 0)
+ continue;
+ (void)memcpy(sin, &IA_SIN(ia)->sin_addr,
+ sizeof(struct in_addr));
+ ipt->ipt_ptr += sizeof(struct in_addr);
+ break;
+
+ case IPOPT_TS_PRESPEC:
+ if (ipt->ipt_ptr + sizeof(n_time) +
+ sizeof(struct in_addr) > ipt->ipt_len)
+ goto bad;
+ (void)memcpy(&ipaddr.sin_addr, sin,
+ sizeof(struct in_addr));
+ if (ifa_ifwithaddr((SA)&ipaddr) == 0)
+ continue;
+ ipt->ipt_ptr += sizeof(struct in_addr);
+ break;
+
+ default:
+ goto bad;
+ }
+ ntime = iptime();
+ (void)memcpy(cp + ipt->ipt_ptr - 1, &ntime,
+ sizeof(n_time));
+ ipt->ipt_ptr += sizeof(n_time);
+ }
+ }
+ if (forward && ipforwarding) {
+ ip_forward(m, 1);
+ return (1);
+ }
+ return (0);
+bad:
+ ip->ip_len -= IP_VHL_HL(ip->ip_vhl) << 2; /* XXX icmp_error adds in hdr length */
+ icmp_error(m, type, code, 0, 0);
+ ipstat.ips_badoptions++;
+ return (1);
+}
+
+/*
+ * Given address of next destination (final or next hop),
+ * return internet address info of interface to be used to get there.
+ */
+static struct in_ifaddr *
+ip_rtaddr(dst)
+ struct in_addr dst;
+{
+ register struct sockaddr_in *sin;
+
+ sin = (struct sockaddr_in *) &ipforward_rt.ro_dst;
+
+ if (ipforward_rt.ro_rt == 0 || dst.s_addr != sin->sin_addr.s_addr) {
+ if (ipforward_rt.ro_rt) {
+ RTFREE(ipforward_rt.ro_rt);
+ ipforward_rt.ro_rt = 0;
+ }
+ sin->sin_family = AF_INET;
+ sin->sin_len = sizeof(*sin);
+ sin->sin_addr = dst;
+
+ rtalloc_ign(&ipforward_rt, RTF_PRCLONING);
+ }
+ if (ipforward_rt.ro_rt == 0)
+ return ((struct in_ifaddr *)0);
+ return ((struct in_ifaddr *) ipforward_rt.ro_rt->rt_ifa);
+}
+
+/*
+ * Save incoming source route for use in replies,
+ * to be picked up later by ip_srcroute if the receiver is interested.
+ */
+void
+save_rte(option, dst)
+ u_char *option;
+ struct in_addr dst;
+{
+ unsigned olen;
+
+ olen = option[IPOPT_OLEN];
+#ifdef DIAGNOSTIC
+ if (ipprintfs)
+ printf("save_rte: olen %d\n", olen);
+#endif
+ if (olen > sizeof(ip_srcrt) - (1 + sizeof(dst)))
+ return;
+ bcopy(option, ip_srcrt.srcopt, olen);
+ ip_nhops = (olen - IPOPT_OFFSET - 1) / sizeof(struct in_addr);
+ ip_srcrt.dst = dst;
+}
+
+/*
+ * Retrieve incoming source route for use in replies,
+ * in the same form used by setsockopt.
+ * The first hop is placed before the options, will be removed later.
+ */
+struct mbuf *
+ip_srcroute()
+{
+ register struct in_addr *p, *q;
+ register struct mbuf *m;
+
+ if (ip_nhops == 0)
+ return ((struct mbuf *)0);
+ m = m_get(M_DONTWAIT, MT_SOOPTS);
+ if (m == 0)
+ return ((struct mbuf *)0);
+
+#define OPTSIZ (sizeof(ip_srcrt.nop) + sizeof(ip_srcrt.srcopt))
+
+ /* length is (nhops+1)*sizeof(addr) + sizeof(nop + srcrt header) */
+ m->m_len = ip_nhops * sizeof(struct in_addr) + sizeof(struct in_addr) +
+ OPTSIZ;
+#ifdef DIAGNOSTIC
+ if (ipprintfs)
+ printf("ip_srcroute: nhops %d mlen %d", ip_nhops, m->m_len);
+#endif
+
+ /*
+ * First save first hop for return route
+ */
+ p = &ip_srcrt.route[ip_nhops - 1];
+ *(mtod(m, struct in_addr *)) = *p--;
+#ifdef DIAGNOSTIC
+ if (ipprintfs)
+ printf(" hops %lx", ntohl(mtod(m, struct in_addr *)->s_addr));
+#endif
+
+ /*
+ * Copy option fields and padding (nop) to mbuf.
+ */
+ ip_srcrt.nop = IPOPT_NOP;
+ ip_srcrt.srcopt[IPOPT_OFFSET] = IPOPT_MINOFF;
+ (void)memcpy(mtod(m, caddr_t) + sizeof(struct in_addr),
+ &ip_srcrt.nop, OPTSIZ);
+ q = (struct in_addr *)(mtod(m, caddr_t) +
+ sizeof(struct in_addr) + OPTSIZ);
+#undef OPTSIZ
+ /*
+ * Record return path as an IP source route,
+ * reversing the path (pointers are now aligned).
+ */
+ while (p >= ip_srcrt.route) {
+#ifdef DIAGNOSTIC
+ if (ipprintfs)
+ printf(" %lx", ntohl(q->s_addr));
+#endif
+ *q++ = *p--;
+ }
+ /*
+ * Last hop goes to final destination.
+ */
+ *q = ip_srcrt.dst;
+#ifdef DIAGNOSTIC
+ if (ipprintfs)
+ printf(" %lx\n", ntohl(q->s_addr));
+#endif
+ return (m);
+}
+
+/*
+ * Strip out IP options, at higher
+ * level protocol in the kernel.
+ * Second argument is buffer to which options
+ * will be moved, and return value is their length.
+ * XXX should be deleted; last arg currently ignored.
+ */
+void
+ip_stripoptions(m, mopt)
+ register struct mbuf *m;
+ struct mbuf *mopt;
+{
+ register int i;
+ struct ip *ip = mtod(m, struct ip *);
+ register caddr_t opts;
+ int olen;
+
+ olen = (IP_VHL_HL(ip->ip_vhl) << 2) - sizeof (struct ip);
+ opts = (caddr_t)(ip + 1);
+ i = m->m_len - (sizeof (struct ip) + olen);
+ bcopy(opts + olen, opts, (unsigned)i);
+ m->m_len -= olen;
+ if (m->m_flags & M_PKTHDR)
+ m->m_pkthdr.len -= olen;
+ ip->ip_vhl = IP_MAKE_VHL(IPVERSION, sizeof(struct ip) >> 2);
+}
+
+u_char inetctlerrmap[PRC_NCMDS] = {
+ 0, 0, 0, 0,
+ 0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH,
+ EHOSTUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED,
+ EMSGSIZE, EHOSTUNREACH, 0, 0,
+ 0, 0, 0, 0,
+ ENOPROTOOPT
+};
+
+/*
+ * Forward a packet. If some error occurs return the sender
+ * an icmp packet. Note we can't always generate a meaningful
+ * icmp message because icmp doesn't have a large enough repertoire
+ * of codes and types.
+ *
+ * If not forwarding, just drop the packet. This could be confusing
+ * if ipforwarding was zero but some routing protocol was advancing
+ * us as a gateway to somewhere. However, we must let the routing
+ * protocol deal with that.
+ *
+ * The srcrt parameter indicates whether the packet is being forwarded
+ * via a source route.
+ */
+static void
+ip_forward(m, srcrt)
+ struct mbuf *m;
+ int srcrt;
+{
+ register struct ip *ip = mtod(m, struct ip *);
+ register struct sockaddr_in *sin;
+ register struct rtentry *rt;
+ int error, type = 0, code = 0;
+ struct mbuf *mcopy;
+ n_long dest;
+ struct ifnet *destifp;
+
+ dest = 0;
+#ifdef DIAGNOSTIC
+ if (ipprintfs)
+ printf("forward: src %lx dst %lx ttl %x\n",
+ ip->ip_src.s_addr, ip->ip_dst.s_addr, ip->ip_ttl);
+#endif
+
+
+ if (m->m_flags & M_BCAST || in_canforward(ip->ip_dst) == 0) {
+ ipstat.ips_cantforward++;
+ m_freem(m);
+ return;
+ }
+ HTONS(ip->ip_id);
+ if (ip->ip_ttl <= IPTTLDEC) {
+ icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, dest, 0);
+ return;
+ }
+ ip->ip_ttl -= IPTTLDEC;
+
+ sin = (struct sockaddr_in *)&ipforward_rt.ro_dst;
+ if ((rt = ipforward_rt.ro_rt) == 0 ||
+ ip->ip_dst.s_addr != sin->sin_addr.s_addr) {
+ if (ipforward_rt.ro_rt) {
+ RTFREE(ipforward_rt.ro_rt);
+ ipforward_rt.ro_rt = 0;
+ }
+ sin->sin_family = AF_INET;
+ sin->sin_len = sizeof(*sin);
+ sin->sin_addr = ip->ip_dst;
+
+ rtalloc_ign(&ipforward_rt, RTF_PRCLONING);
+ if (ipforward_rt.ro_rt == 0) {
+ icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, dest, 0);
+ return;
+ }
+ rt = ipforward_rt.ro_rt;
+ }
+
+ /*
+ * Save at most 64 bytes of the packet in case
+ * we need to generate an ICMP message to the src.
+ */
+ mcopy = m_copy(m, 0, imin((int)ip->ip_len, 64));
+
+ /*
+ * If forwarding packet using same interface that it came in on,
+ * perhaps should send a redirect to sender to shortcut a hop.
+ * Only send redirect if source is sending directly to us,
+ * and if packet was not source routed (or has any options).
+ * Also, don't send redirect if forwarding using a default route
+ * or a route modified by a redirect.
+ */
+#define satosin(sa) ((struct sockaddr_in *)(sa))
+ if (rt->rt_ifp == m->m_pkthdr.rcvif &&
+ (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 &&
+ satosin(rt_key(rt))->sin_addr.s_addr != 0 &&
+ ipsendredirects && !srcrt) {
+#define RTA(rt) ((struct in_ifaddr *)(rt->rt_ifa))
+ u_long src = ntohl(ip->ip_src.s_addr);
+
+ if (RTA(rt) &&
+ (src & RTA(rt)->ia_subnetmask) == RTA(rt)->ia_subnet) {
+ if (rt->rt_flags & RTF_GATEWAY)
+ dest = satosin(rt->rt_gateway)->sin_addr.s_addr;
+ else
+ dest = ip->ip_dst.s_addr;
+ /* Router requirements says to only send host redirects */
+ type = ICMP_REDIRECT;
+ code = ICMP_REDIRECT_HOST;
+#ifdef DIAGNOSTIC
+ if (ipprintfs)
+ printf("redirect (%d) to %lx\n", code, (u_long)dest);
+#endif
+ }
+ }
+
+ error = ip_output(m, (struct mbuf *)0, &ipforward_rt,
+ IP_FORWARDING, 0);
+ if (error)
+ ipstat.ips_cantforward++;
+ else {
+ ipstat.ips_forward++;
+ if (type)
+ ipstat.ips_redirectsent++;
+ else {
+ if (mcopy)
+ m_freem(mcopy);
+ return;
+ }
+ }
+ if (mcopy == NULL)
+ return;
+ destifp = NULL;
+
+ switch (error) {
+
+ case 0: /* forwarded, but need redirect */
+ /* type, code set above */
+ break;
+
+ case ENETUNREACH: /* shouldn't happen, checked above */
+ case EHOSTUNREACH:
+ case ENETDOWN:
+ case EHOSTDOWN:
+ default:
+ type = ICMP_UNREACH;
+ code = ICMP_UNREACH_HOST;
+ break;
+
+ case EMSGSIZE:
+ type = ICMP_UNREACH;
+ code = ICMP_UNREACH_NEEDFRAG;
+ if (ipforward_rt.ro_rt)
+ destifp = ipforward_rt.ro_rt->rt_ifp;
+ ipstat.ips_cantfrag++;
+ break;
+
+ case ENOBUFS:
+ type = ICMP_SOURCEQUENCH;
+ code = 0;
+ break;
+ }
+ icmp_error(mcopy, type, code, dest, destifp);
+}
+
+void
+ip_savecontrol(inp, mp, ip, m)
+ register struct inpcb *inp;
+ register struct mbuf **mp;
+ register struct ip *ip;
+ register struct mbuf *m;
+{
+ if (inp->inp_socket->so_options & SO_TIMESTAMP) {
+ struct timeval tv;
+
+ microtime(&tv);
+ *mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv),
+ SCM_TIMESTAMP, SOL_SOCKET);
+ if (*mp)
+ mp = &(*mp)->m_next;
+ }
+ if (inp->inp_flags & INP_RECVDSTADDR) {
+ *mp = sbcreatecontrol((caddr_t) &ip->ip_dst,
+ sizeof(struct in_addr), IP_RECVDSTADDR, IPPROTO_IP);
+ if (*mp)
+ mp = &(*mp)->m_next;
+ }
+#ifdef notyet
+ /* XXX
+ * Moving these out of udp_input() made them even more broken
+ * than they already were.
+ */
+ /* options were tossed already */
+ if (inp->inp_flags & INP_RECVOPTS) {
+ *mp = sbcreatecontrol((caddr_t) opts_deleted_above,
+ sizeof(struct in_addr), IP_RECVOPTS, IPPROTO_IP);
+ if (*mp)
+ mp = &(*mp)->m_next;
+ }
+ /* ip_srcroute doesn't do what we want here, need to fix */
+ if (inp->inp_flags & INP_RECVRETOPTS) {
+ *mp = sbcreatecontrol((caddr_t) ip_srcroute(),
+ sizeof(struct in_addr), IP_RECVRETOPTS, IPPROTO_IP);
+ if (*mp)
+ mp = &(*mp)->m_next;
+ }
+#endif
+ if (inp->inp_flags & INP_RECVIF) {
+ struct sockaddr_dl sdl;
+
+ sdl.sdl_len = offsetof(struct sockaddr_dl, sdl_data[0]);
+ sdl.sdl_family = AF_LINK;
+ sdl.sdl_index = m->m_pkthdr.rcvif ?
+ m->m_pkthdr.rcvif->if_index : 0;
+ sdl.sdl_nlen = sdl.sdl_alen = sdl.sdl_slen = 0;
+ *mp = sbcreatecontrol((caddr_t) &sdl, sdl.sdl_len,
+ IP_RECVIF, IPPROTO_IP);
+ if (*mp)
+ mp = &(*mp)->m_next;
+ }
+}
+
+int
+ip_rsvp_init(struct socket *so)
+{
+ if (so->so_type != SOCK_RAW ||
+ so->so_proto->pr_protocol != IPPROTO_RSVP)
+ return EOPNOTSUPP;
+
+ if (ip_rsvpd != NULL)
+ return EADDRINUSE;
+
+ ip_rsvpd = so;
+ /*
+ * This may seem silly, but we need to be sure we don't over-increment
+ * the RSVP counter, in case something slips up.
+ */
+ if (!ip_rsvp_on) {
+ ip_rsvp_on = 1;
+ rsvp_on++;
+ }
+
+ return 0;
+}
+
+int
+ip_rsvp_done(void)
+{
+ ip_rsvpd = NULL;
+ /*
+ * This may seem silly, but we need to be sure we don't over-decrement
+ * the RSVP counter, in case something slips up.
+ */
+ if (ip_rsvp_on) {
+ ip_rsvp_on = 0;
+ rsvp_on--;
+ }
+ return 0;
+}
diff --git a/cpukit/libnetworking/netinet/ip_mroute.c b/cpukit/libnetworking/netinet/ip_mroute.c
new file mode 100644
index 0000000000..662d695dfe
--- /dev/null
+++ b/cpukit/libnetworking/netinet/ip_mroute.c
@@ -0,0 +1,2302 @@
+/*
+ * IP multicast forwarding procedures
+ *
+ * Written by David Waitzman, BBN Labs, August 1988.
+ * Modified by Steve Deering, Stanford, February 1989.
+ * Modified by Mark J. Steiglitz, Stanford, May, 1991
+ * Modified by Van Jacobson, LBL, January 1993
+ * Modified by Ajit Thyagarajan, PARC, August 1993
+ * Modified by Bill Fenner, PARC, April 1995
+ *
+ * MROUTING Revision: 3.5
+ * $Id$
+ */
+
+#include "opt_mrouting.h"
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/protosw.h>
+#include <sys/errno.h>
+#include <sys/time.h>
+#include <sys/kernel.h>
+#include <sys/ioctl.h>
+#include <sys/syslog.h>
+#include <net/if.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/in_pcb.h>
+#include <netinet/in_var.h>
+#include <netinet/igmp.h>
+#include <netinet/igmp_var.h>
+#include <netinet/ip_mroute.h>
+#include <netinet/udp.h>
+
+#ifndef NTOHL
+#if BYTE_ORDER != BIG_ENDIAN
+#define NTOHL(d) ((d) = ntohl((d)))
+#define NTOHS(d) ((d) = ntohs((u_short)(d)))
+#define HTONL(d) ((d) = htonl((d)))
+#define HTONS(d) ((d) = htons((u_short)(d)))
+#else
+#define NTOHL(d)
+#define NTOHS(d)
+#define HTONL(d)
+#define HTONS(d)
+#endif
+#endif
+
+#ifndef MROUTING
+extern u_long _ip_mcast_src __P((int vifi));
+extern int _ip_mforward __P((struct ip *ip, struct ifnet *ifp,
+ struct mbuf *m, struct ip_moptions *imo));
+extern int _ip_mrouter_done __P((void));
+extern int _ip_mrouter_get __P((int cmd, struct socket *so,
+ struct mbuf **m));
+extern int _ip_mrouter_set __P((int cmd, struct socket *so,
+ struct mbuf *m));
+extern int _mrt_ioctl __P((int req, caddr_t data, struct proc *p));
+
+/*
+ * Dummy routines and globals used when multicast routing is not compiled in.
+ */
+
+struct socket *ip_mrouter = NULL;
+/* static u_int ip_mrtproto = 0; */
+/* static struct mrtstat mrtstat; */
+u_int rsvpdebug = 0;
+
+int
+_ip_mrouter_set(cmd, so, m)
+ int cmd;
+ struct socket *so;
+ struct mbuf *m;
+{
+ return(EOPNOTSUPP);
+}
+
+int (*ip_mrouter_set)(int, struct socket *, struct mbuf *) = _ip_mrouter_set;
+
+
+int
+_ip_mrouter_get(cmd, so, m)
+ int cmd;
+ struct socket *so;
+ struct mbuf **m;
+{
+ return(EOPNOTSUPP);
+}
+
+int (*ip_mrouter_get)(int, struct socket *, struct mbuf **) = _ip_mrouter_get;
+
+int
+_ip_mrouter_done()
+{
+ return(0);
+}
+
+int (*ip_mrouter_done)(void) = _ip_mrouter_done;
+
+int
+_ip_mforward(ip, ifp, m, imo)
+ struct ip *ip;
+ struct ifnet *ifp;
+ struct mbuf *m;
+ struct ip_moptions *imo;
+{
+ return(0);
+}
+
+int (*ip_mforward)(struct ip *, struct ifnet *, struct mbuf *,
+ struct ip_moptions *) = _ip_mforward;
+
+int
+_mrt_ioctl(int req, caddr_t data, struct proc *p)
+{
+ return EOPNOTSUPP;
+}
+
+int (*mrt_ioctl)(int, caddr_t, struct proc *) = _mrt_ioctl;
+
+void
+rsvp_input(m, iphlen) /* XXX must fixup manually */
+ struct mbuf *m;
+ int iphlen;
+{
+ /* Can still get packets with rsvp_on = 0 if there is a local member
+ * of the group to which the RSVP packet is addressed. But in this
+ * case we want to throw the packet away.
+ */
+ if (!rsvp_on) {
+ m_freem(m);
+ return;
+ }
+
+ if (ip_rsvpd != NULL) {
+ if (rsvpdebug)
+ printf("rsvp_input: Sending packet up old-style socket\n");
+ rip_input(m, iphlen);
+ return;
+ }
+ /* Drop the packet */
+ m_freem(m);
+}
+
+void ipip_input(struct mbuf *m, int iphlen) { /* XXX must fixup manually */
+ rip_input(m, iphlen);
+}
+
+int (*legal_vif_num)(int) = 0;
+
+/*
+ * This should never be called, since IP_MULTICAST_VIF should fail, but
+ * just in case it does get called, the code a little lower in ip_output
+ * will assign the packet a local address.
+ */
+u_long
+_ip_mcast_src(int vifi) { return INADDR_ANY; }
+u_long (*ip_mcast_src)(int) = _ip_mcast_src;
+
+int
+ip_rsvp_vif_init(so, m)
+ struct socket *so;
+ struct mbuf *m;
+{
+ return(EINVAL);
+}
+
+int
+ip_rsvp_vif_done(so, m)
+ struct socket *so;
+ struct mbuf *m;
+{
+ return(EINVAL);
+}
+
+void
+ip_rsvp_force_done(so)
+ struct socket *so;
+{
+ return;
+}
+
+#else /* MROUTING */
+
+#define M_HASCL(m) ((m)->m_flags & M_EXT)
+
+#define INSIZ sizeof(struct in_addr)
+#define same(a1, a2) \
+ (bcmp((caddr_t)(a1), (caddr_t)(a2), INSIZ) == 0)
+
+#define MT_MRTABLE MT_RTABLE /* since nothing else uses it */
+
+/*
+ * Globals. All but ip_mrouter and ip_mrtproto could be static,
+ * except for netstat or debugging purposes.
+ */
+#ifndef MROUTE_LKM
+struct socket *ip_mrouter = NULL;
+struct mrtstat mrtstat;
+
+int ip_mrtproto = IGMP_DVMRP; /* for netstat only */
+#else /* MROUTE_LKM */
+extern void X_ipip_input __P((struct mbuf *m, int iphlen));
+extern struct mrtstat mrtstat;
+static int ip_mrtproto;
+#endif
+
+#define NO_RTE_FOUND 0x1
+#define RTE_FOUND 0x2
+
+static struct mbuf *mfctable[MFCTBLSIZ];
+static u_char nexpire[MFCTBLSIZ];
+static struct vif viftable[MAXVIFS];
+static u_int mrtdebug = 0; /* debug level */
+#define DEBUG_MFC 0x02
+#define DEBUG_FORWARD 0x04
+#define DEBUG_EXPIRE 0x08
+#define DEBUG_XMIT 0x10
+static u_int tbfdebug = 0; /* tbf debug level */
+static u_int rsvpdebug = 0; /* rsvp debug level */
+
+#define EXPIRE_TIMEOUT (hz / 4) /* 4x / second */
+#define UPCALL_EXPIRE 6 /* number of timeouts */
+
+/*
+ * Define the token bucket filter structures
+ * tbftable -> each vif has one of these for storing info
+ */
+
+static struct tbf tbftable[MAXVIFS];
+#define TBF_REPROCESS (hz / 100) /* 100x / second */
+
+/*
+ * 'Interfaces' associated with decapsulator (so we can tell
+ * packets that went through it from ones that get reflected
+ * by a broken gateway). These interfaces are never linked into
+ * the system ifnet list & no routes point to them. I.e., packets
+ * can't be sent this way. They only exist as a placeholder for
+ * multicast source verification.
+ */
+static struct ifnet multicast_decap_if[MAXVIFS];
+
+#define ENCAP_TTL 64
+#define ENCAP_PROTO IPPROTO_IPIP /* 4 */
+
+/* prototype IP hdr for encapsulated packets */
+static struct ip multicast_encap_iphdr = {
+#if BYTE_ORDER == LITTLE_ENDIAN
+ sizeof(struct ip) >> 2, IPVERSION,
+#else
+ IPVERSION, sizeof(struct ip) >> 2,
+#endif
+ 0, /* tos */
+ sizeof(struct ip), /* total length */
+ 0, /* id */
+ 0, /* frag offset */
+ ENCAP_TTL, ENCAP_PROTO,
+ 0, /* checksum */
+};
+
+/*
+ * Private variables.
+ */
+static vifi_t numvifs = 0;
+static int have_encap_tunnel = 0;
+
+/*
+ * one-back cache used by ipip_input to locate a tunnel's vif
+ * given a datagram's src ip address.
+ */
+static u_long last_encap_src;
+static struct vif *last_encap_vif;
+
+static u_long X_ip_mcast_src __P((int vifi));
+static int X_ip_mforward __P((struct ip *ip, struct ifnet *ifp, struct mbuf *m, struct ip_moptions *imo));
+static int X_ip_mrouter_done __P((void));
+static int X_ip_mrouter_get __P((int cmd, struct socket *so, struct mbuf **m));
+static int X_ip_mrouter_set __P((int cmd, struct socket *so, struct mbuf *m));
+static int X_legal_vif_num __P((int vif));
+static int X_mrt_ioctl __P((int cmd, caddr_t data));
+
+static int get_sg_cnt(struct sioc_sg_req *);
+static int get_vif_cnt(struct sioc_vif_req *);
+static int ip_mrouter_init(struct socket *, struct mbuf *);
+static int add_vif(struct vifctl *);
+static int del_vif(vifi_t *);
+static int add_mfc(struct mfcctl *);
+static int del_mfc(struct mfcctl *);
+static int socket_send(struct socket *, struct mbuf *, struct sockaddr_in *);
+static int get_version(struct mbuf *);
+static int get_assert(struct mbuf *);
+static int set_assert(int *);
+static void expire_upcalls(void *);
+static int ip_mdq(struct mbuf *, struct ifnet *, struct mfc *,
+ vifi_t);
+static void phyint_send(struct ip *, struct vif *, struct mbuf *);
+static void encap_send(struct ip *, struct vif *, struct mbuf *);
+static void tbf_control(struct vif *, struct mbuf *, struct ip *, u_long);
+static void tbf_queue(struct vif *, struct mbuf *);
+static void tbf_process_q(struct vif *);
+static void tbf_reprocess_q(void *);
+static int tbf_dq_sel(struct vif *, struct ip *);
+static void tbf_send_packet(struct vif *, struct mbuf *);
+static void tbf_update_tokens(struct vif *);
+static int priority(struct vif *, struct ip *);
+void multiencap_decap(struct mbuf *);
+
+/*
+ * whether or not special PIM assert processing is enabled.
+ */
+static int pim_assert;
+/*
+ * Rate limit for assert notification messages, in usec
+ */
+#define ASSERT_MSG_TIME 3000000
+
+/*
+ * Hash function for a source, group entry
+ */
+#define MFCHASH(a, g) MFCHASHMOD(((a) >> 20) ^ ((a) >> 10) ^ (a) ^ \
+ ((g) >> 20) ^ ((g) >> 10) ^ (g))
+
+/*
+ * Find a route for a given origin IP address and Multicast group address
+ * Type of service parameter to be added in the future!!!
+ */
+
+#define MFCFIND(o, g, rt) { \
+ register struct mbuf *_mb_rt = mfctable[MFCHASH(o,g)]; \
+ register struct mfc *_rt = NULL; \
+ rt = NULL; \
+ ++mrtstat.mrts_mfc_lookups; \
+ while (_mb_rt) { \
+ _rt = mtod(_mb_rt, struct mfc *); \
+ if ((_rt->mfc_origin.s_addr == o) && \
+ (_rt->mfc_mcastgrp.s_addr == g) && \
+ (_mb_rt->m_act == NULL)) { \
+ rt = _rt; \
+ break; \
+ } \
+ _mb_rt = _mb_rt->m_next; \
+ } \
+ if (rt == NULL) { \
+ ++mrtstat.mrts_mfc_misses; \
+ } \
+}
+
+
+/*
+ * Macros to compute elapsed time efficiently
+ * Borrowed from Van Jacobson's scheduling code
+ */
+#define TV_DELTA(a, b, delta) { \
+ register int xxs; \
+ \
+ delta = (a).tv_usec - (b).tv_usec; \
+ if ((xxs = (a).tv_sec - (b).tv_sec)) { \
+ switch (xxs) { \
+ case 2: \
+ delta += 1000000; \
+ /* fall through */ \
+ case 1: \
+ delta += 1000000; \
+ break; \
+ default: \
+ delta += (1000000 * xxs); \
+ } \
+ } \
+}
+
+#define TV_LT(a, b) (((a).tv_usec < (b).tv_usec && \
+ (a).tv_sec <= (b).tv_sec) || (a).tv_sec < (b).tv_sec)
+
+#ifdef UPCALL_TIMING
+u_long upcall_data[51];
+static void collate(struct timeval *);
+#endif /* UPCALL_TIMING */
+
+
+/*
+ * Handle MRT setsockopt commands to modify the multicast routing tables.
+ */
+static int
+X_ip_mrouter_set(cmd, so, m)
+ int cmd;
+ struct socket *so;
+ struct mbuf *m;
+{
+ if (cmd != MRT_INIT && so != ip_mrouter) return EACCES;
+
+ switch (cmd) {
+ case MRT_INIT: return ip_mrouter_init(so, m);
+ case MRT_DONE: return ip_mrouter_done();
+ case MRT_ADD_VIF: return add_vif (mtod(m, struct vifctl *));
+ case MRT_DEL_VIF: return del_vif (mtod(m, vifi_t *));
+ case MRT_ADD_MFC: return add_mfc (mtod(m, struct mfcctl *));
+ case MRT_DEL_MFC: return del_mfc (mtod(m, struct mfcctl *));
+ case MRT_ASSERT: return set_assert(mtod(m, int *));
+ default: return EOPNOTSUPP;
+ }
+}
+
+#ifndef MROUTE_LKM
+int (*ip_mrouter_set)(int, struct socket *, struct mbuf *) = X_ip_mrouter_set;
+#endif
+
+/*
+ * Handle MRT getsockopt commands
+ */
+static int
+X_ip_mrouter_get(cmd, so, m)
+ int cmd;
+ struct socket *so;
+ struct mbuf **m;
+{
+ struct mbuf *mb;
+
+ if (so != ip_mrouter) return EACCES;
+
+ *m = mb = m_get(M_WAIT, MT_SOOPTS);
+
+ switch (cmd) {
+ case MRT_VERSION: return get_version(mb);
+ case MRT_ASSERT: return get_assert(mb);
+ default: return EOPNOTSUPP;
+ }
+}
+
+#ifndef MROUTE_LKM
+int (*ip_mrouter_get)(int, struct socket *, struct mbuf **) = X_ip_mrouter_get;
+#endif
+
+/*
+ * Handle ioctl commands to obtain information from the cache
+ */
+static int
+X_mrt_ioctl(cmd, data)
+ int cmd;
+ caddr_t data;
+{
+ int error = 0;
+
+ switch (cmd) {
+ case (SIOCGETVIFCNT):
+ return (get_vif_cnt((struct sioc_vif_req *)data));
+ break;
+ case (SIOCGETSGCNT):
+ return (get_sg_cnt((struct sioc_sg_req *)data));
+ break;
+ default:
+ return (EINVAL);
+ break;
+ }
+ return error;
+}
+
+#ifndef MROUTE_LKM
+int (*mrt_ioctl)(int, caddr_t) = X_mrt_ioctl;
+#endif
+
+/*
+ * returns the packet, byte, rpf-failure count for the source group provided
+ */
+static int
+get_sg_cnt(req)
+ register struct sioc_sg_req *req;
+{
+ register struct mfc *rt;
+ int s;
+
+ s = splnet();
+ MFCFIND(req->src.s_addr, req->grp.s_addr, rt);
+ splx(s);
+ if (rt != NULL) {
+ req->pktcnt = rt->mfc_pkt_cnt;
+ req->bytecnt = rt->mfc_byte_cnt;
+ req->wrong_if = rt->mfc_wrong_if;
+ } else
+ req->pktcnt = req->bytecnt = req->wrong_if = 0xffffffff;
+
+ return 0;
+}
+
+/*
+ * returns the input and output packet and byte counts on the vif provided
+ */
+static int
+get_vif_cnt(req)
+ register struct sioc_vif_req *req;
+{
+ register vifi_t vifi = req->vifi;
+
+ if (vifi >= numvifs) return EINVAL;
+
+ req->icount = viftable[vifi].v_pkt_in;
+ req->ocount = viftable[vifi].v_pkt_out;
+ req->ibytes = viftable[vifi].v_bytes_in;
+ req->obytes = viftable[vifi].v_bytes_out;
+
+ return 0;
+}
+
+/*
+ * Enable multicast routing
+ */
+static int
+ip_mrouter_init(so, m)
+ struct socket *so;
+ struct mbuf *m;
+{
+ int *v;
+
+ if (mrtdebug)
+ log(LOG_DEBUG,"ip_mrouter_init: so_type = %d, pr_protocol = %d\n",
+ so->so_type, so->so_proto->pr_protocol);
+
+ if (so->so_type != SOCK_RAW ||
+ so->so_proto->pr_protocol != IPPROTO_IGMP) return EOPNOTSUPP;
+
+ if (!m || (m->m_len != sizeof(int *)))
+ return ENOPROTOOPT;
+
+ v = mtod(m, int *);
+ if (*v != 1)
+ return ENOPROTOOPT;
+
+ if (ip_mrouter != NULL) return EADDRINUSE;
+
+ ip_mrouter = so;
+
+ bzero((caddr_t)mfctable, sizeof(mfctable));
+ bzero((caddr_t)nexpire, sizeof(nexpire));
+
+ pim_assert = 0;
+
+ timeout(expire_upcalls, (caddr_t)NULL, EXPIRE_TIMEOUT);
+
+ if (mrtdebug)
+ log(LOG_DEBUG, "ip_mrouter_init\n");
+
+ return 0;
+}
+
+/*
+ * Disable multicast routing
+ */
+static int
+X_ip_mrouter_done()
+{
+ vifi_t vifi;
+ int i;
+ struct ifnet *ifp;
+ struct ifreq ifr;
+ struct mbuf *mb_rt;
+ struct mbuf *m;
+ struct rtdetq *rte;
+ int s;
+
+ s = splnet();
+
+ /*
+ * For each phyint in use, disable promiscuous reception of all IP
+ * multicasts.
+ */
+ for (vifi = 0; vifi < numvifs; vifi++) {
+ if (viftable[vifi].v_lcl_addr.s_addr != 0 &&
+ !(viftable[vifi].v_flags & VIFF_TUNNEL)) {
+ ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET;
+ ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr.s_addr
+ = INADDR_ANY;
+ ifp = viftable[vifi].v_ifp;
+ (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr);
+ }
+ }
+ bzero((caddr_t)tbftable, sizeof(tbftable));
+ bzero((caddr_t)viftable, sizeof(viftable));
+ numvifs = 0;
+ pim_assert = 0;
+
+ untimeout(expire_upcalls, (caddr_t)NULL);
+
+ /*
+ * Free all multicast forwarding cache entries.
+ */
+ for (i = 0; i < MFCTBLSIZ; i++) {
+ mb_rt = mfctable[i];
+ while (mb_rt) {
+ if (mb_rt->m_act != NULL) {
+ while (mb_rt->m_act) {
+ m = mb_rt->m_act;
+ mb_rt->m_act = m->m_act;
+ rte = mtod(m, struct rtdetq *);
+ m_freem(rte->m);
+ m_free(m);
+ }
+ }
+ mb_rt = m_free(mb_rt);
+ }
+ }
+
+ bzero((caddr_t)mfctable, sizeof(mfctable));
+
+ /*
+ * Reset de-encapsulation cache
+ */
+ last_encap_src = 0;
+ last_encap_vif = NULL;
+ have_encap_tunnel = 0;
+
+ ip_mrouter = NULL;
+
+ splx(s);
+
+ if (mrtdebug)
+ log(LOG_DEBUG, "ip_mrouter_done\n");
+
+ return 0;
+}
+
+#ifndef MROUTE_LKM
+int (*ip_mrouter_done)(void) = X_ip_mrouter_done;
+#endif
+
+static int
+get_version(mb)
+ struct mbuf *mb;
+{
+ int *v;
+
+ v = mtod(mb, int *);
+
+ *v = 0x0305; /* XXX !!!! */
+ mb->m_len = sizeof(int);
+
+ return 0;
+}
+
+/*
+ * Set PIM assert processing global
+ */
+static int
+set_assert(i)
+ int *i;
+{
+ if ((*i != 1) && (*i != 0))
+ return EINVAL;
+
+ pim_assert = *i;
+
+ return 0;
+}
+
+/*
+ * Get PIM assert processing global
+ */
+static int
+get_assert(m)
+ struct mbuf *m;
+{
+ int *i;
+
+ i = mtod(m, int *);
+
+ *i = pim_assert;
+
+ return 0;
+}
+
+/*
+ * Add a vif to the vif table
+ */
+static int
+add_vif(vifcp)
+ register struct vifctl *vifcp;
+{
+ register struct vif *vifp = viftable + vifcp->vifc_vifi;
+ static struct sockaddr_in sin = {sizeof sin, AF_INET};
+ struct ifaddr *ifa;
+ struct ifnet *ifp;
+ struct ifreq ifr;
+ int error, s;
+ struct tbf *v_tbf = tbftable + vifcp->vifc_vifi;
+
+ if (vifcp->vifc_vifi >= MAXVIFS) return EINVAL;
+ if (vifp->v_lcl_addr.s_addr != 0) return EADDRINUSE;
+
+ /* Find the interface with an address in AF_INET family */
+ sin.sin_addr = vifcp->vifc_lcl_addr;
+ ifa = ifa_ifwithaddr((struct sockaddr *)&sin);
+ if (ifa == 0) return EADDRNOTAVAIL;
+ ifp = ifa->ifa_ifp;
+
+ if (vifcp->vifc_flags & VIFF_TUNNEL) {
+ if ((vifcp->vifc_flags & VIFF_SRCRT) == 0) {
+ /*
+ * An encapsulating tunnel is wanted. Tell ipip_input() to
+ * start paying attention to encapsulated packets.
+ */
+ if (have_encap_tunnel == 0) {
+ have_encap_tunnel = 1;
+ for (s = 0; s < MAXVIFS; ++s) {
+ multicast_decap_if[s].if_name = "mdecap";
+ multicast_decap_if[s].if_unit = s;
+ }
+ }
+ /*
+ * Set interface to fake encapsulator interface
+ */
+ ifp = &multicast_decap_if[vifcp->vifc_vifi];
+ /*
+ * Prepare cached route entry
+ */
+ bzero(&vifp->v_route, sizeof(vifp->v_route));
+ } else {
+ log(LOG_ERR, "source routed tunnels not supported\n");
+ return EOPNOTSUPP;
+ }
+ } else {
+ /* Make sure the interface supports multicast */
+ if ((ifp->if_flags & IFF_MULTICAST) == 0)
+ return EOPNOTSUPP;
+
+ /* Enable promiscuous reception of all IP multicasts from the if */
+ ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET;
+ ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr.s_addr = INADDR_ANY;
+ s = splnet();
+ error = (*ifp->if_ioctl)(ifp, SIOCADDMULTI, (caddr_t)&ifr);
+ splx(s);
+ if (error)
+ return error;
+ }
+
+ s = splnet();
+ /* define parameters for the tbf structure */
+ vifp->v_tbf = v_tbf;
+ GET_TIME(vifp->v_tbf->tbf_last_pkt_t);
+ vifp->v_tbf->tbf_n_tok = 0;
+ vifp->v_tbf->tbf_q_len = 0;
+ vifp->v_tbf->tbf_max_q_len = MAXQSIZE;
+ vifp->v_tbf->tbf_q = vifp->v_tbf->tbf_t = NULL;
+
+ vifp->v_flags = vifcp->vifc_flags;
+ vifp->v_threshold = vifcp->vifc_threshold;
+ vifp->v_lcl_addr = vifcp->vifc_lcl_addr;
+ vifp->v_rmt_addr = vifcp->vifc_rmt_addr;
+ vifp->v_ifp = ifp;
+ /* scaling up here allows division by 1024 in critical code */
+ vifp->v_rate_limit= vifcp->vifc_rate_limit * 1024 / 1000;
+ vifp->v_rsvp_on = 0;
+ vifp->v_rsvpd = NULL;
+ /* initialize per vif pkt counters */
+ vifp->v_pkt_in = 0;
+ vifp->v_pkt_out = 0;
+ vifp->v_bytes_in = 0;
+ vifp->v_bytes_out = 0;
+ splx(s);
+
+ /* Adjust numvifs up if the vifi is higher than numvifs */
+ if (numvifs <= vifcp->vifc_vifi) numvifs = vifcp->vifc_vifi + 1;
+
+ if (mrtdebug)
+ log(LOG_DEBUG, "add_vif #%d, lcladdr %x, %s %x, thresh %x, rate %d\n",
+ vifcp->vifc_vifi,
+ ntohl(vifcp->vifc_lcl_addr.s_addr),
+ (vifcp->vifc_flags & VIFF_TUNNEL) ? "rmtaddr" : "mask",
+ ntohl(vifcp->vifc_rmt_addr.s_addr),
+ vifcp->vifc_threshold,
+ vifcp->vifc_rate_limit);
+
+ return 0;
+}
+
+/*
+ * Delete a vif from the vif table
+ */
+static int
+del_vif(vifip)
+ vifi_t *vifip;
+{
+ register struct vif *vifp = viftable + *vifip;
+ register vifi_t vifi;
+ register struct mbuf *m;
+ struct ifnet *ifp;
+ struct ifreq ifr;
+ int s;
+
+ if (*vifip >= numvifs) return EINVAL;
+ if (vifp->v_lcl_addr.s_addr == 0) return EADDRNOTAVAIL;
+
+ s = splnet();
+
+ if (!(vifp->v_flags & VIFF_TUNNEL)) {
+ ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET;
+ ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr.s_addr = INADDR_ANY;
+ ifp = vifp->v_ifp;
+ (*ifp->if_ioctl)(ifp, SIOCDELMULTI, (caddr_t)&ifr);
+ }
+
+ if (vifp == last_encap_vif) {
+ last_encap_vif = 0;
+ last_encap_src = 0;
+ }
+
+ /*
+ * Free packets queued at the interface
+ */
+ while (vifp->v_tbf->tbf_q) {
+ m = vifp->v_tbf->tbf_q;
+ vifp->v_tbf->tbf_q = m->m_act;
+ m_freem(m);
+ }
+
+ bzero((caddr_t)vifp->v_tbf, sizeof(*(vifp->v_tbf)));
+ bzero((caddr_t)vifp, sizeof (*vifp));
+
+ /* Adjust numvifs down */
+ for (vifi = numvifs; vifi > 0; vifi--)
+ if (viftable[vifi-1].v_lcl_addr.s_addr != 0) break;
+ numvifs = vifi;
+
+ splx(s);
+
+ if (mrtdebug)
+ log(LOG_DEBUG, "del_vif %d, numvifs %d\n", *vifip, numvifs);
+
+ return 0;
+}
+
+/*
+ * Add an mfc entry
+ */
+static int
+add_mfc(mfccp)
+ struct mfcctl *mfccp;
+{
+ struct mfc *rt;
+ register struct mbuf *mb_rt;
+ u_long hash;
+ struct mbuf *mb_ntry;
+ struct rtdetq *rte;
+ register u_short nstl;
+ int s;
+ int i;
+
+ MFCFIND(mfccp->mfcc_origin.s_addr, mfccp->mfcc_mcastgrp.s_addr, rt);
+
+ /* If an entry already exists, just update the fields */
+ if (rt) {
+ if (mrtdebug & DEBUG_MFC)
+ log(LOG_DEBUG,"add_mfc update o %x g %x p %x\n",
+ ntohl(mfccp->mfcc_origin.s_addr),
+ ntohl(mfccp->mfcc_mcastgrp.s_addr),
+ mfccp->mfcc_parent);
+
+ s = splnet();
+ rt->mfc_parent = mfccp->mfcc_parent;
+ for (i = 0; i < numvifs; i++)
+ rt->mfc_ttls[i] = mfccp->mfcc_ttls[i];
+ splx(s);
+ return 0;
+ }
+
+ /*
+ * Find the entry for which the upcall was made and update
+ */
+ s = splnet();
+ hash = MFCHASH(mfccp->mfcc_origin.s_addr, mfccp->mfcc_mcastgrp.s_addr);
+ for (mb_rt = mfctable[hash], nstl = 0; mb_rt; mb_rt = mb_rt->m_next) {
+
+ rt = mtod(mb_rt, struct mfc *);
+ if ((rt->mfc_origin.s_addr == mfccp->mfcc_origin.s_addr) &&
+ (rt->mfc_mcastgrp.s_addr == mfccp->mfcc_mcastgrp.s_addr) &&
+ (mb_rt->m_act != NULL)) {
+
+ if (nstl++)
+ log(LOG_ERR, "add_mfc %s o %x g %x p %x dbx %x\n",
+ "multiple kernel entries",
+ ntohl(mfccp->mfcc_origin.s_addr),
+ ntohl(mfccp->mfcc_mcastgrp.s_addr),
+ mfccp->mfcc_parent, mb_rt->m_act);
+
+ if (mrtdebug & DEBUG_MFC)
+ log(LOG_DEBUG,"add_mfc o %x g %x p %x dbg %x\n",
+ ntohl(mfccp->mfcc_origin.s_addr),
+ ntohl(mfccp->mfcc_mcastgrp.s_addr),
+ mfccp->mfcc_parent, mb_rt->m_act);
+
+ rt->mfc_origin = mfccp->mfcc_origin;
+ rt->mfc_mcastgrp = mfccp->mfcc_mcastgrp;
+ rt->mfc_parent = mfccp->mfcc_parent;
+ for (i = 0; i < numvifs; i++)
+ rt->mfc_ttls[i] = mfccp->mfcc_ttls[i];
+ /* initialize pkt counters per src-grp */
+ rt->mfc_pkt_cnt = 0;
+ rt->mfc_byte_cnt = 0;
+ rt->mfc_wrong_if = 0;
+ rt->mfc_last_assert.tv_sec = rt->mfc_last_assert.tv_usec = 0;
+
+ rt->mfc_expire = 0; /* Don't clean this guy up */
+ nexpire[hash]--;
+
+ /* free packets Qed at the end of this entry */
+ while (mb_rt->m_act) {
+ mb_ntry = mb_rt->m_act;
+ rte = mtod(mb_ntry, struct rtdetq *);
+/* #ifdef RSVP_ISI */
+ ip_mdq(rte->m, rte->ifp, rt, -1);
+/* #endif */
+ mb_rt->m_act = mb_ntry->m_act;
+ m_freem(rte->m);
+#ifdef UPCALL_TIMING
+ collate(&(rte->t));
+#endif /* UPCALL_TIMING */
+ m_free(mb_ntry);
+ }
+ }
+ }
+
+ /*
+ * It is possible that an entry is being inserted without an upcall
+ */
+ if (nstl == 0) {
+ if (mrtdebug & DEBUG_MFC)
+ log(LOG_DEBUG,"add_mfc no upcall h %d o %x g %x p %x\n",
+ hash, ntohl(mfccp->mfcc_origin.s_addr),
+ ntohl(mfccp->mfcc_mcastgrp.s_addr),
+ mfccp->mfcc_parent);
+
+ for (mb_rt = mfctable[hash]; mb_rt; mb_rt = mb_rt->m_next) {
+
+ rt = mtod(mb_rt, struct mfc *);
+ if ((rt->mfc_origin.s_addr == mfccp->mfcc_origin.s_addr) &&
+ (rt->mfc_mcastgrp.s_addr == mfccp->mfcc_mcastgrp.s_addr)) {
+
+ rt->mfc_origin = mfccp->mfcc_origin;
+ rt->mfc_mcastgrp = mfccp->mfcc_mcastgrp;
+ rt->mfc_parent = mfccp->mfcc_parent;
+ for (i = 0; i < numvifs; i++)
+ rt->mfc_ttls[i] = mfccp->mfcc_ttls[i];
+ /* initialize pkt counters per src-grp */
+ rt->mfc_pkt_cnt = 0;
+ rt->mfc_byte_cnt = 0;
+ rt->mfc_wrong_if = 0;
+ rt->mfc_last_assert.tv_sec = rt->mfc_last_assert.tv_usec = 0;
+ if (rt->mfc_expire)
+ nexpire[hash]--;
+ rt->mfc_expire = 0;
+ }
+ }
+ if (mb_rt == NULL) {
+ /* no upcall, so make a new entry */
+ MGET(mb_rt, M_DONTWAIT, MT_MRTABLE);
+ if (mb_rt == NULL) {
+ splx(s);
+ return ENOBUFS;
+ }
+
+ rt = mtod(mb_rt, struct mfc *);
+
+ /* insert new entry at head of hash chain */
+ rt->mfc_origin = mfccp->mfcc_origin;
+ rt->mfc_mcastgrp = mfccp->mfcc_mcastgrp;
+ rt->mfc_parent = mfccp->mfcc_parent;
+ for (i = 0; i < numvifs; i++)
+ rt->mfc_ttls[i] = mfccp->mfcc_ttls[i];
+ /* initialize pkt counters per src-grp */
+ rt->mfc_pkt_cnt = 0;
+ rt->mfc_byte_cnt = 0;
+ rt->mfc_wrong_if = 0;
+ rt->mfc_last_assert.tv_sec = rt->mfc_last_assert.tv_usec = 0;
+ rt->mfc_expire = 0;
+
+ /* link into table */
+ mb_rt->m_next = mfctable[hash];
+ mfctable[hash] = mb_rt;
+ mb_rt->m_act = NULL;
+ }
+ }
+ splx(s);
+ return 0;
+}
+
+#ifdef UPCALL_TIMING
+/*
+ * collect delay statistics on the upcalls
+ */
+static void collate(t)
+register struct timeval *t;
+{
+ register u_long d;
+ register struct timeval tp;
+ register u_long delta;
+
+ GET_TIME(tp);
+
+ if (TV_LT(*t, tp))
+ {
+ TV_DELTA(tp, *t, delta);
+
+ d = delta >> 10;
+ if (d > 50)
+ d = 50;
+
+ ++upcall_data[d];
+ }
+}
+#endif /* UPCALL_TIMING */
+
+/*
+ * Delete an mfc entry
+ */
+static int
+del_mfc(mfccp)
+ struct mfcctl *mfccp;
+{
+ struct in_addr origin;
+ struct in_addr mcastgrp;
+ struct mfc *rt;
+ struct mbuf *mb_rt;
+ struct mbuf **nptr;
+ u_long hash;
+ int s;
+
+ origin = mfccp->mfcc_origin;
+ mcastgrp = mfccp->mfcc_mcastgrp;
+ hash = MFCHASH(origin.s_addr, mcastgrp.s_addr);
+
+ if (mrtdebug & DEBUG_MFC)
+ log(LOG_DEBUG,"del_mfc orig %x mcastgrp %x\n",
+ ntohl(origin.s_addr), ntohl(mcastgrp.s_addr));
+
+ s = splnet();
+
+ nptr = &mfctable[hash];
+ while ((mb_rt = *nptr) != NULL) {
+ rt = mtod(mb_rt, struct mfc *);
+ if (origin.s_addr == rt->mfc_origin.s_addr &&
+ mcastgrp.s_addr == rt->mfc_mcastgrp.s_addr &&
+ mb_rt->m_act == NULL)
+ break;
+
+ nptr = &mb_rt->m_next;
+ }
+ if (mb_rt == NULL) {
+ splx(s);
+ return EADDRNOTAVAIL;
+ }
+
+ MFREE(mb_rt, *nptr);
+
+ splx(s);
+
+ return 0;
+}
+
+/*
+ * Send a message to mrouted on the multicast routing socket
+ */
+static int
+socket_send(s, mm, src)
+ struct socket *s;
+ struct mbuf *mm;
+ struct sockaddr_in *src;
+{
+ if (s) {
+ if (sbappendaddr(&s->so_rcv,
+ (struct sockaddr *)src,
+ mm, (struct mbuf *)0) != 0) {
+ sorwakeup(s);
+ return 0;
+ }
+ }
+ m_freem(mm);
+ return -1;
+}
+
+/*
+ * IP multicast forwarding function. This function assumes that the packet
+ * pointed to by "ip" has arrived on (or is about to be sent to) the interface
+ * pointed to by "ifp", and the packet is to be relayed to other networks
+ * that have members of the packet's destination IP multicast group.
+ *
+ * The packet is returned unscathed to the caller, unless it is
+ * erroneous, in which case a non-zero return value tells the caller to
+ * discard it.
+ */
+
+#define IP_HDR_LEN 20 /* # bytes of fixed IP header (excluding options) */
+#define TUNNEL_LEN 12 /* # bytes of IP option for tunnel encapsulation */
+
+static int
+X_ip_mforward(ip, ifp, m, imo)
+ register struct ip *ip;
+ struct ifnet *ifp;
+ struct mbuf *m;
+ struct ip_moptions *imo;
+{
+ register struct mfc *rt;
+ register u_char *ipoptions;
+ static struct sockaddr_in k_igmpsrc = { sizeof k_igmpsrc, AF_INET };
+ static int srctun = 0;
+ register struct mbuf *mm;
+ int s;
+ vifi_t vifi;
+ struct vif *vifp;
+
+ if (mrtdebug & DEBUG_FORWARD)
+ log(LOG_DEBUG, "ip_mforward: src %x, dst %x, ifp %x\n",
+ ntohl(ip->ip_src.s_addr), ntohl(ip->ip_dst.s_addr), ifp);
+
+ if (ip->ip_hl < (IP_HDR_LEN + TUNNEL_LEN) >> 2 ||
+ (ipoptions = (u_char *)(ip + 1))[1] != IPOPT_LSRR ) {
+ /*
+ * Packet arrived via a physical interface or
+ * an encapsulated tunnel.
+ */
+ } else {
+ /*
+ * Packet arrived through a source-route tunnel.
+ * Source-route tunnels are no longer supported.
+ */
+ if ((srctun++ % 1000) == 0)
+ log(LOG_ERR, "ip_mforward: received source-routed packet from %x\n",
+ ntohl(ip->ip_src.s_addr));
+
+ return 1;
+ }
+
+ if ((imo) && ((vifi = imo->imo_multicast_vif) < numvifs)) {
+ if (ip->ip_ttl < 255)
+ ip->ip_ttl++; /* compensate for -1 in *_send routines */
+ if (rsvpdebug && ip->ip_p == IPPROTO_RSVP) {
+ vifp = viftable + vifi;
+ printf("Sending IPPROTO_RSVP from %lx to %lx on vif %d (%s%s%d)\n",
+ ntohl(ip->ip_src.s_addr), ntohl(ip->ip_dst.s_addr), vifi,
+ (vifp->v_flags & VIFF_TUNNEL) ? "tunnel on " : "",
+ vifp->v_ifp->if_name, vifp->v_ifp->if_unit);
+ }
+ return (ip_mdq(m, ifp, NULL, vifi));
+ }
+ if (rsvpdebug && ip->ip_p == IPPROTO_RSVP) {
+ printf("Warning: IPPROTO_RSVP from %lx to %lx without vif option\n",
+ ntohl(ip->ip_src.s_addr), ntohl(ip->ip_dst.s_addr));
+ if(!imo)
+ printf("In fact, no options were specified at all\n");
+ }
+
+ /*
+ * Don't forward a packet with time-to-live of zero or one,
+ * or a packet destined to a local-only group.
+ */
+ if (ip->ip_ttl <= 1 ||
+ ntohl(ip->ip_dst.s_addr) <= INADDR_MAX_LOCAL_GROUP)
+ return 0;
+
+ /*
+ * Determine forwarding vifs from the forwarding cache table
+ */
+ s = splnet();
+ MFCFIND(ip->ip_src.s_addr, ip->ip_dst.s_addr, rt);
+
+ /* Entry exists, so forward if necessary */
+ if (rt != NULL) {
+ splx(s);
+ return (ip_mdq(m, ifp, rt, -1));
+ } else {
+ /*
+ * If we don't have a route for packet's origin,
+ * Make a copy of the packet &
+ * send message to routing daemon
+ */
+
+ register struct mbuf *mb_rt;
+ register struct mbuf *mb_ntry;
+ register struct mbuf *mb0;
+ register struct rtdetq *rte;
+ register struct mbuf *rte_m;
+ register u_long hash;
+ register int npkts;
+ int hlen = ip->ip_hl << 2;
+#ifdef UPCALL_TIMING
+ struct timeval tp;
+
+ GET_TIME(tp);
+#endif
+
+ mrtstat.mrts_no_route++;
+ if (mrtdebug & (DEBUG_FORWARD | DEBUG_MFC))
+ log(LOG_DEBUG, "ip_mforward: no rte s %x g %x\n",
+ ntohl(ip->ip_src.s_addr),
+ ntohl(ip->ip_dst.s_addr));
+
+ /*
+ * Allocate mbufs early so that we don't do extra work if we are
+ * just going to fail anyway. Make sure to pullup the header so
+ * that other people can't step on it.
+ */
+ MGET(mb_ntry, M_DONTWAIT, MT_DATA);
+ if (mb_ntry == NULL) {
+ splx(s);
+ return ENOBUFS;
+ }
+ mb0 = m_copy(m, 0, M_COPYALL);
+ if (mb0 && (M_HASCL(mb0) || mb0->m_len < hlen))
+ mb0 = m_pullup(mb0, hlen);
+ if (mb0 == NULL) {
+ m_free(mb_ntry);
+ splx(s);
+ return ENOBUFS;
+ }
+
+ /* is there an upcall waiting for this packet? */
+ hash = MFCHASH(ip->ip_src.s_addr, ip->ip_dst.s_addr);
+ for (mb_rt = mfctable[hash]; mb_rt; mb_rt = mb_rt->m_next) {
+ rt = mtod(mb_rt, struct mfc *);
+ if ((ip->ip_src.s_addr == rt->mfc_origin.s_addr) &&
+ (ip->ip_dst.s_addr == rt->mfc_mcastgrp.s_addr) &&
+ (mb_rt->m_act != NULL))
+ break;
+ }
+
+ if (mb_rt == NULL) {
+ int i;
+ struct igmpmsg *im;
+
+ /* no upcall, so make a new entry */
+ MGET(mb_rt, M_DONTWAIT, MT_MRTABLE);
+ if (mb_rt == NULL) {
+ m_free(mb_ntry);
+ m_freem(mb0);
+ splx(s);
+ return ENOBUFS;
+ }
+ /* Make a copy of the header to send to the user level process */
+ mm = m_copy(mb0, 0, hlen);
+ if (mm == NULL) {
+ m_free(mb_ntry);
+ m_freem(mb0);
+ m_free(mb_rt);
+ splx(s);
+ return ENOBUFS;
+ }
+
+ /*
+ * Send message to routing daemon to install
+ * a route into the kernel table
+ */
+ k_igmpsrc.sin_addr = ip->ip_src;
+
+ im = mtod(mm, struct igmpmsg *);
+ im->im_msgtype = IGMPMSG_NOCACHE;
+ im->im_mbz = 0;
+
+ mrtstat.mrts_upcalls++;
+
+ if (socket_send(ip_mrouter, mm, &k_igmpsrc) < 0) {
+ log(LOG_WARNING, "ip_mforward: ip_mrouter socket queue full\n");
+ ++mrtstat.mrts_upq_sockfull;
+ m_free(mb_ntry);
+ m_freem(mb0);
+ m_free(mb_rt);
+ splx(s);
+ return ENOBUFS;
+ }
+
+ rt = mtod(mb_rt, struct mfc *);
+
+ /* insert new entry at head of hash chain */
+ rt->mfc_origin.s_addr = ip->ip_src.s_addr;
+ rt->mfc_mcastgrp.s_addr = ip->ip_dst.s_addr;
+ rt->mfc_expire = UPCALL_EXPIRE;
+ nexpire[hash]++;
+ for (i = 0; i < numvifs; i++)
+ rt->mfc_ttls[i] = 0;
+ rt->mfc_parent = -1;
+
+ /* link into table */
+ mb_rt->m_next = mfctable[hash];
+ mfctable[hash] = mb_rt;
+ mb_rt->m_act = NULL;
+
+ rte_m = mb_rt;
+ } else {
+ /* determine if q has overflowed */
+ for (rte_m = mb_rt, npkts = 0; rte_m->m_act; rte_m = rte_m->m_act)
+ npkts++;
+
+ if (npkts > MAX_UPQ) {
+ mrtstat.mrts_upq_ovflw++;
+ m_free(mb_ntry);
+ m_freem(mb0);
+ splx(s);
+ return 0;
+ }
+ }
+
+ mb_ntry->m_act = NULL;
+ rte = mtod(mb_ntry, struct rtdetq *);
+
+ rte->m = mb0;
+ rte->ifp = ifp;
+#ifdef UPCALL_TIMING
+ rte->t = tp;
+#endif
+
+ /* Add this entry to the end of the queue */
+ rte_m->m_act = mb_ntry;
+
+ splx(s);
+
+ return 0;
+ }
+}
+
+#ifndef MROUTE_LKM
+int (*ip_mforward)(struct ip *, struct ifnet *, struct mbuf *,
+ struct ip_moptions *) = X_ip_mforward;
+#endif
+
+/*
+ * Clean up the cache entry if upcall is not serviced
+ */
+static void
+expire_upcalls(void *unused)
+{
+ struct mbuf *mb_rt, *m, **nptr;
+ struct rtdetq *rte;
+ struct mfc *mfc;
+ int i;
+ int s;
+
+ s = splnet();
+ for (i = 0; i < MFCTBLSIZ; i++) {
+ if (nexpire[i] == 0)
+ continue;
+ nptr = &mfctable[i];
+ for (mb_rt = *nptr; mb_rt != NULL; mb_rt = *nptr) {
+ mfc = mtod(mb_rt, struct mfc *);
+
+ /*
+ * Skip real cache entries
+ * Make sure it wasn't marked to not expire (shouldn't happen)
+ * If it expires now
+ */
+ if (mb_rt->m_act != NULL &&
+ mfc->mfc_expire != 0 &&
+ --mfc->mfc_expire == 0) {
+ if (mrtdebug & DEBUG_EXPIRE)
+ log(LOG_DEBUG, "expire_upcalls: expiring (%x %x)\n",
+ ntohl(mfc->mfc_origin.s_addr),
+ ntohl(mfc->mfc_mcastgrp.s_addr));
+ /*
+ * drop all the packets
+ * free the mbuf with the pkt, if, timing info
+ */
+ while (mb_rt->m_act) {
+ m = mb_rt->m_act;
+ mb_rt->m_act = m->m_act;
+
+ rte = mtod(m, struct rtdetq *);
+ m_freem(rte->m);
+ m_free(m);
+ }
+ ++mrtstat.mrts_cache_cleanups;
+ nexpire[i]--;
+
+ MFREE(mb_rt, *nptr);
+ } else {
+ nptr = &mb_rt->m_next;
+ }
+ }
+ }
+ splx(s);
+ timeout(expire_upcalls, (caddr_t)NULL, EXPIRE_TIMEOUT);
+}
+
+/*
+ * Packet forwarding routine once entry in the cache is made
+ */
+static int
+ip_mdq(m, ifp, rt, xmt_vif)
+ register struct mbuf *m;
+ register struct ifnet *ifp;
+ register struct mfc *rt;
+ register vifi_t xmt_vif;
+{
+ register struct ip *ip = mtod(m, struct ip *);
+ register vifi_t vifi;
+ register struct vif *vifp;
+ register int plen = ntohs(ip->ip_len);
+
+/*
+ * Macro to send packet on vif. Since RSVP packets don't get counted on
+ * input, they shouldn't get counted on output, so statistics keeping is
+ * seperate.
+ */
+#define MC_SEND(ip,vifp,m) { \
+ if ((vifp)->v_flags & VIFF_TUNNEL) \
+ encap_send((ip), (vifp), (m)); \
+ else \
+ phyint_send((ip), (vifp), (m)); \
+}
+
+ /*
+ * If xmt_vif is not -1, send on only the requested vif.
+ *
+ * (since vifi_t is u_short, -1 becomes MAXUSHORT, which > numvifs.)
+ */
+ if (xmt_vif < numvifs) {
+ MC_SEND(ip, viftable + xmt_vif, m);
+ return 1;
+ }
+
+ /*
+ * Don't forward if it didn't arrive from the parent vif for its origin.
+ */
+ vifi = rt->mfc_parent;
+ if ((vifi >= numvifs) || (viftable[vifi].v_ifp != ifp)) {
+ /* came in the wrong interface */
+ if (mrtdebug & DEBUG_FORWARD)
+ log(LOG_DEBUG, "wrong if: ifp %x vifi %d vififp %x\n",
+ ifp, vifi, viftable[vifi].v_ifp);
+ ++mrtstat.mrts_wrong_if;
+ ++rt->mfc_wrong_if;
+ /*
+ * If we are doing PIM assert processing, and we are forwarding
+ * packets on this interface, and it is a broadcast medium
+ * interface (and not a tunnel), send a message to the routing daemon.
+ */
+ if (pim_assert && rt->mfc_ttls[vifi] &&
+ (ifp->if_flags & IFF_BROADCAST) &&
+ !(viftable[vifi].v_flags & VIFF_TUNNEL)) {
+ struct sockaddr_in k_igmpsrc;
+ struct mbuf *mm;
+ struct igmpmsg *im;
+ int hlen = ip->ip_hl << 2;
+ struct timeval now;
+ register u_long delta;
+
+ GET_TIME(now);
+
+ TV_DELTA(rt->mfc_last_assert, now, delta);
+
+ if (delta > ASSERT_MSG_TIME) {
+ mm = m_copy(m, 0, hlen);
+ if (mm && (M_HASCL(mm) || mm->m_len < hlen))
+ mm = m_pullup(mm, hlen);
+ if (mm == NULL) {
+ return ENOBUFS;
+ }
+
+ rt->mfc_last_assert = now;
+
+ im = mtod(mm, struct igmpmsg *);
+ im->im_msgtype = IGMPMSG_WRONGVIF;
+ im->im_mbz = 0;
+ im->im_vif = vifi;
+
+ k_igmpsrc.sin_addr = im->im_src;
+
+ socket_send(ip_mrouter, mm, &k_igmpsrc);
+ }
+ }
+ return 0;
+ }
+
+ /* If I sourced this packet, it counts as output, else it was input. */
+ if (ip->ip_src.s_addr == viftable[vifi].v_lcl_addr.s_addr) {
+ viftable[vifi].v_pkt_out++;
+ viftable[vifi].v_bytes_out += plen;
+ } else {
+ viftable[vifi].v_pkt_in++;
+ viftable[vifi].v_bytes_in += plen;
+ }
+ rt->mfc_pkt_cnt++;
+ rt->mfc_byte_cnt += plen;
+
+ /*
+ * For each vif, decide if a copy of the packet should be forwarded.
+ * Forward if:
+ * - the ttl exceeds the vif's threshold
+ * - there are group members downstream on interface
+ */
+ for (vifp = viftable, vifi = 0; vifi < numvifs; vifp++, vifi++)
+ if ((rt->mfc_ttls[vifi] > 0) &&
+ (ip->ip_ttl > rt->mfc_ttls[vifi])) {
+ vifp->v_pkt_out++;
+ vifp->v_bytes_out += plen;
+ MC_SEND(ip, vifp, m);
+ }
+
+ return 0;
+}
+
+/*
+ * check if a vif number is legal/ok. This is used by ip_output, to export
+ * numvifs there,
+ */
+static int
+X_legal_vif_num(vif)
+ int vif;
+{
+ if (vif >= 0 && vif < numvifs)
+ return(1);
+ else
+ return(0);
+}
+
+#ifndef MROUTE_LKM
+int (*legal_vif_num)(int) = X_legal_vif_num;
+#endif
+
+/*
+ * Return the local address used by this vif
+ */
+static u_long
+X_ip_mcast_src(vifi)
+ int vifi;
+{
+ if (vifi >= 0 && vifi < numvifs)
+ return viftable[vifi].v_lcl_addr.s_addr;
+ else
+ return INADDR_ANY;
+}
+
+#ifndef MROUTE_LKM
+u_long (*ip_mcast_src)(int) = X_ip_mcast_src;
+#endif
+
+static void
+phyint_send(ip, vifp, m)
+ struct ip *ip;
+ struct vif *vifp;
+ struct mbuf *m;
+{
+ register struct mbuf *mb_copy;
+ register int hlen = ip->ip_hl << 2;
+
+ /*
+ * Make a new reference to the packet; make sure that
+ * the IP header is actually copied, not just referenced,
+ * so that ip_output() only scribbles on the copy.
+ */
+ mb_copy = m_copy(m, 0, M_COPYALL);
+ if (mb_copy && (M_HASCL(mb_copy) || mb_copy->m_len < hlen))
+ mb_copy = m_pullup(mb_copy, hlen);
+ if (mb_copy == NULL)
+ return;
+
+ if (vifp->v_rate_limit <= 0)
+ tbf_send_packet(vifp, mb_copy);
+ else
+ tbf_control(vifp, mb_copy, mtod(mb_copy, struct ip *), ip->ip_len);
+}
+
+static void
+encap_send(ip, vifp, m)
+ register struct ip *ip;
+ register struct vif *vifp;
+ register struct mbuf *m;
+{
+ register struct mbuf *mb_copy;
+ register struct ip *ip_copy;
+ register int i, len = ip->ip_len;
+
+ /*
+ * copy the old packet & pullup it's IP header into the
+ * new mbuf so we can modify it. Try to fill the new
+ * mbuf since if we don't the ethernet driver will.
+ */
+ MGETHDR(mb_copy, M_DONTWAIT, MT_HEADER);
+ if (mb_copy == NULL)
+ return;
+ mb_copy->m_data += max_linkhdr;
+ mb_copy->m_len = sizeof(multicast_encap_iphdr);
+
+ if ((mb_copy->m_next = m_copy(m, 0, M_COPYALL)) == NULL) {
+ m_freem(mb_copy);
+ return;
+ }
+ i = MHLEN - M_LEADINGSPACE(mb_copy);
+ if (i > len)
+ i = len;
+ mb_copy = m_pullup(mb_copy, i);
+ if (mb_copy == NULL)
+ return;
+ mb_copy->m_pkthdr.len = len + sizeof(multicast_encap_iphdr);
+
+ /*
+ * fill in the encapsulating IP header.
+ */
+ ip_copy = mtod(mb_copy, struct ip *);
+ *ip_copy = multicast_encap_iphdr;
+ ip_copy->ip_id = htons(ip_id++);
+ ip_copy->ip_len += len;
+ ip_copy->ip_src = vifp->v_lcl_addr;
+ ip_copy->ip_dst = vifp->v_rmt_addr;
+
+ /*
+ * turn the encapsulated IP header back into a valid one.
+ */
+ ip = (struct ip *)((caddr_t)ip_copy + sizeof(multicast_encap_iphdr));
+ --ip->ip_ttl;
+ HTONS(ip->ip_len);
+ HTONS(ip->ip_off);
+ ip->ip_sum = 0;
+ mb_copy->m_data += sizeof(multicast_encap_iphdr);
+ ip->ip_sum = in_cksum(mb_copy, ip->ip_hl << 2);
+ mb_copy->m_data -= sizeof(multicast_encap_iphdr);
+
+ if (vifp->v_rate_limit <= 0)
+ tbf_send_packet(vifp, mb_copy);
+ else
+ tbf_control(vifp, mb_copy, ip, ip_copy->ip_len);
+}
+
+/*
+ * De-encapsulate a packet and feed it back through ip input (this
+ * routine is called whenever IP gets a packet with proto type
+ * ENCAP_PROTO and a local destination address).
+ */
+void
+#ifdef MROUTE_LKM
+X_ipip_input(m, iphlen)
+#else
+ipip_input(m, iphlen)
+#endif
+ register struct mbuf *m;
+ int iphlen;
+{
+ struct ifnet *ifp = m->m_pkthdr.rcvif;
+ register struct ip *ip = mtod(m, struct ip *);
+ register int hlen = ip->ip_hl << 2;
+ register int s;
+ register struct ifqueue *ifq;
+ register struct vif *vifp;
+
+ if (!have_encap_tunnel) {
+ rip_input(m, iphlen);
+ return;
+ }
+ /*
+ * dump the packet if it's not to a multicast destination or if
+ * we don't have an encapsulating tunnel with the source.
+ * Note: This code assumes that the remote site IP address
+ * uniquely identifies the tunnel (i.e., that this site has
+ * at most one tunnel with the remote site).
+ */
+ if (! IN_MULTICAST(ntohl(((struct ip *)((char *)ip + hlen))->ip_dst.s_addr))) {
+ ++mrtstat.mrts_bad_tunnel;
+ m_freem(m);
+ return;
+ }
+ if (ip->ip_src.s_addr != last_encap_src) {
+ register struct vif *vife;
+
+ vifp = viftable;
+ vife = vifp + numvifs;
+ last_encap_src = ip->ip_src.s_addr;
+ last_encap_vif = 0;
+ for ( ; vifp < vife; ++vifp)
+ if (vifp->v_rmt_addr.s_addr == ip->ip_src.s_addr) {
+ if ((vifp->v_flags & (VIFF_TUNNEL|VIFF_SRCRT))
+ == VIFF_TUNNEL)
+ last_encap_vif = vifp;
+ break;
+ }
+ }
+ if ((vifp = last_encap_vif) == 0) {
+ last_encap_src = 0;
+ mrtstat.mrts_cant_tunnel++; /*XXX*/
+ m_freem(m);
+ if (mrtdebug)
+ log(LOG_DEBUG, "ip_mforward: no tunnel with %x\n",
+ ntohl(ip->ip_src.s_addr));
+ return;
+ }
+ ifp = vifp->v_ifp;
+
+ if (hlen > IP_HDR_LEN)
+ ip_stripoptions(m, (struct mbuf *) 0);
+ m->m_data += IP_HDR_LEN;
+ m->m_len -= IP_HDR_LEN;
+ m->m_pkthdr.len -= IP_HDR_LEN;
+ m->m_pkthdr.rcvif = ifp;
+
+ ifq = &ipintrq;
+ s = splimp();
+ if (IF_QFULL(ifq)) {
+ IF_DROP(ifq);
+ m_freem(m);
+ } else {
+ IF_ENQUEUE(ifq, m);
+ /*
+ * normally we would need a "schednetisr(NETISR_IP)"
+ * here but we were called by ip_input and it is going
+ * to loop back & try to dequeue the packet we just
+ * queued as soon as we return so we avoid the
+ * unnecessary software interrrupt.
+ */
+ }
+ splx(s);
+}
+
+/*
+ * Token bucket filter module
+ */
+
+static void
+tbf_control(vifp, m, ip, p_len)
+ register struct vif *vifp;
+ register struct mbuf *m;
+ register struct ip *ip;
+ register u_long p_len;
+{
+ register struct tbf *t = vifp->v_tbf;
+
+ if (p_len > MAX_BKT_SIZE) {
+ /* drop if packet is too large */
+ mrtstat.mrts_pkt2large++;
+ m_freem(m);
+ return;
+ }
+
+ tbf_update_tokens(vifp);
+
+ /* if there are enough tokens,
+ * and the queue is empty,
+ * send this packet out
+ */
+
+ if (t->tbf_q_len == 0) {
+ /* queue empty, send packet if enough tokens */
+ if (p_len <= t->tbf_n_tok) {
+ t->tbf_n_tok -= p_len;
+ tbf_send_packet(vifp, m);
+ } else {
+ /* queue packet and timeout till later */
+ tbf_queue(vifp, m);
+ timeout(tbf_reprocess_q, (caddr_t)vifp, TBF_REPROCESS);
+ }
+ } else if (t->tbf_q_len < t->tbf_max_q_len) {
+ /* finite queue length, so queue pkts and process queue */
+ tbf_queue(vifp, m);
+ tbf_process_q(vifp);
+ } else {
+ /* queue length too much, try to dq and queue and process */
+ if (!tbf_dq_sel(vifp, ip)) {
+ mrtstat.mrts_q_overflow++;
+ m_freem(m);
+ return;
+ } else {
+ tbf_queue(vifp, m);
+ tbf_process_q(vifp);
+ }
+ }
+ return;
+}
+
+/*
+ * adds a packet to the queue at the interface
+ */
+static void
+tbf_queue(vifp, m)
+ register struct vif *vifp;
+ register struct mbuf *m;
+{
+ register int s = splnet();
+ register struct tbf *t = vifp->v_tbf;
+
+ if (t->tbf_t == NULL) {
+ /* Queue was empty */
+ t->tbf_q = m;
+ } else {
+ /* Insert at tail */
+ t->tbf_t->m_act = m;
+ }
+
+ /* Set new tail pointer */
+ t->tbf_t = m;
+
+#ifdef DIAGNOSTIC
+ /* Make sure we didn't get fed a bogus mbuf */
+ if (m->m_act)
+ panic("tbf_queue: m_act");
+#endif
+ m->m_act = NULL;
+
+ t->tbf_q_len++;
+
+ splx(s);
+}
+
+
+/*
+ * processes the queue at the interface
+ */
+static void
+tbf_process_q(vifp)
+ register struct vif *vifp;
+{
+ register struct mbuf *m;
+ register int len;
+ register int s = splnet();
+ register struct tbf *t = vifp->v_tbf;
+
+ /* loop through the queue at the interface and send as many packets
+ * as possible
+ */
+ while (t->tbf_q_len > 0) {
+ m = t->tbf_q;
+
+ len = mtod(m, struct ip *)->ip_len;
+
+ /* determine if the packet can be sent */
+ if (len <= t->tbf_n_tok) {
+ /* if so,
+ * reduce no of tokens, dequeue the packet,
+ * send the packet.
+ */
+ t->tbf_n_tok -= len;
+
+ t->tbf_q = m->m_act;
+ if (--t->tbf_q_len == 0)
+ t->tbf_t = NULL;
+
+ m->m_act = NULL;
+ tbf_send_packet(vifp, m);
+
+ } else break;
+ }
+ splx(s);
+}
+
+static void
+tbf_reprocess_q(xvifp)
+ void *xvifp;
+{
+ register struct vif *vifp = xvifp;
+ if (ip_mrouter == NULL)
+ return;
+
+ tbf_update_tokens(vifp);
+
+ tbf_process_q(vifp);
+
+ if (vifp->v_tbf->tbf_q_len)
+ timeout(tbf_reprocess_q, (caddr_t)vifp, TBF_REPROCESS);
+}
+
+/* function that will selectively discard a member of the queue
+ * based on the precedence value and the priority
+ */
+static int
+tbf_dq_sel(vifp, ip)
+ register struct vif *vifp;
+ register struct ip *ip;
+{
+ register int s = splnet();
+ register u_int p;
+ register struct mbuf *m, *last;
+ register struct mbuf **np;
+ register struct tbf *t = vifp->v_tbf;
+
+ p = priority(vifp, ip);
+
+ np = &t->tbf_q;
+ last = NULL;
+ while ((m = *np) != NULL) {
+ if (p > priority(vifp, mtod(m, struct ip *))) {
+ *np = m->m_act;
+ /* If we're removing the last packet, fix the tail pointer */
+ if (m == t->tbf_t)
+ t->tbf_t = last;
+ m_freem(m);
+ /* it's impossible for the queue to be empty, but
+ * we check anyway. */
+ if (--t->tbf_q_len == 0)
+ t->tbf_t = NULL;
+ splx(s);
+ mrtstat.mrts_drop_sel++;
+ return(1);
+ }
+ np = &m->m_act;
+ last = m;
+ }
+ splx(s);
+ return(0);
+}
+
+static void
+tbf_send_packet(vifp, m)
+ register struct vif *vifp;
+ register struct mbuf *m;
+{
+ struct ip_moptions imo;
+ int error;
+ static struct route ro;
+ int s = splnet();
+
+ if (vifp->v_flags & VIFF_TUNNEL) {
+ /* If tunnel options */
+ ip_output(m, (struct mbuf *)0, &vifp->v_route,
+ IP_FORWARDING, (struct ip_moptions *)0);
+ } else {
+ imo.imo_multicast_ifp = vifp->v_ifp;
+ imo.imo_multicast_ttl = mtod(m, struct ip *)->ip_ttl - 1;
+ imo.imo_multicast_loop = 1;
+ imo.imo_multicast_vif = -1;
+
+ /*
+ * Re-entrancy should not be a problem here, because
+ * the packets that we send out and are looped back at us
+ * should get rejected because they appear to come from
+ * the loopback interface, thus preventing looping.
+ */
+ error = ip_output(m, (struct mbuf *)0, &ro,
+ IP_FORWARDING, &imo);
+
+ if (mrtdebug & DEBUG_XMIT)
+ log(LOG_DEBUG, "phyint_send on vif %d err %d\n",
+ vifp - viftable, error);
+ }
+ splx(s);
+}
+
+/* determine the current time and then
+ * the elapsed time (between the last time and time now)
+ * in milliseconds & update the no. of tokens in the bucket
+ */
+static void
+tbf_update_tokens(vifp)
+ register struct vif *vifp;
+{
+ struct timeval tp;
+ register u_long tm;
+ register int s = splnet();
+ register struct tbf *t = vifp->v_tbf;
+
+ GET_TIME(tp);
+
+ TV_DELTA(tp, t->tbf_last_pkt_t, tm);
+
+ /*
+ * This formula is actually
+ * "time in seconds" * "bytes/second".
+ *
+ * (tm / 1000000) * (v_rate_limit * 1000 * (1000/1024) / 8)
+ *
+ * The (1000/1024) was introduced in add_vif to optimize
+ * this divide into a shift.
+ */
+ t->tbf_n_tok += tm * vifp->v_rate_limit / 1024 / 8;
+ t->tbf_last_pkt_t = tp;
+
+ if (t->tbf_n_tok > MAX_BKT_SIZE)
+ t->tbf_n_tok = MAX_BKT_SIZE;
+
+ splx(s);
+}
+
+static int
+priority(vifp, ip)
+ register struct vif *vifp;
+ register struct ip *ip;
+{
+ register int prio;
+
+ /* temporary hack; may add general packet classifier some day */
+
+ /*
+ * The UDP port space is divided up into four priority ranges:
+ * [0, 16384) : unclassified - lowest priority
+ * [16384, 32768) : audio - highest priority
+ * [32768, 49152) : whiteboard - medium priority
+ * [49152, 65536) : video - low priority
+ */
+ if (ip->ip_p == IPPROTO_UDP) {
+ struct udphdr *udp = (struct udphdr *)(((char *)ip) + (ip->ip_hl << 2));
+ switch (ntohs(udp->uh_dport) & 0xc000) {
+ case 0x4000:
+ prio = 70;
+ break;
+ case 0x8000:
+ prio = 60;
+ break;
+ case 0xc000:
+ prio = 55;
+ break;
+ default:
+ prio = 50;
+ break;
+ }
+ if (tbfdebug > 1)
+ log(LOG_DEBUG, "port %x prio%d\n", ntohs(udp->uh_dport), prio);
+ } else {
+ prio = 50;
+ }
+ return prio;
+}
+
+/*
+ * End of token bucket filter modifications
+ */
+
+int
+ip_rsvp_vif_init(so, m)
+ struct socket *so;
+ struct mbuf *m;
+{
+ int i;
+ register int s;
+
+ if (rsvpdebug)
+ printf("ip_rsvp_vif_init: so_type = %d, pr_protocol = %d\n",
+ so->so_type, so->so_proto->pr_protocol);
+
+ if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_RSVP)
+ return EOPNOTSUPP;
+
+ /* Check mbuf. */
+ if (m == NULL || m->m_len != sizeof(int)) {
+ return EINVAL;
+ }
+ i = *(mtod(m, int *));
+
+ if (rsvpdebug)
+ printf("ip_rsvp_vif_init: vif = %d rsvp_on = %d\n",i,rsvp_on);
+
+ s = splnet();
+
+ /* Check vif. */
+ if (!legal_vif_num(i)) {
+ splx(s);
+ return EADDRNOTAVAIL;
+ }
+
+ /* Check if socket is available. */
+ if (viftable[i].v_rsvpd != NULL) {
+ splx(s);
+ return EADDRINUSE;
+ }
+
+ viftable[i].v_rsvpd = so;
+ /* This may seem silly, but we need to be sure we don't over-increment
+ * the RSVP counter, in case something slips up.
+ */
+ if (!viftable[i].v_rsvp_on) {
+ viftable[i].v_rsvp_on = 1;
+ rsvp_on++;
+ }
+
+ splx(s);
+ return 0;
+}
+
+int
+ip_rsvp_vif_done(so, m)
+ struct socket *so;
+ struct mbuf *m;
+{
+ int i;
+ register int s;
+
+ if (rsvpdebug)
+ printf("ip_rsvp_vif_done: so_type = %d, pr_protocol = %d\n",
+ so->so_type, so->so_proto->pr_protocol);
+
+ if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_RSVP)
+ return EOPNOTSUPP;
+
+ /* Check mbuf. */
+ if (m == NULL || m->m_len != sizeof(int)) {
+ return EINVAL;
+ }
+ i = *(mtod(m, int *));
+
+ s = splnet();
+
+ /* Check vif. */
+ if (!legal_vif_num(i)) {
+ splx(s);
+ return EADDRNOTAVAIL;
+ }
+
+ if (rsvpdebug)
+ printf("ip_rsvp_vif_done: v_rsvpd = %p so = %p\n",
+ viftable[i].v_rsvpd, so);
+
+ viftable[i].v_rsvpd = NULL;
+ /* This may seem silly, but we need to be sure we don't over-decrement
+ * the RSVP counter, in case something slips up.
+ */
+ if (viftable[i].v_rsvp_on) {
+ viftable[i].v_rsvp_on = 0;
+ rsvp_on--;
+ }
+
+ splx(s);
+ return 0;
+}
+
+void
+ip_rsvp_force_done(so)
+ struct socket *so;
+{
+ int vifi;
+ register int s;
+
+ /* Don't bother if it is not the right type of socket. */
+ if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_RSVP)
+ return;
+
+ s = splnet();
+
+ /* The socket may be attached to more than one vif...this
+ * is perfectly legal.
+ */
+ for (vifi = 0; vifi < numvifs; vifi++) {
+ if (viftable[vifi].v_rsvpd == so) {
+ viftable[vifi].v_rsvpd = NULL;
+ /* This may seem silly, but we need to be sure we don't
+ * over-decrement the RSVP counter, in case something slips up.
+ */
+ if (viftable[vifi].v_rsvp_on) {
+ viftable[vifi].v_rsvp_on = 0;
+ rsvp_on--;
+ }
+ }
+ }
+
+ splx(s);
+ return;
+}
+
+void
+rsvp_input(m, iphlen)
+ struct mbuf *m;
+ int iphlen;
+{
+ int vifi;
+ register struct ip *ip = mtod(m, struct ip *);
+ static struct sockaddr_in rsvp_src = { sizeof rsvp_src, AF_INET };
+ register int s;
+ struct ifnet *ifp;
+
+ if (rsvpdebug)
+ printf("rsvp_input: rsvp_on %d\n",rsvp_on);
+
+ /* Can still get packets with rsvp_on = 0 if there is a local member
+ * of the group to which the RSVP packet is addressed. But in this
+ * case we want to throw the packet away.
+ */
+ if (!rsvp_on) {
+ m_freem(m);
+ return;
+ }
+
+ /* If the old-style non-vif-associated socket is set, then use
+ * it and ignore the new ones.
+ */
+ if (ip_rsvpd != NULL) {
+ if (rsvpdebug)
+ printf("rsvp_input: Sending packet up old-style socket\n");
+ rip_input(m, iphlen);
+ return;
+ }
+
+ s = splnet();
+
+ if (rsvpdebug)
+ printf("rsvp_input: check vifs\n");
+
+#ifdef DIAGNOSTIC
+ if (!(m->m_flags & M_PKTHDR))
+ panic("rsvp_input no hdr");
+#endif
+
+ ifp = m->m_pkthdr.rcvif;
+ /* Find which vif the packet arrived on. */
+ for (vifi = 0; vifi < numvifs; vifi++) {
+ if (viftable[vifi].v_ifp == ifp)
+ break;
+ }
+
+ if (vifi == numvifs) {
+ /* Can't find vif packet arrived on. Drop packet. */
+ if (rsvpdebug)
+ printf("rsvp_input: Can't find vif for packet...dropping it.\n");
+ m_freem(m);
+ splx(s);
+ return;
+ }
+
+ if (rsvpdebug)
+ printf("rsvp_input: check socket\n");
+
+ if (viftable[vifi].v_rsvpd == NULL) {
+ /* drop packet, since there is no specific socket for this
+ * interface */
+ if (rsvpdebug)
+ printf("rsvp_input: No socket defined for vif %d\n",vifi);
+ m_freem(m);
+ splx(s);
+ return;
+ }
+ rsvp_src.sin_addr = ip->ip_src;
+
+ if (rsvpdebug && m)
+ printf("rsvp_input: m->m_len = %d, sbspace() = %ld\n",
+ m->m_len,sbspace(&(viftable[vifi].v_rsvpd->so_rcv)));
+
+ if (socket_send(viftable[vifi].v_rsvpd, m, &rsvp_src) < 0)
+ if (rsvpdebug)
+ printf("rsvp_input: Failed to append to socket\n");
+ else
+ if (rsvpdebug)
+ printf("rsvp_input: send packet up\n");
+
+ splx(s);
+}
+
+#ifdef MROUTE_LKM
+#include <sys/conf.h>
+#include <sys/exec.h>
+#include <sys/sysent.h>
+#include <sys/lkm.h>
+
+MOD_MISC("ip_mroute_mod")
+
+static int
+ip_mroute_mod_handle(struct lkm_table *lkmtp, int cmd)
+{
+ int i;
+ struct lkm_misc *args = lkmtp->private.lkm_misc;
+ int err = 0;
+
+ switch(cmd) {
+ static int (*old_ip_mrouter_cmd)();
+ static int (*old_ip_mrouter_done)();
+ static int (*old_ip_mforward)();
+ static int (*old_mrt_ioctl)();
+ static void (*old_proto4_input)();
+ static int (*old_legal_vif_num)();
+ extern struct protosw inetsw[];
+
+ case LKM_E_LOAD:
+ if(lkmexists(lkmtp) || ip_mrtproto)
+ return(EEXIST);
+ old_ip_mrouter_cmd = ip_mrouter_cmd;
+ ip_mrouter_cmd = X_ip_mrouter_cmd;
+ old_ip_mrouter_done = ip_mrouter_done;
+ ip_mrouter_done = X_ip_mrouter_done;
+ old_ip_mforward = ip_mforward;
+ ip_mforward = X_ip_mforward;
+ old_mrt_ioctl = mrt_ioctl;
+ mrt_ioctl = X_mrt_ioctl;
+ old_proto4_input = inetsw[ip_protox[ENCAP_PROTO]].pr_input;
+ inetsw[ip_protox[ENCAP_PROTO]].pr_input = X_ipip_input;
+ old_legal_vif_num = legal_vif_num;
+ legal_vif_num = X_legal_vif_num;
+ ip_mrtproto = IGMP_DVMRP;
+
+ printf("\nIP multicast routing loaded\n");
+ break;
+
+ case LKM_E_UNLOAD:
+ if (ip_mrouter)
+ return EINVAL;
+
+ ip_mrouter_cmd = old_ip_mrouter_cmd;
+ ip_mrouter_done = old_ip_mrouter_done;
+ ip_mforward = old_ip_mforward;
+ mrt_ioctl = old_mrt_ioctl;
+ inetsw[ip_protox[ENCAP_PROTO]].pr_input = old_proto4_input;
+ legal_vif_num = old_legal_vif_num;
+ ip_mrtproto = 0;
+ break;
+
+ default:
+ err = EINVAL;
+ break;
+ }
+
+ return(err);
+}
+
+int
+ip_mroute_mod(struct lkm_table *lkmtp, int cmd, int ver) {
+ DISPATCH(lkmtp, cmd, ver, ip_mroute_mod_handle, ip_mroute_mod_handle,
+ nosys);
+}
+
+#endif /* MROUTE_LKM */
+#endif /* MROUTING */
diff --git a/cpukit/libnetworking/netinet/ip_mroute.h b/cpukit/libnetworking/netinet/ip_mroute.h
new file mode 100644
index 0000000000..35d2437089
--- /dev/null
+++ b/cpukit/libnetworking/netinet/ip_mroute.h
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 1989 Stephen Deering.
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Stephen Deering of Stanford University.
+ *
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)ip_mroute.h 8.1 (Berkeley) 6/10/93
+ * $Id$
+ */
+
+#ifndef _NETINET_IP_MROUTE_H_
+#define _NETINET_IP_MROUTE_H_
+
+/*
+ * Definitions for IP multicast forwarding.
+ *
+ * Written by David Waitzman, BBN Labs, August 1988.
+ * Modified by Steve Deering, Stanford, February 1989.
+ * Modified by Ajit Thyagarajan, PARC, August 1993.
+ * Modified by Ajit Thyagarajan, PARC, August 1994.
+ *
+ * MROUTING Revision: 3.3.1.3
+ */
+
+
+/*
+ * Multicast Routing set/getsockopt commands.
+ */
+#define MRT_INIT 100 /* initialize forwarder */
+#define MRT_DONE 101 /* shut down forwarder */
+#define MRT_ADD_VIF 102 /* create virtual interface */
+#define MRT_DEL_VIF 103 /* delete virtual interface */
+#define MRT_ADD_MFC 104 /* insert forwarding cache entry */
+#define MRT_DEL_MFC 105 /* delete forwarding cache entry */
+#define MRT_VERSION 106 /* get kernel version number */
+#define MRT_ASSERT 107 /* enable PIM assert processing */
+
+
+#define GET_TIME(t) microtime(&t)
+
+/*
+ * Types and macros for handling bitmaps with one bit per virtual interface.
+ */
+#define MAXVIFS 32
+typedef u_long vifbitmap_t;
+typedef u_short vifi_t; /* type of a vif index */
+#define ALL_VIFS (vifi_t)-1
+
+#define VIFM_SET(n, m) ((m) |= (1 << (n)))
+#define VIFM_CLR(n, m) ((m) &= ~(1 << (n)))
+#define VIFM_ISSET(n, m) ((m) & (1 << (n)))
+#define VIFM_CLRALL(m) ((m) = 0x00000000)
+#define VIFM_COPY(mfrom, mto) ((mto) = (mfrom))
+#define VIFM_SAME(m1, m2) ((m1) == (m2))
+
+
+/*
+ * Argument structure for MRT_ADD_VIF.
+ * (MRT_DEL_VIF takes a single vifi_t argument.)
+ */
+struct vifctl {
+ vifi_t vifc_vifi; /* the index of the vif to be added */
+ u_char vifc_flags; /* VIFF_ flags defined below */
+ u_char vifc_threshold; /* min ttl required to forward on vif */
+ u_int vifc_rate_limit; /* max rate */
+ struct in_addr vifc_lcl_addr; /* local interface address */
+ struct in_addr vifc_rmt_addr; /* remote address (tunnels only) */
+};
+
+#define VIFF_TUNNEL 0x1 /* vif represents a tunnel end-point */
+#define VIFF_SRCRT 0x2 /* tunnel uses IP source routing */
+
+/*
+ * Argument structure for MRT_ADD_MFC and MRT_DEL_MFC
+ * (mfcc_tos to be added at a future point)
+ */
+struct mfcctl {
+ struct in_addr mfcc_origin; /* ip origin of mcasts */
+ struct in_addr mfcc_mcastgrp; /* multicast group associated*/
+ vifi_t mfcc_parent; /* incoming vif */
+ u_char mfcc_ttls[MAXVIFS]; /* forwarding ttls on vifs */
+};
+
+/*
+ * The kernel's multicast routing statistics.
+ */
+struct mrtstat {
+ u_long mrts_mfc_lookups; /* # forw. cache hash table hits */
+ u_long mrts_mfc_misses; /* # forw. cache hash table misses */
+ u_long mrts_upcalls; /* # calls to mrouted */
+ u_long mrts_no_route; /* no route for packet's origin */
+ u_long mrts_bad_tunnel; /* malformed tunnel options */
+ u_long mrts_cant_tunnel; /* no room for tunnel options */
+ u_long mrts_wrong_if; /* arrived on wrong interface */
+ u_long mrts_upq_ovflw; /* upcall Q overflow */
+ u_long mrts_cache_cleanups; /* # entries with no upcalls */
+ u_long mrts_drop_sel; /* pkts dropped selectively */
+ u_long mrts_q_overflow; /* pkts dropped - Q overflow */
+ u_long mrts_pkt2large; /* pkts dropped - size > BKT SIZE */
+ u_long mrts_upq_sockfull; /* upcalls dropped - socket full */
+};
+
+/*
+ * Argument structure used by mrouted to get src-grp pkt counts
+ */
+struct sioc_sg_req {
+ struct in_addr src;
+ struct in_addr grp;
+ u_long pktcnt;
+ u_long bytecnt;
+ u_long wrong_if;
+};
+
+/*
+ * Argument structure used by mrouted to get vif pkt counts
+ */
+struct sioc_vif_req {
+ vifi_t vifi; /* vif number */
+ u_long icount; /* Input packet count on vif */
+ u_long ocount; /* Output packet count on vif */
+ u_long ibytes; /* Input byte count on vif */
+ u_long obytes; /* Output byte count on vif */
+};
+
+
+/*
+ * The kernel's virtual-interface structure.
+ */
+struct vif {
+ u_char v_flags; /* VIFF_ flags defined above */
+ u_char v_threshold; /* min ttl required to forward on vif*/
+ u_int v_rate_limit; /* max rate */
+ struct tbf *v_tbf; /* token bucket structure at intf. */
+ struct in_addr v_lcl_addr; /* local interface address */
+ struct in_addr v_rmt_addr; /* remote address (tunnels only) */
+ struct ifnet *v_ifp; /* pointer to interface */
+ u_long v_pkt_in; /* # pkts in on interface */
+ u_long v_pkt_out; /* # pkts out on interface */
+ u_long v_bytes_in; /* # bytes in on interface */
+ u_long v_bytes_out; /* # bytes out on interface */
+ struct route v_route; /* cached route if this is a tunnel */
+ u_int v_rsvp_on; /* RSVP listening on this vif */
+ struct socket *v_rsvpd; /* RSVP daemon socket */
+};
+
+/*
+ * The kernel's multicast forwarding cache entry structure
+ * (A field for the type of service (mfc_tos) is to be added
+ * at a future point)
+ */
+struct mfc {
+ struct in_addr mfc_origin; /* IP origin of mcasts */
+ struct in_addr mfc_mcastgrp; /* multicast group associated*/
+ vifi_t mfc_parent; /* incoming vif */
+ u_char mfc_ttls[MAXVIFS]; /* forwarding ttls on vifs */
+ u_long mfc_pkt_cnt; /* pkt count for src-grp */
+ u_long mfc_byte_cnt; /* byte count for src-grp */
+ u_long mfc_wrong_if; /* wrong if for src-grp */
+ int mfc_expire; /* time to clean entry up */
+ struct timeval mfc_last_assert; /* last time I sent an assert*/
+};
+
+/*
+ * Struct used to communicate from kernel to multicast router
+ * note the convenient similarity to an IP packet
+ */
+struct igmpmsg {
+ u_long unused1;
+ u_long unused2;
+ u_char im_msgtype; /* what type of message */
+#define IGMPMSG_NOCACHE 1
+#define IGMPMSG_WRONGVIF 2
+ u_char im_mbz; /* must be zero */
+ u_char im_vif; /* vif rec'd on */
+ u_char unused3;
+ struct in_addr im_src, im_dst;
+};
+
+/*
+ * Argument structure used for pkt info. while upcall is made
+ */
+struct rtdetq {
+ struct mbuf *m; /* A copy of the packet */
+ struct ifnet *ifp; /* Interface pkt came in on */
+ vifi_t xmt_vif; /* Saved copy of imo_multicast_vif */
+#ifdef UPCALL_TIMING
+ struct timeval t; /* Timestamp */
+#endif /* UPCALL_TIMING */
+};
+
+#define MFCTBLSIZ 256
+#if (MFCTBLSIZ & (MFCTBLSIZ - 1)) == 0 /* from sys:route.h */
+#define MFCHASHMOD(h) ((h) & (MFCTBLSIZ - 1))
+#else
+#define MFCHASHMOD(h) ((h) % MFCTBLSIZ)
+#endif
+
+#define MAX_UPQ 4 /* max. no of pkts in upcall Q */
+
+/*
+ * Token Bucket filter code
+ */
+#define MAX_BKT_SIZE 10000 /* 10K bytes size */
+#define MAXQSIZE 10 /* max # of pkts in queue */
+
+/*
+ * the token bucket filter at each vif
+ */
+struct tbf
+{
+ struct timeval tbf_last_pkt_t; /* arr. time of last pkt */
+ u_long tbf_n_tok; /* no of tokens in bucket */
+ u_long tbf_q_len; /* length of queue at this vif */
+ u_long tbf_max_q_len; /* max. queue length */
+ struct mbuf *tbf_q; /* Packet queue */
+ struct mbuf *tbf_t; /* tail-insertion pointer */
+};
+
+#ifdef _KERNEL
+
+extern int (*ip_mrouter_set) __P((int, struct socket *, struct mbuf *));
+extern int (*ip_mrouter_get) __P((int, struct socket *, struct mbuf **));
+extern int (*ip_mrouter_done) __P((void));
+#ifdef MROUTING
+extern int (*mrt_ioctl) __P((int, caddr_t));
+#else
+extern int (*mrt_ioctl) __P((int, caddr_t, struct proc *));
+#endif
+
+#endif /* _KERNEL */
+
+#endif /* _NETINET_IP_MROUTE_H_ */
diff --git a/cpukit/libnetworking/netinet/ip_output.c b/cpukit/libnetworking/netinet/ip_output.c
new file mode 100644
index 0000000000..810f6c7479
--- /dev/null
+++ b/cpukit/libnetworking/netinet/ip_output.c
@@ -0,0 +1,1307 @@
+/*
+ * Copyright (c) 1982, 1986, 1988, 1990, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)ip_output.c 8.3 (Berkeley) 1/21/94
+ * $Id$
+ */
+
+#define _IP_VHL
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/errno.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+
+#include <net/if.h>
+#include <net/route.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/in_pcb.h>
+#include <netinet/in_var.h>
+#include <netinet/ip_var.h>
+
+#ifdef vax
+#include <machine/mtpr.h>
+#endif
+#include <machine/in_cksum.h>
+
+#if !defined(COMPAT_IPFW) || COMPAT_IPFW == 1
+#undef COMPAT_IPFW
+#define COMPAT_IPFW 1
+#else
+#undef COMPAT_IPFW
+#endif
+
+u_short ip_id;
+
+static struct mbuf *ip_insertoptions __P((struct mbuf *, struct mbuf *, int *));
+static void ip_mloopback
+ __P((struct ifnet *, struct mbuf *, struct sockaddr_in *, int));
+static int ip_getmoptions
+ __P((int, struct ip_moptions *, struct mbuf **));
+static int ip_optcopy __P((struct ip *, struct ip *));
+static int ip_pcbopts __P((struct mbuf **, struct mbuf *));
+static int ip_setmoptions
+ __P((int, struct ip_moptions **, struct mbuf *));
+
+extern struct protosw inetsw[];
+
+/*
+ * IP output. The packet in mbuf chain m contains a skeletal IP
+ * header (with len, off, ttl, proto, tos, src, dst).
+ * The mbuf chain containing the packet will be freed.
+ * The mbuf opt, if present, will not be freed.
+ */
+int
+ip_output(m0, opt, ro, flags, imo)
+ struct mbuf *m0;
+ struct mbuf *opt;
+ struct route *ro;
+ int flags;
+ struct ip_moptions *imo;
+{
+ struct ip *ip, *mhip;
+ struct ifnet *ifp;
+ struct mbuf *m = m0;
+ int hlen = sizeof (struct ip);
+ int len, off, error = 0;
+ struct sockaddr_in *dst;
+ struct in_ifaddr *ia;
+ int isbroadcast;
+
+#ifdef DIAGNOSTIC
+ if ((m->m_flags & M_PKTHDR) == 0)
+ panic("ip_output no HDR");
+ if (!ro)
+ panic("ip_output no route, proto = %d",
+ mtod(m, struct ip *)->ip_p);
+#endif
+ if (opt) {
+ m = ip_insertoptions(m, opt, &len);
+ hlen = len;
+ }
+ ip = mtod(m, struct ip *);
+ /*
+ * Fill in IP header.
+ */
+ if ((flags & (IP_FORWARDING|IP_RAWOUTPUT)) == 0) {
+ ip->ip_vhl = IP_MAKE_VHL(IPVERSION, hlen >> 2);
+ ip->ip_off &= IP_DF;
+ ip->ip_id = htons(ip_id++);
+ ipstat.ips_localout++;
+ } else {
+ hlen = IP_VHL_HL(ip->ip_vhl) << 2;
+ }
+
+ dst = (struct sockaddr_in *)&ro->ro_dst;
+ /*
+ * If there is a cached route,
+ * check that it is to the same destination
+ * and is still up. If not, free it and try again.
+ */
+ if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
+ dst->sin_addr.s_addr != ip->ip_dst.s_addr)) {
+ RTFREE(ro->ro_rt);
+ ro->ro_rt = (struct rtentry *)0;
+ }
+ if (ro->ro_rt == 0) {
+ dst->sin_family = AF_INET;
+ dst->sin_len = sizeof(*dst);
+ dst->sin_addr = ip->ip_dst;
+ }
+ /*
+ * If routing to interface only,
+ * short circuit routing lookup.
+ */
+#define ifatoia(ifa) ((struct in_ifaddr *)(ifa))
+#define sintosa(sin) ((struct sockaddr *)(sin))
+ if (flags & IP_ROUTETOIF) {
+ if ((ia = ifatoia(ifa_ifwithdstaddr(sintosa(dst)))) == 0 &&
+ (ia = ifatoia(ifa_ifwithnet(sintosa(dst)))) == 0) {
+ ipstat.ips_noroute++;
+ error = ENETUNREACH;
+ goto bad;
+ }
+ ifp = ia->ia_ifp;
+ ip->ip_ttl = 1;
+ isbroadcast = in_broadcast(dst->sin_addr, ifp);
+ } else {
+ /*
+ * If this is the case, we probably don't want to allocate
+ * a protocol-cloned route since we didn't get one from the
+ * ULP. This lets TCP do its thing, while not burdening
+ * forwarding or ICMP with the overhead of cloning a route.
+ * Of course, we still want to do any cloning requested by
+ * the link layer, as this is probably required in all cases
+ * for correct operation (as it is for ARP).
+ */
+ if (ro->ro_rt == 0)
+ rtalloc_ign(ro, RTF_PRCLONING);
+ if (ro->ro_rt == 0) {
+ ipstat.ips_noroute++;
+ error = EHOSTUNREACH;
+ goto bad;
+ }
+ ia = ifatoia(ro->ro_rt->rt_ifa);
+ ifp = ro->ro_rt->rt_ifp;
+ ro->ro_rt->rt_use++;
+ if (ro->ro_rt->rt_flags & RTF_GATEWAY)
+ dst = (struct sockaddr_in *)ro->ro_rt->rt_gateway;
+ if (ro->ro_rt->rt_flags & RTF_HOST)
+ isbroadcast = (ro->ro_rt->rt_flags & RTF_BROADCAST);
+ else
+ isbroadcast = in_broadcast(dst->sin_addr, ifp);
+ }
+ if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
+ struct in_multi *inm;
+
+ m->m_flags |= M_MCAST;
+ /*
+ * IP destination address is multicast. Make sure "dst"
+ * still points to the address in "ro". (It may have been
+ * changed to point to a gateway address, above.)
+ */
+ dst = (struct sockaddr_in *)&ro->ro_dst;
+ /*
+ * See if the caller provided any multicast options
+ */
+ if (imo != NULL) {
+ ip->ip_ttl = imo->imo_multicast_ttl;
+ if (imo->imo_multicast_ifp != NULL)
+ ifp = imo->imo_multicast_ifp;
+ if (imo->imo_multicast_vif != -1)
+ ip->ip_src.s_addr =
+ ip_mcast_src(imo->imo_multicast_vif);
+ } else
+ ip->ip_ttl = IP_DEFAULT_MULTICAST_TTL;
+ /*
+ * Confirm that the outgoing interface supports multicast.
+ */
+ if ((imo == NULL) || (imo->imo_multicast_vif == -1)) {
+ if ((ifp->if_flags & IFF_MULTICAST) == 0) {
+ ipstat.ips_noroute++;
+ error = ENETUNREACH;
+ goto bad;
+ }
+ }
+ /*
+ * If source address not specified yet, use address
+ * of outgoing interface.
+ */
+ if (ip->ip_src.s_addr == INADDR_ANY) {
+ register struct in_ifaddr *ia;
+
+ for (ia = in_ifaddr; ia; ia = ia->ia_next)
+ if (ia->ia_ifp == ifp) {
+ ip->ip_src = IA_SIN(ia)->sin_addr;
+ break;
+ }
+ }
+
+ IN_LOOKUP_MULTI(ip->ip_dst, ifp, inm);
+ if (inm != NULL &&
+ (imo == NULL || imo->imo_multicast_loop)) {
+ /*
+ * If we belong to the destination multicast group
+ * on the outgoing interface, and the caller did not
+ * forbid loopback, loop back a copy.
+ */
+ ip_mloopback(ifp, m, dst, hlen);
+ }
+ else {
+ /*
+ * If we are acting as a multicast router, perform
+ * multicast forwarding as if the packet had just
+ * arrived on the interface to which we are about
+ * to send. The multicast forwarding function
+ * recursively calls this function, using the
+ * IP_FORWARDING flag to prevent infinite recursion.
+ *
+ * Multicasts that are looped back by ip_mloopback(),
+ * above, will be forwarded by the ip_input() routine,
+ * if necessary.
+ */
+ if (ip_mrouter && (flags & IP_FORWARDING) == 0) {
+ /*
+ * Check if rsvp daemon is running. If not, don't
+ * set ip_moptions. This ensures that the packet
+ * is multicast and not just sent down one link
+ * as prescribed by rsvpd.
+ */
+ if (!rsvp_on)
+ imo = NULL;
+ if (ip_mforward(ip, ifp, m, imo) != 0) {
+ m_freem(m);
+ goto done;
+ }
+ }
+ }
+
+ /*
+ * Multicasts with a time-to-live of zero may be looped-
+ * back, above, but must not be transmitted on a network.
+ * Also, multicasts addressed to the loopback interface
+ * are not sent -- the above call to ip_mloopback() will
+ * loop back a copy if this host actually belongs to the
+ * destination group on the loopback interface.
+ */
+ if (ip->ip_ttl == 0 || ifp->if_flags & IFF_LOOPBACK) {
+ m_freem(m);
+ goto done;
+ }
+
+ goto sendit;
+ }
+#ifndef notdef
+ /*
+ * If source address not specified yet, use address
+ * of outgoing interface.
+ */
+ if (ip->ip_src.s_addr == INADDR_ANY)
+ ip->ip_src = IA_SIN(ia)->sin_addr;
+#endif
+ /*
+ * Verify that we have any chance at all of being able to queue
+ * the packet or packet fragments
+ */
+ if ((ifp->if_snd.ifq_len + ip->ip_len / ifp->if_mtu + 1) >=
+ ifp->if_snd.ifq_maxlen) {
+ error = ENOBUFS;
+ goto bad;
+ }
+
+ /*
+ * Look for broadcast address and
+ * and verify user is allowed to send
+ * such a packet.
+ */
+ if (isbroadcast) {
+ if ((ifp->if_flags & IFF_BROADCAST) == 0) {
+ error = EADDRNOTAVAIL;
+ goto bad;
+ }
+ if ((flags & IP_ALLOWBROADCAST) == 0) {
+ error = EACCES;
+ goto bad;
+ }
+ /* don't allow broadcast messages to be fragmented */
+ if ((u_short)ip->ip_len > ifp->if_mtu) {
+ error = EMSGSIZE;
+ goto bad;
+ }
+ m->m_flags |= M_BCAST;
+ } else {
+ m->m_flags &= ~M_BCAST;
+ }
+
+sendit:
+ /*
+ * IpHack's section.
+ * - Xlate: translate packet's addr/port (NAT).
+ * - Firewall: deny/allow/etc.
+ * - Wrap: fake packet's addr/port <unimpl.>
+ * - Encapsulate: put it in another IP and send out. <unimp.>
+ */
+
+#ifdef COMPAT_IPFW
+ if (ip_nat_ptr && !(*ip_nat_ptr)(&ip, &m, ifp, IP_NAT_OUT)) {
+ error = EACCES;
+ goto done;
+ }
+
+ /*
+ * Check with the firewall...
+ */
+ if (ip_fw_chk_ptr) {
+#ifdef IPDIVERT
+ ip_divert_port = (*ip_fw_chk_ptr)(&ip,
+ hlen, ifp, ip_divert_ignore, &m);
+ ip_divert_ignore = 0;
+ if (ip_divert_port) { /* Divert packet */
+ (*inetsw[ip_protox[IPPROTO_DIVERT]].pr_input)(m, 0);
+ goto done;
+ }
+#else
+ /* If ipfw says divert, we have to just drop packet */
+ if ((*ip_fw_chk_ptr)(&ip, hlen, ifp, 0, &m)) {
+ m_freem(m);
+ goto done;
+ }
+#endif
+ if (!m) {
+ error = EACCES;
+ goto done;
+ }
+ }
+#endif /* COMPAT_IPFW */
+
+ /*
+ * If small enough for interface, can just send directly.
+ */
+ if ((u_short)ip->ip_len <= ifp->if_mtu) {
+ ip->ip_len = htons((u_short)ip->ip_len);
+ ip->ip_off = htons((u_short)ip->ip_off);
+ ip->ip_sum = 0;
+ if (ip->ip_vhl == IP_VHL_BORING) {
+ ip->ip_sum = in_cksum_hdr(ip);
+ } else {
+ ip->ip_sum = in_cksum(m, hlen);
+ }
+ error = (*ifp->if_output)(ifp, m,
+ (struct sockaddr *)dst, ro->ro_rt);
+ goto done;
+ }
+ /*
+ * Too large for interface; fragment if possible.
+ * Must be able to put at least 8 bytes per fragment.
+ */
+ if (ip->ip_off & IP_DF) {
+ error = EMSGSIZE;
+ /*
+ * This case can happen if the user changed the MTU
+ * of an interface after enabling IP on it. Because
+ * most netifs don't keep track of routes pointing to
+ * them, there is no way for one to update all its
+ * routes when the MTU is changed.
+ */
+ if ((ro->ro_rt->rt_flags & (RTF_UP | RTF_HOST))
+ && !(ro->ro_rt->rt_rmx.rmx_locks & RTV_MTU)
+ && (ro->ro_rt->rt_rmx.rmx_mtu > ifp->if_mtu)) {
+ ro->ro_rt->rt_rmx.rmx_mtu = ifp->if_mtu;
+ }
+ ipstat.ips_cantfrag++;
+ goto bad;
+ }
+ len = (ifp->if_mtu - hlen) &~ 7;
+ if (len < 8) {
+ error = EMSGSIZE;
+ goto bad;
+ }
+
+ {
+ int mhlen, firstlen = len;
+ struct mbuf **mnext = &m->m_nextpkt;
+
+ /*
+ * Loop through length of segment after first fragment,
+ * make new header and copy data of each part and link onto chain.
+ */
+ m0 = m;
+ mhlen = sizeof (struct ip);
+ for (off = hlen + len; off < (u_short)ip->ip_len; off += len) {
+ MGETHDR(m, M_DONTWAIT, MT_HEADER);
+ if (m == 0) {
+ error = ENOBUFS;
+ ipstat.ips_odropped++;
+ goto sendorfree;
+ }
+ m->m_data += max_linkhdr;
+ mhip = mtod(m, struct ip *);
+ *mhip = *ip;
+ if (hlen > sizeof (struct ip)) {
+ mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
+ mhip->ip_vhl = IP_MAKE_VHL(IPVERSION, mhlen >> 2);
+ }
+ m->m_len = mhlen;
+ mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF);
+ if (ip->ip_off & IP_MF)
+ mhip->ip_off |= IP_MF;
+ if (off + len >= (u_short)ip->ip_len)
+ len = (u_short)ip->ip_len - off;
+ else
+ mhip->ip_off |= IP_MF;
+ mhip->ip_len = htons((u_short)(len + mhlen));
+ m->m_next = m_copy(m0, off, len);
+ if (m->m_next == 0) {
+ (void) m_free(m);
+ error = ENOBUFS; /* ??? */
+ ipstat.ips_odropped++;
+ goto sendorfree;
+ }
+ m->m_pkthdr.len = mhlen + len;
+ m->m_pkthdr.rcvif = (struct ifnet *)0;
+ mhip->ip_off = htons((u_short)mhip->ip_off);
+ mhip->ip_sum = 0;
+ if (mhip->ip_vhl == IP_VHL_BORING) {
+ mhip->ip_sum = in_cksum_hdr(mhip);
+ } else {
+ mhip->ip_sum = in_cksum(m, mhlen);
+ }
+ *mnext = m;
+ mnext = &m->m_nextpkt;
+ ipstat.ips_ofragments++;
+ }
+ /*
+ * Update first fragment by trimming what's been copied out
+ * and updating header, then send each fragment (in order).
+ */
+ m = m0;
+ m_adj(m, hlen + firstlen - (u_short)ip->ip_len);
+ m->m_pkthdr.len = hlen + firstlen;
+ ip->ip_len = htons((u_short)m->m_pkthdr.len);
+ ip->ip_off = htons((u_short)(ip->ip_off | IP_MF));
+ ip->ip_sum = 0;
+ if (ip->ip_vhl == IP_VHL_BORING) {
+ ip->ip_sum = in_cksum_hdr(ip);
+ } else {
+ ip->ip_sum = in_cksum(m, hlen);
+ }
+sendorfree:
+ for (m = m0; m; m = m0) {
+ m0 = m->m_nextpkt;
+ m->m_nextpkt = 0;
+ if (error == 0)
+ error = (*ifp->if_output)(ifp, m,
+ (struct sockaddr *)dst, ro->ro_rt);
+ else
+ m_freem(m);
+ }
+
+ if (error == 0)
+ ipstat.ips_fragmented++;
+ }
+done:
+ return (error);
+bad:
+ m_freem(m0);
+ goto done;
+}
+
+/*
+ * Insert IP options into preformed packet.
+ * Adjust IP destination as required for IP source routing,
+ * as indicated by a non-zero in_addr at the start of the options.
+ *
+ * XXX This routine assumes that the packet has no options in place.
+ */
+static struct mbuf *
+ip_insertoptions(m, opt, phlen)
+ register struct mbuf *m;
+ struct mbuf *opt;
+ int *phlen;
+{
+ register struct ipoption *p = mtod(opt, struct ipoption *);
+ struct mbuf *n;
+ register struct ip *ip = mtod(m, struct ip *);
+ unsigned optlen;
+
+ optlen = opt->m_len - sizeof(p->ipopt_dst);
+ if (optlen + (u_short)ip->ip_len > IP_MAXPACKET)
+ return (m); /* XXX should fail */
+ if (p->ipopt_dst.s_addr)
+ ip->ip_dst = p->ipopt_dst;
+ if (m->m_flags & M_EXT || m->m_data - optlen < m->m_pktdat) {
+ MGETHDR(n, M_DONTWAIT, MT_HEADER);
+ if (n == 0)
+ return (m);
+ n->m_pkthdr.len = m->m_pkthdr.len + optlen;
+ m->m_len -= sizeof(struct ip);
+ m->m_data += sizeof(struct ip);
+ n->m_next = m;
+ m = n;
+ m->m_len = optlen + sizeof(struct ip);
+ m->m_data += max_linkhdr;
+ (void)memcpy(mtod(m, void *), ip, sizeof(struct ip));
+ } else {
+ m->m_data -= optlen;
+ m->m_len += optlen;
+ m->m_pkthdr.len += optlen;
+ ovbcopy((caddr_t)ip, mtod(m, caddr_t), sizeof(struct ip));
+ }
+ ip = mtod(m, struct ip *);
+ bcopy(p->ipopt_list, ip + 1, optlen);
+ *phlen = sizeof(struct ip) + optlen;
+ ip->ip_vhl = IP_MAKE_VHL(IPVERSION, *phlen >> 2);
+ ip->ip_len += optlen;
+ return (m);
+}
+
+/*
+ * Copy options from ip to jp,
+ * omitting those not copied during fragmentation.
+ */
+static int
+ip_optcopy(ip, jp)
+ struct ip *ip, *jp;
+{
+ register u_char *cp, *dp;
+ int opt, optlen, cnt;
+
+ cp = (u_char *)(ip + 1);
+ dp = (u_char *)(jp + 1);
+ cnt = (IP_VHL_HL(ip->ip_vhl) << 2) - sizeof (struct ip);
+ for (; cnt > 0; cnt -= optlen, cp += optlen) {
+ opt = cp[0];
+ if (opt == IPOPT_EOL)
+ break;
+ if (opt == IPOPT_NOP) {
+ /* Preserve for IP mcast tunnel's LSRR alignment. */
+ *dp++ = IPOPT_NOP;
+ optlen = 1;
+ continue;
+ } else
+ optlen = cp[IPOPT_OLEN];
+ /* bogus lengths should have been caught by ip_dooptions */
+ if (optlen > cnt)
+ optlen = cnt;
+ if (IPOPT_COPIED(opt)) {
+ bcopy(cp, dp, optlen);
+ dp += optlen;
+ }
+ }
+ for (optlen = dp - (u_char *)(jp+1); optlen & 0x3; optlen++)
+ *dp++ = IPOPT_EOL;
+ return (optlen);
+}
+
+/*
+ * IP socket option processing.
+ */
+int
+ip_ctloutput(op, so, level, optname, mp)
+ int op;
+ struct socket *so;
+ int level, optname;
+ struct mbuf **mp;
+{
+ register struct inpcb *inp = sotoinpcb(so);
+ register struct mbuf *m = *mp;
+ register int optval = 0;
+ int error = 0;
+
+ if (level != IPPROTO_IP) {
+ error = EINVAL;
+ if (op == PRCO_SETOPT && *mp)
+ (void) m_free(*mp);
+ } else switch (op) {
+
+ case PRCO_SETOPT:
+ switch (optname) {
+ case IP_OPTIONS:
+#ifdef notyet
+ case IP_RETOPTS:
+ return (ip_pcbopts(optname, &inp->inp_options, m));
+#else
+ return (ip_pcbopts(&inp->inp_options, m));
+#endif
+
+ case IP_TOS:
+ case IP_TTL:
+ case IP_RECVOPTS:
+ case IP_RECVRETOPTS:
+ case IP_RECVDSTADDR:
+ case IP_RECVIF:
+ if (m == 0 || m->m_len != sizeof(int))
+ error = EINVAL;
+ else {
+ optval = *mtod(m, int *);
+ switch (optname) {
+
+ case IP_TOS:
+ inp->inp_ip_tos = optval;
+ break;
+
+ case IP_TTL:
+ inp->inp_ip_ttl = optval;
+ break;
+#define OPTSET(bit) \
+ if (optval) \
+ inp->inp_flags |= bit; \
+ else \
+ inp->inp_flags &= ~bit;
+
+ case IP_RECVOPTS:
+ OPTSET(INP_RECVOPTS);
+ break;
+
+ case IP_RECVRETOPTS:
+ OPTSET(INP_RECVRETOPTS);
+ break;
+
+ case IP_RECVDSTADDR:
+ OPTSET(INP_RECVDSTADDR);
+ break;
+
+ case IP_RECVIF:
+ OPTSET(INP_RECVIF);
+ break;
+ }
+ }
+ break;
+#undef OPTSET
+
+ case IP_MULTICAST_IF:
+ case IP_MULTICAST_VIF:
+ case IP_MULTICAST_TTL:
+ case IP_MULTICAST_LOOP:
+ case IP_ADD_MEMBERSHIP:
+ case IP_DROP_MEMBERSHIP:
+ error = ip_setmoptions(optname, &inp->inp_moptions, m);
+ break;
+
+ case IP_PORTRANGE:
+ if (m == 0 || m->m_len != sizeof(int))
+ error = EINVAL;
+ else {
+ optval = *mtod(m, int *);
+
+ switch (optval) {
+
+ case IP_PORTRANGE_DEFAULT:
+ inp->inp_flags &= ~(INP_LOWPORT);
+ inp->inp_flags &= ~(INP_HIGHPORT);
+ break;
+
+ case IP_PORTRANGE_HIGH:
+ inp->inp_flags &= ~(INP_LOWPORT);
+ inp->inp_flags |= INP_HIGHPORT;
+ break;
+
+ case IP_PORTRANGE_LOW:
+ inp->inp_flags &= ~(INP_HIGHPORT);
+ inp->inp_flags |= INP_LOWPORT;
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+ }
+ break;
+
+ default:
+ error = ENOPROTOOPT;
+ break;
+ }
+ if (m)
+ (void)m_free(m);
+ break;
+
+ case PRCO_GETOPT:
+ switch (optname) {
+ case IP_OPTIONS:
+ case IP_RETOPTS:
+ *mp = m = m_get(M_WAIT, MT_SOOPTS);
+ if (inp->inp_options) {
+ m->m_len = inp->inp_options->m_len;
+ bcopy(mtod(inp->inp_options, void *),
+ mtod(m, void *), m->m_len);
+ } else
+ m->m_len = 0;
+ break;
+
+ case IP_TOS:
+ case IP_TTL:
+ case IP_RECVOPTS:
+ case IP_RECVRETOPTS:
+ case IP_RECVDSTADDR:
+ case IP_RECVIF:
+ *mp = m = m_get(M_WAIT, MT_SOOPTS);
+ m->m_len = sizeof(int);
+ switch (optname) {
+
+ case IP_TOS:
+ optval = inp->inp_ip_tos;
+ break;
+
+ case IP_TTL:
+ optval = inp->inp_ip_ttl;
+ break;
+
+#define OPTBIT(bit) (inp->inp_flags & bit ? 1 : 0)
+
+ case IP_RECVOPTS:
+ optval = OPTBIT(INP_RECVOPTS);
+ break;
+
+ case IP_RECVRETOPTS:
+ optval = OPTBIT(INP_RECVRETOPTS);
+ break;
+
+ case IP_RECVDSTADDR:
+ optval = OPTBIT(INP_RECVDSTADDR);
+ break;
+
+ case IP_RECVIF:
+ optval = OPTBIT(INP_RECVIF);
+ break;
+ }
+ *mtod(m, int *) = optval;
+ break;
+
+ case IP_MULTICAST_IF:
+ case IP_MULTICAST_VIF:
+ case IP_MULTICAST_TTL:
+ case IP_MULTICAST_LOOP:
+ case IP_ADD_MEMBERSHIP:
+ case IP_DROP_MEMBERSHIP:
+ error = ip_getmoptions(optname, inp->inp_moptions, mp);
+ break;
+
+ case IP_PORTRANGE:
+ *mp = m = m_get(M_WAIT, MT_SOOPTS);
+ m->m_len = sizeof(int);
+
+ if (inp->inp_flags & INP_HIGHPORT)
+ optval = IP_PORTRANGE_HIGH;
+ else if (inp->inp_flags & INP_LOWPORT)
+ optval = IP_PORTRANGE_LOW;
+ else
+ optval = 0;
+
+ *mtod(m, int *) = optval;
+ break;
+
+ default:
+ error = ENOPROTOOPT;
+ break;
+ }
+ break;
+ }
+ return (error);
+}
+
+/*
+ * Set up IP options in pcb for insertion in output packets.
+ * Store in mbuf with pointer in pcbopt, adding pseudo-option
+ * with destination address if source routed.
+ */
+static int
+#ifdef notyet
+ip_pcbopts(optname, pcbopt, m)
+ int optname;
+#else
+ip_pcbopts(pcbopt, m)
+#endif
+ struct mbuf **pcbopt;
+ register struct mbuf *m;
+{
+ register int cnt, optlen;
+ register u_char *cp;
+ u_char opt;
+
+ /* turn off any old options */
+ if (*pcbopt)
+ (void)m_free(*pcbopt);
+ *pcbopt = 0;
+ if (m == (struct mbuf *)0 || m->m_len == 0) {
+ /*
+ * Only turning off any previous options.
+ */
+ if (m)
+ (void)m_free(m);
+ return (0);
+ }
+
+#ifndef vax
+ if (m->m_len % sizeof(long))
+ goto bad;
+#endif
+ /*
+ * IP first-hop destination address will be stored before
+ * actual options; move other options back
+ * and clear it when none present.
+ */
+ if (m->m_data + m->m_len + sizeof(struct in_addr) >= &m->m_dat[MLEN])
+ goto bad;
+ cnt = m->m_len;
+ m->m_len += sizeof(struct in_addr);
+ cp = mtod(m, u_char *) + sizeof(struct in_addr);
+ ovbcopy(mtod(m, caddr_t), (caddr_t)cp, (unsigned)cnt);
+ bzero(mtod(m, caddr_t), sizeof(struct in_addr));
+
+ for (; cnt > 0; cnt -= optlen, cp += optlen) {
+ opt = cp[IPOPT_OPTVAL];
+ if (opt == IPOPT_EOL)
+ break;
+ if (opt == IPOPT_NOP)
+ optlen = 1;
+ else {
+ optlen = cp[IPOPT_OLEN];
+ if (optlen <= IPOPT_OLEN || optlen > cnt)
+ goto bad;
+ }
+ switch (opt) {
+
+ default:
+ break;
+
+ case IPOPT_LSRR:
+ case IPOPT_SSRR:
+ /*
+ * user process specifies route as:
+ * ->A->B->C->D
+ * D must be our final destination (but we can't
+ * check that since we may not have connected yet).
+ * A is first hop destination, which doesn't appear in
+ * actual IP option, but is stored before the options.
+ */
+ if (optlen < IPOPT_MINOFF - 1 + sizeof(struct in_addr))
+ goto bad;
+ m->m_len -= sizeof(struct in_addr);
+ cnt -= sizeof(struct in_addr);
+ optlen -= sizeof(struct in_addr);
+ cp[IPOPT_OLEN] = optlen;
+ /*
+ * Move first hop before start of options.
+ */
+ bcopy((caddr_t)&cp[IPOPT_OFFSET+1], mtod(m, caddr_t),
+ sizeof(struct in_addr));
+ /*
+ * Then copy rest of options back
+ * to close up the deleted entry.
+ */
+ ovbcopy((caddr_t)(&cp[IPOPT_OFFSET+1] +
+ sizeof(struct in_addr)),
+ (caddr_t)&cp[IPOPT_OFFSET+1],
+ (unsigned)cnt + sizeof(struct in_addr));
+ break;
+ }
+ }
+ if (m->m_len > MAX_IPOPTLEN + sizeof(struct in_addr))
+ goto bad;
+ *pcbopt = m;
+ return (0);
+
+bad:
+ (void)m_free(m);
+ return (EINVAL);
+}
+
+/*
+ * Set the IP multicast options in response to user setsockopt().
+ */
+static int
+ip_setmoptions(optname, imop, m)
+ int optname;
+ struct ip_moptions **imop;
+ struct mbuf *m;
+{
+ register int error = 0;
+ u_char loop;
+ register int i;
+ struct in_addr addr;
+ register struct ip_mreq *mreq;
+ register struct ifnet *ifp;
+ register struct ip_moptions *imo = *imop;
+ struct route ro;
+ register struct sockaddr_in *dst;
+ int s;
+
+ if (imo == NULL) {
+ /*
+ * No multicast option buffer attached to the pcb;
+ * allocate one and initialize to default values.
+ */
+ imo = (struct ip_moptions*)malloc(sizeof(*imo), M_IPMOPTS,
+ M_WAITOK);
+
+ if (imo == NULL)
+ return (ENOBUFS);
+ *imop = imo;
+ imo->imo_multicast_ifp = NULL;
+ imo->imo_multicast_vif = -1;
+ imo->imo_multicast_ttl = IP_DEFAULT_MULTICAST_TTL;
+ imo->imo_multicast_loop = IP_DEFAULT_MULTICAST_LOOP;
+ imo->imo_num_memberships = 0;
+ }
+
+ switch (optname) {
+ /* store an index number for the vif you wanna use in the send */
+ case IP_MULTICAST_VIF:
+ if (!legal_vif_num) {
+ error = EOPNOTSUPP;
+ break;
+ }
+ if (m == NULL || m->m_len != sizeof(int)) {
+ error = EINVAL;
+ break;
+ }
+ i = *(mtod(m, int *));
+ if (!legal_vif_num(i) && (i != -1)) {
+ error = EINVAL;
+ break;
+ }
+ imo->imo_multicast_vif = i;
+ break;
+
+ case IP_MULTICAST_IF:
+ /*
+ * Select the interface for outgoing multicast packets.
+ */
+ if (m == NULL || m->m_len != sizeof(struct in_addr)) {
+ error = EINVAL;
+ break;
+ }
+ addr = *(mtod(m, struct in_addr *));
+ /*
+ * INADDR_ANY is used to remove a previous selection.
+ * When no interface is selected, a default one is
+ * chosen every time a multicast packet is sent.
+ */
+ if (addr.s_addr == INADDR_ANY) {
+ imo->imo_multicast_ifp = NULL;
+ break;
+ }
+ /*
+ * The selected interface is identified by its local
+ * IP address. Find the interface and confirm that
+ * it supports multicasting.
+ */
+ s = splimp();
+ INADDR_TO_IFP(addr, ifp);
+ if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
+ splx(s);
+ error = EADDRNOTAVAIL;
+ break;
+ }
+ imo->imo_multicast_ifp = ifp;
+ splx(s);
+ break;
+
+ case IP_MULTICAST_TTL:
+ /*
+ * Set the IP time-to-live for outgoing multicast packets.
+ */
+ if (m == NULL || m->m_len != 1) {
+ error = EINVAL;
+ break;
+ }
+ imo->imo_multicast_ttl = *(mtod(m, u_char *));
+ break;
+
+ case IP_MULTICAST_LOOP:
+ /*
+ * Set the loopback flag for outgoing multicast packets.
+ * Must be zero or one.
+ */
+ if (m == NULL || m->m_len != 1 ||
+ (loop = *(mtod(m, u_char *))) > 1) {
+ error = EINVAL;
+ break;
+ }
+ imo->imo_multicast_loop = loop;
+ break;
+
+ case IP_ADD_MEMBERSHIP:
+ /*
+ * Add a multicast group membership.
+ * Group must be a valid IP multicast address.
+ */
+ if (m == NULL || m->m_len != sizeof(struct ip_mreq)) {
+ error = EINVAL;
+ break;
+ }
+ mreq = mtod(m, struct ip_mreq *);
+ if (!IN_MULTICAST(ntohl(mreq->imr_multiaddr.s_addr))) {
+ error = EINVAL;
+ break;
+ }
+ s = splimp();
+ /*
+ * If no interface address was provided, use the interface of
+ * the route to the given multicast address.
+ */
+ if (mreq->imr_interface.s_addr == INADDR_ANY) {
+ bzero((caddr_t)&ro, sizeof(ro));
+ dst = (struct sockaddr_in *)&ro.ro_dst;
+ dst->sin_len = sizeof(*dst);
+ dst->sin_family = AF_INET;
+ dst->sin_addr = mreq->imr_multiaddr;
+ rtalloc(&ro);
+ if (ro.ro_rt == NULL) {
+ error = EADDRNOTAVAIL;
+ splx(s);
+ break;
+ }
+ ifp = ro.ro_rt->rt_ifp;
+ rtfree(ro.ro_rt);
+ }
+ else {
+ INADDR_TO_IFP(mreq->imr_interface, ifp);
+ }
+
+ /*
+ * See if we found an interface, and confirm that it
+ * supports multicast.
+ */
+ if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
+ error = EADDRNOTAVAIL;
+ splx(s);
+ break;
+ }
+ /*
+ * See if the membership already exists or if all the
+ * membership slots are full.
+ */
+ for (i = 0; i < imo->imo_num_memberships; ++i) {
+ if (imo->imo_membership[i]->inm_ifp == ifp &&
+ imo->imo_membership[i]->inm_addr.s_addr
+ == mreq->imr_multiaddr.s_addr)
+ break;
+ }
+ if (i < imo->imo_num_memberships) {
+ error = EADDRINUSE;
+ splx(s);
+ break;
+ }
+ if (i == IP_MAX_MEMBERSHIPS) {
+ error = ETOOMANYREFS;
+ splx(s);
+ break;
+ }
+ /*
+ * Everything looks good; add a new record to the multicast
+ * address list for the given interface.
+ */
+ if ((imo->imo_membership[i] =
+ in_addmulti(&mreq->imr_multiaddr, ifp)) == NULL) {
+ error = ENOBUFS;
+ splx(s);
+ break;
+ }
+ ++imo->imo_num_memberships;
+ splx(s);
+ break;
+
+ case IP_DROP_MEMBERSHIP:
+ /*
+ * Drop a multicast group membership.
+ * Group must be a valid IP multicast address.
+ */
+ if (m == NULL || m->m_len != sizeof(struct ip_mreq)) {
+ error = EINVAL;
+ break;
+ }
+ mreq = mtod(m, struct ip_mreq *);
+ if (!IN_MULTICAST(ntohl(mreq->imr_multiaddr.s_addr))) {
+ error = EINVAL;
+ break;
+ }
+
+ s = splimp();
+ /*
+ * If an interface address was specified, get a pointer
+ * to its ifnet structure.
+ */
+ if (mreq->imr_interface.s_addr == INADDR_ANY)
+ ifp = NULL;
+ else {
+ INADDR_TO_IFP(mreq->imr_interface, ifp);
+ if (ifp == NULL) {
+ error = EADDRNOTAVAIL;
+ splx(s);
+ break;
+ }
+ }
+ /*
+ * Find the membership in the membership array.
+ */
+ for (i = 0; i < imo->imo_num_memberships; ++i) {
+ if ((ifp == NULL ||
+ imo->imo_membership[i]->inm_ifp == ifp) &&
+ imo->imo_membership[i]->inm_addr.s_addr ==
+ mreq->imr_multiaddr.s_addr)
+ break;
+ }
+ if (i == imo->imo_num_memberships) {
+ error = EADDRNOTAVAIL;
+ splx(s);
+ break;
+ }
+ /*
+ * Give up the multicast address record to which the
+ * membership points.
+ */
+ in_delmulti(imo->imo_membership[i]);
+ /*
+ * Remove the gap in the membership array.
+ */
+ for (++i; i < imo->imo_num_memberships; ++i)
+ imo->imo_membership[i-1] = imo->imo_membership[i];
+ --imo->imo_num_memberships;
+ splx(s);
+ break;
+
+ default:
+ error = EOPNOTSUPP;
+ break;
+ }
+
+ /*
+ * If all options have default values, no need to keep the mbuf.
+ */
+ if (imo->imo_multicast_ifp == NULL &&
+ imo->imo_multicast_vif == -1 &&
+ imo->imo_multicast_ttl == IP_DEFAULT_MULTICAST_TTL &&
+ imo->imo_multicast_loop == IP_DEFAULT_MULTICAST_LOOP &&
+ imo->imo_num_memberships == 0) {
+ free(*imop, M_IPMOPTS);
+ *imop = NULL;
+ }
+
+ return (error);
+}
+
+/*
+ * Return the IP multicast options in response to user getsockopt().
+ */
+static int
+ip_getmoptions(optname, imo, mp)
+ int optname;
+ register struct ip_moptions *imo;
+ register struct mbuf **mp;
+{
+ u_char *ttl;
+ u_char *loop;
+ struct in_addr *addr;
+ struct in_ifaddr *ia;
+
+ *mp = m_get(M_WAIT, MT_SOOPTS);
+
+ switch (optname) {
+
+ case IP_MULTICAST_VIF:
+ if (imo != NULL)
+ *(mtod(*mp, int *)) = imo->imo_multicast_vif;
+ else
+ *(mtod(*mp, int *)) = -1;
+ (*mp)->m_len = sizeof(int);
+ return(0);
+
+ case IP_MULTICAST_IF:
+ addr = mtod(*mp, struct in_addr *);
+ (*mp)->m_len = sizeof(struct in_addr);
+ if (imo == NULL || imo->imo_multicast_ifp == NULL)
+ addr->s_addr = INADDR_ANY;
+ else {
+ IFP_TO_IA(imo->imo_multicast_ifp, ia);
+ addr->s_addr = (ia == NULL) ? INADDR_ANY
+ : IA_SIN(ia)->sin_addr.s_addr;
+ }
+ return (0);
+
+ case IP_MULTICAST_TTL:
+ ttl = mtod(*mp, u_char *);
+ (*mp)->m_len = 1;
+ *ttl = (imo == NULL) ? IP_DEFAULT_MULTICAST_TTL
+ : imo->imo_multicast_ttl;
+ return (0);
+
+ case IP_MULTICAST_LOOP:
+ loop = mtod(*mp, u_char *);
+ (*mp)->m_len = 1;
+ *loop = (imo == NULL) ? IP_DEFAULT_MULTICAST_LOOP
+ : imo->imo_multicast_loop;
+ return (0);
+
+ default:
+ return (EOPNOTSUPP);
+ }
+}
+
+/*
+ * Discard the IP multicast options.
+ */
+void
+ip_freemoptions(imo)
+ register struct ip_moptions *imo;
+{
+ register int i;
+
+ if (imo != NULL) {
+ for (i = 0; i < imo->imo_num_memberships; ++i)
+ in_delmulti(imo->imo_membership[i]);
+ free(imo, M_IPMOPTS);
+ }
+}
+
+/*
+ * Routine called from ip_output() to loop back a copy of an IP multicast
+ * packet to the input queue of a specified interface. Note that this
+ * calls the output routine of the loopback "driver", but with an interface
+ * pointer that might NOT be a loopback interface -- evil, but easier than
+ * replicating that code here.
+ */
+static void
+ip_mloopback(ifp, m, dst, hlen)
+ struct ifnet *ifp;
+ register struct mbuf *m;
+ register struct sockaddr_in *dst;
+ int hlen;
+{
+ register struct ip *ip;
+ struct mbuf *copym;
+
+ copym = m_copy(m, 0, M_COPYALL);
+ if (copym != NULL && (copym->m_flags & M_EXT || copym->m_len < hlen))
+ copym = m_pullup(copym, hlen);
+ if (copym != NULL) {
+ /*
+ * We don't bother to fragment if the IP length is greater
+ * than the interface's MTU. Can this possibly matter?
+ */
+ ip = mtod(copym, struct ip *);
+ ip->ip_len = htons((u_short)ip->ip_len);
+ ip->ip_off = htons((u_short)ip->ip_off);
+ ip->ip_sum = 0;
+ if (ip->ip_vhl == IP_VHL_BORING) {
+ ip->ip_sum = in_cksum_hdr(ip);
+ } else {
+ ip->ip_sum = in_cksum(copym, hlen);
+ }
+ /*
+ * NB:
+ * It's not clear whether there are any lingering
+ * reentrancy problems in other areas which might
+ * be exposed by using ip_input directly (in
+ * particular, everything which modifies the packet
+ * in-place). Yet another option is using the
+ * protosw directly to deliver the looped back
+ * packet. For the moment, we'll err on the side
+ * of safety by continuing to abuse looutput().
+ */
+#ifdef notdef
+ copym->m_pkthdr.rcvif = ifp;
+ ip_input(copym)
+#else
+ (void) looutput(ifp, copym, (struct sockaddr *)dst, NULL);
+#endif
+ }
+}
diff --git a/cpukit/libnetworking/netinet/ip_var.h b/cpukit/libnetworking/netinet/ip_var.h
new file mode 100644
index 0000000000..7d40243f24
--- /dev/null
+++ b/cpukit/libnetworking/netinet/ip_var.h
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)ip_var.h 8.2 (Berkeley) 1/9/95
+ * $Id$
+ */
+
+#ifndef _NETINET_IP_VAR_H_
+#define _NETINET_IP_VAR_H_
+
+/*
+ * Overlay for ip header used by other protocols (tcp, udp).
+ */
+struct ipovly {
+ caddr_t ih_next BYTE_PACK;
+ caddr_t ih_prev BYTE_PACK; /* for protocol sequence q's */
+ u_char ih_x1; /* (unused) */
+ u_char ih_pr; /* protocol */
+ u_short ih_len BYTE_PACK; /* protocol length */
+ struct in_addr ih_src; /* source internet address */
+ struct in_addr ih_dst; /* destination internet address */
+};
+
+/*
+ * Ip reassembly queue structure. Each fragment
+ * being reassembled is attached to one of these structures.
+ * They are timed out after ipq_ttl drops to 0, and may also
+ * be reclaimed if memory becomes tight.
+ */
+struct ipq {
+ struct ipq *next,*prev; /* to other reass headers */
+ u_char ipq_ttl; /* time for reass q to live */
+ u_char ipq_p; /* protocol of this fragment */
+ u_short ipq_id BYTE_PACK; /* sequence id for reassembly */
+ struct ipasfrag *ipq_next,*ipq_prev;
+ /* to ip headers of fragments */
+ struct in_addr ipq_src,ipq_dst;
+#ifdef IPDIVERT
+ u_short ipq_divert BYTE_PACK; /* divert protocol port */
+#endif
+};
+
+/*
+ * Ip header, when holding a fragment.
+ *
+ * Note: ipf_next must be at same offset as ipq_next above
+ */
+struct ipasfrag {
+#if BYTE_ORDER == LITTLE_ENDIAN
+ u_char ip_hl:4,
+ ip_v:4;
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char ip_v:4,
+ ip_hl:4;
+#endif
+ u_char ipf_mff; /* XXX overlays ip_tos: use low bit
+ * to avoid destroying tos;
+ * copied from (ip_off&IP_MF) */
+ u_short ip_len BYTE_PACK;
+ u_short ip_id BYTE_PACK;
+ u_short ip_off BYTE_PACK;
+ u_char ip_ttl;
+ u_char ip_p;
+ u_short ip_sum BYTE_PACK;
+ struct ipasfrag *ipf_next; /* next fragment */
+ struct ipasfrag *ipf_prev; /* previous fragment */
+};
+
+/*
+ * Structure stored in mbuf in inpcb.ip_options
+ * and passed to ip_output when ip options are in use.
+ * The actual length of the options (including ipopt_dst)
+ * is in m_len.
+ */
+#define MAX_IPOPTLEN 40
+
+struct ipoption {
+ struct in_addr ipopt_dst; /* first-hop dst if source routed */
+ char ipopt_list[MAX_IPOPTLEN]; /* options proper */
+};
+
+/*
+ * Structure attached to inpcb.ip_moptions and
+ * passed to ip_output when IP multicast options are in use.
+ */
+struct ip_moptions {
+ struct ifnet *imo_multicast_ifp; /* ifp for outgoing multicasts */
+ u_char imo_multicast_ttl; /* TTL for outgoing multicasts */
+ u_char imo_multicast_loop; /* 1 => hear sends if a member */
+ u_short imo_num_memberships; /* no. memberships this socket */
+ struct in_multi *imo_membership[IP_MAX_MEMBERSHIPS];
+ u_long imo_multicast_vif; /* vif num outgoing multicasts */
+};
+
+struct ipstat {
+ u_long ips_total; /* total packets received */
+ u_long ips_badsum; /* checksum bad */
+ u_long ips_tooshort; /* packet too short */
+ u_long ips_toosmall; /* not enough data */
+ u_long ips_badhlen; /* ip header length < data size */
+ u_long ips_badlen; /* ip length < ip header length */
+ u_long ips_fragments; /* fragments received */
+ u_long ips_fragdropped; /* frags dropped (dups, out of space) */
+ u_long ips_fragtimeout; /* fragments timed out */
+ u_long ips_forward; /* packets forwarded */
+ u_long ips_cantforward; /* packets rcvd for unreachable dest */
+ u_long ips_redirectsent; /* packets forwarded on same net */
+ u_long ips_noproto; /* unknown or unsupported protocol */
+ u_long ips_delivered; /* datagrams delivered to upper level*/
+ u_long ips_localout; /* total ip packets generated here */
+ u_long ips_odropped; /* lost packets due to nobufs, etc. */
+ u_long ips_reassembled; /* total packets reassembled ok */
+ u_long ips_fragmented; /* datagrams successfully fragmented */
+ u_long ips_ofragments; /* output fragments created */
+ u_long ips_cantfrag; /* don't fragment flag was set, etc. */
+ u_long ips_badoptions; /* error in option processing */
+ u_long ips_noroute; /* packets discarded due to no route */
+ u_long ips_badvers; /* ip version != 4 */
+ u_long ips_rawout; /* total raw ip packets generated */
+ u_long ips_toolong; /* ip length > max ip packet size */
+};
+
+#ifdef _KERNEL
+/* flags passed to ip_output as last parameter */
+#define IP_FORWARDING 0x1 /* most of ip header exists */
+#define IP_RAWOUTPUT 0x2 /* raw ip header exists */
+#define IP_ROUTETOIF SO_DONTROUTE /* bypass routing tables */
+#define IP_ALLOWBROADCAST SO_BROADCAST /* can send broadcast packets */
+
+struct inpcb;
+struct route;
+
+extern struct ipstat ipstat;
+extern u_short ip_id; /* ip packet ctr, for ids */
+extern int ip_defttl; /* default IP ttl */
+extern u_char ip_protox[];
+extern struct socket *ip_rsvpd; /* reservation protocol daemon */
+extern struct socket *ip_mrouter; /* multicast routing daemon */
+extern int (*legal_vif_num) __P((int));
+extern u_long (*ip_mcast_src) __P((int));
+extern int rsvp_on;
+
+int ip_ctloutput __P((int, struct socket *, int, int, struct mbuf **));
+void ip_drain __P((void));
+void ip_freemoptions __P((struct ip_moptions *));
+void ip_init __P((void));
+extern int (*ip_mforward) __P((struct ip *, struct ifnet *, struct mbuf *,
+ struct ip_moptions *));
+int ip_output __P((struct mbuf *,
+ struct mbuf *, struct route *, int, struct ip_moptions *));
+void ip_savecontrol __P((struct inpcb *, struct mbuf **, struct ip *,
+ struct mbuf *));
+void ip_slowtimo __P((void));
+struct mbuf *
+ ip_srcroute __P((void));
+void ip_stripoptions __P((struct mbuf *, struct mbuf *));
+int rip_ctloutput __P((int, struct socket *, int, int, struct mbuf **));
+void rip_init __P((void));
+void rip_input __P((struct mbuf *, int));
+int rip_output __P((struct mbuf *, struct socket *, u_long));
+int rip_usrreq __P((struct socket *,
+ int, struct mbuf *, struct mbuf *, struct mbuf *));
+void ipip_input __P((struct mbuf *, int));
+void rsvp_input __P((struct mbuf *, int));
+int ip_rsvp_init __P((struct socket *));
+int ip_rsvp_done __P((void));
+int ip_rsvp_vif_init __P((struct socket *, struct mbuf *));
+int ip_rsvp_vif_done __P((struct socket *, struct mbuf *));
+void ip_rsvp_force_done __P((struct socket *));
+
+#ifdef IPDIVERT
+void div_init __P((void));
+void div_input __P((struct mbuf *, int));
+int div_usrreq __P((struct socket *,
+ int, struct mbuf *, struct mbuf *, struct mbuf *));
+extern u_short ip_divert_port;
+extern u_short ip_divert_ignore;
+#endif /* IPDIVERT */
+
+#endif /* _KERNEL */
+
+#endif /* _NETINET_IP_VAR_H_ */
diff --git a/cpukit/libnetworking/netinet/raw_ip.c b/cpukit/libnetworking/netinet/raw_ip.c
new file mode 100644
index 0000000000..44d58f1844
--- /dev/null
+++ b/cpukit/libnetworking/netinet/raw_ip.c
@@ -0,0 +1,486 @@
+/*
+ * Copyright (c) 1982, 1986, 1988, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)raw_ip.c 8.7 (Berkeley) 5/15/95
+ * $Id$
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/protosw.h>
+#include <sys/socketvar.h>
+#include <sys/errno.h>
+#include <sys/systm.h>
+
+#include <net/if.h>
+#include <net/route.h>
+
+#define _IP_VHL
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/in_pcb.h>
+#include <netinet/in_var.h>
+#include <netinet/ip_var.h>
+#include <netinet/ip_mroute.h>
+
+#include <netinet/ip_fw.h>
+
+#if !defined(COMPAT_IPFW) || COMPAT_IPFW == 1
+#undef COMPAT_IPFW
+#define COMPAT_IPFW 1
+#else
+#undef COMPAT_IPFW
+#endif
+
+static struct inpcbhead ripcb;
+static struct inpcbinfo ripcbinfo;
+
+/*
+ * Nominal space allocated to a raw ip socket.
+ */
+#define RIPSNDQ 8192
+#define RIPRCVQ 8192
+
+/*
+ * Raw interface to IP protocol.
+ */
+
+/*
+ * Initialize raw connection block q.
+ */
+void
+rip_init()
+{
+ LIST_INIT(&ripcb);
+ ripcbinfo.listhead = &ripcb;
+ /*
+ * XXX We don't use the hash list for raw IP, but it's easier
+ * to allocate a one entry hash list than it is to check all
+ * over the place for hashbase == NULL.
+ */
+ ripcbinfo.hashbase = hashinit(1, M_PCB, &ripcbinfo.hashmask);
+}
+
+static struct sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET };
+/*
+ * Setup generic address and protocol structures
+ * for raw_input routine, then pass them along with
+ * mbuf chain.
+ */
+void
+rip_input(m, iphlen)
+ struct mbuf *m;
+ int iphlen;
+{
+ register struct ip *ip = mtod(m, struct ip *);
+ register struct inpcb *inp;
+ struct inpcb *last = 0;
+ struct mbuf *opts = 0;
+
+ ripsrc.sin_addr = ip->ip_src;
+ for (inp = ripcb.lh_first; inp != NULL; inp = inp->inp_list.le_next) {
+ if (inp->inp_ip_p && inp->inp_ip_p != ip->ip_p)
+ continue;
+ if (inp->inp_laddr.s_addr &&
+ inp->inp_laddr.s_addr != ip->ip_dst.s_addr)
+ continue;
+ if (inp->inp_faddr.s_addr &&
+ inp->inp_faddr.s_addr != ip->ip_src.s_addr)
+ continue;
+ if (last) {
+ struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
+ if (n) {
+ if (last->inp_flags & INP_CONTROLOPTS ||
+ last->inp_socket->so_options & SO_TIMESTAMP)
+ ip_savecontrol(last, &opts, ip, n);
+ if (sbappendaddr(&last->inp_socket->so_rcv,
+ (struct sockaddr *)&ripsrc, n,
+ opts) == 0) {
+ /* should notify about lost packet */
+ m_freem(n);
+ if (opts)
+ m_freem(opts);
+ } else
+ sorwakeup(last->inp_socket);
+ opts = 0;
+ }
+ }
+ last = inp;
+ }
+ if (last) {
+ if (last->inp_flags & INP_CONTROLOPTS ||
+ last->inp_socket->so_options & SO_TIMESTAMP)
+ ip_savecontrol(last, &opts, ip, m);
+ if (sbappendaddr(&last->inp_socket->so_rcv,
+ (struct sockaddr *)&ripsrc, m, opts) == 0) {
+ m_freem(m);
+ if (opts)
+ m_freem(opts);
+ } else
+ sorwakeup(last->inp_socket);
+ } else {
+ m_freem(m);
+ ipstat.ips_noproto++;
+ ipstat.ips_delivered--;
+ }
+}
+
+/*
+ * Generate IP header and pass packet to ip_output.
+ * Tack on options user may have setup with control call.
+ */
+int
+rip_output(m, so, dst)
+ register struct mbuf *m;
+ struct socket *so;
+ u_long dst;
+{
+ register struct ip *ip;
+ register struct inpcb *inp = sotoinpcb(so);
+ int flags = (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST;
+
+ /*
+ * If the user handed us a complete IP packet, use it.
+ * Otherwise, allocate an mbuf for a header and fill it in.
+ */
+ if ((inp->inp_flags & INP_HDRINCL) == 0) {
+ if (m->m_pkthdr.len + sizeof(struct ip) > IP_MAXPACKET) {
+ m_freem(m);
+ return(EMSGSIZE);
+ }
+ M_PREPEND(m, sizeof(struct ip), M_WAIT);
+ ip = mtod(m, struct ip *);
+ ip->ip_tos = 0;
+ ip->ip_off = 0;
+ ip->ip_p = inp->inp_ip_p;
+ ip->ip_len = m->m_pkthdr.len;
+ ip->ip_src = inp->inp_laddr;
+ ip->ip_dst.s_addr = dst;
+ ip->ip_ttl = MAXTTL;
+ } else {
+ if (m->m_pkthdr.len > IP_MAXPACKET) {
+ m_freem(m);
+ return(EMSGSIZE);
+ }
+ ip = mtod(m, struct ip *);
+ /* don't allow both user specified and setsockopt options,
+ and don't allow packet length sizes that will crash */
+ if (((IP_VHL_HL(ip->ip_vhl) != (sizeof (*ip) >> 2))
+ && inp->inp_options)
+ || (ip->ip_len > m->m_pkthdr.len)
+ || (ip->ip_len < (IP_VHL_HL(ip->ip_vhl) << 2))) {
+ m_freem(m);
+ return EINVAL;
+ }
+ if (ip->ip_id == 0)
+ ip->ip_id = htons(ip_id++);
+ /* XXX prevent ip_output from overwriting header fields */
+ flags |= IP_RAWOUTPUT;
+ ipstat.ips_rawout++;
+ }
+ return (ip_output(m, inp->inp_options, &inp->inp_route, flags,
+ inp->inp_moptions));
+}
+
+/*
+ * Raw IP socket option processing.
+ */
+int
+rip_ctloutput(op, so, level, optname, m)
+ int op;
+ struct socket *so;
+ int level, optname;
+ struct mbuf **m;
+{
+ register struct inpcb *inp = sotoinpcb(so);
+ register int error;
+
+ if (level != IPPROTO_IP) {
+ if (op == PRCO_SETOPT && *m)
+ (void)m_free(*m);
+ return (EINVAL);
+ }
+
+ switch (optname) {
+
+ case IP_HDRINCL:
+ error = 0;
+ if (op == PRCO_SETOPT) {
+ if (m == 0 || *m == 0 || (*m)->m_len < sizeof (int))
+ error = EINVAL;
+ else if (*mtod(*m, int *))
+ inp->inp_flags |= INP_HDRINCL;
+ else
+ inp->inp_flags &= ~INP_HDRINCL;
+ if (*m)
+ (void)m_free(*m);
+ } else {
+ *m = m_get(M_WAIT, MT_SOOPTS);
+ (*m)->m_len = sizeof (int);
+ *mtod(*m, int *) = inp->inp_flags & INP_HDRINCL;
+ }
+ return (error);
+
+#ifdef COMPAT_IPFW
+ case IP_FW_GET:
+ if (ip_fw_ctl_ptr == NULL || op == PRCO_SETOPT) {
+ if (*m) (void)m_free(*m);
+ return(EINVAL);
+ }
+ return (*ip_fw_ctl_ptr)(optname, m);
+
+ case IP_FW_ADD:
+ case IP_FW_DEL:
+ case IP_FW_FLUSH:
+ case IP_FW_ZERO:
+ if (ip_fw_ctl_ptr == NULL || op != PRCO_SETOPT) {
+ if (*m) (void)m_free(*m);
+ return(EINVAL);
+ }
+ return (*ip_fw_ctl_ptr)(optname, m);
+
+ case IP_NAT:
+ if (ip_nat_ctl_ptr == NULL) {
+ if (*m) (void)m_free(*m);
+ return(EINVAL);
+ }
+ return (*ip_nat_ctl_ptr)(op, m);
+
+#endif
+ case IP_RSVP_ON:
+ return ip_rsvp_init(so);
+ break;
+
+ case IP_RSVP_OFF:
+ return ip_rsvp_done();
+ break;
+
+ case IP_RSVP_VIF_ON:
+ return ip_rsvp_vif_init(so, *m);
+
+ case IP_RSVP_VIF_OFF:
+ return ip_rsvp_vif_done(so, *m);
+
+ case MRT_INIT:
+ case MRT_DONE:
+ case MRT_ADD_VIF:
+ case MRT_DEL_VIF:
+ case MRT_ADD_MFC:
+ case MRT_DEL_MFC:
+ case MRT_VERSION:
+ case MRT_ASSERT:
+ if (op == PRCO_SETOPT) {
+ error = ip_mrouter_set(optname, so, *m);
+ if (*m)
+ (void)m_free(*m);
+ } else if (op == PRCO_GETOPT) {
+ error = ip_mrouter_get(optname, so, m);
+ } else
+ error = EINVAL;
+ return (error);
+ }
+ return (ip_ctloutput(op, so, level, optname, m));
+}
+
+static u_long rip_sendspace = RIPSNDQ; /* XXX sysctl ? */
+static u_long rip_recvspace = RIPRCVQ; /* XXX sysctl ? */
+
+/*ARGSUSED*/
+int
+rip_usrreq(so, req, m, nam, control)
+ register struct socket *so;
+ int req;
+ struct mbuf *m, *nam, *control;
+{
+ register int error = 0;
+ register struct inpcb *inp = sotoinpcb(so);
+ int s;
+
+ if (req == PRU_CONTROL)
+ return (in_control(so, (u_long)m, (caddr_t)nam,
+ (struct ifnet *)control));
+
+ switch (req) {
+
+ case PRU_ATTACH:
+ if (inp)
+ panic("rip_attach");
+ if ((so->so_state & SS_PRIV) == 0) {
+ error = EACCES;
+ break;
+ }
+ s = splnet();
+ error = in_pcballoc(so, &ripcbinfo);
+ splx(s);
+ if (error)
+ break;
+ error = soreserve(so, rip_sendspace, rip_recvspace);
+ if (error)
+ break;
+ inp = (struct inpcb *)so->so_pcb;
+ inp->inp_ip_p = (int)nam;
+ break;
+
+ case PRU_DISCONNECT:
+ if ((so->so_state & SS_ISCONNECTED) == 0) {
+ error = ENOTCONN;
+ break;
+ }
+ /* FALLTHROUGH */
+ case PRU_ABORT:
+ soisdisconnected(so);
+ /* FALLTHROUGH */
+ case PRU_DETACH:
+ if (inp == 0)
+ panic("rip_detach");
+ if (so == ip_mrouter)
+ ip_mrouter_done();
+ ip_rsvp_force_done(so);
+ if (so == ip_rsvpd)
+ ip_rsvp_done();
+ in_pcbdetach(inp);
+ break;
+
+ case PRU_BIND:
+ {
+ struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);
+
+ if (nam->m_len != sizeof(*addr)) {
+ error = EINVAL;
+ break;
+ }
+ if ((ifnet == 0) ||
+ ((addr->sin_family != AF_INET) &&
+ (addr->sin_family != AF_IMPLINK)) ||
+ (addr->sin_addr.s_addr &&
+ ifa_ifwithaddr((struct sockaddr *)addr) == 0)) {
+ error = EADDRNOTAVAIL;
+ break;
+ }
+ inp->inp_laddr = addr->sin_addr;
+ break;
+ }
+ case PRU_CONNECT:
+ {
+ struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);
+
+ if (nam->m_len != sizeof(*addr)) {
+ error = EINVAL;
+ break;
+ }
+ if (ifnet == 0) {
+ error = EADDRNOTAVAIL;
+ break;
+ }
+ if ((addr->sin_family != AF_INET) &&
+ (addr->sin_family != AF_IMPLINK)) {
+ error = EAFNOSUPPORT;
+ break;
+ }
+ inp->inp_faddr = addr->sin_addr;
+ soisconnected(so);
+ break;
+ }
+
+ case PRU_CONNECT2:
+ error = EOPNOTSUPP;
+ break;
+
+ /*
+ * Mark the connection as being incapable of further input.
+ */
+ case PRU_SHUTDOWN:
+ socantsendmore(so);
+ break;
+
+ /*
+ * Ship a packet out. The appropriate raw output
+ * routine handles any massaging necessary.
+ */
+ case PRU_SEND:
+ {
+ register u_long dst;
+
+ if (so->so_state & SS_ISCONNECTED) {
+ if (nam) {
+ error = EISCONN;
+ break;
+ }
+ dst = inp->inp_faddr.s_addr;
+ } else {
+ if (nam == NULL) {
+ error = ENOTCONN;
+ break;
+ }
+ dst = mtod(nam, struct sockaddr_in *)->sin_addr.s_addr;
+ }
+ error = rip_output(m, so, dst);
+ m = NULL;
+ break;
+ }
+
+ case PRU_SENSE:
+ /*
+ * stat: don't bother with a blocksize.
+ */
+ return (0);
+
+ /*
+ * Not supported.
+ */
+ case PRU_RCVOOB:
+ case PRU_RCVD:
+ case PRU_LISTEN:
+ case PRU_ACCEPT:
+ case PRU_SENDOOB:
+ error = EOPNOTSUPP;
+ break;
+
+ case PRU_SOCKADDR:
+ in_setsockaddr(inp, nam);
+ break;
+
+ case PRU_PEERADDR:
+ in_setpeeraddr(inp, nam);
+ break;
+
+ default:
+ panic("rip_usrreq");
+ }
+ if (m != NULL)
+ m_freem(m);
+ return (error);
+}
diff --git a/cpukit/libnetworking/netinet/tcp.h b/cpukit/libnetworking/netinet/tcp.h
new file mode 100644
index 0000000000..131d8011cf
--- /dev/null
+++ b/cpukit/libnetworking/netinet/tcp.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)tcp.h 8.1 (Berkeley) 6/10/93
+ * $Id$
+ */
+
+#ifndef _NETINET_TCP_H_
+#define _NETINET_TCP_H_
+
+typedef u_long tcp_seq;
+typedef u_long tcp_cc; /* connection count per rfc1644 */
+
+/*
+ * TCP header.
+ * Per RFC 793, September, 1981.
+ */
+struct tcphdr {
+ u_short th_sport BYTE_PACK; /* source port */
+ u_short th_dport BYTE_PACK; /* destination port */
+ tcp_seq th_seq BYTE_PACK; /* sequence number */
+ tcp_seq th_ack BYTE_PACK; /* acknowledgement number */
+#if BYTE_ORDER == LITTLE_ENDIAN
+ u_char th_x2:4, /* (unused) */
+ th_off:4; /* data offset */
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char th_off:4, /* data offset */
+ th_x2:4; /* (unused) */
+#endif
+ u_char th_flags;
+#define TH_FIN 0x01
+#define TH_SYN 0x02
+#define TH_RST 0x04
+#define TH_PUSH 0x08
+#define TH_ACK 0x10
+#define TH_URG 0x20
+#define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG)
+
+ u_short th_win BYTE_PACK; /* window */
+ u_short th_sum BYTE_PACK; /* checksum */
+ u_short th_urp BYTE_PACK; /* urgent pointer */
+};
+
+#define TCPOPT_EOL 0
+#define TCPOPT_NOP 1
+#define TCPOPT_MAXSEG 2
+#define TCPOLEN_MAXSEG 4
+#define TCPOPT_WINDOW 3
+#define TCPOLEN_WINDOW 3
+#define TCPOPT_SACK_PERMITTED 4 /* Experimental */
+#define TCPOLEN_SACK_PERMITTED 2
+#define TCPOPT_SACK 5 /* Experimental */
+#define TCPOPT_TIMESTAMP 8
+#define TCPOLEN_TIMESTAMP 10
+#define TCPOLEN_TSTAMP_APPA (TCPOLEN_TIMESTAMP+2) /* appendix A */
+#define TCPOPT_TSTAMP_HDR \
+ (TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP)
+
+#define TCPOPT_CC 11 /* CC options: RFC-1644 */
+#define TCPOPT_CCNEW 12
+#define TCPOPT_CCECHO 13
+#define TCPOLEN_CC 6
+#define TCPOLEN_CC_APPA (TCPOLEN_CC+2)
+#define TCPOPT_CC_HDR(ccopt) \
+ (TCPOPT_NOP<<24|TCPOPT_NOP<<16|(ccopt)<<8|TCPOLEN_CC)
+
+/*
+ * Default maximum segment size for TCP.
+ * With an IP MSS of 576, this is 536,
+ * but 512 is probably more convenient.
+ * This should be defined as MIN(512, IP_MSS - sizeof (struct tcpiphdr)).
+ */
+#define TCP_MSS 512
+
+#define TCP_MAXWIN 65535 /* largest value for (unscaled) window */
+#define TTCP_CLIENT_SND_WND 4096 /* dflt send window for T/TCP client */
+
+#define TCP_MAX_WINSHIFT 14 /* maximum window shift */
+
+#define TCP_MAXHLEN (0xf<<2) /* max length of header in bytes */
+#define TCP_MAXOLEN (TCP_MAXHLEN - sizeof(struct tcphdr))
+ /* max space left for options */
+
+/*
+ * User-settable options (used with setsockopt).
+ */
+#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */
+#define TCP_MAXSEG 0x02 /* set maximum segment size */
+#define TCP_NOPUSH 0x04 /* don't push last block of write */
+#define TCP_NOOPT 0x08 /* don't use TCP options */
+
+#endif
diff --git a/cpukit/libnetworking/netinet/tcp_debug.c b/cpukit/libnetworking/netinet/tcp_debug.c
new file mode 100644
index 0000000000..2f88ae658e
--- /dev/null
+++ b/cpukit/libnetworking/netinet/tcp_debug.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)tcp_debug.c 8.1 (Berkeley) 6/10/93
+ * $Id$
+ */
+
+#include "opt_tcpdebug.h"
+
+#ifdef TCPDEBUG
+/* load symbolic names */
+#define PRUREQUESTS
+#define TCPSTATES
+#define TCPTIMERS
+#define TANAMES
+#endif
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/protosw.h>
+#include <sys/errno.h>
+
+#include <net/route.h>
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/in_pcb.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcp_fsm.h>
+#include <netinet/tcp_seq.h>
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_var.h>
+#include <netinet/tcpip.h>
+#include <netinet/tcp_debug.h>
+
+#ifdef TCPDEBUG
+static int tcpconsdebug = 0; /* set to 1 to enable prints */
+#endif
+
+static struct tcp_debug tcp_debug[TCP_NDEBUG];
+static int tcp_debx;
+
+/*
+ * Tcp debug routines
+ */
+void
+tcp_trace(act, ostate, tp, ti, req)
+ short act, ostate;
+ struct tcpcb *tp;
+ struct tcpiphdr *ti;
+ int req;
+{
+#ifdef TCPDEBUG
+ tcp_seq seq, ack;
+ int len, flags;
+#endif
+ struct tcp_debug *td = &tcp_debug[tcp_debx++];
+
+ if (tcp_debx == TCP_NDEBUG)
+ tcp_debx = 0;
+ td->td_time = iptime();
+ td->td_act = act;
+ td->td_ostate = ostate;
+ td->td_tcb = (caddr_t)tp;
+ if (tp)
+ td->td_cb = *tp;
+ else
+ bzero((caddr_t)&td->td_cb, sizeof (*tp));
+ if (ti)
+ td->td_ti = *ti;
+ else
+ bzero((caddr_t)&td->td_ti, sizeof (*ti));
+ td->td_req = req;
+#ifdef TCPDEBUG
+ if (tcpconsdebug == 0)
+ return;
+ if (tp)
+ printf("%p %s:", tp, tcpstates[ostate]);
+ else
+ printf("???????? ");
+ printf("%s ", tanames[act]);
+ switch (act) {
+
+ case TA_INPUT:
+ case TA_OUTPUT:
+ case TA_DROP:
+ if (ti == 0)
+ break;
+ seq = ti->ti_seq;
+ ack = ti->ti_ack;
+ len = ti->ti_len;
+ if (act == TA_OUTPUT) {
+ seq = ntohl(seq);
+ ack = ntohl(ack);
+ len = ntohs((u_short)len);
+ }
+ if (act == TA_OUTPUT)
+ len -= sizeof (struct tcphdr);
+ if (len)
+ printf("[%x..%x)", seq, seq+len);
+ else
+ printf("%x", seq);
+ printf("@%x, urp=%x", ack, ti->ti_urp);
+ flags = ti->ti_flags;
+ if (flags) {
+ char *cp = "<";
+#define pf(f) { \
+ if (ti->ti_flags & TH_##f) { \
+ printf("%s%s", cp, #f); \
+ cp = ","; \
+ } \
+}
+ pf(SYN); pf(ACK); pf(FIN); pf(RST); pf(PUSH); pf(URG);
+ printf(">");
+ }
+ break;
+
+ case TA_USER:
+ printf("%s", prurequests[req&0xff]);
+ if ((req & 0xff) == PRU_SLOWTIMO)
+ printf("<%s>", tcptimers[req>>8]);
+ break;
+ }
+ if (tp)
+ printf(" -> %s", tcpstates[tp->t_state]);
+ /* print out internal state of tp !?! */
+ printf("\n");
+ if (tp == 0)
+ return;
+ printf("\trcv_(nxt,wnd,up) (%x,%x,%x) snd_(una,nxt,max) (%x,%x,%x)\n",
+ tp->rcv_nxt, tp->rcv_wnd, tp->rcv_up, tp->snd_una, tp->snd_nxt,
+ tp->snd_max);
+ printf("\tsnd_(wl1,wl2,wnd) (%x,%x,%x)\n",
+ tp->snd_wl1, tp->snd_wl2, tp->snd_wnd);
+#endif /* TCPDEBUG */
+}
diff --git a/cpukit/libnetworking/netinet/tcp_debug.h b/cpukit/libnetworking/netinet/tcp_debug.h
new file mode 100644
index 0000000000..4bff757e2a
--- /dev/null
+++ b/cpukit/libnetworking/netinet/tcp_debug.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)tcp_debug.h 8.1 (Berkeley) 6/10/93
+ * $Id$
+ */
+
+#ifndef _NETINET_TCP_DEBUG_H_
+#define _NETINET_TCP_DEBUG_H_
+
+struct tcp_debug {
+ n_time td_time;
+ short td_act;
+ short td_ostate;
+ caddr_t td_tcb;
+ struct tcpiphdr td_ti;
+ short td_req;
+ struct tcpcb td_cb;
+};
+
+#define TA_INPUT 0
+#define TA_OUTPUT 1
+#define TA_USER 2
+#define TA_RESPOND 3
+#define TA_DROP 4
+
+#ifdef TANAMES
+static char *tanames[] =
+ { "input", "output", "user", "respond", "drop" };
+#endif
+
+#define TCP_NDEBUG 100
+
+#ifndef _KERNEL
+/* XXX common variables for broken applications. */
+struct tcp_debug tcp_debug[TCP_NDEBUG];
+int tcp_debx;
+#endif
+
+#endif /* !_NETINET_TCP_DEBUG_H_ */
diff --git a/cpukit/libnetworking/netinet/tcp_fsm.h b/cpukit/libnetworking/netinet/tcp_fsm.h
new file mode 100644
index 0000000000..3f2c12f54f
--- /dev/null
+++ b/cpukit/libnetworking/netinet/tcp_fsm.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)tcp_fsm.h 8.1 (Berkeley) 6/10/93
+ * $Id$
+ */
+
+#ifndef _NETINET_TCP_FSM_H_
+#define _NETINET_TCP_FSM_H_
+
+/*
+ * TCP FSM state definitions.
+ * Per RFC793, September, 1981.
+ */
+
+#define TCP_NSTATES 11
+
+#define TCPS_CLOSED 0 /* closed */
+#define TCPS_LISTEN 1 /* listening for connection */
+#define TCPS_SYN_SENT 2 /* active, have sent syn */
+#define TCPS_SYN_RECEIVED 3 /* have send and received syn */
+/* states < TCPS_ESTABLISHED are those where connections not established */
+#define TCPS_ESTABLISHED 4 /* established */
+#define TCPS_CLOSE_WAIT 5 /* rcvd fin, waiting for close */
+/* states > TCPS_CLOSE_WAIT are those where user has closed */
+#define TCPS_FIN_WAIT_1 6 /* have closed, sent fin */
+#define TCPS_CLOSING 7 /* closed xchd FIN; await FIN ACK */
+#define TCPS_LAST_ACK 8 /* had fin and close; await FIN ACK */
+/* states > TCPS_CLOSE_WAIT && < TCPS_FIN_WAIT_2 await ACK of FIN */
+#define TCPS_FIN_WAIT_2 9 /* have closed, fin is acked */
+#define TCPS_TIME_WAIT 10 /* in 2*msl quiet wait after close */
+
+#define TCPS_HAVERCVDSYN(s) ((s) >= TCPS_SYN_RECEIVED)
+#define TCPS_HAVEESTABLISHED(s) ((s) >= TCPS_ESTABLISHED)
+#define TCPS_HAVERCVDFIN(s) ((s) >= TCPS_TIME_WAIT)
+
+#ifdef TCPOUTFLAGS
+/*
+ * Flags used when sending segments in tcp_output.
+ * Basic flags (TH_RST,TH_ACK,TH_SYN,TH_FIN) are totally
+ * determined by state, with the proviso that TH_FIN is sent only
+ * if all data queued for output is included in the segment.
+ */
+static u_char tcp_outflags[TCP_NSTATES] = {
+ TH_RST|TH_ACK, 0, TH_SYN, TH_SYN|TH_ACK,
+ TH_ACK, TH_ACK,
+ TH_FIN|TH_ACK, TH_FIN|TH_ACK, TH_FIN|TH_ACK, TH_ACK, TH_ACK,
+};
+#endif
+
+#ifdef KPROF
+int tcp_acounts[TCP_NSTATES][PRU_NREQ];
+#endif
+
+#ifdef TCPSTATES
+char *tcpstates[] = {
+ "CLOSED", "LISTEN", "SYN_SENT", "SYN_RCVD",
+ "ESTABLISHED", "CLOSE_WAIT", "FIN_WAIT_1", "CLOSING",
+ "LAST_ACK", "FIN_WAIT_2", "TIME_WAIT",
+};
+#endif
+
+#endif
diff --git a/cpukit/libnetworking/netinet/tcp_input.c b/cpukit/libnetworking/netinet/tcp_input.c
new file mode 100644
index 0000000000..a33f9593c4
--- /dev/null
+++ b/cpukit/libnetworking/netinet/tcp_input.c
@@ -0,0 +1,2165 @@
+/*
+ * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1994, 1995
+ * The Regents of the University of California. 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 acknowledgment:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)tcp_input.c 8.12 (Berkeley) 5/24/95
+ * $Id$
+ */
+
+#include "opt_tcpdebug.h"
+
+#ifndef TUBA_INCLUDE
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/errno.h>
+#include <sys/syslog.h>
+
+#include <machine/cpu.h> /* before tcp_seq.h, for tcp_random18() */
+
+#include <net/if.h>
+#include <net/route.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/in_pcb.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcp_fsm.h>
+#include <netinet/tcp_seq.h>
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_var.h>
+#include <netinet/tcpip.h>
+#ifdef TCPDEBUG
+#include <netinet/tcp_debug.h>
+static struct tcpiphdr tcp_saveti;
+#endif
+
+static int tcprexmtthresh = 3;
+tcp_seq tcp_iss;
+tcp_cc tcp_ccgen;
+
+struct tcpstat tcpstat;
+SYSCTL_STRUCT(_net_inet_tcp, TCPCTL_STATS, stats,
+ CTLFLAG_RD, &tcpstat , tcpstat, "");
+
+static int log_in_vain = 0;
+SYSCTL_INT(_net_inet_tcp, OID_AUTO, log_in_vain, CTLFLAG_RW,
+ &log_in_vain, 0, "");
+
+u_long tcp_now;
+struct inpcbhead tcb;
+struct inpcbinfo tcbinfo;
+
+static void tcp_dooptions __P((struct tcpcb *,
+ u_char *, int, struct tcpiphdr *, struct tcpopt *));
+static void tcp_pulloutofband __P((struct socket *,
+ struct tcpiphdr *, struct mbuf *));
+static int tcp_reass __P((struct tcpcb *, struct tcpiphdr *, struct mbuf *));
+static void tcp_xmit_timer __P((struct tcpcb *, int));
+
+#endif /* TUBA_INCLUDE */
+
+/*
+ * Insert segment ti into reassembly queue of tcp with
+ * control block tp. Return TH_FIN if reassembly now includes
+ * a segment with FIN. The macro form does the common case inline
+ * (segment is the next to be received on an established connection,
+ * and the queue is empty), avoiding linkage into and removal
+ * from the queue and repetition of various conversions.
+ * Set DELACK for segments received in order, but ack immediately
+ * when segments are out of order (so fast retransmit can work).
+ */
+#ifdef TCP_ACK_HACK
+#define TCP_REASS(tp, ti, m, so, flags) { \
+ if ((ti)->ti_seq == (tp)->rcv_nxt && \
+ (tp)->seg_next == (struct tcpiphdr *)(tp) && \
+ (tp)->t_state == TCPS_ESTABLISHED) { \
+ if (ti->ti_flags & TH_PUSH) \
+ tp->t_flags |= TF_ACKNOW; \
+ else \
+ tp->t_flags |= TF_DELACK; \
+ (tp)->rcv_nxt += (ti)->ti_len; \
+ flags = (ti)->ti_flags & TH_FIN; \
+ tcpstat.tcps_rcvpack++;\
+ tcpstat.tcps_rcvbyte += (ti)->ti_len;\
+ sbappend(&(so)->so_rcv, (m)); \
+ sorwakeup(so); \
+ } else { \
+ (flags) = tcp_reass((tp), (ti), (m)); \
+ tp->t_flags |= TF_ACKNOW; \
+ } \
+}
+#else
+#define TCP_REASS(tp, ti, m, so, flags) { \
+ if ((ti)->ti_seq == (tp)->rcv_nxt && \
+ (tp)->seg_next == (struct tcpiphdr *)(tp) && \
+ (tp)->t_state == TCPS_ESTABLISHED) { \
+ tp->t_flags |= TF_DELACK; \
+ (tp)->rcv_nxt += (ti)->ti_len; \
+ flags = (ti)->ti_flags & TH_FIN; \
+ tcpstat.tcps_rcvpack++;\
+ tcpstat.tcps_rcvbyte += (ti)->ti_len;\
+ sbappend(&(so)->so_rcv, (m)); \
+ sorwakeup(so); \
+ } else { \
+ (flags) = tcp_reass((tp), (ti), (m)); \
+ tp->t_flags |= TF_ACKNOW; \
+ } \
+}
+#endif
+#ifndef TUBA_INCLUDE
+
+static int
+tcp_reass(tp, ti, m)
+ register struct tcpcb *tp;
+ register struct tcpiphdr *ti;
+ struct mbuf *m;
+{
+ register struct tcpiphdr *q;
+ struct socket *so = tp->t_inpcb->inp_socket;
+ int flags;
+ /*
+ * Call with ti==0 after become established to
+ * force pre-ESTABLISHED data up to user socket.
+ */
+ if (ti == 0)
+ goto present;
+
+ /*
+ * Find a segment which begins after this one does.
+ */
+ for (q = tp->seg_next; q != (struct tcpiphdr *)tp;
+ q = (struct tcpiphdr *)q->ti_next)
+ if (SEQ_GT(q->ti_seq, ti->ti_seq))
+ break;
+
+ /*
+ * If there is a preceding segment, it may provide some of
+ * our data already. If so, drop the data from the incoming
+ * segment. If it provides all of our data, drop us.
+ */
+ if ((struct tcpiphdr *)q->ti_prev != (struct tcpiphdr *)tp) {
+ register int i;
+ q = (struct tcpiphdr *)q->ti_prev;
+ /* conversion to int (in i) handles seq wraparound */
+ i = q->ti_seq + q->ti_len - ti->ti_seq;
+ if (i > 0) {
+ if (i >= ti->ti_len) {
+ tcpstat.tcps_rcvduppack++;
+ tcpstat.tcps_rcvdupbyte += ti->ti_len;
+ m_freem(m);
+ /*
+ * Try to present any queued data
+ * at the left window edge to the user.
+ * This is needed after the 3-WHS
+ * completes.
+ */
+ goto present; /* ??? */
+ }
+ m_adj(m, i);
+ ti->ti_len -= i;
+ ti->ti_seq += i;
+ }
+ q = (struct tcpiphdr *)(q->ti_next);
+ }
+ tcpstat.tcps_rcvoopack++;
+ tcpstat.tcps_rcvoobyte += ti->ti_len;
+#if (defined(__GNUC__) && defined(__arm__))
+ STR32_UNALGN(ti,m);
+#else
+ REASS_MBUF(ti) = m; /* XXX */
+#endif
+ /*
+ * While we overlap succeeding segments trim them or,
+ * if they are completely covered, dequeue them.
+ */
+ while (q != (struct tcpiphdr *)tp) {
+ register int i = (ti->ti_seq + ti->ti_len) - q->ti_seq;
+ if (i <= 0)
+ break;
+ if (i < q->ti_len) {
+ q->ti_seq += i;
+ q->ti_len -= i;
+#if (defined(__GNUC__) && defined(__arm__))
+ LD32_UNALGN(q,m);
+ m_adj(m, i);
+#else
+ m_adj(REASS_MBUF(q), i);
+#endif
+ break;
+ }
+ q = (struct tcpiphdr *)q->ti_next;
+#if (defined(__GNUC__) && defined(__arm__))
+ LD32_UNALGN((struct tcpiphdr *)q->ti_prev,m);
+#else
+ m = REASS_MBUF((struct tcpiphdr *)q->ti_prev);
+#endif
+ remque(q->ti_prev);
+ m_freem(m);
+ }
+
+ /*
+ * Stick new segment in its place.
+ */
+ insque(ti, q->ti_prev);
+
+present:
+ /*
+ * Present data to user, advancing rcv_nxt through
+ * completed sequence space.
+ */
+ if (!TCPS_HAVEESTABLISHED(tp->t_state))
+ return (0);
+ ti = tp->seg_next;
+ if (ti == (struct tcpiphdr *)tp || ti->ti_seq != tp->rcv_nxt)
+ return (0);
+ do {
+ tp->rcv_nxt += ti->ti_len;
+ flags = ti->ti_flags & TH_FIN;
+ remque(ti);
+#if (defined(__GNUC__) && defined(__arm__))
+ LD32_UNALGN(ti,m);
+#else
+ m = REASS_MBUF(ti);
+#endif
+ ti = (struct tcpiphdr *)ti->ti_next;
+ if (so->so_state & SS_CANTRCVMORE)
+ m_freem(m);
+ else
+ sbappend(&so->so_rcv, m);
+ } while (ti != (struct tcpiphdr *)tp && ti->ti_seq == tp->rcv_nxt);
+ sorwakeup(so);
+ return (flags);
+}
+
+/*
+ * TCP input routine, follows pages 65-76 of the
+ * protocol specification dated September, 1981 very closely.
+ */
+void
+tcp_input(m, iphlen)
+ register struct mbuf *m;
+ int iphlen;
+{
+ register struct tcpiphdr *ti;
+ register struct inpcb *inp;
+ u_char *optp = NULL;
+ int optlen = 0;
+ int len, tlen, off;
+ register struct tcpcb *tp = 0;
+ register int tiflags;
+ struct socket *so = 0;
+ int todrop, acked, ourfinisacked, needoutput = 0;
+ struct in_addr laddr;
+ int dropsocket = 0;
+ int iss = 0;
+ u_long tiwin;
+ struct tcpopt to; /* options in this segment */
+ struct rmxp_tao *taop; /* pointer to our TAO cache entry */
+ struct rmxp_tao tao_noncached; /* in case there's no cached entry */
+#ifdef TCPDEBUG
+ short ostate = 0;
+#endif
+
+ bzero((char *)&to, sizeof(to));
+
+ tcpstat.tcps_rcvtotal++;
+ /*
+ * Get IP and TCP header together in first mbuf.
+ * Note: IP leaves IP header in first mbuf.
+ */
+ ti = mtod(m, struct tcpiphdr *);
+ if (iphlen > sizeof (struct ip))
+ ip_stripoptions(m, (struct mbuf *)0);
+ if (m->m_len < sizeof (struct tcpiphdr)) {
+ if ((m = m_pullup(m, sizeof (struct tcpiphdr))) == 0) {
+ tcpstat.tcps_rcvshort++;
+ return;
+ }
+ ti = mtod(m, struct tcpiphdr *);
+ }
+
+ /*
+ * Checksum extended TCP header and data.
+ */
+ tlen = ((struct ip *)ti)->ip_len;
+ len = sizeof (struct ip) + tlen;
+ ti->ti_next = ti->ti_prev = 0;
+ ti->ti_x1 = 0;
+ ti->ti_len = (u_short)tlen;
+ HTONS(ti->ti_len);
+ ti->ti_sum = in_cksum(m, len);
+ if (ti->ti_sum) {
+ tcpstat.tcps_rcvbadsum++;
+ goto drop;
+ }
+#endif /* TUBA_INCLUDE */
+
+ /*
+ * Check that TCP offset makes sense,
+ * pull out TCP options and adjust length. XXX
+ */
+ off = ti->ti_off << 2;
+ if (off < sizeof (struct tcphdr) || off > tlen) {
+ tcpstat.tcps_rcvbadoff++;
+ goto drop;
+ }
+ tlen -= off;
+ ti->ti_len = tlen;
+ if (off > sizeof (struct tcphdr)) {
+ if (m->m_len < sizeof(struct ip) + off) {
+ if ((m = m_pullup(m, sizeof (struct ip) + off)) == 0) {
+ tcpstat.tcps_rcvshort++;
+ return;
+ }
+ ti = mtod(m, struct tcpiphdr *);
+ }
+ optlen = off - sizeof (struct tcphdr);
+ optp = mtod(m, u_char *) + sizeof (struct tcpiphdr);
+ }
+ tiflags = ti->ti_flags;
+
+ /*
+ * Convert TCP protocol specific fields to host format.
+ */
+ NTOHL(ti->ti_seq);
+ NTOHL(ti->ti_ack);
+ NTOHS(ti->ti_win);
+ NTOHS(ti->ti_urp);
+
+ /*
+ * Drop TCP, IP headers and TCP options.
+ */
+ m->m_data += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
+ m->m_len -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
+
+ /*
+ * Locate pcb for segment.
+ */
+findpcb:
+ inp = in_pcblookuphash(&tcbinfo, ti->ti_src, ti->ti_sport,
+ ti->ti_dst, ti->ti_dport, 1);
+
+ /*
+ * If the state is CLOSED (i.e., TCB does not exist) then
+ * all data in the incoming segment is discarded.
+ * If the TCB exists but is in CLOSED state, it is embryonic,
+ * but should either do a listen or a connect soon.
+ */
+ if (inp == NULL) {
+ if (log_in_vain && tiflags & TH_SYN) {
+ char buf[4*sizeof "123"];
+
+ strcpy(buf, inet_ntoa(ti->ti_dst));
+ log(LOG_INFO, "Connection attempt to TCP %s:%d"
+ " from %s:%d\n",
+ buf, ntohs(ti->ti_dport),
+ inet_ntoa(ti->ti_src), ntohs(ti->ti_sport));
+ }
+ goto dropwithreset;
+ }
+ tp = intotcpcb(inp);
+ if (tp == 0)
+ goto dropwithreset;
+ if (tp->t_state == TCPS_CLOSED)
+ goto drop;
+
+ /* Unscale the window into a 32-bit value. */
+ if ((tiflags & TH_SYN) == 0)
+ tiwin = ti->ti_win << tp->snd_scale;
+ else
+ tiwin = ti->ti_win;
+
+ so = inp->inp_socket;
+ if (so->so_options & (SO_DEBUG|SO_ACCEPTCONN)) {
+#ifdef TCPDEBUG
+ if (so->so_options & SO_DEBUG) {
+ ostate = tp->t_state;
+ tcp_saveti = *ti;
+ }
+#endif
+ if (so->so_options & SO_ACCEPTCONN) {
+ register struct tcpcb *tp0 = tp;
+ struct socket *so2;
+ if ((tiflags & (TH_RST|TH_ACK|TH_SYN)) != TH_SYN) {
+ /*
+ * Note: dropwithreset makes sure we don't
+ * send a RST in response to a RST.
+ */
+ if (tiflags & TH_ACK) {
+ tcpstat.tcps_badsyn++;
+ goto dropwithreset;
+ }
+ goto drop;
+ }
+ so2 = sonewconn(so, 0);
+ if (so2 == 0) {
+ tcpstat.tcps_listendrop++;
+ so2 = sodropablereq(so);
+ if (so2) {
+ tcp_drop(sototcpcb(so2), ETIMEDOUT);
+ so2 = sonewconn(so, 0);
+ }
+ if (!so2)
+ goto drop;
+ }
+ so = so2;
+ /*
+ * This is ugly, but ....
+ *
+ * Mark socket as temporary until we're
+ * committed to keeping it. The code at
+ * ``drop'' and ``dropwithreset'' check the
+ * flag dropsocket to see if the temporary
+ * socket created here should be discarded.
+ * We mark the socket as discardable until
+ * we're committed to it below in TCPS_LISTEN.
+ */
+ dropsocket++;
+ inp = (struct inpcb *)so->so_pcb;
+ inp->inp_laddr = ti->ti_dst;
+ inp->inp_lport = ti->ti_dport;
+ in_pcbrehash(inp);
+#if BSD>=43
+ inp->inp_options = ip_srcroute();
+#endif
+ tp = intotcpcb(inp);
+ tp->t_state = TCPS_LISTEN;
+ tp->t_flags |= tp0->t_flags & (TF_NOPUSH|TF_NOOPT);
+
+ /* Compute proper scaling value from buffer space */
+ while (tp->request_r_scale < TCP_MAX_WINSHIFT &&
+ TCP_MAXWIN << tp->request_r_scale < so->so_rcv.sb_hiwat)
+ tp->request_r_scale++;
+ }
+ }
+
+ /*
+ * Segment received on connection.
+ * Reset idle time and keep-alive timer.
+ */
+ tp->t_idle = 0;
+ if (TCPS_HAVEESTABLISHED(tp->t_state))
+ tp->t_timer[TCPT_KEEP] = tcp_keepidle;
+
+ /*
+ * Process options if not in LISTEN state,
+ * else do it below (after getting remote address).
+ */
+ if (tp->t_state != TCPS_LISTEN)
+ tcp_dooptions(tp, optp, optlen, ti, &to);
+
+ /*
+ * Header prediction: check for the two common cases
+ * of a uni-directional data xfer. If the packet has
+ * no control flags, is in-sequence, the window didn't
+ * change and we're not retransmitting, it's a
+ * candidate. If the length is zero and the ack moved
+ * forward, we're the sender side of the xfer. Just
+ * free the data acked & wake any higher level process
+ * that was blocked waiting for space. If the length
+ * is non-zero and the ack didn't move, we're the
+ * receiver side. If we're getting packets in-order
+ * (the reassembly queue is empty), add the data to
+ * the socket buffer and note that we need a delayed ack.
+ * Make sure that the hidden state-flags are also off.
+ * Since we check for TCPS_ESTABLISHED above, it can only
+ * be TH_NEEDSYN.
+ */
+ if (tp->t_state == TCPS_ESTABLISHED &&
+ (tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) == TH_ACK &&
+ ((tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN)) == 0) &&
+ ((to.to_flag & TOF_TS) == 0 ||
+ TSTMP_GEQ(to.to_tsval, tp->ts_recent)) &&
+ /*
+ * Using the CC option is compulsory if once started:
+ * the segment is OK if no T/TCP was negotiated or
+ * if the segment has a CC option equal to CCrecv
+ */
+ ((tp->t_flags & (TF_REQ_CC|TF_RCVD_CC)) != (TF_REQ_CC|TF_RCVD_CC) ||
+ ((to.to_flag & TOF_CC) != 0 && to.to_cc == tp->cc_recv)) &&
+ ti->ti_seq == tp->rcv_nxt &&
+ tiwin && tiwin == tp->snd_wnd &&
+ tp->snd_nxt == tp->snd_max) {
+
+ /*
+ * If last ACK falls within this segment's sequence numbers,
+ * record the timestamp.
+ * NOTE that the test is modified according to the latest
+ * proposal of the tcplw@cray.com list (Braden 1993/04/26).
+ */
+ if ((to.to_flag & TOF_TS) != 0 &&
+ SEQ_LEQ(ti->ti_seq, tp->last_ack_sent)) {
+ tp->ts_recent_age = tcp_now;
+ tp->ts_recent = to.to_tsval;
+ }
+
+ if (ti->ti_len == 0) {
+ if (SEQ_GT(ti->ti_ack, tp->snd_una) &&
+ SEQ_LEQ(ti->ti_ack, tp->snd_max) &&
+ tp->snd_cwnd >= tp->snd_wnd &&
+ tp->t_dupacks < tcprexmtthresh) {
+ /*
+ * this is a pure ack for outstanding data.
+ */
+ ++tcpstat.tcps_predack;
+ if ((to.to_flag & TOF_TS) != 0)
+ tcp_xmit_timer(tp,
+ tcp_now - to.to_tsecr + 1);
+ else if (tp->t_rtt &&
+ SEQ_GT(ti->ti_ack, tp->t_rtseq))
+ tcp_xmit_timer(tp, tp->t_rtt);
+ acked = ti->ti_ack - tp->snd_una;
+ tcpstat.tcps_rcvackpack++;
+ tcpstat.tcps_rcvackbyte += acked;
+ sbdrop(&so->so_snd, acked);
+ tp->snd_una = ti->ti_ack;
+ m_freem(m);
+
+ /*
+ * If all outstanding data are acked, stop
+ * retransmit timer, otherwise restart timer
+ * using current (possibly backed-off) value.
+ * If process is waiting for space,
+ * wakeup/selwakeup/signal. If data
+ * are ready to send, let tcp_output
+ * decide between more output or persist.
+ */
+ if (tp->snd_una == tp->snd_max)
+ tp->t_timer[TCPT_REXMT] = 0;
+ else if (tp->t_timer[TCPT_PERSIST] == 0)
+ tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;
+
+ if (so->so_snd.sb_flags & SB_NOTIFY)
+ sowwakeup(so);
+ if (so->so_snd.sb_cc)
+ (void) tcp_output(tp);
+ return;
+ }
+ } else if (ti->ti_ack == tp->snd_una &&
+ tp->seg_next == (struct tcpiphdr *)tp &&
+ ti->ti_len <= sbspace(&so->so_rcv)) {
+ /*
+ * this is a pure, in-sequence data packet
+ * with nothing on the reassembly queue and
+ * we have enough buffer space to take it.
+ */
+ ++tcpstat.tcps_preddat;
+ tp->rcv_nxt += ti->ti_len;
+ tcpstat.tcps_rcvpack++;
+ tcpstat.tcps_rcvbyte += ti->ti_len;
+ /*
+ * Add data to socket buffer.
+ */
+ sbappend(&so->so_rcv, m);
+ sorwakeup(so);
+#ifdef TCP_ACK_HACK
+ /*
+ * If this is a short packet, then ACK now - with Nagel
+ * congestion avoidance sender won't send more until
+ * he gets an ACK.
+ */
+ if (tiflags & TH_PUSH) {
+ tp->t_flags |= TF_ACKNOW;
+ tcp_output(tp);
+ } else {
+ tp->t_flags |= TF_DELACK;
+ }
+#else
+ tp->t_flags |= TF_DELACK;
+#endif
+ return;
+ }
+ }
+
+ /*
+ * Calculate amount of space in receive window,
+ * and then do TCP input processing.
+ * Receive window is amount of space in rcv queue,
+ * but not less than advertised window.
+ */
+ { int win;
+
+ win = sbspace(&so->so_rcv);
+ if (win < 0)
+ win = 0;
+ tp->rcv_wnd = imax(win, (int)(tp->rcv_adv - tp->rcv_nxt));
+ }
+
+ switch (tp->t_state) {
+
+ /*
+ * If the state is LISTEN then ignore segment if it contains an RST.
+ * If the segment contains an ACK then it is bad and send a RST.
+ * If it does not contain a SYN then it is not interesting; drop it.
+ * If it is from this socket, drop it, it must be forged.
+ * Don't bother responding if the destination was a broadcast.
+ * Otherwise initialize tp->rcv_nxt, and tp->irs, select an initial
+ * tp->iss, and send a segment:
+ * <SEQ=ISS><ACK=RCV_NXT><CTL=SYN,ACK>
+ * Also initialize tp->snd_nxt to tp->iss+1 and tp->snd_una to tp->iss.
+ * Fill in remote peer address fields if not previously specified.
+ * Enter SYN_RECEIVED state, and process any other fields of this
+ * segment in this state.
+ */
+ case TCPS_LISTEN: {
+ struct mbuf *am;
+ register struct sockaddr_in *sin;
+
+ if (tiflags & TH_RST)
+ goto drop;
+ if (tiflags & TH_ACK)
+ goto dropwithreset;
+ if ((tiflags & TH_SYN) == 0)
+ goto drop;
+ if ((ti->ti_dport == ti->ti_sport) &&
+ (ti->ti_dst.s_addr == ti->ti_src.s_addr))
+ goto drop;
+ /*
+ * RFC1122 4.2.3.10, p. 104: discard bcast/mcast SYN
+ * in_broadcast() should never return true on a received
+ * packet with M_BCAST not set.
+ */
+ if (m->m_flags & (M_BCAST|M_MCAST) ||
+ IN_MULTICAST(ntohl(ti->ti_dst.s_addr)))
+ goto drop;
+ am = m_get(M_DONTWAIT, MT_SONAME); /* XXX */
+ if (am == NULL)
+ goto drop;
+ am->m_len = sizeof (struct sockaddr_in);
+ sin = mtod(am, struct sockaddr_in *);
+ sin->sin_family = AF_INET;
+ sin->sin_len = sizeof(*sin);
+ sin->sin_addr = ti->ti_src;
+ sin->sin_port = ti->ti_sport;
+ bzero((caddr_t)sin->sin_zero, sizeof(sin->sin_zero));
+ laddr = inp->inp_laddr;
+ if (inp->inp_laddr.s_addr == INADDR_ANY)
+ inp->inp_laddr = ti->ti_dst;
+ if (in_pcbconnect(inp, am)) {
+ inp->inp_laddr = laddr;
+ (void) m_free(am);
+ goto drop;
+ }
+ (void) m_free(am);
+ tp->t_template = tcp_template(tp);
+ if (tp->t_template == 0) {
+ tp = tcp_drop(tp, ENOBUFS);
+ dropsocket = 0; /* socket is already gone */
+ goto drop;
+ }
+ if ((taop = tcp_gettaocache(inp)) == NULL) {
+ taop = &tao_noncached;
+ bzero(taop, sizeof(*taop));
+ }
+ tcp_dooptions(tp, optp, optlen, ti, &to);
+ if (iss)
+ tp->iss = iss;
+ else
+ tp->iss = tcp_iss;
+ tcp_iss += TCP_ISSINCR/4;
+ tp->irs = ti->ti_seq;
+ tcp_sendseqinit(tp);
+ tcp_rcvseqinit(tp);
+ /*
+ * Initialization of the tcpcb for transaction;
+ * set SND.WND = SEG.WND,
+ * initialize CCsend and CCrecv.
+ */
+ tp->snd_wnd = tiwin; /* initial send-window */
+ tp->cc_send = CC_INC(tcp_ccgen);
+ tp->cc_recv = to.to_cc;
+ /*
+ * Perform TAO test on incoming CC (SEG.CC) option, if any.
+ * - compare SEG.CC against cached CC from the same host,
+ * if any.
+ * - if SEG.CC > chached value, SYN must be new and is accepted
+ * immediately: save new CC in the cache, mark the socket
+ * connected, enter ESTABLISHED state, turn on flag to
+ * send a SYN in the next segment.
+ * A virtual advertised window is set in rcv_adv to
+ * initialize SWS prevention. Then enter normal segment
+ * processing: drop SYN, process data and FIN.
+ * - otherwise do a normal 3-way handshake.
+ */
+ if ((to.to_flag & TOF_CC) != 0) {
+ if (taop->tao_cc != 0 && CC_GT(to.to_cc, taop->tao_cc)) {
+ taop->tao_cc = to.to_cc;
+ tp->t_state = TCPS_ESTABLISHED;
+
+ /*
+ * If there is a FIN, or if there is data and the
+ * connection is local, then delay SYN,ACK(SYN) in
+ * the hope of piggy-backing it on a response
+ * segment. Otherwise must send ACK now in case
+ * the other side is slow starting.
+ */
+ if ((tiflags & TH_FIN) || (ti->ti_len != 0 &&
+ in_localaddr(inp->inp_faddr)))
+ tp->t_flags |= (TF_DELACK | TF_NEEDSYN);
+ else
+ tp->t_flags |= (TF_ACKNOW | TF_NEEDSYN);
+
+ /*
+ * Limit the `virtual advertised window' to TCP_MAXWIN
+ * here. Even if we requested window scaling, it will
+ * become effective only later when our SYN is acked.
+ */
+ tp->rcv_adv += min(tp->rcv_wnd, TCP_MAXWIN);
+ tcpstat.tcps_connects++;
+ soisconnected(so);
+ tp->t_timer[TCPT_KEEP] = tcp_keepinit;
+ dropsocket = 0; /* committed to socket */
+ tcpstat.tcps_accepts++;
+ goto trimthenstep6;
+ }
+ /* else do standard 3-way handshake */
+ } else {
+ /*
+ * No CC option, but maybe CC.NEW:
+ * invalidate cached value.
+ */
+ taop->tao_cc = 0;
+ }
+ /*
+ * TAO test failed or there was no CC option,
+ * do a standard 3-way handshake.
+ */
+ tp->t_flags |= TF_ACKNOW;
+ tp->t_state = TCPS_SYN_RECEIVED;
+ tp->t_timer[TCPT_KEEP] = tcp_keepinit;
+ dropsocket = 0; /* committed to socket */
+ tcpstat.tcps_accepts++;
+ goto trimthenstep6;
+ }
+
+ /*
+ * If the state is SYN_RECEIVED:
+ * if seg contains SYN/ACK, send a RST.
+ * if seg contains an ACK, but not for our SYN/ACK, send a RST.
+ */
+ case TCPS_SYN_RECEIVED:
+ if (tiflags & TH_ACK) {
+ if (tiflags & TH_SYN) {
+ tcpstat.tcps_badsyn++;
+ goto dropwithreset;
+ }
+ if (SEQ_LEQ(ti->ti_ack, tp->snd_una) ||
+ SEQ_GT(ti->ti_ack, tp->snd_max))
+ goto dropwithreset;
+ }
+ break;
+
+ /*
+ * If the state is SYN_SENT:
+ * if seg contains an ACK, but not for our SYN, drop the input.
+ * if seg contains a RST, then drop the connection.
+ * if seg does not contain SYN, then drop it.
+ * Otherwise this is an acceptable SYN segment
+ * initialize tp->rcv_nxt and tp->irs
+ * if seg contains ack then advance tp->snd_una
+ * if SYN has been acked change to ESTABLISHED else SYN_RCVD state
+ * arrange for segment to be acked (eventually)
+ * continue processing rest of data/controls, beginning with URG
+ */
+ case TCPS_SYN_SENT:
+ if ((taop = tcp_gettaocache(inp)) == NULL) {
+ taop = &tao_noncached;
+ bzero(taop, sizeof(*taop));
+ }
+
+ if ((tiflags & TH_ACK) &&
+ (SEQ_LEQ(ti->ti_ack, tp->iss) ||
+ SEQ_GT(ti->ti_ack, tp->snd_max))) {
+ /*
+ * If we have a cached CCsent for the remote host,
+ * hence we haven't just crashed and restarted,
+ * do not send a RST. This may be a retransmission
+ * from the other side after our earlier ACK was lost.
+ * Our new SYN, when it arrives, will serve as the
+ * needed ACK.
+ */
+ if (taop->tao_ccsent != 0)
+ goto drop;
+ else
+ goto dropwithreset;
+ }
+ if (tiflags & TH_RST) {
+ if (tiflags & TH_ACK)
+ tp = tcp_drop(tp, ECONNREFUSED);
+ goto drop;
+ }
+ if ((tiflags & TH_SYN) == 0)
+ goto drop;
+ tp->snd_wnd = ti->ti_win; /* initial send window */
+ tp->cc_recv = to.to_cc; /* foreign CC */
+
+ tp->irs = ti->ti_seq;
+ tcp_rcvseqinit(tp);
+ if (tiflags & TH_ACK) {
+ /*
+ * Our SYN was acked. If segment contains CC.ECHO
+ * option, check it to make sure this segment really
+ * matches our SYN. If not, just drop it as old
+ * duplicate, but send an RST if we're still playing
+ * by the old rules. If no CC.ECHO option, make sure
+ * we don't get fooled into using T/TCP.
+ */
+ if (to.to_flag & TOF_CCECHO) {
+ if (tp->cc_send != to.to_ccecho) {
+ if (taop->tao_ccsent != 0)
+ goto drop;
+ else
+ goto dropwithreset;
+ }
+ } else
+ tp->t_flags &= ~TF_RCVD_CC;
+ tcpstat.tcps_connects++;
+ soisconnected(so);
+ /* Do window scaling on this connection? */
+ if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==
+ (TF_RCVD_SCALE|TF_REQ_SCALE)) {
+ tp->snd_scale = tp->requested_s_scale;
+ tp->rcv_scale = tp->request_r_scale;
+ }
+ /* Segment is acceptable, update cache if undefined. */
+ if (taop->tao_ccsent == 0)
+ taop->tao_ccsent = to.to_ccecho;
+
+ tp->rcv_adv += tp->rcv_wnd;
+ tp->snd_una++; /* SYN is acked */
+ /*
+ * If there's data, delay ACK; if there's also a FIN
+ * ACKNOW will be turned on later.
+ */
+ if (ti->ti_len != 0)
+ tp->t_flags |= TF_DELACK;
+ else
+ tp->t_flags |= TF_ACKNOW;
+ /*
+ * Received <SYN,ACK> in SYN_SENT[*] state.
+ * Transitions:
+ * SYN_SENT --> ESTABLISHED
+ * SYN_SENT* --> FIN_WAIT_1
+ */
+ if (tp->t_flags & TF_NEEDFIN) {
+ tp->t_state = TCPS_FIN_WAIT_1;
+ tp->t_flags &= ~TF_NEEDFIN;
+ tiflags &= ~TH_SYN;
+ } else {
+ tp->t_state = TCPS_ESTABLISHED;
+ tp->t_timer[TCPT_KEEP] = tcp_keepidle;
+ }
+ } else {
+ /*
+ * Received initial SYN in SYN-SENT[*] state => simul-
+ * taneous open. If segment contains CC option and there is
+ * a cached CC, apply TAO test; if it succeeds, connection is
+ * half-synchronized. Otherwise, do 3-way handshake:
+ * SYN-SENT -> SYN-RECEIVED
+ * SYN-SENT* -> SYN-RECEIVED*
+ * If there was no CC option, clear cached CC value.
+ */
+ tp->t_flags |= TF_ACKNOW;
+ tp->t_timer[TCPT_REXMT] = 0;
+ if (to.to_flag & TOF_CC) {
+ if (taop->tao_cc != 0 &&
+ CC_GT(to.to_cc, taop->tao_cc)) {
+ /*
+ * update cache and make transition:
+ * SYN-SENT -> ESTABLISHED*
+ * SYN-SENT* -> FIN-WAIT-1*
+ */
+ taop->tao_cc = to.to_cc;
+ if (tp->t_flags & TF_NEEDFIN) {
+ tp->t_state = TCPS_FIN_WAIT_1;
+ tp->t_flags &= ~TF_NEEDFIN;
+ } else {
+ tp->t_state = TCPS_ESTABLISHED;
+ tp->t_timer[TCPT_KEEP] = tcp_keepidle;
+ }
+ tp->t_flags |= TF_NEEDSYN;
+ } else
+ tp->t_state = TCPS_SYN_RECEIVED;
+ } else {
+ /* CC.NEW or no option => invalidate cache */
+ taop->tao_cc = 0;
+ tp->t_state = TCPS_SYN_RECEIVED;
+ }
+ }
+
+trimthenstep6:
+ /*
+ * Advance ti->ti_seq to correspond to first data byte.
+ * If data, trim to stay within window,
+ * dropping FIN if necessary.
+ */
+ ti->ti_seq++;
+ if (ti->ti_len > tp->rcv_wnd) {
+ todrop = ti->ti_len - tp->rcv_wnd;
+ m_adj(m, -todrop);
+ ti->ti_len = tp->rcv_wnd;
+ tiflags &= ~TH_FIN;
+ tcpstat.tcps_rcvpackafterwin++;
+ tcpstat.tcps_rcvbyteafterwin += todrop;
+ }
+ tp->snd_wl1 = ti->ti_seq - 1;
+ tp->rcv_up = ti->ti_seq;
+ /*
+ * Client side of transaction: already sent SYN and data.
+ * If the remote host used T/TCP to validate the SYN,
+ * our data will be ACK'd; if so, enter normal data segment
+ * processing in the middle of step 5, ack processing.
+ * Otherwise, goto step 6.
+ */
+ if (tiflags & TH_ACK)
+ goto process_ACK;
+ goto step6;
+ /*
+ * If the state is LAST_ACK or CLOSING or TIME_WAIT:
+ * if segment contains a SYN and CC [not CC.NEW] option:
+ * if state == TIME_WAIT and connection duration > MSL,
+ * drop packet and send RST;
+ *
+ * if SEG.CC > CCrecv then is new SYN, and can implicitly
+ * ack the FIN (and data) in retransmission queue.
+ * Complete close and delete TCPCB. Then reprocess
+ * segment, hoping to find new TCPCB in LISTEN state;
+ *
+ * else must be old SYN; drop it.
+ * else do normal processing.
+ */
+ case TCPS_LAST_ACK:
+ case TCPS_CLOSING:
+ case TCPS_TIME_WAIT:
+ if ((tiflags & TH_SYN) &&
+ (to.to_flag & TOF_CC) && tp->cc_recv != 0) {
+ if (tp->t_state == TCPS_TIME_WAIT &&
+ tp->t_duration > TCPTV_MSL)
+ goto dropwithreset;
+ if (CC_GT(to.to_cc, tp->cc_recv)) {
+ tp = tcp_close(tp);
+ goto findpcb;
+ }
+ else
+ goto drop;
+ }
+ break; /* continue normal processing */
+ }
+
+ /*
+ * States other than LISTEN or SYN_SENT.
+ * First check timestamp, if present.
+ * Then check the connection count, if present.
+ * Then check that at least some bytes of segment are within
+ * receive window. If segment begins before rcv_nxt,
+ * drop leading data (and SYN); if nothing left, just ack.
+ *
+ * RFC 1323 PAWS: If we have a timestamp reply on this segment
+ * and it's less than ts_recent, drop it.
+ */
+ if ((to.to_flag & TOF_TS) != 0 && (tiflags & TH_RST) == 0 &&
+ tp->ts_recent && TSTMP_LT(to.to_tsval, tp->ts_recent)) {
+
+ /* Check to see if ts_recent is over 24 days old. */
+ if ((int)(tcp_now - tp->ts_recent_age) > TCP_PAWS_IDLE) {
+ /*
+ * Invalidate ts_recent. If this segment updates
+ * ts_recent, the age will be reset later and ts_recent
+ * will get a valid value. If it does not, setting
+ * ts_recent to zero will at least satisfy the
+ * requirement that zero be placed in the timestamp
+ * echo reply when ts_recent isn't valid. The
+ * age isn't reset until we get a valid ts_recent
+ * because we don't want out-of-order segments to be
+ * dropped when ts_recent is old.
+ */
+ tp->ts_recent = 0;
+ } else {
+ tcpstat.tcps_rcvduppack++;
+ tcpstat.tcps_rcvdupbyte += ti->ti_len;
+ tcpstat.tcps_pawsdrop++;
+ goto dropafterack;
+ }
+ }
+
+ /*
+ * T/TCP mechanism
+ * If T/TCP was negotiated and the segment doesn't have CC,
+ * or if it's CC is wrong then drop the segment.
+ * RST segments do not have to comply with this.
+ */
+ if ((tp->t_flags & (TF_REQ_CC|TF_RCVD_CC)) == (TF_REQ_CC|TF_RCVD_CC) &&
+ ((to.to_flag & TOF_CC) == 0 || tp->cc_recv != to.to_cc) &&
+ (tiflags & TH_RST) == 0)
+ goto dropafterack;
+
+ todrop = tp->rcv_nxt - ti->ti_seq;
+ if (todrop > 0) {
+ if (tiflags & TH_SYN) {
+ tiflags &= ~TH_SYN;
+ ti->ti_seq++;
+ if (ti->ti_urp > 1)
+ ti->ti_urp--;
+ else
+ tiflags &= ~TH_URG;
+ todrop--;
+ }
+ /*
+ * Following if statement from Stevens, vol. 2, p. 960.
+ */
+ if (todrop > ti->ti_len
+ || (todrop == ti->ti_len && (tiflags & TH_FIN) == 0)) {
+ /*
+ * Any valid FIN must be to the left of the window.
+ * At this point the FIN must be a duplicate or out
+ * of sequence; drop it.
+ */
+ tiflags &= ~TH_FIN;
+
+ /*
+ * Send an ACK to resynchronize and drop any data.
+ * But keep on processing for RST or ACK.
+ */
+ tp->t_flags |= TF_ACKNOW;
+ todrop = ti->ti_len;
+ tcpstat.tcps_rcvduppack++;
+ tcpstat.tcps_rcvdupbyte += todrop;
+ } else {
+ tcpstat.tcps_rcvpartduppack++;
+ tcpstat.tcps_rcvpartdupbyte += todrop;
+ }
+ m_adj(m, todrop);
+ ti->ti_seq += todrop;
+ ti->ti_len -= todrop;
+ if (ti->ti_urp > todrop)
+ ti->ti_urp -= todrop;
+ else {
+ tiflags &= ~TH_URG;
+ ti->ti_urp = 0;
+ }
+ }
+
+ /*
+ * If new data are received on a connection after the
+ * user processes are gone, then RST the other end.
+ */
+ if ((so->so_state & SS_NOFDREF) &&
+ tp->t_state > TCPS_CLOSE_WAIT && ti->ti_len) {
+ tp = tcp_close(tp);
+ tcpstat.tcps_rcvafterclose++;
+ goto dropwithreset;
+ }
+
+ /*
+ * If segment ends after window, drop trailing data
+ * (and PUSH and FIN); if nothing left, just ACK.
+ */
+ todrop = (ti->ti_seq+ti->ti_len) - (tp->rcv_nxt+tp->rcv_wnd);
+ if (todrop > 0) {
+ tcpstat.tcps_rcvpackafterwin++;
+ if (todrop >= ti->ti_len) {
+ tcpstat.tcps_rcvbyteafterwin += ti->ti_len;
+ /*
+ * If a new connection request is received
+ * while in TIME_WAIT, drop the old connection
+ * and start over if the sequence numbers
+ * are above the previous ones.
+ */
+ if (tiflags & TH_SYN &&
+ tp->t_state == TCPS_TIME_WAIT &&
+ SEQ_GT(ti->ti_seq, tp->rcv_nxt)) {
+ iss = tp->rcv_nxt + TCP_ISSINCR;
+ tp = tcp_close(tp);
+ goto findpcb;
+ }
+ /*
+ * If window is closed can only take segments at
+ * window edge, and have to drop data and PUSH from
+ * incoming segments. Continue processing, but
+ * remember to ack. Otherwise, drop segment
+ * and ack.
+ */
+ if (tp->rcv_wnd == 0 && ti->ti_seq == tp->rcv_nxt) {
+ tp->t_flags |= TF_ACKNOW;
+ tcpstat.tcps_rcvwinprobe++;
+ } else
+ goto dropafterack;
+ } else
+ tcpstat.tcps_rcvbyteafterwin += todrop;
+ m_adj(m, -todrop);
+ ti->ti_len -= todrop;
+ tiflags &= ~(TH_PUSH|TH_FIN);
+ }
+
+ /*
+ * If last ACK falls within this segment's sequence numbers,
+ * record its timestamp.
+ * NOTE that the test is modified according to the latest
+ * proposal of the tcplw@cray.com list (Braden 1993/04/26).
+ */
+ if ((to.to_flag & TOF_TS) != 0 &&
+ SEQ_LEQ(ti->ti_seq, tp->last_ack_sent)) {
+ tp->ts_recent_age = tcp_now;
+ tp->ts_recent = to.to_tsval;
+ }
+
+ /*
+ * If the RST bit is set examine the state:
+ * SYN_RECEIVED STATE:
+ * If passive open, return to LISTEN state.
+ * If active open, inform user that connection was refused.
+ * ESTABLISHED, FIN_WAIT_1, FIN_WAIT2, CLOSE_WAIT STATES:
+ * Inform user that connection was reset, and close tcb.
+ * CLOSING, LAST_ACK, TIME_WAIT STATES
+ * Close the tcb.
+ */
+ if (tiflags&TH_RST) switch (tp->t_state) {
+
+ case TCPS_SYN_RECEIVED:
+ so->so_error = ECONNREFUSED;
+ goto close;
+
+ case TCPS_ESTABLISHED:
+ case TCPS_FIN_WAIT_1:
+ case TCPS_FIN_WAIT_2:
+ case TCPS_CLOSE_WAIT:
+ so->so_error = ECONNRESET;
+ close:
+ tp->t_state = TCPS_CLOSED;
+ tcpstat.tcps_drops++;
+ tp = tcp_close(tp);
+ goto drop;
+
+ case TCPS_CLOSING:
+ case TCPS_LAST_ACK:
+ case TCPS_TIME_WAIT:
+ tp = tcp_close(tp);
+ goto drop;
+ }
+
+ /*
+ * If a SYN is in the window, then this is an
+ * error and we send an RST and drop the connection.
+ */
+ if (tiflags & TH_SYN) {
+ tp = tcp_drop(tp, ECONNRESET);
+ goto dropwithreset;
+ }
+
+ /*
+ * If the ACK bit is off: if in SYN-RECEIVED state or SENDSYN
+ * flag is on (half-synchronized state), then queue data for
+ * later processing; else drop segment and return.
+ */
+ if ((tiflags & TH_ACK) == 0) {
+ if (tp->t_state == TCPS_SYN_RECEIVED ||
+ (tp->t_flags & TF_NEEDSYN))
+ goto step6;
+ else
+ goto drop;
+ }
+
+ /*
+ * Ack processing.
+ */
+ switch (tp->t_state) {
+
+ /*
+ * In SYN_RECEIVED state, the ack ACKs our SYN, so enter
+ * ESTABLISHED state and continue processing.
+ * The ACK was checked above.
+ */
+ case TCPS_SYN_RECEIVED:
+
+ tcpstat.tcps_connects++;
+ soisconnected(so);
+ /* Do window scaling? */
+ if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==
+ (TF_RCVD_SCALE|TF_REQ_SCALE)) {
+ tp->snd_scale = tp->requested_s_scale;
+ tp->rcv_scale = tp->request_r_scale;
+ }
+ /*
+ * Upon successful completion of 3-way handshake,
+ * update cache.CC if it was undefined, pass any queued
+ * data to the user, and advance state appropriately.
+ */
+ if ((taop = tcp_gettaocache(inp)) != NULL &&
+ taop->tao_cc == 0)
+ taop->tao_cc = tp->cc_recv;
+
+ /*
+ * Make transitions:
+ * SYN-RECEIVED -> ESTABLISHED
+ * SYN-RECEIVED* -> FIN-WAIT-1
+ */
+ if (tp->t_flags & TF_NEEDFIN) {
+ tp->t_state = TCPS_FIN_WAIT_1;
+ tp->t_flags &= ~TF_NEEDFIN;
+ } else {
+ tp->t_state = TCPS_ESTABLISHED;
+ tp->t_timer[TCPT_KEEP] = tcp_keepidle;
+ }
+ /*
+ * If segment contains data or ACK, will call tcp_reass()
+ * later; if not, do so now to pass queued data to user.
+ */
+ if (ti->ti_len == 0 && (tiflags & TH_FIN) == 0)
+ (void) tcp_reass(tp, (struct tcpiphdr *)0,
+ (struct mbuf *)0);
+ tp->snd_wl1 = ti->ti_seq - 1;
+ /* fall into ... */
+
+ /*
+ * In ESTABLISHED state: drop duplicate ACKs; ACK out of range
+ * ACKs. If the ack is in the range
+ * tp->snd_una < ti->ti_ack <= tp->snd_max
+ * then advance tp->snd_una to ti->ti_ack and drop
+ * data from the retransmission queue. If this ACK reflects
+ * more up to date window information we update our window information.
+ */
+ case TCPS_ESTABLISHED:
+ case TCPS_FIN_WAIT_1:
+ case TCPS_FIN_WAIT_2:
+ case TCPS_CLOSE_WAIT:
+ case TCPS_CLOSING:
+ case TCPS_LAST_ACK:
+ case TCPS_TIME_WAIT:
+
+ if (SEQ_LEQ(ti->ti_ack, tp->snd_una)) {
+ if (ti->ti_len == 0 && tiwin == tp->snd_wnd) {
+ tcpstat.tcps_rcvdupack++;
+ /*
+ * If we have outstanding data (other than
+ * a window probe), this is a completely
+ * duplicate ack (ie, window info didn't
+ * change), the ack is the biggest we've
+ * seen and we've seen exactly our rexmt
+ * threshhold of them, assume a packet
+ * has been dropped and retransmit it.
+ * Kludge snd_nxt & the congestion
+ * window so we send only this one
+ * packet.
+ *
+ * We know we're losing at the current
+ * window size so do congestion avoidance
+ * (set ssthresh to half the current window
+ * and pull our congestion window back to
+ * the new ssthresh).
+ *
+ * Dup acks mean that packets have left the
+ * network (they're now cached at the receiver)
+ * so bump cwnd by the amount in the receiver
+ * to keep a constant cwnd packets in the
+ * network.
+ */
+ if (tp->t_timer[TCPT_REXMT] == 0 ||
+ ti->ti_ack != tp->snd_una)
+ tp->t_dupacks = 0;
+ else if (++tp->t_dupacks == tcprexmtthresh) {
+ tcp_seq onxt = tp->snd_nxt;
+ u_int win =
+ min(tp->snd_wnd, tp->snd_cwnd) / 2 /
+ tp->t_maxseg;
+
+ if (win < 2)
+ win = 2;
+ tp->snd_ssthresh = win * tp->t_maxseg;
+ tp->t_timer[TCPT_REXMT] = 0;
+ tp->t_rtt = 0;
+ tp->snd_nxt = ti->ti_ack;
+ tp->snd_cwnd = tp->t_maxseg;
+ (void) tcp_output(tp);
+ tp->snd_cwnd = tp->snd_ssthresh +
+ tp->t_maxseg * tp->t_dupacks;
+ if (SEQ_GT(onxt, tp->snd_nxt))
+ tp->snd_nxt = onxt;
+ goto drop;
+ } else if (tp->t_dupacks > tcprexmtthresh) {
+ tp->snd_cwnd += tp->t_maxseg;
+ (void) tcp_output(tp);
+ goto drop;
+ }
+ } else
+ tp->t_dupacks = 0;
+ break;
+ }
+ /*
+ * If the congestion window was inflated to account
+ * for the other side's cached packets, retract it.
+ */
+ if (tp->t_dupacks >= tcprexmtthresh &&
+ tp->snd_cwnd > tp->snd_ssthresh)
+ tp->snd_cwnd = tp->snd_ssthresh;
+ tp->t_dupacks = 0;
+ if (SEQ_GT(ti->ti_ack, tp->snd_max)) {
+ tcpstat.tcps_rcvacktoomuch++;
+ goto dropafterack;
+ }
+ /*
+ * If we reach this point, ACK is not a duplicate,
+ * i.e., it ACKs something we sent.
+ */
+ if (tp->t_flags & TF_NEEDSYN) {
+ /*
+ * T/TCP: Connection was half-synchronized, and our
+ * SYN has been ACK'd (so connection is now fully
+ * synchronized). Go to non-starred state,
+ * increment snd_una for ACK of SYN, and check if
+ * we can do window scaling.
+ */
+ tp->t_flags &= ~TF_NEEDSYN;
+ tp->snd_una++;
+ /* Do window scaling? */
+ if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==
+ (TF_RCVD_SCALE|TF_REQ_SCALE)) {
+ tp->snd_scale = tp->requested_s_scale;
+ tp->rcv_scale = tp->request_r_scale;
+ }
+ }
+
+process_ACK:
+ acked = ti->ti_ack - tp->snd_una;
+ tcpstat.tcps_rcvackpack++;
+ tcpstat.tcps_rcvackbyte += acked;
+
+ /*
+ * If we have a timestamp reply, update smoothed
+ * round trip time. If no timestamp is present but
+ * transmit timer is running and timed sequence
+ * number was acked, update smoothed round trip time.
+ * Since we now have an rtt measurement, cancel the
+ * timer backoff (cf., Phil Karn's retransmit alg.).
+ * Recompute the initial retransmit timer.
+ */
+ if (to.to_flag & TOF_TS)
+ tcp_xmit_timer(tp, tcp_now - to.to_tsecr + 1);
+ else if (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq))
+ tcp_xmit_timer(tp,tp->t_rtt);
+
+ /*
+ * If all outstanding data is acked, stop retransmit
+ * timer and remember to restart (more output or persist).
+ * If there is more data to be acked, restart retransmit
+ * timer, using current (possibly backed-off) value.
+ */
+ if (ti->ti_ack == tp->snd_max) {
+ tp->t_timer[TCPT_REXMT] = 0;
+ needoutput = 1;
+ } else if (tp->t_timer[TCPT_PERSIST] == 0)
+ tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;
+
+ /*
+ * If no data (only SYN) was ACK'd,
+ * skip rest of ACK processing.
+ */
+ if (acked == 0)
+ goto step6;
+
+ /*
+ * When new data is acked, open the congestion window.
+ * If the window gives us less than ssthresh packets
+ * in flight, open exponentially (maxseg per packet).
+ * Otherwise open linearly: maxseg per window
+ * (maxseg^2 / cwnd per packet).
+ */
+ {
+ register u_int cw = tp->snd_cwnd;
+ register u_int incr = tp->t_maxseg;
+
+ if (cw > tp->snd_ssthresh)
+ incr = incr * incr / cw;
+ tp->snd_cwnd = min(cw + incr, TCP_MAXWIN<<tp->snd_scale);
+ }
+ if (acked > so->so_snd.sb_cc) {
+ tp->snd_wnd -= so->so_snd.sb_cc;
+ sbdrop(&so->so_snd, (int)so->so_snd.sb_cc);
+ ourfinisacked = 1;
+ } else {
+ sbdrop(&so->so_snd, acked);
+ tp->snd_wnd -= acked;
+ ourfinisacked = 0;
+ }
+ if (so->so_snd.sb_flags & SB_NOTIFY)
+ sowwakeup(so);
+ tp->snd_una = ti->ti_ack;
+ if (SEQ_LT(tp->snd_nxt, tp->snd_una))
+ tp->snd_nxt = tp->snd_una;
+
+ switch (tp->t_state) {
+
+ /*
+ * In FIN_WAIT_1 STATE in addition to the processing
+ * for the ESTABLISHED state if our FIN is now acknowledged
+ * then enter FIN_WAIT_2.
+ */
+ case TCPS_FIN_WAIT_1:
+ if (ourfinisacked) {
+ /*
+ * If we can't receive any more
+ * data, then closing user can proceed.
+ * Starting the timer is contrary to the
+ * specification, but if we don't get a FIN
+ * we'll hang forever.
+ */
+ if (so->so_state & SS_CANTRCVMORE) {
+ soisdisconnected(so);
+ tp->t_timer[TCPT_2MSL] = tcp_maxidle;
+ }
+ tp->t_state = TCPS_FIN_WAIT_2;
+ }
+ break;
+
+ /*
+ * In CLOSING STATE in addition to the processing for
+ * the ESTABLISHED state if the ACK acknowledges our FIN
+ * then enter the TIME-WAIT state, otherwise ignore
+ * the segment.
+ */
+ case TCPS_CLOSING:
+ if (ourfinisacked) {
+ tp->t_state = TCPS_TIME_WAIT;
+ tcp_canceltimers(tp);
+ /* Shorten TIME_WAIT [RFC-1644, p.28] */
+ if (tp->cc_recv != 0 &&
+ tp->t_duration < TCPTV_MSL)
+ tp->t_timer[TCPT_2MSL] =
+ tp->t_rxtcur * TCPTV_TWTRUNC;
+ else
+ tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
+ soisdisconnected(so);
+ }
+ break;
+
+ /*
+ * In LAST_ACK, we may still be waiting for data to drain
+ * and/or to be acked, as well as for the ack of our FIN.
+ * If our FIN is now acknowledged, delete the TCB,
+ * enter the closed state and return.
+ */
+ case TCPS_LAST_ACK:
+ if (ourfinisacked) {
+ tp = tcp_close(tp);
+ goto drop;
+ }
+ break;
+
+ /*
+ * In TIME_WAIT state the only thing that should arrive
+ * is a retransmission of the remote FIN. Acknowledge
+ * it and restart the finack timer.
+ */
+ case TCPS_TIME_WAIT:
+ tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
+ goto dropafterack;
+ }
+ }
+
+step6:
+ /*
+ * Update window information.
+ * Don't look at window if no ACK: TAC's send garbage on first SYN.
+ */
+ if ((tiflags & TH_ACK) &&
+ (SEQ_LT(tp->snd_wl1, ti->ti_seq) ||
+ (tp->snd_wl1 == ti->ti_seq && (SEQ_LT(tp->snd_wl2, ti->ti_ack) ||
+ (tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd))))) {
+ /* keep track of pure window updates */
+ if (ti->ti_len == 0 &&
+ tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd)
+ tcpstat.tcps_rcvwinupd++;
+ tp->snd_wnd = tiwin;
+ tp->snd_wl1 = ti->ti_seq;
+ tp->snd_wl2 = ti->ti_ack;
+ if (tp->snd_wnd > tp->max_sndwnd)
+ tp->max_sndwnd = tp->snd_wnd;
+ needoutput = 1;
+ }
+
+ /*
+ * Process segments with URG.
+ */
+ if ((tiflags & TH_URG) && ti->ti_urp &&
+ TCPS_HAVERCVDFIN(tp->t_state) == 0) {
+ /*
+ * This is a kludge, but if we receive and accept
+ * random urgent pointers, we'll crash in
+ * soreceive. It's hard to imagine someone
+ * actually wanting to send this much urgent data.
+ */
+ if (ti->ti_urp + so->so_rcv.sb_cc > sb_max) {
+ ti->ti_urp = 0; /* XXX */
+ tiflags &= ~TH_URG; /* XXX */
+ goto dodata; /* XXX */
+ }
+ /*
+ * If this segment advances the known urgent pointer,
+ * then mark the data stream. This should not happen
+ * in CLOSE_WAIT, CLOSING, LAST_ACK or TIME_WAIT STATES since
+ * a FIN has been received from the remote side.
+ * In these states we ignore the URG.
+ *
+ * According to RFC961 (Assigned Protocols),
+ * the urgent pointer points to the last octet
+ * of urgent data. We continue, however,
+ * to consider it to indicate the first octet
+ * of data past the urgent section as the original
+ * spec states (in one of two places).
+ */
+ if (SEQ_GT(ti->ti_seq+ti->ti_urp, tp->rcv_up)) {
+ tp->rcv_up = ti->ti_seq + ti->ti_urp;
+ so->so_oobmark = so->so_rcv.sb_cc +
+ (tp->rcv_up - tp->rcv_nxt) - 1;
+ if (so->so_oobmark == 0)
+ so->so_state |= SS_RCVATMARK;
+ sohasoutofband(so);
+ tp->t_oobflags &= ~(TCPOOB_HAVEDATA | TCPOOB_HADDATA);
+ }
+ /*
+ * Remove out of band data so doesn't get presented to user.
+ * This can happen independent of advancing the URG pointer,
+ * but if two URG's are pending at once, some out-of-band
+ * data may creep in... ick.
+ */
+ if (ti->ti_urp <= (u_long)ti->ti_len
+#ifdef SO_OOBINLINE
+ && (so->so_options & SO_OOBINLINE) == 0
+#endif
+ )
+ tcp_pulloutofband(so, ti, m);
+ } else
+ /*
+ * If no out of band data is expected,
+ * pull receive urgent pointer along
+ * with the receive window.
+ */
+ if (SEQ_GT(tp->rcv_nxt, tp->rcv_up))
+ tp->rcv_up = tp->rcv_nxt;
+dodata: /* XXX */
+
+ /*
+ * Process the segment text, merging it into the TCP sequencing queue,
+ * and arranging for acknowledgment of receipt if necessary.
+ * This process logically involves adjusting tp->rcv_wnd as data
+ * is presented to the user (this happens in tcp_usrreq.c,
+ * case PRU_RCVD). If a FIN has already been received on this
+ * connection then we just ignore the text.
+ */
+ if ((ti->ti_len || (tiflags&TH_FIN)) &&
+ TCPS_HAVERCVDFIN(tp->t_state) == 0) {
+ TCP_REASS(tp, ti, m, so, tiflags);
+ /*
+ * Note the amount of data that peer has sent into
+ * our window, in order to estimate the sender's
+ * buffer size.
+ */
+ len = so->so_rcv.sb_hiwat - (tp->rcv_adv - tp->rcv_nxt);
+ } else {
+ m_freem(m);
+ tiflags &= ~TH_FIN;
+ }
+
+ /*
+ * If FIN is received ACK the FIN and let the user know
+ * that the connection is closing.
+ */
+ if (tiflags & TH_FIN) {
+ if (TCPS_HAVERCVDFIN(tp->t_state) == 0) {
+ socantrcvmore(so);
+ /*
+ * If connection is half-synchronized
+ * (ie NEEDSYN flag on) then delay ACK,
+ * so it may be piggybacked when SYN is sent.
+ * Otherwise, since we received a FIN then no
+ * more input can be expected, send ACK now.
+ */
+ if (tp->t_flags & TF_NEEDSYN)
+ tp->t_flags |= TF_DELACK;
+ else
+ tp->t_flags |= TF_ACKNOW;
+ tp->rcv_nxt++;
+ }
+ switch (tp->t_state) {
+
+ /*
+ * In SYN_RECEIVED and ESTABLISHED STATES
+ * enter the CLOSE_WAIT state.
+ */
+ case TCPS_SYN_RECEIVED:
+ case TCPS_ESTABLISHED:
+ tp->t_state = TCPS_CLOSE_WAIT;
+ break;
+
+ /*
+ * If still in FIN_WAIT_1 STATE FIN has not been acked so
+ * enter the CLOSING state.
+ */
+ case TCPS_FIN_WAIT_1:
+ tp->t_state = TCPS_CLOSING;
+ break;
+
+ /*
+ * In FIN_WAIT_2 state enter the TIME_WAIT state,
+ * starting the time-wait timer, turning off the other
+ * standard timers.
+ */
+ case TCPS_FIN_WAIT_2:
+ tp->t_state = TCPS_TIME_WAIT;
+ tcp_canceltimers(tp);
+ /* Shorten TIME_WAIT [RFC-1644, p.28] */
+ if (tp->cc_recv != 0 &&
+ tp->t_duration < TCPTV_MSL) {
+ tp->t_timer[TCPT_2MSL] =
+ tp->t_rxtcur * TCPTV_TWTRUNC;
+ /* For transaction client, force ACK now. */
+ tp->t_flags |= TF_ACKNOW;
+ }
+ else
+ tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
+ soisdisconnected(so);
+ break;
+
+ /*
+ * In TIME_WAIT state restart the 2 MSL time_wait timer.
+ */
+ case TCPS_TIME_WAIT:
+ tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
+ break;
+ }
+ }
+#ifdef TCPDEBUG
+ if (so->so_options & SO_DEBUG)
+ tcp_trace(TA_INPUT, ostate, tp, &tcp_saveti, 0);
+#endif
+
+ /*
+ * Return any desired output.
+ */
+ if (needoutput || (tp->t_flags & TF_ACKNOW))
+ (void) tcp_output(tp);
+ return;
+
+dropafterack:
+ /*
+ * Generate an ACK dropping incoming segment if it occupies
+ * sequence space, where the ACK reflects our state.
+ */
+ if (tiflags & TH_RST)
+ goto drop;
+#ifdef TCPDEBUG
+ if (so->so_options & SO_DEBUG)
+ tcp_trace(TA_DROP, ostate, tp, &tcp_saveti, 0);
+#endif
+ m_freem(m);
+ tp->t_flags |= TF_ACKNOW;
+ (void) tcp_output(tp);
+ return;
+
+dropwithreset:
+ /*
+ * Generate a RST, dropping incoming segment.
+ * Make ACK acceptable to originator of segment.
+ * Don't bother to respond if destination was broadcast/multicast.
+ */
+ if ((tiflags & TH_RST) || m->m_flags & (M_BCAST|M_MCAST) ||
+ IN_MULTICAST(ntohl(ti->ti_dst.s_addr)))
+ goto drop;
+#ifdef TCPDEBUG
+ if (tp == 0 || (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
+ tcp_trace(TA_DROP, ostate, tp, &tcp_saveti, 0);
+#endif
+ if (tiflags & TH_ACK)
+ tcp_respond(tp, ti, m, (tcp_seq)0, ti->ti_ack, TH_RST);
+ else {
+ if (tiflags & TH_SYN)
+ ti->ti_len++;
+ tcp_respond(tp, ti, m, ti->ti_seq+ti->ti_len, (tcp_seq)0,
+ TH_RST|TH_ACK);
+ }
+ /* destroy temporarily created socket */
+ if (dropsocket)
+ (void) soabort(so);
+ return;
+
+drop:
+ /*
+ * Drop space held by incoming segment and return.
+ */
+#ifdef TCPDEBUG
+ if (tp == 0 || (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
+ tcp_trace(TA_DROP, ostate, tp, &tcp_saveti, 0);
+#endif
+ m_freem(m);
+ /* destroy temporarily created socket */
+ if (dropsocket)
+ (void) soabort(so);
+ return;
+#ifndef TUBA_INCLUDE
+}
+
+static void
+tcp_dooptions(tp, cp, cnt, ti, to)
+ struct tcpcb *tp;
+ u_char *cp;
+ int cnt;
+ struct tcpiphdr *ti;
+ struct tcpopt *to;
+{
+ u_short mss = 0;
+ int opt, optlen;
+
+ for (; cnt > 0; cnt -= optlen, cp += optlen) {
+ opt = cp[0];
+ if (opt == TCPOPT_EOL)
+ break;
+ if (opt == TCPOPT_NOP)
+ optlen = 1;
+ else {
+ optlen = cp[1];
+ if (optlen <= 0)
+ break;
+ }
+ switch (opt) {
+
+ default:
+ continue;
+
+ case TCPOPT_MAXSEG:
+ if (optlen != TCPOLEN_MAXSEG)
+ continue;
+ if (!(ti->ti_flags & TH_SYN))
+ continue;
+ bcopy((char *) cp + 2, (char *) &mss, sizeof(mss));
+ NTOHS(mss);
+ break;
+
+ case TCPOPT_WINDOW:
+ if (optlen != TCPOLEN_WINDOW)
+ continue;
+ if (!(ti->ti_flags & TH_SYN))
+ continue;
+ tp->t_flags |= TF_RCVD_SCALE;
+ tp->requested_s_scale = min(cp[2], TCP_MAX_WINSHIFT);
+ break;
+
+ case TCPOPT_TIMESTAMP:
+ if (optlen != TCPOLEN_TIMESTAMP)
+ continue;
+ to->to_flag |= TOF_TS;
+ bcopy((char *)cp + 2,
+ (char *)&to->to_tsval, sizeof(to->to_tsval));
+ NTOHL(to->to_tsval);
+ bcopy((char *)cp + 6,
+ (char *)&to->to_tsecr, sizeof(to->to_tsecr));
+ NTOHL(to->to_tsecr);
+
+ /*
+ * A timestamp received in a SYN makes
+ * it ok to send timestamp requests and replies.
+ */
+ if (ti->ti_flags & TH_SYN) {
+ tp->t_flags |= TF_RCVD_TSTMP;
+ tp->ts_recent = to->to_tsval;
+ tp->ts_recent_age = tcp_now;
+ }
+ break;
+ case TCPOPT_CC:
+ if (optlen != TCPOLEN_CC)
+ continue;
+ to->to_flag |= TOF_CC;
+ bcopy((char *)cp + 2,
+ (char *)&to->to_cc, sizeof(to->to_cc));
+ NTOHL(to->to_cc);
+ /*
+ * A CC or CC.new option received in a SYN makes
+ * it ok to send CC in subsequent segments.
+ */
+ if (ti->ti_flags & TH_SYN)
+ tp->t_flags |= TF_RCVD_CC;
+ break;
+ case TCPOPT_CCNEW:
+ if (optlen != TCPOLEN_CC)
+ continue;
+ if (!(ti->ti_flags & TH_SYN))
+ continue;
+ to->to_flag |= TOF_CCNEW;
+ bcopy((char *)cp + 2,
+ (char *)&to->to_cc, sizeof(to->to_cc));
+ NTOHL(to->to_cc);
+ /*
+ * A CC or CC.new option received in a SYN makes
+ * it ok to send CC in subsequent segments.
+ */
+ tp->t_flags |= TF_RCVD_CC;
+ break;
+ case TCPOPT_CCECHO:
+ if (optlen != TCPOLEN_CC)
+ continue;
+ if (!(ti->ti_flags & TH_SYN))
+ continue;
+ to->to_flag |= TOF_CCECHO;
+ bcopy((char *)cp + 2,
+ (char *)&to->to_ccecho, sizeof(to->to_ccecho));
+ NTOHL(to->to_ccecho);
+ break;
+ }
+ }
+ if (ti->ti_flags & TH_SYN)
+ tcp_mss(tp, mss); /* sets t_maxseg */
+}
+
+/*
+ * Pull out of band byte out of a segment so
+ * it doesn't appear in the user's data queue.
+ * It is still reflected in the segment length for
+ * sequencing purposes.
+ */
+static void
+tcp_pulloutofband(so, ti, m)
+ struct socket *so;
+ struct tcpiphdr *ti;
+ register struct mbuf *m;
+{
+ int cnt = ti->ti_urp - 1;
+
+ while (cnt >= 0) {
+ if (m->m_len > cnt) {
+ char *cp = mtod(m, caddr_t) + cnt;
+ struct tcpcb *tp = sototcpcb(so);
+
+ tp->t_iobc = *cp;
+ tp->t_oobflags |= TCPOOB_HAVEDATA;
+ bcopy(cp+1, cp, (unsigned)(m->m_len - cnt - 1));
+ m->m_len--;
+ return;
+ }
+ cnt -= m->m_len;
+ m = m->m_next;
+ if (m == 0)
+ break;
+ }
+ panic("tcp_pulloutofband");
+}
+
+/*
+ * Collect new round-trip time estimate
+ * and update averages and current timeout.
+ */
+static void
+tcp_xmit_timer(tp, rtt)
+ register struct tcpcb *tp;
+ short rtt;
+{
+ register int delta;
+
+ tcpstat.tcps_rttupdated++;
+ tp->t_rttupdated++;
+ if (tp->t_srtt != 0) {
+ /*
+ * srtt is stored as fixed point with 5 bits after the
+ * binary point (i.e., scaled by 8). The following magic
+ * is equivalent to the smoothing algorithm in rfc793 with
+ * an alpha of .875 (srtt = rtt/8 + srtt*7/8 in fixed
+ * point). Adjust rtt to origin 0.
+ */
+ delta = ((rtt - 1) << TCP_DELTA_SHIFT)
+ - (tp->t_srtt >> (TCP_RTT_SHIFT - TCP_DELTA_SHIFT));
+
+ if ((tp->t_srtt += delta) <= 0)
+ tp->t_srtt = 1;
+
+ /*
+ * We accumulate a smoothed rtt variance (actually, a
+ * smoothed mean difference), then set the retransmit
+ * timer to smoothed rtt + 4 times the smoothed variance.
+ * rttvar is stored as fixed point with 4 bits after the
+ * binary point (scaled by 16). The following is
+ * equivalent to rfc793 smoothing with an alpha of .75
+ * (rttvar = rttvar*3/4 + |delta| / 4). This replaces
+ * rfc793's wired-in beta.
+ */
+ if (delta < 0)
+ delta = -delta;
+ delta -= tp->t_rttvar >> (TCP_RTTVAR_SHIFT - TCP_DELTA_SHIFT);
+ if ((tp->t_rttvar += delta) <= 0)
+ tp->t_rttvar = 1;
+ } else {
+ /*
+ * No rtt measurement yet - use the unsmoothed rtt.
+ * Set the variance to half the rtt (so our first
+ * retransmit happens at 3*rtt).
+ */
+ tp->t_srtt = rtt << TCP_RTT_SHIFT;
+ tp->t_rttvar = rtt << (TCP_RTTVAR_SHIFT - 1);
+ }
+ tp->t_rtt = 0;
+ tp->t_rxtshift = 0;
+
+ /*
+ * the retransmit should happen at rtt + 4 * rttvar.
+ * Because of the way we do the smoothing, srtt and rttvar
+ * will each average +1/2 tick of bias. When we compute
+ * the retransmit timer, we want 1/2 tick of rounding and
+ * 1 extra tick because of +-1/2 tick uncertainty in the
+ * firing of the timer. The bias will give us exactly the
+ * 1.5 tick we need. But, because the bias is
+ * statistical, we have to test that we don't drop below
+ * the minimum feasible timer (which is 2 ticks).
+ */
+ TCPT_RANGESET(tp->t_rxtcur, TCP_REXMTVAL(tp),
+ max(tp->t_rttmin, rtt + 2), TCPTV_REXMTMAX);
+
+ /*
+ * We received an ack for a packet that wasn't retransmitted;
+ * it is probably safe to discard any error indications we've
+ * received recently. This isn't quite right, but close enough
+ * for now (a route might have failed after we sent a segment,
+ * and the return path might not be symmetrical).
+ */
+ tp->t_softerror = 0;
+}
+
+/*
+ * Determine a reasonable value for maxseg size.
+ * If the route is known, check route for mtu.
+ * If none, use an mss that can be handled on the outgoing
+ * interface without forcing IP to fragment; if bigger than
+ * an mbuf cluster (MCLBYTES), round down to nearest multiple of MCLBYTES
+ * to utilize large mbufs. If no route is found, route has no mtu,
+ * or the destination isn't local, use a default, hopefully conservative
+ * size (usually 512 or the default IP max size, but no more than the mtu
+ * of the interface), as we can't discover anything about intervening
+ * gateways or networks. We also initialize the congestion/slow start
+ * window to be a single segment if the destination isn't local.
+ * While looking at the routing entry, we also initialize other path-dependent
+ * parameters from pre-set or cached values in the routing entry.
+ *
+ * Also take into account the space needed for options that we
+ * send regularly. Make maxseg shorter by that amount to assure
+ * that we can send maxseg amount of data even when the options
+ * are present. Store the upper limit of the length of options plus
+ * data in maxopd.
+ *
+ * NOTE that this routine is only called when we process an incoming
+ * segment, for outgoing segments only tcp_mssopt is called.
+ *
+ * In case of T/TCP, we call this routine during implicit connection
+ * setup as well (offer = -1), to initialize maxseg from the cached
+ * MSS of our peer.
+ */
+void
+tcp_mss(tp, offer)
+ struct tcpcb *tp;
+ int offer;
+{
+ register struct rtentry *rt;
+ struct ifnet *ifp;
+ register int rtt, mss;
+ u_long bufsize;
+ struct inpcb *inp;
+ struct socket *so;
+ struct rmxp_tao *taop;
+ int origoffer = offer;
+
+ inp = tp->t_inpcb;
+ if ((rt = tcp_rtlookup(inp)) == NULL) {
+ tp->t_maxopd = tp->t_maxseg = tcp_mssdflt;
+ return;
+ }
+ ifp = rt->rt_ifp;
+ so = inp->inp_socket;
+
+ taop = rmx_taop(rt->rt_rmx);
+ /*
+ * Offer == -1 means that we didn't receive SYN yet,
+ * use cached value in that case;
+ */
+ if (offer == -1)
+ offer = taop->tao_mssopt;
+ /*
+ * Offer == 0 means that there was no MSS on the SYN segment,
+ * in this case we use tcp_mssdflt.
+ */
+ if (offer == 0)
+ offer = tcp_mssdflt;
+ else
+ /*
+ * Sanity check: make sure that maxopd will be large
+ * enough to allow some data on segments even is the
+ * all the option space is used (40bytes). Otherwise
+ * funny things may happen in tcp_output.
+ */
+ offer = max(offer, 64);
+ taop->tao_mssopt = offer;
+
+ /*
+ * While we're here, check if there's an initial rtt
+ * or rttvar. Convert from the route-table units
+ * to scaled multiples of the slow timeout timer.
+ */
+ if (tp->t_srtt == 0 && (rtt = rt->rt_rmx.rmx_rtt)) {
+ /*
+ * XXX the lock bit for RTT indicates that the value
+ * is also a minimum value; this is subject to time.
+ */
+ if (rt->rt_rmx.rmx_locks & RTV_RTT)
+ tp->t_rttmin = rtt / (RTM_RTTUNIT / PR_SLOWHZ);
+ tp->t_srtt = rtt / (RTM_RTTUNIT / (PR_SLOWHZ * TCP_RTT_SCALE));
+ tcpstat.tcps_usedrtt++;
+ if (rt->rt_rmx.rmx_rttvar) {
+ tp->t_rttvar = rt->rt_rmx.rmx_rttvar /
+ (RTM_RTTUNIT / (PR_SLOWHZ * TCP_RTTVAR_SCALE));
+ tcpstat.tcps_usedrttvar++;
+ } else {
+ /* default variation is +- 1 rtt */
+ tp->t_rttvar =
+ tp->t_srtt * TCP_RTTVAR_SCALE / TCP_RTT_SCALE;
+ }
+ TCPT_RANGESET(tp->t_rxtcur,
+ ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1,
+ tp->t_rttmin, TCPTV_REXMTMAX);
+ }
+ /*
+ * if there's an mtu associated with the route, use it
+ */
+ if (rt->rt_rmx.rmx_mtu)
+ mss = rt->rt_rmx.rmx_mtu - sizeof(struct tcpiphdr);
+ else
+ {
+ mss = ifp->if_mtu - sizeof(struct tcpiphdr);
+ if (!in_localaddr(inp->inp_faddr))
+ mss = min(mss, tcp_mssdflt);
+ }
+ mss = min(mss, offer);
+ /*
+ * maxopd stores the maximum length of data AND options
+ * in a segment; maxseg is the amount of data in a normal
+ * segment. We need to store this value (maxopd) apart
+ * from maxseg, because now every segment carries options
+ * and thus we normally have somewhat less data in segments.
+ */
+ tp->t_maxopd = mss;
+
+ /*
+ * In case of T/TCP, origoffer==-1 indicates, that no segments
+ * were received yet. In this case we just guess, otherwise
+ * we do the same as before T/TCP.
+ */
+ if ((tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP &&
+ (origoffer == -1 ||
+ (tp->t_flags & TF_RCVD_TSTMP) == TF_RCVD_TSTMP))
+ mss -= TCPOLEN_TSTAMP_APPA;
+ if ((tp->t_flags & (TF_REQ_CC|TF_NOOPT)) == TF_REQ_CC &&
+ (origoffer == -1 ||
+ (tp->t_flags & TF_RCVD_CC) == TF_RCVD_CC))
+ mss -= TCPOLEN_CC_APPA;
+
+#if (MCLBYTES & (MCLBYTES - 1)) == 0
+ if (mss > MCLBYTES)
+ mss &= ~(MCLBYTES-1);
+#else
+ if (mss > MCLBYTES)
+ mss = mss / MCLBYTES * MCLBYTES;
+#endif
+ /*
+ * If there's a pipesize, change the socket buffer
+ * to that size. Make the socket buffers an integral
+ * number of mss units; if the mss is larger than
+ * the socket buffer, decrease the mss.
+ */
+#ifdef RTV_SPIPE
+ if ((bufsize = rt->rt_rmx.rmx_sendpipe) == 0)
+#endif
+ bufsize = so->so_snd.sb_hiwat;
+ if (bufsize < mss)
+ mss = bufsize;
+ else {
+ bufsize = roundup(bufsize, mss);
+ if (bufsize > sb_max)
+ bufsize = sb_max;
+ (void)sbreserve(&so->so_snd, bufsize);
+ }
+ tp->t_maxseg = mss;
+
+#ifdef RTV_RPIPE
+ if ((bufsize = rt->rt_rmx.rmx_recvpipe) == 0)
+#endif
+ bufsize = so->so_rcv.sb_hiwat;
+ if (bufsize > mss) {
+ bufsize = roundup(bufsize, mss);
+ if (bufsize > sb_max)
+ bufsize = sb_max;
+ (void)sbreserve(&so->so_rcv, bufsize);
+ }
+ /*
+ * Don't force slow-start on local network.
+ */
+ if (!in_localaddr(inp->inp_faddr))
+ tp->snd_cwnd = mss;
+
+ if (rt->rt_rmx.rmx_ssthresh) {
+ /*
+ * There's some sort of gateway or interface
+ * buffer limit on the path. Use this to set
+ * the slow start threshhold, but set the
+ * threshold to no less than 2*mss.
+ */
+ tp->snd_ssthresh = max(2 * mss, rt->rt_rmx.rmx_ssthresh);
+ tcpstat.tcps_usedssthresh++;
+ }
+}
+
+/*
+ * Determine the MSS option to send on an outgoing SYN.
+ */
+int
+tcp_mssopt(tp)
+ struct tcpcb *tp;
+{
+ struct rtentry *rt;
+
+ rt = tcp_rtlookup(tp->t_inpcb);
+ if (rt == NULL)
+ return tcp_mssdflt;
+
+ return rt->rt_ifp->if_mtu - sizeof(struct tcpiphdr);
+}
+#endif /* TUBA_INCLUDE */
diff --git a/cpukit/libnetworking/netinet/tcp_output.c b/cpukit/libnetworking/netinet/tcp_output.c
new file mode 100644
index 0000000000..cbb5218dce
--- /dev/null
+++ b/cpukit/libnetworking/netinet/tcp_output.c
@@ -0,0 +1,755 @@
+/*
+ * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)tcp_output.c 8.4 (Berkeley) 5/24/95
+ * $Id$
+ */
+
+#include "opt_tcpdebug.h"
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/errno.h>
+
+#include <net/route.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/in_pcb.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#define TCPOUTFLAGS
+#include <netinet/tcp_fsm.h>
+#include <netinet/tcp_seq.h>
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_var.h>
+#include <netinet/tcpip.h>
+#ifdef TCPDEBUG
+#include <netinet/tcp_debug.h>
+#endif
+
+#ifdef notyet
+extern struct mbuf *m_copypack();
+#endif
+
+
+/*
+ * Tcp output routine: figure out what should be sent and send it.
+ */
+int
+tcp_output(tp)
+ register struct tcpcb *tp;
+{
+ register struct socket *so = tp->t_inpcb->inp_socket;
+ register long len, win;
+ int off, flags, error;
+ register struct mbuf *m;
+ register struct tcpiphdr *ti;
+ u_char opt[TCP_MAXOLEN];
+ unsigned optlen, hdrlen;
+ int idle, sendalot;
+ struct rmxp_tao *taop;
+ struct rmxp_tao tao_noncached;
+
+ /*
+ * Determine length of data that should be transmitted,
+ * and flags that will be used.
+ * If there is some data or critical controls (SYN, RST)
+ * to send, then transmit; otherwise, investigate further.
+ */
+ idle = (tp->snd_max == tp->snd_una);
+ if (idle && tp->t_idle >= tp->t_rxtcur)
+ /*
+ * We have been idle for "a while" and no acks are
+ * expected to clock out any data we send --
+ * slow start to get ack "clock" running again.
+ */
+ tp->snd_cwnd = tp->t_maxseg;
+again:
+ sendalot = 0;
+ off = tp->snd_nxt - tp->snd_una;
+ win = min(tp->snd_wnd, tp->snd_cwnd);
+
+ flags = tcp_outflags[tp->t_state];
+ /*
+ * Get standard flags, and add SYN or FIN if requested by 'hidden'
+ * state flags.
+ */
+ if (tp->t_flags & TF_NEEDFIN)
+ flags |= TH_FIN;
+ if (tp->t_flags & TF_NEEDSYN)
+ flags |= TH_SYN;
+
+ /*
+ * If in persist timeout with window of 0, send 1 byte.
+ * Otherwise, if window is small but nonzero
+ * and timer expired, we will send what we can
+ * and go to transmit state.
+ */
+ if (tp->t_force) {
+ if (win == 0) {
+ /*
+ * If we still have some data to send, then
+ * clear the FIN bit. Usually this would
+ * happen below when it realizes that we
+ * aren't sending all the data. However,
+ * if we have exactly 1 byte of unset data,
+ * then it won't clear the FIN bit below,
+ * and if we are in persist state, we wind
+ * up sending the packet without recording
+ * that we sent the FIN bit.
+ *
+ * We can't just blindly clear the FIN bit,
+ * because if we don't have any more data
+ * to send then the probe will be the FIN
+ * itself.
+ */
+ if (off < so->so_snd.sb_cc)
+ flags &= ~TH_FIN;
+ win = 1;
+ } else {
+ tp->t_timer[TCPT_PERSIST] = 0;
+ tp->t_rxtshift = 0;
+ }
+ }
+
+ len = min(so->so_snd.sb_cc, win) - off;
+
+ if ((taop = tcp_gettaocache(tp->t_inpcb)) == NULL) {
+ taop = &tao_noncached;
+ bzero(taop, sizeof(*taop));
+ }
+
+ /*
+ * Lop off SYN bit if it has already been sent. However, if this
+ * is SYN-SENT state and if segment contains data and if we don't
+ * know that foreign host supports TAO, suppress sending segment.
+ */
+ if ((flags & TH_SYN) && SEQ_GT(tp->snd_nxt, tp->snd_una)) {
+ flags &= ~TH_SYN;
+ off--, len++;
+ if (len > 0 && tp->t_state == TCPS_SYN_SENT &&
+ taop->tao_ccsent == 0)
+ return 0;
+ }
+
+ /*
+ * Be careful not to send data and/or FIN on SYN segments
+ * in cases when no CC option will be sent.
+ * This measure is needed to prevent interoperability problems
+ * with not fully conformant TCP implementations.
+ */
+ if ((flags & TH_SYN) &&
+ ((tp->t_flags & TF_NOOPT) || !(tp->t_flags & TF_REQ_CC) ||
+ ((flags & TH_ACK) && !(tp->t_flags & TF_RCVD_CC)))) {
+ len = 0;
+ flags &= ~TH_FIN;
+ }
+
+ if (len < 0) {
+ /*
+ * If FIN has been sent but not acked,
+ * but we haven't been called to retransmit,
+ * len will be -1. Otherwise, window shrank
+ * after we sent into it. If window shrank to 0,
+ * cancel pending retransmit, pull snd_nxt back
+ * to (closed) window, and set the persist timer
+ * if it isn't already going. If the window didn't
+ * close completely, just wait for an ACK.
+ */
+ len = 0;
+ if (win == 0) {
+ tp->t_timer[TCPT_REXMT] = 0;
+ tp->t_rxtshift = 0;
+ tp->snd_nxt = tp->snd_una;
+ if (tp->t_timer[TCPT_PERSIST] == 0)
+ tcp_setpersist(tp);
+ }
+ }
+ if (len > tp->t_maxseg) {
+ len = tp->t_maxseg;
+ sendalot = 1;
+ }
+ if (SEQ_LT(tp->snd_nxt + len, tp->snd_una + so->so_snd.sb_cc))
+ flags &= ~TH_FIN;
+
+ win = sbspace(&so->so_rcv);
+
+ /*
+ * Sender silly window avoidance. If connection is idle
+ * and can send all data, a maximum segment,
+ * at least a maximum default-size segment do it,
+ * or are forced, do it; otherwise don't bother.
+ * If peer's buffer is tiny, then send
+ * when window is at least half open.
+ * If retransmitting (possibly after persist timer forced us
+ * to send into a small window), then must resend.
+ */
+ if (len) {
+ if (len == tp->t_maxseg)
+ goto send;
+ if ((idle || tp->t_flags & TF_NODELAY) &&
+ (tp->t_flags & TF_NOPUSH) == 0 &&
+ len + off >= so->so_snd.sb_cc)
+ goto send;
+ if (tp->t_force)
+ goto send;
+ if (len >= tp->max_sndwnd / 2 && tp->max_sndwnd > 0)
+ goto send;
+ if (SEQ_LT(tp->snd_nxt, tp->snd_max))
+ goto send;
+ }
+
+ /*
+ * Compare available window to amount of window
+ * known to peer (as advertised window less
+ * next expected input). If the difference is at least two
+ * max size segments, or at least 50% of the maximum possible
+ * window, then want to send a window update to peer.
+ */
+ if (win > 0) {
+ /*
+ * "adv" is the amount we can increase the window,
+ * taking into account that we are limited by
+ * TCP_MAXWIN << tp->rcv_scale.
+ */
+ long adv = min(win, (long)TCP_MAXWIN << tp->rcv_scale) -
+ (tp->rcv_adv - tp->rcv_nxt);
+
+ if (adv >= (long) (2 * tp->t_maxseg))
+ goto send;
+ if (2 * adv >= (long) so->so_rcv.sb_hiwat)
+ goto send;
+ }
+
+ /*
+ * Send if we owe peer an ACK.
+ */
+ if (tp->t_flags & TF_ACKNOW)
+ goto send;
+ if ((flags & TH_RST) ||
+ ((flags & TH_SYN) && (tp->t_flags & TF_NEEDSYN) == 0))
+ goto send;
+ if (SEQ_GT(tp->snd_up, tp->snd_una))
+ goto send;
+ /*
+ * If our state indicates that FIN should be sent
+ * and we have not yet done so, or we're retransmitting the FIN,
+ * then we need to send.
+ */
+ if (flags & TH_FIN &&
+ ((tp->t_flags & TF_SENTFIN) == 0 || tp->snd_nxt == tp->snd_una))
+ goto send;
+
+ /*
+ * TCP window updates are not reliable, rather a polling protocol
+ * using ``persist'' packets is used to insure receipt of window
+ * updates. The three ``states'' for the output side are:
+ * idle not doing retransmits or persists
+ * persisting to move a small or zero window
+ * (re)transmitting and thereby not persisting
+ *
+ * tp->t_timer[TCPT_PERSIST]
+ * is set when we are in persist state.
+ * tp->t_force
+ * is set when we are called to send a persist packet.
+ * tp->t_timer[TCPT_REXMT]
+ * is set when we are retransmitting
+ * The output side is idle when both timers are zero.
+ *
+ * If send window is too small, there is data to transmit, and no
+ * retransmit or persist is pending, then go to persist state.
+ * If nothing happens soon, send when timer expires:
+ * if window is nonzero, transmit what we can,
+ * otherwise force out a byte.
+ */
+ if (so->so_snd.sb_cc && tp->t_timer[TCPT_REXMT] == 0 &&
+ tp->t_timer[TCPT_PERSIST] == 0) {
+ tp->t_rxtshift = 0;
+ tcp_setpersist(tp);
+ }
+
+ /*
+ * No reason to send a segment, just return.
+ */
+ return (0);
+
+send:
+ /*
+ * Before ESTABLISHED, force sending of initial options
+ * unless TCP set not to do any options.
+ * NOTE: we assume that the IP/TCP header plus TCP options
+ * always fit in a single mbuf, leaving room for a maximum
+ * link header, i.e.
+ * max_linkhdr + sizeof (struct tcpiphdr) + optlen <= MHLEN
+ */
+ optlen = 0;
+ hdrlen = sizeof (struct tcpiphdr);
+ if (flags & TH_SYN) {
+ tp->snd_nxt = tp->iss;
+ if ((tp->t_flags & TF_NOOPT) == 0) {
+ u_short mss;
+
+ opt[0] = TCPOPT_MAXSEG;
+ opt[1] = TCPOLEN_MAXSEG;
+ mss = htons((u_short) tcp_mssopt(tp));
+ (void)memcpy(opt + 2, &mss, sizeof(mss));
+ optlen = TCPOLEN_MAXSEG;
+
+ if ((tp->t_flags & TF_REQ_SCALE) &&
+ ((flags & TH_ACK) == 0 ||
+ (tp->t_flags & TF_RCVD_SCALE))) {
+ *((u_long *) (opt + optlen)) = htonl(
+ TCPOPT_NOP << 24 |
+ TCPOPT_WINDOW << 16 |
+ TCPOLEN_WINDOW << 8 |
+ tp->request_r_scale);
+ optlen += 4;
+ }
+ }
+ }
+
+ /*
+ * Send a timestamp and echo-reply if this is a SYN and our side
+ * wants to use timestamps (TF_REQ_TSTMP is set) or both our side
+ * and our peer have sent timestamps in our SYN's.
+ */
+ if ((tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP &&
+ (flags & TH_RST) == 0 &&
+ ((flags & TH_ACK) == 0 ||
+ (tp->t_flags & TF_RCVD_TSTMP))) {
+ u_long *lp = (u_long *)(opt + optlen);
+
+ /* Form timestamp option as shown in appendix A of RFC 1323. */
+ *lp++ = htonl(TCPOPT_TSTAMP_HDR);
+ *lp++ = htonl(tcp_now);
+ *lp = htonl(tp->ts_recent);
+ optlen += TCPOLEN_TSTAMP_APPA;
+ }
+
+ /*
+ * Send `CC-family' options if our side wants to use them (TF_REQ_CC),
+ * options are allowed (!TF_NOOPT) and it's not a RST.
+ */
+ if ((tp->t_flags & (TF_REQ_CC|TF_NOOPT)) == TF_REQ_CC &&
+ (flags & TH_RST) == 0) {
+ switch (flags & (TH_SYN|TH_ACK)) {
+ /*
+ * This is a normal ACK, send CC if we received CC before
+ * from our peer.
+ */
+ case TH_ACK:
+ if (!(tp->t_flags & TF_RCVD_CC))
+ break;
+ /*FALLTHROUGH*/
+
+ /*
+ * We can only get here in T/TCP's SYN_SENT* state, when
+ * we're a sending a non-SYN segment without waiting for
+ * the ACK of our SYN. A check above assures that we only
+ * do this if our peer understands T/TCP.
+ */
+ case 0:
+ opt[optlen++] = TCPOPT_NOP;
+ opt[optlen++] = TCPOPT_NOP;
+ opt[optlen++] = TCPOPT_CC;
+ opt[optlen++] = TCPOLEN_CC;
+ *(u_int32_t *)&opt[optlen] = htonl(tp->cc_send);
+
+ optlen += 4;
+ break;
+
+ /*
+ * This is our initial SYN, check whether we have to use
+ * CC or CC.new.
+ */
+ case TH_SYN:
+ opt[optlen++] = TCPOPT_NOP;
+ opt[optlen++] = TCPOPT_NOP;
+ opt[optlen++] = tp->t_flags & TF_SENDCCNEW ?
+ TCPOPT_CCNEW : TCPOPT_CC;
+ opt[optlen++] = TCPOLEN_CC;
+ *(u_int32_t *)&opt[optlen] = htonl(tp->cc_send);
+ optlen += 4;
+ break;
+
+ /*
+ * This is a SYN,ACK; send CC and CC.echo if we received
+ * CC from our peer.
+ */
+ case (TH_SYN|TH_ACK):
+ if (tp->t_flags & TF_RCVD_CC) {
+ opt[optlen++] = TCPOPT_NOP;
+ opt[optlen++] = TCPOPT_NOP;
+ opt[optlen++] = TCPOPT_CC;
+ opt[optlen++] = TCPOLEN_CC;
+ *(u_int32_t *)&opt[optlen] =
+ htonl(tp->cc_send);
+ optlen += 4;
+ opt[optlen++] = TCPOPT_NOP;
+ opt[optlen++] = TCPOPT_NOP;
+ opt[optlen++] = TCPOPT_CCECHO;
+ opt[optlen++] = TCPOLEN_CC;
+ *(u_int32_t *)&opt[optlen] =
+ htonl(tp->cc_recv);
+ optlen += 4;
+ }
+ break;
+ }
+ }
+
+ hdrlen += optlen;
+
+ /*
+ * Adjust data length if insertion of options will
+ * bump the packet length beyond the t_maxopd length.
+ * Clear the FIN bit because we cut off the tail of
+ * the segment.
+ */
+ if (len + optlen > tp->t_maxopd) {
+ /*
+ * If there is still more to send, don't close the connection.
+ */
+ flags &= ~TH_FIN;
+ len = tp->t_maxopd - optlen;
+ sendalot = 1;
+ }
+
+/*#ifdef DIAGNOSTIC*/
+ if (max_linkhdr + hdrlen > MHLEN)
+ panic("tcphdr too big");
+/*#endif*/
+
+ /*
+ * Grab a header mbuf, attaching a copy of data to
+ * be transmitted, and initialize the header from
+ * the template for sends on this connection.
+ */
+ if (len) {
+ if (tp->t_force && len == 1)
+ tcpstat.tcps_sndprobe++;
+ else if (SEQ_LT(tp->snd_nxt, tp->snd_max)) {
+ tcpstat.tcps_sndrexmitpack++;
+ tcpstat.tcps_sndrexmitbyte += len;
+ } else {
+ tcpstat.tcps_sndpack++;
+ tcpstat.tcps_sndbyte += len;
+ }
+#ifdef notyet
+ if ((m = m_copypack(so->so_snd.sb_mb, off,
+ (int)len, max_linkhdr + hdrlen)) == 0) {
+ error = ENOBUFS;
+ goto out;
+ }
+ /*
+ * m_copypack left space for our hdr; use it.
+ */
+ m->m_len += hdrlen;
+ m->m_data -= hdrlen;
+#else
+ MGETHDR(m, M_DONTWAIT, MT_HEADER);
+ if (m == NULL) {
+ error = ENOBUFS;
+ goto out;
+ }
+ m->m_data += max_linkhdr;
+ m->m_len = hdrlen;
+ if (len <= MHLEN - hdrlen - max_linkhdr) {
+ m_copydata(so->so_snd.sb_mb, off, (int) len,
+ mtod(m, caddr_t) + hdrlen);
+ m->m_len += len;
+ } else {
+ m->m_next = m_copy(so->so_snd.sb_mb, off, (int) len);
+ if (m->m_next == 0) {
+ (void) m_free(m);
+ error = ENOBUFS;
+ goto out;
+ }
+ }
+#endif
+ /*
+ * If we're sending everything we've got, set PUSH.
+ * (This will keep happy those implementations which only
+ * give data to the user when a buffer fills or
+ * a PUSH comes in.)
+ */
+ if (off + len == so->so_snd.sb_cc)
+ flags |= TH_PUSH;
+ } else {
+ if (tp->t_flags & TF_ACKNOW)
+ tcpstat.tcps_sndacks++;
+ else if (flags & (TH_SYN|TH_FIN|TH_RST))
+ tcpstat.tcps_sndctrl++;
+ else if (SEQ_GT(tp->snd_up, tp->snd_una))
+ tcpstat.tcps_sndurg++;
+ else
+ tcpstat.tcps_sndwinup++;
+
+ MGETHDR(m, M_DONTWAIT, MT_HEADER);
+ if (m == NULL) {
+ error = ENOBUFS;
+ goto out;
+ }
+ m->m_data += max_linkhdr;
+ m->m_len = hdrlen;
+ }
+ m->m_pkthdr.rcvif = (struct ifnet *)0;
+ ti = mtod(m, struct tcpiphdr *);
+ if (tp->t_template == 0)
+ panic("tcp_output");
+ (void)memcpy(ti, tp->t_template, sizeof (struct tcpiphdr));
+
+ /*
+ * Fill in fields, remembering maximum advertised
+ * window for use in delaying messages about window sizes.
+ * If resending a FIN, be sure not to use a new sequence number.
+ */
+ if (flags & TH_FIN && tp->t_flags & TF_SENTFIN &&
+ tp->snd_nxt == tp->snd_max)
+ tp->snd_nxt--;
+ /*
+ * If we are doing retransmissions, then snd_nxt will
+ * not reflect the first unsent octet. For ACK only
+ * packets, we do not want the sequence number of the
+ * retransmitted packet, we want the sequence number
+ * of the next unsent octet. So, if there is no data
+ * (and no SYN or FIN), use snd_max instead of snd_nxt
+ * when filling in ti_seq. But if we are in persist
+ * state, snd_max might reflect one byte beyond the
+ * right edge of the window, so use snd_nxt in that
+ * case, since we know we aren't doing a retransmission.
+ * (retransmit and persist are mutually exclusive...)
+ */
+ if (len || (flags & (TH_SYN|TH_FIN)) || tp->t_timer[TCPT_PERSIST])
+ ti->ti_seq = htonl(tp->snd_nxt);
+ else
+ ti->ti_seq = htonl(tp->snd_max);
+ ti->ti_ack = htonl(tp->rcv_nxt);
+ if (optlen) {
+ bcopy(opt, ti + 1, optlen);
+ ti->ti_off = (sizeof (struct tcphdr) + optlen) >> 2;
+ }
+ ti->ti_flags = flags;
+ /*
+ * Calculate receive window. Don't shrink window,
+ * but avoid silly window syndrome.
+ */
+ if (win < (long)(so->so_rcv.sb_hiwat / 4) && win < (long)tp->t_maxseg)
+ win = 0;
+ if (win < (long)(tp->rcv_adv - tp->rcv_nxt))
+ win = (long)(tp->rcv_adv - tp->rcv_nxt);
+ if (win > (long)TCP_MAXWIN << tp->rcv_scale)
+ win = (long)TCP_MAXWIN << tp->rcv_scale;
+ ti->ti_win = htons((u_short) (win>>tp->rcv_scale));
+ if (SEQ_GT(tp->snd_up, tp->snd_nxt)) {
+ ti->ti_urp = htons((u_short)(tp->snd_up - tp->snd_nxt));
+ ti->ti_flags |= TH_URG;
+ } else
+ /*
+ * If no urgent pointer to send, then we pull
+ * the urgent pointer to the left edge of the send window
+ * so that it doesn't drift into the send window on sequence
+ * number wraparound.
+ */
+ tp->snd_up = tp->snd_una; /* drag it along */
+
+ /*
+ * Put TCP length in extended header, and then
+ * checksum extended header and data.
+ */
+ if (len + optlen)
+ ti->ti_len = htons((u_short)(sizeof (struct tcphdr) +
+ optlen + len));
+ ti->ti_sum = in_cksum(m, (int)(hdrlen + len));
+
+ /*
+ * In transmit state, time the transmission and arrange for
+ * the retransmit. In persist state, just set snd_max.
+ */
+ if (tp->t_force == 0 || tp->t_timer[TCPT_PERSIST] == 0) {
+ tcp_seq startseq = tp->snd_nxt;
+
+ /*
+ * Advance snd_nxt over sequence space of this segment.
+ */
+ if (flags & (TH_SYN|TH_FIN)) {
+ if (flags & TH_SYN)
+ tp->snd_nxt++;
+ if (flags & TH_FIN) {
+ tp->snd_nxt++;
+ tp->t_flags |= TF_SENTFIN;
+ }
+ }
+ tp->snd_nxt += len;
+ if (SEQ_GT(tp->snd_nxt, tp->snd_max)) {
+ tp->snd_max = tp->snd_nxt;
+ /*
+ * Time this transmission if not a retransmission and
+ * not currently timing anything.
+ */
+ if (tp->t_rtt == 0) {
+ tp->t_rtt = 1;
+ tp->t_rtseq = startseq;
+ tcpstat.tcps_segstimed++;
+ }
+ }
+
+ /*
+ * Set retransmit timer if not currently set,
+ * and not doing an ack or a keep-alive probe.
+ * Initial value for retransmit timer is smoothed
+ * round-trip time + 2 * round-trip time variance.
+ * Initialize shift counter which is used for backoff
+ * of retransmit time.
+ */
+ if (tp->t_timer[TCPT_REXMT] == 0 &&
+ tp->snd_nxt != tp->snd_una) {
+ tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;
+ if (tp->t_timer[TCPT_PERSIST]) {
+ tp->t_timer[TCPT_PERSIST] = 0;
+ tp->t_rxtshift = 0;
+ }
+ }
+ } else
+ if (SEQ_GT(tp->snd_nxt + len, tp->snd_max))
+ tp->snd_max = tp->snd_nxt + len;
+
+#ifdef TCPDEBUG
+ /*
+ * Trace.
+ */
+ if (so->so_options & SO_DEBUG)
+ tcp_trace(TA_OUTPUT, tp->t_state, tp, ti, 0);
+#endif
+
+ /*
+ * Fill in IP length and desired time to live and
+ * send to IP level. There should be a better way
+ * to handle ttl and tos; we could keep them in
+ * the template, but need a way to checksum without them.
+ */
+ m->m_pkthdr.len = hdrlen + len;
+#ifdef TUBA
+ if (tp->t_tuba_pcb)
+ error = tuba_output(m, tp);
+ else
+#endif
+ {
+#if 1
+ struct rtentry *rt;
+#endif
+ ((struct ip *)ti)->ip_len = m->m_pkthdr.len;
+ ((struct ip *)ti)->ip_ttl = tp->t_inpcb->inp_ip_ttl; /* XXX */
+ ((struct ip *)ti)->ip_tos = tp->t_inpcb->inp_ip_tos; /* XXX */
+#if 1
+ /*
+ * See if we should do MTU discovery. We do it only if the following
+ * are true:
+ * 1) we have a valid route to the destination
+ * 2) the MTU is not locked (if it is, then discovery has been
+ * disabled)
+ */
+ if ((rt = tp->t_inpcb->inp_route.ro_rt)
+ && rt->rt_flags & RTF_UP
+ && !(rt->rt_rmx.rmx_locks & RTV_MTU)) {
+ ((struct ip *)ti)->ip_off |= IP_DF;
+ }
+#endif
+ error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route,
+ so->so_options & SO_DONTROUTE, 0);
+ }
+ if (error) {
+out:
+ if (error == ENOBUFS) {
+ tcp_quench(tp->t_inpcb, 0);
+ return (0);
+ }
+#if 1
+ if (error == EMSGSIZE) {
+ /*
+ * ip_output() will have already fixed the route
+ * for us. tcp_mtudisc() will, as its last action,
+ * initiate retransmission, so it is important to
+ * not do so here.
+ */
+ tcp_mtudisc(tp->t_inpcb, 0);
+ return 0;
+ }
+#endif
+ if ((error == EHOSTUNREACH || error == ENETDOWN)
+ && TCPS_HAVERCVDSYN(tp->t_state)) {
+ tp->t_softerror = error;
+ return (0);
+ }
+ return (error);
+ }
+ tcpstat.tcps_sndtotal++;
+
+ /*
+ * Data sent (as far as we can tell).
+ * If this advertises a larger window than any other segment,
+ * then remember the size of the advertised window.
+ * Any pending ACK has now been sent.
+ */
+ if (win > 0 && SEQ_GT(tp->rcv_nxt+win, tp->rcv_adv))
+ tp->rcv_adv = tp->rcv_nxt + win;
+ tp->last_ack_sent = tp->rcv_nxt;
+ tp->t_flags &= ~(TF_ACKNOW|TF_DELACK);
+ if (sendalot)
+ goto again;
+ return (0);
+}
+
+void
+tcp_setpersist(tp)
+ register struct tcpcb *tp;
+{
+ register int t = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1;
+
+ if (tp->t_timer[TCPT_REXMT])
+ panic("tcp_output REXMT");
+ /*
+ * Start/restart persistance timer.
+ */
+ TCPT_RANGESET(tp->t_timer[TCPT_PERSIST],
+ t * tcp_backoff[tp->t_rxtshift],
+ TCPTV_PERSMIN, TCPTV_PERSMAX);
+ if (tp->t_rxtshift < TCP_MAXRXTSHIFT)
+ tp->t_rxtshift++;
+}
diff --git a/cpukit/libnetworking/netinet/tcp_seq.h b/cpukit/libnetworking/netinet/tcp_seq.h
new file mode 100644
index 0000000000..ffc64c50af
--- /dev/null
+++ b/cpukit/libnetworking/netinet/tcp_seq.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 1982, 1986, 1993, 1995
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)tcp_seq.h 8.3 (Berkeley) 6/21/95
+ * $Id$
+ */
+
+#ifndef _NETINET_TCP_SEQ_H_
+#define _NETINET_TCP_SEQ_H_
+/*
+ * TCP sequence numbers are 32 bit integers operated
+ * on with modular arithmetic. These macros can be
+ * used to compare such integers.
+ */
+#define SEQ_LT(a,b) ((int)((a)-(b)) < 0)
+#define SEQ_LEQ(a,b) ((int)((a)-(b)) <= 0)
+#define SEQ_GT(a,b) ((int)((a)-(b)) > 0)
+#define SEQ_GEQ(a,b) ((int)((a)-(b)) >= 0)
+
+/* for modulo comparisons of timestamps */
+#define TSTMP_LT(a,b) ((int)((a)-(b)) < 0)
+#define TSTMP_GEQ(a,b) ((int)((a)-(b)) >= 0)
+
+/*
+ * TCP connection counts are 32 bit integers operated
+ * on with modular arithmetic. These macros can be
+ * used to compare such integers.
+ */
+#define CC_LT(a,b) ((int)((a)-(b)) < 0)
+#define CC_LEQ(a,b) ((int)((a)-(b)) <= 0)
+#define CC_GT(a,b) ((int)((a)-(b)) > 0)
+#define CC_GEQ(a,b) ((int)((a)-(b)) >= 0)
+
+/* Macro to increment a CC: skip 0 which has a special meaning */
+#define CC_INC(c) (++(c) == 0 ? ++(c) : (c))
+
+/*
+ * Macros to initialize tcp sequence numbers for
+ * send and receive from initial send and receive
+ * sequence numbers.
+ */
+#define tcp_rcvseqinit(tp) \
+ (tp)->rcv_adv = (tp)->rcv_nxt = (tp)->irs + 1
+
+#define tcp_sendseqinit(tp) \
+ (tp)->snd_una = (tp)->snd_nxt = (tp)->snd_max = (tp)->snd_up = \
+ (tp)->iss
+
+#define TCP_PAWS_IDLE (24 * 24 * 60 * 60 * PR_SLOWHZ)
+ /* timestamp wrap-around time */
+
+#ifdef _KERNEL
+extern tcp_cc tcp_ccgen; /* global connection count */
+
+/*
+ * Increment for tcp_iss each second.
+ * This is designed to increment at the standard 250 KB/s,
+ * but with a random component averaging 128 KB.
+ * We also increment tcp_iss by a quarter of this amount
+ * each time we use the value for a new connection.
+ * If defined, the tcp_random18() macro should produce a
+ * number in the range [0-0x3ffff] that is hard to predict.
+ */
+#ifndef tcp_random18
+#define tcp_random18() ((random() >> 14) & 0x3ffff)
+#endif
+#define TCP_ISSINCR (122*1024 + tcp_random18())
+
+extern tcp_seq tcp_iss; /* tcp initial send seq # */
+#else
+#define TCP_ISSINCR (250*1024) /* increment for tcp_iss each second */
+#endif /* _KERNEL */
+#endif /* _NETINET_TCP_SEQ_H_ */
diff --git a/cpukit/libnetworking/netinet/tcp_subr.c b/cpukit/libnetworking/netinet/tcp_subr.c
new file mode 100644
index 0000000000..5802ccc465
--- /dev/null
+++ b/cpukit/libnetworking/netinet/tcp_subr.c
@@ -0,0 +1,762 @@
+/*
+ * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)tcp_subr.c 8.2 (Berkeley) 5/24/95
+ * $Id$
+ */
+
+#include "opt_tcpdebug.h"
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/protosw.h>
+#include <sys/errno.h>
+
+#include <net/route.h>
+#include <net/if.h>
+
+#define _IP_VHL
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/in_pcb.h>
+#include <netinet/in_var.h>
+#include <netinet/ip_var.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/tcp.h>
+#include <netinet/tcp_fsm.h>
+#include <netinet/tcp_seq.h>
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_var.h>
+#include <netinet/tcpip.h>
+#ifdef TCPDEBUG
+#include <netinet/tcp_debug.h>
+#endif
+
+int tcp_mssdflt = TCP_MSS;
+SYSCTL_INT(_net_inet_tcp, TCPCTL_MSSDFLT, mssdflt,
+ CTLFLAG_RW, &tcp_mssdflt , 0, "");
+
+static int tcp_do_rfc1323 = 1;
+static int tcp_do_rfc1644 = 1;
+#if !defined(__rtems__)
+static int tcp_rttdflt = TCPTV_SRTTDFLT / PR_SLOWHZ;
+SYSCTL_INT(_net_inet_tcp, TCPCTL_RTTDFLT, rttdflt,
+ CTLFLAG_RW, &tcp_rttdflt , 0, "");
+
+SYSCTL_INT(_net_inet_tcp, TCPCTL_DO_RFC1323, rfc1323,
+ CTLFLAG_RW, &tcp_do_rfc1323 , 0, "");
+
+SYSCTL_INT(_net_inet_tcp, TCPCTL_DO_RFC1644, rfc1644,
+ CTLFLAG_RW, &tcp_do_rfc1644 , 0, "");
+#endif
+
+static void tcp_cleartaocache(void);
+static void tcp_notify __P((struct inpcb *, int));
+
+/*
+ * Target size of TCP PCB hash table. Will be rounded down to a prime
+ * number.
+ */
+#ifndef TCBHASHSIZE
+#define TCBHASHSIZE 128
+#endif
+
+/*
+ * Tcp initialization
+ */
+void
+tcp_init()
+{
+
+ tcp_iss = random(); /* wrong, but better than a constant */
+ tcp_ccgen = 1;
+ tcp_cleartaocache();
+ LIST_INIT(&tcb);
+ tcbinfo.listhead = &tcb;
+ tcbinfo.hashbase = hashinit(TCBHASHSIZE, M_PCB, &tcbinfo.hashmask);
+ if (max_protohdr < sizeof(struct tcpiphdr))
+ max_protohdr = sizeof(struct tcpiphdr);
+ if (max_linkhdr + sizeof(struct tcpiphdr) > MHLEN)
+ panic("tcp_init");
+}
+
+/*
+ * Create template to be used to send tcp packets on a connection.
+ * Call after host entry created, allocates an mbuf and fills
+ * in a skeletal tcp/ip header, minimizing the amount of work
+ * necessary when the connection is used.
+ */
+struct tcpiphdr *
+tcp_template(tp)
+ struct tcpcb *tp;
+{
+ register struct inpcb *inp = tp->t_inpcb;
+ register struct mbuf *m;
+ register struct tcpiphdr *n;
+
+ if ((n = tp->t_template) == 0) {
+ m = m_get(M_DONTWAIT, MT_HEADER);
+ if (m == NULL)
+ return (0);
+ m->m_len = sizeof (struct tcpiphdr);
+ n = mtod(m, struct tcpiphdr *);
+ }
+ n->ti_next = n->ti_prev = 0;
+ n->ti_x1 = 0;
+ n->ti_pr = IPPROTO_TCP;
+ n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip));
+ n->ti_src = inp->inp_laddr;
+ n->ti_dst = inp->inp_faddr;
+ n->ti_sport = inp->inp_lport;
+ n->ti_dport = inp->inp_fport;
+ n->ti_seq = 0;
+ n->ti_ack = 0;
+ n->ti_x2 = 0;
+ n->ti_off = 5;
+ n->ti_flags = 0;
+ n->ti_win = 0;
+ n->ti_sum = 0;
+ n->ti_urp = 0;
+ return (n);
+}
+
+/*
+ * Send a single message to the TCP at address specified by
+ * the given TCP/IP header. If m == 0, then we make a copy
+ * of the tcpiphdr at ti and send directly to the addressed host.
+ * This is used to force keep alive messages out using the TCP
+ * template for a connection tp->t_template. If flags are given
+ * then we send a message back to the TCP which originated the
+ * segment ti, and discard the mbuf containing it and any other
+ * attached mbufs.
+ *
+ * In any case the ack and sequence number of the transmitted
+ * segment are as specified by the parameters.
+ *
+ * NOTE: If m != NULL, then ti must point to *inside* the mbuf.
+ */
+void
+tcp_respond(tp, ti, m, ack, seq, flags)
+ struct tcpcb *tp;
+ register struct tcpiphdr *ti;
+ register struct mbuf *m;
+ tcp_seq ack, seq;
+ int flags;
+{
+ register int tlen;
+ int win = 0;
+ struct route *ro = 0;
+ struct route sro;
+
+ if (tp) {
+ win = sbspace(&tp->t_inpcb->inp_socket->so_rcv);
+ ro = &tp->t_inpcb->inp_route;
+ } else {
+ ro = &sro;
+ bzero(ro, sizeof *ro);
+ }
+ if (m == 0) {
+ m = m_gethdr(M_DONTWAIT, MT_HEADER);
+ if (m == NULL)
+ return;
+#ifdef TCP_COMPAT_42
+ tlen = 1;
+#else
+ tlen = 0;
+#endif
+ m->m_data += max_linkhdr;
+ *mtod(m, struct tcpiphdr *) = *ti;
+ ti = mtod(m, struct tcpiphdr *);
+ flags = TH_ACK;
+ } else {
+ m_freem(m->m_next);
+ m->m_next = 0;
+ m->m_data = (caddr_t)ti;
+ m->m_len = sizeof (struct tcpiphdr);
+ tlen = 0;
+#define xchg(a,b,type) { type t; t=a; a=b; b=t; }
+ xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, u_long);
+ xchg(ti->ti_dport, ti->ti_sport, u_short);
+#undef xchg
+ }
+ ti->ti_len = htons((u_short)(sizeof (struct tcphdr) + tlen));
+ tlen += sizeof (struct tcpiphdr);
+ m->m_len = tlen;
+ m->m_pkthdr.len = tlen;
+ m->m_pkthdr.rcvif = (struct ifnet *) 0;
+ ti->ti_next = ti->ti_prev = 0;
+ ti->ti_x1 = 0;
+ ti->ti_seq = htonl(seq);
+ ti->ti_ack = htonl(ack);
+ ti->ti_x2 = 0;
+ ti->ti_off = sizeof (struct tcphdr) >> 2;
+ ti->ti_flags = flags;
+ if (tp)
+ ti->ti_win = htons((u_short) (win >> tp->rcv_scale));
+ else
+ ti->ti_win = htons((u_short)win);
+ ti->ti_urp = 0;
+ ti->ti_sum = 0;
+ ti->ti_sum = in_cksum(m, tlen);
+ ((struct ip *)ti)->ip_len = tlen;
+ ((struct ip *)ti)->ip_ttl = ip_defttl;
+#ifdef TCPDEBUG
+ if (tp == NULL || (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
+ tcp_trace(TA_OUTPUT, 0, tp, ti, 0);
+#endif
+ (void) ip_output(m, NULL, ro, 0, NULL);
+ if (ro == &sro && ro->ro_rt) {
+ RTFREE(ro->ro_rt);
+ }
+}
+
+/*
+ * Create a new TCP control block, making an
+ * empty reassembly queue and hooking it to the argument
+ * protocol control block.
+ */
+struct tcpcb *
+tcp_newtcpcb(inp)
+ struct inpcb *inp;
+{
+ register struct tcpcb *tp;
+
+ tp = malloc(sizeof(*tp), M_PCB, M_NOWAIT);
+ if (tp == NULL)
+ return ((struct tcpcb *)0);
+ bzero((char *) tp, sizeof(struct tcpcb));
+ tp->seg_next = tp->seg_prev = (struct tcpiphdr *)tp;
+ tp->t_maxseg = tp->t_maxopd = tcp_mssdflt;
+
+ if (tcp_do_rfc1323)
+ tp->t_flags = (TF_REQ_SCALE|TF_REQ_TSTMP);
+ if (tcp_do_rfc1644)
+ tp->t_flags |= TF_REQ_CC;
+ tp->t_inpcb = inp;
+ /*
+ * Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no
+ * rtt estimate. Set rttvar so that srtt + 4 * rttvar gives
+ * reasonable initial retransmit time.
+ */
+ tp->t_srtt = TCPTV_SRTTBASE;
+ tp->t_rttvar = ((TCPTV_RTOBASE - TCPTV_SRTTBASE) << TCP_RTTVAR_SHIFT) / 4;
+ tp->t_rttmin = TCPTV_MIN;
+ tp->t_rxtcur = TCPTV_RTOBASE;
+ tp->snd_cwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT;
+ tp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT;
+ inp->inp_ip_ttl = ip_defttl;
+ inp->inp_ppcb = (caddr_t)tp;
+ return (tp);
+}
+
+/*
+ * Drop a TCP connection, reporting
+ * the specified error. If connection is synchronized,
+ * then send a RST to peer.
+ */
+struct tcpcb *
+tcp_drop(tp, errnum)
+ register struct tcpcb *tp;
+ int errnum;
+{
+ struct socket *so = tp->t_inpcb->inp_socket;
+
+ if (TCPS_HAVERCVDSYN(tp->t_state)) {
+ tp->t_state = TCPS_CLOSED;
+ (void) tcp_output(tp);
+ tcpstat.tcps_drops++;
+ } else
+ tcpstat.tcps_conndrops++;
+ if (errnum == ETIMEDOUT && tp->t_softerror)
+ errnum = tp->t_softerror;
+ so->so_error = errnum;
+ return (tcp_close(tp));
+}
+
+/*
+ * Close a TCP control block:
+ * discard all space held by the tcp
+ * discard internet protocol block
+ * wake up any sleepers
+ */
+struct tcpcb *
+tcp_close(tp)
+ register struct tcpcb *tp;
+{
+ register struct tcpiphdr *t;
+ struct inpcb *inp = tp->t_inpcb;
+ struct socket *so = inp->inp_socket;
+ register struct mbuf *m;
+ register struct rtentry *rt;
+
+ /*
+ * If we got enough samples through the srtt filter,
+ * save the rtt and rttvar in the routing entry.
+ * 'Enough' is arbitrarily defined as the 16 samples.
+ * 16 samples is enough for the srtt filter to converge
+ * to within 5% of the correct value; fewer samples and
+ * we could save a very bogus rtt.
+ *
+ * Don't update the default route's characteristics and don't
+ * update anything that the user "locked".
+ */
+ if (tp->t_rttupdated >= 16 &&
+ (rt = inp->inp_route.ro_rt) &&
+ ((struct sockaddr_in *)rt_key(rt))->sin_addr.s_addr != INADDR_ANY) {
+ register u_long i = 0;
+
+ if ((rt->rt_rmx.rmx_locks & RTV_RTT) == 0) {
+ i = tp->t_srtt *
+ (RTM_RTTUNIT / (PR_SLOWHZ * TCP_RTT_SCALE));
+ if (rt->rt_rmx.rmx_rtt && i)
+ /*
+ * filter this update to half the old & half
+ * the new values, converting scale.
+ * See route.h and tcp_var.h for a
+ * description of the scaling constants.
+ */
+ rt->rt_rmx.rmx_rtt =
+ (rt->rt_rmx.rmx_rtt + i) / 2;
+ else
+ rt->rt_rmx.rmx_rtt = i;
+ tcpstat.tcps_cachedrtt++;
+ }
+ if ((rt->rt_rmx.rmx_locks & RTV_RTTVAR) == 0) {
+ i = tp->t_rttvar *
+ (RTM_RTTUNIT / (PR_SLOWHZ * TCP_RTTVAR_SCALE));
+ if (rt->rt_rmx.rmx_rttvar && i)
+ rt->rt_rmx.rmx_rttvar =
+ (rt->rt_rmx.rmx_rttvar + i) / 2;
+ else
+ rt->rt_rmx.rmx_rttvar = i;
+ tcpstat.tcps_cachedrttvar++;
+ }
+ /*
+ * update the pipelimit (ssthresh) if it has been updated
+ * already or if a pipesize was specified & the threshhold
+ * got below half the pipesize. I.e., wait for bad news
+ * before we start updating, then update on both good
+ * and bad news.
+ */
+ if (((rt->rt_rmx.rmx_locks & RTV_SSTHRESH) == 0 &&
+ ((i = tp->snd_ssthresh) != 0) && rt->rt_rmx.rmx_ssthresh) ||
+ i < (rt->rt_rmx.rmx_sendpipe / 2)) {
+ /*
+ * convert the limit from user data bytes to
+ * packets then to packet data bytes.
+ */
+ i = (i + tp->t_maxseg / 2) / tp->t_maxseg;
+ if (i < 2)
+ i = 2;
+ i *= (u_long)(tp->t_maxseg + sizeof (struct tcpiphdr));
+ if (rt->rt_rmx.rmx_ssthresh)
+ rt->rt_rmx.rmx_ssthresh =
+ (rt->rt_rmx.rmx_ssthresh + i) / 2;
+ else
+ rt->rt_rmx.rmx_ssthresh = i;
+ tcpstat.tcps_cachedssthresh++;
+ }
+ }
+ /* free the reassembly queue, if any */
+ t = tp->seg_next;
+ while (t != (struct tcpiphdr *)tp) {
+ t = (struct tcpiphdr *)t->ti_next;
+#if (defined(__GNUC__) && defined(__arm__))
+ LD32_UNALGN((struct tcpiphdr *)t->ti_prev,m);
+#else
+ m = REASS_MBUF((struct tcpiphdr *)t->ti_prev);
+#endif
+ remque(t->ti_prev);
+ m_freem(m);
+ }
+ if (tp->t_template)
+ (void) m_free(dtom(tp->t_template));
+ free(tp, M_PCB);
+ inp->inp_ppcb = 0;
+ soisdisconnected(so);
+ in_pcbdetach(inp);
+ tcpstat.tcps_closed++;
+ return ((struct tcpcb *)0);
+}
+
+void
+tcp_drain()
+{
+
+}
+
+/*
+ * Notify a tcp user of an asynchronous error;
+ * store error as soft error, but wake up user
+ * (for now, won't do anything until can select for soft error).
+ */
+static void
+tcp_notify(inp, error)
+ struct inpcb *inp;
+ int error;
+{
+ register struct tcpcb *tp = (struct tcpcb *)inp->inp_ppcb;
+ register struct socket *so = inp->inp_socket;
+
+ /*
+ * Ignore some errors if we are hooked up.
+ * If connection hasn't completed, has retransmitted several times,
+ * and receives a second error, give up now. This is better
+ * than waiting a long time to establish a connection that
+ * can never complete.
+ */
+ if (tp->t_state == TCPS_ESTABLISHED &&
+ (error == EHOSTUNREACH || error == ENETUNREACH ||
+ error == EHOSTDOWN)) {
+ return;
+ } else if (tp->t_state < TCPS_ESTABLISHED && tp->t_rxtshift > 3 &&
+ tp->t_softerror)
+ so->so_error = error;
+ else
+ tp->t_softerror = error;
+ soconnwakeup (so);
+ sorwakeup(so);
+ sowwakeup(so);
+}
+
+#ifdef __rtems__
+#define INP_INFO_RLOCK(a)
+#define INP_INFO_RUNLOCK(a)
+#define INP_LOCK(a)
+#define INP_UNLOCK(a)
+#endif
+
+static int
+tcp_pcblist(SYSCTL_HANDLER_ARGS)
+{
+ int error, i, n, s;
+ struct inpcb *inp, **inp_list;
+ inp_gen_t gencnt;
+ struct xinpgen xig;
+
+ /*
+ * The process of preparing the TCB list is too time-consuming and
+ * resource-intensive to repeat twice on every request.
+ */
+ if (req->oldptr == 0) {
+ n = tcbinfo.ipi_count;
+ req->oldidx = 2 * (sizeof xig)
+ + (n + n/8) * sizeof(struct xtcpcb);
+ return 0;
+ }
+
+ if (req->newptr != 0)
+ return EPERM;
+
+ /*
+ * OK, now we're committed to doing something.
+ */
+ s = splnet();
+ INP_INFO_RLOCK(&tcbinfo);
+ gencnt = tcbinfo.ipi_gencnt;
+ n = tcbinfo.ipi_count;
+ INP_INFO_RUNLOCK(&tcbinfo);
+ splx(s);
+
+ sysctl_wire_old_buffer(req, 2 * (sizeof xig)
+ + n * sizeof(struct xtcpcb));
+
+ xig.xig_len = sizeof xig;
+ xig.xig_count = n;
+ xig.xig_gen = gencnt;
+/* xig.xig_sogen = so_gencnt; remove by ccj */
+ error = SYSCTL_OUT(req, &xig, sizeof xig);
+ if (error)
+ return error;
+
+ /* ccj add exit if the count is 0 */
+ if (!n)
+ return error;
+
+ inp_list = malloc(n * sizeof *inp_list, M_TEMP, M_WAITOK);
+ if (inp_list == 0)
+ return ENOMEM;
+
+ s = splnet();
+ INP_INFO_RLOCK(&tcbinfo);
+ for (inp = LIST_FIRST(tcbinfo.listhead), i = 0; inp && i < n;
+ inp = LIST_NEXT(inp, inp_list)) {
+ INP_LOCK(inp);
+ if (inp->inp_gencnt <= gencnt)
+#if 0
+ &&
+ cr_canseesocket(req->td->td_ucred, inp->inp_socket) == 0)
+#endif
+ inp_list[i++] = inp;
+ INP_UNLOCK(inp);
+ }
+ INP_INFO_RUNLOCK(&tcbinfo);
+ splx(s);
+ n = i;
+
+ error = 0;
+ for (i = 0; i < n; i++) {
+ inp = inp_list[i];
+ INP_LOCK(inp);
+ if (inp->inp_gencnt <= gencnt) {
+ struct xtcpcb xt;
+ caddr_t inp_ppcb;
+ xt.xt_len = sizeof xt;
+ /* XXX should avoid extra copy */
+ bcopy(inp, &xt.xt_inp, sizeof *inp);
+ inp_ppcb = inp->inp_ppcb;
+ if (inp_ppcb != NULL)
+ bcopy(inp_ppcb, &xt.xt_tp, sizeof xt.xt_tp);
+ else
+ bzero((char *) &xt.xt_tp, sizeof xt.xt_tp);
+#if 0
+ if (inp->inp_socket)
+ sotoxsocket(inp->inp_socket, &xt.xt_socket);
+#endif
+ error = SYSCTL_OUT(req, &xt, sizeof xt);
+ }
+ INP_UNLOCK(inp);
+ }
+ if (!error) {
+ /*
+ * Give the user an updated idea of our state.
+ * If the generation differs from what we told
+ * her before, she knows that something happened
+ * while we were processing this request, and it
+ * might be necessary to retry.
+ */
+ s = splnet();
+ INP_INFO_RLOCK(&tcbinfo);
+ xig.xig_gen = tcbinfo.ipi_gencnt;
+#if 0
+ xig.xig_sogen = so_gencnt;
+#endif
+ xig.xig_count = tcbinfo.ipi_count;
+ INP_INFO_RUNLOCK(&tcbinfo);
+ splx(s);
+ error = SYSCTL_OUT(req, &xig, sizeof xig);
+ }
+ free(inp_list, M_TEMP);
+ return error;
+}
+
+SYSCTL_PROC(_net_inet_tcp, TCPCTL_PCBLIST, pcblist, CTLFLAG_RD, 0, 0,
+ tcp_pcblist, "S,xtcpcb", "List of active TCP connections");
+
+void
+tcp_ctlinput(cmd, sa, vip)
+ int cmd;
+ struct sockaddr *sa;
+ void *vip;
+{
+ register struct ip *ip = vip;
+ register struct tcphdr *th;
+ void (*notify) __P((struct inpcb *, int)) = tcp_notify;
+
+ if (cmd == PRC_QUENCH)
+ notify = tcp_quench;
+#if 1
+ else if (cmd == PRC_MSGSIZE)
+ notify = tcp_mtudisc;
+#endif
+ else if (!PRC_IS_REDIRECT(cmd) &&
+ ((unsigned)cmd > PRC_NCMDS || inetctlerrmap[cmd] == 0))
+ return;
+ if (ip) {
+ th = (struct tcphdr *)((caddr_t)ip
+ + (IP_VHL_HL(ip->ip_vhl) << 2));
+ in_pcbnotify(&tcb, sa, th->th_dport, ip->ip_src, th->th_sport,
+ cmd, notify);
+ } else
+ in_pcbnotify(&tcb, sa, 0, zeroin_addr, 0, cmd, notify);
+}
+
+/*
+ * When a source quench is received, close congestion window
+ * to one segment. We will gradually open it again as we proceed.
+ */
+void
+tcp_quench(inp, errnum)
+ struct inpcb *inp;
+ int errnum;
+{
+ struct tcpcb *tp = intotcpcb(inp);
+
+ if (tp)
+ tp->snd_cwnd = tp->t_maxseg;
+}
+
+#if 1
+/*
+ * When `need fragmentation' ICMP is received, update our idea of the MSS
+ * based on the new value in the route. Also nudge TCP to send something,
+ * since we know the packet we just sent was dropped.
+ * This duplicates some code in the tcp_mss() function in tcp_input.c.
+ */
+void
+tcp_mtudisc(inp, errnum)
+ struct inpcb *inp;
+ int errnum;
+{
+ struct tcpcb *tp = intotcpcb(inp);
+ struct rtentry *rt;
+ struct rmxp_tao *taop;
+ struct socket *so = inp->inp_socket;
+ int offered;
+ int mss;
+
+ if (tp) {
+ rt = tcp_rtlookup(inp);
+ if (!rt || !rt->rt_rmx.rmx_mtu) {
+ tp->t_maxopd = tp->t_maxseg = tcp_mssdflt;
+ return;
+ }
+ taop = rmx_taop(rt->rt_rmx);
+ offered = taop->tao_mssopt;
+ mss = rt->rt_rmx.rmx_mtu - sizeof(struct tcpiphdr);
+ if (offered)
+ mss = min(mss, offered);
+ /*
+ * XXX - The above conditional probably violates the TCP
+ * spec. The problem is that, since we don't know the
+ * other end's MSS, we are supposed to use a conservative
+ * default. But, if we do that, then MTU discovery will
+ * never actually take place, because the conservative
+ * default is much less than the MTUs typically seen
+ * on the Internet today. For the moment, we'll sweep
+ * this under the carpet.
+ *
+ * The conservative default might not actually be a problem
+ * if the only case this occurs is when sending an initial
+ * SYN with options and data to a host we've never talked
+ * to before. Then, they will reply with an MSS value which
+ * will get recorded and the new parameters should get
+ * recomputed. For Further Study.
+ */
+ if (tp->t_maxopd <= mss)
+ return;
+ tp->t_maxopd = mss;
+
+ if ((tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP &&
+ (tp->t_flags & TF_RCVD_TSTMP) == TF_RCVD_TSTMP)
+ mss -= TCPOLEN_TSTAMP_APPA;
+ if ((tp->t_flags & (TF_REQ_CC|TF_NOOPT)) == TF_REQ_CC &&
+ (tp->t_flags & TF_RCVD_CC) == TF_RCVD_CC)
+ mss -= TCPOLEN_CC_APPA;
+#if (MCLBYTES & (MCLBYTES - 1)) == 0
+ if (mss > MCLBYTES)
+ mss &= ~(MCLBYTES-1);
+#else
+ if (mss > MCLBYTES)
+ mss = mss / MCLBYTES * MCLBYTES;
+#endif
+ if (so->so_snd.sb_hiwat < mss)
+ mss = so->so_snd.sb_hiwat;
+
+ tp->t_maxseg = mss;
+
+ tcpstat.tcps_mturesent++;
+ tp->t_rtt = 0;
+ tp->snd_nxt = tp->snd_una;
+ tcp_output(tp);
+ }
+}
+#endif
+
+/*
+ * Look-up the routing entry to the peer of this inpcb. If no route
+ * is found and it cannot be allocated the return NULL. This routine
+ * is called by TCP routines that access the rmx structure and by tcp_mss
+ * to get the interface MTU.
+ */
+struct rtentry *
+tcp_rtlookup(inp)
+ struct inpcb *inp;
+{
+ struct route *ro;
+ struct rtentry *rt;
+
+ ro = &inp->inp_route;
+ rt = ro->ro_rt;
+ if (rt == NULL || !(rt->rt_flags & RTF_UP)) {
+ /* No route yet, so try to acquire one */
+ if (inp->inp_faddr.s_addr != INADDR_ANY) {
+ ro->ro_dst.sa_family = AF_INET;
+ ro->ro_dst.sa_len = sizeof(ro->ro_dst);
+ ((struct sockaddr_in *) &ro->ro_dst)->sin_addr =
+ inp->inp_faddr;
+ rtalloc(ro);
+ rt = ro->ro_rt;
+ }
+ }
+ return rt;
+}
+
+/*
+ * Return a pointer to the cached information about the remote host.
+ * The cached information is stored in the protocol specific part of
+ * the route metrics.
+ */
+struct rmxp_tao *
+tcp_gettaocache(inp)
+ struct inpcb *inp;
+{
+ struct rtentry *rt = tcp_rtlookup(inp);
+
+ /* Make sure this is a host route and is up. */
+ if (rt == NULL ||
+ (rt->rt_flags & (RTF_UP|RTF_HOST)) != (RTF_UP|RTF_HOST))
+ return NULL;
+
+ return rmx_taop(rt->rt_rmx);
+}
+
+/*
+ * Clear all the TAO cache entries, called from tcp_init.
+ *
+ * XXX
+ * This routine is just an empty one, because we assume that the routing
+ * routing tables are initialized at the same time when TCP, so there is
+ * nothing in the cache left over.
+ */
+static void
+tcp_cleartaocache(void)
+{ }
diff --git a/cpukit/libnetworking/netinet/tcp_timer.c b/cpukit/libnetworking/netinet/tcp_timer.c
new file mode 100644
index 0000000000..04d3d604e2
--- /dev/null
+++ b/cpukit/libnetworking/netinet/tcp_timer.c
@@ -0,0 +1,387 @@
+/*
+ * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)tcp_timer.c 8.2 (Berkeley) 5/24/95
+ * $Id$
+ */
+
+#include "opt_tcpdebug.h"
+
+#ifndef TUBA_INCLUDE
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/protosw.h>
+#include <sys/errno.h>
+
+#include <machine/cpu.h> /* before tcp_seq.h, for tcp_random18() */
+
+#include <net/if.h>
+#include <net/route.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/in_pcb.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcp_fsm.h>
+#include <netinet/tcp_seq.h>
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_var.h>
+#include <netinet/tcpip.h>
+#ifdef TCPDEBUG
+#include <netinet/tcp_debug.h>
+#endif
+
+int tcp_keepinit = TCPTV_KEEP_INIT;
+SYSCTL_INT(_net_inet_tcp, TCPCTL_KEEPINIT, keepinit,
+ CTLFLAG_RW, &tcp_keepinit , 0, "");
+
+int tcp_keepidle = TCPTV_KEEP_IDLE;
+SYSCTL_INT(_net_inet_tcp, TCPCTL_KEEPIDLE, keepidle,
+ CTLFLAG_RW, &tcp_keepidle , 0, "");
+
+static int tcp_keepintvl = TCPTV_KEEPINTVL;
+SYSCTL_INT(_net_inet_tcp, TCPCTL_KEEPINTVL, keepintvl,
+ CTLFLAG_RW, &tcp_keepintvl , 0, "");
+
+static int always_keepalive = 0;
+SYSCTL_INT(_net_inet_tcp, OID_AUTO, always_keepalive,
+ CTLFLAG_RW, &always_keepalive , 0, "");
+
+static int tcp_keepcnt = TCPTV_KEEPCNT;
+ /* max idle probes */
+static int tcp_maxpersistidle = TCPTV_KEEP_IDLE;
+ /* max idle time in persist */
+int tcp_maxidle;
+#else /* TUBA_INCLUDE */
+
+static int tcp_maxpersistidle;
+#endif /* TUBA_INCLUDE */
+
+/*
+ * Fast timeout routine for processing delayed acks
+ */
+void
+tcp_fasttimo()
+{
+ register struct inpcb *inp;
+ register struct tcpcb *tp;
+ int s;
+
+ s = splnet();
+
+ for (inp = tcb.lh_first; inp != NULL; inp = inp->inp_list.le_next) {
+ if ((tp = (struct tcpcb *)inp->inp_ppcb) &&
+ (tp->t_flags & TF_DELACK)) {
+ tp->t_flags &= ~TF_DELACK;
+ tp->t_flags |= TF_ACKNOW;
+ tcpstat.tcps_delack++;
+ (void) tcp_output(tp);
+ }
+ }
+ splx(s);
+}
+
+/*
+ * Tcp protocol timeout routine called every 500 ms.
+ * Updates the timers in all active tcb's and
+ * causes finite state machine actions if timers expire.
+ */
+void
+tcp_slowtimo()
+{
+ register struct inpcb *ip, *ipnxt;
+ register struct tcpcb *tp;
+ register int i;
+ int s;
+#ifdef TCPDEBUG
+ int ostate;
+#endif
+
+ s = splnet();
+
+ tcp_maxidle = tcp_keepcnt * tcp_keepintvl;
+
+ ip = tcb.lh_first;
+ if (ip == NULL) {
+ splx(s);
+ return;
+ }
+ /*
+ * Search through tcb's and update active timers.
+ */
+ for (; ip != NULL; ip = ipnxt) {
+ ipnxt = ip->inp_list.le_next;
+ tp = intotcpcb(ip);
+ if (tp == 0 || tp->t_state == TCPS_LISTEN)
+ continue;
+ for (i = 0; i < TCPT_NTIMERS; i++) {
+ if (tp->t_timer[i] && --tp->t_timer[i] == 0) {
+#ifdef TCPDEBUG
+ ostate = tp->t_state;
+#endif
+ tp = tcp_timers(tp, i);
+ if (tp == NULL)
+ goto tpgone;
+#ifdef TCPDEBUG
+ if (tp->t_inpcb->inp_socket->so_options
+ & SO_DEBUG)
+ tcp_trace(TA_USER, ostate, tp,
+ (struct tcpiphdr *)0,
+ PRU_SLOWTIMO);
+#endif
+ }
+ }
+ tp->t_idle++;
+ tp->t_duration++;
+ if (tp->t_rtt)
+ tp->t_rtt++;
+tpgone:
+ ;
+ }
+ tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */
+#ifdef TCP_COMPAT_42
+ if ((int)tcp_iss < 0)
+ tcp_iss = TCP_ISSINCR; /* XXX */
+#endif
+ tcp_now++; /* for timestamps */
+ splx(s);
+}
+#ifndef TUBA_INCLUDE
+
+/*
+ * Cancel all timers for TCP tp.
+ */
+void
+tcp_canceltimers(tp)
+ struct tcpcb *tp;
+{
+ register int i;
+
+ for (i = 0; i < TCPT_NTIMERS; i++)
+ tp->t_timer[i] = 0;
+}
+
+int tcp_backoff[TCP_MAXRXTSHIFT + 1] =
+ { 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 };
+
+static int tcp_totbackoff = 511; /* sum of tcp_backoff[] */
+
+/*
+ * TCP timer processing.
+ */
+struct tcpcb *
+tcp_timers(tp, timer)
+ register struct tcpcb *tp;
+ int timer;
+{
+ register int rexmt;
+
+ switch (timer) {
+
+ /*
+ * 2 MSL timeout in shutdown went off. If we're closed but
+ * still waiting for peer to close and connection has been idle
+ * too long, or if 2MSL time is up from TIME_WAIT, delete connection
+ * control block. Otherwise, check again in a bit.
+ */
+ case TCPT_2MSL:
+ if (tp->t_state != TCPS_TIME_WAIT &&
+ tp->t_idle <= tcp_maxidle)
+ tp->t_timer[TCPT_2MSL] = tcp_keepintvl;
+ else
+ tp = tcp_close(tp);
+ break;
+
+ /*
+ * Retransmission timer went off. Message has not
+ * been acked within retransmit interval. Back off
+ * to a longer retransmit interval and retransmit one segment.
+ */
+ case TCPT_REXMT:
+ if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) {
+ tp->t_rxtshift = TCP_MAXRXTSHIFT;
+ tcpstat.tcps_timeoutdrop++;
+ tp = tcp_drop(tp, tp->t_softerror ?
+ tp->t_softerror : ETIMEDOUT);
+ break;
+ }
+ tcpstat.tcps_rexmttimeo++;
+ rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift];
+ TCPT_RANGESET(tp->t_rxtcur, rexmt,
+ tp->t_rttmin, TCPTV_REXMTMAX);
+ tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;
+ /*
+ * If losing, let the lower level know and try for
+ * a better route. Also, if we backed off this far,
+ * our srtt estimate is probably bogus. Clobber it
+ * so we'll take the next rtt measurement as our srtt;
+ * move the current srtt into rttvar to keep the current
+ * retransmit times until then.
+ */
+ if (tp->t_rxtshift > TCP_MAXRXTSHIFT / 4) {
+ in_losing(tp->t_inpcb);
+ tp->t_rttvar += (tp->t_srtt >> TCP_RTT_SHIFT);
+ tp->t_srtt = 0;
+ }
+ tp->snd_nxt = tp->snd_una;
+ /*
+ * Force a segment to be sent.
+ */
+ tp->t_flags |= TF_ACKNOW;
+ /*
+ * If timing a segment in this window, stop the timer.
+ */
+ tp->t_rtt = 0;
+ /*
+ * Close the congestion window down to one segment
+ * (we'll open it by one segment for each ack we get).
+ * Since we probably have a window's worth of unacked
+ * data accumulated, this "slow start" keeps us from
+ * dumping all that data as back-to-back packets (which
+ * might overwhelm an intermediate gateway).
+ *
+ * There are two phases to the opening: Initially we
+ * open by one mss on each ack. This makes the window
+ * size increase exponentially with time. If the
+ * window is larger than the path can handle, this
+ * exponential growth results in dropped packet(s)
+ * almost immediately. To get more time between
+ * drops but still "push" the network to take advantage
+ * of improving conditions, we switch from exponential
+ * to linear window opening at some threshhold size.
+ * For a threshhold, we use half the current window
+ * size, truncated to a multiple of the mss.
+ *
+ * (the minimum cwnd that will give us exponential
+ * growth is 2 mss. We don't allow the threshhold
+ * to go below this.)
+ */
+ {
+ u_int win = min(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg;
+ if (win < 2)
+ win = 2;
+ tp->snd_cwnd = tp->t_maxseg;
+ tp->snd_ssthresh = win * tp->t_maxseg;
+ tp->t_dupacks = 0;
+ }
+ (void) tcp_output(tp);
+ break;
+
+ /*
+ * Persistance timer into zero window.
+ * Force a byte to be output, if possible.
+ */
+ case TCPT_PERSIST:
+ tcpstat.tcps_persisttimeo++;
+ /*
+ * Hack: if the peer is dead/unreachable, we do not
+ * time out if the window is closed. After a full
+ * backoff, drop the connection if the idle time
+ * (no responses to probes) reaches the maximum
+ * backoff that we would use if retransmitting.
+ */
+ if (tp->t_rxtshift == TCP_MAXRXTSHIFT) {
+ u_long maxidle = TCP_REXMTVAL(tp);
+ if (maxidle < tp->t_rttmin)
+ maxidle = tp->t_rttmin;
+ maxidle *= tcp_totbackoff;
+ if (tp->t_idle >= tcp_maxpersistidle ||
+ tp->t_idle >= maxidle) {
+ tcpstat.tcps_persistdrop++;
+ tp = tcp_drop(tp, ETIMEDOUT);
+ break;
+ }
+ }
+ tcp_setpersist(tp);
+ tp->t_force = 1;
+ (void) tcp_output(tp);
+ tp->t_force = 0;
+ break;
+
+ /*
+ * Keep-alive timer went off; send something
+ * or drop connection if idle for too long.
+ */
+ case TCPT_KEEP:
+ tcpstat.tcps_keeptimeo++;
+ if (tp->t_state < TCPS_ESTABLISHED)
+ goto dropit;
+ if ((always_keepalive ||
+ tp->t_inpcb->inp_socket->so_options & SO_KEEPALIVE) &&
+ tp->t_state <= TCPS_CLOSING) {
+ if (tp->t_idle >= tcp_keepidle + tcp_maxidle)
+ goto dropit;
+ /*
+ * Send a packet designed to force a response
+ * if the peer is up and reachable:
+ * either an ACK if the connection is still alive,
+ * or an RST if the peer has closed the connection
+ * due to timeout or reboot.
+ * Using sequence number tp->snd_una-1
+ * causes the transmitted zero-length segment
+ * to lie outside the receive window;
+ * by the protocol spec, this requires the
+ * correspondent TCP to respond.
+ */
+ tcpstat.tcps_keepprobe++;
+#ifdef TCP_COMPAT_42
+ /*
+ * The keepalive packet must have nonzero length
+ * to get a 4.2 host to respond.
+ */
+ tcp_respond(tp, tp->t_template, (struct mbuf *)NULL,
+ tp->rcv_nxt - 1, tp->snd_una - 1, 0);
+#else
+ tcp_respond(tp, tp->t_template, (struct mbuf *)NULL,
+ tp->rcv_nxt, tp->snd_una - 1, 0);
+#endif
+ tp->t_timer[TCPT_KEEP] = tcp_keepintvl;
+ } else
+ tp->t_timer[TCPT_KEEP] = tcp_keepidle;
+ break;
+ dropit:
+ tcpstat.tcps_keepdrops++;
+ tp = tcp_drop(tp, ETIMEDOUT);
+ break;
+ }
+ return (tp);
+}
+#endif /* TUBA_INCLUDE */
diff --git a/cpukit/libnetworking/netinet/tcp_timer.h b/cpukit/libnetworking/netinet/tcp_timer.h
new file mode 100644
index 0000000000..98ce0ea1b3
--- /dev/null
+++ b/cpukit/libnetworking/netinet/tcp_timer.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)tcp_timer.h 8.1 (Berkeley) 6/10/93
+ * $Id$
+ */
+
+#ifndef _NETINET_TCP_TIMER_H_
+#define _NETINET_TCP_TIMER_H_
+
+/*
+ * Definitions of the TCP timers. These timers are counted
+ * down PR_SLOWHZ times a second.
+ */
+#define TCPT_NTIMERS 4
+
+#define TCPT_REXMT 0 /* retransmit */
+#define TCPT_PERSIST 1 /* retransmit persistence */
+#define TCPT_KEEP 2 /* keep alive */
+#define TCPT_2MSL 3 /* 2*msl quiet time timer */
+
+/*
+ * The TCPT_REXMT timer is used to force retransmissions.
+ * The TCP has the TCPT_REXMT timer set whenever segments
+ * have been sent for which ACKs are expected but not yet
+ * received. If an ACK is received which advances tp->snd_una,
+ * then the retransmit timer is cleared (if there are no more
+ * outstanding segments) or reset to the base value (if there
+ * are more ACKs expected). Whenever the retransmit timer goes off,
+ * we retransmit one unacknowledged segment, and do a backoff
+ * on the retransmit timer.
+ *
+ * The TCPT_PERSIST timer is used to keep window size information
+ * flowing even if the window goes shut. If all previous transmissions
+ * have been acknowledged (so that there are no retransmissions in progress),
+ * and the window is too small to bother sending anything, then we start
+ * the TCPT_PERSIST timer. When it expires, if the window is nonzero,
+ * we go to transmit state. Otherwise, at intervals send a single byte
+ * into the peer's window to force him to update our window information.
+ * We do this at most as often as TCPT_PERSMIN time intervals,
+ * but no more frequently than the current estimate of round-trip
+ * packet time. The TCPT_PERSIST timer is cleared whenever we receive
+ * a window update from the peer.
+ *
+ * The TCPT_KEEP timer is used to keep connections alive. If an
+ * connection is idle (no segments received) for TCPTV_KEEP_INIT amount of time,
+ * but not yet established, then we drop the connection. Once the connection
+ * is established, if the connection is idle for TCPTV_KEEP_IDLE time
+ * (and keepalives have been enabled on the socket), we begin to probe
+ * the connection. We force the peer to send us a segment by sending:
+ * <SEQ=SND.UNA-1><ACK=RCV.NXT><CTL=ACK>
+ * This segment is (deliberately) outside the window, and should elicit
+ * an ack segment in response from the peer. If, despite the TCPT_KEEP
+ * initiated segments we cannot elicit a response from a peer in TCPT_MAXIDLE
+ * amount of time probing, then we drop the connection.
+ */
+
+/*
+ * Time constants.
+ */
+#define TCPTV_MSL ( 30*PR_SLOWHZ) /* max seg lifetime (hah!) */
+#define TCPTV_SRTTBASE 0 /* base roundtrip time;
+ if 0, no idea yet */
+#define TCPTV_RTOBASE ( 3*PR_SLOWHZ) /* assumed RTO if no info */
+#define TCPTV_SRTTDFLT ( 3*PR_SLOWHZ) /* assumed RTT if no info */
+
+#define TCPTV_PERSMIN ( 5*PR_SLOWHZ) /* retransmit persistence */
+#define TCPTV_PERSMAX ( 60*PR_SLOWHZ) /* maximum persist interval */
+
+#define TCPTV_KEEP_INIT ( 75*PR_SLOWHZ) /* initial connect keep alive */
+#define TCPTV_KEEP_IDLE (120*60*PR_SLOWHZ) /* dflt time before probing */
+#define TCPTV_KEEPINTVL ( 75*PR_SLOWHZ) /* default probe interval */
+#define TCPTV_KEEPCNT 8 /* max probes before drop */
+
+#define TCPTV_MIN ( 1*PR_SLOWHZ) /* minimum allowable value */
+#define TCPTV_REXMTMAX ( 64*PR_SLOWHZ) /* max allowable REXMT value */
+
+#define TCPTV_TWTRUNC 8 /* RTO factor to truncate TW */
+
+#define TCP_LINGERTIME 120 /* linger at most 2 minutes */
+
+#define TCP_MAXRXTSHIFT 12 /* maximum retransmits */
+
+#ifdef TCPTIMERS
+static char *tcptimers[] =
+ { "REXMT", "PERSIST", "KEEP", "2MSL" };
+#endif
+
+/*
+ * Force a time value to be in a certain range.
+ */
+#define TCPT_RANGESET(tv, value, tvmin, tvmax) { \
+ (tv) = (value); \
+ if ((u_long)(tv) < (u_long)(tvmin)) \
+ (tv) = (tvmin); \
+ else if ((u_long)(tv) > (u_long)(tvmax)) \
+ (tv) = (tvmax); \
+}
+
+#ifdef _KERNEL
+extern int tcp_keepinit; /* time to establish connection */
+extern int tcp_keepidle; /* time before keepalive probes begin */
+extern int tcp_keepintvl; /* time between keepalive probes */
+extern int tcp_maxidle; /* time to drop after starting probes */
+extern int tcp_ttl; /* time to live for TCP segs */
+extern int tcp_backoff[];
+#endif
+
+#endif
diff --git a/cpukit/libnetworking/netinet/tcp_usrreq.c b/cpukit/libnetworking/netinet/tcp_usrreq.c
new file mode 100644
index 0000000000..e5157662a0
--- /dev/null
+++ b/cpukit/libnetworking/netinet/tcp_usrreq.c
@@ -0,0 +1,839 @@
+/*
+ * Copyright (c) 1982, 1986, 1988, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * From: @(#)tcp_usrreq.c 8.2 (Berkeley) 1/3/94
+ * $Id$
+ */
+
+#include "opt_tcpdebug.h"
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/protosw.h>
+#include <sys/errno.h>
+#include <sys/stat.h>
+
+#include <net/if.h>
+#include <net/route.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/in_pcb.h>
+#include <netinet/in_var.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcp_fsm.h>
+#include <netinet/tcp_seq.h>
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_var.h>
+#include <netinet/tcpip.h>
+#ifdef TCPDEBUG
+#include <netinet/tcp_debug.h>
+#endif
+
+/*
+ * TCP protocol interface to socket abstraction.
+ */
+extern char *tcpstates[];
+
+static int tcp_attach __P((struct socket *));
+static int tcp_connect __P((struct tcpcb *, struct mbuf *));
+static struct tcpcb *
+ tcp_disconnect __P((struct tcpcb *));
+static struct tcpcb *
+ tcp_usrclosed __P((struct tcpcb *));
+
+#ifdef TCPDEBUG
+#define TCPDEBUG0 int ostate
+#define TCPDEBUG1() ostate = tp ? tp->t_state : 0
+#define TCPDEBUG2(req) if (tp && (so->so_options & SO_DEBUG)) \
+ tcp_trace(TA_USER, ostate, tp, 0, req)
+#else
+#define TCPDEBUG0
+#define TCPDEBUG1()
+#define TCPDEBUG2(req)
+#endif
+
+/*
+ * TCP attaches to socket via pru_attach(), reserving space,
+ * and an internet control block.
+ */
+static int
+tcp_usr_attach(struct socket *so, int proto)
+{
+ int s = splnet();
+ int error;
+ struct inpcb *inp = sotoinpcb(so);
+ struct tcpcb *tp = 0;
+ TCPDEBUG0;
+
+ TCPDEBUG1();
+ if (inp) {
+ error = EISCONN;
+ goto out;
+ }
+
+ error = tcp_attach(so);
+ if (error)
+ goto out;
+
+ if ((so->so_options & SO_LINGER) && so->so_linger == 0)
+ so->so_linger = TCP_LINGERTIME * hz;
+ tp = sototcpcb(so);
+out:
+ TCPDEBUG2(PRU_ATTACH);
+ splx(s);
+ return error;
+}
+
+/*
+ * pru_detach() detaches the TCP protocol from the socket.
+ * If the protocol state is non-embryonic, then can't
+ * do this directly: have to initiate a pru_disconnect(),
+ * which may finish later; embryonic TCB's can just
+ * be discarded here.
+ */
+static int
+tcp_usr_detach(struct socket *so)
+{
+ int s = splnet();
+ int error = 0;
+ struct inpcb *inp = sotoinpcb(so);
+ struct tcpcb *tp;
+ TCPDEBUG0;
+
+ if (inp == 0) {
+ splx(s);
+ return EINVAL; /* XXX */
+ }
+ tp = intotcpcb(inp);
+ TCPDEBUG1();
+ if (tp->t_state > TCPS_LISTEN)
+ tp = tcp_disconnect(tp);
+ else
+ tp = tcp_close(tp);
+
+ TCPDEBUG2(PRU_DETACH);
+ splx(s);
+ return error;
+}
+
+#define COMMON_START() TCPDEBUG0; \
+ do { \
+ if (inp == 0) { \
+ splx(s); \
+ return EINVAL; \
+ } \
+ tp = intotcpcb(inp); \
+ TCPDEBUG1(); \
+ } while(0)
+
+#define COMMON_END(req) out: TCPDEBUG2(req); splx(s); return error; goto out
+
+
+/*
+ * Give the socket an address.
+ */
+static int
+tcp_usr_bind(struct socket *so, struct mbuf *nam)
+{
+ int s = splnet();
+ int error = 0;
+ struct inpcb *inp = sotoinpcb(so);
+ struct tcpcb *tp;
+ struct sockaddr_in *sinp;
+
+ COMMON_START();
+
+ /*
+ * Must check for multicast addresses and disallow binding
+ * to them.
+ */
+ sinp = mtod(nam, struct sockaddr_in *);
+ if (sinp->sin_family == AF_INET &&
+ IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) {
+ error = EAFNOSUPPORT;
+ goto out;
+ }
+ error = in_pcbbind(inp, nam);
+ if (error)
+ goto out;
+ COMMON_END(PRU_BIND);
+
+}
+
+/*
+ * Prepare to accept connections.
+ */
+static int
+tcp_usr_listen(struct socket *so)
+{
+ int s = splnet();
+ int error = 0;
+ struct inpcb *inp = sotoinpcb(so);
+ struct tcpcb *tp;
+
+ COMMON_START();
+ if (inp->inp_lport == 0)
+ error = in_pcbbind(inp, NULL);
+ if (error == 0)
+ tp->t_state = TCPS_LISTEN;
+ COMMON_END(PRU_LISTEN);
+}
+
+/*
+ * Initiate connection to peer.
+ * Create a template for use in transmissions on this connection.
+ * Enter SYN_SENT state, and mark socket as connecting.
+ * Start keep-alive timer, and seed output sequence space.
+ * Send initial segment on connection.
+ */
+static int
+tcp_usr_connect(struct socket *so, struct mbuf *nam)
+{
+ int s = splnet();
+ int error = 0;
+ struct inpcb *inp = sotoinpcb(so);
+ struct tcpcb *tp;
+ struct sockaddr_in *sinp;
+
+ COMMON_START();
+
+ /*
+ * Must disallow TCP ``connections'' to multicast addresses.
+ */
+ sinp = mtod(nam, struct sockaddr_in *);
+ if (sinp->sin_family == AF_INET
+ && IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) {
+ error = EAFNOSUPPORT;
+ goto out;
+ }
+
+ if ((error = tcp_connect(tp, nam)) != 0)
+ goto out;
+ error = tcp_output(tp);
+ COMMON_END(PRU_CONNECT);
+}
+
+/*
+ * Initiate disconnect from peer.
+ * If connection never passed embryonic stage, just drop;
+ * else if don't need to let data drain, then can just drop anyways,
+ * else have to begin TCP shutdown process: mark socket disconnecting,
+ * drain unread data, state switch to reflect user close, and
+ * send segment (e.g. FIN) to peer. Socket will be really disconnected
+ * when peer sends FIN and acks ours.
+ *
+ * SHOULD IMPLEMENT LATER PRU_CONNECT VIA REALLOC TCPCB.
+ */
+static int
+tcp_usr_disconnect(struct socket *so)
+{
+ int s = splnet();
+ int error = 0;
+ struct inpcb *inp = sotoinpcb(so);
+ struct tcpcb *tp;
+
+ COMMON_START();
+ tp = tcp_disconnect(tp);
+ COMMON_END(PRU_DISCONNECT);
+}
+
+/*
+ * Accept a connection. Essentially all the work is
+ * done at higher levels; just return the address
+ * of the peer, storing through addr.
+ */
+static int
+tcp_usr_accept(struct socket *so, struct mbuf *nam)
+{
+ int s = splnet();
+ int error = 0;
+ struct inpcb *inp = sotoinpcb(so);
+ struct tcpcb *tp;
+
+ COMMON_START();
+ in_setpeeraddr(inp, nam);
+ COMMON_END(PRU_ACCEPT);
+}
+
+/*
+ * Mark the connection as being incapable of further output.
+ */
+static int
+tcp_usr_shutdown(struct socket *so)
+{
+ int s = splnet();
+ int error = 0;
+ struct inpcb *inp = sotoinpcb(so);
+ struct tcpcb *tp;
+
+ COMMON_START();
+ socantsendmore(so);
+ tp = tcp_usrclosed(tp);
+ if (tp)
+ error = tcp_output(tp);
+ COMMON_END(PRU_SHUTDOWN);
+}
+
+/*
+ * After a receive, possibly send window update to peer.
+ */
+static int
+tcp_usr_rcvd(struct socket *so, int flags)
+{
+ int s = splnet();
+ int error = 0;
+ struct inpcb *inp = sotoinpcb(so);
+ struct tcpcb *tp;
+
+ COMMON_START();
+ tcp_output(tp);
+ COMMON_END(PRU_RCVD);
+}
+
+/*
+ * Do a send by putting data in output queue and updating urgent
+ * marker if URG set. Possibly send more data.
+ */
+static int
+tcp_usr_send(struct socket *so, int flags, struct mbuf *m, struct mbuf *nam,
+ struct mbuf *control)
+{
+ int s = splnet();
+ int error = 0;
+ struct inpcb *inp = sotoinpcb(so);
+ struct tcpcb *tp;
+
+ COMMON_START();
+ if (control && control->m_len) {
+ m_freem(control); /* XXX shouldn't caller do this??? */
+ if (m)
+ m_freem(m);
+ error = EINVAL;
+ goto out;
+ }
+
+ if(!(flags & PRUS_OOB)) {
+ sbappend(&so->so_snd, m);
+ if (nam && tp->t_state < TCPS_SYN_SENT) {
+ /*
+ * Do implied connect if not yet connected,
+ * initialize window to default value, and
+ * initialize maxseg/maxopd using peer's cached
+ * MSS.
+ */
+ error = tcp_connect(tp, nam);
+ if (error)
+ goto out;
+ tp->snd_wnd = TTCP_CLIENT_SND_WND;
+ tcp_mss(tp, -1);
+ }
+
+ if (flags & PRUS_EOF) {
+ /*
+ * Close the send side of the connection after
+ * the data is sent.
+ */
+ socantsendmore(so);
+ tp = tcp_usrclosed(tp);
+ }
+ if (tp != NULL)
+ error = tcp_output(tp);
+ } else {
+ if (sbspace(&so->so_snd) < -512) {
+ m_freem(m);
+ error = ENOBUFS;
+ goto out;
+ }
+ /*
+ * According to RFC961 (Assigned Protocols),
+ * the urgent pointer points to the last octet
+ * of urgent data. We continue, however,
+ * to consider it to indicate the first octet
+ * of data past the urgent section.
+ * Otherwise, snd_up should be one lower.
+ */
+ sbappend(&so->so_snd, m);
+ if (nam && tp->t_state < TCPS_SYN_SENT) {
+ /*
+ * Do implied connect if not yet connected,
+ * initialize window to default value, and
+ * initialize maxseg/maxopd using peer's cached
+ * MSS.
+ */
+ error = tcp_connect(tp, nam);
+ if (error)
+ goto out;
+ tp->snd_wnd = TTCP_CLIENT_SND_WND;
+ tcp_mss(tp, -1);
+ }
+ tp->snd_up = tp->snd_una + so->so_snd.sb_cc;
+ tp->t_force = 1;
+ error = tcp_output(tp);
+ tp->t_force = 0;
+ }
+ COMMON_END((flags & PRUS_OOB) ? PRU_SENDOOB :
+ ((flags & PRUS_EOF) ? PRU_SEND_EOF : PRU_SEND));
+}
+
+/*
+ * Abort the TCP.
+ */
+static int
+tcp_usr_abort(struct socket *so)
+{
+ int s = splnet();
+ int error = 0;
+ struct inpcb *inp = sotoinpcb(so);
+ struct tcpcb *tp;
+
+ COMMON_START();
+ tp = tcp_drop(tp, ECONNABORTED);
+ COMMON_END(PRU_ABORT);
+}
+
+/*
+ * Fill in st_bklsize for fstat() operations on a socket.
+ */
+static int
+tcp_usr_sense(struct socket *so, struct stat *sb)
+{
+ int s = splnet();
+
+ sb->st_blksize = so->so_snd.sb_hiwat;
+ splx(s);
+ return 0;
+}
+
+/*
+ * Receive out-of-band data.
+ */
+static int
+tcp_usr_rcvoob(struct socket *so, struct mbuf *m, int flags)
+{
+ int s = splnet();
+ int error = 0;
+ struct inpcb *inp = sotoinpcb(so);
+ struct tcpcb *tp;
+
+ COMMON_START();
+ if ((so->so_oobmark == 0 &&
+ (so->so_state & SS_RCVATMARK) == 0) ||
+ so->so_options & SO_OOBINLINE ||
+ tp->t_oobflags & TCPOOB_HADDATA) {
+ error = EINVAL;
+ goto out;
+ }
+ if ((tp->t_oobflags & TCPOOB_HAVEDATA) == 0) {
+ error = EWOULDBLOCK;
+ goto out;
+ }
+ m->m_len = 1;
+ *mtod(m, caddr_t) = tp->t_iobc;
+ if ((flags & MSG_PEEK) == 0)
+ tp->t_oobflags ^= (TCPOOB_HAVEDATA | TCPOOB_HADDATA);
+ COMMON_END(PRU_RCVOOB);
+}
+
+static int
+tcp_usr_sockaddr(struct socket *so, struct mbuf *nam)
+{
+ int s = splnet();
+ int error = 0;
+ struct inpcb *inp = sotoinpcb(so);
+ struct tcpcb *tp;
+
+ COMMON_START();
+ in_setsockaddr(inp, nam);
+ COMMON_END(PRU_SOCKADDR);
+}
+
+static int
+tcp_usr_peeraddr(struct socket *so, struct mbuf *nam)
+{
+ int s = splnet();
+ int error = 0;
+ struct inpcb *inp = sotoinpcb(so);
+ struct tcpcb *tp;
+
+ COMMON_START();
+ in_setpeeraddr(inp, nam);
+ COMMON_END(PRU_PEERADDR);
+}
+
+/*
+ * XXX - this should just be a call to in_control, but we need to get
+ * the types worked out.
+ */
+static int
+tcp_usr_control(struct socket *so, int cmd, caddr_t arg, struct ifnet *ifp)
+{
+ return in_control(so, cmd, arg, ifp);
+}
+
+/* xxx - should be const */
+struct pr_usrreqs tcp_usrreqs = {
+ tcp_usr_abort, tcp_usr_accept, tcp_usr_attach, tcp_usr_bind,
+ tcp_usr_connect, pru_connect2_notsupp, tcp_usr_control, tcp_usr_detach,
+ tcp_usr_disconnect, tcp_usr_listen, tcp_usr_peeraddr, tcp_usr_rcvd,
+ tcp_usr_rcvoob, tcp_usr_send, tcp_usr_sense, tcp_usr_shutdown,
+ tcp_usr_sockaddr
+};
+
+/*
+ * Common subroutine to open a TCP connection to remote host specified
+ * by struct sockaddr_in in mbuf *nam. Call in_pcbbind to assign a local
+ * port number if needed. Call in_pcbladdr to do the routing and to choose
+ * a local host address (interface). If there is an existing incarnation
+ * of the same connection in TIME-WAIT state and if the remote host was
+ * sending CC options and if the connection duration was < MSL, then
+ * truncate the previous TIME-WAIT state and proceed.
+ * Initialize connection parameters and enter SYN-SENT state.
+ */
+static int
+tcp_connect(tp, nam)
+ register struct tcpcb *tp;
+ struct mbuf *nam;
+{
+ struct inpcb *inp = tp->t_inpcb, *oinp;
+ struct socket *so = inp->inp_socket;
+ struct tcpcb *otp;
+ struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
+ struct sockaddr_in *ifaddr;
+ int error;
+ struct rmxp_tao *taop;
+ struct rmxp_tao tao_noncached;
+
+ if (inp->inp_lport == 0) {
+ error = in_pcbbind(inp, NULL);
+ if (error)
+ return error;
+ }
+
+ /*
+ * Cannot simply call in_pcbconnect, because there might be an
+ * earlier incarnation of this same connection still in
+ * TIME_WAIT state, creating an ADDRINUSE error.
+ */
+ error = in_pcbladdr(inp, nam, &ifaddr);
+ if (error)
+ return error;
+ oinp = in_pcblookuphash(inp->inp_pcbinfo,
+ sin->sin_addr, sin->sin_port,
+ inp->inp_laddr.s_addr != INADDR_ANY ? inp->inp_laddr
+ : ifaddr->sin_addr,
+ inp->inp_lport, 0);
+ if (oinp) {
+ if (oinp != inp && (otp = intotcpcb(oinp)) != NULL &&
+ otp->t_state == TCPS_TIME_WAIT &&
+ otp->t_duration < TCPTV_MSL &&
+ (otp->t_flags & TF_RCVD_CC))
+ otp = tcp_close(otp);
+ else
+ return EADDRINUSE;
+ }
+ if (inp->inp_laddr.s_addr == INADDR_ANY)
+ inp->inp_laddr = ifaddr->sin_addr;
+ inp->inp_faddr = sin->sin_addr;
+ inp->inp_fport = sin->sin_port;
+ in_pcbrehash(inp);
+
+ tp->t_template = tcp_template(tp);
+ if (tp->t_template == 0) {
+ in_pcbdisconnect(inp);
+ return ENOBUFS;
+ }
+
+ /* Compute window scaling to request. */
+ while (tp->request_r_scale < TCP_MAX_WINSHIFT &&
+ (TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat)
+ tp->request_r_scale++;
+
+ soisconnecting(so);
+ tcpstat.tcps_connattempt++;
+ tp->t_state = TCPS_SYN_SENT;
+ tp->t_timer[TCPT_KEEP] = tcp_keepinit;
+ tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2;
+ tcp_sendseqinit(tp);
+
+ /*
+ * Generate a CC value for this connection and
+ * check whether CC or CCnew should be used.
+ */
+ if ((taop = tcp_gettaocache(tp->t_inpcb)) == NULL) {
+ taop = &tao_noncached;
+ bzero(taop, sizeof(*taop));
+ }
+
+ tp->cc_send = CC_INC(tcp_ccgen);
+ if (taop->tao_ccsent != 0 &&
+ CC_GEQ(tp->cc_send, taop->tao_ccsent)) {
+ taop->tao_ccsent = tp->cc_send;
+ } else {
+ taop->tao_ccsent = 0;
+ tp->t_flags |= TF_SENDCCNEW;
+ }
+
+ return 0;
+}
+
+int
+tcp_ctloutput(op, so, level, optname, mp)
+ int op;
+ struct socket *so;
+ int level, optname;
+ struct mbuf **mp;
+{
+ int error = 0, s;
+ struct inpcb *inp;
+ register struct tcpcb *tp;
+ register struct mbuf *m;
+ register int i;
+
+ s = splnet();
+ inp = sotoinpcb(so);
+ if (inp == NULL) {
+ splx(s);
+ if (op == PRCO_SETOPT && *mp)
+ (void) m_free(*mp);
+ return (ECONNRESET);
+ }
+ if (level != IPPROTO_TCP) {
+ error = ip_ctloutput(op, so, level, optname, mp);
+ splx(s);
+ return (error);
+ }
+ tp = intotcpcb(inp);
+
+ switch (op) {
+
+ case PRCO_SETOPT:
+ m = *mp;
+ switch (optname) {
+
+ case TCP_NODELAY:
+ if (m == NULL || m->m_len < sizeof (int))
+ error = EINVAL;
+ else if (*mtod(m, int *))
+ tp->t_flags |= TF_NODELAY;
+ else
+ tp->t_flags &= ~TF_NODELAY;
+ break;
+
+ case TCP_MAXSEG:
+ if (m && (i = *mtod(m, int *)) > 0 && i <= tp->t_maxseg)
+ tp->t_maxseg = i;
+ else
+ error = EINVAL;
+ break;
+
+ case TCP_NOOPT:
+ if (m == NULL || m->m_len < sizeof (int))
+ error = EINVAL;
+ else if (*mtod(m, int *))
+ tp->t_flags |= TF_NOOPT;
+ else
+ tp->t_flags &= ~TF_NOOPT;
+ break;
+
+ case TCP_NOPUSH:
+ if (m == NULL || m->m_len < sizeof (int))
+ error = EINVAL;
+ else if (*mtod(m, int *))
+ tp->t_flags |= TF_NOPUSH;
+ else
+ tp->t_flags &= ~TF_NOPUSH;
+ break;
+
+ default:
+ error = ENOPROTOOPT;
+ break;
+ }
+ if (m)
+ (void) m_free(m);
+ break;
+
+ case PRCO_GETOPT:
+ *mp = m = m_get(M_WAIT, MT_SOOPTS);
+ m->m_len = sizeof(int);
+
+ switch (optname) {
+ case TCP_NODELAY:
+ *mtod(m, int *) = tp->t_flags & TF_NODELAY;
+ break;
+ case TCP_MAXSEG:
+ *mtod(m, int *) = tp->t_maxseg;
+ break;
+ case TCP_NOOPT:
+ *mtod(m, int *) = tp->t_flags & TF_NOOPT;
+ break;
+ case TCP_NOPUSH:
+ *mtod(m, int *) = tp->t_flags & TF_NOPUSH;
+ break;
+ default:
+ error = ENOPROTOOPT;
+ break;
+ }
+ break;
+ }
+ splx(s);
+ return (error);
+}
+
+/*
+ * tcp_sendspace and tcp_recvspace are the default send and receive window
+ * sizes, respectively. These are obsolescent (this information should
+ * be set by the route).
+ */
+u_long tcp_sendspace = 1024*16;
+SYSCTL_INT(_net_inet_tcp, TCPCTL_SENDSPACE, sendspace,
+ CTLFLAG_RW, &tcp_sendspace , 0, "");
+u_long tcp_recvspace = 1024*16;
+SYSCTL_INT(_net_inet_tcp, TCPCTL_RECVSPACE, recvspace,
+ CTLFLAG_RW, &tcp_recvspace , 0, "");
+
+/*
+ * Attach TCP protocol to socket, allocating
+ * internet protocol control block, tcp control block,
+ * bufer space, and entering LISTEN state if to accept connections.
+ */
+static int
+tcp_attach(so)
+ struct socket *so;
+{
+ register struct tcpcb *tp;
+ struct inpcb *inp;
+ int error;
+
+ if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
+ error = soreserve(so, tcp_sendspace, tcp_recvspace);
+ if (error)
+ return (error);
+ }
+ error = in_pcballoc(so, &tcbinfo);
+ if (error)
+ return (error);
+ inp = sotoinpcb(so);
+ tp = tcp_newtcpcb(inp);
+ if (tp == 0) {
+ int nofd = so->so_state & SS_NOFDREF; /* XXX */
+
+ so->so_state &= ~SS_NOFDREF; /* don't free the socket yet */
+ in_pcbdetach(inp);
+ so->so_state |= nofd;
+ return (ENOBUFS);
+ }
+ tp->t_state = TCPS_CLOSED;
+ return (0);
+}
+
+/*
+ * Initiate (or continue) disconnect.
+ * If embryonic state, just send reset (once).
+ * If in ``let data drain'' option and linger null, just drop.
+ * Otherwise (hard), mark socket disconnecting and drop
+ * current input data; switch states based on user close, and
+ * send segment to peer (with FIN).
+ */
+static struct tcpcb *
+tcp_disconnect(tp)
+ register struct tcpcb *tp;
+{
+ struct socket *so = tp->t_inpcb->inp_socket;
+
+ if (tp->t_state < TCPS_ESTABLISHED)
+ tp = tcp_close(tp);
+ else if ((so->so_options & SO_LINGER) && so->so_linger == 0)
+ tp = tcp_drop(tp, 0);
+ else {
+ soisdisconnecting(so);
+ sbflush(&so->so_rcv);
+ tp = tcp_usrclosed(tp);
+ if (tp)
+ (void) tcp_output(tp);
+ }
+ return (tp);
+}
+
+/*
+ * User issued close, and wish to trail through shutdown states:
+ * if never received SYN, just forget it. If got a SYN from peer,
+ * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN.
+ * If already got a FIN from peer, then almost done; go to LAST_ACK
+ * state. In all other cases, have already sent FIN to peer (e.g.
+ * after PRU_SHUTDOWN), and just have to play tedious game waiting
+ * for peer to send FIN or not respond to keep-alives, etc.
+ * We can let the user exit from the close as soon as the FIN is acked.
+ */
+static struct tcpcb *
+tcp_usrclosed(tp)
+ register struct tcpcb *tp;
+{
+
+ switch (tp->t_state) {
+
+ case TCPS_CLOSED:
+ case TCPS_LISTEN:
+ tp->t_state = TCPS_CLOSED;
+ tp = tcp_close(tp);
+ break;
+
+ case TCPS_SYN_SENT:
+ case TCPS_SYN_RECEIVED:
+ tp->t_flags |= TF_NEEDFIN;
+ break;
+
+ case TCPS_ESTABLISHED:
+ tp->t_state = TCPS_FIN_WAIT_1;
+ break;
+
+ case TCPS_CLOSE_WAIT:
+ tp->t_state = TCPS_LAST_ACK;
+ break;
+ }
+ if (tp && tp->t_state >= TCPS_FIN_WAIT_2) {
+ soisdisconnected(tp->t_inpcb->inp_socket);
+ /* To prevent the connection hanging in FIN_WAIT_2 forever. */
+ if (tp->t_state == TCPS_FIN_WAIT_2)
+ tp->t_timer[TCPT_2MSL] = tcp_maxidle;
+ }
+ return (tp);
+}
diff --git a/cpukit/libnetworking/netinet/tcp_var.h b/cpukit/libnetworking/netinet/tcp_var.h
new file mode 100644
index 0000000000..6c772b5053
--- /dev/null
+++ b/cpukit/libnetworking/netinet/tcp_var.h
@@ -0,0 +1,405 @@
+/*
+ * Copyright (c) 1982, 1986, 1993, 1994, 1995
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)tcp_var.h 8.4 (Berkeley) 5/24/95
+ * $Id$
+ */
+
+#ifndef _NETINET_TCP_VAR_H_
+#define _NETINET_TCP_VAR_H_
+/*
+ * Kernel variables for tcp.
+ */
+
+/*
+ * Tcp control block, one per tcp; fields:
+ */
+struct tcpcb {
+ struct tcpiphdr *seg_next; /* sequencing queue */
+ struct tcpiphdr *seg_prev;
+ int t_state; /* state of this connection */
+ int t_timer[TCPT_NTIMERS]; /* tcp timers */
+ int t_rxtshift; /* log(2) of rexmt exp. backoff */
+ int t_rxtcur; /* current retransmit value */
+ int t_dupacks; /* consecutive dup acks recd */
+ u_int t_maxseg; /* maximum segment size */
+ u_int t_maxopd; /* mss plus options */
+ int t_force; /* 1 if forcing out a byte */
+ u_int t_flags;
+#define TF_ACKNOW 0x0001 /* ack peer immediately */
+#define TF_DELACK 0x0002 /* ack, but try to delay it */
+#define TF_NODELAY 0x0004 /* don't delay packets to coalesce */
+#define TF_NOOPT 0x0008 /* don't use tcp options */
+#define TF_SENTFIN 0x0010 /* have sent FIN */
+#define TF_REQ_SCALE 0x0020 /* have/will request window scaling */
+#define TF_RCVD_SCALE 0x0040 /* other side has requested scaling */
+#define TF_REQ_TSTMP 0x0080 /* have/will request timestamps */
+#define TF_RCVD_TSTMP 0x0100 /* a timestamp was received in SYN */
+#define TF_SACK_PERMIT 0x0200 /* other side said I could SACK */
+#define TF_NEEDSYN 0x0400 /* send SYN (implicit state) */
+#define TF_NEEDFIN 0x0800 /* send FIN (implicit state) */
+#define TF_NOPUSH 0x1000 /* don't push */
+#define TF_REQ_CC 0x2000 /* have/will request CC */
+#define TF_RCVD_CC 0x4000 /* a CC was received in SYN */
+#define TF_SENDCCNEW 0x8000 /* send CCnew instead of CC in SYN */
+
+ struct tcpiphdr *t_template; /* skeletal packet for transmit */
+ struct inpcb *t_inpcb; /* back pointer to internet pcb */
+/*
+ * The following fields are used as in the protocol specification.
+ * See RFC783, Dec. 1981, page 21.
+ */
+/* send sequence variables */
+ tcp_seq snd_una; /* send unacknowledged */
+ tcp_seq snd_nxt; /* send next */
+ tcp_seq snd_up; /* send urgent pointer */
+ tcp_seq snd_wl1; /* window update seg seq number */
+ tcp_seq snd_wl2; /* window update seg ack number */
+ tcp_seq iss; /* initial send sequence number */
+ u_long snd_wnd; /* send window */
+/* receive sequence variables */
+ u_long rcv_wnd; /* receive window */
+ tcp_seq rcv_nxt; /* receive next */
+ tcp_seq rcv_up; /* receive urgent pointer */
+ tcp_seq irs; /* initial receive sequence number */
+/*
+ * Additional variables for this implementation.
+ */
+/* receive variables */
+ tcp_seq rcv_adv; /* advertised window */
+/* retransmit variables */
+ tcp_seq snd_max; /* highest sequence number sent;
+ * used to recognize retransmits
+ */
+/* congestion control (for slow start, source quench, retransmit after loss) */
+ u_long snd_cwnd; /* congestion-controlled window */
+ u_long snd_ssthresh; /* snd_cwnd size threshold for
+ * for slow start exponential to
+ * linear switch
+ */
+/*
+ * transmit timing stuff. See below for scale of srtt and rttvar.
+ * "Variance" is actually smoothed difference.
+ */
+ u_int t_idle; /* inactivity time */
+ int t_rtt; /* round trip time */
+ tcp_seq t_rtseq; /* sequence number being timed */
+ int t_srtt; /* smoothed round-trip time */
+ int t_rttvar; /* variance in round-trip time */
+ u_int t_rttmin; /* minimum rtt allowed */
+ u_long max_sndwnd; /* largest window peer has offered */
+
+/* out-of-band data */
+ char t_oobflags; /* have some */
+ char t_iobc; /* input character */
+#define TCPOOB_HAVEDATA 0x01
+#define TCPOOB_HADDATA 0x02
+ int t_softerror; /* possible error not yet reported */
+
+/* RFC 1323 variables */
+ u_char snd_scale; /* window scaling for send window */
+ u_char rcv_scale; /* window scaling for recv window */
+ u_char request_r_scale; /* pending window scaling */
+ u_char requested_s_scale;
+ u_long ts_recent; /* timestamp echo data */
+ u_long ts_recent_age; /* when last updated */
+ tcp_seq last_ack_sent;
+/* RFC 1644 variables */
+ tcp_cc cc_send; /* send connection count */
+ tcp_cc cc_recv; /* receive connection count */
+ u_long t_duration; /* connection duration */
+
+/* TUBA stuff */
+ caddr_t t_tuba_pcb; /* next level down pcb for TCP over z */
+/* More RTT stuff */
+ u_long t_rttupdated; /* number of times rtt sampled */
+};
+
+/*
+ * Structure to hold TCP options that are only used during segment
+ * processing (in tcp_input), but not held in the tcpcb.
+ * It's basically used to reduce the number of parameters
+ * to tcp_dooptions.
+ */
+struct tcpopt {
+ u_long to_flag; /* which options are present */
+#define TOF_TS 0x0001 /* timestamp */
+#define TOF_CC 0x0002 /* CC and CCnew are exclusive */
+#define TOF_CCNEW 0x0004
+#define TOF_CCECHO 0x0008
+ u_long to_tsval;
+ u_long to_tsecr;
+ tcp_cc to_cc; /* holds CC or CCnew */
+ tcp_cc to_ccecho;
+};
+
+/*
+ * The TAO cache entry which is stored in the protocol family specific
+ * portion of the route metrics.
+ */
+struct rmxp_tao {
+ tcp_cc tao_cc; /* latest CC in valid SYN */
+ tcp_cc tao_ccsent; /* latest CC sent to peer */
+ u_short tao_mssopt; /* peer's cached MSS */
+#ifdef notyet
+ u_short tao_flags; /* cache status flags */
+#define TAOF_DONT 0x0001 /* peer doesn't understand rfc1644 */
+#define TAOF_OK 0x0002 /* peer does understand rfc1644 */
+#define TAOF_UNDEF 0 /* we don't know yet */
+#endif /* notyet */
+};
+#define rmx_taop(r) ((struct rmxp_tao *)(r).rmx_filler)
+
+#define intotcpcb(ip) ((struct tcpcb *)(ip)->inp_ppcb)
+#define sototcpcb(so) (intotcpcb(sotoinpcb(so)))
+
+/*
+ * The smoothed round-trip time and estimated variance
+ * are stored as fixed point numbers scaled by the values below.
+ * For convenience, these scales are also used in smoothing the average
+ * (smoothed = (1/scale)sample + ((scale-1)/scale)smoothed).
+ * With these scales, srtt has 3 bits to the right of the binary point,
+ * and thus an "ALPHA" of 0.875. rttvar has 2 bits to the right of the
+ * binary point, and is smoothed with an ALPHA of 0.75.
+ */
+#define TCP_RTT_SCALE 32 /* multiplier for srtt; 3 bits frac. */
+#define TCP_RTT_SHIFT 5 /* shift for srtt; 3 bits frac. */
+#define TCP_RTTVAR_SCALE 16 /* multiplier for rttvar; 2 bits */
+#define TCP_RTTVAR_SHIFT 4 /* shift for rttvar; 2 bits */
+#define TCP_DELTA_SHIFT 2 /* see tcp_input.c */
+
+/*
+ * The initial retransmission should happen at rtt + 4 * rttvar.
+ * Because of the way we do the smoothing, srtt and rttvar
+ * will each average +1/2 tick of bias. When we compute
+ * the retransmit timer, we want 1/2 tick of rounding and
+ * 1 extra tick because of +-1/2 tick uncertainty in the
+ * firing of the timer. The bias will give us exactly the
+ * 1.5 tick we need. But, because the bias is
+ * statistical, we have to test that we don't drop below
+ * the minimum feasible timer (which is 2 ticks).
+ * This version of the macro adapted from a paper by Lawrence
+ * Brakmo and Larry Peterson which outlines a problem caused
+ * by insufficient precision in the original implementation,
+ * which results in inappropriately large RTO values for very
+ * fast networks.
+ */
+#define TCP_REXMTVAL(tp) \
+ ((((tp)->t_srtt >> (TCP_RTT_SHIFT - TCP_DELTA_SHIFT)) \
+ + (tp)->t_rttvar) >> TCP_DELTA_SHIFT)
+
+/* XXX
+ * We want to avoid doing m_pullup on incoming packets but that
+ * means avoiding dtom on the tcp reassembly code. That in turn means
+ * keeping an mbuf pointer in the reassembly queue (since we might
+ * have a cluster). As a quick hack, the source & destination
+ * port numbers (which are no longer needed once we've located the
+ * tcpcb) are overlayed with an mbuf pointer.
+ */
+#if (defined(__GNUC__) && defined(__arm__))
+#define STR32_UNALGN(ti,m) \
+ (ti)->ti_sport = (unsigned short)(((unsigned int) m & 0xffff0000) >> 16); \
+ (ti)->ti_dport = (unsigned short) ((unsigned int) m & 0x0000ffff);
+#define LD32_UNALGN(ti,m) \
+ m = (struct mbuf *)((((unsigned int) (ti)->ti_sport) << 16) | ( (unsigned int)(ti)->ti_dport));
+
+#else
+#define REASS_MBUF(ti) (*(struct mbuf **)&((ti)->ti_t))
+#endif
+
+/*
+ * TCP statistics.
+ * Many of these should be kept per connection,
+ * but that's inconvenient at the moment.
+ */
+struct tcpstat {
+ u_long tcps_connattempt; /* connections initiated */
+ u_long tcps_accepts; /* connections accepted */
+ u_long tcps_connects; /* connections established */
+ u_long tcps_drops; /* connections dropped */
+ u_long tcps_conndrops; /* embryonic connections dropped */
+ u_long tcps_closed; /* conn. closed (includes drops) */
+ u_long tcps_segstimed; /* segs where we tried to get rtt */
+ u_long tcps_rttupdated; /* times we succeeded */
+ u_long tcps_delack; /* delayed acks sent */
+ u_long tcps_timeoutdrop; /* conn. dropped in rxmt timeout */
+ u_long tcps_rexmttimeo; /* retransmit timeouts */
+ u_long tcps_persisttimeo; /* persist timeouts */
+ u_long tcps_keeptimeo; /* keepalive timeouts */
+ u_long tcps_keepprobe; /* keepalive probes sent */
+ u_long tcps_keepdrops; /* connections dropped in keepalive */
+
+ u_long tcps_sndtotal; /* total packets sent */
+ u_long tcps_sndpack; /* data packets sent */
+ u_long tcps_sndbyte; /* data bytes sent */
+ u_long tcps_sndrexmitpack; /* data packets retransmitted */
+ u_long tcps_sndrexmitbyte; /* data bytes retransmitted */
+ u_long tcps_sndacks; /* ack-only packets sent */
+ u_long tcps_sndprobe; /* window probes sent */
+ u_long tcps_sndurg; /* packets sent with URG only */
+ u_long tcps_sndwinup; /* window update-only packets sent */
+ u_long tcps_sndctrl; /* control (SYN|FIN|RST) packets sent */
+
+ u_long tcps_rcvtotal; /* total packets received */
+ u_long tcps_rcvpack; /* packets received in sequence */
+ u_long tcps_rcvbyte; /* bytes received in sequence */
+ u_long tcps_rcvbadsum; /* packets received with ccksum errs */
+ u_long tcps_rcvbadoff; /* packets received with bad offset */
+ u_long tcps_rcvshort; /* packets received too short */
+ u_long tcps_rcvduppack; /* duplicate-only packets received */
+ u_long tcps_rcvdupbyte; /* duplicate-only bytes received */
+ u_long tcps_rcvpartduppack; /* packets with some duplicate data */
+ u_long tcps_rcvpartdupbyte; /* dup. bytes in part-dup. packets */
+ u_long tcps_rcvoopack; /* out-of-order packets received */
+ u_long tcps_rcvoobyte; /* out-of-order bytes received */
+ u_long tcps_rcvpackafterwin; /* packets with data after window */
+ u_long tcps_rcvbyteafterwin; /* bytes rcvd after window */
+ u_long tcps_rcvafterclose; /* packets rcvd after "close" */
+ u_long tcps_rcvwinprobe; /* rcvd window probe packets */
+ u_long tcps_rcvdupack; /* rcvd duplicate acks */
+ u_long tcps_rcvacktoomuch; /* rcvd acks for unsent data */
+ u_long tcps_rcvackpack; /* rcvd ack packets */
+ u_long tcps_rcvackbyte; /* bytes acked by rcvd acks */
+ u_long tcps_rcvwinupd; /* rcvd window update packets */
+ u_long tcps_pawsdrop; /* segments dropped due to PAWS */
+ u_long tcps_predack; /* times hdr predict ok for acks */
+ u_long tcps_preddat; /* times hdr predict ok for data pkts */
+ u_long tcps_pcbcachemiss;
+ u_long tcps_cachedrtt; /* times cached RTT in route updated */
+ u_long tcps_cachedrttvar; /* times cached rttvar updated */
+ u_long tcps_cachedssthresh; /* times cached ssthresh updated */
+ u_long tcps_usedrtt; /* times RTT initialized from route */
+ u_long tcps_usedrttvar; /* times RTTVAR initialized from rt */
+ u_long tcps_usedssthresh; /* times ssthresh initialized from rt*/
+ u_long tcps_persistdrop; /* timeout in persist state */
+ u_long tcps_badsyn; /* bogus SYN, e.g. premature ACK */
+ u_long tcps_mturesent; /* resends due to MTU discovery */
+ u_long tcps_listendrop; /* listen queue overflows */
+};
+
+/*
+ * TCB structure exported to user-land via sysctl(3).
+ * Evil hack: declare only if in_pcb.h and sys/socketvar.h have been
+ * included. Not all of our clients do.
+ */
+#if defined(_NETINET_IN_PCB_H_) && defined(_SYS_SOCKETVAR_H_)
+struct xtcpcb {
+ size_t xt_len;
+ struct inpcb xt_inp;
+ struct tcpcb xt_tp;
+#if 0
+ struct xsocket xt_socket;
+ u_quad_t xt_alignment_hack;
+#endif
+};
+#endif
+
+/*
+ * Names for TCP sysctl objects
+ */
+#define TCPCTL_DO_RFC1323 1 /* use RFC-1323 extensions */
+#define TCPCTL_DO_RFC1644 2 /* use RFC-1644 extensions */
+#define TCPCTL_MSSDFLT 3 /* MSS default */
+#define TCPCTL_STATS 4 /* statistics (read-only) */
+#define TCPCTL_RTTDFLT 5 /* default RTT estimate */
+#define TCPCTL_KEEPIDLE 6 /* keepalive idle timer */
+#define TCPCTL_KEEPINTVL 7 /* interval to send keepalives */
+#define TCPCTL_SENDSPACE 8 /* send buffer space */
+#define TCPCTL_RECVSPACE 9 /* receive buffer space */
+#define TCPCTL_KEEPINIT 10 /* receive buffer space */
+#define TCPCTL_PCBLIST 11 /* list of all outstanding PCBs */
+#define TCPCTL_MAXID 12
+
+#define TCPCTL_NAMES { \
+ { 0, 0 }, \
+ { "rfc1323", CTLTYPE_INT }, \
+ { "rfc1644", CTLTYPE_INT }, \
+ { "mssdflt", CTLTYPE_INT }, \
+ { "stats", CTLTYPE_STRUCT }, \
+ { "rttdflt", CTLTYPE_INT }, \
+ { "keepidle", CTLTYPE_INT }, \
+ { "keepintvl", CTLTYPE_INT }, \
+ { "sendspace", CTLTYPE_INT }, \
+ { "recvspace", CTLTYPE_INT }, \
+ { "keepinit", CTLTYPE_INT }, \
+}
+
+#ifdef _KERNEL
+#ifdef SYSCTL_DECL
+SYSCTL_DECL(_net_inet_tcp);
+#endif
+
+extern struct inpcbhead tcb; /* head of queue of active tcpcb's */
+extern struct inpcbinfo tcbinfo;
+extern struct tcpstat tcpstat; /* tcp statistics */
+extern int tcp_mssdflt; /* XXX */
+extern u_long tcp_now; /* for RFC 1323 timestamps */
+
+void tcp_canceltimers __P((struct tcpcb *));
+struct tcpcb *
+ tcp_close __P((struct tcpcb *));
+void tcp_ctlinput __P((int, struct sockaddr *, void *));
+int tcp_ctloutput __P((int, struct socket *, int, int, struct mbuf **));
+struct tcpcb *
+ tcp_drop __P((struct tcpcb *, int));
+void tcp_drain __P((void));
+void tcp_fasttimo __P((void));
+struct rmxp_tao *
+ tcp_gettaocache __P((struct inpcb *));
+void tcp_init __P((void));
+void tcp_input __P((struct mbuf *, int));
+void tcp_mss __P((struct tcpcb *, int));
+int tcp_mssopt __P((struct tcpcb *));
+void tcp_mtudisc __P((struct inpcb *, int));
+struct tcpcb *
+ tcp_newtcpcb __P((struct inpcb *));
+int tcp_output __P((struct tcpcb *));
+void tcp_quench __P((struct inpcb *, int));
+void tcp_respond __P((struct tcpcb *,
+ struct tcpiphdr *, struct mbuf *, u_long, u_long, int));
+struct rtentry *
+ tcp_rtlookup __P((struct inpcb *));
+void tcp_setpersist __P((struct tcpcb *));
+void tcp_slowtimo __P((void));
+struct tcpiphdr *
+ tcp_template __P((struct tcpcb *));
+struct tcpcb *
+ tcp_timers __P((struct tcpcb *, int));
+void tcp_trace __P((int, int, struct tcpcb *, struct tcpiphdr *, int));
+
+extern struct pr_usrreqs tcp_usrreqs;
+extern u_long tcp_sendspace;
+extern u_long tcp_recvspace;
+
+#endif /* _KERNEL */
+
+#endif /* _NETINET_TCP_VAR_H_ */
diff --git a/cpukit/libnetworking/netinet/tcpip.h b/cpukit/libnetworking/netinet/tcpip.h
new file mode 100644
index 0000000000..b8634bfd15
--- /dev/null
+++ b/cpukit/libnetworking/netinet/tcpip.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)tcpip.h 8.1 (Berkeley) 6/10/93
+ * $Id$
+ */
+
+#ifndef _NETINET_TCPIP_H_
+#define _NETINET_TCPIP_H_
+
+/*
+ * Tcp+ip header, after ip options removed.
+ */
+struct tcpiphdr {
+ struct ipovly ti_i; /* overlaid ip structure */
+ struct tcphdr ti_t; /* tcp header */
+};
+#ifdef notyet
+/*
+ * Tcp+ip header, after ip options removed but including TCP options.
+ */
+struct full_tcpiphdr {
+ struct ipovly ti_i; /* overlaid ip structure */
+ struct tcphdr ti_t; /* tcp header */
+ char ti_o[TCP_MAXOLEN]; /* space for tcp options */
+};
+#endif /* notyet */
+#define ti_next ti_i.ih_next
+#define ti_prev ti_i.ih_prev
+#define ti_x1 ti_i.ih_x1
+#define ti_pr ti_i.ih_pr
+#define ti_len ti_i.ih_len
+#define ti_src ti_i.ih_src
+#define ti_dst ti_i.ih_dst
+#define ti_sport ti_t.th_sport
+#define ti_dport ti_t.th_dport
+#define ti_seq ti_t.th_seq
+#define ti_ack ti_t.th_ack
+#define ti_x2 ti_t.th_x2
+#define ti_off ti_t.th_off
+#define ti_flags ti_t.th_flags
+#define ti_win ti_t.th_win
+#define ti_sum ti_t.th_sum
+#define ti_urp ti_t.th_urp
+
+#endif
diff --git a/cpukit/libnetworking/netinet/udp.h b/cpukit/libnetworking/netinet/udp.h
new file mode 100644
index 0000000000..e73e1f4ddb
--- /dev/null
+++ b/cpukit/libnetworking/netinet/udp.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)udp.h 8.1 (Berkeley) 6/10/93
+ * $Id$
+ */
+
+#ifndef _NETINET_UDP_H_
+#define _NETINET_UDP_H_
+
+/*
+ * Udp protocol header.
+ * Per RFC 768, September, 1981.
+ */
+struct udphdr {
+ u_short uh_sport; /* source port */
+ u_short uh_dport; /* destination port */
+ u_short uh_ulen; /* udp length */
+ u_short uh_sum; /* udp checksum */
+};
+
+#endif
diff --git a/cpukit/libnetworking/netinet/udp_usrreq.c b/cpukit/libnetworking/netinet/udp_usrreq.c
new file mode 100644
index 0000000000..c748d8a03b
--- /dev/null
+++ b/cpukit/libnetworking/netinet/udp_usrreq.c
@@ -0,0 +1,731 @@
+/*
+ * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)udp_usrreq.c 8.6 (Berkeley) 5/23/95
+ * $Id$
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/errno.h>
+#include <sys/stat.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <sys/syslog.h>
+
+#include <net/if.h>
+#include <net/route.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/in_pcb.h>
+#include <netinet/in_var.h>
+#include <netinet/ip_var.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+
+/*
+ * UDP protocol implementation.
+ * Per RFC 768, August, 1980.
+ */
+#ifndef COMPAT_42
+static int udpcksum = 1;
+#else
+static int udpcksum = 0; /* XXX */
+#endif
+SYSCTL_INT(_net_inet_udp, UDPCTL_CHECKSUM, checksum, CTLFLAG_RW,
+ &udpcksum, 0, "");
+
+static int log_in_vain = 0;
+SYSCTL_INT(_net_inet_udp, OID_AUTO, log_in_vain, CTLFLAG_RW,
+ &log_in_vain, 0, "");
+
+static struct inpcbhead udb; /* from udp_var.h */
+static struct inpcbinfo udbinfo;
+
+#ifndef UDBHASHSIZE
+#define UDBHASHSIZE 64
+#endif
+
+ struct udpstat udpstat; /* from udp_var.h */
+SYSCTL_STRUCT(_net_inet_udp, UDPCTL_STATS, stats, CTLFLAG_RD,
+ &udpstat, udpstat, "");
+
+static struct sockaddr_in udp_in = { sizeof(udp_in), AF_INET };
+
+static void udp_detach __P((struct inpcb *));
+static int udp_output __P((struct inpcb *, struct mbuf *, struct mbuf *,
+ struct mbuf *));
+static void udp_notify __P((struct inpcb *, int));
+
+void
+udp_init()
+{
+ LIST_INIT(&udb);
+ udbinfo.listhead = &udb;
+ udbinfo.hashbase = hashinit(UDBHASHSIZE, M_PCB, &udbinfo.hashmask);
+}
+
+void
+udp_input(m, iphlen)
+ register struct mbuf *m;
+ int iphlen;
+{
+ register struct ip *ip;
+ register struct udphdr *uh;
+ register struct inpcb *inp;
+ struct mbuf *opts = 0;
+ int len;
+ struct ip save_ip;
+
+ udpstat.udps_ipackets++;
+
+ /*
+ * Strip IP options, if any; should skip this,
+ * make available to user, and use on returned packets,
+ * but we don't yet have a way to check the checksum
+ * with options still present.
+ */
+ if (iphlen > sizeof (struct ip)) {
+ ip_stripoptions(m, (struct mbuf *)0);
+ iphlen = sizeof(struct ip);
+ }
+
+ /*
+ * Get IP and UDP header together in first mbuf.
+ */
+ ip = mtod(m, struct ip *);
+ if (m->m_len < iphlen + sizeof(struct udphdr)) {
+ if ((m = m_pullup(m, iphlen + sizeof(struct udphdr))) == 0) {
+ udpstat.udps_hdrops++;
+ return;
+ }
+ ip = mtod(m, struct ip *);
+ }
+ uh = (struct udphdr *)((caddr_t)ip + iphlen);
+
+ /*
+ * Make mbuf data length reflect UDP length.
+ * If not enough data to reflect UDP length, drop.
+ */
+ len = ntohs((u_short)uh->uh_ulen);
+ if (ip->ip_len != len) {
+ if (len > ip->ip_len || len < sizeof(struct udphdr)) {
+ udpstat.udps_badlen++;
+ goto bad;
+ }
+ m_adj(m, len - ip->ip_len);
+ /* ip->ip_len = len; */
+ }
+ /*
+ * Save a copy of the IP header in case we want restore it
+ * for sending an ICMP error message in response.
+ */
+ save_ip = *ip;
+
+ /*
+ * Checksum extended UDP header and data.
+ */
+ if (uh->uh_sum) {
+ ((struct ipovly *)ip)->ih_next = 0;
+ ((struct ipovly *)ip)->ih_prev = 0;
+ ((struct ipovly *)ip)->ih_x1 = 0;
+ ((struct ipovly *)ip)->ih_len = uh->uh_ulen;
+ uh->uh_sum = in_cksum(m, len + sizeof (struct ip));
+ if (uh->uh_sum) {
+ udpstat.udps_badsum++;
+ m_freem(m);
+ return;
+ }
+ }
+
+ if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) ||
+ in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) {
+ struct inpcb *last;
+ /*
+ * Deliver a multicast or broadcast datagram to *all* sockets
+ * for which the local and remote addresses and ports match
+ * those of the incoming datagram. This allows more than
+ * one process to receive multi/broadcasts on the same port.
+ * (This really ought to be done for unicast datagrams as
+ * well, but that would cause problems with existing
+ * applications that open both address-specific sockets and
+ * a wildcard socket listening to the same port -- they would
+ * end up receiving duplicates of every unicast datagram.
+ * Those applications open the multiple sockets to overcome an
+ * inadequacy of the UDP socket interface, but for backwards
+ * compatibility we avoid the problem here rather than
+ * fixing the interface. Maybe 4.5BSD will remedy this?)
+ */
+
+ /*
+ * Construct sockaddr format source address.
+ */
+ udp_in.sin_port = uh->uh_sport;
+ udp_in.sin_addr = ip->ip_src;
+ m->m_len -= sizeof (struct udpiphdr);
+ m->m_data += sizeof (struct udpiphdr);
+ /*
+ * Locate pcb(s) for datagram.
+ * (Algorithm copied from raw_intr().)
+ */
+ last = NULL;
+ for (inp = udb.lh_first; inp != NULL; inp = inp->inp_list.le_next) {
+ if (inp->inp_lport != uh->uh_dport)
+ continue;
+ if (inp->inp_laddr.s_addr != INADDR_ANY) {
+ if (inp->inp_laddr.s_addr !=
+ ip->ip_dst.s_addr)
+ continue;
+ }
+ if (inp->inp_faddr.s_addr != INADDR_ANY) {
+ if (inp->inp_faddr.s_addr !=
+ ip->ip_src.s_addr ||
+ inp->inp_fport != uh->uh_sport)
+ continue;
+ }
+
+ if (last != NULL) {
+ struct mbuf *n;
+
+ if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
+ if (last->inp_flags & INP_CONTROLOPTS
+ || last->inp_socket->so_options & SO_TIMESTAMP)
+ ip_savecontrol(last, &opts, ip, n);
+ if (sbappendaddr(&last->inp_socket->so_rcv,
+ (struct sockaddr *)&udp_in,
+ n, opts) == 0) {
+ m_freem(n);
+ if (opts)
+ m_freem(opts);
+ udpstat.udps_fullsock++;
+ } else
+ sorwakeup(last->inp_socket);
+ opts = 0;
+ }
+ }
+ last = inp;
+ /*
+ * Don't look for additional matches if this one does
+ * not have either the SO_REUSEPORT or SO_REUSEADDR
+ * socket options set. This heuristic avoids searching
+ * through all pcbs in the common case of a non-shared
+ * port. It * assumes that an application will never
+ * clear these options after setting them.
+ */
+ if (((last->inp_socket->so_options&(SO_REUSEPORT|SO_REUSEADDR)) == 0))
+ break;
+ }
+
+ if (last == NULL) {
+ /*
+ * No matching pcb found; discard datagram.
+ * (No need to send an ICMP Port Unreachable
+ * for a broadcast or multicast datgram.)
+ */
+ udpstat.udps_noportbcast++;
+ goto bad;
+ }
+ if (last->inp_flags & INP_CONTROLOPTS
+ || last->inp_socket->so_options & SO_TIMESTAMP)
+ ip_savecontrol(last, &opts, ip, m);
+ if (sbappendaddr(&last->inp_socket->so_rcv,
+ (struct sockaddr *)&udp_in,
+ m, opts) == 0) {
+ udpstat.udps_fullsock++;
+ goto bad;
+ }
+ sorwakeup(last->inp_socket);
+ return;
+ }
+ /*
+ * Locate pcb for datagram.
+ */
+ inp = in_pcblookuphash(&udbinfo, ip->ip_src, uh->uh_sport,
+ ip->ip_dst, uh->uh_dport, 1);
+ if (inp == NULL) {
+ if (log_in_vain) {
+ char buf[4*sizeof "123"];
+
+ strcpy(buf, inet_ntoa(ip->ip_dst));
+ log(LOG_INFO, "Connection attempt to UDP %s:%d"
+ " from %s:%d\n",
+ buf, ntohs(uh->uh_dport),
+ inet_ntoa(ip->ip_src), ntohs(uh->uh_sport));
+ }
+ udpstat.udps_noport++;
+ if (m->m_flags & (M_BCAST | M_MCAST)) {
+ udpstat.udps_noportbcast++;
+ goto bad;
+ }
+ *ip = save_ip;
+ icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0);
+ return;
+ }
+
+ /*
+ * Construct sockaddr format source address.
+ * Stuff source address and datagram in user buffer.
+ */
+ udp_in.sin_port = uh->uh_sport;
+ udp_in.sin_addr = ip->ip_src;
+ if (inp->inp_flags & INP_CONTROLOPTS
+ || inp->inp_socket->so_options & SO_TIMESTAMP)
+ ip_savecontrol(inp, &opts, ip, m);
+ iphlen += sizeof(struct udphdr);
+ m->m_len -= iphlen;
+ m->m_pkthdr.len -= iphlen;
+ m->m_data += iphlen;
+ if (sbappendaddr(&inp->inp_socket->so_rcv, (struct sockaddr *)&udp_in,
+ m, opts) == 0) {
+ udpstat.udps_fullsock++;
+ goto bad;
+ }
+ sorwakeup(inp->inp_socket);
+ return;
+bad:
+ m_freem(m);
+ if (opts)
+ m_freem(opts);
+}
+
+/*
+ * Notify a udp user of an asynchronous error;
+ * just wake up so that he can collect error status.
+ */
+static void
+udp_notify(inp, errnum)
+ register struct inpcb *inp;
+ int errnum;
+{
+ inp->inp_socket->so_error = errnum;
+ sorwakeup(inp->inp_socket);
+ sowwakeup(inp->inp_socket);
+}
+
+void
+udp_ctlinput(cmd, sa, vip)
+ int cmd;
+ struct sockaddr *sa;
+ void *vip;
+{
+ register struct ip *ip = vip;
+ register struct udphdr *uh;
+
+ if (!PRC_IS_REDIRECT(cmd) &&
+ ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0))
+ return;
+ if (ip) {
+ uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2));
+ in_pcbnotify(&udb, sa, uh->uh_dport, ip->ip_src, uh->uh_sport,
+ cmd, udp_notify);
+ } else
+ in_pcbnotify(&udb, sa, 0, zeroin_addr, 0, cmd, udp_notify);
+}
+
+static int
+udp_output(inp, m, addr, control)
+ register struct inpcb *inp;
+ register struct mbuf *m;
+ struct mbuf *addr, *control;
+{
+ register struct udpiphdr *ui;
+ register int len = m->m_pkthdr.len;
+ struct in_addr laddr;
+ int s = 0, error = 0;
+
+ if (control)
+ m_freem(control); /* XXX */
+
+ if (len + sizeof(struct udpiphdr) > IP_MAXPACKET) {
+ error = EMSGSIZE;
+ goto release;
+ }
+
+ if (addr) {
+ laddr = inp->inp_laddr;
+ if (inp->inp_faddr.s_addr != INADDR_ANY) {
+ error = EISCONN;
+ goto release;
+ }
+ /*
+ * Must block input while temporarily connected.
+ */
+ s = splnet();
+ error = in_pcbconnect(inp, addr);
+ if (error) {
+ splx(s);
+ goto release;
+ }
+ } else {
+ if (inp->inp_faddr.s_addr == INADDR_ANY) {
+ error = ENOTCONN;
+ goto release;
+ }
+ }
+ /*
+ * Calculate data length and get a mbuf
+ * for UDP and IP headers.
+ */
+ M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT);
+ if (m == 0) {
+ error = ENOBUFS;
+ if (addr)
+ splx(s);
+ goto release;
+ }
+
+ /*
+ * Fill in mbuf with extended UDP header
+ * and addresses and length put into network format.
+ */
+ ui = mtod(m, struct udpiphdr *);
+ ui->ui_next = ui->ui_prev = 0;
+ ui->ui_x1 = 0;
+ ui->ui_pr = IPPROTO_UDP;
+ ui->ui_len = htons((u_short)len + sizeof (struct udphdr));
+ ui->ui_src = inp->inp_laddr;
+ ui->ui_dst = inp->inp_faddr;
+ ui->ui_sport = inp->inp_lport;
+ ui->ui_dport = inp->inp_fport;
+ ui->ui_ulen = ui->ui_len;
+
+ /*
+ * Stuff checksum and output datagram.
+ */
+ ui->ui_sum = 0;
+ if (udpcksum) {
+ if ((ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len)) == 0)
+ ui->ui_sum = 0xffff;
+ }
+ ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len;
+ ((struct ip *)ui)->ip_ttl = inp->inp_ip_ttl; /* XXX */
+ ((struct ip *)ui)->ip_tos = inp->inp_ip_tos; /* XXX */
+ udpstat.udps_opackets++;
+ error = ip_output(m, inp->inp_options, &inp->inp_route,
+ inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST),
+ inp->inp_moptions);
+
+ if (addr) {
+ in_pcbdisconnect(inp);
+ inp->inp_laddr = laddr;
+ splx(s);
+ }
+ return (error);
+
+release:
+ m_freem(m);
+ return (error);
+}
+
+#ifdef __rtems__
+#define INP_INFO_RLOCK(a)
+#define INP_INFO_RUNLOCK(a)
+#define INP_LOCK(a)
+#define INP_UNLOCK(a)
+#endif
+
+static int
+udp_pcblist(SYSCTL_HANDLER_ARGS)
+{
+ int error, i, n, s;
+ struct inpcb *inp, **inp_list;
+ inp_gen_t gencnt;
+ struct xinpgen xig;
+
+ /*
+ * The process of preparing the TCB list is too time-consuming and
+ * resource-intensive to repeat twice on every request.
+ */
+ if (req->oldptr == 0) {
+ n = udbinfo.ipi_count;
+ req->oldidx = 2 * (sizeof xig)
+ + (n + n/8) * sizeof(struct xinpcb);
+ return 0;
+ }
+
+ if (req->newptr != 0)
+ return EPERM;
+
+ /*
+ * OK, now we're committed to doing something.
+ */
+ s = splnet();
+ gencnt = udbinfo.ipi_gencnt;
+ n = udbinfo.ipi_count;
+ splx(s);
+
+ sysctl_wire_old_buffer(req, 2 * (sizeof xig)
+ + n * sizeof(struct xinpcb));
+
+ xig.xig_len = sizeof xig;
+ xig.xig_count = n;
+ xig.xig_gen = gencnt;
+#if 0
+ xig.xig_sogen = so_gencnt;
+#endif
+ error = SYSCTL_OUT(req, &xig, sizeof xig);
+ if (error)
+ return error;
+
+ /* ccj add the exit if count is 0 */
+ if (!n)
+ return error;
+
+ inp_list = malloc(n * sizeof *inp_list, M_TEMP, M_WAITOK);
+ if (inp_list == 0)
+ return ENOMEM;
+
+ s = splnet();
+ INP_INFO_RLOCK(&udbinfo);
+ for (inp = LIST_FIRST(udbinfo.listhead), i = 0; inp && i < n;
+ inp = LIST_NEXT(inp, inp_list)) {
+ INP_LOCK(inp);
+ if (inp->inp_gencnt <= gencnt)
+#if 0
+ &&
+ cr_canseesocket(req->td->td_ucred, inp->inp_socket) == 0)
+#endif
+ inp_list[i++] = inp;
+ INP_UNLOCK(inp);
+ }
+ INP_INFO_RUNLOCK(&udbinfo);
+ splx(s);
+ n = i;
+
+ error = 0;
+ for (i = 0; i < n; i++) {
+ inp = inp_list[i];
+ INP_LOCK(inp);
+ if (inp->inp_gencnt <= gencnt) {
+ struct xinpcb xi;
+ xi.xi_len = sizeof xi;
+ /* XXX should avoid extra copy */
+ bcopy(inp, &xi.xi_inp, sizeof *inp);
+#if 0
+ if (inp->inp_socket)
+ sotoxsocket(inp->inp_socket, &xi.xi_socket);
+#endif
+ error = SYSCTL_OUT(req, &xi, sizeof xi);
+ }
+ INP_UNLOCK(inp);
+ }
+ if (!error) {
+ /*
+ * Give the user an updated idea of our state.
+ * If the generation differs from what we told
+ * her before, she knows that something happened
+ * while we were processing this request, and it
+ * might be necessary to retry.
+ */
+ s = splnet();
+ INP_INFO_RLOCK(&udbinfo);
+ xig.xig_gen = udbinfo.ipi_gencnt;
+#if 0
+ xig.xig_sogen = so_gencnt;
+#endif
+ xig.xig_count = udbinfo.ipi_count;
+ INP_INFO_RUNLOCK(&udbinfo);
+ splx(s);
+ error = SYSCTL_OUT(req, &xig, sizeof xig);
+ }
+ free(inp_list, M_TEMP);
+ return error;
+}
+
+SYSCTL_PROC(_net_inet_udp, UDPCTL_PCBLIST, pcblist, CTLFLAG_RD, 0, 0,
+ udp_pcblist, "S,xinpcb", "List of active UDP sockets");
+
+static u_long udp_sendspace = 9216; /* really max datagram size */
+ /* 40 1K datagrams */
+SYSCTL_INT(_net_inet_udp, UDPCTL_MAXDGRAM, maxdgram, CTLFLAG_RW,
+ &udp_sendspace, 0, "");
+
+static u_long udp_recvspace = 40 * (1024 + sizeof(struct sockaddr_in));
+SYSCTL_INT(_net_inet_udp, UDPCTL_RECVSPACE, recvspace, CTLFLAG_RW,
+ &udp_recvspace, 0, "");
+
+/*ARGSUSED*/
+int
+udp_usrreq(so, req, m, addr, control)
+ struct socket *so;
+ int req;
+ struct mbuf *m, *addr, *control;
+{
+ struct inpcb *inp = sotoinpcb(so);
+ int error = 0;
+ int s;
+
+ if (req == PRU_CONTROL)
+ return (in_control(so, (u_long)m, (caddr_t)addr,
+ (struct ifnet *)control));
+ if (inp == NULL && req != PRU_ATTACH) {
+ error = EINVAL;
+ goto release;
+ }
+ /*
+ * Note: need to block udp_input while changing
+ * the udp pcb queue and/or pcb addresses.
+ */
+ switch (req) {
+
+ case PRU_ATTACH:
+ if (inp != NULL) {
+ error = EINVAL;
+ break;
+ }
+ s = splnet();
+ error = in_pcballoc(so, &udbinfo);
+ splx(s);
+ if (error)
+ break;
+ error = soreserve(so, udp_sendspace, udp_recvspace);
+ if (error)
+ break;
+ ((struct inpcb *) so->so_pcb)->inp_ip_ttl = ip_defttl;
+ break;
+
+ case PRU_DETACH:
+ udp_detach(inp);
+ break;
+
+ case PRU_BIND:
+ s = splnet();
+ error = in_pcbbind(inp, addr);
+ splx(s);
+ break;
+
+ case PRU_LISTEN:
+ error = EOPNOTSUPP;
+ break;
+
+ case PRU_CONNECT:
+ if (inp->inp_faddr.s_addr != INADDR_ANY) {
+ error = EISCONN;
+ break;
+ }
+ s = splnet();
+ error = in_pcbconnect(inp, addr);
+ splx(s);
+ if (error == 0)
+ soisconnected(so);
+ break;
+
+ case PRU_CONNECT2:
+ error = EOPNOTSUPP;
+ break;
+
+ case PRU_ACCEPT:
+ error = EOPNOTSUPP;
+ break;
+
+ case PRU_DISCONNECT:
+ if (inp->inp_faddr.s_addr == INADDR_ANY) {
+ error = ENOTCONN;
+ break;
+ }
+ s = splnet();
+ in_pcbdisconnect(inp);
+ inp->inp_laddr.s_addr = INADDR_ANY;
+ splx(s);
+ so->so_state &= ~SS_ISCONNECTED; /* XXX */
+ break;
+
+ case PRU_SHUTDOWN:
+ socantsendmore(so);
+ break;
+
+ case PRU_SEND:
+ return (udp_output(inp, m, addr, control));
+
+ case PRU_ABORT:
+ soisdisconnected(so);
+ udp_detach(inp);
+ break;
+
+ case PRU_SOCKADDR:
+ in_setsockaddr(inp, addr);
+ break;
+
+ case PRU_PEERADDR:
+ in_setpeeraddr(inp, addr);
+ break;
+
+ case PRU_SENSE:
+ /*
+ * stat: don't bother with a blocksize.
+ */
+ return (0);
+
+ case PRU_SENDOOB:
+ case PRU_FASTTIMO:
+ case PRU_SLOWTIMO:
+ case PRU_PROTORCV:
+ case PRU_PROTOSEND:
+ error = EOPNOTSUPP;
+ break;
+
+ case PRU_RCVD:
+ case PRU_RCVOOB:
+ return (EOPNOTSUPP); /* do not free mbuf's */
+
+ default:
+ panic("udp_usrreq");
+ }
+
+release:
+ if (control) {
+ printf("udp control data unexpectedly retained\n");
+ m_freem(control);
+ }
+ if (m)
+ m_freem(m);
+ return (error);
+}
+
+static void
+udp_detach(inp)
+ struct inpcb *inp;
+{
+ int s = splnet();
+
+ in_pcbdetach(inp);
+ splx(s);
+}
diff --git a/cpukit/libnetworking/netinet/udp_var.h b/cpukit/libnetworking/netinet/udp_var.h
new file mode 100644
index 0000000000..86bfd9d614
--- /dev/null
+++ b/cpukit/libnetworking/netinet/udp_var.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 1982, 1986, 1989, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)udp_var.h 8.1 (Berkeley) 6/10/93
+ * $Id$
+ */
+
+#ifndef _NETINET_UDP_VAR_H_
+#define _NETINET_UDP_VAR_H_
+
+/*
+ * UDP kernel structures and variables.
+ */
+struct udpiphdr {
+ struct ipovly ui_i; /* overlaid ip structure */
+ struct udphdr ui_u; /* udp header */
+};
+#define ui_next ui_i.ih_next
+#define ui_prev ui_i.ih_prev
+#define ui_x1 ui_i.ih_x1
+#define ui_pr ui_i.ih_pr
+#define ui_len ui_i.ih_len
+#define ui_src ui_i.ih_src
+#define ui_dst ui_i.ih_dst
+#define ui_sport ui_u.uh_sport
+#define ui_dport ui_u.uh_dport
+#define ui_ulen ui_u.uh_ulen
+#define ui_sum ui_u.uh_sum
+
+struct udpstat {
+ /* input statistics: */
+ u_long udps_ipackets; /* total input packets */
+ u_long udps_hdrops; /* packet shorter than header */
+ u_long udps_badsum; /* checksum error */
+ u_long udps_badlen; /* data length larger than packet */
+ u_long udps_noport; /* no socket on port */
+ u_long udps_noportbcast; /* of above, arrived as broadcast */
+ u_long udps_fullsock; /* not delivered, input socket full */
+ u_long udpps_pcbcachemiss; /* input packets missing pcb cache */
+ u_long udpps_pcbhashmiss; /* input packets not for hashed pcb */
+ /* output statistics: */
+ u_long udps_opackets; /* total output packets */
+};
+
+/*
+ * Names for UDP sysctl objects
+ */
+#define UDPCTL_CHECKSUM 1 /* checksum UDP packets */
+#define UDPCTL_STATS 2 /* statistics (read-only) */
+#define UDPCTL_MAXDGRAM 3 /* max datagram size */
+#define UDPCTL_RECVSPACE 4 /* default receive buffer space */
+#define UDPCTL_PCBLIST 5 /* list of PCBs for UDP sockets */
+#define UDPCTL_MAXID 6
+
+#define UDPCTL_NAMES { \
+ { 0, 0 }, \
+ { "checksum", CTLTYPE_INT }, \
+ { "stats", CTLTYPE_STRUCT }, \
+ { "maxdgram", CTLTYPE_INT }, \
+ { "recvspace", CTLTYPE_INT }, \
+}
+
+#ifdef _KERNEL
+SYSCTL_DECL(_net_inet_udp);
+
+extern struct inpcbhead udb;
+extern struct inpcbinfo udbinfo;
+extern struct udpstat udpstat;
+
+void udp_ctlinput __P((int, struct sockaddr *, void *));
+void udp_init __P((void));
+void udp_input __P((struct mbuf *, int));
+int udp_usrreq __P((struct socket *,
+ int, struct mbuf *, struct mbuf *, struct mbuf *));
+#endif
+
+#endif
diff --git a/cpukit/libnetworking/nfs/bootp_subr.c b/cpukit/libnetworking/nfs/bootp_subr.c
new file mode 100644
index 0000000000..7328a21f2c
--- /dev/null
+++ b/cpukit/libnetworking/nfs/bootp_subr.c
@@ -0,0 +1,1164 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 1995 Gordon Ross, Adam Glass
+ * Copyright (c) 1992 Regents of the University of California.
+ * All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * 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 the University of
+ * California, Lawrence Berkeley Laboratory and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * based on:
+ * nfs/krpc_subr.c
+ * $NetBSD: krpc_subr.c,v 1.10 1995/08/08 20:43:43 gwr Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/sockio.h>
+#include <sys/proc.h>
+#include <sys/mount.h>
+#include <sys/mbuf.h>
+#include <sys/reboot.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+
+#include <net/if.h>
+#include <net/route.h>
+
+#include <netinet/in.h>
+#include <net/if_types.h>
+#include <net/if_dl.h>
+#include <netinet/if_ether.h>
+
+#include <nfs/rpcv2.h>
+#include <nfs/nfsproto.h>
+#include <nfs/nfs.h>
+#include <nfs/nfsdiskless.h>
+#include <nfs/krpc.h>
+#include <nfs/xdr_subs.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <rtems/mkrootfs.h>
+#include <rtems/rtems_bsdnet.h>
+
+#define BOOTP_MIN_LEN 300 /* Minimum size of bootp udp packet */
+
+/*
+ * What is the longest we will wait before re-sending a request?
+ * Note this is also the frequency of "RPC timeout" messages.
+ * The re-send loop count sup linearly to this maximum, so the
+ * first complaint will happen after (1+2+3+4+5)=15 seconds.
+ */
+#define MAX_RESEND_DELAY 5 /* seconds */
+
+/* Definitions from RFC951 */
+struct bootp_packet {
+ u_int8_t op;
+ u_int8_t htype;
+ u_int8_t hlen;
+ u_int8_t hops;
+ u_int32_t xid;
+ u_int16_t secs;
+ u_int16_t flags;
+ struct in_addr ciaddr;
+ struct in_addr yiaddr;
+ struct in_addr siaddr;
+ struct in_addr giaddr;
+ unsigned char chaddr[16];
+ char sname[64];
+ char file[128];
+ unsigned char vend[256];
+};
+
+#define IPPORT_BOOTPC 68
+#define IPPORT_BOOTPS 67
+
+extern int nfs_diskless_valid;
+extern struct nfsv3_diskless nfsv3_diskless;
+
+/* mountd RPC */
+#if !defined(__rtems__)
+static int md_mount __P((struct sockaddr_in *mdsin, char *path,
+ u_char *fhp, int *fhsizep, struct nfs_args *args,struct proc *procp));
+static int md_lookup_swap __P((struct sockaddr_in *mdsin,char *path,
+ u_char *fhp, int *fhsizep,
+ struct nfs_args *args,
+ struct proc *procp));
+static int setfs __P((struct sockaddr_in *addr, char *path, char *p));
+static int getdec __P((char **ptr));
+#endif
+#if !defined(__rtems__)
+static char *substr __P((char *a,char *b));
+static void mountopts __P((struct nfs_args *args, char *p));
+static int xdr_opaque_decode __P((struct mbuf **ptr,u_char *buf,
+ int len));
+static int xdr_int_decode __P((struct mbuf **ptr,int *iptr));
+#endif
+static void printip __P((char *prefix,struct in_addr addr));
+
+#ifdef BOOTP_DEBUG
+void bootpboot_p_sa(struct sockaddr *sa,struct sockaddr *ma);
+void bootpboot_p_ma(struct sockaddr *ma);
+void bootpboot_p_rtentry(struct rtentry *rt);
+void bootpboot_p_tree(struct radix_node *rn);
+void bootpboot_p_rtlist(void);
+void bootpboot_p_iflist(void);
+#endif
+
+int bootpc_call(struct bootp_packet *call,
+ struct bootp_packet *reply,
+ struct proc *procp);
+
+int bootpc_fakeup_interface(struct ifreq *ireq,struct socket *so,
+ struct proc *procp);
+
+int
+bootpc_adjust_interface(struct ifreq *ireq,struct socket *so,
+ struct sockaddr_in *myaddr,
+ struct sockaddr_in *netmask,
+ struct sockaddr_in *gw,
+ struct proc *procp);
+
+void bootpc_init(int update_files);
+
+#ifdef BOOTP_DEBUG
+void bootpboot_p_sa(sa,ma)
+ struct sockaddr *sa;
+ struct sockaddr *ma;
+{
+ if (!sa) {
+ printf("(sockaddr *) <null>");
+ return;
+ }
+ switch (sa->sa_family) {
+ case AF_INET:
+ {
+ struct sockaddr_in *sin = (struct sockaddr_in *) sa;
+ printf("inet %x",ntohl(sin->sin_addr.s_addr));
+ if (ma) {
+ struct sockaddr_in *sin = (struct sockaddr_in *) ma;
+ printf(" mask %x",ntohl(sin->sin_addr.s_addr));
+ }
+ }
+ break;
+ case AF_LINK:
+ {
+ struct sockaddr_dl *sli = (struct sockaddr_dl *) sa;
+ int i;
+ printf("link %.*s ",sli->sdl_nlen,sli->sdl_data);
+ for (i=0;i<sli->sdl_alen;i++) {
+ if (i>0)
+ printf(":");
+ printf("%x",(unsigned char) sli->sdl_data[i+sli->sdl_nlen]);
+ }
+ }
+ break;
+ default:
+ printf("af%d",sa->sa_family);
+ }
+}
+
+void bootpboot_p_ma(ma)
+ struct sockaddr *ma;
+{
+ if (!ma) {
+ printf("<null>");
+ return;
+ }
+ printf("%x",*(int*)ma);
+}
+
+void bootpboot_p_rtentry(rt)
+ struct rtentry *rt;
+{
+ bootpboot_p_sa(rt_key(rt),rt_mask(rt));
+ printf(" ");
+ bootpboot_p_ma(rt->rt_genmask);
+ printf(" ");
+ bootpboot_p_sa(rt->rt_gateway,NULL);
+ printf(" ");
+ printf("flags %x",(unsigned short) rt->rt_flags);
+ printf(" %d",rt->rt_rmx.rmx_expire);
+ printf(" %s%d\n",rt->rt_ifp->if_name,rt->rt_ifp->if_unit);
+}
+void bootpboot_p_tree(rn)
+ struct radix_node *rn;
+{
+ while (rn) {
+ if (rn->rn_b < 0) {
+ if (rn->rn_flags & RNF_ROOT) {
+ } else {
+ bootpboot_p_rtentry((struct rtentry *) rn);
+ }
+ rn = rn->rn_dupedkey;
+ } else {
+ bootpboot_p_tree(rn->rn_l);
+ bootpboot_p_tree(rn->rn_r);
+ return;
+ }
+
+ }
+}
+
+void bootpboot_p_rtlist(void)
+{
+ printf("Routing table:\n");
+ bootpboot_p_tree(rt_tables[AF_INET]->rnh_treetop);
+}
+
+void bootpboot_p_iflist(void)
+{
+ struct ifnet *ifp;
+ struct ifaddr *ifa;
+ printf("Interface list:\n");
+ for (ifp = TAILQ_FIRST(&ifnet); ifp != 0; ifp = TAILQ_NEXT(ifp,if_link))
+ {
+ for (ifa = TAILQ_FIRST(&ifp->if_addrhead) ;ifa;
+ ifa=TAILQ_NEXT(ifa,ifa_link))
+ if (ifa->ifa_addr->sa_family == AF_INET ) {
+ printf("%s%d flags %x, addr %x, bcast %x, net %x\n",
+ ifp->if_name,ifp->if_unit,
+ (unsigned short) ifp->if_flags,
+ ntohl(((struct sockaddr_in *) ifa->ifa_addr)->sin_addr.s_addr),
+ ntohl(((struct sockaddr_in *) ifa->ifa_dstaddr)->sin_addr.s_addr),
+ ntohl(((struct sockaddr_in *) ifa->ifa_netmask)->sin_addr.s_addr)
+ );
+ }
+ }
+}
+#endif
+
+/*
+ * - determine space needed to store src string
+ * - allocate or reallocate dst, so that string fits in
+ * - copy string from src to dest
+ */
+void *bootp_strdup_realloc(char *dst,const char *src)
+{
+ size_t len;
+ void *realloc(void * __r, size_t __size);
+
+ if (dst == NULL) {
+ /* first allocation, simply use strdup */
+ if (src)
+ dst = strdup(src);
+ }
+ else {
+ /* already allocated, so use realloc/strcpy */
+ len = src ? strlen(src) + 1 : 0;
+ /* src == NULL tells us to effectively free dst */
+ dst = realloc(dst,len);
+ if (dst != NULL) {
+ strcpy(dst,src);
+ }
+ }
+ return dst;
+}
+
+int
+bootpc_call(call,reply,procp)
+ struct bootp_packet *call;
+ struct bootp_packet *reply; /* output */
+ struct proc *procp;
+{
+ struct socket *so;
+ struct sockaddr_in *sin;
+ struct mbuf *m, *nam;
+ struct uio auio;
+ struct iovec aio;
+ int error, rcvflg, timo, secs, len;
+
+ /* Free at end if not null. */
+ nam = NULL;
+
+ /*
+ * Create socket and set its recieve timeout.
+ */
+ if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0,procp)))
+ goto out;
+
+ m = m_get(M_WAIT, MT_SOOPTS);
+ if (m == NULL) {
+ error = ENOBUFS;
+ goto out;
+ } else {
+ struct timeval *tv;
+ tv = mtod(m, struct timeval *);
+ m->m_len = sizeof(*tv);
+ tv->tv_sec = 1;
+ tv->tv_usec = 0;
+ if ((error = sosetopt(so, SOL_SOCKET, SO_RCVTIMEO, m)))
+ goto out;
+ }
+
+ /*
+ * Enable broadcast.
+ */
+ {
+ int *on;
+ m = m_get(M_WAIT, MT_SOOPTS);
+ if (m == NULL) {
+ error = ENOBUFS;
+ goto out;
+ }
+ on = mtod(m, int *);
+ m->m_len = sizeof(*on);
+ *on = 1;
+ if ((error = sosetopt(so, SOL_SOCKET, SO_BROADCAST, m)))
+ goto out;
+ }
+
+ /*
+ * Bind the local endpoint to a bootp client port.
+ */
+ m = m_getclr(M_WAIT, MT_SONAME);
+ sin = mtod(m, struct sockaddr_in *);
+ sin->sin_len = m->m_len = sizeof(*sin);
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = INADDR_ANY;
+ sin->sin_port = htons(IPPORT_BOOTPC);
+ error = sobind(so, m);
+ m_freem(m);
+ if (error) {
+ printf("bind failed\n");
+ goto out;
+ }
+
+ /*
+ * Setup socket address for the server.
+ */
+ nam = m_get(M_WAIT, MT_SONAME);
+ if (nam == NULL) {
+ error = ENOBUFS;
+ goto out;
+ }
+ sin = mtod(nam, struct sockaddr_in *);
+ sin-> sin_len = sizeof(*sin);
+ sin-> sin_family = AF_INET;
+ sin->sin_addr.s_addr = INADDR_BROADCAST;
+ sin->sin_port = htons(IPPORT_BOOTPS);
+
+ nam->m_len = sizeof(*sin);
+
+ /*
+ * Send it, repeatedly, until a reply is received,
+ * but delay each re-send by an increasing amount.
+ * If the delay hits the maximum, start complaining.
+ */
+ timo = 0;
+ for (;;) {
+ /* Send BOOTP request (or re-send). */
+
+ aio.iov_base = (caddr_t) call;
+ aio.iov_len = sizeof(*call);
+
+ auio.uio_iov = &aio;
+ auio.uio_iovcnt = 1;
+ auio.uio_segflg = UIO_SYSSPACE;
+ auio.uio_rw = UIO_WRITE;
+ auio.uio_offset = 0;
+ auio.uio_resid = sizeof(*call);
+ auio.uio_procp = procp;
+
+ error = sosend(so, nam, &auio, NULL, NULL, 0);
+ if (error) {
+ printf("bootpc_call: sosend: %d\n", error);
+ goto out;
+ }
+
+ /* Determine new timeout. */
+ if (timo < MAX_RESEND_DELAY)
+ timo++;
+ else
+ printf("BOOTP timeout for server 0x%x\n",
+ (int)ntohl(sin->sin_addr.s_addr));
+
+ /*
+ * Wait for up to timo seconds for a reply.
+ * The socket receive timeout was set to 1 second.
+ */
+ secs = timo;
+ while (secs > 0) {
+ aio.iov_base = (caddr_t) reply;
+ aio.iov_len = sizeof(*reply);
+
+ auio.uio_iov = &aio;
+ auio.uio_iovcnt = 1;
+ auio.uio_segflg = UIO_SYSSPACE;
+ auio.uio_rw = UIO_READ;
+ auio.uio_offset = 0;
+ auio.uio_resid = sizeof(*reply);
+ auio.uio_procp = procp;
+
+ rcvflg = 0;
+ error = soreceive(so, NULL, &auio, NULL, NULL, &rcvflg);
+ if (error == EWOULDBLOCK) {
+ secs--;
+ call->secs=htons(ntohs(call->secs)+1);
+ continue;
+ }
+ if (error)
+ goto out;
+ len = sizeof(*reply) - auio.uio_resid;
+
+ /* Do we have the required number of bytes ? */
+ if (len < BOOTP_MIN_LEN)
+ continue;
+
+ /* Is it the right reply? */
+ if (reply->op != 2)
+ continue;
+
+ if (reply->xid != call->xid)
+ continue;
+
+ if (reply->hlen != call->hlen)
+ continue;
+
+ if (bcmp(reply->chaddr,call->chaddr,call->hlen))
+ continue;
+
+ goto gotreply; /* break two levels */
+
+ } /* while secs */
+ } /* forever send/receive */
+
+ error = ETIMEDOUT;
+ goto out;
+
+ gotreply:
+ out:
+ if (nam) m_freem(nam);
+ soclose(so);
+ return error;
+}
+
+int
+bootpc_fakeup_interface(struct ifreq *ireq,struct socket *so,
+ struct proc *procp)
+{
+ struct sockaddr_in *sin;
+ int error;
+ struct sockaddr_in dst;
+ struct sockaddr_in gw;
+ struct sockaddr_in mask;
+
+ /*
+ * Bring up the interface.
+ *
+ * Get the old interface flags and or IFF_UP into them; if
+ * IFF_UP set blindly, interface selection can be clobbered.
+ */
+ error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, procp);
+ if (error)
+ panic("bootpc_fakeup_interface: GIFFLAGS, error=%d", error);
+ ireq->ifr_flags |= IFF_UP;
+ error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, procp);
+ if (error)
+ panic("bootpc_fakeup_interface: SIFFLAGS, error=%d", error);
+
+ /*
+ * Do enough of ifconfig(8) so that the chosen interface
+ * can talk to the servers. (just set the address)
+ */
+
+ /* addr is 0.0.0.0 */
+
+ sin = (struct sockaddr_in *)&ireq->ifr_addr;
+ bzero((caddr_t)sin, sizeof(*sin));
+ sin->sin_len = sizeof(*sin);
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = INADDR_ANY;
+ error = ifioctl(so, SIOCSIFADDR, (caddr_t)ireq, procp);
+ if (error)
+ panic("bootpc_fakeup_interface: set if addr, error=%d", error);
+
+ /* netmask is 0.0.0.0 */
+
+ sin = (struct sockaddr_in *)&ireq->ifr_addr;
+ bzero((caddr_t)sin, sizeof(*sin));
+ sin->sin_len = sizeof(*sin);
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = INADDR_ANY;
+ error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, procp);
+ if (error)
+ panic("bootpc_fakeup_interface: set if net addr, error=%d", error);
+
+ /* Broadcast is 255.255.255.255 */
+
+ sin = (struct sockaddr_in *)&ireq->ifr_addr;
+ bzero((caddr_t)sin, sizeof(*sin));
+ sin->sin_len = sizeof(*sin);
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = INADDR_BROADCAST;
+ error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, procp);
+ if (error)
+ panic("bootpc_fakeup_interface: set if broadcast addr, error=%d", error);
+
+ /* Add default route to 0.0.0.0 so we can send data */
+
+ bzero((caddr_t) &dst, sizeof(dst));
+ dst.sin_len=sizeof(dst);
+ dst.sin_family=AF_INET;
+ dst.sin_addr.s_addr = htonl(0);
+
+ bzero((caddr_t) &gw, sizeof(gw));
+ gw.sin_len=sizeof(gw);
+ gw.sin_family=AF_INET;
+ gw.sin_addr.s_addr = htonl(0x0);
+
+ bzero((caddr_t) &mask, sizeof(mask));
+ mask.sin_len=sizeof(mask);
+ mask.sin_family=AF_INET;
+ mask.sin_addr.s_addr = htonl(0);
+
+ error = rtrequest(RTM_ADD,
+ (struct sockaddr *) &dst,
+ (struct sockaddr *) &gw,
+ (struct sockaddr *) &mask,
+ RTF_UP | RTF_STATIC
+ , NULL);
+ if (error)
+ printf("bootpc_fakeup_interface: add default route, error=%d\n", error);
+ return error;
+}
+
+int
+bootpc_adjust_interface(struct ifreq *ireq,struct socket *so,
+ struct sockaddr_in *myaddr,
+ struct sockaddr_in *netmask,
+ struct sockaddr_in *gw,
+ struct proc *procp)
+{
+ int error;
+ struct sockaddr_in oldgw;
+ struct sockaddr_in olddst;
+ struct sockaddr_in oldmask;
+ struct sockaddr_in *sin;
+
+ /* Remove old default route to 0.0.0.0 */
+
+ bzero((caddr_t) &olddst, sizeof(olddst));
+ olddst.sin_len=sizeof(olddst);
+ olddst.sin_family=AF_INET;
+ olddst.sin_addr.s_addr = INADDR_ANY;
+
+ bzero((caddr_t) &oldgw, sizeof(oldgw));
+ oldgw.sin_len=sizeof(oldgw);
+ oldgw.sin_family=AF_INET;
+ oldgw.sin_addr.s_addr = INADDR_ANY;
+
+ bzero((caddr_t) &oldmask, sizeof(oldmask));
+ oldmask.sin_len=sizeof(oldmask);
+ oldmask.sin_family=AF_INET;
+ oldmask.sin_addr.s_addr = INADDR_ANY;
+
+ error = rtrequest(RTM_DELETE,
+ (struct sockaddr *) &olddst,
+ (struct sockaddr *) &oldgw,
+ (struct sockaddr *) &oldmask,
+ (RTF_UP | RTF_STATIC), NULL);
+ if (error) {
+ printf("nfs_boot: del default route, error=%d\n", error);
+ return error;
+ }
+
+ /*
+ * Do enough of ifconfig(8) so that the chosen interface
+ * can talk to the servers. (just set the address)
+ */
+ bcopy(netmask,&ireq->ifr_addr,sizeof(*netmask));
+ error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, procp);
+ if (error)
+ panic("nfs_boot: set if netmask, error=%d", error);
+
+ /* Broadcast is with host part of IP address all 1's */
+
+ sin = (struct sockaddr_in *)&ireq->ifr_addr;
+ bzero((caddr_t)sin, sizeof(*sin));
+ sin->sin_len = sizeof(*sin);
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = myaddr->sin_addr.s_addr | ~ netmask->sin_addr.s_addr;
+ error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, procp);
+ if (error)
+ panic("bootpc_call: set if broadcast addr, error=%d", error);
+
+ bcopy(myaddr,&ireq->ifr_addr,sizeof(*myaddr));
+ error = ifioctl(so, SIOCSIFADDR, (caddr_t)ireq, procp);
+ if (error)
+ panic("nfs_boot: set if addr, error=%d", error);
+
+ /* Add new default route */
+
+ error = rtrequest(RTM_ADD,
+ (struct sockaddr *) &olddst,
+ (struct sockaddr *) gw,
+ (struct sockaddr *) &oldmask,
+ (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL);
+ if (error) {
+ printf("nfs_boot: add net route, error=%d\n", error);
+ return error;
+ }
+
+ return 0;
+}
+
+#if !defined(__rtems__)
+static int setfs(addr, path, p)
+ struct sockaddr_in *addr;
+ char *path;
+ char *p;
+{
+ unsigned ip = 0;
+ int val;
+
+ if (((val = getdec(&p)) < 0) || (val > 255)) return(0);
+ ip = val << 24;
+ if (*p != '.') return(0);
+ p++;
+ if (((val = getdec(&p)) < 0) || (val > 255)) return(0);
+ ip |= (val << 16);
+ if (*p != '.') return(0);
+ p++;
+ if (((val = getdec(&p)) < 0) || (val > 255)) return(0);
+ ip |= (val << 8);
+ if (*p != '.') return(0);
+ p++;
+ if (((val = getdec(&p)) < 0) || (val > 255)) return(0);
+ ip |= val;
+ if (*p != ':') return(0);
+ p++;
+
+ addr->sin_addr.s_addr = htonl(ip);
+ addr->sin_len = sizeof(struct sockaddr_in);
+ addr->sin_family = AF_INET;
+
+ strncpy(path,p,MNAMELEN-1);
+ return(1);
+}
+#endif
+
+#if !defined(__rtems__)
+static int getdec(ptr)
+ char **ptr;
+{
+ char *p = *ptr;
+ int ret=0;
+ if ((*p < '0') || (*p > '9')) return(-1);
+ while ((*p >= '0') && (*p <= '9')) {
+ ret = ret*10 + (*p - '0');
+ p++;
+ }
+ *ptr = p;
+ return(ret);
+}
+#endif
+
+#if !defined(__rtems__)
+static char *substr(a,b)
+ char *a,*b;
+{
+ char *loc1;
+ char *loc2;
+
+ while (*a != '\0') {
+ loc1 = a;
+ loc2 = b;
+ while (*loc1 == *loc2++) {
+ if (*loc1 == '\0') return (0);
+ loc1++;
+ if (*loc2 == '\0') return (loc1);
+ }
+ a++;
+ }
+ return (0);
+}
+#endif
+
+static void printip(char *prefix,struct in_addr addr)
+{
+ unsigned int ip;
+
+ ip = ntohl(addr.s_addr);
+
+ printf("%s is %d.%d.%d.%d\n",prefix,
+ ip >> 24, (ip >> 16) & 255 ,(ip >> 8) & 255 ,ip & 255 );
+}
+
+static int dhcpOptionOverload = 0;
+static char dhcp_gotgw = 0;
+static char dhcp_gotnetmask = 0;
+static char dhcp_gotserver = 0;
+static char dhcp_gotlogserver = 0;
+static struct sockaddr_in dhcp_netmask;
+static struct sockaddr_in dhcp_gw;
+static char *dhcp_hostname = NULL;
+
+static void
+processOptions (unsigned char *optbuf, int optbufSize)
+{
+ int j = 0;
+ int len;
+ int code, ncode;
+ char *p;
+
+ ncode = optbuf[0];
+ while (j < optbufSize) {
+ code = optbuf[j] = ncode;
+ if (code == 255)
+ return;
+ if (code == 0) {
+ j++;
+ continue;
+ }
+ len = optbuf[j+1];
+ j += 2;
+ if ((len + j) >= optbufSize) {
+ printf ("Truncated field for code %d", code);
+ return;
+ }
+ ncode = optbuf[j+len];
+ optbuf[j+len] = '\0';
+ p = &optbuf[j];
+ j += len;
+
+ /*
+ * Process the option
+ */
+ switch (code) {
+ case 1:
+ /* Subnet mask */
+ if (len!=4)
+ panic("bootpc: subnet mask len is %d",len);
+ bcopy (p, &dhcp_netmask.sin_addr, 4);
+ dhcp_gotnetmask = 1;
+ break;
+
+ case 2:
+ /* Time offset */
+ if (len!=4)
+ panic("bootpc: time offset len is %d",len);
+ bcopy (p, &rtems_bsdnet_timeoffset, 4);
+ rtems_bsdnet_timeoffset = ntohl (rtems_bsdnet_timeoffset);
+ break;
+
+ case 3:
+ /* Routers */
+ if (len % 4)
+ panic ("bootpc: Router Len is %d", len);
+ if (len > 0) {
+ bcopy(p, &dhcp_gw.sin_addr, 4);
+ dhcp_gotgw = 1;
+ }
+ break;
+
+ case 42:
+ /* NTP servers */
+ if (len % 4)
+ panic ("bootpc: time server Len is %d", len);
+ {
+ int tlen = 0;
+ while ((tlen < len) &&
+ (rtems_bsdnet_ntpserver_count < sizeof rtems_bsdnet_config.ntp_server /
+ sizeof rtems_bsdnet_config.ntp_server[0])) {
+ bcopy (p+tlen,
+ &rtems_bsdnet_ntpserver[rtems_bsdnet_ntpserver_count],
+ 4);
+ printip("Time Server",
+ rtems_bsdnet_ntpserver[rtems_bsdnet_ntpserver_count]);
+ rtems_bsdnet_ntpserver_count++;
+ tlen += 4;
+ }
+ }
+ break;
+
+ case 6:
+ /* Domain Name servers */
+ if (len % 4)
+ panic ("bootpc: DNS Len is %d", len);
+ {
+ int dlen = 0;
+ while ((dlen < len) &&
+ (rtems_bsdnet_nameserver_count < sizeof rtems_bsdnet_config.name_server /
+ sizeof rtems_bsdnet_config.name_server[0])) {
+ bcopy (p+dlen,
+ &rtems_bsdnet_nameserver[rtems_bsdnet_nameserver_count],
+ 4);
+ printip("Domain Name Server",
+ rtems_bsdnet_nameserver[rtems_bsdnet_nameserver_count]);
+ rtems_bsdnet_nameserver_count++;
+ dlen += 4;
+ }
+ }
+ break;
+
+ case 12:
+ /* Host name */
+ if (len>=MAXHOSTNAMELEN)
+ panic ("bootpc: hostname >=%d bytes", MAXHOSTNAMELEN);
+ if (sethostname (p, len) < 0)
+ panic("Can't set host name");
+ printf("Hostname is %s\n", p);
+ dhcp_hostname = bootp_strdup_realloc(dhcp_hostname,p);
+ break;
+
+ case 7:
+ /* Log servers */
+ if (len % 4)
+ panic ("bootpc: Log server Len is %d", len);
+ if (len > 0) {
+ bcopy(p, &rtems_bsdnet_log_host_address, 4);
+ dhcp_gotlogserver = 1;
+ }
+ break;
+
+ case 15:
+ /* Domain name */
+ if (p[0]) {
+ rtems_bsdnet_domain_name =
+ bootp_strdup_realloc(rtems_bsdnet_domain_name,p);
+ printf("Domain name is %s\n", rtems_bsdnet_domain_name);
+ }
+ break;
+
+ case 16: /* Swap server IP address. unused */
+ break;
+
+ case 52:
+ /* DHCP option override */
+ if (len != 1)
+ panic ("bootpc: DHCP option overload len is %d", len);
+ dhcpOptionOverload = p[0];
+ break;
+
+ case 128: /* Site-specific option for DHCP servers that
+ * a) don't supply tag 54
+ * and
+ * b) don't supply the server address in siaddr
+ * For example, on Solaris 2.6 in.dhcpd, include in the dhcptab:
+ * Bootsrv s Site,128,IP,1,1
+ * and use that symbol in the macro that defines the client:
+ * Bootsrv=<tftp-server-ip-address>
+ */
+ case 54:
+ /* DHCP server */
+ if (len != 4)
+ panic ("bootpc: DHCP server len is %d", len);
+ bcopy(p, &rtems_bsdnet_bootp_server_address, 4);
+ dhcp_gotserver = 1;
+ break;
+
+ case 66:
+ /* DHCP server name option */
+ if (p[0])
+ rtems_bsdnet_bootp_server_name =
+ bootp_strdup_realloc(rtems_bsdnet_bootp_server_name,p);
+ break;
+
+ case 67:
+ /* DHCP bootfile option */
+ if (p[0])
+ rtems_bsdnet_bootp_boot_file_name =
+ bootp_strdup_realloc(rtems_bsdnet_bootp_boot_file_name,p);
+ break;
+
+ case 129:
+ /* Site specific option; we use this to get
+ * a 'command line string'
+ */
+ if (p[0])
+ rtems_bsdnet_bootp_cmdline = strdup(p);
+ break;
+
+ default:
+ printf ("Ignoring BOOTP/DHCP option code %d\n", code);
+ break;
+ }
+ }
+}
+
+#define EALEN 6
+
+void
+bootpc_init(int update_files)
+{
+ struct bootp_packet call;
+ struct bootp_packet reply;
+ static u_int32_t xid = ~0xFF;
+
+ struct ifreq ireq;
+ struct ifnet *ifp;
+ struct socket *so;
+ int j;
+ int error;
+ struct sockaddr_in myaddr;
+ struct ifaddr *ifa;
+ struct sockaddr_dl *sdl = NULL;
+ char *delim;
+ struct proc *procp = NULL;
+
+ /*
+ * If already filled in, don't touch it here
+ */
+ if (nfs_diskless_valid)
+ return;
+
+ /*
+ * If we are to update the files create the root
+ * file structure.
+ */
+ if (update_files)
+ if (rtems_create_root_fs () < 0) {
+ printf("Error creating the root filesystem.\nFile not created.\n");
+ update_files = 0;
+ }
+
+ if (dhcp_hostname != NULL) {
+ /* free it */
+ dhcp_hostname=bootp_strdup_realloc(dhcp_hostname,0);
+ }
+
+ /*
+ * Find a network interface.
+ */
+ for (ifp = ifnet; ifp != 0; ifp = ifp->if_next)
+ if ((ifp->if_flags &
+ (IFF_LOOPBACK|IFF_POINTOPOINT)) == 0)
+ break;
+ if (ifp == NULL)
+ panic("bootpc_init: no suitable interface");
+ bzero(&ireq,sizeof(ireq));
+ sprintf(ireq.ifr_name, "%s%d", ifp->if_name,ifp->if_unit);
+ printf("bootpc_init: using network interface '%s'\n",
+ ireq.ifr_name);
+
+ if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0,procp)) != 0)
+ panic("nfs_boot: socreate, error=%d", error);
+
+ bootpc_fakeup_interface(&ireq,so,procp);
+
+ printf("Bootpc testing starting\n");
+
+ /* Get HW address */
+
+ for (ifa = ifp->if_addrlist;ifa; ifa = ifa->ifa_next)
+ if (ifa->ifa_addr->sa_family == AF_LINK &&
+ (sdl = ((struct sockaddr_dl *) ifa->ifa_addr)) &&
+ sdl->sdl_type == IFT_ETHER)
+ break;
+
+ if (!sdl)
+ panic("bootpc: Unable to find HW address");
+ if (sdl->sdl_alen != EALEN )
+ panic("bootpc: HW address len is %d, expected value is %d",
+ sdl->sdl_alen,EALEN);
+
+ printf("bootpc hw address is ");
+ delim="";
+ for (j=0;j<sdl->sdl_alen;j++) {
+ printf("%s%x",delim,((unsigned char *)LLADDR(sdl))[j]);
+ delim=":";
+ }
+ printf("\n");
+
+#if 0
+ bootpboot_p_iflist();
+ bootpboot_p_rtlist();
+#endif
+
+ bzero((caddr_t) &call, sizeof(call));
+
+ /* bootpc part */
+ call.op = 1; /* BOOTREQUEST */
+ call.htype= 1; /* 10mb ethernet */
+ call.hlen=sdl->sdl_alen; /* Hardware address length */
+ call.hops=0;
+ xid++;
+ call.xid = txdr_unsigned(xid);
+ bcopy(LLADDR(sdl),&call.chaddr,sdl->sdl_alen);
+
+ call.vend[0]=99;
+ call.vend[1]=130;
+ call.vend[2]=83;
+ call.vend[3]=99;
+ call.vend[4]=255;
+
+ call.secs = 0;
+ call.flags = htons(0x8000); /* We need an broadcast answer */
+
+ error = bootpc_call(&call,&reply,procp);
+
+ if (error)
+ panic("BOOTP call failed -- error %d", error);
+
+ /*
+ * Initialize network address structures
+ */
+ bzero(&myaddr,sizeof(myaddr));
+ bzero(&dhcp_netmask,sizeof(dhcp_netmask));
+ bzero(&dhcp_gw,sizeof(dhcp_gw));
+ myaddr.sin_len = sizeof(myaddr);
+ myaddr.sin_family = AF_INET;
+ dhcp_netmask.sin_len = sizeof(dhcp_netmask);
+ dhcp_netmask.sin_family = AF_INET;
+ dhcp_gw.sin_len = sizeof(dhcp_gw);
+ dhcp_gw.sin_family= AF_INET;
+
+ /*
+ * Set our address
+ */
+ myaddr.sin_addr = reply.yiaddr;
+ printip("My ip address",myaddr.sin_addr);
+
+ /*
+ * Process BOOTP/DHCP options
+ */
+ if (reply.vend[0]==99 && reply.vend[1]==130 &&
+ reply.vend[2]==83 && reply.vend[3]==99) {
+ processOptions (&reply.vend[4], sizeof(reply.vend) - 4);
+ }
+ if (dhcpOptionOverload & 1) {
+ processOptions (reply.file, sizeof reply.file);
+ }
+ else {
+ if (reply.file[0])
+ rtems_bsdnet_bootp_boot_file_name =
+ bootp_strdup_realloc(rtems_bsdnet_bootp_boot_file_name,reply.file);
+ }
+ if (dhcpOptionOverload & 2) {
+ processOptions (reply.sname, sizeof reply.sname);
+ }
+ else {
+ if (reply.sname[0])
+ rtems_bsdnet_bootp_server_name =
+ bootp_strdup_realloc(rtems_bsdnet_bootp_server_name,reply.sname);
+ }
+ if (rtems_bsdnet_bootp_server_name)
+ printf ("Server name is %s\n", rtems_bsdnet_bootp_server_name);
+ if (rtems_bsdnet_bootp_boot_file_name)
+ printf ("Boot file is %s\n", rtems_bsdnet_bootp_boot_file_name);
+ if (rtems_bsdnet_bootp_cmdline)
+ printf ("Command line is %s\n", rtems_bsdnet_bootp_cmdline);
+
+ /*
+ * Use defaults if values were not supplied by BOOTP/DHCP options
+ */
+ if (!dhcp_gotnetmask) {
+ if (IN_CLASSA(ntohl(myaddr.sin_addr.s_addr)))
+ dhcp_netmask.sin_addr.s_addr = htonl(IN_CLASSA_NET);
+ else if (IN_CLASSB(ntohl(myaddr.sin_addr.s_addr)))
+ dhcp_netmask.sin_addr.s_addr = htonl(IN_CLASSB_NET);
+ else
+ dhcp_netmask.sin_addr.s_addr = htonl(IN_CLASSC_NET);
+ }
+ printip ("Subnet mask", dhcp_netmask.sin_addr);
+ if (!dhcp_gotserver)
+ rtems_bsdnet_bootp_server_address = reply.siaddr;
+ printip ("Server ip address" ,rtems_bsdnet_bootp_server_address);
+ if (!dhcp_gotgw)
+ dhcp_gw.sin_addr = reply.giaddr;
+ printip ("Gateway ip address", dhcp_gw.sin_addr);
+ if (!dhcp_gotlogserver)
+ rtems_bsdnet_log_host_address = rtems_bsdnet_bootp_server_address;
+ printip ("Log server ip address", rtems_bsdnet_log_host_address);
+
+ /*
+ * Update the files if we are asked too.
+ */
+ if (update_files) {
+ char *dn = rtems_bsdnet_domain_name;
+ char *hn = dhcp_hostname;
+ if (!dn)
+ dn = "mydomain";
+ if (!hn)
+ hn = "me";
+ rtems_rootfs_append_host_rec(*((unsigned long*) &myaddr.sin_addr), hn, dn);
+
+ /*
+ * Should the given domainname be used here ?
+ */
+ if (dhcp_gotserver) {
+ if (rtems_bsdnet_bootp_server_name)
+ hn = rtems_bsdnet_bootp_server_name;
+ else
+ hn = "bootps";
+ rtems_rootfs_append_host_rec(*((unsigned long *) &rtems_bsdnet_bootp_server_address),
+ hn, dn);
+ }
+
+ if (dhcp_gotlogserver) {
+ rtems_rootfs_append_host_rec(*((unsigned long *) &rtems_bsdnet_log_host_address),
+ "logs", dn);
+ }
+
+ /*
+ * Setup the DNS configuration file /etc/resolv.conf.
+ */
+ if (rtems_bsdnet_nameserver_count) {
+ int i;
+ char buf[64];
+ const char *bufl[1];
+
+ bufl[0] = buf;
+
+#define MKFILE_MODE (S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH)
+
+ if (rtems_bsdnet_domain_name &&
+ (strlen(rtems_bsdnet_domain_name) < (sizeof(buf) - 1))) {
+ strcpy(buf, "search ");
+ strcat(buf, rtems_bsdnet_domain_name);
+ strcat(buf, "\n");
+ rtems_rootfs_file_append ("/etc/resolv.conf", MKFILE_MODE, 1, bufl);
+ }
+
+ for (i = 0; i < rtems_bsdnet_nameserver_count; i++) {
+ strcpy(buf, "nameserver ");
+ strcat(buf, inet_ntoa(rtems_bsdnet_ntpserver[i]));
+ strcat(buf, "\n");
+ if (rtems_rootfs_file_append ("/etc/resolv.conf", MKFILE_MODE, 1, bufl))
+ break;
+ }
+ }
+ }
+
+ /*
+ * Configure the interface with the new settings
+ */
+ error = bootpc_adjust_interface(&ireq,so,
+ &myaddr,&dhcp_netmask,&dhcp_gw,procp);
+ soclose(so);
+}
diff --git a/cpukit/libnetworking/nfs/krpc.h b/cpukit/libnetworking/nfs/krpc.h
new file mode 100644
index 0000000000..8a21392657
--- /dev/null
+++ b/cpukit/libnetworking/nfs/krpc.h
@@ -0,0 +1,26 @@
+/* $NetBSD: krpc.h,v 1.4 1995/12/19 23:07:11 cgd Exp $ */
+/* $Id$ */
+
+#include <sys/cdefs.h>
+
+int krpc_call __P((struct sockaddr_in *sin,
+ u_int prog, u_int vers, u_int func,
+ struct mbuf **data, struct mbuf **from, struct proc *procp));
+
+int krpc_portmap __P((struct sockaddr_in *sin,
+ u_int prog, u_int vers, u_int16_t *portp, struct proc *procp));
+
+struct mbuf *xdr_string_encode __P((char *str, int len));
+
+/*
+ * RPC definitions for the portmapper
+ */
+#define PMAPPORT 111
+#define PMAPPROG 100000
+#define PMAPVERS 2
+#define PMAPPROC_NULL 0
+#define PMAPPROC_SET 1
+#define PMAPPROC_UNSET 2
+#define PMAPPROC_GETPORT 3
+#define PMAPPROC_DUMP 4
+#define PMAPPROC_CALLIT 5
diff --git a/cpukit/libnetworking/nfs/nfs.h b/cpukit/libnetworking/nfs/nfs.h
new file mode 100644
index 0000000000..afa7593278
--- /dev/null
+++ b/cpukit/libnetworking/nfs/nfs.h
@@ -0,0 +1,620 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Rick Macklem at The University of Guelph.
+ *
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)nfs.h 8.1 (Berkeley) 6/10/93
+ * $Id$
+ */
+
+#ifndef _NFS_NFS_H_
+#define _NFS_NFS_H_
+
+#include <nfs/rpcv2.h>
+
+/*
+ * Tunable constants for nfs
+ */
+
+#define NFS_MAXIOVEC 34
+#define NFS_TICKINTVL 5 /* Desired time for a tick (msec) */
+#define NFS_HZ (hz / nfs_ticks) /* Ticks/sec */
+#define NFS_TIMEO (1 * NFS_HZ) /* Default timeout = 1 second */
+#define NFS_MINTIMEO (1 * NFS_HZ) /* Min timeout to use */
+#define NFS_MAXTIMEO (60 * NFS_HZ) /* Max timeout to backoff to */
+#define NFS_MINIDEMTIMEO (5 * NFS_HZ) /* Min timeout for non-idempotent ops*/
+#define NFS_MAXREXMIT 100 /* Stop counting after this many */
+#define NFS_MAXWINDOW 1024 /* Max number of outstanding requests */
+#define NFS_RETRANS 10 /* Num of retrans for soft mounts */
+#define NFS_MAXGRPS 16 /* Max. size of groups list */
+#ifndef NFS_MINATTRTIMO
+#define NFS_MINATTRTIMO 5 /* Attribute cache timeout in sec */
+#endif
+#ifndef NFS_MAXATTRTIMO
+#define NFS_MAXATTRTIMO 60
+#endif
+#define NFS_WSIZE 8192 /* Def. write data size <= 8192 */
+#define NFS_RSIZE 8192 /* Def. read data size <= 8192 */
+#define NFS_READDIRSIZE 8192 /* Def. readdir size */
+#define NFS_DEFRAHEAD 1 /* Def. read ahead # blocks */
+#define NFS_MAXRAHEAD 4 /* Max. read ahead # blocks */
+#define NFS_MAXUIDHASH 64 /* Max. # of hashed uid entries/mp */
+#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runnable */
+#define NFS_MAXGATHERDELAY 100 /* Max. write gather delay (msec) */
+#ifndef NFS_GATHERDELAY
+#define NFS_GATHERDELAY 10 /* Default write gather delay (msec) */
+#endif
+#define NFS_DIRBLKSIZ 4096 /* Must be a multiple of DIRBLKSIZ */
+
+/*
+ * Oddballs
+ */
+#define NMOD(a) ((a) % nfs_asyncdaemons)
+#define NFS_CMPFH(n, f, s) \
+ ((n)->n_fhsize == (s) && !bcmp((caddr_t)(n)->n_fhp, (caddr_t)(f), (s)))
+#define NFS_ISV3(v) (VFSTONFS((v)->v_mount)->nm_flag & NFSMNT_NFSV3)
+#define NFS_SRVMAXDATA(n) \
+ (((n)->nd_flag & ND_NFSV3) ? (((n)->nd_nam2) ? \
+ NFS_MAXDGRAMDATA : NFS_MAXDATA) : NFS_V2MAXDATA)
+
+/*
+ * XXX
+ * sys/buf.h should be edited to change B_APPENDWRITE --> B_NEEDCOMMIT, but
+ * until then...
+ * Same goes for sys/malloc.h, which needs M_NFSDIROFF,
+ * M_NFSRVDESC and M_NFSBIGFH added.
+ * The VA_EXCLUSIVE flag should be added for va_vaflags and set for an
+ * exclusive create.
+ * The B_INVAFTERWRITE flag should be set to whatever is required by the
+ * buffer cache code to say "Invalidate the block after it is written back".
+ */
+#ifndef B_NEEDCOMMIT
+#define B_NEEDCOMMIT B_APPENDWRITE
+#endif
+#ifndef M_NFSRVDESC
+#define M_NFSRVDESC M_TEMP
+#endif
+#ifndef M_NFSDIROFF
+#define M_NFSDIROFF M_TEMP
+#endif
+#ifndef M_NFSBIGFH
+#define M_NFSBIGFH M_TEMP
+#endif
+#ifndef VA_EXCLUSIVE
+#define VA_EXCLUSIVE 0
+#endif
+#ifdef __FreeBSD__
+#define B_INVAFTERWRITE B_NOCACHE
+#else
+#define B_INVAFTERWRITE B_INVAL
+#endif
+
+/*
+ * These ifdefs try to handle the differences between the various 4.4BSD-Lite
+ * based vfs interfaces.
+ * btw: NetBSD-current does have a VOP_LEASDE(), but I don't know how to
+ * differentiate between NetBSD-1.0 and NetBSD-current, so..
+ * I also don't know about BSDi's 2.0 release.
+ */
+#if !defined(HAS_VOPLEASE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
+#define HAS_VOPLEASE 1
+#endif
+#if !defined(HAS_VOPREVOKE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
+#define HAS_VOPREVOKE 1
+#endif
+
+/*
+ * The IO_METASYNC flag should be implemented for local file systems.
+ * (Until then, it is nothin at all.)
+ */
+#ifndef IO_METASYNC
+#define IO_METASYNC 0
+#endif
+
+/*
+ * Set the attribute timeout based on how recently the file has been modified.
+ */
+#define NFS_ATTRTIMEO(np) \
+ ((((np)->n_flag & NMODIFIED) || \
+ (time.tv_sec - (np)->n_mtime) / 10 < NFS_MINATTRTIMO) ? NFS_MINATTRTIMO : \
+ ((time.tv_sec - (np)->n_mtime) / 10 > NFS_MAXATTRTIMO ? NFS_MAXATTRTIMO : \
+ (time.tv_sec - (np)->n_mtime) / 10))
+
+/*
+ * Expected allocation sizes for major data structures. If the actual size
+ * of the structure exceeds these sizes, then malloc() will be allocating
+ * almost twice the memory required. This is used in nfs_init() to warn
+ * the sysadmin that the size of a structure should be reduced.
+ * (These sizes are always a power of 2. If the kernel malloc() changes
+ * to one that does not allocate space in powers of 2 size, then this all
+ * becomes bunk!)
+ */
+#define NFS_NODEALLOC 256
+#define NFS_MNTALLOC 512
+#define NFS_SVCALLOC 256
+#define NFS_UIDALLOC 128
+
+/*
+ * Structures for the nfssvc(2) syscall. Not that anyone but nfsd and mount_nfs
+ * should ever try and use it.
+ */
+struct nfsd_args {
+ int sock; /* Socket to serve */
+ caddr_t name; /* Client address for connection based sockets */
+ int namelen; /* Length of name */
+};
+
+struct nfsd_srvargs {
+ struct nfsd *nsd_nfsd; /* Pointer to in kernel nfsd struct */
+ uid_t nsd_uid; /* Effective uid mapped to cred */
+ u_long nsd_haddr; /* Ip address of client */
+ struct ucred nsd_cr; /* Cred. uid maps to */
+ int nsd_authlen; /* Length of auth string (ret) */
+ u_char *nsd_authstr; /* Auth string (ret) */
+ int nsd_verflen; /* and the verfier */
+ u_char *nsd_verfstr;
+ struct timeval nsd_timestamp; /* timestamp from verifier */
+ u_long nsd_ttl; /* credential ttl (sec) */
+ NFSKERBKEY_T nsd_key; /* Session key */
+};
+
+struct nfsd_cargs {
+ char *ncd_dirp; /* Mount dir path */
+ uid_t ncd_authuid; /* Effective uid */
+ int ncd_authtype; /* Type of authenticator */
+ int ncd_authlen; /* Length of authenticator string */
+ u_char *ncd_authstr; /* Authenticator string */
+ int ncd_verflen; /* and the verifier */
+ u_char *ncd_verfstr;
+ NFSKERBKEY_T ncd_key; /* Session key */
+};
+
+/*
+ * Stats structure
+ */
+struct nfsstats {
+ int attrcache_hits;
+ int attrcache_misses;
+ int lookupcache_hits;
+ int lookupcache_misses;
+ int direofcache_hits;
+ int direofcache_misses;
+ int biocache_reads;
+ int read_bios;
+ int read_physios;
+ int biocache_writes;
+ int write_bios;
+ int write_physios;
+ int biocache_readlinks;
+ int readlink_bios;
+ int biocache_readdirs;
+ int readdir_bios;
+ int rpccnt[NFS_NPROCS];
+ int rpcretries;
+ int srvrpccnt[NFS_NPROCS];
+ int srvrpc_errs;
+ int srv_errs;
+ int rpcrequests;
+ int rpctimeouts;
+ int rpcunexpected;
+ int rpcinvalid;
+ int srvcache_inproghits;
+ int srvcache_idemdonehits;
+ int srvcache_nonidemdonehits;
+ int srvcache_misses;
+ int srvnqnfs_leases;
+ int srvnqnfs_maxleases;
+ int srvnqnfs_getleases;
+ int srvvop_writes;
+};
+
+/*
+ * Flags for nfssvc() system call.
+ */
+#define NFSSVC_BIOD 0x002
+#define NFSSVC_NFSD 0x004
+#define NFSSVC_ADDSOCK 0x008
+#define NFSSVC_AUTHIN 0x010
+#define NFSSVC_GOTAUTH 0x040
+#define NFSSVC_AUTHINFAIL 0x080
+#define NFSSVC_MNTD 0x100
+
+/*
+ * fs.nfs sysctl(3) identifiers
+ */
+#define NFS_NFSSTATS 1 /* struct: struct nfsstats */
+#define NFS_NFSPRIVPORT 2 /* int: prohibit nfs to resvports */
+
+#define FS_NFS_NAMES { \
+ { 0, 0 }, \
+ { "nfsstats", CTLTYPE_STRUCT }, \
+ { "nfsprivport", CTLTYPE_INT }, \
+}
+
+/*
+ * The set of signals the interrupt an I/O in progress for NFSMNT_INT mounts.
+ * What should be in this set is open to debate, but I believe that since
+ * I/O system calls on ufs are never interrupted by signals the set should
+ * be minimal. My reasoning is that many current programs that use signals
+ * such as SIGALRM will not expect file I/O system calls to be interrupted
+ * by them and break.
+ */
+#if defined(_KERNEL) || defined(_KERNEL)
+
+struct uio; struct buf; struct vattr; struct nameidata; /* XXX */
+
+#define NFSINT_SIGMASK (sigmask(SIGINT)|sigmask(SIGTERM)|sigmask(SIGKILL)| \
+ sigmask(SIGHUP)|sigmask(SIGQUIT))
+
+/*
+ * Socket errors ignored for connectionless sockets??
+ * For now, ignore them all
+ */
+#define NFSIGNORE_SOERROR(s, e) \
+ ((e) != EINTR && (e) != ERESTART && (e) != EWOULDBLOCK && \
+ ((s) & PR_CONNREQUIRED) == 0)
+
+/*
+ * Nfs outstanding request list element
+ */
+struct nfsreq {
+ TAILQ_ENTRY(nfsreq) r_chain;
+ struct mbuf *r_mreq;
+ struct mbuf *r_mrep;
+ struct mbuf *r_md;
+ caddr_t r_dpos;
+ struct nfsmount *r_nmp;
+ struct vnode *r_vp;
+ u_long r_xid;
+ int r_flags; /* flags on request, see below */
+ int r_retry; /* max retransmission count */
+ int r_rexmit; /* current retrans count */
+ int r_timer; /* tick counter on reply */
+ int r_procnum; /* NFS procedure number */
+ int r_rtt; /* RTT for rpc */
+ struct proc *r_procp; /* Proc that did I/O system call */
+};
+
+/*
+ * Queue head for nfsreq's
+ */
+extern TAILQ_HEAD(nfs_reqq, nfsreq) nfs_reqq;
+
+/* Flag values for r_flags */
+#define R_TIMING 0x01 /* timing request (in mntp) */
+#define R_SENT 0x02 /* request has been sent */
+#define R_SOFTTERM 0x04 /* soft mnt, too many retries */
+#define R_INTR 0x08 /* intr mnt, signal pending */
+#define R_SOCKERR 0x10 /* Fatal error on socket */
+#define R_TPRINTFMSG 0x20 /* Did a tprintf msg. */
+#define R_MUSTRESEND 0x40 /* Must resend request */
+#define R_GETONEREP 0x80 /* Probe for one reply only */
+
+/*
+ * A list of nfssvc_sock structures is maintained with all the sockets
+ * that require service by the nfsd.
+ * The nfsuid structs hang off of the nfssvc_sock structs in both lru
+ * and uid hash lists.
+ */
+#ifndef NFS_UIDHASHSIZ
+#define NFS_UIDHASHSIZ 29 /* Tune the size of nfssvc_sock with this */
+#endif
+#define NUIDHASH(sock, uid) \
+ (&(sock)->ns_uidhashtbl[(uid) % NFS_UIDHASHSIZ])
+#ifndef NFS_WDELAYHASHSIZ
+#define NFS_WDELAYHASHSIZ 16 /* and with this */
+#endif
+#define NWDELAYHASH(sock, f) \
+ (&(sock)->ns_wdelayhashtbl[(*((u_long *)(f))) % NFS_WDELAYHASHSIZ])
+#ifndef NFS_MUIDHASHSIZ
+#define NFS_MUIDHASHSIZ 63 /* Tune the size of nfsmount with this */
+#endif
+#define NMUIDHASH(nmp, uid) \
+ (&(nmp)->nm_uidhashtbl[(uid) % NFS_MUIDHASHSIZ])
+#define NFSNOHASH(fhsum) \
+ (&nfsnodehashtbl[(fhsum) & nfsnodehash])
+
+/*
+ * Network address hash list element
+ */
+union nethostaddr {
+ u_long had_inetaddr;
+ struct mbuf *had_nam;
+};
+
+struct nfsuid {
+ TAILQ_ENTRY(nfsuid) nu_lru; /* LRU chain */
+ LIST_ENTRY(nfsuid) nu_hash; /* Hash list */
+ int nu_flag; /* Flags */
+ union nethostaddr nu_haddr; /* Host addr. for dgram sockets */
+ struct ucred nu_cr; /* Cred uid mapped to */
+ int nu_expire; /* Expiry time (sec) */
+ struct timeval nu_timestamp; /* Kerb. timestamp */
+ u_long nu_nickname; /* Nickname on server */
+ NFSKERBKEY_T nu_key; /* and session key */
+};
+
+#define nu_inetaddr nu_haddr.had_inetaddr
+#define nu_nam nu_haddr.had_nam
+/* Bits for nu_flag */
+#define NU_INETADDR 0x1
+#define NU_NAM 0x2
+#define NU_NETFAM(u) (((u)->nu_flag & NU_INETADDR) ? AF_INET : AF_ISO)
+
+struct nfssvc_sock {
+ TAILQ_ENTRY(nfssvc_sock) ns_chain; /* List of all nfssvc_sock's */
+ TAILQ_HEAD(, nfsuid) ns_uidlruhead;
+ struct file *ns_fp;
+ struct socket *ns_so;
+ struct mbuf *ns_nam;
+ struct mbuf *ns_raw;
+ struct mbuf *ns_rawend;
+ struct mbuf *ns_rec;
+ struct mbuf *ns_recend;
+ struct mbuf *ns_frag;
+ int ns_flag;
+ int ns_solock;
+ int ns_cc;
+ int ns_reclen;
+ int ns_numuids;
+ u_long ns_sref;
+ LIST_HEAD(, nfsrv_descript) ns_tq; /* Write gather lists */
+ LIST_HEAD(, nfsuid) ns_uidhashtbl[NFS_UIDHASHSIZ];
+ LIST_HEAD(nfsrvw_delayhash, nfsrv_descript) ns_wdelayhashtbl[NFS_WDELAYHASHSIZ];
+};
+
+/* Bits for "ns_flag" */
+#define SLP_VALID 0x01
+#define SLP_DOREC 0x02
+#define SLP_NEEDQ 0x04
+#define SLP_DISCONN 0x08
+#define SLP_GETSTREAM 0x10
+#define SLP_LASTFRAG 0x20
+#define SLP_ALLFLAGS 0xff
+
+extern TAILQ_HEAD(nfssvc_sockhead, nfssvc_sock) nfssvc_sockhead;
+extern int nfssvc_sockhead_flag;
+#define SLP_INIT 0x01
+#define SLP_WANTINIT 0x02
+
+/*
+ * One of these structures is allocated for each nfsd.
+ */
+struct nfsd {
+ TAILQ_ENTRY(nfsd) nfsd_chain; /* List of all nfsd's */
+ int nfsd_flag; /* NFSD_ flags */
+ struct nfssvc_sock *nfsd_slp; /* Current socket */
+ int nfsd_authlen; /* Authenticator len */
+ u_char nfsd_authstr[RPCAUTH_MAXSIZ]; /* Authenticator data */
+ int nfsd_verflen; /* and the Verifier */
+ u_char nfsd_verfstr[RPCVERF_MAXSIZ];
+ struct proc *nfsd_procp; /* Proc ptr */
+ struct nfsrv_descript *nfsd_nd; /* Associated nfsrv_descript */
+};
+
+/* Bits for "nfsd_flag" */
+#define NFSD_WAITING 0x01
+#define NFSD_REQINPROG 0x02
+#define NFSD_NEEDAUTH 0x04
+#define NFSD_AUTHFAIL 0x08
+
+/*
+ * This structure is used by the server for describing each request.
+ * Some fields are used only when write request gathering is performed.
+ */
+struct nfsrv_descript {
+ u_quad_t nd_time; /* Write deadline (usec) */
+ off_t nd_off; /* Start byte offset */
+ off_t nd_eoff; /* and end byte offset */
+ LIST_ENTRY(nfsrv_descript) nd_hash; /* Hash list */
+ LIST_ENTRY(nfsrv_descript) nd_tq; /* and timer list */
+ LIST_HEAD(,nfsrv_descript) nd_coalesce; /* coalesced writes */
+ struct mbuf *nd_mrep; /* Request mbuf list */
+ struct mbuf *nd_md; /* Current dissect mbuf */
+ struct mbuf *nd_mreq; /* Reply mbuf list */
+ struct mbuf *nd_nam; /* and socket addr */
+ struct mbuf *nd_nam2; /* return socket addr */
+ caddr_t nd_dpos; /* Current dissect pos */
+ int nd_procnum; /* RPC # */
+ int nd_stable; /* storage type */
+ int nd_flag; /* nd_flag */
+ int nd_len; /* Length of this write */
+ int nd_repstat; /* Reply status */
+ u_long nd_retxid; /* Reply xid */
+ u_long nd_duration; /* Lease duration */
+ struct timeval nd_starttime; /* Time RPC initiated */
+ fhandle_t nd_fh; /* File handle */
+ struct ucred nd_cr; /* Credentials */
+};
+
+/* Bits for "nd_flag" */
+#define ND_READ LEASE_READ
+#define ND_WRITE LEASE_WRITE
+#define ND_CHECK 0x04
+#define ND_LEASE (ND_READ | ND_WRITE | ND_CHECK)
+#define ND_NFSV3 0x08
+#define ND_NQNFS 0x10
+#define ND_KERBNICK 0x20
+#define ND_KERBFULL 0x40
+#define ND_KERBAUTH (ND_KERBNICK | ND_KERBFULL)
+
+extern TAILQ_HEAD(nfsd_head, nfsd) nfsd_head;
+extern int nfsd_head_flag;
+#define NFSD_CHECKSLP 0x01
+
+/*
+ * These macros compare nfsrv_descript structures.
+ */
+#define NFSW_CONTIG(o, n) \
+ ((o)->nd_eoff >= (n)->nd_off && \
+ !bcmp((caddr_t)&(o)->nd_fh, (caddr_t)&(n)->nd_fh, NFSX_V3FH))
+
+#define NFSW_SAMECRED(o, n) \
+ (((o)->nd_flag & ND_KERBAUTH) == ((n)->nd_flag & ND_KERBAUTH) && \
+ !bcmp((caddr_t)&(o)->nd_cr, (caddr_t)&(n)->nd_cr, \
+ sizeof (struct ucred)))
+
+int nfs_reply __P((struct nfsreq *));
+int nfs_getreq __P((struct nfsrv_descript *,struct nfsd *,int));
+int nfs_send __P((struct socket *,struct mbuf *,struct mbuf *,struct nfsreq *));
+int nfs_rephead __P((int,struct nfsrv_descript *,struct nfssvc_sock *,int,int,u_quad_t *,struct mbuf **,struct mbuf **,caddr_t *));
+int nfs_sndlock __P((int *,struct nfsreq *));
+void nfs_sndunlock __P((int *flagp));
+int nfs_disct __P((struct mbuf **,caddr_t *,int,int,caddr_t *));
+int nfs_vinvalbuf __P((struct vnode *,int,struct ucred *,struct proc *,int));
+int nfs_readrpc __P((struct vnode *,struct uio *,struct ucred *));
+int nfs_writerpc __P((struct vnode *,struct uio *,struct ucred *,int *,int *));
+int nfs_readdirrpc __P((register struct vnode *,struct uio *,struct ucred *));
+int nfs_asyncio __P((struct buf *,struct ucred *));
+int nfs_doio __P((struct buf *,struct ucred *,struct proc *));
+int nfs_readlinkrpc __P((struct vnode *,struct uio *,struct ucred *));
+int nfs_sigintr __P((struct nfsmount *,struct nfsreq *r,struct proc *));
+int nfs_readdirplusrpc __P((struct vnode *,register struct uio *,struct ucred *));
+int nfsm_disct __P((struct mbuf **,caddr_t *,int,int,caddr_t *));
+void nfsm_srvfattr __P((struct nfsrv_descript *,struct vattr *,struct nfs_fattr *));
+void nfsm_srvwcc __P((struct nfsrv_descript *,int,struct vattr *,int,struct vattr *,struct mbuf **,char **));
+void nfsm_srvpostopattr __P((struct nfsrv_descript *,int,struct vattr *,struct mbuf **,char **));
+int netaddr_match __P((int,union nethostaddr *,struct mbuf *));
+int nfs_request __P((struct vnode *,struct mbuf *,int,struct proc *,struct ucred *,struct mbuf **,struct mbuf **,caddr_t *));
+int nfs_loadattrcache __P((struct vnode **,struct mbuf **,caddr_t *,struct vattr *));
+int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct vnode **,struct proc *,int));
+void nfsm_adj __P((struct mbuf *,int,int));
+int nfsm_mbuftouio __P((struct mbuf **,struct uio *,int,caddr_t *));
+void nfsrv_initcache __P((void));
+int nfs_getauth __P((struct nfsmount *,struct nfsreq *,struct ucred *,char **,int *,char *,int *,NFSKERBKEY_T));
+int nfs_getnickauth __P((struct nfsmount *,struct ucred *,char **,int *,char *,int));
+int nfs_savenickauth __P((struct nfsmount *,struct ucred *,int,NFSKERBKEY_T,struct mbuf **,char **,struct mbuf *));
+int nfs_adv __P((struct mbuf **,caddr_t *,int,int));
+void nfs_nhinit __P((void));
+void nfs_timer __P((void*));
+u_long nfs_hash __P((nfsfh_t *,int));
+void nfsrv_slpderef __P((struct nfssvc_sock *slp));
+int nfsrv_dorec __P((struct nfssvc_sock *,struct nfsd *,struct nfsrv_descript **));
+void nfsrv_cleancache __P((void));
+int nfsrv_getcache __P((struct nfsrv_descript *,struct nfssvc_sock *,struct mbuf **));
+int nfs_init __P((void));
+void nfsrv_updatecache __P((struct nfsrv_descript *,int,struct mbuf *));
+int nfs_connect __P((struct nfsmount *,struct nfsreq *));
+void nfs_disconnect __P((struct nfsmount *nmp));
+int nfs_getattrcache __P((struct vnode *,struct vattr *));
+int nfsm_strtmbuf __P((struct mbuf **,char **,char *,long));
+int nfs_bioread __P((struct vnode *,struct uio *,int,struct ucred *, int getpages));
+int nfsm_uiotombuf __P((struct uio *,struct mbuf **,int,caddr_t *));
+void nfsrv_init __P((int));
+void nfs_clearcommit __P((struct mount *));
+int nfsrv_errmap __P((struct nfsrv_descript *, int));
+void nfsrv_rcv __P((struct socket *so, caddr_t arg, int waitflag));
+void nfsrvw_sort __P((gid_t [],int));
+void nfsrv_setcred __P((struct ucred *,struct ucred *));
+int nfs_writebp __P((struct buf *,int));
+int nfsrv_object_create __P(( struct vnode * ));
+void nfsrv_wakenfsd __P((struct nfssvc_sock *slp));
+int nfsrv_writegather __P((struct nfsrv_descript **, struct nfssvc_sock *,
+ struct proc *, struct mbuf **));
+int nfs_fsinfo __P((struct nfsmount *, struct vnode *, struct ucred *,
+ struct proc *p));
+
+int nfsrv3_access __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct proc *procp, struct mbuf **mrq));
+int nfsrv_commit __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct proc *procp, struct mbuf **mrq));
+int nfsrv_create __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct proc *procp, struct mbuf **mrq));
+int nfsrv_fhtovp __P((fhandle_t *,int,struct vnode **,
+ struct ucred *,struct nfssvc_sock *,struct mbuf *,
+ int *,int));
+int nfsrv_fsinfo __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct proc *procp, struct mbuf **mrq));
+int nfsrv_getattr __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct proc *procp, struct mbuf **mrq));
+int nfsrv_link __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct proc *procp, struct mbuf **mrq));
+int nfsrv_lookup __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct proc *procp, struct mbuf **mrq));
+int nfsrv_mkdir __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct proc *procp, struct mbuf **mrq));
+int nfsrv_mknod __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct proc *procp, struct mbuf **mrq));
+int nfsrv_noop __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct proc *procp, struct mbuf **mrq));
+int nfsrv_null __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct proc *procp, struct mbuf **mrq));
+int nfsrv_pathconf __P((struct nfsrv_descript *nfsd,
+ struct nfssvc_sock *slp, struct proc *procp,
+ struct mbuf **mrq));
+int nfsrv_read __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct proc *procp, struct mbuf **mrq));
+int nfsrv_readdir __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct proc *procp, struct mbuf **mrq));
+int nfsrv_readdirplus __P((struct nfsrv_descript *nfsd,
+ struct nfssvc_sock *slp, struct proc *procp,
+ struct mbuf **mrq));
+int nfsrv_readlink __P((struct nfsrv_descript *nfsd,
+ struct nfssvc_sock *slp, struct proc *procp,
+ struct mbuf **mrq));
+int nfsrv_remove __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct proc *procp, struct mbuf **mrq));
+int nfsrv_rename __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct proc *procp, struct mbuf **mrq));
+int nfsrv_rmdir __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct proc *procp, struct mbuf **mrq));
+int nfsrv_setattr __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct proc *procp, struct mbuf **mrq));
+int nfsrv_statfs __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct proc *procp, struct mbuf **mrq));
+int nfsrv_symlink __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct proc *procp, struct mbuf **mrq));
+int nfsrv_write __P((struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
+ struct proc *procp, struct mbuf **mrq));
+
+#ifdef NFS_DEBUG
+
+extern int nfs_debug;
+#define NFS_DEBUG_ASYNCIO 1 /* asynchronous i/o */
+#define NFS_DEBUG_WG 2 /* server write gathering */
+#define NFS_DEBUG_RC 4 /* server request caching */
+
+#define NFS_DPF(cat, args) \
+ do { \
+ if (nfs_debug & NFS_DEBUG_##cat) printf args; \
+ } while (0)
+
+#else
+
+#define NFS_DPF(cat, args)
+
+#endif
+
+#endif /* _KERNEL */
+
+#endif
diff --git a/cpukit/libnetworking/nfs/nfsdiskless.h b/cpukit/libnetworking/nfs/nfsdiskless.h
new file mode 100644
index 0000000000..0ed5c8f6f7
--- /dev/null
+++ b/cpukit/libnetworking/nfs/nfsdiskless.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Rick Macklem at The University of Guelph.
+ *
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)nfsdiskless.h 8.1 (Berkeley) 6/10/93
+ * $Id$
+ */
+
+#ifndef _NFS_NFSDISKLESS_H_
+#define _NFS_NFSDISKLESS_H_
+
+/*
+ * Structure that must be initialized for a diskless nfs client.
+ * This structure is used by nfs_mountroot() to set up the root and swap
+ * vnodes plus do a partial ifconfig(8) and route(8) so that the critical net
+ * interface can communicate with the server.
+ * The primary bootstrap is expected to fill in the appropriate fields before
+ * starting the kernel. Whether or not the swap area is nfs mounted is determined
+ * by the value in swdevt[0]. (equal to NODEV --> swap over nfs)
+ * Currently only works for AF_INET protocols.
+ * NB: All fields are stored in net byte order to avoid hassles with
+ * client/server byte ordering differences.
+ */
+
+/*
+ * I have defined a new structure that can handle an NFS Version 3 file handle
+ * but the kernel still expects the old Version 2 one to be provided. The
+ * changes required in nfs_vfsops.c for using the new are documented there in
+ * comments. (I felt that breaking network booting code by changing this
+ * structure would not be prudent at this time, since almost all servers are
+ * still Version 2 anyhow.)
+ */
+struct nfsv3_diskless {
+ struct ifaliasreq myif; /* Default interface */
+ struct sockaddr_in mygateway; /* Default gateway */
+ struct nfs_args swap_args; /* Mount args for swap file */
+ int swap_fhsize; /* Size of file handle */
+ u_char swap_fh[NFSX_V3FHMAX]; /* Swap file's file handle */
+ struct sockaddr_in swap_saddr; /* Address of swap server */
+ char swap_hostnam[MNAMELEN]; /* Host name for mount pt */
+ int swap_nblks; /* Size of server swap file */
+ struct ucred swap_ucred; /* Swap credentials */
+ struct nfs_args root_args; /* Mount args for root fs */
+ int root_fhsize; /* Size of root file handle */
+ u_char root_fh[NFSX_V3FHMAX]; /* File handle of root dir */
+ struct sockaddr_in root_saddr; /* Address of root server */
+ char root_hostnam[MNAMELEN]; /* Host name for mount pt */
+ long root_time; /* Timestamp of root fs */
+ char my_hostnam[MAXHOSTNAMELEN]; /* Client host name */
+};
+
+struct nfs_diskless {
+ struct ifaliasreq myif; /* Default interface */
+ struct sockaddr_in mygateway; /* Default gateway */
+ struct nfs_args swap_args; /* Mount args for swap file */
+ u_char swap_fh[NFSX_V2FH]; /* Swap file's file handle */
+ struct sockaddr_in swap_saddr; /* Address of swap server */
+ char swap_hostnam[MNAMELEN]; /* Host name for mount pt */
+ int swap_nblks; /* Size of server swap file */
+ struct ucred swap_ucred; /* Swap credentials */
+ struct nfs_args root_args; /* Mount args for root fs */
+ u_char root_fh[NFSX_V2FH]; /* File handle of root dir */
+ struct sockaddr_in root_saddr; /* Address of root server */
+ char root_hostnam[MNAMELEN]; /* Host name for mount pt */
+ long root_time; /* Timestamp of root fs */
+ char my_hostnam[MAXHOSTNAMELEN]; /* Client host name */
+};
+
+#endif
diff --git a/cpukit/libnetworking/nfs/nfsproto.h b/cpukit/libnetworking/nfs/nfsproto.h
new file mode 100644
index 0000000000..6ce7c5b960
--- /dev/null
+++ b/cpukit/libnetworking/nfs/nfsproto.h
@@ -0,0 +1,441 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Rick Macklem at The University of Guelph.
+ *
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)nfsproto.h 8.1 (Berkeley) 6/10/93
+ * $Id$
+ */
+
+#ifndef _NFS_NFSPROTO_H_
+#define _NFS_NFSPROTO_H_
+
+/*
+ * nfs definitions as per the Version 2 and 3 specs
+ */
+
+/*
+ * Constants as defined in the Sun NFS Version 2 and 3 specs.
+ * "NFS: Network File System Protocol Specification" RFC1094
+ * and in the "NFS: Network File System Version 3 Protocol
+ * Specification"
+ */
+
+#define NFS_PORT 2049
+#define NFS_PROG 100003
+#define NFS_VER2 2
+#define NFS_VER3 3
+#define NFS_V2MAXDATA 8192
+#define NFS_MAXDGRAMDATA 16384
+#define NFS_MAXDATA 32768
+#define NFS_MAXPATHLEN 1024
+#define NFS_MAXNAMLEN 255
+#define NFS_MAXPKTHDR 404
+#define NFS_MAXPACKET (NFS_MAXPKTHDR + NFS_MAXDATA)
+#define NFS_MINPACKET 20
+#define NFS_FABLKSIZE 512 /* Size in bytes of a block wrt fa_blocks */
+
+/* Stat numbers for rpc returns (version 2 and 3) */
+#define NFS_OK 0
+#define NFSERR_PERM 1
+#define NFSERR_NOENT 2
+#define NFSERR_IO 5
+#define NFSERR_NXIO 6
+#define NFSERR_ACCES 13
+#define NFSERR_EXIST 17
+#define NFSERR_XDEV 18 /* Version 3 only */
+#define NFSERR_NODEV 19
+#define NFSERR_NOTDIR 20
+#define NFSERR_ISDIR 21
+#define NFSERR_INVAL 22 /* Version 3 only */
+#define NFSERR_FBIG 27
+#define NFSERR_NOSPC 28
+#define NFSERR_ROFS 30
+#define NFSERR_MLINK 31 /* Version 3 only */
+#define NFSERR_NAMETOL 63
+#define NFSERR_NOTEMPTY 66
+#define NFSERR_DQUOT 69
+#define NFSERR_STALE 70
+#define NFSERR_REMOTE 71 /* Version 3 only */
+#define NFSERR_WFLUSH 99 /* Version 2 only */
+#define NFSERR_BADHANDLE 10001 /* The rest Version 3 only */
+#define NFSERR_NOT_SYNC 10002
+#define NFSERR_BAD_COOKIE 10003
+#define NFSERR_NOTSUPP 10004
+#define NFSERR_TOOSMALL 10005
+#define NFSERR_SERVERFAULT 10006
+#define NFSERR_BADTYPE 10007
+#define NFSERR_JUKEBOX 10008
+#define NFSERR_TRYLATER NFSERR_JUKEBOX
+#define NFSERR_STALEWRITEVERF 30001 /* Fake return for nfs_commit() */
+
+#define NFSERR_RETVOID 0x20000000 /* Return void, not error */
+#define NFSERR_AUTHERR 0x40000000 /* Mark an authentication error */
+#define NFSERR_RETERR 0x80000000 /* Mark an error return for V3 */
+
+/* Sizes in bytes of various nfs rpc components */
+#define NFSX_UNSIGNED 4
+
+/* specific to NFS Version 2 */
+#define NFSX_V2FH 32
+#define NFSX_V2FATTR 68
+#define NFSX_V2SATTR 32
+#define NFSX_V2COOKIE 4
+#define NFSX_V2STATFS 20
+
+/* specific to NFS Version 3 */
+#define NFSX_V3FH (sizeof (fhandle_t)) /* size this server uses */
+#define NFSX_V3FHMAX 64 /* max. allowed by protocol */
+#define NFSX_V3FATTR 84
+#define NFSX_V3SATTR 60 /* max. all fields filled in */
+#define NFSX_V3SRVSATTR (sizeof (struct nfsv3_sattr))
+#define NFSX_V3POSTOPATTR (NFSX_V3FATTR + NFSX_UNSIGNED)
+#define NFSX_V3WCCDATA (NFSX_V3POSTOPATTR + 8 * NFSX_UNSIGNED)
+#define NFSX_V3COOKIEVERF 8
+#define NFSX_V3WRITEVERF 8
+#define NFSX_V3CREATEVERF 8
+#define NFSX_V3STATFS 52
+#define NFSX_V3FSINFO 48
+#define NFSX_V3PATHCONF 24
+
+/* variants for both versions */
+#define NFSX_FH(v3) ((v3) ? (NFSX_V3FHMAX + NFSX_UNSIGNED) : \
+ NFSX_V2FH)
+#define NFSX_SRVFH(v3) ((v3) ? NFSX_V3FH : NFSX_V2FH)
+#define NFSX_FATTR(v3) ((v3) ? NFSX_V3FATTR : NFSX_V2FATTR)
+#define NFSX_PREOPATTR(v3) ((v3) ? (7 * NFSX_UNSIGNED) : 0)
+#define NFSX_POSTOPATTR(v3) ((v3) ? (NFSX_V3FATTR + NFSX_UNSIGNED) : 0)
+#define NFSX_POSTOPORFATTR(v3) ((v3) ? (NFSX_V3FATTR + NFSX_UNSIGNED) : \
+ NFSX_V2FATTR)
+#define NFSX_WCCDATA(v3) ((v3) ? NFSX_V3WCCDATA : 0)
+#define NFSX_WCCORFATTR(v3) ((v3) ? NFSX_V3WCCDATA : NFSX_V2FATTR)
+#define NFSX_SATTR(v3) ((v3) ? NFSX_V3SATTR : NFSX_V2SATTR)
+#define NFSX_COOKIEVERF(v3) ((v3) ? NFSX_V3COOKIEVERF : 0)
+#define NFSX_WRITEVERF(v3) ((v3) ? NFSX_V3WRITEVERF : 0)
+#define NFSX_READDIR(v3) ((v3) ? (5 * NFSX_UNSIGNED) : \
+ (2 * NFSX_UNSIGNED))
+#define NFSX_STATFS(v3) ((v3) ? NFSX_V3STATFS : NFSX_V2STATFS)
+
+/* nfs rpc procedure numbers (before version mapping) */
+#define NFSPROC_NULL 0
+#define NFSPROC_GETATTR 1
+#define NFSPROC_SETATTR 2
+#define NFSPROC_LOOKUP 3
+#define NFSPROC_ACCESS 4
+#define NFSPROC_READLINK 5
+#define NFSPROC_READ 6
+#define NFSPROC_WRITE 7
+#define NFSPROC_CREATE 8
+#define NFSPROC_MKDIR 9
+#define NFSPROC_SYMLINK 10
+#define NFSPROC_MKNOD 11
+#define NFSPROC_REMOVE 12
+#define NFSPROC_RMDIR 13
+#define NFSPROC_RENAME 14
+#define NFSPROC_LINK 15
+#define NFSPROC_READDIR 16
+#define NFSPROC_READDIRPLUS 17
+#define NFSPROC_FSSTAT 18
+#define NFSPROC_FSINFO 19
+#define NFSPROC_PATHCONF 20
+#define NFSPROC_COMMIT 21
+
+/* And leasing (nqnfs) procedure numbers (must be last) */
+#define NQNFSPROC_GETLEASE 22
+#define NQNFSPROC_VACATED 23
+#define NQNFSPROC_EVICTED 24
+
+#define NFSPROC_NOOP 25
+#define NFS_NPROCS 26
+
+/* Actual Version 2 procedure numbers */
+#define NFSV2PROC_NULL 0
+#define NFSV2PROC_GETATTR 1
+#define NFSV2PROC_SETATTR 2
+#define NFSV2PROC_NOOP 3
+#define NFSV2PROC_ROOT NFSV2PROC_NOOP /* Obsolete */
+#define NFSV2PROC_LOOKUP 4
+#define NFSV2PROC_READLINK 5
+#define NFSV2PROC_READ 6
+#define NFSV2PROC_WRITECACHE NFSV2PROC_NOOP /* Obsolete */
+#define NFSV2PROC_WRITE 8
+#define NFSV2PROC_CREATE 9
+#define NFSV2PROC_REMOVE 10
+#define NFSV2PROC_RENAME 11
+#define NFSV2PROC_LINK 12
+#define NFSV2PROC_SYMLINK 13
+#define NFSV2PROC_MKDIR 14
+#define NFSV2PROC_RMDIR 15
+#define NFSV2PROC_READDIR 16
+#define NFSV2PROC_STATFS 17
+
+/*
+ * Constants used by the Version 3 protocol for various RPCs
+ */
+#define NFSV3SATTRTIME_DONTCHANGE 0
+#define NFSV3SATTRTIME_TOSERVER 1
+#define NFSV3SATTRTIME_TOCLIENT 2
+
+#define NFSV3ACCESS_READ 0x01
+#define NFSV3ACCESS_LOOKUP 0x02
+#define NFSV3ACCESS_MODIFY 0x04
+#define NFSV3ACCESS_EXTEND 0x08
+#define NFSV3ACCESS_DELETE 0x10
+#define NFSV3ACCESS_EXECUTE 0x20
+
+#define NFSV3WRITE_UNSTABLE 0
+#define NFSV3WRITE_DATASYNC 1
+#define NFSV3WRITE_FILESYNC 2
+
+#define NFSV3CREATE_UNCHECKED 0
+#define NFSV3CREATE_GUARDED 1
+#define NFSV3CREATE_EXCLUSIVE 2
+
+#define NFSV3FSINFO_LINK 0x01
+#define NFSV3FSINFO_SYMLINK 0x02
+#define NFSV3FSINFO_HOMOGENEOUS 0x08
+#define NFSV3FSINFO_CANSETTIME 0x10
+
+/* Conversion macros */
+#define vtonfsv2_mode(t,m) \
+ txdr_unsigned(((t) == VFIFO) ? MAKEIMODE(VCHR, (m)) : \
+ MAKEIMODE((t), (m)))
+#define vtonfsv3_mode(m) txdr_unsigned((m) & 07777)
+#define nfstov_mode(a) (fxdr_unsigned(u_short, (a))&07777)
+#define vtonfsv2_type(a) txdr_unsigned(nfsv2_type[((long)(a))])
+#define vtonfsv3_type(a) txdr_unsigned(nfsv3_type[((long)(a))])
+#define nfsv2tov_type(a) nv2tov_type[fxdr_unsigned(u_long,(a))&0x7]
+#define nfsv3tov_type(a) nv3tov_type[fxdr_unsigned(u_long,(a))&0x7]
+
+/* File types */
+typedef enum { NFNON=0, NFREG=1, NFDIR=2, NFBLK=3, NFCHR=4, NFLNK=5,
+ NFSOCK=6, NFFIFO=7 } nfstype;
+
+/* Structs for common parts of the rpc's */
+/*
+ * File Handle (32 bytes for version 2), variable up to 64 for version 3.
+ * File Handles of up to NFS_SMALLFH in size are stored directly in the
+ * nfs node, whereas larger ones are malloc'd. (This never happens when
+ * NFS_SMALLFH is set to 64.)
+ * NFS_SMALLFH should be in the range of 32 to 64 and be divisible by 4.
+ */
+#ifndef NFS_SMALLFH
+#define NFS_SMALLFH 64
+#endif
+union nfsfh {
+ fhandle_t fh_generic;
+ u_char fh_bytes[NFS_SMALLFH];
+};
+typedef union nfsfh nfsfh_t;
+
+struct nfsv2_time {
+ u_long nfsv2_sec;
+ u_long nfsv2_usec;
+};
+typedef struct nfsv2_time nfstime2;
+
+struct nfsv3_time {
+ u_long nfsv3_sec;
+ u_long nfsv3_nsec;
+};
+typedef struct nfsv3_time nfstime3;
+
+/*
+ * Quads are defined as arrays of 2 longs to ensure dense packing for the
+ * protocol and to facilitate xdr conversion.
+ */
+struct nfs_uquad {
+ u_long nfsuquad[2];
+};
+typedef struct nfs_uquad nfsuint64;
+
+/*
+ * Used to convert between two u_longs and a u_quad_t.
+ */
+union nfs_quadconvert {
+ u_long lval[2];
+ u_quad_t qval;
+};
+typedef union nfs_quadconvert nfsquad_t;
+
+/*
+ * NFS Version 3 special file number.
+ */
+struct nfsv3_spec {
+ u_long specdata1;
+ u_long specdata2;
+};
+typedef struct nfsv3_spec nfsv3spec;
+
+/*
+ * File attributes and setable attributes. These structures cover both
+ * NFS version 2 and the version 3 protocol. Note that the union is only
+ * used so that one pointer can refer to both variants. These structures
+ * go out on the wire and must be densely packed, so no quad data types
+ * are used. (all fields are longs or u_longs or structures of same)
+ * NB: You can't do sizeof(struct nfs_fattr), you must use the
+ * NFSX_FATTR(v3) macro.
+ */
+struct nfs_fattr {
+ u_long fa_type;
+ u_long fa_mode;
+ u_long fa_nlink;
+ u_long fa_uid;
+ u_long fa_gid;
+ union {
+ struct {
+ u_long nfsv2fa_size;
+ u_long nfsv2fa_blocksize;
+ u_long nfsv2fa_rdev;
+ u_long nfsv2fa_blocks;
+ u_long nfsv2fa_fsid;
+ u_long nfsv2fa_fileid;
+ nfstime2 nfsv2fa_atime;
+ nfstime2 nfsv2fa_mtime;
+ nfstime2 nfsv2fa_ctime;
+ } fa_nfsv2;
+ struct {
+ nfsuint64 nfsv3fa_size;
+ nfsuint64 nfsv3fa_used;
+ nfsv3spec nfsv3fa_rdev;
+ nfsuint64 nfsv3fa_fsid;
+ nfsuint64 nfsv3fa_fileid;
+ nfstime3 nfsv3fa_atime;
+ nfstime3 nfsv3fa_mtime;
+ nfstime3 nfsv3fa_ctime;
+ } fa_nfsv3;
+ } fa_un;
+};
+
+/* and some ugly defines for accessing union components */
+#define fa2_size fa_un.fa_nfsv2.nfsv2fa_size
+#define fa2_blocksize fa_un.fa_nfsv2.nfsv2fa_blocksize
+#define fa2_rdev fa_un.fa_nfsv2.nfsv2fa_rdev
+#define fa2_blocks fa_un.fa_nfsv2.nfsv2fa_blocks
+#define fa2_fsid fa_un.fa_nfsv2.nfsv2fa_fsid
+#define fa2_fileid fa_un.fa_nfsv2.nfsv2fa_fileid
+#define fa2_atime fa_un.fa_nfsv2.nfsv2fa_atime
+#define fa2_mtime fa_un.fa_nfsv2.nfsv2fa_mtime
+#define fa2_ctime fa_un.fa_nfsv2.nfsv2fa_ctime
+#define fa3_size fa_un.fa_nfsv3.nfsv3fa_size
+#define fa3_used fa_un.fa_nfsv3.nfsv3fa_used
+#define fa3_rdev fa_un.fa_nfsv3.nfsv3fa_rdev
+#define fa3_fsid fa_un.fa_nfsv3.nfsv3fa_fsid
+#define fa3_fileid fa_un.fa_nfsv3.nfsv3fa_fileid
+#define fa3_atime fa_un.fa_nfsv3.nfsv3fa_atime
+#define fa3_mtime fa_un.fa_nfsv3.nfsv3fa_mtime
+#define fa3_ctime fa_un.fa_nfsv3.nfsv3fa_ctime
+
+struct nfsv2_sattr {
+ u_long sa_mode;
+ u_long sa_uid;
+ u_long sa_gid;
+ u_long sa_size;
+ nfstime2 sa_atime;
+ nfstime2 sa_mtime;
+};
+
+/*
+ * NFS Version 3 sattr structure for the new node creation case.
+ */
+struct nfsv3_sattr {
+ u_long sa_modetrue;
+ u_long sa_mode;
+ u_long sa_uidtrue;
+ u_long sa_uid;
+ u_long sa_gidtrue;
+ u_long sa_gid;
+ u_long sa_sizefalse;
+ u_long sa_atimetype;
+ nfstime3 sa_atime;
+ u_long sa_mtimetype;
+ nfstime3 sa_mtime;
+};
+
+struct nfs_statfs {
+ union {
+ struct {
+ u_long nfsv2sf_tsize;
+ u_long nfsv2sf_bsize;
+ u_long nfsv2sf_blocks;
+ u_long nfsv2sf_bfree;
+ u_long nfsv2sf_bavail;
+ } sf_nfsv2;
+ struct {
+ nfsuint64 nfsv3sf_tbytes;
+ nfsuint64 nfsv3sf_fbytes;
+ nfsuint64 nfsv3sf_abytes;
+ nfsuint64 nfsv3sf_tfiles;
+ nfsuint64 nfsv3sf_ffiles;
+ nfsuint64 nfsv3sf_afiles;
+ u_long nfsv3sf_invarsec;
+ } sf_nfsv3;
+ } sf_un;
+};
+
+#define sf_tsize sf_un.sf_nfsv2.nfsv2sf_tsize
+#define sf_bsize sf_un.sf_nfsv2.nfsv2sf_bsize
+#define sf_blocks sf_un.sf_nfsv2.nfsv2sf_blocks
+#define sf_bfree sf_un.sf_nfsv2.nfsv2sf_bfree
+#define sf_bavail sf_un.sf_nfsv2.nfsv2sf_bavail
+#define sf_tbytes sf_un.sf_nfsv3.nfsv3sf_tbytes
+#define sf_fbytes sf_un.sf_nfsv3.nfsv3sf_fbytes
+#define sf_abytes sf_un.sf_nfsv3.nfsv3sf_abytes
+#define sf_tfiles sf_un.sf_nfsv3.nfsv3sf_tfiles
+#define sf_ffiles sf_un.sf_nfsv3.nfsv3sf_ffiles
+#define sf_afiles sf_un.sf_nfsv3.nfsv3sf_afiles
+#define sf_invarsec sf_un.sf_nfsv3.nfsv3sf_invarsec
+
+struct nfsv3_fsinfo {
+ u_long fs_rtmax;
+ u_long fs_rtpref;
+ u_long fs_rtmult;
+ u_long fs_wtmax;
+ u_long fs_wtpref;
+ u_long fs_wtmult;
+ u_long fs_dtpref;
+ nfsuint64 fs_maxfilesize;
+ nfstime3 fs_timedelta;
+ u_long fs_properties;
+};
+
+struct nfsv3_pathconf {
+ u_long pc_linkmax;
+ u_long pc_namemax;
+ u_long pc_notrunc;
+ u_long pc_chownrestricted;
+ u_long pc_caseinsensitive;
+ u_long pc_casepreserving;
+};
+
+#endif
diff --git a/cpukit/libnetworking/nfs/rpcv2.h b/cpukit/libnetworking/nfs/rpcv2.h
new file mode 100644
index 0000000000..5fd6e7febf
--- /dev/null
+++ b/cpukit/libnetworking/nfs/rpcv2.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Rick Macklem at The University of Guelph.
+ *
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)rpcv2.h 8.1 (Berkeley) 6/10/93
+ * $Id$
+ */
+
+#ifndef _NFS_RPCV2_H_
+#define _NFS_RPCV2_H_
+
+/*
+ * Definitions for Sun RPC Version 2, from
+ * "RPC: Remote Procedure Call Protocol Specification" RFC1057
+ */
+
+/* Version # */
+#define RPC_VER2 2
+
+/* Authentication */
+#define RPCAUTH_NULL 0
+#define RPCAUTH_UNIX 1
+#define RPCAUTH_SHORT 2
+#define RPCAUTH_KERB4 4
+#define RPCAUTH_NQNFS 300000
+#define RPCAUTH_MAXSIZ 400
+#define RPCVERF_MAXSIZ 12 /* For Kerb, can actually be 400 */
+#define RPCAUTH_UNIXGIDS 16
+
+/*
+ * Constants associated with authentication flavours.
+ */
+#define RPCAKN_FULLNAME 0
+#define RPCAKN_NICKNAME 1
+
+/* Rpc Constants */
+#define RPC_CALL 0
+#define RPC_REPLY 1
+#define RPC_MSGACCEPTED 0
+#define RPC_MSGDENIED 1
+#define RPC_PROGUNAVAIL 1
+#define RPC_PROGMISMATCH 2
+#define RPC_PROCUNAVAIL 3
+#define RPC_GARBAGE 4 /* I like this one */
+#define RPC_MISMATCH 0
+#define RPC_AUTHERR 1
+
+/* Authentication failures */
+#define AUTH_BADCRED 1
+#define AUTH_REJECTCRED 2
+#define AUTH_BADVERF 3
+#define AUTH_REJECTVERF 4
+#define AUTH_TOOWEAK 5 /* Give em wheaties */
+
+/* Sizes of rpc header parts */
+#define RPC_SIZ 24
+#define RPC_REPLYSIZ 28
+
+/* RPC Prog definitions */
+#define RPCPROG_MNT 100005
+#define RPCMNT_VER1 1
+#define RPCMNT_VER3 3
+#define RPCMNT_MOUNT 1
+#define RPCMNT_DUMP 2
+#define RPCMNT_UMOUNT 3
+#define RPCMNT_UMNTALL 4
+#define RPCMNT_EXPORT 5
+#define RPCMNT_NAMELEN 255
+#define RPCMNT_PATHLEN 1024
+#define RPCPROG_NFS 100003
+
+/*
+ * Structures used for RPCAUTH_KERB4.
+ */
+struct nfsrpc_fullverf {
+ u_long t1;
+ u_long t2;
+ u_long w2;
+};
+
+struct nfsrpc_fullblock {
+ u_long t1;
+ u_long t2;
+ u_long w1;
+ u_long w2;
+};
+
+struct nfsrpc_nickverf {
+ u_long kind;
+ struct nfsrpc_fullverf verf;
+};
+
+/*
+ * and their sizes in bytes.. If sizeof (struct nfsrpc_xx) != these
+ * constants, well then things will break in mount_nfs and nfsd.
+ */
+#define RPCX_FULLVERF 12
+#define RPCX_FULLBLOCK 16
+#define RPCX_NICKVERF 16
+
+#ifdef NFSKERB
+XXX
+#else
+typedef u_char NFSKERBKEY_T[2];
+typedef u_char NFSKERBKEYSCHED_T[2];
+#endif
+#define NFS_KERBSRV "rcmd" /* Kerberos Service for NFS */
+#define NFS_KERBTTL (30 * 60) /* Credential ttl (sec) */
+#define NFS_KERBCLOCKSKEW (5 * 60) /* Clock skew (sec) */
+#define NFS_KERBW1(t) (*((u_long *)(&((t).dat[((t).length + 3) & ~0x3]))))
+#endif
diff --git a/cpukit/libnetworking/nfs/xdr_subs.h b/cpukit/libnetworking/nfs/xdr_subs.h
new file mode 100644
index 0000000000..874730378f
--- /dev/null
+++ b/cpukit/libnetworking/nfs/xdr_subs.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Rick Macklem at The University of Guelph.
+ *
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)xdr_subs.h 8.1 (Berkeley) 6/10/93
+ * $Id$
+ */
+
+#ifndef _NFS_XDR_SUBS_H_
+#define _NFS_XDR_SUBS_H_
+
+/*
+ * Macros used for conversion to/from xdr representation by nfs...
+ * These use the MACHINE DEPENDENT routines ntohl, htonl
+ * As defined by "XDR: External Data Representation Standard" RFC1014
+ *
+ * To simplify the implementation, we use ntohl/htonl even on big-endian
+ * machines, and count on them being `#define'd away. Some of these
+ * might be slightly more efficient as quad_t copies on a big-endian,
+ * but we cannot count on their alignment anyway.
+ */
+
+#define fxdr_unsigned(t, v) ((t)ntohl((long)(v)))
+#define txdr_unsigned(v) (htonl((long)(v)))
+
+#define fxdr_nfsv2time(f, t) { \
+ (t)->tv_sec = ntohl(((struct nfsv2_time *)(f))->nfsv2_sec); \
+ if (((struct nfsv2_time *)(f))->nfsv2_usec != 0xffffffff) \
+ (t)->tv_nsec = 1000 * ntohl(((struct nfsv2_time *)(f))->nfsv2_usec); \
+ else \
+ (t)->tv_nsec = 0; \
+}
+#define txdr_nfsv2time(f, t) { \
+ ((struct nfsv2_time *)(t))->nfsv2_sec = htonl((f)->tv_sec); \
+ if ((f)->tv_nsec != -1) \
+ ((struct nfsv2_time *)(t))->nfsv2_usec = htonl((f)->tv_nsec / 1000); \
+ else \
+ ((struct nfsv2_time *)(t))->nfsv2_usec = 0xffffffff; \
+}
+
+#define fxdr_nfsv3time(f, t) { \
+ (t)->tv_sec = ntohl(((struct nfsv3_time *)(f))->nfsv3_sec); \
+ (t)->tv_nsec = ntohl(((struct nfsv3_time *)(f))->nfsv3_nsec); \
+}
+#define txdr_nfsv3time(f, t) { \
+ ((struct nfsv3_time *)(t))->nfsv3_sec = htonl((f)->tv_sec); \
+ ((struct nfsv3_time *)(t))->nfsv3_nsec = htonl((f)->tv_nsec); \
+}
+
+#define fxdr_hyper(f, t) { \
+ ((long *)(t))[_QUAD_HIGHWORD] = ntohl(((long *)(f))[0]); \
+ ((long *)(t))[_QUAD_LOWWORD] = ntohl(((long *)(f))[1]); \
+}
+#define txdr_hyper(f, t) { \
+ ((long *)(t))[0] = htonl(((long *)(f))[_QUAD_HIGHWORD]); \
+ ((long *)(t))[1] = htonl(((long *)(f))[_QUAD_LOWWORD]); \
+}
+
+#endif
diff --git a/cpukit/libnetworking/opt_ipfw.h b/cpukit/libnetworking/opt_ipfw.h
new file mode 100644
index 0000000000..2b4c47e48f
--- /dev/null
+++ b/cpukit/libnetworking/opt_ipfw.h
@@ -0,0 +1,5 @@
+/*
+ * $Id$
+ */
+
+/* intentionally empty file */
diff --git a/cpukit/libnetworking/opt_mrouting.h b/cpukit/libnetworking/opt_mrouting.h
new file mode 100644
index 0000000000..2b4c47e48f
--- /dev/null
+++ b/cpukit/libnetworking/opt_mrouting.h
@@ -0,0 +1,5 @@
+/*
+ * $Id$
+ */
+
+/* intentionally empty file */
diff --git a/cpukit/libnetworking/opt_tcpdebug.h b/cpukit/libnetworking/opt_tcpdebug.h
new file mode 100644
index 0000000000..4c10d1bac2
--- /dev/null
+++ b/cpukit/libnetworking/opt_tcpdebug.h
@@ -0,0 +1,16 @@
+/*
+ * $Id$
+ */
+
+/* intentionally empty file */
+
+/*
+ * Uncomment the following line to turn on debug code. When you define
+ * this symbol, tcp_trace() is called. If you want tcp_trace() to
+ * print, then you need to edit netinet/tcp_debug to set the variable
+ * "tcpconsdebug" to 1.
+ */
+
+/*
+#define TCPDEBUG
+*/
diff --git a/cpukit/libnetworking/poll.h b/cpukit/libnetworking/poll.h
new file mode 100644
index 0000000000..0287495599
--- /dev/null
+++ b/cpukit/libnetworking/poll.h
@@ -0,0 +1,6 @@
+#ifndef _POLL_H_
+#define _POLL_H_
+
+#include <sys/poll.h>
+
+#endif /* !_POLL_H_ */
diff --git a/cpukit/libnetworking/resolv.h b/cpukit/libnetworking/resolv.h
new file mode 100644
index 0000000000..614f204706
--- /dev/null
+++ b/cpukit/libnetworking/resolv.h
@@ -0,0 +1,306 @@
+/*-
+ * Copyright (c) 1983, 1987, 1989, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ */
+
+/*
+ * Portions Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, 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.
+ */
+
+/*
+ * @(#)resolv.h 8.1 (Berkeley) 6/2/93
+ * From Id: resolv.h,v 8.12 1998/04/28 19:36:46 halley Exp $
+ * $Id$
+ */
+
+#ifndef _RESOLV_H_
+#define _RESOLV_H_
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/cdefs.h>
+#include <stdio.h>
+
+/*
+ * Revision information. This is the release date in YYYYMMDD format.
+ * It can change every day so the right thing to do with it is use it
+ * in preprocessor commands such as "#if (__RES > 19931104)". Do not
+ * compare for equality; rather, use it to determine whether your resolver
+ * is new enough to contain a certain feature.
+ */
+
+#define __RES 19960801
+
+/*
+ * This used to be defined in res_query.c, now it's in herror.c. It was
+ * never extern'd by any *.h file before it was placed here. herror.c is
+ * part of libresolv.a even though it might make more sense in libnetdb.a
+ * or even libnet.a.
+ */
+
+extern int h_errno;
+
+/*
+ * Resolver configuration file.
+ * Normally not present, but may contain the address of the
+ * inital name server(s) to query and the domain search list.
+ */
+
+#ifndef _PATH_RESCONF
+#define _PATH_RESCONF "/etc/resolv.conf"
+#endif
+
+/*
+ * Global defines and variables for resolver stub.
+ */
+#define MAXNS 3 /* max # name servers we'll track */
+#define MAXDFLSRCH 3 /* # default domain levels to try */
+#define MAXDNSRCH 6 /* max # domains in search path */
+#define LOCALDOMAINPARTS 2 /* min levels in name that is "local" */
+
+#define RES_TIMEOUT 5 /* min. seconds between retries */
+#define MAXRESOLVSORT 10 /* number of net to sort on */
+#define RES_MAXNDOTS 15 /* should reflect bit field size */
+
+struct __res_state {
+ int retrans; /* retransmition time interval */
+ int retry; /* number of times to retransmit */
+ u_long options; /* option flags - see below. */
+ int nscount; /* number of name servers */
+ struct sockaddr_in
+ nsaddr_list[MAXNS]; /* address of name server */
+#define nsaddr nsaddr_list[0] /* for backward compatibility */
+ u_short id; /* current message id */
+ char *dnsrch[MAXDNSRCH+1]; /* components of domain to search */
+ char defdname[256]; /* default domain (deprecated) */
+ u_long pfcode; /* RES_PRF_ flags - see below. */
+ unsigned ndots:4; /* threshold for initial abs. query */
+ unsigned nsort:4; /* number of elements in sort_list[] */
+ char unused[3];
+ struct {
+ struct in_addr addr;
+ u_int32_t mask;
+ } sort_list[MAXRESOLVSORT];
+ char pad[72]; /* on an i386 this means 512b total */
+};
+
+/*
+ * Resolver options (keep these in synch with res_debug.c, please)
+ */
+#define RES_INIT 0x00000001 /* address initialized */
+#define RES_DEBUG 0x00000002 /* print debug messages */
+#define RES_AAONLY 0x00000004 /* authoritative answers only (!IMPL)*/
+#define RES_USEVC 0x00000008 /* use virtual circuit */
+#define RES_PRIMARY 0x00000010 /* query primary server only (!IMPL) */
+#define RES_IGNTC 0x00000020 /* ignore truncation errors */
+#define RES_RECURSE 0x00000040 /* recursion desired */
+#define RES_DEFNAMES 0x00000080 /* use default domain name */
+#define RES_STAYOPEN 0x00000100 /* Keep TCP socket open */
+#define RES_DNSRCH 0x00000200 /* search up local domain tree */
+#define RES_INSECURE1 0x00000400 /* type 1 security disabled */
+#define RES_INSECURE2 0x00000800 /* type 2 security disabled */
+#define RES_NOALIASES 0x00001000 /* shuts off HOSTALIASES feature */
+#define RES_USE_INET6 0x00002000 /* use/map IPv6 in gethostbyname() */
+#define RES_NOTLDQUERY 0x00004000 /* Don't query TLD names */
+
+#define RES_DEFAULT (RES_RECURSE | RES_DEFNAMES | RES_DNSRCH)
+
+/*
+ * Resolver "pfcode" values. Used by dig.
+ */
+#define RES_PRF_STATS 0x00000001
+#define RES_PRF_UPDATE 0x00000002
+#define RES_PRF_CLASS 0x00000004
+#define RES_PRF_CMD 0x00000008
+#define RES_PRF_QUES 0x00000010
+#define RES_PRF_ANS 0x00000020
+#define RES_PRF_AUTH 0x00000040
+#define RES_PRF_ADD 0x00000080
+#define RES_PRF_HEAD1 0x00000100
+#define RES_PRF_HEAD2 0x00000200
+#define RES_PRF_TTLID 0x00000400
+#define RES_PRF_HEADX 0x00000800
+#define RES_PRF_QUERY 0x00001000
+#define RES_PRF_REPLY 0x00002000
+#define RES_PRF_INIT 0x00004000
+/* 0x00008000 */
+
+typedef enum { res_goahead, res_nextns, res_modified, res_done, res_error }
+ res_sendhookact;
+
+typedef res_sendhookact (*res_send_qhook)__P((struct sockaddr_in * const *ns,
+ const u_char **query,
+ int *querylen,
+ u_char *ans,
+ int anssiz,
+ int *resplen));
+
+typedef res_sendhookact (*res_send_rhook)__P((const struct sockaddr_in *ns,
+ const u_char *query,
+ int querylen,
+ u_char *ans,
+ int anssiz,
+ int *resplen));
+
+struct res_sym {
+ int number; /* Identifying number, like T_MX */
+ char * name; /* Its symbolic name, like "MX" */
+ char * humanname; /* Its fun name, like "mail exchanger" */
+};
+
+extern struct __res_state _res;
+extern const struct res_sym __p_class_syms[];
+extern const struct res_sym __p_type_syms[];
+
+/* Private routines shared between libc/net, named, nslookup and others. */
+#define res_hnok __res_hnok
+#define res_ownok __res_ownok
+#define res_mailok __res_mailok
+#define res_dnok __res_dnok
+#define sym_ston __sym_ston
+#define sym_ntos __sym_ntos
+#define sym_ntop __sym_ntop
+#define b64_ntop __b64_ntop
+#define b64_pton __b64_pton
+#define loc_ntoa __loc_ntoa
+#define loc_aton __loc_aton
+#define fp_resstat __fp_resstat
+#define p_query __p_query
+#define dn_skipname __dn_skipname
+#define fp_resstat __fp_resstat
+#define fp_query __fp_query
+#define fp_nquery __fp_nquery
+#define hostalias __hostalias
+#define putlong __putlong
+#define putshort __putshort
+#define p_class __p_class
+#define p_time __p_time
+#define p_type __p_type
+#define p_query __p_query
+#define p_cdnname __p_cdnname
+#define p_section __p_section
+#define p_cdname __p_cdname
+#define p_fqnname __p_fqnname
+#define p_fqname __p_fqname
+#define p_option __p_option
+#define p_secstodate __p_secstodate
+#define dn_count_labels __dn_count_labels
+#define dn_comp __dn_comp
+#define dn_expand __dn_expand
+#define res_init __res_init
+#define res_randomid __res_randomid
+#define res_query __res_query
+#define res_search __res_search
+#define res_querydomain __res_querydomain
+#define res_mkquery __res_mkquery
+#define res_send __res_send
+#define res_isourserver __res_isourserver
+#define res_nameinquery __res_nameinquery
+#define res_queriesmatch __res_queriesmatch
+#define res_close __res_close
+#define res_mkupdate __res_mkupdate
+#define res_mkupdrec __res_mkupdrec
+#define res_freeupdrec __res_freeupdrec
+
+__BEGIN_DECLS
+int res_hnok __P((const char *));
+int res_ownok __P((const char *));
+int res_mailok __P((const char *));
+int res_dnok __P((const char *));
+int sym_ston __P((const struct res_sym *, const char *, int *));
+const char * sym_ntos __P((const struct res_sym *, int, int *));
+const char * sym_ntop __P((const struct res_sym *, int, int *));
+int b64_ntop __P((u_char const *, size_t, char *, size_t));
+int b64_pton __P((char const *, u_char *, size_t));
+int loc_aton __P((const char *, u_char *));
+const char * loc_ntoa __P((const u_char *, char *));
+int dn_skipname __P((const u_char *, const u_char *));
+void fp_resstat __P((struct __res_state *, FILE *));
+void fp_query __P((const u_char *, FILE *));
+void fp_nquery __P((const u_char *, int, FILE *));
+const char * hostalias __P((const char *));
+void putlong __P((u_int32_t, u_char *));
+void putshort __P((u_int16_t, u_char *));
+const char * p_class __P((int));
+const char * p_time __P((u_int32_t));
+const char * p_type __P((int));
+void p_query __P((const u_char *));
+const u_char * p_cdnname __P((const u_char *, const u_char *, int, FILE *));
+const u_char * p_cdname __P((const u_char *, const u_char *, FILE *));
+const u_char * p_fqnname __P((const u_char *, const u_char *,
+ int, char *, int));
+const u_char * p_fqname __P((const u_char *, const u_char *, FILE *));
+const char * p_option __P((u_long));
+char * p_secstodate __P((u_long));
+int dn_count_labels __P((const char *));
+int dn_comp __P((const char *, u_char *, int,
+ u_char **, u_char **));
+int dn_expand __P((const u_char *, const u_char *, const u_char *,
+ char *, int));
+int res_init __P((void));
+u_int res_randomid __P((void));
+int res_query __P((const char *, int, int, u_char *, int));
+int res_search __P((const char *, int, int, u_char *, int));
+int res_querydomain __P((const char *, const char *, int, int,
+ u_char *, int));
+int res_mkquery __P((int, const char *, int, int, const u_char *,
+ int, const u_char *, u_char *, int));
+int res_send __P((const u_char *, int, u_char *, int));
+int res_isourserver __P((const struct sockaddr_in *));
+int res_nameinquery __P((const char *, int, int,
+ const u_char *, const u_char *));
+int res_queriesmatch __P((const u_char *, const u_char *,
+ const u_char *, const u_char *));
+void res_close __P((void));
+const char * p_section __P((int, int));
+/* XXX The following depend on the ns_updrec typedef in arpa/nameser.h */
+#ifdef _ARPA_NAMESER_H_
+int res_update __P((ns_updrec *));
+int res_mkupdate __P((ns_updrec *, u_char *, int));
+ns_updrec * res_mkupdrec __P((int, const char *, u_int, u_int, u_long));
+void res_freeupdrec __P((ns_updrec *));
+#endif
+__END_DECLS
+
+#endif /* !_RESOLV_H_ */
diff --git a/cpukit/libnetworking/rtems/ftpfs.h b/cpukit/libnetworking/rtems/ftpfs.h
new file mode 100644
index 0000000000..a79923263f
--- /dev/null
+++ b/cpukit/libnetworking/rtems/ftpfs.h
@@ -0,0 +1,34 @@
+/*
+ * File Transfer Protocol client declarations
+ *
+ * Transfer file to/from remote host
+ *
+ *
+ * (c) Copyright 2002
+ * Thomas Doerfler
+ * IMD Ingenieurbuero fuer Microcomputertechnik
+ * Herbststr. 8
+ * 82178 Puchheim, Germany
+ * <Thomas.Doerfler@imd-systems.de>
+ *
+ * This code has been created after closly inspecting
+ * "tftpdriver.c" from Eric Norum.
+ *
+ * $Id$
+ */
+
+#ifndef _FTP_DRIVER_H
+#define _FTP_DRIVER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ /* create mount point and mount ftp file system */
+ int rtems_bsdnet_initialize_ftp_filesystem () ;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/libnetworking/rtems/issetugid.c b/cpukit/libnetworking/rtems/issetugid.c
new file mode 100644
index 0000000000..3baf0ec88b
--- /dev/null
+++ b/cpukit/libnetworking/rtems/issetugid.c
@@ -0,0 +1,11 @@
+/*
+ * Dummy version of BSD routine
+ *
+ * $Id$
+ */
+
+int
+issetugid (void)
+{
+ return 0;
+}
diff --git a/cpukit/libnetworking/rtems/mkrootfs.c b/cpukit/libnetworking/rtems/mkrootfs.c
new file mode 100644
index 0000000000..92dde4a892
--- /dev/null
+++ b/cpukit/libnetworking/rtems/mkrootfs.c
@@ -0,0 +1,331 @@
+/*
+ ------------------------------------------------------------------------
+ $Id$
+ ------------------------------------------------------------------------
+
+ Copyright Cybertec Pty Ltd, 2000
+ All rights reserved Cybertec Pty Ltd, 2000
+
+ COPYRIGHT (c) 1989-1998.
+ On-Line Applications Research Corporation (OAR).
+
+ The license and distribution terms for this file may be
+ found in the file LICENSE in this distribution or at
+
+ http://www.rtems.com/license/LICENSE.
+
+ This software with is provided ``as is'' and with NO WARRANTY.
+
+ ------------------------------------------------------------------------
+
+ Set of helpers when creating a root file system. The root filesystem
+ in RTEMS is the In Memory Filesystem (IMFS). We could copy an exiting
+ filesystem to here, how-ever a number of files can have target
+ specific initialisation info which we need to write.
+
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <rtems/mkrootfs.h>
+
+/*
+ * A table a list of names and their modes.
+ */
+
+typedef struct rtems_rootfs_dir_table
+{
+ const char *name;
+ int mode;
+} rtems_rootfs_dir_table;
+
+/*
+ * Table of directorys to make.
+ */
+
+static const rtems_rootfs_dir_table default_directories[] =
+{
+ { "/bin", S_IFDIR | S_IRWXU | S_IXGRP | S_IRGRP | S_IROTH | S_IXOTH },
+ { "/etc", S_IFDIR | S_IRWXU | S_IXGRP | S_IRGRP | S_IROTH | S_IXOTH },
+ { "/dev", S_IFDIR | S_IRWXU | S_IXGRP | S_IRGRP | S_IROTH | S_IXOTH },
+ { "/usr/bin", S_IFDIR | S_IRWXU | S_IXGRP | S_IRGRP | S_IROTH | S_IXOTH }
+};
+
+#define MKFILE_MODE (S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH)
+#define MKDIR_MODE (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
+
+/*
+ * Build a path. Taken from the BSD `mkdir' command.
+ */
+
+int
+rtems_rootfs_mkdir (const char *path_orig, mode_t omode)
+{
+ struct stat sb;
+ mode_t numask, oumask;
+ int first, last, retval;
+ char path[128];
+ char *p = path;
+
+ if (strlen (path_orig) >= sizeof path)
+ {
+ printf ("root fs: mkdir path too long `%s'\n", path);
+ return -1;
+ }
+
+ strcpy (path, path_orig);
+ oumask = 0;
+ retval = 0;
+ if (p[0] == '/') /* Skip leading '/'. */
+ ++p;
+ for (first = 1, last = 0; !last ; ++p)
+ {
+ if (p[0] == '\0')
+ last = 1;
+ else if (p[0] != '/')
+ continue;
+ *p = '\0';
+ if (p[1] == '\0')
+ last = 1;
+ if (first)
+ {
+ /*
+ * POSIX 1003.2:
+ * For each dir operand that does not name an existing
+ * directory, effects equivalent to those cased by the
+ * following command shall occcur:
+ *
+ * mkdir -p -m $(umask -S),u+wx $(dirname dir) &&
+ * mkdir [-m mode] dir
+ *
+ * We change the user's umask and then restore it,
+ * instead of doing chmod's.
+ */
+ oumask = umask(0);
+ numask = oumask & ~(S_IWUSR | S_IXUSR);
+ umask(numask);
+ first = 0;
+ }
+ if (last)
+ umask(oumask);
+ if (stat(path, &sb))
+ {
+ if (errno != ENOENT)
+ {
+ printf ("root fs: error stat'ing path `%s', %s\n",
+ path, strerror (errno));
+ retval = 1;
+ break;
+ }
+ if (mkdir(path, last ? omode : S_IRWXU | S_IRWXG | S_IRWXO) < 0)
+ {
+ printf ("root fs: error building path `%s', %s\n",
+ path, strerror (errno));
+ retval = 1;
+ break;
+ }
+ }
+ else if ((sb.st_mode & S_IFMT) != S_IFDIR)
+ {
+ if (last)
+ errno = EEXIST;
+ else
+ errno = ENOTDIR;
+ printf ("root fs: path `%s' contains a file, %s\n",
+ path, strerror (errno));
+ retval = 1;
+ break;
+ }
+ if (!last)
+ *p = '/';
+ }
+ if (!first && !last)
+ umask(oumask);
+ return retval;
+}
+
+/*
+ * Create enough files to support the networking stack.
+ * Points to a table of strings.
+ */
+
+int
+rtems_rootfs_file_append (const char *file,
+ mode_t omode,
+ const int line_cnt,
+ const char **lines)
+{
+ struct stat sb;
+ int fd;
+ int i;
+
+ /*
+ * See is a file exists. If it does not, create the
+ * file and the path to the file.
+ */
+
+ fd = -1;
+
+ if (stat(file, &sb))
+ {
+ if (errno == ENOENT)
+ {
+ /*
+ * Get the path to the file if one exists and create the
+ * path. If it exists nothing happens.
+ */
+
+ int i = strlen (file);
+
+ while (i)
+ {
+ if (file[i] == '/')
+ {
+ char path[128];
+
+ if (i >= sizeof path)
+ {
+ printf ("root fs, path too long `%s'\n", file);
+ return -1;
+ }
+
+ strncpy (path, file, i);
+ path[i] = '\0';
+
+ if (rtems_rootfs_mkdir (path, MKDIR_MODE))
+ return -1;
+ break;
+ }
+ i--;
+ }
+
+ if ((fd = open (file, O_CREAT | O_APPEND | O_WRONLY, omode)) < 0)
+ {
+ printf ("root fs, cannot create file `%s' : %s\n",
+ file, strerror (errno));
+ return -1;
+ }
+ }
+ }
+
+ if (fd < 0)
+ {
+ if ((fd = open (file, O_APPEND | O_WRONLY)) < 0)
+ {
+ printf ("root fs, cannot open file `%s' : %s\n",
+ file, strerror (errno));
+ return -1;
+ }
+ }
+
+ for (i = 0; i < line_cnt; i++)
+ {
+ int len = strlen (lines[i]);
+
+ if (len)
+ {
+ if (write (fd, lines[i], strlen (lines[i])) < 0)
+ {
+ close (fd);
+ printf ("root fs, cannot write to `%s' : %s\n",
+ file, strerror (errno));
+ return -1;
+ }
+ }
+ }
+
+ return close (fd);
+}
+
+/*
+ * Write hosts record.
+ */
+
+int
+rtems_rootfs_append_host_rec (unsigned long cip,
+ const char *cname,
+ const char *dname)
+{
+ char buf[128];
+ char *bufp = buf;
+ const char *bufl[1];
+ struct in_addr ip;
+
+ ip.s_addr = cip;
+
+ if (cname && strlen (cname))
+ {
+ snprintf (bufp, sizeof (buf), "%s\t\t%s", inet_ntoa (ip), cname);
+ bufp += strlen (buf);
+
+ if (dname && strlen (dname))
+ {
+ snprintf (bufp, sizeof (buf), "\t\t%s.%s", cname, dname);
+ bufp += strlen (buf);
+ }
+
+ strcat (buf, "\n");
+
+ bufl[0] = buf;
+
+ if (rtems_rootfs_file_append ("/etc/hosts", MKFILE_MODE, 1, bufl) < 0)
+ return -1;
+ }
+ else
+ {
+ printf ("rootfs hosts rec append, no cname supplied\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Create a root file system.
+ */
+
+int
+rtems_create_root_fs ()
+{
+ const char *lines[1];
+ int i;
+
+ /*
+ * Create the directories.
+ */
+
+ for (i = 0;
+ i < (sizeof (default_directories) / sizeof (rtems_rootfs_dir_table));
+ i++)
+ if (rtems_rootfs_mkdir (default_directories[i].name,
+ default_directories[i].mode))
+ return -1;
+
+ /*
+ * The TCP/IP stack likes this one. If DNS does not work
+ * use the host file.
+ */
+
+ lines[0] = "hosts,bind\n";
+
+ if (rtems_rootfs_file_append ("/etc/host.conf", MKFILE_MODE, 1, lines))
+ return -1;
+
+ /*
+ * Create a `/etc/hosts' file.
+ */
+
+ if (rtems_rootfs_append_host_rec (0x7f000001, "localhost", "localdomain"))
+ return -1;
+
+ return 0;
+}
diff --git a/cpukit/libnetworking/rtems/mkrootfs.h b/cpukit/libnetworking/rtems/mkrootfs.h
new file mode 100644
index 0000000000..42bb944b2a
--- /dev/null
+++ b/cpukit/libnetworking/rtems/mkrootfs.h
@@ -0,0 +1,66 @@
+/*
+ ------------------------------------------------------------------------
+ $Id$
+ ------------------------------------------------------------------------
+
+ Copyright Cybertec Pty Ltd, 2000
+ All rights reserved Cybertec Pty Ltd, 2000
+
+ COPYRIGHT (c) 1989-1998.
+ On-Line Applications Research Corporation (OAR).
+
+ The license and distribution terms for this file may be
+ found in the file LICENSE in this distribution or at
+
+ http://www.rtems.com/license/LICENSE.
+
+ This software with is provided ``as is'' and with NO WARRANTY.
+
+ ------------------------------------------------------------------------
+
+ RTEMS Root FS creatation support.
+
+*/
+
+#ifndef __RTEMS_MKROOTFS_h
+#define __RTEMS_MKROOTFS_h
+
+#include <rtems.h>
+
+/*
+ * Builds the complete path, like "mkdir -p".
+ */
+
+int
+rtems_rootfs_mkdir (const char *path, mode_t omode);
+
+/*
+ * Appends the lines to the a file. Create the file
+ * and builds the path if it does not exist.
+ */
+
+int
+rtems_rootfs_file_append (const char *file,
+ mode_t omode,
+ const int line_cnt,
+ const char **lines);
+
+/*
+ * Helper for bulding an /etc/hosts file.
+ */
+
+int
+rtems_rootfs_append_host_rec (unsigned long cip,
+ const char *cname,
+ const char *dname);
+
+/*
+ * Create a few common directories, plus a :
+ * /etc/passwd, /etc/group, /etc/host.conf, and
+ * /etc/hosts file.
+ */
+
+int
+rtems_create_root_fs ();
+
+#endif
diff --git a/cpukit/libnetworking/rtems/rtems_bootp.c b/cpukit/libnetworking/rtems/rtems_bootp.c
new file mode 100644
index 0000000000..1bfdb11906
--- /dev/null
+++ b/cpukit/libnetworking/rtems/rtems_bootp.c
@@ -0,0 +1,32 @@
+/*
+ * $Id$
+ */
+
+#include <rtems.h>
+#include <rtems/error.h>
+#include <sys/types.h>
+#include <rtems/rtems_bsdnet.h>
+#include <rtems/rtems_bsdnet_internal.h>
+
+/*
+ * Perform a BOOTP request
+ */
+void
+rtems_bsdnet_do_bootp (void)
+{
+ rtems_bsdnet_semaphore_obtain ();
+ bootpc_init (FALSE);
+ rtems_bsdnet_semaphore_release ();
+}
+
+/*
+ * Perform a BOOTP request and update "standard" files in /etc
+ * with the results.
+ */
+void
+rtems_bsdnet_do_bootp_and_rootfs (void)
+{
+ rtems_bsdnet_semaphore_obtain ();
+ bootpc_init (TRUE);
+ rtems_bsdnet_semaphore_release ();
+}
diff --git a/cpukit/libnetworking/rtems/rtems_bsdnet.h b/cpukit/libnetworking/rtems/rtems_bsdnet.h
new file mode 100644
index 0000000000..e7ac7cd116
--- /dev/null
+++ b/cpukit/libnetworking/rtems/rtems_bsdnet.h
@@ -0,0 +1,192 @@
+/*
+ * $Id$
+ */
+
+#ifndef _RTEMS_BSDNET_
+#define _RTEMS_BSDNET_
+
+#include <rtems.h>
+
+/*
+ * If this file is included from inside the Network Stack proper or
+ * a device driver, then __INSIDE_RTEMS_BSD_TCPIP_STACK__ should be
+ * defined. This triggers a number of internally used definitions.
+ */
+
+#if defined(__INSIDE_RTEMS_BSD_TCPIP_STACK__)
+#undef _COMPILING_BSD_KERNEL_
+#undef _KERNEL
+#undef INET
+#undef NFS
+#undef DIAGNOSTIC
+#undef BOOTP_COMPAT
+
+#define _COMPILING_BSD_KERNEL_
+#define _KERNEL
+#define INET
+#define NFS
+#define DIAGNOSTIC
+#define BOOTP_COMPAT
+#endif
+
+/*
+ * Values that may be obtained by BOOTP
+ */
+extern struct in_addr rtems_bsdnet_bootp_server_address;
+extern char *rtems_bsdnet_bootp_server_name;
+extern char *rtems_bsdnet_bootp_boot_file_name;
+extern char *rtems_bsdnet_bootp_cmdline;
+extern struct in_addr rtems_bsdnet_ntpserver[];
+extern int rtems_bsdnet_ntpserver_count;
+extern long rtems_bsdnet_timeoffset;
+
+/*
+ * Manipulate routing tables
+ */
+struct sockaddr;
+struct rtentry;
+int rtems_bsdnet_rtrequest (
+ int req,
+ struct sockaddr *dst,
+ struct sockaddr *gateway,
+ struct sockaddr *netmask,
+ int flags,
+ struct rtentry **net_nrt);
+
+/*
+ * Diagnostics
+ */
+void rtems_bsdnet_show_inet_routes (void);
+void rtems_bsdnet_show_mbuf_stats (void);
+void rtems_bsdnet_show_if_stats (void);
+void rtems_bsdnet_show_ip_stats (void);
+void rtems_bsdnet_show_icmp_stats (void);
+void rtems_bsdnet_show_udp_stats (void);
+void rtems_bsdnet_show_tcp_stats (void);
+
+/*
+ * Network configuration
+ */
+struct rtems_bsdnet_ifconfig {
+ /*
+ * These three entries must be supplied for each interface.
+ */
+ char *name;
+
+ /*
+ * This function now handles attaching and detaching an interface.
+ * The parameter attaching indicates the operation being invoked.
+ * For older attach functions which do not have the extra parameter
+ * it will be ignored.
+ */
+ int (*attach)(struct rtems_bsdnet_ifconfig *conf, int attaching);
+
+ /*
+ * Link to next interface
+ */
+ struct rtems_bsdnet_ifconfig *next;
+
+ /*
+ * The following entries may be obtained
+ * from BOOTP or explicitily supplied.
+ */
+ char *ip_address;
+ char *ip_netmask;
+ void *hardware_address;
+
+ /*
+ * The driver assigns defaults values to the following
+ * entries if they are not explicitly supplied.
+ */
+ int ignore_broadcast;
+ int mtu;
+ int rbuf_count;
+ int xbuf_count;
+
+ /*
+ * For external ethernet controller board the following
+ * parameters are needed
+ */
+ unsigned int port; /* port of the board */
+ unsigned int irno; /* irq of the board */
+ unsigned int bpar; /* memory of the board */
+
+ /*
+ * Driver control block pointer. Typcially this points to the driver's
+ * controlling structure. You set this when you have the structure allocated
+ * externally to the driver.
+ */
+ void *drv_ctrl;
+
+};
+
+struct rtems_bsdnet_config {
+ /*
+ * This entry points to the head of the ifconfig chain.
+ */
+ struct rtems_bsdnet_ifconfig *ifconfig;
+
+ /*
+ * This entry should be rtems_bsdnet_do_bootp if BOOTP
+ * is being used to configure the network, and NULL
+ * if BOOTP is not being used.
+ */
+ void (*bootp)(void);
+
+ /*
+ * The remaining items can be initialized to 0, in
+ * which case the default value will be used.
+ */
+ rtems_task_priority network_task_priority; /* 100 */
+ unsigned long mbuf_bytecount; /* 64 kbytes */
+ unsigned long mbuf_cluster_bytecount; /* 128 kbytes */
+ char *hostname; /* BOOTP */
+ char *domainname; /* BOOTP */
+ char *gateway; /* BOOTP */
+ char *log_host; /* BOOTP */
+ char *name_server[3]; /* BOOTP */
+ char *ntp_server[3]; /* BOOTP */
+};
+
+/*
+ * Default global device configuration structure. This is scanned
+ * by the initialize network function. Check the network demo's for
+ * an example of the structure. Like the RTEMS configuration tables,
+ * they are not part of RTEMS but part of your application or bsp
+ * code.
+ */
+extern struct rtems_bsdnet_config rtems_bsdnet_config;
+
+/*
+ * Initialise the BSD stack, attach and `up' interfaces
+ * in the `rtems_bsdnet_config'. RTEMS must already be initialised.
+ */
+int rtems_bsdnet_initialize_network (void);
+
+/*
+ * Dynamic interface control. Drivers must free any resources such as
+ * memory, interrupts, io regions claimed during the `attach' and/or
+ * `up' operations when asked to `detach'.
+ * You must configure the interface after attaching it.
+ */
+void rtems_bsdnet_attach (struct rtems_bsdnet_ifconfig *ifconfig);
+void rtems_bsdnet_detach (struct rtems_bsdnet_ifconfig *ifconfig);
+
+/*
+ * Interface configuration. The commands are listed in `sys/sockio.h'.
+ */
+int rtems_bsdnet_ifconfig (const char *ifname, uint32_t cmd, void *param);
+
+void rtems_bsdnet_do_bootp (void);
+void rtems_bsdnet_do_bootp_and_rootfs (void);
+
+int rtems_bsdnet_synchronize_ntp (int interval, rtems_task_priority priority);
+
+/*
+ * Callback to report BSD malloc starvation.
+ * The default implementation just prints a message but an application
+ * can provide its own version.
+ */
+void rtems_bsdnet_malloc_starvation(void);
+
+#endif /* _RTEMS_BSDNET_ */
diff --git a/cpukit/libnetworking/rtems/rtems_bsdnet_internal.h b/cpukit/libnetworking/rtems/rtems_bsdnet_internal.h
new file mode 100644
index 0000000000..2f84138346
--- /dev/null
+++ b/cpukit/libnetworking/rtems/rtems_bsdnet_internal.h
@@ -0,0 +1,200 @@
+/*
+ * Declarations to fit FreeBSD to RTEMS.
+ *
+ *******************************************************************
+ * WARNING *
+ * This file should *never* be included by any application program *
+ *******************************************************************
+ *
+ * $Id$
+ */
+
+#ifndef _RTEMS_BSDNET_INTERNAL_H_
+#define _RTEMS_BSDNET_INTERNAL_H_
+
+#include <rtems.h>
+
+typedef unsigned int vm_offset_t;
+typedef long long vm_ooffset_t;
+typedef unsigned int vm_pindex_t;
+typedef unsigned int vm_size_t;
+
+#define _BSD_OFF_T_ int32_t
+#define _BSD_PID_T_ rtems_id
+#define _BSD_VA_LIST_ char *
+
+/* make sure we get the network versions of these */
+#include <machine/types.h>
+#include <machine/param.h>
+#include <rtems/cdefs.h>
+
+#include <sys/time.h>
+/*
+struct itimerval {
+ struct timeval it_interval;
+ struct timeval it_value;
+};
+*/
+struct mdproc {
+ int md_flags;
+ int *md_regs;
+};
+
+/*
+ * Other RTEMS/BSD glue
+ */
+struct socket;
+extern int soconnsleep (struct socket *so);
+extern void soconnwakeup (struct socket *so);
+#define splnet() 0
+#define splimp() 0
+#define splx(_s) do { (_s) = 0; } while(0)
+
+/* to avoid warnings */
+void *memcpy(void *dest, const void *src, size_t n);
+void *memset(void *s, int c, size_t n);
+
+#define ovbcopy(f,t,n) bcopy(f,t,n)
+#define copyout(f,t,n) (memcpy(t,f,n),0)
+#define copyin(f,t,n) (memcpy(t,f,n),0)
+
+#define random() rtems_bsdnet_random()
+#define panic rtems_panic
+#define suser(a,b) 0
+
+void microtime (struct timeval *tv);
+#define hz rtems_bsdnet_ticks_per_second
+#define tick rtems_bsdnet_microseconds_per_tick
+
+#define log rtems_bsdnet_log
+
+/*
+ * Since we can't have two sys/types.h files, we'll hack around
+ * and copy the contents of the BSD sys/types.h to here....
+ */
+#include <sys/cdefs.h>
+
+typedef u_int64_t u_quad_t; /* quads */
+typedef int64_t quad_t;
+typedef quad_t * qaddr_t;
+
+typedef void __sighandler_t __P((int));
+typedef __sighandler_t *sig_t; /* type of pointer to a signal function */
+#define NSIG 32
+struct sigaltstack {
+ char *ss_sp; /* signal stack base */
+ int ss_size; /* signal stack length */
+ int ss_flags; /* SS_DISABLE and/or SS_ONSTACK */
+};
+
+#ifdef _KERNEL
+typedef int boolean_t;
+typedef struct vm_page *vm_page_t;
+#endif
+
+#ifndef _POSIX_SOURCE
+/*
+ * minor() gives a cookie instead of an index since we don't want to
+ * change the meanings of bits 0-15 or waste time and space shifting
+ * bits 16-31 for devices that don't use them.
+ */
+#define major(x) ((int)(((u_int)(x) >> 8)&0xff)) /* major number */
+#define minor(x) ((int)((x)&0xffff00ff)) /* minor number */
+#define makedev(x,y) ((dev_t)(((x) << 8) | (y))) /* create dev_t */
+#endif
+
+#include <machine/endian.h>
+
+typedef quad_t rlim_t; /* resource limit */
+typedef u_int32_t fixpt_t; /* fixed point number */
+
+/*
+ * Forward structure declarations for function prototypes. We include the
+ * common structures that cross subsystem boundaries here; others are mostly
+ * used in the same place that the structure is defined.
+ */
+struct proc;
+struct pgrp;
+struct ucred;
+struct rusage;
+struct file;
+struct buf;
+struct tty;
+struct uio;
+struct rtems_bsdnet_ifconfig;
+
+/*
+ * Redo kernel memory allocation
+ */
+#define malloc rtems_bsdnet_malloc
+#define free rtems_bsdnet_free
+
+#define M_NOWAIT 0x0001
+void *rtems_bsdnet_malloc (unsigned long size, int type, int flags);
+void rtems_bsdnet_free (void *addr, int type);
+
+void rtems_bsdnet_semaphore_obtain (void);
+void rtems_bsdnet_semaphore_release (void);
+void rtems_bsdnet_schednetisr (int n);
+int rtems_bsdnet_parse_driver_name (const struct rtems_bsdnet_ifconfig *config, char **namep);
+
+unsigned long rtems_bsdnet_seconds_since_boot (void);
+unsigned long rtems_bsdnet_random (void);
+
+rtems_id rtems_bsdnet_newproc (
+ char *name,
+ int stacksize,
+ void (*entry)(void *),
+ void *arg
+);
+
+rtems_status_code rtems_bsdnet_event_receive (
+ rtems_event_set event_in,
+ rtems_option option_set,
+ rtems_interval ticks,
+ rtems_event_set *event_out
+);
+
+/*
+ * Network configuration
+ */
+extern int rtems_bsdnet_ticks_per_second;
+extern int rtems_bsdnet_microseconds_per_tick;
+extern struct in_addr rtems_bsdnet_log_host_address;
+extern char *rtems_bsdnet_domain_name;
+extern struct in_addr rtems_bsdnet_nameserver[];
+extern int rtems_bsdnet_nameserver_count;
+
+/*
+ * Internal IOCTL command
+ */
+#define SIO_RTEMS_SHOW_STATS _IO('i', 250)
+
+/*
+ * Some extra prototypes
+ */
+int sethostname (char *name, size_t namelen);
+void domaininit (void *);
+void ifinit (void *);
+void ipintr (void);
+void arpintr (void);
+void bootpc_init(int );
+int socket (int, int, int);
+int ioctl (int, int, ...);
+
+/*
+ * Events used by networking routines.
+ * Everything will break if the application
+ * tries to use these events or if the `sleep'
+ * events are equal to any of the NETISR * events.
+ */
+#define SBWAIT_EVENT RTEMS_EVENT_24
+#define SOSLEEP_EVENT RTEMS_EVENT_25
+#define NETISR_IP_EVENT (1 << NETISR_IP)
+#define NETISR_ARP_EVENT (1 << NETISR_ARP)
+#define NETISR_EVENTS (NETISR_IP_EVENT|NETISR_ARP_EVENT)
+#if (SBWAIT_EVENT & SOSLEEP_EVENT & NETISR_EVENTS)
+# error "Network event conflict"
+#endif
+
+#endif /* _RTEMS_BSDNET_INTERNAL_H_ */
diff --git a/cpukit/libnetworking/rtems/rtems_bsdnet_malloc_starvation.c b/cpukit/libnetworking/rtems/rtems_bsdnet_malloc_starvation.c
new file mode 100644
index 0000000000..52e78f00e2
--- /dev/null
+++ b/cpukit/libnetworking/rtems/rtems_bsdnet_malloc_starvation.c
@@ -0,0 +1,15 @@
+/*
+ * Routine called when malloc() is not succeeding. This can be overridden
+ * by a BSP.
+ *
+ * $Id*
+ */
+
+#include <stdio.h>
+#include <rtems/rtems_bsdnet.h>
+
+void
+rtems_bsdnet_malloc_starvation(void)
+{
+ printf ("rtems_bsdnet_malloc still waiting.\n");
+}
diff --git a/cpukit/libnetworking/rtems/rtems_glue.c b/cpukit/libnetworking/rtems/rtems_glue.c
new file mode 100644
index 0000000000..cded876081
--- /dev/null
+++ b/cpukit/libnetworking/rtems/rtems_glue.c
@@ -0,0 +1,1231 @@
+/*
+ * $Id$
+ */
+
+#define RTEMS_FAST_MUTEX
+
+#ifdef RTEMS_FAST_MUTEX
+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__ 1
+#endif
+
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <rtems/error.h>
+#include <rtems/rtems_bsdnet.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/domain.h>
+#include <sys/mbuf.h>
+#include <sys/socketvar.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/callout.h>
+#include <sys/proc.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <vm/vm.h>
+#include <arpa/inet.h>
+
+#include <net/netisr.h>
+#include <net/route.h>
+
+/*
+ * Sysctl init all.
+ */
+void sysctl_register_all(void *arg);
+
+/*
+ * Memory allocation
+ */
+static int nmbuf = (64 * 1024) / MSIZE;
+ int nmbclusters = (128 * 1024) / MCLBYTES;
+
+/*
+ * Socket buffering parameters
+ */
+unsigned long sb_efficiency = 8;
+
+/*
+ * Network task synchronization
+ */
+static rtems_id networkSemaphore;
+#ifdef RTEMS_FAST_MUTEX
+Semaphore_Control *the_networkSemaphore;
+#endif
+static rtems_id networkDaemonTid;
+static uint32_t networkDaemonPriority;
+static void networkDaemon (void *task_argument);
+
+/*
+ * Network timing
+ */
+int rtems_bsdnet_ticks_per_second;
+int rtems_bsdnet_microseconds_per_tick;
+
+/*
+ * Callout processing
+ */
+static rtems_interval ticksWhenCalloutsLastChecked;
+static struct callout *callfree, calltodo;
+
+/*
+ * FreeBSD variables
+ */
+int nfs_diskless_valid;
+
+/*
+ * BOOTP values
+ */
+struct in_addr rtems_bsdnet_log_host_address = {0};
+struct in_addr rtems_bsdnet_bootp_server_address = {0};
+char *rtems_bsdnet_bootp_boot_file_name = 0;
+char *rtems_bsdnet_bootp_server_name = 0;
+char *rtems_bsdnet_domain_name = 0;
+char *rtems_bsdnet_bootp_cmdline = 0;
+struct in_addr rtems_bsdnet_nameserver[sizeof rtems_bsdnet_config.name_server /
+ sizeof rtems_bsdnet_config.name_server[0]];
+int rtems_bsdnet_nameserver_count = 0;
+struct in_addr rtems_bsdnet_ntpserver[sizeof rtems_bsdnet_config.ntp_server /
+ sizeof rtems_bsdnet_config.ntp_server[0]];
+int rtems_bsdnet_ntpserver_count = 0;
+long rtems_bsdnet_timeoffset = 0;
+
+/*
+ * Perform FreeBSD memory allocation.
+ * FIXME: This should be modified to keep memory allocation statistics.
+ */
+#undef malloc
+#undef free
+extern void *malloc (size_t);
+extern void free (void *);
+void *
+rtems_bsdnet_malloc (unsigned long size, int type, int flags)
+{
+ void *p;
+ int try = 0;
+
+ for (;;) {
+ p = malloc (size);
+ if (p || (flags & M_NOWAIT))
+ return p;
+ rtems_bsdnet_semaphore_release ();
+ if (++try >= 30) {
+ rtems_bsdnet_malloc_starvation();
+ try = 0;
+ }
+ rtems_task_wake_after (rtems_bsdnet_ticks_per_second);
+ rtems_bsdnet_semaphore_obtain ();
+ }
+}
+
+/*
+ * Free FreeBSD memory
+ * FIXME: This should be modified to keep memory allocation statistics.
+ */
+void
+rtems_bsdnet_free (void *addr, int type)
+{
+ free (addr);
+}
+
+/*
+ * Do the initializations required by the BSD code
+ */
+static int
+bsd_init (void)
+{
+ int i;
+ char *p;
+
+ /*
+ * Set up mbuf cluster data strutures
+ */
+ p = malloc ((nmbclusters*MCLBYTES)+MCLBYTES-1);
+ if (p == NULL) {
+ printf ("Can't get network cluster memory.\n");
+ return -1;
+ }
+ p = (char *)(((unsigned long)p + (MCLBYTES-1)) & ~(MCLBYTES-1));
+ mbutl = (struct mbuf *)p;
+ for (i = 0; i < nmbclusters; i++) {
+ ((union mcluster *)p)->mcl_next = mclfree;
+ mclfree = (union mcluster *)p;
+ p += MCLBYTES;
+ mbstat.m_clfree++;
+ }
+ mbstat.m_clusters = nmbclusters;
+ mclrefcnt = malloc (nmbclusters);
+ if (mclrefcnt == NULL) {
+ printf ("Can't get mbuf cluster reference counts memory.\n");
+ return -1;
+ }
+ memset (mclrefcnt, '\0', nmbclusters);
+
+ /*
+ * Set up mbuf data structures
+ */
+
+ p = malloc(nmbuf * MSIZE + MSIZE - 1);
+ p = (char *)(((unsigned int)p + MSIZE - 1) & ~(MSIZE - 1));
+ if (p == NULL) {
+ printf ("Can't get network memory.\n");
+ return -1;
+ }
+ for (i = 0; i < nmbuf; i++) {
+ ((struct mbuf *)p)->m_next = mmbfree;
+ mmbfree = (struct mbuf *)p;
+ p += MSIZE;
+ }
+ mbstat.m_mbufs = nmbuf;
+ mbstat.m_mtypes[MT_FREE] = nmbuf;
+
+ /*
+ * Set up domains
+ */
+ {
+ extern struct domain routedomain;
+ extern struct domain inetdomain;
+
+ routedomain.dom_next = domains;
+ domains = &routedomain;
+ inetdomain.dom_next = domains;
+ domains = &inetdomain;
+ domaininit (NULL);
+ }
+
+ /*
+ * Setup the sysctl, normally done by a SYSINIT call.
+ */
+ sysctl_register_all(0);
+
+ /*
+ * Set up interfaces
+ */
+ ifinit (NULL);
+ return 0;
+}
+
+/*
+ * Initialize and start network operations
+ */
+static int
+rtems_bsdnet_initialize (void)
+{
+ rtems_status_code sc;
+
+ /*
+ * Set the priority of all network tasks
+ */
+ if (rtems_bsdnet_config.network_task_priority == 0)
+ networkDaemonPriority = 100;
+ else
+ networkDaemonPriority = rtems_bsdnet_config.network_task_priority;
+
+ /*
+ * Set the memory allocation limits
+ */
+ if (rtems_bsdnet_config.mbuf_bytecount)
+ nmbuf = rtems_bsdnet_config.mbuf_bytecount / MSIZE;
+ if (rtems_bsdnet_config.mbuf_cluster_bytecount)
+ nmbclusters = rtems_bsdnet_config.mbuf_cluster_bytecount / MCLBYTES;
+
+ /*
+ * Create the task-synchronization semaphore
+ */
+ sc = rtems_semaphore_create (rtems_build_name('B', 'S', 'D', 'n'),
+ 0,
+ RTEMS_PRIORITY |
+ RTEMS_BINARY_SEMAPHORE |
+ RTEMS_INHERIT_PRIORITY |
+ RTEMS_NO_PRIORITY_CEILING |
+ RTEMS_LOCAL,
+ 0,
+ &networkSemaphore);
+ if (sc != RTEMS_SUCCESSFUL) {
+ printf ("Can't create network seamphore: `%s'\n", rtems_status_text (sc));
+ return -1;
+ }
+#ifdef RTEMS_FAST_MUTEX
+ {
+ Objects_Locations location;
+ the_networkSemaphore = _Semaphore_Get( networkSemaphore, &location );
+ _Thread_Enable_dispatch();
+ }
+#endif
+
+ /*
+ * Compute clock tick conversion factors
+ */
+ rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &rtems_bsdnet_ticks_per_second);
+ if (rtems_bsdnet_ticks_per_second <= 0)
+ rtems_bsdnet_ticks_per_second = 1;
+ rtems_bsdnet_microseconds_per_tick = 1000000 / rtems_bsdnet_ticks_per_second;
+
+ /*
+ * Ensure that `seconds' is greater than 0
+ */
+ while (rtems_bsdnet_seconds_since_boot() == 0)
+ rtems_task_wake_after(1);
+
+ /*
+ * Set up BSD-style sockets
+ */
+ if (bsd_init () < 0)
+ return -1;
+
+ /*
+ * Start network daemon
+ */
+ networkDaemonTid = rtems_bsdnet_newproc ("ntwk", 4096, networkDaemon, NULL);
+
+ /*
+ * Let other network tasks begin
+ */
+ rtems_bsdnet_semaphore_release ();
+ return 0;
+}
+
+/*
+ * Obtain network mutex
+ */
+void
+rtems_bsdnet_semaphore_obtain (void)
+{
+#ifdef RTEMS_FAST_MUTEX
+ ISR_Level level;
+ _ISR_Disable (level);
+ _CORE_mutex_Seize (
+ &the_networkSemaphore->Core_control.mutex,
+ networkSemaphore,
+ 1, /* wait */
+ 0, /* forever */
+ level
+ );
+ if (_Thread_Executing->Wait.return_code)
+ rtems_panic ("Can't obtain network semaphore\n");
+#else
+ rtems_status_code sc;
+
+ sc = rtems_semaphore_obtain (networkSemaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_panic ("Can't obtain network semaphore: `%s'\n", rtems_status_text (sc));
+#endif
+}
+
+/*
+ * Release network mutex
+ */
+void
+rtems_bsdnet_semaphore_release (void)
+{
+#ifdef RTEMS_FAST_MUTEX
+ int i;
+
+ _Thread_Disable_dispatch();
+ i = _CORE_mutex_Surrender (
+ &the_networkSemaphore->Core_control.mutex,
+ networkSemaphore,
+ NULL
+ );
+ _Thread_Enable_dispatch();
+ if (i)
+ rtems_panic ("Can't release network semaphore\n");
+#else
+ rtems_status_code sc;
+
+ sc = rtems_semaphore_release (networkSemaphore);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_panic ("Can't release network semaphore: `%s'\n", rtems_status_text (sc));
+#endif
+}
+
+/*
+ * Wait for something to happen to a socket buffer
+ */
+int
+sbwait(sb)
+ struct sockbuf *sb;
+{
+ rtems_event_set events;
+ rtems_id tid;
+ rtems_status_code sc;
+
+ /*
+ * Soak up any pending events.
+ * The sleep/wakeup synchronization in the FreeBSD
+ * kernel has no memory.
+ */
+ rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT, &events);
+
+ /*
+ * Set this task as the target of the wakeup operation.
+ */
+ rtems_task_ident (RTEMS_SELF, 0, &tid);
+ sb->sb_sel.si_pid = tid;
+
+ /*
+ * Show that socket is waiting
+ */
+ sb->sb_flags |= SB_WAIT;
+
+ /*
+ * Release the network semaphore.
+ */
+ rtems_bsdnet_semaphore_release ();
+
+ /*
+ * Wait for the wakeup event.
+ */
+ sc = rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, sb->sb_timeo, &events);
+
+ /*
+ * Reobtain the network semaphore.
+ */
+ rtems_bsdnet_semaphore_obtain ();
+
+ /*
+ * Return the status of the wait.
+ */
+ switch (sc) {
+ case RTEMS_SUCCESSFUL: return 0;
+ case RTEMS_TIMEOUT: return EWOULDBLOCK;
+ default: return ENXIO;
+ }
+}
+
+
+/*
+ * Wake up the task waiting on a socket buffer.
+ */
+void
+sowakeup(so, sb)
+ register struct socket *so;
+ register struct sockbuf *sb;
+{
+ if (sb->sb_flags & SB_WAIT) {
+ sb->sb_flags &= ~SB_WAIT;
+ rtems_event_send (sb->sb_sel.si_pid, SBWAIT_EVENT);
+ }
+ if (sb->sb_wakeup) {
+ (*sb->sb_wakeup) (so, sb->sb_wakeuparg);
+ }
+}
+
+/*
+ * For now, a socket can be used by only one task at a time.
+ */
+int
+sb_lock(sb)
+ register struct sockbuf *sb;
+{
+ rtems_panic ("Socket buffer is already in use.");
+ return 0;
+}
+void
+wakeup (void *p)
+{
+ rtems_panic ("Wakeup called");
+}
+
+/*
+ * Wait for a connection/disconnection event.
+ */
+int
+soconnsleep (struct socket *so)
+{
+ rtems_event_set events;
+ rtems_id tid;
+ rtems_status_code sc;
+
+ /*
+ * Soak up any pending events.
+ * The sleep/wakeup synchronization in the FreeBSD
+ * kernel has no memory.
+ */
+ rtems_event_receive (SOSLEEP_EVENT, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT, &events);
+
+ /*
+ * Set this task as the target of the wakeup operation.
+ */
+ if (so->so_pgid)
+ rtems_panic ("Another task is already sleeping on that socket");
+ rtems_task_ident (RTEMS_SELF, 0, &tid);
+ so->so_pgid = tid;
+
+ /*
+ * Wait for the wakeup event.
+ */
+ sc = rtems_bsdnet_event_receive (SOSLEEP_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, so->so_rcv.sb_timeo, &events);
+
+ /*
+ * Relinquish ownership of the socket.
+ */
+ so->so_pgid = 0;
+
+ switch (sc) {
+ case RTEMS_SUCCESSFUL: return 0;
+ case RTEMS_TIMEOUT: return EWOULDBLOCK;
+ default: return ENXIO;
+ }
+}
+
+/*
+ * Wake up a task waiting for a connection/disconnection to complete.
+ */
+void
+soconnwakeup (struct socket *so)
+{
+ if (so->so_pgid)
+ rtems_event_send (so->so_pgid, SOSLEEP_EVENT);
+}
+
+/*
+ * Send an event to the network daemon.
+ * This corresponds to sending a software interrupt in the BSD kernel.
+ */
+void
+rtems_bsdnet_schednetisr (int n)
+{
+ rtems_event_send (networkDaemonTid, 1 << n);
+}
+
+/*
+ * The network daemon
+ * This provides a context to run BSD software interrupts
+ */
+static void
+networkDaemon (void *task_argument)
+{
+ rtems_status_code sc;
+ rtems_event_set events;
+ rtems_interval now;
+ int ticksPassed;
+ uint32_t timeout;
+ struct callout *c;
+
+ for (;;) {
+ c = calltodo.c_next;
+ if (c)
+ timeout = c->c_time;
+ else
+ timeout = RTEMS_NO_TIMEOUT;
+
+ sc = rtems_bsdnet_event_receive (NETISR_EVENTS,
+ RTEMS_EVENT_ANY | RTEMS_WAIT,
+ timeout,
+ &events);
+ if ( sc == RTEMS_SUCCESSFUL ) {
+ if (events & NETISR_IP_EVENT)
+ ipintr ();
+ if (events & NETISR_ARP_EVENT)
+ arpintr ();
+ }
+
+ rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
+ ticksPassed = now - ticksWhenCalloutsLastChecked;
+ if (ticksPassed != 0) {
+ ticksWhenCalloutsLastChecked = now;
+
+ c = calltodo.c_next;
+ if (c) {
+ c->c_time -= ticksPassed;
+ while ((c = calltodo.c_next) != NULL && c->c_time <= 0) {
+ void *arg;
+ void (*func) (void *);
+
+ func = c->c_func;
+ arg = c->c_arg;
+ calltodo.c_next = c->c_next;
+ c->c_next = callfree;
+ callfree = c;
+ (*func)(arg);
+ }
+ }
+ }
+ }
+}
+
+/*
+ * Structure passed to task-start stub
+ */
+struct newtask {
+ void (*entry)(void *);
+ void *arg;
+};
+
+/*
+ * Task-start stub
+ */
+static void
+taskEntry (rtems_task_argument arg)
+{
+ struct newtask t;
+
+ /*
+ * Pick up task information and free
+ * the memory allocated to pass the
+ * information to this task.
+ */
+ t = *(struct newtask *)arg;
+ free ((struct newtask *)arg);
+
+ /*
+ * Enter the competition for the network semaphore
+ */
+ rtems_bsdnet_semaphore_obtain ();
+
+ /*
+ * Enter the task
+ */
+ (*t.entry)(t.arg);
+ rtems_panic ("Network task returned!\n");
+}
+
+/*
+ * Start a network task
+ */
+rtems_id
+rtems_bsdnet_newproc (char *name, int stacksize, void(*entry)(void *), void *arg)
+{
+ struct newtask *t;
+ char nm[4];
+ rtems_id tid;
+ rtems_status_code sc;
+
+ strncpy (nm, name, 4);
+ sc = rtems_task_create (rtems_build_name(nm[0], nm[1], nm[2], nm[3]),
+ networkDaemonPriority,
+ stacksize,
+ RTEMS_PREEMPT|RTEMS_NO_TIMESLICE|RTEMS_NO_ASR|RTEMS_INTERRUPT_LEVEL(0),
+ RTEMS_NO_FLOATING_POINT|RTEMS_LOCAL,
+ &tid);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_panic ("Can't create network daemon `%s': `%s'\n", name, rtems_status_text (sc));
+
+ /*
+ * Set up task arguments
+ */
+ t = malloc (sizeof *t);
+ t->entry = entry;
+ t->arg = arg;
+
+ /*
+ * Start the task
+ */
+ sc = rtems_task_start (tid, taskEntry, (rtems_task_argument)t);
+ if (sc != RTEMS_SUCCESSFUL)
+ rtems_panic ("Can't start network daemon `%s': `%s'\n", name, rtems_status_text (sc));
+
+ /*
+ * Let our caller know the i.d. of the new task
+ */
+ return tid;
+}
+
+rtems_status_code rtems_bsdnet_event_receive (
+ rtems_event_set event_in,
+ rtems_option option_set,
+ rtems_interval ticks,
+ rtems_event_set *event_out)
+{
+ rtems_status_code sc;
+
+ rtems_bsdnet_semaphore_release ();
+ sc = rtems_event_receive (event_in, option_set, ticks, event_out);
+ rtems_bsdnet_semaphore_obtain ();
+ return sc;
+}
+
+/*
+ * Return time since startup
+ */
+void
+microtime (struct timeval *t)
+{
+ rtems_interval now;
+
+ rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
+ t->tv_sec = now / rtems_bsdnet_ticks_per_second;
+ t->tv_usec = (now % rtems_bsdnet_ticks_per_second) * rtems_bsdnet_microseconds_per_tick;
+}
+
+unsigned long
+rtems_bsdnet_seconds_since_boot (void)
+{
+ rtems_interval now;
+
+ rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
+ return now / rtems_bsdnet_ticks_per_second;
+}
+
+/*
+ * Fake random number generator
+ */
+unsigned long
+rtems_bsdnet_random (void)
+{
+ rtems_interval now;
+
+ rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
+ return (now * 99991);
+}
+
+/*
+ * Callout list processing
+ */
+void
+timeout(void (*ftn)(void *), void *arg, int ticks)
+{
+ register struct callout *new, *p, *t;
+
+ if (ticks <= 0)
+ ticks = 1;
+
+ /* Fill in the next free callout structure. */
+ if (callfree == NULL) {
+ callfree = malloc (sizeof *callfree);
+ if (callfree == NULL)
+ rtems_panic ("No memory for timeout table entry");
+ callfree->c_next = NULL;
+ }
+
+ new = callfree;
+ callfree = new->c_next;
+ new->c_arg = arg;
+ new->c_func = ftn;
+
+ /*
+ * The time for each event is stored as a difference from the time
+ * of the previous event on the queue. Walk the queue, correcting
+ * the ticks argument for queue entries passed. Correct the ticks
+ * value for the queue entry immediately after the insertion point
+ * as well. Watch out for negative c_time values; these represent
+ * overdue events.
+ */
+ for (p = &calltodo;
+ (t = p->c_next) != NULL && ticks > t->c_time; p = t)
+ if (t->c_time > 0)
+ ticks -= t->c_time;
+ new->c_time = ticks;
+ if (t != NULL)
+ t->c_time -= ticks;
+
+ /* Insert the new entry into the queue. */
+ p->c_next = new;
+ new->c_next = t;
+}
+
+/*
+ * Ticks till specified time
+ * XXX: This version worries only about seconds, but that's good
+ * enough for the way the network code uses this routine.
+ */
+int
+hzto(struct timeval *tv)
+{
+ long diff = tv->tv_sec - rtems_bsdnet_seconds_since_boot();
+
+ if (diff <= 0)
+ return 1;
+ return diff * rtems_bsdnet_ticks_per_second;
+}
+
+/*
+ * Kernel debugging
+ */
+int rtems_bsdnet_log_priority;
+void
+rtems_bsdnet_log (int priority, const char *fmt, ...)
+{
+ va_list args;
+
+ if (priority & rtems_bsdnet_log_priority) {
+ va_start (args, fmt);
+ vprintf (fmt, args);
+ va_end (args);
+ }
+}
+
+/*
+ * IP header checksum routine for processors which don't have an inline version
+ */
+u_int
+in_cksum_hdr (const void *ip)
+{
+ uint32_t sum;
+ const uint16_t *sp;
+ int i;
+
+ sum = 0;
+ sp = (uint16_t *)ip;
+ for (i = 0 ; i < 10 ; i++)
+ sum += *sp++;
+ while (sum > 0xFFFF)
+ sum = (sum & 0xffff) + (sum >> 16);
+ return ~sum & 0xFFFF;
+}
+
+/*
+ * Manipulate routing tables
+ */
+int rtems_bsdnet_rtrequest (
+ int req,
+ struct sockaddr *dst,
+ struct sockaddr *gateway,
+ struct sockaddr *netmask,
+ int flags,
+ struct rtentry **net_nrt)
+{
+ int error;
+
+ rtems_bsdnet_semaphore_obtain ();
+ error = rtrequest (req, dst, gateway, netmask, flags, net_nrt);
+ rtems_bsdnet_semaphore_release ();
+ if (error) {
+ errno = error;
+ return -1;
+ }
+ return 0;
+}
+
+static int
+rtems_bsdnet_setup (void)
+{
+ struct rtems_bsdnet_ifconfig *ifp;
+ short flags;
+ struct sockaddr_in address;
+ struct sockaddr_in netmask;
+ struct sockaddr_in broadcast;
+ struct sockaddr_in gateway;
+ int i;
+ extern char *strdup (const char *cp);
+
+ /*
+ * Set local parameters
+ */
+ if (rtems_bsdnet_config.hostname)
+ sethostname (rtems_bsdnet_config.hostname,
+ strlen (rtems_bsdnet_config.hostname));
+ if (rtems_bsdnet_config.domainname)
+ rtems_bsdnet_domain_name =
+ strdup (rtems_bsdnet_config.domainname);
+ if (rtems_bsdnet_config.log_host)
+ rtems_bsdnet_log_host_address.s_addr =
+ inet_addr (rtems_bsdnet_config.log_host);
+ for (i = 0 ; i < sizeof rtems_bsdnet_config.name_server /
+ sizeof rtems_bsdnet_config.name_server[0] ; i++) {
+ if (!rtems_bsdnet_config.name_server[i])
+ break;
+ rtems_bsdnet_nameserver[rtems_bsdnet_nameserver_count++].s_addr
+ = inet_addr (rtems_bsdnet_config.name_server[i]);
+ }
+ for (i = 0 ; i < sizeof rtems_bsdnet_config.ntp_server /
+ sizeof rtems_bsdnet_config.ntp_server[0] ; i++) {
+ if (!rtems_bsdnet_config.ntp_server[i])
+ break;
+ rtems_bsdnet_ntpserver[rtems_bsdnet_ntpserver_count++].s_addr
+ = inet_addr (rtems_bsdnet_config.ntp_server[i]);
+ }
+
+ /*
+ * Configure interfaces
+ */
+ for (ifp = rtems_bsdnet_config.ifconfig ; ifp ; ifp = ifp->next) {
+ if (ifp->ip_address == NULL)
+ continue;
+
+ /*
+ * Bring interface up
+ */
+ flags = IFF_UP;
+ if (rtems_bsdnet_ifconfig (ifp->name, SIOCSIFFLAGS, &flags) < 0) {
+ printf ("Can't bring %s up: %s\n", ifp->name, strerror (errno));
+ continue;
+ }
+
+ /*
+ * Set interface netmask
+ */
+ memset (&netmask, '\0', sizeof netmask);
+ netmask.sin_len = sizeof netmask;
+ netmask.sin_family = AF_INET;
+ netmask.sin_addr.s_addr = inet_addr (ifp->ip_netmask);
+ if (rtems_bsdnet_ifconfig (ifp->name, SIOCSIFNETMASK, &netmask) < 0) {
+ printf ("Can't set %s netmask: %s\n", ifp->name, strerror (errno));
+ continue;
+ }
+
+ /*
+ * Set interface address
+ */
+ memset (&address, '\0', sizeof address);
+ address.sin_len = sizeof address;
+ address.sin_family = AF_INET;
+ address.sin_addr.s_addr = inet_addr (ifp->ip_address);
+ if (rtems_bsdnet_ifconfig (ifp->name, SIOCSIFADDR, &address) < 0) {
+ printf ("Can't set %s address: %s\n", ifp->name, strerror (errno));
+ continue;
+ }
+
+ /*
+ * Set interface broadcast address if the interface has the
+ * broadcast flag set.
+ */
+ if (rtems_bsdnet_ifconfig (ifp->name, SIOCGIFFLAGS, &flags) < 0) {
+ printf ("Can't read %s flags: %s\n", ifp->name, strerror (errno));
+ continue;
+ }
+ if (flags & IFF_BROADCAST) {
+ memset (&broadcast, '\0', sizeof broadcast);
+ broadcast.sin_len = sizeof broadcast;
+ broadcast.sin_family = AF_INET;
+ broadcast.sin_addr.s_addr =
+ address.sin_addr.s_addr | ~netmask.sin_addr.s_addr;
+ if (rtems_bsdnet_ifconfig (ifp->name, SIOCSIFBRDADDR, &broadcast) < 0) {
+ struct in_addr in_addr;
+ char buf[20];
+ in_addr.s_addr = broadcast.sin_addr.s_addr;
+ if (!inet_ntop(AF_INET, &in_addr, buf, sizeof(buf)))
+ strcpy(buf,"?.?.?.?");
+ printf ("Can't set %s broadcast address %s: %s\n",
+ ifp->name, buf, strerror (errno));
+ }
+ }
+ }
+
+ /*
+ * Set default route
+ */
+ if (rtems_bsdnet_config.gateway) {
+ address.sin_addr.s_addr = INADDR_ANY;
+ netmask.sin_addr.s_addr = INADDR_ANY;
+ memset (&gateway, '\0', sizeof gateway);
+ gateway.sin_len = sizeof gateway;
+ gateway.sin_family = AF_INET;
+ gateway.sin_addr.s_addr = inet_addr (rtems_bsdnet_config.gateway);
+ if (rtems_bsdnet_rtrequest (
+ RTM_ADD,
+ (struct sockaddr *)&address,
+ (struct sockaddr *)&gateway,
+ (struct sockaddr *)&netmask,
+ (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL) < 0) {
+ printf ("Can't set default route: %s\n", strerror (errno));
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Initialize the network
+ */
+int
+rtems_bsdnet_initialize_network (void)
+{
+ struct rtems_bsdnet_ifconfig *ifp;
+
+ /*
+ * Start network tasks.
+ * Initialize BSD network data structures.
+ */
+ if (rtems_bsdnet_initialize () < 0)
+ return -1;
+
+ /*
+ * Attach interfaces
+ */
+ for (ifp = rtems_bsdnet_config.ifconfig ; ifp ; ifp = ifp->next) {
+ rtems_bsdnet_attach (ifp);
+ }
+
+ /*
+ * Bring up the network
+ */
+ if (rtems_bsdnet_setup () < 0)
+ return -1;
+ if (rtems_bsdnet_config.bootp)
+ (*rtems_bsdnet_config.bootp)();
+ return 0;
+}
+
+/*
+ * Attach a network interface.
+ */
+void rtems_bsdnet_attach (struct rtems_bsdnet_ifconfig *ifp)
+{
+ if (ifp) {
+ rtems_bsdnet_semaphore_obtain ();
+ (ifp->attach)(ifp, 1);
+ rtems_bsdnet_semaphore_release ();
+ }
+}
+
+/*
+ * Detach a network interface.
+ */
+void rtems_bsdnet_detach (struct rtems_bsdnet_ifconfig *ifp)
+{
+ if (ifp) {
+ rtems_bsdnet_semaphore_obtain ();
+ (ifp->attach)(ifp, 0);
+ rtems_bsdnet_semaphore_release ();
+ }
+}
+
+/*
+ * Interface Configuration.
+ */
+int rtems_bsdnet_ifconfig (const char *ifname, uint32_t cmd, void *param)
+{
+ int s, r = 0;
+ struct ifreq ifreq;
+
+ /*
+ * Configure interfaces
+ */
+ s = socket (AF_INET, SOCK_DGRAM, 0);
+ if (s < 0)
+ return -1;
+
+ strncpy (ifreq.ifr_name, ifname, IFNAMSIZ);
+
+ rtems_bsdnet_semaphore_obtain ();
+
+ switch (cmd) {
+ case SIOCSIFADDR:
+ case SIOCSIFNETMASK:
+ memcpy (&ifreq.ifr_addr, param, sizeof (struct sockaddr));
+ r = ioctl (s, cmd, &ifreq);
+ break;
+
+ case OSIOCGIFADDR:
+ case SIOCGIFADDR:
+ case OSIOCGIFNETMASK:
+ case SIOCGIFNETMASK:
+ if ((r = ioctl (s, cmd, &ifreq)) < 0)
+ break;
+ memcpy (param, &ifreq.ifr_addr, sizeof (struct sockaddr));
+ break;
+
+ case SIOCGIFFLAGS:
+ case SIOCSIFFLAGS:
+ if ((r = ioctl (s, SIOCGIFFLAGS, &ifreq)) < 0)
+ break;
+ if (cmd == SIOCGIFFLAGS) {
+ *((short*) param) = ifreq.ifr_flags;
+ break;
+ }
+ ifreq.ifr_flags |= *((short*) param);
+ if ( (*((short*) param) & IFF_UP ) == 0 ) {
+ /* set the interface down */
+ ifreq.ifr_flags &= ~(IFF_UP);
+ }
+ r = ioctl (s, SIOCSIFFLAGS, &ifreq);
+ break;
+
+ case SIOCSIFDSTADDR:
+ memcpy (&ifreq.ifr_dstaddr, param, sizeof (struct sockaddr));
+ r = ioctl (s, cmd, &ifreq);
+ break;
+
+ case OSIOCGIFDSTADDR:
+ case SIOCGIFDSTADDR:
+ if ((r = ioctl (s, cmd, &ifreq)) < 0)
+ break;
+ memcpy (param, &ifreq.ifr_dstaddr, sizeof (struct sockaddr));
+ break;
+
+ case SIOCSIFBRDADDR:
+ memcpy (&ifreq.ifr_broadaddr, param, sizeof (struct sockaddr));
+ r = ioctl (s, cmd, &ifreq);
+ break;
+
+ case OSIOCGIFBRDADDR:
+ case SIOCGIFBRDADDR:
+ if ((r = ioctl (s, cmd, &ifreq)) < 0)
+ break;
+ memcpy (param, &ifreq.ifr_broadaddr, sizeof (struct sockaddr));
+ break;
+
+ case SIOCSIFMETRIC:
+ ifreq.ifr_metric = *((int*) param);
+ r = ioctl (s, cmd, &ifreq);
+ break;
+
+ case SIOCGIFMETRIC:
+ if ((r = ioctl (s, cmd, &ifreq)) < 0)
+ break;
+ *((int*) param) = ifreq.ifr_metric;
+ break;
+
+ case SIOCSIFMTU:
+ ifreq.ifr_mtu = *((int*) param);
+ r = ioctl (s, cmd, &ifreq);
+ break;
+
+ case SIOCGIFMTU:
+ if ((r = ioctl (s, cmd, &ifreq)) < 0)
+ break;
+ *((int*) param) = ifreq.ifr_mtu;
+ break;
+
+ case SIOCSIFPHYS:
+ ifreq.ifr_phys = *((int*) param);
+ r = ioctl (s, cmd, &ifreq);
+ break;
+
+ case SIOCGIFPHYS:
+ if ((r = ioctl (s, cmd, &ifreq)) < 0)
+ break;
+ *((int*) param) = ifreq.ifr_phys;
+ break;
+
+ case SIOCSIFMEDIA:
+ ifreq.ifr_media = *((int*) param);
+ r = ioctl (s, cmd, &ifreq);
+ break;
+
+ case SIOCGIFMEDIA:
+ if ((r = ioctl (s, cmd, &ifreq)) < 0)
+ break;
+ *((int*) param) = ifreq.ifr_media;
+ break;
+
+ case SIOCAIFADDR:
+ case SIOCDIFADDR:
+ r = ioctl(s, cmd, (struct freq *) param);
+ break;
+
+ default:
+ errno = EOPNOTSUPP;
+ r = -1;
+ break;
+ }
+
+ rtems_bsdnet_semaphore_release ();
+
+ close (s);
+ return r;
+}
+
+/*
+ * Parse a network driver name into a name and a unit number
+ */
+int
+rtems_bsdnet_parse_driver_name (const struct rtems_bsdnet_ifconfig *config, char **namep)
+{
+ const char *cp = config->name;
+ char c;
+ int unitNumber = 0;
+
+ if (cp == NULL) {
+ printf ("No network driver name.\n");
+ return -1;
+ }
+ while ((c = *cp++) != '\0') {
+ if ((c >= '0') && (c <= '9')) {
+ int len = cp - config->name;
+ if ((len < 2) || (len > 50))
+ break;
+ for (;;) {
+ unitNumber = (unitNumber * 10) + (c - '0');
+ c = *cp++;
+ if (c == '\0') {
+ char *unitName = malloc (len);
+ if (unitName == NULL) {
+ printf ("No memory.\n");
+ return -1;
+ }
+ strncpy (unitName, config->name, len - 1);
+ unitName[len-1] = '\0';
+ *namep = unitName;
+ return unitNumber;
+ }
+ if ((c < '0') || (c > '9'))
+ break;
+ }
+ break;
+ }
+ }
+ printf ("Bad network driver name `%s'.\n", config->name);
+ return -1;
+}
+
+/*
+ * Handle requests for more network memory
+ * XXX: Another possibility would be to use a semaphore here with
+ * a release in the mbuf free macro. I have chosen this `polling'
+ * approach because:
+ * 1) It is simpler.
+ * 2) It adds no complexity to the free macro.
+ * 3) Running out of mbufs should be a rare
+ * condition -- predeployment testing of
+ * an application should indicate the
+ * required mbuf pool size.
+ * XXX: Should there be a panic if a task is stuck in the loop for
+ * more than a minute or so?
+ */
+int
+m_mballoc (int nmb, int nowait)
+{
+ if (nowait)
+ return 0;
+ m_reclaim ();
+ if (mmbfree == NULL) {
+ int try = 0;
+ int print_limit = 30 * rtems_bsdnet_ticks_per_second;
+
+ mbstat.m_wait++;
+ for (;;) {
+ rtems_bsdnet_semaphore_release ();
+ rtems_task_wake_after (1);
+ rtems_bsdnet_semaphore_obtain ();
+ if (mmbfree)
+ break;
+ if (++try >= print_limit) {
+ printf ("Still waiting for mbuf.\n");
+ try = 0;
+ }
+ }
+ }
+ else {
+ mbstat.m_drops++;
+ }
+ return 1;
+}
+
+int
+m_clalloc(ncl, nowait)
+{
+ if (nowait)
+ return 0;
+ m_reclaim ();
+ if (mclfree == NULL) {
+ int try = 0;
+ int print_limit = 30 * rtems_bsdnet_ticks_per_second;
+
+ mbstat.m_wait++;
+ for (;;) {
+ rtems_bsdnet_semaphore_release ();
+ rtems_task_wake_after (1);
+ rtems_bsdnet_semaphore_obtain ();
+ if (mclfree)
+ break;
+ if (++try >= print_limit) {
+ printf ("Still waiting for mbuf cluster.\n");
+ try = 0;
+ }
+ }
+ }
+ else {
+ mbstat.m_drops++;
+ }
+ return 1;
+}
diff --git a/cpukit/libnetworking/rtems/rtems_select.c b/cpukit/libnetworking/rtems/rtems_select.c
new file mode 100644
index 0000000000..a3e55562fd
--- /dev/null
+++ b/cpukit/libnetworking/rtems/rtems_select.c
@@ -0,0 +1,174 @@
+/*
+ * $Id$
+ */
+
+#include <string.h>
+#include <stdarg.h>
+/* #include <stdlib.h> */
+#include <stdio.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <rtems/error.h>
+#include <rtems/rtems_bsdnet.h>
+
+#include <sys/errno.h>
+#include <sys/fcntl.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/protosw.h>
+#include <sys/proc.h>
+#include <sys/filio.h>
+
+#include <net/if.h>
+#include <net/route.h>
+
+/*
+ *********************************************************************
+ * RTEMS implementation of select() system call *
+ *********************************************************************
+ */
+
+/*
+ * This implementation is quite restricted:
+ * Works on sockets only -- no support for other devices!
+ * A given socket can be in a read-select or a read/recv* by only
+ * one task at a time.
+ * A given socket can be in a write-select or a write/send* by only
+ * one task at a time.
+ *
+ * NOTE - select() is a very expensive system call. It should be avoided
+ * if at all possible. In many cases, rewriting the application
+ * to use multiple tasks (one per socket) is a better solution.
+ */
+
+static __inline int imin(int a, int b) { return (a < b ? a : b); }
+struct socket *rtems_bsdnet_fdToSocket(int fd);
+
+static int
+socket_select (struct socket *so, int which, rtems_id tid)
+{
+ switch (which) {
+
+ case FREAD:
+ if (soreadable(so))
+ return (1);
+ so->so_rcv.sb_flags |= SB_WAIT;
+ so->so_rcv.sb_sel.si_pid = tid;
+ break;
+
+ case FWRITE:
+ if (sowriteable(so))
+ return (1);
+ so->so_rcv.sb_flags |= SB_WAIT;
+ so->so_snd.sb_sel.si_pid = tid;
+ break;
+
+ case 0:
+ if (so->so_oobmark || (so->so_state & SS_RCVATMARK))
+ return (1);
+ so->so_rcv.sb_sel.si_pid = tid;
+ break;
+ }
+ return (0);
+}
+
+static int
+selscan (rtems_id tid, fd_mask **ibits, fd_mask **obits, int nfd, int *retval)
+{
+ struct socket *so;
+ int msk, i, fd;
+ fd_mask bits, bit;
+ int n = 0;
+ static int flag[3] = { FREAD, FWRITE, 0 };
+
+ for (msk = 0; msk < 3; msk++) {
+ if (ibits[msk] == NULL)
+ continue;
+ for (i = 0; i < nfd; i += NFDBITS) {
+ bits = ibits[msk][i/NFDBITS];
+ for (fd = i, bit = 1 ; bits && (fd < nfd) ; fd++, bit <<= 1) {
+ if ((bits & bit) == 0)
+ continue;
+ bits &= ~bit;
+ so = rtems_bsdnet_fdToSocket (fd);
+ if (so == NULL)
+ return (EBADF);
+ if (socket_select (so, flag[msk], tid)) {
+ obits[msk][fd/NFDBITS] |=
+ (1 << (fd % NFDBITS));
+ n++;
+ }
+ }
+ }
+ }
+ *retval = n;
+ return (0);
+}
+
+int
+select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *tv)
+{
+ fd_mask *ibits[3], *obits[3];
+ fd_set ob[3];
+ int error, timo;
+ int retval;
+ rtems_id tid;
+ rtems_interval then, now;
+ rtems_event_set events;
+
+ if (nfds < 0)
+ return (EINVAL);
+ if (tv) {
+ timo = tv->tv_sec * hz + tv->tv_usec / tick;
+ if (timo == 0)
+ timo = 1;
+ rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then);
+ }
+ else {
+ timo = 0;
+ }
+
+#define getbits(name,i) if (name) { \
+ ibits[i] = &name->fds_bits[0]; \
+ obits[i] = &ob[i].fds_bits[0]; \
+ FD_ZERO(&ob[i]); \
+ } \
+ else ibits[i] = NULL
+ getbits (readfds, 0);
+ getbits (writefds, 1);
+ getbits (exceptfds, 2);
+#undef getbits
+
+ rtems_task_ident (RTEMS_SELF, 0, &tid);
+ rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT, &events);
+ for (;;) {
+ rtems_bsdnet_semaphore_obtain ();
+ error = selscan(tid, ibits, obits, nfds, &retval);
+ rtems_bsdnet_semaphore_release ();
+ if (error || retval)
+ break;
+ if (timo) {
+ rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
+ timo -= now - then;
+ if (timo <= 0)
+ break;
+ then = now;
+ }
+ rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, timo, &events);
+ }
+
+#define putbits(name,i) if (name) *name = ob[i]
+ putbits (readfds, 0);
+ putbits (writefds, 1);
+ putbits (exceptfds, 2);
+#undef putbits
+ if (error) {
+ errno = error;
+ retval = -1;
+ }
+ return (retval);
+}
diff --git a/cpukit/libnetworking/rtems/rtems_showicmpstat.c b/cpukit/libnetworking/rtems/rtems_showicmpstat.c
new file mode 100644
index 0000000000..1faea2512b
--- /dev/null
+++ b/cpukit/libnetworking/rtems/rtems_showicmpstat.c
@@ -0,0 +1,60 @@
+/*
+ * $Id$
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <sys/proc.h>
+#include <sys/mbuf.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/icmp_var.h>
+
+/*
+ * Display ICMP statistics
+ * Don't lock the rest of the network tasks out while printing.
+ * It's no big deal if the values change while being printed.
+ */
+static void
+showicmpstat (const char *name, unsigned long n)
+{
+ if (n)
+ printf ("%35s%12lu\n", name, n);
+}
+
+void
+rtems_bsdnet_show_icmp_stats (void)
+{
+ int i;
+ char cbuf[20];
+
+ printf ("************ ICMP Statistics ************\n");
+ showicmpstat ("Calls to icmp_error()", icmpstat.icps_error);
+ showicmpstat ("Errors not sent -- old was icmp", icmpstat.icps_oldicmp);
+ for (i = 0 ; i <= ICMP_MAXTYPE ; i++) {
+ if (icmpstat.icps_outhist[i]) {
+ sprintf (cbuf, "Type %d sent", i);
+ showicmpstat (cbuf, icmpstat.icps_outhist[i]);
+ }
+ }
+ showicmpstat ("icmp_code out of range", icmpstat.icps_badcode);
+ showicmpstat ("packet < ICMP_MINLEN", icmpstat.icps_tooshort);
+ showicmpstat ("bad checksum", icmpstat.icps_checksum);
+ showicmpstat ("calculated bound mismatch", icmpstat.icps_badlen);
+ showicmpstat ("number of responses", icmpstat.icps_reflect);
+ showicmpstat ("b/mcast echo requests dropped", icmpstat.icps_bmcastecho);
+ showicmpstat ("b/mcast tstamp requests dropped", icmpstat.icps_bmcasttstamp);
+ for (i = 0 ; i <= ICMP_MAXTYPE ; i++) {
+ if (icmpstat.icps_inhist[i]) {
+ sprintf (cbuf, "Type %d received", i);
+ showicmpstat (cbuf, icmpstat.icps_inhist[i]);
+ }
+ }
+
+ printf ("\n");
+}
diff --git a/cpukit/libnetworking/rtems/rtems_showifstat.c b/cpukit/libnetworking/rtems/rtems_showifstat.c
new file mode 100644
index 0000000000..0c879f8051
--- /dev/null
+++ b/cpukit/libnetworking/rtems/rtems_showifstat.c
@@ -0,0 +1,152 @@
+/*
+ * $Id$
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <sys/proc.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+/*
+ * Display an address
+ */
+static int
+showaddress (char *name, struct sockaddr *a)
+{
+ struct sockaddr_in *sa;
+ char buf[17];
+
+ if (!a)
+ return 0;
+ printf ("%s:", name);
+ sa = (struct sockaddr_in *)a;
+ printf ("%-16s", inet_ntop (AF_INET, &sa->sin_addr, buf, sizeof(buf)));
+ return 1;
+}
+
+/*
+ * Display interface statistics
+ */
+void
+rtems_bsdnet_show_if_stats (void)
+{
+ struct ifnet *ifp;
+ struct ifaddr *ifa;
+ unsigned short bit, flags;
+
+ printf ("************ INTERFACE STATISTICS ************\n");
+ for (ifp = ifnet; ifp; ifp = ifp->if_next) {
+ printf ("***** %s%d *****\n", ifp->if_name, ifp->if_unit);
+ for (ifa = ifp->if_addrlist ; ifa ; ifa = ifa->ifa_next) {
+
+ if ( !ifa->ifa_addr )
+ continue;
+
+ switch ( ifa->ifa_addr->sa_family ) {
+ case AF_LINK:
+ {
+ struct sockaddr_dl *sdl = (struct sockaddr_dl *)ifa->ifa_addr;
+ unsigned char *cp = LLADDR(sdl);
+ int i;
+
+ switch ( sdl->sdl_type ) {
+ case IFT_ETHER:
+ if ( (i=sdl->sdl_alen) > 0 ) {
+ printf("Ethernet Address: ");
+ do {
+ i--;
+ printf("%02X%c", *cp++, i ? ':' : '\n');
+ } while ( i>0 );
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ break;
+
+ case AF_INET:
+ {
+ int printed;
+ printed = showaddress ("Address", ifa->ifa_addr);
+ if (ifp->if_flags & IFF_BROADCAST)
+ printed |= showaddress ("Broadcast Address", ifa->ifa_broadaddr);
+ if (ifp->if_flags & IFF_POINTOPOINT)
+ printed |= showaddress ("Destination Address", ifa->ifa_dstaddr);
+ printed |= showaddress ("Net mask", ifa->ifa_netmask);
+ if (printed)
+ printf ("\n");
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ printf ("Flags:");
+ for (bit = 1, flags = ifp->if_flags ; flags ; bit <<= 1) {
+ char *cp;
+ char xbuf[20];
+ switch (flags & bit) {
+ case 0: cp = NULL; break;
+ case IFF_UP: cp = "Up"; break;
+ case IFF_BROADCAST: cp = "Broadcast"; break;
+ case IFF_DEBUG: cp = "Debug"; break;
+ case IFF_LOOPBACK: cp = "Loopback"; break;
+ case IFF_POINTOPOINT: cp = "Point-to-point"; break;
+ case IFF_RUNNING: cp = "Running"; break;
+ case IFF_NOARP: cp = "No-ARP"; break;
+ case IFF_PROMISC: cp = "Promiscuous"; break;
+ case IFF_ALLMULTI: cp = "All-multicast"; break;
+ case IFF_OACTIVE: cp = "Active"; break;
+ case IFF_SIMPLEX: cp = "Simplex"; break;
+ case IFF_LINK0: cp = "Link0"; break;
+ case IFF_LINK1: cp = "Link1"; break;
+ case IFF_LINK2: cp = "Link2"; break;
+ case IFF_MULTICAST: cp = "Multicast"; break;
+ default: sprintf (xbuf, "%#x", bit); cp = xbuf; break;
+ }
+ if (cp) {
+ flags &= ~bit;
+ printf (" %s", cp);
+ }
+ }
+ printf ("\n");
+
+ printf ("Send queue limit:%-4d length:%-4d Dropped:%-8d\n",
+ ifp->if_snd.ifq_maxlen,
+ ifp->if_snd.ifq_len,
+ ifp->if_snd.ifq_drops);
+
+ /*
+ * FIXME: Could print if_data statistics here,
+ * but right now the drivers maintain their
+ * own statistics.
+ */
+
+ /*
+ * Grab the network semaphore.
+ * In most cases this is not necessary, but it's
+ * easier to always call the driver ioctl function
+ * while holding the semaphore than to try
+ * and explain why some ioctl commands are invoked
+ * while holding the semaphore and others are
+ * invoked while not holding the semaphore.
+ */
+ rtems_bsdnet_semaphore_obtain ();
+ (*ifp->if_ioctl)(ifp, SIO_RTEMS_SHOW_STATS, NULL);
+ rtems_bsdnet_semaphore_release ();
+ }
+ printf ("\n");
+}
diff --git a/cpukit/libnetworking/rtems/rtems_showipstat.c b/cpukit/libnetworking/rtems/rtems_showipstat.c
new file mode 100644
index 0000000000..2dd499a8c0
--- /dev/null
+++ b/cpukit/libnetworking/rtems/rtems_showipstat.c
@@ -0,0 +1,59 @@
+/*
+ * $Id$
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <sys/proc.h>
+#include <sys/mbuf.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+
+/*
+ * Display IP statistics
+ * Don't lock the rest of the network tasks out while printing.
+ * It's no big deal if the values change while being printed.
+ */
+static void
+showipstat (const char *name, unsigned long n)
+{
+ if (n)
+ printf ("%35s%12lu\n", name, n);
+}
+
+void
+rtems_bsdnet_show_ip_stats (void)
+{
+ printf ("************ IP Statistics ************\n");
+ showipstat ("total packets received", ipstat.ips_total);
+ showipstat ("checksum bad", ipstat.ips_badsum);
+ showipstat ("packet too short", ipstat.ips_tooshort);
+ showipstat ("not enough data", ipstat.ips_toosmall);
+ showipstat ("ip header length < data size", ipstat.ips_badhlen);
+ showipstat ("ip length < ip header length", ipstat.ips_badlen);
+ showipstat ("fragments received", ipstat.ips_fragments);
+ showipstat ("frags dropped (dups, out of space)", ipstat.ips_fragdropped);
+ showipstat ("fragments timed out", ipstat.ips_fragtimeout);
+ showipstat ("packets forwarded", ipstat.ips_forward);
+ showipstat ("packets rcvd for unreachable dest", ipstat.ips_cantforward);
+ showipstat ("packets forwarded on same net", ipstat.ips_redirectsent);
+ showipstat ("unknown or unsupported protocol", ipstat.ips_noproto);
+ showipstat ("datagrams delivered to upper level", ipstat.ips_delivered);
+ showipstat ("total ip packets generated here", ipstat.ips_localout);
+ showipstat ("lost packets due to nobufs, etc.", ipstat.ips_odropped);
+ showipstat ("total packets reassembled ok", ipstat.ips_reassembled);
+ showipstat ("datagrams successfully fragmented", ipstat.ips_fragmented);
+ showipstat ("output fragments created", ipstat.ips_ofragments);
+ showipstat ("don't fragment flag was set, etc.", ipstat.ips_cantfrag);
+ showipstat ("error in option processing", ipstat.ips_badoptions);
+ showipstat ("packets discarded due to no route", ipstat.ips_noroute);
+ showipstat ("ip version != 4", ipstat.ips_badvers);
+ showipstat ("total raw ip packets generated", ipstat.ips_rawout);
+ showipstat ("ip length > max ip packet size", ipstat.ips_toolong);
+ printf ("\n");
+}
diff --git a/cpukit/libnetworking/rtems/rtems_showmbuf.c b/cpukit/libnetworking/rtems/rtems_showmbuf.c
new file mode 100644
index 0000000000..39523bd00a
--- /dev/null
+++ b/cpukit/libnetworking/rtems/rtems_showmbuf.c
@@ -0,0 +1,65 @@
+/*
+ * $Id$
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <sys/proc.h>
+#include <sys/mbuf.h>
+
+/*
+ * Display MBUF statistics
+ * Don't lock the rest of the network tasks out while printing.
+ * It's no big deal if the values change while being printed.
+ */
+void
+rtems_bsdnet_show_mbuf_stats (void)
+{
+ int i;
+ int printed = 0;
+ char *cp;
+
+ printf ("************ MBUF STATISTICS ************\n");
+ printf ("mbufs:%4lu clusters:%4lu free:%4lu\n",
+ mbstat.m_mbufs, mbstat.m_clusters, mbstat.m_clfree);
+ printf ("drops:%4lu waits:%4lu drains:%4lu\n",
+ mbstat.m_drops, mbstat.m_wait, mbstat.m_drain);
+ for (i = 0 ; i < 20 ; i++) {
+ switch (i) {
+ case MT_FREE: cp = "free"; break;
+ case MT_DATA: cp = "data"; break;
+ case MT_HEADER: cp = "header"; break;
+ case MT_SOCKET: cp = "socket"; break;
+ case MT_PCB: cp = "pcb"; break;
+ case MT_RTABLE: cp = "rtable"; break;
+ case MT_HTABLE: cp = "htable"; break;
+ case MT_ATABLE: cp = "atable"; break;
+ case MT_SONAME: cp = "soname"; break;
+ case MT_SOOPTS: cp = "soopts"; break;
+ case MT_FTABLE: cp = "ftable"; break;
+ case MT_RIGHTS: cp = "rights"; break;
+ case MT_IFADDR: cp = "ifaddr"; break;
+ case MT_CONTROL: cp = "control"; break;
+ case MT_OOBDATA: cp = "oobdata"; break;
+ default: cp = NULL; break;
+ }
+ if ((cp != NULL) || (mbstat.m_mtypes[i] != 0)) {
+ char cbuf[16];
+ if (cp == NULL) {
+ sprintf (cbuf, "Type %d", i);
+ cp = cbuf;
+ }
+ printf ("%10s:%-8u", cp, mbstat.m_mtypes[i]);
+ if (++printed == 4) {
+ printf ("\n");
+ printed = 0;
+ }
+ }
+ }
+ if (printed)
+ printf ("\n");
+ printf ("\n");
+}
diff --git a/cpukit/libnetworking/rtems/rtems_showroute.c b/cpukit/libnetworking/rtems/rtems_showroute.c
new file mode 100644
index 0000000000..bfa78bf6d5
--- /dev/null
+++ b/cpukit/libnetworking/rtems/rtems_showroute.c
@@ -0,0 +1,236 @@
+/*
+ * $Id$
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <sys/proc.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/domain.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/route.h>
+
+#include <netinet/in.h>
+
+#include <arpa/inet.h>
+
+/*
+ * We'll use the application versions of realloc and free.
+ */
+#undef free
+#undef malloc
+#include <stdlib.h>
+
+/*
+ * Information per route
+ */
+struct rinfo {
+ struct sockaddr dst;
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in sin;
+ struct sockaddr_dl sdl;
+ } un;
+ unsigned long pksent;
+ unsigned long expire;
+ int flags;
+ char ifname[16];
+ short ifunit;
+ short refcnt;
+};
+
+/*
+ * Information per display
+ */
+struct dinfo {
+ int capacity;
+ int count;
+ struct rinfo *routes;
+};
+
+/*
+ * Copy address
+ */
+static void
+copyAddress (void *to, void *from, int tolen)
+{
+ int ncopy;
+ struct sockaddr dummy;
+
+ if (from == NULL) {
+ /*
+ * Create a fake address of unspecified type
+ */
+ from = &dummy;
+ dummy.sa_len = 4;
+ dummy.sa_family = AF_UNSPEC;
+ }
+ ncopy = ((struct sockaddr *)from)->sa_len;
+ if (ncopy > tolen)
+ ncopy = tolen;
+ memcpy (to, from, ncopy);
+}
+
+/*
+ * Package everything up before printing it.
+ * We don't want to block all network operations till
+ * the printing completes!
+ */
+static int
+show_inet_route (rn, vw)
+ struct radix_node *rn;
+ void *vw;
+{
+ struct rtentry *rt = (struct rtentry *)rn;
+ struct ifnet *ifp;
+ struct dinfo *dp = (struct dinfo *)vw;
+ struct rinfo *r;
+
+ /*
+ * Get a pointer to a new route info structure
+ */
+ if (dp->count >= dp->capacity) {
+ r = realloc (dp->routes, (sizeof *r) * (dp->capacity + 20));
+ if (r == 0)
+ return ENOMEM;
+ dp->capacity += 20;
+ dp->routes = r;
+ }
+ r = dp->routes + dp->count++;
+
+ /*
+ * Fill in the route info structure
+ */
+ copyAddress (&r->dst, rt_key(rt), sizeof r->dst);
+ if (rt->rt_flags & (RTF_GATEWAY | RTF_HOST)) {
+ copyAddress (&r->un, rt->rt_gateway, sizeof r->un);
+ }
+ else {
+ /*
+ * Create a fake address to hold the mask
+ */
+ struct sockaddr_in dummy;
+
+ dummy.sin_family = AF_INET;
+ dummy.sin_len = sizeof dummy;
+ dummy.sin_addr = ((struct sockaddr_in *)rt_mask(rt))->sin_addr;
+ copyAddress (&r->un, &dummy, sizeof r->un);
+ }
+ r->flags = rt->rt_flags;
+ r->refcnt = rt->rt_refcnt;
+ r->pksent = rt->rt_rmx.rmx_pksent;
+ r->expire = rt->rt_rmx.rmx_expire;
+ ifp = rt->rt_ifp;
+ strncpy (r->ifname, ifp->if_name, sizeof r->ifname);
+ r->ifunit = ifp->if_unit;
+ return 0;
+}
+
+/*
+ * Convert link address to ASCII
+ */
+static char *
+link_ascii (struct sockaddr_dl *sdl, char *buf, int bufsize)
+{
+ char *cp;
+ int i;
+ int first = 1;
+ int nleft = sdl->sdl_alen;
+ unsigned char *ap = LLADDR (sdl);
+ static const char hextab[16] = "0123456789ABCDEF";
+
+ cp = buf;
+ while (nleft && (bufsize > 4)) {
+ if (first) {
+ first = 0;
+ }
+ else {
+ *cp++ = ':';
+ bufsize--;
+ }
+ i = *ap++;
+ *cp++ = hextab[(i >> 4) & 0xf];
+ *cp++ = hextab[i & 0xf];
+ nleft--;
+ bufsize -= 2;
+ }
+ *cp = '\0';
+ return buf;
+}
+
+void
+rtems_bsdnet_show_inet_routes (void)
+{
+ struct radix_node_head *rnh;
+ struct dinfo d;
+ struct rinfo *r;
+ int i, error;
+
+ /*
+ * For now we'll handle only AF_INET
+ */
+ rnh = rt_tables[AF_INET];
+ if (!rnh)
+ return;
+ d.count = d.capacity = 0;
+ d.routes = NULL;
+ rtems_bsdnet_semaphore_obtain ();
+ error = rnh->rnh_walktree(rnh, show_inet_route, &d);
+ rtems_bsdnet_semaphore_release ();
+ if (error) {
+ printf ("Can't get route info: %s\n", strerror (error));
+ return;
+ }
+ if (d.count == 0) {
+ printf ("No routes!\n");
+ return;
+ }
+ printf ("Destination Gateway/Mask/Hw Flags Refs Use Expire Interface\n");
+ for (i = 0, r = d.routes ; i < d.count ; i++, r++) {
+ char buf[30];
+ char *cp, *fc, flagbuf[10];
+ const char *addr;
+ unsigned long flagbit;
+ struct sockaddr_in *sin;
+
+ sin = (struct sockaddr_in *)&r->dst;
+ if (sin->sin_addr.s_addr == INADDR_ANY)
+ addr = "default";
+ else
+ addr = inet_ntop (AF_INET, &sin->sin_addr, buf, sizeof buf);
+ printf ("%-16s", addr);
+ switch (r->un.sa.sa_family) {
+ case AF_INET:
+ addr = inet_ntop (AF_INET, &r->un.sin.sin_addr, buf, sizeof buf);
+ break;
+
+ case AF_LINK:
+ addr = link_ascii (&r->un.sdl, buf, sizeof buf);
+ break;
+
+ default:
+ addr = "";
+ break;
+ }
+ printf ("%-19s", addr);
+ fc = "UGHRDM XLS";
+ for (flagbit = 0x1, cp = flagbuf ; *fc ; flagbit <<= 1, fc++) {
+ if ((r->flags & flagbit) && (*fc != ' '))
+ *cp++ = *fc;
+ }
+ *cp = '\0';
+ printf ("%-10s%3d%9ld%7ld %.*s%d\n", flagbuf,
+ r->refcnt, r->pksent,
+ r->expire,
+ (int)sizeof r->ifname, r->ifname,
+ r->ifunit);
+ }
+ free (d.routes);
+}
diff --git a/cpukit/libnetworking/rtems/rtems_showtcpstat.c b/cpukit/libnetworking/rtems/rtems_showtcpstat.c
new file mode 100644
index 0000000000..b9a0366819
--- /dev/null
+++ b/cpukit/libnetworking/rtems/rtems_showtcpstat.c
@@ -0,0 +1,102 @@
+/*
+ * $Id$
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <sys/proc.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_seq.h>
+#include <netinet/tcp_var.h>
+
+/*
+ * Display TCP statistics
+ * Don't lock the rest of the network tasks out while printing.
+ * It's no big deal if the values change while being printed.
+ */
+static void
+showtcpstat (const char *name, unsigned long n)
+{
+ if (n)
+ printf ("%35s%12lu\n", name, n);
+}
+
+void
+rtems_bsdnet_show_tcp_stats (void)
+{
+ printf ("************ TCP Statistics ************\n");
+ showtcpstat ("connections initiated", tcpstat.tcps_connattempt);
+ showtcpstat ("connections accepted", tcpstat.tcps_accepts);
+ showtcpstat ("connections established", tcpstat.tcps_connects);
+ showtcpstat ("connections dropped", tcpstat.tcps_drops);
+ showtcpstat ("embryonic connections dropped", tcpstat.tcps_conndrops);
+ showtcpstat ("conn. closed (includes drops)", tcpstat.tcps_closed);
+ showtcpstat ("segs where we tried to get rtt", tcpstat.tcps_segstimed);
+ showtcpstat ("times we succeeded", tcpstat.tcps_rttupdated);
+ showtcpstat ("delayed acks sent", tcpstat.tcps_delack);
+ showtcpstat ("conn. dropped in rxmt timeout", tcpstat.tcps_timeoutdrop);
+ showtcpstat ("retransmit timeouts", tcpstat.tcps_rexmttimeo);
+ showtcpstat ("persist timeouts", tcpstat.tcps_persisttimeo);
+ showtcpstat ("keepalive timeouts", tcpstat.tcps_keeptimeo);
+ showtcpstat ("keepalive probes sent", tcpstat.tcps_keepprobe);
+ showtcpstat ("connections dropped in keepalive", tcpstat.tcps_keepdrops);
+
+ showtcpstat ("total packets sent", tcpstat.tcps_sndtotal);
+ showtcpstat ("data packets sent", tcpstat.tcps_sndpack);
+ showtcpstat ("data bytes sent", tcpstat.tcps_sndbyte);
+ showtcpstat ("data packets retransmitted", tcpstat.tcps_sndrexmitpack);
+ showtcpstat ("data bytes retransmitted", tcpstat.tcps_sndrexmitbyte);
+ showtcpstat ("ack-only packets sent", tcpstat.tcps_sndacks);
+ showtcpstat ("window probes sent", tcpstat.tcps_sndprobe);
+ showtcpstat ("packets sent with URG only", tcpstat.tcps_sndurg);
+ showtcpstat ("window update-only packets sent", tcpstat.tcps_sndwinup);
+ showtcpstat ("control (SYN|FIN|RST) packets sent", tcpstat.tcps_sndctrl);
+
+ showtcpstat ("total packets received", tcpstat.tcps_rcvtotal);
+ showtcpstat ("packets received in sequence", tcpstat.tcps_rcvpack);
+ showtcpstat ("bytes received in sequence", tcpstat.tcps_rcvbyte);
+ showtcpstat ("packets received with ccksum errs", tcpstat.tcps_rcvbadsum);
+ showtcpstat ("packets received with bad offset", tcpstat.tcps_rcvbadoff);
+ showtcpstat ("packets received too short", tcpstat.tcps_rcvshort);
+ showtcpstat ("duplicate-only packets received", tcpstat.tcps_rcvduppack);
+ showtcpstat ("duplicate-only bytes received", tcpstat.tcps_rcvdupbyte);
+ showtcpstat ("packets with some duplicate data", tcpstat.tcps_rcvpartduppack);
+ showtcpstat ("dup. bytes in part-dup. packets", tcpstat.tcps_rcvpartdupbyte);
+ showtcpstat ("out-of-order packets received", tcpstat.tcps_rcvoopack);
+ showtcpstat ("out-of-order bytes received", tcpstat.tcps_rcvoobyte);
+ showtcpstat ("packets with data after window", tcpstat.tcps_rcvpackafterwin);
+ showtcpstat ("bytes rcvd after window", tcpstat.tcps_rcvbyteafterwin);
+ showtcpstat ("packets rcvd after \"close\"", tcpstat.tcps_rcvafterclose);
+ showtcpstat ("rcvd window probe packets", tcpstat.tcps_rcvwinprobe);
+ showtcpstat ("rcvd duplicate acks", tcpstat.tcps_rcvdupack);
+ showtcpstat ("rcvd acks for unsent data", tcpstat.tcps_rcvacktoomuch);
+ showtcpstat ("rcvd ack packets", tcpstat.tcps_rcvackpack);
+ showtcpstat ("bytes acked by rcvd acks", tcpstat.tcps_rcvackbyte);
+ showtcpstat ("rcvd window update packets", tcpstat.tcps_rcvwinupd);
+ showtcpstat ("segments dropped due to PAWS", tcpstat.tcps_pawsdrop);
+ showtcpstat ("times hdr predict ok for acks", tcpstat.tcps_predack);
+ showtcpstat ("times hdr predict ok for data pkts", tcpstat.tcps_preddat);
+ showtcpstat ("pcb cache misses", tcpstat.tcps_pcbcachemiss);
+ showtcpstat ("times cached RTT in route updated", tcpstat.tcps_cachedrtt);
+ showtcpstat ("times cached rttvar updated", tcpstat.tcps_cachedrttvar);
+ showtcpstat ("times cached ssthresh updated", tcpstat.tcps_cachedssthresh);
+ showtcpstat ("times RTT initialized from route", tcpstat.tcps_usedrtt);
+ showtcpstat ("times RTTVAR initialized from rt", tcpstat.tcps_usedrttvar);
+ showtcpstat ("times ssthresh initialized from rt", tcpstat.tcps_usedssthresh);
+ showtcpstat ("timeout in persist state", tcpstat.tcps_persistdrop);
+ showtcpstat ("bogus SYN, e.g. premature ACK", tcpstat.tcps_badsyn);
+ showtcpstat ("resends due to MTU discovery", tcpstat.tcps_mturesent);
+ showtcpstat ("listen queue overflows", tcpstat.tcps_listendrop);
+ printf ("\n");
+}
diff --git a/cpukit/libnetworking/rtems/rtems_showudpstat.c b/cpukit/libnetworking/rtems/rtems_showudpstat.c
new file mode 100644
index 0000000000..1fc2d15a0b
--- /dev/null
+++ b/cpukit/libnetworking/rtems/rtems_showudpstat.c
@@ -0,0 +1,48 @@
+/*
+ * $Id$
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <sys/proc.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+
+/*
+ * Display UDP statistics
+ * Don't lock the rest of the network tasks out while printing.
+ * It's no big deal if the values change while being printed.
+ */
+static void
+showudpstat (const char *name, unsigned long n)
+{
+ if (n)
+ printf ("%35s%12lu\n", name, n);
+}
+
+void
+rtems_bsdnet_show_udp_stats (void)
+{
+ printf ("************ UDP Statistics ************\n");
+ showudpstat ("total input packets", udpstat.udps_ipackets);
+ showudpstat ("packet shorter than header", udpstat.udps_hdrops);
+ showudpstat ("checksum error", udpstat.udps_badsum);
+ showudpstat ("data length larger than packet", udpstat.udps_badlen);
+ showudpstat ("no socket on port", udpstat.udps_noport);
+ showudpstat ("of above, arrived as broadcast", udpstat.udps_noportbcast);
+ showudpstat ("not delivered, input socket full", udpstat.udps_fullsock);
+ showudpstat ("input packets missing pcb cache", udpstat.udpps_pcbcachemiss);
+ showudpstat ("input packets not for hashed pcb", udpstat.udpps_pcbhashmiss);
+ showudpstat ("total output packets", udpstat.udps_opackets);
+ printf ("\n");
+}
diff --git a/cpukit/libnetworking/rtems/rtems_syscall.c b/cpukit/libnetworking/rtems/rtems_syscall.c
new file mode 100644
index 0000000000..0285dc36d0
--- /dev/null
+++ b/cpukit/libnetworking/rtems/rtems_syscall.c
@@ -0,0 +1,787 @@
+/*
+ * $Id$
+ */
+
+#include <string.h>
+#include <stdarg.h>
+/* #include <stdlib.h> */
+#include <stdio.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <rtems/error.h>
+#include <rtems/rtems_bsdnet.h>
+
+#include <sys/errno.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/protosw.h>
+#include <sys/proc.h>
+#include <sys/fcntl.h>
+#include <sys/filio.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/route.h>
+
+/*
+ * Hooks to RTEMS I/O system
+ */
+static const rtems_filesystem_file_handlers_r socket_handlers;
+int rtems_bsdnet_makeFdForSocket(void *so, const rtems_filesystem_file_handlers_r *h);
+struct socket *rtems_bsdnet_fdToSocket(int fd);
+
+/*
+ * Package system call argument into mbuf.
+ */
+static int
+sockargstombuf (struct mbuf **mp, const void *buf, int buflen, int type)
+{
+ struct mbuf *m;
+
+ if ((u_int)buflen > MLEN)
+ return (EINVAL);
+ m = m_get(M_WAIT, type);
+ if (m == NULL)
+ return (ENOBUFS);
+ m->m_len = buflen;
+ memcpy (mtod(m, caddr_t), buf, buflen);
+ *mp = m;
+ if (type == MT_SONAME) {
+ struct sockaddr *sa;
+ sa = mtod(m, struct sockaddr *);
+ sa->sa_len = buflen;
+ }
+ return 0;
+}
+
+/*
+ *********************************************************************
+ * BSD-style entry points *
+ *********************************************************************
+ */
+int
+socket (int domain, int type, int protocol)
+{
+ int fd;
+ int error;
+ struct socket *so;
+
+ rtems_bsdnet_semaphore_obtain ();
+ error = socreate(domain, &so, type, protocol, NULL);
+ if (error == 0) {
+ fd = rtems_bsdnet_makeFdForSocket (so, &socket_handlers);
+ if (fd < 0)
+ soclose (so);
+ }
+ else {
+ errno = error;
+ fd = -1;
+ }
+ rtems_bsdnet_semaphore_release ();
+ return fd;
+}
+
+int
+bind (int s, struct sockaddr *name, int namelen)
+{
+ int error;
+ int ret = -1;
+ struct socket *so;
+ struct mbuf *nam;
+
+ rtems_bsdnet_semaphore_obtain ();
+ if ((so = rtems_bsdnet_fdToSocket (s)) != NULL) {
+ error = sockargstombuf (&nam, name, namelen, MT_SONAME);
+ if (error == 0) {
+ error = sobind (so, nam);
+ if (error == 0)
+ ret = 0;
+ else
+ errno = error;
+ m_freem (nam);
+ }
+ else {
+ errno = error;
+ }
+ }
+ rtems_bsdnet_semaphore_release ();
+ return ret;
+}
+
+int
+connect (int s, struct sockaddr *name, int namelen)
+{
+ int error;
+ int ret = -1;
+ struct socket *so;
+ struct mbuf *nam;
+
+ rtems_bsdnet_semaphore_obtain ();
+ if ((so = rtems_bsdnet_fdToSocket (s)) == NULL) {
+ rtems_bsdnet_semaphore_release ();
+ return -1;
+ }
+ if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
+ errno = EALREADY;
+ rtems_bsdnet_semaphore_release ();
+ return -1;
+ }
+ error = sockargstombuf (&nam, name, namelen, MT_SONAME);
+ if (error) {
+ errno = error;
+ rtems_bsdnet_semaphore_release ();
+ return -1;
+ }
+ error = soconnect (so, nam);
+ if (error)
+ goto bad;
+ if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
+ m_freem(nam);
+ errno = EINPROGRESS;
+ rtems_bsdnet_semaphore_release ();
+ return -1;
+ }
+ while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
+ error = soconnsleep (so);
+ if (error)
+ break;
+ }
+ if (error == 0) {
+ error = so->so_error;
+ so->so_error = 0;
+ }
+ bad:
+ so->so_state &= ~SS_ISCONNECTING;
+ m_freem (nam);
+ if (error)
+ errno = error;
+ else
+ ret = 0;
+ rtems_bsdnet_semaphore_release ();
+ return ret;
+}
+
+int
+listen (int s, int backlog)
+{
+ int error;
+ int ret = -1;
+ struct socket *so;
+
+ rtems_bsdnet_semaphore_obtain ();
+ if ((so = rtems_bsdnet_fdToSocket (s)) != NULL) {
+ error = solisten (so, backlog);
+ if (error == 0)
+ ret = 0;
+ else
+ errno = error;
+ }
+ rtems_bsdnet_semaphore_release ();
+ return ret;
+}
+
+int
+accept (int s, struct sockaddr *name, int *namelen)
+{
+ int fd;
+ struct socket *head, *so;
+ struct mbuf *nam;
+
+ rtems_bsdnet_semaphore_obtain ();
+ if ((head = rtems_bsdnet_fdToSocket (s)) == NULL) {
+ rtems_bsdnet_semaphore_release ();
+ return -1;
+ }
+ if ((head->so_options & SO_ACCEPTCONN) == 0) {
+ errno = EINVAL;
+ rtems_bsdnet_semaphore_release ();
+ return -1;
+ }
+ if ((head->so_state & SS_NBIO) && head->so_comp.tqh_first == NULL) {
+ errno = EWOULDBLOCK;
+ rtems_bsdnet_semaphore_release ();
+ return -1;
+ }
+ while (head->so_comp.tqh_first == NULL && head->so_error == 0) {
+ if (head->so_state & SS_CANTRCVMORE) {
+ head->so_error = ECONNABORTED;
+ break;
+ }
+ head->so_error = soconnsleep (head);
+ }
+ if (head->so_error) {
+ errno = head->so_error;
+ head->so_error = 0;
+ rtems_bsdnet_semaphore_release ();
+ return -1;
+ }
+
+ so = head->so_comp.tqh_first;
+ TAILQ_REMOVE(&head->so_comp, so, so_list);
+ head->so_qlen--;
+
+ fd = rtems_bsdnet_makeFdForSocket (so, &socket_handlers);
+ if (fd < 0) {
+ TAILQ_INSERT_HEAD(&head->so_comp, so, so_list);
+ head->so_qlen++;
+ soconnwakeup (head);
+ rtems_bsdnet_semaphore_release ();
+ return -1;
+ }
+ so->so_state &= ~SS_COMP;
+ so->so_head = NULL;
+
+ nam = m_get(M_WAIT, MT_SONAME);
+ (void) soaccept(so, nam);
+ if (name) {
+ /* check length before it is destroyed */
+ if (*namelen > nam->m_len)
+ *namelen = nam->m_len;
+ memcpy (name, mtod(nam, caddr_t), *namelen);
+ }
+ m_freem(nam);
+ rtems_bsdnet_semaphore_release ();
+ return (fd);
+
+}
+
+/*
+ * Shutdown routine
+ */
+
+int
+shutdown (int s, int how)
+{
+ struct socket *so;
+ int error;
+
+ rtems_bsdnet_semaphore_obtain ();
+ if ((so = rtems_bsdnet_fdToSocket (s)) == NULL) {
+ rtems_bsdnet_semaphore_release ();
+ return -1;
+ }
+ error = soshutdown(so, how);
+ rtems_bsdnet_semaphore_release ();
+ if (error) {
+ errno = error;
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * All `transmit' operations end up calling this routine.
+ */
+ssize_t
+sendmsg (int s, const struct msghdr *mp, int flags)
+{
+ int ret = -1;
+ int error;
+ struct uio auio;
+ struct iovec *iov;
+ struct socket *so;
+ struct mbuf *to, *control;
+ int i;
+ int len;
+
+ rtems_bsdnet_semaphore_obtain ();
+ if ((so = rtems_bsdnet_fdToSocket (s)) == NULL) {
+ rtems_bsdnet_semaphore_release ();
+ return -1;
+ }
+ auio.uio_iov = mp->msg_iov;
+ auio.uio_iovcnt = mp->msg_iovlen;
+ auio.uio_segflg = UIO_USERSPACE;
+ auio.uio_rw = UIO_WRITE;
+ auio.uio_offset = 0;
+ auio.uio_resid = 0;
+ iov = mp->msg_iov;
+ for (i = 0; i < mp->msg_iovlen; i++, iov++) {
+ if ((auio.uio_resid += iov->iov_len) < 0) {
+ errno = EINVAL;
+ rtems_bsdnet_semaphore_release ();
+ return -1;
+ }
+ }
+ if (mp->msg_name) {
+ error = sockargstombuf (&to, mp->msg_name, mp->msg_namelen, MT_SONAME);
+ if (error) {
+ errno = error;
+ rtems_bsdnet_semaphore_release ();
+ return -1;
+ }
+ }
+ else {
+ to = NULL;
+ }
+ if (mp->msg_control) {
+ if (mp->msg_controllen < sizeof (struct cmsghdr)) {
+ errno = EINVAL;
+ if (to)
+ m_freem(to);
+ rtems_bsdnet_semaphore_release ();
+ return -1;
+ }
+ sockargstombuf (&control, mp->msg_control, mp->msg_controllen, MT_CONTROL);
+ }
+ else {
+ control = NULL;
+ }
+ len = auio.uio_resid;
+ error = sosend (so, to, &auio, (struct mbuf *)0, control, flags);
+ if (error) {
+ if (auio.uio_resid != len && (error == EINTR || error == EWOULDBLOCK))
+ error = 0;
+ }
+ if (error)
+ errno = error;
+ else
+ ret = len - auio.uio_resid;
+ if (to)
+ m_freem(to);
+ rtems_bsdnet_semaphore_release ();
+ return (ret);
+}
+
+/*
+ * Send a message to a host
+ */
+ssize_t
+sendto (int s, const void *buf, size_t buflen, int flags, const struct sockaddr *to, int tolen)
+{
+ struct msghdr msg;
+ struct iovec iov;
+
+ iov.iov_base = (void *)buf;
+ iov.iov_len = buflen;
+ msg.msg_name = (caddr_t)to;
+ msg.msg_namelen = tolen;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = NULL;
+ msg.msg_controllen = 0;
+ return sendmsg (s, &msg, flags);
+}
+
+/*
+ * Send a message to a connected host
+ */
+ssize_t
+send (int s, const void *buf, size_t buflen, int flags)
+{
+ return sendto (s, buf, buflen, flags, NULL, 0);
+}
+
+/*
+ * All `receive' operations end up calling this routine.
+ */
+ssize_t
+recvmsg (int s, struct msghdr *mp, int flags)
+{
+ int ret = -1;
+ int error;
+ struct uio auio;
+ struct iovec *iov;
+ struct socket *so;
+ struct mbuf *from = NULL, *control = NULL;
+ int i;
+ int len;
+
+ rtems_bsdnet_semaphore_obtain ();
+ if ((so = rtems_bsdnet_fdToSocket (s)) == NULL) {
+ rtems_bsdnet_semaphore_release ();
+ return -1;
+ }
+ auio.uio_iov = mp->msg_iov;
+ auio.uio_iovcnt = mp->msg_iovlen;
+ auio.uio_segflg = UIO_USERSPACE;
+ auio.uio_rw = UIO_READ;
+ auio.uio_offset = 0;
+ auio.uio_resid = 0;
+ iov = mp->msg_iov;
+ for (i = 0; i < mp->msg_iovlen; i++, iov++) {
+ if ((auio.uio_resid += iov->iov_len) < 0) {
+ errno = EINVAL;
+ rtems_bsdnet_semaphore_release ();
+ return -1;
+ }
+ }
+ len = auio.uio_resid;
+ mp->msg_flags = flags;
+ error = soreceive (so, &from, &auio, (struct mbuf **)NULL,
+ mp->msg_control ? &control : (struct mbuf **)NULL,
+ &mp->msg_flags);
+ if (error) {
+ if (auio.uio_resid != len && (error == EINTR || error == EWOULDBLOCK))
+ error = 0;
+ }
+ if (error) {
+ errno = error;
+ }
+ else {
+ ret = len - auio.uio_resid;
+ if (mp->msg_name) {
+ len = mp->msg_namelen;
+ if ((len <= 0) || (from == NULL)) {
+ len = 0;
+ }
+ else {
+ if (len > from->m_len)
+ len = from->m_len;
+ memcpy (mp->msg_name, mtod(from, caddr_t), len);
+ }
+ mp->msg_namelen = len;
+ }
+ if (mp->msg_control) {
+ struct mbuf *m;
+ void *ctlbuf;
+
+ len = mp->msg_controllen;
+ m = control;
+ mp->msg_controllen = 0;
+ ctlbuf = mp->msg_control;
+
+ while (m && (len > 0)) {
+ unsigned int tocopy;
+
+ if (len >= m->m_len)
+ tocopy = m->m_len;
+ else {
+ mp->msg_flags |= MSG_CTRUNC;
+ tocopy = len;
+ }
+ memcpy(ctlbuf, mtod(m, caddr_t), tocopy);
+ ctlbuf += tocopy;
+ len -= tocopy;
+ m = m->m_next;
+ }
+ mp->msg_controllen = ctlbuf - mp->msg_control;
+ }
+ }
+ if (from)
+ m_freem (from);
+ if (control)
+ m_freem (control);
+ rtems_bsdnet_semaphore_release ();
+ return (ret);
+}
+
+/*
+ * Receive a message from a host
+ */
+ssize_t
+recvfrom (int s, void *buf, size_t buflen, int flags, const struct sockaddr *from, int *fromlen)
+{
+ struct msghdr msg;
+ struct iovec iov;
+ int ret;
+
+ iov.iov_base = buf;
+ iov.iov_len = buflen;
+ msg.msg_name = (caddr_t)from;
+ if (fromlen)
+ msg.msg_namelen = *fromlen;
+ else
+ msg.msg_namelen = 0;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = NULL;
+ msg.msg_controllen = 0;
+ ret = recvmsg (s, &msg, flags);
+ if ((from != NULL) && (fromlen != NULL) && (ret >= 0))
+ *fromlen = msg.msg_namelen;
+ return ret;
+}
+
+/*
+ * Receive a message from a connected host
+ */
+ssize_t
+recv (int s, void *buf, size_t buflen, int flags)
+{
+ return recvfrom (s, buf, buflen, flags, NULL, NULL);
+}
+
+int
+setsockopt (int s, int level, int name, const void *val, int len)
+{
+ struct socket *so;
+ struct mbuf *m = NULL;
+ int error;
+
+ rtems_bsdnet_semaphore_obtain ();
+ if ((so = rtems_bsdnet_fdToSocket (s)) == NULL) {
+ rtems_bsdnet_semaphore_release ();
+ return -1;
+ }
+ if (len > MLEN) {
+ errno = EINVAL;
+ rtems_bsdnet_semaphore_release ();
+ return -1;
+ }
+ if (val) {
+ error = sockargstombuf (&m, val, len, MT_SOOPTS);
+ if (error) {
+ errno = error;
+ rtems_bsdnet_semaphore_release ();
+ return -1;
+ }
+ }
+ error = sosetopt(so, level, name, m);
+ if (error) {
+ errno = error;
+ rtems_bsdnet_semaphore_release ();
+ return -1;
+ }
+ rtems_bsdnet_semaphore_release ();
+ return 0;
+}
+
+int
+getsockopt (int s, int level, int name, void *aval, int *avalsize)
+{
+ struct socket *so;
+ struct mbuf *m = NULL, *m0;
+ char *val = aval;
+ int i, op, valsize;
+ int error;
+
+ rtems_bsdnet_semaphore_obtain ();
+ if ((so = rtems_bsdnet_fdToSocket (s)) == NULL) {
+ rtems_bsdnet_semaphore_release ();
+ return -1;
+ }
+ if (val)
+ valsize = *avalsize;
+ else
+ valsize = 0;
+ if (((error = sogetopt(so, level, name, &m)) == 0) && val && valsize && m) {
+ op = 0;
+ while (m && op < valsize) {
+ i = valsize - op;
+ if (i > m->m_len)
+ i = m->m_len;
+ memcpy (val, mtod(m, caddr_t), i);
+ op += i;
+ val += i;
+ m0 = m;
+ MFREE (m0, m);
+ }
+ *avalsize = op;
+ }
+ if (m != NULL)
+ (void) m_free(m);
+ if (error) {
+ errno = error;
+ rtems_bsdnet_semaphore_release ();
+ return -1;
+ }
+ rtems_bsdnet_semaphore_release ();
+ return 0;
+}
+
+static int
+getpeersockname (int s, struct sockaddr *name, int *namelen, int pflag)
+{
+ struct socket *so;
+ struct mbuf *m;
+ int len = *namelen;
+ int error;
+
+ rtems_bsdnet_semaphore_obtain ();
+ if ((so = rtems_bsdnet_fdToSocket (s)) == NULL) {
+ rtems_bsdnet_semaphore_release ();
+ return -1;
+ }
+ m = m_getclr(M_WAIT, MT_SONAME);
+ if (m == NULL) {
+ errno = ENOBUFS;
+ rtems_bsdnet_semaphore_release ();
+ return -1;
+ }
+ if (pflag)
+ error = (*so->so_proto->pr_usrreqs->pru_peeraddr)(so, m);
+ else
+ error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, m);
+ if (error) {
+ m_freem(m);
+ errno = error;
+ rtems_bsdnet_semaphore_release ();
+ return -1;
+ }
+ if (len > m->m_len) {
+ len = m->m_len;
+ *namelen = len;
+ }
+ memcpy (name, mtod(m, caddr_t), len);
+ m_freem (m);
+ rtems_bsdnet_semaphore_release ();
+ return 0;
+}
+
+int
+getpeername (int s, struct sockaddr *name, int *namelen)
+{
+ return getpeersockname (s, name, namelen, 1);
+}
+int
+getsockname (int s, struct sockaddr *name, int *namelen)
+{
+ return getpeersockname (s, name, namelen, 0);
+}
+
+int
+sysctl(int *name, u_int namelen, void *oldp,
+ size_t *oldlenp, void *newp, size_t newlen)
+{
+ int error;
+ size_t j;
+
+ rtems_bsdnet_semaphore_obtain ();
+ error = userland_sysctl (0, name, namelen, oldp, oldlenp, 1, newp, newlen, &j);
+ rtems_bsdnet_semaphore_release ();
+
+ if (oldlenp)
+ *oldlenp = j;
+
+ if (error)
+ {
+ errno = error;
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ ************************************************************************
+ * RTEMS I/O HANDLER ROUTINES *
+ ************************************************************************
+ */
+static int
+rtems_bsdnet_close (rtems_libio_t *iop)
+{
+ struct socket *so;
+ int error;
+
+ rtems_bsdnet_semaphore_obtain ();
+ if ((so = iop->data1) == NULL) {
+ errno = EBADF;
+ rtems_bsdnet_semaphore_release ();
+ return -1;
+ }
+ error = soclose (so);
+ rtems_bsdnet_semaphore_release ();
+ if (error) {
+ errno = error;
+ return -1;
+ }
+ return 0;
+}
+
+static ssize_t
+rtems_bsdnet_read (rtems_libio_t *iop, void *buffer, uint32_t count)
+{
+ return recv (iop->data0, buffer, count, 0);
+}
+
+static ssize_t
+rtems_bsdnet_write (rtems_libio_t *iop, const void *buffer, uint32_t count)
+{
+ return send (iop->data0, buffer, count, 0);
+}
+
+static int
+so_ioctl (rtems_libio_t *iop, struct socket *so, uint32_t command, void *buffer)
+{
+ switch (command) {
+ case FIONBIO:
+ if (*(int *)buffer) {
+ iop->flags |= O_NONBLOCK;
+ so->so_state |= SS_NBIO;
+ }
+ else {
+ iop->flags &= ~O_NONBLOCK;
+ so->so_state &= ~SS_NBIO;
+ }
+ return 0;
+
+ case FIONREAD:
+ *(int *)buffer = so->so_rcv.sb_cc;
+ return 0;
+ }
+
+ if (IOCGROUP(command) == 'i')
+ return ifioctl (so, command, buffer, NULL);
+ if (IOCGROUP(command) == 'r')
+ return rtioctl (command, buffer, NULL);
+ return (*so->so_proto->pr_usrreqs->pru_control)(so, command, buffer, 0);
+}
+
+static int
+rtems_bsdnet_ioctl (rtems_libio_t *iop, uint32_t command, void *buffer)
+{
+ struct socket *so;
+ int error;
+
+ rtems_bsdnet_semaphore_obtain ();
+ if ((so = iop->data1) == NULL) {
+ errno = EBADF;
+ rtems_bsdnet_semaphore_release ();
+ return -1;
+ }
+ error = so_ioctl (iop, so, command, buffer);
+ rtems_bsdnet_semaphore_release ();
+ if (error) {
+ errno = error;
+ return -1;
+ }
+ return 0;
+}
+
+static int
+rtems_bsdnet_fcntl (int cmd, rtems_libio_t *iop)
+{
+ struct socket *so;
+
+ if (cmd == F_SETFL) {
+ rtems_bsdnet_semaphore_obtain ();
+ if ((so = iop->data1) == NULL) {
+ rtems_bsdnet_semaphore_release ();
+ return EBADF;
+ }
+ if (iop->flags & LIBIO_FLAGS_NO_DELAY)
+ so->so_state |= SS_NBIO;
+ else
+ so->so_state &= ~SS_NBIO;
+ rtems_bsdnet_semaphore_release ();
+ }
+ return 0;
+}
+
+static int
+rtems_bsdnet_fstat (rtems_filesystem_location_info_t *loc, struct stat *sp)
+{
+ sp->st_mode = S_IFSOCK;
+ return 0;
+}
+
+static const rtems_filesystem_file_handlers_r socket_handlers = {
+ NULL, /* open */
+ rtems_bsdnet_close, /* close */
+ rtems_bsdnet_read, /* read */
+ rtems_bsdnet_write, /* write */
+ rtems_bsdnet_ioctl, /* ioctl */
+ NULL, /* lseek */
+ rtems_bsdnet_fstat, /* fstat */
+ NULL, /* fchmod */
+ NULL, /* ftruncate */
+ NULL, /* fpathconf */
+ NULL, /* fsync */
+ NULL, /* fdatasync */
+ rtems_bsdnet_fcntl, /* fcntl */
+};
diff --git a/cpukit/libnetworking/rtems/sghostname.c b/cpukit/libnetworking/rtems/sghostname.c
new file mode 100644
index 0000000000..307f045fbd
--- /dev/null
+++ b/cpukit/libnetworking/rtems/sghostname.c
@@ -0,0 +1,49 @@
+/*
+ * RTEMS versions of hostname functions
+ * FIXME: Not thread-safe
+ *
+ * $Id$
+ */
+
+#include <string.h>
+#include <errno.h>
+#include <rtems/rtems_bsdnet.h>
+#include <sys/param.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+
+static char *rtems_hostname;
+
+int
+gethostname (char *name, size_t namelen)
+{
+ char *cp = rtems_hostname;
+
+ if (cp == NULL)
+ cp = "";
+ strncpy (name, cp, namelen);
+ return 0;
+}
+
+int
+sethostname (char *name, size_t namelen)
+{
+ char *old, *new;
+
+ if (namelen >= MAXHOSTNAMELEN) {
+ errno = EINVAL;
+ return -1;
+ }
+ new = malloc (namelen + 1, M_HTABLE, M_NOWAIT);
+ if (new == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ strncpy (new, name, namelen);
+ new[namelen] = '\0';
+ old = rtems_hostname;
+ rtems_hostname = new;
+ if (old)
+ free (old, M_HTABLE);
+ return 0;
+}
diff --git a/cpukit/libnetworking/rtems/tftp.h b/cpukit/libnetworking/rtems/tftp.h
new file mode 100644
index 0000000000..538efa8531
--- /dev/null
+++ b/cpukit/libnetworking/rtems/tftp.h
@@ -0,0 +1,43 @@
+/*
+ * $Id$
+ */
+
+/*
+ * Trivial File Transfer Protocol (TFTP)
+ *
+ * Transfer file to/from remote host
+ *
+ * W. Eric Norum
+ * Saskatchewan Accelerator Laboratory
+ * University of Saskatchewan
+ * Saskatoon, Saskatchewan, CANADA
+ * eric@skatter.usask.ca
+ */
+
+/*
+ * Usage:
+ *
+ * To open `/bootfiles/image' on `hostname' for reading:
+ * fd = open ("/TFTP/hostname/bootfiles/image", O_RDONLY);
+ *
+ * The `hostname' must be four dot-separated decimal values.
+ */
+
+#ifndef _TFTP_FILESYSTEM_h
+#define _TFTP_FILESYSTEM_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Filesystem initialization routine
+ */
+
+int rtems_bsdnet_initialize_tftp_filesystem( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/libnetworking/sys/buf.h b/cpukit/libnetworking/sys/buf.h
new file mode 100644
index 0000000000..109a7d2b39
--- /dev/null
+++ b/cpukit/libnetworking/sys/buf.h
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 1982, 1986, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)buf.h 8.9 (Berkeley) 3/30/95
+ * $Id$
+ */
+
+#ifndef _SYS_BUF_H_
+#define _SYS_BUF_H_
+
+#include <sys/queue.h>
+
+#define NOLIST ((struct buf *)0x87654321)
+
+struct buf;
+
+struct iodone_chain {
+ long ic_prev_flags;
+ void (*ic_prev_iodone) __P((struct buf *));
+ void *ic_prev_iodone_chain;
+ struct {
+ long ia_long;
+ void *ia_ptr;
+ } ic_args[5];
+};
+
+typedef TAILQ_HEAD(buf_queue_head, buf) buf_queue_head, *buf_queue_head_t;
+
+/*
+ * The buffer header describes an I/O operation in the kernel.
+ */
+struct buf {
+ LIST_ENTRY(buf) b_hash; /* Hash chain. */
+ LIST_ENTRY(buf) b_vnbufs; /* Buffer's associated vnode. */
+ TAILQ_ENTRY(buf) b_freelist; /* Free list position if not active. */
+ TAILQ_ENTRY(buf) b_act; /* Device driver queue when active. *new* */
+ struct proc *b_proc; /* Associated proc; NULL if kernel. */
+ long b_flags; /* B_* flags. */
+ unsigned short b_qindex; /* buffer queue index */
+ unsigned char b_usecount; /* buffer use count */
+ int b_error; /* Errno value. */
+ long b_bufsize; /* Allocated buffer size. */
+ long b_bcount; /* Valid bytes in buffer. */
+ long b_resid; /* Remaining I/O. */
+ dev_t b_dev; /* Device associated with buffer. */
+ struct {
+ caddr_t b_addr; /* Memory, superblocks, indirect etc. */
+ } b_un;
+ caddr_t b_kvabase; /* base kva for buffer */
+ int b_kvasize; /* size of kva for buffer */
+ void *b_saveaddr; /* Original b_addr for physio. */
+ daddr_t b_lblkno; /* Logical block number. */
+ daddr_t b_blkno; /* Underlying physical block number. */
+ /* Function to call upon completion. */
+ void (*b_iodone) __P((struct buf *));
+ /* For nested b_iodone's. */
+ struct iodone_chain *b_iodone_chain;
+ struct vnode *b_vp; /* Device vnode. */
+ int b_dirtyoff; /* Offset in buffer of dirty region. */
+ int b_dirtyend; /* Offset of end of dirty region. */
+ struct ucred *b_rcred; /* Read credentials reference. */
+ struct ucred *b_wcred; /* Write credentials reference. */
+ int b_validoff; /* Offset in buffer of valid region. */
+ int b_validend; /* Offset of end of valid region. */
+ daddr_t b_pblkno; /* physical block number */
+ caddr_t b_savekva; /* saved kva for transfer while bouncing */
+ void *b_driver1; /* for private use by the driver */
+ void *b_driver2; /* for private use by the driver */
+ void *b_spc;
+ union cluster_info {
+ TAILQ_HEAD(cluster_list_head, buf) cluster_head;
+ TAILQ_ENTRY(buf) cluster_entry;
+ } b_cluster;
+ struct vm_page *b_pages[btoc(MAXPHYS)];
+ int b_npages;
+};
+
+/* Device driver compatibility definitions. */
+#define b_data b_un.b_addr /* b_un.b_addr is not changeable. */
+
+/*
+ * These flags are kept in b_flags.
+ */
+#define B_AGE 0x00000001 /* Move to age queue when I/O done. */
+#define B_NEEDCOMMIT 0x00000002 /* Append-write in progress. */
+#define B_ASYNC 0x00000004 /* Start I/O, do not wait. */
+#define B_BAD 0x00000008 /* Bad block revectoring in progress. */
+#define B_BUSY 0x00000010 /* I/O in progress. */
+#define B_CACHE 0x00000020 /* Bread found us in the cache. */
+#define B_CALL 0x00000040 /* Call b_iodone from biodone. */
+#define B_DELWRI 0x00000080 /* Delay I/O until buffer reused. */
+#define B_DIRTY 0x00000100 /* Dirty page to be pushed out async. */
+#define B_DONE 0x00000200 /* I/O completed. */
+#define B_EINTR 0x00000400 /* I/O was interrupted */
+#define B_ERROR 0x00000800 /* I/O error occurred. */
+#define B_GATHERED 0x00001000 /* LFS: already in a segment. */
+#define B_INVAL 0x00002000 /* Does not contain valid info. */
+#define B_LOCKED 0x00004000 /* Locked in core (not reusable). */
+#define B_NOCACHE 0x00008000 /* Do not cache block after use. */
+#define B_MALLOC 0x00010000 /* malloced b_data */
+#define B_CLUSTEROK 0x00020000 /* Pagein op, so swap() can count it. */
+#define B_PHYS 0x00040000 /* I/O to user memory. */
+#define B_RAW 0x00080000 /* Set by physio for raw transfers. */
+#define B_READ 0x00100000 /* Read buffer. */
+#define B_TAPE 0x00200000 /* Magnetic tape I/O. */
+#define B_RELBUF 0x00400000 /* Release VMIO buffer. */
+#define B_WANTED 0x00800000 /* Process wants this buffer. */
+#define B_WRITE 0x00000000 /* Write buffer (pseudo flag). */
+#define B_WRITEINPROG 0x01000000 /* Write in progress. */
+#define B_XXX 0x02000000 /* Debugging flag. */
+#define B_PAGING 0x04000000 /* volatile paging I/O -- bypass VMIO */
+#define B_ORDERED 0x08000000 /* Must guarantee I/O ordering */
+#define B_VMIO 0x20000000 /* VMIO flag */
+#define B_CLUSTER 0x40000000 /* pagein op, so swap() can count it */
+#define B_BOUNCE 0x80000000 /* bounce buffer flag */
+
+/*
+ * number of buffer hash entries
+ */
+#define BUFHSZ 512
+
+/*
+ * buffer hash table calculation, originally by David Greenman
+ */
+#define BUFHASH(vnp, bn) \
+ (&bufhashtbl[(((unsigned long)(vnp) >> 7)+(int)(bn)) % BUFHSZ])
+
+/*
+ * Definitions for the buffer free lists.
+ */
+#define BUFFER_QUEUES 6 /* number of free buffer queues */
+
+extern LIST_HEAD(bufhashhdr, buf) bufhashtbl[BUFHSZ], invalhash;
+extern TAILQ_HEAD(bqueues, buf) bufqueues[BUFFER_QUEUES];
+
+#define QUEUE_NONE 0 /* on no queue */
+#define QUEUE_LOCKED 1 /* locked buffers */
+#define QUEUE_LRU 2 /* useful buffers */
+#define QUEUE_VMIO 3 /* VMIO buffers */
+#define QUEUE_AGE 4 /* not-useful buffers */
+#define QUEUE_EMPTY 5 /* empty buffer headers*/
+
+/*
+ * Zero out the buffer's data area.
+ */
+#define clrbuf(bp) { \
+ bzero((bp)->b_data, (u_int)(bp)->b_bcount); \
+ (bp)->b_resid = 0; \
+}
+
+/* Flags to low-level allocation routines. */
+#define B_CLRBUF 0x01 /* Request allocated buffer be cleared. */
+#define B_SYNC 0x02 /* Do all allocations synchronously. */
+
+#ifdef _KERNEL
+extern int nbuf; /* The number of buffer headers */
+extern struct buf *buf; /* The buffer headers. */
+extern char *buffers; /* The buffer contents. */
+extern int bufpages; /* Number of memory pages in the buffer pool. */
+extern struct buf *swbuf; /* Swap I/O buffer headers. */
+extern int nswbuf; /* Number of swap I/O buffer headers. */
+extern TAILQ_HEAD(swqueue, buf) bswlist;
+
+void bufinit __P((void));
+void bremfree __P((struct buf *));
+int bread __P((struct vnode *, daddr_t, int,
+ struct ucred *, struct buf **));
+int breadn __P((struct vnode *, daddr_t, int, daddr_t *, int *, int,
+ struct ucred *, struct buf **));
+int bwrite __P((struct buf *));
+void bdwrite __P((struct buf *));
+void bawrite __P((struct buf *));
+int bowrite __P((struct buf *));
+void brelse __P((struct buf *));
+void bqrelse __P((struct buf *));
+int vfs_bio_awrite __P((struct buf *));
+struct buf * getpbuf __P((void));
+struct buf *incore __P((struct vnode *, daddr_t));
+struct buf *gbincore __P((struct vnode *, daddr_t));
+int inmem __P((struct vnode *, daddr_t));
+struct buf *getblk __P((struct vnode *, daddr_t, int, int, int));
+struct buf *geteblk __P((int));
+int allocbuf __P((struct buf *, int));
+int biowait __P((struct buf *));
+void biodone __P((struct buf *));
+
+void cluster_callback __P((struct buf *));
+int cluster_read __P((struct vnode *, u_quad_t, daddr_t, long,
+ struct ucred *, struct buf **));
+int cluster_wbuild __P((struct vnode *, long, daddr_t, int));
+void cluster_write __P((struct buf *, u_quad_t));
+int physio __P((void (*)(struct buf *), struct buf *, dev_t,
+ int, u_int (*)(struct buf *), struct uio *));
+u_int minphys __P((struct buf *));
+void vfs_bio_clrbuf __P((struct buf *));
+void vfs_busy_pages __P((struct buf *, int clear_modify));
+void vfs_unbusy_pages(struct buf *);
+void vwakeup __P((struct buf *));
+void vmapbuf __P((struct buf *));
+void vunmapbuf __P((struct buf *));
+void relpbuf __P((struct buf *));
+void brelvp __P((struct buf *));
+void bgetvp __P((struct vnode *, struct buf *));
+void pbgetvp __P((struct vnode *, struct buf *));
+void pbrelvp __P((struct buf *));
+void reassignbuf __P((struct buf *, struct vnode *));
+struct buf *trypbuf __P((void));
+void vm_bounce_alloc __P((struct buf *));
+void vm_bounce_free __P((struct buf *));
+vm_offset_t vm_bounce_kva_alloc __P((int));
+void vm_bounce_kva_alloc_free __P((vm_offset_t, int));
+#endif /* _KERNEL */
+
+#endif /* !_SYS_BUF_H_ */
diff --git a/cpukit/libnetworking/sys/callout.h b/cpukit/libnetworking/sys/callout.h
new file mode 100644
index 0000000000..1e682b09c9
--- /dev/null
+++ b/cpukit/libnetworking/sys/callout.h
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)callout.h 8.2 (Berkeley) 1/21/94
+ * $Id$
+ */
+
+#ifndef _SYS_CALLOUT_H_
+#define _SYS_CALLOUT_H_
+
+struct callout {
+ struct callout *c_next; /* next callout in queue */
+ void *c_arg; /* function argument */
+ void (*c_func) __P((void *)); /* function to call */
+ int c_time; /* ticks to the event */
+};
+
+#ifdef _KERNEL
+extern struct callout *callfree, *callout, calltodo;
+extern int ncallout;
+#endif
+
+#endif
diff --git a/cpukit/libnetworking/sys/conf.h b/cpukit/libnetworking/sys/conf.h
new file mode 100644
index 0000000000..207acfe33d
--- /dev/null
+++ b/cpukit/libnetworking/sys/conf.h
@@ -0,0 +1,228 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)conf.h 8.5 (Berkeley) 1/9/95
+ * $Id$
+ */
+
+#ifndef _SYS_CONF_H_
+#define _SYS_CONF_H_
+
+/*
+ * Definitions of device driver entry switches
+ */
+
+struct buf;
+struct proc;
+struct tty;
+struct uio;
+struct vnode;
+
+typedef int d_open_t __P((dev_t dev, int oflags, int devtype, struct proc *p));
+typedef int d_close_t __P((dev_t dev, int fflag, int devtype, struct proc *p));
+typedef void d_strategy_t __P((struct buf *bp));
+typedef int d_ioctl_t __P((dev_t dev, int cmd, caddr_t data,
+ int fflag, struct proc *p));
+typedef int d_dump_t __P((dev_t dev));
+typedef int d_psize_t __P((dev_t dev));
+
+typedef int d_read_t __P((dev_t dev, struct uio *uio, int ioflag));
+typedef int d_write_t __P((dev_t dev, struct uio *uio, int ioflag));
+typedef void d_stop_t __P((struct tty *tp, int rw));
+typedef int d_reset_t __P((dev_t dev));
+typedef struct tty *d_devtotty_t __P((dev_t dev));
+typedef int d_select_t __P((dev_t dev, int which, struct proc *p));
+typedef int d_mmap_t __P((dev_t dev, int offset, int nprot));
+
+typedef int l_open_t __P((dev_t dev, struct tty *tp));
+typedef int l_close_t __P((struct tty *tp, int flag));
+typedef int l_read_t __P((struct tty *tp, struct uio *uio, int flag));
+typedef int l_write_t __P((struct tty *tp, struct uio *uio, int flag));
+typedef int l_ioctl_t __P((struct tty *tp, int cmd, caddr_t data,
+ int flag, struct proc *p));
+typedef int l_rint_t __P((int c, struct tty *tp));
+typedef int l_start_t __P((struct tty *tp));
+typedef int l_modem_t __P((struct tty *tp, int flag));
+
+/*
+ * Block device switch table
+ */
+struct bdevsw {
+ d_open_t *d_open;
+ d_close_t *d_close;
+ d_strategy_t *d_strategy;
+ d_ioctl_t *d_ioctl;
+ d_dump_t *d_dump;
+ d_psize_t *d_psize;
+ int d_flags;
+ char *d_name; /* name of the driver e.g. audio */
+ struct cdevsw *d_cdev; /* cross pointer to the cdev */
+ int d_maj; /* the major number we were assigned */
+};
+
+#ifdef _KERNEL
+extern struct bdevsw *bdevsw[];
+#endif
+
+/*
+ * Character device switch table
+ */
+struct cdevsw {
+ d_open_t *d_open;
+ d_close_t *d_close;
+ d_read_t *d_read;
+ d_write_t *d_write;
+ d_ioctl_t *d_ioctl;
+ d_stop_t *d_stop;
+ d_reset_t *d_reset; /* XXX not used */
+ d_devtotty_t *d_devtotty;
+ d_select_t *d_select;
+ d_mmap_t *d_mmap;
+ d_strategy_t *d_strategy;
+ char *d_name; /* see above */
+ struct bdevsw *d_bdev;
+ int d_maj;
+};
+
+#ifdef _KERNEL
+extern struct cdevsw *cdevsw[];
+#endif
+
+/*
+ * Line discipline switch table
+ */
+struct linesw {
+ l_open_t *l_open;
+ l_close_t *l_close;
+ l_read_t *l_read;
+ l_write_t *l_write;
+ l_ioctl_t *l_ioctl;
+ l_rint_t *l_rint;
+ l_start_t *l_start;
+ l_modem_t *l_modem;
+};
+
+#ifdef _KERNEL
+extern struct linesw linesw[];
+extern int nlinesw;
+
+int ldisc_register __P((int , struct linesw *));
+void ldisc_deregister __P((int));
+#define LDISC_LOAD -1 /* Loadable line discipline */
+#endif
+
+/*
+ * Swap device table
+ */
+struct swdevt {
+ dev_t sw_dev;
+ int sw_flags;
+ int sw_nblks;
+ struct vnode *sw_vp;
+};
+#define SW_FREED 0x01
+#define SW_SEQUENTIAL 0x02
+#define sw_freed sw_flags /* XXX compat */
+
+#ifdef _KERNEL
+d_open_t noopen;
+d_close_t noclose;
+d_read_t noread;
+d_write_t nowrite;
+d_ioctl_t noioctl;
+d_stop_t nostop;
+d_reset_t noreset;
+d_devtotty_t nodevtotty;
+d_select_t noselect;
+d_mmap_t nommap;
+
+/* Bogus defines for compatibility. */
+#define noioc noioctl
+#define nostrat nostrategy
+#define zerosize nopsize
+/*
+ * XXX d_strategy seems to be unused for cdevs that aren't associated with
+ * bdevs and called without checking for it being non-NULL for bdevs.
+ */
+#define nostrategy ((d_strategy_t *)NULL)
+
+d_dump_t nodump;
+
+/*
+ * nopsize is little used, so not worth having dummy functions for.
+ */
+#define nopsize ((d_psize_t *)NULL)
+
+d_open_t nullopen;
+d_close_t nullclose;
+#define nullstop nostop /* one void return is as good as another */
+#define nullreset noreset /* one unused function is as good as another */
+
+d_open_t nxopen;
+d_close_t nxclose;
+d_read_t nxread;
+d_write_t nxwrite;
+d_ioctl_t nxioctl;
+#define nxstop nostop /* one void return is as good as another */
+#define nxreset noreset /* one unused function is as good as another */
+#define nxdevtotty nodevtotty /* one NULL return is as good as another */
+d_select_t nxselect;
+#define nxmmap nommap /* one -1 return is as good as another */
+#define nxstrategy nostrategy /* one NULL value is as good as another */
+d_dump_t nxdump;
+#define nxpsize nopsize /* one NULL value is as good as another */
+
+d_read_t rawread;
+d_write_t rawwrite;
+
+l_read_t l_noread;
+l_write_t l_nowrite;
+
+int bdevsw_add __P((dev_t *descrip,struct bdevsw *new,struct bdevsw **old));
+int cdevsw_add __P((dev_t *descrip,struct cdevsw *new,struct cdevsw **old));
+void cdevsw_make __P((struct bdevsw *from));
+void bdevsw_add_generic __P((int bdev, int cdev, struct bdevsw *bdevsw));
+dev_t chrtoblk __P((dev_t dev));
+int isdisk __P((dev_t dev, int type));
+int iskmemdev __P((dev_t dev));
+int iszerodev __P((dev_t dev));
+void setconf __P((void));
+#endif /* _KERNEL */
+
+#include <machine/conf.h>
+
+#endif /* !_SYS_CONF_H_ */
diff --git a/cpukit/libnetworking/sys/domain.h b/cpukit/libnetworking/sys/domain.h
new file mode 100644
index 0000000000..54622018b2
--- /dev/null
+++ b/cpukit/libnetworking/sys/domain.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)domain.h 8.1 (Berkeley) 6/2/93
+ * $Id$
+ */
+
+#ifndef _SYS_DOMAIN_H_
+#define _SYS_DOMAIN_H_
+
+/*
+ * Structure per communications domain.
+ */
+
+/*
+ * Forward structure declarations for function prototypes [sic].
+ */
+struct mbuf;
+
+struct domain {
+ int dom_family; /* AF_xxx */
+ char *dom_name;
+ void (*dom_init) /* initialize domain data structures */
+ __P((void));
+ int (*dom_externalize) /* externalize access rights */
+ __P((struct mbuf *));
+ void (*dom_dispose) /* dispose of internalized rights */
+ __P((struct mbuf *));
+ struct protosw *dom_protosw, *dom_protoswNPROTOSW;
+ struct domain *dom_next;
+ int (*dom_rtattach) /* initialize routing table */
+ __P((void **, int));
+ int dom_rtoffset; /* an arg to rtattach, in bits */
+ int dom_maxrtkey; /* for routing layer */
+};
+
+#ifdef _KERNEL
+extern struct domain *domains;
+extern struct domain localdomain;
+
+#define DOMAIN_SET(name) \
+ DATA_SET(domain_set, name ## domain);
+
+#endif
+
+#endif
diff --git a/cpukit/libnetworking/sys/kernel.h b/cpukit/libnetworking/sys/kernel.h
new file mode 100644
index 0000000000..25e483809a
--- /dev/null
+++ b/cpukit/libnetworking/sys/kernel.h
@@ -0,0 +1,264 @@
+/*-
+ * Copyright (c) 1995 Terrence R. Lambert
+ * All rights reserved.
+ *
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)kernel.h 8.3 (Berkeley) 1/21/94
+ * $Id$
+ */
+
+#ifndef _SYS_KERNEL_H_
+#define _SYS_KERNEL_H_
+
+/* Global variables for the kernel. */
+
+/* 1.1 */
+extern long hostid;
+extern char hostname[MAXHOSTNAMELEN];
+extern int hostnamelen;
+extern char domainname[MAXHOSTNAMELEN];
+extern int domainnamelen;
+extern char kernelname[MAXPATHLEN];
+
+/* 1.2 */
+extern volatile struct timeval mono_time;
+extern struct timeval boottime;
+extern struct timeval runtime;
+/* extern volatile struct timeval time; */
+extern struct timezone tz; /* XXX */
+
+extern int tick; /* usec per tick (1000000 / hz) */
+extern int hz; /* system clock's frequency */
+extern int psratio; /* ratio: prof / stat */
+extern int stathz; /* statistics clock's frequency */
+extern int profhz; /* profiling clock's frequency */
+extern int ticks;
+extern int lbolt; /* once a second sleep address */
+extern int tickdelta;
+extern long timedelta;
+
+#if FREEBSD_RELENG_2_2_2_BASE
+/*
+ * The following macros are used to declare global sets of objects, which
+ * are collected by the linker into a `struct linker_set' as defined below.
+ *
+ * NB: the constants defined below must match those defined in
+ * ld/ld.h. Since their calculation requires arithmetic, we
+ * can't name them symbolically (e.g., 23 is N_SETT | N_EXT).
+ */
+#define MAKE_SET(set, sym, type)
+#define TEXT_SET(set, sym) MAKE_SET(set, sym, 23)
+#define DATA_SET(set, sym) MAKE_SET(set, sym, 25)
+#define BSS_SET(set, sym) MAKE_SET(set, sym, 27)
+#define ABS_SET(set, sym) MAKE_SET(set, sym, 21)
+
+#else
+
+/*
+ * RTEMS specific port using the updated sys/linker_set.h
+ * from the lastest FreeBSD (2002-Nov-15). This is a better
+ * way.
+ *
+ * Chris Johns (ccj@acm.org> 18 Nov 2002.
+ */
+#include <sys/linker_set.h>
+
+#endif
+
+/*
+ * Enumerated types for known system startup interfaces.
+ *
+ * Startup occurs in ascending numeric order; the list entries are
+ * sorted prior to attempting startup to guarantee order. Items
+ * of the same level are arbitrated for order based on the 'order'
+ * element.
+ *
+ * These numbers are arbitrary and are chosen ONLY for ordering; the
+ * enumeration values are explicit rather than implicit to provide
+ * for binary compatibility with inserted elements.
+ *
+ * The SI_SUB_RUN_SCHEDULER value must have the highest lexical value.
+ *
+ * The SI_SUB_CONSOLE and SI_SUB_SWAP values represent values used by
+ * the BSD 4.4Lite but not by FreeBSD; they are maintained in dependent
+ * order to support porting.
+ *
+ * The SI_SUB_PROTO_BEGIN and SI_SUB_PROTO_END bracket a range of
+ * initializations to take place at splimp(). This is a historical
+ * wart that should be removed -- probably running everything at
+ * splimp() until the first init that doesn't want it is the correct
+ * fix. They are currently present to ensure historical behavior.
+ */
+enum sysinit_sub_id {
+ SI_SUB_DUMMY = 0x00000000, /* not executed; for linker*/
+ SI_SUB_CONSOLE = 0x08000000, /* console*/
+ SI_SUB_COPYRIGHT = 0x08000001, /* first use of console*/
+ SI_SUB_VM = 0x10000000, /* virtual memory system init*/
+ SI_SUB_KMEM = 0x18000000, /* kernel memory*/
+ SI_SUB_CPU = 0x20000000, /* CPU resource(s)*/
+ SI_SUB_DEVFS = 0x22000000, /* get DEVFS ready */
+ SI_SUB_DRIVERS = 0x23000000, /* Let Drivers initialize */
+ SI_SUB_CONFIGURE = 0x24000000, /* Configure devices */
+ SI_SUB_INTRINSIC = 0x28000000, /* proc 0*/
+ SI_SUB_RUN_QUEUE = 0x30000000, /* the run queue*/
+ SI_SUB_VM_CONF = 0x38000000, /* config VM, set limits*/
+ SI_SUB_VFS = 0x40000000, /* virtual file system*/
+ SI_SUB_CLOCKS = 0x48000000, /* real time and stat clocks*/
+ SI_SUB_MBUF = 0x50000000, /* mbufs*/
+ SI_SUB_CLIST = 0x58000000, /* clists*/
+ SI_SUB_SYSV_SHM = 0x64000000, /* System V shared memory*/
+ SI_SUB_SYSV_SEM = 0x68000000, /* System V semaphores*/
+ SI_SUB_SYSV_MSG = 0x6C000000, /* System V message queues*/
+ SI_SUB_PSEUDO = 0x70000000, /* pseudo devices*/
+ SI_SUB_PROTO_BEGIN = 0x80000000, /* XXX: set splimp (kludge)*/
+ SI_SUB_PROTO_IF = 0x84000000, /* interfaces*/
+ SI_SUB_PROTO_DOMAIN = 0x88000000, /* domains (address families?)*/
+ SI_SUB_PROTO_END = 0x8fffffff, /* XXX: set splx (kludge)*/
+ SI_SUB_KPROF = 0x90000000, /* kernel profiling*/
+ SI_SUB_KICK_SCHEDULER = 0xa0000000, /* start the timeout events*/
+ SI_SUB_ROOT = 0xb0000000, /* root mount*/
+ SI_SUB_ROOT_FDTAB = 0xb8000000, /* root vnode in fd table...*/
+ SI_SUB_SWAP = 0xc0000000, /* swap*/
+ SI_SUB_INTRINSIC_POST = 0xd0000000, /* proc 0 cleanup*/
+ SI_SUB_KTHREAD_INIT = 0xe0000000, /* init process*/
+ SI_SUB_KTHREAD_PAGE = 0xe4000000, /* pageout daemon*/
+ SI_SUB_KTHREAD_VM = 0xe8000000, /* vm daemon*/
+ SI_SUB_KTHREAD_UPDATE = 0xec000000, /* update daemon*/
+ SI_SUB_RUN_SCHEDULER = 0xffffffff /* scheduler: no return*/
+};
+
+
+/*
+ * Some enumerated orders; "ANY" sorts last.
+ */
+enum sysinit_elem_order {
+ SI_ORDER_FIRST = 0x00000000, /* first*/
+ SI_ORDER_SECOND = 0x00000001, /* second*/
+ SI_ORDER_THIRD = 0x00000002, /* third*/
+ SI_ORDER_MIDDLE = 0x10000000, /* somewhere in the middle */
+ SI_ORDER_ANY = 0xffffffff /* last*/
+};
+
+
+/*
+ * System initialization call types; currently two are supported... one
+ * to do a simple function call and one to cause a process to be started
+ * by the kernel on the callers behalf.
+ */
+typedef enum sysinit_elem_type {
+ SI_TYPE_DEFAULT = 0x00000000, /* No special processing*/
+ SI_TYPE_KTHREAD = 0x00000001 /* start kernel thread*/
+} si_elem_t;
+
+
+/*
+ * A system initialization call instance
+ *
+ * The subsystem
+ */
+struct sysinit {
+ unsigned int subsystem; /* subsystem identifier*/
+ unsigned int order; /* init order within subsystem*/
+ void (*func) __P((void *)); /* init function*/
+ void *udata; /* multiplexer/argument */
+ si_elem_t type; /* sysinit_elem_type*/
+};
+
+
+/*
+ * Default: no special processing
+ */
+#define SYSINIT(uniquifier, subsystem, order, func, ident)
+
+/*
+ * Call 'fork()' before calling '(*func)(ident)';
+ * for making a kernel 'thread' (or builtin process.)
+ */
+#define SYSINIT_KT(uniquifier, subsystem, order, func, ident)
+
+
+/*
+ * A kernel process descriptor; used to start "internal" daemons
+ *
+ * Note: global_procpp may be NULL for no global save area
+ */
+struct kproc_desc {
+ char *arg0; /* arg 0 (for 'ps' listing)*/
+ void (*func) __P((void)); /* "main" for kernel process*/
+ struct proc **global_procpp; /* ptr to proc ptr save area*/
+};
+
+void kproc_start __P((void *udata));
+
+#ifdef PSEUDO_LKM
+#include <sys/conf.h>
+#include <sys/exec.h>
+#include <sys/sysent.h>
+#include <sys/lkm.h>
+
+#define PSEUDO_SET(init, name) \
+ extern struct linker_set MODVNOPS; \
+ MOD_MISC(name); \
+ static int \
+ name ## _load(struct lkm_table *lkmtp, int cmd) \
+ { init((void *)NULL /* XXX unused (?) */); return 0; } \
+ static int \
+ name ## _unload(struct lkm_table *lkmtp, int cmd) \
+ { return EINVAL; } \
+ int \
+ name ## _mod(struct lkm_table *lkmtp, int cmd, int ver) { \
+ DISPATCH(lkmtp, cmd, ver, name ## _load, name ## _unload, \
+ lkm_nullcmd); }
+#else /* PSEUDO_LKM */
+
+/*
+ * Compatibility. To be deprecated after LKM is updated.
+ */
+#define PSEUDO_SET(sym, name) SYSINIT(ps, SI_SUB_PSEUDO, SI_ORDER_ANY, sym, 0)
+
+#endif /* PSEUDO_LKM */
+
+struct linker_set {
+ int ls_length;
+ const void *ls_items[1]; /* really ls_length of them,
+ * trailing NULL */
+};
+
+extern struct linker_set execsw_set;
+
+#endif /* !_SYS_KERNEL_H_*/
diff --git a/cpukit/libnetworking/sys/libkern.h b/cpukit/libnetworking/sys/libkern.h
new file mode 100644
index 0000000000..c01e35b273
--- /dev/null
+++ b/cpukit/libnetworking/sys/libkern.h
@@ -0,0 +1,89 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)libkern.h 8.1 (Berkeley) 6/10/93
+ * $Id$
+ */
+
+#ifndef _SYS_LIBKERN_H_
+#define _SYS_LIBKERN_H_
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+/* BCD conversions. */
+extern u_char const bcd2bin_data[];
+extern u_char const bin2bcd_data[];
+extern char const hex2ascii_data[];
+
+#define bcd2bin(bcd) (bcd2bin_data[bcd])
+#define bin2bcd(bin) (bin2bcd_data[bin])
+#define hex2ascii(hex) (hex2ascii_data[hex])
+
+static __inline int imax(int a, int b) { return (a > b ? a : b); }
+static __inline int imin(int a, int b) { return (a < b ? a : b); }
+static __inline long lmax(long a, long b) { return (a > b ? a : b); }
+static __inline long lmin(long a, long b) { return (a < b ? a : b); }
+static __inline u_int max(u_int a, u_int b) { return (a > b ? a : b); }
+static __inline u_int min(u_int a, u_int b) { return (a < b ? a : b); }
+static __inline quad_t qmax(quad_t a, quad_t b) { return (a > b ? a : b); }
+static __inline quad_t qmin(quad_t a, quad_t b) { return (a < b ? a : b); }
+static __inline u_long ulmax(u_long a, u_long b) { return (a > b ? a : b); }
+static __inline u_long ulmin(u_long a, u_long b) { return (a < b ? a : b); }
+
+/* Prototypes for non-quad routines. */
+int bcmp __P((const void *, const void *, size_t));
+#ifndef HAVE_INLINE_FFS
+int ffs __P((int));
+#endif
+#ifndef HAVE_INLINE_FLS
+int fls __P((int));
+#endif
+int locc __P((int, char *, u_int));
+void qsort __P((void *base, size_t nmemb, size_t size,
+ int (*compar)(const void *, const void *)));
+u_long random __P((void));
+char *index __P((const char *, int));
+char *rindex __P((const char *, int));
+int scanc __P((u_int, const u_char *, const u_char *, int));
+int skpc __P((int, int, char *));
+void srandom __P((u_long));
+char *strcat __P((char *, const char *));
+int strcmp __P((const char *, const char *));
+char *strdup __P((const char *s));
+char *strcpy __P((char *, const char *));
+size_t strlen __P((const char *));
+int strncmp __P((const char *, const char *, size_t));
+char *strncpy __P((char *, const char *, size_t));
+char *strerror __P((int errnum));
+
+#endif /* !_SYS_LIBKERN_H_ */
diff --git a/cpukit/libnetworking/sys/linker_set.h b/cpukit/libnetworking/sys/linker_set.h
new file mode 100644
index 0000000000..c79fe87f0b
--- /dev/null
+++ b/cpukit/libnetworking/sys/linker_set.h
@@ -0,0 +1,93 @@
+/*-
+ * Copyright (c) 1999 John D. Polstra
+ * Copyright (c) 1999,2001 Peter Wemm <peter@FreeBSD.org>
+ * 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.
+ *
+ * $FreeBSD: src/sys/sys/linker_set.h,v 1.13 2002/09/23 06:11:29 peter Exp $
+ */
+
+#ifndef _SYS_LINKER_SET_H_
+#define _SYS_LINKER_SET_H_
+
+/*
+ * The following macros are used to declare global sets of objects, which
+ * are collected by the linker into a `linker_set' as defined below.
+ * For ELF, this is done by constructing a separate segment for each set.
+ */
+
+/*
+ * Private macros, not to be used outside this header file.
+ */
+#ifdef __GNUC__
+#define __MAKE_SET(set, sym) \
+ static void const * const __set_##set##_sym_##sym \
+ __attribute((section("set_" #set))) __unused = &sym
+#else /* !__GNUC__ */
+#ifndef lint
+#error "This file needs to be compiled by GCC or lint"
+#endif /* lint */
+#define __MAKE_SET(set, sym) extern void const * const (__set_##set##_sym_##sym)
+#endif /* __GNUC__ */
+
+/*
+ * Public macros.
+ */
+#define TEXT_SET(set, sym) __MAKE_SET(set, sym)
+#define DATA_SET(set, sym) __MAKE_SET(set, sym)
+#define BSS_SET(set, sym) __MAKE_SET(set, sym)
+#define ABS_SET(set, sym) __MAKE_SET(set, sym)
+#define SET_ENTRY(set, sym) __MAKE_SET(set, sym)
+
+/*
+ * Initialize before referring to a give linker set
+ */
+#define SET_DECLARE(set, ptype) \
+ extern ptype *__CONCAT(__start_set_,set)[]; \
+ extern ptype *__CONCAT(__stop_set_,set)[]
+
+#define SET_BEGIN(set) \
+ (__CONCAT(__start_set_,set))
+#define SET_LIMIT(set) \
+ (__CONCAT(__stop_set_,set))
+
+/*
+ * Iterate over all the elements of a set.
+ *
+ * Sets always contain addresses of things, and "pvar" points to words
+ * containing those addresses. Thus is must be declared as "type **pvar",
+ * and the address of each set item is obtained inside the loop by "*pvar".
+ */
+#define SET_FOREACH(pvar, set) \
+ for (pvar = SET_BEGIN(set); pvar < SET_LIMIT(set); pvar++)
+
+#define SET_ITEM(set, i) \
+ ((SET_BEGIN(set))[i])
+
+/*
+ * Provide a count of the items in a set.
+ */
+#define SET_COUNT(set) \
+ (SET_LIMIT(set) - SET_BEGIN(set))
+
+#endif /* _SYS_LINKER_SET_H_ */
diff --git a/cpukit/libnetworking/sys/malloc.h b/cpukit/libnetworking/sys/malloc.h
new file mode 100644
index 0000000000..4574213ee8
--- /dev/null
+++ b/cpukit/libnetworking/sys/malloc.h
@@ -0,0 +1,355 @@
+/*
+ * Copyright (c) 1987, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)malloc.h 8.5 (Berkeley) 5/3/95
+ * $Id$
+ */
+
+#ifndef _SYS_MALLOC_H_
+#define _SYS_MALLOC_H_
+
+#include <rtems/rtems_bsdnet_internal.h> /* Ensure we get RTEMS malloc hooks */
+#define KMEMSTATS
+
+/*
+ * flags to malloc
+ */
+#define M_WAITOK 0x0000
+#define M_NOWAIT 0x0001
+#define M_KERNEL 0x0002
+
+/*
+ * Types of memory to be allocated
+ */
+#define M_FREE 0 /* should be on free list */
+#define M_MBUF 1 /* mbuf */
+#define M_DEVBUF 2 /* device driver memory */
+#define M_SOCKET 3 /* socket structure */
+#define M_PCB 4 /* protocol control block */
+#define M_RTABLE 5 /* routing tables */
+#define M_HTABLE 6 /* IMP host tables */
+#define M_FTABLE 7 /* fragment reassembly header */
+#define M_ZOMBIE 8 /* zombie proc status */
+#define M_IFADDR 9 /* interface address */
+#define M_SOOPTS 10 /* socket options */
+#define M_SONAME 11 /* socket name */
+#define M_NAMEI 12 /* namei path name buffer */
+#define M_GPROF 13 /* kernel profiling buffer */
+#define M_IOCTLOPS 14 /* ioctl data buffer */
+#define M_MAPMEM 15 /* mapped memory descriptors */
+#define M_CRED 16 /* credentials */
+#define M_PGRP 17 /* process group header */
+#define M_SESSION 18 /* session header */
+#define M_IOV 19 /* large iov's */
+#define M_MOUNT 20 /* vfs mount struct */
+#define M_FHANDLE 21 /* network file handle */
+#define M_NFSREQ 22 /* NFS request header */
+#define M_NFSMNT 23 /* NFS mount structure */
+#define M_NFSNODE 24 /* NFS vnode private part */
+#define M_VNODE 25 /* Dynamically allocated vnodes */
+#define M_CACHE 26 /* Dynamically allocated cache entries */
+#define M_DQUOT 27 /* UFS quota entries */
+#define M_UFSMNT 28 /* UFS mount structure */
+#define M_SHM 29 /* SVID compatible shared memory segments */
+#define M_VMMAP 30 /* VM map structures */
+#define M_VMMAPENT 31 /* VM map entry structures */
+#define M_VMOBJ 32 /* VM object structure */
+#define M_VMOBJHASH 33 /* VM object hash structure */
+#define M_VMPMAP 34 /* VM pmap */
+#define M_VMPVENT 35 /* VM phys-virt mapping entry */
+#define M_VMPAGER 36 /* XXX: VM pager struct */
+#define M_VMPGDATA 37 /* XXX: VM pager private data */
+#define M_FILE 38 /* Open file structure */
+#define M_FILEDESC 39 /* Open file descriptor table */
+#define M_LOCKF 40 /* Byte-range locking structures */
+#define M_PROC 41 /* Proc structures */
+#define M_SUBPROC 42 /* Proc sub-structures */
+#define M_SEGMENT 43 /* Segment for LFS */
+#define M_LFSNODE 44 /* LFS vnode private part */
+#define M_FFSNODE 45 /* FFS vnode private part */
+#define M_MFSNODE 46 /* MFS vnode private part */
+#define M_NQLEASE 47 /* Nqnfs lease */
+#define M_NQMHOST 48 /* Nqnfs host address table */
+#define M_NETADDR 49 /* Export host address structure */
+#define M_NFSSVC 50 /* Nfs server structure */
+#define M_NFSUID 51 /* Nfs uid mapping structure */
+#define M_NFSD 52 /* Nfs server daemon structure */
+#define M_IPMOPTS 53 /* internet multicast options */
+#define M_IPMADDR 54 /* internet multicast address */
+#define M_IFMADDR 55 /* link-level multicast address */
+#define M_MRTABLE 56 /* multicast routing tables */
+#define M_ISOFSMNT 57 /* ISOFS mount structure */
+#define M_ISOFSNODE 58 /* ISOFS vnode private part */
+#define M_NFSRVDESC 59 /* NFS server socket descriptor */
+#define M_NFSDIROFF 60 /* NFS directory offset data */
+#define M_NFSBIGFH 61 /* NFS version 3 file handle */
+#define M_MSDOSFSMNT 67 /* MSDOSFS mount structure */
+#define M_MSDOSFSNODE 68 /* MSDOSFS vnode private part */
+#define M_MSDOSFSFAT 69 /* MSDOSFS file allocation table */
+#define M_DEVFSMNT 70 /* DEVFS mount structure */
+#define M_DEVFSBACK 71 /* DEVFS Back node */
+#define M_DEVFSFRONT 72 /* DEVFS Front node */
+#define M_DEVFSNODE 73 /* DEVFS node */
+#define M_TEMP 74 /* misc temporary data buffers */
+#define M_TTYS 75 /* tty data structures */
+#define M_GZIP 76 /* Gzip trees */
+#define M_IPFW 77 /* IpFw/IpAcct chain's */
+#define M_DEVL 78 /* isa_device lists in userconfig() */
+#define M_PKTCLASS 79 /* structures used in packet classifier */
+#define M_SYSCTL 80 /* sysctl internal magic */
+#define M_SECA 81 /* security associations, key management */
+#define M_BIOBUF 82 /* BIO buffer */
+#define M_KTRACE 83 /* KTRACE */
+#define M_SELECT 84 /* select() buffer */
+#define M_CFS 85 /* Coda */
+#define M_LAST 86 /* Must be last type + 1 */
+
+#define INITKMEMNAMES { \
+ "free", /* 0 M_FREE */ \
+ "mbuf", /* 1 M_MBUF */ \
+ "devbuf", /* 2 M_DEVBUF */ \
+ "socket", /* 3 M_SOCKET */ \
+ "pcb", /* 4 M_PCB */ \
+ "routetbl", /* 5 M_RTABLE */ \
+ "hosttbl", /* 6 M_HTABLE */ \
+ "fragtbl", /* 7 M_FTABLE */ \
+ "zombie", /* 8 M_ZOMBIE */ \
+ "ifaddr", /* 9 M_IFADDR */ \
+ "soopts", /* 10 M_SOOPTS */ \
+ "soname", /* 11 M_SONAME */ \
+ "namei", /* 12 M_NAMEI */ \
+ "gprof", /* 13 M_GPROF */ \
+ "ioctlops", /* 14 M_IOCTLOPS */ \
+ "mapmem", /* 15 M_MAPMEM */ \
+ "cred", /* 16 M_CRED */ \
+ "pgrp", /* 17 M_PGRP */ \
+ "session", /* 18 M_SESSION */ \
+ "iov", /* 19 M_IOV */ \
+ "mount", /* 20 M_MOUNT */ \
+ "fhandle", /* 21 M_FHANDLE */ \
+ "NFS req", /* 22 M_NFSREQ */ \
+ "NFS mount", /* 23 M_NFSMNT */ \
+ "NFS node", /* 24 M_NFSNODE */ \
+ "vnodes", /* 25 M_VNODE */ \
+ "namecache", /* 26 M_CACHE */ \
+ "UFS quota", /* 27 M_DQUOT */ \
+ "UFS mount", /* 28 M_UFSMNT */ \
+ "shm", /* 29 M_SHM */ \
+ "VM map", /* 30 M_VMMAP */ \
+ "VM mapent", /* 31 M_VMMAPENT */ \
+ "VM object", /* 32 M_VMOBJ */ \
+ "VM objhash", /* 33 M_VMOBJHASH */ \
+ "VM pmap", /* 34 M_VMPMAP */ \
+ "VM pvmap", /* 35 M_VMPVENT */ \
+ "VM pager", /* 36 M_VMPAGER */ \
+ "VM pgdata", /* 37 M_VMPGDATA */ \
+ "file", /* 38 M_FILE */ \
+ "file desc", /* 39 M_FILEDESC */ \
+ "lockf", /* 40 M_LOCKF */ \
+ "proc", /* 41 M_PROC */ \
+ "subproc", /* 42 M_SUBPROC */ \
+ "LFS segment", /* 43 M_SEGMENT */ \
+ "LFS node", /* 44 M_LFSNODE */ \
+ "FFS node", /* 45 M_FFSNODE */ \
+ "MFS node", /* 46 M_MFSNODE */ \
+ "NQNFS Lease", /* 47 M_NQLEASE */ \
+ "NQNFS Host", /* 48 M_NQMHOST */ \
+ "Export Host", /* 49 M_NETADDR */ \
+ "NFS srvsock", /* 50 M_NFSSVC */ \
+ "NFS uid", /* 51 M_NFSUID */ \
+ "NFS daemon", /* 52 M_NFSD */ \
+ "ip_moptions", /* 53 M_IPMOPTS */ \
+ "in_multi", /* 54 M_IPMADDR */ \
+ "ether_multi", /* 55 M_IFMADDR */ \
+ "mrt", /* 56 M_MRTABLE */ \
+ "ISOFS mount", /* 57 M_ISOFSMNT */ \
+ "ISOFS node", /* 58 M_ISOFSNODE */ \
+ "NFSV3 srvdesc",/* 59 M_NFSRVDESC */ \
+ "NFSV3 diroff", /* 60 M_NFSDIROFF */ \
+ "NFSV3 bigfh", /* 61 M_NFSBIGFH */ \
+ NULL, \
+ NULL, NULL, NULL, NULL, \
+ "MSDOSFS mount",/* 67 M_MSDOSFSMNT */ \
+ "MSDOSFS node", /* 68 M_MSDOSFSNODE */ \
+ "MSDOSFS FAT", /* 69 M_MSDOSFSFAR */ \
+ "DEVFS mount", /* 70 M_DEVFSMNT */ \
+ "DEVFS back", /* 71 M_DEVFSBACK */ \
+ "DEVFS front", /* 72 M_DEVFSFRONT */ \
+ "DEVFS node", /* 73 M_DEVFSNODE */ \
+ "temp", /* 74 M_TEMP */ \
+ "ttys", /* 75 M_TTYS */ \
+ "Gzip trees", /* 76 M_GZIP */ \
+ "IpFw/IpAcct", /* 77 M_IPFW */ \
+ "isa_devlist", /* 78 M_DEVL */ \
+ "PktClass", /* 79 M_PKTCLASS */ \
+ "sysctl", /* 80 M_SYSCTL */ \
+ "key mgmt", /* 81 M_SECA */ \
+ "BIO buffer", /* 82 M_BIOBUF */ \
+ "KTRACE", /* 83 M_KTRACE */ \
+ "select", /* 84 M_SELECT */ \
+ "Coda", /* 85 M_CFS */ \
+}
+
+struct kmemstats {
+ long ks_inuse; /* # of packets of this type currently in use */
+ long ks_calls; /* total packets of this type ever allocated */
+ long ks_memuse; /* total memory held in bytes */
+ u_short ks_limblocks; /* number of times blocked for hitting limit */
+ u_short ks_mapblocks; /* number of times blocked for kernel map */
+ long ks_maxused; /* maximum number ever used */
+ long ks_limit; /* most that are allowed to exist */
+ long ks_size; /* sizes of this thing that are allocated */
+ long ks_spare;
+};
+
+/*
+ * Array of descriptors that describe the contents of each page
+ */
+struct kmemusage {
+ short ku_indx; /* bucket index */
+ union {
+ u_short freecnt;/* for small allocations, free pieces in page */
+ u_short pagecnt;/* for large allocations, pages alloced */
+ } ku_un;
+};
+#define ku_freecnt ku_un.freecnt
+#define ku_pagecnt ku_un.pagecnt
+
+/*
+ * Set of buckets for each size of memory block that is retained
+ */
+struct kmembuckets {
+ caddr_t kb_next; /* list of free blocks */
+ caddr_t kb_last; /* last free block */
+ long kb_calls; /* total calls to allocate this size */
+ long kb_total; /* total number of blocks allocated */
+ long kb_totalfree; /* # of free elements in this bucket */
+ long kb_elmpercl; /* # of elements in this sized allocation */
+ long kb_highwat; /* high water mark */
+ long kb_couldfree; /* over high water mark and could free */
+};
+
+#ifdef _KERNEL
+#define MINALLOCSIZE (1 << MINBUCKET)
+#define BUCKETINDX(size) \
+ ((size) <= (MINALLOCSIZE * 128) \
+ ? (size) <= (MINALLOCSIZE * 8) \
+ ? (size) <= (MINALLOCSIZE * 2) \
+ ? (size) <= (MINALLOCSIZE * 1) \
+ ? (MINBUCKET + 0) \
+ : (MINBUCKET + 1) \
+ : (size) <= (MINALLOCSIZE * 4) \
+ ? (MINBUCKET + 2) \
+ : (MINBUCKET + 3) \
+ : (size) <= (MINALLOCSIZE* 32) \
+ ? (size) <= (MINALLOCSIZE * 16) \
+ ? (MINBUCKET + 4) \
+ : (MINBUCKET + 5) \
+ : (size) <= (MINALLOCSIZE * 64) \
+ ? (MINBUCKET + 6) \
+ : (MINBUCKET + 7) \
+ : (size) <= (MINALLOCSIZE * 2048) \
+ ? (size) <= (MINALLOCSIZE * 512) \
+ ? (size) <= (MINALLOCSIZE * 256) \
+ ? (MINBUCKET + 8) \
+ : (MINBUCKET + 9) \
+ : (size) <= (MINALLOCSIZE * 1024) \
+ ? (MINBUCKET + 10) \
+ : (MINBUCKET + 11) \
+ : (size) <= (MINALLOCSIZE * 8192) \
+ ? (size) <= (MINALLOCSIZE * 4096) \
+ ? (MINBUCKET + 12) \
+ : (MINBUCKET + 13) \
+ : (size) <= (MINALLOCSIZE * 16384) \
+ ? (MINBUCKET + 14) \
+ : (MINBUCKET + 15))
+
+/*
+ * Turn virtual addresses into kmem map indices
+ */
+#define kmemxtob(alloc) (kmembase + (alloc) * PAGE_SIZE)
+#define btokmemx(addr) (((caddr_t)(addr) - kmembase) / PAGE_SIZE)
+#define btokup(addr) (&kmemusage[(caddr_t)(addr) - kmembase >> PAGE_SHIFT])
+
+/*
+ * Macro versions for the usual cases of malloc/free
+ */
+#if defined(KMEMSTATS) || defined(DIAGNOSTIC)
+#define MALLOC(space, cast, size, type, flags) \
+ (space) = (cast)malloc((u_long)(size), type, flags)
+#define FREE(addr, type) free((addr), type)
+
+#else /* do not collect statistics */
+#define MALLOC(space, cast, size, type, flags) { \
+ register struct kmembuckets *kbp = &bucket[BUCKETINDX(size)]; \
+ long s = splimp(); \
+ if (kbp->kb_next == NULL) { \
+ (space) = (cast)malloc((u_long)(size), type, flags); \
+ } else { \
+ (space) = (cast)kbp->kb_next; \
+ kbp->kb_next = *(caddr_t *)(space); \
+ } \
+ splx(s); \
+}
+
+#define FREE(addr, type) { \
+ register struct kmembuckets *kbp; \
+ register struct kmemusage *kup = btokup(addr); \
+ long s = splimp(); \
+ if (1 << kup->ku_indx > MAXALLOCSAVE) { \
+ free((addr), type); \
+ } else { \
+ kbp = &bucket[kup->ku_indx]; \
+ if (kbp->kb_next == NULL) \
+ kbp->kb_next = (caddr_t)(addr); \
+ else \
+ *(caddr_t *)(kbp->kb_last) = (caddr_t)(addr); \
+ *(caddr_t *)(addr) = NULL; \
+ kbp->kb_last = (caddr_t)(addr); \
+ } \
+ splx(s); \
+}
+#endif /* do not collect statistics */
+
+extern struct kmemstats kmemstats[];
+extern struct kmemusage *kmemusage;
+extern char *kmembase;
+extern struct kmembuckets bucket[];
+
+void *contigmalloc __P((unsigned long size, int type, int flags,
+ unsigned long low, unsigned long high,
+ unsigned long alignment, unsigned long boundary));
+void free __P((void *addr, int type));
+void *malloc __P((unsigned long size, int type, int flags));
+#endif /* _KERNEL */
+
+#endif /* !_SYS_MALLOC_H_ */
diff --git a/cpukit/libnetworking/sys/mbuf.h b/cpukit/libnetworking/sys/mbuf.h
new file mode 100644
index 0000000000..30c7d06be3
--- /dev/null
+++ b/cpukit/libnetworking/sys/mbuf.h
@@ -0,0 +1,440 @@
+/*
+ * Copyright (c) 1982, 1986, 1988, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)mbuf.h 8.5 (Berkeley) 2/19/95
+ * $Id$
+ */
+
+#ifndef _SYS_MBUF_H_
+#define _SYS_MBUF_H_
+
+#ifndef M_WAITOK
+#include <sys/malloc.h>
+#endif
+
+/*
+ * Mbufs are of a single size, MSIZE (machine/machparam.h), which
+ * includes overhead. An mbuf may add a single "mbuf cluster" of size
+ * MCLBYTES (also in machine/machparam.h), which has no additional overhead
+ * and is used instead of the internal data area; this is done when
+ * at least MINCLSIZE of data must be stored.
+ */
+
+#define MLEN (MSIZE - sizeof(struct m_hdr)) /* normal data len */
+#define MHLEN (MLEN - sizeof(struct pkthdr)) /* data len w/pkthdr */
+
+#define MINCLSIZE (MHLEN + MLEN) /* smallest amount to put in cluster */
+#define M_MAXCOMPRESS (MHLEN / 2) /* max amount to copy for compression */
+
+/*
+ * Macros for type conversion
+ * mtod(m,t) - convert mbuf pointer to data pointer of correct type
+ * dtom(x) - convert data pointer within mbuf to mbuf pointer (XXX)
+ * mtocl(x) - convert pointer within cluster to cluster index #
+ * cltom(x) - convert cluster # to ptr to beginning of cluster
+ */
+#define mtod(m,t) ((t)((m)->m_data))
+#define dtom(x) ((struct mbuf *)((long)(x) & ~(MSIZE-1)))
+#define mtocl(x) (((u_long)(x) - (u_long)mbutl) >> MCLSHIFT)
+#define cltom(x) ((caddr_t)((u_long)mbutl + ((u_long)(x) << MCLSHIFT)))
+
+/* header at beginning of each mbuf: */
+struct m_hdr {
+ struct mbuf *mh_next; /* next buffer in chain */
+ struct mbuf *mh_nextpkt; /* next chain in queue/record */
+ caddr_t mh_data; /* location of data */
+ int mh_len; /* amount of data in this mbuf */
+ short mh_type; /* type of data in this mbuf */
+ short mh_flags; /* flags; see below */
+};
+
+/* record/packet header in first mbuf of chain; valid if M_PKTHDR set */
+struct pkthdr {
+ struct ifnet *rcvif; /* rcv interface */
+ int len; /* total packet length */
+};
+
+/* description of external storage mapped into mbuf, valid if M_EXT set */
+struct m_ext {
+ caddr_t ext_buf; /* start of buffer */
+ void (*ext_free) /* free routine if not the usual */
+ __P((caddr_t, u_int));
+ u_int ext_size; /* size of buffer, for ext_free */
+ void (*ext_ref) /* add a reference to the ext object */
+ __P((caddr_t, u_int));
+};
+
+struct mbuf {
+ struct m_hdr m_hdr;
+ union {
+ struct {
+ struct pkthdr MH_pkthdr; /* M_PKTHDR set */
+ union {
+ struct m_ext MH_ext; /* M_EXT set */
+ char MH_databuf[MHLEN];
+ } MH_dat;
+ } MH;
+ char M_databuf[MLEN]; /* !M_PKTHDR, !M_EXT */
+ } M_dat;
+};
+#define m_next m_hdr.mh_next
+#define m_len m_hdr.mh_len
+#define m_data m_hdr.mh_data
+#define m_type m_hdr.mh_type
+#define m_flags m_hdr.mh_flags
+#define m_nextpkt m_hdr.mh_nextpkt
+#define m_act m_nextpkt
+#define m_pkthdr M_dat.MH.MH_pkthdr
+#define m_ext M_dat.MH.MH_dat.MH_ext
+#define m_pktdat M_dat.MH.MH_dat.MH_databuf
+#define m_dat M_dat.M_databuf
+
+/* mbuf flags */
+#define M_EXT 0x0001 /* has associated external storage */
+#define M_PKTHDR 0x0002 /* start of record */
+#define M_EOR 0x0004 /* end of record */
+#define M_PROTO1 0x0008 /* protocol-specific */
+
+/* mbuf pkthdr flags, also in m_flags */
+#define M_BCAST 0x0100 /* send/received as link-level broadcast */
+#define M_MCAST 0x0200 /* send/received as link-level multicast */
+
+/* flags copied when copying m_pkthdr */
+#define M_COPYFLAGS (M_PKTHDR|M_EOR|M_PROTO1|M_BCAST|M_MCAST)
+
+/* mbuf types */
+#define MT_FREE 0 /* should be on free list */
+#define MT_DATA 1 /* dynamic (data) allocation */
+#define MT_HEADER 2 /* packet header */
+#define MT_SOCKET 3 /* socket structure */
+#define MT_PCB 4 /* protocol control block */
+#define MT_RTABLE 5 /* routing tables */
+#define MT_HTABLE 6 /* IMP host tables */
+#define MT_ATABLE 7 /* address resolution tables */
+#define MT_SONAME 8 /* socket name */
+#define MT_SOOPTS 10 /* socket options */
+#define MT_FTABLE 11 /* fragment reassembly header */
+#define MT_RIGHTS 12 /* access rights */
+#define MT_IFADDR 13 /* interface address */
+#define MT_CONTROL 14 /* extra-data protocol message */
+#define MT_OOBDATA 15 /* expedited data */
+
+/* flags to m_get/MGET */
+#define M_DONTWAIT M_NOWAIT
+#define M_WAIT M_WAITOK
+
+/* Freelists:
+ *
+ * Normal mbuf clusters are normally treated as character arrays
+ * after allocation, but use the first word of the buffer as a free list
+ * pointer while on the free list.
+ */
+union mcluster {
+ union mcluster *mcl_next;
+ char mcl_buf[MCLBYTES];
+};
+
+/*
+ * mbuf utility macros:
+ *
+ * MBUFLOCK(code)
+ * prevents a section of code from from being interrupted by network
+ * drivers.
+ */
+#define MBUFLOCK(code) \
+ { int ms = splimp(); \
+ { code } \
+ splx(ms); \
+ }
+
+/*
+ * mbuf allocation/deallocation macros:
+ *
+ * MGET(struct mbuf *m, int how, int type)
+ * allocates an mbuf and initializes it to contain internal data.
+ *
+ * MGETHDR(struct mbuf *m, int how, int type)
+ * allocates an mbuf and initializes it to contain a packet header
+ * and internal data.
+ */
+#define MGET(m, how, type) { \
+ int _ms = splimp(); \
+ if (mmbfree == 0) \
+ (void)m_mballoc(1, (how)); \
+ if (((m) = mmbfree) != 0) { \
+ mmbfree = (m)->m_next; \
+ mbstat.m_mtypes[MT_FREE]--; \
+ (m)->m_type = (type); \
+ mbstat.m_mtypes[type]++; \
+ (m)->m_next = (struct mbuf *)NULL; \
+ (m)->m_nextpkt = (struct mbuf *)NULL; \
+ (m)->m_data = (m)->m_dat; \
+ (m)->m_flags = 0; \
+ splx(_ms); \
+ } else { \
+ splx(_ms); \
+ (m) = m_retry((how), (type)); \
+ } \
+}
+
+#define MGETHDR(m, how, type) { \
+ int _ms = splimp(); \
+ if (mmbfree == 0) \
+ (void)m_mballoc(1, (how)); \
+ if (((m) = mmbfree) != 0) { \
+ mmbfree = (m)->m_next; \
+ mbstat.m_mtypes[MT_FREE]--; \
+ (m)->m_type = (type); \
+ mbstat.m_mtypes[type]++; \
+ (m)->m_next = (struct mbuf *)NULL; \
+ (m)->m_nextpkt = (struct mbuf *)NULL; \
+ (m)->m_data = (m)->m_pktdat; \
+ (m)->m_flags = M_PKTHDR; \
+ splx(_ms); \
+ } else { \
+ splx(_ms); \
+ (m) = m_retryhdr((how), (type)); \
+ } \
+}
+
+/*
+ * Mbuf cluster macros.
+ * MCLALLOC(caddr_t p, int how) allocates an mbuf cluster.
+ * MCLGET adds such clusters to a normal mbuf;
+ * the flag M_EXT is set upon success.
+ * MCLFREE releases a reference to a cluster allocated by MCLALLOC,
+ * freeing the cluster if the reference count has reached 0.
+ */
+#define MCLALLOC(p, how) \
+ MBUFLOCK( \
+ if (mclfree == 0) \
+ (void)m_clalloc(1, (how)); \
+ if (((p) = (caddr_t)mclfree) != 0) { \
+ ++mclrefcnt[mtocl(p)]; \
+ mbstat.m_clfree--; \
+ mclfree = ((union mcluster *)(p))->mcl_next; \
+ } \
+ )
+
+#define MCLGET(m, how) \
+ { MCLALLOC((m)->m_ext.ext_buf, (how)); \
+ if ((m)->m_ext.ext_buf != NULL) { \
+ (m)->m_data = (m)->m_ext.ext_buf; \
+ (m)->m_flags |= M_EXT; \
+ (m)->m_ext.ext_free = NULL; \
+ (m)->m_ext.ext_ref = NULL; \
+ (m)->m_ext.ext_size = MCLBYTES; \
+ } \
+ }
+
+#define MCLFREE(p) \
+ MBUFLOCK ( \
+ if (--mclrefcnt[mtocl(p)] == 0) { \
+ ((union mcluster *)(p))->mcl_next = mclfree; \
+ mclfree = (union mcluster *)(p); \
+ mbstat.m_clfree++; \
+ } \
+ )
+
+/*
+ * MFREE(struct mbuf *m, struct mbuf *n)
+ * Free a single mbuf and associated external storage.
+ * Place the successor, if any, in n.
+ */
+#define MFREE(m, n) \
+ MBUFLOCK( \
+ mbstat.m_mtypes[(m)->m_type]--; \
+ if ((m)->m_flags & M_EXT) { \
+ if ((m)->m_ext.ext_free) \
+ (*((m)->m_ext.ext_free))((m)->m_ext.ext_buf, \
+ (m)->m_ext.ext_size); \
+ else { \
+ char *p = (m)->m_ext.ext_buf; \
+ if (--mclrefcnt[mtocl(p)] == 0) { \
+ ((union mcluster *)(p))->mcl_next = mclfree; \
+ mclfree = (union mcluster *)(p); \
+ mbstat.m_clfree++; \
+ } \
+ } \
+ } \
+ (n) = (m)->m_next; \
+ (m)->m_type = MT_FREE; \
+ mbstat.m_mtypes[MT_FREE]++; \
+ (m)->m_next = mmbfree; \
+ mmbfree = (m); \
+ )
+
+/*
+ * Copy mbuf pkthdr from from to to.
+ * from must have M_PKTHDR set, and to must be empty.
+ */
+#define M_COPY_PKTHDR(to, from) { \
+ (to)->m_pkthdr = (from)->m_pkthdr; \
+ (to)->m_flags = (from)->m_flags & M_COPYFLAGS; \
+ (to)->m_data = (to)->m_pktdat; \
+}
+
+/*
+ * Set the m_data pointer of a newly-allocated mbuf (m_get/MGET) to place
+ * an object of the specified size at the end of the mbuf, longword aligned.
+ */
+#define M_ALIGN(m, len) \
+ { (m)->m_data += (MLEN - (len)) &~ (sizeof(long) - 1); }
+/*
+ * As above, for mbufs allocated with m_gethdr/MGETHDR
+ * or initialized by M_COPY_PKTHDR.
+ */
+#define MH_ALIGN(m, len) \
+ { (m)->m_data += (MHLEN - (len)) &~ (sizeof(long) - 1); }
+
+/*
+ * Compute the amount of space available
+ * before the current start of data in an mbuf.
+ */
+#define M_LEADINGSPACE(m) \
+ ((m)->m_flags & M_EXT ? /* (m)->m_data - (m)->m_ext.ext_buf */ 0 : \
+ (m)->m_flags & M_PKTHDR ? (m)->m_data - (m)->m_pktdat : \
+ (m)->m_data - (m)->m_dat)
+
+/*
+ * Compute the amount of space available
+ * after the end of data in an mbuf.
+ */
+#define M_TRAILINGSPACE(m) \
+ ((m)->m_flags & M_EXT ? (m)->m_ext.ext_buf + (m)->m_ext.ext_size - \
+ ((m)->m_data + (m)->m_len) : \
+ &(m)->m_dat[MLEN] - ((m)->m_data + (m)->m_len))
+
+/*
+ * Arrange to prepend space of size plen to mbuf m.
+ * If a new mbuf must be allocated, how specifies whether to wait.
+ * If how is M_DONTWAIT and allocation fails, the original mbuf chain
+ * is freed and m is set to NULL.
+ */
+#define M_PREPEND(m, plen, how) { \
+ if (M_LEADINGSPACE(m) >= (plen)) { \
+ (m)->m_data -= (plen); \
+ (m)->m_len += (plen); \
+ } else \
+ (m) = m_prepend((m), (plen), (how)); \
+ if ((m) && (m)->m_flags & M_PKTHDR) \
+ (m)->m_pkthdr.len += (plen); \
+}
+
+/* change mbuf to new type */
+#define MCHTYPE(m, t) { \
+ MBUFLOCK(mbstat.m_mtypes[(m)->m_type]--; mbstat.m_mtypes[t]++;) \
+ (m)->m_type = t;\
+}
+
+/* length to m_copy to copy all */
+#define M_COPYALL 1000000000
+
+/* compatibility with 4.3 */
+#define m_copy(m, o, l) m_copym((m), (o), (l), M_DONTWAIT)
+
+/*
+ * Mbuf statistics.
+ */
+struct mbstat {
+ u_long m_mbufs; /* mbufs obtained from page pool */
+ u_long m_clusters; /* clusters obtained from page pool */
+ u_long m_spare; /* spare field */
+ u_long m_clfree; /* free clusters */
+ u_long m_drops; /* times failed to find space */
+ u_long m_wait; /* times waited for space */
+ u_long m_drain; /* times drained protocols for space */
+ u_short m_mtypes[256]; /* type specific mbuf allocations */
+};
+
+#ifdef _KERNEL
+extern struct mbuf *mbutl; /* virtual address of mclusters */
+extern char *mclrefcnt; /* cluster reference counts */
+extern struct mbstat mbstat;
+extern int nmbclusters;
+extern int nmbufs;
+extern struct mbuf *mmbfree;
+extern union mcluster *mclfree;
+extern int max_linkhdr; /* largest link-level header */
+extern int max_protohdr; /* largest protocol header */
+extern int max_hdr; /* largest link+protocol header */
+extern int max_datalen; /* MHLEN - max_hdr */
+extern int mbtypes[]; /* XXX */
+
+struct mbuf *m_copym __P((struct mbuf *, int, int, int));
+struct mbuf *m_copypacket __P((struct mbuf *, int));
+struct mbuf *m_devget __P((char *, int, int, struct ifnet *,
+ void (*copy)(char *, caddr_t, u_int)));
+struct mbuf *m_free __P((struct mbuf *));
+struct mbuf *m_get __P((int, int));
+struct mbuf *m_getclr __P((int, int));
+struct mbuf *m_gethdr __P((int, int));
+struct mbuf *m_prepend __P((struct mbuf *,int,int));
+struct mbuf *m_pullup __P((struct mbuf *, int));
+struct mbuf *m_retry __P((int, int));
+struct mbuf *m_retryhdr __P((int, int));
+struct mbuf *m_split __P((struct mbuf *,int,int));
+void m_adj __P((struct mbuf *, int));
+void m_cat __P((struct mbuf *,struct mbuf *));
+int m_mballoc __P((int, int));
+int m_clalloc __P((int, int));
+int m_copyback __P((struct mbuf *, int, int, caddr_t));
+int m_copydata __P((struct mbuf *, int, int, caddr_t));
+void m_freem __P((struct mbuf *));
+void m_reclaim __P((void));
+
+#ifdef MBTYPES
+int mbtypes[] = { /* XXX */
+ M_FREE, /* MT_FREE 0 should be on free list */
+ M_MBUF, /* MT_DATA 1 dynamic (data) allocation */
+ M_MBUF, /* MT_HEADER 2 packet header */
+ M_SOCKET, /* MT_SOCKET 3 socket structure */
+ M_PCB, /* MT_PCB 4 protocol control block */
+ M_RTABLE, /* MT_RTABLE 5 routing tables */
+ M_HTABLE, /* MT_HTABLE 6 IMP host tables */
+ 0, /* MT_ATABLE 7 address resolution tables */
+ M_MBUF, /* MT_SONAME 8 socket name */
+ 0, /* 9 */
+ M_SOOPTS, /* MT_SOOPTS 10 socket options */
+ M_FTABLE, /* MT_FTABLE 11 fragment reassembly header */
+ M_MBUF, /* MT_RIGHTS 12 access rights */
+ M_IFADDR, /* MT_IFADDR 13 interface address */
+ M_MBUF, /* MT_CONTROL 14 extra-data protocol message */
+ M_MBUF, /* MT_OOBDATA 15 expedited data */
+#ifdef DATAKIT
+ 25, 26, 27, 28, 29, 30, 31, 32 /* datakit ugliness */
+#endif
+};
+#endif
+#endif
+
+#endif /* !_SYS_MBUF_H_ */
diff --git a/cpukit/libnetworking/sys/mount.h b/cpukit/libnetworking/sys/mount.h
new file mode 100644
index 0000000000..e3f6d04f9d
--- /dev/null
+++ b/cpukit/libnetworking/sys/mount.h
@@ -0,0 +1,531 @@
+/*
+ * Copyright (c) 1989, 1991, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)mount.h 8.13 (Berkeley) 3/27/94
+ * $Id$
+ */
+
+#ifndef _SYS_MOUNT_H_
+#define _SYS_MOUNT_H_
+
+#ifndef _KERNEL
+#include <sys/ucred.h>
+#endif
+#include <sys/queue.h>
+
+typedef struct fsid { long val[2]; } fsid_t; /* file system id type */
+
+/*
+ * File identifier.
+ * These are unique per filesystem on a single machine.
+ */
+#define MAXFIDSZ 16
+
+struct fid {
+ u_short fid_len; /* length of data in bytes */
+ u_short fid_reserved; /* force longword alignment */
+ char fid_data[MAXFIDSZ]; /* data (variable length) */
+};
+
+/*
+ * file system statistics
+ */
+
+#define MNAMELEN 90 /* length of buffer for returned name */
+
+struct statfs {
+ long f_spare2; /* placeholder */
+ long f_bsize; /* fundamental file system block size */
+ long f_iosize; /* optimal transfer block size */
+ long f_blocks; /* total data blocks in file system */
+ long f_bfree; /* free blocks in fs */
+ long f_bavail; /* free blocks avail to non-superuser */
+ long f_files; /* total file nodes in file system */
+ long f_ffree; /* free file nodes in fs */
+ fsid_t f_fsid; /* file system id */
+ uid_t f_owner; /* user that mounted the filesystem */
+ int f_type; /* type of filesystem (see below) */
+ int f_flags; /* copy of mount flags */
+ long f_spare[6]; /* spare for later */
+ char f_mntonname[MNAMELEN]; /* directory on which mounted */
+ char f_mntfromname[MNAMELEN];/* mounted filesystem */
+};
+
+/*
+ * File system types.
+ */
+#define MOUNT_NONE 0
+#define MOUNT_UFS 1 /* Fast Filesystem */
+#define MOUNT_NFS 2 /* Sun-compatible Network Filesystem */
+#define MOUNT_MFS 3 /* Memory-based Filesystem */
+#define MOUNT_MSDOS 4 /* MS/DOS Filesystem */
+#define MOUNT_LFS 5 /* Log-based Filesystem */
+#define MOUNT_LOFS 6 /* Loopback Filesystem */
+#define MOUNT_FDESC 7 /* File Descriptor Filesystem */
+#define MOUNT_PORTAL 8 /* Portal Filesystem */
+#define MOUNT_NULL 9 /* Minimal Filesystem Layer */
+#define MOUNT_UMAP 10 /* User/Group Identifier Remapping Filesystem */
+#define MOUNT_KERNFS 11 /* Kernel Information Filesystem */
+#define MOUNT_PROCFS 12 /* /proc Filesystem */
+#define MOUNT_AFS 13 /* Andrew Filesystem */
+#define MOUNT_CD9660 14 /* ISO9660 (aka CDROM) Filesystem */
+#define MOUNT_UNION 15 /* Union (translucent) Filesystem */
+#define MOUNT_DEVFS 16 /* existing device Filesystem */
+#define MOUNT_EXT2FS 17 /* Linux EXT2FS */
+#define MOUNT_TFS 18 /* Netcon Novell filesystem */
+#define MOUNT_CFS 19 /* Coda filesystem */
+#define MOUNT_MAXTYPE 19
+
+#define INITMOUNTNAMES { \
+ "none", /* 0 MOUNT_NONE */ \
+ "ufs", /* 1 MOUNT_UFS */ \
+ "nfs", /* 2 MOUNT_NFS */ \
+ "mfs", /* 3 MOUNT_MFS */ \
+ "msdos", /* 4 MOUNT_MSDOS */ \
+ "lfs", /* 5 MOUNT_LFS */ \
+ "lofs", /* 6 MOUNT_LOFS */ \
+ "fdesc", /* 7 MOUNT_FDESC */ \
+ "portal", /* 8 MOUNT_PORTAL */ \
+ "null", /* 9 MOUNT_NULL */ \
+ "umap", /* 10 MOUNT_UMAP */ \
+ "kernfs", /* 11 MOUNT_KERNFS */ \
+ "procfs", /* 12 MOUNT_PROCFS */ \
+ "afs", /* 13 MOUNT_AFS */ \
+ "cd9660", /* 14 MOUNT_CD9660 */ \
+ "union", /* 15 MOUNT_UNION */ \
+ "devfs", /* 16 MOUNT_DEVFS */ \
+ "ext2fs", /* 17 MOUNT_EXT2FS */ \
+ "tfs", /* 18 MOUNT_TFS */ \
+ "cfs", /* 19 MOUNT_CFS */ \
+ 0, /* 20 MOUNT_SPARE */ \
+}
+
+/*
+ * Structure per mounted file system. Each mounted file system has an
+ * array of operations and an instance record. The file systems are
+ * put on a doubly linked list.
+ */
+LIST_HEAD(vnodelst, vnode);
+
+struct mount {
+ CIRCLEQ_ENTRY(mount) mnt_list; /* mount list */
+ struct vfsops *mnt_op; /* operations on fs */
+ struct vfsconf *mnt_vfc; /* configuration info */
+ struct vnode *mnt_vnodecovered; /* vnode we mounted on */
+ struct vnodelst mnt_vnodelist; /* list of vnodes this mount */
+ int mnt_flag; /* flags */
+ int mnt_maxsymlinklen; /* max size of short symlink */
+ struct statfs mnt_stat; /* cache of filesystem stats */
+ qaddr_t mnt_data; /* private data */
+/* struct vfsconf *mnt_vfc; */ /* configuration info */
+ time_t mnt_time; /* last time written*/
+};
+
+/*
+ * Mount flags.
+ *
+ * Unmount uses MNT_FORCE flag.
+ */
+#define MNT_RDONLY 0x00000001 /* read only filesystem */
+#define MNT_SYNCHRONOUS 0x00000002 /* file system written synchronously */
+#define MNT_NOEXEC 0x00000004 /* can't exec from filesystem */
+#define MNT_NOSUID 0x00000008 /* don't honor setuid bits on fs */
+#define MNT_NODEV 0x00000010 /* don't interpret special files */
+#define MNT_UNION 0x00000020 /* union with underlying filesystem */
+#define MNT_ASYNC 0x00000040 /* file system written asynchronously */
+#define MNT_NOATIME 0x10000000 /* Disable update of file access times */
+
+/*
+ * exported mount flags.
+ */
+#define MNT_EXRDONLY 0x00000080 /* exported read only */
+#define MNT_EXPORTED 0x00000100 /* file system is exported */
+#define MNT_DEFEXPORTED 0x00000200 /* exported to the world */
+#define MNT_EXPORTANON 0x00000400 /* use anon uid mapping for everyone */
+#define MNT_EXKERB 0x00000800 /* exported with Kerberos uid mapping */
+
+/*
+ * Flags set by internal operations.
+ */
+#define MNT_LOCAL 0x00001000 /* filesystem is stored locally */
+#define MNT_QUOTA 0x00002000 /* quotas are enabled on filesystem */
+#define MNT_ROOTFS 0x00004000 /* identifies the root filesystem */
+#define MNT_USER 0x00008000 /* mounted by a user */
+
+/*
+ * Mask of flags that are visible to statfs()
+ */
+#define MNT_VISFLAGMASK (MNT_RDONLY|MNT_SYNCHRONOUS|MNT_NOEXEC|MNT_NOSUID| \
+ MNT_NODEV|MNT_UNION|MNT_ASYNC|MNT_EXRDONLY|MNT_EXPORTED| \
+ MNT_DEFEXPORTED|MNT_EXPORTANON|MNT_EXKERB|MNT_LOCAL| \
+ MNT_QUOTA|MNT_ROOTFS|MNT_USER|MNT_NOATIME)
+
+/*
+ * filesystem control flags.
+ *
+ * MNT_MLOCK lock the mount entry so that name lookup cannot proceed
+ * past the mount point. This keeps the subtree stable during mounts
+ * and unmounts.
+ */
+#define MNT_UPDATE 0x00010000 /* not a real mount, just an update */
+#define MNT_DELEXPORT 0x00020000 /* delete export host lists */
+#define MNT_RELOAD 0x00040000 /* reload filesystem data */
+#define MNT_FORCE 0x00080000 /* force unmount or readonly change */
+#define MNT_MLOCK 0x00100000 /* lock so that subtree is stable */
+#define MNT_MWAIT 0x00200000 /* someone is waiting for lock */
+#define MNT_MPBUSY 0x00400000 /* scan of mount point in progress */
+#define MNT_MPWANT 0x00800000 /* waiting for mount point */
+#define MNT_UNMOUNT 0x01000000 /* unmount in progress */
+#define MNT_WANTRDWR 0x02000000 /* want upgrade to read/write */
+
+/*
+ * used to get configured filesystems information
+ */
+#define VFS_MAXNAMELEN 32
+struct vfsconf {
+ void *vfc_vfsops;
+ char vfc_name[VFS_MAXNAMELEN];
+ int vfc_index;
+ int vfc_refcount;
+ int vfc_flags;
+};
+
+/*
+ * NB: these flags refer to IMPLEMENTATION properties, not properties of
+ * any actual mounts; i.e., it does not make sense to change the flags.
+ */
+#define VFCF_STATIC 0x00000001 /* statically compiled into kernel */
+#define VFCF_NETWORK 0x00000002 /* may get data over the network */
+#define VFCF_READONLY 0x00000004 /* writes are not implemented */
+#define VFCF_SYNTHETIC 0x00000008 /* data does not represent real files */
+#define VFCF_LOOPBACK 0x00000010 /* aliases some other mounted FS */
+#define VFCF_UNICODE 0x00000020 /* stores file names as Unicode*/
+
+/*
+ * Operations supported on mounted file system.
+ */
+#ifdef _KERNEL
+
+extern int doforce; /* Flag to permit forcible unmounting. */
+extern struct vfsconf void_vfsconf;
+extern struct vfsconf *vfsconf[];
+
+#ifdef __STDC__
+struct nameidata;
+struct mbuf;
+#endif
+
+struct vfsops {
+ int (*vfs_mount) __P((struct mount *mp, char *path, caddr_t data,
+ struct nameidata *ndp, struct proc *p));
+ int (*vfs_start) __P((struct mount *mp, int flags,
+ struct proc *p));
+ int (*vfs_unmount) __P((struct mount *mp, int mntflags,
+ struct proc *p));
+ int (*vfs_root) __P((struct mount *mp, struct vnode **vpp));
+ int (*vfs_quotactl) __P((struct mount *mp, int cmds, uid_t uid,
+ caddr_t arg, struct proc *p));
+ int (*vfs_statfs) __P((struct mount *mp, struct statfs *sbp,
+ struct proc *p));
+ int (*vfs_sync) __P((struct mount *mp, int waitfor,
+ struct ucred *cred, struct proc *p));
+ int (*vfs_vget) __P((struct mount *mp, ino_t ino,
+ struct vnode **vpp));
+ int (*vfs_fhtovp) __P((struct mount *mp, struct fid *fhp,
+ struct mbuf *nam, struct vnode **vpp,
+ int *exflagsp, struct ucred **credanonp));
+ int (*vfs_vptofh) __P((struct vnode *vp, struct fid *fhp));
+ int (*vfs_init) __P((void));
+};
+
+#define VFS_MOUNT(MP, PATH, DATA, NDP, P) \
+ (*(MP)->mnt_op->vfs_mount)(MP, PATH, DATA, NDP, P)
+#define VFS_START(MP, FLAGS, P) (*(MP)->mnt_op->vfs_start)(MP, FLAGS, P)
+#define VFS_UNMOUNT(MP, FORCE, P) (*(MP)->mnt_op->vfs_unmount)(MP, FORCE, P)
+#define VFS_ROOT(MP, VPP) (*(MP)->mnt_op->vfs_root)(MP, VPP)
+#define VFS_QUOTACTL(MP,C,U,A,P) (*(MP)->mnt_op->vfs_quotactl)(MP, C, U, A, P)
+#define VFS_STATFS(MP, SBP, P) (*(MP)->mnt_op->vfs_statfs)(MP, SBP, P)
+#define VFS_SYNC(MP, WAIT, C, P) (*(MP)->mnt_op->vfs_sync)(MP, WAIT, C, P)
+#define VFS_VGET(MP, INO, VPP) (*(MP)->mnt_op->vfs_vget)(MP, INO, VPP)
+#define VFS_FHTOVP(MP, FIDP, NAM, VPP, EXFLG, CRED) \
+ (*(MP)->mnt_op->vfs_fhtovp)(MP, FIDP, NAM, VPP, EXFLG, CRED)
+#define VFS_VPTOFH(VP, FIDP) (*(VP)->v_mount->mnt_op->vfs_vptofh)(VP, FIDP)
+
+#ifdef VFS_LKM
+#include <sys/conf.h>
+#include <sys/exec.h>
+#include <sys/sysent.h>
+#include <sys/lkm.h>
+
+#define VFS_SET(vfsops, fsname, index, flags) \
+ static struct vfsconf _fs_vfsconf = { \
+ &vfsops, \
+ #fsname, \
+ index, \
+ 0, \
+ flags \
+ }; \
+ extern struct linker_set MODVNOPS; \
+ MOD_VFS(#fsname,index,&MODVNOPS,&_fs_vfsconf); \
+ int \
+ fsname ## _mod(struct lkm_table *lkmtp, int cmd, int ver) { \
+ DISPATCH(lkmtp, cmd, ver, lkm_nullcmd, lkm_nullcmd, lkm_nullcmd); }
+#else
+
+#define VFS_SET(vfsops, fsname, index, flags) \
+ static struct vfsconf _fs_vfsconf = { \
+ &vfsops, \
+ #fsname, \
+ index, \
+ 0, \
+ flags | VFCF_STATIC \
+ }; \
+ DATA_SET(vfs_set,_fs_vfsconf)
+#endif /* VFS_LKM */
+
+#endif /* _KERNEL */
+
+/*
+ * Flags for various system call interfaces.
+ *
+ * waitfor flags to vfs_sync() and getfsstat()
+ */
+#define MNT_WAIT 1
+#define MNT_NOWAIT 2
+
+/*
+ * Generic file handle
+ */
+struct fhandle {
+ fsid_t fh_fsid; /* File system id of mount point */
+ struct fid fh_fid; /* File sys specific id */
+};
+typedef struct fhandle fhandle_t;
+
+#ifdef _KERNEL
+#include <net/radix.h>
+#include <sys/socket.h> /* XXX for AF_MAX */
+
+/*
+ * Network address lookup element
+ */
+struct netcred {
+ struct radix_node netc_rnodes[2];
+ int netc_exflags;
+ struct ucred netc_anon;
+};
+
+/*
+ * Network export information
+ */
+struct netexport {
+ struct netcred ne_defexported; /* Default export */
+ struct radix_node_head *ne_rtable[AF_MAX+1]; /* Individual exports */
+};
+#endif /* _KERNEL */
+
+/*
+ * Export arguments for local filesystem mount calls.
+ */
+struct export_args {
+ int ex_flags; /* export related flags */
+ uid_t ex_root; /* mapping for root uid */
+ struct ucred ex_anon; /* mapping for anonymous user */
+ struct sockaddr *ex_addr; /* net address to which exported */
+ int ex_addrlen; /* and the net address length */
+ struct sockaddr *ex_mask; /* mask of valid bits in saddr */
+ int ex_masklen; /* and the smask length */
+};
+
+/*
+ * Arguments to mount UFS-based filesystems
+ */
+struct ufs_args {
+ char *fspec; /* block special device to mount */
+ struct export_args export; /* network export information */
+};
+
+#ifdef MFS
+/*
+ * Arguments to mount MFS
+ */
+struct mfs_args {
+ char *fspec; /* name to export for statfs */
+ struct export_args export; /* if exported MFSes are supported */
+ caddr_t base; /* base of file system in memory */
+ u_long size; /* size of file system */
+};
+#endif /* MFS */
+
+#ifdef MSDOSFS
+/*
+ * Arguments to mount MSDOS filesystems.
+ */
+struct msdosfs_args {
+ char *fspec; /* blocks special holding the fs to mount */
+ struct export_args export; /* network export information */
+ uid_t uid; /* uid that owns msdosfs files */
+ gid_t gid; /* gid that owns msdosfs files */
+ mode_t mask; /* mask to be applied for msdosfs perms */
+};
+#endif
+
+#ifdef CD9660
+/*
+ * Arguments to mount ISO 9660 filesystems.
+ */
+struct iso_args {
+ char *fspec; /* block special device to mount */
+ struct export_args export; /* network export info */
+ int flags; /* mounting flags, see below */
+ int ssector; /* starting sector */
+
+};
+#define ISOFSMNT_NORRIP 0x00000001 /* disable Rock Ridge Ext.*/
+#define ISOFSMNT_GENS 0x00000002 /* enable generation numbers */
+#define ISOFSMNT_EXTATT 0x00000004 /* enable extended attributes */
+#endif /* CD9660 */
+
+#ifdef NFS
+/*
+ * Arguments to mount NFS
+ */
+struct nfs_args {
+ struct sockaddr *addr; /* file server address */
+ int addrlen; /* length of address */
+ int sotype; /* Socket type */
+ int proto; /* and Protocol */
+ u_char *fh; /* File handle to be mounted */
+ int fhsize; /* Size, in bytes, of fh */
+ int flags; /* flags */
+ int wsize; /* write size in bytes */
+ int rsize; /* read size in bytes */
+ int readdirsize; /* readdir size in bytes */
+ int timeo; /* initial timeout in .1 secs */
+ int retrans; /* times to retry send */
+ int maxgrouplist; /* Max. size of group list */
+ int readahead; /* # of blocks to readahead */
+ int leaseterm; /* Term (sec) of lease */
+ int deadthresh; /* Retrans threshold */
+ char *hostname; /* server's name */
+};
+
+/*
+ * NFS mount option flags
+ */
+#define NFSMNT_SOFT 0x00000001 /* soft mount (hard is default) */
+#define NFSMNT_WSIZE 0x00000002 /* set write size */
+#define NFSMNT_RSIZE 0x00000004 /* set read size */
+#define NFSMNT_TIMEO 0x00000008 /* set initial timeout */
+#define NFSMNT_RETRANS 0x00000010 /* set number of request retrys */
+#define NFSMNT_MAXGRPS 0x00000020 /* set maximum grouplist size */
+#define NFSMNT_INT 0x00000040 /* allow interrupts on hard mount */
+#define NFSMNT_NOCONN 0x00000080 /* Don't Connect the socket */
+#define NFSMNT_NQNFS 0x00000100 /* Use Nqnfs protocol */
+#define NFSMNT_NFSV3 0x00000200 /* Use NFS Version 3 protocol */
+#define NFSMNT_KERB 0x00000400 /* Use Kerberos authentication */
+#define NFSMNT_DUMBTIMR 0x00000800 /* Don't estimate rtt dynamically */
+#define NFSMNT_LEASETERM 0x00001000 /* set lease term (nqnfs) */
+#define NFSMNT_READAHEAD 0x00002000 /* set read ahead */
+#define NFSMNT_DEADTHRESH 0x00004000 /* set dead server retry thresh */
+#define NFSMNT_RESVPORT 0x00008000 /* Allocate a reserved port */
+#define NFSMNT_RDIRPLUS 0x00010000 /* Use Readdirplus for V3 */
+#define NFSMNT_READDIRSIZE 0x00020000 /* Set readdir size */
+#define NFSMNT_INTERNAL 0xfffc0000 /* Bits set internally */
+#define NFSMNT_HASWRITEVERF 0x00040000 /* Has write verifier for V3 */
+#define NFSMNT_GOTPATHCONF 0x00080000 /* Got the V3 pathconf info */
+#define NFSMNT_GOTFSINFO 0x00100000 /* Got the V3 fsinfo */
+#define NFSMNT_MNTD 0x00200000 /* Mnt server for mnt point */
+#define NFSMNT_DISMINPROG 0x00400000 /* Dismount in progress */
+#define NFSMNT_DISMNT 0x00800000 /* Dismounted */
+#define NFSMNT_SNDLOCK 0x01000000 /* Send socket lock */
+#define NFSMNT_WANTSND 0x02000000 /* Want above */
+#define NFSMNT_RCVLOCK 0x04000000 /* Rcv socket lock */
+#define NFSMNT_WANTRCV 0x08000000 /* Want above */
+#define NFSMNT_WAITAUTH 0x10000000 /* Wait for authentication */
+#define NFSMNT_HASAUTH 0x20000000 /* Has authenticator */
+#define NFSMNT_WANTAUTH 0x40000000 /* Wants an authenticator */
+#define NFSMNT_AUTHERR 0x80000000 /* Authentication error */
+#endif /* NFS */
+
+#ifdef _KERNEL
+extern int (*mountroot) __P((void *));
+extern struct vfsops *mountrootvfsops;
+
+/*
+ * exported vnode operations
+ */
+int dounmount __P((struct mount *, int, struct proc *));
+struct mount *getvfs __P((fsid_t *)); /* return vfs given fsid */
+void getnewfsid __P((struct mount *, int));
+int vflush __P((struct mount *, struct vnode *, int));
+int vfs_export /* process mount export info */
+ __P((struct mount *, struct netexport *, struct export_args *));
+struct netcred *vfs_export_lookup /* lookup host in fs export list */
+ __P((struct mount *, struct netexport *, struct mbuf *));
+int vfs_lock __P((struct mount *)); /* lock a vfs */
+int vfs_mountedon __P((struct vnode *)); /* is a vfs mounted on vp */
+int vfs_mountroot __P((void *)); /* XXX goes away? */
+void vfs_msync __P((struct mount *, int));
+void vfs_unlock __P((struct mount *)); /* unlock a vfs */
+void vfs_unmountall __P((void));
+int vfs_busy __P((struct mount *)); /* mark a vfs busy */
+void vfs_unbusy __P((struct mount *)); /* mark a vfs not busy */
+extern CIRCLEQ_HEAD(mntlist, mount) mountlist; /* mounted filesystem list */
+extern struct vfsops *vfssw[]; /* filesystem type table */
+
+#else /* _KERNEL */
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+int fstatfs __P((int, struct statfs *));
+int getfh __P((const char *, fhandle_t *));
+int getfsstat __P((struct statfs *, long, int));
+int getmntinfo __P((struct statfs **, int));
+int mount __P((int, const char *, int, void *));
+int statfs __P((const char *, struct statfs *));
+int unmount __P((const char *, int));
+
+/* C library stuff */
+struct vfsconf *getvfsbyname __P((const char *));
+struct vfsconf *getvfsbytype __P((int));
+struct vfsconf *getvfsent __P((void));
+void setvfsent __P((int));
+void endvfsent __P((void));
+int vfsisloadable __P((const char *));
+int vfsload __P((const char *));
+__END_DECLS
+
+#endif /* _KERNEL */
+
+#endif /* !_SYS_MOUNT_H_ */
diff --git a/cpukit/libnetworking/sys/poll.h b/cpukit/libnetworking/sys/poll.h
new file mode 100644
index 0000000000..9ea42b9ddf
--- /dev/null
+++ b/cpukit/libnetworking/sys/poll.h
@@ -0,0 +1,104 @@
+/*-
+ * Copyright (c) 1997 Peter Wemm <peter@freebsd.org>
+ * 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. 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 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.
+ *
+ * $FreeBSD: src/sys/sys/poll.h,v 1.13 2002/07/10 04:47:25 mike Exp $
+ */
+
+#ifndef _SYS_POLL_H_
+#define _SYS_POLL_H_
+
+#include <sys/cdefs.h>
+
+/*
+ * This file is intended to be compatible with the traditional poll.h.
+ */
+
+typedef unsigned int nfds_t;
+
+/*
+ * This structure is passed as an array to poll(2).
+ */
+struct pollfd {
+ int fd; /* which file descriptor to poll */
+ short events; /* events we are interested in */
+ short revents; /* events found on return */
+};
+
+/*
+ * Requestable events. If poll(2) finds any of these set, they are
+ * copied to revents on return.
+ * XXX Note that FreeBSD doesn't make much distinction between POLLPRI
+ * and POLLRDBAND since none of the file types have distinct priority
+ * bands - and only some have an urgent "mode".
+ * XXX Note POLLIN isn't really supported in true SVSV terms. Under SYSV
+ * POLLIN includes all of normal, band and urgent data. Most poll handlers
+ * on FreeBSD only treat it as "normal" data.
+ */
+#define POLLIN 0x0001 /* any readable data available */
+#define POLLPRI 0x0002 /* OOB/Urgent readable data */
+#define POLLOUT 0x0004 /* file descriptor is writeable */
+#define POLLRDNORM 0x0040 /* non-OOB/URG data available */
+#define POLLWRNORM POLLOUT /* no write type differentiation */
+#define POLLRDBAND 0x0080 /* OOB/Urgent readable data */
+#define POLLWRBAND 0x0100 /* OOB/Urgent data can be written */
+
+#if __BSD_VISIBLE
+/* General FreeBSD extension (currently only supported for sockets): */
+#define POLLINIGNEOF 0x2000 /* like POLLIN, except ignore EOF */
+#endif
+
+/*
+ * These events are set if they occur regardless of whether they were
+ * requested.
+ */
+#define POLLERR 0x0008 /* some poll error occurred */
+#define POLLHUP 0x0010 /* file descriptor was "hung up" */
+#define POLLNVAL 0x0020 /* requested events "invalid" */
+
+#if __BSD_VISIBLE
+
+#define POLLSTANDARD (POLLIN|POLLPRI|POLLOUT|POLLRDNORM|POLLRDBAND|\
+ POLLWRBAND|POLLERR|POLLHUP|POLLNVAL)
+
+/*
+ * Request that poll() wait forever.
+ * XXX in SYSV, this is defined in stropts.h, which is not included
+ * by poll.h.
+ */
+#define INFTIM (-1)
+
+#endif
+
+#ifndef _KERNEL
+
+__BEGIN_DECLS
+int poll(struct pollfd _pfd[], nfds_t _nfds, int _timeout);
+__END_DECLS
+
+#endif /* !_KERNEL */
+
+#endif /* !_SYS_POLL_H_ */
diff --git a/cpukit/libnetworking/sys/proc.h b/cpukit/libnetworking/sys/proc.h
new file mode 100644
index 0000000000..2189a33b11
--- /dev/null
+++ b/cpukit/libnetworking/sys/proc.h
@@ -0,0 +1,8 @@
+/*
+ * Dummy structure
+ *
+ * $Id$
+ */
+struct proc {
+ int this_should_never_be_referenced;
+};
diff --git a/cpukit/libnetworking/sys/protosw.h b/cpukit/libnetworking/sys/protosw.h
new file mode 100644
index 0000000000..13bbc26cee
--- /dev/null
+++ b/cpukit/libnetworking/sys/protosw.h
@@ -0,0 +1,300 @@
+/*-
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)protosw.h 8.1 (Berkeley) 6/2/93
+ * $FreeBSD: src/sys/sys/protosw.h,v 1.43 2004/04/07 04:19:49 imp Exp $
+ */
+
+#ifndef _SYS_PROTOSW_H_
+#define _SYS_PROTOSW_H_
+
+/* Forward declare these structures referenced from prototypes below. */
+struct mbuf;
+struct sockaddr;
+struct socket;
+struct sockproto;
+struct stat;
+
+/*
+ * Protocol switch table.
+ *
+ * Each protocol has a handle initializing one of these structures,
+ * which is used for protocol-protocol and system-protocol communication.
+ *
+ * A protocol is called through the pr_init entry before any other.
+ * Thereafter it is called every 200ms through the pr_fasttimo entry and
+ * every 500ms through the pr_slowtimo for timer based actions.
+ * The system will call the pr_drain entry if it is low on space and
+ * this should throw away any non-critical data.
+ *
+ * Protocols pass data between themselves as chains of mbufs using
+ * the pr_input and pr_output hooks. Pr_input passes data up (towards
+ * UNIX) and pr_output passes it down (towards the imps); control
+ * information passes up and down on pr_ctlinput and pr_ctloutput.
+ * The protocol is responsible for the space occupied by any the
+ * arguments to these entries and must dispose it.
+ *
+ * The userreq routine interfaces protocols to the system and is
+ * described below.
+ */
+struct protosw {
+ short pr_type; /* socket type used for */
+ struct domain *pr_domain; /* domain protocol a member of */
+ short pr_protocol; /* protocol number */
+ short pr_flags; /* see below */
+/* protocol-protocol hooks */
+ void (*pr_input) __P((struct mbuf *, int len));
+ /* input to protocol (from below) */
+ int (*pr_output) __P((struct mbuf *m, struct socket *so));
+ /* output to protocol (from above) */
+ void (*pr_ctlinput)__P((int, struct sockaddr *, void *));
+ /* control input (from below) */
+ int (*pr_ctloutput)__P((int, struct socket *, int, int,
+ struct mbuf **));
+ /* control output (from above) */
+/* user-protocol hook */
+ int (*pr_ousrreq) __P((struct socket *, int, struct mbuf *,
+ struct mbuf *, struct mbuf *));
+ /* user request: see list below */
+/* utility hooks */
+ void (*pr_init) __P((void)); /* initialization hook */
+ void (*pr_fasttimo) __P((void));
+ /* fast timeout (200ms) */
+ void (*pr_slowtimo) __P((void));
+ /* slow timeout (500ms) */
+ void (*pr_drain) __P((void));
+ /* flush any excess space possible */
+ struct pr_usrreqs *pr_usrreqs; /* supersedes pr_usrreq() */
+};
+
+#define PR_SLOWHZ 2 /* 2 slow timeouts per second */
+#define PR_FASTHZ 5 /* 5 fast timeouts per second */
+
+/*
+ * Values for pr_flags.
+ * PR_ADDR requires PR_ATOMIC;
+ * PR_ADDR and PR_CONNREQUIRED are mutually exclusive.
+ * PR_IMPLOPCL means that the protocol allows sendto without prior connect,
+ * and the protocol understands the MSG_EOF flag. The first property is
+ * is only relevant if PR_CONNREQUIRED is set (otherwise sendto is allowed
+ * anyhow).
+ */
+#define PR_ATOMIC 0x01 /* exchange atomic messages only */
+#define PR_ADDR 0x02 /* addresses given with messages */
+#define PR_CONNREQUIRED 0x04 /* connection required by protocol */
+#define PR_WANTRCVD 0x08 /* want PRU_RCVD calls */
+#define PR_RIGHTS 0x10 /* passes capabilities */
+#define PR_IMPLOPCL 0x20 /* implied open/close */
+#define PR_LASTHDR 0x40 /* enforce ipsec policy; last header */
+
+/*
+ * The arguments to usrreq are:
+ * (*protosw[].pr_usrreq)(up, req, m, nam, opt);
+ * where up is a (struct socket *), req is one of these requests,
+ * m is an optional mbuf chain containing a message,
+ * nam is an optional mbuf chain containing an address,
+ * and opt is a pointer to a socketopt structure or nil.
+ * The protocol is responsible for disposal of the mbuf chain m,
+ * the caller is responsible for any space held by nam and opt.
+ * A non-zero return from usrreq gives an
+ * UNIX error number which should be passed to higher level software.
+ */
+#define PRU_ATTACH 0 /* attach protocol to up */
+#define PRU_DETACH 1 /* detach protocol from up */
+#define PRU_BIND 2 /* bind socket to address */
+#define PRU_LISTEN 3 /* listen for connection */
+#define PRU_CONNECT 4 /* establish connection to peer */
+#define PRU_ACCEPT 5 /* accept connection from peer */
+#define PRU_DISCONNECT 6 /* disconnect from peer */
+#define PRU_SHUTDOWN 7 /* won't send any more data */
+#define PRU_RCVD 8 /* have taken data; more room now */
+#define PRU_SEND 9 /* send this data */
+#define PRU_ABORT 10 /* abort (fast DISCONNECT, DETATCH) */
+#define PRU_CONTROL 11 /* control operations on protocol */
+#define PRU_SENSE 12 /* return status into m */
+#define PRU_RCVOOB 13 /* retrieve out of band data */
+#define PRU_SENDOOB 14 /* send out of band data */
+#define PRU_SOCKADDR 15 /* fetch socket's address */
+#define PRU_PEERADDR 16 /* fetch peer's address */
+#define PRU_CONNECT2 17 /* connect two sockets */
+/* begin for protocols internal use */
+#define PRU_FASTTIMO 18 /* 200ms timeout */
+#define PRU_SLOWTIMO 19 /* 500ms timeout */
+#define PRU_PROTORCV 20 /* receive from below */
+#define PRU_PROTOSEND 21 /* send to below */
+/* end for protocol's internal use */
+#define PRU_SEND_EOF 22 /* send and close */
+#define PRU_NREQ 22
+
+#ifdef PRUREQUESTS
+const char *prurequests[] = {
+ "ATTACH", "DETACH", "BIND", "LISTEN",
+ "CONNECT", "ACCEPT", "DISCONNECT", "SHUTDOWN",
+ "RCVD", "SEND", "ABORT", "CONTROL",
+ "SENSE", "RCVOOB", "SENDOOB", "SOCKADDR",
+ "PEERADDR", "CONNECT2", "FASTTIMO", "SLOWTIMO",
+ "PROTORCV", "PROTOSEND",
+ "SEND_EOF",
+};
+#endif
+
+#ifdef _KERNEL /* users shouldn't see this decl */
+struct stat;
+struct ifnet;
+
+/*
+ * If the ordering here looks odd, that's because it's alphabetical.
+ */
+struct pr_usrreqs {
+ int (*pru_abort) __P((struct socket *so));
+ int (*pru_accept) __P((struct socket *so, struct mbuf *nam));
+ int (*pru_attach) __P((struct socket *so, int proto));
+ int (*pru_bind) __P((struct socket *so, struct mbuf *nam));
+ int (*pru_connect) __P((struct socket *so, struct mbuf *nam));
+ int (*pru_connect2) __P((struct socket *so1, struct socket *so2));
+ int (*pru_control) __P((struct socket *so, int cmd, caddr_t data,
+ struct ifnet *ifp));
+ int (*pru_detach) __P((struct socket *so));
+ int (*pru_disconnect) __P((struct socket *so));
+ int (*pru_listen) __P((struct socket *so));
+ int (*pru_peeraddr) __P((struct socket *so, struct mbuf *nam));
+ int (*pru_rcvd) __P((struct socket *so, int flags));
+ int (*pru_rcvoob) __P((struct socket *so, struct mbuf *m,
+ int flags));
+ /*
+ * The `m' parameter here is almost certainly going to become a
+ * `struct uio' at some point in the future. Similar changes
+ * will probably happen for the receive entry points.
+ */
+ int (*pru_send) __P((struct socket *so, int flags, struct mbuf *m,
+ struct mbuf *addr, struct mbuf *control));
+#define PRUS_OOB 0x1
+#define PRUS_EOF 0x2
+ int (*pru_sense) __P((struct socket *so, struct stat *sb));
+ int (*pru_shutdown) __P((struct socket *so));
+ int (*pru_sockaddr) __P((struct socket *so, struct mbuf *nam));
+};
+
+int pru_accept_notsupp(struct socket *so, struct mbuf *nam);
+int pru_connect2_notsupp(struct socket *so1, struct socket *so2);
+int pru_control_notsupp(struct socket *so, int cmd, caddr_t data,
+ struct ifnet *ifp);
+int pru_listen_notsupp(struct socket *so);
+int pru_rcvd_notsupp(struct socket *so, int flags);
+int pru_rcvoob_notsupp(struct socket *so, struct mbuf *m, int flags);
+int pru_sense_null(struct socket *so, struct stat *sb);
+
+#define PRU_OLDSTYLE
+
+#ifdef PRU_OLDSTYLE
+/*
+ * Protocols which don't yet implement pr_usrreqs can point it to this
+ * structure, which will call the old pr_usrreq() entry point with the
+ * appropriate arguments.
+ */
+extern struct pr_usrreqs pru_oldstyle;
+#endif /* PRU_OLDSTYLE */
+
+#endif /* _KERNEL */
+
+/*
+ * The arguments to the ctlinput routine are
+ * (*protosw[].pr_ctlinput)(cmd, sa, arg);
+ * where cmd is one of the commands below, sa is a pointer to a sockaddr,
+ * and arg is a `void *' argument used within a protocol family.
+ */
+#define PRC_IFDOWN 0 /* interface transition */
+#define PRC_ROUTEDEAD 1 /* select new route if possible ??? */
+#define PRC_IFUP 2 /* interface has come back up */
+#define PRC_QUENCH2 3 /* DEC congestion bit says slow down */
+#define PRC_QUENCH 4 /* some one said to slow down */
+#define PRC_MSGSIZE 5 /* message size forced drop */
+#define PRC_HOSTDEAD 6 /* host appears to be down */
+#define PRC_HOSTUNREACH 7 /* deprecated (use PRC_UNREACH_HOST) */
+#define PRC_UNREACH_NET 8 /* no route to network */
+#define PRC_UNREACH_HOST 9 /* no route to host */
+#define PRC_UNREACH_PROTOCOL 10 /* dst says bad protocol */
+#define PRC_UNREACH_PORT 11 /* bad port # */
+/* was PRC_UNREACH_NEEDFRAG 12 (use PRC_MSGSIZE) */
+#define PRC_UNREACH_SRCFAIL 13 /* source route failed */
+#define PRC_REDIRECT_NET 14 /* net routing redirect */
+#define PRC_REDIRECT_HOST 15 /* host routing redirect */
+#define PRC_REDIRECT_TOSNET 16 /* redirect for type of service & net */
+#define PRC_REDIRECT_TOSHOST 17 /* redirect for tos & host */
+#define PRC_TIMXCEED_INTRANS 18 /* packet lifetime expired in transit */
+#define PRC_TIMXCEED_REASS 19 /* lifetime expired on reass q */
+#define PRC_PARAMPROB 20 /* header incorrect */
+#define PRC_UNREACH_ADMIN_PROHIB 21 /* packet administrativly prohibited */
+
+#define PRC_NCMDS 22
+
+#define PRC_IS_REDIRECT(cmd) \
+ ((cmd) >= PRC_REDIRECT_NET && (cmd) <= PRC_REDIRECT_TOSHOST)
+
+#ifdef PRCREQUESTS
+char *prcrequests[] = {
+ "IFDOWN", "ROUTEDEAD", "IFUP", "DEC-BIT-QUENCH2",
+ "QUENCH", "MSGSIZE", "HOSTDEAD", "#7",
+ "NET-UNREACH", "HOST-UNREACH", "PROTO-UNREACH", "PORT-UNREACH",
+ "#12", "SRCFAIL-UNREACH", "NET-REDIRECT", "HOST-REDIRECT",
+ "TOSNET-REDIRECT", "TOSHOST-REDIRECT", "TX-INTRANS", "TX-REASS",
+ "PARAMPROB", "ADMIN-UNREACH"
+};
+#endif
+
+/*
+ * The arguments to ctloutput are:
+ * (*protosw[].pr_ctloutput)(req, so, level, optname, optval);
+ * req is one of the actions listed below, so is a (struct socket *),
+ * level is an indication of which protocol layer the option is intended.
+ * optname is a protocol dependent socket option request,
+ * optval is a pointer to a mbuf-chain pointer, for value-return results.
+ * The protocol is responsible for disposal of the mbuf chain *optval
+ * if supplied,
+ * the caller is responsible for any space held by *optval, when returned.
+ * A non-zero return from usrreq gives an
+ * UNIX error number which should be passed to higher level software.
+ */
+#define PRCO_GETOPT 0
+#define PRCO_SETOPT 1
+
+#define PRCO_NCMDS 2
+
+#ifdef PRCOREQUESTS
+char *prcorequests[] = {
+ "GETOPT", "SETOPT",
+};
+#endif
+
+#ifdef _KERNEL
+void pfctlinput(int, struct sockaddr *);
+struct protosw *pffindproto(int family, int protocol, int type);
+struct protosw *pffindtype(int family, int type);
+#endif
+
+#endif
diff --git a/cpukit/libnetworking/sys/queue.h b/cpukit/libnetworking/sys/queue.h
new file mode 100644
index 0000000000..6ff47d9fe2
--- /dev/null
+++ b/cpukit/libnetworking/sys/queue.h
@@ -0,0 +1,611 @@
+/*
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)queue.h 8.5 (Berkeley) 8/20/94
+ * $FreeBSD: src/sys/sys/queue.h,v 1.54 2002/08/05 05:18:43 alfred Exp $
+ */
+
+#ifndef _SYS_QUEUE_H_
+#define _SYS_QUEUE_H_
+
+#include <sys/cdefs.h>
+
+/*
+ * This file defines four types of data structures: singly-linked lists,
+ * singly-linked tail queues, lists and tail queues.
+ *
+ * A singly-linked list is headed by a single forward pointer. The elements
+ * are singly linked for minimum space and pointer manipulation overhead at
+ * the expense of O(n) removal for arbitrary elements. New elements can be
+ * added to the list after an existing element or at the head of the list.
+ * Elements being removed from the head of the list should use the explicit
+ * macro for this purpose for optimum efficiency. A singly-linked list may
+ * only be traversed in the forward direction. Singly-linked lists are ideal
+ * for applications with large datasets and few or no removals or for
+ * implementing a LIFO queue.
+ *
+ * A singly-linked tail queue is headed by a pair of pointers, one to the
+ * head of the list and the other to the tail of the list. The elements are
+ * singly linked for minimum space and pointer manipulation overhead at the
+ * expense of O(n) removal for arbitrary elements. New elements can be added
+ * to the list after an existing element, at the head of the list, or at the
+ * end of the list. Elements being removed from the head of the tail queue
+ * should use the explicit macro for this purpose for optimum efficiency.
+ * A singly-linked tail queue may only be traversed in the forward direction.
+ * Singly-linked tail queues are ideal for applications with large datasets
+ * and few or no removals or for implementing a FIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ *
+ *
+ * SLIST LIST STAILQ TAILQ
+ * _HEAD + + + +
+ * _HEAD_INITIALIZER + + + +
+ * _ENTRY + + + +
+ * _INIT + + + +
+ * _EMPTY + + + +
+ * _FIRST + + + +
+ * _NEXT + + + +
+ * _PREV - - - +
+ * _LAST - - + +
+ * _FOREACH + + + +
+ * _FOREACH_REVERSE - - - +
+ * _INSERT_HEAD + + + +
+ * _INSERT_BEFORE - + - +
+ * _INSERT_AFTER + + + +
+ * _INSERT_TAIL - - + +
+ * _CONCAT - - + +
+ * _REMOVE_HEAD + - + -
+ * _REMOVE + + + +
+ *
+ */
+#define QUEUE_MACRO_DEBUG 0
+#if QUEUE_MACRO_DEBUG
+/* Store the last 2 places the queue element or head was altered */
+struct qm_trace {
+ char * lastfile;
+ int lastline;
+ char * prevfile;
+ int prevline;
+};
+
+#define TRACEBUF struct qm_trace trace;
+#define TRASHIT(x) do {(x) = (void *)-1;} while (0)
+
+#define QMD_TRACE_HEAD(head) do { \
+ (head)->trace.prevline = (head)->trace.lastline; \
+ (head)->trace.prevfile = (head)->trace.lastfile; \
+ (head)->trace.lastline = __LINE__; \
+ (head)->trace.lastfile = __FILE__; \
+} while (0)
+
+#define QMD_TRACE_ELEM(elem) do { \
+ (elem)->trace.prevline = (elem)->trace.lastline; \
+ (elem)->trace.prevfile = (elem)->trace.lastfile; \
+ (elem)->trace.lastline = __LINE__; \
+ (elem)->trace.lastfile = __FILE__; \
+} while (0)
+
+#else
+#define QMD_TRACE_ELEM(elem)
+#define QMD_TRACE_HEAD(head)
+#define TRACEBUF
+#define TRASHIT(x)
+#endif /* QUEUE_MACRO_DEBUG */
+
+/*
+ * Singly-linked List declarations.
+ */
+#define SLIST_HEAD(name, type) \
+struct name { \
+ struct type *slh_first; /* first element */ \
+}
+
+#define SLIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define SLIST_ENTRY(type) \
+struct { \
+ struct type *sle_next; /* next element */ \
+}
+
+/*
+ * Singly-linked List functions.
+ */
+#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
+
+#define SLIST_FIRST(head) ((head)->slh_first)
+
+#define SLIST_FOREACH(var, head, field) \
+ for ((var) = SLIST_FIRST((head)); \
+ (var); \
+ (var) = SLIST_NEXT((var), field))
+
+#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
+ for ((varp) = &SLIST_FIRST((head)); \
+ ((var) = *(varp)) != NULL; \
+ (varp) = &SLIST_NEXT((var), field))
+
+#define SLIST_INIT(head) do { \
+ SLIST_FIRST((head)) = NULL; \
+} while (0)
+
+#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
+ SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
+ SLIST_NEXT((slistelm), field) = (elm); \
+} while (0)
+
+#define SLIST_INSERT_HEAD(head, elm, field) do { \
+ SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
+ SLIST_FIRST((head)) = (elm); \
+} while (0)
+
+#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
+
+#define SLIST_REMOVE(head, elm, type, field) do { \
+ if (SLIST_FIRST((head)) == (elm)) { \
+ SLIST_REMOVE_HEAD((head), field); \
+ } \
+ else { \
+ struct type *curelm = SLIST_FIRST((head)); \
+ while (SLIST_NEXT(curelm, field) != (elm)) \
+ curelm = SLIST_NEXT(curelm, field); \
+ SLIST_NEXT(curelm, field) = \
+ SLIST_NEXT(SLIST_NEXT(curelm, field), field); \
+ } \
+} while (0)
+
+#define SLIST_REMOVE_HEAD(head, field) do { \
+ SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
+} while (0)
+
+/*
+ * Singly-linked Tail queue declarations.
+ */
+#define STAILQ_HEAD(name, type) \
+struct name { \
+ struct type *stqh_first;/* first element */ \
+ struct type **stqh_last;/* addr of last next element */ \
+}
+
+#define STAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).stqh_first }
+
+#define STAILQ_ENTRY(type) \
+struct { \
+ struct type *stqe_next; /* next element */ \
+}
+
+/*
+ * Singly-linked Tail queue functions.
+ */
+#define STAILQ_CONCAT(head1, head2) do { \
+ if (!STAILQ_EMPTY((head2))) { \
+ *(head1)->stqh_last = (head2)->stqh_first; \
+ (head1)->stqh_last = (head2)->stqh_last; \
+ STAILQ_INIT((head2)); \
+ } \
+} while (0)
+
+#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
+
+#define STAILQ_FIRST(head) ((head)->stqh_first)
+
+#define STAILQ_FOREACH(var, head, field) \
+ for((var) = STAILQ_FIRST((head)); \
+ (var); \
+ (var) = STAILQ_NEXT((var), field))
+
+#define STAILQ_INIT(head) do { \
+ STAILQ_FIRST((head)) = NULL; \
+ (head)->stqh_last = &STAILQ_FIRST((head)); \
+} while (0)
+
+#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
+ if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+ STAILQ_NEXT((tqelm), field) = (elm); \
+} while (0)
+
+#define STAILQ_INSERT_HEAD(head, elm, field) do { \
+ if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+ STAILQ_FIRST((head)) = (elm); \
+} while (0)
+
+#define STAILQ_INSERT_TAIL(head, elm, field) do { \
+ STAILQ_NEXT((elm), field) = NULL; \
+ *(head)->stqh_last = (elm); \
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+} while (0)
+
+#define STAILQ_LAST(head, type, field) \
+ (STAILQ_EMPTY((head)) ? \
+ NULL : \
+ ((struct type *) \
+ ((char *)((head)->stqh_last) - __offsetof(struct type, field))))
+
+#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
+
+#define STAILQ_REMOVE(head, elm, type, field) do { \
+ if (STAILQ_FIRST((head)) == (elm)) { \
+ STAILQ_REMOVE_HEAD((head), field); \
+ } \
+ else { \
+ struct type *curelm = STAILQ_FIRST((head)); \
+ while (STAILQ_NEXT(curelm, field) != (elm)) \
+ curelm = STAILQ_NEXT(curelm, field); \
+ if ((STAILQ_NEXT(curelm, field) = \
+ STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\
+ (head)->stqh_last = &STAILQ_NEXT((curelm), field);\
+ } \
+} while (0)
+
+#define STAILQ_REMOVE_HEAD(head, field) do { \
+ if ((STAILQ_FIRST((head)) = \
+ STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
+ (head)->stqh_last = &STAILQ_FIRST((head)); \
+} while (0)
+
+#define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \
+ if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL) \
+ (head)->stqh_last = &STAILQ_FIRST((head)); \
+} while (0)
+
+/*
+ * List declarations.
+ */
+#define LIST_HEAD(name, type) \
+struct name { \
+ struct type *lh_first; /* first element */ \
+}
+
+#define LIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define LIST_ENTRY(type) \
+struct { \
+ struct type *le_next; /* next element */ \
+ struct type **le_prev; /* address of previous next element */ \
+}
+
+/*
+ * List functions.
+ */
+
+#define LIST_EMPTY(head) ((head)->lh_first == NULL)
+
+#define LIST_FIRST(head) ((head)->lh_first)
+
+#define LIST_FOREACH(var, head, field) \
+ for ((var) = LIST_FIRST((head)); \
+ (var); \
+ (var) = LIST_NEXT((var), field))
+
+#define LIST_INIT(head) do { \
+ LIST_FIRST((head)) = NULL; \
+} while (0)
+
+#define LIST_INSERT_AFTER(listelm, elm, field) do { \
+ if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
+ LIST_NEXT((listelm), field)->field.le_prev = \
+ &LIST_NEXT((elm), field); \
+ LIST_NEXT((listelm), field) = (elm); \
+ (elm)->field.le_prev = &LIST_NEXT((listelm), field); \
+} while (0)
+
+#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.le_prev = (listelm)->field.le_prev; \
+ LIST_NEXT((elm), field) = (listelm); \
+ *(listelm)->field.le_prev = (elm); \
+ (listelm)->field.le_prev = &LIST_NEXT((elm), field); \
+} while (0)
+
+#define LIST_INSERT_HEAD(head, elm, field) do { \
+ if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
+ LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
+ LIST_FIRST((head)) = (elm); \
+ (elm)->field.le_prev = &LIST_FIRST((head)); \
+} while (0)
+
+#define LIST_NEXT(elm, field) ((elm)->field.le_next)
+
+#define LIST_REMOVE(elm, field) do { \
+ if (LIST_NEXT((elm), field) != NULL) \
+ LIST_NEXT((elm), field)->field.le_prev = \
+ (elm)->field.le_prev; \
+ *(elm)->field.le_prev = LIST_NEXT((elm), field); \
+} while (0)
+
+/*
+ * Tail queue declarations.
+ */
+#define TAILQ_HEAD(name, type) \
+struct name { \
+ struct type *tqh_first; /* first element */ \
+ struct type **tqh_last; /* addr of last next element */ \
+ TRACEBUF \
+}
+
+#define TAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).tqh_first }
+
+#define TAILQ_ENTRY(type) \
+struct { \
+ struct type *tqe_next; /* next element */ \
+ struct type **tqe_prev; /* address of previous next element */ \
+ TRACEBUF \
+}
+
+/*
+ * Tail queue functions.
+ */
+#define TAILQ_CONCAT(head1, head2, field) do { \
+ if (!TAILQ_EMPTY(head2)) { \
+ *(head1)->tqh_last = (head2)->tqh_first; \
+ (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
+ (head1)->tqh_last = (head2)->tqh_last; \
+ TAILQ_INIT((head2)); \
+ QMD_TRACE_HEAD(head); \
+ QMD_TRACE_HEAD(head2); \
+ } \
+} while (0)
+
+#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
+
+#define TAILQ_FIRST(head) ((head)->tqh_first)
+
+#define TAILQ_FOREACH(var, head, field) \
+ for ((var) = TAILQ_FIRST((head)); \
+ (var); \
+ (var) = TAILQ_NEXT((var), field))
+
+#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
+ for ((var) = TAILQ_LAST((head), headname); \
+ (var); \
+ (var) = TAILQ_PREV((var), headname, field))
+
+#define TAILQ_INIT(head) do { \
+ TAILQ_FIRST((head)) = NULL; \
+ (head)->tqh_last = &TAILQ_FIRST((head)); \
+ QMD_TRACE_HEAD(head); \
+} while (0)
+
+#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
+ TAILQ_NEXT((elm), field)->field.tqe_prev = \
+ &TAILQ_NEXT((elm), field); \
+ else { \
+ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
+ QMD_TRACE_HEAD(head); \
+ } \
+ TAILQ_NEXT((listelm), field) = (elm); \
+ (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
+ QMD_TRACE_ELEM(&(elm)->field); \
+ QMD_TRACE_ELEM(&listelm->field); \
+} while (0)
+
+#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
+ TAILQ_NEXT((elm), field) = (listelm); \
+ *(listelm)->field.tqe_prev = (elm); \
+ (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
+ QMD_TRACE_ELEM(&(elm)->field); \
+ QMD_TRACE_ELEM(&listelm->field); \
+} while (0)
+
+#define TAILQ_INSERT_HEAD(head, elm, field) do { \
+ if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
+ TAILQ_FIRST((head))->field.tqe_prev = \
+ &TAILQ_NEXT((elm), field); \
+ else \
+ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
+ TAILQ_FIRST((head)) = (elm); \
+ (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
+ QMD_TRACE_HEAD(head); \
+ QMD_TRACE_ELEM(&(elm)->field); \
+} while (0)
+
+#define TAILQ_INSERT_TAIL(head, elm, field) do { \
+ TAILQ_NEXT((elm), field) = NULL; \
+ (elm)->field.tqe_prev = (head)->tqh_last; \
+ *(head)->tqh_last = (elm); \
+ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
+ QMD_TRACE_HEAD(head); \
+ QMD_TRACE_ELEM(&(elm)->field); \
+} while (0)
+
+#define TAILQ_LAST(head, headname) \
+ (*(((struct headname *)((head)->tqh_last))->tqh_last))
+
+#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+
+#define TAILQ_PREV(elm, headname, field) \
+ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+
+#define TAILQ_REMOVE(head, elm, field) do { \
+ if ((TAILQ_NEXT((elm), field)) != NULL) \
+ TAILQ_NEXT((elm), field)->field.tqe_prev = \
+ (elm)->field.tqe_prev; \
+ else { \
+ (head)->tqh_last = (elm)->field.tqe_prev; \
+ QMD_TRACE_HEAD(head); \
+ } \
+ *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
+ TRASHIT((elm)->field.tqe_next); \
+ TRASHIT((elm)->field.tqe_prev); \
+ QMD_TRACE_ELEM(&(elm)->field); \
+} while (0)
+
+
+/*
+ * Circular queue definitions.
+ */
+#define CIRCLEQ_HEAD(name, type) \
+struct name { \
+ struct type *cqh_first; /* first element */ \
+ struct type *cqh_last; /* last element */ \
+}
+
+#define CIRCLEQ_ENTRY(type) \
+struct { \
+ struct type *cqe_next; /* next element */ \
+ struct type *cqe_prev; /* previous element */ \
+}
+
+/*
+ * Circular queue functions.
+ */
+#define CIRCLEQ_INIT(head) { \
+ (head)->cqh_first = (void *)(head); \
+ (head)->cqh_last = (void *)(head); \
+}
+
+#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) { \
+ (elm)->field.cqe_next = (listelm)->field.cqe_next; \
+ (elm)->field.cqe_prev = (listelm); \
+ if ((listelm)->field.cqe_next == (void *)(head)) \
+ (head)->cqh_last = (elm); \
+ else \
+ (listelm)->field.cqe_next->field.cqe_prev = (elm); \
+ (listelm)->field.cqe_next = (elm); \
+}
+
+#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) { \
+ (elm)->field.cqe_next = (listelm); \
+ (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
+ if ((listelm)->field.cqe_prev == (void *)(head)) \
+ (head)->cqh_first = (elm); \
+ else \
+ (listelm)->field.cqe_prev->field.cqe_next = (elm); \
+ (listelm)->field.cqe_prev = (elm); \
+}
+
+#define CIRCLEQ_INSERT_HEAD(head, elm, field) { \
+ (elm)->field.cqe_next = (head)->cqh_first; \
+ (elm)->field.cqe_prev = (void *)(head); \
+ if ((head)->cqh_last == (void *)(head)) \
+ (head)->cqh_last = (elm); \
+ else \
+ (head)->cqh_first->field.cqe_prev = (elm); \
+ (head)->cqh_first = (elm); \
+}
+
+#define CIRCLEQ_INSERT_TAIL(head, elm, field) { \
+ (elm)->field.cqe_next = (void *)(head); \
+ (elm)->field.cqe_prev = (head)->cqh_last; \
+ if ((head)->cqh_first == (void *)(head)) \
+ (head)->cqh_first = (elm); \
+ else \
+ (head)->cqh_last->field.cqe_next = (elm); \
+ (head)->cqh_last = (elm); \
+}
+
+#define CIRCLEQ_REMOVE(head, elm, field) { \
+ if ((elm)->field.cqe_next == (void *)(head)) \
+ (head)->cqh_last = (elm)->field.cqe_prev; \
+ else \
+ (elm)->field.cqe_next->field.cqe_prev = \
+ (elm)->field.cqe_prev; \
+ if ((elm)->field.cqe_prev == (void *)(head)) \
+ (head)->cqh_first = (elm)->field.cqe_next; \
+ else \
+ (elm)->field.cqe_prev->field.cqe_next = \
+ (elm)->field.cqe_next; \
+}
+
+#ifdef _KERNEL
+
+/*
+ * XXX insque() and remque() are an old way of handling certain queues.
+ * They bogusly assumes that all queue heads look alike.
+ */
+
+
+#ifdef __GNUC__
+
+struct quehead {
+#if defined(__arm__)
+ struct quehead *qh_link __attribute__((packed));
+ struct quehead *qh_rlink __attribute__((packed));
+#else /* !defined(__arm__)) */
+ struct quehead *qh_link;
+ struct quehead *qh_rlink;
+#endif
+};
+
+static __inline void
+insque(void *a, void *b)
+{
+ struct quehead *element = (struct quehead *)a,
+ *head = (struct quehead *)b;
+
+ element->qh_link = head->qh_link;
+ element->qh_rlink = head;
+ head->qh_link = element;
+ element->qh_link->qh_rlink = element;
+}
+
+static __inline void
+remque(void *a)
+{
+ struct quehead *element = (struct quehead *)a;
+
+ element->qh_link->qh_rlink = element->qh_rlink;
+ element->qh_rlink->qh_link = element->qh_link;
+ element->qh_rlink = 0;
+}
+
+#else /* !__GNUC__ */
+
+void insque(void *a, void *b);
+void remque(void *a);
+
+#endif /* __GNUC__ */
+
+#endif /* _KERNEL */
+
+#endif /* !_SYS_QUEUE_H_ */
diff --git a/cpukit/libnetworking/sys/reboot.h b/cpukit/libnetworking/sys/reboot.h
new file mode 100644
index 0000000000..48a7f0f782
--- /dev/null
+++ b/cpukit/libnetworking/sys/reboot.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 1982, 1986, 1988, 1993, 1994
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)reboot.h 8.3 (Berkeley) 12/13/94
+ * $Id$
+ */
+
+#ifndef _SYS_REBOOT_H_
+#define _SYS_REBOOT_H_
+
+/*
+ * Arguments to reboot system call. These are passed to
+ * the boot program and on to init.
+ */
+#define RB_AUTOBOOT 0 /* flags for system auto-booting itself */
+
+#define RB_ASKNAME 0x001 /* ask for file name to reboot from */
+#define RB_SINGLE 0x002 /* reboot to single user only */
+#define RB_NOSYNC 0x004 /* dont sync before reboot */
+#define RB_HALT 0x008 /* don't reboot, just halt */
+#define RB_INITNAME 0x010 /* name given for /etc/init (unused) */
+#define RB_DFLTROOT 0x020 /* use compiled-in rootdev */
+#define RB_KDB 0x040 /* give control to kernel debugger */
+#define RB_RDONLY 0x080 /* mount root fs read-only */
+#define RB_DUMP 0x100 /* dump kernel memory before reboot */
+#define RB_MINIROOT 0x200 /* mini-root present in memory at boot time */
+#define RB_CONFIG 0x400 /* invoke user configuration routing */
+#define RB_VERBOSE 0x800 /* print all potentially useful info */
+#define RB_SERIAL 0x1000 /* user serial port as console */
+#define RB_CDROM 0x2000 /* use cdrom as root */
+#define RB_POWEROFF 0x4000 /* if you can, turn the power off */
+#define RB_GDB 0x8000 /* use GDB remote debugger instead of DDB */
+#define RB_MUTE 0x10000 /* Come up with the console muted */
+#define RB_SELFTEST 0x20000 /* don't boot to normal operation, do selftest */
+
+#define RB_BOOTINFO 0x80000000 /* have `struct bootinfo *' arg */
+
+/*
+ * Constants for converting boot-style device number to type,
+ * adaptor (uba, mba, etc), unit number and partition number.
+ * Type (== major device number) is in the low byte
+ * for backward compatibility. Except for that of the "magic
+ * number", each mask applies to the shifted value.
+ * Format:
+ * (4) (4) (4) (4) (8) (8)
+ * --------------------------------
+ * |MA | AD| CT| UN| PART | TYPE |
+ * --------------------------------
+ */
+#define B_ADAPTORSHIFT 24
+#define B_ADAPTORMASK 0x0f
+#define B_ADAPTOR(val) (((val) >> B_ADAPTORSHIFT) & B_ADAPTORMASK)
+#define B_CONTROLLERSHIFT 20
+#define B_CONTROLLERMASK 0xf
+#define B_CONTROLLER(val) (((val)>>B_CONTROLLERSHIFT) & B_CONTROLLERMASK)
+#define B_SLICESHIFT 20
+#define B_SLICEMASK 0xff
+#define B_SLICE(val) (((val)>>B_SLICESHIFT) & B_SLICEMASK)
+#define B_UNITSHIFT 16
+#define B_UNITMASK 0xf
+#define B_UNIT(val) (((val) >> B_UNITSHIFT) & B_UNITMASK)
+#define B_PARTITIONSHIFT 8
+#define B_PARTITIONMASK 0xff
+#define B_PARTITION(val) (((val) >> B_PARTITIONSHIFT) & B_PARTITIONMASK)
+#define B_TYPESHIFT 0
+#define B_TYPEMASK 0xff
+#define B_TYPE(val) (((val) >> B_TYPESHIFT) & B_TYPEMASK)
+
+#define B_MAGICMASK 0xf0000000
+#define B_DEVMAGIC 0xa0000000
+
+#define MAKEBOOTDEV(type, adaptor, controller, unit, partition) \
+ (((type) << B_TYPESHIFT) | ((adaptor) << B_ADAPTORSHIFT) | \
+ ((controller) << B_CONTROLLERSHIFT) | ((unit) << B_UNITSHIFT) | \
+ ((partition) << B_PARTITIONSHIFT) | B_DEVMAGIC)
+
+#endif
diff --git a/cpukit/libnetworking/sys/resourcevar.h b/cpukit/libnetworking/sys/resourcevar.h
new file mode 100644
index 0000000000..2b4c47e48f
--- /dev/null
+++ b/cpukit/libnetworking/sys/resourcevar.h
@@ -0,0 +1,5 @@
+/*
+ * $Id$
+ */
+
+/* intentionally empty file */
diff --git a/cpukit/libnetworking/sys/rtprio.h b/cpukit/libnetworking/sys/rtprio.h
new file mode 100644
index 0000000000..843cf8cd1f
--- /dev/null
+++ b/cpukit/libnetworking/sys/rtprio.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 1994, Henrik Vestergaard Draboel
+ * 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 (name).
+ * 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 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.
+ *
+ * $Id$
+ */
+
+#ifndef _SYS_RTPRIO_H_
+#define _SYS_RTPRIO_H_
+
+/*
+ * Process realtime-priority specifications to rtprio.
+ */
+
+/* priority types */
+#define RTP_PRIO_REALTIME 0
+#define RTP_PRIO_NORMAL 1
+#define RTP_PRIO_IDLE 2
+
+/* priority range */
+#define RTP_PRIO_MIN 0 /* Highest priority */
+#define RTP_PRIO_MAX 31 /* Lowest priority */
+
+/*
+ * rtprio() syscall functions
+ */
+#define RTP_LOOKUP 0
+#define RTP_SET 1
+
+#ifndef LOCORE
+struct rtprio {
+ u_short type;
+ u_short prio;
+};
+#endif
+
+#ifndef _KERNEL
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+int rtprio __P((int, pid_t, struct rtprio *));
+__END_DECLS
+#endif /* !_KERNEL */
+#endif /* !_SYS_RTPRIO_H_ */
diff --git a/cpukit/libnetworking/sys/select.h b/cpukit/libnetworking/sys/select.h
new file mode 100644
index 0000000000..c03a1abe2c
--- /dev/null
+++ b/cpukit/libnetworking/sys/select.h
@@ -0,0 +1,75 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)select.h 8.2 (Berkeley) 1/4/94
+ * $Id$
+ */
+
+#ifndef _SYS_SELECT_H_
+#define _SYS_SELECT_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Used to maintain information about processes that wish to be
+ * notified when I/O becomes possible.
+ */
+struct selinfo {
+ pid_t si_pid; /* process to be notified */
+ short si_flags; /* see below */
+};
+#define SI_COLL 0x0001 /* collision occurred */
+
+#ifdef _KERNEL
+struct proc;
+
+void selrecord __P((struct proc *selector, struct selinfo *));
+void selwakeup __P((struct selinfo *));
+#endif
+
+/* Check the first NFDS descriptors each in READFDS (if not NULL) for read
+ readiness, in WRITEFDS (if not NULL) for write readiness, and in EXCEPTFDS
+ (if not NULL) for exceptional conditions. If TIMEOUT is not NULL, time out
+ after waiting the interval specified therein. Returns the number of ready
+ descriptors, or -1 for errors. */
+extern int select (int __nfds, fd_set *__readfds,
+ fd_set *__writefds,
+ fd_set *__exceptfds,
+ struct timeval *__timeout);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_SYS_SELECT_H_ */
diff --git a/cpukit/libnetworking/sys/signalvar.h b/cpukit/libnetworking/sys/signalvar.h
new file mode 100644
index 0000000000..151f2c6d8e
--- /dev/null
+++ b/cpukit/libnetworking/sys/signalvar.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)signalvar.h 8.6 (Berkeley) 2/19/95
+ * $Id$
+ */
+
+#ifndef _SYS_SIGNALVAR_H_ /* tmp for user.h */
+#define _SYS_SIGNALVAR_H_
+
+/*
+ * Kernel signal definitions and data structures,
+ * not exported to user programs.
+ */
+
+/*
+ * Process signal actions and state, needed only within the process
+ * (not necessarily resident).
+ */
+struct sigacts {
+ sig_t ps_sigact[NSIG]; /* disposition of signals */
+ sigset_t ps_catchmask[NSIG]; /* signals to be blocked */
+ sigset_t ps_sigonstack; /* signals to take on sigstack */
+ sigset_t ps_sigintr; /* signals that interrupt syscalls */
+ sigset_t ps_sigreset; /* signals that reset when caught */
+ sigset_t ps_signodefer; /* signals not masked while handled */
+ sigset_t ps_oldmask; /* saved mask from before sigpause */
+ int ps_flags; /* signal flags, below */
+ struct sigaltstack ps_sigstk; /* sp & on stack state variable */
+ int ps_sig; /* for core dump/debugger XXX */
+ u_long ps_code; /* for core dump/debugger XXX */
+ sigset_t ps_usertramp; /* SunOS compat; libc sigtramp XXX */
+};
+
+/* signal flags */
+#define SAS_OLDMASK 0x01 /* need to restore mask before pause */
+#define SAS_ALTSTACK 0x02 /* have alternate signal stack */
+
+/* additional signal action values, used only temporarily/internally */
+#define SIG_CATCH ((__sighandler_t *)2)
+#define SIG_HOLD ((__sighandler_t *)3)
+
+/*
+ * get signal action for process and signal; currently only for current process
+ */
+#define SIGACTION(p, sig) (p->p_sigacts->ps_sigact[(sig)])
+
+/*
+ * Determine signal that should be delivered to process p, the current
+ * process, 0 if none. If there is a pending stop signal with default
+ * action, the process stops in issignal().
+ */
+#define CURSIG(p) \
+ (((p)->p_siglist == 0 || \
+ (((p)->p_flag & P_TRACED) == 0 && \
+ ((p)->p_siglist & ~(p)->p_sigmask) == 0)) ? \
+ 0 : issignal(p))
+
+/*
+ * Clear a pending signal from a process.
+ */
+#define CLRSIG(p, sig) { (p)->p_siglist &= ~sigmask(sig); }
+
+/*
+ * Signal properties and actions.
+ * The array below categorizes the signals and their default actions
+ * according to the following properties:
+ */
+#define SA_KILL 0x01 /* terminates process by default */
+#define SA_CORE 0x02 /* ditto and coredumps */
+#define SA_STOP 0x04 /* suspend process */
+#define SA_TTYSTOP 0x08 /* ditto, from tty */
+#define SA_IGNORE 0x10 /* ignore by default */
+#define SA_CONT 0x20 /* continue if suspended */
+#define SA_CANTMASK 0x40 /* non-maskable, catchable */
+
+#ifdef SIGPROP
+static int sigprop[NSIG + 1] = {
+ 0, /* unused */
+ SA_KILL, /* SIGHUP */
+ SA_KILL, /* SIGINT */
+ SA_KILL|SA_CORE, /* SIGQUIT */
+ SA_KILL|SA_CORE, /* SIGILL */
+ SA_KILL|SA_CORE, /* SIGTRAP */
+ SA_KILL|SA_CORE, /* SIGABRT */
+ SA_KILL|SA_CORE, /* SIGEMT */
+ SA_KILL|SA_CORE, /* SIGFPE */
+ SA_KILL, /* SIGKILL */
+ SA_KILL|SA_CORE, /* SIGBUS */
+ SA_KILL|SA_CORE, /* SIGSEGV */
+ SA_KILL|SA_CORE, /* SIGSYS */
+ SA_KILL, /* SIGPIPE */
+ SA_KILL, /* SIGALRM */
+ SA_KILL, /* SIGTERM */
+ SA_IGNORE, /* SIGURG */
+ SA_STOP, /* SIGSTOP */
+ SA_STOP|SA_TTYSTOP, /* SIGTSTP */
+ SA_IGNORE|SA_CONT, /* SIGCONT */
+ SA_IGNORE, /* SIGCHLD */
+ SA_STOP|SA_TTYSTOP, /* SIGTTIN */
+ SA_STOP|SA_TTYSTOP, /* SIGTTOU */
+ SA_IGNORE, /* SIGIO */
+ SA_KILL, /* SIGXCPU */
+ SA_KILL, /* SIGXFSZ */
+ SA_KILL, /* SIGVTALRM */
+ SA_KILL, /* SIGPROF */
+ SA_IGNORE, /* SIGWINCH */
+ SA_IGNORE, /* SIGINFO */
+ SA_KILL, /* SIGUSR1 */
+ SA_KILL, /* SIGUSR2 */
+};
+
+#define contsigmask (sigmask(SIGCONT))
+#define stopsigmask (sigmask(SIGSTOP) | sigmask(SIGTSTP) | \
+ sigmask(SIGTTIN) | sigmask(SIGTTOU))
+
+#endif /* SIGPROP */
+
+#define sigcantmask (sigmask(SIGKILL) | sigmask(SIGSTOP))
+
+#ifdef _KERNEL
+/*
+ * Machine-independent functions:
+ */
+void execsigs __P((struct proc *p));
+void gsignal __P((int pgid, int sig));
+int issignal __P((struct proc *p));
+void killproc __P((struct proc *p, char *why));
+void pgsignal __P((struct pgrp *pgrp, int sig, int checkctty));
+void postsig __P((int sig));
+void psignal __P((struct proc *p, int sig));
+void setsigvec __P((struct proc *p, int signum, struct sigaction *sa));
+void sigexit __P((struct proc *p, int signum));
+void siginit __P((struct proc *p));
+void trapsignal __P((struct proc *p, int sig, u_long code));
+
+/*
+ * Machine-dependent functions:
+ */
+void sendsig __P((sig_t action, int sig, int returnmask, u_long code));
+#endif /* _KERNEL */
+#endif /* !_SYS_SIGNALVAR_H_ */
diff --git a/cpukit/libnetworking/sys/socket.h b/cpukit/libnetworking/sys/socket.h
new file mode 100644
index 0000000000..7899eaf79a
--- /dev/null
+++ b/cpukit/libnetworking/sys/socket.h
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 1982, 1985, 1986, 1988, 1993, 1994
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)socket.h 8.4 (Berkeley) 2/21/94
+ * $FreeBSD: src/sys/sys/socket.h,v 1.77 2004/03/14 00:49:09 mdodd Exp $
+ */
+
+#ifndef _SYS_SOCKET_H_
+#define _SYS_SOCKET_H_
+
+#include <sys/cdefs.h>
+
+#if defined(__rtems__)
+/* RTEMS doesn't have FreeBSD's sys/_types.h machinery. */
+typedef int socklen_t;
+typedef unsigned char sa_family_t;
+#endif
+
+/*
+ * Definitions related to sockets: types, address families, options.
+ */
+
+/*
+ * Types
+ */
+#define SOCK_STREAM 1 /* stream socket */
+#define SOCK_DGRAM 2 /* datagram socket */
+#define SOCK_RAW 3 /* raw-protocol interface */
+#define SOCK_RDM 4 /* reliably-delivered message */
+#define SOCK_SEQPACKET 5 /* sequenced packet stream */
+
+/*
+ * Option flags per-socket.
+ */
+#define SO_DEBUG 0x0001 /* turn on debugging info recording */
+#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */
+#define SO_REUSEADDR 0x0004 /* allow local address reuse */
+#define SO_KEEPALIVE 0x0008 /* keep connections alive */
+#define SO_DONTROUTE 0x0010 /* just use interface addresses */
+#define SO_BROADCAST 0x0020 /* permit sending of broadcast msgs */
+#define SO_USELOOPBACK 0x0040 /* bypass hardware when possible */
+#define SO_LINGER 0x0080 /* linger on close if data present */
+#define SO_OOBINLINE 0x0100 /* leave received OOB data in line */
+#define SO_REUSEPORT 0x0200 /* allow local address & port reuse */
+#define SO_TIMESTAMP 0x0400 /* timestamp received dgram traffic */
+
+/*
+ * Additional options, not kept in so_options.
+ */
+#define SO_SNDBUF 0x1001 /* send buffer size */
+#define SO_RCVBUF 0x1002 /* receive buffer size */
+#define SO_SNDLOWAT 0x1003 /* send low-water mark */
+#define SO_RCVLOWAT 0x1004 /* receive low-water mark */
+#define SO_SNDTIMEO 0x1005 /* send timeout */
+#define SO_RCVTIMEO 0x1006 /* receive timeout */
+#define SO_ERROR 0x1007 /* get error status and clear */
+#define SO_TYPE 0x1008 /* get socket type */
+#define SO_PRIVSTATE 0x1009 /* get/deny privileged state */
+
+/*
+ * RTEMS addition: get and set wakeup functions.
+ */
+#define SO_SNDWAKEUP 0x1020 /* wakeup when ready to send */
+#define SO_RCVWAKEUP 0x1021 /* wakeup when ready to receive */
+
+/*
+ * Structure used for manipulating linger option.
+ */
+struct linger {
+ int l_onoff; /* option on/off */
+ int l_linger; /* linger time */
+};
+
+/*
+ * RTEMS addition: structure used to get and set wakeup function.
+ */
+struct socket;
+struct sockwakeup {
+ void (*sw_pfn) __P((struct socket *, caddr_t));
+ caddr_t sw_arg;
+};
+
+/*
+ * Level number for (get/set)sockopt() to apply to socket itself.
+ */
+#define SOL_SOCKET 0xffff /* options for socket level */
+
+/*
+ * Address families.
+ */
+#define AF_UNSPEC 0 /* unspecified */
+#define AF_LOCAL 1 /* local to host (pipes, portals) */
+#define AF_UNIX AF_LOCAL /* backward compatibility */
+#define AF_INET 2 /* internetwork: UDP, TCP, etc. */
+#define AF_IMPLINK 3 /* arpanet imp addresses */
+#define AF_PUP 4 /* pup protocols: e.g. BSP */
+#define AF_CHAOS 5 /* mit CHAOS protocols */
+#define AF_NS 6 /* XEROX NS protocols */
+#define AF_ISO 7 /* ISO protocols */
+#define AF_OSI AF_ISO
+#define AF_ECMA 8 /* European computer manufacturers */
+#define AF_DATAKIT 9 /* datakit protocols */
+#define AF_CCITT 10 /* CCITT protocols, X.25 etc */
+#define AF_SNA 11 /* IBM SNA */
+#define AF_DECnet 12 /* DECnet */
+#define AF_DLI 13 /* DEC Direct data link interface */
+#define AF_LAT 14 /* LAT */
+#define AF_HYLINK 15 /* NSC Hyperchannel */
+#define AF_APPLETALK 16 /* Apple Talk */
+#define AF_ROUTE 17 /* Internal Routing Protocol */
+#define AF_LINK 18 /* Link layer interface */
+#define pseudo_AF_XTP 19 /* eXpress Transfer Protocol (no AF) */
+#define AF_COIP 20 /* connection-oriented IP, aka ST II */
+#define AF_CNT 21 /* Computer Network Technology */
+#define pseudo_AF_RTIP 22 /* Help Identify RTIP packets */
+#define AF_IPX 23 /* Novell Internet Protocol */
+#define AF_SIP 24 /* Simple Internet Protocol */
+#define pseudo_AF_PIP 25 /* Help Identify PIP packets */
+#define AF_ISDN 26 /* Integrated Services Digital Network*/
+#define AF_E164 AF_ISDN /* CCITT E.164 recommendation */
+#define pseudo_AF_KEY 27 /* Internal key-management function */
+#define AF_INET6 28 /* IPv6 */
+
+#define AF_MAX 29
+
+/*
+ * Structure used by kernel to store most
+ * addresses.
+ */
+struct sockaddr {
+ unsigned char sa_len; /* total length */
+ sa_family_t sa_family; /* address family */
+ char sa_data[14]; /* actually longer; address value */
+};
+
+/*
+ * Structure used by kernel to pass protocol
+ * information in raw sockets.
+ */
+struct sockproto {
+ unsigned short sp_family; /* address family */
+ unsigned short sp_protocol; /* protocol */
+};
+
+/*
+ * Protocol families, same as address families for now.
+ */
+#define PF_UNSPEC AF_UNSPEC
+#define PF_LOCAL AF_LOCAL
+#define PF_UNIX PF_LOCAL /* backward compatibility */
+#define PF_INET AF_INET
+#define PF_IMPLINK AF_IMPLINK
+#define PF_PUP AF_PUP
+#define PF_CHAOS AF_CHAOS
+#define PF_NS AF_NS
+#define PF_ISO AF_ISO
+#define PF_OSI AF_ISO
+#define PF_ECMA AF_ECMA
+#define PF_DATAKIT AF_DATAKIT
+#define PF_CCITT AF_CCITT
+#define PF_SNA AF_SNA
+#define PF_DECnet AF_DECnet
+#define PF_DLI AF_DLI
+#define PF_LAT AF_LAT
+#define PF_HYLINK AF_HYLINK
+#define PF_APPLETALK AF_APPLETALK
+#define PF_ROUTE AF_ROUTE
+#define PF_LINK AF_LINK
+#define PF_XTP pseudo_AF_XTP /* really just proto family, no AF */
+#define PF_COIP AF_COIP
+#define PF_CNT AF_CNT
+#define PF_SIP AF_SIP
+#define PF_IPX AF_IPX
+#define PF_RTIP pseudo_AF_RTIP /* same format as AF_INET */
+#define PF_PIP pseudo_AF_PIP
+#define PF_ISDN AF_ISDN
+#define PF_KEY pseudo_AF_KEY
+#define PF_INET6 AF_INET6
+
+#define PF_MAX AF_MAX
+
+/*
+ * Definitions for network related sysctl, CTL_NET.
+ *
+ * Second level is protocol family.
+ * Third level is protocol number.
+ *
+ * Further levels are defined by the individual families below.
+ */
+#define NET_MAXID AF_MAX
+
+#define CTL_NET_NAMES { \
+ { 0, 0 }, \
+ { "unix", CTLTYPE_NODE }, \
+ { "inet", CTLTYPE_NODE }, \
+ { "implink", CTLTYPE_NODE }, \
+ { "pup", CTLTYPE_NODE }, \
+ { "chaos", CTLTYPE_NODE }, \
+ { "xerox_ns", CTLTYPE_NODE }, \
+ { "iso", CTLTYPE_NODE }, \
+ { "emca", CTLTYPE_NODE }, \
+ { "datakit", CTLTYPE_NODE }, \
+ { "ccitt", CTLTYPE_NODE }, \
+ { "ibm_sna", CTLTYPE_NODE }, \
+ { "decnet", CTLTYPE_NODE }, \
+ { "dec_dli", CTLTYPE_NODE }, \
+ { "lat", CTLTYPE_NODE }, \
+ { "hylink", CTLTYPE_NODE }, \
+ { "appletalk", CTLTYPE_NODE }, \
+ { "route", CTLTYPE_NODE }, \
+ { "link_layer", CTLTYPE_NODE }, \
+ { "xtp", CTLTYPE_NODE }, \
+ { "coip", CTLTYPE_NODE }, \
+ { "cnt", CTLTYPE_NODE }, \
+ { "rtip", CTLTYPE_NODE }, \
+ { "ipx", CTLTYPE_NODE }, \
+ { "sip", CTLTYPE_NODE }, \
+ { "pip", CTLTYPE_NODE }, \
+ { "isdn", CTLTYPE_NODE }, \
+ { "key", CTLTYPE_NODE }, \
+}
+
+/*
+ * PF_ROUTE - Routing table
+ *
+ * Three additional levels are defined:
+ * Fourth: address family, 0 is wildcard
+ * Fifth: type of info, defined below
+ * Sixth: flag(s) to mask with for NET_RT_FLAGS
+ */
+#define NET_RT_DUMP 1 /* dump; may limit to a.f. */
+#define NET_RT_FLAGS 2 /* by flags, e.g. RESOLVING */
+#define NET_RT_IFLIST 3 /* survey interface list */
+#define NET_RT_MAXID 4
+
+#define CTL_NET_RT_NAMES { \
+ { 0, 0 }, \
+ { "dump", CTLTYPE_STRUCT }, \
+ { "flags", CTLTYPE_STRUCT }, \
+ { "iflist", CTLTYPE_STRUCT }, \
+}
+
+/*
+ * Maximum queue length specifiable by listen.
+ */
+#define SOMAXCONN 128
+
+/*
+ * Message header for recvmsg and sendmsg calls.
+ * Used value-result for recvmsg, value only for sendmsg.
+ */
+struct msghdr {
+ void *msg_name; /* optional address */
+ socklen_t msg_namelen; /* size of address */
+ struct iovec *msg_iov; /* scatter/gather array */
+ int msg_iovlen; /* # elements in msg_iov */
+ void *msg_control; /* ancillary data, see below */
+ socklen_t msg_controllen; /* ancillary data buffer len */
+ int msg_flags; /* flags on received message */
+};
+
+#define MSG_OOB 0x1 /* process out-of-band data */
+#define MSG_PEEK 0x2 /* peek at incoming message */
+#define MSG_DONTROUTE 0x4 /* send without using routing tables */
+#define MSG_EOR 0x8 /* data completes record */
+#define MSG_TRUNC 0x10 /* data discarded before delivery */
+#define MSG_CTRUNC 0x20 /* control data lost before delivery */
+#define MSG_WAITALL 0x40 /* wait for full request or error */
+#define MSG_DONTWAIT 0x80 /* this message should be nonblocking */
+#define MSG_EOF 0x100 /* data completes connection */
+#define MSG_COMPAT 0x8000 /* used in sendit() */
+
+/*
+ * Header for ancillary data objects in msg_control buffer.
+ * Used for additional information with/about a datagram
+ * not expressible by flags. The format is a sequence
+ * of message elements headed by cmsghdr structures.
+ */
+struct cmsghdr {
+ socklen_t cmsg_len; /* data byte count, including hdr */
+ int cmsg_level; /* originating protocol */
+ int cmsg_type; /* protocol-specific type */
+/* followed by u_char cmsg_data[]; */
+};
+
+/* given pointer to struct cmsghdr, return pointer to data */
+#define CMSG_DATA(cmsg) ((u_char *)((cmsg) + 1))
+
+/* given pointer to struct cmsghdr, return pointer to next cmsghdr */
+#define CMSG_NXTHDR(mhdr, cmsg) \
+ (((caddr_t)(cmsg) + (cmsg)->cmsg_len + sizeof(struct cmsghdr) > \
+ (mhdr)->msg_control + (mhdr)->msg_controllen) ? \
+ (struct cmsghdr *)NULL : \
+ (struct cmsghdr *)((caddr_t)(cmsg) + ALIGN((cmsg)->cmsg_len)))
+
+#define CMSG_FIRSTHDR(mhdr) ((struct cmsghdr *)(mhdr)->msg_control)
+
+/* "Socket"-level control message types: */
+#define SCM_RIGHTS 0x01 /* access rights (array of int) */
+#define SCM_TIMESTAMP 0x02 /* timestamp (struct timeval) */
+
+/*
+ * 4.3 compat sockaddr, move to compat file later
+ */
+struct osockaddr {
+ unsigned short sa_family; /* address family */
+ char sa_data[14]; /* up to 14 bytes of direct address */
+};
+
+/*
+ * 4.3-compat message header (move to compat file later).
+ */
+struct omsghdr {
+ char *msg_name; /* optional address */
+ int msg_namelen; /* size of address */
+ struct iovec *msg_iov; /* scatter/gather array */
+ int msg_iovlen; /* # elements in msg_iov */
+ char *msg_accrights; /* access rights sent/received */
+ int msg_accrightslen;
+};
+
+/*
+ * howto arguments for shutdown(2), specified by Posix.1g.
+ */
+#define SHUT_RD 0 /* shut down the reading side */
+#define SHUT_WR 1 /* shut down the writing side */
+#define SHUT_RDWR 2 /* shut down both sides */
+
+#ifndef _KERNEL
+
+__BEGIN_DECLS
+int accept(int, struct sockaddr * __restrict, socklen_t * __restrict);
+int bind(int, const struct sockaddr *, socklen_t);
+int connect(int, const struct sockaddr *, socklen_t);
+int getpeername(int, struct sockaddr * __restrict, socklen_t * __restrict);
+int getsockname(int, struct sockaddr * __restrict, socklen_t * __restrict);
+int getsockopt(int, int, int, void * __restrict, socklen_t * __restrict);
+int listen(int, int);
+ssize_t recv(int, void *, size_t, int);
+ssize_t recvfrom(int, void *, size_t, int, struct sockaddr * __restrict, socklen_t * __restrict);
+ssize_t recvmsg(int, struct msghdr *, int);
+ssize_t send(int, const void *, size_t, int);
+ssize_t sendto(int, const void *,
+ size_t, int, const struct sockaddr *, socklen_t);
+ssize_t sendmsg(int, const struct msghdr *, int);
+int setsockopt(int, int, int, const void *, socklen_t);
+int shutdown(int, int);
+int socket(int, int, int);
+int socketpair(int, int, int, int *);
+__END_DECLS
+
+#endif /* !_KERNEL */
+
+#endif /* !_SYS_SOCKET_H_ */
diff --git a/cpukit/libnetworking/sys/socketvar.h b/cpukit/libnetworking/sys/socketvar.h
new file mode 100644
index 0000000000..080fb0ab66
--- /dev/null
+++ b/cpukit/libnetworking/sys/socketvar.h
@@ -0,0 +1,283 @@
+/* $Id$ */
+
+/*-
+ * Copyright (c) 1982, 1986, 1990, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)socketvar.h 8.3 (Berkeley) 2/19/95
+ * $FreeBSD: src/sys/sys/socketvar.h,v 1.110 2004/03/01 03:14:23 rwatson Exp $
+ */
+
+#ifndef _SYS_SOCKETVAR_H_
+#define _SYS_SOCKETVAR_H_
+
+#include <sys/queue.h> /* for TAILQ macros */
+#include <sys/select.h> /* for struct selinfo */
+
+/*
+ * Kernel structure per socket.
+ * Contains send and receive buffer queues,
+ * handle on protocol and pointer to protocol
+ * private data and error information.
+ */
+struct socket {
+ short so_type; /* generic type, see socket.h */
+ short so_options; /* from socket call, see socket.h */
+ short so_linger; /* time to linger while closing */
+ short so_state; /* internal state flags SS_*, below */
+ void *so_pcb; /* protocol control block */
+ struct protosw *so_proto; /* protocol handle */
+/*
+ * Variables for connection queuing.
+ * Socket where accepts occur is so_head in all subsidiary sockets.
+ * If so_head is 0, socket is not related to an accept.
+ * For head socket so_q0 queues partially completed connections,
+ * while so_q is a queue of connections ready to be accepted.
+ * If a connection is aborted and it has so_head set, then
+ * it has to be pulled out of either so_q0 or so_q.
+ * We allow connections to queue up based on current queue lengths
+ * and limit on number of queued connections for this socket.
+ */
+ struct socket *so_head; /* back pointer to accept socket */
+ TAILQ_HEAD(, socket) so_incomp; /* queue of partial unaccepted connections */
+ TAILQ_HEAD(, socket) so_comp; /* queue of complete unaccepted connections */
+ TAILQ_ENTRY(socket) so_list; /* list of unaccepted connections */
+ short so_qlen; /* number of unaccepted connections */
+ short so_incqlen; /* number of unaccepted incomplete
+ connections */
+ short so_qlimit; /* max number queued connections */
+ short so_timeo; /* connection timeout */
+ u_short so_error; /* error affecting connection */
+ pid_t so_pgid; /* pgid for signals */
+ u_long so_oobmark; /* chars to oob mark */
+/*
+ * Variables for socket buffering.
+ */
+ struct sockbuf {
+ u_int sb_cc; /* actual chars in buffer */
+ u_int sb_hiwat; /* max actual char count */
+ u_int sb_mbcnt; /* chars of mbufs used */
+ u_int sb_mbmax; /* max chars of mbufs to use */
+ int sb_lowat; /* low water mark */
+ struct mbuf *sb_mb; /* the mbuf chain */
+ struct selinfo sb_sel; /* process selecting read/write */
+ short sb_flags; /* flags, see below */
+ int sb_timeo; /* timeout for read/write */
+ void (*sb_wakeup) __P((struct socket *, caddr_t));
+ caddr_t sb_wakeuparg; /* arg for above */
+ } so_rcv, so_snd;
+#define SB_MAX (256*1024) /* default for max chars in sockbuf */
+#define SB_LOCK 0x01 /* lock on data queue */
+#define SB_WANT 0x02 /* someone is waiting to lock */
+#define SB_WAIT 0x04 /* someone is waiting for data/space */
+#define SB_SEL 0x08 /* someone is selecting */
+#define SB_ASYNC 0x10 /* ASYNC I/O, need signals */
+#define SB_NOTIFY (SB_WAIT|SB_SEL|SB_ASYNC)
+#define SB_NOINTR 0x40 /* operations not interruptible */
+
+ caddr_t so_tpcb; /* Wisc. protocol control block XXX */
+ void (*so_upcall)(struct socket *, void *arg, int);
+ void *so_upcallarg; /* Arg for above */
+ uid_t so_uid; /* who opened the socket */
+};
+
+/*
+ * Socket state bits.
+ */
+#define SS_NOFDREF 0x0001 /* no file table ref any more */
+#define SS_ISCONNECTED 0x0002 /* socket connected to a peer */
+#define SS_ISCONNECTING 0x0004 /* in process of connecting to peer */
+#define SS_ISDISCONNECTING 0x0008 /* in process of disconnecting */
+#define SS_CANTSENDMORE 0x0010 /* can't send more data to peer */
+#define SS_CANTRCVMORE 0x0020 /* can't receive more data from peer */
+#define SS_RCVATMARK 0x0040 /* at mark on input */
+
+#define SS_PRIV 0x0080 /* privileged for broadcast, raw... */
+#define SS_NBIO 0x0100 /* non-blocking ops */
+#define SS_ASYNC 0x0200 /* async i/o notify */
+#define SS_ISCONFIRMING 0x0400 /* deciding to accept connection req */
+
+#define SS_INCOMP 0x0800 /* unaccepted, incomplete connection */
+#define SS_COMP 0x1000 /* unaccepted, complete connection */
+
+
+/*
+ * Macros for sockets and socket buffering.
+ */
+
+/*
+ * How much space is there in a socket buffer (so->so_snd or so->so_rcv)?
+ * This is problematical if the fields are unsigned, as the space might
+ * still be negative (cc > hiwat or mbcnt > mbmax). Should detect
+ * overflow and return 0. Should use "lmin" but it doesn't exist now.
+ */
+#define sbspace(sb) \
+ ((long) imin((int)((sb)->sb_hiwat - (sb)->sb_cc), \
+ (int)((sb)->sb_mbmax - (sb)->sb_mbcnt)))
+
+/* do we have to send all at once on a socket? */
+#define sosendallatonce(so) \
+ ((so)->so_proto->pr_flags & PR_ATOMIC)
+
+/* can we read something from so? */
+#define soreadable(so) \
+ ((so)->so_rcv.sb_cc >= (so)->so_rcv.sb_lowat || \
+ ((so)->so_state & SS_CANTRCVMORE) || \
+ (so)->so_comp.tqh_first || (so)->so_error)
+
+/* can we write something to so? */
+#define sowriteable(so) \
+ ((sbspace(&(so)->so_snd) >= (so)->so_snd.sb_lowat && \
+ (((so)->so_state&SS_ISCONNECTED) || \
+ ((so)->so_proto->pr_flags&PR_CONNREQUIRED)==0)) || \
+ ((so)->so_state & SS_CANTSENDMORE) || \
+ (so)->so_error)
+
+/* adjust counters in sb reflecting allocation of m */
+#define sballoc(sb, m) { \
+ (sb)->sb_cc += (m)->m_len; \
+ (sb)->sb_mbcnt += MSIZE; \
+ if ((m)->m_flags & M_EXT) \
+ (sb)->sb_mbcnt += (m)->m_ext.ext_size; \
+}
+
+/* adjust counters in sb reflecting freeing of m */
+#define sbfree(sb, m) { \
+ (sb)->sb_cc -= (m)->m_len; \
+ (sb)->sb_mbcnt -= MSIZE; \
+ if ((m)->m_flags & M_EXT) \
+ (sb)->sb_mbcnt -= (m)->m_ext.ext_size; \
+}
+
+/*
+ * Set lock on sockbuf sb; sleep if lock is already held.
+ * Unless SB_NOINTR is set on sockbuf, sleep is interruptible.
+ * Returns error without lock if sleep is interrupted.
+ */
+#define sblock(sb, wf) ((sb)->sb_flags & SB_LOCK ? \
+ (((wf) == M_WAITOK) ? sb_lock(sb) : EWOULDBLOCK) : \
+ ((sb)->sb_flags |= SB_LOCK), 0)
+
+/* release lock on sockbuf sb */
+#define sbunlock(sb) { \
+ (sb)->sb_flags &= ~SB_LOCK; \
+ if ((sb)->sb_flags & SB_WANT) { \
+ (sb)->sb_flags &= ~SB_WANT; \
+ wakeup((caddr_t)&(sb)->sb_flags); \
+ } \
+}
+
+#define sorwakeup(so) { sowakeup((so), &(so)->so_rcv); \
+ if ((so)->so_upcall) \
+ (*((so)->so_upcall))((so), (so)->so_upcallarg, M_DONTWAIT); \
+ }
+
+#define sowwakeup(so) sowakeup((so), &(so)->so_snd)
+
+#ifdef _KERNEL
+extern u_long sb_max;
+
+/* to catch callers missing new second argument to sonewconn: */
+#define sonewconn(head, connstatus) sonewconn1((head), (connstatus))
+
+struct filedesc;
+struct mbuf;
+struct sockaddr;
+struct stat;
+
+/*
+ * File operations on sockets.
+ */
+int soo_ioctl(struct file *fp, int cmd, caddr_t data,
+ struct proc *p);
+int soo_select(struct file *fp, int which, struct proc *p);
+int soo_stat(struct socket *so, struct stat *ub);
+
+/*
+ * From uipc_socket and friends
+ */
+int getsock(struct filedesc *fdp, int fdes, struct file **fpp);
+int sockargs(struct mbuf **mp, caddr_t buf, int buflen, int type);
+void sbappend(struct sockbuf *sb, struct mbuf *m);
+int sbappendaddr(struct sockbuf *sb, struct sockaddr *asa,
+ struct mbuf *m0, struct mbuf *control);
+int sbappendcontrol(struct sockbuf *sb, struct mbuf *m0,
+ struct mbuf *control);
+void sbappendrecord(struct sockbuf *sb, struct mbuf *m0);
+void sbcheck(struct sockbuf *sb);
+void sbcompress(struct sockbuf *sb, struct mbuf *m, struct mbuf *n);
+struct mbuf *
+ sbcreatecontrol(caddr_t p, int size, int type, int level);
+void sbdrop(struct sockbuf *sb, int len);
+void sbdroprecord(struct sockbuf *sb);
+void sbflush(struct sockbuf *sb);
+void sbinsertoob(struct sockbuf *sb, struct mbuf *m0);
+void sbrelease(struct sockbuf *sb);
+int sbreserve(struct sockbuf *sb, u_long cc);
+int sbwait(struct sockbuf *sb);
+int sb_lock(struct sockbuf *sb);
+int soabort(struct socket *so);
+int soaccept(struct socket *so, struct mbuf *nam);
+int sobind(struct socket *so, struct mbuf *nam);
+void socantrcvmore(struct socket *so);
+void socantsendmore(struct socket *so);
+int soclose(struct socket *so);
+int soconnect(struct socket *so, struct mbuf *nam);
+int soconnect2(struct socket *so1, struct socket *so2);
+int socreate(int dom, struct socket **aso, int type, int proto,
+ struct proc *p);
+int sodisconnect(struct socket *so);
+void sofree(struct socket *so);
+int sogetopt(struct socket *so, int level, int optname,
+ struct mbuf **mp);
+void sohasoutofband(struct socket *so);
+void soisconnected(struct socket *so);
+void soisconnecting(struct socket *so);
+void soisdisconnected(struct socket *so);
+void soisdisconnecting(struct socket *so);
+int solisten(struct socket *so, int backlog);
+struct socket *
+ sodropablereq(struct socket *head);
+struct socket *
+ sonewconn1(struct socket *head, int connstatus);
+int soreceive(struct socket *so, struct mbuf **paddr, struct uio *uio,
+ struct mbuf **mp0, struct mbuf **controlp, int *flagsp);
+int soreserve(struct socket *so, u_long sndcc, u_long rcvcc);
+void sorflush(struct socket *so);
+int sosend(struct socket *so, struct mbuf *addr, struct uio *uio,
+ struct mbuf *top, struct mbuf *control, int flags);
+int sosetopt(struct socket *so, int level, int optname,
+ struct mbuf *m0);
+int soshutdown(struct socket *so, int how);
+void sowakeup(struct socket *so, struct sockbuf *sb);
+#endif /* _KERNEL */
+
+#endif /* !_SYS_SOCKETVAR_H_ */
diff --git a/cpukit/libnetworking/sys/sysctl.h b/cpukit/libnetworking/sys/sysctl.h
new file mode 100644
index 0000000000..64d46ba434
--- /dev/null
+++ b/cpukit/libnetworking/sys/sysctl.h
@@ -0,0 +1,637 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Karels at Berkeley Software Design, Inc.
+ *
+ * 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)sysctl.h 8.1 (Berkeley) 6/2/93
+ * $FreeBSD: src/sys/sys/sysctl.h,v 1.128 2004/04/07 04:19:49 imp Exp $
+ */
+
+#ifndef _SYS_SYSCTL_H_
+#define _SYS_SYSCTL_H_
+
+#include <sys/queue.h>
+
+struct thread;
+/*
+ * Definitions for sysctl call. The sysctl call uses a hierarchical name
+ * for objects that can be examined or modified. The name is expressed as
+ * a sequence of integers. Like a file path name, the meaning of each
+ * component depends on its place in the hierarchy. The top-level and kern
+ * identifiers are defined here, and other identifiers are defined in the
+ * respective subsystem header files.
+ */
+
+#define CTL_MAXNAME 24 /* largest number of components supported */
+
+/*
+ * Each subsystem defined by sysctl defines a list of variables
+ * for that subsystem. Each name is either a node with further
+ * levels defined below it, or it is a leaf of some particular
+ * type given below. Each sysctl level defines a set of name/type
+ * pairs to be used by sysctl(8) in manipulating the subsystem.
+ */
+struct ctlname {
+ char *ctl_name; /* subsystem name */
+ int ctl_type; /* type of name */
+};
+
+#define CTLTYPE 0xf /* Mask for the type */
+#define CTLTYPE_NODE 1 /* name is a node */
+#define CTLTYPE_INT 2 /* name describes an integer */
+#define CTLTYPE_STRING 3 /* name describes a string */
+#define CTLTYPE_QUAD 4 /* name describes a 64-bit number */
+#define CTLTYPE_OPAQUE 5 /* name describes a structure */
+#define CTLTYPE_STRUCT CTLTYPE_OPAQUE /* name describes a structure */
+#define CTLTYPE_UINT 6 /* name describes an unsigned integer */
+#define CTLTYPE_LONG 7 /* name describes a long */
+#define CTLTYPE_ULONG 8 /* name describes an unsigned long */
+
+#define CTLFLAG_RD 0x80000000 /* Allow reads of variable */
+#define CTLFLAG_WR 0x40000000 /* Allow writes to the variable */
+#define CTLFLAG_RW (CTLFLAG_RD|CTLFLAG_WR)
+#define CTLFLAG_NOLOCK 0x20000000 /* XXX Don't Lock */
+#define CTLFLAG_ANYBODY 0x10000000 /* All users can set this var */
+#define CTLFLAG_SECURE 0x08000000 /* Permit set only if securelevel<=0 */
+#define CTLFLAG_PRISON 0x04000000 /* Prisoned roots can fiddle */
+#define CTLFLAG_DYN 0x02000000 /* Dynamic oid - can be freed */
+#define CTLFLAG_SKIP 0x01000000 /* Skip this sysctl when listing */
+#define CTLMASK_SECURE 0x00F00000 /* Secure level */
+#define CTLFLAG_TUN 0x00080000 /* Tunable variable */
+#define CTLFLAG_RDTUN (CTLFLAG_RD|CTLFLAG_TUN)
+
+/*
+ * Secure level. Note that CTLFLAG_SECURE == CTLFLAG_SECURE1.
+ *
+ * Secure when the securelevel is raised to at least N.
+ */
+#define CTLSHIFT_SECURE 20
+#define CTLFLAG_SECURE1 (CTLFLAG_SECURE | (0 << CTLSHIFT_SECURE))
+#define CTLFLAG_SECURE2 (CTLFLAG_SECURE | (1 << CTLSHIFT_SECURE))
+#define CTLFLAG_SECURE3 (CTLFLAG_SECURE | (2 << CTLSHIFT_SECURE))
+
+/*
+ * USE THIS instead of a hardwired number from the categories below
+ * to get dynamically assigned sysctl entries using the linker-set
+ * technology. This is the way nearly all new sysctl variables should
+ * be implemented.
+ * e.g. SYSCTL_INT(_parent, OID_AUTO, name, CTLFLAG_RW, &variable, 0, "");
+ */
+#define OID_AUTO (-1)
+
+/*
+ * The starting number for dynamically-assigned entries. WARNING!
+ * ALL static sysctl entries should have numbers LESS than this!
+ */
+#define CTL_AUTO_START 0x100
+
+#ifdef _KERNEL
+#define SYSCTL_HANDLER_ARGS struct sysctl_oid *oidp, void *arg1, int arg2, \
+ struct sysctl_req *req
+
+/* definitions for sysctl_req 'lock' member */
+#define REQ_UNLOCKED 0 /* not locked and not wired */
+#define REQ_LOCKED 1 /* locked and not wired */
+#define REQ_WIRED 2 /* locked and wired */
+
+/*
+ * This describes the access space for a sysctl request. This is needed
+ * so that we can use the interface from the kernel or from user-space.
+ */
+struct sysctl_req {
+ struct thread *td; /* used for access checking */
+ int lock; /* locking/wiring state */
+ void *oldptr;
+ size_t oldlen;
+ size_t oldidx;
+ int (*oldfunc)(struct sysctl_req *, const void *, size_t);
+ void *newptr;
+ size_t newlen;
+ size_t newidx;
+ int (*newfunc)(struct sysctl_req *, void *, size_t);
+ size_t validlen;
+};
+
+SLIST_HEAD(sysctl_oid_list, sysctl_oid);
+
+/*
+ * This describes one "oid" in the MIB tree. Potentially more nodes can
+ * be hidden behind it, expanded by the handler.
+ */
+struct sysctl_oid {
+ struct sysctl_oid_list *oid_parent;
+ SLIST_ENTRY(sysctl_oid) oid_link;
+ int oid_number;
+ u_int oid_kind;
+ void *oid_arg1;
+ int oid_arg2;
+ const char *oid_name;
+ int (*oid_handler)(SYSCTL_HANDLER_ARGS);
+ const char *oid_fmt;
+ int oid_refcnt;
+ const char *descr;
+};
+
+#define SYSCTL_IN(r, p, l) (r->newfunc)(r, p, l)
+#define SYSCTL_OUT(r, p, l) (r->oldfunc)(r, p, l)
+
+int sysctl_handle_int(SYSCTL_HANDLER_ARGS);
+int sysctl_handle_long(SYSCTL_HANDLER_ARGS);
+int sysctl_handle_intptr(SYSCTL_HANDLER_ARGS);
+int sysctl_handle_string(SYSCTL_HANDLER_ARGS);
+int sysctl_handle_opaque(SYSCTL_HANDLER_ARGS);
+
+/*
+ * These functions are used to add/remove an oid from the mib.
+ */
+void sysctl_register_oid(struct sysctl_oid *oidp);
+void sysctl_unregister_oid(struct sysctl_oid *oidp);
+
+/* Declare a static oid to allow child oids to be added to it. */
+#define SYSCTL_DECL(name) \
+ extern struct sysctl_oid_list sysctl_##name##_children
+
+/* Hide these in macros */
+#define SYSCTL_CHILDREN(oid_ptr) (struct sysctl_oid_list *) \
+ (oid_ptr)->oid_arg1
+#define SYSCTL_STATIC_CHILDREN(oid_name) \
+ (&sysctl_##oid_name##_children)
+
+/* === Structs and macros related to context handling === */
+
+/* All dynamically created sysctls can be tracked in a context list. */
+struct sysctl_ctx_entry {
+ struct sysctl_oid *entry;
+ TAILQ_ENTRY(sysctl_ctx_entry) link;
+};
+
+TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_entry);
+
+#define SYSCTL_NODE_CHILDREN(parent, name) \
+ sysctl_##parent##_##name##_children
+
+/* This constructs a "raw" MIB oid. */
+#define SYSCTL_OID(parent, nbr, name, kind, a1, a2, handler, fmt, descr) \
+ static struct sysctl_oid sysctl__##parent##_##name = { \
+ &sysctl_##parent##_children, { 0 }, \
+ nbr, kind, a1, a2, #name, handler, fmt, 0, descr }; \
+ DATA_SET(sysctl_set, sysctl__##parent##_##name)
+
+#define SYSCTL_ADD_OID(ctx, parent, nbr, name, kind, a1, a2, handler, fmt, descr) \
+ sysctl_add_oid(ctx, parent, nbr, name, kind, a1, a2, handler, fmt, descr)
+
+/* This constructs a node from which other oids can hang. */
+#define SYSCTL_NODE(parent, nbr, name, access, handler, descr) \
+ struct sysctl_oid_list SYSCTL_NODE_CHILDREN(parent, name); \
+ SYSCTL_OID(parent, nbr, name, CTLTYPE_NODE|(access), \
+ (void*)&SYSCTL_NODE_CHILDREN(parent, name), 0, handler, \
+ "N", descr)
+
+#define SYSCTL_ADD_NODE(ctx, parent, nbr, name, access, handler, descr) \
+ sysctl_add_oid(ctx, parent, nbr, name, CTLTYPE_NODE|(access), \
+ 0, 0, handler, "N", descr)
+
+/* Oid for a string. len can be 0 to indicate '\0' termination. */
+#define SYSCTL_STRING(parent, nbr, name, access, arg, len, descr) \
+ SYSCTL_OID(parent, nbr, name, CTLTYPE_STRING|(access), \
+ arg, len, sysctl_handle_string, "A", descr)
+
+#define SYSCTL_ADD_STRING(ctx, parent, nbr, name, access, arg, len, descr) \
+ sysctl_add_oid(ctx, parent, nbr, name, CTLTYPE_STRING|(access), \
+ arg, len, sysctl_handle_string, "A", descr)
+
+/* Oid for an int. If ptr is NULL, val is returned. */
+#define SYSCTL_INT(parent, nbr, name, access, ptr, val, descr) \
+ SYSCTL_OID(parent, nbr, name, CTLTYPE_INT|(access), \
+ ptr, val, sysctl_handle_int, "I", descr)
+
+#define SYSCTL_ADD_INT(ctx, parent, nbr, name, access, ptr, val, descr) \
+ sysctl_add_oid(ctx, parent, nbr, name, CTLTYPE_INT|(access), \
+ ptr, val, sysctl_handle_int, "I", descr)
+
+/* Oid for an unsigned int. If ptr is NULL, val is returned. */
+#define SYSCTL_UINT(parent, nbr, name, access, ptr, val, descr) \
+ SYSCTL_OID(parent, nbr, name, CTLTYPE_UINT|(access), \
+ ptr, val, sysctl_handle_int, "IU", descr)
+
+#define SYSCTL_ADD_UINT(ctx, parent, nbr, name, access, ptr, val, descr) \
+ sysctl_add_oid(ctx, parent, nbr, name, CTLTYPE_UINT|(access), \
+ ptr, val, sysctl_handle_int, "IU", descr)
+
+/* Oid for a long. The pointer must be non NULL. */
+#define SYSCTL_LONG(parent, nbr, name, access, ptr, val, descr) \
+ SYSCTL_OID(parent, nbr, name, CTLTYPE_LONG|(access), \
+ ptr, val, sysctl_handle_long, "L", descr)
+
+#define SYSCTL_ADD_LONG(ctx, parent, nbr, name, access, ptr, descr) \
+ sysctl_add_oid(ctx, parent, nbr, name, CTLTYPE_LONG|(access), \
+ ptr, 0, sysctl_handle_long, "L", descr)
+
+/* Oid for an unsigned long. The pointer must be non NULL. */
+#define SYSCTL_ULONG(parent, nbr, name, access, ptr, val, descr) \
+ SYSCTL_OID(parent, nbr, name, CTLTYPE_ULONG|(access), \
+ ptr, val, sysctl_handle_long, "LU", descr)
+
+#define SYSCTL_ADD_ULONG(ctx, parent, nbr, name, access, ptr, descr) \
+ sysctl_add_oid(ctx, parent, nbr, name, CTLTYPE_ULONG|(access), \
+ ptr, 0, sysctl_handle_long, "LU", descr)
+
+/* Oid for an opaque object. Specified by a pointer and a length. */
+#define SYSCTL_OPAQUE(parent, nbr, name, access, ptr, len, fmt, descr) \
+ SYSCTL_OID(parent, nbr, name, CTLTYPE_OPAQUE|(access), \
+ ptr, len, sysctl_handle_opaque, fmt, descr)
+
+#define SYSCTL_ADD_OPAQUE(ctx, parent, nbr, name, access, ptr, len, fmt, descr)\
+ sysctl_add_oid(ctx, parent, nbr, name, CTLTYPE_OPAQUE|(access), \
+ ptr, len, sysctl_handle_opaque, fmt, descr)
+
+/* Oid for a struct. Specified by a pointer and a type. */
+#define SYSCTL_STRUCT(parent, nbr, name, access, ptr, type, descr) \
+ SYSCTL_OID(parent, nbr, name, CTLTYPE_OPAQUE|(access), \
+ ptr, sizeof(struct type), sysctl_handle_opaque, \
+ "S," #type, descr)
+
+#define SYSCTL_ADD_STRUCT(ctx, parent, nbr, name, access, ptr, type, descr) \
+ sysctl_add_oid(ctx, parent, nbr, name, CTLTYPE_OPAQUE|(access), \
+ ptr, sizeof(struct type), sysctl_handle_opaque, "S," #type, descr)
+
+/* Oid for a procedure. Specified by a pointer and an arg. */
+#define SYSCTL_PROC(parent, nbr, name, access, ptr, arg, handler, fmt, descr) \
+ SYSCTL_OID(parent, nbr, name, (access), \
+ ptr, arg, handler, fmt, descr)
+
+#define SYSCTL_ADD_PROC(ctx, parent, nbr, name, access, ptr, arg, handler, fmt, descr) \
+ sysctl_add_oid(ctx, parent, nbr, name, (access), \
+ ptr, arg, handler, fmt, descr)
+
+#endif /* _KERNEL */
+
+/*
+ * Top-level identifiers
+ */
+#define CTL_UNSPEC 0 /* unused */
+#define CTL_KERN 1 /* "high kernel": proc, limits */
+#define CTL_VM 2 /* virtual memory */
+#define CTL_VFS 3 /* filesystem, mount type is next */
+#define CTL_NET 4 /* network, see socket.h */
+#define CTL_DEBUG 5 /* debugging parameters */
+#define CTL_HW 6 /* generic cpu/io */
+#define CTL_MACHDEP 7 /* machine dependent */
+#define CTL_USER 8 /* user-level */
+#define CTL_P1003_1B 9 /* POSIX 1003.1B */
+#define CTL_MAXID 10 /* number of valid top-level ids */
+
+#define CTL_NAMES { \
+ { 0, 0 }, \
+ { "kern", CTLTYPE_NODE }, \
+ { "vm", CTLTYPE_NODE }, \
+ { "vfs", CTLTYPE_NODE }, \
+ { "net", CTLTYPE_NODE }, \
+ { "debug", CTLTYPE_NODE }, \
+ { "hw", CTLTYPE_NODE }, \
+ { "machdep", CTLTYPE_NODE }, \
+ { "user", CTLTYPE_NODE }, \
+ { "p1003_1b", CTLTYPE_NODE }, \
+}
+
+/*
+ * CTL_KERN identifiers
+ */
+#define KERN_OSTYPE 1 /* string: system version */
+#define KERN_OSRELEASE 2 /* string: system release */
+#define KERN_OSREV 3 /* int: system revision */
+#define KERN_VERSION 4 /* string: compile time info */
+#define KERN_MAXVNODES 5 /* int: max vnodes */
+#define KERN_MAXPROC 6 /* int: max processes */
+#define KERN_MAXFILES 7 /* int: max open files */
+#define KERN_ARGMAX 8 /* int: max arguments to exec */
+#define KERN_SECURELVL 9 /* int: system security level */
+#define KERN_HOSTNAME 10 /* string: hostname */
+#define KERN_HOSTID 11 /* int: host identifier */
+#define KERN_CLOCKRATE 12 /* struct: struct clockrate */
+#define KERN_VNODE 13 /* struct: vnode structures */
+#define KERN_PROC 14 /* struct: process entries */
+#define KERN_FILE 15 /* struct: file entries */
+#define KERN_PROF 16 /* node: kernel profiling info */
+#define KERN_POSIX1 17 /* int: POSIX.1 version */
+#define KERN_NGROUPS 18 /* int: # of supplemental group ids */
+#define KERN_JOB_CONTROL 19 /* int: is job control available */
+#define KERN_SAVED_IDS 20 /* int: saved set-user/group-ID */
+#define KERN_BOOTTIME 21 /* struct: time kernel was booted */
+#define KERN_NISDOMAINNAME 22 /* string: YP domain name */
+#define KERN_UPDATEINTERVAL 23 /* int: update process sleep time */
+#define KERN_OSRELDATE 24 /* int: kernel release date */
+#define KERN_NTP_PLL 25 /* node: NTP PLL control */
+#define KERN_BOOTFILE 26 /* string: name of booted kernel */
+#define KERN_MAXFILESPERPROC 27 /* int: max open files per proc */
+#define KERN_MAXPROCPERUID 28 /* int: max processes per uid */
+#define KERN_DUMPDEV 29 /* dev_t: device to dump on */
+#define KERN_IPC 30 /* node: anything related to IPC */
+#define KERN_DUMMY 31 /* unused */
+#define KERN_PS_STRINGS 32 /* int: address of PS_STRINGS */
+#define KERN_USRSTACK 33 /* int: address of USRSTACK */
+#define KERN_LOGSIGEXIT 34 /* int: do we log sigexit procs? */
+#define KERN_IOV_MAX 35 /* int: value of UIO_MAXIOV */
+#define KERN_MAXID 36 /* number of valid kern ids */
+
+#define CTL_KERN_NAMES { \
+ { 0, 0 }, \
+ { "ostype", CTLTYPE_STRING }, \
+ { "osrelease", CTLTYPE_STRING }, \
+ { "osrevision", CTLTYPE_INT }, \
+ { "version", CTLTYPE_STRING }, \
+ { "maxvnodes", CTLTYPE_INT }, \
+ { "maxproc", CTLTYPE_INT }, \
+ { "maxfiles", CTLTYPE_INT }, \
+ { "argmax", CTLTYPE_INT }, \
+ { "securelevel", CTLTYPE_INT }, \
+ { "hostname", CTLTYPE_STRING }, \
+ { "hostid", CTLTYPE_UINT }, \
+ { "clockrate", CTLTYPE_STRUCT }, \
+ { "vnode", CTLTYPE_STRUCT }, \
+ { "proc", CTLTYPE_STRUCT }, \
+ { "file", CTLTYPE_STRUCT }, \
+ { "profiling", CTLTYPE_NODE }, \
+ { "posix1version", CTLTYPE_INT }, \
+ { "ngroups", CTLTYPE_INT }, \
+ { "job_control", CTLTYPE_INT }, \
+ { "saved_ids", CTLTYPE_INT }, \
+ { "boottime", CTLTYPE_STRUCT }, \
+ { "nisdomainname", CTLTYPE_STRING }, \
+ { "update", CTLTYPE_INT }, \
+ { "osreldate", CTLTYPE_INT }, \
+ { "ntp_pll", CTLTYPE_NODE }, \
+ { "bootfile", CTLTYPE_STRING }, \
+ { "maxfilesperproc", CTLTYPE_INT }, \
+ { "maxprocperuid", CTLTYPE_INT }, \
+ { "ipc", CTLTYPE_NODE }, \
+ { "dummy", CTLTYPE_INT }, \
+ { "ps_strings", CTLTYPE_INT }, \
+ { "usrstack", CTLTYPE_INT }, \
+ { "logsigexit", CTLTYPE_INT }, \
+ { "iov_max", CTLTYPE_INT }, \
+}
+
+/*
+ * CTL_VFS identifiers
+ */
+#define CTL_VFS_NAMES { \
+ { "vfsconf", CTLTYPE_STRUCT }, \
+}
+
+/*
+ * KERN_PROC subtypes
+ */
+#define KERN_PROC_ALL 0 /* everything */
+#define KERN_PROC_PID 1 /* by process id */
+#define KERN_PROC_PGRP 2 /* by process group id */
+#define KERN_PROC_SESSION 3 /* by session of pid */
+#define KERN_PROC_TTY 4 /* by controlling tty */
+#define KERN_PROC_UID 5 /* by effective uid */
+#define KERN_PROC_RUID 6 /* by real uid */
+#define KERN_PROC_ARGS 7 /* get/set arguments/proctitle */
+#define KERN_PROC_PROC 8 /* only return procs */
+#define KERN_PROC_SV_NAME 9 /* get syscall vector name */
+#define KERN_PROC_INC_THREAD 0x10 /*
+ * modifier for pid, pgrp, tty,
+ * uid, ruid, and proc
+ */
+
+/*
+ * KERN_IPC identifiers
+ */
+#define KIPC_MAXSOCKBUF 1 /* int: max size of a socket buffer */
+#define KIPC_SOCKBUF_WASTE 2 /* int: wastage factor in sockbuf */
+#define KIPC_SOMAXCONN 3 /* int: max length of connection q */
+#define KIPC_MAX_LINKHDR 4 /* int: max length of link header */
+#define KIPC_MAX_PROTOHDR 5 /* int: max length of network header */
+#define KIPC_MAX_HDR 6 /* int: max total length of headers */
+#define KIPC_MAX_DATALEN 7 /* int: max length of data? */
+
+/*
+ * CTL_HW identifiers
+ */
+#define HW_MACHINE 1 /* string: machine class */
+#define HW_MODEL 2 /* string: specific machine model */
+#define HW_NCPU 3 /* int: number of cpus */
+#define HW_BYTEORDER 4 /* int: machine byte order */
+#define HW_PHYSMEM 5 /* int: total memory */
+#define HW_USERMEM 6 /* int: non-kernel memory */
+#define HW_PAGESIZE 7 /* int: software page size */
+#define HW_DISKNAMES 8 /* strings: disk drive names */
+#define HW_DISKSTATS 9 /* struct: diskstats[] */
+#define HW_FLOATINGPT 10 /* int: has HW floating point? */
+#define HW_MACHINE_ARCH 11 /* string: machine architecture */
+#define HW_MAXID 12 /* number of valid hw ids */
+
+#define CTL_HW_NAMES { \
+ { 0, 0 }, \
+ { "machine", CTLTYPE_STRING }, \
+ { "model", CTLTYPE_STRING }, \
+ { "ncpu", CTLTYPE_INT }, \
+ { "byteorder", CTLTYPE_INT }, \
+ { "physmem", CTLTYPE_ULONG }, \
+ { "usermem", CTLTYPE_ULONG }, \
+ { "pagesize", CTLTYPE_INT }, \
+ { "disknames", CTLTYPE_STRUCT }, \
+ { "diskstats", CTLTYPE_STRUCT }, \
+ { "floatingpoint", CTLTYPE_INT }, \
+}
+
+/*
+ * CTL_USER definitions
+ */
+#define USER_CS_PATH 1 /* string: _CS_PATH */
+#define USER_BC_BASE_MAX 2 /* int: BC_BASE_MAX */
+#define USER_BC_DIM_MAX 3 /* int: BC_DIM_MAX */
+#define USER_BC_SCALE_MAX 4 /* int: BC_SCALE_MAX */
+#define USER_BC_STRING_MAX 5 /* int: BC_STRING_MAX */
+#define USER_COLL_WEIGHTS_MAX 6 /* int: COLL_WEIGHTS_MAX */
+#define USER_EXPR_NEST_MAX 7 /* int: EXPR_NEST_MAX */
+#define USER_LINE_MAX 8 /* int: LINE_MAX */
+#define USER_RE_DUP_MAX 9 /* int: RE_DUP_MAX */
+#define USER_POSIX2_VERSION 10 /* int: POSIX2_VERSION */
+#define USER_POSIX2_C_BIND 11 /* int: POSIX2_C_BIND */
+#define USER_POSIX2_C_DEV 12 /* int: POSIX2_C_DEV */
+#define USER_POSIX2_CHAR_TERM 13 /* int: POSIX2_CHAR_TERM */
+#define USER_POSIX2_FORT_DEV 14 /* int: POSIX2_FORT_DEV */
+#define USER_POSIX2_FORT_RUN 15 /* int: POSIX2_FORT_RUN */
+#define USER_POSIX2_LOCALEDEF 16 /* int: POSIX2_LOCALEDEF */
+#define USER_POSIX2_SW_DEV 17 /* int: POSIX2_SW_DEV */
+#define USER_POSIX2_UPE 18 /* int: POSIX2_UPE */
+#define USER_STREAM_MAX 19 /* int: POSIX2_STREAM_MAX */
+#define USER_TZNAME_MAX 20 /* int: POSIX2_TZNAME_MAX */
+#define USER_MAXID 21 /* number of valid user ids */
+
+#define CTL_USER_NAMES { \
+ { 0, 0 }, \
+ { "cs_path", CTLTYPE_STRING }, \
+ { "bc_base_max", CTLTYPE_INT }, \
+ { "bc_dim_max", CTLTYPE_INT }, \
+ { "bc_scale_max", CTLTYPE_INT }, \
+ { "bc_string_max", CTLTYPE_INT }, \
+ { "coll_weights_max", CTLTYPE_INT }, \
+ { "expr_nest_max", CTLTYPE_INT }, \
+ { "line_max", CTLTYPE_INT }, \
+ { "re_dup_max", CTLTYPE_INT }, \
+ { "posix2_version", CTLTYPE_INT }, \
+ { "posix2_c_bind", CTLTYPE_INT }, \
+ { "posix2_c_dev", CTLTYPE_INT }, \
+ { "posix2_char_term", CTLTYPE_INT }, \
+ { "posix2_fort_dev", CTLTYPE_INT }, \
+ { "posix2_fort_run", CTLTYPE_INT }, \
+ { "posix2_localedef", CTLTYPE_INT }, \
+ { "posix2_sw_dev", CTLTYPE_INT }, \
+ { "posix2_upe", CTLTYPE_INT }, \
+ { "stream_max", CTLTYPE_INT }, \
+ { "tzname_max", CTLTYPE_INT }, \
+}
+
+#define CTL_P1003_1B_ASYNCHRONOUS_IO 1 /* boolean */
+#define CTL_P1003_1B_MAPPED_FILES 2 /* boolean */
+#define CTL_P1003_1B_MEMLOCK 3 /* boolean */
+#define CTL_P1003_1B_MEMLOCK_RANGE 4 /* boolean */
+#define CTL_P1003_1B_MEMORY_PROTECTION 5 /* boolean */
+#define CTL_P1003_1B_MESSAGE_PASSING 6 /* boolean */
+#define CTL_P1003_1B_PRIORITIZED_IO 7 /* boolean */
+#define CTL_P1003_1B_PRIORITY_SCHEDULING 8 /* boolean */
+#define CTL_P1003_1B_REALTIME_SIGNALS 9 /* boolean */
+#define CTL_P1003_1B_SEMAPHORES 10 /* boolean */
+#define CTL_P1003_1B_FSYNC 11 /* boolean */
+#define CTL_P1003_1B_SHARED_MEMORY_OBJECTS 12 /* boolean */
+#define CTL_P1003_1B_SYNCHRONIZED_IO 13 /* boolean */
+#define CTL_P1003_1B_TIMERS 14 /* boolean */
+#define CTL_P1003_1B_AIO_LISTIO_MAX 15 /* int */
+#define CTL_P1003_1B_AIO_MAX 16 /* int */
+#define CTL_P1003_1B_AIO_PRIO_DELTA_MAX 17 /* int */
+#define CTL_P1003_1B_DELAYTIMER_MAX 18 /* int */
+#define CTL_P1003_1B_MQ_OPEN_MAX 19 /* int */
+#define CTL_P1003_1B_PAGESIZE 20 /* int */
+#define CTL_P1003_1B_RTSIG_MAX 21 /* int */
+#define CTL_P1003_1B_SEM_NSEMS_MAX 22 /* int */
+#define CTL_P1003_1B_SEM_VALUE_MAX 23 /* int */
+#define CTL_P1003_1B_SIGQUEUE_MAX 24 /* int */
+#define CTL_P1003_1B_TIMER_MAX 25 /* int */
+
+#define CTL_P1003_1B_MAXID 26
+
+#define CTL_P1003_1B_NAMES { \
+ { 0, 0 }, \
+ { "asynchronous_io", CTLTYPE_INT }, \
+ { "mapped_files", CTLTYPE_INT }, \
+ { "memlock", CTLTYPE_INT }, \
+ { "memlock_range", CTLTYPE_INT }, \
+ { "memory_protection", CTLTYPE_INT }, \
+ { "message_passing", CTLTYPE_INT }, \
+ { "prioritized_io", CTLTYPE_INT }, \
+ { "priority_scheduling", CTLTYPE_INT }, \
+ { "realtime_signals", CTLTYPE_INT }, \
+ { "semaphores", CTLTYPE_INT }, \
+ { "fsync", CTLTYPE_INT }, \
+ { "shared_memory_objects", CTLTYPE_INT }, \
+ { "synchronized_io", CTLTYPE_INT }, \
+ { "timers", CTLTYPE_INT }, \
+ { "aio_listio_max", CTLTYPE_INT }, \
+ { "aio_max", CTLTYPE_INT }, \
+ { "aio_prio_delta_max", CTLTYPE_INT }, \
+ { "delaytimer_max", CTLTYPE_INT }, \
+ { "mq_open_max", CTLTYPE_INT }, \
+ { "pagesize", CTLTYPE_INT }, \
+ { "rtsig_max", CTLTYPE_INT }, \
+ { "nsems_max", CTLTYPE_INT }, \
+ { "sem_value_max", CTLTYPE_INT }, \
+ { "sigqueue_max", CTLTYPE_INT }, \
+ { "timer_max", CTLTYPE_INT }, \
+}
+
+#ifdef _KERNEL
+
+/*
+ * Declare some common oids.
+ */
+extern struct sysctl_oid_list sysctl__children;
+SYSCTL_DECL(_kern);
+SYSCTL_DECL(_sysctl);
+SYSCTL_DECL(_vm);
+SYSCTL_DECL(_vfs);
+SYSCTL_DECL(_net);
+SYSCTL_DECL(_debug);
+SYSCTL_DECL(_debug_sizeof);
+SYSCTL_DECL(_hw);
+SYSCTL_DECL(_machdep);
+SYSCTL_DECL(_user);
+SYSCTL_DECL(_compat);
+
+extern char machine[];
+extern char osrelease[];
+extern char ostype[];
+extern char kern_ident[];
+
+/* Dynamic oid handling */
+struct sysctl_oid *sysctl_add_oid(struct sysctl_ctx_list *clist,
+ struct sysctl_oid_list *parent, int nbr, const char *name,
+ int kind, void *arg1, int arg2,
+ int (*handler) (SYSCTL_HANDLER_ARGS),
+ const char *fmt, const char *descr);
+int sysctl_move_oid(struct sysctl_oid *oidp,
+ struct sysctl_oid_list *parent);
+int sysctl_remove_oid(struct sysctl_oid *oidp, int del, int recurse);
+int sysctl_ctx_init(struct sysctl_ctx_list *clist);
+int sysctl_ctx_free(struct sysctl_ctx_list *clist);
+struct sysctl_ctx_entry *sysctl_ctx_entry_add(struct sysctl_ctx_list *clist,
+ struct sysctl_oid *oidp);
+struct sysctl_ctx_entry *sysctl_ctx_entry_find(struct sysctl_ctx_list *clist,
+ struct sysctl_oid *oidp);
+int sysctl_ctx_entry_del(struct sysctl_ctx_list *clist,
+ struct sysctl_oid *oidp);
+
+int kernel_sysctl(struct thread *td, int *name, u_int namelen, void *old,
+ size_t *oldlenp, void *new, size_t newlen,
+ size_t *retval);
+int kernel_sysctlbyname(struct thread *td, char *name,
+ void *old, size_t *oldlenp, void *new, size_t newlen,
+ size_t *retval);
+int userland_sysctl(struct thread *td, int *name, u_int namelen, void *old,
+ size_t *oldlenp, int inkernel, void *new, size_t newlen,
+ size_t *retval);
+int sysctl_find_oid(int *name, u_int namelen, struct sysctl_oid **noid,
+ int *nindx, struct sysctl_req *req);
+int sysctl_wire_old_buffer(struct sysctl_req *req, size_t len);
+
+#else /* !_KERNEL */
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+int sysctl(int *, u_int, void *, size_t *, void *, size_t);
+int sysctlbyname(const char *, void *, size_t *, void *, size_t);
+int sysctlnametomib(const char *, int *, size_t *);
+__END_DECLS
+#endif /* _KERNEL */
+
+#endif /* !_SYS_SYSCTL_H_ */
diff --git a/cpukit/libnetworking/sys/syslog.h b/cpukit/libnetworking/sys/syslog.h
new file mode 100644
index 0000000000..f8820f42b3
--- /dev/null
+++ b/cpukit/libnetworking/sys/syslog.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 1982, 1986, 1988, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)syslog.h 8.1 (Berkeley) 6/2/93
+ * $Id$
+ */
+
+#ifndef _SYS_SYSLOG_H_
+#define _SYS_SYSLOG_H_
+
+#define _PATH_LOG "/var/run/log"
+#define _PATH_OLDLOG "/dev/log" /* backward compatibility */
+
+/*
+ * priorities/facilities are encoded into a single 32-bit quantity, where the
+ * bottom 3 bits are the priority (0-7) and the top 28 bits are the facility
+ * (0-big number). Both the priorities and the facilities map roughly
+ * one-to-one to strings in the syslogd(8) source code. This mapping is
+ * included in this file.
+ *
+ * priorities (these are ordered)
+ */
+#define LOG_EMERG 0 /* system is unusable */
+#define LOG_ALERT 1 /* action must be taken immediately */
+#define LOG_CRIT 2 /* critical conditions */
+#define LOG_ERR 3 /* error conditions */
+#define LOG_WARNING 4 /* warning conditions */
+#define LOG_NOTICE 5 /* normal but significant condition */
+#define LOG_INFO 6 /* informational */
+#define LOG_DEBUG 7 /* debug-level messages */
+
+#define LOG_PRIMASK 0x07 /* mask to extract priority part (internal) */
+ /* extract priority */
+#define LOG_PRI(p) ((p) & LOG_PRIMASK)
+#define LOG_MAKEPRI(fac, pri) ((fac) | (pri))
+
+#ifdef SYSLOG_NAMES
+#define INTERNAL_NOPRI 0x10 /* the "no priority" priority */
+ /* mark "facility" */
+#define INTERNAL_MARK LOG_MAKEPRI((LOG_NFACILITIES<<3), 0)
+typedef struct _code {
+ char *c_name;
+ int c_val;
+} CODE;
+
+CODE prioritynames[] = {
+ { "alert", LOG_ALERT, },
+ { "crit", LOG_CRIT, },
+ { "debug", LOG_DEBUG, },
+ { "emerg", LOG_EMERG, },
+ { "err", LOG_ERR, },
+ { "error", LOG_ERR, }, /* DEPRECATED */
+ { "info", LOG_INFO, },
+ { "none", INTERNAL_NOPRI, }, /* INTERNAL */
+ { "notice", LOG_NOTICE, },
+ { "panic", LOG_EMERG, }, /* DEPRECATED */
+ { "warn", LOG_WARNING, }, /* DEPRECATED */
+ { "warning", LOG_WARNING, },
+ { NULL, -1, }
+};
+#endif
+
+/* facility codes */
+#define LOG_KERN (0<<3) /* kernel messages */
+#define LOG_USER (1<<3) /* random user-level messages */
+#define LOG_MAIL (2<<3) /* mail system */
+#define LOG_DAEMON (3<<3) /* system daemons */
+#define LOG_AUTH (4<<3) /* security/authorization messages */
+#define LOG_SYSLOG (5<<3) /* messages generated internally by syslogd */
+#define LOG_LPR (6<<3) /* line printer subsystem */
+#define LOG_NEWS (7<<3) /* network news subsystem */
+#define LOG_UUCP (8<<3) /* UUCP subsystem */
+#define LOG_CRON (9<<3) /* clock daemon */
+#define LOG_AUTHPRIV (10<<3) /* security/authorization messages (private) */
+ /* Facility #10 clashes in DEC UNIX, where */
+ /* it's defined as LOG_MEGASAFE for AdvFS */
+ /* event logging. */
+#define LOG_FTP (11<<3) /* ftp daemon */
+#define LOG_NTP (12<<3) /* NTP subsystem */
+
+ /* other codes through 15 reserved for system use */
+#define LOG_LOCAL0 (16<<3) /* reserved for local use */
+#define LOG_LOCAL1 (17<<3) /* reserved for local use */
+#define LOG_LOCAL2 (18<<3) /* reserved for local use */
+#define LOG_LOCAL3 (19<<3) /* reserved for local use */
+#define LOG_LOCAL4 (20<<3) /* reserved for local use */
+#define LOG_LOCAL5 (21<<3) /* reserved for local use */
+#define LOG_LOCAL6 (22<<3) /* reserved for local use */
+#define LOG_LOCAL7 (23<<3) /* reserved for local use */
+
+#define LOG_NFACILITIES 24 /* current number of facilities */
+#define LOG_FACMASK 0x03f8 /* mask to extract facility part */
+ /* facility of pri */
+#define LOG_FAC(p) (((p) & LOG_FACMASK) >> 3)
+
+#ifdef SYSLOG_NAMES
+CODE facilitynames[] = {
+ { "auth", LOG_AUTH, },
+ { "authpriv", LOG_AUTHPRIV, },
+ { "cron", LOG_CRON, },
+ { "daemon", LOG_DAEMON, },
+ { "ftp", LOG_FTP, },
+ { "kern", LOG_KERN, },
+ { "lpr", LOG_LPR, },
+ { "mail", LOG_MAIL, },
+ { "mark", INTERNAL_MARK, }, /* INTERNAL */
+ { "news", LOG_NEWS, },
+ { "ntp", LOG_NTP, },
+ { "security", LOG_AUTH, }, /* DEPRECATED */
+ { "syslog", LOG_SYSLOG, },
+ { "user", LOG_USER, },
+ { "uucp", LOG_UUCP, },
+ { "local0", LOG_LOCAL0, },
+ { "local1", LOG_LOCAL1, },
+ { "local2", LOG_LOCAL2, },
+ { "local3", LOG_LOCAL3, },
+ { "local4", LOG_LOCAL4, },
+ { "local5", LOG_LOCAL5, },
+ { "local6", LOG_LOCAL6, },
+ { "local7", LOG_LOCAL7, },
+ { NULL, -1, }
+};
+#endif
+
+#ifdef _KERNEL
+#define LOG_PRINTF -1 /* pseudo-priority to indicate use of printf */
+#endif
+
+/*
+ * arguments to setlogmask.
+ */
+#define LOG_MASK(pri) (1 << (pri)) /* mask for one priority */
+#define LOG_UPTO(pri) ((1 << ((pri)+1)) - 1) /* all priorities through pri */
+
+/*
+ * Option flags for openlog.
+ *
+ * LOG_ODELAY no longer does anything.
+ * LOG_NDELAY is the inverse of what it used to be.
+ */
+#define LOG_PID 0x01 /* log the pid with each message */
+#define LOG_CONS 0x02 /* log on the console if errors in sending */
+#define LOG_ODELAY 0x04 /* delay open until first syslog() (default) */
+#define LOG_NDELAY 0x08 /* don't delay open */
+#define LOG_NOWAIT 0x10 /* don't wait for console forks: DEPRECATED */
+#define LOG_PERROR 0x20 /* log to stderr as well */
+
+/*
+#ifdef _KERNEL
+
+#else not _KERNEL */
+
+#include <sys/cdefs.h>
+#include <stdarg.h>
+
+__BEGIN_DECLS
+void closelog __P((void));
+void openlog __P((const char *, int, int));
+int setlogmask __P((int));
+void syslog __P((int, const char *, ...));
+void vsyslog __P((int, const char *, va_list));
+__END_DECLS
+
+/* #endif !_KERNEL */
+
+#endif
diff --git a/cpukit/libnetworking/sys/systm.h b/cpukit/libnetworking/sys/systm.h
new file mode 100644
index 0000000000..3363140dbe
--- /dev/null
+++ b/cpukit/libnetworking/sys/systm.h
@@ -0,0 +1,199 @@
+/*-
+ * Copyright (c) 1982, 1988, 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)systm.h 8.7 (Berkeley) 3/29/95
+ * $Id$
+ */
+
+#ifndef _SYS_SYSTM_H_
+#define _SYS_SYSTM_H_
+
+#include <rtems/rtems_bsdnet_internal.h> /* for __BSD_VA_LIST__ */
+#include <machine/cpufunc.h>
+
+extern int securelevel; /* system security level (see init(8)) */
+
+extern int cold; /* nonzero if we are doing a cold boot */
+extern const char *panicstr; /* panic message */
+extern char version[]; /* system version */
+extern char copyright[]; /* system copyright */
+
+extern int nblkdev; /* number of entries in bdevsw */
+extern int nchrdev; /* number of entries in cdevsw */
+extern struct swdevt *swdevt; /* swap-device information */
+extern int nswdev; /* number of swap devices */
+extern int nswap; /* size of swap space */
+
+extern int selwait; /* select timeout address */
+
+extern u_char curpriority; /* priority of current process */
+
+extern int physmem; /* physical memory */
+
+extern dev_t dumpdev; /* dump device */
+extern long dumplo; /* offset into dumpdev */
+
+extern dev_t rootdev; /* root device */
+extern struct vnode *rootvp; /* vnode equivalent to above */
+
+extern dev_t swapdev; /* swapping device */
+extern struct vnode *swapdev_vp;/* vnode equivalent to above */
+
+extern int boothowto; /* reboot flags, from console subsystem */
+extern int bootverbose; /* nonzero to print verbose messages */
+
+/*
+ * General function declarations.
+ */
+void Debugger __P((const char *msg));
+int nullop __P((void));
+int eopnotsupp __P((void));
+int einval __P((void));
+int seltrue __P((dev_t dev, int which, struct proc *p));
+int ureadc __P((int, struct uio *));
+void *hashinit __P((int count, int type, u_long *hashmask));
+void *phashinit __P((int count, int type, u_long *nentries));
+
+void panic __P((const char *, ...)) __dead2;
+void boot __P((int)) __dead2;
+void cpu_boot __P((int));
+void tablefull __P((const char *));
+int addlog __P((const char *, ...));
+int kvprintf __P((char const *, void (*)(int, void*), void *, int,
+ _BSD_VA_LIST_));
+void log __P((int, const char *, ...));
+int printf __P((const char *, ...));
+int sprintf __P((char *buf, const char *, ...));
+void uprintf __P((const char *, ...));
+void ttyprintf __P((struct tty *, const char *, ...));
+
+#define bcopy(f,t,n) memcpy((t),(f),(n))
+#define bzero(p,n) memset((p),(0),(n))
+
+int copystr __P((const void *kfaddr, void *kdaddr, size_t len,
+ size_t *lencopied));
+int copyinstr __P((const void *udaddr, void *kaddr, size_t len,
+ size_t *lencopied));
+int copyin __P((const void *udaddr, void *kaddr, size_t len));
+int copyout __P((const void *kaddr, void *udaddr, size_t len));
+
+int fubyte __P((const void *base));
+int fuibyte __P((const void *base));
+int subyte __P((void *base, int byte));
+int suibyte __P((void *base, int byte));
+int fuword __P((const void *base));
+int suword __P((void *base, int word));
+int susword __P((void *base, int word));
+
+int hzto __P((struct timeval *tv));
+void realitexpire __P((void *));
+
+struct clockframe;
+void hardclock __P((struct clockframe *frame));
+void softclock __P((void));
+void statclock __P((struct clockframe *frame));
+
+void startprofclock __P((struct proc *));
+void stopprofclock __P((struct proc *));
+void setstatclockrate __P((int hzrate));
+
+void hardupdate __P((long));
+void hardpps __P((struct timeval *tvp, long usec));
+
+#include <sys/libkern.h>
+
+/* Initialize the world */
+extern void consinit(void);
+extern void usrinfoinit(void);
+extern void cpu_initclocks(void);
+extern void vntblinit(void);
+extern void nchinit(void);
+
+/* Finalize the world. */
+void shutdown_nice __P((void));
+
+/*
+ * Kernel to clock driver interface.
+ */
+void inittodr __P((time_t base));
+void resettodr __P((void));
+void startrtclock __P((void));
+
+/* Timeouts */
+typedef void (timeout_t)(void *); /* actual timeout function type */
+typedef timeout_t *timeout_func_t; /* a pointer to this type */
+
+void timeout(timeout_func_t, void *, int);
+void untimeout(timeout_func_t, void *);
+void logwakeup __P((void));
+
+/* Various other callout lists that modules might want to know about */
+/* shutdown callout list definitions */
+typedef void (*bootlist_fn)(int,void *);
+int at_shutdown(bootlist_fn function, void *arg, int);
+int rm_at_shutdown(bootlist_fn function, void *arg);
+#define SHUTDOWN_PRE_SYNC 0
+#define SHUTDOWN_POST_SYNC 1
+
+/* forking */ /* XXX not yet */
+typedef void (*forklist_fn)(struct proc *parent,struct proc *child,int flags);
+int at_fork(forklist_fn function);
+int rm_at_fork(forklist_fn function);
+
+/* exiting */
+typedef void (*exitlist_fn)(struct proc *procp);
+int at_exit(exitlist_fn function);
+int rm_at_exit(exitlist_fn function);
+
+/* Not exactly a callout LIST, but a callout entry.. */
+/* Allow an external module to define a hardware watchdog tickler */
+/* Normally a process would do this, but there are times when the */
+/* kernel needs to be able to hold off the watchdog, when the process */
+/* is not active, e.g. when dumping core. Costs us a whole 4 bytes to */
+/* make this generic. the variable is in kern_shutdown.c */
+typedef void (*watchdog_tickle_fn)(void);
+extern watchdog_tickle_fn wdog_tickler;
+
+
+/*
+ * Common `proc' functions are declared here so that proc.h can be included
+ * less often.
+ */
+int tsleep __P((void *chan, int pri, char *wmesg, int timo));
+void wakeup __P((void *chan));
+
+#endif /* !_SYS_SYSTM_H_ */
diff --git a/cpukit/libnetworking/sys/ttydefaults.h b/cpukit/libnetworking/sys/ttydefaults.h
new file mode 100644
index 0000000000..68f0ddbe77
--- /dev/null
+++ b/cpukit/libnetworking/sys/ttydefaults.h
@@ -0,0 +1,97 @@
+/*-
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)ttydefaults.h 8.4 (Berkeley) 1/21/94
+ * $Id$
+ */
+
+/*
+ * System wide defaults for terminal state.
+ */
+#ifndef _SYS_TTYDEFAULTS_H_
+#define _SYS_TTYDEFAULTS_H_
+
+/*
+ * Defaults on "first" open.
+ */
+#define TTYDEF_IFLAG (BRKINT | ICRNL | IMAXBEL | IXON | IXANY)
+#define TTYDEF_OFLAG (OPOST | ONLCR)
+#define TTYDEF_LFLAG (ECHO | ICANON | ISIG | IEXTEN | ECHOE|ECHOKE|ECHOCTL)
+#define TTYDEF_CFLAG (CREAD | CS8 | HUPCL)
+#define TTYDEF_SPEED (B9600)
+
+/*
+ * Control Character Defaults
+ */
+#define CTRL(x) (x&037)
+#define CEOF CTRL('d')
+#define CEOL 0xff /* XXX avoid _POSIX_VDISABLE */
+#define CERASE 0177
+#define CINTR CTRL('c')
+#define CSTATUS CTRL('t')
+#define CKILL CTRL('u')
+#define CMIN 1
+#define CQUIT 034 /* FS, ^\ */
+#define CSUSP CTRL('z')
+#define CTIME 0
+#define CDSUSP CTRL('y')
+#define CSTART CTRL('q')
+#define CSTOP CTRL('s')
+#define CLNEXT CTRL('v')
+#define CDISCARD CTRL('o')
+#define CWERASE CTRL('w')
+#define CREPRINT CTRL('r')
+#define CEOT CEOF
+/* compat */
+#define CBRK CEOL
+#define CRPRNT CREPRINT
+#define CFLUSH CDISCARD
+
+/* PROTECTED INCLUSION ENDS HERE */
+#endif /* !_SYS_TTYDEFAULTS_H_ */
+
+/*
+ * #define TTYDEFCHARS to include an array of default control characters.
+ */
+#ifdef TTYDEFCHARS
+static cc_t ttydefchars[NCCS] = {
+ CEOF, CEOL, CEOL, CERASE, CWERASE, CKILL, CREPRINT,
+ _POSIX_VDISABLE, CINTR, CQUIT, CSUSP, CDSUSP, CSTART, CSTOP, CLNEXT,
+ CDISCARD, CMIN, CTIME, CSTATUS, _POSIX_VDISABLE
+};
+#undef TTYDEFCHARS
+#endif
diff --git a/cpukit/libnetworking/sys/ucred.h b/cpukit/libnetworking/sys/ucred.h
new file mode 100644
index 0000000000..5da8b344d0
--- /dev/null
+++ b/cpukit/libnetworking/sys/ucred.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)ucred.h 8.4 (Berkeley) 1/9/95
+ * $Id$
+ */
+
+#ifndef _SYS_UCRED_H_
+#define _SYS_UCRED_H_
+
+/*
+ * Credentials.
+ */
+struct ucred {
+ u_short cr_ref; /* reference count */
+ uid_t cr_uid; /* effective user id */
+ short cr_ngroups; /* number of groups */
+ gid_t cr_groups[NGROUPS]; /* groups */
+};
+#define cr_gid cr_groups[0]
+#define NOCRED ((struct ucred *)0) /* no credential available */
+#define FSCRED ((struct ucred *)-1) /* filesystem credential */
+
+#ifdef _KERNEL
+#define crhold(cr) (cr)->cr_ref++
+
+struct ucred *crcopy __P((struct ucred *cr));
+struct ucred *crdup __P((struct ucred *cr));
+void crfree __P((struct ucred *cr));
+struct ucred *crget __P((void));
+int suser __P((struct ucred *cred, u_short *acflag));
+int groupmember __P((gid_t gid, struct ucred *cred));
+#endif /* _KERNEL */
+
+#endif /* !_SYS_UCRED_H_ */
diff --git a/cpukit/libnetworking/sys/uio.h b/cpukit/libnetworking/sys/uio.h
new file mode 100644
index 0000000000..693bde1d82
--- /dev/null
+++ b/cpukit/libnetworking/sys/uio.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 1982, 1986, 1993, 1994
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)uio.h 8.5 (Berkeley) 2/22/94
+ * $Id$
+ */
+
+#ifndef _SYS_UIO_H_
+#define _SYS_UIO_H_
+
+/*
+ * XXX
+ * iov_base should be a void *.
+ */
+struct iovec {
+ char *iov_base; /* Base address. */
+ size_t iov_len; /* Length. */
+};
+
+enum uio_rw { UIO_READ, UIO_WRITE };
+
+/* Segment flag values. */
+enum uio_seg {
+ UIO_USERSPACE, /* from user data space */
+ UIO_SYSSPACE, /* from system space */
+ UIO_USERISPACE, /* from user I space */
+ UIO_NOCOPY /* don't copy, already in object */
+};
+
+#ifdef _KERNEL
+struct uio {
+ struct iovec *uio_iov;
+ int uio_iovcnt;
+ off_t uio_offset;
+ int uio_resid;
+ enum uio_seg uio_segflg;
+ enum uio_rw uio_rw;
+ struct proc *uio_procp;
+};
+
+/*
+ * Limits
+ */
+#define UIO_MAXIOV 1024 /* max 1K of iov's */
+#define UIO_SMALLIOV 8 /* 8 on stack, else malloc */
+#endif /* _KERNEL */
+
+#ifdef _KERNEL
+
+int uiomove __P((caddr_t, int, struct uio *));
+
+#else /* !_KERNEL */
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+ssize_t readv __P((int, const struct iovec *, int));
+ssize_t writev __P((int, const struct iovec *, int));
+__END_DECLS
+
+#endif /* _KERNEL */
+
+#endif /* !_SYS_UIO_H_ */
diff --git a/cpukit/libnetworking/sys/un.h b/cpukit/libnetworking/sys/un.h
new file mode 100644
index 0000000000..d742bb7d5d
--- /dev/null
+++ b/cpukit/libnetworking/sys/un.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)un.h 8.3 (Berkeley) 2/19/95
+ * $FreeBSD: src/sys/sys/un.h,v 1.17 1999/12/29 04:24:49 peter Exp $
+ */
+
+#ifndef _SYS_UN_H_
+#define _SYS_UN_H_
+
+/*
+ * Definitions for UNIX IPC domain.
+ */
+struct sockaddr_un {
+ u_char sun_len; /* sockaddr len including null */
+ u_char sun_family; /* AF_UNIX */
+ char sun_path[104]; /* path name (gag) */
+};
+
+#ifdef _KERNEL
+struct mbuf;
+struct socket;
+
+int uipc_usrreq __P((struct socket *so, int req, struct mbuf *m,
+ struct mbuf *nam, struct mbuf *control));
+int unp_connect2 __P((struct socket *so, struct socket *so2));
+void unp_dispose __P((struct mbuf *m));
+int unp_externalize __P((struct mbuf *rights));
+void unp_init __P((void));
+extern struct pr_usrreqs uipc_usrreqs;
+#else /* !_KERNEL */
+
+/* actual length of an initialized sockaddr_un */
+#define SUN_LEN(su) \
+ (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
+
+#endif /* _KERNEL */
+
+#endif /* !_SYS_UN_H_ */
diff --git a/cpukit/libnetworking/syslog.h b/cpukit/libnetworking/syslog.h
new file mode 100644
index 0000000000..6d223d00b7
--- /dev/null
+++ b/cpukit/libnetworking/syslog.h
@@ -0,0 +1,5 @@
+/*
+ * $Id$
+ */
+
+#include <sys/syslog.h>
diff --git a/cpukit/libnetworking/vm/vm.h b/cpukit/libnetworking/vm/vm.h
new file mode 100644
index 0000000000..7debe74a82
--- /dev/null
+++ b/cpukit/libnetworking/vm/vm.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)vm.h 8.2 (Berkeley) 12/13/93
+ * $Id$
+ */
+
+#ifndef VM_H
+#define VM_H
+
+typedef char vm_inherit_t; /* XXX: inheritance codes */
+typedef u_char vm_prot_t; /* protection codes */
+
+union vm_map_object;
+typedef union vm_map_object vm_map_object_t;
+
+struct vm_map_entry;
+typedef struct vm_map_entry *vm_map_entry_t;
+
+struct vm_map;
+typedef struct vm_map *vm_map_t;
+
+struct vm_object;
+typedef struct vm_object *vm_object_t;
+
+#ifndef _KERNEL
+/*
+ * This is defined in <sys/types.h> for the kernel so that non-vm kernel
+ * sources (mainly Mach-derived ones such as ddb) don't have to include
+ * vm stuff. Defining it there for applications might break things.
+ * Define it here for "applications" that include vm headers (e.g.,
+ * genassym).
+ */
+typedef int boolean_t;
+
+/*
+ * This is defined in <sys/types.h> for the kernel so that vnode_if.h
+ * doesn't have to include <vm/vm.h>.
+ */
+struct vm_page;
+typedef struct vm_page *vm_page_t;
+#endif
+
+#endif /* VM_H */
diff --git a/cpukit/libnetworking/vm/vm_extern.h b/cpukit/libnetworking/vm/vm_extern.h
new file mode 100644
index 0000000000..50503a7f6f
--- /dev/null
+++ b/cpukit/libnetworking/vm/vm_extern.h
@@ -0,0 +1,103 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)vm_extern.h 8.2 (Berkeley) 1/12/94
+ * $Id$
+ */
+
+#ifndef _VM_EXTERN_H_
+#define _VM_EXTERN_H_
+
+struct buf;
+struct proc;
+struct vmspace;
+struct vmtotal;
+struct mount;
+struct vnode;
+
+#ifdef _KERNEL
+
+#ifdef TYPEDEF_FOR_UAP
+int getpagesize __P((struct proc * p, void *, int *));
+int madvise __P((struct proc *, void *, int *));
+int mincore __P((struct proc *, void *, int *));
+int mprotect __P((struct proc *, void *, int *));
+int msync __P((struct proc *, void *, int *));
+int munmap __P((struct proc *, void *, int *));
+int obreak __P((struct proc *, void *, int *));
+int sbrk __P((struct proc *, void *, int *));
+int smmap __P((struct proc *, void *, int *));
+int sstk __P((struct proc *, void *, int *));
+int swapon __P((struct proc *, void *, int *));
+#endif
+
+void faultin __P((struct proc *p));
+int grow __P((struct proc *, u_int));
+int kernacc __P((caddr_t, int, int));
+vm_offset_t kmem_alloc __P((vm_map_t, vm_size_t));
+vm_offset_t kmem_alloc_pageable __P((vm_map_t, vm_size_t));
+vm_offset_t kmem_alloc_wait __P((vm_map_t, vm_size_t));
+void kmem_free __P((vm_map_t, vm_offset_t, vm_size_t));
+void kmem_free_wakeup __P((vm_map_t, vm_offset_t, vm_size_t));
+void kmem_init __P((vm_offset_t, vm_offset_t));
+vm_offset_t kmem_malloc __P((vm_map_t, vm_size_t, boolean_t));
+vm_map_t kmem_suballoc __P((vm_map_t, vm_offset_t *, vm_offset_t *, vm_size_t, boolean_t));
+void munmapfd __P((struct proc *, int));
+int pager_cache __P((vm_object_t, boolean_t));
+int swaponvp __P((struct proc *, struct vnode *, dev_t , u_long));
+void swapout_procs __P((void));
+int useracc __P((caddr_t, int, int));
+int vm_fault __P((vm_map_t, vm_offset_t, vm_prot_t, boolean_t));
+void vm_fault_copy_entry __P((vm_map_t, vm_map_t, vm_map_entry_t, vm_map_entry_t));
+void vm_fault_unwire __P((vm_map_t, vm_offset_t, vm_offset_t));
+int vm_fault_wire __P((vm_map_t, vm_offset_t, vm_offset_t));
+int vm_fault_user_wire __P((vm_map_t, vm_offset_t, vm_offset_t));
+int vm_fork __P((struct proc *, struct proc *));
+int vm_mmap __P((vm_map_t, vm_offset_t *, vm_size_t, vm_prot_t, vm_prot_t, int, caddr_t, vm_ooffset_t));
+vm_offset_t vm_page_alloc_contig __P((vm_offset_t, vm_offset_t, vm_offset_t, vm_offset_t));
+void vm_set_page_size __P((void));
+void vmmeter __P((void));
+struct vmspace *vmspace_alloc __P((vm_offset_t, vm_offset_t, int));
+struct vmspace *vmspace_fork __P((struct vmspace *));
+void vmspace_free __P((struct vmspace *));
+void vnode_pager_setsize __P((struct vnode *, vm_ooffset_t));
+void vnode_pager_umount __P((struct mount *));
+void vnode_pager_uncache __P((struct vnode *));
+void vslock __P((caddr_t, u_int));
+void vsunlock __P((caddr_t, u_int, int));
+void vm_object_print __P((/* db_expr_t */ int, boolean_t, /* db_expr_t */ int,
+ char *));
+void vm_fault_quick __P((caddr_t v, int prot));
+
+#endif /* _KERNEL */
+
+#endif /* !_VM_EXTERN_H_ */
diff --git a/cpukit/libnetworking/vm/vm_kern.h b/cpukit/libnetworking/vm/vm_kern.h
new file mode 100644
index 0000000000..b1e073dd3a
--- /dev/null
+++ b/cpukit/libnetworking/vm/vm_kern.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * The Mach Operating System project at Carnegie-Mellon University.
+ *
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * from: @(#)vm_kern.h 8.1 (Berkeley) 6/11/93
+ *
+ *
+ * Copyright (c) 1987, 1990 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Authors: Avadis Tevanian, Jr., Michael Wayne Young
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ *
+ * $Id$
+ */
+
+#ifndef _VM_VM_KERN_H_
+#define _VM_VM_KERN_H_ 1
+
+/* Kernel memory management definitions. */
+extern vm_map_t buffer_map;
+extern vm_map_t kernel_map;
+extern vm_map_t kmem_map;
+extern vm_map_t mb_map;
+extern int mb_map_full;
+extern vm_map_t io_map;
+extern vm_map_t clean_map;
+extern vm_map_t phys_map;
+extern vm_map_t exec_map;
+extern vm_map_t u_map;
+
+extern vm_offset_t kernel_vm_end;
+
+#endif /* _VM_VM_KERN_H_ */
diff --git a/cpukit/libnetworking/vm/vm_param.h b/cpukit/libnetworking/vm/vm_param.h
new file mode 100644
index 0000000000..0f58fab6c6
--- /dev/null
+++ b/cpukit/libnetworking/vm/vm_param.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * The Mach Operating System project at Carnegie-Mellon University.
+ *
+ * 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 the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * from: @(#)vm_param.h 8.1 (Berkeley) 6/11/93
+ *
+ *
+ * Copyright (c) 1987, 1990 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Authors: Avadis Tevanian, Jr., Michael Wayne Young
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ *
+ * $Id$
+ */
+
+/*
+ * Machine independent virtual memory parameters.
+ */
+
+#ifndef _VM_PARAM_
+#define _VM_PARAM_
+
+#include <machine/vmparam.h>
+
+/*
+ * The machine independent pages are refered to as PAGES. A page
+ * is some number of hardware pages, depending on the target machine.
+ */
+#define DEFAULT_PAGE_SIZE 4096
+
+#if 0
+
+/*
+ * All references to the size of a page should be done with PAGE_SIZE
+ * or PAGE_SHIFT. The fact they are variables is hidden here so that
+ * we can easily make them constant if we so desire.
+ */
+#ifndef PAGE_SIZE
+#define PAGE_SIZE cnt.v_page_size /* size of page */
+#endif
+#ifndef PAGE_MASK
+#define PAGE_MASK page_mask /* size of page - 1 */
+#endif
+#ifndef PAGE_SHIFT
+#define PAGE_SHIFT page_shift /* bits to shift for pages */
+#endif
+
+#endif
+
+#ifdef _KERNEL
+extern vm_size_t page_mask;
+extern int page_shift;
+
+#endif
+
+/*
+ * CTL_VM identifiers
+ */
+#define VM_METER 1 /* struct vmmeter */
+#define VM_LOADAVG 2 /* struct loadavg */
+#define VM_V_FREE_MIN 3 /* cnt.v_free_min */
+#define VM_V_FREE_TARGET 4 /* cnt.v_free_target */
+#define VM_V_FREE_RESERVED 5 /* cnt.v_free_reserved */
+#define VM_V_INACTIVE_TARGET 6 /* cnt.v_inactive_target */
+#define VM_V_CACHE_MIN 7 /* cnt.v_cache_max */
+#define VM_V_CACHE_MAX 8 /* cnt.v_cache_min */
+#define VM_V_PAGEOUT_FREE_MIN 9 /* cnt.v_pageout_free_min */
+#define VM_PAGEOUT_ALGORITHM 10 /* pageout algorithm */
+#define VM_SWAPPING_ENABLED 11 /* swapping enabled */
+#define VM_MAXID 12 /* number of valid vm ids */
+
+#define CTL_VM_NAMES { \
+ { 0, 0 }, \
+ { "vmmeter", CTLTYPE_STRUCT }, \
+ { "loadavg", CTLTYPE_STRUCT }, \
+ { "v_free_min", CTLTYPE_INT }, \
+ { "v_free_target", CTLTYPE_INT }, \
+ { "v_free_reserved", CTLTYPE_INT }, \
+ { "v_inactive_target", CTLTYPE_INT }, \
+ { "v_cache_min", CTLTYPE_INT }, \
+ { "v_cache_max", CTLTYPE_INT }, \
+ { "v_pageout_free_min", CTLTYPE_INT}, \
+ { "pageout_algorithm", CTLTYPE_INT}, \
+ { "swapping_enabled", CTLTYPE_INT},\
+}
+
+/*
+ * Return values from the VM routines.
+ */
+#define KERN_SUCCESS 0
+#define KERN_INVALID_ADDRESS 1
+#define KERN_PROTECTION_FAILURE 2
+#define KERN_NO_SPACE 3
+#define KERN_INVALID_ARGUMENT 4
+#define KERN_FAILURE 5
+#define KERN_RESOURCE_SHORTAGE 6
+#define KERN_NOT_RECEIVER 7
+#define KERN_NO_ACCESS 8
+
+#ifndef ASSEMBLER
+/*
+ * Convert addresses to pages and vice versa.
+ * No rounding is used.
+ */
+#ifdef _KERNEL
+#define num_pages(x) \
+ ((vm_offset_t)((((vm_offset_t)(x)) + PAGE_MASK) >> PAGE_SHIFT))
+
+extern vm_size_t mem_size; /* size of physical memory (bytes) */
+extern vm_offset_t first_addr; /* first physical page */
+extern vm_offset_t last_addr; /* last physical page */
+#endif /* _KERNEL */
+#endif /* ASSEMBLER */
+#endif /* _VM_PARAM_ */
diff --git a/cpukit/librpc/.cvsignore b/cpukit/librpc/.cvsignore
new file mode 100644
index 0000000000..282522db03
--- /dev/null
+++ b/cpukit/librpc/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/cpukit/librpc/Makefile.am b/cpukit/librpc/Makefile.am
new file mode 100644
index 0000000000..975bfceabd
--- /dev/null
+++ b/cpukit/librpc/Makefile.am
@@ -0,0 +1,187 @@
+##
+## $Id$
+##
+
+include $(top_srcdir)/automake/multilib.am
+include $(top_srcdir)/automake/compile.am
+
+EXTRA_DIST =
+CLEANFILES =
+
+if LIBRPC
+include_rpcdir = $(includedir)/rpc
+include_rpc_HEADERS = include/rpc/auth.h include/rpc/auth_des.h \
+ include/rpc/auth_unix.h include/rpc/clnt.h include/rpc/des.h \
+ include/rpc/des_crypt.h include/rpc/pmap_clnt.h include/rpc/pmap_prot.h \
+ include/rpc/pmap_rmt.h include/rpc/rpc.h include/rpc/rpc_com.h \
+ include/rpc/rpc_msg.h include/rpc/svc.h include/rpc/svc_auth.h \
+ include/rpc/types.h include/rpc/xdr.h
+
+man_MANS =
+
+EXTRA_LIBRARIES = libxdr.a
+CLEANFILES += libxdr.a
+libxdr_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libxdr_g.a
+CLEANFILES += libxdr_g.a
+libxdr_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+libxdr_a_SOURCES = src/xdr/xdr.c src/xdr/xdr_array.c src/xdr/xdr_float.c \
+ src/xdr/xdr_mem.c src/xdr/xdr_rec.c src/xdr/xdr_reference.c \
+ src/xdr/xdr_sizeof.c src/xdr/xdr_stdio.c
+libxdr_g_a_SOURCES = $(libxdr_a_SOURCES)
+endif
+
+libxdr_mans = src/xdr/xdr.3
+EXTRA_DIST += $(libxdr_mans)
+
+if LIBRPC
+man_MANS += $(libxdr_mans)
+
+all-local: libxdr$(LIB_VARIANT).a
+
+EXTRA_LIBRARIES += librpc.a
+CLEANFILES += librpc.a
+librpc_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V) $(librpc_CPPFLAGS)
+
+EXTRA_LIBRARIES += librpc_g.a
+CLEANFILES += librpc_g.a
+librpc_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V) $(librpc_CPPFLAGS)
+
+librpc_a_SOURCES = src/rpc/auth_none.c src/rpc/auth_unix.c \
+ src/rpc/authunix_prot.c src/rpc/bindresvport.c src/rpc/clnt_generic.c \
+ src/rpc/clnt_perror.c src/rpc/clnt_raw.c src/rpc/clnt_simple.c \
+ src/rpc/clnt_tcp.c src/rpc/clnt_udp.c src/rpc/get_myaddress.c \
+ src/rpc/getrpcent.c src/rpc/getrpcport.c src/rpc/netname.c \
+ src/rpc/netnamer.c src/rpc/pmap_clnt.c src/rpc/pmap_getmaps.c \
+ src/rpc/pmap_getport.c src/rpc/pmap_prot.c src/rpc/pmap_prot2.c \
+ src/rpc/pmap_rmt.c src/rpc/rpc_callmsg.c src/rpc/rpc_commondata.c \
+ src/rpc/rpc_dtablesize.c src/rpc/rpc_prot.c src/rpc/rpcdname.c \
+ src/rpc/rtime.c src/rpc/svc.c src/rpc/svc_auth.c src/rpc/svc_auth_unix.c \
+ src/rpc/svc_raw.c src/rpc/svc_run.c src/rpc/svc_simple.c \
+ src/rpc/svc_tcp.c src/rpc/svc_udp.c src/rpc/rtems_portmapper.c \
+ src/rpc/rtems_rpc.c
+# librpc_UNUSED_C_FILES
+EXTRA_DIST += src/rpc/auth_des.c src/rpc/auth_time.c src/rpc/authdes_prot.c \
+ src/rpc/clnt_unix.c src/rpc/crypt_client.c src/rpc/des_crypt.c \
+ src/rpc/des_soft.c src/rpc/getpublickey.c src/rpc/key_call.c \
+ src/rpc/key_prot_xdr.c src/rpc/svc_auth_des.c src/rpc/svc_unix.c
+librpc_g_a_SOURCES = $(librpc_a_SOURCES)
+
+librpc_CPPFLAGS = -D_RPC_read=read -D_RPC_write=write -D_RPC_close=close \
+ -D_RTEMS_RPC_INTERNAL_
+endif
+
+librpc_mans = src/rpc/bindresvport.3 src/rpc/getrpcent.3 src/rpc/publickey.3 \
+ src/rpc/rpc.3 src/rpc/rpc_secure.3 src/rpc/rstat_svc.8 \
+ src/rpc/des_crypt.3 src/rpc/getrpcport.3 src/rpc/publickey.5 \
+ src/rpc/rpc.5 src/rpc/rstat.1 src/rpc/rtime.3
+EXTRA_DIST += $(librpc_mans)
+
+if LIBRPC
+man_MANS += $(librpc_mans)
+
+all-local: librpc$(LIB_VARIANT).a
+endif
+
+EXTRA_DIST += src/rpc/DISCLAIMER src/rpc/README
+
+EXTRA_DIST += src/rpc/PSD.doc/nfs.rfc.ms src/rpc/PSD.doc/rpc.prog.ms \
+ src/rpc/PSD.doc/rpc.rfc.ms src/rpc/PSD.doc/rpcgen.ms \
+ src/rpc/PSD.doc/xdr.nts.ms src/rpc/PSD.doc/xdr.rfc.ms
+EXTRA_DIST += README_RTEMS
+
+## FIXME: Unused
+EXTRA_DIST += include/rpcsvc/bootparam_prot.x include/rpcsvc/crypt.x \
+ include/rpcsvc/key_prot.x include/rpcsvc/klm_prot.x \
+ include/rpcsvc/mount.x include/rpcsvc/nfs_prot.x \
+ include/rpcsvc/nis_cache.x include/rpcsvc/nis_callback.x \
+ include/rpcsvc/nis_db.h include/rpcsvc/nislib.h \
+ include/rpcsvc/nis_object.x include/rpcsvc/nis_tags.h \
+ include/rpcsvc/nis.x include/rpcsvc/nlm_prot.x \
+ include/rpcsvc/pmap_prot.x include/rpcsvc/rex.x include/rpcsvc/rnusers.x \
+ include/rpcsvc/rquota.x include/rpcsvc/rstat.x include/rpcsvc/rwall.x \
+ include/rpcsvc/sm_inter.x include/rpcsvc/spray.x include/rpcsvc/ypclnt.h \
+ include/rpcsvc/yppasswd.x include/rpcsvc/yp_prot.h \
+ include/rpcsvc/ypupdate_prot.x include/rpcsvc/yp.x \
+ include/rpcsvc/ypxfrd.x
+
+PREINSTALL_DIRS =
+PREINSTALL_FILES =
+
+if LIBRPC
+$(PROJECT_INCLUDE)/rpc/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rpc
+ @: > $(PROJECT_INCLUDE)/rpc/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rpc/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rpc/auth.h: include/rpc/auth.h $(PROJECT_INCLUDE)/rpc/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rpc/auth.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rpc/auth.h
+
+$(PROJECT_INCLUDE)/rpc/auth_des.h: include/rpc/auth_des.h $(PROJECT_INCLUDE)/rpc/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rpc/auth_des.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rpc/auth_des.h
+
+$(PROJECT_INCLUDE)/rpc/auth_unix.h: include/rpc/auth_unix.h $(PROJECT_INCLUDE)/rpc/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rpc/auth_unix.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rpc/auth_unix.h
+
+$(PROJECT_INCLUDE)/rpc/clnt.h: include/rpc/clnt.h $(PROJECT_INCLUDE)/rpc/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rpc/clnt.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rpc/clnt.h
+
+$(PROJECT_INCLUDE)/rpc/des.h: include/rpc/des.h $(PROJECT_INCLUDE)/rpc/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rpc/des.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rpc/des.h
+
+$(PROJECT_INCLUDE)/rpc/des_crypt.h: include/rpc/des_crypt.h $(PROJECT_INCLUDE)/rpc/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rpc/des_crypt.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rpc/des_crypt.h
+
+$(PROJECT_INCLUDE)/rpc/pmap_clnt.h: include/rpc/pmap_clnt.h $(PROJECT_INCLUDE)/rpc/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rpc/pmap_clnt.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rpc/pmap_clnt.h
+
+$(PROJECT_INCLUDE)/rpc/pmap_prot.h: include/rpc/pmap_prot.h $(PROJECT_INCLUDE)/rpc/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rpc/pmap_prot.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rpc/pmap_prot.h
+
+$(PROJECT_INCLUDE)/rpc/pmap_rmt.h: include/rpc/pmap_rmt.h $(PROJECT_INCLUDE)/rpc/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rpc/pmap_rmt.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rpc/pmap_rmt.h
+
+$(PROJECT_INCLUDE)/rpc/rpc.h: include/rpc/rpc.h $(PROJECT_INCLUDE)/rpc/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rpc/rpc.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rpc/rpc.h
+
+$(PROJECT_INCLUDE)/rpc/rpc_com.h: include/rpc/rpc_com.h $(PROJECT_INCLUDE)/rpc/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rpc/rpc_com.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rpc/rpc_com.h
+
+$(PROJECT_INCLUDE)/rpc/rpc_msg.h: include/rpc/rpc_msg.h $(PROJECT_INCLUDE)/rpc/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rpc/rpc_msg.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rpc/rpc_msg.h
+
+$(PROJECT_INCLUDE)/rpc/svc.h: include/rpc/svc.h $(PROJECT_INCLUDE)/rpc/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rpc/svc.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rpc/svc.h
+
+$(PROJECT_INCLUDE)/rpc/svc_auth.h: include/rpc/svc_auth.h $(PROJECT_INCLUDE)/rpc/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rpc/svc_auth.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rpc/svc_auth.h
+
+$(PROJECT_INCLUDE)/rpc/types.h: include/rpc/types.h $(PROJECT_INCLUDE)/rpc/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rpc/types.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rpc/types.h
+
+$(PROJECT_INCLUDE)/rpc/xdr.h: include/rpc/xdr.h $(PROJECT_INCLUDE)/rpc/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rpc/xdr.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rpc/xdr.h
+endif
+
+CLEANFILES += $(PREINSTALL_FILES)
+DISTCLEANFILES = $(PREINSTALL_DIRS)
+
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/librpc/README_RTEMS b/cpukit/librpc/README_RTEMS
new file mode 100644
index 0000000000..e60f8799aa
--- /dev/null
+++ b/cpukit/librpc/README_RTEMS
@@ -0,0 +1,64 @@
+USING RPC/XDR ON RTEMS
+======================
+For the most part, programmers using RPC/XDR routines on RTEMS
+can proceed as if they were to be using a POSIX/UNIX system.
+The only significant changes are those to start the portmapper
+and to allow use of RPC/XDR by multiple threads.
+
+Starting the portmapper
+=======================
+The SUN portmapper program has been modified to run as an RTEMS
+task. Applications which need the portmapper can start this
+task by calling:
+ int rtems_rpc_start_portmapper (int priority);
+The return value is an RTEMS status code.
+
+Multi-threaded operation
+========================
+The RPC/XDR package has been modified to allow for multiple RTEMS
+tasks to use RPC/XDR routines. If more than one task is to call
+an RPC/XDR routine, the additional tasks must call:
+ int rtems_rpc_task_init(void);
+before calling any RPC/XDR routines. For example, the portmapper
+calls this routine since the portmapper uses RPC/XDR routines in
+a separate thread.
+The return value is an RTEMS status code.
+
+
+Porting Notes
+=============
+Most of the FreeBSD rpc library ports to RTEMS with little
+or no modification beyond that required to provide for operation
+in a multitasking environment. Multitasking operation was
+provided by moving all `static persistence' variables into
+a single structure and using an RTEMS task variable to point
+to that structure.
+
+Some of the library, however, has not made it into the RTEMS
+implementation. FreeBSD source files which have been left out include:
+- Files which provide RPC to the AF_UNIX address family:
+ clnt_unix.c
+ svc_unix.c
+ An `ifndef __rtems__' was added to clnt_generic.c because clnt_unix.c
+ was omitted.
+- Files which need NIS:
+ auth_time.c
+- Files which provide DES authentication:
+ auth_des.c
+ authdes_prot.c
+ crypt_client.c
+ des_crypt.c
+ des_soft.c
+ getpublickey.c
+ key_call.c
+ key_prot_xdr.c
+ svc_auth_des.c
+
+The FreeBSD xdr source compiles and runs on RTEMS without modification.
+
+The original source was obtained from:
+ ftp://ftp.FreeBSD.org/pub/FreeBSD/
+ branches/4.0-stable/src/lib/libc/rpc
+ branches/4.0-stable/src/lib/libc/xdr
+ branches/4.0-stable/src/include/rpc
+ branches/4.0-stable/src/include/rpcsvc
diff --git a/cpukit/librpc/include/rpc/auth.h b/cpukit/librpc/include/rpc/auth.h
new file mode 100644
index 0000000000..a15be39185
--- /dev/null
+++ b/cpukit/librpc/include/rpc/auth.h
@@ -0,0 +1,260 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ *
+ * from: @(#)auth.h 1.17 88/02/08 SMI
+ * from: @(#)auth.h 2.3 88/08/07 4.0 RPCSRC
+ * $FreeBSD: src/include/rpc/auth.h,v 1.15 1999/08/27 23:45:02 peter Exp $
+ */
+
+/*
+ * auth.h, Authentication interface.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * The data structures are completely opaque to the client. The client
+ * is required to pass a AUTH * to routines that create rpc
+ * "sessions".
+ */
+
+#ifndef _RPC_AUTH_H
+#define _RPC_AUTH_H
+#include <sys/cdefs.h>
+#include <sys/socket.h>
+
+#define MAX_AUTH_BYTES 400
+#define MAXNETNAMELEN 255 /* maximum length of network user's name */
+
+/*
+ * Status returned from authentication check
+ */
+enum auth_stat {
+ AUTH_OK=0,
+ /*
+ * failed at remote end
+ */
+ AUTH_BADCRED=1, /* bogus credentials (seal broken) */
+ AUTH_REJECTEDCRED=2, /* client should begin new session */
+ AUTH_BADVERF=3, /* bogus verifier (seal broken) */
+ AUTH_REJECTEDVERF=4, /* verifier expired or was replayed */
+ AUTH_TOOWEAK=5, /* rejected due to security reasons */
+ /*
+ * failed locally
+ */
+ AUTH_INVALIDRESP=6, /* bogus response verifier */
+ AUTH_FAILED=7 /* some unknown reason */
+};
+
+union des_block {
+ struct {
+ u_int32_t high;
+ u_int32_t low;
+ } key;
+ char c[8];
+};
+typedef union des_block des_block;
+__BEGIN_DECLS
+extern bool_t xdr_des_block __P((XDR *, des_block *));
+__END_DECLS
+
+/*
+ * Authentication info. Opaque to client.
+ */
+struct opaque_auth {
+ enum_t oa_flavor; /* flavor of auth */
+ caddr_t oa_base; /* address of more auth stuff */
+ u_int oa_length; /* not to exceed MAX_AUTH_BYTES */
+};
+__BEGIN_DECLS
+bool_t xdr_opaque_auth __P((XDR *xdrs, struct opaque_auth *ap));
+__END_DECLS
+
+
+/*
+ * Auth handle, interface to client side authenticators.
+ */
+typedef struct __rpc_auth {
+ struct opaque_auth ah_cred;
+ struct opaque_auth ah_verf;
+ union des_block ah_key;
+ struct auth_ops {
+ void (*ah_nextverf) __P((struct __rpc_auth *));
+ /* nextverf & serialize */
+ int (*ah_marshal) __P((struct __rpc_auth *, XDR *));
+ /* validate verifier */
+ int (*ah_validate) __P((struct __rpc_auth *,
+ struct opaque_auth *));
+ /* refresh credentials */
+ int (*ah_refresh) __P((struct __rpc_auth *));
+ /* destroy this structure */
+ void (*ah_destroy) __P((struct __rpc_auth *));
+ } *ah_ops;
+ caddr_t ah_private;
+} AUTH;
+
+
+/*
+ * Authentication ops.
+ * The ops and the auth handle provide the interface to the authenticators.
+ *
+ * AUTH *auth;
+ * XDR *xdrs;
+ * struct opaque_auth verf;
+ */
+#define AUTH_NEXTVERF(auth) \
+ ((*((auth)->ah_ops->ah_nextverf))(auth))
+#define auth_nextverf(auth) \
+ ((*((auth)->ah_ops->ah_nextverf))(auth))
+
+#define AUTH_MARSHALL(auth, xdrs) \
+ ((*((auth)->ah_ops->ah_marshal))(auth, xdrs))
+#define auth_marshall(auth, xdrs) \
+ ((*((auth)->ah_ops->ah_marshal))(auth, xdrs))
+
+#define AUTH_VALIDATE(auth, verfp) \
+ ((*((auth)->ah_ops->ah_validate))((auth), verfp))
+#define auth_validate(auth, verfp) \
+ ((*((auth)->ah_ops->ah_validate))((auth), verfp))
+
+#define AUTH_REFRESH(auth) \
+ ((*((auth)->ah_ops->ah_refresh))(auth))
+#define auth_refresh(auth) \
+ ((*((auth)->ah_ops->ah_refresh))(auth))
+
+#define AUTH_DESTROY(auth) \
+ ((*((auth)->ah_ops->ah_destroy))(auth))
+#define auth_destroy(auth) \
+ ((*((auth)->ah_ops->ah_destroy))(auth))
+
+
+extern struct opaque_auth _null_auth;
+
+/*
+ * These are the various implementations of client side authenticators.
+ */
+
+/*
+ * Unix style authentication
+ * AUTH *authunix_create(machname, uid, gid, len, aup_gids)
+ * char *machname;
+ * int uid;
+ * int gid;
+ * int len;
+ * int *aup_gids;
+ */
+__BEGIN_DECLS
+struct sockaddr_in;
+extern AUTH *authunix_create __P((char *, int, int, int, int *));
+extern AUTH *authunix_create_default __P((void));
+extern AUTH *authnone_create __P((void));
+__END_DECLS
+
+/* Forward compatibility with TI-RPC */
+#define authsys_create authunix_create
+#define authsys_create_default authunix_create_default
+
+/*
+ * DES style authentication
+ * AUTH *authdes_create(servername, window, timehost, ckey)
+ * char *servername; - network name of server
+ * u_int window; - time to live
+ * struct sockaddr *timehost; - optional hostname to sync with
+ * des_block *ckey; - optional conversation key to use
+ */
+__BEGIN_DECLS
+extern AUTH *authdes_create __P(( char *, u_int, struct sockaddr *, des_block * ));
+#ifdef NOTYET
+/*
+ * TI-RPC supports this call, but it requires the inclusion of
+ * NIS+-specific headers which would require the inclusion of other
+ * headers which would result in a tangled mess. For now, the NIS+
+ * code prototypes this routine internally.
+ */
+extern AUTH *authdes_pk_create __P(( char *, netobj *, u_int,
+ struct sockaddr *, des_block *,
+ nis_server * ));
+#endif
+__END_DECLS
+
+/*
+ * Netname manipulation routines.
+ */
+__BEGIN_DECLS
+extern int netname2user __P(( char *, uid_t *, gid_t *, int *, gid_t *));
+extern int netname2host __P(( char *, char *, int ));
+extern int getnetname __P(( char * ));
+extern int user2netname __P(( char *, uid_t, char * ));
+extern int host2netname __P(( char *, char *, char * ));
+extern void passwd2des __P(( char *, char * ));
+__END_DECLS
+
+/*
+ * Keyserv interface routines.
+ * XXX Should not be here.
+ */
+#ifndef HEXKEYBYTES
+#define HEXKEYBYTES 48
+#endif
+typedef char kbuf[HEXKEYBYTES];
+typedef char *namestr;
+
+struct netstarg {
+ kbuf st_priv_key;
+ kbuf st_pub_key;
+ namestr st_netname;
+};
+
+__BEGIN_DECLS
+extern int key_decryptsession __P(( const char *, des_block * ));
+extern int key_decryptsession_pk __P(( char *, netobj *, des_block * ));
+extern int key_encryptsession __P(( const char *, des_block * ));
+extern int key_encryptsession_pk __P(( char *, netobj *, des_block * ));
+extern int key_gendes __P(( des_block * ));
+extern int key_setsecret __P(( const char * ));
+extern int key_secretkey_is_set __P(( void ));
+extern int key_setnet __P(( struct netstarg * ));
+extern int key_get_conv __P(( char *, des_block * ));
+__END_DECLS
+
+/*
+ * Publickey routines.
+ */
+__BEGIN_DECLS
+extern int getpublickey __P(( char *, char * ));
+extern int getpublicandprivatekey __P(( char *, char * ));
+extern int getsecretkey __P(( char *, char *, char * ));
+__END_DECLS
+
+
+#define AUTH_NONE 0 /* no authentication */
+#define AUTH_NULL 0 /* backward compatibility */
+#define AUTH_UNIX 1 /* unix style (uid, gids) */
+#define AUTH_SYS 1 /* forward compatibility */
+#define AUTH_SHORT 2 /* short hand unix style */
+#define AUTH_DES 3 /* des style (encrypted timestamps) */
+
+#endif /* !_RPC_AUTH_H */
diff --git a/cpukit/librpc/include/rpc/auth_des.h b/cpukit/librpc/include/rpc/auth_des.h
new file mode 100644
index 0000000000..a7635f87e1
--- /dev/null
+++ b/cpukit/librpc/include/rpc/auth_des.h
@@ -0,0 +1,109 @@
+/* @(#)auth_des.h 2.2 88/07/29 4.0 RPCSRC; from 1.3 88/02/08 SMI */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * Copyright (c) 1988 by Sun Microsystems, Inc.
+ */
+
+/*
+ * auth_des.h, Protocol for DES style authentication for RPC
+ */
+
+#ifndef _AUTH_DES_
+#define _AUTH_DES_
+
+/*
+ * There are two kinds of "names": fullnames and nicknames
+ */
+enum authdes_namekind {
+ ADN_FULLNAME,
+ ADN_NICKNAME
+};
+
+/*
+ * A fullname contains the network name of the client,
+ * a conversation key and the window
+ */
+struct authdes_fullname {
+ char *name; /* network name of client, up to MAXNETNAMELEN */
+ des_block key; /* conversation key */
+ u_long window; /* associated window */
+};
+
+
+/*
+ * A credential
+ */
+struct authdes_cred {
+ enum authdes_namekind adc_namekind;
+ struct authdes_fullname adc_fullname;
+ u_long adc_nickname;
+};
+
+
+
+/*
+ * A des authentication verifier
+ */
+struct authdes_verf {
+ union {
+ struct timeval adv_ctime; /* clear time */
+ des_block adv_xtime; /* crypt time */
+ } adv_time_u;
+ u_long adv_int_u;
+};
+
+/*
+ * des authentication verifier: client variety
+ *
+ * adv_timestamp is the current time.
+ * adv_winverf is the credential window + 1.
+ * Both are encrypted using the conversation key.
+ */
+#define adv_timestamp adv_time_u.adv_ctime
+#define adv_xtimestamp adv_time_u.adv_xtime
+#define adv_winverf adv_int_u
+
+/*
+ * des authentication verifier: server variety
+ *
+ * adv_timeverf is the client's timestamp + client's window
+ * adv_nickname is the server's nickname for the client.
+ * adv_timeverf is encrypted using the conversation key.
+ */
+#define adv_timeverf adv_time_u.adv_ctime
+#define adv_xtimeverf adv_time_u.adv_xtime
+#define adv_nickname adv_int_u
+
+__BEGIN_DECLS
+extern int authdes_getucred __P(( struct authdes_cred *, uid_t *, gid_t *, int *, gid_t * ));
+__END_DECLS
+
+#endif /* ndef _AUTH_DES_ */
diff --git a/cpukit/librpc/include/rpc/auth_unix.h b/cpukit/librpc/include/rpc/auth_unix.h
new file mode 100644
index 0000000000..4b015b67ab
--- /dev/null
+++ b/cpukit/librpc/include/rpc/auth_unix.h
@@ -0,0 +1,84 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ *
+ * from: @(#)auth_unix.h 1.8 88/02/08 SMI
+ * from: @(#)auth_unix.h 2.2 88/07/29 4.0 RPCSRC
+ * $FreeBSD: src/include/rpc/auth_unix.h,v 1.10 1999/08/27 23:45:03 peter Exp $
+ */
+
+/*
+ * auth_unix.h, Protocol for UNIX style authentication parameters for RPC
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+/*
+ * The system is very weak. The client uses no encryption for it
+ * credentials and only sends null verifiers. The server sends backs
+ * null verifiers or optionally a verifier that suggests a new short hand
+ * for the credentials.
+ */
+
+#ifndef _RPC_AUTH_UNIX_H
+#define _RPC_AUTH_UNIX_H
+#include <sys/cdefs.h>
+
+/* The machine name is part of a credential; it may not exceed 255 bytes */
+#define MAX_MACHINE_NAME 255
+
+/* gids compose part of a credential; there may not be more than 16 of them */
+#define NGRPS 16
+
+/*
+ * Unix style credentials.
+ */
+struct authunix_parms {
+ u_long aup_time;
+ char *aup_machname;
+ int aup_uid;
+ int aup_gid;
+ u_int aup_len;
+ int *aup_gids;
+};
+
+#define authsys_parms authunix_parms
+
+__BEGIN_DECLS
+extern bool_t xdr_authunix_parms __P((XDR *, struct authunix_parms *));
+__END_DECLS
+
+/*
+ * If a response verifier has flavor AUTH_SHORT,
+ * then the body of the response verifier encapsulates the following structure;
+ * again it is serialized in the obvious fashion.
+ */
+struct short_hand_verf {
+ struct opaque_auth new_cred;
+};
+
+#endif /* !_RPC_AUTH_UNIX_H */
diff --git a/cpukit/librpc/include/rpc/clnt.h b/cpukit/librpc/include/rpc/clnt.h
new file mode 100644
index 0000000000..dc0f12d25c
--- /dev/null
+++ b/cpukit/librpc/include/rpc/clnt.h
@@ -0,0 +1,419 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ *
+ * from: @(#)clnt.h 1.31 88/02/08 SMI
+ * from: @(#)clnt.h 2.1 88/07/29 4.0 RPCSRC
+ * $FreeBSD: src/include/rpc/clnt.h,v 1.11 1999/08/27 23:45:03 peter Exp $
+ */
+
+/*
+ * clnt.h - Client side remote procedure call interface.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#ifndef _RPC_CLNT_H_
+#define _RPC_CLNT_H_
+#include <sys/cdefs.h>
+#include <sys/un.h>
+
+/*
+ * Rpc calls return an enum clnt_stat. This should be looked at more,
+ * since each implementation is required to live with this (implementation
+ * independent) list of errors.
+ */
+enum clnt_stat {
+ RPC_SUCCESS=0, /* call succeeded */
+ /*
+ * local errors
+ */
+ RPC_CANTENCODEARGS=1, /* can't encode arguments */
+ RPC_CANTDECODERES=2, /* can't decode results */
+ RPC_CANTSEND=3, /* failure in sending call */
+ RPC_CANTRECV=4, /* failure in receiving result */
+ RPC_TIMEDOUT=5, /* call timed out */
+ /*
+ * remote errors
+ */
+ RPC_VERSMISMATCH=6, /* rpc versions not compatible */
+ RPC_AUTHERROR=7, /* authentication error */
+ RPC_PROGUNAVAIL=8, /* program not available */
+ RPC_PROGVERSMISMATCH=9, /* program version mismatched */
+ RPC_PROCUNAVAIL=10, /* procedure unavailable */
+ RPC_CANTDECODEARGS=11, /* decode arguments error */
+ RPC_SYSTEMERROR=12, /* generic "other problem" */
+
+ /*
+ * callrpc & clnt_create errors
+ */
+ RPC_UNKNOWNHOST=13, /* unknown host name */
+ RPC_UNKNOWNPROTO=17, /* unkown protocol */
+
+ /*
+ * _ create errors
+ */
+ RPC_PMAPFAILURE=14, /* the pmapper failed in its call */
+ RPC_PROGNOTREGISTERED=15, /* remote program is not registered */
+ /*
+ * unspecified error
+ */
+ RPC_FAILED=16
+};
+
+
+/*
+ * Error info.
+ */
+struct rpc_err {
+ enum clnt_stat re_status;
+ union {
+ int RE_errno; /* related system error */
+ enum auth_stat RE_why; /* why the auth error occurred */
+ struct {
+ u_int32_t low; /* lowest verion supported */
+ u_int32_t high; /* highest verion supported */
+ } RE_vers;
+ struct { /* maybe meaningful if RPC_FAILED */
+ int32_t s1;
+ int32_t s2;
+ } RE_lb; /* life boot & debugging only */
+ } ru;
+#define re_errno ru.RE_errno
+#define re_why ru.RE_why
+#define re_vers ru.RE_vers
+#define re_lb ru.RE_lb
+};
+
+
+/*
+ * Client rpc handle.
+ * Created by individual implementations, see e.g. rpc_udp.c.
+ * Client is responsible for initializing auth, see e.g. auth_none.c.
+ */
+typedef struct __rpc_client {
+ AUTH *cl_auth; /* authenticator */
+ struct clnt_ops {
+ /* call remote procedure */
+ enum clnt_stat (*cl_call) __P((struct __rpc_client *,
+ u_long, xdrproc_t, caddr_t, xdrproc_t,
+ caddr_t, struct timeval));
+ /* abort a call */
+ void (*cl_abort) __P((struct __rpc_client *));
+ /* get specific error code */
+ void (*cl_geterr) __P((struct __rpc_client *,
+ struct rpc_err *));
+ /* frees results */
+ bool_t (*cl_freeres) __P((struct __rpc_client *,
+ xdrproc_t, caddr_t));
+ /* destroy this structure */
+ void (*cl_destroy) __P((struct __rpc_client *));
+ /* the ioctl() of rpc */
+ bool_t (*cl_control) __P((struct __rpc_client *, u_int,
+ void *));
+ } *cl_ops;
+ caddr_t cl_private; /* private stuff */
+} CLIENT;
+
+
+/*
+ * client side rpc interface ops
+ *
+ * Parameter types are:
+ *
+ */
+
+/*
+ * enum clnt_stat
+ * CLNT_CALL(rh, proc, xargs, argsp, xres, resp, timeout)
+ * CLIENT *rh;
+ * u_long proc;
+ * xdrproc_t xargs;
+ * caddr_t argsp;
+ * xdrproc_t xres;
+ * caddr_t resp;
+ * struct timeval timeout;
+ */
+#define CLNT_CALL(rh, proc, xargs, argsp, xres, resp, secs) \
+ ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, (caddr_t)argsp, \
+ xres, (caddr_t)resp, secs))
+#define clnt_call(rh, proc, xargs, argsp, xres, resp, secs) \
+ ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, (caddr_t)argsp, \
+ xres, (caddr_t)resp, secs))
+
+/*
+ * void
+ * CLNT_ABORT(rh);
+ * CLIENT *rh;
+ */
+#define CLNT_ABORT(rh) ((*(rh)->cl_ops->cl_abort)(rh))
+#define clnt_abort(rh) ((*(rh)->cl_ops->cl_abort)(rh))
+
+/*
+ * struct rpc_err
+ * CLNT_GETERR(rh);
+ * CLIENT *rh;
+ */
+#define CLNT_GETERR(rh,errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp))
+#define clnt_geterr(rh,errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp))
+
+
+/*
+ * bool_t
+ * CLNT_FREERES(rh, xres, resp);
+ * CLIENT *rh;
+ * xdrproc_t xres;
+ * caddr_t resp;
+ */
+#define CLNT_FREERES(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp))
+#define clnt_freeres(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp))
+
+/*
+ * bool_t
+ * CLNT_CONTROL(cl, request, info)
+ * CLIENT *cl;
+ * u_int request;
+ * char *info;
+ */
+#define CLNT_CONTROL(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in))
+#define clnt_control(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in))
+
+/*
+ * control operations that apply to udp, tcp and unix transports
+ *
+ * Note: options marked XXX are no-ops in this implementation of RPC.
+ * The are present in TI-RPC but can't be implemented here since they
+ * depend on the presence of STREAMS/TLI, which we don't have.
+ *
+ */
+#define CLSET_TIMEOUT 1 /* set timeout (timeval) */
+#define CLGET_TIMEOUT 2 /* get timeout (timeval) */
+#define CLGET_SERVER_ADDR 3 /* get server's address (sockaddr) */
+#define CLGET_FD 6 /* get connections file descriptor */
+#define CLGET_SVC_ADDR 7 /* get server's address (netbuf) XXX */
+#define CLSET_FD_CLOSE 8 /* close fd while clnt_destroy */
+#define CLSET_FD_NCLOSE 9 /* Do not close fd while clnt_destroy */
+#define CLGET_XID 10 /* Get xid */
+#define CLSET_XID 11 /* Set xid */
+#define CLGET_VERS 12 /* Get version number */
+#define CLSET_VERS 13 /* Set version number */
+#define CLGET_PROG 14 /* Get program number */
+#define CLSET_PROG 15 /* Set program number */
+#define CLSET_SVC_ADDR 16 /* get server's address (netbuf) XXX */
+#define CLSET_PUSH_TIMOD 17 /* push timod if not already present XXX */
+#define CLSET_POP_TIMOD 18 /* pop timod XXX */
+
+/*
+ * udp only control operations
+ */
+#define CLSET_RETRY_TIMEOUT 4 /* set retry timeout (timeval) */
+#define CLGET_RETRY_TIMEOUT 5 /* get retry timeout (timeval) */
+
+/*
+ * Operations which GSSAPI needs. (Bletch.)
+ */
+#define CLGET_LOCAL_ADDR 19 /* get local addr (sockaddr) */
+
+
+/*
+ * void
+ * CLNT_DESTROY(rh);
+ * CLIENT *rh;
+ */
+#define CLNT_DESTROY(rh) ((*(rh)->cl_ops->cl_destroy)(rh))
+#define clnt_destroy(rh) ((*(rh)->cl_ops->cl_destroy)(rh))
+
+
+/*
+ * RPCTEST is a test program which is accessible on every rpc
+ * transport/port. It is used for testing, performance evaluation,
+ * and network administration.
+ */
+
+#define RPCTEST_PROGRAM ((u_long)1)
+#define RPCTEST_VERSION ((u_long)1)
+#define RPCTEST_NULL_PROC ((u_long)2)
+#define RPCTEST_NULL_BATCH_PROC ((u_long)3)
+
+/*
+ * By convention, procedure 0 takes null arguments and returns them
+ */
+
+#define NULLPROC ((u_long)0)
+
+/*
+ * Below are the client handle creation routines for the various
+ * implementations of client side rpc. They can return NULL if a
+ * creation failure occurs.
+ */
+
+/*
+ * Memory based rpc (for speed check and testing)
+ * CLIENT *
+ * clntraw_create(prog, vers)
+ * u_long prog;
+ * u_long vers;
+ */
+__BEGIN_DECLS
+extern CLIENT *clntraw_create __P((u_long, u_long));
+__END_DECLS
+
+
+/*
+ * Generic client creation routine. Supported protocols are "udp", "tcp"
+ * and "unix".
+ * CLIENT *
+ * clnt_create(host, prog, vers, prot);
+ * char *host; -- hostname
+ * u_long prog; -- program number
+ * u_long vers; -- version number
+ * char *prot; -- protocol
+ */
+__BEGIN_DECLS
+extern CLIENT *clnt_create __P((char *, u_long, u_long, char *));
+__END_DECLS
+
+
+/*
+ * TCP based rpc
+ * CLIENT *
+ * clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
+ * struct sockaddr_in *raddr;
+ * u_long prog;
+ * u_long version;
+ * register int *sockp;
+ * u_int sendsz;
+ * u_int recvsz;
+ */
+__BEGIN_DECLS
+extern CLIENT *clnttcp_create __P((struct sockaddr_in *,
+ u_long,
+ u_long,
+ int *,
+ u_int,
+ u_int));
+__END_DECLS
+
+
+/*
+ * UDP based rpc.
+ * CLIENT *
+ * clntudp_create(raddr, program, version, wait, sockp)
+ * struct sockaddr_in *raddr;
+ * u_long program;
+ * u_long version;
+ * struct timeval wait;
+ * int *sockp;
+ *
+ * Same as above, but you specify max packet sizes.
+ * CLIENT *
+ * clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz)
+ * struct sockaddr_in *raddr;
+ * u_long program;
+ * u_long version;
+ * struct timeval wait;
+ * int *sockp;
+ * u_int sendsz;
+ * u_int recvsz;
+ */
+__BEGIN_DECLS
+extern CLIENT *clntudp_create __P((struct sockaddr_in *,
+ u_long,
+ u_long,
+ struct timeval,
+ int *));
+extern CLIENT *clntudp_bufcreate __P((struct sockaddr_in *,
+ u_long,
+ u_long,
+ struct timeval,
+ int *,
+ u_int,
+ u_int));
+__END_DECLS
+
+
+/*
+ * AF_UNIX based rpc
+ * CLIENT *
+ * clntunix_create(raddr, prog, vers, sockp, sendsz, recvsz)
+ * struct sockaddr_un *raddr;
+ * u_long prog;
+ * u_long version;
+ * register int *sockp;
+ * u_int sendsz;
+ * u_int recvsz;
+ */
+__BEGIN_DECLS
+extern CLIENT *clntunix_create __P((struct sockaddr_un *,
+ u_long,
+ u_long,
+ int *,
+ u_int,
+ u_int));
+__END_DECLS
+
+
+/*
+ * Print why creation failed
+ */
+__BEGIN_DECLS
+extern void clnt_pcreateerror __P((char *)); /* stderr */
+extern char *clnt_spcreateerror __P((char *)); /* string */
+__END_DECLS
+
+/*
+ * Like clnt_perror(), but is more verbose in its output
+ */
+__BEGIN_DECLS
+extern void clnt_perrno __P((enum clnt_stat)); /* stderr */
+extern char *clnt_sperrno __P((enum clnt_stat)); /* string */
+__END_DECLS
+
+/*
+ * Print an English error message, given the client error code
+ */
+__BEGIN_DECLS
+extern void clnt_perror __P((CLIENT *, char *)); /* stderr */
+extern char *clnt_sperror __P((CLIENT *, char *)); /* string */
+__END_DECLS
+
+
+/*
+ * If a creation fails, the following allows the user to figure out why.
+ */
+struct rpc_createerr {
+ enum clnt_stat cf_stat;
+ struct rpc_err cf_error; /* useful when cf_stat == RPC_PMAPFAILURE */
+};
+
+extern struct rpc_createerr rpc_createerr;
+
+
+#define UDPMSGSIZE 8800 /* rpc imposed limit on udp msg size */
+#define RPCSMALLMSGSIZE 400 /* a more reasonable packet size */
+
+#endif /* !_RPC_CLNT_H */
diff --git a/cpukit/librpc/include/rpc/des.h b/cpukit/librpc/include/rpc/des.h
new file mode 100644
index 0000000000..f41e5a7804
--- /dev/null
+++ b/cpukit/librpc/include/rpc/des.h
@@ -0,0 +1,82 @@
+/* @(#)des.h 2.2 88/08/10 4.0 RPCSRC; from 2.7 88/02/08 SMI */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Generic DES driver interface
+ * Keep this file hardware independent!
+ * Copyright (c) 1986 by Sun Microsystems, Inc.
+ */
+
+#define DES_MAXLEN 65536 /* maximum # of bytes to encrypt */
+#define DES_QUICKLEN 16 /* maximum # of bytes to encrypt quickly */
+
+enum desdir { ENCRYPT, DECRYPT };
+enum desmode { CBC, ECB };
+
+/*
+ * parameters to ioctl call
+ */
+struct desparams {
+ u_char des_key[8]; /* key (with low bit parity) */
+ enum desdir des_dir; /* direction */
+ enum desmode des_mode; /* mode */
+ u_char des_ivec[8]; /* input vector */
+ unsigned des_len; /* number of bytes to crypt */
+ union {
+ u_char UDES_data[DES_QUICKLEN];
+ u_char *UDES_buf;
+ } UDES;
+# define des_data UDES.UDES_data /* direct data here if quick */
+# define des_buf UDES.UDES_buf /* otherwise, pointer to data */
+};
+
+#ifdef notdef
+
+/*
+ * These ioctls are only implemented in SunOS. Maybe someday
+ * if somebody writes a driver for DES hardware that works
+ * with FreeBSD, we can being that back.
+ */
+
+/*
+ * Encrypt an arbitrary sized buffer
+ */
+#define DESIOCBLOCK _IOWR(d, 6, struct desparams)
+
+/*
+ * Encrypt of small amount of data, quickly
+ */
+#define DESIOCQUICK _IOWR(d, 7, struct desparams)
+
+#endif
+
+/*
+ * Software DES.
+ */
+extern int _des_crypt __P(( char *, int, struct desparams * ));
diff --git a/cpukit/librpc/include/rpc/des_crypt.h b/cpukit/librpc/include/rpc/des_crypt.h
new file mode 100644
index 0000000000..c9458fcf24
--- /dev/null
+++ b/cpukit/librpc/include/rpc/des_crypt.h
@@ -0,0 +1,120 @@
+/*
+ * @(#)des_crypt.h 2.1 88/08/11 4.0 RPCSRC; from 1.4 88/02/08 (C) 1986 SMI
+ * $FreeBSD: src/include/rpc/des_crypt.h,v 1.2 1999/12/29 05:00:42 peter Exp $
+ *
+ * des_crypt.h, des library routine interface
+ * Copyright (C) 1986, Sun Microsystems, Inc.
+ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#include <sys/cdefs.h>
+#include <rpc/rpc.h>
+
+#define DES_MAXDATA 8192 /* max bytes encrypted in one call */
+#define DES_DIRMASK (1 << 0)
+#define DES_ENCRYPT (0*DES_DIRMASK) /* Encrypt */
+#define DES_DECRYPT (1*DES_DIRMASK) /* Decrypt */
+
+
+#define DES_DEVMASK (1 << 1)
+#define DES_HW (0*DES_DEVMASK) /* Use hardware device */
+#define DES_SW (1*DES_DEVMASK) /* Use software device */
+
+
+#define DESERR_NONE 0 /* succeeded */
+#define DESERR_NOHWDEVICE 1 /* succeeded, but hw device not available */
+#define DESERR_HWERROR 2 /* failed, hardware/driver error */
+#define DESERR_BADPARAM 3 /* failed, bad parameter to call */
+
+#define DES_FAILED(err) \
+ ((err) > DESERR_NOHWDEVICE)
+
+/*
+ * cbc_crypt()
+ * ecb_crypt()
+ *
+ * Encrypt (or decrypt) len bytes of a buffer buf.
+ * The length must be a multiple of eight.
+ * The key should have odd parity in the low bit of each byte.
+ * ivec is the input vector, and is updated to the new one (cbc only).
+ * The mode is created by oring together the appropriate parameters.
+ * DESERR_NOHWDEVICE is returned if DES_HW was specified but
+ * there was no hardware to do it on (the data will still be
+ * encrypted though, in software).
+ */
+
+
+/*
+ * Cipher Block Chaining mode
+ */
+__BEGIN_DECLS
+#ifdef __STDC__
+int cbc_crypt __P(( char *, char *, unsigned int, unsigned int, char *));
+#else
+cbc_crypt(/* key, buf, len, mode, ivec */); /*
+ char *key;
+ char *buf;
+ unsigned len;
+ unsigned mode;
+ char *ivec;
+*/
+#endif
+
+/*
+ * Electronic Code Book mode
+ */
+#ifdef __STDC__
+int ecb_crypt __P(( char *, char *, unsigned int, unsigned int ));
+#else
+ecb_crypt(/* key, buf, len, mode */); /*
+ char *key;
+ char *buf;
+ unsigned len;
+ unsigned mode;
+*/
+#endif
+__END_DECLS
+
+#ifndef _KERNEL
+/*
+ * Set des parity for a key.
+ * DES parity is odd and in the low bit of each byte
+ */
+__BEGIN_DECLS
+#ifdef __STDC__
+void des_setparity __P(( char *));
+#else
+void
+des_setparity(/* key */); /*
+ char *key;
+*/
+#endif
+__END_DECLS
+#endif
diff --git a/cpukit/librpc/include/rpc/pmap_clnt.h b/cpukit/librpc/include/rpc/pmap_clnt.h
new file mode 100644
index 0000000000..2f4a2780dd
--- /dev/null
+++ b/cpukit/librpc/include/rpc/pmap_clnt.h
@@ -0,0 +1,85 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ *
+ * from: @(#)pmap_clnt.h 1.11 88/02/08 SMI
+ * from: @(#)pmap_clnt.h 2.1 88/07/29 4.0 RPCSRC
+ * $FreeBSD: src/include/rpc/pmap_clnt.h,v 1.11 1999/08/27 23:45:04 peter Exp $
+ */
+
+/*
+ * pmap_clnt.h
+ * Supplies C routines to get to portmap services.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+/*
+ * Usage:
+ * success = pmap_set(program, version, protocol, port);
+ * success = pmap_unset(program, version);
+ * port = pmap_getport(address, program, version, protocol);
+ * head = pmap_getmaps(address);
+ * clnt_stat = pmap_rmtcall(address, program, version, procedure,
+ * xdrargs, argsp, xdrres, resp, tout, port_ptr)
+ * (works for udp only.)
+ * clnt_stat = clnt_broadcast(program, version, procedure,
+ * xdrargs, argsp, xdrres, resp, eachresult)
+ * (like pmap_rmtcall, except the call is broadcasted to all
+ * locally connected nets. For each valid response received,
+ * the procedure eachresult is called. Its form is:
+ * done = eachresult(resp, raddr)
+ * bool_t done;
+ * caddr_t resp;
+ * struct sockaddr_in raddr;
+ * where resp points to the results of the call and raddr is the
+ * address if the responder to the broadcast.
+ */
+
+#ifndef _RPC_PMAPCLNT_H
+#define _RPC_PMAPCLNT_H
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+extern bool_t pmap_set __P((u_long, u_long, int, int));
+extern bool_t pmap_unset __P((u_long, u_long));
+extern struct pmaplist *pmap_getmaps __P((struct sockaddr_in *));
+extern enum clnt_stat pmap_rmtcall __P((struct sockaddr_in *,
+ u_long, u_long, u_long,
+ xdrproc_t, caddr_t,
+ xdrproc_t, caddr_t,
+ struct timeval, u_long *));
+extern enum clnt_stat clnt_broadcast __P((u_long, u_long, u_long,
+ xdrproc_t, char *,
+ xdrproc_t, char *,
+ bool_t (*) __P((caddr_t,
+ struct sockaddr_in *))));
+extern u_short pmap_getport __P((struct sockaddr_in *,
+ u_long, u_long, u_int));
+__END_DECLS
+
+#endif /* !_RPC_PMAPCLNT_H */
diff --git a/cpukit/librpc/include/rpc/pmap_prot.h b/cpukit/librpc/include/rpc/pmap_prot.h
new file mode 100644
index 0000000000..14f0837bfe
--- /dev/null
+++ b/cpukit/librpc/include/rpc/pmap_prot.h
@@ -0,0 +1,104 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ *
+ * from: @(#)pmap_prot.h 1.14 88/02/08 SMI
+ * from: @(#)pmap_prot.h 2.1 88/07/29 4.0 RPCSRC
+ * $FreeBSD: src/include/rpc/pmap_prot.h,v 1.10 1999/08/27 23:45:04 peter Exp $
+ */
+
+/*
+ * pmap_prot.h
+ * Protocol for the local binder service, or pmap.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * The following procedures are supported by the protocol:
+ *
+ * PMAPPROC_NULL() returns ()
+ * takes nothing, returns nothing
+ *
+ * PMAPPROC_SET(struct pmap) returns (bool_t)
+ * TRUE is success, FALSE is failure. Registers the tuple
+ * [prog, vers, prot, port].
+ *
+ * PMAPPROC_UNSET(struct pmap) returns (bool_t)
+ * TRUE is success, FALSE is failure. Un-registers pair
+ * [prog, vers]. prot and port are ignored.
+ *
+ * PMAPPROC_GETPORT(struct pmap) returns (long unsigned).
+ * 0 is failure. Otherwise returns the port number where the pair
+ * [prog, vers] is registered. It may lie!
+ *
+ * PMAPPROC_DUMP() RETURNS (struct pmaplist *)
+ *
+ * PMAPPROC_CALLIT(unsigned, unsigned, unsigned, string<>)
+ * RETURNS (port, string<>);
+ * usage: encapsulatedresults = PMAPPROC_CALLIT(prog, vers, proc, encapsulatedargs);
+ * Calls the procedure on the local machine. If it is not registered,
+ * this procedure is quite; ie it does not return error information!!!
+ * This procedure only is supported on rpc/udp and calls via
+ * rpc/udp. This routine only passes null authentication parameters.
+ * This file has no interface to xdr routines for PMAPPROC_CALLIT.
+ *
+ * The service supports remote procedure calls on udp/ip or tcp/ip socket 111.
+ */
+
+#ifndef _RPC_PMAPPROT_H
+#define _RPC_PMAPPROT_H
+#include <sys/cdefs.h>
+
+#define PMAPPORT ((u_short)111)
+#define PMAPPROG ((u_long)100000)
+#define PMAPVERS ((u_long)2)
+#define PMAPVERS_PROTO ((u_long)2)
+#define PMAPVERS_ORIG ((u_long)1)
+#define PMAPPROC_NULL ((u_long)0)
+#define PMAPPROC_SET ((u_long)1)
+#define PMAPPROC_UNSET ((u_long)2)
+#define PMAPPROC_GETPORT ((u_long)3)
+#define PMAPPROC_DUMP ((u_long)4)
+#define PMAPPROC_CALLIT ((u_long)5)
+
+struct pmap {
+ long unsigned pm_prog;
+ long unsigned pm_vers;
+ long unsigned pm_prot;
+ long unsigned pm_port;
+};
+
+struct pmaplist {
+ struct pmap pml_map;
+ struct pmaplist *pml_next;
+};
+
+__BEGIN_DECLS
+extern bool_t xdr_pmap __P((XDR *, struct pmap *));
+extern bool_t xdr_pmaplist __P((XDR *, struct pmaplist **));
+__END_DECLS
+
+#endif /* !_RPC_PMAPPROT_H */
diff --git a/cpukit/librpc/include/rpc/pmap_rmt.h b/cpukit/librpc/include/rpc/pmap_rmt.h
new file mode 100644
index 0000000000..e632f8deca
--- /dev/null
+++ b/cpukit/librpc/include/rpc/pmap_rmt.h
@@ -0,0 +1,63 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ *
+ * from: @(#)pmap_rmt.h 1.2 88/02/08 SMI
+ * from: @(#)pmap_rmt.h 2.1 88/07/29 4.0 RPCSRC
+ * $FreeBSD: src/include/rpc/pmap_rmt.h,v 1.10 1999/08/27 23:45:05 peter Exp $
+ */
+
+/*
+ * Structures and XDR routines for parameters to and replies from
+ * the portmapper remote-call-service.
+ *
+ * Copyright (C) 1986, Sun Microsystems, Inc.
+ */
+
+#ifndef _RPC_PMAPRMT_H
+#define _RPC_PMAPRMT_H
+#include <sys/cdefs.h>
+
+struct rmtcallargs {
+ u_long prog, vers, proc, arglen;
+ caddr_t args_ptr;
+ xdrproc_t xdr_args;
+};
+
+struct rmtcallres {
+ u_long *port_ptr;
+ u_long resultslen;
+ caddr_t results_ptr;
+ xdrproc_t xdr_results;
+};
+
+__BEGIN_DECLS
+extern bool_t xdr_rmtcall_args __P((XDR *, struct rmtcallargs *));
+extern bool_t xdr_rmtcallres __P((XDR *, struct rmtcallres *));
+__END_DECLS
+
+#endif /* !_RPC_PMAPRMT_H */
diff --git a/cpukit/librpc/include/rpc/rpc.h b/cpukit/librpc/include/rpc/rpc.h
new file mode 100644
index 0000000000..74b97e6b1d
--- /dev/null
+++ b/cpukit/librpc/include/rpc/rpc.h
@@ -0,0 +1,137 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ *
+ * from: @(#)rpc.h 1.9 88/02/08 SMI
+ * from: @(#)rpc.h 2.4 89/07/11 4.0 RPCSRC
+ * $FreeBSD: src/include/rpc/rpc.h,v 1.12 2000/01/26 09:02:40 shin Exp $
+ */
+
+/*
+ * rpc.h, Just includes the billions of rpc header files necessary to
+ * do remote procedure calling.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+#ifndef _RPC_RPC_H
+#define _RPC_RPC_H
+
+#include <rpc/types.h> /* some typedefs */
+#include <netinet/in.h>
+
+/* external data representation interfaces */
+#include <rpc/xdr.h> /* generic (de)serializer */
+
+/* Client side only authentication */
+#include <rpc/auth.h> /* generic authenticator (client side) */
+
+/* Client side (mostly) remote procedure call */
+#include <rpc/clnt.h> /* generic rpc stuff */
+
+/* semi-private protocol headers */
+#include <rpc/rpc_msg.h> /* protocol for rpc messages */
+#include <rpc/auth_unix.h> /* protocol for unix style cred */
+/*
+ * Uncomment-out the next line if you are building the rpc library with
+ * DES Authentication (see the README file in the secure_rpc/ directory).
+ */
+#include <rpc/auth_des.h> /* protocol for des style cred */
+
+/* Server side only remote procedure callee */
+#include <rpc/svc.h> /* service manager and multiplexer */
+#include <rpc/svc_auth.h> /* service side authenticator */
+
+/*
+ * COMMENT OUT THE NEXT INCLUDE (or add to the #ifndef) IF RUNNING ON
+ * A VERSION OF UNIX THAT USES SUN'S NFS SOURCE. These systems will
+ * already have the structures defined by <rpc/netdb.h> included in <netdb.h>.
+ */
+/* routines for parsing /etc/rpc */
+
+struct rpcent {
+ char *r_name; /* name of server for this rpc program */
+ char **r_aliases; /* alias list */
+ int r_number; /* rpc program number */
+};
+
+__BEGIN_DECLS
+extern struct rpcent *getrpcbyname __P((char *));
+extern struct rpcent *getrpcbynumber __P((int));
+extern struct rpcent *getrpcent __P((void));
+extern int getrpcport __P((char *host, int prognum, int versnum, int proto));
+extern void setrpcent __P((int));
+extern void endrpcent __P((void));
+
+extern int bindresvport __P((int, struct sockaddr_in *));
+extern int bindresvport_sa __P((int, struct sockaddr *));
+extern int get_myaddress __P((struct sockaddr_in *));
+__END_DECLS
+
+int rtems_rpc_task_init (void);
+int rtems_rpc_start_portmapper (int priority);
+
+#ifdef _RTEMS_RPC_INTERNAL_
+/*
+ * Multi-threaded support
+ * Group all global and static variables into a single spot.
+ * This area will be allocated on a per-task basis
+ */
+struct _rtems_rpc_task_variables {
+ int svc_svc_maxfd;
+ fd_set svc_svc_fdset;
+ void *svc_xports;
+ int svc_xportssize;
+ int svc__svc_fdsetsize;
+ void *svc__svc_fdset;
+ void *svc_svc_head;
+
+ void *clnt_perror_buf;
+
+ void *clnt_raw_private;
+
+ void *call_rpc_private;
+
+ void *svc_raw_private;
+
+ void *svc_simple_proglst;
+ void *svc_simple_pl;
+ void *svc_simple_transp;
+
+ void *rpcdname_default_domain;
+
+ void *svc_auths_Auths;
+};
+extern struct _rtems_rpc_task_variables *rtems_rpc_task_variables;
+
+#define svc_maxfd (rtems_rpc_task_variables->svc_svc_maxfd)
+#define svc_fdset ((rtems_rpc_task_variables)->svc_svc_fdset)
+#define __svc_fdsetsize (rtems_rpc_task_variables->svc__svc_fdsetsize)
+#define __svc_fdset (fd_set *)(rtems_rpc_task_variables->svc__svc_fdset)
+
+#endif /* _RTEMS_RPC_INTERNAL_ */
+
+#endif /* !_RPC_RPC_H */
diff --git a/cpukit/librpc/include/rpc/rpc_com.h b/cpukit/librpc/include/rpc/rpc_com.h
new file mode 100644
index 0000000000..2cf5995d2d
--- /dev/null
+++ b/cpukit/librpc/include/rpc/rpc_com.h
@@ -0,0 +1,78 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
+ */
+
+/*
+ * rpc_com.h, Common definitions for both the server and client side.
+ * All for the topmost layer of rpc
+ *
+ */
+
+#ifndef _RPC_RPCCOM_H
+#define _RPC_RPCCOM_H
+
+/* From: #pragma ident "@(#)rpc_com.h 1.11 93/07/05 SMI" */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * File descriptor to be used on xxx_create calls to get default descriptor
+ */
+#define RPC_ANYSOCK -1
+#define RPC_ANYFD RPC_ANYSOCK
+/*
+ * The max size of the transport, if the size cannot be determined
+ * by other means.
+ */
+#define RPC_MAXDATASIZE 9000
+#define RPC_MAXADDRSIZE 1024
+
+#if defined(__STDC__) || defined(__cplusplus)
+extern u_int __rpc_get_t_size (int, long);
+extern u_int __rpc_get_a_size (long);
+extern int __rpc_dtbsize (void);
+extern int _rpc_dtablesize (void);
+extern int _rpc_get_default_domain(char **);
+#else
+extern u_int __rpc_get_t_size ();
+extern u_int __rpc_get_a_size ();
+extern int __rpc_dtbsize ();
+extern int _rpc_dtablesize ();
+extern int _rpc_get_default_domain();
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RPC_RPCCOM_H */
diff --git a/cpukit/librpc/include/rpc/rpc_msg.h b/cpukit/librpc/include/rpc/rpc_msg.h
new file mode 100644
index 0000000000..bc5dc223fd
--- /dev/null
+++ b/cpukit/librpc/include/rpc/rpc_msg.h
@@ -0,0 +1,196 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ *
+ * from: @(#)rpc_msg.h 1.7 86/07/16 SMI
+ * from: @(#)rpc_msg.h 2.1 88/07/29 4.0 RPCSRC
+ * $FreeBSD: src/include/rpc/rpc_msg.h,v 1.12 1999/08/27 23:45:05 peter Exp $
+ */
+
+/*
+ * rpc_msg.h
+ * rpc message definition
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#ifndef _RPC_RPCMSG_H
+#define _RPC_RPCMSG_H
+
+#define RPC_MSG_VERSION ((u_long) 2)
+#define RPC_SERVICE_PORT ((u_short) 2048)
+
+/*
+ * Bottom up definition of an rpc message.
+ * NOTE: call and reply use the same overall stuct but
+ * different parts of unions within it.
+ */
+
+enum msg_type {
+ CALL=0,
+ REPLY=1
+};
+
+enum reply_stat {
+ MSG_ACCEPTED=0,
+ MSG_DENIED=1
+};
+
+enum accept_stat {
+ SUCCESS=0,
+ PROG_UNAVAIL=1,
+ PROG_MISMATCH=2,
+ PROC_UNAVAIL=3,
+ GARBAGE_ARGS=4,
+ SYSTEM_ERR=5
+};
+
+enum reject_stat {
+ RPC_MISMATCH=0,
+ AUTH_ERROR=1
+};
+
+/*
+ * Reply part of an rpc exchange
+ */
+
+/*
+ * Reply to an rpc request that was accepted by the server.
+ * Note: there could be an error even though the request was
+ * accepted.
+ */
+struct accepted_reply {
+ struct opaque_auth ar_verf;
+ enum accept_stat ar_stat;
+ union {
+ struct {
+ u_int32_t low;
+ u_int32_t high;
+ } AR_versions;
+ struct {
+ caddr_t where;
+ xdrproc_t proc;
+ } AR_results;
+ /* and many other null cases */
+ } ru;
+#define ar_results ru.AR_results
+#define ar_vers ru.AR_versions
+};
+
+/*
+ * Reply to an rpc request that was rejected by the server.
+ */
+struct rejected_reply {
+ enum reject_stat rj_stat;
+ union {
+ struct {
+ u_int32_t low;
+ u_int32_t high;
+ } RJ_versions;
+ enum auth_stat RJ_why; /* why authentication did not work */
+ } ru;
+#define rj_vers ru.RJ_versions
+#define rj_why ru.RJ_why
+};
+
+/*
+ * Body of a reply to an rpc request.
+ */
+struct reply_body {
+ enum reply_stat rp_stat;
+ union {
+ struct accepted_reply RP_ar;
+ struct rejected_reply RP_dr;
+ } ru;
+#define rp_acpt ru.RP_ar
+#define rp_rjct ru.RP_dr
+};
+
+/*
+ * Body of an rpc request call.
+ */
+struct call_body {
+ u_int32_t cb_rpcvers; /* must be equal to two */
+ u_int32_t cb_prog;
+ u_int32_t cb_vers;
+ u_int32_t cb_proc;
+ struct opaque_auth cb_cred;
+ struct opaque_auth cb_verf; /* protocol specific - provided by client */
+};
+
+/*
+ * The rpc message
+ */
+struct rpc_msg {
+ u_int32_t rm_xid;
+ enum msg_type rm_direction;
+ union {
+ struct call_body RM_cmb;
+ struct reply_body RM_rmb;
+ } ru;
+#define rm_call ru.RM_cmb
+#define rm_reply ru.RM_rmb
+};
+#define acpted_rply ru.RM_rmb.ru.RP_ar
+#define rjcted_rply ru.RM_rmb.ru.RP_dr
+
+__BEGIN_DECLS
+/*
+ * XDR routine to handle a rpc message.
+ * xdr_callmsg(xdrs, cmsg)
+ * XDR *xdrs;
+ * struct rpc_msg *cmsg;
+ */
+extern bool_t xdr_callmsg __P((XDR *, struct rpc_msg *));
+
+/*
+ * XDR routine to pre-serialize the static part of a rpc message.
+ * xdr_callhdr(xdrs, cmsg)
+ * XDR *xdrs;
+ * struct rpc_msg *cmsg;
+ */
+extern bool_t xdr_callhdr __P((XDR *, struct rpc_msg *));
+
+/*
+ * XDR routine to handle a rpc reply.
+ * xdr_replymsg(xdrs, rmsg)
+ * XDR *xdrs;
+ * struct rpc_msg *rmsg;
+ */
+extern bool_t xdr_replymsg __P((XDR *, struct rpc_msg *));
+
+/*
+ * Fills in the error part of a reply message.
+ * _seterr_reply(msg, error)
+ * struct rpc_msg *msg;
+ * struct rpc_err *error;
+ */
+struct rpc_err;
+extern void _seterr_reply __P((struct rpc_msg *, struct rpc_err *));
+__END_DECLS
+
+#endif /* !_RPC_RPCMSG_H */
diff --git a/cpukit/librpc/include/rpc/svc.h b/cpukit/librpc/include/rpc/svc.h
new file mode 100644
index 0000000000..e57a7454be
--- /dev/null
+++ b/cpukit/librpc/include/rpc/svc.h
@@ -0,0 +1,324 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ *
+ * from: @(#)svc.h 1.20 88/02/08 SMI
+ * from: @(#)svc.h 2.2 88/07/29 4.0 RPCSRC
+ * $FreeBSD: src/include/rpc/svc.h,v 1.16 1999/12/29 05:00:43 peter Exp $
+ */
+
+/*
+ * svc.h, Server-side remote procedure call interface.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#ifndef _RPC_SVC_H
+#define _RPC_SVC_H
+#include <sys/cdefs.h>
+
+/*
+ * This interface must manage two items concerning remote procedure calling:
+ *
+ * 1) An arbitrary number of transport connections upon which rpc requests
+ * are received. The two most notable transports are TCP and UDP; they are
+ * created and registered by routines in svc_tcp.c and svc_udp.c, respectively;
+ * they in turn call xprt_register and xprt_unregister.
+ *
+ * 2) An arbitrary number of locally registered services. Services are
+ * described by the following four data: program number, version number,
+ * "service dispatch" function, a transport handle, and a boolean that
+ * indicates whether or not the exported program should be registered with a
+ * local binder service; if true the program's number and version and the
+ * port number from the transport handle are registered with the binder.
+ * These data are registered with the rpc svc system via svc_register.
+ *
+ * A service's dispatch function is called whenever an rpc request comes in
+ * on a transport. The request's program and version numbers must match
+ * those of the registered service. The dispatch function is passed two
+ * parameters, struct svc_req * and SVCXPRT *, defined below.
+ */
+
+enum xprt_stat {
+ XPRT_DIED,
+ XPRT_MOREREQS,
+ XPRT_IDLE
+};
+
+struct rpc_msg;
+
+/*
+ * Server side transport handle
+ */
+typedef struct __rpc_svcxprt {
+ int xp_sock;
+ u_short xp_port; /* associated port number */
+ struct xp_ops {
+ /* receive incoming requests */
+ bool_t (*xp_recv) __P((struct __rpc_svcxprt *,
+ struct rpc_msg *));
+ /* get transport status */
+ enum xprt_stat (*xp_stat) __P((struct __rpc_svcxprt *));
+ /* get arguments */
+ bool_t (*xp_getargs) __P((struct __rpc_svcxprt *, xdrproc_t,
+ caddr_t));
+ /* send reply */
+ bool_t (*xp_reply) __P((struct __rpc_svcxprt *,
+ struct rpc_msg *));
+ /* free mem allocated for args */
+ bool_t (*xp_freeargs) __P((struct __rpc_svcxprt *, xdrproc_t,
+ caddr_t));
+ /* destroy this struct */
+ void (*xp_destroy) __P((struct __rpc_svcxprt *));
+ } *xp_ops;
+ int xp_addrlen; /* length of remote address */
+ struct sockaddr_in xp_raddr; /* remote address */
+ struct opaque_auth xp_verf; /* raw response verifier */
+ caddr_t xp_p1; /* private */
+ caddr_t xp_p2; /* private */
+} SVCXPRT;
+
+/*
+ * Approved way of getting address of caller
+ */
+#define svc_getcaller(x) (&(x)->xp_raddr)
+
+/*
+ * Operations defined on an SVCXPRT handle
+ *
+ * SVCXPRT *xprt;
+ * struct rpc_msg *msg;
+ * xdrproc_t xargs;
+ * caddr_t argsp;
+ */
+#define SVC_RECV(xprt, msg) \
+ (*(xprt)->xp_ops->xp_recv)((xprt), (msg))
+#define svc_recv(xprt, msg) \
+ (*(xprt)->xp_ops->xp_recv)((xprt), (msg))
+
+#define SVC_STAT(xprt) \
+ (*(xprt)->xp_ops->xp_stat)(xprt)
+#define svc_stat(xprt) \
+ (*(xprt)->xp_ops->xp_stat)(xprt)
+
+#define SVC_GETARGS(xprt, xargs, argsp) \
+ (*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp))
+#define svc_getargs(xprt, xargs, argsp) \
+ (*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp))
+
+#define SVC_REPLY(xprt, msg) \
+ (*(xprt)->xp_ops->xp_reply) ((xprt), (msg))
+#define svc_reply(xprt, msg) \
+ (*(xprt)->xp_ops->xp_reply) ((xprt), (msg))
+
+#define SVC_FREEARGS(xprt, xargs, argsp) \
+ (*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp))
+#define svc_freeargs(xprt, xargs, argsp) \
+ (*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp))
+
+#define SVC_DESTROY(xprt) \
+ (*(xprt)->xp_ops->xp_destroy)(xprt)
+#define svc_destroy(xprt) \
+ (*(xprt)->xp_ops->xp_destroy)(xprt)
+
+
+/*
+ * Service request
+ */
+struct svc_req {
+ u_int32_t rq_prog; /* service program number */
+ u_int32_t rq_vers; /* service protocol version */
+ u_int32_t rq_proc; /* the desired procedure */
+ struct opaque_auth rq_cred; /* raw creds from the wire */
+ caddr_t rq_clntcred; /* read only cooked cred */
+ SVCXPRT *rq_xprt; /* associated transport */
+};
+
+
+/*
+ * Service registration
+ *
+ * svc_register(xprt, prog, vers, dispatch, protocol)
+ * SVCXPRT *xprt;
+ * u_long prog;
+ * u_long vers;
+ * void (*dispatch)();
+ * int protocol; (like TCP or UDP, zero means do not register)
+ */
+__BEGIN_DECLS
+extern bool_t svc_register __P((SVCXPRT *, u_long, u_long,
+ void (*) __P((struct svc_req *, SVCXPRT *)), int));
+__END_DECLS
+
+/*
+ * Service un-registration
+ *
+ * svc_unregister(prog, vers)
+ * u_long prog;
+ * u_long vers;
+ */
+__BEGIN_DECLS
+extern void svc_unregister __P((u_long, u_long));
+__END_DECLS
+
+/*
+ * Transport registration.
+ *
+ * xprt_register(xprt)
+ * SVCXPRT *xprt;
+ */
+__BEGIN_DECLS
+extern void xprt_register __P((SVCXPRT *));
+__END_DECLS
+
+/*
+ * Transport un-register
+ *
+ * xprt_unregister(xprt)
+ * SVCXPRT *xprt;
+ */
+__BEGIN_DECLS
+extern void xprt_unregister __P((SVCXPRT *));
+__END_DECLS
+
+
+
+
+/*
+ * When the service routine is called, it must first check to see if it
+ * knows about the procedure; if not, it should call svcerr_noproc
+ * and return. If so, it should deserialize its arguments via
+ * SVC_GETARGS (defined above). If the deserialization does not work,
+ * svcerr_decode should be called followed by a return. Successful
+ * decoding of the arguments should be followed the execution of the
+ * procedure's code and a call to svc_sendreply.
+ *
+ * Also, if the service refuses to execute the procedure due to too-
+ * weak authentication parameters, svcerr_weakauth should be called.
+ * Note: do not confuse access-control failure with weak authentication!
+ *
+ * NB: In pure implementations of rpc, the caller always waits for a reply
+ * msg. This message is sent when svc_sendreply is called.
+ * Therefore pure service implementations should always call
+ * svc_sendreply even if the function logically returns void; use
+ * xdr.h - xdr_void for the xdr routine. HOWEVER, tcp based rpc allows
+ * for the abuse of pure rpc via batched calling or pipelining. In the
+ * case of a batched call, svc_sendreply should NOT be called since
+ * this would send a return message, which is what batching tries to avoid.
+ * It is the service/protocol writer's responsibility to know which calls are
+ * batched and which are not. Warning: responding to batch calls may
+ * deadlock the caller and server processes!
+ */
+
+__BEGIN_DECLS
+extern bool_t svc_sendreply __P((SVCXPRT *, xdrproc_t, char *));
+extern void svcerr_decode __P((SVCXPRT *));
+extern void svcerr_weakauth __P((SVCXPRT *));
+extern void svcerr_noproc __P((SVCXPRT *));
+extern void svcerr_progvers __P((SVCXPRT *, u_long, u_long));
+extern void svcerr_auth __P((SVCXPRT *, enum auth_stat));
+extern void svcerr_noprog __P((SVCXPRT *));
+extern void svcerr_systemerr __P((SVCXPRT *));
+__END_DECLS
+
+/*
+ * Lowest level dispatching -OR- who owns this process anyway.
+ * Somebody has to wait for incoming requests and then call the correct
+ * service routine. The routine svc_run does infinite waiting; i.e.,
+ * svc_run never returns.
+ * Since another (co-existant) package may wish to selectively wait for
+ * incoming calls or other events outside of the rpc architecture, the
+ * routine svc_getreq is provided. It must be passed readfds, the
+ * "in-place" results of a select system call (see select, section 2).
+ */
+
+/*
+ * Global keeper of rpc service descriptors in use
+ * dynamic; must be inspected before each call to select
+ */
+extern int svc_maxfd;
+extern fd_set svc_fdset;
+#define svc_fds svc_fdset.fds_bits[0] /* compatibility */
+
+#ifndef _KERNEL
+/*
+ * a small program implemented by the svc_rpc implementation itself;
+ * also see clnt.h for protocol numbers.
+ */
+extern void rpctest_service();
+#endif
+
+__BEGIN_DECLS
+extern void svc_getreq __P((int));
+extern void svc_getreqset __P((fd_set *));
+extern void svc_getreqset2 __P((fd_set *, int)); /* XXX: nonstd, undoc */
+extern void svc_run __P((void));
+__END_DECLS
+
+/*
+ * Socket to use on svcxxx_create call to get default socket
+ */
+#define RPC_ANYSOCK -1
+
+/*
+ * These are the existing service side transport implementations
+ */
+
+/*
+ * Memory based rpc for testing and timing.
+ */
+__BEGIN_DECLS
+extern SVCXPRT *svcraw_create __P((void));
+__END_DECLS
+
+
+/*
+ * Udp based rpc.
+ */
+__BEGIN_DECLS
+extern SVCXPRT *svcudp_create __P((int));
+extern SVCXPRT *svcudp_bufcreate __P((int, u_int, u_int));
+__END_DECLS
+
+
+/*
+ * Tcp based rpc.
+ */
+__BEGIN_DECLS
+extern SVCXPRT *svctcp_create __P((int, u_int, u_int));
+extern SVCXPRT *svcfd_create __P((int, u_int, u_int));
+__END_DECLS
+
+/*
+ * AF_UNIX socket based rpc.
+ */
+__BEGIN_DECLS
+extern SVCXPRT *svcunix_create __P((int, u_int, u_int, char *));
+extern SVCXPRT *svcunixfd_create __P((int, u_int, u_int));
+__END_DECLS
+
+#endif /* !_RPC_SVC_H */
diff --git a/cpukit/librpc/include/rpc/svc_auth.h b/cpukit/librpc/include/rpc/svc_auth.h
new file mode 100644
index 0000000000..a203d8cbeb
--- /dev/null
+++ b/cpukit/librpc/include/rpc/svc_auth.h
@@ -0,0 +1,56 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ *
+ * from: @(#)svc_auth.h 1.6 86/07/16 SMI
+ * from: @(#)svc_auth.h 2.1 88/07/29 4.0 RPCSRC
+ * $FreeBSD: src/include/rpc/svc_auth.h,v 1.12 1999/08/27 23:45:05 peter Exp $
+ */
+
+/*
+ * svc_auth.h, Service side of rpc authentication.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#ifndef _RPC_SVCAUTH_H
+#define _RPC_SVCAUTH_H
+
+struct rpc_msg;
+struct svc_req;
+
+/*
+ * Server side authenticator
+ */
+__BEGIN_DECLS
+extern enum auth_stat _authenticate __P((struct svc_req *, struct rpc_msg *));
+extern int svc_auth_reg __P((int, enum auth_stat (*)(struct svc_req *,
+ struct rpc_msg *)));
+extern enum auth_stat _svcauth_des __P((struct svc_req *, struct rpc_msg *));
+__END_DECLS
+
+#endif /* !_RPC_SVCAUTH_H */
diff --git a/cpukit/librpc/include/rpc/types.h b/cpukit/librpc/include/rpc/types.h
new file mode 100644
index 0000000000..c907674c51
--- /dev/null
+++ b/cpukit/librpc/include/rpc/types.h
@@ -0,0 +1,62 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ *
+ * from: @(#)types.h 1.18 87/07/24 SMI
+ * from: @(#)types.h 2.3 88/08/15 4.0 RPCSRC
+ * $FreeBSD: src/include/rpc/types.h,v 1.9 1999/08/27 23:45:06 peter Exp $
+ */
+
+/*
+ * Rpc additions to <sys/types.h>
+ */
+#ifndef _RPC_TYPES_H
+#define _RPC_TYPES_H
+
+#define bool_t int32_t
+#define enum_t int32_t
+#define __dontcare__ -1
+
+#ifndef FALSE
+# define FALSE (0)
+#endif
+#ifndef TRUE
+# define TRUE (1)
+#endif
+#ifndef NULL
+# define NULL 0
+#endif
+
+#define mem_alloc(bsize) malloc(bsize)
+#define mem_free(ptr, bsize) free(ptr)
+
+#ifndef makedev /* ie, we haven't already included it */
+#include <sys/types.h>
+#endif
+#include <sys/time.h>
+
+#endif /* !_RPC_TYPES_H */
diff --git a/cpukit/librpc/include/rpc/xdr.h b/cpukit/librpc/include/rpc/xdr.h
new file mode 100644
index 0000000000..75c2493176
--- /dev/null
+++ b/cpukit/librpc/include/rpc/xdr.h
@@ -0,0 +1,314 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ *
+ * from: @(#)xdr.h 1.19 87/04/22 SMI
+ * from: @(#)xdr.h 2.2 88/07/29 4.0 RPCSRC
+ * $FreeBSD: src/include/rpc/xdr.h,v 1.14 1999/12/29 05:00:44 peter Exp $
+ */
+
+/*
+ * xdr.h, External Data Representation Serialization Routines.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#ifndef _RPC_XDR_H
+#define _RPC_XDR_H
+#include <sys/cdefs.h>
+
+/*
+ * XDR provides a conventional way for converting between C data
+ * types and an external bit-string representation. Library supplied
+ * routines provide for the conversion on built-in C data types. These
+ * routines and utility routines defined here are used to help implement
+ * a type encode/decode routine for each user-defined type.
+ *
+ * Each data type provides a single procedure which takes two arguments:
+ *
+ * bool_t
+ * xdrproc(xdrs, argresp)
+ * XDR *xdrs;
+ * <type> *argresp;
+ *
+ * xdrs is an instance of a XDR handle, to which or from which the data
+ * type is to be converted. argresp is a pointer to the structure to be
+ * converted. The XDR handle contains an operation field which indicates
+ * which of the operations (ENCODE, DECODE * or FREE) is to be performed.
+ *
+ * XDR_DECODE may allocate space if the pointer argresp is null. This
+ * data can be freed with the XDR_FREE operation.
+ *
+ * We write only one procedure per data type to make it easy
+ * to keep the encode and decode procedures for a data type consistent.
+ * In many cases the same code performs all operations on a user defined type,
+ * because all the hard work is done in the component type routines.
+ * decode as a series of calls on the nested data types.
+ */
+
+/*
+ * Xdr operations. XDR_ENCODE causes the type to be encoded into the
+ * stream. XDR_DECODE causes the type to be extracted from the stream.
+ * XDR_FREE can be used to release the space allocated by an XDR_DECODE
+ * request.
+ */
+enum xdr_op {
+ XDR_ENCODE=0,
+ XDR_DECODE=1,
+ XDR_FREE=2
+};
+
+/*
+ * This is the number of bytes per unit of external data.
+ */
+#define BYTES_PER_XDR_UNIT (4)
+#define RNDUP(x) ((((x) + BYTES_PER_XDR_UNIT - 1) / BYTES_PER_XDR_UNIT) \
+ * BYTES_PER_XDR_UNIT)
+
+/*
+ * The XDR handle.
+ * Contains operation which is being applied to the stream,
+ * an operations vector for the particular implementation (e.g. see xdr_mem.c),
+ * and two private fields for the use of the particular implementation.
+ */
+typedef struct __rpc_xdr {
+ enum xdr_op x_op; /* operation; fast additional param */
+ struct xdr_ops {
+ /* get a long from underlying stream */
+ bool_t (*x_getlong) __P((struct __rpc_xdr *, long *));
+ /* put a long to underlying stream */
+ bool_t (*x_putlong) __P((struct __rpc_xdr *, long *));
+ /* get some bytes from underlying stream */
+ bool_t (*x_getbytes) __P((struct __rpc_xdr *, caddr_t, u_int));
+ /* put some bytes to underlying stream */
+ bool_t (*x_putbytes) __P((struct __rpc_xdr *, caddr_t, u_int));
+ /* returns bytes off from beginning */
+ u_int (*x_getpostn) __P((struct __rpc_xdr *));
+ /* lets you reposition the stream */
+ bool_t (*x_setpostn) __P((struct __rpc_xdr *, u_int));
+ /* buf quick ptr to buffered data */
+ int32_t *(*x_inline) __P((struct __rpc_xdr *, u_int));
+ /* free privates of this xdr_stream */
+ void (*x_destroy) __P((struct __rpc_xdr *));
+ } *x_ops;
+ caddr_t x_public; /* users' data */
+ caddr_t x_private; /* pointer to private data */
+ caddr_t x_base; /* private used for position info */
+ int x_handy; /* extra private word */
+} XDR;
+
+/*
+ * A xdrproc_t exists for each data type which is to be encoded or decoded.
+ *
+ * The second argument to the xdrproc_t is a pointer to an opaque pointer.
+ * The opaque pointer generally points to a structure of the data type
+ * to be decoded. If this pointer is 0, then the type routines should
+ * allocate dynamic storage of the appropriate size and return it.
+ */
+#ifdef _KERNEL
+typedef bool_t (*xdrproc_t) __P((XDR *, void *, u_int));
+#else
+/*
+ * XXX can't actually prototype it, because some take two args!!!
+ */
+typedef bool_t (*xdrproc_t) __P((/* XDR *, void *, u_int */));
+#endif
+
+/*
+ * Operations defined on a XDR handle
+ *
+ * XDR *xdrs;
+ * long *longp;
+ * caddr_t addr;
+ * u_int len;
+ * u_int pos;
+ */
+#define XDR_GETLONG(xdrs, longp) \
+ (*(xdrs)->x_ops->x_getlong)(xdrs, longp)
+#define xdr_getlong(xdrs, longp) \
+ (*(xdrs)->x_ops->x_getlong)(xdrs, longp)
+
+#define XDR_PUTLONG(xdrs, longp) \
+ (*(xdrs)->x_ops->x_putlong)(xdrs, longp)
+#define xdr_putlong(xdrs, longp) \
+ (*(xdrs)->x_ops->x_putlong)(xdrs, longp)
+
+#define XDR_GETBYTES(xdrs, addr, len) \
+ (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len)
+#define xdr_getbytes(xdrs, addr, len) \
+ (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len)
+
+#define XDR_PUTBYTES(xdrs, addr, len) \
+ (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len)
+#define xdr_putbytes(xdrs, addr, len) \
+ (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len)
+
+#define XDR_GETPOS(xdrs) \
+ (*(xdrs)->x_ops->x_getpostn)(xdrs)
+#define xdr_getpos(xdrs) \
+ (*(xdrs)->x_ops->x_getpostn)(xdrs)
+
+#define XDR_SETPOS(xdrs, pos) \
+ (*(xdrs)->x_ops->x_setpostn)(xdrs, pos)
+#define xdr_setpos(xdrs, pos) \
+ (*(xdrs)->x_ops->x_setpostn)(xdrs, pos)
+
+#define XDR_INLINE(xdrs, len) \
+ (*(xdrs)->x_ops->x_inline)(xdrs, len)
+#define xdr_inline(xdrs, len) \
+ (*(xdrs)->x_ops->x_inline)(xdrs, len)
+
+#define XDR_DESTROY(xdrs) \
+ if ((xdrs)->x_ops->x_destroy) \
+ (*(xdrs)->x_ops->x_destroy)(xdrs)
+#define xdr_destroy(xdrs) \
+ if ((xdrs)->x_ops->x_destroy) \
+ (*(xdrs)->x_ops->x_destroy)(xdrs)
+
+/*
+ * Support struct for discriminated unions.
+ * You create an array of xdrdiscrim structures, terminated with
+ * a entry with a null procedure pointer. The xdr_union routine gets
+ * the discriminant value and then searches the array of structures
+ * for a matching value. If a match is found the associated xdr routine
+ * is called to handle that part of the union. If there is
+ * no match, then a default routine may be called.
+ * If there is no match and no default routine it is an error.
+ */
+#define NULL_xdrproc_t ((xdrproc_t)0)
+struct xdr_discrim {
+ int value;
+ xdrproc_t proc;
+};
+
+/*
+ * In-line routines for fast encode/decode of primitive data types.
+ * Caveat emptor: these use single memory cycles to get the
+ * data from the underlying buffer, and will fail to operate
+ * properly if the data is not aligned. The standard way to use these
+ * is to say:
+ * if ((buf = XDR_INLINE(xdrs, count)) == NULL)
+ * return (FALSE);
+ * <<< macro calls >>>
+ * where ``count'' is the number of bytes of data occupied
+ * by the primitive data types.
+ *
+ * N.B. and frozen for all time: each data type here uses 4 bytes
+ * of external representation.
+ */
+#define IXDR_GET_LONG(buf) ((long)ntohl((u_long)*(buf)++))
+#define IXDR_PUT_LONG(buf, v) (*(buf)++ = (long)htonl((u_long)v))
+
+#define IXDR_GET_BOOL(buf) ((bool_t)IXDR_GET_LONG(buf))
+#define IXDR_GET_ENUM(buf, t) ((t)IXDR_GET_LONG(buf))
+#define IXDR_GET_U_LONG(buf) ((u_long)IXDR_GET_LONG(buf))
+#define IXDR_GET_SHORT(buf) ((short)IXDR_GET_LONG(buf))
+#define IXDR_GET_U_SHORT(buf) ((u_short)IXDR_GET_LONG(buf))
+
+#define IXDR_PUT_BOOL(buf, v) IXDR_PUT_LONG((buf), ((long)(v)))
+#define IXDR_PUT_ENUM(buf, v) IXDR_PUT_LONG((buf), ((long)(v)))
+#define IXDR_PUT_U_LONG(buf, v) IXDR_PUT_LONG((buf), ((long)(v)))
+#define IXDR_PUT_SHORT(buf, v) IXDR_PUT_LONG((buf), ((long)(v)))
+#define IXDR_PUT_U_SHORT(buf, v) IXDR_PUT_LONG((buf), ((long)(v)))
+
+/*
+ * These are the "generic" xdr routines.
+ */
+__BEGIN_DECLS
+extern bool_t xdr_void __P((void));
+extern bool_t xdr_int __P((XDR *, int *));
+extern bool_t xdr_u_int __P((XDR *, u_int *));
+extern bool_t xdr_long __P((XDR *, long *));
+extern bool_t xdr_u_long __P((XDR *, u_long *));
+extern bool_t xdr_short __P((XDR *, short *));
+extern bool_t xdr_u_short __P((XDR *, u_short *));
+extern bool_t xdr_int16_t __P((XDR *, int16_t *));
+extern bool_t xdr_u_int16_t __P((XDR *, u_int16_t *));
+extern bool_t xdr_int32_t __P((XDR *, int32_t *));
+extern bool_t xdr_u_int32_t __P((XDR *, u_int32_t *));
+extern bool_t xdr_int64_t __P((XDR *, int64_t *));
+extern bool_t xdr_u_int64_t __P((XDR *, u_int64_t *));
+extern bool_t xdr_bool __P((XDR *, bool_t *));
+extern bool_t xdr_enum __P((XDR *, enum_t *));
+extern bool_t xdr_array __P((XDR *, char **, u_int *, u_int, u_int, xdrproc_t));
+extern bool_t xdr_bytes __P((XDR *, char **, u_int *, u_int));
+extern bool_t xdr_opaque __P((XDR *, caddr_t, u_int));
+extern bool_t xdr_string __P((XDR *, char **, u_int));
+extern bool_t xdr_union __P((XDR *, enum_t *, char *, struct xdr_discrim *, xdrproc_t));
+extern unsigned long xdr_sizeof __P((xdrproc_t, void *));
+extern bool_t xdr_char __P((XDR *, char *));
+extern bool_t xdr_u_char __P((XDR *, u_char *));
+extern bool_t xdr_vector __P((XDR *, char *, u_int, u_int, xdrproc_t));
+extern bool_t xdr_float __P((XDR *, float *));
+extern bool_t xdr_double __P((XDR *, double *));
+extern bool_t xdr_reference __P((XDR *, caddr_t *, u_int, xdrproc_t));
+extern bool_t xdr_pointer __P((XDR *, caddr_t *, u_int, xdrproc_t));
+extern bool_t xdr_wrapstring __P((XDR *, char **));
+extern void xdr_free __P((xdrproc_t, char *));
+__END_DECLS
+
+/*
+ * Common opaque bytes objects used by many rpc protocols;
+ * declared here due to commonality.
+ */
+#define MAX_NETOBJ_SZ 1024
+struct netobj {
+ u_int n_len;
+ char *n_bytes;
+};
+typedef struct netobj netobj;
+extern bool_t xdr_netobj __P((XDR *, struct netobj *));
+
+/*
+ * These are the public routines for the various implementations of
+ * xdr streams.
+ */
+__BEGIN_DECLS
+/* XDR using memory buffers */
+extern void xdrmem_create __P((XDR *, char *, u_int, enum xdr_op));
+
+#ifdef _STDIO_H_
+/* XDR using stdio library */
+extern void xdrstdio_create __P((XDR *, FILE *, enum xdr_op));
+#endif
+
+/* XDR pseudo records for tcp */
+extern void xdrrec_create __P((XDR *, u_int, u_int, char *,
+ int (*) __P((caddr_t, caddr_t, int)),
+ int (*) __P((caddr_t, caddr_t, int))));
+
+/* make end of xdr record */
+extern bool_t xdrrec_endofrecord __P((XDR *, bool_t));
+
+/* move to beginning of next record */
+extern bool_t xdrrec_skiprecord __P((XDR *));
+
+/* true if no more input */
+extern bool_t xdrrec_eof __P((XDR *));
+__END_DECLS
+
+#endif /* !_RPC_XDR_H */
diff --git a/cpukit/librpc/include/rpcsvc/bootparam_prot.x b/cpukit/librpc/include/rpcsvc/bootparam_prot.x
new file mode 100644
index 0000000000..0f74c8f8ad
--- /dev/null
+++ b/cpukit/librpc/include/rpcsvc/bootparam_prot.x
@@ -0,0 +1,103 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * RPC for bootparms service.
+ * There are two procedures:
+ * WHOAMI takes a net address and returns a client name and also a
+ * likely net address for routing
+ * GETFILE takes a client name and file identifier and returns the
+ * server name, server net address and pathname for the file.
+ * file identifiers typically include root, swap, pub and dump
+ */
+
+#ifdef RPC_HDR
+%#include <rpc/types.h>
+%#include <sys/time.h>
+%#include <sys/errno.h>
+%#include <sys/param.h>
+%#include <sys/syslimits.h>
+%#include <sys/ucred.h>
+#else
+%#ifndef lint
+%/*static char sccsid[] = "from: @(#)bootparam_prot.x 1.2 87/06/24 Copyr 1987 Sun Micro";*/
+%/*static char sccsid[] = "from: @(#)bootparam_prot.x 2.1 88/08/01 4.0 RPCSRC";*/
+%static const char rcsid[] =
+% "$FreeBSD: src/include/rpcsvc/bootparam_prot.x,v 1.5 1999/08/27 23:45:07 peter Exp $";
+%#endif /* not lint */
+#endif
+
+const MAX_MACHINE_NAME = 255;
+const MAX_PATH_LEN = 1024;
+const MAX_FILEID = 32;
+const IP_ADDR_TYPE = 1;
+
+typedef string bp_machine_name_t<MAX_MACHINE_NAME>;
+typedef string bp_path_t<MAX_PATH_LEN>;
+typedef string bp_fileid_t<MAX_FILEID>;
+
+struct ip_addr_t {
+ char net;
+ char host;
+ char lh;
+ char impno;
+};
+
+union bp_address switch (int address_type) {
+ case IP_ADDR_TYPE:
+ ip_addr_t ip_addr;
+};
+
+struct bp_whoami_arg {
+ bp_address client_address;
+};
+
+struct bp_whoami_res {
+ bp_machine_name_t client_name;
+ bp_machine_name_t domain_name;
+ bp_address router_address;
+};
+
+struct bp_getfile_arg {
+ bp_machine_name_t client_name;
+ bp_fileid_t file_id;
+};
+
+struct bp_getfile_res {
+ bp_machine_name_t server_name;
+ bp_address server_address;
+ bp_path_t server_path;
+};
+
+program BOOTPARAMPROG {
+ version BOOTPARAMVERS {
+ bp_whoami_res BOOTPARAMPROC_WHOAMI(bp_whoami_arg) = 1;
+ bp_getfile_res BOOTPARAMPROC_GETFILE(bp_getfile_arg) = 2;
+ } = 1;
+} = 100026;
diff --git a/cpukit/librpc/include/rpcsvc/crypt.x b/cpukit/librpc/include/rpcsvc/crypt.x
new file mode 100644
index 0000000000..8df1654440
--- /dev/null
+++ b/cpukit/librpc/include/rpcsvc/crypt.x
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 1996
+ * Bill Paul <wpaul@ctr.columbia.edu>. 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 Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul 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.
+ *
+ * $FreeBSD: src/include/rpcsvc/crypt.x,v 1.3 1999/08/27 23:45:08 peter Exp $
+ */
+
+#ifndef RPC_HDR
+%#ifndef lint
+%static const char rcsid[] =
+% "$FreeBSD: src/include/rpcsvc/crypt.x,v 1.3 1999/08/27 23:45:08 peter Exp $";
+%#endif
+#endif
+
+/*
+ * This protocol definition exists because of the U.S. government and
+ * its stupid export laws. We can't export DES code from the United
+ * States to other countries (even though the code already exists
+ * outside the U.S. -- go figure that one out) but we need to make
+ * Secure RPC work. The normal way around this is to break the DES
+ * code out into a shared library; we can then provide a dummy lib
+ * in the base OS and provide the real lib in the secure dist, which
+ * the user can install later. But we need Secure RPC for NIS+, and
+ * there are several system programs that use NIS+ which are statically
+ * linked. We would have to provide replacements for these programs
+ * in the secure dist, but there are a lot, and this is a pain. The
+ * shared lib trick won't work for these programs, and we can't change
+ * them once they're compiled.
+ *
+ * One solution for this problem is to do the DES encryption as a system
+ * call; no programs need to be changed and we can even supply the DES
+ * support as an LKM. But this bloats the kernel. Maybe if we have
+ * Secure NFS one day this will be worth it, but for now we should keep
+ * this mess in user space.
+ *
+ * So we have this second solution: we provide a server that does the
+ * DES encryption for us. In this case, the server is keyserv (we need
+ * it to make Secure RPC work anyway) and we use this protocol to ship
+ * the data back and forth between keyserv and the application.
+ */
+
+enum des_dir { ENCRYPT_DES, DECRYPT_DES };
+enum des_mode { CBC_DES, ECB_DES };
+
+struct desargs {
+ u_char des_key[8]; /* key (with low bit parity) */
+ des_dir des_dir; /* direction */
+ des_mode des_mode; /* mode */
+ u_char des_ivec[8]; /* input vector */
+ opaque desbuf<>;
+};
+
+struct desresp {
+ opaque desbuf<>;
+ u_char des_ivec[8];
+ int stat;
+};
+
+program CRYPT_PROG {
+ version CRYPT_VERS {
+ desresp
+ DES_CRYPT(desargs) = 1;
+ } = 1;
+} = 600100029;
diff --git a/cpukit/librpc/include/rpcsvc/key_prot.x b/cpukit/librpc/include/rpcsvc/key_prot.x
new file mode 100644
index 0000000000..f545569e01
--- /dev/null
+++ b/cpukit/librpc/include/rpcsvc/key_prot.x
@@ -0,0 +1,282 @@
+%/*
+% * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+% * unrestricted use provided that this legend is included on all tape
+% * media and as a part of the software program in whole or part. Users
+% * may copy or modify Sun RPC without charge, but are not authorized
+% * to license or distribute it to anyone else except as part of a product or
+% * program developed by the user.
+% *
+% * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+% * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+% * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+% *
+% * Sun RPC is provided with no support and without any obligation on the
+% * part of Sun Microsystems, Inc. to assist in its use, correction,
+% * modification or enhancement.
+% *
+% * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+% * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+% * OR ANY PART THEREOF.
+% *
+% * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+% * or profits or other special, indirect and consequential damages, even if
+% * Sun has been advised of the possibility of such damages.
+% *
+% * Sun Microsystems, Inc.
+% * 2550 Garcia Avenue
+% * Mountain View, California 94043
+% */
+/*
+ * Key server protocol definition
+ * Copyright (C) 1990, 1991 Sun Microsystems, Inc.
+ *
+ * The keyserver is a public key storage/encryption/decryption service
+ * The encryption method used is based on the Diffie-Hellman exponential
+ * key exchange technology.
+ *
+ * The key server is local to each machine, akin to the portmapper.
+ * Under TI-RPC, communication with the keyserver is through the
+ * loopback transport.
+ *
+ * NOTE: This .x file generates the USER level headers for the keyserver.
+ * the KERNEL level headers are created by hand as they kernel has special
+ * requirements.
+ */
+
+%/* From: #pragma ident "@(#)key_prot.x 1.7 94/04/29 SMI" */
+%
+%/* Copyright (c) 1990, 1991 Sun Microsystems, Inc. */
+%
+%/*
+% * Compiled from key_prot.x using rpcgen.
+% * DO NOT EDIT THIS FILE!
+% * This is NOT source code!
+% */
+
+/*
+ * PROOT and MODULUS define the way the Diffie-Hellman key is generated.
+ *
+ * MODULUS should be chosen as a prime of the form: MODULUS == 2*p + 1,
+ * where p is also prime.
+ *
+ * PROOT satisfies the following two conditions:
+ * (1) (PROOT ** 2) % MODULUS != 1
+ * (2) (PROOT ** p) % MODULUS != 1
+ *
+ */
+
+const PROOT = 3;
+const HEXMODULUS = "d4a0ba0250b6fd2ec626e7efd637df76c716e22d0944b88b";
+
+const HEXKEYBYTES = 48; /* HEXKEYBYTES == strlen(HEXMODULUS) */
+const KEYSIZE = 192; /* KEYSIZE == bit length of key */
+const KEYBYTES = 24; /* byte length of key */
+
+/*
+ * The first 16 hex digits of the encrypted secret key are used as
+ * a checksum in the database.
+ */
+const KEYCHECKSUMSIZE = 16;
+
+/*
+ * status of operation
+ */
+enum keystatus {
+ KEY_SUCCESS, /* no problems */
+ KEY_NOSECRET, /* no secret key stored */
+ KEY_UNKNOWN, /* unknown netname */
+ KEY_SYSTEMERR /* system error (out of memory, encryption failure) */
+};
+
+typedef opaque keybuf[HEXKEYBYTES]; /* store key in hex */
+
+typedef string netnamestr<MAXNETNAMELEN>;
+
+/*
+ * Argument to ENCRYPT or DECRYPT
+ */
+struct cryptkeyarg {
+ netnamestr remotename;
+ des_block deskey;
+};
+
+/*
+ * Argument to ENCRYPT_PK or DECRYPT_PK
+ */
+struct cryptkeyarg2 {
+ netnamestr remotename;
+ netobj remotekey; /* Contains a length up to 1024 bytes */
+ des_block deskey;
+};
+
+
+/*
+ * Result of ENCRYPT, DECRYPT, ENCRYPT_PK, and DECRYPT_PK
+ */
+union cryptkeyres switch (keystatus status) {
+case KEY_SUCCESS:
+ des_block deskey;
+default:
+ void;
+};
+
+const MAXGIDS = 16; /* max number of gids in gid list */
+
+/*
+ * Unix credential
+ */
+struct unixcred {
+ u_int uid;
+ u_int gid;
+ u_int gids<MAXGIDS>;
+};
+
+/*
+ * Result returned from GETCRED
+ */
+union getcredres switch (keystatus status) {
+case KEY_SUCCESS:
+ unixcred cred;
+default:
+ void;
+};
+/*
+ * key_netstarg;
+ */
+
+struct key_netstarg {
+ keybuf st_priv_key;
+ keybuf st_pub_key;
+ netnamestr st_netname;
+};
+
+union key_netstres switch (keystatus status){
+case KEY_SUCCESS:
+ key_netstarg knet;
+default:
+ void;
+};
+
+#ifdef RPC_HDR
+%
+%#ifndef opaque
+%#define opaque char
+%#endif
+%
+#endif
+program KEY_PROG {
+ version KEY_VERS {
+
+ /*
+ * This is my secret key.
+ * Store it for me.
+ */
+ keystatus
+ KEY_SET(keybuf) = 1;
+
+ /*
+ * I want to talk to X.
+ * Encrypt a conversation key for me.
+ */
+ cryptkeyres
+ KEY_ENCRYPT(cryptkeyarg) = 2;
+
+ /*
+ * X just sent me a message.
+ * Decrypt the conversation key for me.
+ */
+ cryptkeyres
+ KEY_DECRYPT(cryptkeyarg) = 3;
+
+ /*
+ * Generate a secure conversation key for me
+ */
+ des_block
+ KEY_GEN(void) = 4;
+
+ /*
+ * Get me the uid, gid and group-access-list associated
+ * with this netname (for kernel which cannot use NIS)
+ */
+ getcredres
+ KEY_GETCRED(netnamestr) = 5;
+ } = 1;
+ version KEY_VERS2 {
+
+ /*
+ * #######
+ * Procedures 1-5 are identical to version 1
+ * #######
+ */
+
+ /*
+ * This is my secret key.
+ * Store it for me.
+ */
+ keystatus
+ KEY_SET(keybuf) = 1;
+
+ /*
+ * I want to talk to X.
+ * Encrypt a conversation key for me.
+ */
+ cryptkeyres
+ KEY_ENCRYPT(cryptkeyarg) = 2;
+
+ /*
+ * X just sent me a message.
+ * Decrypt the conversation key for me.
+ */
+ cryptkeyres
+ KEY_DECRYPT(cryptkeyarg) = 3;
+
+ /*
+ * Generate a secure conversation key for me
+ */
+ des_block
+ KEY_GEN(void) = 4;
+
+ /*
+ * Get me the uid, gid and group-access-list associated
+ * with this netname (for kernel which cannot use NIS)
+ */
+ getcredres
+ KEY_GETCRED(netnamestr) = 5;
+
+ /*
+ * I want to talk to X. and I know X's public key
+ * Encrypt a conversation key for me.
+ */
+ cryptkeyres
+ KEY_ENCRYPT_PK(cryptkeyarg2) = 6;
+
+ /*
+ * X just sent me a message. and I know X's public key
+ * Decrypt the conversation key for me.
+ */
+ cryptkeyres
+ KEY_DECRYPT_PK(cryptkeyarg2) = 7;
+
+ /*
+ * Store my public key, netname and private key.
+ */
+ keystatus
+ KEY_NET_PUT(key_netstarg) = 8;
+
+ /*
+ * Retrieve my public key, netname and private key.
+ */
+ key_netstres
+ KEY_NET_GET(void) = 9;
+
+ /*
+ * Return me the conversation key that is constructed
+ * from my secret key and this publickey.
+ */
+
+ cryptkeyres
+ KEY_GET_CONV(keybuf) = 10;
+
+
+ } = 2;
+} = 100029;
diff --git a/cpukit/librpc/include/rpcsvc/klm_prot.x b/cpukit/librpc/include/rpcsvc/klm_prot.x
new file mode 100644
index 0000000000..c4cfe36d42
--- /dev/null
+++ b/cpukit/librpc/include/rpcsvc/klm_prot.x
@@ -0,0 +1,139 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * Kernel/lock manager protocol definition
+ * Copyright (C) 1986 Sun Microsystems, Inc.
+ *
+ * protocol used between the UNIX kernel (the "client") and the
+ * local lock manager. The local lock manager is a deamon running
+ * above the kernel.
+ */
+
+#ifndef RPC_HDR
+%#ifndef lint
+%/*static char sccsid[] = "from: @(#)klm_prot.x 1.7 87/07/08 Copyr 1987 Sun Micro";*/
+%/*static char sccsid[] = "from: @(#)klm_prot.x 2.1 88/08/01 4.0 RPCSRC";*/
+%static const char rcsid[] =
+% "$FreeBSD: src/include/rpcsvc/klm_prot.x,v 1.6 1999/08/27 23:45:08 peter Exp $";
+%#endif /* not lint */
+#endif
+
+const LM_MAXSTRLEN = 1024;
+
+/*
+ * lock manager status returns
+ */
+enum klm_stats {
+ klm_granted = 0, /* lock is granted */
+ klm_denied = 1, /* lock is denied */
+ klm_denied_nolocks = 2, /* no lock entry available */
+ klm_working = 3 /* lock is being processed */
+};
+
+/*
+ * lock manager lock identifier
+ */
+struct klm_lock {
+ string server_name<LM_MAXSTRLEN>;
+ netobj fh; /* a counted file handle */
+ int pid; /* holder of the lock */
+ unsigned l_offset; /* beginning offset of the lock */
+ unsigned l_len; /* byte length of the lock;
+ * zero means through end of file */
+};
+
+/*
+ * lock holder identifier
+ */
+struct klm_holder {
+ bool exclusive; /* FALSE if shared lock */
+ int svid; /* holder of the lock (pid) */
+ unsigned l_offset; /* beginning offset of the lock */
+ unsigned l_len; /* byte length of the lock;
+ * zero means through end of file */
+};
+
+/*
+ * reply to KLM_LOCK / KLM_UNLOCK / KLM_CANCEL
+ */
+struct klm_stat {
+ klm_stats stat;
+};
+
+/*
+ * reply to a KLM_TEST call
+ */
+union klm_testrply switch (klm_stats stat) {
+ case klm_denied:
+ struct klm_holder holder;
+ default: /* All other cases return no arguments */
+ void;
+};
+
+
+/*
+ * arguments to KLM_LOCK
+ */
+struct klm_lockargs {
+ bool block;
+ bool exclusive;
+ struct klm_lock alock;
+};
+
+/*
+ * arguments to KLM_TEST
+ */
+struct klm_testargs {
+ bool exclusive;
+ struct klm_lock alock;
+};
+
+/*
+ * arguments to KLM_UNLOCK
+ */
+struct klm_unlockargs {
+ struct klm_lock alock;
+};
+
+program KLM_PROG {
+ version KLM_VERS {
+
+ klm_testrply KLM_TEST (struct klm_testargs) = 1;
+
+ klm_stat KLM_LOCK (struct klm_lockargs) = 2;
+
+ klm_stat KLM_CANCEL (struct klm_lockargs) = 3;
+ /* klm_granted=> the cancel request fails due to lock is already granted */
+ /* klm_denied=> the cancel request successfully aborts
+lock request */
+
+ klm_stat KLM_UNLOCK (struct klm_unlockargs) = 4;
+ } = 1;
+} = 100020;
diff --git a/cpukit/librpc/include/rpcsvc/mount.x b/cpukit/librpc/include/rpcsvc/mount.x
new file mode 100644
index 0000000000..f68a06fe9b
--- /dev/null
+++ b/cpukit/librpc/include/rpcsvc/mount.x
@@ -0,0 +1,257 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * Protocol description for the mount program
+ */
+
+#ifndef RPC_HDR
+%#ifndef lint
+%/*static char sccsid[] = "from: @(#)mount.x 1.2 87/09/18 Copyr 1987 Sun Micro";*/
+%/*static char sccsid[] = "from: @(#)mount.x 2.1 88/08/01 4.0 RPCSRC";*/
+%static const char rcsid[] =
+% "$FreeBSD: src/include/rpcsvc/mount.x,v 1.6 1999/08/27 23:45:08 peter Exp $";
+%#endif /* not lint */
+#endif
+
+const MNTPATHLEN = 1024; /* maximum bytes in a pathname argument */
+const MNTNAMLEN = 255; /* maximum bytes in a name argument */
+const FHSIZE = 32; /* size in bytes of a file handle */
+#ifdef WANT_NFS3
+const FHSIZE3 = 64; /* size in bytes of a file handle (v3) */
+#endif
+
+/*
+ * The fhandle is the file handle that the server passes to the client.
+ * All file operations are done using the file handles to refer to a file
+ * or a directory. The file handle can contain whatever information the
+ * server needs to distinguish an individual file.
+ */
+typedef opaque fhandle[FHSIZE];
+#ifdef WANT_NFS3
+typedef opaque fhandle3<FHSIZE3>;
+#endif
+
+/*
+ * If a status of zero is returned, the call completed successfully, and
+ * a file handle for the directory follows. A non-zero status indicates
+ * some sort of error. The status corresponds with UNIX error numbers.
+ */
+union fhstatus switch (unsigned fhs_status) {
+case 0:
+ fhandle fhs_fhandle;
+default:
+ void;
+};
+
+#ifdef WANT_NFS3
+/*
+ * Status codes returned by the version 3 mount call.
+ */
+enum mountstat3 {
+ MNT3_OK = 0, /* no error */
+ MNT3ERR_PERM = 1, /* Not owner */
+ MNT3ERR_NOENT = 2, /* No such file or directory */
+ MNT3ERR_IO = 5, /* I/O error */
+ MNT3ERR_ACCES = 13, /* Permission denied */
+ MNT3ERR_NOTDIR = 20, /* Not a directory */
+ MNT3ERR_INVAL = 22, /* Invalid argument */
+ MNT3ERR_NAMETOOLONG = 63, /* Filename too long */
+ MNT3ERR_NOTSUPP = 10004, /* Operation not supported */
+ MNT3ERR_SERVERFAULT = 10006 /* A failure on the server */
+};
+
+struct mountres3_ok {
+ fhandle3 fhandle;
+ int auth_flavors<>;
+};
+
+union mountres3 switch (mountstat3 fhs_status) {
+case 0:
+ mountres3_ok mountinfo;
+default:
+ void;
+};
+#endif
+
+/*
+ * The type dirpath is the pathname of a directory
+ */
+typedef string dirpath<MNTPATHLEN>;
+
+/*
+ * The type name is used for arbitrary names (hostnames, groupnames)
+ */
+typedef string name<MNTNAMLEN>;
+
+/*
+ * A list of who has what mounted
+ */
+typedef struct mountbody *mountlist;
+struct mountbody {
+ name ml_hostname;
+ dirpath ml_directory;
+ mountlist ml_next;
+};
+
+/*
+ * A list of netgroups
+ */
+typedef struct groupnode *groups;
+struct groupnode {
+ name gr_name;
+ groups gr_next;
+};
+
+/*
+ * A list of what is exported and to whom
+ */
+typedef struct exportnode *exports;
+struct exportnode {
+ dirpath ex_dir;
+ groups ex_groups;
+ exports ex_next;
+};
+
+program MOUNTPROG {
+ /*
+ * Version one of the mount protocol communicates with version two
+ * of the NFS protocol. Version three communicates with
+ * version three of the NFS protocol. The only connecting
+ * point is the fhandle structure, which is the same for both
+ * protocols.
+ */
+ version MOUNTVERS {
+ /*
+ * Does no work. It is made available in all RPC services
+ * to allow server reponse testing and timing
+ */
+ void
+ MOUNTPROC_NULL(void) = 0;
+
+ /*
+ * If fhs_status is 0, then fhs_fhandle contains the
+ * file handle for the directory. This file handle may
+ * be used in the NFS protocol. This procedure also adds
+ * a new entry to the mount list for this client mounting
+ * the directory.
+ * Unix authentication required.
+ */
+ fhstatus
+ MOUNTPROC_MNT(dirpath) = 1;
+
+ /*
+ * Returns the list of remotely mounted filesystems. The
+ * mountlist contains one entry for each hostname and
+ * directory pair.
+ */
+ mountlist
+ MOUNTPROC_DUMP(void) = 2;
+
+ /*
+ * Removes the mount list entry for the directory
+ * Unix authentication required.
+ */
+ void
+ MOUNTPROC_UMNT(dirpath) = 3;
+
+ /*
+ * Removes all of the mount list entries for this client
+ * Unix authentication required.
+ */
+ void
+ MOUNTPROC_UMNTALL(void) = 4;
+
+ /*
+ * Returns a list of all the exported filesystems, and which
+ * machines are allowed to import it.
+ */
+ exports
+ MOUNTPROC_EXPORT(void) = 5;
+
+ /*
+ * Identical to MOUNTPROC_EXPORT above
+ */
+ exports
+ MOUNTPROC_EXPORTALL(void) = 6;
+ } = 1;
+#ifdef WANT_NFS3
+ version MOUNTVERS3 {
+ /*
+ * Does no work. It is made available in all RPC services
+ * to allow server reponse testing and timing
+ */
+ void
+ MOUNTPROC_NULL(void) = 0;
+
+ /*
+ * If mountres3.fhs_status is MNT3_OK, then
+ * mountres3.mountinfo contains the file handle for
+ * the directory and a list of acceptable
+ * authentication flavors. This file handle may only
+ * be used in the NFS version 3 protocol. This
+ * procedure also results in the server adding a new
+ * entry to its mount list recording that this client
+ * has mounted the directory. AUTH_UNIX authentication
+ * or better is required.
+ */
+ mountres3
+ MOUNTPROC_MNT(dirpath) = 1;
+
+ /*
+ * Returns the list of remotely mounted filesystems. The
+ * mountlist contains one entry for each hostname and
+ * directory pair.
+ */
+ mountlist
+ MOUNTPROC_DUMP(void) = 2;
+
+ /*
+ * Removes the mount list entry for the directory
+ * Unix authentication required.
+ */
+ void
+ MOUNTPROC_UMNT(dirpath) = 3;
+
+ /*
+ * Removes all of the mount list entries for this client
+ * Unix authentication required.
+ */
+ void
+ MOUNTPROC_UMNTALL(void) = 4;
+
+ /*
+ * Returns a list of all the exported filesystems, and which
+ * machines are allowed to import it.
+ */
+ exports
+ MOUNTPROC_EXPORT(void) = 5;
+ } = 3;
+#endif
+} = 100005;
diff --git a/cpukit/librpc/include/rpcsvc/nfs_prot.x b/cpukit/librpc/include/rpcsvc/nfs_prot.x
new file mode 100644
index 0000000000..c1e592c1a1
--- /dev/null
+++ b/cpukit/librpc/include/rpcsvc/nfs_prot.x
@@ -0,0 +1,1265 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#ifndef RPC_HDR
+%#ifndef lint
+%/*static char sccsid[] = "from: @(#)nfs_prot.x 1.2 87/10/12 Copyr 1987 Sun Micro";*/
+%/*static char sccsid[] = "from: @(#)nfs_prot.x 2.1 88/08/01 4.0 RPCSRC";*/
+%static const char rcsid[] =
+% "$FreeBSD: src/include/rpcsvc/nfs_prot.x,v 1.7 1999/08/27 23:45:08 peter Exp $";
+%#endif /* not lint */
+#endif
+
+const NFS_PORT = 2049;
+const NFS_MAXDATA = 8192;
+const NFS_MAXPATHLEN = 1024;
+const NFS_MAXNAMLEN = 255;
+const NFS_FHSIZE = 32;
+const NFS_COOKIESIZE = 4;
+const NFS_FIFO_DEV = -1; /* size kludge for named pipes */
+
+/*
+ * File types
+ */
+const NFSMODE_FMT = 0170000; /* type of file */
+const NFSMODE_DIR = 0040000; /* directory */
+const NFSMODE_CHR = 0020000; /* character special */
+const NFSMODE_BLK = 0060000; /* block special */
+const NFSMODE_REG = 0100000; /* regular */
+const NFSMODE_LNK = 0120000; /* symbolic link */
+const NFSMODE_SOCK = 0140000; /* socket */
+const NFSMODE_FIFO = 0010000; /* fifo */
+
+/*
+ * Error status
+ */
+enum nfsstat {
+ NFS_OK= 0, /* no error */
+ NFSERR_PERM=1, /* Not owner */
+ NFSERR_NOENT=2, /* No such file or directory */
+ NFSERR_IO=5, /* I/O error */
+ NFSERR_NXIO=6, /* No such device or address */
+ NFSERR_ACCES=13, /* Permission denied */
+ NFSERR_EXIST=17, /* File exists */
+ NFSERR_NODEV=19, /* No such device */
+ NFSERR_NOTDIR=20, /* Not a directory*/
+ NFSERR_ISDIR=21, /* Is a directory */
+ NFSERR_FBIG=27, /* File too large */
+ NFSERR_NOSPC=28, /* No space left on device */
+ NFSERR_ROFS=30, /* Read-only file system */
+ NFSERR_NAMETOOLONG=63, /* File name too long */
+ NFSERR_NOTEMPTY=66, /* Directory not empty */
+ NFSERR_DQUOT=69, /* Disc quota exceeded */
+ NFSERR_STALE=70, /* Stale NFS file handle */
+ NFSERR_WFLUSH=99 /* write cache flushed */
+};
+
+/*
+ * File types
+ */
+enum ftype {
+ NFNON = 0, /* non-file */
+ NFREG = 1, /* regular file */
+ NFDIR = 2, /* directory */
+ NFBLK = 3, /* block special */
+ NFCHR = 4, /* character special */
+ NFLNK = 5, /* symbolic link */
+ NFSOCK = 6, /* unix domain sockets */
+ NFBAD = 7, /* unused */
+ NFFIFO = 8 /* named pipe */
+};
+
+/*
+ * File access handle
+ */
+struct nfs_fh {
+ opaque data[NFS_FHSIZE];
+};
+
+/*
+ * Timeval
+ */
+struct nfstime {
+ unsigned seconds;
+ unsigned useconds;
+};
+
+
+/*
+ * File attributes
+ */
+struct fattr {
+ ftype type; /* file type */
+ unsigned mode; /* protection mode bits */
+ unsigned nlink; /* # hard links */
+ unsigned uid; /* owner user id */
+ unsigned gid; /* owner group id */
+ unsigned size; /* file size in bytes */
+ unsigned blocksize; /* prefered block size */
+ unsigned rdev; /* special device # */
+ unsigned blocks; /* Kb of disk used by file */
+ unsigned fsid; /* device # */
+ unsigned fileid; /* inode # */
+ nfstime atime; /* time of last access */
+ nfstime mtime; /* time of last modification */
+ nfstime ctime; /* time of last change */
+};
+
+/*
+ * File attributes which can be set
+ */
+struct sattr {
+ unsigned mode; /* protection mode bits */
+ unsigned uid; /* owner user id */
+ unsigned gid; /* owner group id */
+ unsigned size; /* file size in bytes */
+ nfstime atime; /* time of last access */
+ nfstime mtime; /* time of last modification */
+};
+
+
+typedef string filename<NFS_MAXNAMLEN>;
+typedef string nfspath<NFS_MAXPATHLEN>;
+
+/*
+ * Reply status with file attributes
+ */
+union attrstat switch (nfsstat status) {
+case NFS_OK:
+ fattr attributes;
+default:
+ void;
+};
+
+struct sattrargs {
+ nfs_fh file;
+ sattr attributes;
+};
+
+/*
+ * Arguments for directory operations
+ */
+struct diropargs {
+ nfs_fh dir; /* directory file handle */
+ filename name; /* name (up to NFS_MAXNAMLEN bytes) */
+};
+
+struct diropokres {
+ nfs_fh file;
+ fattr attributes;
+};
+
+/*
+ * Results from directory operation
+ */
+union diropres switch (nfsstat status) {
+case NFS_OK:
+ diropokres diropres;
+default:
+ void;
+};
+
+union readlinkres switch (nfsstat status) {
+case NFS_OK:
+ nfspath data;
+default:
+ void;
+};
+
+/*
+ * Arguments to remote read
+ */
+struct readargs {
+ nfs_fh file; /* handle for file */
+ unsigned offset; /* byte offset in file */
+ unsigned count; /* immediate read count */
+ unsigned totalcount; /* total read count (from this offset)*/
+};
+
+/*
+ * Status OK portion of remote read reply
+ */
+struct readokres {
+ fattr attributes; /* attributes, need for pagin*/
+ opaque data<NFS_MAXDATA>;
+};
+
+union readres switch (nfsstat status) {
+case NFS_OK:
+ readokres reply;
+default:
+ void;
+};
+
+/*
+ * Arguments to remote write
+ */
+struct writeargs {
+ nfs_fh file; /* handle for file */
+ unsigned beginoffset; /* beginning byte offset in file */
+ unsigned offset; /* current byte offset in file */
+ unsigned totalcount; /* total write count (to this offset)*/
+ opaque data<NFS_MAXDATA>;
+};
+
+struct createargs {
+ diropargs where;
+ sattr attributes;
+};
+
+struct renameargs {
+ diropargs from;
+ diropargs to;
+};
+
+struct linkargs {
+ nfs_fh from;
+ diropargs to;
+};
+
+struct symlinkargs {
+ diropargs from;
+ nfspath to;
+ sattr attributes;
+};
+
+
+typedef opaque nfscookie[NFS_COOKIESIZE];
+
+/*
+ * Arguments to readdir
+ */
+struct readdirargs {
+ nfs_fh dir; /* directory handle */
+ nfscookie cookie;
+ unsigned count; /* number of directory bytes to read */
+};
+
+struct entry {
+ unsigned fileid;
+ filename name;
+ nfscookie cookie;
+ entry *nextentry;
+};
+
+struct dirlist {
+ entry *entries;
+ bool eof;
+};
+
+union readdirres switch (nfsstat status) {
+case NFS_OK:
+ dirlist reply;
+default:
+ void;
+};
+
+struct statfsokres {
+ unsigned tsize; /* preferred transfer size in bytes */
+ unsigned bsize; /* fundamental file system block size */
+ unsigned blocks; /* total blocks in file system */
+ unsigned bfree; /* free blocks in fs */
+ unsigned bavail; /* free blocks avail to non-superuser */
+};
+
+union statfsres switch (nfsstat status) {
+case NFS_OK:
+ statfsokres reply;
+default:
+ void;
+};
+
+#ifdef WANT_NFS3
+
+/*
+ * NFSv3 constants and types
+ */
+const NFS3_FHSIZE = 64; /* maximum size in bytes of a file handle */
+const NFS3_COOKIEVERFSIZE = 8; /* size of a cookie verifier for READDIR */
+const NFS3_CREATEVERFSIZE = 8; /* size of the verifier used for CREATE */
+const NFS3_WRITEVERFSIZE = 8; /* size of the verifier used for WRITE */
+
+typedef unsigned hyper uint64;
+typedef hyper int64;
+typedef unsigned long uint32;
+typedef long int32;
+typedef string filename3<>;
+typedef string nfspath3<>;
+typedef uint64 fileid3;
+typedef uint64 cookie3;
+typedef opaque cookieverf3[NFS3_COOKIEVERFSIZE];
+typedef opaque createverf3[NFS3_CREATEVERFSIZE];
+typedef opaque writeverf3[NFS3_WRITEVERFSIZE];
+typedef uint32 uid3;
+typedef uint32 gid3;
+typedef uint64 size3;
+typedef uint64 offset3;
+typedef uint32 mode3;
+typedef uint32 count3;
+
+/*
+ * Error status (v3)
+ */
+enum nfsstat3 {
+ NFS3_OK = 0,
+ NFS3ERR_PERM = 1,
+ NFS3ERR_NOENT = 2,
+ NFS3ERR_IO = 5,
+ NFS3ERR_NXIO = 6,
+ NFS3ERR_ACCES = 13,
+ NFS3ERR_EXIST = 17,
+ NFS3ERR_XDEV = 18,
+ NFS3ERR_NODEV = 19,
+ NFS3ERR_NOTDIR = 20,
+ NFS3ERR_ISDIR = 21,
+ NFS3ERR_INVAL = 22,
+ NFS3ERR_FBIG = 27,
+ NFS3ERR_NOSPC = 28,
+ NFS3ERR_ROFS = 30,
+ NFS3ERR_MLINK = 31,
+ NFS3ERR_NAMETOOLONG = 63,
+ NFS3ERR_NOTEMPTY = 66,
+ NFS3ERR_DQUOT = 69,
+ NFS3ERR_STALE = 70,
+ NFS3ERR_REMOTE = 71,
+ NFS3ERR_BADHANDLE = 10001,
+ NFS3ERR_NOT_SYNC = 10002,
+ NFS3ERR_BAD_COOKIE = 10003,
+ NFS3ERR_NOTSUPP = 10004,
+ NFS3ERR_TOOSMALL = 10005,
+ NFS3ERR_SERVERFAULT = 10006,
+ NFS3ERR_BADTYPE = 10007,
+ NFS3ERR_JUKEBOX = 10008
+};
+
+/*
+ * File types (v3)
+ */
+enum ftype3 {
+ NF3REG = 1, /* regular file */
+ NF3DIR = 2, /* directory */
+ NF3BLK = 3, /* block special */
+ NF3CHR = 4, /* character special */
+ NF3LNK = 5, /* symbolic link */
+ NF3SOCK = 6, /* unix domain sockets */
+ NF3FIFO = 7 /* named pipe */
+};
+
+struct specdata3 {
+ uint32 specdata1;
+ uint32 specdata2;
+};
+
+/*
+ * File access handle (v3)
+ */
+struct nfs_fh3 {
+ opaque data<NFS3_FHSIZE>;
+};
+
+/*
+ * Timeval (v3)
+ */
+struct nfstime3 {
+ uint32 seconds;
+ uint32 nseconds;
+};
+
+
+/*
+ * File attributes (v3)
+ */
+struct fattr3 {
+ ftype3 type; /* file type */
+ mode3 mode; /* protection mode bits */
+ uint32 nlink; /* # hard links */
+ uid3 uid; /* owner user id */
+ gid3 gid; /* owner group id */
+ size3 size; /* file size in bytes */
+ size3 used; /* prefered block size */
+ specdata3 rdev; /* special device # */
+ uint64 fsid; /* device # */
+ fileid3 fileid; /* inode # */
+ nfstime3 atime; /* time of last access */
+ nfstime3 mtime; /* time of last modification */
+ nfstime3 ctime; /* time of last change */
+};
+
+union post_op_attr switch (bool attributes_follow) {
+case TRUE:
+ fattr3 attributes;
+case FALSE:
+ void;
+};
+
+struct wcc_attr {
+ size3 size;
+ nfstime3 mtime;
+ nfstime3 ctime;
+};
+
+union pre_op_attr switch (bool attributes_follow) {
+case TRUE:
+ wcc_attr attributes;
+case FALSE:
+ void;
+};
+
+struct wcc_data {
+ pre_op_attr before;
+ post_op_attr after;
+};
+
+union post_op_fh3 switch (bool handle_follows) {
+case TRUE:
+ nfs_fh3 handle;
+case FALSE:
+ void;
+};
+
+/*
+ * File attributes which can be set (v3)
+ */
+enum time_how {
+ DONT_CHANGE = 0,
+ SET_TO_SERVER_TIME = 1,
+ SET_TO_CLIENT_TIME = 2
+};
+
+union set_mode3 switch (bool set_it) {
+case TRUE:
+ mode3 mode;
+default:
+ void;
+};
+
+union set_uid3 switch (bool set_it) {
+case TRUE:
+ uid3 uid;
+default:
+ void;
+};
+
+union set_gid3 switch (bool set_it) {
+case TRUE:
+ gid3 gid;
+default:
+ void;
+};
+
+union set_size3 switch (bool set_it) {
+case TRUE:
+ size3 size;
+default:
+ void;
+};
+
+union set_atime switch (time_how set_it) {
+case SET_TO_CLIENT_TIME:
+ nfstime3 atime;
+default:
+ void;
+};
+
+union set_mtime switch (time_how set_it) {
+case SET_TO_CLIENT_TIME:
+ nfstime3 mtime;
+default:
+ void;
+};
+
+struct sattr3 {
+ set_mode3 mode;
+ set_uid3 uid;
+ set_gid3 gid;
+ set_size3 size;
+ set_atime atime;
+ set_mtime mtime;
+};
+
+/*
+ * Arguments for directory operations (v3)
+ */
+struct diropargs3 {
+ nfs_fh3 dir; /* directory file handle */
+ filename3 name; /* name (up to NFS_MAXNAMLEN bytes) */
+};
+
+/*
+ * Arguments to getattr (v3).
+ */
+struct GETATTR3args {
+ nfs_fh3 object;
+};
+
+struct GETATTR3resok {
+ fattr3 obj_attributes;
+};
+
+union GETATTR3res switch (nfsstat3 status) {
+case NFS3_OK:
+ GETATTR3resok resok;
+default:
+ void;
+};
+
+/*
+ * Arguments to setattr (v3).
+ */
+union sattrguard3 switch (bool check) {
+case TRUE:
+ nfstime3 obj_ctime;
+case FALSE:
+ void;
+};
+
+struct SETATTR3args {
+ nfs_fh3 object;
+ sattr3 new_attributes;
+ sattrguard3 guard;
+};
+
+struct SETATTR3resok {
+ wcc_data obj_wcc;
+};
+
+struct SETATTR3resfail {
+ wcc_data obj_wcc;
+};
+
+union SETATTR3res switch (nfsstat3 status) {
+case NFS3_OK:
+ SETATTR3resok resok;
+default:
+ SETATTR3resfail resfail;
+};
+
+/*
+ * Arguments to lookup (v3).
+ */
+struct LOOKUP3args {
+ diropargs3 what;
+};
+
+struct LOOKUP3resok {
+ nfs_fh3 object;
+ post_op_attr obj_attributes;
+ post_op_attr dir_attributes;
+};
+
+struct LOOKUP3resfail {
+ post_op_attr dir_attributes;
+};
+
+union LOOKUP3res switch (nfsstat3 status) {
+case NFS3_OK:
+ LOOKUP3resok resok;
+default:
+ LOOKUP3resfail resfail;
+};
+
+/*
+ * Arguments to access (v3).
+ */
+const ACCESS3_READ = 0x0001;
+const ACCESS3_LOOKUP = 0x0002;
+const ACCESS3_MODIFY = 0x0004;
+const ACCESS3_EXTEND = 0x0008;
+const ACCESS3_DELETE = 0x0010;
+const ACCESS3_EXECUTE = 0x0020;
+
+struct ACCESS3args {
+ nfs_fh3 object;
+ uint32 access;
+};
+
+struct ACCESS3resok {
+ post_op_attr obj_attributes;
+ uint32 access;
+};
+
+struct ACCESS3resfail {
+ post_op_attr obj_attributes;
+};
+
+union ACCESS3res switch (nfsstat3 status) {
+case NFS3_OK:
+ ACCESS3resok resok;
+default:
+ ACCESS3resfail resfail;
+};
+
+/*
+ * Arguments to readlink (v3).
+ */
+struct READLINK3args {
+ nfs_fh3 symlink;
+};
+
+struct READLINK3resok {
+ post_op_attr symlink_attributes;
+ nfspath3 data;
+};
+
+struct READLINK3resfail {
+ post_op_attr symlink_attributes;
+};
+
+union READLINK3res switch (nfsstat3 status) {
+case NFS3_OK:
+ READLINK3resok resok;
+default:
+ READLINK3resfail resfail;
+};
+
+/*
+ * Arguments to read (v3).
+ */
+struct READ3args {
+ nfs_fh3 file;
+ offset3 offset;
+ count3 count;
+};
+
+struct READ3resok {
+ post_op_attr file_attributes;
+ count3 count;
+ bool eof;
+ opaque data<>;
+};
+
+struct READ3resfail {
+ post_op_attr file_attributes;
+};
+
+/* XXX: solaris 2.6 uses ``nfsstat'' here */
+union READ3res switch (nfsstat3 status) {
+case NFS3_OK:
+ READ3resok resok;
+default:
+ READ3resfail resfail;
+};
+
+/*
+ * Arguments to write (v3).
+ */
+enum stable_how {
+ UNSTABLE = 0,
+ DATA_SYNC = 1,
+ FILE_SYNC = 2
+};
+
+struct WRITE3args {
+ nfs_fh3 file;
+ offset3 offset;
+ count3 count;
+ stable_how stable;
+ opaque data<>;
+};
+
+struct WRITE3resok {
+ wcc_data file_wcc;
+ count3 count;
+ stable_how committed;
+ writeverf3 verf;
+};
+
+struct WRITE3resfail {
+ wcc_data file_wcc;
+};
+
+union WRITE3res switch (nfsstat3 status) {
+case NFS3_OK:
+ WRITE3resok resok;
+default:
+ WRITE3resfail resfail;
+};
+
+/*
+ * Arguments to create (v3).
+ */
+enum createmode3 {
+ UNCHECKED = 0,
+ GUARDED = 1,
+ EXCLUSIVE = 2
+};
+
+union createhow3 switch (createmode3 mode) {
+case UNCHECKED:
+case GUARDED:
+ sattr3 obj_attributes;
+case EXCLUSIVE:
+ createverf3 verf;
+};
+
+struct CREATE3args {
+ diropargs3 where;
+ createhow3 how;
+};
+
+struct CREATE3resok {
+ post_op_fh3 obj;
+ post_op_attr obj_attributes;
+ wcc_data dir_wcc;
+};
+
+struct CREATE3resfail {
+ wcc_data dir_wcc;
+};
+
+union CREATE3res switch (nfsstat3 status) {
+case NFS3_OK:
+ CREATE3resok resok;
+default:
+ CREATE3resfail resfail;
+};
+
+/*
+ * Arguments to mkdir (v3).
+ */
+struct MKDIR3args {
+ diropargs3 where;
+ sattr3 attributes;
+};
+
+struct MKDIR3resok {
+ post_op_fh3 obj;
+ post_op_attr obj_attributes;
+ wcc_data dir_wcc;
+};
+
+struct MKDIR3resfail {
+ wcc_data dir_wcc;
+};
+
+union MKDIR3res switch (nfsstat3 status) {
+case NFS3_OK:
+ MKDIR3resok resok;
+default:
+ MKDIR3resfail resfail;
+};
+
+/*
+ * Arguments to symlink (v3).
+ */
+struct symlinkdata3 {
+ sattr3 symlink_attributes;
+ nfspath3 symlink_data;
+};
+
+struct SYMLINK3args {
+ diropargs3 where;
+ symlinkdata3 symlink;
+};
+
+struct SYMLINK3resok {
+ post_op_fh3 obj;
+ post_op_attr obj_attributes;
+ wcc_data dir_wcc;
+};
+
+struct SYMLINK3resfail {
+ wcc_data dir_wcc;
+};
+
+union SYMLINK3res switch (nfsstat3 status) {
+case NFS3_OK:
+ SYMLINK3resok resok;
+default:
+ SYMLINK3resfail resfail;
+};
+
+/*
+ * Arguments to mknod (v3).
+ */
+struct devicedata3 {
+ sattr3 dev_attributes;
+ specdata3 spec;
+};
+
+union mknoddata3 switch (ftype3 type) {
+case NF3CHR:
+case NF3BLK:
+ devicedata3 device;
+case NF3SOCK:
+case NF3FIFO:
+ sattr3 pipe_attributes;
+default:
+ void;
+};
+
+struct MKNOD3args {
+ diropargs3 where;
+ mknoddata3 what;
+};
+
+struct MKNOD3resok {
+ post_op_fh3 obj;
+ post_op_attr obj_attributes;
+ wcc_data dir_wcc;
+};
+
+struct MKNOD3resfail {
+ wcc_data dir_wcc;
+};
+
+union MKNOD3res switch (nfsstat3 status) {
+case NFS3_OK:
+ MKNOD3resok resok;
+default:
+ MKNOD3resfail resfail;
+};
+
+/*
+ * Arguments to remove (v3).
+ */
+struct REMOVE3args {
+ diropargs3 object;
+};
+
+struct REMOVE3resok {
+ wcc_data dir_wcc;
+};
+
+struct REMOVE3resfail {
+ wcc_data dir_wcc;
+};
+
+union REMOVE3res switch (nfsstat3 status) {
+case NFS3_OK:
+ REMOVE3resok resok;
+default:
+ REMOVE3resfail resfail;
+};
+
+/*
+ * Arguments to rmdir (v3).
+ */
+struct RMDIR3args {
+ diropargs3 object;
+};
+
+struct RMDIR3resok {
+ wcc_data dir_wcc;
+};
+
+struct RMDIR3resfail {
+ wcc_data dir_wcc;
+};
+
+union RMDIR3res switch (nfsstat3 status) {
+case NFS3_OK:
+ RMDIR3resok resok;
+default:
+ RMDIR3resfail resfail;
+};
+
+/*
+ * Arguments to rename (v3).
+ */
+struct RENAME3args {
+ diropargs3 from;
+ diropargs3 to;
+};
+
+struct RENAME3resok {
+ wcc_data fromdir_wcc;
+ wcc_data todir_wcc;
+};
+
+struct RENAME3resfail {
+ wcc_data fromdir_wcc;
+ wcc_data todir_wcc;
+};
+
+union RENAME3res switch (nfsstat3 status) {
+case NFS3_OK:
+ RENAME3resok resok;
+default:
+ RENAME3resfail resfail;
+};
+
+/*
+ * Arguments to link (v3).
+ */
+struct LINK3args {
+ nfs_fh3 file;
+ diropargs3 link;
+};
+
+struct LINK3resok {
+ post_op_attr file_attributes;
+ wcc_data linkdir_wcc;
+};
+
+struct LINK3resfail {
+ post_op_attr file_attributes;
+ wcc_data linkdir_wcc;
+};
+
+union LINK3res switch (nfsstat3 status) {
+case NFS3_OK:
+ LINK3resok resok;
+default:
+ LINK3resfail resfail;
+};
+
+/*
+ * Arguments to readdir (v3).
+ */
+struct READDIR3args {
+ nfs_fh3 dir;
+ cookie3 cookie;
+ cookieverf3 cookieverf;
+ count3 count;
+};
+
+struct entry3 {
+ fileid3 fileid;
+ filename3 name;
+ cookie3 cookie;
+ entry3 *nextentry;
+};
+
+struct dirlist3 {
+ entry3 *entries;
+ bool eof;
+};
+
+struct READDIR3resok {
+ post_op_attr dir_attributes;
+ cookieverf3 cookieverf;
+ dirlist3 reply;
+};
+
+struct READDIR3resfail {
+ post_op_attr dir_attributes;
+};
+
+union READDIR3res switch (nfsstat3 status) {
+case NFS3_OK:
+ READDIR3resok resok;
+default:
+ READDIR3resfail resfail;
+};
+
+/*
+ * Arguments to readdirplus (v3).
+ */
+struct READDIRPLUS3args {
+ nfs_fh3 dir;
+ cookie3 cookie;
+ cookieverf3 cookieverf;
+ count3 dircount;
+ count3 maxcount;
+};
+
+struct entryplus3 {
+ fileid3 fileid;
+ filename3 name;
+ cookie3 cookie;
+ post_op_attr name_attributes;
+ post_op_fh3 name_handle;
+ entryplus3 *nextentry;
+};
+
+struct dirlistplus3 {
+ entryplus3 *entries;
+ bool eof;
+};
+
+struct READDIRPLUS3resok {
+ post_op_attr dir_attributes;
+ cookieverf3 cookieverf;
+ dirlistplus3 reply;
+};
+
+struct READDIRPLUS3resfail {
+ post_op_attr dir_attributes;
+};
+
+union READDIRPLUS3res switch (nfsstat3 status) {
+case NFS3_OK:
+ READDIRPLUS3resok resok;
+default:
+ READDIRPLUS3resfail resfail;
+};
+
+/*
+ * Arguments to fsstat (v3).
+ */
+struct FSSTAT3args {
+ nfs_fh3 fsroot;
+};
+
+struct FSSTAT3resok {
+ post_op_attr obj_attributes;
+ size3 tbytes;
+ size3 fbytes;
+ size3 abytes;
+ size3 tfiles;
+ size3 ffiles;
+ size3 afiles;
+ uint32 invarsec;
+};
+
+struct FSSTAT3resfail {
+ post_op_attr obj_attributes;
+};
+
+union FSSTAT3res switch (nfsstat3 status) {
+case NFS3_OK:
+ FSSTAT3resok resok;
+default:
+ FSSTAT3resfail resfail;
+};
+
+/*
+ * Arguments to fsinfo (v3).
+ */
+const FSF3_LINK = 0x0001;
+const FSF3_SYMLINK = 0x0002;
+const FSF3_HOMOGENEOUS = 0x0008;
+const FSF3_CANSETTIME = 0x0010;
+
+struct FSINFO3args {
+ nfs_fh3 fsroot;
+};
+
+struct FSINFO3resok {
+ post_op_attr obj_attributes;
+ uint32 rtmax;
+ uint32 rtpref;
+ uint32 rtmult;
+ uint32 wtmax;
+ uint32 wtpref;
+ uint32 wtmult;
+ uint32 dtpref;
+ size3 maxfilesize;
+ nfstime3 time_delta;
+ uint32 properties;
+};
+
+struct FSINFO3resfail {
+ post_op_attr obj_attributes;
+};
+
+union FSINFO3res switch (nfsstat3 status) {
+case NFS3_OK:
+ FSINFO3resok resok;
+default:
+ FSINFO3resfail resfail;
+};
+
+/*
+ * Arguments to pathconf (v3).
+ */
+struct PATHCONF3args {
+ nfs_fh3 object;
+};
+
+struct PATHCONF3resok {
+ post_op_attr obj_attributes;
+ uint32 linkmax;
+ uint32 name_max;
+ bool no_trunc;
+ bool chown_restricted;
+ bool case_insensitive;
+ bool case_preserving;
+};
+
+struct PATHCONF3resfail {
+ post_op_attr obj_attributes;
+};
+
+union PATHCONF3res switch (nfsstat3 status) {
+case NFS3_OK:
+ PATHCONF3resok resok;
+default:
+ PATHCONF3resfail resfail;
+};
+
+/*
+ * Arguments to commit (v3).
+ */
+struct COMMIT3args {
+ nfs_fh3 file;
+ offset3 offset;
+ count3 count;
+};
+
+struct COMMIT3resok {
+ wcc_data file_wcc;
+ writeverf3 verf;
+};
+
+struct COMMIT3resfail {
+ wcc_data file_wcc;
+};
+
+union COMMIT3res switch (nfsstat3 status) {
+case NFS3_OK:
+ COMMIT3resok resok;
+default:
+ COMMIT3resfail resfail;
+};
+
+#endif /* WANT_NFS3 */
+
+/*
+ * Remote file service routines
+ */
+program NFS_PROGRAM {
+ version NFS_VERSION {
+ void
+ NFSPROC_NULL(void) = 0;
+
+ attrstat
+ NFSPROC_GETATTR(nfs_fh) = 1;
+
+ attrstat
+ NFSPROC_SETATTR(sattrargs) = 2;
+
+ void
+ NFSPROC_ROOT(void) = 3;
+
+ diropres
+ NFSPROC_LOOKUP(diropargs) = 4;
+
+ readlinkres
+ NFSPROC_READLINK(nfs_fh) = 5;
+
+ readres
+ NFSPROC_READ(readargs) = 6;
+
+ void
+ NFSPROC_WRITECACHE(void) = 7;
+
+ attrstat
+ NFSPROC_WRITE(writeargs) = 8;
+
+ diropres
+ NFSPROC_CREATE(createargs) = 9;
+
+ nfsstat
+ NFSPROC_REMOVE(diropargs) = 10;
+
+ nfsstat
+ NFSPROC_RENAME(renameargs) = 11;
+
+ nfsstat
+ NFSPROC_LINK(linkargs) = 12;
+
+ nfsstat
+ NFSPROC_SYMLINK(symlinkargs) = 13;
+
+ diropres
+ NFSPROC_MKDIR(createargs) = 14;
+
+ nfsstat
+ NFSPROC_RMDIR(diropargs) = 15;
+
+ readdirres
+ NFSPROC_READDIR(readdirargs) = 16;
+
+ statfsres
+ NFSPROC_STATFS(nfs_fh) = 17;
+ } = 2;
+} = 100003;
+#ifdef WANT_NFS3
+program NFS3_PROGRAM {
+ version NFS_V3 {
+ void
+ NFSPROC3_NULL(void) = 0;
+
+ GETATTR3res
+ NFSPROC3_GETATTR(GETATTR3args) = 1;
+
+ SETATTR3res
+ NFSPROC3_SETATTR(SETATTR3args) = 2;
+
+ LOOKUP3res
+ NFSPROC3_LOOKUP(LOOKUP3args) = 3;
+
+ ACCESS3res
+ NFSPROC3_ACCESS(ACCESS3args) = 4;
+
+ READLINK3res
+ NFSPROC3_READLINK(READLINK3args) = 5;
+
+ READ3res
+ NFSPROC3_READ(READ3args) = 6;
+
+ WRITE3res
+ NFSPROC3_WRITE(WRITE3args) = 7;
+
+ CREATE3res
+ NFSPROC3_CREATE(CREATE3args) = 8;
+
+ MKDIR3res
+ NFSPROC3_MKDIR(MKDIR3args) = 9;
+
+ SYMLINK3res
+ NFSPROC3_SYMLINK(SYMLINK3args) = 10;
+
+ MKNOD3res
+ NFSPROC3_MKNOD(MKNOD3args) = 11;
+
+ REMOVE3res
+ NFSPROC3_REMOVE(REMOVE3args) = 12;
+
+ RMDIR3res
+ NFSPROC3_RMDIR(RMDIR3args) = 13;
+
+ RENAME3res
+ NFSPROC3_RENAME(RENAME3args) = 14;
+
+ LINK3res
+ NFSPROC3_LINK(LINK3args) = 15;
+
+ READDIR3res
+ NFSPROC3_READDIR(READDIR3args) = 16;
+
+ READDIRPLUS3res
+ NFSPROC3_READDIRPLUS(READDIRPLUS3args) = 17;
+
+ FSSTAT3res
+ NFSPROC3_FSSTAT(FSSTAT3args) = 18;
+
+ FSINFO3res
+ NFSPROC3_FSINFO(FSINFO3args) = 19;
+
+ PATHCONF3res
+ NFSPROC3_PATHCONF(PATHCONF3args) = 20;
+
+ COMMIT3res
+ NFSPROC3_COMMIT(COMMIT3args) = 21;
+ } = 3;
+} = 100003;
+#endif
diff --git a/cpukit/librpc/include/rpcsvc/nis.x b/cpukit/librpc/include/rpcsvc/nis.x
new file mode 100644
index 0000000000..ba6c6d1576
--- /dev/null
+++ b/cpukit/librpc/include/rpcsvc/nis.x
@@ -0,0 +1,466 @@
+%/*
+% * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+% * unrestricted use provided that this legend is included on all tape
+% * media and as a part of the software program in whole or part. Users
+% * may copy or modify Sun RPC without charge, but are not authorized
+% * to license or distribute it to anyone else except as part of a product or
+% * program developed by the user or with the express written consent of
+% * Sun Microsystems, Inc.
+% *
+% * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+% * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+% * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+% *
+% * Sun RPC is provided with no support and without any obligation on the
+% * part of Sun Microsystems, Inc. to assist in its use, correction,
+% * modification or enhancement.
+% *
+% * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+% * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+% * OR ANY PART THEREOF.
+% *
+% * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+% * or profits or other special, indirect and consequential damages, even if
+% * Sun has been advised of the possibility of such damages.
+% *
+% * Sun Microsystems, Inc.
+% * 2550 Garcia Avenue
+% * Mountain View, California 94043
+% */
+
+#ifndef RPC_HDR
+%#ifndef lint
+%static const char rcsid[] =
+% "$FreeBSD: src/include/rpcsvc/nis.x,v 1.3 1999/08/27 23:45:09 peter Exp $";
+%#endif /* not lint */
+#endif
+
+/*
+ * From 4.1 : @(#)nis.x 1.61 Copyright 1989 Sun Microsystems
+ *
+ * RPC Language Protocol description file for NIS Plus
+ * This version : 1.61
+ * Last Modified : 3/19/91
+ */
+#ifdef RPC_HDR
+%/*
+% * nis.h
+% *
+% * This file is the main include file for NIS clients. It contains
+% * both the client library function defines and the various data
+% * structures used by the NIS service. It includes the file nis_tags.h
+% * which defines the tag values. This allows the tags to change without
+% * having to change the nis.x file.
+% *
+% * NOTE : DO NOT EDIT THIS FILE! It is automatically generated when
+% * rpcgen is run on the nis.x file. Note that there is a
+% * simple sed script to remove some unneeded lines. (See the
+% * Makefile target nis.h)
+% *
+% */
+%#include <rpcsvc/nis_tags.h>
+#endif
+
+/* This gets stuffed into the source files. */
+#if RPC_HDR
+%#include <rpc/xdr.h>
+#endif
+/*
+ * This is just pointless.
+ */
+#ifdef SUN_STUPIDITY
+#if RPC_SVC
+%#include "nis_svc.h"
+#endif
+#endif
+
+/* Include the RPC Language description of NIS objects */
+#include "nis_object.x"
+
+/* Errors that can be returned by the service */
+enum nis_error {
+ NIS_SUCCESS = 0, /* A-ok, let's rock n roll */
+ NIS_S_SUCCESS = 1, /* Name found (maybe) */
+ NIS_NOTFOUND = 2, /* Name definitely not found */
+ NIS_S_NOTFOUND = 3, /* Name maybe not found */
+ NIS_CACHEEXPIRED = 4, /* Name exists but cache out of date */
+ NIS_NAMEUNREACHABLE = 5, /* Can't get there from here */
+ NIS_UNKNOWNOBJ = 6, /* Object type is bogus */
+ NIS_TRYAGAIN = 7, /* I'm busy, call back */
+ NIS_SYSTEMERROR = 8, /* Out of band failure */
+ NIS_CHAINBROKEN = 9, /* First/Next warning */
+ NIS_PERMISSION = 10, /* Not enough permission to access */
+ NIS_NOTOWNER = 11, /* You don't own it, sorry */
+ NIS_NOT_ME = 12, /* I don't serve this name */
+ NIS_NOMEMORY = 13, /* Outta VM! Help! */
+ NIS_NAMEEXISTS = 14, /* Can't create over another name */
+ NIS_NOTMASTER = 15, /* I'm justa secondaray, don't ask me */
+ NIS_INVALIDOBJ = 16, /* Object is broken somehow */
+ NIS_BADNAME = 17, /* Unparsable name */
+ NIS_NOCALLBACK = 18, /* Couldn't talk to call back proc */
+ NIS_CBRESULTS = 19, /* Results being called back to you */
+ NIS_NOSUCHNAME = 20, /* Name unknown */
+ NIS_NOTUNIQUE = 21, /* Value is not uniques (entry) */
+ NIS_IBMODERROR = 22, /* Inf. Base. Modify error. */
+ NIS_NOSUCHTABLE = 23, /* Name for table was wrong */
+ NIS_TYPEMISMATCH = 24, /* Entry and table type mismatch */
+ NIS_LINKNAMEERROR = 25, /* Link points to bogus name */
+ NIS_PARTIAL = 26, /* Partial success, found table */
+ NIS_TOOMANYATTRS = 27, /* Too many attributes */
+ NIS_RPCERROR = 28, /* RPC error encountered */
+ NIS_BADATTRIBUTE = 29, /* Bad or invalid attribute */
+ NIS_NOTSEARCHABLE = 30, /* Non-searchable object searched */
+ NIS_CBERROR = 31, /* Error during callback (svc crash) */
+ NIS_FOREIGNNS = 32, /* Foreign Namespace */
+ NIS_BADOBJECT = 33, /* Malformed object structure */
+ NIS_NOTSAMEOBJ = 34, /* Object swapped during deletion */
+ NIS_MODFAIL = 35, /* Failure during a Modify. */
+ NIS_BADREQUEST = 36, /* Illegal query for table */
+ NIS_NOTEMPTY = 37, /* Attempt to remove a non-empty tbl */
+ NIS_COLDSTART_ERR = 38, /* Error accesing the cold start file */
+ NIS_RESYNC = 39, /* Transaction log too far out of date */
+ NIS_FAIL = 40, /* NIS operation failed. */
+ NIS_UNAVAIL = 41, /* NIS+ service is unavailable (client) */
+ NIS_RES2BIG = 42, /* NIS+ result too big for datagram */
+ NIS_SRVAUTH = 43, /* NIS+ server wasn't authenticated. */
+ NIS_CLNTAUTH = 44, /* NIS+ Client wasn't authenticated. */
+ NIS_NOFILESPACE = 45, /* NIS+ server ran out of disk space */
+ NIS_NOPROC = 46, /* NIS+ server couldn't create new proc */
+ NIS_DUMPLATER = 47 /* NIS+ server already has dump child */
+};
+
+
+/*
+ * Structure definitions for the parameters and results of the actual
+ * NIS RPC calls.
+ *
+ * This is the standard result (in the protocol) of most of the nis
+ * requests.
+ */
+
+struct nis_result {
+ nis_error status; /* Status of the response */
+ nis_object objects<>; /* objects found */
+ netobj cookie; /* Cookie Data */
+ u_long zticks; /* server ticks */
+ u_long dticks; /* DBM ticks. */
+ u_long aticks; /* Cache (accel) ticks */
+ u_long cticks; /* Client ticks */
+};
+
+/*
+ * A Name Service request
+ * This request is used to access the name space, ns_name is the name
+ * of the object within the namespace and the object is it's value, for
+ * add/modify, a copy of the original for remove.
+ */
+
+struct ns_request {
+ nis_name ns_name; /* Name in the NIS name space */
+ nis_object ns_object<1>; /* Optional Object (add/remove) */
+};
+
+/*
+ * An information base request
+ * This request includes the NIS name of the table we wish to search, the
+ * search criteria in the form of attribute/value pairs and an optional
+ * callback program number. If the callback program number is provided
+ * the server will send back objects one at a time, otherwise it will
+ * return them all in the response.
+ */
+
+struct ib_request {
+ nis_name ibr_name; /* The name of the Table */
+ nis_attr ibr_srch<>; /* The search critereia */
+ u_long ibr_flags; /* Optional flags */
+ nis_object ibr_obj<1>; /* optional object (add/modify) */
+ nis_server ibr_cbhost<1>; /* Optional callback info */
+ u_long ibr_bufsize; /* Optional first/next bufsize */
+ netobj ibr_cookie; /* The first/next cookie */
+};
+
+/*
+ * This argument to the PING call notifies the replicas that something in
+ * a directory has changed and this is it's timestamp. The replica will use
+ * the timestamp to determine if its resync operation was successful.
+ */
+struct ping_args {
+ nis_name dir; /* Directory that had the change */
+ u_long stamp; /* timestamp of the transaction */
+};
+
+/*
+ * These are the type of entries that are stored in the transaction log,
+ * note that modifications will appear as two entries, for names, they have
+ * a "OLD" entry followed by a "NEW" entry. For entries in tables, there
+ * is a remove followed by an add. It is done this way so that we can read
+ * the log backwards to back out transactions and forwards to propogate
+ * updated.
+ */
+enum log_entry_t {
+ LOG_NOP = 0,
+ ADD_NAME = 1, /* Name Added to name space */
+ REM_NAME = 2, /* Name removed from name space */
+ MOD_NAME_OLD = 3, /* Name was modified in the name space */
+ MOD_NAME_NEW = 4, /* Name was modified in the name space */
+ ADD_IBASE = 5, /* Entry added to information base */
+ REM_IBASE = 6, /* Entry removed from information base */
+ MOD_IBASE = 7, /* Entry was modified in information base */
+ UPD_STAMP = 8 /* Update timestamp (used as fenceposts) */
+};
+
+/*
+ * This result is returned from the name service when it is requested to
+ * dump logged entries from its transaction log. Information base updates
+ * will have the name of the information base in the le_name field and
+ * a canonical set of attribute/value pairs to fully specify the entry's
+ * 'name'.
+ */
+struct log_entry {
+ u_long le_time; /* Time in seconds */
+ log_entry_t le_type; /* Type of log entry */
+ nis_name le_princp; /* Principal making the change */
+ nis_name le_name; /* Name of table/dir involved */
+ nis_attr le_attrs<>; /* List of AV pairs. */
+ nis_object le_object; /* Actual object value */
+};
+
+struct log_result {
+ nis_error lr_status; /* The status itself */
+ netobj lr_cookie; /* Used by the dump callback */
+ log_entry lr_entries<>; /* zero or more entries */
+};
+
+struct cp_result {
+ nis_error cp_status; /* Status of the checkpoint */
+ u_long cp_zticks; /* Service 'ticks' */
+ u_long cp_dticks; /* Database 'ticks' */
+};
+
+/*
+ * This structure defines a generic NIS tag list. The taglist contains
+ * zero or tags, each of which is a type and a value. (u_long).
+ * These are used to report statistics (see tag definitions below)
+ * and to set or reset state variables.
+ */
+struct nis_tag {
+ u_long tag_type; /* Statistic tag (may vary) */
+ string tag_val<1024>; /* Statistic value may also vary */
+};
+
+struct nis_taglist {
+ nis_tag tags<>; /* List of tags */
+};
+
+struct dump_args {
+ nis_name da_dir; /* Directory to dump */
+ u_long da_time; /* From this timestamp */
+ nis_server da_cbhost<1>; /* Callback to use. */
+};
+
+struct fd_args {
+ nis_name dir_name; /* The directory we're looking for */
+ nis_name requester; /* Host principal name for signature */
+};
+
+struct fd_result {
+ nis_error status; /* Status returned by function */
+ nis_name source; /* Source of this answer */
+ opaque dir_data<>; /* Directory Data (XDR'ed) */
+ opaque signature<>; /* Signature of the source */
+};
+
+
+/*
+ * What's going on here? Well, it's like this. When the service
+ * is being compiled it wants to have the service definition specific
+ * info included, and when the client is being compiled it wants that
+ * info. This includes the appropriate file which was generated by
+ * make in the protocols directory (probably /usr/include/rpcsvc).
+ *
+ * Uhm... guys? With RPC, you aren't supposed to have seperate
+ * server-specific and client-specific header files. You have one header
+ * file that's suitable for both. If your code doesn't work using just
+ * the one header file, I submit to you that it's broken.
+ * -Bill
+ */
+#ifdef SUN_STUPIDITY
+#ifdef RPC_SVC
+%#include "nis_svc.h"
+#endif
+#ifdef RPC_CLNT
+%#include "nis_clnt.h"
+#endif
+#endif
+
+program NIS_PROG {
+
+ /* RPC Language description of the NIS+ protocol */
+ version NIS_VERSION {
+ /* The name service functions */
+ nis_result NIS_LOOKUP(ns_request) = 1;
+ nis_result NIS_ADD(ns_request) = 2;
+ nis_result NIS_MODIFY(ns_request) = 3;
+ nis_result NIS_REMOVE(ns_request) = 4;
+
+ /* The information base functions */
+ nis_result NIS_IBLIST(ib_request) = 5;
+ nis_result NIS_IBADD(ib_request) = 6;
+ nis_result NIS_IBMODIFY(ib_request) = 7;
+ nis_result NIS_IBREMOVE(ib_request) = 8;
+ nis_result NIS_IBFIRST(ib_request) = 9;
+ nis_result NIS_IBNEXT(ib_request) = 10;
+
+ /* NIS Administrative functions */
+ fd_result NIS_FINDDIRECTORY(fd_args) = 12;
+
+ /* If fetch and optionally reset statistics */
+ nis_taglist NIS_STATUS(nis_taglist) = 14;
+
+ /* Dump changes to directory since time in da_time */
+ log_result NIS_DUMPLOG(dump_args) = 15;
+
+ /* Dump contents of directory named */
+ log_result NIS_DUMP(dump_args) = 16;
+
+ /* Check status of callback thread */
+ bool NIS_CALLBACK(netobj) = 17;
+
+ /* Return last update time for named dir */
+ u_long NIS_CPTIME(nis_name) = 18;
+
+ /* Checkpoint directory or table named */
+ cp_result NIS_CHECKPOINT(nis_name) = 19;
+
+ /* Send 'status changed' ping to replicates */
+ void NIS_PING(ping_args) = 20;
+
+ /* Modify server behaviour (such as debugging) */
+ nis_taglist NIS_SERVSTATE(nis_taglist) = 21;
+
+ /* Create a Directory */
+ nis_error NIS_MKDIR(nis_name) = 22;
+
+ /* Remove a Directory */
+ nis_error NIS_RMDIR(nis_name) = 23;
+
+ /* Update public keys of a directory object */
+ nis_error NIS_UPDKEYS(nis_name) = 24;
+ } = 3;
+} = 100300;
+
+/*
+ * Included below are the defines that become part of nis.h,
+ * they are technically not part of the protocol, but do define
+ * key aspects of the implementation and are therefore useful
+ * in building a conforming server or client.
+ */
+#if RPC_HDR
+%/*
+% * Generic "hash" datastructures, used by all types of hashed data.
+% */
+%struct nis_hash_data {
+% nis_name name; /* NIS name of hashed item */
+% int keychain; /* It's hash key (for pop) */
+% struct nis_hash_data *next; /* Hash collision pointer */
+% struct nis_hash_data *prv_item; /* A serial, doubly linked list */
+% struct nis_hash_data *nxt_item; /* of items in the hash table */
+%};
+%typedef struct nis_hash_data NIS_HASH_ITEM;
+%
+%struct nis_hash_table {
+% NIS_HASH_ITEM *keys[64]; /* A hash table of items */
+% NIS_HASH_ITEM *first; /* The first "item" in serial list */
+%};
+%typedef struct nis_hash_table NIS_HASH_TABLE;
+%
+%/* Structure for storing dynamically allocated static data */
+%struct nis_sdata {
+% void *buf; /* Memory allocation pointer */
+% u_long size; /* Buffer size */
+%};
+%
+%/* Generic client creating flags */
+%#define ZMH_VC 1
+%#define ZMH_DG 2
+%#define ZMH_AUTH 4
+%
+%/* Testing Access rights for objects */
+%
+%#define NIS_READ_ACC 1
+%#define NIS_MODIFY_ACC 2
+%#define NIS_CREATE_ACC 4
+%#define NIS_DESTROY_ACC 8
+%/* Test macros. a == access rights, m == desired rights. */
+%#define WORLD(a, m) (((a) & (m)) != 0)
+%#define GROUP(a, m) (((a) & ((m) << 8)) != 0)
+%#define OWNER(a, m) (((a) & ((m) << 16)) != 0)
+%#define NOBODY(a, m) (((a) & ((m) << 24)) != 0)
+%
+%#define OATYPE(d, n) (((d)->do_armask.do_armask_val+n)->oa_otype)
+%#define OARIGHTS(d, n) (((d)->do_armask.do_armask_val+n)->oa_rights)
+%#define WORLD_DEFAULT (NIS_READ_ACC)
+%#define GROUP_DEFAULT (NIS_READ_ACC << 8)
+%#define OWNER_DEFAULT ((NIS_READ_ACC +\
+ NIS_MODIFY_ACC +\
+ NIS_CREATE_ACC +\
+ NIS_DESTROY_ACC) << 16)
+%#define DEFAULT_RIGHTS (WORLD_DEFAULT | GROUP_DEFAULT | OWNER_DEFAULT)
+%
+%/* Result manipulation defines ... */
+%#define NIS_RES_NUMOBJ(x) ((x)->objects.objects_len)
+%#define NIS_RES_OBJECT(x) ((x)->objects.objects_val)
+%#define NIS_RES_COOKIE(x) ((x)->cookie)
+%#define NIS_RES_STATUS(x) ((x)->status)
+%
+%/* These defines make getting at the variant part of the object easier. */
+%#define TA_data zo_data.objdata_u.ta_data
+%#define EN_data zo_data.objdata_u.en_data
+%#define DI_data zo_data.objdata_u.di_data
+%#define LI_data zo_data.objdata_u.li_data
+%#define GR_data zo_data.objdata_u.gr_data
+%
+%#define __type_of(o) ((o)->zo_data.zo_type)
+%
+%/* Declarations for the internal subroutines in nislib.c */
+%enum name_pos {SAME_NAME, HIGHER_NAME, LOWER_NAME, NOT_SEQUENTIAL, BAD_NAME};
+%typedef enum name_pos name_pos;
+%
+%/*
+% * Defines for getting at column data in entry objects. Because RPCGEN
+% * generates some rather wordy structures, we create some defines that
+% * collapse the needed keystrokes to access a particular value using
+% * these definitions they take an nis_object *, and an int and return
+% * a u_char * for Value, and an int for length.
+% */
+%#define ENTRY_VAL(obj, col) \
+ (obj)->EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val
+%#define ENTRY_LEN(obj, col) \
+ (obj)->EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len
+%
+%#ifdef __cplusplus
+%}
+%#endif
+%
+%/* Prototypes, and extern declarations for the NIS library functions. */
+%#include <rpcsvc/nislib.h>
+%#endif /* __NIS_RPCGEN_H */
+%/* EDIT_START */
+%
+%/*
+% * nis_3.h
+% *
+% * This file contains definitions that are only of interest to the actual
+% * service daemon and client stubs. Normal users of NIS will not include
+% * this file.
+% *
+% * NOTE : This include file is automatically created by a combination
+% * of rpcgen and sed. DO NOT EDIT IT, change the nis.x file instead
+% * and then remake this file.
+% */
+%#ifndef __nis_3_h
+%#define __nis_3_h
+%#ifdef __cplusplus
+%extern "C" {
+%#endif
+#endif
diff --git a/cpukit/librpc/include/rpcsvc/nis_cache.x b/cpukit/librpc/include/rpcsvc/nis_cache.x
new file mode 100644
index 0000000000..8343cfd050
--- /dev/null
+++ b/cpukit/librpc/include/rpcsvc/nis_cache.x
@@ -0,0 +1,87 @@
+%/*
+% * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+% * unrestricted use provided that this legend is included on all tape
+% * media and as a part of the software program in whole or part. Users
+% * may copy or modify Sun RPC without charge, but are not authorized
+% * to license or distribute it to anyone else except as part of a product or
+% * program developed by the user or with the express written consent of
+% * Sun Microsystems, Inc.
+% *
+% * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+% * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+% * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+% *
+% * Sun RPC is provided with no support and without any obligation on the
+% * part of Sun Microsystems, Inc. to assist in its use, correction,
+% * modification or enhancement.
+% *
+% * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+% * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+% * OR ANY PART THEREOF.
+% *
+% * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+% * or profits or other special, indirect and consequential damages, even if
+% * Sun has been advised of the possibility of such damages.
+% *
+% * Sun Microsystems, Inc.
+% * 2550 Garcia Avenue
+% * Mountain View, California 94043
+% */
+
+/*
+ * nis_cache.x
+ *
+ * Copyright (c) 1988-1992 Sun Microsystems Inc
+ * All Rights Reserved.
+ */
+
+/* From: %#pragma ident "@(#)nis_cache.x 1.11 94/05/03 SMI" */
+
+#ifndef RPC_HDR
+%#ifndef lint
+%static const char rcsid[] =
+% "$FreeBSD: src/include/rpcsvc/nis_cache.x,v 1.3 1999/08/27 23:45:09 peter Exp $";
+%#endif /* not lint */
+#endif
+
+#ifdef RPC_HDR
+%#include <rpc/types.h>
+%#include <rpcsvc/nis.h>
+%
+%/* default cache file */
+%#define CACHEFILE "/var/nis/NIS_SHARED_DIRCACHE"
+%
+%/* clients have to read-lock the cache file, and SVR4 locking requires that */
+%/* the file be writable, but we don't want a world-writable cache file. */
+%/* So... everyone agrees to use a different, world-writable file for the */
+%/* locking operations, but the data is in CACHEFILE. */
+%#define CACHELOCK "/usr/tmp/.NIS_DIR_CACHELOCK"
+%
+%/* the file containing one trusted XDR'ed directory object.
+% * This has to be present for the system to work.
+% */
+%#define COLD_START_FILE "/var/nis/NIS_COLD_START"
+%
+%enum pc_status {HIT, MISS, NEAR_MISS};
+%
+%extern int __nis_debuglevel;
+%
+%
+#endif
+
+#ifdef RPC_CLNT
+#ifdef SOLARIS
+%#include "../gen/nis_clnt.h"
+#else
+%#include "nis.h"
+#endif
+#endif
+
+program CACHEPROG {
+ version CACHE_VER_1 {
+ void NIS_CACHE_ADD_ENTRY(fd_result) = 1;
+ void NIS_CACHE_REMOVE_ENTRY(directory_obj) = 2;
+ void NIS_CACHE_READ_COLDSTART(void) = 3;
+ void NIS_CACHE_REFRESH_ENTRY(string<>) = 4;
+ } = 1;
+} = 100301;
diff --git a/cpukit/librpc/include/rpcsvc/nis_callback.x b/cpukit/librpc/include/rpcsvc/nis_callback.x
new file mode 100644
index 0000000000..4e74aa0a2e
--- /dev/null
+++ b/cpukit/librpc/include/rpcsvc/nis_callback.x
@@ -0,0 +1,76 @@
+%/*
+% * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+% * unrestricted use provided that this legend is included on all tape
+% * media and as a part of the software program in whole or part. Users
+% * may copy or modify Sun RPC without charge, but are not authorized
+% * to license or distribute it to anyone else except as part of a product or
+% * program developed by the user or with the express written consent of
+% * Sun Microsystems, Inc.
+% *
+% * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+% * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+% * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+% *
+% * Sun RPC is provided with no support and without any obligation on the
+% * part of Sun Microsystems, Inc. to assist in its use, correction,
+% * modification or enhancement.
+% *
+% * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+% * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+% * OR ANY PART THEREOF.
+% *
+% * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+% * or profits or other special, indirect and consequential damages, even if
+% * Sun has been advised of the possibility of such damages.
+% *
+% * Sun Microsystems, Inc.
+% * 2550 Garcia Avenue
+% * Mountain View, California 94043
+% */
+
+/*
+ * nis_callback.x
+ *
+ * Copyright (c) 1988-1992 Sun Microsystems Inc
+ * All Rights Reserved.
+ */
+
+/* From: %#pragma ident "@(#)nis_callback.x 1.7 94/05/03 SMI" */
+
+#ifndef RPC_HDR
+%#ifndef lint
+%static const char rcsid[] =
+% "$FreeBSD: src/include/rpcsvc/nis_callback.x,v 1.3 1999/08/27 23:45:09 peter Exp $";
+%#endif /* not lint */
+#endif
+
+/*
+ * "@(#)zns_cback.x 1.2 90/09/10 Copyr 1990 Sun Micro"
+ *
+ * RPCL description of the Callback Service.
+ */
+
+#ifdef RPC_HDR
+%#include <rpcsvc/nis.h>
+#endif
+#ifdef RPC_XDR
+#ifdef SOLARIS
+%#include "nis_clnt.h"
+#else
+%#include "nis.h"
+#endif
+#endif
+
+typedef nis_object *obj_p;
+
+struct cback_data {
+ obj_p entries<>; /* List of objects */
+};
+
+program CB_PROG {
+ version CB_VERS {
+ bool CBPROC_RECEIVE(cback_data) = 1;
+ void CBPROC_FINISH(void) = 2;
+ void CBPROC_ERROR(nis_error) = 3;
+ } = 1;
+} = 100302;
diff --git a/cpukit/librpc/include/rpcsvc/nis_db.h b/cpukit/librpc/include/rpcsvc/nis_db.h
new file mode 100644
index 0000000000..dbdee5aac8
--- /dev/null
+++ b/cpukit/librpc/include/rpcsvc/nis_db.h
@@ -0,0 +1,162 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ *
+ * $FreeBSD: src/include/rpcsvc/nis_db.h,v 1.5 1999/08/27 23:45:09 peter Exp $
+ */
+
+/*
+ * Copyright (c) 1991, by Sun Microsystems Inc.
+ */
+
+/*
+ * This header file defines the interface to the NIS database. All
+ * implementations of the database must export at least these routines.
+ * They must also follow the conventions set herein. See the implementors
+ * guide for specific semantics that are required.
+ */
+
+#ifndef _RPCSVC_NIS_DB_H
+#define _RPCSVC_NIS_DB_H
+
+
+/* From: #pragma ident "@(#)nis_db.h 1.8 94/05/03 SMI" */
+
+/*
+ * Note: although the version of <rpcsvc/nis_db.h> shipped with Solaris
+ * 2.5/2.5.x is actually older than this one (according to the ident
+ * string), it contains changes and a few added functions. Those changes
+ * have been hand merged into this file to bring it up to date.
+ */
+
+#include <rpc/rpc.h>
+#include <rpcsvc/nis.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum db_status {
+ DB_SUCCESS = 0,
+ DB_NOTFOUND = 1,
+ DB_NOTUNIQUE = 2,
+ DB_BADTABLE = 3,
+ DB_BADQUERY = 4,
+ DB_BADOBJECT = 5,
+ DB_MEMORY_LIMIT = 6,
+ DB_STORAGE_LIMIT = 7,
+ DB_INTERNAL_ERROR = 8
+};
+typedef enum db_status db_status;
+
+enum db_action {
+ DB_LOOKUP = 0,
+ DB_REMOVE = 1,
+ DB_ADD = 2,
+ DB_FIRST = 3,
+ DB_NEXT = 4,
+ DB_ALL = 5,
+ DB_RESET_NEXT = 6
+};
+typedef enum db_action db_action;
+
+typedef entry_obj *entry_object_p;
+
+typedef struct {
+ u_int db_next_desc_len;
+ char *db_next_desc_val;
+} db_next_desc;
+
+struct db_result {
+ db_status status;
+ db_next_desc nextinfo;
+ struct {
+ u_int objects_len;
+ entry_object_p *objects_val;
+ } objects;
+ long ticks;
+};
+typedef struct db_result db_result;
+
+/*
+ * Prototypes for the database functions.
+ */
+
+#if (__STDC__)
+
+extern bool_t db_initialize(char *);
+#ifdef ORIGINAL_DECLS
+extern bool_t db_create_table(char *, table_obj *);
+extern bool_t db_destroy_table(char *);
+#else
+extern db_status db_create_table(char *, table_obj *);
+extern db_status db_destroy_table(char *);
+#endif
+extern db_result *db_first_entry(char *, int, nis_attr *);
+extern db_result *db_next_entry(char *, db_next_desc *);
+extern db_result *db_reset_next_entry(char *, db_next_desc *);
+extern db_result *db_list_entries(char *, int, nis_attr *);
+extern db_result *db_add_entry(char *, int, nis_attr *, entry_obj *);
+extern db_result *db_remove_entry(char *, int, nis_attr *);
+extern db_status db_checkpoint(char *);
+extern db_status db_standby(char *);
+#ifndef ORIGINAL_DECLS
+extern db_status db_table_exists(char *);
+extern db_status db_unload_table(char *);
+extern void db_free_result(db_result *);
+#endif
+
+#else /* Non-prototype definitions */
+
+extern bool_t db_initialize();
+#ifdef ORIGINAL_DECLS
+extern bool_t db_create_table();
+extern bool_t db_destroy_table();
+#else
+extern db_status db_create_table();
+extern db_status db_destroy_table();
+#endif
+extern db_result *db_first_entry();
+extern db_result *db_next_entry();
+extern db_result *db_reset_next_entry();
+extern db_result *db_list_entries();
+extern db_result *db_add_entry();
+extern db_result *db_remove_entry();
+extern db_status db_checkpoint();
+extern db_status db_standby();
+#ifndef ORIGINAL_DECLS
+extern db_status db_table_exists();
+extern db_status db_unload_table();
+extern void db_free_result();
+#endif
+#endif /* __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RPCSVC_NIS_DB_H */
diff --git a/cpukit/librpc/include/rpcsvc/nis_object.x b/cpukit/librpc/include/rpcsvc/nis_object.x
new file mode 100644
index 0000000000..3156724f1b
--- /dev/null
+++ b/cpukit/librpc/include/rpcsvc/nis_object.x
@@ -0,0 +1,317 @@
+%/*
+% * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+% * unrestricted use provided that this legend is included on all tape
+% * media and as a part of the software program in whole or part. Users
+% * may copy or modify Sun RPC without charge, but are not authorized
+% * to license or distribute it to anyone else except as part of a product or
+% * program developed by the user or with the express written consent of
+% * Sun Microsystems, Inc.
+% *
+% * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+% * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+% * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+% *
+% * Sun RPC is provided with no support and without any obligation on the
+% * part of Sun Microsystems, Inc. to assist in its use, correction,
+% * modification or enhancement.
+% *
+% * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+% * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+% * OR ANY PART THEREOF.
+% *
+% * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+% * or profits or other special, indirect and consequential damages, even if
+% * Sun has been advised of the possibility of such damages.
+% *
+% * Sun Microsystems, Inc.
+% * 2550 Garcia Avenue
+% * Mountain View, California 94043
+% */
+
+/*
+ * nis_object.x
+ *
+ * Copyright (c) 1988-1992 Sun Microsystems Inc
+ * All Rights Reserved.
+ */
+
+/* From: %#pragma ident "@(#)nis_object.x 1.10 94/05/03 SMI" */
+
+#if RPC_HDR
+%
+%#ifndef __nis_object_h
+%#define __nis_object_h
+%
+#endif
+/*
+ * This file defines the format for a NIS object in RPC language.
+ * It is included by the main .x file and the database access protocol
+ * file. It is common because both of them need to deal with the same
+ * type of object. Generating the actual code though is a bit messy because
+ * the nis.x file and the nis_dba.x file will generate xdr routines to
+ * encode/decode objects when only one set is needed. Such is life when
+ * one is using rpcgen.
+ *
+ * Note, the protocol doesn't specify any limits on such things as
+ * maximum name length, number of attributes, etc. These are enforced
+ * by the database backend. When you hit them you will no. Also see
+ * the db_getlimits() function for fetching the limit values.
+ *
+ */
+
+/* Some manifest constants, chosen to maximize flexibility without
+ * plugging the wire full of data.
+ */
+const NIS_MAXSTRINGLEN = 255;
+const NIS_MAXNAMELEN = 1024;
+const NIS_MAXATTRNAME = 32;
+const NIS_MAXATTRVAL = 2048;
+const NIS_MAXCOLUMNS = 64;
+const NIS_MAXATTR = 16;
+const NIS_MAXPATH = 1024;
+const NIS_MAXREPLICAS = 128;
+const NIS_MAXLINKS = 16;
+
+const NIS_PK_NONE = 0; /* no public key (unix/sys auth) */
+const NIS_PK_DH = 1; /* Public key is Diffie-Hellman type */
+const NIS_PK_RSA = 2; /* Public key if RSA type */
+const NIS_PK_KERB = 3; /* Use kerberos style authentication */
+
+/*
+ * The fundamental name type of NIS. The name may consist of two parts,
+ * the first being the fully qualified name, and the second being an
+ * optional set of attribute/value pairs.
+ */
+struct nis_attr {
+ string zattr_ndx<>; /* name of the index */
+ opaque zattr_val<>; /* Value for the attribute. */
+};
+
+typedef string nis_name<>; /* The NIS name itself. */
+
+/* NIS object types are defined by the following enumeration. The numbers
+ * they use are based on the following scheme :
+ * 0 - 1023 are reserved for Sun,
+ * 1024 - 2047 are defined to be private to a particular tree.
+ * 2048 - 4095 are defined to be user defined.
+ * 4096 - ... are reserved for future use.
+ */
+
+enum zotypes {
+ BOGUS_OBJ = 0, /* Uninitialized object structure */
+ NO_OBJ = 1, /* NULL object (no data) */
+ DIRECTORY_OBJ = 2, /* Directory object describing domain */
+ GROUP_OBJ = 3, /* Group object (a list of names) */
+ TABLE_OBJ = 4, /* Table object (a database schema) */
+ ENTRY_OBJ = 5, /* Entry object (a database record) */
+ LINK_OBJ = 6, /* A name link. */
+ PRIVATE_OBJ = 7 /* Private object (all opaque data) */
+};
+
+/*
+ * The types of Name services NIS knows about. They are enumerated
+ * here. The Binder code will use this type to determine if it has
+ * a set of library routines that will access the indicated name service.
+ */
+enum nstype {
+ UNKNOWN = 0,
+ NIS = 1, /* Nis Plus Service */
+ SUNYP = 2, /* Old NIS Service */
+ IVY = 3, /* Nis Plus Plus Service */
+ DNS = 4, /* Domain Name Service */
+ X500 = 5, /* ISO/CCCIT X.500 Service */
+ DNANS = 6, /* Digital DECNet Name Service */
+ XCHS = 7, /* Xerox ClearingHouse Service */
+ CDS= 8
+};
+
+/*
+ * DIRECTORY - The name service object. These objects identify other name
+ * servers that are serving some portion of the name space. Each has a
+ * type associated with it. The resolver library will note whether or not
+ * is has the needed routines to access that type of service.
+ * The oarmask structure defines an access rights mask on a per object
+ * type basis for the name spaces. The only bits currently used are
+ * create and destroy. By enabling or disabling these access rights for
+ * a specific object type for a one of the accessor entities (owner,
+ * group, world) the administrator can control what types of objects
+ * may be freely added to the name space and which require the
+ * administrator's approval.
+ */
+struct oar_mask {
+ u_long oa_rights; /* Access rights mask */
+ zotypes oa_otype; /* Object type */
+};
+
+struct endpoint {
+ string uaddr<>;
+ string family<>; /* Transport family (INET, OSI, etc) */
+ string proto<>; /* Protocol (TCP, UDP, CLNP, etc) */
+};
+
+/*
+ * Note: pkey is a netobj which is limited to 1024 bytes which limits the
+ * keysize to 8192 bits. This is consider to be a reasonable limit for
+ * the expected lifetime of this service.
+ */
+struct nis_server {
+ nis_name name; /* Principal name of the server */
+ endpoint ep<>; /* Universal addr(s) for server */
+ u_long key_type; /* Public key type */
+ netobj pkey; /* server's public key */
+};
+
+struct directory_obj {
+ nis_name do_name; /* Name of the directory being served */
+ nstype do_type; /* one of NIS, DNS, IVY, YP, or X.500 */
+ nis_server do_servers<>; /* <0> == Primary name server */
+ u_long do_ttl; /* Time To Live (for caches) */
+ oar_mask do_armask<>; /* Create/Destroy rights by object type */
+};
+
+/*
+ * ENTRY - This is one row of data from an information base.
+ * The type value is used by the client library to convert the entry to
+ * it's internal structure representation. The Table name is a back pointer
+ * to the table where the entry is stored. This allows the client library
+ * to determine where to send a request if the client wishes to change this
+ * entry but got to it through a LINK rather than directly.
+ * If the entry is a "standalone" entry then this field is void.
+ */
+const EN_BINARY = 1; /* Indicates value is binary data */
+const EN_CRYPT = 2; /* Indicates the value is encrypted */
+const EN_XDR = 4; /* Indicates the value is XDR encoded */
+const EN_MODIFIED = 8; /* Indicates entry is modified. */
+const EN_ASN1 = 64; /* Means contents use ASN.1 encoding */
+
+struct entry_col {
+ u_long ec_flags; /* Flags for this value */
+ opaque ec_value<>; /* It's textual value */
+};
+
+struct entry_obj {
+ string en_type<>; /* Type of entry such as "passwd" */
+ entry_col en_cols<>; /* Value for the entry */
+};
+
+/*
+ * GROUP - The group object contains a list of NIS principal names. Groups
+ * are used to authorize principals. Each object has a set of access rights
+ * for members of its group. Principal names in groups are in the form
+ * name.directory and recursive groups are expressed as @groupname.directory
+ */
+struct group_obj {
+ u_long gr_flags; /* Flags controlling group */
+ nis_name gr_members<>; /* List of names in group */
+};
+
+/*
+ * LINK - This is the LINK object. It is quite similar to a symbolic link
+ * in the UNIX filesystem. The attributes in the main object structure are
+ * relative to the LINK data and not what it points to (like the file system)
+ * "modify" privleges here indicate the right to modify what the link points
+ * at and not to modify that actual object pointed to by the link.
+ */
+struct link_obj {
+ zotypes li_rtype; /* Real type of the object */
+ nis_attr li_attrs<>; /* Attribute/Values for tables */
+ nis_name li_name; /* The object's real NIS name */
+};
+
+/*
+ * TABLE - This is the table object. It implements a simple
+ * data base that applications and use for configuration or
+ * administration purposes. The role of the table is to group together
+ * a set of related entries. Tables are the simple database component
+ * of NIS. Like many databases, tables are logically divided into columns
+ * and rows. The columns are labeled with indexes and each ENTRY makes
+ * up a row. Rows may be addressed within the table by selecting one
+ * or more indexes, and values for those indexes. Each row which has
+ * a value for the given index that matches the desired value is returned.
+ * Within the definition of each column there is a flags variable, this
+ * variable contains flags which determine whether or not the column is
+ * searchable, contains binary data, and access rights for the entry objects
+ * column value.
+ */
+
+const TA_BINARY = 1; /* Means table data is binary */
+const TA_CRYPT = 2; /* Means value should be encrypted */
+const TA_XDR = 4; /* Means value is XDR encoded */
+const TA_SEARCHABLE = 8; /* Means this column is searchable */
+const TA_CASE = 16; /* Means this column is Case Sensitive */
+const TA_MODIFIED = 32; /* Means this columns attrs are modified*/
+const TA_ASN1 = 64; /* Means contents use ASN.1 encoding */
+
+struct table_col {
+ string tc_name<64>; /* Column Name */
+ u_long tc_flags; /* control flags */
+ u_long tc_rights; /* Access rights mask */
+};
+
+struct table_obj {
+ string ta_type<64>; /* Table type such as "passwd" */
+ int ta_maxcol; /* Total number of columns */
+ u_char ta_sep; /* Separator character */
+ table_col ta_cols<>; /* The number of table indexes */
+ string ta_path<>; /* A search path for this table */
+};
+
+/*
+ * This union joins together all of the currently known objects.
+ */
+union objdata switch (zotypes zo_type) {
+ case DIRECTORY_OBJ :
+ struct directory_obj di_data;
+ case GROUP_OBJ :
+ struct group_obj gr_data;
+ case TABLE_OBJ :
+ struct table_obj ta_data;
+ case ENTRY_OBJ:
+ struct entry_obj en_data;
+ case LINK_OBJ :
+ struct link_obj li_data;
+ case PRIVATE_OBJ :
+ opaque po_data<>;
+ case NO_OBJ :
+ void;
+ case BOGUS_OBJ :
+ void;
+ default :
+ void;
+};
+
+/*
+ * This is the basic NIS object data type. It consists of a generic part
+ * which all objects contain, and a specialized part which varies depending
+ * on the type of the object. All of the specialized sections have been
+ * described above. You might have wondered why they all start with an
+ * integer size, followed by the useful data. The answer is, when the
+ * server doesn't recognize the type returned it treats it as opaque data.
+ * And the definition for opaque data is {int size; char *data;}. In this
+ * way, servers and utility routines that do not understand a given type
+ * may still pass it around. One has to be careful in setting
+ * this variable accurately, it must take into account such things as
+ * XDR padding of structures etc. The best way to set it is to note one's
+ * position in the XDR encoding stream, encode the structure, look at the
+ * new position and calculate the size.
+ */
+struct nis_oid {
+ u_long ctime; /* Time of objects creation */
+ u_long mtime; /* Time of objects modification */
+};
+
+struct nis_object {
+ nis_oid zo_oid; /* object identity verifier. */
+ nis_name zo_name; /* The NIS name for this object */
+ nis_name zo_owner; /* NIS name of object owner. */
+ nis_name zo_group; /* NIS name of access group. */
+ nis_name zo_domain; /* The administrator for the object */
+ u_long zo_access; /* Access rights (owner, group, world) */
+ u_long zo_ttl; /* Object's time to live in seconds. */
+ objdata zo_data; /* Data structure for this type */
+};
+#if RPC_HDR
+%
+%#endif /* if __nis_object_h */
+%
+#endif
diff --git a/cpukit/librpc/include/rpcsvc/nis_tags.h b/cpukit/librpc/include/rpcsvc/nis_tags.h
new file mode 100644
index 0000000000..0eaee6d442
--- /dev/null
+++ b/cpukit/librpc/include/rpcsvc/nis_tags.h
@@ -0,0 +1,137 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * Copyright (c) 1991, Sun Microsystems Inc.
+ */
+
+/*
+ * nis_tags.h
+ *
+ * This file contains the tags and statistics definitions. It is
+ * automatically included by nis.h
+ */
+
+#ifndef _RPCSVC_NIS_TAGS_H
+#define _RPCSVC_NIS_TAGS_H
+
+/* From: #pragma ident "@(#)nis_tags.h 1.10 94/05/03 SMI" */
+/* from file: zns_tags.h 1.7 Copyright (c) 1990 Sun Microsystems */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef ORIGINAL_DECLS
+#define NIS_DIR "data"
+#endif
+
+/* Lookup and List function flags */
+#define FOLLOW_LINKS (1<<0) /* Follow link objects */
+#define FOLLOW_PATH (1<<1) /* Follow the path in a table */
+#define HARD_LOOKUP (1<<2) /* Block until successful */
+#define ALL_RESULTS (1<<3) /* Retrieve all results */
+#define NO_CACHE (1<<4) /* Do not return 'cached' results */
+#define MASTER_ONLY (1<<5) /* Get value only from master server */
+#define EXPAND_NAME (1<<6) /* Expand partitially qualified names */
+
+/* Semantic modification for table operations flags */
+#define RETURN_RESULT (1<<7) /* Return resulting object to client */
+#define ADD_OVERWRITE (1<<8) /* Allow overwrites on ADD */
+#define REM_MULTIPLE (1<<9) /* Allow wildcard deletes */
+#define MOD_SAMEOBJ (1<<10) /* Check modified object before write */
+#define ADD_RESERVED (1<<11) /* Spare ADD semantic */
+#define REM_RESERVED (1<<12) /* Spare REM semantic */
+#ifdef ORIGINAL_DECLS
+#define MOD_RESERVED (1<<13) /* Spare MOD semantic */
+#else
+#define MOD_EXCLUSIVE (1<<13) /* Modify no overwrite on modified keys */
+#endif
+
+/* Transport specific modifications to the operation */
+#define USE_DGRAM (1<<16) /* Use a datagram transport */
+#define NO_AUTHINFO (1<<17) /* Don't bother attaching auth info */
+
+/*
+ * Declarations for "standard" NIS+ tags
+ * State variable tags have values 0 - 2047
+ * Statistic tags have values 2048 - 65535
+ * User Tags have values >2^16
+ */
+#define TAG_DEBUG 1 /* set debug level */
+#define TAG_STATS 2 /* Enable/disable statistics */
+#define TAG_GCACHE 3 /* Flush the Group Cache */
+#ifndef ORIGINAL_DECLS
+#define TAG_GCACHE_ALL TAG_GCACHE
+#endif
+#define TAG_DCACHE 4 /* Flush the directory cache */
+#ifndef ORIGINAL_DECLS
+#define TAG_DCACHE_ONE TAG_DCACHE
+#endif
+#define TAG_OCACHE 5 /* Flush the Object Cache */
+#define TAG_SECURE 6 /* Set the security level */
+#ifndef ORIGINAL_DECLS
+#define TAG_TCACHE_ONE 7 /* Flush the table cache */
+#define TAG_DCACHE_ALL 8 /* Flush entire directory cache */
+#define TAG_TCACHE_ALL 9 /* Flush entire table cache */
+#define TAG_GCACHE_ONE 10 /* Flush one group object */
+#define TAG_DCACHE_ONE_REFRESH 11 /* Flush and refresh one DO */
+#endif
+
+#define TAG_OPSTATS 2048 /* NIS+ operations statistics */
+#define TAG_THREADS 2049 /* Child process/thread status */
+#define TAG_HEAP 2050 /* Heap usage statistics */
+#define TAG_UPDATES 2051 /* Updates to this service */
+#define TAG_VISIBLE 2052 /* First update that isn't replicated */
+#define TAG_S_DCACHE 2053 /* Directory cache statistics */
+#define TAG_S_OCACHE 2054 /* Object cache statistics */
+#define TAG_S_GCACHE 2055 /* Group cache statistics */
+#define TAG_S_STORAGE 2056 /* Group cache statistics */
+#define TAG_UPTIME 2057 /* Time that server has been up */
+#ifndef ORIGINAL_DECLS
+#define TAG_DIRLIST 2058 /* Dir served by this server */
+#define TAG_NISCOMPAT 2059 /* Whether supports NIS compat mode */
+#define TAG_DNSFORWARDING 2060 /* Whether DNS forwarding supported*/
+#define TAG_SECURITY_LEVEL 2061 /* Security level of the server */
+#define TAG_ROOTSERVER 2062 /* Whether root server */
+#endif
+
+/*
+ * Declarations for the Group object flags. Currently
+ * there are only 3.
+ */
+#define IMPMEM_GROUPS 1 /* Implicit Membership allowed */
+#define RECURS_GROUPS 2 /* Recursive Groups allowed */
+#define NEGMEM_GROUPS 4 /* Negative Groups allowed */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RPCSVC_NIS_TAGS_H */
diff --git a/cpukit/librpc/include/rpcsvc/nislib.h b/cpukit/librpc/include/rpcsvc/nislib.h
new file mode 100644
index 0000000000..9f874d270e
--- /dev/null
+++ b/cpukit/librpc/include/rpcsvc/nislib.h
@@ -0,0 +1,317 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * Copyright (c) 1991, Sun Microsystems Inc.
+ */
+
+/*
+ * This file contains the interfaces that are visible in the SunOS 5.x
+ * implementation of NIS Plus. When using C++ the defined __cplusplus and
+ * __STDC__ should both be true.
+ */
+
+#ifndef _RPCSVC_NISLIB_H
+#define _RPCSVC_NISLIB_H
+
+/* From: #pragma ident "@(#)nislib.h 1.16 94/05/03 SMI" */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct signature {
+ int signature_len;
+ char *signature_val;
+};
+
+#ifdef __STDC__
+extern void nis_freeresult(nis_result *);
+extern nis_result * nis_lookup(nis_name, u_long);
+extern nis_result * nis_list(nis_name, u_long,
+ int (*)(nis_name, nis_object *, void *), void *);
+extern nis_result * nis_add(nis_name, nis_object *);
+extern nis_result * nis_remove(nis_name, nis_object *);
+extern nis_result * nis_modify(nis_name, nis_object *);
+
+extern nis_result * nis_add_entry(nis_name, nis_object *, u_long);
+extern nis_result * nis_remove_entry(nis_name, nis_object *, u_long);
+extern nis_result * nis_modify_entry(nis_name, nis_object *, u_long);
+extern nis_result * nis_first_entry(nis_name);
+extern nis_result * nis_next_entry(nis_name, netobj *);
+
+extern nis_error nis_mkdir(nis_name, nis_server *);
+extern nis_error nis_rmdir(nis_name, nis_server *);
+extern name_pos nis_dir_cmp(nis_name, nis_name);
+
+extern nis_name * nis_getnames(nis_name);
+extern void nis_freenames(nis_name *);
+extern nis_name nis_domain_of(nis_name);
+extern nis_name nis_leaf_of(nis_name);
+extern nis_name nis_leaf_of_r(const nis_name, char *, size_t);
+extern nis_name nis_name_of(nis_name);
+extern nis_name nis_local_group(void);
+extern nis_name nis_local_directory(void);
+extern nis_name nis_local_principal(void);
+extern nis_name nis_local_host(void);
+
+extern void nis_destroy_object(nis_object *);
+extern nis_object * nis_clone_object(nis_object *, nis_object *);
+extern void nis_print_object(nis_object *);
+
+extern char * nis_sperrno(nis_error);
+extern void nis_perror(nis_error, char *);
+extern char * nis_sperror(nis_error, char *);
+extern void nis_lerror(nis_error, char *);
+
+extern void nis_print_group_entry(nis_name);
+extern bool_t nis_ismember(nis_name, nis_name);
+extern nis_error nis_creategroup(nis_name, u_long);
+extern nis_error nis_destroygroup(nis_name);
+extern nis_error nis_addmember(nis_name, nis_name);
+extern nis_error nis_removemember(nis_name, nis_name);
+extern nis_error nis_verifygroup(nis_name);
+
+extern void nis_freeservlist(nis_server **);
+extern nis_server ** nis_getservlist(nis_name);
+extern nis_error nis_stats(nis_server *, nis_tag *, int, nis_tag **);
+extern nis_error nis_servstate(nis_server *, nis_tag *, int, nis_tag **);
+extern void nis_freetags(nis_tag *, int);
+
+extern nis_result * nis_checkpoint(nis_name);
+extern void nis_ping(nis_name, u_long, nis_object *);
+
+/*
+ * XXX: PLEASE NOTE THAT THE FOLLOWING FUNCTIONS ARE INTERNAL
+ * TO NIS+ AND SHOULD NOT BE USED BY ANY APPLICATION PROGRAM.
+ * THEIR SEMANTICS AND/OR SIGNATURE CAN CHANGE WITHOUT NOTICE.
+ * SO, PLEASE DO NOT USE THEM. YOU ARE WARNED!!!!
+ */
+
+extern char ** __break_name(nis_name, int *);
+extern int __name_distance(char **, char **);
+extern nis_result * nis_make_error(nis_error, u_long, u_long, u_long, u_long);
+extern nis_attr * __cvt2attr(int *, char **);
+extern void nis_free_request(ib_request *);
+extern nis_error nis_get_request(nis_name, nis_object *, netobj*, ib_request*);
+extern nis_object * nis_read_obj(char *);
+extern int nis_write_obj(char *, nis_object *);
+extern int nis_in_table(nis_name, NIS_HASH_TABLE *, int *);
+extern int nis_insert_item(NIS_HASH_ITEM *, NIS_HASH_TABLE *);
+extern NIS_HASH_ITEM * nis_find_item(nis_name, NIS_HASH_TABLE *);
+extern NIS_HASH_ITEM * nis_remove_item(nis_name, NIS_HASH_TABLE *);
+extern void nis_insert_name(nis_name, NIS_HASH_TABLE *);
+extern void nis_remove_name(nis_name, NIS_HASH_TABLE *);
+extern CLIENT * nis_make_rpchandle(nis_server *, int, u_long, u_long, u_long,
+ int, int);
+extern void * nis_get_static_storage(struct nis_sdata *, u_long, u_long);
+extern char * nis_data(char *);
+extern void nis_print_rights(u_long);
+extern void nis_print_directory(directory_obj *);
+extern void nis_print_group(group_obj *);
+extern void nis_print_table(table_obj *);
+extern void nis_print_link(link_obj *);
+extern void nis_print_entry(entry_obj *);
+extern nis_object * nis_get_object(char *, char *, char *, u_long, u_long,
+ zotypes);
+extern nis_server * __nis_init_callback(CLIENT *,
+ int (*)(nis_name, nis_object *, void *), void *);
+extern int nis_getdtblsize(void);
+extern int __nis_run_callback(netobj *, u_long, struct timeval *, CLIENT *);
+
+extern log_result *nis_dumplog(nis_server *, nis_name, u_long);
+extern log_result *nis_dump(nis_server *, nis_name,
+ int (*)(nis_name, nis_object *, void *));
+
+extern bool_t __do_ismember(nis_name, nis_name,
+ nis_result *(*)(nis_name, u_long));
+extern nis_name __nis_map_group(nis_name);
+extern nis_name __nis_map_group_r(nis_name, char*, size_t);
+
+extern nis_error __nis_CacheBind(char *, directory_obj *);
+extern nis_error __nis_CacheSearch(char *, directory_obj *);
+extern bool_t __nis_CacheRemoveEntry(directory_obj *);
+extern void __nis_CacheRestart(void);
+extern void __nis_CachePrint(void);
+extern void __nis_CacheDumpStatistics(void);
+extern bool_t writeColdStartFile(directory_obj *);
+
+extern CLIENT * __get_ti_clnt(char *, CLIENT *, char **, pid_t *);
+extern int __strcmp_case_insens(char *, char *);
+extern int __strncmp_case_insens(char *, char *);
+
+extern fd_result * nis_finddirectory(directory_obj *, nis_name);
+extern int __start_clock(int);
+extern u_long __stop_clock(int);
+
+/*
+ * This particular function is part of the FreeBSD NIS+ implementation
+ * only. Ideally it should be somewhere else, but it is used by both
+ * rpc.nisd and nis_cachemgr, and there aren't that many headers common
+ * to both programs.
+ */
+
+extern struct signature *__nis_calculate_encrypted_cksum(unsigned char *, unsigned int, char *, int);
+
+#else
+
+/* Non-prototype definitions (old fashioned C) */
+
+extern void nis_freeresult();
+extern nis_result * nis_lookup();
+extern nis_result * nis_list();
+extern nis_result * nis_add();
+extern nis_result * nis_remove();
+extern nis_result * nis_modify();
+
+extern nis_result * nis_add_entry();
+extern nis_result * nis_remove_entry();
+extern nis_result * nis_modify_entry();
+extern nis_result * nis_first_entry();
+extern nis_result * nis_next_entry();
+
+extern nis_error nis_mkdir();
+extern nis_error nis_rmdir();
+extern name_pos nis_dir_cmp();
+
+extern nis_name *nis_getnames();
+extern void nis_freenames();
+extern nis_name nis_domain_of();
+extern nis_name nis_leaf_of();
+extern nis_name nis_leaf_of_r();
+extern nis_name nis_name_of();
+extern nis_name nis_local_group();
+extern nis_name nis_local_directory();
+extern nis_name nis_local_principal();
+extern nis_name nis_local_host();
+
+extern void nis_destroy_object();
+extern nis_object * nis_clone_object();
+extern void nis_print_object();
+
+extern char * nis_sperrno();
+extern void nis_perror();
+extern char * nis_sperror();
+extern void nis_lerror();
+
+extern void nis_print_group_entry();
+extern bool_t nis_ismember();
+extern nis_error nis_creategroup();
+extern nis_error nis_destroygroup();
+extern nis_error nis_addmember();
+extern nis_error nis_removemember();
+extern nis_error nis_verifygroup();
+
+extern void nis_freeservlist();
+extern nis_server ** nis_getservlist();
+extern nis_error nis_stats();
+extern nis_error nis_servstate();
+extern void nis_freetags();
+
+extern nis_result * nis_checkpoint();
+extern void nis_ping();
+
+/*
+ * XXX: PLEASE NOTE THAT THE FOLLOWING FUNCTIONS ARE INTERNAL
+ * TO NIS+ AND SHOULD NOT BE USED BY ANY APPLICATION PROGRAM.
+ * THEIR SEMANTICS AND/OR SIGNATURE CAN CHANGE WITHOUT NOTICE.
+ * SO, PLEASE DO NOT USE THEM. YOU ARE WARNED!!!!
+ */
+extern char ** __break_name();
+extern int __name_distance();
+extern nis_result * nis_make_error();
+extern nis_attr * __cvt2attr();
+extern void nis_free_request();
+extern nis_error nis_get_request();
+extern nis_object * nis_read_obj();
+extern int nis_write_obj();
+extern int nis_in_table();
+extern int nis_insert_item();
+extern NIS_HASH_ITEM * nis_find_item();
+extern NIS_HASH_ITEM * nis_remove_item();
+extern void nis_insert_name();
+extern void nis_remove_name();
+extern CLIENT * nis_make_rpchandle();
+extern void * nis_get_static_storage();
+extern char * nis_data();
+
+extern void nis_print_rights();
+extern void nis_print_directory();
+extern void nis_print_group();
+extern void nis_print_table();
+extern void nis_print_link();
+extern void nis_print_entry();
+extern nis_object * nis_get_object();
+
+extern nis_server * __nis_init_callback();
+extern int nis_getdtblsize();
+extern int __nis_run_callback();
+
+extern log_result * nis_dump();
+extern log_result * nis_dumplog();
+
+extern bool_t __do_ismember();
+extern nis_name __nis_map_group();
+extern nis_name __nis_map_group_r();
+
+
+extern nis_error __nis_CacheBind();
+extern directory_obj * __nis_CacheSearch();
+extern bool_t __nis_CacheRemoveEntry();
+extern void __nis_CacheRestart();
+extern void __nis_CachePrint();
+extern void __nis_CacheDumpStatistics();
+extern bool_t writeColdStartFile();
+
+extern CLIENT * __get_ti_clnt();
+extern int __strcmp_case_insens();
+extern int __strncmp_case_insens();
+
+extern fd_result * nis_finddirectory();
+extern int __start_clock();
+extern u_long __stop_clock();
+
+/*
+ * This particular function is part of the FreeBSD NIS+ implementation
+ * only. Ideally it should be somewhere else, but it is used by both
+ * rpc.nisd and nis_cachemgr, and there aren't that many headers common
+ * to both programs.
+ */
+
+extern struct signature *__nis_calculate_encrypted_cksum();
+
+#endif
+
+#define NUL '\0'
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RPCSVC_NISLIB_H */
diff --git a/cpukit/librpc/include/rpcsvc/nlm_prot.x b/cpukit/librpc/include/rpcsvc/nlm_prot.x
new file mode 100644
index 0000000000..fdc6d6ea96
--- /dev/null
+++ b/cpukit/librpc/include/rpcsvc/nlm_prot.x
@@ -0,0 +1,183 @@
+/* @(#)nlm_prot.x 2.1 88/08/01 4.0 RPCSRC */
+/* @(#)nlm_prot.x 1.8 87/09/21 Copyr 1987 Sun Micro */
+
+/*
+ * Network lock manager protocol definition
+ * Copyright (C) 1986 Sun Microsystems, Inc.
+ *
+ * protocol used between local lock manager and remote lock manager
+ */
+
+#ifdef RPC_HDR
+%#define LM_MAXSTRLEN 1024
+%#define MAXNAMELEN LM_MAXSTRLEN+1
+#else
+%#ifndef lint
+%static const char rcsid[] =
+% "$FreeBSD: src/include/rpcsvc/nlm_prot.x,v 1.8 1999/08/27 23:45:10 peter Exp $";
+%#endif /* not lint */
+#endif
+
+/*
+ * status of a call to the lock manager
+ */
+enum nlm_stats {
+ nlm_granted = 0,
+ nlm_denied = 1,
+ nlm_denied_nolocks = 2,
+ nlm_blocked = 3,
+ nlm_denied_grace_period = 4
+};
+
+struct nlm_holder {
+ bool exclusive;
+ int svid;
+ netobj oh;
+ unsigned l_offset;
+ unsigned l_len;
+};
+
+union nlm_testrply switch (nlm_stats stat) {
+ case nlm_denied:
+ struct nlm_holder holder;
+ default:
+ void;
+};
+
+struct nlm_stat {
+ nlm_stats stat;
+};
+
+struct nlm_res {
+ netobj cookie;
+ nlm_stat stat;
+};
+
+struct nlm_testres {
+ netobj cookie;
+ nlm_testrply stat;
+};
+
+struct nlm_lock {
+ string caller_name<LM_MAXSTRLEN>;
+ netobj fh; /* identify a file */
+ netobj oh; /* identify owner of a lock */
+ int svid; /* generated from pid for svid */
+ unsigned l_offset;
+ unsigned l_len;
+};
+
+struct nlm_lockargs {
+ netobj cookie;
+ bool block;
+ bool exclusive;
+ struct nlm_lock alock;
+ bool reclaim; /* used for recovering locks */
+ int state; /* specify local status monitor state */
+};
+
+struct nlm_cancargs {
+ netobj cookie;
+ bool block;
+ bool exclusive;
+ struct nlm_lock alock;
+};
+
+struct nlm_testargs {
+ netobj cookie;
+ bool exclusive;
+ struct nlm_lock alock;
+};
+
+struct nlm_unlockargs {
+ netobj cookie;
+ struct nlm_lock alock;
+};
+
+
+#ifdef RPC_HDR
+%/*
+% * The following enums are actually bit encoded for efficient
+% * boolean algebra.... DON'T change them.....
+% */
+#endif
+enum fsh_mode {
+ fsm_DN = 0, /* deny none */
+ fsm_DR = 1, /* deny read */
+ fsm_DW = 2, /* deny write */
+ fsm_DRW = 3 /* deny read/write */
+};
+
+enum fsh_access {
+ fsa_NONE = 0, /* for completeness */
+ fsa_R = 1, /* read only */
+ fsa_W = 2, /* write only */
+ fsa_RW = 3 /* read/write */
+};
+
+struct nlm_share {
+ string caller_name<LM_MAXSTRLEN>;
+ netobj fh;
+ netobj oh;
+ fsh_mode mode;
+ fsh_access access;
+};
+
+struct nlm_shareargs {
+ netobj cookie;
+ nlm_share share;
+ bool reclaim;
+};
+
+struct nlm_shareres {
+ netobj cookie;
+ nlm_stats stat;
+ int sequence;
+};
+
+struct nlm_notify {
+ string name<MAXNAMELEN>;
+ long state;
+};
+
+/*
+ * Over-the-wire protocol used between the network lock managers
+ */
+
+program NLM_PROG {
+ version NLM_VERS {
+
+ nlm_testres NLM_TEST(struct nlm_testargs) = 1;
+
+ nlm_res NLM_LOCK(struct nlm_lockargs) = 2;
+
+ nlm_res NLM_CANCEL(struct nlm_cancargs) = 3;
+ nlm_res NLM_UNLOCK(struct nlm_unlockargs) = 4;
+
+ /*
+ * remote lock manager call-back to grant lock
+ */
+ nlm_res NLM_GRANTED(struct nlm_testargs)= 5;
+ /*
+ * message passing style of requesting lock
+ */
+ void NLM_TEST_MSG(struct nlm_testargs) = 6;
+ void NLM_LOCK_MSG(struct nlm_lockargs) = 7;
+ void NLM_CANCEL_MSG(struct nlm_cancargs) =8;
+ void NLM_UNLOCK_MSG(struct nlm_unlockargs) = 9;
+ void NLM_GRANTED_MSG(struct nlm_testargs) = 10;
+ void NLM_TEST_RES(nlm_testres) = 11;
+ void NLM_LOCK_RES(nlm_res) = 12;
+ void NLM_CANCEL_RES(nlm_res) = 13;
+ void NLM_UNLOCK_RES(nlm_res) = 14;
+ void NLM_GRANTED_RES(nlm_res) = 15;
+ } = 1;
+
+ version NLM_VERSX {
+ nlm_shareres NLM_SHARE(nlm_shareargs) = 20;
+ nlm_shareres NLM_UNSHARE(nlm_shareargs) = 21;
+ nlm_res NLM_NM_LOCK(nlm_lockargs) = 22;
+ void NLM_FREE_ALL(nlm_notify) = 23;
+ } = 3;
+
+} = 100021;
diff --git a/cpukit/librpc/include/rpcsvc/pmap_prot.x b/cpukit/librpc/include/rpcsvc/pmap_prot.x
new file mode 100644
index 0000000000..2e9c089484
--- /dev/null
+++ b/cpukit/librpc/include/rpcsvc/pmap_prot.x
@@ -0,0 +1,284 @@
+%/*
+% * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+% * unrestricted use provided that this legend is included on all tape
+% * media and as a part of the software program in whole or part. Users
+% * may copy or modify Sun RPC without charge, but are not authorized
+% * to license or distribute it to anyone else except as part of a product or
+% * program developed by the user.
+% *
+% * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+% * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+% * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+% *
+% * Sun RPC is provided with no support and without any obligation on the
+% * part of Sun Microsystems, Inc. to assist in its use, correction,
+% * modification or enhancement.
+% *
+% * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+% * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+% * OR ANY PART THEREOF.
+% *
+% * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+% * or profits or other special, indirect and consequential damages, even if
+% * Sun has been advised of the possibility of such damages.
+% *
+% * Sun Microsystems, Inc.
+% * 2550 Garcia Avenue
+% * Mountain View, California 94043
+% */
+%/*
+% * Copyright (c) 1984,1989 by Sun Microsystems, Inc.
+% */
+
+%/* from pmap_prot.x */
+
+#ifdef RPC_HDR
+%
+%#pragma ident "@(#)pmap_prot.x 1.6 94/04/29 SMI"
+%
+%#ifndef _KERNEL
+%
+#endif
+
+/*
+ * Port Mapper Protocol Specification (in RPC Language)
+ * derived from RFC 1057
+ */
+
+%/*
+% * Protocol for the local binder service, or pmap.
+% *
+% * Copyright (C) 1984, Sun Microsystems, Inc.
+% *
+% * The following procedures are supported by the protocol:
+% *
+% * PMAPPROC_NULL() returns ()
+% * takes nothing, returns nothing
+% *
+% * PMAPPROC_SET(struct pmap) returns (bool_t)
+% * TRUE is success, FALSE is failure. Registers the tuple
+% * [prog, vers, prot, port].
+% *
+% * PMAPPROC_UNSET(struct pmap) returns (bool_t)
+% * TRUE is success, FALSE is failure. Un-registers pair
+% * [prog, vers]. prot and port are ignored.
+% *
+% * PMAPPROC_GETPORT(struct pmap) returns (long unsigned).
+% * 0 is failure. Otherwise returns the port number where the pair
+% * [prog, vers] is registered. It may lie!
+% *
+% * PMAPPROC_DUMP() RETURNS (struct pmaplist_ptr)
+% *
+% * PMAPPROC_CALLIT(unsigned, unsigned, unsigned, string<>)
+% * RETURNS (port, string<>);
+% * usage: encapsulatedresults = PMAPPROC_CALLIT(prog, vers, proc,
+% * encapsulatedargs);
+% * Calls the procedure on the local machine. If it is not registered,
+% * this procedure is quite; ie it does not return error information!!!
+% * This procedure only is supported on rpc/udp and calls via
+% * rpc/udp. This routine only passes null authentication parameters.
+% * This file has no interface to xdr routines for PMAPPROC_CALLIT.
+% *
+% * The service supports remote procedure calls on udp/ip or tcp/ip socket 111.
+% */
+%
+const PMAPPORT = 111; /* portmapper port number */
+%
+%
+%/*
+% * A mapping of (program, version, protocol) to port number
+% */
+
+struct pmap {
+ unsigned long pm_prog;
+ unsigned long pm_vers;
+ unsigned long pm_prot;
+ unsigned long pm_port;
+};
+#ifdef RPC_HDR
+%
+%typedef pmap PMAP;
+%
+#endif
+%
+%/*
+% * Supported values for the "prot" field
+% */
+%
+const PMAP_IPPROTO_TCP = 6; /* protocol number for TCP/IP */
+const PMAP_IPPROTO_UDP = 17; /* protocol number for UDP/IP */
+%
+%
+%/*
+% * A list of mappings
+% *
+% * Below are two definitions for the pmaplist structure. This is done because
+% * xdr_pmaplist() is specified to take a struct pmaplist **, rather than a
+% * struct pmaplist * that rpcgen would produce. One version of the pmaplist
+% * structure (actually called pm__list) is used with rpcgen, and the other is
+% * defined only in the header file for compatibility with the specified
+% * interface.
+% */
+
+struct pm__list {
+ pmap pml_map;
+ struct pm__list *pml_next;
+};
+
+typedef pm__list *pmaplist_ptr; /* results of PMAPPROC_DUMP */
+
+#ifdef RPC_HDR
+%
+%typedef struct pm__list pmaplist;
+%typedef struct pm__list PMAPLIST;
+%
+%#ifndef __cplusplus
+%struct pmaplist {
+% PMAP pml_map;
+% struct pmaplist *pml_next;
+%};
+%#endif
+%
+%#ifdef __cplusplus
+%extern "C" {
+%#endif
+%#ifdef __STDC__
+%extern bool_t xdr_pmaplist(XDR *, pmaplist**);
+%#else /* K&R C */
+%bool_t xdr_pmaplist();
+%#endif
+%#ifdef __cplusplus
+%}
+%#endif
+%
+#endif
+
+%
+%/*
+% * Arguments to callit
+% */
+
+struct rmtcallargs {
+ unsigned long prog;
+ unsigned long vers;
+ unsigned long proc;
+ opaque args<>;
+};
+#ifdef RPC_HDR
+%
+%/*
+% * Client-side only representation of rmtcallargs structure.
+% *
+% * The routine that XDRs the rmtcallargs structure must deal with the
+% * opaque arguments in the "args" structure. xdr_rmtcall_args() needs to be
+% * passed the XDR routine that knows the args' structure. This routine
+% * doesn't need to go over-the-wire (and it wouldn't make sense anyway) since
+% * the application being called knows the args structure already. So we use a
+% * different "XDR" structure on the client side, p_rmtcallargs, which includes
+% * the args' XDR routine.
+% */
+%struct p_rmtcallargs {
+% u_long prog;
+% u_long vers;
+% u_long proc;
+% struct {
+% u_int args_len;
+% char *args_val;
+% } args;
+% xdrproc_t xdr_args; /* encodes args */
+%};
+%
+#endif /* def RPC_HDR */
+%
+%
+%/*
+% * Results of callit
+% */
+
+struct rmtcallres {
+ unsigned long port;
+ opaque res<>;
+};
+#ifdef RPC_HDR
+%
+%/*
+% * Client-side only representation of rmtcallres structure.
+% */
+%struct p_rmtcallres {
+% u_long port;
+% struct {
+% u_int res_len;
+% char *res_val;
+% } res;
+% xdrproc_t xdr_res; /* decodes res */
+%};
+%
+#endif /* def RPC_HDR */
+
+/*
+ * Port mapper procedures
+ */
+
+program PMAPPROG {
+ version PMAPVERS {
+ void
+ PMAPPROC_NULL(void) = 0;
+
+ bool
+ PMAPPROC_SET(pmap) = 1;
+
+ bool
+ PMAPPROC_UNSET(pmap) = 2;
+
+ unsigned long
+ PMAPPROC_GETPORT(pmap) = 3;
+
+ pmaplist_ptr
+ PMAPPROC_DUMP(void) = 4;
+
+ rmtcallres
+ PMAPPROC_CALLIT(rmtcallargs) = 5;
+ } = 2;
+} = 100000;
+%
+#ifdef RPC_HDR
+%#define PMAPVERS_PROTO ((u_long)2)
+%#define PMAPVERS_ORIG ((u_long)1)
+%
+%#else /* ndef _KERNEL */
+%
+%#include <rpc/pmap_rmt.h>
+%
+%#ifdef __cplusplus
+%extern "C" {
+%#endif
+%
+%#define PMAPPORT 111
+%
+%struct pmap {
+% long unsigned pm_prog;
+% long unsigned pm_vers;
+% long unsigned pm_prot;
+% long unsigned pm_port;
+%};
+%typedef struct pmap PMAP;
+%#ifdef __STDC__
+%extern bool_t xdr_pmap (XDR *, struct pmap *);
+%#else
+%extern bool_t xdr_pmap ();
+%#endif
+%
+%struct pmaplist {
+% struct pmap pml_map;
+% struct pmaplist *pml_next;
+%};
+%typedef struct pmaplist PMAPLIST;
+%typedef struct pmaplist *pmaplist_ptr;
+%
+%
+%#ifdef __cplusplus
+%}
+%#endif
+%
+%#endif /* ndef _KERNEL */
+#endif
diff --git a/cpukit/librpc/include/rpcsvc/rex.x b/cpukit/librpc/include/rpcsvc/rex.x
new file mode 100644
index 0000000000..928efa21e7
--- /dev/null
+++ b/cpukit/librpc/include/rpcsvc/rex.x
@@ -0,0 +1,235 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * Remote execution (rex) protocol specification
+ */
+
+#ifndef RPC_HDR
+%#ifndef lint
+%/*static char sccsid[] = "from: @(#)rex.x 1.3 87/09/18 Copyr 1987 Sun Micro";*/
+%/*static char sccsid[] = "from: @(#)rex.x 2.1 88/08/01 4.0 RPCSRC";*/
+%static const char rcsid[] =
+% "$FreeBSD: src/include/rpcsvc/rex.x,v 1.6 1999/08/27 23:45:10 peter Exp $";
+%#endif /* not lint */
+#endif
+
+const STRINGSIZE = 1024;
+typedef string rexstring<1024>;
+
+/*
+ * values to pass to REXPROC_SIGNAL
+ */
+const SIGINT = 2; /* interrupt */
+
+/*
+ * Values for rst_flags, below
+ */
+const REX_INTERACTIVE = 1; /* interactive mode */
+
+struct rex_start {
+ rexstring rst_cmd<>; /* list of command and args */
+ rexstring rst_host; /* working directory host name */
+ rexstring rst_fsname; /* working directory file system name */
+ rexstring rst_dirwithin;/* working directory within file system */
+ rexstring rst_env<>; /* list of environment */
+ unsigned int rst_port0; /* port for stdin */
+ unsigned int rst_port1; /* port for stdout */
+ unsigned int rst_port2; /* port for stderr */
+ unsigned int rst_flags; /* options - see const above */
+};
+
+struct rex_result {
+ int rlt_stat; /* integer status code */
+ rexstring rlt_message; /* string message for human consumption */
+};
+
+
+struct sgttyb {
+ unsigned four; /* always equals 4 */
+ opaque chars[4];
+ /* chars[0] == input speed */
+ /* chars[1] == output speed */
+ /* chars[2] == kill character */
+ /* chars[3] == erase character */
+ unsigned flags;
+};
+/* values for speeds above (baud rates) */
+const B0 = 0;
+const B50 = 1;
+const B75 = 2;
+const B110 = 3;
+const B134 = 4;
+const B150 = 5;
+const B200 = 6;
+const B300 = 7;
+const B600 = 8;
+const B1200 = 9;
+const B1800 = 10;
+const B2400 = 11;
+const B4800 = 12;
+const B9600 = 13;
+const B19200 = 14;
+const B38400 = 15;
+
+/* values for flags above */
+const TANDEM = 0x00000001; /* send stopc on out q full */
+const CBREAK = 0x00000002; /* half-cooked mode */
+const LCASE = 0x00000004; /* simulate lower case */
+const ECHO = 0x00000008; /* echo input */
+const CRMOD = 0x00000010; /* map \r to \r\n on output */
+const RAW = 0x00000020; /* no i/o processing */
+const ODDP = 0x00000040; /* get/send odd parity */
+const EVENP = 0x00000080; /* get/send even parity */
+const ANYP = 0x000000c0; /* get any parity/send none */
+const NLDELAY = 0x00000300; /* \n delay */
+const NL0 = 0x00000000;
+const NL1 = 0x00000100; /* tty 37 */
+const NL2 = 0x00000200; /* vt05 */
+const NL3 = 0x00000300;
+const TBDELAY = 0x00000c00; /* horizontal tab delay */
+const TAB0 = 0x00000000;
+const TAB1 = 0x00000400; /* tty 37 */
+const TAB2 = 0x00000800;
+const XTABS = 0x00000c00; /* expand tabs on output */
+const CRDELAY = 0x00003000; /* \r delay */
+const CR0 = 0x00000000;
+const CR1 = 0x00001000; /* tn 300 */
+const CR2 = 0x00002000; /* tty 37 */
+const CR3 = 0x00003000; /* concept 100 */
+const VTDELAY = 0x00004000; /* vertical tab delay */
+const FF0 = 0x00000000;
+const FF1 = 0x00004000; /* tty 37 */
+const BSDELAY = 0x00008000; /* \b delay */
+const BS0 = 0x00000000;
+const BS1 = 0x00008000;
+const CRTBS = 0x00010000; /* do backspacing for crt */
+const PRTERA = 0x00020000; /* \ ... / erase */
+const CRTERA = 0x00040000; /* " \b " to wipe out char */
+const TILDE = 0x00080000; /* hazeltine tilde kludge */
+const MDMBUF = 0x00100000; /* start/stop output on carrier intr */
+const LITOUT = 0x00200000; /* literal output */
+const TOSTOP = 0x00400000; /* SIGTTOU on background output */
+const FLUSHO = 0x00800000; /* flush output to terminal */
+const NOHANG = 0x01000000; /* no SIGHUP on carrier drop */
+const L001000 = 0x02000000;
+const CRTKIL = 0x04000000; /* kill line with " \b " */
+const PASS8 = 0x08000000;
+const CTLECH = 0x10000000; /* echo control chars as ^X */
+const PENDIN = 0x20000000; /* tp->t_rawq needs reread */
+const DECCTQ = 0x40000000; /* only ^Q starts after ^S */
+const NOFLSH = 0x80000000; /* no output flush on signal */
+
+struct tchars {
+ unsigned six; /* always equals 6 */
+ opaque chars[6];
+ /* chars[0] == interrupt char */
+ /* chars[1] == quit char */
+ /* chars[2] == start output char */
+ /* chars[3] == stop output char */
+ /* chars[4] == end-of-file char */
+ /* chars[5] == input delimeter (like nl) */
+};
+
+struct ltchars {
+ unsigned six; /* always equals 6 */
+ opaque chars[6];
+ /* chars[0] == stop process signal */
+ /* chars[1] == delayed stop process signal */
+ /* chars[2] == reprint line */
+ /* chars[3] == flush output */
+ /* chars[4] == word erase */
+ /* chars[5] == literal next character */
+ unsigned mode;
+};
+
+struct rex_ttysize {
+ int ts_lines;
+ int ts_cols;
+};
+
+struct rex_ttymode {
+ sgttyb basic; /* standard unix tty flags */
+ tchars more; /* interrupt, kill characters, etc. */
+ ltchars yetmore; /* special Berkeley characters */
+ unsigned andmore; /* and Berkeley modes */
+};
+
+/* values for andmore above */
+const LCRTBS = 0x0001; /* do backspacing for crt */
+const LPRTERA = 0x0002; /* \ ... / erase */
+const LCRTERA = 0x0004; /* " \b " to wipe out char */
+const LTILDE = 0x0008; /* hazeltine tilde kludge */
+const LMDMBUF = 0x0010; /* start/stop output on carrier intr */
+const LLITOUT = 0x0020; /* literal output */
+const LTOSTOP = 0x0040; /* SIGTTOU on background output */
+const LFLUSHO = 0x0080; /* flush output to terminal */
+const LNOHANG = 0x0100; /* no SIGHUP on carrier drop */
+const LL001000 = 0x0200;
+const LCRTKIL = 0x0400; /* kill line with " \b " */
+const LPASS8 = 0x0800;
+const LCTLECH = 0x1000; /* echo control chars as ^X */
+const LPENDIN = 0x2000; /* needs reread */
+const LDECCTQ = 0x4000; /* only ^Q starts after ^S */
+const LNOFLSH = 0x8000; /* no output flush on signal */
+
+program REXPROG {
+ version REXVERS {
+
+ /*
+ * Start remote execution
+ */
+ rex_result
+ REXPROC_START(rex_start) = 1;
+
+ /*
+ * Wait for remote execution to terminate
+ */
+ rex_result
+ REXPROC_WAIT(void) = 2;
+
+ /*
+ * Send tty modes
+ */
+ void
+ REXPROC_MODES(rex_ttymode) = 3;
+
+ /*
+ * Send window size change
+ */
+ void
+ REXPROC_WINCH(rex_ttysize) = 4;
+
+ /*
+ * Send other signal
+ */
+ void
+ REXPROC_SIGNAL(int) = 5;
+ } = 1;
+} = 100017;
diff --git a/cpukit/librpc/include/rpcsvc/rnusers.x b/cpukit/librpc/include/rpcsvc/rnusers.x
new file mode 100644
index 0000000000..393eaf4eac
--- /dev/null
+++ b/cpukit/librpc/include/rpcsvc/rnusers.x
@@ -0,0 +1,122 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * Find out about remote users
+ */
+
+#ifndef RPC_HDR
+%#ifndef lint
+%/*static char sccsid[] = "from: @(#)rnusers.x 1.2 87/09/20 Copyr 1987 Sun Micro";*/
+%/*static char sccsid[] = "from: @(#)rnusers.x 2.1 88/08/01 4.0 RPCSRC";*/
+%static const char rcsid[] =
+% "$FreeBSD: src/include/rpcsvc/rnusers.x,v 1.6 1999/08/27 23:45:10 peter Exp $";
+%#endif /* not lint */
+#endif
+
+const MAXUSERS = 100;
+const MAXUTLEN = 256;
+
+struct utmp {
+ string ut_line<MAXUTLEN>;
+ string ut_name<MAXUTLEN>;
+ string ut_host<MAXUTLEN>;
+ int ut_time;
+};
+
+
+struct utmpidle {
+ utmp ui_utmp;
+ unsigned int ui_idle;
+};
+
+typedef utmp utmparr<MAXUSERS>;
+
+typedef utmpidle utmpidlearr<MAXUSERS>;
+
+const RUSERS_MAXUSERLEN = 32;
+const RUSERS_MAXLINELEN = 32;
+const RUSERS_MAXHOSTLEN = 257;
+
+struct rusers_utmp {
+ string ut_user<RUSERS_MAXUSERLEN>; /* aka ut_name */
+ string ut_line<RUSERS_MAXLINELEN>; /* device */
+ string ut_host<RUSERS_MAXHOSTLEN>; /* host user logged on from */
+ int ut_type; /* type of entry */
+ int ut_time; /* time entry was made */
+ unsigned int ut_idle; /* minutes idle */
+};
+
+typedef rusers_utmp utmp_array<>;
+
+program RUSERSPROG {
+ /*
+ * Old version does not include idle information
+ */
+ version RUSERSVERS_ORIG {
+ int
+ RUSERSPROC_NUM(void) = 1;
+
+ utmparr
+ RUSERSPROC_NAMES(void) = 2;
+
+ utmparr
+ RUSERSPROC_ALLNAMES(void) = 3;
+ } = 1;
+
+ /*
+ * Includes idle information
+ */
+ version RUSERSVERS_IDLE {
+ int
+ RUSERSPROC_NUM(void) = 1;
+
+ utmpidlearr
+ RUSERSPROC_NAMES(void) = 2;
+
+ utmpidlearr
+ RUSERSPROC_ALLNAMES(void) = 3;
+ } = 2;
+
+ /*
+ * Version 3 rusers procedures (from Solaris).
+ * (Thanks a lot Sun.)
+ */
+ version RUSERSVERS_3 {
+ int
+ RUSERSPROC_NUM(void) = 1;
+
+ utmp_array
+ RUSERSPROC_NAMES(void) = 2;
+
+ utmp_array
+ RUSERSPROC_ALLNAMES(void) = 3;
+ } = 3;
+
+} = 100002;
diff --git a/cpukit/librpc/include/rpcsvc/rquota.x b/cpukit/librpc/include/rpcsvc/rquota.x
new file mode 100644
index 0000000000..72864d1c69
--- /dev/null
+++ b/cpukit/librpc/include/rpcsvc/rquota.x
@@ -0,0 +1,67 @@
+/*
+ * Remote quota protocol
+ * Requires unix authentication
+ */
+
+#ifndef RPC_HDR
+%#ifndef lint
+%/*static char sccsid[] = "from: @(#)rquota.x 1.2 87/09/20 Copyr 1987 Sun Micro";*/
+%/*static char sccsid[] = "from: @(#)rquota.x 2.1 88/08/01 4.0 RPCSRC";*/
+%static const char rcsid[] =
+% "$FreeBSD: src/include/rpcsvc/rquota.x,v 1.6 1999/08/27 23:45:10 peter Exp $";
+%#endif /* not lint */
+#endif
+
+const RQ_PATHLEN = 1024;
+
+struct getquota_args {
+ string gqa_pathp<RQ_PATHLEN>; /* path to filesystem of interest */
+ int gqa_uid; /* inquire about quota for uid */
+};
+
+/*
+ * remote quota structure
+ */
+struct rquota {
+ int rq_bsize; /* block size for block counts */
+ bool rq_active; /* indicates whether quota is active */
+ unsigned int rq_bhardlimit; /* absolute limit on disk blks alloc */
+ unsigned int rq_bsoftlimit; /* preferred limit on disk blks */
+ unsigned int rq_curblocks; /* current block count */
+ unsigned int rq_fhardlimit; /* absolute limit on allocated files */
+ unsigned int rq_fsoftlimit; /* preferred file limit */
+ unsigned int rq_curfiles; /* current # allocated files */
+ unsigned int rq_btimeleft; /* time left for excessive disk use */
+ unsigned int rq_ftimeleft; /* time left for excessive files */
+};
+
+enum gqr_status {
+ Q_OK = 1, /* quota returned */
+ Q_NOQUOTA = 2, /* noquota for uid */
+ Q_EPERM = 3 /* no permission to access quota */
+};
+
+union getquota_rslt switch (gqr_status status) {
+case Q_OK:
+ rquota gqr_rquota; /* valid if status == Q_OK */
+case Q_NOQUOTA:
+ void;
+case Q_EPERM:
+ void;
+};
+
+program RQUOTAPROG {
+ version RQUOTAVERS {
+ /*
+ * Get all quotas
+ */
+ getquota_rslt
+ RQUOTAPROC_GETQUOTA(getquota_args) = 1;
+
+ /*
+ * Get active quotas only
+ */
+ getquota_rslt
+ RQUOTAPROC_GETACTIVEQUOTA(getquota_args) = 2;
+ } = 1;
+} = 100011;
diff --git a/cpukit/librpc/include/rpcsvc/rstat.x b/cpukit/librpc/include/rpcsvc/rstat.x
new file mode 100644
index 0000000000..fee9d52032
--- /dev/null
+++ b/cpukit/librpc/include/rpcsvc/rstat.x
@@ -0,0 +1,151 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * Gather statistics on remote machines
+ */
+
+#ifdef RPC_HDR
+
+%#ifndef FSCALE
+%/*
+% * Scale factor for scaled integers used to count load averages.
+% */
+%#define FSHIFT 8 /* bits to right of fixed binary point */
+%#define FSCALE (1<<FSHIFT)
+%
+%#endif /* ndef FSCALE */
+
+#else
+
+%#ifndef lint
+%/*static char sccsid[] = "from: @(#)rstat.x 1.2 87/09/18 Copyr 1987 Sun Micro";*/
+%/*static char sccsid[] = "from: @(#)rstat.x 2.2 88/08/01 4.0 RPCSRC";*/
+%static const char rcsid[] =
+% "$FreeBSD: src/include/rpcsvc/rstat.x,v 1.6 1999/08/27 23:45:11 peter Exp $";
+%#endif /* not lint */
+
+#endif /* def RPC_HDR */
+
+const RSTAT_CPUSTATES = 4;
+const RSTAT_DK_NDRIVE = 4;
+
+/*
+ * GMT since 0:00, January 1, 1970
+ */
+struct rstat_timeval {
+ unsigned int tv_sec; /* seconds */
+ unsigned int tv_usec; /* and microseconds */
+};
+
+struct statstime { /* RSTATVERS_TIME */
+ int cp_time[RSTAT_CPUSTATES];
+ int dk_xfer[RSTAT_DK_NDRIVE];
+ unsigned int v_pgpgin; /* these are cumulative sum */
+ unsigned int v_pgpgout;
+ unsigned int v_pswpin;
+ unsigned int v_pswpout;
+ unsigned int v_intr;
+ int if_ipackets;
+ int if_ierrors;
+ int if_oerrors;
+ int if_collisions;
+ unsigned int v_swtch;
+ int avenrun[3]; /* scaled by FSCALE */
+ rstat_timeval boottime;
+ rstat_timeval curtime;
+ int if_opackets;
+};
+
+struct statsswtch { /* RSTATVERS_SWTCH */
+ int cp_time[RSTAT_CPUSTATES];
+ int dk_xfer[RSTAT_DK_NDRIVE];
+ unsigned int v_pgpgin; /* these are cumulative sum */
+ unsigned int v_pgpgout;
+ unsigned int v_pswpin;
+ unsigned int v_pswpout;
+ unsigned int v_intr;
+ int if_ipackets;
+ int if_ierrors;
+ int if_oerrors;
+ int if_collisions;
+ unsigned int v_swtch;
+ unsigned int avenrun[3];/* scaled by FSCALE */
+ rstat_timeval boottime;
+ int if_opackets;
+};
+
+struct stats { /* RSTATVERS_ORIG */
+ int cp_time[RSTAT_CPUSTATES];
+ int dk_xfer[RSTAT_DK_NDRIVE];
+ unsigned int v_pgpgin; /* these are cumulative sum */
+ unsigned int v_pgpgout;
+ unsigned int v_pswpin;
+ unsigned int v_pswpout;
+ unsigned int v_intr;
+ int if_ipackets;
+ int if_ierrors;
+ int if_oerrors;
+ int if_collisions;
+ int if_opackets;
+};
+
+
+program RSTATPROG {
+ /*
+ * Newest version includes current time and context switching info
+ */
+ version RSTATVERS_TIME {
+ statstime
+ RSTATPROC_STATS(void) = 1;
+
+ unsigned int
+ RSTATPROC_HAVEDISK(void) = 2;
+ } = 3;
+ /*
+ * Does not have current time
+ */
+ version RSTATVERS_SWTCH {
+ statsswtch
+ RSTATPROC_STATS(void) = 1;
+
+ unsigned int
+ RSTATPROC_HAVEDISK(void) = 2;
+ } = 2;
+ /*
+ * Old version has no info about current time or context switching
+ */
+ version RSTATVERS_ORIG {
+ stats
+ RSTATPROC_STATS(void) = 1;
+
+ unsigned int
+ RSTATPROC_HAVEDISK(void) = 2;
+ } = 1;
+} = 100001;
diff --git a/cpukit/librpc/include/rpcsvc/rwall.x b/cpukit/librpc/include/rpcsvc/rwall.x
new file mode 100644
index 0000000000..6c26c1f18f
--- /dev/null
+++ b/cpukit/librpc/include/rpcsvc/rwall.x
@@ -0,0 +1,57 @@
+%/*
+% * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+% * unrestricted use provided that this legend is included on all tape
+% * media and as a part of the software program in whole or part. Users
+% * may copy or modify Sun RPC without charge, but are not authorized
+% * to license or distribute it to anyone else except as part of a product or
+% * program developed by the user or with the express written consent of
+% * Sun Microsystems, Inc.
+% *
+% * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+% * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+% * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+% *
+% * Sun RPC is provided with no support and without any obligation on the
+% * part of Sun Microsystems, Inc. to assist in its use, correction,
+% * modification or enhancement.
+% *
+% * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+% * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+% * OR ANY PART THEREOF.
+% *
+% * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+% * or profits or other special, indirect and consequential damages, even if
+% * Sun has been advised of the possibility of such damages.
+% *
+% * Sun Microsystems, Inc.
+% * 2550 Garcia Avenue
+% * Mountain View, California 94043
+% */
+
+%/*
+% * Copyright (c) 1984, 1990 by Sun Microsystems, Inc.
+% */
+%
+%/* from @(#)rwall.x 1.6 91/03/11 TIRPC 1.0 */
+
+#ifdef RPC_HDR
+%
+%#ifndef _rpcsvc_rwall_h
+%#define _rpcsvc_rwall_h
+%
+%typedef char *wrapstring;
+%
+#endif
+
+program WALLPROG {
+ version WALLVERS {
+ void
+ WALLPROC_WALL(wrapstring) = 2;
+
+ } = 1;
+} = 100008;
+
+#ifdef RPC_HDR
+%
+%#endif /* ! _rpcsvc_rwall_h */
+#endif
diff --git a/cpukit/librpc/include/rpcsvc/sm_inter.x b/cpukit/librpc/include/rpcsvc/sm_inter.x
new file mode 100644
index 0000000000..2071516a7f
--- /dev/null
+++ b/cpukit/librpc/include/rpcsvc/sm_inter.x
@@ -0,0 +1,122 @@
+/* @(#)sm_inter.x 2.2 88/08/01 4.0 RPCSRC */
+/* @(#)sm_inter.x 1.7 87/06/24 Copyr 1987 Sun Micro */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * Status monitor protocol specification
+ * Copyright (C) 1986 Sun Microsystems, Inc.
+ *
+ */
+
+#ifndef RPC_HDR
+%#ifndef lint
+%static const char rcsid[] =
+% "$FreeBSD: src/include/rpcsvc/sm_inter.x,v 1.8 1999/08/27 23:45:11 peter Exp $";
+%#endif /* not lint */
+#endif
+
+program SM_PROG {
+ version SM_VERS {
+ /* res_stat = stat_succ if status monitor agrees to monitor */
+ /* res_stat = stat_fail if status monitor cannot monitor */
+ /* if res_stat == stat_succ, state = state number of site sm_name */
+ struct sm_stat_res SM_STAT(struct sm_name) = 1;
+
+ /* res_stat = stat_succ if status monitor agrees to monitor */
+ /* res_stat = stat_fail if status monitor cannot monitor */
+ /* stat consists of state number of local site */
+ struct sm_stat_res SM_MON(struct mon) = 2;
+
+ /* stat consists of state number of local site */
+ struct sm_stat SM_UNMON(struct mon_id) = 3;
+
+ /* stat consists of state number of local site */
+ struct sm_stat SM_UNMON_ALL(struct my_id) = 4;
+
+ void SM_SIMU_CRASH(void) = 5;
+
+ } = 1;
+} = 100024;
+
+const SM_MAXSTRLEN = 1024;
+
+struct sm_name {
+ string mon_name<SM_MAXSTRLEN>;
+};
+
+struct my_id {
+ string my_name<SM_MAXSTRLEN>; /* name of the site iniates the monitoring request*/
+ int my_prog; /* rpc program # of the requesting process */
+ int my_vers; /* rpc version # of the requesting process */
+ int my_proc; /* rpc procedure # of the requesting process */
+};
+
+struct mon_id {
+ string mon_name<SM_MAXSTRLEN>; /* name of the site to be monitored */
+ struct my_id my_id;
+};
+
+
+struct mon{
+ struct mon_id mon_id;
+ opaque priv[16]; /* private information to store at monitor for requesting process */
+};
+
+
+/*
+ * state # of status monitor monitonically increases each time
+ * status of the site changes:
+ * an even number (>= 0) indicates the site is down and
+ * an odd number (> 0) indicates the site is up;
+ */
+struct sm_stat {
+ int state; /* state # of status monitor */
+};
+
+enum res {
+ stat_succ = 0, /* status monitor agrees to monitor */
+ stat_fail = 1 /* status monitor cannot monitor */
+};
+
+struct sm_stat_res {
+ res res_stat;
+ int state;
+};
+
+/*
+ * structure of the status message sent back by the status monitor
+ * when monitor site status changes
+ */
+struct status {
+ string mon_name<SM_MAXSTRLEN>;
+ int state;
+ opaque priv[16]; /* stored private information */
+};
diff --git a/cpukit/librpc/include/rpcsvc/spray.x b/cpukit/librpc/include/rpcsvc/spray.x
new file mode 100644
index 0000000000..a4d086af48
--- /dev/null
+++ b/cpukit/librpc/include/rpcsvc/spray.x
@@ -0,0 +1,90 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * Spray a server with packets
+ * Useful for testing flakiness of network interfaces
+ */
+
+#ifndef RPC_HDR
+%#ifndef lint
+%/*static char sccsid[] = "from: @(#)spray.x 1.2 87/09/18 Copyr 1987 Sun Micro";*/
+%/*static char sccsid[] = "from: @(#)spray.x 2.1 88/08/01 4.0 RPCSRC";*/
+%static const char rcsid[] =
+% "$FreeBSD: src/include/rpcsvc/spray.x,v 1.6 1999/08/27 23:45:11 peter Exp $";
+%#endif /* not lint */
+#endif
+
+const SPRAYMAX = 8845; /* max amount can spray */
+
+/*
+ * GMT since 0:00, 1 January 1970
+ */
+struct spraytimeval {
+ unsigned int sec;
+ unsigned int usec;
+};
+
+/*
+ * spray statistics
+ */
+struct spraycumul {
+ unsigned int counter;
+ spraytimeval clock;
+};
+
+/*
+ * spray data
+ */
+typedef opaque sprayarr<SPRAYMAX>;
+
+program SPRAYPROG {
+ version SPRAYVERS {
+ /*
+ * Just throw away the data and increment the counter
+ * This call never returns, so the client should always
+ * time it out.
+ */
+ void
+ SPRAYPROC_SPRAY(sprayarr) = 1;
+
+ /*
+ * Get the value of the counter and elapsed time since
+ * last CLEAR.
+ */
+ spraycumul
+ SPRAYPROC_GET(void) = 2;
+
+ /*
+ * Clear the counter and reset the elapsed time
+ */
+ void
+ SPRAYPROC_CLEAR(void) = 3;
+ } = 1;
+} = 100012;
diff --git a/cpukit/librpc/include/rpcsvc/yp.x b/cpukit/librpc/include/rpcsvc/yp.x
new file mode 100644
index 0000000000..aa872653ff
--- /dev/null
+++ b/cpukit/librpc/include/rpcsvc/yp.x
@@ -0,0 +1,379 @@
+/* @(#)yp.x 2.1 88/08/01 4.0 RPCSRC */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * Protocol description file for the Yellow Pages Service
+ */
+
+#ifndef RPC_HDR
+%#ifndef lint
+%static const char rcsid[] =
+% "$FreeBSD: src/include/rpcsvc/yp.x,v 1.12 1999/08/27 23:45:12 peter Exp $";
+%#endif /* not lint */
+#endif
+
+const YPMAXRECORD = 1024;
+const YPMAXDOMAIN = 64;
+const YPMAXMAP = 64;
+const YPMAXPEER = 64;
+
+
+enum ypstat {
+ YP_TRUE = 1,
+ YP_NOMORE = 2,
+ YP_FALSE = 0,
+ YP_NOMAP = -1,
+ YP_NODOM = -2,
+ YP_NOKEY = -3,
+ YP_BADOP = -4,
+ YP_BADDB = -5,
+ YP_YPERR = -6,
+ YP_BADARGS = -7,
+ YP_VERS = -8
+};
+
+
+enum ypxfrstat {
+ YPXFR_SUCC = 1,
+ YPXFR_AGE = 2,
+ YPXFR_NOMAP = -1,
+ YPXFR_NODOM = -2,
+ YPXFR_RSRC = -3,
+ YPXFR_RPC = -4,
+ YPXFR_MADDR = -5,
+ YPXFR_YPERR = -6,
+ YPXFR_BADARGS = -7,
+ YPXFR_DBM = -8,
+ YPXFR_FILE = -9,
+ YPXFR_SKEW = -10,
+ YPXFR_CLEAR = -11,
+ YPXFR_FORCE = -12,
+ YPXFR_XFRERR = -13,
+ YPXFR_REFUSED = -14
+};
+
+
+typedef string domainname<YPMAXDOMAIN>;
+typedef string mapname<YPMAXMAP>;
+typedef string peername<YPMAXPEER>;
+typedef opaque keydat<YPMAXRECORD>;
+typedef opaque valdat<YPMAXRECORD>;
+
+
+struct ypmap_parms {
+ domainname domain;
+ mapname map;
+ unsigned int ordernum;
+ peername peer;
+};
+
+struct ypreq_key {
+ domainname domain;
+ mapname map;
+ keydat key;
+};
+
+struct ypreq_nokey {
+ domainname domain;
+ mapname map;
+};
+
+struct ypreq_xfr {
+ ypmap_parms map_parms;
+ unsigned int transid;
+ unsigned int prog;
+ unsigned int port;
+};
+
+
+struct ypresp_val {
+ ypstat stat;
+ valdat val;
+};
+
+struct ypresp_key_val {
+ ypstat stat;
+#ifdef STUPID_SUN_BUG /* These are backwards */
+ keydat key;
+ valdat val;
+#else
+ valdat val;
+ keydat key;
+#endif
+};
+
+
+struct ypresp_master {
+ ypstat stat;
+ peername peer;
+};
+
+struct ypresp_order {
+ ypstat stat;
+ unsigned int ordernum;
+};
+
+union ypresp_all switch (bool more) {
+case TRUE:
+ ypresp_key_val val;
+case FALSE:
+ void;
+};
+
+struct ypresp_xfr {
+ unsigned int transid;
+ ypxfrstat xfrstat;
+};
+
+struct ypmaplist {
+ mapname map;
+ ypmaplist *next;
+};
+
+struct ypresp_maplist {
+ ypstat stat;
+ ypmaplist *maps;
+};
+
+enum yppush_status {
+ YPPUSH_SUCC = 1, /* Success */
+ YPPUSH_AGE = 2, /* Master's version not newer */
+ YPPUSH_NOMAP = -1, /* Can't find server for map */
+ YPPUSH_NODOM = -2, /* Domain not supported */
+ YPPUSH_RSRC = -3, /* Local resource alloc failure */
+ YPPUSH_RPC = -4, /* RPC failure talking to server */
+ YPPUSH_MADDR = -5, /* Can't get master address */
+ YPPUSH_YPERR = -6, /* YP server/map db error */
+ YPPUSH_BADARGS = -7, /* Request arguments bad */
+ YPPUSH_DBM = -8, /* Local dbm operation failed */
+ YPPUSH_FILE = -9, /* Local file I/O operation failed */
+ YPPUSH_SKEW = -10, /* Map version skew during transfer */
+ YPPUSH_CLEAR = -11, /* Can't send "Clear" req to local ypserv */
+ YPPUSH_FORCE = -12, /* No local order number in map use -f flag. */
+ YPPUSH_XFRERR = -13, /* ypxfr error */
+ YPPUSH_REFUSED = -14 /* Transfer request refused by ypserv */
+};
+
+struct yppushresp_xfr {
+ unsigned transid;
+ yppush_status status;
+};
+
+/*
+ * Response structure and overall result status codes. Success and failure
+ * represent two separate response message types.
+ */
+
+enum ypbind_resptype {
+ YPBIND_SUCC_VAL = 1,
+ YPBIND_FAIL_VAL = 2
+};
+
+struct ypbind_binding {
+ opaque ypbind_binding_addr[4]; /* In network order */
+ opaque ypbind_binding_port[2]; /* In network order */
+};
+
+union ypbind_resp switch (ypbind_resptype ypbind_status) {
+case YPBIND_FAIL_VAL:
+ unsigned ypbind_error;
+case YPBIND_SUCC_VAL:
+ ypbind_binding ypbind_bindinfo;
+};
+
+/* Detailed failure reason codes for response field ypbind_error*/
+
+const YPBIND_ERR_ERR = 1; /* Internal error */
+const YPBIND_ERR_NOSERV = 2; /* No bound server for passed domain */
+const YPBIND_ERR_RESC = 3; /* System resource allocation failure */
+
+
+/*
+ * Request data structure for ypbind "Set domain" procedure.
+ */
+struct ypbind_setdom {
+ domainname ypsetdom_domain;
+ ypbind_binding ypsetdom_binding;
+ unsigned ypsetdom_vers;
+};
+
+
+/*
+ * NIS v1 support for backwards compatibility
+ */
+enum ypreqtype {
+ YPREQ_KEY = 1,
+ YPREQ_NOKEY = 2,
+ YPREQ_MAP_PARMS = 3
+};
+
+enum ypresptype {
+ YPRESP_VAL = 1,
+ YPRESP_KEY_VAL = 2,
+ YPRESP_MAP_PARMS = 3
+};
+
+union yprequest switch (ypreqtype yp_reqtype) {
+case YPREQ_KEY:
+ ypreq_key yp_req_keytype;
+case YPREQ_NOKEY:
+ ypreq_nokey yp_req_nokeytype;
+case YPREQ_MAP_PARMS:
+ ypmap_parms yp_req_map_parmstype;
+};
+
+union ypresponse switch (ypresptype yp_resptype) {
+case YPRESP_VAL:
+ ypresp_val yp_resp_valtype;
+case YPRESP_KEY_VAL:
+ ypresp_key_val yp_resp_key_valtype;
+case YPRESP_MAP_PARMS:
+ ypmap_parms yp_resp_map_parmstype;
+};
+
+#if !defined(YPBIND_ONLY) && !defined(YPPUSH_ONLY)
+/*
+ * YP access protocol
+ */
+program YPPROG {
+/*
+ * NIS v1 support for backwards compatibility
+ */
+ version YPOLDVERS {
+ void
+ YPOLDPROC_NULL(void) = 0;
+
+ bool
+ YPOLDPROC_DOMAIN(domainname) = 1;
+
+ bool
+ YPOLDPROC_DOMAIN_NONACK(domainname) = 2;
+
+ ypresponse
+ YPOLDPROC_MATCH(yprequest) = 3;
+
+ ypresponse
+ YPOLDPROC_FIRST(yprequest) = 4;
+
+ ypresponse
+ YPOLDPROC_NEXT(yprequest) = 5;
+
+ ypresponse
+ YPOLDPROC_POLL(yprequest) = 6;
+
+ ypresponse
+ YPOLDPROC_PUSH(yprequest) = 7;
+
+ ypresponse
+ YPOLDPROC_PULL(yprequest) = 8;
+
+ ypresponse
+ YPOLDPROC_GET(yprequest) = 9;
+ } = 1;
+
+ version YPVERS {
+ void
+ YPPROC_NULL(void) = 0;
+
+ bool
+ YPPROC_DOMAIN(domainname) = 1;
+
+ bool
+ YPPROC_DOMAIN_NONACK(domainname) = 2;
+
+ ypresp_val
+ YPPROC_MATCH(ypreq_key) = 3;
+
+ ypresp_key_val
+#ifdef STUPID_SUN_BUG /* should be ypreq_nokey */
+ YPPROC_FIRST(ypreq_key) = 4;
+#else
+ YPPROC_FIRST(ypreq_nokey) = 4;
+#endif
+ ypresp_key_val
+ YPPROC_NEXT(ypreq_key) = 5;
+
+ ypresp_xfr
+ YPPROC_XFR(ypreq_xfr) = 6;
+
+ void
+ YPPROC_CLEAR(void) = 7;
+
+ ypresp_all
+ YPPROC_ALL(ypreq_nokey) = 8;
+
+ ypresp_master
+ YPPROC_MASTER(ypreq_nokey) = 9;
+
+ ypresp_order
+ YPPROC_ORDER(ypreq_nokey) = 10;
+
+ ypresp_maplist
+ YPPROC_MAPLIST(domainname) = 11;
+ } = 2;
+} = 100004;
+#endif
+#if !defined(YPSERV_ONLY) && !defined(YPBIND_ONLY)
+/*
+ * YPPUSHPROC_XFRRESP is the callback routine for result of YPPROC_XFR
+ */
+program YPPUSH_XFRRESPPROG {
+ version YPPUSH_XFRRESPVERS {
+ void
+ YPPUSHPROC_NULL(void) = 0;
+#ifdef STUPID_SUN_BUG /* argument and return value are backwards */
+ yppushresp_xfr
+ YPPUSHPROC_XFRRESP(void) = 1;
+#else
+ void
+ YPPUSHPROC_XFRRESP(yppushresp_xfr) = 1;
+#endif
+ } = 1;
+} = 0x40000000; /* transient: could be anything up to 0x5fffffff */
+#endif
+#if !defined(YPSERV_ONLY) && !defined(YPPUSH_ONLY)
+/*
+ * YP binding protocol
+ */
+program YPBINDPROG {
+ version YPBINDVERS {
+ void
+ YPBINDPROC_NULL(void) = 0;
+
+ ypbind_resp
+ YPBINDPROC_DOMAIN(domainname) = 1;
+
+ void
+ YPBINDPROC_SETDOM(ypbind_setdom) = 2;
+ } = 2;
+} = 100007;
+
+#endif
diff --git a/cpukit/librpc/include/rpcsvc/yp_prot.h b/cpukit/librpc/include/rpcsvc/yp_prot.h
new file mode 100644
index 0000000000..92de593611
--- /dev/null
+++ b/cpukit/librpc/include/rpcsvc/yp_prot.h
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 1992/3 Theo de Raadt <deraadt@fsa.ca>
+ * 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. 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.
+ *
+ * $FreeBSD: src/include/rpcsvc/yp_prot.h,v 1.10 1999/08/27 23:45:12 peter Exp $
+ */
+
+#ifndef _RPCSVC_YP_PROT_H_
+#define _RPCSVC_YP_PROT_H_
+
+/*
+ * YPSERV PROTOCOL:
+ *
+ * ypserv supports the following procedures:
+ *
+ * YPPROC_NULL takes (void), returns (void).
+ * called to check if server is alive.
+ * YPPROC_DOMAIN takes (char *), returns (bool_t).
+ * true if ypserv serves the named domain.
+ * YPPROC_DOMAIN_NOACK takes (char *), returns (bool_t).
+ * true if ypserv serves the named domain.
+ * used for broadcasts, does not ack if ypserv
+ * doesn't handle named domain.
+ * YPPROC_MATCH takes (struct ypreq_key), returns (struct ypresp_val)
+ * does a lookup.
+ * YPPROC_FIRST takes (struct ypreq_nokey) returns (ypresp_key_val).
+ * gets the first key/datum from the map.
+ * YPPROC_NEXT takes (struct ypreq_key) returns (ypresp_key_val).
+ * gets the next key/datum from the map.
+ * YPPROC_XFR takes (struct ypreq_xfr), returns (void).
+ * tells ypserv to check if there is a new version of
+ * the map.
+ * YPPROC_CLEAR takes (void), returns (void).
+ * tells ypserv to flush it's file cache, so that
+ * newly transferred files will get read.
+ * YPPROC_ALL takes (struct ypreq_nokey), returns (bool_t and
+ * struct ypresp_key_val).
+ * returns an array of data, with the bool_t being
+ * false on the last datum. read the source, it's
+ * convoluted.
+ * YPPROC_MASTER takes (struct ypreq_nokey), returns (ypresp_master).
+ * YPPROC_ORDER takes (struct ypreq_nokey), returns (ypresp_order).
+ * YPPROC_MAPLIST takes (char *), returns (struct ypmaplist *).
+ */
+
+#ifndef BOOL_DEFINED
+typedef u_int bool;
+#define BOOL_DEFINED
+#endif
+
+/* Program and version symbols, magic numbers */
+
+#define YPPROG ((u_long)100004)
+#define YPVERS ((u_long)2)
+#define YPVERS_ORIG ((u_long)1)
+#define YPMAXRECORD ((u_long)1024)
+#define YPMAXDOMAIN ((u_long)64)
+#define YPMAXMAP ((u_long)64)
+#define YPMAXPEER ((u_long)256)
+
+/*
+ * I don't know if anything of sun's depends on this, or if they
+ * simply defined it so that their own code wouldn't try to send
+ * packets over the ethernet MTU. This YP code doesn't use it.
+ */
+#define YPMSGSZ 1600
+
+#ifndef DATUM
+typedef struct {
+ char *dptr;
+ int dsize;
+} datum;
+#define DATUM
+#endif
+
+struct ypmap_parms {
+ char *domain;
+ char *map;
+ u_long ordernum;
+ char *owner;
+};
+
+struct ypreq_key {
+ char *domain;
+ char *map;
+ datum keydat;
+};
+
+struct ypreq_nokey {
+ char *domain;
+ char *map;
+};
+
+struct ypreq_xfr {
+ struct ypmap_parms map_parms;
+ u_long transid;
+ u_long proto;
+ u_short port;
+};
+#define ypxfr_domain map_parms.domain
+#define ypxfr_map map_parms.map
+#define ypxfr_ordernum map_parms.ordernum
+#define ypxfr_owner map_parms.owner
+
+struct ypresp_val {
+ u_long status;
+ datum valdat;
+};
+
+struct ypresp_key_val {
+ u_long status;
+ datum keydat;
+ datum valdat;
+};
+
+struct ypresp_master {
+ u_long status;
+ char *master;
+};
+
+struct ypresp_order {
+ u_long status;
+ u_long ordernum;
+};
+
+struct ypmaplist {
+ char ypml_name[YPMAXMAP + 1];
+ struct ypmaplist *ypml_next;
+};
+
+struct ypresp_maplist {
+ u_long status;
+ struct ypmaplist *list;
+};
+
+/* ypserv procedure numbers */
+#define YPPROC_NULL ((u_long)0)
+#define YPPROC_DOMAIN ((u_long)1)
+#define YPPROC_DOMAIN_NONACK ((u_long)2)
+#define YPPROC_MATCH ((u_long)3)
+#define YPPROC_FIRST ((u_long)4)
+#define YPPROC_NEXT ((u_long)5)
+#define YPPROC_XFR ((u_long)6)
+#define YPPROC_CLEAR ((u_long)7)
+#define YPPROC_ALL ((u_long)8)
+#define YPPROC_MASTER ((u_long)9)
+#define YPPROC_ORDER ((u_long)10)
+#define YPPROC_MAPLIST ((u_long)11)
+
+/* ypserv procedure return status values */
+#define YP_TRUE ((long)1) /* general purpose success code */
+#define YP_NOMORE ((long)2) /* no more entries in map */
+#define YP_FALSE ((long)0) /* general purpose failure code */
+#define YP_NOMAP ((long)-1) /* no such map in domain */
+#define YP_NODOM ((long)-2) /* domain not supported */
+#define YP_NOKEY ((long)-3) /* no such key in map */
+#define YP_BADOP ((long)-4) /* invalid operation */
+#define YP_BADDB ((long)-5) /* server data base is bad */
+#define YP_YPERR ((long)-6) /* YP server error */
+#define YP_BADARGS ((long)-7) /* request arguments bad */
+#define YP_VERS ((long)-8) /* YP server version mismatch */
+
+/*
+ * Sun's header file says:
+ * "Domain binding data structure, used by ypclnt package and ypserv modules.
+ * Users of the ypclnt package (or of this protocol) don't HAVE to know about
+ * it, but it must be available to users because _yp_dobind is a public
+ * interface."
+ *
+ * This is totally bogus! Nowhere else does Sun state that _yp_dobind() is
+ * a public interface, and I don't know any reason anyone would want to call
+ * it. But, just in case anyone does actually expect it to be available..
+ * we provide this.. exactly as Sun wants it.
+ */
+struct dom_binding {
+ struct dom_binding *dom_pnext;
+ char dom_domain[YPMAXDOMAIN + 1];
+ struct sockaddr_in dom_server_addr;
+ u_short dom_server_port;
+ int dom_socket;
+ CLIENT *dom_client;
+ u_short dom_local_port;
+ long dom_vers;
+};
+
+/*
+ * YPBIND PROTOCOL:
+ *
+ * ypbind supports the following procedures:
+ *
+ * YPBINDPROC_NULL takes (void), returns (void).
+ * to check if ypbind is running.
+ * YPBINDPROC_DOMAIN takes (char *), returns (struct ypbind_resp).
+ * requests that ypbind start to serve the
+ * named domain (if it doesn't already)
+ * YPBINDPROC_SETDOM takes (struct ypbind_setdom), returns (void).
+ * used by ypset.
+ */
+
+#define YPBINDPROG ((u_long)100007)
+#define YPBINDVERS ((u_long)2)
+#define YPBINDVERS_ORIG ((u_long)1)
+
+/* ypbind procedure numbers */
+#define YPBINDPROC_NULL ((u_long)0)
+#define YPBINDPROC_DOMAIN ((u_long)1)
+#define YPBINDPROC_SETDOM ((u_long)2)
+
+/* error code in ypbind_resp.ypbind_status */
+enum ypbind_resptype {
+ YPBIND_SUCC_VAL = 1,
+ YPBIND_FAIL_VAL = 2
+};
+
+/* network order, of course */
+struct ypbind_binding {
+ struct in_addr ypbind_binding_addr;
+ u_short ypbind_binding_port;
+};
+
+struct ypbind_resp {
+ enum ypbind_resptype ypbind_status;
+ union {
+ u_long ypbind_error;
+ struct ypbind_binding ypbind_bindinfo;
+ } ypbind_respbody;
+};
+
+/* error code in ypbind_resp.ypbind_respbody.ypbind_error */
+#define YPBIND_ERR_ERR 1 /* internal error */
+#define YPBIND_ERR_NOSERV 2 /* no bound server for passed domain */
+#define YPBIND_ERR_RESC 3 /* system resource allocation failure */
+
+/*
+ * Request data structure for ypbind "Set domain" procedure.
+ */
+struct ypbind_setdom {
+ char ypsetdom_domain[YPMAXDOMAIN + 1];
+ struct ypbind_binding ypsetdom_binding;
+ u_short ypsetdom_vers;
+};
+#define ypsetdom_addr ypsetdom_binding.ypbind_binding_addr
+#define ypsetdom_port ypsetdom_binding.ypbind_binding_port
+
+/*
+ * YPPUSH PROTOCOL:
+ *
+ * Sun says:
+ * "Protocol between clients (ypxfr, only) and yppush
+ * yppush speaks a protocol in the transient range, which
+ * is supplied to ypxfr as a command-line parameter when it
+ * is activated by ypserv."
+ *
+ * This protocol is not implemented, naturally, because this YP
+ * implementation only does the client side.
+ */
+#define YPPUSHVERS ((u_long)1)
+#define YPPUSHVERS_ORIG ((u_long)1)
+
+/* yppush procedure numbers */
+#define YPPUSHPROC_NULL ((u_long)0)
+#define YPPUSHPROC_XFRRESP ((u_long)1)
+
+struct yppushresp_xfr {
+ u_long transid;
+ u_long status;
+};
+
+/* yppush status value in yppushresp_xfr.status */
+#define YPPUSH_SUCC ((long)1) /* Success */
+#define YPPUSH_AGE ((long)2) /* Master's version not newer */
+#define YPPUSH_NOMAP ((long)-1) /* Can't find server for map */
+#define YPPUSH_NODOM ((long)-2) /* Domain not supported */
+#define YPPUSH_RSRC ((long)-3) /* Local resource alloc failure */
+#define YPPUSH_RPC ((long)-4) /* RPC failure talking to server */
+#define YPPUSH_MADDR ((long)-5) /* Can't get master address */
+#define YPPUSH_YPERR ((long)-6) /* YP server/map db error */
+#define YPPUSH_BADARGS ((long)-7) /* Request arguments bad */
+#define YPPUSH_DBM ((long)-8) /* Local dbm operation failed */
+#define YPPUSH_FILE ((long)-9) /* Local file I/O operation failed */
+#define YPPUSH_SKEW ((long)-10) /* Map version skew during transfer */
+#define YPPUSH_CLEAR ((long)-11) /* Can't send "Clear" req to local ypserv */
+#define YPPUSH_FORCE ((long)-12) /* No local order number in map - use -f */
+#define YPPUSH_XFRERR ((long)-13) /* ypxfr error */
+#define YPPUSH_REFUSED ((long)-14) /* Transfer request refused by ypserv */
+
+struct inaddr;
+__BEGIN_DECLS
+bool_t xdr_datum __P((XDR *, datum *));
+bool_t xdr_ypreq_key __P((XDR *, struct ypreq_key *));
+bool_t xdr_ypreq_nokey __P((XDR *, struct ypreq_nokey *));
+bool_t xdr_ypreq_xfr __P((XDR *, struct ypreq_xfr *));
+bool_t xdr_ypresp_val __P((XDR *, struct ypresp_val *));
+bool_t xdr_ypresp_key_val __P((XDR *, struct ypresp_key_val *));
+bool_t xdr_ypbind_resp __P((XDR *, struct ypbind_resp *));
+bool_t xdr_ypbind_setdom __P((XDR *, struct ypbind_setdom *));
+bool_t xdr_yp_inaddr __P((XDR *, struct inaddr *));
+bool_t xdr_ypmap_parms __P((XDR *, struct ypmap_parms *));
+bool_t xdr_yppushresp_xfr __P((XDR *, struct yppushresp_xfr *));
+bool_t xdr_ypresp_order __P((XDR *, struct ypresp_order *));
+bool_t xdr_ypresp_master __P((XDR *, struct ypresp_master *));
+bool_t xdr_ypresp_maplist __P((XDR *, struct ypresp_maplist *));
+__END_DECLS
+
+#endif /* _RPCSVC_YP_PROT_H_ */
diff --git a/cpukit/librpc/include/rpcsvc/ypclnt.h b/cpukit/librpc/include/rpcsvc/ypclnt.h
new file mode 100644
index 0000000000..0c73147998
--- /dev/null
+++ b/cpukit/librpc/include/rpcsvc/ypclnt.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 1992/3 Theo de Raadt <deraadt@fsa.ca>
+ * 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. 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.
+ *
+ * $FreeBSD: src/include/rpcsvc/ypclnt.h,v 1.11 1999/08/27 23:45:12 peter Exp $
+ */
+
+#ifndef _RPCSVC_YPCLNT_H_
+#define _RPCSVC_YPCLNT_H_
+
+#include <sys/cdefs.h>
+
+#define YPERR_BADARGS 1 /* args to function are bad */
+#define YPERR_RPC 2 /* RPC failure */
+#define YPERR_DOMAIN 3 /* can't bind to a server for domain */
+#define YPERR_MAP 4 /* no such map in server's domain */
+#define YPERR_KEY 5 /* no such key in map */
+#define YPERR_YPERR 6 /* some internal YP server or client error */
+#define YPERR_RESRC 7 /* local resource allocation failure */
+#define YPERR_NOMORE 8 /* no more records in map database */
+#define YPERR_PMAP 9 /* can't communicate with portmapper */
+#define YPERR_YPBIND 10 /* can't communicate with ypbind */
+#define YPERR_YPSERV 11 /* can't communicate with ypserv */
+#define YPERR_NODOM 12 /* local domain name not set */
+#define YPERR_BADDB 13 /* YP data base is bad */
+#define YPERR_VERS 14 /* YP version mismatch */
+#define YPERR_ACCESS 15 /* access violation */
+#define YPERR_BUSY 16 /* database is busy */
+
+/*
+ * Types of update operations
+ */
+#define YPOP_CHANGE 1 /* change, do not add */
+#define YPOP_INSERT 2 /* add, do not change */
+#define YPOP_DELETE 3 /* delete this entry */
+#define YPOP_STORE 4 /* add, or change */
+
+struct ypall_callback {
+ /* return non-0 to stop getting called */
+ int (*foreach) __P((unsigned long, char *, int, char *, int, void *));
+ char *data; /* opaque pointer for use of callback fn */
+};
+
+struct dom_binding;
+
+__BEGIN_DECLS
+int yp_bind __P((char *dom));
+int _yp_dobind __P((char *dom, struct dom_binding **ypdb));
+void yp_unbind __P((char *dom));
+int yp_get_default_domain __P((char **domp));
+int yp_match __P((char *indomain, char *inmap,
+ const char *inkey, int inkeylen, char **outval,
+ int *outvallen));
+int yp_first __P((char *indomain, char *inmap,
+ char **outkey, int *outkeylen, char **outval,
+ int *outvallen));
+int yp_next __P((char *indomain, char *inmap,
+ char *inkey, int inkeylen, char **outkey,
+ int *outkeylen, char **outval, int *outvallen));
+int yp_master __P((char *indomain, char *inmap, char **outname));
+int yp_order __P((char *indomain, char *inmap, int *outorder));
+int yp_all __P((char *indomain, char *inmap,
+ struct ypall_callback *incallback));
+char * yperr_string __P((int incode));
+char * ypbinderr_string __P((int incode));
+int ypprot_err __P((unsigned int incode));
+__END_DECLS
+
+#endif /* _RPCSVC_YPCLNT_H_ */
diff --git a/cpukit/librpc/include/rpcsvc/yppasswd.x b/cpukit/librpc/include/rpcsvc/yppasswd.x
new file mode 100644
index 0000000000..bcc83a1346
--- /dev/null
+++ b/cpukit/librpc/include/rpcsvc/yppasswd.x
@@ -0,0 +1,75 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * YP password update protocol
+ * Requires unix authentication
+ */
+
+#ifndef RPC_HDR
+%#ifndef lint
+%/*static char sccsid[] = "from: @(#)yppasswd.x 1.1 87/04/13 Copyr 1987 Sun Micro";*/
+%/*static char sccsid[] = "from: @(#)yppasswd.x 2.1 88/08/01 4.0 RPCSRC";*/
+%static const char rcsid[] =
+% "$FreeBSD: src/include/rpcsvc/yppasswd.x,v 1.6 1999/08/27 23:45:12 peter Exp $";
+%#endif /* not lint */
+#endif
+
+program YPPASSWDPROG {
+ version YPPASSWDVERS {
+ /*
+ * Update my passwd entry
+ */
+ int
+ YPPASSWDPROC_UPDATE(yppasswd) = 1;
+ } = 1;
+} = 100009;
+
+
+struct x_passwd {
+ string pw_name<>; /* username */
+ string pw_passwd<>; /* encrypted password */
+ int pw_uid; /* user id */
+ int pw_gid; /* group id */
+ string pw_gecos<>; /* in real life name */
+ string pw_dir<>; /* home directory */
+ string pw_shell<>; /* default shell */
+};
+
+struct yppasswd {
+ string oldpass<>; /* unencrypted old password */
+ x_passwd newpw; /* new passwd entry */
+};
+
+
+#ifdef RPC_HDR
+%#include <sys/cdefs.h>
+%extern int _yppasswd __P(( char * , struct x_passwd * ));
+%#define yppasswd(x,y) _yppasswd(x,y)
+#endif
diff --git a/cpukit/librpc/include/rpcsvc/ypupdate_prot.x b/cpukit/librpc/include/rpcsvc/ypupdate_prot.x
new file mode 100644
index 0000000000..f16d5ee45e
--- /dev/null
+++ b/cpukit/librpc/include/rpcsvc/ypupdate_prot.x
@@ -0,0 +1,88 @@
+%/*
+% * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+% * unrestricted use provided that this legend is included on all tape
+% * media and as a part of the software program in whole or part. Users
+% * may copy or modify Sun RPC without charge, but are not authorized
+% * to license or distribute it to anyone else except as part of a product or
+% * program developed by the user or with the express written consent of
+% * Sun Microsystems, Inc.
+% *
+% * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+% * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+% * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+% *
+% * Sun RPC is provided with no support and without any obligation on the
+% * part of Sun Microsystems, Inc. to assist in its use, correction,
+% * modification or enhancement.
+% *
+% * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+% * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+% * OR ANY PART THEREOF.
+% *
+% * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+% * or profits or other special, indirect and consequential damages, even if
+% * Sun has been advised of the possibility of such damages.
+% *
+% * Sun Microsystems, Inc.
+% * 2550 Garcia Avenue
+% * Mountain View, California 94043
+% */
+
+%/*
+% * Copyright (c) 1986, 1990 by Sun Microsystems, Inc.
+% */
+%
+%/* from @(#)ypupdate_prot.x 1.3 91/03/11 TIRPC 1.0 */
+#ifndef RPC_HDR
+%#ifndef lint
+%static const char rcsid[] =
+% "$FreeBSD: src/include/rpcsvc/ypupdate_prot.x,v 1.3 1999/08/27 23:45:13 peter Exp $";
+%#endif
+#endif
+%
+%/*
+% * Compiled from ypupdate_prot.x using rpcgen
+% * This is NOT source code!
+% * DO NOT EDIT THIS FILE!
+% */
+
+/*
+ * YP update service protocol
+ */
+#ifdef RPC_HDR
+%
+%#ifndef _rpcsvc_ypupdate_prot_h
+%#define _rpcsvc_ypupdate_prot_h
+%
+#endif
+
+const MAXMAPNAMELEN = 255;
+const MAXYPDATALEN = 1023;
+const MAXERRMSGLEN = 255;
+
+program YPU_PROG {
+ version YPU_VERS {
+ u_int YPU_CHANGE(ypupdate_args) = 1;
+ u_int YPU_INSERT(ypupdate_args) = 2;
+ u_int YPU_DELETE(ypdelete_args) = 3;
+ u_int YPU_STORE(ypupdate_args) = 4;
+ } = 1;
+} = 100028;
+
+typedef opaque yp_buf<MAXYPDATALEN>;
+
+struct ypupdate_args {
+ string mapname<MAXMAPNAMELEN>;
+ yp_buf key;
+ yp_buf datum;
+};
+
+struct ypdelete_args {
+ string mapname<MAXMAPNAMELEN>;
+ yp_buf key;
+};
+
+#ifdef RPC_HDR
+%
+%#endif /* !_rpcsvc_ypupdate_prot_h */
+#endif
diff --git a/cpukit/librpc/include/rpcsvc/ypxfrd.x b/cpukit/librpc/include/rpcsvc/ypxfrd.x
new file mode 100644
index 0000000000..1845a4f43b
--- /dev/null
+++ b/cpukit/librpc/include/rpcsvc/ypxfrd.x
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 1995, 1996
+ * Bill Paul <wpaul@ctr.columbia.edu>. 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 Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul 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.
+ *
+ * $FreeBSD: src/include/rpcsvc/ypxfrd.x,v 1.7 1999/08/27 23:45:13 peter Exp $
+ */
+
+/*
+ * This protocol definition file describes a file transfer
+ * system used to very quickly move NIS maps from one host to
+ * another. This is similar to what Sun does with their ypxfrd
+ * protocol, but it must be stressed that this protocol is _NOT_
+ * compatible with Sun's. There are a couple of reasons for this:
+ *
+ * 1) Sun's protocol is proprietary. The protocol definition is
+ * not freely available in any of the SunRPC source distributions,
+ * even though the NIS v2 protocol is.
+ *
+ * 2) The idea here is to transfer entire raw files rather than
+ * sending just the records. Sun uses ndbm for its NIS map files,
+ * while FreeBSD uses Berkeley DB. Both are hash databases, but the
+ * formats are incompatible, making it impossible for them to
+ * use each others' files. Even if FreeBSD adopted ndbm for its
+ * database format, FreeBSD/i386 is a little-endian OS and
+ * SunOS/SPARC is big-endian; ndbm is byte-order sensitive and
+ * not very smart about it, which means an attempt to read a
+ * database on a little-endian box that was created on a big-endian
+ * box (or vice-versa) can cause the ndbm code to eat itself.
+ * Luckily, Berkeley DB is able to deal with this situation in
+ * a more graceful manner.
+ *
+ * While the protocol is incompatible, the idea is the same: we just open
+ * up a TCP pipe to the client and transfer the raw map database
+ * from the master server to the slave. This is many times faster than
+ * the standard yppush/ypxfr transfer method since it saves us from
+ * having to recreate the map databases via the DB library each time.
+ * For example: creating a passwd database with 30,000 entries with yp_mkdb
+ * can take a couple of minutes, but to just copy the file takes only a few
+ * seconds.
+ */
+
+#ifndef RPC_HDR
+%#ifndef lint
+%static const char rcsid[] =
+% "$FreeBSD: src/include/rpcsvc/ypxfrd.x,v 1.7 1999/08/27 23:45:13 peter Exp $";
+%#endif /* not lint */
+#endif
+
+/* XXX cribbed from yp.x */
+const _YPMAXRECORD = 1024;
+const _YPMAXDOMAIN = 64;
+const _YPMAXMAP = 64;
+const _YPMAXPEER = 64;
+
+/* Suggested default -- not necesarrily the one used. */
+const YPXFRBLOCK = 32767;
+
+/*
+ * Possible return codes from the remote server.
+ */
+enum xfrstat {
+ XFR_REQUEST_OK = 1, /* Transfer request granted */
+ XFR_DENIED = 2, /* Transfer request denied */
+ XFR_NOFILE = 3, /* Requested map file doesn't exist */
+ XFR_ACCESS = 4, /* File exists, but I couldn't access it */
+ XFR_BADDB = 5, /* File is not a hash database */
+ XFR_READ_OK = 6, /* Block read successfully */
+ XFR_READ_ERR = 7, /* Read error during transfer */
+ XFR_DONE = 8, /* Transfer completed */
+ XFR_DB_ENDIAN_MISMATCH = 9, /* Database byte order mismatch */
+ XFR_DB_TYPE_MISMATCH = 10 /* Database type mismatch */
+};
+
+/*
+ * Database type specifications. The client can use this to ask
+ * the server for a particular type of database or just take whatever
+ * the server has to offer.
+ */
+enum xfr_db_type {
+ XFR_DB_ASCII = 1, /* Flat ASCII text */
+ XFR_DB_BSD_HASH = 2, /* Berkeley DB, hash method */
+ XFR_DB_BSD_BTREE = 3, /* Berkeley DB, btree method */
+ XFR_DB_BSD_RECNO = 4, /* Berkeley DB, recno method */
+ XFR_DB_BSD_MPOOL = 5, /* Berkeley DB, mpool method */
+ XFR_DB_BSD_NDBM = 6, /* Berkeley DB, hash, ndbm compat */
+ XFR_DB_GNU_GDBM = 7, /* GNU GDBM */
+ XFR_DB_DBM = 8, /* Old, deprecated dbm format */
+ XFR_DB_NDBM = 9, /* ndbm format (used by Sun's NISv2) */
+ XFR_DB_OPAQUE = 10, /* Mystery format -- just pass along */
+ XFR_DB_ANY = 11, /* I'll take any format you've got */
+ XFR_DB_UNKNOWN = 12 /* Unknown format */
+};
+
+/*
+ * Machine byte order specification. This allows the client to check
+ * that it's copying a map database from a machine of similar byte sex.
+ * This is necessary for handling database libraries that are fatally
+ * byte order sensitive.
+ *
+ * The XFR_ENDIAN_ANY type is for use with the Berkeley DB database
+ * formats; Berkeley DB is smart enough to make up for byte order
+ * differences, so byte sex isn't important.
+ */
+enum xfr_byte_order {
+ XFR_ENDIAN_BIG = 1, /* We want big endian */
+ XFR_ENDIAN_LITTLE = 2, /* We want little endian */
+ XFR_ENDIAN_ANY = 3 /* We'll take whatever you got */
+};
+
+typedef string xfrdomain<_YPMAXDOMAIN>;
+typedef string xfrmap<_YPMAXMAP>;
+typedef string xfrmap_filename<_YPMAXMAP>; /* actual name of map file */
+
+/*
+ * Ask the remote ypxfrd for a map using this structure.
+ * Note: we supply both a map name and a map file name. These are not
+ * the same thing. In the case of ndbm, maps are stored in two files:
+ * map.bykey.pag and may.bykey.dir. We may also have to deal with
+ * file extensions (on the off chance that the remote server is supporting
+ * multiple DB formats). To handle this, we tell the remote server both
+ * what map we want and, in the case of ndbm, whether we want the .dir
+ * or the .pag part. This name should not be a fully qualified path:
+ * it's up to the remote server to decide which directories to look in.
+ */
+struct ypxfr_mapname {
+ xfrmap xfrmap;
+ xfrdomain xfrdomain;
+ xfrmap_filename xfrmap_filename;
+ xfr_db_type xfr_db_type;
+ xfr_byte_order xfr_byte_order;
+};
+
+/* Read response using this structure. */
+union xfr switch (bool ok) {
+case TRUE:
+ opaque xfrblock_buf<>;
+case FALSE:
+ xfrstat xfrstat;
+};
+
+program YPXFRD_FREEBSD_PROG {
+ version YPXFRD_FREEBSD_VERS {
+ union xfr
+ YPXFRD_GETMAP(ypxfr_mapname) = 1;
+ } = 1;
+} = 600100069; /* 100069 + 60000000 -- 100069 is the Sun ypxfrd prog number */
diff --git a/cpukit/librpc/src/rpc/DISCLAIMER b/cpukit/librpc/src/rpc/DISCLAIMER
new file mode 100644
index 0000000000..1a66d5f4c9
--- /dev/null
+++ b/cpukit/librpc/src/rpc/DISCLAIMER
@@ -0,0 +1,28 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
diff --git a/cpukit/librpc/src/rpc/PSD.doc/nfs.rfc.ms b/cpukit/librpc/src/rpc/PSD.doc/nfs.rfc.ms
new file mode 100644
index 0000000000..0c9a8995b5
--- /dev/null
+++ b/cpukit/librpc/src/rpc/PSD.doc/nfs.rfc.ms
@@ -0,0 +1,1372 @@
+.\"
+.\" Must use -- tbl -- with this one
+.\"
+.\" @(#)nfs.rfc.ms 2.2 88/08/05 4.0 RPCSRC
+.de BT
+.if \\n%=1 .tl ''- % -''
+..
+.ND
+.\" prevent excess underlining in nroff
+.if n .fp 2 R
+.OH 'Network File System: Version 2 Protocol Specification''Page %'
+.EH 'Page %''Network File System: Version 2 Protocol Specification'
+.if \\n%=1 .bp
+.SH
+\&Network File System: Version 2 Protocol Specification
+.IX NFS "" "" "" PAGE MAJOR
+.IX "Network File System" "" "" "" PAGE MAJOR
+.IX NFS "version-2 protocol specification"
+.IX "Network File System" "version-2 protocol specification"
+.LP
+.NH 0
+\&Status of this Standard
+.LP
+Note: This document specifies a protocol that Sun Microsystems, Inc.,
+and others are using. It specifies it in standard ARPA RFC form.
+.NH 1
+\&Introduction
+.IX NFS introduction
+.LP
+The Sun Network Filesystem (NFS) protocol provides transparent remote
+access to shared filesystems over local area networks. The NFS
+protocol is designed to be machine, operating system, network architecture,
+and transport protocol independent. This independence is
+achieved through the use of Remote Procedure Call (RPC) primitives
+built on top of an External Data Representation (XDR). Implementations
+exist for a variety of machines, from personal computers to
+supercomputers.
+.LP
+The supporting mount protocol allows the server to hand out remote
+access privileges to a restricted set of clients. It performs the
+operating system-specific functions that allow, for example, to
+attach remote directory trees to some local file system.
+.NH 2
+\&Remote Procedure Call
+.IX "Remote Procedure Call"
+.LP
+Sun's remote procedure call specification provides a procedure-
+oriented interface to remote services. Each server supplies a
+program that is a set of procedures. NFS is one such "program".
+The combination of host address, program number, and procedure
+number specifies one remote service procedure. RPC does not depend
+on services provided by specific protocols, so it can be used with
+any underlying transport protocol. See the
+.I "Remote Procedure Calls: Protocol Specification"
+chapter of this manual.
+.NH 2
+\&External Data Representation
+.IX "External Data Representation"
+.LP
+The External Data Representation (XDR) standard provides a common
+way of representing a set of data types over a network.
+The NFS
+Protocol Specification is written using the RPC data description
+language.
+For more information, see the
+.I " External Data Representation Standard: Protocol Specification."
+Sun provides implementations of XDR and
+RPC, but NFS does not require their use. Any software that
+provides equivalent functionality can be used, and if the encoding
+is exactly the same it can interoperate with other implementations
+of NFS.
+.NH 2
+\&Stateless Servers
+.IX "stateless servers"
+.IX servers stateless
+.LP
+The NFS protocol is stateless. That is, a server does not need to
+maintain any extra state information about any of its clients in
+order to function correctly. Stateless servers have a distinct
+advantage over stateful servers in the event of a failure. With
+stateless servers, a client need only retry a request until the
+server responds; it does not even need to know that the server has
+crashed, or the network temporarily went down. The client of a
+stateful server, on the other hand, needs to either detect a server
+crash and rebuild the server's state when it comes back up, or
+cause client operations to fail.
+.LP
+This may not sound like an important issue, but it affects the
+protocol in some unexpected ways. We feel that it is worth a bit
+of extra complexity in the protocol to be able to write very simple
+servers that do not require fancy crash recovery.
+.LP
+On the other hand, NFS deals with objects such as files and
+directories that inherently have state -- what good would a file be
+if it did not keep its contents intact? The goal is to not
+introduce any extra state in the protocol itself. Another way to
+simplify recovery is by making operations "idempotent" whenever
+possible (so that they can potentially be repeated).
+.NH 1
+\&NFS Protocol Definition
+.IX NFS "protocol definition"
+.IX NFS protocol
+.LP
+Servers have been known to change over time, and so can the
+protocol that they use. So RPC provides a version number with each
+RPC request. This RFC describes version two of the NFS protocol.
+Even in the second version, there are various obsolete procedures
+and parameters, which will be removed in later versions. An RFC
+for version three of the NFS protocol is currently under
+preparation.
+.NH 2
+\&File System Model
+.IX filesystem model
+.LP
+NFS assumes a file system that is hierarchical, with directories as
+all but the bottom-level files. Each entry in a directory (file,
+directory, device, etc.) has a string name. Different operating
+systems may have restrictions on the depth of the tree or the names
+used, as well as using different syntax to represent the "pathname",
+which is the concatenation of all the "components" (directory and
+file names) in the name. A "file system" is a tree on a single
+server (usually a single disk or physical partition) with a specified
+"root". Some operating systems provide a "mount" operation to make
+all file systems appear as a single tree, while others maintain a
+"forest" of file systems. Files are unstructured streams of
+uninterpreted bytes. Version 3 of NFS uses a slightly more general
+file system model.
+.LP
+NFS looks up one component of a pathname at a time. It may not be
+obvious why it does not just take the whole pathname, traipse down
+the directories, and return a file handle when it is done. There are
+several good reasons not to do this. First, pathnames need
+separators between the directory components, and different operating
+systems use different separators. We could define a Network Standard
+Pathname Representation, but then every pathname would have to be
+parsed and converted at each end. Other issues are discussed in
+\fINFS Implementation Issues\fP below.
+.LP
+Although files and directories are similar objects in many ways,
+different procedures are used to read directories and files. This
+provides a network standard format for representing directories. The
+same argument as above could have been used to justify a procedure
+that returns only one directory entry per call. The problem is
+efficiency. Directories can contain many entries, and a remote call
+to return each would be just too slow.
+.NH 2
+\&RPC Information
+.IX NFS "RPC information"
+.IP \fIAuthentication\fP
+The NFS service uses
+.I AUTH_UNIX ,
+.I AUTH_DES ,
+or
+.I AUTH_SHORT
+style
+authentication, except in the NULL procedure where
+.I AUTH_NONE
+is also allowed.
+.IP "\fITransport Protocols\fP"
+NFS currently is supported on UDP/IP only.
+.IP "\fIPort Number\fP"
+The NFS protocol currently uses the UDP port number 2049. This is
+not an officially assigned port, so later versions of the protocol
+use the \*QPortmapping\*U facility of RPC.
+.NH 2
+\&Sizes of XDR Structures
+.IX "XDR structure sizes"
+.LP
+These are the sizes, given in decimal bytes, of various XDR
+structures used in the protocol:
+.DS
+/* \fIThe maximum number of bytes of data in a READ or WRITE request\fP */
+const MAXDATA = 8192;
+
+/* \fIThe maximum number of bytes in a pathname argument\fP */
+const MAXPATHLEN = 1024;
+
+/* \fIThe maximum number of bytes in a file name argument\fP */
+const MAXNAMLEN = 255;
+
+/* \fIThe size in bytes of the opaque "cookie" passed by READDIR\fP */
+const COOKIESIZE = 4;
+
+/* \fIThe size in bytes of the opaque file handle\fP */
+const FHSIZE = 32;
+.DE
+.NH 2
+\&Basic Data Types
+.IX "NFS data types"
+.IX NFS "basic data types"
+.LP
+The following XDR definitions are basic structures and types used
+in other structures described further on.
+.KS
+.NH 3
+\&stat
+.IX "NFS data types" stat "" \fIstat\fP
+.DS
+enum stat {
+ NFS_OK = 0,
+ NFSERR_PERM=1,
+ NFSERR_NOENT=2,
+ NFSERR_IO=5,
+ NFSERR_NXIO=6,
+ NFSERR_ACCES=13,
+ NFSERR_EXIST=17,
+ NFSERR_NODEV=19,
+ NFSERR_NOTDIR=20,
+ NFSERR_ISDIR=21,
+ NFSERR_FBIG=27,
+ NFSERR_NOSPC=28,
+ NFSERR_ROFS=30,
+ NFSERR_NAMETOOLONG=63,
+ NFSERR_NOTEMPTY=66,
+ NFSERR_DQUOT=69,
+ NFSERR_STALE=70,
+ NFSERR_WFLUSH=99
+};
+.DE
+.KE
+.LP
+The
+.I stat
+type is returned with every procedure's results. A
+value of
+.I NFS_OK
+indicates that the call completed successfully and
+the results are valid. The other values indicate some kind of
+error occurred on the server side during the servicing of the
+procedure. The error values are derived from UNIX error numbers.
+.IP \fBNFSERR_PERM\fP:
+Not owner. The caller does not have correct ownership
+to perform the requested operation.
+.IP \fBNFSERR_NOENT\fP:
+No such file or directory. The file or directory
+specified does not exist.
+.IP \fBNFSERR_IO\fP:
+Some sort of hard error occurred when the operation was
+in progress. This could be a disk error, for example.
+.IP \fBNFSERR_NXIO\fP:
+No such device or address.
+.IP \fBNFSERR_ACCES\fP:
+Permission denied. The caller does not have the
+correct permission to perform the requested operation.
+.IP \fBNFSERR_EXIST\fP:
+File exists. The file specified already exists.
+.IP \fBNFSERR_NODEV\fP:
+No such device.
+.IP \fBNFSERR_NOTDIR\fP:
+Not a directory. The caller specified a
+non-directory in a directory operation.
+.IP \fBNFSERR_ISDIR\fP:
+Is a directory. The caller specified a directory in
+a non- directory operation.
+.IP \fBNFSERR_FBIG\fP:
+File too large. The operation caused a file to grow
+beyond the server's limit.
+.IP \fBNFSERR_NOSPC\fP:
+No space left on device. The operation caused the
+server's filesystem to reach its limit.
+.IP \fBNFSERR_ROFS\fP:
+Read-only filesystem. Write attempted on a read-only filesystem.
+.IP \fBNFSERR_NAMETOOLONG\fP:
+File name too long. The file name in an operation was too long.
+.IP \fBNFSERR_NOTEMPTY\fP:
+Directory not empty. Attempted to remove a
+directory that was not empty.
+.IP \fBNFSERR_DQUOT\fP:
+Disk quota exceeded. The client's disk quota on the
+server has been exceeded.
+.IP \fBNFSERR_STALE\fP:
+The "fhandle" given in the arguments was invalid.
+That is, the file referred to by that file handle no longer exists,
+or access to it has been revoked.
+.IP \fBNFSERR_WFLUSH\fP:
+The server's write cache used in the
+.I WRITECACHE
+call got flushed to disk.
+.LP
+.KS
+.NH 3
+\&ftype
+.IX "NFS data types" ftype "" \fIftype\fP
+.DS
+enum ftype {
+ NFNON = 0,
+ NFREG = 1,
+ NFDIR = 2,
+ NFBLK = 3,
+ NFCHR = 4,
+ NFLNK = 5
+};
+.DE
+.KE
+The enumeration
+.I ftype
+gives the type of a file. The type
+.I NFNON
+indicates a non-file,
+.I NFREG
+is a regular file,
+.I NFDIR
+is a directory,
+.I NFBLK
+is a block-special device,
+.I NFCHR
+is a character-special device, and
+.I NFLNK
+is a symbolic link.
+.KS
+.NH 3
+\&fhandle
+.IX "NFS data types" fhandle "" \fIfhandle\fP
+.DS
+typedef opaque fhandle[FHSIZE];
+.DE
+.KE
+The
+.I fhandle
+is the file handle passed between the server and the client.
+All file operations are done using file handles to refer to a file or
+directory. The file handle can contain whatever information the server
+needs to distinguish an individual file.
+.KS
+.NH 3
+\&timeval
+.IX "NFS data types" timeval "" \fItimeval\fP
+.DS
+struct timeval {
+ unsigned int seconds;
+ unsigned int useconds;
+};
+.DE
+.KE
+The
+.I timeval
+structure is the number of seconds and microseconds
+since midnight January 1, 1970, Greenwich Mean Time. It is used to
+pass time and date information.
+.KS
+.NH 3
+\&fattr
+.IX "NFS data types" fattr "" \fIfattr\fP
+.DS
+struct fattr {
+ ftype type;
+ unsigned int mode;
+ unsigned int nlink;
+ unsigned int uid;
+ unsigned int gid;
+ unsigned int size;
+ unsigned int blocksize;
+ unsigned int rdev;
+ unsigned int blocks;
+ unsigned int fsid;
+ unsigned int fileid;
+ timeval atime;
+ timeval mtime;
+ timeval ctime;
+};
+.DE
+.KE
+The
+.I fattr
+structure contains the attributes of a file; "type" is the type of
+the file; "nlink" is the number of hard links to the file (the number
+of different names for the same file); "uid" is the user
+identification number of the owner of the file; "gid" is the group
+identification number of the group of the file; "size" is the size in
+bytes of the file; "blocksize" is the size in bytes of a block of the
+file; "rdev" is the device number of the file if it is type
+.I NFCHR
+or
+.I NFBLK ;
+"blocks" is the number of blocks the file takes up on disk; "fsid" is
+the file system identifier for the filesystem containing the file;
+"fileid" is a number that uniquely identifies the file within its
+filesystem; "atime" is the time when the file was last accessed for
+either read or write; "mtime" is the time when the file data was last
+modified (written); and "ctime" is the time when the status of the
+file was last changed. Writing to the file also changes "ctime" if
+the size of the file changes.
+.LP
+"mode" is the access mode encoded as a set of bits. Notice that the
+file type is specified both in the mode bits and in the file type.
+This is really a bug in the protocol and will be fixed in future
+versions. The descriptions given below specify the bit positions
+using octal numbers.
+.TS
+box tab (&) ;
+cfI cfI
+lfL l .
+Bit&Description
+_
+0040000&This is a directory; "type" field should be NFDIR.
+0020000&This is a character special file; "type" field should be NFCHR.
+0060000&This is a block special file; "type" field should be NFBLK.
+0100000&This is a regular file; "type" field should be NFREG.
+0120000&This is a symbolic link file; "type" field should be NFLNK.
+0140000&This is a named socket; "type" field should be NFNON.
+0004000&Set user id on execution.
+0002000&Set group id on execution.
+0001000&Save swapped text even after use.
+0000400&Read permission for owner.
+0000200&Write permission for owner.
+0000100&Execute and search permission for owner.
+0000040&Read permission for group.
+0000020&Write permission for group.
+0000010&Execute and search permission for group.
+0000004&Read permission for others.
+0000002&Write permission for others.
+0000001&Execute and search permission for others.
+.TE
+.KS
+Notes:
+.IP
+The bits are the same as the mode bits returned by the
+.I stat(2)
+system call in the UNIX system. The file type is specified both in
+the mode bits and in the file type. This is fixed in future
+versions.
+.IP
+The "rdev" field in the attributes structure is an operating system
+specific device specifier. It will be removed and generalized in
+the next revision of the protocol.
+.KE
+.LP
+.KS
+.NH 3
+\&sattr
+.IX "NFS data types" sattr "" \fIsattr\fP
+.DS
+struct sattr {
+ unsigned int mode;
+ unsigned int uid;
+ unsigned int gid;
+ unsigned int size;
+ timeval atime;
+ timeval mtime;
+};
+.DE
+.KE
+The
+.I sattr
+structure contains the file attributes which can be set
+from the client. The fields are the same as for
+.I fattr
+above. A "size" of zero means the file should be truncated.
+A value of -1 indicates a field that should be ignored.
+.LP
+.KS
+.NH 3
+\&filename
+.IX "NFS data types" filename "" \fIfilename\fP
+.DS
+typedef string filename<MAXNAMLEN>;
+.DE
+.KE
+The type
+.I filename
+is used for passing file names or pathname components.
+.LP
+.KS
+.NH 3
+\&path
+.IX "NFS data types" path "" \fIpath\fP
+.DS
+typedef string path<MAXPATHLEN>;
+.DE
+.KE
+The type
+.I path
+is a pathname. The server considers it as a string
+with no internal structure, but to the client it is the name of a
+node in a filesystem tree.
+.LP
+.KS
+.NH 3
+\&attrstat
+.IX "NFS data types" attrstat "" \fIattrstat\fP
+.DS
+union attrstat switch (stat status) {
+ case NFS_OK:
+ fattr attributes;
+ default:
+ void;
+};
+.DE
+.KE
+The
+.I attrstat
+structure is a common procedure result. It contains
+a "status" and, if the call succeeded, it also contains the
+attributes of the file on which the operation was done.
+.LP
+.KS
+.NH 3
+\&diropargs
+.IX "NFS data types" diropargs "" \fIdiropargs\fP
+.DS
+struct diropargs {
+ fhandle dir;
+ filename name;
+};
+.DE
+.KE
+The
+.I diropargs
+structure is used in directory operations. The
+"fhandle" "dir" is the directory in which to find the file "name".
+A directory operation is one in which the directory is affected.
+.LP
+.KS
+.NH 3
+\&diropres
+.IX "NFS data types" diropres "" \fIdiropres\fP
+.DS
+union diropres switch (stat status) {
+ case NFS_OK:
+ struct {
+ fhandle file;
+ fattr attributes;
+ } diropok;
+ default:
+ void;
+};
+.DE
+.KE
+The results of a directory operation are returned in a
+.I diropres
+structure. If the call succeeded, a new file handle "file" and the
+"attributes" associated with that file are returned along with the
+"status".
+.NH 2
+\&Server Procedures
+.IX "NFS server procedures" "" "" "" PAGE MAJOR
+.LP
+The protocol definition is given as a set of procedures with
+arguments and results defined using the RPC language. A brief
+description of the function of each procedure should provide enough
+information to allow implementation.
+.LP
+All of the procedures in the NFS protocol are assumed to be
+synchronous. When a procedure returns to the client, the client
+can assume that the operation has completed and any data associated
+with the request is now on stable storage. For example, a client
+.I WRITE
+request may cause the server to update data blocks,
+filesystem information blocks (such as indirect blocks), and file
+attribute information (size and modify times). When the
+.I WRITE
+returns to the client, it can assume that the write is safe, even
+in case of a server crash, and it can discard the data written.
+This is a very important part of the statelessness of the server.
+If the server waited to flush data from remote requests, the client
+would have to save those requests so that it could resend them in
+case of a server crash.
+.ie t .DS
+.el .DS L
+
+.ft I
+/*
+* Remote file service routines
+*/
+.ft CW
+program NFS_PROGRAM {
+ version NFS_VERSION {
+ void NFSPROC_NULL(void) = 0;
+ attrstat NFSPROC_GETATTR(fhandle) = 1;
+ attrstat NFSPROC_SETATTR(sattrargs) = 2;
+ void NFSPROC_ROOT(void) = 3;
+ diropres NFSPROC_LOOKUP(diropargs) = 4;
+ readlinkres NFSPROC_READLINK(fhandle) = 5;
+ readres NFSPROC_READ(readargs) = 6;
+ void NFSPROC_WRITECACHE(void) = 7;
+ attrstat NFSPROC_WRITE(writeargs) = 8;
+ diropres NFSPROC_CREATE(createargs) = 9;
+ stat NFSPROC_REMOVE(diropargs) = 10;
+ stat NFSPROC_RENAME(renameargs) = 11;
+ stat NFSPROC_LINK(linkargs) = 12;
+ stat NFSPROC_SYMLINK(symlinkargs) = 13;
+ diropres NFSPROC_MKDIR(createargs) = 14;
+ stat NFSPROC_RMDIR(diropargs) = 15;
+ readdirres NFSPROC_READDIR(readdirargs) = 16;
+ statfsres NFSPROC_STATFS(fhandle) = 17;
+ } = 2;
+} = 100003;
+.DE
+.KS
+.NH 3
+\&Do Nothing
+.IX "NFS server procedures" NFSPROC_NULL() "" \fINFSPROC_NULL()\fP
+.DS
+void
+NFSPROC_NULL(void) = 0;
+.DE
+.KE
+This procedure does no work. It is made available in all RPC
+services to allow server response testing and timing.
+.KS
+.NH 3
+\&Get File Attributes
+.IX "NFS server procedures" NFSPROC_GETATTR() "" \fINFSPROC_GETATTR()\fP
+.DS
+attrstat
+NFSPROC_GETATTR (fhandle) = 1;
+.DE
+.KE
+If the reply status is
+.I NFS_OK ,
+then the reply attributes contains
+the attributes for the file given by the input fhandle.
+.KS
+.NH 3
+\&Set File Attributes
+.IX "NFS server procedures" NFSPROC_SETATTR() "" \fINFSPROC_SETATTR()\fP
+.DS
+struct sattrargs {
+ fhandle file;
+ sattr attributes;
+ };
+
+attrstat
+NFSPROC_SETATTR (sattrargs) = 2;
+.DE
+.KE
+The "attributes" argument contains fields which are either -1 or
+are the new value for the attributes of "file". If the reply
+status is
+.I NFS_OK ,
+then the reply attributes have the attributes of
+the file after the "SETATTR" operation has completed.
+.LP
+Note: The use of -1 to indicate an unused field in "attributes" is
+changed in the next version of the protocol.
+.KS
+.NH 3
+\&Get Filesystem Root
+.IX "NFS server procedures" NFSPROC_ROOT "" \fINFSPROC_ROOT\fP
+.DS
+void
+NFSPROC_ROOT(void) = 3;
+.DE
+.KE
+Obsolete. This procedure is no longer used because finding the
+root file handle of a filesystem requires moving pathnames between
+client and server. To do this right we would have to define a
+network standard representation of pathnames. Instead, the
+function of looking up the root file handle is done by the
+.I MNTPROC_MNT()
+procedure. (See the
+.I "Mount Protocol Definition"
+later in this chapter for details).
+.KS
+.NH 3
+\&Look Up File Name
+.IX "NFS server procedures" NFSPROC_LOOKUP() "" \fINFSPROC_LOOKUP()\fP
+.DS
+diropres
+NFSPROC_LOOKUP(diropargs) = 4;
+.DE
+.KE
+If the reply "status" is
+.I NFS_OK ,
+then the reply "file" and reply
+"attributes" are the file handle and attributes for the file "name"
+in the directory given by "dir" in the argument.
+.KS
+.NH 3
+\&Read From Symbolic Link
+.IX "NFS server procedures" NFSPROC_READLINK() "" \fINFSPROC_READLINK()\fP
+.DS
+union readlinkres switch (stat status) {
+ case NFS_OK:
+ path data;
+ default:
+ void;
+};
+
+readlinkres
+NFSPROC_READLINK(fhandle) = 5;
+.DE
+.KE
+If "status" has the value
+.I NFS_OK ,
+then the reply "data" is the data in
+the symbolic link given by the file referred to by the fhandle argument.
+.LP
+Note: since NFS always parses pathnames on the client, the
+pathname in a symbolic link may mean something different (or be
+meaningless) on a different client or on the server if a different
+pathname syntax is used.
+.KS
+.NH 3
+\&Read From File
+.IX "NFS server procedures" NFSPROC_READ "" \fINFSPROC_READ\fP
+.DS
+struct readargs {
+ fhandle file;
+ unsigned offset;
+ unsigned count;
+ unsigned totalcount;
+};
+
+union readres switch (stat status) {
+ case NFS_OK:
+ fattr attributes;
+ opaque data<NFS_MAXDATA>;
+ default:
+ void;
+};
+
+readres
+NFSPROC_READ(readargs) = 6;
+.DE
+.KE
+Returns up to "count" bytes of "data" from the file given by
+"file", starting at "offset" bytes from the beginning of the file.
+The first byte of the file is at offset zero. The file attributes
+after the read takes place are returned in "attributes".
+.LP
+Note: The argument "totalcount" is unused, and is removed in the
+next protocol revision.
+.KS
+.NH 3
+\&Write to Cache
+.IX "NFS server procedures" NFSPROC_WRITECACHE() "" \fINFSPROC_WRITECACHE()\fP
+.DS
+void
+NFSPROC_WRITECACHE(void) = 7;
+.DE
+.KE
+To be used in the next protocol revision.
+.KS
+.NH 3
+\&Write to File
+.IX "NFS server procedures" NFSPROC_WRITE() "" \fINFSPROC_WRITE()\fP
+.DS
+struct writeargs {
+ fhandle file;
+ unsigned beginoffset;
+ unsigned offset;
+ unsigned totalcount;
+ opaque data<NFS_MAXDATA>;
+};
+
+attrstat
+NFSPROC_WRITE(writeargs) = 8;
+.DE
+.KE
+Writes "data" beginning "offset" bytes from the beginning of
+"file". The first byte of the file is at offset zero. If the
+reply "status" is NFS_OK, then the reply "attributes" contains the
+attributes of the file after the write has completed. The write
+operation is atomic. Data from this call to
+.I WRITE
+will not be mixed with data from another client's calls.
+.LP
+Note: The arguments "beginoffset" and "totalcount" are ignored and
+are removed in the next protocol revision.
+.KS
+.NH 3
+\&Create File
+.IX "NFS server procedures" NFSPROC_CREATE() "" \fINFSPROC_CREATE()\fP
+.DS
+struct createargs {
+ diropargs where;
+ sattr attributes;
+};
+
+diropres
+NFSPROC_CREATE(createargs) = 9;
+.DE
+.KE
+The file "name" is created in the directory given by "dir". The
+initial attributes of the new file are given by "attributes". A
+reply "status" of NFS_OK indicates that the file was created, and
+reply "file" and reply "attributes" are its file handle and
+attributes. Any other reply "status" means that the operation
+failed and no file was created.
+.LP
+Note: This routine should pass an exclusive create flag, meaning
+"create the file only if it is not already there".
+.KS
+.NH 3
+\&Remove File
+.IX "NFS server procedures" NFSPROC_REMOVE() "" \fINFSPROC_REMOVE()\fP
+.DS
+stat
+NFSPROC_REMOVE(diropargs) = 10;
+.DE
+.KE
+The file "name" is removed from the directory given by "dir". A
+reply of NFS_OK means the directory entry was removed.
+.LP
+Note: possibly non-idempotent operation.
+.KS
+.NH 3
+\&Rename File
+.IX "NFS server procedures" NFSPROC_RENAME() "" \fINFSPROC_RENAME()\fP
+.DS
+struct renameargs {
+ diropargs from;
+ diropargs to;
+};
+
+stat
+NFSPROC_RENAME(renameargs) = 11;
+.DE
+.KE
+The existing file "from.name" in the directory given by "from.dir"
+is renamed to "to.name" in the directory given by "to.dir". If the
+reply is
+.I NFS_OK ,
+the file was renamed. The
+RENAME
+operation is
+atomic on the server; it cannot be interrupted in the middle.
+.LP
+Note: possibly non-idempotent operation.
+.KS
+.NH 3
+\&Create Link to File
+.IX "NFS server procedures" NFSPROC_LINK() "" \fINFSPROC_LINK()\fP
+.DS
+struct linkargs {
+ fhandle from;
+ diropargs to;
+};
+
+stat
+NFSPROC_LINK(linkargs) = 12;
+.DE
+.KE
+Creates the file "to.name" in the directory given by "to.dir",
+which is a hard link to the existing file given by "from". If the
+return value is
+.I NFS_OK ,
+a link was created. Any other return value
+indicates an error, and the link was not created.
+.LP
+A hard link should have the property that changes to either of the
+linked files are reflected in both files. When a hard link is made
+to a file, the attributes for the file should have a value for
+"nlink" that is one greater than the value before the link.
+.LP
+Note: possibly non-idempotent operation.
+.KS
+.NH 3
+\&Create Symbolic Link
+.IX "NFS server procedures" NFSPROC_SYMLINK() "" \fINFSPROC_SYMLINK()\fP
+.DS
+struct symlinkargs {
+ diropargs from;
+ path to;
+ sattr attributes;
+};
+
+stat
+NFSPROC_SYMLINK(symlinkargs) = 13;
+.DE
+.KE
+Creates the file "from.name" with ftype
+.I NFLNK
+in the directory
+given by "from.dir". The new file contains the pathname "to" and
+has initial attributes given by "attributes". If the return value
+is
+.I NFS_OK ,
+a link was created. Any other return value indicates an
+error, and the link was not created.
+.LP
+A symbolic link is a pointer to another file. The name given in
+"to" is not interpreted by the server, only stored in the newly
+created file. When the client references a file that is a symbolic
+link, the contents of the symbolic link are normally transparently
+reinterpreted as a pathname to substitute. A
+.I READLINK
+operation returns the data to the client for interpretation.
+.LP
+Note: On UNIX servers the attributes are never used, since
+symbolic links always have mode 0777.
+.KS
+.NH 3
+\&Create Directory
+.IX "NFS server procedures" NFSPROC_MKDIR() "" \fINFSPROC_MKDIR()\fP
+.DS
+diropres
+NFSPROC_MKDIR (createargs) = 14;
+.DE
+.KE
+The new directory "where.name" is created in the directory given by
+"where.dir". The initial attributes of the new directory are given
+by "attributes". A reply "status" of NFS_OK indicates that the new
+directory was created, and reply "file" and reply "attributes" are
+its file handle and attributes. Any other reply "status" means
+that the operation failed and no directory was created.
+.LP
+Note: possibly non-idempotent operation.
+.KS
+.NH 3
+\&Remove Directory
+.IX "NFS server procedures" NFSPROC_RMDIR() "" \fINFSPROC_RMDIR()\fP
+.DS
+stat
+NFSPROC_RMDIR(diropargs) = 15;
+.DE
+.KE
+The existing empty directory "name" in the directory given by "dir"
+is removed. If the reply is
+.I NFS_OK ,
+the directory was removed.
+.LP
+Note: possibly non-idempotent operation.
+.KS
+.NH 3
+\&Read From Directory
+.IX "NFS server procedures" NFSPROC_READDIR() "" \fINFSPROC_READDIR()\fP
+.DS
+struct readdirargs {
+ fhandle dir;
+ nfscookie cookie;
+ unsigned count;
+};
+
+struct entry {
+ unsigned fileid;
+ filename name;
+ nfscookie cookie;
+ entry *nextentry;
+};
+
+union readdirres switch (stat status) {
+ case NFS_OK:
+ struct {
+ entry *entries;
+ bool eof;
+ } readdirok;
+ default:
+ void;
+};
+
+readdirres
+NFSPROC_READDIR (readdirargs) = 16;
+.DE
+.KE
+Returns a variable number of directory entries, with a total size
+of up to "count" bytes, from the directory given by "dir". If the
+returned value of "status" is
+.I NFS_OK ,
+then it is followed by a
+variable number of "entry"s. Each "entry" contains a "fileid"
+which consists of a unique number to identify the file within a
+filesystem, the "name" of the file, and a "cookie" which is an
+opaque pointer to the next entry in the directory. The cookie is
+used in the next
+.I READDIR
+call to get more entries starting at a
+given point in the directory. The special cookie zero (all bits
+zero) can be used to get the entries starting at the beginning of
+the directory. The "fileid" field should be the same number as the
+"fileid" in the the attributes of the file. (See the
+.I "Basic Data Types"
+section.)
+The "eof" flag has a value of
+.I TRUE
+if there are no more entries in the directory.
+.KS
+.NH 3
+\&Get Filesystem Attributes
+.IX "NFS server procedures" NFSPROC_STATFS() "" \fINFSPROC_STATFS()\fP
+.DS
+union statfsres (stat status) {
+ case NFS_OK:
+ struct {
+ unsigned tsize;
+ unsigned bsize;
+ unsigned blocks;
+ unsigned bfree;
+ unsigned bavail;
+ } info;
+ default:
+ void;
+};
+
+statfsres
+NFSPROC_STATFS(fhandle) = 17;
+.DE
+.KE
+If the reply "status" is
+.I NFS_OK ,
+then the reply "info" gives the
+attributes for the filesystem that contains file referred to by the
+input fhandle. The attribute fields contain the following values:
+.IP tsize:
+The optimum transfer size of the server in bytes. This is
+the number of bytes the server would like to have in the
+data part of READ and WRITE requests.
+.IP bsize:
+The block size in bytes of the filesystem.
+.IP blocks:
+The total number of "bsize" blocks on the filesystem.
+.IP bfree:
+The number of free "bsize" blocks on the filesystem.
+.IP bavail:
+The number of "bsize" blocks available to non-privileged users.
+.LP
+Note: This call does not work well if a filesystem has variable
+size blocks.
+.NH 1
+\&NFS Implementation Issues
+.IX NFS implementation
+.LP
+The NFS protocol is designed to be operating system independent, but
+since this version was designed in a UNIX environment, many
+operations have semantics similar to the operations of the UNIX file
+system. This section discusses some of the implementation-specific
+semantic issues.
+.NH 2
+\&Server/Client Relationship
+.IX NFS "server/client relationship"
+.LP
+The NFS protocol is designed to allow servers to be as simple and
+general as possible. Sometimes the simplicity of the server can be a
+problem, if the client wants to implement complicated filesystem
+semantics.
+.LP
+For example, some operating systems allow removal of open files. A
+process can open a file and, while it is open, remove it from the
+directory. The file can be read and written as long as the process
+keeps it open, even though the file has no name in the filesystem.
+It is impossible for a stateless server to implement these semantics.
+The client can do some tricks such as renaming the file on remove,
+and only removing it on close. We believe that the server provides
+enough functionality to implement most file system semantics on the
+client.
+.LP
+Every NFS client can also potentially be a server, and remote and
+local mounted filesystems can be freely intermixed. This leads to
+some interesting problems when a client travels down the directory
+tree of a remote filesystem and reaches the mount point on the server
+for another remote filesystem. Allowing the server to follow the
+second remote mount would require loop detection, server lookup, and
+user revalidation. Instead, we decided not to let clients cross a
+server's mount point. When a client does a LOOKUP on a directory on
+which the server has mounted a filesystem, the client sees the
+underlying directory instead of the mounted directory. A client can
+do remote mounts that match the server's mount points to maintain the
+server's view.
+.LP
+.NH 2
+\&Pathname Interpretation
+.IX NFS "pathname interpretation"
+.LP
+There are a few complications to the rule that pathnames are always
+parsed on the client. For example, symbolic links could have
+different interpretations on different clients. Another common
+problem for non-UNIX implementations is the special interpretation of
+the pathname ".." to mean the parent of a given directory. The next
+revision of the protocol uses an explicit flag to indicate the parent
+instead.
+.NH 2
+\&Permission Issues
+.IX NFS "permission issues"
+.LP
+The NFS protocol, strictly speaking, does not define the permission
+checking used by servers. However, it is expected that a server
+will do normal operating system permission checking using
+.I AUTH_UNIX
+style authentication as the basis of its protection mechanism. The
+server gets the client's effective "uid", effective "gid", and groups
+on each call and uses them to check permission. There are various
+problems with this method that can been resolved in interesting ways.
+.LP
+Using "uid" and "gid" implies that the client and server share the
+same "uid" list. Every server and client pair must have the same
+mapping from user to "uid" and from group to "gid". Since every
+client can also be a server, this tends to imply that the whole
+network shares the same "uid/gid" space.
+.I AUTH_DES
+(and the next
+revision of the NFS protocol) uses string names instead of numbers,
+but there are still complex problems to be solved.
+.LP
+Another problem arises due to the usually stateful open operation.
+Most operating systems check permission at open time, and then check
+that the file is open on each read and write request. With stateless
+servers, the server has no idea that the file is open and must do
+permission checking on each read and write call. On a local
+filesystem, a user can open a file and then change the permissions so
+that no one is allowed to touch it, but will still be able to write
+to the file because it is open. On a remote filesystem, by contrast,
+the write would fail. To get around this problem, the server's
+permission checking algorithm should allow the owner of a file to
+access it regardless of the permission setting.
+.LP
+A similar problem has to do with paging in from a file over the
+network. The operating system usually checks for execute permission
+before opening a file for demand paging, and then reads blocks from
+the open file. The file may not have read permission, but after it
+is opened it doesn't matter. An NFS server can not tell the
+difference between a normal file read and a demand page-in read. To
+make this work, the server allows reading of files if the "uid" given
+in the call has execute or read permission on the file.
+.LP
+In most operating systems, a particular user (on the user ID zero)
+has access to all files no matter what permission and ownership they
+have. This "super-user" permission may not be allowed on the server,
+since anyone who can become super-user on their workstation could
+gain access to all remote files. The UNIX server by default maps
+user id 0 to -2 before doing its access checking. This works except
+for NFS root filesystems, where super-user access cannot be avoided.
+.NH 2
+\&Setting RPC Parameters
+.IX NFS "setting RPC parameters"
+.LP
+Various file system parameters and options should be set at mount
+time. The mount protocol is described in the appendix below. For
+example, "Soft" mounts as well as "Hard" mounts are usually both
+provided. Soft mounted file systems return errors when RPC
+operations fail (after a given number of optional retransmissions),
+while hard mounted file systems continue to retransmit forever.
+Clients and servers may need to keep caches of recent operations to
+help avoid problems with non-idempotent operations.
+.NH 1
+\&Mount Protocol Definition
+.IX "mount protocol" "" "" "" PAGE MAJOR
+.sp 1
+.NH 2
+\&Introduction
+.IX "mount protocol" introduction
+.LP
+The mount protocol is separate from, but related to, the NFS
+protocol. It provides operating system specific services to get the
+NFS off the ground -- looking up server path names, validating user
+identity, and checking access permissions. Clients use the mount
+protocol to get the first file handle, which allows them entry into a
+remote filesystem.
+.LP
+The mount protocol is kept separate from the NFS protocol to make it
+easy to plug in new access checking and validation methods without
+changing the NFS server protocol.
+.LP
+Notice that the protocol definition implies stateful servers because
+the server maintains a list of client's mount requests. The mount
+list information is not critical for the correct functioning of
+either the client or the server. It is intended for advisory use
+only, for example, to warn possible clients when a server is going
+down.
+.LP
+Version one of the mount protocol is used with version two of the NFS
+protocol. The only connecting point is the
+.I fhandle
+structure, which is the same for both protocols.
+.NH 2
+\&RPC Information
+.IX "mount protocol" "RPC information"
+.IP \fIAuthentication\fP
+The mount service uses
+.I AUTH_UNIX
+and
+.I AUTH_DES
+style authentication only.
+.IP "\fITransport Protocols\fP"
+The mount service is currently supported on UDP/IP only.
+.IP "\fIPort Number\fP"
+Consult the server's portmapper, described in the chapter
+.I "Remote Procedure Calls: Protocol Specification",
+to find the port number on which the mount service is registered.
+.NH 2
+\&Sizes of XDR Structures
+.IX "mount protocol" "XDR structure sizes"
+.LP
+These are the sizes, given in decimal bytes, of various XDR
+structures used in the protocol:
+.DS
+/* \fIThe maximum number of bytes in a pathname argument\fP */
+const MNTPATHLEN = 1024;
+
+/* \fIThe maximum number of bytes in a name argument\fP */
+const MNTNAMLEN = 255;
+
+/* \fIThe size in bytes of the opaque file handle\fP */
+const FHSIZE = 32;
+.DE
+.NH 2
+\&Basic Data Types
+.IX "mount protocol" "basic data types"
+.IX "mount data types"
+.LP
+This section presents the data types used by the mount protocol.
+In many cases they are similar to the types used in NFS.
+.KS
+.NH 3
+\&fhandle
+.IX "mount data types" fhandle "" \fIfhandle\fP
+.DS
+typedef opaque fhandle[FHSIZE];
+.DE
+.KE
+The type
+.I fhandle
+is the file handle that the server passes to the
+client. All file operations are done using file handles to refer
+to a file or directory. The file handle can contain whatever
+information the server needs to distinguish an individual file.
+.LP
+This is the same as the "fhandle" XDR definition in version 2 of
+the NFS protocol; see
+.I "Basic Data Types"
+in the definition of the NFS protocol, above.
+.KS
+.NH 3
+\&fhstatus
+.IX "mount data types" fhstatus "" \fIfhstatus\fP
+.DS
+union fhstatus switch (unsigned status) {
+ case 0:
+ fhandle directory;
+ default:
+ void;
+};
+.DE
+.KE
+The type
+.I fhstatus
+is a union. If a "status" of zero is returned,
+the call completed successfully, and a file handle for the
+"directory" follows. A non-zero status indicates some sort of
+error. In this case the status is a UNIX error number.
+.KS
+.NH 3
+\&dirpath
+.IX "mount data types" dirpath "" \fIdirpath\fP
+.DS
+typedef string dirpath<MNTPATHLEN>;
+.DE
+.KE
+The type
+.I dirpath
+is a server pathname of a directory.
+.KS
+.NH 3
+\&name
+.IX "mount data types" name "" \fIname\fP
+.DS
+typedef string name<MNTNAMLEN>;
+.DE
+.KE
+The type
+.I name
+is an arbitrary string used for various names.
+.NH 2
+\&Server Procedures
+.IX "mount server procedures"
+.LP
+The following sections define the RPC procedures supplied by a
+mount server.
+.ie t .DS
+.el .DS L
+.ft I
+/*
+* Protocol description for the mount program
+*/
+.ft CW
+
+program MOUNTPROG {
+.ft I
+/*
+* Version 1 of the mount protocol used with
+* version 2 of the NFS protocol.
+*/
+.ft CW
+ version MOUNTVERS {
+ void MOUNTPROC_NULL(void) = 0;
+ fhstatus MOUNTPROC_MNT(dirpath) = 1;
+ mountlist MOUNTPROC_DUMP(void) = 2;
+ void MOUNTPROC_UMNT(dirpath) = 3;
+ void MOUNTPROC_UMNTALL(void) = 4;
+ exportlist MOUNTPROC_EXPORT(void) = 5;
+ } = 1;
+} = 100005;
+.DE
+.KS
+.NH 3
+\&Do Nothing
+.IX "mount server procedures" MNTPROC_NULL() "" \fIMNTPROC_NULL()\fP
+.DS
+void
+MNTPROC_NULL(void) = 0;
+.DE
+.KE
+This procedure does no work. It is made available in all RPC
+services to allow server response testing and timing.
+.KS
+.NH 3
+\&Add Mount Entry
+.IX "mount server procedures" MNTPROC_MNT() "" \fIMNTPROC_MNT()\fP
+.DS
+fhstatus
+MNTPROC_MNT(dirpath) = 1;
+.DE
+.KE
+If the reply "status" is 0, then the reply "directory" contains the
+file handle for the directory "dirname". This file handle may be
+used in the NFS protocol. This procedure also adds a new entry to
+the mount list for this client mounting "dirname".
+.KS
+.NH 3
+\&Return Mount Entries
+.IX "mount server procedures" MNTPROC_DUMP() "" \fIMNTPROC_DUMP()\fP
+.DS
+struct *mountlist {
+ name hostname;
+ dirpath directory;
+ mountlist nextentry;
+};
+
+mountlist
+MNTPROC_DUMP(void) = 2;
+.DE
+.KE
+Returns the list of remote mounted filesystems. The "mountlist"
+contains one entry for each "hostname" and "directory" pair.
+.KS
+.NH 3
+\&Remove Mount Entry
+.IX "mount server procedures" MNTPROC_UMNT() "" \fIMNTPROC_UMNT()\fP
+.DS
+void
+MNTPROC_UMNT(dirpath) = 3;
+.DE
+.KE
+Removes the mount list entry for the input "dirpath".
+.KS
+.NH 3
+\&Remove All Mount Entries
+.IX "mount server procedures" MNTPROC_UMNTALL() "" \fIMNTPROC_UMNTALL()\fP
+.DS
+void
+MNTPROC_UMNTALL(void) = 4;
+.DE
+.KE
+Removes all of the mount list entries for this client.
+.KS
+.NH 3
+\&Return Export List
+.IX "mount server procedures" MNTPROC_EXPORT() "" \fIMNTPROC_EXPORT()\fP
+.DS
+struct *groups {
+ name grname;
+ groups grnext;
+};
+
+struct *exportlist {
+ dirpath filesys;
+ groups groups;
+ exportlist next;
+};
+
+exportlist
+MNTPROC_EXPORT(void) = 5;
+.DE
+.KE
+Returns a variable number of export list entries. Each entry
+contains a filesystem name and a list of groups that are allowed to
+import it. The filesystem name is in "filesys", and the group name
+is in the list "groups".
+.LP
+Note: The exportlist should contain
+more information about the status of the filesystem, such as a
+read-only flag.
diff --git a/cpukit/librpc/src/rpc/PSD.doc/rpc.prog.ms b/cpukit/librpc/src/rpc/PSD.doc/rpc.prog.ms
new file mode 100644
index 0000000000..3b02447fe8
--- /dev/null
+++ b/cpukit/librpc/src/rpc/PSD.doc/rpc.prog.ms
@@ -0,0 +1,2684 @@
+.\"
+.\" Must use -- tbl and pic -- with this one
+.\"
+.\" @(#)rpc.prog.ms 2.3 88/08/11 4.0 RPCSRC
+.de BT
+.if \\n%=1 .tl ''- % -''
+..
+.IX "Network Programming" "" "" "" PAGE MAJOR
+.nr OF 0
+.ND
+.\" prevent excess underlining in nroff
+.if n .fp 2 R
+.OH 'Remote Procedure Call Programming Guide''Page %'
+.EH 'Page %''Remote Procedure Call Programming Guide'
+.SH
+\&Remote Procedure Call Programming Guide
+.nr OF 1
+.IX "RPC Programming Guide"
+.LP
+This document assumes a working knowledge of network theory. It is
+intended for programmers who wish to write network applications using
+remote procedure calls (explained below), and who want to understand
+the RPC mechanisms usually hidden by the
+.I rpcgen(1)
+protocol compiler.
+.I rpcgen
+is described in detail in the previous chapter, the
+.I "\fBrpcgen\fP \fIProgramming Guide\fP".
+.SH
+Note:
+.I
+.IX rpcgen "" \fIrpcgen\fP
+Before attempting to write a network application, or to convert an
+existing non-network application to run over the network, you may want to
+understand the material in this chapter. However, for most applications,
+you can circumvent the need to cope with the details presented here by using
+.I rpcgen .
+The
+.I "Generating XDR Routines"
+section of that chapter contains the complete source for a working RPC
+service\(ema remote directory listing service which uses
+.I rpcgen
+to generate XDR routines as well as client and server stubs.
+.LP
+.LP
+What are remote procedure calls? Simply put, they are the high-level
+communications paradigm used in the operating system.
+RPC presumes the existence of
+low-level networking mechanisms (such as TCP/IP and UDP/IP), and upon them
+it implements a logical client to server communications system designed
+specifically for the support of network applications. With RPC, the client
+makes a procedure call to send a data packet to the server. When the
+packet arrives, the server calls a dispatch routine, performs whatever
+service is requested, sends back the reply, and the procedure call returns
+to the client.
+.NH 0
+\&Layers of RPC
+.IX "layers of RPC"
+.IX "RPC" "layers"
+.LP
+The RPC interface can be seen as being divided into three layers.\**
+.FS
+For a complete specification of the routines in the remote procedure
+call Library, see the
+.I rpc(3N)
+manual page.
+.FE
+.LP
+.I "The Highest Layer:"
+.IX RPC "The Highest Layer"
+The highest layer is totally transparent to the operating system,
+machine and network upon which is is run. It's probably best to
+think of this level as a way of
+.I using
+RPC, rather than as
+a \fIpart of\fP RPC proper. Programmers who write RPC routines
+should (almost) always make this layer available to others by way
+of a simple C front end that entirely hides the networking.
+.LP
+To illustrate, at this level a program can simply make a call to
+.I rnusers (),
+a C routine which returns the number of users on a remote machine.
+The user is not explicitly aware of using RPC \(em they simply
+call a procedure, just as they would call
+.I malloc() .
+.LP
+.I "The Middle Layer:"
+.IX RPC "The Middle Layer"
+The middle layer is really \*QRPC proper.\*U Here, the user doesn't
+need to consider details about sockets, the UNIX system, or other low-level
+implementation mechanisms. They simply make remote procedure calls
+to routines on other machines. The selling point here is simplicity.
+It's this layer that allows RPC to pass the \*Qhello world\*U test \(em
+simple things should be simple. The middle-layer routines are used
+for most applications.
+.LP
+RPC calls are made with the system routines
+.I registerrpc()
+.I callrpc()
+and
+.I svc_run ().
+The first two of these are the most fundamental:
+.I registerrpc()
+obtains a unique system-wide procedure-identification number, and
+.I callrpc()
+actually executes a remote procedure call. At the middle level, a
+call to
+.I rnusers()
+is implemented by way of these two routines.
+.LP
+The middle layer is unfortunately rarely used in serious programming
+due to its inflexibility (simplicity). It does not allow timeout
+specifications or the choice of transport. It allows no UNIX
+process control or flexibility in case of errors. It doesn't support
+multiple kinds of call authentication. The programmer rarely needs
+all these kinds of control, but one or two of them is often necessary.
+.LP
+.I "The Lowest Layer:"
+.IX RPC "The Lowest Layer"
+The lowest layer does allow these details to be controlled by the
+programmer, and for that reason it is often necessary. Programs
+written at this level are also most efficient, but this is rarely a
+real issue \(em since RPC clients and servers rarely generate
+heavy network loads.
+.LP
+Although this document only discusses the interface to C,
+remote procedure calls can be made from any language.
+Even though this document discusses RPC
+when it is used to communicate
+between processes on different machines,
+it works just as well for communication
+between different processes on the same machine.
+.br
+.KS
+.NH 2
+\&The RPC Paradigm
+.IX RPC paradigm
+.LP
+Here is a diagram of the RPC paradigm:
+.LP
+\fBFigure 1-1\fI Network Communication with the Remote Reocedure Call\fR
+.LP
+.PS
+L1: arrow down 1i "client " rjust "program " rjust
+L2: line right 1.5i "\fIcallrpc\fP" "function"
+move up 1.5i; line dotted down 6i; move up 4.5i
+arrow right 1i
+L3: arrow down 1i "invoke " rjust "service " rjust
+L4: arrow right 1.5i "call" "service"
+L5: arrow down 1i " service" ljust " executes" ljust
+L6: arrow left 1.5i "\fIreturn\fP" "answer"
+L7: arrow down 1i "request " rjust "completed " rjust
+L8: line left 1i
+arrow left 1.5i "\fIreturn\fP" "reply"
+L9: arrow down 1i "program " rjust "continues " rjust
+line dashed down from L2 to L9
+line dashed down from L4 to L7
+line dashed up 1i from L3 "service " rjust "daemon " rjust
+arrow dashed down 1i from L8
+move right 1i from L3
+box invis "Machine B"
+move left 1.2i from L2; move down
+box invis "Machine A"
+.PE
+.KE
+.KS
+.NH 1
+\&Higher Layers of RPC
+.NH 2
+\&Highest Layer
+.IX "highest layer of RPC"
+.IX RPC "highest layer"
+.LP
+Imagine you're writing a program that needs to know
+how many users are logged into a remote machine.
+You can do this by calling the RPC library routine
+.I rnusers()
+as illustrated below:
+.ie t .DS
+.el .DS L
+.ft CW
+#include <stdio.h>
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ int num;
+
+ if (argc != 2) {
+ fprintf(stderr, "usage: rnusers hostname\en");
+ exit(1);
+ }
+ if ((num = rnusers(argv[1])) < 0) {
+ fprintf(stderr, "error: rnusers\en");
+ exit(-1);
+ }
+ printf("%d users on %s\en", num, argv[1]);
+ exit(0);
+}
+.DE
+.KE
+RPC library routines such as
+.I rnusers()
+are in the RPC services library
+.I librpcsvc.a
+Thus, the program above should be compiled with
+.DS
+.ft CW
+% cc \fIprogram.c -lrpcsvc\fP
+.DE
+.I rnusers (),
+like the other RPC library routines, is documented in section 3R
+of the
+.I "System Interface Manual for the Sun Workstation" ,
+the same section which documents the standard Sun RPC services.
+.IX "RPC Services"
+See the
+.I intro(3R)
+manual page for an explanation of the documentation strategy
+for these services and their RPC protocols.
+.LP
+Here are some of the RPC service library routines available to the
+C programmer:
+.LP
+\fBTable 3-3\fI RPC Service Library Routines\RP
+.TS
+box tab (&) ;
+cfI cfI
+lfL l .
+Routine&Description
+_
+.sp.5
+rnusers&Return number of users on remote machine
+rusers&Return information about users on remote machine
+havedisk&Determine if remote machine has disk
+rstats&Get performance data from remote kernel
+rwall&Write to specified remote machines
+yppasswd&Update user password in Yellow Pages
+.TE
+.LP
+Other RPC services \(em for example
+.I ether()
+.I mount
+.I rquota()
+and
+.I spray
+\(em are not available to the C programmer as library routines.
+They do, however,
+have RPC program numbers so they can be invoked with
+.I callrpc()
+which will be discussed in the next section. Most of them also
+have compilable
+.I rpcgen(1)
+protocol description files. (The
+.I rpcgen
+protocol compiler radically simplifies the process of developing
+network applications.
+See the \fBrpcgen\fI Programming Guide\fR
+for detailed information about
+.I rpcgen
+and
+.I rpcgen
+protocol description files).
+.KS
+.NH 2
+\&Intermediate Layer
+.IX "intermediate layer of RPC"
+.IX "RPC" "intermediate layer"
+.LP
+The simplest interface, which explicitly makes RPC calls, uses the
+functions
+.I callrpc()
+and
+.I registerrpc()
+Using this method, the number of remote users can be gotten as follows:
+.ie t .DS
+.el .DS L
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <utmp.h>
+#include <rpcsvc/rusers.h>
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ unsigned long nusers;
+ int stat;
+
+ if (argc != 2) {
+ fprintf(stderr, "usage: nusers hostname\en");
+ exit(-1);
+ }
+ if (stat = callrpc(argv[1],
+ RUSERSPROG, RUSERSVERS, RUSERSPROC_NUM,
+ xdr_void, 0, xdr_u_long, &nusers) != 0) {
+ clnt_perrno(stat);
+ exit(1);
+ }
+ printf("%d users on %s\en", nusers, argv[1]);
+ exit(0);
+}
+.DE
+.KE
+Each RPC procedure is uniquely defined by a program number,
+version number, and procedure number. The program number
+specifies a group of related remote procedures, each of
+which has a different procedure number. Each program also
+has a version number, so when a minor change is made to a
+remote service (adding a new procedure, for example), a new
+program number doesn't have to be assigned. When you want
+to call a procedure to find the number of remote users, you
+look up the appropriate program, version and procedure numbers
+in a manual, just as you look up the name of a memory allocator
+when you want to allocate memory.
+.LP
+The simplest way of making remote procedure calls is with the the RPC
+library routine
+.I callrpc()
+It has eight parameters. The first is the name of the remote server
+machine. The next three parameters are the program, version, and procedure
+numbers\(emtogether they identify the procedure to be called.
+The fifth and sixth parameters are an XDR filter and an argument to
+be encoded and passed to the remote procedure.
+The final two parameters are a filter for decoding the results
+returned by the remote procedure and a pointer to the place where
+the procedure's results are to be stored. Multiple arguments and
+results are handled by embedding them in structures. If
+.I callrpc()
+completes successfully, it returns zero; else it returns a nonzero
+value. The return codes (of type
+.IX "enum clnt_stat (in RPC programming)" "" "\fIenum clnt_stat\fP (in RPC programming)"
+cast into an integer) are found in
+.I <rpc/clnt.h> .
+.LP
+Since data types may be represented differently on different machines,
+.I callrpc()
+needs both the type of the RPC argument, as well as
+a pointer to the argument itself (and similarly for the result). For
+.I RUSERSPROC_NUM ,
+the return value is an
+.I "unsigned long"
+so
+.I callrpc()
+has
+.I xdr_u_long()
+as its first return parameter, which says
+that the result is of type
+.I "unsigned long"
+and
+.I &nusers
+as its second return parameter,
+which is a pointer to where the long result will be placed. Since
+.I RUSERSPROC_NUM
+takes no argument, the argument parameter of
+.I callrpc()
+is
+.I xdr_void ().
+.LP
+After trying several times to deliver a message, if
+.I callrpc()
+gets no answer, it returns with an error code.
+The delivery mechanism is UDP,
+which stands for User Datagram Protocol.
+Methods for adjusting the number of retries
+or for using a different protocol require you to use the lower
+layer of the RPC library, discussed later in this document.
+The remote server procedure
+corresponding to the above might look like this:
+.ie t .DS
+.el .DS L
+.ft CW
+.ft CW
+char *
+nuser(indata)
+ char *indata;
+{
+ unsigned long nusers;
+
+.ft I
+ /*
+ * Code here to compute the number of users
+ * and place result in variable \fInusers\fP.
+ */
+.ft CW
+ return((char *)&nusers);
+}
+.DE
+.LP
+It takes one argument, which is a pointer to the input
+of the remote procedure call (ignored in our example),
+and it returns a pointer to the result.
+In the current version of C,
+character pointers are the generic pointers,
+so both the input argument and the return value are cast to
+.I "char *" .
+.LP
+Normally, a server registers all of the RPC calls it plans
+to handle, and then goes into an infinite loop waiting to service requests.
+In this example, there is only a single procedure
+to register, so the main body of the server would look like this:
+.ie t .DS
+.el .DS L
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <utmp.h>
+#include <rpcsvc/rusers.h>
+
+char *nuser();
+
+main()
+{
+ registerrpc(RUSERSPROG, RUSERSVERS, RUSERSPROC_NUM,
+ nuser, xdr_void, xdr_u_long);
+ svc_run(); /* \fINever returns\fP */
+ fprintf(stderr, "Error: svc_run returned!\en");
+ exit(1);
+}
+.DE
+.LP
+The
+.I registerrpc()
+routine registers a C procedure as corresponding to a
+given RPC procedure number. The first three parameters,
+.I RUSERPROG ,
+.I RUSERSVERS ,
+and
+.I RUSERSPROC_NUM
+are the program, version, and procedure numbers
+of the remote procedure to be registered;
+.I nuser()
+is the name of the local procedure that implements the remote
+procedure; and
+.I xdr_void()
+and
+.I xdr_u_long()
+are the XDR filters for the remote procedure's arguments and
+results, respectively. (Multiple arguments or multiple results
+are passed as structures).
+.LP
+Only the UDP transport mechanism can use
+.I registerrpc()
+thus, it is always safe in conjunction with calls generated by
+.I callrpc() .
+.SH
+.IX "UDP 8K warning"
+Warning: the UDP transport mechanism can only deal with
+arguments and results less than 8K bytes in length.
+.LP
+.LP
+After registering the local procedure, the server program's
+main procedure calls
+.I svc_run (),
+the RPC library's remote procedure dispatcher. It is this
+function that calls the remote procedures in response to RPC
+call messages. Note that the dispatcher takes care of decoding
+remote procedure arguments and encoding results, using the XDR
+filters specified when the remote procedure was registered.
+.NH 2
+\&Assigning Program Numbers
+.IX "program number assignment"
+.IX "assigning program numbers"
+.LP
+Program numbers are assigned in groups of
+.I 0x20000000
+according to the following chart:
+.DS
+.ft CW
+ 0x0 - 0x1fffffff \fRDefined by Sun\fP
+0x20000000 - 0x3fffffff \fRDefined by user\fP
+0x40000000 - 0x5fffffff \fRTransient\fP
+0x60000000 - 0x7fffffff \fRReserved\fP
+0x80000000 - 0x9fffffff \fRReserved\fP
+0xa0000000 - 0xbfffffff \fRReserved\fP
+0xc0000000 - 0xdfffffff \fRReserved\fP
+0xe0000000 - 0xffffffff \fRReserved\fP
+.ft R
+.DE
+Sun Microsystems administers the first group of numbers, which
+should be identical for all Sun customers. If a customer
+develops an application that might be of general interest, that
+application should be given an assigned number in the first
+range. The second group of numbers is reserved for specific
+customer applications. This range is intended primarily for
+debugging new programs. The third group is reserved for
+applications that generate program numbers dynamically. The
+final groups are reserved for future use, and should not be
+used.
+.LP
+To register a protocol specification, send a request by network
+mail to
+.I rpc@sun
+or write to:
+.DS
+RPC Administrator
+Sun Microsystems
+2550 Garcia Ave.
+Mountain View, CA 94043
+.DE
+Please include a compilable
+.I rpcgen
+\*Q.x\*U file describing your protocol.
+You will be given a unique program number in return.
+.IX RPC administration
+.IX administration "of RPC"
+.LP
+The RPC program numbers and protocol specifications
+of standard Sun RPC services can be
+found in the include files in
+.I "/usr/include/rpcsvc" .
+These services, however, constitute only a small subset
+of those which have been registered. The complete list of
+registered programs, as of the time when this manual was
+printed, is:
+.LP
+\fBTable 3-2\fI RPC Registered Programs\fR
+.TS H
+box tab (&) ;
+lfBI lfBI lfBI
+lfL lfL lfI .
+RPC Number&Program&Description
+_
+.TH
+.sp.5
+100000&PMAPPROG&portmapper
+100001&RSTATPROG&remote stats
+100002&RUSERSPROG&remote users
+100003&NFSPROG&nfs
+100004&YPPROG&Yellow Pages
+100005&MOUNTPROG&mount demon
+100006&DBXPROG&remote dbx
+100007&YPBINDPROG&yp binder
+100008&WALLPROG&shutdown msg
+100009&YPPASSWDPROG&yppasswd server
+100010&ETHERSTATPROG&ether stats
+100011&RQUOTAPROG&disk quotas
+100012&SPRAYPROG&spray packets
+100013&IBM3270PROG&3270 mapper
+100014&IBMRJEPROG&RJE mapper
+100015&SELNSVCPROG&selection service
+100016&RDATABASEPROG&remote database access
+100017&REXECPROG&remote execution
+100018&ALICEPROG&Alice Office Automation
+100019&SCHEDPROG&scheduling service
+100020&LOCKPROG&local lock manager
+100021&NETLOCKPROG&network lock manager
+100022&X25PROG&x.25 inr protocol
+100023&STATMON1PROG&status monitor 1
+100024&STATMON2PROG&status monitor 2
+100025&SELNLIBPROG&selection library
+100026&BOOTPARAMPROG&boot parameters service
+100027&MAZEPROG&mazewars game
+100028&YPUPDATEPROG&yp update
+100029&KEYSERVEPROG&key server
+100030&SECURECMDPROG&secure login
+100031&NETFWDIPROG&nfs net forwarder init
+100032&NETFWDTPROG&nfs net forwarder trans
+100033&SUNLINKMAP_PROG&sunlink MAP
+100034&NETMONPROG&network monitor
+100035&DBASEPROG&lightweight database
+100036&PWDAUTHPROG&password authorization
+100037&TFSPROG&translucent file svc
+100038&NSEPROG&nse server
+100039&NSE_ACTIVATE_PROG&nse activate daemon
+.sp .2i
+150001&PCNFSDPROG&pc passwd authorization
+.sp .2i
+200000&PYRAMIDLOCKINGPROG&Pyramid-locking
+200001&PYRAMIDSYS5&Pyramid-sys5
+200002&CADDS_IMAGE&CV cadds_image
+.sp .2i
+300001&ADT_RFLOCKPROG&ADT file locking
+.TE
+.NH 2
+\&Passing Arbitrary Data Types
+.IX "arbitrary data types"
+.LP
+In the previous example, the RPC call passes a single
+.I "unsigned long"
+RPC can handle arbitrary data structures, regardless of
+different machines' byte orders or structure layout conventions,
+by always converting them to a network standard called
+.I "External Data Representation"
+(XDR) before
+sending them over the wire.
+The process of converting from a particular machine representation
+to XDR format is called
+.I serializing ,
+and the reverse process is called
+.I deserializing .
+The type field parameters of
+.I callrpc()
+and
+.I registerrpc()
+can be a built-in procedure like
+.I xdr_u_long()
+in the previous example, or a user supplied one.
+XDR has these built-in type routines:
+.IX RPC "built-in routines"
+.DS
+.ft CW
+xdr_int() xdr_u_int() xdr_enum()
+xdr_long() xdr_u_long() xdr_bool()
+xdr_short() xdr_u_short() xdr_wrapstring()
+xdr_char() xdr_u_char()
+.DE
+Note that the routine
+.I xdr_string()
+exists, but cannot be used with
+.I callrpc()
+and
+.I registerrpc (),
+which only pass two parameters to their XDR routines.
+.I xdr_wrapstring()
+has only two parameters, and is thus OK. It calls
+.I xdr_string ().
+.LP
+As an example of a user-defined type routine,
+if you wanted to send the structure
+.DS
+.ft CW
+struct simple {
+ int a;
+ short b;
+} simple;
+.DE
+then you would call
+.I callrpc()
+as
+.DS
+.ft CW
+callrpc(hostname, PROGNUM, VERSNUM, PROCNUM,
+ xdr_simple, &simple ...);
+.DE
+where
+.I xdr_simple()
+is written as:
+.ie t .DS
+.el .DS L
+.ft CW
+#include <rpc/rpc.h>
+
+xdr_simple(xdrsp, simplep)
+ XDR *xdrsp;
+ struct simple *simplep;
+{
+ if (!xdr_int(xdrsp, &simplep->a))
+ return (0);
+ if (!xdr_short(xdrsp, &simplep->b))
+ return (0);
+ return (1);
+}
+.DE
+.LP
+An XDR routine returns nonzero (true in the sense of C) if it
+completes successfully, and zero otherwise.
+A complete description of XDR is in the
+.I "XDR Protocol Specification"
+section of this manual, only few implementation examples are
+given here.
+.LP
+In addition to the built-in primitives,
+there are also the prefabricated building blocks:
+.DS
+.ft CW
+xdr_array() xdr_bytes() xdr_reference()
+xdr_vector() xdr_union() xdr_pointer()
+xdr_string() xdr_opaque()
+.DE
+To send a variable array of integers,
+you might package them up as a structure like this
+.DS
+.ft CW
+struct varintarr {
+ int *data;
+ int arrlnth;
+} arr;
+.DE
+and make an RPC call such as
+.DS
+.ft CW
+callrpc(hostname, PROGNUM, VERSNUM, PROCNUM,
+ xdr_varintarr, &arr...);
+.DE
+with
+.I xdr_varintarr()
+defined as:
+.ie t .DS
+.el .DS L
+.ft CW
+xdr_varintarr(xdrsp, arrp)
+ XDR *xdrsp;
+ struct varintarr *arrp;
+{
+ return (xdr_array(xdrsp, &arrp->data, &arrp->arrlnth,
+ MAXLEN, sizeof(int), xdr_int));
+}
+.DE
+This routine takes as parameters the XDR handle,
+a pointer to the array, a pointer to the size of the array,
+the maximum allowable array size,
+the size of each array element,
+and an XDR routine for handling each array element.
+.KS
+.LP
+If the size of the array is known in advance, one can use
+.I xdr_vector (),
+which serializes fixed-length arrays.
+.ie t .DS
+.el .DS L
+.ft CW
+int intarr[SIZE];
+
+xdr_intarr(xdrsp, intarr)
+ XDR *xdrsp;
+ int intarr[];
+{
+ int i;
+
+ return (xdr_vector(xdrsp, intarr, SIZE, sizeof(int),
+ xdr_int));
+}
+.DE
+.KE
+.LP
+XDR always converts quantities to 4-byte multiples when serializing.
+Thus, if either of the examples above involved characters
+instead of integers, each character would occupy 32 bits.
+That is the reason for the XDR routine
+.I xdr_bytes()
+which is like
+.I xdr_array()
+except that it packs characters;
+.I xdr_bytes()
+has four parameters, similar to the first four parameters of
+.I xdr_array ().
+For null-terminated strings, there is also the
+.I xdr_string()
+routine, which is the same as
+.I xdr_bytes()
+without the length parameter.
+On serializing it gets the string length from
+.I strlen (),
+and on deserializing it creates a null-terminated string.
+.LP
+Here is a final example that calls the previously written
+.I xdr_simple()
+as well as the built-in functions
+.I xdr_string()
+and
+.I xdr_reference (),
+which chases pointers:
+.ie t .DS
+.el .DS L
+.ft CW
+struct finalexample {
+ char *string;
+ struct simple *simplep;
+} finalexample;
+
+xdr_finalexample(xdrsp, finalp)
+ XDR *xdrsp;
+ struct finalexample *finalp;
+{
+
+ if (!xdr_string(xdrsp, &finalp->string, MAXSTRLEN))
+ return (0);
+ if (!xdr_reference(xdrsp, &finalp->simplep,
+ sizeof(struct simple), xdr_simple);
+ return (0);
+ return (1);
+}
+.DE
+Note that we could as easily call
+.I xdr_simple()
+here instead of
+.I xdr_reference ().
+.NH 1
+\&Lowest Layer of RPC
+.IX "lowest layer of RPC"
+.IX "RPC" "lowest layer"
+.LP
+In the examples given so far,
+RPC takes care of many details automatically for you.
+In this section, we'll show you how you can change the defaults
+by using lower layers of the RPC library.
+It is assumed that you are familiar with sockets
+and the system calls for dealing with them.
+.LP
+There are several occasions when you may need to use lower layers of
+RPC. First, you may need to use TCP, since the higher layer uses UDP,
+which restricts RPC calls to 8K bytes of data. Using TCP permits calls
+to send long streams of data.
+For an example, see the
+.I TCP
+section below. Second, you may want to allocate and free memory
+while serializing or deserializing with XDR routines.
+There is no call at the higher level to let
+you free memory explicitly.
+For more explanation, see the
+.I "Memory Allocation with XDR"
+section below.
+Third, you may need to perform authentication
+on either the client or server side, by supplying
+credentials or verifying them.
+See the explanation in the
+.I Authentication
+section below.
+.NH 2
+\&More on the Server Side
+.IX RPC "server side"
+.LP
+The server for the
+.I nusers()
+program shown below does the same thing as the one using
+.I registerrpc()
+above, but is written using a lower layer of the RPC package:
+.ie t .DS
+.el .DS L
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <utmp.h>
+#include <rpcsvc/rusers.h>
+
+main()
+{
+ SVCXPRT *transp;
+ int nuser();
+
+ transp = svcudp_create(RPC_ANYSOCK);
+ if (transp == NULL){
+ fprintf(stderr, "can't create an RPC server\en");
+ exit(1);
+ }
+ pmap_unset(RUSERSPROG, RUSERSVERS);
+ if (!svc_register(transp, RUSERSPROG, RUSERSVERS,
+ nuser, IPPROTO_UDP)) {
+ fprintf(stderr, "can't register RUSER service\en");
+ exit(1);
+ }
+ svc_run(); /* \fINever returns\fP */
+ fprintf(stderr, "should never reach this point\en");
+}
+
+nuser(rqstp, transp)
+ struct svc_req *rqstp;
+ SVCXPRT *transp;
+{
+ unsigned long nusers;
+
+ switch (rqstp->rq_proc) {
+ case NULLPROC:
+ if (!svc_sendreply(transp, xdr_void, 0))
+ fprintf(stderr, "can't reply to RPC call\en");
+ return;
+ case RUSERSPROC_NUM:
+.ft I
+ /*
+ * Code here to compute the number of users
+ * and assign it to the variable \fInusers\fP
+ */
+.ft CW
+ if (!svc_sendreply(transp, xdr_u_long, &nusers))
+ fprintf(stderr, "can't reply to RPC call\en");
+ return;
+ default:
+ svcerr_noproc(transp);
+ return;
+ }
+}
+.DE
+.LP
+First, the server gets a transport handle, which is used
+for receiving and replying to RPC messages.
+.I registerrpc()
+uses
+.I svcudp_create()
+to get a UDP handle.
+If you require a more reliable protocol, call
+.I svctcp_create()
+instead.
+If the argument to
+.I svcudp_create()
+is
+.I RPC_ANYSOCK
+the RPC library creates a socket
+on which to receive and reply to RPC calls. Otherwise,
+.I svcudp_create()
+expects its argument to be a valid socket number.
+If you specify your own socket, it can be bound or unbound.
+If it is bound to a port by the user, the port numbers of
+.I svcudp_create()
+and
+.I clnttcp_create()
+(the low-level client routine) must match.
+.LP
+If the user specifies the
+.I RPC_ANYSOCK
+argument, the RPC library routines will open sockets.
+Otherwise they will expect the user to do so. The routines
+.I svcudp_create()
+and
+.I clntudp_create()
+will cause the RPC library routines to
+.I bind()
+their socket if it is not bound already.
+.LP
+A service may choose to register its port number with the
+local portmapper service. This is done is done by specifying
+a non-zero protocol number in
+.I svc_register ().
+Incidently, a client can discover the server's port number by
+consulting the portmapper on their server's machine. This can
+be done automatically by specifying a zero port number in
+.I clntudp_create()
+or
+.I clnttcp_create ().
+.LP
+After creating an
+.I SVCXPRT ,
+the next step is to call
+.I pmap_unset()
+so that if the
+.I nusers()
+server crashed earlier,
+any previous trace of it is erased before restarting.
+More precisely,
+.I pmap_unset()
+erases the entry for
+.I RUSERSPROG
+from the port mapper's tables.
+.LP
+Finally, we associate the program number for
+.I nusers()
+with the procedure
+.I nuser ().
+The final argument to
+.I svc_register()
+is normally the protocol being used,
+which, in this case, is
+.I IPPROTO_UDP
+Notice that unlike
+.I registerrpc (),
+there are no XDR routines involved
+in the registration process.
+Also, registration is done on the program,
+rather than procedure, level.
+.LP
+The user routine
+.I nuser()
+must call and dispatch the appropriate XDR routines
+based on the procedure number.
+Note that
+two things are handled by
+.I nuser()
+that
+.I registerrpc()
+handles automatically.
+The first is that procedure
+.I NULLPROC
+(currently zero) returns with no results.
+This can be used as a simple test
+for detecting if a remote program is running.
+Second, there is a check for invalid procedure numbers.
+If one is detected,
+.I svcerr_noproc()
+is called to handle the error.
+.KS
+.LP
+The user service routine serializes the results and returns
+them to the RPC caller via
+.I svc_sendreply()
+Its first parameter is the
+.I SVCXPRT
+handle, the second is the XDR routine,
+and the third is a pointer to the data to be returned.
+Not illustrated above is how a server
+handles an RPC program that receives data.
+As an example, we can add a procedure
+.I RUSERSPROC_BOOL
+which has an argument
+.I nusers (),
+and returns
+.I TRUE
+or
+.I FALSE
+depending on whether there are nusers logged on.
+It would look like this:
+.ie t .DS
+.el .DS L
+.ft CW
+case RUSERSPROC_BOOL: {
+ int bool;
+ unsigned nuserquery;
+
+ if (!svc_getargs(transp, xdr_u_int, &nuserquery) {
+ svcerr_decode(transp);
+ return;
+ }
+.ft I
+ /*
+ * Code to set \fInusers\fP = number of users
+ */
+.ft CW
+ if (nuserquery == nusers)
+ bool = TRUE;
+ else
+ bool = FALSE;
+ if (!svc_sendreply(transp, xdr_bool, &bool)) {
+ fprintf(stderr, "can't reply to RPC call\en");
+ return (1);
+ }
+ return;
+}
+.DE
+.KE
+.LP
+The relevant routine is
+.I svc_getargs()
+which takes an
+.I SVCXPRT
+handle, the XDR routine,
+and a pointer to where the input is to be placed as arguments.
+.NH 2
+\&Memory Allocation with XDR
+.IX "memory allocation with XDR"
+.IX XDR "memory allocation"
+.LP
+XDR routines not only do input and output,
+they also do memory allocation.
+This is why the second parameter of
+.I xdr_array()
+is a pointer to an array, rather than the array itself.
+If it is
+.I NULL ,
+then
+.I xdr_array()
+allocates space for the array and returns a pointer to it,
+putting the size of the array in the third argument.
+As an example, consider the following XDR routine
+.I xdr_chararr1()
+which deals with a fixed array of bytes with length
+.I SIZE .
+.ie t .DS
+.el .DS L
+.ft CW
+xdr_chararr1(xdrsp, chararr)
+ XDR *xdrsp;
+ char chararr[];
+{
+ char *p;
+ int len;
+
+ p = chararr;
+ len = SIZE;
+ return (xdr_bytes(xdrsp, &p, &len, SIZE));
+}
+.DE
+If space has already been allocated in
+.I chararr ,
+it can be called from a server like this:
+.ie t .DS
+.el .DS L
+.ft CW
+char chararr[SIZE];
+
+svc_getargs(transp, xdr_chararr1, chararr);
+.DE
+If you want XDR to do the allocation,
+you would have to rewrite this routine in the following way:
+.ie t .DS
+.el .DS L
+.ft CW
+xdr_chararr2(xdrsp, chararrp)
+ XDR *xdrsp;
+ char **chararrp;
+{
+ int len;
+
+ len = SIZE;
+ return (xdr_bytes(xdrsp, charrarrp, &len, SIZE));
+}
+.DE
+Then the RPC call might look like this:
+.ie t .DS
+.el .DS L
+.ft CW
+char *arrptr;
+
+arrptr = NULL;
+svc_getargs(transp, xdr_chararr2, &arrptr);
+.ft I
+/*
+ * Use the result here
+ */
+.ft CW
+svc_freeargs(transp, xdr_chararr2, &arrptr);
+.DE
+Note that, after being used, the character array can be freed with
+.I svc_freeargs()
+.I svc_freeargs()
+will not attempt to free any memory if the variable indicating it
+is NULL. For example, in the the routine
+.I xdr_finalexample (),
+given earlier, if
+.I finalp->string
+was NULL, then it would not be freed. The same is true for
+.I finalp->simplep .
+.LP
+To summarize, each XDR routine is responsible
+for serializing, deserializing, and freeing memory.
+When an XDR routine is called from
+.I callrpc()
+the serializing part is used.
+When called from
+.I svc_getargs()
+the deserializer is used.
+And when called from
+.I svc_freeargs()
+the memory deallocator is used. When building simple examples like those
+in this section, a user doesn't have to worry
+about the three modes.
+See the
+.I "External Data Representation: Sun Technical Notes"
+for examples of more sophisticated XDR routines that determine
+which of the three modes they are in and adjust their behavior accordingly.
+.KS
+.NH 2
+\&The Calling Side
+.IX RPC "calling side"
+.LP
+When you use
+.I callrpc()
+you have no control over the RPC delivery
+mechanism or the socket used to transport the data.
+To illustrate the layer of RPC that lets you adjust these
+parameters, consider the following code to call the
+.I nusers
+service:
+.ie t .DS
+.el .DS L
+.ft CW
+.vs 11
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <utmp.h>
+#include <rpcsvc/rusers.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netdb.h>
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ struct hostent *hp;
+ struct timeval pertry_timeout, total_timeout;
+ struct sockaddr_in server_addr;
+ int sock = RPC_ANYSOCK;
+ register CLIENT *client;
+ enum clnt_stat clnt_stat;
+ unsigned long nusers;
+
+ if (argc != 2) {
+ fprintf(stderr, "usage: nusers hostname\en");
+ exit(-1);
+ }
+ if ((hp = gethostbyname(argv[1])) == NULL) {
+ fprintf(stderr, "can't get addr for %s\en",argv[1]);
+ exit(-1);
+ }
+ pertry_timeout.tv_sec = 3;
+ pertry_timeout.tv_usec = 0;
+ bcopy(hp->h_addr, (caddr_t)&server_addr.sin_addr,
+ hp->h_length);
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_port = 0;
+ if ((client = clntudp_create(&server_addr, RUSERSPROG,
+ RUSERSVERS, pertry_timeout, &sock)) == NULL) {
+ clnt_pcreateerror("clntudp_create");
+ exit(-1);
+ }
+ total_timeout.tv_sec = 20;
+ total_timeout.tv_usec = 0;
+ clnt_stat = clnt_call(client, RUSERSPROC_NUM, xdr_void,
+ 0, xdr_u_long, &nusers, total_timeout);
+ if (clnt_stat != RPC_SUCCESS) {
+ clnt_perror(client, "rpc");
+ exit(-1);
+ }
+ clnt_destroy(client);
+ close(sock);
+ exit(0);
+}
+.vs
+.DE
+.KE
+The low-level version of
+.I callrpc()
+is
+.I clnt_call()
+which takes a
+.I CLIENT
+pointer rather than a host name. The parameters to
+.I clnt_call()
+are a
+.I CLIENT
+pointer, the procedure number,
+the XDR routine for serializing the argument,
+a pointer to the argument,
+the XDR routine for deserializing the return value,
+a pointer to where the return value will be placed,
+and the time in seconds to wait for a reply.
+.LP
+The
+.I CLIENT
+pointer is encoded with the transport mechanism.
+.I callrpc()
+uses UDP, thus it calls
+.I clntudp_create()
+to get a
+.I CLIENT
+pointer. To get TCP (Transmission Control Protocol), you would use
+.I clnttcp_create() .
+.LP
+The parameters to
+.I clntudp_create()
+are the server address, the program number, the version number,
+a timeout value (between tries), and a pointer to a socket.
+The final argument to
+.I clnt_call()
+is the total time to wait for a response.
+Thus, the number of tries is the
+.I clnt_call()
+timeout divided by the
+.I clntudp_create()
+timeout.
+.LP
+Note that the
+.I clnt_destroy()
+call
+always deallocates the space associated with the
+.I CLIENT
+handle. It closes the socket associated with the
+.I CLIENT
+handle, however, only if the RPC library opened it. It the
+socket was opened by the user, it stays open. This makes it
+possible, in cases where there are multiple client handles
+using the same socket, to destroy one handle without closing
+the socket that other handles are using.
+.LP
+To make a stream connection, the call to
+.I clntudp_create()
+is replaced with a call to
+.I clnttcp_create() .
+.DS
+.ft CW
+clnttcp_create(&server_addr, prognum, versnum, &sock,
+ inputsize, outputsize);
+.DE
+There is no timeout argument; instead, the receive and send buffer
+sizes must be specified. When the
+.I clnttcp_create()
+call is made, a TCP connection is established.
+All RPC calls using that
+.I CLIENT
+handle would use this connection.
+The server side of an RPC call using TCP has
+.I svcudp_create()
+replaced by
+.I svctcp_create() .
+.DS
+.ft CW
+transp = svctcp_create(RPC_ANYSOCK, 0, 0);
+.DE
+The last two arguments to
+.I svctcp_create()
+are send and receive sizes respectively. If `0' is specified for
+either of these, the system chooses a reasonable default.
+.KS
+.NH 1
+\&Other RPC Features
+.IX "RPC" "miscellaneous features"
+.IX "miscellaneous RPC features"
+.LP
+This section discusses some other aspects of RPC
+that are occasionally useful.
+.NH 2
+\&Select on the Server Side
+.IX RPC select() RPC \fIselect()\fP
+.IX select() "" \fIselect()\fP "on the server side"
+.LP
+Suppose a process is processing RPC requests
+while performing some other activity.
+If the other activity involves periodically updating a data structure,
+the process can set an alarm signal before calling
+.I svc_run()
+But if the other activity
+involves waiting on a a file descriptor, the
+.I svc_run()
+call won't work.
+The code for
+.I svc_run()
+is as follows:
+.ie t .DS
+.el .DS L
+.ft CW
+.vs 11
+void
+svc_run()
+{
+ fd_set readfds;
+ int dtbsz = getdtablesize();
+
+ for (;;) {
+ readfds = svc_fds;
+ switch (select(dtbsz, &readfds, NULL,NULL,NULL)) {
+
+ case -1:
+ if (errno == EINTR)
+ continue;
+ perror("select");
+ return;
+ case 0:
+ break;
+ default:
+ svc_getreqset(&readfds);
+ }
+ }
+}
+.vs
+.DE
+.KE
+.LP
+You can bypass
+.I svc_run()
+and call
+.I svc_getreqset()
+yourself.
+All you need to know are the file descriptors
+of the socket(s) associated with the programs you are waiting on.
+Thus you can have your own
+.I select()
+.IX select() "" \fIselect()\fP
+that waits on both the RPC socket,
+and your own descriptors. Note that
+.I svc_fds()
+is a bit mask of all the file descriptors that RPC is using for
+services. It can change everytime that
+.I any
+RPC library routine is called, because descriptors are constantly
+being opened and closed, for example for TCP connections.
+.NH 2
+\&Broadcast RPC
+.IX "broadcast RPC"
+.IX RPC "broadcast"
+.LP
+The
+.I portmapper
+is a daemon that converts RPC program numbers
+into DARPA protocol port numbers; see the
+.I portmap
+man page. You can't do broadcast RPC without the portmapper.
+Here are the main differences between
+broadcast RPC and normal RPC calls:
+.IP 1.
+Normal RPC expects one answer, whereas
+broadcast RPC expects many answers
+(one or more answer from each responding machine).
+.IP 2.
+Broadcast RPC can only be supported by packet-oriented (connectionless)
+transport protocols like UPD/IP.
+.IP 3.
+The implementation of broadcast RPC
+treats all unsuccessful responses as garbage by filtering them out.
+Thus, if there is a version mismatch between the
+broadcaster and a remote service,
+the user of broadcast RPC never knows.
+.IP 4.
+All broadcast messages are sent to the portmap port.
+Thus, only services that register themselves with their portmapper
+are accessible via the broadcast RPC mechanism.
+.IP 5.
+Broadcast requests are limited in size to the MTU (Maximum Transfer
+Unit) of the local network. For Ethernet, the MTU is 1500 bytes.
+.KS
+.NH 3
+\&Broadcast RPC Synopsis
+.IX "broadcast RPC" synopsis
+.IX "RPC" "broadcast synopsis"
+.ie t .DS
+.el .DS L
+.ft CW
+#include <rpc/pmap_clnt.h>
+ . . .
+enum clnt_stat clnt_stat;
+ . . .
+clnt_stat = clnt_broadcast(prognum, versnum, procnum,
+ inproc, in, outproc, out, eachresult)
+ u_long prognum; /* \fIprogram number\fP */
+ u_long versnum; /* \fIversion number\fP */
+ u_long procnum; /* \fIprocedure number\fP */
+ xdrproc_t inproc; /* \fIxdr routine for args\fP */
+ caddr_t in; /* \fIpointer to args\fP */
+ xdrproc_t outproc; /* \fIxdr routine for results\fP */
+ caddr_t out; /* \fIpointer to results\fP */
+ bool_t (*eachresult)();/* \fIcall with each result gotten\fP */
+.DE
+.KE
+The procedure
+.I eachresult()
+is called each time a valid result is obtained.
+It returns a boolean that indicates
+whether or not the user wants more responses.
+.ie t .DS
+.el .DS L
+.ft CW
+bool_t done;
+ . . .
+done = eachresult(resultsp, raddr)
+ caddr_t resultsp;
+ struct sockaddr_in *raddr; /* \fIAddr of responding machine\fP */
+.DE
+If
+.I done
+is
+.I TRUE ,
+then broadcasting stops and
+.I clnt_broadcast()
+returns successfully.
+Otherwise, the routine waits for another response.
+The request is rebroadcast
+after a few seconds of waiting.
+If no responses come back,
+the routine returns with
+.I RPC_TIMEDOUT .
+.NH 2
+\&Batching
+.IX "batching"
+.IX RPC "batching"
+.LP
+The RPC architecture is designed so that clients send a call message,
+and wait for servers to reply that the call succeeded.
+This implies that clients do not compute
+while servers are processing a call.
+This is inefficient if the client does not want or need
+an acknowledgement for every message sent.
+It is possible for clients to continue computing
+while waiting for a response,
+using RPC batch facilities.
+.LP
+RPC messages can be placed in a \*Qpipeline\*U of calls
+to a desired server; this is called batching.
+Batching assumes that:
+1) each RPC call in the pipeline requires no response from the server,
+and the server does not send a response message; and
+2) the pipeline of calls is transported on a reliable
+byte stream transport such as TCP/IP.
+Since the server does not respond to every call,
+the client can generate new calls in parallel
+with the server executing previous calls.
+Furthermore, the TCP/IP implementation can buffer up
+many call messages, and send them to the server in one
+.I write()
+system call. This overlapped execution
+greatly decreases the interprocess communication overhead of
+the client and server processes,
+and the total elapsed time of a series of calls.
+.LP
+Since the batched calls are buffered,
+the client should eventually do a nonbatched call
+in order to flush the pipeline.
+.LP
+A contrived example of batching follows.
+Assume a string rendering service (like a window system)
+has two similar calls: one renders a string and returns void results,
+while the other renders a string and remains silent.
+The service (using the TCP/IP transport) may look like:
+.ie t .DS
+.el .DS L
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <suntool/windows.h>
+
+void windowdispatch();
+
+main()
+{
+ SVCXPRT *transp;
+
+ transp = svctcp_create(RPC_ANYSOCK, 0, 0);
+ if (transp == NULL){
+ fprintf(stderr, "can't create an RPC server\en");
+ exit(1);
+ }
+ pmap_unset(WINDOWPROG, WINDOWVERS);
+ if (!svc_register(transp, WINDOWPROG, WINDOWVERS,
+ windowdispatch, IPPROTO_TCP)) {
+ fprintf(stderr, "can't register WINDOW service\en");
+ exit(1);
+ }
+ svc_run(); /* \fINever returns\fP */
+ fprintf(stderr, "should never reach this point\en");
+}
+
+void
+windowdispatch(rqstp, transp)
+ struct svc_req *rqstp;
+ SVCXPRT *transp;
+{
+ char *s = NULL;
+
+ switch (rqstp->rq_proc) {
+ case NULLPROC:
+ if (!svc_sendreply(transp, xdr_void, 0))
+ fprintf(stderr, "can't reply to RPC call\en");
+ return;
+ case RENDERSTRING:
+ if (!svc_getargs(transp, xdr_wrapstring, &s)) {
+ fprintf(stderr, "can't decode arguments\en");
+.ft I
+ /*
+ * Tell caller he screwed up
+ */
+.ft CW
+ svcerr_decode(transp);
+ break;
+ }
+.ft I
+ /*
+ * Code here to render the string \fIs\fP
+ */
+.ft CW
+ if (!svc_sendreply(transp, xdr_void, NULL))
+ fprintf(stderr, "can't reply to RPC call\en");
+ break;
+ case RENDERSTRING_BATCHED:
+ if (!svc_getargs(transp, xdr_wrapstring, &s)) {
+ fprintf(stderr, "can't decode arguments\en");
+.ft I
+ /*
+ * We are silent in the face of protocol errors
+ */
+.ft CW
+ break;
+ }
+.ft I
+ /*
+ * Code here to render string s, but send no reply!
+ */
+.ft CW
+ break;
+ default:
+ svcerr_noproc(transp);
+ return;
+ }
+.ft I
+ /*
+ * Now free string allocated while decoding arguments
+ */
+.ft CW
+ svc_freeargs(transp, xdr_wrapstring, &s);
+}
+.DE
+Of course the service could have one procedure
+that takes the string and a boolean
+to indicate whether or not the procedure should respond.
+.LP
+In order for a client to take advantage of batching,
+the client must perform RPC calls on a TCP-based transport
+and the actual calls must have the following attributes:
+1) the result's XDR routine must be zero
+.I NULL ),
+and 2) the RPC call's timeout must be zero.
+.KS
+.LP
+Here is an example of a client that uses batching to render a
+bunch of strings; the batching is flushed when the client gets
+a null string (EOF):
+.ie t .DS
+.el .DS L
+.ft CW
+.vs 11
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netdb.h>
+#include <suntool/windows.h>
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ struct hostent *hp;
+ struct timeval pertry_timeout, total_timeout;
+ struct sockaddr_in server_addr;
+ int sock = RPC_ANYSOCK;
+ register CLIENT *client;
+ enum clnt_stat clnt_stat;
+ char buf[1000], *s = buf;
+
+ if ((client = clnttcp_create(&server_addr,
+ WINDOWPROG, WINDOWVERS, &sock, 0, 0)) == NULL) {
+ perror("clnttcp_create");
+ exit(-1);
+ }
+ total_timeout.tv_sec = 0;
+ total_timeout.tv_usec = 0;
+ while (scanf("%s", s) != EOF) {
+ clnt_stat = clnt_call(client, RENDERSTRING_BATCHED,
+ xdr_wrapstring, &s, NULL, NULL, total_timeout);
+ if (clnt_stat != RPC_SUCCESS) {
+ clnt_perror(client, "batched rpc");
+ exit(-1);
+ }
+ }
+
+ /* \fINow flush the pipeline\fP */
+
+ total_timeout.tv_sec = 20;
+ clnt_stat = clnt_call(client, NULLPROC, xdr_void, NULL,
+ xdr_void, NULL, total_timeout);
+ if (clnt_stat != RPC_SUCCESS) {
+ clnt_perror(client, "rpc");
+ exit(-1);
+ }
+ clnt_destroy(client);
+ exit(0);
+}
+.vs
+.DE
+.KE
+Since the server sends no message,
+the clients cannot be notified of any of the failures that may occur.
+Therefore, clients are on their own when it comes to handling errors.
+.LP
+The above example was completed to render
+all of the (2000) lines in the file
+.I /etc/termcap .
+The rendering service did nothing but throw the lines away.
+The example was run in the following four configurations:
+1) machine to itself, regular RPC;
+2) machine to itself, batched RPC;
+3) machine to another, regular RPC; and
+4) machine to another, batched RPC.
+The results are as follows:
+1) 50 seconds;
+2) 16 seconds;
+3) 52 seconds;
+4) 10 seconds.
+Running
+.I fscanf()
+on
+.I /etc/termcap
+only requires six seconds.
+These timings show the advantage of protocols
+that allow for overlapped execution,
+though these protocols are often hard to design.
+.NH 2
+\&Authentication
+.IX "authentication"
+.IX "RPC" "authentication"
+.LP
+In the examples presented so far,
+the caller never identified itself to the server,
+and the server never required an ID from the caller.
+Clearly, some network services, such as a network filesystem,
+require stronger security than what has been presented so far.
+.LP
+In reality, every RPC call is authenticated by
+the RPC package on the server, and similarly,
+the RPC client package generates and sends authentication parameters.
+Just as different transports (TCP/IP or UDP/IP)
+can be used when creating RPC clients and servers,
+different forms of authentication can be associated with RPC clients;
+the default authentication type used as a default is type
+.I none .
+.LP
+The authentication subsystem of the RPC package is open ended.
+That is, numerous types of authentication are easy to support.
+.NH 3
+\&UNIX Authentication
+.IX "UNIX Authentication"
+.IP "\fIThe Client Side\fP"
+.LP
+When a caller creates a new RPC client handle as in:
+.DS
+.ft CW
+clnt = clntudp_create(address, prognum, versnum,
+ wait, sockp)
+.DE
+the appropriate transport instance defaults
+the associate authentication handle to be
+.DS
+.ft CW
+clnt->cl_auth = authnone_create();
+.DE
+The RPC client can choose to use
+.I UNIX
+style authentication by setting
+.I clnt\->cl_auth
+after creating the RPC client handle:
+.DS
+.ft CW
+clnt->cl_auth = authunix_create_default();
+.DE
+This causes each RPC call associated with
+.I clnt
+to carry with it the following authentication credentials structure:
+.ie t .DS
+.el .DS L
+.ft I
+/*
+ * UNIX style credentials.
+ */
+.ft CW
+struct authunix_parms {
+ u_long aup_time; /* \fIcredentials creation time\fP */
+ char *aup_machname; /* \fIhost name where client is\fP */
+ int aup_uid; /* \fIclient's UNIX effective uid\fP */
+ int aup_gid; /* \fIclient's current group id\fP */
+ u_int aup_len; /* \fIelement length of aup_gids\fP */
+ int *aup_gids; /* \fIarray of groups user is in\fP */
+};
+.DE
+These fields are set by
+.I authunix_create_default()
+by invoking the appropriate system calls.
+Since the RPC user created this new style of authentication,
+the user is responsible for destroying it with:
+.DS
+.ft CW
+auth_destroy(clnt->cl_auth);
+.DE
+This should be done in all cases, to conserve memory.
+.sp
+.IP "\fIThe Server Side\fP"
+.LP
+Service implementors have a harder time dealing with authentication issues
+since the RPC package passes the service dispatch routine a request
+that has an arbitrary authentication style associated with it.
+Consider the fields of a request handle passed to a service dispatch routine:
+.ie t .DS
+.el .DS L
+.ft I
+/*
+ * An RPC Service request
+ */
+.ft CW
+struct svc_req {
+ u_long rq_prog; /* \fIservice program number\fP */
+ u_long rq_vers; /* \fIservice protocol vers num\fP */
+ u_long rq_proc; /* \fIdesired procedure number\fP */
+ struct opaque_auth rq_cred; /* \fIraw credentials from wire\fP */
+ caddr_t rq_clntcred; /* \fIcredentials (read only)\fP */
+};
+.DE
+The
+.I rq_cred
+is mostly opaque, except for one field of interest:
+the style or flavor of authentication credentials:
+.ie t .DS
+.el .DS L
+.ft I
+/*
+ * Authentication info. Mostly opaque to the programmer.
+ */
+.ft CW
+struct opaque_auth {
+ enum_t oa_flavor; /* \fIstyle of credentials\fP */
+ caddr_t oa_base; /* \fIaddress of more auth stuff\fP */
+ u_int oa_length; /* \fInot to exceed \fIMAX_AUTH_BYTES */
+};
+.DE
+.IX RPC guarantees
+The RPC package guarantees the following
+to the service dispatch routine:
+.IP 1.
+That the request's
+.I rq_cred
+is well formed. Thus the service implementor may inspect the request's
+.I rq_cred.oa_flavor
+to determine which style of authentication the caller used.
+The service implementor may also wish to inspect the other fields of
+.I rq_cred
+if the style is not one of the styles supported by the RPC package.
+.IP 2.
+That the request's
+.I rq_clntcred
+field is either
+.I NULL
+or points to a well formed structure
+that corresponds to a supported style of authentication credentials.
+Remember that only
+.I unix
+style is currently supported, so (currently)
+.I rq_clntcred
+could be cast to a pointer to an
+.I authunix_parms
+structure. If
+.I rq_clntcred
+is
+.I NULL ,
+the service implementor may wish to inspect the other (opaque) fields of
+.I rq_cred
+in case the service knows about a new type of authentication
+that the RPC package does not know about.
+.LP
+Our remote users service example can be extended so that
+it computes results for all users except UID 16:
+.ie t .DS
+.el .DS L
+.ft CW
+.vs 11
+nuser(rqstp, transp)
+ struct svc_req *rqstp;
+ SVCXPRT *transp;
+{
+ struct authunix_parms *unix_cred;
+ int uid;
+ unsigned long nusers;
+
+.ft I
+ /*
+ * we don't care about authentication for null proc
+ */
+.ft CW
+ if (rqstp->rq_proc == NULLPROC) {
+ if (!svc_sendreply(transp, xdr_void, 0)) {
+ fprintf(stderr, "can't reply to RPC call\en");
+ return (1);
+ }
+ return;
+ }
+.ft I
+ /*
+ * now get the uid
+ */
+.ft CW
+ switch (rqstp->rq_cred.oa_flavor) {
+ case AUTH_UNIX:
+ unix_cred =
+ (struct authunix_parms *)rqstp->rq_clntcred;
+ uid = unix_cred->aup_uid;
+ break;
+ case AUTH_NULL:
+ default:
+ svcerr_weakauth(transp);
+ return;
+ }
+ switch (rqstp->rq_proc) {
+ case RUSERSPROC_NUM:
+.ft I
+ /*
+ * make sure caller is allowed to call this proc
+ */
+.ft CW
+ if (uid == 16) {
+ svcerr_systemerr(transp);
+ return;
+ }
+.ft I
+ /*
+ * Code here to compute the number of users
+ * and assign it to the variable \fInusers\fP
+ */
+.ft CW
+ if (!svc_sendreply(transp, xdr_u_long, &nusers)) {
+ fprintf(stderr, "can't reply to RPC call\en");
+ return (1);
+ }
+ return;
+ default:
+ svcerr_noproc(transp);
+ return;
+ }
+}
+.vs
+.DE
+A few things should be noted here.
+First, it is customary not to check
+the authentication parameters associated with the
+.I NULLPROC
+(procedure number zero).
+Second, if the authentication parameter's type is not suitable
+for your service, you should call
+.I svcerr_weakauth() .
+And finally, the service protocol itself should return status
+for access denied; in the case of our example, the protocol
+does not have such a status, so we call the service primitive
+.I svcerr_systemerr()
+instead.
+.LP
+The last point underscores the relation between
+the RPC authentication package and the services;
+RPC deals only with
+.I authentication
+and not with individual services'
+.I "access control" .
+The services themselves must implement their own access control policies
+and reflect these policies as return statuses in their protocols.
+.NH 2
+\&DES Authentication
+.IX RPC DES
+.IX RPC authentication
+.LP
+UNIX authentication is quite easy to defeat. Instead of using
+.I authunix_create_default (),
+one can call
+.I authunix_create()
+and then modify the RPC authentication handle it returns by filling in
+whatever user ID and hostname they wish the server to think they have.
+DES authentication is thus recommended for people who want more security
+than UNIX authentication offers.
+.LP
+The details of the DES authentication protocol are complicated and
+are not explained here.
+See
+.I "Remote Procedure Calls: Protocol Specification"
+for the details.
+.LP
+In order for DES authentication to work, the
+.I keyserv(8c)
+daemon must be running on both the server and client machines. The
+users on these machines need public keys assigned by the network
+administrator in the
+.I publickey(5)
+database. And, they need to have decrypted their secret keys
+using their login password. This automatically happens when one
+logs in using
+.I login(1) ,
+or can be done manually using
+.I keylogin(1) .
+The
+.I "Network Services"
+chapter
+./" XXX
+explains more how to setup secure networking.
+.sp
+.IP "\fIClient Side\fP"
+.LP
+If a client wishes to use DES authentication, it must set its
+authentication handle appropriately. Here is an example:
+.DS
+cl->cl_auth =
+ authdes_create(servername, 60, &server_addr, NULL);
+.DE
+The first argument is the network name or \*Qnetname\*U of the owner of
+the server process. Typically, server processes are root processes
+and their netname can be derived using the following call:
+.DS
+char servername[MAXNETNAMELEN];
+
+host2netname(servername, rhostname, NULL);
+.DE
+Here,
+.I rhostname
+is the hostname of the machine the server process is running on.
+.I host2netname()
+fills in
+.I servername
+to contain this root process's netname. If the
+server process was run by a regular user, one could use the call
+.I user2netname()
+instead. Here is an example for a server process with the same user
+ID as the client:
+.DS
+char servername[MAXNETNAMELEN];
+
+user2netname(servername, getuid(), NULL);
+.DE
+The last argument to both of these calls,
+.I user2netname()
+and
+.I host2netname (),
+is the name of the naming domain where the server is located. The
+.I NULL
+used here means \*Quse the local domain name.\*U
+.LP
+The second argument to
+.I authdes_create()
+is a lifetime for the credential. Here it is set to sixty
+seconds. What that means is that the credential will expire 60
+seconds from now. If some mischievous user tries to reuse the
+credential, the server RPC subsystem will recognize that it has
+expired and not grant any requests. If the same mischievous user
+tries to reuse the credential within the sixty second lifetime,
+he will still be rejected because the server RPC subsystem
+remembers which credentials it has already seen in the near past,
+and will not grant requests to duplicates.
+.LP
+The third argument to
+.I authdes_create()
+is the address of the host to synchronize with. In order for DES
+authentication to work, the server and client must agree upon the
+time. Here we pass the address of the server itself, so the
+client and server will both be using the same time: the server's
+time. The argument can be
+.I NULL ,
+which means \*Qdon't bother synchronizing.\*U You should only do this
+if you are sure the client and server are already synchronized.
+.LP
+The final argument to
+.I authdes_create()
+is the address of a DES encryption key to use for encrypting
+timestamps and data. If this argument is
+.I NULL ,
+as it is in this example, a random key will be chosen. The client
+may find out the encryption key being used by consulting the
+.I ah_key
+field of the authentication handle.
+.sp
+.IP "\fIServer Side\fP"
+.LP
+The server side is a lot simpler than the client side. Here is the
+previous example rewritten to use
+.I AUTH_DES
+instead of
+.I AUTH_UNIX :
+.ie t .DS
+.el .DS L
+.ft CW
+.vs 11
+#include <sys/time.h>
+#include <rpc/auth_des.h>
+ . . .
+ . . .
+nuser(rqstp, transp)
+ struct svc_req *rqstp;
+ SVCXPRT *transp;
+{
+ struct authdes_cred *des_cred;
+ int uid;
+ int gid;
+ int gidlen;
+ int gidlist[10];
+.ft I
+ /*
+ * we don't care about authentication for null proc
+ */
+.ft CW
+
+ if (rqstp->rq_proc == NULLPROC) {
+ /* \fIsame as before\fP */
+ }
+
+.ft I
+ /*
+ * now get the uid
+ */
+.ft CW
+ switch (rqstp->rq_cred.oa_flavor) {
+ case AUTH_DES:
+ des_cred =
+ (struct authdes_cred *) rqstp->rq_clntcred;
+ if (! netname2user(des_cred->adc_fullname.name,
+ &uid, &gid, &gidlen, gidlist))
+ {
+ fprintf(stderr, "unknown user: %s\n",
+ des_cred->adc_fullname.name);
+ svcerr_systemerr(transp);
+ return;
+ }
+ break;
+ case AUTH_NULL:
+ default:
+ svcerr_weakauth(transp);
+ return;
+ }
+
+.ft I
+ /*
+ * The rest is the same as before
+ */
+.ft CW
+.vs
+.DE
+Note the use of the routine
+.I netname2user (),
+the inverse of
+.I user2netname ():
+it takes a network ID and converts to a unix ID.
+.I netname2user ()
+also supplies the group IDs which we don't use in this example,
+but which may be useful to other UNIX programs.
+.NH 2
+\&Using Inetd
+.IX inetd "" "using \fIinetd\fP"
+.LP
+An RPC server can be started from
+.I inetd
+The only difference from the usual code is that the service
+creation routine should be called in the following form:
+.ie t .DS
+.el .DS L
+.ft CW
+transp = svcudp_create(0); /* \fIFor UDP\fP */
+transp = svctcp_create(0,0,0); /* \fIFor listener TCP sockets\fP */
+transp = svcfd_create(0,0,0); /* \fIFor connected TCP sockets\fP */
+.DE
+since
+.I inet
+passes a socket as file descriptor 0.
+Also,
+.I svc_register()
+should be called as
+.ie t .DS
+.el .DS L
+.ft CW
+svc_register(transp, PROGNUM, VERSNUM, service, 0);
+.DE
+with the final flag as 0,
+since the program would already be registered by
+.I inetd
+Remember that if you want to exit
+from the server process and return control to
+.I inet
+you need to explicitly exit, since
+.I svc_run()
+never returns.
+.LP
+The format of entries in
+.I /etc/inetd.conf
+for RPC services is in one of the following two forms:
+.ie t .DS
+.el .DS L
+.ft CW
+p_name/version dgram rpc/udp wait/nowait user server args
+p_name/version stream rpc/tcp wait/nowait user server args
+.DE
+where
+.I p_name
+is the symbolic name of the program as it appears in
+.I rpc(5) ,
+.I server
+is the program implementing the server,
+and
+.I program
+and
+.I version
+are the program and version numbers of the service.
+For more information, see
+.I inetd.conf(5) .
+.LP
+If the same program handles multiple versions,
+then the version number can be a range,
+as in this example:
+.ie t .DS
+.el .DS L
+.ft CW
+rstatd/1-2 dgram rpc/udp wait root /usr/etc/rpc.rstatd
+.DE
+.NH 1
+\&More Examples
+.sp 1
+.NH 2
+\&Versions
+.IX "versions"
+.IX "RPC" "versions"
+.LP
+By convention, the first version number of program
+.I PROG
+is
+.I PROGVERS_ORIG
+and the most recent version is
+.I PROGVERS
+Suppose there is a new version of the
+.I user
+program that returns an
+.I "unsigned short"
+rather than a
+.I long .
+If we name this version
+.I RUSERSVERS_SHORT
+then a server that wants to support both versions
+would do a double register.
+.ie t .DS
+.el .DS L
+.ft CW
+if (!svc_register(transp, RUSERSPROG, RUSERSVERS_ORIG,
+ nuser, IPPROTO_TCP)) {
+ fprintf(stderr, "can't register RUSER service\en");
+ exit(1);
+}
+if (!svc_register(transp, RUSERSPROG, RUSERSVERS_SHORT,
+ nuser, IPPROTO_TCP)) {
+ fprintf(stderr, "can't register RUSER service\en");
+ exit(1);
+}
+.DE
+Both versions can be handled by the same C procedure:
+.ie t .DS
+.el .DS L
+.ft CW
+.vs 11
+nuser(rqstp, transp)
+ struct svc_req *rqstp;
+ SVCXPRT *transp;
+{
+ unsigned long nusers;
+ unsigned short nusers2;
+
+ switch (rqstp->rq_proc) {
+ case NULLPROC:
+ if (!svc_sendreply(transp, xdr_void, 0)) {
+ fprintf(stderr, "can't reply to RPC call\en");
+ return (1);
+ }
+ return;
+ case RUSERSPROC_NUM:
+.ft I
+ /*
+ * Code here to compute the number of users
+ * and assign it to the variable \fInusers\fP
+ */
+.ft CW
+ nusers2 = nusers;
+ switch (rqstp->rq_vers) {
+ case RUSERSVERS_ORIG:
+ if (!svc_sendreply(transp, xdr_u_long,
+ &nusers)) {
+ fprintf(stderr,"can't reply to RPC call\en");
+ }
+ break;
+ case RUSERSVERS_SHORT:
+ if (!svc_sendreply(transp, xdr_u_short,
+ &nusers2)) {
+ fprintf(stderr,"can't reply to RPC call\en");
+ }
+ break;
+ }
+ default:
+ svcerr_noproc(transp);
+ return;
+ }
+}
+.vs
+.DE
+.KS
+.NH 2
+\&TCP
+.IX "TCP"
+.LP
+Here is an example that is essentially
+.I rcp.
+The initiator of the RPC
+.I snd
+call takes its standard input and sends it to the server
+.I rcv
+which prints it on standard output.
+The RPC call uses TCP.
+This also illustrates an XDR procedure that behaves differently
+on serialization than on deserialization.
+.ie t .DS
+.el .DS L
+.vs 11
+.ft I
+/*
+ * The xdr routine:
+ * on decode, read from wire, write onto fp
+ * on encode, read from fp, write onto wire
+ */
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h>
+
+xdr_rcp(xdrs, fp)
+ XDR *xdrs;
+ FILE *fp;
+{
+ unsigned long size;
+ char buf[BUFSIZ], *p;
+
+ if (xdrs->x_op == XDR_FREE)/* nothing to free */
+ return 1;
+ while (1) {
+ if (xdrs->x_op == XDR_ENCODE) {
+ if ((size = fread(buf, sizeof(char), BUFSIZ,
+ fp)) == 0 && ferror(fp)) {
+ fprintf(stderr, "can't fread\en");
+ return (1);
+ }
+ }
+ p = buf;
+ if (!xdr_bytes(xdrs, &p, &size, BUFSIZ))
+ return 0;
+ if (size == 0)
+ return 1;
+ if (xdrs->x_op == XDR_DECODE) {
+ if (fwrite(buf, sizeof(char), size,
+ fp) != size) {
+ fprintf(stderr, "can't fwrite\en");
+ return (1);
+ }
+ }
+ }
+}
+.vs
+.DE
+.KE
+.ie t .DS
+.el .DS L
+.vs 11
+.ft I
+/*
+ * The sender routines
+ */
+.ft CW
+#include <stdio.h>
+#include <netdb.h>
+#include <rpc/rpc.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ int xdr_rcp();
+ int err;
+
+ if (argc < 2) {
+ fprintf(stderr, "usage: %s servername\en", argv[0]);
+ exit(-1);
+ }
+ if ((err = callrpctcp(argv[1], RCPPROG, RCPPROC,
+ RCPVERS, xdr_rcp, stdin, xdr_void, 0) != 0)) {
+ clnt_perrno(err);
+ fprintf(stderr, "can't make RPC call\en");
+ exit(1);
+ }
+ exit(0);
+}
+
+callrpctcp(host, prognum, procnum, versnum,
+ inproc, in, outproc, out)
+ char *host, *in, *out;
+ xdrproc_t inproc, outproc;
+{
+ struct sockaddr_in server_addr;
+ int socket = RPC_ANYSOCK;
+ enum clnt_stat clnt_stat;
+ struct hostent *hp;
+ register CLIENT *client;
+ struct timeval total_timeout;
+
+ if ((hp = gethostbyname(host)) == NULL) {
+ fprintf(stderr, "can't get addr for '%s'\en", host);
+ return (-1);
+ }
+ bcopy(hp->h_addr, (caddr_t)&server_addr.sin_addr,
+ hp->h_length);
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_port = 0;
+ if ((client = clnttcp_create(&server_addr, prognum,
+ versnum, &socket, BUFSIZ, BUFSIZ)) == NULL) {
+ perror("rpctcp_create");
+ return (-1);
+ }
+ total_timeout.tv_sec = 20;
+ total_timeout.tv_usec = 0;
+ clnt_stat = clnt_call(client, procnum,
+ inproc, in, outproc, out, total_timeout);
+ clnt_destroy(client);
+ return (int)clnt_stat;
+}
+.vs
+.DE
+.ie t .DS
+.el .DS L
+.vs 11
+.ft I
+/*
+ * The receiving routines
+ */
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h>
+
+main()
+{
+ register SVCXPRT *transp;
+ int rcp_service(), xdr_rcp();
+
+ if ((transp = svctcp_create(RPC_ANYSOCK,
+ BUFSIZ, BUFSIZ)) == NULL) {
+ fprintf("svctcp_create: error\en");
+ exit(1);
+ }
+ pmap_unset(RCPPROG, RCPVERS);
+ if (!svc_register(transp,
+ RCPPROG, RCPVERS, rcp_service, IPPROTO_TCP)) {
+ fprintf(stderr, "svc_register: error\en");
+ exit(1);
+ }
+ svc_run(); /* \fInever returns\fP */
+ fprintf(stderr, "svc_run should never return\en");
+}
+
+rcp_service(rqstp, transp)
+ register struct svc_req *rqstp;
+ register SVCXPRT *transp;
+{
+ switch (rqstp->rq_proc) {
+ case NULLPROC:
+ if (svc_sendreply(transp, xdr_void, 0) == 0) {
+ fprintf(stderr, "err: rcp_service");
+ return (1);
+ }
+ return;
+ case RCPPROC_FP:
+ if (!svc_getargs(transp, xdr_rcp, stdout)) {
+ svcerr_decode(transp);
+ return;
+ }
+ if (!svc_sendreply(transp, xdr_void, 0)) {
+ fprintf(stderr, "can't reply\en");
+ return;
+ }
+ return (0);
+ default:
+ svcerr_noproc(transp);
+ return;
+ }
+}
+.vs
+.DE
+.NH 2
+\&Callback Procedures
+.IX RPC "callback procedures"
+.LP
+Occasionally, it is useful to have a server become a client,
+and make an RPC call back to the process which is its client.
+An example is remote debugging,
+where the client is a window system program,
+and the server is a debugger running on the remote machine.
+Most of the time,
+the user clicks a mouse button at the debugging window,
+which converts this to a debugger command,
+and then makes an RPC call to the server
+(where the debugger is actually running),
+telling it to execute that command.
+However, when the debugger hits a breakpoint, the roles are reversed,
+and the debugger wants to make an rpc call to the window program,
+so that it can inform the user that a breakpoint has been reached.
+.LP
+In order to do an RPC callback,
+you need a program number to make the RPC call on.
+Since this will be a dynamically generated program number,
+it should be in the transient range,
+.I "0x40000000 - 0x5fffffff" .
+The routine
+.I gettransient()
+returns a valid program number in the transient range,
+and registers it with the portmapper.
+It only talks to the portmapper running on the same machine as the
+.I gettransient()
+routine itself. The call to
+.I pmap_set()
+is a test and set operation,
+in that it indivisibly tests whether a program number
+has already been registered,
+and if it has not, then reserves it. On return, the
+.I sockp
+argument will contain a socket that can be used
+as the argument to an
+.I svcudp_create()
+or
+.I svctcp_create()
+call.
+.ie t .DS
+.el .DS L
+.ft CW
+.vs 11
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <sys/socket.h>
+
+gettransient(proto, vers, sockp)
+ int proto, vers, *sockp;
+{
+ static int prognum = 0x40000000;
+ int s, len, socktype;
+ struct sockaddr_in addr;
+
+ switch(proto) {
+ case IPPROTO_UDP:
+ socktype = SOCK_DGRAM;
+ break;
+ case IPPROTO_TCP:
+ socktype = SOCK_STREAM;
+ break;
+ default:
+ fprintf(stderr, "unknown protocol type\en");
+ return 0;
+ }
+ if (*sockp == RPC_ANYSOCK) {
+ if ((s = socket(AF_INET, socktype, 0)) < 0) {
+ perror("socket");
+ return (0);
+ }
+ *sockp = s;
+ }
+ else
+ s = *sockp;
+ addr.sin_addr.s_addr = 0;
+ addr.sin_family = AF_INET;
+ addr.sin_port = 0;
+ len = sizeof(addr);
+.ft I
+ /*
+ * may be already bound, so don't check for error
+ */
+.ft CW
+ bind(s, &addr, len);
+ if (getsockname(s, &addr, &len)< 0) {
+ perror("getsockname");
+ return (0);
+ }
+ while (!pmap_set(prognum++, vers, proto,
+ ntohs(addr.sin_port))) continue;
+ return (prognum-1);
+}
+.vs
+.DE
+.SH
+Note:
+.I
+The call to
+.I ntohs()
+is necessary to ensure that the port number in
+.I "addr.sin_port" ,
+which is in
+.I network
+byte order, is passed in
+.I host
+byte order (as
+.I pmap_set()
+expects). See the
+.I byteorder(3N)
+man page for more details on the conversion of network
+addresses from network to host byte order.
+.KS
+.LP
+The following pair of programs illustrate how to use the
+.I gettransient()
+routine.
+The client makes an RPC call to the server,
+passing it a transient program number.
+Then the client waits around to receive a callback
+from the server at that program number.
+The server registers the program
+.I EXAMPLEPROG
+so that it can receive the RPC call
+informing it of the callback program number.
+Then at some random time (on receiving an
+.I ALRM
+signal in this example), it sends a callback RPC call,
+using the program number it received earlier.
+.ie t .DS
+.el .DS L
+.vs 11
+.ft I
+/*
+ * client
+ */
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h>
+
+int callback();
+char hostname[256];
+
+main()
+{
+ int x, ans, s;
+ SVCXPRT *xprt;
+
+ gethostname(hostname, sizeof(hostname));
+ s = RPC_ANYSOCK;
+ x = gettransient(IPPROTO_UDP, 1, &s);
+ fprintf(stderr, "client gets prognum %d\en", x);
+ if ((xprt = svcudp_create(s)) == NULL) {
+ fprintf(stderr, "rpc_server: svcudp_create\en");
+ exit(1);
+ }
+.ft I
+ /* protocol is 0 - gettransient does registering
+ */
+.ft CW
+ (void)svc_register(xprt, x, 1, callback, 0);
+ ans = callrpc(hostname, EXAMPLEPROG, EXAMPLEVERS,
+ EXAMPLEPROC_CALLBACK, xdr_int, &x, xdr_void, 0);
+ if ((enum clnt_stat) ans != RPC_SUCCESS) {
+ fprintf(stderr, "call: ");
+ clnt_perrno(ans);
+ fprintf(stderr, "\en");
+ }
+ svc_run();
+ fprintf(stderr, "Error: svc_run shouldn't return\en");
+}
+
+callback(rqstp, transp)
+ register struct svc_req *rqstp;
+ register SVCXPRT *transp;
+{
+ switch (rqstp->rq_proc) {
+ case 0:
+ if (!svc_sendreply(transp, xdr_void, 0)) {
+ fprintf(stderr, "err: exampleprog\en");
+ return (1);
+ }
+ return (0);
+ case 1:
+ if (!svc_getargs(transp, xdr_void, 0)) {
+ svcerr_decode(transp);
+ return (1);
+ }
+ fprintf(stderr, "client got callback\en");
+ if (!svc_sendreply(transp, xdr_void, 0)) {
+ fprintf(stderr, "err: exampleprog");
+ return (1);
+ }
+ }
+}
+.vs
+.DE
+.KE
+.ie t .DS
+.el .DS L
+.vs 11
+.ft I
+/*
+ * server
+ */
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <sys/signal.h>
+
+char *getnewprog();
+char hostname[256];
+int docallback();
+int pnum; /* \fIprogram number for callback routine\fP */
+
+main()
+{
+ gethostname(hostname, sizeof(hostname));
+ registerrpc(EXAMPLEPROG, EXAMPLEVERS,
+ EXAMPLEPROC_CALLBACK, getnewprog, xdr_int, xdr_void);
+ fprintf(stderr, "server going into svc_run\en");
+ signal(SIGALRM, docallback);
+ alarm(10);
+ svc_run();
+ fprintf(stderr, "Error: svc_run shouldn't return\en");
+}
+
+char *
+getnewprog(pnump)
+ char *pnump;
+{
+ pnum = *(int *)pnump;
+ return NULL;
+}
+
+docallback()
+{
+ int ans;
+
+ ans = callrpc(hostname, pnum, 1, 1, xdr_void, 0,
+ xdr_void, 0);
+ if (ans != 0) {
+ fprintf(stderr, "server: ");
+ clnt_perrno(ans);
+ fprintf(stderr, "\en");
+ }
+}
+.vs
+.DE
diff --git a/cpukit/librpc/src/rpc/PSD.doc/rpc.rfc.ms b/cpukit/librpc/src/rpc/PSD.doc/rpc.rfc.ms
new file mode 100644
index 0000000000..af9c2df2ed
--- /dev/null
+++ b/cpukit/librpc/src/rpc/PSD.doc/rpc.rfc.ms
@@ -0,0 +1,1302 @@
+.\"
+.\" Must use -- tbl -- with this one
+.\"
+.\" @(#)rpc.rfc.ms 2.2 88/08/05 4.0 RPCSRC
+.de BT
+.if \\n%=1 .tl ''- % -''
+..
+.ND
+.\" prevent excess underlining in nroff
+.if n .fp 2 R
+.OH 'Remote Procedure Calls: Protocol Specification''Page %'
+.EH 'Page %''Remote Procedure Calls: Protocol Specification'
+.if \\n%=1 .bp
+.SH
+\&Remote Procedure Calls: Protocol Specification
+.LP
+.NH 0
+\&Status of this Memo
+.LP
+Note: This chapter specifies a protocol that Sun Microsystems, Inc.,
+and others are using.
+It has been designated RFC1050 by the ARPA Network
+Information Center.
+.LP
+.NH 1
+\&Introduction
+.LP
+This chapter specifies a message protocol used in implementing
+Sun's Remote Procedure Call (RPC) package. (The message protocol is
+specified with the External Data Representation (XDR) language.
+See the
+.I "External Data Representation Standard: Protocol Specification"
+for the details. Here, we assume that the reader is familiar
+with XDR and do not attempt to justify it or its uses). The paper
+by Birrell and Nelson [1] is recommended as an excellent background
+to and justification of RPC.
+.NH 2
+\&Terminology
+.LP
+This chapter discusses servers, services, programs, procedures,
+clients, and versions. A server is a piece of software where network
+services are implemented. A network service is a collection of one
+or more remote programs. A remote program implements one or more
+remote procedures; the procedures, their parameters, and results are
+documented in the specific program's protocol specification (see the
+\fIPort Mapper Program Protocol\fP\, below, for an example). Network
+clients are pieces of software that initiate remote procedure calls
+to services. A server may support more than one version of a remote
+program in order to be forward compatible with changing protocols.
+.LP
+For example, a network file service may be composed of two programs.
+One program may deal with high-level applications such as file system
+access control and locking. The other may deal with low-level file
+IO and have procedures like "read" and "write". A client machine of
+the network file service would call the procedures associated with
+the two programs of the service on behalf of some user on the client
+machine.
+.NH 2
+\&The RPC Model
+.LP
+The remote procedure call model is similar to the local procedure
+call model. In the local case, the caller places arguments to a
+procedure in some well-specified location (such as a result
+register). It then transfers control to the procedure, and
+eventually gains back control. At that point, the results of the
+procedure are extracted from the well-specified location, and the
+caller continues execution.
+.LP
+The remote procedure call is similar, in that one thread of control
+logically winds through two processes\(emone is the caller's process,
+the other is a server's process. That is, the caller process sends a
+call message to the server process and waits (blocks) for a reply
+message. The call message contains the procedure's parameters, among
+other things. The reply message contains the procedure's results,
+among other things. Once the reply message is received, the results
+of the procedure are extracted, and caller's execution is resumed.
+.LP
+On the server side, a process is dormant awaiting the arrival of a
+call message. When one arrives, the server process extracts the
+procedure's parameters, computes the results, sends a reply message,
+and then awaits the next call message.
+.LP
+Note that in this model, only one of the two processes is active at
+any given time. However, this model is only given as an example.
+The RPC protocol makes no restrictions on the concurrency model
+implemented, and others are possible. For example, an implementation
+may choose to have RPC calls be asynchronous, so that the client may
+do useful work while waiting for the reply from the server. Another
+possibility is to have the server create a task to process an
+incoming request, so that the server can be free to receive other
+requests.
+.NH 2
+\&Transports and Semantics
+.LP
+The RPC protocol is independent of transport protocols. That is, RPC
+does not care how a message is passed from one process to another.
+The protocol deals only with specification and interpretation of
+messages.
+.LP
+It is important to point out that RPC does not try to implement any
+kind of reliability and that the application must be aware of the
+type of transport protocol underneath RPC. If it knows it is running
+on top of a reliable transport such as TCP/IP[6], then most of the
+work is already done for it. On the other hand, if it is running on
+top of an unreliable transport such as UDP/IP[7], it must implement
+is own retransmission and time-out policy as the RPC layer does not
+provide this service.
+.LP
+Because of transport independence, the RPC protocol does not attach
+specific semantics to the remote procedures or their execution.
+Semantics can be inferred from (but should be explicitly specified
+by) the underlying transport protocol. For example, consider RPC
+running on top of an unreliable transport such as UDP/IP. If an
+application retransmits RPC messages after short time-outs, the only
+thing it can infer if it receives no reply is that the procedure was
+executed zero or more times. If it does receive a reply, then it can
+infer that the procedure was executed at least once.
+.LP
+A server may wish to remember previously granted requests from a
+client and not regrant them in order to insure some degree of
+execute-at-most-once semantics. A server can do this by taking
+advantage of the transaction ID that is packaged with every RPC
+request. The main use of this transaction is by the client RPC layer
+in matching replies to requests. However, a client application may
+choose to reuse its previous transaction ID when retransmitting a
+request. The server application, knowing this fact, may choose to
+remember this ID after granting a request and not regrant requests
+with the same ID in order to achieve some degree of
+execute-at-most-once semantics. The server is not allowed to examine
+this ID in any other way except as a test for equality.
+.LP
+On the other hand, if using a reliable transport such as TCP/IP, the
+application can infer from a reply message that the procedure was
+executed exactly once, but if it receives no reply message, it cannot
+assume the remote procedure was not executed. Note that even if a
+connection-oriented protocol like TCP is used, an application still
+needs time-outs and reconnection to handle server crashes.
+.LP
+There are other possibilities for transports besides datagram- or
+connection-oriented protocols. For example, a request-reply protocol
+such as VMTP[2] is perhaps the most natural transport for RPC.
+.SH
+.I
+NOTE: At Sun, RPC is currently implemented on top of both TCP/IP
+and UDP/IP transports.
+.LP
+.NH 2
+\&Binding and Rendezvous Independence
+.LP
+The act of binding a client to a service is NOT part of the remote
+procedure call specification. This important and necessary function
+is left up to some higher-level software. (The software may use RPC
+itself\(emsee the \fIPort Mapper Program Protocol\fP\, below).
+.LP
+Implementors should think of the RPC protocol as the jump-subroutine
+instruction ("JSR") of a network; the loader (binder) makes JSR
+useful, and the loader itself uses JSR to accomplish its task.
+Likewise, the network makes RPC useful, using RPC to accomplish this
+task.
+.NH 2
+\&Authentication
+.LP
+The RPC protocol provides the fields necessary for a client to
+identify itself to a service and vice-versa. Security and access
+control mechanisms can be built on top of the message authentication.
+Several different authentication protocols can be supported. A field
+in the RPC header indicates which protocol is being used. More
+information on specific authentication protocols can be found in the
+\fIAuthentication Protocols\fP\,
+below.
+.KS
+.NH 1
+\&RPC Protocol Requirements
+.LP
+The RPC protocol must provide for the following:
+.IP 1.
+Unique specification of a procedure to be called.
+.IP 2.
+Provisions for matching response messages to request messages.
+.KE
+.IP 3.
+Provisions for authenticating the caller to service and vice-versa.
+.LP
+Besides these requirements, features that detect the following are
+worth supporting because of protocol roll-over errors, implementation
+bugs, user error, and network administration:
+.IP 1.
+RPC protocol mismatches.
+.IP 2.
+Remote program protocol version mismatches.
+.IP 3.
+Protocol errors (such as misspecification of a procedure's parameters).
+.IP 4.
+Reasons why remote authentication failed.
+.IP 5.
+Any other reasons why the desired procedure was not called.
+.NH 2
+\&Programs and Procedures
+.LP
+The RPC call message has three unsigned fields: remote program
+number, remote program version number, and remote procedure number.
+The three fields uniquely identify the procedure to be called.
+Program numbers are administered by some central authority (like
+Sun). Once an implementor has a program number, he can implement his
+remote program; the first implementation would most likely have the
+version number of 1. Because most new protocols evolve into better,
+stable, and mature protocols, a version field of the call message
+identifies which version of the protocol the caller is using.
+Version numbers make speaking old and new protocols through the same
+server process possible.
+.LP
+The procedure number identifies the procedure to be called. These
+numbers are documented in the specific program's protocol
+specification. For example, a file service's protocol specification
+may state that its procedure number 5 is "read" and procedure number
+12 is "write".
+.LP
+Just as remote program protocols may change over several versions,
+the actual RPC message protocol could also change. Therefore, the
+call message also has in it the RPC version number, which is always
+equal to two for the version of RPC described here.
+.LP
+The reply message to a request message has enough information to
+distinguish the following error conditions:
+.IP 1.
+The remote implementation of RPC does speak protocol version 2.
+The lowest and highest supported RPC version numbers are returned.
+.IP 2.
+The remote program is not available on the remote system.
+.IP 3.
+The remote program does not support the requested version number.
+The lowest and highest supported remote program version numbers are
+returned.
+.IP 4.
+The requested procedure number does not exist. (This is usually a
+caller side protocol or programming error.)
+.IP 5.
+The parameters to the remote procedure appear to be garbage from the
+server's point of view. (Again, this is usually caused by a
+disagreement about the protocol between client and service.)
+.NH 2
+\&Authentication
+.LP
+Provisions for authentication of caller to service and vice-versa are
+provided as a part of the RPC protocol. The call message has two
+authentication fields, the credentials and verifier. The reply
+message has one authentication field, the response verifier. The RPC
+protocol specification defines all three fields to be the following
+opaque type:
+.DS
+.ft CW
+.vs 11
+enum auth_flavor {
+ AUTH_NULL = 0,
+ AUTH_UNIX = 1,
+ AUTH_SHORT = 2,
+ AUTH_DES = 3
+ /* \fIand more to be defined\fP */
+};
+
+struct opaque_auth {
+ auth_flavor flavor;
+ opaque body<400>;
+};
+.DE
+.LP
+In simple English, any
+.I opaque_auth
+structure is an
+.I auth_flavor
+enumeration followed by bytes which are opaque to the RPC protocol
+implementation.
+.LP
+The interpretation and semantics of the data contained within the
+authentication fields is specified by individual, independent
+authentication protocol specifications. (See
+\fIAuthentication Protocols\fP\,
+below, for definitions of the various authentication protocols.)
+.LP
+If authentication parameters were rejected, the response message
+contains information stating why they were rejected.
+.NH 2
+\&Program Number Assignment
+.LP
+Program numbers are given out in groups of
+.I 0x20000000
+(decimal 536870912) according to the following chart:
+.TS
+box tab (&) ;
+lfI lfI
+rfL cfI .
+Program Numbers&Description
+_
+.sp .5
+0 - 1fffffff&Defined by Sun
+20000000 - 3fffffff&Defined by user
+40000000 - 5fffffff&Transient
+60000000 - 7fffffff&Reserved
+80000000 - 9fffffff&Reserved
+a0000000 - bfffffff&Reserved
+c0000000 - dfffffff&Reserved
+e0000000 - ffffffff&Reserved
+.TE
+.LP
+The first group is a range of numbers administered by Sun
+Microsystems and should be identical for all sites. The second range
+is for applications peculiar to a particular site. This range is
+intended primarily for debugging new programs. When a site develops
+an application that might be of general interest, that application
+should be given an assigned number in the first range. The third
+group is for applications that generate program numbers dynamically.
+The final groups are reserved for future use, and should not be used.
+.NH 2
+\&Other Uses of the RPC Protocol
+.LP
+The intended use of this protocol is for calling remote procedures.
+That is, each call message is matched with a response message.
+However, the protocol itself is a message-passing protocol with which
+other (non-RPC) protocols can be implemented. Sun currently uses, or
+perhaps abuses, the RPC message protocol for the following two
+(non-RPC) protocols: batching (or pipelining) and broadcast RPC.
+These two protocols are discussed but not defined below.
+.NH 3
+\&Batching
+.LP
+Batching allows a client to send an arbitrarily large sequence of
+call messages to a server; batching typically uses reliable byte
+stream protocols (like TCP/IP) for its transport. In the case of
+batching, the client never waits for a reply from the server, and the
+server does not send replies to batch requests. A sequence of batch
+calls is usually terminated by a legitimate RPC in order to flush the
+pipeline (with positive acknowledgement).
+.NH 3
+\&Broadcast RPC
+.LP
+In broadcast RPC-based protocols, the client sends a broadcast packet
+to the network and waits for numerous replies. Broadcast RPC uses
+unreliable, packet-based protocols (like UDP/IP) as its transports.
+Servers that support broadcast protocols only respond when the
+request is successfully processed, and are silent in the face of
+errors. Broadcast RPC uses the Port Mapper RPC service to achieve
+its semantics. See the \fIPort Mapper Program Protocol\fP\, below,
+for more information.
+.KS
+.NH 1
+\&The RPC Message Protocol
+.LP
+This section defines the RPC message protocol in the XDR data
+description language. The message is defined in a top-down style.
+.ie t .DS
+.el .DS L
+.ft CW
+enum msg_type {
+ CALL = 0,
+ REPLY = 1
+};
+
+.ft I
+/*
+* A reply to a call message can take on two forms:
+* The message was either accepted or rejected.
+*/
+.ft CW
+enum reply_stat {
+ MSG_ACCEPTED = 0,
+ MSG_DENIED = 1
+};
+
+.ft I
+/*
+* Given that a call message was accepted, the following is the
+* status of an attempt to call a remote procedure.
+*/
+.ft CW
+enum accept_stat {
+ SUCCESS = 0, /* \fIRPC executed successfully \fP*/
+ PROG_UNAVAIL = 1, /* \fIremote hasn't exported program \fP*/
+ PROG_MISMATCH = 2, /* \fIremote can't support version # \fP*/
+ PROC_UNAVAIL = 3, /* \fIprogram can't support procedure \fP*/
+ GARBAGE_ARGS = 4 /* \fIprocedure can't decode params \fP*/
+};
+.DE
+.ie t .DS
+.el .DS L
+.ft I
+/*
+* Reasons why a call message was rejected:
+*/
+.ft CW
+enum reject_stat {
+ RPC_MISMATCH = 0, /* \fIRPC version number != 2 \fP*/
+ AUTH_ERROR = 1 /* \fIremote can't authenticate caller \fP*/
+};
+
+.ft I
+/*
+* Why authentication failed:
+*/
+.ft CW
+enum auth_stat {
+ AUTH_BADCRED = 1, /* \fIbad credentials \fP*/
+ AUTH_REJECTEDCRED = 2, /* \fIclient must begin new session \fP*/
+ AUTH_BADVERF = 3, /* \fIbad verifier \fP*/
+ AUTH_REJECTEDVERF = 4, /* \fIverifier expired or replayed \fP*/
+ AUTH_TOOWEAK = 5 /* \fIrejected for security reasons \fP*/
+};
+.DE
+.KE
+.ie t .DS
+.el .DS L
+.ft I
+/*
+* The RPC message:
+* All messages start with a transaction identifier, xid,
+* followed by a two-armed discriminated union. The union's
+* discriminant is a msg_type which switches to one of the two
+* types of the message. The xid of a \fIREPLY\fP message always
+* matches that of the initiating \fICALL\fP message. NB: The xid
+* field is only used for clients matching reply messages with
+* call messages or for servers detecting retransmissions; the
+* service side cannot treat this id as any type of sequence
+* number.
+*/
+.ft CW
+struct rpc_msg {
+ unsigned int xid;
+ union switch (msg_type mtype) {
+ case CALL:
+ call_body cbody;
+ case REPLY:
+ reply_body rbody;
+ } body;
+};
+.DE
+.ie t .DS
+.el .DS L
+.ft I
+/*
+* Body of an RPC request call:
+* In version 2 of the RPC protocol specification, rpcvers must
+* be equal to 2. The fields prog, vers, and proc specify the
+* remote program, its version number, and the procedure within
+* the remote program to be called. After these fields are two
+* authentication parameters: cred (authentication credentials)
+* and verf (authentication verifier). The two authentication
+* parameters are followed by the parameters to the remote
+* procedure, which are specified by the specific program
+* protocol.
+*/
+.ft CW
+struct call_body {
+ unsigned int rpcvers; /* \fImust be equal to two (2) \fP*/
+ unsigned int prog;
+ unsigned int vers;
+ unsigned int proc;
+ opaque_auth cred;
+ opaque_auth verf;
+ /* \fIprocedure specific parameters start here \fP*/
+};
+.DE
+.ie t .DS
+.el .DS L
+.ft I
+/*
+* Body of a reply to an RPC request:
+* The call message was either accepted or rejected.
+*/
+.ft CW
+union reply_body switch (reply_stat stat) {
+ case MSG_ACCEPTED:
+ accepted_reply areply;
+ case MSG_DENIED:
+ rejected_reply rreply;
+} reply;
+.DE
+.ie t .DS
+.el .DS L
+.ft I
+/*
+* Reply to an RPC request that was accepted by the server:
+* there could be an error even though the request was accepted.
+* The first field is an authentication verifier that the server
+* generates in order to validate itself to the caller. It is
+* followed by a union whose discriminant is an enum
+* accept_stat. The \fISUCCESS\fP arm of the union is protocol
+* specific. The \fIPROG_UNAVAIL\fP, \fIPROC_UNAVAIL\fP, and \fIGARBAGE_ARGP\fP
+* arms of the union are void. The \fIPROG_MISMATCH\fP arm specifies
+* the lowest and highest version numbers of the remote program
+* supported by the server.
+*/
+.ft CW
+struct accepted_reply {
+ opaque_auth verf;
+ union switch (accept_stat stat) {
+ case SUCCESS:
+ opaque results[0];
+ /* \fIprocedure-specific results start here\fP */
+ case PROG_MISMATCH:
+ struct {
+ unsigned int low;
+ unsigned int high;
+ } mismatch_info;
+ default:
+.ft I
+ /*
+ * Void. Cases include \fIPROG_UNAVAIL, PROC_UNAVAIL\fP,
+ * and \fIGARBAGE_ARGS\fP.
+ */
+.ft CW
+ void;
+ } reply_data;
+};
+.DE
+.ie t .DS
+.el .DS L
+.ft I
+/*
+* Reply to an RPC request that was rejected by the server:
+* The request can be rejected for two reasons: either the
+* server is not running a compatible version of the RPC
+* protocol (\fIRPC_MISMATCH\fP), or the server refuses to
+* authenticate the caller (\fIAUTH_ERROR\fP). In case of an RPC
+* version mismatch, the server returns the lowest and highest
+* supported RPC version numbers. In case of refused
+* authentication, failure status is returned.
+*/
+.ft CW
+union rejected_reply switch (reject_stat stat) {
+ case RPC_MISMATCH:
+ struct {
+ unsigned int low;
+ unsigned int high;
+ } mismatch_info;
+ case AUTH_ERROR:
+ auth_stat stat;
+};
+.DE
+.NH 1
+\&Authentication Protocols
+.LP
+As previously stated, authentication parameters are opaque, but
+open-ended to the rest of the RPC protocol. This section defines
+some "flavors" of authentication implemented at (and supported by)
+Sun. Other sites are free to invent new authentication types, with
+the same rules of flavor number assignment as there is for program
+number assignment.
+.NH 2
+\&Null Authentication
+.LP
+Often calls must be made where the caller does not know who he is or
+the server does not care who the caller is. In this case, the flavor
+value (the discriminant of the \fIopaque_auth\fP's union) of the RPC
+message's credentials, verifier, and response verifier is
+.I AUTH_NULL .
+The bytes of the opaque_auth's body are undefined.
+It is recommended that the opaque length be zero.
+.NH 2
+\&UNIX Authentication
+.LP
+The caller of a remote procedure may wish to identify himself as he
+is identified on a UNIX system. The value of the credential's
+discriminant of an RPC call message is
+.I AUTH_UNIX .
+The bytes of
+the credential's opaque body encode the following structure:
+.DS
+.ft CW
+struct auth_unix {
+ unsigned int stamp;
+ string machinename<255>;
+ unsigned int uid;
+ unsigned int gid;
+ unsigned int gids<10>;
+};
+.DE
+The
+.I stamp
+is an arbitrary ID which the caller machine may
+generate. The
+.I machinename
+is the name of the caller's machine (like "krypton"). The
+.I uid
+is the caller's effective user ID. The
+.I gid
+is the caller's effective group ID. The
+.I gids
+is a
+counted array of groups which contain the caller as a member. The
+verifier accompanying the credentials should be of
+.I AUTH_NULL
+(defined above).
+.LP
+The value of the discriminant of the response verifier received in
+the reply message from the server may be
+.I AUTH_NULL
+or
+.I AUTH_SHORT .
+In the case of
+.I AUTH_SHORT ,
+the bytes of the response verifier's string encode an opaque
+structure. This new opaque structure may now be passed to the server
+instead of the original
+.I AUTH_UNIX
+flavor credentials. The server keeps a cache which maps shorthand
+opaque structures (passed back by way of an
+.I AUTH_SHORT
+style response verifier) to the original credentials of the caller.
+The caller can save network bandwidth and server cpu cycles by using
+the new credentials.
+.LP
+The server may flush the shorthand opaque structure at any time. If
+this happens, the remote procedure call message will be rejected due
+to an authentication error. The reason for the failure will be
+.I AUTH_REJECTEDCRED .
+At this point, the caller may wish to try the original
+.I AUTH_UNIX
+style of credentials.
+.KS
+.NH 2
+\&DES Authentication
+.LP
+UNIX authentication suffers from two major problems:
+.IP 1.
+The naming is too UNIX-system oriented.
+.IP 2.
+There is no verifier, so credentials can easily be faked.
+.LP
+DES authentication attempts to fix these two problems.
+.KE
+.NH 3
+\&Naming
+.LP
+The first problem is handled by addressing the caller by a simple
+string of characters instead of by an operating system specific
+integer. This string of characters is known as the "netname" or
+network name of the caller. The server is not allowed to interpret
+the contents of the caller's name in any other way except to
+identify the caller. Thus, netnames should be unique for every
+caller in the internet.
+.LP
+It is up to each operating system's implementation of DES
+authentication to generate netnames for its users that insure this
+uniqueness when they call upon remote servers. Operating systems
+already know how to distinguish users local to their systems. It is
+usually a simple matter to extend this mechanism to the network.
+For example, a UNIX user at Sun with a user ID of 515 might be
+assigned the following netname: "unix.515@sun.com". This netname
+contains three items that serve to insure it is unique. Going
+backwards, there is only one naming domain called "sun.com" in the
+internet. Within this domain, there is only one UNIX user with
+user ID 515. However, there may be another user on another
+operating system, for example VMS, within the same naming domain
+that, by coincidence, happens to have the same user ID. To insure
+that these two users can be distinguished we add the operating
+system name. So one user is "unix.515@sun.com" and the other is
+"vms.515@sun.com".
+.LP
+The first field is actually a naming method rather than an
+operating system name. It just happens that today there is almost
+a one-to-one correspondence between naming methods and operating
+systems. If the world could agree on a naming standard, the first
+field could be the name of that standard, instead of an operating
+system name.
+.LP
+.NH 3
+\&DES Authentication Verifiers
+.LP
+Unlike UNIX authentication, DES authentication does have a verifier
+so the server can validate the client's credential (and
+vice-versa). The contents of this verifier is primarily an
+encrypted timestamp. The server can decrypt this timestamp, and if
+it is close to what the real time is, then the client must have
+encrypted it correctly. The only way the client could encrypt it
+correctly is to know the "conversation key" of the RPC session. And
+if the client knows the conversation key, then it must be the real
+client.
+.LP
+The conversation key is a DES [5] key which the client generates
+and notifies the server of in its first RPC call. The conversation
+key is encrypted using a public key scheme in this first
+transaction. The particular public key scheme used in DES
+authentication is Diffie-Hellman [3] with 192-bit keys. The
+details of this encryption method are described later.
+.LP
+The client and the server need the same notion of the current time
+in order for all of this to work. If network time synchronization
+cannot be guaranteed, then client can synchronize with the server
+before beginning the conversation, perhaps by consulting the
+Internet Time Server (TIME[4]).
+.LP
+The way a server determines if a client timestamp is valid is
+somewhat complicated. For any other transaction but the first, the
+server just checks for two things:
+.IP 1.
+the timestamp is greater than the one previously seen from the
+same client.
+.IP 2.
+the timestamp has not expired.
+.LP
+A timestamp is expired if the server's time is later than the sum
+of the client's timestamp plus what is known as the client's
+"window". The "window" is a number the client passes (encrypted)
+to the server in its first transaction. You can think of it as a
+lifetime for the credential.
+.LP
+This explains everything but the first transaction. In the first
+transaction, the server checks only that the timestamp has not
+expired. If this was all that was done though, then it would be
+quite easy for the client to send random data in place of the
+timestamp with a fairly good chance of succeeding. As an added
+check, the client sends an encrypted item in the first transaction
+known as the "window verifier" which must be equal to the window
+minus 1, or the server will reject the credential.
+.LP
+The client too must check the verifier returned from the server to
+be sure it is legitimate. The server sends back to the client the
+encrypted timestamp it received from the client, minus one second.
+If the client gets anything different than this, it will reject it.
+.LP
+.NH 3
+\&Nicknames and Clock Synchronization
+.LP
+After the first transaction, the server's DES authentication
+subsystem returns in its verifier to the client an integer
+"nickname" which the client may use in its further transactions
+instead of passing its netname, encrypted DES key and window every
+time. The nickname is most likely an index into a table on the
+server which stores for each client its netname, decrypted DES key
+and window.
+.LP
+Though they originally were synchronized, the client's and server's
+clocks can get out of sync again. When this happens the client RPC
+subsystem most likely will get back
+.I RPC_AUTHERROR
+at which point it should resynchronize.
+.LP
+A client may still get the
+.I RPC_AUTHERROR
+error even though it is
+synchronized with the server. The reason is that the server's
+nickname table is a limited size, and it may flush entries whenever
+it wants. A client should resend its original credential in this
+case and the server will give it a new nickname. If a server
+crashes, the entire nickname table gets flushed, and all clients
+will have to resend their original credentials.
+.KS
+.NH 3
+\&DES Authentication Protocol (in XDR language)
+.ie t .DS
+.el .DS L
+.ft I
+/*
+* There are two kinds of credentials: one in which the client uses
+* its full network name, and one in which it uses its "nickname"
+* (just an unsigned integer) given to it by the server. The
+* client must use its fullname in its first transaction with the
+* server, in which the server will return to the client its
+* nickname. The client may use its nickname in all further
+* transactions with the server. There is no requirement to use the
+* nickname, but it is wise to use it for performance reasons.
+*/
+.ft CW
+enum authdes_namekind {
+ ADN_FULLNAME = 0,
+ ADN_NICKNAME = 1
+};
+
+.ft I
+/*
+* A 64-bit block of encrypted DES data
+*/
+.ft CW
+typedef opaque des_block[8];
+
+.ft I
+/*
+* Maximum length of a network user's name
+*/
+.ft CW
+const MAXNETNAMELEN = 255;
+
+.ft I
+/*
+* A fullname contains the network name of the client, an encrypted
+* conversation key and the window. The window is actually a
+* lifetime for the credential. If the time indicated in the
+* verifier timestamp plus the window has past, then the server
+* should expire the request and not grant it. To insure that
+* requests are not replayed, the server should insist that
+* timestamps are greater than the previous one seen, unless it is
+* the first transaction. In the first transaction, the server
+* checks instead that the window verifier is one less than the
+* window.
+*/
+.ft CW
+struct authdes_fullname {
+string name<MAXNETNAMELEN>; /* \fIname of client \f(CW*/
+des_block key; /* \fIPK encrypted conversation key \f(CW*/
+unsigned int window; /* \fIencrypted window \f(CW*/
+};
+
+.ft I
+/*
+* A credential is either a fullname or a nickname
+*/
+.ft CW
+union authdes_cred switch (authdes_namekind adc_namekind) {
+ case ADN_FULLNAME:
+ authdes_fullname adc_fullname;
+ case ADN_NICKNAME:
+ unsigned int adc_nickname;
+};
+
+.ft I
+/*
+* A timestamp encodes the time since midnight, January 1, 1970.
+*/
+.ft CW
+struct timestamp {
+ unsigned int seconds; /* \fIseconds \fP*/
+ unsigned int useconds; /* \fIand microseconds \fP*/
+};
+
+.ft I
+/*
+* Verifier: client variety
+* The window verifier is only used in the first transaction. In
+* conjunction with a fullname credential, these items are packed
+* into the following structure before being encrypted:
+*
+* \f(CWstruct {\fP
+* \f(CWadv_timestamp; \fP-- one DES block
+* \f(CWadc_fullname.window; \fP-- one half DES block
+* \f(CWadv_winverf; \fP-- one half DES block
+* \f(CW}\fP
+* This structure is encrypted using CBC mode encryption with an
+* input vector of zero. All other encryptions of timestamps use
+* ECB mode encryption.
+*/
+.ft CW
+struct authdes_verf_clnt {
+ timestamp adv_timestamp; /* \fIencrypted timestamp \fP*/
+ unsigned int adv_winverf; /* \fIencrypted window verifier \fP*/
+};
+
+.ft I
+/*
+* Verifier: server variety
+* The server returns (encrypted) the same timestamp the client
+* gave it minus one second. It also tells the client its nickname
+* to be used in future transactions (unencrypted).
+*/
+.ft CW
+struct authdes_verf_svr {
+timestamp adv_timeverf; /* \fIencrypted verifier \fP*/
+unsigned int adv_nickname; /* \fInew nickname for client \fP*/
+};
+.DE
+.KE
+.NH 3
+\&Diffie-Hellman Encryption
+.LP
+In this scheme, there are two constants,
+.I BASE
+and
+.I MODULUS .
+The
+particular values Sun has chosen for these for the DES
+authentication protocol are:
+.ie t .DS
+.el .DS L
+.ft CW
+const BASE = 3;
+const MODULUS =
+ "d4a0ba0250b6fd2ec626e7efd637df76c716e22d0944b88b"; /* \fIhex \fP*/
+.DE
+.ft R
+The way this scheme works is best explained by an example. Suppose
+there are two people "A" and "B" who want to send encrypted
+messages to each other. So, A and B both generate "secret" keys at
+random which they do not reveal to anyone. Let these keys be
+represented as SK(A) and SK(B). They also publish in a public
+directory their "public" keys. These keys are computed as follows:
+.ie t .DS
+.el .DS L
+.ft CW
+PK(A) = ( BASE ** SK(A) ) mod MODULUS
+PK(B) = ( BASE ** SK(B) ) mod MODULUS
+.DE
+.ft R
+The "**" notation is used here to represent exponentiation. Now,
+both A and B can arrive at the "common" key between them,
+represented here as CK(A, B), without revealing their secret keys.
+.LP
+A computes:
+.ie t .DS
+.el .DS L
+.ft CW
+CK(A, B) = ( PK(B) ** SK(A)) mod MODULUS
+.DE
+.ft R
+while B computes:
+.ie t .DS
+.el .DS L
+.ft CW
+CK(A, B) = ( PK(A) ** SK(B)) mod MODULUS
+.DE
+.ft R
+These two can be shown to be equivalent:
+.ie t .DS
+.el .DS L
+.ft CW
+(PK(B) ** SK(A)) mod MODULUS = (PK(A) ** SK(B)) mod MODULUS
+.DE
+.ft R
+We drop the "mod MODULUS" parts and assume modulo arithmetic to
+simplify things:
+.ie t .DS
+.el .DS L
+.ft CW
+PK(B) ** SK(A) = PK(A) ** SK(B)
+.DE
+.ft R
+Then, replace PK(B) by what B computed earlier and likewise for
+PK(A).
+.ie t .DS
+.el .DS L
+.ft CW
+((BASE ** SK(B)) ** SK(A) = (BASE ** SK(A)) ** SK(B)
+.DE
+.ft R
+which leads to:
+.ie t .DS
+.el .DS L
+.ft CW
+BASE ** (SK(A) * SK(B)) = BASE ** (SK(A) * SK(B))
+.DE
+.ft R
+This common key CK(A, B) is not used to encrypt the timestamps used
+in the protocol. Rather, it is used only to encrypt a conversation
+key which is then used to encrypt the timestamps. The reason for
+doing this is to use the common key as little as possible, for fear
+that it could be broken. Breaking the conversation key is a far
+less serious offense, since conversations are relatively
+short-lived.
+.LP
+The conversation key is encrypted using 56-bit DES keys, yet the
+common key is 192 bits. To reduce the number of bits, 56 bits are
+selected from the common key as follows. The middle-most 8-bytes
+are selected from the common key, and then parity is added to the
+lower order bit of each byte, producing a 56-bit key with 8 bits of
+parity.
+.KS
+.NH 1
+\&Record Marking Standard
+.LP
+When RPC messages are passed on top of a byte stream protocol (like
+TCP/IP), it is necessary, or at least desirable, to delimit one
+message from another in order to detect and possibly recover from
+user protocol errors. This is called record marking (RM). Sun uses
+this RM/TCP/IP transport for passing RPC messages on TCP streams.
+One RPC message fits into one RM record.
+.LP
+A record is composed of one or more record fragments. A record
+fragment is a four-byte header followed by 0 to (2**31) - 1 bytes of
+fragment data. The bytes encode an unsigned binary number; as with
+XDR integers, the byte order is from highest to lowest. The number
+encodes two values\(ema boolean which indicates whether the fragment
+is the last fragment of the record (bit value 1 implies the fragment
+is the last fragment) and a 31-bit unsigned binary value which is the
+length in bytes of the fragment's data. The boolean value is the
+highest-order bit of the header; the length is the 31 low-order bits.
+(Note that this record specification is NOT in XDR standard form!)
+.KE
+.KS
+.NH 1
+\&The RPC Language
+.LP
+Just as there was a need to describe the XDR data-types in a formal
+language, there is also need to describe the procedures that operate
+on these XDR data-types in a formal language as well. We use the RPC
+Language for this purpose. It is an extension to the XDR language.
+The following example is used to describe the essence of the
+language.
+.NH 2
+\&An Example Service Described in the RPC Language
+.LP
+Here is an example of the specification of a simple ping program.
+.ie t .DS
+.el .DS L
+.vs 11
+.ft I
+/*
+* Simple ping program
+*/
+.ft CW
+program PING_PROG {
+ /* \fILatest and greatest version\fP */
+ version PING_VERS_PINGBACK {
+ void
+ PINGPROC_NULL(void) = 0;
+
+.ft I
+ /*
+ * Ping the caller, return the round-trip time
+ * (in microseconds). Returns -1 if the operation
+ * timed out.
+ */
+.ft CW
+ int
+ PINGPROC_PINGBACK(void) = 1;
+} = 2;
+
+.ft I
+/*
+* Original version
+*/
+.ft CW
+version PING_VERS_ORIG {
+ void
+ PINGPROC_NULL(void) = 0;
+ } = 1;
+} = 1;
+
+const PING_VERS = 2; /* \fIlatest version \fP*/
+.vs
+.DE
+.KE
+.LP
+The first version described is
+.I PING_VERS_PINGBACK
+with two procedures,
+.I PINGPROC_NULL
+and
+.I PINGPROC_PINGBACK .
+.I PINGPROC_NULL
+takes no arguments and returns no results, but it is useful for
+computing round-trip times from the client to the server and back
+again. By convention, procedure 0 of any RPC protocol should have
+the same semantics, and never require any kind of authentication.
+The second procedure is used for the client to have the server do a
+reverse ping operation back to the client, and it returns the amount
+of time (in microseconds) that the operation used. The next version,
+.I PING_VERS_ORIG ,
+is the original version of the protocol
+and it does not contain
+.I PINGPROC_PINGBACK
+procedure. It is useful
+for compatibility with old client programs, and as this program
+matures it may be dropped from the protocol entirely.
+.KS
+.NH 2
+\&The RPC Language Specification
+.LP
+The RPC language is identical to the XDR language, except for the
+added definition of a
+.I program-def
+described below.
+.DS
+.ft CW
+program-def:
+ "program" identifier "{"
+ version-def
+ version-def *
+ "}" "=" constant ";"
+
+version-def:
+ "version" identifier "{"
+ procedure-def
+ procedure-def *
+ "}" "=" constant ";"
+
+procedure-def:
+ type-specifier identifier "(" type-specifier ")"
+ "=" constant ";"
+.DE
+.KE
+.NH 2
+\&Syntax Notes
+.IP 1.
+The following keywords are added and cannot be used as
+identifiers: "program" and "version";
+.IP 2.
+A version name cannot occur more than once within the scope of
+a program definition. Nor can a version number occur more than once
+within the scope of a program definition.
+.IP 3.
+A procedure name cannot occur more than once within the scope
+of a version definition. Nor can a procedure number occur more than
+once within the scope of version definition.
+.IP 4.
+Program identifiers are in the same name space as constant and
+type identifiers.
+.IP 5.
+Only unsigned constants can be assigned to programs, versions
+and procedures.
+.NH 1
+\&Port Mapper Program Protocol
+.LP
+The port mapper program maps RPC program and version numbers to
+transport-specific port numbers. This program makes dynamic binding
+of remote programs possible.
+.LP
+This is desirable because the range of reserved port numbers is very
+small and the number of potential remote programs is very large. By
+running only the port mapper on a reserved port, the port numbers of
+other remote programs can be ascertained by querying the port mapper.
+.LP
+The port mapper also aids in broadcast RPC. A given RPC program will
+usually have different port number bindings on different machines, so
+there is no way to directly broadcast to all of these programs. The
+port mapper, however, does have a fixed port number. So, to
+broadcast to a given program, the client actually sends its message
+to the port mapper located at the broadcast address. Each port
+mapper that picks up the broadcast then calls the local service
+specified by the client. When the port mapper gets the reply from
+the local service, it sends the reply on back to the client.
+.KS
+.NH 2
+\&Port Mapper Protocol Specification (in RPC Language)
+.ie t .DS
+.el .DS L
+.ft CW
+.vs 11
+const PMAP_PORT = 111; /* \fIportmapper port number \fP*/
+
+.ft I
+/*
+* A mapping of (program, version, protocol) to port number
+*/
+.ft CW
+struct mapping {
+ unsigned int prog;
+ unsigned int vers;
+ unsigned int prot;
+ unsigned int port;
+};
+
+.ft I
+/*
+* Supported values for the "prot" field
+*/
+.ft CW
+const IPPROTO_TCP = 6; /* \fIprotocol number for TCP/IP \fP*/
+const IPPROTO_UDP = 17; /* \fIprotocol number for UDP/IP \fP*/
+
+.ft I
+/*
+* A list of mappings
+*/
+.ft CW
+struct *pmaplist {
+ mapping map;
+ pmaplist next;
+};
+.vs
+.DE
+.ie t .DS
+.el .DS L
+.vs 11
+.ft I
+/*
+* Arguments to callit
+*/
+.ft CW
+struct call_args {
+ unsigned int prog;
+ unsigned int vers;
+ unsigned int proc;
+ opaque args<>;
+};
+
+.ft I
+/*
+* Results of callit
+*/
+.ft CW
+struct call_result {
+ unsigned int port;
+ opaque res<>;
+};
+.vs
+.DE
+.KE
+.ie t .DS
+.el .DS L
+.vs 11
+.ft I
+/*
+* Port mapper procedures
+*/
+.ft CW
+program PMAP_PROG {
+ version PMAP_VERS {
+ void
+ PMAPPROC_NULL(void) = 0;
+
+ bool
+ PMAPPROC_SET(mapping) = 1;
+
+ bool
+ PMAPPROC_UNSET(mapping) = 2;
+
+ unsigned int
+ PMAPPROC_GETPORT(mapping) = 3;
+
+ pmaplist
+ PMAPPROC_DUMP(void) = 4;
+
+ call_result
+ PMAPPROC_CALLIT(call_args) = 5;
+ } = 2;
+} = 100000;
+.vs
+.DE
+.NH 2
+\&Port Mapper Operation
+.LP
+The portmapper program currently supports two protocols (UDP/IP and
+TCP/IP). The portmapper is contacted by talking to it on assigned
+port number 111 (SUNRPC [8]) on either of these protocols. The
+following is a description of each of the portmapper procedures:
+.IP \fBPMAPPROC_NULL:\fP
+This procedure does no work. By convention, procedure zero of any
+protocol takes no parameters and returns no results.
+.IP \fBPMAPPROC_SET:\fP
+When a program first becomes available on a machine, it registers
+itself with the port mapper program on the same machine. The program
+passes its program number "prog", version number "vers", transport
+protocol number "prot", and the port "port" on which it awaits
+service request. The procedure returns a boolean response whose
+value is
+.I TRUE
+if the procedure successfully established the mapping and
+.I FALSE
+otherwise. The procedure refuses to establish
+a mapping if one already exists for the tuple "(prog, vers, prot)".
+.IP \fBPMAPPROC_UNSET:\fP
+When a program becomes unavailable, it should unregister itself with
+the port mapper program on the same machine. The parameters and
+results have meanings identical to those of
+.I PMAPPROC_SET .
+The protocol and port number fields of the argument are ignored.
+.IP \fBPMAPPROC_GETPORT:\fP
+Given a program number "prog", version number "vers", and transport
+protocol number "prot", this procedure returns the port number on
+which the program is awaiting call requests. A port value of zeros
+means the program has not been registered. The "port" field of the
+argument is ignored.
+.IP \fBPMAPPROC_DUMP:\fP
+This procedure enumerates all entries in the port mapper's database.
+The procedure takes no parameters and returns a list of program,
+version, protocol, and port values.
+.IP \fBPMAPPROC_CALLIT:\fP
+This procedure allows a caller to call another remote procedure on
+the same machine without knowing the remote procedure's port number.
+It is intended for supporting broadcasts to arbitrary remote programs
+via the well-known port mapper's port. The parameters "prog",
+"vers", "proc", and the bytes of "args" are the program number,
+version number, procedure number, and parameters of the remote
+procedure.
+.LP
+.B Note:
+.RS
+.IP 1.
+This procedure only sends a response if the procedure was
+successfully executed and is silent (no response) otherwise.
+.IP 2.
+The port mapper communicates with the remote program using UDP/IP
+only.
+.RE
+.LP
+The procedure returns the remote program's port number, and the bytes
+of results are the results of the remote procedure.
+.bp
+.NH 1
+\&References
+.LP
+[1] Birrell, Andrew D. & Nelson, Bruce Jay; "Implementing Remote
+Procedure Calls"; XEROX CSL-83-7, October 1983.
+.LP
+[2] Cheriton, D.; "VMTP: Versatile Message Transaction Protocol",
+Preliminary Version 0.3; Stanford University, January 1987.
+.LP
+[3] Diffie & Hellman; "New Directions in Cryptography"; IEEE
+Transactions on Information Theory IT-22, November 1976.
+.LP
+[4] Harrenstien, K.; "Time Server", RFC 738; Information Sciences
+Institute, October 1977.
+.LP
+[5] National Bureau of Standards; "Data Encryption Standard"; Federal
+Information Processing Standards Publication 46, January 1977.
+.LP
+[6] Postel, J.; "Transmission Control Protocol - DARPA Internet
+Program Protocol Specification", RFC 793; Information Sciences
+Institute, September 1981.
+.LP
+[7] Postel, J.; "User Datagram Protocol", RFC 768; Information Sciences
+Institute, August 1980.
+.LP
+[8] Reynolds, J. & Postel, J.; "Assigned Numbers", RFC 923; Information
+Sciences Institute, October 1984.
diff --git a/cpukit/librpc/src/rpc/PSD.doc/rpcgen.ms b/cpukit/librpc/src/rpc/PSD.doc/rpcgen.ms
new file mode 100644
index 0000000000..b4e50e5d6f
--- /dev/null
+++ b/cpukit/librpc/src/rpc/PSD.doc/rpcgen.ms
@@ -0,0 +1,1299 @@
+.\"
+.\" Must use -- tbl -- for this one
+.\"
+.\" @(#)rpcgen.ms 2.2 88/08/04 4.0 RPCSRC
+.de BT
+.if \\n%=1 .tl ''- % -''
+..
+.ND
+.\" prevent excess underlining in nroff
+.if n .fp 2 R
+.OH '\fBrpcgen\fP Programming Guide''Page %'
+.EH 'Page %''\fBrpcgen\fP Programming Guide'
+.if \\n%=1 .bp
+.SH
+\&\fBrpcgen\fP Programming Guide
+.NH 0
+\&The \fBrpcgen\fP Protocol Compiler
+.IX rpcgen "" \fIrpcgen\fP "" PAGE MAJOR
+.LP
+.IX RPC "" "" \fIrpcgen\fP
+The details of programming applications to use Remote Procedure Calls
+can be overwhelming. Perhaps most daunting is the writing of the XDR
+routines necessary to convert procedure arguments and results into
+their network format and vice-versa.
+.LP
+Fortunately,
+.I rpcgen(1)
+exists to help programmers write RPC applications simply and directly.
+.I rpcgen
+does most of the dirty work, allowing programmers to debug
+the main features of their application, instead of requiring them to
+spend most of their time debugging their network interface code.
+.LP
+.I rpcgen
+is a compiler. It accepts a remote program interface definition written
+in a language, called RPC Language, which is similar to C. It produces a C
+language output which includes stub versions of the client routines, a
+server skeleton, XDR filter routines for both parameters and results, and a
+header file that contains common definitions. The client stubs interface
+with the RPC library and effectively hide the network from their callers.
+The server stub similarly hides the network from the server procedures that
+are to be invoked by remote clients.
+.I rpcgen 's
+output files can be compiled and linked in the usual way. The developer
+writes server procedures\(emin any language that observes Sun calling
+conventions\(emand links them with the server skeleton produced by
+.I rpcgen
+to get an executable server program. To use a remote program, a programmer
+writes an ordinary main program that makes local procedure calls to the
+client stubs produced by
+.I rpcgen .
+Linking this program with
+.I rpcgen 's
+stubs creates an executable program. (At present the main program must be
+written in C).
+.I rpcgen
+options can be used to suppress stub generation and to specify the transport
+to be used by the server stub.
+.LP
+Like all compilers,
+.I rpcgen
+reduces development time
+that would otherwise be spent coding and debugging low-level routines.
+All compilers, including
+.I rpcgen ,
+do this at a small cost in efficiency
+and flexibility. However, many compilers allow escape hatches for
+programmers to mix low-level code with high-level code.
+.I rpcgen
+is no exception. In speed-critical applications, hand-written routines
+can be linked with the
+.I rpcgen
+output without any difficulty. Also, one may proceed by using
+.I rpcgen
+output as a starting point, and then rewriting it as necessary.
+(If you need a discussion of RPC programming without
+.I rpcgen ,
+see the
+.I "Remote Procedure Call Programming Guide)\.
+.NH 1
+\&Converting Local Procedures into Remote Procedures
+.IX rpcgen "local procedures" \fIrpcgen\fP
+.IX rpcgen "remote procedures" \fIrpcgen\fP
+.LP
+Assume an application that runs on a single machine, one which we want
+to convert to run over the network. Here we will demonstrate such a
+conversion by way of a simple example\(ema program that prints a
+message to the console:
+.ie t .DS
+.el .DS L
+.ft I
+/*
+ * printmsg.c: print a message on the console
+ */
+.ft CW
+#include <stdio.h>
+
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ char *message;
+
+ if (argc < 2) {
+ fprintf(stderr, "usage: %s <message>\en", argv[0]);
+ exit(1);
+ }
+ message = argv[1];
+
+ if (!printmessage(message)) {
+ fprintf(stderr, "%s: couldn't print your message\en",
+ argv[0]);
+ exit(1);
+ }
+ printf("Message Delivered!\en");
+ exit(0);
+}
+.ft I
+/*
+ * Print a message to the console.
+ * Return a boolean indicating whether the message was actually printed.
+ */
+.ft CW
+printmessage(msg)
+ char *msg;
+{
+ FILE *f;
+
+ f = fopen("/dev/console", "w");
+ if (f == NULL) {
+ return (0);
+ }
+ fprintf(f, "%s\en", msg);
+ fclose(f);
+ return(1);
+}
+.DE
+.LP
+And then, of course:
+.ie t .DS
+.el .DS L
+.ft CW
+example% \fBcc printmsg.c -o printmsg\fP
+example% \fBprintmsg "Hello, there."\fP
+Message delivered!
+example%
+.DE
+.LP
+If
+.I printmessage()
+was turned into a remote procedure,
+then it could be called from anywhere in the network.
+Ideally, one would just like to stick a keyword like
+.I remote
+in front of a
+procedure to turn it into a remote procedure. Unfortunately,
+we have to live within the constraints of the C language, since
+it existed long before RPC did. But even without language
+support, it's not very difficult to make a procedure remote.
+.LP
+In general, it's necessary to figure out what the types are for
+all procedure inputs and outputs. In this case, we have a
+procedure
+.I printmessage()
+which takes a string as input, and returns an integer
+as output. Knowing this, we can write a protocol specification in RPC
+language that describes the remote version of
+.I printmessage ().
+Here it is:
+.ie t .DS
+.el .DS L
+.ft I
+/*
+ * msg.x: Remote message printing protocol
+ */
+.ft CW
+
+program MESSAGEPROG {
+ version MESSAGEVERS {
+ int PRINTMESSAGE(string) = 1;
+ } = 1;
+} = 99;
+.DE
+.LP
+Remote procedures are part of remote programs, so we actually declared
+an entire remote program here which contains the single procedure
+.I PRINTMESSAGE .
+This procedure was declared to be in version 1 of the
+remote program. No null procedure (procedure 0) is necessary because
+.I rpcgen
+generates it automatically.
+.LP
+Notice that everything is declared with all capital letters. This is
+not required, but is a good convention to follow.
+.LP
+Notice also that the argument type is \*Qstring\*U and not \*Qchar *\*U. This
+is because a \*Qchar *\*U in C is ambiguous. Programmers usually intend it
+to mean a null-terminated string of characters, but it could also
+represent a pointer to a single character or a pointer to an array of
+characters. In RPC language, a null-terminated string is
+unambiguously called a \*Qstring\*U.
+.LP
+There are just two more things to write. First, there is the remote
+procedure itself. Here's the definition of a remote procedure
+to implement the
+.I PRINTMESSAGE
+procedure we declared above:
+.ie t .DS
+.el .DS L
+.vs 11
+.ft I
+/*
+ * msg_proc.c: implementation of the remote procedure "printmessage"
+ */
+.ft CW
+
+#include <stdio.h>
+#include <rpc/rpc.h> /* \fIalways needed\fP */
+#include "msg.h" /* \fIneed this too: msg.h will be generated by rpcgen\fP */
+
+.ft I
+/*
+ * Remote verson of "printmessage"
+ */
+.ft CW
+int *
+printmessage_1(msg)
+ char **msg;
+{
+ static int result; /* \fImust be static!\fP */
+ FILE *f;
+
+ f = fopen("/dev/console", "w");
+ if (f == NULL) {
+ result = 0;
+ return (&result);
+ }
+ fprintf(f, "%s\en", *msg);
+ fclose(f);
+ result = 1;
+ return (&result);
+}
+.vs
+.DE
+.LP
+Notice here that the declaration of the remote procedure
+.I printmessage_1()
+differs from that of the local procedure
+.I printmessage()
+in three ways:
+.IP 1.
+It takes a pointer to a string instead of a string itself. This
+is true of all remote procedures: they always take pointers to their
+arguments rather than the arguments themselves.
+.IP 2.
+It returns a pointer to an integer instead of an integer itself. This is
+also generally true of remote procedures: they always return a pointer
+to their results.
+.IP 3.
+It has an \*Q_1\*U appended to its name. In general, all remote
+procedures called by
+.I rpcgen
+are named by the following rule: the name in the program definition
+(here
+.I PRINTMESSAGE )
+is converted to all
+lower-case letters, an underbar (\*Q_\*U) is appended to it, and
+finally the version number (here 1) is appended.
+.LP
+The last thing to do is declare the main client program that will call
+the remote procedure. Here it is:
+.ie t .DS
+.el .DS L
+.ft I
+/*
+ * rprintmsg.c: remote version of "printmsg.c"
+ */
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h> /* \fIalways needed\fP */
+#include "msg.h" /* \fIneed this too: msg.h will be generated by rpcgen\fP */
+
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ CLIENT *cl;
+ int *result;
+ char *server;
+ char *message;
+
+ if (argc < 3) {
+ fprintf(stderr, "usage: %s host message\en", argv[0]);
+ exit(1);
+ }
+
+.ft I
+ /*
+ * Save values of command line arguments
+ */
+.ft CW
+ server = argv[1];
+ message = argv[2];
+
+.ft I
+ /*
+ * Create client "handle" used for calling \fIMESSAGEPROG\fP on the
+ * server designated on the command line. We tell the RPC package
+ * to use the "tcp" protocol when contacting the server.
+ */
+.ft CW
+ cl = clnt_create(server, MESSAGEPROG, MESSAGEVERS, "tcp");
+ if (cl == NULL) {
+.ft I
+ /*
+ * Couldn't establish connection with server.
+ * Print error message and die.
+ */
+.ft CW
+ clnt_pcreateerror(server);
+ exit(1);
+ }
+
+.ft I
+ /*
+ * Call the remote procedure "printmessage" on the server
+ */
+.ft CW
+ result = printmessage_1(&message, cl);
+ if (result == NULL) {
+.ft I
+ /*
+ * An error occurred while calling the server.
+ * Print error message and die.
+ */
+.ft CW
+ clnt_perror(cl, server);
+ exit(1);
+ }
+
+.ft I
+ /*
+ * Okay, we successfully called the remote procedure.
+ */
+.ft CW
+ if (*result == 0) {
+.ft I
+ /*
+ * Server was unable to print our message.
+ * Print error message and die.
+ */
+.ft CW
+ fprintf(stderr, "%s: %s couldn't print your message\en",
+ argv[0], server);
+ exit(1);
+ }
+
+.ft I
+ /*
+ * The message got printed on the server's console
+ */
+.ft CW
+ printf("Message delivered to %s!\en", server);
+}
+.DE
+There are two things to note here:
+.IP 1.
+.IX "client handle, used by rpcgen" "" "client handle, used by \fIrpcgen\fP"
+First a client \*Qhandle\*U is created using the RPC library routine
+.I clnt_create ().
+This client handle will be passed to the stub routines
+which call the remote procedure.
+.IP 2.
+The remote procedure
+.I printmessage_1()
+is called exactly the same way as it is declared in
+.I msg_proc.c
+except for the inserted client handle as the first argument.
+.LP
+Here's how to put all of the pieces together:
+.ie t .DS
+.el .DS L
+.ft CW
+example% \fBrpcgen msg.x\fP
+example% \fBcc rprintmsg.c msg_clnt.c -o rprintmsg\fP
+example% \fBcc msg_proc.c msg_svc.c -o msg_server\fP
+.DE
+Two programs were compiled here: the client program
+.I rprintmsg
+and the server program
+.I msg_server .
+Before doing this though,
+.I rpcgen
+was used to fill in the missing pieces.
+.LP
+Here is what
+.I rpcgen
+did with the input file
+.I msg.x :
+.IP 1.
+It created a header file called
+.I msg.h
+that contained
+.I #define 's
+for
+.I MESSAGEPROG ,
+.I MESSAGEVERS
+and
+.I PRINTMESSAGE
+for use in the other modules.
+.IP 2.
+It created client \*Qstub\*U routines in the
+.I msg_clnt.c
+file. In this case there is only one, the
+.I printmessage_1()
+that was referred to from the
+.I printmsg
+client program. The name of the output file for
+client stub routines is always formed in this way: if the name of the
+input file is
+.I FOO.x ,
+the client stubs output file is called
+.I FOO_clnt.c .
+.IP 3.
+It created the server program which calls
+.I printmessage_1()
+in
+.I msg_proc.c .
+This server program is named
+.I msg_svc.c .
+The rule for naming the server output file is similar to the
+previous one: for an input file called
+.I FOO.x ,
+the output server file is named
+.I FOO_svc.c .
+.LP
+Now we're ready to have some fun. First, copy the server to a
+remote machine and run it. For this example, the
+machine is called \*Qmoon\*U. Server processes are run in the
+background, because they never exit.
+.ie t .DS
+.el .DS L
+.ft CW
+moon% \fBmsg_server &\fP
+.DE
+Then on our local machine (\*Qsun\*U) we can print a message on \*Qmoon\*Us
+console.
+.ie t .DS
+.el .DS L
+.ft CW
+sun% \fBprintmsg moon "Hello, moon."\fP
+.DE
+The message will get printed to \*Qmoon\*Us console. You can print a
+message on anybody's console (including your own) with this program if
+you are able to copy the server to their machine and run it.
+.NH 1
+\&Generating XDR Routines
+.IX RPC "generating XDR routines"
+.LP
+The previous example only demonstrated the automatic generation of
+client and server RPC code.
+.I rpcgen
+may also be used to generate XDR routines, that is, the routines
+necessary to convert local data
+structures into network format and vice-versa. This example presents
+a complete RPC service\(ema remote directory listing service, which uses
+.I rpcgen
+not only to generate stub routines, but also to generate the XDR
+routines. Here is the protocol description file:
+.ie t .DS
+.el .DS L
+.ft I
+/*
+ * dir.x: Remote directory listing protocol
+ */
+.ft CW
+const MAXNAMELEN = 255; /* \fImaximum length of a directory entry\fP */
+
+typedef string nametype<MAXNAMELEN>; /* \fIa directory entry\fP */
+
+typedef struct namenode *namelist; /* \fIa link in the listing\fP */
+
+.ft I
+/*
+ * A node in the directory listing
+ */
+.ft CW
+struct namenode {
+ nametype name; /* \fIname of directory entry\fP */
+ namelist next; /* \fInext entry\fP */
+};
+
+.ft I
+/*
+ * The result of a READDIR operation.
+ */
+.ft CW
+union readdir_res switch (int errno) {
+case 0:
+ namelist list; /* \fIno error: return directory listing\fP */
+default:
+ void; /* \fIerror occurred: nothing else to return\fP */
+};
+
+.ft I
+/*
+ * The directory program definition
+ */
+.ft CW
+program DIRPROG {
+ version DIRVERS {
+ readdir_res
+ READDIR(nametype) = 1;
+ } = 1;
+} = 76;
+.DE
+.SH
+Note:
+.I
+Types (like
+.I readdir_res
+in the example above) can be defined using
+the \*Qstruct\*U, \*Qunion\*U and \*Qenum\*U keywords, but those keywords
+should not be used in subsequent declarations of variables of those types.
+For example, if you define a union \*Qfoo\*U, you should declare using
+only \*Qfoo\*U and not \*Qunion foo\*U. In fact,
+.I rpcgen
+compiles
+RPC unions into C structures and it is an error to declare them using the
+\*Qunion\*U keyword.
+.LP
+Running
+.I rpcgen
+on
+.I dir.x
+creates four output files. Three are the same as before: header file,
+client stub routines and server skeleton. The fourth are the XDR routines
+necessary for converting the data types we declared into XDR format and
+vice-versa. These are output in the file
+.I dir_xdr.c .
+.LP
+Here is the implementation of the
+.I READDIR
+procedure.
+.ie t .DS
+.el .DS L
+.vs 11
+.ft I
+/*
+ * dir_proc.c: remote readdir implementation
+ */
+.ft CW
+#include <rpc/rpc.h>
+#include <sys/dir.h>
+#include "dir.h"
+
+extern int errno;
+extern char *malloc();
+extern char *strdup();
+
+readdir_res *
+readdir_1(dirname)
+ nametype *dirname;
+{
+ DIR *dirp;
+ struct direct *d;
+ namelist nl;
+ namelist *nlp;
+ static readdir_res res; /* \fImust be static\fP! */
+
+.ft I
+ /*
+ * Open directory
+ */
+.ft CW
+ dirp = opendir(*dirname);
+ if (dirp == NULL) {
+ res.errno = errno;
+ return (&res);
+ }
+
+.ft I
+ /*
+ * Free previous result
+ */
+.ft CW
+ xdr_free(xdr_readdir_res, &res);
+
+.ft I
+ /*
+ * Collect directory entries.
+ * Memory allocated here will be freed by \fIxdr_free\fP
+ * next time \fIreaddir_1\fP is called
+ */
+.ft CW
+ nlp = &res.readdir_res_u.list;
+ while (d = readdir(dirp)) {
+ nl = *nlp = (namenode *) malloc(sizeof(namenode));
+ nl->name = strdup(d->d_name);
+ nlp = &nl->next;
+ }
+ *nlp = NULL;
+
+.ft I
+ /*
+ * Return the result
+ */
+.ft CW
+ res.errno = 0;
+ closedir(dirp);
+ return (&res);
+}
+.vs
+.DE
+Finally, there is the client side program to call the server:
+.ie t .DS
+.el .DS L
+.ft I
+/*
+ * rls.c: Remote directory listing client
+ */
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h> /* \fIalways need this\fP */
+#include "dir.h" /* \fIwill be generated by rpcgen\fI */
+
+extern int errno;
+
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ CLIENT *cl;
+ char *server;
+ char *dir;
+ readdir_res *result;
+ namelist nl;
+
+
+ if (argc != 3) {
+ fprintf(stderr, "usage: %s host directory\en",
+ argv[0]);
+ exit(1);
+ }
+
+.ft I
+ /*
+ * Remember what our command line arguments refer to
+ */
+.ft CW
+ server = argv[1];
+ dir = argv[2];
+
+.ft I
+ /*
+ * Create client "handle" used for calling \fIMESSAGEPROG\fP on the
+ * server designated on the command line. We tell the RPC package
+ * to use the "tcp" protocol when contacting the server.
+ */
+.ft CW
+ cl = clnt_create(server, DIRPROG, DIRVERS, "tcp");
+ if (cl == NULL) {
+.ft I
+ /*
+ * Couldn't establish connection with server.
+ * Print error message and die.
+ */
+.ft CW
+ clnt_pcreateerror(server);
+ exit(1);
+ }
+
+.ft I
+ /*
+ * Call the remote procedure \fIreaddir\fP on the server
+ */
+.ft CW
+ result = readdir_1(&dir, cl);
+ if (result == NULL) {
+.ft I
+ /*
+ * An error occurred while calling the server.
+ * Print error message and die.
+ */
+.ft CW
+ clnt_perror(cl, server);
+ exit(1);
+ }
+
+.ft I
+ /*
+ * Okay, we successfully called the remote procedure.
+ */
+.ft CW
+ if (result->errno != 0) {
+.ft I
+ /*
+ * A remote system error occurred.
+ * Print error message and die.
+ */
+.ft CW
+ errno = result->errno;
+ perror(dir);
+ exit(1);
+ }
+
+.ft I
+ /*
+ * Successfully got a directory listing.
+ * Print it out.
+ */
+.ft CW
+ for (nl = result->readdir_res_u.list; nl != NULL;
+ nl = nl->next) {
+ printf("%s\en", nl->name);
+ }
+ exit(0);
+}
+.DE
+Compile everything, and run.
+.DS
+.ft CW
+sun% \fBrpcgen dir.x\fP
+sun% \fBcc rls.c dir_clnt.c dir_xdr.c -o rls\fP
+sun% \fBcc dir_svc.c dir_proc.c dir_xdr.c -o dir_svc\fP
+
+sun% \fBdir_svc &\fP
+
+moon% \fBrls sun /usr/pub\fP
+\&.
+\&..
+ascii
+eqnchar
+greek
+kbd
+marg8
+tabclr
+tabs
+tabs4
+moon%
+.DE
+.LP
+.IX "debugging with rpcgen" "" "debugging with \fIrpcgen\fP"
+A final note about
+.I rpcgen :
+The client program and the server procedure can be tested together
+as a single program by simply linking them with each other rather
+than with the client and server stubs. The procedure calls will be
+executed as ordinary local procedure calls and the program can be
+debugged with a local debugger such as
+.I dbx .
+When the program is working, the client program can be linked to
+the client stub produced by
+.I rpcgen
+and the server procedures can be linked to the server stub produced
+by
+.I rpcgen .
+.SH
+.I NOTE :
+\fIIf you do this, you may want to comment out calls to RPC library
+routines, and have client-side routines call server routines
+directly.\fP
+.LP
+.NH 1
+\&The C-Preprocessor
+.IX rpcgen "C-preprocessor" \fIrpcgen\fP
+.LP
+The C-preprocessor is run on all input files before they are
+compiled, so all the preprocessor directives are legal within a \*Q.x\*U
+file. Four symbols may be defined, depending upon which output file is
+getting generated. The symbols are:
+.TS
+box tab (&);
+lfI lfI
+lfL l .
+Symbol&Usage
+_
+RPC_HDR&for header-file output
+RPC_XDR&for XDR routine output
+RPC_SVC&for server-skeleton output
+RPC_CLNT&for client stub output
+.TE
+.LP
+Also,
+.I rpcgen
+does a little preprocessing of its own. Any line that
+begins with a percent sign is passed directly into the output file,
+without any interpretation of the line. Here is a simple example that
+demonstrates the preprocessing features.
+.ie t .DS
+.el .DS L
+.ft I
+/*
+ * time.x: Remote time protocol
+ */
+.ft CW
+program TIMEPROG {
+ version TIMEVERS {
+ unsigned int TIMEGET(void) = 1;
+ } = 1;
+} = 44;
+
+#ifdef RPC_SVC
+%int *
+%timeget_1()
+%{
+% static int thetime;
+%
+% thetime = time(0);
+% return (&thetime);
+%}
+#endif
+.DE
+The '%' feature is not generally recommended, as there is no guarantee
+that the compiler will stick the output where you intended.
+.NH 1
+\&\fBrpcgen\fP Programming Notes
+.IX rpcgen "other operations" \fIrpcgen\fP
+.sp
+.NH 2
+\&Timeout Changes
+.IX rpcgen "timeout changes" \fIrpcgen\fP
+.LP
+RPC sets a default timeout of 25 seconds for RPC calls when
+.I clnt_create()
+is used. This timeout may be changed using
+.I clnt_control()
+Here is a small code fragment to demonstrate use of
+.I clnt_control ():
+.ID
+struct timeval tv;
+CLIENT *cl;
+.sp .5
+cl = clnt_create("somehost", SOMEPROG, SOMEVERS, "tcp");
+if (cl == NULL) {
+ exit(1);
+}
+tv.tv_sec = 60; /* \fIchange timeout to 1 minute\fP */
+tv.tv_usec = 0;
+clnt_control(cl, CLSET_TIMEOUT, &tv);
+.DE
+.NH 2
+\&Handling Broadcast on the Server Side
+.IX "broadcast RPC"
+.IX rpcgen "broadcast RPC" \fIrpcgen\fP
+.LP
+When a procedure is known to be called via broadcast RPC,
+it is usually wise for the server to not reply unless it can provide
+some useful information to the client. This prevents the network
+from getting flooded by useless replies.
+.LP
+To prevent the server from replying, a remote procedure can
+return NULL as its result, and the server code generated by
+.I rpcgen
+will detect this and not send out a reply.
+.LP
+Here is an example of a procedure that replies only if it
+thinks it is an NFS server:
+.ID
+void *
+reply_if_nfsserver()
+{
+ char notnull; /* \fIjust here so we can use its address\fP */
+.sp .5
+ if (access("/etc/exports", F_OK) < 0) {
+ return (NULL); /* \fIprevent RPC from replying\fP */
+ }
+.ft I
+ /*
+ * return non-null pointer so RPC will send out a reply
+ */
+.ft L
+ return ((void *)&notnull);
+}
+.DE
+Note that if procedure returns type \*Qvoid *\*U, they must return a non-NULL
+pointer if they want RPC to reply for them.
+.NH 2
+\&Other Information Passed to Server Procedures
+.LP
+Server procedures will often want to know more about an RPC call
+than just its arguments. For example, getting authentication information
+is important to procedures that want to implement some level of security.
+This extra information is actually supplied to the server procedure as a
+second argument. Here is an example to demonstrate its use. What we've
+done here is rewrite the previous
+.I printmessage_1()
+procedure to only allow root users to print a message to the console.
+.ID
+int *
+printmessage_1(msg, rq)
+ char **msg;
+ struct svc_req *rq;
+{
+ static in result; /* \fIMust be static\fP */
+ FILE *f;
+ struct suthunix_parms *aup;
+.sp .5
+ aup = (struct authunix_parms *)rq->rq_clntcred;
+ if (aup->aup_uid != 0) {
+ result = 0;
+ return (&result);
+ }
+.sp
+.ft I
+ /*
+ * Same code as before.
+ */
+.ft L
+}
+.DE
+.NH 1
+\&RPC Language
+.IX RPCL
+.IX rpcgen "RPC Language" \fIrpcgen\fP
+.LP
+RPC language is an extension of XDR language. The sole extension is
+the addition of the
+.I program
+type. For a complete description of the XDR language syntax, see the
+.I "External Data Representation Standard: Protocol Specification"
+chapter. For a description of the RPC extensions to the XDR language,
+see the
+.I "Remote Procedure Calls: Protocol Specification"
+chapter.
+.LP
+However, XDR language is so close to C that if you know C, you know most
+of it already. We describe here the syntax of the RPC language,
+showing a few examples along the way. We also show how the various
+RPC and XDR type definitions get compiled into C type definitions in
+the output header file.
+.KS
+.NH 2
+Definitions
+\&
+.IX rpcgen definitions \fIrpcgen\fP
+.LP
+An RPC language file consists of a series of definitions.
+.DS L
+.ft CW
+ definition-list:
+ definition ";"
+ definition ";" definition-list
+.DE
+.KE
+It recognizes five types of definitions.
+.DS L
+.ft CW
+ definition:
+ enum-definition
+ struct-definition
+ union-definition
+ typedef-definition
+ const-definition
+ program-definition
+.DE
+.NH 2
+Structures
+\&
+.IX rpcgen structures \fIrpcgen\fP
+.LP
+An XDR struct is declared almost exactly like its C counterpart. It
+looks like the following:
+.DS L
+.ft CW
+ struct-definition:
+ "struct" struct-ident "{"
+ declaration-list
+ "}"
+
+ declaration-list:
+ declaration ";"
+ declaration ";" declaration-list
+.DE
+As an example, here is an XDR structure to a two-dimensional
+coordinate, and the C structure that it gets compiled into in the
+output header file.
+.DS
+.ft CW
+ struct coord { struct coord {
+ int x; --> int x;
+ int y; int y;
+ }; };
+ typedef struct coord coord;
+.DE
+The output is identical to the input, except for the added
+.I typedef
+at the end of the output. This allows one to use \*Qcoord\*U instead of
+\*Qstruct coord\*U when declaring items.
+.NH 2
+Unions
+\&
+.IX rpcgen unions \fIrpcgen\fP
+.LP
+XDR unions are discriminated unions, and look quite different from C
+unions. They are more analogous to Pascal variant records than they
+are to C unions.
+.DS L
+.ft CW
+ union-definition:
+ "union" union-ident "switch" "(" declaration ")" "{"
+ case-list
+ "}"
+
+ case-list:
+ "case" value ":" declaration ";"
+ "default" ":" declaration ";"
+ "case" value ":" declaration ";" case-list
+.DE
+Here is an example of a type that might be returned as the result of a
+\*Qread data\*U operation. If there is no error, return a block of data.
+Otherwise, don't return anything.
+.DS L
+.ft CW
+ union read_result switch (int errno) {
+ case 0:
+ opaque data[1024];
+ default:
+ void;
+ };
+.DE
+It gets compiled into the following:
+.DS L
+.ft CW
+ struct read_result {
+ int errno;
+ union {
+ char data[1024];
+ } read_result_u;
+ };
+ typedef struct read_result read_result;
+.DE
+Notice that the union component of the output struct has the name as
+the type name, except for the trailing \*Q_u\*U.
+.NH 2
+Enumerations
+\&
+.IX rpcgen enumerations \fIrpcgen\fP
+.LP
+XDR enumerations have the same syntax as C enumerations.
+.DS L
+.ft CW
+ enum-definition:
+ "enum" enum-ident "{"
+ enum-value-list
+ "}"
+
+ enum-value-list:
+ enum-value
+ enum-value "," enum-value-list
+
+ enum-value:
+ enum-value-ident
+ enum-value-ident "=" value
+.DE
+Here is a short example of an XDR enum, and the C enum that it gets
+compiled into.
+.DS L
+.ft CW
+ enum colortype { enum colortype {
+ RED = 0, RED = 0,
+ GREEN = 1, --> GREEN = 1,
+ BLUE = 2 BLUE = 2,
+ }; };
+ typedef enum colortype colortype;
+.DE
+.NH 2
+Typedef
+\&
+.IX rpcgen typedef \fIrpcgen\fP
+.LP
+XDR typedefs have the same syntax as C typedefs.
+.DS L
+.ft CW
+ typedef-definition:
+ "typedef" declaration
+.DE
+Here is an example that defines a
+.I fname_type
+used for declaring
+file name strings that have a maximum length of 255 characters.
+.DS L
+.ft CW
+typedef string fname_type<255>; --> typedef char *fname_type;
+.DE
+.NH 2
+Constants
+\&
+.IX rpcgen constants \fIrpcgen\fP
+.LP
+XDR constants symbolic constants that may be used wherever a
+integer constant is used, for example, in array size specifications.
+.DS L
+.ft CW
+ const-definition:
+ "const" const-ident "=" integer
+.DE
+For example, the following defines a constant
+.I DOZEN
+equal to 12.
+.DS L
+.ft CW
+ const DOZEN = 12; --> #define DOZEN 12
+.DE
+.NH 2
+Programs
+\&
+.IX rpcgen programs \fIrpcgen\fP
+.LP
+RPC programs are declared using the following syntax:
+.DS L
+.ft CW
+ program-definition:
+ "program" program-ident "{"
+ version-list
+ "}" "=" value
+
+ version-list:
+ version ";"
+ version ";" version-list
+
+ version:
+ "version" version-ident "{"
+ procedure-list
+ "}" "=" value
+
+ procedure-list:
+ procedure ";"
+ procedure ";" procedure-list
+
+ procedure:
+ type-ident procedure-ident "(" type-ident ")" "=" value
+.DE
+For example, here is the time protocol, revisited:
+.ie t .DS
+.el .DS L
+.ft I
+/*
+ * time.x: Get or set the time. Time is represented as number of seconds
+ * since 0:00, January 1, 1970.
+ */
+.ft CW
+program TIMEPROG {
+ version TIMEVERS {
+ unsigned int TIMEGET(void) = 1;
+ void TIMESET(unsigned) = 2;
+ } = 1;
+} = 44;
+.DE
+This file compiles into #defines in the output header file:
+.ie t .DS
+.el .DS L
+.ft CW
+#define TIMEPROG 44
+#define TIMEVERS 1
+#define TIMEGET 1
+#define TIMESET 2
+.DE
+.NH 2
+Declarations
+\&
+.IX rpcgen declarations \fIrpcgen\fP
+.LP
+In XDR, there are only four kinds of declarations.
+.DS L
+.ft CW
+ declaration:
+ simple-declaration
+ fixed-array-declaration
+ variable-array-declaration
+ pointer-declaration
+.DE
+\fB1) Simple declarations\fP are just like simple C declarations.
+.DS L
+.ft CW
+ simple-declaration:
+ type-ident variable-ident
+.DE
+Example:
+.DS L
+.ft CW
+ colortype color; --> colortype color;
+.DE
+\fB2) Fixed-length Array Declarations\fP are just like C array declarations:
+.DS L
+.ft CW
+ fixed-array-declaration:
+ type-ident variable-ident "[" value "]"
+.DE
+Example:
+.DS L
+.ft CW
+ colortype palette[8]; --> colortype palette[8];
+.DE
+\fB3) Variable-Length Array Declarations\fP have no explicit syntax
+in C, so XDR invents its own using angle-brackets.
+.DS L
+.ft CW
+variable-array-declaration:
+ type-ident variable-ident "<" value ">"
+ type-ident variable-ident "<" ">"
+.DE
+The maximum size is specified between the angle brackets. The size may
+be omitted, indicating that the array may be of any size.
+.DS L
+.ft CW
+ int heights<12>; /* \fIat most 12 items\fP */
+ int widths<>; /* \fIany number of items\fP */
+.DE
+Since variable-length arrays have no explicit syntax in C, these
+declarations are actually compiled into \*Qstruct\*Us. For example, the
+\*Qheights\*U declaration gets compiled into the following struct:
+.DS L
+.ft CW
+ struct {
+ u_int heights_len; /* \fI# of items in array\fP */
+ int *heights_val; /* \fIpointer to array\fP */
+ } heights;
+.DE
+Note that the number of items in the array is stored in the \*Q_len\*U
+component and the pointer to the array is stored in the \*Q_val\*U
+component. The first part of each of these component's names is the
+same as the name of the declared XDR variable.
+.LP
+\fB4) Pointer Declarations\fP are made in
+XDR exactly as they are in C. You can't
+really send pointers over the network, but you can use XDR pointers
+for sending recursive data types such as lists and trees. The type is
+actually called \*Qoptional-data\*U, not \*Qpointer\*U, in XDR language.
+.DS L
+.ft CW
+ pointer-declaration:
+ type-ident "*" variable-ident
+.DE
+Example:
+.DS L
+.ft CW
+ listitem *next; --> listitem *next;
+.DE
+.NH 2
+\&Special Cases
+.IX rpcgen "special cases" \fIrpcgen\fP
+.LP
+There are a few exceptions to the rules described above.
+.LP
+.B Booleans:
+C has no built-in boolean type. However, the RPC library does a
+boolean type called
+.I bool_t
+that is either
+.I TRUE
+or
+.I FALSE .
+Things declared as type
+.I bool
+in XDR language are compiled into
+.I bool_t
+in the output header file.
+.LP
+Example:
+.DS L
+.ft CW
+ bool married; --> bool_t married;
+.DE
+.B Strings:
+C has no built-in string type, but instead uses the null-terminated
+\*Qchar *\*U convention. In XDR language, strings are declared using the
+\*Qstring\*U keyword, and compiled into \*Qchar *\*Us in the output header
+file. The maximum size contained in the angle brackets specifies the
+maximum number of characters allowed in the strings (not counting the
+.I NULL
+character). The maximum size may be left off, indicating a string
+of arbitrary length.
+.LP
+Examples:
+.DS L
+.ft CW
+ string name<32>; --> char *name;
+ string longname<>; --> char *longname;
+.DE
+.B "Opaque Data:"
+Opaque data is used in RPC and XDR to describe untyped data, that is,
+just sequences of arbitrary bytes. It may be declared either as a
+fixed or variable length array.
+.DS L
+Examples:
+.ft CW
+ opaque diskblock[512]; --> char diskblock[512];
+
+ opaque filedata<1024>; --> struct {
+ u_int filedata_len;
+ char *filedata_val;
+ } filedata;
+.DE
+.B Voids:
+In a void declaration, the variable is not named. The declaration is
+just \*Qvoid\*U and nothing else. Void declarations can only occur in two
+places: union definitions and program definitions (as the argument or
+result of a remote procedure).
diff --git a/cpukit/librpc/src/rpc/PSD.doc/xdr.nts.ms b/cpukit/librpc/src/rpc/PSD.doc/xdr.nts.ms
new file mode 100644
index 0000000000..6c2d482dea
--- /dev/null
+++ b/cpukit/librpc/src/rpc/PSD.doc/xdr.nts.ms
@@ -0,0 +1,1966 @@
+.\"
+.\" Must use -- eqn -- with this one
+.\"
+.\" @(#)xdr.nts.ms 2.2 88/08/05 4.0 RPCSRC
+.EQ
+delim $$
+.EN
+.de BT
+.if \\n%=1 .tl ''- % -''
+..
+.ND
+.\" prevent excess underlining in nroff
+.if n .fp 2 R
+.OH 'External Data Representation: Sun Technical Notes''Page %'
+.EH 'Page %''External Data Representation: Sun Technical Notes'
+.if \\n%=1 .bp
+.SH
+\&External Data Representation: Sun Technical Notes
+.IX XDR "Sun technical notes"
+.LP
+This chapter contains technical notes on Sun's implementation of the
+External Data Representation (XDR) standard, a set of library routines
+that allow a C programmer to describe arbitrary data structures in a
+machinex-independent fashion.
+For a formal specification of the XDR
+standard, see the
+.I "External Data Representation Standard: Protocol Specification".
+XDR is the backbone of Sun's Remote Procedure Call package, in the
+sense that data for remote procedure calls is transmitted using the
+standard. XDR library routines should be used to transmit data
+that is accessed (read or written) by more than one type of machine.\**
+.FS
+.IX XDR "system routines"
+For a compete specification of the system External Data Representation
+routines, see the
+.I xdr(3N)
+manual page.
+.FE
+.LP
+This chapter contains a short tutorial overview of the XDR library
+routines, a guide to accessing currently available XDR streams, and
+information on defining new streams and data types. XDR was designed
+to work across different languages, operating systems, and machine
+architectures. Most users (particularly RPC users) will only need
+the information in the
+.I "Number Filters",
+.I "Floating Point Filters",
+and
+.I "Enumeration Filters"
+sections.
+Programmers wishing to implement RPC and XDR on new machines
+will be interested in the rest of the chapter, as well as the
+.I "External Data Representaiton Standard: Protocol Specification",
+which will be their primary reference.
+.SH
+Note:
+.I
+.I rpcgen
+can be used to write XDR routines even in cases where no RPC calls are
+being made.
+.LP
+On Sun systems,
+C programs that want to use XDR routines
+must include the file
+.I <rpc/rpc.h> ,
+which contains all the necessary interfaces to the XDR system.
+Since the C library
+.I libc.a
+contains all the XDR routines,
+compile as normal.
+.DS
+example% \fBcc\0\fIprogram\fP.c\fI
+.DE
+.ne 3i
+.NH 0
+\&Justification
+.IX XDR justification
+.LP
+Consider the following two programs,
+.I writer :
+.ie t .DS
+.el .DS L
+.ft CW
+#include <stdio.h>
+.sp.5
+main() /* \fIwriter.c\fP */
+{
+ long i;
+.sp.5
+ for (i = 0; i < 8; i++) {
+ if (fwrite((char *)&i, sizeof(i), 1, stdout) != 1) {
+ fprintf(stderr, "failed!\en");
+ exit(1);
+ }
+ }
+ exit(0);
+}
+.DE
+and
+.I reader :
+.ie t .DS
+.el .DS L
+.ft CW
+#include <stdio.h>
+.sp.5
+main() /* \fIreader.c\fP */
+{
+ long i, j;
+.sp.5
+ for (j = 0; j < 8; j++) {
+ if (fread((char *)&i, sizeof (i), 1, stdin) != 1) {
+ fprintf(stderr, "failed!\en");
+ exit(1);
+ }
+ printf("%ld ", i);
+ }
+ printf("\en");
+ exit(0);
+}
+.DE
+The two programs appear to be portable, because (a) they pass
+.I lint
+checking, and (b) they exhibit the same behavior when executed
+on two different hardware architectures, a Sun and a VAX.
+.LP
+Piping the output of the
+.I writer
+program to the
+.I reader
+program gives identical results on a Sun or a VAX.
+.DS
+.ft CW
+sun% \fBwriter | reader\fP
+0 1 2 3 4 5 6 7
+sun%
+
+
+vax% \fBwriter | reader\fP
+0 1 2 3 4 5 6 7
+vax%
+.DE
+With the advent of local area networks and 4.2BSD came the concept
+of \*Qnetwork pipes\*U \(em a process produces data on one machine,
+and a second process consumes data on another machine.
+A network pipe can be constructed with
+.I writer
+and
+.I reader .
+Here are the results if the first produces data on a Sun,
+and the second consumes data on a VAX.
+.DS
+.ft CW
+sun% \fBwriter | rsh vax reader\fP
+0 16777216 33554432 50331648 67108864 83886080 100663296
+117440512
+sun%
+.DE
+Identical results can be obtained by executing
+.I writer
+on the VAX and
+.I reader
+on the Sun. These results occur because the byte ordering
+of long integers differs between the VAX and the Sun,
+even though word size is the same.
+Note that $16777216$ is $2 sup 24$ \(em
+when four bytes are reversed, the 1 winds up in the 24th bit.
+.LP
+Whenever data is shared by two or more machine types, there is
+a need for portable data. Programs can be made data-portable by
+replacing the
+.I read()
+and
+.I write()
+calls with calls to an XDR library routine
+.I xdr_long() ,
+a filter that knows the standard representation
+of a long integer in its external form.
+Here are the revised versions of
+.I writer :
+.ie t .DS
+.el .DS L
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h> /* \fIxdr is a sub-library of rpc\fP */
+.sp.5
+main() /* \fIwriter.c\fP */
+{
+ XDR xdrs;
+ long i;
+.sp.5
+ xdrstdio_create(&xdrs, stdout, XDR_ENCODE);
+ for (i = 0; i < 8; i++) {
+ if (!xdr_long(&xdrs, &i)) {
+ fprintf(stderr, "failed!\en");
+ exit(1);
+ }
+ }
+ exit(0);
+}
+.DE
+and
+.I reader :
+.ie t .DS
+.el .DS L
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h> /* \fIxdr is a sub-library of rpc\fP */
+.sp.5
+main() /* \fIreader.c\fP */
+{
+ XDR xdrs;
+ long i, j;
+.sp.5
+ xdrstdio_create(&xdrs, stdin, XDR_DECODE);
+ for (j = 0; j < 8; j++) {
+ if (!xdr_long(&xdrs, &i)) {
+ fprintf(stderr, "failed!\en");
+ exit(1);
+ }
+ printf("%ld ", i);
+ }
+ printf("\en");
+ exit(0);
+}
+.DE
+The new programs were executed on a Sun,
+on a VAX, and from a Sun to a VAX;
+the results are shown below.
+.DS
+.ft CW
+sun% \fBwriter | reader\fP
+0 1 2 3 4 5 6 7
+sun%
+
+vax% \fBwriter | reader\fP
+0 1 2 3 4 5 6 7
+vax%
+
+sun% \fBwriter | rsh vax reader\fP
+0 1 2 3 4 5 6 7
+sun%
+.DE
+.SH
+Note:
+.I
+.IX XDR "portable data"
+Integers are just the tip of the portable-data iceberg. Arbitrary
+data structures present portability problems, particularly with
+respect to alignment and pointers. Alignment on word boundaries
+may cause the size of a structure to vary from machine to machine.
+And pointers, which are very convenient to use, have no meaning
+outside the machine where they are defined.
+.LP
+.NH 1
+\&A Canonical Standard
+.IX XDR "canonical standard"
+.LP
+XDR's approach to standardizing data representations is
+.I canonical .
+That is, XDR defines a single byte order (Big Endian), a single
+floating-point representation (IEEE), and so on. Any program running on
+any machine can use XDR to create portable data by translating its
+local representation to the XDR standard representations; similarly, any
+program running on any machine can read portable data by translating the
+XDR standard representaions to its local equivalents. The single standard
+completely decouples programs that create or send portable data from those
+that use or receive portable data. The advent of a new machine or a new
+language has no effect upon the community of existing portable data creators
+and users. A new machine joins this community by being \*Qtaught\*U how to
+convert the standard representations and its local representations; the
+local representations of other machines are irrelevant. Conversely, to
+existing programs running on other machines, the local representations of
+the new machine are also irrelevant; such programs can immediately read
+portable data produced by the new machine because such data conforms to the
+canonical standards that they already understand.
+.LP
+There are strong precedents for XDR's canonical approach. For example,
+TCP/IP, UDP/IP, XNS, Ethernet, and, indeed, all protocols below layer five
+of the ISO model, are canonical protocols. The advantage of any canonical
+approach is simplicity; in the case of XDR, a single set of conversion
+routines is written once and is never touched again. The canonical approach
+has a disadvantage, but it is unimportant in real-world data transfer
+applications. Suppose two Little-Endian machines are transferring integers
+according to the XDR standard. The sending machine converts the integers
+from Little-Endian byte order to XDR (Big-Endian) byte order; the receiving
+machine performs the reverse conversion. Because both machines observe the
+same byte order, their conversions are unnecessary. The point, however, is
+not necessity, but cost as compared to the alternative.
+.LP
+The time spent converting to and from a canonical representation is
+insignificant, especially in networking applications. Most of the time
+required to prepare a data structure for transfer is not spent in conversion
+but in traversing the elements of the data structure. To transmit a tree,
+for example, each leaf must be visited and each element in a leaf record must
+be copied to a buffer and aligned there; storage for the leaf may have to be
+deallocated as well. Similarly, to receive a tree, storage must be
+allocated for each leaf, data must be moved from the buffer to the leaf and
+properly aligned, and pointers must be constructed to link the leaves
+together. Every machine pays the cost of traversing and copying data
+structures whether or not conversion is required. In networking
+applications, communications overhead\(emthe time required to move the data
+down through the sender's protocol layers, across the network and up through
+the receiver's protocol layers\(emdwarfs conversion overhead.
+.NH 1
+\&The XDR Library
+.IX "XDR" "library"
+.LP
+The XDR library not only solves data portability problems, it also
+allows you to write and read arbitrary C constructs in a consistent,
+specified, well-documented manner. Thus, it can make sense to use the
+library even when the data is not shared among machines on a network.
+.LP
+The XDR library has filter routines for
+strings (null-terminated arrays of bytes),
+structures, unions, and arrays, to name a few.
+Using more primitive routines,
+you can write your own specific XDR routines
+to describe arbitrary data structures,
+including elements of arrays, arms of unions,
+or objects pointed at from other structures.
+The structures themselves may contain arrays of arbitrary elements,
+or pointers to other structures.
+.LP
+Let's examine the two programs more closely.
+There is a family of XDR stream creation routines
+in which each member treats the stream of bits differently.
+In our example, data is manipulated using standard I/O routines,
+so we use
+.I xdrstdio_create ().
+.IX xdrstdio_create() "" "\fIxdrstdio_create()\fP"
+The parameters to XDR stream creation routines
+vary according to their function.
+In our example,
+.I xdrstdio_create()
+takes a pointer to an XDR structure that it initializes,
+a pointer to a
+.I FILE
+that the input or output is performed on, and the operation.
+The operation may be
+.I XDR_ENCODE
+for serializing in the
+.I writer
+program, or
+.I XDR_DECODE
+for deserializing in the
+.I reader
+program.
+.LP
+Note: RPC users never need to create XDR streams;
+the RPC system itself creates these streams,
+which are then passed to the users.
+.LP
+The
+.I xdr_long()
+.IX xdr_long() "" "\fIxdr_long()\fP"
+primitive is characteristic of most XDR library
+primitives and all client XDR routines.
+First, the routine returns
+.I FALSE
+(0) if it fails, and
+.I TRUE
+(1) if it succeeds.
+Second, for each data type,
+.I xxx ,
+there is an associated XDR routine of the form:
+.DS
+.ft CW
+xdr_xxx(xdrs, xp)
+ XDR *xdrs;
+ xxx *xp;
+{
+}
+.DE
+In our case,
+.I xxx
+is long, and the corresponding XDR routine is
+a primitive,
+.I xdr_long() .
+The client could also define an arbitrary structure
+.I xxx
+in which case the client would also supply the routine
+.I xdr_xxx (),
+describing each field by calling XDR routines
+of the appropriate type.
+In all cases the first parameter,
+.I xdrs
+can be treated as an opaque handle,
+and passed to the primitive routines.
+.LP
+XDR routines are direction independent;
+that is, the same routines are called to serialize or deserialize data.
+This feature is critical to software engineering of portable data.
+The idea is to call the same routine for either operation \(em
+this almost guarantees that serialized data can also be deserialized.
+One routine is used by both producer and consumer of networked data.
+This is implemented by always passing the address
+of an object rather than the object itself \(em
+only in the case of deserialization is the object modified.
+This feature is not shown in our trivial example,
+but its value becomes obvious when nontrivial data structures
+are passed among machines.
+If needed, the user can obtain the
+direction of the XDR operation.
+See the
+.I "XDR Operation Directions"
+section below for details.
+.LP
+Let's look at a slightly more complicated example.
+Assume that a person's gross assets and liabilities
+are to be exchanged among processes.
+Also assume that these values are important enough
+to warrant their own data type:
+.ie t .DS
+.el .DS L
+.ft CW
+struct gnumbers {
+ long g_assets;
+ long g_liabilities;
+};
+.DE
+The corresponding XDR routine describing this structure would be:
+.ie t .DS
+.el .DS L
+.ft CW
+bool_t /* \fITRUE is success, FALSE is failure\fP */
+xdr_gnumbers(xdrs, gp)
+ XDR *xdrs;
+ struct gnumbers *gp;
+{
+ if (xdr_long(xdrs, &gp->g_assets) &&
+ xdr_long(xdrs, &gp->g_liabilities))
+ return(TRUE);
+ return(FALSE);
+}
+.DE
+Note that the parameter
+.I xdrs
+is never inspected or modified;
+it is only passed on to the subcomponent routines.
+It is imperative to inspect the return value of each XDR routine call,
+and to give up immediately and return
+.I FALSE
+if the subroutine fails.
+.LP
+This example also shows that the type
+.I bool_t
+is declared as an integer whose only values are
+.I TRUE
+(1) and
+.I FALSE
+(0). This document uses the following definitions:
+.ie t .DS
+.el .DS L
+.ft CW
+#define bool_t int
+#define TRUE 1
+#define FALSE 0
+.DE
+.LP
+Keeping these conventions in mind,
+.I xdr_gnumbers()
+can be rewritten as follows:
+.ie t .DS
+.el .DS L
+.ft CW
+xdr_gnumbers(xdrs, gp)
+ XDR *xdrs;
+ struct gnumbers *gp;
+{
+ return(xdr_long(xdrs, &gp->g_assets) &&
+ xdr_long(xdrs, &gp->g_liabilities));
+}
+.DE
+This document uses both coding styles.
+.NH 1
+\&XDR Library Primitives
+.IX "library primitives for XDR"
+.IX XDR "library primitives"
+.LP
+This section gives a synopsis of each XDR primitive.
+It starts with basic data types and moves on to constructed data types.
+Finally, XDR utilities are discussed.
+The interface to these primitives
+and utilities is defined in the include file
+.I <rpc/xdr.h> ,
+automatically included by
+.I <rpc/rpc.h> .
+.NH 2
+\&Number Filters
+.IX "XDR library" "number filters"
+.LP
+The XDR library provides primitives to translate between numbers
+and their corresponding external representations.
+Primitives cover the set of numbers in:
+.DS
+.ft CW
+[signed, unsigned] * [short, int, long]
+.DE
+.ne 2i
+Specifically, the eight primitives are:
+.DS
+.ft CW
+bool_t xdr_char(xdrs, cp)
+ XDR *xdrs;
+ char *cp;
+.sp.5
+bool_t xdr_u_char(xdrs, ucp)
+ XDR *xdrs;
+ unsigned char *ucp;
+.sp.5
+bool_t xdr_int(xdrs, ip)
+ XDR *xdrs;
+ int *ip;
+.sp.5
+bool_t xdr_u_int(xdrs, up)
+ XDR *xdrs;
+ unsigned *up;
+.sp.5
+bool_t xdr_long(xdrs, lip)
+ XDR *xdrs;
+ long *lip;
+.sp.5
+bool_t xdr_u_long(xdrs, lup)
+ XDR *xdrs;
+ u_long *lup;
+.sp.5
+bool_t xdr_short(xdrs, sip)
+ XDR *xdrs;
+ short *sip;
+.sp.5
+bool_t xdr_u_short(xdrs, sup)
+ XDR *xdrs;
+ u_short *sup;
+.DE
+The first parameter,
+.I xdrs ,
+is an XDR stream handle.
+The second parameter is the address of the number
+that provides data to the stream or receives data from it.
+All routines return
+.I TRUE
+if they complete successfully, and
+.I FALSE
+otherwise.
+.NH 2
+\&Floating Point Filters
+.IX "XDR library" "floating point filters"
+.LP
+The XDR library also provides primitive routines
+for C's floating point types:
+.DS
+.ft CW
+bool_t xdr_float(xdrs, fp)
+ XDR *xdrs;
+ float *fp;
+.sp.5
+bool_t xdr_double(xdrs, dp)
+ XDR *xdrs;
+ double *dp;
+.DE
+The first parameter,
+.I xdrs
+is an XDR stream handle.
+The second parameter is the address
+of the floating point number that provides data to the stream
+or receives data from it.
+Both routines return
+.I TRUE
+if they complete successfully, and
+.I FALSE
+otherwise.
+.LP
+Note: Since the numbers are represented in IEEE floating point,
+routines may fail when decoding a valid IEEE representation
+into a machine-specific representation, or vice-versa.
+.NH 2
+\&Enumeration Filters
+.IX "XDR library" "enumeration filters"
+.LP
+The XDR library provides a primitive for generic enumerations.
+The primitive assumes that a C
+.I enum
+has the same representation inside the machine as a C integer.
+The boolean type is an important instance of the
+.I enum .
+The external representation of a boolean is always
+.I TRUE
+(1) or
+.I FALSE
+(0).
+.DS
+.ft CW
+#define bool_t int
+#define FALSE 0
+#define TRUE 1
+.sp.5
+#define enum_t int
+.sp.5
+bool_t xdr_enum(xdrs, ep)
+ XDR *xdrs;
+ enum_t *ep;
+.sp.5
+bool_t xdr_bool(xdrs, bp)
+ XDR *xdrs;
+ bool_t *bp;
+.DE
+The second parameters
+.I ep
+and
+.I bp
+are addresses of the associated type that provides data to, or
+receives data from, the stream
+.I xdrs .
+.NH 2
+\&No Data
+.IX "XDR library" "no data"
+.LP
+Occasionally, an XDR routine must be supplied to the RPC system,
+even when no data is passed or required.
+The library provides such a routine:
+.DS
+.ft CW
+bool_t xdr_void(); /* \fIalways returns TRUE\fP */
+.DE
+.NH 2
+\&Constructed Data Type Filters
+.IX "XDR library" "constructed data type filters"
+.LP
+Constructed or compound data type primitives
+require more parameters and perform more complicated functions
+then the primitives discussed above.
+This section includes primitives for
+strings, arrays, unions, and pointers to structures.
+.LP
+Constructed data type primitives may use memory management.
+In many cases, memory is allocated when deserializing data with
+.I XDR_DECODE
+Therefore, the XDR package must provide means to deallocate memory.
+This is done by an XDR operation,
+.I XDR_FREE
+To review, the three XDR directional operations are
+.I XDR_ENCODE ,
+.I XDR_DECODE
+and
+.I XDR_FREE .
+.NH 3
+\&Strings
+.IX "XDR library" "strings"
+.LP
+In C, a string is defined as a sequence of bytes
+terminated by a null byte,
+which is not considered when calculating string length.
+However, when a string is passed or manipulated,
+a pointer to it is employed.
+Therefore, the XDR library defines a string to be a
+.I "char *"
+and not a sequence of characters.
+The external representation of a string is drastically different
+from its internal representation.
+Externally, strings are represented as
+sequences of ASCII characters,
+while internally, they are represented with character pointers.
+Conversion between the two representations
+is accomplished with the routine
+.I xdr_string ():
+.IX xdr_string() "" \fIxdr_string()\fP
+.DS
+.ft CW
+bool_t xdr_string(xdrs, sp, maxlength)
+ XDR *xdrs;
+ char **sp;
+ u_int maxlength;
+.DE
+The first parameter
+.I xdrs
+is the XDR stream handle.
+The second parameter
+.I sp
+is a pointer to a string (type
+.I "char **" .
+The third parameter
+.I maxlength
+specifies the maximum number of bytes allowed during encoding or decoding.
+its value is usually specified by a protocol. For example, a protocol
+specification may say that a file name may be no longer than 255 characters.
+.LP
+The routine returns
+.I FALSE
+if the number of characters exceeds
+.I maxlength ,
+and
+.I TRUE
+if it doesn't.
+.SH
+Keep
+.I maxlength
+small. If it is too big you can blow the heap, since
+.I xdr_string()
+will call
+.I malloc()
+for space.
+.LP
+The behavior of
+.I xdr_string()
+.IX xdr_string() "" \fIxdr_string()\fP
+is similar to the behavior of other routines
+discussed in this section. The direction
+.I XDR_ENCODE
+is easiest to understand. The parameter
+.I sp
+points to a string of a certain length;
+if the string does not exceed
+.I maxlength ,
+the bytes are serialized.
+.LP
+The effect of deserializing a string is subtle.
+First the length of the incoming string is determined;
+it must not exceed
+.I maxlength .
+Next
+.I sp
+is dereferenced; if the the value is
+.I NULL ,
+then a string of the appropriate length is allocated and
+.I *sp
+is set to this string.
+If the original value of
+.I *sp
+is non-null, then the XDR package assumes
+that a target area has been allocated,
+which can hold strings no longer than
+.I maxlength .
+In either case, the string is decoded into the target area.
+The routine then appends a null character to the string.
+.LP
+In the
+.I XDR_FREE
+operation, the string is obtained by dereferencing
+.I sp .
+If the string is not
+.I NULL ,
+it is freed and
+.I *sp
+is set to
+.I NULL .
+In this operation,
+.I xdr_string()
+ignores the
+.I maxlength
+parameter.
+.NH 3
+\&Byte Arrays
+.IX "XDR library" "byte arrays"
+.LP
+Often variable-length arrays of bytes are preferable to strings.
+Byte arrays differ from strings in the following three ways:
+1) the length of the array (the byte count) is explicitly
+located in an unsigned integer,
+2) the byte sequence is not terminated by a null character, and
+3) the external representation of the bytes is the same as their
+internal representation.
+The primitive
+.I xdr_bytes()
+.IX xdr_bytes() "" \fIxdr_bytes()\fP
+converts between the internal and external
+representations of byte arrays:
+.DS
+.ft CW
+bool_t xdr_bytes(xdrs, bpp, lp, maxlength)
+ XDR *xdrs;
+ char **bpp;
+ u_int *lp;
+ u_int maxlength;
+.DE
+The usage of the first, second and fourth parameters
+are identical to the first, second and third parameters of
+.I xdr_string (),
+respectively.
+The length of the byte area is obtained by dereferencing
+.I lp
+when serializing;
+.I *lp
+is set to the byte length when deserializing.
+.NH 3
+\&Arrays
+.IX "XDR library" "arrays"
+.LP
+The XDR library package provides a primitive
+for handling arrays of arbitrary elements.
+The
+.I xdr_bytes()
+routine treats a subset of generic arrays,
+in which the size of array elements is known to be 1,
+and the external description of each element is built-in.
+The generic array primitive,
+.I xdr_array() ,
+.IX xdr_array() "" \fIxdr_array()\fP
+requires parameters identical to those of
+.I xdr_bytes()
+plus two more:
+the size of array elements,
+and an XDR routine to handle each of the elements.
+This routine is called to encode or decode
+each element of the array.
+.DS
+.ft CW
+bool_t
+xdr_array(xdrs, ap, lp, maxlength, elementsiz, xdr_element)
+ XDR *xdrs;
+ char **ap;
+ u_int *lp;
+ u_int maxlength;
+ u_int elementsiz;
+ bool_t (*xdr_element)();
+.DE
+The parameter
+.I ap
+is the address of the pointer to the array.
+If
+.I *ap
+is
+.I NULL
+when the array is being deserialized,
+XDR allocates an array of the appropriate size and sets
+.I *ap
+to that array.
+The element count of the array is obtained from
+.I *lp
+when the array is serialized;
+.I *lp
+is set to the array length when the array is deserialized.
+The parameter
+.I maxlength
+is the maximum number of elements that the array is allowed to have;
+.I elementsiz
+is the byte size of each element of the array
+(the C function
+.I sizeof()
+can be used to obtain this value).
+The
+.I xdr_element()
+.IX xdr_element() "" \fIxdr_element()\fP
+routine is called to serialize, deserialize, or free
+each element of the array.
+.br
+.LP
+Before defining more constructed data types, it is appropriate to
+present three examples.
+.LP
+.I "Example A:"
+.br
+A user on a networked machine can be identified by
+(a) the machine name, such as
+.I krypton :
+see the
+.I gethostname
+man page; (b) the user's UID: see the
+.I geteuid
+man page; and (c) the group numbers to which the user belongs:
+see the
+.I getgroups
+man page. A structure with this information and its associated
+XDR routine could be coded like this:
+.ie t .DS
+.el .DS L
+.ft CW
+struct netuser {
+ char *nu_machinename;
+ int nu_uid;
+ u_int nu_glen;
+ int *nu_gids;
+};
+#define NLEN 255 /* \fImachine names < 256 chars\fP */
+#define NGRPS 20 /* \fIuser can't be in > 20 groups\fP */
+.sp.5
+bool_t
+xdr_netuser(xdrs, nup)
+ XDR *xdrs;
+ struct netuser *nup;
+{
+ return(xdr_string(xdrs, &nup->nu_machinename, NLEN) &&
+ xdr_int(xdrs, &nup->nu_uid) &&
+ xdr_array(xdrs, &nup->nu_gids, &nup->nu_glen,
+ NGRPS, sizeof (int), xdr_int));
+}
+.DE
+.LP
+.I "Example B:"
+.br
+A party of network users could be implemented
+as an array of
+.I netuser
+structure.
+The declaration and its associated XDR routines
+are as follows:
+.ie t .DS
+.el .DS L
+.ft CW
+struct party {
+ u_int p_len;
+ struct netuser *p_nusers;
+};
+#define PLEN 500 /* \fImax number of users in a party\fP */
+.sp.5
+bool_t
+xdr_party(xdrs, pp)
+ XDR *xdrs;
+ struct party *pp;
+{
+ return(xdr_array(xdrs, &pp->p_nusers, &pp->p_len, PLEN,
+ sizeof (struct netuser), xdr_netuser));
+}
+.DE
+.LP
+.I "Example C:"
+.br
+The well-known parameters to
+.I main ,
+.I argc
+and
+.I argv
+can be combined into a structure.
+An array of these structures can make up a history of commands.
+The declarations and XDR routines might look like:
+.ie t .DS
+.el .DS L
+.ft CW
+struct cmd {
+ u_int c_argc;
+ char **c_argv;
+};
+#define ALEN 1000 /* \fIargs cannot be > 1000 chars\fP */
+#define NARGC 100 /* \fIcommands cannot have > 100 args\fP */
+
+struct history {
+ u_int h_len;
+ struct cmd *h_cmds;
+};
+#define NCMDS 75 /* \fIhistory is no more than 75 commands\fP */
+
+bool_t
+xdr_wrap_string(xdrs, sp)
+ XDR *xdrs;
+ char **sp;
+{
+ return(xdr_string(xdrs, sp, ALEN));
+}
+.DE
+.ie t .DS
+.el .DS L
+.ft CW
+bool_t
+xdr_cmd(xdrs, cp)
+ XDR *xdrs;
+ struct cmd *cp;
+{
+ return(xdr_array(xdrs, &cp->c_argv, &cp->c_argc, NARGC,
+ sizeof (char *), xdr_wrap_string));
+}
+.DE
+.ie t .DS
+.el .DS L
+.ft CW
+bool_t
+xdr_history(xdrs, hp)
+ XDR *xdrs;
+ struct history *hp;
+{
+ return(xdr_array(xdrs, &hp->h_cmds, &hp->h_len, NCMDS,
+ sizeof (struct cmd), xdr_cmd));
+}
+.DE
+The most confusing part of this example is that the routine
+.I xdr_wrap_string()
+is needed to package the
+.I xdr_string()
+routine, because the implementation of
+.I xdr_array()
+only passes two parameters to the array element description routine;
+.I xdr_wrap_string()
+supplies the third parameter to
+.I xdr_string ().
+.LP
+By now the recursive nature of the XDR library should be obvious.
+Let's continue with more constructed data types.
+.NH 3
+\&Opaque Data
+.IX "XDR library" "opaque data"
+.LP
+In some protocols, handles are passed from a server to client.
+The client passes the handle back to the server at some later time.
+Handles are never inspected by clients;
+they are obtained and submitted.
+That is to say, handles are opaque.
+The
+.I xdr_opaque()
+.IX xdr_opaque() "" \fIxdr_opaque()\fP
+primitive is used for describing fixed sized, opaque bytes.
+.DS
+.ft CW
+bool_t xdr_opaque(xdrs, p, len)
+ XDR *xdrs;
+ char *p;
+ u_int len;
+.DE
+The parameter
+.I p
+is the location of the bytes;
+.I len
+is the number of bytes in the opaque object.
+By definition, the actual data
+contained in the opaque object are not machine portable.
+.NH 3
+\&Fixed Sized Arrays
+.IX "XDR library" "fixed sized arrays"
+.LP
+The XDR library provides a primitive,
+.I xdr_vector (),
+for fixed-length arrays.
+.ie t .DS
+.el .DS L
+.ft CW
+#define NLEN 255 /* \fImachine names must be < 256 chars\fP */
+#define NGRPS 20 /* \fIuser belongs to exactly 20 groups\fP */
+.sp.5
+struct netuser {
+ char *nu_machinename;
+ int nu_uid;
+ int nu_gids[NGRPS];
+};
+.sp.5
+bool_t
+xdr_netuser(xdrs, nup)
+ XDR *xdrs;
+ struct netuser *nup;
+{
+ int i;
+.sp.5
+ if (!xdr_string(xdrs, &nup->nu_machinename, NLEN))
+ return(FALSE);
+ if (!xdr_int(xdrs, &nup->nu_uid))
+ return(FALSE);
+ if (!xdr_vector(xdrs, nup->nu_gids, NGRPS, sizeof(int),
+ xdr_int)) {
+ return(FALSE);
+ }
+ return(TRUE);
+}
+.DE
+.NH 3
+\&Discriminated Unions
+.IX "XDR library" "discriminated unions"
+.LP
+The XDR library supports discriminated unions.
+A discriminated union is a C union and an
+.I enum_t
+value that selects an \*Qarm\*U of the union.
+.DS
+.ft CW
+struct xdr_discrim {
+ enum_t value;
+ bool_t (*proc)();
+};
+.sp.5
+bool_t xdr_union(xdrs, dscmp, unp, arms, defaultarm)
+ XDR *xdrs;
+ enum_t *dscmp;
+ char *unp;
+ struct xdr_discrim *arms;
+ bool_t (*defaultarm)(); /* \fImay equal NULL\fP */
+.DE
+First the routine translates the discriminant of the union located at
+.I *dscmp .
+The discriminant is always an
+.I enum_t .
+Next the union located at
+.I *unp
+is translated.
+The parameter
+.I arms
+is a pointer to an array of
+.I xdr_discrim
+structures.
+Each structure contains an ordered pair of
+.I [value,proc] .
+If the union's discriminant is equal to the associated
+.I value ,
+then the
+.I proc
+is called to translate the union.
+The end of the
+.I xdr_discrim
+structure array is denoted by a routine of value
+.I NULL
+(0). If the discriminant is not found in the
+.I arms
+array, then the
+.I defaultarm
+procedure is called if it is non-null;
+otherwise the routine returns
+.I FALSE .
+.LP
+.I "Example D:"
+Suppose the type of a union may be integer,
+character pointer (a string), or a
+.I gnumbers
+structure.
+Also, assume the union and its current type
+are declared in a structure.
+The declaration is:
+.ie t .DS
+.el .DS L
+.ft CW
+enum utype { INTEGER=1, STRING=2, GNUMBERS=3 };
+.sp.5
+struct u_tag {
+ enum utype utype; /* \fIthe union's discriminant\fP */
+ union {
+ int ival;
+ char *pval;
+ struct gnumbers gn;
+ } uval;
+};
+.DE
+The following constructs and XDR procedure (de)serialize
+the discriminated union:
+.ie t .DS
+.el .DS L
+.ft CW
+struct xdr_discrim u_tag_arms[4] = {
+ { INTEGER, xdr_int },
+ { GNUMBERS, xdr_gnumbers }
+ { STRING, xdr_wrap_string },
+ { __dontcare__, NULL }
+ /* \fIalways terminate arms with a NULL xdr_proc\fP */
+}
+.sp.5
+bool_t
+xdr_u_tag(xdrs, utp)
+ XDR *xdrs;
+ struct u_tag *utp;
+{
+ return(xdr_union(xdrs, &utp->utype, &utp->uval,
+ u_tag_arms, NULL));
+}
+.DE
+The routine
+.I xdr_gnumbers()
+was presented above in
+.I "The XDR Library"
+section.
+.I xdr_wrap_string()
+was presented in example C.
+The default
+.I arm
+parameter to
+.I xdr_union()
+(the last parameter) is
+.I NULL
+in this example. Therefore the value of the union's discriminant
+may legally take on only values listed in the
+.I u_tag_arms
+array. This example also demonstrates that
+the elements of the arm's array do not need to be sorted.
+.LP
+It is worth pointing out that the values of the discriminant
+may be sparse, though in this example they are not.
+It is always good
+practice to assign explicitly integer values to each element of the
+discriminant's type.
+This practice both documents the external
+representation of the discriminant and guarantees that different
+C compilers emit identical discriminant values.
+.LP
+Exercise: Implement
+.I xdr_union()
+using the other primitives in this section.
+.NH 3
+\&Pointers
+.IX "XDR library" "pointers"
+.LP
+In C it is often convenient to put pointers
+to another structure within a structure.
+The
+.I xdr_reference()
+.IX xdr_reference() "" \fIxdr_reference()\fP
+primitive makes it easy to serialize, deserialize, and free
+these referenced structures.
+.DS
+.ft CW
+bool_t xdr_reference(xdrs, pp, size, proc)
+ XDR *xdrs;
+ char **pp;
+ u_int ssize;
+ bool_t (*proc)();
+.DE
+.LP
+Parameter
+.I pp
+is the address of
+the pointer to the structure;
+parameter
+.I ssize
+is the size in bytes of the structure (use the C function
+.I sizeof()
+to obtain this value); and
+.I proc
+is the XDR routine that describes the structure.
+When decoding data, storage is allocated if
+.I *pp
+is
+.I NULL .
+.LP
+There is no need for a primitive
+.I xdr_struct()
+to describe structures within structures,
+because pointers are always sufficient.
+.LP
+Exercise: Implement
+.I xdr_reference()
+using
+.I xdr_array ().
+Warning:
+.I xdr_reference()
+and
+.I xdr_array()
+are NOT interchangeable external representations of data.
+.LP
+.I "Example E:"
+Suppose there is a structure containing a person's name
+and a pointer to a
+.I gnumbers
+structure containing the person's gross assets and liabilities.
+The construct is:
+.DS
+.ft CW
+struct pgn {
+ char *name;
+ struct gnumbers *gnp;
+};
+.DE
+The corresponding XDR routine for this structure is:
+.DS
+.ft CW
+bool_t
+xdr_pgn(xdrs, pp)
+ XDR *xdrs;
+ struct pgn *pp;
+{
+ if (xdr_string(xdrs, &pp->name, NLEN) &&
+ xdr_reference(xdrs, &pp->gnp,
+ sizeof(struct gnumbers), xdr_gnumbers))
+ return(TRUE);
+ return(FALSE);
+}
+.DE
+.IX "pointer semantics and XDR"
+.I "Pointer Semantics and XDR"
+.LP
+In many applications, C programmers attach double meaning to
+the values of a pointer. Typically the value
+.I NULL
+(or zero) means data is not needed,
+yet some application-specific interpretation applies.
+In essence, the C programmer is encoding
+a discriminated union efficiently
+by overloading the interpretation of the value of a pointer.
+For instance, in example E a
+.I NULL
+pointer value for
+.I gnp
+could indicate that
+the person's assets and liabilities are unknown.
+That is, the pointer value encodes two things:
+whether or not the data is known;
+and if it is known, where it is located in memory.
+Linked lists are an extreme example of the use
+of application-specific pointer interpretation.
+.LP
+The primitive
+.I xdr_reference()
+.IX xdr_reference() "" \fIxdr_reference()\fP
+cannot and does not attach any special
+meaning to a null-value pointer during serialization.
+That is, passing an address of a pointer whose value is
+.I NULL
+to
+.I xdr_reference()
+when serialing data will most likely cause a memory fault and, on the UNIX
+system, a core dump.
+.LP
+.I xdr_pointer()
+correctly handles
+.I NULL
+pointers. For more information about its use, see
+the
+.I "Linked Lists"
+topics below.
+.LP
+.I Exercise:
+After reading the section on
+.I "Linked Lists" ,
+return here and extend example E so that
+it can correctly deal with
+.I NULL
+pointer values.
+.LP
+.I Exercise:
+Using the
+.I xdr_union (),
+.I xdr_reference()
+and
+.I xdr_void()
+primitives, implement a generic pointer handling primitive
+that implicitly deals with
+.I NULL
+pointers. That is, implement
+.I xdr_pointer ().
+.NH 2
+\&Non-filter Primitives
+.IX "XDR" "non-filter primitives"
+.LP
+XDR streams can be manipulated with
+the primitives discussed in this section.
+.DS
+.ft CW
+u_int xdr_getpos(xdrs)
+ XDR *xdrs;
+.sp.5
+bool_t xdr_setpos(xdrs, pos)
+ XDR *xdrs;
+ u_int pos;
+.sp.5
+xdr_destroy(xdrs)
+ XDR *xdrs;
+.DE
+The routine
+.I xdr_getpos()
+.IX xdr_getpos() "" \fIxdr_getpos()\fP
+returns an unsigned integer
+that describes the current position in the data stream.
+Warning: In some XDR streams, the returned value of
+.I xdr_getpos()
+is meaningless;
+the routine returns a \-1 in this case
+(though \-1 should be a legitimate value).
+.LP
+The routine
+.I xdr_setpos()
+.IX xdr_setpos() "" \fIxdr_setpos()\fP
+sets a stream position to
+.I pos .
+Warning: In some XDR streams, setting a position is impossible;
+in such cases,
+.I xdr_setpos()
+will return
+.I FALSE .
+This routine will also fail if the requested position is out-of-bounds.
+The definition of bounds varies from stream to stream.
+.LP
+The
+.I xdr_destroy()
+.IX xdr_destroy() "" \fIxdr_destroy()\fP
+primitive destroys the XDR stream.
+Usage of the stream
+after calling this routine is undefined.
+.NH 2
+\&XDR Operation Directions
+.IX XDR "operation directions"
+.IX "direction of XDR operations"
+.LP
+At times you may wish to optimize XDR routines by taking
+advantage of the direction of the operation \(em
+.I XDR_ENCODE
+.I XDR_DECODE
+or
+.I XDR_FREE
+The value
+.I xdrs->x_op
+always contains the direction of the XDR operation.
+Programmers are not encouraged to take advantage of this information.
+Therefore, no example is presented here. However, an example in the
+.I "Linked Lists"
+topic below, demonstrates the usefulness of the
+.I xdrs->x_op
+field.
+.NH 2
+\&XDR Stream Access
+.IX "XDR" "stream access"
+.LP
+An XDR stream is obtained by calling the appropriate creation routine.
+These creation routines take arguments that are tailored to the
+specific properties of the stream.
+.LP
+Streams currently exist for (de)serialization of data to or from
+standard I/O
+.I FILE
+streams, TCP/IP connections and UNIX files, and memory.
+.NH 3
+\&Standard I/O Streams
+.IX "XDR" "standard I/O streams"
+.LP
+XDR streams can be interfaced to standard I/O using the
+.I xdrstdio_create()
+.IX xdrstdio_create() "" \fIxdrstdio_create()\fP
+routine as follows:
+.DS
+.ft CW
+#include <stdio.h>
+#include <rpc/rpc.h> /* \fIxdr streams part of rpc\fP */
+.sp.5
+void
+xdrstdio_create(xdrs, fp, x_op)
+ XDR *xdrs;
+ FILE *fp;
+ enum xdr_op x_op;
+.DE
+The routine
+.I xdrstdio_create()
+initializes an XDR stream pointed to by
+.I xdrs .
+The XDR stream interfaces to the standard I/O library.
+Parameter
+.I fp
+is an open file, and
+.I x_op
+is an XDR direction.
+.NH 3
+\&Memory Streams
+.IX "XDR" "memory streams"
+.LP
+Memory streams allow the streaming of data into or out of
+a specified area of memory:
+.DS
+.ft CW
+#include <rpc/rpc.h>
+.sp.5
+void
+xdrmem_create(xdrs, addr, len, x_op)
+ XDR *xdrs;
+ char *addr;
+ u_int len;
+ enum xdr_op x_op;
+.DE
+The routine
+.I xdrmem_create()
+.IX xdrmem_create() "" \fIxdrmem_create()\fP
+initializes an XDR stream in local memory.
+The memory is pointed to by parameter
+.I addr ;
+parameter
+.I len
+is the length in bytes of the memory.
+The parameters
+.I xdrs
+and
+.I x_op
+are identical to the corresponding parameters of
+.I xdrstdio_create ().
+Currently, the UDP/IP implementation of RPC uses
+.I xdrmem_create ().
+Complete call or result messages are built in memory before calling the
+.I sendto()
+system routine.
+.NH 3
+\&Record (TCP/IP) Streams
+.IX "XDR" "record (TCP/IP) streams"
+.LP
+A record stream is an XDR stream built on top of
+a record marking standard that is built on top of the
+UNIX file or 4.2 BSD connection interface.
+.DS
+.ft CW
+#include <rpc/rpc.h> /* \fIxdr streams part of rpc\fP */
+.sp.5
+xdrrec_create(xdrs,
+ sendsize, recvsize, iohandle, readproc, writeproc)
+ XDR *xdrs;
+ u_int sendsize, recvsize;
+ char *iohandle;
+ int (*readproc)(), (*writeproc)();
+.DE
+The routine
+.I xdrrec_create()
+provides an XDR stream interface that allows for a bidirectional,
+arbitrarily long sequence of records.
+The contents of the records are meant to be data in XDR form.
+The stream's primary use is for interfacing RPC to TCP connections.
+However, it can be used to stream data into or out of normal
+UNIX files.
+.LP
+The parameter
+.I xdrs
+is similar to the corresponding parameter described above.
+The stream does its own data buffering similar to that of standard I/O.
+The parameters
+.I sendsize
+and
+.I recvsize
+determine the size in bytes of the output and input buffers, respectively;
+if their values are zero (0), then predetermined defaults are used.
+When a buffer needs to be filled or flushed, the routine
+.I readproc()
+or
+.I writeproc()
+is called, respectively.
+The usage and behavior of these
+routines are similar to the UNIX system calls
+.I read()
+and
+.I write ().
+However,
+the first parameter to each of these routines is the opaque parameter
+.I iohandle .
+The other two parameters
+.I buf ""
+and
+.I nbytes )
+and the results
+(byte count) are identical to the system routines.
+If
+.I xxx
+is
+.I readproc()
+or
+.I writeproc (),
+then it has the following form:
+.DS
+.ft CW
+.ft I
+/*
+ * returns the actual number of bytes transferred.
+ * -1 is an error
+ */
+.ft CW
+int
+xxx(iohandle, buf, len)
+ char *iohandle;
+ char *buf;
+ int nbytes;
+.DE
+The XDR stream provides means for delimiting records in the byte stream.
+The implementation details of delimiting records in a stream are
+discussed in the
+.I "Advanced Topics"
+topic below.
+The primitives that are specific to record streams are as follows:
+.DS
+.ft CW
+bool_t
+xdrrec_endofrecord(xdrs, flushnow)
+ XDR *xdrs;
+ bool_t flushnow;
+.sp.5
+bool_t
+xdrrec_skiprecord(xdrs)
+ XDR *xdrs;
+.sp.5
+bool_t
+xdrrec_eof(xdrs)
+ XDR *xdrs;
+.DE
+The routine
+.I xdrrec_endofrecord()
+.IX xdrrec_endofrecord() "" \fIxdrrec_endofrecord()\fP
+causes the current outgoing data to be marked as a record.
+If the parameter
+.I flushnow
+is
+.I TRUE ,
+then the stream's
+.I writeproc
+will be called; otherwise,
+.I writeproc
+will be called when the output buffer has been filled.
+.LP
+The routine
+.I xdrrec_skiprecord()
+.IX xdrrec_skiprecord() "" \fIxdrrec_skiprecord()\fP
+causes an input stream's position to be moved past
+the current record boundary and onto the
+beginning of the next record in the stream.
+.LP
+If there is no more data in the stream's input buffer,
+then the routine
+.I xdrrec_eof()
+.IX xdrrec_eof() "" \fIxdrrec_eof()\fP
+returns
+.I TRUE .
+That is not to say that there is no more data
+in the underlying file descriptor.
+.NH 2
+\&XDR Stream Implementation
+.IX "XDR" "stream implementation"
+.IX "stream implementation in XDR"
+.LP
+This section provides the abstract data types needed
+to implement new instances of XDR streams.
+.NH 3
+\&The XDR Object
+.IX "XDR" "object"
+.LP
+The following structure defines the interface to an XDR stream:
+.ie t .DS
+.el .DS L
+.ft CW
+enum xdr_op { XDR_ENCODE=0, XDR_DECODE=1, XDR_FREE=2 };
+.sp.5
+typedef struct {
+ enum xdr_op x_op; /* \fIoperation; fast added param\fP */
+ struct xdr_ops {
+ bool_t (*x_getlong)(); /* \fIget long from stream\fP */
+ bool_t (*x_putlong)(); /* \fIput long to stream\fP */
+ bool_t (*x_getbytes)(); /* \fIget bytes from stream\fP */
+ bool_t (*x_putbytes)(); /* \fIput bytes to stream\fP */
+ u_int (*x_getpostn)(); /* \fIreturn stream offset\fP */
+ bool_t (*x_setpostn)(); /* \fIreposition offset\fP */
+ caddr_t (*x_inline)(); /* \fIptr to buffered data\fP */
+ VOID (*x_destroy)(); /* \fIfree private area\fP */
+ } *x_ops;
+ caddr_t x_public; /* \fIusers' data\fP */
+ caddr_t x_private; /* \fIpointer to private data\fP */
+ caddr_t x_base; /* \fIprivate for position info\fP */
+ int x_handy; /* \fIextra private word\fP */
+} XDR;
+.DE
+The
+.I x_op
+field is the current operation being performed on the stream.
+This field is important to the XDR primitives,
+but should not affect a stream's implementation.
+That is, a stream's implementation should not depend
+on this value.
+The fields
+.I x_private ,
+.I x_base ,
+and
+.I x_handy
+are private to the particular
+stream's implementation.
+The field
+.I x_public
+is for the XDR client and should never be used by
+the XDR stream implementations or the XDR primitives.
+.I x_getpostn() ,
+.I x_setpostn()
+and
+.I x_destroy()
+are macros for accessing operations. The operation
+.I x_inline()
+takes two parameters:
+an XDR *, and an unsigned integer, which is a byte count.
+The routine returns a pointer to a piece of
+the stream's internal buffer.
+The caller can then use the buffer segment for any purpose.
+From the stream's point of view, the bytes in the
+buffer segment have been consumed or put.
+The routine may return
+.I NULL
+if it cannot return a buffer segment of the requested size.
+(The
+.I x_inline()
+routine is for cycle squeezers.
+Use of the resulting buffer is not data-portable.
+Users are encouraged not to use this feature.)
+.LP
+The operations
+.I x_getbytes()
+and
+.I x_putbytes()
+blindly get and put sequences of bytes
+from or to the underlying stream;
+they return
+.I TRUE
+if they are successful, and
+.I FALSE
+otherwise. The routines have identical parameters (replace
+.I xxx ):
+.DS
+.ft CW
+bool_t
+xxxbytes(xdrs, buf, bytecount)
+ XDR *xdrs;
+ char *buf;
+ u_int bytecount;
+.DE
+The operations
+.I x_getlong()
+and
+.I x_putlong()
+receive and put
+long numbers from and to the data stream.
+It is the responsibility of these routines
+to translate the numbers between the machine representation
+and the (standard) external representation.
+The UNIX primitives
+.I htonl()
+and
+.I ntohl()
+can be helpful in accomplishing this.
+The higher-level XDR implementation assumes that
+signed and unsigned long integers contain the same number of bits,
+and that nonnegative integers
+have the same bit representations as unsigned integers.
+The routines return
+.I TRUE
+if they succeed, and
+.I FALSE
+otherwise. They have identical parameters:
+.DS
+.ft CW
+bool_t
+xxxlong(xdrs, lp)
+ XDR *xdrs;
+ long *lp;
+.DE
+Implementors of new XDR streams must make an XDR structure
+(with new operation routines) available to clients,
+using some kind of create routine.
+.NH 1
+\&Advanced Topics
+.IX XDR "advanced topics"
+.LP
+This section describes techniques for passing data structures that
+are not covered in the preceding sections. Such structures include
+linked lists (of arbitrary lengths). Unlike the simpler examples
+covered in the earlier sections, the following examples are written
+using both the XDR C library routines and the XDR data description
+language.
+The
+.I "External Data Representation Standard: Protocol Specification"
+describes this
+language in complete detail.
+.NH 2
+\&Linked Lists
+.IX XDR "linked lists"
+.LP
+The last example in the
+.I Pointers
+topic earlier in this chapter
+presented a C data structure and its associated XDR
+routines for a individual's gross assets and liabilities.
+The example is duplicated below:
+.ie t .DS
+.el .DS L
+.ft CW
+struct gnumbers {
+ long g_assets;
+ long g_liabilities;
+};
+.sp.5
+bool_t
+xdr_gnumbers(xdrs, gp)
+ XDR *xdrs;
+ struct gnumbers *gp;
+{
+ if (xdr_long(xdrs, &(gp->g_assets)))
+ return(xdr_long(xdrs, &(gp->g_liabilities)));
+ return(FALSE);
+}
+.DE
+.LP
+Now assume that we wish to implement a linked list of such information.
+A data structure could be constructed as follows:
+.ie t .DS
+.el .DS L
+.ft CW
+struct gnumbers_node {
+ struct gnumbers gn_numbers;
+ struct gnumbers_node *gn_next;
+};
+.sp .5
+typedef struct gnumbers_node *gnumbers_list;
+.DE
+.LP
+The head of the linked list can be thought of as the data object;
+that is, the head is not merely a convenient shorthand for a
+structure. Similarly the
+.I gn_next
+field is used to indicate whether or not the object has terminated.
+Unfortunately, if the object continues, the
+.I gn_next
+field is also the address of where it continues. The link addresses
+carry no useful information when the object is serialized.
+.LP
+The XDR data description of this linked list is described by the
+recursive declaration of
+.I gnumbers_list :
+.ie t .DS
+.el .DS L
+.ft CW
+struct gnumbers {
+ int g_assets;
+ int g_liabilities;
+};
+.sp .5
+struct gnumbers_node {
+ gnumbers gn_numbers;
+ gnumbers_node *gn_next;
+};
+.DE
+.LP
+In this description, the boolean indicates whether there is more data
+following it. If the boolean is
+.I FALSE ,
+then it is the last data field of the structure. If it is
+.I TRUE ,
+then it is followed by a gnumbers structure and (recursively) by a
+.I gnumbers_list .
+Note that the C declaration has no boolean explicitly declared in it
+(though the
+.I gn_next
+field implicitly carries the information), while the XDR data
+description has no pointer explicitly declared in it.
+.LP
+Hints for writing the XDR routines for a
+.I gnumbers_list
+follow easily from the XDR description above. Note how the primitive
+.I xdr_pointer()
+is used to implement the XDR union above.
+.ie t .DS
+.el .DS L
+.ft CW
+bool_t
+xdr_gnumbers_node(xdrs, gn)
+ XDR *xdrs;
+ gnumbers_node *gn;
+{
+ return(xdr_gnumbers(xdrs, &gn->gn_numbers) &&
+ xdr_gnumbers_list(xdrs, &gp->gn_next));
+}
+.sp .5
+bool_t
+xdr_gnumbers_list(xdrs, gnp)
+ XDR *xdrs;
+ gnumbers_list *gnp;
+{
+ return(xdr_pointer(xdrs, gnp,
+ sizeof(struct gnumbers_node),
+ xdr_gnumbers_node));
+}
+.DE
+.LP
+The unfortunate side effect of XDR'ing a list with these routines
+is that the C stack grows linearly with respect to the number of
+node in the list. This is due to the recursion. The following
+routine collapses the above two mutually recursive into a single,
+non-recursive one.
+.ie t .DS
+.el .DS L
+.ft CW
+bool_t
+xdr_gnumbers_list(xdrs, gnp)
+ XDR *xdrs;
+ gnumbers_list *gnp;
+{
+ bool_t more_data;
+ gnumbers_list *nextp;
+.sp .5
+ for (;;) {
+ more_data = (*gnp != NULL);
+ if (!xdr_bool(xdrs, &more_data)) {
+ return(FALSE);
+ }
+ if (! more_data) {
+ break;
+ }
+ if (xdrs->x_op == XDR_FREE) {
+ nextp = &(*gnp)->gn_next;
+ }
+ if (!xdr_reference(xdrs, gnp,
+ sizeof(struct gnumbers_node), xdr_gnumbers)) {
+
+ return(FALSE);
+ }
+ gnp = (xdrs->x_op == XDR_FREE) ?
+ nextp : &(*gnp)->gn_next;
+ }
+ *gnp = NULL;
+ return(TRUE);
+}
+.DE
+.LP
+The first task is to find out whether there is more data or not,
+so that this boolean information can be serialized. Notice that
+this statement is unnecessary in the
+.I XDR_DECODE
+case, since the value of more_data is not known until we
+deserialize it in the next statement.
+.LP
+The next statement XDR's the more_data field of the XDR union.
+Then if there is truly no more data, we set this last pointer to
+.I NULL
+to indicate the end of the list, and return
+.I TRUE
+because we are done. Note that setting the pointer to
+.I NULL
+is only important in the
+.I XDR_DECODE
+case, since it is already
+.I NULL
+in the
+.I XDR_ENCODE
+and
+XDR_FREE
+cases.
+.LP
+Next, if the direction is
+.I XDR_FREE ,
+the value of
+.I nextp
+is set to indicate the location of the next pointer in the list.
+We do this now because we need to dereference gnp to find the
+location of the next item in the list, and after the next
+statement the storage pointed to by
+.I gnp
+will be freed up and no be longer valid. We can't do this for all
+directions though, because in the
+.I XDR_DECODE
+direction the value of
+.I gnp
+won't be set until the next statement.
+.LP
+Next, we XDR the data in the node using the primitive
+.I xdr_reference ().
+.I xdr_reference()
+is like
+.I xdr_pointer()
+which we used before, but it does not
+send over the boolean indicating whether there is more data.
+We use it instead of
+.I xdr_pointer()
+because we have already XDR'd this information ourselves. Notice
+that the xdr routine passed is not the same type as an element
+in the list. The routine passed is
+.I xdr_gnumbers (),
+for XDR'ing gnumbers, but each element in the list is actually of
+type
+.I gnumbers_node .
+We don't pass
+.I xdr_gnumbers_node()
+because it is recursive, and instead use
+.I xdr_gnumbers()
+which XDR's all of the non-recursive part. Note that this trick
+will work only if the
+.I gn_numbers
+field is the first item in each element, so that their addresses
+are identical when passed to
+.I xdr_reference ().
+.LP
+Finally, we update
+.I gnp
+to point to the next item in the list. If the direction is
+.I XDR_FREE ,
+we set it to the previously saved value, otherwise we can
+dereference
+.I gnp
+to get the proper value. Though harder to understand than the
+recursive version, this non-recursive routine is far less likely
+to blow the C stack. It will also run more efficiently since
+a lot of procedure call overhead has been removed. Most lists
+are small though (in the hundreds of items or less) and the
+recursive version should be sufficient for them.
+.EQ
+delim off
+.EN
diff --git a/cpukit/librpc/src/rpc/PSD.doc/xdr.rfc.ms b/cpukit/librpc/src/rpc/PSD.doc/xdr.rfc.ms
new file mode 100644
index 0000000000..d4baff5391
--- /dev/null
+++ b/cpukit/librpc/src/rpc/PSD.doc/xdr.rfc.ms
@@ -0,0 +1,1058 @@
+.\"
+.\" Must use -- tbl -- with this one
+.\"
+.\" @(#)xdr.rfc.ms 2.2 88/08/05 4.0 RPCSRC
+.de BT
+.if \\n%=1 .tl ''- % -''
+..
+.ND
+.\" prevent excess underlining in nroff
+.if n .fp 2 R
+.OH 'External Data Representation Standard''Page %'
+.EH 'Page %''External Data Representation Standard'
+.IX "External Data Representation"
+.if \\n%=1 .bp
+.SH
+\&External Data Representation Standard: Protocol Specification
+.IX XDR RFC
+.IX XDR "protocol specification"
+.LP
+.NH 0
+\&Status of this Standard
+.nr OF 1
+.IX XDR "RFC status"
+.LP
+Note: This chapter specifies a protocol that Sun Microsystems, Inc., and
+others are using. It has been designated RFC1014 by the ARPA Network
+Information Center.
+.NH 1
+Introduction
+\&
+.LP
+XDR is a standard for the description and encoding of data. It is
+useful for transferring data between different computer
+architectures, and has been used to communicate data between such
+diverse machines as the Sun Workstation, VAX, IBM-PC, and Cray.
+XDR fits into the ISO presentation layer, and is roughly analogous in
+purpose to X.409, ISO Abstract Syntax Notation. The major difference
+between these two is that XDR uses implicit typing, while X.409 uses
+explicit typing.
+.LP
+XDR uses a language to describe data formats. The language can only
+be used only to describe data; it is not a programming language.
+This language allows one to describe intricate data formats in a
+concise manner. The alternative of using graphical representations
+(itself an informal language) quickly becomes incomprehensible when
+faced with complexity. The XDR language itself is similar to the C
+language [1], just as Courier [4] is similar to Mesa. Protocols such
+as Sun RPC (Remote Procedure Call) and the NFS (Network File System)
+use XDR to describe the format of their data.
+.LP
+The XDR standard makes the following assumption: that bytes (or
+octets) are portable, where a byte is defined to be 8 bits of data.
+A given hardware device should encode the bytes onto the various
+media in such a way that other hardware devices may decode the bytes
+without loss of meaning. For example, the Ethernet standard
+suggests that bytes be encoded in "little-endian" style [2], or least
+significant bit first.
+.NH 2
+\&Basic Block Size
+.IX XDR "basic block size"
+.IX XDR "block size"
+.LP
+The representation of all items requires a multiple of four bytes (or
+32 bits) of data. The bytes are numbered 0 through n-1. The bytes
+are read or written to some byte stream such that byte m always
+precedes byte m+1. If the n bytes needed to contain the data are not
+a multiple of four, then the n bytes are followed by enough (0 to 3)
+residual zero bytes, r, to make the total byte count a multiple of 4.
+.LP
+We include the familiar graphic box notation for illustration and
+comparison. In most illustrations, each box (delimited by a plus
+sign at the 4 corners and vertical bars and dashes) depicts a byte.
+Ellipses (...) between boxes show zero or more additional bytes where
+required.
+.ie t .DS
+.el .DS L
+\fIA Block\fP
+
+\f(CW+--------+--------+...+--------+--------+...+--------+
+| byte 0 | byte 1 |...|byte n-1| 0 |...| 0 |
++--------+--------+...+--------+--------+...+--------+
+|<-----------n bytes---------->|<------r bytes------>|
+|<-----------n+r (where (n+r) mod 4 = 0)>----------->|\fP
+
+.DE
+.NH 1
+\&XDR Data Types
+.IX XDR "data types"
+.IX "XDR data types"
+.LP
+Each of the sections that follow describes a data type defined in the
+XDR standard, shows how it is declared in the language, and includes
+a graphic illustration of its encoding.
+.LP
+For each data type in the language we show a general paradigm
+declaration. Note that angle brackets (< and >) denote
+variable length sequences of data and square brackets ([ and ]) denote
+fixed-length sequences of data. "n", "m" and "r" denote integers.
+For the full language specification and more formal definitions of
+terms such as "identifier" and "declaration", refer to
+.I "The XDR Language Specification" ,
+below.
+.LP
+For some data types, more specific examples are included.
+A more extensive example of a data description is in
+.I "An Example of an XDR Data Description"
+below.
+.NH 2
+\&Integer
+.IX XDR integer
+.LP
+An XDR signed integer is a 32-bit datum that encodes an integer in
+the range [-2147483648,2147483647]. The integer is represented in
+two's complement notation. The most and least significant bytes are
+0 and 3, respectively. Integers are declared as follows:
+.ie t .DS
+.el .DS L
+\fIInteger\fP
+
+\f(CW(MSB) (LSB)
++-------+-------+-------+-------+
+|byte 0 |byte 1 |byte 2 |byte 3 |
++-------+-------+-------+-------+
+<------------32 bits------------>\fP
+.DE
+.NH 2
+\&Unsigned Integer
+.IX XDR "unsigned integer"
+.IX XDR "integer, unsigned"
+.LP
+An XDR unsigned integer is a 32-bit datum that encodes a nonnegative
+integer in the range [0,4294967295]. It is represented by an
+unsigned binary number whose most and least significant bytes are 0
+and 3, respectively. An unsigned integer is declared as follows:
+.ie t .DS
+.el .DS L
+\fIUnsigned Integer\fP
+
+\f(CW(MSB) (LSB)
++-------+-------+-------+-------+
+|byte 0 |byte 1 |byte 2 |byte 3 |
++-------+-------+-------+-------+
+<------------32 bits------------>\fP
+.DE
+.NH 2
+\&Enumeration
+.IX XDR enumeration
+.LP
+Enumerations have the same representation as signed integers.
+Enumerations are handy for describing subsets of the integers.
+Enumerated data is declared as follows:
+.ft CW
+.DS
+enum { name-identifier = constant, ... } identifier;
+.DE
+For example, the three colors red, yellow, and blue could be
+described by an enumerated type:
+.DS
+.ft CW
+enum { RED = 2, YELLOW = 3, BLUE = 5 } colors;
+.DE
+It is an error to encode as an enum any other integer than those that
+have been given assignments in the enum declaration.
+.NH 2
+\&Boolean
+.IX XDR boolean
+.LP
+Booleans are important enough and occur frequently enough to warrant
+their own explicit type in the standard. Booleans are declared as
+follows:
+.DS
+.ft CW
+bool identifier;
+.DE
+This is equivalent to:
+.DS
+.ft CW
+enum { FALSE = 0, TRUE = 1 } identifier;
+.DE
+.NH 2
+\&Hyper Integer and Unsigned Hyper Integer
+.IX XDR "hyper integer"
+.IX XDR "integer, hyper"
+.LP
+The standard also defines 64-bit (8-byte) numbers called hyper
+integer and unsigned hyper integer. Their representations are the
+obvious extensions of integer and unsigned integer defined above.
+They are represented in two's complement notation. The most and
+least significant bytes are 0 and 7, respectively. Their
+declarations:
+.ie t .DS
+.el .DS L
+\fIHyper Integer\fP
+\fIUnsigned Hyper Integer\fP
+
+\f(CW(MSB) (LSB)
++-------+-------+-------+-------+-------+-------+-------+-------+
+|byte 0 |byte 1 |byte 2 |byte 3 |byte 4 |byte 5 |byte 6 |byte 7 |
++-------+-------+-------+-------+-------+-------+-------+-------+
+<----------------------------64 bits---------------------------->\fP
+.DE
+.NH 2
+\&Floating-point
+.IX XDR "integer, floating point"
+.IX XDR "floating-point integer"
+.LP
+The standard defines the floating-point data type "float" (32 bits or
+4 bytes). The encoding used is the IEEE standard for normalized
+single-precision floating-point numbers [3]. The following three
+fields describe the single-precision floating-point number:
+.RS
+.IP \fBS\fP:
+The sign of the number. Values 0 and 1 represent positive and
+negative, respectively. One bit.
+.IP \fBE\fP:
+The exponent of the number, base 2. 8 bits are devoted to this
+field. The exponent is biased by 127.
+.IP \fBF\fP:
+The fractional part of the number's mantissa, base 2. 23 bits
+are devoted to this field.
+.RE
+.LP
+Therefore, the floating-point number is described by:
+.DS
+(-1)**S * 2**(E-Bias) * 1.F
+.DE
+It is declared as follows:
+.ie t .DS
+.el .DS L
+\fISingle-Precision Floating-Point\fP
+
+\f(CW+-------+-------+-------+-------+
+|byte 0 |byte 1 |byte 2 |byte 3 |
+S| E | F |
++-------+-------+-------+-------+
+1|<- 8 ->|<-------23 bits------>|
+<------------32 bits------------>\fP
+.DE
+Just as the most and least significant bytes of a number are 0 and 3,
+the most and least significant bits of a single-precision floating-
+point number are 0 and 31. The beginning bit (and most significant
+bit) offsets of S, E, and F are 0, 1, and 9, respectively. Note that
+these numbers refer to the mathematical positions of the bits, and
+NOT to their actual physical locations (which vary from medium to
+medium).
+.LP
+The IEEE specifications should be consulted concerning the encoding
+for signed zero, signed infinity (overflow), and denormalized numbers
+(underflow) [3]. According to IEEE specifications, the "NaN" (not a
+number) is system dependent and should not be used externally.
+.NH 2
+\&Double-precision Floating-point
+.IX XDR "integer, double-precision floating point"
+.IX XDR "double-precision floating-point integer"
+.LP
+The standard defines the encoding for the double-precision floating-
+point data type "double" (64 bits or 8 bytes). The encoding used is
+the IEEE standard for normalized double-precision floating-point
+numbers [3]. The standard encodes the following three fields, which
+describe the double-precision floating-point number:
+.RS
+.IP \fBS\fP:
+The sign of the number. Values 0 and 1 represent positive and
+negative, respectively. One bit.
+.IP \fBE\fP:
+The exponent of the number, base 2. 11 bits are devoted to this
+field. The exponent is biased by 1023.
+.IP \fBF\fP:
+The fractional part of the number's mantissa, base 2. 52 bits
+are devoted to this field.
+.RE
+.LP
+Therefore, the floating-point number is described by:
+.DS
+(-1)**S * 2**(E-Bias) * 1.F
+.DE
+It is declared as follows:
+.ie t .DS
+.el .DS L
+\fIDouble-Precision Floating-Point\fP
+
+\f(CW+------+------+------+------+------+------+------+------+
+|byte 0|byte 1|byte 2|byte 3|byte 4|byte 5|byte 6|byte 7|
+S| E | F |
++------+------+------+------+------+------+------+------+
+1|<--11-->|<-----------------52 bits------------------->|
+<-----------------------64 bits------------------------->\fP
+.DE
+Just as the most and least significant bytes of a number are 0 and 3,
+the most and least significant bits of a double-precision floating-
+point number are 0 and 63. The beginning bit (and most significant
+bit) offsets of S, E , and F are 0, 1, and 12, respectively. Note
+that these numbers refer to the mathematical positions of the bits,
+and NOT to their actual physical locations (which vary from medium to
+medium).
+.LP
+The IEEE specifications should be consulted concerning the encoding
+for signed zero, signed infinity (overflow), and denormalized numbers
+(underflow) [3]. According to IEEE specifications, the "NaN" (not a
+number) is system dependent and should not be used externally.
+.NH 2
+\&Fixed-length Opaque Data
+.IX XDR "fixed-length opaque data"
+.IX XDR "opaque data, fixed length"
+.LP
+At times, fixed-length uninterpreted data needs to be passed among
+machines. This data is called "opaque" and is declared as follows:
+.DS
+.ft CW
+opaque identifier[n];
+.DE
+where the constant n is the (static) number of bytes necessary to
+contain the opaque data. If n is not a multiple of four, then the n
+bytes are followed by enough (0 to 3) residual zero bytes, r, to make
+the total byte count of the opaque object a multiple of four.
+.ie t .DS
+.el .DS L
+\fIFixed-Length Opaque\fP
+
+\f(CW0 1 ...
++--------+--------+...+--------+--------+...+--------+
+| byte 0 | byte 1 |...|byte n-1| 0 |...| 0 |
++--------+--------+...+--------+--------+...+--------+
+|<-----------n bytes---------->|<------r bytes------>|
+|<-----------n+r (where (n+r) mod 4 = 0)------------>|\fP
+.DE
+.NH 2
+\&Variable-length Opaque Data
+.IX XDR "variable-length opaque data"
+.IX XDR "opaque data, variable length"
+.LP
+The standard also provides for variable-length (counted) opaque data,
+defined as a sequence of n (numbered 0 through n-1) arbitrary bytes
+to be the number n encoded as an unsigned integer (as described
+below), and followed by the n bytes of the sequence.
+.LP
+Byte m of the sequence always precedes byte m+1 of the sequence, and
+byte 0 of the sequence always follows the sequence's length (count).
+enough (0 to 3) residual zero bytes, r, to make the total byte count
+a multiple of four. Variable-length opaque data is declared in the
+following way:
+.DS
+.ft CW
+opaque identifier<m>;
+.DE
+or
+.DS
+.ft CW
+opaque identifier<>;
+.DE
+The constant m denotes an upper bound of the number of bytes that the
+sequence may contain. If m is not specified, as in the second
+declaration, it is assumed to be (2**32) - 1, the maximum length.
+The constant m would normally be found in a protocol specification.
+For example, a filing protocol may state that the maximum data
+transfer size is 8192 bytes, as follows:
+.DS
+.ft CW
+opaque filedata<8192>;
+.DE
+This can be illustrated as follows:
+.ie t .DS
+.el .DS L
+\fIVariable-Length Opaque\fP
+
+\f(CW0 1 2 3 4 5 ...
++-----+-----+-----+-----+-----+-----+...+-----+-----+...+-----+
+| length n |byte0|byte1|...| n-1 | 0 |...| 0 |
++-----+-----+-----+-----+-----+-----+...+-----+-----+...+-----+
+|<-------4 bytes------->|<------n bytes------>|<---r bytes--->|
+|<----n+r (where (n+r) mod 4 = 0)---->|\fP
+.DE
+.LP
+It is an error to encode a length greater than the maximum
+described in the specification.
+.NH 2
+\&String
+.IX XDR string
+.LP
+The standard defines a string of n (numbered 0 through n-1) ASCII
+bytes to be the number n encoded as an unsigned integer (as described
+above), and followed by the n bytes of the string. Byte m of the
+string always precedes byte m+1 of the string, and byte 0 of the
+string always follows the string's length. If n is not a multiple of
+four, then the n bytes are followed by enough (0 to 3) residual zero
+bytes, r, to make the total byte count a multiple of four. Counted
+byte strings are declared as follows:
+.DS
+.ft CW
+string object<m>;
+.DE
+or
+.DS
+.ft CW
+string object<>;
+.DE
+The constant m denotes an upper bound of the number of bytes that a
+string may contain. If m is not specified, as in the second
+declaration, it is assumed to be (2**32) - 1, the maximum length.
+The constant m would normally be found in a protocol specification.
+For example, a filing protocol may state that a file name can be no
+longer than 255 bytes, as follows:
+.DS
+.ft CW
+string filename<255>;
+.DE
+Which can be illustrated as:
+.ie t .DS
+.el .DS L
+\fIA String\fP
+
+\f(CW0 1 2 3 4 5 ...
++-----+-----+-----+-----+-----+-----+...+-----+-----+...+-----+
+| length n |byte0|byte1|...| n-1 | 0 |...| 0 |
++-----+-----+-----+-----+-----+-----+...+-----+-----+...+-----+
+|<-------4 bytes------->|<------n bytes------>|<---r bytes--->|
+|<----n+r (where (n+r) mod 4 = 0)---->|\fP
+.DE
+.LP
+It is an error to encode a length greater than the maximum
+described in the specification.
+.NH 2
+\&Fixed-length Array
+.IX XDR "fixed-length array"
+.IX XDR "array, fixed length"
+.LP
+Declarations for fixed-length arrays of homogeneous elements are in
+the following form:
+.DS
+.ft CW
+type-name identifier[n];
+.DE
+Fixed-length arrays of elements numbered 0 through n-1 are encoded by
+individually encoding the elements of the array in their natural
+order, 0 through n-1. Each element's size is a multiple of four
+bytes. Though all elements are of the same type, the elements may
+have different sizes. For example, in a fixed-length array of
+strings, all elements are of type "string", yet each element will
+vary in its length.
+.ie t .DS
+.el .DS L
+\fIFixed-Length Array\fP
+
+\f(CW+---+---+---+---+---+---+---+---+...+---+---+---+---+
+| element 0 | element 1 |...| element n-1 |
++---+---+---+---+---+---+---+---+...+---+---+---+---+
+|<--------------------n elements------------------->|\fP
+.DE
+.NH 2
+\&Variable-length Array
+.IX XDR "variable-length array"
+.IX XDR "array, variable length"
+.LP
+Counted arrays provide the ability to encode variable-length arrays
+of homogeneous elements. The array is encoded as the element count n
+(an unsigned integer) followed by the encoding of each of the array's
+elements, starting with element 0 and progressing through element n-
+1. The declaration for variable-length arrays follows this form:
+.DS
+.ft CW
+type-name identifier<m>;
+.DE
+or
+.DS
+.ft CW
+type-name identifier<>;
+.DE
+The constant m specifies the maximum acceptable element count of an
+array; if m is not specified, as in the second declaration, it is
+assumed to be (2**32) - 1.
+.ie t .DS
+.el .DS L
+\fICounted Array\fP
+
+\f(CW0 1 2 3
++--+--+--+--+--+--+--+--+--+--+--+--+...+--+--+--+--+
+| n | element 0 | element 1 |...|element n-1|
++--+--+--+--+--+--+--+--+--+--+--+--+...+--+--+--+--+
+|<-4 bytes->|<--------------n elements------------->|\fP
+.DE
+It is an error to encode a value of n that is greater than the
+maximum described in the specification.
+.NH 2
+\&Structure
+.IX XDR structure
+.LP
+Structures are declared as follows:
+.DS
+.ft CW
+struct {
+ component-declaration-A;
+ component-declaration-B;
+ \&...
+} identifier;
+.DE
+The components of the structure are encoded in the order of their
+declaration in the structure. Each component's size is a multiple of
+four bytes, though the components may be different sizes.
+.ie t .DS
+.el .DS L
+\fIStructure\fP
+
+\f(CW+-------------+-------------+...
+| component A | component B |...
++-------------+-------------+...\fP
+.DE
+.NH 2
+\&Discriminated Union
+.IX XDR "discriminated union"
+.IX XDR union discriminated
+.LP
+A discriminated union is a type composed of a discriminant followed
+by a type selected from a set of prearranged types according to the
+value of the discriminant. The type of discriminant is either "int",
+"unsigned int", or an enumerated type, such as "bool". The component
+types are called "arms" of the union, and are preceded by the value
+of the discriminant which implies their encoding. Discriminated
+unions are declared as follows:
+.DS
+.ft CW
+union switch (discriminant-declaration) {
+ case discriminant-value-A:
+ arm-declaration-A;
+ case discriminant-value-B:
+ arm-declaration-B;
+ \&...
+ default: default-declaration;
+} identifier;
+.DE
+Each "case" keyword is followed by a legal value of the discriminant.
+The default arm is optional. If it is not specified, then a valid
+encoding of the union cannot take on unspecified discriminant values.
+The size of the implied arm is always a multiple of four bytes.
+.LP
+The discriminated union is encoded as its discriminant followed by
+the encoding of the implied arm.
+.ie t .DS
+.el .DS L
+\fIDiscriminated Union\fP
+
+\f(CW0 1 2 3
++---+---+---+---+---+---+---+---+
+| discriminant | implied arm |
++---+---+---+---+---+---+---+---+
+|<---4 bytes--->|\fP
+.DE
+.NH 2
+\&Void
+.IX XDR void
+.LP
+An XDR void is a 0-byte quantity. Voids are useful for describing
+operations that take no data as input or no data as output. They are
+also useful in unions, where some arms may contain data and others do
+not. The declaration is simply as follows:
+.DS
+.ft CW
+void;
+.DE
+Voids are illustrated as follows:
+.ie t .DS
+.el .DS L
+\fIVoid\fP
+
+\f(CW ++
+ ||
+ ++
+--><-- 0 bytes\fP
+.DE
+.NH 2
+\&Constant
+.IX XDR constant
+.LP
+The data declaration for a constant follows this form:
+.DS
+.ft CW
+const name-identifier = n;
+.DE
+"const" is used to define a symbolic name for a constant; it does not
+declare any data. The symbolic constant may be used anywhere a
+regular constant may be used. For example, the following defines a
+symbolic constant DOZEN, equal to 12.
+.DS
+.ft CW
+const DOZEN = 12;
+.DE
+.NH 2
+\&Typedef
+.IX XDR typedef
+.LP
+"typedef" does not declare any data either, but serves to define new
+identifiers for declaring data. The syntax is:
+.DS
+.ft CW
+typedef declaration;
+.DE
+The new type name is actually the variable name in the declaration
+part of the typedef. For example, the following defines a new type
+called "eggbox" using an existing type called "egg":
+.DS
+.ft CW
+typedef egg eggbox[DOZEN];
+.DE
+Variables declared using the new type name have the same type as the
+new type name would have in the typedef, if it was considered a
+variable. For example, the following two declarations are equivalent
+in declaring the variable "fresheggs":
+.DS
+.ft CW
+eggbox fresheggs;
+egg fresheggs[DOZEN];
+.DE
+When a typedef involves a struct, enum, or union definition, there is
+another (preferred) syntax that may be used to define the same type.
+In general, a typedef of the following form:
+.DS
+.ft CW
+typedef <<struct, union, or enum definition>> identifier;
+.DE
+may be converted to the alternative form by removing the "typedef"
+part and placing the identifier after the "struct", "union", or
+"enum" keyword, instead of at the end. For example, here are the two
+ways to define the type "bool":
+.DS
+.ft CW
+typedef enum { /* \fIusing typedef\fP */
+ FALSE = 0,
+ TRUE = 1
+ } bool;
+
+enum bool { /* \fIpreferred alternative\fP */
+ FALSE = 0,
+ TRUE = 1
+ };
+.DE
+The reason this syntax is preferred is one does not have to wait
+until the end of a declaration to figure out the name of the new
+type.
+.NH 2
+\&Optional-data
+.IX XDR "optional data"
+.IX XDR "data, optional"
+.LP
+Optional-data is one kind of union that occurs so frequently that we
+give it a special syntax of its own for declaring it. It is declared
+as follows:
+.DS
+.ft CW
+type-name *identifier;
+.DE
+This is equivalent to the following union:
+.DS
+.ft CW
+union switch (bool opted) {
+ case TRUE:
+ type-name element;
+ case FALSE:
+ void;
+} identifier;
+.DE
+It is also equivalent to the following variable-length array
+declaration, since the boolean "opted" can be interpreted as the
+length of the array:
+.DS
+.ft CW
+type-name identifier<1>;
+.DE
+Optional-data is not so interesting in itself, but it is very useful
+for describing recursive data-structures such as linked-lists and
+trees. For example, the following defines a type "stringlist" that
+encodes lists of arbitrary length strings:
+.DS
+.ft CW
+struct *stringlist {
+ string item<>;
+ stringlist next;
+};
+.DE
+It could have been equivalently declared as the following union:
+.DS
+.ft CW
+union stringlist switch (bool opted) {
+ case TRUE:
+ struct {
+ string item<>;
+ stringlist next;
+ } element;
+ case FALSE:
+ void;
+};
+.DE
+or as a variable-length array:
+.DS
+.ft CW
+struct stringlist<1> {
+ string item<>;
+ stringlist next;
+};
+.DE
+Both of these declarations obscure the intention of the stringlist
+type, so the optional-data declaration is preferred over both of
+them. The optional-data type also has a close correlation to how
+recursive data structures are represented in high-level languages
+such as Pascal or C by use of pointers. In fact, the syntax is the
+same as that of the C language for pointers.
+.NH 2
+\&Areas for Future Enhancement
+.IX XDR futures
+.LP
+The XDR standard lacks representations for bit fields and bitmaps,
+since the standard is based on bytes. Also missing are packed (or
+binary-coded) decimals.
+.LP
+The intent of the XDR standard was not to describe every kind of data
+that people have ever sent or will ever want to send from machine to
+machine. Rather, it only describes the most commonly used data-types
+of high-level languages such as Pascal or C so that applications
+written in these languages will be able to communicate easily over
+some medium.
+.LP
+One could imagine extensions to XDR that would let it describe almost
+any existing protocol, such as TCP. The minimum necessary for this
+are support for different block sizes and byte-orders. The XDR
+discussed here could then be considered the 4-byte big-endian member
+of a larger XDR family.
+.NH 1
+\&Discussion
+.sp 2
+.NH 2
+\&Why a Language for Describing Data?
+.IX XDR language
+.LP
+There are many advantages in using a data-description language such
+as XDR versus using diagrams. Languages are more formal than
+diagrams and lead to less ambiguous descriptions of data.
+Languages are also easier to understand and allow one to think of
+other issues instead of the low-level details of bit-encoding.
+Also, there is a close analogy between the types of XDR and a
+high-level language such as C or Pascal. This makes the
+implementation of XDR encoding and decoding modules an easier task.
+Finally, the language specification itself is an ASCII string that
+can be passed from machine to machine to perform on-the-fly data
+interpretation.
+.NH 2
+\&Why Only one Byte-Order for an XDR Unit?
+.IX XDR "byte order"
+.LP
+Supporting two byte-orderings requires a higher level protocol for
+determining in which byte-order the data is encoded. Since XDR is
+not a protocol, this can't be done. The advantage of this, though,
+is that data in XDR format can be written to a magnetic tape, for
+example, and any machine will be able to interpret it, since no
+higher level protocol is necessary for determining the byte-order.
+.NH 2
+\&Why does XDR use Big-Endian Byte-Order?
+.LP
+Yes, it is unfair, but having only one byte-order means you have to
+be unfair to somebody. Many architectures, such as the Motorola
+68000 and IBM 370, support the big-endian byte-order.
+.NH 2
+\&Why is the XDR Unit Four Bytes Wide?
+.LP
+There is a tradeoff in choosing the XDR unit size. Choosing a small
+size such as two makes the encoded data small, but causes alignment
+problems for machines that aren't aligned on these boundaries. A
+large size such as eight means the data will be aligned on virtually
+every machine, but causes the encoded data to grow too big. We chose
+four as a compromise. Four is big enough to support most
+architectures efficiently, except for rare machines such as the
+eight-byte aligned Cray. Four is also small enough to keep the
+encoded data restricted to a reasonable size.
+.NH 2
+\&Why must Variable-Length Data be Padded with Zeros?
+.IX XDR "variable-length data"
+.LP
+It is desirable that the same data encode into the same thing on all
+machines, so that encoded data can be meaningfully compared or
+checksummed. Forcing the padded bytes to be zero ensures this.
+.NH 2
+\&Why is there No Explicit Data-Typing?
+.LP
+Data-typing has a relatively high cost for what small advantages it
+may have. One cost is the expansion of data due to the inserted type
+fields. Another is the added cost of interpreting these type fields
+and acting accordingly. And most protocols already know what type
+they expect, so data-typing supplies only redundant information.
+However, one can still get the benefits of data-typing using XDR. One
+way is to encode two things: first a string which is the XDR data
+description of the encoded data, and then the encoded data itself.
+Another way is to assign a value to all the types in XDR, and then
+define a universal type which takes this value as its discriminant
+and for each value, describes the corresponding data type.
+.NH 1
+\&The XDR Language Specification
+.IX XDR language
+.sp 1
+.NH 2
+\&Notational Conventions
+.IX "XDR language" notation
+.LP
+This specification uses an extended Backus-Naur Form notation for
+describing the XDR language. Here is a brief description of the
+notation:
+.IP 1.
+The characters
+.I | ,
+.I ( ,
+.I ) ,
+.I [ ,
+.I ] ,
+.I " ,
+and
+.I *
+are special.
+.IP 2.
+Terminal symbols are strings of any characters surrounded by
+double quotes.
+.IP 3.
+Non-terminal symbols are strings of non-special characters.
+.IP 4.
+Alternative items are separated by a vertical bar ("\fI|\fP").
+.IP 5.
+Optional items are enclosed in brackets.
+.IP 6.
+Items are grouped together by enclosing them in parentheses.
+.IP 7.
+A
+.I *
+following an item means 0 or more occurrences of that item.
+.LP
+For example, consider the following pattern:
+.DS L
+"a " "very" (", " " very")* [" cold " "and"] " rainy " ("day" | "night")
+.DE
+.LP
+An infinite number of strings match this pattern. A few of them
+are:
+.DS
+"a very rainy day"
+"a very, very rainy day"
+"a very cold and rainy day"
+"a very, very, very cold and rainy night"
+.DE
+.NH 2
+\&Lexical Notes
+.IP 1.
+Comments begin with '/*' and terminate with '*/'.
+.IP 2.
+White space serves to separate items and is otherwise ignored.
+.IP 3.
+An identifier is a letter followed by an optional sequence of
+letters, digits or underbar ('_'). The case of identifiers is
+not ignored.
+.IP 4.
+A constant is a sequence of one or more decimal digits,
+optionally preceded by a minus-sign ('-').
+.NH 2
+\&Syntax Information
+.IX "XDR language" syntax
+.DS
+.ft CW
+declaration:
+ type-specifier identifier
+ | type-specifier identifier "[" value "]"
+ | type-specifier identifier "<" [ value ] ">"
+ | "opaque" identifier "[" value "]"
+ | "opaque" identifier "<" [ value ] ">"
+ | "string" identifier "<" [ value ] ">"
+ | type-specifier "*" identifier
+ | "void"
+.DE
+.DS
+.ft CW
+value:
+ constant
+ | identifier
+
+type-specifier:
+ [ "unsigned" ] "int"
+ | [ "unsigned" ] "hyper"
+ | "float"
+ | "double"
+ | "bool"
+ | enum-type-spec
+ | struct-type-spec
+ | union-type-spec
+ | identifier
+.DE
+.DS
+.ft CW
+enum-type-spec:
+ "enum" enum-body
+
+enum-body:
+ "{"
+ ( identifier "=" value )
+ ( "," identifier "=" value )*
+ "}"
+.DE
+.DS
+.ft CW
+struct-type-spec:
+ "struct" struct-body
+
+struct-body:
+ "{"
+ ( declaration ";" )
+ ( declaration ";" )*
+ "}"
+.DE
+.DS
+.ft CW
+union-type-spec:
+ "union" union-body
+
+union-body:
+ "switch" "(" declaration ")" "{"
+ ( "case" value ":" declaration ";" )
+ ( "case" value ":" declaration ";" )*
+ [ "default" ":" declaration ";" ]
+ "}"
+
+constant-def:
+ "const" identifier "=" constant ";"
+.DE
+.DS
+.ft CW
+type-def:
+ "typedef" declaration ";"
+ | "enum" identifier enum-body ";"
+ | "struct" identifier struct-body ";"
+ | "union" identifier union-body ";"
+
+definition:
+ type-def
+ | constant-def
+
+specification:
+ definition *
+.DE
+.NH 3
+\&Syntax Notes
+.IX "XDR language" syntax
+.LP
+.IP 1.
+The following are keywords and cannot be used as identifiers:
+"bool", "case", "const", "default", "double", "enum", "float",
+"hyper", "opaque", "string", "struct", "switch", "typedef", "union",
+"unsigned" and "void".
+.IP 2.
+Only unsigned constants may be used as size specifications for
+arrays. If an identifier is used, it must have been declared
+previously as an unsigned constant in a "const" definition.
+.IP 3.
+Constant and type identifiers within the scope of a specification
+are in the same name space and must be declared uniquely within this
+scope.
+.IP 4.
+Similarly, variable names must be unique within the scope of
+struct and union declarations. Nested struct and union declarations
+create new scopes.
+.IP 5.
+The discriminant of a union must be of a type that evaluates to
+an integer. That is, "int", "unsigned int", "bool", an enumerated
+type or any typedefed type that evaluates to one of these is legal.
+Also, the case values must be one of the legal values of the
+discriminant. Finally, a case value may not be specified more than
+once within the scope of a union declaration.
+.NH 1
+\&An Example of an XDR Data Description
+.LP
+Here is a short XDR data description of a thing called a "file",
+which might be used to transfer files from one machine to another.
+.ie t .DS
+.el .DS L
+.ft CW
+
+const MAXUSERNAME = 32; /*\fI max length of a user name \fP*/
+const MAXFILELEN = 65535; /*\fI max length of a file \fP*/
+const MAXNAMELEN = 255; /*\fI max length of a file name \fP*/
+
+.ft I
+/*
+ * Types of files:
+ */
+.ft CW
+
+enum filekind {
+ TEXT = 0, /*\fI ascii data \fP*/
+ DATA = 1, /*\fI raw data \fP*/
+ EXEC = 2 /*\fI executable \fP*/
+};
+
+.ft I
+/*
+ * File information, per kind of file:
+ */
+.ft CW
+
+union filetype switch (filekind kind) {
+ case TEXT:
+ void; /*\fI no extra information \fP*/
+ case DATA:
+ string creator<MAXNAMELEN>; /*\fI data creator \fP*/
+ case EXEC:
+ string interpretor<MAXNAMELEN>; /*\fI program interpretor \fP*/
+};
+
+.ft I
+/*
+ * A complete file:
+ */
+.ft CW
+
+struct file {
+ string filename<MAXNAMELEN>; /*\fI name of file \fP*/
+ filetype type; /*\fI info about file \fP*/
+ string owner<MAXUSERNAME>; /*\fI owner of file \fP*/
+ opaque data<MAXFILELEN>; /*\fI file data \fP*/
+};
+.DE
+.LP
+Suppose now that there is a user named "john" who wants to store
+his lisp program "sillyprog" that contains just the data "(quit)".
+His file would be encoded as follows:
+.TS
+box tab (&) ;
+lfI lfI lfI lfI
+rfL rfL rfL l .
+Offset&Hex Bytes&ASCII&Description
+_
+0&00 00 00 09&....&Length of filename = 9
+4&73 69 6c 6c&sill&Filename characters
+8&79 70 72 6f&ypro& ... and more characters ...
+12&67 00 00 00&g...& ... and 3 zero-bytes of fill
+16&00 00 00 02&....&Filekind is EXEC = 2
+20&00 00 00 04&....&Length of interpretor = 4
+24&6c 69 73 70&lisp&Interpretor characters
+28&00 00 00 04&....&Length of owner = 4
+32&6a 6f 68 6e&john&Owner characters
+36&00 00 00 06&....&Length of file data = 6
+40&28 71 75 69&(qui&File data bytes ...
+44&74 29 00 00&t)..& ... and 2 zero-bytes of fill
+.TE
+.NH 1
+\&References
+.LP
+[1] Brian W. Kernighan & Dennis M. Ritchie, "The C Programming
+Language", Bell Laboratories, Murray Hill, New Jersey, 1978.
+.LP
+[2] Danny Cohen, "On Holy Wars and a Plea for Peace", IEEE Computer,
+October 1981.
+.LP
+[3] "IEEE Standard for Binary Floating-Point Arithmetic", ANSI/IEEE
+Standard 754-1985, Institute of Electrical and Electronics
+Engineers, August 1985.
+.LP
+[4] "Courier: The Remote Procedure Call Protocol", XEROX
+Corporation, XSIS 038112, December 1981.
diff --git a/cpukit/librpc/src/rpc/README b/cpukit/librpc/src/rpc/README
new file mode 100644
index 0000000000..ad9d70f990
--- /dev/null
+++ b/cpukit/librpc/src/rpc/README
@@ -0,0 +1,233 @@
+RPCSRC 4.0 7/11/89
+
+This distribution contains Sun Microsystem's implementation of the
+RPC and XDR protocols and is compatible with 4.2BSD and 4.3BSD. Also
+included is complete documentation, utilities, RPC service
+specification files, and demonstration services in the format used by
+the RPC protocol compiler (rpcgen). See WHAT'S NEW below for
+details.
+
+NOTE ABOUT SECURE RPC:
+
+This release of RPCSRC contains most of the code needed to implement
+Secure RPC (see "DES Authentication" in the RPC Protocol Specification,
+doc/rpc.rfc.ms). Due to legal considerations, we are unable to
+distribute an implementation of DES, the Data Encryption Standard, which
+Secure RPC requires. For this reason, all of the files, documentation, and
+programs associated with Secure RPC have been placed into a separate
+directory, secure_rpc. The RPC library contained in the main body of this
+release *DOES NOT* support Secure RPC. See secure_rpc/README for more
+details. (A DES library was posted in Volume 18 of comp.sources.unix.)
+
+If you wish to report bugs found in this release, send mail to:
+
+Portable ONC/NFS
+Sun Microsystems, Inc
+MS 12-33
+2550 Garcia Avenue
+Mountain View, CA 94043
+
+or send Email to nfsnet@sun.com (the Internet) or sun!nfsnet (Usenet).
+
+ROADMAP
+
+The directory hierarchy is as follows:
+
+ demo/ Various demonstration services
+ demo/dir Remote directory lister
+ demo/msg Remote console message delivery service
+ demo/sort Remote sort service
+
+ doc/ Documentation for RPC, XDR and NFS in "-ms" format.
+
+ etc/ Utilities (rpcinfo and portmap). portmap must be
+ started by root before any other RPC network services are
+ used. SEE BELOW FOR BUGFIX TO 4.3BSD COMPILER.
+
+ man/ Manual pages for RPC library, rpcgen, and utilities.
+
+ rpc/ The RPC and XDR library. SEE BELOW
+ FOR BUGFIX TO 4.2BSD COMPILER.
+
+ rpcgen/ The RPC Language compiler (for .x files)
+
+ rpcsvc/ Service definition files for various services and the
+ server and client code for the Remote Status service.
+
+ secure_rpc/ The files in this directory are used to build a version of
+ the RPC library with DES Authentication. See the README
+ file in that directory for more details.
+
+BUILD INSTRUCTIONS
+
+Makefiles can be found in all directories except for man. The
+Makefile in the top directory will cause these others to be invoked
+(except for in the doc, man and demo directories), in turn building the
+entire release.
+
+WARNING! THE DEFAULT INSTALLATION PROCEDURES WILL INSTALL FILES
+IN /usr/include, /usr/lib, /usr/bin and /etc.
+
+The master RPC include file, rpc/rpc.h, is used by all programs and
+routines that use RPC. It includes other RPC and system include files
+needed by the RPC system. PLEASE NOTE: If your system has NFS, it
+may have been based on Sun's NFS Source. The include files installed
+by this package may duplicate include files you will find on your NFS
+system. The RPCSRC 4.0 include files are upwardly compatible to all
+NFS Source include files as of the date of this distribution (not
+including any new definitions or declarations added by your system
+vendor). HOWEVER: Please read the comments towards the end of
+rpc/rpc.h regarding rpc/netdb.h. You may need to uncomment the
+inclusion of that file if the structures it defines are already
+defined by your system's include files.
+
+After making any compiler fixes that are needed (see below), at
+the top directory, type:
+
+ make install
+
+For all installations, the Makefile macro DESTDIR is prepended to the
+installation path. It is defined to be null in the Makefiles, so
+installations are relative to root. (You will probably need root
+privileges for installing the files under the default path.) To
+install the files under some other tree (e.g., /usr/local), use the
+command:
+
+ make install DESTDIR=/usr/local
+
+This will place the include files in /usr/local/usr/include, the RPC
+library in /usr/local/usr/lib, rpcgen in /usr/local/usr/bin, and the
+utilities in /usr/local/etc. You'll have to edit the Makefiles or
+install the files by hand if you want to do anything other than this
+kind of relocation of the installation tree.
+
+The RPC library will be built and installed first. By default it is
+installed in /usr/lib as "librpclib.a". The directory
+/usr/include/rpc will also be created, and several header files will
+be installed there. ALL RPC SERVICES INCLUDE THESE HEADER FILES.
+
+The programs in etc/ link in routines from librpclib.a. If you change
+where it is installed, be sure to edit etc/'s Makefile to reflect this.
+These programs are installed in /etc. PORTMAP MUST BE RUNNING ON
+YOUR SYSTEM BEFORE YOU START ANY OTHER RPC SERVICE.
+
+rpcgen is installed in /usr/bin. This program is required to build
+the demonstration services in demo and the rstat client and server in
+rpcsvc/.
+
+The rpcsvc/ directory will install its files in the directory
+/usr/include/rpcsvc. The Remote Status service (rstat_svc) will be
+compiled and installed in /etc. If you wish to make this service
+available, you should either start this service when needed or have
+it started at boot time by invoking it in your /etc/rc.local script.
+(Be sure that portmap is started first!) Sun has modified its
+version of inetd to automatically start RPC services. (Use "make
+LIB=" when building rstat on a Sun Workstation.) The Remote Status
+client (rstat) will be installed in /usr/bin. This program queries
+the rstat_svc on a remote host and prints a system status summary
+similar to the one printed by "uptime".
+
+The documentation is not built during the "make install" command.
+Typing "make" in the doc directory will cause all of the manuals to
+be formatted using nroff into a single file. We have had a report
+that certain "troff" equivalents have trouble processing the full
+manual. If you have trouble, try building the manuals individually
+(see the Makefile).
+
+The demonstration services in the demo directory are not built by the
+top-level "make install" command. To build these, cd to the demo
+directory and enter "make". The three services will be built.
+RPCGEN MUST BE INSTALLED in a path that make can find. To run the
+services, start the portmap program as root and invoke the service
+(you probably will want to put it in the background). rpcinfo can be
+used to check that the service succeeded in getting registered with
+portmap, and to ping the service (see rpcinfo's man page). You can
+then use the corresponding client program to exercise the service.
+To build these services on a Sun workstation, you must prevent the
+Makefile from trying to link the RPC library (as these routines are
+already a part of Sun's libc). Use: "make LIB=".
+
+BUGFIX FOR 4.3BSD COMPILER
+
+The use of a 'void *' declaration for one of the arguments in
+the reply_proc() procedure in etc/rpcinfo.c will trigger a bug
+in the 4.3BSD compiler. The bug is fixed by the following change to
+the compiler file mip/manifest.h:
+
+*** manifest.h.r1.1 Thu Apr 30 13:52:25 1987
+--- manifest.h.r1.2 Mon Nov 23 18:58:17 1987
+***************
+*** 21,27 ****
+ /*
+ * Bogus type values
+ */
+! #define TNULL PTR /* pointer to UNDEF */
+ #define TVOID FTN /* function returning UNDEF (for void) */
+
+ /*
+--- 21,27 ----
+ /*
+ * Bogus type values
+ */
+! #define TNULL INCREF(MOETY) /* pointer to MOETY -- impossible type */
+ #define TVOID FTN /* function returning UNDEF (for void) */
+
+ /*
+
+If you cannot fix your compiler, change the declaration in reply_proc()
+from 'void *' to 'char *'.
+
+BUGFIX FOR 4.2BSD COMPILER
+
+Unpatched 4.2BSD compilers complain about valid C. You can make old
+compilers happy by changing some voids to ints. However, the fix to
+the 4.2 VAX compiler is as follows (to mip/trees.c):
+
+*** trees.c.r1.1 Mon May 11 13:47:58 1987
+--- trees.c.r1.2 Wed Jul 2 18:28:52 1986
+***************
+*** 1247,1253 ****
+ if(o==CAST && mt1==0)return(TYPL+TYMATCH);
+ if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH );
+ else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN );
+! else if( mt12 == 0 ) break;
+ else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN );
+ else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
+ break;
+--- 1261,1269 ----
+ if(o==CAST && mt1==0)return(TYPL+TYMATCH);
+ if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH );
+ else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN );
+! /* if right is TVOID and looks like a CALL, is not ok */
+! else if (mt2 == 0 && (p->in.right->in.op == CALL || p->in.right->in.op == UNARY CALL))
+! break;
+ else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN );
+ else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
+ break;
+
+WHAT'S NEW IN THIS RELEASE: RPCSRC 4.0
+
+The previous release was RPCSRC 3.9. As with all previous releases,
+this release is based directly on files from Sun Microsystem's
+implementation.
+
+Upgrade from RPCSRC 3.9
+
+1) RPCSRC 4.0 upgrades RPCSRC 3.9. Improvements from SunOS 4.0 have
+ been integrated into this release.
+
+Secure RPC (in the secure_rpc/ directory)
+
+2) DES Authentication routines and programs are provided.
+3) A new manual, "Secure NFS" is provided, which describes Secure RPC
+ and Secure NFS.
+4) Skeleton routines and manual pages are provided which describe the
+ DES encryption procedures required by Secure RPC. HOWEVER, NO DES
+ ROUTINE IS PROVIDED.
+
+New Functionality
+
+5) rpcinfo can now be used to de-register services from the portmapper
+ which may have terminated abnormally.
+6) A new client, rstat, is provided which queries the rstat_svc and
+ prints a status line similar to the one displayed by "uptime".
diff --git a/cpukit/librpc/src/rpc/auth_des.c b/cpukit/librpc/src/rpc/auth_des.c
new file mode 100644
index 0000000000..87d55b67e7
--- /dev/null
+++ b/cpukit/librpc/src/rpc/auth_des.c
@@ -0,0 +1,554 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1988 by Sun Microsystems, Inc.
+ */
+/*
+ * auth_des.c, client-side implementation of DES authentication
+ */
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/cdefs.h>
+#include <rpc/des_crypt.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#include <rpc/auth_des.h>
+#include <netinet/in.h> /* XXX: just to get htonl() and ntohl() */
+#include <sys/socket.h>
+#undef NIS
+#include <rpcsvc/nis.h>
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/* from: static char sccsid[] = "@(#)auth_des.c 2.2 88/07/29 4.0 RPCSRC; from 1.9 88/02/08 SMI"; */
+static const char rcsid[] = "$FreeBSD: src/lib/libc/rpc/auth_des.c,v 1.3 1999/08/28 00:00:32 peter Exp $";
+#endif
+
+extern bool_t __rpc_get_time_offset __P(( struct timeval *, nis_server *,
+ char *, char **, struct sockaddr_in * ));
+extern int rtime __P(( struct sockaddr_in *, struct timeval *, struct timeval *));
+extern bool_t xdr_authdes_cred __P(( XDR *, struct authdes_cred * ));
+extern bool_t xdr_authdes_verf __P(( XDR *, struct authdes_verf * ));
+
+#define MILLION 1000000L
+#define RTIME_TIMEOUT 5 /* seconds to wait for sync */
+
+#define AUTH_PRIVATE(auth) (struct ad_private *) auth->ah_private
+#define ALLOC(object_type) (object_type *) mem_alloc(sizeof(object_type))
+#define FREE(ptr, size) mem_free((char *)(ptr), (int) size)
+#define ATTEMPT(xdr_op) if (!(xdr_op)) return (FALSE)
+
+#define debug(msg) /*printf("%s\n", msg) */
+
+/*
+ * DES authenticator operations vector
+ */
+static void authdes_nextverf();
+static bool_t authdes_marshal();
+static bool_t authdes_validate();
+static bool_t authdes_refresh();
+static void authdes_destroy();
+static struct auth_ops authdes_ops = {
+ authdes_nextverf,
+ authdes_marshal,
+ authdes_validate,
+ authdes_refresh,
+ authdes_destroy
+};
+#ifdef foo
+static bool_t synchronize __P(( struct sockaddr *, struct timeval *));
+#endif
+/*
+ * This struct is pointed to by the ah_private field of an "AUTH *"
+ */
+struct ad_private {
+ char *ad_fullname; /* client's full name */
+ u_int ad_fullnamelen; /* length of name, rounded up */
+ char *ad_servername; /* server's full name */
+ u_int ad_servernamelen; /* length of name, rounded up */
+ u_int ad_window; /* client specified window */
+ bool_t ad_dosync; /* synchronize? */
+ struct sockaddr ad_syncaddr; /* remote host to synch with */
+ char *ad_timehost; /* remote host to synch with */
+ struct timeval ad_timediff; /* server's time - client's time */
+ u_long ad_nickname; /* server's nickname for client */
+ struct authdes_cred ad_cred; /* storage for credential */
+ struct authdes_verf ad_verf; /* storage for verifier */
+ struct timeval ad_timestamp; /* timestamp sent */
+ des_block ad_xkey; /* encrypted conversation key */
+ u_char ad_pkey[1024]; /* Server's actual public key */
+ char *ad_netid; /* Timehost netid */
+ char *ad_uaddr; /* Timehost uaddr */
+ nis_server *ad_nis_srvr; /* NIS+ server struct */
+};
+
+
+/*
+ * Create the client des authentication object
+ */
+AUTH *
+authdes_create(servername, window, syncaddr, ckey)
+ char *servername; /* network name of server */
+ u_int window; /* time to live */
+ struct sockaddr *syncaddr; /* optional addr of host to sync with */
+ des_block *ckey; /* optional conversation key to use*/
+{
+
+ AUTH *auth;
+ struct ad_private *ad;
+ char namebuf[MAXNETNAMELEN+1];
+ u_char pkey_data[1024];
+
+ if (!getpublickey(servername, pkey_data))
+ return(NULL);
+
+ /*
+ * Allocate everything now
+ */
+ auth = ALLOC(AUTH);
+ ad = ALLOC(struct ad_private);
+ (void) getnetname(namebuf);
+
+ ad->ad_fullnamelen = RNDUP(strlen(namebuf));
+ ad->ad_fullname = (char *)mem_alloc(ad->ad_fullnamelen + 1);
+
+ ad->ad_servernamelen = strlen(servername);
+ ad->ad_servername = (char *)mem_alloc(ad->ad_servernamelen + 1);
+
+ if (auth == NULL || ad == NULL || ad->ad_fullname == NULL ||
+ ad->ad_servername == NULL) {
+ debug("authdes_create: out of memory");
+ goto failed;
+ }
+
+ /*
+ * Set up private data
+ */
+ bcopy(namebuf, ad->ad_fullname, ad->ad_fullnamelen + 1);
+ bcopy(servername, ad->ad_servername, ad->ad_servernamelen + 1);
+ bcopy(pkey_data, ad->ad_pkey, strlen(pkey_data) + 1);
+ if (syncaddr != NULL) {
+ ad->ad_syncaddr = *syncaddr;
+ ad->ad_dosync = TRUE;
+ } else {
+ ad->ad_dosync = FALSE;
+ }
+ ad->ad_window = window;
+ if (ckey == NULL) {
+ if (key_gendes(&auth->ah_key) < 0) {
+ debug("authdes_create: unable to gen conversation key");
+ return (NULL);
+ }
+ } else {
+ auth->ah_key = *ckey;
+ }
+
+ /*
+ * Set up auth handle
+ */
+ auth->ah_cred.oa_flavor = AUTH_DES;
+ auth->ah_verf.oa_flavor = AUTH_DES;
+ auth->ah_ops = &authdes_ops;
+ auth->ah_private = (caddr_t)ad;
+
+ if (!authdes_refresh(auth)) {
+ goto failed;
+ }
+ return (auth);
+
+failed:
+ if (auth != NULL)
+ FREE(auth, sizeof(AUTH));
+ if (ad != NULL)
+ FREE(ad, sizeof(struct ad_private));
+ if (ad->ad_fullname != NULL)
+ FREE(ad->ad_fullname, ad->ad_fullnamelen + 1);
+ if (ad->ad_servername != NULL)
+ FREE(ad->ad_servername, ad->ad_servernamelen + 1);
+ return (NULL);
+}
+
+/*
+ * Slightly modified version of authdes_create which takes the public key
+ * of the server principal as an argument. This spares us a call to
+ * getpublickey() which in the nameserver context can cause a deadlock.
+ */
+AUTH *
+authdes_pk_create(servername, pkey, window, timehost, ckey, srvr)
+ char *servername; /* network name of server */
+ netobj *pkey; /* public key of server */
+ u_int window; /* time to live */
+ char *timehost; /* optional hostname to sync with */
+ des_block *ckey; /* optional conversation key to use */
+ nis_server *srvr; /* optional NIS+ server struct */
+{
+ AUTH *auth;
+ struct ad_private *ad;
+ char namebuf[MAXNETNAMELEN+1];
+
+ /*
+ * Allocate everything now
+ */
+ auth = ALLOC(AUTH);
+ if (auth == NULL) {
+ debug("authdes_pk_create: out of memory");
+ return (NULL);
+ }
+ ad = ALLOC(struct ad_private);
+ if (ad == NULL) {
+ debug("authdes_pk_create: out of memory");
+ goto failed;
+ }
+ ad->ad_fullname = ad->ad_servername = NULL; /* Sanity reasons */
+ ad->ad_timehost = NULL;
+ ad->ad_netid = NULL;
+ ad->ad_uaddr = NULL;
+ ad->ad_nis_srvr = NULL;
+ ad->ad_timediff.tv_sec = 0;
+ ad->ad_timediff.tv_usec = 0;
+ memcpy(ad->ad_pkey, pkey->n_bytes, pkey->n_len);
+ if (!getnetname(namebuf))
+ goto failed;
+ ad->ad_fullnamelen = RNDUP((u_int) strlen(namebuf));
+ ad->ad_fullname = (char *)mem_alloc(ad->ad_fullnamelen + 1);
+ ad->ad_servernamelen = strlen(servername);
+ ad->ad_servername = (char *)mem_alloc(ad->ad_servernamelen + 1);
+
+ if (ad->ad_fullname == NULL || ad->ad_servername == NULL) {
+ debug("authdes_pk_create: out of memory");
+ goto failed;
+ }
+ if (timehost != NULL) {
+ ad->ad_timehost = (char *)mem_alloc(strlen(timehost) + 1);
+ if (ad->ad_timehost == NULL) {
+ debug("authdes_pk_create: out of memory");
+ goto failed;
+ }
+ memcpy(ad->ad_timehost, timehost, strlen(timehost) + 1);
+ ad->ad_dosync = TRUE;
+ } else if (srvr != NULL) {
+ ad->ad_nis_srvr = srvr; /* transient */
+ ad->ad_dosync = TRUE;
+ } else {
+ ad->ad_dosync = FALSE;
+ }
+ memcpy(ad->ad_fullname, namebuf, ad->ad_fullnamelen + 1);
+ memcpy(ad->ad_servername, servername, ad->ad_servernamelen + 1);
+ ad->ad_window = window;
+ if (ckey == NULL) {
+ if (key_gendes(&auth->ah_key) < 0) {
+ debug("authdes_pk_create: unable to gen conversation key");
+ goto failed;
+ }
+ } else {
+ auth->ah_key = *ckey;
+ }
+
+ /*
+ * Set up auth handle
+ */
+ auth->ah_cred.oa_flavor = AUTH_DES;
+ auth->ah_verf.oa_flavor = AUTH_DES;
+ auth->ah_ops = &authdes_ops;
+ auth->ah_private = (caddr_t)ad;
+
+ if (!authdes_refresh(auth)) {
+ goto failed;
+ }
+ ad->ad_nis_srvr = NULL; /* not needed any longer */
+ return (auth);
+
+failed:
+ if (auth)
+ FREE(auth, sizeof (AUTH));
+ if (ad) {
+ if (ad->ad_fullname)
+ FREE(ad->ad_fullname, ad->ad_fullnamelen + 1);
+ if (ad->ad_servername)
+ FREE(ad->ad_servername, ad->ad_servernamelen + 1);
+ if (ad->ad_timehost)
+ FREE(ad->ad_timehost, strlen(ad->ad_timehost) + 1);
+ if (ad->ad_netid)
+ free(ad->ad_netid);
+ if (ad->ad_uaddr)
+ free(ad->ad_uaddr);
+ FREE(ad, sizeof (struct ad_private));
+ }
+ return (NULL);
+}
+/*
+ * Implement the five authentication operations
+ */
+
+
+/*
+ * 1. Next Verifier
+ */
+/*ARGSUSED*/
+static void
+authdes_nextverf(auth)
+ AUTH *auth;
+{
+ /* what the heck am I supposed to do??? */
+}
+
+
+
+/*
+ * 2. Marshal
+ */
+static bool_t
+authdes_marshal(auth, xdrs)
+ AUTH *auth;
+ XDR *xdrs;
+{
+ struct ad_private *ad = AUTH_PRIVATE(auth);
+ struct authdes_cred *cred = &ad->ad_cred;
+ struct authdes_verf *verf = &ad->ad_verf;
+ des_block cryptbuf[2];
+ des_block ivec;
+ int status;
+ long len;
+ int32_t *ixdr;
+
+ /*
+ * Figure out the "time", accounting for any time difference
+ * with the server if necessary.
+ */
+ (void) gettimeofday(&ad->ad_timestamp, (struct timezone *)NULL);
+ ad->ad_timestamp.tv_sec += ad->ad_timediff.tv_sec;
+ ad->ad_timestamp.tv_usec += ad->ad_timediff.tv_usec;
+ if (ad->ad_timestamp.tv_usec >= MILLION) {
+ ad->ad_timestamp.tv_usec -= MILLION;
+ ad->ad_timestamp.tv_sec += 1;
+ }
+
+ /*
+ * XDR the timestamp and possibly some other things, then
+ * encrypt them.
+ */
+ ixdr = (int32_t *)cryptbuf;
+ IXDR_PUT_LONG(ixdr, ad->ad_timestamp.tv_sec);
+ IXDR_PUT_LONG(ixdr, ad->ad_timestamp.tv_usec);
+ if (ad->ad_cred.adc_namekind == ADN_FULLNAME) {
+ IXDR_PUT_U_LONG(ixdr, ad->ad_window);
+ IXDR_PUT_U_LONG(ixdr, ad->ad_window - 1);
+ ivec.key.high = ivec.key.low = 0;
+ status = cbc_crypt((char *)&auth->ah_key, (char *)cryptbuf,
+ 2*sizeof(des_block), DES_ENCRYPT | DES_HW, (char *)&ivec);
+ } else {
+ status = ecb_crypt((char *)&auth->ah_key, (char *)cryptbuf,
+ sizeof(des_block), DES_ENCRYPT | DES_HW);
+ }
+ if (DES_FAILED(status)) {
+ debug("authdes_marshal: DES encryption failure");
+ return (FALSE);
+ }
+ ad->ad_verf.adv_xtimestamp = cryptbuf[0];
+ if (ad->ad_cred.adc_namekind == ADN_FULLNAME) {
+ ad->ad_cred.adc_fullname.window = cryptbuf[1].key.high;
+ ad->ad_verf.adv_winverf = cryptbuf[1].key.low;
+ } else {
+ ad->ad_cred.adc_nickname = ad->ad_nickname;
+ ad->ad_verf.adv_winverf = 0;
+ }
+
+ /*
+ * Serialize the credential and verifier into opaque
+ * authentication data.
+ */
+ if (ad->ad_cred.adc_namekind == ADN_FULLNAME) {
+ len = ((1 + 1 + 2 + 1)*BYTES_PER_XDR_UNIT + ad->ad_fullnamelen);
+ } else {
+ len = (1 + 1)*BYTES_PER_XDR_UNIT;
+ }
+
+ if ((ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT))) {
+ IXDR_PUT_LONG(ixdr, AUTH_DES);
+ IXDR_PUT_LONG(ixdr, len);
+ } else {
+ ATTEMPT(xdr_putlong(xdrs, (long *)&auth->ah_cred.oa_flavor));
+ ATTEMPT(xdr_putlong(xdrs, &len));
+ }
+ ATTEMPT(xdr_authdes_cred(xdrs, cred));
+
+ len = (2 + 1)*BYTES_PER_XDR_UNIT;
+ if ((ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT))) {
+ IXDR_PUT_LONG(ixdr, AUTH_DES);
+ IXDR_PUT_LONG(ixdr, len);
+ } else {
+ ATTEMPT(xdr_putlong(xdrs, (long *)&auth->ah_verf.oa_flavor));
+ ATTEMPT(xdr_putlong(xdrs, &len));
+ }
+ ATTEMPT(xdr_authdes_verf(xdrs, verf));
+ return (TRUE);
+}
+
+
+/*
+ * 3. Validate
+ */
+static bool_t
+authdes_validate(auth, rverf)
+ AUTH *auth;
+ struct opaque_auth *rverf;
+{
+ struct ad_private *ad = AUTH_PRIVATE(auth);
+ struct authdes_verf verf;
+ int status;
+ register u_long *ixdr;
+
+ if (rverf->oa_length != (2 + 1) * BYTES_PER_XDR_UNIT) {
+ return (FALSE);
+ }
+ ixdr = (u_long *)rverf->oa_base;
+ verf.adv_xtimestamp.key.high = (u_long)*ixdr++;
+ verf.adv_xtimestamp.key.low = (u_long)*ixdr++;
+ verf.adv_int_u = (u_long)*ixdr++; /* nickname not XDR'd ! */
+
+ /*
+ * Decrypt the timestamp
+ */
+ status = ecb_crypt((char *)&auth->ah_key, (char *)&verf.adv_xtimestamp,
+ sizeof(des_block), DES_DECRYPT | DES_HW);
+
+ if (DES_FAILED(status)) {
+ debug("authdes_validate: DES decryption failure");
+ return (FALSE);
+ }
+
+ /*
+ * xdr the decrypted timestamp
+ */
+ ixdr = (u_long *)verf.adv_xtimestamp.c;
+ verf.adv_timestamp.tv_sec = IXDR_GET_LONG(ixdr) + 1;
+ verf.adv_timestamp.tv_usec = IXDR_GET_LONG(ixdr);
+
+ /*
+ * validate
+ */
+ if (bcmp((char *)&ad->ad_timestamp, (char *)&verf.adv_timestamp,
+ sizeof(struct timeval)) != 0) {
+ debug("authdes_validate: verifier mismatch\n");
+ return (FALSE);
+ }
+
+ /*
+ * We have a nickname now, let's use it
+ */
+ ad->ad_nickname = verf.adv_nickname;
+ ad->ad_cred.adc_namekind = ADN_NICKNAME;
+ return (TRUE);
+}
+
+/*
+ * 4. Refresh
+ */
+static bool_t
+authdes_refresh(auth)
+ AUTH *auth;
+{
+ struct ad_private *ad = AUTH_PRIVATE(auth);
+ struct authdes_cred *cred = &ad->ad_cred;
+ netobj pkey;
+
+ if (ad->ad_dosync &&
+#ifdef old
+ !synchronize(&ad->ad_syncaddr, &ad->ad_timediff)) {
+#else
+ !__rpc_get_time_offset(&ad->ad_timediff,ad->ad_nis_srvr,
+ ad->ad_timehost, &(ad->ad_uaddr),
+ (struct sockaddr_in *)&(ad->ad_syncaddr))) {
+#endif
+ /*
+ * Hope the clocks are synced!
+ */
+ ad->ad_timediff.tv_sec = ad->ad_timediff.tv_usec = 0;
+ ad->ad_dosync = 0;
+ debug("authdes_refresh: unable to synchronize with server");
+ }
+ ad->ad_xkey = auth->ah_key;
+ pkey.n_bytes = (char *)(ad->ad_pkey);
+ pkey.n_len = strlen((char *)ad->ad_pkey) + 1;
+ if (key_encryptsession_pk(ad->ad_servername, &pkey, &ad->ad_xkey) < 0) {
+ debug("authdes_create: unable to encrypt conversation key");
+ return (FALSE);
+ }
+ cred->adc_fullname.key = ad->ad_xkey;
+ cred->adc_namekind = ADN_FULLNAME;
+ cred->adc_fullname.name = ad->ad_fullname;
+ return (TRUE);
+}
+
+
+/*
+ * 5. Destroy
+ */
+static void
+authdes_destroy(auth)
+ AUTH *auth;
+{
+ struct ad_private *ad = AUTH_PRIVATE(auth);
+
+ FREE(ad->ad_fullname, ad->ad_fullnamelen + 1);
+ FREE(ad->ad_servername, ad->ad_servernamelen + 1);
+ FREE(ad, sizeof(struct ad_private));
+ FREE(auth, sizeof(AUTH));
+}
+
+
+#ifdef old
+/*
+ * Synchronize with the server at the given address, that is,
+ * adjust timep to reflect the delta between our clocks
+ */
+static bool_t
+synchronize(syncaddr, timep)
+ struct sockaddr *syncaddr;
+ struct timeval *timep;
+{
+ struct timeval mytime;
+ struct timeval timeout;
+
+ timeout.tv_sec = RTIME_TIMEOUT;
+ timeout.tv_usec = 0;
+ if (rtime((struct sockaddr_in *)syncaddr, timep, NULL /*&timeout*/) < 0) {
+ return (FALSE);
+ }
+ (void) gettimeofday(&mytime, (struct timezone *)NULL);
+ timep->tv_sec -= mytime.tv_sec;
+ if (mytime.tv_usec > timep->tv_usec) {
+ timep->tv_sec -= 1;
+ timep->tv_usec += MILLION;
+ }
+ timep->tv_usec -= mytime.tv_usec;
+ return (TRUE);
+}
+#endif
diff --git a/cpukit/librpc/src/rpc/auth_none.c b/cpukit/librpc/src/rpc/auth_none.c
new file mode 100644
index 0000000000..9b08699ea8
--- /dev/null
+++ b/cpukit/librpc/src/rpc/auth_none.c
@@ -0,0 +1,136 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)auth_none.c 1.19 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)auth_none.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/rpc/auth_none.c,v 1.9 1999/08/28 00:00:32 peter Exp $";
+#endif
+
+/*
+ * auth_none.c
+ * Creates a client authentication handle for passing "null"
+ * credentials and verifiers to remote systems.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <stdlib.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#define MAX_MARSHEL_SIZE 20
+
+/*
+ * Authenticator operations routines
+ */
+static void authnone_verf();
+static void authnone_destroy();
+static bool_t authnone_marshal();
+static bool_t authnone_validate();
+static bool_t authnone_refresh();
+
+static struct auth_ops ops = {
+ authnone_verf,
+ authnone_marshal,
+ authnone_validate,
+ authnone_refresh,
+ authnone_destroy
+};
+
+static struct authnone_private {
+ AUTH no_client;
+ char marshalled_client[MAX_MARSHEL_SIZE];
+ u_int mcnt;
+} *authnone_private;
+
+AUTH *
+authnone_create()
+{
+ register struct authnone_private *ap = authnone_private;
+ XDR xdr_stream;
+ register XDR *xdrs;
+
+ if (ap == 0) {
+ ap = (struct authnone_private *)calloc(1, sizeof (*ap));
+ if (ap == 0)
+ return (0);
+ authnone_private = ap;
+ }
+ if (!ap->mcnt) {
+ ap->no_client.ah_cred = ap->no_client.ah_verf = _null_auth;
+ ap->no_client.ah_ops = &ops;
+ xdrs = &xdr_stream;
+ xdrmem_create(xdrs, ap->marshalled_client, (u_int)MAX_MARSHEL_SIZE,
+ XDR_ENCODE);
+ (void)xdr_opaque_auth(xdrs, &ap->no_client.ah_cred);
+ (void)xdr_opaque_auth(xdrs, &ap->no_client.ah_verf);
+ ap->mcnt = XDR_GETPOS(xdrs);
+ XDR_DESTROY(xdrs);
+ }
+ return (&ap->no_client);
+}
+
+/*ARGSUSED*/
+static bool_t
+authnone_marshal(client, xdrs)
+ AUTH *client;
+ XDR *xdrs;
+{
+ register struct authnone_private *ap = authnone_private;
+
+ if (ap == 0)
+ return (0);
+ return ((*xdrs->x_ops->x_putbytes)(xdrs,
+ ap->marshalled_client, ap->mcnt));
+}
+
+static void
+authnone_verf()
+{
+}
+
+static bool_t
+authnone_validate()
+{
+
+ return (TRUE);
+}
+
+static bool_t
+authnone_refresh()
+{
+
+ return (FALSE);
+}
+
+static void
+authnone_destroy()
+{
+}
diff --git a/cpukit/librpc/src/rpc/auth_time.c b/cpukit/librpc/src/rpc/auth_time.c
new file mode 100644
index 0000000000..ab3277c4df
--- /dev/null
+++ b/cpukit/librpc/src/rpc/auth_time.c
@@ -0,0 +1,503 @@
+#pragma ident "@(#)auth_time.c 1.4 92/11/10 SMI"
+
+/*
+ * auth_time.c
+ *
+ * This module contains the private function __rpc_get_time_offset()
+ * which will return the difference in seconds between the local system's
+ * notion of time and a remote server's notion of time. This must be
+ * possible without calling any functions that may invoke the name
+ * service. (netdir_getbyxxx, getXbyY, etc). The function is used in the
+ * synchronize call of the authdes code to synchronize clocks between
+ * NIS+ clients and their servers.
+ *
+ * Note to minimize the amount of duplicate code, portions of the
+ * synchronize() function were folded into this code, and the synchronize
+ * call becomes simply a wrapper around this function. Further, if this
+ * function is called with a timehost it *DOES* recurse to the name
+ * server so don't use it in that mode if you are doing name service code.
+ *
+ * Copyright (c) 1992 Sun Microsystems Inc.
+ * All rights reserved.
+ *
+ * Side effects :
+ * When called a client handle to a RPCBIND process is created
+ * and destroyed. Two strings "netid" and "uaddr" are malloc'd
+ * and returned. The SIGALRM processing is modified only if
+ * needed to deal with TCP connections.
+ *
+ * NOTE: This code has had the crap beaten out it in order to convert
+ * it from TI-RPC back to TD-RPC for use on FreeBSD.
+ *
+ * $FreeBSD: src/lib/libc/rpc/auth_time.c,v 1.4 2000/01/27 23:06:35 jasone Exp $
+ */
+#include <stdio.h>
+#include <syslog.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <sys/signal.h>
+#include <sys/errno.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <rpc/rpc.h>
+#include <rpc/rpc_com.h>
+#undef NIS
+#include <rpcsvc/nis.h>
+
+/*
+ * FreeBSD currently uses RPC 4.0, which uses portmap rather than
+ * rpcbind. Consequently, we need to fake up these values here.
+ * Luckily, the RPCB_GETTIME procedure uses only base XDR data types
+ * so we don't need anything besides these magic numbers.
+ */
+#define RPCBPROG (u_long)100000
+#define RPCBVERS (u_long)3
+#define RPCBPROC_GETTIME (u_long)6
+
+#ifdef TESTING
+#define msg(x) printf("ERROR: %s\n", x)
+/* #define msg(x) syslog(LOG_ERR, "%s", x) */
+#else
+#define msg(x)
+#endif
+
+static int saw_alarm = 0;
+
+static void
+alarm_hndler(s)
+ int s;
+{
+ saw_alarm = 1;
+ return;
+}
+
+/*
+ * The internet time server defines the epoch to be Jan 1, 1900
+ * whereas UNIX defines it to be Jan 1, 1970. To adjust the result
+ * from internet time-service time, into UNIX time we subtract the
+ * following offset :
+ */
+#define NYEARS (1970 - 1900)
+#define TOFFSET ((u_long)60*60*24*(365*NYEARS + (NYEARS/4)))
+
+
+/*
+ * Stolen from rpc.nisd:
+ * Turn a 'universal address' into a struct sockaddr_in.
+ * Bletch.
+ */
+static int uaddr_to_sockaddr(uaddr, sin)
+#ifdef foo
+ endpoint *endpt;
+#endif
+ char *uaddr;
+ struct sockaddr_in *sin;
+{
+ unsigned char p_bytes[2];
+ int i;
+ unsigned long a[6];
+
+ i = sscanf(uaddr, "%lu.%lu.%lu.%lu.%lu.%lu", &a[0], &a[1], &a[2],
+ &a[3], &a[4], &a[5]);
+
+ if (i < 6)
+ return(1);
+
+ for (i = 0; i < 4; i++)
+ sin->sin_addr.s_addr |= (a[i] & 0x000000FF) << (8 * i);
+
+ p_bytes[0] = (unsigned char)a[4] & 0x000000FF;
+ p_bytes[1] = (unsigned char)a[5] & 0x000000FF;
+
+ sin->sin_family = AF_INET; /* always */
+ bcopy((char *)&p_bytes, (char *)&sin->sin_port, 2);
+
+ return (0);
+}
+
+/*
+ * free_eps()
+ *
+ * Free the strings that were strduped into the eps structure.
+ */
+static void
+free_eps(eps, num)
+ endpoint eps[];
+ int num;
+{
+ int i;
+
+ for (i = 0; i < num; i++) {
+ free(eps[i].uaddr);
+ free(eps[i].proto);
+ free(eps[i].family);
+ }
+ return;
+}
+
+/*
+ * get_server()
+ *
+ * This function constructs a nis_server structure description for the
+ * indicated hostname.
+ *
+ * NOTE: There is a chance we may end up recursing here due to the
+ * fact that gethostbyname() could do an NIS search. Ideally, the
+ * NIS+ server will call __rpc_get_time_offset() with the nis_server
+ * structure already populated.
+ */
+static nis_server *
+get_server(sin, host, srv, eps, maxep)
+ struct sockaddr_in *sin;
+ char *host; /* name of the time host */
+ nis_server *srv; /* nis_server struct to use. */
+ endpoint eps[]; /* array of endpoints */
+ int maxep; /* max array size */
+{
+ char hname[256];
+ int num_ep = 0, i;
+ struct hostent *he;
+ struct hostent dummy;
+ char *ptr[2];
+
+ if (host == NULL && sin == NULL)
+ return (NULL);
+
+ if (sin == NULL) {
+ he = gethostbyname(host);
+ if (he == NULL)
+ return(NULL);
+ } else {
+ he = &dummy;
+ ptr[0] = (char *)&sin->sin_addr.s_addr;
+ ptr[1] = NULL;
+ dummy.h_addr_list = ptr;
+ }
+
+ /*
+ * This is lame. We go around once for TCP, then again
+ * for UDP.
+ */
+ for (i = 0; (he->h_addr_list[i] != NULL) && (num_ep < maxep);
+ i++, num_ep++) {
+ struct in_addr *a;
+
+ a = (struct in_addr *)he->h_addr_list[i];
+ snprintf(hname, sizeof(hname), "%s.0.111", inet_ntoa(*a));
+ eps[num_ep].uaddr = strdup(hname);
+ eps[num_ep].family = strdup("inet");
+ eps[num_ep].proto = strdup("tcp");
+ }
+
+ for (i = 0; (he->h_addr_list[i] != NULL) && (num_ep < maxep);
+ i++, num_ep++) {
+ struct in_addr *a;
+
+ a = (struct in_addr *)he->h_addr_list[i];
+ snprintf(hname, sizeof(hname), "%s.0.111", inet_ntoa(*a));
+ eps[num_ep].uaddr = strdup(hname);
+ eps[num_ep].family = strdup("inet");
+ eps[num_ep].proto = strdup("udp");
+ }
+
+ srv->name = (nis_name) host;
+ srv->ep.ep_len = num_ep;
+ srv->ep.ep_val = eps;
+ srv->key_type = NIS_PK_NONE;
+ srv->pkey.n_bytes = NULL;
+ srv->pkey.n_len = 0;
+ return (srv);
+}
+
+/*
+ * __rpc_get_time_offset()
+ *
+ * This function uses a nis_server structure to contact the a remote
+ * machine (as named in that structure) and returns the offset in time
+ * between that machine and this one. This offset is returned in seconds
+ * and may be positive or negative.
+ *
+ * The first time through, a lot of fiddling is done with the netconfig
+ * stuff to find a suitable transport. The function is very aggressive
+ * about choosing UDP or at worst TCP if it can. This is because
+ * those transports support both the RCPBIND call and the internet
+ * time service.
+ *
+ * Once through, *uaddr is set to the universal address of
+ * the machine and *netid is set to the local netid for the transport
+ * that uaddr goes with. On the second call, the netconfig stuff
+ * is skipped and the uaddr/netid pair are used to fetch the netconfig
+ * structure and to then contact the machine for the time.
+ *
+ * td = "server" - "client"
+ */
+int
+__rpc_get_time_offset(td, srv, thost, uaddr, netid)
+ struct timeval *td; /* Time difference */
+ nis_server *srv; /* NIS Server description */
+ char *thost; /* if no server, this is the timehost */
+ char **uaddr; /* known universal address */
+ struct sockaddr_in *netid; /* known network identifier */
+{
+ CLIENT *clnt; /* Client handle */
+ endpoint *ep, /* useful endpoints */
+ *useep = NULL; /* endpoint of xp */
+ char *useua = NULL; /* uaddr of selected xp */
+ int epl, i; /* counters */
+ enum clnt_stat status; /* result of clnt_call */
+ u_long thetime, delta;
+ int needfree = 0;
+ struct timeval tv;
+ int time_valid;
+ int udp_ep = -1, tcp_ep = -1;
+ int a1, a2, a3, a4;
+ char ut[64], ipuaddr[64];
+ endpoint teps[32];
+ nis_server tsrv;
+ void (*oldsig)() = NULL; /* old alarm handler */
+ struct sockaddr_in sin;
+ int s = RPC_ANYSOCK, len;
+ int type = 0;
+
+ td->tv_sec = 0;
+ td->tv_usec = 0;
+
+ /*
+ * First check to see if we need to find and address for this
+ * server.
+ */
+ if (*uaddr == NULL) {
+ if ((srv != NULL) && (thost != NULL)) {
+ msg("both timehost and srv pointer used!");
+ return (0);
+ }
+ if (! srv) {
+ srv = get_server(netid, thost, &tsrv, teps, 32);
+ if (srv == NULL) {
+ msg("unable to contruct server data.");
+ return (0);
+ }
+ needfree = 1; /* need to free data in endpoints */
+ }
+
+ ep = srv->ep.ep_val;
+ epl = srv->ep.ep_len;
+
+ /* Identify the TCP and UDP endpoints */
+ for (i = 0;
+ (i < epl) && ((udp_ep == -1) || (tcp_ep == -1)); i++) {
+ if (strcasecmp(ep[i].proto, "udp") == 0)
+ udp_ep = i;
+ if (strcasecmp(ep[i].proto, "tcp") == 0)
+ tcp_ep = i;
+ }
+
+ /* Check to see if it is UDP or TCP */
+ if (tcp_ep > -1) {
+ useep = &ep[tcp_ep];
+ useua = ep[tcp_ep].uaddr;
+ type = SOCK_STREAM;
+ } else if (udp_ep > -1) {
+ useep = &ep[udp_ep];
+ useua = ep[udp_ep].uaddr;
+ type = SOCK_DGRAM;
+ }
+
+ if (useep == NULL) {
+ msg("no acceptable transport endpoints.");
+ if (needfree)
+ free_eps(teps, tsrv.ep.ep_len);
+ return (0);
+ }
+ }
+
+ /*
+ * Create a sockaddr from the uaddr.
+ */
+ if (*uaddr != NULL)
+ useua = *uaddr;
+
+ /* Fixup test for NIS+ */
+ sscanf(useua, "%d.%d.%d.%d.", &a1, &a2, &a3, &a4);
+ sprintf(ipuaddr, "%d.%d.%d.%d.0.111", a1, a2, a3, a4);
+ useua = &ipuaddr[0];
+
+ bzero((char *)&sin, sizeof(sin));
+ if (uaddr_to_sockaddr(useua, &sin)) {
+ msg("unable to translate uaddr to sockaddr.");
+ if (needfree)
+ free_eps(teps, tsrv.ep.ep_len);
+ return (0);
+ }
+
+ /*
+ * Create the client handle to rpcbind. Note we always try
+ * version 3 since that is the earliest version that supports
+ * the RPCB_GETTIME call. Also it is the version that comes
+ * standard with SVR4. Since most everyone supports TCP/IP
+ * we could consider trying the rtime call first.
+ */
+ clnt = clnttcp_create(&sin, RPCBPROG, RPCBVERS, &s, 0, 0);
+ if (clnt == NULL) {
+ msg("unable to create client handle to rpcbind.");
+ if (needfree)
+ free_eps(teps, tsrv.ep.ep_len);
+ return (0);
+ }
+
+ tv.tv_sec = 5;
+ tv.tv_usec = 0;
+ time_valid = 0;
+ status = clnt_call(clnt, RPCBPROC_GETTIME, xdr_void, NULL,
+ xdr_u_long, (char *)&thetime, tv);
+ /*
+ * The only error we check for is anything but success. In
+ * fact we could have seen PROGMISMATCH if talking to a 4.1
+ * machine (pmap v2) or TIMEDOUT if the net was busy.
+ */
+ if (status == RPC_SUCCESS)
+ time_valid = 1;
+ else {
+ int save;
+
+ /* Blow away possible stale CLNT handle. */
+ if (clnt != NULL) {
+ clnt_destroy(clnt);
+ clnt = NULL;
+ }
+
+ /*
+ * Convert PMAP address into timeservice address
+ * We take advantage of the fact that we "know" what
+ * the universal address looks like for inet transports.
+ *
+ * We also know that the internet timeservice is always
+ * listening on port 37.
+ */
+ sscanf(useua, "%d.%d.%d.%d.", &a1, &a2, &a3, &a4);
+ sprintf(ut, "%d.%d.%d.%d.0.37", a1, a2, a3, a4);
+
+ if (uaddr_to_sockaddr(ut, &sin)) {
+ msg("cannot convert timeservice uaddr to sockaddr.");
+ goto error;
+ }
+
+ s = socket(AF_INET, type, 0);
+ if (s == -1) {
+ msg("unable to open fd to network.");
+ goto error;
+ }
+
+ /*
+ * Now depending on whether or not we're talking to
+ * UDP we set a timeout or not.
+ */
+ if (type == SOCK_DGRAM) {
+ struct timeval timeout = { 20, 0 };
+ struct sockaddr_in from;
+ fd_set readfds;
+ int res;
+
+ if (sendto(s, &thetime, sizeof(thetime), 0,
+ (struct sockaddr *)&sin, sizeof(sin)) == -1) {
+ msg("udp : sendto failed.");
+ goto error;
+ }
+ do {
+ FD_ZERO(&readfds);
+ FD_SET(s, &readfds);
+ res = select(_rpc_dtablesize(), &readfds,
+ (fd_set *)NULL, (fd_set *)NULL, &timeout);
+ } while (res < 0 && errno == EINTR);
+ if (res <= 0)
+ goto error;
+ len = sizeof(from);
+ res = recvfrom(s, (char *)&thetime, sizeof(thetime), 0,
+ (struct sockaddr *)&from, &len);
+ if (res == -1) {
+ msg("recvfrom failed on udp transport.");
+ goto error;
+ }
+ time_valid = 1;
+ } else {
+ int res;
+
+ oldsig = (void (*)())signal(SIGALRM, alarm_hndler);
+ saw_alarm = 0; /* global tracking the alarm */
+ alarm(20); /* only wait 20 seconds */
+ res = connect(s, (struct sockaddr *)&sin, sizeof(sin));
+ if (res == -1) {
+ msg("failed to connect to tcp endpoint.");
+ goto error;
+ }
+ if (saw_alarm) {
+ msg("alarm caught it, must be unreachable.");
+ goto error;
+ }
+ res = _RPC_read(s, (char *)&thetime, sizeof(thetime));
+ if (res != sizeof(thetime)) {
+ if (saw_alarm)
+ msg("timed out TCP call.");
+ else
+ msg("wrong size of results returned");
+
+ goto error;
+ }
+ time_valid = 1;
+ }
+ save = errno;
+ (void)_RPC_close(s);
+ errno = save;
+ s = RPC_ANYSOCK;
+
+ if (time_valid) {
+ thetime = ntohl(thetime);
+ thetime = thetime - TOFFSET; /* adjust to UNIX time */
+ } else
+ thetime = 0;
+ }
+
+ gettimeofday(&tv, 0);
+
+error:
+ /*
+ * clean up our allocated data structures.
+ */
+
+ if (s != RPC_ANYSOCK)
+ (void)_RPC_close(s);
+
+ if (clnt != NULL)
+ clnt_destroy(clnt);
+
+ alarm(0); /* reset that alarm if its outstanding */
+ if (oldsig) {
+ signal(SIGALRM, oldsig);
+ }
+
+ /*
+ * note, don't free uaddr strings until after we've made a
+ * copy of them.
+ */
+ if (time_valid) {
+ if (*uaddr == NULL)
+ *uaddr = strdup(useua);
+
+ /* Round to the nearest second */
+ tv.tv_sec += (tv.tv_sec > 500000) ? 1 : 0;
+ delta = (thetime > tv.tv_sec) ? thetime - tv.tv_sec :
+ tv.tv_sec - thetime;
+ td->tv_sec = (thetime < tv.tv_sec) ? - delta : delta;
+ td->tv_usec = 0;
+ } else {
+ msg("unable to get the server's time.");
+ }
+
+ if (needfree)
+ free_eps(teps, tsrv.ep.ep_len);
+
+ return (time_valid);
+}
diff --git a/cpukit/librpc/src/rpc/auth_unix.c b/cpukit/librpc/src/rpc/auth_unix.c
new file mode 100644
index 0000000000..885c92a206
--- /dev/null
+++ b/cpukit/librpc/src/rpc/auth_unix.c
@@ -0,0 +1,349 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)auth_unix.c 1.19 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)auth_unix.c 2.2 88/08/01 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/rpc/auth_unix.c,v 1.12 1999/12/29 05:04:16 peter Exp $";
+#endif
+
+/*
+ * auth_unix.c, Implements UNIX style authentication parameters.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * The system is very weak. The client uses no encryption for it's
+ * credentials and only sends null verifiers. The server sends backs
+ * null verifiers or optionally a verifier that suggests a new short hand
+ * for the credentials.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <sys/param.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#include <rpc/auth_unix.h>
+
+/*
+ * Unix authenticator operations vector
+ */
+static void authunix_nextverf();
+static bool_t authunix_marshal();
+static bool_t authunix_validate();
+static bool_t authunix_refresh();
+static void authunix_destroy();
+
+static struct auth_ops auth_unix_ops = {
+ authunix_nextverf,
+ authunix_marshal,
+ authunix_validate,
+ authunix_refresh,
+ authunix_destroy
+};
+
+/*
+ * This struct is pointed to by the ah_private field of an auth_handle.
+ */
+struct audata {
+ struct opaque_auth au_origcred; /* original credentials */
+ struct opaque_auth au_shcred; /* short hand cred */
+ u_long au_shfaults; /* short hand cache faults */
+ char au_marshed[MAX_AUTH_BYTES];
+ u_int au_mpos; /* xdr pos at end of marshed */
+};
+#define AUTH_PRIVATE(auth) ((struct audata *)auth->ah_private)
+
+static void marshal_new_auth();
+
+/*
+ * This goop is here because some servers refuse to accept a
+ * credential with more than some number (usually 8) supplementary
+ * groups. Blargh!
+ */
+static int authunix_maxgrouplist = 0;
+
+void
+set_rpc_maxgrouplist(int num)
+{
+ authunix_maxgrouplist = num;
+}
+
+/*
+ * Create a unix style authenticator.
+ * Returns an auth handle with the given stuff in it.
+ */
+AUTH *
+authunix_create(machname, uid, gid, len, aup_gids)
+ char *machname;
+ int uid;
+ int gid;
+ register int len;
+ int *aup_gids;
+{
+ struct authunix_parms aup;
+ char mymem[MAX_AUTH_BYTES];
+ struct timeval now;
+ XDR xdrs;
+ register AUTH *auth;
+ register struct audata *au;
+
+ /*
+ * Allocate and set up auth handle
+ */
+ auth = (AUTH *)mem_alloc(sizeof(*auth));
+#ifndef _KERNEL
+ if (auth == NULL) {
+ (void)fprintf(stderr, "authunix_create: out of memory\n");
+ return (NULL);
+ }
+#endif
+ au = (struct audata *)mem_alloc(sizeof(*au));
+#ifndef _KERNEL
+ if (au == NULL) {
+ (void)fprintf(stderr, "authunix_create: out of memory\n");
+ return (NULL);
+ }
+#endif
+ auth->ah_ops = &auth_unix_ops;
+ auth->ah_private = (caddr_t)au;
+ auth->ah_verf = au->au_shcred = _null_auth;
+ au->au_shfaults = 0;
+
+ /*
+ * fill in param struct from the given params
+ */
+ (void)gettimeofday(&now, (struct timezone *)0);
+ aup.aup_time = now.tv_sec;
+ aup.aup_machname = machname;
+ aup.aup_uid = uid;
+ aup.aup_gid = gid;
+ /* GW: continuation of max group list hack */
+ if(authunix_maxgrouplist != 0) {
+ aup.aup_len = ((len < authunix_maxgrouplist) ? len
+ : authunix_maxgrouplist);
+ } else {
+ aup.aup_len = (u_int)len;
+ }
+ aup.aup_gids = aup_gids;
+
+ /*
+ * Serialize the parameters into origcred
+ */
+ xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
+ if (! xdr_authunix_parms(&xdrs, &aup))
+ abort();
+ au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs);
+ au->au_origcred.oa_flavor = AUTH_UNIX;
+#ifdef _KERNEL
+ au->au_origcred.oa_base = mem_alloc((u_int) len);
+#else
+ if ((au->au_origcred.oa_base = mem_alloc((u_int) len)) == NULL) {
+ (void)fprintf(stderr, "authunix_create: out of memory\n");
+ return (NULL);
+ }
+#endif
+ memcpy(au->au_origcred.oa_base, mymem, (u_int)len);
+
+ /*
+ * set auth handle to reflect new cred.
+ */
+ auth->ah_cred = au->au_origcred;
+ marshal_new_auth(auth);
+ return (auth);
+}
+
+/*
+ * Returns an auth handle with parameters determined by doing lots of
+ * syscalls.
+ */
+AUTH *
+authunix_create_default()
+{
+ register int len;
+ char machname[MAX_MACHINE_NAME + 1];
+ register int uid;
+ register int gid;
+ int gids[NGRPS];
+ int i;
+ gid_t real_gids[NGROUPS];
+
+ if (gethostname(machname, MAX_MACHINE_NAME) == -1)
+ abort();
+ machname[MAX_MACHINE_NAME] = 0;
+ uid = (int)geteuid();
+ gid = (int)getegid();
+ if ((len = getgroups(NGROUPS, real_gids)) < 0)
+ abort();
+ if(len > NGRPS) len = NGRPS; /* GW: turn `gid_t's into `int's */
+ for(i = 0; i < len; i++) {
+ gids[i] = (int)real_gids[i];
+ }
+ return (authunix_create(machname, uid, gid, len, gids));
+}
+
+/*
+ * authunix operations
+ */
+
+static void
+authunix_nextverf(auth)
+ AUTH *auth;
+{
+ /* no action necessary */
+}
+
+static bool_t
+authunix_marshal(auth, xdrs)
+ AUTH *auth;
+ XDR *xdrs;
+{
+ register struct audata *au = AUTH_PRIVATE(auth);
+
+ return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos));
+}
+
+static bool_t
+authunix_validate(auth, verf)
+ register AUTH *auth;
+ struct opaque_auth verf;
+{
+ register struct audata *au;
+ XDR xdrs;
+
+ if (verf.oa_flavor == AUTH_SHORT) {
+ au = AUTH_PRIVATE(auth);
+ xdrmem_create(&xdrs, verf.oa_base, verf.oa_length, XDR_DECODE);
+
+ if (au->au_shcred.oa_base != NULL) {
+ mem_free(au->au_shcred.oa_base,
+ au->au_shcred.oa_length);
+ au->au_shcred.oa_base = NULL;
+ }
+ if (xdr_opaque_auth(&xdrs, &au->au_shcred)) {
+ auth->ah_cred = au->au_shcred;
+ } else {
+ xdrs.x_op = XDR_FREE;
+ (void)xdr_opaque_auth(&xdrs, &au->au_shcred);
+ au->au_shcred.oa_base = NULL;
+ auth->ah_cred = au->au_origcred;
+ }
+ marshal_new_auth(auth);
+ }
+ return (TRUE);
+}
+
+static bool_t
+authunix_refresh(auth)
+ register AUTH *auth;
+{
+ register struct audata *au = AUTH_PRIVATE(auth);
+ struct authunix_parms aup;
+ struct timeval now;
+ XDR xdrs;
+ register int stat;
+
+ if (auth->ah_cred.oa_base == au->au_origcred.oa_base) {
+ /* there is no hope. Punt */
+ return (FALSE);
+ }
+ au->au_shfaults ++;
+
+ /* first deserialize the creds back into a struct authunix_parms */
+ aup.aup_machname = NULL;
+ aup.aup_gids = (int *)NULL;
+ xdrmem_create(&xdrs, au->au_origcred.oa_base,
+ au->au_origcred.oa_length, XDR_DECODE);
+ stat = xdr_authunix_parms(&xdrs, &aup);
+ if (! stat)
+ goto done;
+
+ /* update the time and serialize in place */
+ (void)gettimeofday(&now, (struct timezone *)0);
+ aup.aup_time = now.tv_sec;
+ xdrs.x_op = XDR_ENCODE;
+ XDR_SETPOS(&xdrs, 0);
+ stat = xdr_authunix_parms(&xdrs, &aup);
+ if (! stat)
+ goto done;
+ auth->ah_cred = au->au_origcred;
+ marshal_new_auth(auth);
+done:
+ /* free the struct authunix_parms created by deserializing */
+ xdrs.x_op = XDR_FREE;
+ (void)xdr_authunix_parms(&xdrs, &aup);
+ XDR_DESTROY(&xdrs);
+ return (stat);
+}
+
+static void
+authunix_destroy(auth)
+ register AUTH *auth;
+{
+ register struct audata *au = AUTH_PRIVATE(auth);
+
+ mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length);
+
+ if (au->au_shcred.oa_base != NULL)
+ mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length);
+
+ mem_free(auth->ah_private, sizeof(struct audata));
+
+ if (auth->ah_verf.oa_base != NULL)
+ mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length);
+
+ mem_free((caddr_t)auth, sizeof(*auth));
+}
+
+/*
+ * Marshals (pre-serializes) an auth struct.
+ * sets private data, au_marshed and au_mpos
+ */
+static void
+marshal_new_auth(auth)
+ register AUTH *auth;
+{
+ XDR xdr_stream;
+ register XDR *xdrs = &xdr_stream;
+ register struct audata *au = AUTH_PRIVATE(auth);
+
+ xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
+ if ((! xdr_opaque_auth(xdrs, &(auth->ah_cred))) ||
+ (! xdr_opaque_auth(xdrs, &(auth->ah_verf)))) {
+ perror("auth_none.c - Fatal marshalling problem");
+ } else {
+ au->au_mpos = XDR_GETPOS(xdrs);
+ }
+ XDR_DESTROY(xdrs);
+}
diff --git a/cpukit/librpc/src/rpc/authdes_prot.c b/cpukit/librpc/src/rpc/authdes_prot.c
new file mode 100644
index 0000000000..14679c00a9
--- /dev/null
+++ b/cpukit/librpc/src/rpc/authdes_prot.c
@@ -0,0 +1,82 @@
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)authdes_prot.c 2.1 88/07/29 4.0 RPCSRC; from 1.6 88/02/08 SMI";
+#endif
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1988 by Sun Microsystems, Inc.
+ */
+
+/*
+ * authdes_prot.c, XDR routines for DES authentication
+ */
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#include <rpc/auth_des.h>
+
+#define ATTEMPT(xdr_op) if (!(xdr_op)) return (FALSE)
+
+bool_t
+xdr_authdes_cred(xdrs, cred)
+ XDR *xdrs;
+ struct authdes_cred *cred;
+{
+ /*
+ * Unrolled xdr
+ */
+ ATTEMPT(xdr_enum(xdrs, (enum_t *)&cred->adc_namekind));
+ switch (cred->adc_namekind) {
+ case ADN_FULLNAME:
+ ATTEMPT(xdr_string(xdrs, &cred->adc_fullname.name, MAXNETNAMELEN));
+ ATTEMPT(xdr_opaque(xdrs, (caddr_t)&cred->adc_fullname.key, sizeof(des_block)));
+ ATTEMPT(xdr_opaque(xdrs, (caddr_t)&cred->adc_fullname.window, sizeof(cred->adc_fullname.window)));
+ return (TRUE);
+ case ADN_NICKNAME:
+ ATTEMPT(xdr_opaque(xdrs, (caddr_t)&cred->adc_nickname, sizeof(cred->adc_nickname)));
+ return (TRUE);
+ default:
+ return (FALSE);
+ }
+}
+
+
+bool_t
+xdr_authdes_verf(xdrs, verf)
+ register XDR *xdrs;
+ register struct authdes_verf *verf;
+{
+ /*
+ * Unrolled xdr
+ */
+ ATTEMPT(xdr_opaque(xdrs, (caddr_t)&verf->adv_xtimestamp, sizeof(des_block)));
+ ATTEMPT(xdr_opaque(xdrs, (caddr_t)&verf->adv_int_u, sizeof(verf->adv_int_u)));
+ return (TRUE);
+}
diff --git a/cpukit/librpc/src/rpc/authunix_prot.c b/cpukit/librpc/src/rpc/authunix_prot.c
new file mode 100644
index 0000000000..4fddc6b96d
--- /dev/null
+++ b/cpukit/librpc/src/rpc/authunix_prot.c
@@ -0,0 +1,67 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)authunix_prot.c 1.15 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)authunix_prot.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/rpc/authunix_prot.c,v 1.6 1999/08/28 00:00:33 peter Exp $";
+#endif
+
+/*
+ * authunix_prot.c
+ * XDR for UNIX style authentication parameters for RPC
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#include <rpc/auth_unix.h>
+
+/*
+ * XDR for unix authentication parameters.
+ */
+bool_t
+xdr_authunix_parms(xdrs, p)
+ register XDR *xdrs;
+ register struct authunix_parms *p;
+{
+
+ if (xdr_u_long(xdrs, &(p->aup_time))
+ && xdr_string(xdrs, &(p->aup_machname), MAX_MACHINE_NAME)
+ && xdr_int(xdrs, &(p->aup_uid))
+ && xdr_int(xdrs, &(p->aup_gid))
+ && xdr_array(xdrs, (caddr_t *)&(p->aup_gids),
+ &(p->aup_len), NGRPS, sizeof(int), xdr_int) ) {
+ return (TRUE);
+ }
+ return (FALSE);
+}
diff --git a/cpukit/librpc/src/rpc/bindresvport.3 b/cpukit/librpc/src/rpc/bindresvport.3
new file mode 100644
index 0000000000..02a079decc
--- /dev/null
+++ b/cpukit/librpc/src/rpc/bindresvport.3
@@ -0,0 +1,106 @@
+.\" @(#)bindresvport.3n 2.2 88/08/02 4.0 RPCSRC; from 1.7 88/03/14 SMI
+.\" $FreeBSD: src/lib/libc/rpc/bindresvport.3,v 1.10 2000/01/27 02:55:01 bde Exp $
+.\"
+.Dd January 27, 2000
+.Dt BINDRESVPORT 3
+.Os
+.Sh NAME
+.Nm bindresvport ,
+.Nm bindresvport_sa
+.Ndbind a socket to a privileged IP port
+.Sh SYNOPSIS
+.Fd #include <rpc/rpc.h>
+.Ft int
+.Fn bindresvport "int sd" "struct sockaddr_in *sin"
+.Ft int
+.Fn bindresvport_sa "int sd" "struct sockaddr *sa"
+.Sh DESCRIPTION
+.Fn bindresvport
+and
+.Fn bindresvport_sa
+are used to bind a socket descriptor to a privileged
+.Tn IP
+port, that is, a
+port number in the range 0-1023.
+.Pp
+Only root can bind to a privileged port; this call will fail for any
+other users.
+.Pp
+When
+.Va sin
+is not null,
+.Va sin->sin_family
+must be initialized to the address family of the socket, passed by
+.Va sd .
+If the value of sin->sin_port is non-zero
+.Fn bindresvport
+will attempt to use that specific port. If it fails, it chooses another
+privileged port automatically.
+.Pp
+It is legal to pass null pointer to
+.Va sin .
+In this case, the caller cannot get the port number
+.Fn bindresvport
+has picked.
+.Pp
+Function prototype of
+.Fn bindresvport
+is biased to
+.Dv AF_INET
+socket.
+.Fn bindresvport_sa
+acts exactly the same, with more neutral function prototype.
+Note that both functions behave exactly the same, and
+both support
+.Dv AF_INET6
+sockets as well as
+.Dv AF_INET
+sockets.
+.Sh RETURN VALUES
+.Fn bindresvport
+and
+.Fn bindresvport_sa
+return 0 if they are successful, otherwise \-1 is returned and
+.Va errno
+set to reflect the cause of the error.
+.Sh ERRORS
+The
+.Fn bindresvport
+and
+.Fn bindresvport_sa
+functions fail if:
+.Bl -tag -width Er
+.It Bq Er EBADF
+.Fa sd
+is not a valid descriptor.
+.It Bq Er ENOTSOCK
+.Fa sd
+is not a socket.
+.It Bq Er EADDRNOTAVAIL
+The specified address is not available from the local machine.
+.It Bq Er EADDRINUSE
+The specified address is already in use.
+.It Bq Er EINVAL
+The socket is already bound to an address,
+or the socket family and the family of specified address mismatch.
+.It Bq Er EACCES
+The requested address is protected, and the current user
+has inadequate permission to access it.
+.It Bq Er EFAULT
+The
+.Fa name
+parameter is not in a valid part of the user
+address space.
+.It Bq Er ENOBUFS
+Insufficient resources were available in the system
+to perform the operation.
+.It Bq Er EPFNOSUPPORT
+The protocol family has not been configured into the
+system, no implementation for it exists,
+or address family did not match between arguments.
+.El
+.Sh "SEE ALSO"
+.Xr bind 2 ,
+.Xr socket 2 ,
+.Xr rresvport 3 ,
+.Xr rresvport_af 3
diff --git a/cpukit/librpc/src/rpc/bindresvport.c b/cpukit/librpc/src/rpc/bindresvport.c
new file mode 100644
index 0000000000..bb97570b88
--- /dev/null
+++ b/cpukit/librpc/src/rpc/bindresvport.c
@@ -0,0 +1,147 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)bindresvport.c 1.8 88/02/08 SMI";*/
+/*static char *sccsid = "from: @(#)bindresvport.c 2.2 88/07/29 4.0 RPCSRC";*/
+/*from: OpenBSD: bindresvport.c,v 1.7 1996/07/30 16:25:47 downsj Exp */
+static char *rcsid = "$FreeBSD: src/lib/libc/rpc/bindresvport.c,v 1.12 2000/01/26 09:02:42 shin Exp $";
+#endif
+
+/*
+ * Copyright (c) 1987 by Sun Microsystems, Inc.
+ *
+ * Portions Copyright(C) 1996, Jason Downs. All rights reserved.
+ */
+
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <string.h>
+
+/*
+ * Bind a socket to a privileged port for whatever protocol.
+ */
+int
+bindresvport_sa(sd, sa)
+ int sd;
+ struct sockaddr *sa;
+{
+ int old, error, af;
+ struct sockaddr myaddr;
+ struct sockaddr_in *sin;
+#if (defined(AF_INET6) && defined(IPPROTO_IPV6))
+ struct sockaddr_in6 *sin6;
+#endif
+ int proto, portrange, portlow;
+ u_int16_t port;
+ int salen;
+
+ if (sa == NULL) {
+ salen = sizeof(myaddr);
+ sa = (struct sockaddr *)&myaddr;
+
+ if (getsockname(sd, sa, &salen) == -1)
+ return -1; /* errno is correctly set */
+
+ af = sa->sa_family;
+ memset(&myaddr, 0, salen);
+ } else
+ af = sa->sa_family;
+
+ if (af == AF_INET) {
+ proto = IPPROTO_IP;
+ portrange = IP_PORTRANGE;
+ portlow = IP_PORTRANGE_LOW;
+ sin = (struct sockaddr_in *)sa;
+ salen = sizeof(struct sockaddr_in);
+ port = sin->sin_port;
+#if (defined(AF_INET6) && defined(IPPROTO_IPV6))
+ } else if (af == AF_INET6) {
+ proto = IPPROTO_IPV6;
+ portrange = IPV6_PORTRANGE;
+ portlow = IPV6_PORTRANGE_LOW;
+ sin6 = (struct sockaddr_in6 *)sa;
+ salen = sizeof(struct sockaddr_in6);
+ port = sin6->sin6_port;
+#endif
+ } else {
+ errno = EPFNOSUPPORT;
+ return (-1);
+ }
+ sa->sa_family = af;
+ sa->sa_len = salen;
+
+ if (port == 0) {
+ int oldlen = sizeof(old);
+
+ error = getsockopt(sd, proto, portrange, &old, &oldlen);
+ if (error < 0)
+ return (error);
+
+ error = setsockopt(sd, proto, portrange, &portlow,
+ sizeof(portlow));
+ if (error < 0)
+ return (error);
+ }
+
+ error = bind(sd, sa, salen);
+
+ if (port == 0) {
+ int saved_errno = errno;
+
+ if (error) {
+ if (setsockopt(sd, proto, portrange, &old,
+ sizeof(old)) < 0)
+ errno = saved_errno;
+ return (error);
+ }
+
+ if (sa != (struct sockaddr *)&myaddr) {
+ /* Hmm, what did the kernel assign... */
+ if (getsockname(sd, sa, &salen) < 0)
+ errno = saved_errno;
+ return (error);
+ }
+ }
+ return (error);
+}
+
+/*
+ * Bind a socket to a privileged IP port
+ */
+int
+bindresvport(sd, sin)
+ int sd;
+ struct sockaddr_in *sin;
+{
+ return bindresvport_sa(sd, (struct sockaddr *)sin);
+}
diff --git a/cpukit/librpc/src/rpc/clnt_generic.c b/cpukit/librpc/src/rpc/clnt_generic.c
new file mode 100644
index 0000000000..d387fae4c0
--- /dev/null
+++ b/cpukit/librpc/src/rpc/clnt_generic.c
@@ -0,0 +1,141 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)clnt_generic.c 1.4 87/08/11 (C) 1987 SMI";*/
+/*static char *sccsid = "from: @(#)clnt_generic.c 2.2 88/08/01 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/rpc/clnt_generic.c,v 1.9 1999/08/28 00:00:35 peter Exp $";
+#endif
+
+/*
+ * Copyright (C) 1987, Sun Microsystems, Inc.
+ */
+#include <rpc/rpc.h>
+#include <sys/socket.h>
+#include <sys/errno.h>
+#include <netdb.h>
+#include <string.h>
+
+/*
+ * Generic client creation: takes (hostname, program-number, protocol) and
+ * returns client handle. Default options are set, which the user can
+ * change using the rpc equivalent of ioctl()'s.
+ */
+CLIENT *
+clnt_create(hostname, prog, vers, proto)
+ char *hostname;
+ u_long prog;
+ u_long vers;
+ char *proto;
+{
+ struct hostent *h;
+ struct protoent *p;
+ struct sockaddr_in sin;
+#ifndef __rtems__
+ struct sockaddr_un sun;
+#endif
+ int sock;
+ struct timeval tv;
+ CLIENT *client;
+
+#ifndef __rtems__
+ if (!strcmp(proto, "unix")) {
+ bzero((char *)&sun, sizeof(sun));
+ sun.sun_family = AF_UNIX;
+ strcpy(sun.sun_path, hostname);
+ sun.sun_len = sizeof(sun.sun_len) + sizeof(sun.sun_family) +
+ strlen(sun.sun_path) + 1;
+ sock = RPC_ANYSOCK;
+ client = clntunix_create(&sun, prog, vers, &sock, 0, 0);
+ if (client == NULL)
+ return(NULL);
+ tv.tv_sec = 25;
+ tv.tv_usec = 0;
+ clnt_control(client, CLSET_TIMEOUT, &tv);
+ return(client);
+ }
+#endif
+
+ h = gethostbyname(hostname);
+ if (h == NULL) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNHOST;
+ return (NULL);
+ }
+ if (h->h_addrtype != AF_INET) {
+ /*
+ * Only support INET for now
+ */
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = EAFNOSUPPORT;
+ return (NULL);
+ }
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_len = sizeof(struct sockaddr_in);
+ sin.sin_family = h->h_addrtype;
+ sin.sin_port = 0;
+ memcpy((char*)&sin.sin_addr, h->h_addr, h->h_length);
+ p = getprotobyname(proto);
+ if (p == NULL) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ rpc_createerr.cf_error.re_errno = EPFNOSUPPORT;
+ return (NULL);
+ }
+ sock = RPC_ANYSOCK;
+ switch (p->p_proto) {
+ case IPPROTO_UDP:
+ tv.tv_sec = 5;
+ tv.tv_usec = 0;
+ client = clntudp_create(&sin, prog, vers, tv, &sock);
+ if (client == NULL) {
+ return (NULL);
+ }
+#if 0 /* XXX do we need this? */
+ tv.tv_sec = 25;
+ tv.tv_usec = 0;
+ clnt_control(client, CLSET_TIMEOUT, &tv);
+#endif
+ break;
+ case IPPROTO_TCP:
+ client = clnttcp_create(&sin, prog, vers, &sock, 0, 0);
+ if (client == NULL) {
+ return (NULL);
+ }
+#if 0 /* XXX do we need this? */
+ tv.tv_sec = 25;
+ tv.tv_usec = 0;
+ clnt_control(client, CLSET_TIMEOUT, &tv);
+#endif
+ break;
+ default:
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = EPFNOSUPPORT;
+ return (NULL);
+ }
+ return (client);
+}
diff --git a/cpukit/librpc/src/rpc/clnt_perror.c b/cpukit/librpc/src/rpc/clnt_perror.c
new file mode 100644
index 0000000000..a7df29c0dd
--- /dev/null
+++ b/cpukit/librpc/src/rpc/clnt_perror.c
@@ -0,0 +1,254 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)clnt_perror.c 1.15 87/10/07 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)clnt_perror.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/rpc/clnt_perror.c,v 1.11 1999/08/28 00:00:35 peter Exp $";
+#endif
+
+/*
+ * clnt_perror.c
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <rpc/types.h>
+#include <rpc/auth.h>
+#include <rpc/clnt.h>
+
+static char *auth_errmsg();
+#define CLNT_PERROR_BUFLEN 256
+
+#define buf ((char *)(rtems_rpc_task_variables)->clnt_perror_buf)
+
+static char *
+_buf()
+{
+
+ if (buf == 0)
+ buf = (char *)malloc(CLNT_PERROR_BUFLEN);
+ return (buf);
+}
+
+/*
+ * Print reply error info
+ */
+char *
+clnt_sperror(rpch, s)
+ CLIENT *rpch;
+ char *s;
+{
+ struct rpc_err e;
+ char *err;
+ char *str = _buf();
+ char *strstart = str;
+
+ if (str == 0)
+ return (0);
+ CLNT_GETERR(rpch, &e);
+
+ (void) sprintf(str, "%s: %s", s, clnt_sperrno(e.re_status));
+ str += strlen(str);
+
+ switch (e.re_status) {
+ case RPC_SUCCESS:
+ case RPC_CANTENCODEARGS:
+ case RPC_CANTDECODERES:
+ case RPC_TIMEDOUT:
+ case RPC_PROGUNAVAIL:
+ case RPC_PROCUNAVAIL:
+ case RPC_CANTDECODEARGS:
+ case RPC_SYSTEMERROR:
+ case RPC_UNKNOWNHOST:
+ case RPC_UNKNOWNPROTO:
+ case RPC_PMAPFAILURE:
+ case RPC_PROGNOTREGISTERED:
+ case RPC_FAILED:
+ break;
+
+ case RPC_CANTSEND:
+ case RPC_CANTRECV:
+ (void) snprintf(str, CLNT_PERROR_BUFLEN - (str - strstart),
+ "; errno = %s\n", strerror(e.re_errno));
+ break;
+
+ case RPC_VERSMISMATCH:
+ (void) sprintf(str,
+ "; low version = %lu, high version = %lu\n",
+ (u_long)e.re_vers.low, (u_long)e.re_vers.high);
+ break;
+
+ case RPC_AUTHERROR:
+ err = auth_errmsg(e.re_why);
+ (void) sprintf(str,"; why = ");
+ str += strlen(str);
+ if (err != NULL) {
+ (void) sprintf(str, "%s\n",err);
+ } else {
+ (void) sprintf(str,
+ "(unknown authentication error - %d)\n",
+ (int) e.re_why);
+ }
+ break;
+
+ case RPC_PROGVERSMISMATCH:
+ (void) sprintf(str,
+ "; low version = %lu, high version = %lu\n",
+ (u_long)e.re_vers.low, (u_long)e.re_vers.high);
+ break;
+
+ default: /* unknown */
+ (void) sprintf(str,
+ "; s1 = %lu, s2 = %lu\n",
+ (long)e.re_lb.s1, (long)e.re_lb.s2);
+ break;
+ }
+ strstart[CLNT_PERROR_BUFLEN-2] = '\n';
+ strstart[CLNT_PERROR_BUFLEN-1] = '\0';
+ return(strstart) ;
+}
+
+void
+clnt_perror(rpch, s)
+ CLIENT *rpch;
+ char *s;
+{
+ (void) fprintf(stderr,"%s\n",clnt_sperror(rpch,s));
+}
+
+
+static const char *const rpc_errlist[] = {
+ "RPC: Success", /* 0 - RPC_SUCCESS */
+ "RPC: Can't encode arguments", /* 1 - RPC_CANTENCODEARGS */
+ "RPC: Can't decode result", /* 2 - RPC_CANTDECODERES */
+ "RPC: Unable to send", /* 3 - RPC_CANTSEND */
+ "RPC: Unable to receive", /* 4 - RPC_CANTRECV */
+ "RPC: Timed out", /* 5 - RPC_TIMEDOUT */
+ "RPC: Incompatible versions of RPC", /* 6 - RPC_VERSMISMATCH */
+ "RPC: Authentication error", /* 7 - RPC_AUTHERROR */
+ "RPC: Program unavailable", /* 8 - RPC_PROGUNAVAIL */
+ "RPC: Program/version mismatch", /* 9 - RPC_PROGVERSMISMATCH */
+ "RPC: Procedure unavailable", /* 10 - RPC_PROCUNAVAIL */
+ "RPC: Server can't decode arguments", /* 11 - RPC_CANTDECODEARGS */
+ "RPC: Remote system error", /* 12 - RPC_SYSTEMERROR */
+ "RPC: Unknown host", /* 13 - RPC_UNKNOWNHOST */
+ "RPC: Port mapper failure", /* 14 - RPC_PMAPFAILURE */
+ "RPC: Program not registered", /* 15 - RPC_PROGNOTREGISTERED */
+ "RPC: Failed (unspecified error)", /* 16 - RPC_FAILED */
+ "RPC: Unknown protocol" /* 17 - RPC_UNKNOWNPROTO */
+};
+
+
+/*
+ * This interface for use by clntrpc
+ */
+char *
+clnt_sperrno(stat)
+ enum clnt_stat stat;
+{
+ unsigned int errnum = stat;
+
+ if (errnum < (sizeof(rpc_errlist)/sizeof(rpc_errlist[0])))
+ return (char *)rpc_errlist[errnum];
+
+ return ("RPC: (unknown error code)");
+}
+
+void
+clnt_perrno(num)
+ enum clnt_stat num;
+{
+ (void) fprintf(stderr,"%s\n",clnt_sperrno(num));
+}
+
+
+char *
+clnt_spcreateerror(s)
+ char *s;
+{
+ char *str = _buf();
+
+ if (str == 0)
+ return(0);
+ switch (rpc_createerr.cf_stat) {
+ case RPC_PMAPFAILURE:
+ (void) snprintf(str, CLNT_PERROR_BUFLEN, "%s: %s - %s\n", s,
+ clnt_sperrno(rpc_createerr.cf_stat),
+ clnt_sperrno(rpc_createerr.cf_error.re_status));
+ break;
+
+ case RPC_SYSTEMERROR:
+ (void) snprintf(str, CLNT_PERROR_BUFLEN, "%s: %s - %s\n", s,
+ clnt_sperrno(rpc_createerr.cf_stat),
+ strerror(rpc_createerr.cf_error.re_errno));
+ break;
+ default:
+ (void) snprintf(str, CLNT_PERROR_BUFLEN, "%s: %s\n", s,
+ clnt_sperrno(rpc_createerr.cf_stat));
+ break;
+ }
+ str[CLNT_PERROR_BUFLEN-2] = '\n';
+ str[CLNT_PERROR_BUFLEN-1] = '\0';
+ return (str);
+}
+
+void
+clnt_pcreateerror(s)
+ char *s;
+{
+ (void) fprintf(stderr,"%s\n",clnt_spcreateerror(s));
+}
+
+static const char *const auth_errlist[] = {
+ "Authentication OK", /* 0 - AUTH_OK */
+ "Invalid client credential", /* 1 - AUTH_BADCRED */
+ "Server rejected credential", /* 2 - AUTH_REJECTEDCRED */
+ "Invalid client verifier", /* 3 - AUTH_BADVERF */
+ "Server rejected verifier", /* 4 - AUTH_REJECTEDVERF */
+ "Client credential too weak", /* 5 - AUTH_TOOWEAK */
+ "Invalid server verifier", /* 6 - AUTH_INVALIDRESP */
+ "Failed (unspecified error)" /* 7 - AUTH_FAILED */
+};
+
+static char *
+auth_errmsg(stat)
+ enum auth_stat stat;
+{
+ unsigned int errnum = stat;
+
+ if (errnum < (sizeof(auth_errlist)/sizeof(auth_errlist[0])))
+ return (char *)auth_errlist[errnum];
+
+ return(NULL);
+}
diff --git a/cpukit/librpc/src/rpc/clnt_raw.c b/cpukit/librpc/src/rpc/clnt_raw.c
new file mode 100644
index 0000000000..d17221a997
--- /dev/null
+++ b/cpukit/librpc/src/rpc/clnt_raw.c
@@ -0,0 +1,243 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)clnt_raw.c 1.22 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)clnt_raw.c 2.2 88/08/01 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/rpc/clnt_raw.c,v 1.10 1999/08/28 00:00:36 peter Exp $";
+#endif
+
+/*
+ * clnt_raw.c
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * Memory based rpc for simple testing and timing.
+ * Interface to create an rpc client and server in the same process.
+ * This lets us similate rpc and get round trip overhead, without
+ * any interference from the kernal.
+ */
+
+#include <rpc/rpc.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define MCALL_MSG_SIZE 24
+
+/*
+ * This is the "network" we will be moving stuff over.
+ */
+struct clnt_raw_private {
+ CLIENT client_object;
+ XDR xdr_stream;
+ char _raw_buf[UDPMSGSIZE];
+ char mashl_callmsg[MCALL_MSG_SIZE];
+ u_int mcnt;
+};
+#define clntraw_private ((struct clnt_raw_private *) (rtems_rpc_task_variables)->clnt_raw_private)
+
+static enum clnt_stat clntraw_call();
+static void clntraw_abort();
+static void clntraw_geterr();
+static bool_t clntraw_freeres();
+static bool_t clntraw_control();
+static void clntraw_destroy();
+
+static struct clnt_ops client_ops = {
+ clntraw_call,
+ clntraw_abort,
+ clntraw_geterr,
+ clntraw_freeres,
+ clntraw_destroy,
+ clntraw_control
+};
+
+void svc_getreq();
+
+/*
+ * Create a client handle for memory based rpc.
+ */
+CLIENT *
+clntraw_create(prog, vers)
+ u_long prog;
+ u_long vers;
+{
+ register struct clnt_raw_private *clp = clntraw_private;
+ struct rpc_msg call_msg;
+ XDR *xdrs = &clp->xdr_stream;
+ CLIENT *client = &clp->client_object;
+
+ if (clp == 0) {
+ clp = (struct clnt_raw_private *)calloc(1, sizeof (*clp));
+ if (clp == 0)
+ return (0);
+ clntraw_private = clp;
+ }
+ /*
+ * pre-serialize the static part of the call msg and stash it away
+ */
+ call_msg.rm_direction = CALL;
+ call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+ call_msg.rm_call.cb_prog = prog;
+ call_msg.rm_call.cb_vers = vers;
+ xdrmem_create(xdrs, clp->mashl_callmsg, MCALL_MSG_SIZE, XDR_ENCODE);
+ if (! xdr_callhdr(xdrs, &call_msg)) {
+ perror("clnt_raw.c - Fatal header serialization error.");
+ }
+ clp->mcnt = XDR_GETPOS(xdrs);
+ XDR_DESTROY(xdrs);
+
+ /*
+ * Set xdrmem for client/server shared buffer
+ */
+ xdrmem_create(xdrs, clp->_raw_buf, UDPMSGSIZE, XDR_FREE);
+
+ /*
+ * create client handle
+ */
+ client->cl_ops = &client_ops;
+ client->cl_auth = authnone_create();
+ return (client);
+}
+
+static enum clnt_stat
+clntraw_call(h, proc, xargs, argsp, xresults, resultsp, timeout)
+ CLIENT *h;
+ u_long proc;
+ xdrproc_t xargs;
+ caddr_t argsp;
+ xdrproc_t xresults;
+ caddr_t resultsp;
+ struct timeval timeout;
+{
+ register struct clnt_raw_private *clp = clntraw_private;
+ register XDR *xdrs = &clp->xdr_stream;
+ struct rpc_msg msg;
+ enum clnt_stat status;
+ struct rpc_err error;
+
+ if (clp == 0)
+ return (RPC_FAILED);
+call_again:
+ /*
+ * send request
+ */
+ xdrs->x_op = XDR_ENCODE;
+ XDR_SETPOS(xdrs, 0);
+ ((struct rpc_msg *)clp->mashl_callmsg)->rm_xid ++ ;
+ if ((! XDR_PUTBYTES(xdrs, clp->mashl_callmsg, clp->mcnt)) ||
+ (! XDR_PUTLONG(xdrs, (long *)&proc)) ||
+ (! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
+ (! (*xargs)(xdrs, argsp))) {
+ return (RPC_CANTENCODEARGS);
+ }
+ (void)XDR_GETPOS(xdrs); /* called just to cause overhead */
+
+ /*
+ * We have to call server input routine here because this is
+ * all going on in one process. Yuk.
+ */
+ svc_getreq(1);
+
+ /*
+ * get results
+ */
+ xdrs->x_op = XDR_DECODE;
+ XDR_SETPOS(xdrs, 0);
+ msg.acpted_rply.ar_verf = _null_auth;
+ msg.acpted_rply.ar_results.where = resultsp;
+ msg.acpted_rply.ar_results.proc = xresults;
+ if (! xdr_replymsg(xdrs, &msg))
+ return (RPC_CANTDECODERES);
+ _seterr_reply(&msg, &error);
+ status = error.re_status;
+
+ if (status == RPC_SUCCESS) {
+ if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) {
+ status = RPC_AUTHERROR;
+ }
+ } /* end successful completion */
+ else {
+ if (AUTH_REFRESH(h->cl_auth))
+ goto call_again;
+ } /* end of unsuccessful completion */
+
+ if (status == RPC_SUCCESS) {
+ if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) {
+ status = RPC_AUTHERROR;
+ }
+ if (msg.acpted_rply.ar_verf.oa_base != NULL) {
+ xdrs->x_op = XDR_FREE;
+ (void)xdr_opaque_auth(xdrs, &(msg.acpted_rply.ar_verf));
+ }
+ }
+
+ return (status);
+}
+
+static void
+clntraw_geterr()
+{
+}
+
+
+static bool_t
+clntraw_freeres(cl, xdr_res, res_ptr)
+ CLIENT *cl;
+ xdrproc_t xdr_res;
+ caddr_t res_ptr;
+{
+ register struct clnt_raw_private *clp = clntraw_private;
+ register XDR *xdrs = &clp->xdr_stream;
+ bool_t rval;
+
+ if (clp == 0)
+ {
+ rval = (bool_t) RPC_FAILED;
+ return (rval);
+ }
+ xdrs->x_op = XDR_FREE;
+ return ((*xdr_res)(xdrs, res_ptr));
+}
+
+static void
+clntraw_abort()
+{
+}
+
+static bool_t
+clntraw_control()
+{
+ return (FALSE);
+}
+
+static void
+clntraw_destroy()
+{
+}
diff --git a/cpukit/librpc/src/rpc/clnt_simple.c b/cpukit/librpc/src/rpc/clnt_simple.c
new file mode 100644
index 0000000000..b6b90c51c5
--- /dev/null
+++ b/cpukit/librpc/src/rpc/clnt_simple.c
@@ -0,0 +1,123 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)clnt_simple.c 1.35 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)clnt_simple.c 2.2 88/08/01 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/rpc/clnt_simple.c,v 1.12 2000/01/27 23:06:35 jasone Exp $";
+#endif
+
+/*
+ * clnt_simple.c
+ * Simplified front end to rpc.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <sys/param.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+struct call_rpc_private {
+ CLIENT *client;
+ int socket;
+ int oldprognum, oldversnum, valid;
+ char *oldhost;
+};
+#define callrpc_private ((struct call_rpc_private *)(rtems_rpc_task_variables)->call_rpc_private)
+
+int
+callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out)
+ char *host;
+ int prognum, versnum, procnum;
+ xdrproc_t inproc, outproc;
+ char *in, *out;
+{
+ register struct call_rpc_private *crp = callrpc_private;
+ struct sockaddr_in server_addr;
+ enum clnt_stat clnt_stat;
+ struct hostent *hp;
+ struct timeval timeout, tottimeout;
+
+ if (crp == 0) {
+ crp = (struct call_rpc_private *)calloc(1, sizeof (*crp));
+ if (crp == 0)
+ return (0);
+ callrpc_private = crp;
+ }
+ if (crp->oldhost == NULL) {
+ crp->oldhost = malloc(MAXHOSTNAMELEN);
+ crp->oldhost[0] = 0;
+ crp->socket = RPC_ANYSOCK;
+ }
+ if (crp->valid && crp->oldprognum == prognum && crp->oldversnum == versnum
+ && strcmp(crp->oldhost, host) == 0) {
+ /* reuse old client */
+ } else {
+ crp->valid = 0;
+ if (crp->socket != -1)
+ (void)_RPC_close(crp->socket);
+ crp->socket = RPC_ANYSOCK;
+ if (crp->client) {
+ clnt_destroy(crp->client);
+ crp->client = NULL;
+ }
+ if ((hp = gethostbyname(host)) == NULL)
+ return ((int) RPC_UNKNOWNHOST);
+ timeout.tv_usec = 0;
+ timeout.tv_sec = 5;
+ memset(&server_addr, 0, sizeof(server_addr));
+ memcpy((char *)&server_addr.sin_addr, hp->h_addr, hp->h_length);
+ server_addr.sin_len = sizeof(struct sockaddr_in);
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_port = 0;
+ if ((crp->client = clntudp_create(&server_addr, (u_long)prognum,
+ (u_long)versnum, timeout, &crp->socket)) == NULL)
+ return ((int) rpc_createerr.cf_stat);
+ crp->valid = 1;
+ crp->oldprognum = prognum;
+ crp->oldversnum = versnum;
+ (void) strcpy(crp->oldhost, host);
+ }
+ tottimeout.tv_sec = 25;
+ tottimeout.tv_usec = 0;
+ clnt_stat = clnt_call(crp->client, procnum, inproc, in,
+ outproc, out, tottimeout);
+ /*
+ * if call failed, empty cache
+ */
+ if (clnt_stat != RPC_SUCCESS)
+ crp->valid = 0;
+ return ((int) clnt_stat);
+}
diff --git a/cpukit/librpc/src/rpc/clnt_tcp.c b/cpukit/librpc/src/rpc/clnt_tcp.c
new file mode 100644
index 0000000000..fa477b76d4
--- /dev/null
+++ b/cpukit/librpc/src/rpc/clnt_tcp.c
@@ -0,0 +1,581 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)clnt_tcp.c 1.37 87/10/05 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)clnt_tcp.c 2.2 88/08/01 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/rpc/clnt_tcp.c,v 1.14 2000/01/27 23:06:36 jasone Exp $";
+#endif
+
+/*
+ * clnt_tcp.c, Implements a TCP/IP based, client side RPC.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * TCP based RPC supports 'batched calls'.
+ * A sequence of calls may be batched-up in a send buffer. The rpc call
+ * return immediately to the client even though the call was not necessarily
+ * sent. The batching occurs if the results' xdr routine is NULL (0) AND
+ * the rpc timeout value is zero (see clnt.h, rpc).
+ *
+ * Clients should NOT casually batch calls that in fact return results; that is,
+ * the server side should be aware that a call is batched and not produce any
+ * return message. Batched calls that produce many result messages can
+ * deadlock (netlock) the client and the server....
+ *
+ * Now go hang yourself.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <errno.h>
+#include <rpc/pmap_clnt.h>
+#include <sys/select.h>
+
+#define MCALL_MSG_SIZE 24
+
+static int readtcp();
+static int writetcp();
+
+static enum clnt_stat clnttcp_call();
+static void clnttcp_abort();
+static void clnttcp_geterr();
+static bool_t clnttcp_freeres();
+static bool_t clnttcp_control();
+static void clnttcp_destroy();
+
+static struct clnt_ops tcp_ops = {
+ clnttcp_call,
+ clnttcp_abort,
+ clnttcp_geterr,
+ clnttcp_freeres,
+ clnttcp_destroy,
+ clnttcp_control
+};
+
+struct ct_data {
+ int ct_sock;
+ bool_t ct_closeit;
+ struct timeval ct_wait;
+ bool_t ct_waitset; /* wait set by clnt_control? */
+ struct sockaddr_in ct_addr;
+ struct rpc_err ct_error;
+ char ct_mcall[MCALL_MSG_SIZE]; /* marshalled callmsg */
+ u_int ct_mpos; /* pos after marshal */
+ XDR ct_xdrs;
+};
+
+/*
+ * Create a client handle for a tcp/ip connection.
+ * If *sockp<0, *sockp is set to a newly created TCP socket and it is
+ * connected to raddr. If *sockp non-negative then
+ * raddr is ignored. The rpc/tcp package does buffering
+ * similar to stdio, so the client must pick send and receive buffer sizes,];
+ * 0 => use the default.
+ * If raddr->sin_port is 0, then a binder on the remote machine is
+ * consulted for the right port number.
+ * NB: *sockp is copied into a private area.
+ * NB: It is the clients responsibility to close *sockp.
+ * NB: The rpch->cl_auth is set null authentication. Caller may wish to set this
+ * something more useful.
+ */
+CLIENT *
+clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
+ struct sockaddr_in *raddr;
+ u_long prog;
+ u_long vers;
+ register int *sockp;
+ u_int sendsz;
+ u_int recvsz;
+{
+ CLIENT *h;
+ register struct ct_data *ct = NULL;
+ struct timeval now;
+ struct rpc_msg call_msg;
+ static u_int32_t disrupt;
+
+ if (disrupt == 0)
+ disrupt = (u_int32_t)(long)raddr;
+
+ h = (CLIENT *)mem_alloc(sizeof(*h));
+ if (h == NULL) {
+ (void)fprintf(stderr, "clnttcp_create: out of memory\n");
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+ goto fooy;
+ }
+ ct = (struct ct_data *)mem_alloc(sizeof(*ct));
+ if (ct == NULL) {
+ (void)fprintf(stderr, "clnttcp_create: out of memory\n");
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+ goto fooy;
+ }
+
+ /*
+ * If no port number given ask the pmap for one
+ */
+ if (raddr->sin_port == 0) {
+ u_short port;
+ if ((port = pmap_getport(raddr, prog, vers, IPPROTO_TCP)) == 0) {
+ mem_free((caddr_t)ct, sizeof(struct ct_data));
+ mem_free((caddr_t)h, sizeof(CLIENT));
+ return ((CLIENT *)NULL);
+ }
+ raddr->sin_port = htons(port);
+ }
+
+ /*
+ * If no socket given, open one
+ */
+ if (*sockp < 0) {
+ *sockp = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ (void)bindresvport(*sockp, (struct sockaddr_in *)0);
+ if ((*sockp < 0)
+ || (connect(*sockp, (struct sockaddr *)raddr,
+ sizeof(*raddr)) < 0)) {
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+ if (*sockp != -1)
+ (void)_RPC_close(*sockp);
+ goto fooy;
+ }
+ ct->ct_closeit = TRUE;
+ } else {
+ ct->ct_closeit = FALSE;
+ }
+
+ /*
+ * Set up private data struct
+ */
+ ct->ct_sock = *sockp;
+ ct->ct_wait.tv_usec = 0;
+ ct->ct_waitset = FALSE;
+ ct->ct_addr = *raddr;
+
+ /*
+ * Initialize call message
+ */
+ (void)gettimeofday(&now, (struct timezone *)0);
+ call_msg.rm_xid = (++disrupt) ^ getpid() ^ now.tv_sec ^ now.tv_usec;
+ call_msg.rm_direction = CALL;
+ call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+ call_msg.rm_call.cb_prog = prog;
+ call_msg.rm_call.cb_vers = vers;
+
+ /*
+ * pre-serialize the static part of the call msg and stash it away
+ */
+ xdrmem_create(&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE,
+ XDR_ENCODE);
+ if (! xdr_callhdr(&(ct->ct_xdrs), &call_msg)) {
+ if (ct->ct_closeit) {
+ (void)_RPC_close(*sockp);
+ }
+ goto fooy;
+ }
+ ct->ct_mpos = XDR_GETPOS(&(ct->ct_xdrs));
+ XDR_DESTROY(&(ct->ct_xdrs));
+
+ /*
+ * Create a client handle which uses xdrrec for serialization
+ * and authnone for authentication.
+ */
+ xdrrec_create(&(ct->ct_xdrs), sendsz, recvsz,
+ (caddr_t)ct, readtcp, writetcp);
+ h->cl_ops = &tcp_ops;
+ h->cl_private = (caddr_t) ct;
+ h->cl_auth = authnone_create();
+ return (h);
+
+fooy:
+ /*
+ * Something goofed, free stuff and barf
+ */
+ if (ct)
+ mem_free((caddr_t)ct, sizeof(struct ct_data));
+ if (h)
+ mem_free((caddr_t)h, sizeof(CLIENT));
+ return ((CLIENT *)NULL);
+}
+
+static enum clnt_stat
+clnttcp_call(h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout)
+ register CLIENT *h;
+ u_long proc;
+ xdrproc_t xdr_args;
+ caddr_t args_ptr;
+ xdrproc_t xdr_results;
+ caddr_t results_ptr;
+ struct timeval timeout;
+{
+ register struct ct_data *ct = (struct ct_data *) h->cl_private;
+ register XDR *xdrs = &(ct->ct_xdrs);
+ struct rpc_msg reply_msg;
+ u_long x_id;
+ u_int32_t *msg_x_id = (u_int32_t *)(ct->ct_mcall); /* yuk */
+ register bool_t shipnow;
+ int refreshes = 2;
+
+ if (!ct->ct_waitset) {
+ ct->ct_wait = timeout;
+ }
+
+ shipnow =
+ (xdr_results == (xdrproc_t)0 && timeout.tv_sec == 0
+ && timeout.tv_usec == 0) ? FALSE : TRUE;
+
+call_again:
+ xdrs->x_op = XDR_ENCODE;
+ ct->ct_error.re_status = RPC_SUCCESS;
+ x_id = ntohl(--(*msg_x_id));
+ if ((! XDR_PUTBYTES(xdrs, ct->ct_mcall, ct->ct_mpos)) ||
+ (! XDR_PUTLONG(xdrs, (long *)&proc)) ||
+ (! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
+ (! (*xdr_args)(xdrs, args_ptr))) {
+ if (ct->ct_error.re_status == RPC_SUCCESS)
+ ct->ct_error.re_status = RPC_CANTENCODEARGS;
+ (void)xdrrec_endofrecord(xdrs, TRUE);
+ return (ct->ct_error.re_status);
+ }
+ if (! xdrrec_endofrecord(xdrs, shipnow))
+ return (ct->ct_error.re_status = RPC_CANTSEND);
+ if (! shipnow)
+ return (RPC_SUCCESS);
+ /*
+ * Hack to provide rpc-based message passing
+ */
+ if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
+ return(ct->ct_error.re_status = RPC_TIMEDOUT);
+ }
+
+
+ /*
+ * Keep receiving until we get a valid transaction id
+ */
+ xdrs->x_op = XDR_DECODE;
+ while (TRUE) {
+ reply_msg.acpted_rply.ar_verf = _null_auth;
+ reply_msg.acpted_rply.ar_results.where = NULL;
+ reply_msg.acpted_rply.ar_results.proc = xdr_void;
+ if (! xdrrec_skiprecord(xdrs))
+ return (ct->ct_error.re_status);
+ /* now decode and validate the response header */
+ if (! xdr_replymsg(xdrs, &reply_msg)) {
+ if (ct->ct_error.re_status == RPC_SUCCESS)
+ continue;
+ return (ct->ct_error.re_status);
+ }
+ if (reply_msg.rm_xid == x_id)
+ break;
+ }
+
+ /*
+ * process header
+ */
+ _seterr_reply(&reply_msg, &(ct->ct_error));
+ if (ct->ct_error.re_status == RPC_SUCCESS) {
+ if (! AUTH_VALIDATE(h->cl_auth, &reply_msg.acpted_rply.ar_verf)) {
+ ct->ct_error.re_status = RPC_AUTHERROR;
+ ct->ct_error.re_why = AUTH_INVALIDRESP;
+ } else if (! (*xdr_results)(xdrs, results_ptr)) {
+ if (ct->ct_error.re_status == RPC_SUCCESS)
+ ct->ct_error.re_status = RPC_CANTDECODERES;
+ }
+ /* free verifier ... */
+ if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) {
+ xdrs->x_op = XDR_FREE;
+ (void)xdr_opaque_auth(xdrs, &(reply_msg.acpted_rply.ar_verf));
+ }
+ } /* end successful completion */
+ else {
+ /* maybe our credentials need to be refreshed ... */
+ if (refreshes-- && AUTH_REFRESH(h->cl_auth))
+ goto call_again;
+ } /* end of unsuccessful completion */
+ return (ct->ct_error.re_status);
+}
+
+static void
+clnttcp_geterr(h, errp)
+ CLIENT *h;
+ struct rpc_err *errp;
+{
+ register struct ct_data *ct =
+ (struct ct_data *) h->cl_private;
+
+ *errp = ct->ct_error;
+}
+
+static bool_t
+clnttcp_freeres(cl, xdr_res, res_ptr)
+ CLIENT *cl;
+ xdrproc_t xdr_res;
+ caddr_t res_ptr;
+{
+ register struct ct_data *ct = (struct ct_data *)cl->cl_private;
+ register XDR *xdrs = &(ct->ct_xdrs);
+
+ xdrs->x_op = XDR_FREE;
+ return ((*xdr_res)(xdrs, res_ptr));
+}
+
+static void
+clnttcp_abort()
+{
+}
+
+
+static bool_t
+clnttcp_control(cl, request, info)
+ CLIENT *cl;
+ int request;
+ char *info;
+{
+ register struct ct_data *ct = (struct ct_data *)cl->cl_private;
+ register struct timeval *tv;
+ int len;
+
+ switch (request) {
+ case CLSET_FD_CLOSE:
+ ct->ct_closeit = TRUE;
+ break;
+ case CLSET_FD_NCLOSE:
+ ct->ct_closeit = FALSE;
+ break;
+ case CLSET_TIMEOUT:
+ if (info == NULL)
+ return(FALSE);
+ tv = (struct timeval *)info;
+ ct->ct_wait.tv_sec = tv->tv_sec;
+ ct->ct_wait.tv_usec = tv->tv_usec;
+ ct->ct_waitset = TRUE;
+ break;
+ case CLGET_TIMEOUT:
+ if (info == NULL)
+ return(FALSE);
+ *(struct timeval *)info = ct->ct_wait;
+ break;
+ case CLGET_SERVER_ADDR:
+ if (info == NULL)
+ return(FALSE);
+ *(struct sockaddr_in *)info = ct->ct_addr;
+ break;
+ case CLGET_FD:
+ if (info == NULL)
+ return(FALSE);
+ *(int *)info = ct->ct_sock;
+ break;
+ case CLGET_XID:
+ /*
+ * use the knowledge that xid is the
+ * first element in the call structure *.
+ * This will get the xid of the PREVIOUS call
+ */
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)info = ntohl(*(u_long *)ct->ct_mcall);
+ break;
+ case CLSET_XID:
+ /* This will set the xid of the NEXT call */
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)ct->ct_mcall = htonl(*(u_long *)info - 1);
+ /* decrement by 1 as clnttcp_call() increments once */
+ case CLGET_VERS:
+ /*
+ * This RELIES on the information that, in the call body,
+ * the version number field is the fifth field from the
+ * begining of the RPC header. MUST be changed if the
+ * call_struct is changed
+ */
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)info = ntohl(*(u_long *)(ct->ct_mcall +
+ 4 * BYTES_PER_XDR_UNIT));
+ break;
+ case CLSET_VERS:
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)(ct->ct_mcall + 4 * BYTES_PER_XDR_UNIT)
+ = htonl(*(u_long *)info);
+ break;
+ case CLGET_PROG:
+ /*
+ * This RELIES on the information that, in the call body,
+ * the program number field is the field from the
+ * begining of the RPC header. MUST be changed if the
+ * call_struct is changed
+ */
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)info = ntohl(*(u_long *)(ct->ct_mcall +
+ 3 * BYTES_PER_XDR_UNIT));
+ break;
+ case CLSET_PROG:
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)(ct->ct_mcall + 3 * BYTES_PER_XDR_UNIT)
+ = htonl(*(u_long *)info);
+ break;
+ case CLGET_LOCAL_ADDR:
+ len = sizeof(struct sockaddr);
+ if (getsockname(ct->ct_sock, (struct sockaddr *)info, &len) <0)
+ return(FALSE);
+ break;
+ case CLGET_RETRY_TIMEOUT:
+ case CLSET_RETRY_TIMEOUT:
+ case CLGET_SVC_ADDR:
+ case CLSET_SVC_ADDR:
+ case CLSET_PUSH_TIMOD:
+ case CLSET_POP_TIMOD:
+ default:
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+static void
+clnttcp_destroy(h)
+ CLIENT *h;
+{
+ register struct ct_data *ct =
+ (struct ct_data *) h->cl_private;
+
+ if (ct->ct_closeit) {
+ (void)_RPC_close(ct->ct_sock);
+ }
+ XDR_DESTROY(&(ct->ct_xdrs));
+ mem_free((caddr_t)ct, sizeof(struct ct_data));
+ mem_free((caddr_t)h, sizeof(CLIENT));
+}
+
+/*
+ * Interface between xdr serializer and tcp connection.
+ * Behaves like the system calls, read & write, but keeps some error state
+ * around for the rpc level.
+ */
+static int
+readtcp(ct, buf, len)
+ register struct ct_data *ct;
+ caddr_t buf;
+ register int len;
+{
+ fd_set *fds, readfds;
+ struct timeval start, after, duration, delta, tmp, tv;
+ int r, save_errno;
+
+ if (len == 0)
+ return (0);
+
+ if (ct->ct_sock + 1 > FD_SETSIZE) {
+ int bytes = howmany(ct->ct_sock + 1, NFDBITS) * sizeof(fd_mask);
+ fds = (fd_set *)malloc(bytes);
+ if (fds == NULL)
+ return (-1);
+ memset(fds, 0, bytes);
+ } else {
+ fds = &readfds;
+ FD_ZERO(fds);
+ }
+
+ gettimeofday(&start, NULL);
+ delta = ct->ct_wait;
+ while (TRUE) {
+ /* XXX we know the other bits are still clear */
+ FD_SET(ct->ct_sock, fds);
+ tv = delta; /* in case select writes back */
+ r = select(ct->ct_sock+1, fds, NULL, NULL, &tv);
+ save_errno = errno;
+
+ gettimeofday(&after, NULL);
+ timersub(&start, &after, &duration);
+ timersub(&ct->ct_wait, &duration, &tmp);
+ delta = tmp;
+ if (delta.tv_sec < 0 || !timerisset(&delta))
+ r = 0;
+
+ switch (r) {
+ case 0:
+ if (fds != &readfds)
+ free(fds);
+ ct->ct_error.re_status = RPC_TIMEDOUT;
+ return (-1);
+
+ case -1:
+ if (errno == EINTR)
+ continue;
+ if (fds != &readfds)
+ free(fds);
+ ct->ct_error.re_status = RPC_CANTRECV;
+ ct->ct_error.re_errno = save_errno;
+ return (-1);
+ }
+ break;
+ }
+ switch (len = _RPC_read(ct->ct_sock, buf, len)) {
+
+ case 0:
+ /* premature eof */
+ ct->ct_error.re_errno = ECONNRESET;
+ ct->ct_error.re_status = RPC_CANTRECV;
+ len = -1; /* it's really an error */
+ break;
+
+ case -1:
+ ct->ct_error.re_errno = errno;
+ ct->ct_error.re_status = RPC_CANTRECV;
+ break;
+ }
+ return (len);
+}
+
+static int
+writetcp(ct, buf, len)
+ struct ct_data *ct;
+ caddr_t buf;
+ int len;
+{
+ register int i, cnt;
+
+ for (cnt = len; cnt > 0; cnt -= i, buf += i) {
+ if ((i = _RPC_write(ct->ct_sock, buf, cnt)) == -1) {
+ ct->ct_error.re_errno = errno;
+ ct->ct_error.re_status = RPC_CANTSEND;
+ return (-1);
+ }
+ }
+ return (len);
+}
diff --git a/cpukit/librpc/src/rpc/clnt_udp.c b/cpukit/librpc/src/rpc/clnt_udp.c
new file mode 100644
index 0000000000..38c684eabd
--- /dev/null
+++ b/cpukit/librpc/src/rpc/clnt_udp.c
@@ -0,0 +1,568 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)clnt_udp.c 1.39 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)clnt_udp.c 2.2 88/08/01 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/rpc/clnt_udp.c,v 1.15 2000/01/27 23:06:36 jasone Exp $";
+#endif
+
+/*
+ * clnt_udp.c, Implements a UDP/IP based, client side RPC.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netdb.h>
+#include <errno.h>
+#include <rpc/pmap_clnt.h>
+#include <sys/select.h>
+
+/*
+ * UDP bases client side rpc operations
+ */
+static enum clnt_stat clntudp_call();
+static void clntudp_abort();
+static void clntudp_geterr();
+static bool_t clntudp_freeres();
+static bool_t clntudp_control();
+static void clntudp_destroy();
+
+static struct clnt_ops udp_ops = {
+ clntudp_call,
+ clntudp_abort,
+ clntudp_geterr,
+ clntudp_freeres,
+ clntudp_destroy,
+ clntudp_control
+};
+
+/*
+ * Private data kept per client handle
+ */
+struct cu_data {
+ int cu_sock;
+ bool_t cu_closeit;
+ struct sockaddr_in cu_raddr;
+ int cu_rlen;
+ struct timeval cu_wait;
+ struct timeval cu_total;
+ struct rpc_err cu_error;
+ XDR cu_outxdrs;
+ u_int cu_xdrpos;
+ u_int cu_sendsz;
+ char *cu_outbuf;
+ u_int cu_recvsz;
+ char cu_inbuf[1];
+};
+
+/*
+ * Create a UDP based client handle.
+ * If *sockp<0, *sockp is set to a newly created UPD socket.
+ * If raddr->sin_port is 0 a binder on the remote machine
+ * is consulted for the correct port number.
+ * NB: It is the clients responsibility to close *sockp.
+ * NB: The rpch->cl_auth is initialized to null authentication.
+ * Caller may wish to set this something more useful.
+ *
+ * wait is the amount of time used between retransmitting a call if
+ * no response has been heard; retransmition occurs until the actual
+ * rpc call times out.
+ *
+ * sendsz and recvsz are the maximum allowable packet sizes that can be
+ * sent and received.
+ */
+CLIENT *
+clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz)
+ struct sockaddr_in *raddr;
+ u_long program;
+ u_long version;
+ struct timeval wait;
+ register int *sockp;
+ u_int sendsz;
+ u_int recvsz;
+{
+ CLIENT *cl;
+ register struct cu_data *cu = NULL;
+ struct timeval now;
+ struct rpc_msg call_msg;
+ static u_int32_t disrupt;
+
+ if (disrupt == 0)
+ disrupt = (u_int32_t)(long)raddr;
+
+ cl = (CLIENT *)mem_alloc(sizeof(CLIENT));
+ if (cl == NULL) {
+ (void) fprintf(stderr, "clntudp_create: out of memory\n");
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+ goto fooy;
+ }
+ sendsz = ((sendsz + 3) / 4) * 4;
+ recvsz = ((recvsz + 3) / 4) * 4;
+ cu = (struct cu_data *)mem_alloc(sizeof(*cu) + sendsz + recvsz);
+ if (cu == NULL) {
+ (void) fprintf(stderr, "clntudp_create: out of memory\n");
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+ goto fooy;
+ }
+ cu->cu_outbuf = &cu->cu_inbuf[recvsz];
+
+ (void)gettimeofday(&now, (struct timezone *)0);
+ if (raddr->sin_port == 0) {
+ u_short port;
+ if ((port =
+ pmap_getport(raddr, program, version, IPPROTO_UDP)) == 0) {
+ goto fooy;
+ }
+ raddr->sin_port = htons(port);
+ }
+ cl->cl_ops = &udp_ops;
+ cl->cl_private = (caddr_t)cu;
+ cu->cu_raddr = *raddr;
+ cu->cu_rlen = sizeof (cu->cu_raddr);
+ cu->cu_wait = wait;
+ cu->cu_total.tv_sec = -1;
+ cu->cu_total.tv_usec = -1;
+ cu->cu_sendsz = sendsz;
+ cu->cu_recvsz = recvsz;
+ call_msg.rm_xid = (++disrupt) ^ getpid() ^ now.tv_sec ^ now.tv_usec;
+ call_msg.rm_direction = CALL;
+ call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+ call_msg.rm_call.cb_prog = program;
+ call_msg.rm_call.cb_vers = version;
+ xdrmem_create(&(cu->cu_outxdrs), cu->cu_outbuf,
+ sendsz, XDR_ENCODE);
+ if (! xdr_callhdr(&(cu->cu_outxdrs), &call_msg)) {
+ goto fooy;
+ }
+ cu->cu_xdrpos = XDR_GETPOS(&(cu->cu_outxdrs));
+ if (*sockp < 0) {
+ int dontblock = 1;
+
+ *sockp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (*sockp < 0) {
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+ goto fooy;
+ }
+ /* attempt to bind to priv port */
+ (void)bindresvport(*sockp, (struct sockaddr_in *)0);
+ /* the sockets rpc controls are non-blocking */
+ (void)ioctl(*sockp, FIONBIO, (char *) &dontblock);
+ cu->cu_closeit = TRUE;
+ } else {
+ cu->cu_closeit = FALSE;
+ }
+ cu->cu_sock = *sockp;
+ cl->cl_auth = authnone_create();
+ return (cl);
+fooy:
+ if (cu)
+ mem_free((caddr_t)cu, sizeof(*cu) + sendsz + recvsz);
+ if (cl)
+ mem_free((caddr_t)cl, sizeof(CLIENT));
+ return ((CLIENT *)NULL);
+}
+
+CLIENT *
+clntudp_create(raddr, program, version, wait, sockp)
+ struct sockaddr_in *raddr;
+ u_long program;
+ u_long version;
+ struct timeval wait;
+ register int *sockp;
+{
+
+ return(clntudp_bufcreate(raddr, program, version, wait, sockp,
+ UDPMSGSIZE, UDPMSGSIZE));
+}
+
+static enum clnt_stat
+clntudp_call(cl, proc, xargs, argsp, xresults, resultsp, utimeout)
+ register CLIENT *cl; /* client handle */
+ u_long proc; /* procedure number */
+ xdrproc_t xargs; /* xdr routine for args */
+ caddr_t argsp; /* pointer to args */
+ xdrproc_t xresults; /* xdr routine for results */
+ caddr_t resultsp; /* pointer to results */
+ struct timeval utimeout; /* seconds to wait before giving up */
+{
+ register struct cu_data *cu = (struct cu_data *)cl->cl_private;
+ register XDR *xdrs;
+ register int outlen;
+ register int inlen;
+ int fromlen;
+ fd_set *fds, readfds;
+ struct sockaddr_in from;
+ struct rpc_msg reply_msg;
+ XDR reply_xdrs;
+ struct timeval time_waited, start, after, tmp1, tmp2, tv;
+ bool_t ok;
+ int nrefreshes = 2; /* number of times to refresh cred */
+ struct timeval timeout;
+
+ if (cu->cu_total.tv_usec == -1)
+ timeout = utimeout; /* use supplied timeout */
+ else
+ timeout = cu->cu_total; /* use default timeout */
+
+ if (cu->cu_sock + 1 > FD_SETSIZE) {
+ int bytes = howmany(cu->cu_sock + 1, NFDBITS) * sizeof(fd_mask);
+ fds = (fd_set *)malloc(bytes);
+ if (fds == NULL)
+ return (cu->cu_error.re_status = RPC_CANTSEND);
+ memset(fds, 0, bytes);
+ } else {
+ fds = &readfds;
+ FD_ZERO(fds);
+ }
+
+ timerclear(&time_waited);
+
+call_again:
+ xdrs = &(cu->cu_outxdrs);
+ xdrs->x_op = XDR_ENCODE;
+ XDR_SETPOS(xdrs, cu->cu_xdrpos);
+ /*
+ * the transaction is the first thing in the out buffer
+ */
+ (*(u_short *)(cu->cu_outbuf))++;
+ if ((! XDR_PUTLONG(xdrs, (long *)&proc)) ||
+ (! AUTH_MARSHALL(cl->cl_auth, xdrs)) ||
+ (! (*xargs)(xdrs, argsp))) {
+ if (fds != &readfds)
+ free(fds);
+ return (cu->cu_error.re_status = RPC_CANTENCODEARGS);
+ }
+ outlen = (int)XDR_GETPOS(xdrs);
+
+send_again:
+ if (sendto(cu->cu_sock, cu->cu_outbuf, outlen, 0,
+ (struct sockaddr *)&(cu->cu_raddr), cu->cu_rlen) != outlen) {
+ cu->cu_error.re_errno = errno;
+ if (fds != &readfds)
+ free(fds);
+ return (cu->cu_error.re_status = RPC_CANTSEND);
+ }
+
+ /*
+ * Hack to provide rpc-based message passing
+ */
+ if (!timerisset(&timeout)) {
+ if (fds != &readfds)
+ free(fds);
+ return (cu->cu_error.re_status = RPC_TIMEDOUT);
+ }
+ /*
+ * sub-optimal code appears here because we have
+ * some clock time to spare while the packets are in flight.
+ * (We assume that this is actually only executed once.)
+ */
+ reply_msg.acpted_rply.ar_verf = _null_auth;
+ reply_msg.acpted_rply.ar_results.where = resultsp;
+ reply_msg.acpted_rply.ar_results.proc = xresults;
+
+ gettimeofday(&start, NULL);
+ for (;;) {
+ /* XXX we know the other bits are still clear */
+ FD_SET(cu->cu_sock, fds);
+ tv = cu->cu_wait;
+ switch (select(cu->cu_sock+1, fds, NULL, NULL, &tv)) {
+
+ case 0:
+ timeradd(&time_waited, &cu->cu_wait, &tmp1);
+ time_waited = tmp1;
+ if (timercmp(&time_waited, &timeout, <))
+ goto send_again;
+ if (fds != &readfds)
+ free(fds);
+ return (cu->cu_error.re_status = RPC_TIMEDOUT);
+
+ case -1:
+ if (errno == EINTR) {
+ gettimeofday(&after, NULL);
+ timersub(&after, &start, &tmp1);
+ timeradd(&time_waited, &tmp1, &tmp2);
+ time_waited = tmp2;
+ if (timercmp(&time_waited, &timeout, <))
+ continue;
+ if (fds != &readfds)
+ free(fds);
+ return (cu->cu_error.re_status = RPC_TIMEDOUT);
+ }
+ cu->cu_error.re_errno = errno;
+ if (fds != &readfds)
+ free(fds);
+ return (cu->cu_error.re_status = RPC_CANTRECV);
+ }
+
+ do {
+ fromlen = sizeof(struct sockaddr);
+ inlen = recvfrom(cu->cu_sock, cu->cu_inbuf,
+ (int) cu->cu_recvsz, 0,
+ (struct sockaddr *)&from, &fromlen);
+ } while (inlen < 0 && errno == EINTR);
+ if (inlen < 0) {
+ if (errno == EWOULDBLOCK)
+ continue;
+ cu->cu_error.re_errno = errno;
+ if (fds != &readfds)
+ free(fds);
+ return (cu->cu_error.re_status = RPC_CANTRECV);
+ }
+ if (inlen < sizeof(u_int32_t))
+ continue;
+ /* see if reply transaction id matches sent id */
+ if (*((u_int32_t *)(cu->cu_inbuf)) != *((u_int32_t *)(cu->cu_outbuf)))
+ continue;
+ /* we now assume we have the proper reply */
+ break;
+ }
+
+ /*
+ * now decode and validate the response
+ */
+ xdrmem_create(&reply_xdrs, cu->cu_inbuf, (u_int)inlen, XDR_DECODE);
+ ok = xdr_replymsg(&reply_xdrs, &reply_msg);
+ /* XDR_DESTROY(&reply_xdrs); save a few cycles on noop destroy */
+ if (ok) {
+ _seterr_reply(&reply_msg, &(cu->cu_error));
+ if (cu->cu_error.re_status == RPC_SUCCESS) {
+ if (! AUTH_VALIDATE(cl->cl_auth,
+ &reply_msg.acpted_rply.ar_verf)) {
+ cu->cu_error.re_status = RPC_AUTHERROR;
+ cu->cu_error.re_why = AUTH_INVALIDRESP;
+ }
+ if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) {
+ xdrs->x_op = XDR_FREE;
+ (void)xdr_opaque_auth(xdrs,
+ &(reply_msg.acpted_rply.ar_verf));
+ }
+ } /* end successful completion */
+ else {
+ /* maybe our credentials need to be refreshed ... */
+ if (nrefreshes > 0 && AUTH_REFRESH(cl->cl_auth)) {
+ nrefreshes--;
+ goto call_again;
+ }
+ } /* end of unsuccessful completion */
+ } /* end of valid reply message */
+ else {
+ /*
+ * It's possible for xdr_replymsg() to fail partway
+ * through its attempt to decode the result from the
+ * server. If this happens, it will leave the reply
+ * structure partially populated with dynamically
+ * allocated memory. (This can happen if someone uses
+ * clntudp_bufcreate() to create a CLIENT handle and
+ * specifies a receive buffer size that is too small.)
+ * This memory must be free()ed to avoid a leak.
+ */
+ int op = reply_xdrs.x_op;
+ reply_xdrs.x_op = XDR_FREE;
+ xdr_replymsg(&reply_xdrs, &reply_msg);
+ reply_xdrs.x_op = op;
+ cu->cu_error.re_status = RPC_CANTDECODERES;
+ }
+ if (fds != &readfds)
+ free(fds);
+ return (cu->cu_error.re_status);
+}
+
+static void
+clntudp_geterr(cl, errp)
+ CLIENT *cl;
+ struct rpc_err *errp;
+{
+ register struct cu_data *cu = (struct cu_data *)cl->cl_private;
+
+ *errp = cu->cu_error;
+}
+
+
+static bool_t
+clntudp_freeres(cl, xdr_res, res_ptr)
+ CLIENT *cl;
+ xdrproc_t xdr_res;
+ caddr_t res_ptr;
+{
+ register struct cu_data *cu = (struct cu_data *)cl->cl_private;
+ register XDR *xdrs = &(cu->cu_outxdrs);
+
+ xdrs->x_op = XDR_FREE;
+ return ((*xdr_res)(xdrs, res_ptr));
+}
+
+static void
+clntudp_abort(/*h*/)
+ /*CLIENT *h;*/
+{
+}
+
+
+static bool_t
+clntudp_control(cl, request, info)
+ CLIENT *cl;
+ int request;
+ char *info;
+{
+ register struct cu_data *cu = (struct cu_data *)cl->cl_private;
+ register struct timeval *tv;
+ int len;
+
+ switch (request) {
+ case CLSET_FD_CLOSE:
+ cu->cu_closeit = TRUE;
+ break;
+ case CLSET_FD_NCLOSE:
+ cu->cu_closeit = FALSE;
+ break;
+ case CLSET_TIMEOUT:
+ if (info == NULL)
+ return(FALSE);
+ tv = (struct timeval *)info;
+ cu->cu_total.tv_sec = tv->tv_sec;
+ cu->cu_total.tv_usec = tv->tv_usec;
+ break;
+ case CLGET_TIMEOUT:
+ if (info == NULL)
+ return(FALSE);
+ *(struct timeval *)info = cu->cu_total;
+ break;
+ case CLSET_RETRY_TIMEOUT:
+ if (info == NULL)
+ return(FALSE);
+ tv = (struct timeval *)info;
+ cu->cu_wait.tv_sec = tv->tv_sec;
+ cu->cu_wait.tv_usec = tv->tv_usec;
+ break;
+ case CLGET_RETRY_TIMEOUT:
+ if (info == NULL)
+ return(FALSE);
+ *(struct timeval *)info = cu->cu_wait;
+ break;
+ case CLGET_SERVER_ADDR:
+ if (info == NULL)
+ return(FALSE);
+ *(struct sockaddr_in *)info = cu->cu_raddr;
+ break;
+ case CLGET_FD:
+ if (info == NULL)
+ return(FALSE);
+ *(int *)info = cu->cu_sock;
+ break;
+ case CLGET_XID:
+ /*
+ * use the knowledge that xid is the
+ * first element in the call structure *.
+ * This will get the xid of the PREVIOUS call
+ */
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)info = ntohl(*(u_long *)cu->cu_outbuf);
+ break;
+ case CLSET_XID:
+ /* This will set the xid of the NEXT call */
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)cu->cu_outbuf = htonl(*(u_long *)info - 1);
+ /* decrement by 1 as clntudp_call() increments once */
+ case CLGET_VERS:
+ /*
+ * This RELIES on the information that, in the call body,
+ * the version number field is the fifth field from the
+ * begining of the RPC header. MUST be changed if the
+ * call_struct is changed
+ */
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)info = ntohl(*(u_long *)(cu->cu_outbuf +
+ 4 * BYTES_PER_XDR_UNIT));
+ break;
+ case CLSET_VERS:
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)(cu->cu_outbuf + 4 * BYTES_PER_XDR_UNIT)
+ = htonl(*(u_long *)info);
+ break;
+ case CLGET_PROG:
+ /*
+ * This RELIES on the information that, in the call body,
+ * the program number field is the field from the
+ * begining of the RPC header. MUST be changed if the
+ * call_struct is changed
+ */
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)info = ntohl(*(u_long *)(cu->cu_outbuf +
+ 3 * BYTES_PER_XDR_UNIT));
+ break;
+ case CLSET_PROG:
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)(cu->cu_outbuf + 3 * BYTES_PER_XDR_UNIT)
+ = htonl(*(u_long *)info);
+ break;
+ case CLGET_LOCAL_ADDR:
+ len = sizeof(struct sockaddr);
+ if (getsockname(cu->cu_sock, (struct sockaddr *)info, &len) <0)
+ return(FALSE);
+ break;
+ case CLGET_SVC_ADDR:
+ case CLSET_SVC_ADDR:
+ case CLSET_PUSH_TIMOD:
+ case CLSET_POP_TIMOD:
+ default:
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+static void
+clntudp_destroy(cl)
+ CLIENT *cl;
+{
+ register struct cu_data *cu = (struct cu_data *)cl->cl_private;
+
+ if (cu->cu_closeit) {
+ (void)_RPC_close(cu->cu_sock);
+ }
+ XDR_DESTROY(&(cu->cu_outxdrs));
+ mem_free((caddr_t)cu, (sizeof(*cu) + cu->cu_sendsz + cu->cu_recvsz));
+ mem_free((caddr_t)cl, sizeof(CLIENT));
+}
diff --git a/cpukit/librpc/src/rpc/clnt_unix.c b/cpukit/librpc/src/rpc/clnt_unix.c
new file mode 100644
index 0000000000..0cfe988595
--- /dev/null
+++ b/cpukit/librpc/src/rpc/clnt_unix.c
@@ -0,0 +1,635 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)clnt_unix.c 1.37 87/10/05 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)clnt_unix.c 2.2 88/08/01 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/rpc/clnt_unix.c,v 1.5 2000/01/27 23:06:37 jasone Exp $";
+#endif
+
+/*
+ * clnt_unix.c, Implements a AF_UNIX based, client side RPC.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * AF_UNIX based RPC supports 'batched calls'.
+ * A sequence of calls may be batched-up in a send buffer. The rpc call
+ * return immediately to the client even though the call was not necessarily
+ * sent. The batching occurs if the results' xdr routine is NULL (0) AND
+ * the rpc timeout value is zero (see clnt.h, rpc).
+ *
+ * Clients should NOT casually batch calls that in fact return results; that is,
+ * the server side should be aware that a call is batched and not produce any
+ * return message. Batched calls that produce many result messages can
+ * deadlock (netlock) the client and the server....
+ *
+ * Now go hang yourself.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netdb.h>
+#include <errno.h>
+#include <rpc/pmap_clnt.h>
+
+#define MCALL_MSG_SIZE 24
+
+static int readunix();
+static int writeunix();
+
+static enum clnt_stat clntunix_call();
+static void clntunix_abort();
+static void clntunix_geterr();
+static bool_t clntunix_freeres();
+static bool_t clntunix_control();
+static void clntunix_destroy();
+
+static struct clnt_ops unix_ops = {
+ clntunix_call,
+ clntunix_abort,
+ clntunix_geterr,
+ clntunix_freeres,
+ clntunix_destroy,
+ clntunix_control
+};
+
+struct ct_data {
+ int ct_sock;
+ bool_t ct_closeit;
+ struct timeval ct_wait;
+ bool_t ct_waitset; /* wait set by clnt_control? */
+ struct sockaddr_un ct_addr;
+ struct rpc_err ct_error;
+ char ct_mcall[MCALL_MSG_SIZE]; /* marshalled callmsg */
+ u_int ct_mpos; /* pos after marshal */
+ XDR ct_xdrs;
+};
+
+/*
+ * Create a client handle for a unix/ip connection.
+ * If *sockp<0, *sockp is set to a newly created TCP socket and it is
+ * connected to raddr. If *sockp non-negative then
+ * raddr is ignored. The rpc/unix package does buffering
+ * similar to stdio, so the client must pick send and receive buffer sizes,];
+ * 0 => use the default.
+ * If raddr->sin_port is 0, then a binder on the remote machine is
+ * consulted for the right port number.
+ * NB: *sockp is copied into a private area.
+ * NB: It is the clients responsibility to close *sockp.
+ * NB: The rpch->cl_auth is set null authentication. Caller may wish to set this
+ * something more useful.
+ */
+CLIENT *
+clntunix_create(raddr, prog, vers, sockp, sendsz, recvsz)
+ struct sockaddr_un *raddr;
+ u_long prog;
+ u_long vers;
+ register int *sockp;
+ u_int sendsz;
+ u_int recvsz;
+{
+ CLIENT *h;
+ register struct ct_data *ct = NULL;
+ struct timeval now;
+ struct rpc_msg call_msg;
+ static u_int32_t disrupt;
+ int len;
+
+ if (disrupt == 0)
+ disrupt = (u_int32_t)(long)raddr;
+
+ h = (CLIENT *)mem_alloc(sizeof(*h));
+ if (h == NULL) {
+ (void)fprintf(stderr, "clntunix_create: out of memory\n");
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+ goto fooy;
+ }
+ ct = (struct ct_data *)mem_alloc(sizeof(*ct));
+ if (ct == NULL) {
+ (void)fprintf(stderr, "clntunix_create: out of memory\n");
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+ goto fooy;
+ }
+
+ /*
+ * If no socket given, open one
+ */
+ if (*sockp < 0) {
+ *sockp = socket(AF_UNIX, SOCK_STREAM, 0);
+ len = strlen(raddr->sun_path) + sizeof(raddr->sun_family) +
+ sizeof(raddr->sun_len) + 1;
+ raddr->sun_len = len;
+ if ((*sockp < 0)
+ || (connect(*sockp, (struct sockaddr *)raddr, len) < 0)) {
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+ if (*sockp != -1)
+ (void)_RPC_close(*sockp);
+ goto fooy;
+ }
+ ct->ct_closeit = TRUE;
+ } else {
+ ct->ct_closeit = FALSE;
+ }
+
+ /*
+ * Set up private data struct
+ */
+ ct->ct_sock = *sockp;
+ ct->ct_wait.tv_usec = 0;
+ ct->ct_waitset = FALSE;
+ ct->ct_addr = *raddr;
+
+ /*
+ * Initialize call message
+ */
+ (void)gettimeofday(&now, (struct timezone *)0);
+ call_msg.rm_xid = (++disrupt) ^ getpid() ^ now.tv_sec ^ now.tv_usec;
+ call_msg.rm_direction = CALL;
+ call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+ call_msg.rm_call.cb_prog = prog;
+ call_msg.rm_call.cb_vers = vers;
+
+ /*
+ * pre-serialize the static part of the call msg and stash it away
+ */
+ xdrmem_create(&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE,
+ XDR_ENCODE);
+ if (! xdr_callhdr(&(ct->ct_xdrs), &call_msg)) {
+ if (ct->ct_closeit) {
+ (void)_RPC_close(*sockp);
+ }
+ goto fooy;
+ }
+ ct->ct_mpos = XDR_GETPOS(&(ct->ct_xdrs));
+ XDR_DESTROY(&(ct->ct_xdrs));
+
+ /*
+ * Create a client handle which uses xdrrec for serialization
+ * and authnone for authentication.
+ */
+ xdrrec_create(&(ct->ct_xdrs), sendsz, recvsz,
+ (caddr_t)ct, readunix, writeunix);
+ h->cl_ops = &unix_ops;
+ h->cl_private = (caddr_t) ct;
+ h->cl_auth = authnone_create();
+ return (h);
+
+fooy:
+ /*
+ * Something goofed, free stuff and barf
+ */
+ if (ct)
+ mem_free((caddr_t)ct, sizeof(struct ct_data));
+ if (h)
+ mem_free((caddr_t)h, sizeof(CLIENT));
+ return ((CLIENT *)NULL);
+}
+
+static enum clnt_stat
+clntunix_call(h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout)
+ register CLIENT *h;
+ u_long proc;
+ xdrproc_t xdr_args;
+ caddr_t args_ptr;
+ xdrproc_t xdr_results;
+ caddr_t results_ptr;
+ struct timeval timeout;
+{
+ register struct ct_data *ct = (struct ct_data *) h->cl_private;
+ register XDR *xdrs = &(ct->ct_xdrs);
+ struct rpc_msg reply_msg;
+ u_long x_id;
+ u_int32_t *msg_x_id = (u_int32_t *)(ct->ct_mcall); /* yuk */
+ register bool_t shipnow;
+ int refreshes = 2;
+
+ if (!ct->ct_waitset) {
+ ct->ct_wait = timeout;
+ }
+
+ shipnow =
+ (xdr_results == (xdrproc_t)0 && timeout.tv_sec == 0
+ && timeout.tv_usec == 0) ? FALSE : TRUE;
+
+call_again:
+ xdrs->x_op = XDR_ENCODE;
+ ct->ct_error.re_status = RPC_SUCCESS;
+ x_id = ntohl(--(*msg_x_id));
+ if ((! XDR_PUTBYTES(xdrs, ct->ct_mcall, ct->ct_mpos)) ||
+ (! XDR_PUTLONG(xdrs, (long *)&proc)) ||
+ (! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
+ (! (*xdr_args)(xdrs, args_ptr))) {
+ if (ct->ct_error.re_status == RPC_SUCCESS)
+ ct->ct_error.re_status = RPC_CANTENCODEARGS;
+ (void)xdrrec_endofrecord(xdrs, TRUE);
+ return (ct->ct_error.re_status);
+ }
+ if (! xdrrec_endofrecord(xdrs, shipnow))
+ return (ct->ct_error.re_status = RPC_CANTSEND);
+ if (! shipnow)
+ return (RPC_SUCCESS);
+ /*
+ * Hack to provide rpc-based message passing
+ */
+ if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
+ return(ct->ct_error.re_status = RPC_TIMEDOUT);
+ }
+
+
+ /*
+ * Keep receiving until we get a valid transaction id
+ */
+ xdrs->x_op = XDR_DECODE;
+ while (TRUE) {
+ reply_msg.acpted_rply.ar_verf = _null_auth;
+ reply_msg.acpted_rply.ar_results.where = NULL;
+ reply_msg.acpted_rply.ar_results.proc = xdr_void;
+ if (! xdrrec_skiprecord(xdrs))
+ return (ct->ct_error.re_status);
+ /* now decode and validate the response header */
+ if (! xdr_replymsg(xdrs, &reply_msg)) {
+ if (ct->ct_error.re_status == RPC_SUCCESS)
+ continue;
+ return (ct->ct_error.re_status);
+ }
+ if (reply_msg.rm_xid == x_id)
+ break;
+ }
+
+ /*
+ * process header
+ */
+ _seterr_reply(&reply_msg, &(ct->ct_error));
+ if (ct->ct_error.re_status == RPC_SUCCESS) {
+ if (! AUTH_VALIDATE(h->cl_auth, &reply_msg.acpted_rply.ar_verf)) {
+ ct->ct_error.re_status = RPC_AUTHERROR;
+ ct->ct_error.re_why = AUTH_INVALIDRESP;
+ } else if (! (*xdr_results)(xdrs, results_ptr)) {
+ if (ct->ct_error.re_status == RPC_SUCCESS)
+ ct->ct_error.re_status = RPC_CANTDECODERES;
+ }
+ /* free verifier ... */
+ if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) {
+ xdrs->x_op = XDR_FREE;
+ (void)xdr_opaque_auth(xdrs, &(reply_msg.acpted_rply.ar_verf));
+ }
+ } /* end successful completion */
+ else {
+ /* maybe our credentials need to be refreshed ... */
+ if (refreshes-- && AUTH_REFRESH(h->cl_auth))
+ goto call_again;
+ } /* end of unsuccessful completion */
+ return (ct->ct_error.re_status);
+}
+
+static void
+clntunix_geterr(h, errp)
+ CLIENT *h;
+ struct rpc_err *errp;
+{
+ register struct ct_data *ct =
+ (struct ct_data *) h->cl_private;
+
+ *errp = ct->ct_error;
+}
+
+static bool_t
+clntunix_freeres(cl, xdr_res, res_ptr)
+ CLIENT *cl;
+ xdrproc_t xdr_res;
+ caddr_t res_ptr;
+{
+ register struct ct_data *ct = (struct ct_data *)cl->cl_private;
+ register XDR *xdrs = &(ct->ct_xdrs);
+
+ xdrs->x_op = XDR_FREE;
+ return ((*xdr_res)(xdrs, res_ptr));
+}
+
+static void
+clntunix_abort()
+{
+}
+
+
+static bool_t
+clntunix_control(cl, request, info)
+ CLIENT *cl;
+ int request;
+ char *info;
+{
+ register struct ct_data *ct = (struct ct_data *)cl->cl_private;
+ register struct timeval *tv;
+ int len;
+
+ switch (request) {
+ case CLSET_FD_CLOSE:
+ ct->ct_closeit = TRUE;
+ break;
+ case CLSET_FD_NCLOSE:
+ ct->ct_closeit = FALSE;
+ break;
+ case CLSET_TIMEOUT:
+ if (info == NULL)
+ return(FALSE);
+ tv = (struct timeval *)info;
+ ct->ct_wait.tv_sec = tv->tv_sec;
+ ct->ct_wait.tv_usec = tv->tv_usec;
+ ct->ct_waitset = TRUE;
+ break;
+ case CLGET_TIMEOUT:
+ if (info == NULL)
+ return(FALSE);
+ *(struct timeval *)info = ct->ct_wait;
+ break;
+ case CLGET_SERVER_ADDR:
+ if (info == NULL)
+ return(FALSE);
+ *(struct sockaddr_un *)info = ct->ct_addr;
+ break;
+ case CLGET_FD:
+ if (info == NULL)
+ return(FALSE);
+ *(int *)info = ct->ct_sock;
+ break;
+ case CLGET_XID:
+ /*
+ * use the knowledge that xid is the
+ * first element in the call structure *.
+ * This will get the xid of the PREVIOUS call
+ */
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)info = ntohl(*(u_long *)ct->ct_mcall);
+ break;
+ case CLSET_XID:
+ /* This will set the xid of the NEXT call */
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)ct->ct_mcall = htonl(*(u_long *)info - 1);
+ /* decrement by 1 as clntunix_call() increments once */
+ case CLGET_VERS:
+ /*
+ * This RELIES on the information that, in the call body,
+ * the version number field is the fifth field from the
+ * begining of the RPC header. MUST be changed if the
+ * call_struct is changed
+ */
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)info = ntohl(*(u_long *)(ct->ct_mcall +
+ 4 * BYTES_PER_XDR_UNIT));
+ break;
+ case CLSET_VERS:
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)(ct->ct_mcall + 4 * BYTES_PER_XDR_UNIT)
+ = htonl(*(u_long *)info);
+ break;
+ case CLGET_PROG:
+ /*
+ * This RELIES on the information that, in the call body,
+ * the program number field is the field from the
+ * begining of the RPC header. MUST be changed if the
+ * call_struct is changed
+ */
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)info = ntohl(*(u_long *)(ct->ct_mcall +
+ 3 * BYTES_PER_XDR_UNIT));
+ break;
+ case CLSET_PROG:
+ if (info == NULL)
+ return(FALSE);
+ *(u_long *)(ct->ct_mcall + 3 * BYTES_PER_XDR_UNIT)
+ = htonl(*(u_long *)info);
+ break;
+ case CLGET_LOCAL_ADDR:
+ len = sizeof(struct sockaddr);
+ if (getsockname(ct->ct_sock, (struct sockaddr *)info, &len) <0)
+ return(FALSE);
+ break;
+ case CLGET_RETRY_TIMEOUT:
+ case CLSET_RETRY_TIMEOUT:
+ case CLGET_SVC_ADDR:
+ case CLSET_SVC_ADDR:
+ case CLSET_PUSH_TIMOD:
+ case CLSET_POP_TIMOD:
+ default:
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+static void
+clntunix_destroy(h)
+ CLIENT *h;
+{
+ register struct ct_data *ct =
+ (struct ct_data *) h->cl_private;
+
+ if (ct->ct_closeit) {
+ (void)_RPC_close(ct->ct_sock);
+ }
+ XDR_DESTROY(&(ct->ct_xdrs));
+ mem_free((caddr_t)ct, sizeof(struct ct_data));
+ mem_free((caddr_t)h, sizeof(CLIENT));
+}
+
+/*
+ * read() and write() are replaced with recvmsg()/sendmsg() so that
+ * we can pass ancillary control data. In this case, the data constists
+ * of credential information which the kernel will fill in for us.
+ * XXX: This code is specific to FreeBSD and will not work on other
+ * platforms without the requisite kernel modifications.
+ */
+struct cmessage {
+ struct cmsghdr cmsg;
+ struct cmsgcred cmcred;
+};
+
+static int __msgread(sock, buf, cnt)
+ int sock;
+ void *buf;
+ size_t cnt;
+{
+ struct iovec iov[1];
+ struct msghdr msg;
+ struct cmessage cm;
+
+ bzero((char *)&cm, sizeof(cm));
+ iov[0].iov_base = buf;
+ iov[0].iov_len = cnt;
+
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_control = (caddr_t)&cm;
+ msg.msg_controllen = sizeof(struct cmessage);
+ msg.msg_flags = 0;
+
+ return(recvmsg(sock, &msg, 0));
+}
+
+static int __msgwrite(sock, buf, cnt)
+ int sock;
+ void *buf;
+ size_t cnt;
+{
+ struct iovec iov[1];
+ struct msghdr msg;
+ struct cmessage cm;
+
+ bzero((char *)&cm, sizeof(cm));
+ iov[0].iov_base = buf;
+ iov[0].iov_len = cnt;
+
+ cm.cmsg.cmsg_type = SCM_CREDS;
+ cm.cmsg.cmsg_level = SOL_SOCKET;
+ cm.cmsg.cmsg_len = sizeof(struct cmessage);
+
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_control = (caddr_t)&cm;
+ msg.msg_controllen = sizeof(struct cmessage);
+ msg.msg_flags = 0;
+
+ return(sendmsg(sock, &msg, 0));
+}
+
+/*
+ * Interface between xdr serializer and unix connection.
+ * Behaves like the system calls, read & write, but keeps some error state
+ * around for the rpc level.
+ */
+static int
+readunix(ct, buf, len)
+ register struct ct_data *ct;
+ caddr_t buf;
+ register int len;
+{
+ fd_set *fds, readfds;
+ struct timeval start, after, duration, delta, tmp, tv;
+ int r, save_errno;
+
+ if (len == 0)
+ return (0);
+
+ if (ct->ct_sock + 1 > FD_SETSIZE) {
+ int bytes = howmany(ct->ct_sock + 1, NFDBITS) * sizeof(fd_mask);
+ fds = (fd_set *)malloc(bytes);
+ if (fds == NULL)
+ return (-1);
+ memset(fds, 0, bytes);
+ } else {
+ fds = &readfds;
+ FD_ZERO(fds);
+ }
+
+ gettimeofday(&start, NULL);
+ delta = ct->ct_wait;
+ while (TRUE) {
+ /* XXX we know the other bits are still clear */
+ FD_SET(ct->ct_sock, fds);
+ tv = delta; /* in case select writes back */
+ r = select(ct->ct_sock+1, fds, NULL, NULL, &tv);
+ save_errno = errno;
+
+ gettimeofday(&after, NULL);
+ timersub(&start, &after, &duration);
+ timersub(&delta, &duration, &tmp);
+ delta = tmp;
+ if (delta.tv_sec < 0 || !timerisset(&delta))
+ r = 0;
+
+ switch (r) {
+ case 0:
+ if (fds != &readfds)
+ free(fds);
+ ct->ct_error.re_status = RPC_TIMEDOUT;
+ return (-1);
+
+ case -1:
+ if (errno == EINTR)
+ continue;
+ if (fds != &readfds)
+ free(fds);
+ ct->ct_error.re_status = RPC_CANTRECV;
+ ct->ct_error.re_errno = save_errno;
+ return (-1);
+ }
+ break;
+ }
+ switch (len = __msgread(ct->ct_sock, buf, len)) {
+
+ case 0:
+ /* premature eof */
+ ct->ct_error.re_errno = ECONNRESET;
+ ct->ct_error.re_status = RPC_CANTRECV;
+ len = -1; /* it's really an error */
+ break;
+
+ case -1:
+ ct->ct_error.re_errno = errno;
+ ct->ct_error.re_status = RPC_CANTRECV;
+ break;
+ }
+ return (len);
+}
+
+static int
+writeunix(ct, buf, len)
+ struct ct_data *ct;
+ caddr_t buf;
+ int len;
+{
+ register int i, cnt;
+
+ for (cnt = len; cnt > 0; cnt -= i, buf += i) {
+ if ((i = __msgwrite(ct->ct_sock, buf, cnt)) == -1) {
+ ct->ct_error.re_errno = errno;
+ ct->ct_error.re_status = RPC_CANTSEND;
+ return (-1);
+ }
+ }
+ return (len);
+}
diff --git a/cpukit/librpc/src/rpc/crypt_client.c b/cpukit/librpc/src/rpc/crypt_client.c
new file mode 100644
index 0000000000..cb69470614
--- /dev/null
+++ b/cpukit/librpc/src/rpc/crypt_client.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 1996
+ * Bill Paul <wpaul@ctr.columbia.edu>. 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 Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul 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.
+ *
+ * $FreeBSD: src/lib/libc/rpc/crypt_client.c,v 1.4 1999/08/28 00:00:37 peter Exp $
+ */
+
+#include <sys/types.h>
+#include <rpc/des_crypt.h>
+#include <rpc/des.h>
+#include <string.h>
+#include <rpcsvc/crypt.h>
+
+#ifndef lint
+static const char rcsid[] = "$FreeBSD: src/lib/libc/rpc/crypt_client.c,v 1.4 1999/08/28 00:00:37 peter Exp $";
+#endif
+
+#ifndef KEYSERVSOCK
+#define KEYSERVSOCK "/var/run/keyservsock"
+#endif
+
+int
+_des_crypt_call(buf, len, dparms)
+ char *buf;
+ int len;
+ struct desparams *dparms;
+{
+ CLIENT *clnt;
+ desresp *result_1;
+ desargs des_crypt_1_arg;
+ int stat;
+
+ clnt = clnt_create(KEYSERVSOCK, CRYPT_PROG, CRYPT_VERS, "unix");
+ if (clnt == (CLIENT *) NULL) {
+ return(DESERR_HWERROR);
+ }
+
+ des_crypt_1_arg.desbuf.desbuf_len = len;
+ des_crypt_1_arg.desbuf.desbuf_val = buf;
+ des_crypt_1_arg.des_dir = dparms->des_dir;
+ des_crypt_1_arg.des_mode = dparms->des_mode;
+ bcopy(dparms->des_ivec, des_crypt_1_arg.des_ivec, 8);
+ bcopy(dparms->des_key, des_crypt_1_arg.des_key, 8);
+
+ result_1 = des_crypt_1(&des_crypt_1_arg, clnt);
+ if (result_1 == (desresp *) NULL) {
+ clnt_destroy(clnt);
+ return(DESERR_HWERROR);
+ }
+
+ stat = result_1->stat;
+
+ if (result_1->stat == DESERR_NONE ||
+ result_1->stat == DESERR_NOHWDEVICE) {
+ bcopy(result_1->desbuf.desbuf_val, buf, len);
+ bcopy(result_1->des_ivec, dparms->des_ivec, 8);
+ }
+
+ clnt_freeres(clnt, xdr_desresp, (char *)result_1);
+ clnt_destroy(clnt);
+
+ return(stat);
+}
diff --git a/cpukit/librpc/src/rpc/des_crypt.3 b/cpukit/librpc/src/rpc/des_crypt.3
new file mode 100644
index 0000000000..a92f577a56
--- /dev/null
+++ b/cpukit/librpc/src/rpc/des_crypt.3
@@ -0,0 +1,130 @@
+.\" @(#)des_crypt.3 2.1 88/08/11 4.0 RPCSRC; from 1.16 88/03/02 SMI;
+.\" $FreeBSD: src/lib/libc/rpc/des_crypt.3,v 1.4 2000/03/02 09:13:45 sheldonh Exp $
+.\"
+.TH DES_CRYPT 3 "6 October 1987"
+.SH NAME
+des_crypt, ecb_crypt, cbc_crypt, des_setparity \- fast DES encryption
+.SH SYNOPSIS
+.nf
+.B #include <des_crypt.h>
+.LP
+.B int ecb_crypt(key, data, datalen, mode)
+.B char *key;
+.B char *data;
+.B unsigned datalen;
+.B unsigned mode;
+.LP
+.B int cbc_crypt(key, data, datalen, mode, ivec)
+.B char *key;
+.B char *data;
+.B unsigned datalen;
+.B unsigned mode;
+.B char *ivec;
+.LP
+.B void des_setparity(key)
+.B char *key;
+.fi
+.SH DESCRIPTION
+.IX encryption cbc_crypt "" \fLcbc_crypt\fP
+.IX "des encryption" cbc_crypt "DES encryption" \fLcbc_crypt\fP
+.IX encryption des_setparity "" \fLdes_setparity\fP
+.IX "des encryption" des_setparity "DES encryption" \fLdes_setparity\fP
+.B ecb_crypt(\|)
+and
+.B cbc_crypt(\|)
+implement the
+.SM NBS
+.SM DES
+(Data Encryption Standard).
+These routines are faster and more general purpose than
+.BR crypt (3).
+They also are able to utilize
+.SM DES
+hardware if it is available.
+.B ecb_crypt(\|)
+encrypts in
+.SM ECB
+(Electronic Code Book)
+mode, which encrypts blocks of data independently.
+.B cbc_crypt(\|)
+encrypts in
+.SM CBC
+(Cipher Block Chaining)
+mode, which chains together
+successive blocks.
+.SM CBC
+mode protects against insertions, deletions and
+substitutions of blocks.
+Also, regularities in the clear text will
+not appear in the cipher text.
+.LP
+Here is how to use these routines. The first parameter,
+.IR key ,
+is the 8-byte encryption key with parity.
+To set the key's parity, which for
+.SM DES
+is in the low bit of each byte, use
+.IR des_setparity .
+The second parameter,
+.IR data ,
+contains the data to be encrypted or decrypted.
+The
+third parameter,
+.IR datalen ,
+is the length in bytes of
+.IR data ,
+which must be a multiple of 8. The fourth parameter,
+.IR mode ,
+is formed by
+.SM OR\s0'ing
+together some things. For the encryption direction 'or' in either
+.SM DES_ENCRYPT
+or
+.SM DES_DECRYPT\s0.
+For software versus hardware
+encryption, 'or' in either
+.SM DES_HW
+or
+.SM DES_SW\s0.
+If
+.SM DES_HW
+is specified, and there is no hardware, then the encryption is performed
+in software and the routine returns
+.SM DESERR_NOHWDEVICE\s0.
+For
+.IR cbc_crypt ,
+the parameter
+.I ivec
+is the the 8-byte initialization
+vector for the chaining. It is updated to the next initialization
+vector upon return.
+.LP
+.SH "SEE ALSO"
+.BR des (1),
+.BR crypt (3)
+.SH DIAGNOSTICS
+.PD 0
+.TP 20
+.SM DESERR_NONE
+No error.
+.TP
+.SM DESERR_NOHWDEVICE
+Encryption succeeded, but done in software instead of the requested hardware.
+.TP
+.SM DESERR_HWERR
+An error occurred in the hardware or driver.
+.TP
+.SM DESERR_BADPARAM
+Bad parameter to routine.
+.PD
+.LP
+Given a result status
+.IR stat ,
+the macro
+.SM DES_FAILED\c
+.BR ( stat )
+is false only for the first two statuses.
+.SH RESTRICTIONS
+These routines are not available in RPCSRC 4.0.
+This information is provided to describe the DES interface expected by
+Secure RPC.
diff --git a/cpukit/librpc/src/rpc/des_crypt.c b/cpukit/librpc/src/rpc/des_crypt.c
new file mode 100644
index 0000000000..d74ce9403a
--- /dev/null
+++ b/cpukit/librpc/src/rpc/des_crypt.c
@@ -0,0 +1,153 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * des_crypt.c, DES encryption library routines
+ * Copyright (C) 1986, Sun Microsystems, Inc.
+ */
+
+#include <sys/types.h>
+#include <rpc/des_crypt.h>
+#include <rpc/des.h>
+
+#ifndef lint
+/* from: static char sccsid[] = "@(#)des_crypt.c 2.2 88/08/10 4.0 RPCSRC; from 1.13 88/02/08 SMI"; */
+static const char rcsid[] = "$FreeBSD: src/lib/libc/rpc/des_crypt.c,v 1.3 1999/08/28 00:00:38 peter Exp $";
+#endif
+
+static int common_crypt __P(( char *, char *, register unsigned, unsigned, struct desparams * ));
+int (*__des_crypt_LOCAL)() = 0;
+extern _des_crypt_call __P(( char *, int, struct desparams * ));
+/*
+ * Copy 8 bytes
+ */
+#define COPY8(src, dst) { \
+ register char *a = (char *) dst; \
+ register char *b = (char *) src; \
+ *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \
+ *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \
+}
+
+/*
+ * Copy multiple of 8 bytes
+ */
+#define DESCOPY(src, dst, len) { \
+ register char *a = (char *) dst; \
+ register char *b = (char *) src; \
+ register int i; \
+ for (i = (int) len; i > 0; i -= 8) { \
+ *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \
+ *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \
+ } \
+}
+
+/*
+ * CBC mode encryption
+ */
+int
+cbc_crypt(key, buf, len, mode, ivec)
+ char *key;
+ char *buf;
+ unsigned len;
+ unsigned mode;
+ char *ivec;
+{
+ int err;
+ struct desparams dp;
+
+#ifdef BROKEN_DES
+ dp.UDES.UDES_buf = buf;
+ dp.des_mode = ECB;
+#else
+ dp.des_mode = CBC;
+#endif
+ COPY8(ivec, dp.des_ivec);
+ err = common_crypt(key, buf, len, mode, &dp);
+ COPY8(dp.des_ivec, ivec);
+ return(err);
+}
+
+
+/*
+ * ECB mode encryption
+ */
+int
+ecb_crypt(key, buf, len, mode)
+ char *key;
+ char *buf;
+ unsigned len;
+ unsigned mode;
+{
+ struct desparams dp;
+
+#ifdef BROKEN_DES
+ dp.UDES.UDES_buf = buf;
+ dp.des_mode = CBC;
+#else
+ dp.des_mode = ECB;
+#endif
+ return(common_crypt(key, buf, len, mode, &dp));
+}
+
+
+
+/*
+ * Common code to cbc_crypt() & ecb_crypt()
+ */
+static int
+common_crypt(key, buf, len, mode, desp)
+ char *key;
+ char *buf;
+ register unsigned len;
+ unsigned mode;
+ register struct desparams *desp;
+{
+ register int desdev;
+
+ if ((len % 8) != 0 || len > DES_MAXDATA) {
+ return(DESERR_BADPARAM);
+ }
+ desp->des_dir =
+ ((mode & DES_DIRMASK) == DES_ENCRYPT) ? ENCRYPT : DECRYPT;
+
+ desdev = mode & DES_DEVMASK;
+ COPY8(key, desp->des_key);
+ /*
+ * software
+ */
+ if (__des_crypt_LOCAL != NULL) {
+ if (!__des_crypt_LOCAL(buf, len, desp)) {
+ return (DESERR_HWERROR);
+ }
+ } else {
+ if (!_des_crypt_call(buf, len, desp)) {
+ return (DESERR_HWERROR);
+ }
+ }
+ return(desdev == DES_SW ? DESERR_NONE : DESERR_NOHWDEVICE);
+}
diff --git a/cpukit/librpc/src/rpc/des_soft.c b/cpukit/librpc/src/rpc/des_soft.c
new file mode 100644
index 0000000000..01dd7f280b
--- /dev/null
+++ b/cpukit/librpc/src/rpc/des_soft.c
@@ -0,0 +1,67 @@
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)des_soft.c 2.2 88/08/10 4.0 RPCSRC; from 1.13 88/02/08 SMI";
+#endif
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Table giving odd parity in the low bit for ASCII characters
+ */
+static char partab[128] = {
+ 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x07, 0x07,
+ 0x08, 0x08, 0x0b, 0x0b, 0x0d, 0x0d, 0x0e, 0x0e,
+ 0x10, 0x10, 0x13, 0x13, 0x15, 0x15, 0x16, 0x16,
+ 0x19, 0x19, 0x1a, 0x1a, 0x1c, 0x1c, 0x1f, 0x1f,
+ 0x20, 0x20, 0x23, 0x23, 0x25, 0x25, 0x26, 0x26,
+ 0x29, 0x29, 0x2a, 0x2a, 0x2c, 0x2c, 0x2f, 0x2f,
+ 0x31, 0x31, 0x32, 0x32, 0x34, 0x34, 0x37, 0x37,
+ 0x38, 0x38, 0x3b, 0x3b, 0x3d, 0x3d, 0x3e, 0x3e,
+ 0x40, 0x40, 0x43, 0x43, 0x45, 0x45, 0x46, 0x46,
+ 0x49, 0x49, 0x4a, 0x4a, 0x4c, 0x4c, 0x4f, 0x4f,
+ 0x51, 0x51, 0x52, 0x52, 0x54, 0x54, 0x57, 0x57,
+ 0x58, 0x58, 0x5b, 0x5b, 0x5d, 0x5d, 0x5e, 0x5e,
+ 0x61, 0x61, 0x62, 0x62, 0x64, 0x64, 0x67, 0x67,
+ 0x68, 0x68, 0x6b, 0x6b, 0x6d, 0x6d, 0x6e, 0x6e,
+ 0x70, 0x70, 0x73, 0x73, 0x75, 0x75, 0x76, 0x76,
+ 0x79, 0x79, 0x7a, 0x7a, 0x7c, 0x7c, 0x7f, 0x7f,
+};
+
+/*
+ * Add odd parity to low bit of 8 byte key
+ */
+void
+des_setparity(p)
+ char *p;
+{
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ *p = partab[*p & 0x7f];
+ p++;
+ }
+}
diff --git a/cpukit/librpc/src/rpc/get_myaddress.c b/cpukit/librpc/src/rpc/get_myaddress.c
new file mode 100644
index 0000000000..8e951f559e
--- /dev/null
+++ b/cpukit/librpc/src/rpc/get_myaddress.c
@@ -0,0 +1,112 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)get_myaddress.c 1.4 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)get_myaddress.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/rpc/get_myaddress.c,v 1.17 2000/01/27 23:06:37 jasone Exp $";
+#endif
+
+/*
+ * get_myaddress.c
+ *
+ * Get client's IP address via ioctl. This avoids using the yellowpages.
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/pmap_prot.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+/*
+ * don't use gethostbyname, which would invoke yellow pages
+ *
+ * Avoid loopback interfaces. We return information from a loopback
+ * interface only if there are no other possible interfaces.
+ */
+int
+get_myaddress(addr)
+ struct sockaddr_in *addr;
+{
+ int s;
+ char buf[BUFSIZ];
+ struct ifconf ifc;
+ struct ifreq ifreq, *ifr, *end;
+ int loopback = 0, gotit = 0;
+
+ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ return(-1);
+ }
+ ifc.ifc_len = sizeof (buf);
+ ifc.ifc_buf = buf;
+ if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
+ _RPC_close(s);
+ return(-1);
+ }
+again:
+ ifr = ifc.ifc_req;
+ end = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
+
+ while (ifr < end) {
+ ifreq = *ifr;
+ if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
+ _RPC_close(s);
+ return(-1);
+ }
+ if (((ifreq.ifr_flags & IFF_UP) &&
+ ifr->ifr_addr.sa_family == AF_INET &&
+ !(ifreq.ifr_flags & IFF_LOOPBACK)) ||
+ (loopback == 1 && (ifreq.ifr_flags & IFF_LOOPBACK)
+ && (ifr->ifr_addr.sa_family == AF_INET)
+ && (ifreq.ifr_flags & IFF_UP))) {
+ *addr = *((struct sockaddr_in *)&ifr->ifr_addr);
+ addr->sin_port = htons(PMAPPORT);
+ gotit = 1;
+ break;
+ }
+ if (ifr->ifr_addr.sa_len)
+ ifr = (struct ifreq *) ((caddr_t) ifr +
+ ifr->ifr_addr.sa_len -
+ sizeof(struct sockaddr));
+ ifr++;
+ }
+ if (gotit == 0 && loopback == 0) {
+ loopback = 1;
+ goto again;
+ }
+ (void)_RPC_close(s);
+ return (gotit ? 0 : -1);
+}
diff --git a/cpukit/librpc/src/rpc/getpublickey.c b/cpukit/librpc/src/rpc/getpublickey.c
new file mode 100644
index 0000000000..e1c34d9b25
--- /dev/null
+++ b/cpukit/librpc/src/rpc/getpublickey.c
@@ -0,0 +1,172 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)publickey.c 1.10 91/03/11 Copyr 1986 Sun Micro";
+#endif
+
+/*
+ * publickey.c
+ * Copyright (C) 1986, Sun Microsystems, Inc.
+ */
+
+/*
+ * Public key lookup routines
+ */
+#include <stdio.h>
+#include <pwd.h>
+#include <rpc/rpc.h>
+#include <rpc/key_prot.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define PKFILE "/etc/publickey"
+
+/*
+ * Hack to let ypserv/rpc.nisd use AUTH_DES.
+ */
+int (*__getpublickey_LOCAL)() = 0;
+
+/*
+ * Get somebody's public key
+ */
+int
+__getpublickey_real(netname, publickey)
+ char *netname;
+ char *publickey;
+{
+ char lookup[3 * HEXKEYBYTES];
+ char *p;
+
+ if (publickey == NULL)
+ return (0);
+ if (!getpublicandprivatekey(netname, lookup))
+ return (0);
+ p = strchr(lookup, ':');
+ if (p == NULL) {
+ return (0);
+ }
+ *p = '\0';
+ (void) strncpy(publickey, lookup, HEXKEYBYTES);
+ publickey[HEXKEYBYTES] = '\0';
+ return (1);
+}
+
+/*
+ * reads the file /etc/publickey looking for a + to optionally go to the
+ * yellow pages
+ */
+
+int
+getpublicandprivatekey(key, ret)
+ char *key;
+ char *ret;
+{
+ char buf[1024]; /* big enough */
+ char *res;
+ FILE *fd;
+ char *mkey;
+ char *mval;
+
+ fd = fopen(PKFILE, "r");
+ if (fd == (FILE *) 0)
+ return (0);
+ for (;;) {
+ res = fgets(buf, 1024, fd);
+ if (res == 0) {
+ fclose(fd);
+ return (0);
+ }
+ if (res[0] == '#')
+ continue;
+ else if (res[0] == '+') {
+#ifdef YP
+ char *PKMAP = "publickey.byname";
+ char *lookup;
+ char *domain;
+ int err;
+ int len;
+
+ err = yp_get_default_domain(&domain);
+ if (err) {
+ continue;
+ }
+ lookup = NULL;
+ err = yp_match(domain, PKMAP, key, strlen(key), &lookup, &len);
+ if (err) {
+#ifdef DEBUG
+ fprintf(stderr, "match failed error %d\n", err);
+#endif
+ continue;
+ }
+ lookup[len] = 0;
+ strcpy(ret, lookup);
+ fclose(fd);
+ free(lookup);
+ return (2);
+#else /* YP */
+#ifdef DEBUG
+ fprintf(stderr,
+"Bad record in %s '+' -- NIS not supported in this library copy\n", PKFILE);
+#endif /* DEBUG */
+ continue;
+#endif /* YP */
+ } else {
+ mkey = strtok(buf, "\t ");
+ if (mkey == NULL) {
+ fprintf(stderr,
+ "Bad record in %s -- %s", PKFILE, buf);
+ continue;
+ }
+ mval = strtok((char *)NULL, " \t#\n");
+ if (mval == NULL) {
+ fprintf(stderr,
+ "Bad record in %s val problem - %s", PKFILE, buf);
+ continue;
+ }
+ if (strcmp(mkey, key) == 0) {
+ strcpy(ret, mval);
+ fclose(fd);
+ return (1);
+ }
+ }
+ }
+}
+
+int getpublickey(netname, publickey)
+ char *netname;
+ char *publickey;
+{
+ if (__getpublickey_LOCAL != NULL)
+ return(__getpublickey_LOCAL(netname, publickey));
+ else
+ return(__getpublickey_real(netname, publickey));
+}
diff --git a/cpukit/librpc/src/rpc/getrpcent.3 b/cpukit/librpc/src/rpc/getrpcent.3
new file mode 100644
index 0000000000..1e92e9d03d
--- /dev/null
+++ b/cpukit/librpc/src/rpc/getrpcent.3
@@ -0,0 +1,98 @@
+.\" @(#)getrpcent.3n 2.2 88/08/02 4.0 RPCSRC; from 1.11 88/03/14 SMI
+.\" $FreeBSD: src/lib/libc/rpc/getrpcent.3,v 1.11 1999/08/28 00:00:39 peter Exp $
+.\"
+.Dd December 14, 1987
+.Dt GETRPCENT 3
+.Os
+.Sh NAME
+.Nm getrpcent ,
+.Nm getrpcbyname ,
+.Nm getrpcbynumber ,
+.Nm endrpcent ,
+.Nm setrpcent
+.Nd get RPC entry
+.Sh SYNOPSIS
+.Fd #include <rpc/rpc.h>
+.Ft struct rpcent *
+.Fn getrpcent void
+.Ft struct rpcent *
+.Fn getrpcbyname "char *name"
+.Ft struct rpcent *
+.Fn getrpcbynumber "int number"
+.Ft void
+.Fn setrpcent "int stayopen"
+.Ft void
+.Fn endrpcent void
+.Sh DESCRIPTION
+The
+.Fn getrpcent ,
+.Fn getrpcbyname ,
+and
+.Fn getrpcbynumber
+functions each return a pointer to an object with the
+following structure
+containing the broken-out
+fields of a line in the rpc program number data base,
+.Pa /etc/rpc .
+.Bd -literal
+
+struct rpcent {
+ char *r_name; /* name of server for this rpc program */
+ char **r_aliases; /* alias list */
+ long r_number; /* rpc program number */
+};
+.Ed
+.Pp
+The members of this structure are:
+.Bl -tag -width r_aliasesxxx
+.It Fa r_name
+The name of the server for this rpc program.
+.It Fa r_aliases
+A zero terminated list of alternate names for the rpc program.
+.It Fa r_number
+The rpc program number for this service.
+.El
+.Pp
+The
+.Fn getrpcent
+function reads the next line of the file, opening the file if necessary.
+The
+.Nm getrpcent
+function opens and rewinds the file. If the
+.Fa stayopen
+flag is non-zero,
+the net data base will not be closed after each call to
+.Fn getrpcent
+(either directly, or indirectly through one of
+the other
+.Fn getrpcent
+function family.
+.Pp
+.Fn endrpcent
+closes the file.
+.Pp
+.Fn getrpcbyname
+and
+.Fn getrpcbynumber
+sequentially search from the beginning
+of the file until a matching rpc program name or
+program number is found, or until end-of-file is encountered.
+.Sh FILES
+.Bl -tag -width /etc/rpc -compact
+.It Pa /etc/rpc
+.El
+.Sh "SEE ALSO"
+.Xr rpc 5 ,
+.Xr rpcinfo 8 ,
+.Xr ypserv 8
+.Sh DIAGNOSTICS
+A
+.Dv NULL
+pointer is returned on
+.Dv EOF
+or error.
+.Sh BUGS
+All information
+is contained in a static area
+so it must be copied if it is
+to be saved.
diff --git a/cpukit/librpc/src/rpc/getrpcent.c b/cpukit/librpc/src/rpc/getrpcent.c
new file mode 100644
index 0000000000..e2d2e164d5
--- /dev/null
+++ b/cpukit/librpc/src/rpc/getrpcent.c
@@ -0,0 +1,302 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)getrpcent.c 1.14 91/03/11 Copyr 1984 Sun Micro";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/rpc/getrpcent.c,v 1.10 1999/08/28 00:00:39 peter Exp $";
+#endif
+
+/*
+ * Copyright (c) 1984 by Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#ifdef YP
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+
+/*
+ * Internet version.
+ */
+struct rpcdata {
+ FILE *rpcf;
+ int stayopen;
+#define MAXALIASES 35
+ char *rpc_aliases[MAXALIASES];
+ struct rpcent rpc;
+ char line[BUFSIZ+1];
+#ifdef YP
+ char *domain;
+ char *current;
+ int currentlen;
+#endif
+} *rpcdata;
+
+#ifdef YP
+static int __yp_nomap = 0;
+extern int _yp_check(char **);
+#endif /* YP */
+
+static struct rpcent *interpret();
+struct hostent *gethostent();
+char *inet_ntoa();
+
+static char RPCDB[] = "/etc/rpc";
+
+static struct rpcdata *
+_rpcdata()
+{
+ register struct rpcdata *d = rpcdata;
+
+ if (d == 0) {
+ d = (struct rpcdata *)calloc(1, sizeof (struct rpcdata));
+ rpcdata = d;
+ }
+ return (d);
+}
+
+struct rpcent *
+getrpcbynumber(number)
+ register int number;
+{
+ register struct rpcdata *d = _rpcdata();
+ register struct rpcent *p;
+#ifdef YP
+ int reason;
+ char adrstr[16];
+#endif
+
+ if (d == 0)
+ return (0);
+#ifdef YP
+ if (!__yp_nomap && _yp_check(&d->domain)) {
+ sprintf(adrstr, "%d", number);
+ reason = yp_match(d->domain, "rpc.bynumber", adrstr, strlen(adrstr),
+ &d->current, &d->currentlen);
+ switch(reason) {
+ case 0:
+ break;
+ case YPERR_MAP:
+ __yp_nomap = 1;
+ goto no_yp;
+ break;
+ default:
+ return(0);
+ break;
+ }
+ d->current[d->currentlen] = '\0';
+ p = interpret(d->current, d->currentlen);
+ (void) free(d->current);
+ return p;
+ }
+no_yp:
+#endif /* YP */
+ setrpcent(0);
+ while ((p = getrpcent())) {
+ if (p->r_number == number)
+ break;
+ }
+ endrpcent();
+ return (p);
+}
+
+struct rpcent *
+getrpcbyname(name)
+ char *name;
+{
+ struct rpcent *rpc = NULL;
+ char **rp;
+
+ setrpcent(0);
+ while ((rpc = getrpcent())) {
+ if (strcmp(rpc->r_name, name) == 0)
+ goto done;
+ for (rp = rpc->r_aliases; *rp != NULL; rp++) {
+ if (strcmp(*rp, name) == 0)
+ goto done;
+ }
+ }
+done:
+ endrpcent();
+ return (rpc);
+}
+
+void
+setrpcent(f)
+ int f;
+{
+ register struct rpcdata *d = _rpcdata();
+
+ if (d == 0)
+ return;
+#ifdef YP
+ if (!__yp_nomap && _yp_check(NULL)) {
+ if (d->current)
+ free(d->current);
+ d->current = NULL;
+ d->currentlen = 0;
+ return;
+ }
+ __yp_nomap = 0;
+#endif /* YP */
+ if (d->rpcf == NULL)
+ d->rpcf = fopen(RPCDB, "r");
+ else
+ rewind(d->rpcf);
+ d->stayopen |= f;
+}
+
+void
+endrpcent()
+{
+ register struct rpcdata *d = _rpcdata();
+
+ if (d == 0)
+ return;
+#ifdef YP
+ if (!__yp_nomap && _yp_check(NULL)) {
+ if (d->current && !d->stayopen)
+ free(d->current);
+ d->current = NULL;
+ d->currentlen = 0;
+ return;
+ }
+ __yp_nomap = 0;
+#endif /* YP */
+ if (d->rpcf && !d->stayopen) {
+ fclose(d->rpcf);
+ d->rpcf = NULL;
+ }
+}
+
+struct rpcent *
+getrpcent()
+{
+ register struct rpcdata *d = _rpcdata();
+#ifdef YP
+ struct rpcent *hp;
+ int reason;
+ char *val = NULL;
+ int vallen;
+#endif
+
+ if (d == 0)
+ return(NULL);
+#ifdef YP
+ if (!__yp_nomap && _yp_check(&d->domain)) {
+ if (d->current == NULL && d->currentlen == 0) {
+ reason = yp_first(d->domain, "rpc.bynumber",
+ &d->current, &d->currentlen,
+ &val, &vallen);
+ } else {
+ reason = yp_next(d->domain, "rpc.bynumber",
+ d->current, d->currentlen,
+ &d->current, &d->currentlen,
+ &val, &vallen);
+ }
+ switch(reason) {
+ case 0:
+ break;
+ case YPERR_MAP:
+ __yp_nomap = 1;
+ goto no_yp;
+ break;
+ default:
+ return(0);
+ break;
+ }
+ val[vallen] = '\0';
+ hp = interpret(val, vallen);
+ (void) free(val);
+ return hp;
+ }
+no_yp:
+#endif /* YP */
+ if (d->rpcf == NULL && (d->rpcf = fopen(RPCDB, "r")) == NULL)
+ return (NULL);
+ /* -1 so there is room to append a \n below */
+ if (fgets(d->line, BUFSIZ - 1, d->rpcf) == NULL)
+ return (NULL);
+ return (interpret(d->line, strlen(d->line)));
+}
+
+static struct rpcent *
+interpret(val, len)
+ char *val;
+ int len;
+{
+ register struct rpcdata *d = _rpcdata();
+ char *p;
+ register char *cp, **q;
+
+ if (d == 0)
+ return (0);
+ (void) strncpy(d->line, val, BUFSIZ);
+ d->line[BUFSIZ] = '\0';
+ p = d->line;
+ p[len] = '\n';
+ if (*p == '#')
+ return (getrpcent());
+ cp = strpbrk(p, "#\n");
+ if (cp == NULL)
+ return (getrpcent());
+ *cp = '\0';
+ cp = strpbrk(p, " \t");
+ if (cp == NULL)
+ return (getrpcent());
+ *cp++ = '\0';
+ /* THIS STUFF IS INTERNET SPECIFIC */
+ d->rpc.r_name = d->line;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ d->rpc.r_number = atoi(cp);
+ q = d->rpc.r_aliases = d->rpc_aliases;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q < &(d->rpc_aliases[MAXALIASES - 1]))
+ *q++ = cp;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ }
+ *q = NULL;
+ return (&d->rpc);
+}
diff --git a/cpukit/librpc/src/rpc/getrpcport.3 b/cpukit/librpc/src/rpc/getrpcport.3
new file mode 100644
index 0000000000..0e9175ec12
--- /dev/null
+++ b/cpukit/librpc/src/rpc/getrpcport.3
@@ -0,0 +1,31 @@
+.\" @(#)getrpcport.3r 2.2 88/08/02 4.0 RPCSRC; from 1.12 88/02/26 SMI
+.\" $FreeBSD: src/lib/libc/rpc/getrpcport.3,v 1.6 1999/08/28 00:00:40 peter Exp $
+.\"
+.Dd October 6, 1987
+.Dt GETRPCPORT 3
+.Os
+.Sh NAME
+.Nm getrpcport
+.Nd get RPC port number
+.Sh SYNOPSIS
+.Ft int
+.Fn getrpcport "char *host" "int prognum" "int versnum" "int proto"
+.Sh DESCRIPTION
+.Fn getrpcport
+returns the port number for version
+.Fa versnum
+of the RPC program
+.Fa prognum
+running on
+.Fa host
+and using protocol
+.Fa proto .
+It returns 0 if it cannot contact the portmapper, or if
+.Fa prognum
+is not registered. If
+.Fa prognum
+is registered but not with version
+.Fa versnum ,
+it will still return a port number (for some version of the program)
+indicating that the program is indeed registered.
+The version mismatch will be detected upon the first call to the service.
diff --git a/cpukit/librpc/src/rpc/getrpcport.c b/cpukit/librpc/src/rpc/getrpcport.c
new file mode 100644
index 0000000000..8d17615c66
--- /dev/null
+++ b/cpukit/librpc/src/rpc/getrpcport.c
@@ -0,0 +1,63 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)getrpcport.c 1.3 87/08/11 SMI";*/
+/*static char *sccsid = "from: @(#)getrpcport.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/rpc/getrpcport.c,v 1.10 1999/08/28 00:00:40 peter Exp $";
+#endif
+
+/*
+ * Copyright (c) 1985 by Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+#include <netdb.h>
+#include <sys/socket.h>
+
+int
+getrpcport(host, prognum, versnum, proto)
+ char *host;
+ int prognum, versnum, proto;
+{
+ struct sockaddr_in addr;
+ struct hostent *hp;
+
+ if ((hp = gethostbyname(host)) == NULL)
+ return (0);
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_len = sizeof(struct sockaddr_in);
+ addr.sin_family = AF_INET;
+ addr.sin_port = 0;
+ memcpy((char *)&addr.sin_addr, hp->h_addr, hp->h_length);
+ return (pmap_getport(&addr, prognum, versnum, proto));
+}
diff --git a/cpukit/librpc/src/rpc/key_call.c b/cpukit/librpc/src/rpc/key_call.c
new file mode 100644
index 0000000000..98df0d1f95
--- /dev/null
+++ b/cpukit/librpc/src/rpc/key_call.c
@@ -0,0 +1,427 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc.
+ *
+ * $FreeBSD: src/lib/libc/rpc/key_call.c,v 1.3 2000/01/27 23:06:39 jasone Exp $
+ */
+
+#ident "@(#)key_call.c 1.25 94/04/24 SMI"
+
+/*
+ * key_call.c, Interface to keyserver
+ *
+ * setsecretkey(key) - set your secret key
+ * encryptsessionkey(agent, deskey) - encrypt a session key to talk to agent
+ * decryptsessionkey(agent, deskey) - decrypt ditto
+ * gendeskey(deskey) - generate a secure des key
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <rpc/rpc.h>
+#include <rpc/auth.h>
+#include <rpc/auth_unix.h>
+#include <rpc/key_prot.h>
+#include <string.h>
+#include <sys/utsname.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <sys/fcntl.h>
+
+
+#define KEY_TIMEOUT 5 /* per-try timeout in seconds */
+#define KEY_NRETRY 12 /* number of retries */
+
+#ifdef DEBUG
+#define debug(msg) (void) fprintf(stderr, "%s\n", msg);
+#else
+#define debug(msg)
+#endif /* DEBUG */
+
+/*
+ * Hack to allow the keyserver to use AUTH_DES (for authenticated
+ * NIS+ calls, for example). The only functions that get called
+ * are key_encryptsession_pk, key_decryptsession_pk, and key_gendes.
+ *
+ * The approach is to have the keyserver fill in pointers to local
+ * implementations of these functions, and to call those in key_call().
+ */
+
+cryptkeyres *(*__key_encryptsession_pk_LOCAL)() = 0;
+cryptkeyres *(*__key_decryptsession_pk_LOCAL)() = 0;
+des_block *(*__key_gendes_LOCAL)() = 0;
+
+static int key_call __P(( u_long, xdrproc_t, char *, xdrproc_t, char * ));
+
+int
+key_setsecret(secretkey)
+ const char *secretkey;
+{
+ keystatus status;
+
+ if (!key_call((u_long) KEY_SET, xdr_keybuf, (char *) secretkey,
+ xdr_keystatus, (char *)&status)) {
+ return (-1);
+ }
+ if (status != KEY_SUCCESS) {
+ debug("set status is nonzero");
+ return (-1);
+ }
+ return (0);
+}
+
+
+/* key_secretkey_is_set() returns 1 if the keyserver has a secret key
+ * stored for the caller's effective uid; it returns 0 otherwise
+ *
+ * N.B.: The KEY_NET_GET key call is undocumented. Applications shouldn't
+ * be using it, because it allows them to get the user's secret key.
+ */
+
+int
+key_secretkey_is_set(void)
+{
+ struct key_netstres kres;
+
+ memset((void*)&kres, 0, sizeof (kres));
+ if (key_call((u_long) KEY_NET_GET, xdr_void, (char *)NULL,
+ xdr_key_netstres, (char *) &kres) &&
+ (kres.status == KEY_SUCCESS) &&
+ (kres.key_netstres_u.knet.st_priv_key[0] != 0)) {
+ /* avoid leaving secret key in memory */
+ memset(kres.key_netstres_u.knet.st_priv_key, 0, HEXKEYBYTES);
+ return (1);
+ }
+ return (0);
+}
+
+int
+key_encryptsession_pk(remotename, remotekey, deskey)
+ char *remotename;
+ netobj *remotekey;
+ des_block *deskey;
+{
+ cryptkeyarg2 arg;
+ cryptkeyres res;
+
+ arg.remotename = remotename;
+ arg.remotekey = *remotekey;
+ arg.deskey = *deskey;
+ if (!key_call((u_long)KEY_ENCRYPT_PK, xdr_cryptkeyarg2, (char *)&arg,
+ xdr_cryptkeyres, (char *)&res)) {
+ return (-1);
+ }
+ if (res.status != KEY_SUCCESS) {
+ debug("encrypt status is nonzero");
+ return (-1);
+ }
+ *deskey = res.cryptkeyres_u.deskey;
+ return (0);
+}
+
+int
+key_decryptsession_pk(remotename, remotekey, deskey)
+ char *remotename;
+ netobj *remotekey;
+ des_block *deskey;
+{
+ cryptkeyarg2 arg;
+ cryptkeyres res;
+
+ arg.remotename = remotename;
+ arg.remotekey = *remotekey;
+ arg.deskey = *deskey;
+ if (!key_call((u_long)KEY_DECRYPT_PK, xdr_cryptkeyarg2, (char *)&arg,
+ xdr_cryptkeyres, (char *)&res)) {
+ return (-1);
+ }
+ if (res.status != KEY_SUCCESS) {
+ debug("decrypt status is nonzero");
+ return (-1);
+ }
+ *deskey = res.cryptkeyres_u.deskey;
+ return (0);
+}
+
+int
+key_encryptsession(remotename, deskey)
+ const char *remotename;
+ des_block *deskey;
+{
+ cryptkeyarg arg;
+ cryptkeyres res;
+
+ arg.remotename = (char *) remotename;
+ arg.deskey = *deskey;
+ if (!key_call((u_long)KEY_ENCRYPT, xdr_cryptkeyarg, (char *)&arg,
+ xdr_cryptkeyres, (char *)&res)) {
+ return (-1);
+ }
+ if (res.status != KEY_SUCCESS) {
+ debug("encrypt status is nonzero");
+ return (-1);
+ }
+ *deskey = res.cryptkeyres_u.deskey;
+ return (0);
+}
+
+int
+key_decryptsession(remotename, deskey)
+ const char *remotename;
+ des_block *deskey;
+{
+ cryptkeyarg arg;
+ cryptkeyres res;
+
+ arg.remotename = (char *) remotename;
+ arg.deskey = *deskey;
+ if (!key_call((u_long)KEY_DECRYPT, xdr_cryptkeyarg, (char *)&arg,
+ xdr_cryptkeyres, (char *)&res)) {
+ return (-1);
+ }
+ if (res.status != KEY_SUCCESS) {
+ debug("decrypt status is nonzero");
+ return (-1);
+ }
+ *deskey = res.cryptkeyres_u.deskey;
+ return (0);
+}
+
+int
+key_gendes(key)
+ des_block *key;
+{
+ if (!key_call((u_long)KEY_GEN, xdr_void, (char *)NULL,
+ xdr_des_block, (char *)key)) {
+ return (-1);
+ }
+ return (0);
+}
+
+int
+key_setnet(arg)
+struct netstarg *arg;
+{
+ keystatus status;
+
+
+ if (!key_call((u_long) KEY_NET_PUT, xdr_key_netstarg, (char *) arg,
+ xdr_keystatus, (char *) &status)){
+ return (-1);
+ }
+
+ if (status != KEY_SUCCESS) {
+ debug("key_setnet status is nonzero");
+ return (-1);
+ }
+ return (1);
+}
+
+
+int
+key_get_conv(pkey, deskey)
+ char *pkey;
+ des_block *deskey;
+{
+ cryptkeyres res;
+
+ if (!key_call((u_long) KEY_GET_CONV, xdr_keybuf, pkey,
+ xdr_cryptkeyres, (char *)&res)) {
+ return (-1);
+ }
+ if (res.status != KEY_SUCCESS) {
+ debug("get_conv status is nonzero");
+ return (-1);
+ }
+ *deskey = res.cryptkeyres_u.deskey;
+ return (0);
+}
+
+struct key_call_private {
+ CLIENT *client; /* Client handle */
+ pid_t pid; /* process-id at moment of creation */
+ uid_t uid; /* user-id at last authorization */
+};
+static struct key_call_private *key_call_private_main = NULL;
+
+#ifdef foo
+static void
+key_call_destroy(void *vp)
+{
+ register struct key_call_private *kcp = (struct key_call_private *)vp;
+
+ if (kcp) {
+ if (kcp->client)
+ clnt_destroy(kcp->client);
+ free(kcp);
+ }
+}
+#endif
+
+/*
+ * Keep the handle cached. This call may be made quite often.
+ */
+static CLIENT *
+getkeyserv_handle(vers)
+int vers;
+{
+ struct key_call_private *kcp = key_call_private_main;
+ struct timeval wait_time;
+ int fd;
+ struct sockaddr_un name;
+ int namelen = sizeof(struct sockaddr_un);
+
+#define TOTAL_TIMEOUT 30 /* total timeout talking to keyserver */
+#define TOTAL_TRIES 5 /* Number of tries */
+
+ if (kcp == (struct key_call_private *)NULL) {
+ kcp = (struct key_call_private *)malloc(sizeof (*kcp));
+ if (kcp == (struct key_call_private *)NULL) {
+ return ((CLIENT *) NULL);
+ }
+ key_call_private_main = kcp;
+ kcp->client = NULL;
+ }
+
+ /* if pid has changed, destroy client and rebuild */
+ if (kcp->client != NULL && kcp->pid != getpid()) {
+ clnt_destroy(kcp->client);
+ kcp->client = NULL;
+ }
+
+ if (kcp->client != NULL) {
+ /* if other side closed socket, build handle again */
+ clnt_control(kcp->client, CLGET_FD, (char *)&fd);
+ if (getpeername(fd,(struct sockaddr *)&name,&namelen) == -1) {
+ auth_destroy(kcp->client->cl_auth);
+ clnt_destroy(kcp->client);
+ kcp->client = NULL;
+ }
+ }
+
+ if (kcp->client != NULL) {
+ /* if uid has changed, build client handle again */
+ if (kcp->uid != geteuid()) {
+ kcp->uid = geteuid();
+ auth_destroy(kcp->client->cl_auth);
+ kcp->client->cl_auth =
+ authsys_create("", kcp->uid, 0, 0, NULL);
+ if (kcp->client->cl_auth == NULL) {
+ clnt_destroy(kcp->client);
+ kcp->client = NULL;
+ return ((CLIENT *) NULL);
+ }
+ }
+ /* Change the version number to the new one */
+ clnt_control(kcp->client, CLSET_VERS, (void *)&vers);
+ return (kcp->client);
+ }
+
+ if ((kcp->client == (CLIENT *) NULL))
+ /* Use the AF_UNIX transport */
+ kcp->client = clnt_create("/var/run/keyservsock", KEY_PROG,
+ vers, "unix");
+
+ if (kcp->client == (CLIENT *) NULL) {
+ return ((CLIENT *) NULL);
+ }
+ kcp->uid = geteuid();
+ kcp->pid = getpid();
+ kcp->client->cl_auth = authsys_create("", kcp->uid, 0, 0, NULL);
+ if (kcp->client->cl_auth == NULL) {
+ clnt_destroy(kcp->client);
+ kcp->client = NULL;
+ return ((CLIENT *) NULL);
+ }
+
+ wait_time.tv_sec = TOTAL_TIMEOUT/TOTAL_TRIES;
+ wait_time.tv_usec = 0;
+ (void) clnt_control(kcp->client, CLSET_RETRY_TIMEOUT,
+ (char *)&wait_time);
+ if (clnt_control(kcp->client, CLGET_FD, (char *)&fd))
+ _fcntl(fd, F_SETFD, 1); /* make it "close on exec" */
+
+ return (kcp->client);
+}
+
+/* returns 0 on failure, 1 on success */
+
+static int
+key_call(proc, xdr_arg, arg, xdr_rslt, rslt)
+ u_long proc;
+ xdrproc_t xdr_arg;
+ char *arg;
+ xdrproc_t xdr_rslt;
+ char *rslt;
+{
+ CLIENT *clnt;
+ struct timeval wait_time;
+
+ if (proc == KEY_ENCRYPT_PK && __key_encryptsession_pk_LOCAL) {
+ cryptkeyres *res;
+ res = (*__key_encryptsession_pk_LOCAL)(geteuid(), arg);
+ *(cryptkeyres*)rslt = *res;
+ return (1);
+ } else if (proc == KEY_DECRYPT_PK && __key_decryptsession_pk_LOCAL) {
+ cryptkeyres *res;
+ res = (*__key_decryptsession_pk_LOCAL)(geteuid(), arg);
+ *(cryptkeyres*)rslt = *res;
+ return (1);
+ } else if (proc == KEY_GEN && __key_gendes_LOCAL) {
+ des_block *res;
+ res = (*__key_gendes_LOCAL)(geteuid(), 0);
+ *(des_block*)rslt = *res;
+ return (1);
+ }
+
+ if ((proc == KEY_ENCRYPT_PK) || (proc == KEY_DECRYPT_PK) ||
+ (proc == KEY_NET_GET) || (proc == KEY_NET_PUT) ||
+ (proc == KEY_GET_CONV))
+ clnt = getkeyserv_handle(2); /* talk to version 2 */
+ else
+ clnt = getkeyserv_handle(1); /* talk to version 1 */
+
+ if (clnt == NULL) {
+ return (0);
+ }
+
+ wait_time.tv_sec = TOTAL_TIMEOUT;
+ wait_time.tv_usec = 0;
+
+ if (clnt_call(clnt, proc, xdr_arg, arg, xdr_rslt, rslt,
+ wait_time) == RPC_SUCCESS) {
+ return (1);
+ } else {
+ return (0);
+ }
+}
diff --git a/cpukit/librpc/src/rpc/key_prot_xdr.c b/cpukit/librpc/src/rpc/key_prot_xdr.c
new file mode 100644
index 0000000000..8cd6b6b067
--- /dev/null
+++ b/cpukit/librpc/src/rpc/key_prot_xdr.c
@@ -0,0 +1,166 @@
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#include <rpc/key_prot.h>
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#pragma ident "@(#)key_prot.x 1.7 94/04/29 SMI"
+
+/* Copyright (c) 1990, 1991 Sun Microsystems, Inc. */
+
+/*
+ * Compiled from key_prot.x using rpcgen.
+ * DO NOT EDIT THIS FILE!
+ * This is NOT source code!
+ */
+
+bool_t
+xdr_keystatus(register XDR *xdrs, keystatus *objp)
+{
+
+ if (!xdr_enum(xdrs, (enum_t *)objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_keybuf(register XDR *xdrs, keybuf objp)
+{
+
+ if (!xdr_opaque(xdrs, objp, HEXKEYBYTES))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_netnamestr(register XDR *xdrs, netnamestr *objp)
+{
+
+ if (!xdr_string(xdrs, objp, MAXNETNAMELEN))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_cryptkeyarg(register XDR *xdrs, cryptkeyarg *objp)
+{
+
+ if (!xdr_netnamestr(xdrs, &objp->remotename))
+ return (FALSE);
+ if (!xdr_des_block(xdrs, &objp->deskey))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_cryptkeyarg2(register XDR *xdrs, cryptkeyarg2 *objp)
+{
+
+ if (!xdr_netnamestr(xdrs, &objp->remotename))
+ return (FALSE);
+ if (!xdr_netobj(xdrs, &objp->remotekey))
+ return (FALSE);
+ if (!xdr_des_block(xdrs, &objp->deskey))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_cryptkeyres(register XDR *xdrs, cryptkeyres *objp)
+{
+
+ if (!xdr_keystatus(xdrs, &objp->status))
+ return (FALSE);
+ switch (objp->status) {
+ case KEY_SUCCESS:
+ if (!xdr_des_block(xdrs, &objp->cryptkeyres_u.deskey))
+ return (FALSE);
+ break;
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_unixcred(register XDR *xdrs, unixcred *objp)
+{
+
+ if (!xdr_u_int(xdrs, &objp->uid))
+ return (FALSE);
+ if (!xdr_u_int(xdrs, &objp->gid))
+ return (FALSE);
+ if (!xdr_array(xdrs, (char **)&objp->gids.gids_val, (u_int *) &objp->gids.gids_len, MAXGIDS,
+ sizeof (u_int), (xdrproc_t) xdr_u_int))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_getcredres(register XDR *xdrs, getcredres *objp)
+{
+
+ if (!xdr_keystatus(xdrs, &objp->status))
+ return (FALSE);
+ switch (objp->status) {
+ case KEY_SUCCESS:
+ if (!xdr_unixcred(xdrs, &objp->getcredres_u.cred))
+ return (FALSE);
+ break;
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_key_netstarg(register XDR *xdrs, key_netstarg *objp)
+{
+
+ if (!xdr_keybuf(xdrs, objp->st_priv_key))
+ return (FALSE);
+ if (!xdr_keybuf(xdrs, objp->st_pub_key))
+ return (FALSE);
+ if (!xdr_netnamestr(xdrs, &objp->st_netname))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_key_netstres(register XDR *xdrs, key_netstres *objp)
+{
+
+ if (!xdr_keystatus(xdrs, &objp->status))
+ return (FALSE);
+ switch (objp->status) {
+ case KEY_SUCCESS:
+ if (!xdr_key_netstarg(xdrs, &objp->key_netstres_u.knet))
+ return (FALSE);
+ break;
+ }
+ return (TRUE);
+}
diff --git a/cpukit/librpc/src/rpc/netname.c b/cpukit/librpc/src/rpc/netname.c
new file mode 100644
index 0000000000..22167bee86
--- /dev/null
+++ b/cpukit/librpc/src/rpc/netname.c
@@ -0,0 +1,136 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)netname.c 1.8 91/03/11 Copyr 1986 Sun Micro";
+#endif
+
+/*
+ * netname utility routines
+ * convert from unix names to network names and vice-versa
+ * This module is operating system dependent!
+ * What we define here will work with any unix system that has adopted
+ * the sun NIS domain architecture.
+ */
+
+#include <sys/param.h>
+#include <rpc/rpc.h>
+#include <rpc/rpc_com.h>
+#ifdef YP
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 256
+#endif
+#ifndef NGROUPS
+#define NGROUPS 16
+#endif
+
+static char *OPSYS = "unix";
+
+/*
+ * Figure out my fully qualified network name
+ */
+int
+getnetname(name)
+ char name[MAXNETNAMELEN+1];
+{
+ uid_t uid;
+
+ uid = geteuid();
+ if (uid == 0) {
+ return (host2netname(name, (char *) NULL, (char *) NULL));
+ } else {
+ return (user2netname(name, uid, (char *) NULL));
+ }
+}
+
+
+/*
+ * Convert unix cred to network-name
+ */
+int
+user2netname(netname, uid, domain)
+ char netname[MAXNETNAMELEN + 1];
+ uid_t uid;
+ char *domain;
+{
+ char *dfltdom;
+
+#define MAXIPRINT (11) /* max length of printed integer */
+
+ if (domain == NULL) {
+ if (_rpc_get_default_domain(&dfltdom) != 0) {
+ return (0);
+ }
+ domain = dfltdom;
+ }
+ if (strlen(domain) + 1 + MAXIPRINT > MAXNETNAMELEN) {
+ return (0);
+ }
+ (void) sprintf(netname, "%s.%ld@%s", OPSYS, (u_long)uid, domain);
+ return (1);
+}
+
+
+/*
+ * Convert host to network-name
+ */
+int
+host2netname(netname, host, domain)
+ char netname[MAXNETNAMELEN + 1];
+ char *host;
+ char *domain;
+{
+ char *dfltdom;
+ char hostname[MAXHOSTNAMELEN+1];
+
+ if (domain == NULL) {
+ if (_rpc_get_default_domain(&dfltdom) != 0) {
+ return (0);
+ }
+ domain = dfltdom;
+ }
+ if (host == NULL) {
+ (void) gethostname(hostname, sizeof(hostname));
+ host = hostname;
+ }
+ if (strlen(domain) + 1 + strlen(host) > MAXNETNAMELEN) {
+ return (0);
+ }
+ (void) sprintf(netname, "%s.%s@%s", OPSYS, host, domain);
+ return (1);
+}
diff --git a/cpukit/librpc/src/rpc/netnamer.c b/cpukit/librpc/src/rpc/netnamer.c
new file mode 100644
index 0000000000..eac9913119
--- /dev/null
+++ b/cpukit/librpc/src/rpc/netnamer.c
@@ -0,0 +1,326 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)netnamer.c 1.13 91/03/11 Copyr 1986 Sun Micro";
+#endif
+/*
+ * netname utility routines convert from unix names to network names and
+ * vice-versa This module is operating system dependent! What we define here
+ * will work with any unix system that has adopted the sun NIS domain
+ * architecture.
+ */
+#include <sys/param.h>
+#include <rpc/rpc.h>
+#include <rpc/rpc_com.h>
+#ifdef YP
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+#include <ctype.h>
+#include <stdio.h>
+#include <grp.h>
+#include <pwd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static char *OPSYS = "unix";
+#ifdef YP
+static char *NETID = "netid.byname";
+#endif
+static char *NETIDFILE = "/etc/netid";
+
+static int getnetid __P(( char *, char * ));
+static int _getgroups __P(( char *, gid_t * ));
+
+#ifndef NGROUPS
+#define NGROUPS 16
+#endif
+
+/*
+ * Convert network-name into unix credential
+ */
+int
+netname2user(netname, uidp, gidp, gidlenp, gidlist)
+ char netname[MAXNETNAMELEN + 1];
+ uid_t *uidp;
+ gid_t *gidp;
+ int *gidlenp;
+ gid_t *gidlist;
+{
+ char *p;
+ int gidlen;
+ uid_t uid;
+ long luid;
+ struct passwd *pwd;
+ char val[1024];
+ char *val1, *val2;
+ char *domain;
+ int vallen;
+ int err;
+
+ if (getnetid(netname, val)) {
+ p = strtok(val, ":");
+ if (p == NULL)
+ return (0);
+ *uidp = (uid_t) atol(val);
+ p = strtok(NULL, "\n,");
+ *gidp = (gid_t) atol(p);
+ if (p == NULL) {
+ return (0);
+ }
+ gidlen = 0;
+ for (gidlen = 0; gidlen < NGROUPS; gidlen++) {
+ p = strtok(NULL, "\n,");
+ if (p == NULL)
+ break;
+ gidlist[gidlen] = (gid_t) atol(p);
+ }
+ *gidlenp = gidlen;
+
+ return (1);
+ }
+ val1 = strchr(netname, '.');
+ if (val1 == NULL)
+ return (0);
+ if (strncmp(netname, OPSYS, (val1-netname)))
+ return (0);
+ val1++;
+ val2 = strchr(val1, '@');
+ if (val2 == NULL)
+ return (0);
+ vallen = val2 - val1;
+ if (vallen > (1024 - 1))
+ vallen = 1024 - 1;
+ (void) strncpy(val, val1, 1024);
+ val[vallen] = 0;
+
+ err = _rpc_get_default_domain(&domain); /* change to rpc */
+ if (err)
+ return (0);
+
+ if (strcmp(val2 + 1, domain))
+ return (0); /* wrong domain */
+
+ if (sscanf(val, "%ld", &luid) != 1)
+ return (0);
+ uid = luid;
+
+ /* use initgroups method */
+ pwd = getpwuid(uid);
+ if (pwd == NULL)
+ return (0);
+ *uidp = pwd->pw_uid;
+ *gidp = pwd->pw_gid;
+ *gidlenp = _getgroups(pwd->pw_name, gidlist);
+ return (1);
+}
+
+/*
+ * initgroups
+ */
+
+static int
+_getgroups(uname, groups)
+ char *uname;
+ gid_t groups[NGROUPS];
+{
+ gid_t ngroups = 0;
+ register struct group *grp;
+ register int i;
+ register int j;
+ int filter;
+
+ setgrent();
+ while ((grp = getgrent())) {
+ for (i = 0; grp->gr_mem[i]; i++)
+ if (!strcmp(grp->gr_mem[i], uname)) {
+ if (ngroups == NGROUPS) {
+#ifdef DEBUG
+ fprintf(stderr,
+ "initgroups: %s is in too many groups\n", uname);
+#endif
+ goto toomany;
+ }
+ /* filter out duplicate group entries */
+ filter = 0;
+ for (j = 0; j < ngroups; j++)
+ if (groups[j] == grp->gr_gid) {
+ filter++;
+ break;
+ }
+ if (!filter)
+ groups[ngroups++] = grp->gr_gid;
+ }
+ }
+toomany:
+ endgrent();
+ return (ngroups);
+}
+
+/*
+ * Convert network-name to hostname
+ */
+int
+netname2host(netname, hostname, hostlen)
+ char netname[MAXNETNAMELEN + 1];
+ char *hostname;
+ int hostlen;
+{
+ int err;
+ char valbuf[1024];
+ char *val;
+ char *val2;
+ int vallen;
+ char *domain;
+
+ if (getnetid(netname, valbuf)) {
+ val = valbuf;
+ if ((*val == '0') && (val[1] == ':')) {
+ (void) strncpy(hostname, val + 2, hostlen);
+ return (1);
+ }
+ }
+ val = strchr(netname, '.');
+ if (val == NULL)
+ return (0);
+ if (strncmp(netname, OPSYS, (val - netname)))
+ return (0);
+ val++;
+ val2 = strchr(val, '@');
+ if (val2 == NULL)
+ return (0);
+ vallen = val2 - val;
+ if (vallen > (hostlen - 1))
+ vallen = hostlen - 1;
+ (void) strncpy(hostname, val, vallen);
+ hostname[vallen] = 0;
+
+ err = _rpc_get_default_domain(&domain); /* change to rpc */
+ if (err)
+ return (0);
+
+ if (strcmp(val2 + 1, domain))
+ return (0); /* wrong domain */
+ else
+ return (1);
+}
+
+/*
+ * reads the file /etc/netid looking for a + to optionally go to the
+ * network information service.
+ */
+int
+getnetid(key, ret)
+ char *key, *ret;
+{
+ char buf[1024]; /* big enough */
+ char *res;
+ char *mkey;
+ char *mval;
+ FILE *fd;
+#ifdef YP
+ char *domain;
+ int err;
+ char *lookup;
+ int len;
+#endif
+
+ fd = fopen(NETIDFILE, "r");
+ if (fd == (FILE *) 0) {
+#ifdef YP
+ res = "+";
+ goto getnetidyp;
+#else
+ return (0);
+#endif
+ }
+ for (;;) {
+ if (fd == (FILE *) 0)
+ return (0); /* getnetidyp brings us here */
+ res = fgets(buf, 1024, fd);
+ if (res == 0) {
+ fclose(fd);
+ return (0);
+ }
+ if (res[0] == '#')
+ continue;
+ else if (res[0] == '+') {
+#ifdef YP
+ getnetidyp:
+ err = yp_get_default_domain(&domain);
+ if (err) {
+ continue;
+ }
+ lookup = NULL;
+ err = yp_match(domain, NETID, key,
+ strlen(key), &lookup, &len);
+ if (err) {
+#ifdef DEBUG
+ fprintf(stderr, "match failed error %d\n", err);
+#endif
+ continue;
+ }
+ lookup[len] = 0;
+ strcpy(ret, lookup);
+ free(lookup);
+ if (fd != NULL)
+ fclose(fd);
+ return (2);
+#else /* YP */
+#ifdef DEBUG
+ fprintf(stderr,
+"Bad record in %s '+' -- NIS not supported in this library copy\n",
+ NETIDFILE);
+#endif
+ continue;
+#endif /* YP */
+ } else {
+ mkey = strtok(buf, "\t ");
+ if (mkey == NULL) {
+ fprintf(stderr,
+ "Bad record in %s -- %s", NETIDFILE, buf);
+ continue;
+ }
+ mval = strtok(NULL, " \t#\n");
+ if (mval == NULL) {
+ fprintf(stderr,
+ "Bad record in %s val problem - %s", NETIDFILE, buf);
+ continue;
+ }
+ if (strcmp(mkey, key) == 0) {
+ strcpy(ret, mval);
+ fclose(fd);
+ return (1);
+
+ }
+ }
+ }
+}
diff --git a/cpukit/librpc/src/rpc/pmap_clnt.c b/cpukit/librpc/src/rpc/pmap_clnt.c
new file mode 100644
index 0000000000..b9f3550b0b
--- /dev/null
+++ b/cpukit/librpc/src/rpc/pmap_clnt.c
@@ -0,0 +1,149 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)pmap_clnt.c 1.37 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)pmap_clnt.c 2.2 88/08/01 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/rpc/pmap_clnt.c,v 1.11 2000/01/27 23:06:39 jasone Exp $";
+#endif
+
+/*
+ * pmap_clnt.c
+ * Client interface to pmap rpc service.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
+#include <netinet/in.h>
+
+static struct timeval timeout = { 5, 0 };
+static struct timeval tottimeout = { 60, 0 };
+
+void clnt_perror();
+
+#ifndef PORTMAPSOCK
+#define PORTMAPSOCK "/var/run/portmapsock"
+#endif
+
+/*
+ * Set a mapping between program,version and port.
+ * Calls the pmap service remotely to do the mapping.
+ */
+bool_t
+pmap_set(program, version, protocol, port)
+ u_long program;
+ u_long version;
+ int protocol;
+ int port; /* was u_short but changed to match prototype */
+{
+ struct sockaddr_in myaddress;
+ int socket = -1;
+ register CLIENT *client;
+ struct pmap parms;
+ bool_t rslt;
+ struct stat st;
+
+ /*
+ * Temporary hack for backwards compatibility. Eventually
+ * this test will go away and we'll use only the "unix" transport.
+ */
+ if (stat(PORTMAPSOCK, &st) == 0 && st.st_mode & S_IFSOCK)
+ client = clnt_create(PORTMAPSOCK, PMAPPROG, PMAPVERS, "unix");
+ else {
+ if (get_myaddress(&myaddress) != 0)
+ return (FALSE);
+ myaddress.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ client = clntudp_bufcreate(&myaddress, PMAPPROG, PMAPVERS,
+ timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
+ }
+
+ if (client == (CLIENT *)NULL)
+ return (FALSE);
+ parms.pm_prog = program;
+ parms.pm_vers = version;
+ parms.pm_prot = protocol;
+ parms.pm_port = port;
+ if (CLNT_CALL(client, PMAPPROC_SET, xdr_pmap, &parms, xdr_bool, &rslt,
+ tottimeout) != RPC_SUCCESS) {
+ clnt_perror(client, "Cannot register service");
+ return (FALSE);
+ }
+ CLNT_DESTROY(client);
+ if (socket != -1)
+ (void)_RPC_close(socket);
+ return (rslt);
+}
+
+/*
+ * Remove the mapping between program,version and port.
+ * Calls the pmap service remotely to do the un-mapping.
+ */
+bool_t
+pmap_unset(program, version)
+ u_long program;
+ u_long version;
+{
+ struct sockaddr_in myaddress;
+ int socket = -1;
+ register CLIENT *client;
+ struct pmap parms;
+ bool_t rslt;
+ struct stat st;
+
+ /*
+ * Temporary hack for backwards compatibility. Eventually
+ * this test will go away and we'll use only the "unix" transport.
+ */
+ if (stat(PORTMAPSOCK, &st) == 0 && st.st_mode & S_IFSOCK)
+ client = clnt_create(PORTMAPSOCK, PMAPPROG, PMAPVERS, "unix");
+ else {
+ if (get_myaddress(&myaddress) != 0)
+ return (FALSE);
+ myaddress.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ client = clntudp_bufcreate(&myaddress, PMAPPROG, PMAPVERS,
+ timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
+ }
+ if (client == (CLIENT *)NULL)
+ return (FALSE);
+ parms.pm_prog = program;
+ parms.pm_vers = version;
+ parms.pm_port = parms.pm_prot = 0;
+ CLNT_CALL(client, PMAPPROC_UNSET, xdr_pmap, &parms, xdr_bool, &rslt,
+ tottimeout);
+ CLNT_DESTROY(client);
+ if (socket != -1)
+ (void)_RPC_close(socket);
+ return (rslt);
+}
diff --git a/cpukit/librpc/src/rpc/pmap_getmaps.c b/cpukit/librpc/src/rpc/pmap_getmaps.c
new file mode 100644
index 0000000000..3a5f6aa16e
--- /dev/null
+++ b/cpukit/librpc/src/rpc/pmap_getmaps.c
@@ -0,0 +1,86 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)pmap_getmaps.c 1.10 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)pmap_getmaps.c 2.2 88/08/01 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/rpc/pmap_getmaps.c,v 1.11 2000/01/27 23:06:39 jasone Exp $";
+#endif
+
+/*
+ * pmap_getmap.c
+ * Client interface to pmap rpc service.
+ * contains pmap_getmaps, which is only tcp service involved
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#define NAMELEN 255
+#define MAX_BROADCAST_SIZE 1400
+
+/*
+ * Get a copy of the current port maps.
+ * Calls the pmap service remotely to do get the maps.
+ */
+struct pmaplist *
+pmap_getmaps(address)
+ struct sockaddr_in *address;
+{
+ struct pmaplist *head = (struct pmaplist *)NULL;
+ int socket = -1;
+ struct timeval minutetimeout;
+ register CLIENT *client;
+
+ minutetimeout.tv_sec = 60;
+ minutetimeout.tv_usec = 0;
+ address->sin_port = htons(PMAPPORT);
+ client = clnttcp_create(address, PMAPPROG,
+ PMAPVERS, &socket, 50, 500);
+ if (client != (CLIENT *)NULL) {
+ if (CLNT_CALL(client, PMAPPROC_DUMP, xdr_void, NULL, xdr_pmaplist,
+ &head, minutetimeout) != RPC_SUCCESS) {
+ clnt_perror(client, "pmap_getmaps rpc problem");
+ }
+ CLNT_DESTROY(client);
+ }
+ if (socket != -1)
+ (void)_RPC_close(socket);
+ address->sin_port = 0;
+ return (head);
+}
diff --git a/cpukit/librpc/src/rpc/pmap_getport.c b/cpukit/librpc/src/rpc/pmap_getport.c
new file mode 100644
index 0000000000..4029f1e5b9
--- /dev/null
+++ b/cpukit/librpc/src/rpc/pmap_getport.c
@@ -0,0 +1,91 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)pmap_getport.c 1.9 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)pmap_getport.c 2.2 88/08/01 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/rpc/pmap_getport.c,v 1.10 2000/01/27 23:06:40 jasone Exp $";
+#endif
+
+/*
+ * pmap_getport.c
+ * Client interface to pmap rpc service.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <unistd.h>
+
+static struct timeval timeout = { 5, 0 };
+static struct timeval tottimeout = { 60, 0 };
+
+/*
+ * Find the mapped port for program,version.
+ * Calls the pmap service remotely to do the lookup.
+ * Returns 0 if no map exists.
+ */
+u_short
+pmap_getport(address, program, version, protocol)
+ struct sockaddr_in *address;
+ u_long program;
+ u_long version;
+ u_int protocol;
+{
+ u_short port = 0;
+ int socket = -1;
+ register CLIENT *client;
+ struct pmap parms;
+
+ address->sin_port = htons(PMAPPORT);
+ client = clntudp_bufcreate(address, PMAPPROG,
+ PMAPVERS, timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
+ if (client != (CLIENT *)NULL) {
+ parms.pm_prog = program;
+ parms.pm_vers = version;
+ parms.pm_prot = protocol;
+ parms.pm_port = 0; /* not needed or used */
+ if (CLNT_CALL(client, PMAPPROC_GETPORT, xdr_pmap, &parms,
+ xdr_u_short, &port, tottimeout) != RPC_SUCCESS){
+ rpc_createerr.cf_stat = RPC_PMAPFAILURE;
+ clnt_geterr(client, &rpc_createerr.cf_error);
+ } else if (port == 0) {
+ rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
+ }
+ CLNT_DESTROY(client);
+ }
+ if (socket != -1)
+ (void)_RPC_close(socket);
+ address->sin_port = 0;
+ return (port);
+}
diff --git a/cpukit/librpc/src/rpc/pmap_prot.c b/cpukit/librpc/src/rpc/pmap_prot.c
new file mode 100644
index 0000000000..ec7ab30812
--- /dev/null
+++ b/cpukit/librpc/src/rpc/pmap_prot.c
@@ -0,0 +1,59 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)pmap_prot.c 1.17 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)pmap_prot.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/rpc/pmap_prot.c,v 1.6 1999/08/28 00:00:42 peter Exp $";
+#endif
+
+/*
+ * pmap_prot.c
+ * Protocol for the local binder service, or pmap.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/pmap_prot.h>
+
+
+bool_t
+xdr_pmap(xdrs, regs)
+ XDR *xdrs;
+ struct pmap *regs;
+{
+
+ if (xdr_u_long(xdrs, &regs->pm_prog) &&
+ xdr_u_long(xdrs, &regs->pm_vers) &&
+ xdr_u_long(xdrs, &regs->pm_prot))
+ return (xdr_u_long(xdrs, &regs->pm_port));
+ return (FALSE);
+}
diff --git a/cpukit/librpc/src/rpc/pmap_prot2.c b/cpukit/librpc/src/rpc/pmap_prot2.c
new file mode 100644
index 0000000000..e29efe62c1
--- /dev/null
+++ b/cpukit/librpc/src/rpc/pmap_prot2.c
@@ -0,0 +1,118 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)pmap_prot2.c 1.3 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)pmap_prot2.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/rpc/pmap_prot2.c,v 1.7 1999/08/28 00:00:42 peter Exp $";
+#endif
+
+/*
+ * pmap_prot2.c
+ * Protocol for the local binder service, or pmap.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/pmap_prot.h>
+
+
+/*
+ * What is going on with linked lists? (!)
+ * First recall the link list declaration from pmap_prot.h:
+ *
+ * struct pmaplist {
+ * struct pmap pml_map;
+ * struct pmaplist *pml_map;
+ * };
+ *
+ * Compare that declaration with a corresponding xdr declaration that
+ * is (a) pointer-less, and (b) recursive:
+ *
+ * typedef union switch (bool_t) {
+ *
+ * case TRUE: struct {
+ * struct pmap;
+ * pmaplist_t foo;
+ * };
+ *
+ * case FALSE: struct {};
+ * } pmaplist_t;
+ *
+ * Notice that the xdr declaration has no nxt pointer while
+ * the C declaration has no bool_t variable. The bool_t can be
+ * interpreted as ``more data follows me''; if FALSE then nothing
+ * follows this bool_t; if TRUE then the bool_t is followed by
+ * an actual struct pmap, and then (recursively) by the
+ * xdr union, pamplist_t.
+ *
+ * This could be implemented via the xdr_union primitive, though this
+ * would cause a one recursive call per element in the list. Rather than do
+ * that we can ``unwind'' the recursion
+ * into a while loop and do the union arms in-place.
+ *
+ * The head of the list is what the C programmer wishes to past around
+ * the net, yet is the data that the pointer points to which is interesting;
+ * this sounds like a job for xdr_reference!
+ */
+bool_t
+xdr_pmaplist(xdrs, rp)
+ register XDR *xdrs;
+ register struct pmaplist **rp;
+{
+ /*
+ * more_elements is pre-computed in case the direction is
+ * XDR_ENCODE or XDR_FREE. more_elements is overwritten by
+ * xdr_bool when the direction is XDR_DECODE.
+ */
+ bool_t more_elements;
+ register int freeing = (xdrs->x_op == XDR_FREE);
+ register struct pmaplist **next = NULL;
+
+ while (TRUE) {
+ more_elements = (bool_t)(*rp != NULL);
+ if (! xdr_bool(xdrs, &more_elements))
+ return (FALSE);
+ if (! more_elements)
+ return (TRUE); /* we are done */
+ /*
+ * the unfortunate side effect of non-recursion is that in
+ * the case of freeing we must remember the next object
+ * before we free the current object ...
+ */
+ if (freeing)
+ next = &((*rp)->pml_next);
+ if (! xdr_reference(xdrs, (caddr_t *)rp,
+ (u_int)sizeof(struct pmaplist), xdr_pmap))
+ return (FALSE);
+ rp = (freeing) ? next : &((*rp)->pml_next);
+ }
+}
diff --git a/cpukit/librpc/src/rpc/pmap_rmt.c b/cpukit/librpc/src/rpc/pmap_rmt.c
new file mode 100644
index 0000000000..32a51be239
--- /dev/null
+++ b/cpukit/librpc/src/rpc/pmap_rmt.c
@@ -0,0 +1,415 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)pmap_rmt.c 1.21 87/08/27 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)pmap_rmt.c 2.2 88/08/01 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/rpc/pmap_rmt.c,v 1.15 2000/01/27 23:06:40 jasone Exp $";
+#endif
+
+/*
+ * pmap_rmt.c
+ * Client interface to pmap rpc service.
+ * remote call and broadcast service
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
+#include <rpc/pmap_rmt.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <arpa/inet.h>
+#include <sys/select.h>
+#define MAX_BROADCAST_SIZE 1400
+
+static struct timeval timeout = { 3, 0 };
+
+/*
+ * pmapper remote-call-service interface.
+ * This routine is used to call the pmapper remote call service
+ * which will look up a service program in the port maps, and then
+ * remotely call that routine with the given parameters. This allows
+ * programs to do a lookup and call in one step.
+*/
+enum clnt_stat
+pmap_rmtcall(addr, prog, vers, proc, xdrargs, argsp, xdrres, resp, tout, port_ptr)
+ struct sockaddr_in *addr;
+ u_long prog, vers, proc;
+ xdrproc_t xdrargs, xdrres;
+ caddr_t argsp, resp;
+ struct timeval tout;
+ u_long *port_ptr;
+{
+ int socket = -1;
+ register CLIENT *client;
+ struct rmtcallargs a;
+ struct rmtcallres r;
+ enum clnt_stat stat;
+
+ addr->sin_port = htons(PMAPPORT);
+ client = clntudp_create(addr, PMAPPROG, PMAPVERS, timeout, &socket);
+ if (client != (CLIENT *)NULL) {
+ a.prog = prog;
+ a.vers = vers;
+ a.proc = proc;
+ a.args_ptr = argsp;
+ a.xdr_args = xdrargs;
+ r.port_ptr = port_ptr;
+ r.results_ptr = resp;
+ r.xdr_results = xdrres;
+ stat = CLNT_CALL(client, PMAPPROC_CALLIT, xdr_rmtcall_args, &a,
+ xdr_rmtcallres, &r, tout);
+ CLNT_DESTROY(client);
+ } else {
+ stat = RPC_FAILED;
+ }
+ if (socket != -1)
+ (void)_RPC_close(socket);
+ addr->sin_port = 0;
+ return (stat);
+}
+
+
+/*
+ * XDR remote call arguments
+ * written for XDR_ENCODE direction only
+ */
+bool_t
+xdr_rmtcall_args(xdrs, cap)
+ register XDR *xdrs;
+ register struct rmtcallargs *cap;
+{
+ u_int lenposition, argposition, position;
+
+ if (xdr_u_long(xdrs, &(cap->prog)) &&
+ xdr_u_long(xdrs, &(cap->vers)) &&
+ xdr_u_long(xdrs, &(cap->proc))) {
+ lenposition = XDR_GETPOS(xdrs);
+ if (! xdr_u_long(xdrs, &(cap->arglen)))
+ return (FALSE);
+ argposition = XDR_GETPOS(xdrs);
+ if (! (*(cap->xdr_args))(xdrs, cap->args_ptr))
+ return (FALSE);
+ position = XDR_GETPOS(xdrs);
+ cap->arglen = (u_long)position - (u_long)argposition;
+ XDR_SETPOS(xdrs, lenposition);
+ if (! xdr_u_long(xdrs, &(cap->arglen)))
+ return (FALSE);
+ XDR_SETPOS(xdrs, position);
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/*
+ * XDR remote call results
+ * written for XDR_DECODE direction only
+ */
+bool_t
+xdr_rmtcallres(xdrs, crp)
+ register XDR *xdrs;
+ register struct rmtcallres *crp;
+{
+ caddr_t port_ptr;
+
+ port_ptr = (caddr_t)crp->port_ptr;
+ if (xdr_reference(xdrs, &port_ptr, sizeof (u_long),
+ xdr_u_long) && xdr_u_long(xdrs, &crp->resultslen)) {
+ crp->port_ptr = (u_long *)port_ptr;
+ return ((*(crp->xdr_results))(xdrs, crp->results_ptr));
+ }
+ return (FALSE);
+}
+
+
+/*
+ * The following is kludged-up support for simple rpc broadcasts.
+ * Someday a large, complicated system will replace these trivial
+ * routines which only support udp/ip .
+ */
+
+static int
+getbroadcastnets(addrs, sock, buf)
+ struct in_addr *addrs;
+ int sock; /* any valid socket will do */
+ char *buf; /* why allocxate more when we can use existing... */
+{
+ struct ifconf ifc;
+ struct ifreq ifreq, *ifr;
+ struct sockaddr_in *sin;
+ struct in_addr addr;
+ char *cp, *cplim;
+ int n, i = 0;
+
+ ifc.ifc_len = UDPMSGSIZE;
+ ifc.ifc_buf = buf;
+ if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
+ perror("broadcast: ioctl (get interface configuration)");
+ return (0);
+ }
+#define max(a, b) (a > b ? a : b)
+#define size(p) max((p).sa_len, sizeof(p))
+ cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */
+ for (cp = buf; cp < cplim;
+ cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr)) {
+ ifr = (struct ifreq *)cp;
+ if (ifr->ifr_addr.sa_family != AF_INET)
+ continue;
+ ifreq = *ifr;
+ if (ioctl(sock, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
+ perror("broadcast: ioctl (get interface flags)");
+ continue;
+ }
+ if ((ifreq.ifr_flags & IFF_BROADCAST) &&
+ (ifreq.ifr_flags & IFF_UP)) {
+ sin = (struct sockaddr_in *)&ifr->ifr_addr;
+#ifdef SIOCGIFBRDADDR /* 4.3BSD */
+ if (ioctl(sock, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
+ addr =
+ inet_makeaddr(inet_netof(sin->sin_addr),
+ INADDR_ANY);
+ } else {
+ addr = ((struct sockaddr_in*)
+ &ifreq.ifr_addr)->sin_addr;
+ }
+#else /* 4.2 BSD */
+ addr = inet_makeaddr(inet_netof(sin->sin_addr),
+ INADDR_ANY);
+#endif
+ for (n=i-1; n>=0; n--) {
+ if (addr.s_addr == addrs[n].s_addr)
+ break;
+ }
+ if (n<0) {
+ addrs[i++] = addr;
+ }
+ }
+ }
+ return (i);
+}
+
+typedef bool_t (*resultproc_t)();
+
+enum clnt_stat
+clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)
+ u_long prog; /* program number */
+ u_long vers; /* version number */
+ u_long proc; /* procedure number */
+ xdrproc_t xargs; /* xdr routine for args */
+ caddr_t argsp; /* pointer to args */
+ xdrproc_t xresults; /* xdr routine for results */
+ caddr_t resultsp; /* pointer to results */
+ resultproc_t eachresult; /* call with each result obtained */
+{
+ enum clnt_stat stat = RPC_SUCCESS; /* to avoid warning */
+ AUTH *unix_auth = authunix_create_default();
+ XDR xdr_stream;
+ register XDR *xdrs = &xdr_stream;
+ int outlen, inlen, fromlen, nets;
+ register int sock;
+ int on = 1;
+ fd_set *fds = 0, readfds; /* initialized to avoid warning */
+ register int i;
+ bool_t done = FALSE;
+ register u_long xid;
+ u_long port;
+ struct in_addr addrs[20];
+ struct sockaddr_in baddr, raddr; /* broadcast and response addresses */
+ struct rmtcallargs a;
+ struct rmtcallres r;
+ struct rpc_msg msg;
+ struct timeval t, tv;
+ char outbuf[MAX_BROADCAST_SIZE], inbuf[UDPMSGSIZE];
+ static u_int32_t disrupt;
+
+ if (disrupt == 0)
+ disrupt = (u_int32_t)(long)resultsp;
+
+ /*
+ * initialization: create a socket, a broadcast address, and
+ * preserialize the arguments into a send buffer.
+ */
+ if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+ perror("Cannot create socket for broadcast rpc");
+ stat = RPC_CANTSEND;
+ goto done_broad;
+ }
+#ifdef SO_BROADCAST
+ if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) {
+ perror("Cannot set socket option SO_BROADCAST");
+ stat = RPC_CANTSEND;
+ goto done_broad;
+ }
+#endif /* def SO_BROADCAST */
+ if (sock + 1 > FD_SETSIZE) {
+ int bytes = howmany(sock + 1, NFDBITS) * sizeof(fd_mask);
+ fds = (fd_set *)malloc(bytes);
+ if (fds == NULL) {
+ stat = RPC_CANTSEND;
+ goto done_broad;
+ }
+ memset(fds, 0, bytes);
+ } else {
+ fds = &readfds;
+ FD_ZERO(fds);
+ }
+
+ nets = getbroadcastnets(addrs, sock, inbuf);
+ memset(&baddr, 0, sizeof (baddr));
+ baddr.sin_len = sizeof(struct sockaddr_in);
+ baddr.sin_family = AF_INET;
+ baddr.sin_port = htons(PMAPPORT);
+ baddr.sin_addr.s_addr = htonl(INADDR_ANY);
+ (void)gettimeofday(&t, (struct timezone *)0);
+ msg.rm_xid = xid = (++disrupt) ^ getpid() ^ t.tv_sec ^ t.tv_usec;
+ t.tv_usec = 0;
+ msg.rm_direction = CALL;
+ msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+ msg.rm_call.cb_prog = PMAPPROG;
+ msg.rm_call.cb_vers = PMAPVERS;
+ msg.rm_call.cb_proc = PMAPPROC_CALLIT;
+ msg.rm_call.cb_cred = unix_auth->ah_cred;
+ msg.rm_call.cb_verf = unix_auth->ah_verf;
+ a.prog = prog;
+ a.vers = vers;
+ a.proc = proc;
+ a.xdr_args = xargs;
+ a.args_ptr = argsp;
+ r.port_ptr = &port;
+ r.xdr_results = xresults;
+ r.results_ptr = resultsp;
+ xdrmem_create(xdrs, outbuf, MAX_BROADCAST_SIZE, XDR_ENCODE);
+ if ((! xdr_callmsg(xdrs, &msg)) || (! xdr_rmtcall_args(xdrs, &a))) {
+ stat = RPC_CANTENCODEARGS;
+ goto done_broad;
+ }
+ outlen = (int)xdr_getpos(xdrs);
+ xdr_destroy(xdrs);
+ /*
+ * Basic loop: broadcast a packet and wait a while for response(s).
+ * The response timeout grows larger per iteration.
+ *
+ * XXX This will loop about 5 times the stop. If there are
+ * lots of signals being received by the process it will quit
+ * send them all in one quick burst, not paying attention to
+ * the intended function of sending them slowly over half a
+ * minute or so
+ */
+ for (t.tv_sec = 4; t.tv_sec <= 14; t.tv_sec += 2) {
+ for (i = 0; i < nets; i++) {
+ baddr.sin_addr = addrs[i];
+ if (sendto(sock, outbuf, outlen, 0,
+ (struct sockaddr *)&baddr,
+ sizeof (struct sockaddr)) != outlen) {
+ perror("Cannot send broadcast packet");
+ stat = RPC_CANTSEND;
+ goto done_broad;
+ }
+ }
+ if (eachresult == NULL) {
+ stat = RPC_SUCCESS;
+ goto done_broad;
+ }
+ recv_again:
+ msg.acpted_rply.ar_verf = _null_auth;
+ msg.acpted_rply.ar_results.where = (caddr_t)&r;
+ msg.acpted_rply.ar_results.proc = xdr_rmtcallres;
+ /* XXX we know the other bits are still clear */
+ FD_SET(sock, fds);
+ tv = t; /* for select() that copies back */
+ switch (select(sock + 1, fds, NULL, NULL, &tv)) {
+
+ case 0: /* timed out */
+ stat = RPC_TIMEDOUT;
+ continue;
+
+ case -1: /* some kind of error */
+ if (errno == EINTR)
+ goto recv_again;
+ perror("Broadcast select problem");
+ stat = RPC_CANTRECV;
+ goto done_broad;
+
+ } /* end of select results switch */
+ try_again:
+ fromlen = sizeof(struct sockaddr);
+ inlen = recvfrom(sock, inbuf, UDPMSGSIZE, 0,
+ (struct sockaddr *)&raddr, &fromlen);
+ if (inlen < 0) {
+ if (errno == EINTR)
+ goto try_again;
+ perror("Cannot receive reply to broadcast");
+ stat = RPC_CANTRECV;
+ goto done_broad;
+ }
+ if (inlen < sizeof(u_int32_t))
+ goto recv_again;
+ /*
+ * see if reply transaction id matches sent id.
+ * If so, decode the results.
+ */
+ xdrmem_create(xdrs, inbuf, (u_int)inlen, XDR_DECODE);
+ if (xdr_replymsg(xdrs, &msg)) {
+ if ((msg.rm_xid == xid) &&
+ (msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
+ (msg.acpted_rply.ar_stat == SUCCESS)) {
+ raddr.sin_port = htons((u_short)port);
+ done = (*eachresult)(resultsp, &raddr);
+ }
+ /* otherwise, we just ignore the errors ... */
+ }
+ xdrs->x_op = XDR_FREE;
+ msg.acpted_rply.ar_results.proc = xdr_void;
+ (void)xdr_replymsg(xdrs, &msg);
+ (void)(*xresults)(xdrs, resultsp);
+ xdr_destroy(xdrs);
+ if (done) {
+ stat = RPC_SUCCESS;
+ goto done_broad;
+ } else {
+ goto recv_again;
+ }
+ }
+done_broad:
+ if (fds != &readfds)
+ free(fds);
+ if (sock >= 0)
+ (void)_RPC_close(sock);
+ AUTH_DESTROY(unix_auth);
+ return (stat);
+}
diff --git a/cpukit/librpc/src/rpc/publickey.3 b/cpukit/librpc/src/rpc/publickey.3
new file mode 100644
index 0000000000..29094f98b2
--- /dev/null
+++ b/cpukit/librpc/src/rpc/publickey.3
@@ -0,0 +1,47 @@
+.\" @(#)publickey.3r 2.1 88/08/07 4.0 RPCSRC
+.\" $FreeBSD: src/lib/libc/rpc/publickey.3,v 1.4 2000/03/02 09:13:46 sheldonh Exp $
+.\"
+.TH PUBLICKEY 3R "6 October 1987"
+.SH NAME
+publickey, getpublickey, getsecretkey \- get public or secret key
+.SH SYNOPSIS
+.nf
+.B #include <rpc/rpc.h>
+.B #include <rpc/key_prot.h>
+.LP
+.B getpublickey(netname, publickey)
+.B char netname[\s-1MAXNETNAMELEN\s0+1];
+.B char publickey[\s-1HEXKEYBYTES\s0+1];
+.LP
+.B getsecretkey(netname, secretkey, passwd)
+.B char netname[\s-1MAXNETNAMELEN\s0+1];
+.B char secretkey[\s-1HEXKEYBYTES\s0+1];
+.B char *passwd;
+.fi
+.SH DESCRIPTION
+.IX "getpublickey function" "" "\fLgetpublickey()\fP function"
+.IX "getsecretkey function" "" "\fLgetsecretkey()\fP function"
+These routines are used to get public and secret keys from the
+.SM YP
+database.
+.B getsecretkey(\|)
+has an extra argument,
+.IR passwd ,
+which is used to decrypt the encrypted secret key stored in the database.
+Both routines return 1 if they are successful in finding the key, 0 otherwise.
+The keys are returned as
+.SM NULL\s0-terminated,
+hexadecimal strings.
+If the password supplied to
+.B getsecretkey(\|)
+fails to decrypt the secret key, the routine will return 1 but the
+.I secretkey
+argument will be a
+.SM NULL
+string (``'').
+.SH "SEE ALSO"
+.BR publickey (5)
+.LP
+.I \s-1RPC\s0 Programmer's Manual
+in
+.TX NETP
diff --git a/cpukit/librpc/src/rpc/publickey.5 b/cpukit/librpc/src/rpc/publickey.5
new file mode 100644
index 0000000000..9f7a325488
--- /dev/null
+++ b/cpukit/librpc/src/rpc/publickey.5
@@ -0,0 +1,38 @@
+.\" $FreeBSD: src/lib/libc/rpc/publickey.5,v 1.5 2000/03/02 09:13:46 sheldonh Exp $
+.\" @(#)publickey.5 2.1 88/08/07 4.0 RPCSRC; from 1.6 88/02/29 SMI;
+.TH PUBLICKEY 5 "19 October 1987"
+.SH NAME
+publickey \- public key database
+.SH SYNOPSIS
+.B /etc/publickey
+.SH DESCRIPTION
+.LP
+.B /etc/publickey
+is the public key database used for secure
+networking.
+Each entry in
+the database consists of a network user
+name (which may either refer to
+a user or a hostname), followed by the user's
+public key (in hex
+notation), a colon, and then the user's
+secret key encrypted with
+its login password (also in hex notation).
+.LP
+This file is altered either by the user through the
+.BR chkey (1)
+command or by the system administrator through the
+.BR newkey (8)
+command.
+The file
+.B /etc/publickey
+should only contain data on the NIS master machine, where it
+is converted into the
+.SM NIS
+database
+.BR publickey.byname .
+.SH SEE ALSO
+.BR chkey (1),
+.BR publickey (3R),
+.BR newkey (8),
+.BR ypupdated (8C)
diff --git a/cpukit/librpc/src/rpc/rpc.3 b/cpukit/librpc/src/rpc/rpc.3
new file mode 100644
index 0000000000..f40b643827
--- /dev/null
+++ b/cpukit/librpc/src/rpc/rpc.3
@@ -0,0 +1,1767 @@
+.\" @(#)rpc.3n 2.4 88/08/08 4.0 RPCSRC; from 1.19 88/06/24 SMI
+.\" $FreeBSD: src/lib/libc/rpc/rpc.3,v 1.11 2000/03/02 09:13:47 sheldonh Exp $
+.\"
+.TH RPC 3 "16 February 1988"
+.SH NAME
+rpc \- library routines for remote procedure calls
+.SH SYNOPSIS AND DESCRIPTION
+These routines allow C programs to make procedure
+calls on other machines across the network.
+First, the client calls a procedure to send a
+data packet to the server.
+Upon receipt of the packet, the server calls a dispatch routine
+to perform the requested service, and then sends back a
+reply.
+Finally, the procedure call returns to the client.
+.LP
+Routines that are used for Secure RPC (DES authentication) are described in
+.BR rpc_secure (3).
+Secure RPC can be used only if DES encryption is available.
+.LP
+.ft B
+.nf
+.sp .5
+#include <rpc/rpc.h>
+.fi
+.ft R
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+void
+auth_destroy(auth)
+\s-1AUTH\s0 *auth;
+.fi
+.ft R
+.IP
+A macro that destroys the authentication information associated with
+.IR auth .
+Destruction usually involves deallocation of private data
+structures.
+The use of
+.I auth
+is undefined after calling
+.BR auth_destroy(\|) .
+.br
+.if t .ne 6
+.LP
+.ft B
+.nf
+.sp .5
+\s-1AUTH\s0 *
+authnone_create(\|)
+.fi
+.ft R
+.IP
+Create and returns an
+.SM RPC
+authentication handle that passes nonusable authentication
+information with each remote procedure call.
+This is the
+default authentication used by
+.SM RPC.
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+\s-1AUTH\s0 *
+authunix_create(host, uid, gid, len, aup_gids)
+char *host;
+int uid, gid, len, *aup.gids;
+.fi
+.ft R
+.IP
+Create and return an
+.SM RPC
+authentication handle that contains
+.UX
+authentication information.
+The parameter
+.I host
+is the name of the machine on which the information was
+created;
+.I uid
+is the user's user
+.SM ID ;
+.I gid
+is the user's current group
+.SM ID ;
+.I len
+and
+.I aup_gids
+refer to a counted array of groups to which the user belongs.
+It is easy to impersonate a user.
+.br
+.if t .ne 5
+.LP
+.ft B
+.nf
+.sp .5
+\s-1AUTH\s0 *
+authunix_create_default(\|)
+.fi
+.ft R
+.IP
+Calls
+.B authunix_create(\|)
+with the appropriate parameters.
+.br
+.if t .ne 13
+.LP
+.ft B
+.nf
+.sp .5
+callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out)
+char *host;
+u_long prognum, versnum, procnum;
+char *in, *out;
+xdrproc_t inproc, outproc;
+.fi
+.ft R
+.IP
+Call the remote procedure associated with
+.IR prognum ,
+.IR versnum ,
+and
+.I procnum
+on the machine,
+.IR host .
+The parameter
+.I in
+is the address of the procedure's argument(s), and
+.I out
+is the address of where to place the result(s);
+.I inproc
+is used to encode the procedure's parameters, and
+.I outproc
+is used to decode the procedure's results.
+This routine returns zero if it succeeds, or the value of
+.B "enum clnt_stat"
+cast to an integer if it fails.
+The routine
+.B clnt_perrno(\|)
+is handy for translating failure statuses into messages.
+.IP
+Warning: calling remote procedures with this routine
+uses
+.SM UDP/IP
+as a transport; see
+.B clntudp_create(\|)
+for restrictions.
+You do not have control of timeouts or authentication using
+this routine.
+.br
+.if t .ne 16
+.LP
+.ft B
+.nf
+.sp .5
+enum clnt_stat
+clnt_broadcast(prognum, versnum, procnum, inproc, in, outproc, out, eachresult)
+u_long prognum, versnum, procnum;
+char *in, *out;
+xdrproc_t inproc, outproc;
+resultproc_t eachresult;
+.fi
+.ft R
+.IP
+Like
+.BR callrpc(\|) ,
+except the call message is broadcast to all locally
+connected broadcast nets.
+Each time it receives a
+response, this routine calls
+.BR eachresult(\|) ,
+whose form is:
+.IP
+.RS 1i
+.ft B
+.nf
+eachresult(out, addr)
+char *out;
+struct sockaddr_in *addr;
+.ft R
+.fi
+.RE
+.IP
+where
+.I out
+is the same as
+.I out
+passed to
+.BR clnt_broadcast(\|) ,
+except that the remote procedure's output is decoded there;
+.I addr
+points to the address of the machine that sent the results.
+If
+.B eachresult(\|)
+returns zero,
+.B clnt_broadcast(\|)
+waits for more replies; otherwise it returns with appropriate
+status.
+.IP
+Warning: broadcast sockets are limited in size to the
+maximum transfer unit of the data link.
+For ethernet,
+this value is 1500 bytes.
+.br
+.if t .ne 13
+.LP
+.ft B
+.nf
+.sp .5
+enum clnt_stat
+clnt_call(clnt, procnum, inproc, in, outproc, out, tout)
+\s-1CLIENT\s0 *clnt;
+u_long
+procnum;
+xdrproc_t inproc, outproc;
+char *in, *out;
+struct timeval tout;
+.fi
+.ft R
+.IP
+A macro that calls the remote procedure
+.I procnum
+associated with the client handle,
+.IR clnt ,
+which is obtained with an
+.SM RPC
+client creation routine such as
+.BR clnt_create(\|) .
+The parameter
+.I in
+is the address of the procedure's argument(s), and
+.I out
+is the address of where to place the result(s);
+.I inproc
+is used to encode the procedure's parameters, and
+.I outproc
+is used to decode the procedure's results;
+.I tout
+is the time allowed for results to come back.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+clnt_destroy(clnt)
+\s-1CLIENT\s0 *clnt;
+.fi
+.ft R
+.IP
+A macro that destroys the client's
+.SM RPC
+handle.
+Destruction usually involves deallocation
+of private data structures, including
+.I clnt
+itself. Use of
+.I clnt
+is undefined after calling
+.BR clnt_destroy(\|) .
+If the
+.SM RPC
+library opened the associated socket, it will close it also.
+Otherwise, the socket remains open.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+\s-1CLIENT\s0 *
+clnt_create(host, prog, vers, proto)
+char *host;
+u_long prog, vers;
+char *proto;
+.fi
+.ft R
+.IP
+Generic client creation routine.
+.I host
+identifies the name of the remote host where the server
+is located.
+.I proto
+indicates which kind of transport protocol to use.
+The
+currently supported values for this field are \(lqudp\(rq
+and \(lqtcp\(rq.
+Default timeouts are set, but can be modified using
+.BR clnt_control(\|) .
+.IP
+Warning: Using
+.SM UDP
+has its shortcomings. Since
+.SM UDP\s0-based
+.SM RPC
+messages can only hold up to 8 Kbytes of encoded data,
+this transport cannot be used for procedures that take
+large arguments or return huge results.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+bool_t
+clnt_control(cl, req, info)
+\s-1CLIENT\s0 *cl;
+u_int req;
+char *info;
+.fi
+.ft R
+.IP
+A macro used to change or retrieve various information
+about a client object.
+.I req
+indicates the type of operation, and
+.I info
+is a pointer to the information.
+For both
+.SM UDP
+and
+.SM TCP\s0,
+the supported values of
+.I req
+and their argument types and what they do are:
+.IP
+.nf
+.ta +2.0i +2.0i +2.0i
+.SM CLSET_TIMEOUT\s0 struct timeval set total timeout
+.SM CLGET_TIMEOUT\s0 struct timeval get total timeout
+.fi
+.IP
+Note: if you set the timeout using
+.BR clnt_control(\|) ,
+the timeout parameter passed to
+.B clnt_call(\|)
+will be ignored in all future calls.
+.IP
+.nf
+.SM CLGET_SERVER_ADDR\s0 struct sockaddr_in get server's address
+.fi
+.br
+.IP
+The following operations are valid for
+.SM UDP
+only:
+.IP
+.nf
+.ta +2.0i ; +2.0i ; +2.0i
+.SM CLSET_RETRY_TIMEOUT\s0 struct timeval set the retry timeout
+.SM CLGET_RETRY_TIMEOUT\s0 struct timeval get the retry timeout
+.fi
+.br
+.IP
+The retry timeout is the time that
+.SM "UDP RPC"
+waits for the server to reply before
+retransmitting the request.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+clnt_freeres(clnt, outproc, out)
+\s-1CLIENT\s0 *clnt;
+xdrproc_t outproc;
+char *out;
+.fi
+.ft R
+.IP
+A macro that frees any data allocated by the
+.SM RPC/XDR
+system when it decoded the results of an
+.SM RPC
+call. The
+parameter
+.I out
+is the address of the results, and
+.I outproc
+is the
+.SM XDR
+routine describing the results.
+This routine returns one if the results were successfully
+freed,
+and zero otherwise.
+.br
+.if t .ne 6
+.LP
+.ft B
+.nf
+.sp .5
+void
+clnt_geterr(clnt, errp)
+\s-1CLIENT\s0 *clnt;
+struct rpc_err *errp;
+.fi
+.ft R
+.IP
+A macro that copies the error structure out of the client
+handle
+to the structure at address
+.IR errp .
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+void
+clnt_pcreateerror(s)
+char *s;
+.fi
+.ft R
+.IP
+Print a message to standard error indicating
+why a client
+.SM RPC
+handle could not be created.
+The message is prepended with string
+.I s
+and a colon.
+Used when a
+.BR clnt_create(\|) ,
+.BR clntraw_create(\|) ,
+.BR clnttcp_create(\|) ,
+or
+.B clntudp_create(\|)
+call fails.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+void
+clnt_perrno(stat)
+enum clnt_stat stat;
+.fi
+.ft R
+.IP
+Print a message to standard error corresponding
+to the condition indicated by
+.IR stat .
+Used after
+.BR callrpc(\|) .
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+clnt_perror(clnt, s)
+\s-1CLIENT\s0 *clnt;
+char *s;
+.fi
+.ft R
+.IP
+Print a message to standard error indicating why an
+.SM RPC
+call failed;
+.I clnt
+is the handle used to do the call.
+The message is prepended with string
+.I s
+and a colon.
+Used after
+.BR clnt_call(\|) .
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+char *
+clnt_spcreateerror
+char *s;
+.fi
+.ft R
+.IP
+Like
+.BR clnt_pcreateerror(\|) ,
+except that it returns a string
+instead of printing to the standard error.
+.IP
+Bugs: returns pointer to static data that is overwritten
+on each call.
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+char *
+clnt_sperrno(stat)
+enum clnt_stat stat;
+.fi
+.ft R
+.IP
+Take the same arguments as
+.BR clnt_perrno(\|) ,
+but instead of sending a message to the standard error
+indicating why an
+.SM RPC
+call failed, return a pointer to a string which contains
+the message. The string ends with a
+.SM NEWLINE\s0.
+.IP
+.B clnt_sperrno(\|)
+is used instead of
+.B clnt_perrno(\|)
+if the program does not have a standard error (as a program
+running as a server quite likely does not), or if the
+programmer
+does not want the message to be output with
+.BR printf ,
+or if a message format different from that supported by
+.B clnt_perrno(\|)
+is to be used.
+Note: unlike
+.B clnt_sperror(\|)
+and
+.BR clnt_spcreaterror(\|) ,
+.B clnt_sperrno(\|)
+returns pointer to static data, but the
+result will not get overwritten on each call.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+char *
+clnt_sperror(rpch, s)
+\s-1CLIENT\s0 *rpch;
+char *s;
+.fi
+.ft R
+.IP
+Like
+.BR clnt_perror(\|) ,
+except that (like
+.BR clnt_sperrno(\|) )
+it returns a string instead of printing to standard error.
+.IP
+Bugs: returns pointer to static data that is overwritten
+on each call.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+\s-1CLIENT\s0 *
+clntraw_create(prognum, versnum)
+u_long prognum, versnum;
+.fi
+.ft R
+.IP
+This routine creates a toy
+.SM RPC
+client for the remote program
+.IR prognum ,
+version
+.IR versnum .
+The transport used to pass messages to the service is
+actually a buffer within the process's address space, so the
+corresponding
+.SM RPC
+server should live in the same address space; see
+.BR svcraw_create(\|) .
+This allows simulation of
+.SM RPC
+and acquisition of
+.SM RPC
+overheads, such as round trip times, without any
+kernel interference.
+This routine returns
+.SM NULL
+if it fails.
+.br
+.if t .ne 15
+.LP
+.ft B
+.nf
+.sp .5
+\s-1CLIENT\s0 *
+clnttcp_create(addr, prognum, versnum, sockp, sendsz, recvsz)
+struct sockaddr_in *addr;
+u_long prognum, versnum;
+int *sockp;
+u_int sendsz, recvsz;
+.fi
+.ft R
+.IP
+This routine creates an
+.SM RPC
+client for the remote program
+.IR prognum ,
+version
+.IR versnum ;
+the client uses
+.SM TCP/IP
+as a transport.
+The remote program is located at Internet
+address
+.IR *addr .
+If
+.\"The following in-line font conversion is necessary for the hyphen indicator
+\fB\%addr\->sin_port\fR
+is zero, then it is set to the actual port that the remote
+program is listening on (the remote
+.B portmap
+service is consulted for this information). The parameter
+.I sockp
+is a socket; if it is
+.BR \s-1RPC_ANYSOCK\s0 ,
+then this routine opens a new one and sets
+.IR sockp .
+Since
+.SM TCP\s0-based
+.SM RPC
+uses buffered
+.SM I/O ,
+the user may specify the size of the send and receive buffers
+with the parameters
+.I sendsz
+and
+.IR recvsz ;
+values of zero choose suitable defaults.
+This routine returns
+.SM NULL
+if it fails.
+.br
+.if t .ne 15
+.LP
+.ft B
+.nf
+.sp .5
+\s-1CLIENT\s0 *
+clntudp_create(addr, prognum, versnum, wait, sockp)
+struct sockaddr_in *addr;
+u_long prognum, versnum;
+struct timeval wait;
+int *sockp;
+.fi
+.ft R
+.IP
+This routine creates an
+.SM RPC
+client for the remote program
+.IR prognum ,
+version
+.IR versnum ;
+the client uses
+.SM UDP/IP
+as a transport.
+The remote program is located at Internet
+address
+.IR addr .
+If
+\fB\%addr\->sin_port\fR
+is zero, then it is set to actual port that the remote
+program is listening on (the remote
+.B portmap
+service is consulted for this information). The parameter
+.I sockp
+is a socket; if it is
+.BR \s-1RPC_ANYSOCK\s0 ,
+then this routine opens a new one and sets
+.IR sockp .
+The
+.SM UDP
+transport resends the call message in intervals of
+.B wait
+time until a response is received or until the call times
+out.
+The total time for the call to time out is specified by
+.BR clnt_call(\|) .
+.IP
+Warning: since
+.SM UDP\s0-based
+.SM RPC
+messages can only hold up to 8 Kbytes
+of encoded data, this transport cannot be used for procedures
+that take large arguments or return huge results.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+\s-1CLIENT\s0 *
+clntudp_bufcreate(addr, prognum, versnum, wait, sockp, sendsize, recosize)
+struct sockaddr_in *addr;
+u_long prognum, versnum;
+struct timeval wait;
+int *sockp;
+unsigned int sendsize;
+unsigned int recosize;
+.fi
+.ft R
+.IP
+This routine creates an
+.SM RPC
+client for the remote program
+.IR prognum ,
+on
+.IR versnum ;
+the client uses
+.SM UDP/IP
+as a transport.
+The remote program is located at Internet
+address
+.IR addr .
+If
+\fB\%addr\->sin_port\fR
+is zero, then it is set to actual port that the remote
+program is listening on (the remote
+.B portmap
+service is consulted for this information). The parameter
+.I sockp
+is a socket; if it is
+.BR \s-1RPC_ANYSOCK\s0 ,
+then this routine opens a new one and sets
+.BR sockp .
+The
+.SM UDP
+transport resends the call message in intervals of
+.B wait
+time until a response is received or until the call times
+out.
+The total time for the call to time out is specified by
+.BR clnt_call(\|) .
+.IP
+This allows the user to specify the maximum packet size for sending and receiving
+.SM UDP\s0-based
+.SM RPC
+messages.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+int
+get_myaddress(addr)
+struct sockaddr_in *addr;
+.fi
+.ft R
+.IP
+Stuff the machine's
+.SM IP
+address into
+.IR *addr ,
+without consulting the library routines that deal with
+.BR /etc/hosts .
+The port number is always set to
+.BR htons(\s-1PMAPPORT\s0) .
+Returns zero on success, non-zero on failure.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+struct pmaplist *
+pmap_getmaps(addr)
+struct sockaddr_in *addr;
+.fi
+.ft R
+.IP
+A user interface to the
+.B portmap
+service, which returns a list of the current
+.SM RPC
+program-to-port mappings
+on the host located at
+.SM IP
+address
+.IR *addr .
+This routine can return
+.SM NULL .
+The command
+.RB ` "rpcinfo \-p" '
+uses this routine.
+.br
+.if t .ne 12
+.LP
+.ft B
+.nf
+.sp .5
+u_short
+pmap_getport(addr, prognum, versnum, protocol)
+struct sockaddr_in *addr;
+u_long prognum, versnum, protocol;
+.fi
+.ft R
+.IP
+A user interface to the
+.B portmap
+service, which returns the port number
+on which waits a service that supports program number
+.IR prognum ,
+version
+.IR versnum ,
+and speaks the transport protocol associated with
+.IR protocol .
+The value of
+.I protocol
+is most likely
+.B
+.SM IPPROTO_UDP
+or
+.BR \s-1IPPROTO_TCP\s0 .
+A return value of zero means that the mapping does not exist
+or that
+the
+.SM RPC
+system failed to contact the remote
+.B portmap
+service. In the latter case, the global variable
+.B rpc_createerr(\|)
+contains the
+.SM RPC
+status.
+.br
+.if t .ne 15
+.LP
+.ft B
+.nf
+.sp .5
+enum clnt_stat
+pmap_rmtcall(addr, prognum, versnum, procnum, inproc, in, outproc, out, tout, portp)
+struct sockaddr_in *addr;
+u_long prognum, versnum, procnum;
+char *in, *out;
+xdrproc_t inproc, outproc;
+struct timeval tout;
+u_long *portp;
+.fi
+.ft R
+.IP
+A user interface to the
+.B portmap
+service, which instructs
+.B portmap
+on the host at
+.SM IP
+address
+.I *addr
+to make an
+.SM RPC
+call on your behalf to a procedure on that host.
+The parameter
+.I *portp
+will be modified to the program's port number if the
+procedure
+succeeds.
+The definitions of other parameters are discussed
+in
+.B callrpc(\|)
+and
+.BR clnt_call(\|) .
+This procedure should be used for a \(lqping\(rq and nothing
+else.
+See also
+.BR clnt_broadcast(\|) .
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+pmap_set(prognum, versnum, protocol, port)
+u_long prognum, versnum, protocol;
+u_short port;
+.fi
+.ft R
+.IP
+A user interface to the
+.B portmap
+service, which establishes a mapping between the triple
+.RI [ prognum , versnum , protocol\fR]
+and
+.I port
+on the machine's
+.B portmap
+service.
+The value of
+.I protocol
+is most likely
+.B
+.SM IPPROTO_UDP
+or
+.BR \s-1IPPROTO_TCP\s0 .
+This routine returns one if it succeeds, zero otherwise.
+Automatically done by
+.BR svc_register(\|) .
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+pmap_unset(prognum, versnum)
+u_long prognum, versnum;
+.fi
+.ft R
+.IP
+A user interface to the
+.B portmap
+service, which destroys all mapping between the triple
+.RI [ prognum , versnum , *\fR]
+and
+.B ports
+on the machine's
+.B portmap
+service.
+This routine returns one if it succeeds, zero
+otherwise.
+.br
+.if t .ne 15
+.LP
+.ft B
+.nf
+.sp .5
+registerrpc(prognum, versnum, procnum, procname, inproc, outproc)
+u_long prognum, versnum, procnum;
+char *(*procname) (\|) ;
+xdrproc_t inproc, outproc;
+.fi
+.ft R
+.IP
+Register procedure
+.I procname
+with the
+.SM RPC
+service package. If a request arrives for program
+.IR prognum ,
+version
+.IR versnum ,
+and procedure
+.IR procnum ,
+.I procname
+is called with a pointer to its parameter(s);
+.I progname
+should return a pointer to its static result(s);
+.I inproc
+is used to decode the parameters while
+.I outproc
+is used to encode the results.
+This routine returns zero if the registration succeeded, \-1
+otherwise.
+.IP
+Warning: remote procedures registered in this form
+are accessed using the
+.SM UDP/IP
+transport; see
+.B svcudp_create(\|)
+for restrictions.
+.br
+.if t .ne 5
+.LP
+.ft B
+.nf
+.sp .5
+struct rpc_createerr rpc_createerr;
+.fi
+.ft R
+.IP
+A global variable whose value is set by any
+.SM RPC
+client creation routine
+that does not succeed. Use the routine
+.B clnt_pcreateerror(\|)
+to print the reason why.
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+svc_destroy(xprt)
+\s-1SVCXPRT\s0 *
+xprt;
+.fi
+.ft R
+.IP
+A macro that destroys the
+.SM RPC
+service transport handle,
+.IR xprt .
+Destruction usually involves deallocation
+of private data structures, including
+.I xprt
+itself. Use of
+.I xprt
+is undefined after calling this routine.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+fd_set svc_fdset;
+.fi
+.ft R
+.IP
+A global variable reflecting the
+.SM RPC
+service side's
+read file descriptor bit mask; it is suitable as a template parameter
+to the
+.B select
+system call.
+This is only of interest
+if a service implementor does not call
+.BR svc_run(\|) ,
+but rather does his own asynchronous event processing.
+This variable is read-only (do not pass its address to
+.BR select !),
+yet it may change after calls to
+.B svc_getreqset(\|)
+or any creation routines.
+.br
+As well, note that if the process has descriptor limits
+which are extended beyond
+.BR FD_SETSIZE ,
+this variable will only be usable for the first
+.BR FD_SETSIZE
+descriptors.
+.br
+.if t .ne 6
+.LP
+.ft B
+.nf
+.sp .5
+int svc_fds;
+.fi
+.ft R
+.IP
+Similar to
+.BR svc_fedset(\|) ,
+but limited to 32 descriptors.
+This
+interface is obsoleted by
+.BR svc_fdset(\|) .
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+svc_freeargs(xprt, inproc, in)
+\s-1SVCXPRT\s0 *xprt;
+xdrproc_t inproc;
+char *in;
+.fi
+.ft R
+.IP
+A macro that frees any data allocated by the
+.SM RPC/XDR
+system when it decoded the arguments to a service procedure
+using
+.BR svc_getargs(\|) .
+This routine returns 1 if the results were successfully
+freed,
+and zero otherwise.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+svc_getargs(xprt, inproc, in)
+\s-1SVCXPRT\s0 *xprt;
+xdrproc_t inproc;
+char *in;
+.fi
+.ft R
+.IP
+A macro that decodes the arguments of an
+.SM RPC
+request
+associated with the
+.SM RPC
+service transport handle,
+.IR xprt .
+The parameter
+.I in
+is the address where the arguments will be placed;
+.I inproc
+is the
+.SM XDR
+routine used to decode the arguments.
+This routine returns one if decoding succeeds, and zero
+otherwise.
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+struct sockaddr_in *
+svc_getcaller(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+The approved way of getting the network address of the caller
+of a procedure associated with the
+.SM RPC
+service transport handle,
+.IR xprt .
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+svc_getreqset(rdfds)
+fd_set *rdfds;
+.fi
+.ft R
+.IP
+This routine is only of interest if a service implementor
+does not call
+.BR svc_run(\|) ,
+but instead implements custom asynchronous event processing.
+It is called when the
+.B select
+system call has determined that an
+.SM RPC
+request has arrived on some
+.SM RPC
+.B socket(s) ;
+.I rdfds
+is the resultant read file descriptor bit mask.
+The routine returns when all sockets associated with the
+value of
+.I rdfds
+have been serviced.
+.br
+.if t .ne 6
+.LP
+.ft B
+.nf
+.sp .5
+svc_getreq(rdfds)
+int rdfds;
+.fi
+.ft R
+.IP
+Similar to
+.BR svc_getreqset(\|) ,
+but limited to 32 descriptors.
+This interface is obsoleted by
+.BR svc_getreqset(\|) .
+.br
+.if t .ne 17
+.LP
+.ft B
+.nf
+.sp .5
+svc_register(xprt, prognum, versnum, dispatch, protocol)
+\s-1SVCXPRT\s0 *xprt;
+u_long prognum, versnum;
+void (*dispatch) (\|);
+u_long protocol;
+.fi
+.ft R
+.IP
+Associates
+.I prognum
+and
+.I versnum
+with the service dispatch procedure,
+.IR dispatch .
+If
+.I protocol
+is zero, the service is not registered with the
+.B portmap
+service. If
+.I protocol
+is non-zero, then a mapping of the triple
+.RI [ prognum , versnum , protocol\fR]
+to
+\fB\%xprt\->xp_port\fR
+is established with the local
+.B portmap
+service (generally
+.I protocol
+is zero,
+.B
+.SM IPPROTO_UDP
+or
+.B
+.SM IPPROTO_TCP
+).
+The procedure
+.I dispatch
+has the following form:
+.RS 1i
+.ft B
+.nf
+dispatch(request, xprt)
+struct svc_req *request;
+\s-1SVCXPRT\s0 *xprt;
+.ft R
+.fi
+.RE
+.IP
+The
+.B svc_register(\|)
+routine returns one if it succeeds, and zero otherwise.
+.br
+.if t .ne 6
+.LP
+.ft B
+.nf
+.sp .5
+svc_run(\|)
+.fi
+.ft R
+.IP
+This routine never returns.
+It waits for
+.SM RPC
+requests to arrive, and calls the appropriate service
+procedure using
+.B svc_getreq(\|)
+when one arrives.
+This procedure is usually waiting for a
+.B select(\|)
+system call to return.
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+svc_sendreply(xprt, outproc, out)
+\s-1SVCXPRT\s0 *xprt;
+xdrproc_t outproc;
+char *out;
+.fi
+.ft R
+.IP
+Called by an
+.SM RPC
+service's dispatch routine to send the results of a
+remote procedure call. The parameter
+.I xprt
+is the request's associated transport handle;
+.I outproc
+is the
+.SM XDR
+routine which is used to encode the results; and
+.I out
+is the address of the results.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+void
+svc_unregister(prognum, versnum)
+u_long prognum, versnum;
+.fi
+.ft R
+.IP
+Remove all mapping of the double
+.RI [ prognum , versnum ]
+to dispatch routines, and of the triple
+.RI [ prognum , versnum , *\fR]
+to port number.
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+void
+svcerr_auth(xprt, why)
+\s-1SVCXPRT\s0 *xprt;
+enum auth_stat why;
+.fi
+.ft R
+.IP
+Called by a service dispatch routine that refuses to perform
+a remote procedure call due to an authentication error.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+void
+svcerr_decode(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+Called by a service dispatch routine that cannot successfully
+decode its parameters.
+See also
+.BR svc_getargs(\|) .
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+void
+svcerr_noproc(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+Called by a service dispatch routine that does not implement
+the procedure number that the caller requests.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+void
+svcerr_noprog(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+Called when the desired program is not registered with the
+.SM RPC
+package.
+Service implementors usually do not need this routine.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+void
+svcerr_progvers(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+Called when the desired version of a program is not registered
+with the
+.SM RPC
+package.
+Service implementors usually do not need this routine.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+void
+svcerr_systemerr(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+Called by a service dispatch routine when it detects a system
+error
+not covered by any particular protocol.
+For example, if a service can no longer allocate storage,
+it may call this routine.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+void
+svcerr_weakauth(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+Called by a service dispatch routine that refuses to perform
+a remote procedure call due to insufficient
+authentication parameters. The routine calls
+.BR "svcerr_auth(xprt, \s-1AUTH_TOOWEAK\s0)" .
+.br
+.if t .ne 11
+.LP
+.ft B
+.nf
+.sp .5
+\s-1SVCXPRT\s0 *
+svcraw_create(\|)
+.fi
+.ft R
+.IP
+This routine creates a toy
+.SM RPC
+service transport, to which it returns a pointer. The
+transport
+is really a buffer within the process's address space,
+so the corresponding
+.SM RPC
+client should live in the same
+address space;
+see
+.BR clntraw_create(\|) .
+This routine allows simulation of
+.SM RPC
+and acquisition of
+.SM RPC
+overheads (such as round trip times), without any kernel
+interference.
+This routine returns
+.SM NULL
+if it fails.
+.br
+.if t .ne 11
+.LP
+.ft B
+.nf
+.sp .5
+\s-1SVCXPRT\s0 *
+svctcp_create(sock, send_buf_size, recv_buf_size)
+int sock;
+u_int send_buf_size, recv_buf_size;
+.fi
+.ft R
+.IP
+This routine creates a
+.SM TCP/IP\s0-based
+.SM RPC
+service transport, to which it returns a pointer.
+The transport is associated with the socket
+.IR sock ,
+which may be
+.BR \s-1RPC_ANYSOCK\s0 ,
+in which case a new socket is created.
+If the socket is not bound to a local
+.SM TCP
+port, then this routine binds it to an arbitrary port. Upon
+completion,
+\fB\%xprt\->xp_sock\fR
+is the transport's socket descriptor, and
+\fB\%xprt\->xp_port\fR
+is the transport's port number.
+This routine returns
+.SM NULL
+if it fails.
+Since
+.SM TCP\s0-based
+.SM RPC
+uses buffered
+.SM I/O ,
+users may specify the size of buffers; values of zero
+choose suitable defaults.
+.br
+.if t .ne 11
+.LP
+.ft B
+.nf
+.sp .5
+\s-1SVCXPRT\s0 *
+svcfd_create(fd, sendsize, recvsize)
+int fd;
+u_int sendsize;
+u_int recvsize;
+.fi
+.ft R
+.IP
+Create a service on top of any open descriptor.
+Typically,
+this
+descriptor is a connected socket for a stream protocol such
+as
+.SM TCP\s0.
+.I sendsize
+and
+.I recvsize
+indicate sizes for the send and receive buffers. If they are
+zero, a reasonable default is chosen.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+\s-1SVCXPRT\s0 *
+svcudp_bufcreate(sock, sendsize, recosize)
+int sock;
+.fi
+.ft R
+.IP
+This routine creates a
+.SM UDP/IP\s0-based
+.SM RPC
+service transport, to which it returns a pointer.
+The transport is associated with the socket
+.IR sock ,
+which may be
+.B \s-1RPC_ANYSOCK\s0 ,
+in which case a new socket is created.
+If the socket is not bound to a local
+.SM UDP
+port, then this routine binds it to an arbitrary port.
+Upon
+completion,
+\fB\%xprt\->xp_sock\fR
+is the transport's socket descriptor, and
+\fB\%xprt\->xp_port\fR
+is the transport's port number.
+This routine returns
+.SM NULL
+if it fails.
+.IP
+This allows the user to specify the maximum packet size for sending and
+receiving
+.SM UDP\s0-based
+.SM RPC messages.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_accepted_reply(xdrs, ar)
+\s-1XDR\s0 *xdrs;
+struct accepted_reply *ar;
+.fi
+.ft R
+.IP
+Used for encoding
+.SM RPC
+reply messages.
+This routine is useful for users who
+wish to generate
+\s-1RPC\s0-style
+messages without using the
+.SM RPC
+package.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_authunix_parms(xdrs, aupp)
+\s-1XDR\s0 *xdrs;
+struct authunix_parms *aupp;
+.fi
+.ft R
+.IP
+Used for describing
+.SM UNIX
+credentials.
+This routine is useful for users
+who wish to generate these credentials without using the
+.SM RPC
+authentication package.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+void
+xdr_callhdr(xdrs, chdr)
+\s-1XDR\s0 *xdrs;
+struct rpc_msg *chdr;
+.fi
+.ft R
+.IP
+Used for describing
+.SM RPC
+call header messages.
+This routine is useful for users who wish to generate
+.SM RPC\s0-style
+messages without using the
+.SM RPC
+package.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_callmsg(xdrs, cmsg)
+\s-1XDR\s0 *xdrs;
+struct rpc_msg *cmsg;
+.fi
+.ft R
+.IP
+Used for describing
+.SM RPC
+call messages.
+This routine is useful for users who wish to generate
+.SM RPC\s0-style
+messages without using the
+.SM RPC
+package.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_opaque_auth(xdrs, ap)
+\s-1XDR\s0 *xdrs;
+struct opaque_auth *ap;
+.fi
+.ft R
+.IP
+Used for describing
+.SM RPC
+authentication information messages.
+This routine is useful for users who wish to generate
+.SM RPC\s0-style
+messages without using the
+.SM RPC
+package.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_pmap(xdrs, regs)
+\s-1XDR\s0 *xdrs;
+struct pmap *regs;
+.fi
+.ft R
+.IP
+Used for describing parameters to various
+.B portmap
+procedures, externally.
+This routine is useful for users who wish to generate
+these parameters without using the
+.B pmap
+interface.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_pmaplist(xdrs, rp)
+\s-1XDR\s0 *xdrs;
+struct pmaplist **rp;
+.fi
+.ft R
+.IP
+Used for describing a list of port mappings, externally.
+This routine is useful for users who wish to generate
+these parameters without using the
+.B pmap
+interface.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_rejected_reply(xdrs, rr)
+\s-1XDR\s0 *xdrs;
+struct rejected_reply *rr;
+.fi
+.ft R
+.IP
+Used for describing
+.SM RPC
+reply messages.
+This routine is useful for users who wish to generate
+.SM RPC\s0-style
+messages without using the
+.SM RPC
+package.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+xdr_replymsg(xdrs, rmsg)
+\s-1XDR\s0 *xdrs;
+struct rpc_msg *rmsg;
+.fi
+.ft R
+.IP
+Used for describing
+.SM RPC
+reply messages.
+This routine is useful for users who wish to generate
+.SM RPC
+style messages without using the
+.SM RPC
+package.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+void
+xprt_register(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+After
+.SM RPC
+service transport handles are created,
+they should register themselves with the
+.SM RPC
+service package.
+This routine modifies the global variable
+.BR svc_fds(\|) .
+Service implementors usually do not need this routine.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+void
+xprt_unregister(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+Before an
+.SM RPC
+service transport handle is destroyed,
+it should unregister itself with the
+.SM RPC
+service package.
+This routine modifies the global variable
+.BR svc_fds(\|) .
+Service implementors usually do not need this routine.
+.SH SEE ALSO
+.BR rpc_secure (3),
+.BR xdr (3)
+.br
+The following manuals:
+.RS
+.ft I
+Remote Procedure Calls: Protocol Specification
+.br
+Remote Procedure Call Programming Guide
+.br
+rpcgen Programming Guide
+.br
+.ft R
+.RE
+.IR "\s-1RPC\s0: Remote Procedure Call Protocol Specification" ,
+.SM RFC1050, Sun Microsystems, Inc.,
+.SM USC-ISI\s0.
+
diff --git a/cpukit/librpc/src/rpc/rpc.5 b/cpukit/librpc/src/rpc/rpc.5
new file mode 100644
index 0000000000..36f895dbf2
--- /dev/null
+++ b/cpukit/librpc/src/rpc/rpc.5
@@ -0,0 +1,35 @@
+.\" $FreeBSD: src/lib/libc/rpc/rpc.5,v 1.6 1999/08/28 00:00:44 peter Exp $
+.\" @(#)rpc.5 2.2 88/08/03 4.0 RPCSRC; from 1.4 87/11/27 SMI;
+.Dd September 26, 1985
+.Dt RPC 5
+.Sh NAME
+.Nm rpc
+.Nd rpc program number data base
+.Sh SYNOPSIS
+/etc/rpc
+.Sh DESCRIPTION
+The
+.Pa /etc/rpc
+file contains user readable names that
+can be used in place of rpc program numbers.
+Each line has the following information:
+.Pp
+.Bl -bullet -compact
+.It
+name of server for the rpc program
+.It
+rpc program number
+.It
+aliases
+.El
+.Pp
+Items are separated by any number of blanks and/or
+tab characters.
+A ``#'' indicates the beginning of a comment; characters up to the end of
+the line are not interpreted by routines which search the file.
+.Sh FILES
+.Bl -tag -compact -width /etc/rpc
+.Pa /etc/rpc
+.El
+.Sh "SEE ALSO"
+.Xr getrpcent 3
diff --git a/cpukit/librpc/src/rpc/rpc_callmsg.c b/cpukit/librpc/src/rpc/rpc_callmsg.c
new file mode 100644
index 0000000000..495ddca819
--- /dev/null
+++ b/cpukit/librpc/src/rpc/rpc_callmsg.c
@@ -0,0 +1,192 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)rpc_callmsg.c 1.4 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)rpc_callmsg.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/rpc/rpc_callmsg.c,v 1.9 1999/08/28 00:00:45 peter Exp $";
+#endif
+
+/*
+ * rpc_callmsg.c
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ */
+
+#include <sys/param.h>
+#include <stdlib.h>
+#include <string.h>
+#include <rpc/rpc.h>
+
+/*
+ * XDR a call message
+ */
+bool_t
+xdr_callmsg(xdrs, cmsg)
+ register XDR *xdrs;
+ register struct rpc_msg *cmsg;
+{
+ register int32_t *buf;
+ register struct opaque_auth *oa;
+
+ if (xdrs->x_op == XDR_ENCODE) {
+ if (cmsg->rm_call.cb_cred.oa_length > MAX_AUTH_BYTES) {
+ return (FALSE);
+ }
+ if (cmsg->rm_call.cb_verf.oa_length > MAX_AUTH_BYTES) {
+ return (FALSE);
+ }
+ buf = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT
+ + RNDUP(cmsg->rm_call.cb_cred.oa_length)
+ + 2 * BYTES_PER_XDR_UNIT
+ + RNDUP(cmsg->rm_call.cb_verf.oa_length));
+ if (buf != NULL) {
+ IXDR_PUT_LONG(buf, cmsg->rm_xid);
+ IXDR_PUT_ENUM(buf, cmsg->rm_direction);
+ if (cmsg->rm_direction != CALL) {
+ return (FALSE);
+ }
+ IXDR_PUT_LONG(buf, cmsg->rm_call.cb_rpcvers);
+ if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) {
+ return (FALSE);
+ }
+ IXDR_PUT_LONG(buf, cmsg->rm_call.cb_prog);
+ IXDR_PUT_LONG(buf, cmsg->rm_call.cb_vers);
+ IXDR_PUT_LONG(buf, cmsg->rm_call.cb_proc);
+ oa = &cmsg->rm_call.cb_cred;
+ IXDR_PUT_ENUM(buf, oa->oa_flavor);
+ IXDR_PUT_LONG(buf, oa->oa_length);
+ if (oa->oa_length) {
+ memcpy((caddr_t)buf, oa->oa_base, oa->oa_length);
+ buf += RNDUP(oa->oa_length) / sizeof (int32_t);
+ }
+ oa = &cmsg->rm_call.cb_verf;
+ IXDR_PUT_ENUM(buf, oa->oa_flavor);
+ IXDR_PUT_LONG(buf, oa->oa_length);
+ if (oa->oa_length) {
+ memcpy((caddr_t)buf, oa->oa_base, oa->oa_length);
+ /* no real need....
+ buf += RNDUP(oa->oa_length) / sizeof (int32_t);
+ */
+ }
+ return (TRUE);
+ }
+ }
+ if (xdrs->x_op == XDR_DECODE) {
+ buf = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT);
+ if (buf != NULL) {
+ cmsg->rm_xid = IXDR_GET_LONG(buf);
+ cmsg->rm_direction = IXDR_GET_ENUM(buf, enum msg_type);
+ if (cmsg->rm_direction != CALL) {
+ return (FALSE);
+ }
+ cmsg->rm_call.cb_rpcvers = IXDR_GET_LONG(buf);
+ if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) {
+ return (FALSE);
+ }
+ cmsg->rm_call.cb_prog = IXDR_GET_LONG(buf);
+ cmsg->rm_call.cb_vers = IXDR_GET_LONG(buf);
+ cmsg->rm_call.cb_proc = IXDR_GET_LONG(buf);
+ oa = &cmsg->rm_call.cb_cred;
+ oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t);
+ oa->oa_length = IXDR_GET_LONG(buf);
+ if (oa->oa_length) {
+ if (oa->oa_length > MAX_AUTH_BYTES) {
+ return (FALSE);
+ }
+ if (oa->oa_base == NULL) {
+ oa->oa_base = (caddr_t)
+ mem_alloc(oa->oa_length);
+ }
+ buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length));
+ if (buf == NULL) {
+ if (xdr_opaque(xdrs, oa->oa_base,
+ oa->oa_length) == FALSE) {
+ return (FALSE);
+ }
+ } else {
+ memcpy(oa->oa_base, (caddr_t)buf,
+ oa->oa_length);
+ /* no real need....
+ buf += RNDUP(oa->oa_length) /
+ sizeof (int32_t);
+ */
+ }
+ }
+ oa = &cmsg->rm_call.cb_verf;
+ buf = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT);
+ if (buf == NULL) {
+ if (xdr_enum(xdrs, &oa->oa_flavor) == FALSE ||
+ xdr_u_int(xdrs, &oa->oa_length) == FALSE) {
+ return (FALSE);
+ }
+ } else {
+ oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t);
+ oa->oa_length = IXDR_GET_LONG(buf);
+ }
+ if (oa->oa_length) {
+ if (oa->oa_length > MAX_AUTH_BYTES) {
+ return (FALSE);
+ }
+ if (oa->oa_base == NULL) {
+ oa->oa_base = (caddr_t)
+ mem_alloc(oa->oa_length);
+ }
+ buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length));
+ if (buf == NULL) {
+ if (xdr_opaque(xdrs, oa->oa_base,
+ oa->oa_length) == FALSE) {
+ return (FALSE);
+ }
+ } else {
+ memcpy(oa->oa_base, (caddr_t)buf,
+ oa->oa_length);
+ /* no real need...
+ buf += RNDUP(oa->oa_length) /
+ sizeof (int32_t);
+ */
+ }
+ }
+ return (TRUE);
+ }
+ }
+ if (
+ xdr_u_int32_t(xdrs, &(cmsg->rm_xid)) &&
+ xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) &&
+ (cmsg->rm_direction == CALL) &&
+ xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
+ (cmsg->rm_call.cb_rpcvers == RPC_MSG_VERSION) &&
+ xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_prog)) &&
+ xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_vers)) &&
+ xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_proc)) &&
+ xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_cred)) )
+ return (xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_verf)));
+ return (FALSE);
+}
diff --git a/cpukit/librpc/src/rpc/rpc_commondata.c b/cpukit/librpc/src/rpc/rpc_commondata.c
new file mode 100644
index 0000000000..bbe6003337
--- /dev/null
+++ b/cpukit/librpc/src/rpc/rpc_commondata.c
@@ -0,0 +1,41 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)rpc_commondata.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/rpc/rpc_commondata.c,v 1.7 1999/08/28 00:00:45 peter Exp $";
+#endif
+
+#include <rpc/rpc.h>
+/*
+ * This file should only contain common data (global data) that is exported
+ * by public interfaces
+ */
+struct opaque_auth _null_auth;
+struct rpc_createerr rpc_createerr;
diff --git a/cpukit/librpc/src/rpc/rpc_dtablesize.c b/cpukit/librpc/src/rpc/rpc_dtablesize.c
new file mode 100644
index 0000000000..e07c0b6568
--- /dev/null
+++ b/cpukit/librpc/src/rpc/rpc_dtablesize.c
@@ -0,0 +1,61 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)rpc_dtablesize.c 1.2 87/08/11 Copyr 1987 Sun Micro";*/
+/*static char *sccsid = "from: @(#)rpc_dtablesize.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/rpc/rpc_dtablesize.c,v 1.10 1999/08/28 00:00:45 peter Exp $";
+#endif
+
+#include <sys/types.h>
+#include <unistd.h>
+
+/*
+ * Cache the result of getdtablesize(), so we don't have to do an
+ * expensive system call every time.
+ */
+/*
+ * XXX In FreeBSD 2.x, you can have the maximum number of open file
+ * descriptors be greater than FD_SETSIZE (which us 256 by default).
+ *
+ * Since old programs tend to use this call to determine the first arg
+ * for select(), having this return > FD_SETSIZE is a Bad Idea(TM)!
+ */
+int
+_rpc_dtablesize(void)
+{
+ static int size;
+
+ if (size == 0) {
+ size = getdtablesize();
+ if (size > FD_SETSIZE)
+ size = FD_SETSIZE;
+ }
+ return (size);
+}
diff --git a/cpukit/librpc/src/rpc/rpc_prot.c b/cpukit/librpc/src/rpc/rpc_prot.c
new file mode 100644
index 0000000000..14a2524c70
--- /dev/null
+++ b/cpukit/librpc/src/rpc/rpc_prot.c
@@ -0,0 +1,297 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)rpc_prot.c 1.36 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)rpc_prot.c 2.3 88/08/07 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/rpc/rpc_prot.c,v 1.8 1999/08/28 00:00:46 peter Exp $";
+#endif
+
+/*
+ * rpc_prot.c
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * This set of routines implements the rpc message definition,
+ * its serializer and some common rpc utility routines.
+ * The routines are meant for various implementations of rpc -
+ * they are NOT for the rpc client or rpc service implementations!
+ * Because authentication stuff is easy and is part of rpc, the opaque
+ * routines are also in this program.
+ */
+
+#include <sys/param.h>
+
+#include <rpc/rpc.h>
+
+/* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */
+
+struct opaque_auth _null_auth;
+
+/*
+ * XDR an opaque authentication struct
+ * (see auth.h)
+ */
+bool_t
+xdr_opaque_auth(xdrs, ap)
+ register XDR *xdrs;
+ register struct opaque_auth *ap;
+{
+
+ if (xdr_enum(xdrs, &(ap->oa_flavor)))
+ return (xdr_bytes(xdrs, &ap->oa_base,
+ &ap->oa_length, MAX_AUTH_BYTES));
+ return (FALSE);
+}
+
+/*
+ * XDR a DES block
+ */
+bool_t
+xdr_des_block(xdrs, blkp)
+ register XDR *xdrs;
+ register des_block *blkp;
+{
+ return (xdr_opaque(xdrs, (caddr_t)blkp, sizeof(des_block)));
+}
+
+/* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */
+
+/*
+ * XDR the MSG_ACCEPTED part of a reply message union
+ */
+bool_t
+xdr_accepted_reply(xdrs, ar)
+ register XDR *xdrs;
+ register struct accepted_reply *ar;
+{
+
+ /* personalized union, rather than calling xdr_union */
+ if (! xdr_opaque_auth(xdrs, &(ar->ar_verf)))
+ return (FALSE);
+ if (! xdr_enum(xdrs, (enum_t *)&(ar->ar_stat)))
+ return (FALSE);
+ switch (ar->ar_stat) {
+
+ case SUCCESS:
+ return ((*(ar->ar_results.proc))(xdrs, ar->ar_results.where));
+
+ case PROG_MISMATCH:
+ if (! xdr_u_int32_t(xdrs, &(ar->ar_vers.low)))
+ return (FALSE);
+ return (xdr_u_int32_t(xdrs, &(ar->ar_vers.high)));
+ default:
+ break;
+ }
+ return (TRUE); /* TRUE => open ended set of problems */
+}
+
+/*
+ * XDR the MSG_DENIED part of a reply message union
+ */
+bool_t
+xdr_rejected_reply(xdrs, rr)
+ register XDR *xdrs;
+ register struct rejected_reply *rr;
+{
+
+ /* personalized union, rather than calling xdr_union */
+ if (! xdr_enum(xdrs, (enum_t *)&(rr->rj_stat)))
+ return (FALSE);
+ switch (rr->rj_stat) {
+
+ case RPC_MISMATCH:
+ if (! xdr_u_int32_t(xdrs, &(rr->rj_vers.low)))
+ return (FALSE);
+ return (xdr_u_int32_t(xdrs, &(rr->rj_vers.high)));
+
+ case AUTH_ERROR:
+ return (xdr_enum(xdrs, (enum_t *)&(rr->rj_why)));
+ }
+ return (FALSE);
+}
+
+static struct xdr_discrim reply_dscrm[3] = {
+ { (int)MSG_ACCEPTED, xdr_accepted_reply },
+ { (int)MSG_DENIED, xdr_rejected_reply },
+ { __dontcare__, NULL_xdrproc_t } };
+
+/*
+ * XDR a reply message
+ */
+bool_t
+xdr_replymsg(xdrs, rmsg)
+ register XDR *xdrs;
+ register struct rpc_msg *rmsg;
+{
+ if (
+ xdr_u_int32_t(xdrs, &(rmsg->rm_xid)) &&
+ xdr_enum(xdrs, (enum_t *)&(rmsg->rm_direction)) &&
+ (rmsg->rm_direction == REPLY) )
+ return (xdr_union(xdrs, (enum_t *)&(rmsg->rm_reply.rp_stat),
+ (caddr_t)&(rmsg->rm_reply.ru), reply_dscrm, NULL_xdrproc_t));
+ return (FALSE);
+}
+
+
+/*
+ * Serializes the "static part" of a call message header.
+ * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers.
+ * The rm_xid is not really static, but the user can easily munge on the fly.
+ */
+bool_t
+xdr_callhdr(xdrs, cmsg)
+ register XDR *xdrs;
+ register struct rpc_msg *cmsg;
+{
+
+ cmsg->rm_direction = CALL;
+ cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION;
+ if (
+ (xdrs->x_op == XDR_ENCODE) &&
+ xdr_u_int32_t(xdrs, &(cmsg->rm_xid)) &&
+ xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) &&
+ xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
+ xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_prog)) )
+ return (xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_vers)));
+ return (FALSE);
+}
+
+/* ************************** Client utility routine ************* */
+
+static void
+accepted(acpt_stat, error)
+ register enum accept_stat acpt_stat;
+ register struct rpc_err *error;
+{
+
+ switch (acpt_stat) {
+
+ case PROG_UNAVAIL:
+ error->re_status = RPC_PROGUNAVAIL;
+ return;
+
+ case PROG_MISMATCH:
+ error->re_status = RPC_PROGVERSMISMATCH;
+ return;
+
+ case PROC_UNAVAIL:
+ error->re_status = RPC_PROCUNAVAIL;
+ return;
+
+ case GARBAGE_ARGS:
+ error->re_status = RPC_CANTDECODEARGS;
+ return;
+
+ case SYSTEM_ERR:
+ error->re_status = RPC_SYSTEMERROR;
+ return;
+
+ case SUCCESS:
+ error->re_status = RPC_SUCCESS;
+ return;
+ }
+ /* something's wrong, but we don't know what ... */
+ error->re_status = RPC_FAILED;
+ error->re_lb.s1 = (long)MSG_ACCEPTED;
+ error->re_lb.s2 = (long)acpt_stat;
+}
+
+static void
+rejected(rjct_stat, error)
+ register enum reject_stat rjct_stat;
+ register struct rpc_err *error;
+{
+
+ switch (rjct_stat) {
+
+ case RPC_VERSMISMATCH:
+ error->re_status = RPC_VERSMISMATCH;
+ return;
+
+ case AUTH_ERROR:
+ error->re_status = RPC_AUTHERROR;
+ return;
+ default:
+ break;
+ }
+ /* something's wrong, but we don't know what ... */
+ error->re_status = RPC_FAILED;
+ error->re_lb.s1 = (long)MSG_DENIED;
+ error->re_lb.s2 = (long)rjct_stat;
+}
+
+/*
+ * given a reply message, fills in the error
+ */
+void
+_seterr_reply(msg, error)
+ register struct rpc_msg *msg;
+ register struct rpc_err *error;
+{
+
+ /* optimized for normal, SUCCESSful case */
+ switch (msg->rm_reply.rp_stat) {
+
+ case MSG_ACCEPTED:
+ if (msg->acpted_rply.ar_stat == SUCCESS) {
+ error->re_status = RPC_SUCCESS;
+ return;
+ };
+ accepted(msg->acpted_rply.ar_stat, error);
+ break;
+
+ case MSG_DENIED:
+ rejected(msg->rjcted_rply.rj_stat, error);
+ break;
+
+ default:
+ error->re_status = RPC_FAILED;
+ error->re_lb.s1 = (long)(msg->rm_reply.rp_stat);
+ break;
+ }
+ switch (error->re_status) {
+
+ case RPC_VERSMISMATCH:
+ error->re_vers.low = msg->rjcted_rply.rj_vers.low;
+ error->re_vers.high = msg->rjcted_rply.rj_vers.high;
+ break;
+
+ case RPC_AUTHERROR:
+ error->re_why = msg->rjcted_rply.rj_why;
+ break;
+
+ case RPC_PROGVERSMISMATCH:
+ error->re_vers.low = msg->acpted_rply.ar_vers.low;
+ error->re_vers.high = msg->acpted_rply.ar_vers.high;
+ break;
+ default:
+ break;
+ }
+}
diff --git a/cpukit/librpc/src/rpc/rpc_secure.3 b/cpukit/librpc/src/rpc/rpc_secure.3
new file mode 100644
index 0000000000..4efd9b8614
--- /dev/null
+++ b/cpukit/librpc/src/rpc/rpc_secure.3
@@ -0,0 +1,254 @@
+.\" @(#)rpc_secure.3n 2.1 88/08/08 4.0 RPCSRC; from 1.19 88/06/24 SMI
+.\" $FreeBSD: src/lib/libc/rpc/rpc_secure.3,v 1.6 2000/03/02 09:13:48 sheldonh Exp $
+.\"
+.Dd February 16, 1988
+.Dt RPC 3
+.Sh NAME
+.Nm rpc_secure
+.Nd library routines for secure remote procedure calls
+.Sh SYNOPSIS
+.Fd #include <rpc/rpc.h>
+.Ft AUTH *
+.Fo authdes_create
+.Fa "char *name"
+.Fa "unsigned window"
+.Fa "struct sockaddr *addr"
+.Fa "des_block *ckey"
+.Fc
+.Ft int
+.Fn authdes_getucred "struct authdes_cred *adc" "uid_t *uid" "gid_t *gid" "int *grouplen" "gid_t *groups"
+.Ft int
+.Fn getnetname "char *name"
+.Ft int
+.Fn host2netname "char *name" "char *host" "char *domain"
+.Ft int
+.Fn key_decryptsession "const char *remotename" "des_block *deskey"
+.Ft int
+.Fn key_encryptsession "const char *remotename" "des_block *deskey"
+.Ft int
+.Fn key_gendes "des_block *deskey"
+.Ft int
+.Fn key_setsecret "const char *key"
+.Ft int
+.Fn netname2host "char *name" "char *host" "int hostlen"
+.Ft int
+.Fn netname2user "char *name" "uid_t *uidp" "gid_t *gidp" "int *gidlenp" "gid_t *gidlist"
+.Ft int
+.Fn user2netname "char *name" "uid_t uid" "char *domain"
+.Sh DESCRIPTION
+These routines are part of the
+.Tn RPC
+library. They implement
+.Tn DES
+Authentication. See
+.Xr rpc 3
+for further details about
+.Tn RPC .
+.Pp
+The
+.Fn authdes_create
+is the first of two routines which interface to the
+.Tn RPC
+secure authentication system, known as
+.Tn DES
+authentication.
+The second is
+.Fn authdes_getucred ,
+below.
+.Pp
+Note: the keyserver daemon
+.Xr keyserv 8
+must be running for the
+.Tn DES
+authentication system to work.
+.Pp
+.Fn Authdes_create ,
+used on the client side, returns an authentication handle that
+will enable the use of the secure authentication system.
+The first parameter
+.Fa name
+is the network name, or
+.Fa netname ,
+of the owner of the server process.
+This field usually
+represents a
+.Fa hostname
+derived from the utility routine
+.Fn host2netname ,
+but could also represent a user name using
+.Fn user2netname .
+The second field is window on the validity of
+the client credential, given in seconds. A small
+window is more secure than a large one, but choosing
+too small of a window will increase the frequency of
+resynchronizations because of clock drift.
+The third
+parameter
+.Fa addr
+is optional. If it is
+.Dv NULL ,
+then the authentication system will assume
+that the local clock is always in sync with the server's
+clock, and will not attempt resynchronizations.
+If an address
+is supplied, however, then the system will use the address
+for consulting the remote time service whenever
+resynchronization
+is required.
+This parameter is usually the
+address of the
+.Tn RPC
+server itself.
+The final parameter
+.Fa ckey
+is also optional. If it is
+.Dv NULL ,
+then the authentication system will
+generate a random
+.Tn DES
+key to be used for the encryption of credentials.
+If it is supplied, however, then it will be used instead.
+.Pp
+.Fn Authdes_getucred ,
+the second of the two
+.Tn DES
+authentication routines,
+is used on the server side for converting a
+.Tn DES
+credential, which is
+operating system independent, into a
+.Ux
+credential.
+This routine differs from utility routine
+.Fn netname2user
+in that
+.Fn authdes_getucred
+pulls its information from a cache, and does not have to do a
+Yellow Pages lookup every time it is called to get its information.
+.Pp
+.Fn Getnetname
+installs the unique, operating-system independent netname of
+the
+caller in the fixed-length array
+.Fa name .
+Returns
+.Dv TRUE
+if it succeeds and
+.Dv FALSE
+if it fails.
+.Pp
+.Fn Host2netname
+converts from a domain-specific hostname to an
+operating-system independent netname.
+Returns
+.Dv TRUE
+if it succeeds and
+.Dv FALSE
+if it fails.
+Inverse of
+.Fn netname2host .
+.Pp
+.Fn Key_decryptsession
+is an interface to the keyserver daemon, which is associated
+with
+.Tn RPC Ns 's
+secure authentication system (
+.Tn DES
+authentication).
+User programs rarely need to call it, or its associated routines
+.Fn key_encryptsession ,
+.Fn key_gendes
+and
+.Fn key_setsecret .
+System commands such as
+.Xr login 1
+and the
+.Tn RPC
+library are the main clients of these four routines.
+.Pp
+.Fn Key_decryptsession
+takes a server netname and a
+.Tn DES
+key, and decrypts the key by
+using the the public key of the the server and the secret key
+associated with the effective uid of the calling process. It
+is the inverse of
+.Fn key_encryptsession .
+.Pp
+.Fn Key_encryptsession
+is a keyserver interface routine.
+It
+takes a server netname and a des key, and encrypts
+it using the public key of the the server and the secret key
+associated with the effective uid of the calling process. It
+is the inverse of
+.Fn key_decryptsession .
+.Pp
+.Fn Key_gendes
+is a keyserver interface routine.
+It
+is used to ask the keyserver for a secure conversation key.
+Choosing one
+.Qq random
+is usually not good enough,
+because
+the common ways of choosing random numbers, such as using the
+current time, are very easy to guess.
+.Pp
+.Fn Key_setsecret
+is a keyserver interface routine.
+It is used to set the key for
+the effective
+.Fa uid
+of the calling process.
+.Pp
+.Fn Netname2host
+converts from an operating-system independent netname to a
+domain-specific hostname.
+Returns
+.Dv TRUE
+if it succeeds and
+.Dv FALSE
+if it fails. Inverse of
+.Fn host2netname .
+.Pp
+.Fn Netname2user
+converts from an operating-system independent netname to a
+domain-specific user ID.
+Returns
+.Dv TRUE
+if it succeeds and
+.Dv FALSE
+if it fails.
+Inverse of
+.Fn user2netname .
+.Pp
+.Fn User2netname
+converts from a domain-specific username to an operating-system
+independent netname.
+Returns
+.Dv TRUE
+if it succeeds and
+.Dv FALSE
+if it fails.
+Inverse of
+.Fn netname2user .
+.Sh SEE ALSO
+.Xr rpc 3 ,
+.Xr xdr 3 ,
+.Xr keyserv 8
+.Pp
+The following manuals:
+.Rs
+.%B Remote Procedure Calls: Protocol Specification
+.Re
+.Rs
+.%B Remote Procedure Call Programming Guide
+.Re
+.Rs
+.%B Rpcgen Programming Guide
+.Re
+.Rs
+.%B RPC: Remote Procedure Call Protocol Specification
+.%O RFC1050, Sun Microsystems Inc., USC-ISI
+.Re
diff --git a/cpukit/librpc/src/rpc/rpcdname.c b/cpukit/librpc/src/rpc/rpcdname.c
new file mode 100644
index 0000000000..f31ded00c7
--- /dev/null
+++ b/cpukit/librpc/src/rpc/rpcdname.c
@@ -0,0 +1,80 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)rpcdname.c 1.7 91/03/11 Copyr 1989 Sun Micro";
+#endif
+
+/*
+ * rpcdname.c
+ * Gets the default domain name
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <rpc/rpc.h>
+
+int getdomainname(char *, size_t);
+
+#define default_domain ((char *)(rtems_rpc_task_variables)->rpcdname_default_domain)
+
+static char *
+get_default_domain()
+{
+ char temp[256];
+
+ if (default_domain)
+ return (default_domain);
+ if (getdomainname(temp, sizeof(temp)) < 0)
+ return (0);
+ if ((int) strlen(temp) > 0) {
+ default_domain = (char *)malloc((strlen(temp)+(unsigned)1));
+ if (default_domain == 0)
+ return (0);
+ (void) strcpy(default_domain, temp);
+ return (default_domain);
+ }
+ return (0);
+}
+
+/*
+ * This is a wrapper for the system call getdomainname which returns a
+ * ypclnt.h error code in the failure case. It also checks to see that
+ * the domain name is non-null, knowing that the null string is going to
+ * get rejected elsewhere in the NIS client package.
+ */
+int
+_rpc_get_default_domain(domain)
+ char **domain;
+{
+ if ((*domain = get_default_domain()) != 0)
+ return (0);
+ return (-1);
+}
diff --git a/cpukit/librpc/src/rpc/rstat.1 b/cpukit/librpc/src/rpc/rstat.1
new file mode 100644
index 0000000000..6cc47c26c8
--- /dev/null
+++ b/cpukit/librpc/src/rpc/rstat.1
@@ -0,0 +1,58 @@
+.\" $FreeBSD: src/lib/libc/rpc/rstat.1,v 1.5 1999/08/28 00:00:46 peter Exp $
+.\" @(#)rstat.1 2.1 88/08/03 4.0 RPCSRC
+.TH RSTAT 1 "3 August 1988"
+.SH NAME
+rstat \- remote status display
+.SH SYNOPSIS
+.B rstat
+.B host
+.SH DESCRIPTION
+.LP
+.B rstat
+displays a summary of the current system status of a particular
+.BR host .
+The output shows the current time of day, how long the system has
+been up,
+and the load averages.
+The load average numbers give the number of jobs in the run queue
+averaged over 1, 5 and 15 minutes.
+.PP
+The
+.B rstat_svc(8)
+daemon must be running on the remote host for this command to
+work.
+.B rstat
+uses an RPC protocol defined in /usr/include/rpcsvc/rstat.x.
+.SH EXAMPLE
+.RS
+.ft B
+.nf
+example% rstat otherhost
+7:36am up 6 days, 16:45, load average: 0.20, 0.23, 0.18
+example%
+.ft R
+.fi
+.RE
+.SH DIAGNOSTICS
+.LP
+rstat: RPC: Program not registered
+.IP
+The
+.B rstat_svc
+daemon has not been started on the remote host.
+.LP
+rstat: RPC: Timed out
+.IP
+A communication error occurred. Either the network is
+excessively congested, or the
+.B rstat_svc
+daemon has terminated on the remote host.
+.LP
+rstat: RPC: Port mapper failure - RPC: Timed out
+.IP
+The remote host is not running the portmapper (see
+.BR portmap(8) ),
+and cannot accommodate any RPC-based services. The host may be down.
+.SH "SEE ALSO"
+.BR portmap (8),
+.BR rstat_svc (8)
diff --git a/cpukit/librpc/src/rpc/rstat_svc.8 b/cpukit/librpc/src/rpc/rstat_svc.8
new file mode 100644
index 0000000000..e2eae8be3d
--- /dev/null
+++ b/cpukit/librpc/src/rpc/rstat_svc.8
@@ -0,0 +1,22 @@
+.\" $FreeBSD: src/lib/libc/rpc/rstat_svc.8,v 1.5 1999/08/28 00:00:47 peter Exp $
+.\" @(#)rstat_svc.8c 2.2 88/08/03 4.0 RPCSRC; from 1.10 87/09/09 SMI
+.TH RSTAT_SVC 8 "24 November 1987"
+.SH NAME
+rstat_svc \- kernel statistics server
+.SH SYNOPSIS
+.B /etc/rstat_svc
+.SH DESCRIPTION
+.LP
+.B rstat_svc
+is a server which returns performance statistics
+obtained from the kernel.
+These statistics are graphically displayed by the Sun Microsystems program,
+.BR perfmeter (1).
+The
+.B rstat_svc
+daemon is normally invoked at boot time through /etc/rc.local.
+.PP
+.B rstat_svc
+uses an RPC protocol defined in /usr/include/rpcsvc/rstat.x.
+.\" .SH "SEE ALSO"
+.\" .BR rstat (1),
diff --git a/cpukit/librpc/src/rpc/rtems_portmapper.c b/cpukit/librpc/src/rpc/rtems_portmapper.c
new file mode 100644
index 0000000000..c8be0b3188
--- /dev/null
+++ b/cpukit/librpc/src/rpc/rtems_portmapper.c
@@ -0,0 +1,489 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <malloc.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+#include <sys/signal.h>
+
+static void reg_service();
+static void callit();
+static struct pmaplist *pmaplist;
+static int debugging = 0;
+
+#include <rtems.h>
+#define fork() (-1)
+
+
+static rtems_task rtems_portmapper (rtems_task_argument unused)
+{
+ SVCXPRT *xprt;
+ int sock;
+ struct sockaddr_in addr;
+ int len = sizeof(struct sockaddr_in);
+ register struct pmaplist *pml;
+
+ rtems_rpc_task_init ();
+ if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+ perror("portmap cannot create socket");
+ rtems_task_delete (RTEMS_SELF);
+ }
+
+ addr.sin_addr.s_addr = 0;
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(PMAPPORT);
+ if (bind(sock, (struct sockaddr *)&addr, len) != 0) {
+ perror("portmap cannot bind");
+ close (sock);
+ rtems_task_delete (RTEMS_SELF);
+ }
+
+ if ((xprt = svcudp_create(sock)) == (SVCXPRT *)NULL) {
+ fprintf(stderr, "couldn't do udp_create\n");
+ close (sock);
+ rtems_task_delete (RTEMS_SELF);
+ }
+ /* make an entry for ourself */
+ pml = (struct pmaplist *)malloc((u_int)sizeof(struct pmaplist));
+ pml->pml_next = 0;
+ pml->pml_map.pm_prog = PMAPPROG;
+ pml->pml_map.pm_vers = PMAPVERS;
+ pml->pml_map.pm_prot = IPPROTO_UDP;
+ pml->pml_map.pm_port = PMAPPORT;
+ pmaplist = pml;
+
+ if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
+ perror("portmap cannot create socket");
+ close (sock);
+ rtems_task_delete (RTEMS_SELF);
+ }
+ if (bind(sock, (struct sockaddr *)&addr, len) != 0) {
+ perror("portmap cannot bind");
+ close (sock);
+ rtems_task_delete (RTEMS_SELF);
+ }
+ if ((xprt = svctcp_create(sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE))
+ == (SVCXPRT *)NULL) {
+ fprintf(stderr, "couldn't do tcp_create\n");
+ close (sock);
+ rtems_task_delete (RTEMS_SELF);
+ }
+ /* make an entry for ourself */
+ pml = (struct pmaplist *)malloc((u_int)sizeof(struct pmaplist));
+ pml->pml_map.pm_prog = PMAPPROG;
+ pml->pml_map.pm_vers = PMAPVERS;
+ pml->pml_map.pm_prot = IPPROTO_TCP;
+ pml->pml_map.pm_port = PMAPPORT;
+ pml->pml_next = pmaplist;
+ pmaplist = pml;
+
+ (void)svc_register(xprt, PMAPPROG, PMAPVERS, reg_service, FALSE);
+
+ svc_run();
+ fprintf(stderr, "run_svc returned unexpectedly\n");
+ close (sock);
+ rtems_task_delete (RTEMS_SELF);
+}
+
+static struct pmaplist *
+find_service(prog, vers, prot)
+u_long prog;
+u_long vers;
+{
+register struct pmaplist *hit = NULL;
+register struct pmaplist *pml;
+
+for (pml = pmaplist; pml != NULL; pml = pml->pml_next) {
+ if ((pml->pml_map.pm_prog != prog) ||
+ (pml->pml_map.pm_prot != prot))
+ continue;
+ hit = pml;
+ if (pml->pml_map.pm_vers == vers)
+ break;
+}
+ return (hit);
+}
+
+/*
+ * 1 OK, 0 not
+ */
+static void reg_service(rqstp, xprt)
+ struct svc_req *rqstp;
+ SVCXPRT *xprt;
+{
+ struct pmap reg;
+ struct pmaplist *pml, *prevpml, *fnd;
+ int ans, port;
+ caddr_t t;
+
+#ifdef DEBUG
+ fprintf(stderr, "server: about do a switch\n");
+#endif
+ switch (rqstp->rq_proc) {
+
+ case PMAPPROC_NULL:
+ /*
+ * Null proc call
+ */
+ if ((!svc_sendreply(xprt, xdr_void, NULL)) && debugging) {
+ abort();
+ }
+ break;
+
+ case PMAPPROC_SET:
+ /*
+ * Set a program,version to port mapping
+ */
+ if (!svc_getargs(xprt, xdr_pmap, (caddr_t)&reg))
+ svcerr_decode(xprt);
+ else {
+ /*
+ * check to see if already used
+ * find_service returns a hit even if
+ * the versions don't match, so check for it
+ */
+ fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot);
+ if (fnd && fnd->pml_map.pm_vers == reg.pm_vers) {
+ if (fnd->pml_map.pm_port == reg.pm_port) {
+ ans = 1;
+ goto done;
+ }
+ else {
+ ans = 0;
+ goto done;
+ }
+ } else {
+ /*
+ * add to END of list
+ */
+ pml = (struct pmaplist *)
+ malloc((u_int)sizeof(struct pmaplist));
+ pml->pml_map = reg;
+ pml->pml_next = 0;
+ if (pmaplist == 0) {
+ pmaplist = pml;
+ } else {
+ for (fnd= pmaplist; fnd->pml_next != 0;
+ fnd = fnd->pml_next);
+ fnd->pml_next = pml;
+ }
+ ans = 1;
+ }
+ done:
+ if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) &&
+ debugging) {
+ fprintf(stderr, "svc_sendreply\n");
+ abort();
+ }
+ }
+ break;
+
+ case PMAPPROC_UNSET:
+ /*
+ * Remove a program,version to port mapping.
+ */
+ if (!svc_getargs(xprt, xdr_pmap, (caddr_t)&reg))
+ svcerr_decode(xprt);
+ else {
+ ans = 0;
+ for (prevpml = NULL, pml = pmaplist; pml != NULL; ) {
+ if ((pml->pml_map.pm_prog != reg.pm_prog) ||
+ (pml->pml_map.pm_vers != reg.pm_vers)) {
+ /* both pml & prevpml move forwards */
+ prevpml = pml;
+ pml = pml->pml_next;
+ continue;
+ }
+ /* found it; pml moves forward, prevpml stays */
+ ans = 1;
+ t = (caddr_t)pml;
+ pml = pml->pml_next;
+ if (prevpml == NULL)
+ pmaplist = pml;
+ else
+ prevpml->pml_next = pml;
+ free(t);
+ }
+ if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) &&
+ debugging) {
+ fprintf(stderr, "svc_sendreply\n");
+ abort();
+ }
+ }
+ break;
+
+ case PMAPPROC_GETPORT:
+ /*
+ * Lookup the mapping for a program,version and return its port
+ */
+ if (!svc_getargs(xprt, xdr_pmap, (caddr_t)&reg))
+ svcerr_decode(xprt);
+ else {
+ fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot);
+ if (fnd)
+ port = fnd->pml_map.pm_port;
+ else
+ port = 0;
+ if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&port)) &&
+ debugging) {
+ fprintf(stderr, "svc_sendreply\n");
+ abort();
+ }
+ }
+ break;
+
+ case PMAPPROC_DUMP:
+ /*
+ * Return the current set of mapped program,version
+ */
+ if (!svc_getargs(xprt, xdr_void, NULL))
+ svcerr_decode(xprt);
+ else {
+ if ((!svc_sendreply(xprt, xdr_pmaplist,
+ (caddr_t)&pmaplist)) && debugging) {
+ fprintf(stderr, "svc_sendreply\n");
+ abort();
+ }
+ }
+ break;
+
+ case PMAPPROC_CALLIT:
+ /*
+ * Calls a procedure on the local machine. If the requested
+ * procedure is not registered this procedure does not return
+ * error information!!
+ * This procedure is only supported on rpc/udp and calls via
+ * rpc/udp. It passes null authentication parameters.
+ */
+ callit(rqstp, xprt);
+ break;
+
+ default:
+ svcerr_noproc(xprt);
+ break;
+ }
+}
+
+
+/*
+ * Stuff for the rmtcall service
+ */
+#define ARGSIZE 9000
+
+struct encap_parms {
+ u_long arglen;
+ char *args;
+};
+
+static bool_t
+xdr_encap_parms(xdrs, epp)
+ XDR *xdrs;
+ struct encap_parms *epp;
+{
+
+ return (xdr_bytes(xdrs, &(epp->args), (u_int*)&(epp->arglen), ARGSIZE));
+}
+
+struct rmtcallargs {
+ u_long rmt_prog;
+ u_long rmt_vers;
+ u_long rmt_port;
+ u_long rmt_proc;
+ struct encap_parms rmt_args;
+};
+
+static bool_t
+xdr_rmtcall_args(xdrs, cap)
+ register XDR *xdrs;
+ register struct rmtcallargs *cap;
+{
+
+ /* does not get a port number */
+ if (xdr_u_long(xdrs, &(cap->rmt_prog)) &&
+ xdr_u_long(xdrs, &(cap->rmt_vers)) &&
+ xdr_u_long(xdrs, &(cap->rmt_proc))) {
+ return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
+ }
+ return (FALSE);
+}
+
+static bool_t
+xdr_rmtcall_result(xdrs, cap)
+ register XDR *xdrs;
+ register struct rmtcallargs *cap;
+{
+ if (xdr_u_long(xdrs, &(cap->rmt_port)))
+ return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
+ return (FALSE);
+}
+
+/*
+ * only worries about the struct encap_parms part of struct rmtcallargs.
+ * The arglen must already be set!!
+ */
+static bool_t
+xdr_opaque_parms(xdrs, cap)
+ XDR *xdrs;
+ struct rmtcallargs *cap;
+{
+
+ return (xdr_opaque(xdrs, cap->rmt_args.args, cap->rmt_args.arglen));
+}
+
+/*
+ * This routine finds and sets the length of incoming opaque paraters
+ * and then calls xdr_opaque_parms.
+ */
+static bool_t
+xdr_len_opaque_parms(xdrs, cap)
+ register XDR *xdrs;
+ struct rmtcallargs *cap;
+{
+ register u_int beginpos, lowpos, highpos, currpos, pos;
+
+ beginpos = lowpos = pos = xdr_getpos(xdrs);
+ highpos = lowpos + ARGSIZE;
+ while ((int)(highpos - lowpos) >= 0) {
+ currpos = (lowpos + highpos) / 2;
+ if (xdr_setpos(xdrs, currpos)) {
+ pos = currpos;
+ lowpos = currpos + 1;
+ } else {
+ highpos = currpos - 1;
+ }
+ }
+ xdr_setpos(xdrs, beginpos);
+ cap->rmt_args.arglen = pos - beginpos;
+ return (xdr_opaque_parms(xdrs, cap));
+}
+
+/*
+ * Call a remote procedure service
+ * This procedure is very quiet when things go wrong.
+ * The proc is written to support broadcast rpc. In the broadcast case,
+ * a machine should shut-up instead of complain, less the requestor be
+ * overrun with complaints at the expense of not hearing a valid reply ...
+ *
+ * This now forks so that the program & process that it calls can call
+ * back to the portmapper.
+ */
+static void
+callit(rqstp, xprt)
+ struct svc_req *rqstp;
+ SVCXPRT *xprt;
+{
+ struct rmtcallargs a;
+ struct pmaplist *pml;
+ u_short port;
+ struct sockaddr_in me;
+ int pid, socket = -1;
+ CLIENT *client;
+ struct authunix_parms *au = (struct authunix_parms *)rqstp->rq_clntcred;
+ struct timeval timeout;
+ char buf[ARGSIZE];
+
+ timeout.tv_sec = 5;
+ timeout.tv_usec = 0;
+ a.rmt_args.args = buf;
+ if (!svc_getargs(xprt, xdr_rmtcall_args, (caddr_t)&a))
+ return;
+ if ((pml = find_service(a.rmt_prog, a.rmt_vers, IPPROTO_UDP)) == NULL)
+ return;
+ /*
+ * fork a child to do the work. Parent immediately returns.
+ * Child exits upon completion.
+ */
+ if ((pid = fork()) != 0) {
+ if (debugging && (pid < 0)) {
+ fprintf(stderr, "portmap CALLIT: cannot fork.\n");
+ }
+ return;
+ }
+ port = pml->pml_map.pm_port;
+ get_myaddress(&me);
+ me.sin_port = htons(port);
+ client = clntudp_create(&me, a.rmt_prog, a.rmt_vers, timeout, &socket);
+ if (client != (CLIENT *)NULL) {
+ if (rqstp->rq_cred.oa_flavor == AUTH_UNIX) {
+ client->cl_auth = authunix_create(au->aup_machname,
+ au->aup_uid, au->aup_gid, au->aup_len, au->aup_gids);
+ }
+ a.rmt_port = (u_long)port;
+ if (clnt_call(client, a.rmt_proc, xdr_opaque_parms, &a,
+ xdr_len_opaque_parms, &a, timeout) == RPC_SUCCESS) {
+ svc_sendreply(xprt, xdr_rmtcall_result, (caddr_t)&a);
+ }
+ AUTH_DESTROY(client->cl_auth);
+ clnt_destroy(client);
+ }
+ (void)close(socket);
+ exit(0);
+}
+
+/*
+ * Start the RPC portmapper
+ */
+int rtems_rpc_start_portmapper (int priority)
+{
+ rtems_mode mode;
+ rtems_status_code sc;
+ rtems_id tid;
+ static int started;
+
+ rtems_task_mode (RTEMS_NO_PREEMPT, RTEMS_PREEMPT_MASK, &mode);
+ if (started) {
+ rtems_task_mode (mode, RTEMS_PREEMPT_MASK, &mode);
+ return RTEMS_SUCCESSFUL;
+ }
+ sc = rtems_task_create (rtems_build_name('P', 'M', 'A', 'P'),
+ priority,
+ 8000,
+ RTEMS_PREEMPT|RTEMS_NO_TIMESLICE|RTEMS_NO_ASR|RTEMS_INTERRUPT_LEVEL(0),
+ RTEMS_NO_FLOATING_POINT|RTEMS_LOCAL,
+ &tid);
+ if (sc != RTEMS_SUCCESSFUL) {
+ rtems_task_mode (mode, RTEMS_PREEMPT_MASK, &mode);
+ return sc;
+ }
+ sc = rtems_task_start (tid, rtems_portmapper, 0);
+ if (sc != RTEMS_SUCCESSFUL) {
+ rtems_task_mode (mode, RTEMS_PREEMPT_MASK, &mode);
+ return sc;
+ }
+ started = 1;
+ rtems_task_mode (mode, RTEMS_PREEMPT_MASK, &mode);
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/librpc/src/rpc/rtems_rpc.c b/cpukit/librpc/src/rpc/rtems_rpc.c
new file mode 100644
index 0000000000..301ba2138b
--- /dev/null
+++ b/cpukit/librpc/src/rpc/rtems_rpc.c
@@ -0,0 +1,59 @@
+/*
+ * RTEMS multi-tasking support
+ *
+ * $Id$
+ */
+
+#include <rpc/rpc.h>
+#include <rtems.h>
+#include <stdlib.h>
+
+/*
+ * RPC variables for single-thread
+ */
+static struct _rtems_rpc_task_variables rpc_default = {
+ -1, /* svc_maxfd */
+};
+
+/*
+ * RPC values for initializing a new per-task set of variables
+ */
+static const struct _rtems_rpc_task_variables rpc_init = {
+ -1, /* svc_maxfd */
+};
+
+/*
+ * Per-task pointer to RPC data
+ */
+struct _rtems_rpc_task_variables *rtems_rpc_task_variables = &rpc_default;
+
+/*
+ * Set up per-task RPC variables
+ */
+int rtems_rpc_task_init (void)
+{
+ rtems_status_code sc;
+ struct _rtems_rpc_task_variables *tvp;
+
+ if (rtems_rpc_task_variables == &rpc_default) {
+ tvp = malloc (sizeof *tvp);
+ if (tvp == NULL)
+ return RTEMS_NO_MEMORY;
+ /*
+ * FIXME: Should have destructor which cleans up
+ * all RPC stuff:
+ * - Close all files
+ * - Go through and free linked list elements
+ * - Free other allocated memory (e.g. clnt_perror_buf)
+ */
+ sc = rtems_task_variable_add (
+ RTEMS_SELF, (void *)&rtems_rpc_task_variables, NULL);
+ if (sc != RTEMS_SUCCESSFUL) {
+ free (tvp);
+ return sc;
+ }
+ *tvp = rpc_init;
+ rtems_rpc_task_variables = tvp;
+ }
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/librpc/src/rpc/rtime.3 b/cpukit/librpc/src/rpc/rtime.3
new file mode 100644
index 0000000000..ad3e538c43
--- /dev/null
+++ b/cpukit/librpc/src/rpc/rtime.3
@@ -0,0 +1,47 @@
+.\" @(#)rtime.3n 2.1 88/08/08 4.0 RPCSRC; from 1.5 88/02/08 SMI
+.\" $FreeBSD: src/lib/libc/rpc/rtime.3,v 1.4 2000/03/02 09:13:48 sheldonh Exp $
+.\"
+.TH RTIME 3 "22 November 1987"
+.SH NAME
+rtime \- get remote time
+.SH SYNOPSIS
+.nf
+.B #include <sys/types.h>
+.B #include <sys/time.h>
+.B #include <netinet/in.h>
+.LP
+.B int rtime(addrp, timep, timeout)
+.B struct sockaddr_in \(**addrp;
+.B struct timeval \(**timep;
+.B struct timeval \(**timeout;
+.fi
+.SH DESCRIPTION
+.B rtime(\|)
+consults the Internet Time Server at the address pointed to by
+.I addrp
+and returns the remote time in the
+.B timeval
+struct pointed to by
+.IR timep .
+Normally, the
+.SM UDP
+protocol is used when consulting the Time Server.
+The
+.I timeout
+parameter specifies how long the
+routine should wait before giving
+up when waiting for a reply. If
+.I timeout
+is specified as
+.SM NULL\s0,
+however, the routine will instead use
+.SM TCP
+and block until a reply is received from the time server.
+.LP
+The routine returns 0 if it is successful.
+Otherwise,
+it returns \-1 and
+.B errno
+is set to reflect the cause of the error.
+.SH "SEE ALSO"
+.BR timed (8c)
diff --git a/cpukit/librpc/src/rpc/rtime.c b/cpukit/librpc/src/rpc/rtime.c
new file mode 100644
index 0000000000..042d4f4e1d
--- /dev/null
+++ b/cpukit/librpc/src/rpc/rtime.c
@@ -0,0 +1,158 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * Copyright (c) 1988 by Sun Microsystems, Inc.
+
+ */
+
+/*
+ * rtime - get time from remote machine
+ *
+ * gets time, obtaining value from host
+ * on the udp/time socket. Since timeserver returns
+ * with time of day in seconds since Jan 1, 1900, must
+ * subtract seconds before Jan 1, 1970 to get
+ * what unix uses.
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <netdb.h>
+#include <sys/select.h>
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/* from: static char sccsid[] = "@(#)rtime.c 2.2 88/08/10 4.0 RPCSRC; from 1.8 88/02/08 SMI"; */
+static const char rcsid[] = "$FreeBSD: src/lib/libc/rpc/rtime.c,v 1.5 2000/01/27 23:06:41 jasone Exp $";
+#endif
+
+extern int _rpc_dtablesize __P(( void ));
+
+#define NYEARS (unsigned long)(1970 - 1900)
+#define TOFFSET (unsigned long)(60*60*24*(365*NYEARS + (NYEARS/4)))
+
+static void do_close __P(( int ));
+
+int
+rtime(addrp, timep, timeout)
+ struct sockaddr_in *addrp;
+ struct timeval *timep;
+ struct timeval *timeout;
+{
+ int s;
+ fd_set readfds;
+ int res;
+ unsigned long thetime;
+ struct sockaddr_in from;
+ int fromlen;
+ int type;
+ struct servent *serv;
+
+ if (timeout == NULL) {
+ type = SOCK_STREAM;
+ } else {
+ type = SOCK_DGRAM;
+ }
+ s = socket(AF_INET, type, 0);
+ if (s < 0) {
+ return(-1);
+ }
+ addrp->sin_family = AF_INET;
+
+ /* TCP and UDP port are the same in this case */
+ if ((serv = getservbyname("time", "tcp")) == NULL) {
+ return(-1);
+ }
+
+ addrp->sin_port = serv->s_port;
+
+ if (type == SOCK_DGRAM) {
+ res = sendto(s, (char *)&thetime, sizeof(thetime), 0,
+ (struct sockaddr *)addrp, sizeof(*addrp));
+ if (res < 0) {
+ do_close(s);
+ return(-1);
+ }
+ do {
+ FD_ZERO(&readfds);
+ FD_SET(s, &readfds);
+ res = select(_rpc_dtablesize(), &readfds,
+ (fd_set *)NULL, (fd_set *)NULL, timeout);
+ } while (res < 0 && errno == EINTR);
+ if (res <= 0) {
+ if (res == 0) {
+ errno = ETIMEDOUT;
+ }
+ do_close(s);
+ return(-1);
+ }
+ fromlen = sizeof(from);
+ res = recvfrom(s, (char *)&thetime, sizeof(thetime), 0,
+ (struct sockaddr *)&from, &fromlen);
+ do_close(s);
+ if (res < 0) {
+ return(-1);
+ }
+ } else {
+ if (connect(s, (struct sockaddr *)addrp, sizeof(*addrp)) < 0) {
+ do_close(s);
+ return(-1);
+ }
+ res = _RPC_read(s, (char *)&thetime, sizeof(thetime));
+ do_close(s);
+ if (res < 0) {
+ return(-1);
+ }
+ }
+ if (res != sizeof(thetime)) {
+ errno = EIO;
+ return(-1);
+ }
+ thetime = ntohl(thetime);
+ timep->tv_sec = thetime - TOFFSET;
+ timep->tv_usec = 0;
+ return(0);
+}
+
+static void
+do_close(s)
+ int s;
+{
+ int save;
+
+ save = errno;
+ (void)_RPC_close(s);
+ errno = save;
+}
diff --git a/cpukit/librpc/src/rpc/svc.c b/cpukit/librpc/src/rpc/svc.c
new file mode 100644
index 0000000000..751ca3185f
--- /dev/null
+++ b/cpukit/librpc/src/rpc/svc.c
@@ -0,0 +1,491 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)svc.c 1.44 88/02/08 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)svc.c 2.4 88/08/11 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/rpc/svc.c,v 1.14 1999/08/28 00:00:48 peter Exp $";
+#endif
+
+/*
+ * svc.c, Server-side remote procedure call interface.
+ *
+ * There are two sets of procedures here. The xprt routines are
+ * for handling transport handles. The svc routines handle the
+ * list of service routines.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <sys/errno.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+
+#define xports ((SVCXPRT **) rtems_rpc_task_variables->svc_xports)
+#define xportssize (rtems_rpc_task_variables->svc_xportssize)
+
+#define NULL_SVC ((struct svc_callout *)0)
+#define RQCRED_SIZE 400 /* this size is excessive */
+
+#define max(a, b) (a > b ? a : b)
+
+/*
+ * The services list
+ * Each entry represents a set of procedures (an rpc program).
+ * The dispatch routine takes request structs and runs the
+ * apropriate procedure.
+ */
+struct svc_callout {
+ struct svc_callout *sc_next;
+ u_long sc_prog;
+ u_long sc_vers;
+ void (*sc_dispatch)();
+};
+#define svc_head (struct svc_callout *)((rtems_rpc_task_variables)->svc_svc_head)
+
+static struct svc_callout *svc_find();
+
+/* *************** SVCXPRT related stuff **************** */
+
+/*
+ * Activate a transport handle.
+ */
+void
+xprt_register(xprt)
+ SVCXPRT *xprt;
+{
+ register int sock = xprt->xp_sock;
+
+ if (sock + 1 > __svc_fdsetsize) {
+ int bytes = sizeof (fd_set);
+ fd_set *fds;
+
+ fds = (fd_set *)malloc(bytes);
+ memset(fds, 0, bytes);
+ if (__svc_fdset) {
+ memcpy(fds, __svc_fdset, bytes);
+ free(__svc_fdset);
+ }
+ __svc_fdset = fds;
+ __svc_fdsetsize = bytes * NBBY;
+ }
+
+ if (sock < FD_SETSIZE)
+ FD_SET(sock, &svc_fdset);
+ FD_SET(sock, __svc_fdset);
+
+ if (xports == NULL || sock + 1 > xportssize) {
+ SVCXPRT **xp;
+ int size = FD_SETSIZE;
+
+ if (sock + 1 > size)
+ size = sock + 1;
+ xp = (SVCXPRT **)mem_alloc(size * sizeof(SVCXPRT *));
+ memset(xp, 0, size * sizeof(SVCXPRT *));
+ if (xports) {
+ memcpy(xp, xports, xportssize * sizeof(SVCXPRT *));
+ free(xports);
+ }
+ xportssize = size;
+ xports = xp;
+ }
+ xports[sock] = xprt;
+ svc_maxfd = max(svc_maxfd, sock);
+}
+
+/*
+ * De-activate a transport handle.
+ */
+void
+xprt_unregister(xprt)
+ SVCXPRT *xprt;
+{
+ register int sock = xprt->xp_sock;
+
+ if (xports[sock] == xprt) {
+ xports[sock] = (SVCXPRT *)0;
+ if (sock < FD_SETSIZE)
+ FD_CLR(sock, &svc_fdset);
+ FD_CLR(sock, __svc_fdset);
+ if (sock == svc_maxfd) {
+ for (svc_maxfd--; svc_maxfd >= 0; svc_maxfd--)
+ if (xports[svc_maxfd])
+ break;
+ }
+ /*
+ * XXX could use svc_maxfd as a hint to
+ * decrease the size of __svc_fdset
+ */
+ }
+}
+
+
+/* ********************** CALLOUT list related stuff ************* */
+
+/*
+ * Add a service program to the callout list.
+ * The dispatch routine will be called when a rpc request for this
+ * program number comes in.
+ */
+bool_t
+svc_register(xprt, prog, vers, dispatch, protocol)
+ SVCXPRT *xprt;
+ u_long prog;
+ u_long vers;
+ void (*dispatch)();
+ int protocol;
+{
+ struct svc_callout *prev;
+ register struct svc_callout *s;
+
+ if ((s = svc_find(prog, vers, &prev)) != NULL_SVC) {
+ if (s->sc_dispatch == dispatch)
+ goto pmap_it; /* he is registering another xptr */
+ return (FALSE);
+ }
+ s = (struct svc_callout *)mem_alloc(sizeof(struct svc_callout));
+ if (s == (struct svc_callout *)0) {
+ return (FALSE);
+ }
+ s->sc_prog = prog;
+ s->sc_vers = vers;
+ s->sc_dispatch = dispatch;
+ s->sc_next = svc_head;
+ svc_head = s;
+pmap_it:
+ /* now register the information with the local binder service */
+ if (protocol) {
+ return (pmap_set(prog, vers, protocol, xprt->xp_port));
+ }
+ return (TRUE);
+}
+
+/*
+ * Remove a service program from the callout list.
+ */
+void
+svc_unregister(prog, vers)
+ u_long prog;
+ u_long vers;
+{
+ struct svc_callout *prev;
+ register struct svc_callout *s;
+
+ if ((s = svc_find(prog, vers, &prev)) == NULL_SVC)
+ return;
+ if (prev == NULL_SVC) {
+ svc_head = s->sc_next;
+ } else {
+ prev->sc_next = s->sc_next;
+ }
+ s->sc_next = NULL_SVC;
+ mem_free((char *) s, (u_int) sizeof(struct svc_callout));
+ /* now unregister the information with the local binder service */
+ (void)pmap_unset(prog, vers);
+}
+
+/*
+ * Search the callout list for a program number, return the callout
+ * struct.
+ */
+static struct svc_callout *
+svc_find(prog, vers, prev)
+ u_long prog;
+ u_long vers;
+ struct svc_callout **prev;
+{
+ register struct svc_callout *s, *p;
+
+ p = NULL_SVC;
+ for (s = svc_head; s != NULL_SVC; s = s->sc_next) {
+ if ((s->sc_prog == prog) && (s->sc_vers == vers))
+ goto done;
+ p = s;
+ }
+done:
+ *prev = p;
+ return (s);
+}
+
+/* ******************* REPLY GENERATION ROUTINES ************ */
+
+/*
+ * Send a reply to an rpc request
+ */
+bool_t
+svc_sendreply(xprt, xdr_results, xdr_location)
+ register SVCXPRT *xprt;
+ xdrproc_t xdr_results;
+ caddr_t xdr_location;
+{
+ struct rpc_msg rply;
+
+ rply.rm_direction = REPLY;
+ rply.rm_reply.rp_stat = MSG_ACCEPTED;
+ rply.acpted_rply.ar_verf = xprt->xp_verf;
+ rply.acpted_rply.ar_stat = SUCCESS;
+ rply.acpted_rply.ar_results.where = xdr_location;
+ rply.acpted_rply.ar_results.proc = xdr_results;
+ return (SVC_REPLY(xprt, &rply));
+}
+
+/*
+ * No procedure error reply
+ */
+void
+svcerr_noproc(xprt)
+ register SVCXPRT *xprt;
+{
+ struct rpc_msg rply;
+
+ rply.rm_direction = REPLY;
+ rply.rm_reply.rp_stat = MSG_ACCEPTED;
+ rply.acpted_rply.ar_verf = xprt->xp_verf;
+ rply.acpted_rply.ar_stat = PROC_UNAVAIL;
+ SVC_REPLY(xprt, &rply);
+}
+
+/*
+ * Can't decode args error reply
+ */
+void
+svcerr_decode(xprt)
+ register SVCXPRT *xprt;
+{
+ struct rpc_msg rply;
+
+ rply.rm_direction = REPLY;
+ rply.rm_reply.rp_stat = MSG_ACCEPTED;
+ rply.acpted_rply.ar_verf = xprt->xp_verf;
+ rply.acpted_rply.ar_stat = GARBAGE_ARGS;
+ SVC_REPLY(xprt, &rply);
+}
+
+/*
+ * Some system error
+ */
+void
+svcerr_systemerr(xprt)
+ register SVCXPRT *xprt;
+{
+ struct rpc_msg rply;
+
+ rply.rm_direction = REPLY;
+ rply.rm_reply.rp_stat = MSG_ACCEPTED;
+ rply.acpted_rply.ar_verf = xprt->xp_verf;
+ rply.acpted_rply.ar_stat = SYSTEM_ERR;
+ SVC_REPLY(xprt, &rply);
+}
+
+/*
+ * Authentication error reply
+ */
+void
+svcerr_auth(xprt, why)
+ SVCXPRT *xprt;
+ enum auth_stat why;
+{
+ struct rpc_msg rply;
+
+ rply.rm_direction = REPLY;
+ rply.rm_reply.rp_stat = MSG_DENIED;
+ rply.rjcted_rply.rj_stat = AUTH_ERROR;
+ rply.rjcted_rply.rj_why = why;
+ SVC_REPLY(xprt, &rply);
+}
+
+/*
+ * Auth too weak error reply
+ */
+void
+svcerr_weakauth(xprt)
+ SVCXPRT *xprt;
+{
+
+ svcerr_auth(xprt, AUTH_TOOWEAK);
+}
+
+/*
+ * Program unavailable error reply
+ */
+void
+svcerr_noprog(xprt)
+ register SVCXPRT *xprt;
+{
+ struct rpc_msg rply;
+
+ rply.rm_direction = REPLY;
+ rply.rm_reply.rp_stat = MSG_ACCEPTED;
+ rply.acpted_rply.ar_verf = xprt->xp_verf;
+ rply.acpted_rply.ar_stat = PROG_UNAVAIL;
+ SVC_REPLY(xprt, &rply);
+}
+
+/*
+ * Program version mismatch error reply
+ */
+void
+svcerr_progvers(xprt, low_vers, high_vers)
+ register SVCXPRT *xprt;
+ u_long low_vers;
+ u_long high_vers;
+{
+ struct rpc_msg rply;
+
+ rply.rm_direction = REPLY;
+ rply.rm_reply.rp_stat = MSG_ACCEPTED;
+ rply.acpted_rply.ar_verf = xprt->xp_verf;
+ rply.acpted_rply.ar_stat = PROG_MISMATCH;
+ rply.acpted_rply.ar_vers.low = low_vers;
+ rply.acpted_rply.ar_vers.high = high_vers;
+ SVC_REPLY(xprt, &rply);
+}
+
+/* ******************* SERVER INPUT STUFF ******************* */
+
+/*
+ * Get server side input from some transport.
+ *
+ * Statement of authentication parameters management:
+ * This function owns and manages all authentication parameters, specifically
+ * the "raw" parameters (msg.rm_call.cb_cred and msg.rm_call.cb_verf) and
+ * the "cooked" credentials (rqst->rq_clntcred).
+ * However, this function does not know the structure of the cooked
+ * credentials, so it make the following assumptions:
+ * a) the structure is contiguous (no pointers), and
+ * b) the cred structure size does not exceed RQCRED_SIZE bytes.
+ * In all events, all three parameters are freed upon exit from this routine.
+ * The storage is trivially management on the call stack in user land, but
+ * is mallocated in kernel land.
+ */
+
+void
+svc_getreq(rdfds)
+ int rdfds;
+{
+ fd_set readfds;
+
+ FD_ZERO(&readfds);
+ readfds.fds_bits[0] = rdfds;
+ svc_getreqset(&readfds);
+}
+
+void
+svc_getreqset(readfds)
+ fd_set *readfds;
+{
+ svc_getreqset2(readfds, FD_SETSIZE);
+}
+
+void
+svc_getreqset2(readfds, width)
+ fd_set *readfds;
+ int width;
+{
+ enum xprt_stat stat;
+ struct rpc_msg msg;
+ int prog_found;
+ u_long low_vers;
+ u_long high_vers;
+ struct svc_req r;
+ register SVCXPRT *xprt;
+ register int bit;
+ register int sock;
+ register fd_mask mask, *maskp;
+ char cred_area[2*MAX_AUTH_BYTES + RQCRED_SIZE];
+ msg.rm_call.cb_cred.oa_base = cred_area;
+ msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]);
+ r.rq_clntcred = &(cred_area[2*MAX_AUTH_BYTES]);
+
+
+ maskp = readfds->fds_bits;
+ for (sock = 0; sock < width; sock += NFDBITS) {
+ for (mask = *maskp++; (bit = ffs(mask)); mask ^= (1 << (bit - 1))) {
+ /* sock has input waiting */
+ xprt = xports[sock + bit - 1];
+ if (xprt == NULL)
+ /* But do we control sock? */
+ continue;
+ /* now receive msgs from xprtprt (support batch calls) */
+ do {
+ if (SVC_RECV(xprt, &msg)) {
+
+ /* now find the exported program and call it */
+ register struct svc_callout *s;
+ enum auth_stat why;
+
+ r.rq_xprt = xprt;
+ r.rq_prog = msg.rm_call.cb_prog;
+ r.rq_vers = msg.rm_call.cb_vers;
+ r.rq_proc = msg.rm_call.cb_proc;
+ r.rq_cred = msg.rm_call.cb_cred;
+ /* first authenticate the message */
+ if ((why= _authenticate(&r, &msg)) != AUTH_OK) {
+ svcerr_auth(xprt, why);
+ goto call_done;
+ }
+ /* now match message with a registered service*/
+ prog_found = FALSE;
+ low_vers = (u_long) - 1;
+ high_vers = 0;
+ for (s = svc_head; s != NULL_SVC; s = s->sc_next) {
+ if (s->sc_prog == r.rq_prog) {
+ if (s->sc_vers == r.rq_vers) {
+ (*s->sc_dispatch)(&r, xprt);
+ goto call_done;
+ } /* found correct version */
+ prog_found = TRUE;
+ if (s->sc_vers < low_vers)
+ low_vers = s->sc_vers;
+ if (s->sc_vers > high_vers)
+ high_vers = s->sc_vers;
+ } /* found correct program */
+ }
+ /*
+ * if we got here, the program or version
+ * is not served ...
+ */
+ if (prog_found)
+ svcerr_progvers(xprt,
+ low_vers, high_vers);
+ else
+ svcerr_noprog(xprt);
+ /* Fall through to ... */
+ }
+ call_done:
+ if ((stat = SVC_STAT(xprt)) == XPRT_DIED){
+ SVC_DESTROY(xprt);
+ break;
+ }
+ } while (stat == XPRT_MOREREQS);
+ }
+ }
+}
diff --git a/cpukit/librpc/src/rpc/svc_auth.c b/cpukit/librpc/src/rpc/svc_auth.c
new file mode 100644
index 0000000000..5f36433388
--- /dev/null
+++ b/cpukit/librpc/src/rpc/svc_auth.c
@@ -0,0 +1,216 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc.
+ */
+
+/* #ident "@(#)svc_auth.c 1.16 94/04/24 SMI" */
+
+#if !defined(lint) && defined(SCCSIDS)
+#if 0
+static char sccsid[] = "@(#)svc_auth.c 1.26 89/02/07 Copyr 1984 Sun Micro";
+#else
+static const char rcsid[] =
+ "$FreeBSD: src/lib/libc/rpc/svc_auth.c,v 1.7 1999/12/29 05:04:16 peter Exp $";
+#endif
+#endif
+
+/*
+ * svc_auth.c, Server-side rpc authenticator interface.
+ *
+ */
+
+#ifdef _KERNEL
+#include <sys/param.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#include <rpc/clnt.h>
+#include <rpc/rpc_msg.h>
+#include <rpc/svc.h>
+#include <rpc/svc_auth.h>
+#else
+#include <stdlib.h>
+#include <rpc/rpc.h>
+#endif
+#include <sys/types.h>
+
+/*
+ * svcauthsw is the bdevsw of server side authentication.
+ *
+ * Server side authenticators are called from authenticate by
+ * using the client auth struct flavor field to index into svcauthsw.
+ * The server auth flavors must implement a routine that looks
+ * like:
+ *
+ * enum auth_stat
+ * flavorx_auth(rqst, msg)
+ * register struct svc_req *rqst;
+ * register struct rpc_msg *msg;
+ *
+ */
+
+enum auth_stat _svcauth_null(); /* no authentication */
+enum auth_stat _svcauth_unix(); /* (system) unix style (uid, gids) */
+enum auth_stat _svcauth_short(); /* short hand unix style */
+enum auth_stat _svcauth_des(); /* des style */
+
+/* declarations to allow servers to specify new authentication flavors */
+struct authsvc {
+ int flavor;
+ enum auth_stat (*handler)();
+ struct authsvc *next;
+};
+#define Auths ((struct authsvc *)(rtems_rpc_task_variables)->svc_auths_Auths)
+
+/*
+ * The call rpc message, msg has been obtained from the wire. The msg contains
+ * the raw form of credentials and verifiers. authenticate returns AUTH_OK
+ * if the msg is successfully authenticated. If AUTH_OK then the routine also
+ * does the following things:
+ * set rqst->rq_xprt->verf to the appropriate response verifier;
+ * sets rqst->rq_client_cred to the "cooked" form of the credentials.
+ *
+ * NB: rqst->rq_cxprt->verf must be pre-alloctaed;
+ * its length is set appropriately.
+ *
+ * The caller still owns and is responsible for msg->u.cmb.cred and
+ * msg->u.cmb.verf. The authentication system retains ownership of
+ * rqst->rq_client_cred, the cooked credentials.
+ *
+ * There is an assumption that any flavour less than AUTH_NULL is
+ * invalid.
+ */
+enum auth_stat
+_authenticate(rqst, msg)
+ register struct svc_req *rqst;
+ struct rpc_msg *msg;
+{
+ register int cred_flavor;
+ register struct authsvc *asp;
+
+ rqst->rq_cred = msg->rm_call.cb_cred;
+ rqst->rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor;
+ rqst->rq_xprt->xp_verf.oa_length = 0;
+ cred_flavor = rqst->rq_cred.oa_flavor;
+ switch (cred_flavor) {
+ case AUTH_NULL:
+ return(_svcauth_null(rqst, msg));
+ case AUTH_UNIX:
+ return(_svcauth_unix(rqst, msg));
+ case AUTH_SHORT:
+ return(_svcauth_short(rqst, msg));
+ /*
+ * We leave AUTH_DES turned off by default because svcauth_des()
+ * needs getpublickey(), which is in librpcsvc, not libc. If we
+ * included AUTH_DES as a built-in flavor, programs that don't
+ * have -lrpcsvc in their Makefiles wouldn't link correctly, even
+ * though they don't use AUTH_DES. And I'm too lazy to go through
+ * the tree looking for all of them.
+ */
+#ifdef DES_BUILTIN
+ case AUTH_DES:
+ return(_svcauth_des(rqst, msg));
+#endif
+ }
+
+ /* flavor doesn't match any of the builtin types, so try new ones */
+ for (asp = Auths; asp; asp = asp->next) {
+ if (asp->flavor == cred_flavor) {
+ enum auth_stat as;
+
+ as = (*asp->handler)(rqst, msg);
+ return (as);
+ }
+ }
+
+ return (AUTH_REJECTEDCRED);
+}
+
+/*ARGSUSED*/
+enum auth_stat
+_svcauth_null(rqst, msg)
+ struct svc_req *rqst;
+ struct rpc_msg *msg;
+{
+ return (AUTH_OK);
+}
+
+/*
+ * Allow the rpc service to register new authentication types that it is
+ * prepared to handle. When an authentication flavor is registered,
+ * the flavor is checked against already registered values. If not
+ * registered, then a new Auths entry is added on the list.
+ *
+ * There is no provision to delete a registration once registered.
+ *
+ * This routine returns:
+ * 0 if registration successful
+ * 1 if flavor already registered
+ * -1 if can't register (errno set)
+ */
+
+int
+svc_auth_reg(cred_flavor, handler)
+ register int cred_flavor;
+ enum auth_stat (*handler)();
+{
+ register struct authsvc *asp;
+
+ switch (cred_flavor) {
+ case AUTH_NULL:
+ case AUTH_UNIX:
+ case AUTH_SHORT:
+#ifdef DES_BUILTIN
+ case AUTH_DES:
+#endif
+ /* already registered */
+ return (1);
+
+ default:
+ for (asp = Auths; asp; asp = asp->next) {
+ if (asp->flavor == cred_flavor) {
+ /* already registered */
+ return (1);
+ }
+ }
+
+ /* this is a new one, so go ahead and register it */
+ asp = (struct authsvc *)mem_alloc(sizeof (*asp));
+ if (asp == NULL) {
+ return (-1);
+ }
+ asp->flavor = cred_flavor;
+ asp->handler = handler;
+ asp->next = Auths;
+ Auths = asp;
+ break;
+ }
+ return (0);
+}
diff --git a/cpukit/librpc/src/rpc/svc_auth_des.c b/cpukit/librpc/src/rpc/svc_auth_des.c
new file mode 100644
index 0000000000..b08c388ba1
--- /dev/null
+++ b/cpukit/librpc/src/rpc/svc_auth_des.c
@@ -0,0 +1,530 @@
+
+/*
+ * Copyright (c) 1988 by Sun Microsystems, Inc.
+ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * svcauth_des.c, server-side des authentication
+ *
+ * We insure for the service the following:
+ * (1) The timestamp microseconds do not exceed 1 million.
+ * (2) The timestamp plus the window is less than the current time.
+ * (3) The timestamp is not less than the one previously
+ * seen in the current session.
+ *
+ * It is up to the server to determine if the window size is
+ * too small .
+ *
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <rpc/des_crypt.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#include <rpc/auth_des.h>
+#include <rpc/svc.h>
+#include <rpc/rpc_msg.h>
+#include <rpc/svc_auth.h>
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/* from: static char sccsid[] = "@(#)svcauth_des.c 2.3 89/07/11 4.0 RPCSRC; from 1.15 88/02/08 SMI"; */
+static const char rcsid[] = "$FreeBSD: src/lib/libc/rpc/svc_auth_des.c,v 1.3 1999/08/28 00:00:48 peter Exp $";
+#endif
+
+#define debug(msg) printf("svcauth_des: %s\n", msg)
+
+#define USEC_PER_SEC ((u_long) 1000000L)
+#define BEFORE(t1, t2) timercmp(t1, t2, <)
+
+/*
+ * LRU cache of conversation keys and some other useful items.
+ */
+#define AUTHDES_CACHESZ 64
+struct cache_entry {
+ des_block key; /* conversation key */
+ char *rname; /* client's name */
+ u_int window; /* credential lifetime window */
+ struct timeval laststamp; /* detect replays of creds */
+ char *localcred; /* generic local credential */
+};
+static struct cache_entry *authdes_cache/* [AUTHDES_CACHESZ] */;
+static short *authdes_lru/* [AUTHDES_CACHESZ] */;
+
+static void cache_init(); /* initialize the cache */
+static short cache_spot(); /* find an entry in the cache */
+static void cache_ref(/*short sid*/); /* note that sid was ref'd */
+
+static void invalidate(); /* invalidate entry in cache */
+
+/*
+ * cache statistics
+ */
+static struct {
+ u_long ncachehits; /* times cache hit, and is not replay */
+ u_long ncachereplays; /* times cache hit, and is replay */
+ u_long ncachemisses; /* times cache missed */
+} svcauthdes_stats;
+
+/*
+ * Service side authenticator for AUTH_DES
+ */
+enum auth_stat
+_svcauth_des(rqst, msg)
+ register struct svc_req *rqst;
+ register struct rpc_msg *msg;
+{
+
+ register long *ixdr;
+ des_block cryptbuf[2];
+ register struct authdes_cred *cred;
+ struct authdes_verf verf;
+ int status;
+ register struct cache_entry *entry;
+ short sid = 0;
+ des_block *sessionkey;
+ des_block ivec;
+ u_int window;
+ struct timeval timestamp;
+ u_long namelen;
+ struct area {
+ struct authdes_cred area_cred;
+ char area_netname[MAXNETNAMELEN+1];
+ } *area;
+
+ if (authdes_cache == NULL) {
+ cache_init();
+ }
+
+ area = (struct area *)rqst->rq_clntcred;
+ cred = (struct authdes_cred *)&area->area_cred;
+
+ /*
+ * Get the credential
+ */
+ ixdr = (long *)msg->rm_call.cb_cred.oa_base;
+ cred->adc_namekind = IXDR_GET_ENUM(ixdr, enum authdes_namekind);
+ switch (cred->adc_namekind) {
+ case ADN_FULLNAME:
+ namelen = IXDR_GET_U_LONG(ixdr);
+ if (namelen > MAXNETNAMELEN) {
+ return (AUTH_BADCRED);
+ }
+ cred->adc_fullname.name = area->area_netname;
+ bcopy((char *)ixdr, cred->adc_fullname.name,
+ (u_int)namelen);
+ cred->adc_fullname.name[namelen] = 0;
+ ixdr += (RNDUP(namelen) / BYTES_PER_XDR_UNIT);
+ cred->adc_fullname.key.key.high = (u_long)*ixdr++;
+ cred->adc_fullname.key.key.low = (u_long)*ixdr++;
+ cred->adc_fullname.window = (u_long)*ixdr++;
+ break;
+ case ADN_NICKNAME:
+ cred->adc_nickname = (u_long)*ixdr++;
+ break;
+ default:
+ return (AUTH_BADCRED);
+ }
+
+ /*
+ * Get the verifier
+ */
+ ixdr = (long *)msg->rm_call.cb_verf.oa_base;
+ verf.adv_xtimestamp.key.high = (u_long)*ixdr++;
+ verf.adv_xtimestamp.key.low = (u_long)*ixdr++;
+ verf.adv_int_u = (u_long)*ixdr++;
+
+
+ /*
+ * Get the conversation key
+ */
+ if (cred->adc_namekind == ADN_FULLNAME) {
+ netobj pkey;
+ char pkey_data[1024];
+
+ sessionkey = &cred->adc_fullname.key;
+ if (! getpublickey(cred->adc_fullname.name, pkey_data)) {
+ debug("getpublickey");
+ return(AUTH_BADCRED);
+ }
+ pkey.n_bytes = pkey_data;
+ pkey.n_len = strlen(pkey_data) + 1;
+ if (key_decryptsession_pk(cred->adc_fullname.name, &pkey,
+ sessionkey) < 0) {
+ debug("decryptsessionkey");
+ return (AUTH_BADCRED); /* key not found */
+ }
+ } else { /* ADN_NICKNAME */
+ sid = (short)cred->adc_nickname;
+ if (sid >= AUTHDES_CACHESZ) {
+ debug("bad nickname");
+ return (AUTH_BADCRED); /* garbled credential */
+ }
+ sessionkey = &authdes_cache[sid].key;
+ }
+
+
+ /*
+ * Decrypt the timestamp
+ */
+ cryptbuf[0] = verf.adv_xtimestamp;
+ if (cred->adc_namekind == ADN_FULLNAME) {
+ cryptbuf[1].key.high = cred->adc_fullname.window;
+ cryptbuf[1].key.low = verf.adv_winverf;
+ ivec.key.high = ivec.key.low = 0;
+ status = cbc_crypt((char *)sessionkey, (char *)cryptbuf,
+ 2*sizeof(des_block), DES_DECRYPT | DES_HW,
+ (char *)&ivec);
+ } else {
+ status = ecb_crypt((char *)sessionkey, (char *)cryptbuf,
+ sizeof(des_block), DES_DECRYPT | DES_HW);
+ }
+ if (DES_FAILED(status)) {
+ debug("decryption failure");
+ return (AUTH_FAILED); /* system error */
+ }
+
+ /*
+ * XDR the decrypted timestamp
+ */
+ ixdr = (long *)cryptbuf;
+ timestamp.tv_sec = IXDR_GET_LONG(ixdr);
+ timestamp.tv_usec = IXDR_GET_LONG(ixdr);
+
+ /*
+ * Check for valid credentials and verifiers.
+ * They could be invalid because the key was flushed
+ * out of the cache, and so a new session should begin.
+ * Be sure and send AUTH_REJECTED{CRED, VERF} if this is the case.
+ */
+ {
+ struct timeval current;
+ int nick;
+ int winverf;
+
+ if (cred->adc_namekind == ADN_FULLNAME) {
+ window = IXDR_GET_U_LONG(ixdr);
+ winverf = IXDR_GET_U_LONG(ixdr);
+ if (winverf != window - 1) {
+ debug("window verifier mismatch");
+ return (AUTH_BADCRED); /* garbled credential */
+ }
+ sid = cache_spot(sessionkey, cred->adc_fullname.name,
+ &timestamp);
+ if (sid < 0) {
+ debug("replayed credential");
+ return (AUTH_REJECTEDCRED); /* replay */
+ }
+ nick = 0;
+ } else { /* ADN_NICKNAME */
+ window = authdes_cache[sid].window;
+ nick = 1;
+ }
+
+ if ((u_long)timestamp.tv_usec >= USEC_PER_SEC) {
+ debug("invalid usecs");
+ /* cached out (bad key), or garbled verifier */
+ return (nick ? AUTH_REJECTEDVERF : AUTH_BADVERF);
+ }
+ if (nick && BEFORE(&timestamp,
+ &authdes_cache[sid].laststamp)) {
+ debug("timestamp before last seen");
+ return (AUTH_REJECTEDVERF); /* replay */
+ }
+ (void) gettimeofday(&current, (struct timezone *)NULL);
+ current.tv_sec -= window; /* allow for expiration */
+ if (!BEFORE(&current, &timestamp)) {
+ debug("timestamp expired");
+ /* replay, or garbled credential */
+ return (nick ? AUTH_REJECTEDVERF : AUTH_BADCRED);
+ }
+ }
+
+ /*
+ * Set up the reply verifier
+ */
+ verf.adv_nickname = (u_long)sid;
+
+ /*
+ * xdr the timestamp before encrypting
+ */
+ ixdr = (long *)cryptbuf;
+ IXDR_PUT_LONG(ixdr, timestamp.tv_sec - 1);
+ IXDR_PUT_LONG(ixdr, timestamp.tv_usec);
+
+ /*
+ * encrypt the timestamp
+ */
+ status = ecb_crypt((char *)sessionkey, (char *)cryptbuf,
+ sizeof(des_block), DES_ENCRYPT | DES_HW);
+ if (DES_FAILED(status)) {
+ debug("encryption failure");
+ return (AUTH_FAILED); /* system error */
+ }
+ verf.adv_xtimestamp = cryptbuf[0];
+
+ /*
+ * Serialize the reply verifier, and update rqst
+ */
+ ixdr = (long *)msg->rm_call.cb_verf.oa_base;
+ *ixdr++ = (long)verf.adv_xtimestamp.key.high;
+ *ixdr++ = (long)verf.adv_xtimestamp.key.low;
+ *ixdr++ = (long)verf.adv_int_u;
+
+ rqst->rq_xprt->xp_verf.oa_flavor = AUTH_DES;
+ rqst->rq_xprt->xp_verf.oa_base = msg->rm_call.cb_verf.oa_base;
+ rqst->rq_xprt->xp_verf.oa_length =
+ (char *)ixdr - msg->rm_call.cb_verf.oa_base;
+
+ /*
+ * We succeeded, commit the data to the cache now and
+ * finish cooking the credential.
+ */
+ entry = &authdes_cache[sid];
+ entry->laststamp = timestamp;
+ cache_ref(sid);
+ if (cred->adc_namekind == ADN_FULLNAME) {
+ cred->adc_fullname.window = window;
+ cred->adc_nickname = (u_long)sid; /* save nickname */
+ if (entry->rname != NULL) {
+ mem_free(entry->rname, strlen(entry->rname) + 1);
+ }
+ entry->rname = (char *)mem_alloc((u_int)strlen(cred->adc_fullname.name)
+ + 1);
+ if (entry->rname != NULL) {
+ (void) strcpy(entry->rname, cred->adc_fullname.name);
+ } else {
+ debug("out of memory");
+ }
+ entry->key = *sessionkey;
+ entry->window = window;
+ invalidate(entry->localcred); /* mark any cached cred invalid */
+ } else { /* ADN_NICKNAME */
+ /*
+ * nicknames are cooked into fullnames
+ */
+ cred->adc_namekind = ADN_FULLNAME;
+ cred->adc_fullname.name = entry->rname;
+ cred->adc_fullname.key = entry->key;
+ cred->adc_fullname.window = entry->window;
+ }
+ return (AUTH_OK); /* we made it!*/
+}
+
+
+/*
+ * Initialize the cache
+ */
+static void
+cache_init()
+{
+ register int i;
+
+ authdes_cache = (struct cache_entry *)
+ mem_alloc(sizeof(struct cache_entry) * AUTHDES_CACHESZ);
+ bzero((char *)authdes_cache,
+ sizeof(struct cache_entry) * AUTHDES_CACHESZ);
+
+ authdes_lru = (short *)mem_alloc(sizeof(short) * AUTHDES_CACHESZ);
+ /*
+ * Initialize the lru list
+ */
+ for (i = 0; i < AUTHDES_CACHESZ; i++) {
+ authdes_lru[i] = i;
+ }
+}
+
+
+/*
+ * Find the lru victim
+ */
+static short
+cache_victim()
+{
+ return (authdes_lru[AUTHDES_CACHESZ-1]);
+}
+
+/*
+ * Note that sid was referenced
+ */
+static void
+cache_ref(sid)
+ register short sid;
+{
+ register int i;
+ register short curr;
+ register short prev;
+
+ prev = authdes_lru[0];
+ authdes_lru[0] = sid;
+ for (i = 1; prev != sid; i++) {
+ curr = authdes_lru[i];
+ authdes_lru[i] = prev;
+ prev = curr;
+ }
+}
+
+
+/*
+ * Find a spot in the cache for a credential containing
+ * the items given. Return -1 if a replay is detected, otherwise
+ * return the spot in the cache.
+ */
+static short
+cache_spot(key, name, timestamp)
+ register des_block *key;
+ char *name;
+ struct timeval *timestamp;
+{
+ register struct cache_entry *cp;
+ register int i;
+ register u_long hi;
+
+ hi = key->key.high;
+ for (cp = authdes_cache, i = 0; i < AUTHDES_CACHESZ; i++, cp++) {
+ if (cp->key.key.high == hi &&
+ cp->key.key.low == key->key.low &&
+ cp->rname != NULL &&
+ bcmp(cp->rname, name, strlen(name) + 1) == 0) {
+ if (BEFORE(timestamp, &cp->laststamp)) {
+ svcauthdes_stats.ncachereplays++;
+ return (-1); /* replay */
+ }
+ svcauthdes_stats.ncachehits++;
+ return (i); /* refresh */
+ }
+ }
+ svcauthdes_stats.ncachemisses++;
+ return (cache_victim()); /* new credential */
+}
+
+
+#if (defined(sun) || defined(vax) || defined(__FreeBSD__))
+/*
+ * Local credential handling stuff.
+ * NOTE: bsd unix dependent.
+ * Other operating systems should put something else here.
+ */
+#define UNKNOWN -2 /* grouplen, if cached cred is unknown user */
+#define INVALID -1 /* grouplen, if cache entry is invalid */
+
+struct bsdcred {
+ short uid; /* cached uid */
+ short gid; /* cached gid */
+ short grouplen; /* length of cached groups */
+ short groups[NGROUPS]; /* cached groups */
+};
+
+/*
+ * Map a des credential into a unix cred.
+ * We cache the credential here so the application does
+ * not have to make an rpc call every time to interpret
+ * the credential.
+ */
+int
+authdes_getucred(adc, uid, gid, grouplen, groups)
+ struct authdes_cred *adc;
+ uid_t *uid;
+ gid_t *gid;
+ int *grouplen;
+ register gid_t *groups;
+{
+ unsigned sid;
+ register int i;
+ uid_t i_uid;
+ gid_t i_gid;
+ int i_grouplen;
+ struct bsdcred *cred;
+
+ sid = adc->adc_nickname;
+ if (sid >= AUTHDES_CACHESZ) {
+ debug("invalid nickname");
+ return (0);
+ }
+ cred = (struct bsdcred *)authdes_cache[sid].localcred;
+ if (cred == NULL) {
+ cred = (struct bsdcred *)mem_alloc(sizeof(struct bsdcred));
+ authdes_cache[sid].localcred = (char *)cred;
+ cred->grouplen = INVALID;
+ }
+ if (cred->grouplen == INVALID) {
+ /*
+ * not in cache: lookup
+ */
+ if (!netname2user(adc->adc_fullname.name, &i_uid, &i_gid,
+ &i_grouplen, groups))
+ {
+ debug("unknown netname");
+ cred->grouplen = UNKNOWN; /* mark as lookup up, but not found */
+ return (0);
+ }
+ debug("missed ucred cache");
+ *uid = cred->uid = i_uid;
+ *gid = cred->gid = i_gid;
+ *grouplen = cred->grouplen = i_grouplen;
+ for (i = i_grouplen - 1; i >= 0; i--) {
+ cred->groups[i] = groups[i]; /* int to short */
+ }
+ return (1);
+ } else if (cred->grouplen == UNKNOWN) {
+ /*
+ * Already lookup up, but no match found
+ */
+ return (0);
+ }
+
+ /*
+ * cached credentials
+ */
+ *uid = cred->uid;
+ *gid = cred->gid;
+ *grouplen = cred->grouplen;
+ for (i = cred->grouplen - 1; i >= 0; i--) {
+ groups[i] = cred->groups[i]; /* short to int */
+ }
+ return (1);
+}
+
+static void
+invalidate(cred)
+ char *cred;
+{
+ if (cred == NULL) {
+ return;
+ }
+ ((struct bsdcred *)cred)->grouplen = INVALID;
+}
+#endif
diff --git a/cpukit/librpc/src/rpc/svc_auth_unix.c b/cpukit/librpc/src/rpc/svc_auth_unix.c
new file mode 100644
index 0000000000..8b4e257a2c
--- /dev/null
+++ b/cpukit/librpc/src/rpc/svc_auth_unix.c
@@ -0,0 +1,148 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)svc_auth_unix.c 1.28 88/02/08 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)svc_auth_unix.c 2.3 88/08/01 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/rpc/svc_auth_unix.c,v 1.8 1999/08/28 00:00:49 peter Exp $";
+#endif
+
+/*
+ * svc_auth_unix.c
+ * Handles UNIX flavor authentication parameters on the service side of rpc.
+ * There are two svc auth implementations here: AUTH_UNIX and AUTH_SHORT.
+ * _svcauth_unix does full blown unix style uid,gid+gids auth,
+ * _svcauth_short uses a shorthand auth to index into a cache of longhand auths.
+ * Note: the shorthand has been gutted for efficiency.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <rpc/rpc.h>
+
+/*
+ * Unix longhand authenticator
+ */
+enum auth_stat
+_svcauth_unix(rqst, msg)
+ register struct svc_req *rqst;
+ register struct rpc_msg *msg;
+{
+ register enum auth_stat stat;
+ XDR xdrs;
+ register struct authunix_parms *aup;
+ register int32_t *buf;
+ struct area {
+ struct authunix_parms area_aup;
+ char area_machname[MAX_MACHINE_NAME+1];
+ int area_gids[NGRPS];
+ } *area;
+ u_int auth_len;
+ int str_len, gid_len;
+ register int i;
+
+ area = (struct area *) rqst->rq_clntcred;
+ aup = &area->area_aup;
+ aup->aup_machname = area->area_machname;
+ aup->aup_gids = area->area_gids;
+ auth_len = (u_int)msg->rm_call.cb_cred.oa_length;
+ xdrmem_create(&xdrs, msg->rm_call.cb_cred.oa_base, auth_len,XDR_DECODE);
+ buf = XDR_INLINE(&xdrs, auth_len);
+ if (buf != NULL) {
+ aup->aup_time = IXDR_GET_LONG(buf);
+ str_len = IXDR_GET_U_LONG(buf);
+ if (str_len > MAX_MACHINE_NAME) {
+ stat = AUTH_BADCRED;
+ goto done;
+ }
+ memcpy(aup->aup_machname, (caddr_t)buf, (u_int)str_len);
+ aup->aup_machname[str_len] = 0;
+ str_len = RNDUP(str_len);
+ buf += str_len / sizeof (int32_t);
+ aup->aup_uid = IXDR_GET_LONG(buf);
+ aup->aup_gid = IXDR_GET_LONG(buf);
+ gid_len = IXDR_GET_U_LONG(buf);
+ if (gid_len > NGRPS) {
+ stat = AUTH_BADCRED;
+ goto done;
+ }
+ aup->aup_len = gid_len;
+ for (i = 0; i < gid_len; i++) {
+ aup->aup_gids[i] = IXDR_GET_LONG(buf);
+ }
+ /*
+ * five is the smallest unix credentials structure -
+ * timestamp, hostname len (0), uid, gid, and gids len (0).
+ */
+ if ((5 + gid_len) * BYTES_PER_XDR_UNIT + str_len > auth_len) {
+ (void) printf("bad auth_len gid %d str %d auth %d\n",
+ gid_len, str_len, auth_len);
+ stat = AUTH_BADCRED;
+ goto done;
+ }
+ } else if (! xdr_authunix_parms(&xdrs, aup)) {
+ xdrs.x_op = XDR_FREE;
+ (void)xdr_authunix_parms(&xdrs, aup);
+ stat = AUTH_BADCRED;
+ goto done;
+ }
+
+ /* get the verifier */
+ if ((u_int)msg->rm_call.cb_verf.oa_length) {
+ rqst->rq_xprt->xp_verf.oa_flavor =
+ msg->rm_call.cb_verf.oa_flavor;
+ rqst->rq_xprt->xp_verf.oa_base =
+ msg->rm_call.cb_verf.oa_base;
+ rqst->rq_xprt->xp_verf.oa_length =
+ msg->rm_call.cb_verf.oa_length;
+ } else {
+ rqst->rq_xprt->xp_verf.oa_flavor = AUTH_NULL;
+ rqst->rq_xprt->xp_verf.oa_length = 0;
+ }
+ stat = AUTH_OK;
+done:
+ XDR_DESTROY(&xdrs);
+ return (stat);
+}
+
+
+/*
+ * Shorthand unix authenticator
+ * Looks up longhand in a cache.
+ */
+/*ARGSUSED*/
+enum auth_stat
+_svcauth_short(rqst, msg)
+ struct svc_req *rqst;
+ struct rpc_msg *msg;
+{
+ return (AUTH_REJECTEDCRED);
+}
diff --git a/cpukit/librpc/src/rpc/svc_raw.c b/cpukit/librpc/src/rpc/svc_raw.c
new file mode 100644
index 0000000000..108b18a309
--- /dev/null
+++ b/cpukit/librpc/src/rpc/svc_raw.c
@@ -0,0 +1,169 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)svc_raw.c 1.15 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)svc_raw.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/rpc/svc_raw.c,v 1.7 1999/08/28 00:00:49 peter Exp $";
+#endif
+
+/*
+ * svc_raw.c, This a toy for simple testing and timing.
+ * Interface to create an rpc client and server in the same UNIX process.
+ * This lets us similate rpc and get rpc (round trip) overhead, without
+ * any interference from the kernal.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <rpc/rpc.h>
+#include <stdlib.h>
+
+/*
+ * This is the "network" that we will be moving data over
+ */
+struct svc_raw_private {
+ char _raw_buf[UDPMSGSIZE];
+ SVCXPRT server;
+ XDR xdr_stream;
+ char verf_body[MAX_AUTH_BYTES];
+};
+#define svcraw_private ((struct svc_raw_private *)(rtems_rpc_task_variables)->svc_raw_private)
+
+static bool_t svcraw_recv();
+static enum xprt_stat svcraw_stat();
+static bool_t svcraw_getargs();
+static bool_t svcraw_reply();
+static bool_t svcraw_freeargs();
+static void svcraw_destroy();
+
+static struct xp_ops server_ops = {
+ svcraw_recv,
+ svcraw_stat,
+ svcraw_getargs,
+ svcraw_reply,
+ svcraw_freeargs,
+ svcraw_destroy
+};
+
+SVCXPRT *
+svcraw_create()
+{
+ register struct svc_raw_private *srp = svcraw_private;
+
+ if (srp == 0) {
+ srp = (struct svc_raw_private *)calloc(1, sizeof (*srp));
+ if (srp == 0)
+ return (0);
+ }
+ srp->server.xp_sock = 0;
+ srp->server.xp_port = 0;
+ srp->server.xp_ops = &server_ops;
+ srp->server.xp_verf.oa_base = srp->verf_body;
+ xdrmem_create(&srp->xdr_stream, srp->_raw_buf, UDPMSGSIZE, XDR_FREE);
+ return (&srp->server);
+}
+
+static enum xprt_stat
+svcraw_stat()
+{
+
+ return (XPRT_IDLE);
+}
+
+static bool_t
+svcraw_recv(xprt, msg)
+ SVCXPRT *xprt;
+ struct rpc_msg *msg;
+{
+ register struct svc_raw_private *srp = svcraw_private;
+ register XDR *xdrs;
+
+ if (srp == 0)
+ return (0);
+ xdrs = &srp->xdr_stream;
+ xdrs->x_op = XDR_DECODE;
+ XDR_SETPOS(xdrs, 0);
+ if (! xdr_callmsg(xdrs, msg))
+ return (FALSE);
+ return (TRUE);
+}
+
+static bool_t
+svcraw_reply(xprt, msg)
+ SVCXPRT *xprt;
+ struct rpc_msg *msg;
+{
+ register struct svc_raw_private *srp = svcraw_private;
+ register XDR *xdrs;
+
+ if (srp == 0)
+ return (FALSE);
+ xdrs = &srp->xdr_stream;
+ xdrs->x_op = XDR_ENCODE;
+ XDR_SETPOS(xdrs, 0);
+ if (! xdr_replymsg(xdrs, msg))
+ return (FALSE);
+ (void)XDR_GETPOS(xdrs); /* called just for overhead */
+ return (TRUE);
+}
+
+static bool_t
+svcraw_getargs(xprt, xdr_args, args_ptr)
+ SVCXPRT *xprt;
+ xdrproc_t xdr_args;
+ caddr_t args_ptr;
+{
+ register struct svc_raw_private *srp = svcraw_private;
+
+ if (srp == 0)
+ return (FALSE);
+ return ((*xdr_args)(&srp->xdr_stream, args_ptr));
+}
+
+static bool_t
+svcraw_freeargs(xprt, xdr_args, args_ptr)
+ SVCXPRT *xprt;
+ xdrproc_t xdr_args;
+ caddr_t args_ptr;
+{
+ register struct svc_raw_private *srp = svcraw_private;
+ register XDR *xdrs;
+
+ if (srp == 0)
+ return (FALSE);
+ xdrs = &srp->xdr_stream;
+ xdrs->x_op = XDR_FREE;
+ return ((*xdr_args)(xdrs, args_ptr));
+}
+
+static void
+svcraw_destroy()
+{
+}
diff --git a/cpukit/librpc/src/rpc/svc_run.c b/cpukit/librpc/src/rpc/svc_run.c
new file mode 100644
index 0000000000..b1b6dded2f
--- /dev/null
+++ b/cpukit/librpc/src/rpc/svc_run.c
@@ -0,0 +1,84 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)svc_run.c 1.1 87/10/13 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)svc_run.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/rpc/svc_run.c,v 1.10 1999/08/28 00:00:49 peter Exp $";
+#endif
+
+/*
+ * This is the rpc server side idle loop
+ * Wait for input, call server program.
+ */
+#include <rpc/rpc.h>
+#include <stdio.h>
+#include <sys/errno.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/select.h>
+
+void
+svc_run()
+{
+ fd_set *fds;
+
+ for (;;) {
+ if (__svc_fdset) {
+ int bytes = sizeof (fd_set);
+ fds = (fd_set *)malloc(bytes);
+ memcpy(fds, __svc_fdset, bytes);
+ } else
+ fds = NULL;
+ switch (select(svc_maxfd + 1, fds, NULL, NULL,
+ (struct timeval *)0)) {
+ case -1:
+ if (errno == EINTR) {
+ if (fds)
+ free(fds);
+ continue;
+ }
+ perror("svc_run: - select failed");
+ if (fds)
+ free(fds);
+ return;
+ case 0:
+ if (fds)
+ free(fds);
+ continue;
+ default:
+ /* if fds == NULL, select() can't return a result */
+ svc_getreqset2(fds, svc_maxfd + 1);
+ free(fds);
+ }
+ }
+}
diff --git a/cpukit/librpc/src/rpc/svc_simple.c b/cpukit/librpc/src/rpc/svc_simple.c
new file mode 100644
index 0000000000..c22063ffc6
--- /dev/null
+++ b/cpukit/librpc/src/rpc/svc_simple.c
@@ -0,0 +1,150 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)svc_simple.c 1.18 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)svc_simple.c 2.2 88/08/01 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/rpc/svc_simple.c,v 1.9 1999/08/28 00:00:50 peter Exp $";
+#endif
+
+/*
+ * svc_simple.c
+ * Simplified front end to rpc.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+struct prog_lst {
+ char *(*p_progname)();
+ int p_prognum;
+ int p_procnum;
+ xdrproc_t p_inproc, p_outproc;
+ struct prog_lst *p_nxt;
+};
+static void universal();
+#define proglst ((struct prog_lst *)(rtems_rpc_task_variables)->svc_simple_proglst)
+#define pl ((struct prog_lst *)(rtems_rpc_task_variables)->svc_simple_pl)
+#define transp ((SVCXPRT *)(rtems_rpc_task_variables)->svc_simple_transp)
+
+int
+registerrpc(prognum, versnum, procnum, progname, inproc, outproc)
+ int prognum, versnum, procnum;
+ char *(*progname)();
+ xdrproc_t inproc, outproc;
+{
+
+ if (procnum == NULLPROC) {
+ (void) fprintf(stderr,
+ "can't reassign procedure number %ld\n", NULLPROC);
+ return (-1);
+ }
+ if (transp == 0) {
+ transp = svcudp_create(RPC_ANYSOCK);
+ if (transp == NULL) {
+ (void) fprintf(stderr, "couldn't create an rpc server\n");
+ return (-1);
+ }
+ }
+ (void) pmap_unset((u_long)prognum, (u_long)versnum);
+ if (!svc_register(transp, (u_long)prognum, (u_long)versnum,
+ universal, IPPROTO_UDP)) {
+ (void) fprintf(stderr, "couldn't register prog %d vers %d\n",
+ prognum, versnum);
+ return (-1);
+ }
+ pl = (struct prog_lst *)malloc(sizeof(struct prog_lst));
+ if (pl == NULL) {
+ (void) fprintf(stderr, "registerrpc: out of memory\n");
+ return (-1);
+ }
+ pl->p_progname = progname;
+ pl->p_prognum = prognum;
+ pl->p_procnum = procnum;
+ pl->p_inproc = inproc;
+ pl->p_outproc = outproc;
+ pl->p_nxt = proglst;
+ proglst = pl;
+ return (0);
+}
+
+static void
+universal(rqstp, atransp)
+ struct svc_req *rqstp;
+ SVCXPRT *atransp;
+{
+ int prog, proc;
+ char *outdata;
+ char xdrbuf[UDPMSGSIZE];
+ struct prog_lst *lpl;
+
+ /*
+ * enforce "procnum 0 is echo" convention
+ */
+ if (rqstp->rq_proc == NULLPROC) {
+ if (svc_sendreply(atransp, xdr_void, NULL) == FALSE) {
+ (void) fprintf(stderr, "xxx\n");
+ exit(1);
+ }
+ return;
+ }
+ prog = rqstp->rq_prog;
+ proc = rqstp->rq_proc;
+ for (lpl = proglst; lpl != NULL; lpl = lpl->p_nxt)
+ if (lpl->p_prognum == prog && lpl->p_procnum == proc) {
+ /* decode arguments into a CLEAN buffer */
+ memset(xdrbuf, 0, sizeof(xdrbuf)); /* required ! */
+ if (!svc_getargs(atransp, lpl->p_inproc, xdrbuf)) {
+ svcerr_decode(atransp);
+ return;
+ }
+ outdata = (*(lpl->p_progname))(xdrbuf);
+ if (outdata == NULL && lpl->p_outproc != xdr_void)
+ /* there was an error */
+ return;
+ if (!svc_sendreply(atransp, lpl->p_outproc, outdata)) {
+ (void) fprintf(stderr,
+ "trouble replying to prog %d\n",
+ lpl->p_prognum);
+ exit(1);
+ }
+ /* free the decoded arguments */
+ (void)svc_freeargs(atransp, lpl->p_inproc, xdrbuf);
+ return;
+ }
+ (void) fprintf(stderr, "never registered prog %d\n", prog);
+ exit(1);
+}
diff --git a/cpukit/librpc/src/rpc/svc_tcp.c b/cpukit/librpc/src/rpc/svc_tcp.c
new file mode 100644
index 0000000000..116ba7e379
--- /dev/null
+++ b/cpukit/librpc/src/rpc/svc_tcp.c
@@ -0,0 +1,482 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)svc_tcp.c 2.2 88/08/01 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/rpc/svc_tcp.c,v 1.18 2000/01/27 23:06:41 jasone Exp $";
+#endif
+
+/*
+ * svc_tcp.c, Server side for TCP/IP based RPC.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * Actually implements two flavors of transporter -
+ * a tcp rendezvouser (a listner and connection establisher)
+ * and a record/tcp stream.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <sys/select.h>
+
+/*
+ * Ops vector for TCP/IP based rpc service handle
+ */
+static bool_t svctcp_recv();
+static enum xprt_stat svctcp_stat();
+static bool_t svctcp_getargs();
+static bool_t svctcp_reply();
+static bool_t svctcp_freeargs();
+static void svctcp_destroy();
+
+static struct xp_ops svctcp_op = {
+ svctcp_recv,
+ svctcp_stat,
+ svctcp_getargs,
+ svctcp_reply,
+ svctcp_freeargs,
+ svctcp_destroy
+};
+
+/*
+ * Ops vector for TCP/IP rendezvous handler
+ */
+static bool_t rendezvous_request();
+static enum xprt_stat rendezvous_stat();
+
+static struct xp_ops svctcp_rendezvous_op = {
+ rendezvous_request,
+ rendezvous_stat,
+ (bool_t (*)())abort,
+ (bool_t (*)())abort,
+ (bool_t (*)())abort,
+ svctcp_destroy
+};
+
+static int readtcp(), writetcp();
+static SVCXPRT *makefd_xprt();
+
+struct tcp_rendezvous { /* kept in xprt->xp_p1 */
+ u_int sendsize;
+ u_int recvsize;
+};
+
+struct tcp_conn { /* kept in xprt->xp_p1 */
+ enum xprt_stat strm_stat;
+ u_long x_id;
+ XDR xdrs;
+ char verf_body[MAX_AUTH_BYTES];
+};
+
+/*
+ * Usage:
+ * xprt = svctcp_create(sock, send_buf_size, recv_buf_size);
+ *
+ * Creates, registers, and returns a (rpc) tcp based transporter.
+ * Once *xprt is initialized, it is registered as a transporter
+ * see (svc.h, xprt_register). This routine returns
+ * a NULL if a problem occurred.
+ *
+ * If sock<0 then a socket is created, else sock is used.
+ * If the socket, sock is not bound to a port then svctcp_create
+ * binds it to an arbitrary port. The routine then starts a tcp
+ * listener on the socket's associated port. In any (successful) case,
+ * xprt->xp_sock is the registered socket number and xprt->xp_port is the
+ * associated port number.
+ *
+ * Since tcp streams do buffered io similar to stdio, the caller can specify
+ * how big the send and receive buffers are via the second and third parms;
+ * 0 => use the system default.
+ */
+SVCXPRT *
+svctcp_create(sock, sendsize, recvsize)
+ register int sock;
+ u_int sendsize;
+ u_int recvsize;
+{
+ bool_t madesock = FALSE;
+ register SVCXPRT *xprt;
+ register struct tcp_rendezvous *r;
+ struct sockaddr_in addr;
+ int len = sizeof(struct sockaddr_in);
+ int on;
+
+ if (sock == RPC_ANYSOCK) {
+ if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
+ perror("svctcp_.c - udp socket creation problem");
+ return ((SVCXPRT *)NULL);
+ }
+ madesock = TRUE;
+ }
+ on = 1;
+ if (ioctl(sock, FIONBIO, &on) < 0) {
+ perror("svc_tcp.c - cannot turn on non-blocking mode");
+ if (madesock)
+ (void)_RPC_close(sock);
+ return ((SVCXPRT *)NULL);
+ }
+ memset(&addr, 0, sizeof (addr));
+ addr.sin_len = sizeof(struct sockaddr_in);
+ addr.sin_family = AF_INET;
+ if (bindresvport(sock, &addr)) {
+ addr.sin_port = 0;
+ (void)bind(sock, (struct sockaddr *)&addr, len);
+ }
+ if ((getsockname(sock, (struct sockaddr *)&addr, &len) != 0) ||
+ (listen(sock, 2) != 0)) {
+ perror("svctcp_.c - cannot getsockname or listen");
+ if (madesock)
+ (void)_RPC_close(sock);
+ return ((SVCXPRT *)NULL);
+ }
+ r = (struct tcp_rendezvous *)mem_alloc(sizeof(*r));
+ if (r == NULL) {
+ (void) fprintf(stderr, "svctcp_create: out of memory\n");
+ return (NULL);
+ }
+ r->sendsize = sendsize;
+ r->recvsize = recvsize;
+ xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
+ if (xprt == NULL) {
+ (void) fprintf(stderr, "svctcp_create: out of memory\n");
+ return (NULL);
+ }
+ xprt->xp_p2 = NULL;
+ xprt->xp_p1 = (caddr_t)r;
+ xprt->xp_verf = _null_auth;
+ xprt->xp_ops = &svctcp_rendezvous_op;
+ xprt->xp_port = ntohs(addr.sin_port);
+ xprt->xp_sock = sock;
+ xprt_register(xprt);
+ return (xprt);
+}
+
+/*
+ * Like svtcp_create(), except the routine takes any *open* UNIX file
+ * descriptor as its first input.
+ */
+SVCXPRT *
+svcfd_create(fd, sendsize, recvsize)
+ int fd;
+ u_int sendsize;
+ u_int recvsize;
+{
+
+ return (makefd_xprt(fd, sendsize, recvsize));
+}
+
+static SVCXPRT *
+makefd_xprt(fd, sendsize, recvsize)
+ int fd;
+ u_int sendsize;
+ u_int recvsize;
+{
+ register SVCXPRT *xprt;
+ register struct tcp_conn *cd;
+
+ xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
+ if (xprt == (SVCXPRT *)NULL) {
+ (void) fprintf(stderr, "svc_tcp: makefd_xprt: out of memory\n");
+ goto done;
+ }
+ cd = (struct tcp_conn *)mem_alloc(sizeof(struct tcp_conn));
+ if (cd == (struct tcp_conn *)NULL) {
+ (void) fprintf(stderr, "svc_tcp: makefd_xprt: out of memory\n");
+ mem_free((char *) xprt, sizeof(SVCXPRT));
+ xprt = (SVCXPRT *)NULL;
+ goto done;
+ }
+ cd->strm_stat = XPRT_IDLE;
+ xdrrec_create(&(cd->xdrs), sendsize, recvsize,
+ (caddr_t)xprt, readtcp, writetcp);
+ xprt->xp_p2 = NULL;
+ xprt->xp_p1 = (caddr_t)cd;
+ xprt->xp_verf.oa_base = cd->verf_body;
+ xprt->xp_addrlen = 0;
+ xprt->xp_ops = &svctcp_op; /* truely deals with calls */
+ xprt->xp_port = 0; /* this is a connection, not a rendezvouser */
+ xprt->xp_sock = fd;
+ xprt_register(xprt);
+ done:
+ return (xprt);
+}
+
+static bool_t
+rendezvous_request(xprt)
+ register SVCXPRT *xprt;
+{
+ int sock;
+ struct tcp_rendezvous *r;
+ struct sockaddr_in addr;
+ int len;
+ int off;
+
+ r = (struct tcp_rendezvous *)xprt->xp_p1;
+ again:
+ len = sizeof(struct sockaddr_in);
+ if ((sock = accept(xprt->xp_sock, (struct sockaddr *)&addr,
+ &len)) < 0) {
+ if (errno == EINTR)
+ goto again;
+ return (FALSE);
+ }
+ /*
+ * Guard against FTP bounce attacks.
+ */
+ if (addr.sin_port == htons(20)) {
+ _RPC_close(sock);
+ return (FALSE);
+ }
+ /*
+ * The listening socket is in FIONBIO mode and we inherit it.
+ */
+ off = 0;
+ if (ioctl(sock, FIONBIO, &off) < 0) {
+ _RPC_close(sock);
+ return (FALSE);
+ }
+ /*
+ * make a new transporter (re-uses xprt)
+ */
+ xprt = makefd_xprt(sock, r->sendsize, r->recvsize);
+ xprt->xp_raddr = addr;
+ xprt->xp_addrlen = len;
+ return (FALSE); /* there is never an rpc msg to be processed */
+}
+
+static enum xprt_stat
+rendezvous_stat()
+{
+
+ return (XPRT_IDLE);
+}
+
+static void
+svctcp_destroy(xprt)
+ register SVCXPRT *xprt;
+{
+ register struct tcp_conn *cd = (struct tcp_conn *)xprt->xp_p1;
+
+ xprt_unregister(xprt);
+ (void)_RPC_close(xprt->xp_sock);
+ if (xprt->xp_port != 0) {
+ /* a rendezvouser socket */
+ xprt->xp_port = 0;
+ } else {
+ /* an actual connection socket */
+ XDR_DESTROY(&(cd->xdrs));
+ }
+ mem_free((caddr_t)cd, sizeof(struct tcp_conn));
+ mem_free((caddr_t)xprt, sizeof(SVCXPRT));
+}
+
+/*
+ * All read operations timeout after 35 seconds.
+ * A timeout is fatal for the connection.
+ */
+static struct timeval wait_per_try = { 35, 0 };
+
+/*
+ * reads data from the tcp conection.
+ * any error is fatal and the connection is closed.
+ * (And a read of zero bytes is a half closed stream => error.)
+ *
+ * Note: we have to be careful here not to allow ourselves to become
+ * blocked too long in this routine. While we're waiting for data from one
+ * client, another client may be trying to connect. To avoid this situation,
+ * some code from svc_run() is transplanted here: the select() loop checks
+ * all RPC descriptors including the one we want and calls svc_getreqset2()
+ * to handle new requests if any are detected.
+ */
+static int
+readtcp(xprt, buf, len)
+ register SVCXPRT *xprt;
+ caddr_t buf;
+ register int len;
+{
+ register int sock = xprt->xp_sock;
+ struct timeval start, delta, tv;
+ struct timeval tmp1, tmp2;
+ fd_set *fds;
+
+ delta = wait_per_try;
+ fds = NULL;
+ gettimeofday(&start, NULL);
+ do {
+ int bytes = sizeof (fd_set);
+ if (fds != NULL)
+ free(fds);
+ fds = (fd_set *)malloc(bytes);
+ if (fds == NULL)
+ goto fatal_err;
+ memcpy(fds, __svc_fdset, bytes);
+
+ /* XXX we know the other bits are still clear */
+ FD_SET(sock, fds);
+ tv = delta; /* in case select() implements writeback */
+ switch (select(svc_maxfd + 1, fds, NULL, NULL, &tv)) {
+ case -1:
+ if (errno != EINTR)
+ goto fatal_err;
+ gettimeofday(&tmp1, NULL);
+ timersub(&tmp1, &start, &tmp2);
+ timersub(&wait_per_try, &tmp2, &tmp1);
+ if (tmp1.tv_sec < 0 || !timerisset(&tmp1))
+ goto fatal_err;
+ delta = tmp1;
+ continue;
+ case 0:
+ goto fatal_err;
+ default:
+ if (!FD_ISSET(sock, fds)) {
+ svc_getreqset2(fds, svc_maxfd + 1);
+ gettimeofday(&tmp1, NULL);
+ timersub(&tmp1, &start, &tmp2);
+ timersub(&wait_per_try, &tmp2, &tmp1);
+ if (tmp1.tv_sec < 0 || !timerisset(&tmp1))
+ goto fatal_err;
+ delta = tmp1;
+ continue;
+ }
+ }
+ } while (!FD_ISSET(sock, fds));
+ if ((len = _RPC_read(sock, buf, len)) > 0) {
+ if (fds != NULL)
+ free(fds);
+ return (len);
+ }
+fatal_err:
+ ((struct tcp_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED;
+ if (fds != NULL)
+ free(fds);
+ return (-1);
+}
+
+/*
+ * writes data to the tcp connection.
+ * Any error is fatal and the connection is closed.
+ */
+static int
+writetcp(xprt, buf, len)
+ register SVCXPRT *xprt;
+ caddr_t buf;
+ int len;
+{
+ register int i, cnt;
+
+ for (cnt = len; cnt > 0; cnt -= i, buf += i) {
+ if ((i = _RPC_write(xprt->xp_sock, buf, cnt)) < 0) {
+ ((struct tcp_conn *)(xprt->xp_p1))->strm_stat =
+ XPRT_DIED;
+ return (-1);
+ }
+ }
+ return (len);
+}
+
+static enum xprt_stat
+svctcp_stat(xprt)
+ SVCXPRT *xprt;
+{
+ register struct tcp_conn *cd =
+ (struct tcp_conn *)(xprt->xp_p1);
+
+ if (cd->strm_stat == XPRT_DIED)
+ return (XPRT_DIED);
+ if (! xdrrec_eof(&(cd->xdrs)))
+ return (XPRT_MOREREQS);
+ return (XPRT_IDLE);
+}
+
+static bool_t
+svctcp_recv(xprt, msg)
+ SVCXPRT *xprt;
+ register struct rpc_msg *msg;
+{
+ register struct tcp_conn *cd =
+ (struct tcp_conn *)(xprt->xp_p1);
+ register XDR *xdrs = &(cd->xdrs);
+
+ xdrs->x_op = XDR_DECODE;
+ (void)xdrrec_skiprecord(xdrs);
+ if (xdr_callmsg(xdrs, msg)) {
+ cd->x_id = msg->rm_xid;
+ return (TRUE);
+ }
+ cd->strm_stat = XPRT_DIED; /* XXXX */
+ return (FALSE);
+}
+
+static bool_t
+svctcp_getargs(xprt, xdr_args, args_ptr)
+ SVCXPRT *xprt;
+ xdrproc_t xdr_args;
+ caddr_t args_ptr;
+{
+
+ return ((*xdr_args)(&(((struct tcp_conn *)(xprt->xp_p1))->xdrs), args_ptr));
+}
+
+static bool_t
+svctcp_freeargs(xprt, xdr_args, args_ptr)
+ SVCXPRT *xprt;
+ xdrproc_t xdr_args;
+ caddr_t args_ptr;
+{
+ register XDR *xdrs =
+ &(((struct tcp_conn *)(xprt->xp_p1))->xdrs);
+
+ xdrs->x_op = XDR_FREE;
+ return ((*xdr_args)(xdrs, args_ptr));
+}
+
+static bool_t
+svctcp_reply(xprt, msg)
+ SVCXPRT *xprt;
+ register struct rpc_msg *msg;
+{
+ register struct tcp_conn *cd =
+ (struct tcp_conn *)(xprt->xp_p1);
+ register XDR *xdrs = &(cd->xdrs);
+ register bool_t stat;
+
+ xdrs->x_op = XDR_ENCODE;
+ msg->rm_xid = cd->x_id;
+ stat = xdr_replymsg(xdrs, msg);
+ (void)xdrrec_endofrecord(xdrs, TRUE);
+ return (stat);
+}
diff --git a/cpukit/librpc/src/rpc/svc_udp.c b/cpukit/librpc/src/rpc/svc_udp.c
new file mode 100644
index 0000000000..eb5736b23f
--- /dev/null
+++ b/cpukit/librpc/src/rpc/svc_udp.c
@@ -0,0 +1,479 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)svc_udp.c 1.24 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)svc_udp.c 2.2 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/rpc/svc_udp.c,v 1.13 2000/01/27 23:06:41 jasone Exp $";
+#endif
+
+/*
+ * svc_udp.c,
+ * Server side for UDP/IP based RPC. (Does some caching in the hopes of
+ * achieving execute-at-most-once semantics.)
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <sys/socket.h>
+#include <errno.h>
+
+#define rpc_buffer(xprt) ((xprt)->xp_p1)
+#define MAX(a, b) ((a > b) ? a : b)
+
+static bool_t svcudp_recv();
+static bool_t svcudp_reply();
+static enum xprt_stat svcudp_stat();
+static bool_t svcudp_getargs();
+static bool_t svcudp_freeargs();
+static void svcudp_destroy();
+static void cache_set __P((SVCXPRT *, u_long));
+static int cache_get __P((SVCXPRT *, struct rpc_msg *, char **, u_long *));
+
+static struct xp_ops svcudp_op = {
+ svcudp_recv,
+ svcudp_stat,
+ svcudp_getargs,
+ svcudp_reply,
+ svcudp_freeargs,
+ svcudp_destroy
+};
+
+/*
+ * kept in xprt->xp_p2
+ */
+struct svcudp_data {
+ u_int su_iosz; /* byte size of send.recv buffer */
+ u_long su_xid; /* transaction id */
+ XDR su_xdrs; /* XDR handle */
+ char su_verfbody[MAX_AUTH_BYTES]; /* verifier body */
+ char * su_cache; /* cached data, NULL if no cache */
+};
+#define su_data(xprt) ((struct svcudp_data *)(xprt->xp_p2))
+
+/*
+ * Usage:
+ * xprt = svcudp_create(sock);
+ *
+ * If sock<0 then a socket is created, else sock is used.
+ * If the socket, sock is not bound to a port then svcudp_create
+ * binds it to an arbitrary port. In any (successful) case,
+ * xprt->xp_sock is the registered socket number and xprt->xp_port is the
+ * associated port number.
+ * Once *xprt is initialized, it is registered as a transporter;
+ * see (svc.h, xprt_register).
+ * The routines returns NULL if a problem occurred.
+ */
+SVCXPRT *
+svcudp_bufcreate(sock, sendsz, recvsz)
+ register int sock;
+ u_int sendsz, recvsz;
+{
+ bool_t madesock = FALSE;
+ register SVCXPRT *xprt;
+ register struct svcudp_data *su;
+ struct sockaddr_in addr;
+ int len = sizeof(struct sockaddr_in);
+
+ if (sock == RPC_ANYSOCK) {
+ if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+ perror("svcudp_create: socket creation problem");
+ return ((SVCXPRT *)NULL);
+ }
+ madesock = TRUE;
+ }
+ memset((char *)&addr, 0, sizeof (addr));
+ addr.sin_len = sizeof(struct sockaddr_in);
+ addr.sin_family = AF_INET;
+ if (bindresvport(sock, &addr)) {
+ addr.sin_port = 0;
+ (void)bind(sock, (struct sockaddr *)&addr, len);
+ }
+ if (getsockname(sock, (struct sockaddr *)&addr, &len) != 0) {
+ perror("svcudp_create - cannot getsockname");
+ if (madesock)
+ (void)_RPC_close(sock);
+ return ((SVCXPRT *)NULL);
+ }
+ xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
+ if (xprt == NULL) {
+ (void)fprintf(stderr, "svcudp_create: out of memory\n");
+ return (NULL);
+ }
+ su = (struct svcudp_data *)mem_alloc(sizeof(*su));
+ if (su == NULL) {
+ (void)fprintf(stderr, "svcudp_create: out of memory\n");
+ return (NULL);
+ }
+ su->su_iosz = ((MAX(sendsz, recvsz) + 3) / 4) * 4;
+ if ((rpc_buffer(xprt) = mem_alloc(su->su_iosz)) == NULL) {
+ (void)fprintf(stderr, "svcudp_create: out of memory\n");
+ return (NULL);
+ }
+ xdrmem_create(
+ &(su->su_xdrs), rpc_buffer(xprt), su->su_iosz, XDR_DECODE);
+ su->su_cache = NULL;
+ xprt->xp_p2 = (caddr_t)su;
+ xprt->xp_verf.oa_base = su->su_verfbody;
+ xprt->xp_ops = &svcudp_op;
+ xprt->xp_port = ntohs(addr.sin_port);
+ xprt->xp_sock = sock;
+ xprt_register(xprt);
+ return (xprt);
+}
+
+SVCXPRT *
+svcudp_create(sock)
+ int sock;
+{
+
+ return(svcudp_bufcreate(sock, UDPMSGSIZE, UDPMSGSIZE));
+}
+
+static enum xprt_stat
+svcudp_stat(xprt)
+ SVCXPRT *xprt;
+{
+
+ return (XPRT_IDLE);
+}
+
+static bool_t
+svcudp_recv(xprt, msg)
+ register SVCXPRT *xprt;
+ struct rpc_msg *msg;
+{
+ register struct svcudp_data *su = su_data(xprt);
+ register XDR *xdrs = &(su->su_xdrs);
+ register int rlen;
+ char *reply;
+ u_long replylen;
+
+ again:
+ xprt->xp_addrlen = sizeof(struct sockaddr_in);
+ rlen = recvfrom(xprt->xp_sock, rpc_buffer(xprt), (int) su->su_iosz,
+ 0, (struct sockaddr *)&(xprt->xp_raddr), &(xprt->xp_addrlen));
+ if (rlen == -1 && errno == EINTR)
+ goto again;
+ if (rlen == -1 || rlen < 4*sizeof(u_int32_t))
+ return (FALSE);
+ xdrs->x_op = XDR_DECODE;
+ XDR_SETPOS(xdrs, 0);
+ if (! xdr_callmsg(xdrs, msg))
+ return (FALSE);
+ su->su_xid = msg->rm_xid;
+ if (su->su_cache != NULL) {
+ if (cache_get(xprt, msg, &reply, &replylen)) {
+ (void) sendto(xprt->xp_sock, reply, (int) replylen, 0,
+ (struct sockaddr *) &xprt->xp_raddr, xprt->xp_addrlen);
+ return (TRUE);
+ }
+ }
+ return (TRUE);
+}
+
+static bool_t
+svcudp_reply(xprt, msg)
+ register SVCXPRT *xprt;
+ struct rpc_msg *msg;
+{
+ register struct svcudp_data *su = su_data(xprt);
+ register XDR *xdrs = &(su->su_xdrs);
+ register int slen;
+ register bool_t stat = FALSE;
+
+ xdrs->x_op = XDR_ENCODE;
+ XDR_SETPOS(xdrs, 0);
+ msg->rm_xid = su->su_xid;
+ if (xdr_replymsg(xdrs, msg)) {
+ slen = (int)XDR_GETPOS(xdrs);
+ if (sendto(xprt->xp_sock, rpc_buffer(xprt), slen, 0,
+ (struct sockaddr *)&(xprt->xp_raddr), xprt->xp_addrlen)
+ == slen) {
+ stat = TRUE;
+ if (su->su_cache && slen >= 0) {
+ cache_set(xprt, (u_long) slen);
+ }
+ }
+ }
+ return (stat);
+}
+
+static bool_t
+svcudp_getargs(xprt, xdr_args, args_ptr)
+ SVCXPRT *xprt;
+ xdrproc_t xdr_args;
+ caddr_t args_ptr;
+{
+
+ return ((*xdr_args)(&(su_data(xprt)->su_xdrs), args_ptr));
+}
+
+static bool_t
+svcudp_freeargs(xprt, xdr_args, args_ptr)
+ SVCXPRT *xprt;
+ xdrproc_t xdr_args;
+ caddr_t args_ptr;
+{
+ register XDR *xdrs = &(su_data(xprt)->su_xdrs);
+
+ xdrs->x_op = XDR_FREE;
+ return ((*xdr_args)(xdrs, args_ptr));
+}
+
+static void
+svcudp_destroy(xprt)
+ register SVCXPRT *xprt;
+{
+ register struct svcudp_data *su = su_data(xprt);
+
+ xprt_unregister(xprt);
+ (void)_RPC_close(xprt->xp_sock);
+ XDR_DESTROY(&(su->su_xdrs));
+ mem_free(rpc_buffer(xprt), su->su_iosz);
+ mem_free((caddr_t)su, sizeof(struct svcudp_data));
+ mem_free((caddr_t)xprt, sizeof(SVCXPRT));
+}
+
+
+/***********this could be a separate file*********************/
+
+/*
+ * Fifo cache for udp server
+ * Copies pointers to reply buffers into fifo cache
+ * Buffers are sent again if retransmissions are detected.
+ */
+
+#define SPARSENESS 4 /* 75% sparse */
+
+#define CACHE_PERROR(msg) \
+ (void) fprintf(stderr,"%s\n", msg)
+
+#define ALLOC(type, size) \
+ (type *) mem_alloc((unsigned) (sizeof(type) * (size)))
+
+#define BZERO(addr, type, size) \
+ memset((char *) addr, 0, sizeof(type) * (int) (size))
+
+/*
+ * An entry in the cache
+ */
+typedef struct cache_node *cache_ptr;
+struct cache_node {
+ /*
+ * Index into cache is xid, proc, vers, prog and address
+ */
+ u_long cache_xid;
+ u_long cache_proc;
+ u_long cache_vers;
+ u_long cache_prog;
+ struct sockaddr_in cache_addr;
+ /*
+ * The cached reply and length
+ */
+ char * cache_reply;
+ u_long cache_replylen;
+ /*
+ * Next node on the list, if there is a collision
+ */
+ cache_ptr cache_next;
+};
+
+
+
+/*
+ * The entire cache
+ */
+struct udp_cache {
+ u_long uc_size; /* size of cache */
+ cache_ptr *uc_entries; /* hash table of entries in cache */
+ cache_ptr *uc_fifo; /* fifo list of entries in cache */
+ u_long uc_nextvictim; /* points to next victim in fifo list */
+ u_long uc_prog; /* saved program number */
+ u_long uc_vers; /* saved version number */
+ u_long uc_proc; /* saved procedure number */
+ struct sockaddr_in uc_addr; /* saved caller's address */
+};
+
+
+/*
+ * the hashing function
+ */
+#define CACHE_LOC(transp, xid) \
+ (xid % (SPARSENESS*((struct udp_cache *) su_data(transp)->su_cache)->uc_size))
+
+
+/*
+ * Enable use of the cache.
+ * Note: there is no disable.
+ */
+int svcudp_enablecache(transp, size)
+ SVCXPRT *transp;
+ u_long size;
+{
+ struct svcudp_data *su = su_data(transp);
+ struct udp_cache *uc;
+
+ if (su->su_cache != NULL) {
+ CACHE_PERROR("enablecache: cache already enabled");
+ return(0);
+ }
+ uc = ALLOC(struct udp_cache, 1);
+ if (uc == NULL) {
+ CACHE_PERROR("enablecache: could not allocate cache");
+ return(0);
+ }
+ uc->uc_size = size;
+ uc->uc_nextvictim = 0;
+ uc->uc_entries = ALLOC(cache_ptr, size * SPARSENESS);
+ if (uc->uc_entries == NULL) {
+ CACHE_PERROR("enablecache: could not allocate cache data");
+ return(0);
+ }
+ BZERO(uc->uc_entries, cache_ptr, size * SPARSENESS);
+ uc->uc_fifo = ALLOC(cache_ptr, size);
+ if (uc->uc_fifo == NULL) {
+ CACHE_PERROR("enablecache: could not allocate cache fifo");
+ return(0);
+ }
+ BZERO(uc->uc_fifo, cache_ptr, size);
+ su->su_cache = (char *) uc;
+ return(1);
+}
+
+
+/*
+ * Set an entry in the cache
+ */
+static void
+cache_set(xprt, replylen)
+ SVCXPRT *xprt;
+ u_long replylen;
+{
+ register cache_ptr victim;
+ register cache_ptr *vicp;
+ register struct svcudp_data *su = su_data(xprt);
+ struct udp_cache *uc = (struct udp_cache *) su->su_cache;
+ u_int loc;
+ char *newbuf;
+
+ /*
+ * Find space for the new entry, either by
+ * reusing an old entry, or by mallocing a new one
+ */
+ victim = uc->uc_fifo[uc->uc_nextvictim];
+ if (victim != NULL) {
+ loc = CACHE_LOC(xprt, victim->cache_xid);
+ for (vicp = &uc->uc_entries[loc];
+ *vicp != NULL && *vicp != victim;
+ vicp = &(*vicp)->cache_next)
+ ;
+ if (*vicp == NULL) {
+ CACHE_PERROR("cache_set: victim not found");
+ return;
+ }
+ *vicp = victim->cache_next; /* remote from cache */
+ newbuf = victim->cache_reply;
+ } else {
+ victim = ALLOC(struct cache_node, 1);
+ if (victim == NULL) {
+ CACHE_PERROR("cache_set: victim alloc failed");
+ return;
+ }
+ newbuf = mem_alloc(su->su_iosz);
+ if (newbuf == NULL) {
+ CACHE_PERROR("cache_set: could not allocate new rpc_buffer");
+ return;
+ }
+ }
+
+ /*
+ * Store it away
+ */
+ victim->cache_replylen = replylen;
+ victim->cache_reply = rpc_buffer(xprt);
+ rpc_buffer(xprt) = newbuf;
+ xdrmem_create(&(su->su_xdrs), rpc_buffer(xprt), su->su_iosz, XDR_ENCODE);
+ victim->cache_xid = su->su_xid;
+ victim->cache_proc = uc->uc_proc;
+ victim->cache_vers = uc->uc_vers;
+ victim->cache_prog = uc->uc_prog;
+ victim->cache_addr = uc->uc_addr;
+ loc = CACHE_LOC(xprt, victim->cache_xid);
+ victim->cache_next = uc->uc_entries[loc];
+ uc->uc_entries[loc] = victim;
+ uc->uc_fifo[uc->uc_nextvictim++] = victim;
+ uc->uc_nextvictim %= uc->uc_size;
+}
+
+/*
+ * Try to get an entry from the cache
+ * return 1 if found, 0 if not found
+ */
+static int
+cache_get(xprt, msg, replyp, replylenp)
+ SVCXPRT *xprt;
+ struct rpc_msg *msg;
+ char **replyp;
+ u_long *replylenp;
+{
+ u_int loc;
+ register cache_ptr ent;
+ register struct svcudp_data *su = su_data(xprt);
+ register struct udp_cache *uc = (struct udp_cache *) su->su_cache;
+
+# define EQADDR(a1, a2) (memcmp(&a1, &a2, sizeof(a1)) == 0)
+
+ loc = CACHE_LOC(xprt, su->su_xid);
+ for (ent = uc->uc_entries[loc]; ent != NULL; ent = ent->cache_next) {
+ if (ent->cache_xid == su->su_xid &&
+ ent->cache_proc == uc->uc_proc &&
+ ent->cache_vers == uc->uc_vers &&
+ ent->cache_prog == uc->uc_prog &&
+ EQADDR(ent->cache_addr, uc->uc_addr)) {
+ *replyp = ent->cache_reply;
+ *replylenp = ent->cache_replylen;
+ return(1);
+ }
+ }
+ /*
+ * Failed to find entry
+ * Remember a few things so we can do a set later
+ */
+ uc->uc_proc = msg->rm_call.cb_proc;
+ uc->uc_vers = msg->rm_call.cb_vers;
+ uc->uc_prog = msg->rm_call.cb_prog;
+ uc->uc_addr = xprt->xp_raddr;
+ return(0);
+}
diff --git a/cpukit/librpc/src/rpc/svc_unix.c b/cpukit/librpc/src/rpc/svc_unix.c
new file mode 100644
index 0000000000..53772ecd4a
--- /dev/null
+++ b/cpukit/librpc/src/rpc/svc_unix.c
@@ -0,0 +1,527 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)svc_unix.c 1.21 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)svc_unix.c 2.2 88/08/01 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/rpc/svc_unix.c,v 1.7 2000/01/27 23:06:42 jasone Exp $";
+#endif
+
+/*
+ * svc_unix.c, Server side for TCP/IP based RPC.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * Actually implements two flavors of transporter -
+ * a unix rendezvouser (a listner and connection establisher)
+ * and a record/unix stream.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/uio.h>
+#include <errno.h>
+
+/*
+ * Ops vector for AF_UNIX based rpc service handle
+ */
+static bool_t svcunix_recv();
+static enum xprt_stat svcunix_stat();
+static bool_t svcunix_getargs();
+static bool_t svcunix_reply();
+static bool_t svcunix_freeargs();
+static void svcunix_destroy();
+
+static struct xp_ops svcunix_op = {
+ svcunix_recv,
+ svcunix_stat,
+ svcunix_getargs,
+ svcunix_reply,
+ svcunix_freeargs,
+ svcunix_destroy
+};
+
+/*
+ * Ops vector for TCP/IP rendezvous handler
+ */
+static bool_t rendezvous_request();
+static enum xprt_stat rendezvous_stat();
+
+static struct xp_ops svcunix_rendezvous_op = {
+ rendezvous_request,
+ rendezvous_stat,
+ (bool_t (*)())abort,
+ (bool_t (*)())abort,
+ (bool_t (*)())abort,
+ svcunix_destroy
+};
+
+static int readunix(), writeunix();
+static SVCXPRT *makefd_xprt();
+
+struct unix_rendezvous { /* kept in xprt->xp_p1 */
+ u_int sendsize;
+ u_int recvsize;
+};
+
+struct unix_conn { /* kept in xprt->xp_p1 */
+ enum xprt_stat strm_stat;
+ u_long x_id;
+ XDR xdrs;
+ char verf_body[MAX_AUTH_BYTES];
+};
+
+
+struct cmessage {
+ struct cmsghdr cmsg;
+ struct cmsgcred cmcred;
+};
+
+static struct cmessage cm;
+
+static int __msgread(sock, buf, cnt)
+ int sock;
+ void *buf;
+ size_t cnt;
+{
+ struct iovec iov[1];
+ struct msghdr msg;
+
+ bzero((char *)&cm, sizeof(cm));
+ iov[0].iov_base = buf;
+ iov[0].iov_len = cnt;
+
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_control = (caddr_t)&cm;
+ msg.msg_controllen = sizeof(struct cmessage);
+ msg.msg_flags = 0;
+
+ return(recvmsg(sock, &msg, 0));
+}
+
+static int __msgwrite(sock, buf, cnt)
+ int sock;
+ void *buf;
+ size_t cnt;
+{
+ struct iovec iov[1];
+ struct msghdr msg;
+
+ bzero((char *)&cm, sizeof(cm));
+ iov[0].iov_base = buf;
+ iov[0].iov_len = cnt;
+
+ cm.cmsg.cmsg_type = SCM_CREDS;
+ cm.cmsg.cmsg_level = SOL_SOCKET;
+ cm.cmsg.cmsg_len = sizeof(struct cmessage);
+
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_control = (caddr_t)&cm;
+ msg.msg_controllen = sizeof(struct cmessage);
+ msg.msg_flags = 0;
+
+ return(sendmsg(sock, &msg, 0));
+}
+
+/*
+ * Usage:
+ * xprt = svcunix_create(sock, send_buf_size, recv_buf_size);
+ *
+ * Creates, registers, and returns a (rpc) unix based transporter.
+ * Once *xprt is initialized, it is registered as a transporter
+ * see (svc.h, xprt_register). This routine returns
+ * a NULL if a problem occurred.
+ *
+ * If sock<0 then a socket is created, else sock is used.
+ * If the socket, sock is not bound to a port then svcunix_create
+ * binds it to an arbitrary port. The routine then starts a unix
+ * listener on the socket's associated port. In any (successful) case,
+ * xprt->xp_sock is the registered socket number and xprt->xp_port is the
+ * associated port number.
+ *
+ * Since unix streams do buffered io similar to stdio, the caller can specify
+ * how big the send and receive buffers are via the second and third parms;
+ * 0 => use the system default.
+ */
+SVCXPRT *
+svcunix_create(sock, sendsize, recvsize, path)
+ register int sock;
+ u_int sendsize;
+ u_int recvsize;
+ char *path;
+{
+ bool_t madesock = FALSE;
+ register SVCXPRT *xprt;
+ register struct unix_rendezvous *r;
+ struct sockaddr_un addr;
+ int len = sizeof(struct sockaddr_un);
+
+ if (sock == RPC_ANYSOCK) {
+ if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
+ perror("svc_unix.c - AF_UNIX socket creation problem");
+ return ((SVCXPRT *)NULL);
+ }
+ madesock = TRUE;
+ }
+ memset(&addr, 0, sizeof (addr));
+ addr.sun_family = AF_UNIX;
+ strcpy(addr.sun_path, path);
+ len = strlen(addr.sun_path) + sizeof(addr.sun_family) +
+ sizeof(addr.sun_len) + 1;
+ addr.sun_len = len;
+
+ bind(sock, (struct sockaddr *)&addr, len);
+
+ if ((getsockname(sock, (struct sockaddr *)&addr, &len) != 0) ||
+ (listen(sock, 2) != 0)) {
+ perror("svc_unix.c - cannot getsockname or listen");
+ if (madesock)
+ (void)_RPC_close(sock);
+ return ((SVCXPRT *)NULL);
+ }
+ r = (struct unix_rendezvous *)mem_alloc(sizeof(*r));
+ if (r == NULL) {
+ (void) fprintf(stderr, "svcunix_create: out of memory\n");
+ return (NULL);
+ }
+ r->sendsize = sendsize;
+ r->recvsize = recvsize;
+ xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
+ if (xprt == NULL) {
+ (void) fprintf(stderr, "svcunix_create: out of memory\n");
+ return (NULL);
+ }
+ xprt->xp_p2 = NULL;
+ xprt->xp_p1 = (caddr_t)r;
+ xprt->xp_verf = _null_auth;
+ xprt->xp_ops = &svcunix_rendezvous_op;
+ xprt->xp_port = -1 /*ntohs(addr.sin_port)*/;
+ xprt->xp_sock = sock;
+ xprt_register(xprt);
+ return (xprt);
+}
+
+/*
+ * Like svunix_create(), except the routine takes any *open* UNIX file
+ * descriptor as its first input.
+ */
+SVCXPRT *
+svcunixfd_create(fd, sendsize, recvsize)
+ int fd;
+ u_int sendsize;
+ u_int recvsize;
+{
+
+ return (makefd_xprt(fd, sendsize, recvsize));
+}
+
+static SVCXPRT *
+makefd_xprt(fd, sendsize, recvsize)
+ int fd;
+ u_int sendsize;
+ u_int recvsize;
+{
+ register SVCXPRT *xprt;
+ register struct unix_conn *cd;
+
+ xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
+ if (xprt == (SVCXPRT *)NULL) {
+ (void) fprintf(stderr, "svc_unix: makefd_xprt: out of memory\n");
+ goto done;
+ }
+ cd = (struct unix_conn *)mem_alloc(sizeof(struct unix_conn));
+ if (cd == (struct unix_conn *)NULL) {
+ (void) fprintf(stderr, "svc_unix: makefd_xprt: out of memory\n");
+ mem_free((char *) xprt, sizeof(SVCXPRT));
+ xprt = (SVCXPRT *)NULL;
+ goto done;
+ }
+ cd->strm_stat = XPRT_IDLE;
+ xdrrec_create(&(cd->xdrs), sendsize, recvsize,
+ (caddr_t)xprt, readunix, writeunix);
+ xprt->xp_p2 = NULL;
+ xprt->xp_p1 = (caddr_t)cd;
+ xprt->xp_verf.oa_base = cd->verf_body;
+ xprt->xp_addrlen = 0;
+ xprt->xp_ops = &svcunix_op; /* truely deals with calls */
+ xprt->xp_port = 0; /* this is a connection, not a rendezvouser */
+ xprt->xp_sock = fd;
+ xprt_register(xprt);
+ done:
+ return (xprt);
+}
+
+static bool_t
+rendezvous_request(xprt)
+ register SVCXPRT *xprt;
+{
+ int sock;
+ struct unix_rendezvous *r;
+ struct sockaddr_un addr;
+ struct sockaddr_in in_addr;
+ int len;
+
+ r = (struct unix_rendezvous *)xprt->xp_p1;
+ again:
+ len = sizeof(struct sockaddr_in);
+ if ((sock = accept(xprt->xp_sock, (struct sockaddr *)&addr,
+ &len)) < 0) {
+ if (errno == EINTR)
+ goto again;
+ return (FALSE);
+ }
+
+ /*
+ * make a new transporter (re-uses xprt)
+ */
+ bzero((char *)&in_addr, sizeof(in_addr));
+ in_addr.sin_family = AF_UNIX;
+ xprt = makefd_xprt(sock, r->sendsize, r->recvsize);
+ xprt->xp_raddr = in_addr;
+ xprt->xp_addrlen = len;
+ return (FALSE); /* there is never an rpc msg to be processed */
+}
+
+static enum xprt_stat
+rendezvous_stat()
+{
+
+ return (XPRT_IDLE);
+}
+
+static void
+svcunix_destroy(xprt)
+ register SVCXPRT *xprt;
+{
+ register struct unix_conn *cd = (struct unix_conn *)xprt->xp_p1;
+
+ xprt_unregister(xprt);
+ (void)_RPC_close(xprt->xp_sock);
+ if (xprt->xp_port != 0) {
+ /* a rendezvouser socket */
+ xprt->xp_port = 0;
+ } else {
+ /* an actual connection socket */
+ XDR_DESTROY(&(cd->xdrs));
+ }
+ mem_free((caddr_t)cd, sizeof(struct unix_conn));
+ mem_free((caddr_t)xprt, sizeof(SVCXPRT));
+}
+
+/*
+ * All read operations timeout after 35 seconds.
+ * A timeout is fatal for the connection.
+ */
+static struct timeval wait_per_try = { 35, 0 };
+
+/*
+ * reads data from the unix conection.
+ * any error is fatal and the connection is closed.
+ * (And a read of zero bytes is a half closed stream => error.)
+ *
+ * Note: we have to be careful here not to allow ourselves to become
+ * blocked too long in this routine. While we're waiting for data from one
+ * client, another client may be trying to connect. To avoid this situation,
+ * some code from svc_run() is transplanted here: the select() loop checks
+ * all RPC descriptors including the one we want and calls svc_getreqset2()
+ * to handle new requests if any are detected.
+ */
+static int
+readunix(xprt, buf, len)
+ register SVCXPRT *xprt;
+ caddr_t buf;
+ register int len;
+{
+ register int sock = xprt->xp_sock;
+ struct timeval start, delta, tv;
+ struct timeval tmp1, tmp2;
+ fd_set *fds;
+
+ delta = wait_per_try;
+ fds = NULL;
+ gettimeofday(&start, NULL);
+ do {
+ int bytes = sizeof (fd_set);
+ if (fds != NULL)
+ free(fds);
+ fds = (fd_set *)malloc(bytes);
+ if (fds == NULL)
+ goto fatal_err;
+ memcpy(fds, __svc_fdset, bytes);
+
+ /* XXX we know the other bits are still clear */
+ FD_SET(sock, fds);
+ tv = delta; /* in case select() implements writeback */
+ switch (select(svc_maxfd + 1, fds, NULL, NULL, &tv)) {
+ case -1:
+ if (errno != EINTR)
+ goto fatal_err;
+ gettimeofday(&tmp1, NULL);
+ timersub(&tmp1, &start, &tmp2);
+ timersub(&wait_per_try, &tmp2, &tmp1);
+ if (tmp1.tv_sec < 0 || !timerisset(&tmp1))
+ goto fatal_err;
+ delta = tmp1;
+ continue;
+ case 0:
+ goto fatal_err;
+ default:
+ if (!FD_ISSET(sock, fds)) {
+ svc_getreqset2(fds, svc_maxfd + 1);
+ gettimeofday(&tmp1, NULL);
+ timersub(&tmp1, &start, &tmp2);
+ timersub(&wait_per_try, &tmp2, &tmp1);
+ if (tmp1.tv_sec < 0 || !timerisset(&tmp1))
+ goto fatal_err;
+ delta = tmp1;
+ continue;
+ }
+ }
+ } while (!FD_ISSET(sock, fds));
+ if ((len = __msgread(sock, buf, len)) > 0) {
+ if (fds != NULL)
+ free(fds);
+ return (len);
+ }
+fatal_err:
+ ((struct unix_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED;
+ if (fds != NULL)
+ free(fds);
+ return (-1);
+}
+
+/*
+ * writes data to the unix connection.
+ * Any error is fatal and the connection is closed.
+ */
+static int
+writeunix(xprt, buf, len)
+ register SVCXPRT *xprt;
+ caddr_t buf;
+ int len;
+{
+ register int i, cnt;
+
+ for (cnt = len; cnt > 0; cnt -= i, buf += i) {
+ if ((i = __msgwrite(xprt->xp_sock, buf, cnt)) < 0) {
+ ((struct unix_conn *)(xprt->xp_p1))->strm_stat =
+ XPRT_DIED;
+ return (-1);
+ }
+ }
+ return (len);
+}
+
+static enum xprt_stat
+svcunix_stat(xprt)
+ SVCXPRT *xprt;
+{
+ register struct unix_conn *cd =
+ (struct unix_conn *)(xprt->xp_p1);
+
+ if (cd->strm_stat == XPRT_DIED)
+ return (XPRT_DIED);
+ if (! xdrrec_eof(&(cd->xdrs)))
+ return (XPRT_MOREREQS);
+ return (XPRT_IDLE);
+}
+
+static bool_t
+svcunix_recv(xprt, msg)
+ SVCXPRT *xprt;
+ register struct rpc_msg *msg;
+{
+ register struct unix_conn *cd =
+ (struct unix_conn *)(xprt->xp_p1);
+ register XDR *xdrs = &(cd->xdrs);
+
+ xdrs->x_op = XDR_DECODE;
+ (void)xdrrec_skiprecord(xdrs);
+ if (xdr_callmsg(xdrs, msg)) {
+ cd->x_id = msg->rm_xid;
+ /* set up verifiers */
+ msg->rm_call.cb_verf.oa_flavor = AUTH_UNIX;
+ msg->rm_call.cb_verf.oa_base = (caddr_t)&cm;
+ msg->rm_call.cb_verf.oa_length = sizeof(cm);
+ return (TRUE);
+ }
+ cd->strm_stat = XPRT_DIED; /* XXXX */
+ return (FALSE);
+}
+
+static bool_t
+svcunix_getargs(xprt, xdr_args, args_ptr)
+ SVCXPRT *xprt;
+ xdrproc_t xdr_args;
+ caddr_t args_ptr;
+{
+
+ return ((*xdr_args)(&(((struct unix_conn *)(xprt->xp_p1))->xdrs), args_ptr));
+}
+
+static bool_t
+svcunix_freeargs(xprt, xdr_args, args_ptr)
+ SVCXPRT *xprt;
+ xdrproc_t xdr_args;
+ caddr_t args_ptr;
+{
+ register XDR *xdrs =
+ &(((struct unix_conn *)(xprt->xp_p1))->xdrs);
+
+ xdrs->x_op = XDR_FREE;
+ return ((*xdr_args)(xdrs, args_ptr));
+}
+
+static bool_t
+svcunix_reply(xprt, msg)
+ SVCXPRT *xprt;
+ register struct rpc_msg *msg;
+{
+ register struct unix_conn *cd =
+ (struct unix_conn *)(xprt->xp_p1);
+ register XDR *xdrs = &(cd->xdrs);
+ register bool_t stat;
+
+ xdrs->x_op = XDR_ENCODE;
+ msg->rm_xid = cd->x_id;
+ stat = xdr_replymsg(xdrs, msg);
+ (void)xdrrec_endofrecord(xdrs, TRUE);
+ return (stat);
+}
diff --git a/cpukit/librpc/src/xdr/xdr.3 b/cpukit/librpc/src/xdr/xdr.3
new file mode 100644
index 0000000000..c1cdb11015
--- /dev/null
+++ b/cpukit/librpc/src/xdr/xdr.3
@@ -0,0 +1,837 @@
+.\" @(#)xdr.3n 2.2 88/08/03 4.0 RPCSRC; from 1.16 88/03/14 SMI
+.\" $FreeBSD: src/lib/libc/xdr/xdr.3,v 1.8 2000/03/02 09:14:05 sheldonh Exp $
+.\"
+.TH XDR 3 "16 February 1988"
+.SH NAME
+xdr \- library routines for external data representation
+.SH SYNOPSIS AND DESCRIPTION
+.LP
+These routines allow C programmers to describe
+arbitrary data structures in a machine-independent fashion.
+Data for remote procedure calls are transmitted using these
+routines.
+.LP
+.ft B
+.nf
+.sp .5
+xdr_array(xdrs, arrp, sizep, maxsize, elsize, elproc)
+\s-1XDR\s0 *xdrs;
+char **arrp;
+u_int *sizep, maxsize, elsize;
+xdrproc_t elproc;
+.fi
+.ft R
+.IP
+A filter primitive that translates between variable-length
+arrays
+and their corresponding external representations.
+The
+parameter
+.I arrp
+is the address of the pointer to the array, while
+.I sizep
+is the address of the element count of the array;
+this element count cannot exceed
+.IR maxsize .
+The parameter
+.I elsize
+is the
+.I sizeof
+each of the array's elements, and
+.I elproc
+is an
+.SM XDR
+filter that translates between
+the array elements' C form, and their external
+representation.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+xdr_bool(xdrs, bp)
+\s-1XDR\s0 *xdrs;
+bool_t *bp;
+.fi
+.ft R
+.IP
+A filter primitive that translates between booleans (C
+integers)
+and their external representations.
+When encoding data, this
+filter produces values of either one or zero.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+xdr_bytes(xdrs, sp, sizep, maxsize)
+\s-1XDR\s0 *xdrs;
+char **sp;
+u_int *sizep, maxsize;
+.fi
+.ft R
+.IP
+A filter primitive that translates between counted byte
+strings and their external representations.
+The parameter
+.I sp
+is the address of the string pointer.
+The length of the
+string is located at address
+.IR sizep ;
+strings cannot be longer than
+.IR maxsize .
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_char(xdrs, cp)
+\s-1XDR\s0 *xdrs;
+char *cp;
+.fi
+.ft R
+.IP
+A filter primitive that translates between C characters
+and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+Note: encoded characters are not packed, and occupy 4 bytes
+each.
+For arrays of characters, it is worthwhile to
+consider
+.BR xdr_bytes(\|) ,
+.B xdr_opaque(\|)
+or
+.BR xdr_string(\|) .
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+void
+xdr_destroy(xdrs)
+\s-1XDR\s0 *xdrs;
+.fi
+.ft R
+.IP
+A macro that invokes the destroy routine associated with the
+.SM XDR
+stream,
+.IR xdrs .
+Destruction usually involves freeing private data structures
+associated with the stream. Using
+.I xdrs
+after invoking
+.B xdr_destroy(\|)
+is undefined.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_double(xdrs, dp)
+\s-1XDR\s0 *xdrs;
+double *dp;
+.fi
+.ft R
+.IP
+A filter primitive that translates between C
+.B double
+precision numbers and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_enum(xdrs, ep)
+\s-1XDR\s0 *xdrs;
+enum_t *ep;
+.fi
+.ft R
+.IP
+A filter primitive that translates between C
+.BR enum s
+(actually integers) and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+xdr_float(xdrs, fp)
+\s-1XDR\s0 *xdrs;
+float *fp;
+.fi
+.ft R
+.IP
+A filter primitive that translates between C
+.BR float s
+and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+void
+xdr_free(proc, objp)
+xdrproc_t proc;
+char *objp;
+.fi
+.ft R
+.IP
+Generic freeing routine.
+The first argument is the
+.SM XDR
+routine for the object being freed.
+The second argument
+is a pointer to the object itself.
+Note: the pointer passed
+to this routine is
+.I not
+freed, but what it points to
+.I is
+freed (recursively).
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+u_int
+xdr_getpos(xdrs)
+\s-1XDR\s0 *xdrs;
+.fi
+.ft R
+.IP
+A macro that invokes the get-position routine
+associated with the
+.SM XDR
+stream,
+.IR xdrs .
+The routine returns an unsigned integer,
+which indicates the position of the
+.SM XDR
+byte stream.
+A desirable feature of
+.SM XDR
+streams is that simple arithmetic works with this number,
+although the
+.SM XDR
+stream instances need not guarantee this.
+.br
+.if t .ne 4
+.LP
+.ft B
+.nf
+.sp .5
+.br
+long *
+xdr_inline(xdrs, len)
+\s-1XDR\s0 *xdrs;
+int len;
+.fi
+.ft R
+.IP
+A macro that invokes the in-line routine associated with the
+.SM XDR
+stream,
+.IR xdrs .
+The routine returns a pointer
+to a contiguous piece of the stream's buffer;
+.I len
+is the byte length of the desired buffer.
+Note: pointer is cast to
+.BR "long *" .
+.IP
+Warning:
+.B xdr_inline(\|)
+may return
+.SM NULL
+(0)
+if it cannot allocate a contiguous piece of a buffer.
+Therefore the behavior may vary among stream instances;
+it exists for the sake of efficiency.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_int(xdrs, ip)
+\s-1XDR\s0 *xdrs;
+int *ip;
+.fi
+.ft R
+.IP
+A filter primitive that translates between C integers
+and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_long(xdrs, lp)
+\s-1XDR\s0 *xdrs;
+long *lp;
+.fi
+.ft R
+.IP
+A filter primitive that translates between C
+.B long
+integers and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 12
+.LP
+.ft B
+.nf
+.sp .5
+void
+xdrmem_create(xdrs, addr, size, op)
+\s-1XDR\s0 *xdrs;
+char *addr;
+u_int size;
+enum xdr_op op;
+.fi
+.ft R
+.IP
+This routine initializes the
+.SM XDR
+stream object pointed to by
+.IR xdrs .
+The stream's data is written to, or read from,
+a chunk of memory at location
+.I addr
+whose length is no more than
+.I size
+bytes long. The
+.I op
+determines the direction of the
+.SM XDR
+stream
+(either
+.BR \s-1XDR_ENCODE\s0 ,
+.BR \s-1XDR_DECODE\s0 ,
+or
+.BR \s-1XDR_FREE\s0 ).
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+xdr_opaque(xdrs, cp, cnt)
+\s-1XDR\s0 *xdrs;
+char *cp;
+u_int cnt;
+.fi
+.ft R
+.IP
+A filter primitive that translates between fixed size opaque
+data
+and its external representation.
+The parameter
+.I cp
+is the address of the opaque object, and
+.I cnt
+is its size in bytes.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+xdr_pointer(xdrs, objpp, objsize, xdrobj)
+\s-1XDR\s0 *xdrs;
+char **objpp;
+u_int objsize;
+xdrproc_t xdrobj;
+.fi
+.ft R
+.IP
+Like
+.B xdr_reference(\|)
+execpt that it serializes
+.SM NULL
+pointers, whereas
+.B xdr_reference(\|)
+does not. Thus,
+.B xdr_pointer(\|)
+can represent
+recursive data structures, such as binary trees or
+linked lists.
+.br
+.if t .ne 15
+.LP
+.ft B
+.nf
+.sp .5
+void
+xdrrec_create(xdrs, sendsize, recvsize, handle, readit, writeit)
+\s-1XDR\s0 *xdrs;
+u_int sendsize, recvsize;
+char *handle;
+int (*readit) (\|), (*writeit) (\|);
+.fi
+.ft R
+.IP
+This routine initializes the
+.SM XDR
+stream object pointed to by
+.IR xdrs .
+The stream's data is written to a buffer of size
+.IR sendsize ;
+a value of zero indicates the system should use a suitable
+default.
+The stream's data is read from a buffer of size
+.IR recvsize ;
+it too can be set to a suitable default by passing a zero
+value.
+When a stream's output buffer is full,
+.I writeit
+is called. Similarly, when a stream's input buffer is empty,
+.I readit
+is called. The behavior of these two routines is similar to
+the
+system calls
+.B read
+and
+.BR write ,
+except that
+.I handle
+is passed to the former routines as the first parameter.
+Note: the
+.SM XDR
+stream's
+.I op
+field must be set by the caller.
+.IP
+Warning: this
+.SM XDR
+stream implements an intermediate record stream.
+Therefore there are additional bytes in the stream
+to provide record boundary information.
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+xdrrec_endofrecord(xdrs, sendnow)
+\s-1XDR\s0 *xdrs;
+int sendnow;
+.fi
+.ft R
+.IP
+This routine can be invoked only on
+streams created by
+.BR xdrrec_create(\|) .
+The data in the output buffer is marked as a completed
+record,
+and the output buffer is optionally written out if
+.I sendnow
+is non-zero.
+This routine returns one if it succeeds, zero
+otherwise.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+xdrrec_eof(xdrs)
+\s-1XDR\s0 *xdrs;
+int empty;
+.fi
+.ft R
+.IP
+This routine can be invoked only on
+streams created by
+.BR xdrrec_create(\|) .
+After consuming the rest of the current record in the stream,
+this routine returns one if the stream has no more input,
+zero otherwise.
+.br
+.if t .ne 3
+.LP
+.ft B
+.nf
+.sp .5
+xdrrec_skiprecord(xdrs)
+\s-1XDR\s0 *xdrs;
+.fi
+.ft R
+.IP
+This routine can be invoked only on
+streams created by
+.BR xdrrec_create(\|) .
+It tells the
+.SM XDR
+implementation that the rest of the current record
+in the stream's input buffer should be discarded.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 11
+.LP
+.ft B
+.nf
+.sp .5
+xdr_reference(xdrs, pp, size, proc)
+\s-1XDR\s0 *xdrs;
+char **pp;
+u_int size;
+xdrproc_t proc;
+.fi
+.ft R
+.IP
+A primitive that provides pointer chasing within structures.
+The parameter
+.I pp
+is the address of the pointer;
+.I size
+is the
+.I sizeof
+the structure that
+.I *pp
+points to; and
+.I proc
+is an
+.SM XDR
+procedure that filters the structure
+between its C form and its external representation.
+This routine returns one if it succeeds, zero otherwise.
+.IP
+Warning: this routine does not understand
+.SM NULL
+pointers.
+Use
+.B xdr_pointer(\|)
+instead.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+xdr_setpos(xdrs, pos)
+\s-1XDR\s0 *xdrs;
+u_int pos;
+.fi
+.ft R
+.IP
+A macro that invokes the set position routine associated with
+the
+.SM XDR
+stream
+.IR xdrs .
+The parameter
+.I pos
+is a position value obtained from
+.BR xdr_getpos(\|) .
+This routine returns one if the
+.SM XDR
+stream could be repositioned,
+and zero otherwise.
+.IP
+Warning: it is difficult to reposition some types of
+.SM XDR
+streams, so this routine may fail with one
+type of stream and succeed with another.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+xdr_short(xdrs, sp)
+\s-1XDR\s0 *xdrs;
+short *sp;
+.fi
+.ft R
+.IP
+A filter primitive that translates between C
+.B short
+integers and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+void
+xdrstdio_create(xdrs, file, op)
+\s-1XDR\s0 *xdrs;
+\s-1FILE\s0 *file;
+enum xdr_op op;
+.fi
+.ft R
+.IP
+This routine initializes the
+.SM XDR
+stream object pointed to by
+.IR xdrs .
+The
+.SM XDR
+stream data is written to, or read from, the Standard
+.B I/O
+stream
+.IR file .
+The parameter
+.I op
+determines the direction of the
+.SM XDR
+stream (either
+.BR \s-1XDR_ENCODE\s0 ,
+.BR \s-1XDR_DECODE\s0 ,
+or
+.BR \s-1XDR_FREE\s0 ).
+.IP
+Warning: the destroy routine associated with such
+.SM XDR
+streams calls
+.B fflush(\|)
+on the
+.I file
+stream, but never
+.BR fclose(\|) .
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+xdr_string(xdrs, sp, maxsize)
+\s-1XDR\s0
+*xdrs;
+char **sp;
+u_int maxsize;
+.fi
+.ft R
+.IP
+A filter primitive that translates between C strings and
+their
+corresponding external representations.
+Strings cannot be longer than
+.IR maxsize .
+Note:
+.I sp
+is the address of the string's pointer.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+xdr_u_char(xdrs, ucp)
+\s-1XDR\s0 *xdrs;
+unsigned char *ucp;
+.fi
+.ft R
+.IP
+A filter primitive that translates between
+.B unsigned
+C characters and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+xdr_u_int(xdrs, up)
+\s-1XDR\s0 *xdrs;
+unsigned *up;
+.fi
+.ft R
+.IP
+A filter primitive that translates between C
+.B unsigned
+integers and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_u_long(xdrs, ulp)
+\s-1XDR\s0 *xdrs;
+unsigned long *ulp;
+.fi
+.ft R
+.IP
+A filter primitive that translates between C
+.B "unsigned long"
+integers and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_u_short(xdrs, usp)
+\s-1XDR\s0 *xdrs;
+unsigned short *usp;
+.fi
+.ft R
+.IP
+A filter primitive that translates between C
+.B "unsigned short"
+integers and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 16
+.LP
+.ft B
+.nf
+.sp .5
+xdr_union(xdrs, dscmp, unp, choices, dfault)
+\s-1XDR\s0 *xdrs;
+int *dscmp;
+char *unp;
+struct xdr_discrim *choices;
+bool_t (*defaultarm) (\|); /* may equal \s-1NULL\s0 */
+.fi
+.ft R
+.IP
+A filter primitive that translates between a discriminated C
+.B union
+and its corresponding external representation.
+It first
+translates the discriminant of the union located at
+.IR dscmp .
+This discriminant is always an
+.BR enum_t .
+Next the union located at
+.I unp
+is translated. The parameter
+.I choices
+is a pointer to an array of
+.B xdr_discrim(\|)
+structures.
+Each structure contains an ordered pair of
+.RI [ value , proc ].
+If the union's discriminant is equal to the associated
+.IR value ,
+then the
+.I proc
+is called to translate the union. The end of the
+.B xdr_discrim(\|)
+structure array is denoted by a routine of value
+.SM NULL\s0.
+If the discriminant is not found in the
+.I choices
+array, then the
+.I defaultarm
+procedure is called (if it is not
+.SM NULL\s0).
+Returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 6
+.LP
+.ft B
+.nf
+.sp .5
+xdr_vector(xdrs, arrp, size, elsize, elproc)
+\s-1XDR\s0 *xdrs;
+char *arrp;
+u_int size, elsize;
+xdrproc_t elproc;
+.fi
+.ft R
+.IP
+A filter primitive that translates between fixed-length
+arrays
+and their corresponding external representations. The
+parameter
+.I arrp
+is the address of the pointer to the array, while
+.I size
+is the element count of the array. The parameter
+.I elsize
+is the
+.I sizeof
+each of the array's elements, and
+.I elproc
+is an
+.SM XDR
+filter that translates between
+the array elements' C form, and their external
+representation.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 5
+.LP
+.ft B
+.nf
+.sp .5
+xdr_void(\|)
+.fi
+.ft R
+.IP
+This routine always returns one.
+It may be passed to
+.SM RPC
+routines that require a function parameter,
+where nothing is to be done.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+xdr_wrapstring(xdrs, sp)
+\s-1XDR\s0 *xdrs;
+char **sp;
+.fi
+.ft R
+.IP
+A primitive that calls
+.B "xdr_string(xdrs, sp,\s-1MAXUN.UNSIGNED\s0 );"
+where
+.B
+.SM MAXUN.UNSIGNED
+is the maximum value of an unsigned integer.
+.B xdr_wrapstring(\|)
+is handy because the
+.SM RPC
+package passes a maximum of two
+.SM XDR
+routines as parameters, and
+.BR xdr_string(\|) ,
+one of the most frequently used primitives, requires three.
+Returns one if it succeeds, zero otherwise.
+.SH SEE ALSO
+.BR rpc (3)
+.LP
+The following manuals:
+.RS
+.ft I
+eXternal Data Representation Standard: Protocol Specification
+.br
+eXternal Data Representation: Sun Technical Notes
+.ft R
+.br
+.IR "\s-1XDR\s0: External Data Representation Standard" ,
+.SM RFC1014, Sun Microsystems, Inc.,
+.SM USC-ISI\s0.
diff --git a/cpukit/librpc/src/xdr/xdr.c b/cpukit/librpc/src/xdr/xdr.c
new file mode 100644
index 0000000000..e608e46501
--- /dev/null
+++ b/cpukit/librpc/src/xdr/xdr.c
@@ -0,0 +1,777 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)xdr.c 1.35 87/08/12";*/
+/*static char *sccsid = "from: @(#)xdr.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/xdr/xdr.c,v 1.9 1999/08/28 00:02:55 peter Exp $";
+#endif
+
+/*
+ * xdr.c, Generic XDR routines implementation.
+ *
+ * Copyright (C) 1986, Sun Microsystems, Inc.
+ *
+ * These are the "generic" xdr routines used to serialize and de-serialize
+ * most common data items. See xdr.h for more info on the interface to
+ * xdr.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+
+/*
+ * constants specific to the xdr "protocol"
+ */
+#define XDR_FALSE ((long) 0)
+#define XDR_TRUE ((long) 1)
+#define LASTUNSIGNED ((u_int) 0-1)
+
+/*
+ * for unit alignment
+ */
+static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
+
+/*
+ * Free a data structure using XDR
+ * Not a filter, but a convenient utility nonetheless
+ */
+void
+xdr_free(proc, objp)
+ xdrproc_t proc;
+ char *objp;
+{
+ XDR x;
+
+ x.x_op = XDR_FREE;
+ (*proc)(&x, objp);
+}
+
+/*
+ * XDR nothing
+ */
+bool_t
+xdr_void(/* xdrs, addr */)
+ /* XDR *xdrs; */
+ /* caddr_t addr; */
+{
+
+ return (TRUE);
+}
+
+
+/*
+ * XDR integers
+ */
+bool_t
+xdr_int(xdrs, ip)
+ XDR *xdrs;
+ int *ip;
+{
+ long l;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ l = (long) *ip;
+ return (XDR_PUTLONG(xdrs, &l));
+
+ case XDR_DECODE:
+ if (!XDR_GETLONG(xdrs, &l)) {
+ return (FALSE);
+ }
+ *ip = (int) l;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/*
+ * XDR unsigned integers
+ */
+bool_t
+xdr_u_int(xdrs, up)
+ XDR *xdrs;
+ u_int *up;
+{
+ u_long l;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ l = (u_long) *up;
+ return (XDR_PUTLONG(xdrs, (long *)&l));
+
+ case XDR_DECODE:
+ if (!XDR_GETLONG(xdrs, (long *)&l)) {
+ return (FALSE);
+ }
+ *up = (u_int) l;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+
+/*
+ * XDR long integers
+ * same as xdr_u_long - open coded to save a proc call!
+ */
+bool_t
+xdr_long(xdrs, lp)
+ register XDR *xdrs;
+ long *lp;
+{
+ switch (xdrs->x_op) {
+ case XDR_ENCODE:
+ return (XDR_PUTLONG(xdrs, lp));
+ case XDR_DECODE:
+ return (XDR_GETLONG(xdrs, lp));
+ case XDR_FREE:
+ return (TRUE);
+ }
+
+ return (FALSE);
+}
+
+/*
+ * XDR unsigned long integers
+ * same as xdr_long - open coded to save a proc call!
+ */
+bool_t
+xdr_u_long(xdrs, ulp)
+ register XDR *xdrs;
+ u_long *ulp;
+{
+ switch (xdrs->x_op) {
+ case XDR_ENCODE:
+ return (XDR_PUTLONG(xdrs, (long *)ulp));
+ case XDR_DECODE:
+ return (XDR_GETLONG(xdrs, (long *)ulp));
+ case XDR_FREE:
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+
+/*
+ * XDR 32-bit integers
+ * same as xdr_u_int32_t - open coded to save a proc call!
+ */
+bool_t
+xdr_int32_t(xdrs, int32_p)
+ register XDR *xdrs;
+ int32_t *int32_p;
+{
+ long l;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ l = (long) *int32_p;
+ return (XDR_PUTLONG(xdrs, &l));
+
+ case XDR_DECODE:
+ if (!XDR_GETLONG(xdrs, &l)) {
+ return (FALSE);
+ }
+ *int32_p = (int32_t) l;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/*
+ * XDR unsigned 32-bit integers
+ * same as xdr_int32_t - open coded to save a proc call!
+ */
+bool_t
+xdr_u_int32_t(xdrs, u_int32_p)
+ register XDR *xdrs;
+ u_int32_t *u_int32_p;
+{
+ u_long l;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ l = (u_long) *u_int32_p;
+ return (XDR_PUTLONG(xdrs, (long *)&l));
+
+ case XDR_DECODE:
+ if (!XDR_GETLONG(xdrs, (long *)&l)) {
+ return (FALSE);
+ }
+ *u_int32_p = (u_int32_t) l;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/*
+ * XDR 64-bit integers
+ */
+bool_t
+xdr_int64_t(xdrs, int64_p)
+ register XDR *xdrs;
+ int64_t *int64_p;
+{
+ int64_t x;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ return (xdr_opaque(xdrs, (caddr_t)int64_p, sizeof(int64_t)));
+
+ case XDR_DECODE:
+ if (!xdr_opaque(xdrs, (caddr_t)&x, sizeof x)) {
+ return (FALSE);
+ }
+ *int64_p = x;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/*
+ * XDR unsigned 64-bit integers
+ */
+bool_t
+xdr_u_int64_t(xdrs, uint64_p)
+ register XDR *xdrs;
+ u_int64_t *uint64_p;
+{
+ u_int64_t x;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ return (xdr_opaque(xdrs, (caddr_t)uint64_p, sizeof(u_int64_t)));
+
+ case XDR_DECODE:
+ if (!xdr_opaque(xdrs, (caddr_t)&x, sizeof x)) {
+ return (FALSE);
+ }
+ *uint64_p = x;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+
+/*
+ * XDR short integers
+ */
+bool_t
+xdr_short(xdrs, sp)
+ register XDR *xdrs;
+ short *sp;
+{
+ long l;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ l = (long) *sp;
+ return (XDR_PUTLONG(xdrs, &l));
+
+ case XDR_DECODE:
+ if (!XDR_GETLONG(xdrs, &l)) {
+ return (FALSE);
+ }
+ *sp = (short) l;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/*
+ * XDR unsigned short integers
+ */
+bool_t
+xdr_u_short(xdrs, usp)
+ register XDR *xdrs;
+ u_short *usp;
+{
+ u_long l;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ l = (u_long) *usp;
+ return (XDR_PUTLONG(xdrs, (long *)&l));
+
+ case XDR_DECODE:
+ if (!XDR_GETLONG(xdrs, (long *)&l)) {
+ return (FALSE);
+ }
+ *usp = (u_short) l;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+
+/*
+ * XDR 16-bit integers
+ */
+bool_t
+xdr_int16_t(xdrs, int16_p)
+ register XDR *xdrs;
+ int16_t *int16_p;
+{
+ long l;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ l = (long) *int16_p;
+ return (XDR_PUTLONG(xdrs, &l));
+
+ case XDR_DECODE:
+ if (!XDR_GETLONG(xdrs, &l)) {
+ return (FALSE);
+ }
+ *int16_p = (int16_t) l;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/*
+ * XDR unsigned 16-bit integers
+ */
+bool_t
+xdr_u_int16_t(xdrs, u_int16_p)
+ register XDR *xdrs;
+ u_int16_t *u_int16_p;
+{
+ u_long l;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ l = (u_long) *u_int16_p;
+ return (XDR_PUTLONG(xdrs, (long *)&l));
+
+ case XDR_DECODE:
+ if (!XDR_GETLONG(xdrs, (long *)&l)) {
+ return (FALSE);
+ }
+ *u_int16_p = (u_int16_t) l;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+
+/*
+ * XDR a char
+ */
+bool_t
+xdr_char(xdrs, cp)
+ XDR *xdrs;
+ char *cp;
+{
+ int i;
+
+ i = (*cp);
+ if (!xdr_int(xdrs, &i)) {
+ return (FALSE);
+ }
+ *cp = i;
+ return (TRUE);
+}
+
+/*
+ * XDR an unsigned char
+ */
+bool_t
+xdr_u_char(xdrs, cp)
+ XDR *xdrs;
+ u_char *cp;
+{
+ u_int u;
+
+ u = (*cp);
+ if (!xdr_u_int(xdrs, &u)) {
+ return (FALSE);
+ }
+ *cp = u;
+ return (TRUE);
+}
+
+/*
+ * XDR booleans
+ */
+bool_t
+xdr_bool(xdrs, bp)
+ register XDR *xdrs;
+ bool_t *bp;
+{
+ long lb;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ lb = *bp ? XDR_TRUE : XDR_FALSE;
+ return (XDR_PUTLONG(xdrs, &lb));
+
+ case XDR_DECODE:
+ if (!XDR_GETLONG(xdrs, &lb)) {
+ return (FALSE);
+ }
+ *bp = (lb == XDR_FALSE) ? FALSE : TRUE;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/*
+ * XDR enumerations
+ */
+bool_t
+xdr_enum(xdrs, ep)
+ XDR *xdrs;
+ enum_t *ep;
+{
+#ifndef lint
+ enum sizecheck { SIZEVAL }; /* used to find the size of an enum */
+
+ /*
+ * enums are treated as ints
+ */
+ if (sizeof (enum sizecheck) == sizeof (long)) {
+ return (xdr_long(xdrs, (long *)ep));
+ } else if (sizeof (enum sizecheck) == sizeof (int)) {
+ return (xdr_int(xdrs, (int *)ep));
+ } else if (sizeof (enum sizecheck) == sizeof (short)) {
+ return (xdr_short(xdrs, (short *)ep));
+ } else {
+ return (FALSE);
+ }
+#else
+ (void) (xdr_short(xdrs, (short *)ep));
+ (void) (xdr_int(xdrs, (int *)ep));
+ return (xdr_long(xdrs, (long *)ep));
+#endif
+}
+
+/*
+ * XDR opaque data
+ * Allows the specification of a fixed size sequence of opaque bytes.
+ * cp points to the opaque object and cnt gives the byte length.
+ */
+bool_t
+xdr_opaque(xdrs, cp, cnt)
+ register XDR *xdrs;
+ caddr_t cp;
+ register u_int cnt;
+{
+ register u_int rndup;
+ static int crud[BYTES_PER_XDR_UNIT];
+
+ /*
+ * if no data we are done
+ */
+ if (cnt == 0)
+ return (TRUE);
+
+ /*
+ * round byte count to full xdr units
+ */
+ rndup = cnt % BYTES_PER_XDR_UNIT;
+ if (rndup > 0)
+ rndup = BYTES_PER_XDR_UNIT - rndup;
+
+ if (xdrs->x_op == XDR_DECODE) {
+ if (!XDR_GETBYTES(xdrs, cp, cnt)) {
+ return (FALSE);
+ }
+ if (rndup == 0)
+ return (TRUE);
+ return (XDR_GETBYTES(xdrs, (caddr_t)crud, rndup));
+ }
+
+ if (xdrs->x_op == XDR_ENCODE) {
+ if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
+ return (FALSE);
+ }
+ if (rndup == 0)
+ return (TRUE);
+ return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
+ }
+
+ if (xdrs->x_op == XDR_FREE) {
+ return (TRUE);
+ }
+
+ return (FALSE);
+}
+
+/*
+ * XDR counted bytes
+ * *cpp is a pointer to the bytes, *sizep is the count.
+ * If *cpp is NULL maxsize bytes are allocated
+ */
+bool_t
+xdr_bytes(xdrs, cpp, sizep, maxsize)
+ register XDR *xdrs;
+ char **cpp;
+ register u_int *sizep;
+ u_int maxsize;
+{
+ register char *sp = *cpp; /* sp is the actual string pointer */
+ register u_int nodesize;
+
+ /*
+ * first deal with the length since xdr bytes are counted
+ */
+ if (! xdr_u_int(xdrs, sizep)) {
+ return (FALSE);
+ }
+ nodesize = *sizep;
+ if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
+ return (FALSE);
+ }
+
+ /*
+ * now deal with the actual bytes
+ */
+ switch (xdrs->x_op) {
+
+ case XDR_DECODE:
+ if (nodesize == 0) {
+ return (TRUE);
+ }
+ if (sp == NULL) {
+ *cpp = sp = (char *)mem_alloc(nodesize);
+ }
+ if (sp == NULL) {
+ (void) fprintf(stderr, "xdr_bytes: out of memory\n");
+ return (FALSE);
+ }
+ /* fall into ... */
+
+ case XDR_ENCODE:
+ return (xdr_opaque(xdrs, sp, nodesize));
+
+ case XDR_FREE:
+ if (sp != NULL) {
+ mem_free(sp, nodesize);
+ *cpp = NULL;
+ }
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/*
+ * Implemented here due to commonality of the object.
+ */
+bool_t
+xdr_netobj(xdrs, np)
+ XDR *xdrs;
+ struct netobj *np;
+{
+
+ return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
+}
+
+/*
+ * XDR a descriminated union
+ * Support routine for discriminated unions.
+ * You create an array of xdrdiscrim structures, terminated with
+ * an entry with a null procedure pointer. The routine gets
+ * the discriminant value and then searches the array of xdrdiscrims
+ * looking for that value. It calls the procedure given in the xdrdiscrim
+ * to handle the discriminant. If there is no specific routine a default
+ * routine may be called.
+ * If there is no specific or default routine an error is returned.
+ */
+bool_t
+xdr_union(xdrs, dscmp, unp, choices, dfault)
+ register XDR *xdrs;
+ enum_t *dscmp; /* enum to decide which arm to work on */
+ char *unp; /* the union itself */
+ struct xdr_discrim *choices; /* [value, xdr proc] for each arm */
+ xdrproc_t dfault; /* default xdr routine */
+{
+ register enum_t dscm;
+
+ /*
+ * we deal with the discriminator; it's an enum
+ */
+ if (! xdr_enum(xdrs, dscmp)) {
+ return (FALSE);
+ }
+ dscm = *dscmp;
+
+ /*
+ * search choices for a value that matches the discriminator.
+ * if we find one, execute the xdr routine for that value.
+ */
+ for (; choices->proc != NULL_xdrproc_t; choices++) {
+ if (choices->value == dscm)
+ return ((*(choices->proc))(xdrs, unp, LASTUNSIGNED));
+ }
+
+ /*
+ * no match - execute the default xdr routine if there is one
+ */
+ return ((dfault == NULL_xdrproc_t) ? FALSE :
+ (*dfault)(xdrs, unp, LASTUNSIGNED));
+}
+
+
+/*
+ * Non-portable xdr primitives.
+ * Care should be taken when moving these routines to new architectures.
+ */
+
+
+/*
+ * XDR null terminated ASCII strings
+ * xdr_string deals with "C strings" - arrays of bytes that are
+ * terminated by a NULL character. The parameter cpp references a
+ * pointer to storage; If the pointer is null, then the necessary
+ * storage is allocated. The last parameter is the max allowed length
+ * of the string as specified by a protocol.
+ */
+bool_t
+xdr_string(xdrs, cpp, maxsize)
+ register XDR *xdrs;
+ char **cpp;
+ u_int maxsize;
+{
+ register char *sp = *cpp; /* sp is the actual string pointer */
+ u_int size;
+ u_int nodesize;
+
+ /*
+ * first deal with the length since xdr strings are counted-strings
+ */
+ switch (xdrs->x_op) {
+ case XDR_FREE:
+ if (sp == NULL) {
+ return(TRUE); /* already free */
+ }
+ /* fall through... */
+ case XDR_ENCODE:
+ size = strlen(sp);
+ break;
+ case XDR_DECODE: /* to avoid warning */
+ break;
+ }
+ if (! xdr_u_int(xdrs, &size)) {
+ return (FALSE);
+ }
+ if (size > maxsize) {
+ return (FALSE);
+ }
+ nodesize = size + 1;
+
+ /*
+ * now deal with the actual bytes
+ */
+ switch (xdrs->x_op) {
+
+ case XDR_DECODE:
+ if (nodesize == 0) {
+ return (TRUE);
+ }
+ if (sp == NULL)
+ *cpp = sp = (char *)mem_alloc(nodesize);
+ if (sp == NULL) {
+ (void) fprintf(stderr, "xdr_string: out of memory\n");
+ return (FALSE);
+ }
+ sp[size] = 0;
+ /* fall into ... */
+
+ case XDR_ENCODE:
+ return (xdr_opaque(xdrs, sp, size));
+
+ case XDR_FREE:
+ mem_free(sp, nodesize);
+ *cpp = NULL;
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/*
+ * Wrapper for xdr_string that can be called directly from
+ * routines like clnt_call
+ */
+bool_t
+xdr_wrapstring(xdrs, cpp)
+ XDR *xdrs;
+ char **cpp;
+{
+ return xdr_string(xdrs, cpp, LASTUNSIGNED);
+}
diff --git a/cpukit/librpc/src/xdr/xdr_array.c b/cpukit/librpc/src/xdr/xdr_array.c
new file mode 100644
index 0000000000..53ced17096
--- /dev/null
+++ b/cpukit/librpc/src/xdr/xdr_array.c
@@ -0,0 +1,156 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)xdr_array.c 1.10 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)xdr_array.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/xdr/xdr_array.c,v 1.8 1999/08/28 00:02:55 peter Exp $";
+#endif
+
+/*
+ * xdr_array.c, Generic XDR routines impelmentation.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * These are the "non-trivial" xdr primitives used to serialize and de-serialize
+ * arrays. See xdr.h for more info on the interface to xdr.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+
+#define LASTUNSIGNED ((u_int) 0-1)
+
+/*
+ * XDR an array of arbitrary elements
+ * *addrp is a pointer to the array, *sizep is the number of elements.
+ * If addrp is NULL (*sizep * elsize) bytes are allocated.
+ * elsize is the size (in bytes) of each element, and elproc is the
+ * xdr procedure to call to handle each element of the array.
+ */
+bool_t
+xdr_array(xdrs, addrp, sizep, maxsize, elsize, elproc)
+ register XDR *xdrs;
+ caddr_t *addrp; /* array pointer */
+ u_int *sizep; /* number of elements */
+ u_int maxsize; /* max numberof elements */
+ u_int elsize; /* size in bytes of each element */
+ xdrproc_t elproc; /* xdr routine to handle each element */
+{
+ register u_int i;
+ register caddr_t target = *addrp;
+ register u_int c; /* the actual element count */
+ register bool_t stat = TRUE;
+ register u_int nodesize;
+
+ /* like strings, arrays are really counted arrays */
+ if (! xdr_u_int(xdrs, sizep)) {
+ return (FALSE);
+ }
+ c = *sizep;
+ if ((c > maxsize) && (xdrs->x_op != XDR_FREE)) {
+ return (FALSE);
+ }
+ nodesize = c * elsize;
+
+ /*
+ * if we are deserializing, we may need to allocate an array.
+ * We also save time by checking for a null array if we are freeing.
+ */
+ if (target == NULL)
+ switch (xdrs->x_op) {
+ case XDR_DECODE:
+ if (c == 0)
+ return (TRUE);
+ *addrp = target = mem_alloc(nodesize);
+ if (target == NULL) {
+ (void) fprintf(stderr,
+ "xdr_array: out of memory\n");
+ return (FALSE);
+ }
+ memset(target, 0, nodesize);
+ break;
+
+ case XDR_FREE:
+ return (TRUE);
+ case XDR_ENCODE: /* to avoid warning */
+ break;
+ }
+
+ /*
+ * now we xdr each element of array
+ */
+ for (i = 0; (i < c) && stat; i++) {
+ stat = (*elproc)(xdrs, target, LASTUNSIGNED);
+ target += elsize;
+ }
+
+ /*
+ * the array may need freeing
+ */
+ if (xdrs->x_op == XDR_FREE) {
+ mem_free(*addrp, nodesize);
+ *addrp = NULL;
+ }
+ return (stat);
+}
+
+/*
+ * xdr_vector():
+ *
+ * XDR a fixed length array. Unlike variable-length arrays,
+ * the storage of fixed length arrays is static and unfreeable.
+ * > basep: base of the array
+ * > size: size of the array
+ * > elemsize: size of each element
+ * > xdr_elem: routine to XDR each element
+ */
+bool_t
+xdr_vector(xdrs, basep, nelem, elemsize, xdr_elem)
+ register XDR *xdrs;
+ register char *basep;
+ register u_int nelem;
+ register u_int elemsize;
+ register xdrproc_t xdr_elem;
+{
+ register u_int i;
+ register char *elptr;
+
+ elptr = basep;
+ for (i = 0; i < nelem; i++) {
+ if (! (*xdr_elem)(xdrs, elptr, LASTUNSIGNED)) {
+ return(FALSE);
+ }
+ elptr += elemsize;
+ }
+ return(TRUE);
+}
diff --git a/cpukit/librpc/src/xdr/xdr_float.c b/cpukit/librpc/src/xdr/xdr_float.c
new file mode 100644
index 0000000000..64186b8051
--- /dev/null
+++ b/cpukit/librpc/src/xdr/xdr_float.c
@@ -0,0 +1,333 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)xdr_float.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/xdr/xdr_float.c,v 1.7 1999/08/28 00:02:55 peter Exp $";
+#endif
+
+/*
+ * xdr_float.c, Generic XDR routines impelmentation.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * These are the "floating point" xdr routines used to (de)serialize
+ * most common data items. See xdr.h for more info on the interface to
+ * xdr.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+
+/*
+ * NB: Not portable.
+ * This routine works on machines with IEEE754 FP and Vaxen.
+ */
+
+#if defined(__alpha__) || \
+ defined(_AM29K) || \
+ defined(__arm__) || \
+ defined(__H8300__) || defined(__H8300H__) || defined(__H8300S__) || \
+ defined(__hppa__) || \
+ defined(__i386__) || \
+ defined(__i960__) || \
+ defined(__m68k__) || defined(__mc68000__) || \
+ defined(__mips__) || \
+ defined(__ns32k__) || \
+ defined(__sparc__) || \
+ defined(__ppc__) || defined(__PPC__) || \
+ defined(__sh__)
+
+#include <machine/endian.h>
+#if !defined(IEEEFP)
+#define IEEEFP
+#endif
+
+#elif defined(_TMS320C3x) || defined(_TMS320C4x)
+#error "Texas Instruments C3x/C4x Not supported."
+
+#elif defined(vax)
+
+/* What IEEE single precision floating point looks like on a Vax */
+struct ieee_single {
+ unsigned int mantissa: 23;
+ unsigned int exp : 8;
+ unsigned int sign : 1;
+};
+
+/* Vax single precision floating point */
+struct vax_single {
+ unsigned int mantissa1 : 7;
+ unsigned int exp : 8;
+ unsigned int sign : 1;
+ unsigned int mantissa2 : 16;
+};
+
+#define VAX_SNG_BIAS 0x81
+#define IEEE_SNG_BIAS 0x7f
+
+static struct sgl_limits {
+ struct vax_single s;
+ struct ieee_single ieee;
+} sgl_limits[2] = {
+ {{ 0x7f, 0xff, 0x0, 0xffff }, /* Max Vax */
+ { 0x0, 0xff, 0x0 }}, /* Max IEEE */
+ {{ 0x0, 0x0, 0x0, 0x0 }, /* Min Vax */
+ { 0x0, 0x0, 0x0 }} /* Min IEEE */
+};
+/* end of vax */
+#else
+#error "xdr_float.c: unknown CPU"
+#endif
+
+
+bool_t
+xdr_float(xdrs, fp)
+ register XDR *xdrs;
+ register float *fp;
+{
+#ifdef IEEEFP
+ bool_t rv;
+ long tmpl;
+#else
+ struct ieee_single is;
+ struct vax_single vs, *vsp;
+ struct sgl_limits *lim;
+ int i;
+#endif
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+#ifdef IEEEFP
+ tmpl = *(int32_t *)fp;
+ return (XDR_PUTLONG(xdrs, &tmpl));
+#else
+ vs = *((struct vax_single *)fp);
+ for (i = 0, lim = sgl_limits;
+ i < sizeof(sgl_limits)/sizeof(struct sgl_limits);
+ i++, lim++) {
+ if ((vs.mantissa2 == lim->s.mantissa2) &&
+ (vs.exp == lim->s.exp) &&
+ (vs.mantissa1 == lim->s.mantissa1)) {
+ is = lim->ieee;
+ goto shipit;
+ }
+ }
+ is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS;
+ is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2;
+ shipit:
+ is.sign = vs.sign;
+ return (XDR_PUTLONG(xdrs, (long *)&is));
+#endif
+
+ case XDR_DECODE:
+#ifdef IEEEFP
+ rv = XDR_GETLONG(xdrs, &tmpl);
+ *(int32_t *)fp = tmpl;
+ return (rv);
+#else
+ vsp = (struct vax_single *)fp;
+ if (!XDR_GETLONG(xdrs, (long *)&is))
+ return (FALSE);
+ for (i = 0, lim = sgl_limits;
+ i < sizeof(sgl_limits)/sizeof(struct sgl_limits);
+ i++, lim++) {
+ if ((is.exp == lim->ieee.exp) &&
+ (is.mantissa == lim->ieee.mantissa)) {
+ *vsp = lim->s;
+ goto doneit;
+ }
+ }
+ vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS;
+ vsp->mantissa2 = is.mantissa;
+ vsp->mantissa1 = (is.mantissa >> 16);
+ doneit:
+ vsp->sign = is.sign;
+ return (TRUE);
+#endif
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+#ifdef vax
+/* What IEEE double precision floating point looks like on a Vax */
+struct ieee_double {
+ unsigned int mantissa1 : 20;
+ unsigned int exp : 11;
+ unsigned int sign : 1;
+ unsigned int mantissa2 : 32;
+};
+
+/* Vax double precision floating point */
+struct vax_double {
+ unsigned int mantissa1 : 7;
+ unsigned int exp : 8;
+ unsigned int sign : 1;
+ unsigned int mantissa2 : 16;
+ unsigned int mantissa3 : 16;
+ unsigned int mantissa4 : 16;
+};
+
+#define VAX_DBL_BIAS 0x81
+#define IEEE_DBL_BIAS 0x3ff
+#define MASK(nbits) ((1 << nbits) - 1)
+
+static struct dbl_limits {
+ struct vax_double d;
+ struct ieee_double ieee;
+} dbl_limits[2] = {
+ {{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff }, /* Max Vax */
+ { 0x0, 0x7ff, 0x0, 0x0 }}, /* Max IEEE */
+ {{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, /* Min Vax */
+ { 0x0, 0x0, 0x0, 0x0 }} /* Min IEEE */
+};
+
+#endif /* vax */
+
+
+bool_t
+xdr_double(xdrs, dp)
+ register XDR *xdrs;
+ double *dp;
+{
+#ifdef IEEEFP
+ register int32_t *i32p;
+ bool_t rv;
+ long tmpl;
+#else
+ register long *lp;
+ struct ieee_double id;
+ struct vax_double vd;
+ register struct dbl_limits *lim;
+ int i;
+#endif
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+#ifdef IEEEFP
+ i32p = (int32_t *)dp;
+#if BYTE_ORDER == BIG_ENDIAN
+ tmpl = *i32p++;
+ rv = XDR_PUTLONG(xdrs, &tmpl);
+ if (!rv)
+ return (rv);
+ tmpl = *i32p;
+ rv = XDR_PUTLONG(xdrs, &tmpl);
+#else
+ tmpl = *(i32p+1);
+ rv = XDR_PUTLONG(xdrs, &tmpl);
+ if (!rv)
+ return (rv);
+ tmpl = *i32p;
+ rv = XDR_PUTLONG(xdrs, &tmpl);
+#endif
+ return (rv);
+#else
+ vd = *((struct vax_double *)dp);
+ for (i = 0, lim = dbl_limits;
+ i < sizeof(dbl_limits)/sizeof(struct dbl_limits);
+ i++, lim++) {
+ if ((vd.mantissa4 == lim->d.mantissa4) &&
+ (vd.mantissa3 == lim->d.mantissa3) &&
+ (vd.mantissa2 == lim->d.mantissa2) &&
+ (vd.mantissa1 == lim->d.mantissa1) &&
+ (vd.exp == lim->d.exp)) {
+ id = lim->ieee;
+ goto shipit;
+ }
+ }
+ id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS;
+ id.mantissa1 = (vd.mantissa1 << 13) | (vd.mantissa2 >> 3);
+ id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) |
+ (vd.mantissa3 << 13) |
+ ((vd.mantissa4 >> 3) & MASK(13));
+ shipit:
+ id.sign = vd.sign;
+ lp = (long *)&id;
+ return (XDR_PUTLONG(xdrs, lp++) && XDR_PUTLONG(xdrs, lp));
+#endif
+
+ case XDR_DECODE:
+#ifdef IEEEFP
+ i32p = (int32_t *)dp;
+#if BYTE_ORDER == BIG_ENDIAN
+ rv = XDR_GETLONG(xdrs, &tmpl);
+ *i32p++ = tmpl;
+ if (!rv)
+ return (rv);
+ rv = XDR_GETLONG(xdrs, &tmpl);
+ *i32p = tmpl;
+#else
+ rv = XDR_GETLONG(xdrs, &tmpl);
+ *(i32p+1) = tmpl;
+ if (!rv)
+ return (rv);
+ rv = XDR_GETLONG(xdrs, &tmpl);
+ *i32p = tmpl;
+#endif
+ return (rv);
+#else
+ lp = (long *)&id;
+ if (!XDR_GETLONG(xdrs, lp++) || !XDR_GETLONG(xdrs, lp))
+ return (FALSE);
+ for (i = 0, lim = dbl_limits;
+ i < sizeof(dbl_limits)/sizeof(struct dbl_limits);
+ i++, lim++) {
+ if ((id.mantissa2 == lim->ieee.mantissa2) &&
+ (id.mantissa1 == lim->ieee.mantissa1) &&
+ (id.exp == lim->ieee.exp)) {
+ vd = lim->d;
+ goto doneit;
+ }
+ }
+ vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS;
+ vd.mantissa1 = (id.mantissa1 >> 13);
+ vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) |
+ (id.mantissa2 >> 29);
+ vd.mantissa3 = (id.mantissa2 >> 13);
+ vd.mantissa4 = (id.mantissa2 << 3);
+ doneit:
+ vd.sign = id.sign;
+ *dp = *((double *)&vd);
+ return (TRUE);
+#endif
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ return (FALSE);
+}
diff --git a/cpukit/librpc/src/xdr/xdr_mem.c b/cpukit/librpc/src/xdr/xdr_mem.c
new file mode 100644
index 0000000000..0b17afa115
--- /dev/null
+++ b/cpukit/librpc/src/xdr/xdr_mem.c
@@ -0,0 +1,242 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)xdr_mem.c 1.19 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)xdr_mem.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/xdr/xdr_mem.c,v 1.8 1999/08/28 00:02:56 peter Exp $";
+#endif
+
+/*
+ * xdr_mem.h, XDR implementation using memory buffers.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * If you have some data to be interpreted as external data representation
+ * or to be converted to external data representation in a memory buffer,
+ * then this is the package for you.
+ *
+ */
+
+#include <string.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <netinet/in.h>
+
+static bool_t xdrmem_getlong_aligned();
+static bool_t xdrmem_putlong_aligned();
+static bool_t xdrmem_getlong_unaligned();
+static bool_t xdrmem_putlong_unaligned();
+static bool_t xdrmem_getbytes();
+static bool_t xdrmem_putbytes();
+static u_int xdrmem_getpos(); /* XXX w/64-bit pointers, u_int not enough! */
+static bool_t xdrmem_setpos();
+static int32_t *xdrmem_inline_aligned();
+static int32_t *xdrmem_inline_unaligned();
+static void xdrmem_destroy();
+
+static struct xdr_ops xdrmem_ops_aligned = {
+ xdrmem_getlong_aligned,
+ xdrmem_putlong_aligned,
+ xdrmem_getbytes,
+ xdrmem_putbytes,
+ xdrmem_getpos,
+ xdrmem_setpos,
+ xdrmem_inline_aligned,
+ xdrmem_destroy
+};
+
+static struct xdr_ops xdrmem_ops_unaligned = {
+ xdrmem_getlong_unaligned,
+ xdrmem_putlong_unaligned,
+ xdrmem_getbytes,
+ xdrmem_putbytes,
+ xdrmem_getpos,
+ xdrmem_setpos,
+ xdrmem_inline_unaligned,
+ xdrmem_destroy
+};
+
+/*
+ * The procedure xdrmem_create initializes a stream descriptor for a
+ * memory buffer.
+ */
+void
+xdrmem_create(xdrs, addr, size, op)
+ register XDR *xdrs;
+ caddr_t addr;
+ u_int size;
+ enum xdr_op op;
+{
+
+ xdrs->x_op = op;
+ xdrs->x_ops = ((size_t)addr & (sizeof(int32_t) - 1))
+ ? &xdrmem_ops_unaligned : &xdrmem_ops_aligned;
+ xdrs->x_private = xdrs->x_base = addr;
+ xdrs->x_handy = size;
+}
+
+static void
+xdrmem_destroy(/*xdrs*/)
+ /*XDR *xdrs;*/
+{
+
+}
+
+static bool_t
+xdrmem_getlong_aligned(xdrs, lp)
+ register XDR *xdrs;
+ long *lp;
+{
+
+ if ((xdrs->x_handy -= sizeof(int32_t)) < 0)
+ return (FALSE);
+ *lp = ntohl(*(int32_t *)(xdrs->x_private));
+ xdrs->x_private += sizeof(int32_t);
+ return (TRUE);
+}
+
+static bool_t
+xdrmem_putlong_aligned(xdrs, lp)
+ register XDR *xdrs;
+ long *lp;
+{
+
+ if ((xdrs->x_handy -= sizeof(int32_t)) < 0)
+ return (FALSE);
+ *(int32_t *)xdrs->x_private = htonl(*lp);
+ xdrs->x_private += sizeof(int32_t);
+ return (TRUE);
+}
+
+static bool_t
+xdrmem_getlong_unaligned(xdrs, lp)
+ register XDR *xdrs;
+ long *lp;
+{
+ int32_t l;
+
+ if ((xdrs->x_handy -= sizeof(int32_t)) < 0)
+ return (FALSE);
+ memcpy(&l, xdrs->x_private, sizeof(int32_t));
+ *lp = ntohl(l);
+ xdrs->x_private += sizeof(int32_t);
+ return (TRUE);
+}
+
+static bool_t
+xdrmem_putlong_unaligned(xdrs, lp)
+ register XDR *xdrs;
+ long *lp;
+{
+ int32_t l;
+
+ if ((xdrs->x_handy -= sizeof(int32_t)) < 0)
+ return (FALSE);
+ l = htonl(*lp);
+ memcpy(xdrs->x_private, &l, sizeof(int32_t));
+ xdrs->x_private += sizeof(int32_t);
+ return (TRUE);
+}
+
+static bool_t
+xdrmem_getbytes(xdrs, addr, len)
+ register XDR *xdrs;
+ caddr_t addr;
+ register u_int len;
+{
+
+ if ((xdrs->x_handy -= len) < 0)
+ return (FALSE);
+ memcpy(addr, xdrs->x_private, len);
+ xdrs->x_private += len;
+ return (TRUE);
+}
+
+static bool_t
+xdrmem_putbytes(xdrs, addr, len)
+ register XDR *xdrs;
+ caddr_t addr;
+ register u_int len;
+{
+
+ if ((xdrs->x_handy -= len) < 0)
+ return (FALSE);
+ memcpy(xdrs->x_private, addr, len);
+ xdrs->x_private += len;
+ return (TRUE);
+}
+
+static u_int
+xdrmem_getpos(xdrs)
+ register XDR *xdrs;
+{
+
+ /* XXX w/64-bit pointers, u_int not enough! */
+ return ((u_long)xdrs->x_private - (u_long)xdrs->x_base);
+}
+
+static bool_t
+xdrmem_setpos(xdrs, pos)
+ register XDR *xdrs;
+ u_int pos;
+{
+ register caddr_t newaddr = xdrs->x_base + pos;
+ register caddr_t lastaddr = xdrs->x_private + xdrs->x_handy;
+
+ if ((long)newaddr > (long)lastaddr)
+ return (FALSE);
+ xdrs->x_private = newaddr;
+ xdrs->x_handy = (long)lastaddr - (long)newaddr;
+ return (TRUE);
+}
+
+static int32_t *
+xdrmem_inline_aligned(xdrs, len)
+ register XDR *xdrs;
+ int len;
+{
+ int32_t *buf = 0;
+
+ if (xdrs->x_handy >= len) {
+ xdrs->x_handy -= len;
+ buf = (int32_t *) xdrs->x_private;
+ xdrs->x_private += len;
+ }
+ return (buf);
+}
+
+static int32_t *
+xdrmem_inline_unaligned(xdrs, len)
+ register XDR *xdrs;
+ int len;
+{
+
+ return (0);
+}
diff --git a/cpukit/librpc/src/xdr/xdr_rec.c b/cpukit/librpc/src/xdr/xdr_rec.c
new file mode 100644
index 0000000000..d87b413ee6
--- /dev/null
+++ b/cpukit/librpc/src/xdr/xdr_rec.c
@@ -0,0 +1,601 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)xdr_rec.c 1.21 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)xdr_rec.c 2.2 88/08/01 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/xdr/xdr_rec.c,v 1.12 2000/01/19 06:12:32 wpaul Exp $";
+#endif
+
+/*
+ * xdr_rec.c, Implements TCP/IP based XDR streams with a "record marking"
+ * layer above tcp (for rpc's use).
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * These routines interface XDRSTREAMS to a tcp/ip connection.
+ * There is a record marking layer between the xdr stream
+ * and the tcp transport level. A record is composed on one or more
+ * record fragments. A record fragment is a thirty-two bit header followed
+ * by n bytes of data, where n is contained in the header. The header
+ * is represented as a htonl(u_long). Thegh order bit encodes
+ * whether or not the fragment is the last fragment of the record
+ * (1 => fragment is last, 0 => more fragments to follow.
+ * The other 31 bits encode the byte length of the fragment.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <netinet/in.h>
+#include <unistd.h> /* for lseek() */
+
+static u_int fix_buf_size();
+static bool_t flush_out();
+static bool_t get_input_bytes();
+static bool_t set_input_fragment();
+static bool_t skip_input_bytes();
+
+static bool_t xdrrec_getlong();
+static bool_t xdrrec_putlong();
+static bool_t xdrrec_getbytes();
+static bool_t xdrrec_putbytes();
+static u_int xdrrec_getpos();
+static bool_t xdrrec_setpos();
+static int32_t *xdrrec_inline();
+static void xdrrec_destroy();
+
+static struct xdr_ops xdrrec_ops = {
+ xdrrec_getlong,
+ xdrrec_putlong,
+ xdrrec_getbytes,
+ xdrrec_putbytes,
+ xdrrec_getpos,
+ xdrrec_setpos,
+ xdrrec_inline,
+ xdrrec_destroy
+};
+
+/*
+ * A record is composed of one or more record fragments.
+ * A record fragment is a two-byte header followed by zero to
+ * 2**32-1 bytes. The header is treated as a long unsigned and is
+ * encode/decoded to the network via htonl/ntohl. The low order 31 bits
+ * are a byte count of the fragment. The highest order bit is a boolean:
+ * 1 => this fragment is the last fragment of the record,
+ * 0 => this fragment is followed by more fragment(s).
+ *
+ * The fragment/record machinery is not general; it is constructed to
+ * meet the needs of xdr and rpc based on tcp.
+ */
+
+#define LAST_FRAG ((u_int32_t)(1 << 31))
+
+typedef struct rec_strm {
+ caddr_t tcp_handle;
+ caddr_t the_buffer;
+ /*
+ * out-goung bits
+ */
+ int (*writeit) __P((caddr_t, caddr_t, int));
+ caddr_t out_base; /* output buffer (points to frag header) */
+ caddr_t out_finger; /* next output position */
+ caddr_t out_boundry; /* data cannot up to this address */
+ u_int32_t *frag_header; /* beginning of current fragment */
+ bool_t frag_sent; /* true if buffer sent in middle of record */
+ /*
+ * in-coming bits
+ */
+ int (*readit) __P((caddr_t, caddr_t, int));
+ u_long in_size; /* fixed size of the input buffer */
+ caddr_t in_base;
+ caddr_t in_finger; /* location of next byte to be had */
+ caddr_t in_boundry; /* can read up to this location */
+ long fbtbc; /* fragment bytes to be consumed */
+ bool_t last_frag;
+ u_int sendsize;
+ u_int recvsize;
+} RECSTREAM;
+
+
+/*
+ * Create an xdr handle for xdrrec
+ * xdrrec_create fills in xdrs. Sendsize and recvsize are
+ * send and recv buffer sizes (0 => use default).
+ * tcp_handle is an opaque handle that is passed as the first parameter to
+ * the procedures readit and writeit. Readit and writeit are read and
+ * write respectively. They are like the system
+ * calls expect that they take an opaque handle rather than an fd.
+ */
+void
+xdrrec_create(xdrs, sendsize, recvsize, tcp_handle, readit, writeit)
+ register XDR *xdrs;
+ register u_int sendsize;
+ register u_int recvsize;
+ caddr_t tcp_handle;
+ int (*readit)(); /* like read, but pass it a tcp_handle, not sock */
+ int (*writeit)(); /* like write, but pass it a tcp_handle, not sock */
+{
+ register RECSTREAM *rstrm =
+ (RECSTREAM *)mem_alloc(sizeof(RECSTREAM));
+
+ if (rstrm == NULL) {
+ (void)fprintf(stderr, "xdrrec_create: out of memory\n");
+ /*
+ * This is bad. Should rework xdrrec_create to
+ * return a handle, and in this case return NULL
+ */
+ return;
+ }
+ /*
+ * adjust sizes and allocate buffer quad byte aligned
+ */
+ rstrm->sendsize = sendsize = fix_buf_size(sendsize);
+ rstrm->recvsize = recvsize = fix_buf_size(recvsize);
+ rstrm->the_buffer = mem_alloc(sendsize + recvsize + BYTES_PER_XDR_UNIT);
+ if (rstrm->the_buffer == NULL) {
+ (void)fprintf(stderr, "xdrrec_create: out of memory\n");
+ return;
+ }
+ for (rstrm->out_base = rstrm->the_buffer;
+ (u_long)rstrm->out_base % BYTES_PER_XDR_UNIT != 0;
+ rstrm->out_base++);
+ rstrm->in_base = rstrm->out_base + sendsize;
+ /*
+ * now the rest ...
+ */
+ xdrs->x_ops = &xdrrec_ops;
+ xdrs->x_private = (caddr_t)rstrm;
+ rstrm->tcp_handle = tcp_handle;
+ rstrm->readit = readit;
+ rstrm->writeit = writeit;
+ rstrm->out_finger = rstrm->out_boundry = rstrm->out_base;
+ rstrm->frag_header = (u_int32_t *)rstrm->out_base;
+ rstrm->out_finger += sizeof(u_int32_t);
+ rstrm->out_boundry += sendsize;
+ rstrm->frag_sent = FALSE;
+ rstrm->in_size = recvsize;
+ rstrm->in_boundry = rstrm->in_base;
+ rstrm->in_finger = (rstrm->in_boundry += recvsize);
+ rstrm->fbtbc = 0;
+ rstrm->last_frag = TRUE;
+}
+
+
+/*
+ * The reoutines defined below are the xdr ops which will go into the
+ * xdr handle filled in by xdrrec_create.
+ */
+
+static bool_t
+xdrrec_getlong(xdrs, lp)
+ XDR *xdrs;
+ long *lp;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ register int32_t *buflp = (int32_t *)(rstrm->in_finger);
+ int32_t mylong;
+
+ /* first try the inline, fast case */
+ if ((rstrm->fbtbc >= sizeof(int32_t)) &&
+ (((long)rstrm->in_boundry - (long)buflp) >= sizeof(int32_t))) {
+ *lp = (long)ntohl((u_int32_t)(*buflp));
+ rstrm->fbtbc -= sizeof(int32_t);
+ rstrm->in_finger += sizeof(int32_t);
+ } else {
+ if (! xdrrec_getbytes(xdrs, (caddr_t)&mylong, sizeof(int32_t)))
+ return (FALSE);
+ *lp = (long)ntohl((u_int32_t)mylong);
+ }
+ return (TRUE);
+}
+
+static bool_t
+xdrrec_putlong(xdrs, lp)
+ XDR *xdrs;
+ long *lp;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ register int32_t *dest_lp = ((int32_t *)(rstrm->out_finger));
+
+ if ((rstrm->out_finger += sizeof(int32_t)) > rstrm->out_boundry) {
+ /*
+ * this case should almost never happen so the code is
+ * inefficient
+ */
+ rstrm->out_finger -= sizeof(int32_t);
+ rstrm->frag_sent = TRUE;
+ if (! flush_out(rstrm, FALSE))
+ return (FALSE);
+ dest_lp = ((int32_t *)(rstrm->out_finger));
+ rstrm->out_finger += sizeof(int32_t);
+ }
+ *dest_lp = (int32_t)htonl((u_int32_t)(*lp));
+ return (TRUE);
+}
+
+static bool_t /* must manage buffers, fragments, and records */
+xdrrec_getbytes(xdrs, addr, len)
+ XDR *xdrs;
+ register caddr_t addr;
+ register u_int len;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ register int current;
+
+ while (len > 0) {
+ current = rstrm->fbtbc;
+ if (current == 0) {
+ if (rstrm->last_frag)
+ return (FALSE);
+ if (! set_input_fragment(rstrm))
+ return (FALSE);
+ continue;
+ }
+ current = (len < current) ? len : current;
+ if (! get_input_bytes(rstrm, addr, current))
+ return (FALSE);
+ addr += current;
+ rstrm->fbtbc -= current;
+ len -= current;
+ }
+ return (TRUE);
+}
+
+static bool_t
+xdrrec_putbytes(xdrs, addr, len)
+ XDR *xdrs;
+ register caddr_t addr;
+ register u_int len;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ register long current;
+
+ while (len > 0) {
+ current = (u_long)rstrm->out_boundry -
+ (u_long)rstrm->out_finger;
+ current = (len < current) ? len : current;
+ memcpy(rstrm->out_finger, addr, current);
+ rstrm->out_finger += current;
+ addr += current;
+ len -= current;
+ if (rstrm->out_finger == rstrm->out_boundry) {
+ rstrm->frag_sent = TRUE;
+ if (! flush_out(rstrm, FALSE))
+ return (FALSE);
+ }
+ }
+ return (TRUE);
+}
+
+static u_int
+xdrrec_getpos(xdrs)
+ register XDR *xdrs;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
+ register long pos;
+
+ pos = lseek((int)(long)rstrm->tcp_handle, (off_t) 0, 1);
+ if (pos != -1)
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ pos += rstrm->out_finger - rstrm->out_base;
+ break;
+
+ case XDR_DECODE:
+ pos -= rstrm->in_boundry - rstrm->in_finger;
+ break;
+
+ default:
+ pos = -1;
+ break;
+ }
+ return ((u_int) pos);
+}
+
+static bool_t
+xdrrec_setpos(xdrs, pos)
+ register XDR *xdrs;
+ u_int pos;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
+ u_int currpos = xdrrec_getpos(xdrs);
+ int delta = currpos - pos;
+ caddr_t newpos;
+
+ if ((int)currpos != -1)
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ newpos = rstrm->out_finger - delta;
+ if ((newpos > (caddr_t)(rstrm->frag_header)) &&
+ (newpos < rstrm->out_boundry)) {
+ rstrm->out_finger = newpos;
+ return (TRUE);
+ }
+ break;
+
+ case XDR_DECODE:
+ newpos = rstrm->in_finger - delta;
+ if ((delta < (int)(rstrm->fbtbc)) &&
+ (newpos <= rstrm->in_boundry) &&
+ (newpos >= rstrm->in_base)) {
+ rstrm->in_finger = newpos;
+ rstrm->fbtbc -= delta;
+ return (TRUE);
+ }
+ break;
+ case XDR_FREE: /* to avoid warning */
+ break;
+ }
+ return (FALSE);
+}
+
+static int32_t *
+xdrrec_inline(xdrs, len)
+ register XDR *xdrs;
+ int len;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
+ int32_t * buf = NULL;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ if ((rstrm->out_finger + len) <= rstrm->out_boundry) {
+ buf = (int32_t *) rstrm->out_finger;
+ rstrm->out_finger += len;
+ }
+ break;
+
+ case XDR_DECODE:
+ if ((len <= rstrm->fbtbc) &&
+ ((rstrm->in_finger + len) <= rstrm->in_boundry)) {
+ buf = (int32_t *) rstrm->in_finger;
+ rstrm->fbtbc -= len;
+ rstrm->in_finger += len;
+ }
+ break;
+ case XDR_FREE: /* to avoid warning */
+ break;
+ }
+ return (buf);
+}
+
+static void
+xdrrec_destroy(xdrs)
+ register XDR *xdrs;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
+
+ mem_free(rstrm->the_buffer,
+ rstrm->sendsize + rstrm->recvsize + BYTES_PER_XDR_UNIT);
+ mem_free((caddr_t)rstrm, sizeof(RECSTREAM));
+}
+
+
+/*
+ * Exported routines to manage xdr records
+ */
+
+/*
+ * Before reading (deserializing from the stream, one should always call
+ * this procedure to guarantee proper record alignment.
+ */
+bool_t
+xdrrec_skiprecord(xdrs)
+ XDR *xdrs;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+
+ while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) {
+ if (! skip_input_bytes(rstrm, rstrm->fbtbc))
+ return (FALSE);
+ rstrm->fbtbc = 0;
+ if ((! rstrm->last_frag) && (! set_input_fragment(rstrm)))
+ return (FALSE);
+ }
+ rstrm->last_frag = FALSE;
+ return (TRUE);
+}
+
+/*
+ * Look ahead fuction.
+ * Returns TRUE iff there is no more input in the buffer
+ * after consuming the rest of the current record.
+ */
+bool_t
+xdrrec_eof(xdrs)
+ XDR *xdrs;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+
+ while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) {
+ if (! skip_input_bytes(rstrm, rstrm->fbtbc))
+ return (TRUE);
+ rstrm->fbtbc = 0;
+ if ((! rstrm->last_frag) && (! set_input_fragment(rstrm)))
+ return (TRUE);
+ }
+ if (rstrm->in_finger == rstrm->in_boundry)
+ return (TRUE);
+ return (FALSE);
+}
+
+/*
+ * The client must tell the package when an end-of-record has occurred.
+ * The second paraemters tells whether the record should be flushed to the
+ * (output) tcp stream. (This let's the package support batched or
+ * pipelined procedure calls.) TRUE => immmediate flush to tcp connection.
+ */
+bool_t
+xdrrec_endofrecord(xdrs, sendnow)
+ XDR *xdrs;
+ bool_t sendnow;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ register u_long len; /* fragment length */
+
+ if (sendnow || rstrm->frag_sent ||
+ ((u_long)rstrm->out_finger + sizeof(u_int32_t) >=
+ (u_long)rstrm->out_boundry)) {
+ rstrm->frag_sent = FALSE;
+ return (flush_out(rstrm, TRUE));
+ }
+ len = (u_long)(rstrm->out_finger) - (u_long)(rstrm->frag_header) -
+ sizeof(u_int32_t);
+ *(rstrm->frag_header) = htonl((u_long)len | LAST_FRAG);
+ rstrm->frag_header = (u_int32_t *)rstrm->out_finger;
+ rstrm->out_finger += sizeof(u_int32_t);
+ return (TRUE);
+}
+
+
+/*
+ * Internal useful routines
+ */
+static bool_t
+flush_out(rstrm, eor)
+ register RECSTREAM *rstrm;
+ bool_t eor;
+{
+ register u_long eormask = (eor == TRUE) ? LAST_FRAG : 0;
+ register u_int32_t len = (u_long)(rstrm->out_finger) -
+ (u_long)(rstrm->frag_header) - sizeof(u_int32_t);
+
+ *(rstrm->frag_header) = htonl(len | eormask);
+ len = (u_long)(rstrm->out_finger) - (u_long)(rstrm->out_base);
+ if ((*(rstrm->writeit))(rstrm->tcp_handle, rstrm->out_base, (int)len)
+ != (int)len)
+ return (FALSE);
+ rstrm->frag_header = (u_int32_t *)rstrm->out_base;
+ rstrm->out_finger = (caddr_t)rstrm->out_base + sizeof(u_int32_t);
+ return (TRUE);
+}
+
+static bool_t /* knows nothing about records! Only about input buffers */
+fill_input_buf(rstrm)
+ register RECSTREAM *rstrm;
+{
+ register caddr_t where;
+ u_long i;
+ register long len;
+
+ where = rstrm->in_base;
+ i = (u_long)rstrm->in_boundry % BYTES_PER_XDR_UNIT;
+ where += i;
+ len = rstrm->in_size - i;
+ if ((len = (*(rstrm->readit))(rstrm->tcp_handle, where, len)) == -1)
+ return (FALSE);
+ rstrm->in_finger = where;
+ where += len;
+ rstrm->in_boundry = where;
+ return (TRUE);
+}
+
+static bool_t /* knows nothing about records! Only about input buffers */
+get_input_bytes(rstrm, addr, len)
+ register RECSTREAM *rstrm;
+ register caddr_t addr;
+ register int len;
+{
+ register long current;
+
+ while (len > 0) {
+ current = (long)rstrm->in_boundry - (long)rstrm->in_finger;
+ if (current == 0) {
+ if (! fill_input_buf(rstrm))
+ return (FALSE);
+ continue;
+ }
+ current = (len < current) ? len : current;
+ memcpy(addr, rstrm->in_finger, current);
+ rstrm->in_finger += current;
+ addr += current;
+ len -= current;
+ }
+ return (TRUE);
+}
+
+static bool_t /* next two bytes of the input stream are treated as a header */
+set_input_fragment(rstrm)
+ register RECSTREAM *rstrm;
+{
+ u_int32_t header;
+
+ if (! get_input_bytes(rstrm, (caddr_t)&header, sizeof(header)))
+ return (FALSE);
+ header = (long)ntohl(header);
+ rstrm->last_frag = ((header & LAST_FRAG) == 0) ? FALSE : TRUE;
+ /*
+ * Sanity check. Try not to accept wildly incorrect
+ * record sizes. Unfortunately, the only record size
+ * we can positively identify as being 'wildly incorrect'
+ * is zero. Ridiculously large record sizes may look wrong,
+ * but we don't have any way to be certain that they aren't
+ * what the client actually intended to send us.
+ */
+ if (header == 0)
+ return(FALSE);
+ rstrm->fbtbc = header & (~LAST_FRAG);
+ return (TRUE);
+}
+
+static bool_t /* consumes input bytes; knows nothing about records! */
+skip_input_bytes(rstrm, cnt)
+ register RECSTREAM *rstrm;
+ long cnt;
+{
+ register long current;
+
+ while (cnt > 0) {
+ current = (long)rstrm->in_boundry - (long)rstrm->in_finger;
+ if (current == 0) {
+ if (! fill_input_buf(rstrm))
+ return (FALSE);
+ continue;
+ }
+ current = (cnt < current) ? cnt : current;
+ rstrm->in_finger += current;
+ cnt -= current;
+ }
+ return (TRUE);
+}
+
+static u_int
+fix_buf_size(s)
+ register u_int s;
+{
+
+ if (s < 100)
+ s = 4000;
+ return (RNDUP(s));
+}
diff --git a/cpukit/librpc/src/xdr/xdr_reference.c b/cpukit/librpc/src/xdr/xdr_reference.c
new file mode 100644
index 0000000000..41ac34b220
--- /dev/null
+++ b/cpukit/librpc/src/xdr/xdr_reference.c
@@ -0,0 +1,138 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)xdr_reference.c 1.11 87/08/11 SMI";*/
+/*static char *sccsid = "from: @(#)xdr_reference.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/xdr/xdr_reference.c,v 1.8 1999/08/28 00:02:56 peter Exp $";
+#endif
+
+/*
+ * xdr_reference.c, Generic XDR routines impelmentation.
+ *
+ * Copyright (C) 1987, Sun Microsystems, Inc.
+ *
+ * These are the "non-trivial" xdr primitives used to serialize and de-serialize
+ * "pointers". See xdr.h for more info on the interface to xdr.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+
+#define LASTUNSIGNED ((u_int) 0-1)
+
+/*
+ * XDR an indirect pointer
+ * xdr_reference is for recursively translating a structure that is
+ * referenced by a pointer inside the structure that is currently being
+ * translated. pp references a pointer to storage. If *pp is null
+ * the necessary storage is allocated.
+ * size is the sizeof the referneced structure.
+ * proc is the routine to handle the referenced structure.
+ */
+bool_t
+xdr_reference(xdrs, pp, size, proc)
+ register XDR *xdrs;
+ caddr_t *pp; /* the pointer to work on */
+ u_int size; /* size of the object pointed to */
+ xdrproc_t proc; /* xdr routine to handle the object */
+{
+ register caddr_t loc = *pp;
+ register bool_t stat;
+
+ if (loc == NULL)
+ switch (xdrs->x_op) {
+ case XDR_FREE:
+ return (TRUE);
+
+ case XDR_DECODE:
+ *pp = loc = (caddr_t) mem_alloc(size);
+ if (loc == NULL) {
+ (void) fprintf(stderr,
+ "xdr_reference: out of memory\n");
+ return (FALSE);
+ }
+ memset(loc, 0, (int)size);
+ break;
+ case XDR_ENCODE: /* to avoid warning */
+ break;
+ }
+
+ stat = (*proc)(xdrs, loc, LASTUNSIGNED);
+
+ if (xdrs->x_op == XDR_FREE) {
+ mem_free(loc, size);
+ *pp = NULL;
+ }
+ return (stat);
+}
+
+
+/*
+ * xdr_pointer():
+ *
+ * XDR a pointer to a possibly recursive data structure. This
+ * differs with xdr_reference in that it can serialize/deserialiaze
+ * trees correctly.
+ *
+ * What's sent is actually a union:
+ *
+ * union object_pointer switch (boolean b) {
+ * case TRUE: object_data data;
+ * case FALSE: void nothing;
+ * }
+ *
+ * > objpp: Pointer to the pointer to the object.
+ * > obj_size: size of the object.
+ * > xdr_obj: routine to XDR an object.
+ *
+ */
+bool_t
+xdr_pointer(xdrs,objpp,obj_size,xdr_obj)
+ register XDR *xdrs;
+ char **objpp;
+ u_int obj_size;
+ xdrproc_t xdr_obj;
+{
+
+ bool_t more_data;
+
+ more_data = (*objpp != NULL);
+ if (! xdr_bool(xdrs,&more_data)) {
+ return (FALSE);
+ }
+ if (! more_data) {
+ *objpp = NULL;
+ return (TRUE);
+ }
+ return (xdr_reference(xdrs,objpp,obj_size,xdr_obj));
+}
diff --git a/cpukit/librpc/src/xdr/xdr_sizeof.c b/cpukit/librpc/src/xdr/xdr_sizeof.c
new file mode 100644
index 0000000000..5a4c1a78dc
--- /dev/null
+++ b/cpukit/librpc/src/xdr/xdr_sizeof.c
@@ -0,0 +1,163 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * xdr_sizeof.c
+ *
+ * Copyright 1990 Sun Microsystems, Inc.
+ *
+ * General purpose routine to see how much space something will use
+ * when serialized using XDR.
+ */
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <sys/types.h>
+#include <stdlib.h>
+
+/* ARGSUSED */
+static bool_t
+x_putlong(xdrs, longp)
+ XDR *xdrs;
+ long *longp;
+{
+ xdrs->x_handy += BYTES_PER_XDR_UNIT;
+ return (TRUE);
+}
+
+/* ARGSUSED */
+static bool_t
+x_putbytes(xdrs, bp, len)
+ XDR *xdrs;
+ char *bp;
+ int len;
+{
+ xdrs->x_handy += len;
+ return (TRUE);
+}
+
+static u_int
+x_getpostn(xdrs)
+ XDR *xdrs;
+{
+ return (xdrs->x_handy);
+}
+
+/* ARGSUSED */
+static bool_t
+x_setpostn(xdrs, pos)
+ XDR *xdrs;
+ u_int pos;
+{
+ /* This is not allowed */
+ return (FALSE);
+}
+
+static int32_t *
+x_inline(xdrs, len)
+ XDR *xdrs;
+ long len;
+{
+ if (len == 0) {
+ return (NULL);
+ }
+ if (xdrs->x_op != XDR_ENCODE) {
+ return (NULL);
+ }
+ if (len < (long) xdrs->x_base) {
+ /* x_private was already allocated */
+ xdrs->x_handy += len;
+ return ((int32_t *) xdrs->x_private);
+ } else {
+ /* Free the earlier space and allocate new area */
+ if (xdrs->x_private)
+ free(xdrs->x_private);
+ if ((xdrs->x_private = (caddr_t) malloc(len)) == NULL) {
+ xdrs->x_base = 0;
+ return (NULL);
+ }
+ xdrs->x_base = (caddr_t) len;
+ xdrs->x_handy += len;
+ return ((int32_t *) xdrs->x_private);
+ }
+}
+
+static int
+harmless()
+{
+ /* Always return FALSE/NULL, as the case may be */
+ return (0);
+}
+
+static void
+x_destroy(xdrs)
+ XDR *xdrs;
+{
+ xdrs->x_handy = 0;
+ xdrs->x_base = 0;
+ if (xdrs->x_private) {
+ free(xdrs->x_private);
+ xdrs->x_private = NULL;
+ }
+ return;
+}
+
+unsigned long
+xdr_sizeof(func, data)
+ xdrproc_t func;
+ void *data;
+{
+ XDR x;
+ struct xdr_ops ops;
+ bool_t stat;
+ /* to stop ANSI-C compiler from complaining */
+ typedef bool_t (* dummyfunc1)(XDR *, long *);
+ typedef bool_t (* dummyfunc2)(XDR *, caddr_t, u_int);
+
+ ops.x_putlong = x_putlong;
+ ops.x_putbytes = x_putbytes;
+ ops.x_inline = x_inline;
+ ops.x_getpostn = x_getpostn;
+ ops.x_setpostn = x_setpostn;
+ ops.x_destroy = x_destroy;
+
+ /* the other harmless ones */
+ ops.x_getlong = (dummyfunc1) harmless;
+ ops.x_getbytes = (dummyfunc2) harmless;
+
+ x.x_op = XDR_ENCODE;
+ x.x_ops = &ops;
+ x.x_handy = 0;
+ x.x_private = (caddr_t) NULL;
+ x.x_base = (caddr_t) 0;
+
+ stat = func(&x, data);
+ if (x.x_private)
+ free(x.x_private);
+ return (stat == TRUE ? (unsigned) x.x_handy: 0);
+}
diff --git a/cpukit/librpc/src/xdr/xdr_stdio.c b/cpukit/librpc/src/xdr/xdr_stdio.c
new file mode 100644
index 0000000000..f19395f9ba
--- /dev/null
+++ b/cpukit/librpc/src/xdr/xdr_stdio.c
@@ -0,0 +1,190 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char *sccsid = "from: @(#)xdr_stdio.c 1.16 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)xdr_stdio.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$FreeBSD: src/lib/libc/xdr/xdr_stdio.c,v 1.7 1999/08/28 00:02:56 peter Exp $";
+#endif
+
+/*
+ * xdr_stdio.c, XDR implementation on standard i/o file.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * This set of routines implements a XDR on a stdio stream.
+ * XDR_ENCODE serializes onto the stream, XDR_DECODE de-serializes
+ * from the stream.
+ */
+
+#include <rpc/types.h>
+#include <stdio.h>
+#include <rpc/xdr.h>
+#include <netinet/in.h>
+
+static bool_t xdrstdio_getlong();
+static bool_t xdrstdio_putlong();
+static bool_t xdrstdio_getbytes();
+static bool_t xdrstdio_putbytes();
+static u_int xdrstdio_getpos();
+static bool_t xdrstdio_setpos();
+static int32_t *xdrstdio_inline();
+static void xdrstdio_destroy();
+
+/*
+ * Ops vector for stdio type XDR
+ */
+static struct xdr_ops xdrstdio_ops = {
+ xdrstdio_getlong, /* deseraialize a long int */
+ xdrstdio_putlong, /* seraialize a long int */
+ xdrstdio_getbytes, /* deserialize counted bytes */
+ xdrstdio_putbytes, /* serialize counted bytes */
+ xdrstdio_getpos, /* get offset in the stream */
+ xdrstdio_setpos, /* set offset in the stream */
+ xdrstdio_inline, /* prime stream for inline macros */
+ xdrstdio_destroy /* destroy stream */
+};
+
+/*
+ * Initialize a stdio xdr stream.
+ * Sets the xdr stream handle xdrs for use on the stream file.
+ * Operation flag is set to op.
+ */
+void
+xdrstdio_create(xdrs, file, op)
+ register XDR *xdrs;
+ FILE *file;
+ enum xdr_op op;
+{
+
+ xdrs->x_op = op;
+ xdrs->x_ops = &xdrstdio_ops;
+ xdrs->x_private = (caddr_t)file;
+ xdrs->x_handy = 0;
+ xdrs->x_base = 0;
+}
+
+/*
+ * Destroy a stdio xdr stream.
+ * Cleans up the xdr stream handle xdrs previously set up by xdrstdio_create.
+ */
+static void
+xdrstdio_destroy(xdrs)
+ register XDR *xdrs;
+{
+ (void)fflush((FILE *)xdrs->x_private);
+ /* xx should we close the file ?? */
+}
+
+static bool_t
+xdrstdio_getlong(xdrs, lp)
+ XDR *xdrs;
+ register long *lp;
+{
+
+ if (fread((caddr_t)lp, sizeof(int32_t), 1,
+ (FILE *)xdrs->x_private) != 1)
+ return (FALSE);
+ *lp = (long)ntohl((int32_t)*lp);
+ return (TRUE);
+}
+
+static bool_t
+xdrstdio_putlong(xdrs, lp)
+ XDR *xdrs;
+ long *lp;
+{
+
+ long mycopy = (long)htonl((int32_t)*lp);
+
+ if (fwrite((caddr_t)&mycopy, sizeof(int32_t), 1,
+ (FILE *)xdrs->x_private) != 1)
+ return (FALSE);
+ return (TRUE);
+}
+
+static bool_t
+xdrstdio_getbytes(xdrs, addr, len)
+ XDR *xdrs;
+ caddr_t addr;
+ u_int len;
+{
+
+ if ((len != 0) && (fread(addr, (int)len, 1, (FILE *)xdrs->x_private) != 1))
+ return (FALSE);
+ return (TRUE);
+}
+
+static bool_t
+xdrstdio_putbytes(xdrs, addr, len)
+ XDR *xdrs;
+ caddr_t addr;
+ u_int len;
+{
+
+ if ((len != 0) && (fwrite(addr, (int)len, 1, (FILE *)xdrs->x_private) != 1))
+ return (FALSE);
+ return (TRUE);
+}
+
+static u_int
+xdrstdio_getpos(xdrs)
+ XDR *xdrs;
+{
+
+ return ((u_int) ftell((FILE *)xdrs->x_private));
+}
+
+static bool_t
+xdrstdio_setpos(xdrs, pos)
+ XDR *xdrs;
+ u_int pos;
+{
+
+ return ((fseek((FILE *)xdrs->x_private, (long)pos, 0) < 0) ?
+ FALSE : TRUE);
+}
+
+static int32_t *
+xdrstdio_inline(xdrs, len)
+ XDR *xdrs;
+ u_int len;
+{
+
+ /*
+ * Must do some work to implement this: must insure
+ * enough data in the underlying stdio buffer,
+ * that the buffer is aligned so that we can indirect through a
+ * long *, and stuff this pointer in xdrs->x_buf. Doing
+ * a fread or fwrite to a scratch buffer would defeat
+ * most of the gains to be had here and require storage
+ * management on this buffer, so we don't do this.
+ */
+ return (NULL);
+}
diff --git a/cpukit/posix/.cvsignore b/cpukit/posix/.cvsignore
new file mode 100644
index 0000000000..282522db03
--- /dev/null
+++ b/cpukit/posix/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/cpukit/posix/Makefile.am b/cpukit/posix/Makefile.am
new file mode 100644
index 0000000000..ab5b4824d7
--- /dev/null
+++ b/cpukit/posix/Makefile.am
@@ -0,0 +1,360 @@
+##
+## $Id$
+##
+
+include $(top_srcdir)/automake/multilib.am
+include $(top_srcdir)/automake/compile.am
+
+EXTRA_DIST =
+CLEANFILES =
+
+if HAS_POSIX
+
+# include
+
+noinst_HEADERS = include/devctl.h include/intr.h
+
+include_HEADERS = include/sched.h include/aio.h include/mqueue.h \
+ include/semaphore.h
+
+# include/rtems/posix
+
+include_rtems_posixdir = $(includedir)/rtems/posix
+
+include_rtems_posix_HEADERS = include/rtems/posix/cancel.h \
+ include/rtems/posix/cond.h include/rtems/posix/config.h \
+ include/rtems/posix/key.h include/rtems/posix/mqueue.h \
+ include/rtems/posix/mutex.h include/rtems/posix/posixapi.h \
+ include/rtems/posix/priority.h include/rtems/posix/psignal.h \
+ include/rtems/posix/pthread.h include/rtems/posix/ptimer.h \
+ include/rtems/posix/semaphore.h include/rtems/posix/threadsup.h \
+ include/rtems/posix/time.h include/rtems/posix/timer.h
+
+if HAS_MP
+include_rtems_posix_HEADERS += include/rtems/posix/condmp.h \
+ include/rtems/posix/mqueuemp.h include/rtems/posix/mutexmp.h \
+ include/rtems/posix/pthreadmp.h include/rtems/posix/semaphoremp.h
+endif
+
+noinst_HEADERS += include/rtems/posix/intr.h \
+ include/rtems/posix/threadsup.h
+
+if INLINE
+include_rtems_posix_HEADERS += inline/rtems/posix/cond.inl \
+ inline/rtems/posix/key.inl inline/rtems/posix/mqueue.inl \
+ inline/rtems/posix/mutex.inl inline/rtems/posix/pthread.inl \
+ inline/rtems/posix/priority.inl inline/rtems/posix/semaphore.inl \
+ inline/rtems/posix/timer.inl
+noinst_HEADERS += inline/rtems/posix/intr.inl
+else
+include_rtems_posix_HEADERS += macros/rtems/posix/cond.inl \
+ macros/rtems/posix/key.inl macros/rtems/posix/mqueue.inl \
+ macros/rtems/posix/mutex.inl macros/rtems/posix/pthread.inl \
+ macros/rtems/posix/priority.inl macros/rtems/posix/semaphore.inl \
+ macros/rtems/posix/timer.inl
+noinst_HEADERS += macros/rtems/posix/intr.inl
+endif
+
+## src
+
+# following are semi-implemented and untested
+UNUSED_C_FILES = src/devctl.c src/intr.c
+
+# These are really in the stand but not really functional
+BUILD_FOR_NOW_C_FILES = src/aio.c
+
+ENOSYS_C_FILES = src/execl.c src/execle.c src/execlp.c src/execv.c \
+ src/execve.c src/execvp.c src/fork.c src/pthreadatfork.c src/wait.c \
+ src/waitpid.c
+
+CANCEL_C_FILES = src/cancel.c src/cancelrun.c src/cleanuppop.c \
+ src/cleanuppush.c src/setcancelstate.c src/setcanceltype.c \
+ src/testcancel.c
+
+CONDITION_VARIABLE_C_FILES = src/cond.c src/condattrdestroy.c \
+ src/condattrgetpshared.c src/condattrinit.c src/condattrsetpshared.c \
+ src/condbroadcast.c src/conddefaultattributes.c src/conddestroy.c \
+ src/condinit.c src/condmp.c src/condsignal.c src/condsignalsupp.c \
+ src/condtimedwait.c src/condwait.c src/condwaitsupp.c
+
+KEY_C_FILES = src/key.c src/keycreate.c src/keydelete.c src/keygetspecific.c \
+ src/keyrundestructors.c src/keysetspecific.c
+
+MEMORY_C_FILES = src/getpagesize.c src/mprotect.c
+
+MESSAGE_QUEUE_C_FILES = src/mqueue.c src/mqueueclose.c \
+ src/mqueuecreatesupp.c src/mqueuedeletesupp.c src/mqueuegetattr.c \
+ src/mqueuenametoid.c src/mqueuenotify.c src/mqueueopen.c \
+ src/mqueuereceive.c src/mqueuerecvsupp.c src/mqueuesend.c \
+ src/mqueuesendsupp.c src/mqueuesetattr.c src/mqueuetimedreceive.c \
+ src/mqueuetimedsend.c src/mqueuetranslatereturncode.c \
+ src/mqueueunlink.c
+
+MUTEX_C_FILES = src/mutex.c src/mutexattrdestroy.c \
+ src/mutexattrgetprioceiling.c src/mutexattrgetprotocol.c \
+ src/mutexattrgetpshared.c src/mutexattrinit.c \
+ src/mutexattrsetprioceiling.c src/mutexattrsetprotocol.c \
+ src/mutexattrsetpshared.c src/mutexdefaultattributes.c \
+ src/mutexdestroy.c src/mutexfromcorestatus.c src/mutexgetprioceiling.c \
+ src/mutexinit.c src/mutexlock.c src/mutexlocksupp.c src/mutexmp.c \
+ src/mutexsetprioceiling.c src/mutextimedlock.c src/mutextrylock.c \
+ src/mutexunlock.c
+
+PTHREAD_C_FILES = src/pthread.c src/pthreadsetcputime.c \
+ src/pthreadgetcputime.c src/pthreadgetcpuclockid.c src/pthreadonce.c \
+ src/pthreadequal.c src/pthreadself.c src/pthreadexit.c \
+ src/pthreaddetach.c src/pthreadjoin.c src/pthreadcreate.c \
+ src/pthreadattrsetdetachstate.c src/pthreadattrgetdetachstate.c \
+ src/pthreadattrgetstackaddr.c src/pthreadattrsetstackaddr.c \
+ src/pthreadattrgetstacksize.c src/pthreadattrsetstacksize.c \
+ src/pthreadattrinit.c src/pthreadattrdestroy.c \
+ src/pthreadsetschedparam.c src/pthreadgetschedparam.c \
+ src/pthreadattrsetschedparam.c src/pthreadattrgetschedparam.c \
+ src/pthreadattrgetschedpolicy.c src/pthreadattrsetschedpolicy.c \
+ src/pthreadattrgetinheritsched.c src/pthreadattrsetinheritsched.c \
+ src/pthreadattrgetscope.c src/pthreadattrsetscope.c
+
+PSIGNAL_C_FILES = src/psignal.c src/alarm.c src/kill.c src/killinfo.c \
+ src/pause.c src/psignalclearprocesssignals.c \
+ src/psignalsetprocesssignals.c src/psignalchecksignal.c \
+ src/psignalclearsignals.c src/psignalunblockthread.c src/pthreadkill.c \
+ src/pthreadsigmask.c src/sigaction.c src/sigaddset.c src/sigdelset.c \
+ src/sigemptyset.c src/sigfillset.c src/sigismember.c src/sigpending.c \
+ src/sigprocmask.c src/sigqueue.c src/sigsuspend.c src/sigtimedwait.c \
+ src/sigwait.c src/sigwaitinfo.c src/signal_2.c src/ualarm.c
+
+SEMAPHORE_C_FILES = src/semaphore.c src/semaphorecreatesupp.c \
+ src/semaphoredeletesupp.c src/semaphoremp.c src/semaphorenametoid.c \
+ src/semaphorewaitsupp.c src/semclose.c src/semdestroy.c \
+ src/semgetvalue.c src/seminit.c src/semopen.c src/sempost.c \
+ src/semtimedwait.c src/semtrywait.c src/semunlink.c src/semwait.c
+
+TIME_C_FILES = src/adjtime.c src/time.c src/posixtimespecsubtract.c \
+ src/posixtimespectointerval.c src/posixintervaltotimespec.c \
+ src/clockgetcpuclockid.c src/clockgetenableattr.c src/clockgetres.c \
+ src/clockgettime.c src/clocksetenableattr.c src/clocksettime.c \
+ src/nanosleep.c src/sleep.c src/usleep.c
+
+# the timer manager needs to be split further but only after its
+# dependence on the Classic API Timer Manager is removed.
+TIMER_C_FILES = src/ptimer.c src/ptimer1.c
+
+EXTRA_DIST += src/README.mqueue
+
+C_FILES = src/adasupp.c $(CANCEL_C_FILES) $(CONDITION_VARIABLE_C_FILES) \
+ $(KEY_C_FILES) $(MEMORY_C_FILES) $(MESSAGE_QUEUE_C_FILES) \
+ $(MUTEX_C_FILES) $(PTHREAD_C_FILES) $(PSIGNAL_C_FILES) src/sched.c \
+ $(SEMAPHORE_C_FILES) src/sysconf.c $(TIME_C_FILES) $(TIMER_C_FILES) \
+ src/types.c $(ENOSYS_C_FILES) $(BUILD_FOR_NOW_C_FILES)
+
+AM_CPPFLAGS += -I$(top_builddir)
+AM_CPPFLAGS += -D__RTEMS_INSIDE__
+
+EXTRA_LIBRARIES = libposix.a
+CLEANFILES += libposix.a
+libposix_a_SOURCES = $(C_FILES)
+libposix_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libposix_g.a
+CLEANFILES += libposix_g.a
+libposix_g_a_SOURCES = $(libposix_a_SOURCES)
+libposix_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+all-local: $(PREINSTALL_FILES) libposix$(LIB_VARIANT).a
+endif
+
+# temporary so we can see how many things are left to implement
+not:
+ grep -i NOT_IMPL $(C_FILES:%=$(srcdir)/%) | grep -v MP_NOT_IMPL
+ @echo
+ @echo
+ @echo
+ @echo `grep -i NOT_IMPL $(C_FILES:%=$(srcdir)/%) | grep -v MP_NOT_IMPL | wc -l ` places marked not implemented
+ @echo `wc -l $(C_FILES:%=$(srcdir)/%) | grep total` lines of C code to test
+
+EXTRA_DIST += $(C_FILES) $(UNUSED_C_FILES)
+
+PREINSTALL_DIRS =
+PREINSTALL_FILES =
+
+$(PROJECT_INCLUDE)/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)
+ @: > $(PROJECT_INCLUDE)/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/$(dirstamp)
+
+if HAS_POSIX
+$(PROJECT_INCLUDE)/sched.h: include/sched.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/sched.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/sched.h
+
+$(PROJECT_INCLUDE)/aio.h: include/aio.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/aio.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/aio.h
+
+$(PROJECT_INCLUDE)/mqueue.h: include/mqueue.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/mqueue.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/mqueue.h
+
+$(PROJECT_INCLUDE)/semaphore.h: include/semaphore.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/semaphore.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/semaphore.h
+
+$(PROJECT_INCLUDE)/rtems/posix/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems/posix
+ @: > $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/posix/cancel.h: include/rtems/posix/cancel.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/cancel.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/cancel.h
+
+$(PROJECT_INCLUDE)/rtems/posix/cond.h: include/rtems/posix/cond.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/cond.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/cond.h
+
+$(PROJECT_INCLUDE)/rtems/posix/config.h: include/rtems/posix/config.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/config.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/config.h
+
+$(PROJECT_INCLUDE)/rtems/posix/key.h: include/rtems/posix/key.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/key.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/key.h
+
+$(PROJECT_INCLUDE)/rtems/posix/mqueue.h: include/rtems/posix/mqueue.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/mqueue.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/mqueue.h
+
+$(PROJECT_INCLUDE)/rtems/posix/mutex.h: include/rtems/posix/mutex.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/mutex.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/mutex.h
+
+$(PROJECT_INCLUDE)/rtems/posix/posixapi.h: include/rtems/posix/posixapi.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/posixapi.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/posixapi.h
+
+$(PROJECT_INCLUDE)/rtems/posix/priority.h: include/rtems/posix/priority.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/priority.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/priority.h
+
+$(PROJECT_INCLUDE)/rtems/posix/psignal.h: include/rtems/posix/psignal.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/psignal.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/psignal.h
+
+$(PROJECT_INCLUDE)/rtems/posix/pthread.h: include/rtems/posix/pthread.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/pthread.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/pthread.h
+
+$(PROJECT_INCLUDE)/rtems/posix/ptimer.h: include/rtems/posix/ptimer.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/ptimer.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/ptimer.h
+
+$(PROJECT_INCLUDE)/rtems/posix/semaphore.h: include/rtems/posix/semaphore.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/semaphore.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/semaphore.h
+
+$(PROJECT_INCLUDE)/rtems/posix/threadsup.h: include/rtems/posix/threadsup.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/threadsup.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/threadsup.h
+
+$(PROJECT_INCLUDE)/rtems/posix/time.h: include/rtems/posix/time.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/time.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/time.h
+
+$(PROJECT_INCLUDE)/rtems/posix/timer.h: include/rtems/posix/timer.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/timer.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/timer.h
+
+if HAS_MP
+$(PROJECT_INCLUDE)/rtems/posix/condmp.h: include/rtems/posix/condmp.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/condmp.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/condmp.h
+
+$(PROJECT_INCLUDE)/rtems/posix/mqueuemp.h: include/rtems/posix/mqueuemp.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/mqueuemp.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/mqueuemp.h
+
+$(PROJECT_INCLUDE)/rtems/posix/mutexmp.h: include/rtems/posix/mutexmp.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/mutexmp.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/mutexmp.h
+
+$(PROJECT_INCLUDE)/rtems/posix/pthreadmp.h: include/rtems/posix/pthreadmp.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/pthreadmp.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/pthreadmp.h
+
+$(PROJECT_INCLUDE)/rtems/posix/semaphoremp.h: include/rtems/posix/semaphoremp.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/semaphoremp.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/semaphoremp.h
+endif
+
+if INLINE
+$(PROJECT_INCLUDE)/rtems/posix/cond.inl: inline/rtems/posix/cond.inl $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/cond.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/cond.inl
+
+$(PROJECT_INCLUDE)/rtems/posix/key.inl: inline/rtems/posix/key.inl $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/key.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/key.inl
+
+$(PROJECT_INCLUDE)/rtems/posix/mqueue.inl: inline/rtems/posix/mqueue.inl $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/mqueue.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/mqueue.inl
+
+$(PROJECT_INCLUDE)/rtems/posix/mutex.inl: inline/rtems/posix/mutex.inl $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/mutex.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/mutex.inl
+
+$(PROJECT_INCLUDE)/rtems/posix/pthread.inl: inline/rtems/posix/pthread.inl $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/pthread.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/pthread.inl
+
+$(PROJECT_INCLUDE)/rtems/posix/priority.inl: inline/rtems/posix/priority.inl $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/priority.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/priority.inl
+
+$(PROJECT_INCLUDE)/rtems/posix/semaphore.inl: inline/rtems/posix/semaphore.inl $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/semaphore.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/semaphore.inl
+
+$(PROJECT_INCLUDE)/rtems/posix/timer.inl: inline/rtems/posix/timer.inl $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/timer.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/timer.inl
+
+else
+$(PROJECT_INCLUDE)/rtems/posix/cond.inl: macros/rtems/posix/cond.inl $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/cond.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/cond.inl
+
+$(PROJECT_INCLUDE)/rtems/posix/key.inl: macros/rtems/posix/key.inl $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/key.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/key.inl
+
+$(PROJECT_INCLUDE)/rtems/posix/mqueue.inl: macros/rtems/posix/mqueue.inl $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/mqueue.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/mqueue.inl
+
+$(PROJECT_INCLUDE)/rtems/posix/mutex.inl: macros/rtems/posix/mutex.inl $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/mutex.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/mutex.inl
+
+$(PROJECT_INCLUDE)/rtems/posix/pthread.inl: macros/rtems/posix/pthread.inl $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/pthread.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/pthread.inl
+
+$(PROJECT_INCLUDE)/rtems/posix/priority.inl: macros/rtems/posix/priority.inl $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/priority.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/priority.inl
+
+$(PROJECT_INCLUDE)/rtems/posix/semaphore.inl: macros/rtems/posix/semaphore.inl $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/semaphore.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/semaphore.inl
+
+$(PROJECT_INCLUDE)/rtems/posix/timer.inl: macros/rtems/posix/timer.inl $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/timer.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/timer.inl
+endif
+endif
+
+CLEANFILES += $(PREINSTALL_FILES)
+DISTCLEANFILES = $(PREINSTALL_DIRS)
+
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/posix/include/aio.h b/cpukit/posix/include/aio.h
new file mode 100644
index 0000000000..cc9b17a5b4
--- /dev/null
+++ b/cpukit/posix/include/aio.h
@@ -0,0 +1,145 @@
+/* aio.h
+ *
+ * $Id$
+ */
+
+#ifndef __POSIX_ASYNCHRONOUS_IO_h
+#define __POSIX_ASYNCHRONOUS_IO_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/features.h>
+
+#if defined(_POSIX_ASYNCHRONOUS_IO)
+
+/*
+ * 6.7.1 Data Definitions for Asynchronous Input and Output,
+ * P1003.1b-1993, p. 151
+ */
+
+#include <sys/types.h>
+#include <signal.h>
+#include <time.h>
+#include <fcntl.h>
+
+/*
+ * 6.7.1.2 Manifest Constants, P1003.1b-1993, p. 153
+ */
+
+#define AIO_CANCELED 0 /* all requested operations have been canceled */
+#define AIO_NOTCANCELED 1 /* some of the operations could not be canceled */
+ /* since they are in progress */
+#define AIO_ALLDONE 2 /* none of the requested operations could be */
+ /* canceled since they are already complete */
+
+/* lio_listio() options */
+
+#define LIO_WAIT 0 /* calling process is to suspend until the */
+ /* operation is complete */
+#define LIO_NOWAIT 1 /* calling process is to continue execution while */
+ /* the operation is performed and no notification */
+ /* shall be given when the operation is completed */
+#define LIO_READ 2 /* request a read() */
+#define LIO_WRITE 3 /* request a write() */
+#define LIO_NOP 4 /* no transfer is requested */
+
+/*
+ * 6.7.1.1 Asynchronous I/O Control Block, P1003.1b-1993, p. 151
+ */
+
+struct aiocb {
+ int aio_fildes; /* File descriptor */
+ off_t aio_offset; /* File offset */
+ volatile void *aio_buf; /* Location of buffer */
+ size_t aio_nbytes; /* Length of transfer */
+ int aio_reqprio; /* Request priority offset */
+ struct sigevent aio_sigevent; /* Signal number and value */
+ int aoi_lio_opcode; /* Operation to be performed */
+};
+
+/*
+ * 6.7.2 Asynchronous Read, P1003.1b-1993, p. 154
+ */
+
+int aio_read(
+ struct aiocb *aiocbp
+);
+
+/*
+ * 6.7.3 Asynchronous Write, P1003.1b-1993, p. 155
+ */
+
+int aio_write(
+ struct aiocb *aiocbp
+);
+
+/*
+ * 6.7.4 List Directed I/O, P1003.1b-1993, p. 158
+ */
+
+int lio_listio(
+ int mode,
+ struct aiocb * const list[],
+ int nent,
+ struct sigevent *sig
+);
+
+/*
+ * 6.7.5 Retrieve Error of Asynchronous I/O Operation, P1003.1b-1993, p. 161
+ */
+
+int aio_error(
+ const struct aiocb *aiocbp
+);
+
+/*
+ * 6.7.6 Retrieve Return Status of Asynchronous I/O Operation,
+ * P1003.1b-1993, p. 162
+ */
+
+int aio_return(
+ const struct aiocb *aiocbp
+);
+
+/*
+ * 6.7.7 Cancel Asynchronous I/O Operation, P1003.1b-1993, p. 163
+ */
+
+int aio_cancel(
+ int filedes,
+ struct aiocb *aiocbp
+);
+
+/*
+ * 6.7.7 Wait for Asynchronous I/O Request, P1003.1b-1993, p. 164
+ */
+
+int aio_suspend(
+ struct aiocb * const list[],
+ int nent,
+ const struct timespec *timeout
+);
+
+#if defined(_POSIX_SYNCHRONIZED_IO)
+
+/*
+ * 6.7.9 Asynchronous File Synchronization, P1003.1b-1993, p. 166
+ */
+
+int aio_fsync(
+ int op,
+ struct aiocb *aiocbp
+);
+
+#endif /* _POSIX_SYNCHRONIZED_IO */
+
+#endif /* _POSIX_ASYNCHRONOUS_IO */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/posix/include/devctl.h b/cpukit/posix/include/devctl.h
new file mode 100644
index 0000000000..85fca4cc11
--- /dev/null
+++ b/cpukit/posix/include/devctl.h
@@ -0,0 +1,38 @@
+/* devctl.h
+ *
+ * $Id$
+ */
+
+#ifndef __POSIX_DEVICE_CONTROL_h
+#define __POSIX_DEVICE_CONTROL_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/features.h>
+
+#if defined(_POSIX_DEVICE_CONTROL)
+
+#include <sys/types.h>
+#include <unistd.h>
+
+/*
+ * 21.2.1 Control a Device, P1003.4b/D8, p. 65
+ */
+
+int devctl(
+ int filedes,
+ void *dev_data_ptr,
+ size_t nbyte,
+ int *dev_info_ptr
+);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/posix/include/intr.h b/cpukit/posix/include/intr.h
new file mode 100644
index 0000000000..1464f68b1e
--- /dev/null
+++ b/cpukit/posix/include/intr.h
@@ -0,0 +1,80 @@
+/* intr.h
+ *
+ * XXX: It is unclear if the type "intr_t" should be defined when
+ * _POSIX_INTERRUPT_CONTROL is not.
+ *
+ * $Id$
+ */
+
+#ifndef __POSIX_INTERRUPTS_h
+#define __POSIX_INTERRUPTS_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/features.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+#if defined(_POSIX_INTERRUPT_CONTROL)
+
+/*
+ * 22.2 Concepts, P1003.4b/D8, p. 73
+ */
+
+typedef int intr_t;
+
+/*
+ * 22.3.1 Associate a User-Written ISR with an Interrupt, P1003.4b/D8, p. 74
+ */
+
+/*
+ * Return codes from an interrupt handler
+ */
+
+#define INTR_HANDLED_NOTIFY 0 /* ISR handled this interrupt, notify */
+ /* the thread that registered the */
+ /* ISR that the interrupt occurred. */
+#define INTR_HANDLED_DO_NOT_NOTIFY 1 /* ISR handled this interrupt, but */
+ /* do NOT perform notification. */
+#define INTR_NOT_HANDLED 2 /* ISR did not handle this interrupt, */
+ /* let the next handler try. */
+
+int intr_capture(
+ intr_t intr,
+ int (*intr_handler)( void *area ),
+ volatile void *area,
+ size_t areasize
+);
+
+int intr_release(
+ intr_t intr,
+ int (*intr_handler)( void *area )
+);
+
+int intr_lock(
+ intr_t intr
+);
+
+int intr_unlock(
+ intr_t intr
+);
+
+/*
+ * 22.3.2 Await Interrupt Notification, P1003.4b/D8, p. 76
+ */
+
+int intr_timed_wait(
+ int flags,
+ const struct timespec *timeout
+);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/posix/include/mqueue.h b/cpukit/posix/include/mqueue.h
new file mode 100644
index 0000000000..0b1b834f82
--- /dev/null
+++ b/cpukit/posix/include/mqueue.h
@@ -0,0 +1,153 @@
+/* mqueue.h
+ *
+ * $Id$
+ */
+
+#ifndef __POSIX_MESSAGE_QUEUE_h
+#define __POSIX_MESSAGE_QUEUE_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/features.h>
+
+#if defined(_POSIX_MESSAGE_PASSING)
+
+#include <sys/types.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+
+/*
+ * 15.1.1 Data Structures, P1003.1b-1993, p. 271
+ */
+
+typedef Objects_Id mqd_t;
+
+struct mq_attr {
+ long mq_flags; /* Message queue flags */
+ long mq_maxmsg; /* Maximum number of messages */
+ long mq_msgsize; /* Maximum message size */
+ long mq_curmsgs; /* Number of messages currently queued */
+};
+
+/*
+ * 15.2.2 Open a Message Queue, P1003.1b-1993, p. 272
+ */
+
+mqd_t mq_open(
+ const char *name,
+ int oflag,
+ ...
+);
+
+/*
+ * 15.2.2 Close a Message Queue, P1003.1b-1993, p. 275
+ */
+
+int mq_close(
+ mqd_t mqdes
+);
+
+/*
+ * 15.2.2 Remove a Message Queue, P1003.1b-1993, p. 276
+ */
+
+int mq_unlink(
+ const char *name
+);
+
+/*
+ * 15.2.4 Send a Message to a Message Queue, P1003.1b-1993, p. 277
+ *
+ * NOTE: P1003.4b/D8, p. 45 adds mq_timedsend().
+ */
+
+int mq_send(
+ mqd_t mqdes,
+ const char *msg_ptr,
+ size_t msg_len,
+ unsigned int msg_prio
+);
+
+#if defined(_POSIX_TIMEOUTS)
+
+#include <time.h>
+
+int mq_timedsend(
+ mqd_t mqdes,
+ const char *msg_ptr,
+ size_t msg_len,
+ unsigned int msg_prio,
+ const struct timespec *timeout
+);
+
+#endif /* _POSIX_TIMEOUTS */
+
+/*
+ * 15.2.5 Receive a Message From a Message Queue, P1003.1b-1993, p. 279
+ *
+ * NOTE: P1003.4b/D8, p. 45 adds mq_timedreceive().
+ */
+
+ssize_t mq_receive(
+ mqd_t mqdes,
+ char *msg_ptr,
+ size_t msg_len,
+ unsigned int *msg_prio
+);
+
+#if defined(_POSIX_TIMEOUTS)
+
+int mq_timedreceive( /* XXX: should this be ssize_t */
+ mqd_t mqdes,
+ char *msg_ptr,
+ size_t msg_len,
+ unsigned int *msg_prio,
+ const struct timespec *timeout
+);
+
+#endif /* _POSIX_TIMEOUTS */
+
+#if defined(_POSIX_REALTIME_SIGNALS)
+
+/*
+ * 15.2.6 Notify Process that a Message is Available on a Queue,
+ * P1003.1b-1993, p. 280
+ */
+
+int mq_notify(
+ mqd_t mqdes,
+ const struct sigevent *notification
+);
+
+#endif /* _POSIX_REALTIME_SIGNALS */
+
+/*
+ * 15.2.7 Set Message Queue Attributes, P1003.1b-1993, p. 281
+ */
+
+int mq_setattr(
+ mqd_t mqdes,
+ const struct mq_attr *mqstat,
+ struct mq_attr *omqstat
+);
+
+/*
+ * 15.2.8 Get Message Queue Attributes, P1003.1b-1993, p. 283
+ */
+
+int mq_getattr(
+ mqd_t mqdes,
+ struct mq_attr *mqstat
+);
+
+#endif /* _POSIX_MESSAGE_PASSING */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/posix/include/rtems/posix/cancel.h b/cpukit/posix/include/rtems/posix/cancel.h
new file mode 100644
index 0000000000..935912a298
--- /dev/null
+++ b/cpukit/posix/include/rtems/posix/cancel.h
@@ -0,0 +1,29 @@
+/* rtems/posix/cancel.h
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_CANCEL_h
+#define __RTEMS_POSIX_CANCEL_h
+
+typedef struct {
+ Chain_Node Node;
+ void (*routine)( void * );
+ void *arg;
+} POSIX_Cancel_Handler_control;
+
+/*
+ * _POSIX_Threads_cancel_run
+ *
+ * DESCRIPTION:
+ *
+ * This support routine runs through the chain of cancel handlers that
+ * have been registered and executes them.
+ */
+
+void _POSIX_Threads_cancel_run(
+ Thread_Control *the_thread
+);
+
+#endif
+/* end of include file */
diff --git a/cpukit/posix/include/rtems/posix/cond.h b/cpukit/posix/include/rtems/posix/cond.h
new file mode 100644
index 0000000000..c283b84b08
--- /dev/null
+++ b/cpukit/posix/include/rtems/posix/cond.h
@@ -0,0 +1,168 @@
+/* rtems/posix/cond.h
+ *
+ * This include file contains all the private support information for
+ * POSIX condition variables.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_CONDITION_VARIABLES_h
+#define __RTEMS_POSIX_CONDITION_VARIABLES_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/object.h>
+#include <rtems/score/threadq.h>
+
+/*
+ * Constant to indicate condition variable does not currently have
+ * a mutex assigned to it.
+ */
+
+#define POSIX_CONDITION_VARIABLES_NO_MUTEX 0
+
+/*
+ * Data Structure used to manage a POSIX condition variable
+ */
+
+typedef struct {
+ Objects_Control Object;
+ int process_shared;
+ pthread_mutex_t Mutex;
+ Thread_queue_Control Wait_queue;
+} POSIX_Condition_variables_Control;
+
+/*
+ * The following defines the information control block used to manage
+ * this class of objects.
+ */
+
+POSIX_EXTERN Objects_Information _POSIX_Condition_variables_Information;
+
+/*
+ * The default condition variable attributes structure.
+ */
+
+extern const pthread_condattr_t _POSIX_Condition_variables_Default_attributes;
+
+/*
+ * _POSIX_Condition_variables_Manager_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this manager.
+ */
+
+void _POSIX_Condition_variables_Manager_initialization(
+ uint32_t maximum_condition_variables
+);
+
+/*
+ * _POSIX_Condition_variables_Allocate
+ *
+ * DESCRIPTION:
+ *
+ * This function allocates a condition variable control block from
+ * the inactive chain of free condition variable control blocks.
+ */
+
+RTEMS_INLINE_ROUTINE POSIX_Condition_variables_Control *
+ _POSIX_Condition_variables_Allocate( void );
+
+/*
+ * _POSIX_Condition_variables_Free
+ *
+ * DESCRIPTION:
+ *
+ * This routine frees a condition variable control block to the
+ * inactive chain of free condition variable control blocks.
+ */
+
+RTEMS_INLINE_ROUTINE void _POSIX_Condition_variables_Free (
+ POSIX_Condition_variables_Control *the_condition_variable
+);
+
+/*
+ * _POSIX_Condition_variables_Get
+ *
+ * DESCRIPTION:
+ *
+ * This function maps condition variable IDs to condition variable control
+ * blocks. If ID corresponds to a local condition variable, then it returns
+ * the_condition variable control pointer which maps to ID and location
+ * is set to OBJECTS_LOCAL. if the condition variable ID is global and
+ * resides on a remote node, then location is set to OBJECTS_REMOTE,
+ * and the_condition variable is undefined. Otherwise, location is set
+ * to OBJECTS_ERROR and the_condition variable is undefined.
+ */
+
+#if 0
+RTEMS_INLINE_ROUTINE POSIX_Condition_variables_Control *_POSIX_Condition_variables_Get (
+ Objects_Id *id,
+ Objects_Locations *location
+);
+#endif
+
+/*
+ * _POSIX_Condition_variables_Is_null
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_condition variable is NULL
+ * and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _POSIX_Condition_variables_Is_null (
+ POSIX_Condition_variables_Control *the_condition_variable
+);
+
+/*
+ * _POSIX_Condition_variables_Signal_support
+ *
+ * DESCRIPTION:
+ *
+ * A support routine which implements guts of the broadcast and single task
+ * wake up version of the "signal" operation.
+ */
+
+int _POSIX_Condition_variables_Signal_support(
+ pthread_cond_t *cond,
+ boolean is_broadcast
+);
+
+/*
+ * _POSIX_Condition_variables_Wait_support
+ *
+ * DESCRIPTION:
+ *
+ * A support routine which implements guts of the blocking, non-blocking, and
+ * timed wait version of condition variable wait routines.
+ */
+
+int _POSIX_Condition_variables_Wait_support(
+ pthread_cond_t *cond,
+ pthread_mutex_t *mutex,
+ Watchdog_Interval timeout,
+ boolean already_timedout
+);
+
+#include <rtems/posix/cond.inl>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/posix/condmp.h>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/posix/include/rtems/posix/condmp.h b/cpukit/posix/include/rtems/posix/condmp.h
new file mode 100644
index 0000000000..f6a9424f9b
--- /dev/null
+++ b/cpukit/posix/include/rtems/posix/condmp.h
@@ -0,0 +1,161 @@
+/* condmp.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the Multiprocessing Support in the POSIX Condition Variable Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_CONDITION_VARIABLES_MP_h
+#define __RTEMS_POSIX_CONDITION_VARIABLES_MP_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/mppkt.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/watchdog.h>
+
+/*
+ * The following enumerated type defines the list of
+ * remote condition variable operations.
+ */
+
+typedef enum {
+ POSIX_CONDITION_VARIABLES_MP_ANNOUNCE_CREATE = 0,
+ POSIX_CONDITION_VARIABLES_MP_ANNOUNCE_DELETE = 1,
+ POSIX_CONDITION_VARIABLES_MP_EXTRACT_PROXY = 2,
+ POSIX_CONDITION_VARIABLES_MP_OBTAIN_REQUEST = 3,
+ POSIX_CONDITION_VARIABLES_MP_OBTAIN_RESPONSE = 4,
+ POSIX_CONDITION_VARIABLES_MP_RELEASE_REQUEST = 5,
+ POSIX_CONDITION_VARIABLES_MP_RELEASE_RESPONSE = 6,
+} POSIX_Condition_variables_MP_Remote_operations;
+
+/*
+ * The following data structure defines the packet used to perform
+ * remote condition variable operations.
+ */
+
+typedef struct {
+ MP_packet_Prefix Prefix;
+ POSIX_Condition_variables_MP_Remote_operations operation;
+ Objects_Name name;
+ boolean wait; /* XXX options */
+ Objects_Id proxy_id;
+} POSIX_Condition_variables_MP_Packet;
+
+/*
+ * _POSIX_Condition_variables_MP_Send_process_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * process operation can be performed on another node.
+ */
+
+void _POSIX_Condition_variables_MP_Send_process_packet (
+ POSIX_Condition_variables_MP_Remote_operations operation,
+ Objects_Id condition_variables_id,
+ Objects_Name name,
+ Objects_Id proxy_id
+);
+
+/*
+ * _POSIX_Condition_variables_MP_Send_request_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * directive operation can be initiated on another node.
+ */
+
+int _POSIX_Condition_variables_MP_Send_request_packet (
+ POSIX_Condition_variables_MP_Remote_operations operation,
+ Objects_Id condition_variables_id,
+ boolean wait, /* XXX options */
+ Watchdog_Interval timeout
+);
+
+/*
+ * _POSIX_Condition_variables_MP_Send_response_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * directive can be performed on another node.
+ */
+
+void _POSIX_Condition_variables_MP_Send_response_packet (
+ POSIX_Condition_variables_MP_Remote_operations operation,
+ Objects_Id condition_variables_id,
+ Thread_Control *the_thread
+);
+
+/*
+ *
+ * _POSIX_Condition_variables_MP_Process_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the actions specific to this package for
+ * the request from another node.
+ */
+
+void _POSIX_Condition_variables_MP_Process_packet (
+ MP_packet_Prefix *the_packet_prefix
+);
+
+/*
+ * _POSIX_Condition_variables_MP_Send_object_was_deleted
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked indirectly by the thread queue
+ * when a proxy has been removed from the thread queue and
+ * the remote node must be informed of this.
+ */
+
+void _POSIX_Condition_variables_MP_Send_object_was_deleted (
+ Thread_Control *the_proxy
+);
+
+/*
+ * _POSIX_Condition_variables_MP_Send_extract_proxy
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked when a task is deleted and it
+ * has a proxy which must be removed from a thread queue and
+ * the remote node must be informed of this.
+ */
+
+void _POSIX_Condition_variables_MP_Send_extract_proxy (
+ Thread_Control *the_thread
+);
+
+/*
+ * _POSIX_Condition_variables_MP_Get_packet
+ *
+ * DESCRIPTION:
+ *
+ * This function is used to obtain a condition variable mp packet.
+ */
+
+POSIX_Condition_variables_MP_Packet
+ *_POSIX_Condition_variables_MP_Get_packet ( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of file */
diff --git a/cpukit/posix/include/rtems/posix/config.h b/cpukit/posix/include/rtems/posix/config.h
new file mode 100644
index 0000000000..8456ed760a
--- /dev/null
+++ b/cpukit/posix/include/rtems/posix/config.h
@@ -0,0 +1,62 @@
+/* config.h
+ *
+ * This include file contains the table of user defined configuration
+ * parameters specific for the POSIX API.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_CONFIGURATION_h
+#define __RTEMS_POSIX_CONFIGURATION_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * XXX
+ *
+ * The following records define the Configuration Table. The
+ * information contained in this table is required in all
+ * RTEMS systems, whether single or multiprocessor. This
+ * table primarily defines the following:
+ *
+ * + required number of each object type
+ */
+
+/*
+ * For now, we are only allowing the user to specify the entry point
+ * and stack size for POSIX initialization threads.
+ */
+
+typedef struct {
+ void *(*thread_entry)(void *);
+ int stack_size;
+} posix_initialization_threads_table;
+
+typedef struct {
+ int maximum_threads;
+ int maximum_mutexes;
+ int maximum_condition_variables;
+ int maximum_keys;
+ int maximum_timers;
+ int maximum_queued_signals;
+ int maximum_message_queues;
+ int maximum_semaphores;
+ int number_of_initialization_threads;
+ posix_initialization_threads_table *User_initialization_threads_table;
+} posix_api_configuration_table;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/posix/include/rtems/posix/intr.h b/cpukit/posix/include/rtems/posix/intr.h
new file mode 100644
index 0000000000..f6f63a4797
--- /dev/null
+++ b/cpukit/posix/include/rtems/posix/intr.h
@@ -0,0 +1,152 @@
+/* rtems/posix/intr.h
+ *
+ * This include file contains all the private support information for
+ * POSIX Interrupt Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_KEY_h
+#define __RTEMS_POSIX_KEY_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+
+/*
+ * Data Structure used to manage each POSIX Interrupt Vector
+ */
+
+typedef struct {
+ int number_installed;
+ int lock_count;
+ int deferred_count;
+ Chain_Control Handlers;
+} POSIX_Interrupt_Control;
+
+/*
+ * Data Structure used to manage a POSIX Interrupt Handler
+ */
+
+typedef struct {
+ Objects_Control Object;
+ int is_active;
+ intr_t vector;
+ Thread_Control *server;
+ int (*handler)( void *area );
+ volatile void *user_data_area;
+} POSIX_Interrupt_Handler_control;
+
+/*
+ * The following defines the information control block used to manage
+ * this class of objects.
+ */
+
+POSIX_EXTERN Objects_Information _POSIX_Interrupt_Handlers_Information;
+
+/*
+ * The following is an array which is used to manage the set of
+ * interrupt handlers installed on each vector.
+ */
+
+POSIX_EXTERN POSIX_Interrupt_Control
+ _POSIX_Interrupt_Information[ ISR_NUMBER_OF_VECTORS ];
+
+/*
+ * _POSIX_Interrupt_Manager_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this manager.
+ */
+
+void _POSIX_Interrupt_Manager_initialization(
+ uint32_t maximum_interrupt_handlers
+);
+
+/*
+ * _POSIX_Interrupt_Allocate
+ *
+ * DESCRIPTION:
+ *
+ * This function allocates a interrupt handler control block from
+ * the inactive chain of free interrupt handler control blocks.
+ */
+
+RTEMS_INLINE_ROUTINE POSIX_Interrupt_Handler_control *
+ _POSIX_Interrupt_Allocate( void );
+
+/*
+ * _POSIX_Interrupt_Free
+ *
+ * DESCRIPTION:
+ *
+ * This routine frees a interrupt handler control block to the
+ * inactive chain of free interrupt handler control blocks.
+ */
+
+RTEMS_INLINE_ROUTINE void _POSIX_Interrupt_Free (
+ POSIX_Interrupt_Handler_control *the_intr
+);
+
+/*
+ * _POSIX_Interrupt_Get
+ *
+ * DESCRIPTION:
+ *
+ * This function maps interrupt handler IDs to interrupt handler control
+ * blocks. If ID corresponds to a local interrupt handler, then it returns
+ * the_intr control pointer which maps to ID and location
+ * is set to OBJECTS_LOCAL. if the interrupt handler ID is global and
+ * resides on a remote node, then location is set to OBJECTS_REMOTE,
+ * and the_intr is undefined. Otherwise, location is set
+ * to OBJECTS_ERROR and the_intr is undefined.
+ */
+
+RTEMS_INLINE_ROUTINE POSIX_Interrupt_Control *_POSIX_Interrupt_Get (
+ Objects_Id id,
+ Objects_Locations *location
+);
+
+/*
+ * _POSIX_Interrupt_Is_null
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_intr is NULL and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _POSIX_Interrupt_Is_null (
+ POSIX_Interrupt_Handler_control *the_intr
+);
+
+/*
+ * _POSIX_Interrupt_Handler
+ *
+ * DESCRIPTION:
+ *
+ * This function XXX.
+ */
+
+void _POSIX_Interrupt_Handler(
+ ISR_Vector_number vector
+);
+
+#include <rtems/posix/intr.inl>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/posix/include/rtems/posix/key.h b/cpukit/posix/include/rtems/posix/key.h
new file mode 100644
index 0000000000..be9c9579f1
--- /dev/null
+++ b/cpukit/posix/include/rtems/posix/key.h
@@ -0,0 +1,134 @@
+/* rtems/posix/key.h
+ *
+ * This include file contains all the private support information for
+ * POSIX key.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_KEY_h
+#define __RTEMS_POSIX_KEY_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Data Structure used to manage a POSIX key
+ *
+ * NOTE: The Values is a table indexed by the index portion of the
+ * ID of the currently executing thread.
+ */
+
+typedef struct {
+ Objects_Control Object;
+ boolean is_active;
+ void (*destructor)( void * );
+ void **Values[ OBJECTS_APIS_LAST + 1 ];
+} POSIX_Keys_Control;
+
+/*
+ * The following defines the information control block used to manage
+ * this class of objects.
+ */
+
+POSIX_EXTERN Objects_Information _POSIX_Keys_Information;
+
+/*
+ * _POSIX_Keys_Manager_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this manager.
+ */
+
+void _POSIX_Key_Manager_initialization(
+ uint32_t maximum_keys
+);
+
+/*
+ * _POSIX_Keys_Run_destructors
+ *
+ * DESCRIPTION:
+ *
+ * This function executes all the destructors associated with the thread's
+ * keys. This function will execute until all values have been set to NULL.
+ *
+ * NOTE: This is the routine executed when a thread exits to
+ * run through all the keys and do the destructor action.
+ */
+
+void _POSIX_Keys_Run_destructors(
+ Thread_Control *thread
+);
+
+/*
+ * _POSIX_Keys_Allocate
+ *
+ * DESCRIPTION:
+ *
+ * This function allocates a keys control block from
+ * the inactive chain of free keys control blocks.
+ */
+
+RTEMS_INLINE_ROUTINE POSIX_Keys_Control *_POSIX_Keys_Allocate( void );
+
+/*
+ * _POSIX_Keys_Free
+ *
+ * DESCRIPTION:
+ *
+ * This routine frees a keys control block to the
+ * inactive chain of free keys control blocks.
+ */
+
+RTEMS_INLINE_ROUTINE void _POSIX_Keys_Free (
+ POSIX_Keys_Control *the_key
+);
+
+/*
+ * _POSIX_Keys_Get
+ *
+ * DESCRIPTION:
+ *
+ * This function maps key IDs to key control blocks.
+ * If ID corresponds to a local keys, then it returns
+ * the_key control pointer which maps to ID and location
+ * is set to OBJECTS_LOCAL. if the keys ID is global and
+ * resides on a remote node, then location is set to OBJECTS_REMOTE,
+ * and the_key is undefined. Otherwise, location is set
+ * to OBJECTS_ERROR and the_key is undefined.
+ */
+
+RTEMS_INLINE_ROUTINE POSIX_Keys_Control *_POSIX_Keys_Get (
+ Objects_Id id,
+ Objects_Locations *location
+);
+
+/*
+ * _POSIX_Keys_Is_null
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_key is NULL and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _POSIX_Keys_Is_null (
+ POSIX_Keys_Control *the_key
+);
+
+#include <rtems/posix/key.inl>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/posix/include/rtems/posix/mqueue.h b/cpukit/posix/include/rtems/posix/mqueue.h
new file mode 100644
index 0000000000..547091f313
--- /dev/null
+++ b/cpukit/posix/include/rtems/posix/mqueue.h
@@ -0,0 +1,248 @@
+/* rtems/posix/mqueue.h
+ *
+ * This include file contains all the private support information for
+ * POSIX Message Queues.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_MESSAGE_QUEUE_h
+#define __RTEMS_POSIX_MESSAGE_QUEUE_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <signal.h>
+
+#include <rtems/score/coremsg.h>
+#include <rtems/score/object.h>
+
+/*
+ * Data Structure used to manage a POSIX message queue
+ */
+
+typedef struct {
+ Objects_Control Object;
+ int process_shared;
+ boolean named;
+ boolean linked;
+ uint32_t open_count;
+ CORE_message_queue_Control Message_queue;
+ struct sigevent notification;
+} POSIX_Message_queue_Control;
+
+typedef struct {
+ Objects_Control Object;
+ POSIX_Message_queue_Control *Queue;
+ int oflag;
+} POSIX_Message_queue_Control_fd;
+
+/*
+ * The following defines the information control block used to manage
+ * this class of objects. The second item is used to manage the set
+ * of "file descriptors" associated with the message queues.
+ */
+
+POSIX_EXTERN Objects_Information _POSIX_Message_queue_Information;
+POSIX_EXTERN Objects_Information _POSIX_Message_queue_Information_fds;
+
+/*
+ * _POSIX_Message_queue_Manager_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this manager.
+ */
+
+void _POSIX_Message_queue_Manager_initialization(
+ uint32_t maximum_message_queues
+);
+
+/*
+ *
+ * _POSIX_Message_queue_Create_support
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the creation of a message queue utilizing the
+ * core message queue.
+ */
+
+int _POSIX_Message_queue_Create_support(
+ const char *name,
+ int pshared,
+ struct mq_attr *attr,
+ POSIX_Message_queue_Control **message_queue
+);
+
+/*
+ * _POSIX_Message_queue_Delete
+ *
+ * DESCRIPTION:
+ *
+ * This routine supports the mq_unlink and mq_close routines by
+ * doing most of the work involved with removing a message queue.
+ */
+
+void _POSIX_Message_queue_Delete(
+ POSIX_Message_queue_Control *the_mq
+);
+
+/*
+ * _POSIX_Message_queue_Receive_support
+ *
+ * DESCRIPTION:
+ *
+ * This routine supports the various flavors of receiving a message.
+ */
+
+ssize_t _POSIX_Message_queue_Receive_support(
+ mqd_t mqdes,
+ char *msg_ptr,
+ size_t msg_len,
+ unsigned int *msg_prio,
+ Watchdog_Interval timeout
+);
+
+/*
+ * _POSIX_Message_queue_Send_support
+ *
+ * DESCRIPTION:
+ *
+ * This routine posts a message to a specified message queue.
+ */
+
+int _POSIX_Message_queue_Send_support(
+ mqd_t mqdes,
+ const char *msg_ptr,
+ uint32_t msg_len,
+ uint32_t msg_prio,
+ Watchdog_Interval timeout
+);
+
+/*
+ * _POSIX_Message_queue_Allocate
+ *
+ * DESCRIPTION:
+ *
+ * This function allocates a message queue control block from
+ * the inactive chain of free message queue control blocks.
+ */
+
+RTEMS_INLINE_ROUTINE POSIX_Message_queue_Control *_POSIX_Message_queue_Allocate( void );
+
+/*
+ * _POSIX_Message_queue_Free
+ *
+ * DESCRIPTION:
+ *
+ * This routine frees a message queue control block to the
+ * inactive chain of free message queue control blocks.
+ */
+
+RTEMS_INLINE_ROUTINE void _POSIX_Message_queue_Free (
+ POSIX_Message_queue_Control *the_mq
+);
+
+/*
+ * _POSIX_Message_queue_Get
+ *
+ * DESCRIPTION:
+ *
+ * This function maps message queue IDs to message queue control blocks.
+ * If ID corresponds to a local message queue, then it returns
+ * the_mq control pointer which maps to ID and location
+ * is set to OBJECTS_LOCAL. if the message queue ID is global and
+ * resides on a remote node, then location is set to OBJECTS_REMOTE,
+ * and the_message queue is undefined. Otherwise, location is set
+ * to OBJECTS_ERROR and the_mq is undefined.
+ */
+
+RTEMS_INLINE_ROUTINE POSIX_Message_queue_Control *_POSIX_Message_queue_Get (
+ Objects_Id id,
+ Objects_Locations *location
+);
+
+/*
+ * _POSIX_Message_queue_Is_null
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_message_queue is NULL and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _POSIX_Message_queue_Is_null (
+ POSIX_Message_queue_Control *the_mq
+);
+
+/*
+ * _POSIX_Message_queue_Name_to_id
+ *
+ * DESCRIPTION:
+ *
+ * This routine looks up the specified name for a message queue and returns the
+ * id of the message queue associated with it.
+ */
+
+int _POSIX_Message_queue_Name_to_id(
+ const char *name,
+ Objects_Id *id
+);
+
+/*
+ * _POSIX_Message_queue_Priority_to_core
+ *
+ * DESCRIPTION:
+ *
+ * XXX
+ */
+
+RTEMS_INLINE_ROUTINE CORE_message_queue_Submit_types _POSIX_Message_queue_Priority_to_core(
+ unsigned int priority
+);
+
+/*
+ * _POSIX_Message_queue_Priority_from_core
+ *
+ * DESCRIPTION:
+ *
+ * XXX
+ */
+
+RTEMS_INLINE_ROUTINE unsigned int _POSIX_Message_queue_Priority_from_core(
+ CORE_message_queue_Submit_types priority
+);
+
+/*PAGE
+ *
+ * _POSIX_Message_queue_Translate_core_message_queue_return_code
+ *
+ * DESCRIPTION:
+ *
+ * XXX
+ */
+
+int _POSIX_Message_queue_Translate_core_message_queue_return_code(
+ uint32_t the_message_queue_status
+);
+
+
+#include <rtems/posix/mqueue.inl>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/posix/mqueuemp.h>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/posix/include/rtems/posix/mqueuemp.h b/cpukit/posix/include/rtems/posix/mqueuemp.h
new file mode 100644
index 0000000000..01206f056b
--- /dev/null
+++ b/cpukit/posix/include/rtems/posix/mqueuemp.h
@@ -0,0 +1,160 @@
+/* mqueuemp.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the Multiprocessing Support in the POSIX Message Queue Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_MESSAGE_QUEUE_MP_h
+#define __RTEMS_POSIX_MESSAGE_QUEUE_MP_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/mppkt.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/watchdog.h>
+
+/*
+ * The following enumerated type defines the list of
+ * remote message queue operations.
+ */
+
+typedef enum {
+ POSIX_MESSAGE_QUEUE_MP_ANNOUNCE_CREATE = 0,
+ POSIX_MESSAGE_QUEUE_MP_ANNOUNCE_DELETE = 1,
+ POSIX_MESSAGE_QUEUE_MP_EXTRACT_PROXY = 2,
+ POSIX_MESSAGE_QUEUE_MP_OBTAIN_REQUEST = 3,
+ POSIX_MESSAGE_QUEUE_MP_OBTAIN_RESPONSE = 4,
+ POSIX_MESSAGE_QUEUE_MP_RELEASE_REQUEST = 5,
+ POSIX_MESSAGE_QUEUE_MP_RELEASE_RESPONSE = 6,
+} POSIX_Message_queue_MP_Remote_operations;
+
+/*
+ * The following data structure defines the packet used to perform
+ * remote message queue operations.
+ */
+
+typedef struct {
+ MP_packet_Prefix Prefix;
+ POSIX_Message_queue_MP_Remote_operations operation;
+ Objects_Name name;
+ boolean wait; /* XXX options */
+ Objects_Id proxy_id;
+} POSIX_Message_queue_MP_Packet;
+
+/*
+ * _POSIX_Message_queue_MP_Send_process_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * process operation can be performed on another node.
+ */
+
+void _POSIX_Message_queue_MP_Send_process_packet (
+ POSIX_Message_queue_MP_Remote_operations operation,
+ Objects_Id mq_id,
+ Objects_Name name,
+ Objects_Id proxy_id
+);
+
+/*
+ * _POSIX_Message_queue_MP_Send_request_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * directive operation can be initiated on another node.
+ */
+
+int _POSIX_Message_queue_MP_Send_request_packet (
+ POSIX_Message_queue_MP_Remote_operations operation,
+ Objects_Id mq_id,
+ boolean wait, /* XXX options */
+ Watchdog_Interval timeout
+);
+
+/*
+ * _POSIX_Message_queue_MP_Send_response_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * directive can be performed on another node.
+ */
+
+void _POSIX_Message_queue_MP_Send_response_packet (
+ POSIX_Message_queue_MP_Remote_operations operation,
+ Objects_Id mq_id,
+ Thread_Control *the_thread
+);
+
+/*
+ *
+ * _POSIX_Message_queue_MP_Process_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the actions specific to this package for
+ * the request from another node.
+ */
+
+void _POSIX_Message_queue_MP_Process_packet (
+ MP_packet_Prefix *the_packet_prefix
+);
+
+/*
+ * _POSIX_Message_queue_MP_Send_object_was_deleted
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked indirectly by the thread queue
+ * when a proxy has been removed from the thread queue and
+ * the remote node must be informed of this.
+ */
+
+void _POSIX_Message_queue_MP_Send_object_was_deleted (
+ Thread_Control *the_proxy
+);
+
+/*
+ * _POSIX_Message_queue_MP_Send_extract_proxy
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked when a task is deleted and it
+ * has a proxy which must be removed from a thread queue and
+ * the remote node must be informed of this.
+ */
+
+void _POSIX_Message_queue_MP_Send_extract_proxy (
+ Thread_Control *the_thread
+);
+
+/*
+ * _POSIX_Message_queue_MP_Get_packet
+ *
+ * DESCRIPTION:
+ *
+ * This function is used to obtain a message queue mp packet.
+ */
+
+POSIX_Message_queue_MP_Packet *_POSIX_Message_queue_MP_Get_packet ( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of file */
diff --git a/cpukit/posix/include/rtems/posix/mutex.h b/cpukit/posix/include/rtems/posix/mutex.h
new file mode 100644
index 0000000000..99911ac3c0
--- /dev/null
+++ b/cpukit/posix/include/rtems/posix/mutex.h
@@ -0,0 +1,157 @@
+/* rtems/posix/mutex.h
+ *
+ * This include file contains all the private support information for
+ * POSIX mutex's.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_MUTEX_h
+#define __RTEMS_POSIX_MUTEX_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/coremutex.h>
+#include <pthread.h>
+
+/*
+ * Data Structure used to manage a POSIX mutex
+ */
+
+typedef struct {
+ Objects_Control Object;
+ int process_shared;
+ CORE_mutex_Control Mutex;
+} POSIX_Mutex_Control;
+
+/*
+ * The following defines the information control block used to manage
+ * this class of objects.
+ */
+
+POSIX_EXTERN Objects_Information _POSIX_Mutex_Information;
+
+/*
+ * The default mutex attributes structure.
+ */
+
+extern const pthread_mutexattr_t _POSIX_Mutex_Default_attributes;
+
+/*
+ * _POSIX_Mutex_Manager_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this manager.
+ */
+
+void _POSIX_Mutex_Manager_initialization(
+ uint32_t maximum_mutexes
+);
+
+/*
+ * _POSIX_Mutex_Allocate
+ *
+ * DESCRIPTION:
+ *
+ * This function allocates a mutexes control block from
+ * the inactive chain of free mutexes control blocks.
+ */
+
+RTEMS_INLINE_ROUTINE POSIX_Mutex_Control *_POSIX_Mutex_Allocate( void );
+
+/*
+ * _POSIX_Mutex_Free
+ *
+ * DESCRIPTION:
+ *
+ * This routine frees a mutexes control block to the
+ * inactive chain of free mutexes control blocks.
+ */
+
+RTEMS_INLINE_ROUTINE void _POSIX_Mutex_Free (
+ POSIX_Mutex_Control *the_mutex
+);
+
+#if 0
+/*
+ * _POSIX_Mutex_Get
+ *
+ * DESCRIPTION:
+ *
+ * This function maps mutexes IDs to mutexes control blocks.
+ * If ID corresponds to a local mutexes, then it returns
+ * the_mutex control pointer which maps to ID and location
+ * is set to OBJECTS_LOCAL. if the mutexes ID is global and
+ * resides on a remote node, then location is set to OBJECTS_REMOTE,
+ * and the_mutex is undefined. Otherwise, location is set
+ * to OBJECTS_ERROR and the_mutex is undefined.
+ */
+
+RTEMS_INLINE_ROUTINE POSIX_Mutex_Control *_POSIX_Mutex_Get (
+ Objects_Id *id,
+ Objects_Locations *location
+);
+
+/*
+ * _POSIX_Mutex_Is_null
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_mutex is NULL and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _POSIX_Mutex_Is_null (
+ POSIX_Mutex_Control *the_mutex
+);
+#endif
+
+/*
+ * _POSIX_Mutex_Lock_support
+ *
+ * DESCRIPTION:
+ *
+ * A support routine which implements guts of the blocking, non-blocking, and
+ * timed wait version of mutex lock.
+ */
+
+int _POSIX_Mutex_Lock_support(
+ pthread_mutex_t *mutex,
+ boolean blocking,
+ Watchdog_Interval timeout
+);
+
+/*
+ * _POSIX_Mutex_From_core_mutex_status
+ *
+ * DESCRIPTION:
+ *
+ * A support routine which converts core mutex status codes into the
+ * appropriate POSIX status values.
+ */
+
+int _POSIX_Mutex_From_core_mutex_status(
+ CORE_mutex_Status status
+);
+
+
+#include <rtems/posix/mutex.inl>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/posix/mutexmp.h>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/posix/include/rtems/posix/mutexmp.h b/cpukit/posix/include/rtems/posix/mutexmp.h
new file mode 100644
index 0000000000..e3bf586082
--- /dev/null
+++ b/cpukit/posix/include/rtems/posix/mutexmp.h
@@ -0,0 +1,173 @@
+/* mutexmp.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the Multiprocessing Support in the POSIX Mutex Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_MUTEX_MP_h
+#define __RTEMS_POSIX_MUTEX_MP_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/mppkt.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/watchdog.h>
+
+/*
+ * The following enumerated type defines the list of
+ * remote mutex operations.
+ */
+
+typedef enum {
+ POSIX_MUTEX_MP_ANNOUNCE_CREATE = 0,
+ POSIX_MUTEX_MP_ANNOUNCE_DELETE = 1,
+ POSIX_MUTEX_MP_EXTRACT_PROXY = 2,
+ POSIX_MUTEX_MP_OBTAIN_REQUEST = 3,
+ POSIX_MUTEX_MP_OBTAIN_RESPONSE = 4,
+ POSIX_MUTEX_MP_RELEASE_REQUEST = 5,
+ POSIX_MUTEX_MP_RELEASE_RESPONSE = 6,
+} POSIX_Mutex_MP_Remote_operations;
+
+/*
+ * The following data structure defines the packet used to perform
+ * remote mutex operations.
+ */
+
+typedef struct {
+ MP_packet_Prefix Prefix;
+ POSIX_Mutex_MP_Remote_operations operation;
+ Objects_Name name;
+ boolean wait; /* XXX options */
+ Objects_Id proxy_id;
+} POSIX_Mutex_MP_Packet;
+
+/*
+ * _POSIX_Mutex_MP_Send_process_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * process operation can be performed on another node.
+ */
+
+void _POSIX_Mutex_MP_Send_process_packet (
+ POSIX_Mutex_MP_Remote_operations operation,
+ Objects_Id mutex_id,
+ Objects_Name name,
+ Objects_Id proxy_id
+);
+
+/*
+ * _POSIX_Mutex_MP_Send_request_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * directive operation can be initiated on another node.
+ */
+
+int _POSIX_Mutex_MP_Send_request_packet (
+ POSIX_Mutex_MP_Remote_operations operation,
+ Objects_Id mutex_id,
+ boolean wait, /* XXX options */
+ Watchdog_Interval timeout
+);
+
+/*
+ * _POSIX_Mutex_MP_Send_response_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * directive can be performed on another node.
+ */
+
+void _POSIX_Mutex_MP_Send_response_packet (
+ POSIX_Mutex_MP_Remote_operations operation,
+ Objects_Id mutex_id,
+ Thread_Control *the_thread
+);
+
+/*
+ *
+ * _POSIX_Mutex_MP_Process_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the actions specific to this package for
+ * the request from another node.
+ */
+
+void _POSIX_Mutex_MP_Process_packet (
+ MP_packet_Prefix *the_packet_prefix
+);
+
+/*
+ * _POSIX_Mutex_MP_Send_object_was_deleted
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked indirectly by the thread queue
+ * when a proxy has been removed from the thread queue and
+ * the remote node must be informed of this.
+ */
+
+void _POSIX_Mutex_MP_Send_object_was_deleted (
+ Thread_Control *the_proxy
+);
+
+/*
+ * _POSIX_Mutex_MP_Send_extract_proxy
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked when a task is deleted and it
+ * has a proxy which must be removed from a thread queue and
+ * the remote node must be informed of this.
+ */
+
+void _POSIX_Mutex_MP_Send_extract_proxy (
+ Thread_Control *the_thread
+);
+
+/*
+ * _POSIX_Threads_mutex_MP_support
+ *
+ * DESCRIPTION:
+ *
+ * This routine XXX
+ */
+
+void _POSIX_Threads_mutex_MP_support(
+ Thread_Control *the_thread,
+ Objects_Id id
+);
+
+/*
+ * _POSIX_Mutex_MP_Get_packet
+ *
+ * DESCRIPTION:
+ *
+ * This function is used to obtain a mutex mp packet.
+ */
+
+POSIX_Mutex_MP_Packet *_POSIX_Mutex_MP_Get_packet ( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of file */
diff --git a/cpukit/posix/include/rtems/posix/posixapi.h b/cpukit/posix/include/rtems/posix/posixapi.h
new file mode 100644
index 0000000000..81fd227538
--- /dev/null
+++ b/cpukit/posix/include/rtems/posix/posixapi.h
@@ -0,0 +1,33 @@
+/*
+ * POSIX API Support
+ *
+ * NOTE:
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __POSIX_API_h
+#define __POSIX_API_h
+
+#include <rtems/config.h>
+
+/*PAGE
+ *
+ * _POSIX_API_Initialize
+ *
+ * XXX
+ */
+
+void _POSIX_API_Initialize(
+ rtems_configuration_table *configuration_table
+);
+
+#endif
+/* end of include file */
diff --git a/cpukit/posix/include/rtems/posix/priority.h b/cpukit/posix/include/rtems/posix/priority.h
new file mode 100644
index 0000000000..bb4b9cfb19
--- /dev/null
+++ b/cpukit/posix/include/rtems/posix/priority.h
@@ -0,0 +1,44 @@
+/*
+ *
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_PRIORITY_h
+#define __RTEMS_POSIX_PRIORITY_h
+
+#include <rtems/score/priority.h>
+
+/*
+ * 1003.1b-1993,2.2.2.80 definition of priority, p. 19
+ *
+ * "Numericallly higher values represent higher priorities."
+ *
+ * Thus, RTEMS Core has priorities run in the opposite sense of the POSIX API.
+ *
+ * There are only 254 posix priority levels since a task at priority level
+ * 255 would never run because of the RTEMS idle task. This is necessary
+ * because GNAT maps the lowest Ada task priority to the lowest thread
+ * priority. The lowest priority Ada task should get to run, so there is
+ * a fundamental conflict with having 255 priorities.
+ */
+
+#define POSIX_SCHEDULER_MAXIMUM_PRIORITY (254)
+
+#define POSIX_SCHEDULER_MINIMUM_PRIORITY (1)
+
+RTEMS_INLINE_ROUTINE boolean _POSIX_Priority_Is_valid(
+ int priority
+);
+
+RTEMS_INLINE_ROUTINE Priority_Control _POSIX_Priority_To_core(
+ int priority
+);
+
+RTEMS_INLINE_ROUTINE int _POSIX_Priority_From_core(
+ Priority_Control priority
+);
+
+#include <rtems/posix/priority.inl>
+
+#endif
diff --git a/cpukit/posix/include/rtems/posix/psignal.h b/cpukit/posix/include/rtems/posix/psignal.h
new file mode 100644
index 0000000000..905b243e50
--- /dev/null
+++ b/cpukit/posix/include/rtems/posix/psignal.h
@@ -0,0 +1,121 @@
+/*
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_SIGNALS_h
+#define __RTEMS_POSIX_SIGNALS_h
+
+#include <rtems/posix/pthread.h>
+
+/*
+ * Currently 32 signals numbered 1-32 are defined
+ */
+
+#define SIGNAL_EMPTY_MASK 0x00000000
+#define SIGNAL_ALL_MASK 0xffffffff
+
+#define signo_to_mask( _sig ) (1 << ((_sig) - 1))
+
+#define is_valid_signo( _sig ) \
+ ((_sig) >= 1 && (_sig) <= 32 )
+
+#define _States_Is_interruptible_signal( _states ) \
+ ( ((_states) & \
+ (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL)) == \
+ (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL))
+
+#define SIGACTION_TERMINATE \
+ { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Abnormal_termination_handler} }
+#define SIGACTION_IGNORE \
+ { 0, SIGNAL_ALL_MASK, {SIG_IGN} }
+#define SIGACTION_STOP \
+ { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Stop_handler} }
+#define SIGACTION_CONTINUE \
+ { 0, SIGNAL_ALL_MASK, {_POSIX_signals_Continue_handler} }
+
+#define SIG_ARRAY_MAX (SIGRTMAX + 1)
+
+/*
+ * Variables
+ */
+
+extern sigset_t _POSIX_signals_Pending;
+
+extern struct sigaction _POSIX_signals_Default_vectors[ SIG_ARRAY_MAX ];
+
+extern struct sigaction _POSIX_signals_Vectors[ SIG_ARRAY_MAX ];
+
+extern Watchdog_Control _POSIX_signals_Alarm_timer;
+
+extern Thread_queue_Control _POSIX_signals_Wait_queue;
+
+extern Chain_Control _POSIX_signals_Inactive_siginfo;
+
+extern Chain_Control _POSIX_signals_Siginfo[ SIG_ARRAY_MAX ];
+
+/*
+ * POSIX internal siginfo structure
+ */
+
+typedef struct {
+ Chain_Node Node;
+ siginfo_t Info;
+} POSIX_signals_Siginfo_node;
+
+/*
+ * Internal routines
+ */
+
+void _POSIX_signals_Manager_Initialization(
+ int maximum_queued_signals
+);
+
+void _POSIX_signals_Post_switch_extension(
+ Thread_Control *the_thread
+);
+
+boolean _POSIX_signals_Unblock_thread(
+ Thread_Control *the_thread,
+ int signo,
+ siginfo_t *info
+);
+
+boolean _POSIX_signals_Check_signal(
+ POSIX_API_Control *api,
+ int signo,
+ boolean is_global
+);
+
+boolean _POSIX_signals_Clear_signals(
+ POSIX_API_Control *api,
+ int signo,
+ siginfo_t *info,
+ boolean is_global,
+ boolean check_blocked
+);
+
+int killinfo(
+ pid_t pid,
+ int sig,
+ const union sigval *value
+);
+
+void _POSIX_signals_Set_process_signals(
+ sigset_t mask
+);
+
+void _POSIX_signals_Clear_process_signals(
+ sigset_t mask
+);
+
+/*
+ * Default signal handlers
+ */
+
+#define _POSIX_signals_Stop_handler NULL
+#define _POSIX_signals_Continue_handler NULL
+
+void _POSIX_signals_Abnormal_termination_handler( int signo );
+
+#endif
+/* end of file */
diff --git a/cpukit/posix/include/rtems/posix/pthread.h b/cpukit/posix/include/rtems/posix/pthread.h
new file mode 100644
index 0000000000..9a5ff96923
--- /dev/null
+++ b/cpukit/posix/include/rtems/posix/pthread.h
@@ -0,0 +1,149 @@
+/* rtems/posix/pthread.h
+ *
+ * This include file contains all the private support information for
+ * POSIX threads.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_THREADS_h
+#define __RTEMS_POSIX_THREADS_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/posix/config.h>
+#include <rtems/posix/threadsup.h>
+
+#define PTHREAD_MINIMUM_STACK_SIZE (STACK_MINIMUM_SIZE * 2)
+
+/*
+ * The following defines the information control block used to manage
+ * this class of objects.
+ */
+
+POSIX_EXTERN Objects_Information _POSIX_Threads_Information;
+
+/*
+ * These are used to manage the user initialization threads.
+ */
+
+POSIX_EXTERN posix_initialization_threads_table
+ *_POSIX_Threads_User_initialization_threads;
+POSIX_EXTERN uint32_t _POSIX_Threads_Number_of_initialization_threads;
+
+extern const pthread_attr_t _POSIX_Threads_Default_attributes;
+
+/*
+ * _POSIX_Threads_Manager_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this manager.
+ */
+
+void _POSIX_Threads_Manager_initialization(
+ uint32_t maximum_pthreads,
+ uint32_t number_of_initialization_threads,
+ posix_initialization_threads_table *user_threads
+);
+
+/*
+ * _POSIX_Threads_Allocate
+ *
+ * DESCRIPTION:
+ *
+ * This function allocates a pthread control block from
+ * the inactive chain of free pthread control blocks.
+ */
+
+RTEMS_INLINE_ROUTINE Thread_Control *_POSIX_Threads_Allocate( void );
+
+/*
+ * _POSIX_Threads_Free
+ *
+ * DESCRIPTION:
+ *
+ * This routine frees a pthread control block to the
+ * inactive chain of free pthread control blocks.
+ */
+
+RTEMS_INLINE_ROUTINE void _POSIX_Threads_Free(
+ Thread_Control *the_pthread
+);
+
+/*
+ * _POSIX_Threads_Get
+ *
+ * DESCRIPTION:
+ *
+ * This function maps pthread IDs to pthread control blocks.
+ * If ID corresponds to a local pthread, then it returns
+ * the_pthread control pointer which maps to ID and location
+ * is set to OBJECTS_LOCAL. if the pthread ID is global and
+ * resides on a remote node, then location is set to OBJECTS_REMOTE,
+ * and the_pthread is undefined. Otherwise, location is set
+ * to OBJECTS_ERROR and the_pthread is undefined.
+ */
+
+RTEMS_INLINE_ROUTINE Thread_Control *_POSIX_Threads_Get(
+ pthread_t id,
+ Objects_Locations *location
+);
+
+/*
+ * _POSIX_Threads_Is_null
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_pthread is NULL and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _POSIX_Threads_Is_null(
+ Thread_Control *the_pthread
+);
+
+/*
+ * _POSIX_Threads_Sporadic_budget_callout
+ *
+ * DESCRIPTION:
+ *
+ * This routine handles the sporadic scheduling algorithm.
+ */
+
+void _POSIX_Threads_Sporadic_budget_callout(
+ Thread_Control *the_thread
+);
+
+/*
+ * _POSIX_Threads_Sporadic_budget_TSR
+ *
+ * DESCRIPTION:
+ *
+ * This routine supports the sporadic scheduling algorithm.
+ */
+
+void _POSIX_Threads_Sporadic_budget_TSR(
+ Objects_Id id,
+ void *argument
+);
+
+#include <rtems/posix/pthread.inl>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/posix/pthreadmp.h>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/posix/include/rtems/posix/pthreadmp.h b/cpukit/posix/include/rtems/posix/pthreadmp.h
new file mode 100644
index 0000000000..65459c3517
--- /dev/null
+++ b/cpukit/posix/include/rtems/posix/pthreadmp.h
@@ -0,0 +1,160 @@
+/* pthreadmp.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the Multiprocessing Support in the POSIX Threads Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_THREADS_MP_h
+#define __RTEMS_POSIX_THREADS_MP_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/mppkt.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/watchdog.h>
+
+/*
+ * The following enumerated type defines the list of
+ * remote pthread operations.
+ */
+
+typedef enum {
+ POSIX_THREADS_MP_ANNOUNCE_CREATE = 0,
+ POSIX_THREADS_MP_ANNOUNCE_DELETE = 1,
+ POSIX_THREADS_MP_EXTRACT_PROXY = 2,
+ POSIX_THREADS_MP_OBTAIN_REQUEST = 3,
+ POSIX_THREADS_MP_OBTAIN_RESPONSE = 4,
+ POSIX_THREADS_MP_RELEASE_REQUEST = 5,
+ POSIX_THREADS_MP_RELEASE_RESPONSE = 6
+} POSIX_Threads_MP_Remote_operations;
+
+/*
+ * The following data structure defines the packet used to perform
+ * remote pthread operations.
+ */
+
+typedef struct {
+ MP_packet_Prefix Prefix;
+ POSIX_Threads_MP_Remote_operations operation;
+ Objects_Name name;
+ boolean wait;
+ Objects_Id proxy_id;
+} POSIX_Threads_MP_Packet;
+
+/*
+ * _POSIX_Threads_MP_Send_process_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * process operation can be performed on another node.
+ */
+
+void _POSIX_Threads_MP_Send_process_packet (
+ POSIX_Threads_MP_Remote_operations operation,
+ Objects_Id pthread_id,
+ Objects_Name name,
+ Objects_Id proxy_id
+);
+
+/*
+ * _POSIX_Threads_MP_Send_request_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * directive operation can be initiated on another node.
+ */
+
+int _POSIX_Threads_MP_Send_request_packet (
+ POSIX_Threads_MP_Remote_operations operation,
+ Objects_Id pthread_id,
+ boolean wait,
+ Watchdog_Interval timeout
+);
+
+/*
+ * _POSIX_Threads_MP_Send_response_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * directive can be performed on another node.
+ */
+
+void _POSIX_Threads_MP_Send_response_packet (
+ POSIX_Threads_MP_Remote_operations operation,
+ Objects_Id pthread_id,
+ Thread_Control *the_thread
+);
+
+/*
+ *
+ * _POSIX_Threads_MP_Process_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the actions specific to this package for
+ * the request from another node.
+ */
+
+void _POSIX_Threads_MP_Process_packet (
+ MP_packet_Prefix *the_packet_prefix
+);
+
+/*
+ * _POSIX_Threads_MP_Send_object_was_deleted
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked indirectly by the thread queue
+ * when a proxy has been removed from the thread queue and
+ * the remote node must be informed of this.
+ */
+
+void _POSIX_Threads_MP_Send_object_was_deleted (
+ Thread_Control *the_proxy
+);
+
+/*
+ * _POSIX_Threads_MP_Send_extract_proxy
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked when a task is deleted and it
+ * has a proxy which must be removed from a thread queue and
+ * the remote node must be informed of this.
+ */
+
+void _POSIX_Threads_MP_Send_extract_proxy (
+ Thread_Control *the_thread
+);
+
+/*
+ * _POSIX_Threads_MP_Get_packet
+ *
+ * DESCRIPTION:
+ *
+ * This function is used to obtain a pthread mp packet.
+ */
+
+POSIX_Threads_MP_Packet *_POSIX_Threads_MP_Get_packet ( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of file */
diff --git a/cpukit/posix/include/rtems/posix/ptimer.h b/cpukit/posix/include/rtems/posix/ptimer.h
new file mode 100644
index 0000000000..a0836d6ea3
--- /dev/null
+++ b/cpukit/posix/include/rtems/posix/ptimer.h
@@ -0,0 +1,90 @@
+/* rtems/posix/ptimer.h
+ *
+ * This include file contains all the private support information for
+ * POSIX timers.
+ *
+ * COPYRIGHT (c) 1998.
+ * Alfonso Escalera Piña
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * ptimer.h,v 1.0 1998/03/31 16:21:16
+ */
+
+#ifndef __RTEMS_POSIX_TIMERS_h
+#define __RTEMS_POSIX_TIMERS_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/posix/config.h>
+
+/*
+ * _POSIX_Timers_Manager_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this manager.
+ */
+
+void _POSIX_Timer_Manager_initialization ( int max_timers );
+
+/*
+ * 14.2.2 Create a Per-Process Timer, P1003.1b-1993, p. 264
+ *
+ * timer_create
+ */
+
+int timer_create(
+ clockid_t clock_id,
+ struct sigevent *evp,
+ timer_t *timerid
+);
+
+/*
+ * 14.2.3 Delete a Per_process Timer, P1003.1b-1993, p. 266
+ */
+
+int timer_delete(
+ timer_t timerid
+);
+
+/*
+ * 14.2.4 Per-Process Timers, P1003.1b-1993, p. 267
+ *
+ * timer_settime
+ */
+
+int timer_settime(
+ timer_t timerid,
+ int flags,
+ const struct itimerspec *value,
+ struct itimerspec *ovalue
+);
+
+/*
+ * 14.2.4 Per-Process Timers, P1003.1b-1993, p. 267
+ *
+ * timer_gettime
+ */
+
+int timer_gettime(
+ timer_t timerid,
+ struct itimerspec *value
+);
+
+/*
+ * 14.2.4 Per-Process Timers, P1003.1b-1993, p. 267
+ *
+ * timer_getoverrun
+ *
+ */
+
+int timer_getoverrun(
+ timer_t timerid
+);
+
+#endif
diff --git a/cpukit/posix/include/rtems/posix/semaphore.h b/cpukit/posix/include/rtems/posix/semaphore.h
new file mode 100644
index 0000000000..4505efdf9d
--- /dev/null
+++ b/cpukit/posix/include/rtems/posix/semaphore.h
@@ -0,0 +1,180 @@
+/* rtems/posix/semaphore.h
+ *
+ * This include file contains all the private support information for
+ * POSIX Semaphores.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_SEMAPHORE_h
+#define __RTEMS_POSIX_SEMAPHORE_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <semaphore.h>
+#include <rtems/score/coresem.h>
+
+#define SEM_FAILED (sem_t *) -1
+
+/*
+ * Data Structure used to manage a POSIX semaphore
+ */
+
+typedef struct {
+ Objects_Control Object;
+ int process_shared;
+ boolean named;
+ boolean linked;
+ uint32_t open_count;
+ CORE_semaphore_Control Semaphore;
+} POSIX_Semaphore_Control;
+
+/*
+ * The following defines the information control block used to manage
+ * this class of objects.
+ */
+
+POSIX_EXTERN Objects_Information _POSIX_Semaphore_Information;
+
+/*
+ * _POSIX_Semaphore_Manager_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this manager.
+ */
+
+void _POSIX_Semaphore_Manager_initialization(
+ uint32_t maximum_semaphorees
+);
+
+/*
+ * _POSIX_Semaphore_Allocate
+ *
+ * DESCRIPTION:
+ *
+ * This function allocates a semaphore control block from
+ * the inactive chain of free semaphore control blocks.
+ */
+
+RTEMS_INLINE_ROUTINE POSIX_Semaphore_Control *_POSIX_Semaphore_Allocate( void );
+
+/*
+ * _POSIX_Semaphore_Free
+ *
+ * DESCRIPTION:
+ *
+ * This routine frees a semaphore control block to the
+ * inactive chain of free semaphore control blocks.
+ */
+
+RTEMS_INLINE_ROUTINE void _POSIX_Semaphore_Free (
+ POSIX_Semaphore_Control *the_semaphore
+);
+
+/*
+ * _POSIX_Semaphore_Get
+ *
+ * DESCRIPTION:
+ *
+ * This function maps semaphore IDs to semaphore control blocks.
+ * If ID corresponds to a local semaphore, then it returns
+ * the_semaphore control pointer which maps to ID and location
+ * is set to OBJECTS_LOCAL. if the semaphore ID is global and
+ * resides on a remote node, then location is set to OBJECTS_REMOTE,
+ * and the_semaphore is undefined. Otherwise, location is set
+ * to OBJECTS_ERROR and the_semaphore is undefined.
+ */
+
+RTEMS_INLINE_ROUTINE POSIX_Semaphore_Control *_POSIX_Semaphore_Get (
+ sem_t *id,
+ Objects_Locations *location
+);
+
+/*
+ * _POSIX_Semaphore_Is_null
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_semaphore is NULL and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _POSIX_Semaphore_Is_null (
+ POSIX_Semaphore_Control *the_semaphore
+);
+
+/*
+ * _POSIX_Semaphore_Create_support
+ *
+ * DESCRIPTION:
+ *
+ * This routine supports the sem_init and sem_open routines.
+ */
+
+int _POSIX_Semaphore_Create_support(
+ const char *name,
+ int pshared,
+ unsigned int value,
+ POSIX_Semaphore_Control **the_sem
+);
+
+/*
+ * _POSIX_Semaphore_Delete
+ *
+ * DESCRIPTION:
+ *
+ * This routine supports the sem_close and sem_unlink routines.
+ */
+
+void _POSIX_Semaphore_Delete(
+ POSIX_Semaphore_Control *the_semaphore
+);
+
+/*
+ * _POSIX_Semaphore_Wait_support
+ *
+ * DESCRIPTION:
+ *
+ * This routine supports the sem_wait, sem_trywait, and sem_timedwait
+ * services.
+ */
+
+int _POSIX_Semaphore_Wait_support(
+ sem_t *sem,
+ boolean blocking,
+ Watchdog_Interval timeout
+);
+
+/*
+ * _POSIX_Semaphore_Name_to_id
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs name to id translation.
+ */
+
+int _POSIX_Semaphore_Name_to_id(
+ const char *name,
+ sem_t *id
+);
+
+#include <rtems/posix/semaphore.inl>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/posix/semaphoremp.h>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/posix/include/rtems/posix/semaphoremp.h b/cpukit/posix/include/rtems/posix/semaphoremp.h
new file mode 100644
index 0000000000..fc6a2f546b
--- /dev/null
+++ b/cpukit/posix/include/rtems/posix/semaphoremp.h
@@ -0,0 +1,160 @@
+/* semaphoremp.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the Multiprocessing Support in the POSIX Semaphore Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_SEMAPHORE_MP_h
+#define __RTEMS_POSIX_SEMAPHORE_MP_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/mppkt.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/watchdog.h>
+
+/*
+ * The following enumerated type defines the list of
+ * remote semaphore operations.
+ */
+
+typedef enum {
+ POSIX_SEMAPHORE_MP_ANNOUNCE_CREATE = 0,
+ POSIX_SEMAPHORE_MP_ANNOUNCE_DELETE = 1,
+ POSIX_SEMAPHORE_MP_EXTRACT_PROXY = 2,
+ POSIX_SEMAPHORE_MP_OBTAIN_REQUEST = 3,
+ POSIX_SEMAPHORE_MP_OBTAIN_RESPONSE = 4,
+ POSIX_SEMAPHORE_MP_RELEASE_REQUEST = 5,
+ POSIX_SEMAPHORE_MP_RELEASE_RESPONSE = 6,
+} POSIX_Semaphore_MP_Remote_operations;
+
+/*
+ * The following data structure defines the packet used to perform
+ * remote semaphore operations.
+ */
+
+typedef struct {
+ MP_packet_Prefix Prefix;
+ POSIX_Semaphore_MP_Remote_operations operation;
+ Objects_Name name;
+ boolean wait; /* XXX options */
+ Objects_Id proxy_id;
+} POSIX_Semaphore_MP_Packet;
+
+/*
+ * _POSIX_Semaphore_MP_Send_process_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * process operation can be performed on another node.
+ */
+
+void _POSIX_Semaphore_MP_Send_process_packet(
+ POSIX_Semaphore_MP_Remote_operations operation,
+ Objects_Id semaphore_id,
+ Objects_Name name,
+ Objects_Id proxy_id
+);
+
+/*
+ * _POSIX_Semaphore_MP_Send_request_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * directive operation can be initiated on another node.
+ */
+
+int _POSIX_Semaphore_MP_Send_request_packet(
+ POSIX_Semaphore_MP_Remote_operations operation,
+ Objects_Id semaphore_id,
+ boolean wait, /* XXX options */
+ Watchdog_Interval timeout
+);
+
+/*
+ * _POSIX_Semaphore_MP_Send_response_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * directive can be performed on another node.
+ */
+
+void _POSIX_Semaphore_MP_Send_response_packet(
+ POSIX_Semaphore_MP_Remote_operations operation,
+ Objects_Id semaphore_id,
+ Thread_Control *the_thread
+);
+
+/*
+ *
+ * _POSIX_Semaphore_MP_Process_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the actions specific to this package for
+ * the request from another node.
+ */
+
+void _POSIX_Semaphore_MP_Process_packet(
+ MP_packet_Prefix *the_packet_prefix
+);
+
+/*
+ * _POSIX_Semaphore_MP_Send_object_was_deleted
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked indirectly by the thread queue
+ * when a proxy has been removed from the thread queue and
+ * the remote node must be informed of this.
+ */
+
+void _POSIX_Semaphore_MP_Send_object_was_deleted(
+ Thread_Control *the_proxy
+);
+
+/*
+ * _POSIX_Semaphore_MP_Send_extract_proxy
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked when a task is deleted and it
+ * has a proxy which must be removed from a thread queue and
+ * the remote node must be informed of this.
+ */
+
+void _POSIX_Semaphore_MP_Send_extract_proxy(
+ Thread_Control *the_thread
+);
+
+/*
+ * _POSIX_Semaphore_MP_Get_packet
+ *
+ * DESCRIPTION:
+ *
+ * This function is used to obtain a semaphore mp packet.
+ */
+
+POSIX_Semaphore_MP_Packet *_POSIX_Semaphore_MP_Get_packet( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of file */
diff --git a/cpukit/posix/include/rtems/posix/threadsup.h b/cpukit/posix/include/rtems/posix/threadsup.h
new file mode 100644
index 0000000000..3cb25b3982
--- /dev/null
+++ b/cpukit/posix/include/rtems/posix/threadsup.h
@@ -0,0 +1,44 @@
+/* threadsup.h
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_THREAD_SUPPORT_h
+#define __RTEMS_POSIX_THREAD_SUPPORT_h
+
+#include <sys/signal.h>
+#include <rtems/score/coresem.h>
+#include <rtems/score/tqdata.h>
+
+typedef struct {
+ pthread_attr_t Attributes;
+ int detachstate;
+ Thread_queue_Control Join_List;
+ int schedpolicy;
+ struct sched_param schedparam;
+ int ss_high_priority;
+ Watchdog_Control Sporadic_timer;
+
+ sigset_t signals_blocked;
+ sigset_t signals_pending;
+
+#if 0
+ /*
+ * POSIX Interrupts
+ */
+ uint32_t interrupts_installed;
+ CORE_semaphore_Control Interrupt_Semaphore;
+#endif
+
+ /*
+ * POSIX Cancelability
+ */
+ int cancelability_state;
+ int cancelability_type;
+ int cancelation_requested;
+ Chain_Control Cancellation_Handlers;
+
+} POSIX_API_Control;
+
+#endif
+/* end of include file */
diff --git a/cpukit/posix/include/rtems/posix/time.h b/cpukit/posix/include/rtems/posix/time.h
new file mode 100644
index 0000000000..83201ec784
--- /dev/null
+++ b/cpukit/posix/include/rtems/posix/time.h
@@ -0,0 +1,50 @@
+/*
+ *
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_TIME_h
+#define __RTEMS_POSIX_TIME_h
+
+#include <rtems/score/tod.h>
+
+/*
+ * Seconds from January 1, 1970 to January 1, 1988. Used to account for
+ * differences between POSIX API and RTEMS core.
+ */
+
+#define POSIX_TIME_SECONDS_1970_THROUGH_1988 \
+ (((1987 - 1970 + 1) * TOD_SECONDS_PER_NON_LEAP_YEAR) + \
+ (4 * TOD_SECONDS_PER_DAY))
+
+/*PAGE
+ *
+ * _POSIX_Timespec_subtract
+ */
+
+void _POSIX_Timespec_subtract(
+ const struct timespec *the_start,
+ const struct timespec *end,
+ struct timespec *result
+);
+
+/*
+ * _POSIX_Timespec_to_interval
+ */
+
+Watchdog_Interval _POSIX_Timespec_to_interval(
+ const struct timespec *time
+);
+
+/*PAGE
+ *
+ * _POSIX_Interval_to_timespec
+ */
+
+void _POSIX_Interval_to_timespec(
+ Watchdog_Interval ticks,
+ struct timespec *time
+);
+
+#endif
diff --git a/cpukit/posix/include/rtems/posix/timer.h b/cpukit/posix/include/rtems/posix/timer.h
new file mode 100644
index 0000000000..285b6ca216
--- /dev/null
+++ b/cpukit/posix/include/rtems/posix/timer.h
@@ -0,0 +1,72 @@
+/*
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_TIMERS_h
+#define __RTEMS_POSIX_TIMERS_h
+
+/* ************
+ * Constants
+ * ************/
+
+#define STATE_FREE_C 0x01 /* Free position of the table of timers */
+#define STATE_CREATE_NEW_C 0x02 /* Created timer but not running */
+#define STATE_CREATE_RUN_C 0x03 /* Created timer and running */
+#define STATE_CREATE_STOP_C 0x04 /* Created, ran and stopped timer */
+/* Maximum number of nsec allowed */
+#define MAX_NSEC_C (uint32_t )1000000000
+#define MIN_NSEC_C 0 /* Minimum number of nsec allowew */
+#define TIMER_RELATIVE_C 0 /* Indicates that the fire time is
+ * relative to the current one */
+#define SEC_TO_TICKS_C _TOD_Ticks_per_second /* Number of ticks in a second*/
+/* Nanoseconds in a second */
+#define NSEC_PER_SEC_C (uint32_t )1000000000
+
+#define NO_MORE_TIMERS_C 11 /* There is not available timers */
+#define BAD_TIMER_C 11 /* The timer does not exist in the table */
+
+#define SECONDS_PER_YEAR_C (uint32_t )(360 * 24) * (uint32_t )(60 * 60)
+#define SECONDS_PER_MONTH_C (uint32_t )( 30 * 24) * (uint32_t )(60 * 60)
+#define SECONDS_PER_DAY_C (uint32_t )( 24 * 60) * (uint32_t )(60)
+#define SECONDS_PER_HOUR_C (uint32_t )( 60 * 60 )
+#define SECONDS_PER_MINUTE_C (uint32_t )( 60 )
+
+
+/*
+ * Data for a timer
+ */
+
+typedef struct {
+ Objects_Control Object;
+ Watchdog_Control Ticker;
+
+ pthread_t thread_id; /* Thread identifier */
+ char state; /* State of the timer */
+ struct sigevent inf; /* Information associated to the timer */
+ timer_t timer_id; /* Created timer identifier */
+ struct itimerspec timer_data; /* Timing data of the timer */
+ uint32_t ticks; /* Number of ticks of the initialization */
+ uint32_t overrun; /* Number of expirations of the timer */
+ rtems_time_of_day time; /* Time in which the timer was started */
+} POSIX_Timer_Control;
+
+/*
+ * Array of Timers
+ */
+
+extern int timer_max;
+extern POSIX_Timer_Control *timer_struct;
+
+/*
+ * The following defines the information control block used to manage
+ * this class of objects.
+ */
+
+RTEMS_EXTERN Objects_Information _POSIX_Timer_Information;
+
+#ifndef __RTEMS_APPLICATION__
+#include <rtems/posix/timer.inl>
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/posix/include/sched.h b/cpukit/posix/include/sched.h
new file mode 100644
index 0000000000..964430b792
--- /dev/null
+++ b/cpukit/posix/include/sched.h
@@ -0,0 +1,95 @@
+/* sched.h
+ *
+ * $Id$
+ */
+
+
+#ifndef __POSIX_SCHEDULING_h
+#define __POSIX_SCHEDULING_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/features.h>
+
+#if defined(_POSIX_PRIORITY_SCHEDULING)
+
+#include <sys/types.h>
+#include <time.h>
+#include <sys/sched.h>
+#include <pthread.h>
+
+/*
+ * 13.3.1 Set Scheduling Parameters, P1003.1b-1993, p. 252
+ *
+ */
+
+int sched_setparam(
+ pid_t pid,
+ const struct sched_param *param
+);
+
+/*
+ * 13.3.2 Set Scheduling Parameters, P1003.1b-1993, p. 253
+ */
+
+int sched_getparam(
+ pid_t pid,
+ const struct sched_param *param
+);
+
+/*
+ * 13.3.3 Set Scheduling Policy and Scheduling Parameters,
+ * P1003.1b-1993, p. 254
+ */
+
+int sched_setscheduler(
+ pid_t pid,
+ int policy,
+ const struct sched_param *param
+);
+
+/*
+ * 13.3.4 Get Scheduling Policy, P1003.1b-1993, p. 256
+ */
+
+int sched_getscheduler(
+ pid_t pid
+);
+
+/*
+ * 13.3.6 Get Scheduling Parameter Limits, P1003.1b-1993, p. 258
+ */
+
+int sched_get_priority_max(
+ int policy
+);
+
+int sched_get_priority_min(
+ int policy
+);
+
+int sched_rr_get_interval(
+ pid_t pid,
+ struct timespec *interval
+);
+
+#endif /* _POSIX_PRIORITY_SCHEDULING */
+
+#if defined(_POSIX_THREADS) || defined(_POSIX_PRIORITY_SCHEDULING)
+
+/*
+ * 13.3.5 Yield Processor, P1003.1b-1993, p. 257
+ */
+
+int sched_yield( void );
+
+#endif /* _POSIX_THREADS or _POSIX_PRIORITY_SCHEDULING */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/posix/include/semaphore.h b/cpukit/posix/include/semaphore.h
new file mode 100644
index 0000000000..79e85f2d6a
--- /dev/null
+++ b/cpukit/posix/include/semaphore.h
@@ -0,0 +1,116 @@
+/* semaphore.h
+ *
+ * $Id$
+ */
+
+#ifndef __POSIX_SEMAPHORE_h
+#define __POSIX_SEMAPHORE_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/features.h>
+
+#if defined(_POSIX_SEMAPHORES)
+
+#include <sys/time.h>
+
+/*
+ * 11.1 Semaphore Characteristics, P1003.1b-1993, p.219
+ */
+
+typedef int sem_t;
+
+/*
+ * 11.2.1 Initialize an Unnamed Semaphore, P1003.1b-1993, p.219
+ */
+
+int sem_init(
+ sem_t *sem,
+ int pshared,
+ unsigned int value
+);
+
+/*
+ * 11.2.2 Destroy an Unnamed Semaphore, P1003.1b-1993, p.220
+ */
+
+int sem_destroy(
+ sem_t *sem
+);
+
+/*
+ * 11.2.3 Initialize/Open a Named Semaphore, P1003.1b-1993, p.221
+ *
+ * NOTE: Follows open() calling conventions.
+ */
+
+sem_t *sem_open(
+ const char *name,
+ int oflag,
+ ...
+);
+
+/*
+ * 11.2.4 Close a Named Semaphore, P1003.1b-1993, p.224
+ */
+
+int sem_close(
+ sem_t *sem
+);
+
+/*
+ * 11.2.5 Remove a Named Semaphore, P1003.1b-1993, p.225
+ */
+
+int sem_unlink(
+ const char *name
+);
+
+/*
+ * 11.2.6 Lock a Semaphore, P1003.1b-1993, p.226
+ *
+ * NOTE: P1003.4b/D8 adds sem_timedwait(), p. 27
+ */
+
+int sem_wait(
+ sem_t *sem
+);
+
+int sem_trywait(
+ sem_t *sem
+);
+
+#if defined(_POSIX_TIMEOUTS)
+int sem_timedwait(
+ sem_t *sem,
+ const struct timespec *timeout
+);
+#endif
+
+/*
+ * 11.2.7 Unlock a Semaphore, P1003.1b-1993, p.227
+ */
+
+int sem_post(
+ sem_t *sem
+);
+
+/*
+ * 11.2.8 Get the Value of a Semaphore, P1003.1b-1993, p.229
+ */
+
+int sem_getvalue(
+ sem_t *sem,
+ int *sval
+);
+
+#endif /* _POSIX_SEMAPHORES */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/posix/inline/rtems/posix/cond.inl b/cpukit/posix/inline/rtems/posix/cond.inl
new file mode 100644
index 0000000000..09eac152e1
--- /dev/null
+++ b/cpukit/posix/inline/rtems/posix/cond.inl
@@ -0,0 +1,100 @@
+/* rtems/posix/cond.inl
+ *
+ * This include file contains the static inline implementation of the private
+ * inlined routines for POSIX condition variables.
+ *
+ * COPYRIGHT (c) 1989-2002.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_CONDITION_VARIABLES_inl
+#define __RTEMS_POSIX_CONDITION_VARIABLES_inl
+
+#include <pthread.h>
+
+/*PAGE
+ *
+ * _POSIX_Condition_variables_Allocate
+ */
+
+RTEMS_INLINE_ROUTINE POSIX_Condition_variables_Control
+ *_POSIX_Condition_variables_Allocate( void )
+{
+ return (POSIX_Condition_variables_Control *)
+ _Objects_Allocate( &_POSIX_Condition_variables_Information );
+}
+
+/*PAGE
+ *
+ * _POSIX_Condition_variables_Free
+ */
+
+RTEMS_INLINE_ROUTINE void _POSIX_Condition_variables_Free (
+ POSIX_Condition_variables_Control *the_condition_variable
+)
+{
+ _Objects_Free(
+ &_POSIX_Condition_variables_Information,
+ &the_condition_variable->Object
+ );
+}
+
+/*PAGE
+ *
+ * _POSIX_Condition_variables_Get
+ */
+
+RTEMS_INLINE_ROUTINE POSIX_Condition_variables_Control
+*_POSIX_Condition_variables_Get (
+ Objects_Id *id,
+ Objects_Locations *location
+)
+{
+ int status;
+
+ if ( !id ) {
+ *location = OBJECTS_ERROR;
+ return (POSIX_Condition_variables_Control *) 0;
+ }
+
+ if ( *id == PTHREAD_COND_INITIALIZER ) {
+ /*
+ * Do an "auto-create" here.
+ */
+
+ status = pthread_cond_init( id, 0 );
+ if ( status ) {
+ *location = OBJECTS_ERROR;
+ return (POSIX_Condition_variables_Control *) 0;
+ }
+ }
+
+ /*
+ * Now call Objects_Get()
+ */
+
+ return (POSIX_Condition_variables_Control *)
+ _Objects_Get( &_POSIX_Condition_variables_Information, *id, location );
+}
+
+/*PAGE
+ *
+ * _POSIX_Condition_variables_Is_null
+ */
+
+RTEMS_INLINE_ROUTINE boolean _POSIX_Condition_variables_Is_null (
+ POSIX_Condition_variables_Control *the_condition_variable
+)
+{
+ return !the_condition_variable;
+}
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/posix/inline/rtems/posix/intr.inl b/cpukit/posix/inline/rtems/posix/intr.inl
new file mode 100644
index 0000000000..42e332b912
--- /dev/null
+++ b/cpukit/posix/inline/rtems/posix/intr.inl
@@ -0,0 +1,71 @@
+/* rtems/posix/intr.inl
+ *
+ * This include file contains the static inline implementation of the private
+ * inlined routines for POSIX Interrupt Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_INTERRUPT_inl
+#define __RTEMS_POSIX_INTERRUPT_inl
+
+/*PAGE
+ *
+ * _POSIX_Interrupt_Allocate
+ */
+
+RTEMS_INLINE_ROUTINE POSIX_Interrupt_Handler_control *
+ _POSIX_Interrupt_Allocate( void )
+{
+ return (POSIX_Interrupt_Handler_control *)
+ _Objects_Allocate( &_POSIX_Interrupt_Handlers_Information );
+}
+
+/*PAGE
+ *
+ * _POSIX_Interrupt_Free
+ */
+
+RTEMS_INLINE_ROUTINE void _POSIX_Interrupt_Free (
+ POSIX_Interrupt_Handler_control *the_intr
+)
+{
+ _Objects_Free( &_POSIX_Interrupt_Handlers_Information, &the_intr->Object );
+}
+
+/*PAGE
+ *
+ * _POSIX_Interrupt_Get
+ */
+
+RTEMS_INLINE_ROUTINE POSIX_Interrupt_Control *_POSIX_Interrupt_Get (
+ Objects_Id id,
+ Objects_Locations *location
+)
+{
+ return (POSIX_Interrupt_Control *)
+ _Objects_Get( &_POSIX_Interrupt_Handlers_Information, id, location );
+}
+
+/*PAGE
+ *
+ * _POSIX_Interrupt_Is_null
+ */
+
+RTEMS_INLINE_ROUTINE boolean _POSIX_Interrupt_Is_null (
+ POSIX_Interrupt_Handler_control *the_intr
+)
+{
+ return !the_intr;
+}
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/posix/inline/rtems/posix/key.inl b/cpukit/posix/inline/rtems/posix/key.inl
new file mode 100644
index 0000000000..36f8db9a66
--- /dev/null
+++ b/cpukit/posix/inline/rtems/posix/key.inl
@@ -0,0 +1,69 @@
+/* rtems/posix/key.inl
+ *
+ * This include file contains the static inline implementation of the private
+ * inlined routines for POSIX key's.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_KEY_inl
+#define __RTEMS_POSIX_KEY_inl
+
+/*PAGE
+ *
+ * _POSIX_Keys_Allocate
+ */
+
+RTEMS_INLINE_ROUTINE POSIX_Keys_Control *_POSIX_Keys_Allocate( void )
+{
+ return (POSIX_Keys_Control *) _Objects_Allocate( &_POSIX_Keys_Information );
+}
+
+/*PAGE
+ *
+ * _POSIX_Keys_Free
+ */
+
+RTEMS_INLINE_ROUTINE void _POSIX_Keys_Free (
+ POSIX_Keys_Control *the_key
+)
+{
+ _Objects_Free( &_POSIX_Keys_Information, &the_key->Object );
+}
+
+/*PAGE
+ *
+ * _POSIX_Keys_Get
+ */
+
+RTEMS_INLINE_ROUTINE POSIX_Keys_Control *_POSIX_Keys_Get (
+ Objects_Id id,
+ Objects_Locations *location
+)
+{
+ return (POSIX_Keys_Control *)
+ _Objects_Get( &_POSIX_Keys_Information, id, location );
+}
+
+/*PAGE
+ *
+ * _POSIX_Keys_Is_null
+ */
+
+RTEMS_INLINE_ROUTINE boolean _POSIX_Keys_Is_null (
+ POSIX_Keys_Control *the_key
+)
+{
+ return !the_key;
+}
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/posix/inline/rtems/posix/mqueue.inl b/cpukit/posix/inline/rtems/posix/mqueue.inl
new file mode 100644
index 0000000000..58716fab4d
--- /dev/null
+++ b/cpukit/posix/inline/rtems/posix/mqueue.inl
@@ -0,0 +1,150 @@
+/* rtems/posix/mqueue.inl
+ *
+ * This include file contains the static inline implementation of the private
+ * inlined routines for POSIX Message Queue.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_MESSAGE_QUEUE_inl
+#define __RTEMS_POSIX_MESSAGE_QUEUE_inl
+
+/*PAGE
+ *
+ * _POSIX_Message_queue_Allocate
+ */
+
+RTEMS_INLINE_ROUTINE
+ POSIX_Message_queue_Control *_POSIX_Message_queue_Allocate( void )
+{
+ return (POSIX_Message_queue_Control *)
+ _Objects_Allocate( &_POSIX_Message_queue_Information );
+}
+
+/*PAGE
+ *
+ * _POSIX_Message_queue_Allocate_fd
+ */
+
+RTEMS_INLINE_ROUTINE POSIX_Message_queue_Control_fd *
+ _POSIX_Message_queue_Allocate_fd( void )
+{
+ return (POSIX_Message_queue_Control_fd *)
+ _Objects_Allocate( &_POSIX_Message_queue_Information_fds );
+}
+
+/*PAGE
+ *
+ * _POSIX_Message_queue_Free
+ */
+
+RTEMS_INLINE_ROUTINE void _POSIX_Message_queue_Free (
+ POSIX_Message_queue_Control *the_mq
+)
+{
+ _Objects_Free( &_POSIX_Message_queue_Information, &the_mq->Object );
+}
+
+/*PAGE
+ *
+ * _POSIX_Message_queue_Free_fd
+ */
+
+RTEMS_INLINE_ROUTINE void _POSIX_Message_queue_Free_fd (
+ POSIX_Message_queue_Control_fd *the_mq_fd
+)
+{
+ _Objects_Free( &_POSIX_Message_queue_Information_fds, &the_mq_fd->Object );
+}
+
+/*PAGE
+ *
+ * _POSIX_Message_queue_Namespace_remove
+ */
+
+RTEMS_INLINE_ROUTINE void _POSIX_Message_queue_Namespace_remove (
+ POSIX_Message_queue_Control *the_mq
+)
+{
+ _Objects_Namespace_remove(
+ &_POSIX_Message_queue_Information, &the_mq->Object );
+}
+
+/*PAGE
+ *
+ * _POSIX_Message_queue_Get
+ */
+
+RTEMS_INLINE_ROUTINE POSIX_Message_queue_Control *_POSIX_Message_queue_Get (
+ Objects_Id id,
+ Objects_Locations *location
+)
+{
+ return (POSIX_Message_queue_Control *)
+ _Objects_Get( &_POSIX_Message_queue_Information, id, location );
+}
+
+/*PAGE
+ *
+ * _POSIX_Message_queue_Get_fd
+ */
+
+RTEMS_INLINE_ROUTINE POSIX_Message_queue_Control_fd *_POSIX_Message_queue_Get_fd (
+ Objects_Id id,
+ Objects_Locations *location
+)
+{
+ return (POSIX_Message_queue_Control_fd *)
+ _Objects_Get( &_POSIX_Message_queue_Information_fds, id, location );
+}
+
+/*PAGE
+ *
+ * _POSIX_Message_queue_Is_null
+ */
+
+RTEMS_INLINE_ROUTINE boolean _POSIX_Message_queue_Is_null (
+ POSIX_Message_queue_Control *the_mq
+)
+{
+ return !the_mq;
+}
+
+/*PAGE
+ *
+ * _POSIX_Message_queue_Priority_to_core
+ */
+
+RTEMS_INLINE_ROUTINE CORE_message_queue_Submit_types _POSIX_Message_queue_Priority_to_core(
+ unsigned int priority
+)
+{
+ return priority * -1;
+}
+
+/*
+ * _POSIX_Message_queue_Priority_from_core
+ *
+ * DESCRIPTION:
+ *
+ * XXX
+ */
+
+RTEMS_INLINE_ROUTINE unsigned int _POSIX_Message_queue_Priority_from_core(
+ CORE_message_queue_Submit_types priority
+)
+{
+ /* absolute value without a library dependency */
+ return ((priority >= 0) ? priority : -priority);
+}
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/posix/inline/rtems/posix/mutex.inl b/cpukit/posix/inline/rtems/posix/mutex.inl
new file mode 100644
index 0000000000..a1768ebbf1
--- /dev/null
+++ b/cpukit/posix/inline/rtems/posix/mutex.inl
@@ -0,0 +1,110 @@
+/* rtems/posix/mutex.inl
+ *
+ * This include file contains the static inline implementation of the private
+ * inlined routines for POSIX mutex's.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_MUTEX_inl
+#define __RTEMS_POSIX_MUTEX_inl
+
+/*PAGE
+ *
+ * _POSIX_Mutex_Allocate
+ */
+
+RTEMS_INLINE_ROUTINE POSIX_Mutex_Control *_POSIX_Mutex_Allocate( void )
+{
+ return (POSIX_Mutex_Control *) _Objects_Allocate( &_POSIX_Mutex_Information );
+}
+
+/*PAGE
+ *
+ * _POSIX_Mutex_Free
+ */
+
+RTEMS_INLINE_ROUTINE void _POSIX_Mutex_Free (
+ POSIX_Mutex_Control *the_mutex
+)
+{
+ _Objects_Free( &_POSIX_Mutex_Information, &the_mutex->Object );
+}
+
+/*PAGE
+ *
+ * _POSIX_Mutex_Get_support
+ *
+ * NOTE: The support macro makes it possible for both to use exactly
+ * the same code to check for NULL id pointer and
+ * PTHREAD_MUTEX_INITIALIZER without adding overhead.
+ */
+
+#define ___POSIX_Mutex_Get_support( _id, _location ) \
+ do { \
+ int _status; \
+ \
+ if ( !_id ) { \
+ *_location = OBJECTS_ERROR; \
+ return (POSIX_Mutex_Control *) 0; \
+ } \
+ \
+ if ( *_id == PTHREAD_MUTEX_INITIALIZER ) { \
+ /* \
+ * Do an "auto-create" here. \
+ */ \
+ \
+ _status = pthread_mutex_init( _id, 0 ); \
+ if ( _status ) { \
+ *_location = OBJECTS_ERROR; \
+ return (POSIX_Mutex_Control *) 0; \
+ } \
+ } \
+ } while (0)
+
+RTEMS_INLINE_ROUTINE POSIX_Mutex_Control *_POSIX_Mutex_Get (
+ Objects_Id *id,
+ Objects_Locations *location
+)
+{
+ ___POSIX_Mutex_Get_support( id, location );
+
+ return (POSIX_Mutex_Control *)
+ _Objects_Get( &_POSIX_Mutex_Information, *id, location );
+}
+
+RTEMS_INLINE_ROUTINE POSIX_Mutex_Control *_POSIX_Mutex_Get_interrupt_disable (
+ Objects_Id *id,
+ Objects_Locations *location,
+ ISR_Level *level
+)
+{
+ ___POSIX_Mutex_Get_support( id, location );
+
+ return (POSIX_Mutex_Control *)
+ _Objects_Get_isr_disable( &_POSIX_Mutex_Information, *id, location, level );
+}
+
+
+/*PAGE
+ *
+ * _POSIX_Mutex_Is_null
+ */
+
+RTEMS_INLINE_ROUTINE boolean _POSIX_Mutex_Is_null (
+ POSIX_Mutex_Control *the_mutex
+)
+{
+ return !the_mutex;
+}
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/posix/inline/rtems/posix/priority.inl b/cpukit/posix/inline/rtems/posix/priority.inl
new file mode 100644
index 0000000000..dc8187d4ef
--- /dev/null
+++ b/cpukit/posix/inline/rtems/posix/priority.inl
@@ -0,0 +1,37 @@
+/*
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_PRIORITY_inl
+#define __RTEMS_POSIX_PRIORITY_inl
+
+/*
+ * 1003.1b-1993,2.2.2.80 definition of priority, p. 19
+ *
+ * "Numericallly higher values represent higher priorities."
+ *
+ * Thus, RTEMS Core has priorities run in the opposite sense of the POSIX API.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _POSIX_Priority_Is_valid(
+ int priority
+)
+{
+ return (boolean) (priority >= 1 && priority <= 254);
+}
+
+RTEMS_INLINE_ROUTINE Priority_Control _POSIX_Priority_To_core(
+ int priority
+)
+{
+ return (Priority_Control) (255 - priority);
+}
+
+RTEMS_INLINE_ROUTINE int _POSIX_Priority_From_core(
+ Priority_Control priority
+)
+{
+ return 255 - priority;
+}
+
+#endif
diff --git a/cpukit/posix/inline/rtems/posix/pthread.inl b/cpukit/posix/inline/rtems/posix/pthread.inl
new file mode 100644
index 0000000000..18303ff91b
--- /dev/null
+++ b/cpukit/posix/inline/rtems/posix/pthread.inl
@@ -0,0 +1,69 @@
+/* rtems/posix/pthread.inl
+ *
+ * This include file contains the static inline implementation of the private
+ * inlined routines for POSIX threads.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_THREADS_inl
+#define __RTEMS_POSIX_THREADS_inl
+
+/*PAGE
+ *
+ * _POSIX_Threads_Allocate
+ */
+
+RTEMS_INLINE_ROUTINE Thread_Control *_POSIX_Threads_Allocate( void )
+{
+ return (Thread_Control *) _Objects_Allocate( &_POSIX_Threads_Information );
+}
+
+/*PAGE
+ *
+ * _POSIX_Threads_Free
+ */
+
+RTEMS_INLINE_ROUTINE void _POSIX_Threads_Free (
+ Thread_Control *the_pthread
+)
+{
+ _Objects_Free( &_POSIX_Threads_Information, &the_pthread->Object );
+}
+
+/*PAGE
+ *
+ * _POSIX_Threads_Get
+ */
+
+RTEMS_INLINE_ROUTINE Thread_Control *_POSIX_Threads_Get (
+ pthread_t id,
+ Objects_Locations *location
+)
+{
+ return (Thread_Control *)
+ _Objects_Get( &_POSIX_Threads_Information, (Objects_Id)id, location );
+}
+
+/*PAGE
+ *
+ * _POSIX_Threads_Is_null
+ */
+
+RTEMS_INLINE_ROUTINE boolean _POSIX_Threads_Is_null (
+ Thread_Control *the_pthread
+)
+{
+ return !the_pthread;
+}
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/posix/inline/rtems/posix/semaphore.inl b/cpukit/posix/inline/rtems/posix/semaphore.inl
new file mode 100644
index 0000000000..69229e9119
--- /dev/null
+++ b/cpukit/posix/inline/rtems/posix/semaphore.inl
@@ -0,0 +1,85 @@
+/* rtems/posix/semaphore.inl
+ *
+ * This include file contains the static inline implementation of the private
+ * inlined routines for POSIX Semaphores.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_SEMAPHORE_inl
+#define __RTEMS_POSIX_SEMAPHORE_inl
+
+/*PAGE
+ *
+ * _POSIX_Semaphore_Allocate
+ */
+
+RTEMS_INLINE_ROUTINE POSIX_Semaphore_Control *_POSIX_Semaphore_Allocate( void )
+{
+ return (POSIX_Semaphore_Control *)
+ _Objects_Allocate( &_POSIX_Semaphore_Information );
+}
+
+/*PAGE
+ *
+ * _POSIX_Semaphore_Free
+ */
+
+RTEMS_INLINE_ROUTINE void _POSIX_Semaphore_Free (
+ POSIX_Semaphore_Control *the_semaphore
+)
+{
+ _Objects_Free( &_POSIX_Semaphore_Information, &the_semaphore->Object );
+}
+
+/*PAGE
+ *
+ * _POSIX_Semaphore_Namespace_remove
+ */
+
+RTEMS_INLINE_ROUTINE void _POSIX_Semaphore_Namespace_remove (
+ POSIX_Semaphore_Control *the_semaphore
+)
+{
+ _Objects_Namespace_remove(
+ &_POSIX_Semaphore_Information, &the_semaphore->Object );
+}
+
+
+
+/*PAGE
+ *
+ * _POSIX_Semaphore_Get
+ */
+
+RTEMS_INLINE_ROUTINE POSIX_Semaphore_Control *_POSIX_Semaphore_Get (
+ sem_t *id,
+ Objects_Locations *location
+)
+{
+ return (POSIX_Semaphore_Control *)
+ _Objects_Get( &_POSIX_Semaphore_Information, *id, location );
+}
+
+/*PAGE
+ *
+ * _POSIX_Semaphore_Is_null
+ */
+
+RTEMS_INLINE_ROUTINE boolean _POSIX_Semaphore_Is_null (
+ POSIX_Semaphore_Control *the_semaphore
+)
+{
+ return !the_semaphore;
+}
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/posix/inline/rtems/posix/timer.inl b/cpukit/posix/inline/rtems/posix/timer.inl
new file mode 100644
index 0000000000..f70953f18b
--- /dev/null
+++ b/cpukit/posix/inline/rtems/posix/timer.inl
@@ -0,0 +1,90 @@
+/* timer.inl
+ *
+ * This file contains the static inline implementation of the inlined routines
+ * from the POSIX Timer Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __POSIX_TIMER_inl
+#define __POSIX_TIMER_inl
+
+/*PAGE
+ *
+ * _POSIX_Timer_Allocate
+ *
+ * DESCRIPTION:
+ *
+ * This function allocates a timer control block from
+ * the inactive chain of free timer control blocks.
+ */
+
+RTEMS_INLINE_ROUTINE POSIX_Timer_Control *_POSIX_Timer_Allocate( void )
+{
+ return (POSIX_Timer_Control *) _Objects_Allocate( &_POSIX_Timer_Information );
+}
+
+/*PAGE
+ *
+ * _POSIX_Timer_Free
+ *
+ * DESCRIPTION:
+ *
+ * This routine frees a timer control block to the
+ * inactive chain of free timer control blocks.
+ */
+
+RTEMS_INLINE_ROUTINE void _POSIX_Timer_Free (
+ POSIX_Timer_Control *the_timer
+)
+{
+ _Objects_Free( &_POSIX_Timer_Information, &the_timer->Object );
+}
+
+/*PAGE
+ *
+ * _POSIX_Timer_Get
+ *
+ * DESCRIPTION:
+ *
+ * This function maps timer IDs to timer control blocks.
+ * If ID corresponds to a local timer, then it returns
+ * the timer control pointer which maps to ID and location
+ * is set to OBJECTS_LOCAL. Otherwise, location is set
+ * to OBJECTS_ERROR and the returned value is undefined.
+ */
+
+RTEMS_INLINE_ROUTINE POSIX_Timer_Control *_POSIX_Timer_Get (
+ Objects_Id id,
+ Objects_Locations *location
+)
+{
+ return (POSIX_Timer_Control *)
+ _Objects_Get( &_POSIX_Timer_Information, id, location );
+}
+
+/*PAGE
+ *
+ * _POSIX_Timer_Is_null
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_timer is NULL and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _POSIX_Timer_Is_null (
+ Timer_Control *the_timer
+)
+{
+ return (the_timer == NULL);
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/posix/macros/rtems/posix/cond.inl b/cpukit/posix/macros/rtems/posix/cond.inl
new file mode 100644
index 0000000000..e09acd0437
--- /dev/null
+++ b/cpukit/posix/macros/rtems/posix/cond.inl
@@ -0,0 +1,95 @@
+/* rtems/posix/cond.inl
+ *
+ * This include file contains the macro implementation of the private
+ * inlined routines for POSIX condition variables.
+ *
+ * COPYRIGHT (c) 1989-2002.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_CONDITION_VARIABLES_inl
+#define __RTEMS_POSIX_CONDITION_VARIABLES_inl
+
+#include <pthread.h>
+
+/*PAGE
+ *
+ * _POSIX_Condition_variables_Allocate
+ */
+
+#define _POSIX_Condition_variables_Allocate() \
+ (POSIX_Condition_variables_Control *) \
+ _Objects_Allocate( &_POSIX_Condition_variables_Information )
+
+/*PAGE
+ *
+ * _POSIX_Condition_variables_Free
+ *
+ * NOTE: The support macro makes it possible for both to use exactly
+ * the same code to check for NULL id pointer and
+ * PTHREAD_COND_INITIALIZER without adding overhead.
+ */
+
+#define _POSIX_Condition_variables_Free( _the_condition_variable ) \
+ _Objects_Free( &_POSIX_Condition_variables_Information, \
+ &(_the_condition_variable)->Object)
+
+/*PAGE
+ *
+ * _POSIX_Condition_variables_Get
+ *
+ * NOTE: The support macro makes it possible for both to use exactly
+ * the same code to check for NULL id pointer and
+ * PTHREAD_COND_INITIALIZER without adding overhead.
+ */
+
+#define ___POSIX_Condition_variables_Get_support( _id, _location ) \
+ do { \
+ int _status; \
+ \
+ if ( !_id ) { \
+ *_location = OBJECTS_ERROR; \
+ return (POSIX_Condition_variables_Control *) 0; \
+ } \
+ \
+ if ( *_id == PTHREAD_COND_INITIALIZER ) { \
+ /* \
+ * Do an "auto-create" here. \
+ */ \
+ \
+ _status = pthread_cond_init( _id, 0 ); \
+ if ( _status ) { \
+ *_location = OBJECTS_ERROR; \
+ return (POSIX_Condition_variables_Control *) 0; \
+ } \
+ } \
+ } while (0)
+
+
+static POSIX_Condition_variables_Control *_POSIX_Condition_variables_Get (
+ Objects_Id *id,
+ Objects_Locations *location
+)
+{
+ ___POSIX_Condition_variables_Get_support( id, location );
+
+ return (POSIX_Condition_variables_Control *)
+ _Objects_Get( &_POSIX_Condition_variables_Information, *id, location );
+}
+
+/*PAGE
+ *
+ * _POSIX_Condition_variables_Is_null
+ */
+
+#define _POSIX_Condition_variables_Is_null( _the_condition_variable ) \
+ (!(_the_condition_variable))
+
+#endif
+/* end of include file */
diff --git a/cpukit/posix/macros/rtems/posix/intr.inl b/cpukit/posix/macros/rtems/posix/intr.inl
new file mode 100644
index 0000000000..95dfa04fa8
--- /dev/null
+++ b/cpukit/posix/macros/rtems/posix/intr.inl
@@ -0,0 +1,55 @@
+/* rtems/posix/intr.inl
+ *
+ * This include file contains the macro implementation of the private
+ * inlined routines for POSIX Interrupt Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_INTERRUPT_inl
+#define __RTEMS_POSIX_INTERRUPT_inl
+
+/*PAGE
+ *
+ * _POSIX_Interrupt_Allocate
+ */
+
+#define _POSIX_Interrupt_Allocate() \
+ (POSIX_Interrupt_Handler_control *) \
+ _Objects_Allocate( &_POSIX_Interrupt_Handlers_Information )
+
+/*PAGE
+ *
+ * _POSIX_Interrupt_Free
+ */
+
+#define _POSIX_Interrupt_Free( _the_intr ) \
+ _Objects_Free( &_POSIX_Interrupt_Handlers_Information, &(_the_intr)->Object )
+
+/*PAGE
+ *
+ * _POSIX_Interrupt_Get
+ */
+
+#define _POSIX_Interrupt_Get( _id, _location ) \
+ (POSIX_Interrupt_Control *) \
+ _Objects_Get( &_POSIX_Interrupt_Handlers_Information, (_id), (_location) )
+
+/*PAGE
+ *
+ * _POSIX_Interrupt_Is_null
+ */
+
+#define _POSIX_Interrupt_Is_null( _the_intr ) \
+ (!(_the_intr))
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/posix/macros/rtems/posix/key.inl b/cpukit/posix/macros/rtems/posix/key.inl
new file mode 100644
index 0000000000..13fda1dfc9
--- /dev/null
+++ b/cpukit/posix/macros/rtems/posix/key.inl
@@ -0,0 +1,54 @@
+/* rtems/posix/key.inl
+ *
+ * This include file contains the macro implementation of the private
+ * inlined routines for POSIX key's.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_KEY_inl
+#define __RTEMS_POSIX_KEY_inl
+
+/*PAGE
+ *
+ * _POSIX_Keys_Allocate
+ */
+
+#define _POSIX_Keys_Allocate() \
+ (POSIX_Keys_Control *) _Objects_Allocate( &_POSIX_Keys_Information )
+
+/*PAGE
+ *
+ * _POSIX_Keys_Free
+ */
+
+#define _POSIX_Keys_Free( _the_key ) \
+ _Objects_Free( &_POSIX_Keys_Information, &(_the_key)->Object );
+
+/*PAGE
+ *
+ * _POSIX_Keys_Get
+ */
+
+#define _POSIX_Keys_Get( _id, _location ) \
+ (POSIX_Keys_Control *) \
+ _Objects_Get( &_POSIX_Keys_Information, (_id), (_location) )
+
+/*PAGE
+ *
+ * _POSIX_Keys_Is_null
+ */
+
+#define _POSIX_Keys_Is_null( _the_key ) \
+ (!(_the_key))
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/posix/macros/rtems/posix/mqueue.inl b/cpukit/posix/macros/rtems/posix/mqueue.inl
new file mode 100644
index 0000000000..a5db662b0d
--- /dev/null
+++ b/cpukit/posix/macros/rtems/posix/mqueue.inl
@@ -0,0 +1,101 @@
+/* rtems/posix/mqueue.inl
+ *
+ * This include file contains the macro implementation of the private
+ * inlined routines for POSIX Message Queue.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_MESSAGE_QUEUE_inl
+#define __RTEMS_POSIX_MESSAGE_QUEUE_inl
+
+/*
+ * _POSIX_Message_queue_Allocate
+ */
+
+#define _POSIX_Message_queue_Allocate() \
+ (POSIX_Message_queue_Control *) \
+ _Objects_Allocate( &_POSIX_Message_queue_Information )
+
+/*
+ * _POSIX_Message_queue_Allocate_fd
+ */
+
+#define _POSIX_Message_queue_Allocate_fd() \
+ (POSIX_Message_queue_Control_fd *) \
+ _Objects_Allocate( &_POSIX_Message_queue_Information_fds )
+
+/*
+ * _POSIX_Message_queue_Free
+ */
+
+#define _POSIX_Message_queue_Free( _the_mq ) \
+ _Objects_Free( &_POSIX_Message_queue_Information, &(_the_mq)->Object )
+
+/*
+ * _POSIX_Message_queue_Free_fd
+ */
+
+#define _POSIX_Message_queue_Free_fd( _the_mq_fd ) \
+ _Objects_Free( &_POSIX_Message_queue_Information_fds, &(_the_mq_fd)->Object )
+
+/*
+ * _POSIX_Message_queue_Namespace_remove
+ */
+
+#define _POSIX_Message_queue_Namespace_remove( _the_mq ) \
+ _Objects_Namespace_remove( \
+ &_POSIX_Message_queue_Information, &(_the_mq)->Object )
+
+/*
+ * _POSIX_Message_queue_Get
+ */
+
+#define _POSIX_Message_queue_Get( _id, _location ) \
+ (POSIX_Message_queue_Control *) \
+ _Objects_Get( &_POSIX_Message_queue_Information, (_id), (_location) )
+
+/*
+ * _POSIX_Message_queue_Get_fd
+ */
+
+#define _POSIX_Message_queue_Get_fd( _id, _location ) \
+ (POSIX_Message_queue_Control_fd *) \
+ _Objects_Get( &_POSIX_Message_queue_Information_fds, (_id), (_location) )
+
+/*
+ *
+ * _POSIX_Message_queue_Is_null
+ */
+
+#define _POSIX_Message_queue_Is_null( _the_mq ) \
+ (!(_the_mq))
+
+/*
+ *
+ * _POSIX_Message_queue_Priority_to_core
+ */
+
+#define _POSIX_Message_queue_Priority_to_core( _priority ) \
+ ((_priority) * -1)
+
+/*
+ * _POSIX_Message_queue_Priority_from_core
+ */
+
+/* absolute value without a library dependency */
+#define _POSIX_Message_queue_Priority_from_core( _priority ) \
+ ((((CORE_message_queue_Submit_types)(_priority)) >= 0) ? \
+ (_priority) : \
+ -((CORE_message_queue_Submit_types)(_priority)))
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/posix/macros/rtems/posix/mutex.inl b/cpukit/posix/macros/rtems/posix/mutex.inl
new file mode 100644
index 0000000000..a893397695
--- /dev/null
+++ b/cpukit/posix/macros/rtems/posix/mutex.inl
@@ -0,0 +1,100 @@
+/* rtems/posix/mutex.inl
+ *
+ * This include file contains the macro implementation of the private
+ * inlined routines for POSIX mutex's.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_MUTEX_inl
+#define __RTEMS_POSIX_MUTEX_inl
+
+/*PAGE
+ *
+ * _POSIX_Mutex_Allocate
+ */
+
+#define _POSIX_Mutex_Allocate() \
+ (POSIX_Mutex_Control *) _Objects_Allocate( &_POSIX_Mutex_Information )
+
+/*PAGE
+ *
+ * _POSIX_Mutex_Free
+ */
+
+#define _POSIX_Mutex_Free( _the_mutex ) \
+ _Objects_Free( &_POSIX_Mutex_Information, &(_the_mutex)->Object )
+
+/*PAGE
+ *
+ * _POSIX_Mutex_Get
+ *
+ * NOTE: The support macro makes it possible for both to use exactly
+ * the same code to check for NULL id pointer and
+ * PTHREAD_MUTEX_INITIALIZER without adding overhead.
+ */
+
+#define ___POSIX_Mutex_Get_support( _id, _location ) \
+ do { \
+ int _status; \
+ \
+ if ( !_id ) { \
+ *_location = OBJECTS_ERROR; \
+ return (POSIX_Mutex_Control *) 0; \
+ } \
+ \
+ if ( *_id == PTHREAD_MUTEX_INITIALIZER ) { \
+ /* \
+ * Do an "auto-create" here. \
+ */ \
+ \
+ _status = pthread_mutex_init( _id, 0 ); \
+ if ( _status ) { \
+ *_location = OBJECTS_ERROR; \
+ return (POSIX_Mutex_Control *) 0; \
+ } \
+ } \
+ } while (0)
+
+static POSIX_Mutex_Control * _POSIX_Mutex_Get(
+ Objects_Id *id,
+ Objects_Locations *location
+)
+{
+ ___POSIX_Mutex_Get_support( id, location );
+
+ return (POSIX_Mutex_Control *)
+ _Objects_Get( &_POSIX_Mutex_Information, *id, location );
+}
+
+static POSIX_Mutex_Control *_POSIX_Mutex_Get_interrupt_disable(
+ Objects_Id *id,
+ Objects_Locations *location,
+ ISR_Level *level
+)
+{
+ ___POSIX_Mutex_Get_support( id, location );
+
+ return (POSIX_Mutex_Control *)
+ _Objects_Get_isr_disable( &_POSIX_Mutex_Information, *id, location, level );
+}
+
+
+/*PAGE
+ *
+ * _POSIX_Mutex_Is_null
+ */
+
+#define _POSIX_Mutex_Is_null( _the_mutex ) \
+ (!(_the_mutex))
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/posix/macros/rtems/posix/priority.inl b/cpukit/posix/macros/rtems/posix/priority.inl
new file mode 100644
index 0000000000..ea1ce82669
--- /dev/null
+++ b/cpukit/posix/macros/rtems/posix/priority.inl
@@ -0,0 +1,25 @@
+/*
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_PRIORITY_inl
+#define __RTEMS_POSIX_PRIORITY_inl
+
+/*
+ * 1003.1b-1993,2.2.2.80 definition of priority, p. 19
+ *
+ * "Numericallly higher values represent higher priorities."
+ *
+ * Thus, RTEMS Core has priorities run in the opposite sense of the POSIX API.
+ */
+
+#define _POSIX_Priority_Is_valid( _priority ) \
+ ((boolean) ((_priority) >= 1 && (_priority) <= 254))
+
+#define _POSIX_Priority_To_core( _priority ) \
+ ((Priority_Control) (255 - (_priority)))
+
+#define _POSIX_Priority_From_core( _priority ) \
+ (255 - (_priority))
+
+#endif
diff --git a/cpukit/posix/macros/rtems/posix/pthread.inl b/cpukit/posix/macros/rtems/posix/pthread.inl
new file mode 100644
index 0000000000..178c593f52
--- /dev/null
+++ b/cpukit/posix/macros/rtems/posix/pthread.inl
@@ -0,0 +1,54 @@
+/* rtems/posix/pthread.inl
+ *
+ * This include file contains the macro implementation of the private
+ * inlined routines for POSIX threads.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_THREADS_inl
+#define __RTEMS_POSIX_THREADS_inl
+
+/*PAGE
+ *
+ * _POSIX_Threads_Allocate
+ */
+
+#define _POSIX_Threads_Allocate() \
+ (Thread_Control *) _Objects_Allocate( &_POSIX_Threads_Information )
+
+/*PAGE
+ *
+ * _POSIX_Threads_Free
+ */
+
+#define _POSIX_Threads_Free( _the_pthread ) \
+ _Objects_Free( &_POSIX_Threads_Information, &(_the_pthread)->Object )
+
+/*PAGE
+ *
+ * _POSIX_Threads_Get
+ */
+
+#define _POSIX_Threads_Get( _id, _location ) \
+ (Thread_Control *) \
+ _Objects_Get( &_POSIX_Threads_Information, (Objects_Id)(_id), (_location) )
+
+/*PAGE
+ *
+ * _POSIX_Threads_Is_null
+ */
+
+#define _POSIX_Threads_Is_null( _the_pthread ) \
+ (!(_the_pthread))
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/posix/macros/rtems/posix/semaphore.inl b/cpukit/posix/macros/rtems/posix/semaphore.inl
new file mode 100644
index 0000000000..4fae864c3c
--- /dev/null
+++ b/cpukit/posix/macros/rtems/posix/semaphore.inl
@@ -0,0 +1,64 @@
+/* rtems/posix/semaphore.inl
+ *
+ * This include file contains the macro implementation of the private
+ * inlined routines for POSIX Semaphores.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_POSIX_SEMAPHORE_inl
+#define __RTEMS_POSIX_SEMAPHORE_inl
+
+/*PAGE
+ *
+ * _POSIX_Semaphore_Allocate
+ */
+
+#define _POSIX_Semaphore_Allocate() \
+ (POSIX_Semaphore_Control *) \
+ _Objects_Allocate( &_POSIX_Semaphore_Information );
+
+/*PAGE
+ *
+ * _POSIX_Semaphore_Free
+ */
+
+#define _POSIX_Semaphore_Free( _the_semaphore ) \
+ _Objects_Free( &_POSIX_Semaphore_Information, &(_the_semaphore)->Object )
+
+/*PAGE
+ *
+ * _POSIX_Semaphore_Namespace_remove
+ */
+
+#define _POSIX_Semaphore_Namespace_remove( _the_semaphore ) \
+ _Objects_Namespace_remove( \
+ &_POSIX_Semaphore_Information, &(_the_semaphore)->Object )
+
+/*PAGE
+ *
+ * _POSIX_Semaphore_Get
+ */
+
+#define _POSIX_Semaphore_Get( _id, _location ) \
+ (POSIX_Semaphore_Control *) \
+ _Objects_Get( &_POSIX_Semaphore_Information, *(_id), (_location) )
+
+/*PAGE
+ *
+ * _POSIX_Semaphore_Is_null
+ */
+
+#define _POSIX_Semaphore_Is_null( _the_semaphore ) \
+ (!(_the_semaphore))
+
+#endif
+/* end of include file */
+
diff --git a/cpukit/posix/macros/rtems/posix/timer.inl b/cpukit/posix/macros/rtems/posix/timer.inl
new file mode 100644
index 0000000000..6847cad6b3
--- /dev/null
+++ b/cpukit/posix/macros/rtems/posix/timer.inl
@@ -0,0 +1,53 @@
+/* timer.inl
+ *
+ * This file contains the macro implementation of the inlined routines
+ * from the POSIX Timer Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __POSIX_TIMER_inl
+#define __POSIX_TIMER_inl
+
+/*PAGE
+ *
+ * _POSIX_Timer_Allocate
+ */
+
+#define _POSIX_Timer_Allocate() \
+ (POSIX_Timer_Control *) _Objects_Allocate( &_POSIX_Timer_Information )
+
+/*PAGE
+ *
+ * _POSIX_Timer_Free
+ */
+
+#define _POSIX_Timer_Free( _the_timer ) \
+ _Objects_Free( &_POSIX_Timer_Information, &(_the_timer)->Object );
+
+/*PAGE
+ *
+ * _POSIX_Timer_Get
+ */
+
+#define _POSIX_Timer_Get( _the_timer ) \
+ (POSIX_Timer_Control *) \
+ _Objects_Get( &_POSIX_Timer_Information, (_id), (_location) )
+
+/*PAGE
+ *
+ * _POSIX_Timer_Is_null
+ */
+
+#define _POSIX_Timer_Is_null( _the_timer ) \
+ (!(_the_timer))
+
+#endif
+/* end of include file */
diff --git a/cpukit/posix/src/.cvsignore b/cpukit/posix/src/.cvsignore
new file mode 100644
index 0000000000..000074c626
--- /dev/null
+++ b/cpukit/posix/src/.cvsignore
@@ -0,0 +1,4 @@
+stamp-h
+stamp-h.in
+config.h
+config.h.in
diff --git a/cpukit/posix/src/README.mqueue b/cpukit/posix/src/README.mqueue
new file mode 100644
index 0000000000..12c8afc03e
--- /dev/null
+++ b/cpukit/posix/src/README.mqueue
@@ -0,0 +1,38 @@
+#
+# $Id$
+#
+
+This program should print out the default attribute settings for a
+POSIX message queue.
+
+#include <mqueue.h>
+#include <stdio.h>
+
+main()
+{
+ mqd_t mqfd;
+ struct mq_attr mqstat;
+ int status;
+
+ /* this should create it */
+ mqfd = mq_open("myipc",O_WRONLY|O_CREAT,NULL);
+ if ( (int)mqfd == -1 ) {
+ perror( "Unable to open message queue" );
+ exit( 1 );
+ }
+
+ status = mq_getattr(mqfd, &mqstat);
+ if ( !status ) {
+ printf( "mq_maxmsg: %d\n", mqstat.mq_maxmsg );
+ printf( "mq_msgsize: %d\n", mqstat.mq_msgsize );
+ printf( "mq_curmsgs: %d\n", mqstat.mq_curmsgs );
+ } else {
+ perror( "Unable to get attributes on message queue" );
+ exit( 1 );
+ }
+
+ /* this should delete it */
+ (void) mq_close( mqfd );
+ exit( 0 );
+}
+
diff --git a/cpukit/posix/src/adasupp.c b/cpukit/posix/src/adasupp.c
new file mode 100644
index 0000000000..535ff669c2
--- /dev/null
+++ b/cpukit/posix/src/adasupp.c
@@ -0,0 +1,32 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <rtems/system.h>
+#include <rtems/posix/pthread.h>
+
+/*PAGE
+ *
+ * _ada_pthread_minimum_stack_size
+ *
+ * This routine returns the minimum stack size so the GNAT RTS can
+ * allocate enough stack for Ada tasks.
+ */
+
+size_t _ada_pthread_minimum_stack_size( void )
+{
+ /*
+ * Eventually this may need to include a per cpu family calculation
+ * but for now, this will do.
+ */
+
+ return PTHREAD_MINIMUM_STACK_SIZE * 2;
+}
diff --git a/cpukit/posix/src/adjtime.c b/cpukit/posix/src/adjtime.c
new file mode 100644
index 0000000000..1e06dab608
--- /dev/null
+++ b/cpukit/posix/src/adjtime.c
@@ -0,0 +1,60 @@
+/*
+ * adjustime() function - required by NTP
+ *
+ * I am unaware of the history behind the definition of this service
+ * and don't know if its behavior is covered by any standard. --joel
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <time.h>
+#include <sys/time.h>
+
+#include <rtems/system.h>
+#include <rtems/score/tod.h>
+#include <rtems/posix/time.h>
+
+static long __adjustment = 0;
+
+int adjtime ( struct timeval *delta, struct timeval *olddelta )
+{
+ struct timespec ts;
+
+ if ( olddelta ) {
+ olddelta->tv_sec = __adjustment / TOD_MICROSECONDS_PER_SECOND;
+ olddelta->tv_usec = __adjustment / TOD_MICROSECONDS_PER_SECOND;
+ }
+
+ if ( !delta )
+ return -1;
+
+ __adjustment = (delta->tv_sec * TOD_MICROSECONDS_PER_SECOND) + delta->tv_usec;
+ /* too small to account for */
+ if ( __adjustment < _TOD_Microseconds_per_tick )
+ return 0;
+
+ clock_gettime( CLOCK_REALTIME, &ts );
+
+ ts.tv_sec += (__adjustment / TOD_MICROSECONDS_PER_SECOND);
+ ts.tv_nsec += (__adjustment % TOD_MICROSECONDS_PER_SECOND) *
+ TOD_NANOSECONDS_PER_MICROSECOND;
+
+ /* if adjustment is too much positive */
+ while ( ts.tv_nsec >= TOD_NANOSECONDS_PER_SECOND ) {
+ ts.tv_nsec -= TOD_NANOSECONDS_PER_SECOND;
+ ts.tv_sec++;
+ }
+
+ /* if adjustment is too much negative */
+ while ( ts.tv_nsec <= (-1 * TOD_NANOSECONDS_PER_SECOND) ) {
+ ts.tv_nsec += TOD_NANOSECONDS_PER_SECOND;
+ ts.tv_sec--;
+ }
+
+ clock_settime( CLOCK_REALTIME, &ts );
+ return 0;
+}
diff --git a/cpukit/posix/src/aio.c b/cpukit/posix/src/aio.c
new file mode 100644
index 0000000000..f993a5f2d5
--- /dev/null
+++ b/cpukit/posix/src/aio.c
@@ -0,0 +1,118 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <aio.h>
+
+#include <rtems/system.h>
+#include <rtems/seterr.h>
+
+int POSIX_NOT_IMPLEMENTED();
+
+/*PAGE
+ *
+ * 6.7.2 Asynchronous Read, P1003.1b-1993, p. 154
+ */
+
+int aio_read(
+ struct aiocb *aiocbp
+)
+{
+ return POSIX_NOT_IMPLEMENTED();
+}
+
+/*PAGE
+ *
+ * 6.7.3 Asynchronous Write, P1003.1b-1993, p. 155
+ */
+
+int aio_write(
+ struct aiocb *aiocbp
+)
+{
+ return POSIX_NOT_IMPLEMENTED();
+}
+
+/*PAGE
+ *
+ * 6.7.4 List Directed I/O, P1003.1b-1993, p. 158
+ */
+
+int lio_listio(
+ int mode,
+ struct aiocb * const list[],
+ int nent,
+ struct sigevent *sig
+)
+{
+ return POSIX_NOT_IMPLEMENTED();
+}
+
+/*PAGE
+ *
+ * 6.7.5 Retrieve Error of Asynchronous I/O Operation, P1003.1b-1993, p. 161
+ */
+
+int aio_error(
+ const struct aiocb *aiocbp
+)
+{
+ return POSIX_NOT_IMPLEMENTED();
+}
+
+/*PAGE
+ *
+ * 6.7.6 Retrieve Return Status of Asynchronous I/O Operation,
+ * P1003.1b-1993, p. 162
+ */
+
+int aio_return(
+ const struct aiocb *aiocbp
+)
+{
+ return POSIX_NOT_IMPLEMENTED();
+}
+
+/*PAGE
+ *
+ * 6.7.7 Cancel Asynchronous I/O Operation, P1003.1b-1993, p. 163
+ */
+
+int aio_cancel(
+ int filedes,
+ struct aiocb *aiocbp
+)
+{
+ return POSIX_NOT_IMPLEMENTED();
+}
+
+/*PAGE
+ *
+ * 6.7.7 Wait for Asynchronous I/O Request, P1003.1b-1993, p. 164
+ */
+
+int aio_suspend(
+ struct aiocb * const list[],
+ int nent,
+ const struct timespec *timeout
+)
+{
+ return POSIX_NOT_IMPLEMENTED();
+}
+
+/*PAGE
+ *
+ * 6.7.9 Asynchronous File Synchronization, P1003.1b-1993, p. 166
+ */
+
+int aio_fsync(
+ int op,
+ struct aiocb *aiocbp
+)
+{
+ return POSIX_NOT_IMPLEMENTED();
+}
diff --git a/cpukit/posix/src/alarm.c b/cpukit/posix/src/alarm.c
new file mode 100644
index 0000000000..c061b97e48
--- /dev/null
+++ b/cpukit/posix/src/alarm.c
@@ -0,0 +1,82 @@
+/*
+ * 3.4.1 Schedule Alarm, P1003.1b-1993, p. 79
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+/* #include <errno.h> */
+
+#include <rtems/system.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/psignal.h>
+
+Watchdog_Control _POSIX_signals_Alarm_timer;
+
+/*PAGE
+ *
+ * _POSIX_signals_Alarm_TSR
+ */
+
+void _POSIX_signals_Alarm_TSR(
+ Objects_Id id,
+ void *argument
+)
+{
+ int status;
+
+ status = kill( getpid(), SIGALRM );
+ /* XXX can't print from an ISR, should this be fatal? */
+}
+
+unsigned int alarm(
+ unsigned int seconds
+)
+{
+ unsigned int remaining = 0;
+ Watchdog_Control *the_timer;
+
+ the_timer = &_POSIX_signals_Alarm_timer;
+
+ /*
+ * Initialize the timer used to implement alarm().
+ */
+
+ if ( !the_timer->routine ) {
+ _Watchdog_Initialize( the_timer, _POSIX_signals_Alarm_TSR, 0, NULL );
+ } else {
+ switch ( _Watchdog_Remove( the_timer ) ) {
+ case WATCHDOG_INACTIVE:
+ case WATCHDOG_BEING_INSERTED:
+ break;
+
+ case WATCHDOG_ACTIVE:
+ case WATCHDOG_REMOVE_IT:
+ /*
+ * The stop_time and start_time fields are snapshots of ticks since
+ * boot. Since alarm() is dealing in seconds, we must account for
+ * this.
+ */
+
+ remaining = the_timer->initial -
+ ((the_timer->stop_time - the_timer->start_time) /
+ _TOD_Ticks_per_second);
+ break;
+ }
+ }
+
+ _Watchdog_Insert_seconds( the_timer, seconds );
+
+ return remaining;
+}
diff --git a/cpukit/posix/src/cancel.c b/cpukit/posix/src/cancel.c
new file mode 100644
index 0000000000..2b72be4aef
--- /dev/null
+++ b/cpukit/posix/src/cancel.c
@@ -0,0 +1,62 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/posix/cancel.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/threadsup.h>
+
+/*PAGE
+ *
+ * 18.2.1 Canceling Execution of a Thread, P1003.1c/Draft 10, p. 181
+ */
+
+int pthread_cancel(
+ pthread_t thread
+)
+{
+ Thread_Control *the_thread;
+ POSIX_API_Control *thread_support;
+ Objects_Locations location;
+
+ /*
+ * Don't even think about deleting a resource from an ISR.
+ */
+
+ if ( _ISR_Is_in_progress() )
+ return EPROTO;
+
+ the_thread = _POSIX_Threads_Get( thread, &location );
+ switch ( location ) {
+ case OBJECTS_ERROR:
+ return EINVAL;
+ case OBJECTS_REMOTE:
+ return POSIX_MP_NOT_IMPLEMENTED();
+ case OBJECTS_LOCAL:
+ thread_support = the_thread->API_Extensions[ THREAD_API_POSIX ];
+
+ thread_support->cancelation_requested = 1;
+
+ if ( thread_support->cancelability_state == PTHREAD_CANCEL_ENABLE &&
+ thread_support->cancelability_type == PTHREAD_CANCEL_ASYNCHRONOUS ) {
+ _POSIX_Threads_cancel_run( the_thread );
+ }
+
+ _Thread_Enable_dispatch();
+ return 0;
+ }
+
+ return POSIX_BOTTOM_REACHED();
+}
diff --git a/cpukit/posix/src/cancelrun.c b/cpukit/posix/src/cancelrun.c
new file mode 100644
index 0000000000..17fa55bdc6
--- /dev/null
+++ b/cpukit/posix/src/cancelrun.c
@@ -0,0 +1,63 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/posix/cancel.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/threadsup.h>
+
+/*PAGE
+ *
+ * _POSIX_Threads_cancel_run
+ *
+ */
+
+void _POSIX_Threads_cancel_run(
+ Thread_Control *the_thread
+)
+{
+ POSIX_Cancel_Handler_control *handler;
+ Chain_Control *handler_stack;
+ POSIX_API_Control *thread_support;
+ ISR_Level level;
+
+ thread_support = the_thread->API_Extensions[ THREAD_API_POSIX ];
+
+ handler_stack = &thread_support->Cancellation_Handlers;
+
+ thread_support->cancelability_state = PTHREAD_CANCEL_DISABLE;
+
+ while ( !_Chain_Is_empty( handler_stack ) ) {
+ _ISR_Disable( level );
+ handler = (POSIX_Cancel_Handler_control *)
+ _Chain_Tail( handler_stack )->previous;
+ _Chain_Extract_unprotected( &handler->Node );
+ _ISR_Enable( level );
+
+ (*handler->routine)( handler->arg );
+
+ _Workspace_Free( handler );
+ }
+
+ /* Now we can delete the thread */
+
+ the_thread->Wait.return_argument = PTHREAD_CANCELED;
+ _Thread_Close(
+ _Objects_Get_information( the_thread->Object.id ),
+ the_thread
+ );
+ _POSIX_Threads_Free( the_thread );
+
+}
diff --git a/cpukit/posix/src/cleanuppop.c b/cpukit/posix/src/cleanuppop.c
new file mode 100644
index 0000000000..49c35dff41
--- /dev/null
+++ b/cpukit/posix/src/cleanuppop.c
@@ -0,0 +1,60 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/posix/cancel.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/threadsup.h>
+
+/*PAGE
+ *
+ * 18.2.3.1 Establishing Cancellation Handlers, P1003.1c/Draft 10, p. 184
+ */
+
+void pthread_cleanup_pop(
+ int execute
+)
+{
+ POSIX_Cancel_Handler_control *handler;
+ POSIX_Cancel_Handler_control tmp_handler;
+ Chain_Control *handler_stack;
+ POSIX_API_Control *thread_support;
+ ISR_Level level;
+
+ thread_support = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
+
+ handler_stack = &thread_support->Cancellation_Handlers;
+
+ _ISR_Disable( level );
+ if ( _Chain_Is_empty( handler_stack ) ) {
+ _ISR_Enable( level );
+ return;
+ }
+
+ handler = (POSIX_Cancel_Handler_control *)
+ _Chain_Tail( handler_stack )->previous;
+ _Chain_Extract_unprotected( &handler->Node );
+
+ _ISR_Enable( level );
+
+ tmp_handler = *handler;
+
+ _Thread_Disable_dispatch();
+ _Workspace_Free( handler );
+ _Thread_Enable_dispatch();
+
+ if ( execute )
+ (*tmp_handler.routine)( tmp_handler.arg );
+}
diff --git a/cpukit/posix/src/cleanuppush.c b/cpukit/posix/src/cleanuppush.c
new file mode 100644
index 0000000000..6efc7f9c45
--- /dev/null
+++ b/cpukit/posix/src/cleanuppush.c
@@ -0,0 +1,56 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/posix/cancel.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/threadsup.h>
+
+/*PAGE
+ *
+ * 18.2.3.1 Establishing Cancellation Handlers, P1003.1c/Draft 10, p. 184
+ */
+
+void pthread_cleanup_push(
+ void (*routine)( void * ),
+ void *arg
+)
+{
+ POSIX_Cancel_Handler_control *handler;
+ Chain_Control *handler_stack;
+ POSIX_API_Control *thread_support;
+
+ if ( !routine )
+ return; /* XXX what to do really? */
+
+ _Thread_Disable_dispatch();
+ handler = _Workspace_Allocate( sizeof( POSIX_Cancel_Handler_control ) );
+
+ if ( !handler ) {
+ _Thread_Enable_dispatch();
+ return; /* XXX what to do really? */
+ }
+
+ thread_support = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
+
+ handler_stack = &thread_support->Cancellation_Handlers;
+
+ handler->routine = routine;
+ handler->arg = arg;
+
+ _Chain_Append( handler_stack, &handler->Node );
+
+ _Thread_Enable_dispatch();
+}
diff --git a/cpukit/posix/src/clockgetcpuclockid.c b/cpukit/posix/src/clockgetcpuclockid.c
new file mode 100644
index 0000000000..96e554c1f5
--- /dev/null
+++ b/cpukit/posix/src/clockgetcpuclockid.c
@@ -0,0 +1,32 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <time.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/tod.h>
+
+#include <rtems/seterr.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * 20.1.3 Accessing a Process CPU-time CLock, P1003.4b/D8, p. 55
+ */
+
+int clock_getcpuclockid(
+ pid_t pid,
+ clockid_t *clock_id
+)
+{
+ return POSIX_NOT_IMPLEMENTED();
+}
diff --git a/cpukit/posix/src/clockgetenableattr.c b/cpukit/posix/src/clockgetenableattr.c
new file mode 100644
index 0000000000..0d3fbebfb4
--- /dev/null
+++ b/cpukit/posix/src/clockgetenableattr.c
@@ -0,0 +1,32 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <time.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/tod.h>
+
+#include <rtems/seterr.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * 20.1.5 CPU-time Clock Attribute Access, P1003.4b/D8, p. 58
+ */
+
+int clock_getenable_attr(
+ clockid_t clock_id,
+ int *attr
+)
+{
+ return POSIX_NOT_IMPLEMENTED();
+}
diff --git a/cpukit/posix/src/clockgetres.c b/cpukit/posix/src/clockgetres.c
new file mode 100644
index 0000000000..423759c8d8
--- /dev/null
+++ b/cpukit/posix/src/clockgetres.c
@@ -0,0 +1,55 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <time.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/tod.h>
+
+#include <rtems/seterr.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * 14.2.1 Clocks, P1003.1b-1993, p. 263
+ */
+
+int clock_getres(
+ clockid_t clock_id,
+ struct timespec *res
+)
+{
+ if ( !res )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ switch ( clock_id ) {
+
+ /*
+ * All time in rtems is based on the same clock tick.
+ */
+
+ case CLOCK_REALTIME:
+ case CLOCK_PROCESS_CPUTIME:
+ case CLOCK_THREAD_CPUTIME:
+ if ( res ) {
+ res->tv_sec = _TOD_Microseconds_per_tick / 1000000;
+ res->tv_nsec = _TOD_Microseconds_per_tick * 1000;
+ /* _POSIX_Interval_to_timespec( _TOD_Microseconds_per_tick, res ); */
+ }
+ break;
+
+ default:
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ }
+ return 0;
+}
diff --git a/cpukit/posix/src/clockgettime.c b/cpukit/posix/src/clockgettime.c
new file mode 100644
index 0000000000..97a6f607e5
--- /dev/null
+++ b/cpukit/posix/src/clockgettime.c
@@ -0,0 +1,69 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <time.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/tod.h>
+
+#include <rtems/seterr.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * 14.2.1 Clocks, P1003.1b-1993, p. 263
+ */
+
+int clock_gettime(
+ clockid_t clock_id,
+ struct timespec *tp
+)
+{
+ ISR_Level level;
+ time_t seconds;
+ long ticks;
+
+ if ( !tp )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ switch ( clock_id ) {
+
+ case CLOCK_REALTIME:
+
+ _ISR_Disable( level );
+ seconds = _TOD_Seconds_since_epoch;
+ ticks = _TOD_Current.ticks;
+ _ISR_Enable( level );
+
+ tp->tv_sec = seconds + POSIX_TIME_SECONDS_1970_THROUGH_1988;
+ tp->tv_nsec = ticks * _TOD_Microseconds_per_tick *
+ TOD_NANOSECONDS_PER_MICROSECOND;
+ break;
+
+#ifdef _POSIX_CPUTIME
+ case CLOCK_PROCESS_CPUTIME:
+ /* don't base this on _Watchdog_Ticks_since_boot--duration is too short*/
+ return POSIX_NOT_IMPLEMENTED();
+ break;
+#endif
+
+#ifdef _POSIX_THREAD_CPUTIME
+ case CLOCK_THREAD_CPUTIME:
+ return POSIX_NOT_IMPLEMENTED();
+ break;
+#endif
+ default:
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ }
+ return 0;
+}
diff --git a/cpukit/posix/src/clocksetenableattr.c b/cpukit/posix/src/clocksetenableattr.c
new file mode 100644
index 0000000000..f5a29920d1
--- /dev/null
+++ b/cpukit/posix/src/clocksetenableattr.c
@@ -0,0 +1,32 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <time.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/tod.h>
+
+#include <rtems/seterr.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * 20.1.5 CPU-time Clock Attribute Access, P1003.4b/D8, p. 58
+ */
+
+int clock_setenable_attr(
+ clockid_t clock_id,
+ int attr
+)
+{
+ return POSIX_NOT_IMPLEMENTED();
+}
diff --git a/cpukit/posix/src/clocksettime.c b/cpukit/posix/src/clocksettime.c
new file mode 100644
index 0000000000..c85e90de61
--- /dev/null
+++ b/cpukit/posix/src/clocksettime.c
@@ -0,0 +1,88 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <time.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/tod.h>
+
+#include <rtems/seterr.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * 14.2.1 Clocks, P1003.1b-1993, p. 263
+ */
+
+int clock_settime(
+ clockid_t clock_id,
+ const struct timespec *tp
+)
+{
+ struct tm split_time;
+ TOD_Control tod;
+ Watchdog_Interval seconds;
+
+ assert( tp );
+
+ switch ( clock_id ) {
+
+ case CLOCK_REALTIME:
+ (void) gmtime_r( &tp->tv_sec, &split_time );
+
+ /*
+ * Convert the tm structure format to that used by the TOD Handler
+ *
+ * NOTE: TOD Handler does not honor leap seconds.
+ */
+
+ tod.year = split_time.tm_year + 1900; /* RHS is years since 1900 */
+ tod.month = split_time.tm_mon + 1; /* RHS uses 0-11 */
+ tod.day = split_time.tm_mday;
+ tod.hour = split_time.tm_hour;
+ tod.minute = split_time.tm_min;
+ tod.second = split_time.tm_sec; /* RHS allows 0-61 for leap seconds */
+
+ tod.ticks = (tp->tv_nsec / TOD_NANOSECONDS_PER_MICROSECOND) /
+ _TOD_Microseconds_per_tick;
+
+ if ( !_TOD_Validate( &tod ) )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ /*
+ * We can't use the tp->tv_sec field because it is based on
+ * a different EPOCH.
+ */
+
+ seconds = _TOD_To_seconds( &tod );
+ _Thread_Disable_dispatch();
+ _TOD_Set( &tod, seconds );
+ _Thread_Enable_dispatch();
+ break;
+
+#ifdef _POSIX_CPUTIME
+ case CLOCK_PROCESS_CPUTIME:
+ return POSIX_NOT_IMPLEMENTED();
+ break;
+#endif
+
+#ifdef _POSIX_THREAD_CPUTIME
+ case CLOCK_THREAD_CPUTIME:
+ return POSIX_NOT_IMPLEMENTED();
+ break;
+#endif
+ default:
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ }
+ return 0;
+}
diff --git a/cpukit/posix/src/cond.c b/cpukit/posix/src/cond.c
new file mode 100644
index 0000000000..b2d0fcd8d1
--- /dev/null
+++ b/cpukit/posix/src/cond.c
@@ -0,0 +1,52 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/posix/cond.h>
+#include <rtems/posix/time.h>
+#include <rtems/posix/mutex.h>
+
+/*PAGE
+ *
+ * _POSIX_Condition_variables_Manager_initialization
+ *
+ * This routine initializes all condition variable manager related data
+ * structures.
+ *
+ * Input parameters:
+ * maximum_condition_variables - maximum configured condition_variables
+ *
+ * Output parameters: NONE
+ */
+
+void _POSIX_Condition_variables_Manager_initialization(
+ uint32_t maximum_condition_variables
+)
+{
+ _Objects_Initialize_information(
+ &_POSIX_Condition_variables_Information, /* object information table */
+ OBJECTS_POSIX_API, /* object API */
+ OBJECTS_POSIX_CONDITION_VARIABLES, /* object class */
+ maximum_condition_variables, /* maximum objects of this class */
+ sizeof( POSIX_Condition_variables_Control ),
+ /* size of this object's control block */
+ FALSE, /* TRUE if names for this object are strings */
+ 0 /* maximum length of each object's name */
+#if defined(RTEMS_MULTIPROCESSING)
+ ,
+ FALSE, /* TRUE if this is a global object class */
+ NULL /* Proxy extraction support callout */
+#endif
+ );
+}
diff --git a/cpukit/posix/src/condattrdestroy.c b/cpukit/posix/src/condattrdestroy.c
new file mode 100644
index 0000000000..3d818e9fef
--- /dev/null
+++ b/cpukit/posix/src/condattrdestroy.c
@@ -0,0 +1,35 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/posix/cond.h>
+#include <rtems/posix/time.h>
+#include <rtems/posix/mutex.h>
+
+/*PAGE
+ *
+ * 11.4.1 Condition Variable Initialization Attributes,
+ * P1003.1c/Draft 10, p. 96
+ */
+
+int pthread_condattr_destroy(
+ pthread_condattr_t *attr
+)
+{
+ if ( !attr || attr->is_initialized == FALSE )
+ return EINVAL;
+
+ attr->is_initialized = FALSE;
+ return 0;
+}
diff --git a/cpukit/posix/src/condattrgetpshared.c b/cpukit/posix/src/condattrgetpshared.c
new file mode 100644
index 0000000000..479fb61cfb
--- /dev/null
+++ b/cpukit/posix/src/condattrgetpshared.c
@@ -0,0 +1,36 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/posix/cond.h>
+#include <rtems/posix/time.h>
+#include <rtems/posix/mutex.h>
+
+/*PAGE
+ *
+ * 11.4.1 Condition Variable Initialization Attributes,
+ * P1003.1c/Draft 10, p. 96
+ */
+
+int pthread_condattr_getpshared(
+ const pthread_condattr_t *attr,
+ int *pshared
+)
+{
+ if ( !attr )
+ return EINVAL;
+
+ *pshared = attr->process_shared;
+ return 0;
+}
diff --git a/cpukit/posix/src/condattrinit.c b/cpukit/posix/src/condattrinit.c
new file mode 100644
index 0000000000..3cd620a312
--- /dev/null
+++ b/cpukit/posix/src/condattrinit.c
@@ -0,0 +1,35 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/posix/cond.h>
+#include <rtems/posix/time.h>
+#include <rtems/posix/mutex.h>
+
+/*PAGE
+ *
+ * 11.4.1 Condition Variable Initialization Attributes,
+ * P1003.1c/Draft 10, p. 96
+ */
+
+int pthread_condattr_init(
+ pthread_condattr_t *attr
+)
+{
+ if ( !attr )
+ return EINVAL;
+
+ *attr = _POSIX_Condition_variables_Default_attributes;
+ return 0;
+}
diff --git a/cpukit/posix/src/condattrsetpshared.c b/cpukit/posix/src/condattrsetpshared.c
new file mode 100644
index 0000000000..05539b2866
--- /dev/null
+++ b/cpukit/posix/src/condattrsetpshared.c
@@ -0,0 +1,43 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/posix/cond.h>
+#include <rtems/posix/time.h>
+#include <rtems/posix/mutex.h>
+
+/*PAGE
+ *
+ * 11.4.1 Condition Variable Initialization Attributes,
+ * P1003.1c/Draft 10, p. 96
+ */
+
+int pthread_condattr_setpshared(
+ pthread_condattr_t *attr,
+ int pshared
+)
+{
+ if ( !attr )
+ return EINVAL;
+
+ switch ( pshared ) {
+ case PTHREAD_PROCESS_SHARED:
+ case PTHREAD_PROCESS_PRIVATE:
+ attr->process_shared = pshared;
+ return 0;
+
+ default:
+ return EINVAL;
+ }
+}
diff --git a/cpukit/posix/src/condbroadcast.c b/cpukit/posix/src/condbroadcast.c
new file mode 100644
index 0000000000..b1efbceb96
--- /dev/null
+++ b/cpukit/posix/src/condbroadcast.c
@@ -0,0 +1,30 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/posix/cond.h>
+#include <rtems/posix/time.h>
+#include <rtems/posix/mutex.h>
+
+/*PAGE
+ *
+ * 11.4.3 Broadcasting and Signaling a Condition, P1003.1c/Draft 10, p. 101
+ */
+
+int pthread_cond_broadcast(
+ pthread_cond_t *cond
+)
+{
+ return _POSIX_Condition_variables_Signal_support( cond, TRUE );
+}
diff --git a/cpukit/posix/src/conddefaultattributes.c b/cpukit/posix/src/conddefaultattributes.c
new file mode 100644
index 0000000000..b8b0ae824c
--- /dev/null
+++ b/cpukit/posix/src/conddefaultattributes.c
@@ -0,0 +1,28 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/posix/cond.h>
+#include <rtems/posix/time.h>
+#include <rtems/posix/mutex.h>
+
+/*PAGE
+ *
+ * The default condition variable attributes structure.
+ */
+
+const pthread_condattr_t _POSIX_Condition_variables_Default_attributes = {
+ TRUE, /* is_initialized */
+ PTHREAD_PROCESS_PRIVATE /* process_shared */
+};
diff --git a/cpukit/posix/src/conddestroy.c b/cpukit/posix/src/conddestroy.c
new file mode 100644
index 0000000000..a6d2c0fc81
--- /dev/null
+++ b/cpukit/posix/src/conddestroy.c
@@ -0,0 +1,80 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/posix/cond.h>
+#include <rtems/posix/time.h>
+#include <rtems/posix/mutex.h>
+
+/*PAGE
+ *
+ * 11.4.2 Initializing and Destroying a Condition Variable,
+ * P1003.1c/Draft 10, p. 87
+ */
+
+int pthread_cond_destroy(
+ pthread_cond_t *cond
+)
+{
+ register POSIX_Condition_variables_Control *the_cond;
+ Objects_Locations location;
+
+ the_cond = _POSIX_Condition_variables_Get( cond, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE:
+#if defined(RTEMS_MULTIPROCESSING)
+ _Thread_Dispatch();
+ return POSIX_MP_NOT_IMPLEMENTED();
+ return EINVAL;
+#endif
+
+ case OBJECTS_ERROR:
+ return EINVAL;
+
+
+ case OBJECTS_LOCAL:
+
+ if ( _Thread_queue_First( &the_cond->Wait_queue ) ) {
+ _Thread_Enable_dispatch();
+ return EBUSY;
+ }
+
+ _Objects_Close(
+ &_POSIX_Condition_variables_Information,
+ &the_cond->Object
+ );
+
+ _POSIX_Condition_variables_Free( the_cond );
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( the_cond->process_shared == PTHREAD_PROCESS_SHARED ) {
+
+ _Objects_MP_Close(
+ &_POSIX_Condition_variables_Information,
+ the_cond->Object.id
+ );
+
+ _POSIX_Condition_variables_MP_Send_process_packet(
+ POSIX_CONDITION_VARIABLES_MP_ANNOUNCE_DELETE,
+ the_cond->Object.id,
+ 0, /* Not used */
+ 0 /* Not used */
+ );
+ }
+#endif
+ _Thread_Enable_dispatch();
+ return 0;
+ }
+ return POSIX_BOTTOM_REACHED();
+}
diff --git a/cpukit/posix/src/condinit.c b/cpukit/posix/src/condinit.c
new file mode 100644
index 0000000000..319cd4383a
--- /dev/null
+++ b/cpukit/posix/src/condinit.c
@@ -0,0 +1,99 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/posix/cond.h>
+#include <rtems/posix/time.h>
+#include <rtems/posix/mutex.h>
+
+/*PAGE
+ *
+ * 11.4.2 Initializing and Destroying a Condition Variable,
+ * P1003.1c/Draft 10, p. 87
+ */
+
+int pthread_cond_init(
+ pthread_cond_t *cond,
+ const pthread_condattr_t *attr
+)
+{
+ POSIX_Condition_variables_Control *the_cond;
+ const pthread_condattr_t *the_attr;
+
+ if ( attr ) the_attr = attr;
+ else the_attr = &_POSIX_Condition_variables_Default_attributes;
+
+ /*
+ * XXX: Be careful about attributes when global!!!
+ */
+
+ if ( the_attr->process_shared == PTHREAD_PROCESS_SHARED )
+ return POSIX_MP_NOT_IMPLEMENTED();
+
+ if ( !the_attr->is_initialized )
+ return EINVAL;
+
+ _Thread_Disable_dispatch();
+
+ the_cond = _POSIX_Condition_variables_Allocate();
+
+ if ( !the_cond ) {
+ _Thread_Enable_dispatch();
+ return ENOMEM;
+ }
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( the_attr->process_shared == PTHREAD_PROCESS_SHARED &&
+ !( _Objects_MP_Allocate_and_open( &_POSIX_Condition_variables_Information,
+ 0, the_cond->Object.id, FALSE ) ) ) {
+ _POSIX_Condition_variables_Free( the_cond );
+ _Thread_Enable_dispatch();
+ return EAGAIN;
+ }
+#endif
+
+ the_cond->process_shared = the_attr->process_shared;
+
+ the_cond->Mutex = POSIX_CONDITION_VARIABLES_NO_MUTEX;
+
+/* XXX some more initialization might need to go here */
+ _Thread_queue_Initialize(
+ &the_cond->Wait_queue,
+ THREAD_QUEUE_DISCIPLINE_FIFO,
+ STATES_WAITING_FOR_CONDITION_VARIABLE,
+ ETIMEDOUT
+ );
+
+ _Objects_Open(
+ &_POSIX_Condition_variables_Information,
+ &the_cond->Object,
+ 0
+ );
+
+ *cond = the_cond->Object.id;
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( the_attr->process_shared == PTHREAD_PROCESS_SHARED )
+ _POSIX_Condition_variables_MP_Send_process_packet(
+ POSIX_CONDITION_VARIABLES_MP_ANNOUNCE_CREATE,
+ the_cond->Object.id,
+ 0, /* Name not used */
+ 0 /* Not used */
+ );
+#endif
+
+ _Thread_Enable_dispatch();
+
+ return 0;
+}
diff --git a/cpukit/posix/src/condmp.c b/cpukit/posix/src/condmp.c
new file mode 100644
index 0000000000..8b5054d264
--- /dev/null
+++ b/cpukit/posix/src/condmp.c
@@ -0,0 +1,45 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/posix/cond.h>
+#include <rtems/posix/time.h>
+#include <rtems/posix/mutex.h>
+
+/*
+ * TEMPORARY
+ */
+
+#if defined(RTEMS_MULTIPROCESSING)
+void _POSIX_Condition_variables_MP_Send_process_packet (
+ POSIX_Condition_variables_MP_Remote_operations operation,
+ Objects_Id condition_variables_id,
+ Objects_Name name,
+ Objects_Id proxy_id
+)
+{
+ (void) POSIX_MP_NOT_IMPLEMENTED();
+}
+
+void _POSIX_Condition_variables_MP_Send_extract_proxy(
+ Thread_Control *the_thread
+)
+{
+ (void) POSIX_MP_NOT_IMPLEMENTED();
+}
+#endif
+
+/*
+ * END OF TEMPORARY
+ */
diff --git a/cpukit/posix/src/condsignal.c b/cpukit/posix/src/condsignal.c
new file mode 100644
index 0000000000..bd9d4b3b07
--- /dev/null
+++ b/cpukit/posix/src/condsignal.c
@@ -0,0 +1,30 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/posix/cond.h>
+#include <rtems/posix/time.h>
+#include <rtems/posix/mutex.h>
+
+/*PAGE
+ *
+ * 11.4.3 Broadcasting and Signaling a Condition, P1003.1c/Draft 10, p. 101
+ */
+
+int pthread_cond_signal(
+ pthread_cond_t *cond
+)
+{
+ return _POSIX_Condition_variables_Signal_support( cond, FALSE );
+}
diff --git a/cpukit/posix/src/condsignalsupp.c b/cpukit/posix/src/condsignalsupp.c
new file mode 100644
index 0000000000..5fad8e0ead
--- /dev/null
+++ b/cpukit/posix/src/condsignalsupp.c
@@ -0,0 +1,61 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/posix/cond.h>
+#include <rtems/posix/time.h>
+#include <rtems/posix/mutex.h>
+
+/*PAGE
+ *
+ * _POSIX_Condition_variables_Signal_support
+ *
+ * A support routine which implements guts of the broadcast and single task
+ * wake up version of the "signal" operation.
+ */
+
+int _POSIX_Condition_variables_Signal_support(
+ pthread_cond_t *cond,
+ boolean is_broadcast
+)
+{
+ register POSIX_Condition_variables_Control *the_cond;
+ Objects_Locations location;
+ Thread_Control *the_thread;
+
+ the_cond = _POSIX_Condition_variables_Get( cond, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE:
+#if defined(RTEMS_MULTIPROCESSING)
+ _Thread_Dispatch();
+ return POSIX_MP_NOT_IMPLEMENTED();
+ return EINVAL;
+#endif
+
+ case OBJECTS_ERROR:
+ return EINVAL;
+ case OBJECTS_LOCAL:
+
+ do {
+ the_thread = _Thread_queue_Dequeue( &the_cond->Wait_queue );
+ if ( !the_thread )
+ the_cond->Mutex = POSIX_CONDITION_VARIABLES_NO_MUTEX;
+ } while ( is_broadcast && the_thread );
+
+ _Thread_Enable_dispatch();
+
+ return 0;
+ }
+ return POSIX_BOTTOM_REACHED();
+}
diff --git a/cpukit/posix/src/condtimedwait.c b/cpukit/posix/src/condtimedwait.c
new file mode 100644
index 0000000000..32ce1d4a05
--- /dev/null
+++ b/cpukit/posix/src/condtimedwait.c
@@ -0,0 +1,61 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/posix/cond.h>
+#include <rtems/posix/time.h>
+#include <rtems/posix/mutex.h>
+
+/*PAGE
+ *
+ * 11.4.4 Waiting on a Condition, P1003.1c/Draft 10, p. 105
+ */
+
+int pthread_cond_timedwait(
+ pthread_cond_t *cond,
+ pthread_mutex_t *mutex,
+ const struct timespec *abstime
+)
+{
+ Watchdog_Interval timeout;
+ struct timespec current_time;
+ struct timespec difference;
+ boolean already_timedout = FALSE;
+
+ if ( !abstime )
+ return EINVAL;
+
+ /*
+ * The abstime is a walltime. We turn it into an interval.
+ */
+
+ (void) clock_gettime( CLOCK_REALTIME, &current_time );
+
+ /* XXX probably some error checking should go here */
+
+ _POSIX_Timespec_subtract( &current_time, abstime, &difference );
+
+ if ( ( difference.tv_sec < 0 ) || ( ( difference.tv_sec == 0 ) &&
+ ( difference.tv_nsec < 0 ) ) )
+ already_timedout = TRUE;
+
+ timeout = _POSIX_Timespec_to_interval( &difference );
+
+ return _POSIX_Condition_variables_Wait_support(
+ cond,
+ mutex,
+ timeout,
+ already_timedout
+ );
+}
diff --git a/cpukit/posix/src/condwait.c b/cpukit/posix/src/condwait.c
new file mode 100644
index 0000000000..cde020fe93
--- /dev/null
+++ b/cpukit/posix/src/condwait.c
@@ -0,0 +1,36 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/posix/cond.h>
+#include <rtems/posix/time.h>
+#include <rtems/posix/mutex.h>
+
+/*PAGE
+ *
+ * 11.4.4 Waiting on a Condition, P1003.1c/Draft 10, p. 105
+ */
+
+int pthread_cond_wait(
+ pthread_cond_t *cond,
+ pthread_mutex_t *mutex
+)
+{
+ return _POSIX_Condition_variables_Wait_support(
+ cond,
+ mutex,
+ THREAD_QUEUE_WAIT_FOREVER,
+ FALSE
+ );
+}
diff --git a/cpukit/posix/src/condwaitsupp.c b/cpukit/posix/src/condwaitsupp.c
new file mode 100644
index 0000000000..02780779bf
--- /dev/null
+++ b/cpukit/posix/src/condwaitsupp.c
@@ -0,0 +1,108 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/posix/cond.h>
+#include <rtems/posix/time.h>
+#include <rtems/posix/mutex.h>
+
+/*PAGE
+ *
+ * _POSIX_Condition_variables_Wait_support
+ *
+ * A support routine which implements guts of the blocking, non-blocking, and
+ * timed wait version of condition variable wait routines.
+ */
+
+int _POSIX_Condition_variables_Wait_support(
+ pthread_cond_t *cond,
+ pthread_mutex_t *mutex,
+ Watchdog_Interval timeout,
+ boolean already_timedout
+)
+{
+ register POSIX_Condition_variables_Control *the_cond;
+ Objects_Locations location;
+ int status;
+ int mutex_status;
+
+ if ( !_POSIX_Mutex_Get( mutex, &location ) ) {
+ return EINVAL;
+ }
+
+ _Thread_Unnest_dispatch();
+
+ the_cond = _POSIX_Condition_variables_Get( cond, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE:
+#if defined(RTEMS_MULTIPROCESSING)
+ _Thread_Dispatch();
+ return POSIX_MP_NOT_IMPLEMENTED();
+ return EINVAL;
+#endif
+ case OBJECTS_ERROR:
+ return EINVAL;
+ case OBJECTS_LOCAL:
+
+ if ( the_cond->Mutex && ( the_cond->Mutex != *mutex ) ) {
+ _Thread_Enable_dispatch();
+ return EINVAL;
+ }
+
+ (void) pthread_mutex_unlock( mutex );
+/* XXX ignore this for now since behavior is undefined
+ if ( mutex_status ) {
+ _Thread_Enable_dispatch();
+ return EINVAL;
+ }
+*/
+
+ if ( !already_timedout ) {
+ the_cond->Mutex = *mutex;
+
+ _Thread_queue_Enter_critical_section( &the_cond->Wait_queue );
+ _Thread_Executing->Wait.return_code = 0;
+ _Thread_Executing->Wait.queue = &the_cond->Wait_queue;
+ _Thread_Executing->Wait.id = *cond;
+
+ _Thread_queue_Enqueue( &the_cond->Wait_queue, timeout );
+
+ _Thread_Enable_dispatch();
+
+ /*
+ * Switch ourself out because we blocked as a result of the
+ * _Thread_queue_Enqueue.
+ */
+
+ status = _Thread_Executing->Wait.return_code;
+ if ( status && status != ETIMEDOUT )
+ return status;
+
+ } else {
+ _Thread_Enable_dispatch();
+ status = ETIMEDOUT;
+ }
+
+ /*
+ * When we get here the dispatch disable level is 0.
+ */
+
+ mutex_status = pthread_mutex_lock( mutex );
+ if ( mutex_status )
+ return EINVAL;
+
+ return status;
+ }
+ return POSIX_BOTTOM_REACHED();
+}
diff --git a/cpukit/posix/src/devctl.c b/cpukit/posix/src/devctl.c
new file mode 100644
index 0000000000..9800a109eb
--- /dev/null
+++ b/cpukit/posix/src/devctl.c
@@ -0,0 +1,26 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <devctl.h>
+
+#include <rtems/system.h>
+
+/*PAGE
+ *
+ * 21.2.1 Control a Device, P1003.4b/D8, p. 65
+ */
+
+int devctl(
+ int filedes,
+ void *dev_data_ptr,
+ size_t nbyte,
+ int *dev_info_ptr
+)
+{
+ return POSIX_NOT_IMPLEMENTED();
+}
diff --git a/cpukit/posix/src/execl.c b/cpukit/posix/src/execl.c
new file mode 100644
index 0000000000..fa820a268f
--- /dev/null
+++ b/cpukit/posix/src/execl.c
@@ -0,0 +1,21 @@
+/*
+ * execl() - POSIX 1003.1b 3.1.2
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+
+int execl(
+ const char *path,
+ const char *arg,
+ ...
+)
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/cpukit/posix/src/execle.c b/cpukit/posix/src/execle.c
new file mode 100644
index 0000000000..83bd05882c
--- /dev/null
+++ b/cpukit/posix/src/execle.c
@@ -0,0 +1,21 @@
+/*
+ * execle() - POSIX 1003.1b 3.1.2
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+
+int execle(
+ const char *path,
+ char const *arg,
+ ...
+)
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/cpukit/posix/src/execlp.c b/cpukit/posix/src/execlp.c
new file mode 100644
index 0000000000..2bc1303527
--- /dev/null
+++ b/cpukit/posix/src/execlp.c
@@ -0,0 +1,21 @@
+/*
+ * execlp() - POSIX 1003.1b 3.1.2
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+
+int execlp(
+ const char *file,
+ const char *arg,
+ ...
+)
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/cpukit/posix/src/execv.c b/cpukit/posix/src/execv.c
new file mode 100644
index 0000000000..c30d4939b6
--- /dev/null
+++ b/cpukit/posix/src/execv.c
@@ -0,0 +1,20 @@
+/*
+ * execv() - POSIX 1003.1b 3.1.2
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+
+int execv(
+ const char *file,
+ char *const argv[]
+)
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/cpukit/posix/src/execve.c b/cpukit/posix/src/execve.c
new file mode 100644
index 0000000000..43ec3004e6
--- /dev/null
+++ b/cpukit/posix/src/execve.c
@@ -0,0 +1,21 @@
+/*
+ * execve() - POSIX 1003.1b 3.1.2
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+
+int execve(
+ const char *path,
+ char *const argv[],
+ char *const envp[]
+)
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/cpukit/posix/src/execvp.c b/cpukit/posix/src/execvp.c
new file mode 100644
index 0000000000..a82db0ed32
--- /dev/null
+++ b/cpukit/posix/src/execvp.c
@@ -0,0 +1,20 @@
+/*
+ * execvp() - POSIX 1003.1b 3.1.2
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+
+int execvp(
+ const char *path,
+ char *const argv[]
+)
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/cpukit/posix/src/fork.c b/cpukit/posix/src/fork.c
new file mode 100644
index 0000000000..b06b1c9dbf
--- /dev/null
+++ b/cpukit/posix/src/fork.c
@@ -0,0 +1,18 @@
+/*
+ * fork() - POSIX 1003.1b 3.1.1
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <errno.h>
+
+int fork( void )
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/cpukit/posix/src/getpagesize.c b/cpukit/posix/src/getpagesize.c
new file mode 100644
index 0000000000..806c500a9b
--- /dev/null
+++ b/cpukit/posix/src/getpagesize.c
@@ -0,0 +1,23 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+
+/*PAGE
+ *
+ * Get System Page Size (from SVR4 and 4.2+ BSD)
+ *
+ * This is not a functional version but the SPARC backend for at least
+ * gcc 2.8.1 plus gnat 3.13p and gcc 3.0.1 require it to be there and
+ * return a reasonable value.
+ */
+
+size_t getpagesize(void)
+{
+ return 4096;
+}
diff --git a/cpukit/posix/src/intr.c b/cpukit/posix/src/intr.c
new file mode 100644
index 0000000000..895db3c120
--- /dev/null
+++ b/cpukit/posix/src/intr.c
@@ -0,0 +1,349 @@
+/*
+ * NOTE: Each task has an interrupt semaphore associated with it.
+ * No matter which interrupt occurs that it has registered,
+ * the same semaphore is used.
+ *
+ * This whole interrupt scheme may have been eliminated in a later draft.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <intr.h>
+#include <pthread.h>
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/coresem.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/posix/intr.h>
+#include <rtems/posix/time.h>
+#include <rtems/posix/threadsup.h>
+
+/*
+ * _POSIX_Interrupt_Manager_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this manager.
+ */
+
+void _POSIX_Interrupt_Manager_initialization(
+ uint32_t maximum_interrupt_handlers
+)
+{
+ uint32_t index;
+ POSIX_Interrupt_Control *the_vector;
+
+ _Objects_Initialize_information(
+ &_POSIX_Interrupt_Handlers_Information, /* object information table */
+ OBJECTS_POSIX_API, /* object API */
+ OBJECTS_POSIX_INTERRUPTS, /* object class */
+ maximum_interrupt_handlers, /* maximum objects of this class */
+ sizeof( POSIX_Interrupt_Handler_control ),
+ /* size of this object's control block */
+ FALSE, /* TRUE if names for this object are strings */
+ 0 /* maximum length of each object's name */
+#if defined(RTEMS_MULTIPROCESSING)
+ ,
+ FALSE, /* TRUE if this is a global object class */
+ NULL /* Proxy extraction support callout */
+#endif
+ );
+
+ for ( index=0 ; index < CPU_INTERRUPT_NUMBER_OF_VECTORS ; index++ ) {
+ the_vector = &_POSIX_Interrupt_Information[ index ];
+
+ the_vector->number_installed = 0;
+ the_vector->lock_count = 0;
+ the_vector->deferred_count = 0;
+ _Chain_Initialize_empty( &the_vector->Handlers );
+ }
+}
+
+/*PAGE
+ *
+ * 22.3.1 Associate a User-Written ISR with an Interrupt, P1003.4b/D8, p. 74
+ */
+
+int intr_capture(
+ intr_t intr,
+ int (*intr_handler)( void *area ),
+ volatile void *area,
+ size_t areasize
+)
+{
+ POSIX_Interrupt_Handler_control *the_intr;
+ POSIX_Interrupt_Control *the_vector;
+ POSIX_API_Thread_Support_Control *thread_support;
+ proc_ptr old_handler;
+
+ if ( !_ISR_Is_vector_number_valid( intr ) ||
+ !_ISR_Is_valid_user_handler( intr_handler ) )
+ return EINVAL;
+
+ _Thread_Disable_dispatch();
+
+ the_intr = _POSIX_Interrupt_Allocate();
+
+ if ( !the_intr ) {
+ _Thread_Enable_dispatch();
+ return ENOMEM;
+ }
+
+ the_vector = &_POSIX_Interrupt_Information[ intr ];
+
+ the_intr->vector = intr;
+ the_intr->handler = intr_handler;
+ the_intr->user_data_area = area;
+ the_intr->server = _Thread_Executing;
+ the_intr->is_active = TRUE;
+
+ thread_support = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
+ thread_support->interrupts_installed++;
+
+/* XXX should we malloc the semaphore on the fly??? if so we probably need to
+ release it when the thread has released all interrupts and keep
+ a count of how many it has installed. CURRENTLY NO.. ALLOCATED w/TCB
+*/
+
+ /*
+ * This is sufficient to have the handlers invoked in the opposite
+ * order of installation. The loop invoking them can then go from
+ * the front of the list to the end.
+ */
+
+ _Chain_Prepend( &the_vector->Handlers, &the_intr->Object.Node );
+
+ if ( !the_vector->number_installed++ )
+ _ISR_Install_vector(
+ intr,
+ (proc_ptr) _POSIX_Interrupt_Handler,
+ &old_handler
+ );
+
+ _Objects_Open( &_POSIX_Interrupt_Handlers_Information, &the_intr->Object, 0 );
+
+ /*
+ * Normally, an Id would be returned here.
+ */
+
+ _Thread_Enable_dispatch();
+
+ return 0;
+}
+
+/*PAGE
+ *
+ * 22.3.1 Associate a User-Written ISR with an Interrupt, P1003.4b/D8, p. 74
+ */
+
+int intr_release(
+ intr_t intr,
+ int (*intr_handler)( void *area )
+)
+{
+ boolean found;
+ POSIX_Interrupt_Handler_control *the_intr;
+ POSIX_Interrupt_Control *the_vector;
+ POSIX_API_Thread_Support_Control *thread_support;
+ Chain_Node *the_node;
+
+ if ( !_ISR_Is_valid_user_handler( intr_handler ) )
+ return EINVAL;
+
+ _Thread_Disable_dispatch();
+
+ /*
+ * Since interrupt handlers do not have a user visible id, there is
+ * no choice but to search the entire set of active interrupt handlers
+ * to find this one.
+ */
+
+ found = FALSE;
+
+ the_vector = &_POSIX_Interrupt_Information[ intr ];
+
+ the_node = _Chain_Head( &the_vector->Handlers );
+
+ for ( ; !_Chain_Is_tail( &the_vector->Handlers, the_node ) ; ) {
+ the_intr = (POSIX_Interrupt_Handler_control *) the_node;
+
+ if ( the_intr->handler == intr_handler ) {
+ found = TRUE;
+ break;
+ }
+ the_node = the_node->next;
+ }
+
+ if ( !found ) {
+ _Thread_Enable_dispatch();
+ return EINVAL;
+ }
+
+ if ( !_Thread_Is_executing( the_intr->server ) ) {
+ _Thread_Enable_dispatch();
+ return EINVAL; /* XXX should be ENOISR; */
+ }
+
+ /*
+ * OK now we have found the interrupt handler and can do some work.
+ */
+
+ _Chain_Extract( &the_intr->Object.Node );
+
+ the_intr->is_active = FALSE;
+
+ the_vector->number_installed -= 1;
+
+ thread_support = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
+ thread_support->interrupts_installed--;
+
+ /*
+ * It is unnecessary to flush the semaphore since the handler can only
+ * be "removed" by the thread which installed it. Thus it cannot be
+ * blocked on the semaphore or it would not be executing this routine.
+ */
+
+ _Objects_Close( &_POSIX_Interrupt_Handlers_Information, &the_intr->Object );
+
+ _POSIX_Interrupt_Free( the_intr );
+
+ _Thread_Enable_dispatch();
+
+ return 0;
+}
+
+/*PAGE
+ *
+ * 22.3.1 Associate a User-Written ISR with an Interrupt, P1003.4b/D8, p. 74
+ */
+
+int intr_lock(
+ intr_t intr
+)
+{
+ POSIX_Interrupt_Control *the_vector;
+
+ _Thread_Disable_dispatch();
+
+ the_vector = &_POSIX_Interrupt_Information[ intr ];
+
+ the_vector->lock_count++;
+
+ _Thread_Enable_dispatch();
+
+ return 0;
+}
+
+/*PAGE
+ *
+ * 22.3.1 Associate a User-Written ISR with an Interrupt, P1003.4b/D8, p. 74
+ */
+
+int intr_unlock(
+ intr_t intr
+)
+{
+ POSIX_Interrupt_Control *the_vector;
+
+ _Thread_Disable_dispatch();
+
+ the_vector = &_POSIX_Interrupt_Information[ intr ];
+
+ if ( !--the_vector->lock_count ) {
+ while ( --the_vector->deferred_count ) {
+ _POSIX_Interrupt_Handler( intr );
+ }
+ }
+
+ _Thread_Enable_dispatch();
+
+ return 0;
+}
+
+/*
+ * 22.3.2 Await Interrupt Notification, P1003.4b/D8, p. 76
+ */
+
+int intr_timed_wait(
+ int flags,
+ const struct timespec *timeout
+)
+{
+ Watchdog_Interval ticks;
+ POSIX_API_Thread_Support_Control *thread_support;
+
+ ticks = _POSIX_Timespec_to_interval( timeout );
+
+ thread_support = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
+
+ _Thread_Disable_dispatch();
+
+ _CORE_semaphore_Seize(
+ &thread_support->Interrupt_Semaphore,
+ 0, /* XXX does id=0 hurt in this case? */
+ TRUE,
+ ticks
+ );
+ _Thread_Enable_dispatch();
+
+ return _Thread_Executing->Wait.return_code; /* XXX should be POSIX */
+}
+
+/*PAGE
+ *
+ * _POSIX_Interrupt_Handler
+ *
+ */
+
+void _POSIX_Interrupt_Handler(
+ ISR_Vector_number vector
+)
+{
+ POSIX_Interrupt_Handler_control *the_intr;
+ POSIX_Interrupt_Control *the_vector;
+ POSIX_API_Thread_Support_Control *thread_support;
+ Chain_Node *the_node;
+ int status;
+
+ the_vector = &_POSIX_Interrupt_Information[ vector ];
+
+ the_node = _Chain_Head( &the_vector->Handlers );
+
+ for ( ; !_Chain_Is_tail( &the_vector->Handlers, the_node ) ; ) {
+ the_intr = (POSIX_Interrupt_Handler_control *) the_node;
+
+ status = (*the_intr->handler)( (void *) the_intr->user_data_area );
+
+ switch ( status ) {
+ case INTR_HANDLED_NOTIFY:
+ thread_support = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
+
+ _CORE_semaphore_Surrender(
+ &thread_support->Interrupt_Semaphore,
+ 0, /* XXX is id=0 a problem */
+ 0 /* XXX is this a problem (mp support)*/
+ );
+ return;
+
+ case INTR_HANDLED_DO_NOT_NOTIFY:
+ return;
+
+ case INTR_NOT_HANDLED:
+ default: /* this should not happen */
+ break;
+ }
+ the_node = the_node->next;
+ }
+
+ /* XXX
+ *
+ * This is an unhandled interrupt!!!
+ */
+}
diff --git a/cpukit/posix/src/key.c b/cpukit/posix/src/key.c
new file mode 100644
index 0000000000..8723cb67a0
--- /dev/null
+++ b/cpukit/posix/src/key.c
@@ -0,0 +1,46 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <limits.h>
+#include <pthread.h>
+#include <string.h>
+
+#include <rtems/system.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/posix/key.h>
+
+/*
+ * _POSIX_Key_Manager_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this manager.
+ */
+
+void _POSIX_Key_Manager_initialization(
+ uint32_t maximum_keys
+)
+{
+ _Objects_Initialize_information(
+ &_POSIX_Keys_Information, /* object information table */
+ OBJECTS_POSIX_API, /* object API */
+ OBJECTS_POSIX_KEYS, /* object class */
+ maximum_keys, /* maximum objects of this class */
+ sizeof( POSIX_Keys_Control ),
+ /* size of this object's control block */
+ FALSE, /* TRUE if names for this object are strings */
+ 0 /* maximum length of each object's name */
+#if defined(RTEMS_MULTIPROCESSING)
+ ,
+ FALSE, /* TRUE if this is a global object class */
+ NULL /* Proxy extraction support callout */
+#endif
+ );
+}
diff --git a/cpukit/posix/src/keycreate.c b/cpukit/posix/src/keycreate.c
new file mode 100644
index 0000000000..d8ae746992
--- /dev/null
+++ b/cpukit/posix/src/keycreate.c
@@ -0,0 +1,90 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <limits.h>
+#include <pthread.h>
+#include <string.h>
+
+#include <rtems/system.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/posix/key.h>
+
+/*PAGE
+ *
+ * 17.1.1 Thread-Specific Data Key Create, P1003.1c/Draft 10, p. 163
+ */
+
+int pthread_key_create(
+ pthread_key_t *key,
+ void (*destructor)( void * )
+)
+{
+ POSIX_Keys_Control *the_key;
+ void *table;
+ uint32_t the_api;
+ uint32_t bytes_to_allocate;
+
+
+ _Thread_Disable_dispatch();
+
+ the_key = _POSIX_Keys_Allocate();
+
+ if ( !the_key ) {
+ _Thread_Enable_dispatch();
+ return EAGAIN;
+ }
+
+ the_key->destructor = destructor;
+
+ /*
+ * This is a bit more complex than one might initially expect because
+ * APIs are optional. Thus there may be no ITRON tasks to have keys
+ * for. [NOTE: Currently RTEMS Classic API tasks are not always enabled.]
+ */
+
+ for ( the_api = 1;
+ the_api <= OBJECTS_APIS_LAST;
+ the_api++ ) {
+
+ if ( _Objects_Information_table[ the_api ] &&
+ _Objects_Information_table[ the_api ][ 1 ] ) {
+ bytes_to_allocate = sizeof( void * ) *
+ (_Objects_Information_table[ the_api ][ 1 ]->maximum + 1);
+ table = _Workspace_Allocate( bytes_to_allocate );
+ if ( !table ) {
+ for ( --the_api;
+ the_api >= 1;
+ the_api-- )
+ _Workspace_Free( the_key->Values[ the_api ] );
+
+ _POSIX_Keys_Free( the_key );
+ _Thread_Enable_dispatch();
+ return ENOMEM;
+ }
+
+ the_key->Values[ the_api ] = table;
+ memset( table, '\0', bytes_to_allocate );
+ } else {
+ the_key->Values[ the_api ] = NULL;
+ }
+
+
+ }
+
+ the_key->is_active = TRUE;
+
+ _Objects_Open( &_POSIX_Keys_Information, &the_key->Object, 0 );
+
+ *key = the_key->Object.id;
+
+ _Thread_Enable_dispatch();
+
+ return 0;
+}
diff --git a/cpukit/posix/src/keydelete.c b/cpukit/posix/src/keydelete.c
new file mode 100644
index 0000000000..364108046b
--- /dev/null
+++ b/cpukit/posix/src/keydelete.c
@@ -0,0 +1,58 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <limits.h>
+#include <pthread.h>
+#include <string.h>
+
+#include <rtems/system.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/posix/key.h>
+
+/*PAGE
+ *
+ * 17.1.3 Thread-Specific Data Key Deletion, P1003.1c/Draft 10, p. 167
+ */
+
+int pthread_key_delete(
+ pthread_key_t key
+)
+{
+ register POSIX_Keys_Control *the_key;
+ Objects_Locations location;
+ uint32_t the_api;
+
+ the_key = _POSIX_Keys_Get( key, &location );
+ switch ( location ) {
+ case OBJECTS_ERROR:
+ case OBJECTS_REMOTE: /* should never happen */
+ return EINVAL;
+ case OBJECTS_LOCAL:
+ _Objects_Close( &_POSIX_Keys_Information, &the_key->Object );
+
+ the_key->is_active = FALSE;
+
+ for ( the_api = 1;
+ the_api <= OBJECTS_APIS_LAST;
+ the_api++ )
+ if ( the_key->Values[ the_api ] )
+ _Workspace_Free( the_key->Values[ the_api ] );
+
+ /*
+ * NOTE: The destructor is not called and it is the responsibility
+ * of the application to free the memory.
+ */
+
+ _POSIX_Keys_Free( the_key );
+ _Thread_Enable_dispatch();
+ return 0;
+ }
+ return POSIX_BOTTOM_REACHED();
+}
diff --git a/cpukit/posix/src/keygetspecific.c b/cpukit/posix/src/keygetspecific.c
new file mode 100644
index 0000000000..ee6912022c
--- /dev/null
+++ b/cpukit/posix/src/keygetspecific.c
@@ -0,0 +1,48 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <limits.h>
+#include <pthread.h>
+#include <string.h>
+
+#include <rtems/system.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/posix/key.h>
+
+/*PAGE
+ *
+ * 17.1.2 Thread-Specific Data Management, P1003.1c/Draft 10, p. 165
+ */
+
+void *pthread_getspecific(
+ pthread_key_t key
+)
+{
+ register POSIX_Keys_Control *the_key;
+ uint32_t index;
+ uint32_t class;
+ Objects_Locations location;
+ void *key_data;
+
+ the_key = _POSIX_Keys_Get( key, &location );
+ switch ( location ) {
+ case OBJECTS_ERROR:
+ case OBJECTS_REMOTE: /* should never happen */
+ return NULL;
+ case OBJECTS_LOCAL:
+ index = _Objects_Get_index( _Thread_Executing->Object.id );
+ class = _Objects_Get_class( _Thread_Executing->Object.id );
+ key_data = (void *) the_key->Values[ class ][ index ];
+ _Thread_Enable_dispatch();
+ return key_data;
+ }
+ (void) POSIX_BOTTOM_REACHED();
+ return (void *)NULL;
+}
diff --git a/cpukit/posix/src/keyrundestructors.c b/cpukit/posix/src/keyrundestructors.c
new file mode 100644
index 0000000000..f2c3b8e380
--- /dev/null
+++ b/cpukit/posix/src/keyrundestructors.c
@@ -0,0 +1,80 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <limits.h>
+#include <pthread.h>
+#include <string.h>
+
+#include <rtems/system.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/posix/key.h>
+
+/*PAGE
+ *
+ * _POSIX_Keys_Run_destructors
+ *
+ * 17.1.1 Thread-Specific Data Key Create, P1003.1c/Draft 10, p. 163
+ *
+ * NOTE: This is the routine executed when a thread exits to
+ * run through all the keys and do the destructor action.
+ */
+
+void _POSIX_Keys_Run_destructors(
+ Thread_Control *thread
+)
+{
+ uint32_t index;
+ uint32_t pthread_index;
+ uint32_t pthread_class;
+ uint32_t iterations;
+ boolean are_all_null;
+ POSIX_Keys_Control *the_key;
+ void *value;
+
+ pthread_index = _Objects_Get_index( thread->Object.id );
+ pthread_class = _Objects_Get_class( thread->Object.id );
+
+ iterations = 0;
+
+ for ( ; ; ) {
+
+ are_all_null = TRUE;
+
+ for ( index=1 ; index <= _POSIX_Keys_Information.maximum ; index++ ) {
+
+ the_key = (POSIX_Keys_Control *)
+ _POSIX_Keys_Information.local_table[ index ];
+
+ if ( the_key && the_key->is_active && the_key->destructor ) {
+ value = the_key->Values[ pthread_class ][ pthread_index ];
+ if ( value ) {
+ (*the_key->destructor)( value );
+ if ( the_key->Values[ pthread_class ][ pthread_index ] )
+ are_all_null = FALSE;
+ }
+ }
+ }
+
+ if ( are_all_null == TRUE )
+ return;
+
+ iterations++;
+
+ /*
+ * The standard allows one to not do this and thus go into an infinite
+ * loop. It seems rude to unnecessarily lock up a system.
+ *
+ * Reference: 17.1.1.2 P1003.1c/Draft 10, p. 163, line 99.
+ */
+
+ if ( iterations >= PTHREAD_DESTRUCTOR_ITERATIONS )
+ return;
+ }
+}
diff --git a/cpukit/posix/src/keysetspecific.c b/cpukit/posix/src/keysetspecific.c
new file mode 100644
index 0000000000..30f10a06b4
--- /dev/null
+++ b/cpukit/posix/src/keysetspecific.c
@@ -0,0 +1,47 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <limits.h>
+#include <pthread.h>
+#include <string.h>
+
+#include <rtems/system.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/posix/key.h>
+
+/*PAGE
+ *
+ * 17.1.2 Thread-Specific Data Management, P1003.1c/Draft 10, p. 165
+ */
+
+int pthread_setspecific(
+ pthread_key_t key,
+ const void *value
+)
+{
+ register POSIX_Keys_Control *the_key;
+ uint32_t index;
+ uint32_t class;
+ Objects_Locations location;
+
+ the_key = _POSIX_Keys_Get( key, &location );
+ switch ( location ) {
+ case OBJECTS_ERROR:
+ case OBJECTS_REMOTE: /* should never happen */
+ return EINVAL;
+ case OBJECTS_LOCAL:
+ index = _Objects_Get_index( _Thread_Executing->Object.id );
+ class = _Objects_Get_class( _Thread_Executing->Object.id );
+ the_key->Values[ class ][ index ] = (void *) value;
+ _Thread_Enable_dispatch();
+ return 0;
+ }
+ return POSIX_BOTTOM_REACHED();
+}
diff --git a/cpukit/posix/src/kill.c b/cpukit/posix/src/kill.c
new file mode 100644
index 0000000000..b601ee1d01
--- /dev/null
+++ b/cpukit/posix/src/kill.c
@@ -0,0 +1,51 @@
+/*
+ * 3.3.2 Send a Signal to a Process, P1003.1b-1993, p. 68
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/psignal.h>
+
+int kill(
+ pid_t pid,
+ int sig
+)
+{
+ return killinfo( pid, sig, NULL );
+}
+
+/*
+ * _kill_r
+ *
+ * This is the Newlib dependent reentrant version of kill().
+ */
+
+#if defined(RTEMS_NEWLIB)
+
+#include <reent.h>
+
+int _kill_r(
+ struct _reent *ptr,
+ pid_t pid,
+ int sig
+)
+{
+ return kill( pid, sig );
+}
+#endif
diff --git a/cpukit/posix/src/killinfo.c b/cpukit/posix/src/killinfo.c
new file mode 100644
index 0000000000..b275a0b764
--- /dev/null
+++ b/cpukit/posix/src/killinfo.c
@@ -0,0 +1,338 @@
+/*
+ * kill() support routine
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <signal.h>
+#include <errno.h>
+#include <assert.h>
+
+#include <rtems/system.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/psignal.h>
+#include <rtems/seterr.h>
+#include <rtems/score/isr.h>
+
+/*PAGE
+ *
+ * 3.3.2 Send a Signal to a Process, P1003.1b-1993, p. 68
+ *
+ * NOTE: Behavior of kill() depends on _POSIX_SAVED_IDS.
+ */
+
+#define _POSIX_signals_Is_interested( _api, _mask ) \
+ ( ~(_api)->signals_blocked & (_mask) )
+
+int killinfo(
+ pid_t pid,
+ int sig,
+ const union sigval *value
+)
+{
+ sigset_t mask;
+ POSIX_API_Control *api;
+ uint32_t the_api;
+ uint32_t index;
+ uint32_t maximum;
+ Objects_Information *the_info;
+ Objects_Control **object_table;
+ Thread_Control *the_thread;
+ Thread_Control *interested_thread;
+ Priority_Control interested_priority;
+ Chain_Control *the_chain;
+ Chain_Node *the_node;
+ siginfo_t siginfo_struct;
+ siginfo_t *siginfo;
+ POSIX_signals_Siginfo_node *psiginfo;
+
+ /*
+ * Only supported for the "calling process" (i.e. this node).
+ */
+
+ if ( pid != getpid() )
+ rtems_set_errno_and_return_minus_one( ESRCH );
+
+ /*
+ * Validate the signal passed.
+ */
+
+ if ( !sig )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ if ( !is_valid_signo(sig) )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ /*
+ * If the signal is being ignored, then we are out of here.
+ */
+
+ if ( _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN ) {
+ return 0;
+ }
+
+ /*
+ * P1003.1c/Draft 10, p. 33 says that certain signals should always
+ * be directed to the executing thread such as those caused by hardware
+ * faults.
+ */
+
+ switch ( sig ) {
+ case SIGFPE:
+ case SIGILL:
+ case SIGSEGV:
+ return pthread_kill( pthread_self(), sig );
+ default:
+ break;
+ }
+
+ mask = signo_to_mask( sig );
+
+ /*
+ * Build up a siginfo structure
+ */
+
+ siginfo = &siginfo_struct;
+ siginfo->si_signo = sig;
+ siginfo->si_code = SI_USER;
+ if ( !value ) {
+ siginfo->si_value.sival_int = 0;
+ } else {
+ siginfo->si_value = *value;
+ }
+
+ _Thread_Disable_dispatch();
+
+ /*
+ * Is the currently executing thread interested? If so then it will
+ * get it an execute it as soon as the dispatcher executes.
+ */
+
+ the_thread = _Thread_Executing;
+
+ api = the_thread->API_Extensions[ THREAD_API_POSIX ];
+ if ( _POSIX_signals_Is_interested( api, mask ) ) {
+ goto process_it;
+ }
+
+ /*
+ * Is an interested thread waiting for this signal (sigwait())?
+ */
+
+ /* XXX violation of visibility -- need to define thread queue support */
+
+ for( index=0 ;
+ index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ;
+ index++ ) {
+
+ the_chain = &_POSIX_signals_Wait_queue.Queues.Priority[ index ];
+
+ for ( the_node = the_chain->first ;
+ !_Chain_Is_tail( the_chain, the_node ) ;
+ the_node = the_node->next ) {
+
+ the_thread = (Thread_Control *)the_node;
+ api = the_thread->API_Extensions[ THREAD_API_POSIX ];
+
+ if ((the_thread->Wait.option & mask) || (~api->signals_blocked & mask)) {
+ goto process_it;
+ }
+
+ }
+ }
+
+ /*
+ * Is any other thread interested? The highest priority interested
+ * thread is selected. In the event of a tie, then the following
+ * additional criteria is used:
+ *
+ * + ready thread over blocked
+ * + blocked on call interruptible by signal (can return EINTR)
+ * + blocked on call not interruptible by signal
+ *
+ * This looks at every thread in the system regardless of the creating API.
+ *
+ * NOTES:
+ *
+ * + rtems internal threads do not receive signals.
+ */
+
+ interested_thread = NULL;
+ interested_priority = PRIORITY_MAXIMUM + 1;
+
+ for ( the_api = 2;
+ the_api <= OBJECTS_APIS_LAST;
+ the_api++ ) {
+
+ if ( the_api == OBJECTS_INTERNAL_THREADS )
+ continue;
+
+ if ( !_Objects_Information_table[ the_api ] ) /* API not installed */
+ continue;
+
+ the_info = _Objects_Information_table[ the_api ][ 1 ];
+
+ if ( !the_info ) /* manager not installed */
+ continue;
+
+ maximum = the_info->maximum;
+ object_table = the_info->local_table;
+
+ assert( object_table ); /* always at least 1 entry */
+
+ for ( index = 1 ; index <= maximum ; index++ ) {
+ the_thread = (Thread_Control *) object_table[ index ];
+
+ if ( !the_thread )
+ continue;
+
+ /*
+ * If this thread is of lower priority than the interested thread,
+ * go on to the next thread.
+ */
+
+ if ( the_thread->current_priority > interested_priority )
+ continue;
+
+ /*
+ * If this thread is not interested, then go on to the next thread.
+ */
+
+ api = the_thread->API_Extensions[ THREAD_API_POSIX ];
+
+ if ( !api || !_POSIX_signals_Is_interested( api, mask ) )
+ continue;
+
+ /*
+ * Now we know the thread under connsideration is interested.
+ * If the thread under consideration is of higher priority, then
+ * it becomes the interested thread.
+ */
+
+ if ( the_thread->current_priority < interested_priority ) {
+ interested_thread = the_thread;
+ interested_priority = the_thread->current_priority;
+ continue;
+ }
+
+ /*
+ * Now the thread and the interested thread have the same priority.
+ * If the interested thread is ready, then we don't need to send it
+ * to a blocked thread.
+ */
+
+ if ( _States_Is_ready( interested_thread->current_state ) )
+ continue;
+
+ /*
+ * Now the interested thread is blocked.
+ * If the thread we are considering is not, the it becomes the
+ * interested thread.
+ */
+
+ if ( _States_Is_ready( the_thread->current_state ) ) {
+ interested_thread = the_thread;
+ interested_priority = the_thread->current_priority;
+ continue;
+ }
+
+ /*
+ * Now we know both threads are blocked.
+ * If the interested thread is interruptible, then just use it.
+ */
+
+ /* XXX need a new states macro */
+ if ( interested_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL )
+ continue;
+
+ /*
+ * Now both threads are blocked and the interested thread is not
+ * interruptible.
+ * If the thread under consideration is interruptible by a signal,
+ * then it becomes the interested thread.
+ */
+
+ /* XXX need a new states macro */
+ if ( the_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL ) {
+ interested_thread = the_thread;
+ interested_priority = the_thread->current_priority;
+ }
+ }
+ }
+
+ if ( interested_thread ) {
+ the_thread = interested_thread;
+ goto process_it;
+ }
+
+ /*
+ * OK so no threads were interested right now. It will be left on the
+ * global pending until a thread receives it. The global set of threads
+ * can change interest in this signal in one of the following ways:
+ *
+ * + a thread is created with the signal unblocked,
+ * + pthread_sigmask() unblocks the signal,
+ * + sigprocmask() unblocks the signal, OR
+ * + sigaction() which changes the handler to SIG_IGN.
+ */
+
+ the_thread = NULL;
+ goto post_process_signal;
+
+ /*
+ * We found a thread which was interested, so now we mark that this
+ * thread needs to do the post context switch extension so it can
+ * evaluate the signals pending.
+ */
+
+process_it:
+
+ the_thread->do_post_task_switch_extension = TRUE;
+
+ /*
+ * Returns TRUE if the signal was synchronously given to a thread
+ * blocked waiting for the signal.
+ */
+
+ if ( _POSIX_signals_Unblock_thread( the_thread, sig, siginfo ) ) {
+ _Thread_Enable_dispatch();
+ return 0;
+ }
+
+post_process_signal:
+
+ /*
+ * We may have woken up a thread but we definitely need to post the
+ * signal to the process wide information set.
+ */
+
+ _POSIX_signals_Set_process_signals( mask );
+
+ if ( _POSIX_signals_Vectors[ sig ].sa_flags == SA_SIGINFO ) {
+
+ psiginfo = (POSIX_signals_Siginfo_node *)
+ _Chain_Get( &_POSIX_signals_Inactive_siginfo );
+ if ( !psiginfo ) {
+ rtems_set_errno_and_return_minus_one( EAGAIN );
+ }
+
+ psiginfo->Info = *siginfo;
+
+ _Chain_Append( &_POSIX_signals_Siginfo[ sig ], &psiginfo->Node );
+ }
+
+ _Thread_Enable_dispatch();
+ return 0;
+}
diff --git a/cpukit/posix/src/mprotect.c b/cpukit/posix/src/mprotect.c
new file mode 100644
index 0000000000..60740615b5
--- /dev/null
+++ b/cpukit/posix/src/mprotect.c
@@ -0,0 +1,23 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <unistd.h>
+
+/*PAGE
+ *
+ * 12.2.3 Change Memory Protection, P1003.1b-1996, p. 277.
+ *
+ * This is not a functional version but the SPARC backend for at least
+ * gcc 2.8.1 plus gnat 3.13p and gcc 3.0.1 require it to be there and
+ * return 0.
+ */
+
+int mprotect(const void *addr, size_t len, int prot)
+{
+ return 0;
+}
diff --git a/cpukit/posix/src/mqueue.c b/cpukit/posix/src/mqueue.c
new file mode 100644
index 0000000000..7773626c76
--- /dev/null
+++ b/cpukit/posix/src/mqueue.c
@@ -0,0 +1,82 @@
+/*
+ * NOTE: The structure of the routines is identical to that of POSIX
+ * Message_queues to leave the option of having unnamed message
+ * queues at a future date. They are currently not part of the
+ * POSIX standard but unnamed message_queues are. This is also
+ * the reason for the apparently unnecessary tracking of
+ * the process_shared attribute. [In addition to the fact that
+ * it would be trivial to add pshared to the mq_attr structure
+ * and have process private message queues.]
+ *
+ * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
+ * time.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include <pthread.h>
+#include <limits.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <mqueue.h>
+#include <limits.h>
+
+#include <rtems/system.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/seterr.h>
+#include <rtems/posix/mqueue.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * _POSIX_Message_queue_Manager_initialization
+ *
+ * This routine initializes all message_queue manager related data structures.
+ *
+ * Input parameters:
+ * maximum_message_queues - maximum configured message_queues
+ *
+ * Output parameters: NONE
+ */
+
+void _POSIX_Message_queue_Manager_initialization(
+ uint32_t maximum_message_queues
+)
+{
+ _Objects_Initialize_information(
+ &_POSIX_Message_queue_Information, /* object information table */
+ OBJECTS_POSIX_API, /* object API */
+ OBJECTS_POSIX_MESSAGE_QUEUES, /* object class */
+ maximum_message_queues, /* maximum objects of this class */
+ sizeof( POSIX_Message_queue_Control ),
+ /* size of this object's control block */
+ TRUE, /* TRUE if names for this object are strings */
+ _POSIX_PATH_MAX /* maximum length of each object's name */
+#if defined(RTEMS_MULTIPROCESSING)
+ ,
+ FALSE, /* TRUE if this is a global object class */
+ NULL /* Proxy extraction support callout */
+#endif
+ );
+ _Objects_Initialize_information(
+ &_POSIX_Message_queue_Information_fds,
+ OBJECTS_POSIX_API,
+ OBJECTS_POSIX_MESSAGE_QUEUE_FDS,
+ maximum_message_queues,
+ sizeof( POSIX_Message_queue_Control_fd ),
+ /* size of this object's control block */
+ TRUE, /* TRUE if names for this object are strings */
+ NAME_MAX /* maximum length of each object's name */
+#if defined(RTEMS_MULTIPROCESSING)
+ ,
+ FALSE, /* TRUE if this is a global object class */
+ NULL /* Proxy extraction support callout */
+#endif
+ );
+}
diff --git a/cpukit/posix/src/mqueueclose.c b/cpukit/posix/src/mqueueclose.c
new file mode 100644
index 0000000000..9254bbf25b
--- /dev/null
+++ b/cpukit/posix/src/mqueueclose.c
@@ -0,0 +1,79 @@
+/*
+ * NOTE: The structure of the routines is identical to that of POSIX
+ * Message_queues to leave the option of having unnamed message
+ * queues at a future date. They are currently not part of the
+ * POSIX standard but unnamed message_queues are. This is also
+ * the reason for the apparently unnecessary tracking of
+ * the process_shared attribute. [In addition to the fact that
+ * it would be trivial to add pshared to the mq_attr structure
+ * and have process private message queues.]
+ *
+ * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
+ * time.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include <pthread.h>
+#include <limits.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <mqueue.h>
+
+#include <rtems/system.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/seterr.h>
+#include <rtems/posix/mqueue.h>
+#include <rtems/posix/time.h>
+
+/*
+ *
+ * 15.2.2 Close a Message Queue, P1003.1b-1993, p. 275
+ */
+
+int mq_close(
+ mqd_t mqdes
+)
+{
+ POSIX_Message_queue_Control *the_mq;
+ POSIX_Message_queue_Control_fd *the_mq_fd;
+ Objects_Locations location;
+
+ the_mq_fd = _POSIX_Message_queue_Get_fd( mqdes, &location );
+ switch ( location ) {
+ case OBJECTS_ERROR:
+ rtems_set_errno_and_return_minus_one( EBADF );
+ case OBJECTS_REMOTE:
+ _Thread_Dispatch();
+ return POSIX_MP_NOT_IMPLEMENTED();
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ case OBJECTS_LOCAL:
+ /*
+ * First update the actual message queue to reflect this descriptor
+ * being disassociated. This may result in the queue being really
+ * deleted.
+ */
+
+ the_mq = the_mq_fd->Queue;
+ the_mq->open_count -= 1;
+ _POSIX_Message_queue_Delete( the_mq );
+
+ /*
+ * Now close this file descriptor.
+ */
+
+ _Objects_Close(
+ &_POSIX_Message_queue_Information_fds, &the_mq_fd->Object );
+ _POSIX_Message_queue_Free_fd( the_mq_fd );
+
+ _Thread_Enable_dispatch();
+ return 0;
+ }
+ return POSIX_BOTTOM_REACHED();
+}
diff --git a/cpukit/posix/src/mqueuecreatesupp.c b/cpukit/posix/src/mqueuecreatesupp.c
new file mode 100644
index 0000000000..1259701124
--- /dev/null
+++ b/cpukit/posix/src/mqueuecreatesupp.c
@@ -0,0 +1,173 @@
+/*
+ * NOTE: The structure of the routines is identical to that of POSIX
+ * Message_queues to leave the option of having unnamed message
+ * queues at a future date. They are currently not part of the
+ * POSIX standard but unnamed message_queues are. This is also
+ * the reason for the apparently unnecessary tracking of
+ * the process_shared attribute. [In addition to the fact that
+ * it would be trivial to add pshared to the mq_attr structure
+ * and have process private message queues.]
+ *
+ * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
+ * time.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+#include <pthread.h>
+#include <limits.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <mqueue.h>
+
+#include <rtems/system.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/seterr.h>
+#include <rtems/posix/mqueue.h>
+#include <rtems/posix/time.h>
+
+/* pure ANSI mode does not have this prototype */
+size_t strnlen(const char *, size_t);
+
+/*PAGE
+ *
+ * _POSIX_Message_queue_Create_support
+ *
+ * This routine does the actual creation and initialization of
+ * a poxix message queue.
+ */
+
+int _POSIX_Message_queue_Create_support(
+ const char *name_arg,
+ int pshared,
+ struct mq_attr *attr_ptr,
+ POSIX_Message_queue_Control **message_queue
+)
+{
+ POSIX_Message_queue_Control *the_mq;
+ CORE_message_queue_Attributes *the_mq_attr;
+ struct mq_attr attr;
+ char *name;
+ size_t n;
+
+ n = strnlen( name_arg, NAME_MAX );
+ if ( n > NAME_MAX )
+ return ENAMETOOLONG;
+
+ _Thread_Disable_dispatch();
+
+ /*
+ * There is no real basis for the default values. They will work
+ * but were not compared against any existing implementation for
+ * compatibility. See README.mqueue for an example program we
+ * think will print out the defaults. Report anything you find with it.
+ */
+
+ if ( attr_ptr == NULL ) {
+ attr.mq_maxmsg = 10;
+ attr.mq_msgsize = 16;
+ } else {
+ if ( attr_ptr->mq_maxmsg <= 0 ){
+ _Thread_Enable_dispatch();
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ }
+
+ if ( attr_ptr->mq_msgsize <= 0 ){
+ _Thread_Enable_dispatch();
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ }
+
+ attr = *attr_ptr;
+ }
+
+#if 0 && defined(RTEMS_MULTIPROCESSING)
+ if ( pshared == PTHREAD_PROCESS_SHARED &&
+ !( _Objects_MP_Allocate_and_open( &_POSIX_Message_queue_Information, 0,
+ the_mq->Object.id, FALSE ) ) ) {
+ _POSIX_Message_queue_Free( the_mq );
+ _Thread_Enable_dispatch();
+ rtems_set_errno_and_return_minus_one( ENFILE );
+ }
+#endif
+
+ the_mq = _POSIX_Message_queue_Allocate();
+ if ( !the_mq ) {
+ _Thread_Enable_dispatch();
+ rtems_set_errno_and_return_minus_one( ENFILE );
+ }
+
+ the_mq->process_shared = pshared;
+ the_mq->named = TRUE;
+ the_mq->open_count = 1;
+ the_mq->linked = TRUE;
+
+ /*
+ * Make a copy of the user's string for name just in case it was
+ * dynamically constructed.
+ */
+
+ name = _Workspace_Allocate(n);
+ if (!name) {
+ _POSIX_Message_queue_Free( the_mq );
+ _Thread_Enable_dispatch();
+ rtems_set_errno_and_return_minus_one( ENOMEM );
+ }
+ strcpy( name, name_arg );
+
+ /* XXX
+ *
+ * Note that thread blocking discipline should be based on the
+ * current scheduling policy.
+ */
+
+ the_mq_attr = &the_mq->Message_queue.Attributes;
+ the_mq_attr->discipline = CORE_MESSAGE_QUEUE_DISCIPLINES_FIFO;
+
+ if ( ! _CORE_message_queue_Initialize(
+ &the_mq->Message_queue,
+ the_mq_attr,
+ attr.mq_maxmsg,
+ attr.mq_msgsize
+ ) ) {
+
+#if 0 && defined(RTEMS_MULTIPROCESSING)
+ if ( pshared == PTHREAD_PROCESS_SHARED )
+ _Objects_MP_Close( &_POSIX_Message_queue_Information, the_mq->Object.id );
+#endif
+
+ _POSIX_Message_queue_Free( the_mq );
+ _Workspace_Free(name);
+ _Thread_Enable_dispatch();
+ rtems_set_errno_and_return_minus_one( ENOSPC );
+ }
+
+ _Objects_Open(
+ &_POSIX_Message_queue_Information,
+ &the_mq->Object,
+ (char *) name
+ );
+
+ *message_queue = the_mq;
+
+#if 0 && defined(RTEMS_MULTIPROCESSING)
+ if ( pshared == PTHREAD_PROCESS_SHARED )
+ _POSIX_Message_queue_MP_Send_process_packet(
+ POSIX_MESSAGE_QUEUE_MP_ANNOUNCE_CREATE,
+ the_mq->Object.id,
+ (char *) name,
+ 0 /* Not used */
+ );
+#endif
+
+ _Thread_Enable_dispatch();
+ return 0;
+}
diff --git a/cpukit/posix/src/mqueuedeletesupp.c b/cpukit/posix/src/mqueuedeletesupp.c
new file mode 100644
index 0000000000..bf2e52fd64
--- /dev/null
+++ b/cpukit/posix/src/mqueuedeletesupp.c
@@ -0,0 +1,78 @@
+/*
+ * NOTE: The structure of the routines is identical to that of POSIX
+ * Message_queues to leave the option of having unnamed message
+ * queues at a future date. They are currently not part of the
+ * POSIX standard but unnamed message_queues are. This is also
+ * the reason for the apparently unnecessary tracking of
+ * the process_shared attribute. [In addition to the fact that
+ * it would be trivial to add pshared to the mq_attr structure
+ * and have process private message queues.]
+ *
+ * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
+ * time.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include <pthread.h>
+#include <limits.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <mqueue.h>
+
+#include <rtems/system.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/seterr.h>
+#include <rtems/posix/mqueue.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * _POSIX_Message_queue_Delete
+ */
+
+void _POSIX_Message_queue_Delete(
+ POSIX_Message_queue_Control *the_mq
+)
+{
+ if ( !the_mq->linked && !the_mq->open_count ) {
+ /* the name memory may have been freed by unlink. */
+ if ( the_mq->Object.name )
+ _Workspace_Free( the_mq->Object.name );
+
+ _Objects_Close( &_POSIX_Message_queue_Information, &the_mq->Object );
+
+ _CORE_message_queue_Close(
+ &the_mq->Message_queue,
+ NULL, /* no MP support */
+ CORE_MESSAGE_QUEUE_STATUS_WAS_DELETED
+ );
+
+ _POSIX_Message_queue_Free( the_mq );
+
+#if 0 && defined(RTEMS_MULTIPROCESSING)
+ if ( the_mq->process_shared == PTHREAD_PROCESS_SHARED ) {
+
+ _Objects_MP_Close(
+ &_POSIX_Message_queue_Information,
+ the_mq->Object.id
+ );
+
+ _POSIX_Message_queue_MP_Send_process_packet(
+ POSIX_MESSAGE_QUEUE_MP_ANNOUNCE_DELETE,
+ the_mq->Object.id,
+ 0, /* Not used */
+ 0 /* Not used */
+ );
+ }
+#endif
+
+ }
+}
diff --git a/cpukit/posix/src/mqueuegetattr.c b/cpukit/posix/src/mqueuegetattr.c
new file mode 100644
index 0000000000..d5cb7ababb
--- /dev/null
+++ b/cpukit/posix/src/mqueuegetattr.c
@@ -0,0 +1,79 @@
+/*
+ * NOTE: The structure of the routines is identical to that of POSIX
+ * Message_queues to leave the option of having unnamed message
+ * queues at a future date. They are currently not part of the
+ * POSIX standard but unnamed message_queues are. This is also
+ * the reason for the apparently unnecessary tracking of
+ * the process_shared attribute. [In addition to the fact that
+ * it would be trivial to add pshared to the mq_attr structure
+ * and have process private message queues.]
+ *
+ * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
+ * time.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include <pthread.h>
+#include <limits.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <mqueue.h>
+
+#include <rtems/system.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/seterr.h>
+#include <rtems/posix/mqueue.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * 15.2.8 Get Message Queue Attributes, P1003.1b-1993, p. 283
+ */
+
+int mq_getattr(
+ mqd_t mqdes,
+ struct mq_attr *mqstat
+)
+{
+ POSIX_Message_queue_Control *the_mq;
+ POSIX_Message_queue_Control_fd *the_mq_fd;
+ Objects_Locations location;
+ CORE_message_queue_Attributes *the_mq_attr;
+
+ if ( !mqstat )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ the_mq_fd = _POSIX_Message_queue_Get_fd( mqdes, &location );
+ switch ( location ) {
+ case OBJECTS_ERROR:
+ rtems_set_errno_and_return_minus_one( EBADF );
+ case OBJECTS_REMOTE:
+ _Thread_Dispatch();
+ return POSIX_MP_NOT_IMPLEMENTED();
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ case OBJECTS_LOCAL:
+ the_mq = the_mq_fd->Queue;
+
+ /*
+ * Return the old values.
+ */
+
+ the_mq_attr = &the_mq->Message_queue.Attributes;
+
+ mqstat->mq_flags = the_mq_fd->oflag;
+ mqstat->mq_msgsize = the_mq->Message_queue.maximum_message_size;
+ mqstat->mq_maxmsg = the_mq->Message_queue.maximum_pending_messages;
+ mqstat->mq_curmsgs = the_mq->Message_queue.number_of_pending_messages;
+
+ _Thread_Enable_dispatch();
+ return 0;
+ }
+ return POSIX_BOTTOM_REACHED();
+}
diff --git a/cpukit/posix/src/mqueuenametoid.c b/cpukit/posix/src/mqueuenametoid.c
new file mode 100644
index 0000000000..91dd9357fd
--- /dev/null
+++ b/cpukit/posix/src/mqueuenametoid.c
@@ -0,0 +1,66 @@
+/*
+ * NOTE: The structure of the routines is identical to that of POSIX
+ * Message_queues to leave the option of having unnamed message
+ * queues at a future date. They are currently not part of the
+ * POSIX standard but unnamed message_queues are. This is also
+ * the reason for the apparently unnecessary tracking of
+ * the process_shared attribute. [In addition to the fact that
+ * it would be trivial to add pshared to the mq_attr structure
+ * and have process private message queues.]
+ *
+ * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
+ * time.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include <pthread.h>
+#include <limits.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <mqueue.h>
+
+#include <rtems/system.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/seterr.h>
+#include <rtems/posix/mqueue.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * _POSIX_Message_queue_Name_to_id
+ *
+ * Look up the specified name and attempt to locate the id
+ * for the associated message queue.
+ */
+
+int _POSIX_Message_queue_Name_to_id(
+ const char *name,
+ Objects_Id *id
+)
+{
+ Objects_Name_or_id_lookup_errors status;
+
+ if ( !name )
+ return EINVAL;
+
+ if ( !name[0] )
+ return EINVAL;
+
+ if( strlen(name) > PATH_MAX )
+ return ENAMETOOLONG;
+
+ status = _Objects_Name_to_id(
+ &_POSIX_Message_queue_Information, (char *)name, 0, id );
+
+ if ( status == OBJECTS_NAME_OR_ID_LOOKUP_SUCCESSFUL )
+ return 0;
+
+ return ENOENT;
+}
diff --git a/cpukit/posix/src/mqueuenotify.c b/cpukit/posix/src/mqueuenotify.c
new file mode 100644
index 0000000000..5733346e16
--- /dev/null
+++ b/cpukit/posix/src/mqueuenotify.c
@@ -0,0 +1,107 @@
+/*
+ * NOTE: The structure of the routines is identical to that of POSIX
+ * Message_queues to leave the option of having unnamed message
+ * queues at a future date. They are currently not part of the
+ * POSIX standard but unnamed message_queues are. This is also
+ * the reason for the apparently unnecessary tracking of
+ * the process_shared attribute. [In addition to the fact that
+ * it would be trivial to add pshared to the mq_attr structure
+ * and have process private message queues.]
+ *
+ * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
+ * time.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include <pthread.h>
+#include <limits.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <mqueue.h>
+#include <sys/types.h>
+#include <signal.h>
+
+#include <rtems/system.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/seterr.h>
+#include <rtems/posix/mqueue.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * _POSIX_Message_queue_Notify_handler
+ *
+ */
+
+void _POSIX_Message_queue_Notify_handler(
+ void *user_data
+)
+{
+ POSIX_Message_queue_Control *the_mq;
+
+ the_mq = user_data;
+
+ kill( getpid(), the_mq->notification.sigev_signo );
+
+ _CORE_message_queue_Set_notify( &the_mq->Message_queue, NULL, NULL );
+}
+
+/*PAGE
+ *
+ * 15.2.6 Notify Process that a Message is Available on a Queue,
+ * P1003.1b-1993, p. 280
+ */
+
+int mq_notify(
+ mqd_t mqdes,
+ const struct sigevent *notification
+)
+{
+ POSIX_Message_queue_Control *the_mq;
+ POSIX_Message_queue_Control_fd *the_mq_fd;
+ Objects_Locations location;
+
+ the_mq_fd = _POSIX_Message_queue_Get_fd( mqdes, &location );
+ switch ( location ) {
+ case OBJECTS_ERROR:
+ rtems_set_errno_and_return_minus_one( EBADF );
+ case OBJECTS_REMOTE:
+ _Thread_Dispatch();
+ return POSIX_MP_NOT_IMPLEMENTED();
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ case OBJECTS_LOCAL:
+ the_mq = the_mq_fd->Queue;
+
+ if ( notification ) {
+ if ( _CORE_message_queue_Is_notify_enabled( &the_mq->Message_queue ) ) {
+ _Thread_Enable_dispatch();
+ rtems_set_errno_and_return_minus_one( EBUSY );
+ }
+
+ _CORE_message_queue_Set_notify( &the_mq->Message_queue, NULL, NULL );
+
+ the_mq->notification = *notification;
+
+ _CORE_message_queue_Set_notify(
+ &the_mq->Message_queue,
+ _POSIX_Message_queue_Notify_handler,
+ the_mq
+ );
+ } else {
+
+ _CORE_message_queue_Set_notify( &the_mq->Message_queue, NULL, NULL );
+
+ }
+
+ _Thread_Enable_dispatch();
+ return 0;
+ }
+ return POSIX_BOTTOM_REACHED();
+}
diff --git a/cpukit/posix/src/mqueueopen.c b/cpukit/posix/src/mqueueopen.c
new file mode 100644
index 0000000000..8195e9d2af
--- /dev/null
+++ b/cpukit/posix/src/mqueueopen.c
@@ -0,0 +1,158 @@
+/*
+ * NOTE: The structure of the routines is identical to that of POSIX
+ * Message_queues to leave the option of having unnamed message
+ * queues at a future date. They are currently not part of the
+ * POSIX standard but unnamed message_queues are. This is also
+ * the reason for the apparently unnecessary tracking of
+ * the process_shared attribute. [In addition to the fact that
+ * it would be trivial to add pshared to the mq_attr structure
+ * and have process private message queues.]
+ *
+ * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
+ * time.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include <pthread.h>
+#include <limits.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <mqueue.h>
+
+#include <rtems/system.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/seterr.h>
+#include <rtems/posix/mqueue.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * 15.2.2 Open a Message Queue, P1003.1b-1993, p. 272
+ */
+
+mqd_t mq_open(
+ const char *name,
+ int oflag,
+ ...
+ /* mode_t mode, */
+ /* struct mq_attr attr */
+)
+{
+ va_list arg;
+ mode_t mode;
+ struct mq_attr *attr = NULL;
+ int status;
+ Objects_Id the_mq_id;
+ POSIX_Message_queue_Control *the_mq;
+ POSIX_Message_queue_Control_fd *the_mq_fd;
+ Objects_Locations location;
+
+ _Thread_Disable_dispatch();
+
+ if ( oflag & O_CREAT ) {
+ va_start(arg, oflag);
+ mode = (mode_t) va_arg( arg, unsigned int );
+ attr = (struct mq_attr *) va_arg( arg, struct mq_attr * );
+ va_end(arg);
+ }
+
+ the_mq_fd = _POSIX_Message_queue_Allocate_fd();
+ if ( !the_mq_fd ) {
+ _Thread_Enable_dispatch();
+ rtems_set_errno_and_return_minus_one( ENFILE );
+ }
+ the_mq_fd->oflag = oflag;
+
+ status = _POSIX_Message_queue_Name_to_id( name, &the_mq_id );
+
+ /*
+ * If the name to id translation worked, then the message queue exists
+ * and we can just return a pointer to the id. Otherwise we may
+ * need to check to see if this is a "message queue does not exist"
+ * or some other miscellaneous error on the name.
+ */
+
+ if ( status ) {
+
+ /*
+ * Unless provided a valid name that did not already exist
+ * and we are willing to create then it is an error.
+ */
+
+ if ( !( status == ENOENT && (oflag & O_CREAT) ) ) {
+ _POSIX_Message_queue_Free_fd( the_mq_fd );
+ _Thread_Enable_dispatch();
+ rtems_set_errno_and_return_minus_one_cast( status, mqd_t );
+ }
+
+ } else { /* name -> ID translation succeeded */
+
+ /*
+ * Check for existence with creation.
+ */
+
+ if ( (oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL) ) {
+ _POSIX_Message_queue_Free_fd( the_mq_fd );
+ _Thread_Enable_dispatch();
+ rtems_set_errno_and_return_minus_one_cast( EEXIST, mqd_t );
+ }
+
+ /*
+ * In this case we need to do an ID->pointer conversion to
+ * check the mode.
+ */
+
+ the_mq = _POSIX_Message_queue_Get( the_mq_id, &location );
+ the_mq->open_count += 1;
+ the_mq_fd->Queue = the_mq;
+ _Objects_Open(
+ &_POSIX_Message_queue_Information_fds,
+ &the_mq_fd->Object,
+ NULL
+ );
+ _Thread_Enable_dispatch();
+ _Thread_Enable_dispatch();
+ return (mqd_t)the_mq_fd->Object.id;
+
+ }
+
+ /*
+ * At this point, the message queue does not exist and everything has been
+ * checked. We should go ahead and create a message queue.
+ */
+
+ status = _POSIX_Message_queue_Create_support(
+ name,
+ TRUE, /* shared across processes */
+ attr,
+ &the_mq
+ );
+
+ /*
+ * errno was set by Create_support, so don't set it again.
+ */
+
+ if ( status == -1 ) {
+ _Thread_Enable_dispatch();
+ _POSIX_Message_queue_Free_fd( the_mq_fd );
+ return (mqd_t) -1;
+ }
+
+ the_mq_fd->Queue = the_mq;
+ _Objects_Open(
+ &_POSIX_Message_queue_Information_fds,
+ &the_mq_fd->Object,
+ NULL
+ );
+
+ _Thread_Enable_dispatch();
+
+ return (mqd_t) the_mq_fd->Object.id;
+}
diff --git a/cpukit/posix/src/mqueuereceive.c b/cpukit/posix/src/mqueuereceive.c
new file mode 100644
index 0000000000..e87d5fa8e9
--- /dev/null
+++ b/cpukit/posix/src/mqueuereceive.c
@@ -0,0 +1,56 @@
+/*
+ * NOTE: The structure of the routines is identical to that of POSIX
+ * Message_queues to leave the option of having unnamed message
+ * queues at a future date. They are currently not part of the
+ * POSIX standard but unnamed message_queues are. This is also
+ * the reason for the apparently unnecessary tracking of
+ * the process_shared attribute. [In addition to the fact that
+ * it would be trivial to add pshared to the mq_attr structure
+ * and have process private message queues.]
+ *
+ * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
+ * time.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include <pthread.h>
+#include <limits.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <mqueue.h>
+
+#include <rtems/system.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/seterr.h>
+#include <rtems/posix/mqueue.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * 15.2.5 Receive a Message From a Message Queue, P1003.1b-1993, p. 279
+ *
+ * NOTE: P1003.4b/D8, p. 45 adds mq_timedreceive().
+ */
+
+ssize_t mq_receive(
+ mqd_t mqdes,
+ char *msg_ptr,
+ size_t msg_len,
+ unsigned int *msg_prio
+)
+{
+ return _POSIX_Message_queue_Receive_support(
+ mqdes,
+ msg_ptr,
+ msg_len,
+ msg_prio,
+ THREAD_QUEUE_WAIT_FOREVER
+ );
+}
diff --git a/cpukit/posix/src/mqueuerecvsupp.c b/cpukit/posix/src/mqueuerecvsupp.c
new file mode 100644
index 0000000000..6c2ca9e605
--- /dev/null
+++ b/cpukit/posix/src/mqueuerecvsupp.c
@@ -0,0 +1,107 @@
+/*
+ * NOTE: The structure of the routines is identical to that of POSIX
+ * Message_queues to leave the option of having unnamed message
+ * queues at a future date. They are currently not part of the
+ * POSIX standard but unnamed message_queues are. This is also
+ * the reason for the apparently unnecessary tracking of
+ * the process_shared attribute. [In addition to the fact that
+ * it would be trivial to add pshared to the mq_attr structure
+ * and have process private message queues.]
+ *
+ * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
+ * time.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include <pthread.h>
+#include <limits.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <mqueue.h>
+
+#include <rtems/system.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/seterr.h>
+#include <rtems/posix/mqueue.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * _POSIX_Message_queue_Receive_support
+ *
+ * NOTE: XXX Document how size, priority, length, and the buffer go
+ * through the layers.
+ */
+
+ssize_t _POSIX_Message_queue_Receive_support(
+ mqd_t mqdes,
+ char *msg_ptr,
+ size_t msg_len,
+ unsigned int *msg_prio,
+ Watchdog_Interval timeout
+)
+{
+ POSIX_Message_queue_Control *the_mq;
+ POSIX_Message_queue_Control_fd *the_mq_fd;
+ Objects_Locations location;
+ uint32_t length_out;
+
+ the_mq_fd = _POSIX_Message_queue_Get_fd( mqdes, &location );
+ switch ( location ) {
+ case OBJECTS_ERROR:
+ rtems_set_errno_and_return_minus_one( EBADF );
+ case OBJECTS_REMOTE:
+ _Thread_Dispatch();
+ return POSIX_MP_NOT_IMPLEMENTED();
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ case OBJECTS_LOCAL:
+ if ( (the_mq_fd->oflag & O_ACCMODE) == O_WRONLY ) {
+ _Thread_Enable_dispatch();
+ rtems_set_errno_and_return_minus_one( EBADF );
+ }
+
+ the_mq = the_mq_fd->Queue;
+
+ if ( msg_len < the_mq->Message_queue.maximum_message_size ) {
+ _Thread_Enable_dispatch();
+ rtems_set_errno_and_return_minus_one( EMSGSIZE );
+ }
+
+ /*
+ * Now if something goes wrong, we return a "length" of -1
+ * to indicate an error.
+ */
+
+ length_out = -1;
+
+ _CORE_message_queue_Seize(
+ &the_mq->Message_queue,
+ mqdes,
+ msg_ptr,
+ &length_out,
+ (the_mq_fd->oflag & O_NONBLOCK) ? FALSE : TRUE,
+ timeout
+ );
+
+ _Thread_Enable_dispatch();
+ *msg_prio =
+ _POSIX_Message_queue_Priority_from_core(_Thread_Executing->Wait.count);
+
+ if ( !_Thread_Executing->Wait.return_code )
+ return length_out;
+
+ rtems_set_errno_and_return_minus_one(
+ _POSIX_Message_queue_Translate_core_message_queue_return_code(
+ _Thread_Executing->Wait.return_code
+ )
+ );
+ }
+ return POSIX_BOTTOM_REACHED();
+}
diff --git a/cpukit/posix/src/mqueuesend.c b/cpukit/posix/src/mqueuesend.c
new file mode 100644
index 0000000000..484fe72183
--- /dev/null
+++ b/cpukit/posix/src/mqueuesend.c
@@ -0,0 +1,56 @@
+/*
+ * NOTE: The structure of the routines is identical to that of POSIX
+ * Message_queues to leave the option of having unnamed message
+ * queues at a future date. They are currently not part of the
+ * POSIX standard but unnamed message_queues are. This is also
+ * the reason for the apparently unnecessary tracking of
+ * the process_shared attribute. [In addition to the fact that
+ * it would be trivial to add pshared to the mq_attr structure
+ * and have process private message queues.]
+ *
+ * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
+ * time.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include <pthread.h>
+#include <limits.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <mqueue.h>
+
+#include <rtems/system.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/seterr.h>
+#include <rtems/posix/mqueue.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * 15.2.4 Send a Message to a Message Queue, P1003.1b-1993, p. 277
+ *
+ * NOTE: P1003.4b/D8, p. 45 adds mq_timedsend().
+ */
+
+int mq_send(
+ mqd_t mqdes,
+ const char *msg_ptr,
+ size_t msg_len,
+ unsigned int msg_prio
+)
+{
+ return _POSIX_Message_queue_Send_support(
+ mqdes,
+ msg_ptr,
+ msg_len,
+ msg_prio,
+ THREAD_QUEUE_WAIT_FOREVER
+ );
+}
diff --git a/cpukit/posix/src/mqueuesendsupp.c b/cpukit/posix/src/mqueuesendsupp.c
new file mode 100644
index 0000000000..33109465e6
--- /dev/null
+++ b/cpukit/posix/src/mqueuesendsupp.c
@@ -0,0 +1,117 @@
+/*
+ * NOTE: The structure of the routines is identical to that of POSIX
+ * Message_queues to leave the option of having unnamed message
+ * queues at a future date. They are currently not part of the
+ * POSIX standard but unnamed message_queues are. This is also
+ * the reason for the apparently unnecessary tracking of
+ * the process_shared attribute. [In addition to the fact that
+ * it would be trivial to add pshared to the mq_attr structure
+ * and have process private message queues.]
+ *
+ * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
+ * time.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include <pthread.h>
+#include <limits.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <mqueue.h>
+
+#include <rtems/system.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/seterr.h>
+#include <rtems/posix/mqueue.h>
+#include <rtems/posix/time.h>
+
+
+/*PAGE
+ *
+ * _POSIX_Message_queue_Send_support
+ */
+
+int _POSIX_Message_queue_Send_support(
+ mqd_t mqdes,
+ const char *msg_ptr,
+ uint32_t msg_len,
+ uint32_t msg_prio,
+ Watchdog_Interval timeout
+)
+{
+ POSIX_Message_queue_Control *the_mq;
+ POSIX_Message_queue_Control_fd *the_mq_fd;
+ Objects_Locations location;
+ CORE_message_queue_Status msg_status;
+
+ /*
+ * Validate the priority.
+ * XXX - Do not validate msg_prio is not less than 0.
+ */
+
+ if ( msg_prio > MQ_PRIO_MAX )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ the_mq_fd = _POSIX_Message_queue_Get_fd( mqdes, &location );
+ switch ( location ) {
+ case OBJECTS_ERROR:
+ rtems_set_errno_and_return_minus_one( EBADF );
+
+ case OBJECTS_REMOTE:
+ _Thread_Dispatch();
+ return POSIX_MP_NOT_IMPLEMENTED();
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ case OBJECTS_LOCAL:
+ if ( (the_mq_fd->oflag & O_ACCMODE) == O_RDONLY ) {
+ _Thread_Enable_dispatch();
+ rtems_set_errno_and_return_minus_one( EBADF );
+ }
+
+ the_mq = the_mq_fd->Queue;
+
+ msg_status = _CORE_message_queue_Submit(
+ &the_mq->Message_queue,
+ (void *) msg_ptr,
+ msg_len,
+ mqdes, /* mqd_t is an object id */
+#if defined(RTEMS_MULTIPROCESSING)
+ NULL, /* XXX _POSIX_Message_queue_Core_message_queue_mp_support*/
+#else
+ NULL,
+#endif
+ _POSIX_Message_queue_Priority_to_core( msg_prio ),
+ (the_mq_fd->oflag & O_NONBLOCK) ? FALSE : TRUE,
+ timeout /* no timeout */
+ );
+
+ _Thread_Enable_dispatch();
+
+ /*
+ * If we had to block, then this is where the task returns
+ * after it wakes up. The returned status is correct for
+ * non-blocking operations but if we blocked, then we need
+ * to look at the status in our TCB.
+ */
+
+ if ( msg_status == CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_WAIT )
+ msg_status = _Thread_Executing->Wait.return_code;
+
+ if ( !msg_status )
+ return msg_status;
+
+ rtems_set_errno_and_return_minus_one(
+ _POSIX_Message_queue_Translate_core_message_queue_return_code(
+ msg_status
+ )
+ );
+ }
+ return POSIX_BOTTOM_REACHED();
+}
diff --git a/cpukit/posix/src/mqueuesetattr.c b/cpukit/posix/src/mqueuesetattr.c
new file mode 100644
index 0000000000..6d3b132ade
--- /dev/null
+++ b/cpukit/posix/src/mqueuesetattr.c
@@ -0,0 +1,81 @@
+/*
+ * NOTE: The structure of the routines is identical to that of POSIX
+ * Message_queues to leave the option of having unnamed message
+ * queues at a future date. They are currently not part of the
+ * POSIX standard but unnamed message_queues are. This is also
+ * the reason for the apparently unnecessary tracking of
+ * the process_shared attribute. [In addition to the fact that
+ * it would be trivial to add pshared to the mq_attr structure
+ * and have process private message queues.]
+ *
+ * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
+ * time.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include <pthread.h>
+#include <limits.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <mqueue.h>
+
+#include <rtems/system.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/seterr.h>
+#include <rtems/posix/mqueue.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * 15.2.7 Set Message Queue Attributes, P1003.1b-1993, p. 281
+ */
+
+int mq_setattr(
+ mqd_t mqdes,
+ const struct mq_attr *mqstat,
+ struct mq_attr *omqstat
+)
+{
+ POSIX_Message_queue_Control_fd *the_mq_fd;
+ CORE_message_queue_Control *the_core_mq;
+ Objects_Locations location;
+
+ if ( !mqstat )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ the_mq_fd = _POSIX_Message_queue_Get_fd( mqdes, &location );
+ switch ( location ) {
+ case OBJECTS_ERROR:
+ rtems_set_errno_and_return_minus_one( EBADF );
+ case OBJECTS_REMOTE:
+ _Thread_Dispatch();
+ return POSIX_MP_NOT_IMPLEMENTED();
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ case OBJECTS_LOCAL:
+
+ the_core_mq = &the_mq_fd->Queue->Message_queue;
+
+ /*
+ * Return the old values.
+ */
+
+ if ( omqstat ) {
+ omqstat->mq_flags = the_mq_fd->oflag;
+ omqstat->mq_msgsize = the_core_mq->maximum_message_size;
+ omqstat->mq_maxmsg = the_core_mq->maximum_pending_messages;
+ omqstat->mq_curmsgs = the_core_mq->number_of_pending_messages;
+ }
+
+ the_mq_fd->oflag = mqstat->mq_flags;
+ _Thread_Enable_dispatch();
+ return 0;
+ }
+ return POSIX_BOTTOM_REACHED();
+}
diff --git a/cpukit/posix/src/mqueuetimedreceive.c b/cpukit/posix/src/mqueuetimedreceive.c
new file mode 100644
index 0000000000..e0f605ac91
--- /dev/null
+++ b/cpukit/posix/src/mqueuetimedreceive.c
@@ -0,0 +1,57 @@
+/*
+ * NOTE: The structure of the routines is identical to that of POSIX
+ * Message_queues to leave the option of having unnamed message
+ * queues at a future date. They are currently not part of the
+ * POSIX standard but unnamed message_queues are. This is also
+ * the reason for the apparently unnecessary tracking of
+ * the process_shared attribute. [In addition to the fact that
+ * it would be trivial to add pshared to the mq_attr structure
+ * and have process private message queues.]
+ *
+ * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
+ * time.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include <pthread.h>
+#include <limits.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <mqueue.h>
+
+#include <rtems/system.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/seterr.h>
+#include <rtems/posix/mqueue.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * 15.2.5 Receive a Message From a Message Queue, P1003.1b-1993, p. 279
+ *
+ * NOTE: P1003.4b/D8, p. 45 adds mq_timedreceive().
+ */
+
+int mq_timedreceive( /* XXX: should this be ssize_t */
+ mqd_t mqdes,
+ char *msg_ptr,
+ size_t msg_len,
+ unsigned int *msg_prio,
+ const struct timespec *timeout
+)
+{
+ return _POSIX_Message_queue_Receive_support(
+ mqdes,
+ msg_ptr,
+ msg_len,
+ msg_prio,
+ _POSIX_Timespec_to_interval( timeout )
+ );
+}
diff --git a/cpukit/posix/src/mqueuetimedsend.c b/cpukit/posix/src/mqueuetimedsend.c
new file mode 100644
index 0000000000..89569368be
--- /dev/null
+++ b/cpukit/posix/src/mqueuetimedsend.c
@@ -0,0 +1,57 @@
+/*
+ * NOTE: The structure of the routines is identical to that of POSIX
+ * Message_queues to leave the option of having unnamed message
+ * queues at a future date. They are currently not part of the
+ * POSIX standard but unnamed message_queues are. This is also
+ * the reason for the apparently unnecessary tracking of
+ * the process_shared attribute. [In addition to the fact that
+ * it would be trivial to add pshared to the mq_attr structure
+ * and have process private message queues.]
+ *
+ * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
+ * time.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include <pthread.h>
+#include <limits.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <mqueue.h>
+
+#include <rtems/system.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/seterr.h>
+#include <rtems/posix/mqueue.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * 15.2.4 Send a Message to a Message Queue, P1003.1b-1993, p. 277
+ *
+ * NOTE: P1003.4b/D8, p. 45 adds mq_timedsend().
+ */
+
+int mq_timedsend(
+ mqd_t mqdes,
+ const char *msg_ptr,
+ size_t msg_len,
+ unsigned int msg_prio,
+ const struct timespec *timeout
+)
+{
+ return _POSIX_Message_queue_Send_support(
+ mqdes,
+ msg_ptr,
+ msg_len,
+ msg_prio,
+ _POSIX_Timespec_to_interval( timeout )
+ );
+}
diff --git a/cpukit/posix/src/mqueuetranslatereturncode.c b/cpukit/posix/src/mqueuetranslatereturncode.c
new file mode 100644
index 0000000000..74e67d0cf7
--- /dev/null
+++ b/cpukit/posix/src/mqueuetranslatereturncode.c
@@ -0,0 +1,101 @@
+/*
+ * POSIX Message Queue Error Translation
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <limits.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <mqueue.h>
+
+#include <rtems/system.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/seterr.h>
+#include <rtems/posix/mqueue.h>
+#include <rtems/posix/time.h>
+#include <rtems/score/interr.h>
+
+
+/*PAGE
+ *
+ * _POSIX_Message_queue_Translate_core_message_queue_return_code
+ *
+ * Input parameters:
+ * the_message_queue_status - message_queue status code to translate
+ *
+ * Output parameters:
+ * rtems status code - translated POSIX status code
+ *
+ */
+
+int _POSIX_Message_queue_Translate_core_message_queue_return_code(
+ uint32_t the_message_queue_status
+)
+{
+ switch ( the_message_queue_status ) {
+ case CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL:
+ return 0;
+
+ /*
+ * Bad message size
+ */
+ case CORE_MESSAGE_QUEUE_STATUS_INVALID_SIZE:
+ return EMSGSIZE;
+
+ /*
+ * Queue is full of pending messages.
+ */
+ case CORE_MESSAGE_QUEUE_STATUS_TOO_MANY:
+ return EAGAIN;
+
+ /*
+ * Out of message buffers to queue pending message
+ */
+ case CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED:
+ return ENOMEM;
+
+ /*
+ * No message available on receive poll
+ */
+ case CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_NOWAIT:
+ return EAGAIN;
+
+ /*
+ * Queue was deleted while thread blocked on it.
+ */
+ case CORE_MESSAGE_QUEUE_STATUS_WAS_DELETED:
+ return EBADF;
+
+ /*
+ * POSIX Real-Time Extensions add timeouts to send and receive.
+ */
+ case CORE_MESSAGE_QUEUE_STATUS_TIMEOUT:
+ return ETIMEDOUT;
+
+ /*
+ * RTEMS POSIX API implementation does not support multiprocessing.
+ */
+ case THREAD_STATUS_PROXY_BLOCKING:
+ return ENOSYS;
+ }
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_POSIX_API,
+ TRUE,
+ the_message_queue_status
+ );
+ return POSIX_BOTTOM_REACHED();
+}
diff --git a/cpukit/posix/src/mqueueunlink.c b/cpukit/posix/src/mqueueunlink.c
new file mode 100644
index 0000000000..3a14983226
--- /dev/null
+++ b/cpukit/posix/src/mqueueunlink.c
@@ -0,0 +1,85 @@
+/*
+ * NOTE: The structure of the routines is identical to that of POSIX
+ * Message_queues to leave the option of having unnamed message
+ * queues at a future date. They are currently not part of the
+ * POSIX standard but unnamed message_queues are. This is also
+ * the reason for the apparently unnecessary tracking of
+ * the process_shared attribute. [In addition to the fact that
+ * it would be trivial to add pshared to the mq_attr structure
+ * and have process private message queues.]
+ *
+ * This code ignores the O_RDONLY/O_WRONLY/O_RDWR flag at open
+ * time.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include <pthread.h>
+#include <limits.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <mqueue.h>
+
+#include <rtems/system.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/seterr.h>
+#include <rtems/posix/mqueue.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * 15.2.2 Remove a Message Queue, P1003.1b-1993, p. 276
+ */
+
+int mq_unlink(
+ const char *name
+)
+{
+ int status;
+ register POSIX_Message_queue_Control *the_mq;
+ Objects_Id the_mq_id;
+
+ _Thread_Disable_dispatch();
+
+ status = _POSIX_Message_queue_Name_to_id( name, &the_mq_id );
+ if ( status != 0 ) {
+ _Thread_Enable_dispatch();
+ rtems_set_errno_and_return_minus_one( status );
+ }
+
+ /*
+ * Don't support unlinking a remote message queue.
+ */
+
+ if ( !_Objects_Is_local_id(the_mq_id) ) {
+ _Thread_Enable_dispatch();
+ rtems_set_errno_and_return_minus_one( ENOSYS );
+ }
+
+ the_mq = (POSIX_Message_queue_Control *) _Objects_Get_local_object(
+ &_POSIX_Message_queue_Information,
+ _Objects_Get_index( the_mq_id )
+ );
+
+#if 0 && defined(RTEMS_MULTIPROCESSING)
+ if ( the_mq->process_shared == PTHREAD_PROCESS_SHARED ) {
+ _Objects_MP_Close( &_POSIX_Message_queue_Information, the_mq_id );
+ }
+#endif
+
+
+ the_mq->linked = FALSE;
+ _Workspace_Free( the_mq->Object.name );
+ _POSIX_Message_queue_Namespace_remove( the_mq );
+ _POSIX_Message_queue_Delete( the_mq );
+
+ _Thread_Enable_dispatch();
+ return 0;
+}
diff --git a/cpukit/posix/src/mutex.c b/cpukit/posix/src/mutex.c
new file mode 100644
index 0000000000..b7bde39167
--- /dev/null
+++ b/cpukit/posix/src/mutex.c
@@ -0,0 +1,54 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <rtems/system.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/watchdog.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/posix/mutex.h>
+#include <rtems/posix/priority.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * _POSIX_Mutex_Manager_initialization
+ *
+ * This routine initializes all mutex manager related data structures.
+ *
+ * Input parameters:
+ * maximum_mutexes - maximum configured mutexes
+ *
+ * Output parameters: NONE
+ */
+
+void _POSIX_Mutex_Manager_initialization(
+ uint32_t maximum_mutexes
+)
+{
+ _Objects_Initialize_information(
+ &_POSIX_Mutex_Information, /* object information table */
+ OBJECTS_POSIX_API, /* object API */
+ OBJECTS_POSIX_MUTEXES, /* object class */
+ maximum_mutexes, /* maximum objects of this class */
+ sizeof( POSIX_Mutex_Control ),
+ /* size of this object's control block */
+ FALSE, /* TRUE if names for this object are strings */
+ 0 /* maximum length of each object's name */
+#if defined(RTEMS_MULTIPROCESSING)
+ ,
+ FALSE, /* TRUE if this is a global object class */
+ NULL /* Proxy extraction support callout */
+#endif
+ );
+}
diff --git a/cpukit/posix/src/mutexattrdestroy.c b/cpukit/posix/src/mutexattrdestroy.c
new file mode 100644
index 0000000000..429dbeaee2
--- /dev/null
+++ b/cpukit/posix/src/mutexattrdestroy.c
@@ -0,0 +1,37 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <rtems/system.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/watchdog.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/posix/mutex.h>
+#include <rtems/posix/priority.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * 11.3.1 Mutex Initialization Attributes, P1003.1c/Draft 10, p. 81
+ */
+
+int pthread_mutexattr_destroy(
+ pthread_mutexattr_t *attr
+)
+{
+ if ( !attr || !attr->is_initialized )
+ return EINVAL;
+
+ attr->is_initialized = FALSE;
+ return 0;
+}
diff --git a/cpukit/posix/src/mutexattrgetprioceiling.c b/cpukit/posix/src/mutexattrgetprioceiling.c
new file mode 100644
index 0000000000..f0ef90b61f
--- /dev/null
+++ b/cpukit/posix/src/mutexattrgetprioceiling.c
@@ -0,0 +1,38 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <rtems/system.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/watchdog.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/posix/mutex.h>
+#include <rtems/posix/priority.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * 13.6.1 Mutex Initialization Scheduling Attributes, P1003.1c/Draft 10, p. 128
+ */
+
+int pthread_mutexattr_getprioceiling(
+ const pthread_mutexattr_t *attr,
+ int *prioceiling
+)
+{
+ if ( !attr || !attr->is_initialized || !prioceiling )
+ return EINVAL;
+
+ *prioceiling = attr->prio_ceiling;
+ return 0;
+}
diff --git a/cpukit/posix/src/mutexattrgetprotocol.c b/cpukit/posix/src/mutexattrgetprotocol.c
new file mode 100644
index 0000000000..2537ba00bf
--- /dev/null
+++ b/cpukit/posix/src/mutexattrgetprotocol.c
@@ -0,0 +1,38 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <rtems/system.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/watchdog.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/posix/mutex.h>
+#include <rtems/posix/priority.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * 13.6.1 Mutex Initialization Scheduling Attributes, P1003.1c/Draft 10, p. 128
+ */
+
+int pthread_mutexattr_getprotocol(
+ const pthread_mutexattr_t *attr,
+ int *protocol
+)
+{
+ if ( !attr || !attr->is_initialized || !protocol )
+ return EINVAL;
+
+ *protocol = attr->protocol;
+ return 0;
+}
diff --git a/cpukit/posix/src/mutexattrgetpshared.c b/cpukit/posix/src/mutexattrgetpshared.c
new file mode 100644
index 0000000000..3374b250ba
--- /dev/null
+++ b/cpukit/posix/src/mutexattrgetpshared.c
@@ -0,0 +1,38 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <rtems/system.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/watchdog.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/posix/mutex.h>
+#include <rtems/posix/priority.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * 11.3.1 Mutex Initialization Attributes, P1003.1c/Draft 10, p. 81
+ */
+
+int pthread_mutexattr_getpshared(
+ const pthread_mutexattr_t *attr,
+ int *pshared
+)
+{
+ if ( !attr || !attr->is_initialized || !pshared )
+ return EINVAL;
+
+ *pshared = attr->process_shared;
+ return 0;
+}
diff --git a/cpukit/posix/src/mutexattrinit.c b/cpukit/posix/src/mutexattrinit.c
new file mode 100644
index 0000000000..0cd6783ce8
--- /dev/null
+++ b/cpukit/posix/src/mutexattrinit.c
@@ -0,0 +1,37 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <rtems/system.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/watchdog.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/posix/mutex.h>
+#include <rtems/posix/priority.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * 11.3.1 Mutex Initialization Attributes, P1003.1c/Draft 10, p. 81
+ */
+
+int pthread_mutexattr_init(
+ pthread_mutexattr_t *attr
+)
+{
+ if ( !attr )
+ return EINVAL;
+
+ *attr = _POSIX_Mutex_Default_attributes;
+ return 0;
+}
diff --git a/cpukit/posix/src/mutexattrsetprioceiling.c b/cpukit/posix/src/mutexattrsetprioceiling.c
new file mode 100644
index 0000000000..da34a2fbb3
--- /dev/null
+++ b/cpukit/posix/src/mutexattrsetprioceiling.c
@@ -0,0 +1,41 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <rtems/system.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/watchdog.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/posix/mutex.h>
+#include <rtems/posix/priority.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * 13.6.1 Mutex Initialization Scheduling Attributes, P1003.1c/Draft 10, p. 128
+ */
+
+int pthread_mutexattr_setprioceiling(
+ pthread_mutexattr_t *attr,
+ int prioceiling
+)
+{
+ if ( !attr || !attr->is_initialized )
+ return EINVAL;
+
+ if ( !_POSIX_Priority_Is_valid( prioceiling ) )
+ return EINVAL;
+
+ attr->prio_ceiling = prioceiling;
+ return 0;
+}
diff --git a/cpukit/posix/src/mutexattrsetprotocol.c b/cpukit/posix/src/mutexattrsetprotocol.c
new file mode 100644
index 0000000000..2f74abf3d2
--- /dev/null
+++ b/cpukit/posix/src/mutexattrsetprotocol.c
@@ -0,0 +1,46 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <rtems/system.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/watchdog.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/posix/mutex.h>
+#include <rtems/posix/priority.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * 13.6.1 Mutex Initialization Scheduling Attributes, P1003.1c/Draft 10, p. 128
+ */
+
+int pthread_mutexattr_setprotocol(
+ pthread_mutexattr_t *attr,
+ int protocol
+)
+{
+ if ( !attr || !attr->is_initialized )
+ return EINVAL;
+
+ switch ( protocol ) {
+ case PTHREAD_PRIO_NONE:
+ case PTHREAD_PRIO_INHERIT:
+ case PTHREAD_PRIO_PROTECT:
+ attr->protocol = protocol;
+ return 0;
+
+ default:
+ return EINVAL;
+ }
+}
diff --git a/cpukit/posix/src/mutexattrsetpshared.c b/cpukit/posix/src/mutexattrsetpshared.c
new file mode 100644
index 0000000000..10d7a80647
--- /dev/null
+++ b/cpukit/posix/src/mutexattrsetpshared.c
@@ -0,0 +1,45 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <rtems/system.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/watchdog.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/posix/mutex.h>
+#include <rtems/posix/priority.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * 11.3.1 Mutex Initialization Attributes, P1003.1c/Draft 10, p. 81
+ */
+
+int pthread_mutexattr_setpshared(
+ pthread_mutexattr_t *attr,
+ int pshared
+)
+{
+ if ( !attr || !attr->is_initialized )
+ return EINVAL;
+
+ switch ( pshared ) {
+ case PTHREAD_PROCESS_SHARED:
+ case PTHREAD_PROCESS_PRIVATE:
+ attr->process_shared = pshared;
+ return 0;
+
+ default:
+ return EINVAL;
+ }
+}
diff --git a/cpukit/posix/src/mutexdefaultattributes.c b/cpukit/posix/src/mutexdefaultattributes.c
new file mode 100644
index 0000000000..bdca71a43b
--- /dev/null
+++ b/cpukit/posix/src/mutexdefaultattributes.c
@@ -0,0 +1,34 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <rtems/system.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/watchdog.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/posix/mutex.h>
+#include <rtems/posix/priority.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * The default mutex attributes structure.
+ */
+
+const pthread_mutexattr_t _POSIX_Mutex_Default_attributes = {
+ TRUE, /* is_initialized */
+ PTHREAD_PROCESS_PRIVATE, /* process_shared */
+ POSIX_SCHEDULER_MAXIMUM_PRIORITY, /* prio_ceiling */
+ PTHREAD_PRIO_NONE, /* protocol */
+ FALSE /* recursive */
+};
diff --git a/cpukit/posix/src/mutexdestroy.c b/cpukit/posix/src/mutexdestroy.c
new file mode 100644
index 0000000000..f4210148cd
--- /dev/null
+++ b/cpukit/posix/src/mutexdestroy.c
@@ -0,0 +1,87 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <rtems/system.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/watchdog.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/posix/mutex.h>
+#include <rtems/posix/priority.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * 11.3.2 Initializing and Destroying a Mutex, P1003.1c/Draft 10, p. 87
+ */
+
+int pthread_mutex_destroy(
+ pthread_mutex_t *mutex
+)
+{
+ register POSIX_Mutex_Control *the_mutex;
+ Objects_Locations location;
+
+ the_mutex = _POSIX_Mutex_Get( mutex, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE:
+#if defined(RTEMS_MULTIPROCESSING)
+ _Thread_Dispatch();
+ return POSIX_MP_NOT_IMPLEMENTED();
+ return EINVAL;
+#endif
+ case OBJECTS_ERROR:
+ return EINVAL;
+ case OBJECTS_LOCAL:
+ /*
+ * XXX: There is an error for the mutex being locked
+ * or being in use by a condition variable.
+ */
+
+ if ( _CORE_mutex_Is_locked( &the_mutex->Mutex ) ) {
+ _Thread_Enable_dispatch();
+ return EBUSY;
+ }
+
+ _Objects_Close( &_POSIX_Mutex_Information, &the_mutex->Object );
+
+ _CORE_mutex_Flush(
+ &the_mutex->Mutex,
+#if defined(RTEMS_MULTIPROCESSING)
+ _POSIX_Mutex_MP_Send_object_was_deleted,
+#else
+ NULL,
+#endif
+ EINVAL
+ );
+
+ _POSIX_Mutex_Free( the_mutex );
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( the_mutex->process_shared == PTHREAD_PROCESS_SHARED ) {
+
+ _Objects_MP_Close( &_POSIX_Mutex_Information, the_mutex->Object.id );
+
+ _POSIX_Mutex_MP_Send_process_packet(
+ POSIX_MUTEX_MP_ANNOUNCE_DELETE,
+ the_mutex->Object.id,
+ 0, /* Not used */
+ 0 /* Not used */
+ );
+ }
+#endif
+ _Thread_Enable_dispatch();
+ return 0;
+ }
+ return POSIX_BOTTOM_REACHED();
+}
diff --git a/cpukit/posix/src/mutexfromcorestatus.c b/cpukit/posix/src/mutexfromcorestatus.c
new file mode 100644
index 0000000000..3c6f617861
--- /dev/null
+++ b/cpukit/posix/src/mutexfromcorestatus.c
@@ -0,0 +1,52 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <rtems/system.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/watchdog.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/posix/mutex.h>
+#include <rtems/posix/priority.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * _POSIX_Mutex_From_core_mutex_status
+ */
+
+int _POSIX_Mutex_From_core_mutex_status(
+ CORE_mutex_Status status
+)
+{
+ switch ( status ) {
+ case CORE_MUTEX_STATUS_SUCCESSFUL:
+ return 0;
+ case CORE_MUTEX_STATUS_UNSATISFIED_NOWAIT:
+ return EBUSY;
+ case CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED:
+ return EDEADLK;
+ case CORE_MUTEX_STATUS_NOT_OWNER_OF_RESOURCE:
+ return EPERM;
+ case CORE_MUTEX_WAS_DELETED:
+ return EINVAL;
+ case CORE_MUTEX_TIMEOUT:
+ return EAGAIN;
+ case CORE_MUTEX_STATUS_CEILING_VIOLATED:
+ return EINVAL;
+ default:
+ break;
+ }
+ assert( 0 );
+ return 0;
+}
diff --git a/cpukit/posix/src/mutexgetprioceiling.c b/cpukit/posix/src/mutexgetprioceiling.c
new file mode 100644
index 0000000000..4e43325560
--- /dev/null
+++ b/cpukit/posix/src/mutexgetprioceiling.c
@@ -0,0 +1,55 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <rtems/system.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/watchdog.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/posix/mutex.h>
+#include <rtems/posix/priority.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * 13.6.2 Change the Priority Ceiling of a Mutex, P1003.1c/Draft 10, p. 131
+ */
+
+int pthread_mutex_getprioceiling(
+ pthread_mutex_t *mutex,
+ int *prioceiling
+)
+{
+ register POSIX_Mutex_Control *the_mutex;
+ Objects_Locations location;
+
+ if ( !prioceiling )
+ return EINVAL;
+
+ the_mutex = _POSIX_Mutex_Get( mutex, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE:
+#if defined(RTEMS_MULTIPROCESSING)
+ return POSIX_MP_NOT_IMPLEMENTED(); /* XXX feels questionable */
+#endif
+ case OBJECTS_ERROR:
+ return EINVAL;
+ case OBJECTS_LOCAL:
+ *prioceiling = _POSIX_Priority_From_core(
+ the_mutex->Mutex.Attributes.priority_ceiling
+ );
+ _Thread_Enable_dispatch();
+ return 0;
+ }
+ return POSIX_BOTTOM_REACHED();
+}
diff --git a/cpukit/posix/src/mutexinit.c b/cpukit/posix/src/mutexinit.c
new file mode 100644
index 0000000000..3af8c1d621
--- /dev/null
+++ b/cpukit/posix/src/mutexinit.c
@@ -0,0 +1,186 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <rtems/system.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/watchdog.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/posix/mutex.h>
+#include <rtems/posix/priority.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * 11.3.2 Initializing and Destroying a Mutex, P1003.1c/Draft 10, p. 87
+ *
+ * NOTE: XXX Could be optimized so all the attribute error checking
+ * is not performed when attr is NULL.
+ */
+
+int pthread_mutex_init(
+ pthread_mutex_t *mutex,
+ const pthread_mutexattr_t *attr
+)
+{
+ POSIX_Mutex_Control *the_mutex;
+ CORE_mutex_Attributes *the_mutex_attr;
+ const pthread_mutexattr_t *the_attr;
+ CORE_mutex_Disciplines the_discipline;
+#if 0
+ register POSIX_Mutex_Control *mutex_in_use;
+ Objects_Locations location;
+#endif
+
+ if ( attr ) the_attr = attr;
+ else the_attr = &_POSIX_Mutex_Default_attributes;
+
+ /* Check for NULL mutex */
+
+ if ( !mutex )
+ return EINVAL;
+
+ /*
+ * This code should eventually be removed.
+ *
+ * Although the POSIX specification says:
+ *
+ * "Attempting to initialize an already initialized mutex results
+ * in undefined behavior."
+ *
+ * Trying to keep the caller from doing the create when *mutex
+ * is actually a valid ID causes grief. All it takes is the wrong
+ * value in an uninitialized variable to make this fail. As best
+ * I can tell, RTEMS was the only pthread implementation to choose
+ * this option for "undefined behavior" and doing so has created
+ * portability problems. In particular, Rosimildo DaSilva
+ * <rdasilva@connecttel.com> saw seemingly random failures in the
+ * RTEMS port of omniORB2 when this code was enabled.
+ *
+ * Joel Sherrill <joel@OARcorp.com> 14 May 1999
+ */
+
+
+#if 0
+ /* avoid infinite recursion on call to this routine in _POSIX_Mutex_Get */
+
+ if ( *mutex != PTHREAD_MUTEX_INITIALIZER ) {
+
+ /* EBUSY if *mutex is a valid id */
+
+ mutex_in_use = _POSIX_Mutex_Get( mutex, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE:
+ case OBJECTS_ERROR:
+ break;
+ case OBJECTS_LOCAL:
+ _Thread_Enable_dispatch();
+ return EBUSY;
+ }
+ }
+#endif
+
+ if ( !the_attr->is_initialized )
+ return EINVAL;
+
+ /*
+ * XXX: Be careful about attributes when global!!!
+ */
+
+ assert( the_attr->process_shared == PTHREAD_PROCESS_PRIVATE );
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( the_attr->process_shared == PTHREAD_PROCESS_SHARED )
+ return POSIX_MP_NOT_IMPLEMENTED();
+#endif
+
+ /*
+ * Determine the discipline of the mutex
+ */
+
+ switch ( the_attr->protocol ) {
+ case PTHREAD_PRIO_NONE:
+ the_discipline = CORE_MUTEX_DISCIPLINES_FIFO;
+ break;
+ case PTHREAD_PRIO_INHERIT:
+ the_discipline = CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT;
+ break;
+ case PTHREAD_PRIO_PROTECT:
+ the_discipline = CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING;
+ break;
+ default:
+ return EINVAL;
+ }
+
+ if ( !_POSIX_Priority_Is_valid( the_attr->prio_ceiling ) )
+ return EINVAL;
+
+ _Thread_Disable_dispatch();
+
+ the_mutex = _POSIX_Mutex_Allocate();
+
+ if ( !the_mutex ) {
+ _Thread_Enable_dispatch();
+ return EAGAIN;
+ }
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( the_attr->process_shared == PTHREAD_PROCESS_SHARED &&
+ !( _Objects_MP_Allocate_and_open( &_POSIX_Mutex_Information, 0,
+ the_mutex->Object.id, FALSE ) ) ) {
+ _POSIX_Mutex_Free( the_mutex );
+ _Thread_Enable_dispatch();
+ return EAGAIN;
+ }
+#endif
+
+ the_mutex->process_shared = the_attr->process_shared;
+
+ the_mutex_attr = &the_mutex->Mutex.Attributes;
+
+ if ( the_attr->recursive )
+ the_mutex_attr->lock_nesting_behavior = CORE_MUTEX_NESTING_ACQUIRES;
+ else
+ the_mutex_attr->lock_nesting_behavior = CORE_MUTEX_NESTING_IS_ERROR;
+ the_mutex_attr->only_owner_release = TRUE;
+ the_mutex_attr->priority_ceiling =
+ _POSIX_Priority_To_core( the_attr->prio_ceiling );
+ the_mutex_attr->discipline = the_discipline;
+
+ /*
+ * Must be initialized to unlocked.
+ */
+
+ _CORE_mutex_Initialize(
+ &the_mutex->Mutex,
+ the_mutex_attr,
+ CORE_MUTEX_UNLOCKED
+ );
+
+ _Objects_Open( &_POSIX_Mutex_Information, &the_mutex->Object, 0 );
+
+ *mutex = the_mutex->Object.id;
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( the_attr->process_shared == PTHREAD_PROCESS_SHARED )
+ _POSIX_Mutex_MP_Send_process_packet(
+ POSIX_MUTEX_MP_ANNOUNCE_CREATE,
+ the_mutex->Object.id,
+ 0, /* Name not used */
+ 0 /* Not used */
+ );
+#endif
+
+ _Thread_Enable_dispatch();
+ return 0;
+}
diff --git a/cpukit/posix/src/mutexlock.c b/cpukit/posix/src/mutexlock.c
new file mode 100644
index 0000000000..b040dc08d4
--- /dev/null
+++ b/cpukit/posix/src/mutexlock.c
@@ -0,0 +1,35 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <rtems/system.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/watchdog.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/posix/mutex.h>
+#include <rtems/posix/priority.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * 11.3.3 Locking and Unlocking a Mutex, P1003.1c/Draft 10, p. 93
+ *
+ * NOTE: P1003.4b/D8 adds pthread_mutex_timedlock(), p. 29
+ */
+
+int pthread_mutex_lock(
+ pthread_mutex_t *mutex
+)
+{
+ return _POSIX_Mutex_Lock_support( mutex, TRUE, THREAD_QUEUE_WAIT_FOREVER );
+}
diff --git a/cpukit/posix/src/mutexlocksupp.c b/cpukit/posix/src/mutexlocksupp.c
new file mode 100644
index 0000000000..9e8ee10172
--- /dev/null
+++ b/cpukit/posix/src/mutexlocksupp.c
@@ -0,0 +1,67 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <rtems/system.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/watchdog.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/posix/mutex.h>
+#include <rtems/posix/priority.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * _POSIX_Mutex_Lock_support
+ *
+ * A support routine which implements guts of the blocking, non-blocking, and
+ * timed wait version of mutex lock.
+ */
+
+int _POSIX_Mutex_Lock_support(
+ pthread_mutex_t *mutex,
+ boolean blocking,
+ Watchdog_Interval timeout
+)
+{
+ register POSIX_Mutex_Control *the_mutex;
+ Objects_Locations location;
+ ISR_Level level;
+
+ the_mutex = _POSIX_Mutex_Get_interrupt_disable( mutex, &location, &level );
+ switch ( location ) {
+ case OBJECTS_REMOTE:
+#if defined(RTEMS_MULTIPROCESSING)
+ return _POSIX_Mutex_MP_Send_request_packet(
+ POSIX_MUTEX_MP_OBTAIN_REQUEST,
+ *mutex,
+ 0, /* must define the option set */
+ WATCHDOG_NO_TIMEOUT
+ );
+#endif
+ case OBJECTS_ERROR:
+ return EINVAL;
+ case OBJECTS_LOCAL:
+ _CORE_mutex_Seize(
+ &the_mutex->Mutex,
+ the_mutex->Object.id,
+ blocking,
+ timeout,
+ level
+ );
+ return _POSIX_Mutex_From_core_mutex_status(
+ (CORE_mutex_Status) _Thread_Executing->Wait.return_code
+ );
+ }
+ return POSIX_BOTTOM_REACHED();
+}
diff --git a/cpukit/posix/src/mutexmp.c b/cpukit/posix/src/mutexmp.c
new file mode 100644
index 0000000000..75db779ce4
--- /dev/null
+++ b/cpukit/posix/src/mutexmp.c
@@ -0,0 +1,66 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <rtems/system.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/watchdog.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/posix/mutex.h>
+#include <rtems/posix/priority.h>
+#include <rtems/posix/time.h>
+
+/*
+ * TEMPORARY
+ */
+
+#if defined(RTEMS_MULTIPROCESSING)
+void _POSIX_Mutex_MP_Send_process_packet (
+ POSIX_Mutex_MP_Remote_operations operation,
+ Objects_Id mutex_id,
+ Objects_Name name,
+ Objects_Id proxy_id
+)
+{
+ (void) POSIX_MP_NOT_IMPLEMENTED();
+}
+
+void _POSIX_Mutex_MP_Send_object_was_deleted (
+ Thread_Control *the_proxy
+)
+{
+ (void) POSIX_MP_NOT_IMPLEMENTED();
+}
+
+int _POSIX_Mutex_MP_Send_request_packet (
+ POSIX_Mutex_MP_Remote_operations operation,
+ Objects_Id mutex_id,
+ boolean wait, /* XXX options */
+ Watchdog_Interval timeout
+)
+{
+ return POSIX_MP_NOT_IMPLEMENTED();
+}
+
+void _POSIX_Threads_mutex_MP_support(
+ Thread_Control *the_thread,
+ Objects_Id id
+)
+{
+ (void) POSIX_MP_NOT_IMPLEMENTED(); /* XXX: should never get here */
+}
+#endif
+
+/*
+ * END OF TEMPORARY
+ */
diff --git a/cpukit/posix/src/mutexsetprioceiling.c b/cpukit/posix/src/mutexsetprioceiling.c
new file mode 100644
index 0000000000..60c82a4f19
--- /dev/null
+++ b/cpukit/posix/src/mutexsetprioceiling.c
@@ -0,0 +1,82 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <rtems/system.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/watchdog.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/posix/mutex.h>
+#include <rtems/posix/priority.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * 13.6.2 Change the Priority Ceiling of a Mutex, P1003.1c/Draft 10, p. 131
+ */
+
+int pthread_mutex_setprioceiling(
+ pthread_mutex_t *mutex,
+ int prioceiling,
+ int *old_ceiling
+)
+{
+ register POSIX_Mutex_Control *the_mutex;
+ Objects_Locations location;
+ Priority_Control the_priority;
+ int status;
+
+ if ( !old_ceiling )
+ return EINVAL;
+
+ if ( !_POSIX_Priority_Is_valid( prioceiling ) )
+ return EINVAL;
+
+ the_priority = _POSIX_Priority_To_core( prioceiling );
+
+ /*
+ * Must acquire the mutex before we can change it's ceiling
+ */
+
+ status = pthread_mutex_lock( mutex );
+ if ( status )
+ return status;
+
+ the_mutex = _POSIX_Mutex_Get( mutex, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE:
+#if defined(RTEMS_MULTIPROCESSING)
+ /* XXX It feels questionable to set the ceiling on a remote mutex. */
+ return EINVAL;
+#endif
+ case OBJECTS_ERROR:
+ return EINVAL; /* impossible to get here */
+ case OBJECTS_LOCAL:
+ *old_ceiling = _POSIX_Priority_From_core(
+ the_mutex->Mutex.Attributes.priority_ceiling
+ );
+ the_mutex->Mutex.Attributes.priority_ceiling = the_priority;
+ _CORE_mutex_Surrender(
+ &the_mutex->Mutex,
+ the_mutex->Object.id,
+#if defined(RTEMS_MULTIPROCESSING)
+ _POSIX_Threads_mutex_MP_support
+#else
+ NULL
+#endif
+ );
+ _Thread_Enable_dispatch();
+ return 0;
+ }
+ return POSIX_BOTTOM_REACHED();
+}
diff --git a/cpukit/posix/src/mutextimedlock.c b/cpukit/posix/src/mutextimedlock.c
new file mode 100644
index 0000000000..6555f5a4d2
--- /dev/null
+++ b/cpukit/posix/src/mutextimedlock.c
@@ -0,0 +1,40 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <rtems/system.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/watchdog.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/posix/mutex.h>
+#include <rtems/posix/priority.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * 11.3.3 Locking and Unlocking a Mutex, P1003.1c/Draft 10, p. 93
+ *
+ * NOTE: P1003.4b/D8 adds pthread_mutex_timedlock(), p. 29
+ */
+
+int pthread_mutex_timedlock(
+ pthread_mutex_t *mutex,
+ const struct timespec *timeout
+)
+{
+ return _POSIX_Mutex_Lock_support(
+ mutex,
+ TRUE,
+ _POSIX_Timespec_to_interval( timeout )
+ );
+}
diff --git a/cpukit/posix/src/mutextrylock.c b/cpukit/posix/src/mutextrylock.c
new file mode 100644
index 0000000000..68df754b0a
--- /dev/null
+++ b/cpukit/posix/src/mutextrylock.c
@@ -0,0 +1,35 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <rtems/system.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/watchdog.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/posix/mutex.h>
+#include <rtems/posix/priority.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * 11.3.3 Locking and Unlocking a Mutex, P1003.1c/Draft 10, p. 93
+ *
+ * NOTE: P1003.4b/D8 adds pthread_mutex_timedlock(), p. 29
+ */
+
+int pthread_mutex_trylock(
+ pthread_mutex_t *mutex
+)
+{
+ return _POSIX_Mutex_Lock_support( mutex, FALSE, THREAD_QUEUE_WAIT_FOREVER );
+}
diff --git a/cpukit/posix/src/mutexunlock.c b/cpukit/posix/src/mutexunlock.c
new file mode 100644
index 0000000000..b88ae4c269
--- /dev/null
+++ b/cpukit/posix/src/mutexunlock.c
@@ -0,0 +1,66 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <rtems/system.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/watchdog.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/posix/mutex.h>
+#include <rtems/posix/priority.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * 11.3.3 Locking and Unlocking a Mutex, P1003.1c/Draft 10, p. 93
+ *
+ * NOTE: P1003.4b/D8 adds pthread_mutex_timedlock(), p. 29
+ */
+
+int pthread_mutex_unlock(
+ pthread_mutex_t *mutex
+)
+{
+ register POSIX_Mutex_Control *the_mutex;
+ Objects_Locations location;
+ CORE_mutex_Status status;
+
+ the_mutex = _POSIX_Mutex_Get( mutex, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE:
+#if defined(RTEMS_MULTIPROCESSING)
+ return _POSIX_Mutex_MP_Send_request_packet(
+ POSIX_MUTEX_MP_RELEASE_REQUEST,
+ *mutex,
+ 0, /* Not used */
+ MPCI_DEFAULT_TIMEOUT
+ );
+#endif
+ case OBJECTS_ERROR:
+ return EINVAL;
+ case OBJECTS_LOCAL:
+ status = _CORE_mutex_Surrender(
+ &the_mutex->Mutex,
+ the_mutex->Object.id,
+#if defined(RTEMS_MULTIPROCESSING)
+ _POSIX_Threads_mutex_MP_support
+#else
+ NULL
+#endif
+ );
+ _Thread_Enable_dispatch();
+ return _POSIX_Mutex_From_core_mutex_status( status );
+ break;
+ }
+ return POSIX_BOTTOM_REACHED();
+}
diff --git a/cpukit/posix/src/nanosleep.c b/cpukit/posix/src/nanosleep.c
new file mode 100644
index 0000000000..06fc1bc5cb
--- /dev/null
+++ b/cpukit/posix/src/nanosleep.c
@@ -0,0 +1,104 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <time.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/tod.h>
+
+#include <rtems/seterr.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * 14.2.5 High Resolution Sleep, P1003.1b-1993, p. 269
+ */
+
+int nanosleep(
+ const struct timespec *rqtp,
+ struct timespec *rmtp
+)
+{
+ Watchdog_Interval ticks;
+ struct timespec *the_rqtp;
+
+ if ( !rqtp )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ the_rqtp = (struct timespec *)rqtp;
+
+ /*
+ * Return EAGAIN if the delay interval is negative.
+ *
+ * NOTE: This behavior is beyond the POSIX specification.
+ * FSU pthreads shares this behavior.
+ */
+
+ if ( the_rqtp->tv_sec < 0 )
+ the_rqtp->tv_sec = 0;
+
+ if ( /* the_rqtp->tv_sec < 0 || */ the_rqtp->tv_nsec < 0 )
+ rtems_set_errno_and_return_minus_one( EAGAIN );
+
+ if ( the_rqtp->tv_nsec >= TOD_NANOSECONDS_PER_SECOND )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ ticks = _POSIX_Timespec_to_interval( the_rqtp );
+
+ /*
+ * This behavior is also beyond the POSIX specification but is
+ * consistent with the RTEMS api and yields desirable behavior.
+ */
+
+ if ( !ticks ) {
+ _Thread_Disable_dispatch();
+ _Thread_Yield_processor();
+ _Thread_Enable_dispatch();
+ if ( rmtp ) {
+ rmtp->tv_sec = 0;
+ rmtp->tv_nsec = 0;
+ }
+ return 0;
+ }
+
+ _Thread_Disable_dispatch();
+ _Thread_Set_state(
+ _Thread_Executing,
+ STATES_DELAYING | STATES_INTERRUPTIBLE_BY_SIGNAL
+ );
+ _Watchdog_Initialize(
+ &_Thread_Executing->Timer,
+ _Thread_Delay_ended,
+ _Thread_Executing->Object.id,
+ NULL
+ );
+ _Watchdog_Insert_ticks( &_Thread_Executing->Timer, ticks );
+ _Thread_Enable_dispatch();
+
+ /* calculate time remaining */
+
+ if ( rmtp ) {
+ ticks -=
+ _Thread_Executing->Timer.stop_time - _Thread_Executing->Timer.start_time;
+
+ _POSIX_Interval_to_timespec( ticks, rmtp );
+
+ /*
+ * If there is time remaining, then we were interrupted by a signal.
+ */
+
+ if ( ticks )
+ rtems_set_errno_and_return_minus_one( EINTR );
+ }
+
+ return 0;
+}
diff --git a/cpukit/posix/src/pause.c b/cpukit/posix/src/pause.c
new file mode 100644
index 0000000000..e4a8782bc4
--- /dev/null
+++ b/cpukit/posix/src/pause.c
@@ -0,0 +1,40 @@
+/*
+ * 3.4.2 Suspend Process Execution, P1003.1b-1993, p. 81
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <signal.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/psignal.h>
+
+/*
+ * 3.4.2 Suspend Process Execution, P1003.1b-1993, p. 81
+ */
+
+int pause( void )
+{
+ sigset_t all_signals;
+ int status;
+
+ (void) sigfillset( &all_signals );
+
+ status = sigtimedwait( &all_signals, NULL, NULL );
+
+ return status;
+}
diff --git a/cpukit/posix/src/posixintervaltotimespec.c b/cpukit/posix/src/posixintervaltotimespec.c
new file mode 100644
index 0000000000..916b890d8a
--- /dev/null
+++ b/cpukit/posix/src/posixintervaltotimespec.c
@@ -0,0 +1,38 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <time.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/tod.h>
+
+#include <rtems/seterr.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * _POSIX_Interval_to_timespec
+ */
+
+void _POSIX_Interval_to_timespec(
+ Watchdog_Interval ticks,
+ struct timespec *time
+)
+{
+ uint32_t usecs;
+
+ usecs = ticks * _TOD_Microseconds_per_tick;
+
+ time->tv_sec = usecs / TOD_MICROSECONDS_PER_SECOND;
+ time->tv_nsec = (usecs % TOD_MICROSECONDS_PER_SECOND) *
+ TOD_NANOSECONDS_PER_MICROSECOND;
+}
diff --git a/cpukit/posix/src/posixtimespecsubtract.c b/cpukit/posix/src/posixtimespecsubtract.c
new file mode 100644
index 0000000000..0fa611b6ea
--- /dev/null
+++ b/cpukit/posix/src/posixtimespecsubtract.c
@@ -0,0 +1,50 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <time.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/tod.h>
+
+#include <rtems/seterr.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * _POSIX_Timespec_subtract
+ */
+
+void _POSIX_Timespec_subtract(
+ const struct timespec *the_start,
+ const struct timespec *end,
+ struct timespec *result
+)
+{
+ struct timespec start_struct = *the_start;
+ struct timespec *start = &start_struct;
+ uint32_t nsecs_per_sec = TOD_NANOSECONDS_PER_SECOND;
+
+ if (end->tv_nsec < start->tv_nsec) {
+ int seconds = (start->tv_nsec - end->tv_nsec) / nsecs_per_sec + 1;
+ start->tv_nsec -= nsecs_per_sec * seconds;
+ start->tv_sec += seconds;
+ }
+
+ if (end->tv_nsec - start->tv_nsec > nsecs_per_sec) {
+ int seconds = (start->tv_nsec - end->tv_nsec) / nsecs_per_sec;
+ start->tv_nsec += nsecs_per_sec * seconds;
+ start->tv_sec -= seconds;
+ }
+
+ result->tv_sec = end->tv_sec - start->tv_sec;
+ result->tv_nsec = end->tv_nsec - start->tv_nsec;
+}
diff --git a/cpukit/posix/src/posixtimespectointerval.c b/cpukit/posix/src/posixtimespectointerval.c
new file mode 100644
index 0000000000..3e4d5cf130
--- /dev/null
+++ b/cpukit/posix/src/posixtimespectointerval.c
@@ -0,0 +1,42 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <time.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/tod.h>
+
+#include <rtems/seterr.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * _POSIX_Timespec_to_interval
+ */
+
+Watchdog_Interval _POSIX_Timespec_to_interval(
+ const struct timespec *time
+)
+{
+ Watchdog_Interval ticks;
+
+ ticks = (time->tv_sec * TOD_MICROSECONDS_PER_SECOND) /
+ _TOD_Microseconds_per_tick;
+
+ ticks += (time->tv_nsec / TOD_NANOSECONDS_PER_MICROSECOND) /
+ _TOD_Microseconds_per_tick;
+
+ if (ticks)
+ return ticks;
+
+ return 1;
+}
diff --git a/cpukit/posix/src/psignal.c b/cpukit/posix/src/psignal.c
new file mode 100644
index 0000000000..be8a7dadf4
--- /dev/null
+++ b/cpukit/posix/src/psignal.c
@@ -0,0 +1,206 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <string.h> /* memcpy */
+#include <stdlib.h> /* exit */
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/tqdata.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/seterr.h>
+#include <rtems/posix/threadsup.h>
+#include <rtems/posix/psignal.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/time.h>
+#include <stdio.h>
+
+/*** PROCESS WIDE STUFF ****/
+
+sigset_t _POSIX_signals_Pending;
+
+void _POSIX_signals_Abnormal_termination_handler( int signo )
+{
+ exit( 1 );
+}
+
+#define SIG_ARRAY_MAX (SIGRTMAX + 1)
+struct sigaction _POSIX_signals_Default_vectors[ SIG_ARRAY_MAX ] = {
+ /* NO SIGNAL 0 */ SIGACTION_IGNORE,
+ /* SIGHUP 1 */ SIGACTION_TERMINATE,
+ /* SIGINT 2 */ SIGACTION_TERMINATE,
+ /* SIGQUIT 3 */ SIGACTION_TERMINATE,
+ /* SIGILL 4 */ SIGACTION_TERMINATE,
+ /* SIGTRAP 5 */ SIGACTION_TERMINATE,
+ /* SIGIOT 6 */ SIGACTION_TERMINATE,
+ /* SIGABRT 6 SIGACTION_TERMINATE, -- alias for SIGIOT */
+ /* SIGEMT 7 */ SIGACTION_TERMINATE,
+ /* SIGFPE 8 */ SIGACTION_TERMINATE,
+ /* SIGKILL 9 */ SIGACTION_TERMINATE,
+ /* SIGBUS 10 */ SIGACTION_TERMINATE,
+ /* SIGSEGV 11 */ SIGACTION_TERMINATE,
+ /* SIGSYS 12 */ SIGACTION_TERMINATE,
+ /* SIGPIPE 13 */ SIGACTION_TERMINATE,
+ /* SIGALRM 14 */ SIGACTION_TERMINATE,
+ /* SIGTERM 15 */ SIGACTION_TERMINATE,
+ /* SIGURG 16 */ SIGACTION_TERMINATE,
+ /* SIGSTOP 17 */ SIGACTION_TERMINATE,
+ /* SIGTSTP 18 */ SIGACTION_TERMINATE,
+ /* SIGCONT 19 */ SIGACTION_TERMINATE,
+ /* SIGCHLD 20 */ SIGACTION_TERMINATE,
+ /* SIGTTIN 21 */ SIGACTION_TERMINATE,
+ /* SIGTTOU 22 */ SIGACTION_TERMINATE,
+ /* SIGIO 23 */ SIGACTION_TERMINATE,
+ /* SIGWINCH 24 */ SIGACTION_TERMINATE,
+ /* SIGUSR1 25 */ SIGACTION_TERMINATE,
+ /* SIGUSR2 26 */ SIGACTION_TERMINATE,
+ /* SIGRT 27 */ SIGACTION_TERMINATE,
+ /* SIGRT 28 */ SIGACTION_TERMINATE,
+ /* SIGRT 29 */ SIGACTION_TERMINATE,
+ /* SIGRT 30 */ SIGACTION_TERMINATE,
+ /* SIGRTMAX 31 */ SIGACTION_TERMINATE
+};
+
+struct sigaction _POSIX_signals_Vectors[ SIG_ARRAY_MAX ];
+
+Thread_queue_Control _POSIX_signals_Wait_queue;
+
+Chain_Control _POSIX_signals_Inactive_siginfo;
+Chain_Control _POSIX_signals_Siginfo[ SIG_ARRAY_MAX ];
+
+/*PAGE
+ *
+ * XXX - move these
+ */
+
+#define _States_Is_interruptible_signal( _states ) \
+ ( ((_states) & \
+ (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL)) == \
+ (STATES_WAITING_FOR_SIGNAL|STATES_INTERRUPTIBLE_BY_SIGNAL))
+
+/*
+ * _POSIX_signals_Post_switch_extension
+ */
+
+void _POSIX_signals_Post_switch_extension(
+ Thread_Control *the_thread
+)
+{
+ POSIX_API_Control *api;
+ int signo;
+ ISR_Level level;
+
+ api = the_thread->API_Extensions[ THREAD_API_POSIX ];
+
+ /*
+ * If we invoke any user code, there is the possibility that
+ * a new signal has been posted that we should process so we
+ * restart the loop if a signal handler was invoked.
+ *
+ * The first thing done is to check there are any signals to be
+ * processed at all. No point in doing this loop otherwise.
+ */
+
+restart:
+ _ISR_Disable( level );
+ if ( !(~api->signals_blocked &
+ (api->signals_pending | _POSIX_signals_Pending)) ) {
+ _ISR_Enable( level );
+ return;
+ }
+ _ISR_Enable( level );
+
+ for ( signo = SIGRTMIN ; signo <= SIGRTMAX ; signo++ ) {
+
+ if ( _POSIX_signals_Check_signal( api, signo, FALSE ) )
+ goto restart;
+
+ if ( _POSIX_signals_Check_signal( api, signo, TRUE ) )
+ goto restart;
+
+ }
+
+/* XXX - add __SIGFIRSTNOTRT or something like that to newlib signal .h */
+
+ for ( signo = SIGHUP ; signo <= __SIGLASTNOTRT ; signo++ ) {
+
+ if ( _POSIX_signals_Check_signal( api, signo, FALSE ) )
+ goto restart;
+
+ if ( _POSIX_signals_Check_signal( api, signo, TRUE ) )
+ goto restart;
+
+ }
+
+}
+
+/*PAGE
+ *
+ * _POSIX_signals_Manager_Initialization
+ */
+
+void _POSIX_signals_Manager_Initialization(
+ int maximum_queued_signals
+)
+{
+ uint32_t signo;
+
+ /*
+ * Ensure we have the same number of vectors and default vector entries
+ */
+
+ assert(
+ sizeof(_POSIX_signals_Vectors) == sizeof(_POSIX_signals_Default_vectors)
+ );
+
+ memcpy(
+ _POSIX_signals_Vectors,
+ _POSIX_signals_Default_vectors,
+ sizeof( _POSIX_signals_Vectors )
+ );
+
+ /*
+ * Initialize the set of pending signals for the entire process
+ */
+
+ sigemptyset( &_POSIX_signals_Pending );
+
+ /*
+ * Initialize the queue we use to block for signals
+ */
+
+ _Thread_queue_Initialize(
+ &_POSIX_signals_Wait_queue,
+ THREAD_QUEUE_DISCIPLINE_PRIORITY,
+ STATES_WAITING_FOR_SIGNAL | STATES_INTERRUPTIBLE_BY_SIGNAL,
+ EAGAIN
+ );
+
+ /* XXX status codes */
+
+ /*
+ * Allocate the siginfo pools.
+ */
+
+ for ( signo=1 ; signo<= SIGRTMAX ; signo++ )
+ _Chain_Initialize_empty( &_POSIX_signals_Siginfo[ signo ] );
+
+ _Chain_Initialize(
+ &_POSIX_signals_Inactive_siginfo,
+ _Workspace_Allocate_or_fatal_error(
+ maximum_queued_signals * sizeof( POSIX_signals_Siginfo_node )
+ ),
+ maximum_queued_signals,
+ sizeof( POSIX_signals_Siginfo_node )
+ );
+}
diff --git a/cpukit/posix/src/psignalchecksignal.c b/cpukit/posix/src/psignalchecksignal.c
new file mode 100644
index 0000000000..0da7887afd
--- /dev/null
+++ b/cpukit/posix/src/psignalchecksignal.c
@@ -0,0 +1,93 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/tqdata.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/seterr.h>
+#include <rtems/posix/threadsup.h>
+#include <rtems/posix/psignal.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/time.h>
+#include <stdio.h>
+
+
+/*PAGE
+ *
+ * _POSIX_signals_Check_signal
+ */
+
+boolean _POSIX_signals_Check_signal(
+ POSIX_API_Control *api,
+ int signo,
+ boolean is_global
+)
+{
+ siginfo_t siginfo_struct;
+ sigset_t saved_signals_blocked;
+
+ if ( ! _POSIX_signals_Clear_signals( api, signo, &siginfo_struct,
+ is_global, TRUE ) )
+ return FALSE;
+
+ /*
+ * Since we made a union of these, only one test is necessary but this is
+ * safer.
+ */
+
+ assert( _POSIX_signals_Vectors[ signo ].sa_handler ||
+ _POSIX_signals_Vectors[ signo ].sa_sigaction );
+
+ /*
+ * Just to prevent sending a signal which is currently being ignored.
+ */
+
+ if ( _POSIX_signals_Vectors[ signo ].sa_handler == SIG_IGN )
+ return FALSE;
+
+ /*
+ * Block the signals requested in sa_mask
+ */
+
+ saved_signals_blocked = api->signals_blocked;
+ api->signals_blocked |= _POSIX_signals_Vectors[ signo ].sa_mask;
+
+ /* Here, the signal handler function executes */
+
+ switch ( _POSIX_signals_Vectors[ signo ].sa_flags ) {
+ case SA_SIGINFO:
+/*
+ *
+ * assert( is_global );
+ */
+ (*_POSIX_signals_Vectors[ signo ].sa_sigaction)(
+ signo,
+ &siginfo_struct,
+ NULL /* context is undefined per 1003.1b-1993, p. 66 */
+ );
+ break;
+ default:
+ (*_POSIX_signals_Vectors[ signo ].sa_handler)( signo );
+ break;
+ }
+
+ /*
+ * Restore the previous set of blocked signals
+ */
+
+ api->signals_blocked = saved_signals_blocked;
+
+ return TRUE;
+}
diff --git a/cpukit/posix/src/psignalclearprocesssignals.c b/cpukit/posix/src/psignalclearprocesssignals.c
new file mode 100644
index 0000000000..1ff39534d3
--- /dev/null
+++ b/cpukit/posix/src/psignalclearprocesssignals.c
@@ -0,0 +1,42 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/tqdata.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/seterr.h>
+#include <rtems/posix/threadsup.h>
+#include <rtems/posix/psignal.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/time.h>
+#include <stdio.h>
+
+/*PAGE
+ *
+ * _POSIX_signals_Clear_process_signals
+ */
+
+void _POSIX_signals_Clear_process_signals(
+ sigset_t mask
+)
+{
+ ISR_Level level;
+
+ _ISR_Disable( level );
+ _POSIX_signals_Pending &= ~mask;
+ if ( !_POSIX_signals_Pending )
+ _Thread_Do_post_task_switch_extension--;
+ _ISR_Enable( level );
+}
diff --git a/cpukit/posix/src/psignalclearsignals.c b/cpukit/posix/src/psignalclearsignals.c
new file mode 100644
index 0000000000..a1e397c695
--- /dev/null
+++ b/cpukit/posix/src/psignalclearsignals.c
@@ -0,0 +1,89 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/tqdata.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/seterr.h>
+#include <rtems/posix/threadsup.h>
+#include <rtems/posix/psignal.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/time.h>
+#include <stdio.h>
+
+/*PAGE
+ *
+ * _POSIX_signals_Clear_signals
+ */
+
+boolean _POSIX_signals_Clear_signals(
+ POSIX_API_Control *api,
+ int signo,
+ siginfo_t *info,
+ boolean is_global,
+ boolean check_blocked
+)
+{
+ sigset_t mask;
+ sigset_t signals_blocked;
+ ISR_Level level;
+ boolean do_callout;
+ POSIX_signals_Siginfo_node *psiginfo;
+
+ mask = signo_to_mask( signo );
+
+ do_callout = FALSE;
+
+ /* set blocked signals based on if checking for them, SIGNAL_ALL_MASK
+ * insures that no signals are blocked and all are checked.
+ */
+
+ if ( check_blocked )
+ signals_blocked = ~api->signals_blocked;
+ else
+ signals_blocked = SIGNAL_ALL_MASK;
+
+ /* XXX this is not right for siginfo type signals yet */
+ /* XXX since they can't be cleared the same way */
+
+ _ISR_Disable( level );
+ if ( is_global ) {
+ if ( mask & (_POSIX_signals_Pending & signals_blocked) ) {
+ if ( _POSIX_signals_Vectors[ signo ].sa_flags == SA_SIGINFO ) {
+ psiginfo = (POSIX_signals_Siginfo_node *)
+ _Chain_Get_unprotected( &_POSIX_signals_Siginfo[ signo ] );
+ if ( _Chain_Is_empty( &_POSIX_signals_Siginfo[ signo ] ) )
+ _POSIX_signals_Clear_process_signals( mask );
+ if ( psiginfo ) {
+ *info = psiginfo->Info;
+ _Chain_Append_unprotected(
+ &_POSIX_signals_Inactive_siginfo,
+ &psiginfo->Node
+ );
+ } else
+ do_callout = FALSE;
+ } else
+ _POSIX_signals_Clear_process_signals( mask );
+ do_callout = TRUE;
+ }
+ } else {
+ if ( mask & (api->signals_pending & signals_blocked) ) {
+ api->signals_pending &= ~mask;
+ do_callout = TRUE;
+ }
+ }
+ _ISR_Enable( level );
+ return do_callout;
+}
diff --git a/cpukit/posix/src/psignalsetprocesssignals.c b/cpukit/posix/src/psignalsetprocesssignals.c
new file mode 100644
index 0000000000..65cb51664e
--- /dev/null
+++ b/cpukit/posix/src/psignalsetprocesssignals.c
@@ -0,0 +1,42 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/tqdata.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/seterr.h>
+#include <rtems/posix/threadsup.h>
+#include <rtems/posix/psignal.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/time.h>
+#include <stdio.h>
+
+/*PAGE
+ *
+ * _POSIX_signals_Set_process_signals
+ */
+
+void _POSIX_signals_Set_process_signals(
+ sigset_t mask
+)
+{
+ ISR_Level level;
+
+ _ISR_Disable( level );
+ if ( !_POSIX_signals_Pending )
+ _Thread_Do_post_task_switch_extension++;
+ _POSIX_signals_Pending |= mask;
+ _ISR_Enable( level );
+}
diff --git a/cpukit/posix/src/psignalunblockthread.c b/cpukit/posix/src/psignalunblockthread.c
new file mode 100644
index 0000000000..249d16392a
--- /dev/null
+++ b/cpukit/posix/src/psignalunblockthread.c
@@ -0,0 +1,93 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/tqdata.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/seterr.h>
+#include <rtems/posix/threadsup.h>
+#include <rtems/posix/psignal.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/time.h>
+#include <stdio.h>
+
+
+/*PAGE
+ *
+ * _POSIX_signals_Unblock_thread
+ */
+
+/* XXX this routine could probably be cleaned up */
+boolean _POSIX_signals_Unblock_thread(
+ Thread_Control *the_thread,
+ int signo,
+ siginfo_t *info
+)
+{
+ POSIX_API_Control *api;
+ sigset_t mask;
+ siginfo_t *the_info = NULL;
+
+ api = the_thread->API_Extensions[ THREAD_API_POSIX ];
+
+ mask = signo_to_mask( signo );
+
+ /*
+ * Is the thread is specifically waiting for a signal?
+ */
+
+ if ( _States_Is_interruptible_signal( the_thread->current_state ) ) {
+
+ if ( (the_thread->Wait.option & mask) || (~api->signals_blocked & mask) ) {
+ the_thread->Wait.return_code = EINTR;
+
+ the_info = (siginfo_t *) the_thread->Wait.return_argument;
+
+ if ( !info ) {
+ the_info->si_signo = signo;
+ the_info->si_code = SI_USER;
+ the_info->si_value.sival_int = 0;
+ } else {
+ *the_info = *info;
+ }
+
+ _Thread_queue_Extract_with_proxy( the_thread );
+ return TRUE;
+ }
+
+ /*
+ * This should only be reached via pthread_kill().
+ */
+
+ return FALSE;
+ }
+
+ if ( ~api->signals_blocked & mask ) {
+ the_thread->do_post_task_switch_extension = TRUE;
+
+ if ( the_thread->current_state & STATES_INTERRUPTIBLE_BY_SIGNAL ) {
+ the_thread->Wait.return_code = EINTR;
+ if ( _States_Is_waiting_on_thread_queue(the_thread->current_state) )
+ _Thread_queue_Extract_with_proxy( the_thread );
+ else if ( _States_Is_delaying(the_thread->current_state)){
+ if ( _Watchdog_Is_active( &the_thread->Timer ) )
+ (void) _Watchdog_Remove( &the_thread->Timer );
+ _Thread_Unblock( the_thread );
+ }
+ }
+ }
+ return FALSE;
+
+}
diff --git a/cpukit/posix/src/pthread.c b/cpukit/posix/src/pthread.c
new file mode 100644
index 0000000000..0212f9d6ac
--- /dev/null
+++ b/cpukit/posix/src/pthread.c
@@ -0,0 +1,387 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+#include <limits.h>
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/stack.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/posix/cancel.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/priority.h>
+#include <rtems/posix/psignal.h>
+#include <rtems/posix/config.h>
+#include <rtems/posix/key.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * The default pthreads attributes structure.
+ *
+ * NOTE: Be careful .. if the default attribute set changes,
+ * _POSIX_Threads_Initialize_user_threads will need to be examined.
+ *
+ */
+
+const pthread_attr_t _POSIX_Threads_Default_attributes = {
+ TRUE, /* is_initialized */
+ NULL, /* stackaddr */
+ PTHREAD_MINIMUM_STACK_SIZE, /* stacksize */
+ PTHREAD_SCOPE_PROCESS, /* contentionscope */
+ PTHREAD_INHERIT_SCHED, /* inheritsched */
+ SCHED_FIFO, /* schedpolicy */
+ { /* schedparam */
+ 2, /* sched_priority */
+ 0, /* ss_low_priority */
+ { 0L, 0 }, /* ss_replenish_period */
+ { 0L, 0 } /* ss_initial_budget */
+ },
+ PTHREAD_CREATE_JOINABLE, /* detachstate */
+ 1 /* cputime_clock_allowed */
+};
+
+/*PAGE
+ *
+ * _POSIX_Threads_Sporadic_budget_TSR
+ */
+
+void _POSIX_Threads_Sporadic_budget_TSR(
+ Objects_Id id,
+ void *argument
+)
+{
+ uint32_t ticks;
+ uint32_t new_priority;
+ Thread_Control *the_thread;
+ POSIX_API_Control *api;
+
+ the_thread = argument;
+
+ api = the_thread->API_Extensions[ THREAD_API_POSIX ];
+
+ ticks = _POSIX_Timespec_to_interval( &api->schedparam.ss_initial_budget );
+
+ if ( !ticks )
+ ticks = 1;
+
+ the_thread->cpu_time_budget = ticks;
+
+ new_priority = _POSIX_Priority_To_core( api->ss_high_priority );
+ the_thread->real_priority = new_priority;
+
+ if ( the_thread->resource_count == 0 ||
+ the_thread->current_priority > new_priority )
+ _Thread_Change_priority( the_thread, new_priority, TRUE );
+
+ ticks = _POSIX_Timespec_to_interval( &api->schedparam.ss_replenish_period );
+
+ if ( !ticks )
+ ticks = 1;
+
+ _Watchdog_Insert_ticks( &api->Sporadic_timer, ticks );
+}
+
+/*PAGE
+ *
+ * _POSIX_Threads_Sporadic_budget_callout
+ */
+
+void _POSIX_Threads_Sporadic_budget_callout(
+ Thread_Control *the_thread
+)
+{
+ POSIX_API_Control *api;
+ uint32_t new_priority;
+
+ api = the_thread->API_Extensions[ THREAD_API_POSIX ];
+
+ /*
+ * This will prevent the thread from consuming its entire "budget"
+ * while at low priority.
+ */
+
+
+ the_thread->cpu_time_budget = 0xFFFFFFFF; /* XXX should be based on MAX_U32 */
+
+ new_priority = _POSIX_Priority_To_core( api->schedparam.ss_low_priority );
+ the_thread->real_priority = new_priority;
+
+ if ( the_thread->resource_count == 0 ||
+ the_thread->current_priority > new_priority )
+ _Thread_Change_priority( the_thread, new_priority, TRUE );
+}
+
+/*PAGE
+ *
+ * _POSIX_Threads_Create_extension
+ *
+ * XXX
+ */
+
+boolean _POSIX_Threads_Create_extension(
+ Thread_Control *executing,
+ Thread_Control *created
+)
+{
+ POSIX_API_Control *api;
+ POSIX_API_Control *executing_api;
+
+ api = _Workspace_Allocate( sizeof( POSIX_API_Control ) );
+
+ if ( !api )
+ return FALSE;
+
+ created->API_Extensions[ THREAD_API_POSIX ] = api;
+
+ /* XXX check all fields are touched */
+ api->Attributes = _POSIX_Threads_Default_attributes;
+ api->detachstate = _POSIX_Threads_Default_attributes.detachstate;
+ api->schedpolicy = _POSIX_Threads_Default_attributes.schedpolicy;
+ api->schedparam = _POSIX_Threads_Default_attributes.schedparam;
+ api->schedparam.sched_priority =
+ _POSIX_Priority_From_core( created->current_priority );
+
+ /*
+ * POSIX 1003.1 1996, 18.2.2.2
+ */
+ api->cancelation_requested = 0;
+ api->cancelability_state = PTHREAD_CANCEL_ENABLE;
+ api->cancelability_type = PTHREAD_CANCEL_DEFERRED;
+ _Chain_Initialize_empty (&api->Cancellation_Handlers);
+
+ /*
+ * If the thread is not a posix thread, then all posix signals are blocked
+ * by default.
+ */
+
+ /* XXX use signal constants */
+ api->signals_pending = 0;
+ if ( _Objects_Get_API( created->Object.id ) == OBJECTS_POSIX_API &&
+ _Objects_Get_class( created->Object.id ) == 1 ) {
+ executing_api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
+ api->signals_blocked = api->signals_blocked;
+ } else
+ api->signals_blocked = 0xffffffff;
+
+ _Thread_queue_Initialize(
+ &api->Join_List,
+ THREAD_QUEUE_DISCIPLINE_FIFO,
+ STATES_WAITING_FOR_JOIN_AT_EXIT,
+ 0
+ );
+
+ _Watchdog_Initialize(
+ &api->Sporadic_timer,
+ _POSIX_Threads_Sporadic_budget_TSR,
+ created->Object.id,
+ created
+ );
+
+ return TRUE;
+}
+
+/*PAGE
+ *
+ * _POSIX_Threads_Delete_extension
+ */
+
+User_extensions_routine _POSIX_Threads_Delete_extension(
+ Thread_Control *executing,
+ Thread_Control *deleted
+)
+{
+ Thread_Control *the_thread;
+ POSIX_API_Control *api;
+ void **value_ptr;
+
+ api = deleted->API_Extensions[ THREAD_API_POSIX ];
+
+ /*
+ * Run the POSIX cancellation handlers
+ */
+
+ _POSIX_Keys_Run_destructors( deleted );
+
+ /*
+ * Wakeup all the tasks which joined with this one
+ */
+
+ value_ptr = (void **) deleted->Wait.return_argument;
+
+ while ( (the_thread = _Thread_queue_Dequeue( &api->Join_List )) )
+ *(void **)the_thread->Wait.return_argument = value_ptr;
+
+ if ( api->schedpolicy == SCHED_SPORADIC )
+ (void) _Watchdog_Remove( &api->Sporadic_timer );
+
+ deleted->API_Extensions[ THREAD_API_POSIX ] = NULL;
+
+ (void) _Workspace_Free( api );
+}
+
+/*
+ *
+ * _POSIX_Threads_Exitted_extension
+ */
+
+User_extensions_routine _POSIX_Threads_Exitted_extension(
+ Thread_Control *executing
+)
+{
+ pthread_exit( executing->Wait.return_argument );
+}
+
+/*PAGE
+ *
+ * _POSIX_Threads_Initialize_user_threads
+ *
+ * This routine creates and starts all configured user
+ * initialzation threads.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ */
+
+void _POSIX_Threads_Initialize_user_threads( void )
+{
+ int status;
+ uint32_t index;
+ uint32_t maximum;
+ posix_initialization_threads_table *user_threads;
+ pthread_t thread_id;
+ pthread_attr_t attr;
+
+ user_threads = _POSIX_Threads_User_initialization_threads;
+ maximum = _POSIX_Threads_Number_of_initialization_threads;
+
+ if ( !user_threads || maximum == 0 )
+ return;
+
+ /*
+ * Be careful .. if the default attribute set changes, this may need to.
+ *
+ * Setting the attributes explicitly is critical, since we don't want
+ * to inherit the idle tasks attributes.
+ */
+
+ for ( index=0 ; index < maximum ; index++ ) {
+ status = pthread_attr_init( &attr );
+ assert( !status );
+
+ status = pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED );
+ assert( !status );
+
+ status = pthread_attr_setstacksize( &attr, user_threads[ index ].stack_size);
+ assert( !status );
+
+ status = pthread_create(
+ &thread_id,
+ &attr,
+ user_threads[ index ].thread_entry,
+ NULL
+ );
+ assert( !status );
+ }
+}
+
+/*PAGE
+ *
+ * API Extension control structures
+ */
+
+API_extensions_Control _POSIX_Threads_API_extensions = {
+ { NULL, NULL },
+ NULL, /* predriver */
+ _POSIX_Threads_Initialize_user_threads, /* postdriver */
+ _POSIX_signals_Post_switch_extension, /* post switch */
+};
+
+User_extensions_Control _POSIX_Threads_User_extensions = {
+ { NULL, NULL },
+ { { NULL, NULL }, NULL },
+ { _POSIX_Threads_Create_extension, /* create */
+ NULL, /* start */
+ NULL, /* restart */
+ _POSIX_Threads_Delete_extension, /* delete */
+ NULL, /* switch */
+ NULL, /* begin */
+ _POSIX_Threads_Exitted_extension, /* exitted */
+ NULL /* fatal */
+ }
+};
+
+/*PAGE
+ *
+ * _POSIX_Threads_Manager_initialization
+ *
+ * This routine initializes all threads manager related data structures.
+ *
+ * Input parameters:
+ * maximum_pthreads - maximum configured pthreads
+ *
+ * Output parameters: NONE
+ */
+
+void _POSIX_Threads_Manager_initialization(
+ uint32_t maximum_pthreads,
+ uint32_t number_of_initialization_threads,
+ posix_initialization_threads_table *user_threads
+
+)
+{
+ _POSIX_Threads_Number_of_initialization_threads =
+ number_of_initialization_threads;
+ _POSIX_Threads_User_initialization_threads = user_threads;
+
+ /*
+ * There may not be any POSIX initialization threads configured.
+ */
+
+#if 0
+ if ( user_threads == NULL || number_of_initialization_threads == 0 )
+ _Internal_error_Occurred( INTERNAL_ERROR_POSIX_API, TRUE, EINVAL );
+#endif
+
+ _Objects_Initialize_information(
+ &_POSIX_Threads_Information, /* object information table */
+ OBJECTS_POSIX_API, /* object API */
+ OBJECTS_POSIX_THREADS, /* object class */
+ maximum_pthreads, /* maximum objects of this class */
+ sizeof( Thread_Control ),
+ /* size of this object's control block */
+ FALSE, /* TRUE if names for this object are strings */
+ 0 /* maximum length of each object's name */
+#if defined(RTEMS_MULTIPROCESSING)
+ ,
+ FALSE, /* TRUE if this is a global object class */
+ NULL /* Proxy extraction support callout */
+#endif
+ );
+
+ /*
+ * Add all the extensions for this API
+ */
+
+ _User_extensions_Add_API_set( &_POSIX_Threads_User_extensions );
+
+ _API_extensions_Add( &_POSIX_Threads_API_extensions );
+
+
+ /*
+ * If we supported MP, then here we would ...
+ * Register the MP Process Packet routine.
+ */
+
+}
diff --git a/cpukit/posix/src/pthreadatfork.c b/cpukit/posix/src/pthreadatfork.c
new file mode 100644
index 0000000000..7bc398ed85
--- /dev/null
+++ b/cpukit/posix/src/pthreadatfork.c
@@ -0,0 +1,31 @@
+/*
+ * pthread_atfork() - POSIX 1003.1b 3.1.3
+ *
+ * 3.1.3 Register Fork Handlers, P1003.1c/Draft 10, P1003.1c/Draft 10, p. 27
+ *
+ * RTEMS does not support processes, so we fall under this and do not
+ * provide this routine:
+ *
+ * "Either the implementation shall support the pthread_atfork() function
+ * as described above or the pthread_atfork() funciton shall not be
+ * provided."
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <errno.h>
+
+int pthread_atfork(
+ void (*prepare)(void),
+ void (*parent)(void),
+ void (*child)(void)
+)
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/cpukit/posix/src/pthreadattrdestroy.c b/cpukit/posix/src/pthreadattrdestroy.c
new file mode 100644
index 0000000000..9b5858ff60
--- /dev/null
+++ b/cpukit/posix/src/pthreadattrdestroy.c
@@ -0,0 +1,32 @@
+/*
+ * 16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+
+int pthread_attr_destroy(
+ pthread_attr_t *attr
+)
+{
+ if ( !attr || !attr->is_initialized )
+ return EINVAL;
+
+ attr->is_initialized = FALSE;
+ return 0;
+}
diff --git a/cpukit/posix/src/pthreadattrgetdetachstate.c b/cpukit/posix/src/pthreadattrgetdetachstate.c
new file mode 100644
index 0000000000..bd8b9a02ae
--- /dev/null
+++ b/cpukit/posix/src/pthreadattrgetdetachstate.c
@@ -0,0 +1,31 @@
+/*
+ * 16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+int pthread_attr_getdetachstate(
+ const pthread_attr_t *attr,
+ int *detachstate
+)
+{
+ if ( !attr || !attr->is_initialized || !detachstate )
+ return EINVAL;
+
+ *detachstate = attr->detachstate;
+ return 0;
+}
diff --git a/cpukit/posix/src/pthreadattrgetinheritsched.c b/cpukit/posix/src/pthreadattrgetinheritsched.c
new file mode 100644
index 0000000000..e924f2d26c
--- /dev/null
+++ b/cpukit/posix/src/pthreadattrgetinheritsched.c
@@ -0,0 +1,31 @@
+/*
+ * 13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+int pthread_attr_getinheritsched(
+ const pthread_attr_t *attr,
+ int *inheritsched
+)
+{
+ if ( !attr || !attr->is_initialized || !inheritsched )
+ return EINVAL;
+
+ *inheritsched = attr->inheritsched;
+ return 0;
+}
diff --git a/cpukit/posix/src/pthreadattrgetschedparam.c b/cpukit/posix/src/pthreadattrgetschedparam.c
new file mode 100644
index 0000000000..2ec95d729e
--- /dev/null
+++ b/cpukit/posix/src/pthreadattrgetschedparam.c
@@ -0,0 +1,31 @@
+/*
+ * 13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+int pthread_attr_getschedparam(
+ const pthread_attr_t *attr,
+ struct sched_param *param
+)
+{
+ if ( !attr || !attr->is_initialized || !param )
+ return EINVAL;
+
+ *param = attr->schedparam;
+ return 0;
+}
diff --git a/cpukit/posix/src/pthreadattrgetschedpolicy.c b/cpukit/posix/src/pthreadattrgetschedpolicy.c
new file mode 100644
index 0000000000..571430e953
--- /dev/null
+++ b/cpukit/posix/src/pthreadattrgetschedpolicy.c
@@ -0,0 +1,31 @@
+/*
+ * 13.5.1 Thread Creation Scheduling Parameters, P1003.1c/Draft 10, p. 120
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+int pthread_attr_getschedpolicy(
+ const pthread_attr_t *attr,
+ int *policy
+)
+{
+ if ( !attr || !attr->is_initialized || !policy )
+ return EINVAL;
+
+ *policy = attr->schedpolicy;
+ return 0;
+}
diff --git a/cpukit/posix/src/pthreadattrgetscope.c b/cpukit/posix/src/pthreadattrgetscope.c
new file mode 100644
index 0000000000..2d74dc30ba
--- /dev/null
+++ b/cpukit/posix/src/pthreadattrgetscope.c
@@ -0,0 +1,31 @@
+/*
+ * 13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+int pthread_attr_getscope(
+ const pthread_attr_t *attr,
+ int *contentionscope
+)
+{
+ if ( !attr || !attr->is_initialized || !contentionscope )
+ return EINVAL;
+
+ *contentionscope = attr->contentionscope;
+ return 0;
+}
diff --git a/cpukit/posix/src/pthreadattrgetstackaddr.c b/cpukit/posix/src/pthreadattrgetstackaddr.c
new file mode 100644
index 0000000000..3ca66112aa
--- /dev/null
+++ b/cpukit/posix/src/pthreadattrgetstackaddr.c
@@ -0,0 +1,31 @@
+/*
+ * 16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+int pthread_attr_getstackaddr(
+ const pthread_attr_t *attr,
+ void **stackaddr
+)
+{
+ if ( !attr || !attr->is_initialized || !stackaddr )
+ return EINVAL;
+
+ *stackaddr = attr->stackaddr;
+ return 0;
+}
diff --git a/cpukit/posix/src/pthreadattrgetstacksize.c b/cpukit/posix/src/pthreadattrgetstacksize.c
new file mode 100644
index 0000000000..f7f23c6dd6
--- /dev/null
+++ b/cpukit/posix/src/pthreadattrgetstacksize.c
@@ -0,0 +1,31 @@
+/*
+ * 16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+int pthread_attr_getstacksize(
+ const pthread_attr_t *attr,
+ size_t *stacksize
+)
+{
+ if ( !attr || !attr->is_initialized || !stacksize )
+ return EINVAL;
+
+ *stacksize = attr->stacksize;
+ return 0;
+}
diff --git a/cpukit/posix/src/pthreadattrinit.c b/cpukit/posix/src/pthreadattrinit.c
new file mode 100644
index 0000000000..1862623e3e
--- /dev/null
+++ b/cpukit/posix/src/pthreadattrinit.c
@@ -0,0 +1,33 @@
+/*
+ * 16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/posix/pthread.h>
+
+int pthread_attr_init(
+ pthread_attr_t *attr
+)
+{
+ if ( !attr )
+ return EINVAL;
+
+ *attr = _POSIX_Threads_Default_attributes;
+ return 0;
+}
diff --git a/cpukit/posix/src/pthreadattrsetdetachstate.c b/cpukit/posix/src/pthreadattrsetdetachstate.c
new file mode 100644
index 0000000000..cb29f44d3a
--- /dev/null
+++ b/cpukit/posix/src/pthreadattrsetdetachstate.c
@@ -0,0 +1,38 @@
+/*
+ * 16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+int pthread_attr_setdetachstate(
+ pthread_attr_t *attr,
+ int detachstate
+)
+{
+ if ( !attr || !attr->is_initialized )
+ return EINVAL;
+
+ switch ( detachstate ) {
+ case PTHREAD_CREATE_DETACHED:
+ case PTHREAD_CREATE_JOINABLE:
+ attr->detachstate = detachstate;
+ return 0;
+
+ default:
+ return EINVAL;
+ }
+}
diff --git a/cpukit/posix/src/pthreadattrsetinheritsched.c b/cpukit/posix/src/pthreadattrsetinheritsched.c
new file mode 100644
index 0000000000..0819eb48b7
--- /dev/null
+++ b/cpukit/posix/src/pthreadattrsetinheritsched.c
@@ -0,0 +1,41 @@
+/*
+ * 13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/posix/pthread.h>
+
+int pthread_attr_setinheritsched(
+ pthread_attr_t *attr,
+ int inheritsched
+)
+{
+ if ( !attr || !attr->is_initialized )
+ return EINVAL;
+
+ switch ( inheritsched ) {
+ case PTHREAD_INHERIT_SCHED:
+ case PTHREAD_EXPLICIT_SCHED:
+ attr->inheritsched = inheritsched;
+ return 0;
+
+ default:
+ return ENOTSUP;
+ }
+}
diff --git a/cpukit/posix/src/pthreadattrsetschedparam.c b/cpukit/posix/src/pthreadattrsetschedparam.c
new file mode 100644
index 0000000000..cb310a9893
--- /dev/null
+++ b/cpukit/posix/src/pthreadattrsetschedparam.c
@@ -0,0 +1,31 @@
+/*
+ * 13.5.1 Thread Creation Scheduling Parameters, P1003.1c/Draft 10, p. 120
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+int pthread_attr_setschedparam(
+ pthread_attr_t *attr,
+ const struct sched_param *param
+)
+{
+ if ( !attr || !attr->is_initialized || !param )
+ return EINVAL;
+
+ attr->schedparam = *param;
+ return 0;
+}
diff --git a/cpukit/posix/src/pthreadattrsetschedpolicy.c b/cpukit/posix/src/pthreadattrsetschedpolicy.c
new file mode 100644
index 0000000000..ab61e000ed
--- /dev/null
+++ b/cpukit/posix/src/pthreadattrsetschedpolicy.c
@@ -0,0 +1,43 @@
+/*
+ * 13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/posix/pthread.h>
+
+int pthread_attr_setschedpolicy(
+ pthread_attr_t *attr,
+ int policy
+)
+{
+ if ( !attr || !attr->is_initialized )
+ return EINVAL;
+
+ switch ( policy ) {
+ case SCHED_OTHER:
+ case SCHED_FIFO:
+ case SCHED_RR:
+ case SCHED_SPORADIC:
+ attr->schedpolicy = policy;
+ return 0;
+
+ default:
+ return ENOTSUP;
+ }
+}
diff --git a/cpukit/posix/src/pthreadattrsetscope.c b/cpukit/posix/src/pthreadattrsetscope.c
new file mode 100644
index 0000000000..8c6d1c3f9c
--- /dev/null
+++ b/cpukit/posix/src/pthreadattrsetscope.c
@@ -0,0 +1,43 @@
+/*
+ * 13.5.1 Thread Creation Scheduling Attributes, P1003.1c/Draft 10, p. 120
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/posix/pthread.h>
+
+int pthread_attr_setscope(
+ pthread_attr_t *attr,
+ int contentionscope
+)
+{
+ if ( !attr || !attr->is_initialized )
+ return EINVAL;
+
+ switch ( contentionscope ) {
+ case PTHREAD_SCOPE_PROCESS:
+ attr->contentionscope = contentionscope;
+ return 0;
+
+ case PTHREAD_SCOPE_SYSTEM:
+ return ENOTSUP;
+
+ default:
+ return EINVAL;
+ }
+}
diff --git a/cpukit/posix/src/pthreadattrsetstackaddr.c b/cpukit/posix/src/pthreadattrsetstackaddr.c
new file mode 100644
index 0000000000..b7ed212546
--- /dev/null
+++ b/cpukit/posix/src/pthreadattrsetstackaddr.c
@@ -0,0 +1,31 @@
+/*
+ * 16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+int pthread_attr_setstackaddr(
+ pthread_attr_t *attr,
+ void *stackaddr
+)
+{
+ if ( !attr || !attr->is_initialized )
+ return EINVAL;
+
+ attr->stackaddr = stackaddr;
+ return 0;
+}
diff --git a/cpukit/posix/src/pthreadattrsetstacksize.c b/cpukit/posix/src/pthreadattrsetstacksize.c
new file mode 100644
index 0000000000..9598a8a7d7
--- /dev/null
+++ b/cpukit/posix/src/pthreadattrsetstacksize.c
@@ -0,0 +1,37 @@
+/*
+ * 16.1.1 Thread Creation Attributes, P1003.1c/Draft 10, p, 140
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/posix/pthread.h>
+
+int pthread_attr_setstacksize(
+ pthread_attr_t *attr,
+ size_t stacksize
+)
+{
+ if ( !attr || !attr->is_initialized )
+ return EINVAL;
+
+ if (stacksize < PTHREAD_MINIMUM_STACK_SIZE)
+ attr->stacksize = PTHREAD_MINIMUM_STACK_SIZE;
+ else
+ attr->stacksize = stacksize;
+ return 0;
+}
diff --git a/cpukit/posix/src/pthreadcreate.c b/cpukit/posix/src/pthreadcreate.c
new file mode 100644
index 0000000000..61a59c01f8
--- /dev/null
+++ b/cpukit/posix/src/pthreadcreate.c
@@ -0,0 +1,256 @@
+/*
+ * 16.1.2 Thread Creation, P1003.1c/Draft 10, p. 144
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/thread.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/priority.h>
+#include <rtems/posix/time.h>
+
+int pthread_create(
+ pthread_t *thread,
+ const pthread_attr_t *attr,
+ void *(*start_routine)( void * ),
+ void *arg
+)
+{
+ const pthread_attr_t *the_attr;
+ Priority_Control core_priority;
+ Thread_CPU_budget_algorithms budget_algorithm;
+ Thread_CPU_budget_algorithm_callout budget_callout;
+ boolean is_fp;
+ boolean status;
+ Thread_Control *the_thread;
+ POSIX_API_Control *api;
+ int schedpolicy = SCHED_RR;
+ struct sched_param schedparam;
+
+ the_attr = (attr) ? attr : &_POSIX_Threads_Default_attributes;
+
+ if ( !the_attr->is_initialized )
+ return EINVAL;
+
+ /*
+ * Core Thread Initialize insures we get the minimum amount of
+ * stack space if it is allowed to allocate it itself.
+ */
+
+ if ( the_attr->stackaddr && !_Stack_Is_enough( the_attr->stacksize ) )
+ return EINVAL;
+
+#if 0
+ int cputime_clock_allowed; /* see time.h */
+ POSIX_NOT_IMPLEMENTED();
+#endif
+
+ /*
+ * P1003.1c/Draft 10, p. 121.
+ *
+ * If inheritsched is set to PTHREAD_INHERIT_SCHED, then this thread
+ * inherits scheduling attributes from the creating thread. If it is
+ * PTHREAD_EXPLICIT_SCHED, then scheduling parameters come from the
+ * attributes structure.
+ */
+
+ switch ( the_attr->inheritsched ) {
+ case PTHREAD_INHERIT_SCHED:
+ api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
+ schedpolicy = api->schedpolicy;
+ schedparam = api->schedparam;
+ break;
+
+ case PTHREAD_EXPLICIT_SCHED:
+ schedpolicy = the_attr->schedpolicy;
+ schedparam = the_attr->schedparam;
+ break;
+
+ default:
+ return EINVAL;
+ }
+
+ /*
+ * Check the contentionscope since rtems only supports PROCESS wide
+ * contention (i.e. no system wide contention).
+ */
+
+ if ( the_attr->contentionscope != PTHREAD_SCOPE_PROCESS )
+ return ENOTSUP;
+
+ /*
+ * Interpret the scheduling parameters.
+ */
+
+ if ( !_POSIX_Priority_Is_valid( schedparam.sched_priority ) )
+ return EINVAL;
+
+ core_priority = _POSIX_Priority_To_core( schedparam.sched_priority );
+
+ /*
+ * Set the core scheduling policy information.
+ */
+
+ budget_callout = NULL;
+ budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE;
+
+ switch ( schedpolicy ) {
+ case SCHED_OTHER:
+ budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE;
+ break;
+
+ case SCHED_FIFO:
+ budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE;
+ break;
+
+ case SCHED_RR:
+ budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE;
+ break;
+
+ case SCHED_SPORADIC:
+ budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_CALLOUT;
+ budget_callout = _POSIX_Threads_Sporadic_budget_callout;
+
+ if ( _POSIX_Timespec_to_interval( &schedparam.ss_replenish_period ) <
+ _POSIX_Timespec_to_interval( &schedparam.ss_initial_budget ) )
+ return EINVAL;
+
+ if ( !_POSIX_Priority_Is_valid( schedparam.ss_low_priority ) )
+ return EINVAL;
+
+ break;
+
+ default:
+ return EINVAL;
+ }
+
+ /*
+ * Currently all POSIX threads are floating point if the hardware
+ * supports it.
+ */
+
+
+#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+ is_fp = TRUE;
+#else
+ is_fp = FALSE;
+#endif
+
+ /*
+ * Disable dispatch for protection
+ */
+
+ _Thread_Disable_dispatch();
+
+ /*
+ * Allocate the thread control block.
+ *
+ * NOTE: Global threads are not currently supported.
+ */
+
+ the_thread = _POSIX_Threads_Allocate();
+
+ if ( !the_thread ) {
+ _Thread_Enable_dispatch();
+ return EAGAIN;
+ }
+
+ /*
+ * Initialize the core thread for this task.
+ */
+
+ status = _Thread_Initialize(
+ &_POSIX_Threads_Information,
+ the_thread,
+ the_attr->stackaddr,
+ the_attr->stacksize,
+ is_fp,
+ core_priority,
+ TRUE, /* preemptible */
+ budget_algorithm,
+ budget_callout,
+ 0, /* isr level */
+ NULL /* posix threads don't have a name */
+ );
+
+ if ( !status ) {
+ _POSIX_Threads_Free( the_thread );
+ _Thread_Enable_dispatch();
+ return EAGAIN;
+ }
+
+ /*
+ * finish initializing the per API structure
+ */
+
+
+ api = the_thread->API_Extensions[ THREAD_API_POSIX ];
+
+ api->Attributes = *the_attr;
+ api->detachstate = the_attr->detachstate;
+ api->schedpolicy = schedpolicy;
+ api->schedparam = schedparam;
+
+ /*
+ * This insures we evaluate the process-wide signals pending when we
+ * first run.
+ *
+ * NOTE: Since the thread starts with all unblocked, this is necessary.
+ */
+
+ the_thread->do_post_task_switch_extension = TRUE;
+
+ /*
+ * POSIX threads are allocated and started in one operation.
+ */
+
+ status = _Thread_Start(
+ the_thread,
+ THREAD_START_POINTER,
+ start_routine,
+ arg,
+ 0 /* unused */
+ );
+
+ if ( schedpolicy == SCHED_SPORADIC ) {
+ _Watchdog_Insert_ticks(
+ &api->Sporadic_timer,
+ _POSIX_Timespec_to_interval( &api->schedparam.ss_replenish_period )
+ );
+ }
+
+ /*
+ * _Thread_Start only fails if the thread was in the incorrect state
+ */
+
+ if ( !status ) {
+ _POSIX_Threads_Free( the_thread );
+ _Thread_Enable_dispatch();
+ return EINVAL;
+ }
+
+ /*
+ * Return the id and indicate we successfully created the thread
+ */
+
+ *thread = the_thread->Object.id;
+
+ _Thread_Enable_dispatch();
+
+ return 0;
+}
diff --git a/cpukit/posix/src/pthreaddetach.c b/cpukit/posix/src/pthreaddetach.c
new file mode 100644
index 0000000000..7d7629f18a
--- /dev/null
+++ b/cpukit/posix/src/pthreaddetach.c
@@ -0,0 +1,47 @@
+/*
+ * 16.1.4 Detaching a Thread, P1003.1c/Draft 10, p. 149
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/thread.h>
+#include <rtems/posix/pthread.h>
+
+int pthread_detach(
+ pthread_t thread
+)
+{
+ register Thread_Control *the_thread;
+ POSIX_API_Control *api;
+ Objects_Locations location;
+
+ the_thread = _POSIX_Threads_Get( thread, &location );
+ switch ( location ) {
+ case OBJECTS_ERROR:
+ case OBJECTS_REMOTE:
+ return ESRCH;
+ case OBJECTS_LOCAL:
+
+ api = the_thread->API_Extensions[ THREAD_API_POSIX ];
+ api->detachstate = PTHREAD_CREATE_DETACHED;
+ _Thread_Enable_dispatch();
+ return 0;
+ }
+
+ return POSIX_BOTTOM_REACHED();
+}
diff --git a/cpukit/posix/src/pthreadequal.c b/cpukit/posix/src/pthreadequal.c
new file mode 100644
index 0000000000..39136cc388
--- /dev/null
+++ b/cpukit/posix/src/pthreadequal.c
@@ -0,0 +1,82 @@
+/*
+ * 16.1.7 Compare Thread IDs, p1003.1c/Draft 10, p. 153
+ *
+ * NOTE: POSIX does not define the behavior when either thread id is invalid.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/score/thread.h>
+
+int pthread_equal(
+ pthread_t t1,
+ pthread_t t2
+)
+{
+ /*
+ * If the system is configured for debug, then we will do everything we
+ * can to insure that both ids are valid. Otherwise, we will do the
+ * cheapest possible thing to determine if they are equal.
+ */
+
+#ifndef RTEMS_DEBUG
+ return _Objects_Are_ids_equal( t1, t2 );
+#else
+ int status;
+ Objects_Locations location;
+
+ /*
+ * By default this is not a match.
+ */
+
+ status = 0;
+
+ /*
+ * Validate the first id and return 0 if it is not valid
+ */
+
+ (void) _POSIX_Threads_Get( t1, &location );
+ switch ( location ) {
+ case OBJECTS_ERROR:
+ case OBJECTS_REMOTE:
+ break;
+
+ case OBJECTS_LOCAL:
+
+ /*
+ * Validate the second id and return 0 if it is not valid
+ */
+
+ (void) _POSIX_Threads_Get( t2, &location );
+ switch ( location ) {
+ case OBJECTS_ERROR:
+ case OBJECTS_REMOTE:
+ break;
+ case OBJECTS_LOCAL:
+ status = _Objects_Are_ids_equal( t1, t2 );
+ break;
+ }
+ _Thread_Unnest_dispatch();
+ break;
+ }
+
+ _Thread_Enable_dispatch();
+ return status;
+#endif
+}
diff --git a/cpukit/posix/src/pthreadexit.c b/cpukit/posix/src/pthreadexit.c
new file mode 100644
index 0000000000..8346f139b8
--- /dev/null
+++ b/cpukit/posix/src/pthreadexit.c
@@ -0,0 +1,48 @@
+/*
+ * 16.1.5.1 Thread Termination, p1003.1c/Draft 10, p. 150
+ *
+ * NOTE: Key destructors are executed in the POSIX api delete extension.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+#include <assert.h>
+
+#include <rtems/system.h>
+#include <rtems/score/thread.h>
+#include <rtems/posix/pthread.h>
+
+void pthread_exit(
+ void *value_ptr
+)
+{
+ Objects_Information *the_information;
+
+ the_information = _Objects_Get_information( _Thread_Executing->Object.id );
+
+ /* This should never happen if _Thread_Get() works right */
+ assert( the_information );
+
+ _Thread_Disable_dispatch();
+
+ _Thread_Executing->Wait.return_argument = value_ptr;
+
+ _Thread_Close( the_information, _Thread_Executing );
+
+ _POSIX_Threads_Free( _Thread_Executing );
+
+ _Thread_Enable_dispatch();
+}
diff --git a/cpukit/posix/src/pthreadgetcpuclockid.c b/cpukit/posix/src/pthreadgetcpuclockid.c
new file mode 100644
index 0000000000..7769e4b7c6
--- /dev/null
+++ b/cpukit/posix/src/pthreadgetcpuclockid.c
@@ -0,0 +1,29 @@
+/*
+ * 20.1.6 Accessing a Thread CPU-time Clock, P1003.4b/Draft 8, p. 58
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+
+int pthread_getcpuclockid(
+ pthread_t pid,
+ clockid_t *clock_id
+)
+{
+ return POSIX_NOT_IMPLEMENTED();
+}
diff --git a/cpukit/posix/src/pthreadgetcputime.c b/cpukit/posix/src/pthreadgetcputime.c
new file mode 100644
index 0000000000..7c9bb46c7b
--- /dev/null
+++ b/cpukit/posix/src/pthreadgetcputime.c
@@ -0,0 +1,31 @@
+/*
+ * 20.1.7 CPU-time Clock Thread Creation Attribute, P1003.4b/Draft 8, p. 59
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+int pthread_attr_getcputime(
+ pthread_attr_t *attr,
+ int *clock_allowed
+)
+{
+ if ( !attr || !attr->is_initialized || !clock_allowed )
+ return EINVAL;
+
+ *clock_allowed = attr->cputime_clock_allowed;
+ return 0;
+}
diff --git a/cpukit/posix/src/pthreadgetschedparam.c b/cpukit/posix/src/pthreadgetschedparam.c
new file mode 100644
index 0000000000..8b399b75ba
--- /dev/null
+++ b/cpukit/posix/src/pthreadgetschedparam.c
@@ -0,0 +1,59 @@
+/*
+ * 13.5.2 Dynamic Thread Scheduling Parameters Access,
+ * P1003.1c/Draft 10, p. 124
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/priority.h>
+
+int pthread_getschedparam(
+ pthread_t thread,
+ int *policy,
+ struct sched_param *param
+)
+{
+ Objects_Locations location;
+ POSIX_API_Control *api;
+ register Thread_Control *the_thread;
+
+ if ( !policy || !param )
+ return EINVAL;
+
+ the_thread = _POSIX_Threads_Get( thread, &location );
+ switch ( location ) {
+ case OBJECTS_ERROR:
+ case OBJECTS_REMOTE:
+ return ESRCH;
+ case OBJECTS_LOCAL:
+ api = the_thread->API_Extensions[ THREAD_API_POSIX ];
+ if ( policy )
+ *policy = api->schedpolicy;
+ if ( param ) {
+ *param = api->schedparam;
+ param->sched_priority =
+ _POSIX_Priority_From_core( the_thread->current_priority );
+ }
+ _Thread_Enable_dispatch();
+ return 0;
+ }
+
+ return POSIX_BOTTOM_REACHED();
+
+}
diff --git a/cpukit/posix/src/pthreadjoin.c b/cpukit/posix/src/pthreadjoin.c
new file mode 100644
index 0000000000..669028335c
--- /dev/null
+++ b/cpukit/posix/src/pthreadjoin.c
@@ -0,0 +1,71 @@
+/*
+ * 16.1.3 Wait for Thread Termination, P1003.1c/Draft 10, p. 147
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/thread.h>
+#include <rtems/posix/pthread.h>
+
+int pthread_join(
+ pthread_t thread,
+ void **value_ptr
+)
+{
+ register Thread_Control *the_thread;
+ POSIX_API_Control *api;
+ Objects_Locations location;
+ void *return_pointer;
+
+ the_thread = _POSIX_Threads_Get( thread, &location );
+ switch ( location ) {
+ case OBJECTS_ERROR:
+ case OBJECTS_REMOTE:
+ return ESRCH;
+ case OBJECTS_LOCAL:
+ api = the_thread->API_Extensions[ THREAD_API_POSIX ];
+
+ if ( api->detachstate == PTHREAD_CREATE_DETACHED ) {
+ _Thread_Enable_dispatch();
+ return EINVAL;
+ }
+
+ if ( _Thread_Is_executing( the_thread ) ) {
+ _Thread_Enable_dispatch();
+ return EDEADLK;
+ }
+
+ /*
+ * Put ourself on the threads join list
+ */
+
+ _Thread_Executing->Wait.return_argument = &return_pointer;
+
+ _Thread_queue_Enter_critical_section( &api->Join_List );
+
+ _Thread_queue_Enqueue( &api->Join_List, WATCHDOG_NO_TIMEOUT );
+
+ _Thread_Enable_dispatch();
+
+ if ( value_ptr )
+ *value_ptr = return_pointer;
+ return 0;
+ }
+
+ return POSIX_BOTTOM_REACHED();
+}
diff --git a/cpukit/posix/src/pthreadkill.c b/cpukit/posix/src/pthreadkill.c
new file mode 100644
index 0000000000..c6624eb8be
--- /dev/null
+++ b/cpukit/posix/src/pthreadkill.c
@@ -0,0 +1,83 @@
+/*
+ * 3.3.10 Send a Signal to a Thread, P1003.1c/D10, p. 43
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <signal.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/psignal.h>
+#include <rtems/score/isr.h>
+#include <rtems/seterr.h>
+
+int pthread_kill(
+ pthread_t thread,
+ int sig
+)
+{
+ POSIX_API_Control *api;
+ Thread_Control *the_thread;
+ Objects_Locations location;
+
+ if ( !sig )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ if ( !is_valid_signo(sig) )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+/* commented out when posix timers added
+ if ( _POSIX_signals_Vectors[ sig ].sa_flags == SA_SIGINFO )
+ rtems_set_errno_and_return_minus_one( ENOSYS );
+*/
+
+ the_thread = _POSIX_Threads_Get( thread, &location );
+ switch ( location ) {
+ case OBJECTS_ERROR:
+ case OBJECTS_REMOTE:
+ rtems_set_errno_and_return_minus_one( ESRCH );
+ case OBJECTS_LOCAL:
+ /*
+ * If sig == 0 then just validate arguments
+ */
+
+ api = the_thread->API_Extensions[ THREAD_API_POSIX ];
+
+ if ( sig ) {
+
+ if ( _POSIX_signals_Vectors[ sig ].sa_handler == SIG_IGN ) {
+ _Thread_Enable_dispatch();
+ return 0;
+ }
+
+ /* XXX critical section */
+
+ api->signals_pending |= signo_to_mask( sig );
+
+ (void) _POSIX_signals_Unblock_thread( the_thread, sig, NULL );
+
+ the_thread->do_post_task_switch_extension = TRUE;
+
+ if ( _ISR_Is_in_progress() && _Thread_Is_executing( the_thread ) )
+ _ISR_Signals_to_thread_executing = TRUE;
+ }
+ _Thread_Enable_dispatch();
+ return 0;
+ }
+
+ return POSIX_BOTTOM_REACHED();
+}
diff --git a/cpukit/posix/src/pthreadonce.c b/cpukit/posix/src/pthreadonce.c
new file mode 100644
index 0000000000..b1371c8def
--- /dev/null
+++ b/cpukit/posix/src/pthreadonce.c
@@ -0,0 +1,44 @@
+/*
+ * 16.1.8 Dynamic Package Initialization, P1003.1c/Draft 10, p. 154
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems.h>
+#include <rtems/system.h>
+#include <rtems/score/thread.h>
+
+int pthread_once(
+ pthread_once_t *once_control,
+ void (*init_routine)(void)
+)
+{
+ if ( !once_control || !init_routine )
+ return EINVAL;
+
+ if ( !once_control->init_executed ) {
+ rtems_mode saveMode;
+ rtems_task_mode(RTEMS_NO_PREEMPT, RTEMS_PREEMPT_MASK, &saveMode);
+ if ( !once_control->init_executed ) {
+ once_control->is_initialized = TRUE;
+ once_control->init_executed = TRUE;
+ (*init_routine)();
+ }
+ rtems_task_mode(saveMode, RTEMS_PREEMPT_MASK, &saveMode);
+ }
+ return 0;
+}
diff --git a/cpukit/posix/src/pthreadself.c b/cpukit/posix/src/pthreadself.c
new file mode 100644
index 0000000000..c1baf85177
--- /dev/null
+++ b/cpukit/posix/src/pthreadself.c
@@ -0,0 +1,27 @@
+/*
+ * 16.1.6 Get Calling Thread's ID, p1003.1c/Draft 10, p. 152
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/thread.h>
+
+pthread_t pthread_self( void )
+{
+ return _Thread_Executing->Object.id;
+}
diff --git a/cpukit/posix/src/pthreadsetcputime.c b/cpukit/posix/src/pthreadsetcputime.c
new file mode 100644
index 0000000000..70b9594ab9
--- /dev/null
+++ b/cpukit/posix/src/pthreadsetcputime.c
@@ -0,0 +1,38 @@
+/*
+ * 20.1.7 CPU-time Clock Thread Creation Attribute, P1003.4b/Draft 8, p. 59
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+int pthread_attr_setcputime(
+ pthread_attr_t *attr,
+ int clock_allowed
+)
+{
+ if ( !attr || !attr->is_initialized )
+ return EINVAL;
+
+ switch ( clock_allowed ) {
+ case CLOCK_ENABLED:
+ case CLOCK_DISABLED:
+ attr->cputime_clock_allowed = clock_allowed;
+ return 0;
+
+ default:
+ return EINVAL;
+ }
+}
diff --git a/cpukit/posix/src/pthreadsetschedparam.c b/cpukit/posix/src/pthreadsetschedparam.c
new file mode 100644
index 0000000000..3413dbfc74
--- /dev/null
+++ b/cpukit/posix/src/pthreadsetschedparam.c
@@ -0,0 +1,129 @@
+/*
+ * 13.5.2 Dynamic Thread Scheduling Parameters Access,
+ * P1003.1c/Draft 10, p. 124
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/priority.h>
+#include <rtems/posix/time.h>
+
+int pthread_setschedparam(
+ pthread_t thread,
+ int policy,
+ struct sched_param *param
+)
+{
+ register Thread_Control *the_thread;
+ POSIX_API_Control *api;
+ Thread_CPU_budget_algorithms budget_algorithm;
+ Thread_CPU_budget_algorithm_callout budget_callout;
+ Objects_Locations location;
+
+ /*
+ * Check all the parameters
+ */
+
+ if ( !param )
+ return EINVAL;
+
+ if ( !_POSIX_Priority_Is_valid( param->sched_priority ) )
+ return EINVAL;
+
+ budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE;
+ budget_callout = NULL;
+
+ switch ( policy ) {
+ case SCHED_OTHER:
+ budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE;
+ break;
+
+ case SCHED_FIFO:
+ budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE;
+ break;
+
+ case SCHED_RR:
+ budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE;
+ break;
+
+ case SCHED_SPORADIC:
+ budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_CALLOUT;
+ budget_callout = _POSIX_Threads_Sporadic_budget_callout;
+
+ if ( _POSIX_Timespec_to_interval( &param->ss_replenish_period ) <
+ _POSIX_Timespec_to_interval( &param->ss_initial_budget ) )
+ return EINVAL;
+
+ if ( !_POSIX_Priority_Is_valid( param->ss_low_priority ) )
+ return EINVAL;
+
+ break;
+
+ default:
+ return EINVAL;
+ }
+
+ /*
+ * Actually change the scheduling policy and parameters
+ */
+
+ the_thread = _POSIX_Threads_Get( thread, &location );
+ switch ( location ) {
+ case OBJECTS_ERROR:
+ case OBJECTS_REMOTE:
+ return ESRCH;
+ case OBJECTS_LOCAL:
+ api = the_thread->API_Extensions[ THREAD_API_POSIX ];
+
+ if ( api->schedpolicy == SCHED_SPORADIC )
+ (void) _Watchdog_Remove( &api->Sporadic_timer );
+
+ api->schedpolicy = policy;
+ api->schedparam = *param;
+ the_thread->budget_algorithm = budget_algorithm;
+ the_thread->budget_callout = budget_callout;
+
+ switch ( api->schedpolicy ) {
+ case SCHED_OTHER:
+ case SCHED_FIFO:
+ case SCHED_RR:
+ the_thread->cpu_time_budget = _Thread_Ticks_per_timeslice;
+
+ the_thread->real_priority =
+ _POSIX_Priority_To_core( api->schedparam.sched_priority );
+
+ _Thread_Change_priority(
+ the_thread,
+ the_thread->real_priority,
+ TRUE
+ );
+ break;
+
+ case SCHED_SPORADIC:
+ api->ss_high_priority = api->schedparam.sched_priority;
+ _Watchdog_Remove( &api->Sporadic_timer );
+ _POSIX_Threads_Sporadic_budget_TSR( 0, the_thread );
+ break;
+ }
+
+ _Thread_Enable_dispatch();
+ return 0;
+ }
+ return POSIX_BOTTOM_REACHED();
+}
diff --git a/cpukit/posix/src/pthreadsigmask.c b/cpukit/posix/src/pthreadsigmask.c
new file mode 100644
index 0000000000..59bc688fcd
--- /dev/null
+++ b/cpukit/posix/src/pthreadsigmask.c
@@ -0,0 +1,73 @@
+/*
+ * 3.3.5 Examine and Change Blocked Signals, P1003.1b-1993, p. 73
+ *
+ * NOTE: P1003.1c/D10, p. 37 adds pthread_sigmask().
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <signal.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/psignal.h>
+#include <rtems/seterr.h>
+
+int pthread_sigmask(
+ int how,
+ const sigset_t *set,
+ sigset_t *oset
+)
+{
+ POSIX_API_Control *api;
+
+ if ( !set && !oset )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
+
+ if ( oset )
+ *oset = api->signals_blocked;
+
+ if ( !set )
+ return 0;
+
+ switch ( how ) {
+ case SIG_BLOCK:
+ api->signals_blocked |= *set;
+ break;
+ case SIG_UNBLOCK:
+ api->signals_blocked &= ~*set;
+ break;
+ case SIG_SETMASK:
+ api->signals_blocked = *set;
+ break;
+ default:
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ }
+
+ /* XXX are there critical section problems here? */
+
+ /* XXX evaluate the new set */
+
+ if ( ~api->signals_blocked &
+ (api->signals_pending | _POSIX_signals_Pending) ) {
+ _Thread_Executing->do_post_task_switch_extension = TRUE;
+ _Thread_Dispatch();
+ }
+
+ return 0;
+}
diff --git a/cpukit/posix/src/ptimer.c b/cpukit/posix/src/ptimer.c
new file mode 100644
index 0000000000..a2666c86f9
--- /dev/null
+++ b/cpukit/posix/src/ptimer.c
@@ -0,0 +1,101 @@
+/*
+ * ptimer.c,v 1.1 1996/06/03 16:29:58 joel Exp
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <time.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/tod.h>
+
+#include <rtems/posix/time.h>
+
+/************************************/
+/* These includes are now necessary */
+/************************************/
+
+#include <sys/features.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/types.h>
+#include <rtems/rtems/timer.h>
+#include <rtems/rtems/clock.h>
+#include <rtems/posix/psignal.h>
+#include <rtems/score/wkspace.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <signal.h>
+
+/*****************************/
+/* End of necessary includes */
+/*****************************/
+
+#include <rtems/posix/timer.h>
+
+/* ***************************************************************************
+ * TIMER_INITIALIZE_S
+ *
+ * Description: Initialize the data of a timer
+ * ***************************************************************************/
+
+void TIMER_INITIALIZE_S ( int timer_pos )
+{
+
+ /*
+ * Indicates that the position in the table is free
+ */
+
+ timer_struct[timer_pos].state = STATE_FREE_C;
+
+ /*
+ * The initial data of timing are set with null value
+ */
+
+ timer_struct[timer_pos].timer_data.it_value.tv_sec = 0;
+ timer_struct[timer_pos].timer_data.it_value.tv_nsec = 0;
+ timer_struct[timer_pos].timer_data.it_interval.tv_sec = 0;
+ timer_struct[timer_pos].timer_data.it_interval.tv_nsec = 0;
+
+ /*
+ * The count of expirations is 0
+ */
+
+ timer_struct[timer_pos].overrun = 0;
+
+}
+
+/* ***************************************************************************
+ * _POSIX_Timer_Manager_initialization
+ *
+ * Description: Initialize the internal structure in which the data of all
+ * the timers are stored
+ * ***************************************************************************/
+
+int timer_max;
+POSIX_Timer_Control *timer_struct;
+
+
+void _POSIX_Timer_Manager_initialization ( int max_timers )
+{
+ int index;
+
+ timer_struct = _Workspace_Allocate_or_fatal_error(
+ max_timers * sizeof(POSIX_Timer_Control) );
+
+ /*
+ * Initialize all the timers
+ */
+
+ timer_max = max_timers;
+
+ for (index=0; index<max_timers; index++)
+ TIMER_INITIALIZE_S( index );
+
+ timer_max = max_timers;
+}
diff --git a/cpukit/posix/src/ptimer1.c b/cpukit/posix/src/ptimer1.c
new file mode 100644
index 0000000000..368dff43ff
--- /dev/null
+++ b/cpukit/posix/src/ptimer1.c
@@ -0,0 +1,799 @@
+/*
+ * ptimer.c,v 1.1 1996/06/03 16:29:58 joel Exp
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <time.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/tod.h>
+
+#include <rtems/posix/time.h>
+
+/************************************/
+/* These includes are now necessary */
+/************************************/
+
+#include <sys/features.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/types.h>
+#include <rtems/rtems/timer.h>
+#include <rtems/rtems/clock.h>
+#include <rtems/posix/psignal.h>
+#include <rtems/score/wkspace.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <signal.h>
+
+#include <rtems/seterr.h>
+#include <rtems/posix/timer.h>
+
+/*****************************/
+/* End of necessary includes */
+/*****************************/
+
+/* ************
+ * Constants
+ * ************/
+
+/*
+#define DEBUG_MESSAGES
+ */
+
+/*
+ * Data for the signals
+ */
+
+/***********************************
+ * Definition of Internal Functions
+ ***********************************/
+
+/* ***************************************************************************
+ * TIMER_INITIALIZE_S
+ *
+ * Description: Initialize the data of a timer
+ * ***************************************************************************/
+
+extern void TIMER_INITIALIZE_S ( int timer_pos );
+
+/* ***************************************************************************
+ * _POSIX_Timer_Manager_initialization
+ *
+ * Description: Initialize the internal structure in which the data of all
+ * the timers are stored
+ * ***************************************************************************/
+
+/* split to reduce minimum size */
+
+/* ***************************************************************************
+ * FIRST_FREE_POSITION_F
+ *
+ * Description: Returns the first free position in the table of timers.
+ * If there is not a free position, it returns NO_MORE_TIMERS_C
+ * ***************************************************************************/
+
+int FIRST_FREE_POSITION_F ()
+{
+ int index;
+
+ for (index=0; index<timer_max; index++) {
+ if ( timer_struct[index].state == STATE_FREE_C ) {
+ return index;
+ }
+ }
+
+ /* The function reaches this point only if all the position are occupied */
+
+ return NO_MORE_TIMERS_C;
+}
+
+/* ***************************************************************************
+ * TIMER_POSITION_F
+ *
+ * Description: Returns the position in the table of timers in which the
+ * data of the timer are stored.
+ * If the timer identifier does not exist, it returns
+ * BAD_TIMER_C
+ * ***************************************************************************/
+
+int TIMER_POSITION_F ( timer_t timer_id )
+{
+ int index;
+
+ for (index=0; index<timer_max; index++ ) {
+
+ /* Looks for the position of the timer. The timer must exist and the
+ * position can not be free */
+ if ( ( timer_struct[index].timer_id == timer_id ) &&
+ ( timer_struct[index].state != STATE_FREE_C ) ) {
+ return index;
+ }
+ }
+
+ /* If the function reaches this point is because the timer identifier
+ * is not correct */
+
+ return BAD_TIMER_C;
+
+}
+
+/* ***************************************************************************
+ * COPY_ITIMERSPEC_S
+ *
+ * Description: Does a copy of a variable of type struct itimerspec
+ * ***************************************************************************/
+
+void COPY_ITIMERSPEC_S ( const struct itimerspec *source,
+ struct itimerspec *target )
+{
+
+ target->it_value.tv_sec = source->it_value.tv_sec;
+ target->it_value.tv_nsec = source->it_value.tv_nsec;
+ target->it_interval.tv_sec = source->it_interval.tv_sec;
+ target->it_interval.tv_nsec = source->it_interval.tv_nsec;
+
+}
+
+/* ***************************************************************************
+ * ITIMERSPEC_TO_RTEMS_TIME_OF_DAY_S
+ *
+ * Description: This function converts the data of a structure itimerspec
+ * into structure rtems_time_of_day
+ * ***************************************************************************/
+
+void ITIMERSPEC_TO_RTEMS_TIME_OF_DAY_S
+ ( const struct itimerspec *itimer, rtems_time_of_day *rtems_time )
+{
+ unsigned long int seconds;
+
+ /* The leap years and the months with 28, 29 or 31 days have not been
+ * considerated. It will be made in the future */
+
+ seconds = itimer->it_value.tv_sec;
+
+ rtems_time->year = seconds / SECONDS_PER_YEAR_C;
+ seconds = seconds % SECONDS_PER_YEAR_C;
+
+ rtems_time->month = seconds / SECONDS_PER_MONTH_C;
+ seconds = seconds % SECONDS_PER_MONTH_C;
+
+ rtems_time->day = seconds / SECONDS_PER_DAY_C;
+ seconds = seconds % SECONDS_PER_DAY_C;
+
+ rtems_time->hour = seconds / SECONDS_PER_HOUR_C;
+ seconds = seconds % SECONDS_PER_HOUR_C;
+
+ rtems_time->minute = seconds / SECONDS_PER_MINUTE_C;
+ seconds = seconds % SECONDS_PER_MINUTE_C;
+
+ rtems_time->second = seconds;
+
+ rtems_time->ticks = itimer->it_value.tv_nsec/
+ (NSEC_PER_SEC_C / SEC_TO_TICKS_C);
+
+}
+
+
+/* ***************************************************************************
+ * FIRE_TIMER_S
+ *
+ * Description: This is the operation that is ran when a timer expires
+ * ***************************************************************************/
+
+
+rtems_timer_service_routine FIRE_TIMER_S (rtems_id timer, void *data)
+{
+ int timer_pos; /* Position in the table of the timer that
+ * has expirated */
+ rtems_status_code return_v; /* Return value of rtems_timer_fire_after */
+ int sig_number; /* Number of the signal to send */
+
+
+ /* The position of the table of timers that contains the data of the
+ * expired timer will be stored in "timer_pos". In theory a timer can not
+ * expire if it has not been created or has been deleted */
+
+ timer_pos = TIMER_POSITION_F(timer);
+
+ /* Increases the number of expiration of the timer in one unit. */
+ timer_struct[timer_pos].overrun = timer_struct[timer_pos].overrun + 1;
+
+
+ if ( ( timer_struct[timer_pos].timer_data.it_interval.tv_sec != 0 ) ||
+ ( timer_struct[timer_pos].timer_data.it_interval.tv_nsec != 0 ) ) {
+
+ /* The timer must be reprogrammed */
+
+ return_v = rtems_timer_fire_after ( timer,
+ timer_struct[timer_pos].ticks,
+ FIRE_TIMER_S,
+ NULL );
+
+ /* Stores the time when the timer was started again */
+
+ timer_struct[timer_pos].time = _TOD_Current;
+
+ /* The state has not to be actualized, because nothing modifies it */
+
+ timer_struct[timer_pos].state = STATE_CREATE_RUN_C;
+
+ } else {
+ /* Indicates that the timer is stopped */
+
+ timer_struct[timer_pos].state = STATE_CREATE_STOP_C;
+
+ }
+
+ /*
+ * The sending of the signal to the process running the handling function
+ * specified for that signal is simulated
+ */
+
+ sig_number = timer_struct[timer_pos].inf.sigev_signo;
+
+ if( pthread_kill ( timer_struct[timer_pos].thread_id ,
+ timer_struct[timer_pos].inf.sigev_signo ) ) {
+ /* XXX error handling */
+ }
+
+ /*
+ * After the signal handler returns, the count of expirations of the
+ * timer must be set to 0.
+ */
+
+ timer_struct[timer_pos].overrun = 0;
+
+}
+
+/* *********************************************************************
+ * 14.2.2 Create a Per-Process Timer, P1003.1b-1993, p. 264
+ * ********************************************************************/
+
+/* **************
+ * timer_create
+ * **************/
+
+int timer_create(
+ clockid_t clock_id,
+ struct sigevent *evp,
+ timer_t *timerid
+)
+{
+
+ rtems_status_code return_v; /* return value of the operation */
+ rtems_id timer_id; /* created timer identifier */
+ int timer_pos; /* Position in the table of timers */
+
+ if ( clock_id != CLOCK_REALTIME )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ /*
+ * The data of the structure evp are checked in order to verify if they
+ * are coherent.
+ */
+
+ if (evp != NULL) {
+ /* The structure has data */
+ if ( ( evp->sigev_notify != SIGEV_NONE ) &&
+ ( evp->sigev_notify != SIGEV_SIGNAL ) ) {
+ /* The value of the field sigev_notify is not valid */
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ }
+
+ if ( !evp->sigev_signo )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ if ( !is_valid_signo(evp->sigev_signo) )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ }
+
+ /*
+ * A timer is created using the primitive rtems_timer_create
+ */
+
+ return_v = rtems_timer_create ( clock_id, &timer_id );
+
+ switch (return_v) {
+ case RTEMS_SUCCESSFUL :
+
+ /*
+ * The timer has been created properly
+ */
+
+ /* Obtains the first free position in the table of timers */
+
+ timer_pos = FIRST_FREE_POSITION_F();
+
+ if ( timer_pos == NO_MORE_TIMERS_C ) {
+ /* There is not position for another timers in spite of RTEMS
+ * supports it. It will necessaty to increase the structure used */
+
+ rtems_set_errno_and_return_minus_one( EAGAIN );
+ }
+
+ /* Exit parameter */
+
+ *timerid = timer_id;
+
+ /* The data of the created timer are stored to use them later */
+
+ timer_struct[timer_pos].state = STATE_CREATE_NEW_C;
+
+ /* NEW VERSION*/
+ timer_struct[timer_pos].thread_id = pthread_self ();
+
+ if ( evp != NULL ) {
+ timer_struct[timer_pos].inf.sigev_notify = evp->sigev_notify;
+ timer_struct[timer_pos].inf.sigev_signo = evp->sigev_signo;
+ timer_struct[timer_pos].inf.sigev_value = evp->sigev_value;
+ }
+
+ timer_struct[timer_pos].timer_id = timer_id;
+ timer_struct[timer_pos].overrun = 0;
+
+ timer_struct[timer_pos].timer_data.it_value.tv_sec = 0;
+ timer_struct[timer_pos].timer_data.it_value.tv_nsec = 0;
+ timer_struct[timer_pos].timer_data.it_interval.tv_sec = 0;
+ timer_struct[timer_pos].timer_data.it_interval.tv_nsec = 0;
+
+ return 0;
+
+ case RTEMS_INVALID_NAME : /* The assigned name is not valid */
+
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ case RTEMS_TOO_MANY :
+
+ /* There has been created too much timers for the same process */
+ rtems_set_errno_and_return_minus_one( EAGAIN );
+
+ default :
+
+ /*
+ * Does nothing. It only returns the error without assigning a value
+ * to errno. In theory, it can not happen because the call to
+ * rtems_timer_create can not return other different value.
+ */
+
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ }
+
+ /*
+ * The next sentence is used to avoid singular situations
+ */
+
+ rtems_set_errno_and_return_minus_one( EINVAL );
+}
+
+/*
+ * 14.2.3 Delete a Per_process Timer, P1003.1b-1993, p. 266
+ */
+
+int timer_delete(
+ timer_t timerid
+)
+{
+
+ /*
+ * IDEA: This function must probably stop the timer first and then delete it
+ *
+ * It will have to do a call to rtems_timer_cancel and then another
+ * call to rtems_timer_delete.
+ * The call to rtems_timer_delete will be probably unnecessary,
+ * because rtems_timer_delete stops the timer before deleting it.
+ */
+
+ int timer_pos;
+ rtems_status_code status;
+
+
+ /* First the position in the table of timers is obtained */
+
+ timer_pos = TIMER_POSITION_F ( timerid );
+
+ if ( timer_pos == BAD_TIMER_C ) {
+ /* The timer identifier is erroneus */
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ }
+
+ /* The timer is deleted */
+
+ status = rtems_timer_delete ( timerid );
+
+ if ( status == RTEMS_INVALID_ID ) {
+ /* The timer identifier is erroneus */
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ }
+
+ /* Initializes the data of the timer */
+
+ TIMER_INITIALIZE_S ( timer_pos );
+ return 0;
+}
+
+/*
+ * 14.2.4 Per-Process Timers, P1003.1b-1993, p. 267
+ */
+
+/* **************
+ * timer_settime
+ * **************/
+
+
+int timer_settime(
+ timer_t timerid,
+ int flags,
+ const struct itimerspec *value,
+ struct itimerspec *ovalue
+)
+{
+
+ rtems_status_code return_v; /* Return of the calls to RTEMS */
+ int timer_pos; /* Position of the timer in the table */
+ rtems_time_of_day rtems_time; /* Time in RTEMS */
+
+
+ /* First the position in the table of timers is obtained */
+
+ timer_pos = TIMER_POSITION_F ( timerid );
+
+ if ( timer_pos == BAD_TIMER_C ) {
+ /* The timer identifier is erroneus */
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ }
+
+ if ( value == NULL ) {
+ /* The stucture of times of the timer is free, and then returns an
+ error but the variable errno is not actualized */
+
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ }
+
+ /* If the function reaches this point, then it will be necessary to do
+ * something with the structure of times of the timer: to stop, start
+ * or start it again */
+
+ /* First, it verifies if the timer must be stopped */
+
+ if ( value->it_value.tv_sec == 0 && value->it_value.tv_nsec == 0 ) {
+ /* The timer is stopped */
+
+ return_v = rtems_timer_cancel ( timerid );
+
+ /* The old data of the timer are returned */
+
+ if ( ovalue )
+ *ovalue = timer_struct[timer_pos].timer_data;
+
+ /* The new data are set */
+
+ timer_struct[timer_pos].timer_data = *value;
+
+ /* Indicates that the timer is created and stopped */
+
+ timer_struct[timer_pos].state = STATE_CREATE_STOP_C;
+
+ /* Returns with success */
+
+ return 0;
+ }
+
+ /*
+ * If the function reaches this point, then the timer will have to be
+ * initialized with new values: to start it or start it again
+ */
+
+ /* First, it verifies if the structure "value" is correct */
+
+ if ( ( value->it_value.tv_nsec > MAX_NSEC_C ) ||
+ ( value->it_value.tv_nsec < MIN_NSEC_C ) ) {
+ /* The number of nanoseconds is not correct */
+
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ }
+
+ /* Then, "value" must be converted from seconds and nanoseconds to clock
+ * ticks, to use it in the calls to RTEMS */
+
+ /* It is also necessary to take in account if the time is absolute
+ * or relative */
+
+ switch (flags) {
+ case TIMER_ABSTIME:
+
+ /* The fire time is absolute:
+ * It has to use "rtems_time_fire_when" */
+
+ /* First, it converts from struct itimerspec to rtems_time_of_day */
+
+ ITIMERSPEC_TO_RTEMS_TIME_OF_DAY_S ( value, &rtems_time );
+
+ return_v = rtems_timer_fire_when ( timerid, &rtems_time, FIRE_TIMER_S, NULL);
+
+ switch ( return_v ) {
+ case RTEMS_SUCCESSFUL:
+
+ /* The timer has been started and is running */
+
+ /* Actualizes the data of the structure and
+ * returns the old ones in "ovalue" */
+
+ if ( ovalue )
+ *ovalue = timer_struct[timer_pos].timer_data;
+
+ timer_struct[timer_pos].timer_data = *value;
+
+ /* It indicates that the time is running */
+
+ timer_struct[timer_pos].state = STATE_CREATE_RUN_C;
+
+ /* Stores the time in which the timer was started again */
+
+ timer_struct[timer_pos].time = _TOD_Current;
+ return 0;
+
+ break;
+
+ case RTEMS_INVALID_ID:
+
+ /* XXX error handling */
+ break;
+
+ case RTEMS_NOT_DEFINED:
+
+ /* XXX error handling */
+ break;
+
+ case RTEMS_INVALID_CLOCK:
+
+ /* XXX error handling */
+ break;
+
+ default: break;
+
+
+ }
+
+ break;
+
+ case TIMER_RELATIVE_C:
+
+ /* The fire time is relative:
+ * It has to use "rtems_time_fire_after" */
+
+ /* First, it converts from seconds and nanoseconds to ticks */
+
+ /* The form in which this operation is done can produce a lost
+ * of precision of 1 second */
+
+/* This is the process to convert from nanoseconds to ticks
+ *
+ * There is a tick every 10 miliseconds, then the nanoseconds are
+ * divided between 10**7. The result of this operation will be the
+ * number of ticks
+ */
+
+ timer_struct[timer_pos].ticks =
+ ( SEC_TO_TICKS_C * value->it_value.tv_sec ) +
+ ( value->it_value.tv_nsec / (NSEC_PER_SEC_C / SEC_TO_TICKS_C));
+
+ return_v = rtems_timer_fire_after ( timerid,
+ timer_struct[timer_pos].ticks,
+ FIRE_TIMER_S,
+ NULL );
+
+ switch (return_v) {
+ case RTEMS_SUCCESSFUL:
+
+ /* The timer has been started and is running */
+
+ /* Actualizes the data of the structure and
+ * returns the old ones in "ovalue" */
+
+ if ( ovalue )
+ *ovalue = timer_struct[timer_pos].timer_data;
+
+ timer_struct[timer_pos].timer_data = *value;
+
+ /* It indicates that the time is running */
+
+ timer_struct[timer_pos].state = STATE_CREATE_RUN_C;
+
+ /* Stores the time in which the timer was started again */
+
+ timer_struct[timer_pos].time = _TOD_Current;
+
+ return 0;
+
+ break;
+
+ case RTEMS_INVALID_ID:
+
+ /* The timer identifier is not correct. In theory, this
+ * situation can not occur, but the solution is easy */
+
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ break;
+
+ case RTEMS_INVALID_NUMBER:
+
+ /* In this case, RTEMS fails because the values of timing
+ * are incorrect */
+
+ /*
+ * I do not know if errno must be actualized
+ *
+ * errno = EINVAL;
+ */
+
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ break;
+
+ default: break;
+ }
+
+ break;
+
+ default: break;
+
+ /* It does nothing, although it will be probably necessary to
+ * return an error */
+ }
+
+ /* To avoid problems */
+ return 0;
+}
+
+
+/*
+ * 14.2.4 Per-Process Timers, P1003.1b-1993, p. 267
+ */
+
+/* **************
+ * timer_gettime
+ * **************/
+
+int timer_gettime(
+ timer_t timerid,
+ struct itimerspec *value
+)
+{
+
+ /*
+ * IDEA: This function does not use functions of RTEMS to the handle
+ * of timers. It uses some functions for managing the time.
+ *
+ * A possible form to do this is the following:
+ *
+ * - When a timer is initialized, the value of the time in
+ * that moment is stored.
+ * - When this function is called, it returns the difference
+ * between the current time and the initialization time.
+ */
+
+ rtems_time_of_day current_time;
+ int timer_pos;
+ uint32_t hours;
+ uint32_t minutes;
+ uint32_t seconds;
+ uint32_t ticks;
+ uint32_t nanosec;
+
+
+ /* Reads the current time */
+
+ current_time = _TOD_Current;
+
+ timer_pos = TIMER_POSITION_F ( timerid );
+
+ if ( timer_pos == BAD_TIMER_C ) {
+ /* The timer identifier is erroneus */
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ }
+
+ /* Calculates the difference between the start time of the timer and
+ * the current one */
+
+ hours = current_time.hour - timer_struct[timer_pos].time.hour;
+
+ if ( current_time.minute < timer_struct[timer_pos].time.minute ) {
+ minutes = 60 - timer_struct[timer_pos].time.minute + current_time.minute;
+ hours--;
+ } else {
+ minutes = current_time.minute - timer_struct[timer_pos].time.minute;
+ }
+
+ if ( current_time.second < timer_struct[timer_pos].time.second ) {
+ seconds = 60 - timer_struct[timer_pos].time.second + current_time.second;
+ minutes--;
+ } else {
+ seconds = current_time.second - timer_struct[timer_pos].time.second;
+ }
+
+ if ( current_time.ticks < timer_struct[timer_pos].time.ticks ) {
+ ticks = 100 - timer_struct[timer_pos].time.ticks + current_time.ticks;
+ seconds--;
+ } else {
+ ticks = current_time.ticks - timer_struct[timer_pos].time.ticks;
+ }
+
+ /* The time that the timer is running is calculated */
+ seconds = hours * 60 * 60 +
+ minutes * 60 +
+ seconds;
+
+ nanosec = ticks * 10 * /* msec */
+ 1000 * /* microsec */
+ 1000; /* nanosec */
+
+
+ /* Calculates the time left before the timer finishes */
+
+ value->it_value.tv_sec =
+ timer_struct[timer_pos].timer_data.it_value.tv_sec - seconds;
+
+ value->it_value.tv_nsec =
+ timer_struct[timer_pos].timer_data.it_value.tv_nsec - nanosec;
+
+
+ value->it_interval.tv_sec =
+ timer_struct[timer_pos].timer_data.it_interval.tv_sec;
+ value->it_interval.tv_nsec =
+ timer_struct[timer_pos].timer_data.it_interval.tv_nsec;
+
+
+ return 0;
+
+}
+
+/*
+ * 14.2.4 Per-Process Timers, P1003.1b-1993, p. 267
+ */
+
+/* *****************
+ * timer_getoverrun
+ * *****************/
+
+int timer_getoverrun(
+ timer_t timerid
+)
+{
+
+ /*
+ * IDEA: This function must count the times the timer expires.
+ *
+ * The expiration of a timer must increase by one a counter.
+ * After the signal handler associated to the timer finishs
+ * its execution, FIRE_TIMER_S will have to set this counter to 0.
+ */
+
+ int timer_pos; /* Position of the timer in the structure */
+ int overrun; /* Overflow count */
+
+
+ timer_pos = TIMER_POSITION_F ( timerid );
+
+ if ( timer_pos == BAD_TIMER_C ) {
+ /* The timer identifier is erroneus */
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ }
+
+ /* The overflow count of the timer is stored in "overrun" */
+
+ overrun = timer_struct[timer_pos].overrun;
+
+ /* It is set to 0 */
+
+ timer_struct[timer_pos].overrun = 0;
+
+ return overrun;
+
+}
diff --git a/cpukit/posix/src/sched.c b/cpukit/posix/src/sched.c
new file mode 100644
index 0000000000..13b8db2a71
--- /dev/null
+++ b/cpukit/posix/src/sched.c
@@ -0,0 +1,157 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <sched.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/thread.h>
+#include <rtems/seterr.h>
+#include <rtems/posix/priority.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * 13.3.1 Set Scheduling Parameters, P1003.1b-1993, p. 252
+ *
+ */
+
+int sched_setparam(
+ pid_t pid,
+ const struct sched_param *param
+)
+{
+ rtems_set_errno_and_return_minus_one( ENOSYS );
+}
+
+/*PAGE
+ *
+ * 13.3.2 Set Scheduling Parameters, P1003.1b-1993, p. 253
+ */
+
+int sched_getparam(
+ pid_t pid,
+ const struct sched_param *param
+)
+{
+ rtems_set_errno_and_return_minus_one( ENOSYS );
+}
+
+/*PAGE
+ *
+ * 13.3.3 Set Scheduling Policy and Scheduling Parameters,
+ * P1003.1b-1993, p. 254
+ */
+
+int sched_setscheduler(
+ pid_t pid,
+ int policy,
+ const struct sched_param *param
+)
+{
+ rtems_set_errno_and_return_minus_one( ENOSYS );
+}
+
+/*PAGE
+ *
+ * 13.3.4 Get Scheduling Policy, P1003.1b-1993, p. 256
+ */
+
+int sched_getscheduler(
+ pid_t pid
+)
+{
+ rtems_set_errno_and_return_minus_one( ENOSYS );
+}
+
+/*PAGE
+ *
+ * 13.3.6 Get Scheduling Parameter Limits, P1003.1b-1993, p. 258
+ */
+
+int sched_get_priority_max(
+ int policy
+)
+{
+ switch ( policy ) {
+ case SCHED_OTHER:
+ case SCHED_FIFO:
+ case SCHED_RR:
+ case SCHED_SPORADIC:
+ break;
+
+ default:
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ }
+
+ return POSIX_SCHEDULER_MAXIMUM_PRIORITY;
+}
+
+/*PAGE
+ *
+ * 13.3.6 Get Scheduling Parameter Limits, P1003.1b-1993, p. 258
+ */
+
+int sched_get_priority_min(
+ int policy
+)
+{
+ switch ( policy ) {
+ case SCHED_OTHER:
+ case SCHED_FIFO:
+ case SCHED_RR:
+ case SCHED_SPORADIC:
+ break;
+
+ default:
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ }
+
+ return POSIX_SCHEDULER_MINIMUM_PRIORITY;
+}
+
+/*PAGE
+ *
+ * 13.3.6 Get Scheduling Parameter Limits, P1003.1b-1993, p. 258
+ */
+
+int sched_rr_get_interval(
+ pid_t pid,
+ struct timespec *interval
+)
+{
+ /* XXX do we need to support different time quantums per thread */
+
+ /*
+ * Only supported for the "calling process" (i.e. this node).
+ */
+
+ if ( pid && pid != getpid() )
+ rtems_set_errno_and_return_minus_one( ESRCH );
+
+ if ( !interval )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ _POSIX_Interval_to_timespec( _Thread_Ticks_per_timeslice, interval );
+ return 0;
+}
+
+/*PAGE
+ *
+ * 13.3.5 Yield Processor, P1003.1b-1993, p. 257
+ */
+
+int sched_yield( void )
+{
+ _Thread_Disable_dispatch();
+ _Thread_Yield_processor();
+ _Thread_Enable_dispatch();
+ return 0;
+}
diff --git a/cpukit/posix/src/semaphore.c b/cpukit/posix/src/semaphore.c
new file mode 100644
index 0000000000..3ec96d8366
--- /dev/null
+++ b/cpukit/posix/src/semaphore.c
@@ -0,0 +1,54 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <limits.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/posix/semaphore.h>
+#include <rtems/posix/time.h>
+#include <rtems/seterr.h>
+
+/*PAGE
+ *
+ * _POSIX_Semaphore_Manager_initialization
+ *
+ * This routine initializes all semaphore manager related data structures.
+ *
+ * Input parameters:
+ * maximum_semaphores - maximum configured semaphores
+ *
+ * Output parameters: NONE
+ */
+
+void _POSIX_Semaphore_Manager_initialization(
+ uint32_t maximum_semaphores
+)
+{
+ _Objects_Initialize_information(
+ &_POSIX_Semaphore_Information, /* object information table */
+ OBJECTS_POSIX_API, /* object API */
+ OBJECTS_POSIX_SEMAPHORES, /* object class */
+ maximum_semaphores /* maximum objects of this class */,
+ sizeof( POSIX_Semaphore_Control ),
+ /* size of this object's control block */
+ TRUE, /* TRUE if names for this object are strings */
+ _POSIX_PATH_MAX /* maximum length of each object's name */
+#if defined(RTEMS_MULTIPROCESSING)
+ ,
+ FALSE, /* TRUE if this is a global object class */
+ NULL /* Proxy extraction support callout */
+#endif
+ );
+}
diff --git a/cpukit/posix/src/semaphorecreatesupp.c b/cpukit/posix/src/semaphorecreatesupp.c
new file mode 100644
index 0000000000..64d8f435b0
--- /dev/null
+++ b/cpukit/posix/src/semaphorecreatesupp.c
@@ -0,0 +1,129 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <limits.h>
+#include <string.h> /* strlen */
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/posix/semaphore.h>
+#include <rtems/posix/time.h>
+#include <rtems/seterr.h>
+
+/*PAGE
+ *
+ * _POSIX_Semaphore_Create_support
+ *
+ * This routine does the actual creation and initialization of
+ * a poxix semaphore. It is a support routine for sem_init and
+ * sem_open.
+ */
+
+int _POSIX_Semaphore_Create_support(
+ const char *name,
+ int pshared,
+ unsigned int value,
+ POSIX_Semaphore_Control **the_sem
+)
+{
+ POSIX_Semaphore_Control *the_semaphore;
+ CORE_semaphore_Attributes *the_sem_attr;
+
+ _Thread_Disable_dispatch();
+
+ /* Sharing semaphores among processes is not currently supported */
+ if (pshared != 0) {
+ _Thread_Enable_dispatch();
+ rtems_set_errno_and_return_minus_one( ENOSYS );
+ }
+
+ if ( name ) {
+ if( strlen(name) > PATH_MAX ) {
+ _Thread_Enable_dispatch();
+ rtems_set_errno_and_return_minus_one( ENAMETOOLONG );
+ }
+ }
+
+ the_semaphore = _POSIX_Semaphore_Allocate();
+
+ if ( !the_semaphore ) {
+ _Thread_Enable_dispatch();
+ rtems_set_errno_and_return_minus_one( ENOSPC );
+ }
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( pshared == PTHREAD_PROCESS_SHARED &&
+ !( _Objects_MP_Allocate_and_open( &_POSIX_Semaphore_Information, 0,
+ the_semaphore->Object.id, FALSE ) ) ) {
+ _POSIX_Semaphore_Free( the_semaphore );
+ _Thread_Enable_dispatch();
+ rtems_set_errno_and_return_minus_one( EAGAIN );
+ }
+#endif
+
+ the_semaphore->process_shared = pshared;
+
+ if ( name ) {
+ the_semaphore->named = TRUE;
+ the_semaphore->open_count = 1;
+ the_semaphore->linked = TRUE;
+ }
+ else
+ the_semaphore->named = FALSE;
+
+ the_sem_attr = &the_semaphore->Semaphore.Attributes;
+
+ /*
+ * POSIX does not appear to specify what the discipline for
+ * blocking tasks on this semaphore should be. It could somehow
+ * be derived from the current scheduling policy. One
+ * thing is certain, no matter what we decide, it won't be
+ * the same as all other POSIX implementations. :)
+ */
+
+ the_sem_attr->discipline = CORE_SEMAPHORE_DISCIPLINES_FIFO;
+
+ /*
+ * This effectively disables limit checking.
+ */
+
+ the_sem_attr->maximum_count = 0xFFFFFFFF;
+
+ _CORE_semaphore_Initialize( &the_semaphore->Semaphore, the_sem_attr, value );
+
+ /*
+ * Make the semaphore available for use.
+ */
+
+ _Objects_Open(
+ &_POSIX_Semaphore_Information,
+ &the_semaphore->Object,
+ (char *) name
+ );
+
+ *the_sem = the_semaphore;
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( pshared == PTHREAD_PROCESS_SHARED )
+ _POSIX_Semaphore_MP_Send_process_packet(
+ POSIX_SEMAPHORE_MP_ANNOUNCE_CREATE,
+ the_semaphore->Object.id,
+ (char *) name,
+ 0 /* proxy id - Not used */
+ );
+#endif
+
+ _Thread_Enable_dispatch();
+ return 0;
+}
diff --git a/cpukit/posix/src/semaphoredeletesupp.c b/cpukit/posix/src/semaphoredeletesupp.c
new file mode 100644
index 0000000000..44b00fcd67
--- /dev/null
+++ b/cpukit/posix/src/semaphoredeletesupp.c
@@ -0,0 +1,65 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <limits.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/posix/semaphore.h>
+#include <rtems/posix/time.h>
+#include <rtems/seterr.h>
+
+/*PAGE
+ *
+ * _POSIX_Semaphore_Delete
+ */
+
+void _POSIX_Semaphore_Delete(
+ POSIX_Semaphore_Control *the_semaphore
+)
+{
+ if ( !the_semaphore->linked && !the_semaphore->open_count ) {
+ _Objects_Close( &_POSIX_Semaphore_Information, &the_semaphore->Object );
+
+ _CORE_semaphore_Flush(
+ &the_semaphore->Semaphore,
+#if defined(RTEMS_MULTIPROCESSING)
+ _POSIX_Semaphore_MP_Send_object_was_deleted,
+#else
+ NULL,
+#endif
+ -1 /* XXX should also seterrno -> EINVAL */
+ );
+
+ _POSIX_Semaphore_Free( the_semaphore );
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( the_semaphore->process_shared == PTHREAD_PROCESS_SHARED ) {
+
+ _Objects_MP_Close(
+ &_POSIX_Semaphore_Information,
+ the_semaphore->Object.id
+ );
+
+ _POSIX_Semaphore_MP_Send_process_packet(
+ POSIX_SEMAPHORE_MP_ANNOUNCE_DELETE,
+ the_semaphore->Object.id,
+ 0, /* Not used */
+ 0 /* Not used */
+ );
+ }
+#endif
+
+ }
+}
diff --git a/cpukit/posix/src/semaphoremp.c b/cpukit/posix/src/semaphoremp.c
new file mode 100644
index 0000000000..d5a4cf9f1e
--- /dev/null
+++ b/cpukit/posix/src/semaphoremp.c
@@ -0,0 +1,146 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <limits.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/posix/semaphore.h>
+#include <rtems/posix/time.h>
+#include <rtems/seterr.h>
+
+#if defined(RTEMS_MULTIPROCESSING)
+/*
+ * _POSIX_Semaphore_MP_Send_process_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * process operation can be performed on another node.
+ */
+
+void _POSIX_Semaphore_MP_Send_process_packet(
+ POSIX_Semaphore_MP_Remote_operations operation,
+ Objects_Id semaphore_id,
+ Objects_Name name,
+ Objects_Id proxy_id
+)
+{
+ POSIX_MP_NOT_IMPLEMENTED();
+}
+
+/*
+ * _POSIX_Semaphore_MP_Send_request_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * directive operation can be initiated on another node.
+ */
+
+int _POSIX_Semaphore_MP_Send_request_packet(
+ POSIX_Semaphore_MP_Remote_operations operation,
+ Objects_Id semaphore_id,
+ boolean wait, /* XXX options */
+ Watchdog_Interval timeout
+)
+{
+ POSIX_MP_NOT_IMPLEMENTED();
+ return 0;
+}
+
+/*
+ * _POSIX_Semaphore_MP_Send_response_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * directive can be performed on another node.
+ */
+
+void _POSIX_Semaphore_MP_Send_response_packet(
+ POSIX_Semaphore_MP_Remote_operations operation,
+ Objects_Id semaphore_id,
+ Thread_Control *the_thread
+)
+{
+ POSIX_MP_NOT_IMPLEMENTED();
+}
+
+/*
+ *
+ * _POSIX_Semaphore_MP_Process_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the actions specific to this package for
+ * the request from another node.
+ */
+
+void _POSIX_Semaphore_MP_Process_packet(
+ MP_packet_Prefix *the_packet_prefix
+)
+{
+ POSIX_MP_NOT_IMPLEMENTED();
+}
+
+/*
+ * _POSIX_Semaphore_MP_Send_object_was_deleted
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked indirectly by the thread queue
+ * when a proxy has been removed from the thread queue and
+ * the remote node must be informed of this.
+ */
+
+void _POSIX_Semaphore_MP_Send_object_was_deleted(
+ Thread_Control *the_proxy
+)
+{
+ POSIX_MP_NOT_IMPLEMENTED();
+}
+
+/*
+ * _POSIX_Semaphore_MP_Send_extract_proxy
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked when a task is deleted and it
+ * has a proxy which must be removed from a thread queue and
+ * the remote node must be informed of this.
+ */
+
+void _POSIX_Semaphore_MP_Send_extract_proxy(
+ Thread_Control *the_thread
+)
+{
+ POSIX_MP_NOT_IMPLEMENTED();
+}
+
+/*
+ * _POSIX_Semaphore_MP_Get_packet
+ *
+ * DESCRIPTION:
+ *
+ * This function is used to obtain a semaphore mp packet.
+ */
+
+POSIX_Semaphore_MP_Packet *_POSIX_Semaphore_MP_Get_packet( void )
+{
+ POSIX_MP_NOT_IMPLEMENTED();
+ return NULL;
+}
+
+#endif /* endif RTEMS_MULTIPROCESSING */
diff --git a/cpukit/posix/src/semaphorenametoid.c b/cpukit/posix/src/semaphorenametoid.c
new file mode 100644
index 0000000000..eb1a4686cf
--- /dev/null
+++ b/cpukit/posix/src/semaphorenametoid.c
@@ -0,0 +1,51 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <limits.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/posix/semaphore.h>
+#include <rtems/posix/time.h>
+#include <rtems/seterr.h>
+
+/*PAGE
+ *
+ * _POSIX_Semaphore_Name_to_id
+ *
+ * Look up the specified name and attempt to locate the id
+ * for the associated semaphore.
+ */
+
+int _POSIX_Semaphore_Name_to_id(
+ const char *name,
+ sem_t *id
+)
+{
+ Objects_Name_or_id_lookup_errors status;
+
+ if ( !name )
+ return EINVAL;
+
+ if ( !name[0] )
+ return EINVAL;
+
+ status = _Objects_Name_to_id(
+ &_POSIX_Semaphore_Information, (char *)name, 0, (Objects_Id*)id );
+
+ if ( status == OBJECTS_NAME_OR_ID_LOOKUP_SUCCESSFUL )
+ return 0;
+
+ return ENOENT;
+}
diff --git a/cpukit/posix/src/semaphorewaitsupp.c b/cpukit/posix/src/semaphorewaitsupp.c
new file mode 100644
index 0000000000..7c76ff87bd
--- /dev/null
+++ b/cpukit/posix/src/semaphorewaitsupp.c
@@ -0,0 +1,71 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <limits.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/posix/semaphore.h>
+#include <rtems/posix/time.h>
+#include <rtems/seterr.h>
+
+/*PAGE
+ *
+ * _POSIX_Semaphore_Wait_support
+ */
+
+int _POSIX_Semaphore_Wait_support(
+ sem_t *sem,
+ boolean blocking,
+ Watchdog_Interval timeout
+)
+{
+ register POSIX_Semaphore_Control *the_semaphore;
+ Objects_Locations location;
+
+ the_semaphore = _POSIX_Semaphore_Get( sem, &location );
+ switch ( location ) {
+ case OBJECTS_ERROR:
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ case OBJECTS_REMOTE:
+ _Thread_Dispatch();
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ case OBJECTS_LOCAL:
+ _CORE_semaphore_Seize(
+ &the_semaphore->Semaphore,
+ the_semaphore->Object.id,
+ blocking,
+ timeout
+ );
+ _Thread_Enable_dispatch();
+ switch ( _Thread_Executing->Wait.return_code ) {
+ case CORE_SEMAPHORE_STATUS_SUCCESSFUL:
+ break;
+ case CORE_SEMAPHORE_STATUS_UNSATISFIED_NOWAIT:
+ rtems_set_errno_and_return_minus_one( EAGAIN );
+ case CORE_SEMAPHORE_WAS_DELETED:
+ rtems_set_errno_and_return_minus_one( EAGAIN );
+ case CORE_SEMAPHORE_TIMEOUT:
+ rtems_set_errno_and_return_minus_one( ETIMEDOUT );
+ break;
+ case CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED:
+ /*
+ * This error can not occur since we set the maximum
+ * count to the largest value the count can hold.
+ */
+ break;
+ }
+ }
+ return 0;
+}
diff --git a/cpukit/posix/src/semclose.c b/cpukit/posix/src/semclose.c
new file mode 100644
index 0000000000..83b72f36e0
--- /dev/null
+++ b/cpukit/posix/src/semclose.c
@@ -0,0 +1,55 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <limits.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/posix/semaphore.h>
+#include <rtems/posix/time.h>
+#include <rtems/seterr.h>
+
+
+/*PAGE
+ *
+ * sem_close
+ *
+ * Routine to close a semaphore that has been opened or initialized.
+ *
+ * 11.2.4 Close a Named Semaphore, P1003.1b-1993, p.224
+ */
+
+int sem_close(
+ sem_t *sem
+)
+{
+ register POSIX_Semaphore_Control *the_semaphore;
+ Objects_Locations location;
+
+ the_semaphore = _POSIX_Semaphore_Get( sem, &location );
+ switch ( location ) {
+ case OBJECTS_ERROR:
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ case OBJECTS_REMOTE:
+ _Thread_Dispatch();
+ return POSIX_MP_NOT_IMPLEMENTED();
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ case OBJECTS_LOCAL:
+ the_semaphore->open_count -= 1;
+ _POSIX_Semaphore_Delete( the_semaphore );
+ _Thread_Enable_dispatch();
+ return 0;
+ }
+ return POSIX_BOTTOM_REACHED();
+}
diff --git a/cpukit/posix/src/semdestroy.c b/cpukit/posix/src/semdestroy.c
new file mode 100644
index 0000000000..2daccce17c
--- /dev/null
+++ b/cpukit/posix/src/semdestroy.c
@@ -0,0 +1,58 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <limits.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/posix/semaphore.h>
+#include <rtems/posix/time.h>
+#include <rtems/seterr.h>
+
+/*PAGE
+ *
+ * 11.2.2 Destroy an Unnamed Semaphore, P1003.1b-1993, p.220
+ */
+
+int sem_destroy(
+ sem_t *sem
+)
+{
+ register POSIX_Semaphore_Control *the_semaphore;
+ Objects_Locations location;
+
+ the_semaphore = _POSIX_Semaphore_Get( sem, &location );
+ switch ( location ) {
+ case OBJECTS_ERROR:
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ case OBJECTS_REMOTE:
+ _Thread_Dispatch();
+ return POSIX_MP_NOT_IMPLEMENTED();
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ case OBJECTS_LOCAL:
+ /*
+ * Undefined operation on a named semaphore.
+ */
+
+ if ( the_semaphore->named == TRUE ) {
+ _Thread_Enable_dispatch();
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ }
+
+ _POSIX_Semaphore_Delete( the_semaphore );
+ _Thread_Enable_dispatch();
+ return 0;
+ }
+ return POSIX_BOTTOM_REACHED();
+}
diff --git a/cpukit/posix/src/semgetvalue.c b/cpukit/posix/src/semgetvalue.c
new file mode 100644
index 0000000000..e2bf9f83b2
--- /dev/null
+++ b/cpukit/posix/src/semgetvalue.c
@@ -0,0 +1,50 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <limits.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/posix/semaphore.h>
+#include <rtems/posix/time.h>
+#include <rtems/seterr.h>
+
+/*PAGE
+ *
+ * 11.2.8 Get the Value of a Semaphore, P1003.1b-1993, p.229
+ */
+
+int sem_getvalue(
+ sem_t *sem,
+ int *sval
+)
+{
+ register POSIX_Semaphore_Control *the_semaphore;
+ Objects_Locations location;
+
+ the_semaphore = _POSIX_Semaphore_Get( sem, &location );
+ switch ( location ) {
+ case OBJECTS_ERROR:
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ case OBJECTS_REMOTE:
+ _Thread_Dispatch();
+ return POSIX_MP_NOT_IMPLEMENTED();
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ case OBJECTS_LOCAL:
+ *sval = _CORE_semaphore_Get_count( &the_semaphore->Semaphore );
+ _Thread_Enable_dispatch();
+ return 0;
+ }
+ return POSIX_BOTTOM_REACHED();
+}
diff --git a/cpukit/posix/src/seminit.c b/cpukit/posix/src/seminit.c
new file mode 100644
index 0000000000..449f2c1c01
--- /dev/null
+++ b/cpukit/posix/src/seminit.c
@@ -0,0 +1,51 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <limits.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/posix/semaphore.h>
+#include <rtems/posix/time.h>
+#include <rtems/seterr.h>
+
+/*PAGE
+ *
+ * 11.2.1 Initialize an Unnamed Semaphore, P1003.1b-1993, p.219
+ */
+
+int sem_init(
+ sem_t *sem,
+ int pshared,
+ unsigned int value
+)
+{
+ int status;
+ POSIX_Semaphore_Control *the_semaphore;
+
+ if ( !sem )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ status = _POSIX_Semaphore_Create_support(
+ NULL,
+ pshared,
+ value,
+ &the_semaphore
+ );
+
+ if ( status != -1 )
+ *sem = the_semaphore->Object.id;
+
+ return status;
+}
diff --git a/cpukit/posix/src/semopen.c b/cpukit/posix/src/semopen.c
new file mode 100644
index 0000000000..522177d3b0
--- /dev/null
+++ b/cpukit/posix/src/semopen.c
@@ -0,0 +1,122 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <limits.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/posix/semaphore.h>
+#include <rtems/posix/time.h>
+#include <rtems/seterr.h>
+
+/*PAGE
+ *
+ * sem_open
+ *
+ * Opens a named semaphore. Used in conjunction with the sem_close
+ * and sem_unlink commands.
+ *
+ * 11.2.3 Initialize/Open a Named Semaphore, P1003.1b-1993, p.221
+ *
+ * NOTE: When oflag is O_CREAT, then optional third and fourth
+ * parameters must be present.
+ */
+
+sem_t *sem_open(
+ const char *name,
+ int oflag,
+ ...
+ /* mode_t mode, */
+ /* unsigned int value */
+)
+{
+ va_list arg;
+ mode_t mode;
+ unsigned int value = 0;
+ int status;
+ sem_t the_semaphore_id;
+ POSIX_Semaphore_Control *the_semaphore;
+ Objects_Locations location;
+
+ _Thread_Disable_dispatch();
+
+ if ( oflag & O_CREAT ) {
+ va_start(arg, oflag);
+ mode = (mode_t) va_arg( arg, unsigned int );
+ value = va_arg( arg, unsigned int );
+ va_end(arg);
+ }
+
+ status = _POSIX_Semaphore_Name_to_id( name, &the_semaphore_id );
+
+ /*
+ * If the name to id translation worked, then the semaphore exists
+ * and we can just return a pointer to the id. Otherwise we may
+ * need to check to see if this is a "semaphore does not exist"
+ * or some other miscellaneous error on the name.
+ */
+
+ if ( status ) {
+
+ /*
+ * Unless provided a valid name that did not already exist
+ * and we are willing to create then it is an error.
+ */
+
+ if ( !( status == ENOENT && (oflag & O_CREAT) ) ) {
+ _Thread_Enable_dispatch();
+ rtems_set_errno_and_return_minus_one_cast( status, sem_t * );
+ }
+ } else {
+
+ /*
+ * Check for existence with creation.
+ */
+
+ if ( (oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL) ) {
+ _Thread_Enable_dispatch();
+ rtems_set_errno_and_return_minus_one_cast( EEXIST, sem_t * );
+ }
+
+ the_semaphore = _POSIX_Semaphore_Get( &the_semaphore_id, &location );
+ the_semaphore->open_count += 1;
+ _Thread_Enable_dispatch();
+ _Thread_Enable_dispatch();
+ return (sem_t *)&the_semaphore->Object.id;
+
+ }
+
+ /*
+ * At this point, the semaphore does not exist and everything has been
+ * checked. We should go ahead and create a semaphore.
+ */
+
+ status =_POSIX_Semaphore_Create_support(
+ name,
+ FALSE, /* not shared across processes */
+ value,
+ &the_semaphore
+ );
+
+ /*
+ * errno was set by Create_support, so don't set it again.
+ */
+
+ _Thread_Enable_dispatch();
+
+ if ( status == -1 )
+ return SEM_FAILED;
+
+ return (sem_t *) &the_semaphore->Object.id;
+}
diff --git a/cpukit/posix/src/sempost.c b/cpukit/posix/src/sempost.c
new file mode 100644
index 0000000000..a4d7a36876
--- /dev/null
+++ b/cpukit/posix/src/sempost.c
@@ -0,0 +1,57 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <limits.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/posix/semaphore.h>
+#include <rtems/posix/time.h>
+#include <rtems/seterr.h>
+
+/*PAGE
+ *
+ * 11.2.7 Unlock a Semaphore, P1003.1b-1993, p.227
+ */
+
+int sem_post(
+ sem_t *sem
+)
+{
+ register POSIX_Semaphore_Control *the_semaphore;
+ Objects_Locations location;
+
+ the_semaphore = _POSIX_Semaphore_Get( sem, &location );
+ switch ( location ) {
+ case OBJECTS_ERROR:
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ case OBJECTS_REMOTE:
+ _Thread_Dispatch();
+ return POSIX_MP_NOT_IMPLEMENTED();
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ case OBJECTS_LOCAL:
+ _CORE_semaphore_Surrender(
+ &the_semaphore->Semaphore,
+ the_semaphore->Object.id,
+#if defined(RTEMS_MULTIPROCESSING)
+ NULL /* XXX need to define a routine to handle this case */
+#else
+ NULL
+#endif
+ );
+ _Thread_Enable_dispatch();
+ return 0;
+ }
+ return POSIX_BOTTOM_REACHED();
+}
diff --git a/cpukit/posix/src/semtimedwait.c b/cpukit/posix/src/semtimedwait.c
new file mode 100644
index 0000000000..f5904c59fd
--- /dev/null
+++ b/cpukit/posix/src/semtimedwait.c
@@ -0,0 +1,40 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <limits.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/posix/semaphore.h>
+#include <rtems/posix/time.h>
+#include <rtems/seterr.h>
+
+/*PAGE
+ *
+ * 11.2.6 Lock a Semaphore, P1003.1b-1993, p.226
+ *
+ * NOTE: P1003.4b/D8 adds sem_timedwait(), p. 27
+ */
+
+int sem_timedwait(
+ sem_t *sem,
+ const struct timespec *timeout
+)
+{
+ return _POSIX_Semaphore_Wait_support(
+ sem,
+ TRUE,
+ _POSIX_Timespec_to_interval( timeout )
+ );
+}
diff --git a/cpukit/posix/src/semtrywait.c b/cpukit/posix/src/semtrywait.c
new file mode 100644
index 0000000000..2aecde9425
--- /dev/null
+++ b/cpukit/posix/src/semtrywait.c
@@ -0,0 +1,35 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <limits.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/posix/semaphore.h>
+#include <rtems/posix/time.h>
+#include <rtems/seterr.h>
+
+/*PAGE
+ *
+ * 11.2.6 Lock a Semaphore, P1003.1b-1993, p.226
+ *
+ * NOTE: P1003.4b/D8 adds sem_timedwait(), p. 27
+ */
+
+int sem_trywait(
+ sem_t *sem
+)
+{
+ return _POSIX_Semaphore_Wait_support( sem, FALSE, THREAD_QUEUE_WAIT_FOREVER );
+}
diff --git a/cpukit/posix/src/semunlink.c b/cpukit/posix/src/semunlink.c
new file mode 100644
index 0000000000..b694ea19f9
--- /dev/null
+++ b/cpukit/posix/src/semunlink.c
@@ -0,0 +1,75 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <limits.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/posix/semaphore.h>
+#include <rtems/posix/time.h>
+#include <rtems/seterr.h>
+
+/*PAGE
+ *
+ * sem_unlink
+ *
+ * Unlinks a named semaphore, sem_close must also be called to remove
+ * the semaphore.
+ *
+ * 11.2.5 Remove a Named Semaphore, P1003.1b-1993, p.225
+ */
+
+int sem_unlink(
+ const char *name
+)
+{
+ int status;
+ register POSIX_Semaphore_Control *the_semaphore;
+ sem_t the_semaphore_id;
+
+ _Thread_Disable_dispatch();
+
+ status = _POSIX_Semaphore_Name_to_id( name, &the_semaphore_id );
+ if ( status != 0 ) {
+ _Thread_Enable_dispatch();
+ rtems_set_errno_and_return_minus_one( status );
+ }
+
+ /*
+ * Don't support unlinking a remote semaphore.
+ */
+
+ if ( !_Objects_Is_local_id((Objects_Id)the_semaphore_id) ) {
+ _Thread_Enable_dispatch();
+ rtems_set_errno_and_return_minus_one( ENOSYS );
+ }
+
+ the_semaphore = (POSIX_Semaphore_Control *) _Objects_Get_local_object(
+ &_POSIX_Semaphore_Information,
+ _Objects_Get_index( the_semaphore_id )
+ );
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( the_semaphore->process_shared == PTHREAD_PROCESS_SHARED ) {
+ _Objects_MP_Close( &_POSIX_Semaphore_Information, the_semaphore_id );
+ }
+#endif
+
+ the_semaphore->linked = FALSE;
+ _POSIX_Semaphore_Namespace_remove( the_semaphore );
+ _POSIX_Semaphore_Delete( the_semaphore );
+
+ _Thread_Enable_dispatch();
+ return 0;
+}
diff --git a/cpukit/posix/src/semwait.c b/cpukit/posix/src/semwait.c
new file mode 100644
index 0000000000..9ef787c727
--- /dev/null
+++ b/cpukit/posix/src/semwait.c
@@ -0,0 +1,35 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdarg.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <limits.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/posix/semaphore.h>
+#include <rtems/posix/time.h>
+#include <rtems/seterr.h>
+
+/*PAGE
+ *
+ * 11.2.6 Lock a Semaphore, P1003.1b-1993, p.226
+ *
+ * NOTE: P1003.4b/D8 adds sem_timedwait(), p. 27
+ */
+
+int sem_wait(
+ sem_t *sem
+)
+{
+ return _POSIX_Semaphore_Wait_support( sem, TRUE, THREAD_QUEUE_WAIT_FOREVER );
+}
diff --git a/cpukit/posix/src/setcancelstate.c b/cpukit/posix/src/setcancelstate.c
new file mode 100644
index 0000000000..94050bfc91
--- /dev/null
+++ b/cpukit/posix/src/setcancelstate.c
@@ -0,0 +1,61 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/posix/cancel.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/threadsup.h>
+
+/*PAGE
+ *
+ * 18.2.2 Setting Cancelability State, P1003.1c/Draft 10, p. 183
+ */
+
+int pthread_setcancelstate(
+ int state,
+ int *oldstate
+)
+{
+ POSIX_API_Control *thread_support;
+
+ /*
+ * Don't even think about deleting a resource from an ISR.
+ * Besides this request is supposed to be for _Thread_Executing
+ * and the ISR context is not a thread.
+ */
+
+ if ( _ISR_Is_in_progress() )
+ return EPROTO;
+
+ if ( !oldstate )
+ return EINVAL;
+
+ if ( state != PTHREAD_CANCEL_ENABLE && state != PTHREAD_CANCEL_DISABLE )
+ return EINVAL;
+
+ thread_support = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
+
+ _Thread_Disable_dispatch();
+ *oldstate = thread_support->cancelability_state;
+ thread_support->cancelability_state = state;
+
+ if ( thread_support->cancelability_state == PTHREAD_CANCEL_ENABLE &&
+ thread_support->cancelability_type == PTHREAD_CANCEL_ASYNCHRONOUS &&
+ thread_support->cancelation_requested )
+ _POSIX_Threads_cancel_run( _Thread_Executing );
+ _Thread_Enable_dispatch();
+
+ return 0;
+}
diff --git a/cpukit/posix/src/setcanceltype.c b/cpukit/posix/src/setcanceltype.c
new file mode 100644
index 0000000000..a7b7655f1d
--- /dev/null
+++ b/cpukit/posix/src/setcanceltype.c
@@ -0,0 +1,61 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/posix/cancel.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/threadsup.h>
+
+/*PAGE
+ *
+ * 18.2.2 Setting Cancelability State, P1003.1c/Draft 10, p. 183
+ */
+
+int pthread_setcanceltype(
+ int type,
+ int *oldtype
+)
+{
+ POSIX_API_Control *thread_support;
+
+ /*
+ * Don't even think about deleting a resource from an ISR.
+ * Besides this request is supposed to be for _Thread_Executing
+ * and the ISR context is not a thread.
+ */
+
+ if ( _ISR_Is_in_progress() )
+ return EPROTO;
+
+ if ( !oldtype )
+ return EINVAL;
+
+ if ( type != PTHREAD_CANCEL_DEFERRED && type != PTHREAD_CANCEL_ASYNCHRONOUS )
+ return EINVAL;
+
+ thread_support = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
+
+ _Thread_Disable_dispatch();
+ *oldtype = thread_support->cancelability_type;
+ thread_support->cancelability_type = type;
+
+ if ( thread_support->cancelability_state == PTHREAD_CANCEL_ENABLE &&
+ thread_support->cancelability_type == PTHREAD_CANCEL_ASYNCHRONOUS &&
+ thread_support->cancelation_requested )
+ _POSIX_Threads_cancel_run( _Thread_Executing );
+ _Thread_Enable_dispatch();
+
+ return 0;
+}
diff --git a/cpukit/posix/src/sigaction.c b/cpukit/posix/src/sigaction.c
new file mode 100644
index 0000000000..a8d48f9f3b
--- /dev/null
+++ b/cpukit/posix/src/sigaction.c
@@ -0,0 +1,93 @@
+/*
+ * 3.3.4 Examine and Change Signal Action, P1003.1b-1993, p. 70
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <signal.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/psignal.h>
+#include <rtems/seterr.h>
+#include <rtems/score/isr.h>
+
+/*
+ * PARAMETERS_PASSING_S is defined in ptimer.c
+ */
+
+extern void PARAMETERS_PASSING_S (int num_signal, const struct sigaction inf);
+
+int sigaction(
+ int sig,
+ const struct sigaction *act,
+ struct sigaction *oact
+)
+{
+ ISR_Level level;
+
+ if ( oact )
+ *oact = _POSIX_signals_Vectors[ sig ];
+
+ if ( !sig )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ if ( !is_valid_signo(sig) )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ /*
+ * Some signals cannot be ignored (P1003.1b-1993, pp. 70-72 and references.
+ *
+ * NOTE: Solaris documentation claims to "silently enforce" this which
+ * contradicts the POSIX specification.
+ */
+
+ if ( sig == SIGKILL )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ /*
+ * Evaluate the new action structure and set the global signal vector
+ * appropriately.
+ */
+
+ if ( act ) {
+
+ /*
+ * Unless the user is installing the default signal actions, then
+ * we can just copy the provided sigaction structure into the vectors.
+ */
+
+ _ISR_Disable( level );
+ if ( act->sa_handler == SIG_DFL ) {
+ _POSIX_signals_Vectors[ sig ] = _POSIX_signals_Default_vectors[ sig ];
+ } else {
+ _POSIX_signals_Clear_process_signals( signo_to_mask(sig) );
+ _POSIX_signals_Vectors[ sig ] = *act;
+ }
+ _ISR_Enable( level );
+ }
+
+ /*
+ * No need to evaluate or dispatch because:
+ *
+ * + If we were ignoring the signal before, none could be pending
+ * now (signals not posted when SIG_IGN).
+ * + If we are now ignoring a signal that was previously pending,
+ * we clear the pending signal indicator.
+ */
+
+ return 0;
+}
diff --git a/cpukit/posix/src/sigaddset.c b/cpukit/posix/src/sigaddset.c
new file mode 100644
index 0000000000..5ac0fe0f17
--- /dev/null
+++ b/cpukit/posix/src/sigaddset.c
@@ -0,0 +1,42 @@
+/*
+ * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/psignal.h>
+#include <rtems/seterr.h>
+
+int sigaddset(
+ sigset_t *set,
+ int signo
+)
+{
+ if ( !set )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ if ( !signo )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ if ( !is_valid_signo(signo) )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ *set |= signo_to_mask(signo);
+ return 0;
+}
diff --git a/cpukit/posix/src/sigdelset.c b/cpukit/posix/src/sigdelset.c
new file mode 100644
index 0000000000..be0135a7b5
--- /dev/null
+++ b/cpukit/posix/src/sigdelset.c
@@ -0,0 +1,46 @@
+/*
+ * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/psignal.h>
+#include <rtems/seterr.h>
+
+/*
+ * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
+ */
+
+int sigdelset(
+ sigset_t *set,
+ int signo
+)
+{
+ if ( !set )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ if ( !signo )
+ return 0;
+
+ if ( !is_valid_signo(signo) )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ *set &= ~signo_to_mask(signo);
+ return 0;
+}
diff --git a/cpukit/posix/src/sigemptyset.c b/cpukit/posix/src/sigemptyset.c
new file mode 100644
index 0000000000..a216ad7a8c
--- /dev/null
+++ b/cpukit/posix/src/sigemptyset.c
@@ -0,0 +1,35 @@
+/*
+ * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/psignal.h>
+#include <rtems/seterr.h>
+
+int sigemptyset(
+ sigset_t *set
+)
+{
+ if ( !set )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ *set = 0;
+ return 0;
+}
diff --git a/cpukit/posix/src/sigfillset.c b/cpukit/posix/src/sigfillset.c
new file mode 100644
index 0000000000..dd8aa82c69
--- /dev/null
+++ b/cpukit/posix/src/sigfillset.c
@@ -0,0 +1,35 @@
+/*
+ * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/psignal.h>
+#include <rtems/seterr.h>
+
+int sigfillset(
+ sigset_t *set
+)
+{
+ if ( !set )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ *set = SIGNAL_ALL_MASK;
+ return 0;
+}
diff --git a/cpukit/posix/src/sigismember.c b/cpukit/posix/src/sigismember.c
new file mode 100644
index 0000000000..3bdd32b729
--- /dev/null
+++ b/cpukit/posix/src/sigismember.c
@@ -0,0 +1,44 @@
+/*
+ * 3.3.3 Manipulate Signal Sets, P1003.1b-1993, p. 69
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/psignal.h>
+#include <rtems/seterr.h>
+
+int sigismember(
+ const sigset_t *set,
+ int signo
+)
+{
+ if ( !set )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ if ( !signo )
+ return 0;
+
+ if ( !is_valid_signo(signo) )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ if ( *set & signo_to_mask(signo) )
+ return 1;
+
+ return 0;
+}
diff --git a/cpukit/posix/src/signal_2.c b/cpukit/posix/src/signal_2.c
new file mode 100644
index 0000000000..8d9c483803
--- /dev/null
+++ b/cpukit/posix/src/signal_2.c
@@ -0,0 +1,52 @@
+/*
+ * signal(2) - Install signal handler
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <signal.h>
+#include <errno.h>
+
+typedef void (*sighandler_t)(int);
+
+sighandler_t signal(
+ int signum,
+ sighandler_t handler
+)
+{
+ struct sigaction s;
+ struct sigaction old;
+
+ s.sa_handler = handler ;
+ sigemptyset(&s.sa_mask);
+
+ /*
+ * Depending on which system we want to behave like, one of
+ * the following versions should be chosen.
+ */
+
+/* #define signal_like_linux */
+
+#if defined(signal_like_linux)
+ s.sa_flags = SA_RESTART | SA_INTERRUPT | SA_NOMASK;
+ s.sa_restorer= NULL ;
+#elif defined(signal_like_SVR4)
+ s.sa_flags = SA_RESTART;
+#else
+ s.sa_flags = 0;
+#endif
+
+ sigaction( signum, &s, &old );
+ return (sighandler_t) old.sa_handler;
+}
diff --git a/cpukit/posix/src/sigpending.c b/cpukit/posix/src/sigpending.c
new file mode 100644
index 0000000000..9f22760a58
--- /dev/null
+++ b/cpukit/posix/src/sigpending.c
@@ -0,0 +1,40 @@
+/*
+ * 3.3.6 Examine Pending Signals, P1003.1b-1993, p. 75
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <signal.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/psignal.h>
+#include <rtems/seterr.h>
+
+int sigpending(
+ sigset_t *set
+)
+{
+ POSIX_API_Control *api;
+
+ if ( !set )
+ rtems_set_errno_and_return_minus_one( EINVAL );
+
+ api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
+
+ *set = api->signals_pending | _POSIX_signals_Pending;
+
+ return 0;
+}
diff --git a/cpukit/posix/src/sigprocmask.c b/cpukit/posix/src/sigprocmask.c
new file mode 100644
index 0000000000..c149a39065
--- /dev/null
+++ b/cpukit/posix/src/sigprocmask.c
@@ -0,0 +1,39 @@
+/*
+ * 3.3.5 Examine and Change Blocked Signals, P1003.1b-1993, p. 73
+ *
+ * NOTE: P1003.1c/D10, p. 37 adds pthread_sigmask().
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <signal.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/psignal.h>
+
+int sigprocmask(
+ int how,
+ const sigset_t *set,
+ sigset_t *oset
+)
+{
+ /*
+ * P1003.1c/Draft 10, p. 38 maps sigprocmask to pthread_sigmask.
+ */
+
+ return pthread_sigmask( how, set, oset );
+}
diff --git a/cpukit/posix/src/sigqueue.c b/cpukit/posix/src/sigqueue.c
new file mode 100644
index 0000000000..727f2c6b42
--- /dev/null
+++ b/cpukit/posix/src/sigqueue.c
@@ -0,0 +1,32 @@
+/*
+ * 3.3.9 Queue a Signal to a Process, P1003.1b-1993, p. 78
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/psignal.h>
+
+int sigqueue(
+ pid_t pid,
+ int signo,
+ const union sigval value
+)
+{
+ return killinfo( pid, signo, &value );
+}
diff --git a/cpukit/posix/src/sigsuspend.c b/cpukit/posix/src/sigsuspend.c
new file mode 100644
index 0000000000..aa330bc71c
--- /dev/null
+++ b/cpukit/posix/src/sigsuspend.c
@@ -0,0 +1,53 @@
+/*
+ * 3.3.7 Wait for a Signal, P1003.1b-1993, p. 75
+ *
+ * COPYRIGHT (c) 1989-2004.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <signal.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/psignal.h>
+#include <rtems/seterr.h>
+
+int sigsuspend(
+ const sigset_t *sigmask
+)
+{
+ sigset_t saved_signals_blocked;
+ sigset_t all_signals;
+ int status;
+ POSIX_API_Control *api;
+
+ api = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
+
+ status = sigprocmask( SIG_BLOCK, sigmask, &saved_signals_blocked );
+
+ (void) sigfillset( &all_signals );
+
+ status = sigtimedwait( &all_signals, NULL, NULL );
+
+ (void) sigprocmask( SIG_SETMASK, &saved_signals_blocked, NULL );
+
+ /*
+ * sigtimedwait() returns the signal number while sigsuspend()
+ * is supposed to return -1 and EINTR when a signal is caught.
+ */
+ if ( status != -1 )
+ rtems_set_errno_and_return_minus_one( EINTR );
+
+ return status;
+}
diff --git a/cpukit/posix/src/sigtimedwait.c b/cpukit/posix/src/sigtimedwait.c
new file mode 100644
index 0000000000..1486be3054
--- /dev/null
+++ b/cpukit/posix/src/sigtimedwait.c
@@ -0,0 +1,140 @@
+/*
+ * 3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <signal.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/psignal.h>
+#include <rtems/seterr.h>
+#include <rtems/posix/time.h>
+#include <rtems/score/isr.h>
+
+int _POSIX_signals_Get_highest(
+ sigset_t set
+)
+{
+ int signo;
+
+ for ( signo = SIGRTMIN ; signo <= SIGRTMAX ; signo++ ) {
+ if ( set & signo_to_mask( signo ) )
+ return signo;
+ }
+
+/* XXX - add __SIGFIRSTNOTRT or something like that to newlib signal .h */
+
+ for ( signo = SIGHUP ; signo <= __SIGLASTNOTRT ; signo++ ) {
+ if ( set & signo_to_mask( signo ) )
+ return signo;
+ }
+
+ return 0;
+}
+
+int sigtimedwait(
+ const sigset_t *set,
+ siginfo_t *info,
+ const struct timespec *timeout
+)
+{
+ Thread_Control *the_thread;
+ POSIX_API_Control *api;
+ Watchdog_Interval interval;
+ siginfo_t signal_information;
+ siginfo_t *the_info;
+ int signo;
+ ISR_Level level;
+
+ /*
+ * Error check parameters before disabling interrupts.
+ */
+
+ interval = 0;
+ if ( timeout ) {
+
+ if ( timeout->tv_nsec < 0 ||
+ timeout->tv_nsec >= TOD_NANOSECONDS_PER_SECOND) {
+ rtems_set_errno_and_return_minus_one( EINVAL );
+ }
+
+ interval = _POSIX_Timespec_to_interval( timeout );
+ }
+
+ /*
+ * Initialize local variables.
+ */
+
+ the_info = ( info ) ? info : &signal_information;
+
+ the_thread = _Thread_Executing;
+
+ api = the_thread->API_Extensions[ THREAD_API_POSIX ];
+
+ /*
+ * What if they are already pending?
+ */
+
+ /* API signals pending? */
+
+ _ISR_Disable( level );
+ if ( *set & api->signals_pending ) {
+ /* XXX real info later */
+ the_info->si_signo = _POSIX_signals_Get_highest( api->signals_pending );
+ _POSIX_signals_Clear_signals( api, the_info->si_signo, the_info, FALSE, FALSE );
+ _ISR_Enable( level );
+
+ the_info->si_code = SI_USER;
+ the_info->si_value.sival_int = 0;
+ return the_info->si_signo;
+ }
+
+ /* Process pending signals? */
+
+ if ( *set & _POSIX_signals_Pending ) {
+ signo = _POSIX_signals_Get_highest( _POSIX_signals_Pending );
+ _POSIX_signals_Clear_signals( api, signo, the_info, TRUE, FALSE );
+ _ISR_Enable( level );
+
+ the_info->si_signo = signo;
+ the_info->si_code = SI_USER;
+ the_info->si_value.sival_int = 0;
+ return signo;
+ }
+
+ the_info->si_signo = -1;
+
+ _Thread_Disable_dispatch();
+ the_thread->Wait.queue = &_POSIX_signals_Wait_queue;
+ the_thread->Wait.return_code = EINTR;
+ the_thread->Wait.option = *set;
+ the_thread->Wait.return_argument = the_info;
+ _Thread_queue_Enter_critical_section( &_POSIX_signals_Wait_queue );
+ _ISR_Enable( level );
+ _Thread_queue_Enqueue( &_POSIX_signals_Wait_queue, interval );
+ _Thread_Enable_dispatch();
+
+ /*
+ * When the thread is set free by a signal, it is need to eliminate
+ * the signal.
+ */
+
+ _POSIX_signals_Clear_signals( api, the_info->si_signo, the_info, FALSE, FALSE );
+ errno = _Thread_Executing->Wait.return_code;
+ return the_info->si_signo;
+}
diff --git a/cpukit/posix/src/sigwait.c b/cpukit/posix/src/sigwait.c
new file mode 100644
index 0000000000..1c34b5ee5b
--- /dev/null
+++ b/cpukit/posix/src/sigwait.c
@@ -0,0 +1,44 @@
+/*
+ * 3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76
+ *
+ * NOTE: P1003.1c/D10, p. 39 adds sigwait().
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <signal.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/psignal.h>
+
+int sigwait(
+ const sigset_t *set,
+ int *sig
+)
+{
+ int status;
+
+ status = sigtimedwait( set, NULL, NULL );
+
+ if ( status != -1 ) {
+ if ( sig )
+ *sig = status;
+ return 0;
+ }
+
+ return errno;
+}
diff --git a/cpukit/posix/src/sigwaitinfo.c b/cpukit/posix/src/sigwaitinfo.c
new file mode 100644
index 0000000000..2c61e2a8fc
--- /dev/null
+++ b/cpukit/posix/src/sigwaitinfo.c
@@ -0,0 +1,33 @@
+/*
+ * 3.3.8 Synchronously Accept a Signal, P1003.1b-1993, p. 76
+ *
+ * NOTE: P1003.1c/D10, p. 39 adds sigwait().
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <signal.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/psignal.h>
+
+int sigwaitinfo(
+ const sigset_t *set,
+ siginfo_t *info
+)
+{
+ return sigtimedwait( set, info, NULL );
+}
diff --git a/cpukit/posix/src/sleep.c b/cpukit/posix/src/sleep.c
new file mode 100644
index 0000000000..501fe5770f
--- /dev/null
+++ b/cpukit/posix/src/sleep.c
@@ -0,0 +1,31 @@
+/*
+ * 3.4.3 Delay Process Execution, P1003.1b-1993, p. 81
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <time.h>
+#include <unistd.h>
+
+#include <rtems/system.h>
+
+
+unsigned int sleep(
+ unsigned int seconds
+)
+{
+ /* XXX can we get away with this implementation? */
+ struct timespec tp;
+ struct timespec tm;
+
+ tp.tv_sec = seconds;
+ tp.tv_nsec = 0;
+
+ nanosleep( &tp, &tm );
+
+ return tm.tv_sec; /* seconds remaining */
+}
diff --git a/cpukit/posix/src/sysconf.c b/cpukit/posix/src/sysconf.c
new file mode 100644
index 0000000000..4a8add9e35
--- /dev/null
+++ b/cpukit/posix/src/sysconf.c
@@ -0,0 +1,49 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <time.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/tod.h>
+
+/*PAGE
+ *
+ * 4.8.1 Get Configurable System Variables, P1003.1b-1993, p. 95
+ */
+
+long sysconf(
+ int name
+)
+{
+
+ switch (name) {
+ case _SC_CLK_TCK:
+ return _TOD_Ticks_per_second;
+
+ case _SC_OPEN_MAX: {
+ extern uint32_t rtems_libio_number_iops;
+ return rtems_libio_number_iops;
+ }
+
+ case _SC_GETPW_R_SIZE_MAX:
+ return 1024;
+
+#if defined(__sparc__)
+ case 515: /* Solaris _SC_STACK_PROT */
+ return 0;
+#endif
+
+ default:
+ break;
+ }
+
+ errno = EINVAL;
+ return -1;
+}
diff --git a/cpukit/posix/src/testcancel.c b/cpukit/posix/src/testcancel.c
new file mode 100644
index 0000000000..8d80794e2d
--- /dev/null
+++ b/cpukit/posix/src/testcancel.c
@@ -0,0 +1,46 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/posix/cancel.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/threadsup.h>
+
+/*PAGE
+ *
+ * 18.2.2 Setting Cancelability State, P1003.1c/Draft 10, p. 183
+ */
+
+void pthread_testcancel( void )
+{
+ POSIX_API_Control *thread_support;
+
+ /*
+ * Don't even think about deleting a resource from an ISR.
+ * Besides this request is supposed to be for _Thread_Executing
+ * and the ISR context is not a thread.
+ */
+
+ if ( _ISR_Is_in_progress() )
+ return;
+
+ thread_support = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
+
+ _Thread_Disable_dispatch();
+ if ( thread_support->cancelability_state == PTHREAD_CANCEL_ENABLE &&
+ thread_support->cancelation_requested )
+ _POSIX_Threads_cancel_run( _Thread_Executing );
+ _Thread_Enable_dispatch();
+}
diff --git a/cpukit/posix/src/time.c b/cpukit/posix/src/time.c
new file mode 100644
index 0000000000..69592b7318
--- /dev/null
+++ b/cpukit/posix/src/time.c
@@ -0,0 +1,52 @@
+/*
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <time.h>
+#include <errno.h>
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/tod.h>
+
+#include <rtems/seterr.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * 4.5.1 Get System Time, P1003.1b-1993, p. 91
+ */
+
+/* Using the implementation in newlib */
+#if 0
+time_t time(
+ time_t *tloc
+)
+{
+ time_t seconds_since_epoch;
+
+ /*
+ * No error is the time of day is not set. For RTEMS the system time
+ * starts out at the rtems epoch.
+ */
+
+ /*
+ * Internally the RTEMS epoch is 1988. This must be taken into account.
+ */
+
+ seconds_since_epoch = _TOD_Seconds_since_epoch;
+
+ seconds_since_epoch += POSIX_TIME_SECONDS_1970_THROUGH_1988;
+
+ if ( tloc )
+ *tloc = seconds_since_epoch;
+
+ return seconds_since_epoch;
+}
+#endif
diff --git a/cpukit/posix/src/types.c b/cpukit/posix/src/types.c
new file mode 100644
index 0000000000..d9befea289
--- /dev/null
+++ b/cpukit/posix/src/types.c
@@ -0,0 +1,46 @@
+/*
+ * This file is the shell of what it initially was and is now misnamed.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <limits.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/seterr.h>
+
+/*
+ * TEMPORARY
+ */
+
+#include <assert.h>
+
+int POSIX_MP_NOT_IMPLEMENTED()
+{
+ assert( 0 );
+ return 0;
+}
+
+int POSIX_BOTTOM_REACHED()
+{
+ assert( 0 );
+ return 0;
+}
+
+int POSIX_NOT_IMPLEMENTED()
+{
+ assert( 0 );
+ return 0;
+}
+
+/*
+ * END OF TEMPORARY
+ */
diff --git a/cpukit/posix/src/ualarm.c b/cpukit/posix/src/ualarm.c
new file mode 100644
index 0000000000..ab268d105c
--- /dev/null
+++ b/cpukit/posix/src/ualarm.c
@@ -0,0 +1,94 @@
+/*
+ * XXX 3.4.1 Schedule Alarm, P1003.1b-1993, p. 79
+ *
+ * COPYRIGHT (c) 1989-2003.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pthread.h>
+/* #include <errno.h> */
+
+#include <rtems/system.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/psignal.h>
+#include <rtems/posix/time.h>
+
+Watchdog_Control _POSIX_signals_Ualarm_timer;
+
+/*PAGE
+ *
+ * _POSIX_signals_Ualarm_TSR
+ */
+
+void _POSIX_signals_Ualarm_TSR(
+ Objects_Id id,
+ void *argument
+)
+{
+ int status;
+
+ status = kill( getpid(), SIGALRM );
+ /* XXX can't print from an ISR, should this be fatal? */
+}
+
+useconds_t ualarm(
+ useconds_t useconds,
+ useconds_t interval
+)
+{
+ useconds_t remaining = 0;
+ Watchdog_Control *the_timer;
+ Watchdog_Interval ticks;
+ struct timespec tp;
+
+ the_timer = &_POSIX_signals_Ualarm_timer;
+
+ /*
+ * Initialize the timer used to implement alarm().
+ */
+
+ if ( !the_timer->routine ) {
+ _Watchdog_Initialize( the_timer, _POSIX_signals_Ualarm_TSR, 0, NULL );
+ } else {
+ switch ( _Watchdog_Remove( the_timer ) ) {
+ case WATCHDOG_INACTIVE:
+ case WATCHDOG_BEING_INSERTED:
+ break;
+
+ case WATCHDOG_ACTIVE:
+ case WATCHDOG_REMOVE_IT:
+ /*
+ * The stop_time and start_time fields are snapshots of ticks since
+ * boot. Since alarm() is dealing in seconds, we must account for
+ * this.
+ */
+
+
+ ticks = the_timer->initial -
+ ((the_timer->stop_time - the_timer->start_time) /
+ _TOD_Ticks_per_second);
+
+ _POSIX_Interval_to_timespec( ticks, &tp );
+ remaining = tp.tv_sec * TOD_MICROSECONDS_PER_SECOND;
+ remaining += tp.tv_nsec / 1000;
+ break;
+ }
+ }
+
+ tp.tv_sec = useconds / TOD_MICROSECONDS_PER_SECOND;
+ tp.tv_nsec = (useconds % TOD_MICROSECONDS_PER_SECOND) * 1000;
+ ticks = _POSIX_Timespec_to_interval( &tp );
+ _Watchdog_Insert_ticks( the_timer, ticks );
+
+ return remaining;
+}
diff --git a/cpukit/posix/src/usleep.c b/cpukit/posix/src/usleep.c
new file mode 100644
index 0000000000..6753cfe713
--- /dev/null
+++ b/cpukit/posix/src/usleep.c
@@ -0,0 +1,34 @@
+/*
+ * XXX 3.4.3 Delay Process Execution, P1003.1b-1993, p. 81
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <time.h>
+#include <unistd.h>
+
+#include <rtems/system.h>
+#include <rtems/score/tod.h>
+
+
+unsigned usleep(
+ unsigned int useconds
+)
+{
+ struct timespec tp;
+ struct timespec tm;
+ unsigned remaining;
+
+ tp.tv_sec = useconds / TOD_MICROSECONDS_PER_SECOND;
+ tp.tv_nsec = (useconds % TOD_MICROSECONDS_PER_SECOND) * 1000;
+
+ nanosleep( &tp, &tm );
+
+ remaining = tm.tv_sec * TOD_MICROSECONDS_PER_SECOND;
+ remaining += tm.tv_nsec / 1000;
+ return remaining; /* seconds remaining */
+}
diff --git a/cpukit/posix/src/wait.c b/cpukit/posix/src/wait.c
new file mode 100644
index 0000000000..5bfa8ce943
--- /dev/null
+++ b/cpukit/posix/src/wait.c
@@ -0,0 +1,21 @@
+/*
+ * waitpid() - POSIX 1003.1b 3.2.1
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <errno.h>
+
+int wait(
+ int *stat_loc
+)
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/cpukit/posix/src/waitpid.c b/cpukit/posix/src/waitpid.c
new file mode 100644
index 0000000000..5201f56a05
--- /dev/null
+++ b/cpukit/posix/src/waitpid.c
@@ -0,0 +1,23 @@
+/*
+ * waitpid() - POSIX 1003.1 3.2.1
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <errno.h>
+
+int waitpid(
+ pid_t pid,
+ int *stat_loc,
+ int options
+)
+{
+ errno = ENOSYS;
+ return -1;
+}
diff --git a/cpukit/pppd/Makefile.am b/cpukit/pppd/Makefile.am
new file mode 100644
index 0000000000..0e278677f3
--- /dev/null
+++ b/cpukit/pppd/Makefile.am
@@ -0,0 +1,55 @@
+##
+## $Id$
+##
+
+include $(top_srcdir)/automake/compile.am
+
+CLEANFILES =
+EXTRA_LIBRARIES =
+
+if HAS_NETWORKING
+include_HEADERS = rtemspppd.h rtemsdialer.h
+
+EXTRA_LIBRARIES += libpppd.a
+CLEANFILES += libpppd.a
+libpppd_a_SOURCES = auth.c ccp.c chap.c chap_ms.c chat.c demand.c fsm.c \
+ ipcp.c lcp.c magic.c options.c upap.c md4.c md5.c utils.c sys-rtems.c \
+ rtemsmain.c rtemspppd.c
+libpppd_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libpppd_g.a
+CLEANFILES += libpppd_g.a
+libpppd_g_a_SOURCES = $(libpppd_a_SOURCES)
+libpppd_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+noinst_DATA = libpppd$(LIB_VARIANT).a
+endif
+
+# FIXME: Move sources to libpppd_a_SOURCES, remove other files.
+EXTRA_DIST = ccp.h chap.h chap_ms.h fsm.h ipcp.h ipxcp.c ipxcp.h lcp.c lcp.h \
+ magic.h md4.h md5.h patchlevel.h pathnames.h pppd.h upap.h
+
+all-local: $(PREINSTALL_FILES)
+
+PREINSTALL_DIRS =
+PREINSTALL_FILES =
+
+$(PROJECT_INCLUDE)/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)
+ @: > $(PROJECT_INCLUDE)/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/$(dirstamp)
+
+if HAS_NETWORKING
+$(PROJECT_INCLUDE)/rtemspppd.h: rtemspppd.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtemspppd.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtemspppd.h
+
+$(PROJECT_INCLUDE)/rtemsdialer.h: rtemsdialer.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtemsdialer.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtemsdialer.h
+endif
+
+CLEANFILES += $(PREINSTALL_FILES)
+DISTCLEANFILES = $(PREINSTALL_DIRS)
+
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/pppd/README b/cpukit/pppd/README
new file mode 100644
index 0000000000..28c9f7ef5d
--- /dev/null
+++ b/cpukit/pppd/README
@@ -0,0 +1,29 @@
+#
+# $Id$
+#
+
+This directory contains a port of ppp-2.3.11. The official site for
+the original source for this PPP implementation is:
+
+ftp://cs.anu.edu.au/pub/software/ppp
+
+================================================================
+History
+
+The original port was of 2.3.5 by Tomasz Domin <dot@comarch.pl> of
+ComArch SA and was initially only tested on the mpc823. He
+provided the modem driver as well.
+
+The port was updated to 2.3.11 by Mike Siers <mikes@poliac.com>
+who added an example test.
+
+Updated the chat program to return the correct errors and support
+the ABORT commands. Removed some dead code and did a lot of
+testing on a new Coldfire BSP. Version seems to be very stable.
+
+Update code to use RTEMS pppd network drivers. Now the pppd
+software is not dependent on using task driven mode. This
+change improved stablity and performance. This was updated
+by Mike Siers <mikes@poliac.com>.
+=================================================================
+
diff --git a/cpukit/pppd/STATUS b/cpukit/pppd/STATUS
new file mode 100644
index 0000000000..4c0d35d423
--- /dev/null
+++ b/cpukit/pppd/STATUS
@@ -0,0 +1,27 @@
+#
+# $Id$
+#
+
+The pppd application seems to very stable. It has been tested using
+the example application with the i386/pc586 and m68k/sbc5206e BSPs.
+The tests were executed using a null modem serial cable to connect
+with a UNIX box running either the ppp or pppd application and with
+an external modem to dial up a local ISP.
+
+If you have problems getting your target to make consistent connections
+with an ISP, the problem is most likely with the ppp options. First
+try using the "novj" and "noaccomp" options. If you have questions
+about what other option values are available for the rtems_pppd_set_option
+function, please look at the pppd.8 man page file or the the source code.
+The majority of options that are documented in man page should work
+with this function call.
+
+The pppd code had now been updated to use it's own RTEMS network
+drivers. This removes the requirement for the task driven termios
+support. This update has fixed the large packet ping problem.
+Currently, I do not know of any problems with the port.
+
+If you find any other problems or fix some problems, please post your
+changes to the RTEMS mailing list.
+
+Good Luck
diff --git a/cpukit/pppd/auth.c b/cpukit/pppd/auth.c
new file mode 100644
index 0000000000..a92654a650
--- /dev/null
+++ b/cpukit/pppd/auth.c
@@ -0,0 +1,1121 @@
+/*
+ * auth.c - PPP authentication and phase control.
+ *
+ * Copyright (c) 1993 The Australian National University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the Australian National University. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#define RCSID "$Id$"
+
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#if defined(_PATH_LASTLOG) && defined(_linux_)
+#include <lastlog.h>
+#endif
+
+#include <netdb.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#ifdef USE_PAM
+#include <security/pam_appl.h>
+#endif
+
+#ifdef HAS_SHADOW
+#include <shadow.h>
+#ifndef PW_PPP
+#define PW_PPP PW_LOGIN
+#endif
+#endif
+
+#include "pppd.h"
+#include "fsm.h"
+#include "lcp.h"
+#include "ipcp.h"
+#include "upap.h"
+#include "chap.h"
+#ifdef CBCP_SUPPORT
+#include "cbcp.h"
+#endif
+#include "pathnames.h"
+
+static const char rcsid[] = RCSID;
+
+/* The name by which the peer authenticated itself to us. */
+char peer_authname[MAXNAMELEN];
+
+/* Records which authentication operations haven't completed yet. */
+static int auth_pending[NUM_PPP];
+
+/* List of addresses which the peer may use. */
+static struct permitted_ip *addresses[NUM_PPP];
+
+/* Wordlist giving addresses which the peer may use
+ without authenticating itself. */
+static struct wordlist *noauth_addrs;
+
+/* Extra options to apply, from the secrets file entry for the peer. */
+static struct wordlist *extra_options;
+
+/* Number of network protocols which we have opened. */
+static int num_np_open;
+
+/* Number of network protocols which have come up. */
+static int num_np_up;
+
+/* Set if we got the contents of passwd[] from the pap-secrets file. */
+static int passwd_from_file;
+
+/* Set if we require authentication only because we have a default route. */
+static bool default_auth;
+
+/* Hook for a link status */
+void (*auth_linkup_hook)__P((void)) = NULL;
+void (*auth_linkdown_hook)__P((void)) = NULL;
+
+/* Hook to enable a plugin to control the idle time limit */
+int (*idle_time_hook) __P((struct ppp_idle *)) = NULL;
+
+/* Hook for a plugin to say whether we can possibly authenticate any peer */
+int (*pap_check_hook) __P((void)) = NULL;
+
+/* Hook for a plugin to check the PAP user and password */
+int (*pap_auth_hook) __P((char *user, char *passwd/*, char **msgp,
+ struct wordlist **paddrs,
+ struct wordlist **popts*/)) = NULL;
+
+/* Hook for a plugin to know about the PAP user logout */
+void (*pap_logout_hook) __P((void)) = NULL;
+
+/* Hook for a plugin to get the PAP password for authenticating us */
+int (*pap_passwd_hook) __P((char *user, char *passwd)) = NULL;
+
+/*
+ * This is used to ensure that we don't start an auth-up/down
+ * script while one is already running.
+ */
+enum script_state {
+ s_down,
+ s_up
+};
+
+static enum script_state auth_state = s_down;
+static enum script_state auth_script_state = s_down;
+
+/*
+ * Option variables.
+ */
+bool uselogin = 0; /* Use /etc/passwd for checking PAP */
+bool cryptpap = 0; /* Passwords in pap-secrets are encrypted */
+bool refuse_pap = 0; /* Don't wanna auth. ourselves with PAP */
+bool refuse_chap = 0; /* Don't wanna auth. ourselves with CHAP */
+bool usehostname = 0; /* Use hostname for our_name */
+bool auth_required = 0; /* Always require authentication from peer */
+bool allow_any_ip = 0; /* Allow peer to use any IP address */
+bool explicit_remote = 0; /* User specified explicit remote name */
+char remote_name[MAXNAMELEN]; /* Peer's name for authentication */
+
+/* Bits in auth_pending[] */
+#define PAP_WITHPEER 1
+#define PAP_PEER 2
+#define CHAP_WITHPEER 4
+#define CHAP_PEER 8
+
+extern char *crypt __P((const char *, const char *));
+
+/* Prototypes for procedures local to this file. */
+
+static void network_phase __P((int));
+static void check_idle __P((void *));
+static void connect_time_expired __P((void *));
+static int null_login __P((int));
+static int get_pap_passwd __P((char *));
+static int have_pap_secret __P((int *));
+static int have_chap_secret __P((char *, char *, int, int *));
+#if 0
+static int ip_addr_check __P((u_int32_t, struct permitted_ip *));
+#endif
+static void free_wordlist __P((struct wordlist *));
+static void auth_script __P((enum script_state s));
+static void set_allowed_addrs __P((int, struct wordlist *, struct wordlist *));
+
+
+/*
+ * Authentication-related options.
+ */
+option_t auth_options[] = {
+ { "require-pap", o_bool, &lcp_wantoptions[0].neg_upap,
+ "Require PAP authentication from peer", 1, &auth_required },
+ { "+pap", o_bool, &lcp_wantoptions[0].neg_upap,
+ "Require PAP authentication from peer", 1, &auth_required },
+ { "refuse-pap", o_bool, &refuse_pap,
+ "Don't agree to auth to peer with PAP", 1 },
+ { "-pap", o_bool, &refuse_pap,
+ "Don't allow PAP authentication with peer", 1 },
+ { "require-chap", o_bool, &lcp_wantoptions[0].neg_chap,
+ "Require CHAP authentication from peer", 1, &auth_required },
+ { "+chap", o_bool, &lcp_wantoptions[0].neg_chap,
+ "Require CHAP authentication from peer", 1, &auth_required },
+ { "refuse-chap", o_bool, &refuse_chap,
+ "Don't agree to auth to peer with CHAP", 1 },
+ { "-chap", o_bool, &refuse_chap,
+ "Don't allow CHAP authentication with peer", 1 },
+ { "name", o_string, our_name,
+ "Set local name for authentication",
+ OPT_PRIV|OPT_STATIC, NULL, MAXNAMELEN },
+ { "user", o_string, user,
+ "Set name for auth with peer", OPT_STATIC, NULL, MAXNAMELEN },
+ { "usehostname", o_bool, &usehostname,
+ "Must use hostname for authentication", 1 },
+ { "remotename", o_string, remote_name,
+ "Set remote name for authentication", OPT_STATIC,
+ &explicit_remote, MAXNAMELEN },
+ { "auth", o_bool, &auth_required,
+ "Require authentication from peer", 1 },
+ { "noauth", o_bool, &auth_required,
+ "Don't require peer to authenticate", OPT_PRIV, &allow_any_ip },
+ { "login", o_bool, &uselogin,
+ "Use system password database for PAP", 1 },
+ { "papcrypt", o_bool, &cryptpap,
+ "PAP passwords are encrypted", 1 },
+/* Removed for RTEMS PORT
+ { "+ua", o_special, setupapfile,
+ "Get PAP user and password from file" },
+*/
+ { "password", o_string, passwd,
+ "Password for authenticating us to the peer", OPT_STATIC,
+ NULL, MAXSECRETLEN },
+/* Removed for RTEMS_PORT
+ { "privgroup", o_special, privgroup,
+ "Allow group members to use privileged options", OPT_PRIV },
+ { "allow-ip", o_special, set_noauth_addr,
+ "Set IP address(es) which can be used without authentication",
+ OPT_PRIV },
+*/
+ { NULL }
+};
+
+/*
+ * An Open on LCP has requested a change from Dead to Establish phase.
+ * Do what's necessary to bring the physical layer up.
+ */
+void
+link_required(unit)
+ int unit;
+{
+}
+
+/*
+ * LCP has terminated the link; go to the Dead phase and take the
+ * physical layer down.
+ */
+void
+link_terminated(unit)
+ int unit;
+{
+ if (pppd_phase == PHASE_DEAD)
+ return;
+ if (pap_logout_hook) {
+ pap_logout_hook();
+ }
+ new_phase(PHASE_DEAD);
+ notice("Connection terminated.");
+}
+
+/*
+ * LCP has gone down; it will either die or try to re-establish.
+ */
+void
+link_down(unit)
+ int unit;
+{
+ int i;
+ struct protent *protp;
+
+ auth_state = s_down;
+ if (auth_script_state == s_up) {
+ update_link_stats(unit);
+ auth_script(s_down);
+ }
+ for (i = 0; (protp = protocols[i]) != NULL; ++i) {
+ if (!protp->enabled_flag)
+ continue;
+ if (protp->protocol != PPP_LCP && protp->lowerdown != NULL)
+ (*protp->lowerdown)(unit);
+ if (protp->protocol < 0xC000 && protp->close != NULL)
+ (*protp->close)(unit, "LCP down");
+ }
+ num_np_open = 0;
+ num_np_up = 0;
+ if (pppd_phase != PHASE_DEAD)
+ new_phase(PHASE_TERMINATE);
+}
+
+/*
+ * The link is established.
+ * Proceed to the Dead, Authenticate or Network phase as appropriate.
+ */
+void
+link_established(unit)
+ int unit;
+{
+ int auth;
+ lcp_options *wo = &lcp_wantoptions[unit];
+ lcp_options *go = &lcp_gotoptions[unit];
+ lcp_options *ho = &lcp_hisoptions[unit];
+ int i;
+ struct protent *protp;
+
+ /*
+ * Tell higher-level protocols that LCP is up.
+ */
+ for (i = 0; (protp = protocols[i]) != NULL; ++i)
+ if (protp->protocol != PPP_LCP && protp->enabled_flag
+ && protp->lowerup != NULL)
+ (*protp->lowerup)(unit);
+
+ if (auth_required && !(go->neg_chap || go->neg_upap)) {
+ /*
+ * We wanted the peer to authenticate itself, and it refused:
+ * if we have some address(es) it can use without auth, fine,
+ * otherwise treat it as though it authenticated with PAP using
+ * a username * of "" and a password of "". If that's not OK,
+ * boot it out.
+ */
+ if (noauth_addrs != NULL) {
+ set_allowed_addrs(unit, noauth_addrs, NULL);
+ } else if (!wo->neg_upap || !null_login(unit)) {
+ warn("peer refused to authenticate: terminating link");
+ lcp_close(unit, "peer refused to authenticate");
+ pppd_status = EXIT_PEER_AUTH_FAILED;
+ return;
+ }
+ }
+
+ new_phase(PHASE_AUTHENTICATE);
+ auth = 0;
+ if (go->neg_chap) {
+ ChapAuthPeer(unit, our_name, go->chap_mdtype);
+ auth |= CHAP_PEER;
+ } else if (go->neg_upap) {
+ upap_authpeer(unit);
+ auth |= PAP_PEER;
+ }
+ if (ho->neg_chap) {
+ ChapAuthWithPeer(unit, user, ho->chap_mdtype);
+ auth |= CHAP_WITHPEER;
+ } else if (ho->neg_upap) {
+ if (passwd[0] == 0) {
+ passwd_from_file = 1;
+ if (!get_pap_passwd(passwd))
+ error("No secret found for PAP login");
+ }
+ upap_authwithpeer(unit, user, passwd);
+ auth |= PAP_WITHPEER;
+ }
+ auth_pending[unit] = auth;
+
+ if (!auth)
+ network_phase(unit);
+}
+
+/*
+ * Proceed to the network phase.
+ */
+static void
+network_phase(unit)
+ int unit;
+{
+#ifdef CBCP_SUPPORT
+ lcp_options *go = &lcp_gotoptions[unit];
+#endif
+
+ /* always run the auth-up script */
+ auth_state = s_up;
+ if (auth_script_state == s_down) {
+ auth_script(s_up);
+ }
+
+#ifdef CBCP_SUPPORT
+ /*
+ * If we negotiated callback, do it now.
+ */
+ if (go->neg_cbcp) {
+ new_phase(PHASE_CALLBACK);
+ (*cbcp_protent.open)(unit);
+ return;
+ }
+#endif
+
+ /*
+ * Process extra options from the secrets file
+ */
+ if (extra_options) {
+ options_from_list(extra_options, 1);
+ free_wordlist(extra_options);
+ extra_options = 0;
+ }
+ start_networks();
+}
+
+void
+start_networks()
+{
+ int i;
+ struct protent *protp;
+
+ new_phase(PHASE_NETWORK);
+ for (i = 0; (protp = protocols[i]) != NULL; ++i)
+ if (protp->protocol < 0xC000 && protp->enabled_flag
+ && protp->open != NULL) {
+ (*protp->open)(0);
+ if (protp->protocol != PPP_CCP)
+ ++num_np_open;
+ }
+
+ if (num_np_open == 0)
+ /* nothing to do */
+ lcp_close(0, "No network protocols running");
+}
+
+/*
+ * The peer has failed to authenticate himself using `protocol'.
+ */
+void
+auth_peer_fail(unit, protocol)
+ int unit, protocol;
+{
+ /*
+ * Authentication failure: take the link down
+ */
+ lcp_close(unit, "Authentication failed");
+ pppd_status = EXIT_PEER_AUTH_FAILED;
+}
+
+/*
+ * The peer has been successfully authenticated using `protocol'.
+ */
+void
+auth_peer_success(unit, protocol, name, namelen)
+ int unit, protocol;
+ char *name;
+ int namelen;
+{
+ int bit;
+
+ switch (protocol) {
+ case PPP_CHAP:
+ bit = CHAP_PEER;
+ break;
+ case PPP_PAP:
+ bit = PAP_PEER;
+ break;
+ default:
+ warn("auth_peer_success: unknown protocol %x", protocol);
+ return;
+ }
+
+ /*
+ * Save the authenticated name of the peer for later.
+ */
+ if (namelen > sizeof(peer_authname) - 1)
+ namelen = sizeof(peer_authname) - 1;
+ BCOPY(name, peer_authname, namelen);
+ peer_authname[namelen] = 0;
+
+ /*
+ * If there is no more authentication still to be done,
+ * proceed to the network (or callback) phase.
+ */
+ if ((auth_pending[unit] &= ~bit) == 0)
+ network_phase(unit);
+}
+
+/*
+ * We have failed to authenticate ourselves to the peer using `protocol'.
+ */
+void
+auth_withpeer_fail(unit, protocol)
+ int unit, protocol;
+{
+ if (passwd_from_file)
+ BZERO(passwd, MAXSECRETLEN);
+ /*
+ * We've failed to authenticate ourselves to our peer.
+ * Some servers keep sending CHAP challenges, but there
+ * is no point in persisting without any way to get updated
+ * authentication secrets.
+ */
+ lcp_close(unit, "Failed to authenticate ourselves to peer");
+ pppd_status = EXIT_AUTH_TOPEER_FAILED;
+}
+
+/*
+ * We have successfully authenticated ourselves with the peer using `protocol'.
+ */
+void
+auth_withpeer_success(unit, protocol)
+ int unit, protocol;
+{
+ int bit;
+
+ switch (protocol) {
+ case PPP_CHAP:
+ bit = CHAP_WITHPEER;
+ break;
+ case PPP_PAP:
+ if (passwd_from_file)
+ BZERO(passwd, MAXSECRETLEN);
+ bit = PAP_WITHPEER;
+ break;
+ default:
+ warn("auth_withpeer_success: unknown protocol %x", protocol);
+ bit = 0;
+ }
+
+ /*
+ * If there is no more authentication still being done,
+ * proceed to the network (or callback) phase.
+ */
+ if ((auth_pending[unit] &= ~bit) == 0)
+ network_phase(unit);
+}
+
+
+/*
+ * np_up - a network protocol has come up.
+ */
+void
+np_up(unit, proto)
+ int unit, proto;
+{
+ int tlim;
+
+ if (num_np_up == 0) {
+ /*
+ * At this point we consider that the link has come up successfully.
+ */
+ pppd_status = EXIT_OK;
+ unsuccess = 0;
+ new_phase(PHASE_RUNNING);
+
+ if (idle_time_hook != 0)
+ tlim = (*idle_time_hook)(NULL);
+ else
+ tlim = idle_time_limit;
+ if (tlim > 0)
+ TIMEOUT(check_idle, NULL, tlim);
+
+ /*
+ * Set a timeout to close the connection once the maximum
+ * connect time has expired.
+ */
+ if (maxconnect > 0)
+ TIMEOUT(connect_time_expired, 0, maxconnect);
+ }
+ ++num_np_up;
+}
+
+/*
+ * np_down - a network protocol has gone down.
+ */
+void
+np_down(unit, proto)
+ int unit, proto;
+{
+ if (--num_np_up == 0) {
+ UNTIMEOUT(check_idle, NULL);
+ new_phase(PHASE_NETWORK);
+ }
+}
+
+/*
+ * np_finished - a network protocol has finished using the link.
+ */
+void
+np_finished(unit, proto)
+ int unit, proto;
+{
+ if (--num_np_open <= 0) {
+ /* no further use for the link: shut up shop. */
+ lcp_close(0, "No network protocols running");
+ }
+}
+
+/*
+ * check_idle - check whether the link has been idle for long
+ * enough that we can shut it down.
+ */
+static void
+check_idle(arg)
+ void *arg;
+{
+ struct ppp_idle idle;
+ time_t itime;
+ int tlim;
+
+ if (!get_idle_time(0, &idle))
+ return;
+ if (idle_time_hook != 0) {
+ tlim = idle_time_hook(&idle);
+ } else {
+ itime = MIN(idle.xmit_idle, idle.recv_idle);
+ tlim = idle_time_limit - itime;
+ }
+ if (tlim <= 0) {
+ /* link is idle: shut it down. */
+ notice("Terminating connection due to lack of activity.");
+ lcp_close(0, "Link inactive");
+ need_holdoff = 0;
+ pppd_status = EXIT_IDLE_TIMEOUT;
+ } else {
+ TIMEOUT(check_idle, NULL, tlim);
+ }
+}
+
+/*
+ * connect_time_expired - log a message and close the connection.
+ */
+static void
+connect_time_expired(arg)
+ void *arg;
+{
+ info("Connect time expired");
+ lcp_close(0, "Connect time expired"); /* Close connection */
+ pppd_status = EXIT_CONNECT_TIME;
+}
+
+/*
+ * auth_check_options - called to check authentication options.
+ */
+int
+auth_check_options()
+{
+ lcp_options *wo = &lcp_wantoptions[0];
+ int status = 1;
+ int can_auth;
+ int lacks_ip;
+
+ /* Default our_name to hostname, and user to our_name */
+ if (our_name[0] == 0 || usehostname)
+ strlcpy(our_name, hostname, sizeof(our_name));
+ if (user[0] == 0)
+ strlcpy(user, our_name, sizeof(user));
+
+ /*
+ * If we have a default route, require the peer to authenticate
+ * unless the noauth option was given or the real user is root.
+ */
+ if (!auth_required && !allow_any_ip && have_route_to(0) && !privileged) {
+ printf("auth_check_options: turning on\n");
+ auth_required = 1;
+ default_auth = 1;
+ }
+
+ /* If authentication is required, ask peer for CHAP or PAP. */
+ if (auth_required) {
+ if (!wo->neg_chap && !wo->neg_upap) {
+ wo->neg_chap = 1;
+ wo->neg_upap = 1;
+ }
+ } else {
+ wo->neg_chap = 0;
+ wo->neg_upap = 0;
+ }
+
+ /*
+ * Check whether we have appropriate secrets to use
+ * to authenticate the peer.
+ */
+ lacks_ip = 0;
+ can_auth = wo->neg_upap && (uselogin || have_pap_secret(&lacks_ip));
+ if (!can_auth && wo->neg_chap) {
+ can_auth = have_chap_secret((explicit_remote? remote_name: NULL),
+ our_name, 1, &lacks_ip);
+ }
+
+ if (auth_required && !can_auth && noauth_addrs == NULL) {
+ if (default_auth) {
+ option_error(
+"By default the remote system is required to authenticate itself");
+ option_error(
+"(because this system has a default route to the internet)");
+ } else if (explicit_remote)
+ option_error(
+"The remote system (%s) is required to authenticate itself",
+ remote_name);
+ else
+ option_error(
+"The remote system is required to authenticate itself");
+ option_error(
+"but I couldn't find any suitable secret (password) for it to use to do so.");
+ if (lacks_ip)
+ option_error(
+"(None of the available passwords would let it use an IP address.)");
+
+ status = 0;
+ }
+ return ( status );
+}
+
+/*
+ * auth_reset - called when LCP is starting negotiations to recheck
+ * authentication options, i.e. whether we have appropriate secrets
+ * to use for authenticating ourselves and/or the peer.
+ */
+void
+auth_reset(unit)
+ int unit;
+{
+ lcp_options *go = &lcp_gotoptions[unit];
+ lcp_options *ao = &lcp_allowoptions[0];
+
+ ao->neg_upap = !refuse_pap && (passwd[0] != 0 || get_pap_passwd(NULL));
+ ao->neg_chap = !refuse_chap
+ && (passwd[0] != 0
+ || have_chap_secret(user, (explicit_remote? remote_name: NULL),
+ 0, NULL));
+
+ if (go->neg_upap && !uselogin && !have_pap_secret(NULL))
+ go->neg_upap = 0;
+ if (go->neg_chap) {
+ if (!have_chap_secret((explicit_remote? remote_name: NULL),
+ our_name, 1, NULL))
+ go->neg_chap = 0;
+ }
+}
+
+
+/*
+ * check_passwd - Check the user name and passwd against the PAP secrets
+ * file. If requested, also check against the system password database,
+ * and login the user if OK.
+ *
+ * returns:
+ * UPAP_AUTHNAK: Authentication failed.
+ * UPAP_AUTHACK: Authentication succeeded.
+ * In either case, msg points to an appropriate message.
+ */
+int
+check_passwd(unit, auser, userlen, apasswd, passwdlen, msg)
+ int unit;
+ char *auser;
+ int userlen;
+ char *apasswd;
+ int passwdlen;
+ char **msg;
+{
+ char passwd[64], user[64];
+
+ if (pap_auth_hook)
+ {
+ slprintf(passwd, sizeof(passwd), "%.*v", passwdlen, apasswd);
+ slprintf(user, sizeof(user), "%.*v", userlen, auser);
+
+ return (*pap_auth_hook)(user, passwd/*, NULL, NULL, NULL*/) ?
+ UPAP_AUTHACK : UPAP_AUTHNAK;
+ }
+
+ return UPAP_AUTHACK;
+
+#if 0
+ int ret = (int)UPAP_AUTHNAK;
+
+ if (( userlen == 0 ) && ( passwdlen == 0 )) {
+ ret = (int)UPAP_AUTHACK;
+ }
+ printf("check_passwd: %d\n", ret);
+
+ return ret;
+#endif
+}
+
+/*
+ * null_login - Check if a username of "" and a password of "" are
+ * acceptable, and iff so, set the list of acceptable IP addresses
+ * and return 1.
+ */
+static int
+null_login(unit)
+ int unit;
+{
+ return 0;
+}
+
+
+/*
+ * get_pap_passwd - get a password for authenticating ourselves with
+ * our peer using PAP. Returns 1 on success, 0 if no suitable password
+ * could be found.
+ * Assumes passwd points to MAXSECRETLEN bytes of space (if non-null).
+ */
+static int
+get_pap_passwd(passwd)
+ char *passwd;
+{
+ int ret = (int)0;
+
+ /*
+ * Check whether a plugin wants to supply this.
+ */
+ if (pap_passwd_hook) {
+ ret = (*pap_passwd_hook)(user, passwd);
+ }
+
+ return ( ret );
+}
+
+
+/*
+ * have_pap_secret - check whether we have a PAP file with any
+ * secrets that we could possibly use for authenticating the peer.
+ */
+static int
+have_pap_secret(lacks_ipp)
+ int *lacks_ipp;
+{
+ return 1;
+
+#if 0
+ int ret = (int)0;
+
+ /* let the plugin decide, if there is one */
+ printf("have_pap_secret:\n");
+ if (pap_check_hook) {
+ ret = (*pap_check_hook)();
+ }
+
+ return ( ret );
+#endif
+}
+
+
+/*
+ * have_chap_secret - check whether we have a CHAP file with a
+ * secret that we could possibly use for authenticating `client'
+ * on `server'. Either can be the null string, meaning we don't
+ * know the identity yet.
+ */
+static int
+have_chap_secret(client, server, need_ip, lacks_ipp)
+ char *client;
+ char *server;
+ int need_ip;
+ int *lacks_ipp;
+{
+ return 0;
+}
+
+
+/*
+ * get_secret - open the CHAP secret file and return the secret
+ * for authenticating the given client on the given server.
+ * (We could be either client or server).
+ */
+int
+get_secret(unit, client, server, secret, secret_len, am_server)
+ int unit;
+ char *client;
+ char *server;
+ char *secret;
+ int *secret_len;
+ int am_server;
+{
+ int len;
+ char secbuf[MAXWORDLEN];
+
+ if (!am_server && passwd[0] != 0) {
+ strlcpy(secbuf, passwd, sizeof(secbuf));
+ } else {
+ return 0;
+ }
+
+ len = strlen(secbuf);
+ if (len > MAXSECRETLEN) {
+ error("Secret for %s on %s is too long", client, server);
+ len = MAXSECRETLEN;
+ }
+ BCOPY(secbuf, secret, len);
+ BZERO(secbuf, sizeof(secbuf));
+ *secret_len = len;
+
+ return 1;
+}
+
+/*
+ * set_allowed_addrs() - set the list of allowed addresses.
+ * Also looks for `--' indicating options to apply for this peer
+ * and leaves the following words in extra_options.
+ */
+static void
+set_allowed_addrs(unit, addrs, opts)
+ int unit;
+ struct wordlist *addrs;
+ struct wordlist *opts;
+{
+ int n;
+ struct wordlist *ap, **pap;
+ struct permitted_ip *ip;
+ char *ptr_word, *ptr_mask;
+ struct hostent *hp;
+ struct netent *np;
+ u_int32_t a, mask, ah, offset;
+ struct ipcp_options *wo = &ipcp_wantoptions[unit];
+ u_int32_t suggested_ip = 0;
+
+ if (addresses[unit] != NULL)
+ free(addresses[unit]);
+ addresses[unit] = NULL;
+ if (extra_options != NULL)
+ free_wordlist(extra_options);
+ extra_options = opts;
+
+ /*
+ * Count the number of IP addresses given.
+ */
+ for (n = 0, pap = &addrs; (ap = *pap) != NULL; pap = &ap->next)
+ ++n;
+ if (n == 0)
+ return;
+ ip = (struct permitted_ip *) malloc((n + 1) * sizeof(struct permitted_ip));
+ if (ip == 0)
+ return;
+
+ n = 0;
+ for (ap = addrs; ap != NULL; ap = ap->next) {
+ /* "-" means no addresses authorized, "*" means any address allowed */
+ ptr_word = ap->word;
+ if (strcmp(ptr_word, "-") == 0)
+ break;
+ if (strcmp(ptr_word, "*") == 0) {
+ ip[n].permit = 1;
+ ip[n].base = ip[n].mask = 0;
+ ++n;
+ break;
+ }
+
+ ip[n].permit = 1;
+ if (*ptr_word == '!') {
+ ip[n].permit = 0;
+ ++ptr_word;
+ }
+
+ mask = ~ (u_int32_t) 0;
+ offset = 0;
+ ptr_mask = strchr (ptr_word, '/');
+ if (ptr_mask != NULL) {
+ int bit_count;
+ char *endp;
+
+ bit_count = (int) strtol (ptr_mask+1, &endp, 10);
+ if (bit_count <= 0 || bit_count > 32) {
+ warn("invalid address length %v in auth. address list",
+ ptr_mask+1);
+ continue;
+ }
+ bit_count = 32 - bit_count; /* # bits in host part */
+ if (*endp == '+') {
+ offset = pppifunit + 1;
+ ++endp;
+ }
+ if (*endp != 0) {
+ warn("invalid address length syntax: %v", ptr_mask+1);
+ continue;
+ }
+ *ptr_mask = '\0';
+ mask <<= bit_count;
+ }
+
+ hp = gethostbyname(ptr_word);
+ if (hp != NULL && hp->h_addrtype == AF_INET) {
+ a = *(u_int32_t *)hp->h_addr;
+ } else {
+ np = getnetbyname (ptr_word);
+ if (np != NULL && np->n_addrtype == AF_INET) {
+ a = htonl (*(u_int32_t *)np->n_net);
+ if (ptr_mask == NULL) {
+ /* calculate appropriate mask for net */
+ ah = ntohl(a);
+ if (IN_CLASSA(ah))
+ mask = IN_CLASSA_NET;
+ else if (IN_CLASSB(ah))
+ mask = IN_CLASSB_NET;
+ else if (IN_CLASSC(ah))
+ mask = IN_CLASSC_NET;
+ }
+ } else {
+ a = inet_addr (ptr_word);
+ }
+ }
+
+ if (ptr_mask != NULL)
+ *ptr_mask = '/';
+
+ if (a == (u_int32_t)-1L) {
+ warn("unknown host %s in auth. address list", ap->word);
+ continue;
+ }
+ if (offset != 0) {
+ if (offset >= ~mask) {
+ warn("interface unit %d too large for subnet %v",
+ pppifunit, ptr_word);
+ continue;
+ }
+ a = htonl((ntohl(a) & mask) + offset);
+ mask = ~(u_int32_t)0;
+ }
+ ip[n].mask = htonl(mask);
+ ip[n].base = a & ip[n].mask;
+ ++n;
+ if (~mask == 0 && suggested_ip == 0)
+ suggested_ip = a;
+ }
+
+ ip[n].permit = 0; /* make the last entry forbid all addresses */
+ ip[n].base = 0; /* to terminate the list */
+ ip[n].mask = 0;
+
+ addresses[unit] = ip;
+
+ /*
+ * If the address given for the peer isn't authorized, or if
+ * the user hasn't given one, AND there is an authorized address
+ * which is a single host, then use that if we find one.
+ */
+ if (suggested_ip != 0
+ && (wo->hisaddr == 0 || !auth_ip_addr(unit, wo->hisaddr)))
+ wo->hisaddr = suggested_ip;
+}
+
+/*
+ * auth_ip_addr - check whether the peer is authorized to use
+ * a given IP address. Returns 1 if authorized, 0 otherwise.
+ */
+int
+auth_ip_addr(unit, addr)
+ int unit;
+ u_int32_t addr;
+{
+#if 0
+ int ok;
+#endif
+
+ /* don't allow loopback or multicast address */
+ if (bad_ip_adrs(addr))
+ return 0;
+
+ return 1;
+
+#if 0
+ if (addresses[unit] != NULL) {
+ ok = ip_addr_check(addr, addresses[unit]);
+ if (ok >= 0)
+ return ok;
+ }
+ if (auth_required)
+ return 0; /* no addresses authorized */
+ return allow_any_ip || !have_route_to(addr);
+#endif
+}
+
+#if 0
+static int
+ip_addr_check(addr, addrs)
+ u_int32_t addr;
+ struct permitted_ip *addrs;
+{
+ for (; ; ++addrs)
+ if ((addr & addrs->mask) == addrs->base)
+ return addrs->permit;
+}
+#endif
+
+/*
+ * bad_ip_adrs - return 1 if the IP address is one we don't want
+ * to use, such as an address in the loopback net or a multicast address.
+ * addr is in network byte order.
+ */
+int
+bad_ip_adrs(addr)
+ u_int32_t addr;
+{
+ addr = ntohl(addr);
+ return (addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET
+ || IN_MULTICAST(addr) || IN_BADCLASS(addr);
+}
+
+/*
+ * free_wordlist - release memory allocated for a wordlist.
+ */
+static void
+free_wordlist(wp)
+ struct wordlist *wp;
+{
+ struct wordlist *next;
+
+ while (wp != NULL) {
+ next = wp->next;
+ free(wp);
+ wp = next;
+ }
+}
+
+/*
+ * auth_script - execute a script with arguments
+ * interface-name peer-name real-user tty speed
+ */
+static void
+auth_script(s)
+ enum script_state s;
+{
+ switch (s) {
+ case s_up:
+ auth_script_state = s_up;
+ if ( auth_linkup_hook ) {
+ (*auth_linkup_hook)();
+ }
+ break;
+ case s_down:
+ auth_script_state = s_down;
+ if ( auth_linkdown_hook ) {
+ (*auth_linkdown_hook)();
+ }
+ break;
+ }
+}
diff --git a/cpukit/pppd/cbcp.c b/cpukit/pppd/cbcp.c
new file mode 100644
index 0000000000..eb60a8e249
--- /dev/null
+++ b/cpukit/pppd/cbcp.c
@@ -0,0 +1,456 @@
+/*
+ * cbcp - Call Back Configuration Protocol.
+ *
+ * Copyright (c) 1995 Pedro Roque Marques
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Pedro Roque Marques. 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#define RCSID "$Id$"
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include "pppd.h"
+#include "cbcp.h"
+#include "fsm.h"
+#include "lcp.h"
+
+static const char rcsid[] = RCSID;
+
+/*
+ * Options.
+ */
+static int setcbcp __P((char **));
+
+static option_t cbcp_option_list[] = {
+ { "callback", o_special, setcbcp,
+ "Ask for callback" },
+ { NULL }
+};
+
+/*
+ * Protocol entry points.
+ */
+static void cbcp_init __P((int unit));
+static void cbcp_open __P((int unit));
+static void cbcp_lowerup __P((int unit));
+static void cbcp_input __P((int unit, u_char *pkt, int len));
+static void cbcp_protrej __P((int unit));
+static int cbcp_printpkt __P((u_char *pkt, int len,
+ void (*printer) __P((void *, char *, ...)),
+ void *arg));
+
+struct protent cbcp_protent = {
+ PPP_CBCP,
+ cbcp_init,
+ cbcp_input,
+ cbcp_protrej,
+ cbcp_lowerup,
+ NULL,
+ cbcp_open,
+ NULL,
+ cbcp_printpkt,
+ NULL,
+ 0,
+ "CBCP",
+ NULL,
+ cbcp_option_list,
+ NULL,
+ NULL,
+ NULL
+};
+
+cbcp_state cbcp[NUM_PPP];
+
+/* internal prototypes */
+
+static void cbcp_recvreq __P((cbcp_state *us, char *pckt, int len));
+static void cbcp_resp __P((cbcp_state *us));
+static void cbcp_up __P((cbcp_state *us));
+static void cbcp_recvack __P((cbcp_state *us, char *pckt, int len));
+static void cbcp_send __P((cbcp_state *us, u_char code, u_char *buf, int len));
+
+/* option processing */
+static int
+setcbcp(argv)
+ char **argv;
+{
+ lcp_wantoptions[0].neg_cbcp = 1;
+ cbcp_protent.enabled_flag = 1;
+ cbcp[0].us_number = strdup(*argv);
+ if (cbcp[0].us_number == 0)
+ novm("callback number");
+ cbcp[0].us_type |= (1 << CB_CONF_USER);
+ cbcp[0].us_type |= (1 << CB_CONF_ADMIN);
+ return (1);
+}
+
+/* init state */
+static void
+cbcp_init(iface)
+ int iface;
+{
+ cbcp_state *us;
+
+ us = &cbcp[iface];
+ memset(us, 0, sizeof(cbcp_state));
+ us->us_unit = iface;
+ us->us_type |= (1 << CB_CONF_NO);
+}
+
+/* lower layer is up */
+static void
+cbcp_lowerup(iface)
+ int iface;
+{
+ cbcp_state *us = &cbcp[iface];
+
+ dbglog("cbcp_lowerup");
+ dbglog("want: %d", us->us_type);
+
+ if (us->us_type == CB_CONF_USER)
+ dbglog("phone no: %s", us->us_number);
+}
+
+static void
+cbcp_open(unit)
+ int unit;
+{
+ dbglog("cbcp_open");
+}
+
+/* process an incomming packet */
+static void
+cbcp_input(unit, inpacket, pktlen)
+ int unit;
+ u_char *inpacket;
+ int pktlen;
+{
+ u_char *inp;
+ u_char code, id;
+ u_short len;
+
+ cbcp_state *us = &cbcp[unit];
+
+ inp = inpacket;
+
+ if (pktlen < CBCP_MINLEN) {
+ error("CBCP packet is too small");
+ return;
+ }
+
+ GETCHAR(code, inp);
+ GETCHAR(id, inp);
+ GETSHORT(len, inp);
+
+#if 0
+ if (len > pktlen) {
+ error("CBCP packet: invalid length");
+ return;
+ }
+#endif
+
+ len -= CBCP_MINLEN;
+
+ switch(code) {
+ case CBCP_REQ:
+ us->us_id = id;
+ cbcp_recvreq(us, inp, len);
+ break;
+
+ case CBCP_RESP:
+ dbglog("CBCP_RESP received");
+ break;
+
+ case CBCP_ACK:
+ if (id != us->us_id)
+ dbglog("id doesn't match: expected %d recv %d",
+ us->us_id, id);
+
+ cbcp_recvack(us, inp, len);
+ break;
+
+ default:
+ break;
+ }
+}
+
+/* protocol was rejected by foe */
+void cbcp_protrej(int iface)
+{
+}
+
+char *cbcp_codenames[] = {
+ "Request", "Response", "Ack"
+};
+
+char *cbcp_optionnames[] = {
+ "NoCallback",
+ "UserDefined",
+ "AdminDefined",
+ "List"
+};
+
+/* pretty print a packet */
+static int
+cbcp_printpkt(p, plen, printer, arg)
+ u_char *p;
+ int plen;
+ void (*printer) __P((void *, char *, ...));
+ void *arg;
+{
+ int code, opt, id, len, olen, delay;
+ u_char *pstart;
+
+ if (plen < HEADERLEN)
+ return 0;
+ pstart = p;
+ GETCHAR(code, p);
+ GETCHAR(id, p);
+ GETSHORT(len, p);
+ if (len < HEADERLEN || len > plen)
+ return 0;
+
+ if (code >= 1 && code <= sizeof(cbcp_codenames) / sizeof(char *))
+ printer(arg, " %s", cbcp_codenames[code-1]);
+ else
+ printer(arg, " code=0x%x", code);
+
+ printer(arg, " id=0x%x", id);
+ len -= HEADERLEN;
+
+ switch (code) {
+ case CBCP_REQ:
+ case CBCP_RESP:
+ case CBCP_ACK:
+ while(len >= 2) {
+ GETCHAR(opt, p);
+ GETCHAR(olen, p);
+
+ if (olen < 2 || olen > len) {
+ break;
+ }
+
+ printer(arg, " <");
+ len -= olen;
+
+ if (opt >= 1 && opt <= sizeof(cbcp_optionnames) / sizeof(char *))
+ printer(arg, " %s", cbcp_optionnames[opt-1]);
+ else
+ printer(arg, " option=0x%x", opt);
+
+ if (olen > 2) {
+ GETCHAR(delay, p);
+ printer(arg, " delay = %d", delay);
+ }
+
+ if (olen > 3) {
+ int addrt;
+ char str[256];
+
+ GETCHAR(addrt, p);
+ memcpy(str, p, olen - 4);
+ str[olen - 4] = 0;
+ printer(arg, " number = %s", str);
+ }
+ printer(arg, ">");
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ for (; len > 0; --len) {
+ GETCHAR(code, p);
+ printer(arg, " %.2x", code);
+ }
+
+ return p - pstart;
+}
+
+/* received CBCP request */
+static void
+cbcp_recvreq(us, pckt, pcktlen)
+ cbcp_state *us;
+ char *pckt;
+ int pcktlen;
+{
+ u_char type, opt_len, delay, addr_type;
+ char address[256];
+ int len = pcktlen;
+
+ address[0] = 0;
+
+ while (len) {
+ dbglog("length: %d", len);
+
+ GETCHAR(type, pckt);
+ GETCHAR(opt_len, pckt);
+
+ if (opt_len > 2)
+ GETCHAR(delay, pckt);
+
+ us->us_allowed |= (1 << type);
+
+ switch(type) {
+ case CB_CONF_NO:
+ dbglog("no callback allowed");
+ break;
+
+ case CB_CONF_USER:
+ dbglog("user callback allowed");
+ if (opt_len > 4) {
+ GETCHAR(addr_type, pckt);
+ memcpy(address, pckt, opt_len - 4);
+ address[opt_len - 4] = 0;
+ if (address[0])
+ dbglog("address: %s", address);
+ }
+ break;
+
+ case CB_CONF_ADMIN:
+ dbglog("user admin defined allowed");
+ break;
+
+ case CB_CONF_LIST:
+ break;
+ }
+ len -= opt_len;
+ }
+
+ cbcp_resp(us);
+}
+
+static void
+cbcp_resp(us)
+ cbcp_state *us;
+{
+ u_char cb_type;
+ u_char buf[256];
+ u_char *bufp = buf;
+ int len = 0;
+
+ cb_type = us->us_allowed & us->us_type;
+ dbglog("cbcp_resp cb_type=%d", cb_type);
+
+#if 0
+ if (!cb_type)
+ lcp_down(us->us_unit);
+#endif
+
+ if (cb_type & ( 1 << CB_CONF_USER ) ) {
+ dbglog("cbcp_resp CONF_USER");
+ PUTCHAR(CB_CONF_USER, bufp);
+ len = 3 + 1 + strlen(us->us_number) + 1;
+ PUTCHAR(len , bufp);
+ PUTCHAR(5, bufp); /* delay */
+ PUTCHAR(1, bufp);
+ BCOPY(us->us_number, bufp, strlen(us->us_number) + 1);
+ cbcp_send(us, CBCP_RESP, buf, len);
+ return;
+ }
+
+ if (cb_type & ( 1 << CB_CONF_ADMIN ) ) {
+ dbglog("cbcp_resp CONF_ADMIN");
+ PUTCHAR(CB_CONF_ADMIN, bufp);
+ len = 3;
+ PUTCHAR(len, bufp);
+ PUTCHAR(5, bufp); /* delay */
+ cbcp_send(us, CBCP_RESP, buf, len);
+ return;
+ }
+
+ if (cb_type & ( 1 << CB_CONF_NO ) ) {
+ dbglog("cbcp_resp CONF_NO");
+ PUTCHAR(CB_CONF_NO, bufp);
+ len = 3;
+ PUTCHAR(len , bufp);
+ PUTCHAR(0, bufp);
+ cbcp_send(us, CBCP_RESP, buf, len);
+ start_networks();
+ return;
+ }
+}
+
+static void
+cbcp_send(us, code, buf, len)
+ cbcp_state *us;
+ u_char code;
+ u_char *buf;
+ int len;
+{
+ u_char *outp;
+ int outlen;
+
+ outp = outpacket_buf;
+
+ outlen = 4 + len;
+
+ MAKEHEADER(outp, PPP_CBCP);
+
+ PUTCHAR(code, outp);
+ PUTCHAR(us->us_id, outp);
+ PUTSHORT(outlen, outp);
+
+ if (len)
+ BCOPY(buf, outp, len);
+
+ output(us->us_unit, outpacket_buf, outlen + PPP_HDRLEN);
+}
+
+static void
+cbcp_recvack(us, pckt, len)
+ cbcp_state *us;
+ char *pckt;
+ int len;
+{
+ u_char type, delay, addr_type;
+ int opt_len;
+ char address[256];
+
+ if (len) {
+ GETCHAR(type, pckt);
+ GETCHAR(opt_len, pckt);
+
+ if (opt_len > 2)
+ GETCHAR(delay, pckt);
+
+ if (opt_len > 4) {
+ GETCHAR(addr_type, pckt);
+ memcpy(address, pckt, opt_len - 4);
+ address[opt_len - 4] = 0;
+ if (address[0])
+ dbglog("peer will call: %s", address);
+ }
+ if (type == CB_CONF_NO)
+ return;
+ }
+
+ cbcp_up(us);
+}
+
+/* ok peer will do callback */
+static void
+cbcp_up(us)
+ cbcp_state *us;
+{
+ persist = 0;
+ lcp_close(0, "Call me back, please");
+ status = EXIT_CALLBACK;
+}
diff --git a/cpukit/pppd/cbcp.h b/cpukit/pppd/cbcp.h
new file mode 100644
index 0000000000..c2ab3f6899
--- /dev/null
+++ b/cpukit/pppd/cbcp.h
@@ -0,0 +1,26 @@
+#ifndef CBCP_H
+#define CBCP_H
+
+typedef struct cbcp_state {
+ int us_unit; /* Interface unit number */
+ u_char us_id; /* Current id */
+ u_char us_allowed;
+ int us_type;
+ char *us_number; /* Telefone Number */
+} cbcp_state;
+
+extern cbcp_state cbcp[];
+
+extern struct protent cbcp_protent;
+
+#define CBCP_MINLEN 4
+
+#define CBCP_REQ 1
+#define CBCP_RESP 2
+#define CBCP_ACK 3
+
+#define CB_CONF_NO 1
+#define CB_CONF_USER 2
+#define CB_CONF_ADMIN 3
+#define CB_CONF_LIST 4
+#endif
diff --git a/cpukit/pppd/ccp.c b/cpukit/pppd/ccp.c
new file mode 100644
index 0000000000..615950b901
--- /dev/null
+++ b/cpukit/pppd/ccp.c
@@ -0,0 +1,1226 @@
+/*
+ * ccp.c - PPP Compression Control Protocol.
+ *
+ * Copyright (c) 1994 The Australian National University.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, provided that the above copyright
+ * notice appears in all copies. This software is provided without any
+ * warranty, express or implied. The Australian National University
+ * makes no representations about the suitability of this software for
+ * any purpose.
+ *
+ * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+ * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
+ * OR MODIFICATIONS.
+ */
+
+#define RCSID "$Id$"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "pppd.h"
+#include "fsm.h"
+#include "ccp.h"
+#include <net/ppp-comp.h>
+
+static const char rcsid[] = RCSID;
+
+/*
+ * Command-line options.
+ */
+static int setbsdcomp __P((char **));
+static int setdeflate __P((char **));
+
+static option_t ccp_option_list[] = {
+ { "noccp", o_bool, &ccp_protent.enabled_flag,
+ "Disable CCP negotiation" },
+ { "-ccp", o_bool, &ccp_protent.enabled_flag,
+ "Disable CCP negotiation" },
+ { "bsdcomp", o_special, setbsdcomp,
+ "Request BSD-Compress packet compression" },
+ { "nobsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress,
+ "don't allow BSD-Compress", OPT_A2COPY,
+ &ccp_allowoptions[0].bsd_compress },
+ { "-bsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress,
+ "don't allow BSD-Compress", OPT_A2COPY,
+ &ccp_allowoptions[0].bsd_compress },
+ { "deflate", 1, setdeflate,
+ "request Deflate compression" },
+ { "nodeflate", o_bool, &ccp_wantoptions[0].deflate,
+ "don't allow Deflate compression", OPT_A2COPY,
+ &ccp_allowoptions[0].deflate },
+ { "-deflate", o_bool, &ccp_wantoptions[0].deflate,
+ "don't allow Deflate compression", OPT_A2COPY,
+ &ccp_allowoptions[0].deflate },
+ { "nodeflatedraft", o_bool, &ccp_wantoptions[0].deflate_draft,
+ "don't use draft deflate #", OPT_A2COPY,
+ &ccp_allowoptions[0].deflate_draft },
+ { "predictor1", o_bool, &ccp_wantoptions[0].predictor_1,
+ "request Predictor-1", 1, &ccp_allowoptions[0].predictor_1 },
+ { "nopredictor1", o_bool, &ccp_wantoptions[0].predictor_1,
+ "don't allow Predictor-1", OPT_A2COPY,
+ &ccp_allowoptions[0].predictor_1 },
+ { "-predictor1", o_bool, &ccp_wantoptions[0].predictor_1,
+ "don't allow Predictor-1", OPT_A2COPY,
+ &ccp_allowoptions[0].predictor_1 },
+
+ { NULL }
+};
+
+/*
+ * Protocol entry points from main code.
+ */
+static void ccp_init __P((int unit));
+static void ccp_open __P((int unit));
+static void ccp_close __P((int unit, char *));
+static void ccp_lowerup __P((int unit));
+static void ccp_lowerdown __P((int));
+static void ccp_input __P((int unit, u_char *pkt, int len));
+static void ccp_protrej __P((int unit));
+static int ccp_printpkt __P((u_char *pkt, int len,
+ void (*printer) __P((void *, char *, ...)),
+ void *arg));
+static void ccp_datainput __P((int unit, u_char *pkt, int len));
+
+struct protent ccp_protent = {
+ PPP_CCP,
+ ccp_init,
+ ccp_input,
+ ccp_protrej,
+ ccp_lowerup,
+ ccp_lowerdown,
+ ccp_open,
+ ccp_close,
+ ccp_printpkt,
+ ccp_datainput,
+ 1,
+ "CCP",
+ "Compressed",
+ ccp_option_list,
+ NULL,
+ NULL,
+ NULL
+};
+
+fsm ccp_fsm[NUM_PPP];
+ccp_options ccp_wantoptions[NUM_PPP]; /* what to request the peer to use */
+ccp_options ccp_gotoptions[NUM_PPP]; /* what the peer agreed to do */
+ccp_options ccp_allowoptions[NUM_PPP]; /* what we'll agree to do */
+ccp_options ccp_hisoptions[NUM_PPP]; /* what we agreed to do */
+
+/*
+ * Callbacks for fsm code.
+ */
+static void ccp_resetci __P((fsm *));
+static int ccp_cilen __P((fsm *));
+static void ccp_addci __P((fsm *, u_char *, int *));
+static int ccp_ackci __P((fsm *, u_char *, int));
+static int ccp_nakci __P((fsm *, u_char *, int));
+static int ccp_rejci __P((fsm *, u_char *, int));
+static int ccp_reqci __P((fsm *, u_char *, int *, int));
+static void ccp_up __P((fsm *));
+static void ccp_down __P((fsm *));
+static int ccp_extcode __P((fsm *, int, int, u_char *, int));
+static void ccp_rack_timeout __P((void *));
+static char *method_name __P((ccp_options *, ccp_options *));
+
+static fsm_callbacks ccp_callbacks = {
+ ccp_resetci,
+ ccp_cilen,
+ ccp_addci,
+ ccp_ackci,
+ ccp_nakci,
+ ccp_rejci,
+ ccp_reqci,
+ ccp_up,
+ ccp_down,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ ccp_extcode,
+ "CCP"
+};
+
+/*
+ * Do we want / did we get any compression?
+ */
+#define ANY_COMPRESS(opt) ((opt).deflate || (opt).bsd_compress \
+ || (opt).predictor_1 || (opt).predictor_2)
+
+/*
+ * Local state (mainly for handling reset-reqs and reset-acks).
+ */
+static int ccp_localstate[NUM_PPP];
+#define RACK_PENDING 1 /* waiting for reset-ack */
+#define RREQ_REPEAT 2 /* send another reset-req if no reset-ack */
+
+#define RACKTIMEOUT 1 /* second */
+
+static int all_rejected[NUM_PPP]; /* we rejected all peer's options */
+
+/*
+ * Option parsing.
+ */
+static int
+setbsdcomp(argv)
+ char **argv;
+{
+ int rbits, abits;
+ char *str, *endp;
+
+ str = *argv;
+ abits = rbits = strtol(str, &endp, 0);
+ if (endp != str && *endp == ',') {
+ str = endp + 1;
+ abits = strtol(str, &endp, 0);
+ }
+ if (*endp != 0 || endp == str) {
+ option_error("invalid parameter '%s' for bsdcomp option", *argv);
+ return 0;
+ }
+ if ((rbits != 0 && (rbits < BSD_MIN_BITS || rbits > BSD_MAX_BITS))
+ || (abits != 0 && (abits < BSD_MIN_BITS || abits > BSD_MAX_BITS))) {
+ option_error("bsdcomp option values must be 0 or %d .. %d",
+ BSD_MIN_BITS, BSD_MAX_BITS);
+ return 0;
+ }
+ if (rbits > 0) {
+ ccp_wantoptions[0].bsd_compress = 1;
+ ccp_wantoptions[0].bsd_bits = rbits;
+ } else
+ ccp_wantoptions[0].bsd_compress = 0;
+ if (abits > 0) {
+ ccp_allowoptions[0].bsd_compress = 1;
+ ccp_allowoptions[0].bsd_bits = abits;
+ } else
+ ccp_allowoptions[0].bsd_compress = 0;
+ return 1;
+}
+
+static int
+setdeflate(argv)
+ char **argv;
+{
+ int rbits, abits;
+ char *str, *endp;
+
+ str = *argv;
+ abits = rbits = strtol(str, &endp, 0);
+ if (endp != str && *endp == ',') {
+ str = endp + 1;
+ abits = strtol(str, &endp, 0);
+ }
+ if (*endp != 0 || endp == str) {
+ option_error("invalid parameter '%s' for deflate option", *argv);
+ return 0;
+ }
+ if ((rbits != 0 && (rbits < DEFLATE_MIN_SIZE || rbits > DEFLATE_MAX_SIZE))
+ || (abits != 0 && (abits < DEFLATE_MIN_SIZE
+ || abits > DEFLATE_MAX_SIZE))) {
+ option_error("deflate option values must be 0 or %d .. %d",
+ DEFLATE_MIN_SIZE, DEFLATE_MAX_SIZE);
+ return 0;
+ }
+ if (rbits > 0) {
+ ccp_wantoptions[0].deflate = 1;
+ ccp_wantoptions[0].deflate_size = rbits;
+ } else
+ ccp_wantoptions[0].deflate = 0;
+ if (abits > 0) {
+ ccp_allowoptions[0].deflate = 1;
+ ccp_allowoptions[0].deflate_size = abits;
+ } else
+ ccp_allowoptions[0].deflate = 0;
+ return 1;
+}
+
+
+/*
+ * ccp_init - initialize CCP.
+ */
+static void
+ccp_init(unit)
+ int unit;
+{
+ fsm *f = &ccp_fsm[unit];
+
+ f->unit = unit;
+ f->protocol = PPP_CCP;
+ f->callbacks = &ccp_callbacks;
+ fsm_init(f);
+
+ memset(&ccp_wantoptions[unit], 0, sizeof(ccp_options));
+ memset(&ccp_gotoptions[unit], 0, sizeof(ccp_options));
+ memset(&ccp_allowoptions[unit], 0, sizeof(ccp_options));
+ memset(&ccp_hisoptions[unit], 0, sizeof(ccp_options));
+
+ ccp_wantoptions[0].deflate = 1;
+ ccp_wantoptions[0].deflate_size = DEFLATE_MAX_SIZE;
+ ccp_wantoptions[0].deflate_correct = 1;
+ ccp_wantoptions[0].deflate_draft = 1;
+ ccp_allowoptions[0].deflate = 1;
+ ccp_allowoptions[0].deflate_size = DEFLATE_MAX_SIZE;
+ ccp_allowoptions[0].deflate_correct = 1;
+ ccp_allowoptions[0].deflate_draft = 1;
+
+ ccp_wantoptions[0].bsd_compress = 1;
+ ccp_wantoptions[0].bsd_bits = BSD_MAX_BITS;
+ ccp_allowoptions[0].bsd_compress = 1;
+ ccp_allowoptions[0].bsd_bits = BSD_MAX_BITS;
+
+ ccp_allowoptions[0].predictor_1 = 1;
+}
+
+/*
+ * ccp_open - CCP is allowed to come up.
+ */
+static void
+ccp_open(unit)
+ int unit;
+{
+ fsm *f = &ccp_fsm[unit];
+
+ if (f->state != OPENED)
+ ccp_flags_set(unit, 1, 0);
+
+ /*
+ * Find out which compressors the kernel supports before
+ * deciding whether to open in silent mode.
+ */
+ ccp_resetci(f);
+ if (!ANY_COMPRESS(ccp_gotoptions[unit]))
+ f->flags |= OPT_SILENT;
+
+ fsm_open(f);
+}
+
+/*
+ * ccp_close - Terminate CCP.
+ */
+static void
+ccp_close(unit, reason)
+ int unit;
+ char *reason;
+{
+ ccp_flags_set(unit, 0, 0);
+ fsm_close(&ccp_fsm[unit], reason);
+}
+
+/*
+ * ccp_lowerup - we may now transmit CCP packets.
+ */
+static void
+ccp_lowerup(unit)
+ int unit;
+{
+ fsm_lowerup(&ccp_fsm[unit]);
+}
+
+/*
+ * ccp_lowerdown - we may not transmit CCP packets.
+ */
+static void
+ccp_lowerdown(unit)
+ int unit;
+{
+ fsm_lowerdown(&ccp_fsm[unit]);
+}
+
+/*
+ * ccp_input - process a received CCP packet.
+ */
+static void
+ccp_input(unit, p, len)
+ int unit;
+ u_char *p;
+ int len;
+{
+ fsm *f = &ccp_fsm[unit];
+ int oldstate;
+
+ /*
+ * Check for a terminate-request so we can print a message.
+ */
+ oldstate = f->state;
+ fsm_input(f, p, len);
+ if (oldstate == OPENED && p[0] == TERMREQ && f->state != OPENED)
+ notice("Compression disabled by peer.");
+
+ /*
+ * If we get a terminate-ack and we're not asking for compression,
+ * close CCP.
+ */
+ if (oldstate == REQSENT && p[0] == TERMACK
+ && !ANY_COMPRESS(ccp_gotoptions[unit]))
+ ccp_close(unit, "No compression negotiated");
+}
+
+/*
+ * Handle a CCP-specific code.
+ */
+static int
+ccp_extcode(f, code, id, p, len)
+ fsm *f;
+ int code, id;
+ u_char *p;
+ int len;
+{
+ switch (code) {
+ case CCP_RESETREQ:
+ if (f->state != OPENED)
+ break;
+ /* send a reset-ack, which the transmitter will see and
+ reset its compression state. */
+ fsm_sdata(f, CCP_RESETACK, id, NULL, 0);
+ break;
+
+ case CCP_RESETACK:
+ if (ccp_localstate[f->unit] & RACK_PENDING && id == f->reqid) {
+ ccp_localstate[f->unit] &= ~(RACK_PENDING | RREQ_REPEAT);
+ UNTIMEOUT(ccp_rack_timeout, f);
+ }
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * ccp_protrej - peer doesn't talk CCP.
+ */
+static void
+ccp_protrej(unit)
+ int unit;
+{
+ ccp_flags_set(unit, 0, 0);
+ fsm_lowerdown(&ccp_fsm[unit]);
+}
+
+/*
+ * ccp_resetci - initialize at start of negotiation.
+ */
+static void
+ccp_resetci(f)
+ fsm *f;
+{
+ ccp_options *go = &ccp_gotoptions[f->unit];
+ u_char opt_buf[16];
+
+ *go = ccp_wantoptions[f->unit];
+ all_rejected[f->unit] = 0;
+
+ /*
+ * Check whether the kernel knows about the various
+ * compression methods we might request.
+ */
+ if (go->bsd_compress) {
+ opt_buf[0] = CI_BSD_COMPRESS;
+ opt_buf[1] = CILEN_BSD_COMPRESS;
+ opt_buf[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, BSD_MIN_BITS);
+ if (ccp_test(f->unit, opt_buf, CILEN_BSD_COMPRESS, 0) <= 0)
+ go->bsd_compress = 0;
+ }
+ if (go->deflate) {
+ if (go->deflate_correct) {
+ opt_buf[0] = CI_DEFLATE;
+ opt_buf[1] = CILEN_DEFLATE;
+ opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_SIZE);
+ opt_buf[3] = DEFLATE_CHK_SEQUENCE;
+ if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0)
+ go->deflate_correct = 0;
+ }
+ if (go->deflate_draft) {
+ opt_buf[0] = CI_DEFLATE_DRAFT;
+ opt_buf[1] = CILEN_DEFLATE;
+ opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_SIZE);
+ opt_buf[3] = DEFLATE_CHK_SEQUENCE;
+ if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0)
+ go->deflate_draft = 0;
+ }
+ if (!go->deflate_correct && !go->deflate_draft)
+ go->deflate = 0;
+ }
+ if (go->predictor_1) {
+ opt_buf[0] = CI_PREDICTOR_1;
+ opt_buf[1] = CILEN_PREDICTOR_1;
+ if (ccp_test(f->unit, opt_buf, CILEN_PREDICTOR_1, 0) <= 0)
+ go->predictor_1 = 0;
+ }
+ if (go->predictor_2) {
+ opt_buf[0] = CI_PREDICTOR_2;
+ opt_buf[1] = CILEN_PREDICTOR_2;
+ if (ccp_test(f->unit, opt_buf, CILEN_PREDICTOR_2, 0) <= 0)
+ go->predictor_2 = 0;
+ }
+}
+
+/*
+ * ccp_cilen - Return total length of our configuration info.
+ */
+static int
+ccp_cilen(f)
+ fsm *f;
+{
+ ccp_options *go = &ccp_gotoptions[f->unit];
+
+ return (go->bsd_compress? CILEN_BSD_COMPRESS: 0)
+ + (go->deflate? CILEN_DEFLATE: 0)
+ + (go->predictor_1? CILEN_PREDICTOR_1: 0)
+ + (go->predictor_2? CILEN_PREDICTOR_2: 0);
+}
+
+/*
+ * ccp_addci - put our requests in a packet.
+ */
+static void
+ccp_addci(f, p, lenp)
+ fsm *f;
+ u_char *p;
+ int *lenp;
+{
+ int res;
+ ccp_options *go = &ccp_gotoptions[f->unit];
+ u_char *p0 = p;
+
+ /*
+ * Add the compression types that we can receive, in decreasing
+ * preference order. Get the kernel to allocate the first one
+ * in case it gets Acked.
+ */
+ if (go->deflate) {
+ p[0] = go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT;
+ p[1] = CILEN_DEFLATE;
+ p[2] = DEFLATE_MAKE_OPT(go->deflate_size);
+ p[3] = DEFLATE_CHK_SEQUENCE;
+ for (;;) {
+ res = ccp_test(f->unit, p, CILEN_DEFLATE, 0);
+ if (res > 0) {
+ p += CILEN_DEFLATE;
+ break;
+ }
+ if (res < 0 || go->deflate_size <= DEFLATE_MIN_SIZE) {
+ go->deflate = 0;
+ break;
+ }
+ --go->deflate_size;
+ p[2] = DEFLATE_MAKE_OPT(go->deflate_size);
+ }
+ if (p != p0 && go->deflate_correct && go->deflate_draft) {
+ p[0] = CI_DEFLATE_DRAFT;
+ p[1] = CILEN_DEFLATE;
+ p[2] = p[2 - CILEN_DEFLATE];
+ p[3] = DEFLATE_CHK_SEQUENCE;
+ p += CILEN_DEFLATE;
+ }
+ }
+ if (go->bsd_compress) {
+ p[0] = CI_BSD_COMPRESS;
+ p[1] = CILEN_BSD_COMPRESS;
+ p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits);
+ if (p != p0) {
+ p += CILEN_BSD_COMPRESS; /* not the first option */
+ } else {
+ for (;;) {
+ res = ccp_test(f->unit, p, CILEN_BSD_COMPRESS, 0);
+ if (res > 0) {
+ p += CILEN_BSD_COMPRESS;
+ break;
+ }
+ if (res < 0 || go->bsd_bits <= BSD_MIN_BITS) {
+ go->bsd_compress = 0;
+ break;
+ }
+ --go->bsd_bits;
+ p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits);
+ }
+ }
+ }
+ /* XXX Should Predictor 2 be preferable to Predictor 1? */
+ if (go->predictor_1) {
+ p[0] = CI_PREDICTOR_1;
+ p[1] = CILEN_PREDICTOR_1;
+ if (p == p0 && ccp_test(f->unit, p, CILEN_PREDICTOR_1, 0) <= 0) {
+ go->predictor_1 = 0;
+ } else {
+ p += CILEN_PREDICTOR_1;
+ }
+ }
+ if (go->predictor_2) {
+ p[0] = CI_PREDICTOR_2;
+ p[1] = CILEN_PREDICTOR_2;
+ if (p == p0 && ccp_test(f->unit, p, CILEN_PREDICTOR_2, 0) <= 0) {
+ go->predictor_2 = 0;
+ } else {
+ p += CILEN_PREDICTOR_2;
+ }
+ }
+
+ go->method = (p > p0)? p0[0]: -1;
+
+ *lenp = p - p0;
+}
+
+/*
+ * ccp_ackci - process a received configure-ack, and return
+ * 1 iff the packet was OK.
+ */
+static int
+ccp_ackci(f, p, len)
+ fsm *f;
+ u_char *p;
+ int len;
+{
+ ccp_options *go = &ccp_gotoptions[f->unit];
+ u_char *p0 = p;
+
+ if (go->deflate) {
+ if (len < CILEN_DEFLATE
+ || p[0] != (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
+ || p[1] != CILEN_DEFLATE
+ || p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
+ || p[3] != DEFLATE_CHK_SEQUENCE)
+ return 0;
+ p += CILEN_DEFLATE;
+ len -= CILEN_DEFLATE;
+ /* XXX Cope with first/fast ack */
+ if (len == 0)
+ return 1;
+ if (go->deflate_correct && go->deflate_draft) {
+ if (len < CILEN_DEFLATE
+ || p[0] != CI_DEFLATE_DRAFT
+ || p[1] != CILEN_DEFLATE
+ || p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
+ || p[3] != DEFLATE_CHK_SEQUENCE)
+ return 0;
+ p += CILEN_DEFLATE;
+ len -= CILEN_DEFLATE;
+ }
+ }
+ if (go->bsd_compress) {
+ if (len < CILEN_BSD_COMPRESS
+ || p[0] != CI_BSD_COMPRESS || p[1] != CILEN_BSD_COMPRESS
+ || p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits))
+ return 0;
+ p += CILEN_BSD_COMPRESS;
+ len -= CILEN_BSD_COMPRESS;
+ /* XXX Cope with first/fast ack */
+ if (p == p0 && len == 0)
+ return 1;
+ }
+ if (go->predictor_1) {
+ if (len < CILEN_PREDICTOR_1
+ || p[0] != CI_PREDICTOR_1 || p[1] != CILEN_PREDICTOR_1)
+ return 0;
+ p += CILEN_PREDICTOR_1;
+ len -= CILEN_PREDICTOR_1;
+ /* XXX Cope with first/fast ack */
+ if (p == p0 && len == 0)
+ return 1;
+ }
+ if (go->predictor_2) {
+ if (len < CILEN_PREDICTOR_2
+ || p[0] != CI_PREDICTOR_2 || p[1] != CILEN_PREDICTOR_2)
+ return 0;
+ p += CILEN_PREDICTOR_2;
+ len -= CILEN_PREDICTOR_2;
+ /* XXX Cope with first/fast ack */
+ if (p == p0 && len == 0)
+ return 1;
+ }
+
+ if (len != 0)
+ return 0;
+ return 1;
+}
+
+/*
+ * ccp_nakci - process received configure-nak.
+ * Returns 1 iff the nak was OK.
+ */
+static int
+ccp_nakci(f, p, len)
+ fsm *f;
+ u_char *p;
+ int len;
+{
+ ccp_options *go = &ccp_gotoptions[f->unit];
+ ccp_options no; /* options we've seen already */
+ ccp_options try; /* options to ask for next time */
+
+ memset(&no, 0, sizeof(no));
+ try = *go;
+
+ if (go->deflate && len >= CILEN_DEFLATE
+ && p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
+ && p[1] == CILEN_DEFLATE) {
+ no.deflate = 1;
+ /*
+ * Peer wants us to use a different code size or something.
+ * Stop asking for Deflate if we don't understand his suggestion.
+ */
+ if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL
+ || DEFLATE_SIZE(p[2]) < DEFLATE_MIN_SIZE
+ || p[3] != DEFLATE_CHK_SEQUENCE)
+ try.deflate = 0;
+ else if (DEFLATE_SIZE(p[2]) < go->deflate_size)
+ try.deflate_size = DEFLATE_SIZE(p[2]);
+ p += CILEN_DEFLATE;
+ len -= CILEN_DEFLATE;
+ if (go->deflate_correct && go->deflate_draft
+ && len >= CILEN_DEFLATE && p[0] == CI_DEFLATE_DRAFT
+ && p[1] == CILEN_DEFLATE) {
+ p += CILEN_DEFLATE;
+ len -= CILEN_DEFLATE;
+ }
+ }
+
+ if (go->bsd_compress && len >= CILEN_BSD_COMPRESS
+ && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) {
+ no.bsd_compress = 1;
+ /*
+ * Peer wants us to use a different number of bits
+ * or a different version.
+ */
+ if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION)
+ try.bsd_compress = 0;
+ else if (BSD_NBITS(p[2]) < go->bsd_bits)
+ try.bsd_bits = BSD_NBITS(p[2]);
+ p += CILEN_BSD_COMPRESS;
+ len -= CILEN_BSD_COMPRESS;
+ }
+
+ /*
+ * Predictor-1 and 2 have no options, so they can't be Naked.
+ *
+ * There may be remaining options but we ignore them.
+ */
+
+ if (f->state != OPENED)
+ *go = try;
+ return 1;
+}
+
+/*
+ * ccp_rejci - reject some of our suggested compression methods.
+ */
+static int
+ccp_rejci(f, p, len)
+ fsm *f;
+ u_char *p;
+ int len;
+{
+ ccp_options *go = &ccp_gotoptions[f->unit];
+ ccp_options try; /* options to request next time */
+
+ try = *go;
+
+ /*
+ * Cope with empty configure-rejects by ceasing to send
+ * configure-requests.
+ */
+ if (len == 0 && all_rejected[f->unit])
+ return -1;
+
+ if (go->deflate && len >= CILEN_DEFLATE
+ && p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
+ && p[1] == CILEN_DEFLATE) {
+ if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
+ || p[3] != DEFLATE_CHK_SEQUENCE)
+ return 0; /* Rej is bad */
+ if (go->deflate_correct)
+ try.deflate_correct = 0;
+ else
+ try.deflate_draft = 0;
+ p += CILEN_DEFLATE;
+ len -= CILEN_DEFLATE;
+ if (go->deflate_correct && go->deflate_draft
+ && len >= CILEN_DEFLATE && p[0] == CI_DEFLATE_DRAFT
+ && p[1] == CILEN_DEFLATE) {
+ if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
+ || p[3] != DEFLATE_CHK_SEQUENCE)
+ return 0; /* Rej is bad */
+ try.deflate_draft = 0;
+ p += CILEN_DEFLATE;
+ len -= CILEN_DEFLATE;
+ }
+ if (!try.deflate_correct && !try.deflate_draft)
+ try.deflate = 0;
+ }
+ if (go->bsd_compress && len >= CILEN_BSD_COMPRESS
+ && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) {
+ if (p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits))
+ return 0;
+ try.bsd_compress = 0;
+ p += CILEN_BSD_COMPRESS;
+ len -= CILEN_BSD_COMPRESS;
+ }
+ if (go->predictor_1 && len >= CILEN_PREDICTOR_1
+ && p[0] == CI_PREDICTOR_1 && p[1] == CILEN_PREDICTOR_1) {
+ try.predictor_1 = 0;
+ p += CILEN_PREDICTOR_1;
+ len -= CILEN_PREDICTOR_1;
+ }
+ if (go->predictor_2 && len >= CILEN_PREDICTOR_2
+ && p[0] == CI_PREDICTOR_2 && p[1] == CILEN_PREDICTOR_2) {
+ try.predictor_2 = 0;
+ p += CILEN_PREDICTOR_2;
+ len -= CILEN_PREDICTOR_2;
+ }
+
+ if (len != 0)
+ return 0;
+
+ if (f->state != OPENED)
+ *go = try;
+
+ return 1;
+}
+
+/*
+ * ccp_reqci - processed a received configure-request.
+ * Returns CONFACK, CONFNAK or CONFREJ and the packet modified
+ * appropriately.
+ */
+static int
+ccp_reqci(f, p, lenp, dont_nak)
+ fsm *f;
+ u_char *p;
+ int *lenp;
+ int dont_nak;
+{
+ int ret, newret, res;
+ u_char *p0, *retp;
+ int len, clen, type, nb;
+ ccp_options *ho = &ccp_hisoptions[f->unit];
+ ccp_options *ao = &ccp_allowoptions[f->unit];
+
+ ret = CONFACK;
+ retp = p0 = p;
+ len = *lenp;
+
+ memset(ho, 0, sizeof(ccp_options));
+ ho->method = (len > 0)? p[0]: -1;
+
+ while (len > 0) {
+ newret = CONFACK;
+ if (len < 2 || p[1] < 2 || p[1] > len) {
+ /* length is bad */
+ clen = len;
+ newret = CONFREJ;
+
+ } else {
+ type = p[0];
+ clen = p[1];
+
+ switch (type) {
+ case CI_DEFLATE:
+ case CI_DEFLATE_DRAFT:
+ if (!ao->deflate || clen != CILEN_DEFLATE
+ || (!ao->deflate_correct && type == CI_DEFLATE)
+ || (!ao->deflate_draft && type == CI_DEFLATE_DRAFT)) {
+ newret = CONFREJ;
+ break;
+ }
+
+ ho->deflate = 1;
+ ho->deflate_size = nb = DEFLATE_SIZE(p[2]);
+ if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL
+ || p[3] != DEFLATE_CHK_SEQUENCE
+ || nb > ao->deflate_size || nb < DEFLATE_MIN_SIZE) {
+ newret = CONFNAK;
+ if (!dont_nak) {
+ p[2] = DEFLATE_MAKE_OPT(ao->deflate_size);
+ p[3] = DEFLATE_CHK_SEQUENCE;
+ /* fall through to test this #bits below */
+ } else
+ break;
+ }
+
+ /*
+ * Check whether we can do Deflate with the window
+ * size they want. If the window is too big, reduce
+ * it until the kernel can cope and nak with that.
+ * We only check this for the first option.
+ */
+ if (p == p0) {
+ for (;;) {
+ res = ccp_test(f->unit, p, CILEN_DEFLATE, 1);
+ if (res > 0)
+ break; /* it's OK now */
+ if (res < 0 || nb == DEFLATE_MIN_SIZE || dont_nak) {
+ newret = CONFREJ;
+ p[2] = DEFLATE_MAKE_OPT(ho->deflate_size);
+ break;
+ }
+ newret = CONFNAK;
+ --nb;
+ p[2] = DEFLATE_MAKE_OPT(nb);
+ }
+ }
+ break;
+
+ case CI_BSD_COMPRESS:
+ if (!ao->bsd_compress || clen != CILEN_BSD_COMPRESS) {
+ newret = CONFREJ;
+ break;
+ }
+
+ ho->bsd_compress = 1;
+ ho->bsd_bits = nb = BSD_NBITS(p[2]);
+ if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION
+ || nb > ao->bsd_bits || nb < BSD_MIN_BITS) {
+ newret = CONFNAK;
+ if (!dont_nak) {
+ p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, ao->bsd_bits);
+ /* fall through to test this #bits below */
+ } else
+ break;
+ }
+
+ /*
+ * Check whether we can do BSD-Compress with the code
+ * size they want. If the code size is too big, reduce
+ * it until the kernel can cope and nak with that.
+ * We only check this for the first option.
+ */
+ if (p == p0) {
+ for (;;) {
+ res = ccp_test(f->unit, p, CILEN_BSD_COMPRESS, 1);
+ if (res > 0)
+ break;
+ if (res < 0 || nb == BSD_MIN_BITS || dont_nak) {
+ newret = CONFREJ;
+ p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION,
+ ho->bsd_bits);
+ break;
+ }
+ newret = CONFNAK;
+ --nb;
+ p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, nb);
+ }
+ }
+ break;
+
+ case CI_PREDICTOR_1:
+ if (!ao->predictor_1 || clen != CILEN_PREDICTOR_1) {
+ newret = CONFREJ;
+ break;
+ }
+
+ ho->predictor_1 = 1;
+ if (p == p0
+ && ccp_test(f->unit, p, CILEN_PREDICTOR_1, 1) <= 0) {
+ newret = CONFREJ;
+ }
+ break;
+
+ case CI_PREDICTOR_2:
+ if (!ao->predictor_2 || clen != CILEN_PREDICTOR_2) {
+ newret = CONFREJ;
+ break;
+ }
+
+ ho->predictor_2 = 1;
+ if (p == p0
+ && ccp_test(f->unit, p, CILEN_PREDICTOR_2, 1) <= 0) {
+ newret = CONFREJ;
+ }
+ break;
+
+ default:
+ newret = CONFREJ;
+ }
+ }
+
+ if (newret == CONFNAK && dont_nak)
+ newret = CONFREJ;
+ if (!(newret == CONFACK || (newret == CONFNAK && ret == CONFREJ))) {
+ /* we're returning this option */
+ if (newret == CONFREJ && ret == CONFNAK)
+ retp = p0;
+ ret = newret;
+ if (p != retp)
+ BCOPY(p, retp, clen);
+ retp += clen;
+ }
+
+ p += clen;
+ len -= clen;
+ }
+
+ if (ret != CONFACK) {
+ if (ret == CONFREJ && *lenp == retp - p0)
+ all_rejected[f->unit] = 1;
+ else
+ *lenp = retp - p0;
+ }
+ return ret;
+}
+
+/*
+ * Make a string name for a compression method (or 2).
+ */
+static char *
+method_name(opt, opt2)
+ ccp_options *opt, *opt2;
+{
+ static char result[64];
+
+ if (!ANY_COMPRESS(*opt))
+ return "(none)";
+ switch (opt->method) {
+ case CI_DEFLATE:
+ case CI_DEFLATE_DRAFT:
+ if (opt2 != NULL && opt2->deflate_size != opt->deflate_size)
+ slprintf(result, sizeof(result), "Deflate%s (%d/%d)",
+ (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""),
+ opt->deflate_size, opt2->deflate_size);
+ else
+ slprintf(result, sizeof(result), "Deflate%s (%d)",
+ (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""),
+ opt->deflate_size);
+ break;
+ case CI_BSD_COMPRESS:
+ if (opt2 != NULL && opt2->bsd_bits != opt->bsd_bits)
+ slprintf(result, sizeof(result), "BSD-Compress (%d/%d)",
+ opt->bsd_bits, opt2->bsd_bits);
+ else
+ slprintf(result, sizeof(result), "BSD-Compress (%d)",
+ opt->bsd_bits);
+ break;
+ case CI_PREDICTOR_1:
+ return "Predictor 1";
+ case CI_PREDICTOR_2:
+ return "Predictor 2";
+ default:
+ slprintf(result, sizeof(result), "Method %d", opt->method);
+ }
+ return result;
+}
+
+/*
+ * CCP has come up - inform the kernel driver and log a message.
+ */
+static void
+ccp_up(f)
+ fsm *f;
+{
+ ccp_options *go = &ccp_gotoptions[f->unit];
+ ccp_options *ho = &ccp_hisoptions[f->unit];
+ char method1[64];
+
+ ccp_flags_set(f->unit, 1, 1);
+ if (ANY_COMPRESS(*go)) {
+ if (ANY_COMPRESS(*ho)) {
+ if (go->method == ho->method) {
+ notice("%s compression enabled", method_name(go, ho));
+ } else {
+ strlcpy(method1, method_name(go, NULL), sizeof(method1));
+ notice("%s / %s compression enabled",
+ method1, method_name(ho, NULL));
+ }
+ } else
+ notice("%s receive compression enabled", method_name(go, NULL));
+ } else if (ANY_COMPRESS(*ho))
+ notice("%s transmit compression enabled", method_name(ho, NULL));
+}
+
+/*
+ * CCP has gone down - inform the kernel driver.
+ */
+static void
+ccp_down(f)
+ fsm *f;
+{
+ if (ccp_localstate[f->unit] & RACK_PENDING)
+ UNTIMEOUT(ccp_rack_timeout, f);
+ ccp_localstate[f->unit] = 0;
+ ccp_flags_set(f->unit, 1, 0);
+}
+
+/*
+ * Print the contents of a CCP packet.
+ */
+static char *ccp_codenames[] = {
+ "ConfReq", "ConfAck", "ConfNak", "ConfRej",
+ "TermReq", "TermAck", "CodeRej",
+ NULL, NULL, NULL, NULL, NULL, NULL,
+ "ResetReq", "ResetAck",
+};
+
+static int
+ccp_printpkt(p, plen, printer, arg)
+ u_char *p;
+ int plen;
+ void (*printer) __P((void *, char *, ...));
+ void *arg;
+{
+ u_char *p0, *optend;
+ int code, id, len;
+ int optlen;
+
+ p0 = p;
+ if (plen < HEADERLEN)
+ return 0;
+ code = p[0];
+ id = p[1];
+ len = (p[2] << 8) + p[3];
+ if (len < HEADERLEN || len > plen)
+ return 0;
+
+ if (code >= 1 && code <= sizeof(ccp_codenames) / sizeof(char *)
+ && ccp_codenames[code-1] != NULL)
+ printer(arg, " %s", ccp_codenames[code-1]);
+ else
+ printer(arg, " code=0x%x", code);
+ printer(arg, " id=0x%x", id);
+ len -= HEADERLEN;
+ p += HEADERLEN;
+
+ switch (code) {
+ case CONFREQ:
+ case CONFACK:
+ case CONFNAK:
+ case CONFREJ:
+ /* print list of possible compression methods */
+ while (len >= 2) {
+ code = p[0];
+ optlen = p[1];
+ if (optlen < 2 || optlen > len)
+ break;
+ printer(arg, " <");
+ len -= optlen;
+ optend = p + optlen;
+ switch (code) {
+ case CI_DEFLATE:
+ case CI_DEFLATE_DRAFT:
+ if (optlen >= CILEN_DEFLATE) {
+ printer(arg, "deflate%s %d",
+ (code == CI_DEFLATE_DRAFT? "(old#)": ""),
+ DEFLATE_SIZE(p[2]));
+ if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL)
+ printer(arg, " method %d", DEFLATE_METHOD(p[2]));
+ if (p[3] != DEFLATE_CHK_SEQUENCE)
+ printer(arg, " check %d", p[3]);
+ p += CILEN_DEFLATE;
+ }
+ break;
+ case CI_BSD_COMPRESS:
+ if (optlen >= CILEN_BSD_COMPRESS) {
+ printer(arg, "bsd v%d %d", BSD_VERSION(p[2]),
+ BSD_NBITS(p[2]));
+ p += CILEN_BSD_COMPRESS;
+ }
+ break;
+ case CI_PREDICTOR_1:
+ if (optlen >= CILEN_PREDICTOR_1) {
+ printer(arg, "predictor 1");
+ p += CILEN_PREDICTOR_1;
+ }
+ break;
+ case CI_PREDICTOR_2:
+ if (optlen >= CILEN_PREDICTOR_2) {
+ printer(arg, "predictor 2");
+ p += CILEN_PREDICTOR_2;
+ }
+ break;
+ }
+ while (p < optend)
+ printer(arg, " %.2x", *p++);
+ printer(arg, ">");
+ }
+ break;
+
+ case TERMACK:
+ case TERMREQ:
+ if (len > 0 && *p >= ' ' && *p < 0x7f) {
+ print_string(p, len, printer, arg);
+ p += len;
+ len = 0;
+ }
+ break;
+ }
+
+ /* dump out the rest of the packet in hex */
+ while (--len >= 0)
+ printer(arg, " %.2x", *p++);
+
+ return p - p0;
+}
+
+/*
+ * We have received a packet that the decompressor failed to
+ * decompress. Here we would expect to issue a reset-request, but
+ * Motorola has a patent on resetting the compressor as a result of
+ * detecting an error in the decompressed data after decompression.
+ * (See US patent 5,130,993; international patent publication number
+ * WO 91/10289; Australian patent 73296/91.)
+ *
+ * So we ask the kernel whether the error was detected after
+ * decompression; if it was, we take CCP down, thus disabling
+ * compression :-(, otherwise we issue the reset-request.
+ */
+static void
+ccp_datainput(unit, pkt, len)
+ int unit;
+ u_char *pkt;
+ int len;
+{
+ fsm *f;
+
+ f = &ccp_fsm[unit];
+ if (f->state == OPENED) {
+ if (ccp_fatal_error(unit)) {
+ /*
+ * Disable compression by taking CCP down.
+ */
+ error("Lost compression sync: disabling compression");
+ ccp_close(unit, "Lost compression sync");
+ } else {
+ /*
+ * Send a reset-request to reset the peer's compressor.
+ * We don't do that if we are still waiting for an
+ * acknowledgement to a previous reset-request.
+ */
+ if (!(ccp_localstate[f->unit] & RACK_PENDING)) {
+ fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0);
+ TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT);
+ ccp_localstate[f->unit] |= RACK_PENDING;
+ } else
+ ccp_localstate[f->unit] |= RREQ_REPEAT;
+ }
+ }
+}
+
+/*
+ * Timeout waiting for reset-ack.
+ */
+static void
+ccp_rack_timeout(arg)
+ void *arg;
+{
+ fsm *f = arg;
+
+ if (f->state == OPENED && ccp_localstate[f->unit] & RREQ_REPEAT) {
+ fsm_sdata(f, CCP_RESETREQ, f->reqid, NULL, 0);
+ TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT);
+ ccp_localstate[f->unit] &= ~RREQ_REPEAT;
+ } else
+ ccp_localstate[f->unit] &= ~RACK_PENDING;
+}
diff --git a/cpukit/pppd/ccp.h b/cpukit/pppd/ccp.h
new file mode 100644
index 0000000000..609d858c5e
--- /dev/null
+++ b/cpukit/pppd/ccp.h
@@ -0,0 +1,48 @@
+/*
+ * ccp.h - Definitions for PPP Compression Control Protocol.
+ *
+ * Copyright (c) 1994 The Australian National University.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, provided that the above copyright
+ * notice appears in all copies. This software is provided without any
+ * warranty, express or implied. The Australian National University
+ * makes no representations about the suitability of this software for
+ * any purpose.
+ *
+ * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+ * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
+ * OR MODIFICATIONS.
+ *
+ * $Id$
+ */
+
+typedef struct ccp_options {
+ bool bsd_compress; /* do BSD Compress? */
+ bool deflate; /* do Deflate? */
+ bool predictor_1; /* do Predictor-1? */
+ bool predictor_2; /* do Predictor-2? */
+ bool deflate_correct; /* use correct code for deflate? */
+ bool deflate_draft; /* use draft RFC code for deflate? */
+ u_short bsd_bits; /* # bits/code for BSD Compress */
+ u_short deflate_size; /* lg(window size) for Deflate */
+ short method; /* code for chosen compression method */
+} ccp_options;
+
+extern fsm ccp_fsm[];
+extern ccp_options ccp_wantoptions[];
+extern ccp_options ccp_gotoptions[];
+extern ccp_options ccp_allowoptions[];
+extern ccp_options ccp_hisoptions[];
+
+extern struct protent ccp_protent;
diff --git a/cpukit/pppd/chap.c b/cpukit/pppd/chap.c
new file mode 100644
index 0000000000..c1a17e5ab3
--- /dev/null
+++ b/cpukit/pppd/chap.c
@@ -0,0 +1,858 @@
+/*
+ * chap.c - Challenge Handshake Authentication Protocol.
+ *
+ * Copyright (c) 1993 The Australian National University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the Australian National University. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Copyright (c) 1991 Gregory M. Christy.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Gregory M. Christy. 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#define RCSID "$Id$"
+
+/*
+ * TODO:
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h> /* drand48, srand48 */
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include "pppd.h"
+#include "chap.h"
+#include "md5.h"
+#ifdef CHAPMS
+#include "chap_ms.h"
+#endif
+
+static const char rcsid[] = RCSID;
+
+/*
+ * Command-line options.
+ */
+static option_t chap_option_list[] = {
+ { "chap-restart", o_int, &chap[0].timeouttime,
+ "Set timeout for CHAP" },
+ { "chap-max-challenge", o_int, &chap[0].max_transmits,
+ "Set max #xmits for challenge" },
+ { "chap-interval", o_int, &chap[0].chal_interval,
+ "Set interval for rechallenge" },
+#ifdef MSLANMAN
+ { "ms-lanman", o_bool, &ms_lanman,
+ "Use LanMan passwd when using MS-CHAP", 1 },
+#endif
+ { NULL }
+};
+
+/*
+ * Protocol entry points.
+ */
+static void ChapInit __P((int));
+static void ChapLowerUp __P((int));
+static void ChapLowerDown __P((int));
+static void ChapInput __P((int, u_char *, int));
+static void ChapProtocolReject __P((int));
+static int ChapPrintPkt __P((u_char *, int,
+ void (*) __P((void *, char *, ...)), void *));
+
+struct protent chap_protent = {
+ PPP_CHAP,
+ ChapInit,
+ ChapInput,
+ ChapProtocolReject,
+ ChapLowerUp,
+ ChapLowerDown,
+ NULL,
+ NULL,
+ ChapPrintPkt,
+ NULL,
+ 1,
+ "CHAP",
+ NULL,
+ chap_option_list,
+ NULL,
+ NULL,
+ NULL
+};
+
+chap_state chap[NUM_PPP]; /* CHAP state; one for each unit */
+
+static void ChapChallengeTimeout __P((void *));
+static void ChapResponseTimeout __P((void *));
+static void ChapReceiveChallenge __P((chap_state *, u_char *, int, int));
+static void ChapRechallenge __P((void *));
+static void ChapReceiveResponse __P((chap_state *, u_char *, int, int));
+static void ChapReceiveSuccess __P((chap_state *, u_char *, u_char, int));
+static void ChapReceiveFailure __P((chap_state *, u_char *, u_char, int));
+static void ChapSendStatus __P((chap_state *, int));
+static void ChapSendChallenge __P((chap_state *));
+static void ChapSendResponse __P((chap_state *));
+static void ChapGenChallenge __P((chap_state *));
+
+/*
+ * ChapInit - Initialize a CHAP unit.
+ */
+static void
+ChapInit(unit)
+ int unit;
+{
+ chap_state *cstate = &chap[unit];
+
+ BZERO(cstate, sizeof(*cstate));
+ cstate->unit = unit;
+ cstate->clientstate = CHAPCS_INITIAL;
+ cstate->serverstate = CHAPSS_INITIAL;
+ cstate->timeouttime = CHAP_DEFTIMEOUT;
+ cstate->max_transmits = CHAP_DEFTRANSMITS;
+ /* random number generator is initialized in magic_init */
+}
+
+
+/*
+ * ChapAuthWithPeer - Authenticate us with our peer (start client).
+ *
+ */
+void
+ChapAuthWithPeer(unit, our_name, digest)
+ int unit;
+ char *our_name;
+ int digest;
+{
+ chap_state *cstate = &chap[unit];
+
+ cstate->resp_name = our_name;
+ cstate->resp_type = digest;
+
+ if (cstate->clientstate == CHAPCS_INITIAL ||
+ cstate->clientstate == CHAPCS_PENDING) {
+ /* lower layer isn't up - wait until later */
+ cstate->clientstate = CHAPCS_PENDING;
+ return;
+ }
+
+ /*
+ * We get here as a result of LCP coming up.
+ * So even if CHAP was open before, we will
+ * have to re-authenticate ourselves.
+ */
+ cstate->clientstate = CHAPCS_LISTEN;
+}
+
+
+/*
+ * ChapAuthPeer - Authenticate our peer (start server).
+ */
+void
+ChapAuthPeer(unit, our_name, digest)
+ int unit;
+ char *our_name;
+ int digest;
+{
+ chap_state *cstate = &chap[unit];
+
+ cstate->chal_name = our_name;
+ cstate->chal_type = digest;
+
+ if (cstate->serverstate == CHAPSS_INITIAL ||
+ cstate->serverstate == CHAPSS_PENDING) {
+ /* lower layer isn't up - wait until later */
+ cstate->serverstate = CHAPSS_PENDING;
+ return;
+ }
+
+ ChapGenChallenge(cstate);
+ ChapSendChallenge(cstate); /* crank it up dude! */
+ cstate->serverstate = CHAPSS_INITIAL_CHAL;
+}
+
+
+/*
+ * ChapChallengeTimeout - Timeout expired on sending challenge.
+ */
+static void
+ChapChallengeTimeout(arg)
+ void *arg;
+{
+ chap_state *cstate = (chap_state *) arg;
+
+ /* if we aren't sending challenges, don't worry. then again we */
+ /* probably shouldn't be here either */
+ if (cstate->serverstate != CHAPSS_INITIAL_CHAL &&
+ cstate->serverstate != CHAPSS_RECHALLENGE)
+ return;
+
+ if (cstate->chal_transmits >= cstate->max_transmits) {
+ /* give up on peer */
+ error("Peer failed to respond to CHAP challenge");
+ cstate->serverstate = CHAPSS_BADAUTH;
+ auth_peer_fail(cstate->unit, PPP_CHAP);
+ return;
+ }
+
+ ChapSendChallenge(cstate); /* Re-send challenge */
+}
+
+
+/*
+ * ChapResponseTimeout - Timeout expired on sending response.
+ */
+static void
+ChapResponseTimeout(arg)
+ void *arg;
+{
+ chap_state *cstate = (chap_state *) arg;
+
+ /* if we aren't sending a response, don't worry. */
+ if (cstate->clientstate != CHAPCS_RESPONSE)
+ return;
+
+ ChapSendResponse(cstate); /* re-send response */
+}
+
+
+/*
+ * ChapRechallenge - Time to challenge the peer again.
+ */
+static void
+ChapRechallenge(arg)
+ void *arg;
+{
+ chap_state *cstate = (chap_state *) arg;
+
+ /* if we aren't sending a response, don't worry. */
+ if (cstate->serverstate != CHAPSS_OPEN)
+ return;
+
+ ChapGenChallenge(cstate);
+ ChapSendChallenge(cstate);
+ cstate->serverstate = CHAPSS_RECHALLENGE;
+}
+
+
+/*
+ * ChapLowerUp - The lower layer is up.
+ *
+ * Start up if we have pending requests.
+ */
+static void
+ChapLowerUp(unit)
+ int unit;
+{
+ chap_state *cstate = &chap[unit];
+
+ if (cstate->clientstate == CHAPCS_INITIAL)
+ cstate->clientstate = CHAPCS_CLOSED;
+ else if (cstate->clientstate == CHAPCS_PENDING)
+ cstate->clientstate = CHAPCS_LISTEN;
+
+ if (cstate->serverstate == CHAPSS_INITIAL)
+ cstate->serverstate = CHAPSS_CLOSED;
+ else if (cstate->serverstate == CHAPSS_PENDING) {
+ ChapGenChallenge(cstate);
+ ChapSendChallenge(cstate);
+ cstate->serverstate = CHAPSS_INITIAL_CHAL;
+ }
+}
+
+
+/*
+ * ChapLowerDown - The lower layer is down.
+ *
+ * Cancel all timeouts.
+ */
+static void
+ChapLowerDown(unit)
+ int unit;
+{
+ chap_state *cstate = &chap[unit];
+
+ /* Timeout(s) pending? Cancel if so. */
+ if (cstate->serverstate == CHAPSS_INITIAL_CHAL ||
+ cstate->serverstate == CHAPSS_RECHALLENGE)
+ UNTIMEOUT(ChapChallengeTimeout, cstate);
+ else if (cstate->serverstate == CHAPSS_OPEN
+ && cstate->chal_interval != 0)
+ UNTIMEOUT(ChapRechallenge, cstate);
+ if (cstate->clientstate == CHAPCS_RESPONSE)
+ UNTIMEOUT(ChapResponseTimeout, cstate);
+
+ cstate->clientstate = CHAPCS_INITIAL;
+ cstate->serverstate = CHAPSS_INITIAL;
+}
+
+
+/*
+ * ChapProtocolReject - Peer doesn't grok CHAP.
+ */
+static void
+ChapProtocolReject(unit)
+ int unit;
+{
+ chap_state *cstate = &chap[unit];
+
+ if (cstate->serverstate != CHAPSS_INITIAL &&
+ cstate->serverstate != CHAPSS_CLOSED)
+ auth_peer_fail(unit, PPP_CHAP);
+ if (cstate->clientstate != CHAPCS_INITIAL &&
+ cstate->clientstate != CHAPCS_CLOSED)
+ auth_withpeer_fail(unit, PPP_CHAP);
+ ChapLowerDown(unit); /* shutdown chap */
+}
+
+
+/*
+ * ChapInput - Input CHAP packet.
+ */
+static void
+ChapInput(unit, inpacket, packet_len)
+ int unit;
+ u_char *inpacket;
+ int packet_len;
+{
+ chap_state *cstate = &chap[unit];
+ u_char *inp;
+ u_char code, id;
+ int len;
+
+ /*
+ * Parse header (code, id and length).
+ * If packet too short, drop it.
+ */
+ inp = inpacket;
+ if (packet_len < CHAP_HEADERLEN) {
+ CHAPDEBUG(("ChapInput: rcvd short header."));
+ return;
+ }
+ GETCHAR(code, inp);
+ GETCHAR(id, inp);
+ GETSHORT(len, inp);
+ if (len < CHAP_HEADERLEN) {
+ CHAPDEBUG(("ChapInput: rcvd illegal length."));
+ return;
+ }
+ if (len > packet_len) {
+ CHAPDEBUG(("ChapInput: rcvd short packet."));
+ return;
+ }
+ len -= CHAP_HEADERLEN;
+
+ /*
+ * Action depends on code (as in fact it usually does :-).
+ */
+ switch (code) {
+ case CHAP_CHALLENGE:
+ ChapReceiveChallenge(cstate, inp, id, len);
+ break;
+
+ case CHAP_RESPONSE:
+ ChapReceiveResponse(cstate, inp, id, len);
+ break;
+
+ case CHAP_FAILURE:
+ ChapReceiveFailure(cstate, inp, id, len);
+ break;
+
+ case CHAP_SUCCESS:
+ ChapReceiveSuccess(cstate, inp, id, len);
+ break;
+
+ default: /* Need code reject? */
+ warn("Unknown CHAP code (%d) received.", code);
+ break;
+ }
+}
+
+
+/*
+ * ChapReceiveChallenge - Receive Challenge and send Response.
+ */
+static void
+ChapReceiveChallenge(cstate, inp, id, len)
+ chap_state *cstate;
+ u_char *inp;
+ int id;
+ int len;
+{
+ int rchallenge_len;
+ u_char *rchallenge;
+ int secret_len;
+ char secret[MAXSECRETLEN];
+ char rhostname[256];
+ MD5_CTX mdContext;
+ u_char hash[MD5_SIGNATURE_SIZE];
+
+ if (cstate->clientstate == CHAPCS_CLOSED ||
+ cstate->clientstate == CHAPCS_PENDING) {
+ CHAPDEBUG(("ChapReceiveChallenge: in state %d", cstate->clientstate));
+ return;
+ }
+
+ if (len < 2) {
+ CHAPDEBUG(("ChapReceiveChallenge: rcvd short packet."));
+ return;
+ }
+
+ GETCHAR(rchallenge_len, inp);
+ len -= sizeof (u_char) + rchallenge_len; /* now name field length */
+ if (len < 0) {
+ CHAPDEBUG(("ChapReceiveChallenge: rcvd short packet."));
+ return;
+ }
+ rchallenge = inp;
+ INCPTR(rchallenge_len, inp);
+
+ if (len >= sizeof(rhostname))
+ len = sizeof(rhostname) - 1;
+ BCOPY(inp, rhostname, len);
+ rhostname[len] = '\000';
+
+ /* Microsoft doesn't send their name back in the PPP packet */
+ if (explicit_remote || (remote_name[0] != 0 && rhostname[0] == 0)) {
+ strlcpy(rhostname, remote_name, sizeof(rhostname));
+ CHAPDEBUG(("ChapReceiveChallenge: using '%q' as remote name",
+ rhostname));
+ }
+
+ /* get secret for authenticating ourselves with the specified host */
+ if (!get_secret(cstate->unit, cstate->resp_name, rhostname,
+ secret, &secret_len, 0)) {
+ secret_len = 0; /* assume null secret if can't find one */
+ warn("No CHAP secret found for authenticating us to %q", rhostname);
+ }
+
+ /* cancel response send timeout if necessary */
+ if (cstate->clientstate == CHAPCS_RESPONSE)
+ UNTIMEOUT(ChapResponseTimeout, cstate);
+
+ cstate->resp_id = id;
+ cstate->resp_transmits = 0;
+
+ /* generate MD based on negotiated type */
+ switch (cstate->resp_type) {
+
+ case CHAP_DIGEST_MD5:
+ MD5Init(&mdContext);
+ MD5Update(&mdContext, &cstate->resp_id, 1);
+ MD5Update(&mdContext, secret, secret_len);
+ MD5Update(&mdContext, rchallenge, rchallenge_len);
+ MD5Final(hash, &mdContext);
+ BCOPY(hash, cstate->response, MD5_SIGNATURE_SIZE);
+ cstate->resp_length = MD5_SIGNATURE_SIZE;
+ break;
+
+#ifdef CHAPMS
+ case CHAP_MICROSOFT:
+ ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len);
+ break;
+#endif
+
+ default:
+ CHAPDEBUG(("unknown digest type %d", cstate->resp_type));
+ return;
+ }
+
+ BZERO(secret, sizeof(secret));
+ ChapSendResponse(cstate);
+}
+
+
+/*
+ * ChapReceiveResponse - Receive and process response.
+ */
+static void
+ChapReceiveResponse(cstate, inp, id, len)
+ chap_state *cstate;
+ u_char *inp;
+ int id;
+ int len;
+{
+ u_char *remmd, remmd_len;
+ int secret_len, old_state;
+ int code;
+ char rhostname[256];
+ MD5_CTX mdContext;
+ char secret[MAXSECRETLEN];
+ u_char hash[MD5_SIGNATURE_SIZE];
+
+ if (cstate->serverstate == CHAPSS_CLOSED ||
+ cstate->serverstate == CHAPSS_PENDING) {
+ CHAPDEBUG(("ChapReceiveResponse: in state %d", cstate->serverstate));
+ return;
+ }
+
+ if (id != cstate->chal_id)
+ return; /* doesn't match ID of last challenge */
+
+ /*
+ * If we have received a duplicate or bogus Response,
+ * we have to send the same answer (Success/Failure)
+ * as we did for the first Response we saw.
+ */
+ if (cstate->serverstate == CHAPSS_OPEN) {
+ ChapSendStatus(cstate, CHAP_SUCCESS);
+ return;
+ }
+ if (cstate->serverstate == CHAPSS_BADAUTH) {
+ ChapSendStatus(cstate, CHAP_FAILURE);
+ return;
+ }
+
+ if (len < 2) {
+ CHAPDEBUG(("ChapReceiveResponse: rcvd short packet."));
+ return;
+ }
+ GETCHAR(remmd_len, inp); /* get length of MD */
+ remmd = inp; /* get pointer to MD */
+ INCPTR(remmd_len, inp);
+
+ len -= sizeof (u_char) + remmd_len;
+ if (len < 0) {
+ CHAPDEBUG(("ChapReceiveResponse: rcvd short packet."));
+ return;
+ }
+
+ UNTIMEOUT(ChapChallengeTimeout, cstate);
+
+ if (len >= sizeof(rhostname))
+ len = sizeof(rhostname) - 1;
+ BCOPY(inp, rhostname, len);
+ rhostname[len] = '\000';
+
+ /*
+ * Get secret for authenticating them with us,
+ * do the hash ourselves, and compare the result.
+ */
+ code = CHAP_FAILURE;
+ if (!get_secret(cstate->unit, (explicit_remote? remote_name: rhostname),
+ cstate->chal_name, secret, &secret_len, 1)) {
+ warn("No CHAP secret found for authenticating %q", rhostname);
+ } else {
+
+ /* generate MD based on negotiated type */
+ switch (cstate->chal_type) {
+
+ case CHAP_DIGEST_MD5: /* only MD5 is defined for now */
+ if (remmd_len != MD5_SIGNATURE_SIZE)
+ break; /* it's not even the right length */
+ MD5Init(&mdContext);
+ MD5Update(&mdContext, &cstate->chal_id, 1);
+ MD5Update(&mdContext, secret, secret_len);
+ MD5Update(&mdContext, cstate->challenge, cstate->chal_len);
+ MD5Final(hash, &mdContext);
+
+ /* compare local and remote MDs and send the appropriate status */
+ if (memcmp (hash, remmd, MD5_SIGNATURE_SIZE) == 0)
+ code = CHAP_SUCCESS; /* they are the same! */
+ break;
+
+ default:
+ CHAPDEBUG(("unknown digest type %d", cstate->chal_type));
+ }
+ }
+
+ BZERO(secret, sizeof(secret));
+ ChapSendStatus(cstate, code);
+
+ if (code == CHAP_SUCCESS) {
+ old_state = cstate->serverstate;
+ cstate->serverstate = CHAPSS_OPEN;
+ if (old_state == CHAPSS_INITIAL_CHAL) {
+ auth_peer_success(cstate->unit, PPP_CHAP, rhostname, len);
+ }
+ if (cstate->chal_interval != 0)
+ TIMEOUT(ChapRechallenge, cstate, cstate->chal_interval);
+ notice("CHAP peer authentication succeeded for %q", rhostname);
+
+ } else {
+ error("CHAP peer authentication failed for remote host %q", rhostname);
+ cstate->serverstate = CHAPSS_BADAUTH;
+ auth_peer_fail(cstate->unit, PPP_CHAP);
+ }
+}
+
+/*
+ * ChapReceiveSuccess - Receive Success
+ */
+static void
+ChapReceiveSuccess(cstate, inp, id, len)
+ chap_state *cstate;
+ u_char *inp;
+ u_char id;
+ int len;
+{
+
+ if (cstate->clientstate == CHAPCS_OPEN)
+ /* presumably an answer to a duplicate response */
+ return;
+
+ if (cstate->clientstate != CHAPCS_RESPONSE) {
+ /* don't know what this is */
+ CHAPDEBUG(("ChapReceiveSuccess: in state %d\n", cstate->clientstate));
+ return;
+ }
+
+ UNTIMEOUT(ChapResponseTimeout, cstate);
+
+ /*
+ * Print message.
+ */
+ if (len > 0)
+ PRINTMSG(inp, len);
+
+ cstate->clientstate = CHAPCS_OPEN;
+
+ auth_withpeer_success(cstate->unit, PPP_CHAP);
+}
+
+
+/*
+ * ChapReceiveFailure - Receive failure.
+ */
+static void
+ChapReceiveFailure(cstate, inp, id, len)
+ chap_state *cstate;
+ u_char *inp;
+ u_char id;
+ int len;
+{
+ if (cstate->clientstate != CHAPCS_RESPONSE) {
+ /* don't know what this is */
+ CHAPDEBUG(("ChapReceiveFailure: in state %d\n", cstate->clientstate));
+ return;
+ }
+
+ UNTIMEOUT(ChapResponseTimeout, cstate);
+
+ /*
+ * Print message.
+ */
+ if (len > 0)
+ PRINTMSG(inp, len);
+
+ error("CHAP authentication failed");
+ auth_withpeer_fail(cstate->unit, PPP_CHAP);
+}
+
+
+/*
+ * ChapSendChallenge - Send an Authenticate challenge.
+ */
+static void
+ChapSendChallenge(cstate)
+ chap_state *cstate;
+{
+ u_char *outp;
+ int chal_len, name_len;
+ int outlen;
+
+ chal_len = cstate->chal_len;
+ name_len = strlen(cstate->chal_name);
+ outlen = CHAP_HEADERLEN + sizeof (u_char) + chal_len + name_len;
+ outp = outpacket_buf;
+
+ MAKEHEADER(outp, PPP_CHAP); /* paste in a CHAP header */
+
+ PUTCHAR(CHAP_CHALLENGE, outp);
+ PUTCHAR(cstate->chal_id, outp);
+ PUTSHORT(outlen, outp);
+
+ PUTCHAR(chal_len, outp); /* put length of challenge */
+ BCOPY(cstate->challenge, outp, chal_len);
+ INCPTR(chal_len, outp);
+
+ BCOPY(cstate->chal_name, outp, name_len); /* append hostname */
+
+ output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN);
+
+ TIMEOUT(ChapChallengeTimeout, cstate, cstate->timeouttime);
+ ++cstate->chal_transmits;
+}
+
+
+/*
+ * ChapSendStatus - Send a status response (ack or nak).
+ */
+static void
+ChapSendStatus(cstate, code)
+ chap_state *cstate;
+ int code;
+{
+ u_char *outp;
+ int outlen, msglen;
+ char msg[256];
+
+ if (code == CHAP_SUCCESS)
+ slprintf(msg, sizeof(msg), "Welcome to %s.", hostname);
+ else
+ slprintf(msg, sizeof(msg), "I don't like you. Go 'way.");
+ msglen = strlen(msg);
+
+ outlen = CHAP_HEADERLEN + msglen;
+ outp = outpacket_buf;
+
+ MAKEHEADER(outp, PPP_CHAP); /* paste in a header */
+
+ PUTCHAR(code, outp);
+ PUTCHAR(cstate->chal_id, outp);
+ PUTSHORT(outlen, outp);
+ BCOPY(msg, outp, msglen);
+ output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN);
+}
+
+/*
+ * ChapGenChallenge is used to generate a pseudo-random challenge string of
+ * a pseudo-random length between min_len and max_len. The challenge
+ * string and its length are stored in *cstate, and various other fields of
+ * *cstate are initialized.
+ */
+
+static void
+ChapGenChallenge(cstate)
+ chap_state *cstate;
+{
+ int chal_len;
+ u_char *ptr = cstate->challenge;
+ int i;
+
+ /* pick a random challenge length between MIN_CHALLENGE_LENGTH and
+ MAX_CHALLENGE_LENGTH */
+ chal_len = (unsigned) ((drand48() *
+ (MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH)) +
+ MIN_CHALLENGE_LENGTH);
+ cstate->chal_len = chal_len;
+ cstate->chal_id = ++cstate->id;
+ cstate->chal_transmits = 0;
+
+ /* generate a random string */
+ for (i = 0; i < chal_len; i++)
+ *ptr++ = (char) (drand48() * 0xff);
+}
+
+/*
+ * ChapSendResponse - send a response packet with values as specified
+ * in *cstate.
+ */
+/* ARGSUSED */
+static void
+ChapSendResponse(cstate)
+ chap_state *cstate;
+{
+ u_char *outp;
+ int outlen, md_len, name_len;
+
+ md_len = cstate->resp_length;
+ name_len = strlen(cstate->resp_name);
+ outlen = CHAP_HEADERLEN + sizeof (u_char) + md_len + name_len;
+ outp = outpacket_buf;
+
+ MAKEHEADER(outp, PPP_CHAP);
+
+ PUTCHAR(CHAP_RESPONSE, outp); /* we are a response */
+ PUTCHAR(cstate->resp_id, outp); /* copy id from challenge packet */
+ PUTSHORT(outlen, outp); /* packet length */
+
+ PUTCHAR(md_len, outp); /* length of MD */
+ BCOPY(cstate->response, outp, md_len); /* copy MD to buffer */
+ INCPTR(md_len, outp);
+
+ BCOPY(cstate->resp_name, outp, name_len); /* append our name */
+
+ /* send the packet */
+ output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN);
+
+ cstate->clientstate = CHAPCS_RESPONSE;
+ TIMEOUT(ChapResponseTimeout, cstate, cstate->timeouttime);
+ ++cstate->resp_transmits;
+}
+
+/*
+ * ChapPrintPkt - print the contents of a CHAP packet.
+ */
+static char *ChapCodenames[] = {
+ "Challenge", "Response", "Success", "Failure"
+};
+
+static int
+ChapPrintPkt(p, plen, printer, arg)
+ u_char *p;
+ int plen;
+ void (*printer) __P((void *, char *, ...));
+ void *arg;
+{
+ int code, id, len;
+ int clen, nlen;
+ u_char x;
+
+ if (plen < CHAP_HEADERLEN)
+ return 0;
+ GETCHAR(code, p);
+ GETCHAR(id, p);
+ GETSHORT(len, p);
+ if (len < CHAP_HEADERLEN || len > plen)
+ return 0;
+
+ if (code >= 1 && code <= sizeof(ChapCodenames) / sizeof(char *))
+ printer(arg, " %s", ChapCodenames[code-1]);
+ else
+ printer(arg, " code=0x%x", code);
+ printer(arg, " id=0x%x", id);
+ len -= CHAP_HEADERLEN;
+ switch (code) {
+ case CHAP_CHALLENGE:
+ case CHAP_RESPONSE:
+ if (len < 1)
+ break;
+ clen = p[0];
+ if (len < clen + 1)
+ break;
+ ++p;
+ nlen = len - clen - 1;
+ printer(arg, " <");
+ for (; clen > 0; --clen) {
+ GETCHAR(x, p);
+ printer(arg, "%.2x", x);
+ }
+ printer(arg, ">, name = ");
+ print_string((char *)p, nlen, printer, arg);
+ break;
+ case CHAP_FAILURE:
+ case CHAP_SUCCESS:
+ printer(arg, " ");
+ print_string((char *)p, len, printer, arg);
+ break;
+ default:
+ for (clen = len; clen > 0; --clen) {
+ GETCHAR(x, p);
+ printer(arg, " %.2x", x);
+ }
+ }
+
+ return len + CHAP_HEADERLEN;
+}
diff --git a/cpukit/pppd/chap.h b/cpukit/pppd/chap.h
new file mode 100644
index 0000000000..9f0361b1ae
--- /dev/null
+++ b/cpukit/pppd/chap.h
@@ -0,0 +1,124 @@
+/*
+ * chap.h - Challenge Handshake Authentication Protocol definitions.
+ *
+ * Copyright (c) 1993 The Australian National University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the Australian National University. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Copyright (c) 1991 Gregory M. Christy
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the author.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * $Id$
+ */
+
+#ifndef __CHAP_INCLUDE__
+
+/* Code + ID + length */
+#define CHAP_HEADERLEN 4
+
+/*
+ * CHAP codes.
+ */
+
+#define CHAP_DIGEST_MD5 5 /* use MD5 algorithm */
+#define MD5_SIGNATURE_SIZE 16 /* 16 bytes in a MD5 message digest */
+#define CHAP_MICROSOFT 0x80 /* use Microsoft-compatible alg. */
+#define MS_CHAP_RESPONSE_LEN 49 /* Response length for MS-CHAP */
+
+#define CHAP_CHALLENGE 1
+#define CHAP_RESPONSE 2
+#define CHAP_SUCCESS 3
+#define CHAP_FAILURE 4
+
+/*
+ * Challenge lengths (for challenges we send) and other limits.
+ */
+#define MIN_CHALLENGE_LENGTH 16
+#define MAX_CHALLENGE_LENGTH 24
+#define MAX_RESPONSE_LENGTH 64 /* sufficient for MD5 or MS-CHAP */
+
+/*
+ * Each interface is described by a chap structure.
+ */
+
+typedef struct chap_state {
+ int unit; /* Interface unit number */
+ int clientstate; /* Client state */
+ int serverstate; /* Server state */
+ u_char challenge[MAX_CHALLENGE_LENGTH]; /* last challenge string sent */
+ u_char chal_len; /* challenge length */
+ u_char chal_id; /* ID of last challenge */
+ u_char chal_type; /* hash algorithm for challenges */
+ u_char id; /* Current id */
+ char *chal_name; /* Our name to use with challenge */
+ int chal_interval; /* Time until we challenge peer again */
+ int timeouttime; /* Timeout time in seconds */
+ int max_transmits; /* Maximum # of challenge transmissions */
+ int chal_transmits; /* Number of transmissions of challenge */
+ int resp_transmits; /* Number of transmissions of response */
+ u_char response[MAX_RESPONSE_LENGTH]; /* Response to send */
+ u_char resp_length; /* length of response */
+ u_char resp_id; /* ID for response messages */
+ u_char resp_type; /* hash algorithm for responses */
+ char *resp_name; /* Our name to send with response */
+} chap_state;
+
+
+/*
+ * Client (peer) states.
+ */
+#define CHAPCS_INITIAL 0 /* Lower layer down, not opened */
+#define CHAPCS_CLOSED 1 /* Lower layer up, not opened */
+#define CHAPCS_PENDING 2 /* Auth us to peer when lower up */
+#define CHAPCS_LISTEN 3 /* Listening for a challenge */
+#define CHAPCS_RESPONSE 4 /* Sent response, waiting for status */
+#define CHAPCS_OPEN 5 /* We've received Success */
+
+/*
+ * Server (authenticator) states.
+ */
+#define CHAPSS_INITIAL 0 /* Lower layer down, not opened */
+#define CHAPSS_CLOSED 1 /* Lower layer up, not opened */
+#define CHAPSS_PENDING 2 /* Auth peer when lower up */
+#define CHAPSS_INITIAL_CHAL 3 /* We've sent the first challenge */
+#define CHAPSS_OPEN 4 /* We've sent a Success msg */
+#define CHAPSS_RECHALLENGE 5 /* We've sent another challenge */
+#define CHAPSS_BADAUTH 6 /* We've sent a Failure msg */
+
+/*
+ * Timeouts.
+ */
+#define CHAP_DEFTIMEOUT 5 /* Timeout time in seconds */
+#define CHAP_DEFTRANSMITS 10 /* max # times to send challenge */
+
+extern chap_state chap[];
+
+void ChapAuthWithPeer __P((int, char *, int));
+void ChapAuthPeer __P((int, char *, int));
+
+extern struct protent chap_protent;
+
+#define __CHAP_INCLUDE__
+#endif /* __CHAP_INCLUDE__ */
diff --git a/cpukit/pppd/chap_ms.c b/cpukit/pppd/chap_ms.c
new file mode 100644
index 0000000000..81a57bb5aa
--- /dev/null
+++ b/cpukit/pppd/chap_ms.c
@@ -0,0 +1,338 @@
+/*
+ * chap_ms.c - Microsoft MS-CHAP compatible implementation.
+ *
+ * Copyright (c) 1995 Eric Rosenquist, Strata Software Limited.
+ * http://www.strataware.com/
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Eric Rosenquist. 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ * Modifications by Lauri Pesonen / lpesonen@clinet.fi, april 1997
+ *
+ * Implemented LANManager type password response to MS-CHAP challenges.
+ * Now pppd provides both NT style and LANMan style blocks, and the
+ * prefered is set by option "ms-lanman". Default is to use NT.
+ * The hash text (StdText) was taken from Win95 RASAPI32.DLL.
+ *
+ * You should also use DOMAIN\\USERNAME as described in README.MSCHAP80
+ */
+
+#define RCSID "$Id$"
+
+#ifdef CHAPMS
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <unistd.h>
+#ifdef HAVE_CRYPT_H
+#include <crypt.h>
+#endif
+
+#include "pppd.h"
+#include "chap.h"
+#include "chap_ms.h"
+#include "md4.h"
+
+#ifndef USE_CRYPT
+#include <des.h>
+#endif
+
+static const char rcsid[] = RCSID;
+
+typedef struct {
+ u_char LANManResp[24];
+ u_char NTResp[24];
+ u_char UseNT; /* If 1, ignore the LANMan response field */
+} MS_ChapResponse;
+/* We use MS_CHAP_RESPONSE_LEN, rather than sizeof(MS_ChapResponse),
+ in case this struct gets padded. */
+
+
+static void ChallengeResponse __P((u_char *, u_char *, u_char *));
+static void DesEncrypt __P((u_char *, u_char *, u_char *));
+static void MakeKey __P((u_char *, u_char *));
+static u_char Get7Bits __P((u_char *, int));
+static void ChapMS_NT __P((char *, int, char *, int, MS_ChapResponse *));
+#ifdef MSLANMAN
+static void ChapMS_LANMan __P((char *, int, char *, int, MS_ChapResponse *));
+#endif
+
+#ifdef USE_CRYPT
+static void Expand __P((u_char *, u_char *));
+static void Collapse __P((u_char *, u_char *));
+#endif
+
+#ifdef MSLANMAN
+bool ms_lanman = 0; /* Use LanMan password instead of NT */
+ /* Has meaning only with MS-CHAP challenges */
+#endif
+
+static void
+ChallengeResponse(challenge, pwHash, response)
+ u_char *challenge; /* IN 8 octets */
+ u_char *pwHash; /* IN 16 octets */
+ u_char *response; /* OUT 24 octets */
+{
+ char ZPasswordHash[21];
+
+ BZERO(ZPasswordHash, sizeof(ZPasswordHash));
+ BCOPY(pwHash, ZPasswordHash, MD4_SIGNATURE_SIZE);
+
+#if 0
+ dbglog("ChallengeResponse - ZPasswordHash %.*B",
+ sizeof(ZPasswordHash), ZPasswordHash);
+#endif
+
+ DesEncrypt(challenge, ZPasswordHash + 0, response + 0);
+ DesEncrypt(challenge, ZPasswordHash + 7, response + 8);
+ DesEncrypt(challenge, ZPasswordHash + 14, response + 16);
+
+#if 0
+ dbglog("ChallengeResponse - response %.24B", response);
+#endif
+}
+
+
+#ifdef USE_CRYPT
+static void
+DesEncrypt(clear, key, cipher)
+ u_char *clear; /* IN 8 octets */
+ u_char *key; /* IN 7 octets */
+ u_char *cipher; /* OUT 8 octets */
+{
+ u_char des_key[8];
+ u_char crypt_key[66];
+ u_char des_input[66];
+
+ MakeKey(key, des_key);
+
+ Expand(des_key, crypt_key);
+ setkey(crypt_key);
+
+#if 0
+ CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %.8B", clear));
+#endif
+
+ Expand(clear, des_input);
+ encrypt(des_input, 0);
+ Collapse(des_input, cipher);
+
+#if 0
+ CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %.8B", cipher));
+#endif
+}
+
+#else /* USE_CRYPT */
+
+static void
+DesEncrypt(clear, key, cipher)
+ u_char *clear; /* IN 8 octets */
+ u_char *key; /* IN 7 octets */
+ u_char *cipher; /* OUT 8 octets */
+{
+ des_cblock des_key;
+ des_key_schedule key_schedule;
+
+ MakeKey(key, des_key);
+
+ des_set_key(&des_key, key_schedule);
+
+#if 0
+ CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %.8B", clear));
+#endif
+
+ des_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher, key_schedule, 1);
+
+#if 0
+ CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %.8B", cipher));
+#endif
+}
+
+#endif /* USE_CRYPT */
+
+
+static u_char Get7Bits(input, startBit)
+ u_char *input;
+ int startBit;
+{
+ register unsigned int word;
+
+ word = (unsigned)input[startBit / 8] << 8;
+ word |= (unsigned)input[startBit / 8 + 1];
+
+ word >>= 15 - (startBit % 8 + 7);
+
+ return word & 0xFE;
+}
+
+#ifdef USE_CRYPT
+
+/* in == 8-byte string (expanded version of the 56-bit key)
+ * out == 64-byte string where each byte is either 1 or 0
+ * Note that the low-order "bit" is always ignored by by setkey()
+ */
+static void Expand(in, out)
+ u_char *in;
+ u_char *out;
+{
+ int j, c;
+ int i;
+
+ for(i = 0; i < 64; in++){
+ c = *in;
+ for(j = 7; j >= 0; j--)
+ *out++ = (c >> j) & 01;
+ i += 8;
+ }
+}
+
+/* The inverse of Expand
+ */
+static void Collapse(in, out)
+ u_char *in;
+ u_char *out;
+{
+ int j;
+ int i;
+ unsigned int c;
+
+ for (i = 0; i < 64; i += 8, out++) {
+ c = 0;
+ for (j = 7; j >= 0; j--, in++)
+ c |= *in << j;
+ *out = c & 0xff;
+ }
+}
+#endif
+
+static void MakeKey(key, des_key)
+ u_char *key; /* IN 56 bit DES key missing parity bits */
+ u_char *des_key; /* OUT 64 bit DES key with parity bits added */
+{
+ des_key[0] = Get7Bits(key, 0);
+ des_key[1] = Get7Bits(key, 7);
+ des_key[2] = Get7Bits(key, 14);
+ des_key[3] = Get7Bits(key, 21);
+ des_key[4] = Get7Bits(key, 28);
+ des_key[5] = Get7Bits(key, 35);
+ des_key[6] = Get7Bits(key, 42);
+ des_key[7] = Get7Bits(key, 49);
+
+#ifndef USE_CRYPT
+ des_set_odd_parity((des_cblock *)des_key);
+#endif
+
+#if 0
+ CHAPDEBUG((LOG_INFO, "MakeKey: 56-bit input : %.7B", key));
+ CHAPDEBUG((LOG_INFO, "MakeKey: 64-bit output: %.8B", des_key));
+#endif
+}
+
+static void
+ChapMS_NT(rchallenge, rchallenge_len, secret, secret_len, response)
+ char *rchallenge;
+ int rchallenge_len;
+ char *secret;
+ int secret_len;
+ MS_ChapResponse *response;
+{
+ int i;
+#ifdef __NetBSD__
+ /* NetBSD uses the libc md4 routines which take bytes instead of bits */
+ int mdlen = secret_len * 2;
+#else
+ int mdlen = secret_len * 2 * 8;
+#endif
+ MD4_CTX md4Context;
+ u_char hash[MD4_SIGNATURE_SIZE];
+ u_char unicodePassword[MAX_NT_PASSWORD * 2];
+
+ /* Initialize the Unicode version of the secret (== password). */
+ /* This implicitly supports 8-bit ISO8859/1 characters. */
+ BZERO(unicodePassword, sizeof(unicodePassword));
+ for (i = 0; i < secret_len; i++)
+ unicodePassword[i * 2] = (u_char)secret[i];
+
+ MD4Init(&md4Context);
+ MD4Update(&md4Context, unicodePassword, mdlen);
+
+ MD4Final(hash, &md4Context); /* Tell MD4 we're done */
+
+ ChallengeResponse(rchallenge, hash, response->NTResp);
+}
+
+#ifdef MSLANMAN
+static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */
+
+static void
+ChapMS_LANMan(rchallenge, rchallenge_len, secret, secret_len, response)
+ char *rchallenge;
+ int rchallenge_len;
+ char *secret;
+ int secret_len;
+ MS_ChapResponse *response;
+{
+ int i;
+ u_char UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */
+ u_char PasswordHash[MD4_SIGNATURE_SIZE];
+
+ /* LANMan password is case insensitive */
+ BZERO(UcasePassword, sizeof(UcasePassword));
+ for (i = 0; i < secret_len; i++)
+ UcasePassword[i] = (u_char)toupper(secret[i]);
+ DesEncrypt( StdText, UcasePassword + 0, PasswordHash + 0 );
+ DesEncrypt( StdText, UcasePassword + 7, PasswordHash + 8 );
+ ChallengeResponse(rchallenge, PasswordHash, response->LANManResp);
+}
+#endif
+
+void
+ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len)
+ chap_state *cstate;
+ char *rchallenge;
+ int rchallenge_len;
+ char *secret;
+ int secret_len;
+{
+ MS_ChapResponse response;
+
+#if 0
+ CHAPDEBUG((LOG_INFO, "ChapMS: secret is '%.*s'", secret_len, secret));
+#endif
+ BZERO(&response, sizeof(response));
+
+ /* Calculate both always */
+ ChapMS_NT(rchallenge, rchallenge_len, secret, secret_len, &response);
+
+#ifdef MSLANMAN
+ ChapMS_LANMan(rchallenge, rchallenge_len, secret, secret_len, &response);
+
+ /* prefered method is set by option */
+ response.UseNT = !ms_lanman;
+#else
+ response.UseNT = 1;
+#endif
+
+ BCOPY(&response, cstate->response, MS_CHAP_RESPONSE_LEN);
+ cstate->resp_length = MS_CHAP_RESPONSE_LEN;
+}
+
+#endif /* CHAPMS */
diff --git a/cpukit/pppd/chap_ms.h b/cpukit/pppd/chap_ms.h
new file mode 100644
index 0000000000..fad2755c86
--- /dev/null
+++ b/cpukit/pppd/chap_ms.h
@@ -0,0 +1,33 @@
+/*
+ * chap.h - Challenge Handshake Authentication Protocol definitions.
+ *
+ * Copyright (c) 1995 Eric Rosenquist, Strata Software Limited.
+ * http://www.strataware.com/
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Eric Rosenquist. 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * $Id$
+ */
+
+#ifndef __CHAPMS_INCLUDE__
+
+#define MD4_SIGNATURE_SIZE 16 /* 16 bytes in a MD4 message digest */
+#define MAX_NT_PASSWORD 256 /* Maximum number of (Unicode) chars in an NT password */
+
+void ChapMS __P((chap_state *, char *, int, char *, int));
+
+#define __CHAPMS_INCLUDE__
+#endif /* __CHAPMS_INCLUDE__ */
diff --git a/cpukit/pppd/chat.c b/cpukit/pppd/chat.c
new file mode 100644
index 0000000000..6623004d35
--- /dev/null
+++ b/cpukit/pppd/chat.c
@@ -0,0 +1,857 @@
+/*
+ * Chat -- a program for automatic session establishment (i.e. dial
+ * the phone and log in).
+ *
+ * Standard termination codes:
+ * 0 - successful completion of the script
+ * 1 - invalid argument, expect string too large, etc.
+ * 2 - error on an I/O operation or fatal error condition.
+ * 3 - timeout waiting for a simple string.
+ * 4 - the first string declared as "ABORT"
+ * 5 - the second string declared as "ABORT"
+ * 6 - ... and so on for successive ABORT strings.
+ *
+ * This software is in the public domain.
+ *
+ * -----------------
+ * 22-May-99 added environment substitutuion, enabled with -E switch.
+ * Andreas Arens <andras@cityweb.de>.
+ *
+ * 12-May-99 added a feature to read data to be sent from a file,
+ * if the send string starts with @. Idea from gpk <gpk@onramp.net>.
+ *
+ * added -T and -U option and \T and \U substitution to pass a phone
+ * number into chat script. Two are needed for some ISDN TA applications.
+ * Keith Dart <kdart@cisco.com>
+ *
+ *
+ * Added SAY keyword to send output to stderr.
+ * This allows to turn ECHO OFF and to output specific, user selected,
+ * text to give progress messages. This best works when stderr
+ * exists (i.e.: pppd in nodetach mode).
+ *
+ * Added HANGUP directives to allow for us to be called
+ * back. When HANGUP is set to NO, chat will not hangup at HUP signal.
+ * We rely on timeouts in that case.
+ *
+ * Added CLR_ABORT to clear previously set ABORT string. This has been
+ * dictated by the HANGUP above as "NO CARRIER" (for example) must be
+ * an ABORT condition until we know the other host is going to close
+ * the connection for call back. As soon as we have completed the
+ * first stage of the call back sequence, "NO CARRIER" is a valid, non
+ * fatal string. As soon as we got called back (probably get "CONNECT"),
+ * we should re-arm the ABORT "NO CARRIER". Hence the CLR_ABORT command.
+ * Note that CLR_ABORT packs the abort_strings[] array so that we do not
+ * have unused entries not being reclaimed.
+ *
+ * In the same vein as above, added CLR_REPORT keyword.
+ *
+ * Allow for comments. Line starting with '#' are comments and are
+ * ignored. If a '#' is to be expected as the first character, the
+ * expect string must be quoted.
+ *
+ *
+ * Francis Demierre <Francis@SwissMail.Com>
+ * Thu May 15 17:15:40 MET DST 1997
+ *
+ *
+ * Added -r "report file" switch & REPORT keyword.
+ * Robert Geer <bgeer@xmission.com>
+ *
+ * Added -s "use stderr" and -S "don't use syslog" switches.
+ * June 18, 1997
+ * Karl O. Pinc <kop@meme.com>
+ *
+ *
+ * Added -e "echo" switch & ECHO keyword
+ * Dick Streefland <dicks@tasking.nl>
+ *
+ *
+ * Considerable updates and modifications by
+ * Al Longyear <longyear@pobox.com>
+ * Paul Mackerras <paulus@cs.anu.edu.au>
+ *
+ *
+ * The original author is:
+ *
+ * Karl Fox <karl@MorningStar.Com>
+ * Morning Star Technologies, Inc.
+ * 1760 Zollinger Road
+ * Columbus, OH 43221
+ * (614)451-1883
+ *
+ */
+
+/* $Id$ */
+
+/*
+ Fixes and some Changes by Wilfried Busalski Lancier-Monitoring GmbH Germany
+ wilfried.busalski@muenster.de
+
+ Fixes: put_string() Free memory allocated by clean()
+ get_string() Free memory allocated by clean()
+ chat_main() Will Distroy's no more the chat-script
+ getnextcommand() sepatator changed to '@'
+*/
+
+#include <stdio.h>
+#include <ctype.h>
+#include <time.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <syslog.h>
+#include <termios.h>
+#include "pppd.h"
+
+#undef TERMIOS
+#define TERMIOS
+
+
+#define STR_LEN 1024
+char temp2[STR_LEN];
+
+#ifndef SIGTYPE
+#define SIGTYPE void
+#endif
+
+#undef __P
+#undef __V
+
+#ifdef __STDC__
+#include <stdarg.h>
+#define __V(x) x
+#define __P(x) x
+#else
+#include <varargs.h>
+#define __V(x) (va_alist) va_dcl
+#define __P(x) ()
+#define const
+#endif
+
+#ifndef O_NONBLOCK
+#define O_NONBLOCK O_NDELAY
+#endif
+
+
+/*************** Micro getopt() *********************************************/
+#define OPTION(c,v) (_O&2&&**v?*(*v)++:!c||_O&4?0:(!(_O&1)&& \
+ (--c,++v),_O=4,c&&**v=='-'&&v[0][1]?*++*v=='-'\
+ &&!v[0][1]?(--c,++v,0):(_O=2,*(*v)++):0))
+#define OPTARG(c,v) (_O&2?**v||(++v,--c)?(_O=1,--c,*v++): \
+ (_O=4,(char*)0):(char*)0)
+#define OPTONLYARG(c,v) (_O&2&&**v?(_O=1,--c,*v++):(char*)0)
+#define ARG(c,v) (c?(--c,*v++):(char*)0)
+
+#if 0
+static int _O = 0; /* Internal state */
+#endif
+/*************** Micro getopt() *********************************************/
+
+#define MAX_ABORTS 16
+#define MAX_REPORTS 16
+#define DEFAULT_CHAT_TIMEOUT 45
+#define MAX_TIMEOUTS 10
+
+static int echo = 0;
+static int quiet = 0;
+static int use_env = 0;
+static int exit_code = 0;
+static char *phone_num = (char *) 0;
+static char *phone_num2 = (char *) 0;
+static int ttyfd;
+static int timeout = DEFAULT_CHAT_TIMEOUT;
+
+#ifdef TERMIOS
+#define term_parms struct termios
+#define get_term_param(param) tcgetattr(0, param)
+#define set_term_param(param) tcsetattr(0, TCSANOW, param)
+struct termios saved_tty_parameters;
+#endif
+
+char *fail_reason = (char *)0;
+char fail_buffer[50];
+char *abort_string[MAX_ABORTS]={"BUSY","NO DIALTONE","NO CARRIER","NO ANSWER","RING\r\nRING"};
+int n_aborts = 5;
+int abort_next = 0, timeout_next = 0, echo_next = 0;
+int clear_abort_next = 0;
+
+char *report_string[MAX_REPORTS] ;
+char report_buffer[50] ;
+int n_reports = 0, report_next = 0, report_gathering = 0 ;
+int clear_report_next = 0;
+
+int say_next = 0, hup_next = 0;
+
+void *dup_mem __P((void *b, size_t c));
+void *copy_of __P((char *s));
+void break_sequence __P((void));
+static int get_string __P((register char *string));
+static int put_string __P((register char *s));
+static int write_char __P((int c));
+static int put_char __P((int c));
+static int get_char __P((void));
+void chat_send __P((register char *s));
+/* static char *character __P((int c)); */
+void chat_expect __P((register char *s));
+static char *clean __P((register char *s, int sending));
+char *expect_strtok __P((char *, char *));
+int chatmain __P((int, int, char *));
+
+
+void *dup_mem(b, c)
+void *b;
+size_t c;
+{
+ void *ans = malloc (c);
+ if (!ans)
+ return NULL;
+
+ memcpy(ans, b, c);
+ return ans;
+}
+
+void *copy_of (s)
+char *s;
+{
+ return dup_mem(s, strlen (s) + 1);
+}
+
+char *getnextcommand(char *string,char *buff)
+{
+ char *token;
+ int len;
+
+ token=strchr(string,'@');
+ if (token==NULL){
+ return NULL;
+ }
+ len=token-string;
+ if(len > 78 ){
+ len=78;
+ }
+ memcpy(buff,string,len);
+ buff[len]=0;
+ return(token+1);
+}
+
+int chatmain(int fd, int mode, char *pScript)
+{
+ char arg[80];
+ char *script;
+
+ /* initialize exit code */
+ exit_code = 0;
+ ttyfd = fd;
+
+ script=pScript;
+
+ if ( debug ) {
+ dbglog("chat_main: %s\n", script);
+ }
+
+ /* get first expect string */
+ script = getnextcommand(script,arg);
+ while (( script != NULL ) && ( exit_code == 0 )) {
+ /* process the expect string */
+ chat_expect(arg);
+ if ( exit_code == 0 ) {
+ /* get the next send string */
+ script = getnextcommand(script,arg);
+ if ( script != NULL ) {
+ /* process the send string */
+ chat_send(arg);
+
+ /* get the next expect string */
+ script = getnextcommand(script,arg);
+ }
+ }
+ }
+ ttyfd = (int)-1;
+
+ return ( exit_code );
+}
+
+void break_sequence()
+{
+ tcsendbreak(ttyfd, 0);
+}
+
+/*
+ * 'Clean up' this string.
+ */
+static char *clean(s, sending)
+register char *s;
+int sending; /* set to 1 when sending (putting) this string. */
+{
+ char temp[STR_LEN], env_str[STR_LEN], cur_chr;
+ register char *s1, *phchar;
+ int add_return = sending;
+#define isoctal(chr) (((chr) >= '0') && ((chr) <= '7'))
+#define isalnumx(chr) ((((chr) >= '0') && ((chr) <= '9')) \
+ || (((chr) >= 'a') && ((chr) <= 'z')) \
+ || (((chr) >= 'A') && ((chr) <= 'Z')) \
+ || (chr) == '_')
+
+ s1 = temp;
+ while (*s) {
+ cur_chr = *s++;
+ if (cur_chr == '^') {
+ cur_chr = *s++;
+ if (cur_chr == '\0') {
+ *s1++ = '^';
+ break;
+ }
+ cur_chr &= 0x1F;
+ if (cur_chr != 0) {
+ *s1++ = cur_chr;
+ }
+ continue;
+ }
+
+ if (use_env && cur_chr == '$') { /* ARI */
+ phchar = env_str;
+ while (isalnumx(*s))
+ *phchar++ = *s++;
+ *phchar = '\0';
+ phchar = getenv(env_str);
+ if (phchar)
+ while (*phchar)
+ *s1++ = *phchar++;
+ continue;
+ }
+
+ if (cur_chr != '\\') {
+ *s1++ = cur_chr;
+ continue;
+ }
+
+ cur_chr = *s++;
+ if (cur_chr == '\0') {
+ if (sending) {
+ *s1++ = '\\';
+ *s1++ = '\\';
+ }
+ break;
+ }
+
+ switch (cur_chr) {
+ case 'b':
+ *s1++ = '\b';
+ break;
+
+ case 'c':
+ if (sending && *s == '\0')
+ add_return = 0;
+ else
+ *s1++ = cur_chr;
+ break;
+
+ case '\\':
+ case 'K':
+ case 'p':
+ case 'd':
+ if (sending)
+ *s1++ = '\\';
+ *s1++ = cur_chr;
+ break;
+
+ case 'T':
+ if (sending && phone_num) {
+ for (phchar = phone_num; *phchar != '\0'; phchar++)
+ *s1++ = *phchar;
+ }
+ else {
+ *s1++ = '\\';
+ *s1++ = 'T';
+ }
+ break;
+
+ case 'U':
+ if (sending && phone_num2) {
+ for (phchar = phone_num2; *phchar != '\0'; phchar++)
+ *s1++ = *phchar;
+ }
+ else {
+ *s1++ = '\\';
+ *s1++ = 'U';
+ }
+ break;
+
+ case 'q':
+ quiet = 1;
+ break;
+
+ case 'r':
+ *s1++ = '\r';
+ break;
+
+ case 'n':
+ *s1++ = '\n';
+ break;
+
+ case 's':
+ *s1++ = ' ';
+ break;
+
+ case 't':
+ *s1++ = '\t';
+ break;
+
+ case 'N':
+ if (sending) {
+ *s1++ = '\\';
+ *s1++ = '\0';
+ }
+ else
+ *s1++ = 'N';
+ break;
+
+ case '$': /* ARI */
+ if (use_env) {
+ *s1++ = cur_chr;
+ break;
+ }
+ /* FALL THROUGH */
+
+ default:
+ if (isoctal (cur_chr)) {
+ cur_chr &= 0x07;
+ if (isoctal (*s)) {
+ cur_chr <<= 3;
+ cur_chr |= *s++ - '0';
+ if (isoctal (*s)) {
+ cur_chr <<= 3;
+ cur_chr |= *s++ - '0';
+ }
+ }
+
+ if (cur_chr != 0 || sending) {
+ if (sending && (cur_chr == '\\' || cur_chr == 0))
+ *s1++ = '\\';
+ *s1++ = cur_chr;
+ }
+ break;
+ }
+
+ if (sending)
+ *s1++ = '\\';
+ *s1++ = cur_chr;
+ break;
+ }
+ }
+
+ if (add_return)
+ *s1++ = '\r';
+
+ *s1++ = '\0'; /* guarantee closure */
+ *s1++ = '\0'; /* terminate the string */
+ return dup_mem (temp, (size_t) (s1 - temp)); /* may have embedded nuls */
+}
+
+/*
+ * A modified version of 'strtok'. This version skips \ sequences.
+ */
+char *expect_strtok (s, term)
+ char *s, *term;
+{
+ static char *str = "";
+ int escape_flag = 0;
+ char *result;
+
+/*
+ * If a string was specified then do initial processing.
+ */
+ if (s)
+ str = s;
+
+/*
+ * If this is the escape flag then reset it and ignore the character.
+ */
+ if (*str)
+ result = str;
+ else
+ result = (char *) 0;
+
+ while (*str) {
+ if (escape_flag) {
+ escape_flag = 0;
+ ++str;
+ continue;
+ }
+
+ if (*str == '\\') {
+ ++str;
+ escape_flag = 1;
+ continue;
+ }
+
+/*
+ * If this is not in the termination string, continue.
+ */
+ if (strchr (term, *str) == (char *) 0) {
+ ++str;
+ continue;
+ }
+
+/*
+ * This is the terminator. Mark the end of the string and stop.
+ */
+ *str++ = '\0';
+ break;
+ }
+ return (result);
+}
+
+/*
+ * Process the expect string
+ */
+void chat_expect (s)
+char *s;
+{
+ char *expect;
+ char *reply;
+
+ if (strcmp(s, "HANGUP") == 0) {
+ ++hup_next;
+ return;
+ }
+
+ if (strcmp(s, "ABORT") == 0) {
+ ++abort_next;
+ return;
+ }
+
+ if (strcmp(s, "CLR_ABORT") == 0) {
+ ++clear_abort_next;
+ return;
+ }
+
+ if (strcmp(s, "REPORT") == 0) {
+ ++report_next;
+ return;
+ }
+
+ if (strcmp(s, "CLR_REPORT") == 0) {
+ ++clear_report_next;
+ return;
+ }
+
+ if (strcmp(s, "TIMEOUT") == 0) {
+ ++timeout_next;
+ return;
+ }
+
+ if (strcmp(s, "ECHO") == 0) {
+ ++echo_next;
+ return;
+ }
+
+ if (strcmp(s, "SAY") == 0) {
+ ++say_next;
+ return;
+ }
+
+/*
+ * Fetch the expect and reply string.
+ */
+ for (;;) {
+ expect = expect_strtok (s, "-");
+ s = (char *) 0;
+
+ if (expect == (char *) 0)
+ return;
+
+ reply = expect_strtok (s, "-");
+
+/*
+ * Handle the expect string. If successful then exit.
+ */
+ if (get_string (expect))
+ return;
+
+/*
+ * If there is a sub-reply string then send it. Otherwise any condition
+ * is terminal.
+ */
+ if (reply == (char *) 0 || exit_code != 3)
+ break;
+
+ chat_send (reply);
+ }
+}
+
+#if 0
+/*
+ * Translate the input character to the appropriate string for printing
+ * the data.
+ */
+
+static char *character(c)
+int c;
+{
+ static char string[10];
+ char *meta;
+
+ meta = (c & 0x80) ? "M-" : "";
+ c &= 0x7F;
+
+ if (c < 32)
+ sprintf(string, "%s^%c", meta, (int)c + '@');
+ else if (c == 127)
+ sprintf(string, "%s^?", meta);
+ else
+ sprintf(string, "%s%c", meta, c);
+
+ return (string);
+}
+#endif
+
+/*
+ * process the reply string
+ */
+void chat_send (s)
+register char *s;
+{
+/* char file_data[STR_LEN]; */
+
+ if (say_next) {
+ say_next = 0;
+ s = clean(s, 1);
+ write(2, s, strlen(s));
+ free(s);
+ return;
+ }
+
+ if (hup_next) {
+ hup_next = 0;
+ return;
+ }
+
+ if (echo_next) {
+ echo_next = 0;
+ echo = (strcmp(s, "ON") == 0);
+ return;
+ }
+
+ if (abort_next) {
+ char *s1;
+
+ abort_next = 0;
+ if ( n_aborts < MAX_ABORTS ) {
+ s1 = clean(s, 0);
+ if (( strlen(s1) <= strlen(s) ) && ( strlen(s1) < sizeof(fail_buffer))) {
+ abort_string[n_aborts++] = s1;
+ }
+ free(s1);
+ }
+ return;
+ }
+
+ if (clear_abort_next) {
+ clear_abort_next = 0;
+ return;
+ }
+
+ if (report_next) {
+ report_next = 0;
+ return;
+ }
+
+ if (clear_report_next) {
+ clear_report_next = 0;
+ return;
+ }
+
+ if (timeout_next) {
+ timeout_next = 0;
+ timeout = atoi(s);
+
+ if (timeout <= 0){
+ timeout = DEFAULT_CHAT_TIMEOUT;
+ }
+ return;
+ }
+
+ if (strcmp(s, "EOT") == 0){
+ s = "^D\\c";
+ }
+ else{
+ if (strcmp(s, "BREAK") == 0){
+ s = "\\K\\c";
+ }
+
+ if (!put_string(s)) {
+ exit_code = 2;
+ }
+ }
+}
+
+static int get_char()
+{
+ int status;
+ char c;
+ int tries=MAX_TIMEOUTS;
+
+ while(tries)
+ {
+ status = read(ttyfd, &c, 1);
+ switch (status) {
+ case 1:
+ return ((int)c & 0x7F);
+ default:
+ tries--;
+ }
+ }
+ return -1;
+}
+
+static int put_char(c)
+int c;
+{
+ char ch = c;
+
+ return(write(ttyfd, &ch, 1));
+}
+
+static int write_char (c)
+int c;
+{
+ if (put_char(c) < 1) {
+ return (0);
+ }
+ return (1);
+}
+
+static int put_string (s)
+register char *s;
+{
+ char *out,*free_ptr=0;
+
+ quiet = 0;
+ out = free_ptr = clean(s, 1);
+ while (*out) {
+ register char c = *out++;
+
+ if (c != '\\') {
+ if (!write_char (c)){
+ free(free_ptr);
+ return 0;
+ }
+ continue;
+ }
+
+ c = *out++;
+
+ switch (c) {
+ case 'd':
+ sleep(1);
+ break;
+
+ case 'K':
+ break_sequence();
+ break;
+
+ case 'p':
+#if 0 /* FIXME!!! */
+ usleep(10000); /* 1/100th of a second (arg is microseconds) */
+#else
+ sleep(1);
+#endif
+ break;
+
+ default:
+ if (!write_char (c)){
+ free(free_ptr);
+ return 0;
+ }
+ break;
+ }
+ }
+ free(free_ptr);
+
+ return (1);
+}
+
+/*
+ * 'Wait for' this string to appear on this file descriptor.
+ */
+static int get_string(in_string)
+register char *in_string;
+{
+ int c, len, minlen;
+ register char *s = temp2, *end = s + STR_LEN;
+ char *logged = temp2;
+ char *string=0;
+ struct termios tios;
+
+ memset(temp2, 0, sizeof(temp2));
+
+ tcgetattr(ttyfd, &tios);
+ tios.c_cc[VMIN] = 0;
+ tios.c_cc[VTIME] = timeout*10/MAX_TIMEOUTS;
+ tcsetattr(ttyfd, TCSANOW, &tios);
+
+ string = clean(in_string, 0);
+ len = strlen(string);
+ minlen = (len > sizeof(fail_buffer)? len: sizeof(fail_buffer)) - 1;
+
+ if (len > STR_LEN) {
+ exit_code = 1;
+ free(string);
+ return 0;
+ }
+
+ if (len == 0) {
+ return (1);
+ }
+
+ while ( (c = get_char()) >= 0) {
+ int n, abort_len;
+
+ if(c == '\n' || c == '\r'){
+ s = temp2;
+ *s=0;
+ }
+ else{
+ *s++ = c;
+ *s=0;
+ }
+
+ if (s - temp2 >= len &&
+ c == string[len - 1] &&
+ strncmp(s - len, string, len) == 0) {
+ free(string);
+ return (1);
+ }
+
+ for (n = 0; n < n_aborts; ++n) {
+ if (s - temp2 >= (abort_len = strlen(abort_string[n])) &&
+ strncmp(s - abort_len, abort_string[n], abort_len) == 0) {
+
+ exit_code = n + 4;
+ strcpy(fail_reason = fail_buffer, abort_string[n]);
+ free(string);
+ return (0);
+ }
+ }
+
+ if (s >= end) {
+ if (logged < s - minlen) {
+ logged = s;
+ }
+ s -= minlen;
+ memmove(temp2, s, minlen);
+ logged = temp2 + (logged - s);
+ s = temp2 + minlen;
+ }
+ }
+
+ exit_code = 3;
+ free(string);
+ return (0);
+}
diff --git a/cpukit/pppd/demand.c b/cpukit/pppd/demand.c
new file mode 100644
index 0000000000..0b807575c2
--- /dev/null
+++ b/cpukit/pppd/demand.c
@@ -0,0 +1,347 @@
+/*
+ * demand.c - Support routines for demand-dialling.
+ *
+ * Copyright (c) 1993 The Australian National University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the Australian National University. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#define RCSID "$Id$";
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#ifdef PPP_FILTER
+#include <net/if.h>
+#include <net/bpf.h>
+#include <pcap.h>
+#endif
+
+#include "pppd.h"
+#include "fsm.h"
+#include "ipcp.h"
+#include "lcp.h"
+
+static const char rcsid[] = RCSID;
+
+static char *frame;
+static int framelen;
+static int framemax;
+static int escape_flag;
+static int flush_flag;
+static int fcs;
+
+struct packet {
+ int length;
+ struct packet *next;
+ unsigned char data[1];
+};
+
+struct packet *pend_q;
+struct packet *pend_qtail;
+
+static int active_packet __P((unsigned char *, int));
+
+/*
+ * demand_conf - configure the interface for doing dial-on-demand.
+ */
+void
+demand_conf()
+{
+ int i;
+ struct protent *protp;
+
+/* framemax = lcp_allowoptions[0].mru;
+ if (framemax < PPP_MRU) */
+ framemax = PPP_MRU;
+ framemax += PPP_HDRLEN + PPP_FCSLEN;
+ frame = malloc(framemax);
+ if (frame == NULL)
+ novm("demand frame");
+ framelen = 0;
+ pend_q = NULL;
+ escape_flag = 0;
+ flush_flag = 0;
+ fcs = PPP_INITFCS;
+
+ ppp_send_config(0, PPP_MRU, (u_int32_t) 0, 0, 0);
+ ppp_recv_config(0, PPP_MRU, (u_int32_t) 0, 0, 0);
+
+#ifdef PPP_FILTER
+ set_filters(&pass_filter, &active_filter);
+#endif
+
+ /*
+ * Call the demand_conf procedure for each protocol that's got one.
+ */
+ for (i = 0; (protp = protocols[i]) != NULL; ++i)
+ if (protp->enabled_flag && protp->demand_conf != NULL)
+ if (!((*protp->demand_conf)(0)))
+ die(1);
+}
+
+
+/*
+ * demand_block - set each network protocol to block further packets.
+ */
+void
+demand_block()
+{
+ int i;
+ struct protent *protp;
+
+ for (i = 0; (protp = protocols[i]) != NULL; ++i)
+ if (protp->enabled_flag && protp->demand_conf != NULL)
+ sifnpmode(0, protp->protocol & ~0x8000, NPMODE_QUEUE);
+ get_loop_output();
+}
+
+/*
+ * demand_discard - set each network protocol to discard packets
+ * with an error.
+ */
+void
+demand_discard()
+{
+ struct packet *pkt, *nextpkt;
+ int i;
+ struct protent *protp;
+
+ for (i = 0; (protp = protocols[i]) != NULL; ++i)
+ if (protp->enabled_flag && protp->demand_conf != NULL)
+ sifnpmode(0, protp->protocol & ~0x8000, NPMODE_ERROR);
+ get_loop_output();
+
+ /* discard all saved packets */
+ for (pkt = pend_q; pkt != NULL; pkt = nextpkt) {
+ nextpkt = pkt->next;
+ free(pkt);
+ }
+ pend_q = NULL;
+ framelen = 0;
+ flush_flag = 0;
+ escape_flag = 0;
+ fcs = PPP_INITFCS;
+}
+
+/*
+ * demand_unblock - set each enabled network protocol to pass packets.
+ */
+void
+demand_unblock()
+{
+ int i;
+ struct protent *protp;
+
+ for (i = 0; (protp = protocols[i]) != NULL; ++i)
+ if (protp->enabled_flag && protp->demand_conf != NULL)
+ sifnpmode(0, protp->protocol & ~0x8000, NPMODE_PASS);
+}
+
+/*
+ * FCS lookup table as calculated by genfcstab.
+ */
+static u_short fcstab[256] = {
+ 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
+ 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
+ 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
+ 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
+ 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
+ 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
+ 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
+ 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
+ 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
+ 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
+ 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
+ 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
+ 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
+ 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
+ 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
+ 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
+ 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
+ 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
+ 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
+ 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
+ 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
+ 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
+ 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
+ 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
+ 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
+ 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
+ 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
+ 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
+ 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
+ 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
+ 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
+ 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
+};
+
+/*
+ * loop_chars - process characters received from the loopback.
+ * Calls loop_frame when a complete frame has been accumulated.
+ * Return value is 1 if we need to bring up the link, 0 otherwise.
+ */
+int
+loop_chars(p, n)
+ unsigned char *p;
+ int n;
+{
+ int c, rv;
+
+ rv = 0;
+ for (; n > 0; --n) {
+ c = *p++;
+ if (c == PPP_FLAG) {
+ if (!escape_flag && !flush_flag
+ && framelen > 2 && fcs == PPP_GOODFCS) {
+ framelen -= 2;
+ if (loop_frame(frame, framelen))
+ rv = 1;
+ }
+ framelen = 0;
+ flush_flag = 0;
+ escape_flag = 0;
+ fcs = PPP_INITFCS;
+ continue;
+ }
+ if (flush_flag)
+ continue;
+ if (escape_flag) {
+ c ^= PPP_TRANS;
+ escape_flag = 0;
+ } else if (c == PPP_ESCAPE) {
+ escape_flag = 1;
+ continue;
+ }
+ if (framelen >= framemax) {
+ flush_flag = 1;
+ continue;
+ }
+ frame[framelen++] = c;
+ fcs = PPP_FCS(fcs, c);
+ }
+ return rv;
+}
+
+/*
+ * loop_frame - given a frame obtained from the loopback,
+ * decide whether to bring up the link or not, and, if we want
+ * to transmit this frame later, put it on the pending queue.
+ * Return value is 1 if we need to bring up the link, 0 otherwise.
+ * We assume that the kernel driver has already applied the
+ * pass_filter, so we won't get packets it rejected.
+ * We apply the active_filter to see if we want this packet to
+ * bring up the link.
+ */
+int
+loop_frame(frame, len)
+ unsigned char *frame;
+ int len;
+{
+ struct packet *pkt;
+
+ /* dbglog("from loop: %P", frame, len); */
+ if (len < PPP_HDRLEN)
+ return 0;
+ if ((PPP_PROTOCOL(frame) & 0x8000) != 0)
+ return 0; /* shouldn't get any of these anyway */
+ if (!active_packet(frame, len))
+ return 0;
+
+ pkt = (struct packet *) malloc(sizeof(struct packet) + len);
+ if (pkt != NULL) {
+ pkt->length = len;
+ pkt->next = NULL;
+ memcpy(pkt->data, frame, len);
+ if (pend_q == NULL)
+ pend_q = pkt;
+ else
+ pend_qtail->next = pkt;
+ pend_qtail = pkt;
+ }
+ return 1;
+}
+
+/*
+ * demand_rexmit - Resend all those frames which we got via the
+ * loopback, now that the real serial link is up.
+ */
+void
+demand_rexmit(proto)
+ int proto;
+{
+ struct packet *pkt, *prev, *nextpkt;
+
+ prev = NULL;
+ pkt = pend_q;
+ pend_q = NULL;
+ for (; pkt != NULL; pkt = nextpkt) {
+ nextpkt = pkt->next;
+ if (PPP_PROTOCOL(pkt->data) == proto) {
+ output(0, pkt->data, pkt->length);
+ free(pkt);
+ } else {
+ if (prev == NULL)
+ pend_q = pkt;
+ else
+ prev->next = pkt;
+ prev = pkt;
+ }
+ }
+ pend_qtail = prev;
+ if (prev != NULL)
+ prev->next = NULL;
+}
+
+/*
+ * Scan a packet to decide whether it is an "active" packet,
+ * that is, whether it is worth bringing up the link for.
+ */
+static int
+active_packet(p, len)
+ unsigned char *p;
+ int len;
+{
+ int proto, i;
+ struct protent *protp;
+
+ if (len < PPP_HDRLEN)
+ return 0;
+ proto = PPP_PROTOCOL(p);
+#ifdef PPP_FILTER
+ if (active_filter.bf_len != 0
+ && bpf_filter(active_filter.bf_insns, frame, len, len) == 0)
+ return 0;
+#endif
+ for (i = 0; (protp = protocols[i]) != NULL; ++i) {
+ if (protp->protocol < 0xC000 && (protp->protocol & ~0x8000) == proto) {
+ if (!protp->enabled_flag)
+ return 0;
+ if (protp->active_pkt == NULL)
+ return 1;
+ return (*protp->active_pkt)(p, len);
+ }
+ }
+ return 0; /* not a supported protocol !!?? */
+}
diff --git a/cpukit/pppd/example/Makefile-user b/cpukit/pppd/example/Makefile-user
new file mode 100644
index 0000000000..69cc8aab50
--- /dev/null
+++ b/cpukit/pppd/example/Makefile-user
@@ -0,0 +1,45 @@
+#
+# Makefile
+#
+
+#
+# RTEMS_MAKEFILE_PATH is typically set in an environment variable
+#
+
+EXEC=ppptest.exe
+PGM=${ARCH}/$(EXEC)
+
+# optional managers required
+MANAGERS=io event semaphore
+
+# C source names
+CSRCS = init.c pppdapp.c
+
+COBJS_ = $(CSRCS:.c=.o)
+COBJS = $(COBJS_:%=${ARCH}/%)
+
+# C++ source names
+CXXSRCS =
+CXXOBJS_ = $(CXXSRCS:.cc=.o)
+CXXOBJS = $(CXXOBJS_:%=${ARCH}/%)
+
+# AS source names
+ASSRCS =
+ASOBJS_ = $(ASSRCS:.s=.o)
+ASOBJS = $(ASOBJS_:%=${ARCH}/%)
+
+# Libraries
+LIBS = -lrtemsall -lc
+
+include $(RTEMS_MAKEFILE_PATH)/Makefile.inc
+
+include $(RTEMS_CUSTOM)
+include $(PROJECT_ROOT)/make/leaf.cfg
+
+OBJS= $(COBJS) $(CXXOBJS) $(ASOBJS)
+
+all: ${ARCH} $(PGM)
+
+$(PGM): $(OBJS)
+ $(make-exe)
+
diff --git a/cpukit/pppd/example/README b/cpukit/pppd/example/README
new file mode 100644
index 0000000000..677e00af33
--- /dev/null
+++ b/cpukit/pppd/example/README
@@ -0,0 +1,15 @@
+#
+# $Id$
+#
+
+This is an example user application using pppd. It is built using
+the RTEMS application Makefiles. The file Makefile-user should
+be renamed to Makefile or the -f option given to make. The file
+is renamed to avoid bootstrap -c removing it.
+
+The files ppp.conf and pppd.options are sample configuration files
+that have successfully used to make ppp connections over a null
+modem serial cable to a UNIX box. Please review the man pages
+for either the ppp or pppd applications to ensure they are configured
+correctly.
+
diff --git a/cpukit/pppd/example/init.c b/cpukit/pppd/example/init.c
new file mode 100644
index 0000000000..f35d195bf2
--- /dev/null
+++ b/cpukit/pppd/example/init.c
@@ -0,0 +1,24 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <rtems/rtems_bsdnet.h>
+#include <rtemspppd.h>
+
+#define CONFIGURE_INIT
+#include "system.h"
+#include "netconfig.h"
+
+
+extern int pppdapp_initialize(void);
+
+
+rtems_task Init(rtems_task_argument argument)
+{
+ /* initialize network */
+ rtems_bsdnet_initialize_network();
+ rtems_pppd_initialize();
+ pppdapp_initialize();
+
+ rtems_task_delete(RTEMS_SELF);
+}
diff --git a/cpukit/pppd/example/netconfig.h b/cpukit/pppd/example/netconfig.h
new file mode 100644
index 0000000000..3428288cd2
--- /dev/null
+++ b/cpukit/pppd/example/netconfig.h
@@ -0,0 +1,36 @@
+
+#ifndef NETCONFIG_H_
+#define NETCONFIG_H_
+
+#include <bsp.h>
+
+/* external function prototypes */
+extern int rtems_ppp_driver_attach(struct rtems_bsdnet_ifconfig *config, int attaching);
+
+/* Default network interface */
+static struct rtems_bsdnet_ifconfig netdriver_config = {
+ "ppp0", /* name */
+ rtems_ppp_driver_attach, /* attach function */
+ NULL, /* No more interfaces */
+ NULL, /* IP address */
+ NULL, /* IP net mask */
+ NULL, /* Driver supplies hardware address */
+ 0 /* Use default driver parameters */
+};
+
+/* Network configuration */
+struct rtems_bsdnet_config rtems_bsdnet_config = {
+ &netdriver_config,
+ NULL,
+ 30, /* Default network task priority */
+ (256*1024), /* Default mbuf capacity */
+ (512*1024), /* Default mbuf cluster capacity */
+ 0, /* Host name */
+ 0, /* Domain name */
+ 0, /* Gateway */
+ 0, /* Log host */
+ { 0 }, /* Name server(s) */
+ { 0 }, /* NTP server(s) */
+};
+
+#endif
diff --git a/cpukit/pppd/example/ppp.conf b/cpukit/pppd/example/ppp.conf
new file mode 100644
index 0000000000..094b1946a8
--- /dev/null
+++ b/cpukit/pppd/example/ppp.conf
@@ -0,0 +1,27 @@
+
+#
+# Example configuration file for setting up a ppp server
+# using a null-modem serial cable:
+#
+# Tested using ppp on OpenBSD 2.9
+# - just follow instructions in man page for accepting
+# ppp connections over the serial port
+# - if pap and/or chap is enabled, you must have a ppp.secret
+# file which will be used for user authentication
+# - found useful to turn on syslog for ppp
+#
+
+default:
+ set log Phase Chat LQM LCP IPCP CCP command
+ set device /dev/cua00
+ set speed 57600
+ set ctsrts on
+ set dial ""
+
+openbsd-server:
+ set timeout 0
+ set ifaddr 192.168.2.100 192.168.2.123
+ enable dns
+ allow users
+ enable chap
+ enable pap
diff --git a/cpukit/pppd/example/pppd.options b/cpukit/pppd/example/pppd.options
new file mode 100644
index 0000000000..c0706e6ec5
--- /dev/null
+++ b/cpukit/pppd/example/pppd.options
@@ -0,0 +1,9 @@
+/dev/tty00
+57600
+crtscts
+passive
+local
+noauth
+debug
+persist
+192.168.2.222:192.168.2.111
diff --git a/cpukit/pppd/example/pppdapp.c b/cpukit/pppd/example/pppdapp.c
new file mode 100644
index 0000000000..59e5029088
--- /dev/null
+++ b/cpukit/pppd/example/pppdapp.c
@@ -0,0 +1,146 @@
+
+#include <stdio.h>
+#include <rtemspppd.h>
+#include "system.h"
+
+
+/* define global variables */
+static unsigned int pppdapp_linkcount = 0;
+static rtems_id pppdapp_taskid;
+
+
+static void pppdapp_linkup_hook(void)
+{
+ pppdapp_linkcount++;
+ printf("PPP LINK UP [%d]\n", pppdapp_linkcount);
+}
+
+static void pppdapp_linkdown_hook(void)
+{
+ printf("PPP LINK DOWN [%d]\n", pppdapp_linkcount);
+}
+
+static void pppdapp_ipup_hook(void)
+{
+ /* send ipup signal to pppdapp task */
+ rtems_event_send(pppdapp_taskid, RTEMS_EVENT_10);
+}
+
+static void pppdapp_ipdown_hook(void)
+{
+ /* send ip down signal to pppdapp task */
+ rtems_event_send(pppdapp_taskid, RTEMS_EVENT_11);
+}
+
+static void pppdapp_setup(void)
+{
+ const char *pUser = "oscar";
+ const char *pPassword = "goldman";
+
+#undef USE_MODEM
+#ifdef USE_MODEM
+ const char *pTelephone = "5551234";
+ const char *pInitScript = "TIMEOUT@5@@AT@@OK@";
+ const char *pConnectScript = "TIMEOUT@90@@ATDT%s@CONNECT@@name:@%s@word:@%s@";
+ const char *pDisconnectScript = "TIMEOUT@5@@ATH0@@OK@";
+ char pConnect[128];
+
+ /* set the connect string */
+ sprintf(pConnect, pConnectScript, pTelephone, pUser, pPassword);
+
+ /* set pppd options for modem */
+ rtems_pppd_set_option("/dev/ttyS2", NULL);
+ rtems_pppd_set_option("57600", NULL);
+ rtems_pppd_set_option("crtscts", NULL);
+ rtems_pppd_set_option("modem", NULL);
+ rtems_pppd_set_option("noauth", NULL);
+ rtems_pppd_set_option("debug", NULL);
+ rtems_pppd_set_option("init", pInitScript);
+ rtems_pppd_set_option("connect", pConnect);
+ rtems_pppd_set_option("disconnect", pDisconnectScript);
+#else
+ /* set pppd options for null modem direct link serial cable */
+ rtems_pppd_set_option("/dev/ttyS1", NULL);
+ rtems_pppd_set_option("57600", NULL);
+ rtems_pppd_set_option("crtscts", NULL);
+ rtems_pppd_set_option("local", NULL);
+ rtems_pppd_set_option("noauth", NULL);
+ rtems_pppd_set_option("debug", NULL);
+ rtems_pppd_set_option("user", pUser);
+ rtems_pppd_set_option("password", pPassword);
+#endif
+
+ /* set up pppd hooks */
+ rtems_pppd_set_hook(RTEMS_PPPD_LINKUP_HOOK, pppdapp_linkup_hook);
+ rtems_pppd_set_hook(RTEMS_PPPD_LINKDOWN_HOOK, pppdapp_linkdown_hook);
+ rtems_pppd_set_hook(RTEMS_PPPD_IPUP_HOOK, pppdapp_ipup_hook);
+ rtems_pppd_set_hook(RTEMS_PPPD_IPDOWN_HOOK, pppdapp_ipdown_hook);
+}
+
+static rtems_task pppdapp(rtems_task_argument arg)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ rtems_interval tickspersecond = 0;
+ rtems_option options;
+ rtems_event_set in;
+ rtems_event_set out;
+
+ /* initialize ticks per second */
+ rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND, &tickspersecond);
+ if ( tickspersecond == 0 ) {
+ /* ensure value is greater than zero */
+ tickspersecond = 100;
+ }
+
+ /* initiate connection */
+ pppdapp_setup();
+ rtems_pppd_connect();
+
+ /* enter processing loop */
+ in = (RTEMS_EVENT_10 | RTEMS_EVENT_11);
+ options = (RTEMS_EVENT_ANY | RTEMS_WAIT);
+ while ( sc == RTEMS_SUCCESSFUL ) {
+ /* wait for the next event */
+ sc = rtems_event_receive(in, options, RTEMS_NO_TIMEOUT, &out);
+ if ( sc == RTEMS_SUCCESSFUL ) {
+ /* determine which event was sent */
+ if ( out & RTEMS_EVENT_10 ) {
+ /* ip up recived */
+ /* call disconnect function */
+ rtems_pppd_disconnect();
+ }
+ if ( out & RTEMS_EVENT_11 ) {
+ /* ip down recived */
+ /* sleep 10 seconds and call connect function */
+ rtems_task_wake_after(10*tickspersecond);
+ rtems_pppd_connect();
+ }
+ }
+ }
+
+ /* terminate myself */
+ rtems_task_delete(RTEMS_SELF);
+}
+
+int pppdapp_initialize(void)
+{
+ int iReturn = (int)-1;
+ rtems_status_code status;
+ rtems_name taskName;
+
+ taskName = rtems_build_name( 'p', 'a', 'p', 'p' );
+ status = rtems_task_create(taskName,
+ CONFIGURE_INIT_TASK_PRIORITY,
+ CONFIGURE_INIT_TASK_STACK_SIZE,
+ CONFIGURE_INIT_TASK_INITIAL_MODES,
+ RTEMS_DEFAULT_ATTRIBUTES,
+ &pppdapp_taskid);
+ if ( status == RTEMS_SUCCESSFUL ) {
+ status = rtems_task_start(pppdapp_taskid, pppdapp, 0);
+ if ( status == RTEMS_SUCCESSFUL ) {
+ iReturn = (int)0;
+ }
+ }
+
+ return ( iReturn );
+}
diff --git a/cpukit/pppd/example/system.h b/cpukit/pppd/example/system.h
new file mode 100644
index 0000000000..87678da1b6
--- /dev/null
+++ b/cpukit/pppd/example/system.h
@@ -0,0 +1,42 @@
+
+#ifndef SYSTEM_H
+#define SYSTEM_H
+
+#include <rtems.h>
+#include <tty_drv.h>
+
+/* functions */
+extern rtems_task Init(rtems_task_argument argument);
+
+#include <bsp.h>
+
+#define CONFIGURE_HAS_OWN_DEVICE_DRIVER_TABLE
+#ifdef CONFIGURE_INIT
+rtems_driver_address_table Device_drivers[5] = {
+ CONSOLE_DRIVER_TABLE_ENTRY,
+ CLOCK_DRIVER_TABLE_ENTRY,
+ TTY1_DRIVER_TABLE_ENTRY,
+ TTY2_DRIVER_TABLE_ENTRY,
+ {NULL, NULL, NULL, NULL, NULL, NULL}
+};
+#endif
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 8
+
+#define CONFIGURE_EXECUTIVE_RAM_SIZE (512*1024)
+#define CONFIGURE_MAXIMUM_SEMAPHORES 20
+#define CONFIGURE_MAXIMUM_TASKS 20
+
+#define CONFIGURE_MICROSECONDS_PER_TICK 10000
+
+#define CONFIGURE_INIT_TASK_STACK_SIZE (10*1024)
+#define CONFIGURE_INIT_TASK_PRIORITY 120
+#define CONFIGURE_INIT_TASK_INITIAL_MODES (RTEMS_PREEMPT | \
+ RTEMS_NO_TIMESLICE | \
+ RTEMS_NO_ASR | \
+ RTEMS_INTERRUPT_LEVEL(0))
+
+#include <confdefs.h>
+
+#endif
diff --git a/cpukit/pppd/fsm.c b/cpukit/pppd/fsm.c
new file mode 100644
index 0000000000..53401a9129
--- /dev/null
+++ b/cpukit/pppd/fsm.c
@@ -0,0 +1,764 @@
+/*
+ * fsm.c - {Link, IP} Control Protocol Finite State Machine.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#define RCSID "$Id$"
+
+/*
+ * TODO:
+ * Randomize fsm id on link/init.
+ * Deal with variable outgoing MTU.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "pppd.h"
+#include "fsm.h"
+
+static const char rcsid[] = RCSID;
+
+static void fsm_timeout __P((void *));
+static void fsm_rconfreq __P((fsm *, u_char, u_char *, int));
+static void fsm_rconfack __P((fsm *, int, u_char *, int));
+static void fsm_rconfnakrej __P((fsm *, int, int, u_char *, int));
+static void fsm_rtermreq __P((fsm *, int, u_char *, int));
+static void fsm_rtermack __P((fsm *));
+static void fsm_rcoderej __P((fsm *, u_char *, int));
+static void fsm_sconfreq __P((fsm *, int));
+
+#define PROTO_NAME(f) ((f)->callbacks->proto_name)
+
+int peer_mru[NUM_PPP];
+
+
+/*
+ * fsm_init - Initialize fsm.
+ *
+ * Initialize fsm state.
+ */
+void
+fsm_init(f)
+ fsm *f;
+{
+ f->state = INITIAL;
+ f->flags = 0;
+ f->id = 100; /* XXX Start with random id? */
+ f->timeouttime = DEFTIMEOUT;
+ f->maxconfreqtransmits = DEFMAXCONFREQS;
+ f->maxtermtransmits = DEFMAXTERMREQS;
+ f->maxnakloops = DEFMAXNAKLOOPS;
+ f->term_reason_len = 0;
+}
+
+
+/*
+ * fsm_lowerup - The lower layer is up.
+ */
+void
+fsm_lowerup(f)
+ fsm *f;
+{
+ switch( f->state ){
+ case INITIAL:
+ f->state = CLOSED;
+ break;
+
+ case STARTING:
+ if( f->flags & OPT_SILENT )
+ f->state = STOPPED;
+ else {
+ /* Send an initial configure-request */
+ fsm_sconfreq(f, 0);
+ f->state = REQSENT;
+ }
+ break;
+
+ default:
+ FSMDEBUG(("%s: Up event in state %d!", PROTO_NAME(f), f->state));
+ }
+}
+
+
+/*
+ * fsm_lowerdown - The lower layer is down.
+ *
+ * Cancel all timeouts and inform upper layers.
+ */
+void
+fsm_lowerdown(f)
+ fsm *f;
+{
+ switch( f->state ){
+ case CLOSED:
+ f->state = INITIAL;
+ break;
+
+ case STOPPED:
+ f->state = STARTING;
+ if( f->callbacks->starting )
+ (*f->callbacks->starting)(f);
+ break;
+
+ case CLOSING:
+ f->state = INITIAL;
+ UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
+ break;
+
+ case STOPPING:
+ case REQSENT:
+ case ACKRCVD:
+ case ACKSENT:
+ f->state = STARTING;
+ UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
+ break;
+
+ case OPENED:
+ if( f->callbacks->down )
+ (*f->callbacks->down)(f);
+ f->state = STARTING;
+ break;
+
+ default:
+ FSMDEBUG(("%s: Down event in state %d!", PROTO_NAME(f), f->state));
+ }
+}
+
+
+/*
+ * fsm_open - Link is allowed to come up.
+ */
+void
+fsm_open(f)
+ fsm *f;
+{
+ switch( f->state ){
+ case INITIAL:
+ f->state = STARTING;
+ if( f->callbacks->starting )
+ (*f->callbacks->starting)(f);
+ break;
+
+ case CLOSED:
+ if( f->flags & OPT_SILENT )
+ f->state = STOPPED;
+ else {
+ /* Send an initial configure-request */
+ fsm_sconfreq(f, 0);
+ f->state = REQSENT;
+ }
+ break;
+
+ case CLOSING:
+ f->state = STOPPING;
+ /* fall through */
+ case STOPPED:
+ case OPENED:
+ if( f->flags & OPT_RESTART ){
+ fsm_lowerdown(f);
+ fsm_lowerup(f);
+ }
+ break;
+ }
+}
+
+
+/*
+ * fsm_close - Start closing connection.
+ *
+ * Cancel timeouts and either initiate close or possibly go directly to
+ * the CLOSED state.
+ */
+void
+fsm_close(f, reason)
+ fsm *f;
+ char *reason;
+{
+ f->term_reason = reason;
+ f->term_reason_len = (reason == NULL? 0: strlen(reason));
+ switch( f->state ){
+ case STARTING:
+ f->state = INITIAL;
+ break;
+ case STOPPED:
+ f->state = CLOSED;
+ break;
+ case STOPPING:
+ f->state = CLOSING;
+ break;
+
+ case REQSENT:
+ case ACKRCVD:
+ case ACKSENT:
+ case OPENED:
+ if( f->state != OPENED )
+ UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
+ else if( f->callbacks->down )
+ (*f->callbacks->down)(f); /* Inform upper layers we're down */
+
+ /* Init restart counter, send Terminate-Request */
+ f->retransmits = f->maxtermtransmits;
+ fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
+ (u_char *) f->term_reason, f->term_reason_len);
+ TIMEOUT(fsm_timeout, f, f->timeouttime);
+ --f->retransmits;
+
+ f->state = CLOSING;
+ break;
+ }
+}
+
+
+/*
+ * fsm_timeout - Timeout expired.
+ */
+static void
+fsm_timeout(arg)
+ void *arg;
+{
+ fsm *f = (fsm *) arg;
+
+ switch (f->state) {
+ case CLOSING:
+ case STOPPING:
+ if( f->retransmits <= 0 ){
+ /*
+ * We've waited for an ack long enough. Peer probably heard us.
+ */
+ f->state = (f->state == CLOSING)? CLOSED: STOPPED;
+ if( f->callbacks->finished )
+ (*f->callbacks->finished)(f);
+ } else {
+ /* Send Terminate-Request */
+ fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
+ (u_char *) f->term_reason, f->term_reason_len);
+ TIMEOUT(fsm_timeout, f, f->timeouttime);
+ --f->retransmits;
+ }
+ break;
+
+ case REQSENT:
+ case ACKRCVD:
+ case ACKSENT:
+ if (f->retransmits <= 0) {
+ warn("%s: timeout sending Config-Requests\n", PROTO_NAME(f));
+ f->state = STOPPED;
+ if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished )
+ (*f->callbacks->finished)(f);
+
+ } else {
+ /* Retransmit the configure-request */
+ if (f->callbacks->retransmit)
+ (*f->callbacks->retransmit)(f);
+ fsm_sconfreq(f, 1); /* Re-send Configure-Request */
+ if( f->state == ACKRCVD )
+ f->state = REQSENT;
+ }
+ break;
+
+ default:
+ FSMDEBUG(("%s: Timeout event in state %d!", PROTO_NAME(f), f->state));
+ }
+}
+
+
+/*
+ * fsm_input - Input packet.
+ */
+void
+fsm_input(f, inpacket, l)
+ fsm *f;
+ u_char *inpacket;
+ int l;
+{
+ u_char *inp;
+ u_char code, id;
+ int len;
+
+ /*
+ * Parse header (code, id and length).
+ * If packet too short, drop it.
+ */
+ inp = inpacket;
+ if (l < HEADERLEN) {
+ FSMDEBUG(("fsm_input(%x): Rcvd short header.", f->protocol));
+ return;
+ }
+ GETCHAR(code, inp);
+ GETCHAR(id, inp);
+ GETSHORT(len, inp);
+ if (len < HEADERLEN) {
+ FSMDEBUG(("fsm_input(%x): Rcvd illegal length.", f->protocol));
+ return;
+ }
+ if (len > l) {
+ FSMDEBUG(("fsm_input(%x): Rcvd short packet.", f->protocol));
+ return;
+ }
+ len -= HEADERLEN; /* subtract header length */
+
+ if( f->state == INITIAL || f->state == STARTING ){
+ FSMDEBUG(("fsm_input(%x): Rcvd packet in state %d.",
+ f->protocol, f->state));
+ return;
+ }
+
+ /*
+ * Action depends on code.
+ */
+ switch (code) {
+ case CONFREQ:
+ fsm_rconfreq(f, id, inp, len);
+ break;
+
+ case CONFACK:
+ fsm_rconfack(f, id, inp, len);
+ break;
+
+ case CONFNAK:
+ case CONFREJ:
+ fsm_rconfnakrej(f, code, id, inp, len);
+ break;
+
+ case TERMREQ:
+ fsm_rtermreq(f, id, inp, len);
+ break;
+
+ case TERMACK:
+ fsm_rtermack(f);
+ break;
+
+ case CODEREJ:
+ fsm_rcoderej(f, inp, len);
+ break;
+
+ default:
+ if( !f->callbacks->extcode
+ || !(*f->callbacks->extcode)(f, code, id, inp, len) )
+ fsm_sdata(f, CODEREJ, ++f->id, inpacket, len + HEADERLEN);
+ break;
+ }
+}
+
+
+/*
+ * fsm_rconfreq - Receive Configure-Request.
+ */
+static void
+fsm_rconfreq(f, id, inp, len)
+ fsm *f;
+ u_char id;
+ u_char *inp;
+ int len;
+{
+ int code, reject_if_disagree;
+
+ switch( f->state ){
+ case CLOSED:
+ /* Go away, we're closed */
+ fsm_sdata(f, TERMACK, id, NULL, 0);
+ return;
+ case CLOSING:
+ case STOPPING:
+ return;
+
+ case OPENED:
+ /* Go down and restart negotiation */
+ if( f->callbacks->down )
+ (*f->callbacks->down)(f); /* Inform upper layers */
+ fsm_sconfreq(f, 0); /* Send initial Configure-Request */
+ break;
+
+ case STOPPED:
+ /* Negotiation started by our peer */
+ fsm_sconfreq(f, 0); /* Send initial Configure-Request */
+ f->state = REQSENT;
+ break;
+ }
+
+ /*
+ * Pass the requested configuration options
+ * to protocol-specific code for checking.
+ */
+ if (f->callbacks->reqci){ /* Check CI */
+ reject_if_disagree = (f->nakloops >= f->maxnakloops);
+ code = (*f->callbacks->reqci)(f, inp, &len, reject_if_disagree);
+ } else if (len)
+ code = CONFREJ; /* Reject all CI */
+ else
+ code = CONFACK;
+
+ /* send the Ack, Nak or Rej to the peer */
+ fsm_sdata(f, code, id, inp, len);
+
+ if (code == CONFACK) {
+ if (f->state == ACKRCVD) {
+ UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
+ f->state = OPENED;
+ if (f->callbacks->up)
+ (*f->callbacks->up)(f); /* Inform upper layers */
+ } else {
+ f->state = ACKSENT;
+ ppp_delay();
+ }
+ f->nakloops = 0;
+
+ } else {
+ /* we sent CONFACK or CONFREJ */
+ if (f->state != ACKRCVD)
+ f->state = REQSENT;
+ if( code == CONFNAK )
+ ++f->nakloops;
+ }
+}
+
+
+/*
+ * fsm_rconfack - Receive Configure-Ack.
+ */
+static void
+fsm_rconfack(f, id, inp, len)
+ fsm *f;
+ int id;
+ u_char *inp;
+ int len;
+{
+ if (id != f->reqid || f->seen_ack) /* Expected id? */
+ return; /* Nope, toss... */
+ if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len):
+ (len == 0)) ){
+ /* Ack is bad - ignore it */
+ error("Received bad configure-ack: %P", inp, len);
+ return;
+ }
+ f->seen_ack = 1;
+
+ switch (f->state) {
+ case CLOSED:
+ case STOPPED:
+ fsm_sdata(f, TERMACK, id, NULL, 0);
+ break;
+
+ case REQSENT:
+ f->state = ACKRCVD;
+ f->retransmits = f->maxconfreqtransmits;
+ break;
+
+ case ACKRCVD:
+ /* Huh? an extra valid Ack? oh well... */
+ UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
+ fsm_sconfreq(f, 0);
+ f->state = REQSENT;
+ break;
+
+ case ACKSENT:
+ UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
+ f->state = OPENED;
+ f->retransmits = f->maxconfreqtransmits;
+ if (f->callbacks->up)
+ (*f->callbacks->up)(f); /* Inform upper layers */
+ break;
+
+ case OPENED:
+ /* Go down and restart negotiation */
+ if (f->callbacks->down)
+ (*f->callbacks->down)(f); /* Inform upper layers */
+ fsm_sconfreq(f, 0); /* Send initial Configure-Request */
+ f->state = REQSENT;
+ break;
+ }
+}
+
+
+/*
+ * fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject.
+ */
+static void
+fsm_rconfnakrej(f, code, id, inp, len)
+ fsm *f;
+ int code, id;
+ u_char *inp;
+ int len;
+{
+ int (*proc) __P((fsm *, u_char *, int));
+ int ret;
+
+ if (id != f->reqid || f->seen_ack) /* Expected id? */
+ return; /* Nope, toss... */
+ proc = (code == CONFNAK)? f->callbacks->nakci: f->callbacks->rejci;
+ if (!proc || !(ret = proc(f, inp, len))) {
+ /* Nak/reject is bad - ignore it */
+ error("Received bad configure-nak/rej: %P", inp, len);
+ return;
+ }
+ f->seen_ack = 1;
+
+ switch (f->state) {
+ case CLOSED:
+ case STOPPED:
+ fsm_sdata(f, TERMACK, id, NULL, 0);
+ break;
+
+ case REQSENT:
+ case ACKSENT:
+ /* They didn't agree to what we wanted - try another request */
+ UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
+ if (ret < 0)
+ f->state = STOPPED; /* kludge for stopping CCP */
+ else
+ fsm_sconfreq(f, 0); /* Send Configure-Request */
+ break;
+
+ case ACKRCVD:
+ /* Got a Nak/reject when we had already had an Ack?? oh well... */
+ UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
+ fsm_sconfreq(f, 0);
+ f->state = REQSENT;
+ break;
+
+ case OPENED:
+ /* Go down and restart negotiation */
+ if (f->callbacks->down)
+ (*f->callbacks->down)(f); /* Inform upper layers */
+ fsm_sconfreq(f, 0); /* Send initial Configure-Request */
+ f->state = REQSENT;
+ break;
+ }
+}
+
+
+/*
+ * fsm_rtermreq - Receive Terminate-Req.
+ */
+static void
+fsm_rtermreq(f, id, p, len)
+ fsm *f;
+ int id;
+ u_char *p;
+ int len;
+{
+ switch (f->state) {
+ case ACKRCVD:
+ case ACKSENT:
+ f->state = REQSENT; /* Start over but keep trying */
+ break;
+
+ case OPENED:
+ if (len > 0) {
+ info("%s terminated by peer (%0.*v)", PROTO_NAME(f), len, p);
+ } else
+ info("%s terminated by peer", PROTO_NAME(f));
+ if (f->callbacks->down)
+ (*f->callbacks->down)(f); /* Inform upper layers */
+ f->retransmits = 0;
+ f->state = STOPPING;
+ TIMEOUT(fsm_timeout, f, f->timeouttime);
+ break;
+ }
+
+ fsm_sdata(f, TERMACK, id, NULL, 0);
+}
+
+
+/*
+ * fsm_rtermack - Receive Terminate-Ack.
+ */
+static void
+fsm_rtermack(f)
+ fsm *f;
+{
+ switch (f->state) {
+ case CLOSING:
+ UNTIMEOUT(fsm_timeout, f);
+ f->state = CLOSED;
+ if( f->callbacks->finished )
+ (*f->callbacks->finished)(f);
+ break;
+ case STOPPING:
+ UNTIMEOUT(fsm_timeout, f);
+ f->state = STOPPED;
+ if( f->callbacks->finished )
+ (*f->callbacks->finished)(f);
+ break;
+
+ case ACKRCVD:
+ f->state = REQSENT;
+ break;
+
+ case OPENED:
+ if (f->callbacks->down)
+ (*f->callbacks->down)(f); /* Inform upper layers */
+ fsm_sconfreq(f, 0);
+ break;
+ }
+}
+
+
+/*
+ * fsm_rcoderej - Receive an Code-Reject.
+ */
+static void
+fsm_rcoderej(f, inp, len)
+ fsm *f;
+ u_char *inp;
+ int len;
+{
+ u_char code, id;
+
+ if (len < HEADERLEN) {
+ FSMDEBUG(("fsm_rcoderej: Rcvd short Code-Reject packet!"));
+ return;
+ }
+ GETCHAR(code, inp);
+ GETCHAR(id, inp);
+ warn("%s: Rcvd Code-Reject for code %d, id %d", PROTO_NAME(f), code, id);
+
+ if( f->state == ACKRCVD )
+ f->state = REQSENT;
+}
+
+
+/*
+ * fsm_protreject - Peer doesn't speak this protocol.
+ *
+ * Treat this as a catastrophic error (RXJ-).
+ */
+void
+fsm_protreject(f)
+ fsm *f;
+{
+ switch( f->state ){
+ case CLOSING:
+ UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
+ /* fall through */
+ case CLOSED:
+ f->state = CLOSED;
+ if( f->callbacks->finished )
+ (*f->callbacks->finished)(f);
+ break;
+
+ case STOPPING:
+ case REQSENT:
+ case ACKRCVD:
+ case ACKSENT:
+ UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
+ /* fall through */
+ case STOPPED:
+ f->state = STOPPED;
+ if( f->callbacks->finished )
+ (*f->callbacks->finished)(f);
+ break;
+
+ case OPENED:
+ if( f->callbacks->down )
+ (*f->callbacks->down)(f);
+
+ /* Init restart counter, send Terminate-Request */
+ f->retransmits = f->maxtermtransmits;
+ fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
+ (u_char *) f->term_reason, f->term_reason_len);
+ TIMEOUT(fsm_timeout, f, f->timeouttime);
+ --f->retransmits;
+
+ f->state = STOPPING;
+ break;
+
+ default:
+ FSMDEBUG(("%s: Protocol-reject event in state %d!",
+ PROTO_NAME(f), f->state));
+ }
+}
+
+
+/*
+ * fsm_sconfreq - Send a Configure-Request.
+ */
+static void
+fsm_sconfreq(f, retransmit)
+ fsm *f;
+ int retransmit;
+{
+ u_char *outp;
+ int cilen;
+
+ if( f->state != REQSENT && f->state != ACKRCVD && f->state != ACKSENT ){
+ /* Not currently negotiating - reset options */
+ if( f->callbacks->resetci )
+ (*f->callbacks->resetci)(f);
+ f->nakloops = 0;
+ }
+
+ if( !retransmit ){
+ /* New request - reset retransmission counter, use new ID */
+ f->retransmits = f->maxconfreqtransmits;
+ f->reqid = ++f->id;
+ }
+
+ f->seen_ack = 0;
+
+ /*
+ * Make up the request packet
+ */
+ outp = outpacket_buf + PPP_HDRLEN + HEADERLEN;
+ if( f->callbacks->cilen && f->callbacks->addci ){
+ cilen = (*f->callbacks->cilen)(f);
+ if( cilen > peer_mru[f->unit] - HEADERLEN )
+ cilen = peer_mru[f->unit] - HEADERLEN;
+ if (f->callbacks->addci)
+ (*f->callbacks->addci)(f, outp, &cilen);
+ } else
+ cilen = 0;
+
+ /* send the request to our peer */
+ fsm_sdata(f, CONFREQ, f->reqid, outp, cilen);
+
+ /* start the retransmit timer */
+ --f->retransmits;
+ TIMEOUT(fsm_timeout, f, f->timeouttime);
+}
+
+
+/*
+ * fsm_sdata - Send some data.
+ *
+ * Used for all packets sent to our peer by this module.
+ */
+void
+fsm_sdata(f, code, id, data, datalen)
+ fsm *f;
+ u_char code, id;
+ u_char *data;
+ int datalen;
+{
+ u_char *outp;
+ int outlen;
+
+ /* Adjust length to be smaller than MTU */
+ outp = outpacket_buf;
+ if (datalen > peer_mru[f->unit] - HEADERLEN)
+ datalen = peer_mru[f->unit] - HEADERLEN;
+ if (datalen && data != outp + PPP_HDRLEN + HEADERLEN)
+ BCOPY(data, outp + PPP_HDRLEN + HEADERLEN, datalen);
+ outlen = datalen + HEADERLEN;
+ MAKEHEADER(outp, f->protocol);
+ PUTCHAR(code, outp);
+ PUTCHAR(id, outp);
+ PUTSHORT(outlen, outp);
+ output(f->unit, outpacket_buf, outlen + PPP_HDRLEN);
+}
diff --git a/cpukit/pppd/fsm.h b/cpukit/pppd/fsm.h
new file mode 100644
index 0000000000..d1e623467c
--- /dev/null
+++ b/cpukit/pppd/fsm.h
@@ -0,0 +1,144 @@
+/*
+ * fsm.h - {Link, IP} Control Protocol Finite State Machine definitions.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * $Id$
+ */
+
+/*
+ * Packet header = Code, id, length.
+ */
+#define HEADERLEN 4
+
+
+/*
+ * CP (LCP, IPCP, etc.) codes.
+ */
+#define CONFREQ 1 /* Configuration Request */
+#define CONFACK 2 /* Configuration Ack */
+#define CONFNAK 3 /* Configuration Nak */
+#define CONFREJ 4 /* Configuration Reject */
+#define TERMREQ 5 /* Termination Request */
+#define TERMACK 6 /* Termination Ack */
+#define CODEREJ 7 /* Code Reject */
+
+
+/*
+ * Each FSM is described by an fsm structure and fsm callbacks.
+ */
+typedef struct fsm {
+ int unit; /* Interface unit number */
+ int protocol; /* Data Link Layer Protocol field value */
+ int state; /* State */
+ int flags; /* Contains option bits */
+ u_char id; /* Current id */
+ u_char reqid; /* Current request id */
+ u_char seen_ack; /* Have received valid Ack/Nak/Rej to Req */
+ int timeouttime; /* Timeout time in milliseconds */
+ int maxconfreqtransmits; /* Maximum Configure-Request transmissions */
+ int retransmits; /* Number of retransmissions left */
+ int maxtermtransmits; /* Maximum Terminate-Request transmissions */
+ int nakloops; /* Number of nak loops since last ack */
+ int maxnakloops; /* Maximum number of nak loops tolerated */
+ struct fsm_callbacks *callbacks; /* Callback routines */
+ char *term_reason; /* Reason for closing protocol */
+ int term_reason_len; /* Length of term_reason */
+} fsm;
+
+
+typedef struct fsm_callbacks {
+ void (*resetci) /* Reset our Configuration Information */
+ __P((fsm *));
+ int (*cilen) /* Length of our Configuration Information */
+ __P((fsm *));
+ void (*addci) /* Add our Configuration Information */
+ __P((fsm *, u_char *, int *));
+ int (*ackci) /* ACK our Configuration Information */
+ __P((fsm *, u_char *, int));
+ int (*nakci) /* NAK our Configuration Information */
+ __P((fsm *, u_char *, int));
+ int (*rejci) /* Reject our Configuration Information */
+ __P((fsm *, u_char *, int));
+ int (*reqci) /* Request peer's Configuration Information */
+ __P((fsm *, u_char *, int *, int));
+ void (*up) /* Called when fsm reaches OPENED state */
+ __P((fsm *));
+ void (*down) /* Called when fsm leaves OPENED state */
+ __P((fsm *));
+ void (*starting) /* Called when we want the lower layer */
+ __P((fsm *));
+ void (*finished) /* Called when we don't want the lower layer */
+ __P((fsm *));
+ void (*protreject) /* Called when Protocol-Reject received */
+ __P((int));
+ void (*retransmit) /* Retransmission is necessary */
+ __P((fsm *));
+ int (*extcode) /* Called when unknown code received */
+ __P((fsm *, int, int, u_char *, int));
+ char *proto_name; /* String name for protocol (for messages) */
+} fsm_callbacks;
+
+
+/*
+ * Link states.
+ */
+#define INITIAL 0 /* Down, hasn't been opened */
+#define STARTING 1 /* Down, been opened */
+#define CLOSED 2 /* Up, hasn't been opened */
+#define STOPPED 3 /* Open, waiting for down event */
+#define CLOSING 4 /* Terminating the connection, not open */
+#define STOPPING 5 /* Terminating, but open */
+#define REQSENT 6 /* We've sent a Config Request */
+#define ACKRCVD 7 /* We've received a Config Ack */
+#define ACKSENT 8 /* We've sent a Config Ack */
+#define OPENED 9 /* Connection available */
+
+
+/*
+ * Flags - indicate options controlling FSM operation
+ */
+#define OPT_PASSIVE 1 /* Don't die if we don't get a response */
+#define OPT_RESTART 2 /* Treat 2nd OPEN as DOWN, UP */
+#define OPT_SILENT 4 /* Wait for peer to speak first */
+
+
+/*
+ * Timeouts.
+ */
+#define DEFTIMEOUT 5 /* Timeout time in seconds */
+#define DEFMAXTERMREQS 2 /* Maximum Terminate-Request transmissions */
+#define DEFMAXCONFREQS 10 /* Maximum Configure-Request transmissions */
+#define DEFMAXNAKLOOPS 5 /* Maximum number of nak loops */
+
+
+/*
+ * Prototypes
+ */
+void fsm_init __P((fsm *));
+void fsm_lowerup __P((fsm *));
+void fsm_lowerdown __P((fsm *));
+void fsm_open __P((fsm *));
+void fsm_close __P((fsm *, char *));
+void fsm_input __P((fsm *, u_char *, int));
+void fsm_protreject __P((fsm *));
+void fsm_sdata __P((fsm *, u_char, u_char, u_char *, int));
+
+
+/*
+ * Variables
+ */
+extern int peer_mru[]; /* currently negotiated peer MRU (per unit) */
diff --git a/cpukit/pppd/ipcp.c b/cpukit/pppd/ipcp.c
new file mode 100644
index 0000000000..d11e7c653a
--- /dev/null
+++ b/cpukit/pppd/ipcp.c
@@ -0,0 +1,1769 @@
+/*
+ * ipcp.c - PPP IP Control Protocol.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#define RCSID "$Id$"
+
+/*
+ * TODO:
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <netdb.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <resolv.h>
+
+#include "pppd.h"
+#include "fsm.h"
+#include "ipcp.h"
+#include "pathnames.h"
+
+static const char rcsid[] = RCSID;
+
+/* global vars */
+ipcp_options ipcp_wantoptions[NUM_PPP]; /* Options that we want to request */
+ipcp_options ipcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */
+ipcp_options ipcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
+ipcp_options ipcp_hisoptions[NUM_PPP]; /* Options that we ack'd */
+
+bool disable_defaultip = 0; /* Don't use hostname for default IP adrs */
+
+/* Hook for a plugin to know when IP protocol has come up */
+void (*ip_up_hook) __P((void)) = NULL;
+
+/* Hook for a plugin to know when IP protocol has come down */
+void (*ip_down_hook) __P((void)) = NULL;
+
+/* local vars */
+static int default_route_set[NUM_PPP]; /* Have set up a default route */
+static int proxy_arp_set[NUM_PPP]; /* Have created proxy arp entry */
+static bool usepeerdns; /* Ask peer for DNS addrs */
+static int ipcp_is_up; /* have called np_up() */
+
+/*
+ * Callbacks for fsm code. (CI = Configuration Information)
+ */
+static void ipcp_resetci __P((fsm *)); /* Reset our CI */
+static int ipcp_cilen __P((fsm *)); /* Return length of our CI */
+static void ipcp_addci __P((fsm *, u_char *, int *)); /* Add our CI */
+static int ipcp_ackci __P((fsm *, u_char *, int)); /* Peer ack'd our CI */
+static int ipcp_nakci __P((fsm *, u_char *, int)); /* Peer nak'd our CI */
+static int ipcp_rejci __P((fsm *, u_char *, int)); /* Peer rej'd our CI */
+static int ipcp_reqci __P((fsm *, u_char *, int *, int)); /* Rcv CI */
+static void ipcp_up __P((fsm *)); /* We're UP */
+static void ipcp_down __P((fsm *)); /* We're DOWN */
+static void ipcp_finished __P((fsm *)); /* Don't need lower layer */
+
+fsm ipcp_fsm[NUM_PPP]; /* IPCP fsm structure */
+
+static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */
+ ipcp_resetci, /* Reset our Configuration Information */
+ ipcp_cilen, /* Length of our Configuration Information */
+ ipcp_addci, /* Add our Configuration Information */
+ ipcp_ackci, /* ACK our Configuration Information */
+ ipcp_nakci, /* NAK our Configuration Information */
+ ipcp_rejci, /* Reject our Configuration Information */
+ ipcp_reqci, /* Request peer's Configuration Information */
+ ipcp_up, /* Called when fsm reaches OPENED state */
+ ipcp_down, /* Called when fsm leaves OPENED state */
+ NULL, /* Called when we want the lower layer up */
+ ipcp_finished, /* Called when we want the lower layer down */
+ NULL, /* Called when Protocol-Reject received */
+ NULL, /* Retransmission is necessary */
+ NULL, /* Called to handle protocol-specific codes */
+ "IPCP" /* String name of protocol */
+};
+
+/*
+ * Command-line options.
+ */
+static int setvjslots __P((char **));
+static int setdnsaddr __P((char **));
+static int setwinsaddr __P((char **));
+
+static option_t ipcp_option_list[] = {
+ { "noip", o_bool, &ipcp_protent.enabled_flag,
+ "Disable IP and IPCP" },
+ { "-ip", o_bool, &ipcp_protent.enabled_flag,
+ "Disable IP and IPCP" },
+ { "novj", o_bool, &ipcp_wantoptions[0].neg_vj,
+ "Disable VJ compression", OPT_A2COPY, &ipcp_allowoptions[0].neg_vj },
+ { "-vj", o_bool, &ipcp_wantoptions[0].neg_vj,
+ "Disable VJ compression", OPT_A2COPY, &ipcp_allowoptions[0].neg_vj },
+ { "novjccomp", o_bool, &ipcp_wantoptions[0].cflag,
+ "Disable VJ connection-ID compression", OPT_A2COPY,
+ &ipcp_allowoptions[0].cflag },
+ { "-vjccomp", o_bool, &ipcp_wantoptions[0].cflag,
+ "Disable VJ connection-ID compression", OPT_A2COPY,
+ &ipcp_allowoptions[0].cflag },
+ { "vj-max-slots", 1, setvjslots,
+ "Set maximum VJ header slots" },
+ { "ipcp-accept-local", o_bool, &ipcp_wantoptions[0].accept_local,
+ "Accept peer's address for us", 1 },
+ { "ipcp-accept-remote", o_bool, &ipcp_wantoptions[0].accept_remote,
+ "Accept peer's address for it", 1 },
+ { "ipparam", o_string, &ipparam,
+ "Set ip script parameter" },
+ { "noipdefault", o_bool, &disable_defaultip,
+ "Don't use name for default IP adrs", 1 },
+ { "ms-dns", 1, setdnsaddr,
+ "DNS address for the peer's use" },
+ { "ms-wins", 1, setwinsaddr,
+ "Nameserver for SMB over TCP/IP for peer" },
+ { "ipcp-restart", o_int, &ipcp_fsm[0].timeouttime,
+ "Set timeout for IPCP" },
+ { "ipcp-max-terminate", o_int, &ipcp_fsm[0].maxtermtransmits,
+ "Set max #xmits for term-reqs" },
+ { "ipcp-max-configure", o_int, &ipcp_fsm[0].maxconfreqtransmits,
+ "Set max #xmits for conf-reqs" },
+ { "ipcp-max-failure", o_int, &ipcp_fsm[0].maxnakloops,
+ "Set max #conf-naks for IPCP" },
+ { "defaultroute", o_bool, &ipcp_wantoptions[0].default_route,
+ "Add default route", OPT_ENABLE|1, &ipcp_allowoptions[0].default_route },
+ { "nodefaultroute", o_bool, &ipcp_allowoptions[0].default_route,
+ "disable defaultroute option", OPT_A2COPY,
+ &ipcp_wantoptions[0].default_route },
+ { "-defaultroute", o_bool, &ipcp_allowoptions[0].default_route,
+ "disable defaultroute option", OPT_A2COPY,
+ &ipcp_wantoptions[0].default_route },
+ { "proxyarp", o_bool, &ipcp_wantoptions[0].proxy_arp,
+ "Add proxy ARP entry", OPT_ENABLE|1, &ipcp_allowoptions[0].proxy_arp },
+ { "noproxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp,
+ "disable proxyarp option", OPT_A2COPY,
+ &ipcp_wantoptions[0].proxy_arp },
+ { "-proxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp,
+ "disable proxyarp option", OPT_A2COPY,
+ &ipcp_wantoptions[0].proxy_arp },
+ { "usepeerdns", o_bool, &usepeerdns,
+ "Ask peer for DNS address(es)", 1 },
+ { NULL }
+};
+
+/*
+ * Protocol entry points from main code.
+ */
+static void ipcp_init __P((int));
+static void ipcp_open __P((int));
+static void ipcp_close __P((int, char *));
+static void ipcp_lowerup __P((int));
+static void ipcp_lowerdown __P((int));
+static void ipcp_input __P((int, u_char *, int));
+static void ipcp_protrej __P((int));
+static int ipcp_printpkt __P((u_char *, int,
+ void (*) __P((void *, char *, ...)), void *));
+static void ip_check_options __P((void));
+static int ip_demand_conf __P((int));
+static int ip_active_pkt __P((u_char *, int));
+static void create_resolv __P((u_int32_t, u_int32_t));
+
+struct protent ipcp_protent = {
+ PPP_IPCP,
+ ipcp_init,
+ ipcp_input,
+ ipcp_protrej,
+ ipcp_lowerup,
+ ipcp_lowerdown,
+ ipcp_open,
+ ipcp_close,
+ ipcp_printpkt,
+ NULL,
+ 1,
+ "IPCP",
+ "IP",
+ ipcp_option_list,
+ ip_check_options,
+ ip_demand_conf,
+ ip_active_pkt
+};
+
+static void ipcp_clear_addrs __P((int, u_int32_t, u_int32_t));
+
+/*
+ * Lengths of configuration options.
+ */
+#define CILEN_VOID 2
+#define CILEN_COMPRESS 4 /* min length for compression protocol opt. */
+#define CILEN_VJ 6 /* length for RFC1332 Van-Jacobson opt. */
+#define CILEN_ADDR 6 /* new-style single address option */
+#define CILEN_ADDRS 10 /* old-style dual address option */
+
+
+#define CODENAME(x) ((x) == CONFACK ? "ACK" : \
+ (x) == CONFNAK ? "NAK" : "REJ")
+
+/*
+ * Make a string representation of a network IP address.
+ */
+char *
+ip_ntoa(ipaddr)
+u_int32_t ipaddr;
+{
+ static char b[64];
+
+ slprintf(b, sizeof(b), "%I", ipaddr);
+ return b;
+}
+
+/*
+ * Option parsing.
+ */
+
+/*
+ * setvjslots - set maximum number of connection slots for VJ compression
+ */
+static int
+setvjslots(argv)
+ char **argv;
+{
+ int value;
+
+ if (!int_option(*argv, &value))
+ return 0;
+ if (value < 2 || value > 16) {
+ option_error("vj-max-slots value must be between 2 and 16");
+ return 0;
+ }
+ ipcp_wantoptions [0].maxslotindex =
+ ipcp_allowoptions[0].maxslotindex = value - 1;
+ return 1;
+}
+
+/*
+ * setdnsaddr - set the dns address(es)
+ */
+static int
+setdnsaddr(argv)
+ char **argv;
+{
+ u_int32_t dns;
+ struct hostent *hp;
+
+ dns = inet_addr(*argv);
+ if (dns == (u_int32_t) -1) {
+ if ((hp = gethostbyname(*argv)) == NULL) {
+ option_error("invalid address parameter '%s' for ms-dns option",
+ *argv);
+ return 0;
+ }
+ dns = *(u_int32_t *)hp->h_addr;
+ }
+
+ /* if there is no primary then update it. */
+ if (ipcp_allowoptions[0].dnsaddr[0] == 0)
+ ipcp_allowoptions[0].dnsaddr[0] = dns;
+
+ /* always set the secondary address value to the same value. */
+ ipcp_allowoptions[0].dnsaddr[1] = dns;
+
+ return (1);
+}
+
+/*
+ * setwinsaddr - set the wins address(es)
+ * This is primrarly used with the Samba package under UNIX or for pointing
+ * the caller to the existing WINS server on a Windows NT platform.
+ */
+static int
+setwinsaddr(argv)
+ char **argv;
+{
+ u_int32_t wins;
+ struct hostent *hp;
+
+ wins = inet_addr(*argv);
+ if (wins == (u_int32_t) -1) {
+ if ((hp = gethostbyname(*argv)) == NULL) {
+ option_error("invalid address parameter '%s' for ms-wins option",
+ *argv);
+ return 0;
+ }
+ wins = *(u_int32_t *)hp->h_addr;
+ }
+
+ /* if there is no primary then update it. */
+ if (ipcp_allowoptions[0].winsaddr[0] == 0)
+ ipcp_allowoptions[0].winsaddr[0] = wins;
+
+ /* always set the secondary address value to the same value. */
+ ipcp_allowoptions[0].winsaddr[1] = wins;
+
+ return (1);
+}
+
+
+/*
+ * ipcp_init - Initialize IPCP.
+ */
+static void
+ipcp_init(unit)
+ int unit;
+{
+ fsm *f = &ipcp_fsm[unit];
+ ipcp_options *wo = &ipcp_wantoptions[unit];
+ ipcp_options *ao = &ipcp_allowoptions[unit];
+
+ f->unit = unit;
+ f->protocol = PPP_IPCP;
+ f->callbacks = &ipcp_callbacks;
+ fsm_init(&ipcp_fsm[unit]);
+
+ memset(wo, 0, sizeof(*wo));
+ memset(ao, 0, sizeof(*ao));
+
+ wo->neg_addr = 1;
+ wo->neg_vj = 1;
+ wo->vj_protocol = IPCP_VJ_COMP;
+ wo->maxslotindex = MAX_STATES - 1; /* really max index */
+ wo->cflag = 1;
+
+ /* max slots and slot-id compression are currently hardwired in */
+ /* ppp_if.c to 16 and 1, this needs to be changed (among other */
+ /* things) gmc */
+
+ ao->neg_addr = 1;
+ ao->neg_vj = 1;
+ ao->maxslotindex = MAX_STATES - 1;
+ ao->cflag = 1;
+
+ /*
+ * XXX These control whether the user may use the proxyarp
+ * and defaultroute options.
+ */
+ ao->proxy_arp = 1;
+ ao->default_route = 1;
+}
+
+
+/*
+ * ipcp_open - IPCP is allowed to come up.
+ */
+static void
+ipcp_open(unit)
+ int unit;
+{
+ fsm_open(&ipcp_fsm[unit]);
+}
+
+
+/*
+ * ipcp_close - Take IPCP down.
+ */
+static void
+ipcp_close(unit, reason)
+ int unit;
+ char *reason;
+{
+ fsm_close(&ipcp_fsm[unit], reason);
+}
+
+
+/*
+ * ipcp_lowerup - The lower layer is up.
+ */
+static void
+ipcp_lowerup(unit)
+ int unit;
+{
+ fsm_lowerup(&ipcp_fsm[unit]);
+}
+
+
+/*
+ * ipcp_lowerdown - The lower layer is down.
+ */
+static void
+ipcp_lowerdown(unit)
+ int unit;
+{
+ fsm_lowerdown(&ipcp_fsm[unit]);
+}
+
+
+/*
+ * ipcp_input - Input IPCP packet.
+ */
+static void
+ipcp_input(unit, p, len)
+ int unit;
+ u_char *p;
+ int len;
+{
+ fsm_input(&ipcp_fsm[unit], p, len);
+}
+
+
+/*
+ * ipcp_protrej - A Protocol-Reject was received for IPCP.
+ *
+ * Pretend the lower layer went down, so we shut up.
+ */
+static void
+ipcp_protrej(unit)
+ int unit;
+{
+ fsm_lowerdown(&ipcp_fsm[unit]);
+}
+
+
+/*
+ * ipcp_resetci - Reset our CI.
+ * Called by fsm_sconfreq, Send Configure Request.
+ */
+static void
+ipcp_resetci(f)
+ fsm *f;
+{
+ ipcp_options *wo = &ipcp_wantoptions[f->unit];
+ ipcp_options *go = &ipcp_gotoptions[f->unit];
+
+ wo->req_addr = wo->neg_addr && ipcp_allowoptions[f->unit].neg_addr;
+ if (wo->ouraddr == 0 || disable_defaultip)
+ wo->accept_local = 1;
+ if (wo->hisaddr == 0)
+ wo->accept_remote = 1;
+ wo->req_dns1 = usepeerdns; /* Request DNS addresses from the peer */
+ wo->req_dns2 = usepeerdns;
+ *go = *wo;
+ if (disable_defaultip)
+ go->ouraddr = 0;
+}
+
+
+/*
+ * ipcp_cilen - Return length of our CI.
+ * Called by fsm_sconfreq, Send Configure Request.
+ */
+static int
+ipcp_cilen(f)
+ fsm *f;
+{
+ ipcp_options *go = &ipcp_gotoptions[f->unit];
+ ipcp_options *wo = &ipcp_wantoptions[f->unit];
+ ipcp_options *ho = &ipcp_hisoptions[f->unit];
+
+#define LENCIVJ(neg, old) (neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0)
+#define LENCIADDR(neg, old) (neg ? (old? CILEN_ADDRS : CILEN_ADDR) : 0)
+#define LENCIDNS(neg) (neg ? (CILEN_ADDR) : 0)
+
+ /*
+ * First see if we want to change our options to the old
+ * forms because we have received old forms from the peer.
+ */
+ if (wo->neg_addr && !go->neg_addr && !go->old_addrs) {
+ /* use the old style of address negotiation */
+ go->neg_addr = 1;
+ go->old_addrs = 1;
+ }
+ if (wo->neg_vj && !go->neg_vj && !go->old_vj) {
+ /* try an older style of VJ negotiation */
+ /* use the old style only if the peer did */
+ if (ho->neg_vj && ho->old_vj) {
+ go->neg_vj = 1;
+ go->old_vj = 1;
+ go->vj_protocol = ho->vj_protocol;
+ }
+ }
+
+ return (LENCIADDR(go->neg_addr, go->old_addrs) +
+ LENCIVJ(go->neg_vj, go->old_vj) +
+ LENCIDNS(go->req_dns1) +
+ LENCIDNS(go->req_dns2)) ;
+}
+
+
+/*
+ * ipcp_addci - Add our desired CIs to a packet.
+ * Called by fsm_sconfreq, Send Configure Request.
+ */
+static void
+ipcp_addci(f, ucp, lenp)
+ fsm *f;
+ u_char *ucp;
+ int *lenp;
+{
+ ipcp_options *go = &ipcp_gotoptions[f->unit];
+ int len = *lenp;
+
+#define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \
+ if (neg) { \
+ int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
+ if (len >= vjlen) { \
+ PUTCHAR(opt, ucp); \
+ PUTCHAR(vjlen, ucp); \
+ PUTSHORT(val, ucp); \
+ if (!old) { \
+ PUTCHAR(maxslotindex, ucp); \
+ PUTCHAR(cflag, ucp); \
+ } \
+ len -= vjlen; \
+ } else \
+ neg = 0; \
+ }
+
+#define ADDCIADDR(opt, neg, old, val1, val2) \
+ if (neg) { \
+ int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \
+ if (len >= addrlen) { \
+ u_int32_t l; \
+ PUTCHAR(opt, ucp); \
+ PUTCHAR(addrlen, ucp); \
+ l = ntohl(val1); \
+ PUTLONG(l, ucp); \
+ if (old) { \
+ l = ntohl(val2); \
+ PUTLONG(l, ucp); \
+ } \
+ len -= addrlen; \
+ } else \
+ neg = 0; \
+ }
+
+#define ADDCIDNS(opt, neg, addr) \
+ if (neg) { \
+ if (len >= CILEN_ADDR) { \
+ u_int32_t l; \
+ PUTCHAR(opt, ucp); \
+ PUTCHAR(CILEN_ADDR, ucp); \
+ l = ntohl(addr); \
+ PUTLONG(l, ucp); \
+ len -= CILEN_ADDR; \
+ } else \
+ neg = 0; \
+ }
+
+ ADDCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr,
+ go->old_addrs, go->ouraddr, go->hisaddr);
+
+ ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
+ go->maxslotindex, go->cflag);
+
+ ADDCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]);
+
+ ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);
+
+ *lenp -= len;
+}
+
+
+/*
+ * ipcp_ackci - Ack our CIs.
+ * Called by fsm_rconfack, Receive Configure ACK.
+ *
+ * Returns:
+ * 0 - Ack was bad.
+ * 1 - Ack was good.
+ */
+static int
+ipcp_ackci(f, p, len)
+ fsm *f;
+ u_char *p;
+ int len;
+{
+ ipcp_options *go = &ipcp_gotoptions[f->unit];
+ u_short cilen, citype, cishort;
+ u_int32_t cilong;
+ u_char cimaxslotindex, cicflag;
+
+ /*
+ * CIs must be in exactly the same order that we sent...
+ * Check packet length and CI length at each step.
+ * If we find any deviations, then this packet is bad.
+ */
+
+#define ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \
+ if (neg) { \
+ int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
+ if ((len -= vjlen) < 0) \
+ goto bad; \
+ GETCHAR(citype, p); \
+ GETCHAR(cilen, p); \
+ if (cilen != vjlen || \
+ citype != opt) \
+ goto bad; \
+ GETSHORT(cishort, p); \
+ if (cishort != val) \
+ goto bad; \
+ if (!old) { \
+ GETCHAR(cimaxslotindex, p); \
+ if (cimaxslotindex != maxslotindex) \
+ goto bad; \
+ GETCHAR(cicflag, p); \
+ if (cicflag != cflag) \
+ goto bad; \
+ } \
+ }
+
+#define ACKCIADDR(opt, neg, old, val1, val2) \
+ if (neg) { \
+ int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \
+ u_int32_t l; \
+ if ((len -= addrlen) < 0) \
+ goto bad; \
+ GETCHAR(citype, p); \
+ GETCHAR(cilen, p); \
+ if (cilen != addrlen || \
+ citype != opt) \
+ goto bad; \
+ GETLONG(l, p); \
+ cilong = htonl(l); \
+ if (val1 != cilong) \
+ goto bad; \
+ if (old) { \
+ GETLONG(l, p); \
+ cilong = htonl(l); \
+ if (val2 != cilong) \
+ goto bad; \
+ } \
+ }
+
+#define ACKCIDNS(opt, neg, addr) \
+ if (neg) { \
+ u_int32_t l; \
+ if ((len -= CILEN_ADDR) < 0) \
+ goto bad; \
+ GETCHAR(citype, p); \
+ GETCHAR(cilen, p); \
+ if (cilen != CILEN_ADDR || citype != opt) \
+ goto bad; \
+ GETLONG(l, p); \
+ cilong = htonl(l); \
+ if (addr != cilong) \
+ goto bad; \
+ }
+
+ ACKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr,
+ go->old_addrs, go->ouraddr, go->hisaddr);
+
+ ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
+ go->maxslotindex, go->cflag);
+
+ ACKCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]);
+
+ ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);
+
+ /*
+ * If there are any remaining CIs, then this packet is bad.
+ */
+ if (len != 0)
+ goto bad;
+ return (1);
+
+bad:
+ IPCPDEBUG(("ipcp_ackci: received bad Ack!"));
+ return (0);
+}
+
+/*
+ * ipcp_nakci - Peer has sent a NAK for some of our CIs.
+ * This should not modify any state if the Nak is bad
+ * or if IPCP is in the OPENED state.
+ * Calback from fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject.
+ *
+ * Returns:
+ * 0 - Nak was bad.
+ * 1 - Nak was good.
+ */
+static int
+ipcp_nakci(f, p, len)
+ fsm *f;
+ u_char *p;
+ int len;
+{
+ ipcp_options *go = &ipcp_gotoptions[f->unit];
+ u_char cimaxslotindex, cicflag;
+ u_char citype, cilen, *next;
+ u_short cishort;
+ u_int32_t ciaddr1, ciaddr2, l, cidnsaddr;
+ ipcp_options no; /* options we've seen Naks for */
+ ipcp_options try; /* options to request next time */
+
+ BZERO(&no, sizeof(no));
+ try = *go;
+
+ /*
+ * Any Nak'd CIs must be in exactly the same order that we sent.
+ * Check packet length and CI length at each step.
+ * If we find any deviations, then this packet is bad.
+ */
+#define NAKCIADDR(opt, neg, old, code) \
+ if (go->neg && \
+ len >= (cilen = (old? CILEN_ADDRS: CILEN_ADDR)) && \
+ p[1] == cilen && \
+ p[0] == opt) { \
+ len -= cilen; \
+ INCPTR(2, p); \
+ GETLONG(l, p); \
+ ciaddr1 = htonl(l); \
+ if (old) { \
+ GETLONG(l, p); \
+ ciaddr2 = htonl(l); \
+ no.old_addrs = 1; \
+ } else \
+ ciaddr2 = 0; \
+ no.neg = 1; \
+ code \
+ }
+
+#define NAKCIVJ(opt, neg, code) \
+ if (go->neg && \
+ ((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \
+ len >= cilen && \
+ p[0] == opt) { \
+ len -= cilen; \
+ INCPTR(2, p); \
+ GETSHORT(cishort, p); \
+ no.neg = 1; \
+ code \
+ }
+
+#define NAKCIDNS(opt, neg, code) \
+ if (go->neg && \
+ ((cilen = p[1]) == CILEN_ADDR) && \
+ len >= cilen && \
+ p[0] == opt) { \
+ len -= cilen; \
+ INCPTR(2, p); \
+ GETLONG(l, p); \
+ cidnsaddr = htonl(l); \
+ no.neg = 1; \
+ code \
+ }
+
+ /*
+ * Accept the peer's idea of {our,his} address, if different
+ * from our idea, only if the accept_{local,remote} flag is set.
+ */
+ NAKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, go->old_addrs,
+ if (go->accept_local && ciaddr1) { /* Do we know our address? */
+ try.ouraddr = ciaddr1;
+ }
+ if (go->accept_remote && ciaddr2) { /* Does he know his? */
+ try.hisaddr = ciaddr2;
+ }
+ );
+
+ /*
+ * Accept the peer's value of maxslotindex provided that it
+ * is less than what we asked for. Turn off slot-ID compression
+ * if the peer wants. Send old-style compress-type option if
+ * the peer wants.
+ */
+ NAKCIVJ(CI_COMPRESSTYPE, neg_vj,
+ if (cilen == CILEN_VJ) {
+ GETCHAR(cimaxslotindex, p);
+ GETCHAR(cicflag, p);
+ if (cishort == IPCP_VJ_COMP) {
+ try.old_vj = 0;
+ if (cimaxslotindex < go->maxslotindex)
+ try.maxslotindex = cimaxslotindex;
+ if (!cicflag)
+ try.cflag = 0;
+ } else {
+ try.neg_vj = 0;
+ }
+ } else {
+ if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) {
+ try.old_vj = 1;
+ try.vj_protocol = cishort;
+ } else {
+ try.neg_vj = 0;
+ }
+ }
+ );
+
+ NAKCIDNS(CI_MS_DNS1, req_dns1,
+ try.dnsaddr[0] = cidnsaddr;
+ );
+
+ NAKCIDNS(CI_MS_DNS2, req_dns2,
+ try.dnsaddr[1] = cidnsaddr;
+ );
+
+ /*
+ * There may be remaining CIs, if the peer is requesting negotiation
+ * on an option that we didn't include in our request packet.
+ * If they want to negotiate about IP addresses, we comply.
+ * If they want us to ask for compression, we refuse.
+ */
+ while (len > CILEN_VOID) {
+ GETCHAR(citype, p);
+ GETCHAR(cilen, p);
+ if( (len -= cilen) < 0 )
+ goto bad;
+ next = p + cilen - 2;
+
+ switch (citype) {
+ case CI_COMPRESSTYPE:
+ if (go->neg_vj || no.neg_vj ||
+ (cilen != CILEN_VJ && cilen != CILEN_COMPRESS))
+ goto bad;
+ no.neg_vj = 1;
+ break;
+ case CI_ADDRS:
+ if ((go->neg_addr && go->old_addrs) || no.old_addrs
+ || cilen != CILEN_ADDRS)
+ goto bad;
+ try.neg_addr = 1;
+ try.old_addrs = 1;
+ GETLONG(l, p);
+ ciaddr1 = htonl(l);
+ if (ciaddr1 && go->accept_local)
+ try.ouraddr = ciaddr1;
+ GETLONG(l, p);
+ ciaddr2 = htonl(l);
+ if (ciaddr2 && go->accept_remote)
+ try.hisaddr = ciaddr2;
+ no.old_addrs = 1;
+ break;
+ case CI_ADDR:
+ if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR)
+ goto bad;
+ try.old_addrs = 0;
+ GETLONG(l, p);
+ ciaddr1 = htonl(l);
+ if (ciaddr1 && go->accept_local)
+ try.ouraddr = ciaddr1;
+ if (try.ouraddr != 0)
+ try.neg_addr = 1;
+ no.neg_addr = 1;
+ break;
+ }
+ p = next;
+ }
+
+ /*
+ * OK, the Nak is good. Now we can update state.
+ * If there are any remaining options, we ignore them.
+ */
+ if (f->state != OPENED)
+ *go = try;
+
+ return 1;
+
+bad:
+ IPCPDEBUG(("ipcp_nakci: received bad Nak!"));
+ return 0;
+}
+
+
+/*
+ * ipcp_rejci - Reject some of our CIs.
+ * Callback from fsm_rconfnakrej.
+ */
+static int
+ipcp_rejci(f, p, len)
+ fsm *f;
+ u_char *p;
+ int len;
+{
+ ipcp_options *go = &ipcp_gotoptions[f->unit];
+ u_char cimaxslotindex, ciflag, cilen;
+ u_short cishort;
+ u_int32_t cilong;
+ ipcp_options try; /* options to request next time */
+
+ try = *go;
+ /*
+ * Any Rejected CIs must be in exactly the same order that we sent.
+ * Check packet length and CI length at each step.
+ * If we find any deviations, then this packet is bad.
+ */
+#define REJCIADDR(opt, neg, old, val1, val2) \
+ if (go->neg && \
+ len >= (cilen = old? CILEN_ADDRS: CILEN_ADDR) && \
+ p[1] == cilen && \
+ p[0] == opt) { \
+ u_int32_t l; \
+ len -= cilen; \
+ INCPTR(2, p); \
+ GETLONG(l, p); \
+ cilong = htonl(l); \
+ /* Check rejected value. */ \
+ if (cilong != val1) \
+ goto bad; \
+ if (old) { \
+ GETLONG(l, p); \
+ cilong = htonl(l); \
+ /* Check rejected value. */ \
+ if (cilong != val2) \
+ goto bad; \
+ } \
+ try.neg = 0; \
+ }
+
+#define REJCIVJ(opt, neg, val, old, maxslot, cflag) \
+ if (go->neg && \
+ p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \
+ len >= p[1] && \
+ p[0] == opt) { \
+ len -= p[1]; \
+ INCPTR(2, p); \
+ GETSHORT(cishort, p); \
+ /* Check rejected value. */ \
+ if (cishort != val) \
+ goto bad; \
+ if (!old) { \
+ GETCHAR(cimaxslotindex, p); \
+ if (cimaxslotindex != maxslot) \
+ goto bad; \
+ GETCHAR(ciflag, p); \
+ if (ciflag != cflag) \
+ goto bad; \
+ } \
+ try.neg = 0; \
+ }
+
+#define REJCIDNS(opt, neg, dnsaddr) \
+ if (go->neg && \
+ ((cilen = p[1]) == CILEN_ADDR) && \
+ len >= cilen && \
+ p[0] == opt) { \
+ u_int32_t l; \
+ len -= cilen; \
+ INCPTR(2, p); \
+ GETLONG(l, p); \
+ cilong = htonl(l); \
+ /* Check rejected value. */ \
+ if (cilong != dnsaddr) \
+ goto bad; \
+ try.neg = 0; \
+ }
+
+
+ REJCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr,
+ go->old_addrs, go->ouraddr, go->hisaddr);
+
+ REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj,
+ go->maxslotindex, go->cflag);
+
+ REJCIDNS(CI_MS_DNS1, req_dns1, go->dnsaddr[0]);
+
+ REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]);
+
+ /*
+ * If there are any remaining CIs, then this packet is bad.
+ */
+ if (len != 0)
+ goto bad;
+ /*
+ * Now we can update state.
+ */
+ if (f->state != OPENED)
+ *go = try;
+ return 1;
+
+bad:
+ IPCPDEBUG(("ipcp_rejci: received bad Reject!"));
+ return 0;
+}
+
+
+/*
+ * ipcp_reqci - Check the peer's requested CIs and send appropriate response.
+ * Callback from fsm_rconfreq, Receive Configure Request
+ *
+ * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
+ * appropriately. If reject_if_disagree is non-zero, doesn't return
+ * CONFNAK; returns CONFREJ if it can't return CONFACK.
+ */
+static int
+ipcp_reqci(f, inp, len, reject_if_disagree)
+ fsm *f;
+ u_char *inp; /* Requested CIs */
+ int *len; /* Length of requested CIs */
+ int reject_if_disagree;
+{
+ ipcp_options *wo = &ipcp_wantoptions[f->unit];
+ ipcp_options *ho = &ipcp_hisoptions[f->unit];
+ ipcp_options *ao = &ipcp_allowoptions[f->unit];
+ ipcp_options *go = &ipcp_gotoptions[f->unit];
+ u_char *cip, *next; /* Pointer to current and next CIs */
+ u_short cilen, citype; /* Parsed len, type */
+ u_short cishort; /* Parsed short value */
+ u_int32_t tl, ciaddr1, ciaddr2;/* Parsed address values */
+ int rc = CONFACK; /* Final packet return code */
+ int orc; /* Individual option return code */
+ u_char *p; /* Pointer to next char to parse */
+ u_char *ucp = inp; /* Pointer to current output char */
+ int l = *len; /* Length left */
+ u_char maxslotindex, cflag;
+ int d;
+
+ /*
+ * Reset all his options.
+ */
+ BZERO(ho, sizeof(*ho));
+
+ /*
+ * Process all his options.
+ */
+ next = inp;
+ while (l) {
+ orc = CONFACK; /* Assume success */
+ cip = p = next; /* Remember begining of CI */
+ if (l < 2 || /* Not enough data for CI header or */
+ p[1] < 2 || /* CI length too small or */
+ p[1] > l) { /* CI length too big? */
+ IPCPDEBUG(("ipcp_reqci: bad CI length!"));
+ orc = CONFREJ; /* Reject bad CI */
+ cilen = l; /* Reject till end of packet */
+ l = 0; /* Don't loop again */
+ goto endswitch;
+ }
+ GETCHAR(citype, p); /* Parse CI type */
+ GETCHAR(cilen, p); /* Parse CI length */
+ l -= cilen; /* Adjust remaining length */
+ next += cilen; /* Step to next CI */
+
+ switch (citype) { /* Check CI type */
+ case CI_ADDRS:
+ if (!ao->neg_addr ||
+ cilen != CILEN_ADDRS) { /* Check CI length */
+ orc = CONFREJ; /* Reject CI */
+ break;
+ }
+
+ /*
+ * If he has no address, or if we both have his address but
+ * disagree about it, then NAK it with our idea.
+ * In particular, if we don't know his address, but he does,
+ * then accept it.
+ */
+ GETLONG(tl, p); /* Parse source address (his) */
+ ciaddr1 = htonl(tl);
+ if (ciaddr1 != wo->hisaddr
+ && (ciaddr1 == 0 || !wo->accept_remote)) {
+ orc = CONFNAK;
+ if (!reject_if_disagree) {
+ DECPTR(sizeof(u_int32_t), p);
+ tl = ntohl(wo->hisaddr);
+ PUTLONG(tl, p);
+ }
+ } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
+ /*
+ * If neither we nor he knows his address, reject the option.
+ */
+ orc = CONFREJ;
+ wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */
+ break;
+ }
+
+ /*
+ * If he doesn't know our address, or if we both have our address
+ * but disagree about it, then NAK it with our idea.
+ */
+ GETLONG(tl, p); /* Parse desination address (ours) */
+ ciaddr2 = htonl(tl);
+ if (ciaddr2 != wo->ouraddr) {
+ if (ciaddr2 == 0 || !wo->accept_local) {
+ orc = CONFNAK;
+ if (!reject_if_disagree) {
+ DECPTR(sizeof(u_int32_t), p);
+ tl = ntohl(wo->ouraddr);
+ PUTLONG(tl, p);
+ }
+ } else {
+ go->ouraddr = ciaddr2; /* accept peer's idea */
+ }
+ }
+
+ ho->neg_addr = 1;
+ ho->old_addrs = 1;
+ ho->hisaddr = ciaddr1;
+ ho->ouraddr = ciaddr2;
+ break;
+
+ case CI_ADDR:
+ if (!ao->neg_addr ||
+ cilen != CILEN_ADDR) { /* Check CI length */
+ orc = CONFREJ; /* Reject CI */
+ break;
+ }
+
+ /*
+ * If he has no address, or if we both have his address but
+ * disagree about it, then NAK it with our idea.
+ * In particular, if we don't know his address, but he does,
+ * then accept it.
+ */
+ GETLONG(tl, p); /* Parse source address (his) */
+ ciaddr1 = htonl(tl);
+ if (ciaddr1 != wo->hisaddr
+ && (ciaddr1 == 0 || !wo->accept_remote)) {
+ orc = CONFNAK;
+ if (!reject_if_disagree) {
+ DECPTR(sizeof(u_int32_t), p);
+ tl = ntohl(wo->hisaddr);
+ PUTLONG(tl, p);
+ }
+ } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
+ /*
+ * Don't ACK an address of 0.0.0.0 - reject it instead.
+ */
+ orc = CONFREJ;
+ wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */
+ break;
+ }
+
+ ho->neg_addr = 1;
+ ho->hisaddr = ciaddr1;
+ break;
+
+ case CI_MS_DNS1:
+ case CI_MS_DNS2:
+ /* Microsoft primary or secondary DNS request */
+ d = citype == CI_MS_DNS2;
+
+ /* If we do not have a DNS address then we cannot send it */
+ if (ao->dnsaddr[d] == 0 ||
+ cilen != CILEN_ADDR) { /* Check CI length */
+ orc = CONFREJ; /* Reject CI */
+ break;
+ }
+ GETLONG(tl, p);
+ if (htonl(tl) != ao->dnsaddr[d]) {
+ DECPTR(sizeof(u_int32_t), p);
+ tl = ntohl(ao->dnsaddr[d]);
+ PUTLONG(tl, p);
+ orc = CONFNAK;
+ }
+ break;
+
+ case CI_MS_WINS1:
+ case CI_MS_WINS2:
+ /* Microsoft primary or secondary WINS request */
+ d = citype == CI_MS_WINS2;
+
+ /* If we do not have a DNS address then we cannot send it */
+ if (ao->winsaddr[d] == 0 ||
+ cilen != CILEN_ADDR) { /* Check CI length */
+ orc = CONFREJ; /* Reject CI */
+ break;
+ }
+ GETLONG(tl, p);
+ if (htonl(tl) != ao->winsaddr[d]) {
+ DECPTR(sizeof(u_int32_t), p);
+ tl = ntohl(ao->winsaddr[d]);
+ PUTLONG(tl, p);
+ orc = CONFNAK;
+ }
+ break;
+
+ case CI_COMPRESSTYPE:
+ if (!ao->neg_vj ||
+ (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) {
+ orc = CONFREJ;
+ break;
+ }
+ GETSHORT(cishort, p);
+
+ if (!(cishort == IPCP_VJ_COMP ||
+ (cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) {
+ orc = CONFREJ;
+ break;
+ }
+
+ ho->neg_vj = 1;
+ ho->vj_protocol = cishort;
+ if (cilen == CILEN_VJ) {
+ GETCHAR(maxslotindex, p);
+ if (maxslotindex > ao->maxslotindex) {
+ orc = CONFNAK;
+ if (!reject_if_disagree){
+ DECPTR(1, p);
+ PUTCHAR(ao->maxslotindex, p);
+ }
+ }
+ GETCHAR(cflag, p);
+ if (cflag && !ao->cflag) {
+ orc = CONFNAK;
+ if (!reject_if_disagree){
+ DECPTR(1, p);
+ PUTCHAR(wo->cflag, p);
+ }
+ }
+ ho->maxslotindex = maxslotindex;
+ ho->cflag = cflag;
+ } else {
+ ho->old_vj = 1;
+ ho->maxslotindex = MAX_STATES - 1;
+ ho->cflag = 1;
+ }
+ break;
+
+ default:
+ orc = CONFREJ;
+ break;
+ }
+endswitch:
+ if (orc == CONFACK && /* Good CI */
+ rc != CONFACK) /* but prior CI wasnt? */
+ continue; /* Don't send this one */
+
+ if (orc == CONFNAK) { /* Nak this CI? */
+ if (reject_if_disagree) /* Getting fed up with sending NAKs? */
+ orc = CONFREJ; /* Get tough if so */
+ else {
+ if (rc == CONFREJ) /* Rejecting prior CI? */
+ continue; /* Don't send this one */
+ if (rc == CONFACK) { /* Ack'd all prior CIs? */
+ rc = CONFNAK; /* Not anymore... */
+ ucp = inp; /* Backup */
+ }
+ }
+ }
+
+ if (orc == CONFREJ && /* Reject this CI */
+ rc != CONFREJ) { /* but no prior ones? */
+ rc = CONFREJ;
+ ucp = inp; /* Backup */
+ }
+
+ /* Need to move CI? */
+ if (ucp != cip)
+ BCOPY(cip, ucp, cilen); /* Move it */
+
+ /* Update output pointer */
+ INCPTR(cilen, ucp);
+ }
+
+ /*
+ * If we aren't rejecting this packet, and we want to negotiate
+ * their address, and they didn't send their address, then we
+ * send a NAK with a CI_ADDR option appended. We assume the
+ * input buffer is long enough that we can append the extra
+ * option safely.
+ */
+ if (rc != CONFREJ && !ho->neg_addr &&
+ wo->req_addr && !reject_if_disagree) {
+ if (rc == CONFACK) {
+ rc = CONFNAK;
+ ucp = inp; /* reset pointer */
+ wo->req_addr = 0; /* don't ask again */
+ }
+ PUTCHAR(CI_ADDR, ucp);
+ PUTCHAR(CILEN_ADDR, ucp);
+ tl = ntohl(wo->hisaddr);
+ PUTLONG(tl, ucp);
+ }
+
+ *len = ucp - inp; /* Compute output length */
+ IPCPDEBUG(("ipcp: returning Configure-%s", CODENAME(rc)));
+ return (rc); /* Return final code */
+}
+
+
+/*
+ * ip_check_options - check that any IP-related options are OK,
+ * and assign appropriate defaults.
+ */
+static void
+ip_check_options()
+{
+ struct hostent *hp;
+ u_int32_t local;
+ ipcp_options *wo = &ipcp_wantoptions[0];
+
+ /*
+ * Default our local IP address based on our hostname.
+ * If local IP address already given, don't bother.
+ */
+ if (wo->ouraddr == 0) {
+ /*
+ * Look up our hostname (possibly with domain name appended)
+ * and take the first IP address as our local IP address.
+ * If there isn't an IP address for our hostname, too bad.
+ */
+ wo->accept_local = 1; /* don't insist on this default value */
+ if ((hp = gethostbyname(hostname)) != NULL) {
+ local = *(u_int32_t *)hp->h_addr;
+ if (local != 0 && !bad_ip_adrs(local))
+ wo->ouraddr = local;
+ }
+ }
+}
+
+
+/*
+ * ip_demand_conf - configure the interface as though
+ * IPCP were up, for use with dial-on-demand.
+ */
+static int
+ip_demand_conf(u)
+ int u;
+{
+ ipcp_options *wo = &ipcp_wantoptions[u];
+
+ if (wo->hisaddr == 0) {
+ /* make up an arbitrary address for the peer */
+ wo->hisaddr = htonl(0x0a707070 + pppifunit);
+ wo->accept_remote = 1;
+ }
+ if (wo->ouraddr == 0) {
+ /* make up an arbitrary address for us */
+ wo->ouraddr = htonl(0x0a404040 + pppifunit);
+ wo->accept_local = 1;
+ disable_defaultip = 1; /* don't tell the peer this address */
+ }
+ if (!sifaddr(u, wo->ouraddr, wo->hisaddr, GetMask(wo->ouraddr)))
+ return 0;
+ if (!sifup(u))
+ return 0;
+ if (!sifnpmode(u, PPP_IP, NPMODE_QUEUE))
+ return 0;
+ if (wo->default_route)
+ if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr))
+ default_route_set[u] = 1;
+ if (wo->proxy_arp)
+ if (sifproxyarp(u, wo->hisaddr))
+ proxy_arp_set[u] = 1;
+
+ notice("local IP address %I", wo->ouraddr);
+ notice("remote IP address %I", wo->hisaddr);
+
+ return 1;
+}
+
+
+/*
+ * ipcp_up - IPCP has come UP.
+ *
+ * Configure the IP network interface appropriately and bring it up.
+ */
+static void
+ipcp_up(f)
+ fsm *f;
+{
+ u_int32_t mask;
+ ipcp_options *ho = &ipcp_hisoptions[f->unit];
+ ipcp_options *go = &ipcp_gotoptions[f->unit];
+ ipcp_options *wo = &ipcp_wantoptions[f->unit];
+
+ IPCPDEBUG(("ipcp: up"));
+
+ /*
+ * We must have a non-zero IP address for both ends of the link.
+ */
+ if (!ho->neg_addr)
+ ho->hisaddr = wo->hisaddr;
+
+ if (ho->hisaddr == 0) {
+ error("Could not determine remote IP address");
+ ipcp_close(f->unit, "Could not determine remote IP address");
+ return;
+ }
+ if (go->ouraddr == 0) {
+ error("Could not determine local IP address");
+ ipcp_close(f->unit, "Could not determine local IP address");
+ return;
+ }
+
+ if (usepeerdns && (go->dnsaddr[0] || go->dnsaddr[1])) {
+ create_resolv(go->dnsaddr[0], go->dnsaddr[1]);
+ }
+
+ /*
+ * Check that the peer is allowed to use the IP address it wants.
+ */
+ if (!auth_ip_addr(f->unit, ho->hisaddr)) {
+ error("Peer is not authorized to use remote address %I", ho->hisaddr);
+ ipcp_close(f->unit, "Unauthorized remote IP address");
+ return;
+ }
+
+ /* set tcp compression */
+ sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex);
+
+ /*
+ * If we are doing dial-on-demand, the interface is already
+ * configured, so we put out any saved-up packets, then set the
+ * interface to pass IP packets.
+ */
+ if (demand) {
+ if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) {
+ ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr);
+ if (go->ouraddr != wo->ouraddr) {
+ warn("Local IP address changed to %I", go->ouraddr);
+ wo->ouraddr = go->ouraddr;
+ }
+ if (ho->hisaddr != wo->hisaddr) {
+ warn("Remote IP address changed to %I", ho->hisaddr);
+ wo->hisaddr = ho->hisaddr;
+ }
+
+ /* Set the interface to the new addresses */
+ mask = GetMask(go->ouraddr);
+ if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
+ if (debug)
+ warn("Interface configuration failed");
+ ipcp_close(f->unit, "Interface configuration failed");
+ return;
+ }
+
+ /* assign a default route through the interface if required */
+ if (ipcp_wantoptions[f->unit].default_route)
+ if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
+ default_route_set[f->unit] = 1;
+
+ /* Make a proxy ARP entry if requested. */
+ if (ipcp_wantoptions[f->unit].proxy_arp)
+ if (sifproxyarp(f->unit, ho->hisaddr))
+ proxy_arp_set[f->unit] = 1;
+
+ }
+ demand_rexmit(PPP_IP);
+ sifnpmode(f->unit, PPP_IP, NPMODE_PASS);
+
+ } else {
+ /*
+ * Set IP addresses and (if specified) netmask.
+ */
+ mask = GetMask(go->ouraddr);
+
+#if !(defined(SVR4) && (defined(SNI) || defined(__USLC__)))
+ if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
+ if (debug)
+ warn("Interface configuration failed");
+ ipcp_close(f->unit, "Interface configuration failed");
+ return;
+ }
+#endif
+
+ /* bring the interface up for IP */
+ if (!sifup(f->unit)) {
+ if (debug)
+ warn("Interface failed to come up");
+ ipcp_close(f->unit, "Interface configuration failed");
+ return;
+ }
+
+#if (defined(SVR4) && (defined(SNI) || defined(__USLC__)))
+ if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
+ if (debug)
+ warn("Interface configuration failed");
+ ipcp_close(f->unit, "Interface configuration failed");
+ return;
+ }
+#endif
+ sifnpmode(f->unit, PPP_IP, NPMODE_PASS);
+
+ /* assign a default route through the interface if required */
+ if (ipcp_wantoptions[f->unit].default_route)
+ if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
+ default_route_set[f->unit] = 1;
+
+ /* Make a proxy ARP entry if requested. */
+ if (ipcp_wantoptions[f->unit].proxy_arp)
+ if (sifproxyarp(f->unit, ho->hisaddr))
+ proxy_arp_set[f->unit] = 1;
+
+ ipcp_wantoptions[0].ouraddr = go->ouraddr;
+
+ notice("local IP address %I", go->ouraddr);
+ notice("remote IP address %I", ho->hisaddr);
+ if (go->dnsaddr[0])
+ notice("primary DNS address %I", go->dnsaddr[0]);
+ if (go->dnsaddr[1])
+ notice("secondary DNS address %I", go->dnsaddr[1]);
+ }
+
+ np_up(f->unit, PPP_IP);
+ ipcp_is_up = 1;
+
+ if (ip_up_hook)
+ ip_up_hook();
+}
+
+
+/*
+ * ipcp_down - IPCP has gone DOWN.
+ *
+ * Take the IP network interface down, clear its addresses
+ * and delete routes through it.
+ */
+static void
+ipcp_down(f)
+ fsm *f;
+{
+ IPCPDEBUG(("ipcp: down"));
+ /* XXX a bit IPv4-centric here, we only need to get the stats
+ * before the interface is marked down. */
+ update_link_stats(f->unit);
+ if (ip_down_hook)
+ ip_down_hook();
+ if (ipcp_is_up) {
+ ipcp_is_up = 0;
+ np_down(f->unit, PPP_IP);
+ }
+ sifvjcomp(f->unit, 0, 0, 0);
+
+ /*
+ * If we are doing dial-on-demand, set the interface
+ * to queue up outgoing packets (for now).
+ */
+ if (demand) {
+ sifnpmode(f->unit, PPP_IP, NPMODE_QUEUE);
+ } else {
+ sifnpmode(f->unit, PPP_IP, NPMODE_DROP);
+ sifdown(f->unit);
+ ipcp_clear_addrs(f->unit, ipcp_gotoptions[f->unit].ouraddr,
+ ipcp_hisoptions[f->unit].hisaddr);
+ }
+}
+
+
+/*
+ * ipcp_clear_addrs() - clear the interface addresses, routes,
+ * proxy arp entries, etc.
+ */
+static void
+ipcp_clear_addrs(unit, ouraddr, hisaddr)
+ int unit;
+ u_int32_t ouraddr; /* local address */
+ u_int32_t hisaddr; /* remote address */
+{
+ if (proxy_arp_set[unit]) {
+ cifproxyarp(unit, hisaddr);
+ proxy_arp_set[unit] = 0;
+ }
+ if (default_route_set[unit]) {
+ cifdefaultroute(unit, ouraddr, hisaddr);
+ default_route_set[unit] = 0;
+ }
+ cifaddr(unit, ouraddr, hisaddr);
+}
+
+
+/*
+ * ipcp_finished - possibly shut down the lower layers.
+ */
+static void
+ipcp_finished(f)
+ fsm *f;
+{
+ np_finished(f->unit, PPP_IP);
+}
+
+/*
+ * create_resolv - create the replacement resolv.conf file
+ */
+static void
+create_resolv(peerdns1, peerdns2)
+ u_int32_t peerdns1, peerdns2;
+{
+ extern int rtems_bsdnet_nameserver_count;
+ extern struct in_addr rtems_bsdnet_nameserver[];
+
+ /* initialize values */
+ rtems_bsdnet_nameserver_count = (int)0;
+
+ /* check to see if primary was specified */
+ if ( peerdns1 ) {
+ rtems_bsdnet_nameserver[rtems_bsdnet_nameserver_count].s_addr = peerdns1;
+ rtems_bsdnet_nameserver_count++;
+ }
+
+ /* check to see if secondary was specified */
+ if ( peerdns2 ) {
+ rtems_bsdnet_nameserver[rtems_bsdnet_nameserver_count].s_addr = peerdns2;
+ rtems_bsdnet_nameserver_count++;
+ }
+
+ /* initialize resolver */
+ __res_init();
+}
+
+/*
+ * ipcp_printpkt - print the contents of an IPCP packet.
+ */
+static char *ipcp_codenames[] = {
+ "ConfReq", "ConfAck", "ConfNak", "ConfRej",
+ "TermReq", "TermAck", "CodeRej"
+};
+
+static int
+ipcp_printpkt(p, plen, printer, arg)
+ u_char *p;
+ int plen;
+ void (*printer) __P((void *, char *, ...));
+ void *arg;
+{
+ int code, id, len, olen;
+ u_char *pstart, *optend;
+ u_short cishort;
+ u_int32_t cilong;
+
+ if (plen < HEADERLEN)
+ return 0;
+ pstart = p;
+ GETCHAR(code, p);
+ GETCHAR(id, p);
+ GETSHORT(len, p);
+ if (len < HEADERLEN || len > plen)
+ return 0;
+
+ if (code >= 1 && code <= sizeof(ipcp_codenames) / sizeof(char *))
+ printer(arg, " %s", ipcp_codenames[code-1]);
+ else
+ printer(arg, " code=0x%x", code);
+ printer(arg, " id=0x%x", id);
+ len -= HEADERLEN;
+ switch (code) {
+ case CONFREQ:
+ case CONFACK:
+ case CONFNAK:
+ case CONFREJ:
+ /* print option list */
+ while (len >= 2) {
+ GETCHAR(code, p);
+ GETCHAR(olen, p);
+ p -= 2;
+ if (olen < 2 || olen > len) {
+ break;
+ }
+ printer(arg, " <");
+ len -= olen;
+ optend = p + olen;
+ switch (code) {
+ case CI_ADDRS:
+ if (olen == CILEN_ADDRS) {
+ p += 2;
+ GETLONG(cilong, p);
+ printer(arg, "addrs %I", htonl(cilong));
+ GETLONG(cilong, p);
+ printer(arg, " %I", htonl(cilong));
+ }
+ break;
+ case CI_COMPRESSTYPE:
+ if (olen >= CILEN_COMPRESS) {
+ p += 2;
+ GETSHORT(cishort, p);
+ printer(arg, "compress ");
+ switch (cishort) {
+ case IPCP_VJ_COMP:
+ printer(arg, "VJ");
+ break;
+ case IPCP_VJ_COMP_OLD:
+ printer(arg, "old-VJ");
+ break;
+ default:
+ printer(arg, "0x%x", cishort);
+ }
+ }
+ break;
+ case CI_ADDR:
+ if (olen == CILEN_ADDR) {
+ p += 2;
+ GETLONG(cilong, p);
+ printer(arg, "addr %I", htonl(cilong));
+ }
+ break;
+ case CI_MS_DNS1:
+ case CI_MS_DNS2:
+ p += 2;
+ GETLONG(cilong, p);
+ printer(arg, "ms-dns%d %I", code - CI_MS_DNS1 + 1,
+ htonl(cilong));
+ break;
+ case CI_MS_WINS1:
+ case CI_MS_WINS2:
+ p += 2;
+ GETLONG(cilong, p);
+ printer(arg, "ms-wins %I", htonl(cilong));
+ break;
+ }
+ while (p < optend) {
+ GETCHAR(code, p);
+ printer(arg, " %.2x", code);
+ }
+ printer(arg, ">");
+ }
+ break;
+
+ case TERMACK:
+ case TERMREQ:
+ if (len > 0 && *p >= ' ' && *p < 0x7f) {
+ printer(arg, " ");
+ print_string(p, len, printer, arg);
+ p += len;
+ len = 0;
+ }
+ break;
+ }
+
+ /* print the rest of the bytes in the packet */
+ for (; len > 0; --len) {
+ GETCHAR(code, p);
+ printer(arg, " %.2x", code);
+ }
+
+ return p - pstart;
+}
+
+/*
+ * ip_active_pkt - see if this IP packet is worth bringing the link up for.
+ * We don't bring the link up for IP fragments or for TCP FIN packets
+ * with no data.
+ */
+#define IP_HDRLEN 20 /* bytes */
+#define IP_OFFMASK 0x1fff
+#define IPPROTO_TCP 6
+#define TCP_HDRLEN 20
+#define TH_FIN 0x01
+
+/*
+ * We use these macros because the IP header may be at an odd address,
+ * and some compilers might use word loads to get th_off or ip_hl.
+ */
+
+#define net_short(x) (((x)[0] << 8) + (x)[1])
+#define get_iphl(x) (((unsigned char *)(x))[0] & 0xF)
+#define get_ipoff(x) net_short((unsigned char *)(x) + 6)
+#define get_ipproto(x) (((unsigned char *)(x))[9])
+#define get_tcpoff(x) (((unsigned char *)(x))[12] >> 4)
+#define get_tcpflags(x) (((unsigned char *)(x))[13])
+
+static int
+ip_active_pkt(pkt, len)
+ u_char *pkt;
+ int len;
+{
+ u_char *tcp;
+ int hlen;
+
+ len -= PPP_HDRLEN;
+ pkt += PPP_HDRLEN;
+ if (len < IP_HDRLEN)
+ return 0;
+ if ((get_ipoff(pkt) & IP_OFFMASK) != 0)
+ return 0;
+ if (get_ipproto(pkt) != IPPROTO_TCP)
+ return 1;
+ hlen = get_iphl(pkt) * 4;
+ if (len < hlen + TCP_HDRLEN)
+ return 0;
+ tcp = pkt + hlen;
+ if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4)
+ return 0;
+ return 1;
+}
diff --git a/cpukit/pppd/ipcp.h b/cpukit/pppd/ipcp.h
new file mode 100644
index 0000000000..8c5aca861d
--- /dev/null
+++ b/cpukit/pppd/ipcp.h
@@ -0,0 +1,73 @@
+/*
+ * ipcp.h - IP Control Protocol definitions.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * $Id$
+ */
+
+/*
+ * Options.
+ */
+#define CI_ADDRS 1 /* IP Addresses */
+#define CI_COMPRESSTYPE 2 /* Compression Type */
+#define CI_ADDR 3
+
+#define CI_MS_DNS1 129 /* Primary DNS value */
+#define CI_MS_WINS1 130 /* Primary WINS value */
+#define CI_MS_DNS2 131 /* Secondary DNS value */
+#define CI_MS_WINS2 132 /* Secondary WINS value */
+
+#define MAX_STATES 16 /* from slcompress.h */
+
+#define IPCP_VJMODE_OLD 1 /* "old" mode (option # = 0x0037) */
+#define IPCP_VJMODE_RFC1172 2 /* "old-rfc"mode (option # = 0x002d) */
+#define IPCP_VJMODE_RFC1332 3 /* "new-rfc"mode (option # = 0x002d, */
+ /* maxslot and slot number compression) */
+
+#define IPCP_VJ_COMP 0x002d /* current value for VJ compression option*/
+#define IPCP_VJ_COMP_OLD 0x0037 /* "old" (i.e, broken) value for VJ */
+ /* compression option*/
+
+typedef struct ipcp_options {
+ bool neg_addr; /* Negotiate IP Address? */
+ bool old_addrs; /* Use old (IP-Addresses) option? */
+ bool req_addr; /* Ask peer to send IP address? */
+ bool default_route; /* Assign default route through interface? */
+ bool proxy_arp; /* Make proxy ARP entry for peer? */
+ bool neg_vj; /* Van Jacobson Compression? */
+ bool old_vj; /* use old (short) form of VJ option? */
+ bool accept_local; /* accept peer's value for ouraddr */
+ bool accept_remote; /* accept peer's value for hisaddr */
+ bool req_dns1; /* Ask peer to send primary DNS address? */
+ bool req_dns2; /* Ask peer to send secondary DNS address? */
+ int vj_protocol; /* protocol value to use in VJ option */
+ int maxslotindex; /* values for RFC1332 VJ compression neg. */
+ bool cflag;
+ u_int32_t ouraddr, hisaddr; /* Addresses in NETWORK BYTE ORDER */
+ u_int32_t dnsaddr[2]; /* Primary and secondary MS DNS entries */
+ u_int32_t winsaddr[2]; /* Primary and secondary MS WINS entries */
+} ipcp_options;
+
+extern fsm ipcp_fsm[];
+extern ipcp_options ipcp_wantoptions[];
+extern ipcp_options ipcp_gotoptions[];
+extern ipcp_options ipcp_allowoptions[];
+extern ipcp_options ipcp_hisoptions[];
+
+char *ip_ntoa __P((u_int32_t));
+
+extern struct protent ipcp_protent;
diff --git a/cpukit/pppd/ipxcp.c b/cpukit/pppd/ipxcp.c
new file mode 100644
index 0000000000..4e408a00f9
--- /dev/null
+++ b/cpukit/pppd/ipxcp.c
@@ -0,0 +1,1449 @@
+/*
+ * ipxcp.c - PPP IPX Control Protocol.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef IPX_CHANGE
+
+#define RCSID "$Id$"
+
+/*
+ * TODO:
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include "pppd.h"
+#include "fsm.h"
+#include "ipxcp.h"
+#include "pathnames.h"
+#include "magic.h"
+
+static const char rcsid[] = RCSID;
+
+/* global vars */
+ipxcp_options ipxcp_wantoptions[NUM_PPP]; /* Options that we want to request */
+ipxcp_options ipxcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */
+ipxcp_options ipxcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
+ipxcp_options ipxcp_hisoptions[NUM_PPP]; /* Options that we ack'd */
+
+#define wo (&ipxcp_wantoptions[0])
+#define ao (&ipxcp_allowoptions[0])
+#define go (&ipxcp_gotoptions[0])
+#define ho (&ipxcp_hisoptions[0])
+
+/*
+ * Callbacks for fsm code. (CI = Configuration Information)
+ */
+static void ipxcp_resetci __P((fsm *)); /* Reset our CI */
+static int ipxcp_cilen __P((fsm *)); /* Return length of our CI */
+static void ipxcp_addci __P((fsm *, u_char *, int *)); /* Add our CI */
+static int ipxcp_ackci __P((fsm *, u_char *, int)); /* Peer ack'd our CI */
+static int ipxcp_nakci __P((fsm *, u_char *, int)); /* Peer nak'd our CI */
+static int ipxcp_rejci __P((fsm *, u_char *, int)); /* Peer rej'd our CI */
+static int ipxcp_reqci __P((fsm *, u_char *, int *, int)); /* Rcv CI */
+static void ipxcp_up __P((fsm *)); /* We're UP */
+static void ipxcp_down __P((fsm *)); /* We're DOWN */
+static void ipxcp_finished __P((fsm *)); /* Don't need lower layer */
+
+fsm ipxcp_fsm[NUM_PPP]; /* IPXCP fsm structure */
+
+static fsm_callbacks ipxcp_callbacks = { /* IPXCP callback routines */
+ ipxcp_resetci, /* Reset our Configuration Information */
+ ipxcp_cilen, /* Length of our Configuration Information */
+ ipxcp_addci, /* Add our Configuration Information */
+ ipxcp_ackci, /* ACK our Configuration Information */
+ ipxcp_nakci, /* NAK our Configuration Information */
+ ipxcp_rejci, /* Reject our Configuration Information */
+ ipxcp_reqci, /* Request peer's Configuration Information */
+ ipxcp_up, /* Called when fsm reaches OPENED state */
+ ipxcp_down, /* Called when fsm leaves OPENED state */
+ NULL, /* Called when we want the lower layer up */
+ ipxcp_finished, /* Called when we want the lower layer down */
+ NULL, /* Called when Protocol-Reject received */
+ NULL, /* Retransmission is necessary */
+ NULL, /* Called to handle protocol-specific codes */
+ "IPXCP" /* String name of protocol */
+};
+
+/*
+ * Command-line options.
+ */
+static int setipxnode __P((char **));
+static int setipxname __P((char **));
+
+static option_t ipxcp_option_list[] = {
+ { "ipx", o_bool, &ipxcp_protent.enabled_flag,
+ "Enable IPXCP (and IPX)", 1 },
+ { "+ipx", o_bool, &ipxcp_protent.enabled_flag,
+ "Enable IPXCP (and IPX)", 1 },
+ { "noipx", o_bool, &ipxcp_protent.enabled_flag,
+ "Disable IPXCP (and IPX)" },
+ { "-ipx", o_bool, &ipxcp_protent.enabled_flag,
+ "Disable IPXCP (and IPX)" } ,
+ { "ipx-network", o_uint32, &ipxcp_wantoptions[0].our_network,
+ "Set our IPX network number", 0, &ipxcp_wantoptions[0].neg_nn },
+ { "ipxcp-accept-network", o_bool, &ipxcp_wantoptions[0].accept_network,
+ "Accept peer IPX network number", 1,
+ &ipxcp_allowoptions[0].accept_network },
+ { "ipx-node", o_special, setipxnode,
+ "Set IPX node number" },
+ { "ipxcp-accept-local", o_bool, &ipxcp_wantoptions[0].accept_local,
+ "Accept our IPX address", 1,
+ &ipxcp_allowoptions[0].accept_local },
+ { "ipxcp-accept-remote", o_bool, &ipxcp_wantoptions[0].accept_remote,
+ "Accept peer's IPX address", 1,
+ &ipxcp_allowoptions[0].accept_remote },
+ { "ipx-routing", o_int, &ipxcp_wantoptions[0].router,
+ "Set IPX routing proto number", 0,
+ &ipxcp_wantoptions[0].neg_router },
+ { "ipx-router-name", o_special, setipxname,
+ "Set IPX router name" },
+ { "ipxcp-restart", o_int, &ipxcp_fsm[0].timeouttime,
+ "Set timeout for IPXCP" },
+ { "ipxcp-max-terminate", o_int, &ipxcp_fsm[0].maxtermtransmits,
+ "Set max #xmits for IPXCP term-reqs" },
+ { "ipxcp-max-configure", o_int, &ipxcp_fsm[0].maxconfreqtransmits,
+ "Set max #xmits for IPXCP conf-reqs" },
+ { "ipxcp-max-failure", o_int, &ipxcp_fsm[0].maxnakloops,
+ "Set max #conf-naks for IPXCP" },
+ { NULL }
+};
+
+/*
+ * Protocol entry points.
+ */
+
+static void ipxcp_init __P((int));
+static void ipxcp_open __P((int));
+static void ipxcp_close __P((int, char *));
+static void ipxcp_lowerup __P((int));
+static void ipxcp_lowerdown __P((int));
+static void ipxcp_input __P((int, u_char *, int));
+static void ipxcp_protrej __P((int));
+static int ipxcp_printpkt __P((u_char *, int,
+ void (*) __P((void *, char *, ...)), void *));
+
+struct protent ipxcp_protent = {
+ PPP_IPXCP,
+ ipxcp_init,
+ ipxcp_input,
+ ipxcp_protrej,
+ ipxcp_lowerup,
+ ipxcp_lowerdown,
+ ipxcp_open,
+ ipxcp_close,
+ ipxcp_printpkt,
+ NULL,
+ 0,
+ "IPXCP",
+ "IPX",
+ ipxcp_option_list,
+ NULL,
+ NULL,
+ NULL
+};
+
+/*
+ * Lengths of configuration options.
+ */
+
+#define CILEN_VOID 2
+#define CILEN_COMPLETE 2 /* length of complete option */
+#define CILEN_NETN 6 /* network number length option */
+#define CILEN_NODEN 8 /* node number length option */
+#define CILEN_PROTOCOL 4 /* Minimum length of routing protocol */
+#define CILEN_NAME 3 /* Minimum length of router name */
+#define CILEN_COMPRESS 4 /* Minimum length of compression protocol */
+
+#define CODENAME(x) ((x) == CONFACK ? "ACK" : \
+ (x) == CONFNAK ? "NAK" : "REJ")
+
+static int ipxcp_is_up;
+
+static char *ipx_ntoa __P((u_int32_t));
+
+/* Used in printing the node number */
+#define NODE(base) base[0], base[1], base[2], base[3], base[4], base[5]
+
+/* Used to generate the proper bit mask */
+#define BIT(num) (1 << (num))
+
+/*
+ * Convert from internal to external notation
+ */
+
+static short int
+to_external(internal)
+short int internal;
+{
+ short int external;
+
+ if (internal & BIT(IPX_NONE) )
+ external = IPX_NONE;
+ else
+ external = RIP_SAP;
+
+ return external;
+}
+
+/*
+ * Make a string representation of a network IP address.
+ */
+
+static char *
+ipx_ntoa(ipxaddr)
+u_int32_t ipxaddr;
+{
+ static char b[64];
+ slprintf(b, sizeof(b), "%x", ipxaddr);
+ return b;
+}
+
+
+static u_char *
+setipxnodevalue(src,dst)
+u_char *src, *dst;
+{
+ int indx;
+ int item;
+
+ for (;;) {
+ if (!isxdigit (*src))
+ break;
+
+ for (indx = 0; indx < 5; ++indx) {
+ dst[indx] <<= 4;
+ dst[indx] |= (dst[indx + 1] >> 4) & 0x0F;
+ }
+
+ item = toupper (*src) - '0';
+ if (item > 9)
+ item -= 7;
+
+ dst[5] = (dst[5] << 4) | item;
+ ++src;
+ }
+ return src;
+}
+
+static int
+setipxnode(argv)
+ char **argv;
+{
+ char *end;
+
+ memset (&ipxcp_wantoptions[0].our_node[0], 0, 6);
+ memset (&ipxcp_wantoptions[0].his_node[0], 0, 6);
+
+ end = setipxnodevalue (*argv, &ipxcp_wantoptions[0].our_node[0]);
+ if (*end == ':')
+ end = setipxnodevalue (++end, &ipxcp_wantoptions[0].his_node[0]);
+
+ if (*end == '\0') {
+ ipxcp_wantoptions[0].neg_node = 1;
+ return 1;
+ }
+
+ option_error("invalid parameter '%s' for ipx-node option", *argv);
+ return 0;
+}
+
+static int
+setipxname (argv)
+ char **argv;
+{
+ char *dest = ipxcp_wantoptions[0].name;
+ char *src = *argv;
+ int count;
+ char ch;
+
+ ipxcp_wantoptions[0].neg_name = 1;
+ ipxcp_allowoptions[0].neg_name = 1;
+ memset (dest, '\0', sizeof (ipxcp_wantoptions[0].name));
+
+ count = 0;
+ while (*src) {
+ ch = *src++;
+ if (! isalnum (ch) && ch != '_') {
+ option_error("IPX router name must be alphanumeric or _");
+ return 0;
+ }
+
+ if (count >= sizeof (ipxcp_wantoptions[0].name)) {
+ option_error("IPX router name is limited to %d characters",
+ sizeof (ipxcp_wantoptions[0].name) - 1);
+ return 0;
+ }
+
+ dest[count++] = toupper (ch);
+ }
+
+ return 1;
+}
+
+/*
+ * ipxcp_init - Initialize IPXCP.
+ */
+static void
+ipxcp_init(unit)
+ int unit;
+{
+ fsm *f = &ipxcp_fsm[unit];
+
+ f->unit = unit;
+ f->protocol = PPP_IPXCP;
+ f->callbacks = &ipxcp_callbacks;
+ fsm_init(&ipxcp_fsm[unit]);
+
+ memset (wo->name, 0, sizeof (wo->name));
+ memset (wo->our_node, 0, sizeof (wo->our_node));
+ memset (wo->his_node, 0, sizeof (wo->his_node));
+
+ wo->neg_nn = 1;
+ wo->neg_complete = 1;
+ wo->network = 0;
+
+ ao->neg_node = 1;
+ ao->neg_nn = 1;
+ ao->neg_name = 1;
+ ao->neg_complete = 1;
+ ao->neg_router = 1;
+
+ ao->accept_local = 0;
+ ao->accept_remote = 0;
+ ao->accept_network = 0;
+
+ wo->tried_rip = 0;
+ wo->tried_nlsp = 0;
+}
+
+/*
+ * Copy the node number
+ */
+
+static void
+copy_node (src, dst)
+u_char *src, *dst;
+{
+ memcpy (dst, src, sizeof (ipxcp_wantoptions[0].our_node));
+}
+
+/*
+ * Compare node numbers
+ */
+
+static int
+compare_node (src, dst)
+u_char *src, *dst;
+{
+ return memcmp (dst, src, sizeof (ipxcp_wantoptions[0].our_node)) == 0;
+}
+
+/*
+ * Is the node number zero?
+ */
+
+static int
+zero_node (node)
+u_char *node;
+{
+ int indx;
+ for (indx = 0; indx < sizeof (ipxcp_wantoptions[0].our_node); ++indx)
+ if (node [indx] != 0)
+ return 0;
+ return 1;
+}
+
+/*
+ * Increment the node number
+ */
+
+static void
+inc_node (node)
+u_char *node;
+{
+ u_char *outp;
+ u_int32_t magic_num;
+
+ outp = node;
+ magic_num = magic();
+ *outp++ = '\0';
+ *outp++ = '\0';
+ PUTLONG (magic_num, outp);
+}
+
+/*
+ * ipxcp_open - IPXCP is allowed to come up.
+ */
+static void
+ipxcp_open(unit)
+ int unit;
+{
+ fsm_open(&ipxcp_fsm[unit]);
+}
+
+/*
+ * ipxcp_close - Take IPXCP down.
+ */
+static void
+ipxcp_close(unit, reason)
+ int unit;
+ char *reason;
+{
+ fsm_close(&ipxcp_fsm[unit], reason);
+}
+
+
+/*
+ * ipxcp_lowerup - The lower layer is up.
+ */
+static void
+ipxcp_lowerup(unit)
+ int unit;
+{
+ fsm_lowerup(&ipxcp_fsm[unit]);
+}
+
+
+/*
+ * ipxcp_lowerdown - The lower layer is down.
+ */
+static void
+ipxcp_lowerdown(unit)
+ int unit;
+{
+ fsm_lowerdown(&ipxcp_fsm[unit]);
+}
+
+
+/*
+ * ipxcp_input - Input IPXCP packet.
+ */
+static void
+ipxcp_input(unit, p, len)
+ int unit;
+ u_char *p;
+ int len;
+{
+ fsm_input(&ipxcp_fsm[unit], p, len);
+}
+
+
+/*
+ * ipxcp_protrej - A Protocol-Reject was received for IPXCP.
+ *
+ * Pretend the lower layer went down, so we shut up.
+ */
+static void
+ipxcp_protrej(unit)
+ int unit;
+{
+ fsm_lowerdown(&ipxcp_fsm[unit]);
+}
+
+
+/*
+ * ipxcp_resetci - Reset our CI.
+ */
+static void
+ipxcp_resetci(f)
+ fsm *f;
+{
+ wo->req_node = wo->neg_node && ao->neg_node;
+ wo->req_nn = wo->neg_nn && ao->neg_nn;
+
+ if (wo->our_network == 0) {
+ wo->neg_node = 1;
+ ao->accept_network = 1;
+ }
+/*
+ * If our node number is zero then change it.
+ */
+ if (zero_node (wo->our_node)) {
+ inc_node (wo->our_node);
+ ao->accept_local = 1;
+ wo->neg_node = 1;
+ }
+/*
+ * If his node number is zero then change it.
+ */
+ if (zero_node (wo->his_node)) {
+ inc_node (wo->his_node);
+ ao->accept_remote = 1;
+ }
+/*
+ * If no routing agent was specified then we do RIP/SAP according to the
+ * RFC documents. If you have specified something then OK. Otherwise, we
+ * do RIP/SAP.
+ */
+ if (ao->router == 0) {
+ ao->router |= BIT(RIP_SAP);
+ wo->router |= BIT(RIP_SAP);
+ }
+
+ /* Always specify a routing protocol unless it was REJected. */
+ wo->neg_router = 1;
+/*
+ * Start with these default values
+ */
+ *go = *wo;
+}
+
+/*
+ * ipxcp_cilen - Return length of our CI.
+ */
+
+static int
+ipxcp_cilen(f)
+ fsm *f;
+{
+ int len;
+
+ len = go->neg_nn ? CILEN_NETN : 0;
+ len += go->neg_node ? CILEN_NODEN : 0;
+ len += go->neg_name ? CILEN_NAME + strlen (go->name) - 1 : 0;
+
+ /* RFC says that defaults should not be included. */
+ if (go->neg_router && to_external(go->router) != RIP_SAP)
+ len += CILEN_PROTOCOL;
+
+ return (len);
+}
+
+
+/*
+ * ipxcp_addci - Add our desired CIs to a packet.
+ */
+static void
+ipxcp_addci(f, ucp, lenp)
+ fsm *f;
+ u_char *ucp;
+ int *lenp;
+{
+/*
+ * Add the options to the record.
+ */
+ if (go->neg_nn) {
+ PUTCHAR (IPX_NETWORK_NUMBER, ucp);
+ PUTCHAR (CILEN_NETN, ucp);
+ PUTLONG (go->our_network, ucp);
+ }
+
+ if (go->neg_node) {
+ int indx;
+ PUTCHAR (IPX_NODE_NUMBER, ucp);
+ PUTCHAR (CILEN_NODEN, ucp);
+ for (indx = 0; indx < sizeof (go->our_node); ++indx)
+ PUTCHAR (go->our_node[indx], ucp);
+ }
+
+ if (go->neg_name) {
+ int cilen = strlen (go->name);
+ int indx;
+ PUTCHAR (IPX_ROUTER_NAME, ucp);
+ PUTCHAR (CILEN_NAME + cilen - 1, ucp);
+ for (indx = 0; indx < cilen; ++indx)
+ PUTCHAR (go->name [indx], ucp);
+ }
+
+ if (go->neg_router) {
+ short external = to_external (go->router);
+ if (external != RIP_SAP) {
+ PUTCHAR (IPX_ROUTER_PROTOCOL, ucp);
+ PUTCHAR (CILEN_PROTOCOL, ucp);
+ PUTSHORT (external, ucp);
+ }
+ }
+}
+
+/*
+ * ipxcp_ackci - Ack our CIs.
+ *
+ * Returns:
+ * 0 - Ack was bad.
+ * 1 - Ack was good.
+ */
+static int
+ipxcp_ackci(f, p, len)
+ fsm *f;
+ u_char *p;
+ int len;
+{
+ u_short cilen, citype, cishort;
+ u_char cichar;
+ u_int32_t cilong;
+
+#define ACKCIVOID(opt, neg) \
+ if (neg) { \
+ if ((len -= CILEN_VOID) < 0) \
+ break; \
+ GETCHAR(citype, p); \
+ GETCHAR(cilen, p); \
+ if (cilen != CILEN_VOID || \
+ citype != opt) \
+ break; \
+ }
+
+#define ACKCICOMPLETE(opt,neg) ACKCIVOID(opt, neg)
+
+#define ACKCICHARS(opt, neg, val, cnt) \
+ if (neg) { \
+ int indx, count = cnt; \
+ len -= (count + 2); \
+ if (len < 0) \
+ break; \
+ GETCHAR(citype, p); \
+ GETCHAR(cilen, p); \
+ if (cilen != (count + 2) || \
+ citype != opt) \
+ break; \
+ for (indx = 0; indx < count; ++indx) {\
+ GETCHAR(cichar, p); \
+ if (cichar != ((u_char *) &val)[indx]) \
+ break; \
+ }\
+ if (indx != count) \
+ break; \
+ }
+
+#define ACKCINODE(opt,neg,val) ACKCICHARS(opt,neg,val,sizeof(val))
+#define ACKCINAME(opt,neg,val) ACKCICHARS(opt,neg,val,strlen(val))
+
+#define ACKCINETWORK(opt, neg, val) \
+ if (neg) { \
+ if ((len -= CILEN_NETN) < 0) \
+ break; \
+ GETCHAR(citype, p); \
+ GETCHAR(cilen, p); \
+ if (cilen != CILEN_NETN || \
+ citype != opt) \
+ break; \
+ GETLONG(cilong, p); \
+ if (cilong != val) \
+ break; \
+ }
+
+#define ACKCIPROTO(opt, neg, val) \
+ if (neg) { \
+ if (len < 2) \
+ break; \
+ GETCHAR(citype, p); \
+ GETCHAR(cilen, p); \
+ if (cilen != CILEN_PROTOCOL || citype != opt) \
+ break; \
+ len -= cilen; \
+ if (len < 0) \
+ break; \
+ GETSHORT(cishort, p); \
+ if (cishort != to_external (val) || cishort == RIP_SAP) \
+ break; \
+ }
+/*
+ * Process the ACK frame in the order in which the frame was assembled
+ */
+ do {
+ ACKCINETWORK (IPX_NETWORK_NUMBER, go->neg_nn, go->our_network);
+ ACKCINODE (IPX_NODE_NUMBER, go->neg_node, go->our_node);
+ ACKCINAME (IPX_ROUTER_NAME, go->neg_name, go->name);
+ if (len > 0)
+ ACKCIPROTO (IPX_ROUTER_PROTOCOL, go->neg_router, go->router);
+/*
+ * This is the end of the record.
+ */
+ if (len == 0)
+ return (1);
+ } while (0);
+/*
+ * The frame is invalid
+ */
+ IPXCPDEBUG(("ipxcp_ackci: received bad Ack!"));
+ return (0);
+}
+
+/*
+ * ipxcp_nakci - Peer has sent a NAK for some of our CIs.
+ * This should not modify any state if the Nak is bad
+ * or if IPXCP is in the OPENED state.
+ *
+ * Returns:
+ * 0 - Nak was bad.
+ * 1 - Nak was good.
+ */
+
+static int
+ipxcp_nakci(f, p, len)
+ fsm *f;
+ u_char *p;
+ int len;
+{
+ u_char citype, cilen, *next;
+ u_short s;
+ u_int32_t l;
+ ipxcp_options no; /* options we've seen Naks for */
+ ipxcp_options try; /* options to request next time */
+
+ BZERO(&no, sizeof(no));
+ try = *go;
+
+ while (len > CILEN_VOID) {
+ GETCHAR (citype, p);
+ GETCHAR (cilen, p);
+ len -= cilen;
+ if (len < 0)
+ goto bad;
+ next = &p [cilen - CILEN_VOID];
+
+ switch (citype) {
+ case IPX_NETWORK_NUMBER:
+ if (!go->neg_nn || no.neg_nn || (cilen != CILEN_NETN))
+ goto bad;
+ no.neg_nn = 1;
+
+ GETLONG(l, p);
+ if (l && ao->accept_network)
+ try.our_network = l;
+ break;
+
+ case IPX_NODE_NUMBER:
+ if (!go->neg_node || no.neg_node || (cilen != CILEN_NODEN))
+ goto bad;
+ no.neg_node = 1;
+
+ if (!zero_node (p) && ao->accept_local &&
+ ! compare_node (p, ho->his_node))
+ copy_node (p, try.our_node);
+ break;
+
+ /* This has never been sent. Ignore the NAK frame */
+ case IPX_COMPRESSION_PROTOCOL:
+ goto bad;
+
+ case IPX_ROUTER_PROTOCOL:
+ if (!go->neg_router || (cilen < CILEN_PROTOCOL))
+ goto bad;
+
+ GETSHORT (s, p);
+ if (s > 15) /* This is just bad, but ignore for now. */
+ break;
+
+ s = BIT(s);
+ if (no.router & s) /* duplicate NAKs are always bad */
+ goto bad;
+
+ if (no.router == 0) /* Reset on first NAK only */
+ try.router = 0;
+
+ no.router |= s;
+ try.router |= s;
+ try.neg_router = 1;
+ break;
+
+ /* These, according to the RFC, must never be NAKed. */
+ case IPX_ROUTER_NAME:
+ case IPX_COMPLETE:
+ goto bad;
+
+ /* These are for options which we have not seen. */
+ default:
+ break;
+ }
+ p = next;
+ }
+
+ /*
+ * Do not permit the peer to force a router protocol which we do not
+ * support. However, default to the condition that will accept "NONE".
+ */
+ try.router &= (ao->router | BIT(IPX_NONE));
+ if (try.router == 0 && ao->router != 0)
+ try.router = BIT(IPX_NONE);
+
+ if (try.router != 0)
+ try.neg_router = 1;
+
+ /*
+ * OK, the Nak is good. Now we can update state.
+ * If there are any options left, we ignore them.
+ */
+ if (f->state != OPENED)
+ *go = try;
+
+ return 1;
+
+bad:
+ IPXCPDEBUG(("ipxcp_nakci: received bad Nak!"));
+ return 0;
+}
+
+/*
+ * ipxcp_rejci - Reject some of our CIs.
+ */
+static int
+ipxcp_rejci(f, p, len)
+ fsm *f;
+ u_char *p;
+ int len;
+{
+ u_short cilen, citype, cishort;
+ u_char cichar;
+ u_int32_t cilong;
+ ipxcp_options try; /* options to request next time */
+
+#define REJCINETWORK(opt, neg, val) \
+ if (neg && p[0] == opt) { \
+ if ((len -= CILEN_NETN) < 0) \
+ break; \
+ GETCHAR(citype, p); \
+ GETCHAR(cilen, p); \
+ if (cilen != CILEN_NETN || \
+ citype != opt) \
+ break; \
+ GETLONG(cilong, p); \
+ if (cilong != val) \
+ break; \
+ neg = 0; \
+ }
+
+#define REJCICHARS(opt, neg, val, cnt) \
+ if (neg && p[0] == opt) { \
+ int indx, count = cnt; \
+ len -= (count + 2); \
+ if (len < 0) \
+ break; \
+ GETCHAR(citype, p); \
+ GETCHAR(cilen, p); \
+ if (cilen != (count + 2) || \
+ citype != opt) \
+ break; \
+ for (indx = 0; indx < count; ++indx) {\
+ GETCHAR(cichar, p); \
+ if (cichar != ((u_char *) &val)[indx]) \
+ break; \
+ }\
+ if (indx != count) \
+ break; \
+ neg = 0; \
+ }
+
+#define REJCINODE(opt,neg,val) REJCICHARS(opt,neg,val,sizeof(val))
+#define REJCINAME(opt,neg,val) REJCICHARS(opt,neg,val,strlen(val))
+
+#define REJCIVOID(opt, neg) \
+ if (neg && p[0] == opt) { \
+ if ((len -= CILEN_VOID) < 0) \
+ break; \
+ GETCHAR(citype, p); \
+ GETCHAR(cilen, p); \
+ if (cilen != CILEN_VOID || citype != opt) \
+ break; \
+ neg = 0; \
+ }
+
+/* a reject for RIP/SAP is invalid since we don't send it and you can't
+ reject something which is not sent. (You can NAK, but you can't REJ.) */
+#define REJCIPROTO(opt, neg, val, bit) \
+ if (neg && p[0] == opt) { \
+ if ((len -= CILEN_PROTOCOL) < 0) \
+ break; \
+ GETCHAR(citype, p); \
+ GETCHAR(cilen, p); \
+ if (cilen != CILEN_PROTOCOL) \
+ break; \
+ GETSHORT(cishort, p); \
+ if (cishort != to_external (val) || cishort == RIP_SAP) \
+ break; \
+ neg = 0; \
+ }
+/*
+ * Any Rejected CIs must be in exactly the same order that we sent.
+ * Check packet length and CI length at each step.
+ * If we find any deviations, then this packet is bad.
+ */
+ try = *go;
+
+ do {
+ REJCINETWORK (IPX_NETWORK_NUMBER, try.neg_nn, try.our_network);
+ REJCINODE (IPX_NODE_NUMBER, try.neg_node, try.our_node);
+ REJCINAME (IPX_ROUTER_NAME, try.neg_name, try.name);
+ REJCIPROTO (IPX_ROUTER_PROTOCOL, try.neg_router, try.router, 0);
+/*
+ * This is the end of the record.
+ */
+ if (len == 0) {
+ if (f->state != OPENED)
+ *go = try;
+ return (1);
+ }
+ } while (0);
+/*
+ * The frame is invalid at this point.
+ */
+ IPXCPDEBUG(("ipxcp_rejci: received bad Reject!"));
+ return 0;
+}
+
+/*
+ * ipxcp_reqci - Check the peer's requested CIs and send appropriate response.
+ *
+ * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
+ * appropriately. If reject_if_disagree is non-zero, doesn't return
+ * CONFNAK; returns CONFREJ if it can't return CONFACK.
+ */
+static int
+ipxcp_reqci(f, inp, len, reject_if_disagree)
+ fsm *f;
+ u_char *inp; /* Requested CIs */
+ int *len; /* Length of requested CIs */
+ int reject_if_disagree;
+{
+ u_char *cip, *next; /* Pointer to current and next CIs */
+ u_short cilen, citype; /* Parsed len, type */
+ u_short cishort; /* Parsed short value */
+ u_int32_t cinetwork; /* Parsed address values */
+ int rc = CONFACK; /* Final packet return code */
+ int orc; /* Individual option return code */
+ u_char *p; /* Pointer to next char to parse */
+ u_char *ucp = inp; /* Pointer to current output char */
+ int l = *len; /* Length left */
+
+ /*
+ * Reset all his options.
+ */
+ BZERO(ho, sizeof(*ho));
+
+ /*
+ * Process all his options.
+ */
+ next = inp;
+ while (l) {
+ orc = CONFACK; /* Assume success */
+ cip = p = next; /* Remember begining of CI */
+ if (l < 2 || /* Not enough data for CI header or */
+ p[1] < 2 || /* CI length too small or */
+ p[1] > l) { /* CI length too big? */
+ IPXCPDEBUG(("ipxcp_reqci: bad CI length!"));
+ orc = CONFREJ; /* Reject bad CI */
+ cilen = l; /* Reject till end of packet */
+ l = 0; /* Don't loop again */
+ goto endswitch;
+ }
+ GETCHAR(citype, p); /* Parse CI type */
+ GETCHAR(cilen, p); /* Parse CI length */
+ l -= cilen; /* Adjust remaining length */
+ next += cilen; /* Step to next CI */
+
+ switch (citype) { /* Check CI type */
+/*
+ * The network number must match. Choose the larger of the two.
+ */
+ case IPX_NETWORK_NUMBER:
+ /* if we wont negotiate the network number or the length is wrong
+ then reject the option */
+ if ( !ao->neg_nn || cilen != CILEN_NETN ) {
+ orc = CONFREJ;
+ break;
+ }
+ GETLONG(cinetwork, p);
+
+ /* If the network numbers match then acknowledge them. */
+ if (cinetwork != 0) {
+ ho->his_network = cinetwork;
+ ho->neg_nn = 1;
+ if (wo->our_network == cinetwork)
+ break;
+/*
+ * If the network number is not given or we don't accept their change or
+ * the network number is too small then NAK it.
+ */
+ if (! ao->accept_network || cinetwork < wo->our_network) {
+ DECPTR (sizeof (u_int32_t), p);
+ PUTLONG (wo->our_network, p);
+ orc = CONFNAK;
+ }
+ break;
+ }
+/*
+ * The peer sent '0' for the network. Give it ours if we have one.
+ */
+ if (go->our_network != 0) {
+ DECPTR (sizeof (u_int32_t), p);
+ PUTLONG (wo->our_network, p);
+ orc = CONFNAK;
+/*
+ * We don't have one. Reject the value.
+ */
+ } else
+ orc = CONFREJ;
+
+ break;
+/*
+ * The node number is required
+ */
+ case IPX_NODE_NUMBER:
+ /* if we wont negotiate the node number or the length is wrong
+ then reject the option */
+ if ( cilen != CILEN_NODEN ) {
+ orc = CONFREJ;
+ break;
+ }
+
+ copy_node (p, ho->his_node);
+ ho->neg_node = 1;
+/*
+ * If the remote does not have a number and we do then NAK it with the value
+ * which we have for it. (We never have a default value of zero.)
+ */
+ if (zero_node (ho->his_node)) {
+ orc = CONFNAK;
+ copy_node (wo->his_node, p);
+ INCPTR (sizeof (wo->his_node), p);
+ break;
+ }
+/*
+ * If you have given me the expected network node number then I'll accept
+ * it now.
+ */
+ if (compare_node (wo->his_node, ho->his_node)) {
+ orc = CONFACK;
+ ho->neg_node = 1;
+ INCPTR (sizeof (wo->his_node), p);
+ break;
+ }
+/*
+ * If his node number is the same as ours then ask him to try the next
+ * value.
+ */
+ if (compare_node (ho->his_node, go->our_node)) {
+ inc_node (ho->his_node);
+ orc = CONFNAK;
+ copy_node (ho->his_node, p);
+ INCPTR (sizeof (wo->his_node), p);
+ break;
+ }
+/*
+ * If we don't accept a new value then NAK it.
+ */
+ if (! ao->accept_remote) {
+ copy_node (wo->his_node, p);
+ INCPTR (sizeof (wo->his_node), p);
+ orc = CONFNAK;
+ break;
+ }
+ orc = CONFACK;
+ ho->neg_node = 1;
+ INCPTR (sizeof (wo->his_node), p);
+ break;
+/*
+ * Compression is not desired at this time. It is always rejected.
+ */
+ case IPX_COMPRESSION_PROTOCOL:
+ orc = CONFREJ;
+ break;
+/*
+ * The routing protocol is a bitmask of various types. Any combination
+ * of the values RIP_SAP and NLSP are permissible. 'IPX_NONE' for no
+ * routing protocol must be specified only once.
+ */
+ case IPX_ROUTER_PROTOCOL:
+ if ( !ao->neg_router || cilen < CILEN_PROTOCOL ) {
+ orc = CONFREJ;
+ break;
+ }
+
+ GETSHORT (cishort, p);
+
+ if (wo->neg_router == 0) {
+ wo->neg_router = 1;
+ wo->router = BIT(IPX_NONE);
+ }
+
+ if ((cishort == IPX_NONE && ho->router != 0) ||
+ (ho->router & BIT(IPX_NONE))) {
+ orc = CONFREJ;
+ break;
+ }
+
+ cishort = BIT(cishort);
+ if (ho->router & cishort) {
+ orc = CONFREJ;
+ break;
+ }
+
+ ho->router |= cishort;
+ ho->neg_router = 1;
+
+ /* Finally do not allow a router protocol which we do not
+ support. */
+
+ if ((cishort & (ao->router | BIT(IPX_NONE))) == 0) {
+ int protocol;
+
+ if (cishort == BIT(NLSP) &&
+ (ao->router & BIT(RIP_SAP)) &&
+ !wo->tried_rip) {
+ protocol = RIP_SAP;
+ wo->tried_rip = 1;
+ } else
+ protocol = IPX_NONE;
+
+ DECPTR (sizeof (u_int16_t), p);
+ PUTSHORT (protocol, p);
+ orc = CONFNAK;
+ }
+ break;
+/*
+ * The router name is advisorary. Just accept it if it is not too large.
+ */
+ case IPX_ROUTER_NAME:
+ if (cilen >= CILEN_NAME) {
+ int name_size = cilen - CILEN_NAME;
+ if (name_size > sizeof (ho->name))
+ name_size = sizeof (ho->name) - 1;
+ memset (ho->name, 0, sizeof (ho->name));
+ memcpy (ho->name, p, name_size);
+ ho->name [name_size] = '\0';
+ ho->neg_name = 1;
+ orc = CONFACK;
+ break;
+ }
+ orc = CONFREJ;
+ break;
+/*
+ * This is advisorary.
+ */
+ case IPX_COMPLETE:
+ if (cilen != CILEN_COMPLETE)
+ orc = CONFREJ;
+ else {
+ ho->neg_complete = 1;
+ orc = CONFACK;
+ }
+ break;
+/*
+ * All other entries are not known at this time.
+ */
+ default:
+ orc = CONFREJ;
+ break;
+ }
+endswitch:
+ if (orc == CONFACK && /* Good CI */
+ rc != CONFACK) /* but prior CI wasnt? */
+ continue; /* Don't send this one */
+
+ if (orc == CONFNAK) { /* Nak this CI? */
+ if (reject_if_disagree) /* Getting fed up with sending NAKs? */
+ orc = CONFREJ; /* Get tough if so */
+ if (rc == CONFREJ) /* Rejecting prior CI? */
+ continue; /* Don't send this one */
+ if (rc == CONFACK) { /* Ack'd all prior CIs? */
+ rc = CONFNAK; /* Not anymore... */
+ ucp = inp; /* Backup */
+ }
+ }
+
+ if (orc == CONFREJ && /* Reject this CI */
+ rc != CONFREJ) { /* but no prior ones? */
+ rc = CONFREJ;
+ ucp = inp; /* Backup */
+ }
+
+ /* Need to move CI? */
+ if (ucp != cip)
+ BCOPY(cip, ucp, cilen); /* Move it */
+
+ /* Update output pointer */
+ INCPTR(cilen, ucp);
+ }
+
+ /*
+ * If we aren't rejecting this packet, and we want to negotiate
+ * their address, and they didn't send their address, then we
+ * send a NAK with a IPX_NODE_NUMBER option appended. We assume the
+ * input buffer is long enough that we can append the extra
+ * option safely.
+ */
+
+ if (rc != CONFREJ && !ho->neg_node &&
+ wo->req_nn && !reject_if_disagree) {
+ if (rc == CONFACK) {
+ rc = CONFNAK;
+ wo->req_nn = 0; /* don't ask again */
+ ucp = inp; /* reset pointer */
+ }
+
+ if (zero_node (wo->his_node))
+ inc_node (wo->his_node);
+
+ PUTCHAR (IPX_NODE_NUMBER, ucp);
+ PUTCHAR (CILEN_NODEN, ucp);
+ copy_node (wo->his_node, ucp);
+ INCPTR (sizeof (wo->his_node), ucp);
+ }
+
+ *len = ucp - inp; /* Compute output length */
+ IPXCPDEBUG(("ipxcp: returning Configure-%s", CODENAME(rc)));
+ return (rc); /* Return final code */
+}
+
+/*
+ * ipxcp_up - IPXCP has come UP.
+ *
+ * Configure the IP network interface appropriately and bring it up.
+ */
+
+static void
+ipxcp_up(f)
+ fsm *f;
+{
+ int unit = f->unit;
+
+ IPXCPDEBUG(("ipxcp: up"));
+
+ /* The default router protocol is RIP/SAP. */
+ if (ho->router == 0)
+ ho->router = BIT(RIP_SAP);
+
+ if (go->router == 0)
+ go->router = BIT(RIP_SAP);
+
+ /* Fetch the network number */
+ if (!ho->neg_nn)
+ ho->his_network = wo->his_network;
+
+ if (!ho->neg_node)
+ copy_node (wo->his_node, ho->his_node);
+
+ if (!wo->neg_node && !go->neg_node)
+ copy_node (wo->our_node, go->our_node);
+
+ if (zero_node (go->our_node)) {
+ static char errmsg[] = "Could not determine local IPX node address";
+ if (debug)
+ error(errmsg);
+ ipxcp_close(f->unit, errmsg);
+ return;
+ }
+
+ go->network = go->our_network;
+ if (ho->his_network != 0 && ho->his_network > go->network)
+ go->network = ho->his_network;
+
+ if (go->network == 0) {
+ static char errmsg[] = "Can not determine network number";
+ if (debug)
+ error(errmsg);
+ ipxcp_close (unit, errmsg);
+ return;
+ }
+
+ /* bring the interface up */
+ if (!sifup(unit)) {
+ if (debug)
+ warn("sifup failed (IPX)");
+ ipxcp_close(unit, "Interface configuration failed");
+ return;
+ }
+ ipxcp_is_up = 1;
+
+ /* set the network number for IPX */
+ if (!sipxfaddr(unit, go->network, go->our_node)) {
+ if (debug)
+ warn("sipxfaddr failed");
+ ipxcp_close(unit, "Interface configuration failed");
+ return;
+ }
+
+ np_up(f->unit, PPP_IPX);
+}
+
+/*
+ * ipxcp_down - IPXCP has gone DOWN.
+ *
+ * Take the IP network interface down, clear its addresses
+ * and delete routes through it.
+ */
+
+static void
+ipxcp_down(f)
+ fsm *f;
+{
+ IPXCPDEBUG(("ipxcp: down"));
+
+ if (!ipxcp_is_up)
+ return;
+ ipxcp_is_up = 0;
+ np_down(f->unit, PPP_IPX);
+ cipxfaddr(f->unit);
+ sifnpmode(f->unit, PPP_IPX, NPMODE_DROP);
+ sifdown(f->unit);
+}
+
+
+/*
+ * ipxcp_finished - possibly shut down the lower layers.
+ */
+static void
+ipxcp_finished(f)
+ fsm *f;
+{
+ np_finished(f->unit, PPP_IPX);
+}
+
+
+/*
+ * ipxcp_printpkt - print the contents of an IPXCP packet.
+ */
+static char *ipxcp_codenames[] = {
+ "ConfReq", "ConfAck", "ConfNak", "ConfRej",
+ "TermReq", "TermAck", "CodeRej"
+};
+
+static int
+ipxcp_printpkt(p, plen, printer, arg)
+ u_char *p;
+ int plen;
+ void (*printer) __P((void *, char *, ...));
+ void *arg;
+{
+ int code, id, len, olen;
+ u_char *pstart, *optend;
+ u_short cishort;
+ u_int32_t cilong;
+
+ if (plen < HEADERLEN)
+ return 0;
+ pstart = p;
+ GETCHAR(code, p);
+ GETCHAR(id, p);
+ GETSHORT(len, p);
+ if (len < HEADERLEN || len > plen)
+ return 0;
+
+ if (code >= 1 && code <= sizeof(ipxcp_codenames) / sizeof(char *))
+ printer(arg, " %s", ipxcp_codenames[code-1]);
+ else
+ printer(arg, " code=0x%x", code);
+ printer(arg, " id=0x%x", id);
+ len -= HEADERLEN;
+ switch (code) {
+ case CONFREQ:
+ case CONFACK:
+ case CONFNAK:
+ case CONFREJ:
+ /* print option list */
+ while (len >= 2) {
+ GETCHAR(code, p);
+ GETCHAR(olen, p);
+ p -= 2;
+ if (olen < CILEN_VOID || olen > len) {
+ break;
+ }
+ printer(arg, " <");
+ len -= olen;
+ optend = p + olen;
+ switch (code) {
+ case IPX_NETWORK_NUMBER:
+ if (olen == CILEN_NETN) {
+ p += 2;
+ GETLONG(cilong, p);
+ printer (arg, "network %s", ipx_ntoa (cilong));
+ }
+ break;
+ case IPX_NODE_NUMBER:
+ if (olen == CILEN_NODEN) {
+ p += 2;
+ printer (arg, "node ");
+ while (p < optend) {
+ GETCHAR(code, p);
+ printer(arg, "%.2x", (int) (unsigned int) (unsigned char) code);
+ }
+ }
+ break;
+ case IPX_COMPRESSION_PROTOCOL:
+ if (olen == CILEN_COMPRESS) {
+ p += 2;
+ GETSHORT (cishort, p);
+ printer (arg, "compression %d", (int) cishort);
+ }
+ break;
+ case IPX_ROUTER_PROTOCOL:
+ if (olen == CILEN_PROTOCOL) {
+ p += 2;
+ GETSHORT (cishort, p);
+ printer (arg, "router proto %d", (int) cishort);
+ }
+ break;
+ case IPX_ROUTER_NAME:
+ if (olen >= CILEN_NAME) {
+ p += 2;
+ printer (arg, "router name \"");
+ while (p < optend) {
+ GETCHAR(code, p);
+ if (code >= 0x20 && code <= 0x7E)
+ printer (arg, "%c", (int) (unsigned int) (unsigned char) code);
+ else
+ printer (arg, " \\%.2x", (int) (unsigned int) (unsigned char) code);
+ }
+ printer (arg, "\"");
+ }
+ break;
+ case IPX_COMPLETE:
+ if (olen == CILEN_COMPLETE) {
+ p += 2;
+ printer (arg, "complete");
+ }
+ break;
+ default:
+ break;
+ }
+
+ while (p < optend) {
+ GETCHAR(code, p);
+ printer(arg, " %.2x", (int) (unsigned int) (unsigned char) code);
+ }
+ printer(arg, ">");
+ }
+ break;
+
+ case TERMACK:
+ case TERMREQ:
+ if (len > 0 && *p >= ' ' && *p < 0x7f) {
+ printer(arg, " ");
+ print_string(p, len, printer, arg);
+ p += len;
+ len = 0;
+ }
+ break;
+ }
+
+ /* print the rest of the bytes in the packet */
+ for (; len > 0; --len) {
+ GETCHAR(code, p);
+ printer(arg, " %.2x", (int) (unsigned int) (unsigned char) code);
+ }
+
+ return p - pstart;
+}
+#endif /* ifdef IPX_CHANGE */
diff --git a/cpukit/pppd/ipxcp.h b/cpukit/pppd/ipxcp.h
new file mode 100644
index 0000000000..47f680d70c
--- /dev/null
+++ b/cpukit/pppd/ipxcp.h
@@ -0,0 +1,71 @@
+/*
+ * ipxcp.h - IPX Control Protocol definitions.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * $Id$
+ */
+
+/*
+ * Options.
+ */
+#define IPX_NETWORK_NUMBER 1 /* IPX Network Number */
+#define IPX_NODE_NUMBER 2
+#define IPX_COMPRESSION_PROTOCOL 3
+#define IPX_ROUTER_PROTOCOL 4
+#define IPX_ROUTER_NAME 5
+#define IPX_COMPLETE 6
+
+/* Values for the router protocol */
+#define IPX_NONE 0
+#define RIP_SAP 2
+#define NLSP 4
+
+typedef struct ipxcp_options {
+ bool neg_node; /* Negotiate IPX node number? */
+ bool req_node; /* Ask peer to send IPX node number? */
+
+ bool neg_nn; /* Negotiate IPX network number? */
+ bool req_nn; /* Ask peer to send IPX network number */
+
+ bool neg_name; /* Negotiate IPX router name */
+ bool neg_complete; /* Negotiate completion */
+ bool neg_router; /* Negotiate IPX router number */
+
+ bool accept_local; /* accept peer's value for ournode */
+ bool accept_remote; /* accept peer's value for hisnode */
+ bool accept_network; /* accept network number */
+
+ bool tried_nlsp; /* I have suggested NLSP already */
+ bool tried_rip; /* I have suggested RIP/SAP already */
+
+ u_int32_t his_network; /* base network number */
+ u_int32_t our_network; /* our value for network number */
+ u_int32_t network; /* the final network number */
+
+ u_char his_node[6]; /* peer's node number */
+ u_char our_node[6]; /* our node number */
+ u_char name [48]; /* name of the router */
+ int router; /* routing protocol */
+} ipxcp_options;
+
+extern fsm ipxcp_fsm[];
+extern ipxcp_options ipxcp_wantoptions[];
+extern ipxcp_options ipxcp_gotoptions[];
+extern ipxcp_options ipxcp_allowoptions[];
+extern ipxcp_options ipxcp_hisoptions[];
+
+extern struct protent ipxcp_protent;
diff --git a/cpukit/pppd/lcp.c b/cpukit/pppd/lcp.c
new file mode 100644
index 0000000000..4308c86026
--- /dev/null
+++ b/cpukit/pppd/lcp.c
@@ -0,0 +1,1953 @@
+/*
+ * lcp.c - PPP Link Control Protocol.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#define RCSID "$Id$";
+
+/*
+ * TODO:
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "pppd.h"
+#include "fsm.h"
+#include "lcp.h"
+#include "chap.h"
+#include "magic.h"
+
+static const char rcsid[] = RCSID;
+
+/*
+ * LCP-related command-line options.
+ */
+static int lcp_echo_interval = 0; /* Interval between LCP echo-requests */
+static int lcp_echo_fails = 0; /* Tolerance to unanswered echo-requests */
+static bool lax_recv = 0; /* accept control chars in asyncmap */
+
+static int setescape __P((char **));
+
+static option_t lcp_option_list[] = {
+ /* LCP options */
+ { "noaccomp", o_bool, &lcp_wantoptions[0].neg_accompression,
+ "Disable address/control compression",
+ OPT_A2COPY, &lcp_allowoptions[0].neg_accompression },
+ { "-ac", o_bool, &lcp_wantoptions[0].neg_accompression,
+ "Disable address/control compression",
+ OPT_A2COPY, &lcp_allowoptions[0].neg_accompression },
+ { "default-asyncmap", o_bool, &lcp_wantoptions[0].neg_asyncmap,
+ "Disable asyncmap negotiation",
+ OPT_A2COPY, &lcp_allowoptions[0].neg_asyncmap },
+ { "-am", o_bool, &lcp_wantoptions[0].neg_asyncmap,
+ "Disable asyncmap negotiation",
+ OPT_A2COPY, &lcp_allowoptions[0].neg_asyncmap },
+ { "asyncmap", o_uint32, &lcp_wantoptions[0].asyncmap,
+ "Set asyncmap (for received packets)",
+ OPT_OR, &lcp_wantoptions[0].neg_asyncmap },
+ { "-as", o_uint32, &lcp_wantoptions[0].asyncmap,
+ "Set asyncmap (for received packets)",
+ OPT_OR, &lcp_wantoptions[0].neg_asyncmap },
+ { "nomagic", o_bool, &lcp_wantoptions[0].neg_magicnumber,
+ "Disable magic number negotiation (looped-back line detection)",
+ OPT_A2COPY, &lcp_allowoptions[0].neg_magicnumber },
+ { "-mn", o_bool, &lcp_wantoptions[0].neg_magicnumber,
+ "Disable magic number negotiation (looped-back line detection)",
+ OPT_A2COPY, &lcp_allowoptions[0].neg_magicnumber },
+ { "default-mru", o_bool, &lcp_wantoptions[0].neg_mru,
+ "Disable MRU negotiation (use default 1500)",
+ OPT_A2COPY, &lcp_allowoptions[0].neg_mru },
+ { "-mru", o_bool, &lcp_wantoptions[0].neg_mru,
+ "Disable MRU negotiation (use default 1500)",
+ OPT_A2COPY, &lcp_allowoptions[0].neg_mru },
+ { "mru", o_int, &lcp_wantoptions[0].mru,
+ "Set MRU (maximum received packet size) for negotiation",
+ 0, &lcp_wantoptions[0].neg_mru },
+ { "nopcomp", o_bool, &lcp_wantoptions[0].neg_pcompression,
+ "Disable protocol field compression",
+ OPT_A2COPY, &lcp_allowoptions[0].neg_pcompression },
+ { "-pc", o_bool, &lcp_wantoptions[0].neg_pcompression,
+ "Disable protocol field compression",
+ OPT_A2COPY, &lcp_allowoptions[0].neg_pcompression },
+ { "-p", o_bool, &lcp_wantoptions[0].passive,
+ "Set passive mode", 1 },
+ { "passive", o_bool, &lcp_wantoptions[0].passive,
+ "Set passive mode", 1 },
+ { "silent", o_bool, &lcp_wantoptions[0].silent,
+ "Set silent mode", 1 },
+ { "escape", o_special, setescape,
+ "List of character codes to escape on transmission" },
+ { "lcp-echo-failure", o_int, &lcp_echo_fails,
+ "Set number of consecutive echo failures to indicate link failure" },
+ { "lcp-echo-interval", o_int, &lcp_echo_interval,
+ "Set time in seconds between LCP echo requests" },
+ { "lcp-restart", o_int, &lcp_fsm[0].timeouttime,
+ "Set time in seconds between LCP retransmissions" },
+ { "lcp-max-terminate", o_int, &lcp_fsm[0].maxtermtransmits,
+ "Set maximum number of LCP terminate-request transmissions" },
+ { "lcp-max-configure", o_int, &lcp_fsm[0].maxconfreqtransmits,
+ "Set maximum number of LCP configure-request transmissions" },
+ { "lcp-max-failure", o_int, &lcp_fsm[0].maxnakloops,
+ "Set limit on number of LCP configure-naks" },
+ { "receive-all", o_bool, &lax_recv,
+ "Accept all received control characters", 1 },
+ {NULL}
+};
+
+/* global vars */
+fsm lcp_fsm[NUM_PPP]; /* LCP fsm structure (global)*/
+lcp_options lcp_wantoptions[NUM_PPP]; /* Options that we want to request */
+lcp_options lcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */
+lcp_options lcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
+lcp_options lcp_hisoptions[NUM_PPP]; /* Options that we ack'd */
+u_int32_t xmit_accm[NUM_PPP][8]; /* extended transmit ACCM */
+
+static int lcp_echos_pending = 0; /* Number of outstanding echo msgs */
+static int lcp_echo_number = 0; /* ID number of next echo frame */
+static int lcp_echo_timer_running = 0; /* set if a timer is running */
+
+static u_char nak_buffer[PPP_MRU]; /* where we construct a nak packet */
+
+/*
+ * Callbacks for fsm code. (CI = Configuration Information)
+ */
+static void lcp_resetci __P((fsm *)); /* Reset our CI */
+static int lcp_cilen __P((fsm *)); /* Return length of our CI */
+static void lcp_addci __P((fsm *, u_char *, int *)); /* Add our CI to pkt */
+static int lcp_ackci __P((fsm *, u_char *, int)); /* Peer ack'd our CI */
+static int lcp_nakci __P((fsm *, u_char *, int)); /* Peer nak'd our CI */
+static int lcp_rejci __P((fsm *, u_char *, int)); /* Peer rej'd our CI */
+static int lcp_reqci __P((fsm *, u_char *, int *, int)); /* Rcv peer CI */
+static void lcp_up __P((fsm *)); /* We're UP */
+static void lcp_down __P((fsm *)); /* We're DOWN */
+static void lcp_starting __P((fsm *)); /* We need lower layer up */
+static void lcp_finished __P((fsm *)); /* We need lower layer down */
+static int lcp_extcode __P((fsm *, int, int, u_char *, int));
+static void lcp_rprotrej __P((fsm *, u_char *, int));
+
+/*
+ * routines to send LCP echos to peer
+ */
+
+static void lcp_echo_lowerup __P((int));
+static void lcp_echo_lowerdown __P((int));
+static void LcpEchoTimeout __P((void *));
+static void lcp_received_echo_reply __P((fsm *, int, u_char *, int));
+static void LcpSendEchoRequest __P((fsm *));
+static void LcpLinkFailure __P((fsm *));
+static void LcpEchoCheck __P((fsm *));
+
+static fsm_callbacks lcp_callbacks = { /* LCP callback routines */
+ lcp_resetci, /* Reset our Configuration Information */
+ lcp_cilen, /* Length of our Configuration Information */
+ lcp_addci, /* Add our Configuration Information */
+ lcp_ackci, /* ACK our Configuration Information */
+ lcp_nakci, /* NAK our Configuration Information */
+ lcp_rejci, /* Reject our Configuration Information */
+ lcp_reqci, /* Request peer's Configuration Information */
+ lcp_up, /* Called when fsm reaches OPENED state */
+ lcp_down, /* Called when fsm leaves OPENED state */
+ lcp_starting, /* Called when we want the lower layer up */
+ lcp_finished, /* Called when we want the lower layer down */
+ NULL, /* Called when Protocol-Reject received */
+ NULL, /* Retransmission is necessary */
+ lcp_extcode, /* Called to handle LCP-specific codes */
+ "LCP" /* String name of protocol */
+};
+
+/*
+ * Protocol entry points.
+ * Some of these are called directly.
+ */
+
+static void lcp_init __P((int));
+static void lcp_input __P((int, u_char *, int));
+static void lcp_protrej __P((int));
+static int lcp_printpkt __P((u_char *, int,
+ void (*) __P((void *, char *, ...)), void *));
+
+struct protent lcp_protent = {
+ PPP_LCP,
+ lcp_init,
+ lcp_input,
+ lcp_protrej,
+ lcp_lowerup,
+ lcp_lowerdown,
+ lcp_open,
+ lcp_close,
+ lcp_printpkt,
+ NULL,
+ 1,
+ "LCP",
+ NULL,
+ lcp_option_list,
+ NULL,
+ NULL,
+ NULL
+};
+
+int lcp_loopbackfail = DEFLOOPBACKFAIL;
+
+/*
+ * Length of each type of configuration option (in octets)
+ */
+#define CILEN_VOID 2
+#define CILEN_CHAR 3
+#define CILEN_SHORT 4 /* CILEN_VOID + 2 */
+#define CILEN_CHAP 5 /* CILEN_VOID + 2 + 1 */
+#define CILEN_LONG 6 /* CILEN_VOID + 4 */
+#define CILEN_LQR 8 /* CILEN_VOID + 2 + 4 */
+#define CILEN_CBCP 3
+
+#define CODENAME(x) ((x) == CONFACK ? "ACK" : \
+ (x) == CONFNAK ? "NAK" : "REJ")
+
+
+/*
+ * setescape - add chars to the set we escape on transmission.
+ */
+static int
+setescape(argv)
+ char **argv;
+{
+ int n, ret;
+ char *p, *endp;
+
+ p = *argv;
+ ret = 1;
+ while (*p) {
+ n = strtol(p, &endp, 16);
+ if (p == endp) {
+ option_error("escape parameter contains invalid hex number '%s'",
+ p);
+ return 0;
+ }
+ p = endp;
+ if (n < 0 || n == 0x5E || n > 0xFF) {
+ option_error("can't escape character 0x%x", n);
+ ret = 0;
+ } else
+ xmit_accm[0][n >> 5] |= 1 << (n & 0x1F);
+ while (*p == ',' || *p == ' ')
+ ++p;
+ }
+ return ret;
+}
+
+/*
+ * lcp_init - Initialize LCP.
+ */
+static void
+lcp_init(unit)
+ int unit;
+{
+ fsm *f = &lcp_fsm[unit];
+ lcp_options *wo = &lcp_wantoptions[unit];
+ lcp_options *ao = &lcp_allowoptions[unit];
+
+ f->unit = unit;
+ f->protocol = PPP_LCP;
+ f->callbacks = &lcp_callbacks;
+
+ fsm_init(f);
+
+ wo->passive = 0;
+ wo->silent = 0;
+ wo->restart = 0; /* Set to 1 in kernels or multi-line
+ implementations */
+ wo->neg_mru = 1;
+ wo->mru = DEFMRU;
+ wo->neg_asyncmap = 1;
+ wo->asyncmap = 0;
+ wo->neg_chap = 0; /* Set to 1 on server */
+ wo->neg_upap = 0; /* Set to 1 on server */
+ wo->chap_mdtype = CHAP_DIGEST_MD5;
+ wo->neg_magicnumber = 1;
+ wo->neg_pcompression = 1;
+ wo->neg_accompression = 1;
+ wo->neg_lqr = 0; /* no LQR implementation yet */
+ wo->neg_cbcp = 0;
+
+ ao->neg_mru = 1;
+ ao->mru = MAXMRU;
+ ao->neg_asyncmap = 1;
+ ao->asyncmap = 0;
+ ao->neg_chap = 1;
+ ao->chap_mdtype = CHAP_DIGEST_MD5;
+ ao->neg_upap = 1;
+ ao->neg_magicnumber = 1;
+ ao->neg_pcompression = 1;
+ ao->neg_accompression = 1;
+ ao->neg_lqr = 0; /* no LQR implementation yet */
+#ifdef CBCP_SUPPORT
+ ao->neg_cbcp = 1;
+#else
+ ao->neg_cbcp = 0;
+#endif
+
+ memset(xmit_accm[unit], 0, sizeof(xmit_accm[0]));
+ xmit_accm[unit][3] = 0x60000000;
+}
+
+
+/*
+ * lcp_open - LCP is allowed to come up.
+ */
+void
+lcp_open(unit)
+ int unit;
+{
+ fsm *f = &lcp_fsm[unit];
+ lcp_options *wo = &lcp_wantoptions[unit];
+
+ f->flags = 0;
+ if (wo->passive)
+ f->flags |= OPT_PASSIVE;
+ if (wo->silent)
+ f->flags |= OPT_SILENT;
+ fsm_open(f);
+}
+
+
+/*
+ * lcp_close - Take LCP down.
+ */
+void
+lcp_close(unit, reason)
+ int unit;
+ char *reason;
+{
+ fsm *f = &lcp_fsm[unit];
+
+ if (pppd_phase != PHASE_DEAD)
+ new_phase(PHASE_TERMINATE);
+ if (f->state == STOPPED && f->flags & (OPT_PASSIVE|OPT_SILENT)) {
+ /*
+ * This action is not strictly according to the FSM in RFC1548,
+ * but it does mean that the program terminates if you do a
+ * lcp_close() in passive/silent mode when a connection hasn't
+ * been established.
+ */
+ f->state = CLOSED;
+ lcp_finished(f);
+
+ } else
+ fsm_close(&lcp_fsm[unit], reason);
+}
+
+
+/*
+ * lcp_lowerup - The lower layer is up.
+ */
+void
+lcp_lowerup(unit)
+ int unit;
+{
+ lcp_options *wo = &lcp_wantoptions[unit];
+
+ /*
+ * Don't use A/C or protocol compression on transmission,
+ * but accept A/C and protocol compressed packets
+ * if we are going to ask for A/C and protocol compression.
+ */
+ ppp_set_xaccm(unit, xmit_accm[unit]);
+ ppp_send_config(unit, PPP_MRU, 0xffffffff, 0, 0);
+ ppp_recv_config(unit, PPP_MRU, (lax_recv? 0: 0xffffffff),
+ wo->neg_pcompression, wo->neg_accompression);
+ peer_mru[unit] = PPP_MRU;
+ lcp_allowoptions[unit].asyncmap = xmit_accm[unit][0];
+
+ fsm_lowerup(&lcp_fsm[unit]);
+}
+
+
+/*
+ * lcp_lowerdown - The lower layer is down.
+ */
+void
+lcp_lowerdown(unit)
+ int unit;
+{
+ fsm_lowerdown(&lcp_fsm[unit]);
+}
+
+
+/*
+ * lcp_input - Input LCP packet.
+ */
+static void
+lcp_input(unit, p, len)
+ int unit;
+ u_char *p;
+ int len;
+{
+ fsm *f = &lcp_fsm[unit];
+
+ fsm_input(f, p, len);
+}
+
+
+/*
+ * lcp_extcode - Handle a LCP-specific code.
+ */
+static int
+lcp_extcode(f, code, id, inp, len)
+ fsm *f;
+ int code, id;
+ u_char *inp;
+ int len;
+{
+ u_char *magp;
+
+ switch( code ){
+ case PROTREJ:
+ lcp_rprotrej(f, inp, len);
+ break;
+
+ case ECHOREQ:
+ if (f->state != OPENED)
+ break;
+ magp = inp;
+ PUTLONG(lcp_gotoptions[f->unit].magicnumber, magp);
+ fsm_sdata(f, ECHOREP, id, inp, len);
+ break;
+
+ case ECHOREP:
+ lcp_received_echo_reply(f, id, inp, len);
+ break;
+
+ case DISCREQ:
+ break;
+
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+
+/*
+ * lcp_rprotrej - Receive an Protocol-Reject.
+ *
+ * Figure out which protocol is rejected and inform it.
+ */
+static void
+lcp_rprotrej(f, inp, len)
+ fsm *f;
+ u_char *inp;
+ int len;
+{
+ int i;
+ struct protent *protp;
+ u_short prot;
+
+ if (len < 2) {
+ LCPDEBUG(("lcp_rprotrej: Rcvd short Protocol-Reject packet!"));
+ return;
+ }
+
+ GETSHORT(prot, inp);
+
+ /*
+ * Protocol-Reject packets received in any state other than the LCP
+ * OPENED state SHOULD be silently discarded.
+ */
+ if( f->state != OPENED ){
+ LCPDEBUG(("Protocol-Reject discarded: LCP in state %d", f->state));
+ return;
+ }
+
+ /*
+ * Upcall the proper Protocol-Reject routine.
+ */
+ for (i = 0; (protp = protocols[i]) != NULL; ++i)
+ if (protp->protocol == prot && protp->enabled_flag) {
+ (*protp->protrej)(f->unit);
+ return;
+ }
+
+ warn("Protocol-Reject for unsupported protocol 0x%x", prot);
+}
+
+
+/*
+ * lcp_protrej - A Protocol-Reject was received.
+ */
+/*ARGSUSED*/
+static void
+lcp_protrej(unit)
+ int unit;
+{
+ /*
+ * Can't reject LCP!
+ */
+ error("Received Protocol-Reject for LCP!");
+ fsm_protreject(&lcp_fsm[unit]);
+}
+
+
+/*
+ * lcp_sprotrej - Send a Protocol-Reject for some protocol.
+ */
+void
+lcp_sprotrej(unit, p, len)
+ int unit;
+ u_char *p;
+ int len;
+{
+ /*
+ * Send back the protocol and the information field of the
+ * rejected packet. We only get here if LCP is in the OPENED state.
+ */
+ p += 2;
+ len -= 2;
+
+ fsm_sdata(&lcp_fsm[unit], PROTREJ, ++lcp_fsm[unit].id,
+ p, len);
+}
+
+
+/*
+ * lcp_resetci - Reset our CI.
+ */
+static void
+lcp_resetci(f)
+ fsm *f;
+{
+ lcp_wantoptions[f->unit].magicnumber = magic();
+ lcp_wantoptions[f->unit].numloops = 0;
+ lcp_gotoptions[f->unit] = lcp_wantoptions[f->unit];
+ peer_mru[f->unit] = PPP_MRU;
+ auth_reset(f->unit);
+}
+
+
+/*
+ * lcp_cilen - Return length of our CI.
+ */
+static int
+lcp_cilen(f)
+ fsm *f;
+{
+ lcp_options *go = &lcp_gotoptions[f->unit];
+
+#define LENCIVOID(neg) ((neg) ? CILEN_VOID : 0)
+#define LENCICHAP(neg) ((neg) ? CILEN_CHAP : 0)
+#define LENCISHORT(neg) ((neg) ? CILEN_SHORT : 0)
+#define LENCILONG(neg) ((neg) ? CILEN_LONG : 0)
+#define LENCILQR(neg) ((neg) ? CILEN_LQR: 0)
+#define LENCICBCP(neg) ((neg) ? CILEN_CBCP: 0)
+ /*
+ * NB: we only ask for one of CHAP and UPAP, even if we will
+ * accept either.
+ */
+ return (LENCISHORT(go->neg_mru && go->mru != DEFMRU) +
+ LENCILONG(go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) +
+ LENCICHAP(go->neg_chap) +
+ LENCISHORT(!go->neg_chap && go->neg_upap) +
+ LENCILQR(go->neg_lqr) +
+ LENCICBCP(go->neg_cbcp) +
+ LENCILONG(go->neg_magicnumber) +
+ LENCIVOID(go->neg_pcompression) +
+ LENCIVOID(go->neg_accompression));
+}
+
+
+/*
+ * lcp_addci - Add our desired CIs to a packet.
+ */
+static void
+lcp_addci(f, ucp, lenp)
+ fsm *f;
+ u_char *ucp;
+ int *lenp;
+{
+ lcp_options *go = &lcp_gotoptions[f->unit];
+ u_char *start_ucp = ucp;
+
+#define ADDCIVOID(opt, neg) \
+ if (neg) { \
+ PUTCHAR(opt, ucp); \
+ PUTCHAR(CILEN_VOID, ucp); \
+ }
+#define ADDCISHORT(opt, neg, val) \
+ if (neg) { \
+ PUTCHAR(opt, ucp); \
+ PUTCHAR(CILEN_SHORT, ucp); \
+ PUTSHORT(val, ucp); \
+ }
+#define ADDCICHAP(opt, neg, val, digest) \
+ if (neg) { \
+ PUTCHAR(opt, ucp); \
+ PUTCHAR(CILEN_CHAP, ucp); \
+ PUTSHORT(val, ucp); \
+ PUTCHAR(digest, ucp); \
+ }
+#define ADDCILONG(opt, neg, val) \
+ if (neg) { \
+ PUTCHAR(opt, ucp); \
+ PUTCHAR(CILEN_LONG, ucp); \
+ PUTLONG(val, ucp); \
+ }
+#define ADDCILQR(opt, neg, val) \
+ if (neg) { \
+ PUTCHAR(opt, ucp); \
+ PUTCHAR(CILEN_LQR, ucp); \
+ PUTSHORT(PPP_LQR, ucp); \
+ PUTLONG(val, ucp); \
+ }
+#define ADDCICHAR(opt, neg, val) \
+ if (neg) { \
+ PUTCHAR(opt, ucp); \
+ PUTCHAR(CILEN_CHAR, ucp); \
+ PUTCHAR(val, ucp); \
+ }
+
+ ADDCISHORT(CI_MRU, go->neg_mru && go->mru != DEFMRU, go->mru);
+ ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF,
+ go->asyncmap);
+ ADDCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype);
+ ADDCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP);
+ ADDCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
+ ADDCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT);
+ ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
+ ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
+ ADDCIVOID(CI_ACCOMPRESSION, go->neg_accompression);
+
+ if (ucp - start_ucp != *lenp) {
+ /* this should never happen, because peer_mtu should be 1500 */
+ error("Bug in lcp_addci: wrong length");
+ }
+}
+
+
+/*
+ * lcp_ackci - Ack our CIs.
+ * This should not modify any state if the Ack is bad.
+ *
+ * Returns:
+ * 0 - Ack was bad.
+ * 1 - Ack was good.
+ */
+static int
+lcp_ackci(f, p, len)
+ fsm *f;
+ u_char *p;
+ int len;
+{
+ lcp_options *go = &lcp_gotoptions[f->unit];
+ u_char cilen, citype, cichar;
+ u_short cishort;
+ u_int32_t cilong;
+
+ /*
+ * CIs must be in exactly the same order that we sent.
+ * Check packet length and CI length at each step.
+ * If we find any deviations, then this packet is bad.
+ */
+#define ACKCIVOID(opt, neg) \
+ if (neg) { \
+ if ((len -= CILEN_VOID) < 0) \
+ goto bad; \
+ GETCHAR(citype, p); \
+ GETCHAR(cilen, p); \
+ if (cilen != CILEN_VOID || \
+ citype != opt) \
+ goto bad; \
+ }
+#define ACKCISHORT(opt, neg, val) \
+ if (neg) { \
+ if ((len -= CILEN_SHORT) < 0) \
+ goto bad; \
+ GETCHAR(citype, p); \
+ GETCHAR(cilen, p); \
+ if (cilen != CILEN_SHORT || \
+ citype != opt) \
+ goto bad; \
+ GETSHORT(cishort, p); \
+ if (cishort != val) \
+ goto bad; \
+ }
+#define ACKCICHAR(opt, neg, val) \
+ if (neg) { \
+ if ((len -= CILEN_CHAR) < 0) \
+ goto bad; \
+ GETCHAR(citype, p); \
+ GETCHAR(cilen, p); \
+ if (cilen != CILEN_CHAR || \
+ citype != opt) \
+ goto bad; \
+ GETCHAR(cichar, p); \
+ if (cichar != val) \
+ goto bad; \
+ }
+#define ACKCICHAP(opt, neg, val, digest) \
+ if (neg) { \
+ if ((len -= CILEN_CHAP) < 0) \
+ goto bad; \
+ GETCHAR(citype, p); \
+ GETCHAR(cilen, p); \
+ if (cilen != CILEN_CHAP || \
+ citype != opt) \
+ goto bad; \
+ GETSHORT(cishort, p); \
+ if (cishort != val) \
+ goto bad; \
+ GETCHAR(cichar, p); \
+ if (cichar != digest) \
+ goto bad; \
+ }
+#define ACKCILONG(opt, neg, val) \
+ if (neg) { \
+ if ((len -= CILEN_LONG) < 0) \
+ goto bad; \
+ GETCHAR(citype, p); \
+ GETCHAR(cilen, p); \
+ if (cilen != CILEN_LONG || \
+ citype != opt) \
+ goto bad; \
+ GETLONG(cilong, p); \
+ if (cilong != val) \
+ goto bad; \
+ }
+#define ACKCILQR(opt, neg, val) \
+ if (neg) { \
+ if ((len -= CILEN_LQR) < 0) \
+ goto bad; \
+ GETCHAR(citype, p); \
+ GETCHAR(cilen, p); \
+ if (cilen != CILEN_LQR || \
+ citype != opt) \
+ goto bad; \
+ GETSHORT(cishort, p); \
+ if (cishort != PPP_LQR) \
+ goto bad; \
+ GETLONG(cilong, p); \
+ if (cilong != val) \
+ goto bad; \
+ }
+
+ ACKCISHORT(CI_MRU, go->neg_mru && go->mru != DEFMRU, go->mru);
+ ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF,
+ go->asyncmap);
+ ACKCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype);
+ ACKCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP);
+ ACKCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
+ ACKCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT);
+ ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
+ ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
+ ACKCIVOID(CI_ACCOMPRESSION, go->neg_accompression);
+
+ /*
+ * If there are any remaining CIs, then this packet is bad.
+ */
+ if (len != 0)
+ goto bad;
+ return (1);
+bad:
+ LCPDEBUG(("lcp_acki: received bad Ack!"));
+ return (0);
+}
+
+
+/*
+ * lcp_nakci - Peer has sent a NAK for some of our CIs.
+ * This should not modify any state if the Nak is bad
+ * or if LCP is in the OPENED state.
+ *
+ * Returns:
+ * 0 - Nak was bad.
+ * 1 - Nak was good.
+ */
+static int
+lcp_nakci(f, p, len)
+ fsm *f;
+ u_char *p;
+ int len;
+{
+ lcp_options *go = &lcp_gotoptions[f->unit];
+ lcp_options *wo = &lcp_wantoptions[f->unit];
+ u_char citype, cichar, *next;
+ u_short cishort;
+ u_int32_t cilong;
+ lcp_options no; /* options we've seen Naks for */
+ lcp_options try; /* options to request next time */
+ int looped_back = 0;
+ int cilen;
+
+ BZERO(&no, sizeof(no));
+ try = *go;
+
+ /*
+ * Any Nak'd CIs must be in exactly the same order that we sent.
+ * Check packet length and CI length at each step.
+ * If we find any deviations, then this packet is bad.
+ */
+#define NAKCIVOID(opt, neg, code) \
+ if (go->neg && \
+ len >= CILEN_VOID && \
+ p[1] == CILEN_VOID && \
+ p[0] == opt) { \
+ len -= CILEN_VOID; \
+ INCPTR(CILEN_VOID, p); \
+ no.neg = 1; \
+ code \
+ }
+#define NAKCICHAP(opt, neg, code) \
+ if (go->neg && \
+ len >= CILEN_CHAP && \
+ p[1] == CILEN_CHAP && \
+ p[0] == opt) { \
+ len -= CILEN_CHAP; \
+ INCPTR(2, p); \
+ GETSHORT(cishort, p); \
+ GETCHAR(cichar, p); \
+ no.neg = 1; \
+ code \
+ }
+#define NAKCICHAR(opt, neg, code) \
+ if (go->neg && \
+ len >= CILEN_CHAR && \
+ p[1] == CILEN_CHAR && \
+ p[0] == opt) { \
+ len -= CILEN_CHAR; \
+ INCPTR(2, p); \
+ GETCHAR(cichar, p); \
+ no.neg = 1; \
+ code \
+ }
+#define NAKCISHORT(opt, neg, code) \
+ if (go->neg && \
+ len >= CILEN_SHORT && \
+ p[1] == CILEN_SHORT && \
+ p[0] == opt) { \
+ len -= CILEN_SHORT; \
+ INCPTR(2, p); \
+ GETSHORT(cishort, p); \
+ no.neg = 1; \
+ code \
+ }
+#define NAKCILONG(opt, neg, code) \
+ if (go->neg && \
+ len >= CILEN_LONG && \
+ p[1] == CILEN_LONG && \
+ p[0] == opt) { \
+ len -= CILEN_LONG; \
+ INCPTR(2, p); \
+ GETLONG(cilong, p); \
+ no.neg = 1; \
+ code \
+ }
+#define NAKCILQR(opt, neg, code) \
+ if (go->neg && \
+ len >= CILEN_LQR && \
+ p[1] == CILEN_LQR && \
+ p[0] == opt) { \
+ len -= CILEN_LQR; \
+ INCPTR(2, p); \
+ GETSHORT(cishort, p); \
+ GETLONG(cilong, p); \
+ no.neg = 1; \
+ code \
+ }
+
+ /*
+ * We don't care if they want to send us smaller packets than
+ * we want. Therefore, accept any MRU less than what we asked for,
+ * but then ignore the new value when setting the MRU in the kernel.
+ * If they send us a bigger MRU than what we asked, accept it, up to
+ * the limit of the default MRU we'd get if we didn't negotiate.
+ */
+ if (go->neg_mru && go->mru != DEFMRU) {
+ NAKCISHORT(CI_MRU, neg_mru,
+ if (cishort <= wo->mru || cishort <= DEFMRU)
+ try.mru = cishort;
+ );
+ }
+
+ /*
+ * Add any characters they want to our (receive-side) asyncmap.
+ */
+ if (go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) {
+ NAKCILONG(CI_ASYNCMAP, neg_asyncmap,
+ try.asyncmap = go->asyncmap | cilong;
+ );
+ }
+
+ /*
+ * If they've nak'd our authentication-protocol, check whether
+ * they are proposing a different protocol, or a different
+ * hash algorithm for CHAP.
+ */
+ if ((go->neg_chap || go->neg_upap)
+ && len >= CILEN_SHORT
+ && p[0] == CI_AUTHTYPE && p[1] >= CILEN_SHORT && p[1] <= len) {
+ cilen = p[1];
+ len -= cilen;
+ no.neg_chap = go->neg_chap;
+ no.neg_upap = go->neg_upap;
+ INCPTR(2, p);
+ GETSHORT(cishort, p);
+ if (cishort == PPP_PAP && cilen == CILEN_SHORT) {
+ /*
+ * If we were asking for CHAP, they obviously don't want to do it.
+ * If we weren't asking for CHAP, then we were asking for PAP,
+ * in which case this Nak is bad.
+ */
+ if (!go->neg_chap)
+ goto bad;
+ try.neg_chap = 0;
+
+ } else if (cishort == PPP_CHAP && cilen == CILEN_CHAP) {
+ GETCHAR(cichar, p);
+ if (go->neg_chap) {
+ /*
+ * We were asking for CHAP/MD5; they must want a different
+ * algorithm. If they can't do MD5, we can ask for M$-CHAP
+ * if we support it, otherwise we'll have to stop
+ * asking for CHAP.
+ */
+ if (cichar != go->chap_mdtype) {
+#ifdef CHAPMS
+ if (cichar == CHAP_MICROSOFT)
+ go->chap_mdtype = CHAP_MICROSOFT;
+ else
+#endif /* CHAPMS */
+ try.neg_chap = 0;
+ }
+ } else {
+ /*
+ * Stop asking for PAP if we were asking for it.
+ */
+ try.neg_upap = 0;
+ }
+
+ } else {
+ /*
+ * We don't recognize what they're suggesting.
+ * Stop asking for what we were asking for.
+ */
+ if (go->neg_chap)
+ try.neg_chap = 0;
+ else
+ try.neg_upap = 0;
+ p += cilen - CILEN_SHORT;
+ }
+ }
+
+ /*
+ * If they can't cope with our link quality protocol, we'll have
+ * to stop asking for LQR. We haven't got any other protocol.
+ * If they Nak the reporting period, take their value XXX ?
+ */
+ NAKCILQR(CI_QUALITY, neg_lqr,
+ if (cishort != PPP_LQR)
+ try.neg_lqr = 0;
+ else
+ try.lqr_period = cilong;
+ );
+
+ /*
+ * Only implementing CBCP...not the rest of the callback options
+ */
+ NAKCICHAR(CI_CALLBACK, neg_cbcp,
+ try.neg_cbcp = 0;
+ );
+
+ /*
+ * Check for a looped-back line.
+ */
+ NAKCILONG(CI_MAGICNUMBER, neg_magicnumber,
+ try.magicnumber = magic();
+ looped_back = 1;
+ );
+
+ /*
+ * Peer shouldn't send Nak for protocol compression or
+ * address/control compression requests; they should send
+ * a Reject instead. If they send a Nak, treat it as a Reject.
+ */
+ NAKCIVOID(CI_PCOMPRESSION, neg_pcompression,
+ try.neg_pcompression = 0;
+ );
+ NAKCIVOID(CI_ACCOMPRESSION, neg_accompression,
+ try.neg_accompression = 0;
+ );
+
+ /*
+ * There may be remaining CIs, if the peer is requesting negotiation
+ * on an option that we didn't include in our request packet.
+ * If we see an option that we requested, or one we've already seen
+ * in this packet, then this packet is bad.
+ * If we wanted to respond by starting to negotiate on the requested
+ * option(s), we could, but we don't, because except for the
+ * authentication type and quality protocol, if we are not negotiating
+ * an option, it is because we were told not to.
+ * For the authentication type, the Nak from the peer means
+ * `let me authenticate myself with you' which is a bit pointless.
+ * For the quality protocol, the Nak means `ask me to send you quality
+ * reports', but if we didn't ask for them, we don't want them.
+ * An option we don't recognize represents the peer asking to
+ * negotiate some option we don't support, so ignore it.
+ */
+ while (len > CILEN_VOID) {
+ GETCHAR(citype, p);
+ GETCHAR(cilen, p);
+ if (cilen < CILEN_VOID || (len -= cilen) < 0)
+ goto bad;
+ next = p + cilen - 2;
+
+ switch (citype) {
+ case CI_MRU:
+ if ((go->neg_mru && go->mru != DEFMRU)
+ || no.neg_mru || cilen != CILEN_SHORT)
+ goto bad;
+ GETSHORT(cishort, p);
+ if (cishort < DEFMRU)
+ try.mru = cishort;
+ break;
+ case CI_ASYNCMAP:
+ if ((go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF)
+ || no.neg_asyncmap || cilen != CILEN_LONG)
+ goto bad;
+ break;
+ case CI_AUTHTYPE:
+ if (go->neg_chap || no.neg_chap || go->neg_upap || no.neg_upap)
+ goto bad;
+ break;
+ case CI_MAGICNUMBER:
+ if (go->neg_magicnumber || no.neg_magicnumber ||
+ cilen != CILEN_LONG)
+ goto bad;
+ break;
+ case CI_PCOMPRESSION:
+ if (go->neg_pcompression || no.neg_pcompression
+ || cilen != CILEN_VOID)
+ goto bad;
+ break;
+ case CI_ACCOMPRESSION:
+ if (go->neg_accompression || no.neg_accompression
+ || cilen != CILEN_VOID)
+ goto bad;
+ break;
+ case CI_QUALITY:
+ if (go->neg_lqr || no.neg_lqr || cilen != CILEN_LQR)
+ goto bad;
+ break;
+ }
+ p = next;
+ }
+
+ /*
+ * OK, the Nak is good. Now we can update state.
+ * If there are any options left we ignore them.
+ */
+ if (f->state != OPENED) {
+ if (looped_back) {
+ if (++try.numloops >= lcp_loopbackfail) {
+ notice("Serial line is looped back.");
+ lcp_close(f->unit, "Loopback detected");
+ pppd_status = EXIT_LOOPBACK;
+ }
+ } else
+ try.numloops = 0;
+ *go = try;
+ }
+
+ return 1;
+
+bad:
+ LCPDEBUG(("lcp_nakci: received bad Nak!"));
+ return 0;
+}
+
+
+/*
+ * lcp_rejci - Peer has Rejected some of our CIs.
+ * This should not modify any state if the Reject is bad
+ * or if LCP is in the OPENED state.
+ *
+ * Returns:
+ * 0 - Reject was bad.
+ * 1 - Reject was good.
+ */
+static int
+lcp_rejci(f, p, len)
+ fsm *f;
+ u_char *p;
+ int len;
+{
+ lcp_options *go = &lcp_gotoptions[f->unit];
+ u_char cichar;
+ u_short cishort;
+ u_int32_t cilong;
+ lcp_options try; /* options to request next time */
+
+ try = *go;
+
+ /*
+ * Any Rejected CIs must be in exactly the same order that we sent.
+ * Check packet length and CI length at each step.
+ * If we find any deviations, then this packet is bad.
+ */
+#define REJCIVOID(opt, neg) \
+ if (go->neg && \
+ len >= CILEN_VOID && \
+ p[1] == CILEN_VOID && \
+ p[0] == opt) { \
+ len -= CILEN_VOID; \
+ INCPTR(CILEN_VOID, p); \
+ try.neg = 0; \
+ }
+#define REJCISHORT(opt, neg, val) \
+ if (go->neg && \
+ len >= CILEN_SHORT && \
+ p[1] == CILEN_SHORT && \
+ p[0] == opt) { \
+ len -= CILEN_SHORT; \
+ INCPTR(2, p); \
+ GETSHORT(cishort, p); \
+ /* Check rejected value. */ \
+ if (cishort != val) \
+ goto bad; \
+ try.neg = 0; \
+ }
+#define REJCICHAP(opt, neg, val, digest) \
+ if (go->neg && \
+ len >= CILEN_CHAP && \
+ p[1] == CILEN_CHAP && \
+ p[0] == opt) { \
+ len -= CILEN_CHAP; \
+ INCPTR(2, p); \
+ GETSHORT(cishort, p); \
+ GETCHAR(cichar, p); \
+ /* Check rejected value. */ \
+ if (cishort != val || cichar != digest) \
+ goto bad; \
+ try.neg = 0; \
+ try.neg_upap = 0; \
+ }
+#define REJCILONG(opt, neg, val) \
+ if (go->neg && \
+ len >= CILEN_LONG && \
+ p[1] == CILEN_LONG && \
+ p[0] == opt) { \
+ len -= CILEN_LONG; \
+ INCPTR(2, p); \
+ GETLONG(cilong, p); \
+ /* Check rejected value. */ \
+ if (cilong != val) \
+ goto bad; \
+ try.neg = 0; \
+ }
+#define REJCILQR(opt, neg, val) \
+ if (go->neg && \
+ len >= CILEN_LQR && \
+ p[1] == CILEN_LQR && \
+ p[0] == opt) { \
+ len -= CILEN_LQR; \
+ INCPTR(2, p); \
+ GETSHORT(cishort, p); \
+ GETLONG(cilong, p); \
+ /* Check rejected value. */ \
+ if (cishort != PPP_LQR || cilong != val) \
+ goto bad; \
+ try.neg = 0; \
+ }
+#define REJCICBCP(opt, neg, val) \
+ if (go->neg && \
+ len >= CILEN_CBCP && \
+ p[1] == CILEN_CBCP && \
+ p[0] == opt) { \
+ len -= CILEN_CBCP; \
+ INCPTR(2, p); \
+ GETCHAR(cichar, p); \
+ /* Check rejected value. */ \
+ if (cichar != val) \
+ goto bad; \
+ try.neg = 0; \
+ }
+
+ REJCISHORT(CI_MRU, neg_mru, go->mru);
+ REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap);
+ REJCICHAP(CI_AUTHTYPE, neg_chap, PPP_CHAP, go->chap_mdtype);
+ if (!go->neg_chap) {
+ REJCISHORT(CI_AUTHTYPE, neg_upap, PPP_PAP);
+ }
+ REJCILQR(CI_QUALITY, neg_lqr, go->lqr_period);
+ REJCICBCP(CI_CALLBACK, neg_cbcp, CBCP_OPT);
+ REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber);
+ REJCIVOID(CI_PCOMPRESSION, neg_pcompression);
+ REJCIVOID(CI_ACCOMPRESSION, neg_accompression);
+
+ /*
+ * If there are any remaining CIs, then this packet is bad.
+ */
+ if (len != 0)
+ goto bad;
+ /*
+ * Now we can update state.
+ */
+ if (f->state != OPENED)
+ *go = try;
+ return 1;
+
+bad:
+ LCPDEBUG(("lcp_rejci: received bad Reject!"));
+ return 0;
+}
+
+
+/*
+ * lcp_reqci - Check the peer's requested CIs and send appropriate response.
+ *
+ * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
+ * appropriately. If reject_if_disagree is non-zero, doesn't return
+ * CONFNAK; returns CONFREJ if it can't return CONFACK.
+ */
+static int
+lcp_reqci(f, inp, lenp, reject_if_disagree)
+ fsm *f;
+ u_char *inp; /* Requested CIs */
+ int *lenp; /* Length of requested CIs */
+ int reject_if_disagree;
+{
+ lcp_options *go = &lcp_gotoptions[f->unit];
+ lcp_options *ho = &lcp_hisoptions[f->unit];
+ lcp_options *ao = &lcp_allowoptions[f->unit];
+ u_char *cip, *next; /* Pointer to current and next CIs */
+ int cilen, citype, cichar; /* Parsed len, type, char value */
+ u_short cishort; /* Parsed short value */
+ u_int32_t cilong; /* Parse long value */
+ int rc = CONFACK; /* Final packet return code */
+ int orc; /* Individual option return code */
+ u_char *p; /* Pointer to next char to parse */
+ u_char *rejp; /* Pointer to next char in reject frame */
+ u_char *nakp; /* Pointer to next char in Nak frame */
+ int l = *lenp; /* Length left */
+
+ /*
+ * Reset all his options.
+ */
+ BZERO(ho, sizeof(*ho));
+
+ /*
+ * Process all his options.
+ */
+ next = inp;
+ nakp = nak_buffer;
+ rejp = inp;
+ while (l) {
+ orc = CONFACK; /* Assume success */
+ cip = p = next; /* Remember begining of CI */
+ if (l < 2 || /* Not enough data for CI header or */
+ p[1] < 2 || /* CI length too small or */
+ p[1] > l) { /* CI length too big? */
+ LCPDEBUG(("lcp_reqci: bad CI length!"));
+ orc = CONFREJ; /* Reject bad CI */
+ cilen = l; /* Reject till end of packet */
+ l = 0; /* Don't loop again */
+ citype = 0;
+ goto endswitch;
+ }
+ GETCHAR(citype, p); /* Parse CI type */
+ GETCHAR(cilen, p); /* Parse CI length */
+ l -= cilen; /* Adjust remaining length */
+ next += cilen; /* Step to next CI */
+
+ switch (citype) { /* Check CI type */
+ case CI_MRU:
+ if (!ao->neg_mru || /* Allow option? */
+ cilen != CILEN_SHORT) { /* Check CI length */
+ orc = CONFREJ; /* Reject CI */
+ break;
+ }
+ GETSHORT(cishort, p); /* Parse MRU */
+
+ /*
+ * He must be able to receive at least our minimum.
+ * No need to check a maximum. If he sends a large number,
+ * we'll just ignore it.
+ */
+ if (cishort < MINMRU) {
+ orc = CONFNAK; /* Nak CI */
+ PUTCHAR(CI_MRU, nakp);
+ PUTCHAR(CILEN_SHORT, nakp);
+ PUTSHORT(MINMRU, nakp); /* Give him a hint */
+ break;
+ }
+ ho->neg_mru = 1; /* Remember he sent MRU */
+ ho->mru = cishort; /* And remember value */
+ break;
+
+ case CI_ASYNCMAP:
+ if (!ao->neg_asyncmap ||
+ cilen != CILEN_LONG) {
+ orc = CONFREJ;
+ break;
+ }
+ GETLONG(cilong, p);
+
+ /*
+ * Asyncmap must have set at least the bits
+ * which are set in lcp_allowoptions[unit].asyncmap.
+ */
+ if ((ao->asyncmap & ~cilong) != 0) {
+ orc = CONFNAK;
+ PUTCHAR(CI_ASYNCMAP, nakp);
+ PUTCHAR(CILEN_LONG, nakp);
+ PUTLONG(ao->asyncmap | cilong, nakp);
+ break;
+ }
+ ho->neg_asyncmap = 1;
+ ho->asyncmap = cilong;
+ break;
+
+ case CI_AUTHTYPE:
+ if (cilen < CILEN_SHORT ||
+ !(ao->neg_upap || ao->neg_chap)) {
+ /*
+ * Reject the option if we're not willing to authenticate.
+ */
+ orc = CONFREJ;
+ break;
+ }
+ GETSHORT(cishort, p);
+
+ /*
+ * Authtype must be PAP or CHAP.
+ *
+ * Note: if both ao->neg_upap and ao->neg_chap are set,
+ * and the peer sends a Configure-Request with two
+ * authenticate-protocol requests, one for CHAP and one
+ * for UPAP, then we will reject the second request.
+ * Whether we end up doing CHAP or UPAP depends then on
+ * the ordering of the CIs in the peer's Configure-Request.
+ */
+
+ if (cishort == PPP_PAP) {
+ if (ho->neg_chap || /* we've already accepted CHAP */
+ cilen != CILEN_SHORT) {
+ LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE PAP, rejecting..."));
+ orc = CONFREJ;
+ break;
+ }
+ if (!ao->neg_upap) { /* we don't want to do PAP */
+ orc = CONFNAK; /* NAK it and suggest CHAP */
+ PUTCHAR(CI_AUTHTYPE, nakp);
+ PUTCHAR(CILEN_CHAP, nakp);
+ PUTSHORT(PPP_CHAP, nakp);
+ PUTCHAR(ao->chap_mdtype, nakp);
+ /* XXX if we can do CHAP_MICROSOFT as well, we should
+ probably put in another option saying so */
+ break;
+ }
+ ho->neg_upap = 1;
+ break;
+ }
+ if (cishort == PPP_CHAP) {
+ if (ho->neg_upap || /* we've already accepted PAP */
+ cilen != CILEN_CHAP) {
+ LCPDEBUG(("lcp_reqci: rcvd AUTHTYPE CHAP, rejecting..."));
+ orc = CONFREJ;
+ break;
+ }
+ if (!ao->neg_chap) { /* we don't want to do CHAP */
+ orc = CONFNAK; /* NAK it and suggest PAP */
+ PUTCHAR(CI_AUTHTYPE, nakp);
+ PUTCHAR(CILEN_SHORT, nakp);
+ PUTSHORT(PPP_PAP, nakp);
+ break;
+ }
+ GETCHAR(cichar, p); /* get digest type*/
+ if (cichar != CHAP_DIGEST_MD5
+#ifdef CHAPMS
+ && cichar != CHAP_MICROSOFT
+#endif
+ ) {
+ orc = CONFNAK;
+ PUTCHAR(CI_AUTHTYPE, nakp);
+ PUTCHAR(CILEN_CHAP, nakp);
+ PUTSHORT(PPP_CHAP, nakp);
+ PUTCHAR(ao->chap_mdtype, nakp);
+ break;
+ }
+ ho->chap_mdtype = cichar; /* save md type */
+ ho->neg_chap = 1;
+ break;
+ }
+
+ /*
+ * We don't recognize the protocol they're asking for.
+ * Nak it with something we're willing to do.
+ * (At this point we know ao->neg_upap || ao->neg_chap.)
+ */
+ orc = CONFNAK;
+ PUTCHAR(CI_AUTHTYPE, nakp);
+ if (ao->neg_chap) {
+ PUTCHAR(CILEN_CHAP, nakp);
+ PUTSHORT(PPP_CHAP, nakp);
+ PUTCHAR(ao->chap_mdtype, nakp);
+ } else {
+ PUTCHAR(CILEN_SHORT, nakp);
+ PUTSHORT(PPP_PAP, nakp);
+ }
+ break;
+
+ case CI_QUALITY:
+ if (!ao->neg_lqr ||
+ cilen != CILEN_LQR) {
+ orc = CONFREJ;
+ break;
+ }
+
+ GETSHORT(cishort, p);
+ GETLONG(cilong, p);
+
+ /*
+ * Check the protocol and the reporting period.
+ * XXX When should we Nak this, and what with?
+ */
+ if (cishort != PPP_LQR) {
+ orc = CONFNAK;
+ PUTCHAR(CI_QUALITY, nakp);
+ PUTCHAR(CILEN_LQR, nakp);
+ PUTSHORT(PPP_LQR, nakp);
+ PUTLONG(ao->lqr_period, nakp);
+ break;
+ }
+ break;
+
+ case CI_MAGICNUMBER:
+ if (!(ao->neg_magicnumber || go->neg_magicnumber) ||
+ cilen != CILEN_LONG) {
+ orc = CONFREJ;
+ break;
+ }
+ GETLONG(cilong, p);
+
+ /*
+ * He must have a different magic number.
+ */
+ if (go->neg_magicnumber &&
+ cilong == go->magicnumber) {
+ cilong = magic(); /* Don't put magic() inside macro! */
+ orc = CONFNAK;
+ PUTCHAR(CI_MAGICNUMBER, nakp);
+ PUTCHAR(CILEN_LONG, nakp);
+ PUTLONG(cilong, nakp);
+ break;
+ }
+ ho->neg_magicnumber = 1;
+ ho->magicnumber = cilong;
+ break;
+
+
+ case CI_PCOMPRESSION:
+ if (!ao->neg_pcompression ||
+ cilen != CILEN_VOID) {
+ orc = CONFREJ;
+ break;
+ }
+ ho->neg_pcompression = 1;
+ break;
+
+ case CI_ACCOMPRESSION:
+ if (!ao->neg_accompression ||
+ cilen != CILEN_VOID) {
+ orc = CONFREJ;
+ break;
+ }
+ ho->neg_accompression = 1;
+ break;
+
+ default:
+ LCPDEBUG(("lcp_reqci: rcvd unknown option %d", citype));
+ orc = CONFREJ;
+ break;
+ }
+
+endswitch:
+ if (orc == CONFACK && /* Good CI */
+ rc != CONFACK) /* but prior CI wasnt? */
+ continue; /* Don't send this one */
+
+ if (orc == CONFNAK) { /* Nak this CI? */
+ if (reject_if_disagree /* Getting fed up with sending NAKs? */
+ && citype != CI_MAGICNUMBER) {
+ orc = CONFREJ; /* Get tough if so */
+ } else {
+ if (rc == CONFREJ) /* Rejecting prior CI? */
+ continue; /* Don't send this one */
+ rc = CONFNAK;
+ }
+ }
+ if (orc == CONFREJ) { /* Reject this CI */
+ rc = CONFREJ;
+ if (cip != rejp) /* Need to move rejected CI? */
+ BCOPY(cip, rejp, cilen); /* Move it */
+ INCPTR(cilen, rejp); /* Update output pointer */
+ }
+ }
+
+ /*
+ * If we wanted to send additional NAKs (for unsent CIs), the
+ * code would go here. The extra NAKs would go at *nakp.
+ * At present there are no cases where we want to ask the
+ * peer to negotiate an option.
+ */
+
+ switch (rc) {
+ case CONFACK:
+ *lenp = next - inp;
+ break;
+ case CONFNAK:
+ /*
+ * Copy the Nak'd options from the nak_buffer to the caller's buffer.
+ */
+ *lenp = nakp - nak_buffer;
+ BCOPY(nak_buffer, inp, *lenp);
+ break;
+ case CONFREJ:
+ *lenp = rejp - inp;
+ break;
+ }
+
+ LCPDEBUG(("lcp_reqci: returning CONF%s.", CODENAME(rc)));
+ return (rc); /* Return final code */
+}
+
+
+/*
+ * lcp_up - LCP has come UP.
+ */
+static void
+lcp_up(f)
+ fsm *f;
+{
+ lcp_options *wo = &lcp_wantoptions[f->unit];
+ lcp_options *ho = &lcp_hisoptions[f->unit];
+ lcp_options *go = &lcp_gotoptions[f->unit];
+ lcp_options *ao = &lcp_allowoptions[f->unit];
+
+ if (!go->neg_magicnumber)
+ go->magicnumber = 0;
+ if (!ho->neg_magicnumber)
+ ho->magicnumber = 0;
+
+ /*
+ * Set our MTU to the smaller of the MTU we wanted and
+ * the MRU our peer wanted. If we negotiated an MRU,
+ * set our MRU to the larger of value we wanted and
+ * the value we got in the negotiation.
+ */
+ ppp_send_config(f->unit, MIN(ao->mru, (ho->neg_mru? ho->mru: PPP_MRU)),
+ (ho->neg_asyncmap? ho->asyncmap: 0xffffffff),
+ ho->neg_pcompression, ho->neg_accompression);
+ ppp_recv_config(f->unit, (go->neg_mru? MAX(wo->mru, go->mru): PPP_MRU),
+ (lax_recv? 0: go->neg_asyncmap? go->asyncmap: 0xffffffff),
+ go->neg_pcompression, go->neg_accompression);
+
+ if (ho->neg_mru)
+ peer_mru[f->unit] = ho->mru;
+
+ lcp_echo_lowerup(f->unit); /* Enable echo messages */
+
+ link_established(f->unit);
+}
+
+
+/*
+ * lcp_down - LCP has gone DOWN.
+ *
+ * Alert other protocols.
+ */
+static void
+lcp_down(f)
+ fsm *f;
+{
+ lcp_options *go = &lcp_gotoptions[f->unit];
+
+ lcp_echo_lowerdown(f->unit);
+
+ link_down(f->unit);
+
+ ppp_send_config(f->unit, PPP_MRU, 0xffffffff, 0, 0);
+ ppp_recv_config(f->unit, PPP_MRU,
+ (go->neg_asyncmap? go->asyncmap: 0xffffffff),
+ go->neg_pcompression, go->neg_accompression);
+ peer_mru[f->unit] = PPP_MRU;
+}
+
+
+/*
+ * lcp_starting - LCP needs the lower layer up.
+ */
+static void
+lcp_starting(f)
+ fsm *f;
+{
+ link_required(f->unit);
+}
+
+
+/*
+ * lcp_finished - LCP has finished with the lower layer.
+ */
+static void
+lcp_finished(f)
+ fsm *f;
+{
+ link_terminated(f->unit);
+}
+
+
+/*
+ * lcp_printpkt - print the contents of an LCP packet.
+ */
+static char *lcp_codenames[] = {
+ "ConfReq", "ConfAck", "ConfNak", "ConfRej",
+ "TermReq", "TermAck", "CodeRej", "ProtRej",
+ "EchoReq", "EchoRep", "DiscReq"
+};
+
+static int
+lcp_printpkt(p, plen, printer, arg)
+ u_char *p;
+ int plen;
+ void (*printer) __P((void *, char *, ...));
+ void *arg;
+{
+ int code, id, len, olen;
+ u_char *pstart, *optend;
+ u_short cishort;
+ u_int32_t cilong;
+
+ if (plen < HEADERLEN)
+ return 0;
+ pstart = p;
+ GETCHAR(code, p);
+ GETCHAR(id, p);
+ GETSHORT(len, p);
+ if (len < HEADERLEN || len > plen)
+ return 0;
+
+ if (code >= 1 && code <= sizeof(lcp_codenames) / sizeof(char *))
+ printer(arg, " %s", lcp_codenames[code-1]);
+ else
+ printer(arg, " code=0x%x", code);
+ printer(arg, " id=0x%x", id);
+ len -= HEADERLEN;
+ switch (code) {
+ case CONFREQ:
+ case CONFACK:
+ case CONFNAK:
+ case CONFREJ:
+ /* print option list */
+ while (len >= 2) {
+ GETCHAR(code, p);
+ GETCHAR(olen, p);
+ p -= 2;
+ if (olen < 2 || olen > len) {
+ break;
+ }
+ printer(arg, " <");
+ len -= olen;
+ optend = p + olen;
+ switch (code) {
+ case CI_MRU:
+ if (olen == CILEN_SHORT) {
+ p += 2;
+ GETSHORT(cishort, p);
+ printer(arg, "mru %d", cishort);
+ }
+ break;
+ case CI_ASYNCMAP:
+ if (olen == CILEN_LONG) {
+ p += 2;
+ GETLONG(cilong, p);
+ printer(arg, "asyncmap 0x%x", cilong);
+ }
+ break;
+ case CI_AUTHTYPE:
+ if (olen >= CILEN_SHORT) {
+ p += 2;
+ printer(arg, "auth ");
+ GETSHORT(cishort, p);
+ switch (cishort) {
+ case PPP_PAP:
+ printer(arg, "pap");
+ break;
+ case PPP_CHAP:
+ printer(arg, "chap");
+ if (p < optend) {
+ switch (*p) {
+ case CHAP_DIGEST_MD5:
+ printer(arg, " MD5");
+ ++p;
+ break;
+#ifdef CHAPMS
+ case CHAP_MICROSOFT:
+ printer(arg, " m$oft");
+ ++p;
+ break;
+#endif
+ }
+ }
+ break;
+ default:
+ printer(arg, "0x%x", cishort);
+ }
+ }
+ break;
+ case CI_QUALITY:
+ if (olen >= CILEN_SHORT) {
+ p += 2;
+ printer(arg, "quality ");
+ GETSHORT(cishort, p);
+ switch (cishort) {
+ case PPP_LQR:
+ printer(arg, "lqr");
+ break;
+ default:
+ printer(arg, "0x%x", cishort);
+ }
+ }
+ break;
+ case CI_CALLBACK:
+ if (olen >= CILEN_CHAR) {
+ p += 2;
+ printer(arg, "callback ");
+ GETCHAR(cishort, p);
+ switch (cishort) {
+ case CBCP_OPT:
+ printer(arg, "CBCP");
+ break;
+ default:
+ printer(arg, "0x%x", cishort);
+ }
+ }
+ break;
+ case CI_MAGICNUMBER:
+ if (olen == CILEN_LONG) {
+ p += 2;
+ GETLONG(cilong, p);
+ printer(arg, "magic 0x%x", cilong);
+ }
+ break;
+ case CI_PCOMPRESSION:
+ if (olen == CILEN_VOID) {
+ p += 2;
+ printer(arg, "pcomp");
+ }
+ break;
+ case CI_ACCOMPRESSION:
+ if (olen == CILEN_VOID) {
+ p += 2;
+ printer(arg, "accomp");
+ }
+ break;
+ }
+ while (p < optend) {
+ GETCHAR(code, p);
+ printer(arg, " %.2x", code);
+ }
+ printer(arg, ">");
+ }
+ break;
+
+ case TERMACK:
+ case TERMREQ:
+ if (len > 0 && *p >= ' ' && *p < 0x7f) {
+ printer(arg, " ");
+ print_string(p, len, printer, arg);
+ p += len;
+ len = 0;
+ }
+ break;
+
+ case ECHOREQ:
+ case ECHOREP:
+ case DISCREQ:
+ if (len >= 4) {
+ GETLONG(cilong, p);
+ printer(arg, " magic=0x%x", cilong);
+ p += 4;
+ len -= 4;
+ }
+ break;
+ }
+
+ /* print the rest of the bytes in the packet */
+ for (; len > 0; --len) {
+ GETCHAR(code, p);
+ printer(arg, " %.2x", code);
+ }
+
+ return p - pstart;
+}
+
+/*
+ * Time to shut down the link because there is nothing out there.
+ */
+
+static
+void LcpLinkFailure (f)
+ fsm *f;
+{
+ if (f->state == OPENED) {
+ info("No response to %d echo-requests", lcp_echos_pending);
+ notice("Serial link appears to be disconnected.");
+ lcp_close(f->unit, "Peer not responding");
+ pppd_status = EXIT_PEER_DEAD;
+ }
+}
+
+/*
+ * Timer expired for the LCP echo requests from this process.
+ */
+
+static void
+LcpEchoCheck (f)
+ fsm *f;
+{
+ LcpSendEchoRequest (f);
+ if (f->state != OPENED)
+ return;
+
+ /*
+ * Start the timer for the next interval.
+ */
+ if (lcp_echo_timer_running)
+ warn("assertion lcp_echo_timer_running==0 failed");
+ TIMEOUT (LcpEchoTimeout, f, lcp_echo_interval);
+ lcp_echo_timer_running = 1;
+}
+
+/*
+ * LcpEchoTimeout - Timer expired on the LCP echo
+ */
+
+static void
+LcpEchoTimeout (arg)
+ void *arg;
+{
+ if (lcp_echo_timer_running != 0) {
+ lcp_echo_timer_running = 0;
+ LcpEchoCheck ((fsm *) arg);
+ }
+}
+
+/*
+ * LcpEchoReply - LCP has received a reply to the echo
+ */
+
+static void
+lcp_received_echo_reply (f, id, inp, len)
+ fsm *f;
+ int id;
+ u_char *inp;
+ int len;
+{
+ u_int32_t magic;
+
+ /* Check the magic number - don't count replies from ourselves. */
+ if (len < 4) {
+ dbglog("lcp: received short Echo-Reply, length %d", len);
+ return;
+ }
+ GETLONG(magic, inp);
+ if (lcp_gotoptions[f->unit].neg_magicnumber
+ && magic == lcp_gotoptions[f->unit].magicnumber) {
+ warn("appear to have received our own echo-reply!");
+ return;
+ }
+
+ /* Reset the number of outstanding echo frames */
+ lcp_echos_pending = 0;
+}
+
+/*
+ * LcpSendEchoRequest - Send an echo request frame to the peer
+ */
+
+static void
+LcpSendEchoRequest (f)
+ fsm *f;
+{
+ u_int32_t lcp_magic;
+ u_char pkt[4], *pktp;
+
+ /*
+ * Detect the failure of the peer at this point.
+ */
+ if (lcp_echo_fails != 0) {
+ if (lcp_echos_pending >= lcp_echo_fails) {
+ LcpLinkFailure(f);
+ lcp_echos_pending = 0;
+ }
+ }
+
+ /*
+ * Make and send the echo request frame.
+ */
+ if (f->state == OPENED) {
+ lcp_magic = lcp_gotoptions[f->unit].magicnumber;
+ pktp = pkt;
+ PUTLONG(lcp_magic, pktp);
+ fsm_sdata(f, ECHOREQ, lcp_echo_number++ & 0xFF, pkt, pktp - pkt);
+ ++lcp_echos_pending;
+ }
+}
+
+/*
+ * lcp_echo_lowerup - Start the timer for the LCP frame
+ */
+
+static void
+lcp_echo_lowerup (unit)
+ int unit;
+{
+ fsm *f = &lcp_fsm[unit];
+
+ /* Clear the parameters for generating echo frames */
+ lcp_echos_pending = 0;
+ lcp_echo_number = 0;
+ lcp_echo_timer_running = 0;
+
+ /* If a timeout interval is specified then start the timer */
+ if (lcp_echo_interval != 0)
+ LcpEchoCheck (f);
+}
+
+/*
+ * lcp_echo_lowerdown - Stop the timer for the LCP frame
+ */
+
+static void
+lcp_echo_lowerdown (unit)
+ int unit;
+{
+ fsm *f = &lcp_fsm[unit];
+
+ if (lcp_echo_timer_running != 0) {
+ UNTIMEOUT (LcpEchoTimeout, f);
+ lcp_echo_timer_running = 0;
+ }
+}
diff --git a/cpukit/pppd/lcp.h b/cpukit/pppd/lcp.h
new file mode 100644
index 0000000000..16ba4cc44b
--- /dev/null
+++ b/cpukit/pppd/lcp.h
@@ -0,0 +1,88 @@
+/*
+ * lcp.h - Link Control Protocol definitions.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * $Id$
+ */
+
+/*
+ * Options.
+ */
+#define CI_MRU 1 /* Maximum Receive Unit */
+#define CI_ASYNCMAP 2 /* Async Control Character Map */
+#define CI_AUTHTYPE 3 /* Authentication Type */
+#define CI_QUALITY 4 /* Quality Protocol */
+#define CI_MAGICNUMBER 5 /* Magic Number */
+#define CI_PCOMPRESSION 7 /* Protocol Field Compression */
+#define CI_ACCOMPRESSION 8 /* Address/Control Field Compression */
+#define CI_CALLBACK 13 /* callback */
+
+/*
+ * LCP-specific packet types.
+ */
+#define PROTREJ 8 /* Protocol Reject */
+#define ECHOREQ 9 /* Echo Request */
+#define ECHOREP 10 /* Echo Reply */
+#define DISCREQ 11 /* Discard Request */
+#define CBCP_OPT 6 /* Use callback control protocol */
+
+/*
+ * The state of options is described by an lcp_options structure.
+ */
+typedef struct lcp_options {
+ bool passive; /* Don't die if we don't get a response */
+ bool silent; /* Wait for the other end to start first */
+ bool restart; /* Restart vs. exit after close */
+ bool neg_mru; /* Negotiate the MRU? */
+ bool neg_asyncmap; /* Negotiate the async map? */
+ bool neg_upap; /* Ask for UPAP authentication? */
+ bool neg_chap; /* Ask for CHAP authentication? */
+ bool neg_magicnumber; /* Ask for magic number? */
+ bool neg_pcompression; /* HDLC Protocol Field Compression? */
+ bool neg_accompression; /* HDLC Address/Control Field Compression? */
+ bool neg_lqr; /* Negotiate use of Link Quality Reports */
+ bool neg_cbcp; /* Negotiate use of CBCP */
+ int mru; /* Value of MRU */
+ u_char chap_mdtype; /* which MD type (hashing algorithm) */
+ u_int32_t asyncmap; /* Value of async map */
+ u_int32_t magicnumber;
+ int numloops; /* Number of loops during magic number neg. */
+ u_int32_t lqr_period; /* Reporting period for LQR 1/100ths second */
+} lcp_options;
+
+extern fsm lcp_fsm[];
+extern lcp_options lcp_wantoptions[];
+extern lcp_options lcp_gotoptions[];
+extern lcp_options lcp_allowoptions[];
+extern lcp_options lcp_hisoptions[];
+extern u_int32_t xmit_accm[][8];
+
+#define DEFMRU 1500 /* Try for this */
+#define MINMRU 128 /* No MRUs below this */
+#define MAXMRU 16384 /* Normally limit MRU to this */
+
+void lcp_open __P((int));
+void lcp_close __P((int, char *));
+void lcp_lowerup __P((int));
+void lcp_lowerdown __P((int));
+void lcp_sprotrej __P((int, u_char *, int)); /* send protocol reject */
+
+extern struct protent lcp_protent;
+
+/* Default number of times we receive our magic number from the peer
+ before deciding the link is looped-back. */
+#define DEFLOOPBACKFAIL 10
diff --git a/cpukit/pppd/magic.c b/cpukit/pppd/magic.c
new file mode 100644
index 0000000000..3013e08f07
--- /dev/null
+++ b/cpukit/pppd/magic.c
@@ -0,0 +1,58 @@
+/*
+ * magic.c - PPP Magic Number routines.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#define RCSID "$Id$"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include "pppd.h"
+#include "magic.h"
+
+static const char rcsid[] = RCSID;
+
+/*
+ * magic_init - Initialize the magic number generator.
+ *
+ * Attempts to compute a random number seed which will not repeat.
+ * The current method uses the current hostid, current process ID
+ * and current time, currently.
+ */
+void
+magic_init()
+{
+ long seed;
+ struct timeval t;
+
+ gettimeofday(&t, NULL);
+ seed = get_host_seed() ^ t.tv_sec ^ t.tv_usec ^ getpid();
+ srand48(seed);
+}
+
+/*
+ * magic - Returns the next magic number.
+ */
+u_int32_t
+magic()
+{
+ return (u_int32_t) mrand48();
+}
diff --git a/cpukit/pppd/magic.h b/cpukit/pppd/magic.h
new file mode 100644
index 0000000000..1344626a38
--- /dev/null
+++ b/cpukit/pppd/magic.h
@@ -0,0 +1,23 @@
+/*
+ * magic.h - PPP Magic Number definitions.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * $Id$
+ */
+
+void magic_init __P((void)); /* Initialize the magic number generator */
+u_int32_t magic __P((void)); /* Returns the next magic number */
diff --git a/cpukit/pppd/md4.c b/cpukit/pppd/md4.c
new file mode 100644
index 0000000000..cda9f943d0
--- /dev/null
+++ b/cpukit/pppd/md4.c
@@ -0,0 +1,298 @@
+/*
+** ********************************************************************
+** md4.c -- Implementation of MD4 Message Digest Algorithm **
+** Updated: 2/16/90 by Ronald L. Rivest **
+** (C) 1990 RSA Data Security, Inc. **
+** ********************************************************************
+*/
+
+/*
+** To use MD4:
+** -- Include md4.h in your program
+** -- Declare an MDstruct MD to hold the state of the digest
+** computation.
+** -- Initialize MD using MDbegin(&MD)
+** -- For each full block (64 bytes) X you wish to process, call
+** MD4Update(&MD,X,512)
+** (512 is the number of bits in a full block.)
+** -- For the last block (less than 64 bytes) you wish to process,
+** MD4Update(&MD,X,n)
+** where n is the number of bits in the partial block. A partial
+** block terminates the computation, so every MD computation
+** should terminate by processing a partial block, even if it
+** has n = 0.
+** -- The message digest is available in MD.buffer[0] ...
+** MD.buffer[3]. (Least-significant byte of each word
+** should be output first.)
+** -- You can print out the digest using MDprint(&MD)
+*/
+
+/* Implementation notes:
+** This implementation assumes that ints are 32-bit quantities.
+*/
+
+#define TRUE 1
+#define FALSE 0
+
+/* Compile-time includes
+*/
+#include <stdio.h>
+#include "md4.h"
+#include "pppd.h"
+
+/* Compile-time declarations of MD4 "magic constants".
+*/
+#define I0 0x67452301 /* Initial values for MD buffer */
+#define I1 0xefcdab89
+#define I2 0x98badcfe
+#define I3 0x10325476
+#define C2 013240474631 /* round 2 constant = sqrt(2) in octal */
+#define C3 015666365641 /* round 3 constant = sqrt(3) in octal */
+/* C2 and C3 are from Knuth, The Art of Programming, Volume 2
+** (Seminumerical Algorithms), Second Edition (1981), Addison-Wesley.
+** Table 2, page 660.
+*/
+
+#define fs1 3 /* round 1 shift amounts */
+#define fs2 7
+#define fs3 11
+#define fs4 19
+#define gs1 3 /* round 2 shift amounts */
+#define gs2 5
+#define gs3 9
+#define gs4 13
+#define hs1 3 /* round 3 shift amounts */
+#define hs2 9
+#define hs3 11
+#define hs4 15
+
+/* Compile-time macro declarations for MD4.
+** Note: The "rot" operator uses the variable "tmp".
+** It assumes tmp is declared as unsigned int, so that the >>
+** operator will shift in zeros rather than extending the sign bit.
+*/
+#define f(X,Y,Z) ((X&Y) | ((~X)&Z))
+#define g(X,Y,Z) ((X&Y) | (X&Z) | (Y&Z))
+#define h(X,Y,Z) (X^Y^Z)
+#define rot(X,S) (tmp=X,(tmp<<S) | (tmp>>(32-S)))
+#define ff(A,B,C,D,i,s) A = rot((A + f(B,C,D) + X[i]),s)
+#define gg(A,B,C,D,i,s) A = rot((A + g(B,C,D) + X[i] + C2),s)
+#define hh(A,B,C,D,i,s) A = rot((A + h(B,C,D) + X[i] + C3),s)
+
+/* MD4print(MDp)
+** Print message digest buffer MDp as 32 hexadecimal digits.
+** Order is from low-order byte of buffer[0] to high-order byte of
+** buffer[3].
+** Each byte is printed with high-order hexadecimal digit first.
+** This is a user-callable routine.
+*/
+void
+MD4Print(MDp)
+MD4_CTX *MDp;
+{
+ int i,j;
+ for (i=0;i<4;i++)
+ for (j=0;j<32;j=j+8)
+ printf("%02x",(MDp->buffer[i]>>j) & 0xFF);
+}
+
+/* MD4Init(MDp)
+** Initialize message digest buffer MDp.
+** This is a user-callable routine.
+*/
+void
+MD4Init(MDp)
+MD4_CTX *MDp;
+{
+ int i;
+ MDp->buffer[0] = I0;
+ MDp->buffer[1] = I1;
+ MDp->buffer[2] = I2;
+ MDp->buffer[3] = I3;
+ for (i=0;i<8;i++) MDp->count[i] = 0;
+ MDp->done = 0;
+}
+
+/* MDblock(MDp,X)
+** Update message digest buffer MDp->buffer using 16-word data block X.
+** Assumes all 16 words of X are full of data.
+** Does not update MDp->count.
+** This routine is not user-callable.
+*/
+static void
+MDblock(MDp,Xb)
+MD4_CTX *MDp;
+unsigned char *Xb;
+{
+ register unsigned int tmp, A, B, C, D;
+ unsigned int X[16];
+ int i;
+
+ for (i = 0; i < 16; ++i) {
+ X[i] = Xb[0] + (Xb[1] << 8) + (Xb[2] << 16) + (Xb[3] << 24);
+ Xb += 4;
+ }
+
+ A = MDp->buffer[0];
+ B = MDp->buffer[1];
+ C = MDp->buffer[2];
+ D = MDp->buffer[3];
+ /* Update the message digest buffer */
+ ff(A , B , C , D , 0 , fs1); /* Round 1 */
+ ff(D , A , B , C , 1 , fs2);
+ ff(C , D , A , B , 2 , fs3);
+ ff(B , C , D , A , 3 , fs4);
+ ff(A , B , C , D , 4 , fs1);
+ ff(D , A , B , C , 5 , fs2);
+ ff(C , D , A , B , 6 , fs3);
+ ff(B , C , D , A , 7 , fs4);
+ ff(A , B , C , D , 8 , fs1);
+ ff(D , A , B , C , 9 , fs2);
+ ff(C , D , A , B , 10 , fs3);
+ ff(B , C , D , A , 11 , fs4);
+ ff(A , B , C , D , 12 , fs1);
+ ff(D , A , B , C , 13 , fs2);
+ ff(C , D , A , B , 14 , fs3);
+ ff(B , C , D , A , 15 , fs4);
+ gg(A , B , C , D , 0 , gs1); /* Round 2 */
+ gg(D , A , B , C , 4 , gs2);
+ gg(C , D , A , B , 8 , gs3);
+ gg(B , C , D , A , 12 , gs4);
+ gg(A , B , C , D , 1 , gs1);
+ gg(D , A , B , C , 5 , gs2);
+ gg(C , D , A , B , 9 , gs3);
+ gg(B , C , D , A , 13 , gs4);
+ gg(A , B , C , D , 2 , gs1);
+ gg(D , A , B , C , 6 , gs2);
+ gg(C , D , A , B , 10 , gs3);
+ gg(B , C , D , A , 14 , gs4);
+ gg(A , B , C , D , 3 , gs1);
+ gg(D , A , B , C , 7 , gs2);
+ gg(C , D , A , B , 11 , gs3);
+ gg(B , C , D , A , 15 , gs4);
+ hh(A , B , C , D , 0 , hs1); /* Round 3 */
+ hh(D , A , B , C , 8 , hs2);
+ hh(C , D , A , B , 4 , hs3);
+ hh(B , C , D , A , 12 , hs4);
+ hh(A , B , C , D , 2 , hs1);
+ hh(D , A , B , C , 10 , hs2);
+ hh(C , D , A , B , 6 , hs3);
+ hh(B , C , D , A , 14 , hs4);
+ hh(A , B , C , D , 1 , hs1);
+ hh(D , A , B , C , 9 , hs2);
+ hh(C , D , A , B , 5 , hs3);
+ hh(B , C , D , A , 13 , hs4);
+ hh(A , B , C , D , 3 , hs1);
+ hh(D , A , B , C , 11 , hs2);
+ hh(C , D , A , B , 7 , hs3);
+ hh(B , C , D , A , 15 , hs4);
+ MDp->buffer[0] += A;
+ MDp->buffer[1] += B;
+ MDp->buffer[2] += C;
+ MDp->buffer[3] += D;
+}
+
+/* MD4Update(MDp,X,count)
+** Input: X -- a pointer to an array of unsigned characters.
+** count -- the number of bits of X to use.
+** (if not a multiple of 8, uses high bits of last byte.)
+** Update MDp using the number of bits of X given by count.
+** This is the basic input routine for an MD4 user.
+** The routine completes the MD computation when count < 512, so
+** every MD computation should end with one call to MD4Update with a
+** count less than 512. A call with count 0 will be ignored if the
+** MD has already been terminated (done != 0), so an extra call with
+** count 0 can be given as a "courtesy close" to force termination
+** if desired.
+*/
+void
+MD4Update(MDp,X,count)
+MD4_CTX *MDp;
+unsigned char *X;
+unsigned int count;
+{
+ unsigned int i, tmp, bit, byte, mask;
+ unsigned char XX[64];
+ unsigned char *p;
+
+ /* return with no error if this is a courtesy close with count
+ ** zero and MDp->done is true.
+ */
+ if (count == 0 && MDp->done) return;
+ /* check to see if MD is already done and report error */
+ if (MDp->done)
+ { printf("\nError: MD4Update MD already done."); return; }
+
+ /* Add count to MDp->count */
+ tmp = count;
+ p = MDp->count;
+ while (tmp)
+ { tmp += *p;
+ *p++ = tmp;
+ tmp = tmp >> 8;
+ }
+
+ /* Process data */
+ if (count == 512)
+ { /* Full block of data to handle */
+ MDblock(MDp,X);
+ }
+ else if (count > 512) /* Check for count too large */
+ {
+ printf("\nError: MD4Update called with illegal count value %d.",
+ count);
+ return;
+ }
+ else /* partial block -- must be last block so finish up */
+ {
+ /* Find out how many bytes and residual bits there are */
+ byte = count >> 3;
+ bit = count & 7;
+ /* Copy X into XX since we need to modify it */
+ for (i=0;i<=byte;i++) XX[i] = X[i];
+ for (i=byte+1;i<64;i++) XX[i] = 0;
+ /* Add padding '1' bit and low-order zeros in last byte */
+ mask = 1 << (7 - bit);
+ XX[byte] = (XX[byte] | mask) & ~( mask - 1);
+ /* If room for bit count, finish up with this block */
+ if (byte <= 55)
+ {
+ for (i=0;i<8;i++) XX[56+i] = MDp->count[i];
+ MDblock(MDp,XX);
+ }
+ else /* need to do two blocks to finish up */
+ {
+ MDblock(MDp,XX);
+ for (i=0;i<56;i++) XX[i] = 0;
+ for (i=0;i<8;i++) XX[56+i] = MDp->count[i];
+ MDblock(MDp,XX);
+ }
+ /* Set flag saying we're done with MD computation */
+ MDp->done = 1;
+ }
+}
+
+/*
+** Finish up MD4 computation and return message digest.
+*/
+void
+MD4Final(buf, MD)
+unsigned char *buf;
+MD4_CTX *MD;
+{
+ int i, j;
+ unsigned int w;
+
+ MD4Update(MD, NULL, 0);
+ for (i = 0; i < 4; ++i) {
+ w = MD->buffer[i];
+ for (j = 0; j < 4; ++j) {
+ *buf++ = w;
+ w >>= 8;
+ }
+ }
+}
+
+/*
+** End of md4.c
+****************************(cut)***********************************/
diff --git a/cpukit/pppd/md4.h b/cpukit/pppd/md4.h
new file mode 100644
index 0000000000..80e8f9a2ac
--- /dev/null
+++ b/cpukit/pppd/md4.h
@@ -0,0 +1,64 @@
+
+/*
+** ********************************************************************
+** md4.h -- Header file for implementation of **
+** MD4 Message Digest Algorithm **
+** Updated: 2/13/90 by Ronald L. Rivest **
+** (C) 1990 RSA Data Security, Inc. **
+** ********************************************************************
+*/
+
+#ifndef __P
+# if defined(__STDC__) || defined(__GNUC__)
+# define __P(x) x
+# else
+# define __P(x) ()
+# endif
+#endif
+
+
+/* MDstruct is the data structure for a message digest computation.
+*/
+typedef struct {
+ unsigned int buffer[4]; /* Holds 4-word result of MD computation */
+ unsigned char count[8]; /* Number of bits processed so far */
+ unsigned int done; /* Nonzero means MD computation finished */
+} MD4_CTX;
+
+/* MD4Init(MD4_CTX *)
+** Initialize the MD4_CTX prepatory to doing a message digest
+** computation.
+*/
+extern void MD4Init __P((MD4_CTX *MD));
+
+/* MD4Update(MD,X,count)
+** Input: X -- a pointer to an array of unsigned characters.
+** count -- the number of bits of X to use (an unsigned int).
+** Updates MD using the first "count" bits of X.
+** The array pointed to by X is not modified.
+** If count is not a multiple of 8, MD4Update uses high bits of
+** last byte.
+** This is the basic input routine for a user.
+** The routine terminates the MD computation when count < 512, so
+** every MD computation should end with one call to MD4Update with a
+** count less than 512. Zero is OK for a count.
+*/
+extern void MD4Update __P((MD4_CTX *MD, unsigned char *X, unsigned int count));
+
+/* MD4Print(MD)
+** Prints message digest buffer MD as 32 hexadecimal digits.
+** Order is from low-order byte of buffer[0] to high-order byte
+** of buffer[3].
+** Each byte is printed with high-order hexadecimal digit first.
+*/
+extern void MD4Print __P((MD4_CTX *));
+
+/* MD4Final(buf, MD)
+** Returns message digest from MD and terminates the message
+** digest computation.
+*/
+extern void MD4Final __P((unsigned char *, MD4_CTX *));
+
+/*
+** End of md4.h
+****************************(cut)***********************************/
diff --git a/cpukit/pppd/md5.c b/cpukit/pppd/md5.c
new file mode 100644
index 0000000000..0c16b3e545
--- /dev/null
+++ b/cpukit/pppd/md5.c
@@ -0,0 +1,308 @@
+
+
+/*
+ ***********************************************************************
+ ** md5.c -- the source code for MD5 routines **
+ ** RSA Data Security, Inc. MD5 Message-Digest Algorithm **
+ ** Created: 2/17/90 RLR **
+ ** Revised: 1/91 SRD,AJ,BSK,JT Reference C ver., 7/10 constant corr. **
+ ***********************************************************************
+ */
+
+/*
+ ***********************************************************************
+ ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
+ ** **
+ ** License to copy and use this software is granted provided that **
+ ** it is identified as the "RSA Data Security, Inc. MD5 Message- **
+ ** Digest Algorithm" in all material mentioning or referencing this **
+ ** software or this function. **
+ ** **
+ ** License is also granted to make and use derivative works **
+ ** provided that such works are identified as "derived from the RSA **
+ ** Data Security, Inc. MD5 Message-Digest Algorithm" in all **
+ ** material mentioning or referencing the derived work. **
+ ** **
+ ** RSA Data Security, Inc. makes no representations concerning **
+ ** either the merchantability of this software or the suitability **
+ ** of this software for any particular purpose. It is provided "as **
+ ** is" without express or implied warranty of any kind. **
+ ** **
+ ** These notices must be retained in any copies of any part of this **
+ ** documentation and/or software. **
+ ***********************************************************************
+ */
+
+#include <string.h> /* memcpy */
+
+#include "md5.h"
+
+/*
+ ***********************************************************************
+ ** Message-digest routines: **
+ ** To form the message digest for a message M **
+ ** (1) Initialize a context buffer mdContext using MD5Init **
+ ** (2) Call MD5Update on mdContext and M **
+ ** (3) Call MD5Final on mdContext **
+ ** The message digest is now in mdContext->digest[0...15] **
+ ***********************************************************************
+ */
+
+/* forward declaration */
+static void Transform ();
+
+static unsigned char PADDING[64] = {
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/* F, G, H and I are basic MD5 functions */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
+/* Rotation is separate from addition to prevent recomputation */
+#define FF(a, b, c, d, x, s, ac) \
+ {(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define GG(a, b, c, d, x, s, ac) \
+ {(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define HH(a, b, c, d, x, s, ac) \
+ {(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define II(a, b, c, d, x, s, ac) \
+ {(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+
+#ifdef __STDC__
+#define UL(x) x##U
+#else
+#define UL(x) x
+#endif
+
+/* The routine MD5Init initializes the message-digest context
+ mdContext. All fields are set to zero.
+ */
+void MD5Init (mdContext)
+MD5_CTX *mdContext;
+{
+ mdContext->i[0] = mdContext->i[1] = (UINT4)0;
+
+ /* Load magic initialization constants.
+ */
+ mdContext->buf[0] = (UINT4)0x67452301;
+ mdContext->buf[1] = (UINT4)0xefcdab89;
+ mdContext->buf[2] = (UINT4)0x98badcfe;
+ mdContext->buf[3] = (UINT4)0x10325476;
+}
+
+/* The routine MD5Update updates the message-digest context to
+ account for the presence of each of the characters inBuf[0..inLen-1]
+ in the message whose digest is being computed.
+ */
+void MD5Update (mdContext, inBuf, inLen)
+MD5_CTX *mdContext;
+unsigned char *inBuf;
+unsigned int inLen;
+{
+ UINT4 in[16];
+ int mdi;
+ unsigned int i, ii;
+
+ /* compute number of bytes mod 64 */
+ mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
+
+ /* update number of bits */
+ if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0])
+ mdContext->i[1]++;
+ mdContext->i[0] += ((UINT4)inLen << 3);
+ mdContext->i[1] += ((UINT4)inLen >> 29);
+
+ while (inLen--) {
+ /* add new character to buffer, increment mdi */
+ mdContext->in[mdi++] = *inBuf++;
+
+ /* transform if necessary */
+ if (mdi == 0x40) {
+ for (i = 0, ii = 0; i < 16; i++, ii += 4)
+ in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
+ (((UINT4)mdContext->in[ii+2]) << 16) |
+ (((UINT4)mdContext->in[ii+1]) << 8) |
+ ((UINT4)mdContext->in[ii]);
+ Transform (mdContext->buf, in);
+ mdi = 0;
+ }
+ }
+}
+
+/* The routine MD5Final terminates the message-digest computation and
+ ends with the desired message digest in mdContext->digest[0...15].
+ */
+void MD5Final (hash, mdContext)
+unsigned char hash[];
+MD5_CTX *mdContext;
+{
+ UINT4 in[16];
+ int mdi;
+ unsigned int i, ii;
+ unsigned int padLen;
+
+ /* save number of bits */
+ in[14] = mdContext->i[0];
+ in[15] = mdContext->i[1];
+
+ /* compute number of bytes mod 64 */
+ mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
+
+ /* pad out to 56 mod 64 */
+ padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);
+ MD5Update (mdContext, PADDING, padLen);
+
+ /* append length in bits and transform */
+ for (i = 0, ii = 0; i < 14; i++, ii += 4)
+ in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
+ (((UINT4)mdContext->in[ii+2]) << 16) |
+ (((UINT4)mdContext->in[ii+1]) << 8) |
+ ((UINT4)mdContext->in[ii]);
+ Transform (mdContext->buf, in);
+
+ /* store buffer in digest */
+ for (i = 0, ii = 0; i < 4; i++, ii += 4) {
+ mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF);
+ mdContext->digest[ii+1] =
+ (unsigned char)((mdContext->buf[i] >> 8) & 0xFF);
+ mdContext->digest[ii+2] =
+ (unsigned char)((mdContext->buf[i] >> 16) & 0xFF);
+ mdContext->digest[ii+3] =
+ (unsigned char)((mdContext->buf[i] >> 24) & 0xFF);
+ }
+ memcpy(hash, mdContext->digest, 16);
+}
+
+/* Basic MD5 step. Transforms buf based on in.
+ */
+static void Transform (buf, in)
+UINT4 *buf;
+UINT4 *in;
+{
+ UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
+
+ /* Round 1 */
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+ FF ( a, b, c, d, in[ 0], S11, UL(3614090360)); /* 1 */
+ FF ( d, a, b, c, in[ 1], S12, UL(3905402710)); /* 2 */
+ FF ( c, d, a, b, in[ 2], S13, UL( 606105819)); /* 3 */
+ FF ( b, c, d, a, in[ 3], S14, UL(3250441966)); /* 4 */
+ FF ( a, b, c, d, in[ 4], S11, UL(4118548399)); /* 5 */
+ FF ( d, a, b, c, in[ 5], S12, UL(1200080426)); /* 6 */
+ FF ( c, d, a, b, in[ 6], S13, UL(2821735955)); /* 7 */
+ FF ( b, c, d, a, in[ 7], S14, UL(4249261313)); /* 8 */
+ FF ( a, b, c, d, in[ 8], S11, UL(1770035416)); /* 9 */
+ FF ( d, a, b, c, in[ 9], S12, UL(2336552879)); /* 10 */
+ FF ( c, d, a, b, in[10], S13, UL(4294925233)); /* 11 */
+ FF ( b, c, d, a, in[11], S14, UL(2304563134)); /* 12 */
+ FF ( a, b, c, d, in[12], S11, UL(1804603682)); /* 13 */
+ FF ( d, a, b, c, in[13], S12, UL(4254626195)); /* 14 */
+ FF ( c, d, a, b, in[14], S13, UL(2792965006)); /* 15 */
+ FF ( b, c, d, a, in[15], S14, UL(1236535329)); /* 16 */
+
+ /* Round 2 */
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+ GG ( a, b, c, d, in[ 1], S21, UL(4129170786)); /* 17 */
+ GG ( d, a, b, c, in[ 6], S22, UL(3225465664)); /* 18 */
+ GG ( c, d, a, b, in[11], S23, UL( 643717713)); /* 19 */
+ GG ( b, c, d, a, in[ 0], S24, UL(3921069994)); /* 20 */
+ GG ( a, b, c, d, in[ 5], S21, UL(3593408605)); /* 21 */
+ GG ( d, a, b, c, in[10], S22, UL( 38016083)); /* 22 */
+ GG ( c, d, a, b, in[15], S23, UL(3634488961)); /* 23 */
+ GG ( b, c, d, a, in[ 4], S24, UL(3889429448)); /* 24 */
+ GG ( a, b, c, d, in[ 9], S21, UL( 568446438)); /* 25 */
+ GG ( d, a, b, c, in[14], S22, UL(3275163606)); /* 26 */
+ GG ( c, d, a, b, in[ 3], S23, UL(4107603335)); /* 27 */
+ GG ( b, c, d, a, in[ 8], S24, UL(1163531501)); /* 28 */
+ GG ( a, b, c, d, in[13], S21, UL(2850285829)); /* 29 */
+ GG ( d, a, b, c, in[ 2], S22, UL(4243563512)); /* 30 */
+ GG ( c, d, a, b, in[ 7], S23, UL(1735328473)); /* 31 */
+ GG ( b, c, d, a, in[12], S24, UL(2368359562)); /* 32 */
+
+ /* Round 3 */
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+ HH ( a, b, c, d, in[ 5], S31, UL(4294588738)); /* 33 */
+ HH ( d, a, b, c, in[ 8], S32, UL(2272392833)); /* 34 */
+ HH ( c, d, a, b, in[11], S33, UL(1839030562)); /* 35 */
+ HH ( b, c, d, a, in[14], S34, UL(4259657740)); /* 36 */
+ HH ( a, b, c, d, in[ 1], S31, UL(2763975236)); /* 37 */
+ HH ( d, a, b, c, in[ 4], S32, UL(1272893353)); /* 38 */
+ HH ( c, d, a, b, in[ 7], S33, UL(4139469664)); /* 39 */
+ HH ( b, c, d, a, in[10], S34, UL(3200236656)); /* 40 */
+ HH ( a, b, c, d, in[13], S31, UL( 681279174)); /* 41 */
+ HH ( d, a, b, c, in[ 0], S32, UL(3936430074)); /* 42 */
+ HH ( c, d, a, b, in[ 3], S33, UL(3572445317)); /* 43 */
+ HH ( b, c, d, a, in[ 6], S34, UL( 76029189)); /* 44 */
+ HH ( a, b, c, d, in[ 9], S31, UL(3654602809)); /* 45 */
+ HH ( d, a, b, c, in[12], S32, UL(3873151461)); /* 46 */
+ HH ( c, d, a, b, in[15], S33, UL( 530742520)); /* 47 */
+ HH ( b, c, d, a, in[ 2], S34, UL(3299628645)); /* 48 */
+
+ /* Round 4 */
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+ II ( a, b, c, d, in[ 0], S41, UL(4096336452)); /* 49 */
+ II ( d, a, b, c, in[ 7], S42, UL(1126891415)); /* 50 */
+ II ( c, d, a, b, in[14], S43, UL(2878612391)); /* 51 */
+ II ( b, c, d, a, in[ 5], S44, UL(4237533241)); /* 52 */
+ II ( a, b, c, d, in[12], S41, UL(1700485571)); /* 53 */
+ II ( d, a, b, c, in[ 3], S42, UL(2399980690)); /* 54 */
+ II ( c, d, a, b, in[10], S43, UL(4293915773)); /* 55 */
+ II ( b, c, d, a, in[ 1], S44, UL(2240044497)); /* 56 */
+ II ( a, b, c, d, in[ 8], S41, UL(1873313359)); /* 57 */
+ II ( d, a, b, c, in[15], S42, UL(4264355552)); /* 58 */
+ II ( c, d, a, b, in[ 6], S43, UL(2734768916)); /* 59 */
+ II ( b, c, d, a, in[13], S44, UL(1309151649)); /* 60 */
+ II ( a, b, c, d, in[ 4], S41, UL(4149444226)); /* 61 */
+ II ( d, a, b, c, in[11], S42, UL(3174756917)); /* 62 */
+ II ( c, d, a, b, in[ 2], S43, UL( 718787259)); /* 63 */
+ II ( b, c, d, a, in[ 9], S44, UL(3951481745)); /* 64 */
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+}
+
+/*
+ ***********************************************************************
+ ** End of md5.c **
+ ******************************** (cut) ********************************
+ */
diff --git a/cpukit/pppd/md5.h b/cpukit/pppd/md5.h
new file mode 100644
index 0000000000..7492b2228e
--- /dev/null
+++ b/cpukit/pppd/md5.h
@@ -0,0 +1,58 @@
+/*
+ ***********************************************************************
+ ** md5.h -- header file for implementation of MD5 **
+ ** RSA Data Security, Inc. MD5 Message-Digest Algorithm **
+ ** Created: 2/17/90 RLR **
+ ** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version **
+ ** Revised (for MD5): RLR 4/27/91 **
+ ** -- G modified to have y&~z instead of y&z **
+ ** -- FF, GG, HH modified to add in last register done **
+ ** -- Access pattern: round 2 works mod 5, round 3 works mod 3 **
+ ** -- distinct additive constant for each step **
+ ** -- round 4 added, working mod 7 **
+ ***********************************************************************
+ */
+
+/*
+ ***********************************************************************
+ ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. **
+ ** **
+ ** License to copy and use this software is granted provided that **
+ ** it is identified as the "RSA Data Security, Inc. MD5 Message- **
+ ** Digest Algorithm" in all material mentioning or referencing this **
+ ** software or this function. **
+ ** **
+ ** License is also granted to make and use derivative works **
+ ** provided that such works are identified as "derived from the RSA **
+ ** Data Security, Inc. MD5 Message-Digest Algorithm" in all **
+ ** material mentioning or referencing the derived work. **
+ ** **
+ ** RSA Data Security, Inc. makes no representations concerning **
+ ** either the merchantability of this software or the suitability **
+ ** of this software for any particular purpose. It is provided "as **
+ ** is" without express or implied warranty of any kind. **
+ ** **
+ ** These notices must be retained in any copies of any part of this **
+ ** documentation and/or software. **
+ ***********************************************************************
+ */
+
+#ifndef __MD5_INCLUDE__
+
+/* typedef a 32-bit type */
+typedef unsigned int UINT4;
+
+/* Data structure for MD5 (Message-Digest) computation */
+typedef struct {
+ UINT4 i[2]; /* number of _bits_ handled mod 2^64 */
+ UINT4 buf[4]; /* scratch buffer */
+ unsigned char in[64]; /* input buffer */
+ unsigned char digest[16]; /* actual digest after MD5Final call */
+} MD5_CTX;
+
+void MD5Init ();
+void MD5Update ();
+void MD5Final ();
+
+#define __MD5_INCLUDE__
+#endif /* __MD5_INCLUDE__ */
diff --git a/cpukit/pppd/options.c b/cpukit/pppd/options.c
new file mode 100644
index 0000000000..fb686d94a6
--- /dev/null
+++ b/cpukit/pppd/options.c
@@ -0,0 +1,1525 @@
+/*
+ * options.c - handles option processing for PPP.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#define RCSID "$Id$"
+
+#include <ctype.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <string.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#ifdef PLUGIN
+#include <dlfcn.h>
+#endif
+#ifdef PPP_FILTER
+#include <pcap.h>
+#include <pcap-int.h> /* XXX: To get struct pcap */
+#endif
+
+#include "pppd.h"
+#include "pathnames.h"
+#include "patchlevel.h"
+#include "fsm.h"
+#include "lcp.h"
+#include "ipcp.h"
+#include "upap.h"
+#include "chap.h"
+#include "ccp.h"
+
+#include <net/ppp-comp.h>
+
+#if defined(ultrix) || defined(NeXT)
+char *strdup __P((char *));
+#endif
+
+static const char rcsid[] = RCSID;
+
+/*
+ * Option variables and default values.
+ */
+#ifdef PPP_FILTER
+int dflag = 0; /* Tell libpcap we want debugging */
+#endif
+int debug = 0; /* Debug flag */
+int kdebugflag = 0; /* Tell kernel to print debug messages */
+int default_device = 1; /* Using /dev/tty or equivalent */
+char devnam[MAXPATHLEN]; /* Device name */
+int crtscts = 0; /* Use hardware flow control */
+bool modem = 1; /* Use modem control lines */
+int inspeed = 0; /* Input/Output speed requested */
+u_int32_t netmask = 0; /* IP netmask to set on interface */
+bool lockflag = 0; /* Create lock file to lock the serial dev */
+bool nodetach = 0; /* Don't detach from controlling tty */
+bool updetach = 0; /* Detach once link is up */
+char *initializer = NULL; /* Script to initialize physical link */
+char *connect_script = NULL; /* Script to establish physical link */
+char *disconnect_script = NULL; /* Script to disestablish physical link */
+char *welcomer = NULL; /* Script to run after phys link estab. */
+char *ptycommand = NULL; /* Command to run on other side of pty */
+int maxconnect = 0; /* Maximum connect time */
+char user[MAXNAMELEN]; /* Username for PAP */
+char passwd[MAXSECRETLEN]; /* Password for PAP */
+bool persist = 0; /* Reopen link after it goes down */
+char our_name[MAXNAMELEN]; /* Our name for authentication purposes */
+bool demand = 0; /* do dial-on-demand */
+char *ipparam = NULL; /* Extra parameter for ip up/down scripts */
+int idle_time_limit = 0; /* Disconnect if idle for this many seconds */
+int holdoff = 30; /* # seconds to pause before reconnecting */
+bool holdoff_specified; /* true if a holdoff value has been given */
+bool notty = 0; /* Stdin/out is not a tty */
+char *record_file = NULL; /* File to record chars sent/received */
+int using_pty = 0;
+bool sync_serial = 0; /* Device is synchronous serial device */
+int log_to_fd = 1; /* send log messages to this fd too */
+int maxfail = 10; /* max # of unsuccessful connection attempts */
+char linkname[MAXPATHLEN]; /* logical name for link */
+bool tune_kernel; /* may alter kernel settings */
+int connect_delay = 1000; /* wait this many ms after connect script */
+
+extern option_t auth_options[];
+extern struct stat devstat;
+extern int prepass; /* Doing pre-pass to find device name */
+
+struct option_info initializer_info;
+struct option_info connect_script_info;
+struct option_info disconnect_script_info;
+struct option_info welcomer_info;
+struct option_info devnam_info;
+struct option_info ptycommand_info;
+
+#ifdef PPP_FILTER
+struct bpf_program pass_filter;/* Filter program for packets to pass */
+struct bpf_program active_filter; /* Filter program for link-active pkts */
+pcap_t pc; /* Fake struct pcap so we can compile expr */
+#endif
+
+char *current_option; /* the name of the option being parsed */
+int privileged_option; /* set iff the current option came from root */
+char *option_source; /* string saying where the option came from */
+bool log_to_file; /* log_to_fd is a file opened by us */
+
+/*
+ * Prototypes
+ */
+static int setdevname __P((char *));
+static int setipaddr __P((char *));
+static int setspeed __P((char *));
+static int noopt __P((char **));
+static int setdomain __P((char **));
+static int setnetmask __P((char **));
+static int setxonxoff __P((char **));
+static int readfile __P((char **));
+static int callfile __P((char **));
+static void usage __P((void));
+static int setlogfile __P((char **));
+#ifdef PLUGIN
+static int loadplugin __P((char **));
+#endif
+
+#ifdef PPP_FILTER
+static int setpassfilter __P((char **));
+static int setactivefilter __P((char **));
+#endif
+
+static option_t *find_option __P((char *name));
+static int process_option __P((option_t *, char **));
+static int n_arguments __P((option_t *));
+static int number_option __P((char *, u_int32_t *, int));
+
+/*
+ * Structure to store extra lists of options.
+ */
+struct option_list {
+ option_t *options;
+ struct option_list *next;
+};
+
+static struct option_list *extra_options = NULL;
+
+/*
+ * Valid arguments.
+ */
+option_t general_options[] = {
+ { "debug", o_int, &debug,
+ "Increase debugging level", OPT_INC|OPT_NOARG|1 },
+ { "-d", o_int, &debug,
+ "Increase debugging level", OPT_INC|OPT_NOARG|1 },
+ { "kdebug", o_int, &kdebugflag,
+ "Set kernel driver debug level" },
+ { "nodetach", o_bool, &nodetach,
+ "Don't detach from controlling tty", 1 },
+ { "-detach", o_bool, &nodetach,
+ "Don't detach from controlling tty", 1 },
+ { "updetach", o_bool, &updetach,
+ "Detach from controlling tty once link is up", 1 },
+ { "holdoff", o_int, &holdoff,
+ "Set time in seconds before retrying connection" },
+ { "idle", o_int, &idle_time_limit,
+ "Set time in seconds before disconnecting idle link" },
+ { "lock", o_bool, &lockflag,
+ "Lock serial device with UUCP-style lock file", 1 },
+ { "-all", o_special_noarg, noopt,
+ "Don't request/allow any LCP or IPCP options (useless)" },
+ { "init", o_string, &initializer,
+ "A program to initialize the device",
+ OPT_A2INFO | OPT_PRIVFIX, &initializer_info },
+ { "connect", o_string, &connect_script,
+ "A program to set up a connection",
+ OPT_A2INFO | OPT_PRIVFIX, &connect_script_info },
+ { "disconnect", o_string, &disconnect_script,
+ "Program to disconnect serial device",
+ OPT_A2INFO | OPT_PRIVFIX, &disconnect_script_info },
+ { "welcome", o_string, &welcomer,
+ "Script to welcome client",
+ OPT_A2INFO | OPT_PRIVFIX, &welcomer_info },
+ { "pty", o_string, &ptycommand,
+ "Script to run on pseudo-tty master side",
+ OPT_A2INFO | OPT_PRIVFIX | OPT_DEVNAM, &ptycommand_info },
+ { "notty", o_bool, &notty,
+ "Input/output is not a tty", OPT_DEVNAM | 1 },
+ { "record", o_string, &record_file,
+ "Record characters sent/received to file" },
+ { "maxconnect", o_int, &maxconnect,
+ "Set connection time limit", OPT_LLIMIT|OPT_NOINCR|OPT_ZEROINF },
+ { "crtscts", o_int, &crtscts,
+ "Set hardware (RTS/CTS) flow control", OPT_NOARG|OPT_VAL(1) },
+ { "nocrtscts", o_int, &crtscts,
+ "Disable hardware flow control", OPT_NOARG|OPT_VAL(-1) },
+ { "-crtscts", o_int, &crtscts,
+ "Disable hardware flow control", OPT_NOARG|OPT_VAL(-1) },
+ { "cdtrcts", o_int, &crtscts,
+ "Set alternate hardware (DTR/CTS) flow control", OPT_NOARG|OPT_VAL(2) },
+ { "nocdtrcts", o_int, &crtscts,
+ "Disable hardware flow control", OPT_NOARG|OPT_VAL(-1) },
+ { "xonxoff", o_special_noarg, setxonxoff,
+ "Set software (XON/XOFF) flow control" },
+ { "domain", o_special, setdomain,
+ "Add given domain name to hostname" },
+ { "mtu", o_int, &lcp_allowoptions[0].mru,
+ "Set our MTU", OPT_LIMITS, NULL, MAXMRU, MINMRU },
+ { "netmask", o_special, setnetmask,
+ "set netmask" },
+ { "modem", o_bool, &modem,
+ "Use modem control lines", 1 },
+ { "local", o_bool, &modem,
+ "Don't use modem control lines" },
+ { "file", o_special, readfile,
+ "Take options from a file", OPT_PREPASS },
+ { "call", o_special, callfile,
+ "Take options from a privileged file", OPT_PREPASS },
+ { "persist", o_bool, &persist,
+ "Keep on reopening connection after close", 1 },
+ { "nopersist", o_bool, &persist,
+ "Turn off persist option" },
+ { "demand", o_bool, &demand,
+ "Dial on demand", OPT_INITONLY | 1, &persist },
+ { "sync", o_bool, &sync_serial,
+ "Use synchronous HDLC serial encoding", 1 },
+ { "logfd", o_int, &log_to_fd,
+ "Send log messages to this file descriptor" },
+ { "logfile", o_special, setlogfile,
+ "Append log messages to this file" },
+ { "nolog", o_int, &log_to_fd,
+ "Don't send log messages to any file",
+ OPT_NOARG | OPT_VAL(-1) },
+ { "nologfd", o_int, &log_to_fd,
+ "Don't send log messages to any file descriptor",
+ OPT_NOARG | OPT_VAL(-1) },
+ { "linkname", o_string, linkname,
+ "Set logical name for link",
+ OPT_PRIV|OPT_STATIC, NULL, MAXPATHLEN },
+ { "maxfail", o_int, &maxfail,
+ "Maximum number of unsuccessful connection attempts to allow" },
+ { "ktune", o_bool, &tune_kernel,
+ "Alter kernel settings as necessary", 1 },
+ { "noktune", o_bool, &tune_kernel,
+ "Don't alter kernel settings", 0 },
+ { "connect-delay", o_int, &connect_delay,
+ "Maximum time (in ms) to wait after connect script finishes" },
+#ifdef PLUGIN
+ { "plugin", o_special, loadplugin,
+ "Load a plug-in module into pppd", OPT_PRIV },
+#endif
+
+#ifdef PPP_FILTER
+ { "pdebug", o_int, &dflag,
+ "libpcap debugging" },
+ { "pass-filter", 1, setpassfilter,
+ "set filter for packets to pass" },
+ { "active-filter", 1, setactivefilter,
+ "set filter for active pkts" },
+#endif
+
+ { NULL }
+};
+
+#ifndef IMPLEMENTATION
+#define IMPLEMENTATION ""
+#endif
+
+static char *usage_string = "\
+pppd version %s.%d%s\n\
+Usage: %s [ options ], where options are:\n\
+ <device> Communicate over the named device\n\
+ <speed> Set the baud rate to <speed>\n\
+ <loc>:<rem> Set the local and/or remote interface IP\n\
+ addresses. Either one may be omitted.\n\
+ asyncmap <n> Set the desired async map to hex <n>\n\
+ auth Require authentication from peer\n\
+ connect <p> Invoke shell command <p> to set up the serial line\n\
+ crtscts Use hardware RTS/CTS flow control\n\
+ defaultroute Add default route through interface\n\
+ file <f> Take options from file <f>\n\
+ modem Use modem control lines\n\
+ mru <n> Set MRU value to <n> for negotiation\n\
+See pppd(8) for more options.\n\
+";
+
+/*
+ * parse_args - parse a string of arguments from the command line.
+ * If prepass is true, we are scanning for the device name and only
+ * processing a few options, so error messages are suppressed.
+ */
+int
+parse_args(argc, argv)
+ int argc;
+ char **argv;
+{
+ char *arg;
+ option_t *opt;
+ int ret;
+
+ privileged_option = privileged;
+ option_source = "command line";
+ while (argc > 0) {
+ arg = *argv++;
+ --argc;
+
+ /*
+ * First see if it's an option in the new option list.
+ */
+ opt = find_option(arg);
+ if (opt != NULL) {
+ int n = n_arguments(opt);
+ if (argc < n) {
+ option_error("too few parameters for option %s", arg);
+ return 0;
+ }
+ current_option = arg;
+ if (!process_option(opt, argv))
+ return 0;
+ argc -= n;
+ argv += n;
+ continue;
+ }
+
+ /*
+ * Maybe a tty name, speed or IP address?
+ */
+ if ((ret = setdevname(arg)) == 0
+ && (ret = setspeed(arg)) == 0
+ && (ret = setipaddr(arg)) == 0
+ && !prepass) {
+ option_error("unrecognized option '%s'", arg);
+ usage();
+ return 0;
+ }
+ if (ret < 0) /* error */
+ return 0;
+ }
+ return 1;
+}
+
+#if 0
+/*
+ * scan_args - scan the command line arguments to get the tty name,
+ * if specified. Also checks whether the notty or pty option was given.
+ */
+void
+scan_args(argc, argv)
+ int argc;
+ char **argv;
+{
+ char *arg;
+ option_t *opt;
+
+ privileged_option = privileged;
+ while (argc > 0) {
+ arg = *argv++;
+ --argc;
+
+ if (strcmp(arg, "notty") == 0 || strcmp(arg, "pty") == 0)
+ using_pty = 1;
+
+ /* Skip options and their arguments */
+ opt = find_option(arg);
+ if (opt != NULL) {
+ int n = n_arguments(opt);
+ argc -= n;
+ argv += n;
+ continue;
+ }
+
+ /* Check if it's a tty name and copy it if so */
+ (void) setdevname(arg, 1);
+ }
+}
+#endif
+
+/*
+ * options_from_file - Read a string of options from a file,
+ * and interpret them.
+ */
+int
+options_from_file(filename, must_exist, check_prot, priv)
+ char *filename;
+ int must_exist;
+ int check_prot;
+ int priv;
+{
+ FILE *f;
+ int i, newline, ret, err;
+ option_t *opt;
+ int oldpriv;
+ char *oldsource;
+ char *argv[MAXARGS];
+ char args[MAXARGS][MAXWORDLEN];
+ char cmd[MAXWORDLEN];
+
+ f = fopen(filename, "r");
+ err = errno;
+ if (f == NULL) {
+ if (!must_exist && err == ENOENT)
+ return 1;
+ errno = err;
+ option_error("Can't open options file %s: %m", filename);
+ return 0;
+ }
+
+ oldpriv = privileged_option;
+ privileged_option = priv;
+ oldsource = option_source;
+ option_source = strdup(filename);
+ if (option_source == NULL)
+ option_source = "file";
+ ret = 0;
+ while (getword(f, cmd, &newline, filename)) {
+ /*
+ * First see if it's a command.
+ */
+ opt = find_option(cmd);
+ if (opt != NULL) {
+ int n = n_arguments(opt);
+ for (i = 0; i < n; ++i) {
+ if (!getword(f, args[i], &newline, filename)) {
+ option_error(
+ "In file %s: too few parameters for option '%s'",
+ filename, cmd);
+ goto err;
+ }
+ argv[i] = args[i];
+ }
+ current_option = cmd;
+ if ((opt->flags & OPT_DEVEQUIV) && devnam_fixed) {
+ option_error("the %s option may not be used in the %s file",
+ cmd, filename);
+ goto err;
+ }
+ if (!process_option(opt, argv))
+ goto err;
+ continue;
+ }
+
+ /*
+ * Maybe a tty name, speed or IP address?
+ */
+ if ((i = setdevname(cmd)) == 0
+ && (i = setspeed(cmd)) == 0
+ && (i = setipaddr(cmd)) == 0) {
+ option_error("In file %s: unrecognized option '%s'",
+ filename, cmd);
+ goto err;
+ }
+ if (i < 0) /* error */
+ goto err;
+ }
+ ret = 1;
+
+err:
+ fclose(f);
+ privileged_option = oldpriv;
+ option_source = oldsource;
+ return ret;
+}
+
+/*
+ * options_from_user - See if the use has a ~/.ppprc file,
+ * and if so, interpret options from it.
+ */
+int
+options_from_user()
+{
+ return 0;
+}
+
+/*
+ * options_for_tty - See if an options file exists for the serial
+ * device, and if so, interpret options from it.
+ */
+int
+options_for_tty()
+{
+ char *dev, *path, *p;
+ int ret;
+ size_t pl;
+
+ dev = devnam;
+ if (strncmp(dev, "/dev/", 5) == 0)
+ dev += 5;
+ if (dev[0] == 0 || strcmp(dev, "tty") == 0)
+ return 1; /* don't look for /etc/ppp/options.tty */
+ pl = strlen(_PATH_TTYOPT) + strlen(dev) + 1;
+ path = malloc(pl);
+ if (path == NULL)
+ novm("tty init file name");
+ slprintf(path, pl, "%s%s", _PATH_TTYOPT, dev);
+ /* Turn slashes into dots, for Solaris case (e.g. /dev/term/a) */
+ for (p = path + strlen(_PATH_TTYOPT); *p != 0; ++p)
+ if (*p == '/')
+ *p = '.';
+ ret = options_from_file(path, 0, 0, 1);
+ free(path);
+ return ret;
+}
+
+/*
+ * options_from_list - process a string of options in a wordlist.
+ */
+int
+options_from_list(w, priv)
+ struct wordlist *w;
+ int priv;
+{
+ char *argv[MAXARGS];
+ option_t *opt;
+ int i, ret = 0;
+
+ privileged_option = priv;
+ option_source = "secrets file";
+
+ while (w != NULL) {
+ /*
+ * First see if it's a command.
+ */
+ opt = find_option(w->word);
+ if (opt != NULL) {
+ int n = n_arguments(opt);
+ struct wordlist *w0 = w;
+ for (i = 0; i < n; ++i) {
+ w = w->next;
+ if (w == NULL) {
+ option_error(
+ "In secrets file: too few parameters for option '%s'",
+ w0->word);
+ goto err;
+ }
+ argv[i] = w->word;
+ }
+ current_option = w0->word;
+ if (!process_option(opt, argv))
+ goto err;
+ w = w->next;
+ continue;
+ }
+
+ /*
+ * Maybe a tty name, speed or IP address?
+ */
+ if ((i = setdevname(w->word)) == 0
+ && (i = setspeed(w->word)) == 0
+ && (i = setipaddr(w->word)) == 0) {
+ option_error("In secrets file: unrecognized option '%s'",
+ w->word);
+ goto err;
+ }
+ if (i < 0) /* error */
+ goto err;
+ w = w->next;
+ }
+ ret = 1;
+
+err:
+ return ret;
+}
+
+/*
+ * find_option - scan the option lists for the various protocols
+ * looking for an entry with the given name.
+ * This could be optimized by using a hash table.
+ */
+static option_t *
+find_option(name)
+ char *name;
+{
+ option_t *opt;
+ struct option_list *list;
+ int i;
+
+ for (list = extra_options; list != NULL; list = list->next)
+ for (opt = list->options; opt->name != NULL; ++opt)
+ if (strcmp(name, opt->name) == 0)
+ return opt;
+ for (opt = general_options; opt->name != NULL; ++opt)
+ if (strcmp(name, opt->name) == 0)
+ return opt;
+ for (opt = auth_options; opt->name != NULL; ++opt)
+ if (strcmp(name, opt->name) == 0)
+ return opt;
+ for (i = 0; protocols[i] != NULL; ++i)
+ if ((opt = protocols[i]->options) != NULL)
+ for (; opt->name != NULL; ++opt)
+ if (strcmp(name, opt->name) == 0)
+ return opt;
+ return NULL;
+}
+
+/*
+ * process_option - process one new-style option.
+ */
+static int
+process_option(opt, argv)
+ option_t *opt;
+ char **argv;
+{
+ u_int32_t v;
+ int iv, a;
+ char *sv;
+ int (*parser) __P((char **));
+
+ if ((opt->flags & OPT_PREPASS) == 0 && prepass)
+ return 1;
+ if ((opt->flags & OPT_INITONLY) && pppd_phase != PHASE_INITIALIZE) {
+ option_error("it's too late to use the %s option", opt->name);
+ return 0;
+ }
+ if ((opt->flags & OPT_PRIV) && !privileged_option) {
+ option_error("using the %s option requires root privilege", opt->name);
+ return 0;
+ }
+ if ((opt->flags & OPT_ENABLE) && *(bool *)(opt->addr2) == 0) {
+ option_error("%s option is disabled", opt->name);
+ return 0;
+ }
+ if ((opt->flags & OPT_PRIVFIX) && !privileged_option) {
+ struct option_info *ip = (struct option_info *) opt->addr2;
+ if (ip && ip->priv) {
+ option_error("%s option cannot be overridden", opt->name);
+ return 0;
+ }
+ }
+
+ switch (opt->type) {
+ case o_bool:
+ v = opt->flags & OPT_VALUE;
+ *(bool *)(opt->addr) = v;
+ if (opt->addr2 && (opt->flags & OPT_A2COPY))
+ *(bool *)(opt->addr2) = v;
+ break;
+
+ case o_int:
+ iv = 0;
+ if ((opt->flags & OPT_NOARG) == 0) {
+ if (!int_option(*argv, &iv))
+ return 0;
+ if ((((opt->flags & OPT_LLIMIT) && iv < opt->lower_limit)
+ || ((opt->flags & OPT_ULIMIT) && iv > opt->upper_limit))
+ && !((opt->flags & OPT_ZEROOK && iv == 0))) {
+ char *zok = (opt->flags & OPT_ZEROOK)? " zero or": "";
+ switch (opt->flags & OPT_LIMITS) {
+ case OPT_LLIMIT:
+ option_error("%s value must be%s >= %d",
+ opt->name, zok, opt->lower_limit);
+ break;
+ case OPT_ULIMIT:
+ option_error("%s value must be%s <= %d",
+ opt->name, zok, opt->upper_limit);
+ break;
+ case OPT_LIMITS:
+ option_error("%s value must be%s between %d and %d",
+ opt->name, opt->lower_limit, opt->upper_limit);
+ break;
+ }
+ return 0;
+ }
+ }
+ a = opt->flags & OPT_VALUE;
+ if (a >= 128)
+ a -= 256; /* sign extend */
+ iv += a;
+ if (opt->flags & OPT_INC)
+ iv += *(int *)(opt->addr);
+ if ((opt->flags & OPT_NOINCR) && !privileged_option) {
+ int oldv = *(int *)(opt->addr);
+ if ((opt->flags & OPT_ZEROINF) ?
+ (oldv != 0 && (iv == 0 || iv > oldv)) : (iv > oldv)) {
+ option_error("%s value cannot be increased", opt->name);
+ return 0;
+ }
+ }
+ *(int *)(opt->addr) = iv;
+ if (opt->addr2 && (opt->flags & OPT_A2COPY))
+ *(int *)(opt->addr2) = iv;
+ break;
+
+ case o_uint32:
+ if (opt->flags & OPT_NOARG) {
+ v = opt->flags & OPT_VALUE;
+ } else if (!number_option(*argv, &v, 16))
+ return 0;
+ if (opt->flags & OPT_OR)
+ v |= *(u_int32_t *)(opt->addr);
+ *(u_int32_t *)(opt->addr) = v;
+ if (opt->addr2 && (opt->flags & OPT_A2COPY))
+ *(u_int32_t *)(opt->addr2) = v;
+ break;
+
+ case o_string:
+ if (opt->flags & OPT_STATIC) {
+ strlcpy((char *)(opt->addr), *argv, opt->upper_limit);
+ } else {
+ sv = strdup(*argv);
+ if (sv == NULL)
+ novm("option argument");
+ if ( *(char **)(opt->addr) != NULL ) {
+ free((void *)*(char **)(opt->addr));
+ *(char **)(opt->addr) = NULL;
+ }
+ *(char **)(opt->addr) = sv;
+ }
+ break;
+
+ case o_special_noarg:
+ case o_special:
+ parser = (int (*) __P((char **))) opt->addr;
+ if (!(*parser)(argv))
+ return 0;
+ break;
+ }
+
+ if (opt->addr2) {
+ if (opt->flags & OPT_A2INFO) {
+ struct option_info *ip = (struct option_info *) opt->addr2;
+ ip->priv = privileged_option;
+ ip->source = option_source;
+ } else if ((opt->flags & (OPT_A2COPY|OPT_ENABLE)) == 0)
+ *(bool *)(opt->addr2) = 1;
+ }
+
+ return 1;
+}
+
+/*
+ * n_arguments - tell how many arguments an option takes
+ */
+static int
+n_arguments(opt)
+ option_t *opt;
+{
+ return (opt->type == o_bool || opt->type == o_special_noarg
+ || (opt->flags & OPT_NOARG))? 0: 1;
+}
+
+/*
+ * add_options - add a list of options to the set we grok.
+ */
+void
+add_options(opt)
+ option_t *opt;
+{
+ struct option_list *list;
+
+ list = malloc(sizeof(*list));
+ if (list == 0)
+ novm("option list entry");
+ list->options = opt;
+ list->next = extra_options;
+ extra_options = list;
+}
+
+/*
+ * usage - print out a message telling how to use the program.
+ */
+static void
+usage()
+{
+ if (pppd_phase == PHASE_INITIALIZE)
+ fprintf(stderr, usage_string, VERSION, PATCHLEVEL, IMPLEMENTATION,
+ "rtems_pppd");
+}
+
+/*
+ * option_error - print a message about an error in an option.
+ * The message is logged, and also sent to
+ * stderr if pppd_phase == PHASE_INITIALIZE.
+ */
+void
+option_error __V((char *fmt, ...))
+{
+ va_list args;
+ char buf[256];
+
+#if defined(__STDC__)
+ va_start(args, fmt);
+#else
+ char *fmt;
+ va_start(args);
+ fmt = va_arg(args, char *);
+#endif
+ if (prepass) {
+ va_end(args);
+ return;
+ }
+ vslprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ fprintf(stderr, "pppd: %s\n", buf);
+}
+
+/*
+ * Read a word from a file.
+ * Words are delimited by white-space or by quotes (" or ').
+ * Quotes, white-space and \ may be escaped with \.
+ * \<newline> is ignored.
+ */
+int
+getword(f, word, newlinep, filename)
+ FILE *f;
+ char *word;
+ int *newlinep;
+ char *filename;
+{
+ int c, len, escape;
+ int quoted, comment;
+ int value, digit, got, n;
+
+#define isoctal(c) ((c) >= '0' && (c) < '8')
+
+ *newlinep = 0;
+ len = 0;
+ escape = 0;
+ comment = 0;
+
+ /*
+ * First skip white-space and comments.
+ */
+ for (;;) {
+ c = getc(f);
+ if (c == EOF)
+ break;
+
+ /*
+ * A newline means the end of a comment; backslash-newline
+ * is ignored. Note that we cannot have escape && comment.
+ */
+ if (c == '\n') {
+ if (!escape) {
+ *newlinep = 1;
+ comment = 0;
+ } else
+ escape = 0;
+ continue;
+ }
+
+ /*
+ * Ignore characters other than newline in a comment.
+ */
+ if (comment)
+ continue;
+
+ /*
+ * If this character is escaped, we have a word start.
+ */
+ if (escape)
+ break;
+
+ /*
+ * If this is the escape character, look at the next character.
+ */
+ if (c == '\\') {
+ escape = 1;
+ continue;
+ }
+
+ /*
+ * If this is the start of a comment, ignore the rest of the line.
+ */
+ if (c == '#') {
+ comment = 1;
+ continue;
+ }
+
+ /*
+ * A non-whitespace character is the start of a word.
+ */
+ if (!isspace(c))
+ break;
+ }
+
+ /*
+ * Save the delimiter for quoted strings.
+ */
+ if (!escape && (c == '"' || c == '\'')) {
+ quoted = c;
+ c = getc(f);
+ } else
+ quoted = 0;
+
+ /*
+ * Process characters until the end of the word.
+ */
+ while (c != EOF) {
+ if (escape) {
+ /*
+ * This character is escaped: backslash-newline is ignored,
+ * various other characters indicate particular values
+ * as for C backslash-escapes.
+ */
+ escape = 0;
+ if (c == '\n') {
+ c = getc(f);
+ continue;
+ }
+
+ got = 0;
+ switch (c) {
+ case 'a':
+ value = '\a';
+ break;
+ case 'b':
+ value = '\b';
+ break;
+ case 'f':
+ value = '\f';
+ break;
+ case 'n':
+ value = '\n';
+ break;
+ case 'r':
+ value = '\r';
+ break;
+ case 's':
+ value = ' ';
+ break;
+ case 't':
+ value = '\t';
+ break;
+
+ default:
+ if (isoctal(c)) {
+ /*
+ * \ddd octal sequence
+ */
+ value = 0;
+ for (n = 0; n < 3 && isoctal(c); ++n) {
+ value = (value << 3) + (c & 07);
+ c = getc(f);
+ }
+ got = 1;
+ break;
+ }
+
+ if (c == 'x') {
+ /*
+ * \x<hex_string> sequence
+ */
+ value = 0;
+ c = getc(f);
+ for (n = 0; n < 2 && isxdigit(c); ++n) {
+ digit = toupper(c) - '0';
+ if (digit > 10)
+ digit += '0' + 10 - 'A';
+ value = (value << 4) + digit;
+ c = getc (f);
+ }
+ got = 1;
+ break;
+ }
+
+ /*
+ * Otherwise the character stands for itself.
+ */
+ value = c;
+ break;
+ }
+
+ /*
+ * Store the resulting character for the escape sequence.
+ */
+ if (len < MAXWORDLEN-1)
+ word[len] = value;
+ ++len;
+
+ if (!got)
+ c = getc(f);
+ continue;
+
+ }
+
+ /*
+ * Not escaped: see if we've reached the end of the word.
+ */
+ if (quoted) {
+ if (c == quoted)
+ break;
+ } else {
+ if (isspace(c) || c == '#') {
+ ungetc (c, f);
+ break;
+ }
+ }
+
+ /*
+ * Backslash starts an escape sequence.
+ */
+ if (c == '\\') {
+ escape = 1;
+ c = getc(f);
+ continue;
+ }
+
+ /*
+ * An ordinary character: store it in the word and get another.
+ */
+ if (len < MAXWORDLEN-1)
+ word[len] = c;
+ ++len;
+
+ c = getc(f);
+ }
+
+ /*
+ * End of the word: check for errors.
+ */
+ if (c == EOF) {
+ if (ferror(f)) {
+ if (errno == 0)
+ errno = EIO;
+ option_error("Error reading %s: %m", filename);
+ die(1);
+ }
+ /*
+ * If len is zero, then we didn't find a word before the
+ * end of the file.
+ */
+ if (len == 0)
+ return 0;
+ }
+
+ /*
+ * Warn if the word was too long, and append a terminating null.
+ */
+ if (len >= MAXWORDLEN) {
+ option_error("warning: word in file %s too long (%.20s...)",
+ filename, word);
+ len = MAXWORDLEN - 1;
+ }
+ word[len] = 0;
+
+ return 1;
+
+#undef isoctal
+
+}
+
+/*
+ * number_option - parse an unsigned numeric parameter for an option.
+ */
+static int
+number_option(str, valp, base)
+ char *str;
+ u_int32_t *valp;
+ int base;
+{
+ char *ptr;
+
+ *valp = strtoul(str, &ptr, base);
+ if (ptr == str) {
+ option_error("invalid numeric parameter '%s' for %s option",
+ str, current_option);
+ return 0;
+ }
+ return 1;
+}
+
+
+/*
+ * int_option - like number_option, but valp is int *,
+ * the base is assumed to be 0, and *valp is not changed
+ * if there is an error.
+ */
+int
+int_option(str, valp)
+ char *str;
+ int *valp;
+{
+ u_int32_t v;
+
+ if (!number_option(str, &v, 0))
+ return 0;
+ *valp = (int) v;
+ return 1;
+}
+
+
+/*
+ * The following procedures parse options.
+ */
+
+/*
+ * readfile - take commands from a file.
+ */
+static int
+readfile(argv)
+ char **argv;
+{
+ return options_from_file(*argv, 1, 1, privileged_option);
+}
+
+/*
+ * callfile - take commands from /etc/ppp/peers/<name>.
+ * Name may not contain /../, start with / or ../, or end in /..
+ */
+static int
+callfile(argv)
+ char **argv;
+{
+ char *fname, *arg, *p;
+ int l, ok;
+
+ arg = *argv;
+ ok = 1;
+ if (arg[0] == '/' || arg[0] == 0)
+ ok = 0;
+ else {
+ for (p = arg; *p != 0; ) {
+ if (p[0] == '.' && p[1] == '.' && (p[2] == '/' || p[2] == 0)) {
+ ok = 0;
+ break;
+ }
+ while (*p != '/' && *p != 0)
+ ++p;
+ if (*p == '/')
+ ++p;
+ }
+ }
+ if (!ok) {
+ option_error("call option value may not contain .. or start with /");
+ return 0;
+ }
+
+ l = strlen(arg) + strlen(_PATH_PEERFILES) + 1;
+ if ((fname = (char *) malloc(l)) == NULL)
+ novm("call file name");
+ slprintf(fname, l, "%s%s", _PATH_PEERFILES, arg);
+
+ ok = options_from_file(fname, 1, 1, 1);
+
+ free(fname);
+ return ok;
+}
+
+#ifdef PPP_FILTER
+/*
+ * setpdebug - Set libpcap debugging level.
+ */
+static int
+setpdebug(argv)
+ char **argv;
+{
+ return int_option(*argv, &dflag);
+}
+
+/*
+ * setpassfilter - Set the pass filter for packets
+ */
+static int
+setpassfilter(argv)
+ char **argv;
+{
+ pc.linktype = DLT_PPP;
+ pc.snapshot = PPP_HDRLEN;
+
+ if (pcap_compile(&pc, &pass_filter, *argv, 1, netmask) == 0)
+ return 1;
+ option_error("error in pass-filter expression: %s\n", pcap_geterr(&pc));
+ return 0;
+}
+
+/*
+ * setactivefilter - Set the active filter for packets
+ */
+static int
+setactivefilter(argv)
+ char **argv;
+{
+ pc.linktype = DLT_PPP;
+ pc.snapshot = PPP_HDRLEN;
+
+ if (pcap_compile(&pc, &active_filter, *argv, 1, netmask) == 0)
+ return 1;
+ option_error("error in active-filter expression: %s\n", pcap_geterr(&pc));
+ return 0;
+}
+#endif
+
+/*
+ * noopt - Disable all options.
+ */
+static int
+noopt(argv)
+ char **argv;
+{
+ BZERO((char *) &lcp_wantoptions[0], sizeof (struct lcp_options));
+ BZERO((char *) &lcp_allowoptions[0], sizeof (struct lcp_options));
+ BZERO((char *) &ipcp_wantoptions[0], sizeof (struct ipcp_options));
+ BZERO((char *) &ipcp_allowoptions[0], sizeof (struct ipcp_options));
+
+ return (1);
+}
+
+/*
+ * setdomain - Set domain name to append to hostname
+ */
+static int
+setdomain(argv)
+ char **argv;
+{
+ if (!privileged_option) {
+ option_error("using the domain option requires root privilege");
+ return 0;
+ }
+ gethostname(hostname, MAXNAMELEN);
+ if (**argv != 0) {
+ if (**argv != '.')
+ strncat(hostname, ".", MAXNAMELEN - strlen(hostname));
+ strncat(hostname, *argv, MAXNAMELEN - strlen(hostname));
+ }
+ hostname[MAXNAMELEN-1] = 0;
+ return (1);
+}
+
+
+/*
+ * setspeed - Set the speed.
+ */
+static int
+setspeed(arg)
+ char *arg;
+{
+ int spd;
+ int ret = (int )1;
+ speed_t spdValue = (speed_t)0;
+ char *ptr;
+
+ if ( !prepass ) {
+ spd = strtol(arg, &ptr, 0);
+ if (ptr == arg || *ptr != 0 || spd == 0) {
+ ret = (int)0;
+ }
+ else {
+ switch ( spd ) {
+ case 2400:
+ spdValue = B2400;
+ break;
+ case 4800:
+ spdValue = B4800;
+ break;
+ case 9600:
+ spdValue = B9600;
+ break;
+ case 19200:
+ spdValue = B19200;
+ break;
+ case 38400:
+ spdValue = B38400;
+ break;
+ case 57600:
+ spdValue = B57600;
+ break;
+ case 115200:
+ spdValue = B115200;
+ break;
+ default:
+ ret = (int)0;
+ break;
+ }
+
+ if ( spdValue ) {
+ inspeed = spdValue;
+ }
+ }
+ }
+
+ return ( ret );
+}
+
+
+/*
+ * setdevname - Set the device name.
+ */
+static int
+setdevname(cp)
+ char *cp;
+{
+ struct stat statbuf;
+ char dev[MAXPATHLEN];
+
+ if (*cp == 0)
+ return 0;
+
+ if (strncmp("/dev/", cp, 5) != 0) {
+ strlcpy(dev, "/dev/", sizeof(dev));
+ strlcat(dev, cp, sizeof(dev));
+ cp = dev;
+ }
+
+ /*
+ * Check if there is a character device by this name.
+ */
+ if (stat(cp, &statbuf) < 0) {
+ if (errno == ENOENT)
+ return 0;
+ option_error("Couldn't stat %s: %m", cp);
+ return -1;
+ }
+ if (!S_ISCHR(statbuf.st_mode)) {
+ option_error("%s is not a character device", cp);
+ return -1;
+ }
+
+ if (pppd_phase != PHASE_INITIALIZE) {
+ option_error("device name cannot be changed after initialization");
+ return -1;
+ } else if (devnam_fixed) {
+ option_error("per-tty options file may not specify device name");
+ return -1;
+ }
+
+ if (devnam_info.priv && !privileged_option) {
+ option_error("device name cannot be overridden");
+ return -1;
+ }
+
+ strlcpy(devnam, cp, sizeof(devnam));
+ devstat = statbuf;
+ default_device = 0;
+ devnam_info.priv = privileged_option;
+ devnam_info.source = option_source;
+
+ return 1;
+}
+
+
+/*
+ * setipaddr - Set the IP address
+ */
+static int
+setipaddr(arg)
+ char *arg;
+{
+ struct hostent *hp;
+ char *colon;
+ u_int32_t local, remote;
+ ipcp_options *wo = &ipcp_wantoptions[0];
+
+ /*
+ * IP address pair separated by ":".
+ */
+ if ((colon = strchr(arg, ':')) == NULL)
+ return 0;
+ if (prepass)
+ return 1;
+
+ /*
+ * If colon first character, then no local addr.
+ */
+ if (colon != arg) {
+ *colon = '\0';
+ if ((local = inet_addr(arg)) == (u_int32_t) -1) {
+ if ((hp = gethostbyname(arg)) == NULL) {
+ option_error("unknown host: %s", arg);
+ return -1;
+ } else {
+ local = *(u_int32_t *)hp->h_addr;
+ }
+ }
+ if (bad_ip_adrs(local)) {
+ option_error("bad local IP address %s", ip_ntoa(local));
+ return -1;
+ }
+ if (local != 0)
+ wo->ouraddr = local;
+ *colon = ':';
+ }
+
+ /*
+ * If colon last character, then no remote addr.
+ */
+ if (*++colon != '\0') {
+ if ((remote = inet_addr(colon)) == (u_int32_t) -1) {
+ if ((hp = gethostbyname(colon)) == NULL) {
+ option_error("unknown host: %s", colon);
+ return -1;
+ } else {
+ remote = *(u_int32_t *)hp->h_addr;
+ if (remote_name[0] == 0)
+ strlcpy(remote_name, colon, sizeof(remote_name));
+ }
+ }
+ if (bad_ip_adrs(remote)) {
+ option_error("bad remote IP address %s", ip_ntoa(remote));
+ return -1;
+ }
+ if (remote != 0)
+ wo->hisaddr = remote;
+ }
+
+ return 1;
+}
+
+
+/*
+ * setnetmask - set the netmask to be used on the interface.
+ */
+static int
+setnetmask(argv)
+ char **argv;
+{
+ u_int32_t mask, b;
+ int n, ok;
+ char *p, *endp;
+
+ /*
+ * Unfortunately, if we use inet_addr, we can't tell whether
+ * a result of all 1s is an error or a valid 255.255.255.255.
+ */
+ p = *argv;
+ ok = 0;
+ mask = 0;
+ for (n = 3;; --n) {
+ b = strtoul(p, &endp, 0);
+ if (endp == p)
+ break;
+ if (b > 255) {
+ if (n == 3) {
+ /* accept e.g. 0xffffff00 */
+ p = endp;
+ mask = b;
+ }
+ break;
+ }
+ mask |= b << (n * 8);
+ p = endp;
+ if (*p != '.' || n == 0)
+ break;
+ ++p;
+ }
+
+ mask = htonl(mask);
+
+ if (*p != 0 || (netmask & ~mask) != 0) {
+ option_error("invalid netmask value '%s'", *argv);
+ return 0;
+ }
+
+ netmask = mask;
+ return (1);
+}
+
+static int
+setxonxoff(argv)
+ char **argv;
+{
+ lcp_wantoptions[0].asyncmap |= 0x000A0000; /* escape ^S and ^Q */
+ lcp_wantoptions[0].neg_asyncmap = 1;
+
+ crtscts = -2;
+ return (1);
+}
+
+static int
+setlogfile(argv)
+ char **argv;
+{
+ int fd, err;
+
+ fd = open(*argv, O_WRONLY | O_APPEND | O_CREAT | O_EXCL, 0644);
+ if (fd < 0 && errno == EEXIST)
+ fd = open(*argv, O_WRONLY | O_APPEND);
+ err = errno;
+ if (fd < 0) {
+ errno = err;
+ option_error("Can't open log file %s: %m", *argv);
+ return 0;
+ }
+ if (log_to_file && log_to_fd >= 0)
+ close(log_to_fd);
+ log_to_fd = fd;
+ log_to_file = 1;
+ return 1;
+}
+
+#ifdef PLUGIN
+static int
+loadplugin(argv)
+ char **argv;
+{
+ char *arg = *argv;
+ void *handle;
+ const char *err;
+ void (*init) __P((void));
+
+ handle = dlopen(arg, RTLD_GLOBAL | RTLD_NOW);
+ if (handle == 0) {
+ err = dlerror();
+ if (err != 0)
+ option_error("%s", err);
+ option_error("Couldn't load plugin %s", arg);
+ return 0;
+ }
+ init = dlsym(handle, "plugin_init");
+ if (init == 0) {
+ option_error("%s has no initialization entry point", arg);
+ dlclose(handle);
+ return 0;
+ }
+ info("Plugin %s loaded.", arg);
+ (*init)();
+ return 1;
+}
+#endif /* PLUGIN */
diff --git a/cpukit/pppd/patchlevel.h b/cpukit/pppd/patchlevel.h
new file mode 100644
index 0000000000..54d88b8a66
--- /dev/null
+++ b/cpukit/pppd/patchlevel.h
@@ -0,0 +1,6 @@
+/* $Id$ */
+#define PATCHLEVEL 11
+
+#define VERSION "2.3"
+#define IMPLEMENTATION ""
+#define DATE "23 December 1999"
diff --git a/cpukit/pppd/pathnames.h b/cpukit/pppd/pathnames.h
new file mode 100644
index 0000000000..0a4f6e69f2
--- /dev/null
+++ b/cpukit/pppd/pathnames.h
@@ -0,0 +1,43 @@
+/*
+ * define path names
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+
+#else
+#ifndef _PATH_VARRUN
+#define _PATH_VARRUN "/etc/ppp/"
+#endif
+#define _PATH_DEVNULL "/dev/null"
+#endif
+
+#ifndef _ROOT_PATH
+#define _ROOT_PATH
+#endif
+
+#define _PATH_UPAPFILE _ROOT_PATH "/etc/ppp/pap-secrets"
+#define _PATH_CHAPFILE _ROOT_PATH "/etc/ppp/chap-secrets"
+#define _PATH_SYSOPTIONS _ROOT_PATH "/etc/ppp/options"
+#define _PATH_IPUP _ROOT_PATH "/etc/ppp/ip-up"
+#define _PATH_IPDOWN _ROOT_PATH "/etc/ppp/ip-down"
+#define _PATH_AUTHUP _ROOT_PATH "/etc/ppp/auth-up"
+#define _PATH_AUTHDOWN _ROOT_PATH "/etc/ppp/auth-down"
+#define _PATH_TTYOPT _ROOT_PATH "/etc/ppp/options."
+#define _PATH_CONNERRS _ROOT_PATH "/etc/ppp/connect-errors"
+#define _PATH_PEERFILES _ROOT_PATH "/etc/ppp/peers/"
+#define _PATH_RESOLV _ROOT_PATH "/etc/ppp/resolv.conf"
+
+#define _PATH_USEROPT ".ppprc"
+
+#ifdef INET6
+#define _PATH_IPV6UP _ROOT_PATH "/etc/ppp/ipv6-up"
+#define _PATH_IPV6DOWN _ROOT_PATH "/etc/ppp/ipv6-down"
+#endif
+
+#ifdef IPX_CHANGE
+#define _PATH_IPXUP _ROOT_PATH "/etc/ppp/ipx-up"
+#define _PATH_IPXDOWN _ROOT_PATH "/etc/ppp/ipx-down"
+#endif /* IPX_CHANGE */
diff --git a/cpukit/pppd/pppd.8 b/cpukit/pppd/pppd.8
new file mode 100644
index 0000000000..227345ff5f
--- /dev/null
+++ b/cpukit/pppd/pppd.8
@@ -0,0 +1,1480 @@
+.\" manual page [] for pppd 2.3
+.\" $Id$
+.\" SH section heading
+.\" SS subsection heading
+.\" LP paragraph
+.\" IP indented paragraph
+.\" TP hanging label
+.TH PPPD 8
+.SH NAME
+pppd \- Point to Point Protocol daemon
+.SH SYNOPSIS
+.B pppd
+[
+.I tty_name
+] [
+.I speed
+] [
+.I options
+]
+.SH DESCRIPTION
+.LP
+The Point-to-Point Protocol (PPP) provides a method for transmitting
+datagrams over serial point-to-point links. PPP
+is composed of three parts: a method for encapsulating datagrams over
+serial links, an extensible Link Control Protocol (LCP), and
+a family of Network Control Protocols (NCP) for establishing
+and configuring different network-layer protocols.
+.LP
+The encapsulation scheme is provided by driver code in the kernel.
+Pppd provides the basic LCP, authentication support, and an NCP for
+establishing and configuring the Internet Protocol (IP) (called the IP
+Control Protocol, IPCP).
+.SH FREQUENTLY USED OPTIONS
+.TP
+.I <tty_name>
+Communicate over the named device. The string "/dev/" is prepended if
+necessary. If no device name is given, or if the name of the terminal
+connected to the standard input is given, pppd will use that terminal,
+and will not fork to put itself in the background. A value for this
+option from a privileged source cannot be overridden by a
+non-privileged user.
+.TP
+.I <speed>
+Set the baud rate to <speed> (a decimal number). On systems such as
+4.4BSD and NetBSD, any speed can be specified. Other systems
+(e.g. SunOS) allow only a limited set of speeds.
+.TP
+.B asyncmap \fI<map>
+Set the async character map to <map>. This map describes which
+control characters cannot be successfully received over the serial
+line. Pppd will ask the peer to send these characters as a 2-byte
+escape sequence. The argument is a 32 bit hex number with each bit
+representing a character to escape. Bit 0 (00000001) represents the
+character 0x00; bit 31 (80000000) represents the character 0x1f or ^_.
+If multiple \fIasyncmap\fR options are given, the values are ORed
+together. If no \fIasyncmap\fR option is given, no async character
+map will be negotiated for the receive direction; the peer should then
+escape \fIall\fR control characters. To escape transmitted
+characters, use the \fIescape\fR option.
+.TP
+.B auth
+Require the peer to authenticate itself before allowing network
+packets to be sent or received. This option is the default if the
+system has a default route. If neither this option nor the
+\fInoauth\fR option is specified, pppd will only allow the peer to use
+IP addresses to which the system does not already have a route.
+.TP
+.B call \fIname
+Read options from the file /etc/ppp/peers/\fIname\fR. This file may
+contain privileged options, such as \fInoauth\fR, even if pppd
+is not being run by root. The \fIname\fR string may not begin with /
+or include .. as a pathname component. The format of the options file
+is described below.
+.TP
+.B connect \fIscript
+Use the executable or shell command specified by \fIscript\fR to set
+up the serial line. This script would typically use the chat(8)
+program to dial the modem and start the remote ppp session. A value
+for this option from a privileged source cannot be overridden by a
+non-privileged user.
+.TP
+.B crtscts
+Use hardware flow control (i.e. RTS/CTS) to control the flow of
+data on the serial port. If neither the \fIcrtscts\fR, the
+\fInocrtscts\fR, the \fIcdtrcts\fR nor the \fInocdtrcts\fR option
+is given, the hardware flow control setting for the serial port is
+left unchanged.
+Some serial ports (such as Macintosh serial ports) lack a true
+RTS output. Such serial ports use this mode to implement
+unidirectional flow control. The serial port will
+suspend transmission when requested by the modem (via CTS)
+but will be unable to request the modem stop sending to the
+computer. This mode retains the ability to use DTR as
+a modem control line.
+.TP
+.B defaultroute
+Add a default route to the system routing tables, using the peer as
+the gateway, when IPCP negotiation is successfully completed.
+This entry is removed when the PPP connection is broken. This option
+is privileged if the \fInodefaultroute\fR option has been specified.
+.TP
+.B disconnect \fIscript
+Run the executable or shell command specified by \fIscript\fR after
+pppd has terminated the link. This script could, for example, issue
+commands to the modem to cause it to hang up if hardware modem control
+signals were not available. The disconnect script is not run if the
+modem has already hung up. A value for this option from a privileged
+source cannot be overridden by a non-privileged user.
+.TP
+.B escape \fIxx,yy,...
+Specifies that certain characters should be escaped on transmission
+(regardless of whether the peer requests them to be escaped with its
+async control character map). The characters to be escaped are
+specified as a list of hex numbers separated by commas. Note that
+almost any character can be specified for the \fIescape\fR option,
+unlike the \fIasyncmap\fR option which only allows control characters
+to be specified. The characters which may not be escaped are those
+with hex values 0x20 - 0x3f or 0x5e.
+.TP
+.B file \fIname
+Read options from file \fIname\fR (the format is described below).
+The file must be readable by the user who has invoked pppd.
+.TP
+.B init \fIscript
+Run the executable or shell command specified by \fIscript\fR to
+initialize the serial line. This script would typically use the
+chat(8) program to configure the modem to enable auto answer. A value
+for this option from a privileged source cannot be overridden by a
+non-privileged user.
+.TP
+.B lock
+Specifies that pppd should create a UUCP-style lock file for the
+serial device to ensure exclusive access to the device.
+.TP
+.B mru \fIn
+Set the MRU [Maximum Receive Unit] value to \fIn\fR. Pppd
+will ask the peer to send packets of no more than \fIn\fR bytes. The
+minimum MRU value is 128. The default MRU value is 1500. A value of
+296 is recommended for slow links (40 bytes for TCP/IP header + 256
+bytes of data). (Note that for IPv6 MRU must be at least 1280)
+.TP
+.B mtu \fIn
+Set the MTU [Maximum Transmit Unit] value to \fIn\fR. Unless the
+peer requests a smaller value via MRU negotiation, pppd will
+request that the kernel networking code send data packets of no more
+than \fIn\fR bytes through the PPP network interface. (Note that for
+IPv6 MTU must be at least 1280)
+.TP
+.B passive
+Enables the "passive" option in the LCP. With this option, pppd will
+attempt to initiate a connection; if no reply is received from the
+peer, pppd will then just wait passively for a valid LCP packet from
+the peer, instead of exiting, as it would without this option.
+.SH OPTIONS
+.TP
+.I <local_IP_address>\fB:\fI<remote_IP_address>
+Set the local and/or remote interface IP addresses. Either one may be
+omitted. The IP addresses can be specified with a host name or in
+decimal dot notation (e.g. 150.234.56.78). The default local
+address is the (first) IP address of the system (unless the
+\fInoipdefault\fR
+option is given). The remote address will be obtained from the peer
+if not specified in any option. Thus, in simple cases, this option is
+not required. If a local and/or remote IP address is specified with
+this option, pppd
+will not accept a different value from the peer in the IPCP
+negotiation, unless the \fIipcp-accept-local\fR and/or
+\fIipcp-accept-remote\fR options are given, respectively.
+.TP
+.B ipv6 \fI<local_interface_identifier>\fR,\fI<remote_interface_identifier>
+Set the local and/or remote 64-bit interface identifier. Either one may be
+omitted. The identifier must be specified in standard ascii notation of
+IPv6 addresses (e.g. ::dead:beef). If the
+\fIipv6cp-use-ipaddr\fR
+option is given, the local identifier is the local IPv4 address (see above).
+On systems which supports a unique persistent id, such as EUI-48 derived
+from the Ethernet MAC address, \fIipv6cp-use-persistent\fR option can be
+used to replace the \fIipv6 <local>,<remote>\fR option. Otherwise the
+identifier is randomized.
+.TP
+.B active-filter \fIfilter-expression
+Specifies a packet filter to be applied to data packets to determine
+which packets are to be regarded as link activity, and therefore reset
+the idle timer, or cause the link to be brought up in demand-dialling
+mode. This option is useful in conjunction with the
+\fBidle\fR option if there are packets being sent or received
+regularly over the link (for example, routing information packets)
+which would otherwise prevent the link from ever appearing to be idle.
+The \fIfilter-expression\fR syntax is as described for tcpdump(1),
+except that qualifiers which are inappropriate for a PPP link, such as
+\fBether\fR and \fBarp\fR, are not permitted. Generally the filter
+expression should be enclosed in single-quotes to prevent whitespace
+in the expression from being interpreted by the shell. This option
+is currently only available under NetBSD, and then only
+if both the kernel and pppd were compiled with PPP_FILTER defined.
+.TP
+.B allow-ip \fIaddress(es)
+Allow peers to use the given IP address or subnet without
+authenticating themselves. The parameter is parsed as for each
+element of the list of allowed IP addresses in the secrets files (see
+the AUTHENTICATION section below).
+.TP
+.B bsdcomp \fInr,nt
+Request that the peer compress packets that it sends, using the
+BSD-Compress scheme, with a maximum code size of \fInr\fR bits, and
+agree to compress packets sent to the peer with a maximum code size of
+\fInt\fR bits. If \fInt\fR is not specified, it defaults to the value
+given for \fInr\fR. Values in the range 9 to 15 may be used for
+\fInr\fR and \fInt\fR; larger values give better compression but
+consume more kernel memory for compression dictionaries.
+Alternatively, a value of 0 for \fInr\fR or \fInt\fR disables
+compression in the corresponding direction. Use \fInobsdcomp\fR or
+\fIbsdcomp 0\fR to disable BSD-Compress compression entirely.
+.TP
+.B cdtrcts
+Use a non-standard hardware flow control (i.e. DTR/CTS) to control
+the flow of data on the serial port. If neither the \fIcrtscts\fR,
+the \fInocrtscts\fR, the \fIcdtrcts\fR nor the \fInocdtrcts\fR
+option is given, the hardware flow control setting for the serial
+port is left unchanged.
+Some serial ports (such as Macintosh serial ports) lack a true
+RTS output. Such serial ports use this mode to implement true
+bi-directional flow control. The sacrifice is that this flow
+control mode does not permit using DTR as a modem control line.
+.TP
+.B chap-interval \fIn
+If this option is given, pppd will rechallenge the peer every \fIn\fR
+seconds.
+.TP
+.B chap-max-challenge \fIn
+Set the maximum number of CHAP challenge transmissions to \fIn\fR
+(default 10).
+.TP
+.B chap-restart \fIn
+Set the CHAP restart interval (retransmission timeout for challenges)
+to \fIn\fR seconds (default 3).
+.TP
+.B connect-delay \fIn
+Wait for up \fIn\fR milliseconds after the connect script finishes for
+a valid PPP packet from the peer. At the end of this time, or when a
+valid PPP packet is received from the peer, pppd will commence
+negotiation by sending its first LCP packet. The default value is
+1000 (1 second). This wait period only applies if the \fBconnect\fR
+or \fBpty\fR option is used.
+.TP
+.B debug
+Enables connection debugging facilities.
+If this option is given, pppd will log the contents of all
+control packets sent or received in a readable form. The packets are
+logged through syslog with facility \fIdaemon\fR and level
+\fIdebug\fR. This information can be directed to a file by setting up
+/etc/syslog.conf appropriately (see syslog.conf(5)).
+.TP
+.B default-asyncmap
+Disable asyncmap negotiation, forcing all control characters to be
+escaped for both the transmit and the receive direction.
+.TP
+.B default-mru
+Disable MRU [Maximum Receive Unit] negotiation. With this option,
+pppd will use the default MRU value of 1500 bytes for both the
+transmit and receive direction.
+.TP
+.B deflate \fInr,nt
+Request that the peer compress packets that it sends, using the
+Deflate scheme, with a maximum window size of \fI2**nr\fR bytes, and
+agree to compress packets sent to the peer with a maximum window size
+of \fI2**nt\fR bytes. If \fInt\fR is not specified, it defaults to
+the value given for \fInr\fR. Values in the range 8 to 15 may be used
+for \fInr\fR and \fInt\fR; larger values give better compression but
+consume more kernel memory for compression dictionaries.
+Alternatively, a value of 0 for \fInr\fR or \fInt\fR disables
+compression in the corresponding direction. Use \fInodeflate\fR or
+\fIdeflate 0\fR to disable Deflate compression entirely. (Note: pppd
+requests Deflate compression in preference to BSD-Compress if the peer
+can do either.)
+.TP
+.B demand
+Initiate the link only on demand, i.e. when data traffic is present.
+With this option, the remote IP address must be specified by the user
+on the command line or in an options file. Pppd will initially
+configure the interface and enable it for IP traffic without
+connecting to the peer. When traffic is available, pppd will
+connect to the peer and perform negotiation, authentication, etc.
+When this is completed, pppd will commence passing data packets
+(i.e., IP packets) across the link.
+
+The \fIdemand\fR option implies the \fIpersist\fR option. If this
+behaviour is not desired, use the \fInopersist\fR option after the
+\fIdemand\fR option. The \fIidle\fR and \fIholdoff\fR
+options are also useful in conjuction with the \fIdemand\fR option.
+.TP
+.B domain \fId
+Append the domain name \fId\fR to the local host name for authentication
+purposes. For example, if gethostname() returns the name porsche, but
+the fully qualified domain name is porsche.Quotron.COM, you could
+specify \fIdomain Quotron.COM\fR. Pppd would then use the name
+\fIporsche.Quotron.COM\fR for looking up secrets in the secrets file,
+and as the default name to send to the peer when authenticating itself
+to the peer. This option is privileged.
+.TP
+.B hide-password
+When logging the contents of PAP packets, this option causes pppd to
+exclude the password string from the log. This is the default.
+.TP
+.B holdoff \fIn
+Specifies how many seconds to wait before re-initiating the link after
+it terminates. This option only has any effect if the \fIpersist\fR
+or \fIdemand\fR option is used. The holdoff period is not applied if
+the link was terminated because it was idle.
+.TP
+.B idle \fIn
+Specifies that pppd should disconnect if the link is idle for \fIn\fR
+seconds. The link is idle when no data packets (i.e. IP packets) are
+being sent or received. Note: it is not advisable to use this option
+with the \fIpersist\fR option without the \fIdemand\fR option.
+If the \fBactive-filter\fR
+option is given, data packets which are rejected by the specified
+activity filter also count as the link being idle.
+.TP
+.B ipcp-accept-local
+With this option, pppd will accept the peer's idea of our local IP
+address, even if the local IP address was specified in an option.
+.TP
+.B ipcp-accept-remote
+With this option, pppd will accept the peer's idea of its (remote) IP
+address, even if the remote IP address was specified in an option.
+.TP
+.B ipcp-max-configure \fIn
+Set the maximum number of IPCP configure-request transmissions to
+\fIn\fR (default 10).
+.TP
+.B ipcp-max-failure \fIn
+Set the maximum number of IPCP configure-NAKs returned before starting
+to send configure-Rejects instead to \fIn\fR (default 10).
+.TP
+.B ipcp-max-terminate \fIn
+Set the maximum number of IPCP terminate-request transmissions to
+\fIn\fR (default 3).
+.TP
+.B ipcp-restart \fIn
+Set the IPCP restart interval (retransmission timeout) to \fIn\fR
+seconds (default 3).
+.TP
+.B ipparam \fIstring
+Provides an extra parameter to the ip-up and ip-down scripts. If this
+option is given, the \fIstring\fR supplied is given as the 6th
+parameter to those scripts.
+.TP
+.B ipv6cp-max-configure \fIn
+Set the maximum number of IPv6CP configure-request transmissions to
+\fIn\fR (default 10).
+.TP
+.B ipv6cp-max-failure \fIn
+Set the maximum number of IPv6CP configure-NAKs returned before starting
+to send configure-Rejects instead to \fIn\fR (default 10).
+.TP
+.B ipv6cp-max-terminate \fIn
+Set the maximum number of IPv6CP terminate-request transmissions to
+\fIn\fR (default 3).
+.TP
+.B ipv6cp-restart \fIn
+Set the IPv6CP restart interval (retransmission timeout) to \fIn\fR
+seconds (default 3).
+.TP
+.B ipx
+Enable the IPXCP and IPX protocols. This option is presently only
+supported under Linux, and only if your kernel has been configured to
+include IPX support.
+.TP
+.B ipx-network \fIn
+Set the IPX network number in the IPXCP configure request frame to
+\fIn\fR, a hexadecimal number (without a leading 0x). There is no
+valid default. If this option is not specified, the network number is
+obtained from the peer. If the peer does not have the network number,
+the IPX protocol will not be started.
+.TP
+.B ipx-node \fIn\fB:\fIm
+Set the IPX node numbers. The two node numbers are separated from each
+other with a colon character. The first number \fIn\fR is the local
+node number. The second number \fIm\fR is the peer's node number. Each
+node number is a hexadecimal number, at most 10 digits long. The node
+numbers on the ipx-network must be unique. There is no valid
+default. If this option is not specified then the node numbers are
+obtained from the peer.
+.TP
+.B ipx-router-name \fI<string>
+Set the name of the router. This is a string and is sent to the peer
+as information data.
+.TP
+.B ipx-routing \fIn
+Set the routing protocol to be received by this option. More than one
+instance of \fIipx-routing\fR may be specified. The '\fInone\fR'
+option (0) may be specified as the only instance of ipx-routing. The
+values may be \fI0\fR for \fINONE\fR, \fI2\fR for \fIRIP/SAP\fR, and
+\fI4\fR for \fINLSP\fR.
+.TP
+.B ipxcp-accept-local
+Accept the peer's NAK for the node number specified in the ipx-node
+option. If a node number was specified, and non-zero, the default is
+to insist that the value be used. If you include this option then you
+will permit the peer to override the entry of the node number.
+.TP
+.B ipxcp-accept-network
+Accept the peer's NAK for the network number specified in the
+ipx-network option. If a network number was specified, and non-zero, the
+default is to insist that the value be used. If you include this
+option then you will permit the peer to override the entry of the node
+number.
+.TP
+.B ipxcp-accept-remote
+Use the peer's network number specified in the configure request
+frame. If a node number was specified for the peer and this option was
+not specified, the peer will be forced to use the value which you have
+specified.
+.TP
+.B ipxcp-max-configure \fIn
+Set the maximum number of IPXCP configure request frames which the
+system will send to \fIn\fR. The default is 10.
+.TP
+.B ipxcp-max-failure \fIn
+Set the maximum number of IPXCP NAK frames which the local system will
+send before it rejects the options. The default value is 3.
+.TP
+.B ipxcp-max-terminate \fIn
+Set the maximum nuber of IPXCP terminate request frames before the
+local system considers that the peer is not listening to them. The
+default value is 3.
+.TP
+.B kdebug \fIn
+Enable debugging code in the kernel-level PPP driver. The argument
+\fIn\fR is a number which is the sum of the following values: 1 to
+enable general debug messages, 2 to request that the contents of
+received packets be printed, and 4 to request that the contents of
+transmitted packets be printed. On most systems, messages printed by
+the kernel are logged by syslog(1) to a file as directed in the
+/etc/syslog.conf configuration file.
+.TP
+.B ktune
+Enables pppd to alter kernel settings as appropriate. Under Linux,
+pppd will enable IP forwarding (i.e. set /proc/sys/net/ipv4/ip_forward
+to 1) if the \fIproxyarp\fR option is used, and will enable the
+dynamic IP address option (i.e. set /proc/sys/net/ipv4/ip_dynaddr to
+1) in demand mode if the local address changes.
+.TP
+.B lcp-echo-failure \fIn
+If this option is given, pppd will presume the peer to be dead
+if \fIn\fR LCP echo-requests are sent without receiving a valid LCP
+echo-reply. If this happens, pppd will terminate the
+connection. Use of this option requires a non-zero value for the
+\fIlcp-echo-interval\fR parameter. This option can be used to enable
+pppd to terminate after the physical connection has been broken
+(e.g., the modem has hung up) in situations where no hardware modem
+control lines are available.
+.TP
+.B lcp-echo-interval \fIn
+If this option is given, pppd will send an LCP echo-request frame to
+the peer every \fIn\fR seconds. Normally the peer should respond to
+the echo-request by sending an echo-reply. This option can be used
+with the \fIlcp-echo-failure\fR option to detect that the peer is no
+longer connected.
+.TP
+.B lcp-max-configure \fIn
+Set the maximum number of LCP configure-request transmissions to
+\fIn\fR (default 10).
+.TP
+.B lcp-max-failure \fIn
+Set the maximum number of LCP configure-NAKs returned before starting
+to send configure-Rejects instead to \fIn\fR (default 10).
+.TP
+.B lcp-max-terminate \fIn
+Set the maximum number of LCP terminate-request transmissions to
+\fIn\fR (default 3).
+.TP
+.B lcp-restart \fIn
+Set the LCP restart interval (retransmission timeout) to \fIn\fR
+seconds (default 3).
+.TP
+.B linkname \fIname\fR
+Sets the logical name of the link to \fIname\fR. Pppd will create a
+file named \fBppp-\fIname\fB.pid\fR in /var/run (or /etc/ppp on some
+systems) containing its process ID. This can be useful in determining
+which instance of pppd is responsible for the link to a given peer
+system. This is a privileged option.
+.TP
+.B local
+Don't use the modem control lines. With this option, pppd will ignore
+the state of the CD (Carrier Detect) signal from the modem and will
+not change the state of the DTR (Data Terminal Ready) signal.
+.TP
+.B logfd \fIn
+Send log messages to file descriptor \fIn\fR. Pppd will send log
+messages to at most one file or file descriptor (as well as sending
+the log messages to syslog), so this option and the \fBlogfile\fR
+option are mutually exclusive. The default is for pppd to send log
+messages to stdout (file descriptor 1), unless the serial port is
+already open on stdout.
+.TP
+.B logfile \fIfilename
+Append log messages to the file \fIfilename\fR (as well as sending the
+log messages to syslog). The file is opened with the privileges of
+the user who invoked pppd, in append mode.
+.TP
+.B login
+Use the system password database for authenticating the peer using
+PAP, and record the user in the system wtmp file. Note that the peer
+must have an entry in the /etc/ppp/pap-secrets file as well as the
+system password database to be allowed access.
+.TP
+.B maxconnect \fIn
+Terminate the connection when it has been available for network
+traffic for \fIn\fR seconds (i.e. \fIn\fR seconds after the first
+network control protocol comes up).
+.TP
+.B maxfail \fIn
+Terminate after \fIn\fR consecutive failed connection attempts. A
+value of 0 means no limit. The default value is 10.
+.TP
+.B modem
+Use the modem control lines. This option is the default. With this
+option, pppd will wait for the CD (Carrier Detect) signal from the
+modem to be asserted when opening the serial device (unless a connect
+script is specified), and it will drop the DTR (Data Terminal Ready)
+signal briefly when the connection is terminated and before executing
+the connect script. On Ultrix, this option implies hardware flow
+control, as for the \fIcrtscts\fR option.
+.TP
+.B ms-dns \fI<addr>
+If pppd is acting as a server for Microsoft Windows clients, this
+option allows pppd to supply one or two DNS (Domain Name Server)
+addresses to the clients. The first instance of this option specifies
+the primary DNS address; the second instance (if given) specifies the
+secondary DNS address. (This option was present in some older
+versions of pppd under the name \fBdns-addr\fR.)
+.TP
+.B ms-wins \fI<addr>
+If pppd is acting as a server for Microsoft Windows or "Samba"
+clients, this option allows pppd to supply one or two WINS (Windows
+Internet Name Services) server addresses to the clients. The first
+instance of this option specifies the primary WINS address; the second
+instance (if given) specifies the secondary WINS address.
+.TP
+.B name \fIname
+Set the name of the local system for authentication purposes to
+\fIname\fR. This is a privileged option. With this option, pppd will
+use lines in the secrets files which have \fIname\fR as the second
+field when looking for a secret to use in authenticating the peer. In
+addition, unless overridden with the \fIuser\fR option, \fIname\fR
+will be used as the name to send to the peer when authenticating the
+local system to the peer. (Note that pppd does not append the domain
+name to \fIname\fR.)
+.TP
+.B netmask \fIn
+Set the interface netmask to \fIn\fR, a 32 bit netmask in "decimal dot"
+notation (e.g. 255.255.255.0). If this option is given, the value
+specified is ORed with the default netmask. The default netmask is
+chosen based on the negotiated remote IP address; it is the
+appropriate network mask for the class of the remote IP address, ORed
+with the netmasks for any non point-to-point network interfaces in the
+system which are on the same network. (Note: on some platforms, pppd
+will always use 255.255.255.255 for the netmask, if that is the only
+appropriate value for a point-to-point interface.)
+.TP
+.B noaccomp
+Disable Address/Control compression in both directions (send and
+receive).
+.TP
+.B noauth
+Do not require the peer to authenticate itself. This option is
+privileged.
+.TP
+.B nobsdcomp
+Disables BSD-Compress compression; \fBpppd\fR will not request or
+agree to compress packets using the BSD-Compress scheme.
+.TP
+.B noccp
+Disable CCP (Compression Control Protocol) negotiation. This option
+should only be required if the peer is buggy and gets confused by
+requests from pppd for CCP negotiation.
+.TP
+.B nocrtscts
+Disable hardware flow control (i.e. RTS/CTS) on the serial port.
+If neither the \fIcrtscts\fR nor the \fInocrtscts\fR nor the
+\fIcdtrcts\fR nor the \fInodtrcts\fR option is given, the hardware
+flow control setting for the serial port is left unchanged.
+.TP
+.B nodtrcts
+This option is a synonym for \fInocrtscts\fR. Either of these options will
+disable both forms of hardware flow control.
+.TP
+.B nodefaultroute
+Disable the \fIdefaultroute\fR option. The system administrator who
+wishes to prevent users from creating default routes with pppd
+can do so by placing this option in the /etc/ppp/options file.
+.TP
+.B nodeflate
+Disables Deflate compression; pppd will not request or agree to
+compress packets using the Deflate scheme.
+.TP
+.B nodetach
+Don't detach from the controlling terminal. Without this option, if a
+serial device other than the terminal on the standard input is
+specified, pppd will fork to become a background process.
+.TP
+.B noip
+Disable IPCP negotiation and IP communication. This option should
+only be required if the peer is buggy and gets confused by requests
+from pppd for IPCP negotiation.
+.TP
+.B noipv6
+Disable IPv6CP negotiation and IPv6 communication. This option should
+only be required if the peer is buggy and gets confused by requests
+from pppd for IPv6CP negotiation.
+.TP
+.B noipdefault
+Disables the default behaviour when no local IP address is specified,
+which is to determine (if possible) the local IP address from the
+hostname. With this option, the peer will have to supply the local IP
+address during IPCP negotiation (unless it specified explicitly on the
+command line or in an options file).
+.TP
+.B noipx
+Disable the IPXCP and IPX protocols. This option should only be
+required if the peer is buggy and gets confused by requests from pppd
+for IPXCP negotiation.
+.TP
+.B noktune
+Opposite of the \fIktune\fR option; disables pppd from changing system
+settings.
+.TP
+.B nolog
+Do not send log messages to a file or file descriptor. This option
+cancels the \fBlogfd\fR and \fBlogfile\fR options.
+.B nomagic
+Disable magic number negotiation. With this option, pppd cannot
+detect a looped-back line. This option should only be needed if the
+peer is buggy.
+.TP
+.B nopcomp
+Disable protocol field compression negotiation in both the receive and
+the transmit direction.
+.TP
+.B nopersist
+Exit once a connection has been made and terminated. This is the
+default unless the \fIpersist\fR or \fIdemand\fR option has been
+specified.
+.TP
+.B nopredictor1
+Do not accept or agree to Predictor-1 compression.
+.TP
+.B noproxyarp
+Disable the \fIproxyarp\fR option. The system administrator who
+wishes to prevent users from creating proxy ARP entries with pppd can
+do so by placing this option in the /etc/ppp/options file.
+.TP
+.B notty
+Normally, pppd requires a terminal device. With this option, pppd
+will allocate itself a pseudo-tty master/slave pair and use the slave
+as its terminal device. Pppd will create a child process to act as a
+`character shunt' to transfer characters between the pseudo-tty master
+and its standard input and output. Thus pppd will transmit characters
+on its standard output and receive characters on its standard input
+even if they are not terminal devices. This option increases the
+latency and CPU overhead of transferring data over the ppp interface
+as all of the characters sent and received must flow through the
+character shunt process. An explicit device name may not be given if
+this option is used.
+.TP
+.B novj
+Disable Van Jacobson style TCP/IP header compression in both the
+transmit and the receive direction.
+.TP
+.B novjccomp
+Disable the connection-ID compression option in Van Jacobson style
+TCP/IP header compression. With this option, pppd will not omit the
+connection-ID byte from Van Jacobson compressed TCP/IP headers, nor
+ask the peer to do so.
+.TP
+.B papcrypt
+Indicates that all secrets in the /etc/ppp/pap-secrets file which are
+used for checking the identity of the peer are encrypted, and thus
+pppd should not accept a password which, before encryption, is
+identical to the secret from the /etc/ppp/pap-secrets file.
+.TP
+.B pap-max-authreq \fIn
+Set the maximum number of PAP authenticate-request transmissions to
+\fIn\fR (default 10).
+.TP
+.B pap-restart \fIn
+Set the PAP restart interval (retransmission timeout) to \fIn\fR
+seconds (default 3).
+.TP
+.B pap-timeout \fIn
+Set the maximum time that pppd will wait for the peer to authenticate
+itself with PAP to \fIn\fR seconds (0 means no limit).
+.TP
+.B pass-filter \fIfilter-expression
+Specifies a packet filter to applied to data packets being sent or
+received to determine which packets should be allowed to pass.
+Packets which are rejected by the filter are silently discarded. This
+option can be used to prevent specific network daemons (such as
+routed) using up link bandwidth, or to provide a basic firewall
+capability.
+The \fIfilter-expression\fR syntax is as described for tcpdump(1),
+except that qualifiers which are inappropriate for a PPP link, such as
+\fBether\fR and \fBarp\fR, are not permitted. Generally the filter
+expression should be enclosed in single-quotes to prevent whitespace
+in the expression from being interpreted by the shell. Note that it
+is possible to apply different constraints to incoming and outgoing
+packets using the \fBinbound\fR and \fBoutbound\fR qualifiers. This
+option is currently only available under NetBSD, and then only if both
+the kernel and pppd were compiled with PPP_FILTER defined.
+.TP
+.B persist
+Do not exit after a connection is terminated; instead try to reopen
+the connection.
+.TP
+.B plugin \fIfilename
+Load the shared library object file \fIfilename\fR as a plugin. This
+is a privileged option.
+.TP
+.B predictor1
+Request that the peer compress frames that it sends using Predictor-1
+compression, and agree to compress transmitted frames with Predictor-1
+if requested. This option has no effect unless the kernel driver
+supports Predictor-1 compression.
+.TP
+.B privgroup \fIgroup-name
+Allows members of group \fIgroup-name\fR to use privileged options.
+This is a privileged option. Use of this option requires care as
+there is no guarantee that members of \fIgroup-name\fR cannot use pppd
+to become root themselves. Consider it equivalent to putting the
+members of \fIgroup-name\fR in the kmem or disk group.
+.TP
+.B proxyarp
+Add an entry to this system's ARP [Address Resolution Protocol] table
+with the IP address of the peer and the Ethernet address of this
+system. This will have the effect of making the peer appear to other
+systems to be on the local ethernet.
+.TP
+.B pty \fIscript
+Specifies that the command \fIscript\fR is to be used to communicate
+rather than a specific terminal device. Pppd will allocate itself a
+pseudo-tty master/slave pair and use the slave as its terminal
+device. The \fIscript\fR will be run in a child process with the
+pseudo-tty master as its standard input and output. An explicit
+device name may not be given if this option is used. (Note: if the
+\fIrecord\fR option is used in conjuction with the \fIpty\fR option,
+the child process will have pipes on its standard input and output.)
+.TP
+.B receive-all
+With this option, pppd will accept all control characters from the
+peer, including those marked in the receive asyncmap. Without this
+option, pppd will discard those characters as specified in RFC1662.
+This option should only be needed if the peer is buggy.
+.TP
+.B record \fIfilename
+Specifies that pppd should record all characters sent and received to
+a file named \fIfilename\fR. This file is opened in append mode,
+using the user's user-ID and permissions. This option is implemented
+using a pseudo-tty and a process to transfer characters between the
+pseudo-tty and the real serial device, so it will increase the latency
+and CPU overhead of transferring data over the ppp interface. The
+characters are stored in a tagged format with timestamps, which can be
+displayed in readable form using the pppdump(8) program.
+.TP
+.B remotename \fIname
+Set the assumed name of the remote system for authentication purposes
+to \fIname\fR.
+.TP
+.B refuse-chap
+With this option, pppd will not agree to authenticate itself to the
+peer using CHAP.
+.TP
+.B refuse-pap
+With this option, pppd will not agree to authenticate itself to the
+peer using PAP.
+.TP
+.B require-chap
+Require the peer to authenticate itself using CHAP [Challenge
+Handshake Authentication Protocol] authentication.
+.TP
+.B require-pap
+Require the peer to authenticate itself using PAP [Password
+Authentication Protocol] authentication.
+.TP
+.B show-password
+When logging the contents of PAP packets, this option causes pppd to
+show the password string in the log message.
+.TP
+.B silent
+With this option, pppd will not transmit LCP packets to initiate a
+connection until a valid LCP packet is received from the peer (as for
+the `passive' option with ancient versions of pppd).
+.TP
+.B sync
+Use synchronous HDLC serial encoding instead of asynchronous.
+The device used by pppd with this option must have sync support.
+Currently supports Microgate SyncLink adapters
+under Linux and FreeBSD 2.2.8 and later.
+.TP
+.B updetach
+With this option, pppd will detach from its controlling terminal once
+it has successfully established the ppp connection (to the point where
+the first network control protocol, usually the IP control protocol,
+has come up).
+.TP
+.B usehostname
+Enforce the use of the hostname (with domain name appended, if given)
+as the name of the local system for authentication purposes (overrides
+the \fIname\fR option). This option is not normally needed since the
+\fIname\fR option is privileged.
+.TP
+.B usepeerdns
+Ask the peer for up to 2 DNS server addresses. The addresses supplied
+by the peer (if any) are passed to the /etc/ppp/ip-up script in the
+environment variables DNS1 and DNS2. In addition, pppd will create an
+/etc/ppp/resolv.conf file containing one or two nameserver lines with
+the address(es) supplied by the peer.
+.TP
+.B user \fIname
+Sets the name used for authenticating the local system to the peer to
+\fIname\fR.
+.TP
+.B vj-max-slots \fIn
+Sets the number of connection slots to be used by the Van Jacobson
+TCP/IP header compression and decompression code to \fIn\fR, which
+must be between 2 and 16 (inclusive).
+.TP
+.B welcome \fIscript
+Run the executable or shell command specified by \fIscript\fR before
+initiating PPP negotiation, after the connect script (if any) has
+completed. A value for this option from a privileged source cannot be
+overridden by a non-privileged user.
+.TP
+.B xonxoff
+Use software flow control (i.e. XON/XOFF) to control the flow of data on
+the serial port.
+.SH OPTIONS FILES
+Options can be taken from files as well as the command line. Pppd
+reads options from the files /etc/ppp/options, ~/.ppprc and
+/etc/ppp/options.\fIttyname\fR (in that order) before processing the
+options on the command line. (In fact, the command-line options are
+scanned to find the terminal name before the options.\fIttyname\fR
+file is read.) In forming the name of the options.\fIttyname\fR file,
+the initial /dev/ is removed from the terminal name, and any remaining
+/ characters are replaced with dots.
+.PP
+An options file is parsed into a series of words, delimited by
+whitespace. Whitespace can be included in a word by enclosing the
+word in double-quotes ("). A backslash (\\) quotes the following character.
+A hash (#) starts a comment, which continues until the end of the
+line. There is no restriction on using the \fIfile\fR or \fIcall\fR
+options within an options file.
+.SH SECURITY
+.I pppd
+provides system administrators with sufficient access control that PPP
+access to a server machine can be provided to legitimate users without
+fear of compromising the security of the server or the network it's
+on. This control is provided through restrictions on which IP
+addresses the peer may use, based on its authenticated identity (if
+any), and through restrictions on which options a non-privileged user
+may use. Several of pppd's options are privileged, in particular
+those which permit potentially insecure configurations; these options
+are only accepted in files which are under the control of the system
+administrator, or if pppd is being run by root.
+.PP
+The default behaviour of pppd is to allow an unauthenticated peer to
+use a given IP address only if the system does not already have a
+route to that IP address. For example, a system with a
+permanent connection to the wider internet will normally have a
+default route, and thus all peers will have to authenticate themselves
+in order to set up a connection. On such a system, the \fIauth\fR
+option is the default. On the other hand, a system where the
+PPP link is the only connection to the internet will not normally have
+a default route, so the peer will be able to use almost any IP address
+without authenticating itself.
+.PP
+As indicated above, some security-sensitive options are privileged,
+which means that they may not be used by an ordinary non-privileged
+user running a setuid-root pppd, either on the command line, in the
+user's ~/.ppprc file, or in an options file read using the \fIfile\fR
+option. Privileged options may be used in /etc/ppp/options file or in
+an options file read using the \fIcall\fR option. If pppd is being
+run by the root user, privileged options can be used without
+restriction.
+.PP
+When opening the device, pppd uses either the invoking user's user ID
+or the root UID (that is, 0), depending on whether the device name was
+specified by the user or the system administrator. If the device name
+comes from a privileged source, that is, /etc/ppp/options or an
+options file read using the \fIcall\fR option, pppd uses full root
+privileges when opening the device. Thus, by creating an appropriate
+file under /etc/ppp/peers, the system administrator can allow users to
+establish a ppp connection via a device which they would not normally
+have permission to access. Otherwise pppd uses the invoking user's
+real UID when opening the device.
+.SH AUTHENTICATION
+Authentication is the process whereby one peer convinces the other of
+its identity. This involves the first peer sending its name to the
+other, together with some kind of secret information which could only
+come from the genuine authorized user of that name. In such an
+exchange, we will call the first peer the "client" and the other the
+"server". The client has a name by which it identifies itself to the
+server, and the server also has a name by which it identifies itself
+to the client. Generally the genuine client shares some secret (or
+password) with the server, and authenticates itself by proving that it
+knows that secret. Very often, the names used for authentication
+correspond to the internet hostnames of the peers, but this is not
+essential.
+.LP
+At present, pppd supports two authentication protocols: the Password
+Authentication Protocol (PAP) and the Challenge Handshake
+Authentication Protocol (CHAP). PAP involves the client sending its
+name and a cleartext password to the server to authenticate itself.
+In contrast, the server initiates the CHAP authentication exchange by
+sending a challenge to the client (the challenge packet includes the
+server's name). The client must respond with a response which
+includes its name plus a hash value derived from the shared secret and
+the challenge, in order to prove that it knows the secret.
+.LP
+The PPP protocol, being symmetrical, allows both peers to require the
+other to authenticate itself. In that case, two separate and
+independent authentication exchanges will occur. The two exchanges
+could use different authentication protocols, and in principle,
+different names could be used in the two exchanges.
+.LP
+The default behaviour of pppd is to agree to authenticate if
+requested, and to not require authentication from the peer. However,
+pppd will not agree to authenticate itself with a particular protocol
+if it has no secrets which could be used to do so.
+.LP
+Pppd stores secrets for use in authentication in secrets
+files (/etc/ppp/pap-secrets for PAP, /etc/ppp/chap-secrets for CHAP).
+Both secrets files have the same format. The secrets files can
+contain secrets for pppd to use in authenticating itself to other
+systems, as well as secrets for pppd to use when authenticating other
+systems to itself.
+.LP
+Each line in a secrets file contains one secret. A given secret is
+specific to a particular combination of client and server - it can
+only be used by that client to authenticate itself to that server.
+Thus each line in a secrets file has at least 3 fields: the name of
+the client, the name of the server, and the secret. These fields may
+be followed by a list of the IP addresses that the specified client
+may use when connecting to the specified server.
+.LP
+A secrets file is parsed into words as for a options file, so the
+client name, server name and secrets fields must each be one word,
+with any embedded spaces or other special characters quoted or
+escaped. Note that case is significant in the client and server names
+and in the secret.
+.LP
+If the secret starts with an `@', what follows is assumed to be the
+name of a file from which to read the secret. A "*" as the client or
+server name matches any name. When selecting a secret, pppd takes the
+best match, i.e. the match with the fewest wildcards.
+.LP
+Any following words on the same line are taken to be a list of
+acceptable IP addresses for that client. If there are only 3 words on
+the line, or if the first word is "-", then all IP addresses are
+disallowed. To allow any address, use "*". A word starting with "!"
+indicates that the specified address is \fInot\fR acceptable. An
+address may be followed by "/" and a number \fIn\fR, to indicate a
+whole subnet, i.e. all addresses which have the same value in the most
+significant \fIn\fR bits. In this form, the address may be followed
+by a plus sign ("+") to indicate that one address from the subnet is
+authorized, based on the ppp network interface unit number in use.
+In this case, the host part of the address will be set to the unit
+number plus one.
+.LP
+Thus a secrets file contains both secrets for use in authenticating
+other hosts, plus secrets which we use for authenticating ourselves to
+others. When pppd is authenticating the peer (checking the peer's
+identity), it chooses a secret with the peer's name in the first
+field and the name of the local system in the second field. The
+name of the local system defaults to the hostname, with the domain
+name appended if the \fIdomain\fR option is used. This default can be
+overridden with the \fIname\fR option, except when the
+\fIusehostname\fR option is used.
+.LP
+When pppd is choosing a secret to use in authenticating itself to the
+peer, it first determines what name it is going to use to identify
+itself to the peer. This name can be specified by the user with the
+\fIuser\fR option. If this option is not used, the name defaults to
+the name of the local system, determined as described in the previous
+paragraph. Then pppd looks for a secret with this name in the first
+field and the peer's name in the second field. Pppd will know the
+name of the peer if CHAP authentication is being used, because the
+peer will have sent it in the challenge packet. However, if PAP is being
+used, pppd will have to determine the peer's name from the options
+specified by the user. The user can specify the peer's name directly
+with the \fIremotename\fR option. Otherwise, if the remote IP address
+was specified by a name (rather than in numeric form), that name will
+be used as the peer's name. Failing that, pppd will use the null
+string as the peer's name.
+.LP
+When authenticating the peer with PAP, the supplied password is first
+compared with the secret from the secrets file. If the password
+doesn't match the secret, the password is encrypted using crypt() and
+checked against the secret again. Thus secrets for authenticating the
+peer can be stored in encrypted form if desired. If the
+\fIpapcrypt\fR option is given, the first (unencrypted) comparison is
+omitted, for better security.
+.LP
+Furthermore, if the \fIlogin\fR option was specified, the username and
+password are also checked against the system password database. Thus,
+the system administrator can set up the pap-secrets file to allow PPP
+access only to certain users, and to restrict the set of IP addresses
+that each user can use. Typically, when using the \fIlogin\fR option,
+the secret in /etc/ppp/pap-secrets would be "", which will match any
+password supplied by the peer. This avoids the need to have the same
+secret in two places.
+.LP
+Authentication must be satisfactorily completed before IPCP (or any
+other Network Control Protocol) can be started. If the peer is
+required to authenticate itself, and fails to do so, pppd will
+terminated the link (by closing LCP). If IPCP negotiates an
+unacceptable IP address for the remote host, IPCP will be closed. IP
+packets can only be sent or received when IPCP is open.
+.LP
+In some cases it is desirable to allow some hosts which can't
+authenticate themselves to connect and use one of a restricted set of
+IP addresses, even when the local host generally requires
+authentication. If the peer refuses to authenticate itself when
+requested, pppd takes that as equivalent to authenticating with PAP
+using the empty string for the username and password. Thus, by adding
+a line to the pap-secrets file which specifies the empty string for
+the client and password, it is possible to allow restricted access to
+hosts which refuse to authenticate themselves.
+.SH ROUTING
+.LP
+When IPCP negotiation is completed successfully, pppd will inform the
+kernel of the local and remote IP addresses for the ppp interface.
+This is sufficient to create a host route to the remote end of the
+link, which will enable the peers to exchange IP packets.
+Communication with other machines generally requires further
+modification to routing tables and/or ARP (Address Resolution
+Protocol) tables. In most cases the \fIdefaultroute\fR and/or
+\fIproxyarp\fR options are sufficient for this, but in some cases
+further intervention is required. The /etc/ppp/ip-up script can be
+used for this.
+.LP
+Sometimes it is desirable to add a default route through the remote
+host, as in the case of a machine whose only connection to the
+Internet is through the ppp interface. The \fIdefaultroute\fR option
+causes pppd to create such a default route when IPCP comes up, and
+delete it when the link is terminated.
+.LP
+In some cases it is desirable to use proxy ARP, for example on a
+server machine connected to a LAN, in order to allow other hosts to
+communicate with the remote host. The \fIproxyarp\fR option causes
+pppd to look for a network interface on the same subnet as the remote
+host (an interface supporting broadcast and ARP, which is up and not a
+point-to-point or loopback interface). If found, pppd creates a
+permanent, published ARP entry with the IP address of the remote host
+and the hardware address of the network interface found.
+.LP
+When the \fIdemand\fR option is used, the interface IP addresses have
+already been set at the point when IPCP comes up. If pppd has not
+been able to negotiate the same addresses that it used to configure
+the interface (for example when the peer is an ISP that uses dynamic
+IP address assignment), pppd has to change the interface IP addresses
+to the negotiated addresses. This may disrupt existing connections,
+and the use of demand dialling with peers that do dynamic IP address
+assignment is not recommended.
+.SH EXAMPLES
+.LP
+The following examples assume that the /etc/ppp/options file contains
+the \fIauth\fR option (as in the default /etc/ppp/options file in the
+ppp distribution).
+.LP
+Probably the most common use of pppd is to dial out to an ISP. This
+can be done with a command such as
+.IP
+pppd call isp
+.LP
+where the /etc/ppp/peers/isp file is set up by the system
+administrator to contain something like this:
+.IP
+ttyS0 19200 crtscts
+.br
+connect '/usr/sbin/chat -v -f /etc/ppp/chat-isp'
+.br
+noauth
+.LP
+In this example, we are using chat to dial the ISP's modem and go
+through any logon sequence required. The /etc/ppp/chat-isp file
+contains the script used by chat; it could for example contain
+something like this:
+.IP
+ABORT "NO CARRIER"
+.br
+ABORT "NO DIALTONE"
+.br
+ABORT "ERROR"
+.br
+ABORT "NO ANSWER"
+.br
+ABORT "BUSY"
+.br
+ABORT "Username/Password Incorrect"
+.br
+"" "at"
+.br
+OK "at&d0&c1"
+.br
+OK "atdt2468135"
+.br
+"name:" "^Umyuserid"
+.br
+"word:" "\\qmypassword"
+.br
+"ispts" "\\q^Uppp"
+.br
+"~-^Uppp-~"
+.LP
+See the chat(8) man page for details of chat scripts.
+.LP
+Pppd can also be used to provide a dial-in ppp service for users. If
+the users already have login accounts, the simplest way to set up the
+ppp service is to let the users log in to their accounts and run pppd
+(installed setuid-root) with a command such as
+.IP
+pppd proxyarp
+.LP
+To allow a user to use the PPP facilities, you need to allocate an IP
+address for that user's machine and create an entry in
+/etc/ppp/pap-secrets or /etc/ppp/chap-secrets (depending on which
+authentication method the PPP implementation on the user's machine
+supports), so that the user's
+machine can authenticate itself. For example, if Joe has a machine
+called "joespc" which is to be allowed to dial in to the machine
+called "server" and use the IP address joespc.my.net, you would add an
+entry like this to /etc/ppp/pap-secrets or /etc/ppp/chap-secrets:
+.IP
+joespc server "joe's secret" joespc.my.net
+.LP
+Alternatively, you can create a username called (for example) "ppp",
+whose login shell is pppd and whose home directory is /etc/ppp.
+Options to be used when pppd is run this way can be put in
+/etc/ppp/.ppprc.
+.LP
+If your serial connection is any more complicated than a piece of
+wire, you may need to arrange for some control characters to be
+escaped. In particular, it is often useful to escape XON (^Q) and
+XOFF (^S), using \fIasyncmap a0000\fR. If the path includes a telnet,
+you probably should escape ^] as well (\fIasyncmap 200a0000\fR). If
+the path includes an rlogin, you will need to use the \fIescape ff\fR
+option on the end which is running the rlogin client, since many
+rlogin implementations are not transparent; they will remove the
+sequence [0xff, 0xff, 0x73, 0x73, followed by any 8 bytes] from the
+stream.
+.SH DIAGNOSTICS
+.LP
+Messages are sent to the syslog daemon using facility LOG_DAEMON.
+(This can be overriden by recompiling pppd with the macro
+LOG_PPP defined as the desired facility.) In order to see the error
+and debug messages, you will need to edit your /etc/syslog.conf file
+to direct the messages to the desired output device or file.
+.LP
+The \fIdebug\fR option causes the contents of all control packets sent
+or received to be logged, that is, all LCP, PAP, CHAP or IPCP packets.
+This can be useful if the PPP negotiation does not succeed or if
+authentication fails.
+If debugging is enabled at compile time, the \fIdebug\fR option also
+causes other debugging messages to be logged.
+.LP
+Debugging can also be enabled or disabled by sending a SIGUSR1 signal
+to the pppd process. This signal acts as a toggle.
+.SH EXIT STATUS
+The exit status of pppd is set to indicate whether any error was
+detected, or the reason for the link being terminated. The values
+used are:
+.TP
+.B 0
+Pppd has detached, or otherwise the connection was successfully
+established and terminated at the peer's request.
+.TP
+.B 1
+An immediately fatal error of some kind occurred, such as an essential
+system call failing, or running out of virtual memory.
+.TP
+.B 2
+An error was detected in processing the options given, such as two
+mutually exclusive options being used.
+.TP
+.B 3
+Pppd is not setuid-root and the invoking user is not root.
+.TP
+.B 4
+The kernel does not support PPP, for example, the PPP kernel driver is
+not included or cannot be loaded.
+.TP
+.B 5
+Pppd terminated because it was sent a SIGINT, SIGTERM or SIGHUP
+signal.
+.TP
+.B 6
+The serial port could not be locked.
+.TP
+.B 7
+The serial port could not be opened.
+.TP
+.B 8
+The connect script failed (returned a non-zero exit status).
+.TP
+.B 9
+The command specified as the argument to the \fIpty\fR option could
+not be run.
+.TP
+.B 10
+The PPP negotiation failed, that is, it didn't reach the point where
+at least one network protocol (e.g. IP) was running.
+.TP
+.B 11
+The peer system failed (or refused) to authenticate itself.
+.TP
+.B 12
+The link was established successfully and terminated because it was
+idle.
+.TP
+.B 13
+The link was established successfully and terminated because the
+connect time limit was reached.
+.TP
+.B 14
+Callback was negotiated and an incoming call should arrive shortly.
+.TP
+.B 15
+The link was terminated because the peer is not responding to echo
+requests.
+.TP
+.B 16
+The link was terminated by the modem hanging up.
+.TP
+.B 17
+The PPP negotiation failed because serial loopback was detected.
+.TP
+.B 18
+The init script failed (returned a non-zero exit status).
+.TP
+.B 19
+We failed to authenticate ourselves to the peer.
+.SH SCRIPTS
+Pppd invokes scripts at various stages in its processing which can be
+used to perform site-specific ancillary processing. These scripts are
+usually shell scripts, but could be executable code files instead.
+Pppd does not wait for the scripts to finish. The scripts are
+executed as root (with the real and effective user-id set to 0), so
+that they can do things such as update routing tables or run
+privileged daemons. Be careful that the contents of these scripts do
+not compromise your system's security. Pppd runs the scripts with
+standard input, output and error redirected to /dev/null, and with an
+environment that is empty except for some environment variables that
+give information about the link. The environment variables that pppd
+sets are:
+.TP
+.B DEVICE
+The name of the serial tty device being used.
+.TP
+.B IFNAME
+The name of the network interface being used.
+.TP
+.B IPLOCAL
+The IP address for the local end of the link. This is only set when
+IPCP has come up.
+.TP
+.B IPREMOTE
+The IP address for the remote end of the link. This is only set when
+IPCP has come up.
+.TP
+.B PEERNAME
+The authenticated name of the peer. This is only set if the peer
+authenticates itself.
+.TP
+.B SPEED
+The baud rate of the tty device.
+.TP
+.B ORIG_UID
+The real user-id of the user who invoked pppd.
+.TP
+.B PPPLOGNAME
+The username of the real user-id that invoked pppd. This is always set.
+.P
+For the ip-down and auth-down scripts, pppd also sets the following
+variables giving statistics for the connection:
+.TP
+.B CONNECT_TIME
+The number of seconds from when the PPP negotiation started until the
+connection was terminated.
+.TP
+.B BYTES_SENT
+The number of bytes sent (at the level of the serial port) during the
+connection.
+.TP
+.B BYTES_RCVD
+The number of bytes received (at the level of the serial port) during
+the connection.
+.TP
+.B LINKNAME
+The logical name of the link, set with the \fIlinkname\fR option.
+.P
+Pppd invokes the following scripts, if they exist. It is not an error
+if they don't exist.
+.TP
+.B /etc/ppp/auth-up
+A program or script which is executed after the remote system
+successfully authenticates itself. It is executed with the parameters
+.IP
+\fIinterface-name peer-name user-name tty-device speed\fR
+.IP
+Note that this script is not executed if the peer doesn't authenticate
+itself, for example when the \fInoauth\fR option is used.
+.TP
+.B /etc/ppp/auth-down
+A program or script which is executed when the link goes down, if
+/etc/ppp/auth-up was previously executed. It is executed in the same
+manner with the same parameters as /etc/ppp/auth-up.
+.TP
+.B /etc/ppp/ip-up
+A program or script which is executed when the link is available for
+sending and receiving IP packets (that is, IPCP has come up). It is
+executed with the parameters
+.IP
+\fIinterface-name tty-device speed local-IP-address
+remote-IP-address ipparam\fR
+.TP
+.B /etc/ppp/ip-down
+A program or script which is executed when the link is no longer
+available for sending and receiving IP packets. This script can be
+used for undoing the effects of the /etc/ppp/ip-up script. It is
+invoked in the same manner and with the same parameters as the ip-up
+script.
+.TP
+.B /etc/ppp/ipv6-up
+Like /etc/ppp/ip-up, except that it is executed when the link is available
+for sending and receiving IPv6 packets. It is executed with the parameters
+.IP
+\fIinterface-name tty-device speed local-link-local-address
+remote-link-local-address ipparam\fR
+.TP
+.B /etc/ppp/ipv6-down
+Similar to /etc/ppp/ip-down, but it is executed when IPv6 packets can no
+longer be transmitted on the link. It is executed with the same parameters
+as the ipv6-up script.
+.TP
+.B /etc/ppp/ipx-up
+A program or script which is executed when the link is available for
+sending and receiving IPX packets (that is, IPXCP has come up). It is
+executed with the parameters
+.IP
+\fIinterface-name tty-device speed network-number local-IPX-node-address
+remote-IPX-node-address local-IPX-routing-protocol remote-IPX-routing-protocol
+local-IPX-router-name remote-IPX-router-name ipparam pppd-pid\fR
+.IP
+The local-IPX-routing-protocol and remote-IPX-routing-protocol field
+may be one of the following:
+.IP
+NONE to indicate that there is no routing protocol
+.br
+RIP to indicate that RIP/SAP should be used
+.br
+NLSP to indicate that Novell NLSP should be used
+.br
+RIP NLSP to indicate that both RIP/SAP and NLSP should be used
+.TP
+.B /etc/ppp/ipx-down
+A program or script which is executed when the link is no longer
+available for sending and receiving IPX packets. This script can be
+used for undoing the effects of the /etc/ppp/ipx-up script. It is
+invoked in the same manner and with the same parameters as the ipx-up
+script.
+.SH FILES
+.TP
+.B /var/run/ppp\fIn\fB.pid \fR(BSD or Linux), \fB/etc/ppp/ppp\fIn\fB.pid \fR(others)
+Process-ID for pppd process on ppp interface unit \fIn\fR.
+.TP
+.B /var/run/ppp-\fIname\fB.pid \fR(BSD or Linux), \fB/etc/ppp/ppp-\fIname\fB.pid \fR(others)
+Process-ID for pppd process for logical link \fIname\fR (see the
+\fIlinkname\fR option).
+.TP
+.B /etc/ppp/pap-secrets
+Usernames, passwords and IP addresses for PAP authentication. This
+file should be owned by root and not readable or writable by any other
+user. Pppd will log a warning if this is not the case.
+.TP
+.B /etc/ppp/chap-secrets
+Names, secrets and IP addresses for CHAP authentication. As for
+/etc/ppp/pap-secrets, this file should be owned by root and not
+readable or writable by any other user. Pppd will log a warning if
+this is not the case.
+.TP
+.B /etc/ppp/options
+System default options for pppd, read before user default options or
+command-line options.
+.TP
+.B ~/.ppprc
+User default options, read before /etc/ppp/options.\fIttyname\fR.
+.TP
+.B /etc/ppp/options.\fIttyname
+System default options for the serial port being used, read after
+~/.ppprc. In forming the \fIttyname\fR part of this
+filename, an initial /dev/ is stripped from the port name (if
+present), and any slashes in the remaining part are converted to
+dots.
+.TP
+.B /etc/ppp/peers
+A directory containing options files which may contain privileged
+options, even if pppd was invoked by a user other than root. The
+system administrator can create options files in this directory to
+permit non-privileged users to dial out without requiring the peer to
+authenticate, but only to certain trusted peers.
+.SH SEE ALSO
+.TP
+.B RFC1144
+Jacobson, V.
+\fICompressing TCP/IP headers for low-speed serial links.\fR
+February 1990.
+.TP
+.B RFC1321
+Rivest, R.
+.I The MD5 Message-Digest Algorithm.
+April 1992.
+.TP
+.B RFC1332
+McGregor, G.
+.I PPP Internet Protocol Control Protocol (IPCP).
+May 1992.
+.TP
+.B RFC1334
+Lloyd, B.; Simpson, W.A.
+.I PPP authentication protocols.
+October 1992.
+.TP
+.B RFC1661
+Simpson, W.A.
+.I The Point\-to\-Point Protocol (PPP).
+July 1994.
+.TP
+.B RFC1662
+Simpson, W.A.
+.I PPP in HDLC-like Framing.
+July 1994.
+.TP
+.B RFC2472
+Haskin, D.
+.I IP Version 6 over PPP
+December 1998.
+.SH NOTES
+The following signals have the specified effect when sent to pppd.
+.TP
+.B SIGINT, SIGTERM
+These signals cause pppd to terminate the link (by closing LCP),
+restore the serial device settings, and exit.
+.TP
+.B SIGHUP
+This signal causes pppd to terminate the link, restore the serial
+device settings, and close the serial device. If the \fIpersist\fR or
+\fIdemand\fR option has been specified, pppd will try to reopen the
+serial device and start another connection (after the holdoff period).
+Otherwise pppd will exit. If this signal is received during the
+holdoff period, it causes pppd to end the holdoff period immediately.
+.TP
+.B SIGUSR1
+This signal toggles the state of the \fIdebug\fR option.
+.TP
+.B SIGUSR2
+This signal causes pppd to renegotiate compression. This can be
+useful to re-enable compression after it has been disabled as a result
+of a fatal decompression error. (Fatal decompression errors generally
+indicate a bug in one or other implementation.)
+
+.SH AUTHORS
+Paul Mackerras (Paul.Mackerras@cs.anu.edu.au), based on earlier work by
+Drew Perkins,
+Brad Clements,
+Karl Fox,
+Greg Christy,
+and
+Brad Parker.
diff --git a/cpukit/pppd/pppd.h b/cpukit/pppd/pppd.h
new file mode 100644
index 0000000000..0ecd2e1d23
--- /dev/null
+++ b/cpukit/pppd/pppd.h
@@ -0,0 +1,663 @@
+/*
+ * pppd.h - PPP daemon global declarations.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * $Id$
+ */
+
+#ifndef __PPPD_H__
+#define __PPPD_H__
+
+#include <stdio.h> /* for FILE */
+#include <limits.h> /* for NGROUPS_MAX */
+#include <sys/param.h> /* for MAXPATHLEN and BSD4_4, if defined */
+#include <sys/types.h> /* for u_int32_t, if defined */
+#include <sys/time.h> /* for struct timeval */
+#include <net/ppp_defs.h>
+#include "rtemsdialer.h"
+
+#if defined(__STDC__)
+#include <stdarg.h>
+#define __V(x) x
+#else
+#include <varargs.h>
+#define __V(x) (va_alist) va_dcl
+#define const
+#define volatile
+#endif
+
+#ifdef INET6
+#include "eui64.h"
+#endif
+
+/*
+ * Limits.
+ */
+
+#define NUM_PPP 1 /* One PPP interface supported (per process) */
+#define MAXWORDLEN 1024 /* max length of word in file (incl null) */
+#define MAXARGS 1 /* max # args to a command */
+#define MAXNAMELEN 256 /* max length of hostname or name for auth */
+#define MAXSECRETLEN 256 /* max length of password or secret */
+
+/*
+ * Option descriptor structure.
+ */
+
+typedef unsigned char bool;
+
+enum opt_type {
+ o_special_noarg = 0,
+ o_special = 1,
+ o_bool,
+ o_int,
+ o_uint32,
+ o_string,
+};
+
+typedef struct {
+ char *name; /* name of the option */
+ enum opt_type type;
+ void *addr;
+ char *description;
+ int flags;
+ void *addr2;
+ int upper_limit;
+ int lower_limit;
+} option_t;
+
+/* Values for flags */
+#define OPT_VALUE 0xff /* mask for presupplied value */
+#define OPT_HEX 0x100 /* int option is in hex */
+#define OPT_NOARG 0x200 /* option doesn't take argument */
+#define OPT_OR 0x400 /* OR in argument to value */
+#define OPT_INC 0x800 /* increment value */
+#define OPT_PRIV 0x1000 /* privileged option */
+#define OPT_STATIC 0x2000 /* string option goes into static array */
+#define OPT_LLIMIT 0x4000 /* check value against lower limit */
+#define OPT_ULIMIT 0x8000 /* check value against upper limit */
+#define OPT_LIMITS (OPT_LLIMIT|OPT_ULIMIT)
+#define OPT_ZEROOK 0x10000 /* 0 value is OK even if not within limits */
+#define OPT_NOINCR 0x20000 /* value mustn't be increased */
+#define OPT_ZEROINF 0x40000 /* with OPT_NOINCR, 0 == infinity */
+#define OPT_A2INFO 0x100000 /* addr2 -> option_info to update */
+#define OPT_A2COPY 0x200000 /* addr2 -> second location to rcv value */
+#define OPT_ENABLE 0x400000 /* use *addr2 as enable for option */
+#define OPT_PRIVFIX 0x800000 /* can't be overridden if noauth */
+#define OPT_PREPASS 0x1000000 /* do this opt in pre-pass to find device */
+#define OPT_INITONLY 0x2000000 /* option can only be set in init phase */
+#define OPT_DEVEQUIV 0x4000000 /* equiv to device name */
+#define OPT_DEVNAM (OPT_PREPASS | OPT_INITONLY | OPT_DEVEQUIV)
+
+#define OPT_VAL(x) ((x) & OPT_VALUE)
+
+#ifndef GIDSET_TYPE
+#define GIDSET_TYPE gid_t
+#endif
+
+/* Structure representing a list of permitted IP addresses. */
+struct permitted_ip {
+ int permit; /* 1 = permit, 0 = forbid */
+ u_int32_t base; /* match if (addr & mask) == base */
+ u_int32_t mask; /* base and mask are in network byte order */
+};
+
+/*
+ * Unfortunately, the linux kernel driver uses a different structure
+ * for statistics from the rest of the ports.
+ * This structure serves as a common representation for the bits
+ * pppd needs.
+ */
+struct pppd_stats {
+ unsigned int bytes_in;
+ unsigned int bytes_out;
+};
+
+/* Used for storing a sequence of words. Usually malloced. */
+struct wordlist {
+ struct wordlist *next;
+ char *word;
+};
+
+/*
+ * Global variables.
+ */
+
+extern int pppd_kill_link; /* Signal to terminate processing loop */
+extern int hungup; /* Physical layer has disconnected */
+extern int pppifunit; /* Interface unit number */
+extern char ifname[]; /* Interface name */
+extern int ttyfd; /* Serial device file descriptor */
+extern char hostname[]; /* Our hostname */
+extern u_char outpacket_buf[]; /* Buffer for outgoing packets */
+extern int pppd_phase; /* Current state of link - see values below */
+extern int baud_rate; /* Current link speed in bits/sec */
+extern int redirect_stderr;/* Connector's stderr should go to file */
+extern char peer_authname[];/* Authenticated name of peer */
+extern int privileged; /* We were run by real-uid root */
+extern int need_holdoff; /* Need holdoff period after link terminates */
+extern char **script_env; /* Environment variables for scripts */
+extern int detached; /* Have detached from controlling tty */
+extern GIDSET_TYPE groups[NGROUPS_MAX]; /* groups the user is in */
+extern int ngroups; /* How many groups valid in groups */
+extern struct pppd_stats link_stats; /* byte/packet counts etc. for link */
+extern int using_pty; /* using pty as device (notty or pty opt.) */
+extern int log_to_fd; /* logging to this fd as well as syslog */
+extern char *no_ppp_msg; /* message to print if ppp not in kernel */
+extern volatile int pppd_status; /* exit status for pppd */
+extern int devnam_fixed; /* can no longer change devnam */
+extern int unsuccess; /* # unsuccessful connection attempts */
+extern int do_callback; /* set if we want to do callback next */
+extern int doing_callback; /* set if this is a callback */
+extern dialerfp pppd_dialer; /* script dialer function callback */
+
+/* Values for do_callback and doing_callback */
+#define CALLBACK_DIALIN 1 /* we are expecting the call back */
+#define CALLBACK_DIALOUT 2 /* we are dialling out to call back */
+
+/*
+ * Variables set by command-line options.
+ */
+
+extern int debug; /* Debug flag */
+extern int kdebugflag; /* Tell kernel to print debug messages */
+extern int default_device; /* Using /dev/tty or equivalent */
+extern char devnam[MAXPATHLEN]; /* Device name */
+extern int crtscts; /* Use hardware flow control */
+extern bool modem; /* Use modem control lines */
+extern int inspeed; /* Input/Output speed requested */
+extern u_int32_t netmask; /* IP netmask to set on interface */
+extern bool lockflag; /* Create lock file to lock the serial dev */
+extern bool nodetach; /* Don't detach from controlling tty */
+extern bool updetach; /* Detach from controlling tty when link up */
+extern char *initializer; /* Script to initialize physical link */
+extern char *connect_script; /* Script to establish physical link */
+extern char *disconnect_script; /* Script to disestablish physical link */
+extern char *welcomer; /* Script to welcome client after connection */
+extern char *ptycommand; /* Command to run on other side of pty */
+extern int maxconnect; /* Maximum connect time (seconds) */
+extern char user[MAXNAMELEN];/* Our name for authenticating ourselves */
+extern char passwd[MAXSECRETLEN]; /* Password for PAP or CHAP */
+extern bool auth_required; /* Peer is required to authenticate */
+extern bool persist; /* Reopen link after it goes down */
+extern bool uselogin; /* Use /etc/passwd for checking PAP */
+extern char our_name[MAXNAMELEN];/* Our name for authentication purposes */
+extern char remote_name[MAXNAMELEN]; /* Peer's name for authentication */
+extern bool explicit_remote;/* remote_name specified with remotename opt */
+extern bool demand; /* Do dial-on-demand */
+extern char *ipparam; /* Extra parameter for ip up/down scripts */
+extern bool cryptpap; /* Others' PAP passwords are encrypted */
+extern int idle_time_limit;/* Shut down link if idle for this long */
+extern int holdoff; /* Dead time before restarting */
+extern bool holdoff_specified; /* true if user gave a holdoff value */
+extern bool notty; /* Stdin/out is not a tty */
+extern char *record_file; /* File to record chars sent/received */
+extern bool sync_serial; /* Device is synchronous serial device */
+extern int maxfail; /* Max # of unsuccessful connection attempts */
+extern char linkname[MAXPATHLEN]; /* logical name for link */
+extern bool tune_kernel; /* May alter kernel settings as necessary */
+extern int connect_delay; /* Time to delay after connect script */
+
+#ifdef PPP_FILTER
+extern struct bpf_program pass_filter; /* Filter for pkts to pass */
+extern struct bpf_program active_filter; /* Filter for link-active pkts */
+#endif
+
+#ifdef MSLANMAN
+extern bool ms_lanman; /* Use LanMan password instead of NT */
+ /* Has meaning only with MS-CHAP challenges */
+#endif
+
+extern char *current_option; /* the name of the option being parsed */
+extern int privileged_option; /* set iff the current option came from root */
+extern char *option_source; /* string saying where the option came from */
+
+/*
+ * Values for phase.
+ */
+#define PHASE_DEAD 0
+#define PHASE_INITIALIZE 1
+#define PHASE_SERIALCONN 2
+#define PHASE_DORMANT 3
+#define PHASE_ESTABLISH 4
+#define PHASE_AUTHENTICATE 5
+#define PHASE_CALLBACK 6
+#define PHASE_NETWORK 7
+#define PHASE_RUNNING 8
+#define PHASE_TERMINATE 9
+#define PHASE_DISCONNECT 10
+#define PHASE_HOLDOFF 11
+
+/*
+ * The following struct gives the addresses of procedures to call
+ * for a particular protocol.
+ */
+struct protent {
+ u_short protocol; /* PPP protocol number */
+ /* Initialization procedure */
+ void (*init) __P((int unit));
+ /* Process a received packet */
+ void (*input) __P((int unit, u_char *pkt, int len));
+ /* Process a received protocol-reject */
+ void (*protrej) __P((int unit));
+ /* Lower layer has come up */
+ void (*lowerup) __P((int unit));
+ /* Lower layer has gone down */
+ void (*lowerdown) __P((int unit));
+ /* Open the protocol */
+ void (*open) __P((int unit));
+ /* Close the protocol */
+ void (*close) __P((int unit, char *reason));
+ /* Print a packet in readable form */
+ int (*printpkt) __P((u_char *pkt, int len,
+ void (*printer) __P((void *, char *, ...)),
+ void *arg));
+ /* Process a received data packet */
+ void (*datainput) __P((int unit, u_char *pkt, int len));
+ bool enabled_flag; /* 0 iff protocol is disabled */
+ char *name; /* Text name of protocol */
+ char *data_name; /* Text name of corresponding data protocol */
+ option_t *options; /* List of command-line options */
+ /* Check requested options, assign defaults */
+ void (*check_options) __P((void));
+ /* Configure interface for demand-dial */
+ int (*demand_conf) __P((int unit));
+ /* Say whether to bring up link for this pkt */
+ int (*active_pkt) __P((u_char *pkt, int len));
+};
+
+/* Table of pointers to supported protocols */
+extern struct protent *protocols[];
+
+/*
+ * Prototypes.
+ */
+
+/* Procedures exported from main.c. */
+void die __P((int)); /* Cleanup and exit */
+void quit __P((void)); /* like die(1) */
+void novm __P((char *)); /* Say we ran out of memory, and die */
+void ppptimeout __P((void (*func)(void *), void *arg, int t));
+ /* Call func(arg) after t seconds */
+void untimeout __P((void (*func)(void *), void *arg));
+ /* Cancel call to func(arg) */
+void update_link_stats __P((int)); /* Get stats at link termination */
+void new_phase __P((int)); /* signal start of new phase */
+
+/* Procedures exported from utils.c. */
+void log_packet __P((u_char *, int, char *, int));
+ /* Format a packet and log it with syslog */
+void print_string __P((char *, int, void (*) (void *, char *, ...),
+ void *)); /* Format a string for output */
+int slprintf __P((char *, int, char *, ...)); /* sprintf++ */
+int vslprintf __P((char *, int, char *, va_list)); /* vsprintf++ */
+size_t strlcpy __P((char *, const char *, size_t)); /* safe strcpy */
+size_t strlcat __P((char *, const char *, size_t)); /* safe strncpy */
+void pppd_dbglog __P((char *, ...)); /* log a debug message */
+void pppd_info __P((char *, ...)); /* log an informational message */
+void pppd_notice __P((char *, ...)); /* log a notice-level message */
+void pppd_warn __P((char *, ...)); /* log a warning message */
+void pppd_error __P((char *, ...)); /* log an error message */
+void pppd_fatal __P((char *, ...)); /* log an error message and die(1) */
+
+#define dbglog pppd_dbglog
+#define info pppd_info
+#define notice pppd_notice
+#define warn pppd_warn
+#define error pppd_error
+#define fatal pppd_fatal
+
+/* Procedures exported from auth.c */
+void link_required __P((int)); /* we are starting to use the link */
+void link_terminated __P((int)); /* we are finished with the link */
+void link_down __P((int)); /* the LCP layer has left the Opened state */
+void link_established __P((int)); /* the link is up; authenticate now */
+void start_networks __P((void)); /* start all the network control protos */
+void np_up __P((int, int)); /* a network protocol has come up */
+void np_down __P((int, int)); /* a network protocol has gone down */
+void np_finished __P((int, int)); /* a network protocol no longer needs link */
+void auth_peer_fail __P((int, int));
+ /* peer failed to authenticate itself */
+void auth_peer_success __P((int, int, char *, int));
+ /* peer successfully authenticated itself */
+void auth_withpeer_fail __P((int, int));
+ /* we failed to authenticate ourselves */
+void auth_withpeer_success __P((int, int));
+ /* we successfully authenticated ourselves */
+int auth_check_options __P((void));
+ /* check authentication options supplied */
+void auth_reset __P((int)); /* check what secrets we have */
+int check_passwd __P((int, char *, int, char *, int, char **));
+ /* Check peer-supplied username/password */
+int get_secret __P((int, char *, char *, char *, int *, int));
+ /* get "secret" for chap */
+int auth_ip_addr __P((int, u_int32_t));
+ /* check if IP address is authorized */
+int bad_ip_adrs __P((u_int32_t));
+ /* check if IP address is unreasonable */
+
+/* Procedures exported from demand.c */
+void demand_conf __P((void)); /* config interface(s) for demand-dial */
+void demand_block __P((void)); /* set all NPs to queue up packets */
+void demand_unblock __P((void)); /* set all NPs to pass packets */
+void demand_discard __P((void)); /* set all NPs to discard packets */
+void demand_rexmit __P((int)); /* retransmit saved frames for an NP */
+int loop_chars __P((unsigned char *, int)); /* process chars from loopback */
+int loop_frame __P((unsigned char *, int)); /* should we bring link up? */
+
+/* Procedures exported from sys-*.c */
+void sys_init __P((void)); /* Do system-dependent initialization */
+void sys_cleanup __P((void)); /* Restore system state before exiting */
+int sys_check_options __P((void)); /* Check options specified */
+void sys_close __P((void)); /* Clean up in a child before execing */
+int ppp_available __P((void)); /* Test whether ppp kernel support exists */
+int get_pty __P((int *, int *, char *, int)); /* Get pty master/slave */
+int open_ppp_loopback __P((void)); /* Open loopback for demand-dialling */
+int establish_ppp __P((int)); /* Turn serial port into a ppp interface */
+void restore_loop __P((void)); /* Transfer ppp unit back to loopback */
+void disestablish_ppp __P((int)); /* Restore port to normal operation */
+void clean_check __P((void)); /* Check if line was 8-bit clean */
+void set_up_tty __P((int, int)); /* Set up port's speed, parameters, etc. */
+void restore_tty __P((int)); /* Restore port's original parameters */
+void setdtr __P((int, int)); /* Raise or lower port's DTR line */
+void output __P((int, u_char *, int)); /* Output a PPP packet */
+void wait_input __P((struct timeval *)); /* Wait for input, with timeout */
+
+void ppp_delay __P((void)); /* delay task for a little while */
+int read_packet __P((u_char *)); /* Read PPP packet */
+int get_loop_output __P((void)); /* Read pkts from loopback */
+void ppp_send_config __P((int, int, u_int32_t, int, int));
+ /* Configure i/f transmit parameters */
+void ppp_set_xaccm __P((int, ext_accm));
+ /* Set extended transmit ACCM */
+void ppp_recv_config __P((int, int, u_int32_t, int, int));
+ /* Configure i/f receive parameters */
+int ccp_test __P((int, u_char *, int, int));
+ /* Test support for compression scheme */
+void ccp_flags_set __P((int, int, int));
+ /* Set kernel CCP state */
+int ccp_fatal_error __P((int)); /* Test for fatal decomp error in kernel */
+int get_idle_time __P((int, struct ppp_idle *));
+ /* Find out how long link has been idle */
+int get_ppp_stats __P((int, struct pppd_stats *));
+ /* Return link statistics */
+int sifvjcomp __P((int, int, int, int));
+ /* Configure VJ TCP header compression */
+int sifup __P((int)); /* Configure i/f up for one protocol */
+int sifnpmode __P((int u, int proto, enum NPmode mode));
+ /* Set mode for handling packets for proto */
+int sifdown __P((int)); /* Configure i/f down for one protocol */
+int sifaddr __P((int, u_int32_t, u_int32_t, u_int32_t));
+ /* Configure IPv4 addresses for i/f */
+int cifaddr __P((int, u_int32_t, u_int32_t));
+ /* Reset i/f IP addresses */
+#ifdef INET6
+int sif6addr __P((int, eui64_t, eui64_t));
+ /* Configure IPv6 addresses for i/f */
+int cif6addr __P((int, eui64_t, eui64_t));
+ /* Remove an IPv6 address from i/f */
+#endif
+int sifdefaultroute __P((int, u_int32_t, u_int32_t));
+ /* Create default route through i/f */
+int cifdefaultroute __P((int, u_int32_t, u_int32_t));
+ /* Delete default route through i/f */
+int sifproxyarp __P((int, u_int32_t));
+ /* Add proxy ARP entry for peer */
+int cifproxyarp __P((int, u_int32_t));
+ /* Delete proxy ARP entry for peer */
+u_int32_t GetMask __P((u_int32_t)); /* Get appropriate netmask for address */
+int lock __P((char *)); /* Create lock file for device */
+int relock __P((int)); /* Rewrite lock file with new pid */
+void unlock __P((void)); /* Delete previously-created lock file */
+void logwtmp __P((const char *, const char *, const char *));
+ /* Write entry to wtmp file */
+int get_host_seed __P((void)); /* Get host-dependent random number seed */
+int have_route_to __P((u_int32_t)); /* Check if route to addr exists */
+#ifdef PPP_FILTER
+int set_filters __P((struct bpf_program *pass, struct bpf_program *active));
+ /* Set filter programs in kernel */
+#endif
+#ifdef IPX_CHANGE
+int sipxfaddr __P((int, unsigned long, unsigned char *));
+int cipxfaddr __P((int));
+#endif
+
+/* Procedures exported from options.c */
+int parse_args __P((int argc, char **argv));
+ /* Parse options from arguments given */
+int options_from_file __P((char *filename, int must_exist, int check_prot,
+ int privileged));
+ /* Parse options from an options file */
+int options_from_user __P((void)); /* Parse options from user's .ppprc */
+int options_for_tty __P((void)); /* Parse options from /etc/ppp/options.tty */
+int options_from_list __P((struct wordlist *, int privileged));
+ /* Parse options from a wordlist */
+int getword __P((FILE *f, char *word, int *newlinep, char *filename));
+ /* Read a word from a file */
+void option_error __P((char *fmt, ...));
+ /* Print an error message about an option */
+int int_option __P((char *, int *));
+ /* Simplified number_option for decimal ints */
+void add_options __P((option_t *)); /* Add extra options */
+
+/*
+ * This structure is used to store information about certain
+ * options, such as where the option value came from (/etc/ppp/options,
+ * command line, etc.) and whether it came from a privileged source.
+ */
+
+struct option_info {
+ int priv; /* was value set by sysadmin? */
+ char *source; /* where option came from */
+};
+
+extern struct option_info devnam_info;
+extern struct option_info initializer_info;
+extern struct option_info connect_script_info;
+extern struct option_info disconnect_script_info;
+extern struct option_info welcomer_info;
+extern struct option_info ptycommand_info;
+
+/*
+ * Hooks to enable plugins to change various things.
+ */
+extern int (*new_phase_hook) __P((int));
+extern int (*idle_time_hook) __P((struct ppp_idle *));
+extern int (*holdoff_hook) __P((void));
+extern int (*pap_check_hook) __P((void));
+extern int (*pap_auth_hook) __P((char *user, char *passwd/*, char **msgp,
+ struct wordlist **paddrs,
+ struct wordlist **popts*/));
+extern void (*pap_logout_hook) __P((void));
+extern int (*pap_passwd_hook) __P((char *user, char *passwd));
+extern void (*ip_up_hook) __P((void));
+extern void (*ip_down_hook) __P((void));
+extern void (*auth_linkup_hook) __P((void));
+extern void (*auth_linkdown_hook) __P((void));
+
+/*
+ * Inline versions of get/put char/short/long.
+ * Pointer is advanced; we assume that both arguments
+ * are lvalues and will already be in registers.
+ * cp MUST be u_char *.
+ */
+#define GETCHAR(c, cp) { \
+ (c) = *(cp)++; \
+}
+#define PUTCHAR(c, cp) { \
+ *(cp)++ = (u_char) (c); \
+}
+
+
+#define GETSHORT(s, cp) { \
+ (s) = *(cp)++ << 8; \
+ (s) |= *(cp)++; \
+}
+#define PUTSHORT(s, cp) { \
+ *(cp)++ = (u_char) ((s) >> 8); \
+ *(cp)++ = (u_char) (s); \
+}
+
+#define GETLONG(l, cp) { \
+ (l) = *(cp)++ << 8; \
+ (l) |= *(cp)++; (l) <<= 8; \
+ (l) |= *(cp)++; (l) <<= 8; \
+ (l) |= *(cp)++; \
+}
+#define PUTLONG(l, cp) { \
+ *(cp)++ = (u_char) ((l) >> 24); \
+ *(cp)++ = (u_char) ((l) >> 16); \
+ *(cp)++ = (u_char) ((l) >> 8); \
+ *(cp)++ = (u_char) (l); \
+}
+
+#define INCPTR(n, cp) ((cp) += (n))
+#define DECPTR(n, cp) ((cp) -= (n))
+
+/*
+ * System dependent definitions for user-level 4.3BSD UNIX implementation.
+ */
+
+#define TIMEOUT(r, f, t) ppptimeout((r), (f), (t))
+#define UNTIMEOUT(r, f) untimeout((r), (f))
+
+#define BCOPY(s, d, l) memcpy(d, s, l)
+#define BZERO(s, n) memset(s, 0, n)
+
+#define PRINTMSG(m, l) { info("Remote message: %0.*v", l, m); }
+
+/*
+ * MAKEHEADER - Add Header fields to a packet.
+ */
+#define MAKEHEADER(p, t) { \
+ PUTCHAR(PPP_ALLSTATIONS, p); \
+ PUTCHAR(PPP_UI, p); \
+ PUTSHORT(t, p); }
+
+/*
+ * Exit status values.
+ */
+#define EXIT_OK 0
+#define EXIT_FATAL_ERROR 1
+#define EXIT_OPTION_ERROR 2
+#define EXIT_NOT_ROOT 3
+#define EXIT_NO_KERNEL_SUPPORT 4
+#define EXIT_USER_REQUEST 5
+#define EXIT_LOCK_FAILED 6
+#define EXIT_OPEN_FAILED 7
+#define EXIT_CONNECT_FAILED 8
+#define EXIT_PTYCMD_FAILED 9
+#define EXIT_NEGOTIATION_FAILED 10
+#define EXIT_PEER_AUTH_FAILED 11
+#define EXIT_IDLE_TIMEOUT 12
+#define EXIT_CONNECT_TIME 13
+#define EXIT_CALLBACK 14
+#define EXIT_PEER_DEAD 15
+#define EXIT_HANGUP 16
+#define EXIT_LOOPBACK 17
+#define EXIT_INIT_FAILED 18
+#define EXIT_AUTH_TOPEER_FAILED 19
+
+/*
+ * Debug macros. Slightly useful for finding bugs in pppd, not particularly
+ * useful for finding out why your connection isn't being established.
+ */
+
+#ifdef DEBUGALL
+#define DEBUGMAIN 1
+#define DEBUGFSM 1
+#define DEBUGLCP 1
+#define DEBUGIPCP 1
+#define DEBUGIPV6CP 1
+#define DEBUGUPAP 1
+#define DEBUGCHAP 1
+#endif
+#define DEBUGMAIN 1
+#define DEBUGUPAP 1
+#define DEBUGCHAP 1
+
+
+#ifdef DEBUGMAIN
+#define MAINDEBUG(x) if (debug) dbglog x
+#else
+#define MAINDEBUG(x)
+#endif
+
+#ifdef DEBUGSYS
+#define SYSDEBUG(x) if (debug) dbglog x
+#else
+#define SYSDEBUG(x)
+#endif
+
+#ifdef DEBUGFSM
+#define FSMDEBUG(x) if (debug) dbglog x
+#else
+#define FSMDEBUG(x)
+#endif
+
+#ifdef DEBUGLCP
+#define LCPDEBUG(x) if (debug) dbglog x
+#else
+#define LCPDEBUG(x)
+#endif
+
+#ifdef DEBUGIPCP
+#define IPCPDEBUG(x) if (debug) dbglog x
+#else
+#define IPCPDEBUG(x)
+#endif
+
+#ifdef DEBUGIPV6CP
+#define IPV6CPDEBUG(x) if (debug) dbglog x
+#else
+#define IPV6CPDEBUG(x)
+#endif
+
+#ifdef DEBUGUPAP
+#define UPAPDEBUG(x) if (debug) dbglog x
+#else
+#define UPAPDEBUG(x)
+#endif
+
+#ifdef DEBUGCHAP
+#define CHAPDEBUG(x) if (debug) dbglog x
+#else
+#define CHAPDEBUG(x)
+#endif
+
+#ifdef DEBUGIPXCP
+#define IPXCPDEBUG(x) if (debug) dbglog x
+#else
+#define IPXCPDEBUG(x)
+#endif
+
+#ifndef SIGTYPE
+#if defined(sun) || defined(SYSV) || defined(POSIX_SOURCE)
+#define SIGTYPE void
+#else
+#define SIGTYPE int
+#endif /* defined(sun) || defined(SYSV) || defined(POSIX_SOURCE) */
+#endif /* SIGTYPE */
+
+#ifndef MIN
+#define MIN(a, b) ((a) < (b)? (a): (b))
+#endif
+#ifndef MAX
+#define MAX(a, b) ((a) > (b)? (a): (b))
+#endif
+
+#endif /* __PPP_H__ */
diff --git a/cpukit/pppd/rtemsdialer.h b/cpukit/pppd/rtemsdialer.h
new file mode 100644
index 0000000000..611986b802
--- /dev/null
+++ b/cpukit/pppd/rtemsdialer.h
@@ -0,0 +1,24 @@
+
+#ifndef DIALER_H
+#define DIALER_H
+
+/* define constant mode values */
+#define DIALER_INIT 0
+#define DIALER_CONNECT 1
+#define DIALER_WELCOME 2
+#define DIALER_DISCONNECT 3
+
+/* define constant return values */
+#define DIALER_SUCCESS 0
+#define DIALER_INVALIDARG 1
+#define DIALER_UNEXPECTED 2
+#define DIALER_TIMEOUT 3
+#define DIALER_CMDFAILED 4
+
+/* define typedef for dialer function prototype */
+typedef int (*dialerfp)(int tty, int mode, char *pScript);
+
+/* declare default chat program dialer */
+extern int chatmain(int tty, int mode, char *pScript);
+
+#endif
diff --git a/cpukit/pppd/rtemsmain.c b/cpukit/pppd/rtemsmain.c
new file mode 100644
index 0000000000..2c0832b94f
--- /dev/null
+++ b/cpukit/pppd/rtemsmain.c
@@ -0,0 +1,896 @@
+/*
+ * main.c - Point-to-Point Protocol main module
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#define RCSID "$Id$"
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <setjmp.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <rtems.h>
+#include <rtems/rtems_bsdnet.h>
+
+#include "pppd.h"
+#include "magic.h"
+#include "fsm.h"
+#include "lcp.h"
+#include "ipcp.h"
+#ifdef INET6
+#include "ipv6cp.h"
+#endif
+#include "upap.h"
+#include "chap.h"
+#include "ccp.h"
+#include "pathnames.h"
+#include "patchlevel.h"
+#include "rtemsdialer.h"
+
+#ifdef CBCP_SUPPORT
+#include "cbcp.h"
+#endif
+
+#ifdef IPX_CHANGE
+#include "ipxcp.h"
+#endif /* IPX_CHANGE */
+#ifdef AT_CHANGE
+#include "atcp.h"
+#endif
+
+static const char rcsid[] = RCSID;
+
+/* interface vars */
+char ifname[32]; /* Interface name */
+int pppifunit; /* Interface unit number */
+
+char hostname[MAXNAMELEN]; /* Our hostname */
+static char ppp_devnam[MAXPATHLEN]; /* name of PPP tty (maybe ttypx) */
+
+int ttyfd; /* Serial port file descriptor */
+int baud_rate; /* Actual bits/second for serial device */
+int hungup; /* terminal has been hung up */
+int privileged; /* we're running as real uid root */
+int need_holdoff; /* need holdoff period before restarting */
+int detached; /* have detached from terminal */
+struct stat devstat; /* result of stat() on devnam */
+int prepass = 0; /* doing prepass to find device name */
+int devnam_fixed; /* set while in options.ttyxx file */
+volatile int pppd_status; /* exit status for pppd */
+int unsuccess; /* # unsuccessful connection attempts */
+int do_callback; /* != 0 if we should do callback next */
+int doing_callback; /* != 0 if we are doing callback */
+char *callback_script; /* script for doing callback */
+dialerfp pppd_dialer;
+
+int (*holdoff_hook) __P((void)) = NULL;
+int (*new_phase_hook) __P((int)) = NULL;
+
+static int fd_ppp = -1; /* fd for talking PPP */
+static int pty_master; /* fd for master side of pty */
+static int pty_slave; /* fd for slave side of pty */
+static int real_ttyfd; /* fd for actual serial port (not pty) */
+
+int pppd_phase; /* where the link is at */
+int pppd_kill_link;
+int open_ccp_flag;
+
+char **script_env; /* Env. variable values for scripts */
+int s_env_nalloc; /* # words avail at script_env */
+
+u_char outpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for outgoing packet */
+u_char inpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for incoming packet */
+
+char *no_ppp_msg = "Sorry - this system lacks PPP kernel support\n";
+
+static struct timeval start_time; /* Time when link was started. */
+
+struct pppd_stats link_stats;
+int link_connect_time;
+int link_stats_valid;
+
+/* Prototypes for procedures local to this file. */
+
+static void cleanup __P((void));
+static void close_tty __P((void));
+static void get_input __P((void));
+static void calltimeout __P((void));
+static struct timeval *timeleft __P((struct timeval *));
+static void holdoff_end __P((void *));
+static int device_script __P((int, int, char *));
+
+extern char *ttyname __P((int));
+extern char *getlogin __P((void));
+int pppdmain __P((int, char *[]));
+
+/*
+ * PPP Data Link Layer "protocol" table.
+ * One entry per supported protocol.
+ * The last entry must be NULL.
+ */
+struct protent *protocols[] = {
+ &lcp_protent,
+ &pap_protent,
+ &chap_protent,
+#ifdef CBCP_SUPPORT
+ &cbcp_protent,
+#endif
+ &ipcp_protent,
+#ifdef INET6
+ &ipv6cp_protent,
+#endif
+ &ccp_protent,
+#ifdef IPX_CHANGE
+ &ipxcp_protent,
+#endif
+#ifdef AT_CHANGE
+ &atcp_protent,
+#endif
+ NULL
+};
+
+int
+pppdmain(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int i, fdflags, t;
+ char *connector;
+ struct timeval timo;
+ struct protent *protp;
+
+ new_phase(PHASE_INITIALIZE);
+
+ script_env = NULL;
+ hostname[MAXNAMELEN-1] = 0;
+ privileged = 1;
+ privileged_option = 1;
+
+ /*
+ * Initialize magic number generator now so that protocols may
+ * use magic numbers in initialization.
+ */
+ magic_init();
+
+#ifdef XXX_XXX
+ /* moved code the the rtems_pppd_reset_options function */
+
+ /*
+ * Initialize to the standard option set, then parse, in order,
+ * the system options file, the user's options file,
+ * the tty's options file, and the command line arguments.
+ */
+ for (i = 0; (protp = protocols[i]) != NULL; ++i)
+ (*protp->init)(0);
+#endif
+
+
+ if (!ppp_available()) {
+ option_error(no_ppp_msg);
+ return(EXIT_NO_KERNEL_SUPPORT);
+ }
+
+ /*
+ * Check that the options given are valid and consistent.
+ */
+ if (!sys_check_options()) {
+ return(EXIT_OPTION_ERROR);
+ }
+ if (!auth_check_options()) {
+ return(EXIT_OPTION_ERROR);
+ }
+ for (i = 0; (protp = protocols[i]) != NULL; ++i)
+ if (protp->check_options != NULL)
+ (*protp->check_options)();
+
+ /* default holdoff to 0 if no connect script has been given */
+ if (connect_script == 0 && !holdoff_specified)
+ holdoff = 0;
+
+ if (default_device)
+ nodetach = 1;
+
+ /*
+ * Initialize system-dependent stuff.
+ */
+ sys_init();
+ /* if (debug)
+ setlogmask(LOG_UPTO(LOG_DEBUG));
+ */
+
+ do_callback = 0;
+ for (;;) {
+
+ need_holdoff = 1;
+ ttyfd = -1;
+ real_ttyfd = -1;
+ pppd_status = EXIT_OK;
+ ++unsuccess;
+ doing_callback = do_callback;
+ do_callback = 0;
+
+ new_phase(PHASE_SERIALCONN);
+
+ /*
+ * Get a pty master/slave pair if the pty, notty, or record
+ * options were specified.
+ */
+ strlcpy(ppp_devnam, devnam, sizeof(ppp_devnam));
+ pty_master = -1;
+ pty_slave = -1;
+
+ /*
+ * Open the serial device and set it up to be the ppp interface.
+ * First we open it in non-blocking mode so we can set the
+ * various termios flags appropriately. If we aren't dialling
+ * out and we want to use the modem lines, we reopen it later
+ * in order to wait for the carrier detect signal from the modem.
+ */
+ hungup = 0;
+ pppd_kill_link = 0;
+ connector = doing_callback? callback_script: connect_script;
+ if (devnam[0] != 0) {
+ for (;;) {
+ /* If the user specified the device name, become the
+ user before opening it. */
+ int err;
+ ttyfd = open(devnam, O_NONBLOCK | O_RDWR, 0);
+ err = errno;
+ if (ttyfd >= 0) {
+ break;
+ }
+ errno = err;
+ if (err != EINTR) {
+ error("Failed to open %s: %m", devnam);
+ pppd_status = EXIT_OPEN_FAILED;
+ }
+ if (!persist || err != EINTR)
+ goto fail;
+ }
+ if ((fdflags = fcntl(ttyfd, F_GETFL)) == -1
+ || fcntl(ttyfd, F_SETFL, fdflags & ~O_NONBLOCK) < 0)
+ warn("Couldn't reset non-blocking mode on device: %m");
+
+ /*
+ * Set line speed, flow control, etc.
+ * If we have a non-null connection or initializer script,
+ * on most systems we set CLOCAL for now so that we can talk
+ * to the modem before carrier comes up. But this has the
+ * side effect that we might miss it if CD drops before we
+ * get to clear CLOCAL below. On systems where we can talk
+ * successfully to the modem with CLOCAL clear and CD down,
+ * we could clear CLOCAL at this point.
+ */
+ set_up_tty(ttyfd, ((connector != NULL && connector[0] != 0)
+ || initializer != NULL));
+ real_ttyfd = ttyfd;
+ }
+
+ /* run connection script */
+ if ((connector && connector[0]) || initializer) {
+ if (real_ttyfd != -1) {
+ /* XXX do this if doing_callback == CALLBACK_DIALIN? */
+ if (!default_device && modem) {
+ setdtr(real_ttyfd, 0); /* in case modem is off hook */
+ sleep(1);
+ setdtr(real_ttyfd, 1);
+ }
+ }
+
+ if (initializer && initializer[0]) {
+ if (device_script(ttyfd, DIALER_INIT, initializer) < 0) {
+ error("Initializer script failed");
+ pppd_status = EXIT_INIT_FAILED;
+ goto fail;
+ }
+ if (pppd_kill_link)
+ goto disconnect;
+
+ info("Serial port initialized.");
+ }
+
+ if (connector && connector[0]) {
+ if (device_script(ttyfd, DIALER_CONNECT, connector) < 0) {
+ error("Connect script failed");
+ pppd_status = EXIT_CONNECT_FAILED;
+ goto fail;
+ }
+ if (pppd_kill_link)
+ goto disconnect;
+
+ info("Serial connection established.");
+ }
+
+ /* set line speed, flow control, etc.;
+ clear CLOCAL if modem option */
+ if (real_ttyfd != -1)
+ set_up_tty(real_ttyfd, 0);
+
+ if (doing_callback == CALLBACK_DIALIN)
+ connector = NULL;
+ }
+
+ /* reopen tty if necessary to wait for carrier */
+ if (connector == NULL && modem && devnam[0] != 0) {
+ for (;;) {
+ if ((i = open(devnam, O_RDWR)) >= 0)
+ break;
+ if (errno != EINTR) {
+ error("Failed to reopen %s: %m", devnam);
+ pppd_status = EXIT_OPEN_FAILED;
+ }
+ if (!persist || errno != EINTR || hungup || pppd_kill_link)
+ goto fail;
+ }
+ close(i);
+ }
+
+ info("Serial connection established.");
+ sleep(1);
+
+ /* run welcome script, if any */
+ if (welcomer && welcomer[0]) {
+ if (device_script(ttyfd, DIALER_WELCOME, welcomer) < 0)
+ warn("Welcome script failed");
+ }
+
+ /* set up the serial device as a ppp interface */
+ fd_ppp = establish_ppp(ttyfd);
+ if (fd_ppp < 0) {
+ pppd_status = EXIT_FATAL_ERROR;
+ goto disconnect;
+ }
+
+ if (!demand) {
+ info("Using interface ppp%d", pppifunit);
+ slprintf(ifname, sizeof(ifname), "ppp%d", pppifunit);
+ }
+
+ /*
+ * Start opening the connection and wait for
+ * incoming events (reply, timeout, etc.).
+ */
+ notice("Connect: %s <--> %s", ifname, ppp_devnam);
+ gettimeofday(&start_time, NULL);
+
+ lcp_lowerup(0);
+ lcp_open(0); /* Start protocol */
+
+ open_ccp_flag = 0;
+ pppd_status = EXIT_NEGOTIATION_FAILED;
+ new_phase(PHASE_ESTABLISH);
+ while (pppd_phase != PHASE_DEAD) {
+ wait_input(timeleft(&timo));
+ calltimeout();
+ get_input();
+
+ if (pppd_kill_link) {
+ lcp_close(0, "User request");
+ pppd_kill_link = 0;
+ }
+ if (open_ccp_flag) {
+ if (pppd_phase == PHASE_NETWORK || pppd_phase == PHASE_RUNNING) {
+ ccp_fsm[0].flags = OPT_RESTART; /* clears OPT_SILENT */
+ (*ccp_protent.open)(0);
+ }
+ open_ccp_flag = 0;
+ }
+ }
+
+ /*
+ * If we may want to bring the link up again, transfer
+ * the ppp unit back to the loopback. Set the
+ * real serial device back to its normal mode of operation.
+ */
+ clean_check();
+ if (demand)
+ restore_loop();
+ disestablish_ppp(ttyfd);
+ fd_ppp = -1;
+ if (!hungup)
+ lcp_lowerdown(0);
+
+ /*
+ * Run disconnector script, if requested.
+ * XXX we may not be able to do this if the line has hung up!
+ */
+ disconnect:
+ if (disconnect_script && !hungup) {
+ new_phase(PHASE_DISCONNECT);
+ if (real_ttyfd >= 0)
+ set_up_tty(real_ttyfd, 1);
+ if (device_script(ttyfd, DIALER_DISCONNECT, disconnect_script) < 0) {
+ warn("disconnect script failed");
+ } else {
+ info("Serial link disconnected.");
+ }
+ }
+
+ fail:
+ if (pty_master >= 0)
+ close(pty_master);
+ if (pty_slave >= 0)
+ close(pty_slave);
+ if (real_ttyfd >= 0)
+ close_tty();
+
+ if (!persist || (maxfail > 0 && unsuccess >= maxfail))
+ break;
+
+ pppd_kill_link = 0;
+ if (demand)
+ demand_discard();
+ t = need_holdoff? holdoff: 0;
+ if (holdoff_hook)
+ t = (*holdoff_hook)();
+ if (t > 0) {
+ new_phase(PHASE_HOLDOFF);
+ TIMEOUT(holdoff_end, NULL, t);
+ do {
+ wait_input(timeleft(&timo));
+
+ calltimeout();
+ if (pppd_kill_link) {
+ pppd_kill_link = 0;
+ new_phase(PHASE_DORMANT); /* allow signal to end holdoff */
+ }
+ } while (pppd_phase == PHASE_HOLDOFF);
+ if (!persist)
+ break;
+ }
+ }
+
+ die(pppd_status);
+ return pppd_status;
+}
+
+/*
+ * holdoff_end - called via a timeout when the holdoff period ends.
+ */
+static void
+holdoff_end(arg)
+ void *arg;
+{
+ new_phase(PHASE_DORMANT);
+}
+
+/* List of protocol names, to make our messages a little more informative. */
+struct protocol_list {
+ u_short proto;
+ const char *name;
+} protocol_list[] = {
+ { 0x21, "IP" },
+ { 0x23, "OSI Network Layer" },
+ { 0x25, "Xerox NS IDP" },
+ { 0x27, "DECnet Phase IV" },
+ { 0x29, "Appletalk" },
+ { 0x2b, "Novell IPX" },
+ { 0x2d, "VJ compressed TCP/IP" },
+ { 0x2f, "VJ uncompressed TCP/IP" },
+ { 0x31, "Bridging PDU" },
+ { 0x33, "Stream Protocol ST-II" },
+ { 0x35, "Banyan Vines" },
+ { 0x39, "AppleTalk EDDP" },
+ { 0x3b, "AppleTalk SmartBuffered" },
+ { 0x3d, "Multi-Link" },
+ { 0x3f, "NETBIOS Framing" },
+ { 0x41, "Cisco Systems" },
+ { 0x43, "Ascom Timeplex" },
+ { 0x45, "Fujitsu Link Backup and Load Balancing (LBLB)" },
+ { 0x47, "DCA Remote Lan" },
+ { 0x49, "Serial Data Transport Protocol (PPP-SDTP)" },
+ { 0x4b, "SNA over 802.2" },
+ { 0x4d, "SNA" },
+ { 0x4f, "IP6 Header Compression" },
+ { 0x6f, "Stampede Bridging" },
+ { 0xfb, "single-link compression" },
+ { 0xfd, "1st choice compression" },
+ { 0x0201, "802.1d Hello Packets" },
+ { 0x0203, "IBM Source Routing BPDU" },
+ { 0x0205, "DEC LANBridge100 Spanning Tree" },
+ { 0x0231, "Luxcom" },
+ { 0x0233, "Sigma Network Systems" },
+ { 0x8021, "Internet Protocol Control Protocol" },
+ { 0x8023, "OSI Network Layer Control Protocol" },
+ { 0x8025, "Xerox NS IDP Control Protocol" },
+ { 0x8027, "DECnet Phase IV Control Protocol" },
+ { 0x8029, "Appletalk Control Protocol" },
+ { 0x802b, "Novell IPX Control Protocol" },
+ { 0x8031, "Bridging NCP" },
+ { 0x8033, "Stream Protocol Control Protocol" },
+ { 0x8035, "Banyan Vines Control Protocol" },
+ { 0x803d, "Multi-Link Control Protocol" },
+ { 0x803f, "NETBIOS Framing Control Protocol" },
+ { 0x8041, "Cisco Systems Control Protocol" },
+ { 0x8043, "Ascom Timeplex" },
+ { 0x8045, "Fujitsu LBLB Control Protocol" },
+ { 0x8047, "DCA Remote Lan Network Control Protocol (RLNCP)" },
+ { 0x8049, "Serial Data Control Protocol (PPP-SDCP)" },
+ { 0x804b, "SNA over 802.2 Control Protocol" },
+ { 0x804d, "SNA Control Protocol" },
+ { 0x804f, "IP6 Header Compression Control Protocol" },
+ { 0x006f, "Stampede Bridging Control Protocol" },
+ { 0x80fb, "Single Link Compression Control Protocol" },
+ { 0x80fd, "Compression Control Protocol" },
+ { 0xc021, "Link Control Protocol" },
+ { 0xc023, "Password Authentication Protocol" },
+ { 0xc025, "Link Quality Report" },
+ { 0xc027, "Shiva Password Authentication Protocol" },
+ { 0xc029, "CallBack Control Protocol (CBCP)" },
+ { 0xc081, "Container Control Protocol" },
+ { 0xc223, "Challenge Handshake Authentication Protocol" },
+ { 0xc281, "Proprietary Authentication Protocol" },
+ { 0, NULL },
+};
+
+/*
+ * protocol_name - find a name for a PPP protocol.
+ */
+const char *
+protocol_name(proto)
+ int proto;
+{
+ struct protocol_list *lp;
+
+ for (lp = protocol_list; lp->proto != 0; ++lp)
+ if (proto == lp->proto)
+ return lp->name;
+ return NULL;
+}
+
+/*
+ * get_input - called when incoming data is available.
+ */
+static void
+get_input(void)
+{
+ int len, i;
+ u_char *p;
+ u_short protocol;
+ struct protent *protp;
+
+ p = inpacket_buf; /* point to beginning of packet buffer */
+
+ len = read_packet(inpacket_buf);
+ if (len < 0)
+ return;
+
+ if (len == 0) {
+ notice("Modem hangup");
+ hungup = 1;
+ pppd_status = EXIT_HANGUP;
+ lcp_lowerdown(0); /* serial link is no longer available */
+ link_terminated(0);
+ return;
+ }
+
+ if (debug /*&& (debugflags & DBG_INPACKET)*/)
+ dbglog("rcvd %P", p, len);
+
+ if (len < PPP_HDRLEN) {
+ MAINDEBUG(("io(): Received short packet."));
+ return;
+ }
+
+ p += 2; /* Skip address and control */
+ GETSHORT(protocol, p);
+ len -= PPP_HDRLEN;
+
+ /*
+ * Toss all non-LCP packets unless LCP is OPEN.
+ */
+ if (protocol != PPP_LCP && lcp_fsm[0].state != OPENED) {
+ MAINDEBUG(("get_input: Received non-LCP packet when LCP not open."));
+ return;
+ }
+
+ /*
+ * Until we get past the authentication phase, toss all packets
+ * except LCP, LQR and authentication packets.
+ */
+ if (pppd_phase <= PHASE_AUTHENTICATE
+ && !(protocol == PPP_LCP || protocol == PPP_LQR
+ || protocol == PPP_PAP || protocol == PPP_CHAP)) {
+ MAINDEBUG(("get_input: discarding proto 0x%x in phase %d",
+ protocol, pppd_phase));
+ return;
+ }
+
+ /*
+ * Upcall the proper protocol input routine.
+ */
+ for (i = 0; (protp = protocols[i]) != NULL; ++i) {
+ if (protp->protocol == protocol && protp->enabled_flag) {
+ (*protp->input)(0, p, len);
+ return;
+ }
+ if (protocol == (protp->protocol & ~0x8000) && protp->enabled_flag
+ && protp->datainput != NULL) {
+ (*protp->datainput)(0, p, len);
+ return;
+ }
+ }
+
+ if (debug) {
+ const char *pname = protocol_name(protocol);
+ if (pname != NULL)
+ warn("Unsupported protocol '%s' (0x%x) received", pname, protocol);
+ else
+ warn("Unsupported protocol 0x%x received", protocol);
+ }
+ lcp_sprotrej(0, p - PPP_HDRLEN, len + PPP_HDRLEN);
+
+ return;
+}
+
+/*
+ * new_phase - signal the start of a new phase of pppd's operation.
+ */
+void
+new_phase(p)
+ int p;
+{
+ pppd_phase = p;
+ if (new_phase_hook)
+ (*new_phase_hook)(p);
+}
+
+/*
+ * die - clean up state and exit with the specified status.
+ */
+void
+die(status)
+ int status;
+{
+ cleanup();
+}
+
+/*
+ * cleanup - restore anything which needs to be restored before we exit
+ */
+/* ARGSUSED */
+static void
+cleanup()
+{
+ sys_cleanup();
+
+ if (fd_ppp >= 0)
+ disestablish_ppp(ttyfd);
+ if (real_ttyfd >= 0)
+ close_tty();
+
+ sys_close();
+}
+
+/*
+ * close_tty - restore the terminal device and close it.
+ */
+static void
+close_tty()
+{
+ /* drop dtr to hang up */
+ if (!default_device && modem) {
+ setdtr(real_ttyfd, 0);
+ /*
+ * This sleep is in case the serial port has CLOCAL set by default,
+ * and consequently will reassert DTR when we close the device.
+ */
+ sleep(1);
+ }
+
+ restore_tty(real_ttyfd);
+
+ close(real_ttyfd);
+ real_ttyfd = -1;
+}
+
+/*
+ * update_link_stats - get stats at link termination.
+ */
+void
+update_link_stats(u)
+ int u;
+{
+ struct timeval now;
+ char numbuf[32];
+
+ if (!get_ppp_stats(u, &link_stats)
+ || gettimeofday(&now, NULL) < 0)
+ return;
+ link_connect_time = now.tv_sec - start_time.tv_sec;
+ link_stats_valid = 1;
+
+ slprintf(numbuf, sizeof(numbuf), "%d", link_connect_time);
+ slprintf(numbuf, sizeof(numbuf), "%d", link_stats.bytes_out);
+ slprintf(numbuf, sizeof(numbuf), "%d", link_stats.bytes_in);
+}
+
+struct callout {
+ struct timeval c_time; /* time at which to call routine */
+ void *c_arg; /* argument to routine */
+ void (*c_func) __P((void *)); /* routine */
+ struct callout *c_next;
+};
+
+static struct callout *callout = NULL; /* Callout list */
+static struct timeval timenow; /* Current time */
+
+/*
+ * timeout - Schedule a timeout.
+ *
+ * Note that this timeout takes the number of seconds, NOT hz (as in
+ * the kernel).
+ */
+void
+ppptimeout(func, arg, time)
+ void (*func) __P((void *));
+ void *arg;
+ int time;
+{
+ struct callout *newp, *p, **pp;
+
+ MAINDEBUG(("Timeout %p:%p in %d seconds.", func, arg, time));
+
+ /*
+ * Allocate timeout.
+ */
+ if ((newp = (struct callout *) malloc(sizeof(struct callout))) == NULL)
+ fatal("Out of memory in timeout()!");
+ newp->c_arg = arg;
+ newp->c_func = func;
+ gettimeofday(&timenow, NULL);
+ newp->c_time.tv_sec = timenow.tv_sec + time;
+ newp->c_time.tv_usec = timenow.tv_usec;
+
+ /*
+ * Find correct place and link it in.
+ */
+ for (pp = &callout; (p = *pp); pp = &p->c_next)
+ if (newp->c_time.tv_sec < p->c_time.tv_sec
+ || (newp->c_time.tv_sec == p->c_time.tv_sec
+ && newp->c_time.tv_usec < p->c_time.tv_usec))
+ break;
+ newp->c_next = p;
+ *pp = newp;
+}
+
+
+/*
+ * untimeout - Unschedule a timeout.
+ */
+void
+untimeout(func, arg)
+ void (*func) __P((void *));
+ void *arg;
+{
+ struct callout **copp, *freep;
+
+ MAINDEBUG(("Untimeout %p:%p.", func, arg));
+
+ /*
+ * Find first matching timeout and remove it from the list.
+ */
+ for (copp = &callout; (freep = *copp); copp = &freep->c_next)
+ if (freep->c_func == func && freep->c_arg == arg) {
+ *copp = freep->c_next;
+ free((char *) freep);
+ break;
+ }
+}
+
+
+/*
+ * calltimeout - Call any timeout routines which are now due.
+ */
+static void
+calltimeout()
+{
+ struct callout *p;
+
+ while (callout != NULL) {
+ p = callout;
+
+ if (gettimeofday(&timenow, NULL) < 0)
+ fatal("Failed to get time of day: %m");
+ if (!(p->c_time.tv_sec < timenow.tv_sec
+ || (p->c_time.tv_sec == timenow.tv_sec
+ && p->c_time.tv_usec <= timenow.tv_usec)))
+ break; /* no, it's not time yet */
+
+ callout = p->c_next;
+ (*p->c_func)(p->c_arg);
+
+ free((char *) p);
+ }
+}
+
+
+/*
+ * timeleft - return the length of time until the next timeout is due.
+ */
+static struct timeval *
+timeleft(tvp)
+ struct timeval *tvp;
+{
+ if (callout == NULL)
+ return NULL;
+
+ gettimeofday(&timenow, NULL);
+ tvp->tv_sec = callout->c_time.tv_sec - timenow.tv_sec;
+ tvp->tv_usec = callout->c_time.tv_usec - timenow.tv_usec;
+ if (tvp->tv_usec < 0) {
+ tvp->tv_usec += 1000000;
+ tvp->tv_sec -= 1;
+ }
+ if (tvp->tv_sec < 0)
+ tvp->tv_sec = tvp->tv_usec = 0;
+
+ return tvp;
+}
+
+/*
+ * device_script - run a program to talk to the serial device
+ * (e.g. to run the connector or disconnector script).
+ */
+static int device_script(int fd, int mode, char *program)
+{
+ int iReturn = -1;
+ char pScript[128];
+
+ /* copyt script into temporary location */
+ strcpy(pScript, program);
+
+ /* check to see if dialer was initialized */
+ if ( !pppd_dialer ) {
+ /* set default dialer to chatmain */
+ pppd_dialer = chatmain;
+ }
+
+ /* check to see if dialer is set */
+ if ( pppd_dialer ) {
+ /* call the dialer */
+ iReturn = (*pppd_dialer)(fd, mode, program);
+ }
+
+ return ( -iReturn );
+}
+
+/*
+ * novm - log an error message saying we ran out of memory, and die.
+ */
+void
+novm(msg)
+ char *msg;
+{
+ fatal("Virtual memory exhausted allocating %s\n", msg);
+}
diff --git a/cpukit/pppd/rtemspppd.c b/cpukit/pppd/rtemspppd.c
new file mode 100644
index 0000000000..ac8055fc58
--- /dev/null
+++ b/cpukit/pppd/rtemspppd.c
@@ -0,0 +1,217 @@
+
+#include <rtems.h>
+#include <rtems/rtems_bsdnet.h>
+#include "pppd.h"
+#include "rtemspppd.h"
+
+
+/* define pppd function prototypes */
+extern void pppasyncattach(void);
+extern int pppdmain(int, char **);
+
+/* define global variables */
+rtems_id rtems_pppd_taskid;
+rtems_pppd_hookfunction rtems_pppd_errorfp;
+rtems_pppd_hookfunction rtems_pppd_exitfp;
+
+
+static rtems_task pppTask(rtems_task_argument arg)
+{
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ rtems_option options;
+ rtems_event_set in;
+ rtems_event_set out;
+ int iStatus;
+
+ /* call function to setup ppp line discipline */
+ pppasyncattach();
+
+ /* enter processing loop */
+ in = (RTEMS_EVENT_29 | RTEMS_EVENT_30);
+ options = (RTEMS_EVENT_ANY | RTEMS_WAIT);
+ while ( sc == RTEMS_SUCCESSFUL ) {
+ /* wait for the next event */
+ sc = rtems_event_receive(in, options, RTEMS_NO_TIMEOUT, &out);
+ if ( sc == RTEMS_SUCCESSFUL ) {
+ /* determine which event was sent */
+ if ( out & RTEMS_EVENT_29 ) {
+ /* terminate event received */
+ /* set value to break out of event loop */
+ sc = RTEMS_UNSATISFIED;
+ }
+ else if ( out & RTEMS_EVENT_30 ) {
+ /* connect request */
+ /* execute the pppd main code */
+ iStatus = pppdmain(0, NULL);
+ if ( iStatus == EXIT_OK ) {
+ /* check exit callback */
+ if ( rtems_pppd_exitfp ) {
+ (*rtems_pppd_exitfp)();
+ }
+ }
+ else {
+ /* check error callback */
+ if ( rtems_pppd_errorfp ) {
+ (*rtems_pppd_errorfp)();
+ }
+ }
+ }
+ }
+ }
+
+ /* terminate myself */
+ rtems_pppd_taskid = 0;
+ rtems_task_delete(RTEMS_SELF);
+}
+
+int rtems_pppd_initialize(void)
+{
+ int iReturn = (int)-1;
+ rtems_unsigned32 priority = 100;
+ rtems_status_code status;
+ rtems_name taskName;
+
+ /* determine priority value */
+ if ( rtems_bsdnet_config.network_task_priority ) {
+ priority = rtems_bsdnet_config.network_task_priority;
+ }
+
+ /* initialize the exit hook */
+ rtems_pppd_exitfp = (rtems_pppd_hookfunction)0;
+
+ /* create the rtems task */
+ taskName = rtems_build_name( 'p', 'p', 'p', 'd' );
+ status = rtems_task_create(taskName, priority, 8192,
+ (RTEMS_PREEMPT|RTEMS_NO_TIMESLICE|RTEMS_NO_ASR|RTEMS_INTERRUPT_LEVEL(0)),
+ RTEMS_NO_FLOATING_POINT|RTEMS_LOCAL,
+ &rtems_pppd_taskid);
+ if ( status == RTEMS_SUCCESSFUL ) {
+ status = rtems_task_start(rtems_pppd_taskid, pppTask, 0);
+ if ( status == RTEMS_SUCCESSFUL ) {
+ iReturn = rtems_pppd_reset_options();
+ }
+ }
+
+ return ( iReturn );
+}
+
+int rtems_pppd_terminate(void)
+{
+ /* send terminate signal to pppd task */
+ rtems_event_send(rtems_pppd_taskid, RTEMS_EVENT_29);
+
+ /* call the disconnect function */
+ rtems_pppd_disconnect();
+
+ return ( 0 );
+}
+
+int rtems_pppd_reset_options(void)
+{
+ int i;
+ struct protent *protp;
+
+ /*
+ * Initialize to the standard option set, then parse, in order,
+ * the system options file, the user's options file,
+ * the tty's options file, and the command line arguments.
+ */
+ for (i = 0; (protp = protocols[i]) != NULL; ++i)
+ (*protp->init)(0);
+
+ return ( 0 );
+}
+
+int rtems_pppd_set_hook(int id, rtems_pppd_hookfunction hookfp)
+{
+ int iReturn = (int)0;
+
+ switch ( id ) {
+ case RTEMS_PPPD_LINKUP_HOOK:
+ auth_linkup_hook = hookfp;
+ break;
+ case RTEMS_PPPD_LINKDOWN_HOOK:
+ auth_linkdown_hook = hookfp;
+ break;
+ case RTEMS_PPPD_IPUP_HOOK:
+ ip_up_hook = hookfp;
+ break;
+ case RTEMS_PPPD_IPDOWN_HOOK:
+ ip_down_hook = hookfp;
+ break;
+ case RTEMS_PPPD_ERROR_HOOK:
+ rtems_pppd_errorfp = hookfp;
+ break;
+ case RTEMS_PPPD_EXIT_HOOK:
+ rtems_pppd_exitfp = hookfp;
+ break;
+ default:
+ iReturn = (int)-1;
+ break;
+ }
+
+ return ( iReturn );
+}
+
+int rtems_pppd_set_dialer(rtems_pppd_dialerfunction dialerfp)
+{
+ pppd_dialer = dialerfp;
+ return ( (int)0 );
+}
+
+int rtems_pppd_set_option(const char *pOption, const char *pValue)
+{
+ int iReturn = (int)0;
+ int prevPhase;
+ struct wordlist option;
+ struct wordlist value;
+
+ if ( pOption != (const char *)0 ) {
+ /* initialize the values */
+ option.word = (char *)pOption;
+ option.next = (struct wordlist *)0;
+ if ( pValue != (const char *)0 ) {
+ option.next = &value;
+ value.word = (char *)pValue;
+ value.next = (struct wordlist *)0;
+ }
+
+ /* save current phase value */
+ prevPhase = pppd_phase;
+ pppd_phase = PHASE_INITIALIZE;
+
+ /* process option and reset phase value */
+ iReturn = options_from_list(&option, 1);
+ pppd_phase = prevPhase;
+ }
+
+ return ( iReturn );
+}
+
+int rtems_pppd_connect(void)
+{
+ /* send connect signal to pppd task */
+ rtems_event_send(rtems_pppd_taskid, RTEMS_EVENT_30);
+
+ return ( 0 );
+}
+
+static void timeout_terminate(void *arg)
+{
+ /* set pppd global variables to disconnect */
+ persist = 0;
+ pppd_kill_link = 1;
+}
+
+int rtems_pppd_disconnect(void)
+{
+ /* need to wait a little time before we can bring the link down */
+ /* set up time out in 1 seconds */
+ TIMEOUT(timeout_terminate, NULL, 1);
+
+ /* send event to wake up the pppd code */
+ /* pretend its a serial interrput */
+ rtems_event_send(rtems_pppd_taskid, RTEMS_EVENT_31);
+
+ return ( 0 );
+}
diff --git a/cpukit/pppd/rtemspppd.h b/cpukit/pppd/rtemspppd.h
new file mode 100644
index 0000000000..f60916e2ee
--- /dev/null
+++ b/cpukit/pppd/rtemspppd.h
@@ -0,0 +1,29 @@
+
+#ifndef RTEMSPPPD_H
+#define RTEMSPPPD_H
+
+
+/* define hook function identifiers */
+#define RTEMS_PPPD_LINKUP_HOOK 1
+#define RTEMS_PPPD_LINKDOWN_HOOK 2
+#define RTEMS_PPPD_IPUP_HOOK 3
+#define RTEMS_PPPD_IPDOWN_HOOK 4
+#define RTEMS_PPPD_ERROR_HOOK 5
+#define RTEMS_PPPD_EXIT_HOOK 6
+
+/* define hook function pointer prototype */
+typedef void (*rtems_pppd_hookfunction)(void);
+typedef int (*rtems_pppd_dialerfunction)(int tty, int mode, char *pScript);
+
+
+/* define pppd function prototyes */
+int rtems_pppd_initialize(void);
+int rtems_pppd_terminate(void);
+int rtems_pppd_reset_options(void);
+int rtems_pppd_set_hook(int id, rtems_pppd_hookfunction hookfp);
+int rtems_pppd_set_dialer(rtems_pppd_dialerfunction dialerfp);
+int rtems_pppd_set_option(const char *pOption, const char *pValue);
+int rtems_pppd_connect(void);
+int rtems_pppd_disconnect(void);
+
+#endif
diff --git a/cpukit/pppd/sys-rtems.c b/cpukit/pppd/sys-rtems.c
new file mode 100644
index 0000000000..0fc3e139b9
--- /dev/null
+++ b/cpukit/pppd/sys-rtems.c
@@ -0,0 +1,1330 @@
+/*
+ * sys-bsd.c - System-dependent procedures for setting up
+ * PPP interfaces on bsd-4.4-ish systems (including 386BSD, NetBSD, etc.)
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * Copyright (c) 1995 The Australian National University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University and The Australian National University.
+ * The names of the Universities may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#define RCSID "$Id$"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#ifdef PPP_FILTER
+#include <net/bpf.h>
+#endif
+
+#include <net/if.h>
+#include <net/ppp_defs.h>
+#include <net/if_ppp.h>
+#include <net/route.h>
+#include <net/if_dl.h>
+#include <netinet/in.h>
+
+#if RTM_VERSION >= 3
+#include <sys/param.h>
+#if defined(NetBSD) && (NetBSD >= 199703)
+#include <netinet/if_inarp.h>
+#else /* NetBSD 1.2D or later */
+#include <netinet/if_ether.h>
+#endif
+#endif
+
+#include <rtems.h>
+#include <rtems/rtems_bsdnet.h>
+#include <rtems/termiostypes.h>
+extern int rtems_bsdnet_microseconds_per_tick;
+extern rtems_id rtems_pppd_taskid;
+
+#include "pppd.h"
+#include "fsm.h"
+#include "ipcp.h"
+
+static const char rcsid[] = RCSID;
+
+
+static int initdisc = -1; /* Initial TTY discipline for ppp_fd */
+static int initfdflags = -1; /* Initial file descriptor flags for ppp_fd */
+static int ppp_fd = -1; /* fd which is set to PPP discipline */
+static int rtm_seq;
+
+static int restore_term; /* 1 => we've munged the terminal */
+static struct termios inittermios; /* Initial TTY termios */
+static struct winsize wsinfo; /* Initial window size info */
+
+static int loop_slave = -1;
+static int loop_master;
+
+static unsigned char inbuf[512]; /* buffer for chars read from loopback */
+
+static int sockfd; /* socket for doing interface ioctls */
+
+static int if_is_up; /* the interface is currently up */
+static u_int32_t ifaddrs[2]; /* local and remote addresses we set */
+static u_int32_t default_route_gateway; /* gateway addr for default route */
+static u_int32_t proxy_arp_addr; /* remote addr for proxy arp */
+
+/* Prototypes for procedures local to this file. */
+static int dodefaultroute __P((u_int32_t, int));
+static int get_ether_addr __P((u_int32_t, struct sockaddr_dl *));
+
+
+/*
+ * sys_init - System-dependent initialization.
+ */
+void
+sys_init()
+{
+ /* Get an internet socket for doing socket ioctl's on. */
+ if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+ fatal("Couldn't create IP socket: %m");
+}
+
+/*
+ * sys_cleanup - restore any system state we modified before exiting:
+ * mark the interface down, delete default route and/or proxy arp entry.
+ * This should call die() because it's called from die().
+ */
+void
+sys_cleanup()
+{
+ struct ifreq ifr;
+
+ if (if_is_up) {
+ strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) >= 0
+ && ((ifr.ifr_flags & IFF_UP) != 0)) {
+ ifr.ifr_flags &= ~IFF_UP;
+ ioctl(sockfd, SIOCSIFFLAGS, &ifr);
+ }
+ }
+ if (ifaddrs[0] != 0)
+ cifaddr(0, ifaddrs[0], ifaddrs[1]);
+ if (default_route_gateway)
+ cifdefaultroute(0, 0, default_route_gateway);
+ if (proxy_arp_addr)
+ cifproxyarp(0, proxy_arp_addr);
+}
+
+/*
+ * sys_close - Clean up in a child process before execing.
+ */
+void
+sys_close()
+{
+ close(sockfd);
+ if (loop_slave >= 0) {
+ close(loop_slave);
+ close(loop_master);
+ }
+}
+
+/*
+ * sys_check_options - check the options that the user specified
+ */
+int
+sys_check_options()
+{
+ return 1;
+}
+
+/*
+ * ppp_available - check whether the system has any ppp interfaces
+ * (in fact we check whether we can do an ioctl on ppp0).
+ */
+int
+ppp_available()
+{
+ int s, ok;
+ struct ifreq ifr;
+
+ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+ return 1; /* can't tell */
+
+ strlcpy(ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
+ ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
+ close(s);
+
+ return ok;
+}
+
+/*
+ * establish_ppp - Turn the serial port into a ppp interface.
+ */
+int
+establish_ppp(fd)
+ int fd;
+{
+ int taskid = (int)rtems_pppd_taskid;
+ int pppdisc = PPPDISC;
+ int x;
+
+ if (demand) {
+ /*
+ * Demand mode - prime the old ppp device to relinquish the unit.
+ */
+ if (ioctl(ppp_fd, PPPIOCXFERUNIT, 0) < 0)
+ fatal("ioctl(transfer ppp unit): %m");
+ }
+
+ /*
+ * Save the old line discipline of fd, and set it to PPP.
+ */
+ if (ioctl(fd, TIOCGETD, &initdisc) < 0)
+ fatal("ioctl(TIOCGETD): %m");
+ if (ioctl(fd, TIOCSETD, &pppdisc) < 0)
+ fatal("ioctl(TIOCSETD): %m");
+
+ /* set pppd taskid into the driver */
+ ioctl(fd, PPPIOCSTASK, &taskid);
+
+ if (!demand) {
+ /*
+ * Find out which interface we were given.
+ */
+ if (ioctl(fd, PPPIOCGUNIT, &pppifunit) < 0)
+ fatal("ioctl(PPPIOCGUNIT): %m");
+ } else {
+ /*
+ * Check that we got the same unit again.
+ */
+ if (ioctl(fd, PPPIOCGUNIT, &x) < 0)
+ fatal("ioctl(PPPIOCGUNIT): %m");
+ if (x != pppifunit)
+ fatal("transfer_ppp failed: wanted unit %d, got %d", pppifunit, x);
+ x = TTYDISC;
+ ioctl(loop_slave, TIOCSETD, &x);
+ }
+
+ ppp_fd = fd;
+
+ /*
+ * Enable debug in the driver if requested.
+ */
+ if (kdebugflag) {
+ if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
+ warn("ioctl (PPPIOCGFLAGS): %m");
+ } else {
+ x |= (kdebugflag & 0xFF) * SC_DEBUG;
+ if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
+ warn("ioctl(PPPIOCSFLAGS): %m");
+ }
+ }
+
+ /*
+ * Set device for non-blocking reads.
+ */
+ if ((initfdflags = fcntl(fd, F_GETFL)) == -1
+ || fcntl(fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) {
+ warn("Couldn't set device to non-blocking mode: %m");
+ }
+
+ return fd;
+}
+
+/*
+ * restore_loop - reattach the ppp unit to the loopback.
+ */
+void
+restore_loop()
+{
+ int x;
+
+ /*
+ * Transfer the ppp interface back to the loopback.
+ */
+ if (ioctl(ppp_fd, PPPIOCXFERUNIT, 0) < 0)
+ fatal("ioctl(transfer ppp unit): %m");
+ x = PPPDISC;
+ if (ioctl(loop_slave, TIOCSETD, &x) < 0)
+ fatal("ioctl(TIOCSETD): %m");
+
+ /*
+ * Check that we got the same unit again.
+ */
+ if (ioctl(loop_slave, PPPIOCGUNIT, &x) < 0)
+ fatal("ioctl(PPPIOCGUNIT): %m");
+ if (x != pppifunit)
+ fatal("transfer_ppp failed: wanted unit %d, got %d", pppifunit, x);
+ ppp_fd = loop_slave;
+}
+
+
+/*
+ * disestablish_ppp - Restore the serial port to normal operation.
+ * This shouldn't call die() because it's called from die().
+ */
+void
+disestablish_ppp(fd)
+ int fd;
+{
+ int taskid = (int)0;
+
+ /* clear pppd taskid from the driver */
+ ioctl(fd, PPPIOCSTASK, &taskid);
+
+ /* Reset non-blocking mode on fd. */
+ if (initfdflags != -1 && fcntl(fd, F_SETFL, initfdflags) < 0)
+ warn("Couldn't restore device fd flags: %m");
+ initfdflags = -1;
+
+ /* Restore old line discipline. */
+ if (initdisc >= 0 && ioctl(fd, TIOCSETD, &initdisc) < 0)
+ error("ioctl(TIOCSETD): %m");
+ initdisc = -1;
+
+ if (fd == ppp_fd)
+ ppp_fd = -1;
+}
+
+/*
+ * Check whether the link seems not to be 8-bit clean.
+ */
+void
+clean_check()
+{
+ int x;
+ char *s;
+
+ if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) == 0) {
+ s = NULL;
+ switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP)) {
+ case SC_RCV_B7_0:
+ s = "bit 7 set to 1";
+ break;
+ case SC_RCV_B7_1:
+ s = "bit 7 set to 0";
+ break;
+ case SC_RCV_EVNP:
+ s = "odd parity";
+ break;
+ case SC_RCV_ODDP:
+ s = "even parity";
+ break;
+ }
+ if (s != NULL) {
+ warn("Serial link is not 8-bit clean:");
+ warn("All received characters had %s", s);
+ }
+ }
+}
+
+/*
+ * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
+ * at the requested speed, etc. If `local' is true, set CLOCAL
+ * regardless of whether the modem option was specified.
+ *
+ * For *BSD, we assume that speed_t values numerically equal bits/second.
+ */
+void
+set_up_tty(fd, local)
+ int fd, local;
+{
+ struct termios tios;
+
+ if (tcgetattr(fd, &tios) < 0)
+ fatal("tcgetattr: %m");
+
+ if (!restore_term) {
+ inittermios = tios;
+ ioctl(fd, TIOCGWINSZ, &wsinfo);
+ }
+
+ tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
+ if (crtscts > 0 && !local) {
+ if (crtscts == 2) {
+#ifdef CDTRCTS
+ tios.c_cflag |= CDTRCTS;
+#endif
+ } else
+ tios.c_cflag |= CRTSCTS;
+ } else if (crtscts < 0) {
+ tios.c_cflag &= ~CRTSCTS;
+#ifdef CDTRCTS
+ tios.c_cflag &= ~CDTRCTS;
+#endif
+ }
+
+ tios.c_cflag |= CS8 | CREAD | HUPCL;
+ if (local || !modem)
+ tios.c_cflag |= CLOCAL;
+ tios.c_iflag = IGNBRK | IGNPAR;
+ tios.c_oflag = 0;
+ tios.c_lflag = 0;
+ tios.c_cc[VMIN] = 1;
+ tios.c_cc[VTIME] = 0;
+
+ if (crtscts == -2) {
+ tios.c_iflag |= IXON | IXOFF;
+ tios.c_cc[VSTOP] = 0x13; /* DC3 = XOFF = ^S */
+ tios.c_cc[VSTART] = 0x11; /* DC1 = XON = ^Q */
+ }
+
+ if (inspeed) {
+ cfsetospeed(&tios, inspeed);
+ cfsetispeed(&tios, inspeed);
+ } else {
+ inspeed = cfgetospeed(&tios);
+ /*
+ * We can't proceed if the serial port speed is 0,
+ * since that implies that the serial port is disabled.
+ */
+ if (inspeed == 0)
+ fatal("Baud rate for %s is 0; need explicit baud rate", devnam);
+ }
+ baud_rate = inspeed;
+
+/* if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) { */
+ if (tcsetattr(fd, TCSADRAIN, &tios) < 0) {
+ fatal("tcsetattr: %m");
+ }
+
+ restore_term = 1;
+}
+
+/*
+ * restore_tty - restore the terminal to the saved settings.
+ */
+void
+restore_tty(fd)
+ int fd;
+{
+ if (restore_term) {
+ if (!default_device) {
+ /*
+ * Turn off echoing, because otherwise we can get into
+ * a loop with the tty and the modem echoing to each other.
+ * We presume we are the sole user of this tty device, so
+ * when we close it, it will revert to its defaults anyway.
+ */
+ inittermios.c_lflag &= ~(ECHO | ECHONL);
+ }
+/* if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0) { */
+ if (tcsetattr(fd, TCSADRAIN, &inittermios) < 0) {
+ if (errno != ENXIO)
+ warn("tcsetattr: %m");
+ }
+ ioctl(fd, TIOCSWINSZ, &wsinfo);
+ restore_term = 0;
+ }
+}
+
+/*
+ * setdtr - control the DTR line on the serial port.
+ * This is called from die(), so it shouldn't call die().
+ */
+void
+setdtr(fd, on)
+int fd, on;
+{
+ int modembits = TIOCM_DTR;
+
+ ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);
+}
+
+/*
+ * get_pty - get a pty master/slave pair and chown the slave side
+ * to the uid given. Assumes slave_name points to >= 12 bytes of space.
+ */
+int
+get_pty(master_fdp, slave_fdp, slave_name, uid)
+ int *master_fdp;
+ int *slave_fdp;
+ char *slave_name;
+ int uid;
+{
+ return 1;
+}
+
+
+/*
+ * open_ppp_loopback - open the device we use for getting
+ * packets in demand mode, and connect it to a ppp interface.
+ * Here we use a pty.
+ */
+int
+open_ppp_loopback()
+{
+ return loop_master;
+}
+
+
+/*
+ * output - Output PPP packet.
+ */
+void
+output(unit, p, len)
+ int unit;
+ u_char *p;
+ int len;
+{
+ if (debug);
+ dbglog("sent %P", p, len);
+/* printf("sent packet [%d]\n", len); */
+
+ if (write(ttyfd, p, len) < 0) {
+ if (errno != EIO)
+ error("write: %m");
+ }
+}
+
+void
+ppp_delay(void)
+{
+ rtems_interval ticks;
+
+ /* recommended delay to help negotiation */
+ ticks = 300000/rtems_bsdnet_microseconds_per_tick;
+ rtems_task_wake_after(ticks);
+}
+
+/*
+ * wait_input - wait until there is data available,
+ * for the length of time specified by *timo (indefinite
+ * if timo is NULL).
+ */
+void
+wait_input(timo)
+ struct timeval *timo;
+{
+ rtems_interval ticks;
+ rtems_event_set events;
+
+ ticks = ((timo->tv_sec*1000000)+timo->tv_usec)/rtems_bsdnet_microseconds_per_tick;
+ if ( ticks > 0 ) {
+ rtems_event_receive(RTEMS_EVENT_31, (RTEMS_EVENT_ANY|RTEMS_WAIT), ticks, &events);
+ }
+}
+
+/*
+ * read_packet - get a PPP packet from the serial device.
+ */
+int
+read_packet(buf)
+ u_char *buf;
+{
+ int len;
+
+ if ((len = read(ttyfd, buf, PPP_MTU + PPP_HDRLEN)) < 0) {
+ if (errno == EWOULDBLOCK || errno == EINTR) len = -1;
+ /*fatal("read: %m"); */
+ }
+
+/* printf("read packet [%d]\n", len); */
+ return len;
+}
+
+
+/*
+ * get_loop_output - read characters from the loopback, form them
+ * into frames, and detect when we want to bring the real link up.
+ * Return value is 1 if we need to bring up the link, 0 otherwise.
+ */
+int
+get_loop_output()
+{
+ int rv = 0;
+ int n;
+
+ while ((n = read(loop_master, inbuf, sizeof(inbuf))) >= 0) {
+ if (loop_chars(inbuf, n))
+ rv = 1;
+ }
+
+ if (n == 0)
+ fatal("eof on loopback");
+ if (errno != EWOULDBLOCK)
+ fatal("read from loopback: %m");
+
+ return rv;
+}
+
+
+/*
+ * ppp_send_config - configure the transmit characteristics of
+ * the ppp interface.
+ */
+void
+ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
+ int unit, mtu;
+ u_int32_t asyncmap;
+ int pcomp, accomp;
+{
+ u_int x;
+ struct ifreq ifr;
+
+ strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
+ ifr.ifr_mtu = mtu;
+ if (ioctl(sockfd, SIOCSIFMTU, (caddr_t) &ifr) < 0)
+ fatal("ioctl(SIOCSIFMTU): %m");
+
+ if (ioctl(ppp_fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0)
+ fatal("ioctl(PPPIOCSASYNCMAP): %m");
+
+ if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0)
+ fatal("ioctl (PPPIOCGFLAGS): %m");
+ x = pcomp? x | SC_COMP_PROT: x &~ SC_COMP_PROT;
+ x = accomp? x | SC_COMP_AC: x &~ SC_COMP_AC;
+/* x = sync_serial ? x | SC_SYNC : x & ~SC_SYNC; */
+ if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
+ fatal("ioctl(PPPIOCSFLAGS): %m");
+}
+
+
+/*
+ * ppp_set_xaccm - set the extended transmit ACCM for the interface.
+ */
+void
+ppp_set_xaccm(unit, accm)
+ int unit;
+ ext_accm accm;
+{
+ if (ioctl(ppp_fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY)
+ warn("ioctl(set extended ACCM): %m");
+}
+
+
+/*
+ * ppp_recv_config - configure the receive-side characteristics of
+ * the ppp interface.
+ */
+void
+ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
+ int unit, mru;
+ u_int32_t asyncmap;
+ int pcomp, accomp;
+{
+ int x;
+
+ if (ioctl(ppp_fd, PPPIOCSMRU, (caddr_t) &mru) < 0)
+ fatal("ioctl(PPPIOCSMRU): %m");
+ if (ioctl(ppp_fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0)
+ fatal("ioctl(PPPIOCSRASYNCMAP): %m");
+ if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0)
+ fatal("ioctl (PPPIOCGFLAGS): %m");
+ x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC;
+ if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
+ fatal("ioctl(PPPIOCSFLAGS): %m");
+}
+
+/*
+ * ccp_test - ask kernel whether a given compression method
+ * is acceptable for use. Returns 1 if the method and parameters
+ * are OK, 0 if the method is known but the parameters are not OK
+ * (e.g. code size should be reduced), or -1 if the method is unknown.
+ */
+int
+ccp_test(unit, opt_ptr, opt_len, for_transmit)
+ int unit, opt_len, for_transmit;
+ u_char *opt_ptr;
+{
+ struct ppp_option_data data;
+
+ data.ptr = opt_ptr;
+ data.length = opt_len;
+ data.transmit = for_transmit;
+ if (ioctl(ttyfd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0)
+ return 1;
+ return (errno == ENOBUFS)? 0: -1;
+}
+
+/*
+ * ccp_flags_set - inform kernel about the current state of CCP.
+ */
+void
+ccp_flags_set(unit, isopen, isup)
+ int unit, isopen, isup;
+{
+ int x;
+
+ if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
+ error("ioctl (PPPIOCGFLAGS): %m");
+ return;
+ }
+ x = isopen? x | SC_CCP_OPEN: x &~ SC_CCP_OPEN;
+ x = isup? x | SC_CCP_UP: x &~ SC_CCP_UP;
+ if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
+ error("ioctl(PPPIOCSFLAGS): %m");
+}
+
+/*
+ * ccp_fatal_error - returns 1 if decompression was disabled as a
+ * result of an error detected after decompression of a packet,
+ * 0 otherwise. This is necessary because of patent nonsense.
+ */
+int
+ccp_fatal_error(unit)
+ int unit;
+{
+ int x;
+
+ if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
+ error("ioctl(PPPIOCGFLAGS): %m");
+ return 0;
+ }
+ return x & SC_DC_FERROR;
+}
+
+/*
+ * get_idle_time - return how long the link has been idle.
+ */
+int
+get_idle_time(u, ip)
+ int u;
+ struct ppp_idle *ip;
+{
+ return ioctl(ppp_fd, PPPIOCGIDLE, ip) >= 0;
+}
+
+/*
+ * get_ppp_stats - return statistics for the link.
+ */
+int
+get_ppp_stats(u, stats)
+ int u;
+ struct pppd_stats *stats;
+{
+ struct ifpppstatsreq req;
+
+ memset (&req, 0, sizeof (req));
+ strlcpy(req.ifr_name, ifname, sizeof(req.ifr_name));
+ if (ioctl(sockfd, SIOCGPPPSTATS, &req) < 0) {
+ error("Couldn't get PPP statistics: %m");
+ return 0;
+ }
+ stats->bytes_in = req.stats.p.ppp_ibytes;
+ stats->bytes_out = req.stats.p.ppp_obytes;
+ return 1;
+}
+
+
+#ifdef PPP_FILTER
+/*
+ * set_filters - transfer the pass and active filters to the kernel.
+ */
+int
+set_filters(pass, active)
+ struct bpf_program *pass, *active;
+{
+ int ret = 1;
+
+ if (pass->bf_len > 0) {
+ if (ioctl(ppp_fd, PPPIOCSPASS, pass) < 0) {
+ error("Couldn't set pass-filter in kernel: %m");
+ ret = 0;
+ }
+ }
+ if (active->bf_len > 0) {
+ if (ioctl(ppp_fd, PPPIOCSACTIVE, active) < 0) {
+ error("Couldn't set active-filter in kernel: %m");
+ ret = 0;
+ }
+ }
+ return ret;
+}
+#endif
+
+/*
+ * sifvjcomp - config tcp header compression
+ */
+int
+sifvjcomp(u, vjcomp, cidcomp, maxcid)
+ int u, vjcomp, cidcomp, maxcid;
+{
+ u_int x;
+
+ if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
+ error("ioctl (PPPIOCGFLAGS): %m");
+ return 0;
+ }
+ x = vjcomp ? x | SC_COMP_TCP: x &~ SC_COMP_TCP;
+ x = cidcomp? x & ~SC_NO_TCP_CCID: x | SC_NO_TCP_CCID;
+ if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
+ error("ioctl(PPPIOCSFLAGS): %m");
+ return 0;
+ }
+ if (vjcomp && ioctl(ppp_fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) {
+ error("ioctl(PPPIOCSFLAGS): %m");
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * sifup - Config the interface up and enable IP packets to pass.
+ */
+int
+sifup(u)
+ int u;
+{
+ struct ifreq ifr;
+
+ strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
+ if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
+ error("ioctl (SIOCGIFFLAGS): %m");
+ return 0;
+ }
+ ifr.ifr_flags |= IFF_UP;
+ if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
+ error("ioctl(SIOCSIFFLAGS): %m");
+ return 0;
+ }
+ if_is_up = 1;
+ return 1;
+}
+
+/*
+ * sifnpmode - Set the mode for handling packets for a given NP.
+ */
+int
+sifnpmode(u, proto, mode)
+ int u;
+ int proto;
+ enum NPmode mode;
+{
+ struct npioctl npi;
+
+ npi.protocol = proto;
+ npi.mode = mode;
+ if (ioctl(ppp_fd, PPPIOCSNPMODE, &npi) < 0) {
+ error("ioctl(set NP %d mode to %d): %m", proto, mode);
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * sifdown - Config the interface down and disable IP.
+ */
+int
+sifdown(u)
+ int u;
+{
+ struct ifreq ifr;
+ int rv;
+ struct npioctl npi;
+
+ rv = 1;
+ npi.protocol = PPP_IP;
+ npi.mode = NPMODE_ERROR;
+ ioctl(ppp_fd, PPPIOCSNPMODE, (caddr_t) &npi);
+ /* ignore errors, because ppp_fd might have been closed by now. */
+
+ strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
+ if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
+ error("ioctl (SIOCGIFFLAGS): %m");
+ rv = 0;
+ } else {
+ ifr.ifr_flags &= ~IFF_UP;
+ if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
+ error("ioctl(SIOCSIFFLAGS): %m");
+ rv = 0;
+ } else
+ if_is_up = 0;
+ }
+ return rv;
+}
+
+/*
+ * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
+ * if it exists.
+ */
+#define SET_SA_FAMILY(addr, family) \
+ BZERO((char *) &(addr), sizeof(addr)); \
+ addr.sa_family = (family); \
+ addr.sa_len = sizeof(addr);
+
+/*
+ * sifaddr - Config the interface IP addresses and netmask.
+ */
+int
+sifaddr(u, o, h, m)
+ int u;
+ u_int32_t o, h, m;
+{
+ struct ifaliasreq ifra;
+ struct ifreq ifr;
+
+ strlcpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
+ SET_SA_FAMILY(ifra.ifra_addr, AF_INET);
+ ((struct sockaddr_in *) &ifra.ifra_addr)->sin_addr.s_addr = o;
+ SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET);
+ ((struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h;
+ if (m != 0) {
+ SET_SA_FAMILY(ifra.ifra_mask, AF_INET);
+ ((struct sockaddr_in *) &ifra.ifra_mask)->sin_addr.s_addr = m;
+ } else
+ BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask));
+ BZERO(&ifr, sizeof(ifr));
+ strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ if (ioctl(sockfd, SIOCDIFADDR, (caddr_t) &ifr) < 0) {
+ if (errno != EADDRNOTAVAIL)
+ warn("Couldn't remove interface address: %m");
+ }
+ if (ioctl(sockfd, SIOCAIFADDR, (caddr_t) &ifra) < 0) {
+ if (errno != EEXIST) {
+ error("Couldn't set interface address: %m");
+ return 0;
+ }
+ warn("Couldn't set interface address: Address %I already exists", o);
+ }
+ ifaddrs[0] = o;
+ ifaddrs[1] = h;
+ return 1;
+}
+
+/*
+ * cifaddr - Clear the interface IP addresses, and delete routes
+ * through the interface if possible.
+ */
+int
+cifaddr(u, o, h)
+ int u;
+ u_int32_t o, h;
+{
+ struct ifaliasreq ifra;
+
+ ifaddrs[0] = 0;
+ strlcpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
+ SET_SA_FAMILY(ifra.ifra_addr, AF_INET);
+ ((struct sockaddr_in *) &ifra.ifra_addr)->sin_addr.s_addr = o;
+ SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET);
+ ((struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h;
+ BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask));
+ if (ioctl(sockfd, SIOCDIFADDR, (caddr_t) &ifra) < 0) {
+ if (errno != EADDRNOTAVAIL)
+ warn("Couldn't delete interface address: %m");
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * sifdefaultroute - assign a default route through the address given.
+ */
+int
+sifdefaultroute(u, l, g)
+ int u;
+ u_int32_t l, g;
+{
+ return dodefaultroute(g, 's');
+}
+
+/*
+ * cifdefaultroute - delete a default route through the address given.
+ */
+int
+cifdefaultroute(u, l, g)
+ int u;
+ u_int32_t l, g;
+{
+ return dodefaultroute(g, 'c');
+}
+
+/*
+ * dodefaultroute - talk to a routing socket to add/delete a default route.
+ */
+static int
+dodefaultroute(g, cmd)
+ u_int32_t g;
+ int cmd;
+{
+/* int status; */
+ struct sockaddr_in address;
+ struct sockaddr_in netmask;
+ struct sockaddr_in gateway;
+
+ memset((void *) &address, 0, sizeof(address));
+ address.sin_len = sizeof address;
+ address.sin_family = AF_INET;
+ address.sin_addr.s_addr = INADDR_ANY;
+
+ memset((void *) &netmask, 0, sizeof(netmask));
+ netmask.sin_len = sizeof netmask;
+ netmask.sin_addr.s_addr = INADDR_ANY;
+ netmask.sin_family = AF_INET;
+
+ if (cmd=='s') {
+ memset((void *) &gateway, 0, sizeof(gateway));
+ gateway.sin_len = sizeof gateway;
+ gateway.sin_family = AF_INET;
+ gateway.sin_addr.s_addr = g;
+
+ rtems_bsdnet_rtrequest(RTM_ADD,
+ (struct sockaddr *)&address,
+ (struct sockaddr *)&gateway,
+ (struct sockaddr *)&netmask,
+ (RTF_UP|RTF_GATEWAY|RTF_STATIC), NULL);
+ }
+ else {
+ memset((void *) &gateway, 0, sizeof(gateway));
+ gateway.sin_len = sizeof gateway;
+ gateway.sin_family = AF_INET;
+ gateway.sin_addr.s_addr = INADDR_ANY;
+
+ rtems_bsdnet_rtrequest(RTM_DELETE,
+ (struct sockaddr *)&address,
+ (struct sockaddr *)&gateway,
+ (struct sockaddr *)&netmask,
+ (RTF_UP|RTF_STATIC), NULL);
+ }
+
+ default_route_gateway = (cmd == 's')? g: 0;
+
+ return 1;
+}
+
+#if RTM_VERSION >= 3
+
+/*
+ * sifproxyarp - Make a proxy ARP entry for the peer.
+ */
+static struct {
+ struct rt_msghdr hdr;
+ struct sockaddr_inarp dst;
+ struct sockaddr_dl hwa;
+ char extra[128];
+} arpmsg;
+
+static int arpmsg_valid;
+
+int
+sifproxyarp(unit, hisaddr)
+ int unit;
+ u_int32_t hisaddr;
+{
+ int routes;
+
+ /*
+ * Get the hardware address of an interface on the same subnet
+ * as our local address.
+ */
+ memset(&arpmsg, 0, sizeof(arpmsg));
+ if (!get_ether_addr(hisaddr, &arpmsg.hwa)) {
+ error("Cannot determine ethernet address for proxy ARP");
+ return 0;
+ }
+
+ if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
+ error("Couldn't add proxy arp entry: socket: %m");
+ return 0;
+ }
+
+ arpmsg.hdr.rtm_type = RTM_ADD;
+ arpmsg.hdr.rtm_flags = RTF_ANNOUNCE | RTF_HOST | RTF_STATIC;
+ arpmsg.hdr.rtm_version = RTM_VERSION;
+ arpmsg.hdr.rtm_seq = ++rtm_seq;
+ arpmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY;
+ arpmsg.hdr.rtm_inits = RTV_EXPIRE;
+ arpmsg.dst.sin_len = sizeof(struct sockaddr_inarp);
+ arpmsg.dst.sin_family = AF_INET;
+ arpmsg.dst.sin_addr.s_addr = hisaddr;
+ arpmsg.dst.sin_other = SIN_PROXY;
+
+ arpmsg.hdr.rtm_msglen = (char *) &arpmsg.hwa - (char *) &arpmsg
+ + arpmsg.hwa.sdl_len;
+ if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) {
+ error("Couldn't add proxy arp entry: %m");
+ close(routes);
+ return 0;
+ }
+
+ close(routes);
+ arpmsg_valid = 1;
+ proxy_arp_addr = hisaddr;
+ return 1;
+}
+
+/*
+ * cifproxyarp - Delete the proxy ARP entry for the peer.
+ */
+int
+cifproxyarp(unit, hisaddr)
+ int unit;
+ u_int32_t hisaddr;
+{
+ int routes;
+
+ if (!arpmsg_valid)
+ return 0;
+ arpmsg_valid = 0;
+
+ arpmsg.hdr.rtm_type = RTM_DELETE;
+ arpmsg.hdr.rtm_seq = ++rtm_seq;
+
+ if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
+ error("Couldn't delete proxy arp entry: socket: %m");
+ return 0;
+ }
+
+ if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) {
+ error("Couldn't delete proxy arp entry: %m");
+ close(routes);
+ return 0;
+ }
+
+ close(routes);
+ proxy_arp_addr = 0;
+ return 1;
+}
+
+#else /* RTM_VERSION */
+
+/*
+ * sifproxyarp - Make a proxy ARP entry for the peer.
+ */
+int
+sifproxyarp(unit, hisaddr)
+ int unit;
+ u_int32_t hisaddr;
+{
+ struct arpreq arpreq;
+ struct {
+ struct sockaddr_dl sdl;
+ char space[128];
+ } dls;
+
+ BZERO(&arpreq, sizeof(arpreq));
+
+ /*
+ * Get the hardware address of an interface on the same subnet
+ * as our local address.
+ */
+ if (!get_ether_addr(hisaddr, &dls.sdl)) {
+ error("Cannot determine ethernet address for proxy ARP");
+ return 0;
+ }
+
+ arpreq.arp_ha.sa_len = sizeof(struct sockaddr);
+ arpreq.arp_ha.sa_family = AF_UNSPEC;
+ BCOPY(LLADDR(&dls.sdl), arpreq.arp_ha.sa_data, dls.sdl.sdl_alen);
+ SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
+ ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
+ arpreq.arp_flags = ATF_PERM | ATF_PUBL;
+ if (ioctl(sockfd, SIOCSARP, (caddr_t)&arpreq) < 0) {
+ error("Couldn't add proxy arp entry: %m");
+ return 0;
+ }
+
+ proxy_arp_addr = hisaddr;
+ return 1;
+}
+
+/*
+ * cifproxyarp - Delete the proxy ARP entry for the peer.
+ */
+int
+cifproxyarp(unit, hisaddr)
+ int unit;
+ u_int32_t hisaddr;
+{
+ struct arpreq arpreq;
+
+ BZERO(&arpreq, sizeof(arpreq));
+ SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
+ ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
+ if (ioctl(sockfd, SIOCDARP, (caddr_t)&arpreq) < 0) {
+ warn("Couldn't delete proxy arp entry: %m");
+ return 0;
+ }
+ proxy_arp_addr = 0;
+ return 1;
+}
+#endif /* RTM_VERSION */
+
+
+/*
+ * get_ether_addr - get the hardware address of an interface on the
+ * the same subnet as ipaddr.
+ */
+#define MAX_IFS 32
+
+static int
+get_ether_addr(ipaddr, hwaddr)
+ u_int32_t ipaddr;
+ struct sockaddr_dl *hwaddr;
+{
+ struct ifreq *ifr, *ifend, *ifp;
+ u_int32_t ina, mask;
+ struct sockaddr_dl *dla;
+ struct ifreq ifreq;
+ struct ifconf ifc;
+ struct ifreq ifs[MAX_IFS];
+
+ ifc.ifc_len = sizeof(ifs);
+ ifc.ifc_req = ifs;
+ if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
+ error("ioctl(SIOCGIFCONF): %m");
+ return 0;
+ }
+
+ /*
+ * Scan through looking for an interface with an Internet
+ * address on the same subnet as `ipaddr'.
+ */
+ ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
+ for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *)
+ ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len)) {
+ if (ifr->ifr_addr.sa_family == AF_INET) {
+ ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
+ strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
+ /*
+ * Check that the interface is up, and not point-to-point
+ * or loopback.
+ */
+ if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
+ continue;
+ if ((ifreq.ifr_flags &
+ (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
+ != (IFF_UP|IFF_BROADCAST))
+ continue;
+ /*
+ * Get its netmask and check that it's on the right subnet.
+ */
+ if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
+ continue;
+ mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr;
+ if ((ipaddr & mask) != (ina & mask))
+ continue;
+
+ break;
+ }
+ }
+
+ if (ifr >= ifend)
+ return 0;
+ info("found interface %s for proxy arp", ifr->ifr_name);
+
+ /*
+ * Now scan through again looking for a link-level address
+ * for this interface.
+ */
+ ifp = ifr;
+ for (ifr = ifc.ifc_req; ifr < ifend; ) {
+ if (strcmp(ifp->ifr_name, ifr->ifr_name) == 0
+ && ifr->ifr_addr.sa_family == AF_LINK) {
+ /*
+ * Found the link-level address - copy it out
+ */
+ dla = (struct sockaddr_dl *) &ifr->ifr_addr;
+ BCOPY(dla, hwaddr, dla->sdl_len);
+ return 1;
+ }
+ ifr = (struct ifreq *) ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len);
+ }
+
+ return 0;
+}
+
+/*
+ * Return user specified netmask, modified by any mask we might determine
+ * for address `addr' (in network byte order).
+ * Here we scan through the system's list of interfaces, looking for
+ * any non-point-to-point interfaces which might appear to be on the same
+ * network as `addr'. If we find any, we OR in their netmask to the
+ * user-specified netmask.
+ */
+u_int32_t
+GetMask(addr)
+ u_int32_t addr;
+{
+ u_int32_t mask, nmask, ina;
+ struct ifreq *ifr, *ifend, ifreq;
+ struct ifconf ifc;
+ struct ifreq ifs[MAX_IFS];
+
+ addr = ntohl(addr);
+ if (IN_CLASSA(addr)) /* determine network mask for address class */
+ nmask = IN_CLASSA_NET;
+ else if (IN_CLASSB(addr))
+ nmask = IN_CLASSB_NET;
+ else
+ nmask = IN_CLASSC_NET;
+ /* class D nets are disallowed by bad_ip_adrs */
+ mask = netmask | htonl(nmask);
+
+ /*
+ * Scan through the system's network interfaces.
+ */
+ ifc.ifc_len = sizeof(ifs);
+ ifc.ifc_req = ifs;
+ if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
+ warn("ioctl(SIOCGIFCONF): %m");
+ return mask;
+ }
+ ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
+ for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *)
+ ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len)) {
+ /*
+ * Check the interface's internet address.
+ */
+ if (ifr->ifr_addr.sa_family != AF_INET)
+ continue;
+ ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
+ if ((ntohl(ina) & nmask) != (addr & nmask))
+ continue;
+ /*
+ * Check that the interface is up, and not point-to-point or loopback.
+ */
+ strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
+ if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
+ continue;
+ if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
+ != IFF_UP)
+ continue;
+ /*
+ * Get its netmask and OR it into our mask.
+ */
+ if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
+ continue;
+ mask |= ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr;
+ }
+
+ return mask;
+}
+
+/*
+ * have_route_to - determine if the system has any route to
+ * a given IP address.
+ * For demand mode to work properly, we have to ignore routes
+ * through our own interface.
+ */
+int have_route_to(u_int32_t addr)
+{
+ return -1;
+}
+
+/*
+ * Use the hostid as part of the random number seed.
+ */
+int
+get_host_seed()
+{
+ return 17;
+}
diff --git a/cpukit/pppd/upap.c b/cpukit/pppd/upap.c
new file mode 100644
index 0000000000..dc6be8a98b
--- /dev/null
+++ b/cpukit/pppd/upap.c
@@ -0,0 +1,638 @@
+/*
+ * upap.c - User/Password Authentication Protocol.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#define RCSID "$Id$"
+
+/*
+ * TODO:
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "pppd.h"
+#include "upap.h"
+
+static const char rcsid[] = RCSID;
+
+static bool hide_password = 1;
+
+/*
+ * Command-line options.
+ */
+static option_t pap_option_list[] = {
+ { "hide-password", o_bool, &hide_password,
+ "Don't output passwords to log", 1 },
+ { "show-password", o_bool, &hide_password,
+ "Show password string in debug log messages", 0 },
+ { "pap-restart", o_int, &upap[0].us_timeouttime,
+ "Set retransmit timeout for PAP" },
+ { "pap-max-authreq", o_int, &upap[0].us_maxtransmits,
+ "Set max number of transmissions for auth-reqs" },
+ { "pap-timeout", o_int, &upap[0].us_reqtimeout,
+ "Set time limit for peer PAP authentication" },
+ { NULL }
+};
+
+/*
+ * Protocol entry points.
+ */
+static void upap_init __P((int));
+static void upap_lowerup __P((int));
+static void upap_lowerdown __P((int));
+static void upap_input __P((int, u_char *, int));
+static void upap_protrej __P((int));
+static int upap_printpkt __P((u_char *, int,
+ void (*) __P((void *, char *, ...)), void *));
+
+struct protent pap_protent = {
+ PPP_PAP,
+ upap_init,
+ upap_input,
+ upap_protrej,
+ upap_lowerup,
+ upap_lowerdown,
+ NULL,
+ NULL,
+ upap_printpkt,
+ NULL,
+ 1,
+ "PAP",
+ NULL,
+ pap_option_list,
+ NULL,
+ NULL,
+ NULL
+};
+
+upap_state upap[NUM_PPP]; /* UPAP state; one for each unit */
+
+static void upap_timeout __P((void *));
+static void upap_reqtimeout __P((void *));
+static void upap_rauthreq __P((upap_state *, u_char *, int, int));
+static void upap_rauthack __P((upap_state *, u_char *, int, int));
+static void upap_rauthnak __P((upap_state *, u_char *, int, int));
+static void upap_sauthreq __P((upap_state *));
+static void upap_sresp __P((upap_state *, u_char, u_char, char *, int));
+
+
+/*
+ * upap_init - Initialize a UPAP unit.
+ */
+static void
+upap_init(unit)
+ int unit;
+{
+ upap_state *u = &upap[unit];
+
+ u->us_unit = unit;
+ u->us_user = NULL;
+ u->us_userlen = 0;
+ u->us_passwd = NULL;
+ u->us_passwdlen = 0;
+ u->us_clientstate = UPAPCS_INITIAL;
+ u->us_serverstate = UPAPSS_INITIAL;
+ u->us_id = 0;
+ u->us_timeouttime = UPAP_DEFTIMEOUT;
+ u->us_maxtransmits = 10;
+ u->us_reqtimeout = UPAP_DEFREQTIME;
+}
+
+
+/*
+ * upap_authwithpeer - Authenticate us with our peer (start client).
+ *
+ * Set new state and send authenticate's.
+ */
+void
+upap_authwithpeer(unit, user, password)
+ int unit;
+ char *user, *password;
+{
+ upap_state *u = &upap[unit];
+
+ /* Save the username and password we're given */
+ u->us_user = user;
+ u->us_userlen = strlen(user);
+ u->us_passwd = password;
+ u->us_passwdlen = strlen(password);
+ u->us_transmits = 0;
+
+ /* Lower layer up yet? */
+ if (u->us_clientstate == UPAPCS_INITIAL ||
+ u->us_clientstate == UPAPCS_PENDING) {
+ u->us_clientstate = UPAPCS_PENDING;
+ return;
+ }
+
+ upap_sauthreq(u); /* Start protocol */
+}
+
+
+/*
+ * upap_authpeer - Authenticate our peer (start server).
+ *
+ * Set new state.
+ */
+void
+upap_authpeer(unit)
+ int unit;
+{
+ upap_state *u = &upap[unit];
+
+ /* Lower layer up yet? */
+ if (u->us_serverstate == UPAPSS_INITIAL ||
+ u->us_serverstate == UPAPSS_PENDING) {
+ u->us_serverstate = UPAPSS_PENDING;
+ return;
+ }
+
+ u->us_serverstate = UPAPSS_LISTEN;
+ if (u->us_reqtimeout > 0)
+ TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout);
+}
+
+
+/*
+ * upap_timeout - Retransmission timer for sending auth-reqs expired.
+ */
+static void
+upap_timeout(arg)
+ void *arg;
+{
+ upap_state *u = (upap_state *) arg;
+
+ if (u->us_clientstate != UPAPCS_AUTHREQ)
+ return;
+
+ if (u->us_transmits >= u->us_maxtransmits) {
+ /* give up in disgust */
+ error("No response to PAP authenticate-requests");
+ u->us_clientstate = UPAPCS_BADAUTH;
+ auth_withpeer_fail(u->us_unit, PPP_PAP);
+ return;
+ }
+
+ upap_sauthreq(u); /* Send Authenticate-Request */
+}
+
+
+/*
+ * upap_reqtimeout - Give up waiting for the peer to send an auth-req.
+ */
+static void
+upap_reqtimeout(arg)
+ void *arg;
+{
+ upap_state *u = (upap_state *) arg;
+
+ if (u->us_serverstate != UPAPSS_LISTEN)
+ return; /* huh?? */
+
+ auth_peer_fail(u->us_unit, PPP_PAP);
+ u->us_serverstate = UPAPSS_BADAUTH;
+}
+
+
+/*
+ * upap_lowerup - The lower layer is up.
+ *
+ * Start authenticating if pending.
+ */
+static void
+upap_lowerup(unit)
+ int unit;
+{
+ upap_state *u = &upap[unit];
+
+ if (u->us_clientstate == UPAPCS_INITIAL)
+ u->us_clientstate = UPAPCS_CLOSED;
+ else if (u->us_clientstate == UPAPCS_PENDING) {
+ upap_sauthreq(u); /* send an auth-request */
+ }
+
+ if (u->us_serverstate == UPAPSS_INITIAL)
+ u->us_serverstate = UPAPSS_CLOSED;
+ else if (u->us_serverstate == UPAPSS_PENDING) {
+ u->us_serverstate = UPAPSS_LISTEN;
+ if (u->us_reqtimeout > 0)
+ TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout);
+ }
+}
+
+
+/*
+ * upap_lowerdown - The lower layer is down.
+ *
+ * Cancel all timeouts.
+ */
+static void
+upap_lowerdown(unit)
+ int unit;
+{
+ upap_state *u = &upap[unit];
+
+ if (u->us_clientstate == UPAPCS_AUTHREQ) /* Timeout pending? */
+ UNTIMEOUT(upap_timeout, u); /* Cancel timeout */
+ if (u->us_serverstate == UPAPSS_LISTEN && u->us_reqtimeout > 0)
+ UNTIMEOUT(upap_reqtimeout, u);
+
+ u->us_clientstate = UPAPCS_INITIAL;
+ u->us_serverstate = UPAPSS_INITIAL;
+}
+
+
+/*
+ * upap_protrej - Peer doesn't speak this protocol.
+ *
+ * This shouldn't happen. In any case, pretend lower layer went down.
+ */
+static void
+upap_protrej(unit)
+ int unit;
+{
+ upap_state *u = &upap[unit];
+
+ if (u->us_clientstate == UPAPCS_AUTHREQ) {
+ error("PAP authentication failed due to protocol-reject");
+ auth_withpeer_fail(unit, PPP_PAP);
+ }
+ if (u->us_serverstate == UPAPSS_LISTEN) {
+ error("PAP authentication of peer failed (protocol-reject)");
+ auth_peer_fail(unit, PPP_PAP);
+ }
+ upap_lowerdown(unit);
+}
+
+
+/*
+ * upap_input - Input UPAP packet.
+ */
+static void
+upap_input(unit, inpacket, l)
+ int unit;
+ u_char *inpacket;
+ int l;
+{
+ upap_state *u = &upap[unit];
+ u_char *inp;
+ u_char code, id;
+ int len;
+
+ /*
+ * Parse header (code, id and length).
+ * If packet too short, drop it.
+ */
+ inp = inpacket;
+ if (l < UPAP_HEADERLEN) {
+ UPAPDEBUG(("pap_input: rcvd short header."));
+ return;
+ }
+ GETCHAR(code, inp);
+ GETCHAR(id, inp);
+ GETSHORT(len, inp);
+ if (len < UPAP_HEADERLEN) {
+ UPAPDEBUG(("pap_input: rcvd illegal length."));
+ return;
+ }
+ if (len > l) {
+ UPAPDEBUG(("pap_input: rcvd short packet."));
+ return;
+ }
+ len -= UPAP_HEADERLEN;
+
+ /*
+ * Action depends on code.
+ */
+ switch (code) {
+ case UPAP_AUTHREQ:
+ upap_rauthreq(u, inp, id, len);
+ break;
+
+ case UPAP_AUTHACK:
+ upap_rauthack(u, inp, id, len);
+ break;
+
+ case UPAP_AUTHNAK:
+ upap_rauthnak(u, inp, id, len);
+ break;
+
+ default: /* XXX Need code reject */
+ break;
+ }
+}
+
+
+/*
+ * upap_rauth - Receive Authenticate.
+ */
+static void
+upap_rauthreq(u, inp, id, len)
+ upap_state *u;
+ u_char *inp;
+ int id;
+ int len;
+{
+ u_char ruserlen, rpasswdlen;
+ char *ruser, *rpasswd;
+ int retcode;
+ char *msg;
+ int msglen;
+
+ if (u->us_serverstate < UPAPSS_LISTEN)
+ return;
+
+ /*
+ * If we receive a duplicate authenticate-request, we are
+ * supposed to return the same status as for the first request.
+ */
+ if (u->us_serverstate == UPAPSS_OPEN) {
+ upap_sresp(u, UPAP_AUTHACK, id, "", 0); /* return auth-ack */
+ return;
+ }
+ if (u->us_serverstate == UPAPSS_BADAUTH) {
+ upap_sresp(u, UPAP_AUTHNAK, id, "", 0); /* return auth-nak */
+ return;
+ }
+
+ /*
+ * Parse user/passwd.
+ */
+ if (len < 1) {
+ UPAPDEBUG(("pap_rauth: rcvd short packet."));
+ return;
+ }
+ GETCHAR(ruserlen, inp);
+ len -= sizeof (u_char) + ruserlen + sizeof (u_char);
+ if (len < 0) {
+ UPAPDEBUG(("pap_rauth: rcvd short packet."));
+ return;
+ }
+ ruser = (char *) inp;
+ INCPTR(ruserlen, inp);
+ GETCHAR(rpasswdlen, inp);
+ if (len < rpasswdlen) {
+ UPAPDEBUG(("pap_rauth: rcvd short packet."));
+ return;
+ }
+ rpasswd = (char *) inp;
+
+ /*
+ * Check the username and password given.
+ */
+ retcode = check_passwd(u->us_unit, ruser, ruserlen, rpasswd,
+ rpasswdlen, &msg);
+ BZERO(rpasswd, rpasswdlen);
+ msglen = strlen(msg);
+ if (msglen > 255)
+ msglen = 255;
+
+ upap_sresp(u, retcode, id, msg, msglen);
+
+ if (retcode == UPAP_AUTHACK) {
+ u->us_serverstate = UPAPSS_OPEN;
+ auth_peer_success(u->us_unit, PPP_PAP, ruser, ruserlen);
+ } else {
+ u->us_serverstate = UPAPSS_BADAUTH;
+ auth_peer_fail(u->us_unit, PPP_PAP);
+ }
+
+ if (u->us_reqtimeout > 0)
+ UNTIMEOUT(upap_reqtimeout, u);
+}
+
+
+/*
+ * upap_rauthack - Receive Authenticate-Ack.
+ */
+static void
+upap_rauthack(u, inp, id, len)
+ upap_state *u;
+ u_char *inp;
+ int id;
+ int len;
+{
+ u_char msglen;
+ char *msg;
+
+ if (u->us_clientstate != UPAPCS_AUTHREQ) /* XXX */
+ return;
+
+ /*
+ * Parse message.
+ */
+ if (len < 1) {
+ UPAPDEBUG(("pap_rauthack: ignoring missing msg-length."));
+ } else {
+ GETCHAR(msglen, inp);
+ if (msglen > 0) {
+ len -= sizeof (u_char);
+ if (len < msglen) {
+ UPAPDEBUG(("pap_rauthack: rcvd short packet."));
+ return;
+ }
+ msg = (char *) inp;
+ PRINTMSG(msg, msglen);
+ }
+ }
+
+ u->us_clientstate = UPAPCS_OPEN;
+
+ auth_withpeer_success(u->us_unit, PPP_PAP);
+}
+
+
+/*
+ * upap_rauthnak - Receive Authenticate-Nakk.
+ */
+static void
+upap_rauthnak(u, inp, id, len)
+ upap_state *u;
+ u_char *inp;
+ int id;
+ int len;
+{
+ u_char msglen;
+ char *msg;
+
+ if (u->us_clientstate != UPAPCS_AUTHREQ) /* XXX */
+ return;
+
+ /*
+ * Parse message.
+ */
+ if (len < 1) {
+ UPAPDEBUG(("pap_rauthnak: ignoring missing msg-length."));
+ } else {
+ GETCHAR(msglen, inp);
+ if (msglen > 0) {
+ len -= sizeof (u_char);
+ if (len < msglen) {
+ UPAPDEBUG(("pap_rauthnak: rcvd short packet."));
+ return;
+ }
+ msg = (char *) inp;
+ PRINTMSG(msg, msglen);
+ }
+ }
+
+ u->us_clientstate = UPAPCS_BADAUTH;
+
+ error("PAP authentication failed");
+ auth_withpeer_fail(u->us_unit, PPP_PAP);
+}
+
+
+/*
+ * upap_sauthreq - Send an Authenticate-Request.
+ */
+static void
+upap_sauthreq(u)
+ upap_state *u;
+{
+ u_char *outp;
+ int outlen;
+
+ outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) +
+ u->us_userlen + u->us_passwdlen;
+ outp = outpacket_buf;
+
+ MAKEHEADER(outp, PPP_PAP);
+
+ PUTCHAR(UPAP_AUTHREQ, outp);
+ PUTCHAR(++u->us_id, outp);
+ PUTSHORT(outlen, outp);
+ PUTCHAR(u->us_userlen, outp);
+ BCOPY(u->us_user, outp, u->us_userlen);
+ INCPTR(u->us_userlen, outp);
+ PUTCHAR(u->us_passwdlen, outp);
+ BCOPY(u->us_passwd, outp, u->us_passwdlen);
+
+ output(u->us_unit, outpacket_buf, outlen + PPP_HDRLEN);
+
+ TIMEOUT(upap_timeout, u, u->us_timeouttime);
+ ++u->us_transmits;
+ u->us_clientstate = UPAPCS_AUTHREQ;
+}
+
+
+/*
+ * upap_sresp - Send a response (ack or nak).
+ */
+static void
+upap_sresp(u, code, id, msg, msglen)
+ upap_state *u;
+ u_char code, id;
+ char *msg;
+ int msglen;
+{
+ u_char *outp;
+ int outlen;
+
+ outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen;
+ outp = outpacket_buf;
+ MAKEHEADER(outp, PPP_PAP);
+
+ PUTCHAR(code, outp);
+ PUTCHAR(id, outp);
+ PUTSHORT(outlen, outp);
+ PUTCHAR(msglen, outp);
+ BCOPY(msg, outp, msglen);
+ output(u->us_unit, outpacket_buf, outlen + PPP_HDRLEN);
+}
+
+/*
+ * upap_printpkt - print the contents of a PAP packet.
+ */
+static char *upap_codenames[] = {
+ "AuthReq", "AuthAck", "AuthNak"
+};
+
+static int
+upap_printpkt(p, plen, printer, arg)
+ u_char *p;
+ int plen;
+ void (*printer) __P((void *, char *, ...));
+ void *arg;
+{
+ int code, id, len;
+ int mlen, ulen, wlen;
+ char *user, *pwd, *msg;
+ u_char *pstart;
+
+ if (plen < UPAP_HEADERLEN)
+ return 0;
+ pstart = p;
+ GETCHAR(code, p);
+ GETCHAR(id, p);
+ GETSHORT(len, p);
+ if (len < UPAP_HEADERLEN || len > plen)
+ return 0;
+
+ if (code >= 1 && code <= sizeof(upap_codenames) / sizeof(char *))
+ printer(arg, " %s", upap_codenames[code-1]);
+ else
+ printer(arg, " code=0x%x", code);
+ printer(arg, " id=0x%x", id);
+ len -= UPAP_HEADERLEN;
+ switch (code) {
+ case UPAP_AUTHREQ:
+ if (len < 1)
+ break;
+ ulen = p[0];
+ if (len < ulen + 2)
+ break;
+ wlen = p[ulen + 1];
+ if (len < ulen + wlen + 2)
+ break;
+ user = (char *) (p + 1);
+ pwd = (char *) (p + ulen + 2);
+ p += ulen + wlen + 2;
+ len -= ulen + wlen + 2;
+ printer(arg, " user=");
+ print_string(user, ulen, printer, arg);
+ printer(arg, " password=");
+ if (!hide_password)
+ print_string(pwd, wlen, printer, arg);
+ else
+ printer(arg, "<hidden>");
+ break;
+ case UPAP_AUTHACK:
+ case UPAP_AUTHNAK:
+ if (len < 1)
+ break;
+ mlen = p[0];
+ if (len < mlen + 1)
+ break;
+ msg = (char *) (p + 1);
+ p += mlen + 1;
+ len -= mlen + 1;
+ printer(arg, " ");
+ print_string(msg, mlen, printer, arg);
+ break;
+ }
+
+ /* print the rest of the bytes in the packet */
+ for (; len > 0; --len) {
+ GETCHAR(code, p);
+ printer(arg, " %.2x", code);
+ }
+
+ return p - pstart;
+}
diff --git a/cpukit/pppd/upap.h b/cpukit/pppd/upap.h
new file mode 100644
index 0000000000..6d5bf64026
--- /dev/null
+++ b/cpukit/pppd/upap.h
@@ -0,0 +1,87 @@
+/*
+ * upap.h - User/Password Authentication Protocol definitions.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * $Id$
+ */
+
+/*
+ * Packet header = Code, id, length.
+ */
+#define UPAP_HEADERLEN 4
+
+
+/*
+ * UPAP codes.
+ */
+#define UPAP_AUTHREQ 1 /* Authenticate-Request */
+#define UPAP_AUTHACK 2 /* Authenticate-Ack */
+#define UPAP_AUTHNAK 3 /* Authenticate-Nak */
+
+
+/*
+ * Each interface is described by upap structure.
+ */
+typedef struct upap_state {
+ int us_unit; /* Interface unit number */
+ char *us_user; /* User */
+ int us_userlen; /* User length */
+ char *us_passwd; /* Password */
+ int us_passwdlen; /* Password length */
+ int us_clientstate; /* Client state */
+ int us_serverstate; /* Server state */
+ u_char us_id; /* Current id */
+ int us_timeouttime; /* Timeout (seconds) for auth-req retrans. */
+ int us_transmits; /* Number of auth-reqs sent */
+ int us_maxtransmits; /* Maximum number of auth-reqs to send */
+ int us_reqtimeout; /* Time to wait for auth-req from peer */
+} upap_state;
+
+
+/*
+ * Client states.
+ */
+#define UPAPCS_INITIAL 0 /* Connection down */
+#define UPAPCS_CLOSED 1 /* Connection up, haven't requested auth */
+#define UPAPCS_PENDING 2 /* Connection down, have requested auth */
+#define UPAPCS_AUTHREQ 3 /* We've sent an Authenticate-Request */
+#define UPAPCS_OPEN 4 /* We've received an Ack */
+#define UPAPCS_BADAUTH 5 /* We've received a Nak */
+
+/*
+ * Server states.
+ */
+#define UPAPSS_INITIAL 0 /* Connection down */
+#define UPAPSS_CLOSED 1 /* Connection up, haven't requested auth */
+#define UPAPSS_PENDING 2 /* Connection down, have requested auth */
+#define UPAPSS_LISTEN 3 /* Listening for an Authenticate */
+#define UPAPSS_OPEN 4 /* We've sent an Ack */
+#define UPAPSS_BADAUTH 5 /* We've sent a Nak */
+
+
+/*
+ * Timeouts.
+ */
+#define UPAP_DEFTIMEOUT 5 /* Timeout (seconds) for retransmitting req */
+#define UPAP_DEFREQTIME 30 /* Time to wait for auth-req from peer */
+
+extern upap_state upap[];
+
+void upap_authwithpeer __P((int, char *, char *));
+void upap_authpeer __P((int));
+
+extern struct protent pap_protent;
diff --git a/cpukit/pppd/utils.c b/cpukit/pppd/utils.c
new file mode 100644
index 0000000000..6a399385e7
--- /dev/null
+++ b/cpukit/pppd/utils.c
@@ -0,0 +1,832 @@
+/*
+ * utils.c - various utility functions used in pppd.
+ *
+ * Copyright (c) 1999 The Australian National University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the Australian National University. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#define RCSID "$Id$"
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <syslog.h>
+#include <pwd.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#ifdef SVR4
+#include <sys/mkdev.h>
+#endif
+
+#include "pppd.h"
+
+static const char rcsid[] = RCSID;
+
+#if defined(SUNOS4)
+extern char *strerror();
+#endif
+
+static void pr_log __P((void *, char *, ...));
+static void logit __P((int, char *, va_list));
+static void vslp_printer __P((void *, char *, ...));
+static void format_packet __P((u_char *, int, void (*) (void *, char *, ...),
+ void *));
+
+struct buffer_info {
+ char *ptr;
+ int len;
+};
+
+/*
+ * slprintf - format a message into a buffer. Like sprintf except we
+ * also specify the length of the output buffer, and we handle
+ * %r (recursive format), %m (error message), %v (visible string),
+ * %q (quoted string), %t (current time) and %I (IP address) formats.
+ * Doesn't do floating-point formats.
+ * Returns the number of chars put into buf.
+ */
+int
+slprintf __V((char *buf, int buflen, char *fmt, ...))
+{
+ va_list args;
+ int n;
+
+#if defined(__STDC__)
+ va_start(args, fmt);
+#else
+ char *buf;
+ int buflen;
+ char *fmt;
+ va_start(args);
+ buf = va_arg(args, char *);
+ buflen = va_arg(args, int);
+ fmt = va_arg(args, char *);
+#endif
+ n = vslprintf(buf, buflen, fmt, args);
+ va_end(args);
+ return n;
+}
+
+/*
+ * vslprintf - like slprintf, takes a va_list instead of a list of args.
+ */
+#define OUTCHAR(c) (buflen > 0? (--buflen, *buf++ = (c)): 0)
+
+int
+vslprintf(buf, buflen, fmt, args)
+ char *buf;
+ int buflen;
+ char *fmt;
+ va_list args;
+{
+ int c, i, n;
+ int width, prec, fillch;
+ int base, len, neg, quoted;
+ unsigned long val = 0;
+ char *str, *f, *buf0;
+ unsigned char *p;
+ char num[32];
+ time_t t;
+ u_int32_t ip;
+ static char hexchars[] = "0123456789abcdef";
+ struct buffer_info bufinfo;
+
+ buf0 = buf;
+ --buflen;
+ while (buflen > 0) {
+ for (f = fmt; *f != '%' && *f != 0; ++f)
+ ;
+ if (f > fmt) {
+ len = f - fmt;
+ if (len > buflen)
+ len = buflen;
+ memcpy(buf, fmt, len);
+ buf += len;
+ buflen -= len;
+ fmt = f;
+ }
+ if (*fmt == 0)
+ break;
+ c = *++fmt;
+ width = 0;
+ prec = -1;
+ fillch = ' ';
+ if (c == '0') {
+ fillch = '0';
+ c = *++fmt;
+ }
+ if (c == '*') {
+ width = va_arg(args, int);
+ c = *++fmt;
+ } else {
+ while (isdigit(c)) {
+ width = width * 10 + c - '0';
+ c = *++fmt;
+ }
+ }
+ if (c == '.') {
+ c = *++fmt;
+ if (c == '*') {
+ prec = va_arg(args, int);
+ c = *++fmt;
+ } else {
+ prec = 0;
+ while (isdigit(c)) {
+ prec = prec * 10 + c - '0';
+ c = *++fmt;
+ }
+ }
+ }
+ str = 0;
+ base = 0;
+ neg = 0;
+ ++fmt;
+ switch (c) {
+ case 'd':
+ i = va_arg(args, int);
+ if (i < 0) {
+ neg = 1;
+ val = -i;
+ } else
+ val = i;
+ base = 10;
+ break;
+ case 'o':
+ val = va_arg(args, unsigned int);
+ base = 8;
+ break;
+ case 'x':
+ case 'X':
+ val = va_arg(args, unsigned int);
+ base = 16;
+ break;
+ case 'p':
+ val = (unsigned long) va_arg(args, void *);
+ base = 16;
+ neg = 2;
+ break;
+ case 's':
+ str = va_arg(args, char *);
+ break;
+ case 'c':
+ num[0] = va_arg(args, int);
+ num[1] = 0;
+ str = num;
+ break;
+ case 'm':
+ str = strerror(errno);
+ break;
+ case 'I':
+ ip = va_arg(args, u_int32_t);
+ ip = ntohl(ip);
+ slprintf(num, sizeof(num), "%d.%d.%d.%d", (ip >> 24) & 0xff,
+ (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff);
+ str = num;
+ break;
+ case 'r':
+ f = va_arg(args, char *);
+#if !defined(__PPC__) && !defined(__i960__)
+ n = vslprintf(buf, buflen + 1, f, va_arg(args, va_list));
+#else
+ /* HACK: On the powerpc, a va_list is an array of 1 structure */
+ n = vslprintf(buf, buflen + 1, f, va_arg(args, void *));
+#endif
+ buf += n;
+ buflen -= n;
+ continue;
+ case 't':
+ time(&t);
+ str = ctime(&t);
+ str += 4; /* chop off the day name */
+ str[15] = 0; /* chop off year and newline */
+ break;
+ case 'v': /* "visible" string */
+ case 'q': /* quoted string */
+ quoted = c == 'q';
+ p = va_arg(args, unsigned char *);
+ if (fillch == '0' && prec >= 0) {
+ n = prec;
+ } else {
+ n = strlen((char *)p);
+ if (prec >= 0 && n > prec)
+ n = prec;
+ }
+ while (n > 0 && buflen > 0) {
+ c = *p++;
+ --n;
+ if (!quoted && c >= 0x80) {
+ OUTCHAR('M');
+ OUTCHAR('-');
+ c -= 0x80;
+ }
+ if (quoted && (c == '"' || c == '\\'))
+ OUTCHAR('\\');
+ if (c < 0x20 || (0x7f <= c && c < 0xa0)) {
+ if (quoted) {
+ OUTCHAR('\\');
+ switch (c) {
+ case '\t': OUTCHAR('t'); break;
+ case '\n': OUTCHAR('n'); break;
+ case '\b': OUTCHAR('b'); break;
+ case '\f': OUTCHAR('f'); break;
+ default:
+ OUTCHAR('x');
+ OUTCHAR(hexchars[c >> 4]);
+ OUTCHAR(hexchars[c & 0xf]);
+ }
+ } else {
+ if (c == '\t')
+ OUTCHAR(c);
+ else {
+ OUTCHAR('^');
+ OUTCHAR(c ^ 0x40);
+ }
+ }
+ } else
+ OUTCHAR(c);
+ }
+ continue;
+ case 'P': /* print PPP packet */
+ bufinfo.ptr = buf;
+ bufinfo.len = buflen + 1;
+ p = va_arg(args, unsigned char *);
+ n = va_arg(args, int);
+ format_packet(p, n, vslp_printer, &bufinfo);
+ buf = bufinfo.ptr;
+ buflen = bufinfo.len - 1;
+ continue;
+ case 'B':
+ p = va_arg(args, unsigned char *);
+ for (n = prec; n > 0; --n) {
+ c = *p++;
+ if (fillch == ' ')
+ OUTCHAR(' ');
+ OUTCHAR(hexchars[(c >> 4) & 0xf]);
+ OUTCHAR(hexchars[c & 0xf]);
+ }
+ continue;
+ default:
+ *buf++ = '%';
+ if (c != '%')
+ --fmt; /* so %z outputs %z etc. */
+ --buflen;
+ continue;
+ }
+ if (base != 0) {
+ str = num + sizeof(num);
+ *--str = 0;
+ while (str > num + neg) {
+ *--str = hexchars[val % base];
+ val = val / base;
+ if (--prec <= 0 && val == 0)
+ break;
+ }
+ switch (neg) {
+ case 1:
+ *--str = '-';
+ break;
+ case 2:
+ *--str = 'x';
+ *--str = '0';
+ break;
+ }
+ len = num + sizeof(num) - 1 - str;
+ } else {
+ len = strlen(str);
+ if (prec >= 0 && len > prec)
+ len = prec;
+ }
+ if (width > 0) {
+ if (width > buflen)
+ width = buflen;
+ if ((n = width - len) > 0) {
+ buflen -= n;
+ for (; n > 0; --n)
+ *buf++ = fillch;
+ }
+ }
+ if (len > buflen)
+ len = buflen;
+ memcpy(buf, str, len);
+ buf += len;
+ buflen -= len;
+ }
+ *buf = 0;
+ return buf - buf0;
+}
+
+/*
+ * vslp_printer - used in processing a %P format
+ */
+static void
+vslp_printer __V((void *arg, char *fmt, ...))
+{
+ int n;
+ va_list pvar;
+ struct buffer_info *bi;
+
+#if defined(__STDC__)
+ va_start(pvar, fmt);
+#else
+ void *arg;
+ char *fmt;
+ va_start(pvar);
+ arg = va_arg(pvar, void *);
+ fmt = va_arg(pvar, char *);
+#endif
+
+ bi = (struct buffer_info *) arg;
+ n = vslprintf(bi->ptr, bi->len, fmt, pvar);
+ va_end(pvar);
+
+ bi->ptr += n;
+ bi->len -= n;
+}
+
+/*
+ * log_packet - format a packet and log it.
+ */
+
+char line[256]; /* line to be logged accumulated here */
+char *linep;
+
+void
+log_packet(p, len, prefix, level)
+ u_char *p;
+ int len;
+ char *prefix;
+ int level;
+{
+ strlcpy(line, prefix, sizeof(line));
+ linep = line + strlen(line);
+ format_packet(p, len, pr_log, NULL);
+}
+
+/*
+ * format_packet - make a readable representation of a packet,
+ * calling `printer(arg, format, ...)' to output it.
+ */
+static void
+format_packet(p, len, printer, arg)
+ u_char *p;
+ int len;
+ void (*printer) __P((void *, char *, ...));
+ void *arg;
+{
+ int i, n;
+ u_short proto;
+ struct protent *protp;
+
+ if (len >= PPP_HDRLEN && p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) {
+ p += 2;
+ GETSHORT(proto, p);
+ len -= PPP_HDRLEN;
+ for (i = 0; (protp = protocols[i]) != NULL; ++i)
+ if (proto == protp->protocol)
+ break;
+ if (protp != NULL) {
+ printer(arg, "[%s", protp->name);
+ n = (*protp->printpkt)(p, len, printer, arg);
+ printer(arg, "]");
+ p += n;
+ len -= n;
+ } else {
+ for (i = 0; (protp = protocols[i]) != NULL; ++i)
+ if (proto == (protp->protocol & ~0x8000))
+ break;
+ if (protp != 0 && protp->data_name != 0) {
+ printer(arg, "[%s data]", protp->data_name);
+ if (len > 8)
+ printer(arg, "%.8B ...", p);
+ else
+ printer(arg, "%.*B", len, p);
+ len = 0;
+ } else
+ printer(arg, "[proto=0x%x]", proto);
+ }
+ }
+
+ if (len > 32)
+ printer(arg, "%.32B ...", p);
+ else
+ printer(arg, "%.*B", len, p);
+}
+
+static void
+pr_log __V((void *arg, char *fmt, ...))
+{
+ int n;
+ va_list pvar;
+ char buf[256];
+
+#if defined(__STDC__)
+ va_start(pvar, fmt);
+#else
+ void *arg;
+ char *fmt;
+ va_start(pvar);
+ arg = va_arg(pvar, void *);
+ fmt = va_arg(pvar, char *);
+#endif
+
+ n = vslprintf(buf, sizeof(buf), fmt, pvar);
+ va_end(pvar);
+
+ if (linep + n + 1 > line + sizeof(line)) {
+ linep = line;
+ }
+ strlcpy(linep, buf, line + sizeof(line) - linep);
+ linep += n;
+}
+
+/*
+ * print_string - print a readable representation of a string using
+ * printer.
+ */
+void
+print_string(p, len, printer, arg)
+ char *p;
+ int len;
+ void (*printer) __P((void *, char *, ...));
+ void *arg;
+{
+ int c;
+
+ printer(arg, "\"");
+ for (; len > 0; --len) {
+ c = *p++;
+ if (' ' <= c && c <= '~') {
+ if (c == '\\' || c == '"')
+ printer(arg, "\\");
+ printer(arg, "%c", c);
+ } else {
+ switch (c) {
+ case '\n':
+ printer(arg, "\\n");
+ break;
+ case '\r':
+ printer(arg, "\\r");
+ break;
+ case '\t':
+ printer(arg, "\\t");
+ break;
+ default:
+ printer(arg, "\\%.3o", c);
+ }
+ }
+ }
+ printer(arg, "\"");
+}
+
+/*
+ * logit - does the hard work for fatal et al.
+ */
+static void
+logit(level, fmt, args)
+ int level;
+ char *fmt;
+ va_list args;
+{
+ int n;
+ char buf[256];
+
+ n = vslprintf(buf, sizeof(buf), fmt, args);
+/* if (log_to_fd >= 0 && (level != LOG_DEBUG || debug)) { */
+ if (log_to_fd >= 0 && (debug)) {
+ if (buf[n-1] != '\n')
+ buf[n++] = '\n';
+ if (write(log_to_fd, buf, n) != n)
+ log_to_fd = -1;
+ }
+}
+
+/*
+ * fatal - log an error message and die horribly.
+ */
+void
+pppd_fatal __V((char *fmt, ...))
+{
+ va_list pvar;
+
+#if defined(__STDC__)
+ va_start(pvar, fmt);
+#else
+ char *fmt;
+ va_start(pvar);
+ fmt = va_arg(pvar, char *);
+#endif
+
+ logit(LOG_ERR, fmt, pvar);
+ va_end(pvar);
+
+ die(1); /* as promised */
+}
+
+/*
+ * error - log an error message.
+ */
+void
+pppd_error __V((char *fmt, ...))
+{
+ va_list pvar;
+
+#if defined(__STDC__)
+ va_start(pvar, fmt);
+#else
+ char *fmt;
+ va_start(pvar);
+ fmt = va_arg(pvar, char *);
+#endif
+
+ logit(LOG_ERR, fmt, pvar);
+ va_end(pvar);
+}
+
+/*
+ * warn - log a warning message.
+ */
+void
+pppd_warn __V((char *fmt, ...))
+{
+ va_list pvar;
+
+#if defined(__STDC__)
+ va_start(pvar, fmt);
+#else
+ char *fmt;
+ va_start(pvar);
+ fmt = va_arg(pvar, char *);
+#endif
+
+ logit(LOG_WARNING, fmt, pvar);
+ va_end(pvar);
+}
+
+/*
+ * notice - log a notice-level message.
+ */
+void
+pppd_notice __V((char *fmt, ...))
+{
+ va_list pvar;
+
+#if defined(__STDC__)
+ va_start(pvar, fmt);
+#else
+ char *fmt;
+ va_start(pvar);
+ fmt = va_arg(pvar, char *);
+#endif
+
+ logit(LOG_NOTICE, fmt, pvar);
+ va_end(pvar);
+}
+
+/*
+ * info - log an informational message.
+ */
+void
+pppd_info __V((char *fmt, ...))
+{
+ va_list pvar;
+
+#if defined(__STDC__)
+ va_start(pvar, fmt);
+#else
+ char *fmt;
+ va_start(pvar);
+ fmt = va_arg(pvar, char *);
+#endif
+
+ logit(LOG_INFO, fmt, pvar);
+ va_end(pvar);
+}
+
+/*
+ * dbglog - log a debug message.
+ */
+void
+pppd_dbglog __V((char *fmt, ...))
+{
+ va_list pvar;
+
+#if defined(__STDC__)
+ va_start(pvar, fmt);
+#else
+ char *fmt;
+ va_start(pvar);
+ fmt = va_arg(pvar, char *);
+#endif
+
+ logit(LOG_DEBUG, fmt, pvar);
+ va_end(pvar);
+}
+
+/* Procedures for locking the serial device using a lock file. */
+#ifndef LOCK_DIR
+#ifdef _linux_
+#define LOCK_DIR "/var/lock"
+#else
+#ifdef SVR4
+#define LOCK_DIR "/var/spool/locks"
+#else
+#define LOCK_DIR "/var/spool/lock"
+#endif
+#endif
+#endif /* LOCK_DIR */
+
+static char lock_file[MAXPATHLEN];
+
+/*
+ * lock - create a lock file for the named device
+ */
+int
+lock(dev)
+ char *dev;
+{
+#ifdef LOCKLIB
+ int result;
+
+ result = mklock (dev, (void *) 0);
+ if (result == 0) {
+ strlcpy(lock_file, sizeof(lock_file), dev);
+ return 0;
+ }
+
+ if (result > 0)
+ notice("Device %s is locked by pid %d", dev, result);
+ else
+ error("Can't create lock file %s", lock_file);
+ return -1;
+
+#else /* LOCKLIB */
+
+ char lock_buffer[12];
+ int fd, pid, n;
+
+#ifdef SVR4
+ struct stat sbuf;
+
+ if (stat(dev, &sbuf) < 0) {
+ error("Can't get device number for %s: %m", dev);
+ return -1;
+ }
+ if ((sbuf.st_mode & S_IFMT) != S_IFCHR) {
+ error("Can't lock %s: not a character device", dev);
+ return -1;
+ }
+ slprintf(lock_file, sizeof(lock_file), "%s/LK.%03d.%03d.%03d",
+ LOCK_DIR, major(sbuf.st_dev),
+ major(sbuf.st_rdev), minor(sbuf.st_rdev));
+#else
+ char *p;
+
+ if ((p = strrchr(dev, '/')) != NULL)
+ dev = p + 1;
+ slprintf(lock_file, sizeof(lock_file), "%s/LCK..%s", LOCK_DIR, dev);
+#endif
+
+ while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
+ if (errno != EEXIST) {
+ error("Can't create lock file %s: %m", lock_file);
+ break;
+ }
+
+ /* Read the lock file to find out who has the device locked. */
+ fd = open(lock_file, O_RDONLY, 0);
+ if (fd < 0) {
+ if (errno == ENOENT) /* This is just a timing problem. */
+ continue;
+ error("Can't open existing lock file %s: %m", lock_file);
+ break;
+ }
+#ifndef LOCK_BINARY
+ n = read(fd, lock_buffer, 11);
+#else
+ n = read(fd, &pid, sizeof(pid));
+#endif /* LOCK_BINARY */
+ close(fd);
+ fd = -1;
+ if (n <= 0) {
+ error("Can't read pid from lock file %s", lock_file);
+ break;
+ }
+
+ /* See if the process still exists. */
+#ifndef LOCK_BINARY
+ lock_buffer[n] = 0;
+ pid = atoi(lock_buffer);
+#endif /* LOCK_BINARY */
+ if (pid == getpid())
+ return 1; /* somebody else locked it for us */
+ if (pid == 0
+ || (kill(pid, 0) == -1 && errno == ESRCH)) {
+ if (unlink (lock_file) == 0) {
+ notice("Removed stale lock on %s (pid %d)", dev, pid);
+ continue;
+ }
+ warn("Couldn't remove stale lock on %s", dev);
+ } else
+ notice("Device %s is locked by pid %d", dev, pid);
+ break;
+ }
+
+ if (fd < 0) {
+ lock_file[0] = 0;
+ return -1;
+ }
+
+ pid = getpid();
+#ifndef LOCK_BINARY
+ slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid);
+ write (fd, lock_buffer, 11);
+#else
+ write(fd, &pid, sizeof (pid));
+#endif
+ close(fd);
+ return 0;
+
+#endif
+}
+
+/*
+ * relock - called to update our lockfile when we are about to detach,
+ * thus changing our pid (we fork, the child carries on, and the parent dies).
+ * Note that this is called by the parent, with pid equal to the pid
+ * of the child. This avoids a potential race which would exist if
+ * we had the child rewrite the lockfile (the parent might die first,
+ * and another process could think the lock was stale if it checked
+ * between when the parent died and the child rewrote the lockfile).
+ */
+int
+relock(pid)
+ int pid;
+{
+#ifdef LOCKLIB
+ /* XXX is there a way to do this? */
+ return -1;
+#else /* LOCKLIB */
+
+ int fd;
+ char lock_buffer[12];
+
+ if (lock_file[0] == 0)
+ return -1;
+ fd = open(lock_file, O_WRONLY, 0);
+ if (fd < 0) {
+ error("Couldn't reopen lock file %s: %m", lock_file);
+ lock_file[0] = 0;
+ return -1;
+ }
+
+#ifndef LOCK_BINARY
+ slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid);
+ write (fd, lock_buffer, 11);
+#else
+ write(fd, &pid, sizeof(pid));
+#endif /* LOCK_BINARY */
+ close(fd);
+ return 0;
+
+#endif /* LOCKLIB */
+}
+
+/*
+ * unlock - remove our lockfile
+ */
+void
+unlock()
+{
+ if (lock_file[0]) {
+#ifdef LOCKLIB
+ (void) rmlock(lock_file, (void *) 0);
+#else
+ unlink(lock_file);
+#endif
+ lock_file[0] = 0;
+ }
+}
diff --git a/cpukit/rtems/.cvsignore b/cpukit/rtems/.cvsignore
new file mode 100644
index 0000000000..282522db03
--- /dev/null
+++ b/cpukit/rtems/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/cpukit/rtems/Makefile.am b/cpukit/rtems/Makefile.am
new file mode 100644
index 0000000000..35f89a6a80
--- /dev/null
+++ b/cpukit/rtems/Makefile.am
@@ -0,0 +1,411 @@
+##
+## $Id$
+##
+
+include $(top_srcdir)/automake/multilib.am
+include $(top_srcdir)/automake/compile.am
+
+AM_CPPFLAGS += -I$(top_builddir)
+AM_CPPFLAGS += -D__RTEMS_INSIDE__
+
+EXTRA_LIBRARIES = librtems.a
+CLEANFILES = librtems.a
+librtems_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += librtems_g.a
+CLEANFILES += librtems_g.a
+librtems_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+# include
+
+include_HEADERS = include/rtems.h
+
+# include/rtems/rtems
+include_rtems_rtemsdir = $(includedir)/rtems/rtems
+
+include_rtems_rtems_HEADERS = include/rtems/rtems/asr.h \
+ include/rtems/rtems/attr.h include/rtems/rtems/cache.h \
+ include/rtems/rtems/clock.h include/rtems/rtems/config.h \
+ include/rtems/rtems/dpmem.h include/rtems/rtems/event.h \
+ include/rtems/rtems/eventset.h include/rtems/rtems/intr.h \
+ include/rtems/rtems/message.h include/rtems/rtems/modes.h \
+ include/rtems/rtems/options.h include/rtems/rtems/part.h \
+ include/rtems/rtems/ratemon.h include/rtems/rtems/region.h \
+ include/rtems/rtems/rtemsapi.h include/rtems/rtems/sem.h \
+ include/rtems/rtems/signal.h include/rtems/rtems/status.h \
+ include/rtems/rtems/support.h include/rtems/rtems/tasks.h \
+ include/rtems/rtems/timer.h include/rtems/rtems/types.h
+
+if HAS_MP
+## We only build multiprocessing related files if HAS_MP was defined
+include_rtems_rtems_HEADERS += include/rtems/rtems/eventmp.h \
+ include/rtems/rtems/mp.h include/rtems/rtems/msgmp.h \
+ include/rtems/rtems/partmp.h include/rtems/rtems/regionmp.h \
+ include/rtems/rtems/semmp.h include/rtems/rtems/signalmp.h \
+ include/rtems/rtems/taskmp.h
+endif
+
+if INLINE
+include_rtems_rtems_HEADERS += inline/rtems/rtems/asr.inl \
+ inline/rtems/rtems/attr.inl inline/rtems/rtems/dpmem.inl \
+ inline/rtems/rtems/event.inl inline/rtems/rtems/eventset.inl \
+ inline/rtems/rtems/message.inl inline/rtems/rtems/modes.inl \
+ inline/rtems/rtems/options.inl inline/rtems/rtems/part.inl \
+ inline/rtems/rtems/ratemon.inl inline/rtems/rtems/region.inl \
+ inline/rtems/rtems/sem.inl inline/rtems/rtems/status.inl \
+ inline/rtems/rtems/support.inl inline/rtems/rtems/tasks.inl \
+ inline/rtems/rtems/timer.inl
+else
+include_rtems_rtems_HEADERS += macros/rtems/rtems/asr.inl \
+ macros/rtems/rtems/attr.inl macros/rtems/rtems/dpmem.inl \
+ macros/rtems/rtems/event.inl macros/rtems/rtems/eventset.inl \
+ macros/rtems/rtems/message.inl macros/rtems/rtems/modes.inl \
+ macros/rtems/rtems/options.inl macros/rtems/rtems/part.inl \
+ macros/rtems/rtems/ratemon.inl macros/rtems/rtems/region.inl \
+ macros/rtems/rtems/sem.inl macros/rtems/rtems/status.inl \
+ macros/rtems/rtems/support.inl macros/rtems/rtems/tasks.inl \
+ macros/rtems/rtems/timer.inl
+endif
+
+## src
+librtems_a_SOURCES =
+
+TASK_C_FILES = src/tasks.c src/taskcreate.c src/taskdelete.c \
+ src/taskgetnote.c src/taskident.c src/taskinitusers.c \
+ src/taskissuspended.c src/taskmode.c src/taskrestart.c src/taskresume.c \
+ src/tasksetnote.c src/tasksetpriority.c src/taskstart.c \
+ src/tasksuspend.c src/taskwakeafter.c src/taskwakewhen.c \
+ src/taskvariableadd.c src/taskvariabledelete.c src/taskvariableget.c
+
+RATEMON_C_FILES = src/ratemon.c src/ratemoncancel.c src/ratemoncreate.c \
+ src/ratemondelete.c src/ratemongetstatus.c src/ratemonident.c \
+ src/ratemonperiod.c src/ratemontimeout.c
+
+INTR_C_FILES = src/intr.c src/intrbody.c src/intrcatch.c
+
+CLOCK_C_FILES = src/rtclock.c src/clockget.c src/clockset.c src/clocktick.c
+
+TIMER_C_FILES = src/rtemstimer.c src/timercancel.c src/timercreate.c \
+ src/timerdelete.c src/timerfireafter.c src/timerfirewhen.c \
+ src/timergetinfo.c src/timerident.c src/timerreset.c src/timerserver.c \
+ src/timerserverfireafter.c src/timerserverfirewhen.c
+
+MESSAGE_QUEUE_C_FILES = src/msg.c src/msgqallocate.c src/msgqbroadcast.c \
+ src/msgqcreate.c src/msgqdelete.c src/msgqflush.c \
+ src/msgqgetnumberpending.c src/msgqident.c src/msgqreceive.c \
+ src/msgqsend.c src/msgqsubmit.c src/msgqtranslatereturncode.c \
+ src/msgqurgent.c
+
+SEMAPHORE_C_FILES = src/sem.c src/semcreate.c src/semdelete.c src/semident.c \
+ src/semobtain.c src/semrelease.c src/semflush.c \
+ src/semtranslatereturncode.c
+
+EVENT_C_FILES = src/event.c src/eventreceive.c src/eventseize.c \
+ src/eventsend.c src/eventsurrender.c src/eventtimeout.c
+
+SIGNAL_C_FILES = src/signal.c src/signalcatch.c src/signalsend.c
+
+REGION_C_FILES = src/region.c src/regioncreate.c src/regiondelete.c \
+ src/regionextend.c src/regiongetsegment.c src/regiongetsegmentsize.c \
+ src/regionident.c src/regionreturnsegment.c src/regiongetinfo.c
+
+PARTITION_C_FILES = src/part.c src/partcreate.c src/partdelete.c \
+ src/partgetbuffer.c src/partident.c src/partreturnbuffer.c
+
+DPMEM_C_FILES = src/dpmem.c src/dpmemcreate.c src/dpmemdelete.c \
+ src/dpmemexternal2internal.c src/dpmemident.c \
+ src/dpmeminternal2external.c
+
+librtems_a_SOURCES += src/attr.c src/rtemsidtoname.c $(TASK_C_FILES) \
+ $(RATEMON_C_FILES) $(INTR_C_FILES) $(CLOCK_C_FILES) $(TIMER_C_FILES) \
+ $(SEMAPHORE_C_FILES) $(MESSAGE_QUEUE_C_FILES) $(EVENT_C_FILES) \
+ $(SIGNAL_C_FILES) $(PARTITION_C_FILES) $(REGION_C_FILES) \
+ $(DPMEM_C_FILES)
+
+if HAS_MP
+# We only build multiprocessing related files if HAS_MP was defined
+librtems_a_SOURCES += src/eventmp.c src/mp.c src/msgmp.c src/partmp.c \
+ src/regionmp.c src/semmp.c src/signalmp.c src/taskmp.c
+endif
+librtems_g_a_SOURCES = $(librtems_a_SOURCES)
+
+all-local: $(PREINSTALL_FILES) librtems$(LIB_VARIANT).a
+
+PREINSTALL_DIRS =
+PREINSTALL_FILES =
+
+$(PROJECT_INCLUDE)/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)
+ @: > $(PROJECT_INCLUDE)/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems.h: include/rtems.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems.h
+
+$(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems/rtems
+ @: > $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/rtems/asr.h: include/rtems/rtems/asr.h $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/asr.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/asr.h
+
+$(PROJECT_INCLUDE)/rtems/rtems/attr.h: include/rtems/rtems/attr.h $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/attr.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/attr.h
+
+$(PROJECT_INCLUDE)/rtems/rtems/cache.h: include/rtems/rtems/cache.h $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/cache.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/cache.h
+
+$(PROJECT_INCLUDE)/rtems/rtems/clock.h: include/rtems/rtems/clock.h $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/clock.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/clock.h
+
+$(PROJECT_INCLUDE)/rtems/rtems/config.h: include/rtems/rtems/config.h $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/config.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/config.h
+
+$(PROJECT_INCLUDE)/rtems/rtems/dpmem.h: include/rtems/rtems/dpmem.h $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/dpmem.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/dpmem.h
+
+$(PROJECT_INCLUDE)/rtems/rtems/event.h: include/rtems/rtems/event.h $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/event.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/event.h
+
+$(PROJECT_INCLUDE)/rtems/rtems/eventset.h: include/rtems/rtems/eventset.h $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/eventset.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/eventset.h
+
+$(PROJECT_INCLUDE)/rtems/rtems/intr.h: include/rtems/rtems/intr.h $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/intr.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/intr.h
+
+$(PROJECT_INCLUDE)/rtems/rtems/message.h: include/rtems/rtems/message.h $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/message.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/message.h
+
+$(PROJECT_INCLUDE)/rtems/rtems/modes.h: include/rtems/rtems/modes.h $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/modes.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/modes.h
+
+$(PROJECT_INCLUDE)/rtems/rtems/options.h: include/rtems/rtems/options.h $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/options.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/options.h
+
+$(PROJECT_INCLUDE)/rtems/rtems/part.h: include/rtems/rtems/part.h $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/part.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/part.h
+
+$(PROJECT_INCLUDE)/rtems/rtems/ratemon.h: include/rtems/rtems/ratemon.h $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/ratemon.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/ratemon.h
+
+$(PROJECT_INCLUDE)/rtems/rtems/region.h: include/rtems/rtems/region.h $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/region.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/region.h
+
+$(PROJECT_INCLUDE)/rtems/rtems/rtemsapi.h: include/rtems/rtems/rtemsapi.h $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/rtemsapi.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/rtemsapi.h
+
+$(PROJECT_INCLUDE)/rtems/rtems/sem.h: include/rtems/rtems/sem.h $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/sem.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/sem.h
+
+$(PROJECT_INCLUDE)/rtems/rtems/signal.h: include/rtems/rtems/signal.h $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/signal.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/signal.h
+
+$(PROJECT_INCLUDE)/rtems/rtems/status.h: include/rtems/rtems/status.h $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/status.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/status.h
+
+$(PROJECT_INCLUDE)/rtems/rtems/support.h: include/rtems/rtems/support.h $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/support.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/support.h
+
+$(PROJECT_INCLUDE)/rtems/rtems/tasks.h: include/rtems/rtems/tasks.h $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/tasks.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/tasks.h
+
+$(PROJECT_INCLUDE)/rtems/rtems/timer.h: include/rtems/rtems/timer.h $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/timer.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/timer.h
+
+$(PROJECT_INCLUDE)/rtems/rtems/types.h: include/rtems/rtems/types.h $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/types.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/types.h
+
+if HAS_MP
+$(PROJECT_INCLUDE)/rtems/rtems/eventmp.h: include/rtems/rtems/eventmp.h $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/eventmp.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/eventmp.h
+
+$(PROJECT_INCLUDE)/rtems/rtems/mp.h: include/rtems/rtems/mp.h $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/mp.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/mp.h
+
+$(PROJECT_INCLUDE)/rtems/rtems/msgmp.h: include/rtems/rtems/msgmp.h $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/msgmp.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/msgmp.h
+
+$(PROJECT_INCLUDE)/rtems/rtems/partmp.h: include/rtems/rtems/partmp.h $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/partmp.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/partmp.h
+
+$(PROJECT_INCLUDE)/rtems/rtems/regionmp.h: include/rtems/rtems/regionmp.h $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/regionmp.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/regionmp.h
+
+$(PROJECT_INCLUDE)/rtems/rtems/semmp.h: include/rtems/rtems/semmp.h $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/semmp.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/semmp.h
+
+$(PROJECT_INCLUDE)/rtems/rtems/signalmp.h: include/rtems/rtems/signalmp.h $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/signalmp.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/signalmp.h
+
+$(PROJECT_INCLUDE)/rtems/rtems/taskmp.h: include/rtems/rtems/taskmp.h $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/taskmp.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/taskmp.h
+endif
+
+if INLINE
+$(PROJECT_INCLUDE)/rtems/rtems/asr.inl: inline/rtems/rtems/asr.inl $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/asr.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/asr.inl
+
+$(PROJECT_INCLUDE)/rtems/rtems/attr.inl: inline/rtems/rtems/attr.inl $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/attr.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/attr.inl
+
+$(PROJECT_INCLUDE)/rtems/rtems/dpmem.inl: inline/rtems/rtems/dpmem.inl $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/dpmem.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/dpmem.inl
+
+$(PROJECT_INCLUDE)/rtems/rtems/event.inl: inline/rtems/rtems/event.inl $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/event.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/event.inl
+
+$(PROJECT_INCLUDE)/rtems/rtems/eventset.inl: inline/rtems/rtems/eventset.inl $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/eventset.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/eventset.inl
+
+$(PROJECT_INCLUDE)/rtems/rtems/message.inl: inline/rtems/rtems/message.inl $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/message.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/message.inl
+
+$(PROJECT_INCLUDE)/rtems/rtems/modes.inl: inline/rtems/rtems/modes.inl $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/modes.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/modes.inl
+
+$(PROJECT_INCLUDE)/rtems/rtems/options.inl: inline/rtems/rtems/options.inl $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/options.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/options.inl
+
+$(PROJECT_INCLUDE)/rtems/rtems/part.inl: inline/rtems/rtems/part.inl $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/part.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/part.inl
+
+$(PROJECT_INCLUDE)/rtems/rtems/ratemon.inl: inline/rtems/rtems/ratemon.inl $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/ratemon.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/ratemon.inl
+
+$(PROJECT_INCLUDE)/rtems/rtems/region.inl: inline/rtems/rtems/region.inl $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/region.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/region.inl
+
+$(PROJECT_INCLUDE)/rtems/rtems/sem.inl: inline/rtems/rtems/sem.inl $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/sem.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/sem.inl
+
+$(PROJECT_INCLUDE)/rtems/rtems/status.inl: inline/rtems/rtems/status.inl $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/status.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/status.inl
+
+$(PROJECT_INCLUDE)/rtems/rtems/support.inl: inline/rtems/rtems/support.inl $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/support.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/support.inl
+
+$(PROJECT_INCLUDE)/rtems/rtems/tasks.inl: inline/rtems/rtems/tasks.inl $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/tasks.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/tasks.inl
+
+$(PROJECT_INCLUDE)/rtems/rtems/timer.inl: inline/rtems/rtems/timer.inl $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/timer.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/timer.inl
+
+else
+$(PROJECT_INCLUDE)/rtems/rtems/asr.inl: macros/rtems/rtems/asr.inl $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/asr.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/asr.inl
+
+$(PROJECT_INCLUDE)/rtems/rtems/attr.inl: macros/rtems/rtems/attr.inl $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/attr.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/attr.inl
+
+$(PROJECT_INCLUDE)/rtems/rtems/dpmem.inl: macros/rtems/rtems/dpmem.inl $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/dpmem.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/dpmem.inl
+
+$(PROJECT_INCLUDE)/rtems/rtems/event.inl: macros/rtems/rtems/event.inl $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/event.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/event.inl
+
+$(PROJECT_INCLUDE)/rtems/rtems/eventset.inl: macros/rtems/rtems/eventset.inl $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/eventset.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/eventset.inl
+
+$(PROJECT_INCLUDE)/rtems/rtems/message.inl: macros/rtems/rtems/message.inl $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/message.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/message.inl
+
+$(PROJECT_INCLUDE)/rtems/rtems/modes.inl: macros/rtems/rtems/modes.inl $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/modes.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/modes.inl
+
+$(PROJECT_INCLUDE)/rtems/rtems/options.inl: macros/rtems/rtems/options.inl $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/options.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/options.inl
+
+$(PROJECT_INCLUDE)/rtems/rtems/part.inl: macros/rtems/rtems/part.inl $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/part.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/part.inl
+
+$(PROJECT_INCLUDE)/rtems/rtems/ratemon.inl: macros/rtems/rtems/ratemon.inl $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/ratemon.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/ratemon.inl
+
+$(PROJECT_INCLUDE)/rtems/rtems/region.inl: macros/rtems/rtems/region.inl $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/region.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/region.inl
+
+$(PROJECT_INCLUDE)/rtems/rtems/sem.inl: macros/rtems/rtems/sem.inl $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/sem.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/sem.inl
+
+$(PROJECT_INCLUDE)/rtems/rtems/status.inl: macros/rtems/rtems/status.inl $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/status.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/status.inl
+
+$(PROJECT_INCLUDE)/rtems/rtems/support.inl: macros/rtems/rtems/support.inl $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/support.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/support.inl
+
+$(PROJECT_INCLUDE)/rtems/rtems/tasks.inl: macros/rtems/rtems/tasks.inl $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/tasks.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/tasks.inl
+
+$(PROJECT_INCLUDE)/rtems/rtems/timer.inl: macros/rtems/rtems/timer.inl $(PROJECT_INCLUDE)/rtems/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtems/timer.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtems/timer.inl
+endif
+
+CLEANFILES += $(PREINSTALL_FILES)
+DISTCLEANFILES = $(PREINSTALL_DIRS)
+
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/rtems/include/rtems.h b/cpukit/rtems/include/rtems.h
new file mode 100644
index 0000000000..0b70566ec3
--- /dev/null
+++ b/cpukit/rtems/include/rtems.h
@@ -0,0 +1,143 @@
+/* rtems.h
+ *
+ * This include file contains information about RTEMS executive that
+ * is required by the application and is CPU independent. It includes
+ * two (2) CPU dependent files to tailor its data structures for a
+ * particular processor.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_RTEMS_GENERIC_h
+#define __RTEMS_RTEMS_GENERIC_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Unless told otherwise, the RTEMS include files will hide some stuff
+ * from normal application code. Defining this crosses a boundary which
+ * is undesirable since it means your application is using RTEMS features
+ * which are not included in the formally defined and supported API.
+ * Define this at your own risk.
+ */
+
+#if (!defined(__RTEMS_VIOLATE_KERNEL_VISIBILITY__)) && (!defined(__RTEMS_INSIDE__))
+#define __RTEMS_APPLICATION__
+#endif
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/types.h>
+
+#include <rtems/config.h>
+#include <rtems/init.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/tasks.h>
+#include <rtems/rtems/intr.h>
+#include <rtems/rtems/cache.h>
+#include <rtems/rtems/clock.h>
+#include <rtems/extension.h>
+#include <rtems/rtems/timer.h>
+#include <rtems/rtems/sem.h>
+#include <rtems/rtems/message.h>
+#include <rtems/rtems/event.h>
+#include <rtems/rtems/signal.h>
+#include <rtems/rtems/event.h>
+#include <rtems/rtems/part.h>
+#include <rtems/rtems/region.h>
+#include <rtems/rtems/dpmem.h>
+#include <rtems/io.h>
+#include <rtems/fatal.h>
+#include <rtems/rtems/ratemon.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/rtems/mp.h>
+#endif
+
+#include <rtems/rtems/support.h>
+#include <rtems/score/sysstate.h>
+
+#define RTEMS_HAS_HARDWARE_FP CPU_HARDWARE_FP
+
+/*
+ * The following define the constants which may be used in name searches.
+ */
+
+#define RTEMS_SEARCH_ALL_NODES OBJECTS_SEARCH_ALL_NODES
+#define RTEMS_SEARCH_OTHER_NODES OBJECTS_SEARCH_OTHER_NODES
+#define RTEMS_SEARCH_LOCAL_NODE OBJECTS_SEARCH_LOCAL_NODE
+#define RTEMS_WHO_AM_I OBJECTS_WHO_AM_I
+
+/*
+ * Parameters and return id's for _Objects_Get_next
+ */
+
+#define RTEMS_OBJECT_ID_INITIAL_INDEX OBJECTS_ID_INITIAL_INDEX
+#define RTEMS_OBJECT_ID_FINAL_INDEX OBJECTS_ID_FINAL_INDEX
+#define RTEMS_OBJECT_ID_INITIAL(api, class, node) OBJECTS_ID_INITIAL(api, class, node)
+
+#define RTEMS_OBJECT_ID_FINAL OBJECTS_ID_FINAL
+
+/*
+ * The following constant defines the minimum stack size which every
+ * thread must exceed.
+ */
+
+#define RTEMS_MINIMUM_STACK_SIZE STACK_MINIMUM_SIZE
+
+/*
+ * Constant for indefinite wait. (actually an illegal interval)
+ */
+
+#define RTEMS_NO_TIMEOUT WATCHDOG_NO_TIMEOUT
+
+/*
+ * An MPCI must support packets of at least this size.
+ */
+
+#define RTEMS_MINIMUM_PACKET_SIZE MP_PACKET_MINIMUM_PACKET_SIZE
+
+/*
+ * The following constant defines the number of uint32_t 's
+ * in a packet which must be converted to native format in a
+ * heterogeneous system. In packets longer than
+ * MP_PACKET_MINIMUN_HETERO_CONVERSION uint32_t 's, some of the "extra" data
+ * may a user message buffer which is not automatically endian swapped.
+ */
+
+#define RTEMS_MINIMUN_HETERO_CONVERSION MP_PACKET_MINIMUN_HETERO_CONVERSION
+
+/*
+ * rtems_object_id_to_name
+ *
+ * This directive returns the name associated with the specified
+ * object ID.
+ *
+ * Input parameters:
+ * id - message queue id
+ *
+ * Output parameters:
+ * *name - user defined object name
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_object_id_to_name(
+ rtems_id id,
+ rtems_name *name
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/include/rtems/rtems/asr.h b/cpukit/rtems/include/rtems/rtems/asr.h
new file mode 100644
index 0000000000..740ff8ac68
--- /dev/null
+++ b/cpukit/rtems/include/rtems/rtems/asr.h
@@ -0,0 +1,111 @@
+/* asr.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the Asynchronous Signal Handler. This Handler provides the low-level
+ * support required by the Signal Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_ASR_h
+#define __RTEMS_ASR_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/rtems/modes.h>
+
+/*
+ *
+ * The following type defines the control block used to manage
+ * each signal set.
+ */
+
+typedef uint32_t rtems_signal_set;
+
+/*
+ * Return type for ASR Handler
+ */
+
+typedef void rtems_asr;
+
+/*
+ * The following type corresponds to the applications asynchronous
+ * signal processing routine.
+ */
+
+typedef rtems_asr ( *rtems_asr_entry )(
+ rtems_signal_set
+ );
+
+/*
+ *
+ * The following defines the control structure used to manage
+ * signals. Each thread has a copy of this record.
+ */
+
+typedef struct {
+ boolean is_enabled; /* are ASRs enabled currently? */
+ rtems_asr_entry handler; /* address of RTEMS_ASR */
+ Modes_Control mode_set; /* RTEMS_ASR mode */
+ rtems_signal_set signals_posted; /* signal set */
+ rtems_signal_set signals_pending; /* pending signal set */
+ uint32_t nest_level; /* nest level of RTEMS_ASR */
+} ASR_Information;
+
+/*
+ * The following constants define the individual signals which may
+ * be used to compose a signal set.
+ */
+
+#define RTEMS_SIGNAL_0 0x00000001
+#define RTEMS_SIGNAL_1 0x00000002
+#define RTEMS_SIGNAL_2 0x00000004
+#define RTEMS_SIGNAL_3 0x00000008
+#define RTEMS_SIGNAL_4 0x00000010
+#define RTEMS_SIGNAL_5 0x00000020
+#define RTEMS_SIGNAL_6 0x00000040
+#define RTEMS_SIGNAL_7 0x00000080
+#define RTEMS_SIGNAL_8 0x00000100
+#define RTEMS_SIGNAL_9 0x00000200
+#define RTEMS_SIGNAL_10 0x00000400
+#define RTEMS_SIGNAL_11 0x00000800
+#define RTEMS_SIGNAL_12 0x00001000
+#define RTEMS_SIGNAL_13 0x00002000
+#define RTEMS_SIGNAL_14 0x00004000
+#define RTEMS_SIGNAL_15 0x00008000
+#define RTEMS_SIGNAL_16 0x00010000
+#define RTEMS_SIGNAL_17 0x00020000
+#define RTEMS_SIGNAL_18 0x00040000
+#define RTEMS_SIGNAL_19 0x00080000
+#define RTEMS_SIGNAL_20 0x00100000
+#define RTEMS_SIGNAL_21 0x00200000
+#define RTEMS_SIGNAL_22 0x00400000
+#define RTEMS_SIGNAL_23 0x00800000
+#define RTEMS_SIGNAL_24 0x01000000
+#define RTEMS_SIGNAL_25 0x02000000
+#define RTEMS_SIGNAL_26 0x04000000
+#define RTEMS_SIGNAL_27 0x08000000
+#define RTEMS_SIGNAL_28 0x10000000
+#define RTEMS_SIGNAL_29 0x20000000
+#define RTEMS_SIGNAL_30 0x40000000
+#define RTEMS_SIGNAL_31 0x80000000
+
+#ifndef __RTEMS_APPLICATION__
+#include <rtems/rtems/asr.inl>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/include/rtems/rtems/attr.h b/cpukit/rtems/include/rtems/rtems/attr.h
new file mode 100644
index 0000000000..200a434ce6
--- /dev/null
+++ b/cpukit/rtems/include/rtems/rtems/attr.h
@@ -0,0 +1,89 @@
+/* attr.h
+ *
+ * This include file contains all information about the Object Attributes
+ * Handler.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_ATTRIBUTES_h
+#define __RTEMS_ATTRIBUTES_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* types */
+
+typedef uint32_t rtems_attribute;
+
+/* constants */
+
+#define RTEMS_DEFAULT_ATTRIBUTES 0x00000000
+
+#define RTEMS_NO_FLOATING_POINT 0x00000000 /* don't use FP HW */
+#define RTEMS_FLOATING_POINT 0x00000001 /* utilize coprocessor */
+
+#define RTEMS_LOCAL 0x00000000 /* local resource */
+#define RTEMS_GLOBAL 0x00000002 /* global resource */
+
+#define RTEMS_FIFO 0x00000000 /* process RTEMS_FIFO */
+#define RTEMS_PRIORITY 0x00000004 /* process by priority */
+
+#define RTEMS_SEMAPHORE_CLASS 0x00000030 /* mask */
+#define RTEMS_COUNTING_SEMAPHORE 0x00000000
+#define RTEMS_BINARY_SEMAPHORE 0x00000010
+#define RTEMS_SIMPLE_BINARY_SEMAPHORE 0x00000020
+
+#define RTEMS_NO_INHERIT_PRIORITY 0x00000000
+#define RTEMS_INHERIT_PRIORITY 0x00000040
+
+#define RTEMS_NO_PRIORITY_CEILING 0x00000000
+#define RTEMS_PRIORITY_CEILING 0x00000080
+
+#define RTEMS_APPLICATION_TASK 0x00000000
+#define RTEMS_SYSTEM_TASK 0x00000100
+
+
+#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+#define ATTRIBUTES_NOT_SUPPORTED 0
+#else
+#define ATTRIBUTES_NOT_SUPPORTED RTEMS_FLOATING_POINT
+#endif
+
+#if ( CPU_ALL_TASKS_ARE_FP == TRUE )
+#define ATTRIBUTES_REQUIRED RTEMS_FLOATING_POINT
+#else
+#define ATTRIBUTES_REQUIRED 0
+#endif
+
+/*
+ * _Attributes_Handler_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs initialization for this handler.
+ *
+ * NOTE: There is no initialization required in C. Conditional compilation
+ * takes care of this in C.
+ */
+
+#define _Attributes_Handler_initialization()
+
+#ifndef __RTEMS_APPLICATION__
+#include <rtems/rtems/attr.inl>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/include/rtems/rtems/cache.h b/cpukit/rtems/include/rtems/rtems/cache.h
new file mode 100644
index 0000000000..d6ba1de217
--- /dev/null
+++ b/cpukit/rtems/include/rtems/rtems/cache.h
@@ -0,0 +1,137 @@
+/* cache.h
+ *
+ * Cache Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ *
+ * The functions in this file define the API to the RTEMS Cache Manager and
+ * are divided into data cache and instruction cache functions. Data cache
+ * functions are only meaningful if a data cache is supported. Instruction
+ * cache functions are only meaningful if an instruction cache is supported.
+ *
+ * The functions below are implemented with CPU dependent support routines
+ * implemented as part of libcpu. In the event that a CPU does not support a
+ * specific function, the CPU dependent routine does nothing (but does exist).
+ *
+ * At this point, the Cache Manager makes no considerations, and provides no
+ * support for BSP specific issues such as a secondary cache. In such a system,
+ * the CPU dependent routines would have to be modified, or a BSP layer added
+ * to this Manager.
+ */
+
+#ifndef __CACHE_h
+#define __CACHE_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/system.h>
+#include <sys/types.h>
+
+/*
+ * These functions will ONLY do something if the
+ * libcpu support includes data cache routines AND
+ * the CPU model supports data caching.
+ */
+
+/*
+ * This function is called to flush the data cache by performing cache
+ * copybacks. It must determine how many cache lines need to be copied
+ * back and then perform the copybacks.
+ */
+void rtems_cache_flush_multiple_data_lines( const void *, size_t );
+
+/*
+ * This function is responsible for performing a data cache invalidate.
+ * It must determine how many cache lines need to be invalidated and then
+ * perform the invalidations.
+ */
+void rtems_cache_invalidate_multiple_data_lines( const void *, size_t );
+
+/*
+ * This function is responsible for performing a data cache flush.
+ * It flushes the entire cache.
+ */
+void rtems_cache_flush_entire_data( void );
+
+/*
+ * This function is responsible for performing a data cache
+ * invalidate. It invalidates the entire cache.
+ */
+void rtems_cache_invalidate_entire_data( void );
+
+/*
+ * This function returns the data cache granularity.
+ */
+int rtems_cache_get_data_line_size( void );
+
+/*
+ * This function freezes the data cache.
+ */
+void rtems_cache_freeze_data( void );
+
+/*
+ * This function unfreezes the data cache.
+ */
+void rtems_cache_unfreeze_data( void );
+
+/*
+ * These functions enable/disable the data cache.
+ */
+void rtems_cache_enable_data( void );
+void rtems_cache_disable_data( void );
+
+/*
+ * These functions will ONLY do something if the
+ * libcpu support includes instruction cache routines AND
+ * the CPU model supports instruction caching.
+ */
+
+/*
+ * This function is responsible for performing an instruction cache
+ * invalidate. It must determine how many cache lines need to be invalidated
+ * and then perform the invalidations.
+ */
+void rtems_cache_invalidate_multiple_instruction_lines( const void *, size_t );
+
+/*
+ * This function is responsible for performing an instruction cache
+ * invalidate. It invalidates the entire cache.
+ */
+void rtems_cache_invalidate_entire_instruction( void );
+
+/*
+ * This function returns the instruction cache granularity.
+ */
+int rtems_cache_get_instruction_line_size( void );
+
+/*
+ * This function freezes the instruction cache.
+ */
+void rtems_cache_freeze_instruction( void );
+
+/*
+ * This function unfreezes the instruction cache.
+ */
+void rtems_cache_unfreeze_instruction( void );
+
+/*
+ * These functions enable/disable the instruction cache.
+ */
+void rtems_cache_enable_instruction( void );
+void rtems_cache_disable_instruction( void );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/include/rtems/rtems/clock.h b/cpukit/rtems/include/rtems/rtems/clock.h
new file mode 100644
index 0000000000..8008ba6f89
--- /dev/null
+++ b/cpukit/rtems/include/rtems/rtems/clock.h
@@ -0,0 +1,102 @@
+/* clock.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the Clock Manager. This manager provides facilities to set, obtain,
+ * and continually update the current date and time.
+ *
+ * This manager provides directives to:
+ *
+ * + set the current date and time
+ * + obtain the current date and time
+ * + announce a clock tick
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_CLOCK_h
+#define __RTEMS_CLOCK_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/tod.h>
+#include <rtems/rtems/types.h>
+
+/*
+ * List of things which can be returned by the rtems_clock_get directive.
+ */
+
+typedef enum {
+ RTEMS_CLOCK_GET_TOD,
+ RTEMS_CLOCK_GET_SECONDS_SINCE_EPOCH,
+ RTEMS_CLOCK_GET_TICKS_SINCE_BOOT,
+ RTEMS_CLOCK_GET_TICKS_PER_SECOND,
+ RTEMS_CLOCK_GET_TIME_VALUE
+} rtems_clock_get_options;
+
+/*
+ * Standard flavor style to return TOD in for a rtems_clock_get option.
+ */
+
+typedef struct {
+ uint32_t seconds;
+ uint32_t microseconds;
+} rtems_clock_time_value;
+
+/*
+ * rtems_clock_get
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_clock_get directive. It returns
+ * one of the following:
+ * + current time of day
+ * + seconds since epoch
+ * + ticks since boot
+ * + ticks per second
+ */
+
+rtems_status_code rtems_clock_get(
+ rtems_clock_get_options option,
+ void *time_buffer
+);
+
+/*
+ * rtems_clock_set
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_clock_set directive. It sets
+ * the current time of day to that in the time_buffer record.
+ */
+
+rtems_status_code rtems_clock_set(
+ rtems_time_of_day *time_buffer
+);
+
+/*
+ * rtems_clock_tick
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_clock_tick directive. It is invoked
+ * to inform RTEMS of the occurrence of a clock tick.
+ */
+
+rtems_status_code rtems_clock_tick( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/include/rtems/rtems/config.h b/cpukit/rtems/include/rtems/rtems/config.h
new file mode 100644
index 0000000000..ac965c8aca
--- /dev/null
+++ b/cpukit/rtems/include/rtems/rtems/config.h
@@ -0,0 +1,53 @@
+/* config.h
+ *
+ * This include file contains the table of user defined configuration
+ * parameters specific for the RTEMS API.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_RTEMS_CONFIGURATION_h
+#define __RTEMS_RTEMS_CONFIGURATION_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/rtems/types.h>
+#include <rtems/rtems/tasks.h>
+
+/*
+ * The following records define the Configuration Table. The
+ * information contained in this table is required in all
+ * RTEMS systems, whether single or multiprocessor. This
+ * table primarily defines the following:
+ *
+ * + required number of each object type
+ */
+
+typedef struct {
+ uint32_t maximum_tasks;
+ uint32_t maximum_timers;
+ uint32_t maximum_semaphores;
+ uint32_t maximum_message_queues;
+ uint32_t maximum_partitions;
+ uint32_t maximum_regions;
+ uint32_t maximum_ports;
+ uint32_t maximum_periods;
+ uint32_t number_of_initialization_tasks;
+ rtems_initialization_tasks_table *User_initialization_tasks_table;
+} rtems_api_configuration_table;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/include/rtems/rtems/dpmem.h b/cpukit/rtems/include/rtems/rtems/dpmem.h
new file mode 100644
index 0000000000..53bb4bfd3e
--- /dev/null
+++ b/cpukit/rtems/include/rtems/rtems/dpmem.h
@@ -0,0 +1,156 @@
+/* dpmem.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the Dual Ported Memory Manager. This manager provides a mechanism
+ * for converting addresses between internal and external representations
+ * for multiple dual-ported memory areas.
+ *
+ * Directives provided are:
+ *
+ * + create a port
+ * + get ID of a port
+ * + delete a port
+ * + convert external to internal address
+ * + convert internal to external address
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_DUAL_PORTED_MEMORY_h
+#define __RTEMS_DUAL_PORTED_MEMORY_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/object.h>
+
+/*
+ * The following structure defines the port control block. Each port
+ * has a control block associated with it. This control block contains
+ * all information required to support the port related operations.
+ */
+
+typedef struct {
+ Objects_Control Object;
+ void *internal_base; /* base internal address */
+ void *external_base; /* base external address */
+ uint32_t length; /* length of dual-ported area */
+} Dual_ported_memory_Control;
+
+/*
+ * The following define the internal Dual Ported Memory information.
+ */
+
+RTEMS_EXTERN Objects_Information _Dual_ported_memory_Information;
+
+/*
+ * _Dual_ported_memory_Manager_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this manager.
+ */
+
+void _Dual_ported_memory_Manager_initialization(
+ uint32_t maximum_ports
+);
+
+/*
+ * rtems_port_create
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_port_create directive. The port
+ * will have the name name. The port maps onto an area of dual ported
+ * memory of length bytes which has internal_start and external_start
+ * as the internal and external starting addresses, respectively.
+ * It returns the id of the created port in ID.
+ */
+
+rtems_status_code rtems_port_create(
+ rtems_name name,
+ void *internal_start,
+ void *external_start,
+ uint32_t length,
+ Objects_Id *id
+);
+
+/*
+ * rtems_port_ident
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_port_ident directive. This directive
+ * returns the port ID associated with name. If more than one port is
+ * named name, then the port to which the ID belongs is arbitrary.
+ */
+
+rtems_status_code rtems_port_ident(
+ rtems_name name,
+ Objects_Id *id
+);
+
+/*
+ * rtems_port_delete
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_port_delete directive. It deletes
+ * the port associated with ID.
+ */
+
+rtems_status_code rtems_port_delete(
+ Objects_Id id
+);
+
+/*
+ * rtems_port_external_to_internal
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_port_external_to_internal directive.
+ * It returns the internal port address which maps to the provided
+ * external port address for the specified port ID.
+ */
+
+rtems_status_code rtems_port_external_to_internal(
+ Objects_Id id,
+ void *external,
+ void **internal
+);
+
+/*
+ * rtems_port_internal_to_external
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the Port_internal_to_external directive.
+ * It returns the external port address which maps to the provided
+ * internal port address for the specified port ID.
+ */
+
+rtems_status_code rtems_port_internal_to_external(
+ Objects_Id id,
+ void *internal,
+ void **external
+);
+
+#ifndef __RTEMS_APPLICATION__
+#include <rtems/rtems/dpmem.inl>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/include/rtems/rtems/event.h b/cpukit/rtems/include/rtems/rtems/event.h
new file mode 100644
index 0000000000..869d20d374
--- /dev/null
+++ b/cpukit/rtems/include/rtems/rtems/event.h
@@ -0,0 +1,175 @@
+/* event.h
+ *
+ * This include file contains the information pertaining to the Event
+ * Manager. This manager provides a high performance method of communication
+ * and synchronization.
+ *
+ * Directives provided are:
+ *
+ * + send an event set to a task
+ * + receive event condition
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_EVENT_h
+#define __RTEMS_EVENT_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/object.h>
+#include <rtems/rtems/types.h>
+#include <rtems/rtems/options.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/rtems/eventset.h>
+
+/*
+ * This constant is passed as the event_in to the
+ * rtems_event_receive directive to determine which events are pending.
+ */
+
+#define EVENT_CURRENT 0
+
+/*
+ * The following enumerated types indicate what happened while the event
+ * manager was in the synchronization window.
+ */
+
+typedef enum {
+ EVENT_SYNC_SYNCHRONIZED,
+ EVENT_SYNC_NOTHING_HAPPENED,
+ EVENT_SYNC_TIMEOUT,
+ EVENT_SYNC_SATISFIED
+} Event_Sync_states;
+
+/*
+ * Event_Manager_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this manager.
+ */
+
+void _Event_Manager_initialization( void );
+
+/*
+ * rtems_event_send
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_event_send directive. It sends
+ * event_in to the task specified by ID. If the task is blocked
+ * waiting to receive events and the posting of event_in satisfies
+ * the task's event condition, then it is unblocked.
+ */
+
+rtems_status_code rtems_event_send (
+ Objects_Id id,
+ rtems_event_set event_in
+);
+
+/*
+ * rtems_event_receive
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_event_receive directive. This
+ * directive is invoked when the calling task wishes to receive
+ * the event_in event condition. One of the fields in the option_set
+ * parameter determines whether the receive request is satisfied if
+ * any or all of the events are pending. If the event condition
+ * is not satisfied immediately, then the task may block with an
+ * optional timeout of TICKS clock ticks or return immediately.
+ * This determination is based on another field in the option_set
+ * parameter. This directive returns the events received in the
+ * event_out parameter.
+ */
+
+rtems_status_code rtems_event_receive (
+ rtems_event_set event_in,
+ rtems_option option_set,
+ rtems_interval ticks,
+ rtems_event_set *event_out
+);
+
+/*
+ * _Event_Seize
+ *
+ * DESCRIPTION:
+ *
+ * This routine determines if the event condition event_in is
+ * satisfied. If so or if the no_wait option is enabled in option_set,
+ * then the procedure returns immediately. If neither of these
+ * conditions is true, then the calling task is blocked with an
+ * optional timeout of ticks clock ticks.
+ */
+
+void _Event_Seize (
+ rtems_event_set event_in,
+ rtems_option option_set,
+ rtems_interval ticks,
+ rtems_event_set *event_out
+);
+
+/*
+ * _Event_Surrender
+ *
+ * DESCRIPTION:
+ *
+ * This routine determines if the event condition of the_thread
+ * has been satisfied. If so, it unblocks the_thread.
+ */
+
+void _Event_Surrender (
+ Thread_Control *the_thread
+);
+
+/*
+ * _Event_Timeout
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked when a task's event receive request
+ * has not been satisfied after the specified timeout interval.
+ * The task represented by ID will be unblocked and its status
+ * code will be set in it's control block to indicate that a timeout
+ * has occurred.
+ */
+
+void _Event_Timeout (
+ Objects_Id id,
+ void *ignored
+);
+
+/*
+ * The following defines the synchronization flag used by the
+ * Event Manager to insure that signals sent to the currently
+ * executing thread are received properly.
+ */
+
+RTEMS_EXTERN volatile Event_Sync_states _Event_Sync_state;
+
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/rtems/eventmp.h>
+#endif
+#ifndef __RTEMS_APPLICATION__
+#include <rtems/rtems/event.inl>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/include/rtems/rtems/eventmp.h b/cpukit/rtems/include/rtems/rtems/eventmp.h
new file mode 100644
index 0000000000..cf73464092
--- /dev/null
+++ b/cpukit/rtems/include/rtems/rtems/eventmp.h
@@ -0,0 +1,146 @@
+/* eventmp.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the Multiprocessing Support in the Event Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_EVENT_MP_h
+#define __RTEMS_EVENT_MP_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/rtems/event.h>
+#include <rtems/score/mppkt.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/watchdog.h>
+
+/*
+ * The following enumerated type defines the list of
+ * remote event operations.
+ */
+
+typedef enum {
+ EVENT_MP_SEND_REQUEST = 0,
+ EVENT_MP_SEND_RESPONSE = 1
+} Event_MP_Remote_operations;
+
+/*
+ * The following data structure defines the packet used to perform
+ * remote event operations.
+ */
+
+typedef struct {
+ rtems_packet_prefix Prefix;
+ Event_MP_Remote_operations operation;
+ rtems_event_set event_in;
+} Event_MP_Packet;
+
+/*
+ * _Event_MP_Send_process_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * process operation can be performed on another node.
+ *
+ * This routine is not needed since there are no process
+ * packets to be sent by this manager.
+ */
+
+/*
+ * _Event_MP_Send_request_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * directive operation can be initiated on another node.
+ */
+
+rtems_status_code _Event_MP_Send_request_packet (
+ Event_MP_Remote_operations operation,
+ Objects_Id event_id,
+ rtems_event_set event_in
+);
+
+/*
+ * _Event_MP_Send_response_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * directive can be performed on another node.
+ */
+
+void _Event_MP_Send_response_packet (
+ Event_MP_Remote_operations operation,
+ Thread_Control *the_thread
+);
+
+/*
+ *
+ * _Event_MP_Process_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the actions specific to this package for
+ * the request from another node.
+ */
+
+void _Event_MP_Process_packet (
+ rtems_packet_prefix *the_packet_prefix
+);
+
+/*
+ * _Event_MP_Send_object_was_deleted
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked indirectly by the thread queue
+ * when a proxy has been removed from the thread queue and
+ * the remote node must be informed of this.
+ *
+ * This routine is not needed since there are no objects
+ * deleted by this manager.
+ */
+
+/*
+ * _Event_MP_Send_extract_proxy
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked when a task is deleted and it
+ * has a proxy which must be removed from a thread queue and
+ * the remote node must be informed of this.
+ *
+ * This routine is not needed since there are no objects
+ * deleted by this manager.
+ */
+
+/*
+ * _Event_MP_Get_packet
+ *
+ * DESCRIPTION:
+ *
+ * This function is used to obtain a event mp packet.
+ */
+
+Event_MP_Packet *_Event_MP_Get_packet ( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of file */
diff --git a/cpukit/rtems/include/rtems/rtems/eventset.h b/cpukit/rtems/include/rtems/rtems/eventset.h
new file mode 100644
index 0000000000..e70f5d858b
--- /dev/null
+++ b/cpukit/rtems/include/rtems/rtems/eventset.h
@@ -0,0 +1,88 @@
+/* eventset.h
+ *
+ * This include file contains the information pertaining to the
+ * Event Sets Handler. This handler provides methods for the manipulation
+ * of event sets which will be sent and received by tasks.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_EVENT_SET_h
+#define __RTEMS_EVENT_SET_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * The following defines the type used to control event sets.
+ */
+
+typedef uint32_t rtems_event_set;
+
+/*
+ * The following constants define the individual events which may
+ * be used to compose an event set.
+ */
+
+#define RTEMS_PENDING_EVENTS 0 /* receive pending events */
+#define RTEMS_ALL_EVENTS 0xFFFFFFFF
+
+#define RTEMS_EVENT_0 0x00000001
+#define RTEMS_EVENT_1 0x00000002
+#define RTEMS_EVENT_2 0x00000004
+#define RTEMS_EVENT_3 0x00000008
+#define RTEMS_EVENT_4 0x00000010
+#define RTEMS_EVENT_5 0x00000020
+#define RTEMS_EVENT_6 0x00000040
+#define RTEMS_EVENT_7 0x00000080
+#define RTEMS_EVENT_8 0x00000100
+#define RTEMS_EVENT_9 0x00000200
+#define RTEMS_EVENT_10 0x00000400
+#define RTEMS_EVENT_11 0x00000800
+#define RTEMS_EVENT_12 0x00001000
+#define RTEMS_EVENT_13 0x00002000
+#define RTEMS_EVENT_14 0x00004000
+#define RTEMS_EVENT_15 0x00008000
+#define RTEMS_EVENT_16 0x00010000
+#define RTEMS_EVENT_17 0x00020000
+#define RTEMS_EVENT_18 0x00040000
+#define RTEMS_EVENT_19 0x00080000
+#define RTEMS_EVENT_20 0x00100000
+#define RTEMS_EVENT_21 0x00200000
+#define RTEMS_EVENT_22 0x00400000
+#define RTEMS_EVENT_23 0x00800000
+#define RTEMS_EVENT_24 0x01000000
+#define RTEMS_EVENT_25 0x02000000
+#define RTEMS_EVENT_26 0x04000000
+#define RTEMS_EVENT_27 0x08000000
+#define RTEMS_EVENT_28 0x10000000
+#define RTEMS_EVENT_29 0x20000000
+#define RTEMS_EVENT_30 0x40000000
+#define RTEMS_EVENT_31 0x80000000
+
+
+/*
+ * The following constant is the value of an event set which
+ * has no events pending.
+ */
+
+#define EVENT_SETS_NONE_PENDING 0
+
+#ifndef __RTEMS_APPLICATION__
+#include <rtems/rtems/eventset.inl>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/include/rtems/rtems/intr.h b/cpukit/rtems/include/rtems/rtems/intr.h
new file mode 100644
index 0000000000..10ed1d0657
--- /dev/null
+++ b/cpukit/rtems/include/rtems/rtems/intr.h
@@ -0,0 +1,159 @@
+/* intr.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the Interrupt Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_INTERRUPT_h
+#define __RTEMS_INTERRUPT_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/isr.h>
+
+/*
+ * Interrupt level type
+ */
+
+typedef ISR_Level rtems_interrupt_level;
+
+/*
+ * The following type defines the control block used to manage
+ * the vectors.
+ */
+
+typedef ISR_Vector_number rtems_vector_number;
+
+/*
+ * Return type for ISR Handler
+ */
+
+typedef void rtems_isr;
+
+/*
+ * Pointer to an ISR Handler
+ */
+
+typedef rtems_isr ( *rtems_isr_entry )(
+ rtems_vector_number
+ );
+
+/*
+ * _Interrupt_Manager_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine initializes the interrupt manager.
+ *
+ */
+
+void _Interrupt_Manager_initialization( void );
+
+/*
+ * rtems_interrupt_catch
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_interrupt_catch directive. This
+ * directive installs new_isr_handler as the RTEMS interrupt service
+ * routine for vector. The previous RTEMS interrupt service
+ * routine is returned in old_isr_handler.
+ */
+
+rtems_status_code rtems_interrupt_catch(
+ rtems_isr_entry new_isr_handler,
+ rtems_vector_number vector,
+ rtems_isr_entry *old_isr_handler
+);
+
+/*
+ * rtems_interrupt_disable
+ *
+ * DESCRIPTION:
+ *
+ * This routine disables all maskable interrupts and returns the
+ * previous level in _isr_cookie.
+ */
+
+#define rtems_interrupt_disable( _isr_cookie ) \
+ _ISR_Disable(_isr_cookie)
+
+/*
+ * rtems_interrupt_enable
+ *
+ * DESCRIPTION:
+ *
+ * This routine enables maskable interrupts to the level indicated
+ * _isr_cookie.
+ */
+
+#define rtems_interrupt_enable( _isr_cookie ) \
+ _ISR_Enable(_isr_cookie)
+
+/*
+ * rtems_interrupt_flash
+ *
+ * DESCRIPTION:
+ *
+ * This routine temporarily enables maskable interrupts to the
+ * level in _isr_cookie before redisabling them.
+ */
+
+#define rtems_interrupt_flash( _isr_cookie ) \
+ _ISR_Flash(_isr_cookie)
+
+/*
+ * rtems_interrupt_is_in_progress
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the processor is currently servicing
+ * an interrupt and FALSE otherwise. A return value of TRUE indicates
+ * that the caller is an interrupt service routine, NOT a thread. The
+ * directives available to an interrupt service routine are restricted.
+ */
+
+#define rtems_interrupt_is_in_progress() \
+ _ISR_Is_in_progress()
+
+/*
+ * rtems_interrupt_cause
+ *
+ * DESCRIPTION:
+ *
+ * This routine generates an interrupt.
+ *
+ * NOTE: No implementation.
+ */
+
+#define rtems_interrupt_cause( _interrupt_to_cause )
+
+/*
+ * rtems_interrupt_cause
+ *
+ * DESCRIPTION:
+ *
+ * This routine clears the specified interrupt.
+ *
+ * NOTE: No implementation.
+ */
+
+#define rtems_interrupt_clear( _interrupt_to_clear )
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/include/rtems/rtems/message.h b/cpukit/rtems/include/rtems/rtems/message.h
new file mode 100644
index 0000000000..97da3f118e
--- /dev/null
+++ b/cpukit/rtems/include/rtems/rtems/message.h
@@ -0,0 +1,328 @@
+/* message.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the Message Queue Manager. This manager provides a mechanism for
+ * communication and synchronization between tasks using messages.
+ *
+ * Directives provided are:
+ *
+ * + create a queue
+ * + get ID of a queue
+ * + delete a queue
+ * + put a message at the rear of a queue
+ * + put a message at the front of a queue
+ * + broadcast N messages to a queue
+ * + receive message from a queue
+ * + flush all messages on a queue
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_MESSAGE_QUEUE_h
+#define __RTEMS_MESSAGE_QUEUE_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/rtems/types.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/attr.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/coremsg.h>
+
+/*
+ * The following enumerated type details the modes in which a message
+ * may be submitted to a message queue. The message may be posted
+ * in a send or urgent fashion.
+ */
+
+typedef enum {
+ MESSAGE_QUEUE_SEND_REQUEST = 0,
+ MESSAGE_QUEUE_URGENT_REQUEST = 1
+} Message_queue_Submit_types;
+
+/*
+ * The following records define the control block used to manage
+ * each message queue.
+ */
+
+typedef struct {
+ Objects_Control Object;
+ rtems_attribute attribute_set;
+ CORE_message_queue_Control message_queue;
+} Message_queue_Control;
+
+/*
+ * The following defines the information control block used to
+ * manage this class of objects.
+ */
+
+RTEMS_EXTERN Objects_Information _Message_queue_Information;
+
+/*
+ * _Message_queue_Manager_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this manager.
+ */
+
+void _Message_queue_Manager_initialization(
+ uint32_t maximum_message_queues
+);
+
+/*
+ * rtems_message_queue_create
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_message_queue_create directive. The
+ * message queue will have the name name. If the attribute_set indicates
+ * that the message queue is to be limited in the number of messages
+ * that can be outstanding, then count indicates the maximum number of
+ * messages that will be held. It returns the id of the created
+ * message queue in ID.
+ */
+
+rtems_status_code rtems_message_queue_create(
+ rtems_name name,
+ uint32_t count,
+ uint32_t max_message_size,
+ rtems_attribute attribute_set,
+ Objects_Id *id
+);
+
+/*
+ * rtems_message_queue_ident
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_message_queue_ident directive.
+ * This directive returns the message queue ID associated with NAME.
+ * If more than one message queue is named name, then the message
+ * queue to which the ID belongs is arbitrary. node indicates the
+ * extent of the search for the ID of the message queue named name.
+ * The search can be limited to a particular node or allowed to
+ * encompass all nodes.
+ */
+
+rtems_status_code rtems_message_queue_ident(
+ rtems_name name,
+ uint32_t node,
+ Objects_Id *id
+);
+
+/*
+ * rtems_message_queue_delete
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_message_queue_delete directive. The
+ * message queue indicated by ID is deleted.
+ */
+
+rtems_status_code rtems_message_queue_delete(
+ Objects_Id id
+);
+
+/*
+ * rtems_message_queue_send
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_message_queue_send directive.
+ * This directive sends the message buffer to the message queue
+ * indicated by ID. If one or more tasks is blocked waiting
+ * to receive a message from this message queue, then one will
+ * receive the message. The task selected to receive the
+ * message is based on the task queue discipline algorithm in
+ * use by this particular message queue. If no tasks are waiting,
+ * then the message buffer will be placed at the REAR of the
+ * chain of pending messages for this message queue.
+ */
+
+rtems_status_code rtems_message_queue_send(
+ Objects_Id id,
+ void *buffer,
+ uint32_t size
+);
+
+/*
+ * rtems_message_queue_urgent
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_message_queue_urgent directive.
+ * This directive has the same behavior as rtems_message_queue_send
+ * except that if no tasks are waiting, the message buffer will
+ * be placed at the FRONT of the chain of pending messages rather
+ * than at the REAR.
+ */
+
+rtems_status_code rtems_message_queue_urgent(
+ Objects_Id id,
+ void *buffer,
+ uint32_t size
+);
+
+/*
+ * rtems_message_queue_broadcast
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_message_queue_broadcast directive.
+ * This directive sends the message buffer to all of the tasks blocked
+ * waiting for a message on the message queue indicated by ID.
+ * If no tasks are waiting, then the message buffer will not be queued.
+ */
+
+rtems_status_code rtems_message_queue_broadcast(
+ Objects_Id id,
+ void *buffer,
+ uint32_t size,
+ uint32_t *count
+);
+
+/*
+ * rtems_message_queue_receive
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_message_queue_receive directive.
+ * This directive is invoked when the calling task wishes to receive
+ * a message from the message queue indicated by ID. The received
+ * message is to be placed in buffer. If no messages are outstanding
+ * and the option_set indicates that the task is willing to block,
+ * then the task will be blocked until a message arrives or until,
+ * optionally, timeout clock ticks have passed.
+ */
+
+rtems_status_code rtems_message_queue_receive(
+ Objects_Id id,
+ void *buffer,
+ uint32_t *size,
+ uint32_t option_set,
+ rtems_interval timeout
+);
+
+/*
+ * rtems_message_queue_flush
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_message_queue_flush directive.
+ * This directive takes all outstanding messages for the message
+ * queue indicated by ID and returns them to the inactive message
+ * chain. The number of messages flushed is returned in COUNT.
+ */
+
+rtems_status_code rtems_message_queue_flush(
+ Objects_Id id,
+ uint32_t *count
+);
+
+/*
+ * rtems_message_queue_get_number_pending
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_message_queue_get_number_pending
+ * directive. This directive returns the number of pending
+ * messages for the message queue indicated by ID
+ * chain. The number of messages pending is returned in COUNT.
+ */
+
+rtems_status_code rtems_message_queue_get_number_pending(
+ Objects_Id id,
+ uint32_t *count
+);
+
+
+/*
+ * _Message_queue_Submit
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the directives rtems_message_queue_send
+ * and rtems_message_queue_urgent. It processes a message that is
+ * to be submitted to the designated message queue. The message will
+ * either be processed as a send send message which it will be inserted
+ * at the rear of the queue or it will be processed as an urgent message
+ * which will be inserted at the front of the queue.
+ */
+
+rtems_status_code _Message_queue_Submit(
+ Objects_Id id,
+ void *buffer,
+ uint32_t size,
+ Message_queue_Submit_types submit_type
+);
+
+/*
+ * _Message_queue_Allocate
+ *
+ * DESCRIPTION:
+ *
+ * This function allocates a message queue control block from
+ * the inactive chain of free message queue control blocks.
+ */
+
+Message_queue_Control *_Message_queue_Allocate (
+ uint32_t count,
+ uint32_t max_message_size
+);
+
+/*
+ * _Message_queue_Translate_core_message_queue_return_code
+ *
+ * DESCRIPTION:
+ *
+ * This function returns a RTEMS status code based on the core message queue
+ * status code specified.
+ */
+
+rtems_status_code _Message_queue_Translate_core_message_queue_return_code (
+ uint32_t the_message_queue_status
+);
+
+/*
+ *
+ * _Message_queue_Core_message_queue_mp_support
+ *
+ * Input parameters:
+ * the_thread - the remote thread the message was submitted to
+ * id - id of the message queue
+ *
+ * Output parameters: NONE
+ */
+
+#if defined(RTEMS_MULTIPROCESSING)
+void _Message_queue_Core_message_queue_mp_support (
+ Thread_Control *the_thread,
+ Objects_Id id
+);
+#endif
+
+#ifndef __RTEMS_APPLICATION__
+#include <rtems/rtems/message.inl>
+#endif
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/rtems/msgmp.h>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/include/rtems/rtems/modes.h b/cpukit/rtems/include/rtems/rtems/modes.h
new file mode 100644
index 0000000000..55b02e89fb
--- /dev/null
+++ b/cpukit/rtems/include/rtems/rtems/modes.h
@@ -0,0 +1,88 @@
+/* modes.h
+ *
+ * This include file contains all constants and structures associated
+ * with the RTEMS thread and RTEMS_ASR modes.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_MODES_h
+#define __RTEMS_MODES_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/isr.h>
+
+/*
+ * The following type defines the control block used to manage
+ * each a mode set.
+ */
+
+typedef uint32_t Modes_Control;
+
+/*
+ * The following constants define the individual modes and masks
+ * which may be used to compose a mode set and to alter modes.
+ */
+
+#define RTEMS_ALL_MODE_MASKS 0x0000ffff
+
+#define RTEMS_DEFAULT_MODES 0x00000000
+#define RTEMS_CURRENT_MODE 0
+
+#define RTEMS_PREEMPT_MASK 0x00000100 /* preemption bit */
+#define RTEMS_TIMESLICE_MASK 0x00000200 /* timeslice bit */
+#define RTEMS_ASR_MASK 0x00000400 /* RTEMS_ASR enable bit */
+#define RTEMS_INTERRUPT_MASK CPU_MODES_INTERRUPT_MASK
+
+#define RTEMS_PREEMPT 0x00000000 /* enable preemption */
+#define RTEMS_NO_PREEMPT 0x00000100 /* disable preemption */
+
+#define RTEMS_NO_TIMESLICE 0x00000000 /* disable timeslicing */
+#define RTEMS_TIMESLICE 0x00000200 /* enable timeslicing */
+
+#define RTEMS_ASR 0x00000000 /* enable RTEMS_ASR */
+#define RTEMS_NO_ASR 0x00000400 /* disable RTEMS_ASR */
+
+/*
+ * The number of bits for interrupt levels is CPU dependent.
+ * RTEMS supports 0 to 256 levels in bits 0-7 of the mode.
+ */
+
+/*PAGE
+ *
+ * RTEMS_INTERRUPT_LEVEL
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the processor dependent interrupt
+ * level which corresponds to the requested interrupt level.
+ *
+ * NOTE: RTEMS supports 256 interrupt levels using the least
+ * significant eight bits of MODES.CONTROL. On any
+ * particular CPU, fewer than 256 levels may be supported.
+ */
+
+#define RTEMS_INTERRUPT_LEVEL( _mode_set ) \
+ ( (_mode_set) & RTEMS_INTERRUPT_MASK )
+
+
+#ifndef __RTEMS_APPLICATION__
+#include <rtems/rtems/modes.inl>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/include/rtems/rtems/mp.h b/cpukit/rtems/include/rtems/rtems/mp.h
new file mode 100644
index 0000000000..1688b09988
--- /dev/null
+++ b/cpukit/rtems/include/rtems/rtems/mp.h
@@ -0,0 +1,52 @@
+/* mp.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the Multiprocessing Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_MP_h
+#define __RTEMS_MP_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ *
+ * _Multiprocessing_Manager_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this manager.
+ */
+
+void _Multiprocessing_Manager_initialization ( void );
+
+/*
+ *
+ * rtems_multiprocessing_announce
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the MULTIPROCESSING_ANNOUNCE directive.
+ * It is invoked by the MPCI layer to indicate that an MPCI packet
+ * has been received.
+ */
+
+void rtems_multiprocessing_announce ( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/include/rtems/rtems/msgmp.h b/cpukit/rtems/include/rtems/rtems/msgmp.h
new file mode 100644
index 0000000000..c954fb90d6
--- /dev/null
+++ b/cpukit/rtems/include/rtems/rtems/msgmp.h
@@ -0,0 +1,176 @@
+/* msgmp.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the Multiprocessing Support in the Message Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_MESSAGE_QUEUE_MP_h
+#define __RTEMS_MESSAGE_QUEUE_MP_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/rtems/message.h>
+#include <rtems/score/mppkt.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/options.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/watchdog.h>
+
+/*
+ * The following enumerated type defines the list of
+ * remote message queue operations.
+ */
+
+typedef enum {
+ MESSAGE_QUEUE_MP_ANNOUNCE_CREATE = 0,
+ MESSAGE_QUEUE_MP_ANNOUNCE_DELETE = 1,
+ MESSAGE_QUEUE_MP_EXTRACT_PROXY = 2,
+ MESSAGE_QUEUE_MP_RECEIVE_REQUEST = 3,
+ MESSAGE_QUEUE_MP_RECEIVE_RESPONSE = 4,
+ MESSAGE_QUEUE_MP_SEND_REQUEST = 5,
+ MESSAGE_QUEUE_MP_SEND_RESPONSE = 6,
+ MESSAGE_QUEUE_MP_URGENT_REQUEST = 7,
+ MESSAGE_QUEUE_MP_URGENT_RESPONSE = 8,
+ MESSAGE_QUEUE_MP_BROADCAST_REQUEST = 9,
+ MESSAGE_QUEUE_MP_BROADCAST_RESPONSE = 10,
+ MESSAGE_QUEUE_MP_FLUSH_REQUEST = 11,
+ MESSAGE_QUEUE_MP_FLUSH_RESPONSE = 12,
+ MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_REQUEST = 13,
+ MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_RESPONSE = 14
+} Message_queue_MP_Remote_operations;
+
+/*
+ * The following data structure defines the packet used to perform
+ * remote message queue operations.
+ */
+
+typedef struct {
+ rtems_packet_prefix Prefix;
+ Message_queue_MP_Remote_operations operation;
+ rtems_name name;
+ rtems_option option_set;
+ Objects_Id proxy_id;
+ uint32_t count;
+ uint32_t size;
+ uint32_t pad0;
+ CORE_message_queue_Buffer Buffer;
+} Message_queue_MP_Packet;
+
+/*
+ * _Message_queue_MP_Send_process_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * process operation can be performed on another node.
+ */
+
+void _Message_queue_MP_Send_process_packet (
+ Message_queue_MP_Remote_operations operation,
+ Objects_Id message_queue_id,
+ rtems_name name,
+ Objects_Id proxy_id
+);
+
+/*
+ * _Message_queue_MP_Send_request_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * directive operation can be initiated on another node.
+ */
+
+rtems_status_code _Message_queue_MP_Send_request_packet (
+ Message_queue_MP_Remote_operations operation,
+ Objects_Id message_queue_id,
+ void *buffer,
+ uint32_t *size_p,
+ rtems_option option_set,
+ Watchdog_Interval timeout
+);
+
+/*
+ * _Message_queue_MP_Send_response_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * directive can be performed on another node.
+ */
+
+void _Message_queue_MP_Send_response_packet (
+ Message_queue_MP_Remote_operations operation,
+ Objects_Id message_queue_id,
+ Thread_Control *the_thread
+);
+
+/*
+ *
+ * _Message_queue_MP_Process_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the actions specific to this package for
+ * the request from another node.
+ */
+
+void _Message_queue_MP_Process_packet (
+ rtems_packet_prefix *the_packet_prefix
+);
+
+/*
+ * _Message_queue_MP_Send_object_was_deleted
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked indirectly by the thread queue
+ * when a proxy has been removed from the thread queue and
+ * the remote node must be informed of this.
+ */
+
+void _Message_queue_MP_Send_object_was_deleted (
+ Thread_Control *the_proxy
+);
+
+/*
+ * _Message_queue_MP_Send_extract_proxy
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked when a task is deleted and it
+ * has a proxy which must be removed from a thread queue and
+ * the remote node must be informed of this.
+ */
+
+void _Message_queue_MP_Send_extract_proxy (
+ void *argument
+);
+
+/*
+ * _Message_queue_MP_Get_packet
+ *
+ * DESCRIPTION:
+ *
+ * This function is used to obtain a message queue mp packet.
+ */
+
+Message_queue_MP_Packet *_Message_queue_MP_Get_packet ( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of file */
diff --git a/cpukit/rtems/include/rtems/rtems/options.h b/cpukit/rtems/include/rtems/rtems/options.h
new file mode 100644
index 0000000000..aaad18ddd5
--- /dev/null
+++ b/cpukit/rtems/include/rtems/rtems/options.h
@@ -0,0 +1,52 @@
+/* options.h
+ *
+ * This include file contains information which defines the
+ * options available on many directives.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_OPTIONS_h
+#define __RTEMS_OPTIONS_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * The following type defines the control block used to manage
+ * option sets.
+ */
+
+typedef uint32_t rtems_option;
+
+/*
+ * The following constants define the individual options which may
+ * be used to compose an option set.
+ */
+
+#define RTEMS_DEFAULT_OPTIONS 0x00000000
+
+#define RTEMS_WAIT 0x00000000 /* wait on resource */
+#define RTEMS_NO_WAIT 0x00000001 /* do not wait on resource */
+
+#define RTEMS_EVENT_ALL 0x00000000 /* wait for all events */
+#define RTEMS_EVENT_ANY 0x00000002 /* wait on any event */
+
+#ifndef __RTEMS_APPLICATION__
+#include <rtems/rtems/options.inl>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/include/rtems/rtems/part.h b/cpukit/rtems/include/rtems/rtems/part.h
new file mode 100644
index 0000000000..9f1a112bc8
--- /dev/null
+++ b/cpukit/rtems/include/rtems/rtems/part.h
@@ -0,0 +1,169 @@
+/* partition.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the Partition Manager. This manager provides facilities to
+ * dynamically allocate memory in fixed-sized units which are returned
+ * as buffers.
+ *
+ * Directives provided are:
+ *
+ * + create a partition
+ * + get an ID of a partition
+ * + delete a partition
+ * + get a buffer from a partition
+ * + return a buffer to a partition
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_PARTITION_h
+#define __RTEMS_PARTITION_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/address.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/attr.h>
+#include <rtems/rtems/types.h>
+
+/*
+ * The following defines the control block used to manage each partition.
+ */
+
+typedef struct {
+ Objects_Control Object;
+ void *starting_address; /* physical address */
+ uint32_t length; /* in bytes */
+ uint32_t buffer_size; /* in bytes */
+ rtems_attribute attribute_set; /* attributes */
+ uint32_t number_of_used_blocks; /* or allocated buffers */
+ Chain_Control Memory; /* buffer chain */
+} Partition_Control;
+
+/*
+ * The following defines the information control block used to
+ * manage this class of objects.
+ */
+
+RTEMS_EXTERN Objects_Information _Partition_Information;
+
+/*
+ * _Partition_Manager_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this manager.
+ */
+
+void _Partition_Manager_initialization(
+ uint32_t maximum_partitions
+);
+
+/*
+ * rtems_partition_create
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_partition_create directive. The
+ * partition will have the name name. The memory area managed by
+ * the partition is of length bytes and starts at starting_address.
+ * The memory area will be divided into as many buffers of
+ * buffer_size bytes as possible. The attribute_set determines if
+ * the partition is global or local. It returns the id of the
+ * created partition in ID.
+ */
+
+rtems_status_code rtems_partition_create(
+ rtems_name name,
+ void *starting_address,
+ uint32_t length,
+ uint32_t buffer_size,
+ rtems_attribute attribute_set,
+ Objects_Id *id
+);
+
+/*
+ * rtems_partition_ident
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_partition_ident directive.
+ * This directive returns the partition ID associated with name.
+ * If more than one partition is named name, then the partition
+ * to which the ID belongs is arbitrary. node indicates the
+ * extent of the search for the ID of the partition named name.
+ * The search can be limited to a particular node or allowed to
+ * encompass all nodes.
+ */
+
+rtems_status_code rtems_partition_ident(
+ rtems_name name,
+ uint32_t node,
+ Objects_Id *id
+);
+
+/*
+ * rtems_partition_delete
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_partition_delete directive. The
+ * partition indicated by ID is deleted.
+ */
+
+rtems_status_code rtems_partition_delete(
+ Objects_Id id
+);
+
+/*
+ * rtems_partition_get_buffer
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_partition_get_buffer directive. It
+ * attempts to allocate a buffer from the partition associated with ID.
+ * If a buffer is allocated, its address is returned in buffer.
+ */
+
+rtems_status_code rtems_partition_get_buffer(
+ Objects_Id id,
+ void **buffer
+);
+
+/*
+ * rtems_partition_return_buffer
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_partition_return_buffer directive. It
+ * frees the buffer to the partition associated with ID. The buffer must
+ * have been previously allocated from the same partition.
+ */
+
+rtems_status_code rtems_partition_return_buffer(
+ Objects_Id id,
+ void *buffer
+);
+
+#ifndef __RTEMS_APPLICATION__
+#include <rtems/rtems/part.inl>
+#endif
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/rtems/partmp.h>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/include/rtems/rtems/partmp.h b/cpukit/rtems/include/rtems/rtems/partmp.h
new file mode 100644
index 0000000000..9d43924291
--- /dev/null
+++ b/cpukit/rtems/include/rtems/rtems/partmp.h
@@ -0,0 +1,160 @@
+/* partmp.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the Multiprocessing Support in the Partition Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_PARTITION_MP_h
+#define __RTEMS_PARTITION_MP_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/mppkt.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/options.h>
+#include <rtems/score/thread.h>
+
+#include <rtems/rtems/part.h>
+
+/*
+ * The following enumerated type defines the list of
+ * remote partition operations.
+ */
+
+typedef enum {
+ PARTITION_MP_ANNOUNCE_CREATE = 0,
+ PARTITION_MP_ANNOUNCE_DELETE = 1,
+ PARTITION_MP_EXTRACT_PROXY = 2,
+ PARTITION_MP_GET_BUFFER_REQUEST = 3,
+ PARTITION_MP_GET_BUFFER_RESPONSE = 4,
+ PARTITION_MP_RETURN_BUFFER_REQUEST = 5,
+ PARTITION_MP_RETURN_BUFFER_RESPONSE = 6
+} Partition_MP_Remote_operations;
+
+/*
+ * The following data structure defines the packet used to perform
+ * remote partition operations.
+ */
+
+typedef struct {
+ rtems_packet_prefix Prefix;
+ Partition_MP_Remote_operations operation;
+ rtems_name name;
+ void *buffer;
+ Objects_Id proxy_id;
+} Partition_MP_Packet;
+
+/*
+ * _Partition_MP_Send_process_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * process operation can be performed on another node.
+ */
+
+void _Partition_MP_Send_process_packet (
+ Partition_MP_Remote_operations operation,
+ Objects_Id partition_id,
+ rtems_name name,
+ Objects_Id proxy_id
+);
+
+/*
+ * _Partition_MP_Send_request_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * directive operation can be initiated on another node.
+ */
+
+rtems_status_code _Partition_MP_Send_request_packet (
+ Partition_MP_Remote_operations operation,
+ Objects_Id partition_id,
+ void *buffer
+);
+
+/*
+ * _Partition_MP_Send_response_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * directive can be performed on another node.
+ */
+
+void _Partition_MP_Send_response_packet (
+ Partition_MP_Remote_operations operation,
+ Objects_Id partition_id,
+ Thread_Control *the_thread
+);
+
+/*
+ *
+ * _Partition_MP_Process_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the actions specific to this package for
+ * the request from another node.
+ */
+
+void _Partition_MP_Process_packet (
+ rtems_packet_prefix *the_packet_prefix
+);
+
+/*
+ * _Partition_MP_Send_object_was_deleted
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked indirectly by the thread queue
+ * when a proxy has been removed from the thread queue and
+ * the remote node must be informed of this.
+ *
+ * This routine is not needed by the Partition since a partition
+ * cannot be deleted when buffers are in use.
+ */
+
+/*
+ * _Partition_MP_Send_extract_proxy
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked when a task is deleted and it
+ * has a proxy which must be removed from a thread queue and
+ * the remote node must be informed of this.
+ */
+
+void _Partition_MP_Send_extract_proxy (
+ void *argument
+);
+
+/*
+ * _Partition_MP_Get_packet
+ *
+ * DESCRIPTION:
+ *
+ * This function is used to obtain a partition mp packet.
+ */
+
+Partition_MP_Packet *_Partition_MP_Get_packet ( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of file */
diff --git a/cpukit/rtems/include/rtems/rtems/ratemon.h b/cpukit/rtems/include/rtems/rtems/ratemon.h
new file mode 100644
index 0000000000..d80f10caf5
--- /dev/null
+++ b/cpukit/rtems/include/rtems/rtems/ratemon.h
@@ -0,0 +1,213 @@
+/* ratemon.h
+ *
+ * This include file contains all the constants, structures, and
+ * prototypes associated with the Rate Monotonic Manager. This manager
+ * provides facilities to implement tasks which execute in a periodic fashion.
+ *
+ * Directives provided are:
+ *
+ * + create a rate monotonic timer
+ * + cancel a period
+ * + delete a rate monotonic timer
+ * + conclude current and start the next period
+ * + obtain status information on a period
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_RATE_MONOTONIC_h
+#define __RTEMS_RATE_MONOTONIC_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/watchdog.h>
+
+/*
+ * The following enumerated type defines the states in which a
+ * period may be.
+ */
+
+typedef enum {
+ RATE_MONOTONIC_INACTIVE, /* off chain, never initialized */
+ RATE_MONOTONIC_OWNER_IS_BLOCKING, /* on chain, owner is blocking on it */
+ RATE_MONOTONIC_ACTIVE, /* on chain, running continuously */
+ RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING, /* on chain, expired while owner was */
+ /* was blocking on it */
+ RATE_MONOTONIC_EXPIRED /* off chain, will be reset by next */
+ /* rtems_rate_monotonic_period */
+} rtems_rate_monotonic_period_states;
+
+/*
+ * The following constant is the interval passed to the rate_monontonic_period
+ * directive to obtain status information.
+ */
+
+#define RTEMS_PERIOD_STATUS WATCHDOG_NO_TIMEOUT
+
+/*
+ * The following defines the period status structure.
+ */
+
+typedef struct {
+ rtems_rate_monotonic_period_states state;
+ uint32_t ticks_since_last_period;
+ uint32_t ticks_executed_since_last_period;
+} rtems_rate_monotonic_period_status;
+
+/*
+ * The following structure defines the control block used to manage
+ * each period.
+ */
+
+typedef struct {
+ Objects_Control Object;
+ Watchdog_Control Timer;
+ rtems_rate_monotonic_period_states state;
+ uint32_t owner_ticks_executed_at_period;
+ uint32_t time_at_period;
+ uint32_t next_length;
+ Thread_Control *owner;
+} Rate_monotonic_Control;
+
+RTEMS_EXTERN Objects_Information _Rate_monotonic_Information;
+
+/*
+ * _Rate_monotonic_Manager_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this manager.
+ */
+
+void _Rate_monotonic_Manager_initialization(
+ uint32_t maximum_periods
+);
+
+/*
+ * rtems_rate_monotonic_create
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rate_monotonic_create directive. The
+ * period will have the name name. It returns the id of the
+ * created period in ID.
+ */
+
+rtems_status_code rtems_rate_monotonic_create(
+ rtems_name name,
+ Objects_Id *id
+);
+
+/*
+ * rtems_rate_monotonic_ident
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_rate_monotonic_ident directive.
+ * This directive returns the period ID associated with name.
+ * If more than one period is named name, then the period
+ * to which the ID belongs is arbitrary.
+ */
+
+rtems_status_code rtems_rate_monotonic_ident(
+ rtems_name name,
+ Objects_Id *id
+);
+
+/*
+ * rtems_rate_monotonic_cancel
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_rate_monotonic_cancel directive. This
+ * directive stops the period associated with ID from continuing to
+ * run.
+ */
+
+rtems_status_code rtems_rate_monotonic_cancel(
+ Objects_Id id
+);
+
+/*
+ * rtems_rate_monotonic_delete
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_rate_monotonic_delete directive. The
+ * period indicated by ID is deleted.
+ */
+
+rtems_status_code rtems_rate_monotonic_delete(
+ Objects_Id id
+);
+
+/*
+ * rtems_rate_monotonic_get_status
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_rate_monotonic_get_status directive.
+ * Information about the period indicated by ID is returned.
+ *
+ */
+
+rtems_status_code rtems_rate_monotonic_get_status(
+ Objects_Id id,
+ rtems_rate_monotonic_period_status *status
+);
+
+/*
+ * rtems_rate_monotonic_period
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_rate_monotonic_period directive. When
+ * length is non-zero, this directive initiates the period associated with
+ * ID from continuing for a period of length. If length is zero, then
+ * result is set to indicate the current state of the period.
+ */
+
+rtems_status_code rtems_rate_monotonic_period(
+ Objects_Id id,
+ rtems_interval length
+);
+
+/*
+ * _Rate_monotonic_Timeout
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked when the period represented
+ * by ID expires. If the task which owns this period is blocked
+ * waiting for the period to expire, then it is readied and the
+ * period is restarted. If the owning task is not waiting for the
+ * period to expire, then the period is placed in the EXPIRED
+ * state and not restarted.
+ */
+
+void _Rate_monotonic_Timeout (
+ Objects_Id id,
+ void *ignored
+);
+
+#ifndef __RTEMS_APPLICATION__
+#include <rtems/rtems/ratemon.inl>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/include/rtems/rtems/region.h b/cpukit/rtems/include/rtems/rtems/region.h
new file mode 100644
index 0000000000..c3e5febd32
--- /dev/null
+++ b/cpukit/rtems/include/rtems/rtems/region.h
@@ -0,0 +1,252 @@
+/* region.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the Region Manager. This manager provides facilities to dynamically
+ * allocate memory in variable sized units which are returned as segments.
+ *
+ * Directives provided are:
+ *
+ * + create a region
+ * + get an ID of a region
+ * + delete a region
+ * + get a segment from a region
+ * + return a segment to a region
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_REGION_h
+#define __RTEMS_REGION_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stddef.h>
+
+#include <rtems/score/object.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/heap.h>
+#include <rtems/debug.h>
+#include <rtems/rtems/attr.h>
+#include <rtems/rtems/types.h>
+
+/*
+ * The following records define the control block used to manage
+ * each region.
+ */
+
+typedef struct {
+ Objects_Control Object;
+ Thread_queue_Control Wait_queue; /* waiting threads */
+ void *starting_address; /* physical start addr */
+ uint32_t length; /* physical length(bytes) */
+ uint32_t page_size; /* in bytes */
+ uint32_t maximum_segment_size; /* in bytes */
+ rtems_attribute attribute_set;
+ uint32_t number_of_used_blocks; /* blocks allocated */
+ Heap_Control Memory;
+} Region_Control;
+
+/*
+ * The following defines the information control block used to
+ * manage this class of objects.
+ */
+
+RTEMS_EXTERN Objects_Information _Region_Information;
+
+/*
+ * _Region_Manager_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this manager.
+ */
+
+void _Region_Manager_initialization(
+ uint32_t maximum_regions
+);
+
+/*
+ * rtems_region_create
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_region_create directive. The
+ * region will have the name name. The memory area managed by
+ * the region is of length bytes and starts at starting_address.
+ * The memory area will be divided into as many allocatable units of
+ * page_size bytes as possible. The attribute_set determines which
+ * thread queue discipline is used by the region. It returns the
+ * id of the created region in ID.
+ */
+
+rtems_status_code rtems_region_create(
+ rtems_name name,
+ void *starting_address,
+ uint32_t length,
+ uint32_t page_size,
+ rtems_attribute attribute_set,
+ Objects_Id *id
+);
+
+/*
+ * rtems_region_extend
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_region_extend directive. The
+ * region will have the name name. The memory area managed by
+ * the region will be attempted to be grown by length bytes using
+ * the memory starting at starting_address.
+ */
+
+rtems_status_code rtems_region_extend(
+ Objects_Id id,
+ void *starting_address,
+ uint32_t length
+);
+
+/*
+ * rtems_region_ident
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_region_ident directive.
+ * This directive returns the region ID associated with name.
+ * If more than one region is named name, then the region
+ * to which the ID belongs is arbitrary.
+ */
+
+rtems_status_code rtems_region_ident(
+ rtems_name name,
+ Objects_Id *id
+);
+
+/*
+ * rtems_region_ident
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_region_get_information directive.
+ * This directive returns information about the heap associated with
+ * this region.
+ */
+
+rtems_status_code rtems_region_get_information(
+ Objects_Id id,
+ Heap_Information_block *the_info
+);
+
+/*
+ * rtems_region_delete
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_region_delete directive. The
+ * region indicated by ID is deleted.
+ */
+
+rtems_status_code rtems_region_delete(
+ Objects_Id id
+);
+
+/*
+ * rtems_region_get_segment
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_region_get_segment directive. It
+ * attempts to allocate a segment from the region associated with ID.
+ * If a segment of the requested size can be allocated, its address
+ * is returned in segment. If no segment is available, then the task
+ * may return immediately or block waiting for a segment with an optional
+ * timeout of timeout clock ticks. Whether the task blocks or returns
+ * immediately is based on the no_wait option in the option_set.
+ */
+
+rtems_status_code rtems_region_get_segment(
+ Objects_Id id,
+ uint32_t size,
+ rtems_option option_set,
+ rtems_interval timeout,
+ void **segment
+);
+
+/*
+ * rtems_region_get_segment_size
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_region_get_segment_size directive. It
+ * returns the size in bytes of the specified user memory area.
+ */
+
+rtems_status_code rtems_region_get_segment_size(
+ Objects_Id id,
+ void *segment,
+ size_t *size
+);
+
+/*
+ * rtems_region_return_segment
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_region_return_segment directive. It
+ * frees the segment to the region associated with ID. The segment must
+ * have been previously allocated from the same region. If freeing the
+ * segment results in enough memory being available to satisfy the
+ * rtems_region_get_segment of the first blocked task, then that task and as
+ * many subsequent tasks as possible will be unblocked with their requests
+ * satisfied.
+ */
+
+rtems_status_code rtems_region_return_segment(
+ Objects_Id id,
+ void *segment
+);
+
+#ifndef __RTEMS_APPLICATION__
+#include <rtems/rtems/region.inl>
+#endif
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/rtems/regionmp.h>
+#endif
+
+/*
+ * _Region_Debug_Walk
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked to verify the integrity of a heap associated
+ * with the_region.
+ */
+
+#ifdef RTEMS_DEBUG
+
+#define _Region_Debug_Walk( _the_region, _source ) \
+ do { \
+ if ( _Debug_Is_enabled( RTEMS_DEBUG_REGION ) ) \
+ _Heap_Walk( &(_the_region)->Memory, _source, FALSE ); \
+ } while ( 0 )
+
+#else
+
+#define _Region_Debug_Walk( _the_region, _source )
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/include/rtems/rtems/regionmp.h b/cpukit/rtems/include/rtems/rtems/regionmp.h
new file mode 100644
index 0000000000..105621bdc7
--- /dev/null
+++ b/cpukit/rtems/include/rtems/rtems/regionmp.h
@@ -0,0 +1,165 @@
+/* regionmp.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the Multiprocessing Support in the Region Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_REGION_MP_h
+#define __RTEMS_REGION_MP_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/mppkt.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/region.h>
+
+/*
+ * The following enumerated type defines the list of
+ * remote region operations.
+ */
+
+typedef enum {
+ REGION_MP_ANNOUNCE_CREATE = 0,
+ REGION_MP_ANNOUNCE_DELETE = 1,
+ REGION_MP_EXTRACT_PROXY = 2,
+ REGION_MP_GET_SEGMENT_REQUEST = 3,
+ REGION_MP_GET_SEGMENT_RESPONSE = 4,
+ REGION_MP_RETURN_SEGMENT_REQUEST = 5,
+ REGION_MP_RETURN_SEGMENT_RESPONSE = 6
+} Region_MP_Remote_operations;
+
+/*
+ * The following data structure defines the packet used to perform
+ * remote region operations.
+ */
+
+typedef struct {
+ rtems_packet_prefix Prefix;
+ Region_MP_Remote_operations operation;
+ rtems_name name;
+ rtems_option option_set;
+ uint32_t size;
+ Objects_Id proxy_id;
+ void *segment;
+} Region_MP_Packet;
+
+/*
+ * _Region_MP_Send_process_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * process operation can be performed on another node.
+ */
+
+void _Region_MP_Send_process_packet (
+ Region_MP_Remote_operations operation,
+ Objects_Id region_id,
+ rtems_name name,
+ Objects_Id proxy_id
+);
+
+/*
+ * _Region_MP_Send_request_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * directive operation can be initiated on another node.
+ */
+
+rtems_status_code _Region_MP_Send_request_packet (
+ Region_MP_Remote_operations operation,
+ Objects_Id region_id,
+ void *segment,
+ uint32_t size,
+ rtems_option option_set,
+ rtems_interval timeout
+);
+
+/*
+ * _Region_MP_Send_response_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * directive can be performed on another node.
+ */
+
+void _Region_MP_Send_response_packet (
+ Region_MP_Remote_operations operation,
+ Objects_Id region_id,
+ Thread_Control *the_thread
+);
+
+/*
+ *
+ * _Region_MP_Process_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the actions specific to this package for
+ * the request from another node.
+ */
+
+void _Region_MP_Process_packet (
+ rtems_packet_prefix *the_packet_prefix
+);
+
+/*
+ * _Region_MP_Send_object_was_deleted
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked indirectly by the thread queue
+ * when a proxy has been removed from the thread queue and
+ * the remote node must be informed of this.
+ *
+ * This routine is not needed by the Region since a region
+ * cannot be deleted when segments are in use.
+ */
+
+/*
+ * _Region_MP_Send_extract_proxy
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked when a task is deleted and it
+ * has a proxy which must be removed from a thread queue and
+ * the remote node must be informed of this.
+ */
+
+void _Region_MP_Send_extract_proxy (
+ void *argument
+);
+
+/*
+ * _Region_MP_Get_packet
+ *
+ * DESCRIPTION:
+ *
+ * This function is used to obtain a region mp packet.
+ */
+
+Region_MP_Packet *_Region_MP_Get_packet ( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of file */
diff --git a/cpukit/rtems/include/rtems/rtems/rtemsapi.h b/cpukit/rtems/include/rtems/rtems/rtemsapi.h
new file mode 100644
index 0000000000..bc7adaf232
--- /dev/null
+++ b/cpukit/rtems/include/rtems/rtems/rtemsapi.h
@@ -0,0 +1,35 @@
+/*
+ * RTEMS API Support
+ *
+ * NOTE:
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_API_h
+#define __RTEMS_API_h
+
+#include <rtems/config.h>
+
+/*PAGE
+ *
+ * _RTEMS_API_Initialize
+ *
+ * This routine initializes the RTEMS API by invoking the initialization
+ * routine for each RTEMS manager with the appropriate parameters
+ * from the configuration_table.
+ */
+
+void _RTEMS_API_Initialize(
+ rtems_configuration_table *configuration_table
+);
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/include/rtems/rtems/sem.h b/cpukit/rtems/include/rtems/rtems/sem.h
new file mode 100644
index 0000000000..8ed92843de
--- /dev/null
+++ b/cpukit/rtems/include/rtems/rtems/sem.h
@@ -0,0 +1,276 @@
+/* semaphore.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the Semaphore Manager. This manager utilizes standard Dijkstra
+ * counting semaphores to provide synchronization and mutual exclusion
+ * capabilities.
+ *
+ * Directives provided are:
+ *
+ * + create a semaphore
+ * + get an ID of a semaphore
+ * + delete a semaphore
+ * + acquire a semaphore
+ * + release a semaphore
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_SEMAPHORE_h
+#define __RTEMS_SEMAPHORE_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/rtems/types.h>
+#include <rtems/rtems/support.h>
+#include <rtems/rtems/tasks.h>
+#include <rtems/rtems/attr.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/object.h>
+#include <rtems/score/coresem.h>
+#include <rtems/score/threadq.h>
+
+/*
+ * The following defines the control block used to manage each semaphore.
+ */
+
+typedef struct {
+ Objects_Control Object;
+ rtems_attribute attribute_set;
+ union {
+ CORE_mutex_Control mutex;
+ CORE_semaphore_Control semaphore;
+ } Core_control;
+} Semaphore_Control;
+
+/*
+ * The following defines the information control block used to manage
+ * this class of objects.
+ */
+
+RTEMS_EXTERN Objects_Information _Semaphore_Information;
+
+/*
+ * _Semaphore_Manager_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this manager.
+ */
+
+void _Semaphore_Manager_initialization(
+ uint32_t maximum_semaphores
+);
+
+/*
+ * rtems_semaphore_create
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_semaphore_create directive. The
+ * semaphore will have the name name. The starting count for
+ * the semaphore is count. The attribute_set determines if
+ * the semaphore is global or local and the thread queue
+ * discipline. It returns the id of the created semaphore in ID.
+ */
+
+rtems_status_code rtems_semaphore_create(
+ rtems_name name,
+ uint32_t count,
+ rtems_attribute attribute_set,
+ rtems_task_priority priority_ceiling,
+ rtems_id *id
+);
+
+/*
+ * rtems_semaphore_ident
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_semaphore_ident directive.
+ * This directive returns the semaphore ID associated with name.
+ * If more than one semaphore is named name, then the semaphore
+ * to which the ID belongs is arbitrary. node indicates the
+ * extent of the search for the ID of the semaphore named name.
+ * The search can be limited to a particular node or allowed to
+ * encompass all nodes.
+ */
+
+rtems_status_code rtems_semaphore_ident(
+ rtems_name name,
+ uint32_t node,
+ rtems_id *id
+);
+
+/*
+ * rtems_semaphore_delete
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_semaphore_delete directive. The
+ * semaphore indicated by ID is deleted.
+ */
+
+rtems_status_code rtems_semaphore_delete(
+ rtems_id id
+);
+
+/*
+ * rtems_semaphore_obtain
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_semaphore_obtain directive. It
+ * attempts to obtain a unit from the semaphore associated with ID.
+ * If a unit can be allocated, the calling task will return immediately.
+ * If no unit is available, then the task may return immediately or
+ * block waiting for a unit with an optional timeout of timeout
+ * clock ticks. Whether the task blocks or returns immediately
+ * is based on the RTEMS_NO_WAIT option in the option_set.
+ */
+
+rtems_status_code rtems_semaphore_obtain(
+ rtems_id id,
+ uint32_t option_set,
+ rtems_interval timeout
+);
+
+/*
+ * rtems_semaphore_release
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_semaphore_release directive. It
+ * frees a unit to the semaphore associated with ID. If a task was
+ * blocked waiting for a unit from this semaphore, then that task will
+ * be readied and the unit given to that task. Otherwise, the unit
+ * will be returned to the semaphore.
+ */
+
+rtems_status_code rtems_semaphore_release(
+ rtems_id id
+);
+
+/*
+ * rtems_semaphore_flush
+ *
+ * This directive allows a thread to flush the threads
+ * pending on the semaphore.
+ */
+
+rtems_status_code rtems_semaphore_flush(
+ Objects_Id id
+);
+
+/*
+ * _Semaphore_Seize
+ *
+ * DESCRIPTION:
+ *
+ * This routine attempts to receive a unit from the_semaphore.
+ * If a unit is available or if the RTEMS_NO_WAIT option is enabled in
+ * option_set, then the routine returns. Otherwise, the calling task
+ * is blocked until a unit becomes available.
+ */
+
+boolean _Semaphore_Seize(
+ Semaphore_Control *the_semaphore,
+ uint32_t option_set
+);
+
+/*
+ * _Semaphore_Translate_core_mutex_return_code
+ *
+ * DESCRIPTION:
+ *
+ * This function returns a RTEMS status code based on the mutex
+ * status code specified.
+ */
+
+rtems_status_code _Semaphore_Translate_core_mutex_return_code (
+ uint32_t the_mutex_status
+);
+
+/*
+ * _Semaphore_Translate_core_semaphore_return_code
+ *
+ * DESCRIPTION:
+ *
+ * This function returns a RTEMS status code based on the semaphore
+ * status code specified.
+ */
+
+rtems_status_code _Semaphore_Translate_core_semaphore_return_code (
+ uint32_t the_mutex_status
+);
+
+/*PAGE
+ *
+ * _Semaphore_Core_mutex_mp_support
+ *
+ * DESCRIPTION:
+ *
+ * This function processes the global actions necessary for remote
+ * accesses to a global semaphore based on a core mutex. This function
+ * is called by the core.
+ */
+
+#if defined(RTEMS_MULTIPROCESSING)
+void _Semaphore_Core_mutex_mp_support (
+ Thread_Control *the_thread,
+ rtems_id id
+);
+#endif
+
+/*PAGE
+ *
+ * _Semaphore_Core_mp_support
+ *
+ * DESCRIPTION:
+ *
+ * This function processes the global actions necessary for remote
+ * accesses to a global semaphore based on a core semaphore. This function
+ * is called by the core.
+ */
+
+void _Semaphore_Core_semaphore_mp_support (
+ Thread_Control *the_thread,
+ rtems_id id
+);
+
+/*PAGE
+ *
+ * _POSIX_Semaphore_MP_support
+ *
+ * DESCRIPTION:
+ *
+ * XXX
+ */
+
+void _POSIX_Semaphore_MP_support(
+ Thread_Control *the_thread,
+ Objects_Id id
+);
+
+#ifndef __RTEMS_APPLICATION__
+#include <rtems/rtems/sem.inl>
+#endif
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/rtems/semmp.h>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/include/rtems/rtems/semmp.h b/cpukit/rtems/include/rtems/rtems/semmp.h
new file mode 100644
index 0000000000..bf987f4dd9
--- /dev/null
+++ b/cpukit/rtems/include/rtems/rtems/semmp.h
@@ -0,0 +1,162 @@
+/* semmp.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the Multiprocessing Support in the Semaphore Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_SEMAPHORE_MP_h
+#define __RTEMS_SEMAPHORE_MP_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/mppkt.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/sem.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/watchdog.h>
+
+/*
+ * The following enumerated type defines the list of
+ * remote semaphore operations.
+ */
+
+typedef enum {
+ SEMAPHORE_MP_ANNOUNCE_CREATE = 0,
+ SEMAPHORE_MP_ANNOUNCE_DELETE = 1,
+ SEMAPHORE_MP_EXTRACT_PROXY = 2,
+ SEMAPHORE_MP_OBTAIN_REQUEST = 3,
+ SEMAPHORE_MP_OBTAIN_RESPONSE = 4,
+ SEMAPHORE_MP_RELEASE_REQUEST = 5,
+ SEMAPHORE_MP_RELEASE_RESPONSE = 6
+} Semaphore_MP_Remote_operations;
+
+/*
+ * The following data structure defines the packet used to perform
+ * remote semaphore operations.
+ */
+
+typedef struct {
+ rtems_packet_prefix Prefix;
+ Semaphore_MP_Remote_operations operation;
+ rtems_name name;
+ rtems_option option_set;
+ Objects_Id proxy_id;
+} Semaphore_MP_Packet;
+
+/*
+ * _Semaphore_MP_Send_process_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * process operation can be performed on another node.
+ */
+
+void _Semaphore_MP_Send_process_packet (
+ Semaphore_MP_Remote_operations operation,
+ Objects_Id semaphore_id,
+ rtems_name name,
+ Objects_Id proxy_id
+);
+
+/*
+ * _Semaphore_MP_Send_request_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * directive operation can be initiated on another node.
+ */
+
+rtems_status_code _Semaphore_MP_Send_request_packet (
+ Semaphore_MP_Remote_operations operation,
+ Objects_Id semaphore_id,
+ rtems_option option_set,
+ rtems_interval timeout
+);
+
+/*
+ * _Semaphore_MP_Send_response_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * directive can be performed on another node.
+ */
+
+void _Semaphore_MP_Send_response_packet (
+ Semaphore_MP_Remote_operations operation,
+ Objects_Id semaphore_id,
+ Thread_Control *the_thread
+);
+
+/*
+ *
+ * _Semaphore_MP_Process_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the actions specific to this package for
+ * the request from another node.
+ */
+
+void _Semaphore_MP_Process_packet (
+ rtems_packet_prefix *the_packet_prefix
+);
+
+/*
+ * _Semaphore_MP_Send_object_was_deleted
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked indirectly by the thread queue
+ * when a proxy has been removed from the thread queue and
+ * the remote node must be informed of this.
+ */
+
+void _Semaphore_MP_Send_object_was_deleted (
+ Thread_Control *the_proxy
+);
+
+/*
+ * _Semaphore_MP_Send_extract_proxy
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked when a task is deleted and it
+ * has a proxy which must be removed from a thread queue and
+ * the remote node must be informed of this.
+ */
+
+void _Semaphore_MP_Send_extract_proxy (
+ void *argument
+);
+
+/*
+ * _Semaphore_MP_Get_packet
+ *
+ * DESCRIPTION:
+ *
+ * This function is used to obtain a semaphore mp packet.
+ */
+
+Semaphore_MP_Packet *_Semaphore_MP_Get_packet ( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of file */
diff --git a/cpukit/rtems/include/rtems/rtems/signal.h b/cpukit/rtems/include/rtems/rtems/signal.h
new file mode 100644
index 0000000000..985e0a24fd
--- /dev/null
+++ b/cpukit/rtems/include/rtems/rtems/signal.h
@@ -0,0 +1,84 @@
+/* signal.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the Signal Manager. This manager provides capabilities required
+ * for asynchronous communication between tasks via signal sets.
+ *
+ * Directives provided are:
+ *
+ * + establish an asynchronous signal routine
+ * + send a signal set to a task
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_SIGNAL_h
+#define __RTEMS_SIGNAL_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/rtems/asr.h>
+#include <rtems/rtems/modes.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/types.h>
+
+/*
+ * _Signal_Manager_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this manager.
+ */
+
+void _Signal_Manager_initialization( void );
+
+/*
+ * rtems_signal_catch
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_signal_catch directive. This directive
+ * is used to establish asr_handler as the Asynchronous Signal Routine
+ * (RTEMS_ASR) for the calling task. The asr_handler will execute with a
+ * mode of mode_set.
+ */
+
+rtems_status_code rtems_signal_catch(
+ rtems_asr_entry asr_handler,
+ rtems_mode mode_set
+);
+
+/*
+ * rtems_signal_send
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_signal_send directive. This directive
+ * sends the signal_set to the task specified by ID.
+ */
+
+rtems_status_code rtems_signal_send(
+ Objects_Id id,
+ rtems_signal_set signal_set
+);
+
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/rtems/signalmp.h>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/include/rtems/rtems/signalmp.h b/cpukit/rtems/include/rtems/rtems/signalmp.h
new file mode 100644
index 0000000000..3f34667288
--- /dev/null
+++ b/cpukit/rtems/include/rtems/rtems/signalmp.h
@@ -0,0 +1,146 @@
+/* signalmp.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the Multiprocessing Support in the Signal Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_SIGNAL_MP_h
+#define __RTEMS_SIGNAL_MP_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/rtems/asr.h>
+#include <rtems/score/mppkt.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/watchdog.h>
+
+/*
+ * The following enumerated type defines the list of
+ * remote signal operations.
+ */
+
+typedef enum {
+ SIGNAL_MP_SEND_REQUEST = 0,
+ SIGNAL_MP_SEND_RESPONSE = 1
+} Signal_MP_Remote_operations;
+
+/*
+ * The following data structure defines the packet used to perform
+ * remote signal operations.
+ */
+
+typedef struct {
+ rtems_packet_prefix Prefix;
+ Signal_MP_Remote_operations operation;
+ rtems_signal_set signal_in;
+} Signal_MP_Packet;
+
+/*
+ * _Signal_MP_Send_process_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * process operation can be performed on another node.
+ *
+ * This routine is not needed since there are no process
+ * packets to be sent by this manager.
+ */
+
+/*
+ * _Signal_MP_Send_request_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * directive operation can be initiated on another node.
+ */
+
+rtems_status_code _Signal_MP_Send_request_packet (
+ Signal_MP_Remote_operations operation,
+ Objects_Id task_id,
+ rtems_signal_set signal_in
+);
+
+/*
+ * _Signal_MP_Send_response_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * directive can be performed on another node.
+ */
+
+void _Signal_MP_Send_response_packet (
+ Signal_MP_Remote_operations operation,
+ Thread_Control *the_thread
+);
+
+/*
+ *
+ * _Signal_MP_Process_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the actions specific to this package for
+ * the request from another node.
+ */
+
+void _Signal_MP_Process_packet (
+ rtems_packet_prefix *the_packet_prefix
+);
+
+/*
+ * _Signal_MP_Send_object_was_deleted
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked indirectly by the thread queue
+ * when a proxy has been removed from the thread queue and
+ * the remote node must be informed of this.
+ *
+ * This routine is not needed since there are no objects
+ * deleted by this manager.
+ */
+
+/*
+ * _Signal_MP_Send_extract_proxy
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked when a task is deleted and it
+ * has a proxy which must be removed from a thread queue and
+ * the remote node must be informed of this.
+ *
+ * This routine is not needed since there are no objects
+ * deleted by this manager.
+ */
+
+/*
+ * _Signal_MP_Get_packet
+ *
+ * DESCRIPTION:
+ *
+ * This function is used to obtain a signal mp packet.
+ */
+
+Signal_MP_Packet *_Signal_MP_Get_packet ( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of file */
diff --git a/cpukit/rtems/include/rtems/rtems/status.h b/cpukit/rtems/include/rtems/rtems/status.h
new file mode 100644
index 0000000000..3510a8ca36
--- /dev/null
+++ b/cpukit/rtems/include/rtems/rtems/status.h
@@ -0,0 +1,85 @@
+/* status.h
+ *
+ * This include file contains the status codes returned from the
+ * executive directives.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_STATUS_h
+#define __RTEMS_STATUS_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* types */
+
+/* enumerated constants */
+
+typedef enum {
+ RTEMS_SUCCESSFUL = 0, /* successful completion */
+ RTEMS_TASK_EXITTED = 1, /* returned from a thread */
+ RTEMS_MP_NOT_CONFIGURED = 2, /* multiprocessing not configured */
+ RTEMS_INVALID_NAME = 3, /* invalid object name */
+ RTEMS_INVALID_ID = 4, /* invalid object id */
+ RTEMS_TOO_MANY = 5, /* too many */
+ RTEMS_TIMEOUT = 6, /* timed out waiting */
+ RTEMS_OBJECT_WAS_DELETED = 7, /* object deleted while waiting */
+ RTEMS_INVALID_SIZE = 8, /* specified size was invalid */
+ RTEMS_INVALID_ADDRESS = 9, /* address specified is invalid */
+ RTEMS_INVALID_NUMBER = 10, /* number was invalid */
+ RTEMS_NOT_DEFINED = 11, /* item has not been initialized */
+ RTEMS_RESOURCE_IN_USE = 12, /* resources still outstanding */
+ RTEMS_UNSATISFIED = 13, /* request not satisfied */
+ RTEMS_INCORRECT_STATE = 14, /* thread is in wrong state */
+ RTEMS_ALREADY_SUSPENDED = 15, /* thread already in state */
+ RTEMS_ILLEGAL_ON_SELF = 16, /* illegal on calling thread */
+ RTEMS_ILLEGAL_ON_REMOTE_OBJECT = 17, /* illegal for remote object */
+ RTEMS_CALLED_FROM_ISR = 18, /* called from wrong environment */
+ RTEMS_INVALID_PRIORITY = 19, /* invalid thread priority */
+ RTEMS_INVALID_CLOCK = 20, /* invalid date/time */
+ RTEMS_INVALID_NODE = 21, /* invalid node id */
+ RTEMS_NOT_CONFIGURED = 22, /* directive not configured */
+ RTEMS_NOT_OWNER_OF_RESOURCE = 23, /* not owner of resource */
+ RTEMS_NOT_IMPLEMENTED = 24, /* directive not implemented */
+ RTEMS_INTERNAL_ERROR = 25, /* RTEMS inconsistency detected */
+ RTEMS_NO_MEMORY = 26, /* could not get enough memory */
+ RTEMS_IO_ERROR = 27, /* driver IO error */
+ RTEMS_PROXY_BLOCKING = 28 /* internal error only */
+} rtems_status_code;
+
+#define RTEMS_STATUS_CODES_FIRST RTEMS_SUCCESSFUL
+#define RTEMS_STATUS_CODES_LAST RTEMS_PROXY_BLOCKING
+
+extern rtems_status_code _Status_Object_name_errors_to_status[];
+
+#ifdef RTEMS_API_INIT
+rtems_status_code _Status_Object_name_errors_to_status[] = {
+ RTEMS_SUCCESSFUL, /* OBJECTS_SUCCESSFUL */
+ RTEMS_INVALID_NAME, /* OBJECTS_INVALID_NAME */
+ RTEMS_INVALID_ADDRESS, /* OBJECTS_INVALID_ADDRESS */
+ RTEMS_INVALID_ID, /* OBJECTS_INVALID_ID */
+ RTEMS_INVALID_NODE /* OBJECTS_INVALID_NODE */
+};
+#endif
+
+/*
+ * Applications are allowed to use the macros to compare status codes.
+ */
+
+#include <rtems/rtems/status.inl>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/include/rtems/rtems/support.h b/cpukit/rtems/include/rtems/rtems/support.h
new file mode 100644
index 0000000000..591bbd736c
--- /dev/null
+++ b/cpukit/rtems/include/rtems/rtems/support.h
@@ -0,0 +1,98 @@
+/* support.h
+ *
+ * This include file contains information about support functions for
+ * the RTEMS API.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_RTEMS_SUPPORT_h
+#define __RTEMS_RTEMS_SUPPORT_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/rtems/types.h>
+
+/*
+ * rtems_build_name
+ *
+ * DESCRIPTION:
+ *
+ * This function returns an object name composed of the four characters
+ * C1, C2, C3, and C4.
+ *
+ * NOTE:
+ *
+ * This must be implemented as a macro for use in Configuration Tables.
+ *
+ */
+
+#define rtems_build_name( _C1, _C2, _C3, _C4 ) \
+ ( (uint32_t )(_C1) << 24 | (uint32_t )(_C2) << 16 | (uint32_t )(_C3) << 8 | (uint32_t )(_C4) )
+
+/*
+ * rtems_get_class
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the class portion of the ID.
+ *
+ */
+
+#define rtems_get_class( _id ) \
+ _Objects_Get_class( _id )
+
+/*
+ * rtems_get_node
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the node portion of the ID.
+ *
+ */
+
+#define rtems_get_node( _id ) \
+ _Objects_Get_node( _id )
+
+/*
+ * rtems_get_index
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the index portion of the ID.
+ *
+ */
+
+#define rtems_get_index( _id ) \
+ _Objects_Get_index( _id )
+
+/*
+ * Time related
+ */
+
+#define RTEMS_MILLISECONDS_TO_MICROSECONDS(_ms) \
+ TOD_MILLISECONDS_TO_MICROSECONDS(_ms)
+#define RTEMS_MILLISECONDS_TO_TICKS(_ms) \
+ TOD_MILLISECONDS_TO_TICKS(_ms)
+#define RTEMS_MICROSECONDS_TO_TICKS(_ms) \
+ TOD_MICROSECONDS_TO_TICKS(_ms)
+
+#ifndef __RTEMS_APPLICATION__
+#include <rtems/rtems/support.inl>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/include/rtems/rtems/taskmp.h b/cpukit/rtems/include/rtems/rtems/taskmp.h
new file mode 100644
index 0000000000..d78a4e6a61
--- /dev/null
+++ b/cpukit/rtems/include/rtems/rtems/taskmp.h
@@ -0,0 +1,166 @@
+/* taskmp.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the multiprocessing support in the task manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_RTEMS_TASKS_MP_h
+#define __RTEMS_RTEMS_TASKS_MP_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/mppkt.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/options.h>
+#include <rtems/score/priority.h>
+#include <rtems/rtems/tasks.h>
+#include <rtems/score/thread.h>
+
+/*
+ * The following enumerated type defines the list of
+ * remote task operations.
+ */
+
+typedef enum {
+ RTEMS_TASKS_MP_ANNOUNCE_CREATE = 0,
+ RTEMS_TASKS_MP_ANNOUNCE_DELETE = 1,
+ RTEMS_TASKS_MP_SUSPEND_REQUEST = 2,
+ RTEMS_TASKS_MP_SUSPEND_RESPONSE = 3,
+ RTEMS_TASKS_MP_RESUME_REQUEST = 4,
+ RTEMS_TASKS_MP_RESUME_RESPONSE = 5,
+ RTEMS_TASKS_MP_SET_PRIORITY_REQUEST = 6,
+ RTEMS_TASKS_MP_SET_PRIORITY_RESPONSE = 7,
+ RTEMS_TASKS_MP_GET_NOTE_REQUEST = 8,
+ RTEMS_TASKS_MP_GET_NOTE_RESPONSE = 9,
+ RTEMS_TASKS_MP_SET_NOTE_REQUEST = 10,
+ RTEMS_TASKS_MP_SET_NOTE_RESPONSE = 11
+} RTEMS_tasks_MP_Remote_operations;
+
+/*
+ * The following data structure defines the packet used to perform
+ * remote task operations.
+ */
+
+typedef struct {
+ rtems_packet_prefix Prefix;
+ RTEMS_tasks_MP_Remote_operations operation;
+ rtems_name name;
+ rtems_task_priority the_priority;
+ uint32_t notepad;
+ uint32_t note;
+} RTEMS_tasks_MP_Packet;
+
+/*
+ * _RTEMS_tasks_MP_Send_process_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * process operation can be performed on another node.
+ */
+
+void _RTEMS_tasks_MP_Send_process_packet (
+ RTEMS_tasks_MP_Remote_operations operation,
+ Objects_Id task_id,
+ rtems_name name
+);
+
+/*
+ * _RTEMS_tasks_MP_Send_request_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * directive operation can be initiated on another node.
+ */
+
+rtems_status_code _RTEMS_tasks_MP_Send_request_packet (
+ RTEMS_tasks_MP_Remote_operations operation,
+ Objects_Id task_id,
+ rtems_task_priority the_priority,
+ uint32_t notepad,
+ uint32_t note
+);
+
+/*
+ * _RTEMS_tasks_MP_Send_response_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * directive can be performed on another node.
+ */
+
+void _RTEMS_tasks_MP_Send_response_packet (
+ RTEMS_tasks_MP_Remote_operations operation,
+ Thread_Control *the_thread
+);
+
+/*
+ *
+ * _RTEMS_tasks_MP_Process_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the actions specific to this package for
+ * the request from another node.
+ */
+
+void _RTEMS_tasks_MP_Process_packet (
+ rtems_packet_prefix *the_packet_prefix
+);
+
+/*
+ * _RTEMS_tasks_MP_Send_object_was_deleted
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked indirectly by the thread queue
+ * when a proxy has been removed from the thread queue and
+ * the remote node must be informed of this.
+ *
+ * This routine is not needed by RTEMS_tasks since a task
+ * cannot be deleted when segments are in use.
+ */
+
+/*
+ * _RTEMS_tasks_MP_Send_extract_proxy
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked when a task is deleted and it
+ * has a proxy which must be removed from a thread queue and
+ * the remote node must be informed of this.
+ *
+ * This routine is not needed since there are no objects
+ * deleted by this manager.
+ *
+ */
+
+/*
+ * _RTEMS_tasks_MP_Get_packet
+ *
+ * DESCRIPTION:
+ *
+ * This function is used to obtain a task mp packet.
+ */
+
+RTEMS_tasks_MP_Packet *_RTEMS_tasks_MP_Get_packet ( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of file */
diff --git a/cpukit/rtems/include/rtems/rtems/tasks.h b/cpukit/rtems/include/rtems/rtems/tasks.h
new file mode 100644
index 0000000000..1445546c69
--- /dev/null
+++ b/cpukit/rtems/include/rtems/rtems/tasks.h
@@ -0,0 +1,467 @@
+/* tasks.h
+ *
+ * This include file contains all constants and structures associated
+ * with RTEMS tasks. This manager provides a comprehensive set of directives
+ * to create, delete, and administer tasks.
+ *
+ * Directives provided are:
+ *
+ * + create a task
+ * + get an ID of a task
+ * + start a task
+ * + restart a task
+ * + delete a task
+ * + suspend a task
+ * + resume a task
+ * + set a task's priority
+ * + change the current task's mode
+ * + get a task notepad entry
+ * + set a task notepad entry
+ * + wake up after interval
+ * + wake up when specified
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_RTEMS_TASKS_h
+#define __RTEMS_RTEMS_TASKS_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/rtems/types.h>
+#include <rtems/rtems/eventset.h>
+#include <rtems/rtems/asr.h>
+#include <rtems/rtems/attr.h>
+#include <rtems/rtems/status.h>
+
+/*
+ * Constant to be used as the ID of current task
+ */
+
+#define RTEMS_SELF OBJECTS_ID_OF_SELF
+
+/*
+ * This constant is passed to the rtems_task_wake_after directive as the
+ * interval when a task wishes to yield the CPU.
+ */
+
+#define RTEMS_YIELD_PROCESSOR WATCHDOG_NO_TIMEOUT
+
+/*
+ * Define the type for an RTEMS API task priority.
+ */
+
+typedef Priority_Control rtems_task_priority;
+
+#define RTEMS_NO_PRIORITY RTEMS_CURRENT_PRIORITY
+
+#define RTEMS_MINIMUM_PRIORITY (PRIORITY_MINIMUM + 1)
+#define RTEMS_MAXIMUM_PRIORITY PRIORITY_MAXIMUM
+
+/*
+ * The following constant is passed to rtems_task_set_priority when the
+ * caller wants to obtain the current priority.
+ */
+
+#define RTEMS_CURRENT_PRIORITY PRIORITY_MINIMUM
+
+/*
+ * Notepads constants (indices into notepad array)
+ */
+
+#define RTEMS_NOTEPAD_FIRST 0 /* lowest numbered notepad */
+#define RTEMS_NOTEPAD_0 0 /* notepad location 0 */
+#define RTEMS_NOTEPAD_1 1 /* notepad location 1 */
+#define RTEMS_NOTEPAD_2 2 /* notepad location 2 */
+#define RTEMS_NOTEPAD_3 3 /* notepad location 3 */
+#define RTEMS_NOTEPAD_4 4 /* notepad location 4 */
+#define RTEMS_NOTEPAD_5 5 /* notepad location 5 */
+#define RTEMS_NOTEPAD_6 6 /* notepad location 6 */
+#define RTEMS_NOTEPAD_7 7 /* notepad location 7 */
+#define RTEMS_NOTEPAD_8 8 /* notepad location 8 */
+#define RTEMS_NOTEPAD_9 9 /* notepad location 9 */
+#define RTEMS_NOTEPAD_10 10 /* notepad location 10 */
+#define RTEMS_NOTEPAD_11 11 /* notepad location 11 */
+#define RTEMS_NOTEPAD_12 12 /* notepad location 12 */
+#define RTEMS_NOTEPAD_13 13 /* notepad location 13 */
+#define RTEMS_NOTEPAD_14 14 /* notepad location 14 */
+#define RTEMS_NOTEPAD_15 15 /* notepad location 15 */
+#define RTEMS_NOTEPAD_LAST RTEMS_NOTEPAD_15 /* highest numbered notepad */
+
+#define RTEMS_NUMBER_NOTEPADS (RTEMS_NOTEPAD_LAST+1)
+
+/*
+ * External API name for Thread_Control
+ */
+
+typedef Thread_Control rtems_tcb;
+
+/*
+ * The following defines the "return type" of an RTEMS task.
+ */
+
+typedef void rtems_task;
+
+/*
+ * The following defines the argument to an RTEMS task.
+ */
+
+typedef uint32_t rtems_task_argument;
+
+/*
+ * The following defines the type for the entry point of an RTEMS task.
+ */
+
+typedef rtems_task ( *rtems_task_entry )(
+ rtems_task_argument
+ );
+
+/*
+ * The following records define the Initialization Tasks Table.
+ * Each entry contains the information required by RTEMS to
+ * create and start a user task automatically at executive
+ * initialization time.
+ */
+
+typedef struct {
+ rtems_name name; /* task name */
+ uint32_t stack_size; /* task stack size */
+ rtems_task_priority initial_priority; /* task priority */
+ rtems_attribute attribute_set; /* task attributes */
+ rtems_task_entry entry_point; /* task entry point */
+ rtems_mode mode_set; /* task initial mode */
+ uint32_t argument; /* task argument */
+} rtems_initialization_tasks_table;
+
+/*
+ * This is the API specific information required by each thread for
+ * the RTEMS API to function correctly.
+ */
+
+
+typedef struct {
+ uint32_t Notepads[ RTEMS_NUMBER_NOTEPADS ];
+ rtems_event_set pending_events;
+ rtems_event_set event_condition;
+ ASR_Information Signal;
+} RTEMS_API_Control;
+
+/*
+ * The following defines the information control block used to
+ * manage this class of objects.
+ */
+
+RTEMS_EXTERN Objects_Information _RTEMS_tasks_Information;
+
+/*
+ * These are used to manage the user initialization tasks.
+ */
+
+RTEMS_EXTERN rtems_initialization_tasks_table
+ *_RTEMS_tasks_User_initialization_tasks;
+RTEMS_EXTERN uint32_t _RTEMS_tasks_Number_of_initialization_tasks;
+
+/*
+ * _RTEMS_tasks_Manager_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine initializes all Task Manager related data structures.
+ */
+
+void _RTEMS_tasks_Manager_initialization(
+ uint32_t maximum_tasks,
+ uint32_t number_of_initialization_tasks,
+ rtems_initialization_tasks_table *user_tasks
+);
+
+/*
+ * rtems_task_create
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_task_create directive. The task
+ * will have the name name. The attribute_set can be used to indicate
+ * that the task will be globally accessible or utilize floating point.
+ * The task's stack will be stack_size bytes. The task will begin
+ * execution with initial_priority and initial_modes. It returns the
+ * id of the created task in ID.
+ */
+
+rtems_status_code rtems_task_create(
+ rtems_name name,
+ rtems_task_priority initial_priority,
+ uint32_t stack_size,
+ rtems_mode initial_modes,
+ rtems_attribute attribute_set,
+ Objects_Id *id
+);
+
+/*
+ * rtems_task_ident
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_task_ident directive.
+ * This directive returns the task ID associated with name.
+ * If more than one task is named name, then the task to
+ * which the ID belongs is arbitrary. node indicates the
+ * extent of the search for the ID of the task named name.
+ * The search can be limited to a particular node or allowed to
+ * encompass all nodes.
+ */
+
+rtems_status_code rtems_task_ident(
+ rtems_name name,
+ uint32_t node,
+ Objects_Id *id
+);
+
+/*
+ * rtems_task_delete
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_task_delete directive. The
+ * task indicated by ID is deleted.
+ */
+
+rtems_status_code rtems_task_delete(
+ Objects_Id id
+);
+
+/*
+ * rtems_task_get_note
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_task_get_note directive. The
+ * value of the indicated notepad for the task associated with ID
+ * is returned in note.
+ */
+
+rtems_status_code rtems_task_get_note(
+ Objects_Id id,
+ uint32_t notepad,
+ uint32_t *note
+);
+
+/*
+ * rtems_task_set_note
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_task_set_note directive. The
+ * value of the indicated notepad for the task associated with ID
+ * is returned in note.
+ */
+
+rtems_status_code rtems_task_set_note(
+ Objects_Id id,
+ uint32_t notepad,
+ uint32_t note
+);
+
+/*
+ * rtems_task_mode
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_task_mode directive. The current
+ * values of the modes indicated by mask of the calling task are changed
+ * to that indicated in mode_set. The former mode of the task is
+ * returned in mode_set.
+ */
+
+rtems_status_code rtems_task_mode(
+ rtems_mode mode_set,
+ rtems_mode mask,
+ rtems_mode *previous_mode_set
+);
+
+/*
+ * rtems_task_restart
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_task_restart directive. The
+ * task associated with ID is restarted at its initial entry
+ * point with the new argument.
+ */
+
+rtems_status_code rtems_task_restart(
+ Objects_Id id,
+ uint32_t arg
+);
+
+/*
+ * rtems_task_suspend
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_task_suspend directive. The
+ * SUSPENDED state is set for task associated with ID.
+ */
+
+rtems_status_code rtems_task_suspend(
+ Objects_Id id
+);
+
+/*
+ * rtems_task_resume
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_task_resume Directive. The
+ * SUSPENDED state is cleared for task associated with ID.
+ */
+
+rtems_status_code rtems_task_resume(
+ Objects_Id id
+);
+
+/*
+ * rtems_task_set_priority
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_task_set_priority directive. The
+ * current priority of the task associated with ID is set to
+ * new_priority. The former priority of that task is returned
+ * in old_priority.
+ */
+
+rtems_status_code rtems_task_set_priority(
+ Objects_Id id,
+ rtems_task_priority new_priority,
+ rtems_task_priority *old_priority
+);
+
+/*
+ * rtems_task_start
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_task_start directive. The
+ * starting execution point of the task associated with ID is
+ * set to entry_point with the initial argument.
+ */
+
+rtems_status_code rtems_task_start(
+ Objects_Id id,
+ rtems_task_entry entry_point,
+ uint32_t argument
+);
+
+/*
+ * rtems_task_wake_when
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_task_wake_when directive. The
+ * calling task is blocked until the current time of day is
+ * equal to that indicated by time_buffer.
+ */
+
+rtems_status_code rtems_task_wake_when(
+ rtems_time_of_day *time_buffer
+);
+
+/*
+ * rtems_task_wake_after
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_task_wake_after directive. The
+ * calling task is blocked until the indicated number of clock
+ * ticks have occurred.
+ */
+
+rtems_status_code rtems_task_wake_after(
+ rtems_interval ticks
+);
+
+/*
+ * rtems_task_is_suspended
+ *
+ * This directive returns a status indicating whether or not
+ * the specified task is suspended.
+ */
+
+rtems_status_code rtems_task_is_suspended(
+ Objects_Id id
+);
+
+/*
+ * rtems_task_variable_add
+ *
+ * This directive adds a per task variable.
+ */
+
+rtems_status_code rtems_task_variable_add(
+ rtems_id tid,
+ void **ptr,
+ void (*dtor)(void *)
+);
+
+/*
+ * rtems_task_variable_get
+ *
+ * This directive gets the value of a task variable.
+ */
+
+rtems_status_code rtems_task_variable_get(
+ rtems_id tid,
+ void **ptr,
+ void **result
+);
+
+/*
+ * rtems_task_variable_delete
+ *
+ * This directive removes a per task variable.
+ */
+
+rtems_status_code rtems_task_variable_delete(
+ rtems_id tid,
+ void **ptr
+);
+
+/*
+ * _RTEMS_tasks_Initialize_user_tasks
+ *
+ * This routine creates and starts all configured user
+ * initialzation threads.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ */
+
+void _RTEMS_tasks_Initialize_user_tasks( void );
+
+#ifndef __RTEMS_APPLICATION__
+#include <rtems/rtems/tasks.inl>
+#endif
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/rtems/taskmp.h>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/include/rtems/rtems/timer.h b/cpukit/rtems/include/rtems/rtems/timer.h
new file mode 100644
index 0000000000..6e6fe7e4e1
--- /dev/null
+++ b/cpukit/rtems/include/rtems/rtems/timer.h
@@ -0,0 +1,366 @@
+/* timer.h
+ *
+ * This include file contains all the constants, structures, and
+ * prototypes associated with the Timer Manager. This manager provides
+ * facilities to configure, initiate, cancel, and delete timers which will
+ * fire at specified intervals of time.
+ *
+ * Directives provided are:
+ *
+ * + create a timer
+ * + get an ID of a timer
+ * + delete a timer
+ * + set timer to fire in context of clock tick
+ * - after a number of ticks have passed
+ * - when a specified date and time has been reached
+ * + initiate the timer server task
+ * + set timer to fire in context of the timer server task
+ * - after a number of ticks have passed
+ * - when a specified date and time has been reached
+ * + reset a timer
+ * + cancel a time
+ *
+ * COPYRIGHT (c) 1989-2002.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_TIMER_h
+#define __RTEMS_TIMER_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/object.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/rtems/attr.h>
+
+/*
+ * The following enumerated type details the classes to which a timer
+ * may belong.
+ */
+
+typedef enum {
+ TIMER_INTERVAL,
+ TIMER_INTERVAL_ON_TASK,
+ TIMER_TIME_OF_DAY,
+ TIMER_TIME_OF_DAY_ON_TASK,
+ TIMER_DORMANT
+} Timer_Classes;
+
+/*
+ * The following types define a pointer to a timer service routine.
+ */
+
+typedef void rtems_timer_service_routine;
+
+typedef rtems_timer_service_routine ( *rtems_timer_service_routine_entry )(
+ rtems_id,
+ void *
+ );
+
+/*
+ * The following defines the information control block used to manage
+ * this class of objects.
+ */
+
+RTEMS_EXTERN Objects_Information _Timer_Information;
+
+/*
+ * Pointer to TCB of the Timer Server. This is NULL before the
+ * server is executing and task-based timers are not allowed to be
+ * initiated until the server is started.
+ */
+
+RTEMS_EXTERN Thread_Control *_Timer_Server;
+
+/*
+ * The following chains contain the list of interval timers that are
+ * executed in the context of the Timer Server.
+ *
+ * NOTE: These are extern'ed because they do not have to be in the
+ * minimum footprint. They are only really required when
+ * task-based timers are used. Since task-based timers can
+ * not be started until the server is initiated, these structures
+ * do not have to be initialized until then. They are declared
+ * in the same file as _Timer_Server_body.
+ */
+
+extern Chain_Control _Timer_Ticks_chain;
+extern Chain_Control _Timer_Seconds_chain;
+
+/*
+ * The following records define the control block used to manage
+ * each timer.
+ */
+
+typedef struct {
+ Objects_Control Object;
+ Watchdog_Control Ticker;
+ Timer_Classes the_class;
+} Timer_Control;
+
+/*
+ * _Timer_Manager_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this manager.
+ */
+
+void _Timer_Manager_initialization(
+ uint32_t maximum_timers
+);
+
+/*
+ * _Timer_Server_body
+ *
+ * DESCRIPTION:
+ *
+ * This is the server for task based timers. This task executes whenever
+ * a task-based timer should fire. It services both "after" and "when"
+ * timers. It is not created automatically but must be created explicitly
+ * by the application before task-based timers may be initiated.
+ */
+
+Thread _Timer_Server_body(
+ uint32_t ignored
+);
+
+/*
+ * rtems_timer_create
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_timer_create directive. The
+ * timer will have the name name. It returns the id of the
+ * created timer in ID.
+ */
+
+rtems_status_code rtems_timer_create(
+ rtems_name name,
+ Objects_Id *id
+);
+
+/*
+ * rtems_timer_ident
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_timer_ident directive.
+ * This directive returns the timer ID associated with name.
+ * If more than one timer is named name, then the timer
+ * to which the ID belongs is arbitrary.
+ */
+
+rtems_status_code rtems_timer_ident(
+ rtems_name name,
+ Objects_Id *id
+);
+
+/*
+ * rtems_timer_cancel
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_timer_cancel directive. It is used
+ * to stop the timer associated with ID from firing.
+ */
+
+rtems_status_code rtems_timer_cancel(
+ Objects_Id id
+);
+
+/*
+ * rtems_timer_delete
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_timer_delete directive. The
+ * timer indicated by ID is deleted.
+ */
+
+rtems_status_code rtems_timer_delete(
+ Objects_Id id
+);
+
+/*
+ * rtems_timer_fire_after
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_timer_fire_after directive. It
+ * initiates the timer associated with ID to fire in ticks clock ticks.
+ * When the timer fires, the routine will be invoked in the context
+ * of the rtems_clock_tick directive which is normally invoked as
+ * part of servicing a periodic interupt.
+ */
+
+rtems_status_code rtems_timer_fire_after(
+ Objects_Id id,
+ rtems_interval ticks,
+ rtems_timer_service_routine_entry routine,
+ void *user_data
+);
+
+/*
+ * rtems_timer_server_fire_after
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_timer_server_fire_after directive. It
+ * initiates the timer associated with ID to fire in ticks clock
+ * ticks. When the timer fires, the routine will be invoked by the
+ * Timer Server in the context of a task NOT IN THE CONTEXT of the
+ * clock tick interrupt.
+ */
+
+rtems_status_code rtems_timer_server_fire_after(
+ Objects_Id id,
+ rtems_interval ticks,
+ rtems_timer_service_routine_entry routine,
+ void *user_data
+);
+
+/*
+ * rtems_timer_fire_when
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_timer_fire_when directive. It
+ * initiates the timer associated with ID to fire at wall_time
+ * When the timer fires, the routine will be invoked in the context
+ * of the rtems_clock_tick directive which is normally invoked as
+ * part of servicing a periodic interupt.
+ */
+
+rtems_status_code rtems_timer_fire_when(
+ Objects_Id id,
+ rtems_time_of_day *wall_time,
+ rtems_timer_service_routine_entry routine,
+ void *user_data
+);
+
+/*
+ * rtems_timer_server_fire_when
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_timer_server_fire_when directive. It
+ * initiates the timer associated with ID to fire at wall_time
+ * When the timer fires, the routine will be invoked by the
+ * Timer Server in the context of a task NOT IN THE CONTEXT of the
+ * clock tick interrupt.
+ */
+
+rtems_status_code rtems_timer_server_fire_when(
+ Objects_Id id,
+ rtems_time_of_day *wall_time,
+ rtems_timer_service_routine_entry routine,
+ void *user_data
+);
+
+/*
+ * rtems_timer_reset
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_timer_reset directive. It is used
+ * to reinitialize the interval timer associated with ID just as if
+ * rtems_timer_fire_after were re-invoked with the same arguments that
+ * were used to initiate this timer.
+ */
+
+rtems_status_code rtems_timer_reset(
+ Objects_Id id
+);
+
+/*
+ * rtems_timer_initiate_server
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_timer_initiate_server directive.
+ * It creates and starts the server that executes task-based timers.
+ * It must be invoked before any task-based timers can be initiated.
+ */
+
+#define RTEMS_TIMER_SERVER_DEFAULT_PRIORITY -1
+
+rtems_status_code rtems_timer_initiate_server(
+ uint32_t priority,
+ uint32_t stack_size,
+ rtems_attribute attribute_set
+);
+
+/*
+ * rtems_timer_get_information
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_timer_get_information directive.
+ * This directive returns information about the timer.
+ */
+
+typedef struct {
+ Timer_Classes the_class;
+ Watchdog_Interval initial;
+ Watchdog_Interval start_time;
+ Watchdog_Interval stop_time;
+} rtems_timer_information;
+
+rtems_status_code rtems_timer_get_information(
+ Objects_Id id,
+ rtems_timer_information *the_info
+);
+
+/*
+ * Macros and routines that expose the mechanisms required to service
+ * the Timer Server timer. These stop the timer, synchronize it with
+ * the current time, and restart it.
+ */
+
+extern Watchdog_Control _Timer_Seconds_timer;
+
+#define _Timer_Server_stop_ticks_timer() \
+ _Watchdog_Remove( &_Timer_Server->Timer )
+
+#define _Timer_Server_stop_seconds_timer() \
+ _Watchdog_Remove( &_Timer_Seconds_timer );
+
+void _Timer_Server_process_ticks_chain(void);
+void _Timer_Server_process_seconds_chain(void);
+
+#define _Timer_Server_reset_ticks_timer() \
+ do { \
+ if ( !_Chain_Is_empty( &_Timer_Ticks_chain ) ) { \
+ _Watchdog_Insert_ticks( &_Timer_Server->Timer, \
+ ((Watchdog_Control *)_Timer_Ticks_chain.first)->delta_interval ); \
+ } \
+ } while (0)
+
+#define _Timer_Server_reset_seconds_timer() \
+ do { \
+ if ( !_Chain_Is_empty( &_Timer_Seconds_chain ) ) { \
+ _Watchdog_Insert_seconds( &_Timer_Seconds_timer, \
+ ((Watchdog_Control *)_Timer_Seconds_chain.first)->delta_interval ); \
+ } \
+ } while (0)
+
+#ifndef __RTEMS_APPLICATION__
+#include <rtems/rtems/timer.inl>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/include/rtems/rtems/types.h b/cpukit/rtems/include/rtems/rtems/types.h
new file mode 100644
index 0000000000..e77e87cbb6
--- /dev/null
+++ b/cpukit/rtems/include/rtems/rtems/types.h
@@ -0,0 +1,111 @@
+/* types.h
+ *
+ * This include file defines the types used by the RTEMS API.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_RTEMS_TYPES_h
+#define __RTEMS_RTEMS_TYPES_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * RTEMS basic type definitions
+ */
+
+#include <rtems/stdint.h>
+
+/* backward compatibility types */
+typedef uint8_t rtems_unsigned8;
+typedef uint16_t rtems_unsigned16;
+typedef uint32_t rtems_unsigned32;
+#if defined(uint64_t)
+/* FIXME: Some targets do not have 64-bit types */
+typedef uint64_t rtems_unsigned64;
+#endif
+
+typedef int8_t rtems_signed8;
+typedef int16_t rtems_signed16;
+typedef int32_t rtems_signed32;
+#if defined(int64_t)
+/* FIXME: Some targets do not have 64-bit types */
+typedef int64_t rtems_signed64;
+#endif
+
+#include <rtems/score/heap.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/rtems/modes.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#include <rtems/score/mppkt.h>
+#endif
+
+typedef single_precision rtems_single; /* single precision float */
+typedef double_precision rtems_double; /* double precision float */
+
+typedef boolean rtems_boolean;
+
+typedef uint32_t rtems_name;
+typedef Objects_Id rtems_id;
+
+typedef Context_Control rtems_context;
+typedef Context_Control_fp rtems_context_fp;
+typedef CPU_Interrupt_frame rtems_interrupt_frame;
+
+/*
+ * Region information block
+ */
+
+typedef Heap_Information_block region_information_block;
+
+/*
+ * Time related
+ */
+
+typedef Watchdog_Interval rtems_interval;
+typedef TOD_Control rtems_time_of_day;
+
+/*
+ * Define the type for an RTEMS API task mode.
+ */
+
+typedef Modes_Control rtems_mode;
+
+/*
+ * MPCI related entries
+ */
+
+#if defined(RTEMS_MULTIPROCESSING)
+typedef MP_packet_Classes rtems_mp_packet_classes;
+typedef MP_packet_Prefix rtems_packet_prefix;
+
+typedef MPCI_initialization_entry rtems_mpci_initialization_entry;
+typedef MPCI_get_packet_entry rtems_mpci_get_packet_entry;
+typedef MPCI_return_packet_entry rtems_mpci_return_packet_entry;
+typedef MPCI_send_entry rtems_mpci_send_packet_entry;
+typedef MPCI_receive_entry rtems_mpci_receive_packet_entry;
+
+typedef MPCI_Entry rtems_mpci_entry;
+
+typedef MPCI_Control rtems_mpci_table;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/inline/rtems/rtems/asr.inl b/cpukit/rtems/inline/rtems/rtems/asr.inl
new file mode 100644
index 0000000000..e7bd708f6a
--- /dev/null
+++ b/cpukit/rtems/inline/rtems/rtems/asr.inl
@@ -0,0 +1,127 @@
+/* inline/asr.inl
+ *
+ * This include file contains the implemenation of all routines
+ * associated with the asynchronous signal handler which are inlined.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __INLINE_ASR_inl
+#define __INLINE_ASR_inl
+
+#include <rtems/score/isr.h>
+
+/*PAGE
+ *
+ * _ASR_Initialize
+ *
+ * DESCRIPTION:
+ *
+ * This routine initializes the given RTEMS_ASR information record.
+ */
+
+RTEMS_INLINE_ROUTINE void _ASR_Initialize (
+ ASR_Information *information
+)
+{
+ information->is_enabled = TRUE;
+ information->handler = NULL;
+ information->mode_set = RTEMS_DEFAULT_MODES;
+ information->signals_posted = 0;
+ information->signals_pending = 0;
+ information->nest_level = 0;
+}
+
+/*PAGE
+ *
+ * _ASR_Swap_signals
+ *
+ * DESCRIPTION:
+ *
+ * This routine atomically swaps the pending and posted signal
+ * sets. This is done when the thread alters its mode in such a
+ * way that the RTEMS_ASR disable/enable flag changes.
+ */
+
+RTEMS_INLINE_ROUTINE void _ASR_Swap_signals (
+ ASR_Information *information
+)
+{
+ rtems_signal_set _signals;
+ ISR_Level _level;
+
+ _ISR_Disable( _level );
+ _signals = information->signals_pending;
+ information->signals_pending = information->signals_posted;
+ information->signals_posted = _signals;
+ _ISR_Enable( _level );
+}
+
+/*PAGE
+ *
+ * _ASR_Is_null_handler
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the given asr_handler is NULL and
+ * FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _ASR_Is_null_handler (
+ rtems_asr_entry asr_handler
+)
+{
+ return asr_handler == NULL;
+}
+
+/*PAGE
+ *
+ * _ASR_Are_signals_pending
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if there are signals pending in the
+ * given RTEMS_ASR information record and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _ASR_Are_signals_pending (
+ ASR_Information *information
+)
+{
+ return information->signals_posted != 0;
+}
+
+/*PAGE
+ *
+ * _ASR_Post_signals
+ *
+ * DESCRIPTION:
+ *
+ * This routine posts the given signals into the signal_set
+ * passed in. The result is returned to the user in signal_set.
+ *
+ * NOTE: This must be implemented as a macro.
+ */
+
+RTEMS_INLINE_ROUTINE void _ASR_Post_signals(
+ rtems_signal_set signals,
+ rtems_signal_set *signal_set
+)
+{
+ ISR_Level _level;
+
+ _ISR_Disable( _level );
+ *signal_set |= signals;
+ _ISR_Enable( _level );
+}
+
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/inline/rtems/rtems/attr.inl b/cpukit/rtems/inline/rtems/rtems/attr.inl
new file mode 100644
index 0000000000..b58a0f95df
--- /dev/null
+++ b/cpukit/rtems/inline/rtems/rtems/attr.inl
@@ -0,0 +1,212 @@
+/* inline/attr.inl
+ *
+ * This include file contains all of the inlined routines associated
+ * with attributes.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __INLINE_ATTRIBUTES_inl
+#define __INLINE_ATTRIBUTES_inl
+
+/*PAGE
+ *
+ * _Attributes_Set
+ *
+ * DESCRIPTION:
+ *
+ * This function sets the requested new_attributes in the attribute_set
+ * passed in. The result is returned to the user.
+ */
+
+RTEMS_INLINE_ROUTINE rtems_attribute _Attributes_Set (
+ rtems_attribute new_attributes,
+ rtems_attribute attribute_set
+)
+{
+ return attribute_set | new_attributes;
+}
+
+/*PAGE
+ *
+ * _Attributes_Clear
+ *
+ * DESCRIPTION:
+ *
+ * This function clears the requested new_attributes in the attribute_set
+ * passed in. The result is returned to the user.
+ */
+
+RTEMS_INLINE_ROUTINE rtems_attribute _Attributes_Clear (
+ rtems_attribute attribute_set,
+ rtems_attribute mask
+)
+{
+ return attribute_set & ~mask;
+}
+
+/*PAGE
+ *
+ * _Attributes_Is_floating_point
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the floating point attribute is
+ * enabled in the attribute_set and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Attributes_Is_floating_point(
+ rtems_attribute attribute_set
+)
+{
+ return ( attribute_set & RTEMS_FLOATING_POINT );
+}
+
+/*PAGE
+ *
+ * _Attributes_Is_global
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the global object attribute is
+ * enabled in the attribute_set and FALSE otherwise.
+ */
+
+#if defined(RTEMS_MULTIPROCESSING)
+RTEMS_INLINE_ROUTINE boolean _Attributes_Is_global(
+ rtems_attribute attribute_set
+)
+{
+ return ( attribute_set & RTEMS_GLOBAL );
+}
+#endif
+
+/*PAGE
+ *
+ * _Attributes_Is_priority
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the priority attribute is
+ * enabled in the attribute_set and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Attributes_Is_priority(
+ rtems_attribute attribute_set
+)
+{
+ return ( attribute_set & RTEMS_PRIORITY );
+}
+
+/*PAGE
+ *
+ * _Attributes_Is_binary_semaphore
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the binary semaphore attribute is
+ * enabled in the attribute_set and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Attributes_Is_binary_semaphore(
+ rtems_attribute attribute_set
+)
+{
+ return ((attribute_set & RTEMS_SEMAPHORE_CLASS) == RTEMS_BINARY_SEMAPHORE);
+}
+
+/*PAGE
+ *
+ * _Attributes_Is_simple_binary_semaphore
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the simple binary semaphore attribute is
+ * enabled in the attribute_set and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Attributes_Is_simple_binary_semaphore(
+ rtems_attribute attribute_set
+)
+{
+ return
+ ((attribute_set & RTEMS_SEMAPHORE_CLASS) == RTEMS_SIMPLE_BINARY_SEMAPHORE);
+}
+
+/*PAGE
+ *
+ * _Attributes_Is_counting_semaphore
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the counting semaphore attribute is
+ * enabled in the attribute_set and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Attributes_Is_counting_semaphore(
+ rtems_attribute attribute_set
+)
+{
+ return ((attribute_set & RTEMS_SEMAPHORE_CLASS) == RTEMS_COUNTING_SEMAPHORE);
+}
+
+/*PAGE
+ *
+ * _Attributes_Is_inherit_priority
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the priority inheritance attribute
+ * is enabled in the attribute_set and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Attributes_Is_inherit_priority(
+ rtems_attribute attribute_set
+)
+{
+ return ( attribute_set & RTEMS_INHERIT_PRIORITY );
+}
+
+/*PAGE
+ *
+ * _Attributes_Is_priority_ceiling
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the priority ceiling attribute
+ * is enabled in the attribute_set and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Attributes_Is_priority_ceiling(
+ rtems_attribute attribute_set
+)
+{
+ return ( attribute_set & RTEMS_PRIORITY_CEILING );
+}
+
+/*PAGE
+ *
+ * _Attributes_Is_system_task
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the system task attribute
+ * is enabled in the attribute_set and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Attributes_Is_system_task(
+ rtems_attribute attribute_set
+)
+{
+ return ( attribute_set & RTEMS_SYSTEM_TASK );
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/inline/rtems/rtems/dpmem.inl b/cpukit/rtems/inline/rtems/rtems/dpmem.inl
new file mode 100644
index 0000000000..6721d942d4
--- /dev/null
+++ b/cpukit/rtems/inline/rtems/rtems/dpmem.inl
@@ -0,0 +1,94 @@
+/* inline/dpmem.inl
+ *
+ * This include file contains the inline routine used in conjunction
+ * with the Dual Ported Memory Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __INLINE_DPMEM_inl
+#define __INLINE_DPMEM_inl
+
+
+/*PAGE
+ *
+ * _Dual_ported_memory_Allocate
+ *
+ * DESCRIPTION:
+ *
+ * This routine allocates a port control block from the inactive chain
+ * of free port control blocks.
+ */
+
+RTEMS_INLINE_ROUTINE Dual_ported_memory_Control
+ *_Dual_ported_memory_Allocate ( void )
+{
+ return (Dual_ported_memory_Control *)
+ _Objects_Allocate( &_Dual_ported_memory_Information );
+}
+
+/*PAGE
+ *
+ * _Dual_ported_memory_Free
+ *
+ * DESCRIPTION:
+ *
+ * This routine frees a port control block to the inactive chain
+ * of free port control blocks.
+ */
+
+RTEMS_INLINE_ROUTINE void _Dual_ported_memory_Free (
+ Dual_ported_memory_Control *the_port
+)
+{
+ _Objects_Free( &_Dual_ported_memory_Information, &the_port->Object );
+}
+
+/*PAGE
+ *
+ * _Dual_ported_memory_Get
+ *
+ * DESCRIPTION:
+ *
+ * This function maps port IDs to port control blocks. If ID
+ * corresponds to a local port, then it returns the_port control
+ * pointer which maps to ID and location is set to OBJECTS_LOCAL.
+ * Global ports are not supported, thus if ID does not map to a
+ * local port, location is set to OBJECTS_ERROR and the_port is
+ * undefined.
+ */
+
+RTEMS_INLINE_ROUTINE Dual_ported_memory_Control *_Dual_ported_memory_Get (
+ Objects_Id id,
+ Objects_Locations *location
+)
+{
+ return (Dual_ported_memory_Control *)
+ _Objects_Get( &_Dual_ported_memory_Information, id, location );
+}
+
+/*PAGE
+ *
+ * _Dual_ported_memory_Is_null
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_port is NULL and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Dual_ported_memory_Is_null(
+ Dual_ported_memory_Control *the_port
+)
+{
+ return ( the_port == NULL );
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/inline/rtems/rtems/event.inl b/cpukit/rtems/inline/rtems/rtems/event.inl
new file mode 100644
index 0000000000..34bc51e898
--- /dev/null
+++ b/cpukit/rtems/inline/rtems/rtems/event.inl
@@ -0,0 +1,20 @@
+/* inline/event.inl
+ *
+ * This include file contains the static inline implementation of
+ * macros for the Event Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __MACROS_EVENT_inl
+#define __MACROS_EVENT_inl
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/inline/rtems/rtems/eventset.inl b/cpukit/rtems/inline/rtems/rtems/eventset.inl
new file mode 100644
index 0000000000..5baf074664
--- /dev/null
+++ b/cpukit/rtems/inline/rtems/rtems/eventset.inl
@@ -0,0 +1,94 @@
+/* inline/eventset.inl
+ *
+ * This include file contains the information pertaining to event sets.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __INLINE_EVENT_SET_inl
+#define __INLINE_EVENT_SET_inl
+
+/*PAGE
+ *
+ * _Event_sets_Is_empty
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if on events are posted in the event_set,
+ * and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Event_sets_Is_empty(
+ rtems_event_set the_event_set
+)
+{
+ return ( the_event_set == 0 );
+}
+
+/*PAGE
+ *
+ * _Event_sets_Post
+ *
+ * DESCRIPTION:
+ *
+ * This routine posts the given new_events into the event_set
+ * passed in. The result is returned to the user in event_set.
+ */
+
+RTEMS_INLINE_ROUTINE void _Event_sets_Post(
+ rtems_event_set the_new_events,
+ rtems_event_set *the_event_set
+)
+{
+ ISR_Level level;
+
+ _ISR_Disable( level );
+ *the_event_set |= the_new_events;
+ _ISR_Enable( level );
+}
+
+/*PAGE
+ *
+ * _Event_sets_Get
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the events in event_condition which are
+ * set in event_set.
+ */
+
+RTEMS_INLINE_ROUTINE rtems_event_set _Event_sets_Get(
+ rtems_event_set the_event_set,
+ rtems_event_set the_event_condition
+)
+{
+ return ( the_event_set & the_event_condition );
+}
+
+/*PAGE
+ *
+ * _Event_sets_Clear
+ *
+ * DESCRIPTION:
+ *
+ * This function removes the events in mask from the event_set
+ * passed in. The result is returned to the user in event_set.
+ */
+
+RTEMS_INLINE_ROUTINE rtems_event_set _Event_sets_Clear(
+ rtems_event_set the_event_set,
+ rtems_event_set the_mask
+)
+{
+ return ( the_event_set & ~(the_mask) );
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/inline/rtems/rtems/message.inl b/cpukit/rtems/inline/rtems/rtems/message.inl
new file mode 100644
index 0000000000..fd8832bf20
--- /dev/null
+++ b/cpukit/rtems/inline/rtems/rtems/message.inl
@@ -0,0 +1,82 @@
+/* message.inl
+ *
+ * This include file contains the static inline implementation of all
+ * inlined routines in the Message Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __MESSAGE_QUEUE_inl
+#define __MESSAGE_QUEUE_inl
+
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _Message_queue_Is_null
+ *
+ * DESCRIPTION:
+ *
+ * This function places the_message at the rear of the outstanding
+ * messages on the_message_queue.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Message_queue_Is_null (
+ Message_queue_Control *the_message_queue
+)
+{
+ return ( the_message_queue == NULL );
+}
+
+
+/*PAGE
+ *
+ * _Message_queue_Free
+ *
+ * DESCRIPTION:
+ *
+ * This routine deallocates a message queue control block into
+ * the inactive chain of free message queue control blocks.
+ */
+
+RTEMS_INLINE_ROUTINE void _Message_queue_Free (
+ Message_queue_Control *the_message_queue
+)
+{
+ _Objects_Free( &_Message_queue_Information, &the_message_queue->Object );
+}
+
+/*PAGE
+ *
+ * _Message_queue_Get
+ *
+ * DESCRIPTION:
+ *
+ * This function maps message queue IDs to message queue control
+ * blocks. If ID corresponds to a local message queue, then it
+ * returns the_message_queue control pointer which maps to ID
+ * and location is set to OBJECTS_LOCAL. If the message queue ID is
+ * global and resides on a remote node, then location is set
+ * to OBJECTS_REMOTE, and the_message_queue is undefined.
+ * Otherwise, location is set to OBJECTS_ERROR and
+ * the_message_queue is undefined.
+ */
+
+RTEMS_INLINE_ROUTINE Message_queue_Control *_Message_queue_Get (
+ Objects_Id id,
+ Objects_Locations *location
+)
+{
+ return (Message_queue_Control *)
+ _Objects_Get( &_Message_queue_Information, id, location );
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/inline/rtems/rtems/modes.inl b/cpukit/rtems/inline/rtems/rtems/modes.inl
new file mode 100644
index 0000000000..bffe2df1fb
--- /dev/null
+++ b/cpukit/rtems/inline/rtems/rtems/modes.inl
@@ -0,0 +1,151 @@
+/* modes.inl
+ *
+ * This include file contains the static inline implementation of the
+ * inlined routines in the Mode Handler
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __MODES_inl
+#define __MODES_inl
+
+/*PAGE
+ *
+ * _Modes_Mask_changed
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if any of the mode flags in mask
+ * are set in mode_set, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Modes_Mask_changed (
+ Modes_Control mode_set,
+ Modes_Control masks
+)
+{
+ return ( mode_set & masks );
+}
+
+/*PAGE
+ *
+ * _Modes_Is_asr_disabled
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if mode_set indicates that Asynchronous
+ * Signal Processing is disabled, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Modes_Is_asr_disabled (
+ Modes_Control mode_set
+)
+{
+ return (mode_set & RTEMS_ASR_MASK) == RTEMS_NO_ASR;
+}
+
+/*PAGE
+ *
+ * _Modes_Is_preempt
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if mode_set indicates that preemption
+ * is enabled, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Modes_Is_preempt (
+ Modes_Control mode_set
+)
+{
+ return (mode_set & RTEMS_PREEMPT_MASK) == RTEMS_PREEMPT;
+}
+
+/*PAGE
+ *
+ * _Modes_Is_timeslice
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if mode_set indicates that timeslicing
+ * is enabled, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Modes_Is_timeslice (
+ Modes_Control mode_set
+)
+{
+ return (mode_set & RTEMS_TIMESLICE_MASK) == RTEMS_TIMESLICE;
+}
+
+/*PAGE
+ *
+ * _Modes_Get_interrupt_level
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the interrupt level portion of the mode_set.
+ */
+
+RTEMS_INLINE_ROUTINE ISR_Level _Modes_Get_interrupt_level (
+ Modes_Control mode_set
+)
+{
+ return ( mode_set & RTEMS_INTERRUPT_MASK );
+}
+
+/*PAGE
+ *
+ * _Modes_Set_interrupt_level
+ *
+ * DESCRIPTION:
+ *
+ * This routine sets the current interrupt level to that specified
+ * in the mode_set.
+ */
+
+RTEMS_INLINE_ROUTINE void _Modes_Set_interrupt_level (
+ Modes_Control mode_set
+)
+{
+ _ISR_Set_level( _Modes_Get_interrupt_level( mode_set ) );
+}
+
+/*PAGE
+ *
+ * _Modes_Change
+ *
+ * DESCRIPTION:
+ *
+ * This routine changes the modes in old_mode_set indicated by
+ * mask to the requested values in new_mode_set. The resulting
+ * mode set is returned in out_mode_set and the modes that changed
+ * is returned in changed.
+ */
+
+RTEMS_INLINE_ROUTINE void _Modes_Change (
+ Modes_Control old_mode_set,
+ Modes_Control new_mode_set,
+ Modes_Control mask,
+ Modes_Control *out_mode_set,
+ Modes_Control *changed
+)
+{
+ Modes_Control _out_mode;
+
+ _out_mode = old_mode_set;
+ _out_mode &= ~mask;
+ _out_mode |= new_mode_set & mask;
+ *changed = _out_mode ^ old_mode_set;
+ *out_mode_set = _out_mode;
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/inline/rtems/rtems/options.inl b/cpukit/rtems/inline/rtems/rtems/options.inl
new file mode 100644
index 0000000000..e9a4849d30
--- /dev/null
+++ b/cpukit/rtems/inline/rtems/rtems/options.inl
@@ -0,0 +1,54 @@
+/* options.inl
+ *
+ * This file contains the static inline implementation of the inlined
+ * routines from the Options Handler.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __OPTIONS_inl
+#define __OPTIONS_inl
+
+/*PAGE
+ *
+ * _Options_Is_no_wait
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the RTEMS_NO_WAIT option is enabled in
+ * option_set, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Options_Is_no_wait (
+ rtems_option option_set
+)
+{
+ return (option_set & RTEMS_NO_WAIT);
+}
+
+/*PAGE
+ *
+ * _Options_Is_any
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the RTEMS_EVENT_ANY option is enabled in
+ * OPTION_SET, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Options_Is_any (
+ rtems_option option_set
+)
+{
+ return (option_set & RTEMS_EVENT_ANY);
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/inline/rtems/rtems/part.inl b/cpukit/rtems/inline/rtems/rtems/part.inl
new file mode 100644
index 0000000000..009a946401
--- /dev/null
+++ b/cpukit/rtems/inline/rtems/rtems/part.inl
@@ -0,0 +1,198 @@
+/* part.inl
+ *
+ * This file contains the macro implementation of all inlined routines
+ * in the Partition Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __PARTITION_inl
+#define __PARTITION_inl
+
+/*PAGE
+ *
+ * _Partition_Allocate_buffer
+ *
+ * DESCRIPTION:
+ *
+ * This function attempts to allocate a buffer from the_partition.
+ * If successful, it returns the address of the allocated buffer.
+ * Otherwise, it returns NULL.
+ */
+
+RTEMS_INLINE_ROUTINE void *_Partition_Allocate_buffer (
+ Partition_Control *the_partition
+)
+{
+ return _Chain_Get( &the_partition->Memory );
+}
+
+/*PAGE
+ *
+ * _Partition_Free_buffer
+ *
+ * DESCRIPTION:
+ *
+ * This routine frees the_buffer to the_partition.
+ */
+
+RTEMS_INLINE_ROUTINE void _Partition_Free_buffer (
+ Partition_Control *the_partition,
+ Chain_Node *the_buffer
+)
+{
+ _Chain_Append( &the_partition->Memory, the_buffer );
+}
+
+/*PAGE
+ *
+ * _Partition_Is_buffer_on_boundary
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_buffer is on a valid buffer
+ * boundary for the_partition, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Partition_Is_buffer_on_boundary (
+ void *the_buffer,
+ Partition_Control *the_partition
+)
+{
+ uint32_t offset;
+
+ offset = (uint32_t ) _Addresses_Subtract(
+ the_buffer,
+ the_partition->starting_address
+ );
+
+ return ((offset % the_partition->buffer_size) == 0);
+}
+
+/*PAGE
+ *
+ * _Partition_Is_buffer_valid
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_buffer is a valid buffer from
+ * the_partition, otherwise FALSE is returned.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Partition_Is_buffer_valid (
+ Chain_Node *the_buffer,
+ Partition_Control *the_partition
+)
+{
+ void *starting;
+ void *ending;
+
+ starting = the_partition->starting_address;
+ ending = _Addresses_Add_offset( starting, the_partition->length );
+
+ return (
+ _Addresses_Is_in_range( the_buffer, starting, ending ) &&
+ _Partition_Is_buffer_on_boundary( the_buffer, the_partition )
+ );
+}
+
+/*PAGE
+ *
+ * _Partition_Is_buffer_size_aligned
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the use of the specified buffer_size
+ * will result in the allocation of buffers whose first byte is
+ * properly aligned, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Partition_Is_buffer_size_aligned (
+ uint32_t buffer_size
+)
+{
+ return ((buffer_size % CPU_PARTITION_ALIGNMENT) == 0);
+}
+
+/*PAGE
+ *
+ * _Partition_Allocate
+ *
+ * DESCRIPTION:
+ *
+ * This function allocates a partition control block from
+ * the inactive chain of free partition control blocks.
+ */
+
+RTEMS_INLINE_ROUTINE Partition_Control *_Partition_Allocate ( void )
+{
+ return (Partition_Control *) _Objects_Allocate( &_Partition_Information );
+}
+
+/*PAGE
+ *
+ * _Partition_Free
+ *
+ * DESCRIPTION:
+ *
+ * This routine frees a partition control block to the
+ * inactive chain of free partition control blocks.
+ */
+
+RTEMS_INLINE_ROUTINE void _Partition_Free (
+ Partition_Control *the_partition
+)
+{
+ _Objects_Free( &_Partition_Information, &the_partition->Object );
+}
+
+/*PAGE
+ *
+ * _Partition_Get
+ *
+ * DESCRIPTION:
+ *
+ * This function maps partition IDs to partition control blocks.
+ * If ID corresponds to a local partition, then it returns
+ * the_partition control pointer which maps to ID and location
+ * is set to OBJECTS_LOCAL. If the partition ID is global and
+ * resides on a remote node, then location is set to OBJECTS_REMOTE,
+ * and the_partition is undefined. Otherwise, location is set
+ * to OBJECTS_ERROR and the_partition is undefined.
+ */
+
+RTEMS_INLINE_ROUTINE Partition_Control *_Partition_Get (
+ Objects_Id id,
+ Objects_Locations *location
+)
+{
+ return (Partition_Control *)
+ _Objects_Get( &_Partition_Information, id, location );
+}
+
+/*PAGE
+ *
+ * _Partition_Is_null
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_partition is NULL
+ * and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Partition_Is_null (
+ Partition_Control *the_partition
+)
+{
+ return ( the_partition == NULL );
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/inline/rtems/rtems/ratemon.inl b/cpukit/rtems/inline/rtems/rtems/ratemon.inl
new file mode 100644
index 0000000000..8084277204
--- /dev/null
+++ b/cpukit/rtems/inline/rtems/rtems/ratemon.inl
@@ -0,0 +1,142 @@
+/* ratemon.inl
+ *
+ * This file contains the static inline implementation of the inlined
+ * routines in the Rate Monotonic Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RATE_MONOTONIC_inl
+#define __RATE_MONOTONIC_inl
+
+/*PAGE
+ *
+ * _Rate_monotonic_Allocate
+ *
+ * DESCRIPTION:
+ *
+ * This function allocates a period control block from
+ * the inactive chain of free period control blocks.
+ */
+
+RTEMS_INLINE_ROUTINE Rate_monotonic_Control *_Rate_monotonic_Allocate( void )
+{
+ return (Rate_monotonic_Control *)
+ _Objects_Allocate( &_Rate_monotonic_Information );
+}
+
+/*PAGE
+ *
+ * _Rate_monotonic_Free
+ *
+ * DESCRIPTION:
+ *
+ * This routine allocates a period control block from
+ * the inactive chain of free period control blocks.
+ */
+
+RTEMS_INLINE_ROUTINE void _Rate_monotonic_Free (
+ Rate_monotonic_Control *the_period
+)
+{
+ _Objects_Free( &_Rate_monotonic_Information, &the_period->Object );
+}
+
+/*PAGE
+ *
+ * _Rate_monotonic_Get
+ *
+ * DESCRIPTION:
+ *
+ * This function maps period IDs to period control blocks.
+ * If ID corresponds to a local period, then it returns
+ * the_period control pointer which maps to ID and location
+ * is set to OBJECTS_LOCAL. Otherwise, location is set
+ * to OBJECTS_ERROR and the_period is undefined.
+ */
+
+RTEMS_INLINE_ROUTINE Rate_monotonic_Control *_Rate_monotonic_Get (
+ Objects_Id id,
+ Objects_Locations *location
+)
+{
+ return (Rate_monotonic_Control *)
+ _Objects_Get( &_Rate_monotonic_Information, id, location );
+}
+
+/*PAGE
+ *
+ * _Rate_monotonic_Is_active
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_period is in the ACTIVE state,
+ * and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Rate_monotonic_Is_active (
+ Rate_monotonic_Control *the_period
+)
+{
+ return (the_period->state == RATE_MONOTONIC_ACTIVE);
+}
+
+/*PAGE
+ *
+ * _Rate_monotonic_Is_inactive
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_period is in the ACTIVE state,
+ * and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Rate_monotonic_Is_inactive (
+ Rate_monotonic_Control *the_period
+)
+{
+ return (the_period->state == RATE_MONOTONIC_INACTIVE);
+}
+
+/*PAGE
+ *
+ * _Rate_monotonic_Is_expired
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_period is in the EXPIRED state,
+ * and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Rate_monotonic_Is_expired (
+ Rate_monotonic_Control *the_period
+)
+{
+ return (the_period->state == RATE_MONOTONIC_EXPIRED);
+}
+
+/*PAGE
+ *
+ * _Rate_monotonic_Is_null
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_period is NULL and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Rate_monotonic_Is_null (
+ Rate_monotonic_Control *the_period
+)
+{
+ return (the_period == NULL);
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/inline/rtems/rtems/region.inl b/cpukit/rtems/inline/rtems/rtems/region.inl
new file mode 100644
index 0000000000..721d89c110
--- /dev/null
+++ b/cpukit/rtems/inline/rtems/rtems/region.inl
@@ -0,0 +1,126 @@
+/* region.inl
+ *
+ * This file contains the macro implementation of the inlined
+ * routines from the Region Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __REGION_inl
+#define __REGION_inl
+
+/*PAGE
+ *
+ * _Region_Allocate
+ *
+ * DESCRIPTION:
+ *
+ * This function allocates a region control block from
+ * the inactive chain of free region control blocks.
+ */
+
+RTEMS_INLINE_ROUTINE Region_Control *_Region_Allocate( void )
+{
+ return (Region_Control *) _Objects_Allocate( &_Region_Information );
+}
+
+/*PAGE
+ *
+ * _Region_Free
+ *
+ * DESCRIPTION:
+ *
+ * This routine frees a region control block to the
+ * inactive chain of free region control blocks.
+ */
+
+RTEMS_INLINE_ROUTINE void _Region_Free (
+ Region_Control *the_region
+)
+{
+ _Objects_Free( &_Region_Information, &the_region->Object );
+}
+
+/*PAGE
+ *
+ * _Region_Get
+ *
+ * DESCRIPTION:
+ *
+ * This function maps region IDs to region control blocks.
+ * If ID corresponds to a local region, then it returns
+ * the_region control pointer which maps to ID and location
+ * is set to OBJECTS_LOCAL. Otherwise, location is set
+ * to OBJECTS_ERROR and the_region is undefined.
+ */
+
+RTEMS_INLINE_ROUTINE Region_Control *_Region_Get (
+ Objects_Id id,
+ Objects_Locations *location
+)
+{
+ return (Region_Control *)
+ _Objects_Get_no_protection( &_Region_Information, id, location );
+}
+
+/*PAGE
+ *
+ * _Region_Allocate_segment
+ *
+ * DESCRIPTION:
+ *
+ * This function attempts to allocate a segment from the_region.
+ * If successful, it returns the address of the allocated segment.
+ * Otherwise, it returns NULL.
+ */
+
+RTEMS_INLINE_ROUTINE void *_Region_Allocate_segment (
+ Region_Control *the_region,
+ uint32_t size
+)
+{
+ return _Heap_Allocate( &the_region->Memory, size );
+}
+
+/*PAGE
+ *
+ * _Region_Free_segment
+ *
+ * DESCRIPTION:
+ *
+ * This function frees the_segment to the_region.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Region_Free_segment (
+ Region_Control *the_region,
+ void *the_segment
+)
+{
+ return _Heap_Free( &the_region->Memory, the_segment );
+}
+
+/*PAGE
+ *
+ * _Region_Is_null
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_region is NULL and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Region_Is_null (
+ Region_Control *the_region
+)
+{
+ return ( the_region == NULL );
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/inline/rtems/rtems/sem.inl b/cpukit/rtems/inline/rtems/rtems/sem.inl
new file mode 100644
index 0000000000..4c15a99792
--- /dev/null
+++ b/cpukit/rtems/inline/rtems/rtems/sem.inl
@@ -0,0 +1,102 @@
+/* sem.inl
+ *
+ * This file contains the static inlin implementation of the inlined
+ * routines from the Semaphore Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __SEMAPHORE_inl
+#define __SEMAPHORE_inl
+
+/*PAGE
+ *
+ * _Semaphore_Allocate
+ *
+ * DESCRIPTION:
+ *
+ * This function allocates a semaphore control block from
+ * the inactive chain of free semaphore control blocks.
+ */
+
+RTEMS_INLINE_ROUTINE Semaphore_Control *_Semaphore_Allocate( void )
+{
+ return (Semaphore_Control *) _Objects_Allocate( &_Semaphore_Information );
+}
+
+/*PAGE
+ *
+ * _Semaphore_Free
+ *
+ * DESCRIPTION:
+ *
+ * This routine frees a semaphore control block to the
+ * inactive chain of free semaphore control blocks.
+ */
+
+RTEMS_INLINE_ROUTINE void _Semaphore_Free (
+ Semaphore_Control *the_semaphore
+)
+{
+ _Objects_Free( &_Semaphore_Information, &the_semaphore->Object );
+}
+
+/*PAGE
+ *
+ * _Semaphore_Get
+ *
+ * DESCRIPTION:
+ *
+ * This function maps semaphore IDs to semaphore control blocks.
+ * If ID corresponds to a local semaphore, then it returns
+ * the_semaphore control pointer which maps to ID and location
+ * is set to OBJECTS_LOCAL. if the semaphore ID is global and
+ * resides on a remote node, then location is set to OBJECTS_REMOTE,
+ * and the_semaphore is undefined. Otherwise, location is set
+ * to OBJECTS_ERROR and the_semaphore is undefined.
+ */
+
+RTEMS_INLINE_ROUTINE Semaphore_Control *_Semaphore_Get (
+ Objects_Id id,
+ Objects_Locations *location
+)
+{
+ return (Semaphore_Control *)
+ _Objects_Get( &_Semaphore_Information, id, location );
+}
+
+RTEMS_INLINE_ROUTINE Semaphore_Control *_Semaphore_Get_interrupt_disable (
+ Objects_Id id,
+ Objects_Locations *location,
+ ISR_Level *level
+)
+{
+ return (Semaphore_Control *)
+ _Objects_Get_isr_disable( &_Semaphore_Information, id, location, level );
+}
+
+/*PAGE
+ *
+ * _Semaphore_Is_null
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_semaphore is NULL and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Semaphore_Is_null (
+ Semaphore_Control *the_semaphore
+)
+{
+ return ( the_semaphore == NULL );
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/inline/rtems/rtems/status.inl b/cpukit/rtems/inline/rtems/rtems/status.inl
new file mode 100644
index 0000000000..01cd778373
--- /dev/null
+++ b/cpukit/rtems/inline/rtems/rtems/status.inl
@@ -0,0 +1,55 @@
+/* inline/status.inl
+ *
+ * This include file contains the implementations of the inlined
+ * routines for the status package.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __INLINE_STATUS_inl
+#define __INLINE_STATUS_inl
+
+/*PAGE
+ *
+ * rtems_is_status_successful
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the status code is equal to RTEMS_SUCCESSFUL,
+ * and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean rtems_is_status_successful(
+ rtems_status_code code
+)
+{
+ return (code == RTEMS_SUCCESSFUL);
+}
+
+/*PAGE
+ *
+ * rtems_are_statuses_equal
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the status code1 is equal to code2,
+ * and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean rtems_are_statuses_equal(
+ rtems_status_code code1,
+ rtems_status_code code2
+)
+{
+ return (code1 == code2);
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/inline/rtems/rtems/support.inl b/cpukit/rtems/inline/rtems/rtems/support.inl
new file mode 100644
index 0000000000..53a86aa056
--- /dev/null
+++ b/cpukit/rtems/inline/rtems/rtems/support.inl
@@ -0,0 +1,60 @@
+/* support.inl
+ *
+ * This include file contains the static inline implementation of all
+ * of the inlined routines specific to the RTEMS API.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_SUPPORT_inl
+#define __RTEMS_SUPPORT_inl
+
+/*PAGE
+ *
+ * rtems_is_name_valid
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the name is valid, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE rtems_boolean rtems_is_name_valid (
+ rtems_name name
+)
+{
+ return ( name != 0 );
+}
+
+/*PAGE
+ *
+ * rtems_name_to_characters
+ *
+ * DESCRIPTION:
+ *
+ * This function breaks the object name into the four component
+ * characters C1, C2, C3, and C4.
+ */
+
+RTEMS_INLINE_ROUTINE void rtems_name_to_characters(
+ rtems_name name,
+ char *c1,
+ char *c2,
+ char *c3,
+ char *c4
+)
+{
+ *c1 = (name >> 24) & 0xff;
+ *c2 = (name >> 16) & 0xff;
+ *c3 = (name >> 8) & 0xff;
+ *c4 = name & 0xff;
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/inline/rtems/rtems/tasks.inl b/cpukit/rtems/inline/rtems/rtems/tasks.inl
new file mode 100644
index 0000000000..32295570c6
--- /dev/null
+++ b/cpukit/rtems/inline/rtems/rtems/tasks.inl
@@ -0,0 +1,89 @@
+/* tasks.inl
+ *
+ * This file contains the static inline implementation of all inlined
+ * routines in the with RTEMS Tasks Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_TASKS_inl
+#define __RTEMS_TASKS_inl
+
+/*PAGE
+ *
+ * _RTEMS_tasks_Allocate
+ *
+ * DESCRIPTION:
+ *
+ * This function allocates a task control block from
+ * the inactive chain of free task control blocks.
+ */
+
+RTEMS_INLINE_ROUTINE Thread_Control *_RTEMS_tasks_Allocate( void )
+{
+ return (Thread_Control *) _Objects_Allocate( &_RTEMS_tasks_Information );
+}
+
+/*PAGE
+ *
+ * _RTEMS_tasks_Free
+ *
+ * DESCRIPTION:
+ *
+ * This routine frees a task control block to the
+ * inactive chain of free task control blocks.
+ */
+
+RTEMS_INLINE_ROUTINE void _RTEMS_tasks_Free (
+ Thread_Control *the_task
+)
+{
+ _Objects_Free(
+ _Objects_Get_information( the_task->Object.id ),
+ &the_task->Object
+ );
+}
+
+/*PAGE
+ *
+ * _RTEMS_tasks_Priority_to_Core
+ *
+ * DESCRIPTION:
+ *
+ * This function converts an RTEMS API priority into a core priority.
+ */
+
+RTEMS_INLINE_ROUTINE Priority_Control _RTEMS_tasks_Priority_to_Core(
+ rtems_task_priority priority
+)
+{
+ return (Priority_Control) priority;
+}
+
+/*PAGE
+ *
+ * _RTEMS_tasks_Priority_is_valid
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_priority is a valid user task priority
+ * and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _RTEMS_tasks_Priority_is_valid (
+ rtems_task_priority the_priority
+)
+{
+ return ( ( the_priority >= RTEMS_MINIMUM_PRIORITY ) &&
+ ( the_priority <= RTEMS_MAXIMUM_PRIORITY ) );
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/inline/rtems/rtems/timer.inl b/cpukit/rtems/inline/rtems/rtems/timer.inl
new file mode 100644
index 0000000000..afad51ed32
--- /dev/null
+++ b/cpukit/rtems/inline/rtems/rtems/timer.inl
@@ -0,0 +1,141 @@
+/* timer.inl
+ *
+ * This file contains the static inline implementation of the inlined routines
+ * from the Timer Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __TIMER_inl
+#define __TIMER_inl
+
+/*PAGE
+ *
+ * _Timer_Allocate
+ *
+ * DESCRIPTION:
+ *
+ * This function allocates a timer control block from
+ * the inactive chain of free timer control blocks.
+ */
+
+RTEMS_INLINE_ROUTINE Timer_Control *_Timer_Allocate( void )
+{
+ return (Timer_Control *) _Objects_Allocate( &_Timer_Information );
+}
+
+/*PAGE
+ *
+ * _Timer_Free
+ *
+ * DESCRIPTION:
+ *
+ * This routine frees a timer control block to the
+ * inactive chain of free timer control blocks.
+ */
+
+RTEMS_INLINE_ROUTINE void _Timer_Free (
+ Timer_Control *the_timer
+)
+{
+ _Objects_Free( &_Timer_Information, &the_timer->Object );
+}
+
+/*PAGE
+ *
+ * _Timer_Get
+ *
+ * DESCRIPTION:
+ *
+ * This function maps timer IDs to timer control blocks.
+ * If ID corresponds to a local timer, then it returns
+ * the timer control pointer which maps to ID and location
+ * is set to OBJECTS_LOCAL. Otherwise, location is set
+ * to OBJECTS_ERROR and the returned value is undefined.
+ */
+
+RTEMS_INLINE_ROUTINE Timer_Control *_Timer_Get (
+ Objects_Id id,
+ Objects_Locations *location
+)
+{
+ return (Timer_Control *)
+ _Objects_Get( &_Timer_Information, id, location );
+}
+
+/*PAGE
+ *
+ * _Timer_Is_interval_class
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the class is that of an INTERVAL
+ * timer, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Timer_Is_interval_class (
+ Timer_Classes the_class
+)
+{
+ return (the_class == TIMER_INTERVAL) || (the_class == TIMER_INTERVAL_ON_TASK);
+}
+
+/*PAGE
+ *
+ * _Timer_Is_time_of_day_class
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the class is that of an INTERVAL
+ * timer, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Timer_Is_timer_of_day_class (
+ Timer_Classes the_class
+)
+{
+ return ( the_class == TIMER_TIME_OF_DAY );
+}
+
+/*PAGE
+ *
+ * _Timer_Is_dormant_class
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the class is that of a DORMANT
+ * timer, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Timer_Is_dormant_class (
+ Timer_Classes the_class
+)
+{
+ return ( the_class == TIMER_DORMANT );
+}
+
+/*PAGE
+ *
+ * _Timer_Is_null
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_timer is NULL and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Timer_Is_null (
+ Timer_Control *the_timer
+)
+{
+ return ( the_timer == NULL );
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/macros/rtems/rtems/asr.inl b/cpukit/rtems/macros/rtems/rtems/asr.inl
new file mode 100644
index 0000000000..0f39178146
--- /dev/null
+++ b/cpukit/rtems/macros/rtems/rtems/asr.inl
@@ -0,0 +1,89 @@
+/* macros/asr.h
+ *
+ * This include file contains the implemenation of all routines
+ * associated with the asynchronous signal handler which are inlined.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __MACROS_ASR_h
+#define __MACROS_ASR_h
+
+#include <rtems/score/isr.h>
+
+/*PAGE
+ *
+ * _ASR_Initialize
+ *
+ */
+
+#define _ASR_Initialize( _information ) \
+{ \
+ (_information)->is_enabled = TRUE; \
+ (_information)->handler = NULL; \
+ (_information)->mode_set = RTEMS_DEFAULT_MODES; \
+ (_information)->signals_posted = 0; \
+ (_information)->signals_pending = 0; \
+ (_information)->nest_level = 0; \
+}
+
+/*PAGE
+ *
+ * _ASR_Swap_signals
+ *
+ */
+
+#define _ASR_Swap_signals( _information ) \
+{ \
+ rtems_signal_set _signals; \
+ ISR_Level _level; \
+ \
+ _ISR_Disable( _level ); \
+ _signals = (_information)->signals_pending; \
+ (_information)->signals_pending = (_information)->signals_posted; \
+ (_information)->signals_posted = _signals; \
+ _ISR_Enable( _level ); \
+}
+
+/*PAGE
+ *
+ * _ASR_Is_null_handler
+ *
+ */
+
+#define _ASR_Is_null_handler( _asr_handler ) \
+ ( (_asr_handler) == NULL )
+
+/*PAGE
+ *
+ * _ASR_Are_signals_pending
+ *
+ */
+
+#define _ASR_Are_signals_pending( _information ) \
+ ( (_information)->signals_posted != 0 )
+
+/*PAGE
+ *
+ * _ASR_Post_signals
+ *
+ */
+
+#define _ASR_Post_signals( _signals, _signal_set ) \
+ do { \
+ ISR_Level _level; \
+ \
+ _ISR_Disable( _level ); \
+ *(_signal_set) |= (_signals); \
+ _ISR_Enable( _level ); \
+ } while ( 0 )
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/macros/rtems/rtems/attr.inl b/cpukit/rtems/macros/rtems/rtems/attr.inl
new file mode 100644
index 0000000000..37e566913b
--- /dev/null
+++ b/cpukit/rtems/macros/rtems/rtems/attr.inl
@@ -0,0 +1,119 @@
+/* macros/attr.h
+ *
+ * This include file contains all of the inlined routines associated
+ * with attributes.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __MACROS_ATTRIBUTES_h
+#define __MACROS_ATTRIBUTES_h
+
+/*PAGE
+ *
+ * _Attributes_Set
+ */
+
+#define _Attributes_Set( _new_attributes, _attribute_set ) \
+ ( (_attribute_set) | (_new_attributes) )
+
+/*PAGE
+ *
+ * _Attributes_Clear
+ */
+
+#define _Attributes_Clear( _attribute_set, _mask ) \
+ ( (_attribute_set) & ~(_mask) )
+
+/*PAGE
+ *
+ * _Attributes_Is_floating_point
+ *
+ */
+
+#define _Attributes_Is_floating_point( _attribute_set ) \
+ ( (_attribute_set) & RTEMS_FLOATING_POINT )
+
+/*PAGE
+ *
+ * _Attributes_Is_global
+ *
+ */
+
+#if defined(RTEMS_MULTIPROCESSING)
+#define _Attributes_Is_global( _attribute_set ) \
+ ( (_attribute_set) & RTEMS_GLOBAL )
+#endif
+
+/*PAGE
+ *
+ * _Attributes_Is_priority
+ *
+ */
+
+#define _Attributes_Is_priority( _attribute_set ) \
+ ( (_attribute_set) & RTEMS_PRIORITY )
+
+/*PAGE
+ *
+ * _Attributes_Is_binary_semaphore
+ *
+ */
+
+#define _Attributes_Is_binary_semaphore( _attribute_set ) \
+ (((_attribute_set) & RTEMS_SEMAPHORE_CLASS) == RTEMS_BINARY_SEMAPHORE)
+
+/*PAGE
+ *
+ * _Attributes_Is_simple_binary_semaphore
+ *
+ */
+
+#define _Attributes_Is_simple_binary_semaphore( _attribute_set ) \
+ (((_attribute_set) & RTEMS_SEMAPHORE_CLASS) == RTEMS_SIMPLE_BINARY_SEMAPHORE)
+
+/*PAGE
+ *
+ * _Attributes_Is_counting_semaphore
+ *
+ */
+
+#define _Attributes_Is_counting_semaphore( _attribute_set ) \
+ (((_attribute_set) & RTEMS_SEMAPHORE_CLASS) == RTEMS_COUNTING_SEMAPHORE)
+
+/*PAGE
+ *
+ * _Attributes_Is_inherit_priority
+ *
+ */
+
+#define _Attributes_Is_inherit_priority( _attribute_set ) \
+ ( (_attribute_set) & RTEMS_INHERIT_PRIORITY )
+
+/*PAGE
+ *
+ * _Attributes_Is_priority_ceiling
+ *
+ */
+
+#define _Attributes_Is_priority_ceiling( _attribute_set ) \
+ ( (_attribute_set) & RTEMS_PRIORITY_CEILING )
+
+/*PAGE
+ *
+ * _Attributes_Is_system_task
+ *
+ */
+
+#define _Attributes_Is_system_task( _attribute_set ) \
+ ( (_attribute_set) & RTEMS_SYSTEM_TASK )
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/macros/rtems/rtems/dpmem.inl b/cpukit/rtems/macros/rtems/rtems/dpmem.inl
new file mode 100644
index 0000000000..af35e1a448
--- /dev/null
+++ b/cpukit/rtems/macros/rtems/rtems/dpmem.inl
@@ -0,0 +1,58 @@
+/* macros/dpmem.h
+ *
+ * This include file contains the inline routine used in conjunction
+ * with the Dual Ported Memory Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __MACROS_DPMEM_h
+#define __MACROS_DPMEM_h
+
+/*PAGE
+ *
+ * _Dual_ported_memory_Allocate
+ *
+ */
+
+#define _Dual_ported_memory_Allocate() \
+ (Dual_ported_memory_Control *) \
+ _Objects_Allocate( &_Dual_ported_memory_Information )
+
+/*PAGE
+ *
+ * _Dual_ported_memory_Free
+ *
+ */
+
+#define _Dual_ported_memory_Free( _the_port ) \
+ _Objects_Free( &_Dual_ported_memory_Information, &(_the_port)->Object )
+
+/*PAGE
+ *
+ * _Dual_ported_memory_Get
+ *
+ */
+
+#define _Dual_ported_memory_Get( _id, _location ) \
+ (Dual_ported_memory_Control *) \
+ _Objects_Get( &_Dual_ported_memory_Information, (_id), (_location) )
+
+
+/*PAGE
+ *
+ * _Dual_ported_memory_Is_null
+ */
+
+#define _Dual_ported_memory_Is_null( _the_port ) \
+ ( (_the_port) == NULL )
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/macros/rtems/rtems/event.inl b/cpukit/rtems/macros/rtems/rtems/event.inl
new file mode 100644
index 0000000000..3762e91e05
--- /dev/null
+++ b/cpukit/rtems/macros/rtems/rtems/event.inl
@@ -0,0 +1,20 @@
+/* macros/event.h
+ *
+ * This include file contains the implementation of macros for
+ * the Event Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __MACROS_EVENT_h
+#define __MACROS_EVENT_h
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/macros/rtems/rtems/eventset.inl b/cpukit/rtems/macros/rtems/rtems/eventset.inl
new file mode 100644
index 0000000000..1a265cc4af
--- /dev/null
+++ b/cpukit/rtems/macros/rtems/rtems/eventset.inl
@@ -0,0 +1,58 @@
+/* eventset.inl
+ *
+ * This include file contains the macro implementation of inlined
+ * routines in the event set object.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __EVENT_SET_inl
+#define __EVENT_SET_inl
+
+/*PAGE
+ *
+ * _Event_sets_Is_empty
+ */
+
+#define _Event_sets_Is_empty( _the_event_set ) \
+ ((_the_event_set) == 0 )
+
+/*PAGE
+ *
+ * _Event_sets_Is_empty
+ */
+
+#define _Event_sets_Post( _the_new_events, _the_event_set ) \
+ do { \
+ ISR_Level level; \
+ \
+ _ISR_Disable( level ); \
+ *(_the_event_set) |= (_the_new_events); \
+ _ISR_Enable( level ); \
+ } while (0);
+
+/*PAGE
+ *
+ * _Event_sets_Is_empty
+ */
+
+#define _Event_sets_Get( _the_event_set, _the_event_condition ) \
+ ((_the_event_set) & (_the_event_condition))
+
+/*PAGE
+ *
+ * _Event_sets_Clear
+ */
+
+#define _Event_sets_Clear( _the_event_set, _the_mask ) \
+ ((_the_event_set) & ~(_the_mask))
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/macros/rtems/rtems/message.inl b/cpukit/rtems/macros/rtems/rtems/message.inl
new file mode 100644
index 0000000000..af81086f42
--- /dev/null
+++ b/cpukit/rtems/macros/rtems/rtems/message.inl
@@ -0,0 +1,48 @@
+/* message.inl
+ *
+ * This include file contains the macro implementation of all
+ * inlined routines in the Message Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __MESSAGE_QUEUE_inl
+#define __MESSAGE_QUEUE_inl
+
+/*PAGE
+ *
+ * _Message_queue_Is_null
+ *
+ */
+
+#define _Message_queue_Is_null( _the_message_queue ) \
+ ( (_the_message_queue) == NULL )
+
+/*PAGE
+ *
+ * _Message_queue_Free
+ *
+ */
+
+#define _Message_queue_Free( _the_message_queue ) \
+ _Objects_Free( &_Message_queue_Information, &(_the_message_queue)->Object )
+
+/*PAGE
+ *
+ * _Message_queue_Get
+ *
+ */
+
+#define _Message_queue_Get( _id, _location ) \
+ (Message_queue_Control *) \
+ _Objects_Get( &_Message_queue_Information, (_id), (_location) )
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/macros/rtems/rtems/modes.inl b/cpukit/rtems/macros/rtems/rtems/modes.inl
new file mode 100644
index 0000000000..7077604746
--- /dev/null
+++ b/cpukit/rtems/macros/rtems/rtems/modes.inl
@@ -0,0 +1,91 @@
+/* modes.inl
+ *
+ * This include file contains the macro implementation of the
+ * inlined routines in the Mode Handler.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __MODES_inl
+#define __MODES_inl
+
+/*PAGE
+ *
+ * _Modes_Mask_changed
+ *
+ */
+
+#define _Modes_Mask_changed( _mode_set, _masks ) \
+ ( (_mode_set) & (_masks) )
+
+/*PAGE
+ *
+ * _Modes_Is_asr_disabled
+ *
+ */
+
+#define _Modes_Is_asr_disabled( _mode_set ) \
+ (((_mode_set) & RTEMS_ASR_MASK) == RTEMS_NO_ASR)
+
+/*PAGE
+ *
+ * _Modes_Is_preempt
+ *
+ */
+
+#define _Modes_Is_preempt( _mode_set ) \
+ ( ( (_mode_set) & RTEMS_PREEMPT_MASK ) == RTEMS_PREEMPT )
+
+/*PAGE
+ *
+ * _Modes_Is_timeslice
+ *
+ */
+
+#define _Modes_Is_timeslice( _mode_set ) \
+ (((_mode_set) & RTEMS_TIMESLICE_MASK) == RTEMS_TIMESLICE)
+
+/*PAGE
+ *
+ * _Modes_Get_interrupt_level
+ *
+ */
+
+#define _Modes_Get_interrupt_level( _mode_set ) \
+ ( (_mode_set) & RTEMS_INTERRUPT_MASK )
+
+/*PAGE
+ *
+ * _Modes_Set_interrupt_level
+ *
+ */
+
+#define _Modes_Set_interrupt_level( _mode_set ) \
+ _ISR_Set_level( _Modes_Get_interrupt_level( (_mode_set) ) )
+
+/*PAGE
+ *
+ * _Modes_Change
+ *
+ */
+
+#define _Modes_Change( _old_mode_set, _new_mode_set, \
+ _mask, _out_mode_set, _changed ) \
+ { Modes_Control _out_mode; \
+ \
+ _out_mode = (_old_mode_set); \
+ _out_mode &= ~(_mask); \
+ _out_mode |= (_new_mode_set) & (_mask); \
+ *(_changed) = _out_mode ^ (_old_mode_set); \
+ *(_out_mode_set) = _out_mode; \
+ }
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/macros/rtems/rtems/options.inl b/cpukit/rtems/macros/rtems/rtems/options.inl
new file mode 100644
index 0000000000..a9f4a2c464
--- /dev/null
+++ b/cpukit/rtems/macros/rtems/rtems/options.inl
@@ -0,0 +1,38 @@
+/* options.inl
+ *
+ * This file contains the macro implementation of the inlined
+ * routines from the Options Handler.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __OPTIONS_inl
+#define __OPTIONS_inl
+
+/*PAGE
+ *
+ * _Options_Is_no_wait
+ *
+ */
+
+#define _Options_Is_no_wait( _option_set ) \
+ ( (_option_set) & RTEMS_NO_WAIT )
+
+/*PAGE
+ *
+ * _Options_Is_any
+ *
+ */
+
+#define _Options_Is_any( _option_set ) \
+ ( (_option_set) & RTEMS_EVENT_ANY )
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/macros/rtems/rtems/part.inl b/cpukit/rtems/macros/rtems/rtems/part.inl
new file mode 100644
index 0000000000..0aab6545c1
--- /dev/null
+++ b/cpukit/rtems/macros/rtems/rtems/part.inl
@@ -0,0 +1,116 @@
+/* part.inl
+ *
+ * This file contains the macro implementation of all inlined routines
+ * in the Partition Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __PARTITION_inl
+#define __PARTITION_inl
+
+/*PAGE
+ *
+ * _Partition_Allocate_buffer
+ *
+ */
+
+#define _Partition_Allocate_buffer( _the_partition ) \
+ _Chain_Get( &(_the_partition)->Memory )
+
+/*PAGE
+ *
+ * _Partition_Free_buffer
+ *
+ */
+
+#define _Partition_Free_buffer( _the_partition, _the_buffer ) \
+ _Chain_Append( &(_the_partition)->Memory, (_the_buffer) )
+
+/*PAGE
+ *
+ * _Partition_Is_buffer_on_boundary
+ *
+ */
+
+#define _Partition_Is_buffer_on_boundary( _the_buffer, _the_partition ) \
+ ((((uint32_t ) _Addresses_Subtract( \
+ (_the_buffer), \
+ (_the_partition)->starting_address ) \
+ ) % \
+ (_the_partition)->buffer_size) == 0)
+
+/*PAGE
+ *
+ * _Partition_Is_buffer_valid
+ *
+ */
+
+#define _Partition_Is_buffer_valid( _the_buffer, _the_partition ) \
+ ( \
+ _Addresses_Is_in_range( \
+ (_the_buffer), \
+ (_the_partition)->starting_address, \
+ _Addresses_Add_offset( \
+ (_the_partition)->starting_address, \
+ (_the_partition)->length \
+ ) \
+ ) && \
+ _Partition_Is_buffer_on_boundary( (_the_buffer), (_the_partition) ) \
+ )
+
+/*PAGE
+ *
+ * _Partition_Is_buffer_size_aligned
+ *
+ */
+
+#define _Partition_Is_buffer_size_aligned( _buffer_size ) \
+ ((_buffer_size) % CPU_PARTITION_ALIGNMENT == 0)
+
+/*PAGE
+ *
+ * _Partition_Allocate
+ *
+ */
+
+#define _Partition_Allocate() \
+ (Partition_Control *) _Objects_Allocate( &_Partition_Information )
+
+/*PAGE
+ *
+ * _Partition_Free
+ *
+ */
+
+#define _Partition_Free( _the_partition ) \
+ _Objects_Free( &_Partition_Information, &(_the_partition)->Object )
+
+/*PAGE
+ *
+ * _Partition_Get
+ *
+ */
+
+#define _Partition_Get( _id, _location ) \
+ (Partition_Control *) \
+ _Objects_Get( &_Partition_Information, (_id), (_location) )
+
+/*PAGE
+ *
+ * _Partition_Is_null
+ *
+ */
+
+#define _Partition_Is_null( _the_partition ) \
+ ( (_the_partition) == NULL )
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/macros/rtems/rtems/ratemon.inl b/cpukit/rtems/macros/rtems/rtems/ratemon.inl
new file mode 100644
index 0000000000..03e1c7f481
--- /dev/null
+++ b/cpukit/rtems/macros/rtems/rtems/ratemon.inl
@@ -0,0 +1,84 @@
+/* ratemon.inl
+ *
+ * This file contains the macro implementation of the inlined
+ * routines in the Rate Monotonic Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RATE_MONOTONIC_inl
+#define __RATE_MONOTONIC_inl
+
+/*PAGE
+ *
+ * _Rate_monotonic_Allocate
+ *
+ */
+
+#define _Rate_monotonic_Allocate() \
+ (Rate_monotonic_Control *) \
+ _Objects_Allocate( &_Rate_monotonic_Information )
+
+/*PAGE
+ *
+ * _Rate_monotonic_Free
+ *
+ */
+
+#define _Rate_monotonic_Free( _the_period ) \
+ _Objects_Free( &_Rate_monotonic_Information, &(_the_period)->Object )
+
+/*PAGE
+ *
+ * _Rate_monotonic_Get
+ *
+ */
+
+#define _Rate_monotonic_Get( _id, _location ) \
+ (Rate_monotonic_Control *) \
+ _Objects_Get( &_Rate_monotonic_Information, (_id), (_location) )
+
+/*PAGE
+ *
+ * _Rate_monotonic_Is_active
+ *
+ */
+
+#define _Rate_monotonic_Is_active( _the_period ) \
+ ((_the_period)->state == RATE_MONOTONIC_ACTIVE)
+
+/*PAGE
+ *
+ * _Rate_monotonic_Is_inactive
+ *
+ */
+
+#define _Rate_monotonic_Is_inactive( _the_period ) \
+ ((_the_period)->state == RATE_MONOTONIC_INACTIVE)
+
+/*PAGE
+ *
+ * _Rate_monotonic_Is_expired
+ *
+ */
+
+#define _Rate_monotonic_Is_expired( _the_period ) \
+ ((_the_period)->state == RATE_MONOTONIC_EXPIRED)
+
+/*PAGE
+ *
+ * _Rate_monotonic_Is_null
+ *
+ */
+
+#define _Rate_monotonic_Is_null( _the_period ) ( (_the_period) == NULL )
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/macros/rtems/rtems/region.inl b/cpukit/rtems/macros/rtems/rtems/region.inl
new file mode 100644
index 0000000000..56969816c7
--- /dev/null
+++ b/cpukit/rtems/macros/rtems/rtems/region.inl
@@ -0,0 +1,74 @@
+/* region.inl
+ *
+ * This file contains the macro implementation of the inlined
+ * routines from the Region Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __REGION_inl
+#define __REGION_inl
+
+/*PAGE
+ *
+ * _Region_Allocate
+ *
+ */
+
+#define _Region_Allocate() \
+ (Region_Control *) _Objects_Allocate( &_Region_Information )
+
+/*PAGE
+ *
+ * _Region_Free
+ *
+ */
+
+#define _Region_Free( _the_region ) \
+ _Objects_Free( &_Region_Information, &(_the_region)->Object )
+
+/*PAGE
+ *
+ * _Region_Get
+ *
+ */
+
+#define _Region_Get( _id, _location ) \
+ (Region_Control *) \
+ _Objects_Get_no_protection( &_Region_Information, (_id), (_location) )
+
+/*PAGE
+ *
+ * _Region_Allocate_segment
+ *
+ */
+
+#define _Region_Allocate_segment( _the_region, _size ) \
+ _Heap_Allocate( &(_the_region)->Memory, (_size) )
+
+/*PAGE
+ *
+ * _Region_Free_segment
+ *
+ */
+
+#define _Region_Free_segment( _the_region, _the_segment ) \
+ _Heap_Free( &(_the_region)->Memory, (_the_segment) )
+
+/*PAGE
+ *
+ * _Region_Is_null
+ *
+ */
+
+#define _Region_Is_null( _the_region ) ( (_the_region) == NULL )
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/macros/rtems/rtems/sem.inl b/cpukit/rtems/macros/rtems/rtems/sem.inl
new file mode 100644
index 0000000000..b49df036c4
--- /dev/null
+++ b/cpukit/rtems/macros/rtems/rtems/sem.inl
@@ -0,0 +1,62 @@
+/* sem.inl
+ *
+ * This file contains the macro implementation of the inlined
+ * routines from the Semaphore Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __SEMAPHORE_inl
+#define __SEMAPHORE_inl
+
+/*PAGE
+ *
+ * _Semaphore_Allocate
+ *
+ */
+
+#define _Semaphore_Allocate() \
+ (Semaphore_Control *) _Objects_Allocate( &_Semaphore_Information )
+
+/*PAGE
+ *
+ * _Semaphore_Free
+ *
+ */
+
+#define _Semaphore_Free( _the_semaphore ) \
+ _Objects_Free( &_Semaphore_Information, &(_the_semaphore)->Object )
+
+/*PAGE
+ *
+ * _Semaphore_Get
+ *
+ */
+
+#define _Semaphore_Get( _id, _location ) \
+ (Semaphore_Control *) \
+ _Objects_Get( &_Semaphore_Information, (_id), (_location) )
+
+#define _Semaphore_Get_interrupt_disable( _id, _location, _level ) \
+ (Semaphore_Control *) \
+ _Objects_Get_isr_disable( \
+ &_Semaphore_Information, (_id), (_location), (_level) )
+
+/*PAGE
+ *
+ * _Semaphore_Is_null
+ *
+ */
+
+#define _Semaphore_Is_null( _the_semaphore ) \
+ ( (_the_semaphore) == NULL )
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/macros/rtems/rtems/status.inl b/cpukit/rtems/macros/rtems/rtems/status.inl
new file mode 100644
index 0000000000..fb4ee72b8e
--- /dev/null
+++ b/cpukit/rtems/macros/rtems/rtems/status.inl
@@ -0,0 +1,38 @@
+/* macros/status.h
+ *
+ * This include file contains the implementations of the inlined
+ * routines for the status package.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __MACROS_STATUS_h
+#define __MACROS_STATUS_h
+
+/*PAGE
+ *
+ * rtems_is_status_successful
+ *
+ */
+
+#define rtems_is_status_successful( _code ) \
+ ( (_code) == RTEMS_SUCCESSFUL )
+
+/*PAGE
+ *
+ * rtems_are_statuses_equal
+ *
+ */
+
+#define rtems_are_statuses_equal( _code1, _code2 ) \
+ ((_code1) == (_code2))
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/macros/rtems/rtems/support.inl b/cpukit/rtems/macros/rtems/rtems/support.inl
new file mode 100644
index 0000000000..a0239ecfbc
--- /dev/null
+++ b/cpukit/rtems/macros/rtems/rtems/support.inl
@@ -0,0 +1,43 @@
+/* support.inl
+ *
+ * This include file contains the macros implementation of all
+ * of the inlined routines specific to the RTEMS API.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_SUPPORT_inl
+#define __RTEMS_SUPPORT_inl
+
+/*PAGE
+ *
+ * rtems_is_name_valid
+ *
+ */
+
+#define rtems_is_name_valid( _name ) \
+ ( (_name) != 0 )
+
+/*PAGE
+ *
+ * rtems_name_to_characters
+ *
+ */
+
+#define rtems_name_to_characters( _name, _c1, _c2, _c3, _c4 ) \
+ { \
+ (*(_c1) = ((_name) >> 24) & 0xff; \
+ (*(_c2) = ((_name) >> 16) & 0xff; \
+ (*(_c3) = ((_name) >> 8) & 0xff; \
+ (*(_c4) = ((_name)) & 0xff; \
+ }
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/macros/rtems/rtems/tasks.inl b/cpukit/rtems/macros/rtems/rtems/tasks.inl
new file mode 100644
index 0000000000..8c044d873e
--- /dev/null
+++ b/cpukit/rtems/macros/rtems/rtems/tasks.inl
@@ -0,0 +1,57 @@
+/* tasks.inl
+ *
+ * This file contains the macro implementation of all inlined
+ * routines in the with RTEMS Tasks Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_TASKS_inl
+#define __RTEMS_TASKS_inl
+
+/*PAGE
+ *
+ * _RTEMS_tasks_Allocate
+ *
+ */
+
+#define _RTEMS_tasks_Allocate() \
+ (Thread_Control *) _Objects_Allocate( &_RTEMS_tasks_Information )
+
+/*PAGE
+ *
+ * _RTEMS_tasks_Free
+ *
+ */
+
+#define _RTEMS_tasks_Free( _the_task ) \
+ _Objects_Free( &_RTEMS_tasks_Information, &(_the_task)->Object )
+
+/*PAGE
+ *
+ * _RTEMS_tasks_Priority_to_Core
+ */
+
+#define _RTEMS_tasks_Priority_to_Core( _priority ) \
+ ((Priority_Control) (_priority))
+
+/*PAGE
+ *
+ * _RTEMS_tasks_Priority_is_valid
+ *
+ */
+
+#define _RTEMS_tasks_Priority_is_valid( _the_priority ) \
+ ( ((_the_priority) >= RTEMS_MINIMUM_PRIORITY) && \
+ ((_the_priority) <= RTEMS_MAXIMUM_PRIORITY) )
+
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/macros/rtems/rtems/timer.inl b/cpukit/rtems/macros/rtems/rtems/timer.inl
new file mode 100644
index 0000000000..3043e7de21
--- /dev/null
+++ b/cpukit/rtems/macros/rtems/rtems/timer.inl
@@ -0,0 +1,85 @@
+/* timer.inl
+ *
+ * This file contains the macro implementation of the inlined routines
+ * from the Timer Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __TIMER_inl
+#define __TIMER_inl
+
+/*PAGE
+ *
+ * _Timer_Allocate
+ *
+ */
+
+#define _Timer_Allocate() \
+ (Timer_Control *) _Objects_Allocate( &_Timer_Information )
+
+/*PAGE
+ *
+ * _Timer_Free
+ *
+ */
+
+#define _Timer_Free( _the_timer ) \
+ _Objects_Free( &_Timer_Information, &(_the_timer)->Object )
+
+/*PAGE
+ *
+ * _Timer_Get
+ *
+ */
+
+#define _Timer_Get( _id, _location ) \
+ (Timer_Control *) \
+ _Objects_Get( &_Timer_Information, (_id), (_location) )
+
+/*PAGE
+ *
+ * _Timer_Is_interval_class
+ *
+ */
+
+#define _Timer_Is_interval_class( _the_class ) \
+ ( ((_the_class) == TIMER_INTERVAL) || \
+ ((_the_class) == TIMER_INTERVAL_ON_TASK) )
+
+/*PAGE
+ *
+ * _Timer_Is_time_of_day_class
+ *
+ */
+
+#define _Timer_Is_time_of_day_class( _the_class ) \
+ ( (_the_class) == TIMER_TIME_OF_DAY )
+
+/*PAGE
+ *
+ * _Timer_Is_dormant_class
+ *
+ */
+
+#define _Timer_Is_dormant_class( _the_class ) \
+ ( (_the_class) == TIMER_DORMANT )
+
+/*PAGE
+ *
+ * _Timer_Is_null
+ *
+ */
+
+#define _Timer_Is_null( _the_timer ) \
+ ( (_the_timer) == NULL )
+
+#endif
+/* end of include file */
diff --git a/cpukit/rtems/src/attr.c b/cpukit/rtems/src/attr.c
new file mode 100644
index 0000000000..d252fa55ba
--- /dev/null
+++ b/cpukit/rtems/src/attr.c
@@ -0,0 +1,28 @@
+/*
+ * Body for Attribute Routines
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/tasks.h>
+#include <rtems/score/stack.h>
+#include <rtems/rtems/modes.h>
+
+uint32_t rtems_minimum_stack_size = STACK_MINIMUM_SIZE;
+uint32_t rtems_interrupt_mask = RTEMS_INTERRUPT_MASK;
+
+rtems_attribute rtems_interrupt_level_attribute(
+ uint32_t level
+)
+{
+ return RTEMS_INTERRUPT_LEVEL(level);
+}
diff --git a/cpukit/rtems/src/clockget.c b/cpukit/rtems/src/clockget.c
new file mode 100644
index 0000000000..3ae9cab1a0
--- /dev/null
+++ b/cpukit/rtems/src/clockget.c
@@ -0,0 +1,92 @@
+/*
+ * Clock Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/clock.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * rtems_clock_get
+ *
+ * This directive returns the current date and time. If the time has
+ * not been set by a tm_set then an error is returned.
+ *
+ * Input parameters:
+ * option - which value to return
+ * time_buffer - pointer to output buffer (a time and date structure
+ * or an interval)
+ *
+ * Output parameters:
+ * time_buffer - output filled in
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_clock_get(
+ rtems_clock_get_options option,
+ void *time_buffer
+)
+{
+ ISR_Level level;
+ rtems_interval tmp;
+
+ if ( !time_buffer )
+ return RTEMS_INVALID_ADDRESS;
+
+ switch ( option ) {
+ case RTEMS_CLOCK_GET_TOD:
+ if ( !_TOD_Is_set )
+ return RTEMS_NOT_DEFINED;
+
+ *(rtems_time_of_day *)time_buffer = _TOD_Current;
+ return RTEMS_SUCCESSFUL;
+
+ case RTEMS_CLOCK_GET_SECONDS_SINCE_EPOCH:
+ if ( !_TOD_Is_set )
+ return RTEMS_NOT_DEFINED;
+
+ *(rtems_interval *)time_buffer = _TOD_Seconds_since_epoch;
+ return RTEMS_SUCCESSFUL;
+
+ case RTEMS_CLOCK_GET_TICKS_SINCE_BOOT:
+ *(rtems_interval *)time_buffer = _Watchdog_Ticks_since_boot;
+ return RTEMS_SUCCESSFUL;
+
+ case RTEMS_CLOCK_GET_TICKS_PER_SECOND:
+ *(rtems_interval *)time_buffer = _TOD_Ticks_per_second;
+ return RTEMS_SUCCESSFUL;
+
+ case RTEMS_CLOCK_GET_TIME_VALUE:
+ if ( !_TOD_Is_set )
+ return RTEMS_NOT_DEFINED;
+
+ _ISR_Disable( level );
+ ((rtems_clock_time_value *)time_buffer)->seconds =
+ _TOD_Seconds_since_epoch;
+ tmp = _TOD_Current.ticks;
+ _ISR_Enable( level );
+
+ tmp *= _TOD_Microseconds_per_tick;
+ ((rtems_clock_time_value *)time_buffer)->microseconds = tmp;
+
+ return RTEMS_SUCCESSFUL;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* should never get here */
+
+}
diff --git a/cpukit/rtems/src/clockset.c b/cpukit/rtems/src/clockset.c
new file mode 100644
index 0000000000..5de5dc0edb
--- /dev/null
+++ b/cpukit/rtems/src/clockset.c
@@ -0,0 +1,53 @@
+/*
+ * Clock Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/clock.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * rtems_clock_set
+ *
+ * This directive sets the date and time for this node.
+ *
+ * Input parameters:
+ * time_buffer - pointer to the time and date structure
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_clock_set(
+ rtems_time_of_day *time_buffer
+)
+{
+ rtems_interval seconds;
+
+ if ( !time_buffer )
+ return RTEMS_INVALID_ADDRESS;
+
+ if ( _TOD_Validate( time_buffer ) ) {
+ seconds = _TOD_To_seconds( time_buffer );
+ _Thread_Disable_dispatch();
+ _TOD_Set( time_buffer, seconds );
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+ return RTEMS_INVALID_CLOCK;
+}
diff --git a/cpukit/rtems/src/clocktick.c b/cpukit/rtems/src/clocktick.c
new file mode 100644
index 0000000000..39ed628e96
--- /dev/null
+++ b/cpukit/rtems/src/clocktick.c
@@ -0,0 +1,51 @@
+/*
+ * Clock Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/clock.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * rtems_clock_tick
+ *
+ * This directive notifies the executve that a tick has occurred.
+ * When the tick occurs the time manager updates and maintains
+ * the calendar time, timeslicing, and any timeout delays.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - always succeeds
+ *
+ * NOTE: This routine only works for leap-years through 2099.
+ */
+
+rtems_status_code rtems_clock_tick( void )
+{
+ _TOD_Tickle_ticks();
+
+ _Watchdog_Tickle_ticks();
+
+ _Thread_Tickle_timeslice();
+
+ if ( _Thread_Is_context_switch_necessary() &&
+ _Thread_Is_dispatching_enabled() )
+ _Thread_Dispatch();
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/rtems/src/clocktodtoseconds.c b/cpukit/rtems/src/clocktodtoseconds.c
new file mode 100644
index 0000000000..ae60f512b0
--- /dev/null
+++ b/cpukit/rtems/src/clocktodtoseconds.c
@@ -0,0 +1,63 @@
+/*
+ * Time of Day (TOD) Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * _TOD_To_seconds
+ *
+ * This routine returns the seconds from the epoch until the
+ * current date and time.
+ *
+ * Input parameters:
+ * the_tod - pointer to the time and date structure
+ *
+ * Output parameters:
+ * returns - seconds since epoch until the_tod
+ */
+
+uint32_t _TOD_To_seconds(
+ TOD_Control *the_tod
+)
+{
+ uint32_t time;
+ uint32_t year_mod_4;
+
+ time = the_tod->day - 1;
+ year_mod_4 = the_tod->year & 3;
+
+ if ( year_mod_4 == 0 )
+ time += _TOD_Days_to_date[ 1 ][ the_tod->month ];
+ else
+ time += _TOD_Days_to_date[ 0 ][ the_tod->month ];
+
+ time += ( (the_tod->year - TOD_BASE_YEAR) / 4 ) *
+ ( (TOD_DAYS_PER_YEAR * 4) + 1);
+
+ time += _TOD_Days_since_last_leap_year[ year_mod_4 ];
+
+ time *= TOD_SECONDS_PER_DAY;
+
+ time += ((the_tod->hour * TOD_MINUTES_PER_HOUR) + the_tod->minute)
+ * TOD_SECONDS_PER_MINUTE;
+
+ time += the_tod->second;
+
+ return( time );
+}
diff --git a/cpukit/rtems/src/clocktodvalidate.c b/cpukit/rtems/src/clocktodvalidate.c
new file mode 100644
index 0000000000..1a92f81c57
--- /dev/null
+++ b/cpukit/rtems/src/clocktodvalidate.c
@@ -0,0 +1,63 @@
+/*
+ * Time of Day (TOD) Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * _TOD_Validate
+ *
+ * This kernel routine checks the validity of a date and time structure.
+ *
+ * Input parameters:
+ * the_tod - pointer to a time and date structure
+ *
+ * Output parameters:
+ * TRUE - if the date, time, and tick are valid
+ * FALSE - if the the_tod is invalid
+ *
+ * NOTE: This routine only works for leap-years through 2099.
+ */
+
+boolean _TOD_Validate(
+ TOD_Control *the_tod
+)
+{
+ uint32_t days_in_month;
+
+ if ((!the_tod) ||
+ (the_tod->ticks >= _TOD_Ticks_per_second) ||
+ (the_tod->second >= TOD_SECONDS_PER_MINUTE) ||
+ (the_tod->minute >= TOD_MINUTES_PER_HOUR) ||
+ (the_tod->hour >= TOD_HOURS_PER_DAY) ||
+ (the_tod->month == 0) ||
+ (the_tod->month > TOD_MONTHS_PER_YEAR) ||
+ (the_tod->year < TOD_BASE_YEAR) ||
+ (the_tod->day == 0) )
+ return FALSE;
+
+ if ( (the_tod->year % 4) == 0 )
+ days_in_month = _TOD_Days_per_month[ 1 ][ the_tod->month ];
+ else
+ days_in_month = _TOD_Days_per_month[ 0 ][ the_tod->month ];
+
+ if ( the_tod->day > days_in_month )
+ return FALSE;
+
+ return TRUE;
+}
diff --git a/cpukit/rtems/src/dpmem.c b/cpukit/rtems/src/dpmem.c
new file mode 100644
index 0000000000..757450ab30
--- /dev/null
+++ b/cpukit/rtems/src/dpmem.c
@@ -0,0 +1,55 @@
+/*
+ * Dual Port Memory Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/address.h>
+#include <rtems/rtems/dpmem.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/rtems/dpmem.h>
+
+/*PAGE
+ *
+ * _Dual_ported_memory_Manager_initialization
+ *
+ * This routine initializes all dual-ported memory manager related
+ * data structures.
+ *
+ * Input parameters:
+ * maximum_ports - number of ports to initialize
+ *
+ * Output parameters: NONE
+ */
+
+void _Dual_ported_memory_Manager_initialization(
+ uint32_t maximum_ports
+)
+{
+ _Objects_Initialize_information(
+ &_Dual_ported_memory_Information, /* object information table */
+ OBJECTS_CLASSIC_API, /* object API */
+ OBJECTS_RTEMS_PORTS, /* object class */
+ maximum_ports, /* maximum objects of this class */
+ sizeof( Dual_ported_memory_Control ),
+ /* size of this object's control block */
+ FALSE, /* TRUE if names of this object are strings */
+ RTEMS_MAXIMUM_NAME_LENGTH /* maximum length of each object's name */
+#if defined(RTEMS_MULTIPROCESSING)
+ ,
+ FALSE, /* TRUE if this is a global object class */
+ NULL /* Proxy extraction support callout */
+#endif
+ );
+}
diff --git a/cpukit/rtems/src/dpmemcreate.c b/cpukit/rtems/src/dpmemcreate.c
new file mode 100644
index 0000000000..7c6e3604b0
--- /dev/null
+++ b/cpukit/rtems/src/dpmemcreate.c
@@ -0,0 +1,84 @@
+/*
+ * Dual Port Memory Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/address.h>
+#include <rtems/rtems/dpmem.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/rtems/dpmem.h>
+
+/*PAGE
+ *
+ * rtems_port_create
+ *
+ * This directive creates a port into a dual-ported memory area.
+ *
+ * Input parameters:
+ * name - user defined port name
+ * internal_start - internal start address of port
+ * external_start - external start address of port
+ * length - physical length in bytes
+ * id - address of port id to set
+ *
+ * Output parameters:
+ * id - port id
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_port_create(
+ rtems_name name,
+ void *internal_start,
+ void *external_start,
+ uint32_t length,
+ Objects_Id *id
+)
+{
+ register Dual_ported_memory_Control *the_port;
+
+ if ( !rtems_is_name_valid( name) )
+ return RTEMS_INVALID_NAME;
+
+ if ( !id )
+ return RTEMS_INVALID_ADDRESS;
+
+ if ( !_Addresses_Is_aligned( internal_start ) ||
+ !_Addresses_Is_aligned( external_start ) )
+ return RTEMS_INVALID_ADDRESS;
+
+ _Thread_Disable_dispatch(); /* to prevent deletion */
+
+ the_port = _Dual_ported_memory_Allocate();
+
+ if ( !the_port ) {
+ _Thread_Enable_dispatch();
+ return RTEMS_TOO_MANY;
+ }
+
+ the_port->internal_base = internal_start;
+ the_port->external_base = external_start;
+ the_port->length = length - 1;
+
+ _Objects_Open(
+ &_Dual_ported_memory_Information,
+ &the_port->Object,
+ (Objects_Name) name
+ );
+
+ *id = the_port->Object.id;
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/rtems/src/dpmemdelete.c b/cpukit/rtems/src/dpmemdelete.c
new file mode 100644
index 0000000000..d6cbae2528
--- /dev/null
+++ b/cpukit/rtems/src/dpmemdelete.c
@@ -0,0 +1,61 @@
+/*
+ * Dual Port Memory Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/address.h>
+#include <rtems/rtems/dpmem.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/rtems/dpmem.h>
+
+/*PAGE
+ *
+ * rtems_port_delete
+ *
+ * This directive allows a thread to delete a dual-ported memory area
+ * specified by the dual-ported memory identifier.
+ *
+ * Input parameters:
+ * id - dual-ported memory area id
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_port_delete(
+ Objects_Id id
+)
+{
+ register Dual_ported_memory_Control *the_port;
+ Objects_Locations location;
+
+ the_port = _Dual_ported_memory_Get( id, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE: /* this error cannot be returned */
+ return RTEMS_INTERNAL_ERROR;
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ _Objects_Close( &_Dual_ported_memory_Information, &the_port->Object );
+ _Dual_ported_memory_Free( the_port );
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/dpmemexternal2internal.c b/cpukit/rtems/src/dpmemexternal2internal.c
new file mode 100644
index 0000000000..d496404a50
--- /dev/null
+++ b/cpukit/rtems/src/dpmemexternal2internal.c
@@ -0,0 +1,75 @@
+/*
+ * Dual Port Memory Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/address.h>
+#include <rtems/rtems/dpmem.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/rtems/dpmem.h>
+
+/*PAGE
+ *
+ * rtems_port_external_to_internal
+ *
+ * This directive converts an external dual-ported memory address to an
+ * internal dual-ported memory address. If the given external address
+ * is an invalid dual-ported address, then the internal address is set
+ * to the given external address.
+ *
+ * Input parameters:
+ * id - id of dp memory object
+ * external - external address
+ * internal - pointer of internal address to set
+ *
+ * Output parameters:
+ * internal - internal address
+ * RTEMS_SUCCESSFUL - always succeeds
+ */
+
+rtems_status_code rtems_port_external_to_internal(
+ Objects_Id id,
+ void *external,
+ void **internal
+)
+{
+ register Dual_ported_memory_Control *the_port;
+ Objects_Locations location;
+ uint32_t ending;
+
+ if ( !internal )
+ return RTEMS_INVALID_ADDRESS;
+
+ the_port = _Dual_ported_memory_Get( id, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE: /* this error cannot be returned */
+ return RTEMS_INTERNAL_ERROR;
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ ending = _Addresses_Subtract( external, the_port->external_base );
+ if ( ending > the_port->length )
+ *internal = external;
+ else
+ *internal = _Addresses_Add_offset( the_port->internal_base,
+ ending );
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/dpmemident.c b/cpukit/rtems/src/dpmemident.c
new file mode 100644
index 0000000000..e3b6c63df8
--- /dev/null
+++ b/cpukit/rtems/src/dpmemident.c
@@ -0,0 +1,55 @@
+/*
+ * Dual Port Memory Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/address.h>
+#include <rtems/rtems/dpmem.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/rtems/dpmem.h>
+
+/*PAGE
+ *
+ * rtems_port_ident
+ *
+ * This directive returns the system ID associated with
+ * the port name.
+ *
+ * Input parameters:
+ * name - user defined port name
+ * id - pointer to port id
+ *
+ * Output parameters:
+ * *id - port id
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_port_ident(
+ rtems_name name,
+ Objects_Id *id
+)
+{
+ Objects_Name_or_id_lookup_errors status;
+
+ status = _Objects_Name_to_id(
+ &_Dual_ported_memory_Information,
+ (Objects_Name) name,
+ OBJECTS_SEARCH_ALL_NODES,
+ id
+ );
+
+ return _Status_Object_name_errors_to_status[ status ];
+}
diff --git a/cpukit/rtems/src/dpmeminternal2external.c b/cpukit/rtems/src/dpmeminternal2external.c
new file mode 100644
index 0000000000..defe8375f6
--- /dev/null
+++ b/cpukit/rtems/src/dpmeminternal2external.c
@@ -0,0 +1,75 @@
+/*
+ * Dual Port Memory Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/address.h>
+#include <rtems/rtems/dpmem.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/rtems/dpmem.h>
+
+/*PAGE
+ *
+ * rtems_port_internal_to_external
+ *
+ * This directive converts an internal dual-ported memory address to an
+ * external dual-ported memory address. If the given internal address
+ * is an invalid dual-ported address, then the external address is set
+ * to the given internal address.
+ *
+ * Input parameters:
+ * id - id of dual-ported memory object
+ * internal - internal address to set
+ * external - pointer to external address
+ *
+ * Output parameters:
+ * external - external address
+ * RTEMS_SUCCESSFUL - always succeeds
+ */
+
+rtems_status_code rtems_port_internal_to_external(
+ Objects_Id id,
+ void *internal,
+ void **external
+)
+{
+ register Dual_ported_memory_Control *the_port;
+ Objects_Locations location;
+ uint32_t ending;
+
+ if ( !external )
+ return RTEMS_INVALID_ADDRESS;
+
+ the_port = _Dual_ported_memory_Get( id, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE: /* this error cannot be returned */
+ return RTEMS_INTERNAL_ERROR;
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ ending = _Addresses_Subtract( internal, the_port->internal_base );
+ if ( ending > the_port->length )
+ *external = internal;
+ else
+ *external = _Addresses_Add_offset( the_port->external_base,
+ ending );
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/event.c b/cpukit/rtems/src/event.c
new file mode 100644
index 0000000000..0e339c6fcf
--- /dev/null
+++ b/cpukit/rtems/src/event.c
@@ -0,0 +1,44 @@
+/*
+ * Event Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/event.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/options.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/rtems/tasks.h>
+
+/*PAGE
+ *
+ * _Event_Manager_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this manager.
+ */
+
+void _Event_Manager_initialization( void )
+{
+ _Event_Sync_state = EVENT_SYNC_SYNCHRONIZED;
+
+ /*
+ * Register the MP Process Packet routine.
+ */
+
+#if defined(RTEMS_MULTIPROCESSING)
+ _MPCI_Register_packet_processor( MP_PACKET_EVENT, _Event_MP_Process_packet );
+#endif
+}
diff --git a/cpukit/rtems/src/eventmp.c b/cpukit/rtems/src/eventmp.c
new file mode 100644
index 0000000000..cf611c5d5b
--- /dev/null
+++ b/cpukit/rtems/src/eventmp.c
@@ -0,0 +1,189 @@
+/*
+ * Multiprocessing Support for the Event Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/event.h>
+#include <rtems/score/mpci.h>
+#include <rtems/score/mppkt.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/options.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/rtems/support.h>
+
+/*PAGE
+ *
+ * _Event_MP_Send_process_packet
+ *
+ * This subprogram is not needed since there are no process
+ * packets to be sent by this manager.
+ *
+ */
+
+/*PAGE
+ *
+ * _Event_MP_Send_request_packet
+ *
+ */
+
+rtems_status_code _Event_MP_Send_request_packet (
+ Event_MP_Remote_operations operation,
+ Objects_Id event_id,
+ rtems_event_set event_in
+)
+{
+ Event_MP_Packet *the_packet;
+
+ switch ( operation ) {
+
+ case EVENT_MP_SEND_REQUEST:
+
+ the_packet = _Event_MP_Get_packet();
+ the_packet->Prefix.the_class = MP_PACKET_EVENT;
+ the_packet->Prefix.length = sizeof ( Event_MP_Packet );
+ the_packet->Prefix.to_convert = sizeof ( Event_MP_Packet );
+ the_packet->operation = operation;
+ the_packet->Prefix.id = event_id;
+ the_packet->event_in = event_in;
+
+ return (rtems_status_code)
+ _MPCI_Send_request_packet(
+ rtems_get_node( event_id ),
+ &the_packet->Prefix,
+ STATES_READY
+ );
+
+ break;
+
+ case EVENT_MP_SEND_RESPONSE:
+ break;
+
+ }
+ /*
+ * The following line is included to satisfy compilers which
+ * produce warnings when a function does not end with a return.
+ */
+ return RTEMS_SUCCESSFUL;
+}
+
+/*PAGE
+ *
+ * _Event_MP_Send_response_packet
+ *
+ */
+
+void _Event_MP_Send_response_packet (
+ Event_MP_Remote_operations operation,
+ Thread_Control *the_thread
+)
+{
+ Event_MP_Packet *the_packet;
+
+ switch ( operation ) {
+
+ case EVENT_MP_SEND_RESPONSE:
+
+ the_packet = ( Event_MP_Packet *) the_thread->receive_packet;
+
+/*
+ * The packet being returned already contains the class, length, and
+ * to_convert fields, therefore they are not set in this routine.
+ */
+ the_packet->operation = operation;
+ the_packet->Prefix.id = the_packet->Prefix.source_tid;
+
+ _MPCI_Send_response_packet(
+ rtems_get_node( the_packet->Prefix.source_tid ),
+ &the_packet->Prefix
+ );
+ break;
+
+ case EVENT_MP_SEND_REQUEST:
+ break;
+
+ }
+}
+
+/*PAGE
+ *
+ *
+ * _Event_MP_Process_packet
+ *
+ */
+
+void _Event_MP_Process_packet (
+ rtems_packet_prefix *the_packet_prefix
+)
+{
+ Event_MP_Packet *the_packet;
+ Thread_Control *the_thread;
+
+ the_packet = (Event_MP_Packet *) the_packet_prefix;
+
+ switch ( the_packet->operation ) {
+
+ case EVENT_MP_SEND_REQUEST:
+
+ the_packet->Prefix.return_code = rtems_event_send(
+ the_packet->Prefix.id,
+ the_packet->event_in
+ );
+
+ _Event_MP_Send_response_packet(
+ EVENT_MP_SEND_RESPONSE,
+ _Thread_Executing
+ );
+ break;
+
+ case EVENT_MP_SEND_RESPONSE:
+
+ the_thread = _MPCI_Process_response( the_packet_prefix );
+
+ _MPCI_Return_packet( the_packet_prefix );
+
+ break;
+
+ }
+}
+
+/*PAGE
+ *
+ * _Event_MP_Send_object_was_deleted
+ *
+ * This subprogram is not needed since there are no objects
+ * deleted by this manager.
+ *
+ */
+
+/*PAGE
+ *
+ * _Event_MP_Send_extract_proxy
+ *
+ * This subprogram is not needed since there are no objects
+ * deleted by this manager.
+ *
+ */
+
+/*PAGE
+ *
+ * _Event_MP_Get_packet
+ *
+ */
+
+Event_MP_Packet *_Event_MP_Get_packet ( void )
+{
+ return ( (Event_MP_Packet *) _MPCI_Get_packet() );
+}
+
+/* end of file */
diff --git a/cpukit/rtems/src/eventreceive.c b/cpukit/rtems/src/eventreceive.c
new file mode 100644
index 0000000000..646f0b9bca
--- /dev/null
+++ b/cpukit/rtems/src/eventreceive.c
@@ -0,0 +1,65 @@
+/*
+ * Event Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/event.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/options.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/rtems/tasks.h>
+
+/*PAGE
+ *
+ * rtems_event_receive
+ *
+ * This directive allows a thread to receive a set of events.
+ *
+ * Input parameters:
+ * event_in - input event condition
+ * option_set - options
+ * ticks - number of ticks to wait (0 means wait forever)
+ * event_out - pointer to output event set
+ *
+ * Output parameters:
+ * event out - event set
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_event_receive(
+ rtems_event_set event_in,
+ rtems_option option_set,
+ rtems_interval ticks,
+ rtems_event_set *event_out
+)
+{
+ RTEMS_API_Control *api;
+
+ if ( !event_out )
+ return RTEMS_INVALID_ADDRESS;
+
+ api = _Thread_Executing->API_Extensions[ THREAD_API_RTEMS ];
+
+ if ( _Event_sets_Is_empty( event_in ) ) {
+ *event_out = api->pending_events;
+ return RTEMS_SUCCESSFUL;
+ }
+
+ _Thread_Disable_dispatch();
+ _Event_Seize( event_in, option_set, ticks, event_out );
+ _Thread_Enable_dispatch();
+ return( _Thread_Executing->Wait.return_code );
+}
diff --git a/cpukit/rtems/src/eventseize.c b/cpukit/rtems/src/eventseize.c
new file mode 100644
index 0000000000..091f46864d
--- /dev/null
+++ b/cpukit/rtems/src/eventseize.c
@@ -0,0 +1,138 @@
+/*
+ * Event Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/event.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/options.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/rtems/tasks.h>
+
+/*PAGE
+ *
+ * _Event_Seize
+ *
+ * This routine attempts to satisfy the requested event condition
+ * for the running thread.
+ *
+ * Input parameters:
+ * event_in - the event condition to satisfy
+ * option_set - acquire event options
+ * ticks - interval to wait
+ * event_out - pointer to event set output area
+ *
+ * Output parameters: NONE
+ * *event_out - event set output area filled in
+ *
+ * INTERRUPT LATENCY:
+ * available
+ * wait
+ * check sync
+ */
+
+void _Event_Seize(
+ rtems_event_set event_in,
+ rtems_option option_set,
+ rtems_interval ticks,
+ rtems_event_set *event_out
+)
+{
+ Thread_Control *executing;
+ rtems_event_set seized_events;
+ rtems_event_set pending_events;
+ ISR_Level level;
+ RTEMS_API_Control *api;
+ Event_Sync_states sync_state;
+
+ executing = _Thread_Executing;
+ executing->Wait.return_code = RTEMS_SUCCESSFUL;
+
+ api = executing->API_Extensions[ THREAD_API_RTEMS ];
+
+ _ISR_Disable( level );
+ pending_events = api->pending_events;
+ seized_events = _Event_sets_Get( pending_events, event_in );
+
+ if ( !_Event_sets_Is_empty( seized_events ) &&
+ (seized_events == event_in || _Options_Is_any( option_set )) ) {
+ api->pending_events =
+ _Event_sets_Clear( pending_events, seized_events );
+ _ISR_Enable( level );
+ *event_out = seized_events;
+ return;
+ }
+
+ if ( _Options_Is_no_wait( option_set ) ) {
+ _ISR_Enable( level );
+ executing->Wait.return_code = RTEMS_UNSATISFIED;
+ *event_out = seized_events;
+ return;
+ }
+
+ _Event_Sync_state = EVENT_SYNC_NOTHING_HAPPENED;
+
+ executing->Wait.option = (uint32_t ) option_set;
+ executing->Wait.count = (uint32_t ) event_in;
+ executing->Wait.return_argument = event_out;
+
+ _ISR_Enable( level );
+
+ if ( ticks ) {
+ _Watchdog_Initialize(
+ &executing->Timer,
+ _Event_Timeout,
+ executing->Object.id,
+ NULL
+ );
+ _Watchdog_Insert_ticks( &executing->Timer, ticks );
+ }
+
+ _Thread_Set_state( executing, STATES_WAITING_FOR_EVENT );
+
+ _ISR_Disable( level );
+
+ sync_state = _Event_Sync_state;
+ _Event_Sync_state = EVENT_SYNC_SYNCHRONIZED;
+
+ switch ( sync_state ) {
+ case EVENT_SYNC_SYNCHRONIZED:
+ /*
+ * This cannot happen. It indicates that this routine did not
+ * enter the synchronization states above.
+ */
+ return;
+
+ case EVENT_SYNC_NOTHING_HAPPENED:
+ _ISR_Enable( level );
+ return;
+
+ case EVENT_SYNC_TIMEOUT:
+ executing->Wait.return_code = RTEMS_TIMEOUT;
+ _ISR_Enable( level );
+ _Thread_Unblock( executing );
+ return;
+
+ case EVENT_SYNC_SATISFIED:
+ if ( _Watchdog_Is_active( &executing->Timer ) ) {
+ _Watchdog_Deactivate( &executing->Timer );
+ _ISR_Enable( level );
+ (void) _Watchdog_Remove( &executing->Timer );
+ } else
+ _ISR_Enable( level );
+ _Thread_Unblock( executing );
+ return;
+ }
+}
diff --git a/cpukit/rtems/src/eventsend.c b/cpukit/rtems/src/eventsend.c
new file mode 100644
index 0000000000..8294fb3117
--- /dev/null
+++ b/cpukit/rtems/src/eventsend.c
@@ -0,0 +1,71 @@
+/*
+ * Event Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/event.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/options.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/rtems/tasks.h>
+
+/*PAGE
+ *
+ * rtems_event_send
+ *
+ * This directive allows a thread send an event set to another thread.
+ *
+ * Input parameters:
+ * id - thread id
+ * event - event set
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_event_send(
+ Objects_Id id,
+ rtems_event_set event_in
+)
+{
+ register Thread_Control *the_thread;
+ Objects_Locations location;
+ RTEMS_API_Control *api;
+
+ the_thread = _Thread_Get( id, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE:
+#if defined(RTEMS_MULTIPROCESSING)
+ return(
+ _Event_MP_Send_request_packet(
+ EVENT_MP_SEND_REQUEST,
+ id,
+ event_in
+ )
+ );
+#endif
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+ case OBJECTS_LOCAL:
+ api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
+ _Event_sets_Post( event_in, &api->pending_events );
+ _Event_Surrender( the_thread );
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/eventsurrender.c b/cpukit/rtems/src/eventsurrender.c
new file mode 100644
index 0000000000..72ba56e9cb
--- /dev/null
+++ b/cpukit/rtems/src/eventsurrender.c
@@ -0,0 +1,106 @@
+/*
+ * Event Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/event.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/options.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/rtems/tasks.h>
+
+/*PAGE
+ *
+ * _Event_Surrender
+ *
+ * This routines remove a thread from the specified threadq.
+ *
+ * Input parameters:
+ * the_thread - pointer to thread to be dequeued
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY:
+ * before flash
+ * after flash
+ * check sync
+ */
+
+void _Event_Surrender(
+ Thread_Control *the_thread
+)
+{
+ ISR_Level level;
+ rtems_event_set pending_events;
+ rtems_event_set event_condition;
+ rtems_event_set seized_events;
+ rtems_option option_set;
+ RTEMS_API_Control *api;
+
+ api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
+
+ option_set = (rtems_option) the_thread->Wait.option;
+
+ _ISR_Disable( level );
+ pending_events = api->pending_events;
+ event_condition = (rtems_event_set) the_thread->Wait.count;
+
+ seized_events = _Event_sets_Get( pending_events, event_condition );
+
+ if ( !_Event_sets_Is_empty( seized_events ) ) {
+ if ( _States_Is_waiting_for_event( the_thread->current_state ) ) {
+ if ( seized_events == event_condition || _Options_Is_any( option_set ) ) {
+ api->pending_events =
+ _Event_sets_Clear( pending_events, seized_events );
+ (rtems_event_set) the_thread->Wait.count = 0;
+ *(rtems_event_set *)the_thread->Wait.return_argument = seized_events;
+
+ _ISR_Flash( level );
+
+ if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
+ _ISR_Enable( level );
+ _Thread_Unblock( the_thread );
+ }
+ else {
+ _Watchdog_Deactivate( &the_thread->Timer );
+ _ISR_Enable( level );
+ (void) _Watchdog_Remove( &the_thread->Timer );
+ _Thread_Unblock( the_thread );
+ }
+ return;
+ }
+ }
+
+ switch ( _Event_Sync_state ) {
+ case EVENT_SYNC_SYNCHRONIZED:
+ case EVENT_SYNC_SATISFIED:
+ break;
+
+ case EVENT_SYNC_NOTHING_HAPPENED:
+ case EVENT_SYNC_TIMEOUT:
+ if ( !_Thread_Is_executing( the_thread ) )
+ break;
+
+ if ( seized_events == event_condition || _Options_Is_any(option_set) ) {
+ api->pending_events =
+ _Event_sets_Clear( pending_events,seized_events );
+ *(rtems_event_set *)the_thread->Wait.return_argument = seized_events;
+ _Event_Sync_state = EVENT_SYNC_SATISFIED;
+ }
+ break;
+ }
+ }
+ _ISR_Enable( level );
+}
diff --git a/cpukit/rtems/src/eventtimeout.c b/cpukit/rtems/src/eventtimeout.c
new file mode 100644
index 0000000000..292324d4b9
--- /dev/null
+++ b/cpukit/rtems/src/eventtimeout.c
@@ -0,0 +1,87 @@
+/*
+ * Event Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/event.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/options.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/rtems/tasks.h>
+
+/*PAGE
+ *
+ * _Event_Timeout
+ *
+ * This routine processes a thread which timeouts while waiting to
+ * receive an event_set. It is called by the watchdog handler.
+ *
+ * Input parameters:
+ * id - thread id
+ *
+ * Output parameters: NONE
+ */
+
+void _Event_Timeout(
+ Objects_Id id,
+ void *ignored
+)
+{
+ Thread_Control *the_thread;
+ Objects_Locations location;
+ ISR_Level level;
+
+ the_thread = _Thread_Get( id, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE: /* impossible */
+ case OBJECTS_ERROR:
+ break;
+ case OBJECTS_LOCAL:
+
+ /*
+ * If the event manager is not synchronized, then it is either
+ * "nothing happened", "timeout", or "satisfied". If the_thread
+ * is the executing thread, then it is in the process of blocking
+ * and it is the thread which is responsible for the synchronization
+ * process.
+ *
+ * If it is not satisfied, then it is "nothing happened" and
+ * this is the "timeout" transition. After a request is satisfied,
+ * a timeout is not allowed to occur.
+ */
+
+ _ISR_Disable( level );
+ if ( the_thread->Wait.count ) { /* verify thread is waiting */
+ the_thread->Wait.count = 0;
+ if ( _Event_Sync_state != EVENT_SYNC_SYNCHRONIZED &&
+ _Thread_Is_executing( the_thread ) ) {
+ if ( _Event_Sync_state != EVENT_SYNC_SATISFIED ) {
+ _Event_Sync_state = EVENT_SYNC_TIMEOUT;
+ }
+ _ISR_Enable( level );
+ } else {
+ the_thread->Wait.return_code = RTEMS_TIMEOUT;
+ _ISR_Enable( level );
+ _Thread_Unblock( the_thread );
+ }
+ }
+ else {
+ _ISR_Enable( level );
+ }
+
+ _Thread_Unnest_dispatch();
+ break;
+ }
+}
diff --git a/cpukit/rtems/src/intr.c b/cpukit/rtems/src/intr.c
new file mode 100644
index 0000000000..a44ddf8137
--- /dev/null
+++ b/cpukit/rtems/src/intr.c
@@ -0,0 +1,31 @@
+/*
+ * Interrupt Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/score/isr.h>
+#include <rtems/rtems/intr.h>
+
+/* _Interrupt_Manager_initialization
+ *
+ * This routine initializes the interrupt manager.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ */
+
+void _Interrupt_Manager_initialization( void )
+{
+}
diff --git a/cpukit/rtems/src/intrbody.c b/cpukit/rtems/src/intrbody.c
new file mode 100644
index 0000000000..526a196adf
--- /dev/null
+++ b/cpukit/rtems/src/intrbody.c
@@ -0,0 +1,70 @@
+/*
+ * Bodies for Inlined Interrupt Manager Routines
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/score/isr.h>
+#include <rtems/rtems/intr.h>
+
+/*
+ * Real body for rtems_interrupt_disable
+ */
+
+#undef rtems_interrupt_disable
+
+rtems_interrupt_level rtems_interrupt_disable( void )
+{
+ rtems_interrupt_level previous_level;
+
+ _ISR_Disable( previous_level );
+
+ return previous_level;
+}
+
+/*
+ * Real body for rtems_interrupt_enable
+ */
+
+#undef rtems_interrupt_enable
+
+void rtems_interrupt_enable(
+ rtems_interrupt_level previous_level
+)
+{
+ _ISR_Enable( previous_level );
+}
+
+/*
+ * Real body for rtems_interrupt_flash
+ */
+
+#undef rtems_interrupt_flash
+
+void rtems_interrupt_flash(
+ rtems_interrupt_level previous_level
+)
+{
+ _ISR_Flash( previous_level );
+}
+
+/*
+ * Real body for rtems_interrupt_is_in_progress
+ */
+
+#undef rtems_interrupt_is_in_progress
+
+boolean rtems_interrupt_is_in_progress( void )
+{
+ return _ISR_Is_in_progress();
+}
diff --git a/cpukit/rtems/src/intrcatch.c b/cpukit/rtems/src/intrcatch.c
new file mode 100644
index 0000000000..8725f12507
--- /dev/null
+++ b/cpukit/rtems/src/intrcatch.c
@@ -0,0 +1,54 @@
+/*
+ * Interrupt Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/score/isr.h>
+#include <rtems/rtems/intr.h>
+
+/* rtems_interrupt_catch
+ *
+ * This directive allows a thread to specify what action to take when
+ * catching signals.
+ *
+ * Input parameters:
+ * new_isr_handler - address of interrupt service routine (isr)
+ * vector - interrupt vector number
+ * old_isr_handler - address at which to store previous ISR address
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - always succeeds
+ * *old_isr_handler - previous ISR address
+ */
+
+rtems_status_code rtems_interrupt_catch(
+ rtems_isr_entry new_isr_handler,
+ rtems_vector_number vector,
+ rtems_isr_entry *old_isr_handler
+)
+{
+ if ( !_ISR_Is_vector_number_valid( vector ) )
+ return RTEMS_INVALID_NUMBER;
+
+ if ( !_ISR_Is_valid_user_handler( (void *) new_isr_handler ) )
+ return RTEMS_INVALID_ADDRESS;
+
+ if ( !_ISR_Is_valid_user_handler( (void *) old_isr_handler ) )
+ return RTEMS_INVALID_ADDRESS;
+
+ _ISR_Install_vector(
+ vector, (proc_ptr)new_isr_handler, (proc_ptr *)old_isr_handler );
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/rtems/src/mp.c b/cpukit/rtems/src/mp.c
new file mode 100644
index 0000000000..aa2dbc40d0
--- /dev/null
+++ b/cpukit/rtems/src/mp.c
@@ -0,0 +1,41 @@
+/*
+ * Multiprocessing Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/mp.h>
+#include <rtems/score/mpci.h>
+
+/*PAGE
+ *
+ * _Multiprocessing_Manager_initialization
+ *
+ */
+
+void _Multiprocessing_Manager_initialization ( void )
+{
+}
+
+/*PAGE
+ *
+ * rtems_multiprocessing_announce
+ *
+ */
+
+void rtems_multiprocessing_announce ( void )
+{
+ _MPCI_Announce();
+}
+
+/* end of file */
diff --git a/cpukit/rtems/src/msg.c b/cpukit/rtems/src/msg.c
new file mode 100644
index 0000000000..02800b4f3c
--- /dev/null
+++ b/cpukit/rtems/src/msg.c
@@ -0,0 +1,77 @@
+/*
+ * Message Queue Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/coremsg.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/attr.h>
+#include <rtems/rtems/message.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/support.h>
+
+/*PAGE
+ *
+ * _Message_queue_Manager_initialization
+ *
+ * This routine initializes all message queue manager related
+ * data structures.
+ *
+ * Input parameters:
+ * maximum_message_queues - number of message queues to initialize
+ *
+ * Output parameters: NONE
+ */
+
+void _Message_queue_Manager_initialization(
+ uint32_t maximum_message_queues
+)
+{
+ _Objects_Initialize_information(
+ &_Message_queue_Information, /* object information table */
+ OBJECTS_CLASSIC_API, /* object API */
+ OBJECTS_RTEMS_MESSAGE_QUEUES, /* object class */
+ maximum_message_queues, /* maximum objects of this class */
+ sizeof( Message_queue_Control ),
+ /* size of this object's control block */
+ FALSE, /* TRUE if names of this object are strings */
+ RTEMS_MAXIMUM_NAME_LENGTH /* maximum length of each object's name */
+#if defined(RTEMS_MULTIPROCESSING)
+ ,
+ TRUE, /* TRUE if this is a global object class */
+ _Message_queue_MP_Send_extract_proxy /* Proxy extraction support callout */
+#endif
+ );
+
+ /*
+ * Register the MP Process Packet routine.
+ */
+
+#if defined(RTEMS_MULTIPROCESSING)
+ _MPCI_Register_packet_processor(
+ MP_PACKET_MESSAGE_QUEUE,
+ _Message_queue_MP_Process_packet
+ );
+#endif
+
+}
diff --git a/cpukit/rtems/src/msgmp.c b/cpukit/rtems/src/msgmp.c
new file mode 100644
index 0000000000..f9c2ba032f
--- /dev/null
+++ b/cpukit/rtems/src/msgmp.c
@@ -0,0 +1,506 @@
+/*
+ * Multiprocessing Support for the Message Queue Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/message.h>
+#include <rtems/score/mpci.h>
+#include <rtems/rtems/msgmp.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/options.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/rtems/support.h>
+
+/*PAGE
+ *
+ * _Message_queue_MP_Send_process_packet
+ *
+ */
+
+void _Message_queue_MP_Send_process_packet (
+ Message_queue_MP_Remote_operations operation,
+ Objects_Id message_queue_id,
+ rtems_name name,
+ Objects_Id proxy_id
+)
+{
+ Message_queue_MP_Packet *the_packet;
+ uint32_t node;
+
+ switch ( operation ) {
+
+ case MESSAGE_QUEUE_MP_ANNOUNCE_CREATE:
+ case MESSAGE_QUEUE_MP_ANNOUNCE_DELETE:
+ case MESSAGE_QUEUE_MP_EXTRACT_PROXY:
+
+ the_packet = _Message_queue_MP_Get_packet();
+ the_packet->Prefix.the_class = MP_PACKET_MESSAGE_QUEUE;
+ the_packet->Prefix.length = sizeof ( Message_queue_MP_Packet );
+ the_packet->Prefix.to_convert = sizeof ( Message_queue_MP_Packet );
+ the_packet->operation = operation;
+ the_packet->Prefix.id = message_queue_id;
+ the_packet->name = name;
+ the_packet->proxy_id = proxy_id;
+
+ if ( operation == MESSAGE_QUEUE_MP_EXTRACT_PROXY )
+ node = rtems_get_node( message_queue_id );
+ else
+ node = MPCI_ALL_NODES;
+
+ _MPCI_Send_process_packet( node, &the_packet->Prefix );
+ break;
+
+ case MESSAGE_QUEUE_MP_RECEIVE_REQUEST:
+ case MESSAGE_QUEUE_MP_RECEIVE_RESPONSE:
+ case MESSAGE_QUEUE_MP_SEND_REQUEST:
+ case MESSAGE_QUEUE_MP_SEND_RESPONSE:
+ case MESSAGE_QUEUE_MP_URGENT_REQUEST:
+ case MESSAGE_QUEUE_MP_URGENT_RESPONSE:
+ case MESSAGE_QUEUE_MP_BROADCAST_REQUEST:
+ case MESSAGE_QUEUE_MP_BROADCAST_RESPONSE:
+ case MESSAGE_QUEUE_MP_FLUSH_REQUEST:
+ case MESSAGE_QUEUE_MP_FLUSH_RESPONSE:
+ case MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_REQUEST:
+ case MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_RESPONSE:
+ break;
+
+ }
+}
+
+/*PAGE
+ *
+ * _Message_queue_MP_Send_request_packet
+ *
+ */
+
+rtems_status_code _Message_queue_MP_Send_request_packet (
+ Message_queue_MP_Remote_operations operation,
+ Objects_Id message_queue_id,
+ void *buffer,
+ uint32_t *size_p,
+ rtems_option option_set,
+ rtems_interval timeout
+)
+{
+ Message_queue_MP_Packet *the_packet;
+
+ switch ( operation ) {
+
+ case MESSAGE_QUEUE_MP_SEND_REQUEST:
+ case MESSAGE_QUEUE_MP_URGENT_REQUEST:
+ case MESSAGE_QUEUE_MP_BROADCAST_REQUEST:
+ case MESSAGE_QUEUE_MP_FLUSH_REQUEST:
+ case MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_REQUEST:
+
+ the_packet = _Message_queue_MP_Get_packet();
+ the_packet->Prefix.the_class = MP_PACKET_MESSAGE_QUEUE;
+ the_packet->Prefix.length = sizeof(Message_queue_MP_Packet);
+ if ( size_p )
+ the_packet->Prefix.length += *size_p;
+ the_packet->Prefix.to_convert = sizeof(Message_queue_MP_Packet);
+
+ /*
+ * make sure message is not too big for our MPCI driver
+ * We have to check it here instead of waiting for MPCI because
+ * we are about to slam in the payload
+ */
+
+ if (the_packet->Prefix.length > _MPCI_table->maximum_packet_size) {
+ _Thread_Enable_dispatch();
+ return RTEMS_INVALID_SIZE;
+ }
+
+ if (! _Options_Is_no_wait(option_set))
+ the_packet->Prefix.timeout = timeout;
+
+ the_packet->operation = operation;
+ the_packet->Prefix.id = message_queue_id;
+ the_packet->option_set = option_set;
+
+ /*
+ * Copy the data into place if needed
+ */
+
+ if (buffer) {
+ the_packet->Buffer.size = *size_p;
+ _CORE_message_queue_Copy_buffer(
+ buffer,
+ the_packet->Buffer.buffer,
+ *size_p
+ );
+ }
+
+ return (rtems_status_code) _MPCI_Send_request_packet(
+ rtems_get_node(message_queue_id),
+ &the_packet->Prefix,
+ STATES_WAITING_FOR_MESSAGE
+ );
+ break;
+
+ case MESSAGE_QUEUE_MP_RECEIVE_REQUEST:
+
+ the_packet = _Message_queue_MP_Get_packet();
+ the_packet->Prefix.the_class = MP_PACKET_MESSAGE_QUEUE;
+ the_packet->Prefix.length = sizeof(Message_queue_MP_Packet);
+ the_packet->Prefix.to_convert = sizeof(Message_queue_MP_Packet);
+
+ if (! _Options_Is_no_wait(option_set))
+ the_packet->Prefix.timeout = timeout;
+
+ the_packet->operation = MESSAGE_QUEUE_MP_RECEIVE_REQUEST;
+ the_packet->Prefix.id = message_queue_id;
+ the_packet->option_set = option_set;
+ the_packet->size = 0; /* just in case of an error */
+
+ _Thread_Executing->Wait.return_argument = (uint32_t *)buffer;
+ _Thread_Executing->Wait.return_argument_1 = size_p;
+
+ return (rtems_status_code) _MPCI_Send_request_packet(
+ rtems_get_node(message_queue_id),
+ &the_packet->Prefix,
+ STATES_WAITING_FOR_MESSAGE
+ );
+ break;
+
+ case MESSAGE_QUEUE_MP_ANNOUNCE_CREATE:
+ case MESSAGE_QUEUE_MP_ANNOUNCE_DELETE:
+ case MESSAGE_QUEUE_MP_EXTRACT_PROXY:
+ case MESSAGE_QUEUE_MP_RECEIVE_RESPONSE:
+ case MESSAGE_QUEUE_MP_SEND_RESPONSE:
+ case MESSAGE_QUEUE_MP_URGENT_RESPONSE:
+ case MESSAGE_QUEUE_MP_BROADCAST_RESPONSE:
+ case MESSAGE_QUEUE_MP_FLUSH_RESPONSE:
+ case MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_RESPONSE:
+ break;
+ }
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*PAGE
+ *
+ * _Message_queue_MP_Send_response_packet
+ *
+ */
+
+void _Message_queue_MP_Send_response_packet (
+ Message_queue_MP_Remote_operations operation,
+ Objects_Id message_queue_id,
+ Thread_Control *the_thread
+)
+{
+ Message_queue_MP_Packet *the_packet;
+
+ switch ( operation ) {
+
+ case MESSAGE_QUEUE_MP_RECEIVE_RESPONSE:
+ case MESSAGE_QUEUE_MP_SEND_RESPONSE:
+ case MESSAGE_QUEUE_MP_URGENT_RESPONSE:
+ case MESSAGE_QUEUE_MP_BROADCAST_RESPONSE:
+ case MESSAGE_QUEUE_MP_FLUSH_RESPONSE:
+ case MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_RESPONSE:
+
+ the_packet = ( Message_queue_MP_Packet *) the_thread->receive_packet;
+
+/*
+ * The packet being returned already contains the class, length, and
+ * to_convert fields, therefore they are not set in this routine.
+ *
+ * Exception: MESSAGE_QUEUE_MP_RECEIVE_RESPONSE needs payload length
+ * added to 'length'
+ */
+ the_packet->operation = operation;
+ the_packet->Prefix.id = the_packet->Prefix.source_tid;
+
+ if (operation == MESSAGE_QUEUE_MP_RECEIVE_RESPONSE)
+ the_packet->Prefix.length += the_packet->size;
+
+ _MPCI_Send_response_packet(
+ rtems_get_node( the_packet->Prefix.source_tid ),
+ &the_packet->Prefix
+ );
+ break;
+
+ case MESSAGE_QUEUE_MP_ANNOUNCE_CREATE:
+ case MESSAGE_QUEUE_MP_ANNOUNCE_DELETE:
+ case MESSAGE_QUEUE_MP_EXTRACT_PROXY:
+ case MESSAGE_QUEUE_MP_RECEIVE_REQUEST:
+ case MESSAGE_QUEUE_MP_SEND_REQUEST:
+ case MESSAGE_QUEUE_MP_URGENT_REQUEST:
+ case MESSAGE_QUEUE_MP_BROADCAST_REQUEST:
+ case MESSAGE_QUEUE_MP_FLUSH_REQUEST:
+ case MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_REQUEST:
+ break;
+
+ }
+}
+
+/*PAGE
+ *
+ *
+ * _Message_queue_MP_Process_packet
+ *
+ */
+
+void _Message_queue_MP_Process_packet (
+ rtems_packet_prefix *the_packet_prefix
+)
+{
+ Message_queue_MP_Packet *the_packet;
+ Thread_Control *the_thread;
+ boolean ignored;
+
+ the_packet = (Message_queue_MP_Packet *) the_packet_prefix;
+
+ switch ( the_packet->operation ) {
+
+ case MESSAGE_QUEUE_MP_ANNOUNCE_CREATE:
+
+ ignored = _Objects_MP_Allocate_and_open(
+ &_Message_queue_Information,
+ the_packet->name,
+ the_packet->Prefix.id,
+ TRUE
+ );
+
+ _MPCI_Return_packet( the_packet_prefix );
+ break;
+
+ case MESSAGE_QUEUE_MP_ANNOUNCE_DELETE:
+
+ _Objects_MP_Close( &_Message_queue_Information, the_packet->Prefix.id );
+
+ _MPCI_Return_packet( the_packet_prefix );
+ break;
+
+ case MESSAGE_QUEUE_MP_EXTRACT_PROXY:
+
+ the_thread = _Thread_MP_Find_proxy( the_packet->proxy_id );
+
+ if (! _Thread_Is_null( the_thread ) )
+ _Thread_queue_Extract( the_thread->Wait.queue, the_thread );
+
+ _MPCI_Return_packet( the_packet_prefix );
+ break;
+
+ case MESSAGE_QUEUE_MP_RECEIVE_REQUEST:
+
+ the_packet->Prefix.return_code = rtems_message_queue_receive(
+ the_packet->Prefix.id,
+ the_packet->Buffer.buffer,
+ &the_packet->size,
+ the_packet->option_set,
+ the_packet->Prefix.timeout
+ );
+
+ if (! _Thread_Is_proxy_blocking( the_packet->Prefix.return_code ) )
+ _Message_queue_MP_Send_response_packet(
+ MESSAGE_QUEUE_MP_RECEIVE_RESPONSE,
+ the_packet->Prefix.id,
+ _Thread_Executing
+ );
+ break;
+
+ case MESSAGE_QUEUE_MP_RECEIVE_RESPONSE:
+
+ the_thread = _MPCI_Process_response( the_packet_prefix );
+
+ if (the_packet->Prefix.return_code == RTEMS_SUCCESSFUL) {
+ *(uint32_t *)the_thread->Wait.return_argument_1 =
+ the_packet->size;
+
+ _CORE_message_queue_Copy_buffer(
+ the_packet->Buffer.buffer,
+ the_thread->Wait.return_argument,
+ the_packet->size
+ );
+ }
+
+ _MPCI_Return_packet( the_packet_prefix );
+ break;
+
+ case MESSAGE_QUEUE_MP_SEND_REQUEST:
+
+ the_packet->Prefix.return_code = rtems_message_queue_send(
+ the_packet->Prefix.id,
+ the_packet->Buffer.buffer,
+ the_packet->Buffer.size
+ );
+
+ _Message_queue_MP_Send_response_packet(
+ MESSAGE_QUEUE_MP_SEND_RESPONSE,
+ the_packet->Prefix.id,
+ _Thread_Executing
+ );
+ break;
+
+ case MESSAGE_QUEUE_MP_SEND_RESPONSE:
+ case MESSAGE_QUEUE_MP_URGENT_RESPONSE:
+
+ the_thread = _MPCI_Process_response( the_packet_prefix );
+
+ _MPCI_Return_packet( the_packet_prefix );
+ break;
+
+ case MESSAGE_QUEUE_MP_URGENT_REQUEST:
+
+ the_packet->Prefix.return_code = rtems_message_queue_urgent(
+ the_packet->Prefix.id,
+ the_packet->Buffer.buffer,
+ the_packet->Buffer.size
+ );
+
+ _Message_queue_MP_Send_response_packet(
+ MESSAGE_QUEUE_MP_URGENT_RESPONSE,
+ the_packet->Prefix.id,
+ _Thread_Executing
+ );
+ break;
+
+ case MESSAGE_QUEUE_MP_BROADCAST_REQUEST:
+
+ the_packet->Prefix.return_code = rtems_message_queue_broadcast(
+ the_packet->Prefix.id,
+ the_packet->Buffer.buffer,
+ the_packet->Buffer.size,
+ &the_packet->count
+ );
+
+ _Message_queue_MP_Send_response_packet(
+ MESSAGE_QUEUE_MP_BROADCAST_RESPONSE,
+ the_packet->Prefix.id,
+ _Thread_Executing
+ );
+ break;
+
+ case MESSAGE_QUEUE_MP_BROADCAST_RESPONSE:
+ case MESSAGE_QUEUE_MP_FLUSH_RESPONSE:
+ case MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_RESPONSE:
+
+ the_thread = _MPCI_Process_response( the_packet_prefix );
+
+ *(uint32_t *)the_thread->Wait.return_argument = the_packet->count;
+
+ _MPCI_Return_packet( the_packet_prefix );
+ break;
+
+ case MESSAGE_QUEUE_MP_FLUSH_REQUEST:
+
+ the_packet->Prefix.return_code = rtems_message_queue_flush(
+ the_packet->Prefix.id,
+ &the_packet->count
+ );
+
+ _Message_queue_MP_Send_response_packet(
+ MESSAGE_QUEUE_MP_FLUSH_RESPONSE,
+ the_packet->Prefix.id,
+ _Thread_Executing
+ );
+ break;
+
+ case MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_REQUEST:
+
+ the_packet->Prefix.return_code = rtems_message_queue_get_number_pending(
+ the_packet->Prefix.id,
+ &the_packet->count
+ );
+
+ _Message_queue_MP_Send_response_packet(
+ MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_RESPONSE,
+ the_packet->Prefix.id,
+ _Thread_Executing
+ );
+ break;
+
+ }
+}
+
+/*PAGE
+ *
+ * _Message_queue_MP_Send_object_was_deleted
+ *
+ */
+
+void _Message_queue_MP_Send_object_was_deleted (
+ Thread_Control *the_proxy
+)
+{
+ the_proxy->receive_packet->return_code = RTEMS_OBJECT_WAS_DELETED;
+
+ _Message_queue_MP_Send_response_packet(
+ MESSAGE_QUEUE_MP_RECEIVE_RESPONSE,
+ the_proxy->Wait.id,
+ the_proxy
+ );
+}
+
+/*PAGE
+ *
+ * _Message_queue_MP_Send_extract_proxy
+ *
+ */
+
+void _Message_queue_MP_Send_extract_proxy (
+ void *argument
+)
+{
+ Thread_Control *the_thread = (Thread_Control *)argument;
+
+ _Message_queue_MP_Send_process_packet(
+ MESSAGE_QUEUE_MP_EXTRACT_PROXY,
+ the_thread->Wait.id,
+ (rtems_name) 0,
+ the_thread->Object.id
+ );
+}
+
+/*PAGE
+ *
+ * _Message_queue_MP_Get_packet
+ *
+ */
+
+Message_queue_MP_Packet *_Message_queue_MP_Get_packet ( void )
+{
+ return ( (Message_queue_MP_Packet *) _MPCI_Get_packet() );
+}
+
+
+/*PAGE
+ *
+ * _Message_queue_Core_message_queue_mp_support
+ *
+ * Input parameters:
+ * the_thread - the remote thread the message was submitted to
+ * id - id of the message queue
+ *
+ * Output parameters: NONE
+ */
+
+void _Message_queue_Core_message_queue_mp_support (
+ Thread_Control *the_thread,
+ Objects_Id id
+)
+{
+ the_thread->receive_packet->return_code = RTEMS_SUCCESSFUL;
+
+ _Message_queue_MP_Send_response_packet(
+ MESSAGE_QUEUE_MP_RECEIVE_RESPONSE,
+ id,
+ the_thread
+ );
+}
+
+/* end of file */
diff --git a/cpukit/rtems/src/msgqallocate.c b/cpukit/rtems/src/msgqallocate.c
new file mode 100644
index 0000000000..98024917ba
--- /dev/null
+++ b/cpukit/rtems/src/msgqallocate.c
@@ -0,0 +1,56 @@
+/*
+ * Message Queue Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/coremsg.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/attr.h>
+#include <rtems/rtems/message.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/support.h>
+
+/*PAGE
+ *
+ * _Message_queue_Allocate
+ *
+ * Allocate a message queue and the space for its messages
+ *
+ * Input parameters:
+ * the_message_queue - the message queue to allocate message buffers
+ * count - maximum message and reserved buffer count
+ * max_message_size - maximum size of each message
+ *
+ * Output parameters:
+ * the_message_queue - set if successful, NULL otherwise
+ */
+
+Message_queue_Control *_Message_queue_Allocate (
+ uint32_t count,
+ uint32_t max_message_size
+)
+{
+ return
+ (Message_queue_Control *)_Objects_Allocate(&_Message_queue_Information);
+
+}
diff --git a/cpukit/rtems/src/msgqbroadcast.c b/cpukit/rtems/src/msgqbroadcast.c
new file mode 100644
index 0000000000..f81523fa37
--- /dev/null
+++ b/cpukit/rtems/src/msgqbroadcast.c
@@ -0,0 +1,109 @@
+/*
+ * Message Queue Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/coremsg.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/attr.h>
+#include <rtems/rtems/message.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/support.h>
+
+/*PAGE
+ *
+ * rtems_message_queue_broadcast
+ *
+ * This directive sends a message for every thread waiting on the queue
+ * designated by id.
+ *
+ * Input parameters:
+ * id - pointer to message queue
+ * buffer - pointer to message buffer
+ * size - size of message to broadcast
+ * count - pointer to area to store number of threads made ready
+ *
+ * Output parameters:
+ * count - number of threads made ready
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_message_queue_broadcast(
+ Objects_Id id,
+ void *buffer,
+ uint32_t size,
+ uint32_t *count
+)
+{
+ register Message_queue_Control *the_message_queue;
+ Objects_Locations location;
+ CORE_message_queue_Status core_status;
+
+ if ( !buffer )
+ return RTEMS_INVALID_ADDRESS;
+
+ if ( !count )
+ return RTEMS_INVALID_ADDRESS;
+
+ the_message_queue = _Message_queue_Get( id, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE:
+#if defined(RTEMS_MULTIPROCESSING)
+ _Thread_Executing->Wait.return_argument = count;
+
+ return
+ _Message_queue_MP_Send_request_packet(
+ MESSAGE_QUEUE_MP_BROADCAST_REQUEST,
+ id,
+ buffer,
+ &size,
+ 0, /* option_set not used */
+ MPCI_DEFAULT_TIMEOUT
+ );
+#endif
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ core_status = _CORE_message_queue_Broadcast(
+ &the_message_queue->message_queue,
+ buffer,
+ size,
+ id,
+#if defined(RTEMS_MULTIPROCESSING)
+ _Message_queue_Core_message_queue_mp_support,
+#else
+ NULL,
+#endif
+ count
+ );
+
+ _Thread_Enable_dispatch();
+ return
+ _Message_queue_Translate_core_message_queue_return_code( core_status );
+
+ }
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/msgqcreate.c b/cpukit/rtems/src/msgqcreate.c
new file mode 100644
index 0000000000..a230afbf8b
--- /dev/null
+++ b/cpukit/rtems/src/msgqcreate.c
@@ -0,0 +1,161 @@
+/*
+ * Message Queue Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/coremsg.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/attr.h>
+#include <rtems/rtems/message.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/support.h>
+
+/*PAGE
+ *
+ * rtems_message_queue_create
+ *
+ * This directive creates a message queue by allocating and initializing
+ * a message queue data structure.
+ *
+ * Input parameters:
+ * name - user defined queue name
+ * count - maximum message and reserved buffer count
+ * max_message_size - maximum size of each message
+ * attribute_set - process method
+ * id - pointer to queue
+ *
+ * Output parameters:
+ * id - queue id
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_message_queue_create(
+ rtems_name name,
+ uint32_t count,
+ uint32_t max_message_size,
+ rtems_attribute attribute_set,
+ Objects_Id *id
+)
+{
+ register Message_queue_Control *the_message_queue;
+ CORE_message_queue_Attributes the_msgq_attributes;
+#if defined(RTEMS_MULTIPROCESSING)
+ boolean is_global;
+#endif
+
+ if ( !rtems_is_name_valid( name ) )
+ return RTEMS_INVALID_NAME;
+
+ if ( !id )
+ return RTEMS_INVALID_ADDRESS;
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( (is_global = _Attributes_Is_global( attribute_set ) ) &&
+ !_System_state_Is_multiprocessing )
+ return RTEMS_MP_NOT_CONFIGURED;
+#endif
+
+ if ( count == 0 )
+ return RTEMS_INVALID_NUMBER;
+
+ if ( max_message_size == 0 )
+ return RTEMS_INVALID_SIZE;
+
+#if defined(RTEMS_MULTIPROCESSING)
+#if 1
+ /*
+ * I am not 100% sure this should be an error.
+ * It seems reasonable to create a que with a large max size,
+ * and then just send smaller msgs from remote (or all) nodes.
+ */
+
+ if ( is_global && (_MPCI_table->maximum_packet_size < max_message_size) )
+ return RTEMS_INVALID_SIZE;
+#endif
+#endif
+
+ _Thread_Disable_dispatch(); /* protects object pointer */
+
+ the_message_queue = _Message_queue_Allocate( count, max_message_size );
+
+ if ( !the_message_queue ) {
+ _Thread_Enable_dispatch();
+ return RTEMS_TOO_MANY;
+ }
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( is_global &&
+ !( _Objects_MP_Allocate_and_open( &_Message_queue_Information,
+ name, the_message_queue->Object.id, FALSE ) ) ) {
+ _Message_queue_Free( the_message_queue );
+ _Thread_Enable_dispatch();
+ return RTEMS_TOO_MANY;
+ }
+#endif
+
+ the_message_queue->attribute_set = attribute_set;
+
+ if (_Attributes_Is_priority( attribute_set ) )
+ the_msgq_attributes.discipline = CORE_MESSAGE_QUEUE_DISCIPLINES_PRIORITY;
+ else
+ the_msgq_attributes.discipline = CORE_MESSAGE_QUEUE_DISCIPLINES_FIFO;
+
+ if ( ! _CORE_message_queue_Initialize(
+ &the_message_queue->message_queue,
+ &the_msgq_attributes,
+ count,
+ max_message_size
+ ) ) {
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( is_global )
+ _Objects_MP_Close(
+ &_Message_queue_Information, the_message_queue->Object.id);
+#endif
+
+ _Message_queue_Free( the_message_queue );
+ _Thread_Enable_dispatch();
+ return RTEMS_TOO_MANY;
+ }
+
+ _Objects_Open(
+ &_Message_queue_Information,
+ &the_message_queue->Object,
+ (Objects_Name) name
+ );
+
+ *id = the_message_queue->Object.id;
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( is_global )
+ _Message_queue_MP_Send_process_packet(
+ MESSAGE_QUEUE_MP_ANNOUNCE_CREATE,
+ the_message_queue->Object.id,
+ name,
+ 0
+ );
+#endif
+
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/rtems/src/msgqdelete.c b/cpukit/rtems/src/msgqdelete.c
new file mode 100644
index 0000000000..0d281f09c5
--- /dev/null
+++ b/cpukit/rtems/src/msgqdelete.c
@@ -0,0 +1,104 @@
+/*
+ * Message Queue Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/coremsg.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/attr.h>
+#include <rtems/rtems/message.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/support.h>
+
+/*PAGE
+ *
+ * rtems_message_queue_delete
+ *
+ * This directive allows a thread to delete the message queue specified
+ * by the given queue identifier.
+ *
+ * Input parameters:
+ * id - queue id
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_message_queue_delete(
+ Objects_Id id
+)
+{
+ register Message_queue_Control *the_message_queue;
+ Objects_Locations location;
+
+ the_message_queue = _Message_queue_Get( id, &location );
+ switch ( location ) {
+
+ case OBJECTS_REMOTE:
+#if defined(RTEMS_MULTIPROCESSING)
+ _Thread_Dispatch();
+ return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
+#endif
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ _Objects_Close( &_Message_queue_Information,
+ &the_message_queue->Object );
+
+ _CORE_message_queue_Close(
+ &the_message_queue->message_queue,
+#if defined(RTEMS_MULTIPROCESSING)
+ _Message_queue_MP_Send_object_was_deleted,
+#else
+ NULL,
+#endif
+ CORE_MESSAGE_QUEUE_STATUS_WAS_DELETED
+ );
+
+ _Message_queue_Free( the_message_queue );
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( _Attributes_Is_global( the_message_queue->attribute_set ) ) {
+ _Objects_MP_Close(
+ &_Message_queue_Information,
+ the_message_queue->Object.id
+ );
+
+ _Message_queue_MP_Send_process_packet(
+ MESSAGE_QUEUE_MP_ANNOUNCE_DELETE,
+ the_message_queue->Object.id,
+ 0, /* Not used */
+ 0
+ );
+ }
+#endif
+
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/msgqflush.c b/cpukit/rtems/src/msgqflush.c
new file mode 100644
index 0000000000..7eb47d9785
--- /dev/null
+++ b/cpukit/rtems/src/msgqflush.c
@@ -0,0 +1,89 @@
+/*
+ * Message Queue Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/coremsg.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/attr.h>
+#include <rtems/rtems/message.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/support.h>
+
+/*PAGE
+ *
+ * rtems_message_queue_flush
+ *
+ * This directive removes all pending messages from a queue and returns
+ * the number of messages removed. If no messages were present then
+ * a count of zero is returned.
+ *
+ * Input parameters:
+ * id - queue id
+ * count - return area for count
+ *
+ * Output parameters:
+ * count - number of messages removed ( 0 = empty queue )
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_message_queue_flush(
+ Objects_Id id,
+ uint32_t *count
+)
+{
+ register Message_queue_Control *the_message_queue;
+ Objects_Locations location;
+
+ if ( !count )
+ return RTEMS_INVALID_ADDRESS;
+
+ the_message_queue = _Message_queue_Get( id, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE:
+#if defined(RTEMS_MULTIPROCESSING)
+ _Thread_Executing->Wait.return_argument = count;
+
+ return
+ _Message_queue_MP_Send_request_packet(
+ MESSAGE_QUEUE_MP_FLUSH_REQUEST,
+ id,
+ 0, /* buffer not used */
+ 0, /* size */
+ 0, /* option_set not used */
+ MPCI_DEFAULT_TIMEOUT
+ );
+#endif
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ *count = _CORE_message_queue_Flush( &the_message_queue->message_queue );
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/msgqgetnumberpending.c b/cpukit/rtems/src/msgqgetnumberpending.c
new file mode 100644
index 0000000000..a386127ecb
--- /dev/null
+++ b/cpukit/rtems/src/msgqgetnumberpending.c
@@ -0,0 +1,86 @@
+/*
+ * Message Queue Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/coremsg.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/attr.h>
+#include <rtems/rtems/message.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/support.h>
+
+/*PAGE
+ *
+ * rtems_message_queue_get_number_pending
+ *
+ * This directive returns the number of messages pending.
+ *
+ * Input parameters:
+ * id - queue id
+ * count - return area for count
+ *
+ * Output parameters:
+ * count - number of messages removed ( 0 = empty queue )
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_message_queue_get_number_pending(
+ Objects_Id id,
+ uint32_t *count
+)
+{
+ register Message_queue_Control *the_message_queue;
+ Objects_Locations location;
+
+ if ( !count )
+ return RTEMS_INVALID_ADDRESS;
+
+ the_message_queue = _Message_queue_Get( id, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE:
+#if defined(RTEMS_MULTIPROCESSING)
+ _Thread_Executing->Wait.return_argument = count;
+
+ return _Message_queue_MP_Send_request_packet(
+ MESSAGE_QUEUE_MP_GET_NUMBER_PENDING_REQUEST,
+ id,
+ 0, /* buffer not used */
+ 0, /* size */
+ 0, /* option_set not used */
+ MPCI_DEFAULT_TIMEOUT
+ );
+#endif
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ *count = the_message_queue->message_queue.number_of_pending_messages;
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/msgqident.c b/cpukit/rtems/src/msgqident.c
new file mode 100644
index 0000000000..a3778d63ad
--- /dev/null
+++ b/cpukit/rtems/src/msgqident.c
@@ -0,0 +1,67 @@
+/*
+ * Message Queue Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/coremsg.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/attr.h>
+#include <rtems/rtems/message.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/support.h>
+
+/*PAGE
+ *
+ * rtems_message_queue_ident
+ *
+ * This directive returns the system ID associated with
+ * the message queue name.
+ *
+ * Input parameters:
+ * name - user defined message queue name
+ * node - node(s) to be searched
+ * id - pointer to message queue id
+ *
+ * Output parameters:
+ * *id - message queue id
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_message_queue_ident(
+ rtems_name name,
+ uint32_t node,
+ Objects_Id *id
+)
+{
+ Objects_Name_or_id_lookup_errors status;
+
+ status = _Objects_Name_to_id(
+ &_Message_queue_Information,
+ (Objects_Name) name,
+ node,
+ id
+ );
+
+ return _Status_Object_name_errors_to_status[ status ];
+}
diff --git a/cpukit/rtems/src/msgqreceive.c b/cpukit/rtems/src/msgqreceive.c
new file mode 100644
index 0000000000..19d82ae10e
--- /dev/null
+++ b/cpukit/rtems/src/msgqreceive.c
@@ -0,0 +1,110 @@
+/*
+ * Message Queue Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/coremsg.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/attr.h>
+#include <rtems/rtems/message.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/support.h>
+
+/*PAGE
+ *
+ * rtems_message_queue_receive
+ *
+ * This directive dequeues a message from the designated message queue
+ * and copies it into the requesting thread's buffer.
+ *
+ * Input parameters:
+ * id - queue id
+ * buffer - pointer to message buffer
+ * size - size of message receive
+ * option_set - options on receive
+ * timeout - number of ticks to wait
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_message_queue_receive(
+ Objects_Id id,
+ void *buffer,
+ uint32_t *size,
+ uint32_t option_set,
+ rtems_interval timeout
+)
+{
+ register Message_queue_Control *the_message_queue;
+ Objects_Locations location;
+ boolean wait;
+
+ if ( !buffer )
+ return RTEMS_INVALID_ADDRESS;
+
+ if ( !size )
+ return RTEMS_INVALID_ADDRESS;
+
+ the_message_queue = _Message_queue_Get( id, &location );
+ switch ( location ) {
+
+ case OBJECTS_REMOTE:
+#if defined(RTEMS_MULTIPROCESSING)
+ return _Message_queue_MP_Send_request_packet(
+ MESSAGE_QUEUE_MP_RECEIVE_REQUEST,
+ id,
+ buffer,
+ size,
+ option_set,
+ timeout
+ );
+#endif
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ if ( _Options_Is_no_wait( option_set ) )
+ wait = FALSE;
+ else
+ wait = TRUE;
+
+ _CORE_message_queue_Seize(
+ &the_message_queue->message_queue,
+ the_message_queue->Object.id,
+ buffer,
+ size,
+ wait,
+ timeout
+ );
+ _Thread_Enable_dispatch();
+ return _Message_queue_Translate_core_message_queue_return_code(
+ _Thread_Executing->Wait.return_code
+ );
+
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/msgqsend.c b/cpukit/rtems/src/msgqsend.c
new file mode 100644
index 0000000000..3be6bfa897
--- /dev/null
+++ b/cpukit/rtems/src/msgqsend.c
@@ -0,0 +1,57 @@
+/*
+ * Message Queue Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/coremsg.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/attr.h>
+#include <rtems/rtems/message.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/support.h>
+
+/*PAGE
+ *
+ * rtems_message_queue_send
+ *
+ * This routine implements the directives q_send. It sends a
+ * message to the specified message queue.
+ *
+ * Input parameters:
+ * id - pointer to message queue
+ * buffer - pointer to message buffer
+ * size - size of message to sent urgently
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_message_queue_send(
+ Objects_Id id,
+ void *buffer,
+ uint32_t size
+)
+{
+ return( _Message_queue_Submit(id, buffer, size, MESSAGE_QUEUE_SEND_REQUEST) );
+}
diff --git a/cpukit/rtems/src/msgqsubmit.c b/cpukit/rtems/src/msgqsubmit.c
new file mode 100644
index 0000000000..52d18261dc
--- /dev/null
+++ b/cpukit/rtems/src/msgqsubmit.c
@@ -0,0 +1,147 @@
+/*
+ * Message Queue Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/coremsg.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/attr.h>
+#include <rtems/rtems/message.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/support.h>
+
+/*PAGE
+ *
+ * _Message_queue_Submit
+ *
+ * This routine implements the directives rtems_message_queue_send
+ * and rtems_message_queue_urgent. It processes a message that is
+ * to be submitted to the designated message queue. The message will
+ * either be processed as a send send message which it will be inserted
+ * at the rear of the queue or it will be processed as an urgent message
+ * which will be inserted at the front of the queue.
+ *
+ * Input parameters:
+ * id - pointer to message queue
+ * buffer - pointer to message buffer
+ * size - size in bytes of message to send
+ * submit_type - send or urgent message
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+#if defined(RTEMS_MULTIPROCESSING)
+#define MESSAGE_QUEUE_MP_HANDLER _Message_queue_Core_message_queue_mp_support
+#else
+#define MESSAGE_QUEUE_MP_HANDLER NULL
+#endif
+
+rtems_status_code _Message_queue_Submit(
+ Objects_Id id,
+ void *buffer,
+ uint32_t size,
+ Message_queue_Submit_types submit_type
+)
+{
+ register Message_queue_Control *the_message_queue;
+ Objects_Locations location;
+ CORE_message_queue_Status msg_status;
+
+ if ( !buffer )
+ return RTEMS_INVALID_ADDRESS;
+
+ the_message_queue = _Message_queue_Get( id, &location );
+ switch ( location )
+ {
+ case OBJECTS_REMOTE:
+#if defined(RTEMS_MULTIPROCESSING)
+ switch ( submit_type ) {
+ case MESSAGE_QUEUE_SEND_REQUEST:
+ return _Message_queue_MP_Send_request_packet(
+ MESSAGE_QUEUE_MP_SEND_REQUEST,
+ id,
+ buffer,
+ &size,
+ 0, /* option_set */
+ MPCI_DEFAULT_TIMEOUT
+ );
+
+ case MESSAGE_QUEUE_URGENT_REQUEST:
+ return _Message_queue_MP_Send_request_packet(
+ MESSAGE_QUEUE_MP_URGENT_REQUEST,
+ id,
+ buffer,
+ &size,
+ 0, /* option_set */
+ MPCI_DEFAULT_TIMEOUT
+ );
+ }
+ break;
+#endif
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ switch ( submit_type ) {
+ case MESSAGE_QUEUE_SEND_REQUEST:
+ msg_status = _CORE_message_queue_Send(
+ &the_message_queue->message_queue,
+ buffer,
+ size,
+ id,
+ MESSAGE_QUEUE_MP_HANDLER,
+ FALSE, /* sender does not block */
+ 0 /* no timeout */
+ );
+ break;
+ case MESSAGE_QUEUE_URGENT_REQUEST:
+ msg_status = _CORE_message_queue_Urgent(
+ &the_message_queue->message_queue,
+ buffer,
+ size,
+ id,
+ MESSAGE_QUEUE_MP_HANDLER,
+ FALSE, /* sender does not block */
+ 0 /* no timeout */
+ );
+ break;
+ default:
+ return RTEMS_INTERNAL_ERROR; /* should never get here */
+ }
+
+ _Thread_Enable_dispatch();
+
+ /*
+ * Since this API does not allow for blocking sends, we can directly
+ * return the returned msg_status.
+ */
+
+ return
+ _Message_queue_Translate_core_message_queue_return_code( msg_status );
+
+ }
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/msgqtranslatereturncode.c b/cpukit/rtems/src/msgqtranslatereturncode.c
new file mode 100644
index 0000000000..69dd3995ed
--- /dev/null
+++ b/cpukit/rtems/src/msgqtranslatereturncode.c
@@ -0,0 +1,68 @@
+/*
+ * Message Queue Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/coremsg.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/attr.h>
+#include <rtems/rtems/message.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/support.h>
+
+/*PAGE
+ *
+ * _Message_queue_Translate_core_message_queue_return_code
+ *
+ * Input parameters:
+ * the_message_queue_status - message_queue status code to translate
+ *
+ * Output parameters:
+ * rtems status code - translated RTEMS status code
+ *
+ */
+
+rtems_status_code _Message_queue_Translate_core_return_code_[] = {
+ RTEMS_SUCCESSFUL, /* CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL */
+ RTEMS_INVALID_SIZE, /* CORE_MESSAGE_QUEUE_STATUS_INVALID_SIZE */
+ RTEMS_TOO_MANY, /* CORE_MESSAGE_QUEUE_STATUS_TOO_MANY */
+ RTEMS_UNSATISFIED, /* CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED */
+ RTEMS_UNSATISFIED, /* CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_NOWAIT */
+ RTEMS_OBJECT_WAS_DELETED, /* CORE_MESSAGE_QUEUE_STATUS_WAS_DELETED */
+ RTEMS_TIMEOUT /* CORE_MESSAGE_QUEUE_STATUS_TIMEOUT */
+};
+
+rtems_status_code _Message_queue_Translate_core_message_queue_return_code (
+ uint32_t status
+)
+{
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( status == THREAD_STATUS_PROXY_BLOCKING )
+ return RTEMS_PROXY_BLOCKING;
+ else
+#endif
+ if ( status > CORE_MESSAGE_QUEUE_STATUS_TIMEOUT )
+ return RTEMS_INTERNAL_ERROR;
+ else
+ return _Message_queue_Translate_core_return_code_[status];
+}
diff --git a/cpukit/rtems/src/msgqurgent.c b/cpukit/rtems/src/msgqurgent.c
new file mode 100644
index 0000000000..71c9ce563a
--- /dev/null
+++ b/cpukit/rtems/src/msgqurgent.c
@@ -0,0 +1,57 @@
+/*
+ * Message Queue Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/coremsg.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/attr.h>
+#include <rtems/rtems/message.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/support.h>
+
+/*PAGE
+ *
+ * rtems_message_queue_urgent
+ *
+ * This routine implements the directives q_urgent. It urgents a
+ * message to the specified message queue.
+ *
+ * Input parameters:
+ * id - pointer to message queue
+ * buffer - pointer to message buffer
+ * size - size of message to sent urgently
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_message_queue_urgent(
+ Objects_Id id,
+ void *buffer,
+ uint32_t size
+)
+{
+ return(_Message_queue_Submit(id, buffer, size, MESSAGE_QUEUE_URGENT_REQUEST));
+}
diff --git a/cpukit/rtems/src/part.c b/cpukit/rtems/src/part.c
new file mode 100644
index 0000000000..b8c38b8cc7
--- /dev/null
+++ b/cpukit/rtems/src/part.c
@@ -0,0 +1,67 @@
+/*
+ * Partition Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/address.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/part.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/sysstate.h>
+
+/*PAGE
+ *
+ * _Partition_Manager_initialization
+ *
+ * This routine initializes all partition manager related
+ * data structures.
+ *
+ * Input parameters:
+ * maximum_partitions - number of partitions to initialize
+ *
+ * Output parameters: NONE
+ */
+
+void _Partition_Manager_initialization(
+ uint32_t maximum_partitions
+)
+{
+ _Objects_Initialize_information(
+ &_Partition_Information, /* object information table */
+ OBJECTS_CLASSIC_API, /* object API */
+ OBJECTS_RTEMS_PARTITIONS, /* object class */
+ maximum_partitions, /* maximum objects of this class */
+ sizeof( Partition_Control ), /* size of this object's control block */
+ FALSE, /* TRUE if the name is a string */
+ RTEMS_MAXIMUM_NAME_LENGTH /* maximum length of an object name */
+#if defined(RTEMS_MULTIPROCESSING)
+ ,
+ TRUE, /* TRUE if this is a global object class */
+ _Partition_MP_Send_extract_proxy /* Proxy extraction support callout */
+#endif
+ );
+
+ /*
+ * Register the MP Process Packet routine.
+ */
+
+#if defined(RTEMS_MULTIPROCESSING)
+ _MPCI_Register_packet_processor(
+ MP_PACKET_PARTITION,
+ _Partition_MP_Process_packet
+ );
+#endif
+
+}
diff --git a/cpukit/rtems/src/partcreate.c b/cpukit/rtems/src/partcreate.c
new file mode 100644
index 0000000000..d6baa166e7
--- /dev/null
+++ b/cpukit/rtems/src/partcreate.c
@@ -0,0 +1,125 @@
+/*
+ * Partition Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/address.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/part.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/sysstate.h>
+
+/*PAGE
+ *
+ * rtems_partition_create
+ *
+ * This directive creates a partiton of fixed sized buffers from the
+ * given contiguous memory area.
+ *
+ * Input parameters:
+ * name - user defined partition name
+ * starting_address - physical start address of partition
+ * length - physical length in bytes
+ * buffer_size - size of buffers in bytes
+ * attribute_set - partition attributes
+ * id - pointer to partition id
+ *
+ * Output parameters:
+ * id - partition id
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_partition_create(
+ rtems_name name,
+ void *starting_address,
+ uint32_t length,
+ uint32_t buffer_size,
+ rtems_attribute attribute_set,
+ Objects_Id *id
+)
+{
+ register Partition_Control *the_partition;
+
+ if ( !rtems_is_name_valid( name ) )
+ return RTEMS_INVALID_NAME;
+
+ if ( !starting_address )
+ return RTEMS_INVALID_ADDRESS;
+
+ if ( !id )
+ return RTEMS_INVALID_ADDRESS;
+
+ if ( length == 0 || buffer_size == 0 || length < buffer_size ||
+ !_Partition_Is_buffer_size_aligned( buffer_size ) )
+ return RTEMS_INVALID_SIZE;
+
+ if ( !_Addresses_Is_aligned( starting_address ) )
+ return RTEMS_INVALID_ADDRESS;
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( _Attributes_Is_global( attribute_set ) &&
+ !_System_state_Is_multiprocessing )
+ return RTEMS_MP_NOT_CONFIGURED;
+#endif
+
+ _Thread_Disable_dispatch(); /* prevents deletion */
+
+ the_partition = _Partition_Allocate();
+
+ if ( !the_partition ) {
+ _Thread_Enable_dispatch();
+ return RTEMS_TOO_MANY;
+ }
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( _Attributes_Is_global( attribute_set ) &&
+ !( _Objects_MP_Allocate_and_open( &_Partition_Information, name,
+ the_partition->Object.id, FALSE ) ) ) {
+ _Partition_Free( the_partition );
+ _Thread_Enable_dispatch();
+ return RTEMS_TOO_MANY;
+ }
+#endif
+
+ the_partition->starting_address = starting_address;
+ the_partition->length = length;
+ the_partition->buffer_size = buffer_size;
+ the_partition->attribute_set = attribute_set;
+ the_partition->number_of_used_blocks = 0;
+
+ _Chain_Initialize( &the_partition->Memory, starting_address,
+ length / buffer_size, buffer_size );
+
+ _Objects_Open(
+ &_Partition_Information,
+ &the_partition->Object,
+ (Objects_Name) name
+ );
+
+ *id = the_partition->Object.id;
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( _Attributes_Is_global( attribute_set ) )
+ _Partition_MP_Send_process_packet(
+ PARTITION_MP_ANNOUNCE_CREATE,
+ the_partition->Object.id,
+ name,
+ 0 /* Not used */
+ );
+#endif
+
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/rtems/src/partdelete.c b/cpukit/rtems/src/partdelete.c
new file mode 100644
index 0000000000..16b3b4cdd7
--- /dev/null
+++ b/cpukit/rtems/src/partdelete.c
@@ -0,0 +1,87 @@
+/*
+ * Partition Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/address.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/part.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/sysstate.h>
+
+/*PAGE
+ *
+ * rtems_partition_delete
+ *
+ * This directive allows a thread to delete a partition specified by
+ * the partition identifier, provided that none of its buffers are
+ * still allocated.
+ *
+ * Input parameters:
+ * id - partition id
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_partition_delete(
+ Objects_Id id
+)
+{
+ register Partition_Control *the_partition;
+ Objects_Locations location;
+
+ the_partition = _Partition_Get( id, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE:
+#if defined(RTEMS_MULTIPROCESSING)
+ _Thread_Dispatch();
+ return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
+#endif
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ if ( the_partition->number_of_used_blocks == 0 ) {
+ _Objects_Close( &_Partition_Information, &the_partition->Object );
+ _Partition_Free( the_partition );
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( _Attributes_Is_global( the_partition->attribute_set ) ) {
+
+ _Objects_MP_Close(
+ &_Partition_Information,
+ the_partition->Object.id
+ );
+
+ _Partition_MP_Send_process_packet(
+ PARTITION_MP_ANNOUNCE_DELETE,
+ the_partition->Object.id,
+ 0, /* Not used */
+ 0 /* Not used */
+ );
+ }
+#endif
+
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+ _Thread_Enable_dispatch();
+ return RTEMS_RESOURCE_IN_USE;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/partgetbuffer.c b/cpukit/rtems/src/partgetbuffer.c
new file mode 100644
index 0000000000..6870d66ca7
--- /dev/null
+++ b/cpukit/rtems/src/partgetbuffer.c
@@ -0,0 +1,82 @@
+/*
+ * Partition Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/address.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/part.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/sysstate.h>
+
+/*PAGE
+ *
+ * rtems_partition_get_buffer
+ *
+ * This directive will obtain a buffer from a buffer partition.
+ *
+ * Input parameters:
+ * id - partition id
+ * buffer - pointer to buffer address
+ *
+ * Output parameters:
+ * buffer - pointer to buffer address filled in
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_partition_get_buffer(
+ Objects_Id id,
+ void **buffer
+)
+{
+ register Partition_Control *the_partition;
+ Objects_Locations location;
+ void *the_buffer;
+
+ if ( !buffer )
+ return RTEMS_INVALID_ADDRESS;
+
+ the_partition = _Partition_Get( id, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE:
+#if defined(RTEMS_MULTIPROCESSING)
+ _Thread_Executing->Wait.return_argument = buffer;
+ return(
+ _Partition_MP_Send_request_packet(
+ PARTITION_MP_GET_BUFFER_REQUEST,
+ id,
+ 0 /* Not used */
+ )
+ );
+#endif
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ the_buffer = _Partition_Allocate_buffer( the_partition );
+ if ( the_buffer ) {
+ the_partition->number_of_used_blocks += 1;
+ _Thread_Enable_dispatch();
+ *buffer = the_buffer;
+ return RTEMS_SUCCESSFUL;
+ }
+ _Thread_Enable_dispatch();
+ return RTEMS_UNSATISFIED;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/partident.c b/cpukit/rtems/src/partident.c
new file mode 100644
index 0000000000..9ad7fee2b5
--- /dev/null
+++ b/cpukit/rtems/src/partident.c
@@ -0,0 +1,58 @@
+/*
+ * Partition Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/address.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/part.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/sysstate.h>
+
+/*PAGE
+ *
+ * rtems_partition_ident
+ *
+ * This directive returns the system ID associated with
+ * the partition name.
+ *
+ * Input parameters:
+ * name - user defined partition name
+ * node - node(s) to be searched
+ * id - pointer to partition id
+ *
+ * Output parameters:
+ * *id - partition id
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_partition_ident(
+ rtems_name name,
+ uint32_t node,
+ Objects_Id *id
+)
+{
+ Objects_Name_or_id_lookup_errors status;
+
+ status = _Objects_Name_to_id(
+ &_Partition_Information,
+ (Objects_Name) name,
+ node,
+ id
+ );
+
+ return _Status_Object_name_errors_to_status[ status ];
+}
diff --git a/cpukit/rtems/src/partmp.c b/cpukit/rtems/src/partmp.c
new file mode 100644
index 0000000000..01275d7d59
--- /dev/null
+++ b/cpukit/rtems/src/partmp.c
@@ -0,0 +1,303 @@
+/*
+ * Multiprocessing Support for the Partition Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/score/mpci.h>
+#include <rtems/score/mppkt.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/part.h>
+#include <rtems/score/thread.h>
+#include <rtems/rtems/support.h>
+
+/*PAGE
+ *
+ * _Partition_MP_Send_process_packet
+ *
+ */
+
+void _Partition_MP_Send_process_packet (
+ Partition_MP_Remote_operations operation,
+ Objects_Id partition_id,
+ rtems_name name,
+ Objects_Id proxy_id
+)
+{
+ Partition_MP_Packet *the_packet;
+ uint32_t node;
+
+ switch ( operation ) {
+
+ case PARTITION_MP_ANNOUNCE_CREATE:
+ case PARTITION_MP_ANNOUNCE_DELETE:
+ case PARTITION_MP_EXTRACT_PROXY:
+
+ the_packet = _Partition_MP_Get_packet();
+ the_packet->Prefix.the_class = MP_PACKET_PARTITION;
+ the_packet->Prefix.length = sizeof ( Partition_MP_Packet );
+ the_packet->Prefix.to_convert = sizeof ( Partition_MP_Packet );
+ the_packet->operation = operation;
+ the_packet->Prefix.id = partition_id;
+ the_packet->name = name;
+ the_packet->proxy_id = proxy_id;
+
+ if ( operation == PARTITION_MP_EXTRACT_PROXY )
+ node = rtems_get_node( partition_id );
+ else
+ node = MPCI_ALL_NODES;
+
+ _MPCI_Send_process_packet( node, &the_packet->Prefix );
+ break;
+
+ case PARTITION_MP_GET_BUFFER_REQUEST:
+ case PARTITION_MP_GET_BUFFER_RESPONSE:
+ case PARTITION_MP_RETURN_BUFFER_REQUEST:
+ case PARTITION_MP_RETURN_BUFFER_RESPONSE:
+ break;
+ }
+}
+
+/*PAGE
+ *
+ * _Partition_MP_Send_request_packet
+ *
+ */
+
+rtems_status_code _Partition_MP_Send_request_packet (
+ Partition_MP_Remote_operations operation,
+ Objects_Id partition_id,
+ void *buffer
+)
+{
+ Partition_MP_Packet *the_packet;
+
+ switch ( operation ) {
+
+ case PARTITION_MP_GET_BUFFER_REQUEST:
+ case PARTITION_MP_RETURN_BUFFER_REQUEST:
+
+ the_packet = _Partition_MP_Get_packet();
+ the_packet->Prefix.the_class = MP_PACKET_PARTITION;
+ the_packet->Prefix.length = sizeof ( Partition_MP_Packet );
+ the_packet->Prefix.to_convert = sizeof ( Partition_MP_Packet );
+ the_packet->operation = operation;
+ the_packet->Prefix.id = partition_id;
+ the_packet->buffer = buffer;
+
+ return
+ _MPCI_Send_request_packet(
+ rtems_get_node( partition_id ),
+ &the_packet->Prefix,
+ STATES_READY /* Not used */
+ );
+
+ break;
+
+ case PARTITION_MP_ANNOUNCE_CREATE:
+ case PARTITION_MP_ANNOUNCE_DELETE:
+ case PARTITION_MP_EXTRACT_PROXY:
+ case PARTITION_MP_GET_BUFFER_RESPONSE:
+ case PARTITION_MP_RETURN_BUFFER_RESPONSE:
+ break;
+
+ }
+ /*
+ * The following line is included to satisfy compilers which
+ * produce warnings when a function does not end with a return.
+ */
+ return RTEMS_SUCCESSFUL;
+}
+
+/*PAGE
+ *
+ * _Partition_MP_Send_response_packet
+ *
+ */
+
+void _Partition_MP_Send_response_packet (
+ Partition_MP_Remote_operations operation,
+ Objects_Id partition_id,
+ Thread_Control *the_thread
+)
+{
+ Partition_MP_Packet *the_packet;
+
+ switch ( operation ) {
+
+ case PARTITION_MP_GET_BUFFER_RESPONSE:
+ case PARTITION_MP_RETURN_BUFFER_RESPONSE:
+
+ the_packet = ( Partition_MP_Packet *) the_thread->receive_packet;
+
+/*
+ * The packet being returned already contains the class, length, and
+ * to_convert fields, therefore they are not set in this routine.
+ */
+ the_packet->operation = operation;
+ the_packet->Prefix.id = the_packet->Prefix.source_tid;
+
+ _MPCI_Send_response_packet(
+ rtems_get_node( the_packet->Prefix.source_tid ),
+ &the_packet->Prefix
+ );
+ break;
+
+ case PARTITION_MP_ANNOUNCE_CREATE:
+ case PARTITION_MP_ANNOUNCE_DELETE:
+ case PARTITION_MP_EXTRACT_PROXY:
+ case PARTITION_MP_GET_BUFFER_REQUEST:
+ case PARTITION_MP_RETURN_BUFFER_REQUEST:
+ break;
+
+ }
+}
+
+/*PAGE
+ *
+ *
+ * _Partition_MP_Process_packet
+ *
+ */
+
+void _Partition_MP_Process_packet (
+ rtems_packet_prefix *the_packet_prefix
+)
+{
+ Partition_MP_Packet *the_packet;
+ Thread_Control *the_thread;
+ boolean ignored;
+
+ the_packet = (Partition_MP_Packet *) the_packet_prefix;
+
+ switch ( the_packet->operation ) {
+
+ case PARTITION_MP_ANNOUNCE_CREATE:
+
+ ignored = _Objects_MP_Allocate_and_open(
+ &_Partition_Information,
+ the_packet->name,
+ the_packet->Prefix.id,
+ TRUE
+ );
+
+ _MPCI_Return_packet( the_packet_prefix );
+ break;
+
+ case PARTITION_MP_ANNOUNCE_DELETE:
+
+ _Objects_MP_Close( &_Partition_Information, the_packet->Prefix.id );
+
+ _MPCI_Return_packet( the_packet_prefix );
+ break;
+
+ case PARTITION_MP_EXTRACT_PROXY:
+
+ the_thread = _Thread_MP_Find_proxy( the_packet->proxy_id );
+
+ if ( ! _Thread_Is_null( the_thread ) )
+ _Thread_queue_Extract( the_thread->Wait.queue, the_thread );
+
+ _MPCI_Return_packet( the_packet_prefix );
+ break;
+
+ case PARTITION_MP_GET_BUFFER_REQUEST:
+
+ the_packet->Prefix.return_code = rtems_partition_get_buffer(
+ the_packet->Prefix.id,
+ &the_packet->buffer
+ );
+
+ _Partition_MP_Send_response_packet(
+ PARTITION_MP_GET_BUFFER_RESPONSE,
+ the_packet->Prefix.id,
+ _Thread_Executing
+ );
+ break;
+
+ case PARTITION_MP_GET_BUFFER_RESPONSE:
+
+ the_thread = _MPCI_Process_response( the_packet_prefix );
+
+ *(void **)the_thread->Wait.return_argument = the_packet->buffer;
+
+ _MPCI_Return_packet( the_packet_prefix );
+ break;
+
+ case PARTITION_MP_RETURN_BUFFER_REQUEST:
+
+ the_packet->Prefix.return_code = rtems_partition_return_buffer(
+ the_packet->Prefix.id,
+ the_packet->buffer
+ );
+
+ _Partition_MP_Send_response_packet(
+ PARTITION_MP_RETURN_BUFFER_RESPONSE,
+ the_packet->Prefix.id,
+ _Thread_Executing
+ );
+ break;
+
+ case PARTITION_MP_RETURN_BUFFER_RESPONSE:
+
+ the_thread = _MPCI_Process_response( the_packet_prefix );
+
+ _MPCI_Return_packet( the_packet_prefix );
+ break;
+
+ }
+}
+
+/*PAGE
+ *
+ * _Partition_MP_Send_object_was_deleted
+ *
+ * This routine is not needed by the Partition since a partition
+ * cannot be deleted when buffers are in use.
+ *
+ */
+
+/*PAGE
+ *
+ * _Partition_MP_Send_extract_proxy
+ *
+ */
+
+void _Partition_MP_Send_extract_proxy (
+ void *argument
+)
+{
+ Thread_Control *the_thread = (Thread_Control *)argument;
+
+ _Partition_MP_Send_process_packet(
+ PARTITION_MP_EXTRACT_PROXY,
+ the_thread->Wait.id,
+ (rtems_name) 0,
+ the_thread->Object.id
+ );
+
+}
+
+/*PAGE
+ *
+ * _Partition_MP_Get_packet
+ *
+ */
+
+Partition_MP_Packet *_Partition_MP_Get_packet ( void )
+{
+ return ( (Partition_MP_Packet *) _MPCI_Get_packet() );
+}
+
+/* end of file */
diff --git a/cpukit/rtems/src/partreturnbuffer.c b/cpukit/rtems/src/partreturnbuffer.c
new file mode 100644
index 0000000000..344413aba9
--- /dev/null
+++ b/cpukit/rtems/src/partreturnbuffer.c
@@ -0,0 +1,75 @@
+/*
+ * Partition Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/address.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/part.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/sysstate.h>
+
+/*PAGE
+ *
+ * rtems_partition_return_buffer
+ *
+ * This directive will return the given buffer to the specified
+ * buffer partition.
+ *
+ * Input parameters:
+ * id - partition id
+ * buffer - pointer to buffer address
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_partition_return_buffer(
+ Objects_Id id,
+ void *buffer
+)
+{
+ register Partition_Control *the_partition;
+ Objects_Locations location;
+
+ the_partition = _Partition_Get( id, &location );
+ switch ( location ) {
+
+ case OBJECTS_REMOTE:
+#if defined(RTEMS_MULTIPROCESSING)
+ return _Partition_MP_Send_request_packet(
+ PARTITION_MP_RETURN_BUFFER_REQUEST,
+ id,
+ buffer
+ );
+#endif
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ if ( _Partition_Is_buffer_valid( buffer, the_partition ) ) {
+ _Partition_Free_buffer( the_partition, buffer );
+ the_partition->number_of_used_blocks -= 1;
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+ _Thread_Enable_dispatch();
+ return RTEMS_INVALID_ADDRESS;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/ratemon.c b/cpukit/rtems/src/ratemon.c
new file mode 100644
index 0000000000..f3b648e29c
--- /dev/null
+++ b/cpukit/rtems/src/ratemon.c
@@ -0,0 +1,57 @@
+/*
+ * Rate Monotonic Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/ratemon.h>
+#include <rtems/score/thread.h>
+
+/*PAGE
+ *
+ * _Rate_monotonic_Manager_initialization
+ *
+ * This routine initializes all Rate Monotonic Manager related
+ * data structures.
+ *
+ * Input parameters:
+ * maximum_periods - number of periods timers to initialize
+ *
+ * Output parameters: NONE
+ *
+ * NOTE: The Rate Monotonic Manager is built on top of the Watchdog
+ * Handler.
+ */
+
+void _Rate_monotonic_Manager_initialization(
+ uint32_t maximum_periods
+)
+{
+ _Objects_Initialize_information(
+ &_Rate_monotonic_Information, /* object information table */
+ OBJECTS_CLASSIC_API, /* object API */
+ OBJECTS_RTEMS_PERIODS, /* object class */
+ maximum_periods, /* maximum objects of this class */
+ sizeof( Rate_monotonic_Control ), /* size of this object's control block */
+ FALSE, /* TRUE if the name is a string */
+ RTEMS_MAXIMUM_NAME_LENGTH /* maximum length of an object name */
+#if defined(RTEMS_MULTIPROCESSING)
+ ,
+ FALSE, /* TRUE if this is a global object class */
+ NULL /* Proxy extraction support callout */
+#endif
+ );
+}
diff --git a/cpukit/rtems/src/ratemoncancel.c b/cpukit/rtems/src/ratemoncancel.c
new file mode 100644
index 0000000000..645ec510f2
--- /dev/null
+++ b/cpukit/rtems/src/ratemoncancel.c
@@ -0,0 +1,64 @@
+/*
+ * Rate Monotonic Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/ratemon.h>
+#include <rtems/score/thread.h>
+
+/*PAGE
+ *
+ * rtems_rate_monotonic_cancel
+ *
+ * This directive allows a thread to cancel a rate monotonic timer.
+ *
+ * Input parameters:
+ * id - rate monotonic id
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful and caller is not the owning thread
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_rate_monotonic_cancel(
+ Objects_Id id
+)
+{
+ Rate_monotonic_Control *the_period;
+ Objects_Locations location;
+
+ the_period = _Rate_monotonic_Get( id, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE:
+ return RTEMS_INTERNAL_ERROR; /* should never return this */
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ if ( !_Thread_Is_executing( the_period->owner ) ) {
+ _Thread_Enable_dispatch();
+ return RTEMS_NOT_OWNER_OF_RESOURCE;
+ }
+ (void) _Watchdog_Remove( &the_period->Timer );
+ the_period->state = RATE_MONOTONIC_INACTIVE;
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/ratemoncreate.c b/cpukit/rtems/src/ratemoncreate.c
new file mode 100644
index 0000000000..27d397e9ca
--- /dev/null
+++ b/cpukit/rtems/src/ratemoncreate.c
@@ -0,0 +1,74 @@
+/*
+ * Rate Monotonic Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/ratemon.h>
+#include <rtems/score/thread.h>
+
+/*PAGE
+ *
+ * rtems_rate_monotonic_create
+ *
+ * This directive creates a rate monotonic timer and performs
+ * some initialization.
+ *
+ * Input parameters:
+ * name - name of period
+ * id - pointer to rate monotonic id
+ *
+ * Output parameters:
+ * id - rate monotonic id
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_rate_monotonic_create(
+ rtems_name name,
+ Objects_Id *id
+)
+{
+ Rate_monotonic_Control *the_period;
+
+ if ( !rtems_is_name_valid( name ) )
+ return RTEMS_INVALID_NAME;
+
+ if ( !id )
+ return RTEMS_INVALID_ADDRESS;
+
+ _Thread_Disable_dispatch(); /* to prevent deletion */
+
+ the_period = _Rate_monotonic_Allocate();
+
+ if ( !the_period ) {
+ _Thread_Enable_dispatch();
+ return RTEMS_TOO_MANY;
+ }
+
+ the_period->owner = _Thread_Executing;
+ the_period->state = RATE_MONOTONIC_INACTIVE;
+
+ _Objects_Open(
+ &_Rate_monotonic_Information,
+ &the_period->Object,
+ (Objects_Name) name
+ );
+
+ *id = the_period->Object.id;
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/rtems/src/ratemondelete.c b/cpukit/rtems/src/ratemondelete.c
new file mode 100644
index 0000000000..c465c0dc51
--- /dev/null
+++ b/cpukit/rtems/src/ratemondelete.c
@@ -0,0 +1,62 @@
+/*
+ * Rate Monotonic Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/ratemon.h>
+#include <rtems/score/thread.h>
+
+/*PAGE
+ *
+ * rtems_rate_monotonic_delete
+ *
+ * This directive allows a thread to delete a rate monotonic timer.
+ *
+ * Input parameters:
+ * id - rate monotonic id
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_rate_monotonic_delete(
+ Objects_Id id
+)
+{
+ Rate_monotonic_Control *the_period;
+ Objects_Locations location;
+
+ the_period = _Rate_monotonic_Get( id, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE: /* should never return this */
+ return RTEMS_INTERNAL_ERROR;
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ _Objects_Close( &_Rate_monotonic_Information, &the_period->Object );
+ (void) _Watchdog_Remove( &the_period->Timer );
+ the_period->state = RATE_MONOTONIC_INACTIVE;
+ _Rate_monotonic_Free( the_period );
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/ratemongetstatus.c b/cpukit/rtems/src/ratemongetstatus.c
new file mode 100644
index 0000000000..2ae8732c4d
--- /dev/null
+++ b/cpukit/rtems/src/ratemongetstatus.c
@@ -0,0 +1,79 @@
+/*
+ * Rate Monotonic Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/ratemon.h>
+#include <rtems/score/thread.h>
+
+/*PAGE
+ *
+ * rtems_rate_monotonic_get_status
+ *
+ * This directive allows a thread to obtain status information on a
+ * period.
+ *
+ * Input parameters:
+ * id - rate monotonic id
+ * status - pointer to status control block
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ *
+ */
+
+rtems_status_code rtems_rate_monotonic_get_status(
+ Objects_Id id,
+ rtems_rate_monotonic_period_status *status
+)
+{
+ Objects_Locations location;
+ Rate_monotonic_Control *the_period;
+
+ if ( !status )
+ return RTEMS_INVALID_ADDRESS;
+
+ the_period = _Rate_monotonic_Get( id, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE: /* should never return this */
+ return RTEMS_INTERNAL_ERROR;
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ status->state = the_period->state;
+
+ if ( status->state == RATE_MONOTONIC_INACTIVE ) {
+ status->ticks_since_last_period = 0;
+ status->ticks_executed_since_last_period = 0;
+ } else {
+ status->ticks_since_last_period =
+ _Watchdog_Ticks_since_boot - the_period->time_at_period;
+
+ status->ticks_executed_since_last_period =
+ the_period->owner->ticks_executed -
+ the_period->owner_ticks_executed_at_period;
+ }
+
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/ratemonident.c b/cpukit/rtems/src/ratemonident.c
new file mode 100644
index 0000000000..442bfbf685
--- /dev/null
+++ b/cpukit/rtems/src/ratemonident.c
@@ -0,0 +1,55 @@
+/*
+ * Rate Monotonic Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/ratemon.h>
+#include <rtems/score/thread.h>
+
+/*PAGE
+ *
+ * rtems_rate_monotonic_ident
+ *
+ * This directive returns the system ID associated with
+ * the rate monotonic period name.
+ *
+ * Input parameters:
+ * name - user defined period name
+ * id - pointer to period id
+ *
+ * Output parameters:
+ * *id - region id
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_rate_monotonic_ident(
+ rtems_name name,
+ Objects_Id *id
+)
+{
+ Objects_Name_or_id_lookup_errors status;
+
+ status = _Objects_Name_to_id(
+ &_Rate_monotonic_Information,
+ (Objects_Name) name,
+ OBJECTS_SEARCH_LOCAL_NODE,
+ id
+ );
+
+ return _Status_Object_name_errors_to_status[ status ];
+}
diff --git a/cpukit/rtems/src/ratemonperiod.c b/cpukit/rtems/src/ratemonperiod.c
new file mode 100644
index 0000000000..1e5c8fb7f6
--- /dev/null
+++ b/cpukit/rtems/src/ratemonperiod.c
@@ -0,0 +1,163 @@
+/*
+ * Rate Monotonic Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/ratemon.h>
+#include <rtems/score/thread.h>
+
+/*PAGE
+ *
+ * rtems_rate_monotonic_period
+ *
+ * This directive allows a thread to manipulate a rate monotonic timer.
+ *
+ * Input parameters:
+ * id - rate monotonic id
+ * length - length of period (in ticks)
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_rate_monotonic_period(
+ Objects_Id id,
+ rtems_interval length
+)
+{
+ Rate_monotonic_Control *the_period;
+ Objects_Locations location;
+ rtems_status_code return_value;
+ rtems_rate_monotonic_period_states local_state;
+ ISR_Level level;
+
+ the_period = _Rate_monotonic_Get( id, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE: /* should never return this */
+ return RTEMS_INTERNAL_ERROR;
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ if ( !_Thread_Is_executing( the_period->owner ) ) {
+ _Thread_Enable_dispatch();
+ return RTEMS_NOT_OWNER_OF_RESOURCE;
+ }
+
+ if ( length == RTEMS_PERIOD_STATUS ) {
+ switch ( the_period->state ) {
+ case RATE_MONOTONIC_INACTIVE:
+ return_value = RTEMS_NOT_DEFINED;
+ break;
+ case RATE_MONOTONIC_ACTIVE:
+ return_value = RTEMS_SUCCESSFUL;
+ break;
+ case RATE_MONOTONIC_EXPIRED:
+ return_value = RTEMS_TIMEOUT;
+ break;
+ default: /* unreached -- only to remove warnings */
+ return_value = RTEMS_INTERNAL_ERROR;
+ break;
+ }
+ _Thread_Enable_dispatch();
+ return( return_value );
+ }
+
+ _ISR_Disable( level );
+ switch ( the_period->state ) {
+ case RATE_MONOTONIC_INACTIVE:
+ _ISR_Enable( level );
+ the_period->state = RATE_MONOTONIC_ACTIVE;
+ _Watchdog_Initialize(
+ &the_period->Timer,
+ _Rate_monotonic_Timeout,
+ id,
+ NULL
+ );
+
+ the_period->owner_ticks_executed_at_period =
+ _Thread_Executing->ticks_executed;
+
+ the_period->time_at_period = _Watchdog_Ticks_since_boot;
+ the_period->next_length = length;
+
+ _Watchdog_Insert_ticks( &the_period->Timer, length );
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+
+ case RATE_MONOTONIC_ACTIVE:
+ /*
+ * This tells the _Rate_monotonic_Timeout that this task is
+ * in the process of blocking on the period and that we
+ * may be changing the length of the next period.
+ */
+
+ the_period->state = RATE_MONOTONIC_OWNER_IS_BLOCKING;
+ the_period->next_length = length;
+
+ _ISR_Enable( level );
+
+ _Thread_Executing->Wait.id = the_period->Object.id;
+ _Thread_Set_state( _Thread_Executing, STATES_WAITING_FOR_PERIOD );
+
+ /*
+ * Did the watchdog timer expire while we were actually blocking
+ * on it?
+ */
+
+ _ISR_Disable( level );
+ local_state = the_period->state;
+ the_period->state = RATE_MONOTONIC_ACTIVE;
+ _ISR_Enable( level );
+
+ /*
+ * If it did, then we want to unblock ourself and continue as
+ * if nothing happen. The period was reset in the timeout routine.
+ */
+
+ if ( local_state == RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING )
+ _Thread_Clear_state( _Thread_Executing, STATES_WAITING_FOR_PERIOD );
+
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ break;
+
+ case RATE_MONOTONIC_EXPIRED:
+ _ISR_Enable( level );
+ the_period->state = RATE_MONOTONIC_ACTIVE;
+ the_period->owner_ticks_executed_at_period =
+ _Thread_Executing->ticks_executed;
+ the_period->time_at_period = _Watchdog_Ticks_since_boot;
+ the_period->next_length = length;
+
+ _Watchdog_Insert_ticks( &the_period->Timer, length );
+ _Thread_Enable_dispatch();
+ return RTEMS_TIMEOUT;
+
+ case RATE_MONOTONIC_OWNER_IS_BLOCKING:
+ case RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING:
+ /*
+ * These should never happen.
+ */
+ break;
+ }
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/ratemontimeout.c b/cpukit/rtems/src/ratemontimeout.c
new file mode 100644
index 0000000000..a75a831fd0
--- /dev/null
+++ b/cpukit/rtems/src/ratemontimeout.c
@@ -0,0 +1,81 @@
+/*
+ * Rate Monotonic Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/ratemon.h>
+#include <rtems/score/thread.h>
+
+/*PAGE
+ *
+ * _Rate_monotonic_Timeout
+ *
+ * This routine processes a period ending. If the owning thread
+ * is waiting for the period, that thread is unblocked and the
+ * period reinitiated. Otherwise, the period is expired.
+ * This routine is called by the watchdog handler.
+ *
+ * Input parameters:
+ * id - period id
+ *
+ * Output parameters: NONE
+ */
+
+void _Rate_monotonic_Timeout(
+ Objects_Id id,
+ void *ignored
+)
+{
+ Rate_monotonic_Control *the_period;
+ Objects_Locations location;
+ Thread_Control *the_thread;
+
+ /*
+ * When we get here, the Timer is already off the chain so we do not
+ * have to worry about that -- hence no _Watchdog_Remove().
+ */
+
+ the_period = _Rate_monotonic_Get( id, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE: /* impossible */
+ case OBJECTS_ERROR:
+ break;
+
+ case OBJECTS_LOCAL:
+ the_thread = the_period->owner;
+ if ( _States_Is_waiting_for_period( the_thread->current_state ) &&
+ the_thread->Wait.id == the_period->Object.id ) {
+ _Thread_Unblock( the_thread );
+ the_period->owner_ticks_executed_at_period =
+ the_thread->ticks_executed;
+
+ the_period->time_at_period = _Watchdog_Ticks_since_boot;
+
+ _Watchdog_Insert_ticks( &the_period->Timer, the_period->next_length );
+ } else if ( the_period->state == RATE_MONOTONIC_OWNER_IS_BLOCKING ) {
+ the_period->state = RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING;
+ the_period->owner_ticks_executed_at_period =
+ the_thread->ticks_executed;
+
+ the_period->time_at_period = _Watchdog_Ticks_since_boot;
+ _Watchdog_Insert_ticks( &the_period->Timer, the_period->next_length );
+ } else
+ the_period->state = RATE_MONOTONIC_EXPIRED;
+ _Thread_Unnest_dispatch();
+ break;
+ }
+}
diff --git a/cpukit/rtems/src/region.c b/cpukit/rtems/src/region.c
new file mode 100644
index 0000000000..1f747f4a37
--- /dev/null
+++ b/cpukit/rtems/src/region.c
@@ -0,0 +1,71 @@
+/*
+ * Region Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/region.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/apimutex.h>
+
+/*PAGE
+ *
+ * _Region_Manager_initialization
+ *
+ * This routine initializes all region manager related data structures.
+ *
+ * Input parameters:
+ * maximum_regions - number of regions to initialize
+ *
+ * Output parameters: NONE
+ */
+
+void _Region_Manager_initialization(
+ uint32_t maximum_regions
+)
+{
+ /* XXX move me */
+ _API_Mutex_Initialization( 1 );
+ _API_Mutex_Allocate( _RTEMS_Allocator_Mutex );
+
+ _Objects_Initialize_information(
+ &_Region_Information, /* object information table */
+ OBJECTS_CLASSIC_API, /* object API */
+ OBJECTS_RTEMS_REGIONS, /* object class */
+ maximum_regions, /* maximum objects of this class */
+ sizeof( Region_Control ), /* size of this object's control block */
+ FALSE, /* TRUE if the name is a string */
+ RTEMS_MAXIMUM_NAME_LENGTH /* maximum length of an object name */
+#if defined(RTEMS_MULTIPROCESSING)
+ ,
+ FALSE, /* TRUE if this is a global object class */
+ NULL /* Proxy extraction support callout */
+#endif
+ );
+
+ /*
+ * Register the MP Process Packet routine.
+ */
+
+#if defined(RTEMS_MULTIPROCESSING)
+ _MPCI_Register_packet_processor(
+ MP_PACKET_REGION,
+ 0 /* XXX _Region_MP_Process_packet */
+ );
+#endif
+
+}
diff --git a/cpukit/rtems/src/regioncreate.c b/cpukit/rtems/src/regioncreate.c
new file mode 100644
index 0000000000..3aeb78ef0e
--- /dev/null
+++ b/cpukit/rtems/src/regioncreate.c
@@ -0,0 +1,110 @@
+/*
+ * Region Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/region.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/apimutex.h>
+
+/*PAGE
+ *
+ * rtems_region_create
+ *
+ * This directive creates a region of physical contiguous memory area
+ * from which variable sized segments can be allocated.
+ *
+ * Input parameters:
+ * name - user defined region name
+ * starting_address - physical start address of region
+ * length - physical length in bytes
+ * page_size - page size in bytes
+ * attribute_set - region attributes
+ * id - address of region id to set
+ *
+ * Output parameters:
+ * id - region id
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_region_create(
+ rtems_name name,
+ void *starting_address,
+ uint32_t length,
+ uint32_t page_size,
+ rtems_attribute attribute_set,
+ Objects_Id *id
+)
+{
+ Region_Control *the_region;
+
+ if ( !rtems_is_name_valid( name ) )
+ return RTEMS_INVALID_NAME;
+
+ if ( !starting_address )
+ return RTEMS_INVALID_ADDRESS;
+
+ if ( !id )
+ return RTEMS_INVALID_ADDRESS;
+
+ if ( !_Addresses_Is_aligned( starting_address ) )
+ return RTEMS_INVALID_ADDRESS;
+
+ _RTEMS_Lock_allocator(); /* to prevent deletion */
+
+ the_region = _Region_Allocate();
+
+ if ( !the_region ) {
+ _RTEMS_Unlock_allocator();
+ return RTEMS_TOO_MANY;
+ }
+
+ the_region->maximum_segment_size =
+ _Heap_Initialize(&the_region->Memory, starting_address, length, page_size);
+
+ if ( !the_region->maximum_segment_size ) {
+ _Region_Free( the_region );
+ _RTEMS_Unlock_allocator();
+ return RTEMS_INVALID_SIZE;
+ }
+
+ the_region->starting_address = starting_address;
+ the_region->length = length;
+ the_region->page_size = page_size;
+ the_region->attribute_set = attribute_set;
+ the_region->number_of_used_blocks = 0;
+
+ _Thread_queue_Initialize(
+ &the_region->Wait_queue,
+ _Attributes_Is_priority( attribute_set ) ?
+ THREAD_QUEUE_DISCIPLINE_PRIORITY : THREAD_QUEUE_DISCIPLINE_FIFO,
+ STATES_WAITING_FOR_SEGMENT,
+ RTEMS_TIMEOUT
+ );
+
+ _Objects_Open(
+ &_Region_Information,
+ &the_region->Object,
+ (Objects_Name) name
+ );
+
+ *id = the_region->Object.id;
+ _RTEMS_Unlock_allocator();
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/rtems/src/regiondelete.c b/cpukit/rtems/src/regiondelete.c
new file mode 100644
index 0000000000..7a41ee4e87
--- /dev/null
+++ b/cpukit/rtems/src/regiondelete.c
@@ -0,0 +1,72 @@
+/*
+ * Region Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/region.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/apimutex.h>
+
+/*PAGE
+ *
+ * rtems_region_delete
+ *
+ * This directive allows a thread to delete a region specified by
+ * the region identifier, provided that none of its segments are
+ * still allocated.
+ *
+ * Input parameters:
+ * id - region id
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_region_delete(
+ Objects_Id id
+)
+{
+ register Region_Control *the_region;
+ Objects_Locations location;
+
+ _RTEMS_Lock_allocator();
+ the_region = _Region_Get( id, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE: /* this error cannot be returned */
+ _RTEMS_Unlock_allocator();
+ return RTEMS_INTERNAL_ERROR;
+
+ case OBJECTS_ERROR:
+ _RTEMS_Unlock_allocator();
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ _Region_Debug_Walk( the_region, 5 );
+ if ( the_region->number_of_used_blocks == 0 ) {
+ _Objects_Close( &_Region_Information, &the_region->Object );
+ _Region_Free( the_region );
+ _RTEMS_Unlock_allocator();
+ return RTEMS_SUCCESSFUL;
+ }
+ _RTEMS_Unlock_allocator();
+ return RTEMS_RESOURCE_IN_USE;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/regionextend.c b/cpukit/rtems/src/regionextend.c
new file mode 100644
index 0000000000..956ef96513
--- /dev/null
+++ b/cpukit/rtems/src/regionextend.c
@@ -0,0 +1,96 @@
+/*
+ * Region Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/region.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/apimutex.h>
+
+/*PAGE
+ *
+ * rtems_region_extend
+ *
+ * This directive attempts to grow a region of physical contiguous memory area
+ * from which variable sized segments can be allocated.
+ *
+ * Input parameters:
+ * id - id of region to grow
+ * start - starting address of memory area for extension
+ * length - physical length in bytes to grow the region
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_region_extend(
+ Objects_Id id,
+ void *starting_address,
+ uint32_t length
+)
+{
+ Region_Control *the_region;
+ Objects_Locations location;
+ uint32_t amount_extended;
+ Heap_Extend_status heap_status;
+ rtems_status_code status;
+
+ if ( !starting_address )
+ return RTEMS_INVALID_ADDRESS;
+
+ status = RTEMS_SUCCESSFUL;
+
+ _RTEMS_Lock_allocator(); /* to prevent deletion */
+ the_region = _Region_Get( id, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE: /* this error cannot be returned */
+ _RTEMS_Unlock_allocator();
+ return RTEMS_INTERNAL_ERROR;
+
+ case OBJECTS_ERROR:
+ _RTEMS_Unlock_allocator();
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+
+ heap_status = _Heap_Extend(
+ &the_region->Memory,
+ starting_address,
+ length,
+ &amount_extended
+ );
+
+ switch ( heap_status ) {
+ case HEAP_EXTEND_SUCCESSFUL:
+ the_region->length += amount_extended;
+ the_region->maximum_segment_size += amount_extended;
+ break;
+ case HEAP_EXTEND_ERROR:
+ status = RTEMS_INVALID_ADDRESS;
+ break;
+ case HEAP_EXTEND_NOT_IMPLEMENTED:
+ status = RTEMS_NOT_IMPLEMENTED;
+ break;
+ }
+ _RTEMS_Unlock_allocator();
+ return( status );
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/regiongetinfo.c b/cpukit/rtems/src/regiongetinfo.c
new file mode 100644
index 0000000000..699d99dc6e
--- /dev/null
+++ b/cpukit/rtems/src/regiongetinfo.c
@@ -0,0 +1,75 @@
+/*
+ * Region Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/region.h>
+#include <rtems/score/states.h>
+#include <rtems/score/apimutex.h>
+#include <rtems/score/thread.h>
+
+/*PAGE
+ *
+ * rtems_region_get_information
+ *
+ * This directive will return information about the region specified.
+ *
+ * Input parameters:
+ * id - region id
+ * the_info - pointer to region information block
+ *
+ * Output parameters:
+ * *the_info - region information block filled in
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_region_get_information(
+ Objects_Id id,
+ Heap_Information_block *the_info
+)
+{
+ register Region_Control *the_region;
+ Objects_Locations location;
+
+ if ( !the_info )
+ return RTEMS_INVALID_ADDRESS;
+
+ _RTEMS_Lock_allocator();
+ the_region = _Region_Get( id, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE: /* this error cannot be returned */
+ _RTEMS_Unlock_allocator();
+ return RTEMS_INTERNAL_ERROR;
+
+ case OBJECTS_ERROR:
+ _RTEMS_Unlock_allocator();
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+
+ if ( _Heap_Get_information( &the_region->Memory, the_info ) ==
+ HEAP_GET_INFORMATION_SUCCESSFUL ) {
+ _RTEMS_Unlock_allocator();
+ return RTEMS_SUCCESSFUL;
+ }
+ _RTEMS_Unlock_allocator();
+ return RTEMS_INVALID_ADDRESS;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/regiongetsegment.c b/cpukit/rtems/src/regiongetsegment.c
new file mode 100644
index 0000000000..27d6bf66dd
--- /dev/null
+++ b/cpukit/rtems/src/regiongetsegment.c
@@ -0,0 +1,115 @@
+/*
+ * Region Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/region.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/apimutex.h>
+
+/*PAGE
+ *
+ * rtems_region_get_segment
+ *
+ * This directive will obtain a segment from the given region.
+ *
+ * Input parameters:
+ * id - region id
+ * size - segment size in bytes
+ * option_set - wait option
+ * timeout - number of ticks to wait (0 means wait forever)
+ * segment - pointer to segment address
+ *
+ * Output parameters:
+ * segment - pointer to segment address filled in
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_region_get_segment(
+ Objects_Id id,
+ uint32_t size,
+ rtems_option option_set,
+ rtems_interval timeout,
+ void **segment
+)
+{
+ register Region_Control *the_region;
+ Objects_Locations location;
+ Thread_Control *executing;
+ void *the_segment;
+
+ if ( !segment )
+ return RTEMS_INVALID_ADDRESS;
+
+ *segment = NULL;
+
+ if ( size == 0 )
+ return RTEMS_INVALID_SIZE;
+
+ _RTEMS_Lock_allocator();
+ executing = _Thread_Executing;
+ the_region = _Region_Get( id, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE: /* this error cannot be returned */
+ _RTEMS_Unlock_allocator();
+ return RTEMS_INTERNAL_ERROR;
+
+ case OBJECTS_ERROR:
+ _RTEMS_Unlock_allocator();
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ if ( size > the_region->maximum_segment_size ) {
+ _RTEMS_Unlock_allocator();
+ return RTEMS_INVALID_SIZE;
+ }
+
+ _Region_Debug_Walk( the_region, 1 );
+
+ the_segment = _Region_Allocate_segment( the_region, size );
+
+ _Region_Debug_Walk( the_region, 2 );
+
+ if ( the_segment ) {
+ the_region->number_of_used_blocks += 1;
+ _RTEMS_Unlock_allocator();
+ *segment = the_segment;
+ return RTEMS_SUCCESSFUL;
+ }
+
+ if ( _Options_Is_no_wait( option_set ) ) {
+ _RTEMS_Unlock_allocator();
+ return RTEMS_UNSATISFIED;
+ }
+
+ executing->Wait.queue = &the_region->Wait_queue;
+ executing->Wait.id = id;
+ executing->Wait.count = size;
+ executing->Wait.return_argument = segment;
+
+ _Thread_queue_Enter_critical_section( &the_region->Wait_queue );
+
+ _Thread_queue_Enqueue( &the_region->Wait_queue, timeout );
+
+ _RTEMS_Unlock_allocator();
+ return (rtems_status_code) executing->Wait.return_code;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/regiongetsegmentsize.c b/cpukit/rtems/src/regiongetsegmentsize.c
new file mode 100644
index 0000000000..90facf952c
--- /dev/null
+++ b/cpukit/rtems/src/regiongetsegmentsize.c
@@ -0,0 +1,81 @@
+/*
+ * Region Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/region.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/apimutex.h>
+
+/*PAGE
+ *
+ * rtems_region_get_segment_size
+ *
+ * This directive will return the size of the segment indicated
+ *
+ * Input parameters:
+ * id - region id
+ * segment - segment address
+ * size - pointer to segment size in bytes
+ *
+ * Output parameters:
+ * size - segment size in bytes filled in
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_region_get_segment_size(
+ Objects_Id id,
+ void *segment,
+ size_t *size
+)
+{
+ register Region_Control *the_region;
+ Objects_Locations location;
+ Thread_Control *executing;
+
+ if ( !segment )
+ return RTEMS_INVALID_ADDRESS;
+
+ if ( !size )
+ return RTEMS_INVALID_ADDRESS;
+
+ _RTEMS_Lock_allocator();
+ executing = _Thread_Executing;
+ the_region = _Region_Get( id, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE: /* this error cannot be returned */
+ _RTEMS_Unlock_allocator();
+ return RTEMS_INTERNAL_ERROR;
+
+ case OBJECTS_ERROR:
+ _RTEMS_Unlock_allocator();
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+
+ if ( _Heap_Size_of_user_area( &the_region->Memory, segment, size ) ) {
+ _RTEMS_Unlock_allocator();
+ return RTEMS_SUCCESSFUL;
+ }
+ _RTEMS_Unlock_allocator();
+ return RTEMS_INVALID_ADDRESS;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/regionident.c b/cpukit/rtems/src/regionident.c
new file mode 100644
index 0000000000..1449a03ab7
--- /dev/null
+++ b/cpukit/rtems/src/regionident.c
@@ -0,0 +1,57 @@
+/*
+ * Region Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/region.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/apimutex.h>
+
+/*PAGE
+ *
+ * rtems_region_ident
+ *
+ * This directive returns the system ID associated with
+ * the region name.
+ *
+ * Input parameters:
+ * name - user defined region name
+ * id - pointer to region id
+ *
+ * Output parameters:
+ * *id - region id
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_region_ident(
+ rtems_name name,
+ Objects_Id *id
+)
+{
+ Objects_Name_or_id_lookup_errors status;
+
+ status = _Objects_Name_to_id(
+ &_Region_Information,
+ (Objects_Name) name,
+ OBJECTS_SEARCH_LOCAL_NODE,
+ id
+ );
+
+ return _Status_Object_name_errors_to_status[ status ];
+}
diff --git a/cpukit/rtems/src/regionmp.c b/cpukit/rtems/src/regionmp.c
new file mode 100644
index 0000000000..cf23105961
--- /dev/null
+++ b/cpukit/rtems/src/regionmp.c
@@ -0,0 +1,311 @@
+/*
+ * Multiprocessing Support for the Region Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/score/mpci.h>
+#include <rtems/score/mppkt.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/region.h>
+#include <rtems/score/thread.h>
+#include <rtems/rtems/support.h>
+
+/*PAGE
+ *
+ * _Region_MP_Send_process_packet
+ *
+ */
+
+void _Region_MP_Send_process_packet (
+ Region_MP_Remote_operations operation,
+ Objects_Id region_id,
+ rtems_name name,
+ Objects_Id proxy_id
+)
+{
+ Region_MP_Packet *the_packet;
+ uint32_t node;
+
+ switch ( operation ) {
+
+ case REGION_MP_ANNOUNCE_CREATE:
+ case REGION_MP_ANNOUNCE_DELETE:
+ case REGION_MP_EXTRACT_PROXY:
+
+ the_packet = _Region_MP_Get_packet();
+ the_packet->Prefix.the_class = MP_PACKET_REGION;
+ the_packet->Prefix.length = sizeof ( Region_MP_Packet );
+ the_packet->Prefix.to_convert = sizeof ( Region_MP_Packet );
+ the_packet->operation = operation;
+ the_packet->Prefix.id = region_id;
+ the_packet->name = name;
+ the_packet->proxy_id = proxy_id;
+
+ if ( operation == REGION_MP_EXTRACT_PROXY )
+ node = rtems_get_node( region_id );
+ else
+ node = MPCI_ALL_NODES;
+
+ _MPCI_Send_process_packet( node, &the_packet->Prefix );
+ break;
+
+ case REGION_MP_GET_SEGMENT_REQUEST:
+ case REGION_MP_GET_SEGMENT_RESPONSE:
+ case REGION_MP_RETURN_SEGMENT_REQUEST:
+ case REGION_MP_RETURN_SEGMENT_RESPONSE:
+ break;
+ }
+}
+
+/*PAGE
+ *
+ * _Region_MP_Send_request_packet
+ *
+ */
+
+rtems_status_code _Region_MP_Send_request_packet (
+ Region_MP_Remote_operations operation,
+ Objects_Id region_id,
+ void *segment,
+ uint32_t size,
+ rtems_option option_set,
+ rtems_interval timeout
+)
+{
+ Region_MP_Packet *the_packet;
+
+ switch ( operation ) {
+
+ case REGION_MP_GET_SEGMENT_REQUEST:
+ case REGION_MP_RETURN_SEGMENT_REQUEST:
+
+ the_packet = _Region_MP_Get_packet();
+ the_packet->Prefix.the_class = MP_PACKET_REGION;
+ the_packet->Prefix.length = sizeof ( Region_MP_Packet );
+ the_packet->Prefix.to_convert = sizeof ( Region_MP_Packet );
+ if ( ! _Options_Is_no_wait(option_set))
+ the_packet->Prefix.timeout = timeout;
+
+ the_packet->operation = operation;
+ the_packet->Prefix.id = region_id;
+ the_packet->segment = segment;
+ the_packet->size = size;
+ the_packet->option_set = option_set;
+
+ return (rtems_status_code) _MPCI_Send_request_packet(
+ rtems_get_node( region_id ),
+ &the_packet->Prefix,
+ STATES_READY /* Not used */
+ );
+ break;
+
+ case REGION_MP_ANNOUNCE_CREATE:
+ case REGION_MP_ANNOUNCE_DELETE:
+ case REGION_MP_EXTRACT_PROXY:
+ case REGION_MP_GET_SEGMENT_RESPONSE:
+ case REGION_MP_RETURN_SEGMENT_RESPONSE:
+ break;
+
+ }
+ /*
+ * The following line is included to satisfy compilers which
+ * produce warnings when a function does not end with a return.
+ */
+ return RTEMS_INTERNAL_ERROR;
+}
+
+/*PAGE
+ *
+ * _Region_MP_Send_response_packet
+ *
+ */
+
+void _Region_MP_Send_response_packet (
+ Region_MP_Remote_operations operation,
+ Objects_Id region_id,
+ Thread_Control *the_thread
+)
+{
+ Region_MP_Packet *the_packet;
+
+ switch ( operation ) {
+
+ case REGION_MP_GET_SEGMENT_RESPONSE:
+ case REGION_MP_RETURN_SEGMENT_RESPONSE:
+
+ the_packet = ( Region_MP_Packet *) the_thread->receive_packet;
+
+/*
+ * The packet being returned already contains the class, length, and
+ * to_convert fields, therefore they are not set in this routine.
+ */
+ the_packet->operation = operation;
+ the_packet->Prefix.id = the_packet->Prefix.source_tid;
+
+ _MPCI_Send_response_packet(
+ rtems_get_node( the_packet->Prefix.source_tid ),
+ &the_packet->Prefix
+ );
+ break;
+
+ case REGION_MP_ANNOUNCE_CREATE:
+ case REGION_MP_ANNOUNCE_DELETE:
+ case REGION_MP_EXTRACT_PROXY:
+ case REGION_MP_GET_SEGMENT_REQUEST:
+ case REGION_MP_RETURN_SEGMENT_REQUEST:
+ break;
+
+ }
+}
+
+/*PAGE
+ *
+ *
+ * _Region_MP_Process_packet
+ *
+ */
+
+void _Region_MP_Process_packet (
+ rtems_packet_prefix *the_packet_prefix
+)
+{
+ Region_MP_Packet *the_packet;
+ Thread_Control *the_thread;
+ boolean ignored;
+
+ the_packet = (Region_MP_Packet *) the_packet_prefix;
+
+ switch ( the_packet->operation ) {
+
+ case REGION_MP_ANNOUNCE_CREATE:
+
+ ignored = _Objects_MP_Allocate_and_open(
+ &_Region_Information,
+ the_packet->name,
+ the_packet->Prefix.id,
+ TRUE
+ );
+
+ _MPCI_Return_packet( the_packet_prefix );
+ break;
+
+ case REGION_MP_ANNOUNCE_DELETE:
+
+ _Objects_MP_Close( &_Region_Information, the_packet->Prefix.id );
+
+ _MPCI_Return_packet( the_packet_prefix );
+ break;
+
+ case REGION_MP_EXTRACT_PROXY:
+
+ the_thread = _Thread_MP_Find_proxy( the_packet->proxy_id );
+
+ if ( ! _Thread_Is_null( the_thread ) )
+ _Thread_queue_Extract( the_thread->Wait.queue, the_thread );
+
+ _MPCI_Return_packet( the_packet_prefix );
+ break;
+
+ case REGION_MP_GET_SEGMENT_REQUEST:
+
+ the_packet->Prefix.return_code = rtems_region_get_segment(
+ the_packet->Prefix.id,
+ the_packet->size,
+ the_packet->option_set,
+ the_packet->Prefix.timeout,
+ &the_packet->segment
+ );
+
+ _Region_MP_Send_response_packet(
+ REGION_MP_GET_SEGMENT_RESPONSE,
+ the_packet->Prefix.id,
+ _Thread_Executing
+ );
+ break;
+
+ case REGION_MP_GET_SEGMENT_RESPONSE:
+
+ the_thread = _MPCI_Process_response( the_packet_prefix );
+
+ *(void **)the_thread->Wait.return_argument = the_packet->segment;
+
+ _MPCI_Return_packet( the_packet_prefix );
+ break;
+
+ case REGION_MP_RETURN_SEGMENT_REQUEST:
+
+ the_packet->Prefix.return_code = rtems_region_return_segment(
+ the_packet->Prefix.id,
+ the_packet->segment
+ );
+
+ _Region_MP_Send_response_packet(
+ REGION_MP_RETURN_SEGMENT_RESPONSE,
+ the_packet->Prefix.id,
+ _Thread_Executing
+ );
+ break;
+
+ case REGION_MP_RETURN_SEGMENT_RESPONSE:
+
+ the_thread = _MPCI_Process_response( the_packet_prefix );
+
+ _MPCI_Return_packet( the_packet_prefix );
+ break;
+
+ }
+}
+
+/*PAGE
+ *
+ * _Region_MP_Send_object_was_deleted
+ *
+ * This routine is not needed by the Region since a region
+ * cannot be deleted when segments are in use.
+ *
+ */
+
+/*PAGE
+ *
+ * _Region_MP_Send_extract_proxy
+ *
+ */
+
+void _Region_MP_Send_extract_proxy (
+ void *argument
+)
+{
+ Thread_Control *the_thread = (Thread_Control *)argument;
+
+ _Region_MP_Send_process_packet(
+ REGION_MP_EXTRACT_PROXY,
+ the_thread->Wait.id,
+ (rtems_name) 0,
+ the_thread->Object.id
+ );
+}
+
+/*PAGE
+ *
+ * _Region_MP_Get_packet
+ *
+ */
+
+Region_MP_Packet *_Region_MP_Get_packet ( void )
+{
+ return ( (Region_MP_Packet *) _MPCI_Get_packet() );
+}
+
+/* end of file */
diff --git a/cpukit/rtems/src/regionreturnsegment.c b/cpukit/rtems/src/regionreturnsegment.c
new file mode 100644
index 0000000000..74517c0812
--- /dev/null
+++ b/cpukit/rtems/src/regionreturnsegment.c
@@ -0,0 +1,122 @@
+/*
+ * Region Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifdef RTEMS_REGION_SHRED_ON_FREE
+#include <string.h>
+
+#ifndef RTEMS_REGION_FREE_SHRED_PATTERN
+#define RTEMS_REGION_FREE_SHRED_PATTERN 0x00
+#endif
+#endif
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/region.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/apimutex.h>
+
+/*PAGE
+ *
+ * rtems_region_return_segment
+ *
+ * This directive will return a segment to its region.
+ *
+ * Input parameters:
+ * id - region id
+ * segment - pointer to segment address
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_region_return_segment(
+ Objects_Id id,
+ void *segment
+)
+{
+ register Region_Control *the_region;
+ Thread_Control *the_thread;
+ Objects_Locations location;
+ void **the_segment;
+#ifdef RTEMS_REGION_FREE_SHRED_PATTERN
+ uint32_t size;
+#endif
+ int status;
+
+ _RTEMS_Lock_allocator();
+ the_region = _Region_Get( id, &location );
+ switch ( location ) {
+
+ case OBJECTS_REMOTE: /* this error cannot be returned */
+ _RTEMS_Unlock_allocator();
+ return RTEMS_INTERNAL_ERROR;
+
+ case OBJECTS_ERROR:
+ _RTEMS_Unlock_allocator();
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+
+ _Region_Debug_Walk( the_region, 3 );
+
+#ifdef RTEMS_REGION_FREE_SHRED_PATTERN
+ if ( _Heap_Size_of_user_area( &the_region->Memory, segment, &size ) ) {
+ memset(segment, (RTEMS_REGION_FREE_SHRED_PATTERN & 0xFF), size);
+ } else {
+ _RTEMS_Unlock_allocator();
+ return RTEMS_INVALID_ADDRESS;
+ }
+#endif
+
+ status = _Region_Free_segment( the_region, segment );
+
+ _Region_Debug_Walk( the_region, 4 );
+
+ if ( !status ) {
+ _RTEMS_Unlock_allocator();
+ return RTEMS_INVALID_ADDRESS;
+ }
+
+ the_region->number_of_used_blocks -= 1;
+ for ( ; ; ) {
+ the_thread = _Thread_queue_First( &the_region->Wait_queue );
+
+ if ( the_thread == NULL )
+ break;
+
+ the_segment = (void **) _Region_Allocate_segment(
+ the_region,
+ the_thread->Wait.count
+ );
+
+ if ( the_segment == NULL )
+ break;
+
+ *(void **)the_thread->Wait.return_argument = the_segment;
+ the_region->number_of_used_blocks += 1;
+ _Thread_queue_Extract( &the_region->Wait_queue, the_thread );
+ the_thread->Wait.return_code = RTEMS_SUCCESSFUL;
+ }
+
+ _RTEMS_Unlock_allocator();
+ return RTEMS_SUCCESSFUL;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/rtclock.c b/cpukit/rtems/src/rtclock.c
new file mode 100644
index 0000000000..f9c4d2c292
--- /dev/null
+++ b/cpukit/rtems/src/rtclock.c
@@ -0,0 +1,22 @@
+/*
+ * Clock Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/clock.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/watchdog.h>
+
+/* No initialization routine */
diff --git a/cpukit/rtems/src/rtemsidtoname.c b/cpukit/rtems/src/rtemsidtoname.c
new file mode 100644
index 0000000000..1f58a80b57
--- /dev/null
+++ b/cpukit/rtems/src/rtemsidtoname.c
@@ -0,0 +1,46 @@
+/*
+ * RTEMS ID To Name Lookup
+ *
+ *
+ * COPYRIGHT (c) 1989-2003.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/types.h>
+
+/*PAGE
+ *
+ * rtems_object_id_to_name
+ *
+ * This directive returns the name associated with the specified
+ * object ID.
+ *
+ * Input parameters:
+ * id - message queue id
+ *
+ * Output parameters:
+ * *name - user defined object name
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_object_id_to_name(
+ rtems_id id,
+ rtems_name *name
+)
+{
+ Objects_Name_or_id_lookup_errors status;
+
+ status = _Objects_Id_to_name( id, (Objects_Name *) name );
+
+ return _Status_Object_name_errors_to_status[ status ];
+}
diff --git a/cpukit/rtems/src/rtemstimer.c b/cpukit/rtems/src/rtemstimer.c
new file mode 100644
index 0000000000..5733887bc4
--- /dev/null
+++ b/cpukit/rtems/src/rtemstimer.c
@@ -0,0 +1,61 @@
+/*
+ * Timer Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-2002.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/rtems/timer.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * _Timer_Manager_initialization
+ *
+ * This routine initializes all timer manager related data structures.
+ *
+ * Input parameters:
+ * maximum_timers - number of timers to initialize
+ *
+ * Output parameters: NONE
+ */
+
+void _Timer_Manager_initialization(
+ uint32_t maximum_timers
+)
+{
+ _Objects_Initialize_information(
+ &_Timer_Information, /* object information table */
+ OBJECTS_CLASSIC_API, /* object API */
+ OBJECTS_RTEMS_TIMERS, /* object class */
+ maximum_timers, /* maximum objects of this class */
+ sizeof( Timer_Control ), /* size of this object's control block */
+ FALSE, /* TRUE if the name is a string */
+ RTEMS_MAXIMUM_NAME_LENGTH /* maximum length of an object name */
+#if defined(RTEMS_MULTIPROCESSING)
+ ,
+ FALSE, /* TRUE if this is a global object class */
+ NULL /* Proxy extraction support callout */
+#endif
+ );
+
+ /*
+ * Initialize the pointer to the Timer Server TCB to NULL indicating
+ * that task-based timer support is not initialized.
+ */
+
+ _Timer_Server = NULL;
+}
diff --git a/cpukit/rtems/src/sem.c b/cpukit/rtems/src/sem.c
new file mode 100644
index 0000000000..2c367b0d6d
--- /dev/null
+++ b/cpukit/rtems/src/sem.c
@@ -0,0 +1,90 @@
+/*
+ * Semaphore Manager
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the Semaphore Manager.
+ * This manager utilizes standard Dijkstra counting semaphores to provide
+ * synchronization and mutual exclusion capabilities.
+ *
+ * Directives provided are:
+ *
+ * + create a semaphore
+ * + get an ID of a semaphore
+ * + delete a semaphore
+ * + acquire a semaphore
+ * + release a semaphore
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/rtems/attr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/sem.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/coresem.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/score/sysstate.h>
+
+#include <rtems/score/interr.h>
+
+/*PAGE
+ *
+ * _Semaphore_Manager_initialization
+ *
+ * This routine initializes all semaphore manager related data structures.
+ *
+ * Input parameters:
+ * maximum_semaphores - maximum configured semaphores
+ *
+ * Output parameters: NONE
+ */
+
+void _Semaphore_Manager_initialization(
+ uint32_t maximum_semaphores
+)
+{
+ _Objects_Initialize_information(
+ &_Semaphore_Information, /* object information table */
+ OBJECTS_CLASSIC_API, /* object API */
+ OBJECTS_RTEMS_SEMAPHORES, /* object class */
+ maximum_semaphores, /* maximum objects of this class */
+ sizeof( Semaphore_Control ), /* size of this object's control block */
+ FALSE, /* TRUE if the name is a string */
+ RTEMS_MAXIMUM_NAME_LENGTH /* maximum length of an object name */
+#if defined(RTEMS_MULTIPROCESSING)
+ ,
+ TRUE, /* TRUE if this is a global object class */
+ _Semaphore_MP_Send_extract_proxy /* Proxy extraction support callout */
+#endif
+ );
+
+ /*
+ * Register the MP Process Packet routine.
+ */
+
+#if defined(RTEMS_MULTIPROCESSING)
+ _MPCI_Register_packet_processor(
+ MP_PACKET_SEMAPHORE,
+ _Semaphore_MP_Process_packet
+ );
+#endif
+
+}
diff --git a/cpukit/rtems/src/semcreate.c b/cpukit/rtems/src/semcreate.c
new file mode 100644
index 0000000000..fc952e9032
--- /dev/null
+++ b/cpukit/rtems/src/semcreate.c
@@ -0,0 +1,226 @@
+/*
+ * Semaphore Manager
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the Semaphore Manager.
+ * This manager utilizes standard Dijkstra counting semaphores to provide
+ * synchronization and mutual exclusion capabilities.
+ *
+ * Directives provided are:
+ *
+ * + create a semaphore
+ * + get an ID of a semaphore
+ * + delete a semaphore
+ * + acquire a semaphore
+ * + release a semaphore
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/rtems/attr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/sem.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/coresem.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/score/sysstate.h>
+
+#include <rtems/score/interr.h>
+
+/*PAGE
+ *
+ * rtems_semaphore_create
+ *
+ * This directive creates a semaphore and sets the initial value based
+ * on the given count. A semaphore id is returned.
+ *
+ * Input parameters:
+ * name - user defined semaphore name
+ * count - initial count of semaphore
+ * attribute_set - semaphore attributes
+ * priority_ceiling - semaphore's ceiling priority
+ * id - pointer to semaphore id
+ *
+ * Output parameters:
+ * id - semaphore id
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_semaphore_create(
+ rtems_name name,
+ uint32_t count,
+ rtems_attribute attribute_set,
+ rtems_task_priority priority_ceiling,
+ Objects_Id *id
+)
+{
+ register Semaphore_Control *the_semaphore;
+ CORE_mutex_Attributes the_mutex_attributes;
+ CORE_semaphore_Attributes the_semaphore_attributes;
+ uint32_t lock;
+
+ if ( !rtems_is_name_valid( name ) )
+ return RTEMS_INVALID_NAME;
+
+ if ( !id )
+ return RTEMS_INVALID_ADDRESS;
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( _Attributes_Is_global( attribute_set ) ) {
+
+ if ( !_System_state_Is_multiprocessing )
+ return RTEMS_MP_NOT_CONFIGURED;
+
+ if ( _Attributes_Is_inherit_priority( attribute_set ) )
+ return RTEMS_NOT_DEFINED;
+
+ } else
+#endif
+
+ if ( _Attributes_Is_inherit_priority( attribute_set ) ||
+ _Attributes_Is_priority_ceiling( attribute_set ) ) {
+
+ if ( ! ( (_Attributes_Is_binary_semaphore( attribute_set ) ||
+ _Attributes_Is_simple_binary_semaphore( attribute_set )) &&
+
+ _Attributes_Is_priority( attribute_set ) ) )
+ return RTEMS_NOT_DEFINED;
+
+ }
+
+ if ( !_Attributes_Is_counting_semaphore( attribute_set ) && ( count > 1 ) )
+ return RTEMS_INVALID_NUMBER;
+
+ _Thread_Disable_dispatch(); /* prevents deletion */
+
+ the_semaphore = _Semaphore_Allocate();
+
+ if ( !the_semaphore ) {
+ _Thread_Enable_dispatch();
+ return RTEMS_TOO_MANY;
+ }
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( _Attributes_Is_global( attribute_set ) &&
+ ! ( _Objects_MP_Allocate_and_open( &_Semaphore_Information, name,
+ the_semaphore->Object.id, FALSE ) ) ) {
+ _Semaphore_Free( the_semaphore );
+ _Thread_Enable_dispatch();
+ return RTEMS_TOO_MANY;
+ }
+#endif
+
+ the_semaphore->attribute_set = attribute_set;
+
+ /*
+ * If it is not a counting semaphore, then it is either a
+ * simple binary semaphore or a more powerful mutex style binary
+ * semaphore.
+ */
+
+ if ( !_Attributes_Is_counting_semaphore( attribute_set ) ) {
+ if ( _Attributes_Is_inherit_priority( attribute_set ) )
+ the_mutex_attributes.discipline = CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT;
+ else if ( _Attributes_Is_priority_ceiling( attribute_set ) )
+ the_mutex_attributes.discipline = CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING;
+ else if ( _Attributes_Is_priority( attribute_set ) )
+ the_mutex_attributes.discipline = CORE_MUTEX_DISCIPLINES_PRIORITY;
+ else
+ the_mutex_attributes.discipline = CORE_MUTEX_DISCIPLINES_FIFO;
+
+
+ if ( _Attributes_Is_binary_semaphore( attribute_set ) ) {
+ the_mutex_attributes.lock_nesting_behavior = CORE_MUTEX_NESTING_ACQUIRES;
+
+ switch ( the_mutex_attributes.discipline ) {
+ case CORE_MUTEX_DISCIPLINES_FIFO:
+ case CORE_MUTEX_DISCIPLINES_PRIORITY:
+ the_mutex_attributes.only_owner_release = FALSE;
+ break;
+ case CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING:
+ case CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT:
+ the_mutex_attributes.only_owner_release = TRUE;
+ break;
+ }
+ } else {
+ the_mutex_attributes.lock_nesting_behavior = CORE_MUTEX_NESTING_BLOCKS;
+ the_mutex_attributes.only_owner_release = FALSE;
+ }
+
+ the_mutex_attributes.priority_ceiling = priority_ceiling;
+
+ if ( count == 1 )
+ lock = CORE_MUTEX_UNLOCKED;
+ else
+ lock = CORE_MUTEX_LOCKED;
+
+ _CORE_mutex_Initialize(
+ &the_semaphore->Core_control.mutex,
+ &the_mutex_attributes,
+ lock
+ );
+ } else {
+ if ( _Attributes_Is_priority( attribute_set ) )
+ the_semaphore_attributes.discipline = CORE_SEMAPHORE_DISCIPLINES_PRIORITY;
+ else
+ the_semaphore_attributes.discipline = CORE_SEMAPHORE_DISCIPLINES_FIFO;
+
+ /*
+ * This effectively disables limit checking.
+ */
+
+ the_semaphore_attributes.maximum_count = 0xFFFFFFFF;
+
+ /*
+ * The following are just to make Purify happy.
+ */
+
+ the_mutex_attributes.lock_nesting_behavior = CORE_MUTEX_NESTING_ACQUIRES;
+ the_mutex_attributes.priority_ceiling = PRIORITY_MINIMUM;
+
+ _CORE_semaphore_Initialize(
+ &the_semaphore->Core_control.semaphore,
+ &the_semaphore_attributes,
+ count
+ );
+ }
+
+ _Objects_Open(
+ &_Semaphore_Information,
+ &the_semaphore->Object,
+ (Objects_Name) name
+ );
+
+ *id = the_semaphore->Object.id;
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( _Attributes_Is_global( attribute_set ) )
+ _Semaphore_MP_Send_process_packet(
+ SEMAPHORE_MP_ANNOUNCE_CREATE,
+ the_semaphore->Object.id,
+ name,
+ 0 /* Not used */
+ );
+#endif
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/rtems/src/semdelete.c b/cpukit/rtems/src/semdelete.c
new file mode 100644
index 0000000000..a4fb7b7d50
--- /dev/null
+++ b/cpukit/rtems/src/semdelete.c
@@ -0,0 +1,132 @@
+/*
+ * Semaphore Manager
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the Semaphore Manager.
+ * This manager utilizes standard Dijkstra counting semaphores to provide
+ * synchronization and mutual exclusion capabilities.
+ *
+ * Directives provided are:
+ *
+ * + create a semaphore
+ * + get an ID of a semaphore
+ * + delete a semaphore
+ * + acquire a semaphore
+ * + release a semaphore
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/rtems/attr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/sem.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/coresem.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/score/sysstate.h>
+
+#include <rtems/score/interr.h>
+
+/*PAGE
+ *
+ * rtems_semaphore_delete
+ *
+ * This directive allows a thread to delete a semaphore specified by
+ * the semaphore id. The semaphore is freed back to the inactive
+ * semaphore chain.
+ *
+ * Input parameters:
+ * id - semaphore id
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+#if defined(RTEMS_MULTIPROCESSING)
+#define SEMAPHORE_MP_OBJECT_WAS_DELETED _Semaphore_MP_Send_object_was_deleted
+#else
+#define SEMAPHORE_MP_OBJECT_WAS_DELETED NULL
+#endif
+
+rtems_status_code rtems_semaphore_delete(
+ Objects_Id id
+)
+{
+ register Semaphore_Control *the_semaphore;
+ Objects_Locations location;
+
+ the_semaphore = _Semaphore_Get( id, &location );
+ switch ( location ) {
+
+ case OBJECTS_REMOTE:
+#if defined(RTEMS_MULTIPROCESSING)
+ _Thread_Dispatch();
+ return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
+#endif
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ if ( !_Attributes_Is_counting_semaphore(the_semaphore->attribute_set) ) {
+ if ( _CORE_mutex_Is_locked( &the_semaphore->Core_control.mutex ) &&
+ !_Attributes_Is_simple_binary_semaphore(
+ the_semaphore->attribute_set ) ) {
+ _Thread_Enable_dispatch();
+ return RTEMS_RESOURCE_IN_USE;
+ }
+ _CORE_mutex_Flush(
+ &the_semaphore->Core_control.mutex,
+ SEMAPHORE_MP_OBJECT_WAS_DELETED,
+ CORE_MUTEX_WAS_DELETED
+ );
+ } else {
+ _CORE_semaphore_Flush(
+ &the_semaphore->Core_control.semaphore,
+ SEMAPHORE_MP_OBJECT_WAS_DELETED,
+ CORE_SEMAPHORE_WAS_DELETED
+ );
+ }
+
+ _Objects_Close( &_Semaphore_Information, &the_semaphore->Object );
+
+ _Semaphore_Free( the_semaphore );
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( _Attributes_Is_global( the_semaphore->attribute_set ) ) {
+
+ _Objects_MP_Close( &_Semaphore_Information, the_semaphore->Object.id );
+
+ _Semaphore_MP_Send_process_packet(
+ SEMAPHORE_MP_ANNOUNCE_DELETE,
+ the_semaphore->Object.id,
+ 0, /* Not used */
+ 0 /* Not used */
+ );
+ }
+#endif
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/semflush.c b/cpukit/rtems/src/semflush.c
new file mode 100644
index 0000000000..cd244a1cf1
--- /dev/null
+++ b/cpukit/rtems/src/semflush.c
@@ -0,0 +1,98 @@
+/*
+ * rtems_semaphore_flush
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the flush directive
+ * of the Semaphore Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/rtems/attr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/sem.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/coresem.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/score/sysstate.h>
+
+#include <rtems/score/interr.h>
+
+/*PAGE
+ *
+ * rtems_semaphore_flush
+ *
+ * This directive allows a thread to flush the threads
+ * pending on the semaphore.
+ *
+ * Input parameters:
+ * id - semaphore id
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+#if defined(RTEMS_MULTIPROCESSING)
+#define SEND_OBJECT_WAS_DELETED _Semaphore_MP_Send_object_was_deleted
+#else
+#define SEND_OBJECT_WAS_DELETED NULL
+#endif
+
+rtems_status_code rtems_semaphore_flush(
+ Objects_Id id
+)
+{
+ register Semaphore_Control *the_semaphore;
+ Objects_Locations location;
+
+ the_semaphore = _Semaphore_Get( id, &location );
+ switch ( location ) {
+
+ case OBJECTS_REMOTE:
+#if defined(RTEMS_MULTIPROCESSING)
+ _Thread_Dispatch();
+ return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
+#endif
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ if ( !_Attributes_Is_counting_semaphore(the_semaphore->attribute_set) ) {
+ _CORE_mutex_Flush(
+ &the_semaphore->Core_control.mutex,
+ SEND_OBJECT_WAS_DELETED,
+ CORE_MUTEX_STATUS_UNSATISFIED_NOWAIT
+ );
+ } else {
+ _CORE_semaphore_Flush(
+ &the_semaphore->Core_control.semaphore,
+ SEND_OBJECT_WAS_DELETED,
+ CORE_SEMAPHORE_STATUS_UNSATISFIED_NOWAIT
+ );
+ }
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/semident.c b/cpukit/rtems/src/semident.c
new file mode 100644
index 0000000000..9add0f0458
--- /dev/null
+++ b/cpukit/rtems/src/semident.c
@@ -0,0 +1,82 @@
+/*
+ * Semaphore Manager
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the Semaphore Manager.
+ * This manager utilizes standard Dijkstra counting semaphores to provide
+ * synchronization and mutual exclusion capabilities.
+ *
+ * Directives provided are:
+ *
+ * + create a semaphore
+ * + get an ID of a semaphore
+ * + delete a semaphore
+ * + acquire a semaphore
+ * + release a semaphore
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/rtems/attr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/sem.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/coresem.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/score/sysstate.h>
+
+#include <rtems/score/interr.h>
+
+/*PAGE
+ *
+ * rtems_semaphore_ident
+ *
+ * This directive returns the system ID associated with
+ * the semaphore name.
+ *
+ * Input parameters:
+ * name - user defined semaphore name
+ * node - node(s) to be searched
+ * id - pointer to semaphore id
+ *
+ * Output parameters:
+ * *id - semaphore id
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_semaphore_ident(
+ rtems_name name,
+ uint32_t node,
+ Objects_Id *id
+)
+{
+ Objects_Name_or_id_lookup_errors status;
+
+ status = _Objects_Name_to_id(
+ &_Semaphore_Information,
+ (Objects_Name) name,
+ node,
+ id
+ );
+
+ return _Status_Object_name_errors_to_status[ status ];
+}
diff --git a/cpukit/rtems/src/semmp.c b/cpukit/rtems/src/semmp.c
new file mode 100644
index 0000000000..fff31f1e2f
--- /dev/null
+++ b/cpukit/rtems/src/semmp.c
@@ -0,0 +1,363 @@
+/*
+ * Multiprocessing Support for the Semaphore Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/score/mpci.h>
+#include <rtems/score/mppkt.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/sem.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/rtems/support.h>
+
+/*PAGE
+ *
+ * _Semaphore_MP_Send_process_packet
+ *
+ */
+
+void _Semaphore_MP_Send_process_packet (
+ Semaphore_MP_Remote_operations operation,
+ Objects_Id semaphore_id,
+ rtems_name name,
+ Objects_Id proxy_id
+)
+{
+ Semaphore_MP_Packet *the_packet;
+ uint32_t node;
+
+ switch ( operation ) {
+
+ case SEMAPHORE_MP_ANNOUNCE_CREATE:
+ case SEMAPHORE_MP_ANNOUNCE_DELETE:
+ case SEMAPHORE_MP_EXTRACT_PROXY:
+
+ the_packet = _Semaphore_MP_Get_packet();
+ the_packet->Prefix.the_class = MP_PACKET_SEMAPHORE;
+ the_packet->Prefix.length = sizeof ( Semaphore_MP_Packet );
+ the_packet->Prefix.to_convert = sizeof ( Semaphore_MP_Packet );
+ the_packet->operation = operation;
+ the_packet->Prefix.id = semaphore_id;
+ the_packet->name = name;
+ the_packet->proxy_id = proxy_id;
+
+ if ( operation == SEMAPHORE_MP_EXTRACT_PROXY )
+ node = rtems_get_node( semaphore_id );
+ else
+ node = MPCI_ALL_NODES;
+
+ _MPCI_Send_process_packet( node, &the_packet->Prefix );
+ break;
+
+ case SEMAPHORE_MP_OBTAIN_REQUEST:
+ case SEMAPHORE_MP_OBTAIN_RESPONSE:
+ case SEMAPHORE_MP_RELEASE_REQUEST:
+ case SEMAPHORE_MP_RELEASE_RESPONSE:
+ break;
+ }
+}
+
+/*PAGE
+ *
+ * _Semaphore_MP_Send_request_packet
+ *
+ */
+
+rtems_status_code _Semaphore_MP_Send_request_packet (
+ Semaphore_MP_Remote_operations operation,
+ Objects_Id semaphore_id,
+ rtems_option option_set,
+ rtems_interval timeout
+)
+{
+ Semaphore_MP_Packet *the_packet;
+
+ switch ( operation ) {
+
+ case SEMAPHORE_MP_OBTAIN_REQUEST:
+ case SEMAPHORE_MP_RELEASE_REQUEST:
+
+ the_packet = _Semaphore_MP_Get_packet();
+ the_packet->Prefix.the_class = MP_PACKET_SEMAPHORE;
+ the_packet->Prefix.length = sizeof ( Semaphore_MP_Packet );
+ the_packet->Prefix.to_convert = sizeof ( Semaphore_MP_Packet );
+ if ( ! _Options_Is_no_wait(option_set))
+ the_packet->Prefix.timeout = timeout;
+
+ the_packet->operation = operation;
+ the_packet->Prefix.id = semaphore_id;
+ the_packet->option_set = option_set;
+
+ return _MPCI_Send_request_packet(
+ rtems_get_node( semaphore_id ),
+ &the_packet->Prefix,
+ STATES_WAITING_FOR_SEMAPHORE
+ );
+ break;
+
+ case SEMAPHORE_MP_ANNOUNCE_CREATE:
+ case SEMAPHORE_MP_ANNOUNCE_DELETE:
+ case SEMAPHORE_MP_EXTRACT_PROXY:
+ case SEMAPHORE_MP_OBTAIN_RESPONSE:
+ case SEMAPHORE_MP_RELEASE_RESPONSE:
+ break;
+
+ }
+ /*
+ * The following line is included to satisfy compilers which
+ * produce warnings when a function does not end with a return.
+ */
+ return RTEMS_SUCCESSFUL;
+}
+
+/*PAGE
+ *
+ * _Semaphore_MP_Send_response_packet
+ *
+ */
+
+void _Semaphore_MP_Send_response_packet (
+ Semaphore_MP_Remote_operations operation,
+ Objects_Id semaphore_id,
+ Thread_Control *the_thread
+)
+{
+ Semaphore_MP_Packet *the_packet;
+
+ switch ( operation ) {
+
+ case SEMAPHORE_MP_OBTAIN_RESPONSE:
+ case SEMAPHORE_MP_RELEASE_RESPONSE:
+
+ the_packet = ( Semaphore_MP_Packet *) the_thread->receive_packet;
+
+/*
+ * The packet being returned already contains the class, length, and
+ * to_convert fields, therefore they are not set in this routine.
+ */
+ the_packet->operation = operation;
+ the_packet->Prefix.id = the_packet->Prefix.source_tid;
+
+ _MPCI_Send_response_packet(
+ rtems_get_node( the_packet->Prefix.source_tid ),
+ &the_packet->Prefix
+ );
+ break;
+
+ case SEMAPHORE_MP_ANNOUNCE_CREATE:
+ case SEMAPHORE_MP_ANNOUNCE_DELETE:
+ case SEMAPHORE_MP_EXTRACT_PROXY:
+ case SEMAPHORE_MP_OBTAIN_REQUEST:
+ case SEMAPHORE_MP_RELEASE_REQUEST:
+ break;
+
+ }
+}
+
+/*PAGE
+ *
+ *
+ * _Semaphore_MP_Process_packet
+ *
+ */
+
+void _Semaphore_MP_Process_packet (
+ rtems_packet_prefix *the_packet_prefix
+)
+{
+ Semaphore_MP_Packet *the_packet;
+ Thread_Control *the_thread;
+ boolean ignored;
+
+ the_packet = (Semaphore_MP_Packet *) the_packet_prefix;
+
+ switch ( the_packet->operation ) {
+
+ case SEMAPHORE_MP_ANNOUNCE_CREATE:
+
+ ignored = _Objects_MP_Allocate_and_open(
+ &_Semaphore_Information,
+ the_packet->name,
+ the_packet->Prefix.id,
+ TRUE
+ );
+
+ _MPCI_Return_packet( the_packet_prefix );
+ break;
+
+ case SEMAPHORE_MP_ANNOUNCE_DELETE:
+
+ _Objects_MP_Close( &_Semaphore_Information, the_packet->Prefix.id );
+
+ _MPCI_Return_packet( the_packet_prefix );
+ break;
+
+ case SEMAPHORE_MP_EXTRACT_PROXY:
+
+ the_thread = _Thread_MP_Find_proxy( the_packet->proxy_id );
+
+ if ( ! _Thread_Is_null( the_thread ) )
+ _Thread_queue_Extract( the_thread->Wait.queue, the_thread );
+
+ _MPCI_Return_packet( the_packet_prefix );
+ break;
+
+ case SEMAPHORE_MP_OBTAIN_REQUEST:
+
+ the_packet->Prefix.return_code = rtems_semaphore_obtain(
+ the_packet->Prefix.id,
+ the_packet->option_set,
+ the_packet->Prefix.timeout
+ );
+
+ if ( ! _Thread_Is_proxy_blocking( the_packet->Prefix.return_code ) )
+ _Semaphore_MP_Send_response_packet(
+ SEMAPHORE_MP_OBTAIN_RESPONSE,
+ the_packet->Prefix.id,
+ _Thread_Executing
+ );
+ break;
+
+ case SEMAPHORE_MP_OBTAIN_RESPONSE:
+ case SEMAPHORE_MP_RELEASE_RESPONSE:
+
+ the_thread = _MPCI_Process_response( the_packet_prefix );
+
+ _MPCI_Return_packet( the_packet_prefix );
+ break;
+
+ case SEMAPHORE_MP_RELEASE_REQUEST:
+
+ the_packet->Prefix.return_code = rtems_semaphore_release(
+ the_packet->Prefix.id
+ );
+
+ _Semaphore_MP_Send_response_packet(
+ SEMAPHORE_MP_RELEASE_RESPONSE,
+ the_packet->Prefix.id,
+ _Thread_Executing
+ );
+ break;
+ }
+}
+
+/*PAGE
+ *
+ * _Semaphore_MP_Send_object_was_deleted
+ *
+ */
+
+void _Semaphore_MP_Send_object_was_deleted (
+ Thread_Control *the_proxy
+)
+{
+ the_proxy->receive_packet->return_code = RTEMS_OBJECT_WAS_DELETED;
+
+ _Semaphore_MP_Send_response_packet(
+ SEMAPHORE_MP_OBTAIN_RESPONSE,
+ the_proxy->Wait.id,
+ the_proxy
+ );
+
+}
+
+/*PAGE
+ *
+ * _Semaphore_MP_Send_extract_proxy
+ *
+ */
+
+void _Semaphore_MP_Send_extract_proxy (
+ void *argument
+)
+{
+ Thread_Control *the_thread = (Thread_Control *)argument;
+
+ _Semaphore_MP_Send_process_packet(
+ SEMAPHORE_MP_EXTRACT_PROXY,
+ the_thread->Wait.id,
+ (rtems_name) 0,
+ the_thread->Object.id
+ );
+
+}
+
+/*PAGE
+ *
+ * _Semaphore_MP_Get_packet
+ *
+ */
+
+Semaphore_MP_Packet *_Semaphore_MP_Get_packet ( void )
+{
+ return ( (Semaphore_MP_Packet *) _MPCI_Get_packet() );
+}
+
+/*PAGE
+ *
+ * _Semaphore_Core_mutex_mp_support
+ *
+ * Input parameters:
+ * the_thread - the remote thread the semaphore was surrendered to
+ * id - id of the surrendered semaphore
+ *
+ * Output parameters: NONE
+ */
+
+#if defined(RTEMS_MULTIPROCESSING)
+void _Semaphore_Core_mutex_mp_support (
+ Thread_Control *the_thread,
+ Objects_Id id
+)
+{
+ the_thread->receive_packet->return_code = RTEMS_SUCCESSFUL;
+
+ _Semaphore_MP_Send_response_packet(
+ SEMAPHORE_MP_OBTAIN_RESPONSE,
+ id,
+ the_thread
+ );
+}
+#endif
+
+
+/*PAGE
+ *
+ * _Semaphore_Core_semaphore_mp_support
+ *
+ * Input parameters:
+ * the_thread - the remote thread the semaphore was surrendered to
+ * id - id of the surrendered semaphore
+ *
+ * Output parameters: NONE
+ */
+
+#if defined(RTEMS_MULTIPROCESSING)
+void _Semaphore_Core_semaphore_mp_support (
+ Thread_Control *the_thread,
+ Objects_Id id
+)
+{
+ the_thread->receive_packet->return_code = RTEMS_SUCCESSFUL;
+
+ _Semaphore_MP_Send_response_packet(
+ SEMAPHORE_MP_OBTAIN_RESPONSE,
+ id,
+ the_thread
+ );
+}
+#endif
+/* end of file */
diff --git a/cpukit/rtems/src/semobtain.c b/cpukit/rtems/src/semobtain.c
new file mode 100644
index 0000000000..c376f612c2
--- /dev/null
+++ b/cpukit/rtems/src/semobtain.c
@@ -0,0 +1,121 @@
+/*
+ * Semaphore Manager
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the Semaphore Manager.
+ * This manager utilizes standard Dijkstra counting semaphores to provide
+ * synchronization and mutual exclusion capabilities.
+ *
+ * Directives provided are:
+ *
+ * + create a semaphore
+ * + get an ID of a semaphore
+ * + delete a semaphore
+ * + acquire a semaphore
+ * + release a semaphore
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/rtems/attr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/sem.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/coresem.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/score/sysstate.h>
+
+#include <rtems/score/interr.h>
+
+/*PAGE
+ *
+ * rtems_semaphore_obtain
+ *
+ * This directive allows a thread to acquire a semaphore.
+ *
+ * Input parameters:
+ * id - semaphore id
+ * option_set - wait option
+ * timeout - number of ticks to wait (0 means wait forever)
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_semaphore_obtain(
+ Objects_Id id,
+ uint32_t option_set,
+ rtems_interval timeout
+)
+{
+ register Semaphore_Control *the_semaphore;
+ Objects_Locations location;
+ boolean wait;
+ ISR_Level level;
+
+ the_semaphore = _Semaphore_Get_interrupt_disable( id, &location, &level );
+ switch ( location ) {
+ case OBJECTS_REMOTE:
+#if defined(RTEMS_MULTIPROCESSING)
+ return _Semaphore_MP_Send_request_packet(
+ SEMAPHORE_MP_OBTAIN_REQUEST,
+ id,
+ option_set,
+ timeout
+ );
+#endif
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ if ( _Options_Is_no_wait( option_set ) )
+ wait = FALSE;
+ else
+ wait = TRUE;
+
+ if ( !_Attributes_Is_counting_semaphore(the_semaphore->attribute_set) ) {
+ _CORE_mutex_Seize(
+ &the_semaphore->Core_control.mutex,
+ id,
+ wait,
+ timeout,
+ level
+ );
+ return _Semaphore_Translate_core_mutex_return_code(
+ _Thread_Executing->Wait.return_code );
+ }
+
+ /* must be a counting semaphore */
+ _CORE_semaphore_Seize_isr_disable(
+ &the_semaphore->Core_control.semaphore,
+ id,
+ wait,
+ timeout,
+ &level
+ );
+ return _Semaphore_Translate_core_semaphore_return_code(
+ _Thread_Executing->Wait.return_code );
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/semrelease.c b/cpukit/rtems/src/semrelease.c
new file mode 100644
index 0000000000..5d6b38e479
--- /dev/null
+++ b/cpukit/rtems/src/semrelease.c
@@ -0,0 +1,115 @@
+/*
+ * Semaphore Manager
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the Semaphore Manager.
+ * This manager utilizes standard Dijkstra counting semaphores to provide
+ * synchronization and mutual exclusion capabilities.
+ *
+ * Directives provided are:
+ *
+ * + create a semaphore
+ * + get an ID of a semaphore
+ * + delete a semaphore
+ * + acquire a semaphore
+ * + release a semaphore
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/rtems/attr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/sem.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/coresem.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/score/sysstate.h>
+
+#include <rtems/score/interr.h>
+
+/*PAGE
+ *
+ * rtems_semaphore_release
+ *
+ * This directive allows a thread to release a semaphore.
+ *
+ * Input parameters:
+ * id - semaphore id
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+#if defined(RTEMS_MULTIPROCESSING)
+#define MUTEX_MP_SUPPORT _Semaphore_Core_mutex_mp_support
+#else
+#define MUTEX_MP_SUPPORT NULL
+#endif
+
+rtems_status_code rtems_semaphore_release(
+ Objects_Id id
+)
+{
+ register Semaphore_Control *the_semaphore;
+ Objects_Locations location;
+ CORE_mutex_Status mutex_status;
+ CORE_semaphore_Status semaphore_status;
+
+ the_semaphore = _Semaphore_Get( id, &location );
+ switch ( location ) {
+
+ case OBJECTS_REMOTE:
+#if defined(RTEMS_MULTIPROCESSING)
+ return _Semaphore_MP_Send_request_packet(
+ SEMAPHORE_MP_RELEASE_REQUEST,
+ id,
+ 0, /* Not used */
+ MPCI_DEFAULT_TIMEOUT
+ );
+#endif
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ if ( !_Attributes_Is_counting_semaphore(the_semaphore->attribute_set) ) {
+ mutex_status = _CORE_mutex_Surrender(
+ &the_semaphore->Core_control.mutex,
+ id,
+ MUTEX_MP_SUPPORT
+ );
+ _Thread_Enable_dispatch();
+ return _Semaphore_Translate_core_mutex_return_code( mutex_status );
+ } else {
+ semaphore_status = _CORE_semaphore_Surrender(
+ &the_semaphore->Core_control.semaphore,
+ id,
+ MUTEX_MP_SUPPORT
+ );
+ _Thread_Enable_dispatch();
+ return
+ _Semaphore_Translate_core_semaphore_return_code( semaphore_status );
+ }
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/semtranslatereturncode.c b/cpukit/rtems/src/semtranslatereturncode.c
new file mode 100644
index 0000000000..d14ae9d474
--- /dev/null
+++ b/cpukit/rtems/src/semtranslatereturncode.c
@@ -0,0 +1,120 @@
+/*
+ * Semaphore Manager
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the Semaphore Manager.
+ * This manager utilizes standard Dijkstra counting semaphores to provide
+ * synchronization and mutual exclusion capabilities.
+ *
+ * Directives provided are:
+ *
+ * + create a semaphore
+ * + get an ID of a semaphore
+ * + delete a semaphore
+ * + acquire a semaphore
+ * + release a semaphore
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/rtems/attr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/sem.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/coresem.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/score/sysstate.h>
+
+#include <rtems/score/interr.h>
+
+/*PAGE
+ *
+ * _Semaphore_Translate_core_mutex_return_code
+ *
+ * Input parameters:
+ * the_mutex_status - mutex status code to translate
+ *
+ * Output parameters:
+ * rtems status code - translated RTEMS status code
+ *
+ */
+
+rtems_status_code _Semaphore_Translate_core_mutex_return_code_[] = {
+ RTEMS_SUCCESSFUL, /* CORE_MUTEX_STATUS_SUCCESSFUL */
+ RTEMS_UNSATISFIED, /* CORE_MUTEX_STATUS_UNSATISFIED_NOWAIT */
+ RTEMS_UNSATISFIED, /* CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED */
+ RTEMS_NOT_OWNER_OF_RESOURCE, /* CORE_MUTEX_STATUS_NOT_OWNER_OF_RESOURCE */
+ RTEMS_OBJECT_WAS_DELETED, /* CORE_MUTEX_WAS_DELETED */
+ RTEMS_TIMEOUT, /* CORE_MUTEX_TIMEOUT */
+ RTEMS_INTERNAL_ERROR, /* CORE_MUTEX_STATUS_CEILING_VIOLATED */
+};
+
+
+rtems_status_code _Semaphore_Translate_core_mutex_return_code (
+ uint32_t the_mutex_status
+)
+{
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( the_mutex_status == THREAD_STATUS_PROXY_BLOCKING )
+ return RTEMS_PROXY_BLOCKING;
+ else
+#endif
+ if ( the_mutex_status > CORE_MUTEX_STATUS_CEILING_VIOLATED )
+ return RTEMS_INTERNAL_ERROR;
+ else
+ return _Semaphore_Translate_core_mutex_return_code_[the_mutex_status];
+}
+
+/*PAGE
+ *
+ * _Semaphore_Translate_core_semaphore_return_code
+ *
+ * Input parameters:
+ * the_semaphore_status - semaphore status code to translate
+ *
+ * Output parameters:
+ * rtems status code - translated RTEMS status code
+ *
+ */
+
+rtems_status_code _Semaphore_Translate_core_semaphore_return_code_[] = {
+ RTEMS_SUCCESSFUL, /* CORE_SEMAPHORE_STATUS_SUCCESSFUL */
+ RTEMS_UNSATISFIED, /* CORE_SEMAPHORE_STATUS_UNSATISFIED_NOWAIT */
+ RTEMS_OBJECT_WAS_DELETED, /* CORE_SEMAPHORE_WAS_DELETED */
+ RTEMS_TIMEOUT, /* CORE_SEMAPHORE_TIMEOUT */
+ RTEMS_INTERNAL_ERROR, /* CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED */
+
+};
+
+rtems_status_code _Semaphore_Translate_core_semaphore_return_code (
+ uint32_t the_semaphore_status
+)
+{
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( the_semaphore_status == THREAD_STATUS_PROXY_BLOCKING )
+ return RTEMS_PROXY_BLOCKING;
+ else
+#endif
+ if ( the_semaphore_status > CORE_MUTEX_STATUS_CEILING_VIOLATED )
+ return RTEMS_INTERNAL_ERROR;
+ else
+ return _Semaphore_Translate_core_semaphore_return_code_[the_semaphore_status];
+}
diff --git a/cpukit/rtems/src/signal.c b/cpukit/rtems/src/signal.c
new file mode 100644
index 0000000000..49deff90d0
--- /dev/null
+++ b/cpukit/rtems/src/signal.c
@@ -0,0 +1,47 @@
+/*
+ * Signal Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/asr.h>
+#include <rtems/score/isr.h>
+#include <rtems/rtems/modes.h>
+#include <rtems/rtems/signal.h>
+#include <rtems/score/thread.h>
+#include <rtems/rtems/tasks.h>
+
+/*PAGE
+ *
+ * _Signal_Manager_initialization
+ *
+ * This routine initializes all signal manager related data structures.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ */
+
+void _Signal_Manager_initialization( void )
+{
+ /*
+ * Register the MP Process Packet routine.
+ */
+
+#if defined(RTEMS_MULTIPROCESSING)
+ _MPCI_Register_packet_processor(
+ MP_PACKET_SIGNAL,
+ _Signal_MP_Process_packet
+ );
+#endif
+}
diff --git a/cpukit/rtems/src/signalcatch.c b/cpukit/rtems/src/signalcatch.c
new file mode 100644
index 0000000000..3ed01e6280
--- /dev/null
+++ b/cpukit/rtems/src/signalcatch.c
@@ -0,0 +1,65 @@
+/*
+ * Signal Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/asr.h>
+#include <rtems/score/isr.h>
+#include <rtems/rtems/modes.h>
+#include <rtems/rtems/signal.h>
+#include <rtems/score/thread.h>
+#include <rtems/rtems/tasks.h>
+
+/*PAGE
+ *
+ * rtems_signal_catch
+ *
+ * This directive allows a thread to specify what action to take when
+ * catching signals.
+ *
+ * Input parameters:
+ * handler - address of asynchronous signal routine (asr)
+ * ( NULL indicates asr is invalid )
+ * mode_set - mode value for asr
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - always succeeds
+ */
+
+rtems_status_code rtems_signal_catch(
+ rtems_asr_entry asr_handler,
+ rtems_mode mode_set
+)
+{
+ Thread_Control *executing;
+ RTEMS_API_Control *api;
+ ASR_Information *asr;
+
+/* XXX normalize mode */
+ executing = _Thread_Executing;
+ api = (RTEMS_API_Control*)executing->API_Extensions[ THREAD_API_RTEMS ];
+ asr = &api->Signal;
+
+ _Thread_Disable_dispatch(); /* cannot reschedule while */
+ /* the thread is inconsistent */
+
+ if ( !_ASR_Is_null_handler( asr_handler ) ) {
+ asr->mode_set = mode_set;
+ asr->handler = asr_handler;
+ }
+ else
+ _ASR_Initialize( asr );
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/rtems/src/signalmp.c b/cpukit/rtems/src/signalmp.c
new file mode 100644
index 0000000000..d846237723
--- /dev/null
+++ b/cpukit/rtems/src/signalmp.c
@@ -0,0 +1,188 @@
+/*
+ * Multiprocessing Support for the Signal Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/score/mpci.h>
+#include <rtems/score/mppkt.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/signal.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/rtems/support.h>
+
+/*PAGE
+ *
+ * _Signal_MP_Send_process_packet
+ *
+ * This subprogram is not needed since there are no process
+ * packets to be sent by this manager.
+ *
+ */
+
+/*PAGE
+ *
+ * _Signal_MP_Send_request_packet
+ *
+ */
+
+rtems_status_code _Signal_MP_Send_request_packet (
+ Signal_MP_Remote_operations operation,
+ Objects_Id task_id,
+ rtems_signal_set signal_in
+)
+{
+ Signal_MP_Packet *the_packet;
+
+ switch ( operation ) {
+
+ case SIGNAL_MP_SEND_REQUEST:
+
+ the_packet = _Signal_MP_Get_packet();
+ the_packet->Prefix.the_class = MP_PACKET_SIGNAL;
+ the_packet->Prefix.length = sizeof ( Signal_MP_Packet );
+ the_packet->Prefix.to_convert = sizeof ( Signal_MP_Packet );
+ the_packet->operation = operation;
+ the_packet->Prefix.id = task_id;
+ the_packet->signal_in = signal_in;
+
+ return _MPCI_Send_request_packet(
+ rtems_get_node( task_id ),
+ &the_packet->Prefix,
+ STATES_READY /* Not used */
+ );
+ break;
+
+ case SIGNAL_MP_SEND_RESPONSE:
+ break;
+
+ }
+ /*
+ * The following line is included to satisfy compilers which
+ * produce warnings when a function does not end with a return.
+ */
+ return RTEMS_INTERNAL_ERROR;
+}
+
+/*PAGE
+ *
+ * _Signal_MP_Send_response_packet
+ *
+ */
+
+void _Signal_MP_Send_response_packet (
+ Signal_MP_Remote_operations operation,
+ Thread_Control *the_thread
+)
+{
+ Signal_MP_Packet *the_packet;
+
+ switch ( operation ) {
+
+ case SIGNAL_MP_SEND_RESPONSE:
+
+ the_packet = ( Signal_MP_Packet *) the_thread->receive_packet;
+
+/*
+ * The packet being returned already contains the class, length, and
+ * to_convert fields, therefore they are not set in this routine.
+ */
+ the_packet->operation = operation;
+ the_packet->Prefix.id = the_packet->Prefix.source_tid;
+
+ _MPCI_Send_response_packet(
+ rtems_get_node( the_packet->Prefix.source_tid ),
+ &the_packet->Prefix
+ );
+ break;
+
+ case SIGNAL_MP_SEND_REQUEST:
+ break;
+
+ }
+}
+
+/*PAGE
+ *
+ *
+ * _Signal_MP_Process_packet
+ *
+ */
+
+void _Signal_MP_Process_packet (
+ rtems_packet_prefix *the_packet_prefix
+)
+{
+ Signal_MP_Packet *the_packet;
+ Thread_Control *the_thread;
+
+ the_packet = (Signal_MP_Packet *) the_packet_prefix;
+
+ switch ( the_packet->operation ) {
+
+ case SIGNAL_MP_SEND_REQUEST:
+
+ the_packet->Prefix.return_code = rtems_signal_send(
+ the_packet->Prefix.id,
+ the_packet->signal_in
+ );
+
+ _Signal_MP_Send_response_packet(
+ SIGNAL_MP_SEND_RESPONSE,
+ _Thread_Executing
+ );
+ break;
+
+ case SIGNAL_MP_SEND_RESPONSE:
+
+ the_thread = _MPCI_Process_response( the_packet_prefix );
+
+ _MPCI_Return_packet( the_packet_prefix );
+ break;
+
+ }
+}
+
+/*PAGE
+ *
+ * _Signal_MP_Send_object_was_deleted
+ *
+ * This subprogram is not needed since there are no objects
+ * deleted by this manager.
+ *
+ */
+
+/*PAGE
+ *
+ * _Signal_MP_Send_extract_proxy
+ *
+ * This subprogram is not needed since there are no objects
+ * deleted by this manager.
+ *
+ */
+
+/*PAGE
+ *
+ * _Signal_MP_Get_packet
+ *
+ */
+
+Signal_MP_Packet *_Signal_MP_Get_packet ( void )
+{
+ return ( (Signal_MP_Packet *) _MPCI_Get_packet() );
+}
+
+/* end of file */
diff --git a/cpukit/rtems/src/signalsend.c b/cpukit/rtems/src/signalsend.c
new file mode 100644
index 0000000000..e5d512bcc2
--- /dev/null
+++ b/cpukit/rtems/src/signalsend.c
@@ -0,0 +1,87 @@
+/*
+ * Signal Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/asr.h>
+#include <rtems/score/isr.h>
+#include <rtems/rtems/modes.h>
+#include <rtems/rtems/signal.h>
+#include <rtems/score/thread.h>
+#include <rtems/rtems/tasks.h>
+
+/*PAGE
+ *
+ * rtems_signal_send
+ *
+ * This directive allows a thread to send signals to a thread.
+ *
+ * Input parameters:
+ * id - thread id
+ * signal_set - signal set
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_signal_send(
+ Objects_Id id,
+ rtems_signal_set signal_set
+)
+{
+ register Thread_Control *the_thread;
+ Objects_Locations location;
+ RTEMS_API_Control *api;
+ ASR_Information *asr;
+
+ the_thread = _Thread_Get( id, &location );
+ switch ( location ) {
+
+ case OBJECTS_REMOTE:
+#if defined(RTEMS_MULTIPROCESSING)
+ return _Signal_MP_Send_request_packet(
+ SIGNAL_MP_SEND_REQUEST,
+ id,
+ signal_set
+ );
+#endif
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
+ asr = &api->Signal;
+
+ if ( ! _ASR_Is_null_handler( asr->handler ) ) {
+ if ( asr->is_enabled ) {
+ _ASR_Post_signals( signal_set, &asr->signals_posted );
+
+ the_thread->do_post_task_switch_extension = TRUE;
+
+ if ( _ISR_Is_in_progress() && _Thread_Is_executing( the_thread ) )
+ _ISR_Signals_to_thread_executing = TRUE;
+ } else {
+ _ASR_Post_signals( signal_set, &asr->signals_pending );
+ }
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+ _Thread_Enable_dispatch();
+ return RTEMS_NOT_DEFINED;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/taskcreate.c b/cpukit/rtems/src/taskcreate.c
new file mode 100644
index 0000000000..7776af013e
--- /dev/null
+++ b/cpukit/rtems/src/taskcreate.c
@@ -0,0 +1,231 @@
+/*
+ * RTEMS Task Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/rtems/modes.h>
+#include <rtems/score/object.h>
+#include <rtems/score/stack.h>
+#include <rtems/score/states.h>
+#include <rtems/rtems/tasks.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+/*PAGE
+ *
+ * rtems_task_create
+ *
+ * This directive creates a thread by allocating and initializing a
+ * thread control block and a stack. The newly created thread is
+ * placed in the dormant state.
+ *
+ * Input parameters:
+ * name - user defined thread name
+ * initial_priority - thread priority
+ * stack_size - stack size in bytes
+ * initial_modes - initial thread mode
+ * attribute_set - thread attributes
+ * id - pointer to thread id
+ *
+ * Output parameters:
+ * id - thread id
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_task_create(
+ rtems_name name,
+ rtems_task_priority initial_priority,
+ uint32_t stack_size,
+ rtems_mode initial_modes,
+ rtems_attribute attribute_set,
+ Objects_Id *id
+)
+{
+ register Thread_Control *the_thread;
+ boolean is_fp;
+#if defined(RTEMS_MULTIPROCESSING)
+ Objects_MP_Control *the_global_object = NULL;
+ boolean is_global;
+#endif
+ boolean status;
+ rtems_attribute the_attribute_set;
+ Priority_Control core_priority;
+ RTEMS_API_Control *api;
+ ASR_Information *asr;
+
+
+ if ( !id )
+ return RTEMS_INVALID_ADDRESS;
+
+ if ( !rtems_is_name_valid( name ) )
+ return RTEMS_INVALID_NAME;
+
+ /*
+ * Core Thread Initialize insures we get the minimum amount of
+ * stack space.
+ */
+
+#if 0
+ if ( !_Stack_Is_enough( stack_size ) )
+ return RTEMS_INVALID_SIZE;
+#endif
+
+ /*
+ * Fix the attribute set to match the attributes which
+ * this processor (1) requires and (2) is able to support.
+ * First add in the required flags for attribute_set
+ * Typically this might include FP if the platform
+ * or application required all tasks to be fp aware.
+ * Then turn off the requested bits which are not supported.
+ */
+
+ the_attribute_set = _Attributes_Set( attribute_set, ATTRIBUTES_REQUIRED );
+ the_attribute_set =
+ _Attributes_Clear( the_attribute_set, ATTRIBUTES_NOT_SUPPORTED );
+
+ if ( _Attributes_Is_floating_point( the_attribute_set ) )
+ is_fp = TRUE;
+ else
+ is_fp = FALSE;
+
+ /*
+ * Validate the RTEMS API priority and convert it to the core priority range.
+ */
+
+ if ( !_Attributes_Is_system_task( the_attribute_set ) ) {
+ if ( !_RTEMS_tasks_Priority_is_valid( initial_priority ) )
+ return RTEMS_INVALID_PRIORITY;
+ }
+
+ core_priority = _RTEMS_tasks_Priority_to_Core( initial_priority );
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( _Attributes_Is_global( the_attribute_set ) ) {
+
+ is_global = TRUE;
+
+ if ( !_System_state_Is_multiprocessing )
+ return RTEMS_MP_NOT_CONFIGURED;
+
+ } else
+ is_global = FALSE;
+#endif
+
+ /*
+ * Make sure system is MP if this task is global
+ */
+
+ /*
+ * Disable dispatch for protection
+ */
+
+ _Thread_Disable_dispatch();
+
+ /*
+ * Allocate the thread control block and -- if the task is global --
+ * allocate a global object control block.
+ *
+ * NOTE: This routine does not use the combined allocate and open
+ * global object routine because this results in a lack of
+ * control over when memory is allocated and can be freed in
+ * the event of an error.
+ */
+
+ the_thread = _RTEMS_tasks_Allocate();
+
+ if ( !the_thread ) {
+ _Thread_Enable_dispatch();
+ return RTEMS_TOO_MANY;
+ }
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( is_global ) {
+ the_global_object = _Objects_MP_Allocate_global_object();
+
+ if ( _Objects_MP_Is_null_global_object( the_global_object ) ) {
+ _RTEMS_tasks_Free( the_thread );
+ _Thread_Enable_dispatch();
+ return RTEMS_TOO_MANY;
+ }
+ }
+#endif
+
+ /*
+ * Initialize the core thread for this task.
+ */
+
+ status = _Thread_Initialize(
+ &_RTEMS_tasks_Information,
+ the_thread,
+ NULL,
+ stack_size,
+ is_fp,
+ core_priority,
+ _Modes_Is_preempt(initial_modes) ? TRUE : FALSE,
+ _Modes_Is_timeslice(initial_modes) ?
+ THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE :
+ THREAD_CPU_BUDGET_ALGORITHM_NONE,
+ NULL, /* no budget algorithm callout */
+ _Modes_Get_interrupt_level(initial_modes),
+ (Objects_Name) name
+ );
+
+ if ( !status ) {
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( is_global )
+ _Objects_MP_Free_global_object( the_global_object );
+#endif
+ _RTEMS_tasks_Free( the_thread );
+ _Thread_Enable_dispatch();
+ return RTEMS_UNSATISFIED;
+ }
+
+ api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
+ asr = &api->Signal;
+
+ asr->is_enabled = _Modes_Is_asr_disabled(initial_modes) ? FALSE : TRUE;
+
+ *id = the_thread->Object.id;
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( is_global ) {
+
+ the_thread->is_global = TRUE;
+
+ _Objects_MP_Open(
+ &_RTEMS_tasks_Information,
+ the_global_object,
+ name,
+ the_thread->Object.id
+ );
+
+ _RTEMS_tasks_MP_Send_process_packet(
+ RTEMS_TASKS_MP_ANNOUNCE_CREATE,
+ the_thread->Object.id,
+ name
+ );
+
+ }
+#endif
+
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/rtems/src/taskdelete.c b/cpukit/rtems/src/taskdelete.c
new file mode 100644
index 0000000000..b0d4b6572d
--- /dev/null
+++ b/cpukit/rtems/src/taskdelete.c
@@ -0,0 +1,100 @@
+/*
+ * RTEMS Task Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/rtems/modes.h>
+#include <rtems/score/object.h>
+#include <rtems/score/stack.h>
+#include <rtems/score/states.h>
+#include <rtems/rtems/tasks.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+/*PAGE
+ *
+ * rtems_task_delete
+ *
+ * This directive allows a thread to delete itself or the thread
+ * identified in the id field. The executive halts execution
+ * of the thread and frees the thread control block.
+ *
+ * Input parameters:
+ * id - thread id
+ *
+ * Output parameters:
+ * nothing - if id is the requesting thread (always succeeds)
+ * RTEMS_SUCCESSFUL - if successful and id is
+ * not the requesting thread
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_task_delete(
+ Objects_Id id
+)
+{
+ register Thread_Control *the_thread;
+ Objects_Locations location;
+ Objects_Information *the_information;
+
+ the_thread = _Thread_Get( id, &location );
+ switch ( location ) {
+
+ case OBJECTS_REMOTE:
+#if defined(RTEMS_MULTIPROCESSING)
+ _Thread_Dispatch();
+ return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
+#endif
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ the_information = _Objects_Get_information( the_thread->Object.id );
+
+ if ( !the_information ) {
+ _Thread_Enable_dispatch();
+ return RTEMS_INVALID_ID;
+ /* This should never happen if _Thread_Get() works right */
+ }
+
+ _Thread_Close( the_information, the_thread );
+
+ _RTEMS_tasks_Free( the_thread );
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( the_thread->is_global ) {
+
+ _Objects_MP_Close( &_RTEMS_tasks_Information, the_thread->Object.id );
+
+ _RTEMS_tasks_MP_Send_process_packet(
+ RTEMS_TASKS_MP_ANNOUNCE_DELETE,
+ the_thread->Object.id,
+ 0 /* Not used */
+ );
+ }
+#endif
+
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/taskgetnote.c b/cpukit/rtems/src/taskgetnote.c
new file mode 100644
index 0000000000..94b452ad70
--- /dev/null
+++ b/cpukit/rtems/src/taskgetnote.c
@@ -0,0 +1,108 @@
+/*
+ * RTEMS Task Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/rtems/modes.h>
+#include <rtems/score/object.h>
+#include <rtems/score/stack.h>
+#include <rtems/score/states.h>
+#include <rtems/rtems/tasks.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+/*PAGE
+ *
+ * rtems_task_get_note
+ *
+ * This directive obtains the note from the specified notepad
+ * of the specified thread.
+ *
+ * Input parameters:
+ * id - thread id
+ * notepad - notepad number
+ * note - pointer to note
+ *
+ * Output parameters:
+ * note - filled in if successful
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_task_get_note(
+ Objects_Id id,
+ uint32_t notepad,
+ uint32_t *note
+)
+{
+ register Thread_Control *the_thread;
+ Objects_Locations location;
+ RTEMS_API_Control *api;
+
+ if ( !note )
+ return RTEMS_INVALID_ADDRESS;
+
+ /*
+ * NOTE: There is no check for < RTEMS_NOTEPAD_FIRST because that would
+ * be checking an unsigned number for being negative.
+ */
+
+ if ( notepad > RTEMS_NOTEPAD_LAST )
+ return RTEMS_INVALID_NUMBER;
+
+ /*
+ * Optimize the most likely case to avoid the Thread_Dispatch.
+ */
+
+ if ( _Objects_Are_ids_equal( id, OBJECTS_ID_OF_SELF ) ||
+ _Objects_Are_ids_equal( id, _Thread_Executing->Object.id ) ) {
+ api = _Thread_Executing->API_Extensions[ THREAD_API_RTEMS ];
+ *note = api->Notepads[ notepad ];
+ return RTEMS_SUCCESSFUL;
+ }
+
+ the_thread = _Thread_Get( id, &location );
+ switch ( location ) {
+
+ case OBJECTS_REMOTE:
+#if defined(RTEMS_MULTIPROCESSING)
+ _Thread_Executing->Wait.return_argument = note;
+
+ return _RTEMS_tasks_MP_Send_request_packet(
+ RTEMS_TASKS_MP_GET_NOTE_REQUEST,
+ id,
+ 0, /* Not used */
+ notepad,
+ 0 /* Not used */
+ );
+#endif
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
+ *note = api->Notepads[ notepad ];
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/taskident.c b/cpukit/rtems/src/taskident.c
new file mode 100644
index 0000000000..6438bf1db1
--- /dev/null
+++ b/cpukit/rtems/src/taskident.c
@@ -0,0 +1,70 @@
+/*
+ * RTEMS Task Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/rtems/modes.h>
+#include <rtems/score/object.h>
+#include <rtems/score/stack.h>
+#include <rtems/score/states.h>
+#include <rtems/rtems/tasks.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+/*PAGE
+ *
+ * rtems_task_ident
+ *
+ * This directive returns the system ID associated with
+ * the thread name.
+ *
+ * Input parameters:
+ * name - user defined thread name
+ * node - node(s) to be searched
+ * id - pointer to thread id
+ *
+ * Output parameters:
+ * *id - thread id
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_task_ident(
+ rtems_name name,
+ uint32_t node,
+ Objects_Id *id
+)
+{
+ Objects_Name_or_id_lookup_errors status;
+
+ if ( name == OBJECTS_ID_OF_SELF ) {
+ *id = _Thread_Executing->Object.id;
+ return RTEMS_SUCCESSFUL;
+ }
+
+ status = _Objects_Name_to_id(
+ &_RTEMS_tasks_Information,
+ (Objects_Name) name,
+ node,
+ id
+ );
+
+ return _Status_Object_name_errors_to_status[ status ];
+}
diff --git a/cpukit/rtems/src/taskinitusers.c b/cpukit/rtems/src/taskinitusers.c
new file mode 100644
index 0000000000..3191e1ac59
--- /dev/null
+++ b/cpukit/rtems/src/taskinitusers.c
@@ -0,0 +1,83 @@
+/*
+ * RTEMS Task Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/rtems/modes.h>
+#include <rtems/score/object.h>
+#include <rtems/score/stack.h>
+#include <rtems/score/states.h>
+#include <rtems/rtems/tasks.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+/*PAGE
+ *
+ * _RTEMS_tasks_Initialize_user_tasks
+ *
+ * This routine creates and starts all configured user
+ * initialzation threads.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ */
+
+void _RTEMS_tasks_Initialize_user_tasks( void )
+{
+ uint32_t index;
+ uint32_t maximum;
+ rtems_id id;
+ rtems_status_code return_value;
+ rtems_initialization_tasks_table *user_tasks;
+
+ /*
+ * NOTE: This is slightly different from the Ada implementation.
+ */
+
+ user_tasks = _RTEMS_tasks_User_initialization_tasks;
+ maximum = _RTEMS_tasks_Number_of_initialization_tasks;
+
+ if ( !user_tasks || maximum == 0 )
+ return;
+
+ for ( index=0 ; index < maximum ; index++ ) {
+ return_value = rtems_task_create(
+ user_tasks[ index ].name,
+ user_tasks[ index ].initial_priority,
+ user_tasks[ index ].stack_size,
+ user_tasks[ index ].mode_set,
+ user_tasks[ index ].attribute_set,
+ &id
+ );
+
+ if ( !rtems_is_status_successful( return_value ) )
+ _Internal_error_Occurred( INTERNAL_ERROR_RTEMS_API, TRUE, return_value );
+
+ return_value = rtems_task_start(
+ id,
+ user_tasks[ index ].entry_point,
+ user_tasks[ index ].argument
+ );
+
+ if ( !rtems_is_status_successful( return_value ) )
+ _Internal_error_Occurred( INTERNAL_ERROR_RTEMS_API, TRUE, return_value );
+ }
+}
diff --git a/cpukit/rtems/src/taskissuspended.c b/cpukit/rtems/src/taskissuspended.c
new file mode 100644
index 0000000000..d753ba4dcd
--- /dev/null
+++ b/cpukit/rtems/src/taskissuspended.c
@@ -0,0 +1,77 @@
+/*
+ * RTEMS Task Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/rtems/modes.h>
+#include <rtems/score/object.h>
+#include <rtems/score/stack.h>
+#include <rtems/score/states.h>
+#include <rtems/rtems/tasks.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+/*PAGE
+ *
+ * rtems_task_is_suspended
+ *
+ * This directive returns a status indicating whether or not
+ * the specified task is suspended.
+ *
+ * Input parameters:
+ * id - thread id
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful and not suspended
+ * RTEMS_ALREADY_SUSPENDED - if successful and suspended
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_task_is_suspended(
+ Objects_Id id
+)
+{
+ register Thread_Control *the_thread;
+ Objects_Locations location;
+
+ the_thread = _Thread_Get( id, &location );
+ switch ( location ) {
+
+ case OBJECTS_REMOTE:
+
+#if defined(RTEMS_MULTIPROCESSING)
+ _Thread_Dispatch();
+ return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
+#endif
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ if ( !_States_Is_suspended( the_thread->current_state ) ) {
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+ _Thread_Enable_dispatch();
+ return RTEMS_ALREADY_SUSPENDED;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/taskmode.c b/cpukit/rtems/src/taskmode.c
new file mode 100644
index 0000000000..478773681e
--- /dev/null
+++ b/cpukit/rtems/src/taskmode.c
@@ -0,0 +1,125 @@
+/*
+ * RTEMS Task Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/rtems/modes.h>
+#include <rtems/score/object.h>
+#include <rtems/score/stack.h>
+#include <rtems/score/states.h>
+#include <rtems/rtems/tasks.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+/*PAGE
+ *
+ * rtems_task_mode
+ *
+ * This directive enables and disables several modes of
+ * execution for the requesting thread.
+ *
+ * Input parameters:
+ * mode_set - new mode
+ * mask - mask
+ * previous_mode_set - address of previous mode set
+ *
+ * Output:
+ * *previous_mode_set - previous mode set
+ * always return RTEMS_SUCCESSFUL;
+ */
+
+rtems_status_code rtems_task_mode(
+ rtems_mode mode_set,
+ rtems_mode mask,
+ rtems_mode *previous_mode_set
+)
+{
+ Thread_Control *executing;
+ RTEMS_API_Control *api;
+ ASR_Information *asr;
+ boolean is_asr_enabled = FALSE;
+ boolean needs_asr_dispatching = FALSE;
+ rtems_mode old_mode;
+
+ if ( !previous_mode_set )
+ return RTEMS_INVALID_ADDRESS;
+
+ executing = _Thread_Executing;
+ api = executing->API_Extensions[ THREAD_API_RTEMS ];
+ asr = &api->Signal;
+
+ old_mode = (executing->is_preemptible) ? RTEMS_PREEMPT : RTEMS_NO_PREEMPT;
+
+ if ( executing->budget_algorithm == THREAD_CPU_BUDGET_ALGORITHM_NONE )
+ old_mode |= RTEMS_NO_TIMESLICE;
+ else
+ old_mode |= RTEMS_TIMESLICE;
+
+ old_mode |= (asr->is_enabled) ? RTEMS_ASR : RTEMS_NO_ASR;
+ old_mode |= _ISR_Get_level();
+
+ *previous_mode_set = old_mode;
+
+ /*
+ * These are generic thread scheduling characteristics.
+ */
+
+ if ( mask & RTEMS_PREEMPT_MASK )
+ executing->is_preemptible = _Modes_Is_preempt(mode_set) ? TRUE : FALSE;
+
+ if ( mask & RTEMS_TIMESLICE_MASK ) {
+ if ( _Modes_Is_timeslice(mode_set) )
+ executing->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE;
+ else
+ executing->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_NONE;
+ }
+
+ /*
+ * Set the new interrupt level
+ */
+
+ if ( mask & RTEMS_INTERRUPT_MASK )
+ _Modes_Set_interrupt_level( mode_set );
+
+ /*
+ * This is specific to the RTEMS API
+ */
+
+ is_asr_enabled = FALSE;
+ needs_asr_dispatching = FALSE;
+
+ if ( mask & RTEMS_ASR_MASK ) {
+ is_asr_enabled = _Modes_Is_asr_disabled( mode_set ) ? FALSE : TRUE;
+ if ( is_asr_enabled != asr->is_enabled ) {
+ asr->is_enabled = is_asr_enabled;
+ _ASR_Swap_signals( asr );
+ if ( _ASR_Are_signals_pending( asr ) ) {
+ needs_asr_dispatching = TRUE;
+ executing->do_post_task_switch_extension = TRUE;
+ }
+ }
+ }
+
+ if ( _System_state_Is_up(_System_state_Current) )
+ if ( _Thread_Evaluate_mode() || needs_asr_dispatching )
+ _Thread_Dispatch();
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/rtems/src/taskmp.c b/cpukit/rtems/src/taskmp.c
new file mode 100644
index 0000000000..c1d10c0819
--- /dev/null
+++ b/cpukit/rtems/src/taskmp.c
@@ -0,0 +1,339 @@
+/*
+ * Multiprocessing Support for the RTEMS Task Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/score/mpci.h>
+#include <rtems/score/mppkt.h>
+#include <rtems/score/object.h>
+#include <rtems/rtems/options.h>
+#include <rtems/rtems/tasks.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/rtems/support.h>
+
+/*PAGE
+ *
+ * _RTEMS_tasks_MP_Send_process_packet
+ *
+ */
+
+void _RTEMS_tasks_MP_Send_process_packet (
+ RTEMS_tasks_MP_Remote_operations operation,
+ Objects_Id task_id,
+ rtems_name name
+)
+{
+ RTEMS_tasks_MP_Packet *the_packet;
+
+ switch ( operation ) {
+
+ case RTEMS_TASKS_MP_ANNOUNCE_CREATE:
+ case RTEMS_TASKS_MP_ANNOUNCE_DELETE:
+
+ the_packet = _RTEMS_tasks_MP_Get_packet();
+ the_packet->Prefix.the_class = MP_PACKET_TASKS;
+ the_packet->Prefix.length = sizeof ( RTEMS_tasks_MP_Packet );
+ the_packet->Prefix.to_convert = sizeof ( RTEMS_tasks_MP_Packet );
+ the_packet->operation = operation;
+ the_packet->Prefix.id = task_id;
+ the_packet->name = name;
+
+ _MPCI_Send_process_packet( MPCI_ALL_NODES, &the_packet->Prefix );
+ break;
+
+ case RTEMS_TASKS_MP_SUSPEND_REQUEST:
+ case RTEMS_TASKS_MP_SUSPEND_RESPONSE:
+ case RTEMS_TASKS_MP_RESUME_REQUEST:
+ case RTEMS_TASKS_MP_RESUME_RESPONSE:
+ case RTEMS_TASKS_MP_SET_PRIORITY_REQUEST:
+ case RTEMS_TASKS_MP_SET_PRIORITY_RESPONSE:
+ case RTEMS_TASKS_MP_GET_NOTE_REQUEST:
+ case RTEMS_TASKS_MP_GET_NOTE_RESPONSE:
+ case RTEMS_TASKS_MP_SET_NOTE_REQUEST:
+ case RTEMS_TASKS_MP_SET_NOTE_RESPONSE:
+ break;
+ }
+}
+
+/*PAGE
+ *
+ * _RTEMS_tasks_MP_Send_request_packet
+ *
+ */
+
+rtems_status_code _RTEMS_tasks_MP_Send_request_packet (
+ RTEMS_tasks_MP_Remote_operations operation,
+ Objects_Id task_id,
+ rtems_task_priority new_priority,
+ uint32_t notepad,
+ uint32_t note
+)
+{
+ RTEMS_tasks_MP_Packet *the_packet;
+
+ switch ( operation ) {
+
+ case RTEMS_TASKS_MP_SUSPEND_REQUEST:
+ case RTEMS_TASKS_MP_RESUME_REQUEST:
+ case RTEMS_TASKS_MP_SET_PRIORITY_REQUEST:
+ case RTEMS_TASKS_MP_GET_NOTE_REQUEST:
+ case RTEMS_TASKS_MP_SET_NOTE_REQUEST:
+
+ the_packet = _RTEMS_tasks_MP_Get_packet();
+ the_packet->Prefix.the_class = MP_PACKET_TASKS;
+ the_packet->Prefix.length = sizeof ( RTEMS_tasks_MP_Packet );
+ the_packet->Prefix.to_convert = sizeof ( RTEMS_tasks_MP_Packet );
+ the_packet->operation = operation;
+ the_packet->Prefix.id = task_id;
+ the_packet->the_priority = new_priority;
+ the_packet->notepad = notepad;
+ the_packet->note = note;
+
+ return _MPCI_Send_request_packet(
+ rtems_get_node( task_id ),
+ &the_packet->Prefix,
+ STATES_READY /* Not used */
+ );
+ break;
+
+ case RTEMS_TASKS_MP_ANNOUNCE_CREATE:
+ case RTEMS_TASKS_MP_ANNOUNCE_DELETE:
+ case RTEMS_TASKS_MP_SUSPEND_RESPONSE:
+ case RTEMS_TASKS_MP_RESUME_RESPONSE:
+ case RTEMS_TASKS_MP_SET_PRIORITY_RESPONSE:
+ case RTEMS_TASKS_MP_GET_NOTE_RESPONSE:
+ case RTEMS_TASKS_MP_SET_NOTE_RESPONSE:
+ break;
+
+ }
+ /*
+ * The following line is included to satisfy compilers which
+ * produce warnings when a function does not end with a return.
+ */
+ return RTEMS_SUCCESSFUL;
+}
+
+/*PAGE
+ *
+ * _RTEMS_tasks_MP_Send_response_packet
+ *
+ */
+
+void _RTEMS_tasks_MP_Send_response_packet (
+ RTEMS_tasks_MP_Remote_operations operation,
+ Thread_Control *the_thread
+)
+{
+ RTEMS_tasks_MP_Packet *the_packet;
+
+ switch ( operation ) {
+
+ case RTEMS_TASKS_MP_SUSPEND_RESPONSE:
+ case RTEMS_TASKS_MP_RESUME_RESPONSE:
+ case RTEMS_TASKS_MP_SET_PRIORITY_RESPONSE:
+ case RTEMS_TASKS_MP_GET_NOTE_RESPONSE:
+ case RTEMS_TASKS_MP_SET_NOTE_RESPONSE:
+
+ the_packet = (RTEMS_tasks_MP_Packet *) the_thread->receive_packet;
+
+/*
+ * The packet being returned already contains the class, length, and
+ * to_convert fields, therefore they are not set in this routine.
+ */
+ the_packet->operation = operation;
+ the_packet->Prefix.id = the_packet->Prefix.source_tid;
+
+ _MPCI_Send_response_packet(
+ rtems_get_node( the_packet->Prefix.source_tid ),
+ &the_packet->Prefix
+ );
+ break;
+
+ case RTEMS_TASKS_MP_ANNOUNCE_CREATE:
+ case RTEMS_TASKS_MP_ANNOUNCE_DELETE:
+ case RTEMS_TASKS_MP_SUSPEND_REQUEST:
+ case RTEMS_TASKS_MP_RESUME_REQUEST:
+ case RTEMS_TASKS_MP_SET_PRIORITY_REQUEST:
+ case RTEMS_TASKS_MP_GET_NOTE_REQUEST:
+ case RTEMS_TASKS_MP_SET_NOTE_REQUEST:
+ break;
+
+ }
+}
+
+/*PAGE
+ *
+ *
+ * _RTEMS_tasks_MP_Process_packet
+ *
+ */
+
+void _RTEMS_tasks_MP_Process_packet (
+ rtems_packet_prefix *the_packet_prefix
+)
+{
+ RTEMS_tasks_MP_Packet *the_packet;
+ Thread_Control *the_thread;
+ boolean ignored;
+
+ the_packet = (RTEMS_tasks_MP_Packet *) the_packet_prefix;
+
+ switch ( the_packet->operation ) {
+
+ case RTEMS_TASKS_MP_ANNOUNCE_CREATE:
+
+ ignored = _Objects_MP_Allocate_and_open(
+ &_RTEMS_tasks_Information,
+ the_packet->name,
+ the_packet->Prefix.id,
+ TRUE
+ );
+
+ _MPCI_Return_packet( the_packet_prefix );
+ break;
+
+ case RTEMS_TASKS_MP_ANNOUNCE_DELETE:
+
+ _Objects_MP_Close( &_RTEMS_tasks_Information, the_packet->Prefix.id );
+
+ _MPCI_Return_packet( the_packet_prefix );
+ break;
+
+ case RTEMS_TASKS_MP_SUSPEND_REQUEST:
+
+ the_packet->Prefix.return_code = rtems_task_suspend(
+ the_packet->Prefix.id
+ );
+
+ _RTEMS_tasks_MP_Send_response_packet(
+ RTEMS_TASKS_MP_SUSPEND_RESPONSE,
+ _Thread_Executing
+ );
+ break;
+
+ case RTEMS_TASKS_MP_SUSPEND_RESPONSE:
+ case RTEMS_TASKS_MP_RESUME_RESPONSE:
+ case RTEMS_TASKS_MP_SET_NOTE_RESPONSE:
+
+ the_thread = _MPCI_Process_response( the_packet_prefix );
+
+ _MPCI_Return_packet( the_packet_prefix );
+ break;
+
+ case RTEMS_TASKS_MP_RESUME_REQUEST:
+
+ the_packet->Prefix.return_code = rtems_task_resume(
+ the_packet->Prefix.id
+ );
+
+ _RTEMS_tasks_MP_Send_response_packet(
+ RTEMS_TASKS_MP_RESUME_RESPONSE,
+ _Thread_Executing
+ );
+ break;
+
+ case RTEMS_TASKS_MP_SET_PRIORITY_REQUEST:
+
+ the_packet->Prefix.return_code = rtems_task_set_priority(
+ the_packet->Prefix.id,
+ the_packet->the_priority,
+ &the_packet->the_priority
+ );
+
+ _RTEMS_tasks_MP_Send_response_packet(
+ RTEMS_TASKS_MP_SET_PRIORITY_RESPONSE,
+ _Thread_Executing
+ );
+ break;
+
+ case RTEMS_TASKS_MP_SET_PRIORITY_RESPONSE:
+
+ the_thread = _MPCI_Process_response( the_packet_prefix );
+
+ *(rtems_task_priority *)the_thread->Wait.return_argument =
+ the_packet->the_priority;
+
+ _MPCI_Return_packet( the_packet_prefix );
+ break;
+
+ case RTEMS_TASKS_MP_GET_NOTE_REQUEST:
+
+ the_packet->Prefix.return_code = rtems_task_get_note(
+ the_packet->Prefix.id,
+ the_packet->notepad,
+ &the_packet->note
+ );
+
+ _RTEMS_tasks_MP_Send_response_packet(
+ RTEMS_TASKS_MP_GET_NOTE_RESPONSE,
+ _Thread_Executing
+ );
+ break;
+
+ case RTEMS_TASKS_MP_GET_NOTE_RESPONSE:
+
+ the_thread = _MPCI_Process_response( the_packet_prefix );
+
+ *(uint32_t *)the_thread->Wait.return_argument = the_packet->note;
+
+ _MPCI_Return_packet( the_packet_prefix );
+ break;
+
+ case RTEMS_TASKS_MP_SET_NOTE_REQUEST:
+
+ the_packet->Prefix.return_code = rtems_task_set_note(
+ the_packet->Prefix.id,
+ the_packet->notepad,
+ the_packet->note
+ );
+
+ _RTEMS_tasks_MP_Send_response_packet(
+ RTEMS_TASKS_MP_SET_NOTE_RESPONSE,
+ _Thread_Executing
+ );
+ break;
+ }
+}
+
+/*PAGE
+ *
+ * _RTEMS_tasks_MP_Send_object_was_deleted
+ *
+ * This routine is not neededby the Tasks since a task
+ * cannot be globally deleted.
+ *
+ */
+
+/*PAGE
+ *
+ * _RTEMS_tasks_MP_Send_extract_proxy
+ *
+ * This routine is not neededby the Tasks since a task
+ * cannot be globally deleted.
+ *
+ */
+
+/*PAGE
+ *
+ * _RTEMS_tasks_MP_Get_packet
+ *
+ */
+
+RTEMS_tasks_MP_Packet *_RTEMS_tasks_MP_Get_packet ( void )
+{
+ return (RTEMS_tasks_MP_Packet *) _MPCI_Get_packet();
+}
+
+/* end of file */
diff --git a/cpukit/rtems/src/taskrestart.c b/cpukit/rtems/src/taskrestart.c
new file mode 100644
index 0000000000..932dc976af
--- /dev/null
+++ b/cpukit/rtems/src/taskrestart.c
@@ -0,0 +1,79 @@
+/*
+ * RTEMS Task Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/rtems/modes.h>
+#include <rtems/score/object.h>
+#include <rtems/score/stack.h>
+#include <rtems/score/states.h>
+#include <rtems/rtems/tasks.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+/*PAGE
+ *
+ * rtems_task_restart
+ *
+ * This directive readies the specified thread. It restores
+ * the thread environment to the original values established
+ * at thread creation and start time. A thread can be restarted
+ * from any state except the dormant state.
+ *
+ * Input parameters:
+ * id - thread id
+ * argument - thread argument
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_task_restart(
+ Objects_Id id,
+ uint32_t argument
+)
+{
+ register Thread_Control *the_thread;
+ Objects_Locations location;
+
+ the_thread = _Thread_Get( id, &location );
+ switch ( location ) {
+
+ case OBJECTS_REMOTE:
+#if defined(RTEMS_MULTIPROCESSING)
+ _Thread_Dispatch();
+ return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
+#endif
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ if ( _Thread_Restart( the_thread, NULL, argument ) ) {
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+ _Thread_Enable_dispatch();
+ return RTEMS_INCORRECT_STATE;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/taskresume.c b/cpukit/rtems/src/taskresume.c
new file mode 100644
index 0000000000..440dbaac66
--- /dev/null
+++ b/cpukit/rtems/src/taskresume.c
@@ -0,0 +1,81 @@
+/*
+ * RTEMS Task Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/rtems/modes.h>
+#include <rtems/score/object.h>
+#include <rtems/score/stack.h>
+#include <rtems/score/states.h>
+#include <rtems/rtems/tasks.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+/*PAGE
+ *
+ * rtems_task_resume
+ *
+ * This directive will remove the specified thread
+ * from the suspended state.
+ *
+ * Input parameters:
+ * id - thread id
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_task_resume(
+ Objects_Id id
+)
+{
+ register Thread_Control *the_thread;
+ Objects_Locations location;
+
+ the_thread = _Thread_Get( id, &location );
+ switch ( location ) {
+
+ case OBJECTS_REMOTE:
+#if defined(RTEMS_MULTIPROCESSING)
+ return _RTEMS_tasks_MP_Send_request_packet(
+ RTEMS_TASKS_MP_RESUME_REQUEST,
+ id,
+ 0, /* Not used */
+ 0, /* Not used */
+ 0 /* Not used */
+ );
+#endif
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ if ( _States_Is_suspended( the_thread->current_state ) ) {
+ _Thread_Resume( the_thread, TRUE );
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+ _Thread_Enable_dispatch();
+ return RTEMS_INCORRECT_STATE;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/tasks.c b/cpukit/rtems/src/tasks.c
new file mode 100644
index 0000000000..dc10c10803
--- /dev/null
+++ b/cpukit/rtems/src/tasks.c
@@ -0,0 +1,290 @@
+/*
+ * RTEMS Task Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/rtems/modes.h>
+#include <rtems/score/object.h>
+#include <rtems/score/stack.h>
+#include <rtems/score/states.h>
+#include <rtems/rtems/tasks.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+/*PAGE
+ *
+ * _RTEMS_tasks_Create_extension
+ *
+ * This routine is an extension routine that is invoked as part
+ * of creating any type of task or thread in the system. If the
+ * task is created via another API, then this routine is invoked
+ * and this API given the opportunity to initialize its extension
+ * area.
+ */
+
+boolean _RTEMS_tasks_Create_extension(
+ Thread_Control *executing,
+ Thread_Control *created
+)
+{
+ RTEMS_API_Control *api;
+ int i;
+
+ api = _Workspace_Allocate( sizeof( RTEMS_API_Control ) );
+
+ if ( !api )
+ return FALSE;
+
+ created->API_Extensions[ THREAD_API_RTEMS ] = api;
+
+ api->pending_events = EVENT_SETS_NONE_PENDING;
+ _ASR_Initialize( &api->Signal );
+ created->task_variables = NULL;
+
+ for (i=0; i < RTEMS_NUMBER_NOTEPADS; i++)
+ api->Notepads[i] = 0;
+
+ return TRUE;
+}
+
+/*PAGE
+ *
+ * _RTEMS_tasks_Start_extension
+ *
+ * This extension routine is invoked when a task is started for the
+ * first time.
+ */
+
+User_extensions_routine _RTEMS_tasks_Start_extension(
+ Thread_Control *executing,
+ Thread_Control *started
+)
+{
+ RTEMS_API_Control *api;
+
+ api = started->API_Extensions[ THREAD_API_RTEMS ];
+
+ api->pending_events = EVENT_SETS_NONE_PENDING;
+
+ _ASR_Initialize( &api->Signal );
+}
+
+/*PAGE
+ *
+ * _RTEMS_tasks_Delete_extension
+ *
+ * This extension routine is invoked when a task is deleted.
+ */
+
+User_extensions_routine _RTEMS_tasks_Delete_extension(
+ Thread_Control *executing,
+ Thread_Control *deleted
+)
+{
+ rtems_task_variable_t *tvp, *next;
+
+ /*
+ * Free per task variable memory
+ */
+
+ tvp = deleted->task_variables;
+ deleted->task_variables = NULL;
+ while (tvp) {
+ next = tvp->next;
+ if (tvp->dtor)
+ (*tvp->dtor)(*tvp->ptr);
+ if (_Thread_Is_executing(deleted))
+ *tvp->ptr = tvp->gval;
+ _Workspace_Free( tvp );
+ tvp = next;
+ }
+
+ /*
+ * Free API specific memory
+ */
+
+ (void) _Workspace_Free( deleted->API_Extensions[ THREAD_API_RTEMS ] );
+ deleted->API_Extensions[ THREAD_API_RTEMS ] = NULL;
+}
+
+/*PAGE
+ *
+ * _RTEMS_tasks_Switch_extension
+ *
+ * This extension routine is invoked at each context switch.
+ */
+
+void _RTEMS_tasks_Switch_extension(
+ Thread_Control *executing,
+ Thread_Control *heir
+)
+{
+ rtems_task_variable_t *tvp;
+
+ /*
+ * Per Task Variables
+ */
+
+ tvp = executing->task_variables;
+ while (tvp) {
+ tvp->tval = *tvp->ptr;
+ *tvp->ptr = tvp->gval;
+ tvp = tvp->next;
+ }
+
+ tvp = heir->task_variables;
+ while (tvp) {
+ tvp->gval = *tvp->ptr;
+ *tvp->ptr = tvp->tval;
+ tvp = tvp->next;
+ }
+}
+
+/*PAGE
+ *
+ * _RTEMS_tasks_Post_switch_extension
+ *
+ * This extension routine is invoked at each context switch.
+ */
+
+void _RTEMS_tasks_Post_switch_extension(
+ Thread_Control *executing
+)
+{
+ ISR_Level level;
+ RTEMS_API_Control *api;
+ ASR_Information *asr;
+ rtems_signal_set signal_set;
+ Modes_Control prev_mode;
+
+ api = executing->API_Extensions[ THREAD_API_RTEMS ];
+
+ /*
+ * Signal Processing
+ */
+
+ asr = &api->Signal;
+
+ _ISR_Disable( level );
+ signal_set = asr->signals_posted;
+ asr->signals_posted = 0;
+ _ISR_Enable( level );
+
+
+ if ( !signal_set ) /* similar to _ASR_Are_signals_pending( asr ) */
+ return;
+
+ asr->nest_level += 1;
+ rtems_task_mode( asr->mode_set, RTEMS_ALL_MODE_MASKS, &prev_mode );
+
+ (*asr->handler)( signal_set );
+
+ asr->nest_level -= 1;
+ rtems_task_mode( prev_mode, RTEMS_ALL_MODE_MASKS, &prev_mode );
+
+}
+
+API_extensions_Control _RTEMS_tasks_API_extensions = {
+ { NULL, NULL },
+ NULL, /* predriver */
+ _RTEMS_tasks_Initialize_user_tasks, /* postdriver */
+ _RTEMS_tasks_Post_switch_extension /* post switch */
+};
+
+User_extensions_Control _RTEMS_tasks_User_extensions = {
+ { NULL, NULL },
+ { { NULL, NULL }, _RTEMS_tasks_Switch_extension },
+ { _RTEMS_tasks_Create_extension, /* create */
+ _RTEMS_tasks_Start_extension, /* start */
+ _RTEMS_tasks_Start_extension, /* restart */
+ _RTEMS_tasks_Delete_extension, /* delete */
+ _RTEMS_tasks_Switch_extension, /* switch */
+ NULL, /* begin */
+ NULL, /* exitted */
+ NULL /* fatal */
+ }
+};
+
+/*PAGE
+ *
+ * _RTEMS_tasks_Manager_initialization
+ *
+ * This routine initializes all Task Manager related data structures.
+ *
+ * Input parameters:
+ * maximum_tasks - number of tasks to initialize
+ *
+ * Output parameters: NONE
+ */
+
+void _RTEMS_tasks_Manager_initialization(
+ uint32_t maximum_tasks,
+ uint32_t number_of_initialization_tasks,
+ rtems_initialization_tasks_table *user_tasks
+)
+{
+
+ _RTEMS_tasks_Number_of_initialization_tasks = number_of_initialization_tasks;
+ _RTEMS_tasks_User_initialization_tasks = user_tasks;
+
+ /*
+ * There may not be any RTEMS initialization tasks configured.
+ */
+
+#if 0
+ if ( user_tasks == NULL || number_of_initialization_tasks == 0 )
+ _Internal_error_Occurred( INTERNAL_ERROR_RTEMS_API, TRUE, RTEMS_TOO_MANY );
+#endif
+
+ _Objects_Initialize_information(
+ &_RTEMS_tasks_Information, /* object information table */
+ OBJECTS_CLASSIC_API, /* object API */
+ OBJECTS_RTEMS_TASKS, /* object class */
+ maximum_tasks, /* maximum objects of this class */
+ sizeof( Thread_Control ), /* size of this object's control block */
+ FALSE, /* TRUE if the name is a string */
+ RTEMS_MAXIMUM_NAME_LENGTH /* maximum length of an object name */
+#if defined(RTEMS_MULTIPROCESSING)
+ ,
+ TRUE, /* TRUE if this is a global object class */
+ NULL /* Proxy extraction support callout */
+#endif
+ );
+
+ /*
+ * Add all the extensions for this API
+ */
+
+ _User_extensions_Add_API_set( &_RTEMS_tasks_User_extensions );
+
+ _API_extensions_Add( &_RTEMS_tasks_API_extensions );
+
+ /*
+ * Register the MP Process Packet routine.
+ */
+
+#if defined(RTEMS_MULTIPROCESSING)
+ _MPCI_Register_packet_processor(
+ MP_PACKET_TASKS,
+ _RTEMS_tasks_MP_Process_packet
+ );
+#endif
+
+}
diff --git a/cpukit/rtems/src/tasksetnote.c b/cpukit/rtems/src/tasksetnote.c
new file mode 100644
index 0000000000..6372cbc0dc
--- /dev/null
+++ b/cpukit/rtems/src/tasksetnote.c
@@ -0,0 +1,102 @@
+/*
+ * RTEMS Task Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/rtems/modes.h>
+#include <rtems/score/object.h>
+#include <rtems/score/stack.h>
+#include <rtems/score/states.h>
+#include <rtems/rtems/tasks.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+/*PAGE
+ *
+ * rtems_task_set_note
+ *
+ * This directive sets the specified notepad contents to the given
+ * note.
+ *
+ * Input parameters:
+ * id - thread id
+ * notepad - notepad number
+ * note - note value
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_task_set_note(
+ Objects_Id id,
+ uint32_t notepad,
+ uint32_t note
+)
+{
+ register Thread_Control *the_thread;
+ Objects_Locations location;
+ RTEMS_API_Control *api;
+
+ /*
+ * NOTE: There is no check for < RTEMS_NOTEPAD_FIRST because that would
+ * be checking an unsigned number for being negative.
+ */
+
+ if ( notepad > RTEMS_NOTEPAD_LAST )
+ return RTEMS_INVALID_NUMBER;
+
+ /*
+ * Optimize the most likely case to avoid the Thread_Dispatch.
+ */
+
+ if ( _Objects_Are_ids_equal( id, OBJECTS_ID_OF_SELF ) ||
+ _Objects_Are_ids_equal( id, _Thread_Executing->Object.id ) ) {
+ api = _Thread_Executing->API_Extensions[ THREAD_API_RTEMS ];
+ api->Notepads[ notepad ] = note;
+ return RTEMS_SUCCESSFUL;
+ }
+
+ the_thread = _Thread_Get( id, &location );
+ switch ( location ) {
+
+ case OBJECTS_REMOTE:
+#if defined(RTEMS_MULTIPROCESSING)
+ return _RTEMS_tasks_MP_Send_request_packet(
+ RTEMS_TASKS_MP_SET_NOTE_REQUEST,
+ id,
+ 0, /* Not used */
+ notepad,
+ note
+ );
+#endif
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
+ api->Notepads[ notepad ] = note;
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/tasksetpriority.c b/cpukit/rtems/src/tasksetpriority.c
new file mode 100644
index 0000000000..2405f51e8c
--- /dev/null
+++ b/cpukit/rtems/src/tasksetpriority.c
@@ -0,0 +1,98 @@
+/*
+ * RTEMS Task Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/rtems/modes.h>
+#include <rtems/score/object.h>
+#include <rtems/score/stack.h>
+#include <rtems/score/states.h>
+#include <rtems/rtems/tasks.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+/*PAGE
+ *
+ * rtems_task_set_priority
+ *
+ * This directive changes the priority of the specified thread.
+ * The specified thread can be any thread in the system including
+ * the requesting thread.
+ *
+ * Input parameters:
+ * id - thread id (0 indicates requesting thread)
+ * new_priority - thread priority (0 indicates current priority)
+ * old_priority - pointer to previous priority
+ *
+ * Output parameters:
+ * old_priority - previous priority
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_task_set_priority(
+ Objects_Id id,
+ rtems_task_priority new_priority,
+ rtems_task_priority *old_priority
+)
+{
+ register Thread_Control *the_thread;
+ Objects_Locations location;
+
+ if ( new_priority != RTEMS_CURRENT_PRIORITY &&
+ !_RTEMS_tasks_Priority_is_valid( new_priority ) )
+ return RTEMS_INVALID_PRIORITY;
+
+ if ( !old_priority )
+ return RTEMS_INVALID_ADDRESS;
+
+ the_thread = _Thread_Get( id, &location );
+ switch ( location ) {
+
+ case OBJECTS_REMOTE:
+#if defined(RTEMS_MULTIPROCESSING)
+ _Thread_Executing->Wait.return_argument = old_priority;
+ return _RTEMS_tasks_MP_Send_request_packet(
+ RTEMS_TASKS_MP_SET_PRIORITY_REQUEST,
+ id,
+ new_priority,
+ 0, /* Not used */
+ 0 /* Not used */
+ );
+#endif
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ /* XXX convert from core priority */
+ *old_priority = the_thread->current_priority;
+ if ( new_priority != RTEMS_CURRENT_PRIORITY ) {
+ the_thread->real_priority = new_priority;
+ if ( the_thread->resource_count == 0 ||
+ the_thread->current_priority > new_priority )
+ _Thread_Change_priority( the_thread, new_priority, FALSE );
+ }
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/taskstart.c b/cpukit/rtems/src/taskstart.c
new file mode 100644
index 0000000000..9878c54b94
--- /dev/null
+++ b/cpukit/rtems/src/taskstart.c
@@ -0,0 +1,84 @@
+/*
+ * RTEMS Task Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/rtems/modes.h>
+#include <rtems/score/object.h>
+#include <rtems/score/stack.h>
+#include <rtems/score/states.h>
+#include <rtems/rtems/tasks.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+/*PAGE
+ *
+ * rtems_task_start
+ *
+ * This directive readies the thread identified by the "id"
+ * based on its current priorty, to await execution. A thread
+ * can be started only from the dormant state.
+ *
+ * Input parameters:
+ * id - thread id
+ * entry_point - start execution address of thread
+ * argument - thread argument
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_task_start(
+ rtems_id id,
+ rtems_task_entry entry_point,
+ uint32_t argument
+)
+{
+ register Thread_Control *the_thread;
+ Objects_Locations location;
+
+ if ( entry_point == NULL )
+ return RTEMS_INVALID_ADDRESS;
+
+ the_thread = _Thread_Get( id, &location );
+ switch ( location ) {
+
+ case OBJECTS_REMOTE:
+#if defined(RTEMS_MULTIPROCESSING)
+ _Thread_Dispatch();
+ return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
+#endif
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ if ( _Thread_Start(
+ the_thread, THREAD_START_NUMERIC, entry_point, NULL, argument ) ) {
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+ _Thread_Enable_dispatch();
+ return RTEMS_INCORRECT_STATE;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/tasksuspend.c b/cpukit/rtems/src/tasksuspend.c
new file mode 100644
index 0000000000..7f40dd793e
--- /dev/null
+++ b/cpukit/rtems/src/tasksuspend.c
@@ -0,0 +1,82 @@
+/*
+ * RTEMS Task Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/rtems/modes.h>
+#include <rtems/score/object.h>
+#include <rtems/score/stack.h>
+#include <rtems/score/states.h>
+#include <rtems/rtems/tasks.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+/*PAGE
+ *
+ * rtems_task_suspend
+ *
+ * This directive will place the specified thread in the "suspended"
+ * state. Note that the suspended state can be in addition to
+ * other waiting states.
+ *
+ * Input parameters:
+ * id - thread id
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_task_suspend(
+ Objects_Id id
+)
+{
+ register Thread_Control *the_thread;
+ Objects_Locations location;
+
+ the_thread = _Thread_Get( id, &location );
+ switch ( location ) {
+
+ case OBJECTS_REMOTE:
+#if defined(RTEMS_MULTIPROCESSING)
+ return _RTEMS_tasks_MP_Send_request_packet(
+ RTEMS_TASKS_MP_SUSPEND_REQUEST,
+ id,
+ 0, /* Not used */
+ 0, /* Not used */
+ 0 /* Not used */
+ );
+#endif
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ if ( !_States_Is_suspended( the_thread->current_state ) ) {
+ _Thread_Suspend( the_thread );
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+ _Thread_Enable_dispatch();
+ return RTEMS_ALREADY_SUSPENDED;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/taskvariableadd.c b/cpukit/rtems/src/taskvariableadd.c
new file mode 100644
index 0000000000..6e71180a66
--- /dev/null
+++ b/cpukit/rtems/src/taskvariableadd.c
@@ -0,0 +1,88 @@
+/*
+ * rtems_task_variable_add - Add a per-task variable
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/tasks.h>
+#include <rtems/score/wkspace.h>
+
+/*
+ * rtems_task_variable_add
+ *
+ * This directive registers a task variable.
+ */
+
+rtems_status_code rtems_task_variable_add(
+ rtems_id tid,
+ void **ptr,
+ void (*dtor)(void *)
+)
+{
+ Thread_Control *the_thread;
+ Objects_Locations location;
+ rtems_task_variable_t *tvp, *new;
+
+ if ( !ptr )
+ return RTEMS_INVALID_ADDRESS;
+
+ the_thread = _Thread_Get (tid, &location);
+ switch (location) {
+ case OBJECTS_REMOTE:
+#if defined(RTEMS_MULTIPROCESSING)
+ _Thread_Dispatch();
+ return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
+#endif
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ default:
+ return RTEMS_INTERNAL_ERROR;
+
+ case OBJECTS_LOCAL:
+
+ /*
+ * Figure out if the variable is already in this task's list.
+ */
+
+ tvp = the_thread->task_variables;
+ while (tvp) {
+ if (tvp->ptr == ptr) {
+ tvp->dtor = dtor;
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+ tvp = tvp->next;
+ }
+
+ /*
+ * Now allocate memory for this task variable.
+ */
+
+ new = (rtems_task_variable_t *)
+ _Workspace_Allocate(sizeof(rtems_task_variable_t));
+ if (new == NULL) {
+ _Thread_Enable_dispatch();
+ return RTEMS_NO_MEMORY;
+ }
+ new->gval = *ptr;
+ new->ptr = ptr;
+ new->dtor = dtor;
+
+ new->next = the_thread->task_variables;
+ the_thread->task_variables = new;
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/taskvariabledelete.c b/cpukit/rtems/src/taskvariabledelete.c
new file mode 100644
index 0000000000..5dd01497a8
--- /dev/null
+++ b/cpukit/rtems/src/taskvariabledelete.c
@@ -0,0 +1,75 @@
+/*
+ * rtems_task_variable_delete - Delete a per-task variable
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/tasks.h>
+#include <rtems/score/wkspace.h>
+
+/*
+ * rtems_task_variable_delete
+ *
+ * This directive removes a task variable.
+ */
+
+rtems_status_code rtems_task_variable_delete(
+ rtems_id tid,
+ void **ptr
+)
+{
+ Thread_Control *the_thread;
+ Objects_Locations location;
+ rtems_task_variable_t *tvp, *prev;
+
+ if ( !ptr )
+ return RTEMS_INVALID_ADDRESS;
+
+ prev = NULL;
+
+ the_thread = _Thread_Get (tid, &location);
+ switch (location) {
+ case OBJECTS_REMOTE:
+#if defined(RTEMS_MULTIPROCESSING)
+ _Thread_Dispatch();
+ return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
+#endif
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ default:
+ return RTEMS_INTERNAL_ERROR;
+
+ case OBJECTS_LOCAL:
+ tvp = the_thread->task_variables;
+ while (tvp) {
+ if (tvp->ptr == ptr) {
+ if (prev) prev->next = tvp->next;
+ else the_thread->task_variables = tvp->next;
+ if (tvp->dtor)
+ (*tvp->dtor)(*tvp->ptr);
+ if (_Thread_Is_executing(the_thread))
+ *tvp->ptr = tvp->gval;
+ _Workspace_Free(tvp);
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+ prev = tvp;
+ tvp = tvp->next;
+ }
+ _Thread_Enable_dispatch();
+ return RTEMS_INVALID_ADDRESS;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/taskvariableget.c b/cpukit/rtems/src/taskvariableget.c
new file mode 100644
index 0000000000..b9db9f5bd6
--- /dev/null
+++ b/cpukit/rtems/src/taskvariableget.c
@@ -0,0 +1,78 @@
+/*
+ * rtems_task_variable_get - Get a per-task variable
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/tasks.h>
+#include <rtems/score/wkspace.h>
+
+/*
+ * rtems_task_variable_get
+ *
+ * This directive gets the value of a task variable.
+ */
+
+rtems_status_code rtems_task_variable_get(
+ rtems_id tid,
+ void **ptr,
+ void **result
+)
+{
+ Thread_Control *the_thread;
+ Objects_Locations location;
+ rtems_task_variable_t *tvp;
+
+ if ( !ptr )
+ return RTEMS_INVALID_ADDRESS;
+
+ if ( !result )
+ return RTEMS_INVALID_ADDRESS;
+
+ the_thread = _Thread_Get (tid, &location);
+ switch (location) {
+ case OBJECTS_REMOTE:
+#if defined(RTEMS_MULTIPROCESSING)
+ _Thread_Dispatch();
+ return RTEMS_ILLEGAL_ON_REMOTE_OBJECT;
+#endif
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ default:
+ return RTEMS_INTERNAL_ERROR;
+
+ case OBJECTS_LOCAL:
+
+ /*
+ * Figure out if the variable is in this task's list.
+ */
+
+ tvp = the_thread->task_variables;
+ while (tvp) {
+ if (tvp->ptr == ptr) {
+ /*
+ * Should this return the current (i.e not the
+ * saved) value if `tid' is the current task?
+ */
+ *result = tvp->tval;
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+ tvp = tvp->next;
+ }
+ _Thread_Enable_dispatch();
+ return RTEMS_INVALID_ADDRESS;
+ }
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/taskwakeafter.c b/cpukit/rtems/src/taskwakeafter.c
new file mode 100644
index 0000000000..407b2a8a11
--- /dev/null
+++ b/cpukit/rtems/src/taskwakeafter.c
@@ -0,0 +1,64 @@
+/*
+ * RTEMS Task Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/rtems/modes.h>
+#include <rtems/score/object.h>
+#include <rtems/score/stack.h>
+#include <rtems/score/states.h>
+#include <rtems/rtems/tasks.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+/*PAGE
+ *
+ * rtems_task_wake_after
+ *
+ * This directive suspends the requesting thread for the given amount
+ * of ticks.
+ *
+ * Input parameters:
+ * ticks - number of ticks to wait
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - always successful
+ */
+
+rtems_status_code rtems_task_wake_after(
+ rtems_interval ticks
+)
+{
+ _Thread_Disable_dispatch();
+ if ( ticks == 0 ) {
+ _Thread_Yield_processor();
+ } else {
+ _Thread_Set_state( _Thread_Executing, STATES_DELAYING );
+ _Watchdog_Initialize(
+ &_Thread_Executing->Timer,
+ _Thread_Delay_ended,
+ _Thread_Executing->Object.id,
+ NULL
+ );
+ _Watchdog_Insert_ticks( &_Thread_Executing->Timer, ticks );
+ }
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/rtems/src/taskwakewhen.c b/cpukit/rtems/src/taskwakewhen.c
new file mode 100644
index 0000000000..276a0c7f64
--- /dev/null
+++ b/cpukit/rtems/src/taskwakewhen.c
@@ -0,0 +1,82 @@
+/*
+ * RTEMS Task Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/rtems/modes.h>
+#include <rtems/score/object.h>
+#include <rtems/score/stack.h>
+#include <rtems/score/states.h>
+#include <rtems/rtems/tasks.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/sysstate.h>
+
+/*PAGE
+ *
+ * rtems_task_wake_when
+ *
+ * This directive blocks the requesting thread until the given date and
+ * time is reached.
+ *
+ * Input parameters:
+ * time_buffer - pointer to the time and date structure
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_task_wake_when(
+ rtems_time_of_day *time_buffer
+)
+{
+ Watchdog_Interval seconds;
+
+ if ( !_TOD_Is_set )
+ return RTEMS_NOT_DEFINED;
+
+ if ( !time_buffer )
+ return RTEMS_INVALID_ADDRESS;
+
+ time_buffer->ticks = 0;
+
+ if ( !_TOD_Validate( time_buffer ) )
+ return RTEMS_INVALID_CLOCK;
+
+ seconds = _TOD_To_seconds( time_buffer );
+
+ if ( seconds <= _TOD_Seconds_since_epoch )
+ return RTEMS_INVALID_CLOCK;
+
+ _Thread_Disable_dispatch();
+ _Thread_Set_state( _Thread_Executing, STATES_WAITING_FOR_TIME );
+ _Watchdog_Initialize(
+ &_Thread_Executing->Timer,
+ _Thread_Delay_ended,
+ _Thread_Executing->Object.id,
+ NULL
+ );
+ _Watchdog_Insert_seconds(
+ &_Thread_Executing->Timer,
+ seconds - _TOD_Seconds_since_epoch
+ );
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/rtems/src/timercancel.c b/cpukit/rtems/src/timercancel.c
new file mode 100644
index 0000000000..421662c946
--- /dev/null
+++ b/cpukit/rtems/src/timercancel.c
@@ -0,0 +1,61 @@
+/*
+ * Timer Manager - rtems_timer_cancel directive
+ *
+ *
+ * COPYRIGHT (c) 1989-2002.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/rtems/timer.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * rtems_timer_cancel
+ *
+ * This directive allows a thread to cancel a timer.
+ *
+ * Input parameters:
+ * id - timer id
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_timer_cancel(
+ Objects_Id id
+)
+{
+ Timer_Control *the_timer;
+ Objects_Locations location;
+
+ the_timer = _Timer_Get( id, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE: /* should never return this */
+ return RTEMS_INTERNAL_ERROR;
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ if ( !_Timer_Is_dormant_class( the_timer->the_class ) )
+ (void) _Watchdog_Remove( &the_timer->Ticker );
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/timercreate.c b/cpukit/rtems/src/timercreate.c
new file mode 100644
index 0000000000..2a41411bc3
--- /dev/null
+++ b/cpukit/rtems/src/timercreate.c
@@ -0,0 +1,73 @@
+/*
+ * Timer Manager - rtems_timer_create directive
+ *
+ *
+ * COPYRIGHT (c) 1989-2002.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/rtems/timer.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * rtems_timer_create
+ *
+ * This directive creates a timer and performs some initialization.
+ *
+ * Input parameters:
+ * name - timer name
+ * id - pointer to timer id
+ *
+ * Output parameters:
+ * id - timer id
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_timer_create(
+ rtems_name name,
+ Objects_Id *id
+)
+{
+ Timer_Control *the_timer;
+
+ if ( !rtems_is_name_valid( name ) )
+ return RTEMS_INVALID_NAME;
+
+ if ( !id )
+ return RTEMS_INVALID_ADDRESS;
+
+ _Thread_Disable_dispatch(); /* to prevent deletion */
+
+ the_timer = _Timer_Allocate();
+
+ if ( !the_timer ) {
+ _Thread_Enable_dispatch();
+ return RTEMS_TOO_MANY;
+ }
+
+ the_timer->the_class = TIMER_DORMANT;
+
+ _Objects_Open(
+ &_Timer_Information,
+ &the_timer->Object,
+ (Objects_Name) name
+ );
+
+ *id = the_timer->Object.id;
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/rtems/src/timerdelete.c b/cpukit/rtems/src/timerdelete.c
new file mode 100644
index 0000000000..2838d1ee1f
--- /dev/null
+++ b/cpukit/rtems/src/timerdelete.c
@@ -0,0 +1,62 @@
+/*
+ * Timer Manager - rtems_timer_delete directive
+ *
+ *
+ * COPYRIGHT (c) 1989-2002.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/rtems/timer.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * rtems_timer_delete
+ *
+ * This directive allows a thread to delete a timer.
+ *
+ * Input parameters:
+ * id - timer id
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_timer_delete(
+ Objects_Id id
+)
+{
+ Timer_Control *the_timer;
+ Objects_Locations location;
+
+ the_timer = _Timer_Get( id, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE: /* should never return this */
+ return RTEMS_INTERNAL_ERROR;
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ _Objects_Close( &_Timer_Information, &the_timer->Object );
+ (void) _Watchdog_Remove( &the_timer->Ticker );
+ _Timer_Free( the_timer );
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/timerfireafter.c b/cpukit/rtems/src/timerfireafter.c
new file mode 100644
index 0000000000..7b4660c82b
--- /dev/null
+++ b/cpukit/rtems/src/timerfireafter.c
@@ -0,0 +1,75 @@
+/*
+ * Timer Manager - rtems_timer_fire_after directive
+ *
+ *
+ * COPYRIGHT (c) 1989-2002.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/rtems/timer.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * rtems_timer_fire_after
+ *
+ * This directive allows a thread to start a timer.
+ *
+ * Input parameters:
+ * id - timer id
+ * ticks - interval until routine is fired
+ * routine - routine to schedule
+ * user_data - passed as argument to routine when it is fired
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_timer_fire_after(
+ Objects_Id id,
+ rtems_interval ticks,
+ rtems_timer_service_routine_entry routine,
+ void *user_data
+)
+{
+ Timer_Control *the_timer;
+ Objects_Locations location;
+
+ if ( ticks == 0 )
+ return RTEMS_INVALID_NUMBER;
+
+ if ( !routine )
+ return RTEMS_INVALID_ADDRESS;
+
+ the_timer = _Timer_Get( id, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE: /* should never return this */
+ return RTEMS_INTERNAL_ERROR;
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ (void) _Watchdog_Remove( &the_timer->Ticker );
+ the_timer->the_class = TIMER_INTERVAL;
+ _Watchdog_Initialize( &the_timer->Ticker, routine, id, user_data );
+ _Watchdog_Insert_ticks( &the_timer->Ticker, ticks );
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/timerfirewhen.c b/cpukit/rtems/src/timerfirewhen.c
new file mode 100644
index 0000000000..27175ff027
--- /dev/null
+++ b/cpukit/rtems/src/timerfirewhen.c
@@ -0,0 +1,86 @@
+/*
+ * Timer Manager - rtems_timer_fire_when directive
+ *
+ *
+ * COPYRIGHT (c) 1989-2002.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/rtems/timer.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * rtems_timer_fire_when
+ *
+ * This directive allows a thread to start a timer.
+ *
+ * Input parameters:
+ * id - timer id
+ * wall_time - time of day to fire timer
+ * routine - routine to schedule
+ * user_data - passed as argument to routine when it is fired
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_timer_fire_when(
+ Objects_Id id,
+ rtems_time_of_day *wall_time,
+ rtems_timer_service_routine_entry routine,
+ void *user_data
+)
+{
+ Timer_Control *the_timer;
+ Objects_Locations location;
+ rtems_interval seconds;
+
+ if ( !_TOD_Is_set )
+ return RTEMS_NOT_DEFINED;
+
+ if ( !_TOD_Validate( wall_time ) )
+ return RTEMS_INVALID_CLOCK;
+
+ if ( !routine )
+ return RTEMS_INVALID_ADDRESS;
+
+ seconds = _TOD_To_seconds( wall_time );
+ if ( seconds <= _TOD_Seconds_since_epoch )
+ return RTEMS_INVALID_CLOCK;
+
+ the_timer = _Timer_Get( id, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE: /* should never return this */
+ return RTEMS_INTERNAL_ERROR;
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ (void) _Watchdog_Remove( &the_timer->Ticker );
+ the_timer->the_class = TIMER_TIME_OF_DAY;
+ _Watchdog_Initialize( &the_timer->Ticker, routine, id, user_data );
+ _Watchdog_Insert_seconds(
+ &the_timer->Ticker,
+ seconds - _TOD_Seconds_since_epoch
+ );
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/timergetinfo.c b/cpukit/rtems/src/timergetinfo.c
new file mode 100644
index 0000000000..9c21b84a3d
--- /dev/null
+++ b/cpukit/rtems/src/timergetinfo.c
@@ -0,0 +1,70 @@
+/*
+ * Timer Manager - rtems_timer_get_information directive
+ *
+ *
+ * COPYRIGHT (c) 1989-2002.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/rtems/timer.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * rtems_timer_get_information
+ *
+ * This directive allows a thread to obtain information about a timer.
+ *
+ * Input parameters:
+ * id - timer id
+ * the_info - pointer to timer information block
+ *
+ * Output parameters:
+ * *the_info - region information block filled in
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ *
+ */
+
+rtems_status_code rtems_timer_get_information(
+ Objects_Id id,
+ rtems_timer_information *the_info
+)
+{
+ Timer_Control *the_timer;
+ Objects_Locations location;
+
+ if ( !the_info )
+ return RTEMS_INVALID_ADDRESS;
+
+ the_timer = _Timer_Get( id, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE: /* should never return this */
+ return RTEMS_INTERNAL_ERROR;
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ the_info->the_class = the_timer->the_class;
+ the_info->initial = the_timer->Ticker.initial;
+ the_info->start_time = the_timer->Ticker.start_time;
+ the_info->stop_time = the_timer->Ticker.stop_time;
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/timerident.c b/cpukit/rtems/src/timerident.c
new file mode 100644
index 0000000000..d9a05e4f05
--- /dev/null
+++ b/cpukit/rtems/src/timerident.c
@@ -0,0 +1,56 @@
+/*
+ * Timer Manager - rtems_timer_ident directive
+ *
+ *
+ * COPYRIGHT (c) 1989-2002.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/rtems/timer.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * rtems_timer_ident
+ *
+ * This directive returns the system ID associated with
+ * the timer name.
+ *
+ * Input parameters:
+ * name - user defined message queue name
+ * id - pointer to timer id
+ *
+ * Output parameters:
+ * *id - message queue id
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_timer_ident(
+ rtems_name name,
+ Objects_Id *id
+)
+{
+ Objects_Name_or_id_lookup_errors status;
+
+ status = _Objects_Name_to_id(
+ &_Timer_Information,
+ (Objects_Name) name,
+ OBJECTS_SEARCH_LOCAL_NODE,
+ id
+ );
+
+ return _Status_Object_name_errors_to_status[ status ];
+}
diff --git a/cpukit/rtems/src/timerreset.c b/cpukit/rtems/src/timerreset.c
new file mode 100644
index 0000000000..cb096d17b8
--- /dev/null
+++ b/cpukit/rtems/src/timerreset.c
@@ -0,0 +1,77 @@
+/*
+ * Timer Manager - rtems_timer_reset directive
+ *
+ *
+ * COPYRIGHT (c) 1989-2002.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/rtems/timer.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * rtems_timer_reset
+ *
+ * This directive allows a thread to reset a timer.
+ *
+ * Input parameters:
+ * id - timer id
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_timer_reset(
+ Objects_Id id
+)
+{
+ Timer_Control *the_timer;
+ Objects_Locations location;
+
+ the_timer = _Timer_Get( id, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE: /* should never return this */
+ return RTEMS_INTERNAL_ERROR;
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ switch ( the_timer->the_class ) {
+ case TIMER_INTERVAL:
+ _Watchdog_Remove( &the_timer->Ticker );
+ _Watchdog_Insert( &_Watchdog_Ticks_chain, &the_timer->Ticker );
+ break;
+ case TIMER_INTERVAL_ON_TASK:
+ _Timer_Server_stop_ticks_timer();
+ _Watchdog_Remove( &the_timer->Ticker );
+ _Timer_Server_process_ticks_chain();
+ _Watchdog_Insert( &_Timer_Ticks_chain, &the_timer->Ticker );
+ _Timer_Server_reset_ticks_timer();
+ break;
+ case TIMER_TIME_OF_DAY:
+ case TIMER_TIME_OF_DAY_ON_TASK:
+ case TIMER_DORMANT:
+ _Thread_Enable_dispatch();
+ return RTEMS_NOT_DEFINED;
+ }
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/timerserver.c b/cpukit/rtems/src/timerserver.c
new file mode 100644
index 0000000000..a92a828423
--- /dev/null
+++ b/cpukit/rtems/src/timerserver.c
@@ -0,0 +1,317 @@
+/*
+ * Timer Manager - rtems_timer_initiate_server directive along with
+ * the Timer Server Body and support routines
+ *
+ * COPYRIGHT (c) 1989-2002.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/rtems/timer.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/watchdog.h>
+
+#include <rtems/rtems/tasks.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/thread.h>
+
+/*
+ * The following chains contain the list of interval timers that are
+ * executed in the context of the Timer Server.
+ *
+ * NOTE: These are prototyped in rtems/timer/timer.h but since we
+ * do not actually use them until after the Timer Server is
+ * initiated, we can actually declare them here and avoid forcing
+ * them into the minimum footprint.
+ */
+
+Chain_Control _Timer_Ticks_chain;
+Chain_Control _Timer_Seconds_chain;
+
+/*
+ * These variables keep track of the last time the Timer Server actually
+ * processed the chain.
+ */
+
+Watchdog_Interval _Timer_Server_seconds_last_time;
+Watchdog_Interval _Timer_Server_ticks_last_time;
+
+/*
+ * The timer used to control when the Timer Server wakes up to service
+ * "when" timers.
+ */
+
+Watchdog_Control _Timer_Seconds_timer;
+
+/*PAGE
+ *
+ * _Timer_Server_body
+ *
+ * This is the server for task based timers. This task executes whenever
+ * a task-based timer should fire. It services both "after" and "when"
+ * timers. It is not created automatically but must be created explicitly
+ * by the application before task-based timers may be initiated.
+ *
+ * Input parameters:
+ * Ignored - the task argument is ignored
+ *
+ * Output parameters: NONE
+ */
+
+Thread _Timer_Server_body(
+ uint32_t ignored
+)
+{
+ /*
+ * Initialize the "last time" markers to indicate the timer that
+ * the server was initiated.
+ */
+
+ _Timer_Server_ticks_last_time = _Watchdog_Ticks_since_boot;
+ _Timer_Server_seconds_last_time = _TOD_Seconds_since_epoch;
+
+ _Thread_Disable_dispatch();
+ while(1) {
+
+ /*
+ * Block until there is something to do.
+ */
+
+ _Thread_Set_state( _Timer_Server, STATES_DELAYING );
+ _Timer_Server_reset_ticks_timer();
+ _Timer_Server_reset_seconds_timer();
+ _Thread_Enable_dispatch();
+
+ /*
+ * At this point, at least one of the timers this task relies
+ * upon has fired. Stop them both while we process any outstanding
+ * timers. Before we block, we will restart them.
+ */
+
+ _Timer_Server_stop_ticks_timer();
+ _Timer_Server_stop_seconds_timer();
+
+ /*
+ * Disable dispatching while processing the timers since we want
+ * to mimic the environment that non-task-based TSRs execute in.
+ * This ensures that the primary difference is that _ISR_Nest_level
+ * is 0 for task-based timers and non-zero for the others.
+ */
+
+ _Thread_Disable_dispatch();
+ _Timer_Server_process_ticks_chain();
+ _Timer_Server_process_seconds_chain();
+ }
+
+ return 0; /* unreached - only to remove warnings */
+}
+
+/*PAGE
+ *
+ * rtems_timer_initiate_server
+ *
+ * This directive creates and starts the server for task-based timers.
+ * It must be invoked before any task-based timers can be initiated.
+ *
+ * Input parameters:
+ * priority - timer server priority
+ * stack_size - stack size in bytes
+ * attribute_set - timer server attributes
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+
+rtems_status_code rtems_timer_initiate_server(
+ uint32_t priority,
+ uint32_t stack_size,
+ rtems_attribute attribute_set
+)
+{
+ rtems_id id;
+ rtems_status_code status;
+ rtems_task_priority _priority;
+
+ /*
+ * Make sure the requested priority is valid.
+ */
+
+ _priority = priority;
+ if ( priority == RTEMS_TIMER_SERVER_DEFAULT_PRIORITY )
+ _priority = 0;
+ else if ( !_RTEMS_tasks_Priority_is_valid( priority ) )
+ return RTEMS_INVALID_PRIORITY;
+
+ /*
+ * Just to make sure the test versus create/start operation are atomic.
+ */
+
+ _Thread_Disable_dispatch();
+
+ if ( _Timer_Server ) {
+ _Thread_Enable_dispatch();
+ return RTEMS_INCORRECT_STATE;
+ }
+
+ /*
+ * Create the Timer Server with the name the name of "TIME". The attribute
+ * RTEMS_SYSTEM_TASK allows us to set a priority to 0 which will makes it
+ * higher than any other task in the system. It can be viewed as a low
+ * priority interrupt. It is also always NO_PREEMPT so it looks like
+ * an interrupt to other tasks.
+ *
+ * We allow the user to override the default priority because the Timer
+ * Server can invoke TSRs which must adhere to language run-time or
+ * other library rules. For example, if using a TSR written in Ada the
+ * Server should run at the same priority as the priority Ada task.
+ * Otherwise, the priority ceiling for the mutex used to protect the
+ * GNAT run-time is violated.
+ */
+
+ status = rtems_task_create(
+ 0x4954454d, /* "TIME" */
+ _priority, /* create with priority 1 since 0 is illegal */
+ stack_size, /* let user specify stack size */
+ RTEMS_NO_PREEMPT, /* no preempt is like an interrupt */
+ /* user may want floating point but we need */
+ /* system task specified for 0 priority */
+ attribute_set | RTEMS_SYSTEM_TASK,
+ &id /* get the id back */
+ );
+ if (status) {
+ _Thread_Enable_dispatch();
+ return status;
+ }
+
+ status = rtems_task_start(
+ id, /* the id from create */
+ (rtems_task_entry) _Timer_Server_body, /* the timer server entry point */
+ 0 /* there is no argument */
+ );
+ if (status) {
+ /*
+ * One would expect a call to rtems_task_delete() here to clean up
+ * but there is actually no way (in normal circumstances) that the
+ * start can fail. The id and starting address are known to be
+ * be good. If this service fails, something is weirdly wrong on the
+ * target such as a stray write in an ISR or incorrect memory layout.
+ */
+ _Thread_Enable_dispatch();
+ return status;
+ }
+
+ /*
+ * We work with the TCB pointer, not the ID, so we need to convert
+ * to a TCB pointer from here out.
+ *
+ * NOTE: Setting the pointer to the Timer Server TCB to a value other than
+ * NULL indicates that task-based timer support is initialized.
+ */
+
+ _Timer_Server = (Thread_Control *)_Objects_Get_local_object(
+ &_RTEMS_tasks_Information,
+ _Objects_Get_index(id)
+ );
+
+ /*
+ * Initialize the timer lists that the server will manage.
+ */
+
+ _Chain_Initialize_empty( &_Timer_Ticks_chain );
+ _Chain_Initialize_empty( &_Timer_Seconds_chain );
+
+ /*
+ * Initialize the timers that will be used to control when the
+ * Timer Server wakes up and services the task-based timers.
+ */
+
+ _Watchdog_Initialize( &_Timer_Server->Timer, _Thread_Delay_ended, id, NULL );
+ _Watchdog_Initialize( &_Timer_Seconds_timer, _Thread_Delay_ended, id, NULL );
+
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+}
+
+/*PAGE
+ *
+ * _Timer_Server_process_ticks_chain
+ *
+ * This routine is responsible for adjusting the list of task-based
+ * interval timers to reflect the passage of time.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ */
+
+void _Timer_Server_process_ticks_chain(void)
+{
+ Watchdog_Interval snapshot;
+ Watchdog_Interval ticks;
+
+ snapshot = _Watchdog_Ticks_since_boot;
+ if ( snapshot >= _Timer_Server_ticks_last_time )
+ ticks = snapshot - _Timer_Server_ticks_last_time;
+ else
+ ticks = (0xFFFFFFFF - _Timer_Server_ticks_last_time) + snapshot;
+
+ _Timer_Server_ticks_last_time = snapshot;
+ _Watchdog_Adjust( &_Timer_Ticks_chain, WATCHDOG_FORWARD, ticks );
+}
+
+/*PAGE
+ *
+ * _Timer_Server_process_seconds_chain
+ *
+ * This routine is responsible for adjusting the list of task-based
+ * time of day timers to reflect the passage of time.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ */
+
+void _Timer_Server_process_seconds_chain(void)
+{
+ Watchdog_Interval snapshot;
+ Watchdog_Interval ticks;
+
+ /*
+ * Process the seconds chain. Start by checking that the Time
+ * of Day (TOD) has not been set backwards. If it has then
+ * we want to adjust the _Timer_Seconds_chain to indicate this.
+ */
+
+ snapshot = _TOD_Seconds_since_epoch;
+ if ( snapshot > _Timer_Server_seconds_last_time ) {
+ /*
+ * This path is for normal forward movement and cases where the
+ * TOD has been set forward.
+ */
+
+ ticks = snapshot - _Timer_Server_seconds_last_time;
+ _Watchdog_Adjust( &_Timer_Seconds_chain, WATCHDOG_FORWARD, ticks );
+
+ } else if ( snapshot < _Timer_Server_seconds_last_time ) {
+ /*
+ * The current TOD is before the last TOD which indicates that
+ * TOD has been set backwards.
+ */
+
+ ticks = _Timer_Server_seconds_last_time - snapshot;
+ _Watchdog_Adjust( &_Timer_Seconds_chain, WATCHDOG_BACKWARD, ticks );
+ }
+ _Timer_Server_seconds_last_time = snapshot;
+}
diff --git a/cpukit/rtems/src/timerserverfireafter.c b/cpukit/rtems/src/timerserverfireafter.c
new file mode 100644
index 0000000000..a4c36bc6d0
--- /dev/null
+++ b/cpukit/rtems/src/timerserverfireafter.c
@@ -0,0 +1,86 @@
+/*
+ * Timer Manager - rtems_timer_server fire_after directive
+ *
+ *
+ * COPYRIGHT (c) 1989-2002.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/rtems/timer.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * rtems_timer_server_fire_after
+ *
+ * This directive allows a thread to start a timer which will by
+ * executed by the Timer Server when it fires.
+ *
+ * Input parameters:
+ * id - timer id
+ * ticks - interval until routine is fired
+ * routine - routine to schedule
+ * user_data - passed as argument to routine when it is fired
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_timer_server_fire_after(
+ Objects_Id id,
+ rtems_interval ticks,
+ rtems_timer_service_routine_entry routine,
+ void *user_data
+)
+{
+ Timer_Control *the_timer;
+ Objects_Locations location;
+ extern Chain_Control _Timer_Ticks_chain;
+
+ if ( !_Timer_Server )
+ return RTEMS_INCORRECT_STATE;
+
+ if ( !routine )
+ return RTEMS_INVALID_ADDRESS;
+
+ if ( ticks == 0 )
+ return RTEMS_INVALID_NUMBER;
+
+ the_timer = _Timer_Get( id, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE: /* should never return this */
+ return RTEMS_INTERNAL_ERROR;
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ (void) _Watchdog_Remove( &the_timer->Ticker );
+ the_timer->the_class = TIMER_INTERVAL_ON_TASK;
+ _Watchdog_Initialize( &the_timer->Ticker, routine, id, user_data );
+ the_timer->Ticker.initial = ticks;
+
+ _Timer_Server_stop_ticks_timer();
+ _Timer_Server_process_ticks_chain();
+ _Watchdog_Insert( &_Timer_Ticks_chain, &the_timer->Ticker );
+ _Timer_Server_reset_ticks_timer();
+
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/rtems/src/timerserverfirewhen.c b/cpukit/rtems/src/timerserverfirewhen.c
new file mode 100644
index 0000000000..a197ee2d55
--- /dev/null
+++ b/cpukit/rtems/src/timerserverfirewhen.c
@@ -0,0 +1,94 @@
+/*
+ * Timer Manager - rtems_timer_server fire_when directive
+ *
+ *
+ * COPYRIGHT (c) 1989-2002.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/rtems/timer.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * rtems_timer_server_fire_when
+ *
+ * This directive allows a thread to start a timer which will by
+ * executed by the Timer Server when it fires.
+ *
+ * Input parameters:
+ * id - timer id
+ * wall_time - time of day to fire timer
+ * routine - routine to schedule
+ * user_data - passed as argument to routine when it is fired
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_timer_server_fire_when(
+ Objects_Id id,
+ rtems_time_of_day *wall_time,
+ rtems_timer_service_routine_entry routine,
+ void *user_data
+)
+{
+ Timer_Control *the_timer;
+ Objects_Locations location;
+ rtems_interval seconds;
+ extern Chain_Control _Timer_Seconds_chain;
+
+ if ( !_Timer_Server )
+ return RTEMS_INCORRECT_STATE;
+
+ if ( !_TOD_Is_set )
+ return RTEMS_NOT_DEFINED;
+
+ if ( !routine )
+ return RTEMS_INVALID_ADDRESS;
+
+ if ( !_TOD_Validate( wall_time ) )
+ return RTEMS_INVALID_CLOCK;
+
+ seconds = _TOD_To_seconds( wall_time );
+ if ( seconds <= _TOD_Seconds_since_epoch )
+ return RTEMS_INVALID_CLOCK;
+
+ the_timer = _Timer_Get( id, &location );
+ switch ( location ) {
+ case OBJECTS_REMOTE: /* should never return this */
+ return RTEMS_INTERNAL_ERROR;
+
+ case OBJECTS_ERROR:
+ return RTEMS_INVALID_ID;
+
+ case OBJECTS_LOCAL:
+ (void) _Watchdog_Remove( &the_timer->Ticker );
+ the_timer->the_class = TIMER_TIME_OF_DAY_ON_TASK;
+ _Watchdog_Initialize( &the_timer->Ticker, routine, id, user_data );
+ the_timer->Ticker.initial = seconds - _TOD_Seconds_since_epoch;
+
+ _Timer_Server_stop_seconds_timer();
+ _Timer_Server_process_seconds_chain();
+ _Watchdog_Insert( &_Timer_Seconds_chain, &the_timer->Ticker );
+ _Timer_Server_reset_seconds_timer();
+
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/sapi/.cvsignore b/cpukit/sapi/.cvsignore
new file mode 100644
index 0000000000..282522db03
--- /dev/null
+++ b/cpukit/sapi/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/cpukit/sapi/Makefile.am b/cpukit/sapi/Makefile.am
new file mode 100644
index 0000000000..93684bc0dd
--- /dev/null
+++ b/cpukit/sapi/Makefile.am
@@ -0,0 +1,99 @@
+##
+## $Id$
+##
+
+include $(top_srcdir)/automake/multilib.am
+include $(top_srcdir)/automake/compile.am
+
+include_rtemsdir = $(includedir)/rtems
+
+include_rtems_HEADERS = include/confdefs.h
+include_rtems_HEADERS += include/rtems/config.h include/rtems/extension.h \
+ include/rtems/fatal.h include/rtems/init.h include/rtems/io.h \
+ include/rtems/mptables.h include/rtems/sptables.h
+
+EXTRA_DIST = include/rtems/README
+
+if INLINE
+include_rtems_HEADERS += inline/rtems/extension.inl
+else
+include_rtems_HEADERS += macros/rtems/extension.inl
+endif
+
+## src
+
+EXTENSION_FILES = src/extension.c src/extensioncreate.c \
+ src/extensiondelete.c src/extensionident.c
+C_FILES = src/debug.c $(EXTENSION_FILES) src/fatal.c src/exinit.c src/io.c \
+ src/itronapi.c src/posixapi.c src/rtemsapi.c
+
+AM_CPPFLAGS += -I$(top_builddir)
+AM_CPPFLAGS += -D__RTEMS_INSIDE__
+
+EXTRA_LIBRARIES = libsapi.a
+CLEANFILES = libsapi.a
+libsapi_a_SOURCES = $(C_FILES)
+libsapi_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libsapi_g.a
+CLEANFILES += libsapi_g.a
+libsapi_g_a_SOURCES = $(libsapi_a_SOURCES)
+libsapi_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+all-local: $(PREINSTALL_FILES) libsapi$(LIB_VARIANT).a
+
+PREINSTALL_DIRS =
+PREINSTALL_FILES =
+
+$(PROJECT_INCLUDE)/rtems/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems
+ @: > $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/confdefs.h: include/confdefs.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/confdefs.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/confdefs.h
+
+$(PROJECT_INCLUDE)/rtems/config.h: include/rtems/config.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/config.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/config.h
+
+$(PROJECT_INCLUDE)/rtems/extension.h: include/rtems/extension.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/extension.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/extension.h
+
+$(PROJECT_INCLUDE)/rtems/fatal.h: include/rtems/fatal.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/fatal.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/fatal.h
+
+$(PROJECT_INCLUDE)/rtems/init.h: include/rtems/init.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/init.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/init.h
+
+$(PROJECT_INCLUDE)/rtems/io.h: include/rtems/io.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/io.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/io.h
+
+$(PROJECT_INCLUDE)/rtems/mptables.h: include/rtems/mptables.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/mptables.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/mptables.h
+
+$(PROJECT_INCLUDE)/rtems/sptables.h: include/rtems/sptables.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/sptables.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/sptables.h
+
+if INLINE
+$(PROJECT_INCLUDE)/rtems/extension.inl: inline/rtems/extension.inl $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/extension.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/extension.inl
+
+else
+$(PROJECT_INCLUDE)/rtems/extension.inl: macros/rtems/extension.inl $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/extension.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/extension.inl
+endif
+
+CLEANFILES += $(PREINSTALL_FILES)
+DISTCLEANFILES = $(PREINSTALL_DIRS)
+
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/sapi/include/confdefs.h b/cpukit/sapi/include/confdefs.h
new file mode 100644
index 0000000000..571f2423e0
--- /dev/null
+++ b/cpukit/sapi/include/confdefs.h
@@ -0,0 +1,1097 @@
+/* confdefs.h
+ *
+ * This include file contains the configuration table template that will
+ * be instantiated by an application based on the setting of a number
+ * of macros. The macros are documented in the Configuring a System
+ * chapter of the Classic API User's Guide
+ *
+ * The model is to estimate the memory required for each configured item
+ * and sum those estimates. The estimate can be too high or too low for
+ * a variety of reasons:
+ *
+ * Reasons estimate is too high:
+ * + FP contexts (not all tasks are FP)
+ *
+ * Reasons estimate is too low:
+ * + stacks greater than minimum size
+ * + messages
+ * + application must account for device driver resources
+ * + application must account for add-on library resource requirements
+ *
+ * NOTE: Eventually this may be able to take into account some of
+ * the above. This procedure has evolved from just enough to
+ * support the RTEMS Test Suites into something that can be
+ * used remarkably reliably by most applications.
+ *
+ * COPYRIGHT (c) 1989-2002.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __CONFIGURATION_TEMPLATE_h
+#define __CONFIGURATION_TEMPLATE_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Include the executive's configuration
+ */
+#include <rtems/score/cpuopts.h>
+#include <rtems/score/apimutex.h>
+
+extern rtems_initialization_tasks_table Initialization_tasks[];
+extern rtems_driver_address_table Device_drivers[];
+extern rtems_configuration_table Configuration;
+extern rtems_multiprocessing_table Multiprocessing_configuration;
+#ifdef RTEMS_POSIX_API
+extern posix_api_configuration_table Configuration_POSIX_API;
+#endif
+#ifdef RTEMS_ITRON_API
+extern itron_api_configuration_table Configuration_ITRON_API;
+#endif
+
+/*
+ * RTEMS C Library and Newlib support
+ */
+
+#ifdef RTEMS_NEWLIB
+#define CONFIGURE_NEWLIB_EXTENSION 1
+#else
+#define CONFIGURE_NEWLIB_EXTENSION 0
+#endif
+
+#define CONFIGURE_MALLOC_REGION 1
+
+/*
+ * File descriptors managed by libio
+ */
+
+#ifndef CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS
+#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 3
+#endif
+
+#define CONFIGURE_LIBIO_SEMAPHORES \
+ (CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS + 1)
+
+#ifdef CONFIGURE_INIT
+uint32_t rtems_libio_number_iops = CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS;
+#endif
+
+/*
+ * Termios resources
+ */
+
+#ifdef CONFIGURE_TERMIOS_DISABLED
+#define CONFIGURE_TERMIOS_SEMAPHORES 0
+#else
+
+#ifndef CONFIGURE_NUMBER_OF_TERMIOS_PORTS
+#define CONFIGURE_NUMBER_OF_TERMIOS_PORTS 1
+#endif
+
+#define CONFIGURE_TERMIOS_SEMAPHORES \
+ ((CONFIGURE_NUMBER_OF_TERMIOS_PORTS * 4) + 1)
+#endif
+
+/*
+ * Mount Table Configuration
+ */
+
+#include <rtems/imfs.h>
+
+#ifdef CONFIGURE_INIT
+
+#ifndef CONFIGURE_HAS_OWN_MOUNT_TABLE
+rtems_filesystem_mount_table_t configuration_mount_table = {
+#ifdef CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM
+ &IMFS_ops,
+#else /* using miniIMFS as base filesystem */
+ &miniIMFS_ops,
+#endif
+ RTEMS_FILESYSTEM_READ_WRITE,
+ NULL,
+ NULL
+};
+
+rtems_filesystem_mount_table_t
+ *rtems_filesystem_mount_table = &configuration_mount_table;
+int rtems_filesystem_mount_table_size = 1;
+#endif
+
+#endif
+
+
+/*
+ * Stack Checker Requirements
+ *
+ * NOTE: This does not automatically enable reporting at program exit.
+ */
+
+#ifdef STACK_CHECKER_ON
+#define CONFIGURE_STACK_CHECKER_EXTENSION 1
+#else
+#define CONFIGURE_STACK_CHECKER_EXTENSION 0
+#endif
+
+/*
+ * Interrupt Stack Space
+ *
+ * NOTE: There is currently no way for the application to override
+ * the interrupt stack size set by the BSP.
+ */
+
+#if (CPU_ALLOCATE_INTERRUPT_STACK == 0)
+#undef CONFIGURE_INTERRUPT_STACK_MEMORY
+#define CONFIGURE_INTERRUPT_STACK_MEMORY 0
+#else
+ #ifndef CONFIGURE_INTERRUPT_STACK_MEMORY
+ #define CONFIGURE_INTERRUPT_STACK_MEMORY RTEMS_MINIMUM_STACK_SIZE
+ #endif
+#endif
+
+/*
+ * Default User Initialization Task Table. This table guarantees that
+ * one user initialization table is defined.
+ */
+
+#ifdef CONFIGURE_RTEMS_INIT_TASKS_TABLE
+
+#ifdef CONFIGURE_HAS_OWN_INIT_TASK_TABLE
+
+/*
+ * The user is defining their own table information and setting the
+ * appropriate variables.
+ */
+
+#else
+
+#ifndef CONFIGURE_INIT_TASK_NAME
+#define CONFIGURE_INIT_TASK_NAME rtems_build_name( 'U', 'I', '1', ' ' )
+#endif
+
+#ifndef CONFIGURE_INIT_TASK_STACK_SIZE
+#define CONFIGURE_INIT_TASK_STACK_SIZE RTEMS_MINIMUM_STACK_SIZE
+#endif
+
+#ifndef CONFIGURE_INIT_TASK_PRIORITY
+#define CONFIGURE_INIT_TASK_PRIORITY 1
+#endif
+
+#ifndef CONFIGURE_INIT_TASK_ATTRIBUTES
+#define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_DEFAULT_ATTRIBUTES
+#endif
+
+#ifndef CONFIGURE_INIT_TASK_ENTRY_POINT
+#define CONFIGURE_INIT_TASK_ENTRY_POINT Init
+#endif
+
+#ifndef CONFIGURE_INIT_TASK_INITIAL_MODES
+#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_NO_PREEMPT
+#endif
+
+#ifndef CONFIGURE_INIT_TASK_ARGUMENTS
+#define CONFIGURE_INIT_TASK_ARGUMENTS 0
+#endif
+
+#ifdef CONFIGURE_INIT
+rtems_initialization_tasks_table Initialization_tasks[] = {
+ { CONFIGURE_INIT_TASK_NAME,
+ CONFIGURE_INIT_TASK_STACK_SIZE,
+ CONFIGURE_INIT_TASK_PRIORITY,
+ CONFIGURE_INIT_TASK_ATTRIBUTES,
+ CONFIGURE_INIT_TASK_ENTRY_POINT,
+ CONFIGURE_INIT_TASK_INITIAL_MODES,
+ CONFIGURE_INIT_TASK_ARGUMENTS
+ }
+};
+#endif
+
+#define CONFIGURE_INIT_TASK_TABLE Initialization_tasks
+
+#define CONFIGURE_INIT_TASK_TABLE_SIZE \
+ sizeof(CONFIGURE_INIT_TASK_TABLE) / sizeof(rtems_initialization_tasks_table)
+
+#endif /* CONFIGURE_HAS_OWN_INIT_TASK_TABLE */
+
+#else /* CONFIGURE_RTEMS_INIT_TASKS_TABLE */
+
+#define CONFIGURE_INIT_TASK_TABLE NULL
+#define CONFIGURE_INIT_TASK_TABLE_SIZE 0
+#define CONFIGURE_INIT_TASK_STACK_SIZE 0
+
+#endif
+
+/*
+ * Map obsolete names to current ones
+ *
+ * NOTE: These should be obsoleted in a future release.
+ */
+
+#ifdef CONFIGURE_TEST_NEEDS_TIMER_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_TIMER_DRIVER
+#endif
+#ifdef CONFIGURE_TEST_NEEDS_CONSOLE_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+#endif
+#ifdef CONFIGURE_TEST_NEEDS_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+#endif
+#ifdef CONFIGURE_TEST_NEEDS_RTC_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_RTC_DRIVER
+#endif
+#ifdef CONFIGURE_TEST_NEEDS_STUB_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_STUB_DRIVER
+#endif
+
+
+/*
+ * Default Device Driver Table. Each driver needed by the test is explicitly
+ * choosen by that test. There is always a null driver entry.
+ */
+
+#define NULL_DRIVER_TABLE_ENTRY \
+ { NULL, NULL, NULL, NULL, NULL, NULL }
+
+#ifdef CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+#include <rtems/console.h>
+#endif
+
+#ifdef CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+#include <rtems/clockdrv.h>
+#endif
+
+#ifdef CONFIGURE_APPLICATION_NEEDS_TIMER_DRIVER
+#include <rtems/timerdrv.h>
+#endif
+
+#ifdef CONFIGURE_APPLICATION_NEEDS_RTC_DRIVER
+#include <rtems/rtc.h>
+#endif
+
+#ifdef CONFIGURE_APPLICATION_NEEDS_STUB_DRIVER
+#include <rtems/devnull.h>
+#endif
+
+#ifndef CONFIGURE_HAS_OWN_DEVICE_DRIVER_TABLE
+
+#ifdef CONFIGURE_INIT
+rtems_driver_address_table Device_drivers[] = {
+#ifdef CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+ CONSOLE_DRIVER_TABLE_ENTRY,
+#endif
+#ifdef CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+ CLOCK_DRIVER_TABLE_ENTRY,
+#endif
+#ifdef CONFIGURE_APPLICATION_NEEDS_RTC_DRIVER
+ RTC_DRIVER_TABLE_ENTRY,
+#endif
+#ifdef CONFIGURE_APPLICATION_NEEDS_STUB_DRIVER
+ DEVNULL_DRIVER_TABLE_ENTRY,
+#endif
+#ifdef CONFIGURE_APPLICATION_NEEDS_NULL_DRIVER
+ NULL_DRIVER_TABLE_ENTRY
+#elif !defined(CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER) && \
+ !defined(CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER) && \
+ !defined(CONFIGURE_APPLICATION_NEEDS_RTC_DRIVER) && \
+ !defined(CONFIGURE_APPLICATION_NEEDS_STUB_DRIVER)
+ NULL_DRIVER_TABLE_ENTRY
+#endif
+};
+#endif
+
+#endif /* CONFIGURE_HAS_OWN_DEVICE_DRIVER_TABLE */
+
+/*
+ * Default the number of drivers per node. This value may be
+ * overridden by the user.
+ */
+
+#define CONFIGURE_NUMBER_OF_DRIVERS \
+ ((sizeof(Device_drivers) / sizeof(rtems_driver_address_table)))
+
+#ifndef CONFIGURE_MAXIMUM_DRIVERS
+#define CONFIGURE_MAXIMUM_DRIVERS CONFIGURE_NUMBER_OF_DRIVERS
+#endif
+
+/*
+ * Default the number of devices per device driver. This value may be
+ * overridden by the user.
+ */
+
+#ifndef CONFIGURE_MAXIMUM_DEVICES
+#define CONFIGURE_MAXIMUM_DEVICES 20
+#endif
+
+/*
+ * Default Multiprocessing Configuration Table. The defaults are
+ * appropriate for most of the RTEMS Multiprocessor Test Suite. Each
+ * value may be overridden within each test to customize the environment.
+ */
+
+#ifdef CONFIGURE_MP_APPLICATION
+#ifndef CONFIGURE_HAS_OWN_MULTIPROCESING_TABLE
+
+#ifndef CONFIGURE_MP_NODE_NUMBER
+#define CONFIGURE_MP_NODE_NUMBER NODE_NUMBER
+#endif
+
+#ifndef CONFIGURE_MP_MAXIMUM_NODES
+#define CONFIGURE_MP_MAXIMUM_NODES 2
+#endif
+
+#ifndef CONFIGURE_MP_MAXIMUM_GLOBAL_OBJECTS
+#define CONFIGURE_MP_MAXIMUM_GLOBAL_OBJECTS 32
+#endif
+
+#ifndef CONFIGURE_MP_MAXIMUM_PROXIES
+#define CONFIGURE_MP_MAXIMUM_PROXIES 32
+#endif
+
+#ifndef CONFIGURE_MP_MPCI_TABLE_POINTER
+#include <mpci.h>
+#define CONFIGURE_MP_MPCI_TABLE_POINTER &MPCI_table
+#endif
+
+#ifdef CONFIGURE_INIT
+rtems_multiprocessing_table Multiprocessing_configuration = {
+ CONFIGURE_MP_NODE_NUMBER, /* local node number */
+ CONFIGURE_MP_MAXIMUM_NODES, /* maximum # nodes in system */
+ CONFIGURE_MP_MAXIMUM_GLOBAL_OBJECTS, /* maximum # global objects */
+ CONFIGURE_MP_MAXIMUM_PROXIES, /* maximum # proxies */
+ CONFIGURE_MP_MPCI_TABLE_POINTER /* pointer to MPCI config table */
+};
+#endif
+
+#define CONFIGURE_MULTIPROCESSING_TABLE &Multiprocessing_configuration
+
+#endif /* CONFIGURE_HAS_OWN_MULTIPROCESING_TABLE */
+
+#else
+
+#define CONFIGURE_MULTIPROCESSING_TABLE NULL
+
+#endif /* CONFIGURE_MP_APPLICATION */
+
+/*
+ * Default Configuration Table.
+ */
+
+#ifndef CONFIGURE_HAS_OWN_CONFIGURATION_TABLE
+
+#ifndef CONFIGURE_EXECUTIVE_RAM_WORK_AREA
+#define CONFIGURE_EXECUTIVE_RAM_WORK_AREA NULL
+#endif
+
+#ifndef CONFIGURE_MAXIMUM_TASKS
+#define CONFIGURE_MAXIMUM_TASKS 0
+#endif
+
+#ifndef CONFIGURE_MAXIMUM_TIMERS
+#define CONFIGURE_MAXIMUM_TIMERS 0
+#endif
+
+#ifndef CONFIGURE_MAXIMUM_SEMAPHORES
+#define CONFIGURE_MAXIMUM_SEMAPHORES 0
+#endif
+
+#ifndef CONFIGURE_MAXIMUM_MESSAGE_QUEUES
+#define CONFIGURE_MAXIMUM_MESSAGE_QUEUES 0
+#endif
+
+#ifndef CONFIGURE_MAXIMUM_PARTITIONS
+#define CONFIGURE_MAXIMUM_PARTITIONS 0
+#endif
+
+#ifndef CONFIGURE_MAXIMUM_REGIONS
+#define CONFIGURE_MAXIMUM_REGIONS 0
+#endif
+
+#ifndef CONFIGURE_MAXIMUM_PORTS
+#define CONFIGURE_MAXIMUM_PORTS 0
+#endif
+
+#ifndef CONFIGURE_MAXIMUM_PERIODS
+#define CONFIGURE_MAXIMUM_PERIODS 0
+#endif
+
+#ifndef CONFIGURE_MAXIMUM_USER_EXTENSIONS
+#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 0
+#endif
+
+#ifndef CONFIGURE_MICROSECONDS_PER_TICK
+#define CONFIGURE_MICROSECONDS_PER_TICK RTEMS_MILLISECONDS_TO_MICROSECONDS(10)
+#endif
+
+#ifndef CONFIGURE_TICKS_PER_TIMESLICE
+#define CONFIGURE_TICKS_PER_TIMESLICE 50
+#endif
+
+/*
+ * Initial Extension Set
+ */
+
+#ifdef CONFIGURE_INIT
+#ifdef STACK_CHECKER_ON
+#include <rtems/stackchk.h>
+#endif
+
+#if defined(CONFIGURE_INITIAL_EXTENSIONS) || \
+ defined(STACK_CHECKER_ON)
+rtems_extensions_table Configuration_Initial_Extensions[] = {
+#ifdef CONFIGURE_INITIAL_EXTENSIONS
+ CONFIGURE_INITIAL_EXTENSIONS,
+#endif
+#ifdef STACK_CHECKER_ON
+ STACK_CHECKER_EXTENSION,
+#endif
+};
+
+#define CONFIGURE_INITIAL_EXTENSION_TABLE Configuration_Initial_Extensions
+#define CONFIGURE_NUMBER_OF_INITIAL_EXTENSIONS \
+ ((sizeof(Configuration_Initial_Extensions) / \
+ sizeof(rtems_extensions_table)))
+#else
+#define CONFIGURE_INITIAL_EXTENSION_TABLE NULL
+#define CONFIGURE_NUMBER_OF_INITIAL_EXTENSIONS 0
+#endif
+
+
+#endif
+
+/*
+ * POSIX API Configuration Parameters
+ */
+
+#ifdef RTEMS_POSIX_API
+
+#include <sys/types.h>
+#include <signal.h>
+#include <limits.h>
+#include <mqueue.h>
+#include <rtems/posix/cond.h>
+#include <rtems/posix/mqueue.h>
+#include <rtems/posix/mutex.h>
+#include <rtems/posix/key.h>
+#include <rtems/posix/psignal.h>
+#include <rtems/posix/semaphore.h>
+#include <rtems/posix/threadsup.h>
+
+#ifndef CONFIGURE_MAXIMUM_POSIX_THREADS
+#define CONFIGURE_MAXIMUM_POSIX_THREADS 0
+#endif
+
+#ifndef CONFIGURE_MAXIMUM_POSIX_MUTEXES
+#define CONFIGURE_MAXIMUM_POSIX_MUTEXES 0
+#endif
+
+#ifndef CONFIGURE_MAXIMUM_POSIX_CONDITION_VARIABLES
+#define CONFIGURE_MAXIMUM_POSIX_CONDITION_VARIABLES 0
+#endif
+
+#ifndef CONFIGURE_MAXIMUM_POSIX_KEYS
+#define CONFIGURE_MAXIMUM_POSIX_KEYS 0
+#endif
+
+#ifndef CONFIGURE_MAXIMUM_POSIX_TIMERS
+#define CONFIGURE_MAXIMUM_POSIX_TIMERS 0
+#endif
+
+#ifndef CONFIGURE_MAXIMUM_POSIX_QUEUED_SIGNALS
+#define CONFIGURE_MAXIMUM_POSIX_QUEUED_SIGNALS 0
+#endif
+
+#ifndef CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES
+#define CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES 0
+#endif
+
+#ifndef CONFIGURE_MAXIMUM_POSIX_SEMAPHORES
+#define CONFIGURE_MAXIMUM_POSIX_SEMAPHORES 0
+#endif
+
+#ifdef CONFIGURE_POSIX_INIT_THREAD_TABLE
+
+#ifdef CONFIGURE_POSIX_HAS_OWN_INIT_THREAD_TABLE
+
+/*
+ * The user is defining their own table information and setting the
+ * appropriate variables for the POSIX Initialization Thread Table.
+ */
+
+#else
+
+#ifndef CONFIGURE_POSIX_INIT_THREAD_ENTRY_POINT
+#define CONFIGURE_POSIX_INIT_THREAD_ENTRY_POINT POSIX_Init
+#endif
+
+#ifndef CONFIGURE_POSIX_INIT_THREAD_STACK_SIZE
+#define CONFIGURE_POSIX_INIT_THREAD_STACK_SIZE (RTEMS_MINIMUM_STACK_SIZE * 2)
+#endif
+
+#ifdef CONFIGURE_INIT
+posix_initialization_threads_table POSIX_Initialization_threads[] = {
+ { CONFIGURE_POSIX_INIT_THREAD_ENTRY_POINT, \
+ CONFIGURE_POSIX_INIT_THREAD_STACK_SIZE }
+};
+#endif
+
+#define CONFIGURE_POSIX_INIT_THREAD_TABLE_NAME POSIX_Initialization_threads
+
+#define CONFIGURE_POSIX_INIT_THREAD_TABLE_SIZE \
+ sizeof(CONFIGURE_POSIX_INIT_THREAD_TABLE_NAME) / \
+ sizeof(posix_initialization_threads_table)
+
+#endif /* CONFIGURE_POSIX_HAS_OWN_INIT_TASK_TABLE */
+
+#else /* CONFIGURE_POSIX_INIT_THREAD_TABLE */
+
+#define CONFIGURE_POSIX_INIT_THREAD_TABLE_NAME NULL
+#define CONFIGURE_POSIX_INIT_THREAD_TABLE_SIZE 0
+
+#endif
+
+#define CONFIGURE_MEMORY_PER_TASK_FOR_POSIX_API \
+ ( \
+ sizeof (POSIX_API_Control) + \
+ (sizeof (void *) * (CONFIGURE_GNAT_KEYS + CONFIGURE_MAXIMUM_POSIX_KEYS)) \
+ )
+
+#define CONFIGURE_MEMORY_FOR_POSIX_MUTEXES(_mutexes) \
+ ((_mutexes) * \
+ ( sizeof(POSIX_Mutex_Control) + CONFIGURE_OBJECT_TABLE_STUFF + \
+ NAME_MAX ) )
+
+#define CONFIGURE_MEMORY_FOR_POSIX_CONDITION_VARIABLES(_condition_variables) \
+ ((_condition_variables) * \
+ ( sizeof(POSIX_Condition_variables_Control) + \
+ CONFIGURE_OBJECT_TABLE_STUFF ) )
+
+#define CONFIGURE_MEMORY_FOR_POSIX_KEYS(_keys) \
+ ((_keys) * \
+ ( sizeof(POSIX_Keys_Control) + CONFIGURE_OBJECT_TABLE_STUFF ) )
+
+#define CONFIGURE_MEMORY_FOR_POSIX_TIMERS(_timers) \
+ ((_timers) * \
+ ( 0 ) )
+
+#define CONFIGURE_MEMORY_FOR_POSIX_QUEUED_SIGNALS(_queued_signals) \
+ ((_queued_signals) * \
+ ( sizeof(POSIX_signals_Siginfo_node) + CONFIGURE_OBJECT_TABLE_STUFF ) )
+
+#define CONFIGURE_MEMORY_FOR_POSIX_MESSAGE_QUEUES(_message_queues) \
+ ((_message_queues) * \
+ ( sizeof( POSIX_Message_queue_Control) + \
+ CONFIGURE_OBJECT_TABLE_STUFF + \
+ NAME_MAX ) )
+#define CONFIGURE_MEMORY_FOR_POSIX_SEMAPHORES(_semaphores) \
+ ((_semaphores) * \
+ ( sizeof( POSIX_Semaphore_Control) + \
+ CONFIGURE_OBJECT_TABLE_STUFF + \
+ NAME_MAX ) )
+
+#define CONFIGURE_MEMORY_FOR_POSIX \
+ ( \
+ CONFIGURE_MEMORY_FOR_POSIX_MUTEXES( CONFIGURE_MAXIMUM_POSIX_MUTEXES ) + \
+ CONFIGURE_MEMORY_FOR_POSIX_CONDITION_VARIABLES( \
+ CONFIGURE_MAXIMUM_POSIX_CONDITION_VARIABLES ) + \
+ CONFIGURE_MEMORY_FOR_POSIX_KEYS( CONFIGURE_MAXIMUM_POSIX_KEYS ) + \
+ CONFIGURE_MEMORY_FOR_POSIX_QUEUED_SIGNALS( \
+ CONFIGURE_MAXIMUM_POSIX_QUEUED_SIGNALS ) + \
+ CONFIGURE_MEMORY_FOR_POSIX_MESSAGE_QUEUES( \
+ CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES ) + \
+ CONFIGURE_MEMORY_FOR_POSIX_SEMAPHORES( \
+ CONFIGURE_MAXIMUM_POSIX_SEMAPHORES ) + \
+ (CONFIGURE_POSIX_INIT_THREAD_STACK_SIZE) \
+ )
+
+
+#else
+
+#define CONFIGURE_MAXIMUM_POSIX_THREADS 0
+#define CONFIGURE_MEMORY_PER_TASK_FOR_POSIX_API 0
+#define CONFIGURE_MEMORY_FOR_POSIX 0
+
+
+#endif /* RTEMS_POSIX_API */
+
+#ifndef CONFIGURE_POSIX_INIT_THREAD_STACK_SIZE
+#define CONFIGURE_POSIX_INIT_THREAD_STACK_SIZE 0
+#endif
+
+/*
+ * ITRON API Configuration Parameters
+ */
+
+#ifdef RTEMS_ITRON_API
+
+#include <rtems/itron.h>
+#include <rtems/itron/config.h>
+#include <rtems/itron/eventflags.h>
+#include <rtems/itron/fmempool.h>
+#include <rtems/itron/mbox.h>
+#include <rtems/itron/msgbuffer.h>
+#include <rtems/itron/port.h>
+#include <rtems/itron/semaphore.h>
+#include <rtems/itron/task.h>
+#include <rtems/itron/vmempool.h>
+
+#ifndef CONFIGURE_MAXIMUM_ITRON_TASKS
+#define CONFIGURE_MAXIMUM_ITRON_TASKS 0
+#endif
+
+#ifndef CONFIGURE_MAXIMUM_ITRON_SEMAPHORES
+#define CONFIGURE_MAXIMUM_ITRON_SEMAPHORES 0
+#endif
+
+#ifndef CONFIGURE_MAXIMUM_ITRON_EVENTFLAGS
+#define CONFIGURE_MAXIMUM_ITRON_EVENTFLAGS 0
+#endif
+
+#ifndef CONFIGURE_MAXIMUM_ITRON_MAILBOXES
+#define CONFIGURE_MAXIMUM_ITRON_MAILBOXES 0
+#endif
+
+#ifndef CONFIGURE_MAXIMUM_ITRON_MESSAGE_BUFFERS
+#define CONFIGURE_MAXIMUM_ITRON_MESSAGE_BUFFERS 0
+#endif
+
+#ifndef CONFIGURE_MAXIMUM_ITRON_PORTS
+#define CONFIGURE_MAXIMUM_ITRON_PORTS 0
+#endif
+
+#ifndef CONFIGURE_MAXIMUM_ITRON_MEMORY_POOLS
+#define CONFIGURE_MAXIMUM_ITRON_MEMORY_POOLS 0
+#endif
+
+#ifndef CONFIGURE_MAXIMUM_ITRON_FIXED_MEMORY_POOLS
+#define CONFIGURE_MAXIMUM_ITRON_FIXED_MEMORY_POOLS 0
+#endif
+
+#ifdef CONFIGURE_ITRON_INIT_TASK_TABLE
+
+#ifdef CONFIGURE_ITRON_HAS_OWN_INIT_TASK_TABLE
+
+/*
+ * The user is defining their own table information and setting the
+ * appropriate variables for the ITRON Initialization Task Table.
+ */
+
+#else
+
+#ifndef CONFIGURE_ITRON_INIT_TASK_ENTRY_POINT
+#define CONFIGURE_ITRON_INIT_TASK_ENTRY_POINT ITRON_Init
+#endif
+
+#ifndef CONFIGURE_ITRON_INIT_TASK_ATTRIBUTES
+#define CONFIGURE_ITRON_INIT_TASK_ATTRIBUTES TA_HLNG
+#endif
+
+#ifndef CONFIGURE_ITRON_INIT_TASK_PRIORITY
+#define CONFIGURE_ITRON_INIT_TASK_PRIORITY 1
+#endif
+
+#ifndef CONFIGURE_ITRON_INIT_TASK_STACK_SIZE
+#define CONFIGURE_ITRON_INIT_TASK_STACK_SIZE RTEMS_MINIMUM_STACK_SIZE
+#endif
+
+#ifdef CONFIGURE_INIT
+itron_initialization_tasks_table ITRON_Initialization_tasks[] = {
+ { 1, /* ID */
+ { (VP) 0, /* exinfo */
+ CONFIGURE_ITRON_INIT_TASK_ATTRIBUTES, /* task attributes */
+ CONFIGURE_ITRON_INIT_TASK_ENTRY_POINT, /* task start address */
+ CONFIGURE_ITRON_INIT_TASK_PRIORITY, /* initial task priority */
+ CONFIGURE_ITRON_INIT_TASK_STACK_SIZE /* stack size */
+ }
+ }
+};
+#endif
+
+#define CONFIGURE_ITRON_INIT_TASK_TABLE_NAME ITRON_Initialization_tasks
+
+#define CONFIGURE_ITRON_INIT_TASK_TABLE_SIZE \
+ sizeof(CONFIGURE_ITRON_INIT_TASK_TABLE_NAME) / \
+ sizeof(itron_initialization_tasks_table)
+
+#endif /* CONFIGURE_ITRON_HAS_OWN_INIT_TASK_TABLE */
+
+#else /* CONFIGURE_ITRON_INIT_TASK_TABLE */
+
+#define CONFIGURE_ITRON_INIT_TASK_TABLE_NAME NULL
+#define CONFIGURE_ITRON_INIT_TASK_TABLE_SIZE 0
+
+#endif
+
+#define CONFIGURE_MEMORY_PER_TASK_FOR_ITRON_API \
+ ( \
+ sizeof (ITRON_API_Control) \
+ )
+
+#define CONFIGURE_MEMORY_FOR_ITRON_SEMAPHORES(_semaphores) \
+ ((_semaphores) * \
+ ( sizeof(ITRON_Semaphore_Control) + CONFIGURE_OBJECT_TABLE_STUFF ) )
+
+#define CONFIGURE_MEMORY_FOR_ITRON_EVENTFLAGS(_eventflags) \
+ ((_eventflags) * \
+ ( sizeof(ITRON_Eventflags_Control) + CONFIGURE_OBJECT_TABLE_STUFF ) )
+
+#define CONFIGURE_MEMORY_FOR_ITRON_MAILBOXES(_mailboxes) \
+ ((_mailboxes) * \
+ ( sizeof(ITRON_Mailbox_Control) + CONFIGURE_OBJECT_TABLE_STUFF ) )
+
+#define CONFIGURE_MEMORY_FOR_ITRON_MESSAGE_BUFFERS(_message_buffers) \
+ ((_message_buffers) * \
+ ( sizeof(ITRON_Message_buffer_Control) + CONFIGURE_OBJECT_TABLE_STUFF ) )
+
+#define CONFIGURE_MEMORY_FOR_ITRON_PORTS(_ports) \
+ ((_ports) * \
+ ( sizeof(ITRON_Port_Control) + CONFIGURE_OBJECT_TABLE_STUFF ) )
+
+#define CONFIGURE_MEMORY_FOR_ITRON_MEMORY_POOLS(_memory_pools) \
+ ((_memory_pools) * \
+ (sizeof(ITRON_Variable_memory_pool_Control) + CONFIGURE_OBJECT_TABLE_STUFF))
+
+#define CONFIGURE_MEMORY_FOR_ITRON_FIXED_MEMORY_POOLS(_fixed_memory_pools) \
+ ((_fixed_memory_pools) * \
+ ( sizeof(ITRON_Fixed_memory_pool_Control) + CONFIGURE_OBJECT_TABLE_STUFF ) )
+
+#ifndef CONFIGURE_ITRON_INIT_TASK_STACK_SIZE
+#define CONFIGURE_ITRON_INIT_TASK_STACK_SIZE (RTEMS_MINIMUM_STACK_SIZE * 2)
+#endif
+
+
+#define CONFIGURE_MEMORY_FOR_ITRON \
+ ( \
+ CONFIGURE_MEMORY_FOR_ITRON_SEMAPHORES( \
+ CONFIGURE_MAXIMUM_ITRON_SEMAPHORES ) + \
+ CONFIGURE_MEMORY_FOR_ITRON_EVENTFLAGS( \
+ CONFIGURE_MAXIMUM_ITRON_EVENTFLAGS ) + \
+ CONFIGURE_MEMORY_FOR_ITRON_MAILBOXES( \
+ CONFIGURE_MAXIMUM_ITRON_MAILBOXES ) + \
+ CONFIGURE_MEMORY_FOR_ITRON_MESSAGE_BUFFERS( \
+ CONFIGURE_MAXIMUM_ITRON_MESSAGE_BUFFERS ) + \
+ CONFIGURE_MEMORY_FOR_ITRON_PORTS( \
+ CONFIGURE_MAXIMUM_ITRON_PORTS ) + \
+ CONFIGURE_MEMORY_FOR_ITRON_MEMORY_POOLS( \
+ CONFIGURE_MAXIMUM_ITRON_MEMORY_POOLS ) + \
+ CONFIGURE_MEMORY_FOR_ITRON_FIXED_MEMORY_POOLS( \
+ CONFIGURE_MAXIMUM_ITRON_FIXED_MEMORY_POOLS ) + \
+ CONFIGURE_ITRON_INIT_TASK_STACK_SIZE \
+ )
+
+
+#else
+
+#define CONFIGURE_MAXIMUM_ITRON_TASKS 0
+#define CONFIGURE_MAXIMUM_ITRON_SEMAPHORES 0
+#define CONFIGURE_MAXIMUM_ITRON_EVENTFLAGS 0
+#define CONFIGURE_MAXIMUM_ITRON_MAILBOXES 0
+#define CONFIGURE_MAXIMUM_ITRON_MESSAGE_BUFFERS 0
+#define CONFIGURE_MAXIMUM_ITRON_PORTS 0
+#define CONFIGURE_MAXIMUM_ITRON_MEMORY_POOLS 0
+#define CONFIGURE_MAXIMUM_ITRON_FIXED_MEMORY_POOLS 0
+#define CONFIGURE_MEMORY_PER_TASK_FOR_ITRON_API 0
+#define CONFIGURE_MEMORY_FOR_ITRON 0
+
+#endif /* RTEMS_ITRON_API */
+
+
+/*
+ * Calculate the RAM size based on the maximum number of objects configured.
+ */
+
+#ifndef CONFIGURE_EXECUTIVE_RAM_SIZE
+
+#define CONFIGURE_OBJECT_TABLE_STUFF \
+ ( sizeof(Objects_Control *) + sizeof(rtems_name *) + sizeof(rtems_name) )
+
+#if defined(RTEMS_NEWLIB)
+#include <reent.h>
+
+#define CONFIGURE_MEMORY_PER_TASK_FOR_LIBC_REENTRANCY sizeof(struct _reent)
+#else
+#define CONFIGURE_MEMORY_PER_TASK_FOR_LIBC_REENTRANCY 0
+#endif
+
+#define CONFIGURE_MEMORY_FOR_TASKS(_tasks) \
+ (((_tasks) + 1 ) * \
+ ((sizeof(Thread_Control) + CONTEXT_FP_SIZE + \
+ STACK_MINIMUM_SIZE + sizeof( RTEMS_API_Control ) + \
+ CONFIGURE_MEMORY_PER_TASK_FOR_POSIX_API + \
+ CONFIGURE_MEMORY_PER_TASK_FOR_ITRON_API + \
+ CONFIGURE_MEMORY_PER_TASK_FOR_LIBC_REENTRANCY + \
+ CONFIGURE_OBJECT_TABLE_STUFF)) \
+ )
+
+#define CONFIGURE_MEMORY_FOR_TIMERS(_timers) \
+ ((_timers) * ( sizeof(Timer_Control) + CONFIGURE_OBJECT_TABLE_STUFF ) )
+
+#define CONFIGURE_MEMORY_FOR_SEMAPHORES(_semaphores) \
+ ((_semaphores) * \
+ ( sizeof(Semaphore_Control) + CONFIGURE_OBJECT_TABLE_STUFF ) )
+
+#define CONFIGURE_MEMORY_FOR_MESSAGE_QUEUES(_queues) \
+ ( (_queues) * \
+ ( sizeof(Message_queue_Control) + CONFIGURE_OBJECT_TABLE_STUFF ) )
+
+#define CONFIGURE_MEMORY_FOR_PARTITIONS(_partitions) \
+ ( (_partitions) * \
+ ( sizeof(Partition_Control) + CONFIGURE_OBJECT_TABLE_STUFF ) )
+
+#define CONFIGURE_MEMORY_FOR_REGIONS(_regions) \
+ ( (_regions) * \
+ ( sizeof(Region_Control) + CONFIGURE_OBJECT_TABLE_STUFF ) )
+
+#define CONFIGURE_MEMORY_FOR_PORTS(_ports) \
+ ( (_ports) * \
+ ( sizeof(Dual_ported_memory_Control) + CONFIGURE_OBJECT_TABLE_STUFF ) )
+
+#define CONFIGURE_MEMORY_FOR_PERIODS(_periods) \
+ ( (_periods) * \
+ ( sizeof(Rate_monotonic_Control) + CONFIGURE_OBJECT_TABLE_STUFF ) )
+
+#define CONFIGURE_MEMORY_FOR_USER_EXTENSIONS(_extensions) \
+ ( (_extensions) * \
+ ( sizeof(Extension_Control) + CONFIGURE_OBJECT_TABLE_STUFF ) )
+
+#define CONFIGURE_MEMORY_FOR_DEVICES(_devices) \
+ (((_devices) + 1) * ( sizeof(rtems_driver_name_t) ) )
+
+#ifdef CONFIGURE_MP_APPLICATION
+
+#ifndef CONFIGURE_HAS_OWN_MULTIPROCESING_TABLE
+
+#define CONFIGURE_MEMORY_FOR_PROXIES(_proxies) \
+ ( ((_proxies) + 1) * ( sizeof(Thread_Proxy_control) ) )
+
+#define CONFIGURE_MEMORY_FOR_GLOBAL_OBJECTS(_global_objects) \
+ ((_global_objects) * ( sizeof(Objects_MP_Control) ) )
+
+#define CONFIGURE_MEMORY_FOR_MP \
+ ( CONFIGURE_MEMORY_FOR_PROXIES(CONFIGURE_MP_MAXIMUM_PROXIES) + \
+ CONFIGURE_MEMORY_FOR_GLOBAL_OBJECTS(CONFIGURE_MP_MAXIMUM_GLOBAL_OBJECTS) + \
+ CONFIGURE_MEMORY_FOR_TASKS(1) \
+ )
+
+#endif /* CONFIGURE_HAS_OWN_MULTIPROCESING_TABLE */
+
+#else
+
+#define CONFIGURE_MEMORY_FOR_MP 0
+
+#endif
+
+#ifndef CONFIGURE_MEMORY_OVERHEAD
+#define CONFIGURE_MEMORY_OVERHEAD 0
+#endif
+
+#ifndef CONFIGURE_EXTRA_TASK_STACKS
+#define CONFIGURE_EXTRA_TASK_STACKS 0
+#endif
+
+#define CONFIGURE_API_MUTEX_MEMORY \
+ ( (1) * \
+ ( sizeof(API_Mutex_Control) + CONFIGURE_OBJECT_TABLE_STUFF ) \
+ )
+
+#define CONFIGURE_MEMORY_FOR_SYSTEM_OVERHEAD \
+ ( CONFIGURE_MEMORY_FOR_TASKS(1) + /* IDLE */ \
+ (256 * 12) + /* Ready chains */ \
+ 256 + /* name/ptr table overhead */ \
+ CONFIGURE_INTERRUPT_STACK_MEMORY + /* interrupt stack */ \
+ CONFIGURE_API_MUTEX_MEMORY /* allocation mutex */ \
+ )
+
+/*
+ * Now account for any extra memory that initialization tasks or threads
+ * may have requested.
+ */
+
+#ifdef RTEMS_POSIX_API
+#define CONFIGURE_INITIALIZATION_THREADS_STACKS_POSIX_PART \
+ (CONFIGURE_POSIX_INIT_THREAD_STACK_SIZE - RTEMS_MINIMUM_STACK_SIZE)
+#else
+#define CONFIGURE_INITIALIZATION_THREADS_STACKS_POSIX_PART 0
+#endif
+#ifdef RTEMS_ITRON_API
+#define CONFIGURE_INITIALIZATION_THREADS_STACKS_ITRON_PART \
+ (CONFIGURE_ITRON_INIT_TASK_STACK_SIZE - RTEMS_MINIMUM_STACK_SIZE)
+#else
+#define CONFIGURE_INITIALIZATION_THREADS_STACKS_ITRON_PART 0
+#endif
+
+#define CONFIGURE_INITIALIZATION_THREADS_STACKS \
+ ((CONFIGURE_INIT_TASK_STACK_SIZE - RTEMS_MINIMUM_STACK_SIZE) + \
+ CONFIGURE_INITIALIZATION_THREADS_STACKS_POSIX_PART + \
+ CONFIGURE_INITIALIZATION_THREADS_STACKS_ITRON_PART)
+
+#define CONFIGURE_EXECUTIVE_RAM_SIZE \
+(( CONFIGURE_MEMORY_FOR_POSIX + \
+ CONFIGURE_MEMORY_FOR_ITRON + \
+ CONFIGURE_MEMORY_FOR_TASKS(CONFIGURE_MAXIMUM_TASKS + \
+ CONFIGURE_MAXIMUM_POSIX_THREADS + CONFIGURE_MAXIMUM_ADA_TASKS + \
+ CONFIGURE_MAXIMUM_ITRON_TASKS ) + \
+ CONFIGURE_INITIALIZATION_THREADS_STACKS + \
+ CONFIGURE_MEMORY_FOR_TIMERS(CONFIGURE_MAXIMUM_TIMERS) + \
+ CONFIGURE_MEMORY_FOR_SEMAPHORES(CONFIGURE_MAXIMUM_SEMAPHORES + \
+ CONFIGURE_LIBIO_SEMAPHORES + CONFIGURE_TERMIOS_SEMAPHORES) + \
+ CONFIGURE_MEMORY_FOR_MESSAGE_QUEUES(CONFIGURE_MAXIMUM_MESSAGE_QUEUES) + \
+ CONFIGURE_MEMORY_FOR_PARTITIONS(CONFIGURE_MAXIMUM_PARTITIONS) + \
+ CONFIGURE_MEMORY_FOR_REGIONS( \
+ CONFIGURE_MAXIMUM_REGIONS + CONFIGURE_MALLOC_REGION ) + \
+ CONFIGURE_MEMORY_FOR_PORTS(CONFIGURE_MAXIMUM_PORTS) + \
+ CONFIGURE_MEMORY_FOR_PERIODS(CONFIGURE_MAXIMUM_PERIODS) + \
+ CONFIGURE_MEMORY_FOR_USER_EXTENSIONS( \
+ CONFIGURE_MAXIMUM_USER_EXTENSIONS + CONFIGURE_NEWLIB_EXTENSION + \
+ CONFIGURE_STACK_CHECKER_EXTENSION ) + \
+ CONFIGURE_MEMORY_FOR_DEVICES(CONFIGURE_MAXIMUM_DEVICES) + \
+ CONFIGURE_MEMORY_FOR_MP + \
+ CONFIGURE_MEMORY_FOR_SYSTEM_OVERHEAD + \
+ (((CONFIGURE_MEMORY_OVERHEAD)+1) * 1024) + \
+ (CONFIGURE_EXTRA_TASK_STACKS) + (CONFIGURE_ADA_TASKS_STACK) \
+) & 0xfffffc00)
+#endif
+
+#ifdef CONFIGURE_GNAT_RTEMS
+#define CONFIGURE_GNAT_MUTEXES 10
+#define CONFIGURE_GNAT_KEYS 1
+
+/* 20 are required to run all tests in the ACVC */
+#ifndef CONFIGURE_MAXIMUM_ADA_TASKS
+#define CONFIGURE_MAXIMUM_ADA_TASKS 20
+#endif
+
+/* This is the number of non-Ada tasks which invoked Ada code. */
+#ifndef CONFIGURE_MAXIMUM_FAKE_ADA_TASKS
+#define CONFIGURE_MAXIMUM_FAKE_ADA_TASKS 0
+#endif
+
+/* Ada tasks are allocated twice the minimum stack space */
+#define CONFIGURE_ADA_TASKS_STACK \
+ (CONFIGURE_MAXIMUM_ADA_TASKS * (RTEMS_MINIMUM_STACK_SIZE + (6 * 1024)))
+
+#else
+#define CONFIGURE_GNAT_MUTEXES 0
+#define CONFIGURE_GNAT_KEYS 0
+#define CONFIGURE_MAXIMUM_ADA_TASKS 0
+#define CONFIGURE_MAXIMUM_FAKE_ADA_TASKS 0
+#define CONFIGURE_ADA_TASKS_STACK 0
+#endif
+
+
+#ifdef CONFIGURE_INIT
+
+rtems_api_configuration_table Configuration_RTEMS_API = {
+ CONFIGURE_MAXIMUM_TASKS,
+ CONFIGURE_MAXIMUM_TIMERS,
+ CONFIGURE_MAXIMUM_SEMAPHORES + CONFIGURE_LIBIO_SEMAPHORES +
+ CONFIGURE_TERMIOS_SEMAPHORES,
+ CONFIGURE_MAXIMUM_MESSAGE_QUEUES,
+ CONFIGURE_MAXIMUM_PARTITIONS,
+ CONFIGURE_MAXIMUM_REGIONS + CONFIGURE_MALLOC_REGION,
+ CONFIGURE_MAXIMUM_PORTS,
+ CONFIGURE_MAXIMUM_PERIODS,
+ CONFIGURE_INIT_TASK_TABLE_SIZE,
+ CONFIGURE_INIT_TASK_TABLE
+};
+
+#ifdef RTEMS_POSIX_API
+posix_api_configuration_table Configuration_POSIX_API = {
+ CONFIGURE_MAXIMUM_POSIX_THREADS + CONFIGURE_MAXIMUM_ADA_TASKS,
+ CONFIGURE_MAXIMUM_POSIX_MUTEXES + CONFIGURE_GNAT_MUTEXES +
+ CONFIGURE_MAXIMUM_ADA_TASKS + CONFIGURE_MAXIMUM_FAKE_ADA_TASKS,
+ CONFIGURE_MAXIMUM_POSIX_CONDITION_VARIABLES +
+ CONFIGURE_MAXIMUM_ADA_TASKS + CONFIGURE_MAXIMUM_FAKE_ADA_TASKS,
+ CONFIGURE_MAXIMUM_POSIX_KEYS + CONFIGURE_GNAT_KEYS,
+ CONFIGURE_MAXIMUM_POSIX_TIMERS,
+ CONFIGURE_MAXIMUM_POSIX_QUEUED_SIGNALS,
+ CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES,
+ CONFIGURE_MAXIMUM_POSIX_SEMAPHORES,
+ CONFIGURE_POSIX_INIT_THREAD_TABLE_SIZE,
+ CONFIGURE_POSIX_INIT_THREAD_TABLE_NAME
+};
+#endif
+
+#ifdef RTEMS_ITRON_API
+itron_api_configuration_table Configuration_ITRON_API = {
+ CONFIGURE_MAXIMUM_ITRON_TASKS,
+ CONFIGURE_MAXIMUM_ITRON_SEMAPHORES,
+ CONFIGURE_MAXIMUM_ITRON_EVENTFLAGS,
+ CONFIGURE_MAXIMUM_ITRON_MAILBOXES,
+ CONFIGURE_MAXIMUM_ITRON_MESSAGE_BUFFERS,
+ CONFIGURE_MAXIMUM_ITRON_PORTS,
+ CONFIGURE_MAXIMUM_ITRON_MEMORY_POOLS,
+ CONFIGURE_MAXIMUM_ITRON_FIXED_MEMORY_POOLS,
+ CONFIGURE_ITRON_INIT_TASK_TABLE_SIZE,
+ CONFIGURE_ITRON_INIT_TASK_TABLE_NAME
+};
+#endif
+
+rtems_configuration_table Configuration = {
+ CONFIGURE_EXECUTIVE_RAM_WORK_AREA,
+ CONFIGURE_EXECUTIVE_RAM_SIZE,
+ CONFIGURE_MAXIMUM_USER_EXTENSIONS + CONFIGURE_NEWLIB_EXTENSION +
+ CONFIGURE_STACK_CHECKER_EXTENSION,
+ CONFIGURE_MICROSECONDS_PER_TICK,
+ CONFIGURE_TICKS_PER_TIMESLICE,
+ CONFIGURE_MAXIMUM_DEVICES,
+ CONFIGURE_MAXIMUM_DRIVERS,
+ CONFIGURE_NUMBER_OF_DRIVERS, /* number of device drivers */
+ Device_drivers, /* pointer to driver table */
+ CONFIGURE_NUMBER_OF_INITIAL_EXTENSIONS, /* number of initial extensions */
+ CONFIGURE_INITIAL_EXTENSION_TABLE, /* pointer to initial extensions */
+ CONFIGURE_MULTIPROCESSING_TABLE, /* pointer to MP config table */
+ &Configuration_RTEMS_API, /* pointer to RTEMS API config */
+#ifdef RTEMS_POSIX_API
+ &Configuration_POSIX_API, /* pointer to POSIX API config */
+#else
+ NULL, /* pointer to POSIX API config */
+#endif
+#ifdef RTEMS_ITRON_API
+ &Configuration_ITRON_API /* pointer to ITRON API config */
+#else
+ NULL /* pointer to ITRON API config */
+#endif
+};
+#endif
+
+#endif /* CONFIGURE_HAS_OWN_CONFIGURATION_TABLE */
+
+#ifdef __cplusplus
+}
+#endif
+
+/*
+ * Some warnings and error checking
+ */
+
+/*
+ * Make sure a task/thread of some sort is configured
+ */
+
+#if (CONFIGURE_MAXIMUM_TASKS == 0) && \
+ (CONFIGURE_MAXIMUM_POSIX_THREADS == 0) && \
+ (CONFIGURE_MAXIMUM_ADA_TASKS == 0) && \
+ (CONFIGURE_MAXIMUM_ITRON_TASKS == 0)
+#error "CONFIGURATION ERROR: No tasks or threads configured!!"
+#endif
+
+/*
+ * Make sure at least one of the initialization task/thread
+ * tables was defined.
+ */
+
+#if !defined(CONFIGURE_RTEMS_INIT_TASKS_TABLE) && \
+ !defined(CONFIGURE_POSIX_INIT_THREAD_TABLE) && \
+ !defined(CONFIGURE_ITRON_INIT_TASK_TABLE)
+#error "CONFIGURATION ERROR: No initialization tasks or threads configured!!"
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/sapi/include/rtems/README b/cpukit/sapi/include/rtems/README
new file mode 100644
index 0000000000..f29bdb45b7
--- /dev/null
+++ b/cpukit/sapi/include/rtems/README
@@ -0,0 +1,133 @@
+#
+# $Id$
+#
+
+Configuring a System Using the Template in confdefs.h
+=====================================================
+
+The file confdefs.h is a Configuration Template file which can be
+used to greatly simplify the creation and maintenance of RTEMS
+Configuration Tables. The basic concepts are:
+
+ + confdefs.h provides defaults for all configuration parameters
+
+ + applications specify only those values they wish to override
+
+ + confdefs.h can be the only file which knows the precise layout
+ of the RTEMS Configuration Tables.
+
+The Configuration Template setup is used by all RTEMS tests to
+simplify the maintenance of the tests.
+
+Here is the section from the system.h file from test tm21 from
+the Timing Test Suite:
+
+ /* configuration information */
+
+ #define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+ #define CONFIGURE_APPLICATION_NEEDS_TIMER_DRIVER
+
+ #define CONFIGURE_MAXIMUM_TASKS 102
+ #define CONFIGURE_MAXIMUM_TIMERS 100
+ #define CONFIGURE_MAXIMUM_SEMAPHORES 100
+ #define CONFIGURE_MAXIMUM_MESSAGE_QUEUES 100
+ #define CONFIGURE_MAXIMUM_PARTITIONS 100
+ #define CONFIGURE_MAXIMUM_REGIONS 100
+ #define CONFIGURE_MAXIMUM_PORTS 100
+ #define CONFIGURE_MAXIMUM_PERIODS 100
+
+ #define CONFIGURE_TICKS_PER_TIMESLICE 0
+
+ #include <confdefs.h>
+
+
+The above example overrides a number of the configuration parameters.
+It informs the template that it is a member of the Timing Suite,
+requires a console and timer driver, and that it needs 102 tasks,
+100 timers, 100 semaphores, 100 message queues, 100 partitions,
+100 regions, 100 ports, and 100 periods. By default, the test
+would have gotten no drivers, 10 tasks, and no other RTEMS objects.
+
+The following shows the configuration tables generated by the
+template by default.
+
+
+#include <bsp.h>
+
+#define NULL_DRIVER_TABLE_ENTRY \
+ { NULL, NULL, NULL, NULL, NULL, NULL }
+
+rtems_driver_address_table Device_drivers[] = {
+#ifdef CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+ CONSOLE_DRIVER_TABLE_ENTRY,
+#endif
+#ifdef CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+ CLOCK_DRIVER_TABLE_ENTRY,
+#endif
+#ifdef CONFIGURE_APPLICATION_NEEDS_STUB_DRIVER
+ STUB_DRIVER_TABLE_ENTRY,
+#endif
+ NULL_DRIVER_TABLE_ENTRY,
+};
+
+rtems_initialization_tasks_table Initialization_tasks[] = {
+ { rtems_build_name( 'U', 'I', '1', ' ' ), /* init task name */
+ RTEMS_MINIMUM_STACK_SIZE, /* init task stack size */
+ 1, /* init task priority */
+ RTEMS_DEFAULT_ATTRIBUTES, /* init task attributes */
+ Init, /* init task entry point */
+ RTEMS_NO_PREEMPT, /* init task initial mode */
+ 0 /* init task argument list */
+ }
+};
+
+#ifdef CONFIGURE_MP_APPLICATION
+/*
+ * NODE_NUMBER is assumed to be set on the compile line.
+ */
+
+rtems_multiprocessing_table Multiprocessing_configuration = {
+ NODE_NUMBER, /* local node number */
+ 2, /* maximum # nodes in system */
+ 32, /* maximum # global objects */
+ 32, /* maximum # proxies */
+ &MPCI_table /* pointer to MPCI config table */
+};
+#endif
+
+/*
+ * CONFIGURE_EXECUTIVE_RAM_SIZE is a rough guess based on the number of
+ * tasks in the system plus enough extra to get a whole 64K extra.
+ *
+ * The NULL address for the workspace area is assumed to be assigned
+ * at startup time by the BSP.
+ */
+
+rtems_configuration_table Configuration = {
+ NULL, /* executive RAM work area */
+ CONFIGURE_EXECUTIVE_RAM_SIZE, /* executive RAM size */
+ 10, /* maximum # tasks */
+ 0, /* maximum # timers */
+ 0, /* maximum # semaphores */
+ 0, /* maximum # message queues */
+ 0, /* maximum # messages */
+ 0, /* maximum # partitions */
+ 0, /* maximum # regions */
+ 0, /* maximum # dp memory areas */
+ 0, /* maximum # periods */
+ 0, /* maximum # user extensions */
+ RTEMS_MILLISECONDS_TO_MICROSECONDS(10), /* # us in a tick */
+ 50, /* # ticks in a timeslice */
+ sizeof (Initialization_tasks) / sizeof(rtems_initialization_tasks_table),
+ /* number of init tasks */
+ Initialization_tasks, /* init task(s) table */
+ sizeof (Device_drivers) / sizeof(rtems_driver_address_table),
+ /* number of device drivers */
+ Device_drivers, /* pointer to driver address table */
+ NULL, /* pointer to initial extensions */
+#ifdef CONFIGURE_MP_APPLICATION
+ &Multiprocessing_configuration
+#else
+ NULL /* ptr to MP config table */
+#endif
+};
diff --git a/cpukit/sapi/include/rtems/config.h b/cpukit/sapi/include/rtems/config.h
new file mode 100644
index 0000000000..ca477d4571
--- /dev/null
+++ b/cpukit/sapi/include/rtems/config.h
@@ -0,0 +1,183 @@
+/* config.h
+ *
+ * This include file contains the table of user defined configuration
+ * parameters.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_CONFIGURATION_h
+#define __RTEMS_CONFIGURATION_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Unlimited object support. Changes the configuration table entry for POSIX
+ * or RTEMS APIs to bounded only by the memory of the work-space.
+ *
+ * Use the macro to define the resource unlimited before placing in
+ * the configuration table.
+ */
+
+#include <rtems/score/object.h>
+#define RTEMS_UNLIMITED_OBJECTS OBJECTS_UNLIMITED_OBJECTS
+
+#define rtems_resource_unlimited(resource) \
+ ( resource | RTEMS_UNLIMITED_OBJECTS )
+
+/*
+ * This is kind of kludgy but it allows targets to totally ignore the
+ * optional APIs like POSIX and ITRON safely.
+ */
+
+#ifdef RTEMS_POSIX_API
+#include <rtems/posix/config.h>
+#else
+typedef void *posix_api_configuration_table;
+#endif
+
+#ifdef RTEMS_ITRON_API
+#include <rtems/itron.h>
+#include <rtems/itron/config.h>
+#else
+typedef void *itron_api_configuration_table;
+#endif
+
+#include <rtems/rtems/config.h>
+
+/* XXX <rtems/rtems/config.h> should cover these
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/types.h>
+#include <rtems/rtems/tasks.h>
+*/
+
+#include <rtems/extension.h>
+#include <rtems/io.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+
+/*
+ * The following records define the Multiprocessor Configuration
+ * Table. This table defines the multiprocessor system
+ * characteristics which must be known by RTEMS in a multiprocessor
+ * system.
+ */
+
+typedef struct {
+ uint32_t node; /* local node number */
+ uint32_t maximum_nodes; /* maximum # nodes in system */
+ uint32_t maximum_global_objects; /* maximum # global objects */
+ uint32_t maximum_proxies; /* maximum # proxies */
+#if defined(RTEMS_MULTIPROCESSING)
+ rtems_mpci_table *User_mpci_table; /* pointer to MPCI table */
+#else
+ void *User_mpci_table; /* pointer to MPCI table */
+#endif
+} rtems_multiprocessing_table;
+
+/*
+ * The following records define the Configuration Table. The
+ * information contained in this table is required in all
+ * RTEMS systems, whether single or multiprocessor. This
+ * table primarily defines the following:
+ *
+ * + location and size of the RTEMS Workspace
+ * + microseconds per clock tick
+ * + clock ticks per task timeslice
+ * + required number of each object type for each API configured
+ */
+
+typedef struct {
+ void *work_space_start;
+ uint32_t work_space_size;
+ uint32_t maximum_extensions;
+ uint32_t microseconds_per_tick;
+ uint32_t ticks_per_timeslice;
+ uint32_t maximum_devices;
+ uint32_t maximum_drivers;
+ uint32_t number_of_device_drivers;
+ rtems_driver_address_table *Device_driver_table;
+ uint32_t number_of_initial_extensions;
+ rtems_extensions_table *User_extension_table;
+ rtems_multiprocessing_table *User_multiprocessing_table;
+ rtems_api_configuration_table *RTEMS_api_configuration;
+ posix_api_configuration_table *POSIX_api_configuration;
+ itron_api_configuration_table *ITRON_api_configuration;
+} rtems_configuration_table;
+
+/*
+ * The following are provided strictly for the convenience of
+ * the user. They are not used in RTEMS itself.
+ */
+
+SAPI_EXTERN rtems_configuration_table *_Configuration_Table;
+SAPI_EXTERN rtems_multiprocessing_table *_Configuration_MP_table;
+
+/*
+ * Some handy macros to avoid dependencies on either the BSP
+ * or the exact format of the configuration table.
+ */
+
+#define rtems_configuration_get_table() \
+ (&_Configuration_Table)
+
+#define rtems_configuration_get_work_space_start() \
+ (_Configuration_Table->work_space_start)
+
+#define rtems_configuration_get_work_space_size() \
+ (_Configuration_Table->work_space_size)
+
+#define rtems_configuration_get_maximum_extensions() \
+ (_Configuration_Table->maximum_extensions)
+
+#define rtems_configuration_get_microseconds_per_tick() \
+ (_Configuration_Table->microseconds_per_tick)
+#define rtems_configuration_get_milliseconds_per_tick() \
+ (_Configuration_Table->microseconds_per_tick / 1000)
+
+#define rtems_configuration_get_ticks_per_timeslice() \
+ (_Configuration_Table->ticks_per_timeslice)
+
+#define rtems_configuration_get_maximum_devices() \
+ (_Configuration_Table->maximum_devices)
+
+#define rtems_configuration_get_number_of_device_drivers() \
+ (_Configuration_Table->number_of_device_drivers)
+
+#define rtems_configuration_get_device_driver_table() \
+ (_Configuration_Table->device_driver_table)
+
+#define rtems_configuration_get_number_of_initial_extensions() \
+ (_Configuration_Table->number_of_initial_extensions)
+
+#define rtems_configuration_get_user_extension_table() \
+ (_Configuration_Table->user_extension_table)
+
+#define rtems_configuration_get_user_multiprocessing_table() \
+ (_Configuration_Table->User_multiprocessing_table)
+
+#define rtems_configuration_get_rtems_api_configuration() \
+ (_Configuration_Table->RTEMS_api_configuration)
+
+#define rtems_configuration_get_posix_api_configuration() \
+ (_Configuration_Table->POSIX_api_configuration)
+
+#define rtems_configuration_get_itron_api_configuration() \
+ (_Configuration_Table->ITRON_api_configuration)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/sapi/include/rtems/extension.h b/cpukit/sapi/include/rtems/extension.h
new file mode 100644
index 0000000000..5b6d393620
--- /dev/null
+++ b/cpukit/sapi/include/rtems/extension.h
@@ -0,0 +1,137 @@
+/* extension.h
+ *
+ * This include file contains all the constants, structures, and
+ * prototypes associated with the User Extension Manager. This manager
+ * provides a mechanism for manipulating sets of user-defined extensions.
+ *
+ * Directives provided are:
+ *
+ * + create user extension set
+ * + get ID of user extension set
+ * + delete user extension set
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_EXTENSION_MANAGER_h
+#define __RTEMS_EXTENSION_MANAGER_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/object.h>
+#include <rtems/score/userext.h>
+#include <rtems/rtems/status.h> /* XXX */
+#include <rtems/rtems/types.h> /* XXX */
+
+/*
+ * Extension related types
+ */
+
+typedef User_extensions_routine rtems_extension;
+typedef User_extensions_thread_create_extension rtems_task_create_extension;
+typedef User_extensions_thread_delete_extension rtems_task_delete_extension;
+typedef User_extensions_thread_start_extension rtems_task_start_extension;
+typedef User_extensions_thread_restart_extension rtems_task_restart_extension;
+typedef User_extensions_thread_switch_extension rtems_task_switch_extension;
+typedef User_extensions_thread_post_switch_extension
+ rtems_task_post_switch_extension;
+typedef User_extensions_thread_begin_extension rtems_task_begin_extension;
+typedef User_extensions_thread_exitted_extension rtems_task_exitted_extension;
+typedef User_extensions_fatal_extension rtems_fatal_extension;
+
+typedef User_extensions_Table rtems_extensions_table;
+
+/*
+ * The following defines the information control block used to manage
+ * this class of objects.
+ */
+
+SAPI_EXTERN Objects_Information _Extension_Information;
+
+/*
+ * The following records define the control block used to manage
+ * each extension.
+ */
+
+typedef struct {
+ Objects_Control Object;
+ User_extensions_Control Extension;
+} Extension_Control;
+
+/*
+ * _Extension_Manager_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this manager.
+ */
+
+void _Extension_Manager_initialization(
+ uint32_t maximum_extensions
+);
+
+/*
+ * rtems_extension_create
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_extension_create directive. The
+ * extension will have the name name. The entry points of the
+ * routines which constitute this extension set are in EXTENSION_TABLE.
+ * It returns the id of the created extension in ID.
+ */
+
+rtems_status_code rtems_extension_create(
+ rtems_name name,
+ rtems_extensions_table *extension_table,
+ Objects_Id *id
+);
+
+/*
+ * rtems_extension_ident
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_extension_ident directive.
+ * This directive returns the extension ID associated with name.
+ * If more than one extension is named name, then the extension
+ * to which the ID belongs is arbitrary.
+ */
+
+rtems_status_code rtems_extension_ident(
+ rtems_name name,
+ Objects_Id *id
+);
+
+/*
+ * rtems_extension_delete
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_extension_delete directive. The
+ * extension indicated by ID is deleted.
+ */
+
+rtems_status_code rtems_extension_delete(
+ Objects_Id id
+);
+
+#ifndef __RTEMS_APPLICATION__
+#include <rtems/extension.inl>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/sapi/include/rtems/fatal.h b/cpukit/sapi/include/rtems/fatal.h
new file mode 100644
index 0000000000..5f67bb4b2b
--- /dev/null
+++ b/cpukit/sapi/include/rtems/fatal.h
@@ -0,0 +1,48 @@
+/* fatal.h
+ *
+ * This include file contains constants and prototypes related
+ * to the Fatal Error Manager. This manager processes all fatal or
+ * irrecoverable errors.
+ *
+ * This manager provides directives to:
+ *
+ * + announce a fatal error has occurred
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_FATAL_h
+#define __RTEMS_FATAL_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * rtems_fatal_error_occurred
+ *
+ * DESCRIPTION:
+ *
+ * This is the routine which implements the rtems_fatal_error_occurred
+ * directive. It is invoked when the application or RTEMS
+ * determines that a fatal error has occurred.
+ */
+
+void volatile rtems_fatal_error_occurred(
+ uint32_t the_error
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/sapi/include/rtems/init.h b/cpukit/sapi/include/rtems/init.h
new file mode 100644
index 0000000000..d17c17d5be
--- /dev/null
+++ b/cpukit/sapi/include/rtems/init.h
@@ -0,0 +1,109 @@
+/* init.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the Initialization Manager. This manager is responsible for
+ * initializing RTEMS, creating and starting all configured initialization
+ * tasks, invoking the initialization routine for each user-supplied device
+ * driver, and initializing the optional multiprocessor layer.
+ *
+ * This manager provides directives to:
+ *
+ * + initialize the RTEMS executive
+ * + shutdown the RTEMS executive
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_INIT_h
+#define __RTEMS_INIT_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/rtems/types.h>
+#include <rtems/config.h>
+#include <rtems/rtems/intr.h>
+
+/*
+ * The following defines the default Multiprocessing Configuration
+ * Table. This table is used in a single processor system.
+ */
+
+extern const rtems_multiprocessing_table
+ _Initialization_Default_multiprocessing_table;
+
+/*
+ * rtems_initialize_executive
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_initialize_executive directive. This
+ * directive is invoked at system startup to initialize the RTEMS
+ * multitasking environment.
+ */
+
+void rtems_initialize_executive(
+ rtems_configuration_table *configuration_table,
+ rtems_cpu_table *cpu_table
+);
+
+/*
+ * rtems_initialize_executive_early
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the early portion of rtems_initialize_executive
+ * directive up to the pretasking hook. This directive is invoked at system
+ * startup to initialize the RTEMS multitasking environment.
+ */
+
+rtems_interrupt_level rtems_initialize_executive_early(
+ rtems_configuration_table *configuration_table,
+ rtems_cpu_table *cpu_table
+);
+
+/*
+ * rtems_initialize_executive_late
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the early portion of rtems_initialize_executive
+ * directive up to the pretasking hook. This directive is invoked at system
+ * startup to initialize the RTEMS multitasking environment.
+ */
+
+void rtems_initialize_executive_late(
+ rtems_interrupt_level bsp_level
+);
+
+/*
+ * rtems_shutdown_executive
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_shutdown_executive directive. The
+ * invocation of this directive results in the RTEMS environment being
+ * shutdown and multitasking halted. From the application's perspective,
+ * invocation of this directive results in the rtems_initialize_executive
+ * directive exitting to the startup code which invoked it.
+ */
+
+void rtems_shutdown_executive(
+ uint32_t result
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/sapi/include/rtems/io.h b/cpukit/sapi/include/rtems/io.h
new file mode 100644
index 0000000000..8cdf687ae7
--- /dev/null
+++ b/cpukit/sapi/include/rtems/io.h
@@ -0,0 +1,272 @@
+/* io.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the Input/Output Manager. This manager provides a well defined
+ * mechanism for accessing device drivers and a structured methodology for
+ * organizing device drivers.
+ *
+ * Directives provided are:
+ *
+ * + initialize a device driver
+ * + open a device driver
+ * + close a device driver
+ * + read from a device driver
+ * + write to a device driver
+ * + special device services
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_IO_h
+#define __RTEMS_IO_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/rtems/status.h>
+
+/*
+ *
+ * The following defines the types for:
+ *
+ * + major and minor numbers
+ * + the return type of a device driver entry
+ * + a pointer to a device driver entry
+ * + an entry in the the Device Driver Address Table. Each entry in this
+ * table corresponds to an application provided device driver and
+ * defines the entry points for that device driver.
+ */
+
+typedef uint32_t rtems_device_major_number;
+typedef uint32_t rtems_device_minor_number;
+
+typedef rtems_status_code rtems_device_driver;
+
+typedef rtems_device_driver ( *rtems_device_driver_entry )(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *
+ );
+
+typedef struct {
+ rtems_device_driver_entry initialization_entry; /* initialization procedure */
+ rtems_device_driver_entry open_entry; /* open request procedure */
+ rtems_device_driver_entry close_entry; /* close request procedure */
+ rtems_device_driver_entry read_entry; /* read request procedure */
+ rtems_device_driver_entry write_entry; /* write request procedure */
+ rtems_device_driver_entry control_entry; /* special functions procedure */
+} rtems_driver_address_table;
+
+/*
+ * Table for the io device names
+ */
+
+typedef struct {
+ char *device_name;
+ uint32_t device_name_length;
+ rtems_device_major_number major;
+ rtems_device_minor_number minor;
+} rtems_driver_name_t;
+
+/*
+ * This is the table of device names.
+ */
+
+/*
+ * The following declare the data required to manage the Driver
+ * Address Table and Device Name Table.
+ */
+
+SAPI_EXTERN uint32_t _IO_Number_of_drivers;
+SAPI_EXTERN rtems_driver_address_table *_IO_Driver_address_table;
+SAPI_EXTERN uint32_t _IO_Number_of_devices;
+SAPI_EXTERN rtems_driver_name_t *_IO_Driver_name_table;
+
+/*
+ * _IO_Manager_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this manager.
+ */
+
+void _IO_Manager_initialization(
+ rtems_driver_address_table *driver_table,
+ uint32_t drivers_in_table,
+ uint32_t number_of_drivers,
+ uint32_t number_of_devices
+);
+
+/*
+ * rtems_io_register_driver
+ *
+ * DESCRIPTION:
+ *
+ * Register a driver into the device driver table.
+ *
+ */
+
+rtems_status_code rtems_io_register_driver(
+ rtems_device_major_number major,
+ rtems_driver_address_table *driver_table,
+ rtems_device_major_number *registered_major
+);
+
+/*
+ * rtems_io_unregister_driver
+ *
+ * DESCRIPTION:
+ *
+ * Unregister a driver from the device driver table.
+ *
+ */
+
+rtems_status_code rtems_io_unregister_driver(
+ rtems_device_major_number major
+);
+
+/*
+ * rtems_io_register_name
+ *
+ * DESCRIPTION:
+ *
+ * Associate a name with a driver.
+ *
+ */
+
+rtems_status_code rtems_io_register_name(
+ char *device_name,
+ rtems_device_major_number major,
+ rtems_device_minor_number minor
+);
+
+
+/*
+ * rtems_io_lookup_name
+ *
+ * DESCRIPTION:
+ *
+ * Find what driver "owns" this name
+ */
+
+rtems_status_code rtems_io_lookup_name(
+ const char *name,
+ rtems_driver_name_t *device_info
+);
+
+
+/*
+ * rtems_io_initialize
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_io_initialize directive. It is invoked
+ * to initialize a device driver or an individual device.
+ */
+
+rtems_status_code rtems_io_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *argument
+);
+
+/*
+ * rtems_io_open
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_io_open directive. It is invoked
+ * to open a device.
+ */
+
+rtems_status_code rtems_io_open(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *argument
+);
+
+/*
+ * rtems_io_close
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_io_close directive. It is invoked
+ * to close a device.
+ */
+
+rtems_status_code rtems_io_close(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *argument
+);
+
+/*
+ * rtems_io_read
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_io_read directive. It is invoked
+ * to read from a device.
+ */
+
+rtems_status_code rtems_io_read(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *argument
+);
+
+/*
+ * rtems_io_write
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_io_write directive. It is invoked
+ * to write to a device.
+ */
+
+rtems_status_code rtems_io_write(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *argument
+);
+
+/*
+ * rtems_io_control
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the rtems_io_control directive. It is invoked
+ * to perform a device specific operation on a device.
+ */
+
+rtems_status_code rtems_io_control(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *argument
+);
+
+/*
+ * _IO_Initialize_all_drivers
+ *
+ * DESCRIPTION:
+ *
+ * This routine initializes all of the device drivers configured
+ * in the Device Driver Address Table.
+ */
+
+void _IO_Initialize_all_drivers( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/sapi/include/rtems/mptables.h b/cpukit/sapi/include/rtems/mptables.h
new file mode 100644
index 0000000000..d9e79b77dc
--- /dev/null
+++ b/cpukit/sapi/include/rtems/mptables.h
@@ -0,0 +1,28 @@
+/* mptables.h
+ *
+ * This include file contains the executive's pre-initialized tables
+ * used in a multiprocessor configuration.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_MPTABLES_h
+#define __RTEMS_MPTABLES_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/sapi/include/rtems/sptables.h b/cpukit/sapi/include/rtems/sptables.h
new file mode 100644
index 0000000000..93507ae250
--- /dev/null
+++ b/cpukit/sapi/include/rtems/sptables.h
@@ -0,0 +1,71 @@
+/* sptables.h
+ *
+ * This include file contains the executive's pre-initialized tables
+ * used when in a single processor configuration.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_SPTABLES_h
+#define __RTEMS_SPTABLES_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/config.h>
+
+#include <rtems/debug.h>
+#include <rtems/fatal.h>
+#include <rtems/init.h>
+#include <rtems/io.h>
+#include <rtems/score/sysstate.h>
+
+#include <rtems/rtems/intr.h>
+#include <rtems/rtems/clock.h>
+#include <rtems/rtems/tasks.h>
+#include <rtems/rtems/dpmem.h>
+#include <rtems/rtems/event.h>
+#include <rtems/rtems/message.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/rtems/mp.h>
+#endif
+#include <rtems/rtems/part.h>
+#include <rtems/rtems/ratemon.h>
+#include <rtems/rtems/region.h>
+#include <rtems/rtems/sem.h>
+#include <rtems/rtems/signal.h>
+#include <rtems/rtems/timer.h>
+
+/*
+ * This is the default Multiprocessing Configuration Table.
+ * It is used in single processor configurations.
+ */
+
+#if defined(SAPI_INIT)
+const rtems_multiprocessing_table
+ _Initialization_Default_multiprocessing_table = {
+ 1, /* local node number */
+ 1, /* maximum number nodes in system */
+ 0, /* maximum number global objects */
+ 0, /* maximum number proxies */
+ NULL, /* pointer to MPCI address table */
+};
+#else
+extern const rtems_multiprocessing_table
+ _Initialization_Default_multiprocessing_table;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/sapi/inline/rtems/extension.inl b/cpukit/sapi/inline/rtems/extension.inl
new file mode 100644
index 0000000000..a7507b2306
--- /dev/null
+++ b/cpukit/sapi/inline/rtems/extension.inl
@@ -0,0 +1,90 @@
+/* extension.inl
+ *
+ * This file contains the static inline implementation of the inlined routines
+ * from the Extension Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __EXTENSION_MANAGER_inl
+#define __EXTENSION_MANAGER_inl
+
+/*PAGE
+ *
+ * _Extension_Allocate
+ *
+ * DESCRIPTION:
+ *
+ * This function allocates a extension control block from
+ * the inactive chain of free extension control blocks.
+ */
+
+RTEMS_INLINE_ROUTINE Extension_Control *_Extension_Allocate( void )
+{
+ return (Extension_Control *) _Objects_Allocate( &_Extension_Information );
+}
+
+/*PAGE
+ *
+ * _Extension_Free
+ *
+ * DESCRIPTION:
+ *
+ * This routine frees a extension control block to the
+ * inactive chain of free extension control blocks.
+ */
+
+RTEMS_INLINE_ROUTINE void _Extension_Free (
+ Extension_Control *the_extension
+)
+{
+ _Objects_Free( &_Extension_Information, &the_extension->Object );
+}
+
+/*PAGE
+ *
+ * _Extension_Get
+ *
+ * DESCRIPTION:
+ *
+ * This function maps extension IDs to extension control blocks.
+ * If ID corresponds to a local extension, then it returns
+ * the extension control pointer which maps to ID and location
+ * is set to OBJECTS_LOCAL. Otherwise, location is set
+ * to OBJECTS_ERROR and the returned value is undefined.
+ */
+
+RTEMS_INLINE_ROUTINE Extension_Control *_Extension_Get (
+ Objects_Id id,
+ Objects_Locations *location
+)
+{
+ return (Extension_Control *)
+ _Objects_Get( &_Extension_Information, id, location );
+}
+
+/*PAGE
+ *
+ * _Extension_Is_null
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_extension is NULL and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Extension_Is_null (
+ Extension_Control *the_extension
+)
+{
+ return ( the_extension == NULL );
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/sapi/macros/rtems/extension.inl b/cpukit/sapi/macros/rtems/extension.inl
new file mode 100644
index 0000000000..2acb14114f
--- /dev/null
+++ b/cpukit/sapi/macros/rtems/extension.inl
@@ -0,0 +1,57 @@
+/* extension.inl
+ *
+ * This file contains the macro implementation of the inlined routines
+ * from the Extension Manager.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __EXTENSION_inl
+#define __EXTENSION_inl
+
+/*PAGE
+ *
+ * _Extension_Allocate
+ *
+ */
+
+#define _Extension_Allocate() \
+ (Extension_Control *) _Objects_Allocate( &_Extension_Information )
+
+/*PAGE
+ *
+ * _Extension_Free
+ *
+ */
+
+#define _Extension_Free( _the_extension ) \
+ _Objects_Free( &_Extension_Information, &(_the_extension)->Object )
+
+/*PAGE
+ *
+ * _Extension_Get
+ *
+ */
+
+#define _Extension_Get( _id, _location ) \
+ (Extension_Control *) \
+ _Objects_Get( &_Extension_Information, (_id), (_location) )
+
+/*PAGE
+ *
+ * _Extension_Is_null
+ *
+ */
+
+#define _Extension_Is_null( _the_extension ) \
+ ( (_the_extension) == NULL )
+
+#endif
+/* end of include file */
diff --git a/cpukit/sapi/src/debug.c b/cpukit/sapi/src/debug.c
new file mode 100644
index 0000000000..4f6c68ea5c
--- /dev/null
+++ b/cpukit/sapi/src/debug.c
@@ -0,0 +1,61 @@
+/*
+ * Debug Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/debug.h>
+
+/*PAGE
+ *
+ * _Debug_Manager_initialization
+ */
+
+void _Debug_Manager_initialization( void )
+{
+ rtems_debug_disable( RTEMS_DEBUG_ALL_MASK );
+}
+
+/*PAGE
+ *
+ * rtems_debug_enable
+ */
+
+void rtems_debug_enable (
+ rtems_debug_control to_be_enabled
+)
+{
+ _Debug_Level |= to_be_enabled;
+}
+
+/*PAGE
+ *
+ * rtems_debug_disable
+ */
+
+void rtems_debug_disable (
+ rtems_debug_control to_be_disabled
+)
+{
+ _Debug_Level &= ~to_be_disabled;
+}
+
+/*PAGE
+ *
+ * _Debug_Is_enabled
+ */
+
+boolean _Debug_Is_enabled(
+ rtems_debug_control level
+)
+{
+ return (_Debug_Level & level);
+}
diff --git a/cpukit/sapi/src/exinit.c b/cpukit/sapi/src/exinit.c
new file mode 100644
index 0000000000..82e8c6efab
--- /dev/null
+++ b/cpukit/sapi/src/exinit.c
@@ -0,0 +1,328 @@
+/*
+ * Initialization Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+/*
+ * SCORE_INIT and SAPI_INIT are defined so all of the super core and
+ * super API data will be included in this object file.
+ */
+
+#define SAPI_INIT
+#define SCORE_INIT
+
+#include <rtems/system.h>
+#include <rtems/config.h>
+#include <rtems/debug.h>
+#include <rtems/extension.h>
+#include <rtems/fatal.h>
+#include <rtems/init.h>
+#include <rtems/io.h>
+#include <rtems/score/sysstate.h>
+
+#include <rtems/score/apiext.h>
+#include <rtems/score/apimutex.h>
+#include <rtems/score/copyrt.h>
+#include <rtems/score/heap.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+#include <rtems/score/priority.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/score/wkspace.h>
+
+#include <rtems/sptables.h>
+
+
+#include <rtems/rtems/rtemsapi.h>
+#ifdef RTEMS_POSIX_API
+#include <rtems/posix/posixapi.h>
+#endif
+#ifdef RTEMS_ITRON_API
+#include <rtems/itron/itronapi.h>
+#endif
+
+Objects_Information *_Internal_Objects[ OBJECTS_INTERNAL_CLASSES_LAST + 1 ];
+
+/*PAGE
+ *
+ * rtems_initialize_executive
+ *
+ * This directive initializes all the kernels data structures
+ * to the states necessary for the kernel to begin execution. All
+ * include files that contain global variable definitions should be
+ * included in this file. The system threads and initialization threads
+ * are created and started by this routine. This routine then
+ * initiates multithreading.
+ *
+ * Input parameters:
+ * configuration_table - pointer to the user's configuration table
+ * cpu_table - pointer to the user's CPU configuration table
+ *
+ * Output parameters: NONE
+ */
+
+void rtems_initialize_executive(
+ rtems_configuration_table *configuration_table,
+ rtems_cpu_table *cpu_table
+)
+{
+ rtems_interrupt_level bsp_level;
+
+ bsp_level = rtems_initialize_executive_early(configuration_table, cpu_table);
+ rtems_initialize_executive_late( bsp_level );
+}
+
+rtems_interrupt_level rtems_initialize_executive_early(
+ rtems_configuration_table *configuration_table,
+ rtems_cpu_table *cpu_table
+)
+{
+ rtems_interrupt_level bsp_level;
+ rtems_multiprocessing_table *multiprocessing_table;
+
+ /*
+ * Dispatching and interrupts are disabled until the end of the
+ * initialization sequence. This prevents an inadvertent context
+ * switch before the executive is initialized.
+ */
+
+ _ISR_Disable( bsp_level );
+
+ if ( configuration_table == NULL )
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ TRUE,
+ INTERNAL_ERROR_NO_CONFIGURATION_TABLE
+ );
+
+ /*
+ * Initialize the system state based on whether this is an MP system.
+ */
+
+#if defined(RTEMS_MULTIPROCESSING)
+ multiprocessing_table = configuration_table->User_multiprocessing_table;
+
+ _System_state_Handler_initialization(
+ (multiprocessing_table) ? TRUE : FALSE
+ );
+#else
+ multiprocessing_table = NULL;
+
+ _System_state_Handler_initialization( FALSE );
+#endif
+
+ /*
+ * Provided just for user convenience.
+ */
+
+ _Configuration_Table = configuration_table;
+ _Configuration_MP_table = multiprocessing_table;
+
+ /*
+ * Internally we view single processor systems as a very restricted
+ * multiprocessor system.
+ */
+
+ if ( multiprocessing_table == NULL )
+ multiprocessing_table =
+ (void *)&_Initialization_Default_multiprocessing_table;
+
+ if ( cpu_table == NULL )
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ TRUE,
+ INTERNAL_ERROR_NO_CPU_TABLE
+ );
+
+ _CPU_Initialize( cpu_table, _Thread_Dispatch );
+
+ /*
+ * Do this as early as possible to insure no debugging output
+ * is even attempted to be printed.
+ */
+
+ _Debug_Manager_initialization();
+
+ _API_extensions_Initialization();
+
+ _Thread_Dispatch_initialization();
+
+ _Workspace_Handler_initialization(
+ (void *)configuration_table->work_space_start,
+ configuration_table->work_space_size
+ );
+
+ _User_extensions_Handler_initialization(
+ configuration_table->number_of_initial_extensions,
+ configuration_table->User_extension_table
+ );
+
+ _ISR_Handler_initialization();
+
+ _Objects_Handler_initialization(
+ multiprocessing_table->node,
+ multiprocessing_table->maximum_nodes,
+ multiprocessing_table->maximum_global_objects
+ );
+
+ _Objects_Information_table[OBJECTS_INTERNAL_API] = _Internal_Objects;
+
+ _Priority_Handler_initialization();
+
+ _Watchdog_Handler_initialization();
+
+ _TOD_Handler_initialization( configuration_table->microseconds_per_tick );
+
+ _Thread_Handler_initialization(
+ configuration_table->ticks_per_timeslice,
+ configuration_table->maximum_extensions,
+ multiprocessing_table->maximum_proxies
+ );
+
+#if defined(RTEMS_MULTIPROCESSING)
+ _MPCI_Handler_initialization(
+ multiprocessing_table->User_mpci_table,
+ RTEMS_TIMEOUT
+ );
+#endif
+
+/* MANAGERS */
+
+ _RTEMS_API_Initialize( configuration_table );
+
+ _Extension_Manager_initialization( configuration_table->maximum_extensions );
+
+ _IO_Manager_initialization(
+ configuration_table->Device_driver_table,
+ configuration_table->number_of_device_drivers,
+ configuration_table->maximum_drivers,
+ configuration_table->maximum_devices
+ );
+
+#ifdef RTEMS_POSIX_API
+ _POSIX_API_Initialize( configuration_table );
+#endif
+
+#ifdef RTEMS_ITRON_API
+ _ITRON_API_Initialize( configuration_table );
+#endif
+
+ _System_state_Set( SYSTEM_STATE_BEFORE_MULTITASKING );
+
+ /*
+ * No threads should be created before this point!!!
+ * _Thread_Executing and _Thread_Heir are not set.
+ *
+ * At this point all API extensions are in place. After the call to
+ * _Thread_Create_idle() _Thread_Executing and _Thread_Heir will be set.
+ */
+
+ _Thread_Create_idle();
+
+
+ /*
+ * Scheduling can properly occur now as long as we avoid dispatching.
+ */
+
+ if ( cpu_table->pretasking_hook )
+ (*cpu_table->pretasking_hook)();
+
+#if defined(RTEMS_MULTIPROCESSING)
+ _MPCI_Create_server();
+#endif
+
+ /*
+ * Run the API and BSPs predriver hook.
+ */
+
+ _API_extensions_Run_predriver();
+
+ if ( _CPU_Table.predriver_hook )
+ (*_CPU_Table.predriver_hook)();
+
+ /*
+ * Initialize all the device drivers and initialize the MPCI layer.
+ *
+ * NOTE: The MPCI may be build upon a device driver.
+ */
+
+ _IO_Initialize_all_drivers();
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( _System_state_Is_multiprocessing ) {
+ _MPCI_Initialization();
+ _MPCI_Internal_packets_Send_process_packet(
+ MPCI_PACKETS_SYSTEM_VERIFY
+ );
+ }
+#endif
+
+ /*
+ * Run the APIs and BSPs postdriver hooks.
+ *
+ * The API extensions are supposed to create user initialization tasks.
+ */
+
+ _API_extensions_Run_postdriver();
+
+ if ( _CPU_Table.postdriver_hook )
+ (*_CPU_Table.postdriver_hook)();
+
+ return bsp_level;
+}
+
+void rtems_initialize_executive_late(
+ rtems_interrupt_level bsp_level
+)
+{
+
+ _System_state_Set( SYSTEM_STATE_BEGIN_MULTITASKING );
+
+ _Thread_Start_multitasking();
+
+ /*
+ * Restore the interrupt level to what the BSP had. Technically,
+ * this is unnecessary since the BSP should have all interrupts
+ * disabled when rtems_initialize_executive is invoked. But this keeps
+ * the ISR Disable/Enable calls paired.
+ */
+
+ _ISR_Enable( bsp_level );
+}
+
+/*PAGE
+ *
+ * rtems_shutdown_executive
+ *
+ * This kernel routine shutdowns the executive. It halts multitasking
+ * and returns control to the application execution "thread" which
+ * initialially invoked the rtems_initialize_executive directive.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ */
+
+void rtems_shutdown_executive(
+ uint32_t result
+)
+{
+ if ( _System_state_Current != SYSTEM_STATE_SHUTDOWN ) {
+ _System_state_Set( SYSTEM_STATE_SHUTDOWN );
+ _Thread_Stop_multitasking();
+ }
+}
diff --git a/cpukit/sapi/src/extension.c b/cpukit/sapi/src/extension.c
new file mode 100644
index 0000000000..894cf5b315
--- /dev/null
+++ b/cpukit/sapi/src/extension.c
@@ -0,0 +1,51 @@
+/*
+ * Extension Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-2002.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/extension.h>
+
+/*PAGE
+ *
+ * _Extension_Manager_initialization
+ *
+ * This routine initializes all extension manager related data structures.
+ *
+ * Input parameters:
+ * maximum_extensions - number of extensions to initialize
+ *
+ * Output parameters: NONE
+ */
+
+void _Extension_Manager_initialization(
+ uint32_t maximum_extensions
+)
+{
+ _Objects_Initialize_information(
+ &_Extension_Information,
+ OBJECTS_CLASSIC_API, /* object API */
+ OBJECTS_RTEMS_EXTENSIONS,
+ maximum_extensions,
+ sizeof( Extension_Control ),
+ FALSE, /* TRUE if the name is a string */
+ RTEMS_MAXIMUM_NAME_LENGTH /* maximum length of an object name */
+#if defined(RTEMS_MULTIPROCESSING)
+ ,
+ FALSE, /* TRUE if this is a global object class */
+ NULL /* Proxy extraction support callout */
+#endif
+ );
+}
diff --git a/cpukit/sapi/src/extensioncreate.c b/cpukit/sapi/src/extensioncreate.c
new file mode 100644
index 0000000000..8c9b25b1dd
--- /dev/null
+++ b/cpukit/sapi/src/extensioncreate.c
@@ -0,0 +1,65 @@
+/*
+ * Extension Manager -- rtems_extension_create
+ *
+ *
+ * COPYRIGHT (c) 1989-2002.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/extension.h>
+
+/*PAGE
+ *
+ * rtems_extension_create
+ *
+ * This directive creates a extension and performs some initialization.
+ *
+ * Input parameters:
+ * name - extension name
+ * extension_table - pointer to extension set information
+ * id - pointer to extension id
+ *
+ * Output parameters:
+ * id - extension id
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_extension_create(
+ rtems_name name,
+ rtems_extensions_table *extension_table,
+ Objects_Id *id
+)
+{
+ Extension_Control *the_extension;
+
+ if ( !rtems_is_name_valid( name ) )
+ return RTEMS_INVALID_NAME;
+
+ _Thread_Disable_dispatch(); /* to prevent deletion */
+
+ the_extension = _Extension_Allocate();
+
+ if ( !the_extension ) {
+ _Thread_Enable_dispatch();
+ return RTEMS_TOO_MANY;
+ }
+
+ _User_extensions_Add_set( &the_extension->Extension, extension_table );
+
+ _Objects_Open( &_Extension_Information, &the_extension->Object, &name );
+
+ *id = the_extension->Object.id;
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/sapi/src/extensiondelete.c b/cpukit/sapi/src/extensiondelete.c
new file mode 100644
index 0000000000..001c53756b
--- /dev/null
+++ b/cpukit/sapi/src/extensiondelete.c
@@ -0,0 +1,56 @@
+/*
+ * Extension Manager -- rtems_extension_delete
+ *
+ *
+ * COPYRIGHT (c) 1989-2002.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/extension.h>
+
+/*PAGE
+ *
+ * rtems_extension_delete
+ *
+ * This directive allows a thread to delete a extension.
+ *
+ * Input parameters:
+ * id - extension id
+ *
+ * Output parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_extension_delete(
+ Objects_Id id
+)
+{
+ Extension_Control *the_extension;
+ Objects_Locations location;
+
+ the_extension = _Extension_Get( id, &location );
+ switch ( location ) {
+ case OBJECTS_ERROR:
+ case OBJECTS_REMOTE: /* should never return this */
+ return RTEMS_INVALID_ID;
+ case OBJECTS_LOCAL:
+ _User_extensions_Remove_set( &the_extension->Extension );
+ _Objects_Close( &_Extension_Information, &the_extension->Object );
+ _Extension_Free( the_extension );
+ _Thread_Enable_dispatch();
+ return RTEMS_SUCCESSFUL;
+ }
+
+ return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */
+}
diff --git a/cpukit/sapi/src/extensionident.c b/cpukit/sapi/src/extensionident.c
new file mode 100644
index 0000000000..be519496a1
--- /dev/null
+++ b/cpukit/sapi/src/extensionident.c
@@ -0,0 +1,53 @@
+/*
+ * Extension Manager -- rtems_extension_ident
+ *
+ *
+ * COPYRIGHT (c) 1989-2002.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/rtems/support.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/extension.h>
+
+/*PAGE
+ *
+ * rtems_extension_ident
+ *
+ * This directive returns the system ID associated with
+ * the extension name.
+ *
+ * Input parameters:
+ * name - user defined message queue name
+ * id - pointer to extension id
+ *
+ * Output parameters:
+ * *id - message queue id
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_extension_ident(
+ rtems_name name,
+ Objects_Id *id
+)
+{
+ Objects_Name_or_id_lookup_errors status;
+
+ status = _Objects_Name_to_id(
+ &_Extension_Information,
+ &name,
+ OBJECTS_SEARCH_LOCAL_NODE,
+ id
+ );
+
+ return _Status_Object_name_errors_to_status[ status ];
+}
diff --git a/cpukit/sapi/src/fatal.c b/cpukit/sapi/src/fatal.c
new file mode 100644
index 0000000000..fb01c92ee3
--- /dev/null
+++ b/cpukit/sapi/src/fatal.c
@@ -0,0 +1,37 @@
+/*
+ * Fatal Error Manager
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/fatal.h>
+#include <rtems/score/interr.h>
+
+/*PAGE
+ *
+ * rtems_fatal_error_occurred
+ *
+ * This directive will invoke the internal fatal error handler.
+ *
+ * Input parameters:
+ * the_error - fatal error status code
+ *
+ * Output parameters: NONE
+ */
+
+void volatile rtems_fatal_error_occurred(
+ uint32_t the_error
+)
+{
+ _Internal_error_Occurred( INTERNAL_ERROR_RTEMS_API, FALSE, the_error );
+
+/* will not return from this routine */
+}
diff --git a/cpukit/sapi/src/io.c b/cpukit/sapi/src/io.c
new file mode 100644
index 0000000000..b4bb4b6a9d
--- /dev/null
+++ b/cpukit/sapi/src/io.c
@@ -0,0 +1,419 @@
+/*
+ * Input/Output Manager
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/io.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+
+#include <string.h>
+
+/*PAGE
+ *
+ * _IO_Manager_initialization
+ *
+ * The IO manager has been extended to support runtime driver
+ * registration. The driver table is now allocated in the
+ * workspace.
+ *
+ */
+
+void _IO_Manager_initialization(
+ rtems_driver_address_table *driver_table,
+ uint32_t drivers_in_table,
+ uint32_t number_of_drivers,
+ uint32_t number_of_devices
+)
+{
+ void *tmp;
+ uint32_t index;
+ rtems_driver_name_t *np;
+
+ if ( number_of_drivers < drivers_in_table )
+ number_of_drivers = drivers_in_table;
+
+ tmp = _Workspace_Allocate_or_fatal_error(
+ sizeof( rtems_driver_address_table ) * ( number_of_drivers )
+ );
+
+ _IO_Driver_address_table = (rtems_driver_address_table *) tmp;
+
+ memset(
+ _IO_Driver_address_table, 0,
+ sizeof( rtems_driver_address_table ) * ( number_of_drivers )
+ );
+
+ if ( drivers_in_table )
+ for ( index = 0 ; index < drivers_in_table ; index++ )
+ _IO_Driver_address_table[index] = driver_table[index];
+
+ _IO_Number_of_drivers = number_of_drivers;
+ _IO_Number_of_devices = number_of_devices;
+
+ tmp = _Workspace_Allocate_or_fatal_error(
+ sizeof( rtems_driver_name_t ) * ( number_of_devices + 1 )
+ );
+
+ _IO_Driver_name_table = (rtems_driver_name_t *) tmp;
+
+ for( index=0, np = _IO_Driver_name_table ;
+ index < _IO_Number_of_devices ;
+ index++, np++ ) {
+ np->device_name = 0;
+ np->device_name_length = 0;
+ np->major = 0;
+ np->minor = 0;
+ }
+}
+
+/*PAGE
+ *
+ * _IO_Initialize_all_drivers
+ *
+ * This routine initializes all device drivers
+ *
+ * Input Paramters: NONE
+ *
+ * Output Parameters: NONE
+ */
+
+void _IO_Initialize_all_drivers( void )
+{
+ rtems_device_major_number major;
+
+ for ( major=0 ; major < _IO_Number_of_drivers ; major ++ )
+ (void) rtems_io_initialize( major, 0, NULL);
+}
+
+/*PAGE
+ *
+ * rtems_io_register_driver
+ *
+ * Register a driver into the device driver table.
+ *
+ * Input Paramters:
+ * major - device major number (0 means allocate
+ * a number)
+ * driver_table - driver callout function table
+ * registered_major - the major number which is registered
+ *
+ * Output Parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_io_register_driver(
+ rtems_device_major_number major,
+ rtems_driver_address_table *driver_table,
+ rtems_device_major_number *registered_major
+)
+{
+ *registered_major = 0;
+
+ /*
+ * Test for initialise/open being present to indicate the driver slot is
+ * in use.
+ */
+
+ if ( major >= _IO_Number_of_drivers )
+ return RTEMS_INVALID_NUMBER;
+
+ if ( major == 0 )
+ {
+ for ( major = _IO_Number_of_drivers - 1 ; major ; major-- )
+ if ( _IO_Driver_address_table[major].initialization_entry == 0 &&
+ _IO_Driver_address_table[major].open_entry == 0 )
+ break;
+
+ if (( major == 0 ) &&
+ ( _IO_Driver_address_table[major].initialization_entry == 0 &&
+ _IO_Driver_address_table[major].open_entry == 0 ))
+ return RTEMS_TOO_MANY;
+ }
+
+ if ( _IO_Driver_address_table[major].initialization_entry == 0 &&
+ _IO_Driver_address_table[major].open_entry == 0 )
+ {
+ _IO_Driver_address_table[major] = *driver_table;
+ *registered_major = major;
+
+ rtems_io_initialize( major, 0, NULL );
+
+ return RTEMS_SUCCESSFUL;
+ }
+
+ return RTEMS_RESOURCE_IN_USE;
+}
+
+/*PAGE
+ *
+ * rtems_io_unregister_driver
+ *
+ * Unregister a driver from the device driver table.
+ *
+ * Input Paramters:
+ * major - device major number
+ *
+ * Output Parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+rtems_status_code rtems_io_unregister_driver(
+ rtems_device_major_number major
+)
+{
+ if ( major < _IO_Number_of_drivers )
+ {
+ memset(
+ &_IO_Driver_address_table[major],
+ 0,
+ sizeof( rtems_driver_address_table )
+ );
+ return RTEMS_SUCCESSFUL;
+ }
+ return RTEMS_UNSATISFIED;
+}
+
+/*PAGE
+ *
+ * rtems_io_register_name
+ *
+ * Associate a name with a driver
+ *
+ * Input Paramters:
+ * device_name - pointer to name string to associate with device
+ * major - device major number to receive name
+ * minor - device minor number to receive name
+ *
+ * Output Parameters:
+ * RTEMS_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+#if 0
+rtems_status_code rtems_io_register_name(
+ char *device_name,
+ rtems_device_major_number major,
+ rtems_device_minor_number minor
+ )
+{
+ rtems_driver_name_t *np;
+ uint32_t level;
+ uint32_t index;
+
+ /* find an empty slot */
+ for( index=0, np = _IO_Driver_name_table ;
+ index < _IO_Number_of_devices ;
+ index++, np++ )
+ {
+
+ _ISR_Disable(level);
+ if (np->device_name == 0)
+ {
+ np->device_name = device_name;
+ np->device_name_length = strlen(device_name);
+ np->major = major;
+ np->minor = minor;
+ _ISR_Enable(level);
+
+ return RTEMS_SUCCESSFUL;
+ }
+ _ISR_Enable(level);
+ }
+
+ return RTEMS_TOO_MANY;
+}
+#endif
+
+/*PAGE
+ *
+ * rtems_io_initialize
+ *
+ * This routine is the initialization directive of the IO manager.
+ *
+ * Input Paramters:
+ * major - device driver number
+ * minor - device number
+ * argument - pointer to argument(s)
+ *
+ * Output Parameters:
+ * returns - return code
+ */
+
+rtems_status_code rtems_io_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *argument
+)
+{
+ rtems_device_driver_entry callout;
+
+ if ( major >= _IO_Number_of_drivers )
+ return RTEMS_INVALID_NUMBER;
+
+ callout = _IO_Driver_address_table[major].initialization_entry;
+ return callout ? callout(major, minor, argument) : RTEMS_SUCCESSFUL;
+}
+
+/*PAGE
+ *
+ * rtems_io_open
+ *
+ * This routine is the open directive of the IO manager.
+ *
+ * Input Paramters:
+ * major - device driver number
+ * minor - device number
+ * argument - pointer to argument(s)
+ *
+ * Output Parameters:
+ * returns - return code
+ */
+
+rtems_status_code rtems_io_open(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *argument
+)
+{
+ rtems_device_driver_entry callout;
+
+ if ( major >= _IO_Number_of_drivers )
+ return RTEMS_INVALID_NUMBER;
+
+ callout = _IO_Driver_address_table[major].open_entry;
+ return callout ? callout(major, minor, argument) : RTEMS_SUCCESSFUL;
+}
+
+/*PAGE
+ *
+ * rtems_io_close
+ *
+ * This routine is the close directive of the IO manager.
+ *
+ * Input Paramters:
+ * major - device driver number
+ * minor - device number
+ * argument - pointer to argument(s)
+ *
+ * Output Parameters:
+ * returns - return code
+ */
+
+rtems_status_code rtems_io_close(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *argument
+)
+{
+ rtems_device_driver_entry callout;
+
+ if ( major >= _IO_Number_of_drivers )
+ return RTEMS_INVALID_NUMBER;
+
+ callout = _IO_Driver_address_table[major].close_entry;
+ return callout ? callout(major, minor, argument) : RTEMS_SUCCESSFUL;
+}
+
+/*PAGE
+ *
+ * rtems_io_read
+ *
+ * This routine is the read directive of the IO manager.
+ *
+ * Input Paramters:
+ * major - device driver number
+ * minor - device number
+ * argument - pointer to argument(s)
+ *
+ * Output Parameters:
+ * returns - return code
+ */
+
+rtems_status_code rtems_io_read(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *argument
+)
+{
+ rtems_device_driver_entry callout;
+
+ if ( major >= _IO_Number_of_drivers )
+ return RTEMS_INVALID_NUMBER;
+
+ callout = _IO_Driver_address_table[major].read_entry;
+ return callout ? callout(major, minor, argument) : RTEMS_SUCCESSFUL;
+}
+
+/*PAGE
+ *
+ * rtems_io_write
+ *
+ * This routine is the write directive of the IO manager.
+ *
+ * Input Paramters:
+ * major - device driver number
+ * minor - device number
+ * argument - pointer to argument(s)
+ *
+ * Output Parameters:
+ * returns - return code
+ */
+
+rtems_status_code rtems_io_write(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *argument
+)
+{
+ rtems_device_driver_entry callout;
+
+ if ( major >= _IO_Number_of_drivers )
+ return RTEMS_INVALID_NUMBER;
+
+ callout = _IO_Driver_address_table[major].write_entry;
+ return callout ? callout(major, minor, argument) : RTEMS_SUCCESSFUL;
+}
+
+/*PAGE
+ *
+ * rtems_io_control
+ *
+ * This routine is the control directive of the IO manager.
+ *
+ * Input Paramters:
+ * major - device driver number
+ * minor - device number
+ * argument - pointer to argument(s)
+ *
+ * Output Parameters:
+ * returns - return code
+ */
+
+rtems_status_code rtems_io_control(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *argument
+)
+{
+ rtems_device_driver_entry callout;
+
+ if ( major >= _IO_Number_of_drivers )
+ return RTEMS_INVALID_NUMBER;
+
+ callout = _IO_Driver_address_table[major].control_entry;
+ return callout ? callout(major, minor, argument) : RTEMS_SUCCESSFUL;
+}
diff --git a/cpukit/sapi/src/itronapi.c b/cpukit/sapi/src/itronapi.c
new file mode 100644
index 0000000000..23f6533fb2
--- /dev/null
+++ b/cpukit/sapi/src/itronapi.c
@@ -0,0 +1,119 @@
+/*
+ * ITRON API Initialization Support
+ *
+ * NOTE:
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <assert.h>
+
+/*
+ * ITRON_API_INIT is defined so all of the ITRON API
+ * data will be included in this object file.
+ */
+
+#define ITRON_API_INIT
+
+#include <rtems/system.h> /* include this before checking RTEMS_ITRON_API */
+#ifdef RTEMS_ITRON_API
+
+#include <rtems/itron.h>
+
+#include <sys/types.h>
+#include <rtems/config.h>
+#include <rtems/score/object.h>
+
+#include <rtems/itron/eventflags.h>
+#include <rtems/itron/fmempool.h>
+#include <rtems/itron/mbox.h>
+#include <rtems/itron/msgbuffer.h>
+#include <rtems/itron/port.h>
+#include <rtems/itron/semaphore.h>
+#include <rtems/itron/task.h>
+#include <rtems/itron/vmempool.h>
+
+/*PAGE
+ *
+ * _ITRON_API_Initialize
+ *
+ * XXX
+ */
+
+itron_api_configuration_table _ITRON_Default_configuration = {
+ 0, /* maximum_tasks */
+ 0, /* maximum_semaphores */
+ 0, /* maximum_eventflags */
+ 0, /* maximum_mailboxes */
+ 0, /* maximum_message_buffers */
+ 0, /* maximum_ports */
+ 0, /* maximum_memory_pools */
+ 0, /* maximum_fixed_memory_pools */
+ 0, /* number_of_initialization_tasks */
+ NULL /* User_initialization_tasks_table */
+};
+
+Objects_Information *_ITRON_Objects[ OBJECTS_ITRON_CLASSES_LAST + 1 ];
+
+void _ITRON_API_Initialize(
+ rtems_configuration_table *configuration_table
+)
+{
+ itron_api_configuration_table *api_configuration;
+
+ /* XXX need to assert here based on size assumptions */
+
+ assert( sizeof(ID) == sizeof(Objects_Id) );
+
+ api_configuration = configuration_table->ITRON_api_configuration;
+ if ( !api_configuration )
+ api_configuration = &_ITRON_Default_configuration;
+
+ _Objects_Information_table[OBJECTS_ITRON_API] = _ITRON_Objects;
+
+ _ITRON_Task_Manager_initialization(
+ api_configuration->maximum_tasks,
+ api_configuration->number_of_initialization_tasks,
+ api_configuration->User_initialization_tasks_table
+ );
+
+ _ITRON_Semaphore_Manager_initialization(
+ api_configuration->maximum_semaphores
+ );
+
+ _ITRON_Eventflags_Manager_initialization(
+ api_configuration->maximum_eventflags
+ );
+
+ _ITRON_Fixed_memory_pool_Manager_initialization(
+ api_configuration->maximum_fixed_memory_pools
+ );
+
+ _ITRON_Mailbox_Manager_initialization(
+ api_configuration->maximum_mailboxes
+ );
+
+ _ITRON_Message_buffer_Manager_initialization(
+ api_configuration->maximum_message_buffers
+ );
+
+ _ITRON_Port_Manager_initialization(
+ api_configuration->maximum_ports
+ );
+
+ _ITRON_Variable_memory_pool_Manager_initialization(
+ api_configuration->maximum_memory_pools
+ );
+
+
+}
+
+#endif
+/* end of file */
diff --git a/cpukit/sapi/src/posixapi.c b/cpukit/sapi/src/posixapi.c
new file mode 100644
index 0000000000..a062ecf21b
--- /dev/null
+++ b/cpukit/sapi/src/posixapi.c
@@ -0,0 +1,115 @@
+/*
+ * RTEMS API Initialization Support
+ *
+ * NOTE:
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <assert.h>
+
+/*
+ * POSIX_API_INIT is defined so all of the POSIX API
+ * data will be included in this object file.
+ */
+
+#define POSIX_API_INIT
+
+#include <rtems/system.h> /* include this before checking RTEMS_POSIX_API */
+#ifdef RTEMS_POSIX_API
+
+#include <sys/types.h>
+#include <mqueue.h>
+#include <rtems/config.h>
+#include <rtems/score/object.h>
+#include <rtems/posix/cond.h>
+#include <rtems/posix/config.h>
+#include <rtems/posix/key.h>
+#include <rtems/posix/mqueue.h>
+#include <rtems/posix/mutex.h>
+#include <rtems/posix/priority.h>
+#include <rtems/posix/psignal.h>
+#include <rtems/posix/pthread.h>
+#include <rtems/posix/ptimer.h>
+#include <rtems/posix/semaphore.h>
+#include <rtems/posix/time.h>
+
+/*PAGE
+ *
+ * _POSIX_API_Initialize
+ *
+ * XXX
+ */
+
+posix_api_configuration_table _POSIX_Default_configuration = {
+ 0, /* maximum_threads */
+ 0, /* maximum_mutexes */
+ 0, /* maximum_condition_variables */
+ 0, /* maximum_keys */
+ 0, /* maximum_timers */
+ 0, /* maximum_queued_signals */
+ 0, /* number_of_initialization_threads */
+ 0, /* maximum_message_queues */
+ 0, /* maximum_semaphores */
+ NULL /* User_initialization_threads_table */
+};
+
+Objects_Information *_POSIX_Objects[ OBJECTS_POSIX_CLASSES_LAST + 1 ];
+
+
+void _POSIX_API_Initialize(
+ rtems_configuration_table *configuration_table
+)
+{
+ posix_api_configuration_table *api_configuration;
+
+ /* XXX need to assert here based on size assumptions */
+
+ assert( sizeof(pthread_t) == sizeof(Objects_Id) );
+
+ api_configuration = configuration_table->POSIX_api_configuration;
+ if ( !api_configuration )
+ api_configuration = &_POSIX_Default_configuration;
+
+ _Objects_Information_table[OBJECTS_POSIX_API] = _POSIX_Objects;
+
+ _POSIX_signals_Manager_Initialization(
+ api_configuration->maximum_queued_signals
+ );
+
+ _POSIX_Threads_Manager_initialization(
+ api_configuration->maximum_threads,
+ api_configuration->number_of_initialization_threads,
+ api_configuration->User_initialization_threads_table
+ );
+
+ _POSIX_Condition_variables_Manager_initialization(
+ api_configuration->maximum_condition_variables
+ );
+
+ _POSIX_Key_Manager_initialization( api_configuration->maximum_keys );
+
+ _POSIX_Mutex_Manager_initialization(
+ api_configuration->maximum_mutexes
+ );
+
+ _POSIX_Message_queue_Manager_initialization(
+ api_configuration->maximum_message_queues
+ );
+
+ _POSIX_Semaphore_Manager_initialization(
+ api_configuration->maximum_semaphores
+ );
+
+ _POSIX_Timer_Manager_initialization ( api_configuration->maximum_timers );
+}
+
+#endif
+/* end of file */
diff --git a/cpukit/sapi/src/rtemsapi.c b/cpukit/sapi/src/rtemsapi.c
new file mode 100644
index 0000000000..073fb7028d
--- /dev/null
+++ b/cpukit/sapi/src/rtemsapi.c
@@ -0,0 +1,97 @@
+/*
+ * POSIX API Initialization Support
+ *
+ * NOTE:
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+/*
+ * RTEMS_API_INIT is defined so all of the RTEMS API
+ * data will be included in this object file.
+ */
+
+#define RTEMS_API_INIT
+
+#include <rtems/system.h>
+#include <rtems/rtems/status.h>
+#include <rtems/rtems/rtemsapi.h>
+
+#include <rtems/rtems/intr.h>
+#include <rtems/rtems/clock.h>
+#include <rtems/rtems/tasks.h>
+#include <rtems/rtems/dpmem.h>
+#include <rtems/rtems/event.h>
+#include <rtems/rtems/message.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/rtems/mp.h>
+#endif
+#include <rtems/rtems/part.h>
+#include <rtems/rtems/ratemon.h>
+#include <rtems/rtems/region.h>
+#include <rtems/rtems/sem.h>
+#include <rtems/rtems/signal.h>
+#include <rtems/rtems/timer.h>
+
+Objects_Information *_RTEMS_Objects[ OBJECTS_RTEMS_CLASSES_LAST + 1 ];
+
+/*PAGE
+ *
+ * _RTEMS_API_Initialize
+ *
+ * XXX
+ */
+
+void _RTEMS_API_Initialize(
+ rtems_configuration_table *configuration_table
+)
+{
+ rtems_api_configuration_table *api_configuration;
+
+ api_configuration = configuration_table->RTEMS_api_configuration;
+
+ _Objects_Information_table[OBJECTS_CLASSIC_API] = _RTEMS_Objects;
+
+ _Attributes_Handler_initialization();
+
+ _Interrupt_Manager_initialization();
+
+#if defined(RTEMS_MULTIPROCESSING)
+ _Multiprocessing_Manager_initialization();
+#endif
+
+ _RTEMS_tasks_Manager_initialization(
+ api_configuration->maximum_tasks,
+ api_configuration->number_of_initialization_tasks,
+ api_configuration->User_initialization_tasks_table
+ );
+
+ _Timer_Manager_initialization( api_configuration->maximum_timers );
+
+ _Signal_Manager_initialization();
+
+ _Event_Manager_initialization();
+
+ _Message_queue_Manager_initialization(
+ api_configuration->maximum_message_queues
+ );
+
+ _Semaphore_Manager_initialization( api_configuration->maximum_semaphores );
+
+ _Partition_Manager_initialization( api_configuration->maximum_partitions );
+
+ _Region_Manager_initialization( api_configuration->maximum_regions );
+
+ _Dual_ported_memory_Manager_initialization( api_configuration->maximum_ports);
+
+ _Rate_monotonic_Manager_initialization( api_configuration->maximum_periods );
+}
+
+/* end of file */
diff --git a/cpukit/score/.cvsignore b/cpukit/score/.cvsignore
new file mode 100644
index 0000000000..282522db03
--- /dev/null
+++ b/cpukit/score/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am
new file mode 100644
index 0000000000..ab4af5f5ca
--- /dev/null
+++ b/cpukit/score/Makefile.am
@@ -0,0 +1,490 @@
+##
+## $Id$
+##
+
+include $(top_srcdir)/automake/multilib.am
+include $(top_srcdir)/automake/compile.am
+
+SUBDIRS = . cpu
+
+## include
+
+include_rtemsdir = $(includedir)/rtems
+
+include_rtems_HEADERS = include/rtems/debug.h include/rtems/system.h \
+ include/rtems/seterr.h
+
+include_rtems_scoredir = $(includedir)/rtems/score
+
+include_rtems_score_HEADERS = include/rtems/score/address.h \
+ include/rtems/score/apiext.h include/rtems/score/apimutex.h \
+ include/rtems/score/bitfield.h include/rtems/score/chain.h \
+ include/rtems/score/context.h include/rtems/score/copyrt.h \
+ include/rtems/score/coremsg.h include/rtems/score/coremutex.h \
+ include/rtems/score/coresem.h include/rtems/score/heap.h \
+ include/rtems/score/interr.h include/rtems/score/isr.h \
+ include/rtems/score/object.h include/rtems/score/priority.h \
+ include/rtems/score/stack.h include/rtems/score/states.h \
+ include/rtems/score/sysstate.h include/rtems/score/thread.h \
+ include/rtems/score/threadq.h include/rtems/score/tod.h \
+ include/rtems/score/tqdata.h include/rtems/score/userext.h \
+ include/rtems/score/watchdog.h include/rtems/score/wkspace.h \
+ include/rtems/score/cpuopts.h
+
+if HAS_MP
+# We only build multiprocessing related files if HAS_MP was defined
+include_rtems_score_HEADERS += include/rtems/score/mpci.h \
+ include/rtems/score/mppkt.h include/rtems/score/objectmp.h \
+ include/rtems/score/threadmp.h
+endif
+
+## inline
+if INLINE
+include_rtems_score_HEADERS += inline/rtems/score/address.inl \
+ inline/rtems/score/chain.inl inline/rtems/score/coremsg.inl \
+ inline/rtems/score/coremutex.inl inline/rtems/score/coresem.inl \
+ inline/rtems/score/heap.inl inline/rtems/score/isr.inl \
+ inline/rtems/score/object.inl inline/rtems/score/priority.inl \
+ inline/rtems/score/stack.inl inline/rtems/score/states.inl \
+ inline/rtems/score/sysstate.inl inline/rtems/score/thread.inl \
+ inline/rtems/score/tod.inl inline/rtems/score/tqdata.inl \
+ inline/rtems/score/userext.inl inline/rtems/score/watchdog.inl \
+ inline/rtems/score/wkspace.inl
+
+if HAS_MP
+## We only build multiprocessing related files if HAS_MP was defined
+include_rtems_score_HEADERS += inline/rtems/score/mppkt.inl \
+ inline/rtems/score/objectmp.inl inline/rtems/score/threadmp.inl
+endif
+else
+## macros
+include_rtems_score_HEADERS += macros/rtems/score/address.inl \
+ macros/rtems/score/chain.inl macros/rtems/score/coremsg.inl \
+ macros/rtems/score/coremutex.inl macros/rtems/score/coresem.inl \
+ macros/rtems/score/heap.inl macros/rtems/score/isr.inl \
+ macros/rtems/score/object.inl macros/rtems/score/priority.inl \
+ macros/rtems/score/stack.inl macros/rtems/score/states.inl \
+ macros/rtems/score/sysstate.inl macros/rtems/score/thread.inl \
+ macros/rtems/score/tod.inl macros/rtems/score/tqdata.inl \
+ macros/rtems/score/userext.inl macros/rtems/score/watchdog.inl \
+ macros/rtems/score/wkspace.inl
+if HAS_MP
+## We only build multiprocessing related files if HAS_MP was defined
+include_rtems_score_HEADERS += macros/rtems/score/mppkt.inl \
+ macros/rtems/score/objectmp.inl macros/rtems/score/threadmp.inl
+endif
+endif
+
+EXTRA_DIST = macros/README
+
+## src
+
+# We only build multiprocessing related files if HAS_MP was defined
+MP_C_FILES = src/mpci.c src/objectmp.c src/threadmp.c
+
+CORE_MESSAGE_QUEUE_C_FILES = src/coremsg.c src/coremsgbroadcast.c \
+ src/coremsgclose.c src/coremsgflush.c src/coremsgflushwait.c \
+ src/coremsginsert.c src/coremsgflushsupp.c src/coremsgseize.c \
+ src/coremsgsubmit.c
+
+CORE_MUTEX_C_FILES = src/coremutex.c src/coremutexflush.c \
+ src/coremutexseize.c src/coremutexsurrender.c
+
+CORE_SEMAPHORE_C_FILES = src/coresem.c src/coresemflush.c src/coresemseize.c \
+ src/coresemsurrender.c
+
+HEAP_C_FILES = src/heap.c src/heapallocate.c src/heapextend.c src/heapfree.c \
+ src/heapsizeofuserarea.c src/heapwalk.c src/heapgetinfo.c
+
+OBJECT_C_FILES = src/object.c src/objectallocate.c \
+ src/objectallocatebyindex.c src/objectclearname.c \
+ src/objectcomparenameraw.c src/objectcomparenamestring.c \
+ src/objectcopynameraw.c src/objectcopynamestring.c \
+ src/objectextendinformation.c src/objectfree.c src/objectget.c \
+ src/objectgetisr.c src/objectgetbyindex.c src/objectgetnext.c \
+ src/objectinitializeinformation.c src/objectnametoid.c \
+ src/objectshrinkinformation.c src/objectgetnoprotection.c \
+ src/objectidtoname.c
+
+THREAD_C_FILES = src/thread.c src/threadchangepriority.c \
+ src/threadclearstate.c src/threadclose.c src/threadcreateidle.c \
+ src/threaddelayended.c src/threaddispatch.c src/threadevaluatemode.c \
+ src/threadget.c src/threadhandler.c src/threadidlebody.c \
+ src/threadinitialize.c src/threadloadenv.c src/threadready.c \
+ src/threadresettimeslice.c src/threadreset.c src/threadrestart.c \
+ src/threadresume.c src/threadrotatequeue.c src/threadsetpriority.c \
+ src/threadsetstate.c src/threadsettransient.c src/threadstackallocate.c \
+ src/threadstackfree.c src/threadstart.c src/threadstartmultitasking.c \
+ src/threadsuspend.c src/threadtickletimeslice.c \
+ src/threadyieldprocessor.c src/iterateoverthreads.c
+
+THREADQ_C_FILES = src/threadq.c src/threadqdequeue.c \
+ src/threadqdequeuefifo.c src/threadqdequeuepriority.c \
+ src/threadqenqueue.c src/threadqenqueuefifo.c \
+ src/threadqenqueuepriority.c src/threadqextract.c \
+ src/threadqextractfifo.c src/threadqextractpriority.c \
+ src/threadqextractwithproxy.c src/threadqfirst.c src/threadqfirstfifo.c \
+ src/threadqfirstpriority.c src/threadqflush.c src/threadqtimeout.c
+
+TOD_C_FILES = src/coretod.c src/coretodset.c src/coretodtickle.c \
+ src/coretodtoseconds.c src/coretodvalidate.c
+
+WATCHDOG_C_FILES = src/watchdog.c src/watchdogadjust.c src/watchdoginsert.c \
+ src/watchdogremove.c src/watchdogtickle.c
+
+STD_C_FILES = src/apiext.c src/chain.c $(CORE_MESSAGE_QUEUE_C_FILES) \
+ $(CORE_MUTEX_C_FILES) $(CORE_SEMAPHORE_C_FILES) $(HEAP_C_FILES) \
+ src/interr.c src/isr.c $(OBJECT_C_FILES) $(THREAD_C_FILES) \
+ $(THREADQ_C_FILES) $(TOD_C_FILES) src/userext.c $(WATCHDOG_C_FILES) \
+ src/wkspace.c
+
+C_FILES = $(STD_C_FILES)
+if HAS_MP
+C_FILES += $(MP_C_FILES)
+endif
+
+AM_CPPFLAGS += -D__RTEMS_INSIDE__
+
+EXTRA_LIBRARIES = libscore.a
+CLEANFILES = libscore.a
+libscore_a_SOURCES = $(C_FILES)
+libscore_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libscore_g.a
+CLEANFILES += libscore_g.a
+libscore_g_a_SOURCES = $(libscore_a_SOURCES)
+libscore_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+EXTRA_DIST += $(STD_C_FILES) $(MP_C_FILES) src/Unlimited.txt
+
+all-local: $(PREINSTALL_FILES) libscore$(LIB_VARIANT).a
+
+DISTCLEANFILES = include/rtems/score/cpuopts.h
+
+PREINSTALL_DIRS =
+PREINSTALL_FILES =
+
+$(PROJECT_INCLUDE)/rtems/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems
+ @: > $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/debug.h: include/rtems/debug.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/debug.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/debug.h
+
+$(PROJECT_INCLUDE)/rtems/system.h: include/rtems/system.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/system.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/system.h
+
+$(PROJECT_INCLUDE)/rtems/seterr.h: include/rtems/seterr.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/seterr.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/seterr.h
+
+$(PROJECT_INCLUDE)/rtems/score/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems/score
+ @: > $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/score/address.h: include/rtems/score/address.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/address.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/address.h
+
+$(PROJECT_INCLUDE)/rtems/score/apiext.h: include/rtems/score/apiext.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/apiext.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/apiext.h
+
+$(PROJECT_INCLUDE)/rtems/score/apimutex.h: include/rtems/score/apimutex.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/apimutex.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/apimutex.h
+
+$(PROJECT_INCLUDE)/rtems/score/bitfield.h: include/rtems/score/bitfield.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/bitfield.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/bitfield.h
+
+$(PROJECT_INCLUDE)/rtems/score/chain.h: include/rtems/score/chain.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/chain.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/chain.h
+
+$(PROJECT_INCLUDE)/rtems/score/context.h: include/rtems/score/context.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/context.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/context.h
+
+$(PROJECT_INCLUDE)/rtems/score/copyrt.h: include/rtems/score/copyrt.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/copyrt.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/copyrt.h
+
+$(PROJECT_INCLUDE)/rtems/score/coremsg.h: include/rtems/score/coremsg.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/coremsg.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/coremsg.h
+
+$(PROJECT_INCLUDE)/rtems/score/coremutex.h: include/rtems/score/coremutex.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/coremutex.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/coremutex.h
+
+$(PROJECT_INCLUDE)/rtems/score/coresem.h: include/rtems/score/coresem.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/coresem.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/coresem.h
+
+$(PROJECT_INCLUDE)/rtems/score/heap.h: include/rtems/score/heap.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/heap.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/heap.h
+
+$(PROJECT_INCLUDE)/rtems/score/interr.h: include/rtems/score/interr.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/interr.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/interr.h
+
+$(PROJECT_INCLUDE)/rtems/score/isr.h: include/rtems/score/isr.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/isr.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/isr.h
+
+$(PROJECT_INCLUDE)/rtems/score/object.h: include/rtems/score/object.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/object.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/object.h
+
+$(PROJECT_INCLUDE)/rtems/score/priority.h: include/rtems/score/priority.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/priority.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/priority.h
+
+$(PROJECT_INCLUDE)/rtems/score/stack.h: include/rtems/score/stack.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/stack.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/stack.h
+
+$(PROJECT_INCLUDE)/rtems/score/states.h: include/rtems/score/states.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/states.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/states.h
+
+$(PROJECT_INCLUDE)/rtems/score/sysstate.h: include/rtems/score/sysstate.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/sysstate.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/sysstate.h
+
+$(PROJECT_INCLUDE)/rtems/score/thread.h: include/rtems/score/thread.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/thread.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/thread.h
+
+$(PROJECT_INCLUDE)/rtems/score/threadq.h: include/rtems/score/threadq.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/threadq.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/threadq.h
+
+$(PROJECT_INCLUDE)/rtems/score/tod.h: include/rtems/score/tod.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/tod.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/tod.h
+
+$(PROJECT_INCLUDE)/rtems/score/tqdata.h: include/rtems/score/tqdata.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/tqdata.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/tqdata.h
+
+$(PROJECT_INCLUDE)/rtems/score/userext.h: include/rtems/score/userext.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/userext.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/userext.h
+
+$(PROJECT_INCLUDE)/rtems/score/watchdog.h: include/rtems/score/watchdog.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/watchdog.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/watchdog.h
+
+$(PROJECT_INCLUDE)/rtems/score/wkspace.h: include/rtems/score/wkspace.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/wkspace.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/wkspace.h
+
+$(PROJECT_INCLUDE)/rtems/score/cpuopts.h: include/rtems/score/cpuopts.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/cpuopts.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/cpuopts.h
+
+if HAS_MP
+$(PROJECT_INCLUDE)/rtems/score/mpci.h: include/rtems/score/mpci.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/mpci.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/mpci.h
+
+$(PROJECT_INCLUDE)/rtems/score/mppkt.h: include/rtems/score/mppkt.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/mppkt.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/mppkt.h
+
+$(PROJECT_INCLUDE)/rtems/score/objectmp.h: include/rtems/score/objectmp.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/objectmp.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/objectmp.h
+
+$(PROJECT_INCLUDE)/rtems/score/threadmp.h: include/rtems/score/threadmp.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/threadmp.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/threadmp.h
+endif
+
+if INLINE
+$(PROJECT_INCLUDE)/rtems/score/address.inl: inline/rtems/score/address.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/address.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/address.inl
+
+$(PROJECT_INCLUDE)/rtems/score/chain.inl: inline/rtems/score/chain.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/chain.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/chain.inl
+
+$(PROJECT_INCLUDE)/rtems/score/coremsg.inl: inline/rtems/score/coremsg.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/coremsg.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/coremsg.inl
+
+$(PROJECT_INCLUDE)/rtems/score/coremutex.inl: inline/rtems/score/coremutex.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/coremutex.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/coremutex.inl
+
+$(PROJECT_INCLUDE)/rtems/score/coresem.inl: inline/rtems/score/coresem.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/coresem.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/coresem.inl
+
+$(PROJECT_INCLUDE)/rtems/score/heap.inl: inline/rtems/score/heap.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/heap.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/heap.inl
+
+$(PROJECT_INCLUDE)/rtems/score/isr.inl: inline/rtems/score/isr.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/isr.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/isr.inl
+
+$(PROJECT_INCLUDE)/rtems/score/object.inl: inline/rtems/score/object.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/object.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/object.inl
+
+$(PROJECT_INCLUDE)/rtems/score/priority.inl: inline/rtems/score/priority.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/priority.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/priority.inl
+
+$(PROJECT_INCLUDE)/rtems/score/stack.inl: inline/rtems/score/stack.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/stack.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/stack.inl
+
+$(PROJECT_INCLUDE)/rtems/score/states.inl: inline/rtems/score/states.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/states.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/states.inl
+
+$(PROJECT_INCLUDE)/rtems/score/sysstate.inl: inline/rtems/score/sysstate.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/sysstate.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/sysstate.inl
+
+$(PROJECT_INCLUDE)/rtems/score/thread.inl: inline/rtems/score/thread.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/thread.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/thread.inl
+
+$(PROJECT_INCLUDE)/rtems/score/tod.inl: inline/rtems/score/tod.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/tod.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/tod.inl
+
+$(PROJECT_INCLUDE)/rtems/score/tqdata.inl: inline/rtems/score/tqdata.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/tqdata.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/tqdata.inl
+
+$(PROJECT_INCLUDE)/rtems/score/userext.inl: inline/rtems/score/userext.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/userext.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/userext.inl
+
+$(PROJECT_INCLUDE)/rtems/score/watchdog.inl: inline/rtems/score/watchdog.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/watchdog.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/watchdog.inl
+
+$(PROJECT_INCLUDE)/rtems/score/wkspace.inl: inline/rtems/score/wkspace.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/wkspace.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/wkspace.inl
+
+if HAS_MP
+$(PROJECT_INCLUDE)/rtems/score/mppkt.inl: inline/rtems/score/mppkt.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/mppkt.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/mppkt.inl
+
+$(PROJECT_INCLUDE)/rtems/score/objectmp.inl: inline/rtems/score/objectmp.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/objectmp.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/objectmp.inl
+
+$(PROJECT_INCLUDE)/rtems/score/threadmp.inl: inline/rtems/score/threadmp.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/threadmp.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/threadmp.inl
+endif
+
+else
+$(PROJECT_INCLUDE)/rtems/score/address.inl: macros/rtems/score/address.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/address.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/address.inl
+
+$(PROJECT_INCLUDE)/rtems/score/chain.inl: macros/rtems/score/chain.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/chain.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/chain.inl
+
+$(PROJECT_INCLUDE)/rtems/score/coremsg.inl: macros/rtems/score/coremsg.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/coremsg.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/coremsg.inl
+
+$(PROJECT_INCLUDE)/rtems/score/coremutex.inl: macros/rtems/score/coremutex.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/coremutex.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/coremutex.inl
+
+$(PROJECT_INCLUDE)/rtems/score/coresem.inl: macros/rtems/score/coresem.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/coresem.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/coresem.inl
+
+$(PROJECT_INCLUDE)/rtems/score/heap.inl: macros/rtems/score/heap.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/heap.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/heap.inl
+
+$(PROJECT_INCLUDE)/rtems/score/isr.inl: macros/rtems/score/isr.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/isr.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/isr.inl
+
+$(PROJECT_INCLUDE)/rtems/score/object.inl: macros/rtems/score/object.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/object.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/object.inl
+
+$(PROJECT_INCLUDE)/rtems/score/priority.inl: macros/rtems/score/priority.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/priority.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/priority.inl
+
+$(PROJECT_INCLUDE)/rtems/score/stack.inl: macros/rtems/score/stack.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/stack.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/stack.inl
+
+$(PROJECT_INCLUDE)/rtems/score/states.inl: macros/rtems/score/states.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/states.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/states.inl
+
+$(PROJECT_INCLUDE)/rtems/score/sysstate.inl: macros/rtems/score/sysstate.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/sysstate.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/sysstate.inl
+
+$(PROJECT_INCLUDE)/rtems/score/thread.inl: macros/rtems/score/thread.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/thread.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/thread.inl
+
+$(PROJECT_INCLUDE)/rtems/score/tod.inl: macros/rtems/score/tod.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/tod.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/tod.inl
+
+$(PROJECT_INCLUDE)/rtems/score/tqdata.inl: macros/rtems/score/tqdata.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/tqdata.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/tqdata.inl
+
+$(PROJECT_INCLUDE)/rtems/score/userext.inl: macros/rtems/score/userext.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/userext.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/userext.inl
+
+$(PROJECT_INCLUDE)/rtems/score/watchdog.inl: macros/rtems/score/watchdog.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/watchdog.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/watchdog.inl
+
+$(PROJECT_INCLUDE)/rtems/score/wkspace.inl: macros/rtems/score/wkspace.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/wkspace.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/wkspace.inl
+
+if HAS_MP
+$(PROJECT_INCLUDE)/rtems/score/mppkt.inl: macros/rtems/score/mppkt.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/mppkt.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/mppkt.inl
+
+$(PROJECT_INCLUDE)/rtems/score/objectmp.inl: macros/rtems/score/objectmp.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/objectmp.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/objectmp.inl
+
+$(PROJECT_INCLUDE)/rtems/score/threadmp.inl: macros/rtems/score/threadmp.inl $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/threadmp.inl
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/threadmp.inl
+endif
+endif
+
+CLEANFILES += $(PREINSTALL_FILES)
+DISTCLEANFILES += $(PREINSTALL_DIRS)
+
+include $(top_srcdir)/automake/subdirs.am
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/score/cpu/.cvsignore b/cpukit/score/cpu/.cvsignore
new file mode 100644
index 0000000000..282522db03
--- /dev/null
+++ b/cpukit/score/cpu/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/cpukit/score/cpu/Makefile.am b/cpukit/score/cpu/Makefile.am
new file mode 100644
index 0000000000..c354422082
--- /dev/null
+++ b/cpukit/score/cpu/Makefile.am
@@ -0,0 +1,11 @@
+##
+## $Id$
+##
+
+SUBDIRS = @RTEMS_CPU@
+
+DIST_SUBDIRS = arm c4x h8300 i386 i960 m68k mips no_cpu or32 powerpc sh \
+ sparc unix
+
+include $(top_srcdir)/automake/subdirs.am
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/score/cpu/arm/.cvsignore b/cpukit/score/cpu/arm/.cvsignore
new file mode 100644
index 0000000000..282522db03
--- /dev/null
+++ b/cpukit/score/cpu/arm/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/cpukit/score/cpu/arm/ChangeLog b/cpukit/score/cpu/arm/ChangeLog
new file mode 100644
index 0000000000..5d5c7114e4
--- /dev/null
+++ b/cpukit/score/cpu/arm/ChangeLog
@@ -0,0 +1,331 @@
+2004-04-09 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/cpu.h: Fix typo.
+
+2004-04-06 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * configure.ac: Remove (Merged into $(top_srcdir)/configure.ac).
+ * Makefile.am: Don't include multilib.am.
+ Reflect merging configure.ac into $(top_srcdir)/configure.ac.
+
+2004-04-01 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * Makefile.am: Install asm.h to $(includedir)/rtems.
+
+2004-04-01 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * cpu_asm.S: Include <rtems/asm.h> instead of <asm.h>.
+
+2004-03-30 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * cpu.c, rtems/score/cpu.h: Convert to using c99 fixed size types.
+
+2004-03-29 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * configure.ac: RTEMS_TOP([../../../..]).
+
+2004-01-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Move RTEMS_TOP one subdir down.
+
+2004-01-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add PREINSTALL_DIRS.
+
+2004-01-14 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Re-add dirstamps to PREINSTALL_FILES.
+ Add PREINSTALL_FILES to CLEANFILES.
+
+2004-01-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Requires automake >= 1.8.1.
+
+2004-01-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include compile.am, again.
+
+2004-01-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Convert to using automake compilation rules.
+
+2003-12-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use mkdir_p. Remove dirs from PREINSTALL_FILES.
+
+2003-12-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Require automake >= 1.8, autoconf >= 2.59.
+
+2003-12-01 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Remove TMPINSTALL_FILES.
+
+2003-11-30 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add $(dirstamp) to preinstallation rules.
+
+2003-11-30 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add $(dirstamp) to preinstallation rules.
+
+2003-11-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Don't use gmake rules for preinstallation.
+
+2003-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_CANONICAL_HOST.
+
+2003-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_CHECK_CPU.
+
+2003-09-26 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/cpu.h: Obsoleting HP PA-RISC port and removing all
+ references.
+
+2003-09-04 Joel Sherrill <joel@OARcorp.com>
+
+ * asm.h, cpu.c, cpu_asm.S, rtems/score/arm.h, rtems/score/cpu.h,
+ rtems/score/cpu_asm.h, rtems/score/types.h: URL for license changed.
+
+2003-08-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use rtems-bugs@rtems.com as bug report email address.
+
+2003-04-17 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use "all-local:" instead of "all:".
+
+2003-03-06 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove AC_CONFIG_AUX_DIR.
+
+2003-03-03 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/score/arm.h: Remove ARM_HAS_THUMB (Unused).
+
+2003-03-02 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/score/cpu.h: Set up CPU_*_ENDIAN based on -D__ARMEL__ and
+ -D__ARMEB__. Fix minor typo in comment.
+
+2003-02-26 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/score/arm.h: Set up ARM_HAS_FPU based on -D__SOFTFP__.
+
+2002-12-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Require autoconf-2.57 + automake-1.7.2.
+ * Makefile.am: Eliminate C_O_FILES, S_O_FILES, libscorecpu_a_OBJECTS.
+
+2002-11-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Fix package name.
+
+2002-11-04 Joel Sherrill <joel@OARcorp.com>
+
+ * cpu.c: Removed warning.
+
+2002-11-01 Joel Sherrill <joel@OARcorp.com>
+
+ * cpu.c: Removed warnings.
+
+2002-10-31 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/cpu.h: Removed warning.
+
+2002-10-25 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Add nostdinc to AM_INIT_AUTOMAKE.
+
+2002-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * .cvsignore: Reformat.
+ Add autom4te*cache.
+ Remove autom4te.cache.
+
+2002-10-04 Jay Monkman <jtm@smoothsmoothie.com>
+
+ * rtems/score/cpu.h: Fix u16 and u32 swap routines.
+
+2002-08-05 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/cpu.h, rtems/score/types.h: Updated to fix some typos.
+
+2002-07-30 Jay Monkman <jtm@smoothsmoothie.com>
+
+ * cpu.c, cpu_asm.S, rtems/score/arm.h, rtems/score/cpu.h,
+ rtems/score/cpu_asm.h, rtems/score/types.h: ARM port works
+ well enough to run all sptests, tmtests, and ttcp.
+ In addition to general cleanup, there has been considerable
+ optimization to interrupt disable/enable, endian swapping,
+ and context switching.
+
+2002-07-26 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Build libscorecpu.a instead of rtems-cpu.rel.
+
+2002-07-22 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use .$(OBJEXT) instead of .o.
+
+2002-07-22 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use . instead of .o.
+
+2002-07-17 Jay Monkman <jtm@smoothsmoothie.com>
+
+ * rtems/score/cpu_asm.h: Enhanced to include register offsets.
+ * Makefile.am: Install rtems/score/cpu_asm.h.
+ * cpu.c: Significantly enhanced including the implementation of
+ _CPU_ISR_Get_level.
+ * cpu_asm.S: Improved behavior of context switch and interrupt
+ dispatching.
+ * rtems/score/arm.h: Improved the CPU model name determination.
+ * rtems/score/cpu.h: Improved interrupt disable/enable functions.
+
+2002-07-05 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/cpu.h: Filled in something that was marked XXX.
+
+2002-07-05 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: RTEMS_TOP(../../../..).
+
+2002-07-03 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems.c: Remove.
+ * Makefile.am: Reflect changes above.
+
+2002-07-01 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_PROJECT_ROOT.
+
+2002-06-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Add RTEMS_PROG_CCAS
+
+2002-06-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use AC_CONFIG_AUX_DIR(../../../..).
+ Add AC_PROG_RANLIB.
+
+2002-06-17 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include $(top_srcdir)/../../../automake/*.am.
+ Use ../../../aclocal.
+
+2002-04-18 Jay Monkman <jtm@smoothsmoothie.com>
+
+ * rtems/score/cpu.h (CPU_ISR_Disable and CPU_ISR_Enable): Correct them
+ where they correctly inform the compiler about the register they
+ are modifying.
+
+2001-04-03 Joel Sherrill <joel@OARcorp.com>
+
+ * Per PR94, all rtems/score/CPUtypes.h are named rtems/score/types.h.
+ * rtems/score/a29ktypes.h: Removed.
+ * rtems/score/types.h: New file via CVS magic.
+ * Makefile.am, rtems/score/cpu.h: Account for name change.
+
+2002-03-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac:
+ AC_INIT(package,_RTEMS_VERSION,_RTEMS_BUGS).
+ AM_INIT_AUTOMAKE([no-define foreign 1.6]).
+ * Makefile.am: Remove AUTOMAKE_OPTIONS.
+
+2001-02-04 Joel Sherrill <joel@OARcorp.com>
+
+ * configure.ac: Removed references to rtems/Makefile and
+ rtems/score/Makefile.
+
+2002-01-29 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/Makefile.am: Removed.
+ * rtems/score/Makefile.am: Removed.
+ * configure.ac: Reflect changes above.
+ * Makefile.am: Reflect changes above.
+
+2002-02-05 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_CHECK_CUSTOM_BSP.
+
+2002-01-03 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * cpu.c: Include rtems/bspIo.h instead of bspIo.h.
+
+2001-12-20 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use RTEMS_ENV_RTEMSCPU.
+
+2001-12-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add multilib support.
+
+2001-12-09 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * asm.h: include cpuopts.h instead of targopts.h
+ * rtems/score/arm.h: Use __arm__.
+
+2001-11-28 Joel Sherrill <joel@OARcorp.com>,
+
+ This was tracked as PR91.
+ * rtems/score/cpu.h: Added CPU_PROVIDES_ISR_IS_IN_PROGRESS macro which
+ is used to specify if the port uses the standard macro for this (FALSE).
+ A TRUE setting indicates the port provides its own implementation.
+
+2001-10-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * .cvsignore: Add autom4te.cache for autoconf > 2.52.
+ * configure.in: Remove.
+ * configure.ac: New file, generated from configure.in by autoupdate.
+
+2001-09-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/score/Makefile.am: Use 'PREINSTALL_FILES ='.
+ * Makefile.am: Use 'PREINSTALL_FILES ='.
+
+2001-02-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am, rtems/score/Makefile.am:
+ Apply include_*HEADERS instead of H_FILES.
+
+2001-01-03 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/cpu.h: Added _CPU_Initialize_vectors().
+
+2000-11-09 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use ... instead of RTEMS_TOPdir in ACLOCAL_AMFLAGS.
+
+2000-11-02 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Switch to ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal.
+
+2000-10-25 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: ACLOCAL_AMFLAGS= -I $(RTEMS_TOPdir)/macros.
+ Switch to GNU canonicalization.
+
+2000-09-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include compile.am, formatting.
+ * rtems/Makefile.am: Formatting.
+ * rtems/score/Makefile.am: Formatting.
+
+2000-08-29 Joel Sherrill <joel.sherrill@OARcorp.com>
+
+ * cpu.c: Spacing issues.
+ * rtems/score/cpu.h: Removed warning by setting _level.
+
+2000-08-29 Joel Sherrill <joel.sherrill@OARcorp.com>
+
+ * Makefile.am: Added S_O_FILES to list of objects.
+
+2000-08-10 Joel Sherrill <joel@OARcorp.com>
+
+ * ChangeLog: New file.
diff --git a/cpukit/score/cpu/arm/Makefile.am b/cpukit/score/cpu/arm/Makefile.am
new file mode 100644
index 0000000000..f3231c01ab
--- /dev/null
+++ b/cpukit/score/cpu/arm/Makefile.am
@@ -0,0 +1,62 @@
+##
+## $Id$
+##
+
+include $(top_srcdir)/automake/compile.am
+
+include_rtemsdir = $(includedir)/rtems
+include_rtems_HEADERS = asm.h
+
+include_rtems_scoredir = $(includedir)/rtems/score
+include_rtems_score_HEADERS = rtems/score/cpu.h rtems/score/cpu_asm.h \
+ rtems/score/arm.h rtems/score/types.h
+
+EXTRA_LIBRARIES = libscorecpu.a
+CLEANFILES = libscorecpu.a
+libscorecpu_a_SOURCES = cpu.c cpu_asm.S
+libscorecpu_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libscorecpu_g.a
+CLEANFILES += libscorecpu_g.a
+libscorecpu_g_a_SOURCES = $(libscorecpu_a_SOURCES)
+libscorecpu_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+all-local: $(PREINSTALL_FILES) libscorecpu$(LIB_VARIANT).a
+
+PREINSTALL_DIRS =
+PREINSTALL_FILES =
+
+$(PROJECT_INCLUDE)/rtems/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems
+ @: > $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/asm.h: asm.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/asm.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/asm.h
+
+$(PROJECT_INCLUDE)/rtems/score/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems/score
+ @: > $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/score/cpu.h: rtems/score/cpu.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/cpu.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/cpu.h
+
+$(PROJECT_INCLUDE)/rtems/score/cpu_asm.h: rtems/score/cpu_asm.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/cpu_asm.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/cpu_asm.h
+
+$(PROJECT_INCLUDE)/rtems/score/arm.h: rtems/score/arm.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/arm.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/arm.h
+
+$(PROJECT_INCLUDE)/rtems/score/types.h: rtems/score/types.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/types.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/types.h
+
+CLEANFILES += $(PREINSTALL_FILES)
+DISTCLEANFILES = $(PREINSTALL_DIRS)
+
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/score/cpu/arm/asm.h b/cpukit/score/cpu/arm/asm.h
new file mode 100644
index 0000000000..058697def3
--- /dev/null
+++ b/cpukit/score/cpu/arm/asm.h
@@ -0,0 +1,123 @@
+/* asm.h
+ *
+ * This include file attempts to address the problems
+ * caused by incompatible flavors of assemblers and
+ * toolsets. It primarily addresses variations in the
+ * use of leading underscores on symbols and the requirement
+ * that register names be preceded by a %.
+ *
+ *
+ * NOTE: The spacing in the use of these macros
+ * is critical to them working as advertised.
+ *
+ * COPYRIGHT:
+ *
+ * This file is based on similar code found in newlib available
+ * from ftp.cygnus.com. The file which was used had no copyright
+ * notice. This file is freely distributable as long as the source
+ * of the file is noted. This file is:
+ *
+ * COPYRIGHT (c) 2000 Canon Research Centre France SA.
+ * Emmanuel Raguet, mailto:raguet@crf.canon.fr
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ */
+
+#ifndef __ARM_ASM_h
+#define __ARM_ASM_h
+
+/*
+ * Indicate we are in an assembly file and get the basic CPU definitions.
+ */
+
+#ifndef ASM
+#define ASM
+#endif
+#include <rtems/score/cpuopts.h>
+#include <rtems/score/arm.h>
+
+/*
+ * Recent versions of GNU cpp define variables which indicate the
+ * need for underscores and percents. If not using GNU cpp or
+ * the version does not support this, then you will obviously
+ * have to define these as appropriate.
+ */
+
+#ifndef __USER_LABEL_PREFIX__
+#define __USER_LABEL_PREFIX__ _
+#endif
+
+#ifndef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__
+#endif
+
+/* ANSI concatenation macros. */
+
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+/* Use the right prefix for global labels. */
+
+#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+
+/* Use the right prefix for registers. */
+
+#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
+
+/*
+ * define macros for all of the registers on this CPU
+ *
+ * EXAMPLE: #define d0 REG (d0)
+ */
+
+#define r0 REG(r0)
+#define r1 REG(r1)
+#define r2 REG(r2)
+#define r3 REG(r3)
+#define r4 REG(r4)
+#define r5 REG(r5)
+#define r6 REG(r6)
+#define r7 REG(r7)
+#define r8 REG(r8)
+#define r9 REG(r9)
+#define r10 REG(r10)
+#define r11 REG(r11)
+#define r12 REG(r12)
+#define r13 REG(r13)
+#define r14 REG(r14)
+#define r15 REG(r15)
+
+#define CPSR REG(CPSR)
+
+#define SPSR REG(SPSR)
+
+/*
+ * Define macros to handle section beginning and ends.
+ */
+
+
+#define BEGIN_CODE_DCL .text
+#define END_CODE_DCL
+#define BEGIN_DATA_DCL .data
+#define END_DATA_DCL
+#define BEGIN_CODE .text
+#define END_CODE
+#define BEGIN_DATA
+#define END_DATA
+#define BEGIN_BSS
+#define END_BSS
+#define END
+
+/*
+ * Following must be tailor for a particular flavor of the C compiler.
+ * They may need to put underscores in front of the symbols.
+ */
+
+#define PUBLIC(sym) .globl SYM (sym)
+#define EXTERN(sym) .globl SYM (sym)
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/arm/cpu.c b/cpukit/score/cpu/arm/cpu.c
new file mode 100644
index 0000000000..772fe46ab7
--- /dev/null
+++ b/cpukit/score/cpu/arm/cpu.c
@@ -0,0 +1,320 @@
+/*
+ * ARM CPU Dependent Source
+ *
+ *
+ * COPYRIGHT (c) 2000 Canon Research Centre France SA.
+ * Emmanuel Raguet, mailto:raguet@crf.canon.fr
+ *
+ * Copyright (c) 2002 Advent Networks, Inc
+ * Jay Monkman <jmonkman@adventnetworks.com>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ */
+
+#include <rtems/system.h>
+#include <rtems.h>
+#include <rtems/bspIo.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/cpu.h>
+
+/* _CPU_Initialize
+ *
+ * This routine performs processor dependent initialization.
+ *
+ * INPUT PARAMETERS:
+ * cpu_table - CPU table to initialize
+ * thread_dispatch - address of ISR disptaching routine (unused)
+ *
+ */
+
+uint32_t g_data_abort_cnt = 0;
+uint32_t g_data_abort_insn_list[1024];
+
+void _CPU_Initialize(
+ rtems_cpu_table *cpu_table,
+ void (*thread_dispatch) /* ignored on this CPU */
+)
+{
+ _CPU_Table = *cpu_table;
+}
+
+/*
+ *
+ * _CPU_ISR_Get_level - returns the current interrupt level
+ */
+
+uint32_t _CPU_ISR_Get_level( void )
+{
+ uint32_t reg = 0; /* to avoid warning */
+
+ asm volatile ("mrs %0, cpsr \n" \
+ "and %0, %0, #0xc0 \n" \
+ : "=r" (reg) \
+ : "0" (reg) );
+
+ return reg;
+}
+
+/*
+ * _CPU_ISR_install_vector
+ *
+ * This kernel routine installs the RTEMS handler for the
+ * specified vector.
+ *
+ * Input parameters:
+ * vector - interrupt vector number
+ * new_handler - replacement ISR for this vector number
+ * old_handler - pointer to store former ISR for this vector number
+ *
+ * FIXME: This vector scheme should be changed to allow FIQ to be
+ * handled better. I'd like to be able to put VectorTable
+ * elsewhere - JTM
+ *
+ *
+ * Output parameters: NONE
+ *
+ */
+void _CPU_ISR_install_vector(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+)
+{
+ /* pointer on the redirection table in RAM */
+ long *VectorTable = (long *)(MAX_EXCEPTIONS * 4);
+
+ if (old_handler != NULL) {
+ old_handler = *(proc_ptr *)(VectorTable + vector);
+ }
+
+ *(VectorTable + vector) = (long)new_handler ;
+
+}
+
+void _CPU_Context_Initialize(
+ Context_Control *the_context,
+ uint32_t *stack_base,
+ uint32_t size,
+ uint32_t new_level,
+ void *entry_point,
+ boolean is_fp
+)
+{
+ the_context->register_sp = (uint32_t )stack_base + size ;
+ the_context->register_lr = (uint32_t )entry_point;
+ the_context->register_cpsr = new_level | 0x13;
+}
+
+
+/*
+ * _CPU_Install_interrupt_stack - this function is empty since the
+ * BSP must set up the interrupt stacks.
+ */
+
+void _CPU_Install_interrupt_stack( void )
+{
+}
+
+void _defaultExcHandler (CPU_Exception_frame *ctx)
+{
+ printk("\n\r");
+ printk("----------------------------------------------------------\n\r");
+#if 0
+ printk("Exception 0x%x caught at PC 0x%x by thread %d\n",
+ ctx->register_pc, ctx->register_lr - 4,
+ _Thread_Executing->Object.id);
+#endif
+ printk("----------------------------------------------------------\n\r");
+ printk("Processor execution context at time of the fault was :\n\r");
+ printk("----------------------------------------------------------\n\r");
+#if 0
+ printk(" r0 = %8x r1 = %8x r2 = %8x r3 = %8x\n\r",
+ ctx->register_r0, ctx->register_r1,
+ ctx->register_r2, ctx->register_r3);
+ printk(" r4 = %8x r5 = %8x r6 = %8x r7 = %8x\n\r",
+ ctx->register_r4, ctx->register_r5,
+ ctx->register_r6, ctx->register_r7);
+ printk(" r8 = %8x r9 = %8x r10 = %8x\n\r",
+ ctx->register_r8, ctx->register_r9, ctx->register_r10);
+ printk(" fp = %8x ip = %8x sp = %8x pc = %8x\n\r",
+ ctx->register_fp, ctx->register_ip,
+ ctx->register_sp, ctx->register_lr - 4);
+ printk("----------------------------------------------------------\n\r");
+#endif
+ if (_ISR_Nest_level > 0) {
+ /*
+ * In this case we shall not delete the task interrupted as
+ * it has nothing to do with the fault. We cannot return either
+ * because the eip points to the faulty instruction so...
+ */
+ printk("Exception while executing ISR!!!. System locked\n\r");
+ while(1);
+ }
+ else {
+ printk("*********** FAULTY THREAD WILL BE DELETED **************\n\r");
+ rtems_task_delete(_Thread_Executing->Object.id);
+ }
+}
+
+cpuExcHandlerType _currentExcHandler = _defaultExcHandler;
+
+extern void _Exception_Handler_Undef_Swi();
+extern void _Exception_Handler_Abort();
+extern void _exc_data_abort();
+/* FIXME: put comments here */
+void rtems_exception_init_mngt()
+{
+ ISR_Level level;
+
+ _CPU_ISR_Disable(level);
+ _CPU_ISR_install_vector(ARM_EXCEPTION_UNDEF,
+ _Exception_Handler_Undef_Swi,
+ NULL);
+
+ _CPU_ISR_install_vector(ARM_EXCEPTION_SWI,
+ _Exception_Handler_Undef_Swi,
+ NULL);
+
+ _CPU_ISR_install_vector(ARM_EXCEPTION_PREF_ABORT,
+ _Exception_Handler_Abort,
+ NULL);
+
+ _CPU_ISR_install_vector(ARM_EXCEPTION_DATA_ABORT,
+ _exc_data_abort,
+ NULL);
+
+ _CPU_ISR_install_vector(ARM_EXCEPTION_FIQ,
+ _Exception_Handler_Abort,
+ NULL);
+
+ _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ,
+ _Exception_Handler_Abort,
+ NULL);
+
+ _CPU_ISR_Enable(level);
+}
+
+#define INSN_MASK 0xc5
+
+#define INSN_STM1 0x80
+#define INSN_STM2 0x84
+#define INSN_STR 0x40
+#define INSN_STRB 0x44
+
+#define INSN_LDM1 0x81
+#define INSN_LDM23 0x85
+#define INSN_LDR 0x41
+#define INSN_LDRB 0x45
+
+#define GET_RD(x) ((x & 0x0000f000) >> 12)
+#define GET_RN(x) ((x & 0x000f0000) >> 16)
+
+#define GET_U(x) ((x & 0x00800000) >> 23)
+#define GET_I(x) ((x & 0x02000000) >> 25)
+
+#define GET_REG(r, ctx) (((uint32_t *)ctx)[r])
+#define SET_REG(r, ctx, v) (((uint32_t *)ctx)[r] = v)
+#define GET_OFFSET(insn) (insn & 0xfff)
+
+
+/* This function is supposed to figure out what caused the
+ * data abort, do that, then return.
+ *
+ * All unhandled instructions cause the system to hang.
+ */
+
+void do_data_abort(uint32_t insn, uint32_t spsr,
+ CPU_Exception_frame *ctx)
+{
+ uint8_t decode;
+ uint8_t insn_type;
+
+ uint32_t rn;
+ uint32_t rd;
+
+ uint8_t *src_addr;
+ uint32_t tmp;
+
+ g_data_abort_insn_list[g_data_abort_cnt & 0x3ff] = ctx->register_lr - 8;
+ g_data_abort_cnt++;
+
+ decode = ((insn >> 20) & 0xff);
+
+ insn_type = decode & INSN_MASK;
+ switch(insn_type) {
+ case INSN_STM1:
+ printk("\n\nINSN_STM1\n");
+ break;
+ case INSN_STM2:
+ printk("\n\nINSN_STM2\n");
+ break;
+ case INSN_STR:
+ printk("\n\nINSN_STR\n");
+ break;
+ case INSN_STRB:
+ printk("\n\nINSN_STRB\n");
+ break;
+ case INSN_LDM1:
+ printk("\n\nINSN_LDM1\n");
+ break;
+ case INSN_LDM23:
+ printk("\n\nINSN_LDM23\n");
+ break;
+ case INSN_LDR:
+ printk("\n\nINSN_LDR\n");
+
+ rn = GET_RN(insn);
+ rd = GET_RD(insn);
+
+ /* immediate offset/index */
+ if (GET_I(insn) == 0) {
+ switch(decode & 0x12) { /* P and W bits */
+ case 0x00: /* P=0, W=0 -> base is updated, post-indexed */
+ printk("\tPost-indexed\n");
+ break;
+ case 0x02: /* P=0, W=1 -> user mode access */
+ printk("\tUser mode\n");
+ break;
+ case 0x10: /* P=1, W=0 -> base not updated */
+ src_addr = (uint8_t *)GET_REG(rn, ctx);
+ if (GET_U(insn) == 0) {
+ src_addr -= GET_OFFSET(insn);
+ } else {
+ src_addr += GET_OFFSET(insn);
+ }
+ tmp = (src_addr[0] |
+ (src_addr[1] << 8) |
+ (src_addr[2] << 16) |
+ (src_addr[3] << 24));
+ SET_REG(rd, ctx, tmp);
+ return;
+ break;
+ case 0x12: /* P=1, W=1 -> base is updated, pre-indexed */
+ printk("\tPre-indexed\n");
+ break;
+ }
+ }
+ break;
+ case INSN_LDRB:
+ printk("\n\nINSN_LDRB\n");
+ break;
+ default:
+ printk("\n\nUnrecognized instruction\n");
+ break;
+ }
+
+ printk("data_abort at address 0x%x, instruction: 0x%x, spsr = 0x%x\n",
+ ctx->register_lr - 8, insn, spsr);
+
+ /* disable interrupts, wait forever */
+ _CPU_ISR_Disable(tmp);
+ while(1) {
+ continue;
+ }
+ return;
+}
diff --git a/cpukit/score/cpu/arm/cpu_asm.S b/cpukit/score/cpu/arm/cpu_asm.S
new file mode 100644
index 0000000000..a418657c72
--- /dev/null
+++ b/cpukit/score/cpu/arm/cpu_asm.S
@@ -0,0 +1,154 @@
+/*
+ * $Id$
+ *
+ * This file contains all assembly code for the ARM implementation
+ * of RTEMS.
+ *
+ * Copyright (c) 2002 by Advent Networks, Inc.
+ * Jay Monkman <jmonkman@adventnetworks.com>
+ *
+ * COPYRIGHT (c) 2000 Canon Research Centre France SA.
+ * Emmanuel Raguet, mailto:raguet@crf.canon.fr
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ */
+
+#include <rtems/asm.h>
+#include <rtems/score/cpu_asm.h>
+
+
+/*
+ * void _CPU_Context_switch( run_context, heir_context )
+ * void _CPU_Context_restore( run_context, heir_context )
+ *
+ * This routine performs a normal non-FP context.
+ *
+ * R0 = run_context R1 = heir_context
+ *
+ * This function copies the current registers to where r0 points, then
+ * restores the ones from where r1 points.
+ *
+ * Using the ldm/stm opcodes save 2-3 us on 100 MHz ARM9TDMI with
+ * a 16 bit data bus.
+ *
+ */
+ .globl _CPU_Context_switch
+_CPU_Context_switch:
+/* Start saving context */
+ mrs r2, cpsr
+ stmia r0, {r2, r4, r5, r6, r7, r8, r9, r10, r11, r13, r14}
+
+
+/* Start restoring context */
+_restore:
+ ldmia r1, {r2, r4, r5, r6, r7, r8, r9, r10, r11, r13, r14}
+ msr cpsr, r2
+ mov pc, lr
+
+/*
+ * void _CPU_Context_restore( new_context )
+ *
+ * This function copies the restores the registers from where r0 points.
+ * It must match _CPU_Context_switch()
+ *
+ */
+ .globl _CPU_Context_restore
+_CPU_Context_restore:
+ mov r1, r0
+ b _restore
+
+
+
+/* FIXME: _Exception_Handler_Undef_Swi is untested */
+ .globl _Exception_Handler_Undef_Swi
+_Exception_Handler_Undef_Swi:
+/* FIXME: This should use load and store multiple instructions */
+ sub r13,r13,#SIZE_REGS
+ str r4, [r13, #REG_R4]
+ str r5, [r13, #REG_R5]
+ str r6, [r13, #REG_R6]
+ str r7, [r13, #REG_R7]
+ str r8, [r13, #REG_R8]
+ str r9, [r13, #REG_R9]
+ str r10, [r13, #REG_R10]
+ str r11, [r13, #REG_R11]
+ str sp, [r13, #REG_SP]
+ str lr, [r13, #REG_LR]
+ mrs r0, cpsr /* read the status */
+ and r0, r0,#0x1f /* we keep the mode as exception number */
+ str r0, [r13, #REG_PC] /* we store it in a free place */
+ mov r0, r13 /* put frame address in r0 (C arg 1) */
+
+ ldr r1, =SWI_Handler
+ ldr lr, =_go_back_1
+ ldr pc,[r1] /* call handler */
+_go_back_1:
+ ldr r4, [r13, #REG_R4]
+ ldr r5, [r13, #REG_R5]
+ ldr r6, [r13, #REG_R6]
+ ldr r7, [r13, #REG_R7]
+ ldr r8, [r13, #REG_R8]
+ ldr r9, [r13, #REG_R9]
+ ldr r10, [r13, #REG_R10]
+ ldr r11, [r13, #REG_R11]
+ ldr sp, [r13, #REG_SP]
+ ldr lr, [r13, #REG_LR]
+ add r13,r13,#SIZE_REGS
+ movs pc,r14 /* return */
+
+/* FIXME: _Exception_Handler_Abort is untested */
+ .globl _Exception_Handler_Abort
+_Exception_Handler_Abort:
+/* FIXME: This should use load and store multiple instructions */
+ sub r13,r13,#SIZE_REGS
+ str r4, [r13, #REG_R4]
+ str r5, [r13, #REG_R5]
+ str r6, [r13, #REG_R6]
+ str r7, [r13, #REG_R7]
+ str r8, [r13, #REG_R8]
+ str r9, [r13, #REG_R9]
+ str sp, [r13, #REG_R11]
+ str lr, [r13, #REG_SP]
+ str lr, [r13, #REG_LR]
+ mrs r0, cpsr /* read the status */
+ and r0, r0,#0x1f /* we keep the mode as exception number */
+ str r0, [r13, #REG_PC] /* we store it in a free place */
+ mov r0, r13 /* put frame address in ro (C arg 1) */
+
+ ldr r1, =_currentExcHandler
+ ldr lr, =_go_back_2
+ ldr pc,[r1] /* call handler */
+_go_back_2:
+ ldr r4, [r13, #REG_R4]
+ ldr r5, [r13, #REG_R5]
+ ldr r6, [r13, #REG_R6]
+ ldr r7, [r13, #REG_R7]
+ ldr r8, [r13, #REG_R8]
+ ldr r9, [r13, #REG_R9]
+ ldr r10, [r13, #REG_R10]
+ ldr sp, [r13, #REG_R11]
+ ldr lr, [r13, #REG_SP]
+ ldr lr, [r13, #REG_LR]
+ add r13,r13,#SIZE_REGS
+ subs pc,r14,#4 /* return */
+
+ .globl _exc_data_abort
+_exc_data_abort:
+ sub sp, sp, #SIZE_REGS /* reserve register frame */
+ stmia sp, {r0-r12}
+ str lr, [sp, #REG_LR]
+ mov r1, lr
+ ldr r0, [r1, #-8] /* r0 = bad instruction */
+ mrs r1, spsr /* r1 = spsr */
+ mov r2, r13 /* r2 = exception frame */
+ bl do_data_abort
+
+ ldr lr, [sp, #REG_LR]
+ ldmia sp, {r0-r12}
+ add sp, sp, #SIZE_REGS
+
+ subs pc, r14, #4 /* return to the instruction */
+ /* _AFTER_ the aborted one */
diff --git a/cpukit/score/cpu/arm/rtems/asm.h b/cpukit/score/cpu/arm/rtems/asm.h
new file mode 100644
index 0000000000..058697def3
--- /dev/null
+++ b/cpukit/score/cpu/arm/rtems/asm.h
@@ -0,0 +1,123 @@
+/* asm.h
+ *
+ * This include file attempts to address the problems
+ * caused by incompatible flavors of assemblers and
+ * toolsets. It primarily addresses variations in the
+ * use of leading underscores on symbols and the requirement
+ * that register names be preceded by a %.
+ *
+ *
+ * NOTE: The spacing in the use of these macros
+ * is critical to them working as advertised.
+ *
+ * COPYRIGHT:
+ *
+ * This file is based on similar code found in newlib available
+ * from ftp.cygnus.com. The file which was used had no copyright
+ * notice. This file is freely distributable as long as the source
+ * of the file is noted. This file is:
+ *
+ * COPYRIGHT (c) 2000 Canon Research Centre France SA.
+ * Emmanuel Raguet, mailto:raguet@crf.canon.fr
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ */
+
+#ifndef __ARM_ASM_h
+#define __ARM_ASM_h
+
+/*
+ * Indicate we are in an assembly file and get the basic CPU definitions.
+ */
+
+#ifndef ASM
+#define ASM
+#endif
+#include <rtems/score/cpuopts.h>
+#include <rtems/score/arm.h>
+
+/*
+ * Recent versions of GNU cpp define variables which indicate the
+ * need for underscores and percents. If not using GNU cpp or
+ * the version does not support this, then you will obviously
+ * have to define these as appropriate.
+ */
+
+#ifndef __USER_LABEL_PREFIX__
+#define __USER_LABEL_PREFIX__ _
+#endif
+
+#ifndef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__
+#endif
+
+/* ANSI concatenation macros. */
+
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+/* Use the right prefix for global labels. */
+
+#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+
+/* Use the right prefix for registers. */
+
+#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
+
+/*
+ * define macros for all of the registers on this CPU
+ *
+ * EXAMPLE: #define d0 REG (d0)
+ */
+
+#define r0 REG(r0)
+#define r1 REG(r1)
+#define r2 REG(r2)
+#define r3 REG(r3)
+#define r4 REG(r4)
+#define r5 REG(r5)
+#define r6 REG(r6)
+#define r7 REG(r7)
+#define r8 REG(r8)
+#define r9 REG(r9)
+#define r10 REG(r10)
+#define r11 REG(r11)
+#define r12 REG(r12)
+#define r13 REG(r13)
+#define r14 REG(r14)
+#define r15 REG(r15)
+
+#define CPSR REG(CPSR)
+
+#define SPSR REG(SPSR)
+
+/*
+ * Define macros to handle section beginning and ends.
+ */
+
+
+#define BEGIN_CODE_DCL .text
+#define END_CODE_DCL
+#define BEGIN_DATA_DCL .data
+#define END_DATA_DCL
+#define BEGIN_CODE .text
+#define END_CODE
+#define BEGIN_DATA
+#define END_DATA
+#define BEGIN_BSS
+#define END_BSS
+#define END
+
+/*
+ * Following must be tailor for a particular flavor of the C compiler.
+ * They may need to put underscores in front of the symbols.
+ */
+
+#define PUBLIC(sym) .globl SYM (sym)
+#define EXTERN(sym) .globl SYM (sym)
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/arm/rtems/score/arm.h b/cpukit/score/cpu/arm/rtems/score/arm.h
new file mode 100644
index 0000000000..6c5a19b132
--- /dev/null
+++ b/cpukit/score/cpu/arm/rtems/score/arm.h
@@ -0,0 +1,80 @@
+/*
+ * $Id$
+ *
+ * COPYRIGHT (c) 2000 Canon Research Centre France SA.
+ * Emmanuel Raguet, mailto:raguet@crf.canon.fr
+ *
+ * Copyright (c) 2002 Advent Networks, Inc.
+ * Jay Monkman <jmonkman@adventnetworks.com>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ */
+
+#ifndef _INCLUDE_ARM_h
+#define _INCLUDE_ARM_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This file contains the information required to build
+ * RTEMS for a particular member of the "arm"
+ * family when executing in protected mode. It does
+ * this by setting variables to indicate which implementation
+ * dependent features are present in a particular member
+ * of the family.
+ */
+#if defined(__ARM_ARCH_4__)
+# define CPU_MODEL_NAME "ARMv4"
+# define ARM_HAS_CLZ 0
+
+#elif defined(__ARM_ARCH_4T__)
+# define CPU_MODEL_NAME "ARMv4T"
+# define ARM_HAS_CLZ 0
+
+#elif defined(__ARM_ARCH_5__)
+# define CPU_MODEL_NAME "ARMv5"
+# define ARM_HAS_CLZ 1
+
+#elif defined(__ARM_ARCH_5T__)
+# define CPU_MODEL_NAME "ARMv5T"
+# define ARM_HAS_CLZ 1
+
+#elif defined(__ARM_ARCH_5E__)
+# define CPU_MODEL_NAME "ARMv5E"
+# define ARM_HAS_CLZ 1
+
+#elif defined(__ARM_ARCH_5TE__)
+# define CPU_MODEL_NAME "ARMv5TE"
+# define ARM_HAS_CLZ 1
+
+#else
+# error "Unsupported CPU Model"
+
+#endif
+
+/* All ARM CPUs are assumed to not have floating point units */
+#if defined(__SOFTFP__)
+#define ARM_HAS_FPU 0
+#else
+#define ARM_HAS_FPU 1
+# error "FPU-support not yet implemented for the arm"
+#endif
+
+
+/*
+ * Define the name of the CPU family.
+ */
+
+#define CPU_NAME "ARM"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ! _INCLUDE_ARM_h */
+/* end of include file */
diff --git a/cpukit/score/cpu/arm/rtems/score/cpu.h b/cpukit/score/cpu/arm/rtems/score/cpu.h
new file mode 100644
index 0000000000..160084ed8f
--- /dev/null
+++ b/cpukit/score/cpu/arm/rtems/score/cpu.h
@@ -0,0 +1,928 @@
+/*
+ * $Id$
+ *
+ * This include file contains information pertaining to the ARM
+ * processor.
+ *
+ * Copyright (c) 2002 Advent Networks, Inc.
+ * Jay Monkman <jmonkman@adventnetworks.com>
+ *
+ * COPYRIGHT (c) 2000 Canon Research Centre France SA.
+ * Emmanuel Raguet, mailto:raguet@crf.canon.fr
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ */
+
+/* FIXME: finish commenting/cleaning up this file */
+#ifndef __CPU_h
+#define __CPU_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/arm.h> /* pick up machine definitions */
+#ifndef ASM
+#include <rtems/score/types.h>
+#endif
+
+/* conditional compilation parameters */
+
+/*
+ * Should the calls to _Thread_Enable_dispatch be inlined?
+ *
+ * If TRUE, then they are inlined.
+ * If FALSE, then a subroutine call is made.
+ *
+ * Basically this is an example of the classic trade-off of size
+ * versus speed. Inlining the call (TRUE) typically increases the
+ * size of RTEMS while speeding up the enabling of dispatching.
+ * [NOTE: In general, the _Thread_Dispatch_disable_level will
+ * only be 0 or 1 unless you are in an interrupt handler and that
+ * interrupt handler invokes the executive.] When not inlined
+ * something calls _Thread_Enable_dispatch which in turns calls
+ * _Thread_Dispatch. If the enable dispatch is inlined, then
+ * one subroutine call is avoided entirely.]
+ */
+
+#define CPU_INLINE_ENABLE_DISPATCH TRUE
+
+/*
+ * Should the body of the search loops in _Thread_queue_Enqueue_priority
+ * be unrolled one time? In unrolled each iteration of the loop examines
+ * two "nodes" on the chain being searched. Otherwise, only one node
+ * is examined per iteration.
+ *
+ * If TRUE, then the loops are unrolled.
+ * If FALSE, then the loops are not unrolled.
+ *
+ * The primary factor in making this decision is the cost of disabling
+ * and enabling interrupts (_ISR_Flash) versus the cost of rest of the
+ * body of the loop. On some CPUs, the flash is more expensive than
+ * one iteration of the loop body. In this case, it might be desirable
+ * to unroll the loop. It is important to note that on some CPUs, this
+ * code is the longest interrupt disable period in RTEMS. So it is
+ * necessary to strike a balance when setting this parameter.
+ */
+
+#define CPU_UNROLL_ENQUEUE_PRIORITY TRUE
+
+/*
+ * Does RTEMS manage a dedicated interrupt stack in software?
+ *
+ * If TRUE, then a stack is allocated in _Interrupt_Manager_initialization.
+ * If FALSE, nothing is done.
+ *
+ * If the CPU supports a dedicated interrupt stack in hardware,
+ * then it is generally the responsibility of the BSP to allocate it
+ * and set it up.
+ *
+ * If the CPU does not support a dedicated interrupt stack, then
+ * the porter has two options: (1) execute interrupts on the
+ * stack of the interrupted task, and (2) have RTEMS manage a dedicated
+ * interrupt stack.
+ *
+ * If this is TRUE, CPU_ALLOCATE_INTERRUPT_STACK should also be TRUE.
+ *
+ * Only one of CPU_HAS_SOFTWARE_INTERRUPT_STACK and
+ * CPU_HAS_HARDWARE_INTERRUPT_STACK should be set to TRUE. It is
+ * possible that both are FALSE for a particular CPU. Although it
+ * is unclear what that would imply about the interrupt processing
+ * procedure on that CPU.
+ */
+
+#define CPU_HAS_SOFTWARE_INTERRUPT_STACK FALSE
+
+/*
+ * Does this CPU have hardware support for a dedicated interrupt stack?
+ *
+ * If TRUE, then it must be installed during initialization.
+ * If FALSE, then no installation is performed.
+ *
+ * If this is TRUE, CPU_ALLOCATE_INTERRUPT_STACK should also be TRUE.
+ *
+ * Only one of CPU_HAS_SOFTWARE_INTERRUPT_STACK and
+ * CPU_HAS_HARDWARE_INTERRUPT_STACK should be set to TRUE. It is
+ * possible that both are FALSE for a particular CPU. Although it
+ * is unclear what that would imply about the interrupt processing
+ * procedure on that CPU.
+ */
+
+#define CPU_HAS_HARDWARE_INTERRUPT_STACK TRUE
+
+/*
+ * Does RTEMS allocate a dedicated interrupt stack in the Interrupt Manager?
+ *
+ * If TRUE, then the memory is allocated during initialization.
+ * If FALSE, then the memory is allocated during initialization.
+ *
+ * This should be TRUE is CPU_HAS_SOFTWARE_INTERRUPT_STACK is TRUE
+ * or CPU_INSTALL_HARDWARE_INTERRUPT_STACK is TRUE.
+ */
+
+#define CPU_ALLOCATE_INTERRUPT_STACK FALSE
+
+/*
+ * Does the RTEMS invoke the user's ISR with the vector number and
+ * a pointer to the saved interrupt frame (1) or just the vector
+ * number (0)?
+ */
+
+#define CPU_ISR_PASSES_FRAME_POINTER 0
+
+/*
+ * Does the CPU have hardware floating point?
+ *
+ * If TRUE, then the RTEMS_FLOATING_POINT task attribute is supported.
+ * If FALSE, then the RTEMS_FLOATING_POINT task attribute is ignored.
+ *
+ * If there is a FP coprocessor such as the i387 or mc68881, then
+ * the answer is TRUE.
+ *
+ * The macro name "ARM_HAS_FPU" should be made CPU specific.
+ * It indicates whether or not this CPU model has FP support. For
+ * example, it would be possible to have an i386_nofp CPU model
+ * which set this to false to indicate that you have an i386 without
+ * an i387 and wish to leave floating point support out of RTEMS.
+ */
+
+#if ( ARM_HAS_FPU == 1 )
+#define CPU_HARDWARE_FP TRUE
+#else
+#define CPU_HARDWARE_FP FALSE
+#endif
+
+#define CPU_SOFTWARE_FP FALSE
+
+/*
+ * Are all tasks RTEMS_FLOATING_POINT tasks implicitly?
+ *
+ * If TRUE, then the RTEMS_FLOATING_POINT task attribute is assumed.
+ * If FALSE, then the RTEMS_FLOATING_POINT task attribute is followed.
+ *
+ * If CPU_HARDWARE_FP is FALSE, then this should be FALSE as well.
+ */
+
+#define CPU_ALL_TASKS_ARE_FP FALSE
+
+/*
+ * Should the IDLE task have a floating point context?
+ *
+ * If TRUE, then the IDLE task is created as a RTEMS_FLOATING_POINT task
+ * and it has a floating point context which is switched in and out.
+ * If FALSE, then the IDLE task does not have a floating point context.
+ *
+ * Setting this to TRUE negatively impacts the time required to preempt
+ * the IDLE task from an interrupt because the floating point context
+ * must be saved as part of the preemption.
+ */
+
+#define CPU_IDLE_TASK_IS_FP FALSE
+
+/*
+ * Should the saving of the floating point registers be deferred
+ * until a context switch is made to another different floating point
+ * task?
+ *
+ * If TRUE, then the floating point context will not be stored until
+ * necessary. It will remain in the floating point registers and not
+ * disturned until another floating point task is switched to.
+ *
+ * If FALSE, then the floating point context is saved when a floating
+ * point task is switched out and restored when the next floating point
+ * task is restored. The state of the floating point registers between
+ * those two operations is not specified.
+ *
+ * If the floating point context does NOT have to be saved as part of
+ * interrupt dispatching, then it should be safe to set this to TRUE.
+ *
+ * Setting this flag to TRUE results in using a different algorithm
+ * for deciding when to save and restore the floating point context.
+ * The deferred FP switch algorithm minimizes the number of times
+ * the FP context is saved and restored. The FP context is not saved
+ * until a context switch is made to another, different FP task.
+ * Thus in a system with only one FP task, the FP context will never
+ * be saved or restored.
+ */
+
+#define CPU_USE_DEFERRED_FP_SWITCH FALSE
+
+/*
+ * Does this port provide a CPU dependent IDLE task implementation?
+ *
+ * If TRUE, then the routine _CPU_Thread_Idle_body
+ * must be provided and is the default IDLE thread body instead of
+ * _CPU_Thread_Idle_body.
+ *
+ * If FALSE, then use the generic IDLE thread body if the BSP does
+ * not provide one.
+ *
+ * This is intended to allow for supporting processors which have
+ * a low power or idle mode. When the IDLE thread is executed, then
+ * the CPU can be powered down.
+ *
+ * The order of precedence for selecting the IDLE thread body is:
+ *
+ * 1. BSP provided
+ * 2. CPU dependent (if provided)
+ * 3. generic (if no BSP and no CPU dependent)
+ */
+
+#define CPU_PROVIDES_IDLE_THREAD_BODY FALSE
+
+/*
+ * Does the stack grow up (toward higher addresses) or down
+ * (toward lower addresses)?
+ *
+ * If TRUE, then the grows upward.
+ * If FALSE, then the grows toward smaller addresses.
+ */
+
+#define CPU_STACK_GROWS_UP FALSE
+
+/*
+ * The following is the variable attribute used to force alignment
+ * of critical RTEMS structures. On some processors it may make
+ * sense to have these aligned on tighter boundaries than
+ * the minimum requirements of the compiler in order to have as
+ * much of the critical data area as possible in a cache line.
+ *
+ * The placement of this macro in the declaration of the variables
+ * is based on the syntactically requirements of the GNU C
+ * "__attribute__" extension. For example with GNU C, use
+ * the following to force a structures to a 32 byte boundary.
+ *
+ * __attribute__ ((aligned (32)))
+ *
+ * NOTE: Currently only the Priority Bit Map table uses this feature.
+ * To benefit from using this, the data must be heavily
+ * used so it will stay in the cache and used frequently enough
+ * in the executive to justify turning this on.
+ */
+
+#define CPU_STRUCTURE_ALIGNMENT __attribute__ ((aligned (32)))
+
+/*
+ * Define what is required to specify how the network to host conversion
+ * routines are handled.
+ */
+
+#define CPU_HAS_OWN_HOST_TO_NETWORK_ROUTINES FALSE
+
+#if defined(__ARMEL__)
+#define CPU_BIG_ENDIAN FALSE
+#define CPU_LITTLE_ENDIAN TRUE
+#elif defined(__ARMEB__)
+#define CPU_BIG_ENDIAN TRUE
+#define CPU_LITTLE_ENDIAN FALSE
+#else
+#error "Unknown endianness"
+#endif
+
+/*
+ * The following defines the number of bits actually used in the
+ * interrupt field of the task mode. How those bits map to the
+ * CPU interrupt levels is defined by the routine _CPU_ISR_Set_level().
+ */
+
+#define CPU_MODES_INTERRUPT_MASK 0x000000c0
+
+/*
+ * Processor defined structures
+ *
+ * Examples structures include the descriptor tables from the i386
+ * and the processor control structure on the i960ca.
+ */
+
+/* may need to put some structures here. */
+
+/*
+ * Contexts
+ *
+ * Generally there are 2 types of context to save.
+ * 1. Interrupt registers to save
+ * 2. Task level registers to save
+ *
+ * This means we have the following 3 context items:
+ * 1. task level context stuff:: Context_Control
+ * 2. floating point task stuff:: Context_Control_fp
+ * 3. special interrupt level context :: Context_Control_interrupt
+ *
+ * On some processors, it is cost-effective to save only the callee
+ * preserved registers during a task context switch. This means
+ * that the ISR code needs to save those registers which do not
+ * persist across function calls. It is not mandatory to make this
+ * distinctions between the caller/callee saves registers for the
+ * purpose of minimizing context saved during task switch and on interrupts.
+ * If the cost of saving extra registers is minimal, simplicity is the
+ * choice. Save the same context on interrupt entry as for tasks in
+ * this case.
+ *
+ * Additionally, if gdb is to be made aware of RTEMS tasks for this CPU, then
+ * care should be used in designing the context area.
+ *
+ * On some CPUs with hardware floating point support, the Context_Control_fp
+ * structure will not be used or it simply consist of an array of a
+ * fixed number of bytes. This is done when the floating point context
+ * is dumped by a "FP save context" type instruction and the format
+ * is not really defined by the CPU. In this case, there is no need
+ * to figure out the exact format -- only the size. Of course, although
+ * this is enough information for RTEMS, it is probably not enough for
+ * a debugger such as gdb. But that is another problem.
+ */
+typedef struct {
+ uint32_t register_cpsr;
+ uint32_t register_r4;
+ uint32_t register_r5;
+ uint32_t register_r6;
+ uint32_t register_r7;
+ uint32_t register_r8;
+ uint32_t register_r9;
+ uint32_t register_r10;
+ uint32_t register_fp;
+ uint32_t register_sp;
+ uint32_t register_lr;
+ uint32_t register_pc;
+} Context_Control;
+
+typedef struct {
+ double some_float_register;
+} Context_Control_fp;
+
+typedef struct {
+ uint32_t register_r0;
+ uint32_t register_r1;
+ uint32_t register_r2;
+ uint32_t register_r3;
+ uint32_t register_ip;
+ uint32_t register_lr;
+} CPU_Exception_frame;
+
+typedef void (*cpuExcHandlerType) (CPU_Exception_frame*);
+extern cpuExcHandlerType _currentExcHandler;
+extern void rtems_exception_init_mngt();
+
+/*
+ * The following structure defines the set of information saved
+ * on the current stack by RTEMS upon receipt of each interrupt
+ * that will lead to re-enter the kernel to signal the thread.
+ */
+
+typedef CPU_Exception_frame CPU_Interrupt_frame;
+
+/*
+ * The following table contains the information required to configure
+ * the XXX processor specific parameters.
+ */
+
+typedef struct {
+ void (*pretasking_hook)( void );
+ void (*predriver_hook)( void );
+ void (*postdriver_hook)( void );
+ void (*idle_task)( void );
+ boolean do_zero_of_workspace;
+ uint32_t idle_task_stack_size;
+ uint32_t interrupt_stack_size;
+ uint32_t extra_mpci_receive_server_stack;
+ void * (*stack_allocate_hook)( uint32_t );
+ void (*stack_free_hook)( void* );
+ /* end of fields required on all CPUs */
+
+} rtems_cpu_table;
+
+/*
+ * Macros to access required entires in the CPU Table are in
+ * the file rtems/system.h.
+ */
+
+/*
+ * Macros to access ARM specific additions to the CPU Table
+ *
+ * none required
+ */
+
+/* There are no CPU specific additions to the CPU Table for this port. */
+
+/*
+ * This variable is optional. It is used on CPUs on which it is difficult
+ * to generate an "uninitialized" FP context. It is filled in by
+ * _CPU_Initialize and copied into the task's FP context area during
+ * _CPU_Context_Initialize.
+ */
+
+SCORE_EXTERN Context_Control_fp _CPU_Null_fp_context;
+
+/*
+ * The size of the floating point context area. On some CPUs this
+ * will not be a "sizeof" because the format of the floating point
+ * area is not defined -- only the size is. This is usually on
+ * CPUs with a "floating point save context" instruction.
+ */
+
+#define CPU_CONTEXT_FP_SIZE sizeof( Context_Control_fp )
+
+/*
+ * Amount of extra stack (above minimum stack size) required by
+ * MPCI receive server thread. Remember that in a multiprocessor
+ * system this thread must exist and be able to process all directives.
+ */
+
+#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 0
+
+/*
+ * This defines the number of entries in the ISR_Vector_table managed
+ * by RTEMS.
+ */
+
+#define CPU_INTERRUPT_NUMBER_OF_VECTORS 8
+#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1)
+
+/*
+ * This is defined if the port has a special way to report the ISR nesting
+ * level. Most ports maintain the variable _ISR_Nest_level.
+ */
+
+#define CPU_PROVIDES_ISR_IS_IN_PROGRESS FALSE
+
+/*
+ * Should be large enough to run all RTEMS tests. This insures
+ * that a "reasonable" small application should not have any problems.
+ */
+
+#define CPU_STACK_MINIMUM_SIZE (1024*4)
+
+/*
+ * CPU's worst alignment requirement for data types on a byte boundary. This
+ * alignment does not take into account the requirements for the stack.
+ */
+
+#define CPU_ALIGNMENT 4
+
+/*
+ * This number corresponds to the byte alignment requirement for the
+ * heap handler. This alignment requirement may be stricter than that
+ * for the data types alignment specified by CPU_ALIGNMENT. It is
+ * common for the heap to follow the same alignment requirement as
+ * CPU_ALIGNMENT. If the CPU_ALIGNMENT is strict enough for the heap,
+ * then this should be set to CPU_ALIGNMENT.
+ *
+ * NOTE: This does not have to be a power of 2. It does have to
+ * be greater or equal to than CPU_ALIGNMENT.
+ */
+
+#define CPU_HEAP_ALIGNMENT CPU_ALIGNMENT
+
+/*
+ * This number corresponds to the byte alignment requirement for memory
+ * buffers allocated by the partition manager. This alignment requirement
+ * may be stricter than that for the data types alignment specified by
+ * CPU_ALIGNMENT. It is common for the partition to follow the same
+ * alignment requirement as CPU_ALIGNMENT. If the CPU_ALIGNMENT is strict
+ * enough for the partition, then this should be set to CPU_ALIGNMENT.
+ *
+ * NOTE: This does not have to be a power of 2. It does have to
+ * be greater or equal to than CPU_ALIGNMENT.
+ */
+
+#define CPU_PARTITION_ALIGNMENT CPU_ALIGNMENT
+
+/*
+ * This number corresponds to the byte alignment requirement for the
+ * stack. This alignment requirement may be stricter than that for the
+ * data types alignment specified by CPU_ALIGNMENT. If the CPU_ALIGNMENT
+ * is strict enough for the stack, then this should be set to 0.
+ *
+ * NOTE: This must be a power of 2 either 0 or greater than CPU_ALIGNMENT.
+ */
+
+#define CPU_STACK_ALIGNMENT 4
+
+/* ISR handler macros */
+
+/*
+ * Support routine to initialize the RTEMS vector table after it is allocated.
+ */
+
+#define _CPU_Initialize_vectors()
+
+/*
+ * Disable all interrupts for an RTEMS critical section. The previous
+ * level is returned in _level.
+ */
+
+#define _CPU_ISR_Disable( _level ) \
+ { \
+ int reg; \
+ asm volatile ("MRS %0, cpsr \n" \
+ "ORR %1, %0, #0xc0 \n" \
+ "MSR cpsr, %1 \n" \
+ : "=&r" (_level), "=&r" (reg)); \
+ }
+
+/*
+ * Enable interrupts to the previous level (returned by _CPU_ISR_Disable).
+ * This indicates the end of an RTEMS critical section. The parameter
+ * _level is not modified.
+ */
+
+#define _CPU_ISR_Enable( _level ) \
+ { \
+ asm volatile ("MSR cpsr, %0 \n" \
+ : : "r" (_level)); \
+ }
+
+/*
+ * This temporarily restores the interrupt to _level before immediately
+ * disabling them again. This is used to divide long RTEMS critical
+ * sections into two or more parts. The parameter _level is not
+ * modified.
+ */
+
+#define _CPU_ISR_Flash( _level ) \
+ { \
+ int reg; \
+ asm volatile ("MRS %0, cpsr \n" \
+ "MSR cpsr, %1 \n" \
+ "MSR cpsr, %0 \n" \
+ : "=&r" (reg) \
+ : "r" (_level)); \
+ }
+
+/*
+ * Map interrupt level in task mode onto the hardware that the CPU
+ * actually provides. Currently, interrupt levels which do not
+ * map onto the CPU in a generic fashion are undefined. Someday,
+ * it would be nice if these were "mapped" by the application
+ * via a callout. For example, m68k has 8 levels 0 - 7, levels
+ * 8 - 255 would be available for bsp/application specific meaning.
+ * This could be used to manage a programmable interrupt controller
+ * via the rtems_task_mode directive.
+ *
+ * The get routine usually must be implemented as a subroutine.
+ */
+
+#define _CPU_ISR_Set_level( new_level ) \
+ { \
+ int reg = 0; /* to avoid warning */ \
+ asm volatile ("MRS %0, cpsr \n" \
+ "BIC %0, %0, #0xc0 \n" \
+ "ORR %0, %0, %2 \n" \
+ "MSR cpsr_c, %0 \n" \
+ : "=r" (reg) \
+ : "r" (reg), "0" (reg)); \
+ }
+
+
+uint32_t _CPU_ISR_Get_level( void );
+
+/* end of ISR handler macros */
+
+/* Context handler macros */
+
+/*
+ * Initialize the context to a state suitable for starting a
+ * task after a context restore operation. Generally, this
+ * involves:
+ *
+ * - setting a starting address
+ * - preparing the stack
+ * - preparing the stack and frame pointers
+ * - setting the proper interrupt level in the context
+ * - initializing the floating point context
+ *
+ * This routine generally does not set any unnecessary register
+ * in the context. The state of the "general data" registers is
+ * undefined at task start time.
+ *
+ * NOTE: This is_fp parameter is TRUE if the thread is to be a floating
+ * point thread. This is typically only used on CPUs where the
+ * FPU may be easily disabled by software such as on the SPARC
+ * where the PSR contains an enable FPU bit.
+ */
+
+void _CPU_Context_Initialize(
+ Context_Control *the_context,
+ uint32_t *stack_base,
+ uint32_t size,
+ uint32_t new_level,
+ void *entry_point,
+ boolean is_fp
+);
+
+/*
+ * This routine is responsible for somehow restarting the currently
+ * executing task. If you are lucky, then all that is necessary
+ * is restoring the context. Otherwise, there will need to be
+ * a special assembly routine which does something special in this
+ * case. Context_Restore should work most of the time. It will
+ * not work if restarting self conflicts with the stack frame
+ * assumptions of restoring a context.
+ */
+
+#define _CPU_Context_Restart_self( _the_context ) \
+ _CPU_Context_restore( (_the_context) );
+
+/*
+ * The purpose of this macro is to allow the initial pointer into
+ * a floating point context area (used to save the floating point
+ * context) to be at an arbitrary place in the floating point
+ * context area.
+ *
+ * This is necessary because some FP units are designed to have
+ * their context saved as a stack which grows into lower addresses.
+ * Other FP units can be saved by simply moving registers into offsets
+ * from the base of the context area. Finally some FP units provide
+ * a "dump context" instruction which could fill in from high to low
+ * or low to high based on the whim of the CPU designers.
+ */
+
+#define _CPU_Context_Fp_start( _base, _offset ) \
+ ( (void *) _Addresses_Add_offset( (_base), (_offset) ) )
+
+/*
+ * This routine initializes the FP context area passed to it to.
+ * There are a few standard ways in which to initialize the
+ * floating point context. The code included for this macro assumes
+ * that this is a CPU in which a "initial" FP context was saved into
+ * _CPU_Null_fp_context and it simply copies it to the destination
+ * context passed to it.
+ *
+ * Other models include (1) not doing anything, and (2) putting
+ * a "null FP status word" in the correct place in the FP context.
+ */
+
+#define _CPU_Context_Initialize_fp( _destination ) \
+ { \
+ *((Context_Control_fp *) *((void **) _destination)) = _CPU_Null_fp_context; \
+ }
+
+/* end of Context handler macros */
+
+/* Fatal Error manager macros */
+
+/*
+ * This routine copies _error into a known place -- typically a stack
+ * location or a register, optionally disables interrupts, and
+ * halts/stops the CPU.
+ */
+
+#define _CPU_Fatal_halt( _error ) \
+ do { \
+ int _level; \
+ _CPU_ISR_Disable( _level ); \
+ asm volatile ("mov r0, %0\n" \
+ : "=r" (_error) \
+ : "0" (_error) \
+ : "r0" ); \
+ while(1) ; \
+ } while(0);
+
+
+/* end of Fatal Error manager macros */
+
+/* Bitfield handler macros */
+
+/*
+ * This routine sets _output to the bit number of the first bit
+ * set in _value. _value is of CPU dependent type Priority_Bit_map_control.
+ * This type may be either 16 or 32 bits wide although only the 16
+ * least significant bits will be used.
+ *
+ * There are a number of variables in using a "find first bit" type
+ * instruction.
+ *
+ * (1) What happens when run on a value of zero?
+ * (2) Bits may be numbered from MSB to LSB or vice-versa.
+ * (3) The numbering may be zero or one based.
+ * (4) The "find first bit" instruction may search from MSB or LSB.
+ *
+ * RTEMS guarantees that (1) will never happen so it is not a concern.
+ * (2),(3), (4) are handled by the macros _CPU_Priority_mask() and
+ * _CPU_Priority_bits_index(). These three form a set of routines
+ * which must logically operate together. Bits in the _value are
+ * set and cleared based on masks built by _CPU_Priority_mask().
+ * The basic major and minor values calculated by _Priority_Major()
+ * and _Priority_Minor() are "massaged" by _CPU_Priority_bits_index()
+ * to properly range between the values returned by the "find first bit"
+ * instruction. This makes it possible for _Priority_Get_highest() to
+ * calculate the major and directly index into the minor table.
+ * This mapping is necessary to ensure that 0 (a high priority major/minor)
+ * is the first bit found.
+ *
+ * This entire "find first bit" and mapping process depends heavily
+ * on the manner in which a priority is broken into a major and minor
+ * components with the major being the 4 MSB of a priority and minor
+ * the 4 LSB. Thus (0 << 4) + 0 corresponds to priority 0 -- the highest
+ * priority. And (15 << 4) + 14 corresponds to priority 254 -- the next
+ * to the lowest priority.
+ *
+ * If your CPU does not have a "find first bit" instruction, then
+ * there are ways to make do without it. Here are a handful of ways
+ * to implement this in software:
+ *
+ * - a series of 16 bit test instructions
+ * - a "binary search using if's"
+ * - _number = 0
+ * if _value > 0x00ff
+ * _value >>=8
+ * _number = 8;
+ *
+ * if _value > 0x0000f
+ * _value >=8
+ * _number += 4
+ *
+ * _number += bit_set_table[ _value ]
+ *
+ * where bit_set_table[ 16 ] has values which indicate the first
+ * bit set
+ */
+#if (ARM_HAS_CLZ == 0)
+# define CPU_USE_GENERIC_BITFIELD_CODE TRUE
+# define CPU_USE_GENERIC_BITFIELD_DATA TRUE
+#else
+# define CPU_USE_GENERIC_BITFIELD_CODE FALSE
+# define CPU_USE_GENERIC_BITFIELD_DATA FALSE
+
+# define _CPU_Bitfield_Find_first_bit( _value, _output ) \
+ { \
+ (_output) = 0; /* do something to prevent warnings */ \
+ }
+
+/* end of Bitfield handler macros */
+
+/*
+ * This routine builds the mask which corresponds to the bit fields
+ * as searched by _CPU_Bitfield_Find_first_bit(). See the discussion
+ * for that routine.
+ */
+
+
+# define _CPU_Priority_Mask( _bit_number ) \
+ ( 1 << (_bit_number) )
+
+
+/*
+ * This routine translates the bit numbers returned by
+ * _CPU_Bitfield_Find_first_bit() into something suitable for use as
+ * a major or minor component of a priority. See the discussion
+ * for that routine.
+ */
+
+
+# define _CPU_Priority_bits_index( _priority ) \
+ (_priority)
+
+# error "Implement CLZ version of priority bit functions for ARMv5"
+#endif
+
+/* end of Priority handler macros */
+
+/* functions */
+
+/*
+ * _CPU_Initialize
+ *
+ * This routine performs CPU dependent initialization.
+ */
+
+void _CPU_Initialize(
+ rtems_cpu_table *cpu_table,
+ void (*thread_dispatch)
+);
+
+typedef enum {
+ ARM_EXCEPTION_RESET = 0,
+ ARM_EXCEPTION_UNDEF = 1,
+ ARM_EXCEPTION_SWI = 2,
+ ARM_EXCEPTION_PREF_ABORT = 3,
+ ARM_EXCEPTION_DATA_ABORT = 4,
+ ARM_EXCEPTION_RESERVED = 5,
+ ARM_EXCEPTION_IRQ = 6,
+ ARM_EXCEPTION_FIQ = 7,
+ MAX_EXCEPTIONS = 8
+} Arm_symbolic_exception_name;
+
+/*
+ * _CPU_ISR_install_vector
+ *
+ * This routine installs an interrupt vector.
+ */
+
+void _CPU_ISR_install_vector(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+);
+
+/*
+ * _CPU_Install_interrupt_stack
+ *
+ * This routine installs the hardware interrupt stack pointer.
+ *
+ * NOTE: It need only be provided if CPU_HAS_HARDWARE_INTERRUPT_STACK
+ * is TRUE.
+ */
+
+void _CPU_Install_interrupt_stack( void );
+
+/*
+ * _CPU_Context_switch
+ *
+ * This routine switches from the run context to the heir context.
+ */
+
+void _CPU_Context_switch(
+ Context_Control *run,
+ Context_Control *heir
+);
+
+/*
+ * _CPU_Context_restore
+ *
+ * This routine is generally used only to restart self in an
+ * efficient manner. It may simply be a label in _CPU_Context_switch.
+ *
+ * NOTE: May be unnecessary to reload some registers.
+ */
+
+void _CPU_Context_restore(
+ Context_Control *new_context
+);
+
+#if (ARM_HAS_FPU == 1)
+/*
+ * _CPU_Context_save_fp
+ *
+ * This routine saves the floating point context passed to it.
+ */
+
+void _CPU_Context_save_fp(
+ void **fp_context_ptr
+);
+
+/*
+ * _CPU_Context_restore_fp
+ *
+ * This routine restores the floating point context passed to it.
+ */
+
+void _CPU_Context_restore_fp(
+ void **fp_context_ptr
+);
+#endif /* (ARM_HAS_FPU == 1) */
+
+/* The following routine swaps the endian format of an unsigned int.
+ * It must be static because it is referenced indirectly.
+ *
+ * This version will work on any processor, but if there is a better
+ * way for your CPU PLEASE use it. The most common way to do this is to:
+ *
+ * swap least significant two bytes with 16-bit rotate
+ * swap upper and lower 16-bits
+ * swap most significant two bytes with 16-bit rotate
+ *
+ * Some CPUs have special instructions which swap a 32-bit quantity in
+ * a single instruction (e.g. i486). It is probably best to avoid
+ * an "endian swapping control bit" in the CPU. One good reason is
+ * that interrupts would probably have to be disabled to insure that
+ * an interrupt does not try to access the same "chunk" with the wrong
+ * endian. Another good reason is that on some CPUs, the endian bit
+ * endianness for ALL fetches -- both code and data -- so the code
+ * will be fetched incorrectly.
+ */
+
+static inline unsigned int CPU_swap_u32(
+ unsigned int value
+)
+{
+ uint32_t tmp = value; /* make compiler warnings go away */
+ asm volatile ("EOR %1, %0, %0, ROR #16\n"
+ "BIC %1, %1, #0xff0000\n"
+ "MOV %0, %0, ROR #8\n"
+ "EOR %0, %0, %1, LSR #8\n"
+ : "=r" (value), "=r" (tmp)
+ : "0" (value), "1" (tmp));
+
+ return value;
+}
+
+static inline uint16_t CPU_swap_u16(uint16_t value)
+{
+ uint16_t lower;
+ uint16_t upper;
+
+ value = value & (uint16_t ) 0xffff;
+ lower = (value >> 8) ;
+ upper = (value << 8) ;
+
+ return (lower | upper);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/score/cpu/arm/rtems/score/cpu_asm.h b/cpukit/score/cpu/arm/rtems/score/cpu_asm.h
new file mode 100644
index 0000000000..2c843ac421
--- /dev/null
+++ b/cpukit/score/cpu/arm/rtems/score/cpu_asm.h
@@ -0,0 +1,35 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2002 by Advent Networks, Inc.
+ * Jay Monkman <jmonkman@adventnetworks.com>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * This file is the include file for cpu_asm.S
+ *
+ *
+ */
+
+#ifndef __CPU_ASM_h
+#define __CPU_ASM_h
+
+
+/* Registers saved in context switch: */
+.set REG_CPSR, 0
+.set REG_R4, 4
+.set REG_R5, 8
+.set REG_R6, 12
+.set REG_R7, 16
+.set REG_R8, 20
+.set REG_R9, 24
+.set REG_R10, 28
+.set REG_R11, 32
+.set REG_SP, 36
+.set REG_LR, 40
+.set REG_PC, 44
+.set SIZE_REGS, REG_PC + 4
+
+#endif
diff --git a/cpukit/score/cpu/arm/rtems/score/types.h b/cpukit/score/cpu/arm/rtems/score/types.h
new file mode 100644
index 0000000000..4568a3c911
--- /dev/null
+++ b/cpukit/score/cpu/arm/rtems/score/types.h
@@ -0,0 +1,55 @@
+/*
+ * $Id$
+ *
+ * This include file contains type definitions pertaining to the
+ * arm processor family.
+ *
+ * COPYRIGHT (c) 2000 Canon Research Centre France SA.
+ * Emmanuel Raguet, mailto:raguet@crf.canon.fr
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ */
+
+#ifndef __ARM_TYPES_h
+#define __ARM_TYPES_h
+
+#ifndef ASM
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This section defines the basic types for this processor.
+ */
+
+typedef unsigned char unsigned8; /* unsigned 8-bit integer */
+typedef unsigned short unsigned16; /* unsigned 16-bit integer */
+typedef unsigned int unsigned32; /* unsigned 32-bit integer */
+typedef unsigned long long unsigned64; /* unsigned 64-bit integer */
+
+typedef signed char signed8; /* 8-bit signed integer */
+typedef signed short signed16; /* 16-bit signed integer */
+typedef signed int signed32; /* 32-bit signed integer */
+typedef signed long long signed64; /* 64 bit signed integer */
+
+typedef unsigned32 boolean; /* Boolean value */
+typedef unsigned16 Priority_Bit_map_control;
+
+typedef float single_precision; /* single precision float */
+typedef double double_precision; /* double precision float */
+
+typedef void arm_cpu_isr;
+typedef void ( *arm_cpu_isr_entry )( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !ASM */
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/c4x/.cvsignore b/cpukit/score/cpu/c4x/.cvsignore
new file mode 100644
index 0000000000..282522db03
--- /dev/null
+++ b/cpukit/score/cpu/c4x/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/cpukit/score/cpu/c4x/ChangeLog b/cpukit/score/cpu/c4x/ChangeLog
new file mode 100644
index 0000000000..9b10463e6d
--- /dev/null
+++ b/cpukit/score/cpu/c4x/ChangeLog
@@ -0,0 +1,262 @@
+2004-04-06 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * configure.ac: Remove (Merged into $(top_srcdir)/configure.ac).
+ * Makefile.am: Don't include multilib.am.
+ Reflect merging configure.ac into $(top_srcdir)/configure.ac.
+
+2004-04-02 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * Makefile.am: Install c4xio.h to $(includedir)/rtems/c4x.
+
+2004-04-01 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * Makefile.am: Install asm.h to $(includedir)/rtems.
+
+2004-04-01 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * cpu_asm.S: Include <rtems/asm.h> instead of <asm.h>.
+
+2004-03-30 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * c4xio.h, cpu.c, irq.c, rtems/score/cpu.h: Convert to using c99
+ fixed size types.
+
+2004-03-29 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * configure.ac: RTEMS_TOP([../../../..]).
+
+2004-01-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Move RTEMS_TOP one subdir down.
+
+2004-01-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add PREINSTALL_DIRS.
+
+2004-01-14 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Re-add dirstamps to PREINSTALL_FILES.
+ Add PREINSTALL_FILES to CLEANFILES.
+
+2004-01-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Requires automake >= 1.8.1.
+
+2004-01-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include compile.am, again.
+
+2004-01-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Convert to using automake compilation rules.
+
+2003-12-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use mkdir_p. Remove dirs from PREINSTALL_FILES.
+
+2003-12-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Require automake >= 1.8, autoconf >= 2.59.
+
+2003-12-01 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Remove TMPINSTALL_FILES.
+
+2003-11-30 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add $(dirstamp) to preinstallation rules.
+
+2003-11-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Don't use gmake rules for preinstallation.
+
+2003-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_CANONICAL_HOST.
+
+2003-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_CHECK_CPU.
+
+2003-09-26 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/cpu.h: Obsoleting HP PA-RISC port and removing all
+ references.
+
+2003-09-04 Joel Sherrill <joel@OARcorp.com>
+
+ * cpu.c, cpu_asm.S, irq.c, rtems/score/c4x.h, rtems/score/cpu.h,
+ rtems/score/cpu_asm.h, rtems/score/types.h: URL for license changed.
+
+2003-08-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use rtems-bugs@rtems.com as bug report email address.
+
+2003-03-06 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove AC_CONFIG_AUX_DIR.
+
+2003-02-11 Joel Sherrill <joel@OARcorp.com>
+
+ * irq.c: Rework logic that decides when to call
+ _Thread_Dispatch. Analysis by Sergei Organov <osv@javad.ru>
+ determined that _ISR_Signals_to_thread_executing was not being
+ honored and/or cleared properly.
+
+2002-12-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Require autoconf-2.57 + automake-1.7.2.
+ * Makefile.am: Eliminate C_O_FILES, S_O_FILES, libscorecpu_a_OBJECTS.
+
+2002-11-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Fix package name.
+
+2002-10-25 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Add nostdinc to AM_INIT_AUTOMAKE.
+
+2002-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * .cvsignore: Reformat.
+ Add autom4te*cache.
+ Remove autom4te.cache.
+
+2002-07-26 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Build libscorecpu.a instead of rtems-cpu.rel.
+
+2002-07-22 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use .$(OBJEXT) instead of .o.
+
+2002-07-22 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use . instead of .o.
+
+2002-07-05 Joel Sherrill <joel@OARcorp.com>
+
+ * cpu.c, irq.c, rtems/score/cpu.h: Filled in something that was
+ marked XXX.
+
+2002-07-05 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: RTEMS_TOP(../../../..).
+
+2002-07-03 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems.c: Remove.
+ * Makefile.am: Reflect changes above.
+
+2002-07-01 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_PROJECT_ROOT.
+
+2002-06-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Add RTEMS_PROG_CCAS
+
+2002-06-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use AC_CONFIG_AUX_DIR(../../../..).
+ Add AC_PROG_RANLIB.
+
+2002-06-17 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include $(top_srcdir)/../../../automake/*.am.
+ Use ../../../aclocal.
+
+2001-04-03 Joel Sherrill <joel@OARcorp.com>
+
+ * Per PR94, all rtems/score/CPUtypes.h are named rtems/score/types.h.
+ * rtems/score/c4xtypes.h: Removed.
+ * rtems/score/types.h: New file via CVS magic.
+ * Makefile.am, rtems/score/cpu.h: Account for name change.
+
+2002-03-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac:
+ AC_INIT(package,_RTEMS_VERSION,_RTEMS_BUGS).
+ AM_INIT_AUTOMAKE([no-define foreign 1.6]).
+ * Makefile.am: Remove AUTOMAKE_OPTIONS.
+
+2002-01-29 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/Makefile.am: Removed.
+ * rtems/score/Makefile.am: Removed.
+ * configure.ac: Reflect changes above.
+ * Makefile.am: Reflect changes above.
+
+2002-02-09 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * asm.h: Remove #include <rtems/score/targopts.h>.
+ Add #include <rtems/score/cpuopts.h>.
+
+
+
+2002-02-05 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_CHECK_CUSTOM_BSP.
+
+2001-12-20 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use RTEMS_ENV_RTEMSCPU.
+
+2001-12-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add multilib support.
+
+2001-11-28 Joel Sherrill <joel@OARcorp.com>,
+
+ This was tracked as PR91.
+ * rtems/score/cpu.h: Added CPU_PROVIDES_ISR_IS_IN_PROGRESS macro which
+ is used to specify if the port uses the standard macro for this (FALSE).
+ A TRUE setting indicates the port provides its own implementation.
+
+2001-10-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * .cvsignore: Add autom4te.cache for autoconf > 2.52.
+ * configure.in: Remove.
+ * configure.ac: New file, generated from configure.in by autoupdate.
+
+2001-09-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/score/Makefile.am: Use 'PREINSTALL_FILES ='.
+ * Makefile.am: Use 'PREINSTALL_FILES ='.
+
+2001-02-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am, rtems/score/Makefile.am:
+ Apply include_*HEADERS instead of H_FILES.
+
+2001-01-03 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/cpu.h: Added _CPU_Initialize_vectors().
+
+2000-11-09 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use ... instead of RTEMS_TOPdir in ACLOCAL_AMFLAGS.
+
+2000-11-02 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Switch to ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal.
+
+2000-10-25 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: ACLOCAL_AMFLAGS= -I $(RTEMS_TOPdir)/macros.
+ Switch to GNU canonicalization.
+
+2000-10-18 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/c4x.h: Modified to properly multilib. This required
+ using only macros predefined by gcc.
+
+2000-09-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include compile.am, formatting.
+ * rtems/Makefile.am: formatting.
+ * rtems/score/Makefile.am: formatting.
+
+2000-08-10 Joel Sherrill <joel@OARcorp.com>
+
+ * ChangeLog: New file.
diff --git a/cpukit/score/cpu/c4x/Makefile.am b/cpukit/score/cpu/c4x/Makefile.am
new file mode 100644
index 0000000000..24378adb05
--- /dev/null
+++ b/cpukit/score/cpu/c4x/Makefile.am
@@ -0,0 +1,74 @@
+##
+## $Id$
+##
+
+include $(top_srcdir)/automake/compile.am
+
+include_rtemsdir = $(includedir)/rtems
+include_rtems_HEADERS = asm.h
+
+include_rtems_c4xdir = $(includedir)/rtems/c4x
+include_rtems_c4x_HEADERS = c4xio.h
+
+include_rtems_scoredir = $(includedir)/rtems/score
+include_rtems_score_HEADERS = rtems/score/cpu.h rtems/score/c4x.h \
+ rtems/score/types.h rtems/score/cpu_asm.h
+
+EXTRA_LIBRARIES = libscorecpu.a
+CLEANFILES = libscorecpu.a
+libscorecpu_a_SOURCES = cpu.c irq.c cpu_asm.S
+libscorecpu_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libscorecpu_g.a
+CLEANFILES += libscorecpu_g.a
+libscorecpu_g_a_SOURCES = $(libscorecpu_a_SOURCES)
+libscorecpu_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+all-local: $(PREINSTALL_FILES) libscorecpu$(LIB_VARIANT).a
+
+PREINSTALL_DIRS =
+PREINSTALL_FILES =
+
+$(PROJECT_INCLUDE)/rtems/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems
+ @: > $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/asm.h: asm.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/asm.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/asm.h
+
+$(PROJECT_INCLUDE)/rtems/c4x/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems/c4x
+ @: > $(PROJECT_INCLUDE)/rtems/c4x/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/c4x/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/c4x/c4xio.h: c4xio.h $(PROJECT_INCLUDE)/rtems/c4x/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/c4x/c4xio.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/c4x/c4xio.h
+
+$(PROJECT_INCLUDE)/rtems/score/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems/score
+ @: > $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/score/cpu.h: rtems/score/cpu.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/cpu.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/cpu.h
+
+$(PROJECT_INCLUDE)/rtems/score/c4x.h: rtems/score/c4x.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/c4x.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/c4x.h
+
+$(PROJECT_INCLUDE)/rtems/score/types.h: rtems/score/types.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/types.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/types.h
+
+$(PROJECT_INCLUDE)/rtems/score/cpu_asm.h: rtems/score/cpu_asm.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/cpu_asm.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/cpu_asm.h
+
+CLEANFILES += $(PREINSTALL_FILES)
+DISTCLEANFILES = $(PREINSTALL_DIRS)
+
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/score/cpu/c4x/asm.h b/cpukit/score/cpu/c4x/asm.h
new file mode 100644
index 0000000000..a63abf2784
--- /dev/null
+++ b/cpukit/score/cpu/c4x/asm.h
@@ -0,0 +1,99 @@
+/* asm.h
+ *
+ * This include file attempts to address the problems
+ * caused by incompatible flavors of assemblers and
+ * toolsets. It primarily addresses variations in the
+ * use of leading underscores on symbols and the requirement
+ * that register names be preceded by a %.
+ *
+ *
+ * NOTE: The spacing in the use of these macros
+ * is critical to them working as advertised.
+ *
+ * COPYRIGHT:
+ *
+ * This file is based on similar code found in newlib available
+ * from ftp.cygnus.com. The file which was used had no copyright
+ * notice. This file is freely distributable as long as the source
+ * of the file is noted. This file is:
+ *
+ * COPYRIGHT (c) 1994-1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * $Id$
+ */
+
+#ifndef __C4X_ASM_h
+#define __C4X_ASM_h
+
+/*
+ * Indicate we are in an assembly file and get the basic CPU definitions.
+ */
+
+#ifndef ASM
+#define ASM
+#endif
+#include <rtems/score/cpuopts.h>
+#include <rtems/score/c4x.h>
+
+/*
+ * Recent versions of GNU cpp define variables which indicate the
+ * need for underscores and percents. If not using GNU cpp or
+ * the version does not support this, then you will obviously
+ * have to define these as appropriate.
+ */
+
+#ifndef __USER_LABEL_PREFIX__
+#define __USER_LABEL_PREFIX__ _
+#endif
+
+#ifndef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__
+#endif
+
+/* ANSI concatenation macros. */
+
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+/* Use the right prefix for global labels. */
+
+#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+
+/* Use the right prefix for registers. */
+
+#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
+
+/*
+ * define macros for all of the registers on this CPU
+ *
+ * EXAMPLE: #define d0 REG (d0)
+ */
+
+/*
+ * Define macros to handle section beginning and ends.
+ */
+
+
+#define BEGIN_CODE_DCL .text
+#define END_CODE_DCL
+#define BEGIN_DATA_DCL .data
+#define END_DATA_DCL
+#define BEGIN_CODE .text
+#define END_CODE
+#define BEGIN_DATA
+#define END_DATA
+#define BEGIN_BSS
+#define END_BSS
+#define END
+
+/*
+ * Following must be tailor for a particular flavor of the C compiler.
+ * They may need to put underscores in front of the symbols.
+ */
+
+#define PUBLIC(sym) .globl SYM (sym)
+#define EXTERN(sym) .globl SYM (sym)
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/c4x/c4xio.h b/cpukit/score/cpu/c4x/c4xio.h
new file mode 100644
index 0000000000..d398211dfb
--- /dev/null
+++ b/cpukit/score/cpu/c4x/c4xio.h
@@ -0,0 +1,110 @@
+/*
+ * C4X IO Information
+ *
+ * $Id$
+ */
+
+#ifndef __C4XIO_h
+#define __C4XIO_h
+
+/*
+ * Address defines
+ */
+
+#ifdef _TMS320C40
+#define C4X_TIMER_0 ((struct c4x_timer*)0x100020)
+#else
+#define C4X_TIMER_0 ((struct c4x_timer*)0x808020)
+#define C4X_TIMER_1 ((struct c4x_timer*)0x808030)
+#endif
+
+/* XXX how portable */
+
+/* C32 Internal Control Registers */
+#define C4X_STRB0_REG 0x808064
+#define C4X_STRB1_REG 0x808068
+#define C4X_IOSTRB_REG 0x808060
+
+/* C32 Internal RAM Locations */
+/* XXX how long */
+#define C4X_RAM_BLK_0 0x87fe00
+#define C4X_RAM_BLK_1 0x87ff00
+
+/*
+ * Data Structures to Overlay the Peripherals on the CPU
+ */
+
+struct c4x_timer {
+ volatile int tcontrol;
+ volatile int r1[3];
+ volatile int tcounter;
+ volatile int r2[3];
+ volatile int tperiod;
+};
+
+
+
+
+/*
+ * Timer Support Routines
+ *
+ * The following section of C4x timer code is based on C40 specific
+ * timer code from Ran Cabell <rcabell@norfolk.infi.net>. The
+ * only C3x/C4x difference spotted was the address of the timer.
+ * The names have been changed to be more RTEMS like.
+ */
+
+#define c4x_timer_get_control( _timer ) (volatile int)(_timer->tcontrol)
+
+#define c4x_timer_set_control( _timer, _value ) \
+ do { \
+ (volatile int)(_timer->tcontrol) = _value; \
+ } while (0);
+
+#define c4x_timer_start( _timer ) \
+ c4x_timer_set_control(_timer, 0x02c1 )
+
+#define c4x_timer_stop( _timer ) _timer->tcontrol = 0
+
+#define c4x_timer_get_counter( _timer ) (volatile int)(_timer->tcounter)
+
+#define c4x_timer_set_counter( _timer, _value ) \
+ do { \
+ (volatile int)(_timer->tcounter) = _value; \
+ } while (0);
+
+#define c4x_timer_get_period( _timer ) (volatile int)(_timer->tperiod)
+
+#define c4x_timer_set_period( _timer, _value ) \
+ do { \
+ (volatile int)(_timer->tperiod) = _value; \
+ } while (0);
+
+/*
+ * IO Flags
+ *
+ * NOTE: iof on c3x, iiof on c4x
+ */
+
+#ifdef _TMS320C40
+
+#else
+
+static inline uint32_t c3x_get_iof( void )
+{
+ register uint32_t iof_value;
+
+ __asm__ volatile ("ldi iof, %0" : "=r" (iof_value));
+ return iof_value;
+}
+
+static inline void c3x_set_iof( uint32_t value )
+{
+ __asm__ volatile ("ldi %0,iof" : : "g" (value) : "iof", "cc");
+}
+
+#endif
+
+
+#endif
+/* end if include file */
diff --git a/cpukit/score/cpu/c4x/cpu.c b/cpukit/score/cpu/c4x/cpu.c
new file mode 100644
index 0000000000..b9655b642f
--- /dev/null
+++ b/cpukit/score/cpu/c4x/cpu.c
@@ -0,0 +1,199 @@
+/*
+ * C4x CPU Dependent Source
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/wkspace.h>
+
+
+/* _CPU_Initialize
+ *
+ * This routine performs processor dependent initialization.
+ *
+ * INPUT PARAMETERS:
+ * cpu_table - CPU table to initialize
+ * thread_dispatch - address of disptaching routine
+ *
+ * C4x Specific Information:
+ *
+ */
+
+void _CPU_Initialize(
+ rtems_cpu_table *cpu_table,
+ void (*thread_dispatch) /* ignored on this CPU */
+)
+{
+#if 0
+ /*
+ * The thread_dispatch argument is the address of the entry point
+ * for the routine called at the end of an ISR once it has been
+ * decided a context switch is necessary. On some compilation
+ * systems it is difficult to call a high-level language routine
+ * from assembly. This allows us to trick these systems.
+ *
+ * If you encounter this problem save the entry point in a CPU
+ * dependent variable.
+ */
+
+ _CPU_Thread_dispatch_pointer = thread_dispatch;
+#endif
+
+#if (CPU_HARDWARE_FP == TRUE)
+ /*
+ * If there is not an easy way to initialize the FP context
+ * during Context_Initialize, then it is usually easier to
+ * save an "uninitialized" FP context here and copy it to
+ * the task's during Context_Initialize.
+ */
+
+ /* FP context initialization support goes here */
+#endif
+
+ _CPU_Table = *cpu_table;
+}
+
+/*PAGE
+ *
+ * _CPU_ISR_install_raw_handler
+ *
+ * C4x Specific Information:
+ *
+ */
+
+void _CPU_ISR_install_raw_handler(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+)
+{
+ void **ittp;
+
+ /*
+ * This is where we install the interrupt handler into the "raw" interrupt
+ * table used by the CPU to dispatch interrupt handlers.
+ */
+
+ ittp = c4x_get_ittp();
+ *old_handler = ittp[ vector ];
+ ittp[ vector ] = new_handler;
+}
+
+/*XXX */
+
+#define C4X_CACHE 1
+#define C4X_BASE_ST (C4X_CACHE==1) ? 0x4800 : 0x4000
+
+void _CPU_Context_Initialize(
+ Context_Control *_the_context,
+ void *_stack_base,
+ uint32_t _size,
+ uint32_t _isr,
+ void (*_entry_point)(void),
+ int _is_fp
+)
+{
+ unsigned int *_stack;
+ _stack = (unsigned int *)_stack_base;
+
+ *_stack = (unsigned int) _entry_point;
+ _the_context->sp = (unsigned int) _stack;
+ _the_context->st = C4X_BASE_ST;
+ if ( _isr == 0 )
+ _the_context->st |= C4X_ST_GIE;
+}
+
+/*PAGE
+ *
+ * _CPU_ISR_install_vector
+ *
+ * This kernel routine installs the RTEMS handler for the
+ * specified vector.
+ *
+ * Input parameters:
+ * vector - interrupt vector number
+ * old_handler - former ISR for this vector number
+ * new_handler - replacement ISR for this vector number
+ *
+ * Output parameters: NONE
+ *
+ *
+ * C4x Specific Information:
+ *
+ */
+
+void _CPU_ISR_install_vector(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+)
+{
+ proc_ptr ignored;
+ extern void rtems_irq_prologue_0(void);
+ extern void rtems_irq_prologue_1(void);
+ void *entry;
+
+ *old_handler = _ISR_Vector_table[ vector ];
+
+ /*
+ * If the interrupt vector table is a table of pointer to isr entry
+ * points, then we need to install the appropriate RTEMS interrupt
+ * handler for this vector number.
+ */
+
+ entry = (void *)rtems_irq_prologue_0 +
+ ((rtems_irq_prologue_1 - rtems_irq_prologue_0) * vector);
+ _CPU_ISR_install_raw_handler( vector, entry, &ignored );
+
+ /*
+ * We put the actual user ISR address in '_ISR_vector_table'. This will
+ * be used by the _ISR_Handler so the user gets control.
+ */
+
+ _ISR_Vector_table[ vector ] = new_handler;
+}
+
+/*PAGE
+ *
+ * _CPU_Thread_Idle_body
+ *
+ * NOTES:
+ *
+ * 1. This is the same as the regular CPU independent algorithm.
+ *
+ * 2. If you implement this using a "halt", "idle", or "shutdown"
+ * instruction, then don't forget to put it in an infinite loop.
+ *
+ * 3. Be warned. Some processors with onboard DMA have been known
+ * to stop the DMA if the CPU were put in IDLE mode. This might
+ * also be a problem with other on-chip peripherals. So use this
+ * hook with caution.
+ *
+ * C4x Specific Information:
+ *
+ *
+ */
+
+#if (CPU_PROVIDES_IDLE_THREAD_BODY == 1)
+void _CPU_Thread_Idle_body( void )
+{
+
+ for( ; ; ) {
+ __asm__( "idle" );
+ __asm__( "nop" );
+ __asm__( "nop" );
+ __asm__( "nop" );
+ /* insert your "halt" instruction here */ ;
+ }
+}
+#endif
diff --git a/cpukit/score/cpu/c4x/cpu_asm.S b/cpukit/score/cpu/c4x/cpu_asm.S
new file mode 100644
index 0000000000..020c3a8d9e
--- /dev/null
+++ b/cpukit/score/cpu/c4x/cpu_asm.S
@@ -0,0 +1,769 @@
+/* cpu_asm.c ===> cpu_asm.S or cpu_asm.s
+ *
+ * This file contains the basic algorithms for all assembly code used
+ * in an specific CPU port of RTEMS. These algorithms must be implemented
+ * in assembly language
+ *
+ * NOTE: This is supposed to be a .S or .s file NOT a C file.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/asm.h>
+
+/*
+ * _CPU_Context_save_fp_context
+ *
+ * This routine is responsible for saving the FP context
+ * at *fp_context_ptr. If the point to load the FP context
+ * from is changed then the pointer is modified by this routine.
+ *
+ * Sometimes a macro implementation of this is in cpu.h which dereferences
+ * the ** and a similarly named routine in this file is passed something
+ * like a (Context_Control_fp *). The general rule on making this decision
+ * is to avoid writing assembly language.
+ *
+ * void _CPU_Context_save_fp(
+ * void **fp_context_ptr
+ *
+ * C4x Specific Information:
+ *
+ * There is no distiniction between FP and integer context in this port.
+ */
+
+/*
+ * _CPU_Context_restore_fp_context
+ *
+ * This routine is responsible for restoring the FP context
+ * at *fp_context_ptr. If the point to load the FP context
+ * from is changed then the pointer is modified by this routine.
+ *
+ * Sometimes a macro implementation of this is in cpu.h which dereferences
+ * the ** and a similarly named routine in this file is passed something
+ * like a (Context_Control_fp *). The general rule on making this decision
+ * is to avoid writing assembly language.
+ *
+ * void _CPU_Context_restore_fp(
+ * void **fp_context_ptr
+ * )
+ *
+ * C4x Specific Information:
+ *
+ * There is no distiniction between FP and integer context in this port.
+ */
+
+
+/* _CPU_Context_switch
+ *
+ * This routine performs a normal non-FP context switch.
+ *
+ * void _CPU_Context_switch(
+ * Context_Control *run,
+ * Context_Control *heir
+ * )
+ *
+ * TMS320C3x General-Purpose Applications User's Guide, section 2.4
+ * (p 2-11 and following), Context Switching in Interrupts and
+ * Subroutines states that "If the program is in a subroutine, it
+ * must preserve the dedicated C registers as follows:"
+ *
+ * Save as Integers Save as Floating-Point
+ * ================ ======================
+ * R4 R8 R6 R7
+ * AR4 AR5
+ * AR6 AR7
+ * FP DP (small model only)
+ * SP
+ */
+
+ .global SYM(_CPU_Context_switch)
+SYM(_CPU_Context_switch):
+ .if .REGPARM == 0
+ ldi sp, ar0
+ ldi *ar0, ar2 ; get the location of running context
+ .endif
+ sti st,*ar2++ ; store status word
+ sti ar3,*ar2++ ; store ar3
+ sti ar4,*ar2++ ; store ar4
+ sti ar5,*ar2++ ; store ar5
+ sti ar6,*ar2++ ; store ar6
+ sti ar7,*ar2++ ; store ar7
+ sti r4,*ar2++ ; store integer portion of r4
+ sti r5,*ar2++ ; store integer portion of r5
+ stf r6,*ar2++ ; store float portion of r6
+ stf r7,*ar2++ ; store float portion of r7
+ .if .TMS320C40
+ sti r8,*ar2++ ; store integer portion of r8
+ .endif
+ sti sp,*ar2++ ; store sp
+
+ ; end of save
+
+ .if .REGPARM == 0
+ ldi *-ar0(2), ar2 ; get the location of heir context
+ .else
+ ldi r2,ar2
+ .endif
+_local_restore:
+ ldi *ar2++,ar0 ; load status word into register
+ ldi *ar2++,ar3 ; load ar3
+ ldi *ar2++,ar4 ; load ar4
+ ldi *ar2++,ar5 ; load ar5
+ ldi *ar2++,ar6 ; load ar6
+ ldi *ar2++,ar7 ; load ar7
+ ldi *ar2++,r4 ; load integer portion of r4
+ ldi *ar2++,r5 ; load integer portion of r5
+ ldf *ar2++,r6 ; load float portion of r6
+ ldf *ar2++,r7 ; load float portion of r7
+ .if .TMS320C40
+ ldi *ar2++,r8 ; load integer portion of r8
+ .endif
+ ldi *ar2++,sp ; load sp
+ ldi ar0,st ; restore status word and interrupts
+ rets
+
+/*
+ * _CPU_Context_restore
+ *
+ * This routine is generally used only to restart self in an
+ * efficient manner. It may simply be a label in _CPU_Context_switch.
+ *
+ * NOTE: May be unnecessary to reload some registers.
+ *
+ * void _CPU_Context_restore(
+ * Context_Control *new_context
+ * )
+ */
+
+ .global SYM(_CPU_Context_restore)
+SYM(_CPU_Context_restore):
+ .if .REGPARM == 0
+ ldi sp, ar0
+ ldi *ar0, ar2 ; get the location of context to restore
+ .endif
+ br _local_restore
+
+/* void _ISR_Handler()
+ *
+ * This routine provides the RTEMS interrupt management.
+ *
+ * void _ISR_Handler()
+ */
+
+ /*
+ * At entry to "common" _ISR_Handler, the vector number must be
+ * available. On some CPUs the hardware puts either the vector
+ * number or the offset into the vector table for this ISR in a
+ * known place. If the hardware does not give us this information,
+ * then the assembly portion of RTEMS for this port will contain
+ * a set of distinct interrupt entry points which somehow place
+ * the vector number in a known place (which is safe if another
+ * interrupt nests this one) and branches to _ISR_Handler.
+ */
+
+ /*
+ * save some or all context on stack
+ * may need to save some special interrupt information for exit
+ *
+ * #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
+ * if ( _ISR_Nest_level == 0 )
+ * switch to software interrupt stack
+ * #endif
+ *
+ * _ISR_Nest_level++;
+ *
+ * _Thread_Dispatch_disable_level++;
+ *
+ * (*_ISR_Vector_table[ vector ])( vector );
+ *
+ * --_ISR_Nest_level;
+ *
+ * if ( _ISR_Nest_level )
+ * goto the label "exit interrupt (simple case)"
+ *
+ * #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
+ * restore stack
+ * #endif
+ *
+ * if ( !_Context_Switch_necessary )
+ * goto the label "exit interrupt (simple case)"
+ *
+ * if ( !_ISR_Signals_to_thread_executing )
+ * _ISR_Signals_to_thread_executing = FALSE;
+ * goto the label "exit interrupt (simple case)"
+ *
+ * call _Thread_Dispatch() or prepare to return to _ISR_Dispatch
+ *
+ * prepare to get out of interrupt
+ * return from interrupt (maybe to _ISR_Dispatch)
+ *
+ * LABEL "exit interrupt (simple case):
+ * prepare to get out of interrupt
+ * return from interrupt
+ */
+
+ .global SYM(_ISR_Handler_save_registers)
+SYM(_ISR_Handler_save_registers):
+ ; no push st because it is already pushed
+ ; no push ar2 because it is already pushed and vector number loaded
+ push ar0
+ push ar1
+ push dp
+ push ir0
+ push ir1
+ push rs
+ push re
+ push rc
+ push bk
+
+ push r0
+ pushf r0
+ push r1
+ pushf r1
+ push r2
+ pushf r2
+ push r3
+ pushf r3
+ ; no push r4 because other part of register is in basic context
+ push r4
+ pushf r4
+ ; no push r5 because other part of register is in basic context
+ push r5
+ pushf r5
+ push r6
+ pushf r6
+ ; no pushf r6 because other part of register is in basic context
+ push r7
+ pushf r7
+ ; no pushf r7 because other part of register is in basic context
+ .if .TMS320C40
+ push r8
+ ; no pushf r8 because other part of register is in basic context
+ push r9
+ pushf r9
+ push r10
+ pushf r10
+ push r11
+ pushf r11
+ .endif
+
+ ldi sp,r2
+ call SYM(__ISR_Handler)
+
+ .if .TMS320C40
+ popf r11
+ pop r11
+ popf r10
+ pop r10
+ popf r9
+ pop r9
+ ; no popf r8 because other part of register is in basic context
+ pop r8
+ .endif
+ ; no popf r7 because other part of register is in basic context
+ popf r7
+ pop r7
+ ; no popf r6 because other part of register is in basic context
+ popf r6
+ pop r6
+ ; no popf r5 because other part of register is in basic context
+ popf r5
+ pop r5
+ ; no pop r4 because other part of register is in basic context
+ popf r4
+ pop r4
+ popf r3
+ pop r3
+ popf r2
+ pop r2
+ popf r1
+ pop r1
+ popf r0
+ pop r0
+
+ pop bk
+ pop rc
+ pop re
+ pop rs
+ pop ir1
+ pop ir0
+ pop dp
+ pop ar1
+ pop ar0
+ pop ar2 ; because the vector numbers goes here
+ pop st
+ reti
+
+/*
+ * Prologues so we can know the vector number. Generated by this script:
+ *
+ * i=0
+ * while test $i -lt 64
+ * do
+ *
+ * printf "\t.global\tSYM(rtems_irq_prologue_%X)\n" $i
+ * printf "SYM(rtems_irq_prologue_%X):\n" $i
+ * printf "\tpush\tst\n"
+ * printf "\tpush\tar2\n"
+ * printf "\tldi\t0x%x,ar2\n" $i
+ * printf "\tbr\tSYM(_ISR_Handler_save_registers)\n"
+ * printf "\n"
+ * i=`expr $i + 1`
+ *
+ * done
+ */
+
+ .global SYM(rtems_irq_prologue_0)
+SYM(rtems_irq_prologue_0):
+ push st
+ push ar2
+ ldi 0x0,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_1)
+SYM(rtems_irq_prologue_1):
+ push st
+ push ar2
+ ldi 0x1,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_2)
+SYM(rtems_irq_prologue_2):
+ push st
+ push ar2
+ ldi 0x2,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_3)
+SYM(rtems_irq_prologue_3):
+ push st
+ push ar2
+ ldi 0x3,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_4)
+SYM(rtems_irq_prologue_4):
+ push st
+ push ar2
+ ldi 0x4,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_5)
+SYM(rtems_irq_prologue_5):
+ push st
+ push ar2
+ ldi 0x5,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_6)
+SYM(rtems_irq_prologue_6):
+ push st
+ push ar2
+ ldi 0x6,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_7)
+SYM(rtems_irq_prologue_7):
+ push st
+ push ar2
+ ldi 0x7,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_8)
+SYM(rtems_irq_prologue_8):
+ push st
+ push ar2
+ ldi 0x8,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_9)
+SYM(rtems_irq_prologue_9):
+ push st
+ push ar2
+ ldi 0x9,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_A)
+SYM(rtems_irq_prologue_A):
+ push st
+ push ar2
+ ldi 0xa,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_B)
+SYM(rtems_irq_prologue_B):
+ push st
+ push ar2
+ ldi 0xb,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_C)
+SYM(rtems_irq_prologue_C):
+ push st
+ push ar2
+ ldi 0xc,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_D)
+SYM(rtems_irq_prologue_D):
+ push st
+ push ar2
+ ldi 0xd,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_E)
+SYM(rtems_irq_prologue_E):
+ push st
+ push ar2
+ ldi 0xe,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_F)
+SYM(rtems_irq_prologue_F):
+ push st
+ push ar2
+ ldi 0xf,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_10)
+SYM(rtems_irq_prologue_10):
+ push st
+ push ar2
+ ldi 0x10,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_11)
+SYM(rtems_irq_prologue_11):
+ push st
+ push ar2
+ ldi 0x11,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_12)
+SYM(rtems_irq_prologue_12):
+ push st
+ push ar2
+ ldi 0x12,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_13)
+SYM(rtems_irq_prologue_13):
+ push st
+ push ar2
+ ldi 0x13,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_14)
+SYM(rtems_irq_prologue_14):
+ push st
+ push ar2
+ ldi 0x14,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_15)
+SYM(rtems_irq_prologue_15):
+ push st
+ push ar2
+ ldi 0x15,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_16)
+SYM(rtems_irq_prologue_16):
+ push st
+ push ar2
+ ldi 0x16,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_17)
+SYM(rtems_irq_prologue_17):
+ push st
+ push ar2
+ ldi 0x17,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_18)
+SYM(rtems_irq_prologue_18):
+ push st
+ push ar2
+ ldi 0x18,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_19)
+SYM(rtems_irq_prologue_19):
+ push st
+ push ar2
+ ldi 0x19,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_1A)
+SYM(rtems_irq_prologue_1A):
+ push st
+ push ar2
+ ldi 0x1a,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_1B)
+SYM(rtems_irq_prologue_1B):
+ push st
+ push ar2
+ ldi 0x1b,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_1C)
+SYM(rtems_irq_prologue_1C):
+ push st
+ push ar2
+ ldi 0x1c,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_1D)
+SYM(rtems_irq_prologue_1D):
+ push st
+ push ar2
+ ldi 0x1d,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_1E)
+SYM(rtems_irq_prologue_1E):
+ push st
+ push ar2
+ ldi 0x1e,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_1F)
+SYM(rtems_irq_prologue_1F):
+ push st
+ push ar2
+ ldi 0x1f,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_20)
+SYM(rtems_irq_prologue_20):
+ push st
+ push ar2
+ ldi 0x20,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_21)
+SYM(rtems_irq_prologue_21):
+ push st
+ push ar2
+ ldi 0x21,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_22)
+SYM(rtems_irq_prologue_22):
+ push st
+ push ar2
+ ldi 0x22,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_23)
+SYM(rtems_irq_prologue_23):
+ push st
+ push ar2
+ ldi 0x23,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_24)
+SYM(rtems_irq_prologue_24):
+ push st
+ push ar2
+ ldi 0x24,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_25)
+SYM(rtems_irq_prologue_25):
+ push st
+ push ar2
+ ldi 0x25,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_26)
+SYM(rtems_irq_prologue_26):
+ push st
+ push ar2
+ ldi 0x26,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_27)
+SYM(rtems_irq_prologue_27):
+ push st
+ push ar2
+ ldi 0x27,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_28)
+SYM(rtems_irq_prologue_28):
+ push st
+ push ar2
+ ldi 0x28,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_29)
+SYM(rtems_irq_prologue_29):
+ push st
+ push ar2
+ ldi 0x29,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_2A)
+SYM(rtems_irq_prologue_2A):
+ push st
+ push ar2
+ ldi 0x2a,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_2B)
+SYM(rtems_irq_prologue_2B):
+ push st
+ push ar2
+ ldi 0x2b,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_2C)
+SYM(rtems_irq_prologue_2C):
+ push st
+ push ar2
+ ldi 0x2c,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_2D)
+SYM(rtems_irq_prologue_2D):
+ push st
+ push ar2
+ ldi 0x2d,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_2E)
+SYM(rtems_irq_prologue_2E):
+ push st
+ push ar2
+ ldi 0x2e,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_2F)
+SYM(rtems_irq_prologue_2F):
+ push st
+ push ar2
+ ldi 0x2f,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_30)
+SYM(rtems_irq_prologue_30):
+ push st
+ push ar2
+ ldi 0x30,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_31)
+SYM(rtems_irq_prologue_31):
+ push st
+ push ar2
+ ldi 0x31,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_32)
+SYM(rtems_irq_prologue_32):
+ push st
+ push ar2
+ ldi 0x32,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_33)
+SYM(rtems_irq_prologue_33):
+ push st
+ push ar2
+ ldi 0x33,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_34)
+SYM(rtems_irq_prologue_34):
+ push st
+ push ar2
+ ldi 0x34,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_35)
+SYM(rtems_irq_prologue_35):
+ push st
+ push ar2
+ ldi 0x35,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_36)
+SYM(rtems_irq_prologue_36):
+ push st
+ push ar2
+ ldi 0x36,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_37)
+SYM(rtems_irq_prologue_37):
+ push st
+ push ar2
+ ldi 0x37,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_38)
+SYM(rtems_irq_prologue_38):
+ push st
+ push ar2
+ ldi 0x38,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_39)
+SYM(rtems_irq_prologue_39):
+ push st
+ push ar2
+ ldi 0x39,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_3A)
+SYM(rtems_irq_prologue_3A):
+ push st
+ push ar2
+ ldi 0x3a,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_3B)
+SYM(rtems_irq_prologue_3B):
+ push st
+ push ar2
+ ldi 0x3b,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_3C)
+SYM(rtems_irq_prologue_3C):
+ push st
+ push ar2
+ ldi 0x3c,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_3D)
+SYM(rtems_irq_prologue_3D):
+ push st
+ push ar2
+ ldi 0x3d,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_3E)
+SYM(rtems_irq_prologue_3E):
+ push st
+ push ar2
+ ldi 0x3e,ar2
+ br SYM(_ISR_Handler_save_registers)
+
+ .global SYM(rtems_irq_prologue_3F)
+SYM(rtems_irq_prologue_3F):
+ push st
+ push ar2
+ ldi 0x3f,ar2
+ br SYM(_ISR_Handler_save_registers)
diff --git a/cpukit/score/cpu/c4x/irq.c b/cpukit/score/cpu/c4x/irq.c
new file mode 100644
index 0000000000..104b3afdc4
--- /dev/null
+++ b/cpukit/score/cpu/c4x/irq.c
@@ -0,0 +1,89 @@
+/*
+ * C4x CPU Dependent Source
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/cpu.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/thread.h>
+
+/*
+ * This routine provides the RTEMS interrupt management.
+ */
+
+#if( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE)
+ unsigned long *_old_stack_ptr;
+#endif
+
+register unsigned long *stack_ptr asm("sp");
+
+void __ISR_Handler(uint32_t vector, void *isr_sp)
+{
+ register uint32_t level;
+
+ /* already disabled when we get here */
+ /* _CPU_ISR_Disable( level ); */
+
+ _Thread_Dispatch_disable_level++;
+
+#if 0
+ if ( stack_ptr > (_Thread_Executing->Start.stack +
+ _Thread_Executing->Start.Initial_stack.size) ) {
+ printk( "Blown interrupt stack at 0x%x\n", stack_ptr );
+ }
+#endif
+
+#if( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE)
+ if ( _ISR_Nest_level == 0 ) {
+ /* Install irq stack */
+ _old_stack_ptr = stack_ptr;
+ stack_ptr = _CPU_Interrupt_stack_low;
+ }
+#endif
+
+ _ISR_Nest_level++;
+
+ /* leave it to the ISR to decide if they get reenabled */
+ /* _CPU_ISR_Enable( level ); */
+
+ /* call isp */
+ if ( _ISR_Vector_table[ vector] )
+ (*_ISR_Vector_table[ vector ])(
+ vector, isr_sp - sizeof(CPU_Interrupt_frame) + 1 );
+
+ _CPU_ISR_Disable( level );
+
+ _ISR_Nest_level--;
+
+#if( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE)
+ if ( _ISR_Nest_level == 0 ) /* restore old stack pointer */
+ stack_ptr = _old_stack_ptr;
+#endif
+
+ _Thread_Dispatch_disable_level--;
+
+ _CPU_ISR_Enable( level );
+
+ if ( _ISR_Nest_level )
+ return;
+
+ if ( _Thread_Dispatch_disable_level ) {
+ _ISR_Signals_to_thread_executing = FALSE;
+ return;
+ }
+
+ if ( _Context_Switch_necessary || _ISR_Signals_to_thread_executing ) {
+ _ISR_Signals_to_thread_executing = FALSE;
+ _Thread_Dispatch();
+ }
+}
diff --git a/cpukit/score/cpu/c4x/rtems/asm.h b/cpukit/score/cpu/c4x/rtems/asm.h
new file mode 100644
index 0000000000..a63abf2784
--- /dev/null
+++ b/cpukit/score/cpu/c4x/rtems/asm.h
@@ -0,0 +1,99 @@
+/* asm.h
+ *
+ * This include file attempts to address the problems
+ * caused by incompatible flavors of assemblers and
+ * toolsets. It primarily addresses variations in the
+ * use of leading underscores on symbols and the requirement
+ * that register names be preceded by a %.
+ *
+ *
+ * NOTE: The spacing in the use of these macros
+ * is critical to them working as advertised.
+ *
+ * COPYRIGHT:
+ *
+ * This file is based on similar code found in newlib available
+ * from ftp.cygnus.com. The file which was used had no copyright
+ * notice. This file is freely distributable as long as the source
+ * of the file is noted. This file is:
+ *
+ * COPYRIGHT (c) 1994-1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * $Id$
+ */
+
+#ifndef __C4X_ASM_h
+#define __C4X_ASM_h
+
+/*
+ * Indicate we are in an assembly file and get the basic CPU definitions.
+ */
+
+#ifndef ASM
+#define ASM
+#endif
+#include <rtems/score/cpuopts.h>
+#include <rtems/score/c4x.h>
+
+/*
+ * Recent versions of GNU cpp define variables which indicate the
+ * need for underscores and percents. If not using GNU cpp or
+ * the version does not support this, then you will obviously
+ * have to define these as appropriate.
+ */
+
+#ifndef __USER_LABEL_PREFIX__
+#define __USER_LABEL_PREFIX__ _
+#endif
+
+#ifndef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__
+#endif
+
+/* ANSI concatenation macros. */
+
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+/* Use the right prefix for global labels. */
+
+#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+
+/* Use the right prefix for registers. */
+
+#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
+
+/*
+ * define macros for all of the registers on this CPU
+ *
+ * EXAMPLE: #define d0 REG (d0)
+ */
+
+/*
+ * Define macros to handle section beginning and ends.
+ */
+
+
+#define BEGIN_CODE_DCL .text
+#define END_CODE_DCL
+#define BEGIN_DATA_DCL .data
+#define END_DATA_DCL
+#define BEGIN_CODE .text
+#define END_CODE
+#define BEGIN_DATA
+#define END_DATA
+#define BEGIN_BSS
+#define END_BSS
+#define END
+
+/*
+ * Following must be tailor for a particular flavor of the C compiler.
+ * They may need to put underscores in front of the symbols.
+ */
+
+#define PUBLIC(sym) .globl SYM (sym)
+#define EXTERN(sym) .globl SYM (sym)
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/c4x/rtems/score/c4x.h b/cpukit/score/cpu/c4x/rtems/score/c4x.h
new file mode 100644
index 0000000000..88d682e8bc
--- /dev/null
+++ b/cpukit/score/cpu/c4x/rtems/score/c4x.h
@@ -0,0 +1,365 @@
+/* c4x.h
+ *
+ * This file is an example (i.e. "no CPU") of the file which is
+ * created for each CPU family port of RTEMS.
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ *
+ */
+
+#ifndef _INCLUDE_C4X_h
+#define _INCLUDE_C4X_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This file contains the information required to build
+ * RTEMS for a particular member of the "no cpu"
+ * family when executing in protected mode. It does
+ * this by setting variables to indicate which implementation
+ * dependent features are present in a particular member
+ * of the family.
+ */
+
+#if defined(_C30)
+#define CPU_MODEL_NAME "C30"
+
+#elif defined(_C31)
+#define CPU_MODEL_NAME "C31"
+
+#elif defined(_C32)
+#define CPU_MODEL_NAME "C32"
+
+#elif defined(_C33)
+#define CPU_MODEL_NAME "C33"
+
+#elif defined(_C40)
+#define CPU_MODEL_NAME "C40"
+
+#elif defined(_C44)
+#define CPU_MODEL_NAME "C44"
+
+#else
+
+#error "Unsupported CPU Model"
+
+#endif
+
+/*
+ * Define the name of the CPU family.
+ */
+
+#define CPU_NAME "Texas Instruments C3x/C4x"
+
+/*
+ * This port is a little unusual in that even though there are "floating
+ * point registers", the notion of floating point is very inherent to
+ * applications. In addition, the calling conventions require that
+ * only a few extended registers be preserved across subroutine calls.
+ * The overhead of including these few registers in the basic
+ * context is small compared to the overhead of managing the notion
+ * of separate floating point contexts. So we decided to pretend that
+ * there is no FPU on the C3x or C4x.
+ */
+
+#define C4X_HAS_FPU 0
+
+/*
+ * Routines to manipulate the bits in the Status Word (ST).
+ */
+
+#define C4X_ST_C 0x0001
+#define C4X_ST_V 0x0002
+#define C4X_ST_Z 0x0004
+#define C4X_ST_N 0x0008
+#define C4X_ST_UF 0x0010
+#define C4X_ST_LV 0x0020
+#define C4X_ST_LUF 0x0040
+#define C4X_ST_OVM 0x0080
+#define C4X_ST_RM 0x0100
+#define C4X_ST_CF 0x0400
+#define C4X_ST_CE 0x0800
+#define C4X_ST_CC 0x1000
+#define C4X_ST_GIE 0x2000
+
+#ifndef _TMS320C40
+#define C3X_IE_INTERRUPT_MASK_BITS 0xffff
+#define C3x_IE_INTERRUPTS_ALL_ENABLED 0x0000
+#define C3x_IE_INTERRUPTS_ALL_DISABLED 0xffff
+#endif
+
+#ifndef ASM
+
+/*
+ * A nop macro.
+ */
+
+#define c4x_nop() \
+ __asm__("nop");
+
+/*
+ * Routines to set and clear individual bits in the ST (status word).
+ *
+ * cpu_st_bit_clear - clear bit in ST
+ * cpu_st_bit_set - set bit in ST
+ * cpu_st_get - obtain entire ST
+ */
+
+#ifdef _TMS320C40
+#define c4x_gie_nop()
+#else
+#define c4x_gie_nop() { c4x_nop(); c4x_nop(); }
+#endif
+
+#define cpu_st_bit_clear(_st_bit) \
+ do { \
+ __asm__("andn %0,st" : : "g" (_st_bit) : "cc"); \
+ c4x_gie_nop(); \
+ } while (0)
+
+#define cpu_st_bit_set(_st_bit) \
+ do { \
+ __asm__("or %0,st" : : "g" (_st_bit) : "cc"); \
+ c4x_gie_nop(); \
+ } while (0)
+
+static inline unsigned int cpu_st_get(void)
+{
+ register unsigned int st_value;
+ __asm__("ldi st, %0" : "=r" (st_value));
+ return st_value;
+}
+
+/*
+ * Routines to manipulate the Global Interrupt Enable (GIE) bit in
+ * the Status Word (ST).
+ *
+ * c4x_global_interrupts_get - returns current GIE setting
+ * c4x_global_interrupts_disable - disables global interrupts
+ * c4x_global_interrupts_enable - enables global interrupts
+ * c4x_global_interrupts_restore - restores GIE to pre-disable state
+ * c4x_global_interrupts_flash - temporarily enable global interrupts
+ */
+
+#define c4x_global_interrupts_get() \
+ (cpu_st_get() & C4X_ST_GIE)
+
+#define c4x_global_interrupts_disable() \
+ cpu_st_bit_clear(C4X_ST_GIE)
+
+#define c4x_global_interrupts_enable() \
+ cpu_st_bit_set(C4X_ST_GIE)
+
+#define c4x_global_interrupts_restore(_old_level) \
+ cpu_st_bit_set(_old_level)
+
+#define c4x_global_interrupts_flash(_old_level) \
+ do { \
+ cpu_st_bit_set(_old_level); \
+ cpu_st_bit_clear(C4X_ST_GIE); \
+ } while (0)
+
+#ifndef _TMS320C40
+
+/*
+ * Routines to set and get the IF register
+ *
+ * c3x_get_if - obtains IF register
+ * c3x_set_if - sets IF register
+ */
+
+static inline unsigned int c3x_get_if(void)
+{
+ register unsigned int _if_value;
+
+ __asm__( "ldi if, %0" : "=r" (_if_value) );
+ return _if_value;
+}
+
+static inline void c3x_set_if(unsigned int _if_value)
+{
+ __asm__( "ldi %0, if" : : "g" (_if_value) : "if", "cc");
+}
+
+/*
+ * Routines to set and get the IE register
+ *
+ * c3x_get_ie - obtains IE register
+ * c3x_set_ie - sets IE register
+ */
+
+static inline unsigned int c3x_get_ie(void)
+{
+ register unsigned int _ie_value;
+
+ __asm__ volatile ( "ldi ie, %0" : "=r" (_ie_value) );
+ return _ie_value;
+}
+
+static inline void c3x_set_ie(unsigned int _ie_value)
+{
+ __asm__ volatile ( "ldi %0, ie" : : "g" (_ie_value) : "ie", "cc");
+}
+
+/*
+ * Routines to manipulates the mask portion of the IE register.
+ *
+ * c3x_ie_mask_all - returns previous IE mask
+ * c3x_ie_mask_restore - restores previous IE mask
+ * c3x_ie_mask_flash - temporarily restores previous IE mask
+ * c3x_ie_mask_set - sets a specific set of the IE mask
+ */
+
+#define c3x_ie_mask_all( _isr_cookie ) \
+ do { \
+ __asm__("ldi ie,%0\n" \
+ "\tandn 0ffffh, ie" \
+ : "=r" (_isr_cookie): : "ie", "cc" ); \
+ } while (0)
+
+#define c3x_ie_mask_restore( _isr_cookie ) \
+ do { \
+ __asm__("or %0, ie" \
+ : : "g" (_isr_cookie) : "ie", "cc" ); \
+ } while (0)
+
+#define c3x_ie_mask_flash( _isr_cookie ) \
+ do { \
+ __asm__("or %0, ie\n" \
+ "\tandn 0ffffh, ie" \
+ : : "g" (_isr_cookie) : "ie", "cc" ); \
+ } while (0)
+
+#define c3x_ie_mask_set( _new_mask ) \
+ do { unsigned int _ie_mask; \
+ unsigned int _ie_value; \
+ \
+ if ( _new_mask == 0 ) _ie_mask = 0; \
+ else _ie_mask = 0xffff; \
+ _ie_value = c3x_get_ie(); \
+ _ie_value &= C4X_IE_INTERRUPT_MASK_BITS; \
+ _ie_value |= _ie_mask; \
+ c3x_set_ie(_ie_value); \
+ } while (0)
+#endif
+/* end of C3x specific interrupt flag routines */
+
+/*
+ * This is a section of C4x specific interrupt flag management routines.
+ */
+
+#ifdef _TMS320C40
+
+/*
+ * Routines to set and get the IIF register
+ *
+ * c4x_get_iif - obtains IIF register
+ * c4x_set_iif - sets IIF register
+ */
+
+static inline unsigned int c4x_get_iif(void)
+{
+ register unsigned int _iif_value;
+
+ __asm__( "ldi iif, %0" : "=r" (_iif_value) );
+ return _iif_value;
+}
+
+static inline void c4x_set_iif(unsigned int _iif_value)
+{
+ __asm__( "ldi %0, iif" : : "g" (_iif_value) : "iif", "cc");
+}
+
+/*
+ * Routines to set and get the IIE register
+ *
+ * c4x_get_iie - obtains IIE register
+ * c4x_set_iie - sets IIE register
+ */
+
+static inline unsigned int c4x_get_iie(void)
+{
+ register unsigned int _iie_value;
+
+ __asm__( "ldi iie, %0" : "=r" (_iie_value) );
+ return _iie_value;
+}
+
+static inline void c4x_set_iie(unsigned int _iie_value)
+{
+ __asm__( "ldi %0, iie" : : "g" (_iie_value) : "iie", "cc");
+}
+
+/*
+ * Routines to manipulates the mask portion of the IIE register.
+ *
+ * c4x_ie_mask_all - returns previous IIE mask
+ * c4x_ie_mask_restore - restores previous IIE mask
+ * c4x_ie_mask_flash - temporarily restores previous IIE mask
+ * c4x_ie_mask_set - sets a specific set of the IIE mask
+ */
+
+#if 0
+#warning "C4x IIE masking routines not implemented."
+#define c4x_iie_mask_all( _isr_cookie )
+#define c4x_iie_mask_restore( _isr_cookie )
+#define c4x_iie_mask_flash( _isr_cookie )
+#define c4x_iie_mask_set( _new_mask )
+#endif
+
+#endif
+/* end of C4x specific interrupt flag routines */
+
+/*
+ * Routines to access the Interrupt Trap Table Pointer
+ *
+ * c4x_get_ittp - get ITTP
+ * c4x_set_ittp - set ITTP
+ */
+
+static inline void * c4x_get_ittp(void)
+{
+ register unsigned int _if_value;
+
+ __asm__( "ldi if, %0" : "=r" (_if_value) );
+ return (void *)((_if_value & 0xffff0000) >> 8);
+}
+
+static inline void c4x_set_ittp(void *_ittp_value)
+{
+ unsigned int _if_value;
+ unsigned int _ittp_field;
+
+#ifdef _TMS320C40
+ _if_value = c4x_get_iif();
+#else
+ _if_value = c3x_get_if();
+#endif
+ _if_value &= 0xffff;
+ _ittp_field = (((unsigned int) _ittp_value) >> 8);
+ _if_value |= _ittp_field << 16 ;
+#ifdef _TMS320C40
+ c4x_set_iif( _if_value );
+#else
+ c3x_set_if( _if_value );
+#endif
+}
+
+#endif /* ifndef ASM */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ! _INCLUDE_C4X_h */
+/* end of include file */
diff --git a/cpukit/score/cpu/c4x/rtems/score/cpu.h b/cpukit/score/cpu/c4x/rtems/score/cpu.h
new file mode 100644
index 0000000000..f2ed61319f
--- /dev/null
+++ b/cpukit/score/cpu/c4x/rtems/score/cpu.h
@@ -0,0 +1,1261 @@
+/* cpu.h
+ *
+ * This include file contains information pertaining to the C4x
+ * processor.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __CPU_h
+#define __CPU_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/c4x.h> /* pick up machine definitions */
+#ifndef ASM
+#include <rtems/score/types.h>
+#endif
+
+/* conditional compilation parameters */
+
+/*
+ * Should the calls to _Thread_Enable_dispatch be inlined?
+ *
+ * If TRUE, then they are inlined.
+ * If FALSE, then a subroutine call is made.
+ *
+ * Basically this is an example of the classic trade-off of size
+ * versus speed. Inlining the call (TRUE) typically increases the
+ * size of RTEMS while speeding up the enabling of dispatching.
+ * [NOTE: In general, the _Thread_Dispatch_disable_level will
+ * only be 0 or 1 unless you are in an interrupt handler and that
+ * interrupt handler invokes the executive.] When not inlined
+ * something calls _Thread_Enable_dispatch which in turns calls
+ * _Thread_Dispatch. If the enable dispatch is inlined, then
+ * one subroutine call is avoided entirely.]
+ *
+ * C4x Specific Information:
+ *
+ * We might as well try to inline this code until there is a
+ * code space problem.
+ */
+
+#define CPU_INLINE_ENABLE_DISPATCH TRUE
+
+/*
+ * Should the body of the search loops in _Thread_queue_Enqueue_priority
+ * be unrolled one time? In unrolled each iteration of the loop examines
+ * two "nodes" on the chain being searched. Otherwise, only one node
+ * is examined per iteration.
+ *
+ * If TRUE, then the loops are unrolled.
+ * If FALSE, then the loops are not unrolled.
+ *
+ * The primary factor in making this decision is the cost of disabling
+ * and enabling interrupts (_ISR_Flash) versus the cost of rest of the
+ * body of the loop. On some CPUs, the flash is more expensive than
+ * one iteration of the loop body. In this case, it might be desirable
+ * to unroll the loop. It is important to note that on some CPUs, this
+ * code is the longest interrupt disable period in RTEMS. So it is
+ * necessary to strike a balance when setting this parameter.
+ *
+ * C4x Specific Information:
+ *
+ * We might as well unroll this loop until there is a reason not to do so.
+ */
+
+#define CPU_UNROLL_ENQUEUE_PRIORITY TRUE
+
+/*
+ * Does RTEMS manage a dedicated interrupt stack in software?
+ *
+ * If TRUE, then a stack is allocated in _Interrupt_Manager_initialization.
+ * If FALSE, nothing is done.
+ *
+ * If the CPU supports a dedicated interrupt stack in hardware,
+ * then it is generally the responsibility of the BSP to allocate it
+ * and set it up.
+ *
+ * If the CPU does not support a dedicated interrupt stack, then
+ * the porter has two options: (1) execute interrupts on the
+ * stack of the interrupted task, and (2) have RTEMS manage a dedicated
+ * interrupt stack.
+ *
+ * If this is TRUE, CPU_ALLOCATE_INTERRUPT_STACK should also be TRUE.
+ *
+ * Only one of CPU_HAS_SOFTWARE_INTERRUPT_STACK and
+ * CPU_HAS_HARDWARE_INTERRUPT_STACK should be set to TRUE. It is
+ * possible that both are FALSE for a particular CPU. Although it
+ * is unclear what that would imply about the interrupt processing
+ * procedure on that CPU.
+ *
+ * C4x Specific Information:
+ *
+ * Initial investigation indicates a software managed stack will be needed.
+ * But the implementation does not currently include support for one.
+ */
+
+#define CPU_HAS_SOFTWARE_INTERRUPT_STACK FALSE
+
+/*
+ * Does this CPU have hardware support for a dedicated interrupt stack?
+ *
+ * If TRUE, then it must be installed during initialization.
+ * If FALSE, then no installation is performed.
+ *
+ * If this is TRUE, CPU_ALLOCATE_INTERRUPT_STACK should also be TRUE.
+ *
+ * Only one of CPU_HAS_SOFTWARE_INTERRUPT_STACK and
+ * CPU_HAS_HARDWARE_INTERRUPT_STACK should be set to TRUE. It is
+ * possible that both are FALSE for a particular CPU. Although it
+ * is unclear what that would imply about the interrupt processing
+ * procedure on that CPU.
+ *
+ * C4x Specific Information:
+ *
+ * XXXanswer
+ *
+ * Initial investigation indicates a software managed stack will be needed.
+ */
+
+#define CPU_HAS_HARDWARE_INTERRUPT_STACK FALSE
+
+/*
+ * Does RTEMS allocate a dedicated interrupt stack in the Interrupt Manager?
+ *
+ * If TRUE, then the memory is allocated during initialization.
+ * If FALSE, then the memory is allocated during initialization.
+ *
+ * This should be TRUE is CPU_HAS_SOFTWARE_INTERRUPT_STACK is TRUE
+ * or CPU_INSTALL_HARDWARE_INTERRUPT_STACK is TRUE.
+ *
+ * C4x Specific Information:
+ *
+ * XXXanswer
+ *
+ * Until we know what to do with the memory, we should not allocated it.
+ */
+
+#define CPU_ALLOCATE_INTERRUPT_STACK FALSE
+
+/*
+ * Does the RTEMS invoke the user's ISR with the vector number and
+ * a pointer to the saved interrupt frame (1) or just the vector
+ * number (0)?
+ *
+ * C4x Specific Information:
+ *
+ * XXXanswer
+ *
+ * The interrupt code will have to be written before this is answered
+ * but the answer should be yes.
+ */
+
+#define CPU_ISR_PASSES_FRAME_POINTER 1
+
+/*
+ * Does the CPU have hardware floating point?
+ *
+ * If TRUE, then the RTEMS_FLOATING_POINT task attribute is supported.
+ * If FALSE, then the RTEMS_FLOATING_POINT task attribute is ignored.
+ *
+ * If there is a FP coprocessor such as the i387 or mc68881, then
+ * the answer is TRUE.
+ *
+ * The macro name "C4X_HAS_FPU" should be made CPU specific.
+ * It indicates whether or not this CPU model has FP support. For
+ * example, it would be possible to have an i386_nofp CPU model
+ * which set this to false to indicate that you have an i386 without
+ * an i387 and wish to leave floating point support out of RTEMS.
+ *
+ * C4x Specific Information:
+ *
+ * See c4x.h for more details but the bottom line is that the
+ * few extended registers required to be preserved across subroutines
+ * calls are considered part of the integer context. This eliminates
+ * overhead.
+ *
+ * The C4X_HAS_FPU refers to the extended precision registers R0-R7
+ * (plus R8-R11 on some models).
+ *
+ * XXX check that we even need to have the context area pointer in
+ * the TCB in this case.
+ */
+
+#if ( C4X_HAS_FPU == 1 )
+#define CPU_HARDWARE_FP TRUE
+#else
+#define CPU_HARDWARE_FP FALSE
+#endif
+#define CPU_SOFTWARE_FP FALSE
+
+/*
+ * Are all tasks RTEMS_FLOATING_POINT tasks implicitly?
+ *
+ * If TRUE, then the RTEMS_FLOATING_POINT task attribute is assumed.
+ * If FALSE, then the RTEMS_FLOATING_POINT task attribute is followed.
+ *
+ * If CPU_HARDWARE_FP is FALSE, then this should be FALSE as well.
+ *
+ * C4x Specific Information:
+ *
+ * There is no known reason to make all tasks include the extended
+ * precision registers (i.e. floating point context).
+ */
+
+#define CPU_ALL_TASKS_ARE_FP FALSE
+
+/*
+ * Should the IDLE task have a floating point context?
+ *
+ * If TRUE, then the IDLE task is created as a RTEMS_FLOATING_POINT task
+ * and it has a floating point context which is switched in and out.
+ * If FALSE, then the IDLE task does not have a floating point context.
+ *
+ * Setting this to TRUE negatively impacts the time required to preempt
+ * the IDLE task from an interrupt because the floating point context
+ * must be saved as part of the preemption.
+ *
+ * C4x Specific Information:
+ *
+ * There is no known reason to make the IDLE task floating point and
+ * no point in wasting the memory or increasing the context switch
+ * time for the IDLE task.
+ */
+
+#define CPU_IDLE_TASK_IS_FP FALSE
+
+/*
+ * Should the saving of the floating point registers be deferred
+ * until a context switch is made to another different floating point
+ * task?
+ *
+ * If TRUE, then the floating point context will not be stored until
+ * necessary. It will remain in the floating point registers and not
+ * disturned until another floating point task is switched to.
+ *
+ * If FALSE, then the floating point context is saved when a floating
+ * point task is switched out and restored when the next floating point
+ * task is restored. The state of the floating point registers between
+ * those two operations is not specified.
+ *
+ * If the floating point context does NOT have to be saved as part of
+ * interrupt dispatching, then it should be safe to set this to TRUE.
+ *
+ * Setting this flag to TRUE results in using a different algorithm
+ * for deciding when to save and restore the floating point context.
+ * The deferred FP switch algorithm minimizes the number of times
+ * the FP context is saved and restored. The FP context is not saved
+ * until a context switch is made to another, different FP task.
+ * Thus in a system with only one FP task, the FP context will never
+ * be saved or restored.
+ *
+ * C4x Specific Information:
+ *
+ * There is no reason to avoid the deferred FP switch logic on this
+ * CPU family.
+ */
+
+#define CPU_USE_DEFERRED_FP_SWITCH TRUE
+
+/*
+ * Does this port provide a CPU dependent IDLE task implementation?
+ *
+ * If TRUE, then the routine _CPU_Thread_Idle_body
+ * must be provided and is the default IDLE thread body instead of
+ * _CPU_Thread_Idle_body.
+ *
+ * If FALSE, then use the generic IDLE thread body if the BSP does
+ * not provide one.
+ *
+ * This is intended to allow for supporting processors which have
+ * a low power or idle mode. When the IDLE thread is executed, then
+ * the CPU can be powered down.
+ *
+ * The order of precedence for selecting the IDLE thread body is:
+ *
+ * 1. BSP provided
+ * 2. CPU dependent (if provided)
+ * 3. generic (if no BSP and no CPU dependent)
+ *
+ * C4x Specific Information:
+ *
+ * There is currently no reason to avoid using the generic implementation.
+ * In the future, a C4x specific IDLE thread body may be added to take
+ * advantage of low power modes.
+ */
+
+#define CPU_PROVIDES_IDLE_THREAD_BODY FALSE
+
+/*
+ * Does the stack grow up (toward higher addresses) or down
+ * (toward lower addresses)?
+ *
+ * If TRUE, then the grows upward.
+ * If FALSE, then the grows toward smaller addresses.
+ *
+ * C4x Specific Information:
+ *
+ * The system stack grows from low to high memory.
+ *
+ * C4x Specific Information:
+ *
+ * This setting was derived from the discussion of stack management
+ * in section 6.1 (p. 6-29) System and User Stack Management of the
+ * TMS32C3x User's Guide (rev L, July 1997) which states: "A push
+ * performs a preincrement, and a pop performs a postdecrement of the
+ * system-stack pointer." There are instructions for making "a stack"
+ * run from high to low memory but this appears to be the exception.
+ */
+
+#define CPU_STACK_GROWS_UP TRUE
+
+/*
+ * The following is the variable attribute used to force alignment
+ * of critical RTEMS structures. On some processors it may make
+ * sense to have these aligned on tighter boundaries than
+ * the minimum requirements of the compiler in order to have as
+ * much of the critical data area as possible in a cache line.
+ *
+ * The placement of this macro in the declaration of the variables
+ * is based on the syntactically requirements of the GNU C
+ * "__attribute__" extension. For example with GNU C, use
+ * the following to force a structures to a 32 byte boundary.
+ *
+ * __attribute__ ((aligned (32)))
+ *
+ * NOTE: Currently only the Priority Bit Map table uses this feature.
+ * To benefit from using this, the data must be heavily
+ * used so it will stay in the cache and used frequently enough
+ * in the executive to justify turning this on.
+ *
+ * C4x Specific Information:
+ *
+ * The C4x is word oriented and there should be no alignment issues.
+ */
+
+#define CPU_STRUCTURE_ALIGNMENT
+
+/*
+ * Define what is required to specify how the network to host conversion
+ * routines are handled.
+ *
+ * C4x Specific Information:
+ *
+ */
+
+#define CPU_HAS_OWN_HOST_TO_NETWORK_ROUTINES FALSE
+#define CPU_BIG_ENDIAN TRUE
+#define CPU_LITTLE_ENDIAN FALSE
+
+/*
+ * The following defines the number of bits actually used in the
+ * interrupt field of the task mode. How those bits map to the
+ * CPU interrupt levels is defined by the routine _CPU_ISR_Set_level().
+ *
+ * C4x Specific Information:
+ *
+ * Currently we are only supporting interrupt levels 0 (all on) and
+ * 1 (all off). Levels 2-255 COULD be looked up in a user provided
+ * table that gives GIE and IE Mask settings. But this is not the
+ * case today.
+ */
+
+#define CPU_MODES_INTERRUPT_MASK 0x000000FF
+
+/*
+ * Processor defined structures
+ *
+ * Examples structures include the descriptor tables from the i386
+ * and the processor control structure on the i960ca.
+ *
+ * C4x Specific Information:
+ *
+ * XXXanswer
+ */
+
+/* may need to put some structures here. */
+
+/*
+ * Contexts
+ *
+ * Generally there are 2 types of context to save.
+ * 1. Interrupt registers to save
+ * 2. Task level registers to save
+ *
+ * This means we have the following 3 context items:
+ * 1. task level context stuff:: Context_Control
+ * 2. floating point task stuff:: Context_Control_fp
+ * 3. special interrupt level context :: Context_Control_interrupt
+ *
+ * On some processors, it is cost-effective to save only the callee
+ * preserved registers during a task context switch. This means
+ * that the ISR code needs to save those registers which do not
+ * persist across function calls. It is not mandatory to make this
+ * distinctions between the caller/callee saves registers for the
+ * purpose of minimizing context saved during task switch and on interrupts.
+ * If the cost of saving extra registers is minimal, simplicity is the
+ * choice. Save the same context on interrupt entry as for tasks in
+ * this case.
+ *
+ * Additionally, if gdb is to be made aware of RTEMS tasks for this CPU, then
+ * care should be used in designing the context area.
+ *
+ * On some CPUs with hardware floating point support, the Context_Control_fp
+ * structure will not be used or it simply consist of an array of a
+ * fixed number of bytes. This is done when the floating point context
+ * is dumped by a "FP save context" type instruction and the format
+ * is not really defined by the CPU. In this case, there is no need
+ * to figure out the exact format -- only the size. Of course, although
+ * this is enough information for RTEMS, it is probably not enough for
+ * a debugger such as gdb. But that is another problem.
+ *
+ * C4x Specific Information:
+ *
+ * From email with Michael Hayes:
+ * > > But what are the rules for what is passed in what registers?
+ *
+ * Args are passed in the following registers (in order):
+ *
+ * AR2, R2, R3, RC, RS, RE
+ *
+ * However, the first and second floating point values are always in R2
+ * and R3 (and all other floats are on the stack). Structs are always
+ * passed on the stack. If the last argument is an ellipsis, the
+ * previous argument is passed on the stack so that its address can be
+ * taken for the stdargs macros.
+ *
+ * > > What is assumed to be preserved across calls?
+ *
+ * AR3, AR4, AR5, AR6, AR7
+ * R4, R5, R8 (using STI/LDI)
+ * R6, R7 (using STF/LDF)
+ *
+ * > > What is assumed to be scratch registers?
+ *
+ * R0, R1, R2, R3, AR0, AR1, AR2, IR0, IR1, BK, RS, RE, RC, R9, R10, R11
+ *
+ * Based on this information, the task specific context is quite small
+ * but the interrupt context is much larger. In fact, it could
+ * easily be argued that there is no point in distinguishing between
+ * integer and floating point contexts on the Cxx since there is
+ * so little context involved. So that is the decision made.
+ *
+ * Not Mentioned in list: DP
+ *
+ * Assumed to be global resources:
+ *
+ * C3X: IE, IF, and IOF
+ * C4X: DIE, IIF, and IIF
+ */
+
+
+typedef struct {
+ unsigned int st;
+ unsigned int ar3;
+ unsigned int ar4;
+ unsigned int ar5;
+ unsigned int ar6;
+ unsigned int ar7;
+ unsigned int r4_sti; /* other part of register is in interrupt context */
+ unsigned int r5_sti; /* other part of register is in interrupt context */
+ unsigned int r6_stf; /* other part of register is in interrupt context */
+ unsigned int r7_stf; /* other part of register is in interrupt context */
+#ifdef _TMS320C40
+ unsigned int r8_sti; /* other part of register is in interrupt context */
+#endif
+ unsigned int sp;
+} Context_Control;
+
+typedef struct {
+} Context_Control_fp;
+
+/*
+ * This is the order the interrupt entry code pushes the registers.
+ */
+
+typedef struct {
+ void *interrupted;
+ unsigned int st;
+ unsigned int ar2; /* because the vector numbers goes here */
+ unsigned int ar0;
+ unsigned int ar1;
+ unsigned int dp;
+ unsigned int ir0;
+ unsigned int ir1;
+ unsigned int rs;
+ unsigned int re;
+ unsigned int rc;
+ unsigned int bk;
+ unsigned int r0_sti;
+ unsigned int r0_stf;
+ unsigned int r1_sti;
+ unsigned int r1_stf;
+ unsigned int r2_sti;
+ unsigned int r2_stf;
+ unsigned int r3_sti;
+ unsigned int r3_stf;
+ unsigned int r4_stf; /* other part of register is in basic context */
+ unsigned int r5_stf; /* other part of register is in basic context */
+ unsigned int r6_sti; /* other part of register is in basic context */
+ unsigned int r7_sti; /* other part of register is in basic context */
+
+#ifdef _TMS320C40
+ unsigned int r8_sti; /* other part of register is in basic context */
+ unsigned int r9_sti;
+ unsigned int r9_stf;
+ unsigned int r10_sti;
+ unsigned int r10_stf;
+ unsigned int r11_sti;
+ unsigned int r11_stf;
+#endif
+
+} CPU_Interrupt_frame;
+
+/*
+ * The following table contains the information required to configure
+ * the C4x processor specific parameters.
+ *
+ * C4x Specific Information:
+ *
+ * XXXanswer
+ */
+
+typedef struct {
+ void (*pretasking_hook)( void );
+ void (*predriver_hook)( void );
+ void (*postdriver_hook)( void );
+ void (*idle_task)( void );
+ boolean do_zero_of_workspace;
+ uint32_t idle_task_stack_size;
+ uint32_t interrupt_stack_size;
+ uint32_t extra_mpci_receive_server_stack;
+ void * (*stack_allocate_hook)( uint32_t );
+ void (*stack_free_hook)( void* );
+ /* end of fields required on all CPUs */
+
+} rtems_cpu_table;
+
+/*
+ * Macros to access required entires in the CPU Table are in
+ * the file rtems/system.h.
+ */
+
+/*
+ * Macros to access C4X specific additions to the CPU Table
+ *
+ * C4x Specific Information:
+ *
+ * XXXanswer
+ */
+
+/* There are no CPU specific additions to the CPU Table for this port. */
+
+#if 0
+/*
+ * This variable is optional. It is used on CPUs on which it is difficult
+ * to generate an "uninitialized" FP context. It is filled in by
+ * _CPU_Initialize and copied into the task's FP context area during
+ * _CPU_Context_Initialize.
+ *
+ * C4x Specific Information:
+ *
+ * Unused
+ */
+
+SCORE_EXTERN Context_Control_fp _CPU_Null_fp_context;
+#endif
+
+/*
+ * On some CPUs, RTEMS supports a software managed interrupt stack.
+ * This stack is allocated by the Interrupt Manager and the switch
+ * is performed in _ISR_Handler. These variables contain pointers
+ * to the lowest and highest addresses in the chunk of memory allocated
+ * for the interrupt stack. Since it is unknown whether the stack
+ * grows up or down (in general), this give the CPU dependent
+ * code the option of picking the version it wants to use.
+ *
+ * NOTE: These two variables are required if the macro
+ * CPU_HAS_SOFTWARE_INTERRUPT_STACK is defined as TRUE.
+ *
+ * C4x Specific Information:
+ *
+ * XXXanswer
+ */
+
+SCORE_EXTERN void *_CPU_Interrupt_stack_low;
+SCORE_EXTERN void *_CPU_Interrupt_stack_high;
+
+/*
+ * With some compilation systems, it is difficult if not impossible to
+ * call a high-level language routine from assembly language. This
+ * is especially true of commercial Ada compilers and name mangling
+ * C++ ones. This variable can be optionally defined by the CPU porter
+ * and contains the address of the routine _Thread_Dispatch. This
+ * can make it easier to invoke that routine at the end of the interrupt
+ * sequence (if a dispatch is necessary).
+ *
+ * C4x Specific Information:
+ *
+ * This port should not require this.
+ */
+
+#if 0
+SCORE_EXTERN void (*_CPU_Thread_dispatch_pointer)();
+#endif
+
+/*
+ * Nothing prevents the porter from declaring more CPU specific variables.
+ *
+ * C4x Specific Information:
+ *
+ * XXXanswer
+ */
+
+/* XXX: if needed, put more variables here */
+
+/*
+ * The size of the floating point context area. On some CPUs this
+ * will not be a "sizeof" because the format of the floating point
+ * area is not defined -- only the size is. This is usually on
+ * CPUs with a "floating point save context" instruction.
+ *
+ * C4x Specific Information:
+ *
+ * If we decide to have a separate floating point context, then
+ * the answer is the size of the data structure. Otherwise, we
+ * need to define it as 0 to let upper level configuration work.
+ */
+
+#if ( C4X_HAS_FPU == 1 )
+#define CPU_CONTEXT_FP_SIZE sizeof( Context_Control_fp )
+#else
+#define CPU_CONTEXT_FP_SIZE 0
+#endif
+
+/*
+ * Amount of extra stack (above minimum stack size) required by
+ * MPCI receive server thread. Remember that in a multiprocessor
+ * system this thread must exist and be able to process all directives.
+ *
+ * C4x Specific Information:
+ *
+ * XXXanswer
+ */
+
+#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 0
+
+/*
+ * This defines the number of entries in the ISR_Vector_table managed
+ * by RTEMS.
+ *
+ * C4x Specific Information:
+ *
+ * Based on the information provided in section 7.6.1 (p. 7-26)
+ * titled "TMS320C30 and TMS320C31 Interrupt Vector Table" and section
+ * 7.6.2 "TMS320C32 Interrupt Vector Table" of the TMS32C3x User's
+ * Guide (rev L, July 1997), vectors are numbered 0x00 - 0x3F. Thus
+ * there are 0x40 or 64 vectors.
+ */
+
+#define CPU_INTERRUPT_NUMBER_OF_VECTORS 0x40
+#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1)
+
+/*
+ * This is defined if the port has a special way to report the ISR nesting
+ * level. Most ports maintain the variable _ISR_Nest_level.
+ */
+
+#define CPU_PROVIDES_ISR_IS_IN_PROGRESS FALSE
+
+/*
+ * Should be large enough to run all RTEMS tests. This insures
+ * that a "reasonable" small application should not have any problems.
+ *
+ * C4x Specific Information:
+ *
+ * XXXanswer
+ */
+
+#define CPU_STACK_MINIMUM_SIZE (1024)
+
+/*
+ * CPU's worst alignment requirement for data types on a byte boundary. This
+ * alignment does not take into account the requirements for the stack.
+ *
+ * C4x Specific Information:
+ *
+ * XXXanswer
+ * As best I can tell, there are no restrictions since this is a word
+ * -- not byte -- oriented archtiecture.
+ */
+
+#define CPU_ALIGNMENT 0
+
+/*
+ * This number corresponds to the byte alignment requirement for the
+ * heap handler. This alignment requirement may be stricter than that
+ * for the data types alignment specified by CPU_ALIGNMENT. It is
+ * common for the heap to follow the same alignment requirement as
+ * CPU_ALIGNMENT. If the CPU_ALIGNMENT is strict enough for the heap,
+ * then this should be set to CPU_ALIGNMENT.
+ *
+ * NOTE: This does not have to be a power of 2. It does have to
+ * be greater or equal to than CPU_ALIGNMENT.
+ *
+ * C4x Specific Information:
+ *
+ * XXXanswer
+ *
+ * A CPU_HEAP_ALIGNMENT of 2 comes close to disabling all the rounding
+ * while still ensuring that the least significant bit of the front
+ * and back flags can be used as the used bit -- not part of the size.
+ */
+
+#define CPU_HEAP_ALIGNMENT 2
+
+/*
+ * This number corresponds to the byte alignment requirement for memory
+ * buffers allocated by the partition manager. This alignment requirement
+ * may be stricter than that for the data types alignment specified by
+ * CPU_ALIGNMENT. It is common for the partition to follow the same
+ * alignment requirement as CPU_ALIGNMENT. If the CPU_ALIGNMENT is strict
+ * enough for the partition, then this should be set to CPU_ALIGNMENT.
+ *
+ * NOTE: This does not have to be a power of 2. It does have to
+ * be greater or equal to than CPU_ALIGNMENT.
+ *
+ * C4x Specific Information:
+ *
+ * XXXanswer
+ * I think a CPU_PARTITION_ALIGNMENT of 1 will effectively disable all
+ * the rounding.
+ */
+
+#define CPU_PARTITION_ALIGNMENT 1
+
+/*
+ * This number corresponds to the byte alignment requirement for the
+ * stack. This alignment requirement may be stricter than that for the
+ * data types alignment specified by CPU_ALIGNMENT. If the CPU_ALIGNMENT
+ * is strict enough for the stack, then this should be set to 0.
+ *
+ * NOTE: This must be a power of 2 either 0 or greater than CPU_ALIGNMENT.
+ *
+ * C4x Specific Information:
+ *
+ * XXXanswer
+ */
+
+#define CPU_STACK_ALIGNMENT 0
+
+/*
+ * ISR handler macros
+ *
+ * C4x Specific Information:
+ *
+ * These macros disable interrupts using the GIE (global interrupts enable)
+ * bit in the status word.
+ */
+
+/*
+ * Support routine to initialize the RTEMS vector table after it is allocated.
+ */
+
+#define _CPU_Initialize_vectors()
+
+/*
+ * Disable all interrupts for an RTEMS critical section. The previous
+ * level is returned in _isr_cookie.
+ */
+
+#define _CPU_ISR_Disable( _isr_cookie ) \
+ do { \
+ (_isr_cookie) = c4x_global_interrupts_get(); \
+ c4x_global_interrupts_disable(); \
+ } while (0)
+
+/*
+ * Enable interrupts to the previous level (returned by _CPU_ISR_Disable).
+ * This indicates the end of an RTEMS critical section. The parameter
+ * _isr_cookie is not modified.
+ */
+
+#define _CPU_ISR_Enable( _isr_cookie ) \
+ c4x_global_interrupts_restore( _isr_cookie )
+
+/*
+ * This temporarily restores the interrupt to _isr_cookie before immediately
+ * disabling them again. This is used to divide long RTEMS critical
+ * sections into two or more parts. The parameter _isr_cookie is not
+ * modified.
+ */
+
+#define _CPU_ISR_Flash( _isr_cookie ) \
+ c4x_global_interrupts_flash( _isr_cookie )
+
+/*
+ * Map interrupt level in task mode onto the hardware that the CPU
+ * actually provides. Currently, interrupt levels which do not
+ * map onto the CPU in a generic fashion are undefined. Someday,
+ * it would be nice if these were "mapped" by the application
+ * via a callout. For example, m68k has 8 levels 0 - 7, levels
+ * 8 - 255 would be available for bsp/application specific meaning.
+ * This could be used to manage a programmable interrupt controller
+ * via the rtems_task_mode directive.
+ *
+ * The get routine usually must be implemented as a subroutine.
+ *
+ * C4x Specific Information:
+ *
+ * The C4x port probably needs to allow the BSP to define
+ * a mask table for all values 0-255. For now, 0 is global
+ * interrupts enabled and and non-zero is global interrupts
+ * disabled. In the future, values 1-254 could be defined as
+ * specific combinations of the global interrupt enabled and the IE mask.
+ *
+ * The logic for setting the mask field is something like this:
+ * _ie_value = c4x_get_ie();
+ * _ie_value &= C4X_IE_INTERRUPT_MASK_BITS;
+ * _ie_value |= _ie_mask;
+ * c4x_set_ie(_ie_value);
+ *
+ * NOTE: If this is implemented, then the context of each task
+ * must be extended to include the IE register.
+ */
+
+#define _CPU_ISR_Set_level( _new_level ) \
+ do { \
+ if ( _new_level == 0 ) c4x_global_interrupts_enable(); \
+ else c4x_global_interrupts_disable(); \
+ } while (0)
+
+/* if GIE = 1, then logical level is 0. */
+#define _CPU_ISR_Get_level() \
+ (c4x_global_interrupts_get() ? 0 : 1)
+
+
+/* end of ISR handler macros */
+
+/* Context handler macros */
+
+/*
+ * Initialize the context to a state suitable for starting a
+ * task after a context restore operation. Generally, this
+ * involves:
+ *
+ * - setting a starting address
+ * - preparing the stack
+ * - preparing the stack and frame pointers
+ * - setting the proper interrupt level in the context
+ * - initializing the floating point context
+ *
+ * This routine generally does not set any unnecessary register
+ * in the context. The state of the "general data" registers is
+ * undefined at task start time.
+ *
+ * NOTE: This is_fp parameter is TRUE if the thread is to be a floating
+ * point thread. This is typically only used on CPUs where the
+ * FPU may be easily disabled by software such as on the SPARC
+ * where the PSR contains an enable FPU bit.
+ *
+ * C4x Specific Information:
+ *
+ * XXXanswer
+ */
+
+void _CPU_Context_Initialize(
+ Context_Control *_the_context,
+ void *_stack_base,
+ uint32_t _size,
+ uint32_t _isr,
+ void (*_entry_point)(void),
+ int _is_fp
+);
+
+/*
+ * This routine is responsible for somehow restarting the currently
+ * executing task. If you are lucky, then all that is necessary
+ * is restoring the context. Otherwise, there will need to be
+ * a special assembly routine which does something special in this
+ * case. Context_Restore should work most of the time. It will
+ * not work if restarting self conflicts with the stack frame
+ * assumptions of restoring a context.
+ *
+ * C4x Specific Information:
+ *
+ * XXXanswer
+ */
+
+#define _CPU_Context_Restart_self( _the_context ) \
+ _CPU_Context_restore( (_the_context) );
+
+#if ( C4X_HAS_FPU == 1 )
+/*
+ * The purpose of this macro is to allow the initial pointer into
+ * a floating point context area (used to save the floating point
+ * context) to be at an arbitrary place in the floating point
+ * context area.
+ *
+ * This is necessary because some FP units are designed to have
+ * their context saved as a stack which grows into lower addresses.
+ * Other FP units can be saved by simply moving registers into offsets
+ * from the base of the context area. Finally some FP units provide
+ * a "dump context" instruction which could fill in from high to low
+ * or low to high based on the whim of the CPU designers.
+ *
+ * C4x Specific Information:
+ *
+ * No Floating Point from RTEMS perspective.
+ */
+
+#define _CPU_Context_Fp_start( _base, _offset ) \
+ ( (void *) _Addresses_Add_offset( (_base), (_offset) ) )
+#endif
+
+#if ( C4X_HAS_FPU == 1 )
+/*
+ * This routine initializes the FP context area passed to it to.
+ * There are a few standard ways in which to initialize the
+ * floating point context. The code included for this macro assumes
+ * that this is a CPU in which a "initial" FP context was saved into
+ * _CPU_Null_fp_context and it simply copies it to the destination
+ * context passed to it.
+ *
+ * Other models include (1) not doing anything, and (2) putting
+ * a "null FP status word" in the correct place in the FP context.
+ *
+ * C4x Specific Information:
+ *
+ * No Floating Point from RTEMS perspective.
+ */
+
+#define _CPU_Context_Initialize_fp( _destination ) \
+ do { \
+ *((Context_Control_fp *) *((void **) _destination)) = _CPU_Null_fp_context; \
+ } while (0)
+#endif
+
+/* end of Context handler macros */
+
+/* Fatal Error manager macros */
+
+/*
+ * This routine copies _error into a known place -- typically a stack
+ * location or a register, optionally disables interrupts, and
+ * halts/stops the CPU.
+ *
+ * C4x Specific Information:
+ *
+ * XXXanswer
+ */
+
+#define _CPU_Fatal_halt( _error ) \
+ do { \
+ } while (0)
+
+/* end of Fatal Error manager macros */
+
+/* Bitfield handler macros */
+
+/*
+ * This routine sets _output to the bit number of the first bit
+ * set in _value. _value is of CPU dependent type Priority_Bit_map_control.
+ * This type may be either 16 or 32 bits wide although only the 16
+ * least significant bits will be used.
+ *
+ * There are a number of variables in using a "find first bit" type
+ * instruction.
+ *
+ * (1) What happens when run on a value of zero?
+ * (2) Bits may be numbered from MSB to LSB or vice-versa.
+ * (3) The numbering may be zero or one based.
+ * (4) The "find first bit" instruction may search from MSB or LSB.
+ *
+ * RTEMS guarantees that (1) will never happen so it is not a concern.
+ * (2),(3), (4) are handled by the macros _CPU_Priority_mask() and
+ * _CPU_Priority_bits_index(). These three form a set of routines
+ * which must logically operate together. Bits in the _value are
+ * set and cleared based on masks built by _CPU_Priority_mask().
+ * The basic major and minor values calculated by _Priority_Major()
+ * and _Priority_Minor() are "massaged" by _CPU_Priority_bits_index()
+ * to properly range between the values returned by the "find first bit"
+ * instruction. This makes it possible for _Priority_Get_highest() to
+ * calculate the major and directly index into the minor table.
+ * This mapping is necessary to ensure that 0 (a high priority major/minor)
+ * is the first bit found.
+ *
+ * This entire "find first bit" and mapping process depends heavily
+ * on the manner in which a priority is broken into a major and minor
+ * components with the major being the 4 MSB of a priority and minor
+ * the 4 LSB. Thus (0 << 4) + 0 corresponds to priority 0 -- the highest
+ * priority. And (15 << 4) + 14 corresponds to priority 254 -- the next
+ * to the lowest priority.
+ *
+ * If your CPU does not have a "find first bit" instruction, then
+ * there are ways to make do without it. Here are a handful of ways
+ * to implement this in software:
+ *
+ * - a series of 16 bit test instructions
+ * - a "binary search using if's"
+ * - _number = 0
+ * if _value > 0x00ff
+ * _value >>=8
+ * _number = 8;
+ *
+ * if _value > 0x0000f
+ * _value >=8
+ * _number += 4
+ *
+ * _number += bit_set_table[ _value ]
+ *
+ * where bit_set_table[ 16 ] has values which indicate the first
+ * bit set
+ *
+ * C4x Specific Information:
+ *
+ * There does not appear to be a simple way to do this on this
+ * processor family that is better than the generic algorithm.
+ * Almost certainly, a hand-optimized assembly version of the
+ * generic algorithm could be written although it is not
+ * worth the development effort at this time.
+ */
+
+#define CPU_USE_GENERIC_BITFIELD_CODE TRUE
+#define CPU_USE_GENERIC_BITFIELD_DATA TRUE
+
+#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
+
+#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
+ do { \
+ (_output) = 0; /* do something to prevent warnings */ \
+ } while (0)
+
+#endif
+
+/* end of Bitfield handler macros */
+
+/*
+ * This routine builds the mask which corresponds to the bit fields
+ * as searched by _CPU_Bitfield_Find_first_bit(). See the discussion
+ * for that routine.
+ *
+ * C4x Specific Information:
+ *
+ * XXXanswer
+ */
+
+#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
+
+#define _CPU_Priority_Mask( _bit_number ) \
+ ( 1 << (_bit_number) )
+
+#endif
+
+/*
+ * This routine translates the bit numbers returned by
+ * _CPU_Bitfield_Find_first_bit() into something suitable for use as
+ * a major or minor component of a priority. See the discussion
+ * for that routine.
+ *
+ * C4x Specific Information:
+ *
+ * XXXanswer
+ */
+
+#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
+
+#define _CPU_Priority_bits_index( _priority ) \
+ (_priority)
+
+#endif
+
+/* end of Priority handler macros */
+
+/* functions */
+
+/*
+ * _CPU_Initialize
+ *
+ * This routine performs CPU dependent initialization.
+ *
+ * C4x Specific Information:
+ *
+ * XXXanswer
+ */
+
+void _CPU_Initialize(
+ rtems_cpu_table *cpu_table,
+ void (*thread_dispatch)
+);
+
+/*
+ * _CPU_ISR_install_raw_handler
+ *
+ * This routine installs a "raw" interrupt handler directly into the
+ * processor's vector table.
+ *
+ * C4x Specific Information:
+ *
+ * XXXanswer
+ */
+
+void _CPU_ISR_install_raw_handler(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+);
+
+/*
+ * _CPU_ISR_install_vector
+ *
+ * This routine installs an interrupt vector.
+ *
+ * C4x Specific Information:
+ *
+ * XXXanswer
+ */
+
+void _CPU_ISR_install_vector(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+);
+
+/*
+ * _CPU_Thread_Idle_body
+ *
+ * This routine is the CPU dependent IDLE thread body.
+ *
+ * NOTE: It need only be provided if CPU_PROVIDES_IDLE_THREAD_BODY
+ *
+ * C4x Specific Information:
+ *
+ * XXXanswer
+ * is TRUE.
+ */
+
+#if (CPU_PROVIDES_IDLE_THREAD_BODY == 1)
+void _CPU_Thread_Idle_body( void );
+#endif
+
+/*
+ * _CPU_Context_switch
+ *
+ * This routine switches from the run context to the heir context.
+ *
+ * C4x Specific Information:
+ *
+ * XXXanswer
+ */
+
+void _CPU_Context_switch(
+ Context_Control *run,
+ Context_Control *heir
+);
+
+/*
+ * _CPU_Context_restore
+ *
+ * This routine is generally used only to restart self in an
+ * efficient manner. It may simply be a label in _CPU_Context_switch.
+ *
+ * NOTE: May be unnecessary to reload some registers.
+ *
+ * C4x Specific Information:
+ *
+ * XXXanswer
+ */
+
+void _CPU_Context_restore(
+ Context_Control *new_context
+);
+
+/*
+ * _CPU_Context_save_fp
+ *
+ * This routine saves the floating point context passed to it.
+ *
+ * C4x Specific Information:
+ *
+ * No Floating Point from RTEMS perspective.
+ */
+
+#if ( C4X_HAS_FPU == 1 )
+void _CPU_Context_save_fp(
+ void **fp_context_ptr
+);
+#endif
+
+/*
+ * _CPU_Context_restore_fp
+ *
+ * This routine restores the floating point context passed to it.
+ *
+ * C4x Specific Information:
+ *
+ * No Floating Point from RTEMS perspective.
+ */
+
+#if ( C4X_HAS_FPU == 1 )
+void _CPU_Context_restore_fp(
+ void **fp_context_ptr
+);
+#endif
+
+/* The following routine swaps the endian format of an unsigned int.
+ * It must be static because it is referenced indirectly.
+ *
+ * This version will work on any processor, but if there is a better
+ * way for your CPU PLEASE use it. The most common way to do this is to:
+ *
+ * swap least significant two bytes with 16-bit rotate
+ * swap upper and lower 16-bits
+ * swap most significant two bytes with 16-bit rotate
+ *
+ * Some CPUs have special instructions which swap a 32-bit quantity in
+ * a single instruction (e.g. i486). It is probably best to avoid
+ * an "endian swapping control bit" in the CPU. One good reason is
+ * that interrupts would probably have to be disabled to insure that
+ * an interrupt does not try to access the same "chunk" with the wrong
+ * endian. Another good reason is that on some CPUs, the endian bit
+ * endianness for ALL fetches -- both code and data -- so the code
+ * will be fetched incorrectly.
+ *
+ * C4x Specific Information:
+ *
+ * XXXanswer
+ */
+
+static inline unsigned int CPU_swap_u32(
+ unsigned int value
+)
+{
+ uint32_t byte1, byte2, byte3, byte4, swapped;
+
+ byte4 = (value >> 24) & 0xff;
+ byte3 = (value >> 16) & 0xff;
+ byte2 = (value >> 8) & 0xff;
+ byte1 = value & 0xff;
+
+ swapped = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
+ return( swapped );
+}
+
+#define CPU_swap_u16( value ) \
+ (((value&0xff) << 8) | ((value >> 8)&0xff))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/score/cpu/c4x/rtems/score/cpu_asm.h b/cpukit/score/cpu/c4x/rtems/score/cpu_asm.h
new file mode 100644
index 0000000000..70e9b2fd4a
--- /dev/null
+++ b/cpukit/score/cpu/c4x/rtems/score/cpu_asm.h
@@ -0,0 +1,70 @@
+/*
+ * cpu_asm.h
+ *
+ * Very loose template for an include file for the cpu_asm.? file
+ * if it is implemented as a ".S" file (preprocessed by cpp) instead
+ * of a ".s" file (preprocessed by gm4 or gasp).
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ *
+ */
+
+#ifndef __CPU_ASM_h
+#define __CPU_ASM_h
+
+/* pull in the generated offsets */
+
+#include <rtems/score/offsets.h>
+
+/*
+ * Hardware General Registers
+ */
+
+/* put something here */
+
+/*
+ * Hardware Floating Point Registers
+ */
+
+/* put something here */
+
+/*
+ * Hardware Control Registers
+ */
+
+/* put something here */
+
+/*
+ * Calling Convention
+ */
+
+/* put something here */
+
+/*
+ * Temporary registers
+ */
+
+/* put something here */
+
+/*
+ * Floating Point Registers - SW Conventions
+ */
+
+/* put something here */
+
+/*
+ * Temporary floating point registers
+ */
+
+/* put something here */
+
+#endif
+
+/* end of file */
diff --git a/cpukit/score/cpu/c4x/rtems/score/types.h b/cpukit/score/cpu/c4x/rtems/score/types.h
new file mode 100644
index 0000000000..d767400db4
--- /dev/null
+++ b/cpukit/score/cpu/c4x/rtems/score/types.h
@@ -0,0 +1,56 @@
+/* c4xtypes.h
+ *
+ * This include file contains type definitions pertaining to the Intel
+ * C4x processor family.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __C4X_TYPES_h
+#define __C4X_TYPES_h
+
+#ifndef ASM
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This section defines the basic types for this processor.
+ */
+
+typedef unsigned char unsigned8; /* unsigned 8-bit integer */
+typedef unsigned short unsigned16; /* unsigned 16-bit integer */
+typedef unsigned int unsigned32; /* unsigned 32-bit integer */
+typedef unsigned long long unsigned64; /* unsigned 64-bit integer */
+
+typedef unsigned16 Priority_Bit_map_control;
+
+typedef signed char signed8; /* 8-bit signed integer */
+typedef signed short signed16; /* 16-bit signed integer */
+typedef signed int signed32; /* 32-bit signed integer */
+typedef signed long long signed64; /* 64 bit signed integer */
+
+typedef unsigned32 boolean; /* Boolean value */
+
+typedef float single_precision; /* single precision float */
+typedef double double_precision; /* double precision float */
+
+typedef void c4x_isr;
+typedef void ( *c4x_isr_entry )( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !ASM */
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/c4x/rtems/tic4x/c4xio.h b/cpukit/score/cpu/c4x/rtems/tic4x/c4xio.h
new file mode 100644
index 0000000000..d398211dfb
--- /dev/null
+++ b/cpukit/score/cpu/c4x/rtems/tic4x/c4xio.h
@@ -0,0 +1,110 @@
+/*
+ * C4X IO Information
+ *
+ * $Id$
+ */
+
+#ifndef __C4XIO_h
+#define __C4XIO_h
+
+/*
+ * Address defines
+ */
+
+#ifdef _TMS320C40
+#define C4X_TIMER_0 ((struct c4x_timer*)0x100020)
+#else
+#define C4X_TIMER_0 ((struct c4x_timer*)0x808020)
+#define C4X_TIMER_1 ((struct c4x_timer*)0x808030)
+#endif
+
+/* XXX how portable */
+
+/* C32 Internal Control Registers */
+#define C4X_STRB0_REG 0x808064
+#define C4X_STRB1_REG 0x808068
+#define C4X_IOSTRB_REG 0x808060
+
+/* C32 Internal RAM Locations */
+/* XXX how long */
+#define C4X_RAM_BLK_0 0x87fe00
+#define C4X_RAM_BLK_1 0x87ff00
+
+/*
+ * Data Structures to Overlay the Peripherals on the CPU
+ */
+
+struct c4x_timer {
+ volatile int tcontrol;
+ volatile int r1[3];
+ volatile int tcounter;
+ volatile int r2[3];
+ volatile int tperiod;
+};
+
+
+
+
+/*
+ * Timer Support Routines
+ *
+ * The following section of C4x timer code is based on C40 specific
+ * timer code from Ran Cabell <rcabell@norfolk.infi.net>. The
+ * only C3x/C4x difference spotted was the address of the timer.
+ * The names have been changed to be more RTEMS like.
+ */
+
+#define c4x_timer_get_control( _timer ) (volatile int)(_timer->tcontrol)
+
+#define c4x_timer_set_control( _timer, _value ) \
+ do { \
+ (volatile int)(_timer->tcontrol) = _value; \
+ } while (0);
+
+#define c4x_timer_start( _timer ) \
+ c4x_timer_set_control(_timer, 0x02c1 )
+
+#define c4x_timer_stop( _timer ) _timer->tcontrol = 0
+
+#define c4x_timer_get_counter( _timer ) (volatile int)(_timer->tcounter)
+
+#define c4x_timer_set_counter( _timer, _value ) \
+ do { \
+ (volatile int)(_timer->tcounter) = _value; \
+ } while (0);
+
+#define c4x_timer_get_period( _timer ) (volatile int)(_timer->tperiod)
+
+#define c4x_timer_set_period( _timer, _value ) \
+ do { \
+ (volatile int)(_timer->tperiod) = _value; \
+ } while (0);
+
+/*
+ * IO Flags
+ *
+ * NOTE: iof on c3x, iiof on c4x
+ */
+
+#ifdef _TMS320C40
+
+#else
+
+static inline uint32_t c3x_get_iof( void )
+{
+ register uint32_t iof_value;
+
+ __asm__ volatile ("ldi iof, %0" : "=r" (iof_value));
+ return iof_value;
+}
+
+static inline void c3x_set_iof( uint32_t value )
+{
+ __asm__ volatile ("ldi %0,iof" : : "g" (value) : "iof", "cc");
+}
+
+#endif
+
+
+#endif
+/* end if include file */
diff --git a/cpukit/score/cpu/h8300/.cvsignore b/cpukit/score/cpu/h8300/.cvsignore
new file mode 100644
index 0000000000..282522db03
--- /dev/null
+++ b/cpukit/score/cpu/h8300/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/cpukit/score/cpu/h8300/ChangeLog b/cpukit/score/cpu/h8300/ChangeLog
new file mode 100644
index 0000000000..b6192d6643
--- /dev/null
+++ b/cpukit/score/cpu/h8300/ChangeLog
@@ -0,0 +1,256 @@
+2004-04-06 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * configure.ac: Remove (Merged into $(top_srcdir)/configure.ac).
+ * Makefile.am: Don't include multilib.am.
+ Reflect merging configure.ac into $(top_srcdir)/configure.ac.
+
+2004-04-01 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * Makefile.am: Install asm.h to $(includedir)/rtems.
+
+2004-03-30 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * cpu.c, rtems/score/cpu.h: Convert to using c99 fixed size types.
+
+2004-03-29 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * configure.ac: RTEMS_TOP([../../../..]).
+
+2004-01-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Move RTEMS_TOP one subdir down.
+
+2004-01-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add PREINSTALL_DIRS.
+
+2004-01-14 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Re-add dirstamps to PREINSTALL_FILES.
+ Add PREINSTALL_FILES to CLEANFILES.
+
+2004-01-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Requires automake >= 1.8.1.
+
+2004-01-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include compile.am, again.
+
+2004-01-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Convert to using automake compilation rules.
+
+2003-12-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use mkdir_p. Remove dirs from PREINSTALL_FILES.
+
+2003-12-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Require automake >= 1.8, autoconf >= 2.59.
+
+2003-12-01 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Remove TMPINSTALL_FILES.
+
+2003-11-30 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add $(dirstamp) to preinstallation rules.
+
+2003-11-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Don't use gmake rules for preinstallation.
+
+2003-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_CANONICAL_HOST.
+
+2003-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_CHECK_CPU.
+
+2003-09-26 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/cpu.h: Obsoleting HP PA-RISC port and removing all
+ references.
+
+2003-09-04 Joel Sherrill <joel@OARcorp.com>
+
+ * asm.h, cpu.c, cpu_asm.S, rtems/score/cpu.h, rtems/score/h8300.h,
+ rtems/score/types.h: URL for license changed.
+
+2003-08-14 Joel Sherrill <joel@OARcorp.com>
+
+ PR 455/bsps
+ * rtems/score/cpu.h: Added missing CPU_swap_u16().
+
+2003-08-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use rtems-bugs@rtems.com as bug report email address.
+
+2003-03-06 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove AC_CONFIG_AUX_DIR.
+
+2002-12-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Require autoconf-2.57 + automake-1.7.2.
+ * Makefile.am: Eliminate C_O_FILES, S_O_FILES, libscorecpu_a_OBJECTS.
+
+2002-11-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Fix package name.
+
+2002-11-06 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/score/cpu.h: Add prototype of H8BD_Install_IRQ to eliminate
+ warning.
+
+2002-10-25 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Add nostdinc to AM_INIT_AUTOMAKE.
+
+2002-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * .cvsignore: Reformat.
+ Add autom4te*cache.
+ Remove autom4te.cache.
+
+2002-07-26 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Build libscorecpu.a instead of rtems-cpu.rel.
+
+2002-07-22 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use .$(OBJEXT) instead of .o.
+
+2002-07-22 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use . instead of .o.
+
+2002-07-05 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/cpu.h: Filled in something that was marked XXX.
+
+2002-07-05 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: RTEMS_TOP(../../../..).
+
+2002-07-04 Joel Sherrill <joel@OARcorp.com>
+
+ * Makefile.am: Remove reference to deprecated rtems.c.
+
+2002-07-03 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems.c: Remove.
+ * Makefile.am: Reflect changes above.
+
+2002-07-01 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/cpu.h: Fixed comments and renamed
+ CPU_SYSTEM_INITIALIZATION_THREAD_EXTRA_STACK to
+ CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK to be consistent with other code.
+
+2002-07-01 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_PROJECT_ROOT.
+
+2002-06-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Add RTEMS_PROG_CCAS
+
+2002-06-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use AC_CONFIG_AUX_DIR(../../../..).
+ Add AC_PROG_RANLIB.
+
+2002-06-17 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include $(top_srcdir)/../../../automake/*.am.
+ Use ../../../aclocal.
+
+2001-04-03 Joel Sherrill <joel@OARcorp.com>
+
+ * Per PR94, all rtems/score/CPUtypes.h are named rtems/score/types.h.
+ * rtems/score/h8300types.h: Removed.
+ * rtems/score/types.h: New file via CVS magic.
+ * Makefile.am, rtems/score/cpu.h: Account for name change.
+
+2002-03-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac:
+ AC_INIT(package,_RTEMS_VERSION,_RTEMS_BUGS).
+ AM_INIT_AUTOMAKE([no-define foreign 1.6]).
+ * Makefile.am: Remove AUTOMAKE_OPTIONS.
+
+2002-01-29 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/Makefile.am: Removed.
+ * rtems/score/Makefile.am: Removed.
+ * configure.ac: Reflect changes above.
+ * Makefile.am: Reflect changes above.
+
+2002-01-07 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/score/cpu.h: #include <rtems/bspIo.h>.
+
+2001-12-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add multilib support.
+
+2001-11-28 Joel Sherrill <joel@OARcorp.com>,
+
+ This was tracked as PR91.
+ * rtems/score/cpu.h: Added CPU_PROVIDES_ISR_IS_IN_PROGRESS macro which
+ is used to specify if the port uses the standard macro for this (FALSE).
+ A TRUE setting indicates the port provides its own implementation.
+
+2001-10-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * .cvsignore: Add autom4te.cache for autoconf > 2.52.
+ * configure.in: Remove.
+ * configure.ac: New file, generated from configure.in by autoupdate.
+
+2001-09-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/score/Makefile.am: Use 'PREINSTALL_FILES ='.
+ * Makefile.am: Use 'PREINSTALL_FILES ='.
+
+2001-02-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am, rtems/score/Makefile.am:
+ Apply include_*HEADERS instead of H_FILES.
+
+2001-01-03 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/cpu.h: Added _CPU_Initialize_vectors().
+ * cpu_asm.S: Modify to properly dereference _ISR_Vector_table
+ now that it is dynamically allocated.
+
+2000-11-09 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use ... instead of RTEMS_TOPdir in ACLOCAL_AMFLAGS.
+
+2000-11-02 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Switch to ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal.
+
+2000-10-25 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: ACLOCAL_AMFLAGS= -I $(RTEMS_TOPdir)/macros.
+ Switch to GNU canonicalization.
+
+2000-10-18 Joel Sherrill <joel@OARcorp.com>
+
+ * cpu_asm.S, rtems/score/cpu.h: Modified to better support
+ multilibing. These changes result in the code being able to
+ compile with the default gcc settings. It is not functional
+ in this configuration but does compile.
+
+2000-09-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include compile.am.
+
+2000-08-10 Joel Sherrill <joel@OARcorp.com>
+
+ * ChangeLog: New file.
diff --git a/cpukit/score/cpu/h8300/Makefile.am b/cpukit/score/cpu/h8300/Makefile.am
new file mode 100644
index 0000000000..328037e175
--- /dev/null
+++ b/cpukit/score/cpu/h8300/Makefile.am
@@ -0,0 +1,58 @@
+##
+## $Id$
+##
+
+include $(top_srcdir)/automake/compile.am
+
+include_rtemsdir = $(includedir)/rtems
+include_rtems_HEADERS = asm.h
+
+include_rtems_scoredir = $(includedir)/rtems/score
+include_rtems_score_HEADERS = rtems/score/cpu.h rtems/score/h8300.h \
+ rtems/score/types.h
+
+EXTRA_LIBRARIES = libscorecpu.a
+CLEANFILES = libscorecpu.a
+libscorecpu_a_SOURCES = cpu.c cpu_asm.S
+libscorecpu_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libscorecpu_g.a
+CLEANFILES += libscorecpu_g.a
+libscorecpu_g_a_SOURCES = $(libscorecpu_a_SOURCES)
+libscorecpu_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+all-local: $(PREINSTALL_FILES) libscorecpu$(LIB_VARIANT).a
+
+PREINSTALL_DIRS =
+PREINSTALL_FILES =
+
+$(PROJECT_INCLUDE)/rtems/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems
+ @: > $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/asm.h: asm.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/asm.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/asm.h
+
+$(PROJECT_INCLUDE)/rtems/score/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems/score
+ @: > $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/score/cpu.h: rtems/score/cpu.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/cpu.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/cpu.h
+
+$(PROJECT_INCLUDE)/rtems/score/h8300.h: rtems/score/h8300.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/h8300.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/h8300.h
+
+$(PROJECT_INCLUDE)/rtems/score/types.h: rtems/score/types.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/types.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/types.h
+
+CLEANFILES += $(PREINSTALL_FILES)
+DISTCLEANFILES = $(PREINSTALL_DIRS)
+
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/score/cpu/h8300/README b/cpukit/score/cpu/h8300/README
new file mode 100644
index 0000000000..a55c61c662
--- /dev/null
+++ b/cpukit/score/cpu/h8300/README
@@ -0,0 +1,31 @@
+#
+# $Id$
+#
+
+
+This port was done by Philip Quaife <philip@qs.co.nz> of Q Solutions
+using RTEMS 3.5.1 under DOS and Hiview. Philip used an H8300H
+to develop and test this port.
+
+It was updated to 4.5 and merged into the main development trunk
+by Joel Sherrill <joel@OARcorp.com>. As part of the merger, the
+port was made to conditionally compile for the H8, H8300H, and H8300S
+series.
+
+The status of each CPU subfamily is as follows.
+
+H8 - Although RTEMS compiles with for these CPUs, it does not
+ truly support them. All code that will not work on these
+ CPUs is conditionally disabled. These CPUs have a 16-bit
+ address space. Thus although a port is technically
+ feasible, some work will to be performed on RTEMS to
+ further minimize its footprint and address pointer
+ manipulation issues.
+
+H8H - Port was developed on this class of H8 so there should be
+ no problems.
+
+H8S - Port should work on this class of H8 but it is untested.
+
+--joel
+28 June 2000
diff --git a/cpukit/score/cpu/h8300/asm.h b/cpukit/score/cpu/h8300/asm.h
new file mode 100644
index 0000000000..1d5f565532
--- /dev/null
+++ b/cpukit/score/cpu/h8300/asm.h
@@ -0,0 +1,122 @@
+/* asm.h
+ *
+ * This include file attempts to address the problems
+ * caused by incompatible flavors of assemblers and
+ * toolsets. It primarily addresses variations in the
+ * use of leading underscores on symbols and the requirement
+ * that register names be preceded by a %.
+ *
+ *
+ * NOTE: The spacing in the use of these macros
+ * is critical to them working as advertised.
+ *
+ * COPYRIGHT:
+ *
+ * This file is based on similar code found in newlib available
+ * from ftp.cygnus.com. The file which was used had no copyright
+ * notice. This file is freely distributable as long as the source
+ * of the file is noted. This file is:
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __H8300_CPU_ASM_h
+#define __H8300_CPU_ASM_h
+
+/*
+ * Indicate we are in an assembly file and get the basic CPU definitions.
+ */
+
+#define ASM
+#include <rtems/score/h8300.h>
+
+/*
+ * Recent versions of GNU cpp define variables which indicate the
+ * need for underscores and percents. If not using GNU cpp or
+ * the version does not support this, then you will obviously
+ * have to define these as appropriate.
+ */
+
+#ifndef __USER_LABEL_PREFIX__
+#define __USER_LABEL_PREFIX__ _
+#endif
+
+#ifndef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__
+#endif
+
+/* ANSI concatenation macros. */
+
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+/* Use the right prefix for global labels. */
+
+#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+
+/* Use the right prefix for registers. */
+
+#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
+
+/*
+ * define macros for all of the registers on this CPU
+ *
+ * EXAMPLE: #define d0 REG (d0)
+ */
+#define r0 REG(r0)
+#define r1 REG(r1)
+#define r2 REG(r2)
+#define r3 REG(r3)
+#define r4 REG(r4)
+#define r5 REG(r5)
+#define r6 REG(r6)
+#define r7 REG(r7)
+
+#define er0 REG(er0)
+#define er1 REG(er1)
+#define er2 REG(er2)
+#define er3 REG(er3)
+#define er4 REG(er4)
+#define er5 REG(er5)
+#define er6 REG(er6)
+#define er7 REG(er7)
+
+#define sp REG(sp)
+
+/*
+ * Define macros to handle section beginning and ends.
+ */
+
+
+#define BEGIN_CODE_DCL .text
+#define END_CODE_DCL
+#define BEGIN_DATA_DCL .data
+#define END_DATA_DCL
+#define BEGIN_CODE asm ( ".text
+#define END_CODE ");
+#define BEGIN_DATA
+#define END_DATA
+#define BEGIN_BSS
+#define END_BSS
+#define END
+
+/*
+ * Following must be tailor for a particular flavor of the C compiler.
+ * They may need to put underscores in front of the symbols.
+ */
+
+#define PUBLIC(sym) .globl SYM (sym)
+#define EXTERN(sym) .globl SYM (sym)
+
+#endif
+/* end of include file */
+
+ asm( \".h8300h\" );
diff --git a/cpukit/score/cpu/h8300/cpu.c b/cpukit/score/cpu/h8300/cpu.c
new file mode 100644
index 0000000000..f49978bb55
--- /dev/null
+++ b/cpukit/score/cpu/h8300/cpu.c
@@ -0,0 +1,174 @@
+/*
+ * Hitachi H8300 CPU Dependent Source
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/wkspace.h>
+
+/* _CPU_Initialize
+ *
+ * This routine performs processor dependent initialization.
+ *
+ * INPUT PARAMETERS:
+ * cpu_table - CPU table to initialize
+ * thread_dispatch - address of disptaching routine
+ */
+
+
+void _CPU_Initialize(
+ rtems_cpu_table *cpu_table,
+ void (*thread_dispatch) /* ignored on this CPU */
+)
+{
+ /*
+ * The thread_dispatch argument is the address of the entry point
+ * for the routine called at the end of an ISR once it has been
+ * decided a context switch is necessary. On some compilation
+ * systems it is difficult to call a high-level language routine
+ * from assembly. This allows us to trick these systems.
+ *
+ * If you encounter this problem save the entry point in a CPU
+ * dependent variable.
+ */
+
+ _CPU_Thread_dispatch_pointer = thread_dispatch;
+
+ /*
+ * If there is not an easy way to initialize the FP context
+ * during Context_Initialize, then it is usually easier to
+ * save an "uninitialized" FP context here and copy it to
+ * the task's during Context_Initialize.
+ */
+
+ /* FP context initialization support goes here */
+
+ _CPU_Table = *cpu_table;
+}
+
+/*PAGE
+ *
+ * _CPU_ISR_Get_level
+ *
+ * This routine returns the current interrupt level.
+ */
+
+uint32_t _CPU_ISR_Get_level( void )
+{
+ unsigned int _ccr;
+
+#if defined(__H8300__)
+#warning "How do we get ccr on base CPU models"
+#else
+ asm volatile ( "stc ccr, %0" : "=m" (_ccr) : );
+#endif
+
+ if ( _ccr & 0x80 )
+ return 1;
+ return 0;
+}
+
+/*PAGE
+ *
+ * _CPU_ISR_install_raw_handler
+ */
+
+void _CPU_ISR_install_raw_handler(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+)
+{
+ /*
+ * This is where we install the interrupt handler into the "raw" interrupt
+ * table used by the CPU to dispatch interrupt handlers.
+ * Use Debug level IRQ Handlers
+ */
+ H8BD_Install_IRQ(vector,new_handler,old_handler);
+}
+
+/*PAGE
+ *
+ * _CPU_ISR_install_vector
+ *
+ * This kernel routine installs the RTEMS handler for the
+ * specified vector.
+ *
+ * Input parameters:
+ * vector - interrupt vector number
+ * old_handler - former ISR for this vector number
+ * new_handler - replacement ISR for this vector number
+ *
+ * Output parameters: NONE
+ *
+ */
+
+void _CPU_ISR_install_vector(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+)
+{
+ *old_handler = _ISR_Vector_table[ vector ];
+
+ /*
+ * If the interrupt vector table is a table of pointer to isr entry
+ * points, then we need to install the appropriate RTEMS interrupt
+ * handler for this vector number.
+ */
+
+ _CPU_ISR_install_raw_handler( vector, new_handler, old_handler );
+
+ /*
+ * We put the actual user ISR address in '_ISR_vector_table'. This will
+ * be used by the _ISR_Handler so the user gets control.
+ */
+
+ _ISR_Vector_table[ vector ] = new_handler;
+}
+
+/*PAGE
+ *
+ * _CPU_Install_interrupt_stack
+ */
+
+void _CPU_Install_interrupt_stack( void )
+{
+}
+
+/*PAGE
+ *
+ * _CPU_Thread_Idle_body
+ *
+ * NOTES:
+ *
+ * 1. This is the same as the regular CPU independent algorithm.
+ *
+ * 2. If you implement this using a "halt", "idle", or "shutdown"
+ * instruction, then don't forget to put it in an infinite loop.
+ *
+ * 3. Be warned. Some processors with onboard DMA have been known
+ * to stop the DMA if the CPU were put in IDLE mode. This might
+ * also be a problem with other on-chip peripherals. So use this
+ * hook with caution.
+ */
+
+#if 0
+void _CPU_Thread_Idle_body( void )
+{
+
+ for( ; ; )
+ IDLE_Monitor();
+ /*asm(" sleep \n"); */
+ /* insert your "halt" instruction here */ ;
+}
+#endif
diff --git a/cpukit/score/cpu/h8300/cpu_asm.S b/cpukit/score/cpu/h8300/cpu_asm.S
new file mode 100644
index 0000000000..e006e015f4
--- /dev/null
+++ b/cpukit/score/cpu/h8300/cpu_asm.S
@@ -0,0 +1,224 @@
+/*
+ * Hitachi H8 Score CPU functions
+ * Copyright Comnet Technologies Ltd 1999
+ *
+ * Based on example code and other ports with this copyright:
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+
+;.equ RUNCONTEXT_ARG, er0
+;.equ HEIRCONTEXT_ARG, er1
+
+/*
+ * Make sure we tell the assembler what type of CPU model we are
+ * being compiled for.
+ */
+
+#if defined(__H8300H__)
+ .h8300h
+#endif
+#if defined(__H8300S__)
+ .h8300s
+#endif
+ .text
+
+ .text
+/*
+ GCC Compiled with optimisations and Wimplicit decs to ensure
+ that stack from doesn't change
+
+ Supposedly R2 and R3 do not need to be saved but who knows
+
+ Arg1 = er0 (not on stack)
+ Arg2 = er1 (not on stack)
+*/
+
+ .align 2
+
+ .global __CPU_Context_switch
+
+__CPU_Context_switch:
+ /* Save Context */
+#if defined(__H8300H__) || defined(__H8300S__)
+ stc.w ccr,@(0:16,er0)
+ mov.l er7,@(2:16,er0)
+ mov.l er6,@(6:16,er0)
+ mov.l er5,@(10:16,er0)
+ mov.l er4,@(14:16,er0)
+ mov.l er3,@(18:16,er0)
+ mov.l er2,@(22:16,er0)
+
+ /* Install New context */
+
+restore:
+ mov.l @(22:16,er1),er2
+ mov.l @(18:16,er1),er3
+ mov.l @(14:16,er1),er4
+ mov.l @(10:16,er1),er5
+ mov.l @(6:16,er1),er6
+ mov.l @(2:16,er1),er7
+ ldc.w @(0:16,er1),ccr
+#endif
+
+ rts
+
+ .align 2
+
+ .global __CPU_Context_restore
+
+__CPU_Context_restore:
+
+#if defined(__H8300H__) || defined(__H8300S__)
+ mov.l er0,er1
+ jmp @restore:24
+#endif
+
+
+
+/*
+ VHandler for Vectored Interrupts
+
+ All IRQ's are vectored to routine _ISR_#vector_number
+ This routine stacks er0 and loads er0 with vector number
+ before transferring to here
+
+*/
+ .align 2
+ .global __ISR_Handler
+ .extern __ISR_Nest_level
+ .extern __Vector_table
+ .extern __Context_switch_necessary
+
+
+__ISR_Handler:
+#if defined(__H8300H__) || defined(__H8300S__)
+ mov.l er1,@-er7
+ mov.l er2,@-er7
+ mov.l er3,@-er7
+ mov.l er4,@-er7
+ mov.l er5,@-er7
+ mov.l er6,@-er7
+
+/* Set IRQ Stack */
+ orc #0xc0,ccr
+ mov.l er7,er6 ; save stack pointer
+ mov.l @__ISR_Nest_level,er1
+ bne nested
+ mov.l @__CPU_Interrupt_stack_high,er7
+
+nested:
+ mov.l er6,@-er7 ; save sp so pop regardless of nest level
+
+;; Inc system counters
+ mov.l @__ISR_Nest_level,er1
+ inc.l #1,er1
+ mov.l er1,@__ISR_Nest_level
+ mov.l @__Thread_Dispatch_disable_level,er1
+ inc.l #1,er1
+ mov.l er1,@__Thread_Dispatch_disable_level
+
+/* Vector to ISR */
+
+ mov.l @__ISR_Vector_table,er1
+ mov er0,er2 ; copy vector
+ shll.l er2
+ shll.l er2 ; vector = vector * 4 (sizeof(int))
+ add.l er2,er1
+ mov.l @er1,er1
+ jsr @er1 ; er0 = arg1 =vector
+
+ orc #0xc0,ccr
+ mov.l @__ISR_Nest_level,er1
+ dec.l #1,er1
+ mov.l er1,@__ISR_Nest_level
+ mov.l @__Thread_Dispatch_disable_level,er1
+ dec.l #1,er1
+ mov.l er1,@__Thread_Dispatch_disable_level
+ bne exit
+
+ mov.l @__Context_Switch_necessary,er1
+ bne bframe ; If yes then dispatch next task
+
+ mov.l @__ISR_Signals_to_thread_executing,er1
+ beq exit ; If no signals waiting
+
+ /* Context switch here through ISR_Dispatch */
+
+bframe:
+ orc #0xc0,ccr
+/* Pop Stack */
+ mov @er7+,er6
+ mov er6,er7
+ mov.l #0,er2
+ mov.l er2,@__ISR_Signals_to_thread_executing
+
+ /* Set up IRQ stack frame and dispatch to _ISR_Dispatch */
+
+ mov.l #0xc0000000,er2 /* Disable IRQ */
+ or.l #_ISR_Dispatch,er2
+ mov.l er2,@-er7
+ rte
+
+/* Inner IRQ Return, pop flags and return */
+exit:
+/* Pop Stack */
+ orc #0x80,ccr
+ mov @er7+,er6
+ mov er6,er7
+ mov @er7+,er6
+ mov @er7+,er5
+ mov @er7+,er4
+ mov @er7+,er3
+ mov @er7+,er2
+ mov @er7+,er1
+ mov @er7+,er0
+#endif
+ rte
+
+/*
+ Called from ISR_Handler as a way of ending IRQ
+ but allowing dispatch to another task.
+ Must use RTE as CCR is still on stack but IRQ has been serviced.
+ CCR and PC occupy same word so rte can be used.
+ now using task stack
+*/
+
+ .align 2
+ .global _ISR_Dispatch
+
+_ISR_Dispatch:
+
+#if defined(__H8300H__) || defined(__H8300S__)
+ jsr @__Thread_Dispatch
+ mov @er7+,er6
+ mov @er7+,er5
+ mov @er7+,er4
+ mov @er7+,er3
+ mov @er7+,er2
+ mov @er7+,er1
+ mov @er7+,er0
+#endif
+ rte
+
+
+ .align 2
+ .global __CPU_Context_save_fp
+
+__CPU_Context_save_fp:
+ rts
+
+
+ .align 2
+ .global __CPU_Context_restore_fp
+
+__CPU_Context_restore_fp:
+ rts
diff --git a/cpukit/score/cpu/h8300/rtems/asm.h b/cpukit/score/cpu/h8300/rtems/asm.h
new file mode 100644
index 0000000000..1d5f565532
--- /dev/null
+++ b/cpukit/score/cpu/h8300/rtems/asm.h
@@ -0,0 +1,122 @@
+/* asm.h
+ *
+ * This include file attempts to address the problems
+ * caused by incompatible flavors of assemblers and
+ * toolsets. It primarily addresses variations in the
+ * use of leading underscores on symbols and the requirement
+ * that register names be preceded by a %.
+ *
+ *
+ * NOTE: The spacing in the use of these macros
+ * is critical to them working as advertised.
+ *
+ * COPYRIGHT:
+ *
+ * This file is based on similar code found in newlib available
+ * from ftp.cygnus.com. The file which was used had no copyright
+ * notice. This file is freely distributable as long as the source
+ * of the file is noted. This file is:
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __H8300_CPU_ASM_h
+#define __H8300_CPU_ASM_h
+
+/*
+ * Indicate we are in an assembly file and get the basic CPU definitions.
+ */
+
+#define ASM
+#include <rtems/score/h8300.h>
+
+/*
+ * Recent versions of GNU cpp define variables which indicate the
+ * need for underscores and percents. If not using GNU cpp or
+ * the version does not support this, then you will obviously
+ * have to define these as appropriate.
+ */
+
+#ifndef __USER_LABEL_PREFIX__
+#define __USER_LABEL_PREFIX__ _
+#endif
+
+#ifndef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__
+#endif
+
+/* ANSI concatenation macros. */
+
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+/* Use the right prefix for global labels. */
+
+#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+
+/* Use the right prefix for registers. */
+
+#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
+
+/*
+ * define macros for all of the registers on this CPU
+ *
+ * EXAMPLE: #define d0 REG (d0)
+ */
+#define r0 REG(r0)
+#define r1 REG(r1)
+#define r2 REG(r2)
+#define r3 REG(r3)
+#define r4 REG(r4)
+#define r5 REG(r5)
+#define r6 REG(r6)
+#define r7 REG(r7)
+
+#define er0 REG(er0)
+#define er1 REG(er1)
+#define er2 REG(er2)
+#define er3 REG(er3)
+#define er4 REG(er4)
+#define er5 REG(er5)
+#define er6 REG(er6)
+#define er7 REG(er7)
+
+#define sp REG(sp)
+
+/*
+ * Define macros to handle section beginning and ends.
+ */
+
+
+#define BEGIN_CODE_DCL .text
+#define END_CODE_DCL
+#define BEGIN_DATA_DCL .data
+#define END_DATA_DCL
+#define BEGIN_CODE asm ( ".text
+#define END_CODE ");
+#define BEGIN_DATA
+#define END_DATA
+#define BEGIN_BSS
+#define END_BSS
+#define END
+
+/*
+ * Following must be tailor for a particular flavor of the C compiler.
+ * They may need to put underscores in front of the symbols.
+ */
+
+#define PUBLIC(sym) .globl SYM (sym)
+#define EXTERN(sym) .globl SYM (sym)
+
+#endif
+/* end of include file */
+
+ asm( \".h8300h\" );
diff --git a/cpukit/score/cpu/h8300/rtems/score/cpu.h b/cpukit/score/cpu/h8300/rtems/score/cpu.h
new file mode 100644
index 0000000000..1f80c36f78
--- /dev/null
+++ b/cpukit/score/cpu/h8300/rtems/score/cpu.h
@@ -0,0 +1,1189 @@
+/* cpu.h
+ *
+ * This include file contains information pertaining to the H8300
+ * processor.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __CPU_h
+#define __CPU_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/h8300.h> /* pick up machine definitions */
+#ifndef ASM
+#include <rtems/score/types.h>
+#endif
+
+#include <rtems/bspIo.h> /* printk */
+
+/* conditional compilation parameters */
+
+/*
+ * Should the calls to _Thread_Enable_dispatch be inlined?
+ *
+ * If TRUE, then they are inlined.
+ * If FALSE, then a subroutine call is made.
+ *
+ * Basically this is an example of the classic trade-off of size
+ * versus speed. Inlining the call (TRUE) typically increases the
+ * size of RTEMS while speeding up the enabling of dispatching.
+ * [NOTE: In general, the _Thread_Dispatch_disable_level will
+ * only be 0 or 1 unless you are in an interrupt handler and that
+ * interrupt handler invokes the executive.] When not inlined
+ * something calls _Thread_Enable_dispatch which in turns calls
+ * _Thread_Dispatch. If the enable dispatch is inlined, then
+ * one subroutine call is avoided entirely.]
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+#define CPU_INLINE_ENABLE_DISPATCH FALSE
+
+/*
+ * Should the body of the search loops in _Thread_queue_Enqueue_priority
+ * be unrolled one time? In unrolled each iteration of the loop examines
+ * two "nodes" on the chain being searched. Otherwise, only one node
+ * is examined per iteration.
+ *
+ * If TRUE, then the loops are unrolled.
+ * If FALSE, then the loops are not unrolled.
+ *
+ * The primary factor in making this decision is the cost of disabling
+ * and enabling interrupts (_ISR_Flash) versus the cost of rest of the
+ * body of the loop. On some CPUs, the flash is more expensive than
+ * one iteration of the loop body. In this case, it might be desirable
+ * to unroll the loop. It is important to note that on some CPUs, this
+ * code is the longest interrupt disable period in RTEMS. So it is
+ * necessary to strike a balance when setting this parameter.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+#define CPU_UNROLL_ENQUEUE_PRIORITY TRUE
+
+/*
+ * Does RTEMS manage a dedicated interrupt stack in software?
+ *
+ * If TRUE, then a stack is allocated in _ISR_Handler_initialization.
+ * If FALSE, nothing is done.
+ *
+ * If the CPU supports a dedicated interrupt stack in hardware,
+ * then it is generally the responsibility of the BSP to allocate it
+ * and set it up.
+ *
+ * If the CPU does not support a dedicated interrupt stack, then
+ * the porter has two options: (1) execute interrupts on the
+ * stack of the interrupted task, and (2) have RTEMS manage a dedicated
+ * interrupt stack.
+ *
+ * If this is TRUE, CPU_ALLOCATE_INTERRUPT_STACK should also be TRUE.
+ *
+ * Only one of CPU_HAS_SOFTWARE_INTERRUPT_STACK and
+ * CPU_HAS_HARDWARE_INTERRUPT_STACK should be set to TRUE. It is
+ * possible that both are FALSE for a particular CPU. Although it
+ * is unclear what that would imply about the interrupt processing
+ * procedure on that CPU.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+#define CPU_HAS_SOFTWARE_INTERRUPT_STACK TRUE
+
+/*
+ * Does this CPU have hardware support for a dedicated interrupt stack?
+ *
+ * If TRUE, then it must be installed during initialization.
+ * If FALSE, then no installation is performed.
+ *
+ * If this is TRUE, CPU_ALLOCATE_INTERRUPT_STACK should also be TRUE.
+ *
+ * Only one of CPU_HAS_SOFTWARE_INTERRUPT_STACK and
+ * CPU_HAS_HARDWARE_INTERRUPT_STACK should be set to TRUE. It is
+ * possible that both are FALSE for a particular CPU. Although it
+ * is unclear what that would imply about the interrupt processing
+ * procedure on that CPU.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+#define CPU_HAS_HARDWARE_INTERRUPT_STACK FALSE
+
+/*
+ * Does RTEMS allocate a dedicated interrupt stack in the Interrupt Manager?
+ *
+ * If TRUE, then the memory is allocated during initialization.
+ * If FALSE, then the memory is allocated during initialization.
+ *
+ * This should be TRUE is CPU_HAS_SOFTWARE_INTERRUPT_STACK is TRUE
+ * or CPU_INSTALL_HARDWARE_INTERRUPT_STACK is TRUE.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+#define CPU_ALLOCATE_INTERRUPT_STACK TRUE
+
+/*
+ * Does the CPU have hardware floating point?
+ *
+ * If TRUE, then the RTEMS_FLOATING_POINT task attribute is supported.
+ * If FALSE, then the RTEMS_FLOATING_POINT task attribute is ignored.
+ *
+ * If there is a FP coprocessor such as the i387 or mc68881, then
+ * the answer is TRUE.
+ *
+ * The macro name "NO_CPU_HAS_FPU" should be made CPU specific.
+ * It indicates whether or not this CPU model has FP support. For
+ * example, it would be possible to have an i386_nofp CPU model
+ * which set this to false to indicate that you have an i386 without
+ * an i387 and wish to leave floating point support out of RTEMS.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+#define CPU_HARDWARE_FP FALSE
+
+/*
+ * Are all tasks RTEMS_FLOATING_POINT tasks implicitly?
+ *
+ * If TRUE, then the RTEMS_FLOATING_POINT task attribute is assumed.
+ * If FALSE, then the RTEMS_FLOATING_POINT task attribute is followed.
+ *
+ * If CPU_HARDWARE_FP is FALSE, then this should be FALSE as well.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+#define CPU_ALL_TASKS_ARE_FP FALSE
+
+/*
+ * Should the IDLE task have a floating point context?
+ *
+ * If TRUE, then the IDLE task is created as a RTEMS_FLOATING_POINT task
+ * and it has a floating point context which is switched in and out.
+ * If FALSE, then the IDLE task does not have a floating point context.
+ *
+ * Setting this to TRUE negatively impacts the time required to preempt
+ * the IDLE task from an interrupt because the floating point context
+ * must be saved as part of the preemption.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+#define CPU_IDLE_TASK_IS_FP FALSE
+
+/*
+ * Should the saving of the floating point registers be deferred
+ * until a context switch is made to another different floating point
+ * task?
+ *
+ * If TRUE, then the floating point context will not be stored until
+ * necessary. It will remain in the floating point registers and not
+ * disturned until another floating point task is switched to.
+ *
+ * If FALSE, then the floating point context is saved when a floating
+ * point task is switched out and restored when the next floating point
+ * task is restored. The state of the floating point registers between
+ * those two operations is not specified.
+ *
+ * If the floating point context does NOT have to be saved as part of
+ * interrupt dispatching, then it should be safe to set this to TRUE.
+ *
+ * Setting this flag to TRUE results in using a different algorithm
+ * for deciding when to save and restore the floating point context.
+ * The deferred FP switch algorithm minimizes the number of times
+ * the FP context is saved and restored. The FP context is not saved
+ * until a context switch is made to another, different FP task.
+ * Thus in a system with only one FP task, the FP context will never
+ * be saved or restored.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+#define CPU_USE_DEFERRED_FP_SWITCH TRUE
+
+/*
+ * Does this port provide a CPU dependent IDLE task implementation?
+ *
+ * If TRUE, then the routine _CPU_Internal_threads_Idle_thread_body
+ * must be provided and is the default IDLE thread body instead of
+ * _Internal_threads_Idle_thread_body.
+ *
+ * If FALSE, then use the generic IDLE thread body if the BSP does
+ * not provide one.
+ *
+ * This is intended to allow for supporting processors which have
+ * a low power or idle mode. When the IDLE thread is executed, then
+ * the CPU can be powered down.
+ *
+ * The order of precedence for selecting the IDLE thread body is:
+ *
+ * 1. BSP provided
+ * 2. CPU dependent (if provided)
+ * 3. generic (if no BSP and no CPU dependent)
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ * The port initially called a BSP dependent routine called
+ * IDLE_Monitor. The idle task body can be overridden by
+ * the BSP in newer versions of RTEMS.
+ */
+
+#define CPU_PROVIDES_IDLE_THREAD_BODY FALSE
+
+/*
+ * Does the stack grow up (toward higher addresses) or down
+ * (toward lower addresses)?
+ *
+ * If TRUE, then the grows upward.
+ * If FALSE, then the grows toward smaller addresses.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+#define CPU_STACK_GROWS_UP FALSE
+
+/*
+ * The following is the variable attribute used to force alignment
+ * of critical RTEMS structures. On some processors it may make
+ * sense to have these aligned on tighter boundaries than
+ * the minimum requirements of the compiler in order to have as
+ * much of the critical data area as possible in a cache line.
+ *
+ * The placement of this macro in the declaration of the variables
+ * is based on the syntactically requirements of the GNU C
+ * "__attribute__" extension. For example with GNU C, use
+ * the following to force a structures to a 32 byte boundary.
+ *
+ * __attribute__ ((aligned (32)))
+ *
+ * NOTE: Currently only the Priority Bit Map table uses this feature.
+ * To benefit from using this, the data must be heavily
+ * used so it will stay in the cache and used frequently enough
+ * in the executive to justify turning this on.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+#define CPU_STRUCTURE_ALIGNMENT
+
+/*
+ * Define what is required to specify how the network to host conversion
+ * routines are handled.
+ */
+
+#define CPU_HAS_OWN_HOST_TO_NETWORK_ROUTINES FALSE
+#define CPU_BIG_ENDIAN TRUE
+#define CPU_LITTLE_ENDIAN FALSE
+
+/*
+ * The following defines the number of bits actually used in the
+ * interrupt field of the task mode. How those bits map to the
+ * CPU interrupt levels is defined by the routine _CPU_ISR_Set_level().
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+#define CPU_MODES_INTERRUPT_MASK 0x00000001
+
+/*
+ * Processor defined structures
+ *
+ * Examples structures include the descriptor tables from the i386
+ * and the processor control structure on the i960ca.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+/* may need to put some structures here. */
+
+/*
+ * Contexts
+ *
+ * Generally there are 2 types of context to save.
+ * 1. Interrupt registers to save
+ * 2. Task level registers to save
+ *
+ * This means we have the following 3 context items:
+ * 1. task level context stuff:: Context_Control
+ * 2. floating point task stuff:: Context_Control_fp
+ * 3. special interrupt level context :: Context_Control_interrupt
+ *
+ * On some processors, it is cost-effective to save only the callee
+ * preserved registers during a task context switch. This means
+ * that the ISR code needs to save those registers which do not
+ * persist across function calls. It is not mandatory to make this
+ * distinctions between the caller/callee saves registers for the
+ * purpose of minimizing context saved during task switch and on interrupts.
+ * If the cost of saving extra registers is minimal, simplicity is the
+ * choice. Save the same context on interrupt entry as for tasks in
+ * this case.
+ *
+ * Additionally, if gdb is to be made aware of RTEMS tasks for this CPU, then
+ * care should be used in designing the context area.
+ *
+ * On some CPUs with hardware floating point support, the Context_Control_fp
+ * structure will not be used or it simply consist of an array of a
+ * fixed number of bytes. This is done when the floating point context
+ * is dumped by a "FP save context" type instruction and the format
+ * is not really defined by the CPU. In this case, there is no need
+ * to figure out the exact format -- only the size. Of course, although
+ * this is enough information for RTEMS, it is probably not enough for
+ * a debugger such as gdb. But that is another problem.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+
+
+#define nogap __attribute__ ((packed))
+
+typedef struct {
+ uint16_t ccr nogap;
+ void *er7 nogap;
+ void *er6 nogap;
+ uint32_t er5 nogap;
+ uint32_t er4 nogap;
+ uint32_t er3 nogap;
+ uint32_t er2 nogap;
+ uint32_t er1 nogap;
+ uint32_t er0 nogap;
+ uint32_t xxx nogap;
+} Context_Control;
+
+typedef struct {
+ double some_float_register[2];
+} Context_Control_fp;
+
+typedef struct {
+ uint32_t special_interrupt_register;
+} CPU_Interrupt_frame;
+
+
+/*
+ * The following table contains the information required to configure
+ * the XXX processor specific parameters.
+ *
+ * NOTE: The interrupt_stack_size field is required if
+ * CPU_ALLOCATE_INTERRUPT_STACK is defined as TRUE.
+ *
+ * The pretasking_hook, predriver_hook, and postdriver_hook,
+ * and the do_zero_of_workspace fields are required on ALL CPUs.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+typedef struct {
+ void (*pretasking_hook)( void );
+ void (*predriver_hook)( void );
+ void (*postdriver_hook)( void );
+ void (*idle_task)( void );
+ boolean do_zero_of_workspace;
+ uint32_t idle_task_stack_size;
+ uint32_t interrupt_stack_size;
+ uint32_t extra_mpci_receive_server_stack;
+ void * (*stack_allocate_hook)( uint32_t );
+ void (*stack_free_hook)( void* );
+} rtems_cpu_table;
+
+/*
+ * This variable is optional. It is used on CPUs on which it is difficult
+ * to generate an "uninitialized" FP context. It is filled in by
+ * _CPU_Initialize and copied into the task's FP context area during
+ * _CPU_Context_Initialize.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+SCORE_EXTERN Context_Control_fp _CPU_Null_fp_context;
+
+/*
+ * On some CPUs, RTEMS supports a software managed interrupt stack.
+ * This stack is allocated by the Interrupt Manager and the switch
+ * is performed in _ISR_Handler. These variables contain pointers
+ * to the lowest and highest addresses in the chunk of memory allocated
+ * for the interrupt stack. Since it is unknown whether the stack
+ * grows up or down (in general), this give the CPU dependent
+ * code the option of picking the version it wants to use.
+ *
+ * NOTE: These two variables are required if the macro
+ * CPU_HAS_SOFTWARE_INTERRUPT_STACK is defined as TRUE.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+SCORE_EXTERN void *_CPU_Interrupt_stack_low;
+SCORE_EXTERN void *_CPU_Interrupt_stack_high;
+
+/*
+ * With some compilation systems, it is difficult if not impossible to
+ * call a high-level language routine from assembly language. This
+ * is especially true of commercial Ada compilers and name mangling
+ * C++ ones. This variable can be optionally defined by the CPU porter
+ * and contains the address of the routine _Thread_Dispatch. This
+ * can make it easier to invoke that routine at the end of the interrupt
+ * sequence (if a dispatch is necessary).
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+SCORE_EXTERN void (*_CPU_Thread_dispatch_pointer)();
+
+/*
+ * Nothing prevents the porter from declaring more CPU specific variables.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+/* XXX: if needed, put more variables here */
+
+/*
+ * The size of the floating point context area. On some CPUs this
+ * will not be a "sizeof" because the format of the floating point
+ * area is not defined -- only the size is. This is usually on
+ * CPUs with a "floating point save context" instruction.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+#define CPU_CONTEXT_FP_SIZE sizeof( Context_Control_fp )
+
+/*
+ * Amount of extra stack (above minimum stack size) required by
+ * system initialization thread. Remember that in a multiprocessor
+ * system the system intialization thread becomes the MP server thread.
+ *
+ * H8300 Specific Information:
+ *
+ * It is highly unlikely the H8300 will get used in a multiprocessor system.
+ */
+
+#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 0
+
+/*
+ * This defines the number of entries in the ISR_Vector_table managed
+ * by RTEMS.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+#define CPU_INTERRUPT_NUMBER_OF_VECTORS 64
+#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1)
+
+/*
+ * This is defined if the port has a special way to report the ISR nesting
+ * level. Most ports maintain the variable _ISR_Nest_level.
+ */
+
+#define CPU_PROVIDES_ISR_IS_IN_PROGRESS FALSE
+
+/*
+ * Should be large enough to run all RTEMS tests. This insures
+ * that a "reasonable" small application should not have any problems.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+#define CPU_STACK_MINIMUM_SIZE (1536)
+
+/*
+ * CPU's worst alignment requirement for data types on a byte boundary. This
+ * alignment does not take into account the requirements for the stack.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+#define CPU_ALIGNMENT 8
+
+/*
+ * This number corresponds to the byte alignment requirement for the
+ * heap handler. This alignment requirement may be stricter than that
+ * for the data types alignment specified by CPU_ALIGNMENT. It is
+ * common for the heap to follow the same alignment requirement as
+ * CPU_ALIGNMENT. If the CPU_ALIGNMENT is strict enough for the heap,
+ * then this should be set to CPU_ALIGNMENT.
+ *
+ * NOTE: This does not have to be a power of 2. It does have to
+ * be greater or equal to than CPU_ALIGNMENT.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+#define CPU_HEAP_ALIGNMENT CPU_ALIGNMENT
+
+/*
+ * This number corresponds to the byte alignment requirement for memory
+ * buffers allocated by the partition manager. This alignment requirement
+ * may be stricter than that for the data types alignment specified by
+ * CPU_ALIGNMENT. It is common for the partition to follow the same
+ * alignment requirement as CPU_ALIGNMENT. If the CPU_ALIGNMENT is strict
+ * enough for the partition, then this should be set to CPU_ALIGNMENT.
+ *
+ * NOTE: This does not have to be a power of 2. It does have to
+ * be greater or equal to than CPU_ALIGNMENT.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+#define CPU_PARTITION_ALIGNMENT CPU_ALIGNMENT
+
+/*
+ * This number corresponds to the byte alignment requirement for the
+ * stack. This alignment requirement may be stricter than that for the
+ * data types alignment specified by CPU_ALIGNMENT. If the CPU_ALIGNMENT
+ * is strict enough for the stack, then this should be set to 0.
+ *
+ * NOTE: This must be a power of 2 either 0 or greater than CPU_ALIGNMENT.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+#define CPU_STACK_ALIGNMENT 2
+
+/*
+ * ISR handler macros
+ */
+
+/*
+ * Support routine to initialize the RTEMS vector table after it is allocated.
+ */
+
+#define _CPU_Initialize_vectors()
+
+/* COPE With Brain dead version of GCC distributed with Hitachi HIView Tools.
+ Note requires ISR_Level be uint16_t or assembler croaks.
+*/
+
+#if (__GNUC__ == 2 && __GNUC_MINOR__ == 7 )
+
+
+/*
+ * Disable all interrupts for an RTEMS critical section. The previous
+ * level is returned in _level.
+ */
+
+#define _CPU_ISR_Disable( _isr_cookie ) \
+ do { \
+ asm volatile( "stc.w ccr, @-er7 ;\n orc #0xC0,ccr ;\n mov.w @er7+,%0" : : "r" (_isr_cookie) ); \
+ } while (0)
+
+
+/*
+ * Enable interrupts to the previois level (returned by _CPU_ISR_Disable).
+ * This indicates the end of an RTEMS critical section. The parameter
+ * _level is not modified.
+ */
+
+
+#define _CPU_ISR_Enable( _isr_cookie ) \
+ do { \
+ asm volatile( "mov.w %0,@-er7 ;\n ldc.w @er7+, ccr" : : "r" (_isr_cookie) ); \
+ } while (0)
+
+
+/*
+ * This temporarily restores the interrupt to _level before immediately
+ * disabling them again. This is used to divide long RTEMS critical
+ * sections into two or more parts. The parameter _level is not
+ * modified.
+ */
+
+
+#define _CPU_ISR_Flash( _isr_cookie ) \
+ do { \
+ asm volatile( "mov.w %0,@-er7 ;\n ldc.w @er7+, ccr ;\n orc #0xC0,ccr" : : "r" (_isr_cookie) ); \
+ } while (0)
+
+/* end of ISR handler macros */
+
+#else /* modern gcc version */
+
+/*
+ * Disable all interrupts for an RTEMS critical section. The previous
+ * level is returned in _level.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+#if defined(__H8300H__) || defined(__H8300S__)
+#define _CPU_ISR_Disable( _isr_cookie ) \
+ do { \
+ unsigned char __ccr; \
+ asm volatile( "stc ccr, %0 ; orc #0x80,ccr " \
+ : "=m" (__ccr) : "0" (__ccr) ); \
+ (_isr_cookie) = __ccr; \
+ } while (0)
+#else
+#define _CPU_ISR_Disable( _isr_cookie ) (_isr_cookie) = 0
+#endif
+
+
+/*
+ * Enable interrupts to the previois level (returned by _CPU_ISR_Disable).
+ * This indicates the end of an RTEMS critical section. The parameter
+ * _level is not modified.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+#if defined(__H8300H__) || defined(__H8300S__)
+#define _CPU_ISR_Enable( _isr_cookie ) \
+ do { \
+ unsigned char __ccr = (unsigned char) (_isr_cookie); \
+ asm volatile( "ldc %0, ccr" : : "m" (__ccr) ); \
+ } while (0)
+#else
+#define _CPU_ISR_Enable( _isr_cookie )
+#endif
+
+/*
+ * This temporarily restores the interrupt to _level before immediately
+ * disabling them again. This is used to divide long RTEMS critical
+ * sections into two or more parts. The parameter _level is not
+ * modified.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+#if defined(__H8300H__) || defined(__H8300S__)
+#define _CPU_ISR_Flash( _isr_cookie ) \
+ do { \
+ unsigned char __ccr = (unsigned char) (_isr_cookie); \
+ asm volatile( "ldc %0, ccr ; orc #0x80,ccr " : : "m" (__ccr) ); \
+ } while (0)
+#else
+#define _CPU_ISR_Flash( _isr_cookie )
+#endif
+
+#endif /* end of old gcc */
+
+
+/*
+ * Map interrupt level in task mode onto the hardware that the CPU
+ * actually provides. Currently, interrupt levels which do not
+ * map onto the CPU in a generic fashion are undefined. Someday,
+ * it would be nice if these were "mapped" by the application
+ * via a callout. For example, m68k has 8 levels 0 - 7, levels
+ * 8 - 255 would be available for bsp/application specific meaning.
+ * This could be used to manage a programmable interrupt controller
+ * via the rtems_task_mode directive.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+#define _CPU_ISR_Set_level( _new_level ) \
+ { \
+ if ( _new_level ) asm volatile ( "orc #0x80,ccr\n" ); \
+ else asm volatile ( "andc #0x7f,ccr\n" ); \
+ }
+
+uint32_t _CPU_ISR_Get_level( void );
+
+/* end of ISR handler macros */
+
+/* Context handler macros */
+
+/*
+ * Initialize the context to a state suitable for starting a
+ * task after a context restore operation. Generally, this
+ * involves:
+ *
+ * - setting a starting address
+ * - preparing the stack
+ * - preparing the stack and frame pointers
+ * - setting the proper interrupt level in the context
+ * - initializing the floating point context
+ *
+ * This routine generally does not set any unnecessary register
+ * in the context. The state of the "general data" registers is
+ * undefined at task start time.
+ *
+ * NOTE: This is_fp parameter is TRUE if the thread is to be a floating
+ * point thread. This is typically only used on CPUs where the
+ * FPU may be easily disabled by software such as on the SPARC
+ * where the PSR contains an enable FPU bit.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+
+#define CPU_CCR_INTERRUPTS_ON 0x80
+#define CPU_CCR_INTERRUPTS_OFF 0x00
+
+#define _CPU_Context_Initialize( _the_context, _stack_base, _size, \
+ _isr, _entry_point, _is_fp ) \
+ /* Locate Me */ \
+ do { \
+ uint32_t _stack; \
+ \
+ if ( (_isr) ) (_the_context)->ccr = CPU_CCR_INTERRUPTS_OFF; \
+ else (_the_context)->ccr = CPU_CCR_INTERRUPTS_ON; \
+ \
+ _stack = ((uint32_t )(_stack_base)) + (_size) - 4; \
+ *((proc_ptr *)(_stack)) = (_entry_point); \
+ (_the_context)->er7 = (void *) _stack; \
+ (_the_context)->er6 = (void *) _stack; \
+ (_the_context)->er5 = 0; \
+ (_the_context)->er4 = 1; \
+ (_the_context)->er3 = 2; \
+ } while (0)
+
+
+/*
+ * This routine is responsible for somehow restarting the currently
+ * executing task. If you are lucky, then all that is necessary
+ * is restoring the context. Otherwise, there will need to be
+ * a special assembly routine which does something special in this
+ * case. Context_Restore should work most of the time. It will
+ * not work if restarting self conflicts with the stack frame
+ * assumptions of restoring a context.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+#define _CPU_Context_Restart_self( _the_context ) \
+ _CPU_Context_restore( (_the_context) );
+
+/*
+ * The purpose of this macro is to allow the initial pointer into
+ * a floating point context area (used to save the floating point
+ * context) to be at an arbitrary place in the floating point
+ * context area.
+ *
+ * This is necessary because some FP units are designed to have
+ * their context saved as a stack which grows into lower addresses.
+ * Other FP units can be saved by simply moving registers into offsets
+ * from the base of the context area. Finally some FP units provide
+ * a "dump context" instruction which could fill in from high to low
+ * or low to high based on the whim of the CPU designers.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+#define _CPU_Context_Fp_start( _base, _offset ) \
+ ( (void *) (_base) + (_offset) )
+
+/*
+ * This routine initializes the FP context area passed to it to.
+ * There are a few standard ways in which to initialize the
+ * floating point context. The code included for this macro assumes
+ * that this is a CPU in which a "initial" FP context was saved into
+ * _CPU_Null_fp_context and it simply copies it to the destination
+ * context passed to it.
+ *
+ * Other models include (1) not doing anything, and (2) putting
+ * a "null FP status word" in the correct place in the FP context.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+#define _CPU_Context_Initialize_fp( _destination ) \
+ { \
+ *((Context_Control_fp *) *((void **) _destination)) = _CPU_Null_fp_context; \
+ }
+
+/* end of Context handler macros */
+
+/* Fatal Error manager macros */
+
+/*
+ * This routine copies _error into a known place -- typically a stack
+ * location or a register, optionally disables interrupts, and
+ * halts/stops the CPU.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+#define _CPU_Fatal_halt( _error ) \
+ printk("Fatal Error %d Halted\n",_error); \
+ for(;;)
+
+
+/* end of Fatal Error manager macros */
+
+/* Bitfield handler macros */
+
+/*
+ * This routine sets _output to the bit number of the first bit
+ * set in _value. _value is of CPU dependent type Priority_Bit_map_control.
+ * This type may be either 16 or 32 bits wide although only the 16
+ * least significant bits will be used.
+ *
+ * There are a number of variables in using a "find first bit" type
+ * instruction.
+ *
+ * (1) What happens when run on a value of zero?
+ * (2) Bits may be numbered from MSB to LSB or vice-versa.
+ * (3) The numbering may be zero or one based.
+ * (4) The "find first bit" instruction may search from MSB or LSB.
+ *
+ * RTEMS guarantees that (1) will never happen so it is not a concern.
+ * (2),(3), (4) are handled by the macros _CPU_Priority_mask() and
+ * _CPU_Priority_bits_index(). These three form a set of routines
+ * which must logically operate together. Bits in the _value are
+ * set and cleared based on masks built by _CPU_Priority_mask().
+ * The basic major and minor values calculated by _Priority_Major()
+ * and _Priority_Minor() are "massaged" by _CPU_Priority_bits_index()
+ * to properly range between the values returned by the "find first bit"
+ * instruction. This makes it possible for _Priority_Get_highest() to
+ * calculate the major and directly index into the minor table.
+ * This mapping is necessary to ensure that 0 (a high priority major/minor)
+ * is the first bit found.
+ *
+ * This entire "find first bit" and mapping process depends heavily
+ * on the manner in which a priority is broken into a major and minor
+ * components with the major being the 4 MSB of a priority and minor
+ * the 4 LSB. Thus (0 << 4) + 0 corresponds to priority 0 -- the highest
+ * priority. And (15 << 4) + 14 corresponds to priority 254 -- the next
+ * to the lowest priority.
+ *
+ * If your CPU does not have a "find first bit" instruction, then
+ * there are ways to make do without it. Here are a handful of ways
+ * to implement this in software:
+ *
+ * - a series of 16 bit test instructions
+ * - a "binary search using if's"
+ * - _number = 0
+ * if _value > 0x00ff
+ * _value >>=8
+ * _number = 8;
+ *
+ * if _value > 0x0000f
+ * _value >=8
+ * _number += 4
+ *
+ * _number += bit_set_table[ _value ]
+ *
+ * where bit_set_table[ 16 ] has values which indicate the first
+ * bit set
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+#define CPU_USE_GENERIC_BITFIELD_CODE TRUE
+#define CPU_USE_GENERIC_BITFIELD_DATA TRUE
+
+#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
+
+#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
+ { \
+ (_output) = 0; /* do something to prevent warnings */ \
+ }
+
+#endif
+
+/* end of Bitfield handler macros */
+
+/*
+ * This routine builds the mask which corresponds to the bit fields
+ * as searched by _CPU_Bitfield_Find_first_bit(). See the discussion
+ * for that routine.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
+
+#define _CPU_Priority_Mask( _bit_number ) \
+ ( 1 << (_bit_number) )
+
+#endif
+
+/*
+ * This routine translates the bit numbers returned by
+ * _CPU_Bitfield_Find_first_bit() into something suitable for use as
+ * a major or minor component of a priority. See the discussion
+ * for that routine.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
+
+#define _CPU_Priority_bits_index( _priority ) \
+ (_priority)
+
+#endif
+
+/* end of Priority handler macros */
+
+/* functions */
+
+/*
+ * _CPU_Initialize
+ *
+ * This routine performs CPU dependent initialization.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+void _CPU_Initialize(
+ rtems_cpu_table *cpu_table,
+ void (*thread_dispatch)
+);
+
+/*
+ * _CPU_ISR_install_raw_handler
+ *
+ * This routine installs a "raw" interrupt handler directly into the
+ * processor's vector table.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+void _CPU_ISR_install_raw_handler(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+);
+
+/*
+ * _CPU_ISR_install_vector
+ *
+ * This routine installs an interrupt vector.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+void _CPU_ISR_install_vector(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+);
+
+/*
+ * _CPU_Install_interrupt_stack
+ *
+ * This routine installs the hardware interrupt stack pointer.
+ *
+ * NOTE: It need only be provided if CPU_HAS_HARDWARE_INTERRUPT_STACK
+ * is TRUE.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+void _CPU_Install_interrupt_stack( void );
+
+/*
+ * _CPU_Internal_threads_Idle_thread_body
+ *
+ * This routine is the CPU dependent IDLE thread body.
+ *
+ * NOTE: It need only be provided if CPU_PROVIDES_IDLE_THREAD_BODY
+ * is TRUE.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+void _CPU_Thread_Idle_body( void );
+
+/*
+ * _CPU_Context_switch
+ *
+ * This routine switches from the run context to the heir context.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+void _CPU_Context_switch(
+ Context_Control *run,
+ Context_Control *heir
+);
+
+/*
+ * _CPU_Context_restore
+ *
+ * This routine is generallu used only to restart self in an
+ * efficient manner. It may simply be a label in _CPU_Context_switch.
+ *
+ * NOTE: May be unnecessary to reload some registers.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+void _CPU_Context_restore(
+ Context_Control *new_context
+);
+
+/*
+ * _CPU_Context_save_fp
+ *
+ * This routine saves the floating point context passed to it.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+void _CPU_Context_save_fp(
+ void **fp_context_ptr
+);
+
+/*
+ * _CPU_Context_restore_fp
+ *
+ * This routine restores the floating point context passed to it.
+ *
+ * H8300 Specific Information:
+ *
+ * XXX
+ */
+
+void _CPU_Context_restore_fp(
+ void **fp_context_ptr
+);
+
+/* The following routine swaps the endian format of an unsigned int.
+ * It must be static because it is referenced indirectly.
+ *
+ * This version will work on any processor, but if there is a better
+ * way for your CPU PLEASE use it. The most common way to do this is to:
+ *
+ * swap least significant two bytes with 16-bit rotate
+ * swap upper and lower 16-bits
+ * swap most significant two bytes with 16-bit rotate
+ *
+ * Some CPUs have special instructions which swap a 32-bit quantity in
+ * a single instruction (e.g. i486). It is probably best to avoid
+ * an "endian swapping control bit" in the CPU. One good reason is
+ * that interrupts would probably have to be disabled to insure that
+ * an interrupt does not try to access the same "chunk" with the wrong
+ * endian. Another good reason is that on some CPUs, the endian bit
+ * endianness for ALL fetches -- both code and data -- so the code
+ * will be fetched incorrectly.
+ *
+ * H8300 Specific Information:
+ *
+ * This is the generic implementation.
+ */
+
+static inline uint32_t CPU_swap_u32(
+ uint32_t value
+)
+{
+ uint32_t byte1, byte2, byte3, byte4, swapped;
+
+ byte4 = (value >> 24) & 0xff;
+ byte3 = (value >> 16) & 0xff;
+ byte2 = (value >> 8) & 0xff;
+ byte1 = value & 0xff;
+
+ swapped = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
+ return( swapped );
+}
+
+#define CPU_swap_u16( value ) \
+ (((value&0xff) << 8) | ((value >> 8)&0xff))
+
+/* to be provided by the BSP */
+extern void H8BD_Install_IRQ(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/score/cpu/h8300/rtems/score/h8300.h b/cpukit/score/cpu/h8300/rtems/score/h8300.h
new file mode 100644
index 0000000000..c051d9e77f
--- /dev/null
+++ b/cpukit/score/cpu/h8300/rtems/score/h8300.h
@@ -0,0 +1,57 @@
+/* h8300.h
+ *
+ * This file contains information pertaining to the Hitachi H8/300
+ * processor family.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef _INCLUDE_H8300_h
+#define _INCLUDE_H8300_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This file contains the information required to build
+ * RTEMS for a particular member of the "h8300"
+ * family when executing in protected mode. It does
+ * this by setting variables to indicate which implementation
+ * dependent features are present in a particular member
+ * of the family.
+ */
+
+/*
+ * RTEMS compiles for the base H8 with numerous warnings but has never
+ * been tested on a CPU with 16 bit address space.
+ *
+ * FIXME:
+ * This macro is defined to handle a couple of places where
+ * addresses are cast to pointers. There really should be
+ * a "int-pointer" type that pointers are cast to before being
+ * mathematcically manipulated. When that is added, search
+ * for all references to this macro and remove them.
+ */
+
+#if defined(__H8300__)
+#define RTEMS_CPU_HAS_16_BIT_ADDRESSES 1
+#endif
+
+#define CPU_NAME "Hitachi H8300"
+#define CPU_MODEL_NAME "h8300"
+#define H8300_HAS_FPU 0
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/h8300/rtems/score/types.h b/cpukit/score/cpu/h8300/rtems/score/types.h
new file mode 100644
index 0000000000..cc0524aa62
--- /dev/null
+++ b/cpukit/score/cpu/h8300/rtems/score/types.h
@@ -0,0 +1,56 @@
+/* h8300types.h
+ *
+ * This include file contains type definitions pertaining to the Hitachi
+ * h8300 processor family.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __H8300_TYPES_h
+#define __H8300_TYPES_h
+
+#ifndef ASM
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This section defines the basic types for this processor.
+ */
+
+typedef unsigned char unsigned8; /* unsigned 8-bit integer */
+typedef unsigned short unsigned16; /* unsigned 16-bit integer */
+typedef unsigned long unsigned32; /* unsigned 32-bit integer */
+typedef unsigned long long unsigned64; /* unsigned 64-bit integer */
+
+typedef unsigned16 Priority_Bit_map_control;
+
+typedef signed char signed8; /* 8-bit signed integer */
+typedef signed short signed16; /* 16-bit signed integer */
+typedef signed long signed32; /* 32-bit signed integer */
+typedef signed long long signed64; /* 64 bit signed integer */
+
+typedef unsigned32 boolean; /* Boolean value */
+
+typedef float single_precision; /* single precision float */
+typedef double double_precision; /* double precision float */
+
+typedef void h8300_isr;
+typedef void ( *h8300_isr_entry )( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !ASM */
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/i386/.cvsignore b/cpukit/score/cpu/i386/.cvsignore
new file mode 100644
index 0000000000..282522db03
--- /dev/null
+++ b/cpukit/score/cpu/i386/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/cpukit/score/cpu/i386/ChangeLog b/cpukit/score/cpu/i386/ChangeLog
new file mode 100644
index 0000000000..18d0de4498
--- /dev/null
+++ b/cpukit/score/cpu/i386/ChangeLog
@@ -0,0 +1,272 @@
+2004-04-16 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * rtems/score/i386.h: Rename i386_swap_U* to i386_swap_u* (API
+ consistency with other ports).
+
+2004-04-09 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * cpu_asm.S: Convert asm comments to C-comments to prevent gcc-3.4.0pre
+ from choking on them.
+
+2004-04-06 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * configure.ac: Remove (Merged into $(top_srcdir)/configure.ac).
+ * Makefile.am: Don't include multilib.am.
+ Reflect merging configure.ac into $(top_srcdir)/configure.ac.
+
+2004-04-01 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * Makefile.am: Install asm.h to $(includedir)/rtems.
+
+2004-04-01 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * cpu_asm.S: Include <rtems/asm.h> instead of <asm.h>.
+
+2004-03-30 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * cpu.c, cpu_asm.S, rtems/score/cpu.h, rtems/score/interrupts.h:
+ Convert to using c99 fixed size types.
+
+2004-03-29 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * configure.ac: RTEMS_TOP([../../../..]).
+
+2004-02-09 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ PR 565/rtems
+ * asm.h: Various hacks.
+
+2004-01-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Move RTEMS_TOP one subdir down.
+
+2004-01-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add PREINSTALL_DIRS.
+
+2004-01-14 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Re-add dirstamps to PREINSTALL_FILES.
+ Add PREINSTALL_FILES to CLEANFILES.
+
+2004-01-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Requires automake >= 1.8.1.
+
+2004-01-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include compile.am, again.
+
+2004-01-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Convert to using automake compilation rules.
+
+2003-12-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use mkdir_p. Remove dirs from PREINSTALL_FILES.
+
+2003-12-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Require automake >= 1.8, autoconf >= 2.59.
+
+2003-12-01 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Remove TMPINSTALL_FILES.
+
+2003-11-30 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add $(dirstamp) to preinstallation rules.
+
+2003-11-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Don't use gmake rules for preinstallation.
+
+2003-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_CANONICAL_HOST.
+
+2003-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_CHECK_CPU.
+
+2003-09-04 Joel Sherrill <joel@OARcorp.com>
+
+ * cpu.c, cpu_asm.S, rtems/score/cpu.h, rtems/score/i386.h,
+ rtems/score/idtr.h, rtems/score/interrupts.h,
+ rtems/score/registers.h, rtems/score/types.h: URL for license
+ changed.
+
+2003-08-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use rtems-bugs@rtems.com as bug report email address.
+
+2003-03-06 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove AC_CONFIG_AUX_DIR.
+
+2002-12-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Require autoconf-2.57 + automake-1.7.2.
+ * Makefile.am: Eliminate C_O_FILES, S_O_FILES, libscorecpu_a_OBJECTS.
+
+2002-11-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Fix package name.
+
+2002-10-25 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Add nostdinc to AM_INIT_AUTOMAKE.
+
+2002-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * .cvsignore: Reformat.
+ Add autom4te*cache.
+ Remove autom4te.cache.
+
+2002-07-26 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Build libscorecpu.a instead of rtems-cpu.rel.
+
+2002-07-22 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use .$(OBJEXT) instead of .o.
+
+2002-07-22 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use . instead of .o.
+
+2002-07-05 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: RTEMS_TOP(../../../..).
+
+2002-07-03 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems.S: Remove.
+ * Makefile.am: Reflect changes above.
+
+2002-07-01 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_PROJECT_ROOT.
+
+2002-06-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Add RTEMS_PROG_CCAS
+
+2002-06-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use AC_CONFIG_AUX_DIR(../../../..).
+ Add AC_PROG_RANLIB.
+
+2002-06-17 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include $(top_srcdir)/../../../automake/*.am.
+ Use ../../../aclocal.
+
+2002-03-29 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/score/idtr.h: New file, extracted from libcpu/cpu.h.
+ * rtems/score/interrupts.h: New file, extracted from libcpu/cpu.h.
+ * rtems/score/registers.h: New file, moved from libcpu.
+ * Makefile.am: Reflect changes above.
+ * cpu.c: Don't include cpuModel.h,
+ #include <rtems.h>,
+ #include <rtems/score/i386types.h>,
+ #include <rtems/score/idtr.h>.
+ * rtems/score/cpu.h: Don't include libcpu/cpu.h.
+ #include <rtems/score/interrupts.h>,
+ #include <rtems/score/registers.h>.
+
+2001-04-03 Joel Sherrill <joel@OARcorp.com>
+
+ * Per PR94, all rtems/score/CPUtypes.h are named rtems/score/types.h.
+ * rtems/score/i386types.h: Removed.
+ * rtems/score/types.h: New file via CVS magic.
+ * Makefile.am, rtems/score/cpu.h: Account for name change.
+
+2002-03-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac:
+ AC_INIT(package,_RTEMS_VERSION,_RTEMS_BUGS).
+ AM_INIT_AUTOMAKE([no-define foreign 1.6]).
+ * Makefile.am: Remove AUTOMAKE_OPTIONS.
+
+2001-02-05 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/Makefile.am, rtems/score/Makefile.am: Removed again.
+
+2002-01-31 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/Makefile.am: Removed.
+ * rtems/score/Makefile.am: Removed.
+ * configure.ac: Reflect changes above.
+ * Makefile.am: Reflect changes above.
+
+2001-01-30 Joel Sherrill <joel@OARcorp.com>
+
+ * Makefile.am: Corrected so .h files from rtems/score/ are installed.
+
+2002-01-03 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * cpu.c: Include rtems/bspIo.h instead of bspIo.h.
+
+2001-12-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add multilib support.
+
+2001-11-28 Joel Sherrill <joel@OARcorp.com>,
+
+ This was tracked as PR91.
+ * rtems/score/cpu.h: Added CPU_PROVIDES_ISR_IS_IN_PROGRESS macro which
+ is used to specify if the port uses the standard macro for this (FALSE).
+ A TRUE setting indicates the port provides its own implementation.
+
+2001-10-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * .cvsignore: Add autom4te.cache for autoconf > 2.52.
+ * configure.in: Remove.
+ * configure.ac: New file, generated from configure.in by autoupdate.
+
+2001-09-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/score/Makefile.am: Use 'PREINSTALL_FILES ='.
+ * Makefile.am: Use 'PREINSTALL_FILES ='.
+
+2001-02-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am, rtems/score/Makefile.am:
+ Apply include_*HEADERS instead of H_FILES.
+
+2001-01-03 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/cpu.h: Added _CPU_Initialize_vectors().
+
+2000-11-09 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use ... instead of RTEMS_TOPdir in ACLOCAL_AMFLAGS.
+
+2000-11-02 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Switch to ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal.
+
+2000-10-25 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: ACLOCAL_AMFLAGS= -I $(RTEMS_TOPdir)/macros.
+ Switch to GNU canonicalization.
+
+2000-09-12 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/i386.h: Corrected "#elsif" to be "#elif".
+
+2000-09-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include compile.am.
+
+2000-08-17 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/score/i386.h: cpu-variant define handling
+ Rewrite due to introduction of multilib defines.
+ * asm.h: include cpuopts.h instead of targopts.h
+
+2000-08-10 Joel Sherrill <joel@OARcorp.com>
+
+ * ChangeLog: New file.
diff --git a/cpukit/score/cpu/i386/Makefile.am b/cpukit/score/cpu/i386/Makefile.am
new file mode 100644
index 0000000000..243fc91436
--- /dev/null
+++ b/cpukit/score/cpu/i386/Makefile.am
@@ -0,0 +1,71 @@
+##
+## $Id$
+##
+
+include $(top_srcdir)/automake/compile.am
+
+include_rtemsdir = $(includedir)/rtems
+include_rtems_HEADERS= asm.h
+
+include_rtems_scoredir = $(includedir)/rtems/score
+include_rtems_score_HEADERS = rtems/score/cpu.h rtems/score/i386.h \
+ rtems/score/types.h rtems/score/interrupts.h rtems/score/registers.h \
+ rtems/score/idtr.h
+
+EXTRA_LIBRARIES = libscorecpu.a
+CLEANFILES = libscorecpu.a
+libscorecpu_a_SOURCES = cpu.c cpu_asm.S
+libscorecpu_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libscorecpu_g.a
+CLEANFILES += libscorecpu_g.a
+libscorecpu_g_a_SOURCES = $(libscorecpu_a_SOURCES)
+libscorecpu_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+all-local: $(PREINSTALL_FILES) libscorecpu$(LIB_VARIANT).a
+
+PREINSTALL_DIRS =
+PREINSTALL_FILES =
+
+$(PROJECT_INCLUDE)/rtems/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems
+ @: > $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/asm.h: asm.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/asm.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/asm.h
+
+$(PROJECT_INCLUDE)/rtems/score/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems/score
+ @: > $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/score/cpu.h: rtems/score/cpu.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/cpu.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/cpu.h
+
+$(PROJECT_INCLUDE)/rtems/score/i386.h: rtems/score/i386.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/i386.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/i386.h
+
+$(PROJECT_INCLUDE)/rtems/score/types.h: rtems/score/types.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/types.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/types.h
+
+$(PROJECT_INCLUDE)/rtems/score/interrupts.h: rtems/score/interrupts.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/interrupts.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/interrupts.h
+
+$(PROJECT_INCLUDE)/rtems/score/registers.h: rtems/score/registers.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/registers.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/registers.h
+
+$(PROJECT_INCLUDE)/rtems/score/idtr.h: rtems/score/idtr.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/idtr.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/idtr.h
+
+CLEANFILES += $(PREINSTALL_FILES)
+DISTCLEANFILES = $(PREINSTALL_DIRS)
+
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/score/cpu/i386/asm.h b/cpukit/score/cpu/i386/asm.h
new file mode 100644
index 0000000000..1793c17015
--- /dev/null
+++ b/cpukit/score/cpu/i386/asm.h
@@ -0,0 +1,143 @@
+/* asm.h
+ *
+ * This include file attempts to address the problems
+ * caused by incompatible flavors of assemblers and
+ * toolsets. It primarily addresses variations in the
+ * use of leading underscores on symbols and the requirement
+ * that register names be preceded by a %.
+ *
+ *
+ * NOTE: The spacing in the use of these macros
+ * is critical to them working as advertised.
+ *
+ * COPYRIGHT:
+ *
+ * This file is based on similar code found in newlib available
+ * from ftp.cygnus.com. The file which was used had no copyright
+ * notice. This file is freely distributable as long as the source
+ * of the file is noted. This file is:
+ *
+ * COPYRIGHT (c) 1994-1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * $Id$
+ */
+
+#ifndef __i386_ASM_h
+#define __i386_ASM_h
+
+/*
+ * Indicate we are in an assembly file and get the basic CPU definitions.
+ */
+
+#ifndef ASM
+#define ASM
+#endif
+#include <rtems/score/cpuopts.h>
+#include <rtems/score/i386.h>
+
+/*
+ * Recent versions of GNU cpp define variables which indicate the
+ * need for underscores and percents. If not using GNU cpp or
+ * the version does not support this, then you will obviously
+ * have to define these as appropriate.
+ */
+
+#ifndef __USER_LABEL_PREFIX__
+#define __USER_LABEL_PREFIX__
+#endif
+
+/*
+ * Looks like there is a bug in gcc 2.6.2 where this is not
+ * defined correctly when configured as i386-coff and
+ * i386-aout.
+ */
+
+#undef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__ %
+
+/*
+#ifndef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__
+#endif
+*/
+
+/* ANSI concatenation macros. */
+
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+#define EVAL(x) x
+#define CONCAT0(a, b) EVAL(a)EVAL(b)
+
+/* Use the right prefix for global labels. */
+
+#define SYM(x) CONCAT0 (__USER_LABEL_PREFIX__, x)
+
+/* Use the right prefix for registers. */
+
+#define REG(x) CONCAT0 (__REGISTER_PREFIX__, x)
+
+#define eax REG (eax)
+#define ebx REG (ebx)
+#define ecx REG (ecx)
+#define edx REG (edx)
+#define esi REG (esi)
+#define edi REG (edi)
+#define esp REG (esp)
+#define ebp REG (ebp)
+#define cr0 REG (cr0)
+
+#define ax REG (ax)
+#define bx REG (bx)
+#define cx REG (cx)
+#define dx REG (dx)
+#define si REG (si)
+#define di REG (di)
+#define sp REG (sp)
+#define bp REG (bp)
+
+#define ah REG (ah)
+#define bh REG (bh)
+#define ch REG (ch)
+#define dh REG (dh)
+
+#define al REG (al)
+#define bl REG (bl)
+#define cl REG (cl)
+#define dl REG (dl)
+
+#define cs REG (cs)
+#define ds REG (ds)
+#define es REG (es)
+#define fs REG (fs)
+#define gs REG (gs)
+#define ss REG (ss)
+
+/*
+ * Define macros to handle section beginning and ends.
+ */
+
+
+#define BEGIN_CODE_DCL .text
+#define END_CODE_DCL
+#define BEGIN_DATA_DCL .data
+#define END_DATA_DCL
+#define BEGIN_CODE .text
+#define END_CODE
+#define BEGIN_DATA .data
+#define END_DATA
+#define BEGIN_BSS .bss
+#define END_BSS
+#define END
+
+/*
+ * Following must be tailor for a particular flavor of the C compiler.
+ * They may need to put underscores in front of the symbols.
+ */
+
+#define PUBLIC(sym) .globl SYM (sym)
+#define EXTERN(sym) .globl SYM (sym)
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/i386/cpu.c b/cpukit/score/cpu/i386/cpu.c
new file mode 100644
index 0000000000..d9f1e1aa47
--- /dev/null
+++ b/cpukit/score/cpu/i386/cpu.c
@@ -0,0 +1,197 @@
+/*
+ * Intel i386 Dependent Source
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems.h>
+#include <rtems/system.h>
+#include <rtems/score/types.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/idtr.h>
+
+#include <rtems/bspIo.h>
+#include <rtems/score/thread.h>
+
+/* _CPU_Initialize
+ *
+ * This routine performs processor dependent initialization.
+ *
+ * INPUT PARAMETERS:
+ * cpu_table - CPU table to initialize
+ * thread_dispatch - address of disptaching routine
+ */
+
+
+void _CPU_Initialize(
+ rtems_cpu_table *cpu_table,
+ void (*thread_dispatch) /* ignored on this CPU */
+)
+{
+#if CPU_HARDWARE_FP
+ register uint16_t fp_status asm ("ax");
+ register void *fp_context;
+#endif
+
+ _CPU_Table = *cpu_table;
+
+ /*
+ * The following code saves a NULL i387 context which is given
+ * to each task at start and restart time. The following code
+ * is based upon that provided in the i386 Programmer's
+ * Manual and should work on any coprocessor greater than
+ * the i80287.
+ *
+ * NOTE: The NO WAIT form of the coprocessor instructions
+ * MUST be used in case there is not a coprocessor
+ * to wait for.
+ */
+
+#if CPU_HARDWARE_FP
+ fp_status = 0xa5a5;
+ asm volatile( "fninit" );
+ asm volatile( "fnstsw %0" : "=a" (fp_status) : "0" (fp_status) );
+
+ if ( fp_status == 0 ) {
+
+ fp_context = &_CPU_Null_fp_context;
+
+ asm volatile( "fsave (%0)" : "=r" (fp_context)
+ : "0" (fp_context)
+ );
+ }
+#endif
+
+}
+
+/*PAGE
+ *
+ * _CPU_ISR_Get_level
+ */
+
+uint32_t _CPU_ISR_Get_level( void )
+{
+ uint32_t level;
+
+ i386_get_interrupt_level( level );
+
+ return level;
+}
+
+void _CPU_Thread_Idle_body ()
+{
+ while(1){
+ asm volatile ("hlt");
+ }
+}
+
+void _defaultExcHandler (CPU_Exception_frame *ctx)
+{
+ unsigned int faultAddr = 0;
+ printk("----------------------------------------------------------\n");
+ printk("Exception %d caught at PC %x by thread %d\n",
+ ctx->idtIndex,
+ ctx->eip,
+ _Thread_Executing->Object.id);
+ printk("----------------------------------------------------------\n");
+ printk("Processor execution context at time of the fault was :\n");
+ printk("----------------------------------------------------------\n");
+ printk(" EAX = %x EBX = %x ECX = %x EDX = %x\n",
+ ctx->eax, ctx->ebx, ctx->ecx, ctx->edx);
+ printk(" ESI = %x EDI = %x EBP = %x ESP = %x\n",
+ ctx->esi, ctx->edi, ctx->ebp, ctx->esp0);
+ printk("----------------------------------------------------------\n");
+ printk("Error code pushed by processor itself (if not 0) = %x\n",
+ ctx->faultCode);
+ printk("----------------------------------------------------------\n");
+ if (ctx->idtIndex == I386_EXCEPTION_PAGE_FAULT){
+ faultAddr = i386_get_cr2();
+ printk("Page fault linear address (CR2) = %x\n", faultAddr);
+ printk("----------------------------------------------------------\n\n");
+ }
+ if (_ISR_Nest_level > 0) {
+ /*
+ * In this case we shall not delete the task interrupted as
+ * it has nothing to do with the fault. We cannot return either
+ * because the eip points to the faulty instruction so...
+ */
+ printk("Exception while executing ISR!!!. System locked\n");
+ _CPU_Fatal_halt(faultAddr);
+ }
+ else {
+ /*
+ * OK I could probably use a simplified version but at least this
+ * should work.
+ */
+ printk(" ************ FAULTY THREAD WILL BE DELETED **************\n");
+ rtems_task_delete(_Thread_Executing->Object.id);
+ }
+}
+
+cpuExcHandlerType _currentExcHandler = _defaultExcHandler;
+
+extern void rtems_exception_prologue_0();
+extern void rtems_exception_prologue_1();
+extern void rtems_exception_prologue_2();
+extern void rtems_exception_prologue_3();
+extern void rtems_exception_prologue_4();
+extern void rtems_exception_prologue_5();
+extern void rtems_exception_prologue_6();
+extern void rtems_exception_prologue_7();
+extern void rtems_exception_prologue_8();
+extern void rtems_exception_prologue_9();
+extern void rtems_exception_prologue_10();
+extern void rtems_exception_prologue_11();
+extern void rtems_exception_prologue_12();
+extern void rtems_exception_prologue_13();
+extern void rtems_exception_prologue_14();
+extern void rtems_exception_prologue_16();
+extern void rtems_exception_prologue_17();
+extern void rtems_exception_prologue_18();
+
+static rtems_raw_irq_hdl tbl[] = {
+ rtems_exception_prologue_0,
+ rtems_exception_prologue_1,
+ rtems_exception_prologue_2,
+ rtems_exception_prologue_3,
+ rtems_exception_prologue_4,
+ rtems_exception_prologue_5,
+ rtems_exception_prologue_6,
+ rtems_exception_prologue_7,
+ rtems_exception_prologue_8,
+ rtems_exception_prologue_9,
+ rtems_exception_prologue_10,
+ rtems_exception_prologue_11,
+ rtems_exception_prologue_12,
+ rtems_exception_prologue_13,
+ rtems_exception_prologue_14,
+ rtems_exception_prologue_16,
+ rtems_exception_prologue_17,
+ rtems_exception_prologue_18,
+};
+
+void rtems_exception_init_mngt()
+{
+ unsigned int i,j;
+ interrupt_gate_descriptor *currentIdtEntry;
+ unsigned limit;
+ unsigned level;
+
+ i = sizeof(tbl) / sizeof (rtems_raw_irq_hdl);
+
+ i386_get_info_from_IDTR (&currentIdtEntry, &limit);
+
+ _CPU_ISR_Disable(level);
+ for (j = 0; j < i; j++) {
+ create_interrupt_gate_descriptor (&currentIdtEntry[j], tbl[j]);
+ }
+ _CPU_ISR_Enable(level);
+}
diff --git a/cpukit/score/cpu/i386/cpu_asm.S b/cpukit/score/cpu/i386/cpu_asm.S
new file mode 100644
index 0000000000..7630aa3b35
--- /dev/null
+++ b/cpukit/score/cpu/i386/cpu_asm.S
@@ -0,0 +1,274 @@
+/* cpu_asm.s
+ *
+ * This file contains all assembly code for the Intel i386 implementation
+ * of RTEMS.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/asm.h>
+
+/*
+ * Format of i386 Register structure
+ */
+
+.set REG_EFLAGS, 0
+.set REG_ESP, REG_EFLAGS + 4
+.set REG_EBP, REG_ESP + 4
+.set REG_EBX, REG_EBP + 4
+.set REG_ESI, REG_EBX + 4
+.set REG_EDI, REG_ESI + 4
+.set SIZE_REGS, REG_EDI + 4
+
+ BEGIN_CODE
+
+/*
+ * void _CPU_Context_switch( run_context, heir_context )
+ *
+ * This routine performs a normal non-FP context.
+ */
+
+ .p2align 1
+ PUBLIC (_CPU_Context_switch)
+
+.set RUNCONTEXT_ARG, 4 /* save context argument */
+.set HEIRCONTEXT_ARG, 8 /* restore context argument */
+
+SYM (_CPU_Context_switch):
+ movl RUNCONTEXT_ARG(esp),eax /* eax = running threads context */
+ pushf /* push eflags */
+ popl REG_EFLAGS(eax) /* save eflags */
+ movl esp,REG_ESP(eax) /* save stack pointer */
+ movl ebp,REG_EBP(eax) /* save base pointer */
+ movl ebx,REG_EBX(eax) /* save ebx */
+ movl esi,REG_ESI(eax) /* save source register */
+ movl edi,REG_EDI(eax) /* save destination register */
+
+ movl HEIRCONTEXT_ARG(esp),eax /* eax = heir threads context */
+
+restore:
+ pushl REG_EFLAGS(eax) /* push eflags */
+ popf /* restore eflags */
+ movl REG_ESP(eax),esp /* restore stack pointer */
+ movl REG_EBP(eax),ebp /* restore base pointer */
+ movl REG_EBX(eax),ebx /* restore ebx */
+ movl REG_ESI(eax),esi /* restore source register */
+ movl REG_EDI(eax),edi /* restore destination register */
+ ret
+
+/*
+ * NOTE: May be unnecessary to reload some registers.
+ */
+
+/*
+ * void _CPU_Context_restore( new_context )
+ *
+ * This routine performs a normal non-FP context.
+ */
+
+ PUBLIC (_CPU_Context_restore)
+
+.set NEWCONTEXT_ARG, 4 /* context to restore argument */
+
+SYM (_CPU_Context_restore):
+
+ movl NEWCONTEXT_ARG(esp),eax /* eax = running threads context */
+ jmp restore
+
+/*PAGE
+ * void _CPU_Context_save_fp_context( &fp_context_ptr )
+ * void _CPU_Context_restore_fp_context( &fp_context_ptr )
+ *
+ * This section is used to context switch an i80287, i80387,
+ * the built-in coprocessor or the i80486 or compatible.
+ */
+
+.set FPCONTEXT_ARG, 4 /* FP context argument */
+
+ .p2align 1
+ PUBLIC (_CPU_Context_save_fp)
+SYM (_CPU_Context_save_fp):
+ movl FPCONTEXT_ARG(esp),eax /* eax = &ptr to FP context area */
+ movl (eax),eax /* eax = FP context area */
+ fsave (eax) /* save FP context */
+ ret
+
+ .p2align 1
+ PUBLIC (_CPU_Context_restore_fp)
+SYM (_CPU_Context_restore_fp):
+ movl FPCONTEXT_ARG(esp),eax /* eax = &ptr to FP context area */
+ movl (eax),eax /* eax = FP context area */
+ frstor (eax) /* restore FP context */
+ ret
+
+ PUBLIC (_Exception_Handler)
+SYM (_Exception_Handler):
+ pusha /* Push general purpose registers */
+ pushl esp /* Push exception frame address */
+ movl _currentExcHandler, eax /* Call function storead in _currentExcHandler */
+ call * eax
+ addl $4, esp
+ popa /* restore general purpose registers */
+ addl $8, esp /* skill vector number and faultCode */
+ iret
+
+#define DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY(_vector) \
+ .p2align 4 ; \
+ PUBLIC (rtems_exception_prologue_ ## _vector ) ; \
+SYM (rtems_exception_prologue_ ## _vector ): \
+ pushl $ _vector ; \
+ jmp SYM (_Exception_Handler) ;
+
+#define DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY(_vector) \
+ .p2align 4 ; \
+ PUBLIC (rtems_exception_prologue_ ## _vector ) ; \
+SYM (rtems_exception_prologue_ ## _vector ): \
+ pushl $ 0 ; \
+ pushl $ _vector ; \
+ jmp SYM (_Exception_Handler) ;
+
+/*
+ * Divide Error
+ */
+DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (0)
+/*
+ * Debug Exception
+ */
+DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (1)
+/*
+ * NMI
+ */
+DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (2)
+/*
+ * Breakpoint
+ */
+DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (3)
+/*
+ * Overflow
+ */
+DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (4)
+/*
+ * Bound Range Exceeded
+ */
+DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (5)
+/*
+ * Invalid Opcode
+ */
+DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (6)
+/*
+ * No Math Coproc
+ */
+DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (7)
+/*
+ * Double Fault
+ */
+DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (8)
+/*
+ * Coprocessor segment overrun
+ */
+DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (9)
+/*
+ * Invalid TSS
+ */
+DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (10)
+/*
+ * Segment Not Present
+ */
+DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (11)
+/*
+ * Stack segment Fault
+ */
+DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (12)
+/*
+ * General Protection Fault
+ */
+DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (13)
+/*
+ * Page Fault
+ */
+DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (14)
+/*
+ * Floating point error (NB 15 is reserved it is therefor skipped)
+ */
+DISTINCT_EXCEPTION_WITHOUT_FAULTCODE_ENTRY (16)
+/*
+ * Aligment Check
+ */
+DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (17)
+/*
+ * Machine Check
+ */
+DISTINCT_EXCEPTION_WITH_FAULTCODE_ENTRY (18)
+
+
+/*
+ * void *i386_Logical_to_physical(
+ * uint16_t segment,
+ * void *address
+ * );
+ *
+ * Returns thirty-two bit physical address for segment:address.
+ */
+
+.set SEGMENT_ARG, 4
+.set ADDRESS_ARG, 8
+
+ PUBLIC (i386_Logical_to_physical)
+
+SYM (i386_Logical_to_physical):
+
+ xorl eax,eax /* clear eax */
+ movzwl SEGMENT_ARG(esp),ecx /* ecx = segment value */
+ movl $ SYM (_Global_descriptor_table),edx
+ /* edx = address of our GDT */
+ addl ecx,edx /* edx = address of desired entry */
+ movb 7(edx),ah /* ah = base 31:24 */
+ movb 4(edx),al /* al = base 23:16 */
+ shll $16,eax /* move ax into correct bits */
+ movw 2(edx),ax /* ax = base 0:15 */
+ movl ADDRESS_ARG(esp),ecx /* ecx = address to convert */
+ addl eax,ecx /* ecx = physical address equivalent */
+ movl ecx,eax /* eax = ecx */
+ ret
+
+/*
+ * void *i386_Physical_to_logical(
+ * uint16_t segment,
+ * void *address
+ * );
+ *
+ * Returns thirty-two bit physical address for segment:address.
+ */
+
+/*
+ *.set SEGMENT_ARG, 4
+ *.set ADDRESS_ARG, 8 -- use sets from above
+ */
+
+ PUBLIC (i386_Physical_to_logical)
+
+SYM (i386_Physical_to_logical):
+ xorl eax,eax /* clear eax */
+ movzwl SEGMENT_ARG(esp),ecx /* ecx = segment value */
+ movl $ SYM (_Global_descriptor_table),edx
+ /* edx = address of our GDT */
+ addl ecx,edx /* edx = address of desired entry */
+ movb 7(edx),ah /* ah = base 31:24 */
+ movb 4(edx),al /* al = base 23:16 */
+ shll $16,eax /* move ax into correct bits */
+ movw 2(edx),ax /* ax = base 0:15 */
+ movl ADDRESS_ARG(esp),ecx /* ecx = address to convert */
+ subl eax,ecx /* ecx = logical address equivalent */
+ movl ecx,eax /* eax = ecx */
+ ret
+
+END_CODE
+
+END
diff --git a/cpukit/score/cpu/i386/rtems/asm.h b/cpukit/score/cpu/i386/rtems/asm.h
new file mode 100644
index 0000000000..1793c17015
--- /dev/null
+++ b/cpukit/score/cpu/i386/rtems/asm.h
@@ -0,0 +1,143 @@
+/* asm.h
+ *
+ * This include file attempts to address the problems
+ * caused by incompatible flavors of assemblers and
+ * toolsets. It primarily addresses variations in the
+ * use of leading underscores on symbols and the requirement
+ * that register names be preceded by a %.
+ *
+ *
+ * NOTE: The spacing in the use of these macros
+ * is critical to them working as advertised.
+ *
+ * COPYRIGHT:
+ *
+ * This file is based on similar code found in newlib available
+ * from ftp.cygnus.com. The file which was used had no copyright
+ * notice. This file is freely distributable as long as the source
+ * of the file is noted. This file is:
+ *
+ * COPYRIGHT (c) 1994-1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * $Id$
+ */
+
+#ifndef __i386_ASM_h
+#define __i386_ASM_h
+
+/*
+ * Indicate we are in an assembly file and get the basic CPU definitions.
+ */
+
+#ifndef ASM
+#define ASM
+#endif
+#include <rtems/score/cpuopts.h>
+#include <rtems/score/i386.h>
+
+/*
+ * Recent versions of GNU cpp define variables which indicate the
+ * need for underscores and percents. If not using GNU cpp or
+ * the version does not support this, then you will obviously
+ * have to define these as appropriate.
+ */
+
+#ifndef __USER_LABEL_PREFIX__
+#define __USER_LABEL_PREFIX__
+#endif
+
+/*
+ * Looks like there is a bug in gcc 2.6.2 where this is not
+ * defined correctly when configured as i386-coff and
+ * i386-aout.
+ */
+
+#undef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__ %
+
+/*
+#ifndef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__
+#endif
+*/
+
+/* ANSI concatenation macros. */
+
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+#define EVAL(x) x
+#define CONCAT0(a, b) EVAL(a)EVAL(b)
+
+/* Use the right prefix for global labels. */
+
+#define SYM(x) CONCAT0 (__USER_LABEL_PREFIX__, x)
+
+/* Use the right prefix for registers. */
+
+#define REG(x) CONCAT0 (__REGISTER_PREFIX__, x)
+
+#define eax REG (eax)
+#define ebx REG (ebx)
+#define ecx REG (ecx)
+#define edx REG (edx)
+#define esi REG (esi)
+#define edi REG (edi)
+#define esp REG (esp)
+#define ebp REG (ebp)
+#define cr0 REG (cr0)
+
+#define ax REG (ax)
+#define bx REG (bx)
+#define cx REG (cx)
+#define dx REG (dx)
+#define si REG (si)
+#define di REG (di)
+#define sp REG (sp)
+#define bp REG (bp)
+
+#define ah REG (ah)
+#define bh REG (bh)
+#define ch REG (ch)
+#define dh REG (dh)
+
+#define al REG (al)
+#define bl REG (bl)
+#define cl REG (cl)
+#define dl REG (dl)
+
+#define cs REG (cs)
+#define ds REG (ds)
+#define es REG (es)
+#define fs REG (fs)
+#define gs REG (gs)
+#define ss REG (ss)
+
+/*
+ * Define macros to handle section beginning and ends.
+ */
+
+
+#define BEGIN_CODE_DCL .text
+#define END_CODE_DCL
+#define BEGIN_DATA_DCL .data
+#define END_DATA_DCL
+#define BEGIN_CODE .text
+#define END_CODE
+#define BEGIN_DATA .data
+#define END_DATA
+#define BEGIN_BSS .bss
+#define END_BSS
+#define END
+
+/*
+ * Following must be tailor for a particular flavor of the C compiler.
+ * They may need to put underscores in front of the symbols.
+ */
+
+#define PUBLIC(sym) .globl SYM (sym)
+#define EXTERN(sym) .globl SYM (sym)
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/i386/rtems/score/cpu.h b/cpukit/score/cpu/i386/rtems/score/cpu.h
new file mode 100644
index 0000000000..eb75cedcf9
--- /dev/null
+++ b/cpukit/score/cpu/i386/rtems/score/cpu.h
@@ -0,0 +1,513 @@
+/* cpu.h
+ *
+ * This include file contains information pertaining to the Intel
+ * i386 processor.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __CPU_h
+#define __CPU_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/i386.h> /* pick up machine definitions */
+
+#ifndef ASM
+#include <rtems/score/types.h>
+#include <rtems/score/interrupts.h> /* formerly in libcpu/cpu.h> */
+#include <rtems/score/registers.h> /* formerly part of libcpu */
+#endif
+
+/* conditional compilation parameters */
+
+#define CPU_INLINE_ENABLE_DISPATCH TRUE
+#define CPU_UNROLL_ENQUEUE_PRIORITY FALSE
+
+/*
+ * i386 has an RTEMS allocated and managed interrupt stack.
+ */
+
+#define CPU_HAS_SOFTWARE_INTERRUPT_STACK TRUE
+#define CPU_HAS_HARDWARE_INTERRUPT_STACK FALSE
+#define CPU_ALLOCATE_INTERRUPT_STACK TRUE
+
+/*
+ * Does the RTEMS invoke the user's ISR with the vector number and
+ * a pointer to the saved interrupt frame (1) or just the vector
+ * number (0)?
+ */
+
+#define CPU_ISR_PASSES_FRAME_POINTER 0
+
+/*
+ * Some family members have no FP, some have an FPU such as the i387
+ * for the i386, others have it built in (i486DX, Pentium).
+ */
+
+#if ( I386_HAS_FPU == 1 )
+#define CPU_HARDWARE_FP TRUE /* i387 for i386 */
+#else
+#define CPU_HARDWARE_FP FALSE
+#endif
+#define CPU_SOFTWARE_FP FALSE
+
+#define CPU_ALL_TASKS_ARE_FP FALSE
+#define CPU_IDLE_TASK_IS_FP FALSE
+#define CPU_USE_DEFERRED_FP_SWITCH TRUE
+
+#define CPU_STACK_GROWS_UP FALSE
+#define CPU_STRUCTURE_ALIGNMENT
+
+/*
+ * Does this port provide a CPU dependent IDLE task implementation?
+ *
+ * If TRUE, then the routine _CPU_Thread_Idle_body
+ * must be provided and is the default IDLE thread body instead of
+ * _CPU_Thread_Idle_body.
+ *
+ * If FALSE, then use the generic IDLE thread body if the BSP does
+ * not provide one.
+ */
+
+#define CPU_PROVIDES_IDLE_THREAD_BODY TRUE
+
+/*
+ * Define what is required to specify how the network to host conversion
+ * routines are handled.
+ */
+
+#define CPU_HAS_OWN_HOST_TO_NETWORK_ROUTINES FALSE
+#define CPU_BIG_ENDIAN FALSE
+#define CPU_LITTLE_ENDIAN TRUE
+
+/* structures */
+
+/*
+ * Basic integer context for the i386 family.
+ */
+
+typedef struct {
+ uint32_t eflags; /* extended flags register */
+ void *esp; /* extended stack pointer register */
+ void *ebp; /* extended base pointer register */
+ uint32_t ebx; /* extended bx register */
+ uint32_t esi; /* extended source index register */
+ uint32_t edi; /* extended destination index flags register */
+} Context_Control;
+
+/*
+ * FP context save area for the i387 numeric coprocessors.
+ */
+
+typedef struct {
+ uint8_t fp_save_area[108]; /* context size area for I80387 */
+ /* 28 bytes for environment */
+} Context_Control_fp;
+
+
+/*
+ * The following structure defines the set of information saved
+ * on the current stack by RTEMS upon receipt of execptions.
+ *
+ * idtIndex is either the interrupt number or the trap/exception number.
+ * faultCode is the code pushed by the processor on some exceptions.
+ */
+
+typedef struct {
+ uint32_t edi;
+ uint32_t esi;
+ uint32_t ebp;
+ uint32_t esp0;
+ uint32_t ebx;
+ uint32_t edx;
+ uint32_t ecx;
+ uint32_t eax;
+ uint32_t idtIndex;
+ uint32_t faultCode;
+ uint32_t eip;
+ uint32_t cs;
+ uint32_t eflags;
+} CPU_Exception_frame;
+
+typedef void (*cpuExcHandlerType) (CPU_Exception_frame*);
+extern cpuExcHandlerType _currentExcHandler;
+extern void rtems_exception_init_mngt();
+
+/*
+ * The following structure defines the set of information saved
+ * on the current stack by RTEMS upon receipt of each interrupt
+ * that will lead to re-enter the kernel to signal the thread.
+ */
+
+typedef CPU_Exception_frame CPU_Interrupt_frame;
+
+typedef enum {
+ I386_EXCEPTION_DIVIDE_BY_ZERO = 0,
+ I386_EXCEPTION_DEBUG = 1,
+ I386_EXCEPTION_NMI = 2,
+ I386_EXCEPTION_BREAKPOINT = 3,
+ I386_EXCEPTION_OVERFLOW = 4,
+ I386_EXCEPTION_BOUND = 5,
+ I386_EXCEPTION_ILLEGAL_INSTR = 6,
+ I386_EXCEPTION_MATH_COPROC_UNAVAIL = 7,
+ I386_EXCEPTION_DOUBLE_FAULT = 8,
+ I386_EXCEPTION_I386_COPROC_SEG_ERR = 9,
+ I386_EXCEPTION_INVALID_TSS = 10,
+ I386_EXCEPTION_SEGMENT_NOT_PRESENT = 11,
+ I386_EXCEPTION_STACK_SEGMENT_FAULT = 12,
+ I386_EXCEPTION_GENERAL_PROT_ERR = 13,
+ I386_EXCEPTION_PAGE_FAULT = 14,
+ I386_EXCEPTION_INTEL_RES15 = 15,
+ I386_EXCEPTION_FLOAT_ERROR = 16,
+ I386_EXCEPTION_ALIGN_CHECK = 17,
+ I386_EXCEPTION_MACHINE_CHECK = 18,
+ I386_EXCEPTION_ENTER_RDBG = 50 /* to enter manually RDBG */
+
+} Intel_symbolic_exception_name;
+
+
+/*
+ * The following table contains the information required to configure
+ * the i386 specific parameters.
+ */
+
+typedef struct {
+ void (*pretasking_hook)( void );
+ void (*predriver_hook)( void );
+ void (*postdriver_hook)( void );
+ void (*idle_task)( void );
+ boolean do_zero_of_workspace;
+ uint32_t idle_task_stack_size;
+ uint32_t interrupt_stack_size;
+ uint32_t extra_mpci_receive_server_stack;
+ void * (*stack_allocate_hook)( uint32_t );
+ void (*stack_free_hook)( void* );
+ /* end of fields required on all CPUs */
+
+ uint32_t interrupt_table_segment;
+ void *interrupt_table_offset;
+} rtems_cpu_table;
+
+/*
+ * Macros to access required entires in the CPU Table are in
+ * the file rtems/system.h.
+ */
+
+/*
+ * Macros to access i386 specific additions to the CPU Table
+ */
+
+#define rtems_cpu_configuration_get_interrupt_table_segment() \
+ (_CPU_Table.interrupt_table_segment)
+
+#define rtems_cpu_configuration_get_interrupt_table_offset() \
+ (_CPU_Table.interrupt_table_offset)
+
+/*
+ * context size area for floating point
+ *
+ * NOTE: This is out of place on the i386 to avoid a forward reference.
+ */
+
+#define CPU_CONTEXT_FP_SIZE sizeof( Context_Control_fp )
+
+/* variables */
+
+SCORE_EXTERN Context_Control_fp _CPU_Null_fp_context;
+SCORE_EXTERN void *_CPU_Interrupt_stack_low;
+SCORE_EXTERN void *_CPU_Interrupt_stack_high;
+
+/* constants */
+
+/*
+ * This defines the number of levels and the mask used to pick those
+ * bits out of a thread mode.
+ */
+
+#define CPU_MODES_INTERRUPT_LEVEL 0x00000001 /* interrupt level in mode */
+#define CPU_MODES_INTERRUPT_MASK 0x00000001 /* interrupt level in mode */
+
+/*
+ * extra stack required by the MPCI receive server thread
+ */
+
+#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 1024
+
+/*
+ * i386 family supports 256 distinct vectors.
+ */
+
+#define CPU_INTERRUPT_NUMBER_OF_VECTORS 256
+#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1)
+
+/*
+ * This is defined if the port has a special way to report the ISR nesting
+ * level. Most ports maintain the variable _ISR_Nest_level.
+ */
+
+#define CPU_PROVIDES_ISR_IS_IN_PROGRESS FALSE
+
+/*
+ * Minimum size of a thread's stack.
+ */
+
+#define CPU_STACK_MINIMUM_SIZE 1024
+
+/*
+ * i386 is pretty tolerant of alignment. Just put things on 4 byte boundaries.
+ */
+
+#define CPU_ALIGNMENT 4
+#define CPU_HEAP_ALIGNMENT CPU_ALIGNMENT
+#define CPU_PARTITION_ALIGNMENT CPU_ALIGNMENT
+
+/*
+ * On i386 thread stacks require no further alignment after allocation
+ * from the Workspace.
+ */
+
+#define CPU_STACK_ALIGNMENT 0
+
+/* macros */
+
+/*
+ * ISR handler macros
+ *
+ * These macros perform the following functions:
+ * + initialize the RTEMS vector table
+ * + disable all maskable CPU interrupts
+ * + restore previous interrupt level (enable)
+ * + temporarily restore interrupts (flash)
+ * + set a particular level
+ */
+
+#define _CPU_Initialize_vectors()
+
+#define _CPU_ISR_Disable( _level ) i386_disable_interrupts( _level )
+
+#define _CPU_ISR_Enable( _level ) i386_enable_interrupts( _level )
+
+#define _CPU_ISR_Flash( _level ) i386_flash_interrupts( _level )
+
+#define _CPU_ISR_Set_level( _new_level ) \
+ { \
+ if ( _new_level ) asm volatile ( "cli" ); \
+ else asm volatile ( "sti" ); \
+ }
+
+uint32_t _CPU_ISR_Get_level( void );
+
+/* end of ISR handler macros */
+
+/*
+ * Context handler macros
+ *
+ * These macros perform the following functions:
+ * + initialize a context area
+ * + restart the current thread
+ * + calculate the initial pointer into a FP context area
+ * + initialize an FP context area
+ */
+
+#define CPU_EFLAGS_INTERRUPTS_ON 0x00003202
+#define CPU_EFLAGS_INTERRUPTS_OFF 0x00003002
+
+#define _CPU_Context_Initialize( _the_context, _stack_base, _size, \
+ _isr, _entry_point, _is_fp ) \
+ do { \
+ uint32_t _stack; \
+ \
+ if ( (_isr) ) (_the_context)->eflags = CPU_EFLAGS_INTERRUPTS_OFF; \
+ else (_the_context)->eflags = CPU_EFLAGS_INTERRUPTS_ON; \
+ \
+ _stack = ((uint32_t )(_stack_base)) + (_size) - 4; \
+ \
+ *((proc_ptr *)(_stack)) = (_entry_point); \
+ (_the_context)->ebp = (void *) _stack; \
+ (_the_context)->esp = (void *) _stack; \
+ } while (0)
+
+#define _CPU_Context_Restart_self( _the_context ) \
+ _CPU_Context_restore( (_the_context) );
+
+#define _CPU_Context_Fp_start( _base, _offset ) \
+ ( (void *) _Addresses_Add_offset( (_base), (_offset) ) )
+
+#define _CPU_Context_Initialize_fp( _fp_area ) \
+ { \
+ uint32_t *_source = (uint32_t *) &_CPU_Null_fp_context; \
+ uint32_t *_destination = *(_fp_area); \
+ uint32_t _index; \
+ \
+ for ( _index=0 ; _index < CPU_CONTEXT_FP_SIZE/4 ; _index++ ) \
+ *_destination++ = *_source++; \
+ }
+
+/* end of Context handler macros */
+
+/*
+ * Fatal Error manager macros
+ *
+ * These macros perform the following functions:
+ * + disable interrupts and halt the CPU
+ */
+
+#define _CPU_Fatal_halt( _error ) \
+ { \
+ asm volatile ( "cli ; \
+ movl %0,%%eax ; \
+ hlt" \
+ : "=r" ((_error)) : "0" ((_error)) \
+ ); \
+ }
+
+/* end of Fatal Error manager macros */
+
+/*
+ * Bitfield handler macros
+ *
+ * These macros perform the following functions:
+ * + scan for the highest numbered (MSB) set in a 16 bit bitfield
+ */
+
+#define CPU_USE_GENERIC_BITFIELD_CODE FALSE
+#define CPU_USE_GENERIC_BITFIELD_DATA FALSE
+
+#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
+ { \
+ register uint16_t __value_in_register = (_value); \
+ \
+ _output = 0; \
+ \
+ asm volatile ( "bsfw %0,%1 " \
+ : "=r" (__value_in_register), "=r" (_output) \
+ : "0" (__value_in_register), "1" (_output) \
+ ); \
+ }
+
+/* end of Bitfield handler macros */
+
+/*
+ * Priority handler macros
+ *
+ * These macros perform the following functions:
+ * + return a mask with the bit for this major/minor portion of
+ * of thread priority set.
+ * + translate the bit number returned by "Bitfield_find_first_bit"
+ * into an index into the thread ready chain bit maps
+ */
+
+#define _CPU_Priority_Mask( _bit_number ) \
+ ( 1 << (_bit_number) )
+
+#define _CPU_Priority_bits_index( _priority ) \
+ (_priority)
+
+/* functions */
+
+/*
+ * _CPU_Initialize
+ *
+ * This routine performs CPU dependent initialization.
+ */
+
+void _CPU_Initialize(
+ rtems_cpu_table *cpu_table,
+ void (*thread_dispatch)
+);
+
+/*
+ * _CPU_ISR_install_raw_handler
+ *
+ * This routine installs a "raw" interrupt handler directly into the
+ * processor's vector table.
+ */
+
+void _CPU_ISR_install_raw_handler(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+);
+
+/*
+ * _CPU_ISR_install_vector
+ *
+ * This routine installs an interrupt vector.
+ */
+
+void _CPU_ISR_install_vector(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+);
+
+/*
+ * _CPU_Thread_Idle_body
+ *
+ * Use the halt instruction of low power mode of a particular i386 model.
+ */
+
+#if (CPU_PROVIDES_IDLE_THREAD_BODY == TRUE)
+
+void _CPU_Thread_Idle_body( void );
+
+#endif /* CPU_PROVIDES_IDLE_THREAD_BODY */
+
+/*
+ * _CPU_Context_switch
+ *
+ * This routine switches from the run context to the heir context.
+ */
+
+void _CPU_Context_switch(
+ Context_Control *run,
+ Context_Control *heir
+);
+
+/*
+ * _CPU_Context_restore
+ *
+ * This routine is generally used only to restart self in an
+ * efficient manner and avoid stack conflicts.
+ */
+
+void _CPU_Context_restore(
+ Context_Control *new_context
+);
+
+/*
+ * _CPU_Context_save_fp
+ *
+ * This routine saves the floating point context passed to it.
+ */
+
+void _CPU_Context_save_fp(
+ void **fp_context_ptr
+);
+
+/*
+ * _CPU_Context_restore_fp
+ *
+ * This routine restores the floating point context passed to it.
+ */
+
+void _CPU_Context_restore_fp(
+ void **fp_context_ptr
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/i386/rtems/score/i386.h b/cpukit/score/cpu/i386/rtems/score/i386.h
new file mode 100644
index 0000000000..7116ce1911
--- /dev/null
+++ b/cpukit/score/cpu/i386/rtems/score/i386.h
@@ -0,0 +1,244 @@
+/* i386.h
+ *
+ * This include file contains information pertaining to the Intel
+ * i386 processor.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __i386_h
+#define __i386_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This section contains the information required to build
+ * RTEMS for a particular member of the Intel i386
+ * family when executing in protected mode. It does
+ * this by setting variables to indicate which implementation
+ * dependent features are present in a particular member
+ * of the family.
+ *
+ * Currently recognized:
+ * i386_fp (i386 DX or SX w/i387)
+ * i386_nofp (i386 DX or SX w/o i387)
+ * i486dx
+ * i486sx
+ * pentium
+ * pentiumpro
+ *
+ * CPU Model Feature Flags:
+ *
+ * I386_HAS_BSWAP: Defined to "1" if the instruction for endian swapping
+ * (bswap) should be used. This instruction appears to
+ * be present in all i486's and above.
+ *
+ * I386_HAS_FPU: Defined to "1" if the CPU has an FPU.
+ *
+ */
+
+#if defined(_SOFT_FLOAT)
+#define I386_HAS_FPU 0
+#else
+#define I386_HAS_FPU 1
+#endif
+
+#if defined(__pentiumpro__)
+
+#define CPU_MODEL_NAME "Pentium Pro"
+
+#elif defined(__i586__)
+
+# if defined(__pentium__)
+# define CPU_MODEL_NAME "Pentium"
+# elif defined(__k6__)
+# define CPU_MODEL_NAME "K6"
+# else
+# define CPU_MODEL_NAME "i586"
+# endif
+
+#elif defined(__i486__)
+
+# if !defined(_SOFT_FLOAT)
+# define CPU_MODEL_NAME "i486dx"
+# else
+# define CPU_MODEL_NAME "i486sx"
+# endif
+
+#elif defined(__i386__)
+
+#define I386_HAS_BSWAP 0
+
+# if !defined(_SOFT_FLOAT)
+# define CPU_MODEL_NAME "i386 with i387"
+# else
+# define CPU_MODEL_NAME "i386 w/o i387"
+# endif
+
+#else
+#error "Unknown CPU Model"
+#endif
+
+/*
+ * Set default values for CPU model feature flags
+ *
+ * NOTE: These settings are chosen to reflect most of the family members.
+ */
+
+#ifndef I386_HAS_FPU
+#define I386_HAS_FPU 1
+#endif
+
+#ifndef I386_HAS_BSWAP
+#define I386_HAS_BSWAP 1
+#endif
+
+/*
+ * Define the name of the CPU family.
+ */
+
+#define CPU_NAME "Intel i386"
+
+#ifndef ASM
+
+/*
+ * The following routine swaps the endian format of an unsigned int.
+ * It must be static so it can be referenced indirectly.
+ */
+
+static inline unsigned int i386_swap_u32(
+ unsigned int value
+)
+{
+ unsigned long lout;
+
+#if (I386_HAS_BSWAP == 0)
+ asm volatile( "rorw $8,%%ax;"
+ "rorl $16,%0;"
+ "rorw $8,%%ax" : "=a" (lout) : "0" (value) );
+#else
+ __asm__ volatile( "bswap %0" : "=r" (lout) : "0" (value));
+#endif
+ return( lout );
+}
+
+static inline unsigned int i386_swap_u16(
+ unsigned int value
+)
+{
+ unsigned short sout;
+
+ __asm__ volatile( "rorw $8,%0" : "=r" (sout) : "0" (value));
+ return (sout);
+}
+
+
+/*
+ * Added for pagination management
+ */
+
+static inline unsigned int i386_get_cr0()
+{
+ register unsigned int segment = 0;
+
+ asm volatile ( "movl %%cr0,%0" : "=r" (segment) : "0" (segment) );
+
+ return segment;
+}
+
+static inline void i386_set_cr0(unsigned int segment)
+{
+ asm volatile ( "movl %0,%%cr0" : "=r" (segment) : "0" (segment) );
+}
+
+static inline unsigned int i386_get_cr2()
+{
+ register unsigned int segment = 0;
+
+ asm volatile ( "movl %%cr2,%0" : "=r" (segment) : "0" (segment) );
+
+ return segment;
+}
+
+static inline unsigned int i386_get_cr3()
+{
+ register unsigned int segment = 0;
+
+ asm volatile ( "movl %%cr3,%0" : "=r" (segment) : "0" (segment) );
+
+ return segment;
+}
+
+static inline void i386_set_cr3(unsigned int segment)
+{
+ asm volatile ( "movl %0,%%cr3" : "=r" (segment) : "0" (segment) );
+}
+
+/* routines */
+
+/*
+ * i386_Logical_to_physical
+ *
+ * Converts logical address to physical address.
+ */
+
+void *i386_Logical_to_physical(
+ unsigned short segment,
+ void *address
+);
+
+/*
+ * i386_Physical_to_logical
+ *
+ * Converts physical address to logical address.
+ */
+
+void *i386_Physical_to_logical(
+ unsigned short segment,
+ void *address
+);
+
+
+/*
+ * "Simpler" names for a lot of the things defined in this file
+ */
+
+/* segment access routines */
+
+#define get_cs() i386_get_cs()
+#define get_ds() i386_get_ds()
+#define get_es() i386_get_es()
+#define get_ss() i386_get_ss()
+#define get_fs() i386_get_fs()
+#define get_gs() i386_get_gs()
+
+#define CPU_swap_u32( _value ) i386_swap_u32( _value )
+#define CPU_swap_u16( _value ) i386_swap_u16( _value )
+
+/* i80x86 I/O instructions */
+
+#define outport_byte( _port, _value ) i386_outport_byte( _port, _value )
+#define outport_word( _port, _value ) i386_outport_word( _port, _value )
+#define outport_long( _port, _value ) i386_outport_long( _port, _value )
+#define inport_byte( _port, _value ) i386_inport_byte( _port, _value )
+#define inport_word( _port, _value ) i386_inport_word( _port, _value )
+#define inport_long( _port, _value ) i386_inport_long( _port, _value )
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !ASM */
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/i386/rtems/score/idtr.h b/cpukit/score/cpu/i386/rtems/score/idtr.h
new file mode 100644
index 0000000000..34ba3f9ebb
--- /dev/null
+++ b/cpukit/score/cpu/i386/rtems/score/idtr.h
@@ -0,0 +1,62 @@
+/*
+ * This file contains definitions for data structure related
+ * to Intel system programming. More information can be found
+ * on Intel site and more precisely in the following book :
+ *
+ * Pentium Processor familly
+ * Developper's Manual
+ *
+ * Volume 3 : Architecture and Programming Manual
+ *
+ * Formerly contained in and extracted from libcpu/i386/cpu.h.
+ *
+ * Copyright (C) 1998 Eric Valette (valette@crf.canon.fr)
+ * Canon Centre Recherche France.
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ *
+ * Applications must not include this file directly.
+ */
+
+#ifndef _rtems_score_idtr_h
+#define _rtems_score_idtr_h
+
+/*
+ * See page 14.9 Figure 14-2.
+ *
+ */
+typedef struct
+{
+ unsigned int low_offsets_bits:16;
+ unsigned int segment_selector:16;
+ unsigned int fixed_value_bits:8;
+ unsigned int gate_type:5;
+ unsigned int privilege:2;
+ unsigned int present:1;
+ unsigned int high_offsets_bits:16;
+} interrupt_gate_descriptor;
+
+/*
+ * C callable function enabling to create a interrupt_gate_descriptor
+ */
+extern void create_interrupt_gate_descriptor (interrupt_gate_descriptor*, rtems_raw_irq_hdl);
+
+/*
+ * C callable function enabling to get easily usable info from
+ * the actual value of IDT register.
+ */
+extern void i386_get_info_from_IDTR (interrupt_gate_descriptor** table,
+ unsigned* limit);
+
+/*
+ * C callable function enabling to change the value of IDT register. Must be called
+ * with interrupts masked at processor level!!!.
+ */
+extern void i386_set_IDTR (interrupt_gate_descriptor* table,
+ unsigned limit);
+
+#endif
diff --git a/cpukit/score/cpu/i386/rtems/score/interrupts.h b/cpukit/score/cpu/i386/rtems/score/interrupts.h
new file mode 100644
index 0000000000..7024859392
--- /dev/null
+++ b/cpukit/score/cpu/i386/rtems/score/interrupts.h
@@ -0,0 +1,75 @@
+/*
+ * i386 interrupt macros.
+ *
+ * Formerly contained in and extracted from libcpu/i386/cpu.h
+ *
+ * COPYRIGHT (c) 1998 valette@crf.canon.fr
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ *
+ * Applications must not include this file directly.
+ */
+
+#ifndef _rtems_score_interrupts_h
+#define _rtems_score_interrupts_h
+
+#ifndef ASM
+
+struct __rtems_raw_irq_connect_data__;
+
+typedef void (*rtems_raw_irq_hdl) (void);
+typedef void (*rtems_raw_irq_enable) (const struct __rtems_raw_irq_connect_data__*);
+typedef void (*rtems_raw_irq_disable) (const struct __rtems_raw_irq_connect_data__*);
+typedef int (*rtems_raw_irq_is_enabled) (const struct __rtems_raw_irq_connect_data__*);
+
+/*
+ * Interrupt Level Macros
+ */
+
+#define i386_disable_interrupts( _level ) \
+ { \
+ asm volatile ( "pushf ; \
+ cli ; \
+ pop %0" \
+ : "=rm" ((_level)) \
+ ); \
+ }
+
+#define i386_enable_interrupts( _level ) \
+ { \
+ asm volatile ( "push %0 ; \
+ popf" \
+ : : "rm" ((_level)) : "cc" \
+ ); \
+ }
+
+#define i386_flash_interrupts( _level ) \
+ { \
+ asm volatile ( "push %0 ; \
+ popf ; \
+ cli" \
+ : : "rm" ((_level)) : "cc" \
+ ); \
+ }
+
+#define i386_get_interrupt_level( _level ) \
+ do { \
+ register uint32_t _eflags; \
+ \
+ asm volatile ( "pushf ; \
+ pop %0" \
+ : "=rm" ((_eflags)) \
+ ); \
+ \
+ _level = (_eflags & EFLAGS_INTR_ENABLE) ? 0 : 1; \
+ } while (0)
+
+#define _CPU_ISR_Disable( _level ) i386_disable_interrupts( _level )
+#define _CPU_ISR_Enable( _level ) i386_enable_interrupts( _level )
+
+#endif
+#endif
diff --git a/cpukit/score/cpu/i386/rtems/score/registers.h b/cpukit/score/cpu/i386/rtems/score/registers.h
new file mode 100644
index 0000000000..41e97abb16
--- /dev/null
+++ b/cpukit/score/cpu/i386/rtems/score/registers.h
@@ -0,0 +1,183 @@
+/* registers.h
+ *
+ * This file contains definition and constants related to Intel Cpu
+ *
+ * COPYRIGHT (c) 1998 valette@crf.canon.fr
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef _rtems_score_registers_h
+#define _rtems_score_registers_h
+
+/*
+ * definition related to EFLAGS
+ */
+#define EFLAGS_CARRY 0x1
+#define EFLAGS_PARITY 0x4
+
+#define EFLAGS_AUX_CARRY 0x10
+#define EFLAGS_ZERO 0x40
+#define EFLAGS_SIGN 0x80
+
+#define EFLAGS_TRAP 0x100
+#define EFLAGS_INTR_ENABLE 0x200
+#define EFLAGS_DIRECTION 0x400
+#define EFLAGS_OVERFLOW 0x800
+
+#define EFLAGS_IOPL_MASK 0x3000
+#define EFLAGS_NESTED_TASK 0x8000
+
+#define EFLAGS_RESUME 0x10000
+#define EFLAGS_VIRTUAL_MODE 0x20000
+#define EFLAGS_ALIGN_CHECK 0x40000
+#define EFLAGS_VIRTUAL_INTR 0x80000
+
+#define EFLAGS_VIRTUAL_INTR_PEND 0x100000
+#define EFLAGS_ID 0x200000
+
+/*
+ * definitions related to CR0
+ */
+#define CR0_PROTECTION_ENABLE 0x1
+#define CR0_MONITOR_COPROC 0x2
+#define CR0_COPROC_SOFT_EMUL 0x4
+#define CR0_FLOATING_INSTR_EXCEPTION 0x8
+
+#define CR0_EXTENSION_TYPE 0x10
+#define CR0_NUMERIC_ERROR 0x20
+
+#define CR0_WRITE_PROTECT 0x10000
+#define CR0_ALIGMENT_MASK 0x40000
+
+#define CR0_NO_WRITE_THROUGH 0x20000000
+#define CR0_PAGE_LEVEL_CACHE_DISABLE 0x40000000
+#define CR0_PAGING 0x80000000
+
+/*
+ * definitions related to CR3
+ */
+
+#define CR3_PAGE_CACHE_DISABLE 0x10
+#define CR3_PAGE_WRITE_THROUGH 0x8
+
+
+#ifndef ASM
+
+/*
+ * definition of eflags registers has a bit field structure
+ */
+typedef struct {
+ /*
+ * fist byte : bits 0->7
+ */
+ unsigned int carry : 1;
+ unsigned int : 1;
+ unsigned int parity : 1;
+ unsigned int : 1;
+
+ unsigned int auxiliary_carry : 1;
+ unsigned int : 1;
+ unsigned int zero : 1; /* result is zero */
+ unsigned int sign : 1; /* result is less than zero */
+ /*
+ * Second byte : bits 7->15
+ */
+ unsigned int trap : 1;
+ unsigned int intr_enable : 1; /* set => intr on */
+ unsigned int direction : 1; /* set => autodecrement */
+ unsigned int overflow : 1;
+
+ unsigned int IO_privilege : 2;
+ unsigned int nested_task : 1;
+ unsigned int : 1;
+ /*
+ * Third byte : bits 15->23
+ */
+ unsigned int resume : 1;
+ unsigned int virtual_mode : 1;
+ unsigned int aligment_check : 1;
+ unsigned int virtual_intr : 1;
+
+ unsigned int virtual_intr_pending : 1;
+ unsigned int id : 1;
+ unsigned int : 2;
+
+ /*
+ * fourth byte : bits 24->31 : UNUSED
+ */
+ unsigned int : 8;
+}eflags_bits;
+
+typedef union {
+ eflags_bits eflags;
+ unsigned int i;
+}eflags;
+/*
+ * definition of eflags registers has a bit field structure
+ */
+typedef struct {
+ /*
+ * fist byte : bits 0->7
+ */
+ unsigned int protection_enable : 1;
+ unsigned int monitor_coproc : 1;
+ unsigned int coproc_soft_emul : 1;
+ unsigned int floating_instr_except : 1;
+
+ unsigned int extension_type : 1;
+ unsigned int numeric_error : 1;
+ unsigned int : 2;
+ /*
+ * second byte 8->15 : UNUSED
+ */
+ unsigned int : 8;
+ /*
+ * third byte 16->23
+ */
+ unsigned int write_protect : 1;
+ unsigned int : 1;
+ unsigned int aligment_mask : 1;
+ unsigned int : 1;
+
+ unsigned int : 4;
+ /*
+ * fourth byte 24->31
+ */
+ unsigned int : 4;
+
+ unsigned int : 1;
+ unsigned int no_write_through : 1;
+ unsigned int page_level_cache_disable : 1;
+ unsigned int paging : 1;
+}cr0_bits;
+
+typedef union {
+ cr0_bits cr0;
+ unsigned int i;
+}cr0;
+
+/*
+ * definition of cr3 registers has a bit field structure
+ */
+typedef struct {
+
+ unsigned int : 3;
+ unsigned int page_write_transparent : 1;
+ unsigned int page_cache_disable : 1;
+ unsigned int : 7;
+ unsigned int page_directory_base :20;
+}cr3_bits;
+
+typedef union {
+ cr3_bits cr3;
+ unsigned int i;
+}cr3;
+
+#endif
+
+#endif
diff --git a/cpukit/score/cpu/i386/rtems/score/types.h b/cpukit/score/cpu/i386/rtems/score/types.h
new file mode 100644
index 0000000000..e52cbeb41a
--- /dev/null
+++ b/cpukit/score/cpu/i386/rtems/score/types.h
@@ -0,0 +1,57 @@
+/* i386types.h
+ *
+ * This include file contains type definitions pertaining to the Intel
+ * i386 processor family.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __i386_TYPES_h
+#define __i386_TYPES_h
+
+#ifndef ASM
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This section defines the basic types for this processor.
+ */
+
+typedef unsigned char unsigned8; /* unsigned 8-bit integer */
+typedef unsigned short unsigned16; /* unsigned 16-bit integer */
+typedef unsigned int unsigned32; /* unsigned 32-bit integer */
+typedef unsigned long long unsigned64; /* unsigned 64-bit integer */
+
+typedef unsigned16 Priority_Bit_map_control;
+
+typedef signed char signed8; /* 8-bit signed integer */
+typedef signed short signed16; /* 16-bit signed integer */
+typedef signed int signed32; /* 32-bit signed integer */
+typedef signed long long signed64; /* 64 bit signed integer */
+
+typedef unsigned32 boolean; /* Boolean value */
+
+typedef float single_precision; /* single precision float */
+typedef double double_precision; /* double precision float */
+
+typedef void i386_isr;
+
+typedef i386_isr ( *i386_isr_entry )( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !ASM */
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/i960/.cvsignore b/cpukit/score/cpu/i960/.cvsignore
new file mode 100644
index 0000000000..282522db03
--- /dev/null
+++ b/cpukit/score/cpu/i960/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/cpukit/score/cpu/i960/ChangeLog b/cpukit/score/cpu/i960/ChangeLog
new file mode 100644
index 0000000000..bd3494374a
--- /dev/null
+++ b/cpukit/score/cpu/i960/ChangeLog
@@ -0,0 +1,224 @@
+2004-04-06 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * configure.ac: Remove (Merged into $(top_srcdir)/configure.ac).
+ * Makefile.am: Don't include multilib.am.
+ Reflect merging configure.ac into $(top_srcdir)/configure.ac.
+
+2004-04-01 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * Makefile.am: Install asm.h to $(includedir)/rtems.
+
+2004-03-30 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * cpu.c, rtems/score/cpu.h: Convert to using c99 fixed size types.
+
+2004-03-29 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * configure.ac: RTEMS_TOP([../../../..]).
+
+2004-01-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Move RTEMS_TOP one subdir down.
+
+2004-01-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add PREINSTALL_DIRS.
+
+2004-01-14 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Re-add dirstamps to PREINSTALL_FILES.
+ Add PREINSTALL_FILES to CLEANFILES.
+
+2004-01-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Requires automake >= 1.8.1.
+
+2004-01-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include compile.am, again.
+
+2004-01-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Convert to using automake compilation rules.
+
+2003-12-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use mkdir_p. Remove dirs from PREINSTALL_FILES.
+
+2003-12-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Require automake >= 1.8, autoconf >= 2.59.
+
+2003-12-01 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Remove TMPINSTALL_FILES.
+
+2003-11-30 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add $(dirstamp) to preinstallation rules.
+
+2003-11-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Don't use gmake rules for preinstallation.
+
+2003-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_CANONICAL_HOST.
+
+2003-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_CHECK_CPU.
+
+2003-09-04 Joel Sherrill <joel@OARcorp.com>
+
+ * cpu.c, cpu_asm.S, rtems/score/cpu.h, rtems/score/i960.h,
+ rtems/score/types.h: URL for license changed.
+
+2003-08-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use rtems-bugs@rtems.com as bug report email address.
+
+2003-03-06 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove AC_CONFIG_AUX_DIR.
+
+2002-12-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Require autoconf-2.57 + automake-1.7.2.
+ * Makefile.am: Eliminate C_O_FILES, S_O_FILES, libscorecpu_a_OBJECTS.
+
+2002-11-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Fix package name.
+
+2002-10-25 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Add nostdinc to AM_INIT_AUTOMAKE.
+
+2002-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * .cvsignore: Reformat.
+ Add autom4te*cache.
+ Remove autom4te.cache.
+
+2002-07-26 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Build libscorecpu.a instead of rtems-cpu.rel.
+
+2002-07-22 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use .$(OBJEXT) instead of .o.
+
+2002-07-05 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: RTEMS_TOP(../../../..).
+
+2002-07-03 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems.S: Remove.
+ * Makefile.am: Reflect changes above.
+
+2002-07-01 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_PROJECT_ROOT.
+
+2002-06-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Add RTEMS_PROG_CCAS
+
+2002-06-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use AC_CONFIG_AUX_DIR(../../../..).
+ Add AC_PROG_RANLIB.
+
+2002-06-17 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include $(top_srcdir)/../../../automake/*.am.
+ Use ../../../aclocal.
+
+2002-06-17 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include $(top_srcdir)/../../../automake/*.am.
+ Use ../../../aclocal.
+
+2001-04-03 Joel Sherrill <joel@OARcorp.com>
+
+ * Per PR94, all rtems/score/CPUtypes.h are named rtems/score/types.h.
+ * rtems/score/m68ktypes.h: Removed.
+ * rtems/score/types.h: New file via CVS magic.
+ * Makefile.am, rtems/score/cpu.h: Account for name change.
+
+2001-04-03 Joel Sherrill <joel@OARcorp.com>
+
+ * Per PR94, all rtems/score/CPUtypes.h are named rtems/score/types.h.
+ * rtems/score/i960types.h: Removed.
+ * rtems/score/types.h: New file via CVS magic.
+ * Makefile.am, rtems/score/cpu.h: Account for name change.
+
+2002-03-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac:
+ AC_INIT(package,_RTEMS_VERSION,_RTEMS_BUGS).
+ AM_INIT_AUTOMAKE([no-define foreign 1.6]).
+ * Makefile.am: Remove AUTOMAKE_OPTIONS.
+
+2002-01-29 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/Makefile.am: Removed.
+ * rtems/score/Makefile.am: Removed.
+ * configure.ac: Reflect changes above.
+ * Makefile.am: Reflect changes above.
+
+2001-12-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add multilib support.
+
+2001-11-28 Joel Sherrill <joel@OARcorp.com>,
+
+ This was tracked as PR91.
+ * rtems/score/cpu.h: Added CPU_PROVIDES_ISR_IS_IN_PROGRESS macro which
+ is used to specify if the port uses the standard macro for this (FALSE).
+ A TRUE setting indicates the port provides its own implementation.
+
+2001-10-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * .cvsignore: Add autom4te.cache for autoconf > 2.52.
+ * configure.in: Remove.
+ * configure.ac: New file, generated from configure.in by autoupdate.
+
+2001-09-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/score/Makefile.am: Use 'PREINSTALL_FILES ='.
+ * Makefile.am: Use 'PREINSTALL_FILES ='.
+
+2001-02-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am, rtems/score/Makefile.am:
+ Apply include_*HEADERS instead of H_FILES.
+
+2001-01-03 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/cpu.h: Added _CPU_Initialize_vectors().
+ * cpu_asm.S: Modify to properly dereference _ISR_Vector_table
+ now that it is dynamically allocated.
+
+2000-11-09 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use ... instead of RTEMS_TOPdir in ACLOCAL_AMFLAGS.
+
+2000-11-02 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Switch to ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal.
+
+2000-10-25 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: ACLOCAL_AMFLAGS= -I $(RTEMS_TOPdir)/macros.
+ Switch to GNU canonicalization.
+
+2000-09-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include compile.am.
+
+2000-08-10 Joel Sherrill <joel@OARcorp.com>
+
+ * ChangeLog: New file.
diff --git a/cpukit/score/cpu/i960/Makefile.am b/cpukit/score/cpu/i960/Makefile.am
new file mode 100644
index 0000000000..c30ddf4213
--- /dev/null
+++ b/cpukit/score/cpu/i960/Makefile.am
@@ -0,0 +1,58 @@
+##
+## $Id$
+##
+
+include $(top_srcdir)/automake/compile.am
+
+include_rtemsdir = $(includedir)/rtems
+include_rtems_HEADERS = asm.h
+
+include_rtems_scoredir = $(includedir)/rtems/score
+include_rtems_score_HEADERS = rtems/score/cpu.h rtems/score/i960.h \
+ rtems/score/types.h
+
+EXTRA_LIBRARIES = libscorecpu.a
+CLEANFILES = libscorecpu.a
+libscorecpu_a_SOURCES = cpu.c cpu_asm.S
+libscorecpu_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libscorecpu_g.a
+CLEANFILES += libscorecpu_g.a
+libscorecpu_g_a_SOURCES = $(libscorecpu_a_SOURCES)
+libscorecpu_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+all-local: $(PREINSTALL_FILES) libscorecpu$(LIB_VARIANT).a
+
+PREINSTALL_DIRS =
+PREINSTALL_FILES =
+
+$(PROJECT_INCLUDE)/rtems/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems
+ @: > $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/asm.h: asm.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/asm.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/asm.h
+
+$(PROJECT_INCLUDE)/rtems/score/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems/score
+ @: > $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/score/cpu.h: rtems/score/cpu.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/cpu.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/cpu.h
+
+$(PROJECT_INCLUDE)/rtems/score/i960.h: rtems/score/i960.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/i960.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/i960.h
+
+$(PROJECT_INCLUDE)/rtems/score/types.h: rtems/score/types.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/types.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/types.h
+
+CLEANFILES += $(PREINSTALL_FILES)
+DISTCLEANFILES = $(PREINSTALL_DIRS)
+
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/score/cpu/i960/asm.h b/cpukit/score/cpu/i960/asm.h
new file mode 100644
index 0000000000..e98f900f59
--- /dev/null
+++ b/cpukit/score/cpu/i960/asm.h
@@ -0,0 +1,110 @@
+/* asm.h
+ *
+ * This include file attempts to address the problems
+ * caused by incompatible flavors of assemblers and
+ * toolsets. It primarily addresses variations in the
+ * use of leading underscores on symbols and the requirement
+ * that register names be preceded by a %.
+ *
+ *
+ * NOTE: The spacing in the use of these macros
+ * is critical to them working as advertised.
+ *
+ * COPYRIGHT:
+ *
+ * This file is based on similar code found in newlib available
+ * from ftp.cygnus.com. The file which was used had no copyright
+ * notice. This file is freely distributable as long as the source
+ * of the file is noted. This file is:
+ *
+ * COPYRIGHT (c) 1994-1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * $Id$
+ */
+
+#ifndef __i960_ASM_h
+#define __i960_ASM_h
+
+/*
+ * Indicate we are in an assembly file and get the basic CPU definitions.
+ */
+
+#ifndef ASM
+#define ASM
+#endif
+#include <rtems/score/cpuopts.h>
+#include <rtems/score/i960.h>
+
+/*
+ * Recent versions of GNU cpp define variables which indicate the
+ * need for underscores and percents. If not using GNU cpp or
+ * the version does not support this, then you will obviously
+ * have to define these as appropriate.
+ */
+
+#ifndef __USER_LABEL_PREFIX__
+#define __USER_LABEL_PREFIX__ _
+#endif
+
+#ifndef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__
+#endif
+
+/* ANSI concatenation macros. */
+
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+/* Use the right prefix for global labels. */
+
+#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+
+/* Use the right prefix for registers. */
+
+#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
+
+#define g0 REG (g0)
+#define g1 REG (g1)
+#define g2 REG (g2)
+#define g3 REG (g3)
+#define g4 REG (g4)
+#define g5 REG (g5)
+#define g6 REG (g6)
+#define g7 REG (g7)
+#define g8 REG (g8)
+#define g9 REG (g9)
+#define g10 REG (g10)
+#define g11 REG (g11)
+#define g12 REG (g12)
+#define g13 REG (g13)
+#define g14 REG (g14)
+#define g15 REG (g15)
+
+/*
+ * Define macros to handle section beginning and ends.
+ */
+
+
+#define BEGIN_CODE_DCL .text
+#define END_CODE_DCL
+#define BEGIN_DATA_DCL .data
+#define END_DATA_DCL
+#define BEGIN_CODE .text
+#define END_CODE
+#define BEGIN_DATA
+#define END_DATA
+#define BEGIN_BSS
+#define END_BSS
+#define END
+
+/*
+ * Following must be tailor for a particular flavor of the C compiler.
+ * They may need to put underscores in front of the symbols.
+ */
+
+#define PUBLIC(sym) .globl SYM (sym)
+#define EXTERN(sym) .globl SYM (sym)
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/i960/cpu.c b/cpukit/score/cpu/i960/cpu.c
new file mode 100644
index 0000000000..5a26da446f
--- /dev/null
+++ b/cpukit/score/cpu/i960/cpu.c
@@ -0,0 +1,81 @@
+/*
+ * Intel i960CA Dependent Source
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+
+/* _CPU_Initialize
+ *
+ * This routine performs processor dependent initialization.
+ *
+ * INPUT PARAMETERS:
+ * cpu_table - CPU table to initialize
+ * thread_dispatch - address of disptaching routine
+ *
+ * OUTPUT PARAMETERS: NONE
+ */
+
+void _CPU_Initialize(
+ rtems_cpu_table *cpu_table,
+ void (*thread_dispatch) /* ignored on this CPU */
+)
+{
+
+ _CPU_Table = *cpu_table;
+
+}
+
+/*PAGE
+ *
+ * _CPU_ISR_Get_level
+ */
+
+uint32_t _CPU_ISR_Get_level( void )
+{
+ uint32_t level;
+
+ i960_get_interrupt_level( level );
+
+ return level;
+}
+
+/*PAGE
+ *
+ * _CPU__ISR_install_vector
+ *
+ * Install the RTEMS vector wrapper in the CPU's interrupt table.
+ *
+ * Input parameters:
+ * vector - interrupt vector number
+ * old_handler - former ISR for this vector number
+ * new_handler - replacement ISR for this vector number
+ *
+ * Output parameters: NONE
+ *
+ */
+
+void _CPU_ISR_install_vector(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+)
+{
+ proc_ptr ignored;
+
+ *old_handler = _ISR_Vector_table[ vector ];
+
+ _CPU_ISR_install_raw_handler( vector, _ISR_Handler, &ignored );
+
+ _ISR_Vector_table[ vector ] = new_handler;
+}
diff --git a/cpukit/score/cpu/i960/cpu_asm.S b/cpukit/score/cpu/i960/cpu_asm.S
new file mode 100644
index 0000000000..2b49b5cda1
--- /dev/null
+++ b/cpukit/score/cpu/i960/cpu_asm.S
@@ -0,0 +1,213 @@
+/*
+ * This file contains all assembly code for the i960 port of RTEMS.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+ .data
+_ISR_reg_save:
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+
+ .text
+/*
+ * Format of i960ca Register structure
+ */
+
+.set REG_R0_PFP , 0 # (r0) Previous Frame Pointer
+.set REG_R1_SP , REG_R0_PFP+4 # (r1) Stack Pointer
+.set REG_PC , REG_R1_SP+4 # (pc) Processor Controls
+.set REG_G8 , REG_PC+4 # (g8) Global Register 8
+.set REG_G9 , REG_G8+4 # (g9) Global Register 9
+.set REG_G10 , REG_G9+4 # (g10) Global Register 10
+.set REG_G11 , REG_G10+4 # (g11) Global Register 11
+.set REG_G12 , REG_G11+4 # (g12) Global Register 12
+.set REG_G13 , REG_G12+4 # (g13) Global Register 13
+.set REG_G14 , REG_G13+4 # (g14) Global Register 14
+.set REG_G15_FP , REG_G14+4 # (g15) Global Register 15
+.set SIZE_REGS , REG_G15_FP+4 # size of cpu_context_registers
+ # structure
+
+/*
+ * void _CPU_Context_switch( run_context, heir_context )
+ *
+ * This routine performs a normal non-FP context.
+ */
+ .align 4
+ .globl __CPU_Context_switch
+
+__CPU_Context_switch:
+ modpc 0,0,g2 # get old intr level (PC)
+ st g2,REG_PC(g0) # save pc
+ stq g8,REG_G8(g0) # save g8-g11
+ stq g12,REG_G12(g0) # save g12-g15
+ stl pfp,REG_R0_PFP(g0) # save pfp, sp
+
+restore: flushreg # flush register cache
+ ldconst 0x001f0000,g2 # g2 = PC mask
+ ld REG_PC(g1),g3 # thread->Regs.pc = pc;
+ ldq REG_G12(g1),g12 # restore g12-g15
+ ldl REG_R0_PFP(g1),pfp # restore pfp, sp
+ ldq REG_G8(g1),g8 # restore g8-g11
+ modpc 0,g2,g3 # restore PC register
+ ret
+
+/*
+ * void _CPU_Context_restore( new_context )
+ *
+ * This routine performs a normal non-FP context.
+ */
+
+ .globl __CPU_Context_restore
+__CPU_Context_restore:
+ mov g0,g1 # g0 = _Thread_executing
+ b restore
+
+/*PAGE
+ * void _CPU_Context_save_fp_context( &fp_context_ptr )
+ * void _CPU_Context_restore_fp_context( &fp_context_ptr )
+ *
+ * There is currently no hardware floating point for the i960.
+ */
+
+ .globl __CPU_Context_save_fp
+ .globl __CPU_Context_restore_fp
+__CPU_Context_save_fp:
+__CPU_Context_restore_fp:
+#if ( I960_HAS_FPU == 1 )
+#error "Floating point support for i960 family has been implemented!!!"
+#endif
+ ret
+
+/*PAGE
+ * void __ISR_Handler()
+ *
+ * This routine provides the RTEMS interrupt management.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * NOTE:
+ * Upon entry, the supervisor stack will contain a stack frame
+ * back to the interrupted thread and the interrupt stack will contain
+ * an interrupt stack frame. If dispatching is enabled, this
+ * is the outer most interrupt, and (a context switch is necessary or
+ * the current thread has signals), then set up the supervisor stack to
+ * transfer control to the interrupt dispatcher.
+ */
+
+ .globl __ISR_Handler
+__ISR_Handler:
+ #ldconst 1,r8
+ #modpc 0,r8,r8 # enable tracing
+
+ # r4 = &_Thread_Dispatch_disable_level
+ ld __Thread_Dispatch_disable_level,r4
+ movl g0,r8 # save g0-g1
+
+ ld -16+8(fp),g0 # g0 = vector number
+ movl g2,r10 # save g2-g3
+
+ ld __ISR_Nest_level,r5 # r5 = &_Isr_nest_level
+ mov g14,r7 # save g14
+
+ lda 0,g14 # NOT Branch and Link
+ movl g4,r12 # save g4-g5
+
+ lda 1(r4),r4 # increment dispatch disable level
+ movl g6,r14 # save g6-g7
+
+ ld __ISR_Vector_table,g1 # g1 = base of vector table
+
+ stq g8, _ISR_reg_save # save g8-g11
+ stl g12, _ISR_reg_save+16 # save g12-g13
+
+ ld (g1)[g0*4],g1 # g1 = Users handler
+ addo 1,r5,r5 # increment ISR level
+
+ st r4,__Thread_Dispatch_disable_level
+ # one ISR nest level deeper
+ subo 1,r4,r4 # decrement dispatch disable level
+
+ st r5,__ISR_Nest_level # disable multitasking
+ subo 1,r5,r5 # decrement ISR nest level
+
+ callx (g1) # invoke user ISR
+
+ # unnest multitasking
+ st r5,__ISR_Nest_level # one less ISR nest level
+ cmpobne.f 0,r4,exit # If dispatch disabled, exit
+ ldl -16(fp),g0 # g0 = threads PC reg
+ # g1 = threads AC reg
+ ld __Context_Switch_necessary,r6
+ # r6 = Is thread switch necessary?
+ bbs.f 13,g0,exit # not outer level, then exit
+ cmpobne.f 0,r6,bframe # Switch necessary?
+
+ ld __ISR_Signals_to_thread_executing,g2
+ # signals sent to Run_thread
+ # while in interrupt handler?
+ cmpobe.f 0,g2,exit # No, then exit
+
+bframe: mov 0,g2
+ st g2,__ISR_Signals_to_thread_executing
+
+ ldconst 0x1f0000,g2 # g2 = intr disable mask
+ mov g2,g3 # g3 = new intr level
+ modpc 0,g2,g3 # set new level
+
+ andnot 7,pfp,r4 # r4 = pfp without ret type
+ flushreg # flush registers
+ # push _Isr_dispatch ret frame
+ # build ISF in r4-r6
+ ldconst 64,g2 # g2 = size of stack frame
+ ld 4(r4),g3 # g3 = previous sp
+ addo g2,g3,r5 # r5 = _Isr_dispatch SP
+ lda __ISR_Dispatch,r6 # r6 = _Isr_dispatch entry
+ stt r4,(g3) # set _Isr_dispatch ret info
+ st g1,16(g3) # set r4 = AC for ISR disp
+ or 7,g3,pfp # pfp to _Isr_dispatch
+ flushreg
+ b exit1
+exit: st r4,__Thread_Dispatch_disable_level
+exit1: mov r7,g14 # restore g14
+ movq r8,g0 # restore g0-g3
+ movq r12,g4 # restore g4-g7
+ ldq _ISR_reg_save, g8 # restore g8-g11
+ ldl _ISR_reg_save+16, g12 # restore g12-g13
+ ret
+
+
+/*PAGE
+ *
+ * void __ISR_Dispatch()
+ *
+ * Entry point from the outermost interrupt service routine exit.
+ * The current stack is the supervisor mode stack.
+ */
+
+ .globl __ISR_Dispatch
+__ISR_Dispatch:
+ mov g14,r7
+ mov 0,g14
+ movq g0,r8
+ movq g4,r12
+ call __Thread_Dispatch
+
+ ldconst -1,r5 # r5 = reload mask
+ modac r5,r4,r4 # restore threads AC register
+ mov r7,g14
+ movq r8,g0
+ movq r12,g4
+ ret
diff --git a/cpukit/score/cpu/i960/rtems/score/cpu.h b/cpukit/score/cpu/i960/rtems/score/cpu.h
new file mode 100644
index 0000000000..77a6dc55a6
--- /dev/null
+++ b/cpukit/score/cpu/i960/rtems/score/cpu.h
@@ -0,0 +1,485 @@
+/* cpu.h
+ *
+ * This include file contains information pertaining to the Intel
+ * i960 processor family.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __CPU_h
+#define __CPU_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/i960.h> /* pick up machine definitions */
+#ifndef ASM
+#include <rtems/score/types.h>
+#endif
+
+#define CPU_INLINE_ENABLE_DISPATCH FALSE
+#define CPU_UNROLL_ENQUEUE_PRIORITY FALSE
+
+/*
+ * Use the i960's hardware interrupt stack support and have the
+ * interrupt manager allocate the memory for it.
+ */
+
+#define CPU_HAS_SOFTWARE_INTERRUPT_STACK FALSE
+#define CPU_HAS_HARDWARE_INTERRUPT_STACK TRUE
+#define CPU_ALLOCATE_INTERRUPT_STACK TRUE
+
+/*
+ * Does the RTEMS invoke the user's ISR with the vector number and
+ * a pointer to the saved interrupt frame (1) or just the vector
+ * number (0)?
+ */
+
+#define CPU_ISR_PASSES_FRAME_POINTER 0
+
+/*
+ * Some family members have no FP (SA/KA/CA/CF), others have it built in
+ * (KB/MC/MX). There does not appear to be an external coprocessor
+ * for this family.
+ */
+
+#if ( I960_HAS_FPU == 1 )
+#define CPU_HARDWARE_FP TRUE
+#error "Floating point support for i960 family has been implemented!!!"
+#else
+#define CPU_HARDWARE_FP FALSE
+#endif
+
+#define CPU_SOFTWARE_FP FALSE
+
+#define CPU_ALL_TASKS_ARE_FP FALSE
+#define CPU_IDLE_TASK_IS_FP FALSE
+#define CPU_USE_DEFERRED_FP_SWITCH TRUE
+
+#define CPU_PROVIDES_IDLE_THREAD_BODY FALSE
+#define CPU_STACK_GROWS_UP TRUE
+#define CPU_STRUCTURE_ALIGNMENT /* __attribute__ ((aligned (16))) */
+
+/*
+ * Define what is required to specify how the network to host conversion
+ * routines are handled.
+ */
+
+#define CPU_HAS_OWN_HOST_TO_NETWORK_ROUTINES FALSE
+#define CPU_BIG_ENDIAN TRUE
+#define CPU_LITTLE_ENDIAN FALSE
+
+
+/* structures */
+
+/*
+ * Basic integer context for the i960 family.
+ */
+
+typedef struct {
+ void *r0_pfp; /* (r0) Previous Frame Pointer */
+ void *r1_sp; /* (r1) Stack Pointer */
+ uint32_t pc; /* (pc) Processor Control */
+ void *g8; /* (g8) Global Register 8 */
+ void *g9; /* (g9) Global Register 9 */
+ void *g10; /* (g10) Global Register 10 */
+ void *g11; /* (g11) Global Register 11 */
+ void *g12; /* (g12) Global Register 12 */
+ void *g13; /* (g13) Global Register 13 */
+ uint32_t g14; /* (g14) Global Register 14 */
+ void *g15_fp; /* (g15) Frame Pointer */
+} Context_Control;
+
+/*
+ * FP context save area for the i960 Numeric Extension
+ */
+
+typedef struct {
+ uint32_t fp0_1; /* (fp0) first word */
+ uint32_t fp0_2; /* (fp0) second word */
+ uint32_t fp0_3; /* (fp0) third word */
+ uint32_t fp1_1; /* (fp1) first word */
+ uint32_t fp1_2; /* (fp1) second word */
+ uint32_t fp1_3; /* (fp1) third word */
+ uint32_t fp2_1; /* (fp2) first word */
+ uint32_t fp2_2; /* (fp2) second word */
+ uint32_t fp2_3; /* (fp2) third word */
+ uint32_t fp3_1; /* (fp3) first word */
+ uint32_t fp3_2; /* (fp3) second word */
+ uint32_t fp3_3; /* (fp3) third word */
+} Context_Control_fp;
+
+/*
+ * The following structure defines the set of information saved
+ * on the current stack by RTEMS upon receipt of each interrupt.
+ */
+
+typedef struct {
+ uint32_t TBD; /* XXX Fix for this CPU */
+} CPU_Interrupt_frame;
+
+/*
+ * Call frame for the i960 family.
+ */
+
+typedef struct {
+ void *r0_pfp; /* (r0) Previous Frame Pointer */
+ void *r1_sp; /* (r1) Stack Pointer */
+ void *r2_rip; /* (r2) Return Instruction Pointer */
+ void *r3; /* (r3) Local Register 3 */
+ void *r4; /* (r4) Local Register 4 */
+ void *r5; /* (r5) Local Register 5 */
+ void *r6; /* (r6) Local Register 6 */
+ void *r7; /* (r7) Local Register 7 */
+ void *r8; /* (r8) Local Register 8 */
+ void *r9; /* (r9) Local Register 9 */
+ void *r10; /* (r10) Local Register 10 */
+ void *r11; /* (r11) Local Register 11 */
+ void *r12; /* (r12) Local Register 12 */
+ void *r13; /* (r13) Local Register 13 */
+ void *r14; /* (r14) Local Register 14 */
+ void *r15; /* (r15) Local Register 15 */
+ /* XXX Looks like sometimes there is FP stuff here (MC manual)? */
+} CPU_Call_frame;
+
+/*
+ * The following table contains the information required to configure
+ * the i960 specific parameters.
+ */
+
+typedef struct {
+ void (*pretasking_hook)( void );
+ void (*predriver_hook)( void );
+ void (*postdriver_hook)( void );
+ void (*idle_task)( void );
+ boolean do_zero_of_workspace;
+ uint32_t idle_task_stack_size;
+ uint32_t interrupt_stack_size;
+ uint32_t extra_mpci_receive_server_stack;
+ void * (*stack_allocate_hook)( uint32_t );
+ void (*stack_free_hook)( void* );
+ /* end of fields required on all CPUs */
+} rtems_cpu_table;
+
+/*
+ * Macros to access required entires in the CPU Table are in
+ * the file rtems/system.h.
+ */
+
+/*
+ * Macros to access i960 specific additions to the CPU Table
+ *
+ * NONE
+ */
+
+/* variables */
+
+SCORE_EXTERN void *_CPU_Interrupt_stack_low;
+SCORE_EXTERN void *_CPU_Interrupt_stack_high;
+
+/* constants */
+
+/*
+ * This defines the number of levels and the mask used to pick those
+ * bits out of a thread mode.
+ */
+
+#define CPU_MODES_INTERRUPT_LEVEL 0x0000001f /* interrupt level in mode */
+#define CPU_MODES_INTERRUPT_MASK 0x0000001f /* interrupt level in mode */
+
+/*
+ * context size area for floating point
+ */
+
+#define CPU_CONTEXT_FP_SIZE sizeof( Context_Control_fp )
+
+/*
+ * extra stack required by the MPCI receive server thread
+ */
+
+#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK (CPU_STACK_MINIMUM_SIZE)
+
+/*
+ * i960 family supports 256 distinct vectors.
+ */
+
+#define CPU_INTERRUPT_NUMBER_OF_VECTORS 256
+#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1)
+
+/*
+ * This is defined if the port has a special way to report the ISR nesting
+ * level. Most ports maintain the variable _ISR_Nest_level.
+ */
+
+#define CPU_PROVIDES_ISR_IS_IN_PROGRESS FALSE
+
+/*
+ * Minimum size of a thread's stack.
+ *
+ * NOTE: See CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK
+ */
+
+#define CPU_STACK_MINIMUM_SIZE 2048
+
+/*
+ * i960 is pretty tolerant of alignment but some CPU models do
+ * better with different default aligments so we use what the
+ * CPU model selected in rtems/score/i960.h.
+ */
+
+#define CPU_ALIGNMENT I960_CPU_ALIGNMENT
+#define CPU_HEAP_ALIGNMENT CPU_ALIGNMENT
+#define CPU_PARTITION_ALIGNMENT CPU_ALIGNMENT
+
+/*
+ * i960ca stack requires 16 byte alignment
+ *
+ * NOTE: This factor may need to be family member dependent.
+ */
+
+#define CPU_STACK_ALIGNMENT 16
+
+/* macros */
+
+/*
+ * ISR handler macros
+ *
+ * These macros perform the following functions:
+ * + initialize the RTEMS vector table
+ * + disable all maskable CPU interrupts
+ * + restore previous interrupt level (enable)
+ * + temporarily restore interrupts (flash)
+ * + set a particular level
+ */
+
+#define _CPU_Initialize_vectors()
+#define _CPU_ISR_Disable( _level ) i960_disable_interrupts( _level )
+#define _CPU_ISR_Enable( _level ) i960_enable_interrupts( _level )
+#define _CPU_ISR_Flash( _level ) i960_flash_interrupts( _level )
+
+#define _CPU_ISR_Set_level( newlevel ) \
+ { \
+ uint32_t _mask = 0; \
+ uint32_t _level = (newlevel); \
+ \
+ __asm__ volatile ( "ldconst 0x1f0000,%0; \
+ modpc 0,%0,%1" : "=d" (_mask), "=d" (_level) \
+ : "0" (_mask), "1" (_level) \
+ ); \
+ }
+
+uint32_t _CPU_ISR_Get_level( void );
+
+/* ISR handler section macros */
+
+/*
+ * Context handler macros
+ *
+ * These macros perform the following functions:
+ * + initialize a context area
+ * + restart the current thread
+ * + calculate the initial pointer into a FP context area
+ * + initialize an FP context area
+ */
+
+#define _CPU_Context_Initialize( _the_context, _stack_base, _size, \
+ _isr, _entry, _is_fp ) \
+ { CPU_Call_frame *_texit_frame; \
+ uint32_t _mask; \
+ uint32_t _base_pc; \
+ uint32_t _stack_tmp; \
+ void *_stack; \
+ \
+ _stack_tmp = (uint32_t )(_stack_base) + CPU_STACK_ALIGNMENT; \
+ _stack_tmp &= ~(CPU_STACK_ALIGNMENT - 1); \
+ _stack = (void *) _stack_tmp; \
+ \
+ __asm__ volatile ( "flushreg" : : ); /* flush register cache */ \
+ \
+ (_the_context)->r0_pfp = _stack; \
+ (_the_context)->g15_fp = _stack + (1 * sizeof(CPU_Call_frame)); \
+ (_the_context)->r1_sp = _stack + (2 * sizeof(CPU_Call_frame)); \
+ __asm__ volatile ( "ldconst 0x1f0000,%0 ; " \
+ "modpc 0,0,%1 ; " \
+ "andnot %0,%1,%1 ; " \
+ : "=d" (_mask), "=d" (_base_pc) : ); \
+ (_the_context)->pc = _base_pc | ((_isr) << 16); \
+ (_the_context)->g14 = 0; \
+ \
+ _texit_frame = (CPU_Call_frame *)_stack; \
+ _texit_frame->r0_pfp = NULL; \
+ _texit_frame->r1_sp = (_the_context)->g15_fp; \
+ _texit_frame->r2_rip = (_entry); \
+ }
+
+#define _CPU_Context_Restart_self( _the_context ) \
+ _CPU_Context_restore( (_the_context) );
+
+#define _CPU_Context_Fp_start( _base, _offset ) NULL
+
+#define _CPU_Context_Initialize_fp( _fp_area )
+
+/* end of Context handler macros */
+
+/*
+ * Fatal Error manager macros
+ *
+ * These macros perform the following functions:
+ * + disable interrupts and halt the CPU
+ */
+
+#define _CPU_Fatal_halt( _errorcode ) \
+ { uint32_t _mask, _level; \
+ uint32_t _error = (_errorcode); \
+ \
+ __asm__ volatile ( "ldconst 0x1f0000,%0 ; \
+ mov %0,%1 ; \
+ modpc 0,%0,%1 ; \
+ mov %2,g0 ; \
+ self: b self " \
+ : "=d" (_mask), "=d" (_level), "=d" (_error) : ); \
+ }
+
+/* end of Fatal Error Manager macros */
+
+/*
+ * Bitfield handler macros
+ *
+ * These macros perform the following functions:
+ * + scan for the highest numbered (MSB) set in a 16 bit bitfield
+ */
+
+#define CPU_USE_GENERIC_BITFIELD_CODE FALSE
+#define CPU_USE_GENERIC_BITFIELD_DATA FALSE
+
+#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
+ { uint32_t _search = (_value); \
+ \
+ (_output) = 0; /* to prevent warnings */ \
+ __asm__ volatile ( "scanbit %0,%1 " \
+ : "=d" (_search), "=d" (_output) \
+ : "0" (_search), "1" (_output) ); \
+ }
+
+/* end of Bitfield handler macros */
+
+/*
+ * Priority handler macros
+ *
+ * These macros perform the following functions:
+ * + return a mask with the bit for this major/minor portion of
+ * of thread priority set.
+ * + translate the bit number returned by "Bitfield_find_first_bit"
+ * into an index into the thread ready chain bit maps
+ */
+
+#define _CPU_Priority_Mask( _bit_number ) \
+ ( 0x8000 >> (_bit_number) )
+
+#define _CPU_Priority_bits_index( _priority ) \
+ ( 15 - (_priority) )
+
+/* end of Priority handler macros */
+
+/* functions */
+
+/*
+ * _CPU_Initialize
+ *
+ * This routine performs CPU dependent initialization.
+ */
+
+void _CPU_Initialize(
+ rtems_cpu_table *cpu_table,
+ void (*thread_dispatch)
+);
+
+/*
+ * _CPU_ISR_install_raw_handler
+ *
+ * This routine installs a "raw" interrupt handler directly into the
+ * processor's vector table.
+ */
+
+void _CPU_ISR_install_raw_handler(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+);
+
+/*
+ * _CPU_ISR_install_vector
+ *
+ * This routine installs an interrupt vector.
+ */
+
+void _CPU_ISR_install_vector(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+);
+
+/*
+ * _CPU_Install_interrupt_stack
+ *
+ * This routine installs the hardware interrupt stack pointer.
+ */
+
+void _CPU_Install_interrupt_stack( void );
+
+/*
+ * _CPU_Context_switch
+ *
+ * This routine switches from the run context to the heir context.
+ */
+
+void _CPU_Context_switch(
+ Context_Control *run,
+ Context_Control *heir
+);
+
+/*
+ * _CPU_Context_restore
+ *
+ * This routine is generally used only to restart self in an
+ * efficient manner and avoid stack conflicts.
+ */
+
+void _CPU_Context_restore(
+ Context_Control *new_context
+);
+
+/*
+ * _CPU_Context_save_fp
+ *
+ * This routine saves the floating point context passed to it.
+ */
+
+void _CPU_Context_save_fp(
+ void **fp_context_ptr
+);
+
+/*
+ * _CPU_Context_restore_fp
+ *
+ * This routine restores the floating point context passed to it.
+ */
+
+void _CPU_Context_restore_fp(
+ void **fp_context_ptr
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/i960/rtems/score/i960.h b/cpukit/score/cpu/i960/rtems/score/i960.h
new file mode 100644
index 0000000000..42991c968b
--- /dev/null
+++ b/cpukit/score/cpu/i960/rtems/score/i960.h
@@ -0,0 +1,194 @@
+/* i960.h
+ *
+ * This include file contains information pertaining to the Intel
+ * i960 processor family.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __i960_h
+#define __i960_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This file contains the information required to build
+ * RTEMS for a particular member of the Intel i960
+ * family. It does this by setting variables to indicate
+ * which implementation dependent features are present
+ * in a particular member of the family.
+ *
+ * NOTE: For now i960 support is for models without an FPU.
+ * The stubs for FP routines are in place so only need to be filled in.
+ *
+ * NOTE: RTEMS defines a canonical name for each cpu model.
+ */
+
+/*
+ * Define the name of the CPU family.
+ */
+
+#define CPU_NAME "Intel i960"
+
+/*
+ * This should work since most i960 models do not have FPUs. The logic is:
+ *
+ * + If the user specifically asks for soft-float, give it to them
+ * regardless of hardware availability.
+ * + If the CPU has hardware FPU, then use it.
+ * + Otherwise, we have to use soft float.
+ */
+
+#if defined(_SOFT_FLOAT)
+#define I960_HAS_FPU 0
+#elif defined(_i960_KB__) || defined(_i960_SB__) || defined(_i960_SB__) || \
+ defined(_i960_JF__) || defined(_i960_MC__) || defined(_i960_CC__)
+#define I960_HAS_FPU 1
+#else
+#define I960_HAS_FPU 0
+#endif
+
+/*
+ * Some of the CPU models may have better performance with
+ * alignment of 8 or 16 but we don't know what model we are
+ * being compiled for based solely on the information provided
+ * when multilibbing.
+ */
+
+#define I960_CPU_ALIGNMENT 4
+
+/*
+ * This is not the perfect CPU model name but it is adequate and
+ * reflects what we know from multilib.
+ */
+
+#if I960_HAS_FPU
+#define CPU_MODEL_NAME "w/FPU"
+#else
+#define CPU_MODEL_NAME "w/soft-float"
+#endif
+#ifndef ASM
+
+
+/*
+ * Miscellaneous Support Routines
+ */
+
+#define i960_reload_ctl_group( group ) \
+ { register int _cmd = ((group)|0x400) ; \
+ asm volatile( "sysctl %0,%0,%0" : "=d" (_cmd) : "0" (_cmd) ); \
+ }
+
+#define i960_atomic_modify( mask, addr, prev ) \
+ { register unsigned int _mask = (mask); \
+ register unsigned int *_addr = (unsigned int *)(addr); \
+ asm volatile( "atmod %0,%1,%1" \
+ : "=d" (_addr), "=d" (_mask) \
+ : "0" (_addr), "1" (_mask) ); \
+ (prev) = _mask; \
+ }
+
+#define atomic_modify( _mask, _address, _previous ) \
+ i960_atomic_modify( _mask, _address, _previous )
+
+#define i960_enable_tracing() \
+ { register unsigned int _pc = 0x1; \
+ asm volatile( "modpc 0,%0,%0" : "=d" (_pc) : "0" (_pc) ); \
+ }
+
+/*
+ * Interrupt Level Routines
+ */
+
+#define i960_disable_interrupts( oldlevel ) \
+ { (oldlevel) = 0x1f0000; \
+ asm volatile ( "modpc 0,%1,%1" \
+ : "=d" ((oldlevel)) \
+ : "0" ((oldlevel)) ); \
+ }
+
+#define i960_enable_interrupts( oldlevel ) \
+ { unsigned int _mask = 0x1f0000; \
+ asm volatile ( "modpc 0,%0,%1" \
+ : "=d" (_mask), "=d" ((oldlevel)) \
+ : "0" (_mask), "1" ((oldlevel)) ); \
+ }
+
+#define i960_flash_interrupts( oldlevel ) \
+ { unsigned int _mask = 0x1f0000; \
+ asm volatile ( "modpc 0,%0,%1 ; \
+ mov %0,%1 ; \
+ modpc 0,%0,%1" \
+ : "=d" (_mask), "=d" ((oldlevel)) \
+ : "0" (_mask), "1" ((oldlevel)) ); \
+ }
+
+#define i960_get_interrupt_level( _level ) \
+ { \
+ i960_disable_interrupts( _level ); \
+ i960_enable_interrupts( _level ); \
+ (_level) = ((_level) & 0x1f0000) >> 16; \
+ } while ( 0 )
+
+#define i960_cause_intr( intr ) \
+ { register int _intr = (intr); \
+ asm volatile( "sysctl %0,%0,%0" : "=d" (_intr) : "0" (_intr) ); \
+ }
+
+/*
+ * Interrupt Masking Routines
+ */
+
+static inline unsigned int i960_get_fp()
+{ register unsigned int _fp=0;
+ asm volatile( "mov fp,%0" : "=d" (_fp) : "0" (_fp) );
+ return ( _fp );
+}
+
+/*
+ * The following routine swaps the endian format of an unsigned int.
+ * It must be static because it is referenced indirectly.
+ *
+ * This version is based on code presented in Vol. 4, No. 4 of
+ * Insight 960. It is certainly something you wouldn't think
+ * of on your own.
+ */
+
+static inline unsigned int CPU_swap_u32(
+ unsigned int value
+)
+{
+ register unsigned int to_swap = value;
+ register unsigned int temp = 0xFF00FF00;
+ register unsigned int swapped = 0;
+
+ /* to_swap swapped */
+ asm volatile ( "rotate 16,%0,%2 ;" /* 0x12345678 0x56781234 */
+ "modify %1,%0,%2 ;" /* 0x12345678 0x12785634 */
+ "rotate 8,%2,%2" /* 0x12345678 0x78563412 */
+ : "=r" (to_swap), "=r" (temp), "=r" (swapped)
+ : "0" (to_swap), "1" (temp), "2" (swapped)
+ );
+ return( swapped );
+}
+
+#define CPU_swap_u16( value ) \
+ (((value&0xff) << 8) | ((value >> 8)&0xff))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !ASM */
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/i960/rtems/score/types.h b/cpukit/score/cpu/i960/rtems/score/types.h
new file mode 100644
index 0000000000..02faa85604
--- /dev/null
+++ b/cpukit/score/cpu/i960/rtems/score/types.h
@@ -0,0 +1,57 @@
+/* i960types.h
+ *
+ * This include file contains type definitions pertaining to the Intel
+ * i960 processor family.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __i960_TYPES_h
+#define __i960_TYPES_h
+
+#ifndef ASM
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This section defines the basic types for this processor.
+ */
+
+typedef unsigned char unsigned8; /* unsigned 8-bit integer */
+typedef unsigned short unsigned16; /* unsigned 16-bit integer */
+typedef unsigned int unsigned32; /* unsigned 32-bit integer */
+typedef unsigned long long unsigned64; /* unsigned 64-bit integer */
+
+typedef unsigned32 Priority_Bit_map_control;
+
+typedef signed char signed8; /* 8-bit signed integer */
+typedef signed short signed16; /* 16-bit signed integer */
+typedef signed int signed32; /* 32-bit signed integer */
+typedef signed long long signed64; /* 64 bit signed integer */
+
+typedef unsigned32 boolean; /* Boolean value */
+
+typedef float single_precision; /* single precision float */
+typedef double double_precision; /* double precision float */
+
+typedef void i960_isr;
+
+typedef void ( *i960_isr_entry )( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !ASM */
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/m68k/.cvsignore b/cpukit/score/cpu/m68k/.cvsignore
new file mode 100644
index 0000000000..282522db03
--- /dev/null
+++ b/cpukit/score/cpu/m68k/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/cpukit/score/cpu/m68k/ChangeLog b/cpukit/score/cpu/m68k/ChangeLog
new file mode 100644
index 0000000000..bf80059917
--- /dev/null
+++ b/cpukit/score/cpu/m68k/ChangeLog
@@ -0,0 +1,309 @@
+2004-04-06 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * configure.ac: Remove (Merged into $(top_srcdir)/configure.ac).
+ * Makefile.am: Don't include multilib.am.
+ Reflect merging configure.ac into $(top_srcdir)/configure.ac.
+
+2004-04-03 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * Makefile.am: Install m68302.h m68360.h qsm.h sim.h
+ to $(includedir)/rtems/m68k.
+
+2004-04-01 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * Makefile.am: Install asm.h to $(includedir)/rtems.
+
+2004-04-01 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * cpu_asm.S: Include <rtems/asm.h> instead of <asm.h>.
+
+2004-03-30 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * cpu.c, m68302.h, rtems/score/cpu.h, rtems/score/m68k.h: Convert to
+ using c99 fixed size types.
+
+2004-03-29 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * configure.ac: RTEMS_TOP([../../../..]).
+
+2004-01-29 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ PR 561/rtems
+ * asm.h: Add CONCAT0, EVAL. Let SYM and REG use CONCAT0 and EVAL.
+
+2004-01-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Move RTEMS_TOP one subdir down.
+
+2004-01-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add PREINSTALL_DIRS.
+
+2004-01-14 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Re-add dirstamps to PREINSTALL_FILES.
+ Add PREINSTALL_FILES to CLEANFILES.
+
+2004-01-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Requires automake >= 1.8.1.
+
+2004-01-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include compile.am, again.
+
+2004-01-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Convert to using automake compilation rules.
+
+2004-01-07 Joel Sherrill <joel@OARcorp.com>
+
+ * qsm.h, sim.h: Remove efi68k and efi332 references as they are no
+ longer in the tree.
+
+2003-12-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use mkdir_p. Remove dirs from PREINSTALL_FILES.
+
+2003-12-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Require automake >= 1.8, autoconf >= 2.59.
+
+2003-12-01 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Remove TMPINSTALL_FILES.
+
+2003-11-30 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add $(dirstamp) to preinstallation rules.
+
+2003-11-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Don't use gmake rules for preinstallation.
+
+2003-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_CANONICAL_HOST.
+
+2003-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_CHECK_CPU.
+
+2003-09-04 Joel Sherrill <joel@OARcorp.com>
+
+ * cpu.c, cpu_asm.S, rtems/score/cpu.h, rtems/score/m68k.h,
+ rtems/score/types.h: URL for license changed.
+
+2003-08-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use rtems-bugs@rtems.com as bug report email address.
+
+2003-03-06 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove AC_CONFIG_AUX_DIR.
+
+2003-02-06 Ilya Alexeev <ilya@continuum.ru>
+
+ * m68360.h: Correct the order of fields in the ethernet structure
+ to account for the typo in MC68360UM (page 7-248).
+
+2002-12-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Require autoconf-2.57 + automake-1.7.2.
+ * Makefile.am: Eliminate C_O_FILES, S_O_FILES, libscorecpu_a_OBJECTS.
+
+2002-11-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Fix package name.
+
+2002-11-01 Joel Sherrill <joel@OARcorp.com>
+
+ * cpu.c: Removed warnings.
+
+2002-10-25 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Add nostdinc to AM_INIT_AUTOMAKE.
+
+2002-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * .cvsignore: Reformat.
+ Add autom4te*cache.
+ Remove autom4te.cache.
+
+2002-08-26 Eric Norum <eric.norum@usask.ca>
+
+ * cpu_asm.S: More PR267 tinkering which eliminates some conditional
+ compilation.
+
+2002-08-14 Brett Swimley <brett.swimley@aedinc.net>
+
+ * cpu_asm.S: Per PR267, the _ISR_Handler() function never was modifying
+ _ISR_Nest_level, and _Watchdog_Insert() requires this variable
+ to be modified to determine if an interrupt may have modified
+ the watchdog chain. Prior to modifying _ISR_Handler(), I had
+ a test that would fail if _ISR_Flash was not commented out in
+ _Watchdog_Insert(). After this modification was made, my test
+ ran flawlessly.
+
+2002-08-05 Joel Sherrill <joel@OARcorp.com>
+
+ * Per PR260 eliminate use of make-target-options. This impacted
+ RTEMS allowing a distinction between the CPU32 and CPU32+ in the
+ SuperCore and required that the m68k optimized memcpy be moved
+ to libcpu.
+ * memcpy.c: Moved to libcpu.
+ * Makefile.am: Modified to reflect above.
+
+2002-07-26 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Build libscorecpu.a instead of rtems-cpu.rel.
+
+2002-07-22 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use .$(OBJEXT) instead of .o.
+
+2002-07-05 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: RTEMS_TOP(../../../..).
+
+2002-07-03 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems.S: Remove.
+ * Makefile.am: Reflect changes above.
+
+2002-07-01 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_PROJECT_ROOT.
+
+2002-06-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Add RTEMS_PROG_CCAS
+
+2002-06-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use AC_CONFIG_AUX_DIR(../../../..).
+ Add AC_PROG_RANLIB.
+
+2002-06-17 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include $(top_srcdir)/../../../automake/*.am.
+ Use ../../../aclocal.
+
+2002-05-28 Chris Johns <ccj@acm.org>
+
+ * rtems/score/m68k.h: Per PR227, mc68060 does not require FPSP
+ since it is now multilib'ed.
+
+2001-04-03 Joel Sherrill <joel@OARcorp.com>
+
+ * Per PR94, all rtems/score/CPUtypes.h are named rtems/score/types.h.
+ * include/rtems/score/ispsh7750.h, score/ispsh7750.c: Account for
+ name change.
+
+2002-03-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac:
+ AC_INIT(package,_RTEMS_VERSION,_RTEMS_BUGS).
+ AM_INIT_AUTOMAKE([no-define foreign 1.6]).
+ * Makefile.am: Remove AUTOMAKE_OPTIONS.
+
+2002-03-15 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/score/m68k.h: m68k_swap_u32 fix typo.
+
+2002-03-06 Victor V. Vengerov <vvv@oktet.ru>
+
+ * rtems/score/m68k.h [M68K_COLDFIRE_ARCH] (CPU_swap_u16, CPU_swap_u32):
+ Generic implementation of endian swap primitives added for Coldfire
+ family.
+
+2002-01-29 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/Makefile.am: Removed.
+ * rtems/score/Makefile.am: Removed.
+ * configure.ac: Reflect changes above.
+ * Makefile.am: Reflect changes above.
+
+2001-12-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add multilib support.
+
+2001-10-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * .cvsignore: Add autom4te.cache for autoconf > 2.52.
+ * configure.in: Remove.
+ * configure.ac: New file, generated from configure.in by autoupdate.
+
+2001-09-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/score/Makefile.am: Use 'PREINSTALL_FILES ='.
+ * Makefile.am: Use 'PREINSTALL_FILES ='.
+
+2001-08-09 Chris Johns <ccj@acm.org>
+
+ * cpu_asm.S: This patch was co-developed with Eric Norum
+ <eric.norum@usask.ca>. It closes a one instruction window
+ on some m68k CPU cores. It fixes symptoms seen as:
+ 1) No more `interrupt handler invoked twice for
+ a single interrupt'.
+ 2) No more `lockup when mc68360 CPM and PIT interrupts
+ are at different levels'.
+ It does insert a little more overhead on machines without hardware
+ interrupt stacks but correctness has a price.
+
+2001-02-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am, rtems/score/Makefile.am:
+ Apply include_*HEADERS instead of H_FILES.
+
+2001-01-03 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/cpu.h: Added _CPU_Initialize_vectors().
+ * cpu_asm.S: Modify to properly dereference _ISR_Vector_table
+ now that it is dynamically allocated.
+
+2000-12-19 Joel Sherrill <joel@OARcorp.com>
+
+ * cpu.c: Do not read or write raw interrupt vector table if
+ we are on a CPU that does not have a %vbr register and the
+ BSP is configured as having the table in ROM.
+
+2000-11-09 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use ... instead of RTEMS_TOPdir in ACLOCAL_AMFLAGS.
+
+2000-11-02 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Switch to ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal.
+
+2000-10-25 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: ACLOCAL_AMFLAGS= -I $(RTEMS_TOPdir)/macros.
+ Switch to GNU canonicalization.
+
+2000-10-19 Antti P Miettinen <anmietti@trshp.ntc.nokia.com>
+
+ * rtems/score/cpu.h: define CPU_Exception_frame for rdbg.
+ * m68302.h: Make buffer pointer in m302_SCC_bd volatile.
+
+2000-10-12 John S Gwynne <jgwynne@mrcday.com>
+
+ * sim.h: These changes enable RTEMS to automatically generate
+ the ram_init file used by gdb with the BDM patches. The 332 has
+ on-board chip select lines (for RAM and FLASH) that must be
+ configured before use of these peripherals. These patches parse
+ data from start.c where the chip select lines are configured in
+ the runtime executable and automatically generates the gdb
+ initialization file using the same settings. A great time saver.
+ A similar file, ram_init_FW (flash writable), is also generated
+ that the flash programming tool uses.
+ * BSP/start/start.c: Must be modified to support above.
+ * BSP/start/ram_init.ld, BSP/start/ram_init.sed: New files.
+
+2000-09-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include compile.am.
+
+2000-08-10 Joel Sherrill <joel@OARcorp.com>
+
+ * ChangeLog: New file.
diff --git a/cpukit/score/cpu/m68k/Makefile.am b/cpukit/score/cpu/m68k/Makefile.am
new file mode 100644
index 0000000000..f5323ff629
--- /dev/null
+++ b/cpukit/score/cpu/m68k/Makefile.am
@@ -0,0 +1,84 @@
+##
+## $Id$
+##
+
+include $(top_srcdir)/automake/compile.am
+
+EXTRA_LIBRARIES = libscorecpu.a
+CLEANFILES = libscorecpu.a
+libscorecpu_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libscorecpu_g.a
+CLEANFILES += libscorecpu_g.a
+libscorecpu_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+include_rtemsdir = $(includedir)/rtems
+include_rtems_HEADERS = asm.h
+
+include_rtems_m68kdir = $(includedir)/rtems/m68k
+include_rtems_m68k_HEADERS = m68302.h m68360.h qsm.h sim.h
+
+include_rtems_scoredir = $(includedir)/rtems/score
+include_rtems_score_HEADERS = rtems/score/cpu.h rtems/score/m68k.h \
+ rtems/score/types.h
+
+libscorecpu_a_SOURCES = cpu.c cpu_asm.S
+
+libscorecpu_g_a_SOURCES = $(libscorecpu_a_SOURCES)
+
+all-local: $(PREINSTALL_FILES) libscorecpu$(LIB_VARIANT).a
+
+PREINSTALL_DIRS =
+PREINSTALL_FILES =
+
+$(PROJECT_INCLUDE)/rtems/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems
+ @: > $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/asm.h: asm.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/asm.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/asm.h
+
+$(PROJECT_INCLUDE)/rtems/m68k/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems/m68k
+ @: > $(PROJECT_INCLUDE)/rtems/m68k/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/m68k/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/m68k/m68302.h: m68302.h $(PROJECT_INCLUDE)/rtems/m68k/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/m68k/m68302.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/m68k/m68302.h
+
+$(PROJECT_INCLUDE)/rtems/m68k/m68360.h: m68360.h $(PROJECT_INCLUDE)/rtems/m68k/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/m68k/m68360.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/m68k/m68360.h
+
+$(PROJECT_INCLUDE)/rtems/m68k/qsm.h: qsm.h $(PROJECT_INCLUDE)/rtems/m68k/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/m68k/qsm.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/m68k/qsm.h
+
+$(PROJECT_INCLUDE)/rtems/m68k/sim.h: sim.h $(PROJECT_INCLUDE)/rtems/m68k/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/m68k/sim.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/m68k/sim.h
+
+$(PROJECT_INCLUDE)/rtems/score/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems/score
+ @: > $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/score/cpu.h: rtems/score/cpu.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/cpu.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/cpu.h
+
+$(PROJECT_INCLUDE)/rtems/score/m68k.h: rtems/score/m68k.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/m68k.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/m68k.h
+
+$(PROJECT_INCLUDE)/rtems/score/types.h: rtems/score/types.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/types.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/types.h
+
+CLEANFILES += $(PREINSTALL_FILES)
+DISTCLEANFILES = $(PREINSTALL_DIRS)
+
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/score/cpu/m68k/asm.h b/cpukit/score/cpu/m68k/asm.h
new file mode 100644
index 0000000000..d35b3595fa
--- /dev/null
+++ b/cpukit/score/cpu/m68k/asm.h
@@ -0,0 +1,145 @@
+/* asm.h
+ *
+ * This include file attempts to address the problems
+ * caused by incompatible flavors of assemblers and
+ * toolsets. It primarily addresses variations in the
+ * use of leading underscores on symbols and the requirement
+ * that register names be preceded by a %.
+ *
+ *
+ * NOTE: The spacing in the use of these macros
+ * is critical to them working as advertised.
+ *
+ * COPYRIGHT:
+ *
+ * This file is based on similar code found in newlib available
+ * from ftp.cygnus.com. The file which was used had no copyright
+ * notice. This file is freely distributable as long as the source
+ * of the file is noted. This file is:
+ *
+ * COPYRIGHT (c) 1994-1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * $Id$
+ */
+
+#ifndef __M68k_ASM_h
+#define __M68k_ASM_h
+
+/*
+ * Indicate we are in an assembly file and get the basic CPU definitions.
+ */
+
+#ifndef ASM
+#define ASM
+#endif
+#include <rtems/score/cpuopts.h>
+#include <rtems/score/cpu.h>
+
+/*
+ * Recent versions of GNU cpp define variables which indicate the
+ * need for underscores and percents. If not using GNU cpp or
+ * the version does not support this, then you will obviously
+ * have to define these as appropriate.
+ */
+
+#ifndef __USER_LABEL_PREFIX__
+#define __USER_LABEL_PREFIX__ _
+#endif
+
+#ifndef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__
+#endif
+
+/* ANSI concatenation macros. */
+
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+#define EVAL(x) x
+#define CONCAT0(a, b) EVAL(a)EVAL(b)
+
+/* Use the right prefix for global labels. */
+
+#define SYM(x) CONCAT0 (__USER_LABEL_PREFIX__, x)
+
+/* Use the right prefix for registers. */
+
+#define REG(x) CONCAT0 (__REGISTER_PREFIX__, x)
+
+#define d0 REG (d0)
+#define d1 REG (d1)
+#define d2 REG (d2)
+#define d3 REG (d3)
+#define d4 REG (d4)
+#define d5 REG (d5)
+#define d6 REG (d6)
+#define d7 REG (d7)
+#define a0 REG (a0)
+#define a1 REG (a1)
+#define a2 REG (a2)
+#define a3 REG (a3)
+#define a4 REG (a4)
+#define a5 REG (a5)
+#define a6 REG (a6)
+#define a7 REG (a7)
+#define sp REG (sp)
+
+#define msp REG (msp)
+#define usp REG (usp)
+#define isp REG (isp)
+#define sr REG (sr)
+#define vbr REG (vbr)
+#define dfc REG (dfc)
+#define sfc REG (sfc)
+
+/* mcf52xx special regs */
+#define cacr REG (cacr)
+#define acr0 REG (acr0)
+#define acr1 REG (acr1)
+#define rambar0 REG (rambar0)
+#define mbar REG (mbar)
+
+
+#define fp0 REG (fp0)
+#define fp1 REG (fp1)
+#define fp2 REG (fp2)
+#define fp3 REG (fp3)
+#define fp4 REG (fp4)
+#define fp5 REG (fp5)
+#define fp6 REG (fp6)
+#define fp7 REG (fp7)
+
+#define fpc REG (fpc)
+#define fpi REG (fpi)
+#define fps REG (fps)
+#define fpsr REG (fpsr)
+
+
+/*
+ * Define macros to handle section beginning and ends.
+ */
+
+
+#define BEGIN_CODE_DCL .text
+#define END_CODE_DCL
+#define BEGIN_DATA_DCL .data
+#define END_DATA_DCL
+#define BEGIN_CODE .text
+#define END_CODE
+#define BEGIN_DATA .data
+#define END_DATA
+#define BEGIN_BSS .bss
+#define END_BSS
+#define END
+
+/*
+ * Following must be tailor for a particular flavor of the C compiler.
+ * They may need to put underscores in front of the symbols.
+ */
+
+#define PUBLIC(sym) .globl SYM (sym)
+#define EXTERN(sym) .globl SYM (sym)
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/m68k/cpu.c b/cpukit/score/cpu/m68k/cpu.c
new file mode 100644
index 0000000000..1b1e6457f0
--- /dev/null
+++ b/cpukit/score/cpu/m68k/cpu.c
@@ -0,0 +1,212 @@
+/*
+ * Motorola MC68xxx Dependent Source
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+
+/* _CPU_Initialize
+ *
+ * This routine performs processor dependent initialization.
+ *
+ * INPUT PARAMETERS:
+ * cpu_table - CPU table to initialize
+ * thread_dispatch - entry pointer to thread dispatcher
+ *
+ * OUTPUT PARAMETERS: NONE
+ */
+
+void _CPU_Initialize(
+ rtems_cpu_table *cpu_table,
+ void (*thread_dispatch) /* ignored on this CPU */
+)
+{
+#if ( M68K_HAS_VBR == 0 )
+ /* fill the isr redirect table with the code to place the format/id
+ onto the stack */
+
+ uint32_t slot;
+
+ for (slot = 0; slot < CPU_INTERRUPT_NUMBER_OF_VECTORS; slot++)
+ {
+ _CPU_ISR_jump_table[slot].move_a7 = M68K_MOVE_A7;
+ _CPU_ISR_jump_table[slot].format_id = slot << 2;
+ _CPU_ISR_jump_table[slot].jmp = M68K_JMP;
+ _CPU_ISR_jump_table[slot].isr_handler = (uint32_t ) 0xDEADDEAD;
+ }
+#endif /* M68K_HAS_VBR */
+
+ _CPU_Table = *cpu_table;
+}
+
+/*PAGE
+ *
+ * _CPU_ISR_Get_level
+ */
+
+uint32_t _CPU_ISR_Get_level( void )
+{
+ uint32_t level;
+
+ m68k_get_interrupt_level( level );
+
+ return level;
+}
+
+/*PAGE
+ *
+ * _CPU_ISR_install_raw_handler
+ */
+
+void _CPU_ISR_install_raw_handler(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+)
+{
+ proc_ptr *interrupt_table = NULL;
+
+#if (M68K_HAS_FPSP_PACKAGE == 1)
+ /*
+ * If this vector being installed is one related to FP, then the
+ * FPSP will install the handler itself and handle it completely
+ * with no intervention from RTEMS.
+ */
+
+ if (*_FPSP_install_raw_handler &&
+ (*_FPSP_install_raw_handler)(vector, new_handler, *old_handler))
+ return;
+#endif
+
+
+ /*
+ * On CPU models without a VBR, it is necessary for there to be some
+ * header code for each ISR which saves a register, loads the vector
+ * number, and jumps to _ISR_Handler.
+ */
+
+ m68k_get_vbr( interrupt_table );
+#if ( M68K_HAS_VBR == 1 )
+ *old_handler = interrupt_table[ vector ];
+ interrupt_table[ vector ] = new_handler;
+#else
+
+ /*
+ * Install handler into RTEMS jump table and if VBR table is in
+ * RAM, install the pointer to the appropriate jump table slot.
+ * If the VBR table is in ROM, it is the BSP's responsibility to
+ * load it appropriately to vector to the RTEMS jump table.
+ */
+
+ *old_handler = (proc_ptr) _CPU_ISR_jump_table[vector].isr_handler;
+ _CPU_ISR_jump_table[vector].isr_handler = (uint32_t ) new_handler;
+ if ( (uint32_t ) interrupt_table != 0xFFFFFFFF )
+ interrupt_table[ vector ] = (proc_ptr) &_CPU_ISR_jump_table[vector];
+#endif /* M68K_HAS_VBR */
+}
+
+/*PAGE
+ *
+ * _CPU_ISR_install_vector
+ *
+ * This kernel routine installs the RTEMS handler for the
+ * specified vector.
+ *
+ * Input parameters:
+ * vector - interrupt vector number
+ * new_handler - replacement ISR for this vector number
+ * old_handler - former ISR for this vector number
+ *
+ * Output parameters: NONE
+ */
+
+void _CPU_ISR_install_vector(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+)
+{
+ proc_ptr ignored;
+
+ *old_handler = _ISR_Vector_table[ vector ];
+
+ _CPU_ISR_install_raw_handler( vector, _ISR_Handler, &ignored );
+
+ _ISR_Vector_table[ vector ] = new_handler;
+}
+
+
+/*PAGE
+ *
+ * _CPU_Install_interrupt_stack
+ */
+
+void _CPU_Install_interrupt_stack( void )
+{
+#if ( M68K_HAS_SEPARATE_STACKS == 1 )
+ void *isp = _CPU_Interrupt_stack_high;
+
+ asm volatile ( "movec %0,%%isp" : "=r" (isp) : "0" (isp) );
+#endif
+}
+
+#if ( M68K_HAS_BFFFO != 1 )
+/*
+ * Returns table for duplication of the BFFFO instruction (16 bits only)
+ */
+const unsigned char __BFFFOtable[256] = {
+ 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+#endif
+
+/*PAGE
+ *
+ * The following code context switches the software FPU emulation
+ * code provided with GCC.
+ */
+
+#if (CPU_SOFTWARE_FP == TRUE)
+extern Context_Control_fp _fpCCR;
+
+void CPU_Context_save_fp (void **fp_context_ptr)
+{
+ Context_Control_fp *fp;
+
+ fp = (Context_Control_fp *) *fp_context_ptr;
+
+ *fp = _fpCCR;
+}
+
+void CPU_Context_restore_fp (void **fp_context_ptr)
+{
+ Context_Control_fp *fp;
+
+ fp = (Context_Control_fp *) *fp_context_ptr;
+
+ _fpCCR = *fp;
+}
+#endif
diff --git a/cpukit/score/cpu/m68k/cpu_asm.S b/cpukit/score/cpu/m68k/cpu_asm.S
new file mode 100644
index 0000000000..9156212311
--- /dev/null
+++ b/cpukit/score/cpu/m68k/cpu_asm.S
@@ -0,0 +1,265 @@
+/* cpu_asm.s
+ *
+ * This file contains all assembly code for the MC68020 implementation
+ * of RTEMS.
+ *
+ * COPYRIGHT (c) 1989-2001.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+
+#include <rtems/asm.h>
+
+ .text
+
+/* void _CPU_Context_switch( run_context, heir_context )
+ *
+ * This routine performs a normal non-FP context.
+ */
+
+ .align 4
+ .global SYM (_CPU_Context_switch)
+
+.set RUNCONTEXT_ARG, 4 | save context argument
+.set HEIRCONTEXT_ARG, 8 | restore context argument
+
+SYM (_CPU_Context_switch):
+ moval a7@(RUNCONTEXT_ARG),a0| a0 = running thread context
+ movw sr,d1 | d1 = status register
+ movml d1-d7/a2-a7,a0@ | save context
+
+ moval a7@(HEIRCONTEXT_ARG),a0| a0 = heir thread context
+restore: movml a0@,d1-d7/a2-a7 | restore context
+ movw d1,sr | restore status register
+ rts
+
+/*PAGE
+ * void __CPU_Context_save_fp_context( &fp_context_ptr )
+ * void __CPU_Context_restore_fp_context( &fp_context_ptr )
+ *
+ * These routines are used to context switch a MC68881 or MC68882.
+ *
+ * NOTE: Context save and restore code is based upon the code shown
+ * on page 6-38 of the MC68881/68882 Users Manual (rev 1).
+ *
+ * CPU_FP_CONTEXT_SIZE is higher than expected to account for the
+ * -1 pushed at end of this sequence.
+ *
+ * Neither of these entries is required if we have software FPU
+ * emulation. But if we don't have an FPU or emulation, then
+ * we need the stub versions of these routines.
+ */
+
+#if (CPU_SOFTWARE_FP == FALSE)
+
+.set FPCONTEXT_ARG, 4 | save FP context argument
+
+ .align 4
+ .global SYM (_CPU_Context_save_fp)
+SYM (_CPU_Context_save_fp):
+#if ( M68K_HAS_FPU == 1 )
+ moval a7@(FPCONTEXT_ARG),a1 | a1 = &ptr to context area
+ moval a1@,a0 | a0 = Save context area
+ fsave a0@- | save 68881/68882 state frame
+ tstb a0@ | check for a null frame
+ beq.b nosv | Yes, skip save of user model
+ fmovem fp0-fp7,a0@- | save data registers (fp0-fp7)
+ fmovem fpc/fps/fpi,a0@- | and save control registers
+ movl #-1,a0@- | place not-null flag on stack
+nosv: movl a0,a1@ | save pointer to saved context
+#endif
+ rts
+
+ .align 4
+ .global SYM (_CPU_Context_restore_fp)
+SYM (_CPU_Context_restore_fp):
+#if ( M68K_HAS_FPU == 1 )
+ moval a7@(FPCONTEXT_ARG),a1 | a1 = &ptr to context area
+ moval a1@,a0 | a0 = address of saved context
+ tstb a0@ | Null context frame?
+ beq.b norst | Yes, skip fp restore
+ addql #4,a0 | throwaway non-null flag
+ fmovem a0@+,fpc/fps/fpi | restore control registers
+ fmovem a0@+,fp0-fp7 | restore data regs (fp0-fp7)
+norst: frestore a0@+ | restore the fp state frame
+ movl a0,a1@ | save pointer to saved context
+#endif
+ rts
+#endif
+
+/*PAGE
+ * void _ISR_Handler()
+ *
+ * This routine provides the RTEMS interrupt management.
+ *
+ * NOTE:
+ * Upon entry, the master stack will contain an interrupt stack frame
+ * back to the interrupted thread and the interrupt stack will contain
+ * a throwaway interrupt stack frame. If dispatching is enabled, and this
+ * is the outer most interrupt, and a context switch is necessary or
+ * the current thread has pending signals, then set up the master stack to
+ * transfer control to the interrupt dispatcher.
+ */
+
+#if ( M68K_COLDFIRE_ARCH == 1 )
+.set SR_OFFSET, 2 | Status register offset
+.set PC_OFFSET, 4 | Program Counter offset
+.set FVO_OFFSET, 0 | Format/vector offset
+#elif ( M68K_HAS_VBR == 1)
+.set SR_OFFSET, 0 | Status register offset
+.set PC_OFFSET, 2 | Program Counter offset
+.set FVO_OFFSET, 6 | Format/vector offset
+#else
+.set SR_OFFSET, 2 | Status register offset
+.set PC_OFFSET, 4 | Program Counter offset
+.set FVO_OFFSET, 0 | Format/vector offset placed in the stack
+#endif /* M68K_HAS_VBR */
+
+.set SAVED, 16 | space for saved registers
+
+ .align 4
+ .global SYM (_ISR_Handler)
+
+SYM (_ISR_Handler):
+ addql #1,SYM (_Thread_Dispatch_disable_level) | disable multitasking
+#if ( M68K_COLDFIRE_ARCH == 0 )
+ moveml d0-d1/a0-a1,a7@- | save d0-d1,a0-a1
+#else
+ lea a7@(-SAVED),a7
+ movm.l d0-d1/a0-a1,a7@ | save d0-d1,a0-a1
+#endif
+ movew a7@(SAVED+FVO_OFFSET),d0 | d0 = F/VO
+ andl #0x0ffc,d0 | d0 = vector offset in vbr
+
+
+#if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == 1 )
+ movel _CPU_Interrupt_stack_high,a0 | a0 now point just above interrupt stack
+ cmpl _CPU_Interrupt_stack_low,a7 | stack below interrupt stack?
+ bcs.b 1f | yes, switch to interrupt stack
+ cmpl a0,a7 | stack above interrupt stack?
+ bcs.b 2f | no, do not switch stacks
+1:
+ movel a7,a1 | copy task stack pointer
+ movel a0,a7 | switch to interrupt stack
+ movel a1,a7@- | store task stack pointer on interrupt stack
+2:
+#endif /* CPU_HAS_SOFTWARE_INTERRUPT_STACK == 1 */
+
+ addql #1,SYM(_ISR_Nest_level) | one nest level deeper
+
+ movel SYM (_ISR_Vector_table),a0 | a0= base of RTEMS table
+#if ( M68K_HAS_PREINDEXING == 1 )
+ movel (a0,d0:w:1),a0 | a0 = address of user routine
+#else
+ addal d0,a0 | a0 = address of vector
+ movel (a0),a0 | a0 = address of user routine
+#endif
+
+ lsrl #2,d0 | d0 = vector number
+ movel d0,a7@- | push vector number
+ jbsr a0@ | invoke the user ISR
+ addql #4,a7 | remove vector number
+ subql #1,SYM(_ISR_Nest_level) | Reduce interrupt-nesting count
+
+#if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == 1 )
+ movel _CPU_Interrupt_stack_high,a0
+ subql #4,a0
+ cmpl a0,a7 | At top of interrupt stack?
+ bne.b 1f | No, do not restore task stack pointer
+ movel (a7),a7 | Restore task stack pointer
+1:
+#endif /* CPU_HAS_SOFTWARE_INTERRUPT_STACK == 1 */
+ subql #1,SYM (_Thread_Dispatch_disable_level)
+ | unnest multitasking
+ bne.b exit | If dispatch disabled, exit
+
+#if ( M68K_HAS_SEPARATE_STACKS == 1 )
+ movew #0xf000,d0 | isolate format nibble
+ andw a7@(SAVED+FVO_OFFSET),d0 | get F/VO
+ cmpiw #0x1000,d0 | is it a throwaway isf?
+ bne.b exit | NOT outer level, so branch
+#else
+/*
+ * If we have a CPU which allows a higher-priority interrupt to preempt a
+ * lower priority handler before the lower-priority handler can increment
+ * _Thread_Dispatch_disable_level then we must check the PC on the stack to
+ * see if it is _ISR_Handler. If it is we have the case of nesting interrupts
+ * without the dispatch level being incremented.
+ */
+ #if ( M68K_COLDFIRE_ARCH == 0 && M68K_MC68060_ARCH == 0 )
+ cmpl #_ISR_Handler,a7@(SAVED+PC_OFFSET)
+ beq.b exit
+ #endif
+#endif
+ tstl SYM (_Context_Switch_necessary)
+ | Is thread switch necessary?
+ bne.b bframe | Yes, invoke dispatcher
+
+ tstl SYM (_ISR_Signals_to_thread_executing)
+ | signals sent to Run_thread
+ | while in interrupt handler?
+ beq.b exit | No, then exit
+
+bframe: clrl SYM (_ISR_Signals_to_thread_executing)
+ | If sent, will be processed
+#if ( M68K_HAS_SEPARATE_STACKS == 1 )
+ movec msp,a0 | a0 = master stack pointer
+ movew #0,a0@- | push format word
+ movel #SYM(_ISR_Dispatch),a0@- | push return addr
+ movew a0@(6),a0@- | push saved sr
+ movec a0,msp | set master stack pointer
+#else
+ jsr SYM (_Thread_Dispatch) | Perform context switch
+#endif
+
+#if ( M68K_COLDFIRE_ARCH == 0 )
+exit: moveml a7@+,d0-d1/a0-a1 | restore d0-d1,a0-a1
+#else
+exit: moveml a7@,d0-d1/a0-a1 | restore d0-d1,a0-a1
+ lea a7@(SAVED),a7
+#endif
+
+#if ( M68K_HAS_VBR == 0 )
+ addql #2,a7 | pop format/id
+#endif /* M68K_HAS_VBR */
+ rte | return to thread
+ | OR _Isr_dispatch
+
+/*PAGE
+ * void _ISR_Dispatch()
+ *
+ * Entry point from the outermost interrupt service routine exit.
+ * The current stack is the supervisor mode stack if this processor
+ * has separate stacks.
+ *
+ * 1. save all registers not preserved across C calls.
+ * 2. invoke the _Thread_Dispatch routine to switch tasks
+ * or a signal to the currently executing task.
+ * 3. restore all registers not preserved across C calls.
+ * 4. return from interrupt
+ */
+
+ .global SYM (_ISR_Dispatch)
+SYM (_ISR_Dispatch):
+#if ( M68K_COLDFIRE_ARCH == 0 )
+ movml d0-d1/a0-a1,a7@-
+ jsr SYM (_Thread_Dispatch)
+ movml a7@+,d0-d1/a0-a1
+#else
+ lea a7@(-SAVED),a7
+ movml d0-d1/a0-a1,a7@
+ jsr SYM (_Thread_Dispatch)
+ movml a7@,d0-d1/a0-a1
+ lea a7@(SAVED),a7
+#endif
+
+#if ( M68K_HAS_VBR == 0 )
+ addql #2,a7 | pop format/id
+#endif /* M68K_HAS_VBR */
+ rte
diff --git a/cpukit/score/cpu/m68k/m68302.h b/cpukit/score/cpu/m68k/m68302.h
new file mode 100644
index 0000000000..0ee052b8b3
--- /dev/null
+++ b/cpukit/score/cpu/m68k/m68302.h
@@ -0,0 +1,661 @@
+/*
+ *------------------------------------------------------------------
+ *
+ * m68302.h - Definitions for Motorola MC68302 processor.
+ *
+ * Section references in this file refer to revision 2 of Motorola's
+ * "MC68302 Integrated Multiprotocol Processor User's Manual".
+ * (Motorola document MC68302UM/AD REV 2.)
+ *
+ * Based on Don Meyer's cpu68302.h that was posted in comp.sys.m68k
+ * on 17 February, 1993.
+ *
+ * Copyright 1995 David W. Glessner.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the following conditions are met:
+ * 1. Redistribution of source code and documentation must retain
+ * the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * 2. 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 "AS IS" without warranty of any kind,
+ * either expressed or implied, including, but not limited to, the
+ * implied warranties of merchantability, title and fitness for a
+ * particular purpose.
+ *
+ *
+ * $Id$
+ *
+ *------------------------------------------------------------------
+ */
+
+#ifndef __MOTOROLA_MC68302_DEFINITIONS_h
+#define __MOTOROLA_MC68302_DEFINITIONS_h
+
+/*
+ * BAR - Base Address Register
+ * Section 2.7
+ */
+#define M302_BAR (*((volatile uint16_t *) 0xf2))
+
+/*
+ * SCR - System Control Register
+ * Section 3.8.1
+ */
+#define M302_SCR (*((volatile uint32_t *) 0xf4))
+/*
+ * SCR bits
+ */
+#define RBIT_SCR_IPA 0x08000000
+#define RBIT_SCR_HWT 0x04000000
+#define RBIT_SCR_WPV 0x02000000
+#define RBIT_SCR_ADC 0x01000000
+
+#define RBIT_SCR_ERRE 0x00400000
+#define RBIT_SCR_VGE 0x00200000
+#define RBIT_SCR_WPVE 0x00100000
+#define RBIT_SCR_RMCST 0x00080000
+#define RBIT_SCR_EMWS 0x00040000
+#define RBIT_SCR_ADCE 0x00020000
+#define RBIT_SCR_BCLM 0x00010000
+
+#define RBIT_SCR_FRZW 0x00008000
+#define RBIT_SCR_FRZ2 0x00004000
+#define RBIT_SCR_FRZ1 0x00002000
+#define RBIT_SCR_SAM 0x00001000
+#define RBIT_SCR_HWDEN 0x00000800
+#define RBIT_SCR_HWDCN2 0x00000400
+#define RBIT_SCR_HWDCN1 0x00000200 /* 512 clocks */
+#define RBIT_SCR_HWDCN0 0x00000100 /* 128 clocks */
+
+#define RBIT_SCR_LPREC 0x00000080
+#define RBIT_SCR_LPP16 0x00000040
+#define RBIT_SCR_LPEN 0x00000020
+#define RBIT_SCR_LPCLKDIV 0x0000001f
+
+
+/*
+ * 68000 interrupt and trap vector numbers
+ */
+#define M68K_IVEC_BUS_ERROR 2
+#define M68K_IVEC_ADDRESS_ERROR 3
+#define M68K_IVEC_ILLEGAL_OPCODE 4
+#define M68K_IVEC_ZERO_DIVIDE 5
+#define M68K_IVEC_CHK 6
+#define M68K_IVEC_TRAPV 7
+#define M68K_IVEC_PRIVILEGE 8
+#define M68K_IVEC_TRACE 9
+#define M68K_IVEC_LINE_A 10
+#define M68K_IVEC_LINE_F 11
+/* Unassigned, Reserved 12-14 */
+#define M68K_IVEC_UNINITIALIZED_INT 15
+/* Unassigned, Reserved 16-23 */
+#define M68K_IVEC_SPURIOUS_INT 24
+
+#define M68K_IVEC_LEVEL1_AUTOVECTOR 25
+#define M68K_IVEC_LEVEL2_AUTOVECTOR 26
+#define M68K_IVEC_LEVEL3_AUTOVECTOR 27
+#define M68K_IVEC_LEVEL4_AUTOVECTOR 28
+#define M68K_IVEC_LEVEL5_AUTOVECTOR 29
+#define M68K_IVEC_LEVEL6_AUTOVECTOR 30
+#define M68K_IVEC_LEVEL7_AUTOVECTOR 31
+
+#define M68K_IVEC_TRAP0 32
+#define M68K_IVEC_TRAP1 33
+#define M68K_IVEC_TRAP2 34
+#define M68K_IVEC_TRAP3 35
+#define M68K_IVEC_TRAP4 36
+#define M68K_IVEC_TRAP5 37
+#define M68K_IVEC_TRAP6 38
+#define M68K_IVEC_TRAP7 39
+#define M68K_IVEC_TRAP8 40
+#define M68K_IVEC_TRAP9 41
+#define M68K_IVEC_TRAP10 42
+#define M68K_IVEC_TRAP11 43
+#define M68K_IVEC_TRAP12 44
+#define M68K_IVEC_TRAP13 45
+#define M68K_IVEC_TRAP14 46
+#define M68K_IVEC_TRAP15 47
+/*
+ * Unassigned, Reserved 48-59
+ *
+ * Note: Vectors 60-63 are used by the MC68302 (e.g. BAR, SCR).
+ */
+
+/*
+ * MC68302 Interrupt Vectors
+ * Section 3.2
+ */
+enum m68302_ivec_e {
+ M302_IVEC_ERR =0,
+ M302_IVEC_PB8 =1, /* General-Purpose Interrupt 0 */
+ M302_IVEC_SMC2 =2,
+ M302_IVEC_SMC1 =3,
+ M302_IVEC_TIMER3 =4,
+ M302_IVEC_SCP =5,
+ M302_IVEC_TIMER2 =6,
+ M302_IVEC_PB9 =7, /* General-Purpose Interrupt 1 */
+ M302_IVEC_SCC3 =8,
+ M302_IVEC_TIMER1 =9,
+ M302_IVEC_SCC2 =10,
+ M302_IVEC_IDMA =11,
+ M302_IVEC_SDMA =12, /* SDMA Channels Bus Error */
+ M302_IVEC_SCC1 =13,
+ M302_IVEC_PB10 =14, /* General-Purpose Interrupt 2 */
+ M302_IVEC_PB11 =15, /* General-Purpose Interrupt 3 */
+ M302_IVEC_IRQ1 =17, /* External Device */
+ M302_IVEC_IRQ6 =22, /* External Device */
+ M302_IVEC_IRQ7 =23 /* External Device */
+};
+
+
+/*
+ * GIMR - Global Interrupt Mode Register
+ * Section 3.2.5.1
+ */
+#define RBIT_GIMR_MOD (1<<15)
+#define RBIT_GIMR_IV7 (1<<14)
+#define RBIT_GIMR_IV6 (1<<13)
+#define RBIT_GIMR_IV1 (1<<12)
+#define RBIT_GIMR_ET7 (1<<10)
+#define RBIT_GIMR_ET6 (1<<9)
+#define RBIT_GIMR_ET1 (1<<8)
+#define RBIT_GIMR_VECTOR (7<<5)
+
+/*
+ * IPR - Interrupt Pending Register (Section 3.2.5.2)
+ * IMR - Interrupt Mask Register (Section 3.2.5.3)
+ * ISR - Interrupt In-Service Register (Section 3.2.5.4)
+ */
+#define RBIT_IPR_PB11 (1<<15)
+#define RBIT_IPR_PB10 (1<<14)
+#define RBIT_IPR_SCC1 (1<<13)
+#define RBIT_IPR_SDMA (1<<12)
+#define RBIT_IPR_IDMA (1<<11)
+#define RBIT_IPR_SCC2 (1<<10)
+#define RBIT_IPR_TIMER1 (1<<9)
+#define RBIT_IPR_SCC3 (1<<8)
+#define RBIT_IPR_PB9 (1<<7)
+#define RBIT_IPR_TIMER2 (1<<6)
+#define RBIT_IPR_SCP (1<<5)
+#define RBIT_IPR_TIMER3 (1<<4)
+#define RBIT_IPR_SMC1 (1<<3)
+#define RBIT_IPR_SMC2 (1<<2)
+#define RBIT_IPR_PB8 (1<<1)
+#define RBIT_IPR_ERR (1<<0)
+
+#define RBIT_ISR_PB11 (1<<15)
+#define RBIT_ISR_PB10 (1<<14)
+#define RBIT_ISR_SCC1 (1<<13)
+#define RBIT_ISR_SDMA (1<<12)
+#define RBIT_ISR_IDMA (1<<11)
+#define RBIT_ISR_SCC2 (1<<10)
+#define RBIT_ISR_TIMER1 (1<<9)
+#define RBIT_ISR_SCC3 (1<<8)
+#define RBIT_ISR_PB9 (1<<7)
+#define RBIT_ISR_TIMER2 (1<<6)
+#define RBIT_ISR_SCP (1<<5)
+#define RBIT_ISR_TIMER3 (1<<4)
+#define RBIT_ISR_SMC1 (1<<3)
+#define RBIT_ISR_SMC2 (1<<2)
+#define RBIT_ISR_PB8 (1<<1)
+
+#define RBIT_IMR_PB11 (1<<15) /* PB11 Interrupt Mask */
+#define RBIT_IMR_PB10 (1<<14) /* PB10 Interrupt Mask */
+#define RBIT_IMR_SCC1 (1<<13) /* SCC1 Interrupt Mask */
+#define RBIT_IMR_SDMA (1<<12) /* SDMA Interrupt Mask */
+#define RBIT_IMR_IDMA (1<<11) /* IDMA Interrupt Mask */
+#define RBIT_IMR_SCC2 (1<<10) /* SCC2 Interrupt Mask */
+#define RBIT_IMR_TIMER1 (1<<9) /* TIMER1 Interrupt Mask */
+#define RBIT_IMR_SCC3 (1<<8) /* SCC3 Interrupt Mask */
+#define RBIT_IMR_PB9 (1<<7) /* PB9 Interrupt Mask */
+#define RBIT_IMR_TIMER2 (1<<6) /* TIMER2 Interrupt Mask */
+#define RBIT_IMR_SCP (1<<5) /* SCP Interrupt Mask */
+#define RBIT_IMR_TIMER3 (1<<4) /* TIMER3 Interrupt Mask */
+#define RBIT_IMR_SMC1 (1<<3) /* SMC1 Interrupt Mask */
+#define RBIT_IMR_SMC2 (1<<2) /* SMC2 Interrupt Mask */
+#define RBIT_IMR_PB8 (1<<1) /* PB8 Interrupt Mask */
+
+
+/*
+ * DRAM Refresh
+ * Section 3.9
+ *
+ * The DRAM refresh memory map replaces the SCC2 Tx BD 6 and Tx BD 7
+ * structures in the parameter RAM.
+ *
+ * Access to the DRAM registers can be accomplished by
+ * the following approach:
+ *
+ * volatile m302_DRAM_refresh_t *dram;
+ * dram = (volatile m302_DRAM_refresh_t *) &m302.scc2.bd.tx[6];
+ *
+ * Then simply use pointer references (e.g. dram->count = 3).
+ */
+typedef struct {
+ uint16_t dram_high; /* DRAM high address and FC */
+ uint16_t dram_low; /* DRAM low address */
+ uint16_t increment; /* increment step (bytes/row) */
+ uint16_t count; /* RAM refresh cycle count (#rows) */
+ uint16_t t_ptr_h; /* temporary refresh high addr & FC */
+ uint16_t t_ptr_l; /* temporary refresh low address */
+ uint16_t t_count; /* temporary refresh cycles count */
+ uint16_t res; /* reserved */
+} m302_DRAM_refresh_t;
+
+
+/*
+ * TMR - Timer Mode Register (for timers 1 and 2)
+ * Section 3.5.2.1
+ */
+#define RBIT_TMR_ICLK_STOP (0<<1)
+#define RBIT_TMR_ICLK_MASTER (1<<1)
+#define RBIT_TMR_ICLK_MASTER16 (2<<1)
+#define RBIT_TMR_ICLK_TIN (3<<1)
+
+#define RBIT_TMR_OM (1<<5)
+#define RBIT_TMR_ORI (1<<4)
+#define RBIT_TMR_FRR (1<<3)
+#define RBIT_TMR_RST (1<<0)
+
+
+/*
+ * TER - Timer Event Register (for timers 1 and 2)
+ * Section 3.5.2.5
+ */
+#define RBIT_TER_REF (1<<1) /* Output Reference Event */
+#define RBIT_TER_CAP (1<<0) /* Capture Event */
+
+
+/*
+ * SCC Buffer Descriptors and Buffer Descriptors Table
+ * Section 4.5.5
+ */
+typedef struct m302_SCC_bd {
+ uint16_t status; /* status and control */
+ uint16_t length; /* data length */
+ volatile uint8_t *buffer; /* data buffer pointer */
+} m302_SCC_bd_t;
+
+typedef struct {
+ m302_SCC_bd_t rx[8]; /* receive buffer descriptors */
+ m302_SCC_bd_t tx[8]; /* transmit buffer descriptors */
+} m302_SCC_bd_table_t;
+
+
+/*
+ * SCC Parameter RAM (offset 0x080 from an SCC Base)
+ * Section 4.5.6
+ *
+ * Each SCC parameter RAM area begins at offset 0x80 from each SCC base
+ * area (0x400, 0x500, or 0x600 from the dual-port RAM base).
+ *
+ * Offsets 0x9c-0xbf from each SCC base area compose the protocol-specific
+ * portion of the SCC parameter RAM.
+ */
+typedef struct {
+ uint8_t rfcr; /* Rx Function Code */
+ uint8_t tfcr; /* Tx Function Code */
+ uint16_t mrblr; /* Maximum Rx Buffer Length */
+ uint16_t _rstate; /* Rx Internal State */
+ uint8_t res2;
+ uint8_t rbd; /* Rx Internal Buffer Number */
+ uint32_t _rdptr; /* Rx Internal Data Pointer */
+ uint16_t _rcount; /* Rx Internal Byte Count */
+ uint16_t _rtmp; /* Rx Temp */
+ uint16_t _tstate; /* Tx Internal State */
+ uint8_t res7;
+ uint8_t tbd; /* Tx Internal Buffer Number */
+ uint32_t _tdptr; /* Tx Internal Data Pointer */
+ uint16_t _tcount; /* Tx Internal Byte Count */
+ uint16_t _ttmp; /* Tx Temp */
+} m302_SCC_parameters_t;
+
+/*
+ * UART-Specific SCC Parameter RAM
+ * Section 4.5.11.3
+ */
+typedef struct {
+ uint16_t max_idl; /* Maximum IDLE Characters (rx) */
+ uint16_t idlc; /* Temporary rx IDLE counter */
+ uint16_t brkcr; /* Break Count Register (tx) */
+ uint16_t parec; /* Receive Parity Error Counter */
+ uint16_t frmec; /* Receive Framing Error Counter */
+ uint16_t nosec; /* Receive Noise Counter */
+ uint16_t brkec; /* Receive Break Condition Counter */
+ uint16_t uaddr1; /* UART ADDRESS Character 1 */
+ uint16_t uaddr2; /* UART ADDRESS Character 2 */
+ uint16_t rccr; /* Receive Control Character Register */
+ uint16_t character[8]; /* Control Characters 1 through 8*/
+} m302_SCC_UartSpecific_t;
+/*
+ * This definition allows for the checking of receive buffers
+ * for errors.
+ */
+
+#define RCV_ERR 0x003F
+
+/*
+ * UART receive buffer descriptor bit definitions.
+ * Section 4.5.11.14
+ */
+#define RBIT_UART_CTRL (1<<11) /* buffer contains a control char */
+#define RBIT_UART_ADDR (1<<10) /* first byte contains an address */
+#define RBIT_UART_MATCH (1<<9) /* indicates which addr char matched */
+#define RBIT_UART_IDLE (1<<8) /* buffer closed due to IDLE sequence */
+#define RBIT_UART_BR (1<<5) /* break sequence was received */
+#define RBIT_UART_FR (1<<4) /* framing error was received */
+#define RBIT_UART_PR (1<<3) /* parity error was received */
+#define RBIT_UART_OV (1<<1) /* receiver overrun occurred */
+#define RBIT_UART_CD (1<<0) /* carrier detect lost */
+#define RBIT_UART_STATUS 0x003B /* all status bits */
+
+/*
+ * UART transmit buffer descriptor bit definitions.
+ * Section 4.5.11.15
+ */
+#define RBIT_UART_CR (1<<11) /* clear-to-send report
+ * this results in two idle bits
+ * between back-to-back frames
+ */
+#define RBIT_UART_A (1<<10) /* buffer contains address characters
+ * only valid in multidrop mode (UM0=1)
+ */
+#define RBIT_UART_PREAMBLE (1<<9) /* send preamble before data */
+#define RBIT_UART_CTS_LOST (1<<0) /* CTS lost */
+
+/*
+ * UART event register
+ * Section 4.5.11.16
+ */
+#define M302_UART_EV_CTS (1<<7) /* CTS status changed */
+#define M302_UART_EV_CD (1<<6) /* carrier detect status changed */
+#define M302_UART_EV_IDL (1<<5) /* IDLE sequence status changed */
+#define M302_UART_EV_BRK (1<<4) /* break character was received */
+#define M302_UART_EV_CCR (1<<3) /* control character received */
+#define M302_UART_EV_TX (1<<1) /* buffer has been transmitted */
+#define M302_UART_EV_RX (1<<0) /* buffer has been received */
+
+
+/*
+ * HDLC-Specific SCC Parameter RAM
+ * Section 4.5.12.3
+ *
+ * c_mask_l should be 0xF0B8 for 16-bit CRC, 0xdebb for 32-bit CRC
+ * c_mask_h is a don't care for 16-bit CRC, 0x20E2 for 32-bit CRC
+ */
+typedef struct {
+ uint16_t rcrc_l; /* Temp Receive CRC Low */
+ uint16_t rcrc_h; /* Temp Receive CRC High */
+ uint16_t c_mask_l; /* CRC Mask Low */
+ uint16_t c_mask_h; /* CRC Mask High */
+ uint16_t tcrc_l; /* Temp Transmit CRC Low */
+ uint16_t tcrc_h; /* Temp Transmit CRC High */
+
+ uint16_t disfc; /* Discard Frame Counter */
+ uint16_t crcec; /* CRC Error Counter */
+ uint16_t abtsc; /* Abort Sequence Counter */
+ uint16_t nmarc; /* Nonmatching Address Received Cntr */
+ uint16_t retrc; /* Frame Retransmission Counter */
+
+ uint16_t mflr; /* Maximum Frame Length Register */
+ uint16_t max_cnt; /* Maximum_Length Counter */
+
+ uint16_t hmask; /* User Defined Frame Address Mask */
+ uint16_t haddr1; /* User Defined Frame Address */
+ uint16_t haddr2; /* " */
+ uint16_t haddr3; /* " */
+ uint16_t haddr4; /* " */
+} m302_SCC_HdlcSpecific_t;
+/*
+ * HDLC receiver buffer descriptor bit definitions
+ * Section 4.5.12.10
+ */
+#define RBIT_HDLC_EMPTY_BIT 0x8000 /* buffer associated with BD is empty */
+#define RBIT_HDLC_LAST_BIT 0x0800 /* buffer is last in a frame */
+#define RBIT_HDLC_FIRST_BIT 0x0400 /* buffer is first in a frame */
+#define RBIT_HDLC_FRAME_LEN 0x0020 /* receiver frame length violation */
+#define RBIT_HDLC_NONOCT_Rx 0x0010 /* received non-octet aligned frame */
+#define RBIT_HDLC_ABORT_SEQ 0x0008 /* received abort sequence */
+#define RBIT_HDLC_CRC_ERROR 0x0004 /* frame contains a CRC error */
+#define RBIT_HDLC_OVERRUN 0x0002 /* receiver overrun occurred */
+#define RBIT_HDLC_CD_LOST 0x0001 /* carrier detect lost */
+
+/*
+ * HDLC transmit buffer descriptor bit definitions
+ * Section 4.5.12.11
+ */
+#define RBIT_HDLC_READY_BIT 0x8000 /* buffer is ready to transmit */
+#define RBIT_HDLC_EXT_BUFFER 0x4000 /* buffer is in external memory */
+#define RBIT_HDLC_WRAP_BIT 0x2000 /* last buffer in bd table, so wrap */
+#define RBIT_HDLC_WAKE_UP 0x1000 /* interrupt when buffer serviced */
+#define RBIT_HDLC_LAST_BIT 0x0800 /* buffer is last in the frame */
+#define RBIT_HDLC_TxCRC_BIT 0x0400 /* transmit a CRC sequence */
+#define RBIT_HDLC_UNDERRUN 0x0002 /* transmitter underrun */
+#define RBIT_HDLC_CTS_LOST 0x0001 /* CTS lost */
+
+/*
+ * HDLC event register bit definitions
+ * Section 4.5.12.12
+ */
+#define RBIT_HDLC_CTS 0x80 /* CTS status changed */
+#define RBIT_HDLC_CD 0x40 /* carrier detect status changed */
+#define RBIT_HDLC_IDL 0x20 /* IDLE sequence status changed */
+#define RBIT_HDLC_TXE 0x10 /* transmit error */
+#define RBIT_HDLC_RXF 0x08 /* received frame */
+#define RBIT_HDLC_BSY 0x04 /* frame rcvd and discarded due to
+ * lack of buffers
+ */
+#define RBIT_HDLC_TXB 0x02 /* buffer has been transmitted */
+#define RBIT_HDLC_RXB 0x01 /* received buffer */
+
+
+
+typedef struct {
+ m302_SCC_bd_table_t bd; /* +000 Buffer Descriptor Table */
+ m302_SCC_parameters_t parm; /* +080 Common Parameter RAM */
+ union { /* +09C Protocol-Specific Parm RAM */
+ m302_SCC_UartSpecific_t uart;
+ m302_SCC_HdlcSpecific_t hdlc;
+ } prot;
+ uint8_t res[0x040]; /* +0C0 reserved, (not implemented) */
+} m302_SCC_t;
+
+
+/*
+ * Common SCC Registers
+ */
+typedef struct {
+ uint16_t res1;
+ uint16_t scon; /* SCC Configuration Register 4.5.2 */
+ uint16_t scm; /* SCC Mode Register 4.5.3 */
+ uint16_t dsr; /* SCC Data Synchronization Register 4.5.4 */
+ uint8_t scce; /* SCC Event Register 4.5.8.1 */
+ uint8_t res2;
+ uint8_t sccm; /* SCC Mask Register 4.5.8.2 */
+ uint8_t res3;
+ uint8_t sccs; /* SCC Status Register 4.5.8.3 */
+ uint8_t res4;
+ uint16_t res5;
+} m302_SCC_Registers_t;
+
+/*
+ * SCON - SCC Configuration Register
+ * Section 4.5.2
+ */
+#define RBIT_SCON_WOMS (1<<15) /* Wired-OR Mode Select (NMSI mode only)
+ * When set, the TXD driver is an
+ * open-drain output */
+#define RBIT_SCON_EXTC (1<<14) /* External Clock Source */
+#define RBIT_SCON_TCS (1<<13) /* Transmit Clock Source */
+#define RBIT_SCON_RCS (1<<12) /* Receive Clock Source */
+
+/*
+ * SCM - SCC Mode Register bit definitions
+ * Section 4.5.3
+ * The parameter-specific mode bits occupy bits 15 through 6.
+ */
+#define RBIT_SCM_ENR (1<<3) /* Enable receiver */
+#define RBIT_SCM_ENT (1<<2) /* Enable transmitter */
+
+
+/*
+ * Internal MC68302 Registers
+ * starts at offset 0x800 from dual-port RAM base
+ * Section 2.8
+ */
+typedef struct {
+ /* offset +800 */
+ uint16_t res0;
+ uint16_t cmr; /* IDMA Channel Mode Register */
+ uint32_t sapr; /* IDMA Source Address Pointer */
+ uint32_t dapr; /* IDMA Destination Address Pointer */
+ uint16_t bcr; /* IDMA Byte Count Register */
+ uint8_t csr; /* IDMA Channel Status Register */
+ uint8_t res1;
+ uint8_t fcr; /* IDMA Function Code Register */
+ uint8_t res2;
+
+ /* offset +812 */
+ uint16_t gimr; /* Global Interrupt Mode Register */
+ uint16_t ipr; /* Interrupt Pending Register */
+ uint16_t imr; /* Interrupt Mask Register */
+ uint16_t isr; /* Interrupt In-Service Register */
+ uint16_t res3;
+ uint16_t res4;
+
+ /* offset +81e */
+ uint16_t pacnt; /* Port A Control Register */
+ uint16_t paddr; /* Port A Data Direction Register */
+ uint16_t padat; /* Port A Data Register */
+ uint16_t pbcnt; /* Port B Control Register */
+ uint16_t pbddr; /* Port B Data Direction Register */
+ uint16_t pbdat; /* Port B Data Register */
+ uint16_t res5;
+
+ /* offset +82c */
+ uint16_t res6;
+ uint16_t res7;
+
+ uint16_t br0; /* Base Register (CS0) */
+ uint16_t or0; /* Option Register (CS0) */
+ uint16_t br1; /* Base Register (CS1) */
+ uint16_t or1; /* Option Register (CS1) */
+ uint16_t br2; /* Base Register (CS2) */
+ uint16_t or2; /* Option Register (CS2) */
+ uint16_t br3; /* Base Register (CS3) */
+ uint16_t or3; /* Option Register (CS3) */
+
+ /* offset +840 */
+ uint16_t tmr1; /* Timer Unit 1 Mode Register */
+ uint16_t trr1; /* Timer Unit 1 Reference Register */
+ uint16_t tcr1; /* Timer Unit 1 Capture Register */
+ uint16_t tcn1; /* Timer Unit 1 Counter */
+ uint8_t res8;
+ uint8_t ter1; /* Timer Unit 1 Event Register */
+ uint16_t wrr; /* Watchdog Reference Register */
+ uint16_t wcn; /* Watchdog Counter */
+ uint16_t res9;
+ uint16_t tmr2; /* Timer Unit 2 Mode Register */
+ uint16_t trr2; /* Timer Unit 2 Reference Register */
+ uint16_t tcr2; /* Timer Unit 2 Capture Register */
+ uint16_t tcn2; /* Timer Unit 2 Counter */
+ uint8_t resa;
+ uint8_t ter2; /* Timer Unit 2 Event Register */
+ uint16_t resb;
+ uint16_t resc;
+ uint16_t resd;
+
+ /* offset +860 */
+ uint8_t cr; /* Command Register */
+ uint8_t rese[0x1f];
+
+ /* offset +880, +890, +8a0 */
+ m302_SCC_Registers_t scc[3]; /* SCC1, SCC2, SCC3 Registers */
+
+ /* offset +8b0 */
+ uint16_t spmode; /* SCP,SMC Mode and Clock Cntrl Reg */
+ uint16_t simask; /* Serial Interface Mask Register */
+ uint16_t simode; /* Serial Interface Mode Register */
+} m302_internalReg_t ;
+
+
+/*
+ * MC68302 dual-port RAM structure.
+ * (Includes System RAM, Parameter RAM, and Internal Registers).
+ * Section 2.8
+ */
+typedef struct {
+ uint8_t mem[0x240]; /* +000 User Data Memory */
+ uint8_t res1[0x1c0]; /* +240 reserved, (not implemented) */
+ m302_SCC_t scc1; /* +400 SCC1 */
+ m302_SCC_t scc2; /* +500 SCC2 */
+ m302_SCC_t scc3; /* +600 SCC3 */
+ uint8_t res2[0x100]; /* +700 reserved, (not implemented) */
+ m302_internalReg_t reg; /* +800 68302 Internal Registers */
+} m302_dualPortRAM_t;
+
+/* some useful defines the some of the registers above */
+
+
+/* ----
+ MC68302 Chip Select Registers
+ p3-46 2nd Edition
+
+ */
+#define BR_ENABLED 1
+#define BR_DISABLED 0
+#define BR_FC_NULL 0
+#define BR_READ_ONLY 0
+#define BR_READ_WRITE 2
+#define OR_DTACK_0 0x0000
+#define OR_DTACK_1 0x2000
+#define OR_DTACK_2 0x4000
+#define OR_DTACK_3 0x6000
+#define OR_DTACK_4 0x8000
+#define OR_DTACK_5 0xA000
+#define OR_DTACK_6 0xC000
+#define OR_DTACK_EXT 0xE000
+#define OR_SIZE_64K 0x1FE0
+#define OR_SIZE_128K 0x1FC0
+#define OR_SIZE_256K 0x1F80
+#define OR_SIZE_512K 0x1F00
+#define OR_SIZE_1M 0x1E00
+#define OR_SIZE_2M 0x1C00
+#define OR_MASK_RW 0x0000
+#define OR_NO_MASK_RW 0x0002
+#define OR_MASK_FC 0x0000
+#define OR_NO_MASK_FC 0x0001
+
+#define MAKE_BR(base_address, enable, rw, fc) \
+ ((base_address >> 11) | fc | rw | enable)
+
+#define MAKE_OR(bsize, DtAck, RW_Mask, FC_Mask) \
+ (DtAck | ((~(bsize - 1) & 0x00FFFFFF) >> 11) | FC_Mask | RW_Mask)
+
+#define __REG_CAT(r, n) r ## n
+#define WRITE_BR(csel, base_address, enable, rw, fc) \
+ __REG_CAT(m302.reg.br, csel) = MAKE_BR(base_address, enable, rw, fc)
+#define WRITE_OR(csel, bsize, DtAck, RW_Mask, FC_Mask) \
+ __REG_CAT(m302.reg.or, csel) = MAKE_OR(bsize, DtAck, RW_Mask, FC_Mask)
+
+/* ----
+ MC68302 Watchdog Timer Enable Bit
+
+ */
+#define WATCHDOG_ENABLE (1)
+#define WATCHDOG_TRIGGER() (m302.reg.wrr = 0x10 | WATCHDOG_ENABLE, m302.reg.wcn = 0)
+#define WATCHDOG_TOGGLE() (m302.reg.wcn = WATCHDOG_TIMEOUT_PERIOD)
+#define DISABLE_WATCHDOG() (m302.reg.wrr = 0)
+
+/*
+ * Declare the variable that's used to reference the variables in
+ * the dual-port RAM.
+ */
+extern volatile m302_dualPortRAM_t m302;
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/m68k/m68360.h b/cpukit/score/cpu/m68k/m68360.h
new file mode 100644
index 0000000000..1bdf0a5995
--- /dev/null
+++ b/cpukit/score/cpu/m68k/m68360.h
@@ -0,0 +1,889 @@
+/*
+ **************************************************************************
+ **************************************************************************
+ ** **
+ ** MOTOROLA MC68360 QUAD INTEGRATED COMMUNICATIONS CONTROLLER (QUICC) **
+ ** **
+ ** HARDWARE DECLARATIONS **
+ ** **
+ ** **
+ ** Submitted By: **
+ ** **
+ ** W. Eric Norum **
+ ** Saskatchewan Accelerator Laboratory **
+ ** University of Saskatchewan **
+ ** 107 North Road **
+ ** Saskatoon, Saskatchewan, CANADA **
+ ** S7N 5C6 **
+ ** **
+ ** eric@skatter.usask.ca **
+ ** **
+ ** $Id$ **
+ ** **
+ **************************************************************************
+ **************************************************************************
+ */
+
+#ifndef __MC68360_h
+#define __MC68360_h
+
+/*
+ *************************************************************************
+ * REGISTER SUBBLOCKS *
+ *************************************************************************
+ */
+
+/*
+ * Memory controller registers
+ */
+typedef struct m360MEMCRegisters_ {
+ unsigned long br;
+ unsigned long or;
+ unsigned long _pad[2];
+} m360MEMCRegisters_t;
+
+/*
+ * Serial Communications Controller registers
+ */
+typedef struct m360SCCRegisters_ {
+ unsigned long gsmr_l;
+ unsigned long gsmr_h;
+ unsigned short psmr;
+ unsigned short _pad0;
+ unsigned short todr;
+ unsigned short dsr;
+ unsigned short scce;
+ unsigned short _pad1;
+ unsigned short sccm;
+ unsigned char _pad2;
+ unsigned char sccs;
+ unsigned long _pad3[2];
+} m360SCCRegisters_t;
+
+/*
+ * Serial Management Controller registers
+ */
+typedef struct m360SMCRegisters_ {
+ unsigned short _pad0;
+ unsigned short smcmr;
+ unsigned short _pad1;
+ unsigned char smce;
+ unsigned char _pad2;
+ unsigned short _pad3;
+ unsigned char smcm;
+ unsigned char _pad4;
+ unsigned long _pad5;
+} m360SMCRegisters_t;
+
+
+/*
+ *************************************************************************
+ * Miscellaneous Parameters *
+ *************************************************************************
+ */
+typedef struct m360MiscParms_ {
+ unsigned short rev_num;
+ unsigned short _res1;
+ unsigned long _res2;
+ unsigned long _res3;
+} m360MiscParms_t;
+
+/*
+ *************************************************************************
+ * RISC Timers *
+ *************************************************************************
+ */
+typedef struct m360TimerParms_ {
+ unsigned short tm_base;
+ unsigned short _tm_ptr;
+ unsigned short _r_tmr;
+ unsigned short _r_tmv;
+ unsigned long tm_cmd;
+ unsigned long tm_cnt;
+} m360TimerParms_t;
+
+/*
+ * RISC Controller Configuration Register (RCCR)
+ * All other bits in this register are either reserved or
+ * used only with a Motorola-supplied RAM microcode packge.
+ */
+#define M360_RCCR_TIME (1<<15) /* Enable timer */
+#define M360_RCCR_TIMEP(x) ((x)<<8) /* Timer period */
+
+/*
+ * Command register
+ * Set up this register before issuing a M360_CR_OP_SET_TIMER command.
+ */
+#define M360_TM_CMD_V (1<<31) /* Set to enable timer */
+#define M360_TM_CMD_R (1<<30) /* Set for automatic restart */
+#define M360_TM_CMD_TIMER(x) ((x)<<16) /* Select timer */
+#define M360_TM_CMD_PERIOD(x) (x) /* Timer period (16 bits) */
+
+/*
+ *************************************************************************
+ * DMA Controllers *
+ *************************************************************************
+ */
+typedef struct m360IDMAparms_ {
+ unsigned short ibase;
+ unsigned short ibptr;
+ unsigned long _istate;
+ unsigned long _itemp;
+} m360IDMAparms_t;
+
+/*
+ *************************************************************************
+ * Serial Communication Controllers *
+ *************************************************************************
+ */
+typedef struct m360SCCparms_ {
+ unsigned short rbase;
+ unsigned short tbase;
+ unsigned char rfcr;
+ unsigned char tfcr;
+ unsigned short mrblr;
+ unsigned long _rstate;
+ unsigned long _pad0;
+ unsigned short _rbptr;
+ unsigned short _pad1;
+ unsigned long _pad2;
+ unsigned long _tstate;
+ unsigned long _pad3;
+ unsigned short _tbptr;
+ unsigned short _pad4;
+ unsigned long _pad5;
+ unsigned long _rcrc;
+ unsigned long _tcrc;
+ union {
+ struct {
+ unsigned long _res0;
+ unsigned long _res1;
+ unsigned short max_idl;
+ unsigned short _idlc;
+ unsigned short brkcr;
+ unsigned short parec;
+ unsigned short frmec;
+ unsigned short nosec;
+ unsigned short brkec;
+ unsigned short brklen;
+ unsigned short uaddr[2];
+ unsigned short _rtemp;
+ unsigned short toseq;
+ unsigned short character[8];
+ unsigned short rccm;
+ unsigned short rccr;
+ unsigned short rlbc;
+ } uart;
+ struct {
+ unsigned long crc_p;
+ unsigned long crc_c;
+ } transparent;
+
+ } un;
+} m360SCCparms_t;
+
+typedef struct m360SCCENparms_ {
+ unsigned short rbase;
+ unsigned short tbase;
+ unsigned char rfcr;
+ unsigned char tfcr;
+ unsigned short mrblr;
+ unsigned long _rstate;
+ unsigned long _pad0;
+ unsigned short _rbptr;
+ unsigned short _pad1;
+ unsigned long _pad2;
+ unsigned long _tstate;
+ unsigned long _pad3;
+ unsigned short _tbptr;
+ unsigned short _pad4;
+ unsigned long _pad5;
+ unsigned long _rcrc;
+ unsigned long _tcrc;
+ union {
+ struct {
+ unsigned long _res0;
+ unsigned long _res1;
+ unsigned short max_idl;
+ unsigned short _idlc;
+ unsigned short brkcr;
+ unsigned short parec;
+ unsigned short frmec;
+ unsigned short nosec;
+ unsigned short brkec;
+ unsigned short brklen;
+ unsigned short uaddr[2];
+ unsigned short _rtemp;
+ unsigned short toseq;
+ unsigned short character[8];
+ unsigned short rccm;
+ unsigned short rccr;
+ unsigned short rlbc;
+ } uart;
+ struct {
+ unsigned long c_pres;
+ unsigned long c_mask;
+ unsigned long crcec;
+ unsigned long alec;
+ unsigned long disfc;
+ unsigned short pads;
+ unsigned short ret_lim;
+ unsigned short _ret_cnt;
+ unsigned short mflr;
+ unsigned short minflr;
+ unsigned short maxd1;
+ unsigned short maxd2;
+ unsigned short _maxd;
+ unsigned short dma_cnt;
+ unsigned short _max_b;
+ unsigned short gaddr1;
+ unsigned short gaddr2;
+ unsigned short gaddr3;
+ unsigned short gaddr4;
+ unsigned long _tbuf0data0;
+ unsigned long _tbuf0data1;
+ unsigned long _tbuf0rba0;
+ unsigned long _tbuf0crc;
+ unsigned short _tbuf0bcnt;
+ unsigned short paddr_h;
+ unsigned short paddr_m;
+ unsigned short paddr_l;
+ unsigned short p_per;
+ unsigned short _rfbd_ptr;
+ unsigned short _tfbd_ptr;
+ unsigned short _tlbd_ptr;
+ unsigned long _tbuf1data0;
+ unsigned long _tbuf1data1;
+ unsigned long _tbuf1rba0;
+ unsigned long _tbuf1crc;
+ unsigned short _tbuf1bcnt;
+ unsigned short _tx_len;
+ unsigned short iaddr1;
+ unsigned short iaddr2;
+ unsigned short iaddr3;
+ unsigned short iaddr4;
+ unsigned short _boff_cnt;
+ unsigned short taddr_h;
+ unsigned short taddr_m;
+ unsigned short taddr_l;
+ } ethernet;
+ struct {
+ unsigned long crc_p;
+ unsigned long crc_c;
+ } transparent;
+ } un;
+} m360SCCENparms_t;
+
+/*
+ * Receive and transmit function code register bits
+ * These apply to the function code registers of all devices, not just SCC.
+ */
+#define M360_RFCR_MOT (1<<4)
+#define M360_RFCR_DMA_SPACE 0x8
+#define M360_TFCR_MOT (1<<4)
+#define M360_TFCR_DMA_SPACE 0x8
+
+/*
+ *************************************************************************
+ * Serial Management Controllers *
+ *************************************************************************
+ */
+typedef struct m360SMCparms_ {
+ unsigned short rbase;
+ unsigned short tbase;
+ unsigned char rfcr;
+ unsigned char tfcr;
+ unsigned short mrblr;
+ unsigned long _rstate;
+ unsigned long _pad0;
+ unsigned short _rbptr;
+ unsigned short _pad1;
+ unsigned long _pad2;
+ unsigned long _tstate;
+ unsigned long _pad3;
+ unsigned short _tbptr;
+ unsigned short _pad4;
+ unsigned long _pad5;
+ union {
+ struct {
+ unsigned short max_idl;
+ unsigned short _pad0;
+ unsigned short brklen;
+ unsigned short brkec;
+ unsigned short brkcr;
+ unsigned short _r_mask;
+ } uart;
+ struct {
+ unsigned short _pad0[5];
+ } transparent;
+ } un;
+} m360SMCparms_t;
+
+/*
+ * Mode register
+ */
+#define M360_SMCMR_CLEN(x) ((x)<<11) /* Character length */
+#define M360_SMCMR_2STOP (1<<10) /* 2 stop bits */
+#define M360_SMCMR_PARITY (1<<9) /* Enable parity */
+#define M360_SMCMR_EVEN (1<<8) /* Even parity */
+#define M360_SMCMR_SM_GCI (0<<4) /* GCI Mode */
+#define M360_SMCMR_SM_UART (2<<4) /* UART Mode */
+#define M360_SMCMR_SM_TRANSPARENT (3<<4) /* Transparent Mode */
+#define M360_SMCMR_DM_LOOPBACK (1<<2) /* Local loopback mode */
+#define M360_SMCMR_DM_ECHO (2<<2) /* Echo mode */
+#define M360_SMCMR_TEN (1<<1) /* Enable transmitter */
+#define M360_SMCMR_REN (1<<0) /* Enable receiver */
+
+/*
+ * Event and mask registers (SMCE, SMCM)
+ */
+#define M360_SMCE_BRK (1<<4)
+#define M360_SMCE_BSY (1<<2)
+#define M360_SMCE_TX (1<<1)
+#define M360_SMCE_RX (1<<0)
+
+/*
+ *************************************************************************
+ * Serial Peripheral Interface *
+ *************************************************************************
+ */
+typedef struct m360SPIparms_ {
+ unsigned short rbase;
+ unsigned short tbase;
+ unsigned char rfcr;
+ unsigned char tfcr;
+ unsigned short mrblr;
+ unsigned long _rstate;
+ unsigned long _pad0;
+ unsigned short _rbptr;
+ unsigned short _pad1;
+ unsigned long _pad2;
+ unsigned long _tstate;
+ unsigned long _pad3;
+ unsigned short _tbptr;
+ unsigned short _pad4;
+ unsigned long _pad5;
+} m360SPIparms_t;
+
+/*
+ * Mode register (SPMODE)
+ */
+#define M360_SPMODE_LOOP (1<<14) /* Local loopback mode */
+#define M360_SPMODE_CI (1<<13) /* Clock invert */
+#define M360_SPMODE_CP (1<<12) /* Clock phase */
+#define M360_SPMODE_DIV16 (1<<11) /* Divide BRGCLK by 16 */
+#define M360_SPMODE_REV (1<<10) /* Reverse data */
+#define M360_SPMODE_MASTER (1<<9) /* SPI is master */
+#define M360_SPMODE_EN (1<<8) /* Enable SPI */
+#define M360_SPMODE_CLEN(x) ((x)<<4) /* Character length */
+#define M360_SPMODE_PM(x) (x) /* Prescaler modulus */
+
+/*
+ * Mode register (SPCOM)
+ */
+#define M360_SPCOM_STR (1<<7) /* Start transmit */
+
+/*
+ * Event and mask registers (SPIE, SPIM)
+ */
+#define M360_SPIE_MME (1<<5) /* Multi-master error */
+#define M360_SPIE_TXE (1<<4) /* Tx error */
+#define M360_SPIE_BSY (1<<2) /* Busy condition*/
+#define M360_SPIE_TXB (1<<1) /* Tx buffer */
+#define M360_SPIE_RXB (1<<0) /* Rx buffer */
+
+/*
+ *************************************************************************
+ * SDMA (SCC, SMC, SPI) Buffer Descriptors *
+ *************************************************************************
+ */
+typedef struct m360BufferDescriptor_ {
+ unsigned short status;
+ unsigned short length;
+ volatile void *buffer;
+} m360BufferDescriptor_t;
+
+/*
+ * Bits in receive buffer descriptor status word
+ */
+#define M360_BD_EMPTY (1<<15) /* Ethernet, SCC UART, SMC UART, SPI */
+#define M360_BD_WRAP (1<<13) /* Ethernet, SCC UART, SMC UART, SPI */
+#define M360_BD_INTERRUPT (1<<12) /* Ethernet, SCC UART, SMC UART, SPI */
+#define M360_BD_LAST (1<<11) /* Ethernet, SPI */
+#define M360_BD_CONTROL_CHAR (1<<11) /* SCC UART */
+#define M360_BD_FIRST_IN_FRAME (1<<10) /* Ethernet */
+#define M360_BD_ADDRESS (1<<10) /* SCC UART */
+#define M360_BD_CONTINUOUS (1<<9) /* SCC UART, SMC UART, SPI */
+#define M360_BD_MISS (1<<8) /* Ethernet */
+#define M360_BD_IDLE (1<<8) /* SCC UART, SMC UART */
+#define M360_BD_ADDRSS_MATCH (1<<7) /* SCC UART */
+#define M360_BD_LONG (1<<5) /* Ethernet */
+#define M360_BD_BREAK (1<<5) /* SCC UART, SMC UART */
+#define M360_BD_NONALIGNED (1<<4) /* Ethernet */
+#define M360_BD_FRAMING_ERROR (1<<4) /* SCC UART, SMC UART */
+#define M360_BD_SHORT (1<<3) /* Ethernet */
+#define M360_BD_PARITY_ERROR (1<<3) /* SCC UART, SMC UART */
+#define M360_BD_CRC_ERROR (1<<2) /* Ethernet */
+#define M360_BD_OVERRUN (1<<1) /* Ethernet, SCC UART, SMC UART, SPI */
+#define M360_BD_COLLISION (1<<0) /* Ethernet */
+#define M360_BD_CARRIER_LOST (1<<0) /* SCC UART */
+#define M360_BD_MASTER_ERROR (1<<0) /* SPI */
+
+/*
+ * Bits in transmit buffer descriptor status word
+ * Many bits have the same meaning as those in receiver buffer descriptors.
+ */
+#define M360_BD_READY (1<<15) /* Ethernet, SCC UART, SMC UART, SPI */
+#define M360_BD_PAD (1<<14) /* Ethernet */
+#define M360_BD_CTS_REPORT (1<<11) /* SCC UART */
+#define M360_BD_TX_CRC (1<<10) /* Ethernet */
+#define M360_BD_DEFER (1<<9) /* Ethernet */
+#define M360_BD_HEARTBEAT (1<<8) /* Ethernet */
+#define M360_BD_PREAMBLE (1<<8) /* SCC UART, SMC UART */
+#define M360_BD_LATE_COLLISION (1<<7) /* Ethernet */
+#define M360_BD_NO_STOP_BIT (1<<7) /* SCC UART */
+#define M360_BD_RETRY_LIMIT (1<<6) /* Ethernet */
+#define M360_BD_RETRY_COUNT(x) (((x)&0x3C)>>2) /* Ethernet */
+#define M360_BD_UNDERRUN (1<<1) /* Ethernet, SPI */
+#define M360_BD_CARRIER_LOST (1<<0) /* Ethernet */
+#define M360_BD_CTS_LOST (1<<0) /* SCC UART */
+
+/*
+ *************************************************************************
+ * IDMA Buffer Descriptors *
+ *************************************************************************
+ */
+typedef struct m360IDMABufferDescriptor_ {
+ unsigned short status;
+ unsigned short _pad;
+ unsigned long length;
+ void *source;
+ void *destination;
+} m360IDMABufferDescriptor_t;
+
+/*
+ *************************************************************************
+ * RISC Communication Processor Module Command Register (CR) *
+ *************************************************************************
+ */
+#define M360_CR_RST (1<<15) /* Reset communication processor */
+#define M360_CR_OP_INIT_RX_TX (0<<8) /* SCC, SMC UART, SMC GCI, SPI */
+#define M360_CR_OP_INIT_RX (1<<8) /* SCC, SMC UART, SPI */
+#define M360_CR_OP_INIT_TX (2<<8) /* SCC, SMC UART, SPI */
+#define M360_CR_OP_INIT_HUNT (3<<8) /* SCC, SMC UART */
+#define M360_CR_OP_STOP_TX (4<<8) /* SCC, SMC UART */
+#define M360_CR_OP_GR_STOP_TX (5<<8) /* SCC */
+#define M360_CR_OP_INIT_IDMA (5<<8) /* IDMA */
+#define M360_CR_OP_RESTART_TX (6<<8) /* SCC, SMC UART */
+#define M360_CR_OP_CLOSE_RX_BD (7<<8) /* SCC, SMC UART, SPI */
+#define M360_CR_OP_SET_GRP_ADDR (8<<8) /* SCC */
+#define M360_CR_OP_SET_TIMER (8<<8) /* Timer */
+#define M360_CR_OP_GCI_TIMEOUT (9<<8) /* SMC GCI */
+#define M360_CR_OP_RESERT_BCS (10<<8) /* SCC */
+#define M360_CR_OP_GCI_ABORT (10<<8) /* SMC GCI */
+#define M360_CR_CHAN_SCC1 (0<<4) /* Channel selection */
+#define M360_CR_CHAN_SCC2 (4<<4)
+#define M360_CR_CHAN_SPI (5<<4)
+#define M360_CR_CHAN_TIMER (5<<4)
+#define M360_CR_CHAN_SCC3 (8<<4)
+#define M360_CR_CHAN_SMC1 (9<<4)
+#define M360_CR_CHAN_IDMA1 (9<<4)
+#define M360_CR_CHAN_SCC4 (12<<4)
+#define M360_CR_CHAN_SMC2 (13<<4)
+#define M360_CR_CHAN_IDMA2 (13<<4)
+#define M360_CR_FLG (1<<0) /* Command flag */
+
+/*
+ *************************************************************************
+ * System Protection Control Register (SYPCR) *
+ *************************************************************************
+ */
+#define M360_SYPCR_SWE (1<<7) /* Software watchdog enable */
+#define M360_SYPCR_SWRI (1<<6) /* Software watchdog reset select */
+#define M360_SYPCR_SWT1 (1<<5) /* Software watchdog timing bit 1 */
+#define M360_SYPCR_SWT0 (1<<4) /* Software watchdog timing bit 0 */
+#define M360_SYPCR_DBFE (1<<3) /* Double bus fault monitor enable */
+#define M360_SYPCR_BME (1<<2) /* Bus monitor external enable */
+#define M360_SYPCR_BMT1 (1<<1) /* Bus monitor timing bit 1 */
+#define M360_SYPCR_BMT0 (1<<0) /* Bus monitor timing bit 0 */
+
+/*
+ *************************************************************************
+ * Memory Control Registers *
+ *************************************************************************
+ */
+#define M360_GMR_RCNT(x) ((x)<<24) /* Refresh count */
+#define M360_GMR_RFEN (1<<23) /* Refresh enable */
+#define M360_GMR_RCYC(x) ((x)<<21) /* Refresh cycle length */
+#define M360_GMR_PGS(x) ((x)<<18) /* Page size */
+#define M360_GMR_DPS_32BIT (0<<16) /* DRAM port size */
+#define M360_GMR_DPS_16BIT (1<<16)
+#define M360_GMR_DPS_8BIT (2<<16)
+#define M360_GMR_DPS_DSACK (3<<16)
+#define M360_GMR_WBT40 (1<<15) /* Wait between 040 transfers */
+#define M360_GMR_WBTQ (1<<14) /* Wait between 360 transfers */
+#define M360_GMR_SYNC (1<<13) /* Synchronous external access */
+#define M360_GMR_EMWS (1<<12) /* External master wait state */
+#define M360_GMR_OPAR (1<<11) /* Odd parity */
+#define M360_GMR_PBEE (1<<10) /* Parity bus error enable */
+#define M360_GMR_TSS40 (1<<9) /* TS* sample for 040 */
+#define M360_GMR_NCS (1<<8) /* No CPU space */
+#define M360_GMR_DWQ (1<<7) /* Delay write for 360 */
+#define M360_GMR_DW40 (1<<6) /* Delay write for 040 */
+#define M360_GMR_GAMX (1<<5) /* Global address mux enable */
+
+#define M360_MEMC_BR_FC(x) ((x)<<7) /* Function code limit */
+#define M360_MEMC_BR_TRLXQ (1<<6) /* Relax timing requirements */
+#define M360_MEMC_BR_BACK40 (1<<5) /* Burst acknowledge to 040 */
+#define M360_MEMC_BR_CSNT40 (1<<4) /* CS* negate timing for 040 */
+#define M360_MEMC_BR_CSNTQ (1<<3) /* CS* negate timing for 360 */
+#define M360_MEMC_BR_PAREN (1<<2) /* Enable parity checking */
+#define M360_MEMC_BR_WP (1<<1) /* Write Protect */
+#define M360_MEMC_BR_V (1<<0) /* Base/Option register are valid */
+
+#define M360_MEMC_OR_TCYC(x) ((x)<<28) /* Cycle length (clocks) */
+#define M360_MEMC_OR_WAITS(x) M360_MEMC_OR_TCYC((x)+1)
+#define M360_MEMC_OR_2KB 0x0FFFF800 /* Address range */
+#define M360_MEMC_OR_4KB 0x0FFFF000
+#define M360_MEMC_OR_8KB 0x0FFFE000
+#define M360_MEMC_OR_16KB 0x0FFFC000
+#define M360_MEMC_OR_32KB 0x0FFF8000
+#define M360_MEMC_OR_64KB 0x0FFF0000
+#define M360_MEMC_OR_128KB 0x0FFE0000
+#define M360_MEMC_OR_256KB 0x0FFC0000
+#define M360_MEMC_OR_512KB 0x0FF80000
+#define M360_MEMC_OR_1MB 0x0FF00000
+#define M360_MEMC_OR_2MB 0x0FE00000
+#define M360_MEMC_OR_4MB 0x0FC00000
+#define M360_MEMC_OR_8MB 0x0F800000
+#define M360_MEMC_OR_16MB 0x0F000000
+#define M360_MEMC_OR_32MB 0x0E000000
+#define M360_MEMC_OR_64MB 0x0C000000
+#define M360_MEMC_OR_128MB 0x08000000
+#define M360_MEMC_OR_256MB 0x00000000
+#define M360_MEMC_OR_FCMC(x) ((x)<<7) /* Function code mask */
+#define M360_MEMC_OR_BCYC(x) ((x)<<5) /* Burst cycle length (clocks) */
+#define M360_MEMC_OR_PGME (1<<3) /* Page mode enable */
+#define M360_MEMC_OR_32BIT (0<<1) /* Port size */
+#define M360_MEMC_OR_16BIT (1<<1)
+#define M360_MEMC_OR_8BIT (2<<1)
+#define M360_MEMC_OR_DSACK (3<<1)
+#define M360_MEMC_OR_DRAM (1<<0) /* Dynamic RAM select */
+
+/*
+ *************************************************************************
+ * SI Mode Register (SIMODE) *
+ *************************************************************************
+ */
+#define M360_SI_SMC2_BITS 0xFFFF0000 /* All SMC2 bits */
+#define M360_SI_SMC2_TDM (1<<31) /* Multiplexed SMC2 */
+#define M360_SI_SMC2_BRG1 (0<<28) /* SMC2 clock souce */
+#define M360_SI_SMC2_BRG2 (1<<28)
+#define M360_SI_SMC2_BRG3 (2<<28)
+#define M360_SI_SMC2_BRG4 (3<<28)
+#define M360_SI_SMC2_CLK5 (0<<28)
+#define M360_SI_SMC2_CLK6 (1<<28)
+#define M360_SI_SMC2_CLK7 (2<<28)
+#define M360_SI_SMC2_CLK8 (3<<28)
+#define M360_SI_SMC1_BITS 0x0000FFFF /* All SMC1 bits */
+#define M360_SI_SMC1_TDM (1<<15) /* Multiplexed SMC1 */
+#define M360_SI_SMC1_BRG1 (0<<12) /* SMC1 clock souce */
+#define M360_SI_SMC1_BRG2 (1<<12)
+#define M360_SI_SMC1_BRG3 (2<<12)
+#define M360_SI_SMC1_BRG4 (3<<12)
+#define M360_SI_SMC1_CLK1 (0<<12)
+#define M360_SI_SMC1_CLK2 (1<<12)
+#define M360_SI_SMC1_CLK3 (2<<12)
+#define M360_SI_SMC1_CLK4 (3<<12)
+
+/*
+ *************************************************************************
+ * SDMA Configuration Register (SDMA) *
+ *************************************************************************
+ */
+#define M360_SDMA_FREEZE (2<<13) /* Freeze on next bus cycle */
+#define M360_SDMA_SISM_7 (7<<8) /* Normal interrupt service mask */
+#define M360_SDMA_SAID_4 (4<<4) /* Normal arbitration ID */
+#define M360_SDMA_INTE (1<<1) /* SBER interrupt enable */
+#define M360_SDMA_INTB (1<<0) /* SBKP interrupt enable */
+
+/*
+ *************************************************************************
+ * Baud (sic) Rate Generators *
+ *************************************************************************
+ */
+#define M360_BRG_RST (1<<17) /* Reset generator */
+#define M360_BRG_EN (1<<16) /* Enable generator */
+#define M360_BRG_EXTC_BRGCLK (0<<14) /* Source is BRGCLK */
+#define M360_BRG_EXTC_CLK2 (1<<14) /* Source is CLK2 pin */
+#define M360_BRG_EXTC_CLK6 (2<<14) /* Source is CLK6 pin */
+#define M360_BRG_ATB (1<<13) /* Autobaud */
+#define M360_BRG_115200 (13<<1) /* Assume 25 MHz clock */
+#define M360_BRG_57600 (26<<1)
+#define M360_BRG_38400 (40<<1)
+#define M360_BRG_19200 (80<<1)
+#define M360_BRG_9600 (162<<1)
+#define M360_BRG_4800 (324<<1)
+#define M360_BRG_2400 (650<<1)
+#define M360_BRG_1200 (1301<<1)
+#define M360_BRG_600 (2603<<1)
+#define M360_BRG_300 ((324<<1) | 1)
+#define M360_BRG_150 ((650<<1) | 1)
+#define M360_BRG_75 ((1301<<1) | 1)
+
+/*
+ *************************************************************************
+ * MC68360 DUAL-PORT RAM AND REGISTERS *
+ *************************************************************************
+ */
+typedef struct m360_ {
+ /*
+ * Dual-port RAM
+ */
+ unsigned char dpram0[0x400]; /* Microcode program */
+ unsigned char dpram1[0x200];
+ unsigned char dpram2[0x100]; /* Microcode scratch */
+ unsigned char dpram3[0x100]; /* Not on REV A or B masks */
+ unsigned char _rsv0[0xC00-0x800];
+ m360SCCENparms_t scc1p;
+ unsigned char _rsv1[0xCB0-0xC00-sizeof(m360SCCENparms_t)];
+ m360MiscParms_t miscp;
+ unsigned char _rsv2[0xD00-0xCB0-sizeof(m360MiscParms_t)];
+ m360SCCparms_t scc2p;
+ unsigned char _rsv3[0xD80-0xD00-sizeof(m360SCCparms_t)];
+ m360SPIparms_t spip;
+ unsigned char _rsv4[0xDB0-0xD80-sizeof(m360SPIparms_t)];
+ m360TimerParms_t tmp;
+ unsigned char _rsv5[0xE00-0xDB0-sizeof(m360TimerParms_t)];
+ m360SCCparms_t scc3p;
+ unsigned char _rsv6[0xE70-0xE00-sizeof(m360SCCparms_t)];
+ m360IDMAparms_t idma1p;
+ unsigned char _rsv7[0xE80-0xE70-sizeof(m360IDMAparms_t)];
+ m360SMCparms_t smc1p;
+ unsigned char _rsv8[0xF00-0xE80-sizeof(m360SMCparms_t)];
+ m360SCCparms_t scc4p;
+ unsigned char _rsv9[0xF70-0xF00-sizeof(m360SCCparms_t)];
+ m360IDMAparms_t idma2p;
+ unsigned char _rsv10[0xF80-0xF70-sizeof(m360IDMAparms_t)];
+ m360SMCparms_t smc2p;
+ unsigned char _rsv11[0x1000-0xF80-sizeof(m360SMCparms_t)];
+
+ /*
+ * SIM Block
+ */
+ unsigned long mcr;
+ unsigned long _pad00;
+ unsigned char avr;
+ unsigned char rsr;
+ unsigned short _pad01;
+ unsigned char clkocr;
+ unsigned char _pad02;
+ unsigned short _pad03;
+ unsigned short pllcr;
+ unsigned short _pad04;
+ unsigned short cdvcr;
+ unsigned short pepar;
+ unsigned long _pad05[2];
+ unsigned short _pad06;
+ unsigned char sypcr;
+ unsigned char swiv;
+ unsigned short _pad07;
+ unsigned short picr;
+ unsigned short _pad08;
+ unsigned short pitr;
+ unsigned short _pad09;
+ unsigned char _pad10;
+ unsigned char swsr;
+ unsigned long bkar;
+ unsigned long bcar;
+ unsigned long _pad11[2];
+
+ /*
+ * MEMC Block
+ */
+ unsigned long gmr;
+ unsigned short mstat;
+ unsigned short _pad12;
+ unsigned long _pad13[2];
+ m360MEMCRegisters_t memc[8];
+ unsigned char _pad14[0xF0-0xD0];
+ unsigned char _pad15[0x100-0xF0];
+ unsigned char _pad16[0x500-0x100];
+
+ /*
+ * IDMA1 Block
+ */
+ unsigned short iccr;
+ unsigned short _pad17;
+ unsigned short cmr1;
+ unsigned short _pad18;
+ unsigned long sapr1;
+ unsigned long dapr1;
+ unsigned long bcr1;
+ unsigned char fcr1;
+ unsigned char _pad19;
+ unsigned char cmar1;
+ unsigned char _pad20;
+ unsigned char csr1;
+ unsigned char _pad21;
+ unsigned short _pad22;
+
+ /*
+ * SDMA Block
+ */
+ unsigned char sdsr;
+ unsigned char _pad23;
+ unsigned short sdcr;
+ unsigned long sdar;
+
+ /*
+ * IDMA2 Block
+ */
+ unsigned short _pad24;
+ unsigned short cmr2;
+ unsigned long sapr2;
+ unsigned long dapr2;
+ unsigned long bcr2;
+ unsigned char fcr2;
+ unsigned char _pad26;
+ unsigned char cmar2;
+ unsigned char _pad27;
+ unsigned char csr2;
+ unsigned char _pad28;
+ unsigned short _pad29;
+ unsigned long _pad30;
+
+ /*
+ * CPIC Block
+ */
+ unsigned long cicr;
+ unsigned long cipr;
+ unsigned long cimr;
+ unsigned long cisr;
+
+ /*
+ * Parallel I/O Block
+ */
+ unsigned short padir;
+ unsigned short papar;
+ unsigned short paodr;
+ unsigned short padat;
+ unsigned long _pad31[2];
+ unsigned short pcdir;
+ unsigned short pcpar;
+ unsigned short pcso;
+ unsigned short pcdat;
+ unsigned short pcint;
+ unsigned short _pad32;
+ unsigned long _pad33[5];
+
+ /*
+ * TIMER Block
+ */
+ unsigned short tgcr;
+ unsigned short _pad34;
+ unsigned long _pad35[3];
+ unsigned short tmr1;
+ unsigned short tmr2;
+ unsigned short trr1;
+ unsigned short trr2;
+ unsigned short tcr1;
+ unsigned short tcr2;
+ unsigned short tcn1;
+ unsigned short tcn2;
+ unsigned short tmr3;
+ unsigned short tmr4;
+ unsigned short trr3;
+ unsigned short trr4;
+ unsigned short tcr3;
+ unsigned short tcr4;
+ unsigned short tcn3;
+ unsigned short tcn4;
+ unsigned short ter1;
+ unsigned short ter2;
+ unsigned short ter3;
+ unsigned short ter4;
+ unsigned long _pad36[2];
+
+ /*
+ * CP Block
+ */
+ unsigned short cr;
+ unsigned short _pad37;
+ unsigned short rccr;
+ unsigned short _pad38;
+ unsigned long _pad39[3];
+ unsigned short _pad40;
+ unsigned short rter;
+ unsigned short _pad41;
+ unsigned short rtmr;
+ unsigned long _pad42[5];
+
+ /*
+ * BRG Block
+ */
+ unsigned long brgc1;
+ unsigned long brgc2;
+ unsigned long brgc3;
+ unsigned long brgc4;
+
+ /*
+ * SCC Block
+ */
+ m360SCCRegisters_t scc1;
+ m360SCCRegisters_t scc2;
+ m360SCCRegisters_t scc3;
+ m360SCCRegisters_t scc4;
+
+ /*
+ * SMC Block
+ */
+ m360SMCRegisters_t smc1;
+ m360SMCRegisters_t smc2;
+
+ /*
+ * SPI Block
+ */
+ unsigned short spmode;
+ unsigned short _pad43[2];
+ unsigned char spie;
+ unsigned char _pad44;
+ unsigned short _pad45;
+ unsigned char spim;
+ unsigned char _pad46[2];
+ unsigned char spcom;
+ unsigned short _pad47[2];
+
+ /*
+ * PIP Block
+ */
+ unsigned short pipc;
+ unsigned short _pad48;
+ unsigned short ptpr;
+ unsigned long pbdir;
+ unsigned long pbpar;
+ unsigned short _pad49;
+ unsigned short pbodr;
+ unsigned long pbdat;
+ unsigned long _pad50[6];
+
+ /*
+ * SI Block
+ */
+ unsigned long simode;
+ unsigned char sigmr;
+ unsigned char _pad51;
+ unsigned char sistr;
+ unsigned char sicmr;
+ unsigned long _pad52;
+ unsigned long sicr;
+ unsigned short _pad53;
+ unsigned short sirp[2];
+ unsigned short _pad54;
+ unsigned long _pad55[2];
+ unsigned char siram[256];
+} m360_t;
+
+extern volatile m360_t m360;
+
+#endif /* __MC68360_h */
diff --git a/cpukit/score/cpu/m68k/qsm.h b/cpukit/score/cpu/m68k/qsm.h
new file mode 100644
index 0000000000..b8593dd54d
--- /dev/null
+++ b/cpukit/score/cpu/m68k/qsm.h
@@ -0,0 +1,204 @@
+/*
+ *-------------------------------------------------------------------
+ *
+ * QSM -- Queued Serial Module
+ *
+ * The QSM contains two serial interfaces: (a) the queued serial
+ * peripheral interface (QSPI) and the serial communication interface
+ * (SCI). The QSPI provides peripheral expansion and/or interprocessor
+ * communication through a full-duplex, synchronous, three-wire bus. A
+ * self contained RAM queue permits serial data transfers without CPU
+ * intervention and automatic continuous sampling. The SCI provides a
+ * standard non-return to zero mark/space format with wakeup functions
+ * to allow the CPU to run uninterrupted until woken
+ *
+ * For more information, refer to Motorola's "Modular Microcontroller
+ * Family Queued Serial Module Reference Manual" (Motorola document
+ * QSMRM/AD).
+ *
+ * This file was created by John S. Gwynne to support Motorola's 68332 MCU.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the following conditions are met:
+ * 1. Redistribution of source code and documentation must retain
+ * the above authorship, this list of conditions and the
+ * following disclaimer.
+ * 2. 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 "AS IS" without warranty of any kind,
+ * either expressed or implied, including, but not limited to, the
+ * implied warranties of merchantability, title and fitness for a
+ * particular purpose.
+ *
+ *------------------------------------------------------------------
+ *
+ * $Id$
+ */
+
+#ifndef _QSM_H_
+#define _QSM_H_
+
+/* SAM-- shift and mask */
+#undef SAM
+#define SAM(a,b,c) ((a << b) & c)
+
+
+/* QSM_CRB (QSM Control Register Block) base address of the QSM
+ control registers */
+#if SIM_MM == 0
+#define QSM_CRB 0x7ffc00
+#else
+#undef SIM_MM
+#define SIM_MM 1
+#define QSM_CRB 0xfffc00
+#endif
+
+
+#define QSMCR (volatile unsigned short int * const)(0x00 + QSM_CRB)
+ /* QSM Configuration Register */
+#define STOP 0x8000 /* Stop Enable */
+#define FRZ 0x6000 /* Freeze Control */
+#define SUPV 0x0080 /* Supervisor/Unrestricted */
+#define IARB 0x000f /* Inerrupt Arbitration */
+
+
+#define QTEST (volatile unsigned short int * const)(0x02 + QSM_CRB)
+ /* QSM Test Register */
+/* Used only for factor testing */
+
+
+#define QILR (volatile unsigned char * const)(0x04 + QSM_CRB)
+ /* QSM Interrupt Level Register */
+#define ILQSPI 0x38 /* Interrupt Level for QSPI */
+#define ILSCI 0x07 /* Interrupt Level for SCI */
+
+
+#define QIVR (volatile unsigned char * const)(0x05 + QSM_CRB)
+ /* QSM Interrupt Vector Register */
+#define INTV 0xff /* Interrupt Vector Number */
+
+
+#define SCCR0 (volatile unsigned short int * const)(0x08 + QSM_CRB)
+ /* SCI Control Register 0 */
+#define SCBR 0x1fff /* SCI Baud Rate */
+
+
+#define SCCR1 (volatile unsigned short int * const)(0x0a + QSM_CRB)
+ /* SCI Control Register 1 */
+#define LOOPS 0x4000 /* Loop Mode */
+#define WOMS 0x2000 /* Wired-OR Mode for SCI Pins */
+#define ILT 0x1000 /* Idle-Line Detect Type */
+#define PT 0x0800 /* Parity Type */
+#define PE 0x0400 /* Parity Enable */
+#define M 0x0200 /* Mode Select */
+#define WAKE 0x0100 /* Wakeup by Address Mark */
+#define TIE 0x0080 /* Transmit Complete Interrupt Enable */
+#define TCIE 0x0040 /* Transmit Complete Interrupt Enable */
+#define RIE 0x0020 /* Receiver Interrupt Enable */
+#define ILIE 0x0010 /* Idle-Line Interrupt Enable */
+#define TE 0x0008 /* Transmitter Enable */
+#define RE 0x0004 /* Receiver Enable */
+#define RWU 0x0002 /* Receiver Wakeup */
+#define SBK 0x0001 /* Send Break */
+
+
+#define SCSR (volatile unsigned short int * const)(0x0c + QSM_CRB)
+ /* SCI Status Register */
+#define TDRE 0x0100 /* Transmit Data Register Empty */
+#define TC 0x0080 /* Transmit Complete */
+#define RDRF 0x0040 /* Receive Data Register Full */
+#define RAF 0x0020 /* Receiver Active */
+#define IDLE 0x0010 /* Idle-Line Detected */
+#define OR 0x0008 /* Overrun Error */
+#define NF 0x0004 /* Noise Error Flag */
+#define FE 0x0002 /* Framing Error */
+#define PF 0x0001 /* Parity Error */
+
+
+#define SCDR (volatile unsigned short int * const)(0x0e + QSM_CRB)
+ /* SCI Data Register */
+
+
+#define PORTQS (volatile unsigned char * const)(0x15 + QSM_CRB)
+ /* Port QS Data Register */
+
+#define PQSPAR (volatile unsigned char * const)(0x16 + QSM_CRB)
+ /* PORT QS Pin Assignment Rgister */
+/* Any bit cleared (zero) defines the corresponding pin to be an I/O
+ pin. Any bit set defines the corresponding pin to be a QSPI
+ signal. */
+/* note: PQS2 is a digital I/O pin unless the SPI is enabled in which
+ case it becomes the SPI serial clock SCK. */
+/* note: PQS7 is a digital I/O pin unless the SCI transmitter is
+ enabled in which case it becomes the SCI serial output TxD. */
+#define QSMFun 0x0
+#define QSMDis 0x1
+/*
+ * PQSPAR Field | QSM Function | Discrete I/O pin
+ *------------------+--------------+------------------ */
+#define PQSPA0 0 /* MISO | PQS0 */
+#define PQSPA1 1 /* MOSI | PQS1 */
+#define PQSPA2 2 /* SCK | PQS2 (see note)*/
+#define PQSPA3 3 /* PCSO/!SS | PQS3 */
+#define PQSPA4 4 /* PCS1 | PQS4 */
+#define PQSPA5 5 /* PCS2 | PQS5 */
+#define PQSPA6 6 /* PCS3 | PQS6 */
+#define PQSPA7 7 /* TxD | PQS7 (see note)*/
+
+
+#define DDRQS (volatile unsigned char * const)(0x17 + QSM_CRB)
+ /* PORT QS Data Direction Register */
+/* Clearing a bit makes the corresponding pin an input; setting a bit
+ makes the pin an output. */
+
+
+#define SPCR0 (volatile unsigned short int * const)(0x18 + QSM_CRB)
+ /* QSPI Control Register 0 */
+#define MSTR 0x8000 /* Master/Slave Mode Select */
+#define WOMQ 0x4000 /* Wired-OR Mode for QSPI Pins */
+#define BITS 0x3c00 /* Bits Per Transfer */
+#define CPOL 0x0200 /* Clock Polarity */
+#define CPHA 0x0100 /* Clock Phase */
+#define SPBR 0x00ff /* Serial Clock Baud Rate */
+
+
+#define SPCR1 (volatile unsigned short int * const)(0x1a + QSM_CRB)
+ /* QSPI Control Register 1 */
+#define SPE 0x8000 /* QSPI Enable */
+#define DSCKL 0x7f00 /* Delay before SCK */
+#define DTL 0x00ff /* Length of Delay after Transfer */
+
+
+#define SPCR2 (volatile unsigned short int * const)(0x1c + QSM_CRB)
+ /* QSPI Control Register 2 */
+#define SPIFIE 0x8000 /* SPI Finished Interrupt Enable */
+#define WREN 0x4000 /* Wrap Enable */
+#define WRTO 0x2000 /* Wrap To */
+#define ENDQP 0x0f00 /* Ending Queue Pointer */
+#define NEWQP 0x000f /* New Queue Pointer Value */
+
+
+#define SPCR3 (volatile unsigned char * const)(0x1e + QSM_CRB)
+ /* QSPI Control Register 3 */
+#define LOOPQ 0x0400 /* QSPI Loop Mode */
+#define HMIE 0x0200 /* HALTA and MODF Interrupt Enable */
+#define HALT 0x0100 /* Halt */
+
+
+#define SPSR (volatile unsigned char * const)(0x1f + QSM_CRB)
+ /* QSPI Status Register */
+#define SPIF 0x0080 /* QSPI Finished Flag */
+#define MODF 0x0040 /* Mode Fault Flag */
+#define HALTA 0x0020 /* Halt Acknowlwdge Flag */
+#define CPTQP x0000f /* Completed Queue Pointer */
+
+#define QSPIRR (volatile unsigned char * const)(0x100 + QSM_CRB)
+ /* QSPI Receive Data RAM */
+#define QSPITR (volatile unsigned char * const)(0x120 + QSM_CRB)
+ /* QSPI Transmit Data RAM */
+#define QSPIcR (volatile unsigned char * const)(0x140 + QSM_CRB)
+ /* QSPI Command RAM */
+
+#endif /* _QSM_H_ */
diff --git a/cpukit/score/cpu/m68k/rtems/asm.h b/cpukit/score/cpu/m68k/rtems/asm.h
new file mode 100644
index 0000000000..d35b3595fa
--- /dev/null
+++ b/cpukit/score/cpu/m68k/rtems/asm.h
@@ -0,0 +1,145 @@
+/* asm.h
+ *
+ * This include file attempts to address the problems
+ * caused by incompatible flavors of assemblers and
+ * toolsets. It primarily addresses variations in the
+ * use of leading underscores on symbols and the requirement
+ * that register names be preceded by a %.
+ *
+ *
+ * NOTE: The spacing in the use of these macros
+ * is critical to them working as advertised.
+ *
+ * COPYRIGHT:
+ *
+ * This file is based on similar code found in newlib available
+ * from ftp.cygnus.com. The file which was used had no copyright
+ * notice. This file is freely distributable as long as the source
+ * of the file is noted. This file is:
+ *
+ * COPYRIGHT (c) 1994-1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * $Id$
+ */
+
+#ifndef __M68k_ASM_h
+#define __M68k_ASM_h
+
+/*
+ * Indicate we are in an assembly file and get the basic CPU definitions.
+ */
+
+#ifndef ASM
+#define ASM
+#endif
+#include <rtems/score/cpuopts.h>
+#include <rtems/score/cpu.h>
+
+/*
+ * Recent versions of GNU cpp define variables which indicate the
+ * need for underscores and percents. If not using GNU cpp or
+ * the version does not support this, then you will obviously
+ * have to define these as appropriate.
+ */
+
+#ifndef __USER_LABEL_PREFIX__
+#define __USER_LABEL_PREFIX__ _
+#endif
+
+#ifndef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__
+#endif
+
+/* ANSI concatenation macros. */
+
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+#define EVAL(x) x
+#define CONCAT0(a, b) EVAL(a)EVAL(b)
+
+/* Use the right prefix for global labels. */
+
+#define SYM(x) CONCAT0 (__USER_LABEL_PREFIX__, x)
+
+/* Use the right prefix for registers. */
+
+#define REG(x) CONCAT0 (__REGISTER_PREFIX__, x)
+
+#define d0 REG (d0)
+#define d1 REG (d1)
+#define d2 REG (d2)
+#define d3 REG (d3)
+#define d4 REG (d4)
+#define d5 REG (d5)
+#define d6 REG (d6)
+#define d7 REG (d7)
+#define a0 REG (a0)
+#define a1 REG (a1)
+#define a2 REG (a2)
+#define a3 REG (a3)
+#define a4 REG (a4)
+#define a5 REG (a5)
+#define a6 REG (a6)
+#define a7 REG (a7)
+#define sp REG (sp)
+
+#define msp REG (msp)
+#define usp REG (usp)
+#define isp REG (isp)
+#define sr REG (sr)
+#define vbr REG (vbr)
+#define dfc REG (dfc)
+#define sfc REG (sfc)
+
+/* mcf52xx special regs */
+#define cacr REG (cacr)
+#define acr0 REG (acr0)
+#define acr1 REG (acr1)
+#define rambar0 REG (rambar0)
+#define mbar REG (mbar)
+
+
+#define fp0 REG (fp0)
+#define fp1 REG (fp1)
+#define fp2 REG (fp2)
+#define fp3 REG (fp3)
+#define fp4 REG (fp4)
+#define fp5 REG (fp5)
+#define fp6 REG (fp6)
+#define fp7 REG (fp7)
+
+#define fpc REG (fpc)
+#define fpi REG (fpi)
+#define fps REG (fps)
+#define fpsr REG (fpsr)
+
+
+/*
+ * Define macros to handle section beginning and ends.
+ */
+
+
+#define BEGIN_CODE_DCL .text
+#define END_CODE_DCL
+#define BEGIN_DATA_DCL .data
+#define END_DATA_DCL
+#define BEGIN_CODE .text
+#define END_CODE
+#define BEGIN_DATA .data
+#define END_DATA
+#define BEGIN_BSS .bss
+#define END_BSS
+#define END
+
+/*
+ * Following must be tailor for a particular flavor of the C compiler.
+ * They may need to put underscores in front of the symbols.
+ */
+
+#define PUBLIC(sym) .globl SYM (sym)
+#define EXTERN(sym) .globl SYM (sym)
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/m68k/rtems/m68k/m68302.h b/cpukit/score/cpu/m68k/rtems/m68k/m68302.h
new file mode 100644
index 0000000000..0ee052b8b3
--- /dev/null
+++ b/cpukit/score/cpu/m68k/rtems/m68k/m68302.h
@@ -0,0 +1,661 @@
+/*
+ *------------------------------------------------------------------
+ *
+ * m68302.h - Definitions for Motorola MC68302 processor.
+ *
+ * Section references in this file refer to revision 2 of Motorola's
+ * "MC68302 Integrated Multiprotocol Processor User's Manual".
+ * (Motorola document MC68302UM/AD REV 2.)
+ *
+ * Based on Don Meyer's cpu68302.h that was posted in comp.sys.m68k
+ * on 17 February, 1993.
+ *
+ * Copyright 1995 David W. Glessner.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the following conditions are met:
+ * 1. Redistribution of source code and documentation must retain
+ * the above copyright notice, this list of conditions and the
+ * following disclaimer.
+ * 2. 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 "AS IS" without warranty of any kind,
+ * either expressed or implied, including, but not limited to, the
+ * implied warranties of merchantability, title and fitness for a
+ * particular purpose.
+ *
+ *
+ * $Id$
+ *
+ *------------------------------------------------------------------
+ */
+
+#ifndef __MOTOROLA_MC68302_DEFINITIONS_h
+#define __MOTOROLA_MC68302_DEFINITIONS_h
+
+/*
+ * BAR - Base Address Register
+ * Section 2.7
+ */
+#define M302_BAR (*((volatile uint16_t *) 0xf2))
+
+/*
+ * SCR - System Control Register
+ * Section 3.8.1
+ */
+#define M302_SCR (*((volatile uint32_t *) 0xf4))
+/*
+ * SCR bits
+ */
+#define RBIT_SCR_IPA 0x08000000
+#define RBIT_SCR_HWT 0x04000000
+#define RBIT_SCR_WPV 0x02000000
+#define RBIT_SCR_ADC 0x01000000
+
+#define RBIT_SCR_ERRE 0x00400000
+#define RBIT_SCR_VGE 0x00200000
+#define RBIT_SCR_WPVE 0x00100000
+#define RBIT_SCR_RMCST 0x00080000
+#define RBIT_SCR_EMWS 0x00040000
+#define RBIT_SCR_ADCE 0x00020000
+#define RBIT_SCR_BCLM 0x00010000
+
+#define RBIT_SCR_FRZW 0x00008000
+#define RBIT_SCR_FRZ2 0x00004000
+#define RBIT_SCR_FRZ1 0x00002000
+#define RBIT_SCR_SAM 0x00001000
+#define RBIT_SCR_HWDEN 0x00000800
+#define RBIT_SCR_HWDCN2 0x00000400
+#define RBIT_SCR_HWDCN1 0x00000200 /* 512 clocks */
+#define RBIT_SCR_HWDCN0 0x00000100 /* 128 clocks */
+
+#define RBIT_SCR_LPREC 0x00000080
+#define RBIT_SCR_LPP16 0x00000040
+#define RBIT_SCR_LPEN 0x00000020
+#define RBIT_SCR_LPCLKDIV 0x0000001f
+
+
+/*
+ * 68000 interrupt and trap vector numbers
+ */
+#define M68K_IVEC_BUS_ERROR 2
+#define M68K_IVEC_ADDRESS_ERROR 3
+#define M68K_IVEC_ILLEGAL_OPCODE 4
+#define M68K_IVEC_ZERO_DIVIDE 5
+#define M68K_IVEC_CHK 6
+#define M68K_IVEC_TRAPV 7
+#define M68K_IVEC_PRIVILEGE 8
+#define M68K_IVEC_TRACE 9
+#define M68K_IVEC_LINE_A 10
+#define M68K_IVEC_LINE_F 11
+/* Unassigned, Reserved 12-14 */
+#define M68K_IVEC_UNINITIALIZED_INT 15
+/* Unassigned, Reserved 16-23 */
+#define M68K_IVEC_SPURIOUS_INT 24
+
+#define M68K_IVEC_LEVEL1_AUTOVECTOR 25
+#define M68K_IVEC_LEVEL2_AUTOVECTOR 26
+#define M68K_IVEC_LEVEL3_AUTOVECTOR 27
+#define M68K_IVEC_LEVEL4_AUTOVECTOR 28
+#define M68K_IVEC_LEVEL5_AUTOVECTOR 29
+#define M68K_IVEC_LEVEL6_AUTOVECTOR 30
+#define M68K_IVEC_LEVEL7_AUTOVECTOR 31
+
+#define M68K_IVEC_TRAP0 32
+#define M68K_IVEC_TRAP1 33
+#define M68K_IVEC_TRAP2 34
+#define M68K_IVEC_TRAP3 35
+#define M68K_IVEC_TRAP4 36
+#define M68K_IVEC_TRAP5 37
+#define M68K_IVEC_TRAP6 38
+#define M68K_IVEC_TRAP7 39
+#define M68K_IVEC_TRAP8 40
+#define M68K_IVEC_TRAP9 41
+#define M68K_IVEC_TRAP10 42
+#define M68K_IVEC_TRAP11 43
+#define M68K_IVEC_TRAP12 44
+#define M68K_IVEC_TRAP13 45
+#define M68K_IVEC_TRAP14 46
+#define M68K_IVEC_TRAP15 47
+/*
+ * Unassigned, Reserved 48-59
+ *
+ * Note: Vectors 60-63 are used by the MC68302 (e.g. BAR, SCR).
+ */
+
+/*
+ * MC68302 Interrupt Vectors
+ * Section 3.2
+ */
+enum m68302_ivec_e {
+ M302_IVEC_ERR =0,
+ M302_IVEC_PB8 =1, /* General-Purpose Interrupt 0 */
+ M302_IVEC_SMC2 =2,
+ M302_IVEC_SMC1 =3,
+ M302_IVEC_TIMER3 =4,
+ M302_IVEC_SCP =5,
+ M302_IVEC_TIMER2 =6,
+ M302_IVEC_PB9 =7, /* General-Purpose Interrupt 1 */
+ M302_IVEC_SCC3 =8,
+ M302_IVEC_TIMER1 =9,
+ M302_IVEC_SCC2 =10,
+ M302_IVEC_IDMA =11,
+ M302_IVEC_SDMA =12, /* SDMA Channels Bus Error */
+ M302_IVEC_SCC1 =13,
+ M302_IVEC_PB10 =14, /* General-Purpose Interrupt 2 */
+ M302_IVEC_PB11 =15, /* General-Purpose Interrupt 3 */
+ M302_IVEC_IRQ1 =17, /* External Device */
+ M302_IVEC_IRQ6 =22, /* External Device */
+ M302_IVEC_IRQ7 =23 /* External Device */
+};
+
+
+/*
+ * GIMR - Global Interrupt Mode Register
+ * Section 3.2.5.1
+ */
+#define RBIT_GIMR_MOD (1<<15)
+#define RBIT_GIMR_IV7 (1<<14)
+#define RBIT_GIMR_IV6 (1<<13)
+#define RBIT_GIMR_IV1 (1<<12)
+#define RBIT_GIMR_ET7 (1<<10)
+#define RBIT_GIMR_ET6 (1<<9)
+#define RBIT_GIMR_ET1 (1<<8)
+#define RBIT_GIMR_VECTOR (7<<5)
+
+/*
+ * IPR - Interrupt Pending Register (Section 3.2.5.2)
+ * IMR - Interrupt Mask Register (Section 3.2.5.3)
+ * ISR - Interrupt In-Service Register (Section 3.2.5.4)
+ */
+#define RBIT_IPR_PB11 (1<<15)
+#define RBIT_IPR_PB10 (1<<14)
+#define RBIT_IPR_SCC1 (1<<13)
+#define RBIT_IPR_SDMA (1<<12)
+#define RBIT_IPR_IDMA (1<<11)
+#define RBIT_IPR_SCC2 (1<<10)
+#define RBIT_IPR_TIMER1 (1<<9)
+#define RBIT_IPR_SCC3 (1<<8)
+#define RBIT_IPR_PB9 (1<<7)
+#define RBIT_IPR_TIMER2 (1<<6)
+#define RBIT_IPR_SCP (1<<5)
+#define RBIT_IPR_TIMER3 (1<<4)
+#define RBIT_IPR_SMC1 (1<<3)
+#define RBIT_IPR_SMC2 (1<<2)
+#define RBIT_IPR_PB8 (1<<1)
+#define RBIT_IPR_ERR (1<<0)
+
+#define RBIT_ISR_PB11 (1<<15)
+#define RBIT_ISR_PB10 (1<<14)
+#define RBIT_ISR_SCC1 (1<<13)
+#define RBIT_ISR_SDMA (1<<12)
+#define RBIT_ISR_IDMA (1<<11)
+#define RBIT_ISR_SCC2 (1<<10)
+#define RBIT_ISR_TIMER1 (1<<9)
+#define RBIT_ISR_SCC3 (1<<8)
+#define RBIT_ISR_PB9 (1<<7)
+#define RBIT_ISR_TIMER2 (1<<6)
+#define RBIT_ISR_SCP (1<<5)
+#define RBIT_ISR_TIMER3 (1<<4)
+#define RBIT_ISR_SMC1 (1<<3)
+#define RBIT_ISR_SMC2 (1<<2)
+#define RBIT_ISR_PB8 (1<<1)
+
+#define RBIT_IMR_PB11 (1<<15) /* PB11 Interrupt Mask */
+#define RBIT_IMR_PB10 (1<<14) /* PB10 Interrupt Mask */
+#define RBIT_IMR_SCC1 (1<<13) /* SCC1 Interrupt Mask */
+#define RBIT_IMR_SDMA (1<<12) /* SDMA Interrupt Mask */
+#define RBIT_IMR_IDMA (1<<11) /* IDMA Interrupt Mask */
+#define RBIT_IMR_SCC2 (1<<10) /* SCC2 Interrupt Mask */
+#define RBIT_IMR_TIMER1 (1<<9) /* TIMER1 Interrupt Mask */
+#define RBIT_IMR_SCC3 (1<<8) /* SCC3 Interrupt Mask */
+#define RBIT_IMR_PB9 (1<<7) /* PB9 Interrupt Mask */
+#define RBIT_IMR_TIMER2 (1<<6) /* TIMER2 Interrupt Mask */
+#define RBIT_IMR_SCP (1<<5) /* SCP Interrupt Mask */
+#define RBIT_IMR_TIMER3 (1<<4) /* TIMER3 Interrupt Mask */
+#define RBIT_IMR_SMC1 (1<<3) /* SMC1 Interrupt Mask */
+#define RBIT_IMR_SMC2 (1<<2) /* SMC2 Interrupt Mask */
+#define RBIT_IMR_PB8 (1<<1) /* PB8 Interrupt Mask */
+
+
+/*
+ * DRAM Refresh
+ * Section 3.9
+ *
+ * The DRAM refresh memory map replaces the SCC2 Tx BD 6 and Tx BD 7
+ * structures in the parameter RAM.
+ *
+ * Access to the DRAM registers can be accomplished by
+ * the following approach:
+ *
+ * volatile m302_DRAM_refresh_t *dram;
+ * dram = (volatile m302_DRAM_refresh_t *) &m302.scc2.bd.tx[6];
+ *
+ * Then simply use pointer references (e.g. dram->count = 3).
+ */
+typedef struct {
+ uint16_t dram_high; /* DRAM high address and FC */
+ uint16_t dram_low; /* DRAM low address */
+ uint16_t increment; /* increment step (bytes/row) */
+ uint16_t count; /* RAM refresh cycle count (#rows) */
+ uint16_t t_ptr_h; /* temporary refresh high addr & FC */
+ uint16_t t_ptr_l; /* temporary refresh low address */
+ uint16_t t_count; /* temporary refresh cycles count */
+ uint16_t res; /* reserved */
+} m302_DRAM_refresh_t;
+
+
+/*
+ * TMR - Timer Mode Register (for timers 1 and 2)
+ * Section 3.5.2.1
+ */
+#define RBIT_TMR_ICLK_STOP (0<<1)
+#define RBIT_TMR_ICLK_MASTER (1<<1)
+#define RBIT_TMR_ICLK_MASTER16 (2<<1)
+#define RBIT_TMR_ICLK_TIN (3<<1)
+
+#define RBIT_TMR_OM (1<<5)
+#define RBIT_TMR_ORI (1<<4)
+#define RBIT_TMR_FRR (1<<3)
+#define RBIT_TMR_RST (1<<0)
+
+
+/*
+ * TER - Timer Event Register (for timers 1 and 2)
+ * Section 3.5.2.5
+ */
+#define RBIT_TER_REF (1<<1) /* Output Reference Event */
+#define RBIT_TER_CAP (1<<0) /* Capture Event */
+
+
+/*
+ * SCC Buffer Descriptors and Buffer Descriptors Table
+ * Section 4.5.5
+ */
+typedef struct m302_SCC_bd {
+ uint16_t status; /* status and control */
+ uint16_t length; /* data length */
+ volatile uint8_t *buffer; /* data buffer pointer */
+} m302_SCC_bd_t;
+
+typedef struct {
+ m302_SCC_bd_t rx[8]; /* receive buffer descriptors */
+ m302_SCC_bd_t tx[8]; /* transmit buffer descriptors */
+} m302_SCC_bd_table_t;
+
+
+/*
+ * SCC Parameter RAM (offset 0x080 from an SCC Base)
+ * Section 4.5.6
+ *
+ * Each SCC parameter RAM area begins at offset 0x80 from each SCC base
+ * area (0x400, 0x500, or 0x600 from the dual-port RAM base).
+ *
+ * Offsets 0x9c-0xbf from each SCC base area compose the protocol-specific
+ * portion of the SCC parameter RAM.
+ */
+typedef struct {
+ uint8_t rfcr; /* Rx Function Code */
+ uint8_t tfcr; /* Tx Function Code */
+ uint16_t mrblr; /* Maximum Rx Buffer Length */
+ uint16_t _rstate; /* Rx Internal State */
+ uint8_t res2;
+ uint8_t rbd; /* Rx Internal Buffer Number */
+ uint32_t _rdptr; /* Rx Internal Data Pointer */
+ uint16_t _rcount; /* Rx Internal Byte Count */
+ uint16_t _rtmp; /* Rx Temp */
+ uint16_t _tstate; /* Tx Internal State */
+ uint8_t res7;
+ uint8_t tbd; /* Tx Internal Buffer Number */
+ uint32_t _tdptr; /* Tx Internal Data Pointer */
+ uint16_t _tcount; /* Tx Internal Byte Count */
+ uint16_t _ttmp; /* Tx Temp */
+} m302_SCC_parameters_t;
+
+/*
+ * UART-Specific SCC Parameter RAM
+ * Section 4.5.11.3
+ */
+typedef struct {
+ uint16_t max_idl; /* Maximum IDLE Characters (rx) */
+ uint16_t idlc; /* Temporary rx IDLE counter */
+ uint16_t brkcr; /* Break Count Register (tx) */
+ uint16_t parec; /* Receive Parity Error Counter */
+ uint16_t frmec; /* Receive Framing Error Counter */
+ uint16_t nosec; /* Receive Noise Counter */
+ uint16_t brkec; /* Receive Break Condition Counter */
+ uint16_t uaddr1; /* UART ADDRESS Character 1 */
+ uint16_t uaddr2; /* UART ADDRESS Character 2 */
+ uint16_t rccr; /* Receive Control Character Register */
+ uint16_t character[8]; /* Control Characters 1 through 8*/
+} m302_SCC_UartSpecific_t;
+/*
+ * This definition allows for the checking of receive buffers
+ * for errors.
+ */
+
+#define RCV_ERR 0x003F
+
+/*
+ * UART receive buffer descriptor bit definitions.
+ * Section 4.5.11.14
+ */
+#define RBIT_UART_CTRL (1<<11) /* buffer contains a control char */
+#define RBIT_UART_ADDR (1<<10) /* first byte contains an address */
+#define RBIT_UART_MATCH (1<<9) /* indicates which addr char matched */
+#define RBIT_UART_IDLE (1<<8) /* buffer closed due to IDLE sequence */
+#define RBIT_UART_BR (1<<5) /* break sequence was received */
+#define RBIT_UART_FR (1<<4) /* framing error was received */
+#define RBIT_UART_PR (1<<3) /* parity error was received */
+#define RBIT_UART_OV (1<<1) /* receiver overrun occurred */
+#define RBIT_UART_CD (1<<0) /* carrier detect lost */
+#define RBIT_UART_STATUS 0x003B /* all status bits */
+
+/*
+ * UART transmit buffer descriptor bit definitions.
+ * Section 4.5.11.15
+ */
+#define RBIT_UART_CR (1<<11) /* clear-to-send report
+ * this results in two idle bits
+ * between back-to-back frames
+ */
+#define RBIT_UART_A (1<<10) /* buffer contains address characters
+ * only valid in multidrop mode (UM0=1)
+ */
+#define RBIT_UART_PREAMBLE (1<<9) /* send preamble before data */
+#define RBIT_UART_CTS_LOST (1<<0) /* CTS lost */
+
+/*
+ * UART event register
+ * Section 4.5.11.16
+ */
+#define M302_UART_EV_CTS (1<<7) /* CTS status changed */
+#define M302_UART_EV_CD (1<<6) /* carrier detect status changed */
+#define M302_UART_EV_IDL (1<<5) /* IDLE sequence status changed */
+#define M302_UART_EV_BRK (1<<4) /* break character was received */
+#define M302_UART_EV_CCR (1<<3) /* control character received */
+#define M302_UART_EV_TX (1<<1) /* buffer has been transmitted */
+#define M302_UART_EV_RX (1<<0) /* buffer has been received */
+
+
+/*
+ * HDLC-Specific SCC Parameter RAM
+ * Section 4.5.12.3
+ *
+ * c_mask_l should be 0xF0B8 for 16-bit CRC, 0xdebb for 32-bit CRC
+ * c_mask_h is a don't care for 16-bit CRC, 0x20E2 for 32-bit CRC
+ */
+typedef struct {
+ uint16_t rcrc_l; /* Temp Receive CRC Low */
+ uint16_t rcrc_h; /* Temp Receive CRC High */
+ uint16_t c_mask_l; /* CRC Mask Low */
+ uint16_t c_mask_h; /* CRC Mask High */
+ uint16_t tcrc_l; /* Temp Transmit CRC Low */
+ uint16_t tcrc_h; /* Temp Transmit CRC High */
+
+ uint16_t disfc; /* Discard Frame Counter */
+ uint16_t crcec; /* CRC Error Counter */
+ uint16_t abtsc; /* Abort Sequence Counter */
+ uint16_t nmarc; /* Nonmatching Address Received Cntr */
+ uint16_t retrc; /* Frame Retransmission Counter */
+
+ uint16_t mflr; /* Maximum Frame Length Register */
+ uint16_t max_cnt; /* Maximum_Length Counter */
+
+ uint16_t hmask; /* User Defined Frame Address Mask */
+ uint16_t haddr1; /* User Defined Frame Address */
+ uint16_t haddr2; /* " */
+ uint16_t haddr3; /* " */
+ uint16_t haddr4; /* " */
+} m302_SCC_HdlcSpecific_t;
+/*
+ * HDLC receiver buffer descriptor bit definitions
+ * Section 4.5.12.10
+ */
+#define RBIT_HDLC_EMPTY_BIT 0x8000 /* buffer associated with BD is empty */
+#define RBIT_HDLC_LAST_BIT 0x0800 /* buffer is last in a frame */
+#define RBIT_HDLC_FIRST_BIT 0x0400 /* buffer is first in a frame */
+#define RBIT_HDLC_FRAME_LEN 0x0020 /* receiver frame length violation */
+#define RBIT_HDLC_NONOCT_Rx 0x0010 /* received non-octet aligned frame */
+#define RBIT_HDLC_ABORT_SEQ 0x0008 /* received abort sequence */
+#define RBIT_HDLC_CRC_ERROR 0x0004 /* frame contains a CRC error */
+#define RBIT_HDLC_OVERRUN 0x0002 /* receiver overrun occurred */
+#define RBIT_HDLC_CD_LOST 0x0001 /* carrier detect lost */
+
+/*
+ * HDLC transmit buffer descriptor bit definitions
+ * Section 4.5.12.11
+ */
+#define RBIT_HDLC_READY_BIT 0x8000 /* buffer is ready to transmit */
+#define RBIT_HDLC_EXT_BUFFER 0x4000 /* buffer is in external memory */
+#define RBIT_HDLC_WRAP_BIT 0x2000 /* last buffer in bd table, so wrap */
+#define RBIT_HDLC_WAKE_UP 0x1000 /* interrupt when buffer serviced */
+#define RBIT_HDLC_LAST_BIT 0x0800 /* buffer is last in the frame */
+#define RBIT_HDLC_TxCRC_BIT 0x0400 /* transmit a CRC sequence */
+#define RBIT_HDLC_UNDERRUN 0x0002 /* transmitter underrun */
+#define RBIT_HDLC_CTS_LOST 0x0001 /* CTS lost */
+
+/*
+ * HDLC event register bit definitions
+ * Section 4.5.12.12
+ */
+#define RBIT_HDLC_CTS 0x80 /* CTS status changed */
+#define RBIT_HDLC_CD 0x40 /* carrier detect status changed */
+#define RBIT_HDLC_IDL 0x20 /* IDLE sequence status changed */
+#define RBIT_HDLC_TXE 0x10 /* transmit error */
+#define RBIT_HDLC_RXF 0x08 /* received frame */
+#define RBIT_HDLC_BSY 0x04 /* frame rcvd and discarded due to
+ * lack of buffers
+ */
+#define RBIT_HDLC_TXB 0x02 /* buffer has been transmitted */
+#define RBIT_HDLC_RXB 0x01 /* received buffer */
+
+
+
+typedef struct {
+ m302_SCC_bd_table_t bd; /* +000 Buffer Descriptor Table */
+ m302_SCC_parameters_t parm; /* +080 Common Parameter RAM */
+ union { /* +09C Protocol-Specific Parm RAM */
+ m302_SCC_UartSpecific_t uart;
+ m302_SCC_HdlcSpecific_t hdlc;
+ } prot;
+ uint8_t res[0x040]; /* +0C0 reserved, (not implemented) */
+} m302_SCC_t;
+
+
+/*
+ * Common SCC Registers
+ */
+typedef struct {
+ uint16_t res1;
+ uint16_t scon; /* SCC Configuration Register 4.5.2 */
+ uint16_t scm; /* SCC Mode Register 4.5.3 */
+ uint16_t dsr; /* SCC Data Synchronization Register 4.5.4 */
+ uint8_t scce; /* SCC Event Register 4.5.8.1 */
+ uint8_t res2;
+ uint8_t sccm; /* SCC Mask Register 4.5.8.2 */
+ uint8_t res3;
+ uint8_t sccs; /* SCC Status Register 4.5.8.3 */
+ uint8_t res4;
+ uint16_t res5;
+} m302_SCC_Registers_t;
+
+/*
+ * SCON - SCC Configuration Register
+ * Section 4.5.2
+ */
+#define RBIT_SCON_WOMS (1<<15) /* Wired-OR Mode Select (NMSI mode only)
+ * When set, the TXD driver is an
+ * open-drain output */
+#define RBIT_SCON_EXTC (1<<14) /* External Clock Source */
+#define RBIT_SCON_TCS (1<<13) /* Transmit Clock Source */
+#define RBIT_SCON_RCS (1<<12) /* Receive Clock Source */
+
+/*
+ * SCM - SCC Mode Register bit definitions
+ * Section 4.5.3
+ * The parameter-specific mode bits occupy bits 15 through 6.
+ */
+#define RBIT_SCM_ENR (1<<3) /* Enable receiver */
+#define RBIT_SCM_ENT (1<<2) /* Enable transmitter */
+
+
+/*
+ * Internal MC68302 Registers
+ * starts at offset 0x800 from dual-port RAM base
+ * Section 2.8
+ */
+typedef struct {
+ /* offset +800 */
+ uint16_t res0;
+ uint16_t cmr; /* IDMA Channel Mode Register */
+ uint32_t sapr; /* IDMA Source Address Pointer */
+ uint32_t dapr; /* IDMA Destination Address Pointer */
+ uint16_t bcr; /* IDMA Byte Count Register */
+ uint8_t csr; /* IDMA Channel Status Register */
+ uint8_t res1;
+ uint8_t fcr; /* IDMA Function Code Register */
+ uint8_t res2;
+
+ /* offset +812 */
+ uint16_t gimr; /* Global Interrupt Mode Register */
+ uint16_t ipr; /* Interrupt Pending Register */
+ uint16_t imr; /* Interrupt Mask Register */
+ uint16_t isr; /* Interrupt In-Service Register */
+ uint16_t res3;
+ uint16_t res4;
+
+ /* offset +81e */
+ uint16_t pacnt; /* Port A Control Register */
+ uint16_t paddr; /* Port A Data Direction Register */
+ uint16_t padat; /* Port A Data Register */
+ uint16_t pbcnt; /* Port B Control Register */
+ uint16_t pbddr; /* Port B Data Direction Register */
+ uint16_t pbdat; /* Port B Data Register */
+ uint16_t res5;
+
+ /* offset +82c */
+ uint16_t res6;
+ uint16_t res7;
+
+ uint16_t br0; /* Base Register (CS0) */
+ uint16_t or0; /* Option Register (CS0) */
+ uint16_t br1; /* Base Register (CS1) */
+ uint16_t or1; /* Option Register (CS1) */
+ uint16_t br2; /* Base Register (CS2) */
+ uint16_t or2; /* Option Register (CS2) */
+ uint16_t br3; /* Base Register (CS3) */
+ uint16_t or3; /* Option Register (CS3) */
+
+ /* offset +840 */
+ uint16_t tmr1; /* Timer Unit 1 Mode Register */
+ uint16_t trr1; /* Timer Unit 1 Reference Register */
+ uint16_t tcr1; /* Timer Unit 1 Capture Register */
+ uint16_t tcn1; /* Timer Unit 1 Counter */
+ uint8_t res8;
+ uint8_t ter1; /* Timer Unit 1 Event Register */
+ uint16_t wrr; /* Watchdog Reference Register */
+ uint16_t wcn; /* Watchdog Counter */
+ uint16_t res9;
+ uint16_t tmr2; /* Timer Unit 2 Mode Register */
+ uint16_t trr2; /* Timer Unit 2 Reference Register */
+ uint16_t tcr2; /* Timer Unit 2 Capture Register */
+ uint16_t tcn2; /* Timer Unit 2 Counter */
+ uint8_t resa;
+ uint8_t ter2; /* Timer Unit 2 Event Register */
+ uint16_t resb;
+ uint16_t resc;
+ uint16_t resd;
+
+ /* offset +860 */
+ uint8_t cr; /* Command Register */
+ uint8_t rese[0x1f];
+
+ /* offset +880, +890, +8a0 */
+ m302_SCC_Registers_t scc[3]; /* SCC1, SCC2, SCC3 Registers */
+
+ /* offset +8b0 */
+ uint16_t spmode; /* SCP,SMC Mode and Clock Cntrl Reg */
+ uint16_t simask; /* Serial Interface Mask Register */
+ uint16_t simode; /* Serial Interface Mode Register */
+} m302_internalReg_t ;
+
+
+/*
+ * MC68302 dual-port RAM structure.
+ * (Includes System RAM, Parameter RAM, and Internal Registers).
+ * Section 2.8
+ */
+typedef struct {
+ uint8_t mem[0x240]; /* +000 User Data Memory */
+ uint8_t res1[0x1c0]; /* +240 reserved, (not implemented) */
+ m302_SCC_t scc1; /* +400 SCC1 */
+ m302_SCC_t scc2; /* +500 SCC2 */
+ m302_SCC_t scc3; /* +600 SCC3 */
+ uint8_t res2[0x100]; /* +700 reserved, (not implemented) */
+ m302_internalReg_t reg; /* +800 68302 Internal Registers */
+} m302_dualPortRAM_t;
+
+/* some useful defines the some of the registers above */
+
+
+/* ----
+ MC68302 Chip Select Registers
+ p3-46 2nd Edition
+
+ */
+#define BR_ENABLED 1
+#define BR_DISABLED 0
+#define BR_FC_NULL 0
+#define BR_READ_ONLY 0
+#define BR_READ_WRITE 2
+#define OR_DTACK_0 0x0000
+#define OR_DTACK_1 0x2000
+#define OR_DTACK_2 0x4000
+#define OR_DTACK_3 0x6000
+#define OR_DTACK_4 0x8000
+#define OR_DTACK_5 0xA000
+#define OR_DTACK_6 0xC000
+#define OR_DTACK_EXT 0xE000
+#define OR_SIZE_64K 0x1FE0
+#define OR_SIZE_128K 0x1FC0
+#define OR_SIZE_256K 0x1F80
+#define OR_SIZE_512K 0x1F00
+#define OR_SIZE_1M 0x1E00
+#define OR_SIZE_2M 0x1C00
+#define OR_MASK_RW 0x0000
+#define OR_NO_MASK_RW 0x0002
+#define OR_MASK_FC 0x0000
+#define OR_NO_MASK_FC 0x0001
+
+#define MAKE_BR(base_address, enable, rw, fc) \
+ ((base_address >> 11) | fc | rw | enable)
+
+#define MAKE_OR(bsize, DtAck, RW_Mask, FC_Mask) \
+ (DtAck | ((~(bsize - 1) & 0x00FFFFFF) >> 11) | FC_Mask | RW_Mask)
+
+#define __REG_CAT(r, n) r ## n
+#define WRITE_BR(csel, base_address, enable, rw, fc) \
+ __REG_CAT(m302.reg.br, csel) = MAKE_BR(base_address, enable, rw, fc)
+#define WRITE_OR(csel, bsize, DtAck, RW_Mask, FC_Mask) \
+ __REG_CAT(m302.reg.or, csel) = MAKE_OR(bsize, DtAck, RW_Mask, FC_Mask)
+
+/* ----
+ MC68302 Watchdog Timer Enable Bit
+
+ */
+#define WATCHDOG_ENABLE (1)
+#define WATCHDOG_TRIGGER() (m302.reg.wrr = 0x10 | WATCHDOG_ENABLE, m302.reg.wcn = 0)
+#define WATCHDOG_TOGGLE() (m302.reg.wcn = WATCHDOG_TIMEOUT_PERIOD)
+#define DISABLE_WATCHDOG() (m302.reg.wrr = 0)
+
+/*
+ * Declare the variable that's used to reference the variables in
+ * the dual-port RAM.
+ */
+extern volatile m302_dualPortRAM_t m302;
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/m68k/rtems/m68k/m68360.h b/cpukit/score/cpu/m68k/rtems/m68k/m68360.h
new file mode 100644
index 0000000000..1bdf0a5995
--- /dev/null
+++ b/cpukit/score/cpu/m68k/rtems/m68k/m68360.h
@@ -0,0 +1,889 @@
+/*
+ **************************************************************************
+ **************************************************************************
+ ** **
+ ** MOTOROLA MC68360 QUAD INTEGRATED COMMUNICATIONS CONTROLLER (QUICC) **
+ ** **
+ ** HARDWARE DECLARATIONS **
+ ** **
+ ** **
+ ** Submitted By: **
+ ** **
+ ** W. Eric Norum **
+ ** Saskatchewan Accelerator Laboratory **
+ ** University of Saskatchewan **
+ ** 107 North Road **
+ ** Saskatoon, Saskatchewan, CANADA **
+ ** S7N 5C6 **
+ ** **
+ ** eric@skatter.usask.ca **
+ ** **
+ ** $Id$ **
+ ** **
+ **************************************************************************
+ **************************************************************************
+ */
+
+#ifndef __MC68360_h
+#define __MC68360_h
+
+/*
+ *************************************************************************
+ * REGISTER SUBBLOCKS *
+ *************************************************************************
+ */
+
+/*
+ * Memory controller registers
+ */
+typedef struct m360MEMCRegisters_ {
+ unsigned long br;
+ unsigned long or;
+ unsigned long _pad[2];
+} m360MEMCRegisters_t;
+
+/*
+ * Serial Communications Controller registers
+ */
+typedef struct m360SCCRegisters_ {
+ unsigned long gsmr_l;
+ unsigned long gsmr_h;
+ unsigned short psmr;
+ unsigned short _pad0;
+ unsigned short todr;
+ unsigned short dsr;
+ unsigned short scce;
+ unsigned short _pad1;
+ unsigned short sccm;
+ unsigned char _pad2;
+ unsigned char sccs;
+ unsigned long _pad3[2];
+} m360SCCRegisters_t;
+
+/*
+ * Serial Management Controller registers
+ */
+typedef struct m360SMCRegisters_ {
+ unsigned short _pad0;
+ unsigned short smcmr;
+ unsigned short _pad1;
+ unsigned char smce;
+ unsigned char _pad2;
+ unsigned short _pad3;
+ unsigned char smcm;
+ unsigned char _pad4;
+ unsigned long _pad5;
+} m360SMCRegisters_t;
+
+
+/*
+ *************************************************************************
+ * Miscellaneous Parameters *
+ *************************************************************************
+ */
+typedef struct m360MiscParms_ {
+ unsigned short rev_num;
+ unsigned short _res1;
+ unsigned long _res2;
+ unsigned long _res3;
+} m360MiscParms_t;
+
+/*
+ *************************************************************************
+ * RISC Timers *
+ *************************************************************************
+ */
+typedef struct m360TimerParms_ {
+ unsigned short tm_base;
+ unsigned short _tm_ptr;
+ unsigned short _r_tmr;
+ unsigned short _r_tmv;
+ unsigned long tm_cmd;
+ unsigned long tm_cnt;
+} m360TimerParms_t;
+
+/*
+ * RISC Controller Configuration Register (RCCR)
+ * All other bits in this register are either reserved or
+ * used only with a Motorola-supplied RAM microcode packge.
+ */
+#define M360_RCCR_TIME (1<<15) /* Enable timer */
+#define M360_RCCR_TIMEP(x) ((x)<<8) /* Timer period */
+
+/*
+ * Command register
+ * Set up this register before issuing a M360_CR_OP_SET_TIMER command.
+ */
+#define M360_TM_CMD_V (1<<31) /* Set to enable timer */
+#define M360_TM_CMD_R (1<<30) /* Set for automatic restart */
+#define M360_TM_CMD_TIMER(x) ((x)<<16) /* Select timer */
+#define M360_TM_CMD_PERIOD(x) (x) /* Timer period (16 bits) */
+
+/*
+ *************************************************************************
+ * DMA Controllers *
+ *************************************************************************
+ */
+typedef struct m360IDMAparms_ {
+ unsigned short ibase;
+ unsigned short ibptr;
+ unsigned long _istate;
+ unsigned long _itemp;
+} m360IDMAparms_t;
+
+/*
+ *************************************************************************
+ * Serial Communication Controllers *
+ *************************************************************************
+ */
+typedef struct m360SCCparms_ {
+ unsigned short rbase;
+ unsigned short tbase;
+ unsigned char rfcr;
+ unsigned char tfcr;
+ unsigned short mrblr;
+ unsigned long _rstate;
+ unsigned long _pad0;
+ unsigned short _rbptr;
+ unsigned short _pad1;
+ unsigned long _pad2;
+ unsigned long _tstate;
+ unsigned long _pad3;
+ unsigned short _tbptr;
+ unsigned short _pad4;
+ unsigned long _pad5;
+ unsigned long _rcrc;
+ unsigned long _tcrc;
+ union {
+ struct {
+ unsigned long _res0;
+ unsigned long _res1;
+ unsigned short max_idl;
+ unsigned short _idlc;
+ unsigned short brkcr;
+ unsigned short parec;
+ unsigned short frmec;
+ unsigned short nosec;
+ unsigned short brkec;
+ unsigned short brklen;
+ unsigned short uaddr[2];
+ unsigned short _rtemp;
+ unsigned short toseq;
+ unsigned short character[8];
+ unsigned short rccm;
+ unsigned short rccr;
+ unsigned short rlbc;
+ } uart;
+ struct {
+ unsigned long crc_p;
+ unsigned long crc_c;
+ } transparent;
+
+ } un;
+} m360SCCparms_t;
+
+typedef struct m360SCCENparms_ {
+ unsigned short rbase;
+ unsigned short tbase;
+ unsigned char rfcr;
+ unsigned char tfcr;
+ unsigned short mrblr;
+ unsigned long _rstate;
+ unsigned long _pad0;
+ unsigned short _rbptr;
+ unsigned short _pad1;
+ unsigned long _pad2;
+ unsigned long _tstate;
+ unsigned long _pad3;
+ unsigned short _tbptr;
+ unsigned short _pad4;
+ unsigned long _pad5;
+ unsigned long _rcrc;
+ unsigned long _tcrc;
+ union {
+ struct {
+ unsigned long _res0;
+ unsigned long _res1;
+ unsigned short max_idl;
+ unsigned short _idlc;
+ unsigned short brkcr;
+ unsigned short parec;
+ unsigned short frmec;
+ unsigned short nosec;
+ unsigned short brkec;
+ unsigned short brklen;
+ unsigned short uaddr[2];
+ unsigned short _rtemp;
+ unsigned short toseq;
+ unsigned short character[8];
+ unsigned short rccm;
+ unsigned short rccr;
+ unsigned short rlbc;
+ } uart;
+ struct {
+ unsigned long c_pres;
+ unsigned long c_mask;
+ unsigned long crcec;
+ unsigned long alec;
+ unsigned long disfc;
+ unsigned short pads;
+ unsigned short ret_lim;
+ unsigned short _ret_cnt;
+ unsigned short mflr;
+ unsigned short minflr;
+ unsigned short maxd1;
+ unsigned short maxd2;
+ unsigned short _maxd;
+ unsigned short dma_cnt;
+ unsigned short _max_b;
+ unsigned short gaddr1;
+ unsigned short gaddr2;
+ unsigned short gaddr3;
+ unsigned short gaddr4;
+ unsigned long _tbuf0data0;
+ unsigned long _tbuf0data1;
+ unsigned long _tbuf0rba0;
+ unsigned long _tbuf0crc;
+ unsigned short _tbuf0bcnt;
+ unsigned short paddr_h;
+ unsigned short paddr_m;
+ unsigned short paddr_l;
+ unsigned short p_per;
+ unsigned short _rfbd_ptr;
+ unsigned short _tfbd_ptr;
+ unsigned short _tlbd_ptr;
+ unsigned long _tbuf1data0;
+ unsigned long _tbuf1data1;
+ unsigned long _tbuf1rba0;
+ unsigned long _tbuf1crc;
+ unsigned short _tbuf1bcnt;
+ unsigned short _tx_len;
+ unsigned short iaddr1;
+ unsigned short iaddr2;
+ unsigned short iaddr3;
+ unsigned short iaddr4;
+ unsigned short _boff_cnt;
+ unsigned short taddr_h;
+ unsigned short taddr_m;
+ unsigned short taddr_l;
+ } ethernet;
+ struct {
+ unsigned long crc_p;
+ unsigned long crc_c;
+ } transparent;
+ } un;
+} m360SCCENparms_t;
+
+/*
+ * Receive and transmit function code register bits
+ * These apply to the function code registers of all devices, not just SCC.
+ */
+#define M360_RFCR_MOT (1<<4)
+#define M360_RFCR_DMA_SPACE 0x8
+#define M360_TFCR_MOT (1<<4)
+#define M360_TFCR_DMA_SPACE 0x8
+
+/*
+ *************************************************************************
+ * Serial Management Controllers *
+ *************************************************************************
+ */
+typedef struct m360SMCparms_ {
+ unsigned short rbase;
+ unsigned short tbase;
+ unsigned char rfcr;
+ unsigned char tfcr;
+ unsigned short mrblr;
+ unsigned long _rstate;
+ unsigned long _pad0;
+ unsigned short _rbptr;
+ unsigned short _pad1;
+ unsigned long _pad2;
+ unsigned long _tstate;
+ unsigned long _pad3;
+ unsigned short _tbptr;
+ unsigned short _pad4;
+ unsigned long _pad5;
+ union {
+ struct {
+ unsigned short max_idl;
+ unsigned short _pad0;
+ unsigned short brklen;
+ unsigned short brkec;
+ unsigned short brkcr;
+ unsigned short _r_mask;
+ } uart;
+ struct {
+ unsigned short _pad0[5];
+ } transparent;
+ } un;
+} m360SMCparms_t;
+
+/*
+ * Mode register
+ */
+#define M360_SMCMR_CLEN(x) ((x)<<11) /* Character length */
+#define M360_SMCMR_2STOP (1<<10) /* 2 stop bits */
+#define M360_SMCMR_PARITY (1<<9) /* Enable parity */
+#define M360_SMCMR_EVEN (1<<8) /* Even parity */
+#define M360_SMCMR_SM_GCI (0<<4) /* GCI Mode */
+#define M360_SMCMR_SM_UART (2<<4) /* UART Mode */
+#define M360_SMCMR_SM_TRANSPARENT (3<<4) /* Transparent Mode */
+#define M360_SMCMR_DM_LOOPBACK (1<<2) /* Local loopback mode */
+#define M360_SMCMR_DM_ECHO (2<<2) /* Echo mode */
+#define M360_SMCMR_TEN (1<<1) /* Enable transmitter */
+#define M360_SMCMR_REN (1<<0) /* Enable receiver */
+
+/*
+ * Event and mask registers (SMCE, SMCM)
+ */
+#define M360_SMCE_BRK (1<<4)
+#define M360_SMCE_BSY (1<<2)
+#define M360_SMCE_TX (1<<1)
+#define M360_SMCE_RX (1<<0)
+
+/*
+ *************************************************************************
+ * Serial Peripheral Interface *
+ *************************************************************************
+ */
+typedef struct m360SPIparms_ {
+ unsigned short rbase;
+ unsigned short tbase;
+ unsigned char rfcr;
+ unsigned char tfcr;
+ unsigned short mrblr;
+ unsigned long _rstate;
+ unsigned long _pad0;
+ unsigned short _rbptr;
+ unsigned short _pad1;
+ unsigned long _pad2;
+ unsigned long _tstate;
+ unsigned long _pad3;
+ unsigned short _tbptr;
+ unsigned short _pad4;
+ unsigned long _pad5;
+} m360SPIparms_t;
+
+/*
+ * Mode register (SPMODE)
+ */
+#define M360_SPMODE_LOOP (1<<14) /* Local loopback mode */
+#define M360_SPMODE_CI (1<<13) /* Clock invert */
+#define M360_SPMODE_CP (1<<12) /* Clock phase */
+#define M360_SPMODE_DIV16 (1<<11) /* Divide BRGCLK by 16 */
+#define M360_SPMODE_REV (1<<10) /* Reverse data */
+#define M360_SPMODE_MASTER (1<<9) /* SPI is master */
+#define M360_SPMODE_EN (1<<8) /* Enable SPI */
+#define M360_SPMODE_CLEN(x) ((x)<<4) /* Character length */
+#define M360_SPMODE_PM(x) (x) /* Prescaler modulus */
+
+/*
+ * Mode register (SPCOM)
+ */
+#define M360_SPCOM_STR (1<<7) /* Start transmit */
+
+/*
+ * Event and mask registers (SPIE, SPIM)
+ */
+#define M360_SPIE_MME (1<<5) /* Multi-master error */
+#define M360_SPIE_TXE (1<<4) /* Tx error */
+#define M360_SPIE_BSY (1<<2) /* Busy condition*/
+#define M360_SPIE_TXB (1<<1) /* Tx buffer */
+#define M360_SPIE_RXB (1<<0) /* Rx buffer */
+
+/*
+ *************************************************************************
+ * SDMA (SCC, SMC, SPI) Buffer Descriptors *
+ *************************************************************************
+ */
+typedef struct m360BufferDescriptor_ {
+ unsigned short status;
+ unsigned short length;
+ volatile void *buffer;
+} m360BufferDescriptor_t;
+
+/*
+ * Bits in receive buffer descriptor status word
+ */
+#define M360_BD_EMPTY (1<<15) /* Ethernet, SCC UART, SMC UART, SPI */
+#define M360_BD_WRAP (1<<13) /* Ethernet, SCC UART, SMC UART, SPI */
+#define M360_BD_INTERRUPT (1<<12) /* Ethernet, SCC UART, SMC UART, SPI */
+#define M360_BD_LAST (1<<11) /* Ethernet, SPI */
+#define M360_BD_CONTROL_CHAR (1<<11) /* SCC UART */
+#define M360_BD_FIRST_IN_FRAME (1<<10) /* Ethernet */
+#define M360_BD_ADDRESS (1<<10) /* SCC UART */
+#define M360_BD_CONTINUOUS (1<<9) /* SCC UART, SMC UART, SPI */
+#define M360_BD_MISS (1<<8) /* Ethernet */
+#define M360_BD_IDLE (1<<8) /* SCC UART, SMC UART */
+#define M360_BD_ADDRSS_MATCH (1<<7) /* SCC UART */
+#define M360_BD_LONG (1<<5) /* Ethernet */
+#define M360_BD_BREAK (1<<5) /* SCC UART, SMC UART */
+#define M360_BD_NONALIGNED (1<<4) /* Ethernet */
+#define M360_BD_FRAMING_ERROR (1<<4) /* SCC UART, SMC UART */
+#define M360_BD_SHORT (1<<3) /* Ethernet */
+#define M360_BD_PARITY_ERROR (1<<3) /* SCC UART, SMC UART */
+#define M360_BD_CRC_ERROR (1<<2) /* Ethernet */
+#define M360_BD_OVERRUN (1<<1) /* Ethernet, SCC UART, SMC UART, SPI */
+#define M360_BD_COLLISION (1<<0) /* Ethernet */
+#define M360_BD_CARRIER_LOST (1<<0) /* SCC UART */
+#define M360_BD_MASTER_ERROR (1<<0) /* SPI */
+
+/*
+ * Bits in transmit buffer descriptor status word
+ * Many bits have the same meaning as those in receiver buffer descriptors.
+ */
+#define M360_BD_READY (1<<15) /* Ethernet, SCC UART, SMC UART, SPI */
+#define M360_BD_PAD (1<<14) /* Ethernet */
+#define M360_BD_CTS_REPORT (1<<11) /* SCC UART */
+#define M360_BD_TX_CRC (1<<10) /* Ethernet */
+#define M360_BD_DEFER (1<<9) /* Ethernet */
+#define M360_BD_HEARTBEAT (1<<8) /* Ethernet */
+#define M360_BD_PREAMBLE (1<<8) /* SCC UART, SMC UART */
+#define M360_BD_LATE_COLLISION (1<<7) /* Ethernet */
+#define M360_BD_NO_STOP_BIT (1<<7) /* SCC UART */
+#define M360_BD_RETRY_LIMIT (1<<6) /* Ethernet */
+#define M360_BD_RETRY_COUNT(x) (((x)&0x3C)>>2) /* Ethernet */
+#define M360_BD_UNDERRUN (1<<1) /* Ethernet, SPI */
+#define M360_BD_CARRIER_LOST (1<<0) /* Ethernet */
+#define M360_BD_CTS_LOST (1<<0) /* SCC UART */
+
+/*
+ *************************************************************************
+ * IDMA Buffer Descriptors *
+ *************************************************************************
+ */
+typedef struct m360IDMABufferDescriptor_ {
+ unsigned short status;
+ unsigned short _pad;
+ unsigned long length;
+ void *source;
+ void *destination;
+} m360IDMABufferDescriptor_t;
+
+/*
+ *************************************************************************
+ * RISC Communication Processor Module Command Register (CR) *
+ *************************************************************************
+ */
+#define M360_CR_RST (1<<15) /* Reset communication processor */
+#define M360_CR_OP_INIT_RX_TX (0<<8) /* SCC, SMC UART, SMC GCI, SPI */
+#define M360_CR_OP_INIT_RX (1<<8) /* SCC, SMC UART, SPI */
+#define M360_CR_OP_INIT_TX (2<<8) /* SCC, SMC UART, SPI */
+#define M360_CR_OP_INIT_HUNT (3<<8) /* SCC, SMC UART */
+#define M360_CR_OP_STOP_TX (4<<8) /* SCC, SMC UART */
+#define M360_CR_OP_GR_STOP_TX (5<<8) /* SCC */
+#define M360_CR_OP_INIT_IDMA (5<<8) /* IDMA */
+#define M360_CR_OP_RESTART_TX (6<<8) /* SCC, SMC UART */
+#define M360_CR_OP_CLOSE_RX_BD (7<<8) /* SCC, SMC UART, SPI */
+#define M360_CR_OP_SET_GRP_ADDR (8<<8) /* SCC */
+#define M360_CR_OP_SET_TIMER (8<<8) /* Timer */
+#define M360_CR_OP_GCI_TIMEOUT (9<<8) /* SMC GCI */
+#define M360_CR_OP_RESERT_BCS (10<<8) /* SCC */
+#define M360_CR_OP_GCI_ABORT (10<<8) /* SMC GCI */
+#define M360_CR_CHAN_SCC1 (0<<4) /* Channel selection */
+#define M360_CR_CHAN_SCC2 (4<<4)
+#define M360_CR_CHAN_SPI (5<<4)
+#define M360_CR_CHAN_TIMER (5<<4)
+#define M360_CR_CHAN_SCC3 (8<<4)
+#define M360_CR_CHAN_SMC1 (9<<4)
+#define M360_CR_CHAN_IDMA1 (9<<4)
+#define M360_CR_CHAN_SCC4 (12<<4)
+#define M360_CR_CHAN_SMC2 (13<<4)
+#define M360_CR_CHAN_IDMA2 (13<<4)
+#define M360_CR_FLG (1<<0) /* Command flag */
+
+/*
+ *************************************************************************
+ * System Protection Control Register (SYPCR) *
+ *************************************************************************
+ */
+#define M360_SYPCR_SWE (1<<7) /* Software watchdog enable */
+#define M360_SYPCR_SWRI (1<<6) /* Software watchdog reset select */
+#define M360_SYPCR_SWT1 (1<<5) /* Software watchdog timing bit 1 */
+#define M360_SYPCR_SWT0 (1<<4) /* Software watchdog timing bit 0 */
+#define M360_SYPCR_DBFE (1<<3) /* Double bus fault monitor enable */
+#define M360_SYPCR_BME (1<<2) /* Bus monitor external enable */
+#define M360_SYPCR_BMT1 (1<<1) /* Bus monitor timing bit 1 */
+#define M360_SYPCR_BMT0 (1<<0) /* Bus monitor timing bit 0 */
+
+/*
+ *************************************************************************
+ * Memory Control Registers *
+ *************************************************************************
+ */
+#define M360_GMR_RCNT(x) ((x)<<24) /* Refresh count */
+#define M360_GMR_RFEN (1<<23) /* Refresh enable */
+#define M360_GMR_RCYC(x) ((x)<<21) /* Refresh cycle length */
+#define M360_GMR_PGS(x) ((x)<<18) /* Page size */
+#define M360_GMR_DPS_32BIT (0<<16) /* DRAM port size */
+#define M360_GMR_DPS_16BIT (1<<16)
+#define M360_GMR_DPS_8BIT (2<<16)
+#define M360_GMR_DPS_DSACK (3<<16)
+#define M360_GMR_WBT40 (1<<15) /* Wait between 040 transfers */
+#define M360_GMR_WBTQ (1<<14) /* Wait between 360 transfers */
+#define M360_GMR_SYNC (1<<13) /* Synchronous external access */
+#define M360_GMR_EMWS (1<<12) /* External master wait state */
+#define M360_GMR_OPAR (1<<11) /* Odd parity */
+#define M360_GMR_PBEE (1<<10) /* Parity bus error enable */
+#define M360_GMR_TSS40 (1<<9) /* TS* sample for 040 */
+#define M360_GMR_NCS (1<<8) /* No CPU space */
+#define M360_GMR_DWQ (1<<7) /* Delay write for 360 */
+#define M360_GMR_DW40 (1<<6) /* Delay write for 040 */
+#define M360_GMR_GAMX (1<<5) /* Global address mux enable */
+
+#define M360_MEMC_BR_FC(x) ((x)<<7) /* Function code limit */
+#define M360_MEMC_BR_TRLXQ (1<<6) /* Relax timing requirements */
+#define M360_MEMC_BR_BACK40 (1<<5) /* Burst acknowledge to 040 */
+#define M360_MEMC_BR_CSNT40 (1<<4) /* CS* negate timing for 040 */
+#define M360_MEMC_BR_CSNTQ (1<<3) /* CS* negate timing for 360 */
+#define M360_MEMC_BR_PAREN (1<<2) /* Enable parity checking */
+#define M360_MEMC_BR_WP (1<<1) /* Write Protect */
+#define M360_MEMC_BR_V (1<<0) /* Base/Option register are valid */
+
+#define M360_MEMC_OR_TCYC(x) ((x)<<28) /* Cycle length (clocks) */
+#define M360_MEMC_OR_WAITS(x) M360_MEMC_OR_TCYC((x)+1)
+#define M360_MEMC_OR_2KB 0x0FFFF800 /* Address range */
+#define M360_MEMC_OR_4KB 0x0FFFF000
+#define M360_MEMC_OR_8KB 0x0FFFE000
+#define M360_MEMC_OR_16KB 0x0FFFC000
+#define M360_MEMC_OR_32KB 0x0FFF8000
+#define M360_MEMC_OR_64KB 0x0FFF0000
+#define M360_MEMC_OR_128KB 0x0FFE0000
+#define M360_MEMC_OR_256KB 0x0FFC0000
+#define M360_MEMC_OR_512KB 0x0FF80000
+#define M360_MEMC_OR_1MB 0x0FF00000
+#define M360_MEMC_OR_2MB 0x0FE00000
+#define M360_MEMC_OR_4MB 0x0FC00000
+#define M360_MEMC_OR_8MB 0x0F800000
+#define M360_MEMC_OR_16MB 0x0F000000
+#define M360_MEMC_OR_32MB 0x0E000000
+#define M360_MEMC_OR_64MB 0x0C000000
+#define M360_MEMC_OR_128MB 0x08000000
+#define M360_MEMC_OR_256MB 0x00000000
+#define M360_MEMC_OR_FCMC(x) ((x)<<7) /* Function code mask */
+#define M360_MEMC_OR_BCYC(x) ((x)<<5) /* Burst cycle length (clocks) */
+#define M360_MEMC_OR_PGME (1<<3) /* Page mode enable */
+#define M360_MEMC_OR_32BIT (0<<1) /* Port size */
+#define M360_MEMC_OR_16BIT (1<<1)
+#define M360_MEMC_OR_8BIT (2<<1)
+#define M360_MEMC_OR_DSACK (3<<1)
+#define M360_MEMC_OR_DRAM (1<<0) /* Dynamic RAM select */
+
+/*
+ *************************************************************************
+ * SI Mode Register (SIMODE) *
+ *************************************************************************
+ */
+#define M360_SI_SMC2_BITS 0xFFFF0000 /* All SMC2 bits */
+#define M360_SI_SMC2_TDM (1<<31) /* Multiplexed SMC2 */
+#define M360_SI_SMC2_BRG1 (0<<28) /* SMC2 clock souce */
+#define M360_SI_SMC2_BRG2 (1<<28)
+#define M360_SI_SMC2_BRG3 (2<<28)
+#define M360_SI_SMC2_BRG4 (3<<28)
+#define M360_SI_SMC2_CLK5 (0<<28)
+#define M360_SI_SMC2_CLK6 (1<<28)
+#define M360_SI_SMC2_CLK7 (2<<28)
+#define M360_SI_SMC2_CLK8 (3<<28)
+#define M360_SI_SMC1_BITS 0x0000FFFF /* All SMC1 bits */
+#define M360_SI_SMC1_TDM (1<<15) /* Multiplexed SMC1 */
+#define M360_SI_SMC1_BRG1 (0<<12) /* SMC1 clock souce */
+#define M360_SI_SMC1_BRG2 (1<<12)
+#define M360_SI_SMC1_BRG3 (2<<12)
+#define M360_SI_SMC1_BRG4 (3<<12)
+#define M360_SI_SMC1_CLK1 (0<<12)
+#define M360_SI_SMC1_CLK2 (1<<12)
+#define M360_SI_SMC1_CLK3 (2<<12)
+#define M360_SI_SMC1_CLK4 (3<<12)
+
+/*
+ *************************************************************************
+ * SDMA Configuration Register (SDMA) *
+ *************************************************************************
+ */
+#define M360_SDMA_FREEZE (2<<13) /* Freeze on next bus cycle */
+#define M360_SDMA_SISM_7 (7<<8) /* Normal interrupt service mask */
+#define M360_SDMA_SAID_4 (4<<4) /* Normal arbitration ID */
+#define M360_SDMA_INTE (1<<1) /* SBER interrupt enable */
+#define M360_SDMA_INTB (1<<0) /* SBKP interrupt enable */
+
+/*
+ *************************************************************************
+ * Baud (sic) Rate Generators *
+ *************************************************************************
+ */
+#define M360_BRG_RST (1<<17) /* Reset generator */
+#define M360_BRG_EN (1<<16) /* Enable generator */
+#define M360_BRG_EXTC_BRGCLK (0<<14) /* Source is BRGCLK */
+#define M360_BRG_EXTC_CLK2 (1<<14) /* Source is CLK2 pin */
+#define M360_BRG_EXTC_CLK6 (2<<14) /* Source is CLK6 pin */
+#define M360_BRG_ATB (1<<13) /* Autobaud */
+#define M360_BRG_115200 (13<<1) /* Assume 25 MHz clock */
+#define M360_BRG_57600 (26<<1)
+#define M360_BRG_38400 (40<<1)
+#define M360_BRG_19200 (80<<1)
+#define M360_BRG_9600 (162<<1)
+#define M360_BRG_4800 (324<<1)
+#define M360_BRG_2400 (650<<1)
+#define M360_BRG_1200 (1301<<1)
+#define M360_BRG_600 (2603<<1)
+#define M360_BRG_300 ((324<<1) | 1)
+#define M360_BRG_150 ((650<<1) | 1)
+#define M360_BRG_75 ((1301<<1) | 1)
+
+/*
+ *************************************************************************
+ * MC68360 DUAL-PORT RAM AND REGISTERS *
+ *************************************************************************
+ */
+typedef struct m360_ {
+ /*
+ * Dual-port RAM
+ */
+ unsigned char dpram0[0x400]; /* Microcode program */
+ unsigned char dpram1[0x200];
+ unsigned char dpram2[0x100]; /* Microcode scratch */
+ unsigned char dpram3[0x100]; /* Not on REV A or B masks */
+ unsigned char _rsv0[0xC00-0x800];
+ m360SCCENparms_t scc1p;
+ unsigned char _rsv1[0xCB0-0xC00-sizeof(m360SCCENparms_t)];
+ m360MiscParms_t miscp;
+ unsigned char _rsv2[0xD00-0xCB0-sizeof(m360MiscParms_t)];
+ m360SCCparms_t scc2p;
+ unsigned char _rsv3[0xD80-0xD00-sizeof(m360SCCparms_t)];
+ m360SPIparms_t spip;
+ unsigned char _rsv4[0xDB0-0xD80-sizeof(m360SPIparms_t)];
+ m360TimerParms_t tmp;
+ unsigned char _rsv5[0xE00-0xDB0-sizeof(m360TimerParms_t)];
+ m360SCCparms_t scc3p;
+ unsigned char _rsv6[0xE70-0xE00-sizeof(m360SCCparms_t)];
+ m360IDMAparms_t idma1p;
+ unsigned char _rsv7[0xE80-0xE70-sizeof(m360IDMAparms_t)];
+ m360SMCparms_t smc1p;
+ unsigned char _rsv8[0xF00-0xE80-sizeof(m360SMCparms_t)];
+ m360SCCparms_t scc4p;
+ unsigned char _rsv9[0xF70-0xF00-sizeof(m360SCCparms_t)];
+ m360IDMAparms_t idma2p;
+ unsigned char _rsv10[0xF80-0xF70-sizeof(m360IDMAparms_t)];
+ m360SMCparms_t smc2p;
+ unsigned char _rsv11[0x1000-0xF80-sizeof(m360SMCparms_t)];
+
+ /*
+ * SIM Block
+ */
+ unsigned long mcr;
+ unsigned long _pad00;
+ unsigned char avr;
+ unsigned char rsr;
+ unsigned short _pad01;
+ unsigned char clkocr;
+ unsigned char _pad02;
+ unsigned short _pad03;
+ unsigned short pllcr;
+ unsigned short _pad04;
+ unsigned short cdvcr;
+ unsigned short pepar;
+ unsigned long _pad05[2];
+ unsigned short _pad06;
+ unsigned char sypcr;
+ unsigned char swiv;
+ unsigned short _pad07;
+ unsigned short picr;
+ unsigned short _pad08;
+ unsigned short pitr;
+ unsigned short _pad09;
+ unsigned char _pad10;
+ unsigned char swsr;
+ unsigned long bkar;
+ unsigned long bcar;
+ unsigned long _pad11[2];
+
+ /*
+ * MEMC Block
+ */
+ unsigned long gmr;
+ unsigned short mstat;
+ unsigned short _pad12;
+ unsigned long _pad13[2];
+ m360MEMCRegisters_t memc[8];
+ unsigned char _pad14[0xF0-0xD0];
+ unsigned char _pad15[0x100-0xF0];
+ unsigned char _pad16[0x500-0x100];
+
+ /*
+ * IDMA1 Block
+ */
+ unsigned short iccr;
+ unsigned short _pad17;
+ unsigned short cmr1;
+ unsigned short _pad18;
+ unsigned long sapr1;
+ unsigned long dapr1;
+ unsigned long bcr1;
+ unsigned char fcr1;
+ unsigned char _pad19;
+ unsigned char cmar1;
+ unsigned char _pad20;
+ unsigned char csr1;
+ unsigned char _pad21;
+ unsigned short _pad22;
+
+ /*
+ * SDMA Block
+ */
+ unsigned char sdsr;
+ unsigned char _pad23;
+ unsigned short sdcr;
+ unsigned long sdar;
+
+ /*
+ * IDMA2 Block
+ */
+ unsigned short _pad24;
+ unsigned short cmr2;
+ unsigned long sapr2;
+ unsigned long dapr2;
+ unsigned long bcr2;
+ unsigned char fcr2;
+ unsigned char _pad26;
+ unsigned char cmar2;
+ unsigned char _pad27;
+ unsigned char csr2;
+ unsigned char _pad28;
+ unsigned short _pad29;
+ unsigned long _pad30;
+
+ /*
+ * CPIC Block
+ */
+ unsigned long cicr;
+ unsigned long cipr;
+ unsigned long cimr;
+ unsigned long cisr;
+
+ /*
+ * Parallel I/O Block
+ */
+ unsigned short padir;
+ unsigned short papar;
+ unsigned short paodr;
+ unsigned short padat;
+ unsigned long _pad31[2];
+ unsigned short pcdir;
+ unsigned short pcpar;
+ unsigned short pcso;
+ unsigned short pcdat;
+ unsigned short pcint;
+ unsigned short _pad32;
+ unsigned long _pad33[5];
+
+ /*
+ * TIMER Block
+ */
+ unsigned short tgcr;
+ unsigned short _pad34;
+ unsigned long _pad35[3];
+ unsigned short tmr1;
+ unsigned short tmr2;
+ unsigned short trr1;
+ unsigned short trr2;
+ unsigned short tcr1;
+ unsigned short tcr2;
+ unsigned short tcn1;
+ unsigned short tcn2;
+ unsigned short tmr3;
+ unsigned short tmr4;
+ unsigned short trr3;
+ unsigned short trr4;
+ unsigned short tcr3;
+ unsigned short tcr4;
+ unsigned short tcn3;
+ unsigned short tcn4;
+ unsigned short ter1;
+ unsigned short ter2;
+ unsigned short ter3;
+ unsigned short ter4;
+ unsigned long _pad36[2];
+
+ /*
+ * CP Block
+ */
+ unsigned short cr;
+ unsigned short _pad37;
+ unsigned short rccr;
+ unsigned short _pad38;
+ unsigned long _pad39[3];
+ unsigned short _pad40;
+ unsigned short rter;
+ unsigned short _pad41;
+ unsigned short rtmr;
+ unsigned long _pad42[5];
+
+ /*
+ * BRG Block
+ */
+ unsigned long brgc1;
+ unsigned long brgc2;
+ unsigned long brgc3;
+ unsigned long brgc4;
+
+ /*
+ * SCC Block
+ */
+ m360SCCRegisters_t scc1;
+ m360SCCRegisters_t scc2;
+ m360SCCRegisters_t scc3;
+ m360SCCRegisters_t scc4;
+
+ /*
+ * SMC Block
+ */
+ m360SMCRegisters_t smc1;
+ m360SMCRegisters_t smc2;
+
+ /*
+ * SPI Block
+ */
+ unsigned short spmode;
+ unsigned short _pad43[2];
+ unsigned char spie;
+ unsigned char _pad44;
+ unsigned short _pad45;
+ unsigned char spim;
+ unsigned char _pad46[2];
+ unsigned char spcom;
+ unsigned short _pad47[2];
+
+ /*
+ * PIP Block
+ */
+ unsigned short pipc;
+ unsigned short _pad48;
+ unsigned short ptpr;
+ unsigned long pbdir;
+ unsigned long pbpar;
+ unsigned short _pad49;
+ unsigned short pbodr;
+ unsigned long pbdat;
+ unsigned long _pad50[6];
+
+ /*
+ * SI Block
+ */
+ unsigned long simode;
+ unsigned char sigmr;
+ unsigned char _pad51;
+ unsigned char sistr;
+ unsigned char sicmr;
+ unsigned long _pad52;
+ unsigned long sicr;
+ unsigned short _pad53;
+ unsigned short sirp[2];
+ unsigned short _pad54;
+ unsigned long _pad55[2];
+ unsigned char siram[256];
+} m360_t;
+
+extern volatile m360_t m360;
+
+#endif /* __MC68360_h */
diff --git a/cpukit/score/cpu/m68k/rtems/m68k/qsm.h b/cpukit/score/cpu/m68k/rtems/m68k/qsm.h
new file mode 100644
index 0000000000..b8593dd54d
--- /dev/null
+++ b/cpukit/score/cpu/m68k/rtems/m68k/qsm.h
@@ -0,0 +1,204 @@
+/*
+ *-------------------------------------------------------------------
+ *
+ * QSM -- Queued Serial Module
+ *
+ * The QSM contains two serial interfaces: (a) the queued serial
+ * peripheral interface (QSPI) and the serial communication interface
+ * (SCI). The QSPI provides peripheral expansion and/or interprocessor
+ * communication through a full-duplex, synchronous, three-wire bus. A
+ * self contained RAM queue permits serial data transfers without CPU
+ * intervention and automatic continuous sampling. The SCI provides a
+ * standard non-return to zero mark/space format with wakeup functions
+ * to allow the CPU to run uninterrupted until woken
+ *
+ * For more information, refer to Motorola's "Modular Microcontroller
+ * Family Queued Serial Module Reference Manual" (Motorola document
+ * QSMRM/AD).
+ *
+ * This file was created by John S. Gwynne to support Motorola's 68332 MCU.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the following conditions are met:
+ * 1. Redistribution of source code and documentation must retain
+ * the above authorship, this list of conditions and the
+ * following disclaimer.
+ * 2. 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 "AS IS" without warranty of any kind,
+ * either expressed or implied, including, but not limited to, the
+ * implied warranties of merchantability, title and fitness for a
+ * particular purpose.
+ *
+ *------------------------------------------------------------------
+ *
+ * $Id$
+ */
+
+#ifndef _QSM_H_
+#define _QSM_H_
+
+/* SAM-- shift and mask */
+#undef SAM
+#define SAM(a,b,c) ((a << b) & c)
+
+
+/* QSM_CRB (QSM Control Register Block) base address of the QSM
+ control registers */
+#if SIM_MM == 0
+#define QSM_CRB 0x7ffc00
+#else
+#undef SIM_MM
+#define SIM_MM 1
+#define QSM_CRB 0xfffc00
+#endif
+
+
+#define QSMCR (volatile unsigned short int * const)(0x00 + QSM_CRB)
+ /* QSM Configuration Register */
+#define STOP 0x8000 /* Stop Enable */
+#define FRZ 0x6000 /* Freeze Control */
+#define SUPV 0x0080 /* Supervisor/Unrestricted */
+#define IARB 0x000f /* Inerrupt Arbitration */
+
+
+#define QTEST (volatile unsigned short int * const)(0x02 + QSM_CRB)
+ /* QSM Test Register */
+/* Used only for factor testing */
+
+
+#define QILR (volatile unsigned char * const)(0x04 + QSM_CRB)
+ /* QSM Interrupt Level Register */
+#define ILQSPI 0x38 /* Interrupt Level for QSPI */
+#define ILSCI 0x07 /* Interrupt Level for SCI */
+
+
+#define QIVR (volatile unsigned char * const)(0x05 + QSM_CRB)
+ /* QSM Interrupt Vector Register */
+#define INTV 0xff /* Interrupt Vector Number */
+
+
+#define SCCR0 (volatile unsigned short int * const)(0x08 + QSM_CRB)
+ /* SCI Control Register 0 */
+#define SCBR 0x1fff /* SCI Baud Rate */
+
+
+#define SCCR1 (volatile unsigned short int * const)(0x0a + QSM_CRB)
+ /* SCI Control Register 1 */
+#define LOOPS 0x4000 /* Loop Mode */
+#define WOMS 0x2000 /* Wired-OR Mode for SCI Pins */
+#define ILT 0x1000 /* Idle-Line Detect Type */
+#define PT 0x0800 /* Parity Type */
+#define PE 0x0400 /* Parity Enable */
+#define M 0x0200 /* Mode Select */
+#define WAKE 0x0100 /* Wakeup by Address Mark */
+#define TIE 0x0080 /* Transmit Complete Interrupt Enable */
+#define TCIE 0x0040 /* Transmit Complete Interrupt Enable */
+#define RIE 0x0020 /* Receiver Interrupt Enable */
+#define ILIE 0x0010 /* Idle-Line Interrupt Enable */
+#define TE 0x0008 /* Transmitter Enable */
+#define RE 0x0004 /* Receiver Enable */
+#define RWU 0x0002 /* Receiver Wakeup */
+#define SBK 0x0001 /* Send Break */
+
+
+#define SCSR (volatile unsigned short int * const)(0x0c + QSM_CRB)
+ /* SCI Status Register */
+#define TDRE 0x0100 /* Transmit Data Register Empty */
+#define TC 0x0080 /* Transmit Complete */
+#define RDRF 0x0040 /* Receive Data Register Full */
+#define RAF 0x0020 /* Receiver Active */
+#define IDLE 0x0010 /* Idle-Line Detected */
+#define OR 0x0008 /* Overrun Error */
+#define NF 0x0004 /* Noise Error Flag */
+#define FE 0x0002 /* Framing Error */
+#define PF 0x0001 /* Parity Error */
+
+
+#define SCDR (volatile unsigned short int * const)(0x0e + QSM_CRB)
+ /* SCI Data Register */
+
+
+#define PORTQS (volatile unsigned char * const)(0x15 + QSM_CRB)
+ /* Port QS Data Register */
+
+#define PQSPAR (volatile unsigned char * const)(0x16 + QSM_CRB)
+ /* PORT QS Pin Assignment Rgister */
+/* Any bit cleared (zero) defines the corresponding pin to be an I/O
+ pin. Any bit set defines the corresponding pin to be a QSPI
+ signal. */
+/* note: PQS2 is a digital I/O pin unless the SPI is enabled in which
+ case it becomes the SPI serial clock SCK. */
+/* note: PQS7 is a digital I/O pin unless the SCI transmitter is
+ enabled in which case it becomes the SCI serial output TxD. */
+#define QSMFun 0x0
+#define QSMDis 0x1
+/*
+ * PQSPAR Field | QSM Function | Discrete I/O pin
+ *------------------+--------------+------------------ */
+#define PQSPA0 0 /* MISO | PQS0 */
+#define PQSPA1 1 /* MOSI | PQS1 */
+#define PQSPA2 2 /* SCK | PQS2 (see note)*/
+#define PQSPA3 3 /* PCSO/!SS | PQS3 */
+#define PQSPA4 4 /* PCS1 | PQS4 */
+#define PQSPA5 5 /* PCS2 | PQS5 */
+#define PQSPA6 6 /* PCS3 | PQS6 */
+#define PQSPA7 7 /* TxD | PQS7 (see note)*/
+
+
+#define DDRQS (volatile unsigned char * const)(0x17 + QSM_CRB)
+ /* PORT QS Data Direction Register */
+/* Clearing a bit makes the corresponding pin an input; setting a bit
+ makes the pin an output. */
+
+
+#define SPCR0 (volatile unsigned short int * const)(0x18 + QSM_CRB)
+ /* QSPI Control Register 0 */
+#define MSTR 0x8000 /* Master/Slave Mode Select */
+#define WOMQ 0x4000 /* Wired-OR Mode for QSPI Pins */
+#define BITS 0x3c00 /* Bits Per Transfer */
+#define CPOL 0x0200 /* Clock Polarity */
+#define CPHA 0x0100 /* Clock Phase */
+#define SPBR 0x00ff /* Serial Clock Baud Rate */
+
+
+#define SPCR1 (volatile unsigned short int * const)(0x1a + QSM_CRB)
+ /* QSPI Control Register 1 */
+#define SPE 0x8000 /* QSPI Enable */
+#define DSCKL 0x7f00 /* Delay before SCK */
+#define DTL 0x00ff /* Length of Delay after Transfer */
+
+
+#define SPCR2 (volatile unsigned short int * const)(0x1c + QSM_CRB)
+ /* QSPI Control Register 2 */
+#define SPIFIE 0x8000 /* SPI Finished Interrupt Enable */
+#define WREN 0x4000 /* Wrap Enable */
+#define WRTO 0x2000 /* Wrap To */
+#define ENDQP 0x0f00 /* Ending Queue Pointer */
+#define NEWQP 0x000f /* New Queue Pointer Value */
+
+
+#define SPCR3 (volatile unsigned char * const)(0x1e + QSM_CRB)
+ /* QSPI Control Register 3 */
+#define LOOPQ 0x0400 /* QSPI Loop Mode */
+#define HMIE 0x0200 /* HALTA and MODF Interrupt Enable */
+#define HALT 0x0100 /* Halt */
+
+
+#define SPSR (volatile unsigned char * const)(0x1f + QSM_CRB)
+ /* QSPI Status Register */
+#define SPIF 0x0080 /* QSPI Finished Flag */
+#define MODF 0x0040 /* Mode Fault Flag */
+#define HALTA 0x0020 /* Halt Acknowlwdge Flag */
+#define CPTQP x0000f /* Completed Queue Pointer */
+
+#define QSPIRR (volatile unsigned char * const)(0x100 + QSM_CRB)
+ /* QSPI Receive Data RAM */
+#define QSPITR (volatile unsigned char * const)(0x120 + QSM_CRB)
+ /* QSPI Transmit Data RAM */
+#define QSPIcR (volatile unsigned char * const)(0x140 + QSM_CRB)
+ /* QSPI Command RAM */
+
+#endif /* _QSM_H_ */
diff --git a/cpukit/score/cpu/m68k/rtems/m68k/sim.h b/cpukit/score/cpu/m68k/rtems/m68k/sim.h
new file mode 100644
index 0000000000..0ad5ba1653
--- /dev/null
+++ b/cpukit/score/cpu/m68k/rtems/m68k/sim.h
@@ -0,0 +1,333 @@
+/*
+ *-------------------------------------------------------------------
+ *
+ * SIM -- System Integration Module
+ *
+ * The system integration module (SIM) is used on many Motorola 16-
+ * and 32-bit MCUs for the following functions:
+ *
+ * () System configuration and protection. Bus and software watchdog
+ * monitors are provided in addition to periodic interrupt generators.
+ *
+ * () Clock signal generation for other intermodule bus (IMB) members
+ * and external devices.
+ *
+ * () The generation of chip-select signals that simplify external
+ * circuitry interface.
+ *
+ * () Data ports that are available for general purpose input and
+ * output.
+ *
+ * () A system test block that is intended only for factory tests.
+ *
+ * For more information, refer to Motorola's "Modular Microcontroller
+ * Family System Integration Module Reference Manual" (Motorola document
+ * SIMRM/AD).
+ *
+ * This file was created by John S. Gwynne to support Motorola's 68332 MCU.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the following conditions are met:
+ * 1. Redistribution of source code and documentation must retain
+ * the above authorship, this list of conditions and the
+ * following disclaimer.
+ * 2. 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 "AS IS" without warranty of any kind,
+ * either expressed or implied, including, but not limited to, the
+ * implied warranties of merchantability, title and fitness for a
+ * particular purpose.
+ *
+ *------------------------------------------------------------------
+ *
+ * $Id$
+ */
+
+#ifndef _SIM_H_
+#define _SIM_H_
+
+
+/* SAM-- shift and mask */
+#undef SAM
+#define SAM(a,b,c) ((a << b) & c)
+
+/*
+ * These macros make this file usable from assembly.
+ */
+
+#ifdef ASM
+#define SIM_VOLATILE_USHORT_POINTER
+#define SIM_VOLATILE_UCHAR_POINTER
+#else
+#define SIM_VOLATILE_USHORT_POINTER (volatile unsigned short int * const)
+#define SIM_VOLATILE_UCHAR_POINTER (volatile unsigned char * const)
+#endif
+
+/* SIM_CRB (SIM Control Register Block) base address of the SIM
+ control registers */
+#ifndef SIM_CRB
+#if SIM_MM == 0
+#define SIM_CRB 0x7ffa00
+#else /* SIM_MM */
+#undef SIM_MM
+#define SIM_MM 1
+#define SIM_CRB 0xfffa00
+#endif /* SIM_MM */
+#endif /* SIM_CRB */
+
+
+#define SIMCR SIM_VOLATILE_USHORT_POINTER(0x00 + SIM_CRB)
+ /* Module Configuration Register */
+#define EXOFF 0x8000 /* External Clock Off */
+#define FRZSW 0x4000 /* Freeze Software Enable */
+#define FRZBM 0x2000 /* Freeze Bus Monitor Enable */
+#define SLVEN 0x0800 /* Factory Test Model Enabled (ro)*/
+#define SHEN 0x0300 /* Show Cycle Enable */
+#define SUPV 0x0080 /* Supervisor/Unrestricted Data Space */
+#define MM 0x0040 /* Module Mapping */
+#define IARB 0x000f /* Interrupt Arbitration Field */
+
+
+
+#define SIMTR SIM_VOLATILE_USHORT_POINTER(0x02 + SIM_CRB)
+ /* SIM Test Register */
+/* Used only for factor testing */
+
+
+
+#define SYNCR SIM_VOLATILE_USHORT_POINTER(0x04 + SIM_CRB)
+ /* Clock Synthesizer Control Register */
+#define VCO 0x8000 /* Frequency Control (VCO) */
+#define PRESCALE 0x4000 /* Frequency Control Bit (Prescale) */
+#define COUNTER 0x3f00 /* Frequency Control Counter */
+#define EDIV 0x0080 /* ECLK Divide Rate */
+#define SLIMP 0x0010 /* Limp Mode Status */
+#define SLOCK 0x0008 /* Synthesizer Lock */
+#define RSTEN 0x0004 /* Reset Enable */
+#define STSIM 0x0002 /* Stop Mode SIM Clock */
+#define STEXT 0x0001 /* Stop Mode External Clock */
+
+
+
+#define RSR SIM_VOLATILE_UCHAR_POINTER(0x07 + SIM_CRB)
+ /* Reset Status Register */
+#define EXT 0x0080 /* External Reset */
+#define POW 0x0040 /* Power-On Reset */
+#define SW 0x0020 /* Software Watchdog Reset */
+#define DBF 0x0010 /* Double Bus Fault Reset */
+#define LOC 0x0004 /* Loss of Clock Reset */
+#define SYS 0x0002 /* System Reset */
+#define TST 0x0001 /* Test Submodule Reset */
+
+
+
+#define SIMTRE SIM_VOLATILE_USHORT_POINTER(0x08 + SIM_CRB)
+ /* System Integration Test Register */
+/* Used only for factor testing */
+
+
+
+#define PORTE0 SIM_VOLATILE_UCHAR_POINTER(0x11 + SIM_CRB)
+#define PORTE1 SIM_VOLATILE_UCHAR_POINTER(0x13 + SIM_CRB)
+ /* Port E Data Register */
+#define DDRE SIM_VOLATILE_UCHAR_POINTER(0x15 + SIM_CRB)
+ /* Port E Data Direction Register */
+#define PEPAR SIM_VOLATILE_UCHAR_POINTER(0x17 + SIM_CRB)
+ /* Port E Pin Assignment Register */
+/* Any bit cleared (zero) defines the corresponding pin to be an I/O
+ pin. Any bit set defines the corresponding pin to be a bus control
+ signal. */
+
+
+
+#define PORTF0 SIM_VOLATILE_UCHAR_POINTER(0x19 + SIM_CRB)
+#define PORTF1 SIM_VOLATILE_UCHAR_POINTER(0x1b + SIM_CRB)
+ /* Port F Data Register */
+#define DDRF SIM_VOLATILE_UCHAR_POINTER(0x1d + SIM_CRB)
+ /* Port E Data Direction Register */
+#define PFPAR SIM_VOLATILE_UCHAR_POINTER(0x1f + SIM_CRB)
+/* Any bit cleared (zero) defines the corresponding pin to be an I/O
+ pin. Any bit set defines the corresponding pin to be a bus control
+ signal. */
+
+
+
+#define SYPCR SIM_VOLATILE_UCHAR_POINTER(0x21 + SIM_CRB)
+/* !!! can write to only once after reset !!! */
+ /* System Protection Control Register */
+#define SWE 0x80 /* Software Watch Enable */
+#define SWP 0x40 /* Software Watchdog Prescale */
+#define SWT 0x30 /* Software Watchdog Timing */
+#define HME 0x08 /* Halt Monitor Enable */
+#define BME 0x04 /* Bus Monitor External Enable */
+#define BMT 0x03 /* Bus Monitor Timing */
+
+
+
+#define PICR SIM_VOLATILE_USHORT_POINTER(0x22 + SIM_CRB)
+ /* Periodic Interrupt Control Reg. */
+#define PIRQL 0x0700 /* Periodic Interrupt Request Level */
+#define PIV 0x00ff /* Periodic Interrupt Level */
+
+
+
+#define PITR SIM_VOLATILE_USHORT_POINTER(0x24 + SIM_CRB)
+ /* Periodic Interrupt Timer Register */
+#define PTP 0x0100 /* Periodic Timer Prescaler Control */
+#define PITM 0x00ff /* Periodic Interrupt Timing Modulus */
+
+
+
+#define SWSR SIM_VOLATILE_UCHAR_POINTER(0x27 + SIM_CRB)
+ /* Software Service Register */
+/* write 0x55 then 0xaa to service the software watchdog */
+
+
+
+#define TSTMSRA SIM_VOLATILE_USHORT_POINTER(0x30 + SIM_CRB)
+ /* Test Module Master Shift A */
+#define TSTMSRB SIM_VOLATILE_USHORT_POINTER(0x32 + SIM_CRB)
+ /* Test Module Master Shift A */
+#define TSTSC SIM_VOLATILE_USHORT_POINTER(0x34 + SIM_CRB)
+ /* Test Module Shift Count */
+#define TSTRC SIM_VOLATILE_USHORT_POINTER(0x36 + SIM_CRB)
+ /* Test Module Repetition Counter */
+#define CREG SIM_VOLATILE_USHORT_POINTER(0x38 + SIM_CRB)
+ /* Test Module Control */
+#define DREG SIM_VOLATILE_USHORT_POINTER(0x3a + SIM_CRB)
+ /* Test Module Distributed */
+/* Used only for factor testing */
+
+
+
+#define PORTC SIM_VOLATILE_UCHAR_POINTER(0x41 + SIM_CRB)
+ /* Port C Data */
+
+
+
+#define CSPAR0 SIM_VOLATILE_USHORT_POINTER(0x44 + SIM_CRB)
+ /* Chip Select Pin Assignment
+ Resgister 0 */
+/* CSPAR0 contains seven two-bit fields that determine the functions
+ of corresponding chip-select pins. CSPAR0[15:14] are not
+ used. These bits always read zero; write have no effect. CSPAR0 bit
+ 1 always reads one; writes to CSPAR0 bit 1 have no effect. */
+#define CSPAR1 SIM_VOLATILE_USHORT_POINTER(0x46 + SIM_CRB)
+ /* Chip Select Pin Assignment
+ Register 1 */
+/* CSPAR1 contains five two-bit fields that determine the finctions of
+ corresponding chip-select pins. CSPAR1[15:10] are not used. These
+ bits always read zero; writes have no effect. */
+/*
+ *
+ * Bit Field | Description
+ * ------------+---------------
+ * 00 | Discrete Output
+ * 01 | Alternate Function
+ * 10 | Chip Select (8-bit port)
+ * 11 | Chip Select (16-bit port)
+ */
+#define DisOut 0x0
+#define AltFun 0x1
+#define CS8bit 0x2
+#define CS16bit 0x3
+/*
+ *
+ * CSPARx Field |Chip Select Signal | Alternate Signal | Discrete Output
+ *-----------------+--------------------+--------------------+---------------*/
+#define CS_5 12 /* !CS5 | FC2 | PC2 */
+#define CS_4 10 /* !CS4 | FC1 | PC1 */
+#define CS_3 8 /* !CS3 | FC0 | PC0 */
+#define CS_2 6 /* !CS2 | !BGACK | */
+#define CS_1 4 /* !CS1 | !BG | */
+#define CS_0 2 /* !CS0 | !BR | */
+#define CSBOOT 0 /* !CSBOOT | | */
+/* | | | */
+#define CS_10 8 /* !CS10 | ADDR23 | ECLK */
+#define CS_9 6 /* !CS9 | ADDR22 | PC6 */
+#define CS_8 4 /* !CS8 | ADDR21 | PC5 */
+#define CS_7 2 /* !CS7 | ADDR20 | PC4 */
+#define CS_6 0 /* !CS6 | ADDR19 | PC3 */
+
+#define BS_2K 0x0
+#define BS_8K 0x1
+#define BS_16K 0x2
+#define BS_64K 0x3
+#define BS_128K 0x4
+#define BS_256K 0x5
+#define BS_512K 0x6
+#define BS_1M 0x7
+
+#define CSBARBT SIM_VOLATILE_USHORT_POINTER(0x48 + SIM_CRB)
+#define CSBAR0 SIM_VOLATILE_USHORT_POINTER(0x4c + SIM_CRB)
+#define CSBAR1 SIM_VOLATILE_USHORT_POINTER(0x50 + SIM_CRB)
+#define CSBAR2 SIM_VOLATILE_USHORT_POINTER(0x54 + SIM_CRB)
+#define CSBAR3 SIM_VOLATILE_USHORT_POINTER(0x58 + SIM_CRB)
+#define CSBAR4 SIM_VOLATILE_USHORT_POINTER(0x5c + SIM_CRB)
+#define CSBAR5 SIM_VOLATILE_USHORT_POINTER(0x60 + SIM_CRB)
+#define CSBAR6 SIM_VOLATILE_USHORT_POINTER(0x64 + SIM_CRB)
+#define CSBAR7 SIM_VOLATILE_USHORT_POINTER(0x68 + SIM_CRB)
+#define CSBAR8 SIM_VOLATILE_USHORT_POINTER(0x6c + SIM_CRB)
+#define CSBAR9 SIM_VOLATILE_USHORT_POINTER(0x70 + SIM_CRB)
+#define CSBAR10 SIM_VOLATILE_USHORT_POINTER(0x74 + SIM_CRB)
+
+#define MODE 0x8000
+#define Disable 0
+#define LowerByte 0x2000
+#define UpperByte 0x4000
+#define BothBytes 0x6000
+#define ReadOnly 0x0800
+#define WriteOnly 0x1000
+#define ReadWrite 0x1800
+#define SyncAS 0x0
+#define SyncDS 0x0400
+
+#define WaitStates_0 (0x0 << 6)
+#define WaitStates_1 (0x1 << 6)
+#define WaitStates_2 (0x2 << 6)
+#define WaitStates_3 (0x3 << 6)
+#define WaitStates_4 (0x4 << 6)
+#define WaitStates_5 (0x5 << 6)
+#define WaitStates_6 (0x6 << 6)
+#define WaitStates_7 (0x7 << 6)
+#define WaitStates_8 (0x8 << 6)
+#define WaitStates_9 (0x9 << 6)
+#define WaitStates_10 (0xa << 6)
+#define WaitStates_11 (0xb << 6)
+#define WaitStates_12 (0xc << 6)
+#define WaitStates_13 (0xd << 6)
+#define FastTerm (0xe << 6)
+#define External (0xf << 6)
+
+#define CPUSpace (0x0 << 4)
+#define UserSpace (0x1 << 4)
+#define SupSpace (0x2 << 4)
+#define UserSupSpace (0x3 << 4)
+
+#define IPLevel_any 0x0
+#define IPLevel_1 0x2
+#define IPLevel_2 0x4
+#define IPLevel_3 0x6
+#define IPLevel_4 0x8
+#define IPLevel_5 0xa
+#define IPLevel_6 0xc
+#define IPLevel_7 0xe
+
+#define AVEC 1
+
+#define CSORBT SIM_VOLATILE_USHORT_POINTER(0x4a + SIM_CRB)
+#define CSOR0 SIM_VOLATILE_USHORT_POINTER(0x4e + SIM_CRB)
+#define CSOR1 SIM_VOLATILE_USHORT_POINTER(0x52 + SIM_CRB)
+#define CSOR2 SIM_VOLATILE_USHORT_POINTER(0x56 + SIM_CRB)
+#define CSOR3 SIM_VOLATILE_USHORT_POINTER(0x5a + SIM_CRB)
+#define CSOR4 SIM_VOLATILE_USHORT_POINTER(0x5e + SIM_CRB)
+#define CSOR5 SIM_VOLATILE_USHORT_POINTER(0x62 + SIM_CRB)
+#define CSOR6 SIM_VOLATILE_USHORT_POINTER(0x66 + SIM_CRB)
+#define CSOR7 SIM_VOLATILE_USHORT_POINTER(0x6a + SIM_CRB)
+#define CSOR8 SIM_VOLATILE_USHORT_POINTER(0x6e + SIM_CRB)
+#define CSOR9 SIM_VOLATILE_USHORT_POINTER(0x72 + SIM_CRB)
+#define CSOR10 SIM_VOLATILE_USHORT_POINTER(0x76 + SIM_CRB)
+
+#endif /* _SIM_h_ */
diff --git a/cpukit/score/cpu/m68k/rtems/score/cpu.h b/cpukit/score/cpu/m68k/rtems/score/cpu.h
new file mode 100644
index 0000000000..968f6d6def
--- /dev/null
+++ b/cpukit/score/cpu/m68k/rtems/score/cpu.h
@@ -0,0 +1,689 @@
+/* cpu.h
+ *
+ * This include file contains information pertaining to the Motorola
+ * m68xxx processor family.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __CPU_h
+#define __CPU_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/m68k.h> /* pick up machine definitions */
+#ifndef ASM
+#include <rtems/score/types.h>
+#endif
+
+/* conditional compilation parameters */
+
+#define CPU_INLINE_ENABLE_DISPATCH TRUE
+#define CPU_UNROLL_ENQUEUE_PRIORITY FALSE
+
+/*
+ * Use the m68k's hardware interrupt stack support and have the
+ * interrupt manager allocate the memory for it.
+ */
+
+#if ( M68K_HAS_SEPARATE_STACKS == 1)
+#define CPU_HAS_SOFTWARE_INTERRUPT_STACK 0
+#define CPU_HAS_HARDWARE_INTERRUPT_STACK 1
+#else
+#define CPU_HAS_SOFTWARE_INTERRUPT_STACK 1
+#define CPU_HAS_HARDWARE_INTERRUPT_STACK 0
+#endif
+#define CPU_ALLOCATE_INTERRUPT_STACK 1
+
+/*
+ * Does the RTEMS invoke the user's ISR with the vector number and
+ * a pointer to the saved interrupt frame (1) or just the vector
+ * number (0)?
+ */
+
+#define CPU_ISR_PASSES_FRAME_POINTER 0
+
+/*
+ * Some family members have no FP, some have an FPU such as the
+ * MC68881/MC68882 for the MC68020, others have it built in (MC68030, 040).
+ *
+ * NOTE: If on a CPU without hardware FP, then one can use software
+ * emulation. The gcc software FP emulation code has data which
+ * must be contexted switched on a per task basis.
+ */
+
+#if ( M68K_HAS_FPU == 1 )
+#define CPU_HARDWARE_FP TRUE
+#define CPU_SOFTWARE_FP FALSE
+#else
+#define CPU_HARDWARE_FP FALSE
+#if defined(__GNUC__)
+#define CPU_SOFTWARE_FP TRUE
+#else
+#define CPU_SOFTWARE_FP FALSE
+#endif
+#endif
+
+/*
+ * All tasks are not by default floating point tasks on this CPU.
+ * The IDLE task does not have a floating point context on this CPU.
+ * It is safe to use the deferred floating point context switch
+ * algorithm on this CPU.
+ */
+
+#define CPU_ALL_TASKS_ARE_FP FALSE
+#define CPU_IDLE_TASK_IS_FP FALSE
+#define CPU_USE_DEFERRED_FP_SWITCH TRUE
+
+#define CPU_PROVIDES_IDLE_THREAD_BODY TRUE
+#define CPU_STACK_GROWS_UP FALSE
+#define CPU_STRUCTURE_ALIGNMENT
+
+/*
+ * Define what is required to specify how the network to host conversion
+ * routines are handled.
+ */
+
+#define CPU_HAS_OWN_HOST_TO_NETWORK_ROUTINES FALSE
+#define CPU_BIG_ENDIAN TRUE
+#define CPU_LITTLE_ENDIAN FALSE
+
+#ifndef ASM
+/* structures */
+
+/*
+ * Basic integer context for the m68k family.
+ */
+
+typedef struct {
+ uint32_t sr; /* (sr) status register */
+ uint32_t d2; /* (d2) data register 2 */
+ uint32_t d3; /* (d3) data register 3 */
+ uint32_t d4; /* (d4) data register 4 */
+ uint32_t d5; /* (d5) data register 5 */
+ uint32_t d6; /* (d6) data register 6 */
+ uint32_t d7; /* (d7) data register 7 */
+ void *a2; /* (a2) address register 2 */
+ void *a3; /* (a3) address register 3 */
+ void *a4; /* (a4) address register 4 */
+ void *a5; /* (a5) address register 5 */
+ void *a6; /* (a6) address register 6 */
+ void *a7_msp; /* (a7) master stack pointer */
+} Context_Control;
+
+/*
+ * Floating point context ares
+ */
+
+#if (CPU_SOFTWARE_FP == TRUE)
+
+/*
+ * This is the same as gcc's view of the software FP condition code
+ * register _fpCCR. The implementation of the emulation code is
+ * in the gcc-VERSION/config/m68k directory. This structure is
+ * correct as of gcc 2.7.2.2.
+ */
+
+typedef struct {
+ uint16_t _exception_bits;
+ uint16_t _trap_enable_bits;
+ uint16_t _sticky_bits;
+ uint16_t _rounding_mode;
+ uint16_t _format;
+ uint16_t _last_operation;
+ union {
+ float sf;
+ double df;
+ } _operand1;
+ union {
+ float sf;
+ double df;
+ } _operand2;
+} Context_Control_fp;
+
+#else
+
+/*
+ * FP context save area for the M68881/M68882 numeric coprocessors.
+ */
+
+typedef struct {
+ uint8_t fp_save_area[332]; /* 216 bytes for FSAVE/FRESTORE */
+ /* 96 bytes for FMOVEM FP0-7 */
+ /* 12 bytes for FMOVEM CREGS */
+ /* 4 bytes for non-null flag */
+} Context_Control_fp;
+#endif
+
+/*
+ * The following structures define the set of information saved
+ * on the current stack by RTEMS upon receipt of each exc/interrupt.
+ * These are not used by m68k handlers.
+ * The exception frame is for rdbg.
+ */
+
+typedef struct {
+ uint32_t vecnum; /* vector number */
+} CPU_Interrupt_frame;
+
+typedef struct {
+ uint32_t vecnum; /* vector number */
+ uint32_t sr; /* status register */
+ uint32_t pc; /* program counter */
+ uint32_t d0, d1, d2, d3, d4, d5, d6, d7;
+ uint32_t a0, a1, a2, a3, a4, a5, a6, a7;
+} CPU_Exception_frame;
+
+/*
+ * The following table contains the information required to configure
+ * the m68k specific parameters.
+ */
+
+typedef struct {
+ void (*pretasking_hook)( void );
+ void (*predriver_hook)( void );
+ void (*postdriver_hook)( void );
+ void (*idle_task)( void );
+ boolean do_zero_of_workspace;
+ uint32_t idle_task_stack_size;
+ uint32_t interrupt_stack_size;
+ uint32_t extra_mpci_receive_server_stack;
+ void * (*stack_allocate_hook)( uint32_t );
+ void (*stack_free_hook)( void* );
+ /* end of fields required on all CPUs */
+
+ m68k_isr *interrupt_vector_table;
+} rtems_cpu_table;
+
+/*
+ * Macros to access required entires in the CPU Table are in
+ * the file rtems/system.h.
+ */
+
+/*
+ * Macros to access M68K specific additions to the CPU Table
+ */
+
+#define rtems_cpu_configuration_get_interrupt_vector_table() \
+ (_CPU_Table.interrupt_vector_table)
+
+/* variables */
+
+SCORE_EXTERN void *_CPU_Interrupt_stack_low;
+SCORE_EXTERN void *_CPU_Interrupt_stack_high;
+
+extern char _VBR[];
+
+#if ( M68K_HAS_VBR == 0 )
+
+/*
+ * Table of ISR handler entries that resides in RAM. The FORMAT/ID is
+ * pushed onto the stack. This is not is the same order as VBR processors.
+ * The ISR handler takes the format and uses it for dispatching the user
+ * handler.
+ *
+ * FIXME : should be moved to below CPU_INTERRUPT_NUMBER_OF_VECTORS
+ *
+ */
+
+typedef struct {
+ uint16_t move_a7; /* move #FORMAT_ID,%a7@- */
+ uint16_t format_id;
+ uint16_t jmp; /* jmp _ISR_Handlers */
+ uint32_t isr_handler;
+} _CPU_ISR_handler_entry;
+
+#define M68K_MOVE_A7 0x3F3C
+#define M68K_JMP 0x4EF9
+
+ /* points to jsr-exception-table in targets wo/ VBR register */
+SCORE_EXTERN _CPU_ISR_handler_entry _CPU_ISR_jump_table[256];
+
+#endif /* M68K_HAS_VBR */
+#endif /* ASM */
+
+/* constants */
+
+/*
+ * This defines the number of levels and the mask used to pick those
+ * bits out of a thread mode.
+ */
+
+#define CPU_MODES_INTERRUPT_LEVEL 0x00000007 /* interrupt level in mode */
+#define CPU_MODES_INTERRUPT_MASK 0x00000007 /* interrupt level in mode */
+
+/*
+ * context size area for floating point
+ */
+
+#define CPU_CONTEXT_FP_SIZE sizeof( Context_Control_fp )
+
+/*
+ * extra stack required by the MPCI receive server thread
+ */
+
+#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 1024
+
+/*
+ * m68k family supports 256 distinct vectors.
+ */
+
+#define CPU_INTERRUPT_NUMBER_OF_VECTORS 256
+#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1)
+
+/*
+ * This is defined if the port has a special way to report the ISR nesting
+ * level. Most ports maintain the variable _ISR_Nest_level.
+ */
+
+#define CPU_PROVIDES_ISR_IS_IN_PROGRESS FALSE
+
+/*
+ * Minimum size of a thread's stack.
+ */
+
+#define CPU_STACK_MINIMUM_SIZE 4096
+
+/*
+ * m68k is pretty tolerant of alignment. Just put things on 4 byte boundaries.
+ */
+
+#define CPU_ALIGNMENT 4
+#define CPU_HEAP_ALIGNMENT CPU_ALIGNMENT
+#define CPU_PARTITION_ALIGNMENT CPU_ALIGNMENT
+
+/*
+ * On m68k thread stacks require no further alignment after allocation
+ * from the Workspace.
+ */
+
+#define CPU_STACK_ALIGNMENT 0
+
+#ifndef ASM
+
+/* macros */
+
+/*
+ * ISR handler macros
+ *
+ * These macros perform the following functions:
+ * + initialize the RTEMS vector table
+ * + disable all maskable CPU interrupts
+ * + restore previous interrupt level (enable)
+ * + temporarily restore interrupts (flash)
+ * + set a particular level
+ */
+
+#define _CPU_Initialize_vectors()
+
+#define _CPU_ISR_Disable( _level ) \
+ m68k_disable_interrupts( _level )
+
+#define _CPU_ISR_Enable( _level ) \
+ m68k_enable_interrupts( _level )
+
+#define _CPU_ISR_Flash( _level ) \
+ m68k_flash_interrupts( _level )
+
+#define _CPU_ISR_Set_level( _newlevel ) \
+ m68k_set_interrupt_level( _newlevel )
+
+uint32_t _CPU_ISR_Get_level( void );
+
+/* end of ISR handler macros */
+
+/*
+ * Context handler macros
+ *
+ * These macros perform the following functions:
+ * + initialize a context area
+ * + restart the current thread
+ * + calculate the initial pointer into a FP context area
+ * + initialize an FP context area
+ */
+
+#define _CPU_Context_Initialize( _the_context, _stack_base, _size, \
+ _isr, _entry_point, _is_fp ) \
+ do { \
+ uint32_t _stack; \
+ \
+ (_the_context)->sr = 0x3000 | ((_isr) << 8); \
+ _stack = (uint32_t )(_stack_base) + (_size) - 4; \
+ (_the_context)->a7_msp = (void *)_stack; \
+ *(void **)_stack = (void *)(_entry_point); \
+ } while ( 0 )
+
+#define _CPU_Context_Restart_self( _the_context ) \
+ { asm volatile( "movew %0,%%sr ; " \
+ "moval %1,%%a7 ; " \
+ "rts" \
+ : "=d" ((_the_context)->sr), "=d" ((_the_context)->a7_msp) \
+ : "0" ((_the_context)->sr), "1" ((_the_context)->a7_msp) ); \
+ }
+
+/*
+ * Floating Point Context Area Support routines
+ */
+
+#if (CPU_SOFTWARE_FP == TRUE)
+
+/*
+ * This software FP implementation is only for GCC.
+ */
+
+#define _CPU_Context_Fp_start( _base, _offset ) \
+ ((void *) _Addresses_Add_offset( (_base), (_offset) ) )
+
+
+#define _CPU_Context_Initialize_fp( _fp_area ) \
+ { \
+ Context_Control_fp *_fp; \
+ _fp = *(Context_Control_fp **)_fp_area; \
+ _fp->_exception_bits = 0; \
+ _fp->_trap_enable_bits = 0; \
+ _fp->_sticky_bits = 0; \
+ _fp->_rounding_mode = 0; /* ROUND_TO_NEAREST */ \
+ _fp->_format = 0; /* NIL */ \
+ _fp->_last_operation = 0; /* NOOP */ \
+ _fp->_operand1.df = 0; \
+ _fp->_operand2.df = 0; \
+ }
+#else
+#define _CPU_Context_Fp_start( _base, _offset ) \
+ ((void *) \
+ _Addresses_Add_offset( \
+ (_base), \
+ (_offset) + CPU_CONTEXT_FP_SIZE - 4 \
+ ) \
+ )
+
+#define _CPU_Context_Initialize_fp( _fp_area ) \
+ { uint32_t *_fp_context = (uint32_t *)*(_fp_area); \
+ \
+ *(--(_fp_context)) = 0; \
+ *(_fp_area) = (uint8_t *)(_fp_context); \
+ }
+#endif
+
+/* end of Context handler macros */
+
+/*
+ * _CPU_Thread_Idle_body
+ *
+ * This routine is the CPU dependent IDLE thread body.
+ *
+ * NOTE: It need only be provided if CPU_PROVIDES_IDLE_THREAD_BODY
+ * is TRUE.
+ */
+
+void _CPU_Thread_Idle_body( void );
+
+/*
+ * Fatal Error manager macros
+ *
+ * These macros perform the following functions:
+ * + disable interrupts and halt the CPU
+ */
+
+#if ( M68K_COLDFIRE_ARCH == 1 )
+#define _CPU_Fatal_halt( _error ) \
+ { asm volatile( "move.w %%sr,%%d0\n\t" \
+ "or.l %2,%%d0\n\t" \
+ "move.w %%d0,%%sr\n\t" \
+ "move.l %1,%%d0\n\t" \
+ "move.l #0xDEADBEEF,%%d1\n\t" \
+ "halt" \
+ : "=g" (_error) \
+ : "0" (_error), "d"(0x0700) \
+ : "d0", "d1" ); \
+ }
+#else
+#define _CPU_Fatal_halt( _error ) \
+ { asm volatile( "movl %0,%%d0; " \
+ "orw #0x0700,%%sr; " \
+ "stop #0x2700" : "=d" ((_error)) : "0" ((_error)) ); \
+ }
+#endif
+
+/* end of Fatal Error manager macros */
+
+/*
+ * Bitfield handler macros
+ *
+ * These macros perform the following functions:
+ * + scan for the highest numbered (MSB) set in a 16 bit bitfield
+ *
+ * NOTE:
+ *
+ * It appears that on the M68020 bitfield are always 32 bits wide
+ * when in a register. This code forces the bitfield to be in
+ * memory (it really always is anyway). This allows us to
+ * have a real 16 bit wide bitfield which operates "correctly."
+ */
+
+#define CPU_USE_GENERIC_BITFIELD_CODE FALSE
+#define CPU_USE_GENERIC_BITFIELD_DATA FALSE
+
+#if ( M68K_HAS_BFFFO == 1 )
+
+#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
+ asm volatile( "bfffo (%1),#0,#16,%0" : "=d" (_output) : "a" (&_value));
+#else
+
+/* duplicates BFFFO results for 16 bits (i.e., 15-(_priority) in
+ _CPU_Priority_bits_index is not needed), handles the 0 case, and
+ does not molest _value -- jsg */
+#if ( M68K_COLDFIRE_ARCH == 1 )
+#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
+ { \
+ extern const unsigned char __BFFFOtable[256]; \
+ register int dumby; \
+ \
+ asm volatile ( \
+ " clr.l %1\n" \
+ " move.w %2,%1\n" \
+ " lsr.l #8,%1\n" \
+ " beq.s 1f\n" \
+ " move.b (%3,%1),%0\n" \
+ " bra.s 0f\n" \
+ "1: move.w %2,%1\n" \
+ " move.b (%3,%1),%0\n" \
+ " addq.l #8,%0\n" \
+ "0: and.l #0xff,%0\n" \
+ : "=&d" ((_output)), "=&d" ((dumby)) \
+ : "d" ((_value)), "ao" ((__BFFFOtable)) \
+ : "cc" ) ; \
+ }
+#elif ( M68K_HAS_EXTB_L == 1 )
+#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
+ { \
+ extern const unsigned char __BFFFOtable[256]; \
+ register int dumby; \
+ \
+ asm volatile ( " move.w %2,%1\n" \
+ " lsr.w #8,%1\n" \
+ " beq.s 1f\n" \
+ " move.b (%3,%1.w),%0\n" \
+ " extb.l %0\n" \
+ " bra.s 0f\n" \
+ "1: moveq.l #8,%0\n" \
+ " add.b (%3,%2.w),%0\n" \
+ "0:\n" \
+ : "=&d" ((_output)), "=&d" ((dumby)) \
+ : "d" ((_value)), "ao" ((__BFFFOtable)) \
+ : "cc" ) ; \
+ }
+#else
+#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
+ { \
+ extern const unsigned char __BFFFOtable[256]; \
+ register int dumby; \
+ \
+ asm volatile ( " move.w %2,%1\n" \
+ " lsr.w #8,%1\n" \
+ " beq.s 1f\n" \
+ " move.b (%3,%1.w),%0\n" \
+ " and.l #0x000000ff,%0\n"\
+ " bra.s 0f\n" \
+ "1: moveq.l #8,%0\n" \
+ " add.b (%3,%2.w),%0\n" \
+ "0:\n" \
+ : "=&d" ((_output)), "=&d" ((dumby)) \
+ : "d" ((_value)), "ao" ((__BFFFOtable)) \
+ : "cc" ) ; \
+ }
+#endif
+
+#endif
+
+/* end of Bitfield handler macros */
+
+/*
+ * Priority handler macros
+ *
+ * These macros perform the following functions:
+ * + return a mask with the bit for this major/minor portion of
+ * of thread priority set.
+ * + translate the bit number returned by "Bitfield_find_first_bit"
+ * into an index into the thread ready chain bit maps
+ */
+
+#define _CPU_Priority_Mask( _bit_number ) \
+ ( 0x8000 >> (_bit_number) )
+
+#define _CPU_Priority_bits_index( _priority ) \
+ (_priority)
+
+/* end of Priority handler macros */
+
+/* functions */
+
+/*
+ * _CPU_Initialize
+ *
+ * This routine performs CPU dependent initialization.
+ */
+
+void _CPU_Initialize(
+ rtems_cpu_table *cpu_table,
+ void (*thread_dispatch)
+);
+
+/*
+ * _CPU_ISR_install_raw_handler
+ *
+ * This routine installs a "raw" interrupt handler directly into the
+ * processor's vector table.
+ */
+
+void _CPU_ISR_install_raw_handler(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+);
+
+/*
+ * _CPU_ISR_install_vector
+ *
+ * This routine installs an interrupt vector.
+ */
+
+void _CPU_ISR_install_vector(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+);
+
+/*
+ * _CPU_Install_interrupt_stack
+ *
+ * This routine installs the hardware interrupt stack pointer.
+ */
+
+void _CPU_Install_interrupt_stack( void );
+
+/*
+ * _CPU_Context_switch
+ *
+ * This routine switches from the run context to the heir context.
+ */
+
+void _CPU_Context_switch(
+ Context_Control *run,
+ Context_Control *heir
+);
+
+/*
+ * _CPU_Context_save_fp
+ *
+ * This routine saves the floating point context passed to it.
+ */
+
+void _CPU_Context_save_fp(
+ void **fp_context_ptr
+);
+
+/*
+ * _CPU_Context_restore_fp
+ *
+ * This routine restores the floating point context passed to it.
+ */
+
+void _CPU_Context_restore_fp(
+ void **fp_context_ptr
+);
+
+#if (M68K_HAS_FPSP_PACKAGE == 1)
+/*
+ * Hooks for the Floating Point Support Package (FPSP) provided by Motorola
+ *
+ * NOTES:
+ *
+ * Motorola 68k family CPU's before the 68040 used a coprocessor
+ * (68881 or 68882) to handle floating point. The 68040 has internal
+ * floating point support -- but *not* the complete support provided by
+ * the 68881 or 68882. The leftover functions are taken care of by the
+ * M68040 Floating Point Support Package. Quoting from the MC68040
+ * Microprocessors User's Manual, Section 9, Floating-Point Unit (MC68040):
+ *
+ * "When used with the M68040FPSP, the MC68040 FPU is fully
+ * compliant with IEEE floating-point standards."
+ *
+ * M68KFPSPInstallExceptionHandlers is in libcpu/m68k/MODEL/fpsp and
+ * is invoked early in the application code to insure that proper FP
+ * behavior is installed. This is not left to the BSP to call, since
+ * this would force all applications using that BSP to use FPSP which
+ * is not necessarily desirable.
+ *
+ * There is a similar package for the 68060 but RTEMS does not yet
+ * support the 68060.
+ */
+
+void M68KFPSPInstallExceptionHandlers (void);
+
+SCORE_EXTERN int (*_FPSP_install_raw_handler)(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+);
+
+#endif
+
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/m68k/rtems/score/m68k.h b/cpukit/score/cpu/m68k/rtems/score/m68k.h
new file mode 100644
index 0000000000..988d4687c7
--- /dev/null
+++ b/cpukit/score/cpu/m68k/rtems/score/m68k.h
@@ -0,0 +1,416 @@
+/* m68k.h
+ *
+ * This include file contains information pertaining to the Motorola
+ * m68xxx processor family.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __M68k_h
+#define __M68k_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This section contains the information required to build
+ * RTEMS for a particular member of the Motorola MC68xxx
+ * family. It does this by setting variables to indicate
+ * which implementation dependent features are present in
+ * a particular member of the family.
+ *
+ * Currently recognized:
+ * -m68000
+ * -m68000 -msoft-float
+ * -m68020
+ * -m68020 -msoft-float
+ * -m68030
+ * -m68040 -msoft-float
+ * -m68040
+ * -m68040 -msoft-float
+ * -m68060
+ * -m68060 -msoft-float
+ * -m68302 (no FP) (deprecated, use -m68000)
+ * -m68332 (no FP) (deprecated, use -mcpu32)
+ * -mcpu32 (no FP)
+ * -m5200 (no FP)
+ *
+ * As of gcc 2.8.1 and egcs 1.1, there is no distinction made between
+ * the CPU32 and CPU32+. The option -mcpu32 generates code which can
+ * be run on either core. RTEMS distinguishes between these two cores
+ * because they have different alignment rules which impact performance.
+ * If you are using a CPU32+, then the symbol RTEMS__mcpu32p__ should
+ * be defined in your custom file (see make/custom/gen68360.cfg for an
+ * example of how to do this. If gcc ever distinguishes between these
+ * two cores, then RTEMS__mcpu32p__ usage will be replaced with the
+ * appropriate compiler defined predefine.
+ *
+ * Here is some information on the 040 variants (courtesy of Doug McBride,
+ * mcbride@rodin.colorado.edu):
+ *
+ * "The 68040 is a superset of the 68EC040 and the 68LC040. The
+ * 68EC040 and 68LC040 do not have FPU's. The 68LC040 and the
+ * 68EC040 have renamed the DLE pin as JS0 which must be tied to
+ * Gnd or Vcc. The 68EC040 has renamed the MDIS pin as JS1. The
+ * 68EC040 has access control units instead of memory management units.
+ * The 68EC040 should not have the PFLUSH or PTEST instructions executed
+ * (cause an indeterminate result). The 68EC040 and 68LC040 do not
+ * implement the DLE or multiplexed bus modes. The 68EC040 does not
+ * implement the output buffer impedance selection mode of operation."
+ *
+ * M68K_HAS_EXTB_L is used to enable/disable usage of the extb.l instruction
+ * which is not available for 68000 or 68ec000 cores (68000, 68001, 68008,
+ * 68010, 68302, 68306, 68307). This instruction is available on the 68020
+ * up and the cpu32 based models.
+ *
+ * M68K_HAS_MISALIGNED is non-zero if the CPU allows byte-misaligned
+ * data access (68020, 68030, 68040, 68060, CPU32+).
+ *
+ * NOTE:
+ * Eventually it would be nice to evaluate doing a lot of this section
+ * by having each model specify which core it uses and then go from there.
+ */
+
+/*
+ * Figure out all CPU Model Feature Flags based upon compiler
+ * predefines. Notice the only exception to this is that
+ * gcc does not distinguish between CPU32 and CPU32+. This
+ * feature selection logic is setup such that if RTEMS__mcpu32p__
+ * is defined, then CPU32+ rules are used. Otherwise, the safe
+ * but less efficient CPU32 rules are used for the CPU32+.
+ */
+
+#if defined(__mc68020__)
+
+#define CPU_MODEL_NAME "m68020"
+#define M68K_HAS_VBR 1
+#define M68K_HAS_SEPARATE_STACKS 1
+#define M68K_HAS_BFFFO 1
+#define M68K_HAS_PREINDEXING 1
+#define M68K_HAS_EXTB_L 1
+#define M68K_HAS_MISALIGNED 1
+# if defined (__HAVE_68881__)
+# define M68K_HAS_FPU 1
+# define M68K_HAS_FPSP_PACKAGE 0
+# else
+# define M68K_HAS_FPU 0
+# define M68K_HAS_FPSP_PACKAGE 0
+# endif
+
+#elif defined(__mc68030__)
+
+#define CPU_MODEL_NAME "m68030"
+#define M68K_HAS_VBR 1
+#define M68K_HAS_SEPARATE_STACKS 1
+#define M68K_HAS_BFFFO 1
+#define M68K_HAS_PREINDEXING 1
+#define M68K_HAS_EXTB_L 1
+#define M68K_HAS_MISALIGNED 1
+# if defined (__HAVE_68881__)
+# define M68K_HAS_FPU 1
+# define M68K_HAS_FPSP_PACKAGE 0
+# else
+# define M68K_HAS_FPU 0
+# define M68K_HAS_FPSP_PACKAGE 0
+# endif
+
+#elif defined(__mc68040__)
+
+#define CPU_MODEL_NAME "m68040"
+#define M68K_HAS_VBR 1
+#define M68K_HAS_SEPARATE_STACKS 1
+#define M68K_HAS_BFFFO 1
+#define M68K_HAS_PREINDEXING 1
+#define M68K_HAS_EXTB_L 1
+#define M68K_HAS_MISALIGNED 1
+# if defined (__HAVE_68881__)
+# define M68K_HAS_FPU 1
+# define M68K_HAS_FPSP_PACKAGE 1
+# else
+# define M68K_HAS_FPU 0
+# define M68K_HAS_FPSP_PACKAGE 0
+# endif
+
+#elif defined(__mc68060__)
+
+#define CPU_MODEL_NAME "m68060"
+#define M68K_HAS_VBR 1
+#define M68K_HAS_SEPARATE_STACKS 0
+#define M68K_HAS_BFFFO 1
+#define M68K_HAS_PREINDEXING 1
+#define M68K_HAS_EXTB_L 1
+#define M68K_HAS_MISALIGNED 1
+# if defined (__HAVE_68881__)
+# define M68K_HAS_FPU 1
+# define M68K_HAS_FPSP_PACKAGE 0
+# else
+# define M68K_HAS_FPU 0
+# define M68K_HAS_FPSP_PACKAGE 0
+# endif
+
+#elif defined(__mc68302__)
+
+#define CPU_MODEL_NAME "m68302"
+#define M68K_HAS_VBR 0
+#define M68K_HAS_SEPARATE_STACKS 0
+#define M68K_HAS_BFFFO 0
+#define M68K_HAS_PREINDEXING 0
+#define M68K_HAS_EXTB_L 0
+#define M68K_HAS_MISALIGNED 0
+#define M68K_HAS_FPU 0
+#define M68K_HAS_FPSP_PACKAGE 0
+
+ /* gcc and egcs do not distinguish between CPU32 and CPU32+ */
+#elif defined(RTEMS__mcpu32p__)
+
+#define CPU_MODEL_NAME "mcpu32+"
+#define M68K_HAS_VBR 1
+#define M68K_HAS_SEPARATE_STACKS 0
+#define M68K_HAS_BFFFO 0
+#define M68K_HAS_PREINDEXING 1
+#define M68K_HAS_EXTB_L 1
+#define M68K_HAS_MISALIGNED 1
+#define M68K_HAS_FPU 0
+#define M68K_HAS_FPSP_PACKAGE 0
+
+#elif defined(__mcpu32__)
+
+#define CPU_MODEL_NAME "mcpu32"
+#define M68K_HAS_VBR 1
+#define M68K_HAS_SEPARATE_STACKS 0
+#define M68K_HAS_BFFFO 0
+#define M68K_HAS_PREINDEXING 1
+#define M68K_HAS_EXTB_L 1
+#define M68K_HAS_MISALIGNED 0
+#define M68K_HAS_FPU 0
+#define M68K_HAS_FPSP_PACKAGE 0
+
+#elif defined(__mcf5200__)
+/* Motorola ColdFire V2 core - RISC/68020 hybrid */
+#define CPU_MODEL_NAME "m5200"
+#define M68K_HAS_VBR 1
+#define M68K_HAS_BFFFO 0
+#define M68K_HAS_SEPARATE_STACKS 0
+#define M68K_HAS_PREINDEXING 0
+#define M68K_HAS_EXTB_L 1
+#define M68K_HAS_MISALIGNED 1
+#define M68K_HAS_FPU 0
+#define M68K_HAS_FPSP_PACKAGE 0
+#define M68K_COLDFIRE_ARCH 1
+
+#elif defined(__mc68000__)
+
+#define CPU_MODEL_NAME "m68000"
+#define M68K_HAS_VBR 0
+#define M68K_HAS_SEPARATE_STACKS 0
+#define M68K_HAS_BFFFO 0
+#define M68K_HAS_PREINDEXING 0
+#define M68K_HAS_EXTB_L 0
+#define M68K_HAS_MISALIGNED 0
+# if defined (__HAVE_68881__)
+# define M68K_HAS_FPU 1
+# define M68K_HAS_FPSP_PACKAGE 0
+# else
+# define M68K_HAS_FPU 0
+# define M68K_HAS_FPSP_PACKAGE 0
+# endif
+
+#else
+
+#error "Unsupported CPU model -- are you sure you're running a 68k compiler?"
+
+#endif
+
+#ifndef ASM
+#include <rtems/score/types.h>
+#endif
+
+/*
+ * If the above did not specify a ColdFire architecture, then set
+ * this flag to indicate that it is not a ColdFire CPU.
+ */
+
+#if !defined(M68K_COLDFIRE_ARCH)
+#define M68K_COLDFIRE_ARCH 0
+#endif
+
+/*
+ * Define the name of the CPU family.
+ */
+
+#if ( M68K_COLDFIRE_ARCH == 1 )
+ #define CPU_NAME "Motorola ColdFire"
+#else
+ #define CPU_NAME "Motorola MC68xxx"
+#endif
+
+#ifndef ASM
+
+#if ( M68K_COLDFIRE_ARCH == 1 )
+#define m68k_disable_interrupts( _level ) \
+ do { register uint32_t _tmpsr = 0x0700; \
+ asm volatile ( "move.w %%sr,%0\n\t" \
+ "or.l %0,%1\n\t" \
+ "move.w %1,%%sr" \
+ : "=d" (_level), "=d"(_tmpsr) : "1"(_tmpsr) ); \
+ } while( 0 )
+#else
+#define m68k_disable_interrupts( _level ) \
+ asm volatile ( "move.w %%sr,%0\n\t" \
+ "or.w #0x0700,%%sr" \
+ : "=d" (_level))
+#endif
+
+#define m68k_enable_interrupts( _level ) \
+ asm volatile ( "move.w %0,%%sr " : : "d" (_level));
+
+#if ( M68K_COLDFIRE_ARCH == 1 )
+#define m68k_flash_interrupts( _level ) \
+ do { register uint32_t _tmpsr = 0x0700; \
+ asm volatile ( "move.w %2,%%sr\n\t" \
+ "or.l %2,%1\n\t" \
+ "move.w %1,%%sr" \
+ : "=d"(_tmpsr) : "0"(_tmpsr), "d"(_level) ); \
+ } while( 0 )
+#else
+#define m68k_flash_interrupts( _level ) \
+ asm volatile ( "move.w %0,%%sr\n\t" \
+ "or.w #0x0700,%%sr" \
+ : : "d" (_level))
+#endif
+
+#define m68k_get_interrupt_level( _level ) \
+ do { \
+ register uint32_t _tmpsr; \
+ \
+ asm volatile( "move.w %%sr,%0" : "=d" (_tmpsr)); \
+ _level = (_tmpsr & 0x0700) >> 8; \
+ } while (0)
+
+#define m68k_set_interrupt_level( _newlevel ) \
+ do { \
+ register uint32_t _tmpsr; \
+ \
+ asm volatile( "move.w %%sr,%0" : "=d" (_tmpsr)); \
+ _tmpsr = (_tmpsr & 0xf8ff) | ((_newlevel) << 8); \
+ asm volatile( "move.w %0,%%sr" : : "d" (_tmpsr)); \
+ } while (0)
+
+#if ( M68K_HAS_VBR == 1 && M68K_COLDFIRE_ARCH == 0 )
+#define m68k_get_vbr( vbr ) \
+ asm volatile ( "movec %%vbr,%0 " : "=r" (vbr))
+
+#define m68k_set_vbr( vbr ) \
+ asm volatile ( "movec %0,%%vbr " : : "r" (vbr))
+
+#elif ( M68K_COLDFIRE_ARCH == 1 )
+#define m68k_get_vbr( _vbr ) _vbr = (void *)_VBR
+
+#define m68k_set_vbr( _vbr ) \
+ asm volatile ("move.l %%a7,%%d1 \n\t" \
+ "move.l %0,%%a7\n\t" \
+ "movec %%a7,%%vbr\n\t" \
+ "move.l %%d1,%%a7\n\t" \
+ : : "d" (_vbr) : "d1" );
+
+#else
+#define m68k_get_vbr( _vbr ) _vbr = (void *)_VBR
+#define m68k_set_vbr( _vbr )
+#endif
+
+/*
+ * The following routine swaps the endian format of an unsigned int.
+ * It must be static because it is referenced indirectly.
+ */
+#if ( M68K_COLDFIRE_ARCH == 1 )
+
+/* There are no rotate commands in Coldfire architecture. We will use
+ * generic implementation of endian swapping for Coldfire.
+ */
+static inline unsigned int m68k_swap_u32(
+ unsigned int value
+ )
+{
+ uint32_t byte1, byte2, byte3, byte4, swapped;
+
+ byte4 = (value >> 24) & 0xff;
+ byte3 = (value >> 16) & 0xff;
+ byte2 = (value >> 8) & 0xff;
+ byte1 = value & 0xff;
+
+ swapped = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
+ return( swapped );
+}
+
+static inline unsigned int m68k_swap_u16(
+ unsigned int value
+)
+{
+ return (((value & 0xff) << 8) | ((value >> 8) & 0xff));
+}
+
+#else
+
+static inline unsigned int m68k_swap_u32(
+ unsigned int value
+)
+{
+ unsigned int swapped = value;
+
+ asm volatile( "rorw #8,%0" : "=d" (swapped) : "0" (swapped) );
+ asm volatile( "swap %0" : "=d" (swapped) : "0" (swapped) );
+ asm volatile( "rorw #8,%0" : "=d" (swapped) : "0" (swapped) );
+
+ return( swapped );
+}
+
+static inline unsigned int m68k_swap_u16(
+ unsigned int value
+)
+{
+ unsigned short swapped = value;
+
+ asm volatile( "rorw #8,%0" : "=d" (swapped) : "0" (swapped) );
+
+ return( swapped );
+}
+#endif
+
+#define CPU_swap_u32( value ) m68k_swap_u32( value )
+#define CPU_swap_u16( value ) m68k_swap_u16( value )
+
+
+/*
+ * _CPU_virtual_to_physical
+ *
+ * DESCRIPTION:
+ *
+ * This function is used to map virtual addresses to physical
+ * addresses.
+ *
+ * FIXME: ASSUMES THAT VIRTUAL ADDRESSES ARE THE SAME AS THE
+ * PHYSICAL ADDRESSES
+ */
+static inline void * _CPU_virtual_to_physical (
+ const void * d_addr )
+{
+ return (void *) d_addr;
+}
+
+
+#endif /* !ASM */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __M68K_h */
+/* end of include file */
diff --git a/cpukit/score/cpu/m68k/rtems/score/types.h b/cpukit/score/cpu/m68k/rtems/score/types.h
new file mode 100644
index 0000000000..954e58a790
--- /dev/null
+++ b/cpukit/score/cpu/m68k/rtems/score/types.h
@@ -0,0 +1,57 @@
+/* m68ktypes.h
+ *
+ * This include file contains type definitions pertaining to the Motorola
+ * m68xxx processor family.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __M68k_TYPES_h
+#define __M68k_TYPES_h
+
+#ifndef ASM
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This section defines the basic types for this processor.
+ */
+
+typedef unsigned char unsigned8; /* unsigned 8-bit integer */
+typedef unsigned short unsigned16; /* unsigned 16-bit integer */
+typedef unsigned int unsigned32; /* unsigned 32-bit integer */
+typedef unsigned long long unsigned64; /* unsigned 64-bit integer */
+
+typedef unsigned16 Priority_Bit_map_control;
+
+typedef signed char signed8; /* 8-bit signed integer */
+typedef signed short signed16; /* 16-bit signed integer */
+typedef signed int signed32; /* 32-bit signed integer */
+typedef signed long long signed64; /* 64 bit signed integer */
+
+typedef unsigned32 boolean; /* Boolean value */
+
+typedef float single_precision; /* single precision float */
+typedef double double_precision; /* double precision float */
+
+typedef void m68k_isr;
+
+typedef void ( *m68k_isr_entry )( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !ASM */
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/m68k/sim.h b/cpukit/score/cpu/m68k/sim.h
new file mode 100644
index 0000000000..0ad5ba1653
--- /dev/null
+++ b/cpukit/score/cpu/m68k/sim.h
@@ -0,0 +1,333 @@
+/*
+ *-------------------------------------------------------------------
+ *
+ * SIM -- System Integration Module
+ *
+ * The system integration module (SIM) is used on many Motorola 16-
+ * and 32-bit MCUs for the following functions:
+ *
+ * () System configuration and protection. Bus and software watchdog
+ * monitors are provided in addition to periodic interrupt generators.
+ *
+ * () Clock signal generation for other intermodule bus (IMB) members
+ * and external devices.
+ *
+ * () The generation of chip-select signals that simplify external
+ * circuitry interface.
+ *
+ * () Data ports that are available for general purpose input and
+ * output.
+ *
+ * () A system test block that is intended only for factory tests.
+ *
+ * For more information, refer to Motorola's "Modular Microcontroller
+ * Family System Integration Module Reference Manual" (Motorola document
+ * SIMRM/AD).
+ *
+ * This file was created by John S. Gwynne to support Motorola's 68332 MCU.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the following conditions are met:
+ * 1. Redistribution of source code and documentation must retain
+ * the above authorship, this list of conditions and the
+ * following disclaimer.
+ * 2. 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 "AS IS" without warranty of any kind,
+ * either expressed or implied, including, but not limited to, the
+ * implied warranties of merchantability, title and fitness for a
+ * particular purpose.
+ *
+ *------------------------------------------------------------------
+ *
+ * $Id$
+ */
+
+#ifndef _SIM_H_
+#define _SIM_H_
+
+
+/* SAM-- shift and mask */
+#undef SAM
+#define SAM(a,b,c) ((a << b) & c)
+
+/*
+ * These macros make this file usable from assembly.
+ */
+
+#ifdef ASM
+#define SIM_VOLATILE_USHORT_POINTER
+#define SIM_VOLATILE_UCHAR_POINTER
+#else
+#define SIM_VOLATILE_USHORT_POINTER (volatile unsigned short int * const)
+#define SIM_VOLATILE_UCHAR_POINTER (volatile unsigned char * const)
+#endif
+
+/* SIM_CRB (SIM Control Register Block) base address of the SIM
+ control registers */
+#ifndef SIM_CRB
+#if SIM_MM == 0
+#define SIM_CRB 0x7ffa00
+#else /* SIM_MM */
+#undef SIM_MM
+#define SIM_MM 1
+#define SIM_CRB 0xfffa00
+#endif /* SIM_MM */
+#endif /* SIM_CRB */
+
+
+#define SIMCR SIM_VOLATILE_USHORT_POINTER(0x00 + SIM_CRB)
+ /* Module Configuration Register */
+#define EXOFF 0x8000 /* External Clock Off */
+#define FRZSW 0x4000 /* Freeze Software Enable */
+#define FRZBM 0x2000 /* Freeze Bus Monitor Enable */
+#define SLVEN 0x0800 /* Factory Test Model Enabled (ro)*/
+#define SHEN 0x0300 /* Show Cycle Enable */
+#define SUPV 0x0080 /* Supervisor/Unrestricted Data Space */
+#define MM 0x0040 /* Module Mapping */
+#define IARB 0x000f /* Interrupt Arbitration Field */
+
+
+
+#define SIMTR SIM_VOLATILE_USHORT_POINTER(0x02 + SIM_CRB)
+ /* SIM Test Register */
+/* Used only for factor testing */
+
+
+
+#define SYNCR SIM_VOLATILE_USHORT_POINTER(0x04 + SIM_CRB)
+ /* Clock Synthesizer Control Register */
+#define VCO 0x8000 /* Frequency Control (VCO) */
+#define PRESCALE 0x4000 /* Frequency Control Bit (Prescale) */
+#define COUNTER 0x3f00 /* Frequency Control Counter */
+#define EDIV 0x0080 /* ECLK Divide Rate */
+#define SLIMP 0x0010 /* Limp Mode Status */
+#define SLOCK 0x0008 /* Synthesizer Lock */
+#define RSTEN 0x0004 /* Reset Enable */
+#define STSIM 0x0002 /* Stop Mode SIM Clock */
+#define STEXT 0x0001 /* Stop Mode External Clock */
+
+
+
+#define RSR SIM_VOLATILE_UCHAR_POINTER(0x07 + SIM_CRB)
+ /* Reset Status Register */
+#define EXT 0x0080 /* External Reset */
+#define POW 0x0040 /* Power-On Reset */
+#define SW 0x0020 /* Software Watchdog Reset */
+#define DBF 0x0010 /* Double Bus Fault Reset */
+#define LOC 0x0004 /* Loss of Clock Reset */
+#define SYS 0x0002 /* System Reset */
+#define TST 0x0001 /* Test Submodule Reset */
+
+
+
+#define SIMTRE SIM_VOLATILE_USHORT_POINTER(0x08 + SIM_CRB)
+ /* System Integration Test Register */
+/* Used only for factor testing */
+
+
+
+#define PORTE0 SIM_VOLATILE_UCHAR_POINTER(0x11 + SIM_CRB)
+#define PORTE1 SIM_VOLATILE_UCHAR_POINTER(0x13 + SIM_CRB)
+ /* Port E Data Register */
+#define DDRE SIM_VOLATILE_UCHAR_POINTER(0x15 + SIM_CRB)
+ /* Port E Data Direction Register */
+#define PEPAR SIM_VOLATILE_UCHAR_POINTER(0x17 + SIM_CRB)
+ /* Port E Pin Assignment Register */
+/* Any bit cleared (zero) defines the corresponding pin to be an I/O
+ pin. Any bit set defines the corresponding pin to be a bus control
+ signal. */
+
+
+
+#define PORTF0 SIM_VOLATILE_UCHAR_POINTER(0x19 + SIM_CRB)
+#define PORTF1 SIM_VOLATILE_UCHAR_POINTER(0x1b + SIM_CRB)
+ /* Port F Data Register */
+#define DDRF SIM_VOLATILE_UCHAR_POINTER(0x1d + SIM_CRB)
+ /* Port E Data Direction Register */
+#define PFPAR SIM_VOLATILE_UCHAR_POINTER(0x1f + SIM_CRB)
+/* Any bit cleared (zero) defines the corresponding pin to be an I/O
+ pin. Any bit set defines the corresponding pin to be a bus control
+ signal. */
+
+
+
+#define SYPCR SIM_VOLATILE_UCHAR_POINTER(0x21 + SIM_CRB)
+/* !!! can write to only once after reset !!! */
+ /* System Protection Control Register */
+#define SWE 0x80 /* Software Watch Enable */
+#define SWP 0x40 /* Software Watchdog Prescale */
+#define SWT 0x30 /* Software Watchdog Timing */
+#define HME 0x08 /* Halt Monitor Enable */
+#define BME 0x04 /* Bus Monitor External Enable */
+#define BMT 0x03 /* Bus Monitor Timing */
+
+
+
+#define PICR SIM_VOLATILE_USHORT_POINTER(0x22 + SIM_CRB)
+ /* Periodic Interrupt Control Reg. */
+#define PIRQL 0x0700 /* Periodic Interrupt Request Level */
+#define PIV 0x00ff /* Periodic Interrupt Level */
+
+
+
+#define PITR SIM_VOLATILE_USHORT_POINTER(0x24 + SIM_CRB)
+ /* Periodic Interrupt Timer Register */
+#define PTP 0x0100 /* Periodic Timer Prescaler Control */
+#define PITM 0x00ff /* Periodic Interrupt Timing Modulus */
+
+
+
+#define SWSR SIM_VOLATILE_UCHAR_POINTER(0x27 + SIM_CRB)
+ /* Software Service Register */
+/* write 0x55 then 0xaa to service the software watchdog */
+
+
+
+#define TSTMSRA SIM_VOLATILE_USHORT_POINTER(0x30 + SIM_CRB)
+ /* Test Module Master Shift A */
+#define TSTMSRB SIM_VOLATILE_USHORT_POINTER(0x32 + SIM_CRB)
+ /* Test Module Master Shift A */
+#define TSTSC SIM_VOLATILE_USHORT_POINTER(0x34 + SIM_CRB)
+ /* Test Module Shift Count */
+#define TSTRC SIM_VOLATILE_USHORT_POINTER(0x36 + SIM_CRB)
+ /* Test Module Repetition Counter */
+#define CREG SIM_VOLATILE_USHORT_POINTER(0x38 + SIM_CRB)
+ /* Test Module Control */
+#define DREG SIM_VOLATILE_USHORT_POINTER(0x3a + SIM_CRB)
+ /* Test Module Distributed */
+/* Used only for factor testing */
+
+
+
+#define PORTC SIM_VOLATILE_UCHAR_POINTER(0x41 + SIM_CRB)
+ /* Port C Data */
+
+
+
+#define CSPAR0 SIM_VOLATILE_USHORT_POINTER(0x44 + SIM_CRB)
+ /* Chip Select Pin Assignment
+ Resgister 0 */
+/* CSPAR0 contains seven two-bit fields that determine the functions
+ of corresponding chip-select pins. CSPAR0[15:14] are not
+ used. These bits always read zero; write have no effect. CSPAR0 bit
+ 1 always reads one; writes to CSPAR0 bit 1 have no effect. */
+#define CSPAR1 SIM_VOLATILE_USHORT_POINTER(0x46 + SIM_CRB)
+ /* Chip Select Pin Assignment
+ Register 1 */
+/* CSPAR1 contains five two-bit fields that determine the finctions of
+ corresponding chip-select pins. CSPAR1[15:10] are not used. These
+ bits always read zero; writes have no effect. */
+/*
+ *
+ * Bit Field | Description
+ * ------------+---------------
+ * 00 | Discrete Output
+ * 01 | Alternate Function
+ * 10 | Chip Select (8-bit port)
+ * 11 | Chip Select (16-bit port)
+ */
+#define DisOut 0x0
+#define AltFun 0x1
+#define CS8bit 0x2
+#define CS16bit 0x3
+/*
+ *
+ * CSPARx Field |Chip Select Signal | Alternate Signal | Discrete Output
+ *-----------------+--------------------+--------------------+---------------*/
+#define CS_5 12 /* !CS5 | FC2 | PC2 */
+#define CS_4 10 /* !CS4 | FC1 | PC1 */
+#define CS_3 8 /* !CS3 | FC0 | PC0 */
+#define CS_2 6 /* !CS2 | !BGACK | */
+#define CS_1 4 /* !CS1 | !BG | */
+#define CS_0 2 /* !CS0 | !BR | */
+#define CSBOOT 0 /* !CSBOOT | | */
+/* | | | */
+#define CS_10 8 /* !CS10 | ADDR23 | ECLK */
+#define CS_9 6 /* !CS9 | ADDR22 | PC6 */
+#define CS_8 4 /* !CS8 | ADDR21 | PC5 */
+#define CS_7 2 /* !CS7 | ADDR20 | PC4 */
+#define CS_6 0 /* !CS6 | ADDR19 | PC3 */
+
+#define BS_2K 0x0
+#define BS_8K 0x1
+#define BS_16K 0x2
+#define BS_64K 0x3
+#define BS_128K 0x4
+#define BS_256K 0x5
+#define BS_512K 0x6
+#define BS_1M 0x7
+
+#define CSBARBT SIM_VOLATILE_USHORT_POINTER(0x48 + SIM_CRB)
+#define CSBAR0 SIM_VOLATILE_USHORT_POINTER(0x4c + SIM_CRB)
+#define CSBAR1 SIM_VOLATILE_USHORT_POINTER(0x50 + SIM_CRB)
+#define CSBAR2 SIM_VOLATILE_USHORT_POINTER(0x54 + SIM_CRB)
+#define CSBAR3 SIM_VOLATILE_USHORT_POINTER(0x58 + SIM_CRB)
+#define CSBAR4 SIM_VOLATILE_USHORT_POINTER(0x5c + SIM_CRB)
+#define CSBAR5 SIM_VOLATILE_USHORT_POINTER(0x60 + SIM_CRB)
+#define CSBAR6 SIM_VOLATILE_USHORT_POINTER(0x64 + SIM_CRB)
+#define CSBAR7 SIM_VOLATILE_USHORT_POINTER(0x68 + SIM_CRB)
+#define CSBAR8 SIM_VOLATILE_USHORT_POINTER(0x6c + SIM_CRB)
+#define CSBAR9 SIM_VOLATILE_USHORT_POINTER(0x70 + SIM_CRB)
+#define CSBAR10 SIM_VOLATILE_USHORT_POINTER(0x74 + SIM_CRB)
+
+#define MODE 0x8000
+#define Disable 0
+#define LowerByte 0x2000
+#define UpperByte 0x4000
+#define BothBytes 0x6000
+#define ReadOnly 0x0800
+#define WriteOnly 0x1000
+#define ReadWrite 0x1800
+#define SyncAS 0x0
+#define SyncDS 0x0400
+
+#define WaitStates_0 (0x0 << 6)
+#define WaitStates_1 (0x1 << 6)
+#define WaitStates_2 (0x2 << 6)
+#define WaitStates_3 (0x3 << 6)
+#define WaitStates_4 (0x4 << 6)
+#define WaitStates_5 (0x5 << 6)
+#define WaitStates_6 (0x6 << 6)
+#define WaitStates_7 (0x7 << 6)
+#define WaitStates_8 (0x8 << 6)
+#define WaitStates_9 (0x9 << 6)
+#define WaitStates_10 (0xa << 6)
+#define WaitStates_11 (0xb << 6)
+#define WaitStates_12 (0xc << 6)
+#define WaitStates_13 (0xd << 6)
+#define FastTerm (0xe << 6)
+#define External (0xf << 6)
+
+#define CPUSpace (0x0 << 4)
+#define UserSpace (0x1 << 4)
+#define SupSpace (0x2 << 4)
+#define UserSupSpace (0x3 << 4)
+
+#define IPLevel_any 0x0
+#define IPLevel_1 0x2
+#define IPLevel_2 0x4
+#define IPLevel_3 0x6
+#define IPLevel_4 0x8
+#define IPLevel_5 0xa
+#define IPLevel_6 0xc
+#define IPLevel_7 0xe
+
+#define AVEC 1
+
+#define CSORBT SIM_VOLATILE_USHORT_POINTER(0x4a + SIM_CRB)
+#define CSOR0 SIM_VOLATILE_USHORT_POINTER(0x4e + SIM_CRB)
+#define CSOR1 SIM_VOLATILE_USHORT_POINTER(0x52 + SIM_CRB)
+#define CSOR2 SIM_VOLATILE_USHORT_POINTER(0x56 + SIM_CRB)
+#define CSOR3 SIM_VOLATILE_USHORT_POINTER(0x5a + SIM_CRB)
+#define CSOR4 SIM_VOLATILE_USHORT_POINTER(0x5e + SIM_CRB)
+#define CSOR5 SIM_VOLATILE_USHORT_POINTER(0x62 + SIM_CRB)
+#define CSOR6 SIM_VOLATILE_USHORT_POINTER(0x66 + SIM_CRB)
+#define CSOR7 SIM_VOLATILE_USHORT_POINTER(0x6a + SIM_CRB)
+#define CSOR8 SIM_VOLATILE_USHORT_POINTER(0x6e + SIM_CRB)
+#define CSOR9 SIM_VOLATILE_USHORT_POINTER(0x72 + SIM_CRB)
+#define CSOR10 SIM_VOLATILE_USHORT_POINTER(0x76 + SIM_CRB)
+
+#endif /* _SIM_h_ */
diff --git a/cpukit/score/cpu/mips/.cvsignore b/cpukit/score/cpu/mips/.cvsignore
new file mode 100644
index 0000000000..282522db03
--- /dev/null
+++ b/cpukit/score/cpu/mips/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/cpukit/score/cpu/mips/ChangeLog b/cpukit/score/cpu/mips/ChangeLog
new file mode 100644
index 0000000000..b9a3b1954e
--- /dev/null
+++ b/cpukit/score/cpu/mips/ChangeLog
@@ -0,0 +1,501 @@
+2004-04-14 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ PR 605/bsps
+ * cpu.c: Remove further c++ style comments having been missed in
+ previous patch. Remove printf's entirely.
+
+2004-04-09 Joel Sherrill <joel@OARcorp.com>
+
+ PR 605/bsps
+ * cpu.c: Do not use C++ style comments.
+
+2004-04-06 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * configure.ac: Remove (Merged into $(top_srcdir)/configure.ac).
+ * Makefile.am: Don't include multilib.am.
+ Reflect merging configure.ac into $(top_srcdir)/configure.ac.
+
+2004-04-03 Art Ferrer <arturo.b.ferrer@nasa.gov>
+
+ PR 598/bsps
+ * cpu_asm.S, rtems/score/cpu.h: Add save of floating point
+ status/control register on context switches. Missing this register
+ was causing intermittent floating point errors.
+
+2004-04-02 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * Makefile.am: Install iregdefs.h and idtcpu.h to
+ $(includedir)/rtems/mips.
+ * cpu_asm.S: Include <rtems/mips/iregdef.h> instead of <iregdef.h>.
+ * rtems/score/mips.h, cpu_asm.S: Include <rtems/mips/idtcpu.h>
+ instead of <idtcpu.h>.
+
+2004-04-01 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * Makefile.am: Install asm.h to $(includedir)/rtems.
+
+2004-04-01 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * cpu_asm.S: Include <rtems/asm.h> instead of <asm.h>.
+
+2004-03-30 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * cpu.c, rtems/score/cpu.h: Convert to using c99 fixed size types.
+
+2004-03-29 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * configure.ac: RTEMS_TOP([../../../..]).
+
+2004-01-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Move RTEMS_TOP one subdir down.
+
+2004-01-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add PREINSTALL_DIRS.
+
+2004-01-14 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Re-add dirstamps to PREINSTALL_FILES.
+ Add PREINSTALL_FILES to CLEANFILES.
+
+2004-01-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Requires automake >= 1.8.1.
+
+2004-01-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include compile.am, again.
+
+2004-01-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Convert to using automake compilation rules.
+
+2004-01-07 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/mips.h: Removed junk revision line.
+
+2003-12-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use mkdir_p. Remove dirs from PREINSTALL_FILES.
+
+2003-12-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Require automake >= 1.8, autoconf >= 2.59.
+
+2003-12-01 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Remove TMPINSTALL_FILES.
+
+2003-11-30 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add $(dirstamp) to preinstallation rules.
+
+2003-11-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Don't use gmake rules for preinstallation.
+
+2003-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_CANONICAL_HOST.
+
+2003-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_CHECK_CPU.
+
+2003-09-26 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/cpu.h: Obsoleting HP PA-RISC port and removing all
+ references.
+
+2003-09-04 Joel Sherrill <joel@OARcorp.com>
+
+ * cpu.c, cpu_asm.S, rtems/score/cpu.h, rtems/score/mips.h,
+ rtems/score/types.h: URL for license changed.
+
+2003-08-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use rtems-bugs@rtems.com as bug report email address.
+
+2003-03-06 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove AC_CONFIG_AUX_DIR.
+
+2002-12-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Require autoconf-2.57 + automake-1.7.2.
+ * Makefile.am: Eliminate C_O_FILES, S_O_FILES, libscorecpu_a_OBJECTS.
+
+2002-11-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Fix package name.
+
+2002-11-04 Joel Sherrill <joel@OARcorp.com>
+
+ * idtcpu.h: Removed warning.
+
+2002-11-01 Joel Sherrill <joel@OARcorp.com>
+
+ * idtcpu.h: Removed warnings.
+
+2002-10-28 Joel Sherrill <joel@OARcorp.com>
+
+ * idtcpu.h: Removed warning by turning extra token at the end of
+ an endif into a comment.
+
+2002-10-25 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Add nostdinc to AM_INIT_AUTOMAKE.
+
+2002-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * .cvsignore: Reformat.
+ Add autom4te*cache.
+ Remove autom4te.cache.
+
+2002-08-14 Greg Menke <gregory.menke@gsfc.nasa.gov>
+
+ * cpu_asm.S: Clarified some comments, removed code that forced
+ SR_IEP on when returning from an interrupt.
+
+2002-06-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Add RTEMS_PROG_CCAS
+
+2002-06-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use AC_CONFIG_AUX_DIR(../../../..).
+ Add AC_PROG_RANLIB.
+
+2002-06-20 Greg Menke <gregory.menke@gsfc.nasa.gov>
+ * cpu_asm.S: Added SR_IEO to context restore to fix isr disabled
+ deadlock caused by interrupt arriving while dispatching.
+
+2002-06-17 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include $(top_srcdir)/../../../automake/*.am.
+ Use ../../../aclocal.
+
+2001-04-03 Joel Sherrill <joel@OARcorp.com>
+
+ * Per PR94, all rtems/score/CPUtypes.h are named rtems/score/types.h.
+ * rtems/score/mipstypes.h: Removed.
+ * rtems/score/types.h: New file via CVS magic.
+ * Makefile.am, rtems/score/cpu.h: Account for name change.
+
+2002-03-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac:
+ AC_INIT(package,_RTEMS_VERSION,_RTEMS_BUGS).
+ AM_INIT_AUTOMAKE([no-define foreign 1.6]).
+ * Makefile.am: Remove AUTOMAKE_OPTIONS.
+
+2002-03-20 Greg Menke <gregory.menke@gsfc.nasa.gov>
+
+ * cpu_asm.S: Now compiles on 4600 and 4650.
+
+2002-03-13 Greg Menke <gregory.menke@gsfc.nasa.gov>
+
+ * cpu_asm.S: Fixed a sneaky return from int w/ ints disabled bug.
+ * rtems/score/cpu.h: Fixed register numbering in comments and made
+ interrupt enable/disable more robust.
+
+2002-03-05 Greg Menke <gregory.menke@gsfc.nasa.gov>
+ * cpu_asm.S: Added support for the debug exception vector, cleaned
+ up the exception processing & exception return stuff. Re-added
+ EPC in the task context structure so the gdb stub will know where
+ a thread is executing. Should've left it there in the first place...
+ * idtcpu.h: Added support for the debug exception vector.
+ * cpu.c: Added ___exceptionTaskStack to hold a pointer to the
+ stack frame in an interrupt so context switch code can get the
+ userspace EPC when scheduling.
+ * rtems/score/cpu.h: Re-added EPC to the task context.
+
+2002-02-27 Greg Menke <gregory.menke@gsfc.nasa.gov>
+
+ * cpu_asm.S: Fixed exception return address, modified FP context
+ switch so FPU is properly enabled and also doesn't screw up the
+ exception FP handling.
+ * idtcpu.h: Added C0_TAR, the MIPS target address register used for
+ returning from exceptions.
+ * iregdef.h: Added R_TAR to the stack frame so the target address
+ can be saved on a per-exception basis. The new entry is past the
+ end of the frame gdb cares about, so doesn't affect gdb or cpu.h
+ stuff.
+ * rtems/score/cpu.h: added an #ifdef so cpu_asm.S can include it
+ to obtain FPU defines without syntax errors generated by the C
+ defintions.
+ * cpu.c: Improved interrupt level saves & restores.
+
+2002-02-08 Joel Sherrill <joel@OARcorp.com>
+
+ * iregdef.h, rtems/score/cpu.h: Reordered register in the
+ exception stack frame to better match gdb's expectations.
+
+2001-02-05 Joel Sherrill <joel@OARcorp.com>
+
+ * cpu_asm.S: Enhanced to save/restore more registers on
+ exceptions.
+ * rtems/score/cpu.h (CPU_Interrupt_frame): Enhanced to list every
+ register individually and document when it is saved.
+ * idtcpu.h: Added constants for the coprocessor 1 registers
+ revision and status.
+
+2001-02-05 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/Makefile.am, rtems/score/Makefile.am: Removed again.
+
+2001-02-04 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/cpu.h: IDLE task should not be FP. This was a mistake
+ in the previous patch that has now been confirmed.
+
+2001-02-01 Greg Menke <gregory.menke@gsfc.nasa.gov>
+
+ * cpu.c: Enhancements and fixes for modifying the SR when changing
+ the interrupt level.
+ * cpu_asm.S: Fixed handling of FP enable bit so it is properly
+ managed on a per-task basis, improved handling of interrupt levels,
+ and made deferred FP contexts work on the MIPS.
+ * rtems/score/cpu.h: Modified to support above changes.
+
+2002-01-28 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/Makefile.am: Removed.
+ * rtems/score/Makefile.am: Removed.
+ * configure.ac: Reflect changes above.
+ * Makefile.am: Reflect changes above.
+
+2002-02-09 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * asm.h: Remove #include <rtems/score/targopts.h>.
+ Add #include <rtems/score/cpuopts.h>.
+ * configure.ac: Remove RTEMS_CHECK_CUSTOM_BSP(RTEMS_BSP).
+
+
+2001-12-20 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use RTEMS_ENV_RTEMSCPU.
+
+2001-12-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add multilib support.
+
+2001-11-28 Joel Sherrill <joel@OARcorp.com>,
+
+ This was tracked as PR91.
+ * rtems/score/cpu.h: Added CPU_PROVIDES_ISR_IS_IN_PROGRESS macro which
+ is used to specify if the port uses the standard macro for this (FALSE).
+ A TRUE setting indicates the port provides its own implementation.
+
+2001-10-12 Joel Sherrill <joel@OARcorp.com>
+
+ * cpu_asm.S: _CPU_Context_save_fp in was incorrectly in conditional
+ compilation block with (CPU_HARDWARE_FP == FALSE). Reported by
+ Wayne Bullaughey <wayne@wmi.com>.
+
+2001-10-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * .cvsignore: Add autom4te.cache for autoconf > 2.52.
+ * configure.in: Remove.
+ * configure.ac: New file, generated from configure.in by autoupdate.
+
+2001-09-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/score/Makefile.am: Use 'PREINSTALL_FILES ='.
+ * Makefile.am: Use 'PREINSTALL_FILES ='.
+
+2001-07-03 Joel Sherrill <joel@OARcorp.com>
+
+ * cpu.c: Fixed typo.
+
+2000-05-24 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/mips.h: Added constants for MIPS exception numbers.
+ All exceptions should be given low numbers and thus can be installed
+ and processed in a uniform manner. Variances between various MIPS
+ ISA levels were not accounted for.
+
+2001-05-24 Greg Menke <gregory.menke@gsfc.nasa.gov>
+
+ * Assisted in design and debug by Joel Sherrill <joel@OARcorp.com>.
+ * cpu_asm.S: Now works on Mongoose-V. Missed in previous patch.
+
+2001-05-22 Greg Menke <gregory.menke@gsfc.nasa.gov>
+
+ * rtems/score/cpu.h: Add the interrupt stack structure and enhance
+ the context initialization to account for floating point tasks.
+ * rtems/score/mips.h: Added the routines mips_set_cause(),
+ mips_get_fcr31(), and mips_set_fcr31().
+ * Assisted in design and debug by Joel Sherrill <joel@OARcorp.com>.
+
+2001-05-07 Joel Sherrill <joel@OARcorp.com>
+
+ * cpu_asm.S: Merged patches from Gregory Menke
+ <Gregory.D.Menke.1@gsfc.nasa.gov> that clean up
+ stack usage and include nops in the delay slots.
+
+2001-04-20 Joel Sherrill <joel@OARcorp.com>
+
+ * cpu_asm.S: Added code to save and restore SR and EPC to
+ properly support nested interrupts. Note that the ISR
+ (not RTEMS) enables interrupts allowing the nesting to occur.
+
+2001-03-14 Joel Sherrill <joel@OARcorp.com>
+
+ * cpu.c, rtems/score/cpu.h, rtems/score/mipstypes.h:
+ Removed unused variable _CPU_Thread_dispatch_pointer
+ and cleaned numerous comments.
+
+2001-03-13 Joel Sherrill <joel@OARcorp.com>
+
+ * cpu.c, cpu_asm.S, iregdef.h, rtems/score/cpu.h, rtems/score/mips.h:
+ Merged MIPS1 and MIPS3 code reducing the number of lines of assembly.
+ Also reimplemented some assembly routines in C further reducing
+ the amount of assembly and increasing maintainability.
+
+2001-02-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am, rtems/score/Makefile.am:
+ Apply include_*HEADERS instead of H_FILES.
+
+2001-01-12 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/mips.h (mips_get_sr, mips_set_sr): Corrected
+ register constraints from "general" to "register".
+
+2001-01-09 Joel Sherrill <joel@OARcorp.com>
+
+ * cpu_asm.S: Use SR_INTERRUPT_ENABLE_BITS instead of SR_XXX constants
+ to make it easier to conditionalize the code for various ISA levels.
+
+2001-01-08 Joel Sherrill <joel@OARcorp.com>
+
+ * idtcpu.h: Commented out definition of "wait". It was stupid to
+ use such a common word as a macro.
+ * rtems/score/cpu.h (_CPU_ISR_Disable): Fixed for mips ISA 3.
+ * rtems/score/mips.h: Added include of <idtcpu.h>.
+ * rtems/score/mips.h (mips_enable_in_interrupt_mask): Corrected.
+
+2001-01-03 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/cpu.h: Added _CPU_Initialize_vectors().
+ * cpu_asm.S: Eliminated warning for duplicate definition of EXTERN.
+
+2000-12-19 Joel Sherrill <joel@OARcorp.com>
+
+ * cpu_asm.S (_ISR_Handler): Return to the address in the EPC register.
+ Previous code resulting in the interrupted immediately returning
+ to the caller of the routine it was inside.
+
+2000-12-19 Joel Sherrill <joel@OARcorp.com>
+
+ * cpu.c (_CPU_Initialize): Do not initialize _ISR_Vector_table() here
+ because it has not been allocated yet.
+
+2000-12-13 Joel Sherrill <joel@OARcorp.com>
+
+ * cpu.c: Removed duplicate declaration for _ISR_Vector_table.
+ * cpu_asm.S: Removed assembly language to vector ISR handler
+ on MIPS ISA I. Now call mips_vector_isr_handlers() in libcpu or BSP.
+ * rtems/score/cpu.h (CPU_INTERRUPT_NUMBER_OF_VECTORS): No
+ longer a constant -- get the real value from libcpu.
+
+2000-12-13 Joel Sherrill <joel@OARcorp.com>
+
+ * cpu_asm.h: Removed.
+ * Makefile.am: Remove cpu_asm.h.
+ * rtems/score/mips64orion.h: Renamed mips.h.
+ * rtems/score/mips.h: New file, formerly mips64orion.h.
+ Header rewritten.
+ (mips_get_sr, mips_set_sr, mips_enable_in_interrupt_mask,
+ mips_disable_in_interrupt_mask): New macros.
+ * rtems/score/Makefile.am: Reflect renaming mips64orion.h.
+ * asm.h: Include <mips.h> not <mips64orion.h>. Now includes the
+ few defines that were in <cpu_asm.h>.
+ * cpu.c (_CPU_ISR_Get_level): Added MIPS ISA I version of this routine.
+ MIPS ISA 3 is still in assembly for now.
+ (_CPU_Thread_Idle_body): Rewrote in C.
+ * cpu_asm.S: Rewrote file header.
+ (FRAME,ENDFRAME) now in asm.h.
+ (_CPU_ISR_Get_level): Removed ISA I version and rewrote in C.
+ (_CPU_ISR_Set_level): Removed ISA I version and rewrote in C.
+ (_CPU_Context_switch): MIPS ISA I now manages preserves SR_IEC and
+ leaves other bits in SR alone on task switch.
+ (mips_enable_interrupts,mips_disable_interrupts,
+ mips_enable_global_interrupts,mips_disable_global_interrupts,
+ disable_int, enable_int): Removed.
+ (mips_get_sr): Rewritten as C macro.
+ (_CPU_Thread_Idle_body): Rewritten in C.
+ (init_exc_vecs): Rewritten in C as mips_install_isr_entries() and
+ placed in libcpu.
+ (exc_tlb_code, exc_xtlb_code, exc_cache_code, exc_norm_code): Moved
+ to libcpu/mips/shared/interrupts.
+ (general): Cleaned up comment blocks and #if 0 areas.
+ * idtcpu.h: Made ifdef report an error.
+ * iregdef.h: Removed warning.
+ * rtems/score/cpu.h (CPU_INTERRUPT_NUMBER_OF_VECTORS): Now a variable
+ number defined by libcpu.
+ (_CPU_ISR_Disable, _CPU_ISR_Enable): Rewritten to use new routines
+ to access SR.
+ (_CPU_ISR_Set_level): Rewritten as macro for ISA I.
+ (_CPU_Context_Initialize): Honor ISR level in task initialization.
+ (_CPU_Fatal_halt): Use new _CPU_ISR_Disable() macro.
+
+2000-12-06 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/cpu.h: When mips ISA level is 1, registers in the
+ context should be 32 not 64 bits.
+
+2000-11-30 Joel Sherrill <joel@OARcorp.com>
+
+ * cpu_asm.S: Changed "_CPU_Ccontext_switch_restore: typo to
+ correct name of _CPU_Context_switch_restore. Added dummy
+ version of exc_utlb_code() so applications would link.
+
+2000-11-09 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use ... instead of RTEMS_TOPdir in ACLOCAL_AMFLAGS.
+
+2000-11-02 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Switch to ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal.
+
+2000-10-25 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: ACLOCAL_AMFLAGS= -I $(RTEMS_TOPdir)/macros.
+ Switch to GNU canonicalization.
+
+2000-10-24 Alan Cudmore <alanc@linuxstart.com> and
+ Joel Sherrill <joel@OARcorp.com>
+
+ * This is a major reworking of the mips64orion port to use
+ gcc predefines as much as possible and a big push to multilib
+ the mips port. The mips64orion port was copied/renamed to mips
+ to be more like other GNU tools. Alan did most of the technical
+ work of determining how to map old macro names used by the mips64orion
+ port to standard compiler macro definitions. Joel did the merge
+ with CVS magic to keep individual file history and did the BSP
+ modifications. Details follow:
+ * Makefile.am: idtmon.h in mips64orion port not present.
+ * asm.h: MIPS64ORION replaced with MIPS. Frame setup macros added.
+ * cpu.c: Comments added.
+ * cpu_asm.S: Conditionals changed. MIPS ISA level 1 support added.
+ First attempt at exception/interrupt processing for ISA level 1
+ and minus any use of IDT/MON added.
+ * idtcpu.h: Conditionals changed to use gcc predefines.
+ * iregdef.h: Ditto.
+ * cpu_asm.h: No real change. Merger required commit.
+ * rtems/Makefile.am: Ditto.
+ * rtems/score/Makefile.am: Ditto.
+ * rtems/score/cpu.h: Change MIPS64ORION to MIPS.
+ * rtems/score/mips64orion.h: Change MIPS64ORION to MIPS. Convert
+ from using RTEMS_CPU_MODEL to gcc predefines to figre things out.
+
+2000-09-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include compile.am.
+
+2000-08-10 Joel Sherrill <joel@OARcorp.com>
+
+ * ChangeLog: New file.
diff --git a/cpukit/score/cpu/mips/Makefile.am b/cpukit/score/cpu/mips/Makefile.am
new file mode 100644
index 0000000000..04613e3922
--- /dev/null
+++ b/cpukit/score/cpu/mips/Makefile.am
@@ -0,0 +1,74 @@
+##
+## $Id$
+##
+
+include $(top_srcdir)/automake/compile.am
+
+include_rtemsdir = $(includedir)/rtems
+include_rtems_HEADERS = asm.h
+
+include_rtems_mipsdir = $(includedir)/rtems/mips
+include_rtems_mips_HEADERS = idtcpu.h iregdef.h
+
+include_rtems_scoredir = $(includedir)/rtems/score
+include_rtems_score_HEADERS = rtems/score/cpu.h rtems/score/mips.h \
+ rtems/score/types.h
+
+EXTRA_LIBRARIES = libscorecpu.a
+CLEANFILES = libscorecpu.a
+libscorecpu_a_SOURCES = cpu.c cpu_asm.S
+libscorecpu_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libscorecpu_g.a
+CLEANFILES += libscorecpu_g.a
+libscorecpu_g_a_SOURCES = $(libscorecpu_a_SOURCES)
+libscorecpu_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+all-local: $(PREINSTALL_FILES) libscorecpu$(LIB_VARIANT).a
+
+PREINSTALL_DIRS =
+PREINSTALL_FILES =
+
+$(PROJECT_INCLUDE)/rtems/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems
+ @: > $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/asm.h: asm.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/asm.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/asm.h
+
+$(PROJECT_INCLUDE)/rtems/mips/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems/mips
+ @: > $(PROJECT_INCLUDE)/rtems/mips/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/mips/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/mips/idtcpu.h: idtcpu.h $(PROJECT_INCLUDE)/rtems/mips/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/mips/idtcpu.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/mips/idtcpu.h
+
+$(PROJECT_INCLUDE)/rtems/mips/iregdef.h: iregdef.h $(PROJECT_INCLUDE)/rtems/mips/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/mips/iregdef.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/mips/iregdef.h
+
+$(PROJECT_INCLUDE)/rtems/score/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems/score
+ @: > $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/score/cpu.h: rtems/score/cpu.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/cpu.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/cpu.h
+
+$(PROJECT_INCLUDE)/rtems/score/mips.h: rtems/score/mips.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/mips.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/mips.h
+
+$(PROJECT_INCLUDE)/rtems/score/types.h: rtems/score/types.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/types.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/types.h
+
+CLEANFILES += $(PREINSTALL_FILES)
+DISTCLEANFILES = $(PREINSTALL_DIRS)
+
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/score/cpu/mips/asm.h b/cpukit/score/cpu/mips/asm.h
new file mode 100644
index 0000000000..eb0c7c1efc
--- /dev/null
+++ b/cpukit/score/cpu/mips/asm.h
@@ -0,0 +1,158 @@
+/* asm.h
+ *
+ * This include file attempts to address the problems
+ * caused by incompatible flavors of assemblers and
+ * toolsets. It primarily addresses variations in the
+ * use of leading underscores on symbols and the requirement
+ * that register names be preceded by a %.
+ *
+ *
+ * NOTE: The spacing in the use of these macros
+ * is critical to them working as advertised.
+ *
+ * COPYRIGHT:
+ *
+ * This file is based on similar code found in newlib available
+ * from ftp.cygnus.com. The file which was used had no copyright
+ * notice. This file is freely distributable as long as the source
+ * of the file is noted. This file is:
+ *
+ * COPYRIGHT (c) 1994-1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * $Id$
+ */
+/* @(#)asm.h 03/15/96 1.1 */
+
+#ifndef __NO_CPU_ASM_h
+#define __NO_CPU_ASM_h
+
+/*
+ * Indicate we are in an assembly file and get the basic CPU definitions.
+ */
+
+#ifndef ASM
+#define ASM
+#endif
+#include <rtems/score/cpuopts.h>
+#include <rtems/score/mips.h>
+
+/*
+ * Recent versions of GNU cpp define variables which indicate the
+ * need for underscores and percents. If not using GNU cpp or
+ * the version does not support this, then you will obviously
+ * have to define these as appropriate.
+ */
+
+#ifndef __USER_LABEL_PREFIX__
+#define __USER_LABEL_PREFIX__ _
+#endif
+
+#ifndef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__
+#endif
+
+/* ANSI concatenation macros. */
+
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+/* Use the right prefix for global labels. */
+
+#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+
+/* Use the right prefix for registers. */
+
+#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
+
+/*
+ * define macros for all of the registers on this CPU
+ *
+ * EXAMPLE: #define d0 REG (d0)
+ */
+
+/*
+ * Define macros to handle section beginning and ends.
+ */
+
+
+#define BEGIN_CODE_DCL .text
+#define END_CODE_DCL
+#define BEGIN_DATA_DCL .data
+#define END_DATA_DCL
+#define BEGIN_CODE .text
+#define END_CODE
+#define BEGIN_DATA
+#define END_DATA
+#define BEGIN_BSS
+#define END_BSS
+#define END
+
+/*
+ * Following must be tailor for a particular flavor of the C compiler.
+ * They may need to put underscores in front of the symbols.
+ */
+
+#define PUBLIC(sym) .globl SYM (sym)
+#define EXTERN(sym) .globl SYM (sym)
+
+/*
+ * Debugger macros for assembly language routines. Allows the
+ * programmer to set up the necessary stack frame info
+ * required by debuggers to do stack traces.
+ */
+
+#ifndef XDS
+#define FRAME(name,frm_reg,offset,ret_reg) \
+ .globl name; \
+ .ent name; \
+name:; \
+ .frame frm_reg,offset,ret_reg
+#define ENDFRAME(name) \
+ .end name
+#else
+#define FRAME(name,frm_reg,offset,ret_reg) \
+ .globl _##name;\
+_##name:
+#define ENDFRAME(name)
+#endif XDS
+
+/*
+ * Hardware Floating Point Registers
+ */
+
+#define R_FP0 0
+#define R_FP1 1
+#define R_FP2 2
+#define R_FP3 3
+#define R_FP4 4
+#define R_FP5 5
+#define R_FP6 6
+#define R_FP7 7
+#define R_FP8 8
+#define R_FP9 9
+#define R_FP10 10
+#define R_FP11 11
+#define R_FP12 12
+#define R_FP13 13
+#define R_FP14 14
+#define R_FP15 15
+#define R_FP16 16
+#define R_FP17 17
+#define R_FP18 18
+#define R_FP19 19
+#define R_FP20 20
+#define R_FP21 21
+#define R_FP22 22
+#define R_FP23 23
+#define R_FP24 24
+#define R_FP25 25
+#define R_FP26 26
+#define R_FP27 27
+#define R_FP28 28
+#define R_FP29 29
+#define R_FP30 30
+#define R_FP31 31
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/mips/cpu.c b/cpukit/score/cpu/mips/cpu.c
new file mode 100644
index 0000000000..c84b738cf2
--- /dev/null
+++ b/cpukit/score/cpu/mips/cpu.c
@@ -0,0 +1,275 @@
+/*
+ * Mips CPU Dependent Source
+ *
+ * 2002: Greg Menke (gregory.menke@gsfc.nasa.gov)
+ * Overhauled interrupt level and interrupt enable/disable code
+ * to more exactly support MIPS. Our mods were for MIPS1 processors
+ * MIPS3 ports are affected, though apps written to the old behavior
+ * should still work OK.
+ *
+ * Conversion to MIPS port by Alan Cudmore <alanc@linuxstart.com> and
+ * Joel Sherrill <joel@OARcorp.com>.
+ *
+ * These changes made the code conditional on standard cpp predefines,
+ * merged the mips1 and mips3 code sequences as much as possible,
+ * and moved some of the assembly code to C. Alan did much of the
+ * initial analysis and rework. Joel took over from there and
+ * wrote the JMR3904 BSP so this could be tested. Joel also
+ * added the new interrupt vectoring support in libcpu and
+ * tried to better support the various interrupt controllers.
+ *
+ * Original MIP64ORION port by Craig Lebakken <craigl@transition.com>
+ * COPYRIGHT (c) 1996 by Transition Networks Inc.
+ *
+ * To anyone who acknowledges that this file is provided "AS IS"
+ * without any express or implied warranty:
+ * permission to use, copy, modify, and distribute this file
+ * for any purpose is hereby granted without fee, provided that
+ * the above copyright notice and this notice appears in all
+ * copies, and that the name of Transition Networks not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ * Transition Networks makes no representations about the
+ * suitability of this software for any purpose.
+ *
+ * COPYRIGHT (c) 1989-2001.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/wkspace.h>
+
+
+
+
+/*
+** local dword used in cpu_asm to pass the exception stack frame to the
+** context switch code.
+*/
+unsigned __exceptionStackFrame = 0;
+
+
+
+
+
+/* _CPU_Initialize
+ *
+ * This routine performs processor dependent initialization.
+ *
+ * INPUT PARAMETERS:
+ * cpu_table - CPU table to initialize
+ * thread_dispatch - address of disptaching routine
+ */
+
+
+void _CPU_Initialize(
+ rtems_cpu_table *cpu_table,
+ void (*thread_dispatch) /* ignored on this CPU */
+)
+{
+ /*
+ * If there is not an easy way to initialize the FP context
+ * during Context_Initialize, then it is usually easier to
+ * save an "uninitialized" FP context here and copy it to
+ * the task's during Context_Initialize.
+ */
+
+ /* FP context initialization support goes here */
+
+ _CPU_Table = *cpu_table;
+}
+
+/*PAGE
+ *
+ * _CPU_ISR_Get_level
+ *
+ * This routine returns the current interrupt level.
+ */
+
+uint32_t _CPU_ISR_Get_level( void )
+{
+ unsigned int sr;
+
+ mips_get_sr(sr);
+
+#if __mips == 3
+/* EXL bit and shift down hardware ints into bits 1 thru 6 */
+ sr = ((sr & SR_EXL) >> 1) | ((sr & 0xfc00) >> 9);
+
+#elif __mips == 1
+/* IEC bit and shift down hardware ints into bits 1 thru 6 */
+ sr = (sr & SR_IEC) | ((sr & 0xfc00) >> 9);
+
+#else
+#error "CPU ISR level: unknown MIPS level for SR handling"
+#endif
+ return sr;
+}
+
+
+void _CPU_ISR_Set_level( uint32_t new_level )
+{
+ unsigned int sr, srbits;
+
+ /*
+ ** mask off the int level bits only so we can
+ ** preserve software int settings and FP enable
+ ** for this thread. Note we don't force software ints
+ ** enabled when changing level, they were turned on
+ ** when this task was created, but may have been turned
+ ** off since, so we'll just leave them alone.
+ */
+
+ new_level &= 0xff;
+
+ mips_get_sr(sr);
+
+#if __mips == 3
+ mips_set_sr( (sr & ~SR_IE) ); /* first disable ie bit (recommended) */
+
+ srbits = sr & ~(0xfc00 | SR_EXL | SR_IE);
+
+ sr = srbits | ((new_level==0)? (0xfc00 | SR_EXL | SR_IE): \
+ (((new_level<<9) & 0xfc00) | \
+ (new_level & 1)?(SR_EXL | SR_IE):0));
+/*
+ if ( (new_level & SR_EXL) == (sr & SR_EXL) )
+ return;
+
+ if ( (new_level & SR_EXL) == 0 ) {
+ sr &= ~SR_EXL; * clear the EXL bit *
+ mips_set_sr(sr);
+ } else {
+
+ sr |= SR_EXL|SR_IE; * enable exception level *
+ mips_set_sr(sr); * first disable ie bit (recommended) *
+ }
+*/
+
+#elif __mips == 1
+ mips_set_sr( (sr & ~SR_IEC) );
+ srbits = sr & ~(0xfc00 | SR_IEC);
+ sr = srbits | ((new_level==0)?0xfc01:( ((new_level<<9) & 0xfc00) | \
+ (new_level & SR_IEC)));
+#else
+#error "CPU ISR level: unknown MIPS level for SR handling"
+#endif
+ mips_set_sr( sr );
+}
+
+
+
+/*PAGE
+ *
+ * _CPU_ISR_install_raw_handler
+ *
+ * Input parameters:
+ * vector - interrupt vector number
+ * old_handler - former ISR for this vector number
+ * new_handler - replacement ISR for this vector number
+ *
+ * Output parameters: NONE
+ *
+ */
+
+void _CPU_ISR_install_raw_handler(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+)
+{
+ /*
+ * This is where we install the interrupt handler into the "raw" interrupt
+ * table used by the CPU to dispatch interrupt handlers.
+ *
+ * Because all interrupts are vectored through the same exception handler
+ * this is not necessary on thi sport.
+ */
+}
+
+/*PAGE
+ *
+ * _CPU_ISR_install_vector
+ *
+ * This kernel routine installs the RTEMS handler for the
+ * specified vector.
+ *
+ * Input parameters:
+ * vector - interrupt vector number
+ * old_handler - former ISR for this vector number
+ * new_handler - replacement ISR for this vector number
+ *
+ * Output parameters: NONE
+ *
+ */
+
+void _CPU_ISR_install_vector(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+)
+{
+ *old_handler = _ISR_Vector_table[ vector ];
+
+ /*
+ * If the interrupt vector table is a table of pointer to isr entry
+ * points, then we need to install the appropriate RTEMS interrupt
+ * handler for this vector number.
+ */
+
+ _CPU_ISR_install_raw_handler( vector, _ISR_Handler, old_handler );
+
+ /*
+ * We put the actual user ISR address in '_ISR_vector_table'. This will
+ * be used by the _ISR_Handler so the user gets control.
+ */
+
+ _ISR_Vector_table[ vector ] = new_handler;
+}
+
+/*PAGE
+ *
+ * _CPU_Install_interrupt_stack
+ */
+
+void _CPU_Install_interrupt_stack( void )
+{
+/* we don't support this yet */
+}
+
+/*PAGE
+ *
+ * _CPU_Internal_threads_Idle_thread_body
+ *
+ * NOTES:
+ *
+ * 1. This is the same as the regular CPU independent algorithm.
+ *
+ * 2. If you implement this using a "halt", "idle", or "shutdown"
+ * instruction, then don't forget to put it in an infinite loop.
+ *
+ * 3. Be warned. Some processors with onboard DMA have been known
+ * to stop the DMA if the CPU were put in IDLE mode. This might
+ * also be a problem with other on-chip peripherals. So use this
+ * hook with caution.
+ */
+
+void _CPU_Thread_Idle_body( void )
+{
+#if __mips == 3
+ for( ; ; )
+ asm volatile("wait"); /* use wait to enter low power mode */
+#elif __mips == 1
+ for( ; ; )
+ ;
+#else
+#error "IDLE: __mips not set to 1 or 3"
+#endif
+}
diff --git a/cpukit/score/cpu/mips/cpu_asm.S b/cpukit/score/cpu/mips/cpu_asm.S
new file mode 100644
index 0000000000..17b00c3301
--- /dev/null
+++ b/cpukit/score/cpu/mips/cpu_asm.S
@@ -0,0 +1,1088 @@
+/*
+ * This file contains the basic algorithms for all assembly code used
+ * in an specific CPU port of RTEMS. These algorithms must be implemented
+ * in assembly language
+ *
+ * History:
+ * Baseline: no_cpu
+ * 1996: Ported to MIPS64ORION by Craig Lebakken <craigl@transition.com>
+ * COPYRIGHT (c) 1996 by Transition Networks Inc.
+ * To anyone who acknowledges that the modifications to this file to
+ * port it to the MIPS64ORION are provided "AS IS" without any
+ * express or implied warranty:
+ * permission to use, copy, modify, and distribute this file
+ * for any purpose is hereby granted without fee, provided that
+ * the above copyright notice and this notice appears in all
+ * copies, and that the name of Transition Networks not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. Transition
+ * Networks makes no representations about the suitability
+ * of this software for any purpose.
+ * 2000: Reworked by Alan Cudmore <alanc@linuxstart.com> to become
+ * the baseline of the more general MIPS port.
+ * 2001: Joel Sherrill <joel@OARcorp.com> continued this rework,
+ * rewriting as much as possible in C and added the JMR3904 BSP
+ * so testing could be performed on a simulator.
+ * 2001: Greg Menke <gregory.menke@gsfc.nasa.gov>, bench tested ISR
+ * performance, tweaking this code and the isr vectoring routines
+ * to reduce overhead & latencies. Added optional
+ * instrumentation as well.
+ * 2002: Greg Menke <gregory.menke@gsfc.nasa.gov>, overhauled cpu_asm.S,
+ * cpu.c and cpu.h to manage FP vs int only tasks, interrupt levels
+ * and deferred FP contexts.
+ * 2002: Joel Sherrill <joel@OARcorp.com> enhanced the exception processing
+ * by increasing the amount of context saved/restored.
+ * 2004: 24March, Art Ferrer, NASA/GSFC, added save of FP status/control
+ * register to fix intermittent FP error encountered on ST5 mission
+ * implementation on Mongoose V processor.
+ *
+ * COPYRIGHT (c) 1989-2002.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/asm.h>
+#include <rtems/mips/iregdef.h>
+#include <rtems/mips/idtcpu.h>
+
+#define ASSEMBLY_ONLY
+#include <rtems/score/cpu.h>
+
+
+/* enable debugging shadow writes to misc ram, this is a vestigal
+* Mongoose-ism debug tool- but may be handy in the future so we
+* left it in...
+*/
+
+/* #define INSTRUMENT_ISR_VECTORING */
+/* #define INSTRUMENT_EXECUTING_THREAD */
+
+
+
+/* Ifdefs prevent the duplication of code for MIPS ISA Level 3 ( R4xxx )
+ * and MIPS ISA Level 1 (R3xxx).
+ */
+
+#if __mips == 3
+/* 64 bit register operations */
+#define NOP
+#define ADD dadd
+#define STREG sd
+#define LDREG ld
+#define MFCO dmfc0
+#define MTCO dmtc0
+#define ADDU addu
+#define ADDIU addiu
+#define R_SZ 8
+#define F_SZ 8
+#define SZ_INT 8
+#define SZ_INT_POW2 3
+
+/* XXX if we don't always want 64 bit register ops, then another ifdef */
+
+#elif __mips == 1
+/* 32 bit register operations*/
+#define NOP nop
+#define ADD add
+#define STREG sw
+#define LDREG lw
+#define MFCO mfc0
+#define MTCO mtc0
+#define ADDU add
+#define ADDIU addi
+#define R_SZ 4
+#define F_SZ 4
+#define SZ_INT 4
+#define SZ_INT_POW2 2
+#else
+#error "mips assembly: what size registers do I deal with?"
+#endif
+
+
+#define ISR_VEC_SIZE 4
+#define EXCP_STACK_SIZE (NREGS*R_SZ)
+
+
+#ifdef __GNUC__
+#define ASM_EXTERN(x,size) .extern x,size
+#else
+#define ASM_EXTERN(x,size)
+#endif
+
+/* NOTE: these constants must match the Context_Control structure in cpu.h */
+#define S0_OFFSET 0
+#define S1_OFFSET 1
+#define S2_OFFSET 2
+#define S3_OFFSET 3
+#define S4_OFFSET 4
+#define S5_OFFSET 5
+#define S6_OFFSET 6
+#define S7_OFFSET 7
+#define SP_OFFSET 8
+#define FP_OFFSET 9
+#define RA_OFFSET 10
+#define C0_SR_OFFSET 11
+#define C0_EPC_OFFSET 12
+
+/* NOTE: these constants must match the Context_Control_fp structure in cpu.h */
+#define FP0_OFFSET 0
+#define FP1_OFFSET 1
+#define FP2_OFFSET 2
+#define FP3_OFFSET 3
+#define FP4_OFFSET 4
+#define FP5_OFFSET 5
+#define FP6_OFFSET 6
+#define FP7_OFFSET 7
+#define FP8_OFFSET 8
+#define FP9_OFFSET 9
+#define FP10_OFFSET 10
+#define FP11_OFFSET 11
+#define FP12_OFFSET 12
+#define FP13_OFFSET 13
+#define FP14_OFFSET 14
+#define FP15_OFFSET 15
+#define FP16_OFFSET 16
+#define FP17_OFFSET 17
+#define FP18_OFFSET 18
+#define FP19_OFFSET 19
+#define FP20_OFFSET 20
+#define FP21_OFFSET 21
+#define FP22_OFFSET 22
+#define FP23_OFFSET 23
+#define FP24_OFFSET 24
+#define FP25_OFFSET 25
+#define FP26_OFFSET 26
+#define FP27_OFFSET 27
+#define FP28_OFFSET 28
+#define FP29_OFFSET 29
+#define FP30_OFFSET 30
+#define FP31_OFFSET 31
+#define FPCS_OFFSET 32
+
+
+ASM_EXTERN(__exceptionStackFrame, SZ_INT)
+
+
+
+/*
+ * _CPU_Context_save_fp_context
+ *
+ * This routine is responsible for saving the FP context
+ * at *fp_context_ptr. If the point to load the FP context
+ * from is changed then the pointer is modified by this routine.
+ *
+ * Sometimes a macro implementation of this is in cpu.h which dereferences
+ * the ** and a similarly named routine in this file is passed something
+ * like a (Context_Control_fp *). The general rule on making this decision
+ * is to avoid writing assembly language.
+ */
+
+/* void _CPU_Context_save_fp(
+ * void **fp_context_ptr
+ * );
+ */
+
+#if ( CPU_HARDWARE_FP == TRUE )
+FRAME(_CPU_Context_save_fp,sp,0,ra)
+ .set noreorder
+ .set noat
+
+ /*
+ ** Make sure the FPU is on before we save state. This code
+ ** is here because the FPU context switch might occur when an
+ ** integer task is switching out with a FP task switching in.
+ */
+ MFC0 t0,C0_SR
+ li t2,SR_CU1
+ move t1,t0
+ or t0,t2 /* turn on the fpu */
+#if __mips == 3
+ li t2,SR_EXL | SR_IE
+#elif __mips == 1
+ li t2,SR_IEC
+#endif
+ not t2
+ and t0,t2 /* turn off interrupts */
+ MTC0 t0,C0_SR
+
+ ld a1,(a0)
+ move t0,ra
+ jal _CPU_Context_save_fp_from_exception
+ NOP
+
+ /*
+ ** Reassert the task's state because we've not saved it yet.
+ */
+ MTC0 t1,C0_SR
+ j t0
+ NOP
+
+ .globl _CPU_Context_save_fp_from_exception
+_CPU_Context_save_fp_from_exception:
+ swc1 $f0,FP0_OFFSET*F_SZ(a1)
+ swc1 $f1,FP1_OFFSET*F_SZ(a1)
+ swc1 $f2,FP2_OFFSET*F_SZ(a1)
+ swc1 $f3,FP3_OFFSET*F_SZ(a1)
+ swc1 $f4,FP4_OFFSET*F_SZ(a1)
+ swc1 $f5,FP5_OFFSET*F_SZ(a1)
+ swc1 $f6,FP6_OFFSET*F_SZ(a1)
+ swc1 $f7,FP7_OFFSET*F_SZ(a1)
+ swc1 $f8,FP8_OFFSET*F_SZ(a1)
+ swc1 $f9,FP9_OFFSET*F_SZ(a1)
+ swc1 $f10,FP10_OFFSET*F_SZ(a1)
+ swc1 $f11,FP11_OFFSET*F_SZ(a1)
+ swc1 $f12,FP12_OFFSET*F_SZ(a1)
+ swc1 $f13,FP13_OFFSET*F_SZ(a1)
+ swc1 $f14,FP14_OFFSET*F_SZ(a1)
+ swc1 $f15,FP15_OFFSET*F_SZ(a1)
+ swc1 $f16,FP16_OFFSET*F_SZ(a1)
+ swc1 $f17,FP17_OFFSET*F_SZ(a1)
+ swc1 $f18,FP18_OFFSET*F_SZ(a1)
+ swc1 $f19,FP19_OFFSET*F_SZ(a1)
+ swc1 $f20,FP20_OFFSET*F_SZ(a1)
+ swc1 $f21,FP21_OFFSET*F_SZ(a1)
+ swc1 $f22,FP22_OFFSET*F_SZ(a1)
+ swc1 $f23,FP23_OFFSET*F_SZ(a1)
+ swc1 $f24,FP24_OFFSET*F_SZ(a1)
+ swc1 $f25,FP25_OFFSET*F_SZ(a1)
+ swc1 $f26,FP26_OFFSET*F_SZ(a1)
+ swc1 $f27,FP27_OFFSET*F_SZ(a1)
+ swc1 $f28,FP28_OFFSET*F_SZ(a1)
+ swc1 $f29,FP29_OFFSET*F_SZ(a1)
+ swc1 $f30,FP30_OFFSET*F_SZ(a1)
+ swc1 $f31,FP31_OFFSET*F_SZ(a1)
+ cfc1 a0,$31 /* Read FP status/conrol reg */
+ cfc1 a0,$31 /* Two reads clear pipeline */
+ NOP
+ NOP
+ sw a0, FPCS_OFFSET*F_SZ(a1) /* Store value to FPCS location */
+ NOP
+ j ra
+ NOP
+ .set at
+ENDFRAME(_CPU_Context_save_fp)
+#endif
+
+/*
+ * _CPU_Context_restore_fp_context
+ *
+ * This routine is responsible for restoring the FP context
+ * at *fp_context_ptr. If the point to load the FP context
+ * from is changed then the pointer is modified by this routine.
+ *
+ * Sometimes a macro implementation of this is in cpu.h which dereferences
+ * the ** and a similarly named routine in this file is passed something
+ * like a (Context_Control_fp *). The general rule on making this decision
+ * is to avoid writing assembly language.
+ */
+
+/* void _CPU_Context_restore_fp(
+ * void **fp_context_ptr
+ * )
+ */
+
+#if ( CPU_HARDWARE_FP == TRUE )
+FRAME(_CPU_Context_restore_fp,sp,0,ra)
+ .set noat
+ .set noreorder
+
+ /*
+ ** Make sure the FPU is on before we retrieve state. This code
+ ** is here because the FPU context switch might occur when an
+ ** integer task is switching out with a FP task switching in.
+ */
+ MFC0 t0,C0_SR
+ li t2,SR_CU1
+ move t1,t0
+ or t0,t2 /* turn on the fpu */
+#if __mips == 3
+ li t2,SR_EXL | SR_IE
+#elif __mips == 1
+ li t2,SR_IEC
+#endif
+ not t2
+ and t0,t2 /* turn off interrupts */
+ MTC0 t0,C0_SR
+
+ ld a1,(a0)
+ move t0,ra
+ jal _CPU_Context_restore_fp_from_exception
+ NOP
+
+ /*
+ ** Reassert the old task's state because we've not restored the
+ ** new one yet.
+ */
+ MTC0 t1,C0_SR
+ j t0
+ NOP
+
+ .globl _CPU_Context_restore_fp_from_exception
+_CPU_Context_restore_fp_from_exception:
+ lwc1 $f0,FP0_OFFSET*4(a1)
+ lwc1 $f1,FP1_OFFSET*4(a1)
+ lwc1 $f2,FP2_OFFSET*4(a1)
+ lwc1 $f3,FP3_OFFSET*4(a1)
+ lwc1 $f4,FP4_OFFSET*4(a1)
+ lwc1 $f5,FP5_OFFSET*4(a1)
+ lwc1 $f6,FP6_OFFSET*4(a1)
+ lwc1 $f7,FP7_OFFSET*4(a1)
+ lwc1 $f8,FP8_OFFSET*4(a1)
+ lwc1 $f9,FP9_OFFSET*4(a1)
+ lwc1 $f10,FP10_OFFSET*4(a1)
+ lwc1 $f11,FP11_OFFSET*4(a1)
+ lwc1 $f12,FP12_OFFSET*4(a1)
+ lwc1 $f13,FP13_OFFSET*4(a1)
+ lwc1 $f14,FP14_OFFSET*4(a1)
+ lwc1 $f15,FP15_OFFSET*4(a1)
+ lwc1 $f16,FP16_OFFSET*4(a1)
+ lwc1 $f17,FP17_OFFSET*4(a1)
+ lwc1 $f18,FP18_OFFSET*4(a1)
+ lwc1 $f19,FP19_OFFSET*4(a1)
+ lwc1 $f20,FP20_OFFSET*4(a1)
+ lwc1 $f21,FP21_OFFSET*4(a1)
+ lwc1 $f22,FP22_OFFSET*4(a1)
+ lwc1 $f23,FP23_OFFSET*4(a1)
+ lwc1 $f24,FP24_OFFSET*4(a1)
+ lwc1 $f25,FP25_OFFSET*4(a1)
+ lwc1 $f26,FP26_OFFSET*4(a1)
+ lwc1 $f27,FP27_OFFSET*4(a1)
+ lwc1 $f28,FP28_OFFSET*4(a1)
+ lwc1 $f29,FP29_OFFSET*4(a1)
+ lwc1 $f30,FP30_OFFSET*4(a1)
+ lwc1 $f31,FP31_OFFSET*4(a1)
+ cfc1 a0,$31 /* Read from FP status/control reg */
+ cfc1 a0,$31 /* Two reads clear pipeline */
+ NOP /* NOPs ensure execution */
+ NOP
+ lw a0,FPCS_OFFSET*4(a1) /* Load saved FPCS value */
+ NOP
+ ctc1 a0,$31 /* Restore FPCS register */
+ NOP
+ j ra
+ NOP
+ .set at
+ENDFRAME(_CPU_Context_restore_fp)
+#endif
+
+/* _CPU_Context_switch
+ *
+ * This routine performs a normal non-FP context switch.
+ */
+
+/* void _CPU_Context_switch(
+ * Context_Control *run,
+ * Context_Control *heir
+ * )
+ */
+
+FRAME(_CPU_Context_switch,sp,0,ra)
+ .set noreorder
+
+ MFC0 t0,C0_SR
+#if __mips == 3
+ li t1,SR_EXL | SR_IE
+#elif __mips == 1
+ li t1,SR_IEC
+#endif
+ STREG t0,C0_SR_OFFSET*R_SZ(a0) /* save the task's SR */
+ not t1
+ and t0,t1 /* mask off interrupts while we context switch */
+ MTC0 t0,C0_SR
+ NOP
+
+ STREG ra,RA_OFFSET*R_SZ(a0) /* save current context */
+ STREG sp,SP_OFFSET*R_SZ(a0)
+ STREG fp,FP_OFFSET*R_SZ(a0)
+ STREG s0,S0_OFFSET*R_SZ(a0)
+ STREG s1,S1_OFFSET*R_SZ(a0)
+ STREG s2,S2_OFFSET*R_SZ(a0)
+ STREG s3,S3_OFFSET*R_SZ(a0)
+ STREG s4,S4_OFFSET*R_SZ(a0)
+ STREG s5,S5_OFFSET*R_SZ(a0)
+ STREG s6,S6_OFFSET*R_SZ(a0)
+ STREG s7,S7_OFFSET*R_SZ(a0)
+
+
+ /*
+ ** this code grabs the userspace EPC if we're dispatching from
+ ** an interrupt frame or supplies the address of the dispatch
+ ** routines if not. This is entirely for the gdbstub's benefit so
+ ** it can know where each task is running.
+ **
+ ** Its value is only set when calling threadDispatch from
+ ** the interrupt handler and is cleared immediately when this
+ ** routine gets it.
+ */
+
+ la t0,__exceptionStackFrame /* see if we're coming in from an exception */
+ LDREG t1, (t0)
+ NOP
+ beqz t1,1f
+
+ STREG zero, (t0) /* and clear it */
+ NOP
+ LDREG t0,R_EPC*R_SZ(t1) /* get the userspace EPC from the frame */
+ b 2f
+
+1: la t0,_Thread_Dispatch /* if ==0, we're switched out */
+
+2: STREG t0,C0_EPC_OFFSET*R_SZ(a0)
+
+
+_CPU_Context_switch_restore:
+ LDREG ra,RA_OFFSET*R_SZ(a1) /* restore context */
+ LDREG sp,SP_OFFSET*R_SZ(a1)
+ LDREG fp,FP_OFFSET*R_SZ(a1)
+ LDREG s0,S0_OFFSET*R_SZ(a1)
+ LDREG s1,S1_OFFSET*R_SZ(a1)
+ LDREG s2,S2_OFFSET*R_SZ(a1)
+ LDREG s3,S3_OFFSET*R_SZ(a1)
+ LDREG s4,S4_OFFSET*R_SZ(a1)
+ LDREG s5,S5_OFFSET*R_SZ(a1)
+ LDREG s6,S6_OFFSET*R_SZ(a1)
+ LDREG s7,S7_OFFSET*R_SZ(a1)
+
+ LDREG t0, C0_SR_OFFSET*R_SZ(a1)
+
+// NOP
+//#if __mips == 3
+// andi t0,SR_EXL
+// bnez t0,_CPU_Context_1 /* set exception level from restore context */
+// li t0,~SR_EXL
+// MFC0 t1,C0_SR
+// NOP
+// and t1,t0
+// MTC0 t1,C0_SR
+//
+//#elif __mips == 1
+//
+// andi t0,(SR_INTERRUPT_ENABLE_BITS) /* we know 0 disabled */
+// beq t0,$0,_CPU_Context_1 /* set level from restore context */
+// MFC0 t0,C0_SR
+// NOP
+// or t0,(SR_INTERRUPT_ENABLE_BITS) /* new_sr = old sr with enabled */
+// MTC0 t0,C0_SR /* set with enabled */
+// NOP
+
+
+/*
+** Incorporate the incoming task's FP coprocessor state and interrupt mask/enable
+** into the status register. We jump thru the requisite hoops to ensure we
+** maintain all other SR bits as global values.
+**
+** Get the task's FPU enable, int mask & int enable bits. Although we keep the
+** software int enables on a per-task basis, the rtems_task_create
+** Interrupt Level & int level manipulation functions cannot enable/disable them,
+** so they are automatically enabled for all tasks. To turn them off, a task
+** must itself manipulate the SR register.
+**
+** Although something of a hack on this processor, we treat the SR register
+** int enables as the RTEMS interrupt level. We use the int level
+** value as a bitmask, not as any sort of greater than/less than metric.
+** Manipulation of a task's interrupt level directly corresponds to manipulation
+** of that task's SR bits, as seen in cpu.c
+**
+** Note, interrupts are disabled before context is saved, though the task's
+** interrupt enable state is recorded. The task swapping in will apply its
+** specific SR bits, including interrupt enable. If further task-specific
+** SR bits are arranged, it is this code, the cpu.c interrupt level stuff and
+** cpu.h task initialization code that will be affected.
+*/
+
+ li t2,SR_CU1
+ or t2,SR_IMASK
+
+ /* int enable bits */
+#if __mips == 3
+ or t2,SR_EXL + SR_IE
+#elif __mips == 1
+ /*
+ ** Save current, previous & old int enables. This is key because
+ ** we can dispatch from within the stack frame used by an
+ ** interrupt service. The int enables nest, but not beyond
+ ** previous and old because of the dispatch interlock seen
+ ** in the interrupt processing code
+ */
+ or t2,SR_IEC + SR_IEP + SR_IEO
+#endif
+ and t0,t2 /* keep only the per-task bits */
+
+ MFC0 t1,C0_SR /* grab the current SR */
+ not t2
+ and t1,t2 /* mask off the old task's bits */
+ or t1,t0 /* or in the new task's bits */
+ MTC0 t1,C0_SR /* and load the new SR */
+ NOP
+
+/* _CPU_Context_1: */
+ j ra
+ NOP
+ENDFRAME(_CPU_Context_switch)
+
+
+/*
+ * _CPU_Context_restore
+ *
+ * This routine is generally used only to restart self in an
+ * efficient manner. It may simply be a label in _CPU_Context_switch.
+ *
+ * NOTE: May be unnecessary to reload some registers.
+ *
+ * void _CPU_Context_restore(
+ * Context_Control *new_context
+ * );
+ */
+
+FRAME(_CPU_Context_restore,sp,0,ra)
+ .set noreorder
+ move a1,a0
+ j _CPU_Context_switch_restore
+ NOP
+
+ENDFRAME(_CPU_Context_restore)
+
+
+ASM_EXTERN(_ISR_Nest_level, SZ_INT)
+ASM_EXTERN(_Thread_Dispatch_disable_level,SZ_INT)
+ASM_EXTERN(_Context_Switch_necessary,SZ_INT)
+ASM_EXTERN(_ISR_Signals_to_thread_executing,SZ_INT)
+ASM_EXTERN(_Thread_Executing,SZ_INT)
+
+.extern _Thread_Dispatch
+.extern _ISR_Vector_table
+
+
+
+
+
+/* void _DBG_Handler()
+ *
+ * This routine services the (at least) MIPS1 debug vector,
+ * only used the the hardware debugging features. This code,
+ * while optional, is best located here because its intrinsically
+ * associated with exceptions in general & thus tied pretty
+ * closely to _ISR_Handler.
+ *
+ */
+
+
+FRAME(_DBG_Handler,sp,0,ra)
+ .set noreorder
+ la k0,_ISR_Handler
+ j k0
+ NOP
+ .set reorder
+ENDFRAME(_DBG_Handler)
+
+
+
+
+
+/* void __ISR_Handler()
+ *
+ * This routine provides the RTEMS interrupt management.
+ *
+ * void _ISR_Handler()
+ *
+ *
+ * This discussion ignores a lot of the ugly details in a real
+ * implementation such as saving enough registers/state to be
+ * able to do something real. Keep in mind that the goal is
+ * to invoke a user's ISR handler which is written in C and
+ * uses a certain set of registers.
+ *
+ * Also note that the exact order is to a large extent flexible.
+ * Hardware will dictate a sequence for a certain subset of
+ * _ISR_Handler while requirements for setting
+ *
+ * At entry to "common" _ISR_Handler, the vector number must be
+ * available. On some CPUs the hardware puts either the vector
+ * number or the offset into the vector table for this ISR in a
+ * known place. If the hardware does not give us this information,
+ * then the assembly portion of RTEMS for this port will contain
+ * a set of distinct interrupt entry points which somehow place
+ * the vector number in a known place (which is safe if another
+ * interrupt nests this one) and branches to _ISR_Handler.
+ *
+ */
+
+FRAME(_ISR_Handler,sp,0,ra)
+ .set noreorder
+
+ /* Q: _ISR_Handler, not using IDT/SIM ...save extra regs? */
+
+ /* wastes a lot of stack space for context?? */
+ ADDIU sp,sp,-EXCP_STACK_SIZE
+
+ STREG ra, R_RA*R_SZ(sp) /* store ra on the stack */
+ STREG v0, R_V0*R_SZ(sp)
+ STREG v1, R_V1*R_SZ(sp)
+ STREG a0, R_A0*R_SZ(sp)
+ STREG a1, R_A1*R_SZ(sp)
+ STREG a2, R_A2*R_SZ(sp)
+ STREG a3, R_A3*R_SZ(sp)
+ STREG t0, R_T0*R_SZ(sp)
+ STREG t1, R_T1*R_SZ(sp)
+ STREG t2, R_T2*R_SZ(sp)
+ STREG t3, R_T3*R_SZ(sp)
+ STREG t4, R_T4*R_SZ(sp)
+ STREG t5, R_T5*R_SZ(sp)
+ STREG t6, R_T6*R_SZ(sp)
+ STREG t7, R_T7*R_SZ(sp)
+ mflo t0
+ STREG t8, R_T8*R_SZ(sp)
+ STREG t0, R_MDLO*R_SZ(sp)
+ STREG t9, R_T9*R_SZ(sp)
+ mfhi t0
+ STREG gp, R_GP*R_SZ(sp)
+ STREG t0, R_MDHI*R_SZ(sp)
+ STREG fp, R_FP*R_SZ(sp)
+
+ .set noat
+ STREG AT, R_AT*R_SZ(sp)
+ .set at
+
+ MFC0 t0,C0_SR
+ MFC0 t1,C0_EPC
+ STREG t0,R_SR*R_SZ(sp)
+ STREG t1,R_EPC*R_SZ(sp)
+
+
+#ifdef INSTRUMENT_EXECUTING_THREAD
+ lw t2, _Thread_Executing
+ NOP
+ sw t2, 0x8001FFF0
+#endif
+
+ /* determine if an interrupt generated this exception */
+
+ MFC0 t0,C0_CAUSE
+ NOP
+
+ and t1,t0,CAUSE_EXCMASK
+ beq t1, 0, _ISR_Handler_1
+
+_ISR_Handler_Exception:
+
+ /* If we return from the exception, it is assumed nothing
+ * bad is going on and we can continue to run normally.
+ * But we want to save the entire CPU context so exception
+ * handlers can look at it and change it.
+ *
+ * NOTE: This is the path the debugger stub will take.
+ */
+
+ /* already got t0 = cause in the interrupt test above */
+ STREG t0,R_CAUSE*R_SZ(sp)
+
+ STREG sp, R_SP*R_SZ(sp)
+
+ STREG s0,R_S0*R_SZ(sp) /* save s0 - s7 */
+ STREG s1,R_S1*R_SZ(sp)
+ STREG s2,R_S2*R_SZ(sp)
+ STREG s3,R_S3*R_SZ(sp)
+ STREG s4,R_S4*R_SZ(sp)
+ STREG s5,R_S5*R_SZ(sp)
+ STREG s6,R_S6*R_SZ(sp)
+ STREG s7,R_S7*R_SZ(sp)
+
+ /* CP0 special registers */
+
+#if __mips == 1
+ MFC0 t0,C0_TAR
+#endif
+ MFC0 t1,C0_BADVADDR
+
+#if __mips == 1
+ STREG t0,R_TAR*R_SZ(sp)
+#else
+ NOP
+#endif
+ STREG t1,R_BADVADDR*R_SZ(sp)
+
+#if ( CPU_HARDWARE_FP == TRUE )
+ MFC0 t0,C0_SR /* FPU is enabled, save state */
+ NOP
+ srl t0,t0,16
+ andi t0,t0,(SR_CU1 >> 16)
+ beqz t0, 1f
+ NOP
+
+ la a1,R_F0*R_SZ(sp)
+ jal _CPU_Context_save_fp_from_exception
+ NOP
+ MFC1 t0,C1_REVISION
+ MFC1 t1,C1_STATUS
+ STREG t0,R_FEIR*R_SZ(sp)
+ STREG t1,R_FCSR*R_SZ(sp)
+
+1:
+#endif
+
+ move a0,sp
+ jal mips_vector_exceptions
+ NOP
+
+
+ /*
+ ** note, if the exception vector returns, rely on it to have
+ ** adjusted EPC so we will return to some correct address. If
+ ** this is not done, we might get stuck in an infinite loop because
+ ** we'll return to the instruction where the exception occured and
+ ** it could throw again.
+ **
+ ** It is expected the only code using the exception processing is
+ ** either the gdb stub or some user code which is either going to
+ ** panic or do something useful. Regardless, it is up to each
+ ** exception routine to properly adjust EPC, so the code below
+ ** may be helpful for doing just that.
+ */
+
+/* *********************************************************************
+** this code follows the R3000's exception return logic, but is not
+** needed because the gdb stub does it for us. It might be useful
+** for something else at some point...
+**
+ * compute the address of the instruction we'll return to *
+
+ LDREG t1, R_CAUSE*R_SZ(sp)
+ LDREG t0, R_EPC*R_SZ(sp)
+
+ * first see if the exception happened in the delay slot *
+ li t3,CAUSE_BD
+ AND t4,t1,t3
+ beqz t4,excnodelay
+ NOP
+
+ * it did, now see if the branch occured or not *
+ li t3,CAUSE_BT
+ AND t4,t1,t3
+ beqz t4,excnobranch
+ NOP
+
+ * branch was taken, we resume at the branch target *
+ LDREG t0, R_TAR*R_SZ(sp)
+ j excreturn
+ NOP
+
+excnobranch:
+ ADDU t0,R_SZ
+
+excnodelay:
+ ADDU t0,R_SZ
+
+excreturn:
+ STREG t0, R_EPC*R_SZ(sp)
+ NOP
+********************************************************************* */
+
+
+ /* if we're returning into mips_break, move to the next instruction */
+
+ LDREG t0,R_EPC*R_SZ(sp)
+ la t1,mips_break
+ xor t2,t0,t1
+ bnez t2,3f
+
+ addu t0,R_SZ
+ STREG t0,R_EPC*R_SZ(sp)
+ NOP
+3:
+
+
+
+
+#if ( CPU_HARDWARE_FP == TRUE )
+ MFC0 t0,C0_SR /* FPU is enabled, restore state */
+ NOP
+ srl t0,t0,16
+ andi t0,t0,(SR_CU1 >> 16)
+ beqz t0, 2f
+ NOP
+
+ la a1,R_F0*R_SZ(sp)
+ jal _CPU_Context_restore_fp_from_exception
+ NOP
+ LDREG t0,R_FEIR*R_SZ(sp)
+ LDREG t1,R_FCSR*R_SZ(sp)
+ MTC1 t0,C1_REVISION
+ MTC1 t1,C1_STATUS
+2:
+#endif
+ LDREG s0,R_S0*R_SZ(sp) /* restore s0 - s7 */
+ LDREG s1,R_S1*R_SZ(sp)
+ LDREG s2,R_S2*R_SZ(sp)
+ LDREG s3,R_S3*R_SZ(sp)
+ LDREG s4,R_S4*R_SZ(sp)
+ LDREG s5,R_S5*R_SZ(sp)
+ LDREG s6,R_S6*R_SZ(sp)
+ LDREG s7,R_S7*R_SZ(sp)
+
+ /* do NOT restore the sp as this could mess up the world */
+ /* do NOT restore the cause as this could mess up the world */
+
+ /*
+ ** Jump all the way out. If theres a pending interrupt, just
+ ** let it be serviced later. Since we're probably using the
+ ** gdb stub, we've already disrupted the ISR service timing
+ ** anyhow. We oughtn't mix exception and interrupt processing
+ ** in the same exception call in case the exception stuff
+ ** might interfere with the dispatching & timer ticks.
+ */
+ j _ISR_Handler_exit
+ NOP
+
+_ISR_Handler_1:
+
+ MFC0 t1,C0_SR
+ and t0,CAUSE_IPMASK
+ and t0,t1
+
+ /* external interrupt not enabled, ignore */
+ /* but if it's not an exception or an interrupt, */
+ /* Then where did it come from??? */
+
+ beq t0,zero,_ISR_Handler_exit
+
+
+
+
+ /*
+ * save some or all context on stack
+ * may need to save some special interrupt information for exit
+ *
+ * #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
+ * if ( _ISR_Nest_level == 0 )
+ * switch to software interrupt stack
+ * #endif
+ */
+
+ /*
+ * _ISR_Nest_level++;
+ */
+ LDREG t0,_ISR_Nest_level
+ NOP
+ ADD t0,t0,1
+ STREG t0,_ISR_Nest_level
+ /*
+ * _Thread_Dispatch_disable_level++;
+ */
+ LDREG t1,_Thread_Dispatch_disable_level
+ NOP
+ ADD t1,t1,1
+ STREG t1,_Thread_Dispatch_disable_level
+
+ /*
+ * Call the CPU model or BSP specific routine to decode the
+ * interrupt source and actually vector to device ISR handlers.
+ */
+
+#ifdef INSTRUMENT_ISR_VECTORING
+ NOP
+ li t1, 1
+ sw t1, 0x8001e000
+#endif
+
+ move a0,sp
+ jal mips_vector_isr_handlers
+ NOP
+
+#ifdef INSTRUMENT_ISR_VECTORING
+ li t1, 0
+ sw t1, 0x8001e000
+ NOP
+#endif
+
+ /*
+ * --_ISR_Nest_level;
+ */
+ LDREG t2,_ISR_Nest_level
+ NOP
+ ADD t2,t2,-1
+ STREG t2,_ISR_Nest_level
+ /*
+ * --_Thread_Dispatch_disable_level;
+ */
+ LDREG t1,_Thread_Dispatch_disable_level
+ NOP
+ ADD t1,t1,-1
+ STREG t1,_Thread_Dispatch_disable_level
+ /*
+ * if ( _Thread_Dispatch_disable_level || _ISR_Nest_level )
+ * goto the label "exit interrupt (simple case)"
+ */
+ or t0,t2,t1
+ bne t0,zero,_ISR_Handler_exit
+ NOP
+
+
+
+
+ /*
+ * #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
+ * restore stack
+ * #endif
+ *
+ * if ( !_Context_Switch_necessary && !_ISR_Signals_to_thread_executing )
+ * goto the label "exit interrupt (simple case)"
+ */
+ LDREG t0,_Context_Switch_necessary
+ LDREG t1,_ISR_Signals_to_thread_executing
+ NOP
+ or t0,t0,t1
+ beq t0,zero,_ISR_Handler_exit
+ NOP
+
+
+
+#ifdef INSTRUMENT_EXECUTING_THREAD
+ lw t0,_Thread_Executing
+ NOP
+ sw t0,0x8001FFF4
+#endif
+
+/*
+** Turn on interrupts before entering Thread_Dispatch which
+** will run for a while, thus allowing new interrupts to
+** be serviced. Observe the Thread_Dispatch_disable_level interlock
+** that prevents recursive entry into Thread_Dispatch.
+*/
+
+ MFC0 t0, C0_SR
+#if __mips == 3
+ li t1,SR_EXL | SR_IE
+#elif __mips == 1
+ li t1,SR_IEC
+#endif
+ or t0, t1
+ MTC0 t0, C0_SR
+ NOP
+
+ /* save off our stack frame so the context switcher can get to it */
+ la t0,__exceptionStackFrame
+ STREG sp,(t0)
+
+ jal _Thread_Dispatch
+ NOP
+
+ /* and make sure its clear in case we didn't dispatch. if we did, its
+ ** already cleared */
+ la t0,__exceptionStackFrame
+ STREG zero,(t0)
+ NOP
+
+/*
+** turn interrupts back off while we restore context so
+** a badly timed interrupt won't accidentally mess things up
+*/
+ MFC0 t0, C0_SR
+#if __mips == 3
+ li t1,SR_EXL | SR_IE
+#elif __mips == 1
+ /* ints off, current & prev kernel mode on (kernel mode enabled is bit clear..argh!) */
+ li t1,SR_IEC | SR_KUP | SR_KUC
+#endif
+ not t1
+ and t0, t1
+
+#if __mips == 1
+ /* disabled 7/29, gregm, this tasks context was saved previously in an interrupt,
+ ** so we'll just restore the task's previous interrupt enables.
+
+ **
+ ** make sure previous int enable is on because we're returning from an interrupt
+ ** which means interrupts have to be enabled
+
+ li t1,SR_IEP
+ or t0,t1
+ */
+#endif
+ MTC0 t0, C0_SR
+ NOP
+
+#ifdef INSTRUMENT_EXECUTING_THREAD
+ lw t0,_Thread_Executing
+ NOP
+ sw t0,0x8001FFF8
+#endif
+
+
+ /*
+ * prepare to get out of interrupt
+ * return from interrupt (maybe to _ISR_Dispatch)
+ *
+ * LABEL "exit interrupt (simple case):"
+ * prepare to get out of interrupt
+ * return from interrupt
+ */
+
+_ISR_Handler_exit:
+/*
+** Skip the SR restore because its a global register. _CPU_Context_switch_restore
+** adjusts it according to each task's configuration. If we didn't dispatch, the
+** SR value isn't changed, so all we need to do is return.
+**
+*/
+ /* restore context from stack */
+
+#ifdef INSTRUMENT_EXECUTING_THREAD
+ lw t0,_Thread_Executing
+ NOP
+ sw t0, 0x8001FFFC
+#endif
+
+ LDREG t8, R_MDLO*R_SZ(sp)
+ LDREG t0, R_T0*R_SZ(sp)
+ mtlo t8
+ LDREG t8, R_MDHI*R_SZ(sp)
+ LDREG t1, R_T1*R_SZ(sp)
+ mthi t8
+ LDREG t2, R_T2*R_SZ(sp)
+ LDREG t3, R_T3*R_SZ(sp)
+ LDREG t4, R_T4*R_SZ(sp)
+ LDREG t5, R_T5*R_SZ(sp)
+ LDREG t6, R_T6*R_SZ(sp)
+ LDREG t7, R_T7*R_SZ(sp)
+ LDREG t8, R_T8*R_SZ(sp)
+ LDREG t9, R_T9*R_SZ(sp)
+ LDREG gp, R_GP*R_SZ(sp)
+ LDREG fp, R_FP*R_SZ(sp)
+ LDREG ra, R_RA*R_SZ(sp)
+ LDREG a0, R_A0*R_SZ(sp)
+ LDREG a1, R_A1*R_SZ(sp)
+ LDREG a2, R_A2*R_SZ(sp)
+ LDREG a3, R_A3*R_SZ(sp)
+ LDREG v1, R_V1*R_SZ(sp)
+ LDREG v0, R_V0*R_SZ(sp)
+
+ LDREG k1, R_EPC*R_SZ(sp)
+
+ .set noat
+ LDREG AT, R_AT*R_SZ(sp)
+ .set at
+
+ ADDIU sp,sp,EXCP_STACK_SIZE
+ j k1
+ rfe
+ NOP
+
+ .set reorder
+ENDFRAME(_ISR_Handler)
+
+
+
+
+FRAME(mips_break,sp,0,ra)
+ .set noreorder
+ break 0x0 /* this statement must be first in this function, assumed so by mips-stub.c */
+ NOP
+ j ra
+ NOP
+ .set reorder
+ENDFRAME(mips_break)
diff --git a/cpukit/score/cpu/mips/idtcpu.h b/cpukit/score/cpu/mips/idtcpu.h
new file mode 100644
index 0000000000..0e451e7f8f
--- /dev/null
+++ b/cpukit/score/cpu/mips/idtcpu.h
@@ -0,0 +1,477 @@
+/*
+
+Based upon IDT provided code with the following release:
+
+This source code has been made available to you by IDT on an AS-IS
+basis. Anyone receiving this source is licensed under IDT copyrights
+to use it in any way he or she deems fit, including copying it,
+modifying it, compiling it, and redistributing it either with or
+without modifications. No license under IDT patents or patent
+applications is to be implied by the copyright license.
+
+Any user of this software should understand that IDT cannot provide
+technical support for this software and will not be responsible for
+any consequences resulting from the use of this software.
+
+Any person who transfers this source code or any derivative work must
+include the IDT copyright notice, this paragraph, and the preceeding
+two paragraphs in the transferred software.
+
+COPYRIGHT IDT CORPORATION 1996
+LICENSED MATERIAL - PROGRAM PROPERTY OF IDT
+
+ $Id$
+*/
+
+/*
+** idtcpu.h -- cpu related defines
+*/
+
+#ifndef _IDTCPU_H__
+#define _IDTCPU_H__
+
+/*
+ * 950313: Ketan added Register definition for XContext reg.
+ * added define for WAIT instruction.
+ * 950421: Ketan added Register definition for Config reg (R3081)
+ */
+
+/*
+** memory configuration and mapping
+*/
+#define K0BASE 0x80000000
+#define K0SIZE 0x20000000
+#define K1BASE 0xa0000000
+#define K1SIZE 0x20000000
+#define K2BASE 0xc0000000
+#define K2SIZE 0x20000000
+#if __mips == 3
+#define KSBASE 0xe0000000
+#define KSSIZE 0x20000000
+#endif
+
+#define KUBASE 0
+#define KUSIZE 0x80000000
+
+/*
+** Exception Vectors
+*/
+#if __mips == 1
+#define UT_VEC K0BASE /* utlbmiss vector */
+#define DB_VEC (K0BASE+0x40) /* debug vector */
+#define E_VEC (K0BASE+0x80) /* exception vector */
+#elif __mips == 3
+#define T_VEC (K0BASE+0x000) /* tlbmiss vector */
+#define X_VEC (K0BASE+0x080) /* xtlbmiss vector */
+#define C_VEC (K0BASE+0x100) /* cache error vector */
+#define E_VEC (K0BASE+0x180) /* exception vector */
+#else
+#error "EXCEPTION VECTORS: unknown ISA level"
+#endif
+#define R_VEC (K1BASE+0x1fc00000) /* reset vector */
+
+/*
+** Address conversion macros
+*/
+#ifdef CLANGUAGE
+#define CAST(as) (as)
+#else
+#define CAST(as)
+#endif
+#define K0_TO_K1(x) (CAST(unsigned)(x)|0xA0000000) /* kseg0 to kseg1 */
+#define K1_TO_K0(x) (CAST(unsigned)(x)&0x9FFFFFFF) /* kseg1 to kseg0 */
+#define K0_TO_PHYS(x) (CAST(unsigned)(x)&0x1FFFFFFF) /* kseg0 to physical */
+#define K1_TO_PHYS(x) (CAST(unsigned)(x)&0x1FFFFFFF) /* kseg1 to physical */
+#define PHYS_TO_K0(x) (CAST(unsigned)(x)|0x80000000) /* physical to kseg0 */
+#define PHYS_TO_K1(x) (CAST(unsigned)(x)|0xA0000000) /* physical to kseg1 */
+
+/*
+** Cache size constants
+*/
+#define MINCACHE 0x200 /* 512 For 3041. */
+#define MAXCACHE 0x40000 /* 256*1024 256k */
+
+#if __mips == 3
+/* R4000 configuration register definitions */
+#define CFG_CM 0x80000000 /* Master-Checker mode */
+#define CFG_ECMASK 0x70000000 /* System Clock Ratio */
+#define CFG_ECBY2 0x00000000 /* divide by 2 */
+#define CFG_ECBY3 0x10000000 /* divide by 3 */
+#define CFG_ECBY4 0x20000000 /* divide by 4 */
+#define CFG_EPMASK 0x0f000000 /* Transmit data pattern */
+#define CFG_EPD 0x00000000 /* D */
+#define CFG_EPDDX 0x01000000 /* DDX */
+#define CFG_EPDDXX 0x02000000 /* DDXX */
+#define CFG_EPDXDX 0x03000000 /* DXDX */
+#define CFG_EPDDXXX 0x04000000 /* DDXXX */
+#define CFG_EPDDXXXX 0x05000000 /* DDXXXX */
+#define CFG_EPDXXDXX 0x06000000 /* DXXDXX */
+#define CFG_EPDDXXXXX 0x07000000 /* DDXXXXX */
+#define CFG_EPDXXXDXXX 0x08000000 /* DXXXDXXX */
+#define CFG_SBMASK 0x00c00000 /* Secondary cache block size */
+#define CFG_SBSHIFT 22
+#define CFG_SB4 0x00000000 /* 4 words */
+#define CFG_SB8 0x00400000 /* 8 words */
+#define CFG_SB16 0x00800000 /* 16 words */
+#define CFG_SB32 0x00c00000 /* 32 words */
+#define CFG_SS 0x00200000 /* Split secondary cache */
+#define CFG_SW 0x00100000 /* Secondary cache port width */
+#define CFG_EWMASK 0x000c0000 /* System port width */
+#define CFG_EWSHIFT 18
+#define CFG_EW64 0x00000000 /* 64 bit */
+#define CFG_EW32 0x00010000 /* 32 bit */
+#define CFG_SC 0x00020000 /* Secondary cache absent */
+#define CFG_SM 0x00010000 /* Dirty Shared mode disabled */
+#define CFG_BE 0x00008000 /* Big Endian */
+#define CFG_EM 0x00004000 /* ECC mode enable */
+#define CFG_EB 0x00002000 /* Block ordering */
+#define CFG_ICMASK 0x00000e00 /* Instruction cache size */
+#define CFG_ICSHIFT 9
+#define CFG_DCMASK 0x000001c0 /* Data cache size */
+#define CFG_DCSHIFT 6
+#define CFG_IB 0x00000020 /* Instruction cache block size */
+#define CFG_DB 0x00000010 /* Data cache block size */
+#define CFG_CU 0x00000008 /* Update on Store Conditional */
+#define CFG_K0MASK 0x00000007 /* KSEG0 coherency algorithm */
+
+/*
+ * R4000 primary cache mode
+ */
+#define CFG_C_UNCACHED 2
+#define CFG_C_NONCOHERENT 3
+#define CFG_C_COHERENTXCL 4
+#define CFG_C_COHERENTXCLW 5
+#define CFG_C_COHERENTUPD 6
+
+/*
+ * R4000 cache operations (should be in assembler...?)
+ */
+#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 Hit_Writeback_Inv_D 0x15 /* 5 1 */
+#define Hit_Writeback_Inv_SD 0x17 /* 5 3 */
+#define Fill_I 0x14 /* 5 0 */
+#define Hit_Writeback_D 0x19 /* 6 1 */
+#define Hit_Writeback_SD 0x1B /* 6 3 */
+#define Hit_Writeback_I 0x18 /* 6 0 */
+#define Hit_Set_Virtual_SI 0x1E /* 7 2 */
+#define Hit_Set_Virtual_SD 0x1F /* 7 3 */
+
+#ifndef WAIT
+#define WAIT .word 0x42000020
+#endif /* WAIT */
+
+/* Disabled by joel -- horrible overload of common word.
+#ifndef wait
+#define wait .word 0x42000020
+#endif wait
+*/
+
+#endif
+
+/*
+** TLB resource defines
+*/
+#if __mips == 1
+#define N_TLB_ENTRIES 64
+#define TLB_PGSIZE 0x1000
+#define RANDBASE 8
+#define TLBLO_PFNMASK 0xfffff000
+#define TLBLO_PFNSHIFT 12
+#define TLBLO_N 0x800 /* non-cacheable */
+#define TLBLO_D 0x400 /* writeable */
+#define TLBLO_V 0x200 /* valid bit */
+#define TLBLO_G 0x100 /* global access bit */
+
+#define TLBHI_VPNMASK 0xfffff000
+#define TLBHI_VPNSHIFT 12
+#define TLBHI_PIDMASK 0xfc0
+#define TLBHI_PIDSHIFT 6
+#define TLBHI_NPID 64
+
+#define TLBINX_PROBE 0x80000000
+#define TLBINX_INXMASK 0x00003f00
+#define TLBINX_INXSHIFT 8
+
+#define TLBRAND_RANDMASK 0x00003f00
+#define TLBRAND_RANDSHIFT 8
+
+#define TLBCTXT_BASEMASK 0xffe00000
+#define TLBCTXT_BASESHIFT 21
+
+#define TLBCTXT_VPNMASK 0x001ffffc
+#define TLBCTXT_VPNSHIFT 2
+#endif
+#if __mips == 3
+#define N_TLB_ENTRIES 48
+
+#define TLBHI_VPN2MASK 0xffffe000
+#define TLBHI_PIDMASK 0x000000ff
+#define TLBHI_NPID 256
+
+#define TLBLO_PFNMASK 0x3fffffc0
+#define TLBLO_PFNSHIFT 6
+#define TLBLO_D 0x00000004 /* writeable */
+#define TLBLO_V 0x00000002 /* valid bit */
+#define TLBLO_G 0x00000001 /* global access bit */
+#define TLBLO_CMASK 0x00000038 /* cache algorithm mask */
+#define TLBLO_CSHIFT 3
+
+#define TLBLO_UNCACHED (CFG_C_UNCACHED<<TLBLO_CSHIFT)
+#define TLBLO_NONCOHERENT (CFG_C_NONCOHERENT<<TLBLO_CSHIFT)
+#define TLBLO_COHERENTXCL (CFG_C_COHERENTXCL<<TLBLO_CSHIFT)
+#define TLBLO_COHERENTXCLW (CFG_C_COHERENTXCLW<<TLBLO_CSHIFT)
+#define TLBLO_COHERENTUPD (CFG_C_COHERENTUPD<<TLBLO_CSHIFT)
+
+#define TLBINX_PROBE 0x80000000
+#define TLBINX_INXMASK 0x0000003f
+
+#define TLBRAND_RANDMASK 0x0000003f
+
+#define TLBCTXT_BASEMASK 0xff800000
+#define TLBCTXT_BASESHIFT 23
+
+#define TLBCTXT_VPN2MASK 0x007ffff0
+#define TLBCTXT_VPN2SHIFT 4
+
+#define TLBPGMASK_MASK 0x01ffe000
+#endif
+
+#if __mips == 1
+
+
+/* definitions for Debug and Cache Invalidate control (DCIC) register bits */
+#define DCIC_TR 0x80000000 /* Trap enable */
+#define DCIC_UD 0x40000000 /* User debug enable */
+#define DCIC_KD 0x20000000 /* Kernel debug enable */
+#define DCIC_TE 0x10000000 /* Trace enable */
+#define DCIC_DW 0x08000000 /* Enable data breakpoints on write */
+#define DCIC_DR 0x04000000 /* Enable data breakpoints on read */
+#define DCIC_DAE 0x02000000 /* Enable data addresss breakpoints */
+#define DCIC_PCE 0x01000000 /* Enable instruction breakpoints */
+#define DCIC_DE 0x00800000 /* Debug enable */
+#define DCIC_DL 0x00008000 /* Data cache line invalidate */
+#define DCIC_IL 0x00004000 /* Instruction cache line invalidate */
+#define DCIC_D 0x00002000 /* Data cache invalidate enable */
+#define DCIC_I 0x00001000 /* Instr. cache invalidate enable */
+#define DCIC_T 0x00000020 /* Trace, set by CPU */
+#define DCIC_W 0x00000010 /* Write reference, set by CPU */
+#define DCIC_R 0x00000008 /* Read reference, set by CPU */
+#define DCIC_DA 0x00000004 /* Data address, set by CPU */
+#define DCIC_PC 0x00000002 /* Program counter, set by CPU */
+#define DCIC_DB 0x00000001 /* Debug, set by CPU */
+
+
+
+
+#define SR_CUMASK 0xf0000000 /* coproc usable bits */
+#define SR_CU3 0x80000000 /* Coprocessor 3 usable */
+#define SR_CU2 0x40000000 /* Coprocessor 2 usable */
+#define SR_CU1 0x20000000 /* Coprocessor 1 usable */
+#define SR_CU0 0x10000000 /* Coprocessor 0 usable */
+
+#define SR_BEV 0x00400000 /* use boot exception vectors */
+
+/* Cache control bits */
+#define SR_TS 0x00200000 /* TLB shutdown */
+#define SR_PE 0x00100000 /* cache parity error */
+#define SR_CM 0x00080000 /* cache miss */
+#define SR_PZ 0x00040000 /* cache parity zero */
+#define SR_SWC 0x00020000 /* swap cache */
+#define SR_ISC 0x00010000 /* Isolate data cache */
+
+/*
+** status register interrupt masks and bits
+*/
+
+#define SR_IMASK 0x0000ff00 /* Interrupt mask */
+#define SR_IMASK8 0x00000000 /* mask level 8 */
+#define SR_IMASK7 0x00008000 /* mask level 7 */
+#define SR_IMASK6 0x0000c000 /* mask level 6 */
+#define SR_IMASK5 0x0000e000 /* mask level 5 */
+#define SR_IMASK4 0x0000f000 /* mask level 4 */
+#define SR_IMASK3 0x0000f800 /* mask level 3 */
+#define SR_IMASK2 0x0000fc00 /* mask level 2 */
+#define SR_IMASK1 0x0000fe00 /* mask level 1 */
+#define SR_IMASK0 0x0000ff00 /* mask level 0 */
+
+#define SR_IMASKSHIFT 8
+
+#define SR_IBIT8 0x00008000 /* bit level 8 */
+#define SR_IBIT7 0x00004000 /* bit level 7 */
+#define SR_IBIT6 0x00002000 /* bit level 6 */
+#define SR_IBIT5 0x00001000 /* bit level 5 */
+#define SR_IBIT4 0x00000800 /* bit level 4 */
+#define SR_IBIT3 0x00000400 /* bit level 3 */
+#define SR_IBIT2 0x00000200 /* bit level 2 */
+#define SR_IBIT1 0x00000100 /* bit level 1 */
+
+#define SR_KUO 0x00000020 /* old kernel/user, 0 => k, 1 => u */
+#define SR_IEO 0x00000010 /* old interrupt enable, 1 => enable */
+#define SR_KUP 0x00000008 /* prev kernel/user, 0 => k, 1 => u */
+#define SR_IEP 0x00000004 /* prev interrupt enable, 1 => enable */
+#define SR_KUC 0x00000002 /* cur kernel/user, 0 => k, 1 => u */
+#define SR_IEC 0x00000001 /* cur interrupt enable, 1 => enable */
+#endif
+
+#if __mips == 3
+#define SR_CUMASK 0xf0000000 /* coproc usable bits */
+#define SR_CU3 0x80000000 /* Coprocessor 3 usable */
+#define SR_CU2 0x40000000 /* Coprocessor 2 usable */
+#define SR_CU1 0x20000000 /* Coprocessor 1 usable */
+#define SR_CU0 0x10000000 /* Coprocessor 0 usable */
+
+#define SR_RP 0x08000000 /* Reduced power operation */
+#define SR_FR 0x04000000 /* Additional floating point registers */
+#define SR_RE 0x02000000 /* Reverse endian in user mode */
+
+#define SR_BEV 0x00400000 /* Use boot exception vectors */
+#define SR_TS 0x00200000 /* TLB shutdown */
+#define SR_SR 0x00100000 /* Soft reset */
+#define SR_CH 0x00040000 /* Cache hit */
+#define SR_CE 0x00020000 /* Use cache ECC */
+#define SR_DE 0x00010000 /* Disable cache exceptions */
+
+/*
+** status register interrupt masks and bits
+*/
+
+#define SR_IMASK 0x0000ff00 /* Interrupt mask */
+#define SR_IMASK8 0x00000000 /* mask level 8 */
+#define SR_IMASK7 0x00008000 /* mask level 7 */
+#define SR_IMASK6 0x0000c000 /* mask level 6 */
+#define SR_IMASK5 0x0000e000 /* mask level 5 */
+#define SR_IMASK4 0x0000f000 /* mask level 4 */
+#define SR_IMASK3 0x0000f800 /* mask level 3 */
+#define SR_IMASK2 0x0000fc00 /* mask level 2 */
+#define SR_IMASK1 0x0000fe00 /* mask level 1 */
+#define SR_IMASK0 0x0000ff00 /* mask level 0 */
+
+#define SR_IMASKSHIFT 8
+
+#define SR_IBIT8 0x00008000 /* bit level 8 */
+#define SR_IBIT7 0x00004000 /* bit level 7 */
+#define SR_IBIT6 0x00002000 /* bit level 6 */
+#define SR_IBIT5 0x00001000 /* bit level 5 */
+#define SR_IBIT4 0x00000800 /* bit level 4 */
+#define SR_IBIT3 0x00000400 /* bit level 3 */
+#define SR_IBIT2 0x00000200 /* bit level 2 */
+#define SR_IBIT1 0x00000100 /* bit level 1 */
+
+#define SR_KSMASK 0x00000018 /* Kernel mode mask */
+#define SR_KSUSER 0x00000010 /* User mode */
+#define SR_KSSUPER 0x00000008 /* Supervisor mode */
+#define SR_KSKERNEL 0x00000000 /* Kernel mode */
+#define SR_ERL 0x00000004 /* Error level */
+#define SR_EXL 0x00000002 /* Exception level */
+#define SR_IE 0x00000001 /* Interrupts enabled */
+#endif
+
+
+
+/*
+ * Cause Register
+ */
+#define CAUSE_BD 0x80000000 /* Branch delay slot */
+#define CAUSE_BT 0x40000000 /* Branch Taken */
+#define CAUSE_CEMASK 0x30000000 /* coprocessor error */
+#define CAUSE_CESHIFT 28
+
+
+#define CAUSE_IPMASK 0x0000FF00 /* Pending interrupt mask */
+#define CAUSE_IPSHIFT 8
+
+#define CAUSE_EXCMASK 0x0000003C /* Cause code bits */
+#define CAUSE_EXCSHIFT 2
+
+#ifndef XDS
+/*
+** Coprocessor 0 registers
+*/
+#define C0_INX $0 /* tlb index */
+#define C0_RAND $1 /* tlb random */
+#if __mips == 1
+#define C0_TLBLO $2 /* tlb entry low */
+#endif
+#if __mips == 3
+#define C0_TLBLO0 $2 /* tlb entry low 0 */
+#define C0_TLBLO1 $3 /* tlb entry low 1 */
+#endif
+
+#define C0_CTXT $4 /* tlb context */
+
+#if __mips == 3
+#define C0_PAGEMASK $5 /* tlb page mask */
+#define C0_WIRED $6 /* number of wired tlb entries */
+#endif
+
+#if __mips == 1
+#define C0_TAR $6
+#endif
+
+#define C0_BADVADDR $8 /* bad virtual address */
+
+#if __mips == 3
+#define C0_COUNT $9 /* cycle count */
+#endif
+
+#define C0_TLBHI $10 /* tlb entry hi */
+
+#if __mips == 3
+#define C0_COMPARE $11 /* cyccle count comparator */
+#endif
+
+#define C0_SR $12 /* status register */
+#define C0_CAUSE $13 /* exception cause */
+#define C0_EPC $14 /* exception pc */
+#define C0_PRID $15 /* revision identifier */
+
+#if __mips == 1
+#define C0_CONFIG $3 /* configuration register R3081*/
+#endif
+
+#if __mips == 3
+#define C0_CONFIG $16 /* configuration register */
+#define C0_LLADDR $17 /* linked load address */
+#define C0_WATCHLO $18 /* watchpoint trap register */
+#define C0_WATCHHI $19 /* watchpoint trap register */
+#define C0_XCTXT $20 /* extended tlb context */
+#define C0_ECC $26 /* secondary cache ECC control */
+#define C0_CACHEERR $27 /* cache error status */
+#define C0_TAGLO $28 /* cache tag lo */
+#define C0_TAGHI $29 /* cache tag hi */
+#define C0_ERRPC $30 /* cache error pc */
+#endif
+
+#define C1_REVISION $0
+#define C1_STATUS $31
+
+#endif /* XDS */
+
+#ifdef R4650
+#define IWATCH $18
+#define DWATCH $19
+#define IBASE $0
+#define IBOUND $1
+#define DBASE $2
+#define DBOUND $3
+#define CALG $17
+#endif
+
+#endif /* _IDTCPU_H__ */
diff --git a/cpukit/score/cpu/mips/iregdef.h b/cpukit/score/cpu/mips/iregdef.h
new file mode 100644
index 0000000000..7abb8d59ba
--- /dev/null
+++ b/cpukit/score/cpu/mips/iregdef.h
@@ -0,0 +1,331 @@
+/*
+
+Based upon IDT provided code with the following release:
+
+This source code has been made available to you by IDT on an AS-IS
+basis. Anyone receiving this source is licensed under IDT copyrights
+to use it in any way he or she deems fit, including copying it,
+modifying it, compiling it, and redistributing it either with or
+without modifications. No license under IDT patents or patent
+applications is to be implied by the copyright license.
+
+Any user of this software should understand that IDT cannot provide
+technical support for this software and will not be responsible for
+any consequences resulting from the use of this software.
+
+Any person who transfers this source code or any derivative work must
+include the IDT copyright notice, this paragraph, and the preceeding
+two paragraphs in the transferred software.
+
+COPYRIGHT IDT CORPORATION 1996
+LICENSED MATERIAL - PROGRAM PROPERTY OF IDT
+
+ $Id$
+*/
+
+/*
+** iregdef.h - IDT R3000 register structure header file
+**
+** Copyright 1989 Integrated Device Technology, Inc
+** All Rights Reserved
+**
+*/
+#ifndef __IREGDEF_H__
+#define __IREGDEF_H__
+
+/*
+ * 950313: Ketan added sreg/lreg and R_SZ for 64-bit saves
+ * added Register definition for XContext reg.
+ * Look towards end of this file.
+ */
+/*
+** register names
+*/
+#define r0 $0
+#define r1 $1
+#define r2 $2
+#define r3 $3
+#define r4 $4
+#define r5 $5
+#define r6 $6
+#define r7 $7
+#define r8 $8
+#define r9 $9
+#define r10 $10
+#define r11 $11
+#define r12 $12
+#define r13 $13
+
+#define r14 $14
+#define r15 $15
+#define r16 $16
+#define r17 $17
+#define r18 $18
+#define r19 $19
+#define r20 $20
+#define r21 $21
+#define r22 $22
+#define r23 $23
+#define r24 $24
+#define r25 $25
+#define r26 $26
+#define r27 $27
+#define r28 $28
+#define r29 $29
+#define r30 $30
+#define r31 $31
+
+#define fp0 $f0
+#define fp1 $f1
+#define fp2 $f2
+#define fp3 $f3
+#define fp4 $f4
+#define fp5 $f5
+#define fp6 $f6
+#define fp7 $f7
+#define fp8 $f8
+#define fp9 $f9
+#define fp10 $f10
+#define fp11 $f11
+#define fp12 $f12
+#define fp13 $f13
+#define fp14 $f14
+#define fp15 $f15
+#define fp16 $f16
+#define fp17 $f17
+#define fp18 $f18
+#define fp19 $f19
+#define fp20 $f20
+#define fp21 $f21
+#define fp22 $f22
+#define fp23 $f23
+#define fp24 $f24
+#define fp25 $f25
+#define fp26 $f26
+#define fp27 $f27
+#define fp28 $f28
+#define fp29 $f29
+#define fp30 $f30
+#define fp31 $f31
+
+#define fcr0 $0
+#define fcr30 $30
+#define fcr31 $31
+
+#define zero $0 /* wired zero */
+#define AT $at /* assembler temp */
+#define v0 $2 /* return value */
+#define v1 $3
+#define a0 $4 /* argument registers a0-a3 */
+#define a1 $5
+#define a2 $6
+#define a3 $7
+#define t0 $8 /* caller saved t0-t9 */
+#define t1 $9
+#define t2 $10
+#define t3 $11
+#define t4 $12
+#define t5 $13
+#define t6 $14
+#define t7 $15
+#define s0 $16 /* callee saved s0-s8 */
+#define s1 $17
+#define s2 $18
+#define s3 $19
+#define s4 $20
+#define s5 $21
+#define s6 $22
+#define s7 $23
+#define t8 $24
+#define t9 $25
+#define k0 $26 /* kernel usage */
+#define k1 $27 /* kernel usage */
+#define gp $28 /* sdata pointer */
+#define sp $29 /* stack pointer */
+#define s8 $30 /* yet another saved reg for the callee */
+#define fp $30 /* frame pointer - this is being phased out by MIPS */
+#define ra $31 /* return address */
+
+
+/*
+** relative position of registers in interrupt/exception frame
+*/
+#define R_R0 0
+#define R_R1 1
+#define R_R2 2
+#define R_R3 3
+#define R_R4 4
+#define R_R5 5
+#define R_R6 6
+#define R_R7 7
+#define R_R8 8
+#define R_R9 9
+#define R_R10 10
+#define R_R11 11
+#define R_R12 12
+#define R_R13 13
+#define R_R14 14
+#define R_R15 15
+#define R_R16 16
+#define R_R17 17
+#define R_R18 18
+#define R_R19 19
+#define R_R20 20
+#define R_R21 21
+#define R_R22 22
+#define R_R23 23
+#define R_R24 24
+#define R_R25 25
+#define R_R26 26
+#define R_R27 27
+#define R_R28 28
+#define R_R29 29
+#define R_R30 30
+#define R_R31 31
+
+#define R_SR 32
+#define R_MDLO 33
+#define R_MDHI 34
+#define R_BADVADDR 35
+#define R_CAUSE 36
+#define R_EPC 37
+
+#define R_F0 38
+#define R_F1 39
+#define R_F2 40
+#define R_F3 41
+#define R_F4 42
+#define R_F5 43
+#define R_F6 44
+#define R_F7 45
+#define R_F8 46
+#define R_F9 47
+#define R_F10 48
+#define R_F11 49
+#define R_F12 50
+#define R_F13 41
+#define R_F14 42
+#define R_F15 43
+#define R_F16 44
+#define R_F17 45
+#define R_F18 56
+#define R_F19 57
+#define R_F20 58
+#define R_F21 59
+#define R_F22 60
+#define R_F23 61
+#define R_F24 62
+#define R_F25 63
+#define R_F26 64
+#define R_F27 65
+#define R_F28 66
+#define R_F29 67
+#define R_F30 68
+#define R_F31 69
+#define R_FCSR 70
+#define R_FEIR 71
+#define R_TLBHI 72
+
+#if __mips == 1
+#define R_TLBLO 73
+#endif
+#if __mips == 3
+#define R_TLBLO0 73
+#endif
+
+#define R_INX 74
+#define R_RAND 75
+#define R_CTXT 76
+#define R_EXCTYPE 77
+#define R_MODE 78
+#define R_PRID 79
+#define R_TAR 80
+#if __mips == 1
+#define NREGS 81
+#endif
+#if __mips == 3
+#define R_TLBLO1 81
+#define R_PAGEMASK 82
+#define R_WIRED 83
+#define R_COUNT 84
+#define R_COMPARE 85
+#define R_CONFIG 86
+#define R_LLADDR 87
+#define R_WATCHLO 88
+#define R_WATCHHI 89
+#define R_ECC 90
+#define R_CACHEERR 91
+#define R_TAGLO 92
+#define R_TAGHI 93
+#define R_ERRPC 94
+#define R_XCTXT 95 /* Ketan added from SIM64bit */
+
+#define NREGS 96
+#endif
+
+/*
+** For those who like to think in terms of the compiler names for the regs
+*/
+#define R_ZERO R_R0
+#define R_AT R_R1
+#define R_V0 R_R2
+#define R_V1 R_R3
+#define R_A0 R_R4
+#define R_A1 R_R5
+#define R_A2 R_R6
+#define R_A3 R_R7
+#define R_T0 R_R8
+#define R_T1 R_R9
+#define R_T2 R_R10
+#define R_T3 R_R11
+#define R_T4 R_R12
+#define R_T5 R_R13
+#define R_T6 R_R14
+#define R_T7 R_R15
+#define R_S0 R_R16
+#define R_S1 R_R17
+#define R_S2 R_R18
+#define R_S3 R_R19
+#define R_S4 R_R20
+#define R_S5 R_R21
+#define R_S6 R_R22
+#define R_S7 R_R23
+#define R_T8 R_R24
+#define R_T9 R_R25
+#define R_K0 R_R26
+#define R_K1 R_R27
+#define R_GP R_R28
+#define R_SP R_R29
+#define R_FP R_R30
+#define R_RA R_R31
+
+/* disabled for RTEMS */
+#if 0
+/* Ketan added the following */
+#if __mips == 1
+#define sreg sw
+#define lreg lw
+#define rmfc0 mfc0
+#define rmtc0 mtc0
+#define R_SZ 4
+#endif /* __mips == 1 */
+
+/* #ifdef __mips == 3 */
+#if __mips < 3
+#define sreg sw
+#define lreg lw
+#define rmfc0 mfc0
+#define rmtc0 mtc0
+#define R_SZ 4
+#else
+#define sreg sd
+#define lreg ld
+#define rmfc0 dmfc0
+#define rmtc0 dmtc0
+#define R_SZ 8
+#endif
+/* #endif __mips == 3 */
+/* Ketan till here */
+#endif
+
+#endif /* __IREGDEF_H__ */
diff --git a/cpukit/score/cpu/mips/rtems/asm.h b/cpukit/score/cpu/mips/rtems/asm.h
new file mode 100644
index 0000000000..eb0c7c1efc
--- /dev/null
+++ b/cpukit/score/cpu/mips/rtems/asm.h
@@ -0,0 +1,158 @@
+/* asm.h
+ *
+ * This include file attempts to address the problems
+ * caused by incompatible flavors of assemblers and
+ * toolsets. It primarily addresses variations in the
+ * use of leading underscores on symbols and the requirement
+ * that register names be preceded by a %.
+ *
+ *
+ * NOTE: The spacing in the use of these macros
+ * is critical to them working as advertised.
+ *
+ * COPYRIGHT:
+ *
+ * This file is based on similar code found in newlib available
+ * from ftp.cygnus.com. The file which was used had no copyright
+ * notice. This file is freely distributable as long as the source
+ * of the file is noted. This file is:
+ *
+ * COPYRIGHT (c) 1994-1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * $Id$
+ */
+/* @(#)asm.h 03/15/96 1.1 */
+
+#ifndef __NO_CPU_ASM_h
+#define __NO_CPU_ASM_h
+
+/*
+ * Indicate we are in an assembly file and get the basic CPU definitions.
+ */
+
+#ifndef ASM
+#define ASM
+#endif
+#include <rtems/score/cpuopts.h>
+#include <rtems/score/mips.h>
+
+/*
+ * Recent versions of GNU cpp define variables which indicate the
+ * need for underscores and percents. If not using GNU cpp or
+ * the version does not support this, then you will obviously
+ * have to define these as appropriate.
+ */
+
+#ifndef __USER_LABEL_PREFIX__
+#define __USER_LABEL_PREFIX__ _
+#endif
+
+#ifndef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__
+#endif
+
+/* ANSI concatenation macros. */
+
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+/* Use the right prefix for global labels. */
+
+#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+
+/* Use the right prefix for registers. */
+
+#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
+
+/*
+ * define macros for all of the registers on this CPU
+ *
+ * EXAMPLE: #define d0 REG (d0)
+ */
+
+/*
+ * Define macros to handle section beginning and ends.
+ */
+
+
+#define BEGIN_CODE_DCL .text
+#define END_CODE_DCL
+#define BEGIN_DATA_DCL .data
+#define END_DATA_DCL
+#define BEGIN_CODE .text
+#define END_CODE
+#define BEGIN_DATA
+#define END_DATA
+#define BEGIN_BSS
+#define END_BSS
+#define END
+
+/*
+ * Following must be tailor for a particular flavor of the C compiler.
+ * They may need to put underscores in front of the symbols.
+ */
+
+#define PUBLIC(sym) .globl SYM (sym)
+#define EXTERN(sym) .globl SYM (sym)
+
+/*
+ * Debugger macros for assembly language routines. Allows the
+ * programmer to set up the necessary stack frame info
+ * required by debuggers to do stack traces.
+ */
+
+#ifndef XDS
+#define FRAME(name,frm_reg,offset,ret_reg) \
+ .globl name; \
+ .ent name; \
+name:; \
+ .frame frm_reg,offset,ret_reg
+#define ENDFRAME(name) \
+ .end name
+#else
+#define FRAME(name,frm_reg,offset,ret_reg) \
+ .globl _##name;\
+_##name:
+#define ENDFRAME(name)
+#endif XDS
+
+/*
+ * Hardware Floating Point Registers
+ */
+
+#define R_FP0 0
+#define R_FP1 1
+#define R_FP2 2
+#define R_FP3 3
+#define R_FP4 4
+#define R_FP5 5
+#define R_FP6 6
+#define R_FP7 7
+#define R_FP8 8
+#define R_FP9 9
+#define R_FP10 10
+#define R_FP11 11
+#define R_FP12 12
+#define R_FP13 13
+#define R_FP14 14
+#define R_FP15 15
+#define R_FP16 16
+#define R_FP17 17
+#define R_FP18 18
+#define R_FP19 19
+#define R_FP20 20
+#define R_FP21 21
+#define R_FP22 22
+#define R_FP23 23
+#define R_FP24 24
+#define R_FP25 25
+#define R_FP26 26
+#define R_FP27 27
+#define R_FP28 28
+#define R_FP29 29
+#define R_FP30 30
+#define R_FP31 31
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/mips/rtems/mips/idtcpu.h b/cpukit/score/cpu/mips/rtems/mips/idtcpu.h
new file mode 100644
index 0000000000..0e451e7f8f
--- /dev/null
+++ b/cpukit/score/cpu/mips/rtems/mips/idtcpu.h
@@ -0,0 +1,477 @@
+/*
+
+Based upon IDT provided code with the following release:
+
+This source code has been made available to you by IDT on an AS-IS
+basis. Anyone receiving this source is licensed under IDT copyrights
+to use it in any way he or she deems fit, including copying it,
+modifying it, compiling it, and redistributing it either with or
+without modifications. No license under IDT patents or patent
+applications is to be implied by the copyright license.
+
+Any user of this software should understand that IDT cannot provide
+technical support for this software and will not be responsible for
+any consequences resulting from the use of this software.
+
+Any person who transfers this source code or any derivative work must
+include the IDT copyright notice, this paragraph, and the preceeding
+two paragraphs in the transferred software.
+
+COPYRIGHT IDT CORPORATION 1996
+LICENSED MATERIAL - PROGRAM PROPERTY OF IDT
+
+ $Id$
+*/
+
+/*
+** idtcpu.h -- cpu related defines
+*/
+
+#ifndef _IDTCPU_H__
+#define _IDTCPU_H__
+
+/*
+ * 950313: Ketan added Register definition for XContext reg.
+ * added define for WAIT instruction.
+ * 950421: Ketan added Register definition for Config reg (R3081)
+ */
+
+/*
+** memory configuration and mapping
+*/
+#define K0BASE 0x80000000
+#define K0SIZE 0x20000000
+#define K1BASE 0xa0000000
+#define K1SIZE 0x20000000
+#define K2BASE 0xc0000000
+#define K2SIZE 0x20000000
+#if __mips == 3
+#define KSBASE 0xe0000000
+#define KSSIZE 0x20000000
+#endif
+
+#define KUBASE 0
+#define KUSIZE 0x80000000
+
+/*
+** Exception Vectors
+*/
+#if __mips == 1
+#define UT_VEC K0BASE /* utlbmiss vector */
+#define DB_VEC (K0BASE+0x40) /* debug vector */
+#define E_VEC (K0BASE+0x80) /* exception vector */
+#elif __mips == 3
+#define T_VEC (K0BASE+0x000) /* tlbmiss vector */
+#define X_VEC (K0BASE+0x080) /* xtlbmiss vector */
+#define C_VEC (K0BASE+0x100) /* cache error vector */
+#define E_VEC (K0BASE+0x180) /* exception vector */
+#else
+#error "EXCEPTION VECTORS: unknown ISA level"
+#endif
+#define R_VEC (K1BASE+0x1fc00000) /* reset vector */
+
+/*
+** Address conversion macros
+*/
+#ifdef CLANGUAGE
+#define CAST(as) (as)
+#else
+#define CAST(as)
+#endif
+#define K0_TO_K1(x) (CAST(unsigned)(x)|0xA0000000) /* kseg0 to kseg1 */
+#define K1_TO_K0(x) (CAST(unsigned)(x)&0x9FFFFFFF) /* kseg1 to kseg0 */
+#define K0_TO_PHYS(x) (CAST(unsigned)(x)&0x1FFFFFFF) /* kseg0 to physical */
+#define K1_TO_PHYS(x) (CAST(unsigned)(x)&0x1FFFFFFF) /* kseg1 to physical */
+#define PHYS_TO_K0(x) (CAST(unsigned)(x)|0x80000000) /* physical to kseg0 */
+#define PHYS_TO_K1(x) (CAST(unsigned)(x)|0xA0000000) /* physical to kseg1 */
+
+/*
+** Cache size constants
+*/
+#define MINCACHE 0x200 /* 512 For 3041. */
+#define MAXCACHE 0x40000 /* 256*1024 256k */
+
+#if __mips == 3
+/* R4000 configuration register definitions */
+#define CFG_CM 0x80000000 /* Master-Checker mode */
+#define CFG_ECMASK 0x70000000 /* System Clock Ratio */
+#define CFG_ECBY2 0x00000000 /* divide by 2 */
+#define CFG_ECBY3 0x10000000 /* divide by 3 */
+#define CFG_ECBY4 0x20000000 /* divide by 4 */
+#define CFG_EPMASK 0x0f000000 /* Transmit data pattern */
+#define CFG_EPD 0x00000000 /* D */
+#define CFG_EPDDX 0x01000000 /* DDX */
+#define CFG_EPDDXX 0x02000000 /* DDXX */
+#define CFG_EPDXDX 0x03000000 /* DXDX */
+#define CFG_EPDDXXX 0x04000000 /* DDXXX */
+#define CFG_EPDDXXXX 0x05000000 /* DDXXXX */
+#define CFG_EPDXXDXX 0x06000000 /* DXXDXX */
+#define CFG_EPDDXXXXX 0x07000000 /* DDXXXXX */
+#define CFG_EPDXXXDXXX 0x08000000 /* DXXXDXXX */
+#define CFG_SBMASK 0x00c00000 /* Secondary cache block size */
+#define CFG_SBSHIFT 22
+#define CFG_SB4 0x00000000 /* 4 words */
+#define CFG_SB8 0x00400000 /* 8 words */
+#define CFG_SB16 0x00800000 /* 16 words */
+#define CFG_SB32 0x00c00000 /* 32 words */
+#define CFG_SS 0x00200000 /* Split secondary cache */
+#define CFG_SW 0x00100000 /* Secondary cache port width */
+#define CFG_EWMASK 0x000c0000 /* System port width */
+#define CFG_EWSHIFT 18
+#define CFG_EW64 0x00000000 /* 64 bit */
+#define CFG_EW32 0x00010000 /* 32 bit */
+#define CFG_SC 0x00020000 /* Secondary cache absent */
+#define CFG_SM 0x00010000 /* Dirty Shared mode disabled */
+#define CFG_BE 0x00008000 /* Big Endian */
+#define CFG_EM 0x00004000 /* ECC mode enable */
+#define CFG_EB 0x00002000 /* Block ordering */
+#define CFG_ICMASK 0x00000e00 /* Instruction cache size */
+#define CFG_ICSHIFT 9
+#define CFG_DCMASK 0x000001c0 /* Data cache size */
+#define CFG_DCSHIFT 6
+#define CFG_IB 0x00000020 /* Instruction cache block size */
+#define CFG_DB 0x00000010 /* Data cache block size */
+#define CFG_CU 0x00000008 /* Update on Store Conditional */
+#define CFG_K0MASK 0x00000007 /* KSEG0 coherency algorithm */
+
+/*
+ * R4000 primary cache mode
+ */
+#define CFG_C_UNCACHED 2
+#define CFG_C_NONCOHERENT 3
+#define CFG_C_COHERENTXCL 4
+#define CFG_C_COHERENTXCLW 5
+#define CFG_C_COHERENTUPD 6
+
+/*
+ * R4000 cache operations (should be in assembler...?)
+ */
+#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 Hit_Writeback_Inv_D 0x15 /* 5 1 */
+#define Hit_Writeback_Inv_SD 0x17 /* 5 3 */
+#define Fill_I 0x14 /* 5 0 */
+#define Hit_Writeback_D 0x19 /* 6 1 */
+#define Hit_Writeback_SD 0x1B /* 6 3 */
+#define Hit_Writeback_I 0x18 /* 6 0 */
+#define Hit_Set_Virtual_SI 0x1E /* 7 2 */
+#define Hit_Set_Virtual_SD 0x1F /* 7 3 */
+
+#ifndef WAIT
+#define WAIT .word 0x42000020
+#endif /* WAIT */
+
+/* Disabled by joel -- horrible overload of common word.
+#ifndef wait
+#define wait .word 0x42000020
+#endif wait
+*/
+
+#endif
+
+/*
+** TLB resource defines
+*/
+#if __mips == 1
+#define N_TLB_ENTRIES 64
+#define TLB_PGSIZE 0x1000
+#define RANDBASE 8
+#define TLBLO_PFNMASK 0xfffff000
+#define TLBLO_PFNSHIFT 12
+#define TLBLO_N 0x800 /* non-cacheable */
+#define TLBLO_D 0x400 /* writeable */
+#define TLBLO_V 0x200 /* valid bit */
+#define TLBLO_G 0x100 /* global access bit */
+
+#define TLBHI_VPNMASK 0xfffff000
+#define TLBHI_VPNSHIFT 12
+#define TLBHI_PIDMASK 0xfc0
+#define TLBHI_PIDSHIFT 6
+#define TLBHI_NPID 64
+
+#define TLBINX_PROBE 0x80000000
+#define TLBINX_INXMASK 0x00003f00
+#define TLBINX_INXSHIFT 8
+
+#define TLBRAND_RANDMASK 0x00003f00
+#define TLBRAND_RANDSHIFT 8
+
+#define TLBCTXT_BASEMASK 0xffe00000
+#define TLBCTXT_BASESHIFT 21
+
+#define TLBCTXT_VPNMASK 0x001ffffc
+#define TLBCTXT_VPNSHIFT 2
+#endif
+#if __mips == 3
+#define N_TLB_ENTRIES 48
+
+#define TLBHI_VPN2MASK 0xffffe000
+#define TLBHI_PIDMASK 0x000000ff
+#define TLBHI_NPID 256
+
+#define TLBLO_PFNMASK 0x3fffffc0
+#define TLBLO_PFNSHIFT 6
+#define TLBLO_D 0x00000004 /* writeable */
+#define TLBLO_V 0x00000002 /* valid bit */
+#define TLBLO_G 0x00000001 /* global access bit */
+#define TLBLO_CMASK 0x00000038 /* cache algorithm mask */
+#define TLBLO_CSHIFT 3
+
+#define TLBLO_UNCACHED (CFG_C_UNCACHED<<TLBLO_CSHIFT)
+#define TLBLO_NONCOHERENT (CFG_C_NONCOHERENT<<TLBLO_CSHIFT)
+#define TLBLO_COHERENTXCL (CFG_C_COHERENTXCL<<TLBLO_CSHIFT)
+#define TLBLO_COHERENTXCLW (CFG_C_COHERENTXCLW<<TLBLO_CSHIFT)
+#define TLBLO_COHERENTUPD (CFG_C_COHERENTUPD<<TLBLO_CSHIFT)
+
+#define TLBINX_PROBE 0x80000000
+#define TLBINX_INXMASK 0x0000003f
+
+#define TLBRAND_RANDMASK 0x0000003f
+
+#define TLBCTXT_BASEMASK 0xff800000
+#define TLBCTXT_BASESHIFT 23
+
+#define TLBCTXT_VPN2MASK 0x007ffff0
+#define TLBCTXT_VPN2SHIFT 4
+
+#define TLBPGMASK_MASK 0x01ffe000
+#endif
+
+#if __mips == 1
+
+
+/* definitions for Debug and Cache Invalidate control (DCIC) register bits */
+#define DCIC_TR 0x80000000 /* Trap enable */
+#define DCIC_UD 0x40000000 /* User debug enable */
+#define DCIC_KD 0x20000000 /* Kernel debug enable */
+#define DCIC_TE 0x10000000 /* Trace enable */
+#define DCIC_DW 0x08000000 /* Enable data breakpoints on write */
+#define DCIC_DR 0x04000000 /* Enable data breakpoints on read */
+#define DCIC_DAE 0x02000000 /* Enable data addresss breakpoints */
+#define DCIC_PCE 0x01000000 /* Enable instruction breakpoints */
+#define DCIC_DE 0x00800000 /* Debug enable */
+#define DCIC_DL 0x00008000 /* Data cache line invalidate */
+#define DCIC_IL 0x00004000 /* Instruction cache line invalidate */
+#define DCIC_D 0x00002000 /* Data cache invalidate enable */
+#define DCIC_I 0x00001000 /* Instr. cache invalidate enable */
+#define DCIC_T 0x00000020 /* Trace, set by CPU */
+#define DCIC_W 0x00000010 /* Write reference, set by CPU */
+#define DCIC_R 0x00000008 /* Read reference, set by CPU */
+#define DCIC_DA 0x00000004 /* Data address, set by CPU */
+#define DCIC_PC 0x00000002 /* Program counter, set by CPU */
+#define DCIC_DB 0x00000001 /* Debug, set by CPU */
+
+
+
+
+#define SR_CUMASK 0xf0000000 /* coproc usable bits */
+#define SR_CU3 0x80000000 /* Coprocessor 3 usable */
+#define SR_CU2 0x40000000 /* Coprocessor 2 usable */
+#define SR_CU1 0x20000000 /* Coprocessor 1 usable */
+#define SR_CU0 0x10000000 /* Coprocessor 0 usable */
+
+#define SR_BEV 0x00400000 /* use boot exception vectors */
+
+/* Cache control bits */
+#define SR_TS 0x00200000 /* TLB shutdown */
+#define SR_PE 0x00100000 /* cache parity error */
+#define SR_CM 0x00080000 /* cache miss */
+#define SR_PZ 0x00040000 /* cache parity zero */
+#define SR_SWC 0x00020000 /* swap cache */
+#define SR_ISC 0x00010000 /* Isolate data cache */
+
+/*
+** status register interrupt masks and bits
+*/
+
+#define SR_IMASK 0x0000ff00 /* Interrupt mask */
+#define SR_IMASK8 0x00000000 /* mask level 8 */
+#define SR_IMASK7 0x00008000 /* mask level 7 */
+#define SR_IMASK6 0x0000c000 /* mask level 6 */
+#define SR_IMASK5 0x0000e000 /* mask level 5 */
+#define SR_IMASK4 0x0000f000 /* mask level 4 */
+#define SR_IMASK3 0x0000f800 /* mask level 3 */
+#define SR_IMASK2 0x0000fc00 /* mask level 2 */
+#define SR_IMASK1 0x0000fe00 /* mask level 1 */
+#define SR_IMASK0 0x0000ff00 /* mask level 0 */
+
+#define SR_IMASKSHIFT 8
+
+#define SR_IBIT8 0x00008000 /* bit level 8 */
+#define SR_IBIT7 0x00004000 /* bit level 7 */
+#define SR_IBIT6 0x00002000 /* bit level 6 */
+#define SR_IBIT5 0x00001000 /* bit level 5 */
+#define SR_IBIT4 0x00000800 /* bit level 4 */
+#define SR_IBIT3 0x00000400 /* bit level 3 */
+#define SR_IBIT2 0x00000200 /* bit level 2 */
+#define SR_IBIT1 0x00000100 /* bit level 1 */
+
+#define SR_KUO 0x00000020 /* old kernel/user, 0 => k, 1 => u */
+#define SR_IEO 0x00000010 /* old interrupt enable, 1 => enable */
+#define SR_KUP 0x00000008 /* prev kernel/user, 0 => k, 1 => u */
+#define SR_IEP 0x00000004 /* prev interrupt enable, 1 => enable */
+#define SR_KUC 0x00000002 /* cur kernel/user, 0 => k, 1 => u */
+#define SR_IEC 0x00000001 /* cur interrupt enable, 1 => enable */
+#endif
+
+#if __mips == 3
+#define SR_CUMASK 0xf0000000 /* coproc usable bits */
+#define SR_CU3 0x80000000 /* Coprocessor 3 usable */
+#define SR_CU2 0x40000000 /* Coprocessor 2 usable */
+#define SR_CU1 0x20000000 /* Coprocessor 1 usable */
+#define SR_CU0 0x10000000 /* Coprocessor 0 usable */
+
+#define SR_RP 0x08000000 /* Reduced power operation */
+#define SR_FR 0x04000000 /* Additional floating point registers */
+#define SR_RE 0x02000000 /* Reverse endian in user mode */
+
+#define SR_BEV 0x00400000 /* Use boot exception vectors */
+#define SR_TS 0x00200000 /* TLB shutdown */
+#define SR_SR 0x00100000 /* Soft reset */
+#define SR_CH 0x00040000 /* Cache hit */
+#define SR_CE 0x00020000 /* Use cache ECC */
+#define SR_DE 0x00010000 /* Disable cache exceptions */
+
+/*
+** status register interrupt masks and bits
+*/
+
+#define SR_IMASK 0x0000ff00 /* Interrupt mask */
+#define SR_IMASK8 0x00000000 /* mask level 8 */
+#define SR_IMASK7 0x00008000 /* mask level 7 */
+#define SR_IMASK6 0x0000c000 /* mask level 6 */
+#define SR_IMASK5 0x0000e000 /* mask level 5 */
+#define SR_IMASK4 0x0000f000 /* mask level 4 */
+#define SR_IMASK3 0x0000f800 /* mask level 3 */
+#define SR_IMASK2 0x0000fc00 /* mask level 2 */
+#define SR_IMASK1 0x0000fe00 /* mask level 1 */
+#define SR_IMASK0 0x0000ff00 /* mask level 0 */
+
+#define SR_IMASKSHIFT 8
+
+#define SR_IBIT8 0x00008000 /* bit level 8 */
+#define SR_IBIT7 0x00004000 /* bit level 7 */
+#define SR_IBIT6 0x00002000 /* bit level 6 */
+#define SR_IBIT5 0x00001000 /* bit level 5 */
+#define SR_IBIT4 0x00000800 /* bit level 4 */
+#define SR_IBIT3 0x00000400 /* bit level 3 */
+#define SR_IBIT2 0x00000200 /* bit level 2 */
+#define SR_IBIT1 0x00000100 /* bit level 1 */
+
+#define SR_KSMASK 0x00000018 /* Kernel mode mask */
+#define SR_KSUSER 0x00000010 /* User mode */
+#define SR_KSSUPER 0x00000008 /* Supervisor mode */
+#define SR_KSKERNEL 0x00000000 /* Kernel mode */
+#define SR_ERL 0x00000004 /* Error level */
+#define SR_EXL 0x00000002 /* Exception level */
+#define SR_IE 0x00000001 /* Interrupts enabled */
+#endif
+
+
+
+/*
+ * Cause Register
+ */
+#define CAUSE_BD 0x80000000 /* Branch delay slot */
+#define CAUSE_BT 0x40000000 /* Branch Taken */
+#define CAUSE_CEMASK 0x30000000 /* coprocessor error */
+#define CAUSE_CESHIFT 28
+
+
+#define CAUSE_IPMASK 0x0000FF00 /* Pending interrupt mask */
+#define CAUSE_IPSHIFT 8
+
+#define CAUSE_EXCMASK 0x0000003C /* Cause code bits */
+#define CAUSE_EXCSHIFT 2
+
+#ifndef XDS
+/*
+** Coprocessor 0 registers
+*/
+#define C0_INX $0 /* tlb index */
+#define C0_RAND $1 /* tlb random */
+#if __mips == 1
+#define C0_TLBLO $2 /* tlb entry low */
+#endif
+#if __mips == 3
+#define C0_TLBLO0 $2 /* tlb entry low 0 */
+#define C0_TLBLO1 $3 /* tlb entry low 1 */
+#endif
+
+#define C0_CTXT $4 /* tlb context */
+
+#if __mips == 3
+#define C0_PAGEMASK $5 /* tlb page mask */
+#define C0_WIRED $6 /* number of wired tlb entries */
+#endif
+
+#if __mips == 1
+#define C0_TAR $6
+#endif
+
+#define C0_BADVADDR $8 /* bad virtual address */
+
+#if __mips == 3
+#define C0_COUNT $9 /* cycle count */
+#endif
+
+#define C0_TLBHI $10 /* tlb entry hi */
+
+#if __mips == 3
+#define C0_COMPARE $11 /* cyccle count comparator */
+#endif
+
+#define C0_SR $12 /* status register */
+#define C0_CAUSE $13 /* exception cause */
+#define C0_EPC $14 /* exception pc */
+#define C0_PRID $15 /* revision identifier */
+
+#if __mips == 1
+#define C0_CONFIG $3 /* configuration register R3081*/
+#endif
+
+#if __mips == 3
+#define C0_CONFIG $16 /* configuration register */
+#define C0_LLADDR $17 /* linked load address */
+#define C0_WATCHLO $18 /* watchpoint trap register */
+#define C0_WATCHHI $19 /* watchpoint trap register */
+#define C0_XCTXT $20 /* extended tlb context */
+#define C0_ECC $26 /* secondary cache ECC control */
+#define C0_CACHEERR $27 /* cache error status */
+#define C0_TAGLO $28 /* cache tag lo */
+#define C0_TAGHI $29 /* cache tag hi */
+#define C0_ERRPC $30 /* cache error pc */
+#endif
+
+#define C1_REVISION $0
+#define C1_STATUS $31
+
+#endif /* XDS */
+
+#ifdef R4650
+#define IWATCH $18
+#define DWATCH $19
+#define IBASE $0
+#define IBOUND $1
+#define DBASE $2
+#define DBOUND $3
+#define CALG $17
+#endif
+
+#endif /* _IDTCPU_H__ */
diff --git a/cpukit/score/cpu/mips/rtems/mips/iregdef.h b/cpukit/score/cpu/mips/rtems/mips/iregdef.h
new file mode 100644
index 0000000000..7abb8d59ba
--- /dev/null
+++ b/cpukit/score/cpu/mips/rtems/mips/iregdef.h
@@ -0,0 +1,331 @@
+/*
+
+Based upon IDT provided code with the following release:
+
+This source code has been made available to you by IDT on an AS-IS
+basis. Anyone receiving this source is licensed under IDT copyrights
+to use it in any way he or she deems fit, including copying it,
+modifying it, compiling it, and redistributing it either with or
+without modifications. No license under IDT patents or patent
+applications is to be implied by the copyright license.
+
+Any user of this software should understand that IDT cannot provide
+technical support for this software and will not be responsible for
+any consequences resulting from the use of this software.
+
+Any person who transfers this source code or any derivative work must
+include the IDT copyright notice, this paragraph, and the preceeding
+two paragraphs in the transferred software.
+
+COPYRIGHT IDT CORPORATION 1996
+LICENSED MATERIAL - PROGRAM PROPERTY OF IDT
+
+ $Id$
+*/
+
+/*
+** iregdef.h - IDT R3000 register structure header file
+**
+** Copyright 1989 Integrated Device Technology, Inc
+** All Rights Reserved
+**
+*/
+#ifndef __IREGDEF_H__
+#define __IREGDEF_H__
+
+/*
+ * 950313: Ketan added sreg/lreg and R_SZ for 64-bit saves
+ * added Register definition for XContext reg.
+ * Look towards end of this file.
+ */
+/*
+** register names
+*/
+#define r0 $0
+#define r1 $1
+#define r2 $2
+#define r3 $3
+#define r4 $4
+#define r5 $5
+#define r6 $6
+#define r7 $7
+#define r8 $8
+#define r9 $9
+#define r10 $10
+#define r11 $11
+#define r12 $12
+#define r13 $13
+
+#define r14 $14
+#define r15 $15
+#define r16 $16
+#define r17 $17
+#define r18 $18
+#define r19 $19
+#define r20 $20
+#define r21 $21
+#define r22 $22
+#define r23 $23
+#define r24 $24
+#define r25 $25
+#define r26 $26
+#define r27 $27
+#define r28 $28
+#define r29 $29
+#define r30 $30
+#define r31 $31
+
+#define fp0 $f0
+#define fp1 $f1
+#define fp2 $f2
+#define fp3 $f3
+#define fp4 $f4
+#define fp5 $f5
+#define fp6 $f6
+#define fp7 $f7
+#define fp8 $f8
+#define fp9 $f9
+#define fp10 $f10
+#define fp11 $f11
+#define fp12 $f12
+#define fp13 $f13
+#define fp14 $f14
+#define fp15 $f15
+#define fp16 $f16
+#define fp17 $f17
+#define fp18 $f18
+#define fp19 $f19
+#define fp20 $f20
+#define fp21 $f21
+#define fp22 $f22
+#define fp23 $f23
+#define fp24 $f24
+#define fp25 $f25
+#define fp26 $f26
+#define fp27 $f27
+#define fp28 $f28
+#define fp29 $f29
+#define fp30 $f30
+#define fp31 $f31
+
+#define fcr0 $0
+#define fcr30 $30
+#define fcr31 $31
+
+#define zero $0 /* wired zero */
+#define AT $at /* assembler temp */
+#define v0 $2 /* return value */
+#define v1 $3
+#define a0 $4 /* argument registers a0-a3 */
+#define a1 $5
+#define a2 $6
+#define a3 $7
+#define t0 $8 /* caller saved t0-t9 */
+#define t1 $9
+#define t2 $10
+#define t3 $11
+#define t4 $12
+#define t5 $13
+#define t6 $14
+#define t7 $15
+#define s0 $16 /* callee saved s0-s8 */
+#define s1 $17
+#define s2 $18
+#define s3 $19
+#define s4 $20
+#define s5 $21
+#define s6 $22
+#define s7 $23
+#define t8 $24
+#define t9 $25
+#define k0 $26 /* kernel usage */
+#define k1 $27 /* kernel usage */
+#define gp $28 /* sdata pointer */
+#define sp $29 /* stack pointer */
+#define s8 $30 /* yet another saved reg for the callee */
+#define fp $30 /* frame pointer - this is being phased out by MIPS */
+#define ra $31 /* return address */
+
+
+/*
+** relative position of registers in interrupt/exception frame
+*/
+#define R_R0 0
+#define R_R1 1
+#define R_R2 2
+#define R_R3 3
+#define R_R4 4
+#define R_R5 5
+#define R_R6 6
+#define R_R7 7
+#define R_R8 8
+#define R_R9 9
+#define R_R10 10
+#define R_R11 11
+#define R_R12 12
+#define R_R13 13
+#define R_R14 14
+#define R_R15 15
+#define R_R16 16
+#define R_R17 17
+#define R_R18 18
+#define R_R19 19
+#define R_R20 20
+#define R_R21 21
+#define R_R22 22
+#define R_R23 23
+#define R_R24 24
+#define R_R25 25
+#define R_R26 26
+#define R_R27 27
+#define R_R28 28
+#define R_R29 29
+#define R_R30 30
+#define R_R31 31
+
+#define R_SR 32
+#define R_MDLO 33
+#define R_MDHI 34
+#define R_BADVADDR 35
+#define R_CAUSE 36
+#define R_EPC 37
+
+#define R_F0 38
+#define R_F1 39
+#define R_F2 40
+#define R_F3 41
+#define R_F4 42
+#define R_F5 43
+#define R_F6 44
+#define R_F7 45
+#define R_F8 46
+#define R_F9 47
+#define R_F10 48
+#define R_F11 49
+#define R_F12 50
+#define R_F13 41
+#define R_F14 42
+#define R_F15 43
+#define R_F16 44
+#define R_F17 45
+#define R_F18 56
+#define R_F19 57
+#define R_F20 58
+#define R_F21 59
+#define R_F22 60
+#define R_F23 61
+#define R_F24 62
+#define R_F25 63
+#define R_F26 64
+#define R_F27 65
+#define R_F28 66
+#define R_F29 67
+#define R_F30 68
+#define R_F31 69
+#define R_FCSR 70
+#define R_FEIR 71
+#define R_TLBHI 72
+
+#if __mips == 1
+#define R_TLBLO 73
+#endif
+#if __mips == 3
+#define R_TLBLO0 73
+#endif
+
+#define R_INX 74
+#define R_RAND 75
+#define R_CTXT 76
+#define R_EXCTYPE 77
+#define R_MODE 78
+#define R_PRID 79
+#define R_TAR 80
+#if __mips == 1
+#define NREGS 81
+#endif
+#if __mips == 3
+#define R_TLBLO1 81
+#define R_PAGEMASK 82
+#define R_WIRED 83
+#define R_COUNT 84
+#define R_COMPARE 85
+#define R_CONFIG 86
+#define R_LLADDR 87
+#define R_WATCHLO 88
+#define R_WATCHHI 89
+#define R_ECC 90
+#define R_CACHEERR 91
+#define R_TAGLO 92
+#define R_TAGHI 93
+#define R_ERRPC 94
+#define R_XCTXT 95 /* Ketan added from SIM64bit */
+
+#define NREGS 96
+#endif
+
+/*
+** For those who like to think in terms of the compiler names for the regs
+*/
+#define R_ZERO R_R0
+#define R_AT R_R1
+#define R_V0 R_R2
+#define R_V1 R_R3
+#define R_A0 R_R4
+#define R_A1 R_R5
+#define R_A2 R_R6
+#define R_A3 R_R7
+#define R_T0 R_R8
+#define R_T1 R_R9
+#define R_T2 R_R10
+#define R_T3 R_R11
+#define R_T4 R_R12
+#define R_T5 R_R13
+#define R_T6 R_R14
+#define R_T7 R_R15
+#define R_S0 R_R16
+#define R_S1 R_R17
+#define R_S2 R_R18
+#define R_S3 R_R19
+#define R_S4 R_R20
+#define R_S5 R_R21
+#define R_S6 R_R22
+#define R_S7 R_R23
+#define R_T8 R_R24
+#define R_T9 R_R25
+#define R_K0 R_R26
+#define R_K1 R_R27
+#define R_GP R_R28
+#define R_SP R_R29
+#define R_FP R_R30
+#define R_RA R_R31
+
+/* disabled for RTEMS */
+#if 0
+/* Ketan added the following */
+#if __mips == 1
+#define sreg sw
+#define lreg lw
+#define rmfc0 mfc0
+#define rmtc0 mtc0
+#define R_SZ 4
+#endif /* __mips == 1 */
+
+/* #ifdef __mips == 3 */
+#if __mips < 3
+#define sreg sw
+#define lreg lw
+#define rmfc0 mfc0
+#define rmtc0 mtc0
+#define R_SZ 4
+#else
+#define sreg sd
+#define lreg ld
+#define rmfc0 dmfc0
+#define rmtc0 dmtc0
+#define R_SZ 8
+#endif
+/* #endif __mips == 3 */
+/* Ketan till here */
+#endif
+
+#endif /* __IREGDEF_H__ */
diff --git a/cpukit/score/cpu/mips/rtems/score/cpu.h b/cpukit/score/cpu/mips/rtems/score/cpu.h
new file mode 100644
index 0000000000..5e104526f1
--- /dev/null
+++ b/cpukit/score/cpu/mips/rtems/score/cpu.h
@@ -0,0 +1,1196 @@
+/*
+ * Mips CPU Dependent Header File
+ *
+ * Conversion to MIPS port by Alan Cudmore <alanc@linuxstart.com> and
+ * Joel Sherrill <joel@OARcorp.com>.
+ *
+ * These changes made the code conditional on standard cpp predefines,
+ * merged the mips1 and mips3 code sequences as much as possible,
+ * and moved some of the assembly code to C. Alan did much of the
+ * initial analysis and rework. Joel took over from there and
+ * wrote the JMR3904 BSP so this could be tested. Joel also
+ * added the new interrupt vectoring support in libcpu and
+ * tried to better support the various interrupt controllers.
+ *
+ * Original MIP64ORION port by Craig Lebakken <craigl@transition.com>
+ * COPYRIGHT (c) 1996 by Transition Networks Inc.
+ *
+ * To anyone who acknowledges that this file is provided "AS IS"
+ * without any express or implied warranty:
+ * permission to use, copy, modify, and distribute this file
+ * for any purpose is hereby granted without fee, provided that
+ * the above copyright notice and this notice appears in all
+ * copies, and that the name of Transition Networks not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ * Transition Networks makes no representations about the suitability
+ * of this software for any purpose.
+ *
+ * COPYRIGHT (c) 1989-2001.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __CPU_h
+#define __CPU_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/mips.h> /* pick up machine definitions */
+#ifndef ASM
+#include <rtems/score/types.h>
+#endif
+
+/* conditional compilation parameters */
+
+/*
+ * Should the calls to _Thread_Enable_dispatch be inlined?
+ *
+ * If TRUE, then they are inlined.
+ * If FALSE, then a subroutine call is made.
+ *
+ * Basically this is an example of the classic trade-off of size
+ * versus speed. Inlining the call (TRUE) typically increases the
+ * size of RTEMS while speeding up the enabling of dispatching.
+ * [NOTE: In general, the _Thread_Dispatch_disable_level will
+ * only be 0 or 1 unless you are in an interrupt handler and that
+ * interrupt handler invokes the executive.] When not inlined
+ * something calls _Thread_Enable_dispatch which in turns calls
+ * _Thread_Dispatch. If the enable dispatch is inlined, then
+ * one subroutine call is avoided entirely.]
+ */
+
+#define CPU_INLINE_ENABLE_DISPATCH FALSE
+
+/*
+ * Should the body of the search loops in _Thread_queue_Enqueue_priority
+ * be unrolled one time? In unrolled each iteration of the loop examines
+ * two "nodes" on the chain being searched. Otherwise, only one node
+ * is examined per iteration.
+ *
+ * If TRUE, then the loops are unrolled.
+ * If FALSE, then the loops are not unrolled.
+ *
+ * The primary factor in making this decision is the cost of disabling
+ * and enabling interrupts (_ISR_Flash) versus the cost of rest of the
+ * body of the loop. On some CPUs, the flash is more expensive than
+ * one iteration of the loop body. In this case, it might be desirable
+ * to unroll the loop. It is important to note that on some CPUs, this
+ * code is the longest interrupt disable period in RTEMS. So it is
+ * necessary to strike a balance when setting this parameter.
+ */
+
+#define CPU_UNROLL_ENQUEUE_PRIORITY TRUE
+
+/*
+ * Does RTEMS manage a dedicated interrupt stack in software?
+ *
+ * If TRUE, then a stack is allocated in _Interrupt_Manager_initialization.
+ * If FALSE, nothing is done.
+ *
+ * If the CPU supports a dedicated interrupt stack in hardware,
+ * then it is generally the responsibility of the BSP to allocate it
+ * and set it up.
+ *
+ * If the CPU does not support a dedicated interrupt stack, then
+ * the porter has two options: (1) execute interrupts on the
+ * stack of the interrupted task, and (2) have RTEMS manage a dedicated
+ * interrupt stack.
+ *
+ * If this is TRUE, CPU_ALLOCATE_INTERRUPT_STACK should also be TRUE.
+ *
+ * Only one of CPU_HAS_SOFTWARE_INTERRUPT_STACK and
+ * CPU_HAS_HARDWARE_INTERRUPT_STACK should be set to TRUE. It is
+ * possible that both are FALSE for a particular CPU. Although it
+ * is unclear what that would imply about the interrupt processing
+ * procedure on that CPU.
+ */
+
+#define CPU_HAS_SOFTWARE_INTERRUPT_STACK FALSE
+
+/*
+ * Does this CPU have hardware support for a dedicated interrupt stack?
+ *
+ * If TRUE, then it must be installed during initialization.
+ * If FALSE, then no installation is performed.
+ *
+ * If this is TRUE, CPU_ALLOCATE_INTERRUPT_STACK should also be TRUE.
+ *
+ * Only one of CPU_HAS_SOFTWARE_INTERRUPT_STACK and
+ * CPU_HAS_HARDWARE_INTERRUPT_STACK should be set to TRUE. It is
+ * possible that both are FALSE for a particular CPU. Although it
+ * is unclear what that would imply about the interrupt processing
+ * procedure on that CPU.
+ */
+
+#define CPU_HAS_HARDWARE_INTERRUPT_STACK FALSE
+
+/*
+ * Does RTEMS allocate a dedicated interrupt stack in the Interrupt Manager?
+ *
+ * If TRUE, then the memory is allocated during initialization.
+ * If FALSE, then the memory is allocated during initialization.
+ *
+ * This should be TRUE is CPU_HAS_SOFTWARE_INTERRUPT_STACK is TRUE
+ * or CPU_INSTALL_HARDWARE_INTERRUPT_STACK is TRUE.
+ */
+
+#define CPU_ALLOCATE_INTERRUPT_STACK FALSE
+
+/*
+ * Does the RTEMS invoke the user's ISR with the vector number and
+ * a pointer to the saved interrupt frame (1) or just the vector
+ * number (0)?
+ *
+ */
+
+#define CPU_ISR_PASSES_FRAME_POINTER 1
+
+
+
+/*
+ * Does the CPU have hardware floating point?
+ *
+ * If TRUE, then the RTEMS_FLOATING_POINT task attribute is supported.
+ * If FALSE, then the RTEMS_FLOATING_POINT task attribute is ignored.
+ *
+ * If there is a FP coprocessor such as the i387 or mc68881, then
+ * the answer is TRUE.
+ *
+ * The macro name "MIPS_HAS_FPU" should be made CPU specific.
+ * It indicates whether or not this CPU model has FP support. For
+ * example, it would be possible to have an i386_nofp CPU model
+ * which set this to false to indicate that you have an i386 without
+ * an i387 and wish to leave floating point support out of RTEMS.
+ */
+
+#if ( MIPS_HAS_FPU == 1 )
+#define CPU_HARDWARE_FP TRUE
+#else
+#define CPU_HARDWARE_FP FALSE
+#endif
+
+/*
+ * Are all tasks RTEMS_FLOATING_POINT tasks implicitly?
+ *
+ * If TRUE, then the RTEMS_FLOATING_POINT task attribute is assumed.
+ * If FALSE, then the RTEMS_FLOATING_POINT task attribute is followed.
+ *
+ * If CPU_HARDWARE_FP is FALSE, then this should be FALSE as well.
+ */
+
+#define CPU_ALL_TASKS_ARE_FP FALSE
+
+/*
+ * Should the IDLE task have a floating point context?
+ *
+ * If TRUE, then the IDLE task is created as a RTEMS_FLOATING_POINT task
+ * and it has a floating point context which is switched in and out.
+ * If FALSE, then the IDLE task does not have a floating point context.
+ *
+ * Setting this to TRUE negatively impacts the time required to preempt
+ * the IDLE task from an interrupt because the floating point context
+ * must be saved as part of the preemption.
+ */
+
+#define CPU_IDLE_TASK_IS_FP FALSE
+
+/*
+ * Should the saving of the floating point registers be deferred
+ * until a context switch is made to another different floating point
+ * task?
+ *
+ * If TRUE, then the floating point context will not be stored until
+ * necessary. It will remain in the floating point registers and not
+ * disturned until another floating point task is switched to.
+ *
+ * If FALSE, then the floating point context is saved when a floating
+ * point task is switched out and restored when the next floating point
+ * task is restored. The state of the floating point registers between
+ * those two operations is not specified.
+ *
+ * If the floating point context does NOT have to be saved as part of
+ * interrupt dispatching, then it should be safe to set this to TRUE.
+ *
+ * Setting this flag to TRUE results in using a different algorithm
+ * for deciding when to save and restore the floating point context.
+ * The deferred FP switch algorithm minimizes the number of times
+ * the FP context is saved and restored. The FP context is not saved
+ * until a context switch is made to another, different FP task.
+ * Thus in a system with only one FP task, the FP context will never
+ * be saved or restored.
+ */
+
+#define CPU_USE_DEFERRED_FP_SWITCH TRUE
+
+/*
+ * Does this port provide a CPU dependent IDLE task implementation?
+ *
+ * If TRUE, then the routine _CPU_Internal_threads_Idle_thread_body
+ * must be provided and is the default IDLE thread body instead of
+ * _Internal_threads_Idle_thread_body.
+ *
+ * If FALSE, then use the generic IDLE thread body if the BSP does
+ * not provide one.
+ *
+ * This is intended to allow for supporting processors which have
+ * a low power or idle mode. When the IDLE thread is executed, then
+ * the CPU can be powered down.
+ *
+ * The order of precedence for selecting the IDLE thread body is:
+ *
+ * 1. BSP provided
+ * 2. CPU dependent (if provided)
+ * 3. generic (if no BSP and no CPU dependent)
+ */
+
+/* we can use the low power wait instruction for the IDLE thread */
+#define CPU_PROVIDES_IDLE_THREAD_BODY TRUE
+
+/*
+ * Does the stack grow up (toward higher addresses) or down
+ * (toward lower addresses)?
+ *
+ * If TRUE, then the grows upward.
+ * If FALSE, then the grows toward smaller addresses.
+ */
+
+/* our stack grows down */
+#define CPU_STACK_GROWS_UP FALSE
+
+/*
+ * The following is the variable attribute used to force alignment
+ * of critical RTEMS structures. On some processors it may make
+ * sense to have these aligned on tighter boundaries than
+ * the minimum requirements of the compiler in order to have as
+ * much of the critical data area as possible in a cache line.
+ *
+ * The placement of this macro in the declaration of the variables
+ * is based on the syntactically requirements of the GNU C
+ * "__attribute__" extension. For example with GNU C, use
+ * the following to force a structures to a 32 byte boundary.
+ *
+ * __attribute__ ((aligned (32)))
+ *
+ * NOTE: Currently only the Priority Bit Map table uses this feature.
+ * To benefit from using this, the data must be heavily
+ * used so it will stay in the cache and used frequently enough
+ * in the executive to justify turning this on.
+ */
+
+/* our cache line size is 16 bytes */
+#if __GNUC__
+#define CPU_STRUCTURE_ALIGNMENT __attribute__ ((aligned (16)))
+#else
+#define CPU_STRUCTURE_ALIGNMENT
+#endif
+
+/*
+ * Define what is required to specify how the network to host conversion
+ * routines are handled.
+ */
+
+#define CPU_HAS_OWN_HOST_TO_NETWORK_ROUTINES FALSE
+#define CPU_BIG_ENDIAN TRUE
+#define CPU_LITTLE_ENDIAN FALSE
+
+/*
+ * The following defines the number of bits actually used in the
+ * interrupt field of the task mode. How those bits map to the
+ * CPU interrupt levels is defined by the routine _CPU_ISR_Set_level().
+ */
+
+#define CPU_MODES_INTERRUPT_MASK 0x000000ff
+
+/*
+ * Processor defined structures
+ *
+ * Examples structures include the descriptor tables from the i386
+ * and the processor control structure on the i960ca.
+ */
+
+/* may need to put some structures here. */
+
+/*
+ * Contexts
+ *
+ * Generally there are 2 types of context to save.
+ * 1. Interrupt registers to save
+ * 2. Task level registers to save
+ *
+ * This means we have the following 3 context items:
+ * 1. task level context stuff:: Context_Control
+ * 2. floating point task stuff:: Context_Control_fp
+ * 3. special interrupt level context :: Context_Control_interrupt
+ *
+ * On some processors, it is cost-effective to save only the callee
+ * preserved registers during a task context switch. This means
+ * that the ISR code needs to save those registers which do not
+ * persist across function calls. It is not mandatory to make this
+ * distinctions between the caller/callee saves registers for the
+ * purpose of minimizing context saved during task switch and on interrupts.
+ * If the cost of saving extra registers is minimal, simplicity is the
+ * choice. Save the same context on interrupt entry as for tasks in
+ * this case.
+ *
+ * Additionally, if gdb is to be made aware of RTEMS tasks for this CPU, then
+ * care should be used in designing the context area.
+ *
+ * On some CPUs with hardware floating point support, the Context_Control_fp
+ * structure will not be used or it simply consist of an array of a
+ * fixed number of bytes. This is done when the floating point context
+ * is dumped by a "FP save context" type instruction and the format
+ * is not really defined by the CPU. In this case, there is no need
+ * to figure out the exact format -- only the size. Of course, although
+ * this is enough information for RTEMS, it is probably not enough for
+ * a debugger such as gdb. But that is another problem.
+ */
+
+#ifndef ASSEMBLY_ONLY
+
+/* WARNING: If this structure is modified, the constants in cpu.h must be updated. */
+#if __mips == 1
+#define __MIPS_REGISTER_TYPE uint32_t
+#define __MIPS_FPU_REGISTER_TYPE uint32_t
+#elif __mips == 3
+#define __MIPS_REGISTER_TYPE uint64_t
+#define __MIPS_FPU_REGISTER_TYPE uint64_t
+#else
+#error "mips register size: unknown architecture level!!"
+#endif
+typedef struct {
+ __MIPS_REGISTER_TYPE s0;
+ __MIPS_REGISTER_TYPE s1;
+ __MIPS_REGISTER_TYPE s2;
+ __MIPS_REGISTER_TYPE s3;
+ __MIPS_REGISTER_TYPE s4;
+ __MIPS_REGISTER_TYPE s5;
+ __MIPS_REGISTER_TYPE s6;
+ __MIPS_REGISTER_TYPE s7;
+ __MIPS_REGISTER_TYPE sp;
+ __MIPS_REGISTER_TYPE fp;
+ __MIPS_REGISTER_TYPE ra;
+ __MIPS_REGISTER_TYPE c0_sr;
+ __MIPS_REGISTER_TYPE c0_epc;
+} Context_Control;
+
+/* WARNING: If this structure is modified, the constants in cpu.h
+ * must also be updated.
+ */
+
+typedef struct {
+#if ( CPU_HARDWARE_FP == TRUE )
+ __MIPS_FPU_REGISTER_TYPE fp0;
+ __MIPS_FPU_REGISTER_TYPE fp1;
+ __MIPS_FPU_REGISTER_TYPE fp2;
+ __MIPS_FPU_REGISTER_TYPE fp3;
+ __MIPS_FPU_REGISTER_TYPE fp4;
+ __MIPS_FPU_REGISTER_TYPE fp5;
+ __MIPS_FPU_REGISTER_TYPE fp6;
+ __MIPS_FPU_REGISTER_TYPE fp7;
+ __MIPS_FPU_REGISTER_TYPE fp8;
+ __MIPS_FPU_REGISTER_TYPE fp9;
+ __MIPS_FPU_REGISTER_TYPE fp10;
+ __MIPS_FPU_REGISTER_TYPE fp11;
+ __MIPS_FPU_REGISTER_TYPE fp12;
+ __MIPS_FPU_REGISTER_TYPE fp13;
+ __MIPS_FPU_REGISTER_TYPE fp14;
+ __MIPS_FPU_REGISTER_TYPE fp15;
+ __MIPS_FPU_REGISTER_TYPE fp16;
+ __MIPS_FPU_REGISTER_TYPE fp17;
+ __MIPS_FPU_REGISTER_TYPE fp18;
+ __MIPS_FPU_REGISTER_TYPE fp19;
+ __MIPS_FPU_REGISTER_TYPE fp20;
+ __MIPS_FPU_REGISTER_TYPE fp21;
+ __MIPS_FPU_REGISTER_TYPE fp22;
+ __MIPS_FPU_REGISTER_TYPE fp23;
+ __MIPS_FPU_REGISTER_TYPE fp24;
+ __MIPS_FPU_REGISTER_TYPE fp25;
+ __MIPS_FPU_REGISTER_TYPE fp26;
+ __MIPS_FPU_REGISTER_TYPE fp27;
+ __MIPS_FPU_REGISTER_TYPE fp28;
+ __MIPS_FPU_REGISTER_TYPE fp29;
+ __MIPS_FPU_REGISTER_TYPE fp30;
+ __MIPS_FPU_REGISTER_TYPE fp31;
+ __MIPS_FPU_REGISTER_TYPE fpcs;
+#endif
+} Context_Control_fp;
+
+/*
+ * This struct reflects the stack frame employed in ISR_Handler. Note
+ * that the ISR routine save some of the registers to this frame for
+ * all interrupts and exceptions. Other registers are saved only on
+ * exceptions, while others are not touched at all. The untouched
+ * registers are not normally disturbed by high-level language
+ * programs so they can be accessed when required.
+ *
+ * The registers and their ordering in this struct must directly
+ * correspond to the layout and ordering of * shown in iregdef.h,
+ * as cpu_asm.S uses those definitions to fill the stack frame.
+ * This struct provides access to the stack frame for C code.
+ *
+ * Similarly, this structure is used by debugger stubs and exception
+ * processing routines so be careful when changing the format.
+ *
+ * NOTE: The comments with this structure and cpu_asm.S should be kept
+ * in sync. When in doubt, look in the code to see if the
+ * registers you're interested in are actually treated as expected.
+ * The order of the first portion of this structure follows the
+ * order of registers expected by gdb.
+ */
+
+typedef struct
+{
+ __MIPS_REGISTER_TYPE r0; /* 0 -- NOT FILLED IN */
+ __MIPS_REGISTER_TYPE at; /* 1 -- saved always */
+ __MIPS_REGISTER_TYPE v0; /* 2 -- saved always */
+ __MIPS_REGISTER_TYPE v1; /* 3 -- saved always */
+ __MIPS_REGISTER_TYPE a0; /* 4 -- saved always */
+ __MIPS_REGISTER_TYPE a1; /* 5 -- saved always */
+ __MIPS_REGISTER_TYPE a2; /* 6 -- saved always */
+ __MIPS_REGISTER_TYPE a3; /* 7 -- saved always */
+ __MIPS_REGISTER_TYPE t0; /* 8 -- saved always */
+ __MIPS_REGISTER_TYPE t1; /* 9 -- saved always */
+ __MIPS_REGISTER_TYPE t2; /* 10 -- saved always */
+ __MIPS_REGISTER_TYPE t3; /* 11 -- saved always */
+ __MIPS_REGISTER_TYPE t4; /* 12 -- saved always */
+ __MIPS_REGISTER_TYPE t5; /* 13 -- saved always */
+ __MIPS_REGISTER_TYPE t6; /* 14 -- saved always */
+ __MIPS_REGISTER_TYPE t7; /* 15 -- saved always */
+ __MIPS_REGISTER_TYPE s0; /* 16 -- saved on exceptions */
+ __MIPS_REGISTER_TYPE s1; /* 17 -- saved on exceptions */
+ __MIPS_REGISTER_TYPE s2; /* 18 -- saved on exceptions */
+ __MIPS_REGISTER_TYPE s3; /* 19 -- saved on exceptions */
+ __MIPS_REGISTER_TYPE s4; /* 20 -- saved on exceptions */
+ __MIPS_REGISTER_TYPE s5; /* 21 -- saved on exceptions */
+ __MIPS_REGISTER_TYPE s6; /* 22 -- saved on exceptions */
+ __MIPS_REGISTER_TYPE s7; /* 23 -- saved on exceptions */
+ __MIPS_REGISTER_TYPE t8; /* 24 -- saved always */
+ __MIPS_REGISTER_TYPE t9; /* 25 -- saved always */
+ __MIPS_REGISTER_TYPE k0; /* 26 -- NOT FILLED IN, kernel tmp reg */
+ __MIPS_REGISTER_TYPE k1; /* 27 -- NOT FILLED IN, kernel tmp reg */
+ __MIPS_REGISTER_TYPE gp; /* 28 -- saved always */
+ __MIPS_REGISTER_TYPE sp; /* 29 -- saved on exceptions NOT RESTORED */
+ __MIPS_REGISTER_TYPE fp; /* 30 -- saved always */
+ __MIPS_REGISTER_TYPE ra; /* 31 -- saved always */
+ __MIPS_REGISTER_TYPE c0_sr; /* 32 -- saved always, some bits are */
+ /* manipulated per-thread */
+ __MIPS_REGISTER_TYPE mdlo; /* 33 -- saved always */
+ __MIPS_REGISTER_TYPE mdhi; /* 34 -- saved always */
+ __MIPS_REGISTER_TYPE badvaddr; /* 35 -- saved on exceptions, read-only */
+ __MIPS_REGISTER_TYPE cause; /* 36 -- saved on exceptions NOT restored */
+ __MIPS_REGISTER_TYPE epc; /* 37 -- saved always, read-only register */
+ /* but logically restored */
+ __MIPS_FPU_REGISTER_TYPE f0; /* 38 -- saved if FP enabled */
+ __MIPS_FPU_REGISTER_TYPE f1; /* 39 -- saved if FP enabled */
+ __MIPS_FPU_REGISTER_TYPE f2; /* 40 -- saved if FP enabled */
+ __MIPS_FPU_REGISTER_TYPE f3; /* 41 -- saved if FP enabled */
+ __MIPS_FPU_REGISTER_TYPE f4; /* 42 -- saved if FP enabled */
+ __MIPS_FPU_REGISTER_TYPE f5; /* 43 -- saved if FP enabled */
+ __MIPS_FPU_REGISTER_TYPE f6; /* 44 -- saved if FP enabled */
+ __MIPS_FPU_REGISTER_TYPE f7; /* 45 -- saved if FP enabled */
+ __MIPS_FPU_REGISTER_TYPE f8; /* 46 -- saved if FP enabled */
+ __MIPS_FPU_REGISTER_TYPE f9; /* 47 -- saved if FP enabled */
+ __MIPS_FPU_REGISTER_TYPE f10; /* 48 -- saved if FP enabled */
+ __MIPS_FPU_REGISTER_TYPE f11; /* 49 -- saved if FP enabled */
+ __MIPS_FPU_REGISTER_TYPE f12; /* 50 -- saved if FP enabled */
+ __MIPS_FPU_REGISTER_TYPE f13; /* 51 -- saved if FP enabled */
+ __MIPS_FPU_REGISTER_TYPE f14; /* 52 -- saved if FP enabled */
+ __MIPS_FPU_REGISTER_TYPE f15; /* 53 -- saved if FP enabled */
+ __MIPS_FPU_REGISTER_TYPE f16; /* 54 -- saved if FP enabled */
+ __MIPS_FPU_REGISTER_TYPE f17; /* 55 -- saved if FP enabled */
+ __MIPS_FPU_REGISTER_TYPE f18; /* 56 -- saved if FP enabled */
+ __MIPS_FPU_REGISTER_TYPE f19; /* 57 -- saved if FP enabled */
+ __MIPS_FPU_REGISTER_TYPE f20; /* 58 -- saved if FP enabled */
+ __MIPS_FPU_REGISTER_TYPE f21; /* 59 -- saved if FP enabled */
+ __MIPS_FPU_REGISTER_TYPE f22; /* 60 -- saved if FP enabled */
+ __MIPS_FPU_REGISTER_TYPE f23; /* 61 -- saved if FP enabled */
+ __MIPS_FPU_REGISTER_TYPE f24; /* 62 -- saved if FP enabled */
+ __MIPS_FPU_REGISTER_TYPE f25; /* 63 -- saved if FP enabled */
+ __MIPS_FPU_REGISTER_TYPE f26; /* 64 -- saved if FP enabled */
+ __MIPS_FPU_REGISTER_TYPE f27; /* 65 -- saved if FP enabled */
+ __MIPS_FPU_REGISTER_TYPE f28; /* 66 -- saved if FP enabled */
+ __MIPS_FPU_REGISTER_TYPE f29; /* 67 -- saved if FP enabled */
+ __MIPS_FPU_REGISTER_TYPE f30; /* 68 -- saved if FP enabled */
+ __MIPS_FPU_REGISTER_TYPE f31; /* 69 -- saved if FP enabled */
+ __MIPS_REGISTER_TYPE fcsr; /* 70 -- saved on exceptions */
+ /* (oddly not documented on MGV) */
+ __MIPS_REGISTER_TYPE feir; /* 71 -- saved on exceptions */
+ /* (oddly not documented on MGV) */
+
+ /* GDB does not seem to care about anything past this point */
+
+ __MIPS_REGISTER_TYPE tlbhi; /* 72 - NOT FILLED IN, doesn't exist on */
+ /* all MIPS CPUs (at least MGV) */
+#if __mips == 1
+ __MIPS_REGISTER_TYPE tlblo; /* 73 - NOT FILLED IN, doesn't exist on */
+ /* all MIPS CPUs (at least MGV) */
+#endif
+#if __mips == 3
+ __MIPS_REGISTER_TYPE tlblo0; /* 73 - NOT FILLED IN, doesn't exist on */
+ /* all MIPS CPUs (at least MGV) */
+#endif
+
+ __MIPS_REGISTER_TYPE inx; /* 74 -- NOT FILLED IN, doesn't exist on */
+ /* all MIPS CPUs (at least MGV) */
+ __MIPS_REGISTER_TYPE rand; /* 75 -- NOT FILLED IN, doesn't exist on */
+ /* all MIPS CPUs (at least MGV) */
+ __MIPS_REGISTER_TYPE ctxt; /* 76 -- NOT FILLED IN, doesn't exist on */
+ /* all MIPS CPUs (at least MGV) */
+ __MIPS_REGISTER_TYPE exctype; /* 77 -- NOT FILLED IN (not enough info) */
+ __MIPS_REGISTER_TYPE mode; /* 78 -- NOT FILLED IN (not enough info) */
+ __MIPS_REGISTER_TYPE prid; /* 79 -- NOT FILLED IN (not need to do so) */
+ __MIPS_REGISTER_TYPE tar ; /* 80 -- target address register, filled on exceptions */
+ /* end of __mips == 1 so NREGS == 81 */
+#if __mips == 3
+ __MIPS_REGISTER_TYPE tlblo1; /* 81 -- NOT FILLED IN */
+ __MIPS_REGISTER_TYPE pagemask; /* 82 -- NOT FILLED IN */
+ __MIPS_REGISTER_TYPE wired; /* 83 -- NOT FILLED IN */
+ __MIPS_REGISTER_TYPE count; /* 84 -- NOT FILLED IN */
+ __MIPS_REGISTER_TYPE compare; /* 85 -- NOT FILLED IN */
+ __MIPS_REGISTER_TYPE config; /* 86 -- NOT FILLED IN */
+ __MIPS_REGISTER_TYPE lladdr; /* 87 -- NOT FILLED IN */
+ __MIPS_REGISTER_TYPE watchlo; /* 88 -- NOT FILLED IN */
+ __MIPS_REGISTER_TYPE watchhi; /* 89 -- NOT FILLED IN */
+ __MIPS_REGISTER_TYPE ecc; /* 90 -- NOT FILLED IN */
+ __MIPS_REGISTER_TYPE cacheerr; /* 91 -- NOT FILLED IN */
+ __MIPS_REGISTER_TYPE taglo; /* 92 -- NOT FILLED IN */
+ __MIPS_REGISTER_TYPE taghi; /* 93 -- NOT FILLED IN */
+ __MIPS_REGISTER_TYPE errpc; /* 94 -- NOT FILLED IN */
+ __MIPS_REGISTER_TYPE xctxt; /* 95 -- NOT FILLED IN */
+ /* end of __mips == 3 so NREGS == 96 */
+#endif
+
+} CPU_Interrupt_frame;
+
+
+/*
+ * The following table contains the information required to configure
+ * the mips processor specific parameters.
+ */
+
+typedef struct {
+ void (*pretasking_hook)( void );
+ void (*predriver_hook)( void );
+ void (*postdriver_hook)( void );
+ void (*idle_task)( void );
+ boolean do_zero_of_workspace;
+ uint32_t idle_task_stack_size;
+ uint32_t interrupt_stack_size;
+ uint32_t extra_mpci_receive_server_stack;
+ void * (*stack_allocate_hook)( uint32_t );
+ void (*stack_free_hook)( void* );
+ /* end of fields required on all CPUs */
+
+ uint32_t clicks_per_microsecond;
+} rtems_cpu_table;
+
+
+/*
+ * Macros to access required entires in the CPU Table are in
+ * the file rtems/system.h.
+ */
+
+/*
+ * Macros to access MIPS specific additions to the CPU Table
+ */
+
+#define rtems_cpu_configuration_get_clicks_per_microsecond() \
+ (_CPU_Table.clicks_per_microsecond)
+
+/*
+ * This variable is optional. It is used on CPUs on which it is difficult
+ * to generate an "uninitialized" FP context. It is filled in by
+ * _CPU_Initialize and copied into the task's FP context area during
+ * _CPU_Context_Initialize.
+ */
+
+SCORE_EXTERN Context_Control_fp _CPU_Null_fp_context;
+
+/*
+ * On some CPUs, RTEMS supports a software managed interrupt stack.
+ * This stack is allocated by the Interrupt Manager and the switch
+ * is performed in _ISR_Handler. These variables contain pointers
+ * to the lowest and highest addresses in the chunk of memory allocated
+ * for the interrupt stack. Since it is unknown whether the stack
+ * grows up or down (in general), this give the CPU dependent
+ * code the option of picking the version it wants to use.
+ *
+ * NOTE: These two variables are required if the macro
+ * CPU_HAS_SOFTWARE_INTERRUPT_STACK is defined as TRUE.
+ */
+
+SCORE_EXTERN void *_CPU_Interrupt_stack_low;
+SCORE_EXTERN void *_CPU_Interrupt_stack_high;
+
+/*
+ * With some compilation systems, it is difficult if not impossible to
+ * call a high-level language routine from assembly language. This
+ * is especially true of commercial Ada compilers and name mangling
+ * C++ ones. This variable can be optionally defined by the CPU porter
+ * and contains the address of the routine _Thread_Dispatch. This
+ * can make it easier to invoke that routine at the end of the interrupt
+ * sequence (if a dispatch is necessary).
+ *
+
+SCORE_EXTERN void (*_CPU_Thread_dispatch_pointer)();
+ *
+ * NOTE: Not needed on this port.
+ */
+
+
+
+/*
+ * Nothing prevents the porter from declaring more CPU specific variables.
+ */
+
+/* XXX: if needed, put more variables here */
+
+/*
+ * The size of the floating point context area. On some CPUs this
+ * will not be a "sizeof" because the format of the floating point
+ * area is not defined -- only the size is. This is usually on
+ * CPUs with a "floating point save context" instruction.
+ */
+
+#define CPU_CONTEXT_FP_SIZE sizeof( Context_Control_fp )
+
+/*
+ * Amount of extra stack (above minimum stack size) required by
+ * system initialization thread. Remember that in a multiprocessor
+ * system the system intialization thread becomes the MP server thread.
+ */
+
+#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 0
+
+/*
+ * This defines the number of entries in the ISR_Vector_table managed
+ * by RTEMS.
+ */
+
+extern unsigned int mips_interrupt_number_of_vectors;
+#define CPU_INTERRUPT_NUMBER_OF_VECTORS (mips_interrupt_number_of_vectors)
+#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1)
+
+/*
+ * Should be large enough to run all RTEMS tests. This insures
+ * that a "reasonable" small application should not have any problems.
+ */
+
+#define CPU_STACK_MINIMUM_SIZE (2048*sizeof(uint32_t ))
+
+
+/*
+ * CPU's worst alignment requirement for data types on a byte boundary. This
+ * alignment does not take into account the requirements for the stack.
+ */
+
+#define CPU_ALIGNMENT 8
+
+/*
+ * This number corresponds to the byte alignment requirement for the
+ * heap handler. This alignment requirement may be stricter than that
+ * for the data types alignment specified by CPU_ALIGNMENT. It is
+ * common for the heap to follow the same alignment requirement as
+ * CPU_ALIGNMENT. If the CPU_ALIGNMENT is strict enough for the heap,
+ * then this should be set to CPU_ALIGNMENT.
+ *
+ * NOTE: This does not have to be a power of 2. It does have to
+ * be greater or equal to than CPU_ALIGNMENT.
+ */
+
+#define CPU_HEAP_ALIGNMENT CPU_ALIGNMENT
+
+/*
+ * This number corresponds to the byte alignment requirement for memory
+ * buffers allocated by the partition manager. This alignment requirement
+ * may be stricter than that for the data types alignment specified by
+ * CPU_ALIGNMENT. It is common for the partition to follow the same
+ * alignment requirement as CPU_ALIGNMENT. If the CPU_ALIGNMENT is strict
+ * enough for the partition, then this should be set to CPU_ALIGNMENT.
+ *
+ * NOTE: This does not have to be a power of 2. It does have to
+ * be greater or equal to than CPU_ALIGNMENT.
+ */
+
+#define CPU_PARTITION_ALIGNMENT CPU_ALIGNMENT
+
+/*
+ * This number corresponds to the byte alignment requirement for the
+ * stack. This alignment requirement may be stricter than that for the
+ * data types alignment specified by CPU_ALIGNMENT. If the CPU_ALIGNMENT
+ * is strict enough for the stack, then this should be set to 0.
+ *
+ * NOTE: This must be a power of 2 either 0 or greater than CPU_ALIGNMENT.
+ */
+
+#define CPU_STACK_ALIGNMENT CPU_ALIGNMENT
+
+/*
+ * ISR handler macros
+ */
+
+/*
+ * Support routine to initialize the RTEMS vector table after it is allocated.
+ */
+
+#define _CPU_Initialize_vectors()
+
+/*
+ * Disable all interrupts for an RTEMS critical section. The previous
+ * level is returned in _level.
+ */
+
+#define _CPU_ISR_Disable( _level ) \
+ do { \
+ unsigned int _scratch; \
+ mips_get_sr( _scratch ); \
+ mips_set_sr( _scratch & ~SR_INTERRUPT_ENABLE_BITS ); \
+ _level = _scratch & SR_INTERRUPT_ENABLE_BITS; \
+ } while(0)
+
+/*
+ * Enable interrupts to the previous level (returned by _CPU_ISR_Disable).
+ * This indicates the end of an RTEMS critical section. The parameter
+ * _level is not modified.
+ */
+
+#define _CPU_ISR_Enable( _level ) \
+ do { \
+ unsigned int _scratch; \
+ mips_get_sr( _scratch ); \
+ mips_set_sr( (_scratch & ~SR_INTERRUPT_ENABLE_BITS) | (_level & SR_INTERRUPT_ENABLE_BITS) ); \
+ } while(0)
+
+/*
+ * This temporarily restores the interrupt to _level before immediately
+ * disabling them again. This is used to divide long RTEMS critical
+ * sections into two or more parts. The parameter _level is not
+ * modified.
+ */
+
+#define _CPU_ISR_Flash( _xlevel ) \
+ do { \
+ unsigned int _scratch2 = _xlevel; \
+ _CPU_ISR_Enable( _scratch2 ); \
+ _CPU_ISR_Disable( _scratch2 ); \
+ _xlevel = _scratch2; \
+ } while(0)
+
+/*
+ * Map interrupt level in task mode onto the hardware that the CPU
+ * actually provides. Currently, interrupt levels which do not
+ * map onto the CPU in a generic fashion are undefined. Someday,
+ * it would be nice if these were "mapped" by the application
+ * via a callout. For example, m68k has 8 levels 0 - 7, levels
+ * 8 - 255 would be available for bsp/application specific meaning.
+ * This could be used to manage a programmable interrupt controller
+ * via the rtems_task_mode directive.
+ *
+ * On the MIPS, 0 is all on. Non-zero is all off. This only
+ * manipulates the IEC.
+ */
+
+uint32_t _CPU_ISR_Get_level( void ); /* in cpu.c */
+
+void _CPU_ISR_Set_level( uint32_t ); /* in cpu.c */
+
+/* end of ISR handler macros */
+
+/* Context handler macros */
+
+/*
+ * Initialize the context to a state suitable for starting a
+ * task after a context restore operation. Generally, this
+ * involves:
+ *
+ * - setting a starting address
+ * - preparing the stack
+ * - preparing the stack and frame pointers
+ * - setting the proper interrupt level in the context
+ * - initializing the floating point context
+ *
+ * This routine generally does not set any unnecessary register
+ * in the context. The state of the "general data" registers is
+ * undefined at task start time.
+ *
+ * NOTE: This is_fp parameter is TRUE if the thread is to be a floating
+ * point thread. This is typically only used on CPUs where the
+ * FPU may be easily disabled by software such as on the SPARC
+ * where the PSR contains an enable FPU bit.
+ *
+ * The per-thread status register holds the interrupt enable, FP enable
+ * and global interrupt enable for that thread. It means each thread can
+ * enable its own set of interrupts. If interrupts are disabled, RTEMS
+ * can still dispatch via blocking calls. This is the function of the
+ * "Interrupt Level", and on the MIPS, it controls the IEC bit and all
+ * the hardware interrupts as defined in the SR. Software ints
+ * are automatically enabled for all threads, as they will only occur under
+ * program control anyhow. Besides, the interrupt level parm is only 8 bits,
+ * and controlling the software ints plus the others would require 9.
+ *
+ * If the Interrupt Level is 0, all ints are on. Otherwise, the
+ * Interrupt Level should supply a bit pattern to impose on the SR
+ * interrupt bits; bit 0 applies to the mips1 IEC bit/mips3 EXL&IE, bits 1 thru 6
+ * apply to the SR register Intr bits from bit 10 thru bit 15. Bit 7 of
+ * the Interrupt Level parameter is unused at this time.
+ *
+ * These are the only per-thread SR bits, the others are maintained
+ * globally & explicitly preserved by the Context Switch code in cpu_asm.s
+ */
+
+
+#if __mips == 3
+#define _INTON (SR_EXL | SR_IE)
+#define _EXTRABITS 0
+#endif
+#if __mips == 1
+#define _INTON SR_IEC
+#define _EXTRABITS 0 /* make sure we're in user mode on MIPS1 processors */
+#endif
+
+#define _CPU_Context_Initialize( _the_context, _stack_base, _size, _isr, _entry_point, _is_fp ) \
+ { \
+ uint32_t _stack_tmp = \
+ (uint32_t )(_stack_base) + (_size) - CPU_STACK_ALIGNMENT; \
+ uint32_t _intlvl = _isr & 0xff; \
+ _stack_tmp &= ~(CPU_STACK_ALIGNMENT - 1); \
+ (_the_context)->sp = _stack_tmp; \
+ (_the_context)->fp = _stack_tmp; \
+ (_the_context)->ra = (uint64_t )_entry_point; \
+ (_the_context)->c0_sr = ((_intlvl==0)?(0xFF00 | _INTON):( ((_intlvl<<9) & 0xfc00) | \
+ 0x300 | \
+ ((_intlvl & 1)?_INTON:0)) ) | \
+ SR_CU0 | ((_is_fp)?SR_CU1:0) | _EXTRABITS; \
+ }
+
+
+
+/*
+ * This routine is responsible for somehow restarting the currently
+ * executing task. If you are lucky, then all that is necessary
+ * is restoring the context. Otherwise, there will need to be
+ * a special assembly routine which does something special in this
+ * case. Context_Restore should work most of the time. It will
+ * not work if restarting self conflicts with the stack frame
+ * assumptions of restoring a context.
+ */
+
+#define _CPU_Context_Restart_self( _the_context ) \
+ _CPU_Context_restore( (_the_context) );
+
+/*
+ * The purpose of this macro is to allow the initial pointer into
+ * A floating point context area (used to save the floating point
+ * context) to be at an arbitrary place in the floating point
+ * context area.
+ *
+ * This is necessary because some FP units are designed to have
+ * their context saved as a stack which grows into lower addresses.
+ * Other FP units can be saved by simply moving registers into offsets
+ * from the base of the context area. Finally some FP units provide
+ * a "dump context" instruction which could fill in from high to low
+ * or low to high based on the whim of the CPU designers.
+ */
+
+#define _CPU_Context_Fp_start( _base, _offset ) \
+ ( (void *) _Addresses_Add_offset( (_base), (_offset) ) )
+
+/*
+ * This routine initializes the FP context area passed to it to.
+ * There are a few standard ways in which to initialize the
+ * floating point context. The code included for this macro assumes
+ * that this is a CPU in which a "initial" FP context was saved into
+ * _CPU_Null_fp_context and it simply copies it to the destination
+ * context passed to it.
+ *
+ * Other models include (1) not doing anything, and (2) putting
+ * a "null FP status word" in the correct place in the FP context.
+ */
+
+#if ( CPU_HARDWARE_FP == TRUE )
+#define _CPU_Context_Initialize_fp( _destination ) \
+ { \
+ *((Context_Control_fp *) *((void **) _destination)) = _CPU_Null_fp_context; \
+ }
+#endif
+
+/* end of Context handler macros */
+
+/* Fatal Error manager macros */
+
+/*
+ * This routine copies _error into a known place -- typically a stack
+ * location or a register, optionally disables interrupts, and
+ * halts/stops the CPU.
+ */
+
+#define _CPU_Fatal_halt( _error ) \
+ do { \
+ unsigned int _level; \
+ _CPU_ISR_Disable(_level); \
+ loop: goto loop; \
+ } while (0)
+
+
+extern void mips_break( int error );
+
+/* Bitfield handler macros */
+
+/*
+ * This routine sets _output to the bit number of the first bit
+ * set in _value. _value is of CPU dependent type Priority_Bit_map_control.
+ * This type may be either 16 or 32 bits wide although only the 16
+ * least significant bits will be used.
+ *
+ * There are a number of variables in using a "find first bit" type
+ * instruction.
+ *
+ * (1) What happens when run on a value of zero?
+ * (2) Bits may be numbered from MSB to LSB or vice-versa.
+ * (3) The numbering may be zero or one based.
+ * (4) The "find first bit" instruction may search from MSB or LSB.
+ *
+ * RTEMS guarantees that (1) will never happen so it is not a concern.
+ * (2),(3), (4) are handled by the macros _CPU_Priority_mask() and
+ * _CPU_Priority_bits_index(). These three form a set of routines
+ * which must logically operate together. Bits in the _value are
+ * set and cleared based on masks built by _CPU_Priority_mask().
+ * The basic major and minor values calculated by _Priority_Major()
+ * and _Priority_Minor() are "massaged" by _CPU_Priority_bits_index()
+ * to properly range between the values returned by the "find first bit"
+ * instruction. This makes it possible for _Priority_Get_highest() to
+ * calculate the major and directly index into the minor table.
+ * This mapping is necessary to ensure that 0 (a high priority major/minor)
+ * is the first bit found.
+ *
+ * This entire "find first bit" and mapping process depends heavily
+ * on the manner in which a priority is broken into a major and minor
+ * components with the major being the 4 MSB of a priority and minor
+ * the 4 LSB. Thus (0 << 4) + 0 corresponds to priority 0 -- the highest
+ * priority. And (15 << 4) + 14 corresponds to priority 254 -- the next
+ * to the lowest priority.
+ *
+ * If your CPU does not have a "find first bit" instruction, then
+ * there are ways to make do without it. Here are a handful of ways
+ * to implement this in software:
+ *
+ * - a series of 16 bit test instructions
+ * - a "binary search using if's"
+ * - _number = 0
+ * if _value > 0x00ff
+ * _value >>=8
+ * _number = 8;
+ *
+ * if _value > 0x0000f
+ * _value >=8
+ * _number += 4
+ *
+ * _number += bit_set_table[ _value ]
+ *
+ * where bit_set_table[ 16 ] has values which indicate the first
+ * bit set
+ */
+
+#define CPU_USE_GENERIC_BITFIELD_CODE TRUE
+#define CPU_USE_GENERIC_BITFIELD_DATA TRUE
+
+#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
+
+#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
+ { \
+ (_output) = 0; /* do something to prevent warnings */ \
+ }
+
+#endif
+
+/* end of Bitfield handler macros */
+
+/*
+ * This routine builds the mask which corresponds to the bit fields
+ * as searched by _CPU_Bitfield_Find_first_bit(). See the discussion
+ * for that routine.
+ */
+
+#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
+
+#define _CPU_Priority_Mask( _bit_number ) \
+ ( 1 << (_bit_number) )
+
+#endif
+
+/*
+ * This routine translates the bit numbers returned by
+ * _CPU_Bitfield_Find_first_bit() into something suitable for use as
+ * a major or minor component of a priority. See the discussion
+ * for that routine.
+ */
+
+#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
+
+#define _CPU_Priority_bits_index( _priority ) \
+ (_priority)
+
+#endif
+
+/* end of Priority handler macros */
+
+/* functions */
+
+/*
+ * _CPU_Initialize
+ *
+ * This routine performs CPU dependent initialization.
+ */
+
+void _CPU_Initialize(
+ rtems_cpu_table *cpu_table,
+ void (*thread_dispatch)
+);
+
+/*
+ * _CPU_ISR_install_raw_handler
+ *
+ * This routine installs a "raw" interrupt handler directly into the
+ * processor's vector table.
+ */
+
+void _CPU_ISR_install_raw_handler(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+);
+
+/*
+ * _CPU_ISR_install_vector
+ *
+ * This routine installs an interrupt vector.
+ */
+
+void _CPU_ISR_install_vector(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+);
+
+/*
+ * _CPU_Install_interrupt_stack
+ *
+ * This routine installs the hardware interrupt stack pointer.
+ *
+ * NOTE: It need only be provided if CPU_HAS_HARDWARE_INTERRUPT_STACK
+ * is TRUE.
+ */
+
+void _CPU_Install_interrupt_stack( void );
+
+/*
+ * _CPU_Internal_threads_Idle_thread_body
+ *
+ * This routine is the CPU dependent IDLE thread body.
+ *
+ * NOTE: It need only be provided if CPU_PROVIDES_IDLE_THREAD_BODY
+ * is TRUE.
+ */
+
+void _CPU_Thread_Idle_body( void );
+
+/*
+ * _CPU_Context_switch
+ *
+ * This routine switches from the run context to the heir context.
+ */
+
+void _CPU_Context_switch(
+ Context_Control *run,
+ Context_Control *heir
+);
+
+/*
+ * _CPU_Context_restore
+ *
+ * This routine is generally used only to restart self in an
+ * efficient manner. It may simply be a label in _CPU_Context_switch.
+ *
+ * NOTE: May be unnecessary to reload some registers.
+ */
+
+void _CPU_Context_restore(
+ Context_Control *new_context
+);
+
+/*
+ * _CPU_Context_save_fp
+ *
+ * This routine saves the floating point context passed to it.
+ */
+
+void _CPU_Context_save_fp(
+ void **fp_context_ptr
+);
+
+/*
+ * _CPU_Context_restore_fp
+ *
+ * This routine restores the floating point context passed to it.
+ */
+
+void _CPU_Context_restore_fp(
+ void **fp_context_ptr
+);
+
+/* The following routine swaps the endian format of an unsigned int.
+ * It must be static because it is referenced indirectly.
+ *
+ * This version will work on any processor, but if there is a better
+ * way for your CPU PLEASE use it. The most common way to do this is to:
+ *
+ * swap least significant two bytes with 16-bit rotate
+ * swap upper and lower 16-bits
+ * swap most significant two bytes with 16-bit rotate
+ *
+ * Some CPUs have special instructions which swap a 32-bit quantity in
+ * a single instruction (e.g. i486). It is probably best to avoid
+ * an "endian swapping control bit" in the CPU. One good reason is
+ * that interrupts would probably have to be disabled to insure that
+ * an interrupt does not try to access the same "chunk" with the wrong
+ * endian. Another good reason is that on some CPUs, the endian bit
+ * endianness for ALL fetches -- both code and data -- so the code
+ * will be fetched incorrectly.
+ */
+
+static inline unsigned int CPU_swap_u32(
+ unsigned int value
+)
+{
+ uint32_t byte1, byte2, byte3, byte4, swapped;
+
+ byte4 = (value >> 24) & 0xff;
+ byte3 = (value >> 16) & 0xff;
+ byte2 = (value >> 8) & 0xff;
+ byte1 = value & 0xff;
+
+ swapped = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
+ return( swapped );
+}
+
+#define CPU_swap_u16( value ) \
+ (((value&0xff) << 8) | ((value >> 8)&0xff))
+
+
+#endif
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/score/cpu/mips/rtems/score/mips.h b/cpukit/score/cpu/mips/rtems/score/mips.h
new file mode 100644
index 0000000000..2e314ce95b
--- /dev/null
+++ b/cpukit/score/cpu/mips/rtems/score/mips.h
@@ -0,0 +1,271 @@
+/* mips.h
+ *
+ * COPYRIGHT (c) 1989-2001.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef _INCLUDE_MIPS_h
+#define _INCLUDE_MIPS_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef ASM
+#include <rtems/mips/idtcpu.h>
+#endif
+
+/*
+ * SR bits that enable/disable interrupts
+ *
+ * NOTE: XXX what about SR_ERL?
+ */
+
+#if __mips == 3
+#ifdef ASM
+#define SR_INTERRUPT_ENABLE_BITS 0x01
+#else
+#define SR_INTERRUPT_ENABLE_BITS SR_IE
+#endif
+
+#elif __mips == 1
+#define SR_INTERRUPT_ENABLE_BITS SR_IEC
+
+#else
+#error "mips interrupt enable bits: unknown architecture level!"
+#endif
+
+/*
+ * This file contains the information required to build
+ * RTEMS for a particular member of the "no cpu"
+ * family when executing in protected mode. It does
+ * this by setting variables to indicate which implementation
+ * dependent features are present in a particular member
+ * of the family.
+ */
+
+#if defined(__mips_soft_float)
+#define MIPS_HAS_FPU 0
+#else
+#define MIPS_HAS_FPU 1
+#endif
+
+#if (__mips == 1)
+#define CPU_MODEL_NAME "ISA Level 1 or 2"
+#elif (__mips == 3)
+#if defined(__mips64)
+#define CPU_MODEL_NAME "ISA Level 4"
+#else
+#define CPU_MODEL_NAME "ISA Level 3"
+#endif
+#else
+#error "Unknown MIPS ISA level"
+#endif
+
+/*
+ * Define the name of the CPU family.
+ */
+
+#define CPU_NAME "MIPS"
+
+/*
+ * RTEMS Vector numbers for exception conditions. This is a direct
+ * map to the causes.
+ */
+
+#define MIPS_EXCEPTION_BASE 0
+
+#define MIPS_EXCEPTION_INT MIPS_EXCEPTION_BASE+0
+#define MIPS_EXCEPTION_MOD MIPS_EXCEPTION_BASE+1
+#define MIPS_EXCEPTION_TLBL MIPS_EXCEPTION_BASE+2
+#define MIPS_EXCEPTION_TLBS MIPS_EXCEPTION_BASE+3
+#define MIPS_EXCEPTION_ADEL MIPS_EXCEPTION_BASE+4
+#define MIPS_EXCEPTION_ADES MIPS_EXCEPTION_BASE+5
+#define MIPS_EXCEPTION_IBE MIPS_EXCEPTION_BASE+6
+#define MIPS_EXCEPTION_DBE MIPS_EXCEPTION_BASE+7
+#define MIPS_EXCEPTION_SYSCALL MIPS_EXCEPTION_BASE+8
+#define MIPS_EXCEPTION_BREAK MIPS_EXCEPTION_BASE+9
+#define MIPS_EXCEPTION_RI MIPS_EXCEPTION_BASE+10
+#define MIPS_EXCEPTION_CPU MIPS_EXCEPTION_BASE+11
+#define MIPS_EXCEPTION_OVERFLOW MIPS_EXCEPTION_BASE+12
+#define MIPS_EXCEPTION_TRAP MIPS_EXCEPTION_BASE+13
+#define MIPS_EXCEPTION_VCEI MIPS_EXCEPTION_BASE+14
+/* FPE only on mips2 and higher */
+#define MIPS_EXCEPTION_FPE MIPS_EXCEPTION_BASE+15
+#define MIPS_EXCEPTION_C2E MIPS_EXCEPTION_BASE+16
+/* 17-22 reserved */
+#define MIPS_EXCEPTION_WATCH MIPS_EXCEPTION_BASE+23
+/* 24-30 reserved */
+#define MIPS_EXCEPTION_VCED MIPS_EXCEPTION_BASE+31
+
+#define MIPS_INTERRUPT_BASE MIPS_EXCEPTION_BASE+32
+
+/*
+ * Some macros to access registers
+ */
+
+#define mips_get_sr( _x ) \
+ do { \
+ asm volatile( "mfc0 %0, $12; nop" : "=r" (_x) : ); \
+ } while (0)
+
+#define mips_set_sr( _x ) \
+ do { \
+ register unsigned int __x = (_x); \
+ asm volatile( "mtc0 %0, $12; nop" : : "r" (__x) ); \
+ } while (0)
+
+
+/*
+ * Access the Cause register
+ */
+
+#define mips_get_cause( _x ) \
+ do { \
+ asm volatile( "mfc0 %0, $13; nop" : "=r" (_x) : ); \
+ } while (0)
+
+
+#define mips_set_cause( _x ) \
+ do { \
+ register unsigned int __x = (_x); \
+ asm volatile( "mtc0 %0, $13; nop" : : "r" (__x) ); \
+ } while (0)
+
+
+
+
+/*
+ * Access the Debug Cache Invalidate Control register
+ */
+
+#define mips_get_dcic( _x ) \
+ do { \
+ asm volatile( "mfc0 %0, $7; nop" : "=r" (_x) : ); \
+ } while (0)
+
+
+#define mips_set_dcic( _x ) \
+ do { \
+ register unsigned int __x = (_x); \
+ asm volatile( "mtc0 %0, $7; nop" : : "r" (__x) ); \
+ } while (0)
+
+
+
+
+/*
+ * Access the Breakpoint Program Counter & Mask registers
+ * (_x for BPC, _y for mask)
+ */
+
+#define mips_get_bpcrm( _x, _y ) \
+ do { \
+ asm volatile( "mfc0 %0, $3; nop" : "=r" (_x) : ); \
+ asm volatile( "mfc0 %0, $11; nop" : "=r" (_y) : ); \
+ } while (0)
+
+
+#define mips_set_bpcrm( _x, _y ) \
+ do { \
+ register unsigned int __x = (_x); \
+ register unsigned int __y = (_y); \
+ asm volatile( "mtc0 %0, $11; nop" : : "r" (__y) ); \
+ asm volatile( "mtc0 %0, $3; nop" : : "r" (__x) ); \
+ } while (0)
+
+
+
+
+
+
+/*
+ * Access the Breakpoint Data Address & Mask registers
+ * (_x for BDA, _y for mask)
+ */
+
+#define mips_get_bdarm( _x, _y ) \
+ do { \
+ asm volatile( "mfc0 %0, $5; nop" : "=r" (_x) : ); \
+ asm volatile( "mfc0 %0, $9; nop" : "=r" (_y) : ); \
+ } while (0)
+
+
+#define mips_set_bdarm( _x, _y ) \
+ do { \
+ register unsigned int __x = (_x); \
+ register unsigned int __y = (_y); \
+ asm volatile( "mtc0 %0, $9; nop" : : "r" (__y) ); \
+ asm volatile( "mtc0 %0, $5; nop" : : "r" (__x) ); \
+ } while (0)
+
+
+
+
+
+
+
+/*
+ * Access FCR31
+ */
+
+#define mips_get_fcr31( _x ) \
+ do { \
+ asm volatile( "cfc1 %0, $31; nop" : "=r" (_x) : ); \
+ } while(0)
+
+
+#define mips_set_fcr31( _x ) \
+ do { \
+ register unsigned int __x = (_x); \
+ asm volatile( "ctc1 %0, $31; nop" : : "r" (__x) ); \
+ } while(0)
+
+
+/*
+ * Manipulate interrupt mask
+ *
+ * mips_unmask_interrupt( _mask)
+ * enables interrupts - mask is positioned so it only needs to be or'ed
+ * into the status reg. This also does some other things !!!! Caution
+ * should be used if invoking this while in the middle of a debugging
+ * session where the client may have nested interrupts.
+ *
+ * mips_mask_interrupt( _mask )
+ * disable the interrupt - mask is the complement of the bits to be
+ * cleared - i.e. to clear ext int 5 the mask would be - 0xffff7fff
+ *
+ *
+ * NOTE: mips_mask_interrupt() used to be disable_int().
+ * mips_unmask_interrupt() used to be enable_int().
+ *
+ */
+
+#define mips_enable_in_interrupt_mask( _mask ) \
+ do { \
+ unsigned int _sr; \
+ mips_get_sr( _sr ); \
+ _sr |= (_mask); \
+ mips_set_sr( _sr ); \
+ } while (0)
+
+#define mips_disable_in_interrupt_mask( _mask ) \
+ do { \
+ unsigned int _sr; \
+ mips_get_sr( _sr ); \
+ _sr &= ~(_mask); \
+ mips_set_sr( _sr ); \
+ } while (0)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ! _INCLUDE_MIPS_h */
+/* end of include file */
diff --git a/cpukit/score/cpu/mips/rtems/score/types.h b/cpukit/score/cpu/mips/rtems/score/types.h
new file mode 100644
index 0000000000..2eadf7a4b1
--- /dev/null
+++ b/cpukit/score/cpu/mips/rtems/score/types.h
@@ -0,0 +1,57 @@
+/* mipstypes.h
+ *
+ * This include file contains type definitions pertaining to the MIPS
+ * processor family.
+ *
+ * COPYRIGHT (c) 1989-2001.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+/* @(#)mipstypes.h 08/20/96 1.4 */
+
+#ifndef __MIPS_TYPES_h
+#define __MIPS_TYPES_h
+
+#ifndef ASM
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This section defines the basic types for this processor.
+ */
+
+typedef unsigned char unsigned8; /* unsigned 8-bit integer */
+typedef unsigned short unsigned16; /* unsigned 16-bit integer */
+typedef unsigned int unsigned32; /* unsigned 32-bit integer */
+typedef unsigned long long unsigned64; /* unsigned 64-bit integer */
+
+typedef unsigned16 Priority_Bit_map_control;
+
+typedef signed char signed8; /* 8-bit signed integer */
+typedef signed short signed16; /* 16-bit signed integer */
+typedef signed int signed32; /* 32-bit signed integer */
+typedef signed long long signed64; /* 64 bit signed integer */
+
+typedef unsigned32 boolean; /* Boolean value */
+
+typedef float single_precision; /* single precision float */
+typedef double double_precision; /* double precision float */
+
+typedef void mips_isr;
+typedef void ( *mips_isr_entry )( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !ASM */
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/no_cpu/.cvsignore b/cpukit/score/cpu/no_cpu/.cvsignore
new file mode 100644
index 0000000000..282522db03
--- /dev/null
+++ b/cpukit/score/cpu/no_cpu/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/cpukit/score/cpu/no_cpu/ChangeLog b/cpukit/score/cpu/no_cpu/ChangeLog
new file mode 100644
index 0000000000..73950edf36
--- /dev/null
+++ b/cpukit/score/cpu/no_cpu/ChangeLog
@@ -0,0 +1,228 @@
+2004-04-06 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * configure.ac: Remove (Merged into$(top_srcdir)/configure.ac).
+ * Makefile.am: Don't include multilib.am.
+ Reflect merging configure.ac into $(top_srcdir)/configure.ac.
+
+2004-04-01 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * Makefile.am: Install asm.h to $(includedir)/rtems.
+
+2004-03-30 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * cpu.c, rtems/score/cpu.h: Convert to using c99 fixed size types.
+
+2004-03-29 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * configure.ac: RTEMS_TOP([../../../..]).
+
+2004-01-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Move RTEMS_TOP one subdir down.
+
+2004-01-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add PREINSTALL_DIRS.
+
+2004-01-14 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Re-add dirstamps to PREINSTALL_FILES.
+ Add PREINSTALL_FILES to CLEANFILES.
+
+2004-01-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Requires automake >= 1.8.1.
+
+2004-01-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include compile.am, again.
+
+2004-01-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Convert to using automake compilation rules.
+
+2003-12-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use mkdir_p. Remove dirs from PREINSTALL_FILES.
+
+2003-12-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Require automake >= 1.8, autoconf >= 2.59.
+
+2003-12-01 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Remove TMPINSTALL_FILES.
+
+2003-11-30 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add $(dirstamp) to preinstallation rules.
+
+2003-11-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Don't use gmake rules for preinstallation.
+
+2003-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_CANONICAL_HOST.
+
+2003-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_CHECK_CPU.
+
+2003-09-26 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/cpu.h: Obsoleting HP PA-RISC port and removing all
+ references.
+
+2003-09-04 Joel Sherrill <joel@OARcorp.com>
+
+ * cpu.c, cpu_asm.c, rtems/score/cpu.h, rtems/score/cpu_asm.h,
+ rtems/score/no_cpu.h, rtems/score/types.h: URL for license changed.
+
+2003-08-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use rtems-bugs@rtems.com as bug report email address.
+
+2003-03-06 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove AC_CONFIG_AUX_DIR.
+
+2003-02-11 Joel Sherrill <joel@OARcorp.com>
+
+ * cpu_asm.c: Rework logic that decides when to call
+ _Thread_Dispatch. Analysis by Sergei Organov <osv@javad.ru>
+ determined that _ISR_Signals_to_thread_executing was not being
+ honored and/or cleared properly.
+
+2002-12-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Require autoconf-2.57 + automake-1.7.2.
+ * Makefile.am: Eliminate C_O_FILES, S_O_FILES, libscorecpu_a_OBJECTS.
+
+2002-11-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Fix package name.
+
+2002-10-25 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Add nostdinc to AM_INIT_AUTOMAKE.
+
+2002-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * .cvsignore: Reformat.
+ Add autom4te*cache.
+ Remove autom4te.cache.
+
+2002-07-26 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Build libscorecpu.a instead of rtems-cpu.rel.
+
+2002-07-22 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use .$(OBJEXT) instead of .o.
+
+2002-07-05 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: RTEMS_TOP(../../../..).
+
+2002-07-03 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems.c: Remove.
+ * Makefile.am: Reflect changes above.
+
+2002-07-01 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_PROJECT_ROOT.
+
+2002-06-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Add RTEMS_PROG_CCAS
+
+2002-06-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use AC_CONFIG_AUX_DIR(../../../..).
+ Add AC_PROG_RANLIB.
+
+2002-06-17 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include $(top_srcdir)/../../../automake/*.am.
+ Use ../../../aclocal.
+
+2001-04-03 Joel Sherrill <joel@OARcorp.com>
+
+ * Per PR94, all rtems/score/CPUtypes.h are named rtems/score/types.h.
+ * rtems/score/no_cputypes.h: Removed.
+ * rtems/score/types.h: New file via CVS magic.
+ * Makefile.am, rtems/score/cpu.h: Account for name change.
+
+2002-03-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac:
+ AC_INIT(package,_RTEMS_VERSION,_RTEMS_BUGS).
+ AM_INIT_AUTOMAKE([no-define foreign 1.6]).
+ * Makefile.am: Remove AUTOMAKE_OPTIONS.
+
+2002-01-29 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/Makefile.am: Removed.
+ * rtems/score/Makefile.am: Removed.
+ * configure.ac: Reflect changes above.
+ * Makefile.am: Reflect changes above.
+
+2001-12-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add multilib support.
+
+2001-11-28 Joel Sherrill <joel@OARcorp.com>,
+
+ This was tracked as PR91.
+ * rtems/score/cpu.h: Added CPU_PROVIDES_ISR_IS_IN_PROGRESS macro which
+ is used to specify if the port uses the standard macro for this (FALSE).
+ A TRUE setting indicates the port provides its own implementation.
+
+2001-10-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * .cvsignore: Add autom4te.cache for autoconf > 2.52.
+ * configure.in: Remove.
+ * configure.ac: New file, generated from configure.in by autoupdate.
+
+2001-09-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/score/Makefile.am: Use 'PREINSTALL_FILES ='.
+ * Makefile.am: Use 'PREINSTALL_FILES ='.
+
+2001-02-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am, rtems/score/Makefile.am:
+ Apply include_*HEADERS instead of H_FILES.
+
+2001-01-03 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/cpu.h: Added _CPU_Initialize_vectors().
+
+2000-11-09 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use ... instead of RTEMS_TOPdir in ACLOCAL_AMFLAGS.
+
+2000-11-02 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Switch to ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal.
+
+2000-10-25 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: ACLOCAL_AMFLAGS= -I $(RTEMS_TOPdir)/macros.
+ Switch to GNU canonicalization.
+
+2000-09-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include compile.am.
+
+2000-08-25 Joel Sherrill <joel.sherrill@OARcorp.com>
+
+ * rtems/score/no_cpu.h: Modified so there are fewer and
+ more consistent variations on "no cpu" so it is easier
+ to sed the source as the starting point for a new port.
+
+2000-08-10 Joel Sherrill <joel@OARcorp.com>
+
+ * ChangeLog: New file.
diff --git a/cpukit/score/cpu/no_cpu/Makefile.am b/cpukit/score/cpu/no_cpu/Makefile.am
new file mode 100644
index 0000000000..ef22e75798
--- /dev/null
+++ b/cpukit/score/cpu/no_cpu/Makefile.am
@@ -0,0 +1,62 @@
+##
+## $Id$
+##
+
+include $(top_srcdir)/automake/compile.am
+
+include_rtemsdir = $(includedir)/rtems
+include_rtems_HEADERS = asm.h
+
+include_rtems_scoredir = $(includedir)/rtems/score
+include_rtems_score_HEADERS = rtems/score/cpu.h rtems/score/no_cpu.h \
+ rtems/score/cpu_asm.h rtems/score/types.h
+
+EXTRA_LIBRARIES = libscorecpu.a
+CLEANFILES = libscorecpu.a
+libscorecpu_a_SOURCES = cpu.c cpu_asm.c
+libscorecpu_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libscorecpu_g.a
+CLEANFILES += libscorecpu_g.a
+libscorecpu_g_a_SOURCES = $(libscorecpu_a_SOURCES)
+libscorecpu_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+all-local: $(PREINSTALL_FILES) libscorecpu$(LIB_VARIANT).a
+
+PREINSTALL_DIRS =
+PREINSTALL_FILES =
+
+$(PROJECT_INCLUDE)/rtems/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems
+ @: > $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/asm.h: asm.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/asm.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/asm.h
+
+$(PROJECT_INCLUDE)/rtems/score/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems/score
+ @: > $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/score/cpu.h: rtems/score/cpu.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/cpu.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/cpu.h
+
+$(PROJECT_INCLUDE)/rtems/score/no_cpu.h: rtems/score/no_cpu.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/no_cpu.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/no_cpu.h
+
+$(PROJECT_INCLUDE)/rtems/score/cpu_asm.h: rtems/score/cpu_asm.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/cpu_asm.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/cpu_asm.h
+
+$(PROJECT_INCLUDE)/rtems/score/types.h: rtems/score/types.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/types.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/types.h
+
+CLEANFILES += $(PREINSTALL_FILES)
+DISTCLEANFILES = $(PREINSTALL_DIRS)
+
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/score/cpu/no_cpu/asm.h b/cpukit/score/cpu/no_cpu/asm.h
new file mode 100644
index 0000000000..c97b616c9e
--- /dev/null
+++ b/cpukit/score/cpu/no_cpu/asm.h
@@ -0,0 +1,99 @@
+/* asm.h
+ *
+ * This include file attempts to address the problems
+ * caused by incompatible flavors of assemblers and
+ * toolsets. It primarily addresses variations in the
+ * use of leading underscores on symbols and the requirement
+ * that register names be preceded by a %.
+ *
+ *
+ * NOTE: The spacing in the use of these macros
+ * is critical to them working as advertised.
+ *
+ * COPYRIGHT:
+ *
+ * This file is based on similar code found in newlib available
+ * from ftp.cygnus.com. The file which was used had no copyright
+ * notice. This file is freely distributable as long as the source
+ * of the file is noted. This file is:
+ *
+ * COPYRIGHT (c) 1994-1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * $Id$
+ */
+
+#ifndef __NO_CPU_ASM_h
+#define __NO_CPU_ASM_h
+
+/*
+ * Indicate we are in an assembly file and get the basic CPU definitions.
+ */
+
+#ifndef ASM
+#define ASM
+#endif
+#include <rtems/score/cpuopts.h>
+#include <rtems/score/no_cpu.h>
+
+/*
+ * Recent versions of GNU cpp define variables which indicate the
+ * need for underscores and percents. If not using GNU cpp or
+ * the version does not support this, then you will obviously
+ * have to define these as appropriate.
+ */
+
+#ifndef __USER_LABEL_PREFIX__
+#define __USER_LABEL_PREFIX__ _
+#endif
+
+#ifndef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__
+#endif
+
+/* ANSI concatenation macros. */
+
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+/* Use the right prefix for global labels. */
+
+#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+
+/* Use the right prefix for registers. */
+
+#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
+
+/*
+ * define macros for all of the registers on this CPU
+ *
+ * EXAMPLE: #define d0 REG (d0)
+ */
+
+/*
+ * Define macros to handle section beginning and ends.
+ */
+
+
+#define BEGIN_CODE_DCL .text
+#define END_CODE_DCL
+#define BEGIN_DATA_DCL .data
+#define END_DATA_DCL
+#define BEGIN_CODE .text
+#define END_CODE
+#define BEGIN_DATA
+#define END_DATA
+#define BEGIN_BSS
+#define END_BSS
+#define END
+
+/*
+ * Following must be tailor for a particular flavor of the C compiler.
+ * They may need to put underscores in front of the symbols.
+ */
+
+#define PUBLIC(sym) .globl SYM (sym)
+#define EXTERN(sym) .globl SYM (sym)
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/no_cpu/cpu.c b/cpukit/score/cpu/no_cpu/cpu.c
new file mode 100644
index 0000000000..2796c707ea
--- /dev/null
+++ b/cpukit/score/cpu/no_cpu/cpu.c
@@ -0,0 +1,185 @@
+/*
+ * XXX CPU Dependent Source
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/wkspace.h>
+
+/* _CPU_Initialize
+ *
+ * This routine performs processor dependent initialization.
+ *
+ * INPUT PARAMETERS:
+ * cpu_table - CPU table to initialize
+ * thread_dispatch - address of disptaching routine
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+
+void _CPU_Initialize(
+ rtems_cpu_table *cpu_table,
+ void (*thread_dispatch) /* ignored on this CPU */
+)
+{
+ /*
+ * The thread_dispatch argument is the address of the entry point
+ * for the routine called at the end of an ISR once it has been
+ * decided a context switch is necessary. On some compilation
+ * systems it is difficult to call a high-level language routine
+ * from assembly. This allows us to trick these systems.
+ *
+ * If you encounter this problem save the entry point in a CPU
+ * dependent variable.
+ */
+
+ _CPU_Thread_dispatch_pointer = thread_dispatch;
+
+ /*
+ * If there is not an easy way to initialize the FP context
+ * during Context_Initialize, then it is usually easier to
+ * save an "uninitialized" FP context here and copy it to
+ * the task's during Context_Initialize.
+ */
+
+ /* FP context initialization support goes here */
+
+ _CPU_Table = *cpu_table;
+}
+
+/*PAGE
+ *
+ * _CPU_ISR_Get_level
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+uint32_t _CPU_ISR_Get_level( void )
+{
+ /*
+ * This routine returns the current interrupt level.
+ */
+
+ return 0;
+}
+
+/*PAGE
+ *
+ * _CPU_ISR_install_raw_handler
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+void _CPU_ISR_install_raw_handler(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+)
+{
+ /*
+ * This is where we install the interrupt handler into the "raw" interrupt
+ * table used by the CPU to dispatch interrupt handlers.
+ */
+}
+
+/*PAGE
+ *
+ * _CPU_ISR_install_vector
+ *
+ * This kernel routine installs the RTEMS handler for the
+ * specified vector.
+ *
+ * Input parameters:
+ * vector - interrupt vector number
+ * old_handler - former ISR for this vector number
+ * new_handler - replacement ISR for this vector number
+ *
+ * Output parameters: NONE
+ *
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+void _CPU_ISR_install_vector(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+)
+{
+ *old_handler = _ISR_Vector_table[ vector ];
+
+ /*
+ * If the interrupt vector table is a table of pointer to isr entry
+ * points, then we need to install the appropriate RTEMS interrupt
+ * handler for this vector number.
+ */
+
+ _CPU_ISR_install_raw_handler( vector, new_handler, old_handler );
+
+ /*
+ * We put the actual user ISR address in '_ISR_vector_table'. This will
+ * be used by the _ISR_Handler so the user gets control.
+ */
+
+ _ISR_Vector_table[ vector ] = new_handler;
+}
+
+/*PAGE
+ *
+ * _CPU_Install_interrupt_stack
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+void _CPU_Install_interrupt_stack( void )
+{
+}
+
+/*PAGE
+ *
+ * _CPU_Thread_Idle_body
+ *
+ * NOTES:
+ *
+ * 1. This is the same as the regular CPU independent algorithm.
+ *
+ * 2. If you implement this using a "halt", "idle", or "shutdown"
+ * instruction, then don't forget to put it in an infinite loop.
+ *
+ * 3. Be warned. Some processors with onboard DMA have been known
+ * to stop the DMA if the CPU were put in IDLE mode. This might
+ * also be a problem with other on-chip peripherals. So use this
+ * hook with caution.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+void _CPU_Thread_Idle_body( void )
+{
+
+ for( ; ; )
+ /* insert your "halt" instruction here */ ;
+}
diff --git a/cpukit/score/cpu/no_cpu/cpu_asm.c b/cpukit/score/cpu/no_cpu/cpu_asm.c
new file mode 100644
index 0000000000..2ca67a07ad
--- /dev/null
+++ b/cpukit/score/cpu/no_cpu/cpu_asm.c
@@ -0,0 +1,182 @@
+/* cpu_asm.c ===> cpu_asm.S or cpu_asm.s
+ *
+ * This file contains the basic algorithms for all assembly code used
+ * in an specific CPU port of RTEMS. These algorithms must be implemented
+ * in assembly language
+ *
+ * NOTE: This is supposed to be a .S or .s file NOT a C file.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+/*
+ * This is supposed to be an assembly file. This means that system.h
+ * and cpu.h should not be included in a "real" cpu_asm file. An
+ * implementation in assembly should include "cpu_asm.h>
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/cpu.h>
+/* #include "cpu_asm.h> */
+
+/*
+ * _CPU_Context_save_fp_context
+ *
+ * This routine is responsible for saving the FP context
+ * at *fp_context_ptr. If the point to load the FP context
+ * from is changed then the pointer is modified by this routine.
+ *
+ * Sometimes a macro implementation of this is in cpu.h which dereferences
+ * the ** and a similarly named routine in this file is passed something
+ * like a (Context_Control_fp *). The general rule on making this decision
+ * is to avoid writing assembly language.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+void _CPU_Context_save_fp(
+ void **fp_context_ptr
+)
+{
+}
+
+/*
+ * _CPU_Context_restore_fp_context
+ *
+ * This routine is responsible for restoring the FP context
+ * at *fp_context_ptr. If the point to load the FP context
+ * from is changed then the pointer is modified by this routine.
+ *
+ * Sometimes a macro implementation of this is in cpu.h which dereferences
+ * the ** and a similarly named routine in this file is passed something
+ * like a (Context_Control_fp *). The general rule on making this decision
+ * is to avoid writing assembly language.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+void _CPU_Context_restore_fp(
+ void **fp_context_ptr
+)
+{
+}
+
+/* _CPU_Context_switch
+ *
+ * This routine performs a normal non-FP context switch.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+void _CPU_Context_switch(
+ Context_Control *run,
+ Context_Control *heir
+)
+{
+}
+
+/*
+ * _CPU_Context_restore
+ *
+ * This routine is generally used only to restart self in an
+ * efficient manner. It may simply be a label in _CPU_Context_switch.
+ *
+ * NOTE: May be unnecessary to reload some registers.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+void _CPU_Context_restore(
+ Context_Control *new_context
+)
+{
+}
+
+/* void __ISR_Handler()
+ *
+ * This routine provides the RTEMS interrupt management.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+void _ISR_Handler()
+{
+ /*
+ * This discussion ignores a lot of the ugly details in a real
+ * implementation such as saving enough registers/state to be
+ * able to do something real. Keep in mind that the goal is
+ * to invoke a user's ISR handler which is written in C and
+ * uses a certain set of registers.
+ *
+ * Also note that the exact order is to a large extent flexible.
+ * Hardware will dictate a sequence for a certain subset of
+ * _ISR_Handler while requirements for setting
+ */
+
+ /*
+ * At entry to "common" _ISR_Handler, the vector number must be
+ * available. On some CPUs the hardware puts either the vector
+ * number or the offset into the vector table for this ISR in a
+ * known place. If the hardware does not give us this information,
+ * then the assembly portion of RTEMS for this port will contain
+ * a set of distinct interrupt entry points which somehow place
+ * the vector number in a known place (which is safe if another
+ * interrupt nests this one) and branches to _ISR_Handler.
+ *
+ * save some or all context on stack
+ * may need to save some special interrupt information for exit
+ *
+ * #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
+ * if ( _ISR_Nest_level == 0 )
+ * switch to software interrupt stack
+ * #endif
+ *
+ * _ISR_Nest_level++;
+ *
+ * _Thread_Dispatch_disable_level++;
+ *
+ * (*_ISR_Vector_table[ vector ])( vector );
+ *
+ * _Thread_Dispatch_disable_level--;
+ *
+ * --_ISR_Nest_level;
+ *
+ * if ( _ISR_Nest_level )
+ * goto the label "exit interrupt (simple case)"
+ *
+ * if ( _Thread_Dispatch_disable_level )
+ * _ISR_Signals_to_thread_executing = FALSE;
+ * goto the label "exit interrupt (simple case)"
+ *
+ * if ( _Context_Switch_necessary || _ISR_Signals_to_thread_executing ) {
+ * _ISR_Signals_to_thread_executing = FALSE;
+ * call _Thread_Dispatch() or prepare to return to _ISR_Dispatch
+ * prepare to get out of interrupt
+ * return from interrupt (maybe to _ISR_Dispatch)
+ *
+ * LABEL "exit interrupt (simple case):
+ * #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
+ * if outermost interrupt
+ * restore stack
+ * #endif
+ * prepare to get out of interrupt
+ * return from interrupt
+ */
+}
diff --git a/cpukit/score/cpu/no_cpu/rtems/asm.h b/cpukit/score/cpu/no_cpu/rtems/asm.h
new file mode 100644
index 0000000000..c97b616c9e
--- /dev/null
+++ b/cpukit/score/cpu/no_cpu/rtems/asm.h
@@ -0,0 +1,99 @@
+/* asm.h
+ *
+ * This include file attempts to address the problems
+ * caused by incompatible flavors of assemblers and
+ * toolsets. It primarily addresses variations in the
+ * use of leading underscores on symbols and the requirement
+ * that register names be preceded by a %.
+ *
+ *
+ * NOTE: The spacing in the use of these macros
+ * is critical to them working as advertised.
+ *
+ * COPYRIGHT:
+ *
+ * This file is based on similar code found in newlib available
+ * from ftp.cygnus.com. The file which was used had no copyright
+ * notice. This file is freely distributable as long as the source
+ * of the file is noted. This file is:
+ *
+ * COPYRIGHT (c) 1994-1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * $Id$
+ */
+
+#ifndef __NO_CPU_ASM_h
+#define __NO_CPU_ASM_h
+
+/*
+ * Indicate we are in an assembly file and get the basic CPU definitions.
+ */
+
+#ifndef ASM
+#define ASM
+#endif
+#include <rtems/score/cpuopts.h>
+#include <rtems/score/no_cpu.h>
+
+/*
+ * Recent versions of GNU cpp define variables which indicate the
+ * need for underscores and percents. If not using GNU cpp or
+ * the version does not support this, then you will obviously
+ * have to define these as appropriate.
+ */
+
+#ifndef __USER_LABEL_PREFIX__
+#define __USER_LABEL_PREFIX__ _
+#endif
+
+#ifndef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__
+#endif
+
+/* ANSI concatenation macros. */
+
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+/* Use the right prefix for global labels. */
+
+#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+
+/* Use the right prefix for registers. */
+
+#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
+
+/*
+ * define macros for all of the registers on this CPU
+ *
+ * EXAMPLE: #define d0 REG (d0)
+ */
+
+/*
+ * Define macros to handle section beginning and ends.
+ */
+
+
+#define BEGIN_CODE_DCL .text
+#define END_CODE_DCL
+#define BEGIN_DATA_DCL .data
+#define END_DATA_DCL
+#define BEGIN_CODE .text
+#define END_CODE
+#define BEGIN_DATA
+#define END_DATA
+#define BEGIN_BSS
+#define END_BSS
+#define END
+
+/*
+ * Following must be tailor for a particular flavor of the C compiler.
+ * They may need to put underscores in front of the symbols.
+ */
+
+#define PUBLIC(sym) .globl SYM (sym)
+#define EXTERN(sym) .globl SYM (sym)
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/no_cpu/rtems/score/cpu.h b/cpukit/score/cpu/no_cpu/rtems/score/cpu.h
new file mode 100644
index 0000000000..55534f7182
--- /dev/null
+++ b/cpukit/score/cpu/no_cpu/rtems/score/cpu.h
@@ -0,0 +1,1142 @@
+/* cpu.h
+ *
+ * This include file contains information pertaining to the XXX
+ * processor.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __CPU_h
+#define __CPU_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/no_cpu.h> /* pick up machine definitions */
+#ifndef ASM
+#include <rtems/score/types.h>
+#endif
+
+/* conditional compilation parameters */
+
+/*
+ * Should the calls to _Thread_Enable_dispatch be inlined?
+ *
+ * If TRUE, then they are inlined.
+ * If FALSE, then a subroutine call is made.
+ *
+ * Basically this is an example of the classic trade-off of size
+ * versus speed. Inlining the call (TRUE) typically increases the
+ * size of RTEMS while speeding up the enabling of dispatching.
+ * [NOTE: In general, the _Thread_Dispatch_disable_level will
+ * only be 0 or 1 unless you are in an interrupt handler and that
+ * interrupt handler invokes the executive.] When not inlined
+ * something calls _Thread_Enable_dispatch which in turns calls
+ * _Thread_Dispatch. If the enable dispatch is inlined, then
+ * one subroutine call is avoided entirely.]
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#define CPU_INLINE_ENABLE_DISPATCH FALSE
+
+/*
+ * Should the body of the search loops in _Thread_queue_Enqueue_priority
+ * be unrolled one time? In unrolled each iteration of the loop examines
+ * two "nodes" on the chain being searched. Otherwise, only one node
+ * is examined per iteration.
+ *
+ * If TRUE, then the loops are unrolled.
+ * If FALSE, then the loops are not unrolled.
+ *
+ * The primary factor in making this decision is the cost of disabling
+ * and enabling interrupts (_ISR_Flash) versus the cost of rest of the
+ * body of the loop. On some CPUs, the flash is more expensive than
+ * one iteration of the loop body. In this case, it might be desirable
+ * to unroll the loop. It is important to note that on some CPUs, this
+ * code is the longest interrupt disable period in RTEMS. So it is
+ * necessary to strike a balance when setting this parameter.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#define CPU_UNROLL_ENQUEUE_PRIORITY TRUE
+
+/*
+ * Does RTEMS manage a dedicated interrupt stack in software?
+ *
+ * If TRUE, then a stack is allocated in _ISR_Handler_initialization.
+ * If FALSE, nothing is done.
+ *
+ * If the CPU supports a dedicated interrupt stack in hardware,
+ * then it is generally the responsibility of the BSP to allocate it
+ * and set it up.
+ *
+ * If the CPU does not support a dedicated interrupt stack, then
+ * the porter has two options: (1) execute interrupts on the
+ * stack of the interrupted task, and (2) have RTEMS manage a dedicated
+ * interrupt stack.
+ *
+ * If this is TRUE, CPU_ALLOCATE_INTERRUPT_STACK should also be TRUE.
+ *
+ * Only one of CPU_HAS_SOFTWARE_INTERRUPT_STACK and
+ * CPU_HAS_HARDWARE_INTERRUPT_STACK should be set to TRUE. It is
+ * possible that both are FALSE for a particular CPU. Although it
+ * is unclear what that would imply about the interrupt processing
+ * procedure on that CPU.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#define CPU_HAS_SOFTWARE_INTERRUPT_STACK FALSE
+
+/*
+ * Does this CPU have hardware support for a dedicated interrupt stack?
+ *
+ * If TRUE, then it must be installed during initialization.
+ * If FALSE, then no installation is performed.
+ *
+ * If this is TRUE, CPU_ALLOCATE_INTERRUPT_STACK should also be TRUE.
+ *
+ * Only one of CPU_HAS_SOFTWARE_INTERRUPT_STACK and
+ * CPU_HAS_HARDWARE_INTERRUPT_STACK should be set to TRUE. It is
+ * possible that both are FALSE for a particular CPU. Although it
+ * is unclear what that would imply about the interrupt processing
+ * procedure on that CPU.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#define CPU_HAS_HARDWARE_INTERRUPT_STACK TRUE
+
+/*
+ * Does RTEMS allocate a dedicated interrupt stack in the Interrupt Manager?
+ *
+ * If TRUE, then the memory is allocated during initialization.
+ * If FALSE, then the memory is allocated during initialization.
+ *
+ * This should be TRUE is CPU_HAS_SOFTWARE_INTERRUPT_STACK is TRUE
+ * or CPU_INSTALL_HARDWARE_INTERRUPT_STACK is TRUE.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#define CPU_ALLOCATE_INTERRUPT_STACK TRUE
+
+/*
+ * Does the RTEMS invoke the user's ISR with the vector number and
+ * a pointer to the saved interrupt frame (1) or just the vector
+ * number (0)?
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#define CPU_ISR_PASSES_FRAME_POINTER 0
+
+/*
+ * Does the CPU have hardware floating point?
+ *
+ * If TRUE, then the RTEMS_FLOATING_POINT task attribute is supported.
+ * If FALSE, then the RTEMS_FLOATING_POINT task attribute is ignored.
+ *
+ * If there is a FP coprocessor such as the i387 or mc68881, then
+ * the answer is TRUE.
+ *
+ * The macro name "NO_CPU_HAS_FPU" should be made CPU specific.
+ * It indicates whether or not this CPU model has FP support. For
+ * example, it would be possible to have an i386_nofp CPU model
+ * which set this to false to indicate that you have an i386 without
+ * an i387 and wish to leave floating point support out of RTEMS.
+ *
+ * The CPU_SOFTWARE_FP is used to indicate whether or not there
+ * is software implemented floating point that must be context
+ * switched. The determination of whether or not this applies
+ * is very tool specific and the state saved/restored is also
+ * compiler specific.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#if ( NO_CPU_HAS_FPU == 1 )
+#define CPU_HARDWARE_FP TRUE
+#else
+#define CPU_HARDWARE_FP FALSE
+#endif
+#define CPU_SOFTWARE_FP FALSE
+
+/*
+ * Are all tasks RTEMS_FLOATING_POINT tasks implicitly?
+ *
+ * If TRUE, then the RTEMS_FLOATING_POINT task attribute is assumed.
+ * If FALSE, then the RTEMS_FLOATING_POINT task attribute is followed.
+ *
+ * So far, the only CPUs in which this option has been used are the
+ * HP PA-RISC and PowerPC. On the PA-RISC, The HP C compiler and
+ * gcc both implicitly used the floating point registers to perform
+ * integer multiplies. Similarly, the PowerPC port of gcc has been
+ * seen to allocate floating point local variables and touch the FPU
+ * even when the flow through a subroutine (like vfprintf()) might
+ * not use floating point formats.
+ *
+ * If a function which you would not think utilize the FP unit DOES,
+ * then one can not easily predict which tasks will use the FP hardware.
+ * In this case, this option should be TRUE.
+ *
+ * If CPU_HARDWARE_FP is FALSE, then this should be FALSE as well.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#define CPU_ALL_TASKS_ARE_FP TRUE
+
+/*
+ * Should the IDLE task have a floating point context?
+ *
+ * If TRUE, then the IDLE task is created as a RTEMS_FLOATING_POINT task
+ * and it has a floating point context which is switched in and out.
+ * If FALSE, then the IDLE task does not have a floating point context.
+ *
+ * Setting this to TRUE negatively impacts the time required to preempt
+ * the IDLE task from an interrupt because the floating point context
+ * must be saved as part of the preemption.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#define CPU_IDLE_TASK_IS_FP FALSE
+
+/*
+ * Should the saving of the floating point registers be deferred
+ * until a context switch is made to another different floating point
+ * task?
+ *
+ * If TRUE, then the floating point context will not be stored until
+ * necessary. It will remain in the floating point registers and not
+ * disturned until another floating point task is switched to.
+ *
+ * If FALSE, then the floating point context is saved when a floating
+ * point task is switched out and restored when the next floating point
+ * task is restored. The state of the floating point registers between
+ * those two operations is not specified.
+ *
+ * If the floating point context does NOT have to be saved as part of
+ * interrupt dispatching, then it should be safe to set this to TRUE.
+ *
+ * Setting this flag to TRUE results in using a different algorithm
+ * for deciding when to save and restore the floating point context.
+ * The deferred FP switch algorithm minimizes the number of times
+ * the FP context is saved and restored. The FP context is not saved
+ * until a context switch is made to another, different FP task.
+ * Thus in a system with only one FP task, the FP context will never
+ * be saved or restored.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#define CPU_USE_DEFERRED_FP_SWITCH TRUE
+
+/*
+ * Does this port provide a CPU dependent IDLE task implementation?
+ *
+ * If TRUE, then the routine _CPU_Thread_Idle_body
+ * must be provided and is the default IDLE thread body instead of
+ * _CPU_Thread_Idle_body.
+ *
+ * If FALSE, then use the generic IDLE thread body if the BSP does
+ * not provide one.
+ *
+ * This is intended to allow for supporting processors which have
+ * a low power or idle mode. When the IDLE thread is executed, then
+ * the CPU can be powered down.
+ *
+ * The order of precedence for selecting the IDLE thread body is:
+ *
+ * 1. BSP provided
+ * 2. CPU dependent (if provided)
+ * 3. generic (if no BSP and no CPU dependent)
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#define CPU_PROVIDES_IDLE_THREAD_BODY TRUE
+
+/*
+ * Does the stack grow up (toward higher addresses) or down
+ * (toward lower addresses)?
+ *
+ * If TRUE, then the grows upward.
+ * If FALSE, then the grows toward smaller addresses.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#define CPU_STACK_GROWS_UP TRUE
+
+/*
+ * The following is the variable attribute used to force alignment
+ * of critical RTEMS structures. On some processors it may make
+ * sense to have these aligned on tighter boundaries than
+ * the minimum requirements of the compiler in order to have as
+ * much of the critical data area as possible in a cache line.
+ *
+ * The placement of this macro in the declaration of the variables
+ * is based on the syntactically requirements of the GNU C
+ * "__attribute__" extension. For example with GNU C, use
+ * the following to force a structures to a 32 byte boundary.
+ *
+ * __attribute__ ((aligned (32)))
+ *
+ * NOTE: Currently only the Priority Bit Map table uses this feature.
+ * To benefit from using this, the data must be heavily
+ * used so it will stay in the cache and used frequently enough
+ * in the executive to justify turning this on.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#define CPU_STRUCTURE_ALIGNMENT
+
+/*
+ * Define what is required to specify how the network to host conversion
+ * routines are handled.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#define CPU_HAS_OWN_HOST_TO_NETWORK_ROUTINES FALSE
+#define CPU_BIG_ENDIAN TRUE
+#define CPU_LITTLE_ENDIAN FALSE
+
+/*
+ * The following defines the number of bits actually used in the
+ * interrupt field of the task mode. How those bits map to the
+ * CPU interrupt levels is defined by the routine _CPU_ISR_Set_level().
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#define CPU_MODES_INTERRUPT_MASK 0x00000001
+
+/*
+ * Processor defined structures
+ *
+ * Examples structures include the descriptor tables from the i386
+ * and the processor control structure on the i960ca.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+/* may need to put some structures here. */
+
+/*
+ * Contexts
+ *
+ * Generally there are 2 types of context to save.
+ * 1. Interrupt registers to save
+ * 2. Task level registers to save
+ *
+ * This means we have the following 3 context items:
+ * 1. task level context stuff:: Context_Control
+ * 2. floating point task stuff:: Context_Control_fp
+ * 3. special interrupt level context :: Context_Control_interrupt
+ *
+ * On some processors, it is cost-effective to save only the callee
+ * preserved registers during a task context switch. This means
+ * that the ISR code needs to save those registers which do not
+ * persist across function calls. It is not mandatory to make this
+ * distinctions between the caller/callee saves registers for the
+ * purpose of minimizing context saved during task switch and on interrupts.
+ * If the cost of saving extra registers is minimal, simplicity is the
+ * choice. Save the same context on interrupt entry as for tasks in
+ * this case.
+ *
+ * Additionally, if gdb is to be made aware of RTEMS tasks for this CPU, then
+ * care should be used in designing the context area.
+ *
+ * On some CPUs with hardware floating point support, the Context_Control_fp
+ * structure will not be used or it simply consist of an array of a
+ * fixed number of bytes. This is done when the floating point context
+ * is dumped by a "FP save context" type instruction and the format
+ * is not really defined by the CPU. In this case, there is no need
+ * to figure out the exact format -- only the size. Of course, although
+ * this is enough information for RTEMS, it is probably not enough for
+ * a debugger such as gdb. But that is another problem.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+typedef struct {
+ uint32_t some_integer_register;
+ uint32_t some_system_register;
+} Context_Control;
+
+typedef struct {
+ double some_float_register;
+} Context_Control_fp;
+
+typedef struct {
+ uint32_t special_interrupt_register;
+} CPU_Interrupt_frame;
+
+
+/*
+ * The following table contains the information required to configure
+ * the XXX processor specific parameters.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+typedef struct {
+ void (*pretasking_hook)( void );
+ void (*predriver_hook)( void );
+ void (*postdriver_hook)( void );
+ void (*idle_task)( void );
+ boolean do_zero_of_workspace;
+ uint32_t idle_task_stack_size;
+ uint32_t interrupt_stack_size;
+ uint32_t extra_mpci_receive_server_stack;
+ void * (*stack_allocate_hook)( uint32_t );
+ void (*stack_free_hook)( void* );
+ /* end of fields required on all CPUs */
+
+} rtems_cpu_table;
+
+/*
+ * Macros to access required entires in the CPU Table are in
+ * the file rtems/system.h.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+/*
+ * Macros to access NO_CPU specific additions to the CPU Table
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+/* There are no CPU specific additions to the CPU Table for this port. */
+
+/*
+ * This variable is optional. It is used on CPUs on which it is difficult
+ * to generate an "uninitialized" FP context. It is filled in by
+ * _CPU_Initialize and copied into the task's FP context area during
+ * _CPU_Context_Initialize.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+SCORE_EXTERN Context_Control_fp _CPU_Null_fp_context;
+
+/*
+ * On some CPUs, RTEMS supports a software managed interrupt stack.
+ * This stack is allocated by the Interrupt Manager and the switch
+ * is performed in _ISR_Handler. These variables contain pointers
+ * to the lowest and highest addresses in the chunk of memory allocated
+ * for the interrupt stack. Since it is unknown whether the stack
+ * grows up or down (in general), this give the CPU dependent
+ * code the option of picking the version it wants to use.
+ *
+ * NOTE: These two variables are required if the macro
+ * CPU_HAS_SOFTWARE_INTERRUPT_STACK is defined as TRUE.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+SCORE_EXTERN void *_CPU_Interrupt_stack_low;
+SCORE_EXTERN void *_CPU_Interrupt_stack_high;
+
+/*
+ * With some compilation systems, it is difficult if not impossible to
+ * call a high-level language routine from assembly language. This
+ * is especially true of commercial Ada compilers and name mangling
+ * C++ ones. This variable can be optionally defined by the CPU porter
+ * and contains the address of the routine _Thread_Dispatch. This
+ * can make it easier to invoke that routine at the end of the interrupt
+ * sequence (if a dispatch is necessary).
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+SCORE_EXTERN void (*_CPU_Thread_dispatch_pointer)();
+
+/*
+ * Nothing prevents the porter from declaring more CPU specific variables.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+/* XXX: if needed, put more variables here */
+
+/*
+ * The size of the floating point context area. On some CPUs this
+ * will not be a "sizeof" because the format of the floating point
+ * area is not defined -- only the size is. This is usually on
+ * CPUs with a "floating point save context" instruction.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#define CPU_CONTEXT_FP_SIZE sizeof( Context_Control_fp )
+
+/*
+ * Amount of extra stack (above minimum stack size) required by
+ * MPCI receive server thread. Remember that in a multiprocessor
+ * system this thread must exist and be able to process all directives.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 0
+
+/*
+ * This defines the number of entries in the ISR_Vector_table managed
+ * by RTEMS.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#define CPU_INTERRUPT_NUMBER_OF_VECTORS 32
+#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1)
+
+/*
+ * This is defined if the port has a special way to report the ISR nesting
+ * level. Most ports maintain the variable _ISR_Nest_level.
+ */
+
+#define CPU_PROVIDES_ISR_IS_IN_PROGRESS FALSE
+
+/*
+ * Should be large enough to run all RTEMS tests. This insures
+ * that a "reasonable" small application should not have any problems.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#define CPU_STACK_MINIMUM_SIZE (1024*4)
+
+/*
+ * CPU's worst alignment requirement for data types on a byte boundary. This
+ * alignment does not take into account the requirements for the stack.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#define CPU_ALIGNMENT 8
+
+/*
+ * This number corresponds to the byte alignment requirement for the
+ * heap handler. This alignment requirement may be stricter than that
+ * for the data types alignment specified by CPU_ALIGNMENT. It is
+ * common for the heap to follow the same alignment requirement as
+ * CPU_ALIGNMENT. If the CPU_ALIGNMENT is strict enough for the heap,
+ * then this should be set to CPU_ALIGNMENT.
+ *
+ * NOTE: This does not have to be a power of 2 although it should be
+ * a multiple of 2 greater than or equal to 2. The requirement
+ * to be a multiple of 2 is because the heap uses the least
+ * significant field of the front and back flags to indicate
+ * that a block is in use or free. So you do not want any odd
+ * length blocks really putting length data in that bit.
+ *
+ * On byte oriented architectures, CPU_HEAP_ALIGNMENT normally will
+ * have to be greater or equal to than CPU_ALIGNMENT to ensure that
+ * elements allocated from the heap meet all restrictions.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#define CPU_HEAP_ALIGNMENT CPU_ALIGNMENT
+
+/*
+ * This number corresponds to the byte alignment requirement for memory
+ * buffers allocated by the partition manager. This alignment requirement
+ * may be stricter than that for the data types alignment specified by
+ * CPU_ALIGNMENT. It is common for the partition to follow the same
+ * alignment requirement as CPU_ALIGNMENT. If the CPU_ALIGNMENT is strict
+ * enough for the partition, then this should be set to CPU_ALIGNMENT.
+ *
+ * NOTE: This does not have to be a power of 2. It does have to
+ * be greater or equal to than CPU_ALIGNMENT.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#define CPU_PARTITION_ALIGNMENT CPU_ALIGNMENT
+
+/*
+ * This number corresponds to the byte alignment requirement for the
+ * stack. This alignment requirement may be stricter than that for the
+ * data types alignment specified by CPU_ALIGNMENT. If the CPU_ALIGNMENT
+ * is strict enough for the stack, then this should be set to 0.
+ *
+ * NOTE: This must be a power of 2 either 0 or greater than CPU_ALIGNMENT.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#define CPU_STACK_ALIGNMENT 0
+
+/*
+ * ISR handler macros
+ */
+
+/*
+ * Support routine to initialize the RTEMS vector table after it is allocated.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#define _CPU_Initialize_vectors()
+
+/*
+ * Disable all interrupts for an RTEMS critical section. The previous
+ * level is returned in _level.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#define _CPU_ISR_Disable( _isr_cookie ) \
+ { \
+ (_isr_cookie) = 0; /* do something to prevent warnings */ \
+ }
+
+/*
+ * Enable interrupts to the previous level (returned by _CPU_ISR_Disable).
+ * This indicates the end of an RTEMS critical section. The parameter
+ * _level is not modified.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#define _CPU_ISR_Enable( _isr_cookie ) \
+ { \
+ }
+
+/*
+ * This temporarily restores the interrupt to _level before immediately
+ * disabling them again. This is used to divide long RTEMS critical
+ * sections into two or more parts. The parameter _level is not
+ * modified.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#define _CPU_ISR_Flash( _isr_cookie ) \
+ { \
+ }
+
+/*
+ * Map interrupt level in task mode onto the hardware that the CPU
+ * actually provides. Currently, interrupt levels which do not
+ * map onto the CPU in a generic fashion are undefined. Someday,
+ * it would be nice if these were "mapped" by the application
+ * via a callout. For example, m68k has 8 levels 0 - 7, levels
+ * 8 - 255 would be available for bsp/application specific meaning.
+ * This could be used to manage a programmable interrupt controller
+ * via the rtems_task_mode directive.
+ *
+ * The get routine usually must be implemented as a subroutine.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#define _CPU_ISR_Set_level( new_level ) \
+ { \
+ }
+
+uint32_t _CPU_ISR_Get_level( void );
+
+/* end of ISR handler macros */
+
+/* Context handler macros */
+
+/*
+ * Initialize the context to a state suitable for starting a
+ * task after a context restore operation. Generally, this
+ * involves:
+ *
+ * - setting a starting address
+ * - preparing the stack
+ * - preparing the stack and frame pointers
+ * - setting the proper interrupt level in the context
+ * - initializing the floating point context
+ *
+ * This routine generally does not set any unnecessary register
+ * in the context. The state of the "general data" registers is
+ * undefined at task start time.
+ *
+ * NOTE: This is_fp parameter is TRUE if the thread is to be a floating
+ * point thread. This is typically only used on CPUs where the
+ * FPU may be easily disabled by software such as on the SPARC
+ * where the PSR contains an enable FPU bit.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#define _CPU_Context_Initialize( _the_context, _stack_base, _size, \
+ _isr, _entry_point, _is_fp ) \
+ { \
+ }
+
+/*
+ * This routine is responsible for somehow restarting the currently
+ * executing task. If you are lucky, then all that is necessary
+ * is restoring the context. Otherwise, there will need to be
+ * a special assembly routine which does something special in this
+ * case. Context_Restore should work most of the time. It will
+ * not work if restarting self conflicts with the stack frame
+ * assumptions of restoring a context.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#define _CPU_Context_Restart_self( _the_context ) \
+ _CPU_Context_restore( (_the_context) );
+
+/*
+ * The purpose of this macro is to allow the initial pointer into
+ * a floating point context area (used to save the floating point
+ * context) to be at an arbitrary place in the floating point
+ * context area.
+ *
+ * This is necessary because some FP units are designed to have
+ * their context saved as a stack which grows into lower addresses.
+ * Other FP units can be saved by simply moving registers into offsets
+ * from the base of the context area. Finally some FP units provide
+ * a "dump context" instruction which could fill in from high to low
+ * or low to high based on the whim of the CPU designers.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#define _CPU_Context_Fp_start( _base, _offset ) \
+ ( (void *) _Addresses_Add_offset( (_base), (_offset) ) )
+
+/*
+ * This routine initializes the FP context area passed to it to.
+ * There are a few standard ways in which to initialize the
+ * floating point context. The code included for this macro assumes
+ * that this is a CPU in which a "initial" FP context was saved into
+ * _CPU_Null_fp_context and it simply copies it to the destination
+ * context passed to it.
+ *
+ * Other models include (1) not doing anything, and (2) putting
+ * a "null FP status word" in the correct place in the FP context.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#define _CPU_Context_Initialize_fp( _destination ) \
+ { \
+ *((Context_Control_fp *) *((void **) _destination)) = _CPU_Null_fp_context; \
+ }
+
+/* end of Context handler macros */
+
+/* Fatal Error manager macros */
+
+/*
+ * This routine copies _error into a known place -- typically a stack
+ * location or a register, optionally disables interrupts, and
+ * halts/stops the CPU.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#define _CPU_Fatal_halt( _error ) \
+ { \
+ }
+
+/* end of Fatal Error manager macros */
+
+/* Bitfield handler macros */
+
+/*
+ * This routine sets _output to the bit number of the first bit
+ * set in _value. _value is of CPU dependent type Priority_Bit_map_control.
+ * This type may be either 16 or 32 bits wide although only the 16
+ * least significant bits will be used.
+ *
+ * There are a number of variables in using a "find first bit" type
+ * instruction.
+ *
+ * (1) What happens when run on a value of zero?
+ * (2) Bits may be numbered from MSB to LSB or vice-versa.
+ * (3) The numbering may be zero or one based.
+ * (4) The "find first bit" instruction may search from MSB or LSB.
+ *
+ * RTEMS guarantees that (1) will never happen so it is not a concern.
+ * (2),(3), (4) are handled by the macros _CPU_Priority_mask() and
+ * _CPU_Priority_bits_index(). These three form a set of routines
+ * which must logically operate together. Bits in the _value are
+ * set and cleared based on masks built by _CPU_Priority_mask().
+ * The basic major and minor values calculated by _Priority_Major()
+ * and _Priority_Minor() are "massaged" by _CPU_Priority_bits_index()
+ * to properly range between the values returned by the "find first bit"
+ * instruction. This makes it possible for _Priority_Get_highest() to
+ * calculate the major and directly index into the minor table.
+ * This mapping is necessary to ensure that 0 (a high priority major/minor)
+ * is the first bit found.
+ *
+ * This entire "find first bit" and mapping process depends heavily
+ * on the manner in which a priority is broken into a major and minor
+ * components with the major being the 4 MSB of a priority and minor
+ * the 4 LSB. Thus (0 << 4) + 0 corresponds to priority 0 -- the highest
+ * priority. And (15 << 4) + 14 corresponds to priority 254 -- the next
+ * to the lowest priority.
+ *
+ * If your CPU does not have a "find first bit" instruction, then
+ * there are ways to make do without it. Here are a handful of ways
+ * to implement this in software:
+ *
+ * - a series of 16 bit test instructions
+ * - a "binary search using if's"
+ * - _number = 0
+ * if _value > 0x00ff
+ * _value >>=8
+ * _number = 8;
+ *
+ * if _value > 0x0000f
+ * _value >=8
+ * _number += 4
+ *
+ * _number += bit_set_table[ _value ]
+ *
+ * where bit_set_table[ 16 ] has values which indicate the first
+ * bit set
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#define CPU_USE_GENERIC_BITFIELD_CODE TRUE
+#define CPU_USE_GENERIC_BITFIELD_DATA TRUE
+
+#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
+
+#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
+ { \
+ (_output) = 0; /* do something to prevent warnings */ \
+ }
+
+#endif
+
+/* end of Bitfield handler macros */
+
+/*
+ * This routine builds the mask which corresponds to the bit fields
+ * as searched by _CPU_Bitfield_Find_first_bit(). See the discussion
+ * for that routine.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
+
+#define _CPU_Priority_Mask( _bit_number ) \
+ ( 1 << (_bit_number) )
+
+#endif
+
+/*
+ * This routine translates the bit numbers returned by
+ * _CPU_Bitfield_Find_first_bit() into something suitable for use as
+ * a major or minor component of a priority. See the discussion
+ * for that routine.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
+
+#define _CPU_Priority_bits_index( _priority ) \
+ (_priority)
+
+#endif
+
+/* end of Priority handler macros */
+
+/* functions */
+
+/*
+ * _CPU_Initialize
+ *
+ * This routine performs CPU dependent initialization.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+void _CPU_Initialize(
+ rtems_cpu_table *cpu_table,
+ void (*thread_dispatch)
+);
+
+/*
+ * _CPU_ISR_install_raw_handler
+ *
+ * This routine installs a "raw" interrupt handler directly into the
+ * processor's vector table.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+void _CPU_ISR_install_raw_handler(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+);
+
+/*
+ * _CPU_ISR_install_vector
+ *
+ * This routine installs an interrupt vector.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+void _CPU_ISR_install_vector(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+);
+
+/*
+ * _CPU_Install_interrupt_stack
+ *
+ * This routine installs the hardware interrupt stack pointer.
+ *
+ * NOTE: It need only be provided if CPU_HAS_HARDWARE_INTERRUPT_STACK
+ * is TRUE.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+void _CPU_Install_interrupt_stack( void );
+
+/*
+ * _CPU_Thread_Idle_body
+ *
+ * This routine is the CPU dependent IDLE thread body.
+ *
+ * NOTE: It need only be provided if CPU_PROVIDES_IDLE_THREAD_BODY
+ * is TRUE.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+void _CPU_Thread_Idle_body( void );
+
+/*
+ * _CPU_Context_switch
+ *
+ * This routine switches from the run context to the heir context.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+void _CPU_Context_switch(
+ Context_Control *run,
+ Context_Control *heir
+);
+
+/*
+ * _CPU_Context_restore
+ *
+ * This routine is generally used only to restart self in an
+ * efficient manner. It may simply be a label in _CPU_Context_switch.
+ *
+ * NOTE: May be unnecessary to reload some registers.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+void _CPU_Context_restore(
+ Context_Control *new_context
+);
+
+/*
+ * _CPU_Context_save_fp
+ *
+ * This routine saves the floating point context passed to it.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+void _CPU_Context_save_fp(
+ void **fp_context_ptr
+);
+
+/*
+ * _CPU_Context_restore_fp
+ *
+ * This routine restores the floating point context passed to it.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+void _CPU_Context_restore_fp(
+ void **fp_context_ptr
+);
+
+/* The following routine swaps the endian format of an unsigned int.
+ * It must be static because it is referenced indirectly.
+ *
+ * This version will work on any processor, but if there is a better
+ * way for your CPU PLEASE use it. The most common way to do this is to:
+ *
+ * swap least significant two bytes with 16-bit rotate
+ * swap upper and lower 16-bits
+ * swap most significant two bytes with 16-bit rotate
+ *
+ * Some CPUs have special instructions which swap a 32-bit quantity in
+ * a single instruction (e.g. i486). It is probably best to avoid
+ * an "endian swapping control bit" in the CPU. One good reason is
+ * that interrupts would probably have to be disabled to insure that
+ * an interrupt does not try to access the same "chunk" with the wrong
+ * endian. Another good reason is that on some CPUs, the endian bit
+ * endianness for ALL fetches -- both code and data -- so the code
+ * will be fetched incorrectly.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+static inline unsigned int CPU_swap_u32(
+ unsigned int value
+)
+{
+ uint32_t byte1, byte2, byte3, byte4, swapped;
+
+ byte4 = (value >> 24) & 0xff;
+ byte3 = (value >> 16) & 0xff;
+ byte2 = (value >> 8) & 0xff;
+ byte1 = value & 0xff;
+
+ swapped = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
+ return( swapped );
+}
+
+#define CPU_swap_u16( value ) \
+ (((value&0xff) << 8) | ((value >> 8)&0xff))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/score/cpu/no_cpu/rtems/score/cpu_asm.h b/cpukit/score/cpu/no_cpu/rtems/score/cpu_asm.h
new file mode 100644
index 0000000000..70e9b2fd4a
--- /dev/null
+++ b/cpukit/score/cpu/no_cpu/rtems/score/cpu_asm.h
@@ -0,0 +1,70 @@
+/*
+ * cpu_asm.h
+ *
+ * Very loose template for an include file for the cpu_asm.? file
+ * if it is implemented as a ".S" file (preprocessed by cpp) instead
+ * of a ".s" file (preprocessed by gm4 or gasp).
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ *
+ */
+
+#ifndef __CPU_ASM_h
+#define __CPU_ASM_h
+
+/* pull in the generated offsets */
+
+#include <rtems/score/offsets.h>
+
+/*
+ * Hardware General Registers
+ */
+
+/* put something here */
+
+/*
+ * Hardware Floating Point Registers
+ */
+
+/* put something here */
+
+/*
+ * Hardware Control Registers
+ */
+
+/* put something here */
+
+/*
+ * Calling Convention
+ */
+
+/* put something here */
+
+/*
+ * Temporary registers
+ */
+
+/* put something here */
+
+/*
+ * Floating Point Registers - SW Conventions
+ */
+
+/* put something here */
+
+/*
+ * Temporary floating point registers
+ */
+
+/* put something here */
+
+#endif
+
+/* end of file */
diff --git a/cpukit/score/cpu/no_cpu/rtems/score/no_cpu.h b/cpukit/score/cpu/no_cpu/rtems/score/no_cpu.h
new file mode 100644
index 0000000000..fd096d8d46
--- /dev/null
+++ b/cpukit/score/cpu/no_cpu/rtems/score/no_cpu.h
@@ -0,0 +1,70 @@
+/* no_cpu.h
+ *
+ * This file sets up basic CPU dependency settings based on
+ * compiler settings. For example, it can determine if
+ * floating point is available. This particular implementation
+ * is specified to the NO CPU port.
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ *
+ */
+
+#ifndef _INCLUDE_NO_CPU_h
+#define _INCLUDE_NO_CPU_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This file contains the information required to build
+ * RTEMS for a particular member of the NO CPU family.
+ * It does this by setting variables to indicate which
+ * implementation dependent features are present in a particular
+ * member of the family.
+ *
+ * This is a good place to list all the known CPU models
+ * that this port supports and which RTEMS CPU model they correspond
+ * to.
+ */
+
+#if defined(rtems_multilib)
+/*
+ * Figure out all CPU Model Feature Flags based upon compiler
+ * predefines.
+ */
+
+#define CPU_MODEL_NAME "rtems_multilib"
+#define NOCPU_HAS_FPU 1
+
+#elif defined(no_cpu)
+
+#define CPU_MODEL_NAME "no_cpu_model"
+#define NOCPU_HAS_FPU 1
+
+#else
+
+#error "Unsupported CPU Model"
+
+#endif
+
+/*
+ * Define the name of the CPU family.
+ */
+
+#define CPU_NAME "NO CPU"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ! _INCLUDE_NO_CPU_h */
+/* end of include file */
diff --git a/cpukit/score/cpu/no_cpu/rtems/score/types.h b/cpukit/score/cpu/no_cpu/rtems/score/types.h
new file mode 100644
index 0000000000..b677705394
--- /dev/null
+++ b/cpukit/score/cpu/no_cpu/rtems/score/types.h
@@ -0,0 +1,56 @@
+/* no_cputypes.h
+ *
+ * This include file contains type definitions pertaining to the Intel
+ * no_cpu processor family.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __NO_CPU_TYPES_h
+#define __NO_CPU_TYPES_h
+
+#ifndef ASM
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This section defines the basic types for this processor.
+ */
+
+typedef unsigned char unsigned8; /* unsigned 8-bit integer */
+typedef unsigned short unsigned16; /* unsigned 16-bit integer */
+typedef unsigned int unsigned32; /* unsigned 32-bit integer */
+typedef unsigned long long unsigned64; /* unsigned 64-bit integer */
+
+typedef unsigned16 Priority_Bit_map_control;
+
+typedef signed char signed8; /* 8-bit signed integer */
+typedef signed short signed16; /* 16-bit signed integer */
+typedef signed int signed32; /* 32-bit signed integer */
+typedef signed long long signed64; /* 64 bit signed integer */
+
+typedef unsigned32 boolean; /* Boolean value */
+
+typedef float single_precision; /* single precision float */
+typedef double double_precision; /* double precision float */
+
+typedef void no_cpu_isr;
+typedef void ( *no_cpu_isr_entry )( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !ASM */
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/or32/.cvsignore b/cpukit/score/cpu/or32/.cvsignore
new file mode 100644
index 0000000000..282522db03
--- /dev/null
+++ b/cpukit/score/cpu/or32/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/cpukit/score/cpu/or32/ChangeLog b/cpukit/score/cpu/or32/ChangeLog
new file mode 100644
index 0000000000..ada0f77fae
--- /dev/null
+++ b/cpukit/score/cpu/or32/ChangeLog
@@ -0,0 +1,239 @@
+2004-04-06 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * configure.ac: Remove (Merged into$(top_srcdir)/configure.ac).
+ * Makefile.am: Don't include multilib.am.
+ Reflect merging configure.ac into $(top_srcdir)/configure.ac.
+
+2004-04-01 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * Makefile.am: Install asm.h to $(includedir)/rtems.
+
+2004-03-30 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * cpu.c, cpu_asm.c, rtems/score/cpu.h: Convert to using c99 fixed
+ size types.
+
+2004-03-29 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * configure.ac: RTEMS_TOP([../../../..]).
+
+2004-01-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Move RTEMS_TOP one subdir down.
+
+2004-01-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add PREINSTALL_DIRS.
+
+2004-01-14 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Re-add dirstamps to PREINSTALL_FILES.
+ Add PREINSTALL_FILES to CLEANFILES.
+
+2004-01-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Requires automake >= 1.8.1.
+
+2004-01-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include compile.am, again.
+
+2004-01-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Convert to using automake compilation rules.
+
+2003-12-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use mkdir_p. Remove dirs from PREINSTALL_FILES.
+
+2003-12-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Require automake >= 1.8, autoconf >= 2.59.
+
+2003-12-01 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Remove TMPINSTALL_FILES.
+
+2003-11-30 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add $(dirstamp) to preinstallation rules.
+
+2003-11-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Don't use gmake rules for preinstallation.
+
+2003-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_CANONICAL_HOST.
+
+2003-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_CHECK_CPU.
+
+2003-09-26 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/cpu.h: Obsoleting HP PA-RISC port and removing all
+ references.
+
+2003-09-04 Joel Sherrill <joel@OARcorp.com>
+
+ * cpu.c, cpu_asm.c, rtems/score/cpu.h, rtems/score/cpu_asm.h,
+ rtems/score/or32.h, rtems/score/types.h: URL for license changed.
+
+2003-08-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use rtems-bugs@rtems.com as bug report email address.
+
+2003-03-06 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove AC_CONFIG_AUX_DIR.
+
+2002-12-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Require autoconf-2.57 + automake-1.7.2.
+ * Makefile.am: Eliminate C_O_FILES, S_O_FILES, libscorecpu_a_OBJECTS.
+
+2002-11-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Fix package name.
+
+2002-10-25 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Add nostdinc to AM_INIT_AUTOMAKE.
+
+2002-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * .cvsignore: Reformat.
+ Add autom4te*cache.
+ Remove autom4te.cache.
+
+2002-09-14 Ivan Guzvinec <ivang@opencores.org>
+
+ * rtems/score/cpu.h (_CPU_Initialize_vectors) Define to NULL
+ since it is not used.
+
+2002-08-06 Joel Sherrill <joel@OARcorp.com>
+
+ * asm.h, rtems/score/cpu.h: Correct items that have changed since
+ RTEMS version or32 port was based upon.
+
+2002-08-05 Chris Ziomkowski <chris@asics.ws>
+
+ * asm.h, cpu.c, cpu_asm.c, rtems/score/cpu.h, rtems/score/or32.h,
+ rtems/score/types.h: Merged from OpenCores CVS repository.
+
+2002-07-26 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Build libscorecpu.a instead of rtems-cpu.rel.
+
+2002-07-22 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use .$(OBJEXT) instead of .o.
+
+2002-07-05 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: RTEMS_TOP(../../../..).
+
+2002-07-03 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems.c: Remove.
+ * Makefile.am: Reflect changes above.
+
+2002-07-01 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_PROJECT_ROOT.
+
+2002-06-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Add RTEMS_PROG_CCAS
+
+2002-06-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use AC_CONFIG_AUX_DIR(../../../..).
+ Add AC_PROG_RANLIB.
+
+2002-06-17 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include $(top_srcdir)/../../../automake/*.am.
+ Use ../../../aclocal.
+
+2001-04-03 Joel Sherrill <joel@OARcorp.com>
+
+ * Per PR94, all rtems/score/CPUtypes.h are named rtems/score/types.h.
+ * rtems/score/or32types.h: Removed.
+ * rtems/score/types.h: New file via CVS magic.
+ * Makefile.am, rtems/score/cpu.h: Account for name change.
+
+2002-03-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac:
+ AC_INIT(package,_RTEMS_VERSION,_RTEMS_BUGS).
+ AM_INIT_AUTOMAKE([no-define foreign 1.6]).
+ * Makefile.am: Remove AUTOMAKE_OPTIONS.
+
+2001-02-27 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/cpu.h: Fix conditional to match current GCC.
+
+2001-02-05 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/Makefile.am, rtems/score/Makefile.am: Removed again.
+
+2002-01-28 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/Makefile.am: Removed.
+ * rtems/score/Makefile.am: Removed.
+ * configure.ac: Reflect changes above.
+ * Makefile.am: Reflect changes above.
+
+2001-12-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add multilib support.
+
+2001-11-28 Joel Sherrill <joel@OARcorp.com>,
+
+ This was tracked as PR91.
+ * rtems/score/cpu.h: Added CPU_PROVIDES_ISR_IS_IN_PROGRESS macro which
+ is used to specify if the port uses the standard macro for this (FALSE).
+ A TRUE setting indicates the port provides its own implementation.
+
+2001-10-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * .cvsignore: Add autom4te.cache for autoconf > 2.52.
+ * configure.in: Remove.
+ * configure.ac: New file, generated from configure.in by autoupdate.
+
+2001-09-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/score/Makefile.am: Use 'PREINSTALL_FILES ='.
+ * Makefile.am: Use 'PREINSTALL_FILES ='.
+
+2001-02-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am, rtems/score/Makefile.am:
+ Apply include_*HEADERS instead of H_FILES.
+
+2001-01-03 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/cpu.h: Added _CPU_Initialize_vectors().
+
+2000-11-09 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use ... instead of RTEMS_TOPdir in ACLOCAL_AMFLAGS.
+
+2000-11-02 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Switch to ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal.
+
+2000-10-25 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: ACLOCAL_AMFLAGS= -I $(RTEMS_TOPdir)/macros.
+ Switch to GNU canonicalization.
+
+2000-09-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include compile.am.
+
+2000-08-11 Joel Sherrill <joel@OARcorp.com>
+
+ * Shell added for or32 port based on no_cpu port with names replaced.
diff --git a/cpukit/score/cpu/or32/Makefile.am b/cpukit/score/cpu/or32/Makefile.am
new file mode 100644
index 0000000000..404c57e564
--- /dev/null
+++ b/cpukit/score/cpu/or32/Makefile.am
@@ -0,0 +1,62 @@
+##
+## $Id$
+##
+
+include $(top_srcdir)/automake/compile.am
+
+include_rtemsdir = $(includedir)/rtems
+include_rtems_HEADERS= asm.h
+
+include_rtems_scoredir = $(includedir)/rtems/score
+include_rtems_score_HEADERS = rtems/score/cpu.h rtems/score/types.h \
+ rtems/score/or32.h rtems/score/cpu_asm.h
+
+EXTRA_LIBRARIES = libscorecpu.a
+CLEANFILES = libscorecpu.a
+libscorecpu_a_SOURCES = cpu.c cpu_asm.c
+libscorecpu_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libscorecpu_g.a
+CLEANFILES += libscorecpu_g.a
+libscorecpu_g_a_SOURCES = $(libscorecpu_a_SOURCES)
+libscorecpu_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+all-local: $(PREINSTALL_FILES) libscorecpu$(LIB_VARIANT).a
+
+PREINSTALL_DIRS =
+PREINSTALL_FILES =
+
+$(PROJECT_INCLUDE)/rtems/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems
+ @: > $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/asm.h: asm.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/asm.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/asm.h
+
+$(PROJECT_INCLUDE)/rtems/score/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems/score
+ @: > $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/score/cpu.h: rtems/score/cpu.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/cpu.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/cpu.h
+
+$(PROJECT_INCLUDE)/rtems/score/types.h: rtems/score/types.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/types.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/types.h
+
+$(PROJECT_INCLUDE)/rtems/score/or32.h: rtems/score/or32.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/or32.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/or32.h
+
+$(PROJECT_INCLUDE)/rtems/score/cpu_asm.h: rtems/score/cpu_asm.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/cpu_asm.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/cpu_asm.h
+
+CLEANFILES += $(PREINSTALL_FILES)
+DISTCLEANFILES = $(PREINSTALL_DIRS)
+
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/score/cpu/or32/asm.h b/cpukit/score/cpu/or32/asm.h
new file mode 100644
index 0000000000..be35ffdecd
--- /dev/null
+++ b/cpukit/score/cpu/or32/asm.h
@@ -0,0 +1,99 @@
+/* asm.h
+ *
+ * This include file attempts to address the problems
+ * caused by incompatible flavors of assemblers and
+ * toolsets. It primarily addresses variations in the
+ * use of leading underscores on symbols and the requirement
+ * that register names be preceded by a %.
+ *
+ *
+ * NOTE: The spacing in the use of these macros
+ * is critical to them working as advertised.
+ *
+ * COPYRIGHT:
+ *
+ * This file is based on similar code found in newlib available
+ * from ftp.cygnus.com. The file which was used had no copyright
+ * notice. This file is freely distributable as long as the source
+ * of the file is noted. This file is:
+ *
+ * COPYRIGHT (c) 1994-1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * $Id$
+ */
+
+#ifndef __OR1K_ASM_h
+#define __OR1K_ASM_h
+
+/*
+ * Indicate we are in an assembly file and get the basic CPU definitions.
+ */
+
+#ifndef ASM
+#define ASM
+#endif
+#include <rtems/score/targopts.h>
+#include <rtems/score/or32.h>
+
+/*
+ * Recent versions of GNU cpp define variables which indicate the
+ * need for underscores and percents. If not using GNU cpp or
+ * the version does not support this, then you will obviously
+ * have to define these as appropriate.
+ */
+
+#ifndef __USER_LABEL_PREFIX__
+#define __USER_LABEL_PREFIX__ _
+#endif
+
+#ifndef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__
+#endif
+
+/* ANSI concatenation macros. */
+
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+/* Use the right prefix for global labels. */
+
+#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+
+/* Use the right prefix for registers. */
+
+#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
+
+/*
+ * define macros for all of the registers on this CPU
+ *
+ * EXAMPLE: #define d0 REG (d0)
+ */
+
+/*
+ * Define macros to handle section beginning and ends.
+ */
+
+
+#define BEGIN_CODE_DCL .text
+#define END_CODE_DCL
+#define BEGIN_DATA_DCL .data
+#define END_DATA_DCL
+#define BEGIN_CODE .text
+#define END_CODE
+#define BEGIN_DATA
+#define END_DATA
+#define BEGIN_BSS
+#define END_BSS
+#define END
+
+/*
+ * Following must be tailor for a particular flavor of the C compiler.
+ * They may need to put underscores in front of the symbols.
+ */
+
+#define PUBLIC(sym) .global SYM (sym)
+#define EXTERN(sym) .global SYM (sym)
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/or32/cpu.c b/cpukit/score/cpu/or32/cpu.c
new file mode 100644
index 0000000000..06393d4717
--- /dev/null
+++ b/cpukit/score/cpu/or32/cpu.c
@@ -0,0 +1,192 @@
+/*
+ * Opencore Or1k CPU Dependent Source
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * This file adapted from no_bsp board library of the RTEMS distribution.
+ * The body has been modified for the Bender Or1k implementation by
+ * Chris Ziomkowski. <chris@asics.ws>
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/wkspace.h>
+
+/* _CPU_Initialize
+ *
+ * This routine performs processor dependent initialization.
+ *
+ * INPUT PARAMETERS:
+ * cpu_table - CPU table to initialize
+ * thread_dispatch - address of disptaching routine
+ *
+ */
+
+
+void _CPU_Initialize(
+ rtems_cpu_table *cpu_table,
+ void (*thread_dispatch)
+)
+{
+ /*
+ * The thread_dispatch argument is the address of the entry point
+ * for the routine called at the end of an ISR once it has been
+ * decided a context switch is necessary. On some compilation
+ * systems it is difficult to call a high-level language routine
+ * from assembly. This allows us to trick these systems.
+ *
+ * If you encounter this problem save the entry point in a CPU
+ * dependent variable.
+ */
+
+ _CPU_Thread_dispatch_pointer = thread_dispatch;
+
+ /*
+ * If there is not an easy way to initialize the FP context
+ * during Context_Initialize, then it is usually easier to
+ * save an "uninitialized" FP context here and copy it to
+ * the task's during Context_Initialize.
+ */
+
+ /* FP context initialization support goes here */
+
+ _CPU_Table = *cpu_table;
+}
+
+/*PAGE
+ *
+ * _CPU_ISR_Get_level
+ *
+ * or1k Specific Information:
+ *
+ * There are only 2 interrupt levels for the or1k architecture.
+ * Either interrupts are enabled or disabled. They are considered
+ * enabled if both exceptions are enabled (SR_EXR) and interrupts
+ * are enabled (SR_EIR). If either of these conditions are not
+ * met, interrupts are disabled, and a level of 1 is returned.
+ */
+
+inline uint32_t _CPU_ISR_Get_level( void )
+{
+ register uint32_t sr;
+ asm("l.mfspr %0,r0,0x17" : "=r" (sr));
+ return !((sr & SR_EXR) && (sr & SR_EIR));
+}
+
+/*PAGE
+ *
+ * _CPU_ISR_install_raw_handler
+ *
+ * or1k Specific Information:
+ *
+ * As a general rule the following is done for interrupts:
+ *
+ * For normal exceptions, exceptions are immediately reenabled
+ * by setting the SR_EXR bit. For interrupt exceptions, the
+ * SR_EIR bit is first cleared, and then exceptions are reenabled.
+ */
+
+void _CPU_ISR_install_raw_handler(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+)
+{
+ register uint32_t sr;
+ register uint32_t tmp;
+ extern uint32_t Or1k_Interrupt_Vectors[];
+
+ asm volatile ("l.mfspr %0,r0,0x11\n\t"
+ "l.addi %1,r0,-5\n\t"
+ "l.and %1,%1,%0\n\t": "=r" (sr) : "r" (tmp));
+ *old_handler = *((proc_ptr*)&Or1k_Interrupt_Vectors[vector]);
+ *((proc_ptr*)&Or1k_Interrupt_Vectors[vector]) = new_handler;
+ asm volatile ("l.mtspr r0,%0,0x11\n\t":: "r" (sr));
+}
+
+/*PAGE
+ *
+ * _CPU_ISR_install_vector
+ *
+ * This kernel routine installs the RTEMS handler for the
+ * specified vector.
+ *
+ * Input parameters:
+ * vector - interrupt vector number
+ * old_handler - former ISR for this vector number
+ * new_handler - replacement ISR for this vector number
+ *
+ * Output parameters: NONE
+ *
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+void _CPU_ISR_install_vector(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+)
+{
+ *old_handler = _ISR_Vector_table[ vector ];
+
+ /*
+ * If the interrupt vector table is a table of pointer to isr entry
+ * points, then we need to install the appropriate RTEMS interrupt
+ * handler for this vector number.
+ */
+
+ _CPU_ISR_install_raw_handler( vector, new_handler, old_handler );
+
+ /*
+ * We put the actual user ISR address in '_ISR_vector_table'. This will
+ * be used by the _ISR_Handler so the user gets control.
+ */
+
+ _ISR_Vector_table[ vector ] = new_handler;
+}
+
+/*PAGE
+ *
+ * _CPU_Install_interrupt_stack
+ *
+ * We don't use a separate interrupt stack.
+ *
+ */
+
+void _CPU_Install_interrupt_stack( void )
+{
+}
+
+/*PAGE
+ *
+ * _CPU_Thread_Idle_body
+ *
+ * NOTES:
+ *
+ * 1. This is the same as the regular CPU independent algorithm.
+ *
+ * 2. If you implement this using a "halt", "idle", or "shutdown"
+ * instruction, then don't forget to put it in an infinite loop.
+ *
+ * 3. Be warned. Some processors with onboard DMA have been known
+ * to stop the DMA if the CPU were put in IDLE mode. This might
+ * also be a problem with other on-chip peripherals. So use this
+ * hook with caution.
+ *
+ */
+
+void _CPU_Thread_Idle_body( void )
+{
+
+ for( ; ; )
+ /* insert your "halt" instruction here */ ;
+}
diff --git a/cpukit/score/cpu/or32/cpu_asm.c b/cpukit/score/cpu/or32/cpu_asm.c
new file mode 100644
index 0000000000..5580ba3115
--- /dev/null
+++ b/cpukit/score/cpu/or32/cpu_asm.c
@@ -0,0 +1,578 @@
+/* cpu_asm.c ===> cpu_asm.S or cpu_asm.s
+ *
+ * This file contains the basic algorithms for all assembly code used
+ * in an specific CPU port of RTEMS. These algorithms must be implemented
+ * in assembly language
+ *
+ * NOTE: This is supposed to be a .S or .s file NOT a C file.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * This file adapted from no_bsp board library of the RTEMS distribution.
+ * The body has been modified for the Bender Or1k implementation by
+ * Chris Ziomkowski. <chris@asics.ws>
+ */
+
+/*
+ * This is supposed to be an assembly file. This means that system.h
+ * and cpu.h should not be included in a "real" cpu_asm file. An
+ * implementation in assembly should include "cpu_asm.h>
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/cpu.h>
+/* #include "cpu_asm.h> */
+
+/*
+ * _CPU_Context_save_fp_context
+ *
+ * This routine is responsible for saving the FP context
+ * at *fp_context_ptr. If the point to load the FP context
+ * from is changed then the pointer is modified by this routine.
+ *
+ * Sometimes a macro implementation of this is in cpu.h which dereferences
+ * the ** and a similarly named routine in this file is passed something
+ * like a (Context_Control_fp *). The general rule on making this decision
+ * is to avoid writing assembly language.
+ *
+ * or1k specific Information:
+ *
+ * This implementation of RTEMS considers the concept of
+ * "fast context switching", as defined in the or1k architecture
+ * specification. Whether or not this makes a significant
+ * impact on speed is dubious, however it is not a significant
+ * impediment to include it. It probably wastes a few cycles on
+ * every floating point context switch.
+ *
+ * This implementation will currently not work on a processor where
+ * the integer unit and floating point unit are not the same size. I
+ * am waiting on an architecture change to make this feasible. It
+ * should work fine on 64 bit architectures, except for the fact that
+ * the variables are declared as 32 bits. This shouldn't really make
+ * a difference, as the fact that they must be registers should force
+ * them into a 64 bit word anyway.
+ *
+ * The decision as to whether to do 32 or 64 bit saves is performed
+ * at run time based on the configuration of the CPUCFGR register. This
+ * takes a performance hit of a few cycles, but this should be a very
+ * small percentage of the total number of cycles necessary to do the
+ * save, and doesn't require special code for 32 or 64 bit versions.
+ *
+ * ADDITIONAL INFORMATION:
+ *
+ * It has been unanimously agreed that floating point will not be
+ * included in the initial releases of the Or1k chips, and that
+ * significant changes to the floating point architecture may
+ * occur before any such release will ever be implemented. The code
+ * below is therefore never called and never used.
+ */
+
+void _CPU_Context_save_fp(
+ void **fp_context_ptr
+)
+{
+ register uint32_t temp;
+ register uint32_t address = (uint32_t )(*fp_context_ptr);
+ register uint32_t xfer;
+ register uint32_t loop;
+
+ /* %0 is a temporary register which is used for several
+ values throughout the code. %3 contains the address
+ to save the context, and is modified during the course
+ of the context save. %1 is a second dummy register
+ which is used during transfer of the floating point
+ value to memory. %2 is an end of loop marker which
+ is compared against the pointer %3. */
+
+ asm volatile ("l.mfspr %0,r0,0x02 \n\t" /* CPUCFGR */
+ "l.andi %0,%0,0x380 \n\t" /* OF32S or OV64S or OF64S */
+ "l.sfnei %0,0x0 \n\t"
+ "l.bf _L_nofps \n\t" /* exit if no floating point */
+ "l.sfeqi %0,0x080 \n\t" /* (DELAY) single precision? */
+ "l.mfspr %0,r0,0x11 \n\t" /* Load Status Register */
+ "l.srli %0,%0,58 \n\t" /* Move CID into low byte*32 */
+ "l.bnf _L_spfp_loops \n\t" /* Branch on single precision */
+ "l.addi %2,%0,0x20 \n" /* Terminating condition */
+ /**** Double Precision Floating Point Section ****/
+ "_L_dpfp_loops: \n\t"
+ "l.mfspr %1,%0,0x600 \n\t" /* Load VFRx */
+ "l.sd 0(%3),%1 \n\t" /* Save VFRx */
+ "l.addi %0,%0,0x01 \n\t" /* Increment counter */
+ "l.sfeq %0,%2 \n\t" /* Branch if incomplete */
+ "l.bf _L_dpfp_loops \n\t"
+ "l.addi %3,%3,0x08 \n\t" /* (DELAY) update pointer */
+ "l.bnf _L_nofps \n\t" /* exit */
+ "l.nop \n"
+ /**** Single Precision Floating Point Section ****/
+ "_L_spfp_loops: \n\t"
+ "l.mfspr %1,%0,0x600 \n\t" /* Load VFRx */
+ "l.sw 0(%3),%1 \n\t" /* Save VFRx */
+ "l.addi %0,%0,0x01 \n\t" /* Increment counter */
+ "l.sfeq %0,%2 \n\t" /* Branch if incomplete */
+ "l.bf _L_spfp_loops \n\t"
+ "l.addi %3,%3,0x04 \n" /* (DELAY) update pointer */
+ "_L_nofps: \n\t" /* End of context save */
+ : "=&r" (temp), "=r" (xfer), "=&r" (loop), "+r" (address));
+}
+
+/*
+ * _CPU_Context_restore_fp_context
+ *
+ * This routine is responsible for restoring the FP context
+ * at *fp_context_ptr. If the point to load the FP context
+ * from is changed then the pointer is modified by this routine.
+ *
+ *
+ */
+
+void _CPU_Context_restore_fp(
+ void **fp_context_ptr
+)
+{
+ register uint32_t temp;
+ register uint32_t address = (uint32_t )(*fp_context_ptr);
+ register uint32_t xfer;
+ register uint32_t loop;
+
+ /* The reverse of Context_save_fp */
+ /* %0 is a temporary register which is used for several
+ values throughout the code. %1 contains the address
+ to save the context, and is modified during the course
+ of the context save. %2 is a second dummy register
+ which is used during transfer of the floating point
+ value to memory. %3 is an end of loop marker which
+ is compared against the pointer %1. */
+
+ asm volatile ("l.mfspr %0,r0,0x02 \n\t" /* CPUCFGR */
+ "l.andi %0,%0,0x380 \n\t" /* OF32S or OV64S or OF64S */
+ "l.sfnei %0,0x0 \n\t"
+ "l.bf _L_nofpr \n\t" /* exit if no floating point */
+ "l.sfeqi %0,0x080 \n\t" /* (DELAY) single precision? */
+ "l.mfspr %0,r0,0x11 \n\t" /* Load Status Register */
+ "l.srli %0,%0,58 \n\t" /* Move CID into low byte*32 */
+ "l.bnf _L_spfp_loopr \n\t" /* Branch on single precision */
+ "l.addi %3,%0,0x20 \n" /* Terminating condition */
+ /**** Double Precision Floating Point Section ****/
+ "_L_dpfp_loopr: \n\t"
+ "l.mfspr %2,%0,0x600 \n\t" /* Load VFRx */
+ "l.sd 0(%1),%2 \n\t" /* Save VFRx */
+ "l.addi %0,%0,0x01 \n\t" /* Increment counter */
+ "l.sfeq %0,%3 \n\t" /* Branch if incomplete */
+ "l.bf _L_dpfp_loopr \n\t"
+ "l.addi %1,%1,0x08 \n\t" /* (DELAY) update pointer */
+ "l.bnf _L_nofpr \n\t" /* exit */
+ "l.nop \n"
+ /**** Single Precision Floating Point Section ****/
+ "_L_spfp_loopr: \n\t"
+ "l.mfspr %2,%0,0x600 \n\t" /* Load VFRx */
+ "l.sw 0(%1),%2 \n\t" /* Save VFRx */
+ "l.addi %0,%0,0x01 \n\t" /* Increment counter */
+ "l.sfeq %0,%3 \n\t" /* Branch if incomplete */
+ "l.bf _L_spfp_loopr \n\t"
+ "l.addi %1,%1,0x04 \n" /* (DELAY) update pointer */
+ "_L_nofpr: \n\t" /* End of context save */
+ : "=&r" (temp), "+r" (address), "=r" (xfer), "=&r" (loop));
+}
+
+/* _CPU_Context_switch
+ *
+ * This routine performs a normal non-FP context switch.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+void _CPU_Context_switch(
+ Context_Control *run,
+ Context_Control *heir
+)
+{
+ register uint32_t temp1 = 0;
+ register uint32_t temp2 = 0;
+
+ /* This function is really tricky. When this function is called,
+ we should save our state as we need it, and then grab the
+ new state from the pointer. We then do a longjump to this
+ code, replacing the current stack pointer with the new
+ environment. This function never returns. Instead, at some
+ later time, another person will call context switch with
+ our pointer in the heir variable, and they will longjump
+ to us. We will then continue. Let's see how this works... */
+
+ /* Technically, we could probably not worry about saving r3
+ and r4, since these are parameters guaranteed to be saved
+ by the calling function. We could also probably get away
+ without saving r11, as that is filled in by the return
+ statement. But as a first cut I'm in favor of just saving
+ everything.... */
+
+ /* We could be more efficient and use compile time directives
+ for 32 or 64 bit, but this will allow the code to run on
+ everything without modification. Feel free to comment the
+ relevant sections out if you don't need it. */
+
+ /* We should probably write this whole routine in assembly
+ so that we can have seperate entry points for self restore
+ or context switch. You can't jump to local labels from
+ inline assembly across function calls, and I don't feel
+ like embedding all the .global directives here...it really
+ screws up the debugger. Oh well, what's 2 more instructions
+ and a branch really cost... */
+
+ /* One thing which we should do is check for 32 or 64 bit models
+ first, and then do one branch to the appropriate code section.
+ Currently, we check the architecture bit in CPUCFGR twice. Once
+ during the load section and again during restore. That is inefficient,
+ and considering this code is huge anyway, saving the few bytes
+ simply doesn't make any practical sense. FIX THIS LATER. */
+
+ /* Note that this routine assumes software context switches are
+ done with the same CID. In other words, it will not manage
+ the CIDs and assign a new one as necessary. If you tell it
+ to restore a context at CID 2, and the current one is at CID
+ 4, it will do what it is told. It will overwrite the registers
+ for context ID 2, meaning they are irretrievably lost. I hope
+ you saved them earlier.... */
+
+ /* Note that you can have a context jump anywhere you want, although
+ by default we will jump to the L_restore label. If you then modify
+ the location in the Context_Control structure, it will continue
+ whereever you told it to go. Note however that you had better
+ also have cleaned up the stack and frame pointers though, because
+ they are probably still set with the values obtained from
+ entering this function... */
+
+ asm volatile ("l.sfeqi %3,0x0 \n\t" /* Is this a self restore? */
+ "l.bf _L_restore \n\t" /* Yes it is...go there */
+ "l.nop \n\t"
+
+ "l.lwz %0,0(%3) \n\t" /* Prefetch new context */
+ "l.mfspr %2,r0,0x11 \n\t" /* Status Register */
+ "l.sw 0(%1),%2 \n\t" /* Save it */
+ "l.srli %2,%2,28 \n\t" /* Move CID into low byte */
+ "l.mfspr %0,%2,0x20 \n\t" /* Offset from EPCR */
+ "l.sw 4(%1),%0 \n\t" /* Store it */
+ "l.mfspr %0,%2,0x30 \n\t" /* Offset from EEAR */
+ "l.sw 8(%1),%0 \n\t" /* Store it */
+ "l.mfspr %0,%2,0x40 \n\t" /* Offset from ESR */
+ "l.sw 12(%1),%0 \n\t" /* Store it */
+ "l.mfspr %0,r0,0x02 \n\t" /* CPUCFGR */
+ "l.andi %0,%0,0x40 \n\t" /* OB64S */
+ "l.sfnei %0,0x0 \n\t"
+ "l.bf _L_64bit \n\t" /* 64 bit architecture */
+ "l.movhi %0,hi(_L_restore)\n\t"
+
+ /**** 32 bit implementation ****/
+ "l.ori %0,%0,lo(_L_restore)\n\t"
+ "l.sw 140(%1),%0 \n\t" /* Save the PC */
+ "l.lwz %0,140(%3) \n\t" /* New PC. Expect cache miss */
+ "l.sw 16(%1),r1 \n\t"
+ "l.sw 20(%1),r2 \n\t"
+ "l.sw 24(%1),r3 \n\t"
+ "l.sw 28(%1),r4 \n\t"
+ "l.sw 32(%1),r5 \n\t"
+ "l.sw 36(%1),r6 \n\t"
+ "l.sw 40(%1),r7 \n\t"
+ "l.sw 44(%1),r8 \n\t"
+ "l.sw 48(%1),r9 \n\t"
+ "l.sw 52(%1),r10 \n\t"
+ "l.sw 56(%1),r11 \n\t"
+ "l.sw 60(%1),r12 \n\t"
+ "l.sw 64(%1),r13 \n\t"
+ "l.sw 68(%1),r14 \n\t"
+ "l.sw 72(%1),r15 \n\t"
+ "l.sw 76(%1),r16 \n\t"
+ "l.sw 80(%1),r17 \n\t"
+ "l.sw 84(%1),r18 \n\t"
+ "l.sw 88(%1),r19 \n\t"
+ "l.sw 92(%1),r20 \n\t"
+ "l.sw 96(%1),r21 \n\t"
+ "l.sw 100(%1),r22 \n\t"
+ "l.sw 104(%1),r23 \n\t"
+ "l.sw 108(%1),r24 \n\t"
+ "l.sw 112(%1),r25 \n\t"
+ "l.sw 116(%1),r26 \n\t"
+ "l.sw 120(%1),r27 \n\t"
+ "l.sw 124(%1),r28 \n\t"
+ "l.sw 128(%1),r29 \n\t"
+ "l.sw 132(%1),r30 \n\t"
+ "l.jr %0 \n\t" /* Go there */
+ "l.sw 136(%1),r31 \n" /* Store the last reg */
+
+ /**** 64 bit implementation ****/
+ "_L_64bit: \n\t"
+ "l.ori %0,%0,lo(_L_restore)\n\t"
+ "l.sw 264(%1),%0 \n\t"
+ "l.sd 16(%1),r1 \n\t"
+ "l.sd 24(%1),r2 \n\t"
+ "l.sd 32(%1),r3 \n\t"
+ "l.sd 40(%1),r4 \n\t"
+ "l.sd 48(%1),r5 \n\t"
+ "l.sd 56(%1),r6 \n\t"
+ "l.sd 64(%1),r7 \n\t"
+ "l.sd 72(%1),r8 \n\t"
+ "l.sd 80(%1),r9 \n\t"
+ "l.sd 88(%1),r10 \n\t"
+ "l.sd 96(%1),r11 \n\t"
+ "l.sd 104(%1),r12 \n\t"
+ "l.sd 112(%1),r13 \n\t"
+ "l.sd 120(%1),r14 \n\t"
+ "l.sd 128(%1),r15 \n\t"
+ "l.sd 136(%1),r16 \n\t"
+ "l.sd 144(%1),r17 \n\t"
+ "l.sd 152(%1),r18 \n\t"
+ "l.sd 160(%1),r19 \n\t"
+ "l.sd 168(%1),r20 \n\t"
+ "l.sd 176(%1),r21 \n\t"
+ "l.sd 184(%1),r22 \n\t"
+ "l.sd 192(%1),r23 \n\t"
+ "l.sd 200(%1),r24 \n\t"
+ "l.sd 208(%1),r25 \n\t"
+ "l.sd 216(%1),r26 \n\t"
+ "l.sd 224(%1),r27 \n\t"
+ "l.sd 232(%1),r28 \n\t"
+ "l.sd 240(%1),r29 \n\t"
+ "l.sd 248(%1),r30 \n\t"
+ "l.jr %0 \n\t" /* Go to the new PC */
+ "l.sd 256(%1),r31 \n" /* Store the last reg */
+
+ /**** The restoration routine. ****/
+
+ /* Note that when we return from this function,
+ we will actually be returning to a different
+ context than when we left. The debugger might
+ have conniptions over this, but we'll have to
+ reengineer that later. The stack and status
+ registers will all be changed, however we
+ will not touch the global interrupt mask. */
+
+ /* Also note, when doing any restore, the most
+ important registers are r1, r2, and r9. These
+ will be accessed immediately upon exiting the
+ routine, and so we want to make sure we load
+ them as early as possible in case they are
+ not in cache */
+
+ "_L_restore: \n\t" /* Restore "heir" */
+ "l.mfspr %2,r0,0x11 \n\t" /* Status Register */
+ "l.movhi %0,0x07FF \n\t" /* ~SR mask */
+ "l.ori %0,%0,0xD1FF \n\t"
+ "l.and %2,%0,%2 \n\t" /* save the global bits */
+ "l.movhi %0,0xF800 \n\t" /* SR mask */
+ "l.ori %0,%0,0x2E00 \n\t"
+ "l.lwz %1,0(%3) \n\t" /* Get the previous SR */
+ "l.and %0,%1,%0 \n\t" /* Mask out the global bits */
+ "l.or %2,%2,%0 \n\t" /* Combine local/global */
+ "l.mtspr r0,%2,0x11 \n\t" /* Restore the status register */
+
+ "l.mfspr %0,r0,0x02 \n\t" /* CPUCFGR */
+ "l.andi %0,%0,0x40 \n\t" /* OB64S */
+ "l.sfnei %0,0x0 \n\t" /* Save the 64 bit flag */
+
+ "l.srli %2,%2,28 \n\t" /* Move CID into low byte */
+ "l.lwz %0,4(%3) \n\t"
+ "l.mtspr %2,%0,0x20 \n\t" /* Offset from EPCR */
+ "l.lwz %0,8(%3) \n\t"
+ "l.mtspr %2,%0,0x30 \n\t" /* Offset from EEAR */
+ "l.lwz %0,12(%3) \n\t"
+
+ "l.bf _L_r64bit \n\t" /* 64 bit architecture */
+ "l.mtspr %2,%0,0x30 \n\t" /* Offset from EEAR (DELAY) */
+
+ /**** 32 bit restore ****/
+ "l.lwz r1,16(%3) \n\t"
+ "l.lwz r2,20(%3) \n\t"
+ "l.lwz r9,48(%3) \n\t"
+ "l.lwz r3,24(%3) \n\t"
+ "l.lwz r4,28(%3) \n\t"
+ "l.lwz r5,32(%3) \n\t"
+ "l.lwz r6,36(%3) \n\t"
+ "l.lwz r7,40(%3) \n\t"
+ "l.lwz r8,44(%3) \n\t"
+ "l.lwz r10,52(%3) \n\t"
+ "l.lwz r11,56(%3) \n\t"
+ "l.lwz r12,60(%3) \n\t"
+ "l.lwz r13,64(%3) \n\t"
+ "l.lwz r14,68(%3) \n\t"
+ "l.lwz r15,72(%3) \n\t"
+ "l.lwz r16,76(%3) \n\t"
+ "l.lwz r17,80(%3) \n\t"
+ "l.lwz r18,84(%3) \n\t"
+ "l.lwz r19,88(%3) \n\t"
+ "l.lwz r20,92(%3) \n\t"
+ "l.lwz r21,96(%3) \n\t"
+ "l.lwz r22,100(%3) \n\t"
+ "l.lwz r23,104(%3) \n\t"
+ "l.lwz r24,108(%3) \n\t"
+ "l.lwz r25,112(%3) \n\t"
+ "l.lwz r26,116(%3) \n\t"
+ "l.lwz r27,120(%3) \n\t"
+ "l.lwz r28,124(%3) \n\t"
+ "l.lwz r29,128(%3) \n\t"
+ "l.lwz r30,132(%3) \n\t"
+ "l.j _L_return \n\t"
+ "l.lwz r31,136(%3) \n"
+
+ /**** 64 bit restore ****/
+ "_L_r64bit: \n\t"
+ "l.ld r1,16(%3) \n\t"
+ "l.ld r2,24(%3) \n\t"
+ "l.ld r9,80(%3) \n\t"
+ "l.ld r3,32(%3) \n\t"
+ "l.ld r4,40(%3) \n\t"
+ "l.ld r5,48(%3) \n\t"
+ "l.ld r6,56(%3) \n\t"
+ "l.ld r7,64(%3) \n\t"
+ "l.ld r8,72(%3) \n\t"
+ "l.ld r10,88(%3) \n\t"
+ "l.ld r11,96(%3) \n\t"
+ "l.ld r12,104(%3) \n\t"
+ "l.ld r13,112(%3) \n\t"
+ "l.ld r14,120(%3) \n\t"
+ "l.ld r15,128(%3) \n\t"
+ "l.ld r16,136(%3) \n\t"
+ "l.ld r17,144(%3) \n\t"
+ "l.ld r18,152(%3) \n\t"
+ "l.ld r19,160(%3) \n\t"
+ "l.ld r20,168(%3) \n\t"
+ "l.ld r21,176(%3) \n\t"
+ "l.ld r22,184(%3) \n\t"
+ "l.ld r23,192(%3) \n\t"
+ "l.ld r24,200(%3) \n\t"
+ "l.ld r25,208(%3) \n\t"
+ "l.ld r26,216(%3) \n\t"
+ "l.ld r27,224(%3) \n\t"
+ "l.ld r28,232(%3) \n\t"
+ "l.ld r29,240(%3) \n\t"
+ "l.ld r30,248(%3) \n\t"
+ "l.ld r31,256(%3) \n"
+
+ "_L_return: \n\t" /* End of routine */
+
+ : "=&r" (temp1), "+r" (run), "=&r" (temp2)
+ : "r" (heir));
+
+ /* Note that some registers were used for parameter passing and
+ temporary registeres (temp1 and temp2). These values were
+ saved and restored across context calls, but the values that
+ the caller needs should have been stored on the stack. The
+ C code should now restore these from the stack, since r1 and
+ r2 have been restored, and return to the location specified
+ by r9. Then, all should be happy in the world. */
+}
+
+/*
+ * _CPU_Context_restore
+ *
+ * This routine is generally used only to restart self in an
+ * efficient manner. It may simply be a label in _CPU_Context_switch.
+ *
+ * NOTE: May be unnecessary to reload some registers.
+ *
+ * Or1k Specific Information:
+ *
+ * In our implementation, this simply redirects to swich context
+ */
+
+void _CPU_Context_restore(
+ Context_Control *run
+)
+{
+ _CPU_Context_switch(run,NULL);
+}
+
+
+/* void __ISR_Handler()
+ *
+ * This routine provides the RTEMS interrupt management.
+ *
+ * Or1k Specific Information:
+ *
+ * Based on the Or1k interrupt architecture described in chapter 16
+ * and the exception architecture described in chapter 9
+ */
+
+void _ISR_Handler(uint32_t vector,uint32_t ProgramCounter,
+ uint32_t EffectiveAddress,uint32_t StatusRegister)
+{
+ /*
+ * This discussion ignores a lot of the ugly details in a real
+ * implementation such as saving enough registers/state to be
+ * able to do something real. Keep in mind that the goal is
+ * to invoke a user's ISR handler which is written in C and
+ * uses a certain set of registers.
+ *
+ * Also note that the exact order is to a large extent flexible.
+ * Hardware will dictate a sequence for a certain subset of
+ * _ISR_Handler while requirements for setting
+ */
+
+ /*
+ * At entry to "common" _ISR_Handler, the vector number must be
+ * available. On some CPUs the hardware puts either the vector
+ * number or the offset into the vector table for this ISR in a
+ * known place. If the hardware does not give us this information,
+ * then the assembly portion of RTEMS for this port will contain
+ * a set of distinct interrupt entry points which somehow place
+ * the vector number in a known place (which is safe if another
+ * interrupt nests this one) and branches to _ISR_Handler.
+ *
+ * save some or all context on stack
+ * may need to save some special interrupt information for exit
+ *
+ * #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
+ * if ( _ISR_Nest_level == 0 )
+ * switch to software interrupt stack
+ * #endif
+ *
+ * _ISR_Nest_level++;
+ *
+ * _Thread_Dispatch_disable_level++;
+ *
+ * (*_ISR_Vector_table[ vector ])( vector );
+ *
+ * --_ISR_Nest_level;
+ *
+ * if ( _ISR_Nest_level )
+ * goto the label "exit interrupt (simple case)"
+ *
+ * #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE )
+ * restore stack
+ * #endif
+ *
+ * if ( !_Context_Switch_necessary )
+ * goto the label "exit interrupt (simple case)"
+ *
+ * if ( !_ISR_Signals_to_thread_executing )
+ * _ISR_Signals_to_thread_executing = FALSE;
+ * goto the label "exit interrupt (simple case)"
+ *
+ * call _Thread_Dispatch() or prepare to return to _ISR_Dispatch
+ *
+ * prepare to get out of interrupt
+ * return from interrupt (maybe to _ISR_Dispatch)
+ *
+ * LABEL "exit interrupt (simple case):
+ * prepare to get out of interrupt
+ * return from interrupt
+ */
+
+ /* In the Or1k architecture, exceptions are handled in the
+ startup code of the board support package. Thus, this
+ routine is never called. Or1k exception routines are called
+ with the following prototype:
+
+ function(int vector#, int PC, int Address, int StatusRegister);
+
+ These parameters are snapshots of the system when the exception
+ was encountered. If virtual memory is active, things like the
+ PC and Address may have little meaning, as they are referenced
+ in physical space, not the virtual space of the process.
+ */
+}
diff --git a/cpukit/score/cpu/or32/rtems/asm.h b/cpukit/score/cpu/or32/rtems/asm.h
new file mode 100644
index 0000000000..be35ffdecd
--- /dev/null
+++ b/cpukit/score/cpu/or32/rtems/asm.h
@@ -0,0 +1,99 @@
+/* asm.h
+ *
+ * This include file attempts to address the problems
+ * caused by incompatible flavors of assemblers and
+ * toolsets. It primarily addresses variations in the
+ * use of leading underscores on symbols and the requirement
+ * that register names be preceded by a %.
+ *
+ *
+ * NOTE: The spacing in the use of these macros
+ * is critical to them working as advertised.
+ *
+ * COPYRIGHT:
+ *
+ * This file is based on similar code found in newlib available
+ * from ftp.cygnus.com. The file which was used had no copyright
+ * notice. This file is freely distributable as long as the source
+ * of the file is noted. This file is:
+ *
+ * COPYRIGHT (c) 1994-1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * $Id$
+ */
+
+#ifndef __OR1K_ASM_h
+#define __OR1K_ASM_h
+
+/*
+ * Indicate we are in an assembly file and get the basic CPU definitions.
+ */
+
+#ifndef ASM
+#define ASM
+#endif
+#include <rtems/score/targopts.h>
+#include <rtems/score/or32.h>
+
+/*
+ * Recent versions of GNU cpp define variables which indicate the
+ * need for underscores and percents. If not using GNU cpp or
+ * the version does not support this, then you will obviously
+ * have to define these as appropriate.
+ */
+
+#ifndef __USER_LABEL_PREFIX__
+#define __USER_LABEL_PREFIX__ _
+#endif
+
+#ifndef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__
+#endif
+
+/* ANSI concatenation macros. */
+
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+/* Use the right prefix for global labels. */
+
+#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+
+/* Use the right prefix for registers. */
+
+#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
+
+/*
+ * define macros for all of the registers on this CPU
+ *
+ * EXAMPLE: #define d0 REG (d0)
+ */
+
+/*
+ * Define macros to handle section beginning and ends.
+ */
+
+
+#define BEGIN_CODE_DCL .text
+#define END_CODE_DCL
+#define BEGIN_DATA_DCL .data
+#define END_DATA_DCL
+#define BEGIN_CODE .text
+#define END_CODE
+#define BEGIN_DATA
+#define END_DATA
+#define BEGIN_BSS
+#define END_BSS
+#define END
+
+/*
+ * Following must be tailor for a particular flavor of the C compiler.
+ * They may need to put underscores in front of the symbols.
+ */
+
+#define PUBLIC(sym) .global SYM (sym)
+#define EXTERN(sym) .global SYM (sym)
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/or32/rtems/score/cpu.h b/cpukit/score/cpu/or32/rtems/score/cpu.h
new file mode 100644
index 0000000000..1fe9218c76
--- /dev/null
+++ b/cpukit/score/cpu/or32/rtems/score/cpu.h
@@ -0,0 +1,1071 @@
+/* cpu.h
+ *
+ * This include file contains macros pertaining to the Opencores
+ * or1k processor family.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * This file adapted from no_cpu example of the RTEMS distribution.
+ * The body has been modified for the Opencores Or1k implementation by
+ * Chris Ziomkowski. <chris@asics.ws>
+ *
+ */
+
+#ifndef _OR1K_CPU_h
+#define _OR1K_CPU_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "rtems/score/or32.h" /* pick up machine definitions */
+#ifndef ASM
+#include "rtems/score/types.h"
+#endif
+
+/* conditional compilation parameters */
+
+/*
+ * Should the calls to _Thread_Enable_dispatch be inlined?
+ *
+ * If TRUE, then they are inlined.
+ * If FALSE, then a subroutine call is made.
+ *
+ * Basically this is an example of the classic trade-off of size
+ * versus speed. Inlining the call (TRUE) typically increases the
+ * size of RTEMS while speeding up the enabling of dispatching.
+ * [NOTE: In general, the _Thread_Dispatch_disable_level will
+ * only be 0 or 1 unless you are in an interrupt handler and that
+ * interrupt handler invokes the executive.] When not inlined
+ * something calls _Thread_Enable_dispatch which in turns calls
+ * _Thread_Dispatch. If the enable dispatch is inlined, then
+ * one subroutine call is avoided entirely.]
+ *
+ */
+
+#define CPU_INLINE_ENABLE_DISPATCH FALSE
+
+/*
+ * Should the body of the search loops in _Thread_queue_Enqueue_priority
+ * be unrolled one time? In unrolled each iteration of the loop examines
+ * two "nodes" on the chain being searched. Otherwise, only one node
+ * is examined per iteration.
+ *
+ * If TRUE, then the loops are unrolled.
+ * If FALSE, then the loops are not unrolled.
+ *
+ * The primary factor in making this decision is the cost of disabling
+ * and enabling interrupts (_ISR_Flash) versus the cost of rest of the
+ * body of the loop. On some CPUs, the flash is more expensive than
+ * one iteration of the loop body. In this case, it might be desirable
+ * to unroll the loop. It is important to note that on some CPUs, this
+ * code is the longest interrupt disable period in RTEMS. So it is
+ * necessary to strike a balance when setting this parameter.
+ *
+ */
+
+#define CPU_UNROLL_ENQUEUE_PRIORITY TRUE
+
+/*
+ * Does RTEMS manage a dedicated interrupt stack in software?
+ *
+ * If TRUE, then a stack is allocated in _ISR_Handler_initialization.
+ * If FALSE, nothing is done.
+ *
+ * If the CPU supports a dedicated interrupt stack in hardware,
+ * then it is generally the responsibility of the BSP to allocate it
+ * and set it up.
+ *
+ * If the CPU does not support a dedicated interrupt stack, then
+ * the porter has two options: (1) execute interrupts on the
+ * stack of the interrupted task, and (2) have RTEMS manage a dedicated
+ * interrupt stack.
+ *
+ * If this is TRUE, CPU_ALLOCATE_INTERRUPT_STACK should also be TRUE.
+ *
+ * Only one of CPU_HAS_SOFTWARE_INTERRUPT_STACK and
+ * CPU_HAS_HARDWARE_INTERRUPT_STACK should be set to TRUE. It is
+ * possible that both are FALSE for a particular CPU. Although it
+ * is unclear what that would imply about the interrupt processing
+ * procedure on that CPU.
+ *
+ * For the first cut of an Or1k implementation, let's not worry
+ * about this, and assume that our C code will autoperform any
+ * frame/stack allocation for us when the procedure is entered.
+ * If we write assembly code, we may have to deal with this manually.
+ * This can be changed later if we find it is impossible. This
+ * behavior is desireable as it allows us to work in low memory
+ * environments where we don't have room for a dedicated stack.
+ */
+
+#define CPU_HAS_SOFTWARE_INTERRUPT_STACK FALSE
+
+/*
+ * Does this CPU have hardware support for a dedicated interrupt stack?
+ *
+ * If TRUE, then it must be installed during initialization.
+ * If FALSE, then no installation is performed.
+ *
+ * If this is TRUE, CPU_ALLOCATE_INTERRUPT_STACK should also be TRUE.
+ *
+ * Only one of CPU_HAS_SOFTWARE_INTERRUPT_STACK and
+ * CPU_HAS_HARDWARE_INTERRUPT_STACK should be set to TRUE. It is
+ * possible that both are FALSE for a particular CPU. Although it
+ * is unclear what that would imply about the interrupt processing
+ * procedure on that CPU.
+ *
+ */
+
+#define CPU_HAS_HARDWARE_INTERRUPT_STACK FALSE
+
+/*
+ * Does RTEMS allocate a dedicated interrupt stack in the Interrupt Manager?
+ *
+ * If TRUE, then the memory is allocated during initialization.
+ * If FALSE, then the memory is allocated during initialization.
+ *
+ * This should be TRUE is CPU_HAS_SOFTWARE_INTERRUPT_STACK is TRUE
+ * or CPU_INSTALL_HARDWARE_INTERRUPT_STACK is TRUE.
+ *
+ */
+
+#define CPU_ALLOCATE_INTERRUPT_STACK FALSE
+
+/*
+ * Does the RTEMS invoke the user's ISR with the vector number and
+ * a pointer to the saved interrupt frame (1) or just the vector
+ * number (0)?
+ *
+ */
+
+#define CPU_ISR_PASSES_FRAME_POINTER 0
+
+/*
+ * Does the CPU have hardware floating point?
+ *
+ * If TRUE, then the RTEMS_FLOATING_POINT task attribute is supported.
+ * If FALSE, then the RTEMS_FLOATING_POINT task attribute is ignored.
+ *
+ * If there is a FP coprocessor such as the i387 or mc68881, then
+ * the answer is TRUE.
+ *
+ * The macro name "OR1K_HAS_FPU" should be made CPU specific.
+ * It indicates whether or not this CPU model has FP support. For
+ * example, it would be possible to have an i386_nofp CPU model
+ * which set this to false to indicate that you have an i386 without
+ * an i387 and wish to leave floating point support out of RTEMS.
+ *
+ * The CPU_SOFTWARE_FP is used to indicate whether or not there
+ * is software implemented floating point that must be context
+ * switched. The determination of whether or not this applies
+ * is very tool specific and the state saved/restored is also
+ * compiler specific.
+ *
+ * Or1k Specific Information:
+ *
+ * At this time there are no implementations of Or1k that are
+ * expected to implement floating point. More importantly, the
+ * floating point architecture is expected to change significantly
+ * before such chips are fabricated.
+ */
+
+#if ( OR1K_HAS_FPU == 1 )
+#define CPU_HARDWARE_FP TRUE
+#define CPU_SOFTWARE_FP FALSE
+#else
+#define CPU_HARDWARE_FP FALSE
+#define CPU_SOFTWARE_FP TRUE
+#endif
+
+
+/*
+ * Are all tasks RTEMS_FLOATING_POINT tasks implicitly?
+ *
+ * If TRUE, then the RTEMS_FLOATING_POINT task attribute is assumed.
+ * If FALSE, then the RTEMS_FLOATING_POINT task attribute is followed.
+ *
+ * If CPU_HARDWARE_FP is FALSE, then this should be FALSE as well.
+ *
+ */
+
+#define CPU_ALL_TASKS_ARE_FP FALSE
+
+/*
+ * Should the IDLE task have a floating point context?
+ *
+ * If TRUE, then the IDLE task is created as a RTEMS_FLOATING_POINT task
+ * and it has a floating point context which is switched in and out.
+ * If FALSE, then the IDLE task does not have a floating point context.
+ *
+ * Setting this to TRUE negatively impacts the time required to preempt
+ * the IDLE task from an interrupt because the floating point context
+ * must be saved as part of the preemption.
+ *
+ */
+
+#define CPU_IDLE_TASK_IS_FP FALSE
+
+/*
+ * Should the saving of the floating point registers be deferred
+ * until a context switch is made to another different floating point
+ * task?
+ *
+ * If TRUE, then the floating point context will not be stored until
+ * necessary. It will remain in the floating point registers and not
+ * disturned until another floating point task is switched to.
+ *
+ * If FALSE, then the floating point context is saved when a floating
+ * point task is switched out and restored when the next floating point
+ * task is restored. The state of the floating point registers between
+ * those two operations is not specified.
+ *
+ * If the floating point context does NOT have to be saved as part of
+ * interrupt dispatching, then it should be safe to set this to TRUE.
+ *
+ * Setting this flag to TRUE results in using a different algorithm
+ * for deciding when to save and restore the floating point context.
+ * The deferred FP switch algorithm minimizes the number of times
+ * the FP context is saved and restored. The FP context is not saved
+ * until a context switch is made to another, different FP task.
+ * Thus in a system with only one FP task, the FP context will never
+ * be saved or restored.
+ *
+ */
+
+#define CPU_USE_DEFERRED_FP_SWITCH TRUE
+
+/*
+ * Does this port provide a CPU dependent IDLE task implementation?
+ *
+ * If TRUE, then the routine _CPU_Thread_Idle_body
+ * must be provided and is the default IDLE thread body instead of
+ * _CPU_Thread_Idle_body.
+ *
+ * If FALSE, then use the generic IDLE thread body if the BSP does
+ * not provide one.
+ *
+ * This is intended to allow for supporting processors which have
+ * a low power or idle mode. When the IDLE thread is executed, then
+ * the CPU can be powered down.
+ *
+ * The order of precedence for selecting the IDLE thread body is:
+ *
+ * 1. BSP provided
+ * 2. CPU dependent (if provided)
+ * 3. generic (if no BSP and no CPU dependent)
+ *
+ */
+
+#define CPU_PROVIDES_IDLE_THREAD_BODY FALSE
+
+/*
+ * Does the stack grow up (toward higher addresses) or down
+ * (toward lower addresses)?
+ *
+ * If TRUE, then the grows upward.
+ * If FALSE, then the grows toward smaller addresses.
+ *
+ * Or1k Specific Information:
+ *
+ * Previously I had misread the documentation and set this
+ * to true. Surprisingly, it seemed to work anyway. I'm
+ * therefore not 100% sure exactly what this does. It should
+ * be correct as it is now, however.
+ */
+
+#define CPU_STACK_GROWS_UP FALSE
+
+/*
+ * The following is the variable attribute used to force alignment
+ * of critical RTEMS structures. On some processors it may make
+ * sense to have these aligned on tighter boundaries than
+ * the minimum requirements of the compiler in order to have as
+ * much of the critical data area as possible in a cache line.
+ *
+ * The placement of this macro in the declaration of the variables
+ * is based on the syntactically requirements of the GNU C
+ * "__attribute__" extension. For example with GNU C, use
+ * the following to force a structures to a 32 byte boundary.
+ *
+ * __attribute__ ((aligned (32)))
+ *
+ * NOTE: Currently only the Priority Bit Map table uses this feature.
+ * To benefit from using this, the data must be heavily
+ * used so it will stay in the cache and used frequently enough
+ * in the executive to justify turning this on.
+ *
+ */
+
+#define CPU_STRUCTURE_ALIGNMENT __attribute__ ((aligned (32)))
+
+/*
+ * Define what is required to specify how the network to host conversion
+ * routines are handled.
+ *
+ * Or1k Specific Information:
+ *
+ * This version of RTEMS is designed specifically to run with
+ * big endian architectures. If you want little endian, you'll
+ * have to make the appropriate adjustments here and write
+ * efficient routines for byte swapping. The Or1k architecture
+ * doesn't do this very well.
+ */
+
+#define CPU_HAS_OWN_HOST_TO_NETWORK_ROUTINES FALSE
+#define CPU_BIG_ENDIAN TRUE
+#define CPU_LITTLE_ENDIAN FALSE
+
+/*
+ * The following defines the number of bits actually used in the
+ * interrupt field of the task mode. How those bits map to the
+ * CPU interrupt levels is defined by the routine _CPU_ISR_Set_level().
+ *
+ */
+
+#define CPU_MODES_INTERRUPT_MASK 0x00000001
+
+/*
+ * Processor defined structures
+ *
+ * Examples structures include the descriptor tables from the i386
+ * and the processor control structure on the i960ca.
+ *
+ */
+
+
+/*
+ * Contexts
+ *
+ * Generally there are 2 types of context to save.
+ * 1. Interrupt registers to save
+ * 2. Task level registers to save
+ *
+ * This means we have the following 3 context items:
+ * 1. task level context stuff:: Context_Control
+ * 2. floating point task stuff:: Context_Control_fp
+ * 3. special interrupt level context :: Context_Control_interrupt
+ *
+ * On some processors, it is cost-effective to save only the callee
+ * preserved registers during a task context switch. This means
+ * that the ISR code needs to save those registers which do not
+ * persist across function calls. It is not mandatory to make this
+ * distinctions between the caller/callee saves registers for the
+ * purpose of minimizing context saved during task switch and on interrupts.
+ * If the cost of saving extra registers is minimal, simplicity is the
+ * choice. Save the same context on interrupt entry as for tasks in
+ * this case.
+ *
+ * Additionally, if gdb is to be made aware of RTEMS tasks for this CPU, then
+ * care should be used in designing the context area.
+ *
+ * On some CPUs with hardware floating point support, the Context_Control_fp
+ * structure will not be used or it simply consist of an array of a
+ * fixed number of bytes. This is done when the floating point context
+ * is dumped by a "FP save context" type instruction and the format
+ * is not really defined by the CPU. In this case, there is no need
+ * to figure out the exact format -- only the size. Of course, although
+ * this is enough information for RTEMS, it is probably not enough for
+ * a debugger such as gdb. But that is another problem.
+ *
+ *
+ */
+
+#ifdef OR1K_64BIT_ARCH
+#define or1kreg uint64_t
+#else
+#define or1kreg uint32_t
+#endif
+
+/* SR_MASK is the mask of values that will be copied to/from the status
+ register on a context switch. Some values, like the flag state, are
+ specific on the context, while others, such as interrupt enables,
+ are global. The currently defined global bits are:
+
+ 0x00001 SUPV: Supervisor mode
+ 0x00002 EXR: Exceptions on/off
+ 0x00004 EIR: Interrupts enabled/disabled
+ 0x00008 DCE: Data cache enabled/disabled
+ 0x00010 ICE: Instruction cache enabled/disabled
+ 0x00020 DME: Data MMU enabled/disabled
+ 0x00040 IME: Instruction MMU enabled/disabled
+ 0x00080 LEE: Little/Big Endian enable
+ 0x00100 CE: Context ID/shadow regs enabled/disabled
+ 0x01000 OVE: Overflow causes exception
+ 0x04000 EP: Exceptions @ 0x0 or 0xF0000000
+ 0x08000 PXR: Partial exception recognition enabled/disabled
+ 0x10000 SUMRA: SPR's accessible/inaccessible
+
+ The context specific bits are:
+
+ 0x00200 F Branch flag indicator
+ 0x00400 CY Carry flag indicator
+ 0x00800 OV Overflow flag indicator
+ 0x02000 DSX Delay slot exception occurred
+ 0xF8000000 CID Current Context ID
+*/
+
+#define SR_MASK 0xF8002E00
+
+typedef enum {
+ SR_SUPV = 0x00001,
+ SR_EXR = 0x00002,
+ SR_EIR = 0x00004,
+ SR_DCE = 0x00008,
+ SR_ICE = 0x00010,
+ SR_DME = 0x00020,
+ SR_IME = 0x00040,
+ SR_LEE = 0x00080,
+ SR_CE = 0x00100,
+ SR_F = 0x00200,
+ SR_CY = 0x00400,
+ SR_OV = 0x00800,
+ SR_OVE = 0x01000,
+ SR_DSX = 0x02000,
+ SR_EP = 0x04000,
+ SR_PXR = 0x08000,
+ SR_SUMRA = 0x10000,
+ SR_CID = 0xF8000000,
+} StatusRegisterBits;
+
+typedef struct {
+ uint32_t sr; /* Current status register non persistent values */
+ uint32_t esr; /* Saved exception status register */
+ uint32_t ear; /* Saved exception effective address register */
+ uint32_t epc; /* Saved exception PC register */
+ or1kreg r[31]; /* Registers */
+ or1kreg pc; /* Context PC 4 or 8 bytes for 64 bit alignment */
+} Context_Control;
+
+typedef int Context_Control_fp;
+typedef Context_Control CPU_Interrupt_frame;
+#define _CPU_Null_fp_context 0
+#define _CPU_Interrupt_stack_low 0
+#define _CPU_Interrupt_stack_high 0
+
+/*
+ * The following table contains the information required to configure
+ * the XXX processor specific parameters.
+ *
+ */
+
+typedef struct {
+ void (*pretasking_hook)( void );
+ void (*predriver_hook)( void );
+ void (*postdriver_hook)( void );
+ void (*idle_task)( void );
+ boolean do_zero_of_workspace;
+ uint32_t idle_task_stack_size;
+ uint32_t interrupt_stack_size;
+ uint32_t extra_mpci_receive_server_stack;
+ void * (*stack_allocate_hook)( uint32_t );
+ void (*stack_free_hook)( void* );
+ /* end of fields required on all CPUs */
+} rtems_cpu_table;
+
+/*
+ * Macros to access required entires in the CPU Table are in
+ * the file rtems/system.h.
+ *
+ */
+
+/*
+ * Macros to access OR1K specific additions to the CPU Table
+ *
+ */
+
+/* There are no CPU specific additions to the CPU Table for this port. */
+
+/*
+ * This variable is optional. It is used on CPUs on which it is difficult
+ * to generate an "uninitialized" FP context. It is filled in by
+ * _CPU_Initialize and copied into the task's FP context area during
+ * _CPU_Context_Initialize.
+ *
+ */
+
+/* SCORE_EXTERN Context_Control_fp _CPU_Null_fp_context; */
+
+/*
+ * On some CPUs, RTEMS supports a software managed interrupt stack.
+ * This stack is allocated by the Interrupt Manager and the switch
+ * is performed in _ISR_Handler. These variables contain pointers
+ * to the lowest and highest addresses in the chunk of memory allocated
+ * for the interrupt stack. Since it is unknown whether the stack
+ * grows up or down (in general), this give the CPU dependent
+ * code the option of picking the version it wants to use.
+ *
+ * NOTE: These two variables are required if the macro
+ * CPU_HAS_SOFTWARE_INTERRUPT_STACK is defined as TRUE.
+ *
+ */
+
+/*
+SCORE_EXTERN void *_CPU_Interrupt_stack_low;
+SCORE_EXTERN void *_CPU_Interrupt_stack_high;
+*/
+
+/*
+ * With some compilation systems, it is difficult if not impossible to
+ * call a high-level language routine from assembly language. This
+ * is especially true of commercial Ada compilers and name mangling
+ * C++ ones. This variable can be optionally defined by the CPU porter
+ * and contains the address of the routine _Thread_Dispatch. This
+ * can make it easier to invoke that routine at the end of the interrupt
+ * sequence (if a dispatch is necessary).
+ *
+ */
+
+SCORE_EXTERN void (*_CPU_Thread_dispatch_pointer)();
+
+/*
+ * Nothing prevents the porter from declaring more CPU specific variables.
+ *
+ */
+
+/* XXX: if needed, put more variables here */
+
+/*
+ * The size of the floating point context area. On some CPUs this
+ * will not be a "sizeof" because the format of the floating point
+ * area is not defined -- only the size is. This is usually on
+ * CPUs with a "floating point save context" instruction.
+ *
+ * Or1k Specific Information:
+ *
+ * We don't support floating point in this version, so the size is 0
+ */
+
+#define CPU_CONTEXT_FP_SIZE 0
+
+/*
+ * Amount of extra stack (above minimum stack size) required by
+ * MPCI receive server thread. Remember that in a multiprocessor
+ * system this thread must exist and be able to process all directives.
+ *
+ */
+
+#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 0
+
+/*
+ * This defines the number of entries in the ISR_Vector_table managed
+ * by RTEMS.
+ *
+ */
+
+#define CPU_INTERRUPT_NUMBER_OF_VECTORS 16
+#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1)
+
+/*
+ * Should be large enough to run all RTEMS tests. This insures
+ * that a "reasonable" small application should not have any problems.
+ *
+ */
+
+#define CPU_STACK_MINIMUM_SIZE 4096
+
+/*
+ * CPU's worst alignment requirement for data types on a byte boundary. This
+ * alignment does not take into account the requirements for the stack.
+ *
+ */
+
+#define CPU_ALIGNMENT 8
+
+/*
+ * This number corresponds to the byte alignment requirement for the
+ * heap handler. This alignment requirement may be stricter than that
+ * for the data types alignment specified by CPU_ALIGNMENT. It is
+ * common for the heap to follow the same alignment requirement as
+ * CPU_ALIGNMENT. If the CPU_ALIGNMENT is strict enough for the heap,
+ * then this should be set to CPU_ALIGNMENT.
+ *
+ * NOTE: This does not have to be a power of 2 although it should be
+ * a multiple of 2 greater than or equal to 2. The requirement
+ * to be a multiple of 2 is because the heap uses the least
+ * significant field of the front and back flags to indicate
+ * that a block is in use or free. So you do not want any odd
+ * length blocks really putting length data in that bit.
+ *
+ * On byte oriented architectures, CPU_HEAP_ALIGNMENT normally will
+ * have to be greater or equal to than CPU_ALIGNMENT to ensure that
+ * elements allocated from the heap meet all restrictions.
+ *
+ */
+
+#define CPU_HEAP_ALIGNMENT CPU_ALIGNMENT
+
+/*
+ * This number corresponds to the byte alignment requirement for memory
+ * buffers allocated by the partition manager. This alignment requirement
+ * may be stricter than that for the data types alignment specified by
+ * CPU_ALIGNMENT. It is common for the partition to follow the same
+ * alignment requirement as CPU_ALIGNMENT. If the CPU_ALIGNMENT is strict
+ * enough for the partition, then this should be set to CPU_ALIGNMENT.
+ *
+ * NOTE: This does not have to be a power of 2. It does have to
+ * be greater or equal to than CPU_ALIGNMENT.
+ *
+ */
+
+#define CPU_PARTITION_ALIGNMENT CPU_ALIGNMENT
+
+/*
+ * This number corresponds to the byte alignment requirement for the
+ * stack. This alignment requirement may be stricter than that for the
+ * data types alignment specified by CPU_ALIGNMENT. If the CPU_ALIGNMENT
+ * is strict enough for the stack, then this should be set to 0.
+ *
+ * NOTE: This must be a power of 2 either 0 or greater than CPU_ALIGNMENT.
+ *
+ */
+
+#define CPU_STACK_ALIGNMENT 0
+
+/* ISR handler macros */
+
+/*
+ * Support routine to initialize the RTEMS vector table after it is allocated.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+#define _CPU_Initialize_vectors()
+
+
+/*
+ * Disable all interrupts for an RTEMS critical section. The previous
+ * level is returned in _level.
+ *
+ */
+
+#define _CPU_ISR_Disable( _isr_cookie ) \
+ { \
+ (_isr_cookie) = 0; /* do something to prevent warnings */ \
+ }
+
+/*
+ * Enable interrupts to the previous level (returned by _CPU_ISR_Disable).
+ * This indicates the end of an RTEMS critical section. The parameter
+ * _level is not modified.
+ *
+ */
+
+#define _CPU_ISR_Enable( _isr_cookie ) \
+ { \
+ }
+
+/*
+ * This temporarily restores the interrupt to _level before immediately
+ * disabling them again. This is used to divide long RTEMS critical
+ * sections into two or more parts. The parameter _level is not
+ * modified.
+ *
+ */
+
+#define _CPU_ISR_Flash( _isr_cookie ) \
+ { \
+ }
+
+/*
+ * Map interrupt level in task mode onto the hardware that the CPU
+ * actually provides. Currently, interrupt levels which do not
+ * map onto the CPU in a generic fashion are undefined. Someday,
+ * it would be nice if these were "mapped" by the application
+ * via a callout. For example, m68k has 8 levels 0 - 7, levels
+ * 8 - 255 would be available for bsp/application specific meaning.
+ * This could be used to manage a programmable interrupt controller
+ * via the rtems_task_mode directive.
+ *
+ * The get routine usually must be implemented as a subroutine.
+ *
+ */
+
+#define _CPU_ISR_Set_level( new_level ) \
+ { \
+ }
+
+uint32_t _CPU_ISR_Get_level( void );
+
+/* end of ISR handler macros */
+
+/* Context handler macros */
+
+/*
+ * Initialize the context to a state suitable for starting a
+ * task after a context restore operation. Generally, this
+ * involves:
+ *
+ * - setting a starting address
+ * - preparing the stack
+ * - preparing the stack and frame pointers
+ * - setting the proper interrupt level in the context
+ * - initializing the floating point context
+ *
+ * This routine generally does not set any unnecessary register
+ * in the context. The state of the "general data" registers is
+ * undefined at task start time.
+ *
+ * NOTE: This is_fp parameter is TRUE if the thread is to be a floating
+ * point thread. This is typically only used on CPUs where the
+ * FPU may be easily disabled by software such as on the SPARC
+ * where the PSR contains an enable FPU bit.
+ *
+ */
+
+#define _CPU_Context_Initialize( _the_context, _stack_base, _size, \
+ _isr, _entry_point, _is_fp ) \
+ { \
+ memset(_the_context,'\0',sizeof(Context_Control)); \
+ (_the_context)->r[1] = (uint32_t *) ((uint32_t ) (_stack_base) + (_size) ); \
+ (_the_context)->r[2] = (uint32_t *) ((uint32_t ) (_stack_base)); \
+ (_the_context)->sr = (_isr) ? 0x0000001B : 0x0000001F; \
+ (_the_context)->pc = (uint32_t *) _entry_point ; \
+ }
+
+/*
+ * This routine is responsible for somehow restarting the currently
+ * executing task. If you are lucky, then all that is necessary
+ * is restoring the context. Otherwise, there will need to be
+ * a special assembly routine which does something special in this
+ * case. Context_Restore should work most of the time. It will
+ * not work if restarting self conflicts with the stack frame
+ * assumptions of restoring a context.
+ *
+ */
+
+#define _CPU_Context_Restart_self( _the_context ) \
+ _CPU_Context_restore( (_the_context) );
+
+/*
+ * The purpose of this macro is to allow the initial pointer into
+ * a floating point context area (used to save the floating point
+ * context) to be at an arbitrary place in the floating point
+ * context area.
+ *
+ * This is necessary because some FP units are designed to have
+ * their context saved as a stack which grows into lower addresses.
+ * Other FP units can be saved by simply moving registers into offsets
+ * from the base of the context area. Finally some FP units provide
+ * a "dump context" instruction which could fill in from high to low
+ * or low to high based on the whim of the CPU designers.
+ *
+ */
+
+#define _CPU_Context_Fp_start( _base, _offset ) \
+ ( (void *) _Addresses_Add_offset( (_base), (_offset) ) )
+
+/*
+ * This routine initializes the FP context area passed to it to.
+ * There are a few standard ways in which to initialize the
+ * floating point context. The code included for this macro assumes
+ * that this is a CPU in which a "initial" FP context was saved into
+ * _CPU_Null_fp_context and it simply copies it to the destination
+ * context passed to it.
+ *
+ * Other models include (1) not doing anything, and (2) putting
+ * a "null FP status word" in the correct place in the FP context.
+ *
+ */
+
+#define _CPU_Context_Initialize_fp( _destination ) \
+ { \
+ *((Context_Control_fp *) *((void **) _destination)) = _CPU_Null_fp_context; \
+ }
+
+/* end of Context handler macros */
+
+/* Fatal Error manager macros */
+
+/*
+ * This routine copies _error into a known place -- typically a stack
+ * location or a register, optionally disables interrupts, and
+ * halts/stops the CPU.
+ *
+ */
+
+#define _CPU_Fatal_halt( _error ) \
+ { \
+ }
+
+/* end of Fatal Error manager macros */
+
+/* Bitfield handler macros */
+
+/*
+ * This routine sets _output to the bit number of the first bit
+ * set in _value. _value is of CPU dependent type Priority_Bit_map_control.
+ * This type may be either 16 or 32 bits wide although only the 16
+ * least significant bits will be used.
+ *
+ * There are a number of variables in using a "find first bit" type
+ * instruction.
+ *
+ * (1) What happens when run on a value of zero?
+ * (2) Bits may be numbered from MSB to LSB or vice-versa.
+ * (3) The numbering may be zero or one based.
+ * (4) The "find first bit" instruction may search from MSB or LSB.
+ *
+ * RTEMS guarantees that (1) will never happen so it is not a concern.
+ * (2),(3), (4) are handled by the macros _CPU_Priority_mask() and
+ * _CPU_Priority_bits_index(). These three form a set of routines
+ * which must logically operate together. Bits in the _value are
+ * set and cleared based on masks built by _CPU_Priority_mask().
+ * The basic major and minor values calculated by _Priority_Major()
+ * and _Priority_Minor() are "massaged" by _CPU_Priority_bits_index()
+ * to properly range between the values returned by the "find first bit"
+ * instruction. This makes it possible for _Priority_Get_highest() to
+ * calculate the major and directly index into the minor table.
+ * This mapping is necessary to ensure that 0 (a high priority major/minor)
+ * is the first bit found.
+ *
+ * This entire "find first bit" and mapping process depends heavily
+ * on the manner in which a priority is broken into a major and minor
+ * components with the major being the 4 MSB of a priority and minor
+ * the 4 LSB. Thus (0 << 4) + 0 corresponds to priority 0 -- the highest
+ * priority. And (15 << 4) + 14 corresponds to priority 254 -- the next
+ * to the lowest priority.
+ *
+ * If your CPU does not have a "find first bit" instruction, then
+ * there are ways to make do without it. Here are a handful of ways
+ * to implement this in software:
+ *
+ * - a series of 16 bit test instructions
+ * - a "binary search using if's"
+ * - _number = 0
+ * if _value > 0x00ff
+ * _value >>=8
+ * _number = 8;
+ *
+ * if _value > 0x0000f
+ * _value >=8
+ * _number += 4
+ *
+ * _number += bit_set_table[ _value ]
+ *
+ * where bit_set_table[ 16 ] has values which indicate the first
+ * bit set
+ *
+ */
+
+ /* #define CPU_USE_GENERIC_BITFIELD_CODE FALSE */
+#define CPU_USE_GENERIC_BITFIELD_CODE TRUE
+#define CPU_USE_GENERIC_BITFIELD_DATA TRUE
+
+#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
+
+ /* Get a value between 0 and N where N is the bit size */
+ /* This routine makes use of the fact that CPUCFGR defines
+ OB32S to have value 32, and OB64S to have value 64. If
+ this ever changes then this routine will fail. */
+#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
+ asm volatile ("l.mfspr %0,r0,0x2 \n\t"\
+ "l.andi %0,%0,0x60 \n\t"\
+ "l.ff1 %1,%1,r0 \n\t"\
+ "l.sub %0,%0,%1 \n\t" : "=&r" (_output), "+r" (_value));
+
+#endif
+
+/* end of Bitfield handler macros */
+
+/*
+ * This routine builds the mask which corresponds to the bit fields
+ * as searched by _CPU_Bitfield_Find_first_bit(). See the discussion
+ * for that routine.
+ *
+ */
+
+#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
+
+#define _CPU_Priority_Mask( _bit_number ) \
+ (1 << _bit_number)
+
+#endif
+
+/*
+ * This routine translates the bit numbers returned by
+ * _CPU_Bitfield_Find_first_bit() into something suitable for use as
+ * a major or minor component of a priority. See the discussion
+ * for that routine.
+ *
+ */
+
+#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
+
+#define _CPU_Priority_bits_index( _priority ) \
+ (_priority)
+
+#endif
+
+/* end of Priority handler macros */
+
+/* functions */
+
+/*
+ * _CPU_Initialize
+ *
+ * This routine performs CPU dependent initialization.
+ *
+ */
+
+void _CPU_Initialize(
+ rtems_cpu_table *cpu_table,
+ void (*thread_dispatch)
+);
+
+/*
+ * _CPU_ISR_install_raw_handler
+ *
+ * This routine installs a "raw" interrupt handler directly into the
+ * processor's vector table.
+ *
+ */
+
+void _CPU_ISR_install_raw_handler(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+);
+
+/*
+ * _CPU_ISR_install_vector
+ *
+ * This routine installs an interrupt vector.
+ *
+ * NO_CPU Specific Information:
+ *
+ * XXX document implementation including references if appropriate
+ */
+
+void _CPU_ISR_install_vector(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+);
+
+/*
+ * _CPU_Install_interrupt_stack
+ *
+ * This routine installs the hardware interrupt stack pointer.
+ *
+ * NOTE: It need only be provided if CPU_HAS_HARDWARE_INTERRUPT_STACK
+ * is TRUE.
+ *
+ */
+
+void _CPU_Install_interrupt_stack( void );
+
+/*
+ * _CPU_Thread_Idle_body
+ *
+ * This routine is the CPU dependent IDLE thread body.
+ *
+ * NOTE: It need only be provided if CPU_PROVIDES_IDLE_THREAD_BODY
+ * is TRUE.
+ *
+ */
+
+void _CPU_Thread_Idle_body( void );
+
+/*
+ * _CPU_Context_switch
+ *
+ * This routine switches from the run context to the heir context.
+ *
+ * Or1k Specific Information:
+ *
+ * Please see the comments in the .c file for a description of how
+ * this function works. There are several things to be aware of.
+ */
+
+void _CPU_Context_switch(
+ Context_Control *run,
+ Context_Control *heir
+);
+
+/*
+ * _CPU_Context_restore
+ *
+ * This routine is generally used only to restart self in an
+ * efficient manner. It may simply be a label in _CPU_Context_switch.
+ *
+ * NOTE: May be unnecessary to reload some registers.
+ *
+ */
+
+void _CPU_Context_restore(
+ Context_Control *new_context
+);
+
+/*
+ * _CPU_Context_save_fp
+ *
+ * This routine saves the floating point context passed to it.
+ *
+ */
+
+void _CPU_Context_save_fp(
+ void **fp_context_ptr
+);
+
+/*
+ * _CPU_Context_restore_fp
+ *
+ * This routine restores the floating point context passed to it.
+ *
+ */
+
+void _CPU_Context_restore_fp(
+ void **fp_context_ptr
+);
+
+/* The following routine swaps the endian format of an unsigned int.
+ * It must be static because it is referenced indirectly.
+ *
+ * This version will work on any processor, but if there is a better
+ * way for your CPU PLEASE use it. The most common way to do this is to:
+ *
+ * swap least significant two bytes with 16-bit rotate
+ * swap upper and lower 16-bits
+ * swap most significant two bytes with 16-bit rotate
+ *
+ * Some CPUs have special instructions which swap a 32-bit quantity in
+ * a single instruction (e.g. i486). It is probably best to avoid
+ * an "endian swapping control bit" in the CPU. One good reason is
+ * that interrupts would probably have to be disabled to insure that
+ * an interrupt does not try to access the same "chunk" with the wrong
+ * endian. Another good reason is that on some CPUs, the endian bit
+ * endianness for ALL fetches -- both code and data -- so the code
+ * will be fetched incorrectly.
+ *
+ */
+
+static inline unsigned int CPU_swap_u32(
+ unsigned int value
+)
+{
+ uint32_t byte1, byte2, byte3, byte4, swapped;
+
+ byte4 = (value >> 24) & 0xff;
+ byte3 = (value >> 16) & 0xff;
+ byte2 = (value >> 8) & 0xff;
+ byte1 = value & 0xff;
+
+ swapped = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
+ return( swapped );
+}
+
+#define CPU_swap_u16( value ) \
+ (((value&0xff) << 8) | ((value >> 8)&0xff))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/score/cpu/or32/rtems/score/cpu_asm.h b/cpukit/score/cpu/or32/rtems/score/cpu_asm.h
new file mode 100644
index 0000000000..70e9b2fd4a
--- /dev/null
+++ b/cpukit/score/cpu/or32/rtems/score/cpu_asm.h
@@ -0,0 +1,70 @@
+/*
+ * cpu_asm.h
+ *
+ * Very loose template for an include file for the cpu_asm.? file
+ * if it is implemented as a ".S" file (preprocessed by cpp) instead
+ * of a ".s" file (preprocessed by gm4 or gasp).
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ *
+ */
+
+#ifndef __CPU_ASM_h
+#define __CPU_ASM_h
+
+/* pull in the generated offsets */
+
+#include <rtems/score/offsets.h>
+
+/*
+ * Hardware General Registers
+ */
+
+/* put something here */
+
+/*
+ * Hardware Floating Point Registers
+ */
+
+/* put something here */
+
+/*
+ * Hardware Control Registers
+ */
+
+/* put something here */
+
+/*
+ * Calling Convention
+ */
+
+/* put something here */
+
+/*
+ * Temporary registers
+ */
+
+/* put something here */
+
+/*
+ * Floating Point Registers - SW Conventions
+ */
+
+/* put something here */
+
+/*
+ * Temporary floating point registers
+ */
+
+/* put something here */
+
+#endif
+
+/* end of file */
diff --git a/cpukit/score/cpu/or32/rtems/score/or32.h b/cpukit/score/cpu/or32/rtems/score/or32.h
new file mode 100644
index 0000000000..3e31b0ded7
--- /dev/null
+++ b/cpukit/score/cpu/or32/rtems/score/or32.h
@@ -0,0 +1,70 @@
+/* or1k.h
+ *
+ * This include file contains Or1k definitions pertaining to the Opencores
+ * or1k processor family.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * This file adapted from no_cpu example of the RTEMS distribution.
+ * The body has been modified for the Opencores Or1k implementation by
+ * Chris Ziomkowski. <chris@asics.ws>
+ *
+ */
+
+#ifndef _OR1K_H
+#define _OR1K_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This file contains the information required to build
+ * RTEMS for a particular member of the or1k CPU family.
+ * It does this by setting variables to indicate which
+ * implementation dependent features are present in a particular
+ * member of the family.
+ *
+ * This is a good place to list all the known CPU models
+ * that this port supports and which RTEMS CPU model they correspond
+ * to.
+ */
+
+#if defined(rtems_multilib)
+/*
+ * Figure out all CPU Model Feature Flags based upon compiler
+ * predefines.
+ */
+
+#define CPU_MODEL_NAME "rtems_multilib"
+#define OR1K_HAS_FPU 1
+
+#elif defined(or1200)
+
+#define CPU_MODEL_NAME "OR1200"
+#define OR1K_HAS_FPU 0
+
+#else
+
+#define CPU_MODEL_NAME "Generic Or1k Compatible"
+#define OR1K_HAS_FPU 0
+
+#endif
+
+/*
+ * Define the name of the CPU family.
+ */
+
+#define CPU_NAME "OpenRisc 1000"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ! _INCLUDE_NO_CPU_h */
+/* end of include file */
diff --git a/cpukit/score/cpu/or32/rtems/score/types.h b/cpukit/score/cpu/or32/rtems/score/types.h
new file mode 100644
index 0000000000..2da896ffda
--- /dev/null
+++ b/cpukit/score/cpu/or32/rtems/score/types.h
@@ -0,0 +1,69 @@
+/* or1ktypes.h
+ *
+ * This include file contains type definitions pertaining to the Opencores
+ * or1k processor family.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * This file adapted from no_cpu example of the RTEMS distribution.
+ * The body has been modified for the Opencores Or1k implementation by
+ * Chris Ziomkowski. <chris@asics.ws>
+ */
+
+#ifndef __OR1K_TYPES_h
+#define __OR1K_TYPES_h
+
+#ifndef ASM
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This section defines the basic types for this processor.
+ */
+
+typedef unsigned char unsigned8; /* unsigned 8-bit integer */
+typedef unsigned short unsigned16; /* unsigned 16-bit integer */
+typedef unsigned int unsigned32; /* unsigned 32-bit integer */
+typedef unsigned long long unsigned64; /* unsigned 64-bit integer */
+
+typedef unsigned16 Priority_Bit_map_control;
+
+typedef signed char signed8; /* 8-bit signed integer */
+typedef signed short signed16; /* 16-bit signed integer */
+typedef signed int signed32; /* 32-bit signed integer */
+typedef signed long long signed64; /* 64 bit signed integer */
+
+typedef unsigned32 boolean; /* Boolean value */
+
+typedef float single_precision; /* single precision float */
+typedef double double_precision; /* double precision float */
+
+typedef void no_cpu_isr;
+typedef void ( *no_cpu_isr_entry )( void );
+
+/*
+ * Turns out the that the disable POSIX option doesn't work
+ * too well. Specifically, the libc library still wants to know
+ * these POSIX values. We'll go ahead and include them here
+ * until such time as someone like OAR who is familiar with this
+ * can figure out what should really be done.
+ */
+
+#define NAME_MAX 255
+#define LINK_MAX 8
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !ASM */
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/powerpc/.cvsignore b/cpukit/score/cpu/powerpc/.cvsignore
new file mode 100644
index 0000000000..282522db03
--- /dev/null
+++ b/cpukit/score/cpu/powerpc/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/cpukit/score/cpu/powerpc/ChangeLog b/cpukit/score/cpu/powerpc/ChangeLog
new file mode 100644
index 0000000000..62f3d41875
--- /dev/null
+++ b/cpukit/score/cpu/powerpc/ChangeLog
@@ -0,0 +1,336 @@
+2004-04-13 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * asm.h: Include rtems/score/powerpc.h instead of
+ rtems/score/ppc.h.
+
+2004-04-13 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * rtems/score/powerpc.h: New (Copied and renamed from rtems/score/ppc.h)
+ for consistency with other ports.
+ * rtems/score/ppc.h: Deprecation wrapper to rtems/score/powerpc.h.
+ * Makefile.am: Reflect changes above.
+ * rtems/score/cpu.h: Include rtems/score/powerpc.h instead of
+ rtems/score/ppc.h.
+
+2004-04-12 David Querbach <querbach@realtime.bc.ca>
+
+ * asm.h, rtems/new-exceptions/cpu.h, rtems/score/ppc.h: addition of
+ MPC555 support as part of the addition of the SS555 BSP.
+
+2004-04-06 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * configure.ac: Remove (Merged into $(top_srcdir)/configure.ac).
+ * Makefile.am: Don't include multilib.am.
+ Reflect merging configure.ac into $(top_srcdir)/configure.ac.
+
+2004-04-01 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * Makefile.am: Install asm.h to $(includedir)/rtems.
+
+2004-03-30 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * rtems/new-exceptions/cpu.h, rtems/old-exceptions/cpu.h,
+ rtems/powerpc/registers.h: Convert to using c99 fixed size types.
+
+2004-03-29 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * configure.ac: RTEMS_TOP([../../../..]).
+
+2004-01-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Move RTEMS_TOP one subdir down.
+
+2004-01-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add PREINSTALL_DIRS.
+
+2004-01-14 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Re-add dirstamps to PREINSTALL_FILES.
+ Add PREINSTALL_FILES to CLEANFILES.
+
+2004-01-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Requires automake >= 1.8.1.
+
+2004-01-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include compile.am, again.
+
+2004-01-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Convert to using automake compilation rules.
+
+2003-12-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use mkdir_p. Remove dirs from PREINSTALL_FILES.
+
+2003-12-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Require automake >= 1.8, autoconf >= 2.59.
+
+2003-11-30 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add $(dirstamp) to preinstallation rules.
+
+2003-11-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Remove all LIB-related rules.
+
+2003-11-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Don't use gmake rules for preinstallation.
+
+2003-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_CANONICAL_HOST.
+
+2003-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_CHECK_CPU.
+
+2003-09-26 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/new-exceptions/cpu.h, rtems/old-exceptions/cpu.h: Obsoleting HP
+ PA-RISC port and removing all references.
+
+2003-09-04 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/new-exceptions/cpu.h, rtems/old-exceptions/cpu.h,
+ rtems/powerpc/registers.h, rtems/score/ppc.h, rtems/score/types.h:
+ URL for license changed.
+
+2003-08-21 Till Straumann <strauman@slac.stanford.edu>
+
+ PR 457/bsps
+ * rtems/powerpc/registers.h: Add a few definitions for the PowerPC
+ thermal assistance unit.
+
+2003-08-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use rtems-bugs@rtems.com as bug report email address.
+
+2003-07-18 Till Straumann <strauman@slac.stanford.edu>
+
+ PR 288/rtems
+ * rtems/new-exceptions/cpu.h: _ISR_Nest_level is now properly
+ maintained and does not reside in SPRG0.
+
+2003-03-06 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove AC_CONFIG_AUX_DIR.
+
+2003-02-20 Till Straumann <strauman@slac.stanford.edu>
+
+ PR 349/bsps
+ * rtems/powerpc/registers.h: Add definitions for HID1 and DABR SPRs.
+
+2002-12-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Require autoconf-2.57 + automake-1.7.2.
+ * Makefile.am: Eliminate C_O_FILES, S_O_FILES, libscorecpu_a_OBJECTS.
+
+2002-11-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Fix package name.
+
+2002-11-06 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/new-exceptions/cpu.h: Remove sections on
+ CPU_INLINE_ENABLE_DISPATCH and CPU_UNROLL_ENQUEUE_PRIORITY.
+ * rtems/old-exceptions/cpu.h: Remove sections on
+ CPU_INLINE_ENABLE_DISPATCH and CPU_UNROLL_ENQUEUE_PRIORITY.
+ * rtems/score/cpu.h: Insert sections on
+ CPU_INLINE_ENABLE_DISPATCH and CPU_UNROLL_ENQUEUE_PRIORITY.
+
+2002-10-31 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/new-exceptions/cpu.h: Removed warnings.
+
+
+2002-10-31 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/new-exceptions/cpu.h: Removed warnings.
+
+2002-10-25 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Add nostdinc to AM_INIT_AUTOMAKE.
+
+2002-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * .cvsignore: Reformat.
+ Add autom4te*cache.
+ Remove autom4te.cache.
+
+2002-07-26 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Build libscorecpu.a instead of rtems-cpu.rel.
+
+2002-07-22 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use .$(OBJEXT) instead of .o.
+
+2002-07-05 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: RTEMS_TOP(../../../..).
+
+2002-07-01 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_PROJECT_ROOT.
+
+2002-06-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Add RTEMS_PROG_CCAS
+
+2002-06-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use AC_CONFIG_AUX_DIR(../../../..).
+ Add AC_PROG_RANLIB.
+
+2002-06-17 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include $(top_srcdir)/../../../automake/*.am.
+ Use ../../../aclocal.
+
+2002-05-01 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/score/ppc.h: Remove PPC_DEBUG_MODEL.
+
+2001-05-14 Till Straumann <strauman@slac.stanford.edu>
+
+ * rtems/powerpc/registers.h, rtems/score/ppc.h: Per PR213, add
+ support for the MPC74000 (AKA G4); there is no AltiVec support yet,
+ however.
+2002-04-30 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/score/ppc.h: Remove rtems_multilib.
+ Add mpc555 (Based on comments from Sergei Organov <osv@javad.ru>).
+ * rtems/old-exceptions/cpu.h: Remove _CPU_Data_Cache_Block_Flush.
+ Remove _CPU_Data_Cache_Block_Invalidate.
+
+2002-04-18 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * asm.h: Include cpuopts.h instead of targopts.h.
+ * rtems/new-exceptions/cpu.h: Relocated from
+ libbsp/powerpc/support/new_exception_processing/rtems/score/cpu.h
+ * rtems/old-exceptions/cpu.h: Relocated from
+ c/src/lib/libbsp/powerpc/support/old_exception_processing/rtems/score/cpu.h
+ * rtems/powerpc/registers.h: Relocated and renamed from
+ libcpu/powerpc/shared/include/cpu.h.
+ * rtems/score/cpu.h: New.
+ * Makefile.am: Reflect changes above.
+
+2001-04-03 Joel Sherrill <joel@OARcorp.com>
+
+ * Per PR94, all rtems/score/CPUtypes.h are named rtems/score/types.h.
+ * rtems/score/ppctypes.h: Removed.
+ * rtems/score/types.h: New file via CVS magic.
+ * Makefile.am, rtems/score/cpu.h: Account for name change.
+
+2002-03-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac:
+ AC_INIT(package,_RTEMS_VERSION,_RTEMS_BUGS).
+ AM_INIT_AUTOMAKE([no-define foreign 1.6]).
+ * Makefile.am: Remove AUTOMAKE_OPTIONS.
+
+2002-01-28 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Reflect changes from 2002-01-23.
+
+2002-01-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/Makefile.am: Removed.
+ * rtems/score/Makefile.am: Removed.
+ * configure.ac: Reflect changes above.
+ AC_CONFIG_SRCDIR(asm.h).
+
+2002-01-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/Makefile.am: New.
+ * rtems/.cvsignore: New.
+ * rtems/score/Makefile.am: New.
+ * rtems/score/.cvsignore: New.
+ * rtems/score/ppc.h: Relocated from shared/.
+ * rtems/score/ppctypes.h: Relocated from shared/.
+ * asm.h: Relocated from shared/.
+ * shared/Makefile.am: Removed.
+ * shared/asm.h: Removed.
+ * shared/ppc.h: Removed.
+ * shared/ppctypes.h: Removed.
+ * shared/.cvsignore: Removed.
+ * Makefile.am: Reflect changes above.
+ * configure.ac: Reflect changes above.
+
+2001-11-28 Joel Sherrill <joel@OARcorp.com>,
+
+ This was tracked as PR91.
+ * rtems/score/cpu.h: Added CPU_PROVIDES_ISR_IS_IN_PROGRESS macro which
+ is used to specify if the port uses the standard macro for this (FALSE).
+ A TRUE setting indicates the port provides its own implementation.
+
+2001-11-14 Joel Sherrill <joel@OARcorp.com>
+
+ * shared/ppc.h: The mpc8260 uses the new exception processing model
+ and thus does not need to define PPC_USE_SPRG.
+
+2001-11-14 Andrew Dachs <A.Dachs@SSTL.co.uk>
+
+ * shared/ppc.h: mpc8260 has double FPU not single FPU.
+
+2001-11-08 Dennis Ehlin (ECS) <Dennis.Ehlin@ecs.ericsson.se>
+
+ This modification is part of the submitted modifications necessary to
+ support the IBM PPC405 family. This submission was reviewed by
+ Thomas Doerfler <Thomas.Doerfler@imd-systems.de> who ensured it did
+ not negatively impact the ppc403 BSPs. The submission and tracking
+ process was captured as PR50.
+ * shared/asm.h, shared/ppc.h: Added PPC405 support.
+
+2001-10-22 Andy Dachs <a.dachs@sstl.co.uk>
+
+ * shared/ppc.h: Added mpc8260 support.
+
+2001-10-12 Joel Sherrill <joel@OARcorp.com>
+
+ * shared/ppctypes.h: Fixed typo.
+
+2001-10-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * .cvsignore: Add autom4te.cache for autoconf > 2.52.
+ * configure.in: Remove.
+ * configure.ac: New file, generated from configure.in by autoupdate.
+
+2001-09-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * shared/Makefile.am: Use 'PREINSTALL_FILES ='.
+
+2001-02-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am, rtems/score/Makefile.am:
+ Apply include_*HEADERS instead of H_FILES.
+
+2000-11-09 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use ... instead of RTEMS_TOPdir in ACLOCAL_AMFLAGS.
+
+2000-11-02 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Switch to ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal.
+
+2000-10-25 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: ACLOCAL_AMFLAGS= -I $(RTEMS_TOPdir)/macros.
+ Switch to GNU canonicalization.
+
+2000-10-20 Joel Sherrill <joel@OARcorp.com>
+
+ * shared/ppc.h: For multilibs, derive PPC_HAS_FPU from _SOFT_FLOAT.
+
+2000-09-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include compile.am.
+
+2000-08-10 Joel Sherrill <joel@OARcorp.com>
+
+ * ChangeLog: New file.
diff --git a/cpukit/score/cpu/powerpc/Makefile.am b/cpukit/score/cpu/powerpc/Makefile.am
new file mode 100644
index 0000000000..64d8ceb878
--- /dev/null
+++ b/cpukit/score/cpu/powerpc/Makefile.am
@@ -0,0 +1,93 @@
+##
+## $Id$
+##
+
+include $(top_srcdir)/automake/compile.am
+
+include_rtemsdir = $(includedir)/rtems
+include_rtems_HEADERS = asm.h
+
+include_rtems_scoredir = $(includedir)/rtems/score
+include_rtems_score_HEADERS = rtems/score/powerpc.h rtems/score/cpu.h \
+ rtems/score/types.h
+if DEPRECATED
+include_rtems_score_HEADERS += rtems/score/ppc.h
+endif
+
+include_rtems_old_exceptionsdir = $(includedir)/rtems/old-exceptions
+include_rtems_old_exceptions_HEADERS = rtems/old-exceptions/cpu.h
+
+include_rtems_new_exceptionsdir = $(includedir)/rtems/new-exceptions
+include_rtems_new_exceptions_HEADERS = rtems/new-exceptions/cpu.h
+
+include_rtems_powerpcdir = $(includedir)/rtems/powerpc
+include_rtems_powerpc_HEADERS = rtems/powerpc/registers.h
+
+all-local: $(PREINSTALL_FILES)
+
+PREINSTALL_DIRS =
+PREINSTALL_FILES =
+
+$(PROJECT_INCLUDE)/rtems/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems
+ @: > $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/asm.h: asm.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/asm.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/asm.h
+
+$(PROJECT_INCLUDE)/rtems/score/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems/score
+ @: > $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/score/powerpc.h: rtems/score/powerpc.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/powerpc.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/powerpc.h
+
+$(PROJECT_INCLUDE)/rtems/score/cpu.h: rtems/score/cpu.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/cpu.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/cpu.h
+
+$(PROJECT_INCLUDE)/rtems/score/types.h: rtems/score/types.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/types.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/types.h
+
+if DEPRECATED
+$(PROJECT_INCLUDE)/rtems/score/ppc.h: rtems/score/ppc.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/ppc.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/ppc.h
+endif
+
+$(PROJECT_INCLUDE)/rtems/old-exceptions/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems/old-exceptions
+ @: > $(PROJECT_INCLUDE)/rtems/old-exceptions/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/old-exceptions/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/old-exceptions/cpu.h: rtems/old-exceptions/cpu.h $(PROJECT_INCLUDE)/rtems/old-exceptions/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/old-exceptions/cpu.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/old-exceptions/cpu.h
+
+$(PROJECT_INCLUDE)/rtems/new-exceptions/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems/new-exceptions
+ @: > $(PROJECT_INCLUDE)/rtems/new-exceptions/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/new-exceptions/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/new-exceptions/cpu.h: rtems/new-exceptions/cpu.h $(PROJECT_INCLUDE)/rtems/new-exceptions/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/new-exceptions/cpu.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/new-exceptions/cpu.h
+
+$(PROJECT_INCLUDE)/rtems/powerpc/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems/powerpc
+ @: > $(PROJECT_INCLUDE)/rtems/powerpc/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/powerpc/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/powerpc/registers.h: rtems/powerpc/registers.h $(PROJECT_INCLUDE)/rtems/powerpc/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/powerpc/registers.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/powerpc/registers.h
+
+CLEANFILES = $(PREINSTALL_FILES)
+DISTCLEANFILES = $(PREINSTALL_DIRS)
+
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/score/cpu/powerpc/asm.h b/cpukit/score/cpu/powerpc/asm.h
new file mode 100644
index 0000000000..18144cad5e
--- /dev/null
+++ b/cpukit/score/cpu/powerpc/asm.h
@@ -0,0 +1,296 @@
+/* asm.h
+ *
+ * This include file attempts to address the problems
+ * caused by incompatible flavors of assemblers and
+ * toolsets. It primarily addresses variations in the
+ * use of leading underscores on symbols and the requirement
+ * that register names be preceded by a %.
+ *
+ *
+ * NOTE: The spacing in the use of these macros
+ * is critical to them working as advertised.
+ *
+ * COPYRIGHT:
+ *
+ * This file is based on similar code found in newlib available
+ * from ftp.cygnus.com. The file which was used had no copyright
+ * notice. This file is freely distributable as long as the source
+ * of the file is noted. This file is:
+ *
+ * COPYRIGHT (c) 1995.
+ * i-cubed ltd.
+ *
+ * COPYRIGHT (c) 1994.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * $Id$
+ */
+
+#ifndef __PPC_ASM_h
+#define __PPC_ASM_h
+
+/*
+ * Indicate we are in an assembly file and get the basic CPU definitions.
+ */
+
+#ifndef ASM
+#define ASM
+#endif
+#include <rtems/score/cpuopts.h>
+#include <rtems/score/powerpc.h>
+
+/*
+ * Recent versions of GNU cpp define variables which indicate the
+ * need for underscores and percents. If not using GNU cpp or
+ * the version does not support this, then you will obviously
+ * have to define these as appropriate.
+ */
+
+#ifndef __USER_LABEL_PREFIX__
+#define __USER_LABEL_PREFIX__
+#endif
+
+#ifndef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__
+#endif
+
+#ifndef __FLOAT_REGISTER_PREFIX__
+#define __FLOAT_REGISTER_PREFIX__ __REGISTER_PREFIX__
+#endif
+
+#if (PPC_ABI == PPC_ABI_POWEROPEN)
+#ifndef __PROC_LABEL_PREFIX__
+#define __PROC_LABEL_PREFIX__ .
+#endif
+#endif
+
+#ifndef __PROC_LABEL_PREFIX__
+#define __PROC_LABEL_PREFIX__ __USER_LABEL_PREFIX__
+#endif
+
+/* ANSI concatenation macros. */
+
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+/* Use the right prefix for global labels. */
+
+#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+
+/* Use the right prefix for procedure labels. */
+
+#define PROC(x) CONCAT1 (__PROC_LABEL_PREFIX__, x)
+
+/* Use the right prefix for registers. */
+
+#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
+
+/* Use the right prefix for floating point registers. */
+
+#define FREG(x) CONCAT1 (__FLOAT_REGISTER_PREFIX__, x)
+
+/*
+ * define macros for all of the registers on this CPU
+ *
+ * EXAMPLE: #define d0 REG (d0)
+ */
+#define r0 REG(0)
+#define r1 REG(1)
+#define r2 REG(2)
+#define r3 REG(3)
+#define r4 REG(4)
+#define r5 REG(5)
+#define r6 REG(6)
+#define r7 REG(7)
+#define r8 REG(8)
+#define r9 REG(9)
+#define r10 REG(10)
+#define r11 REG(11)
+#define r12 REG(12)
+#define r13 REG(13)
+#define r14 REG(14)
+#define r15 REG(15)
+#define r16 REG(16)
+#define r17 REG(17)
+#define r18 REG(18)
+#define r19 REG(19)
+#define r20 REG(20)
+#define r21 REG(21)
+#define r22 REG(22)
+#define r23 REG(23)
+#define r24 REG(24)
+#define r25 REG(25)
+#define r26 REG(26)
+#define r27 REG(27)
+#define r28 REG(28)
+#define r29 REG(29)
+#define r30 REG(30)
+#define r31 REG(31)
+#define f0 FREG(0)
+#define f1 FREG(1)
+#define f2 FREG(2)
+#define f3 FREG(3)
+#define f4 FREG(4)
+#define f5 FREG(5)
+#define f6 FREG(6)
+#define f7 FREG(7)
+#define f8 FREG(8)
+#define f9 FREG(9)
+#define f10 FREG(10)
+#define f11 FREG(11)
+#define f12 FREG(12)
+#define f13 FREG(13)
+#define f14 FREG(14)
+#define f15 FREG(15)
+#define f16 FREG(16)
+#define f17 FREG(17)
+#define f18 FREG(18)
+#define f19 FREG(19)
+#define f20 FREG(20)
+#define f21 FREG(21)
+#define f22 FREG(22)
+#define f23 FREG(23)
+#define f24 FREG(24)
+#define f25 FREG(25)
+#define f26 FREG(26)
+#define f27 FREG(27)
+#define f28 FREG(28)
+#define f29 FREG(29)
+#define f30 FREG(30)
+#define f31 FREG(31)
+
+/*
+ * Some special purpose registers (SPRs).
+ */
+#define srr0 0x01a
+#define srr1 0x01b
+#if defined(ppc403) || defined(ppc405)
+#define srr2 0x3de /* IBM 400 series only */
+#define srr3 0x3df /* IBM 400 series only */
+#endif /* ppc403 or ppc405 */
+
+#define sprg0 0x110
+#define sprg1 0x111
+#define sprg2 0x112
+#define sprg3 0x113
+
+#define dar 0x013 /* Data Address Register */
+#define dec 0x016 /* Decrementer Register */
+
+#if defined(ppc403) || defined(ppc405)
+/* the following SPR/DCR registers exist only in IBM 400 series */
+#define dear 0x3d5
+#define evpr 0x3d6 /* SPR: exception vector prefix register */
+#define iccr 0x3fb /* SPR: instruction cache control reg. */
+#define dccr 0x3fa /* SPR: data cache control reg. */
+
+#if defined (ppc403)
+#define exisr 0x040 /* DCR: external interrupt status register */
+#define exier 0x042 /* DCR: external interrupt enable register */
+#endif /* ppc403 */
+#if defined(ppc405)
+#define exisr 0x0C0 /* DCR: external interrupt status register */
+#define exier 0x0C2 /* DCR: external interrupt enable register */
+#endif /* ppc405 */
+
+#define br0 0x080 /* DCR: memory bank register 0 */
+#define br1 0x081 /* DCR: memory bank register 1 */
+#define br2 0x082 /* DCR: memory bank register 2 */
+#define br3 0x083 /* DCR: memory bank register 3 */
+#define br4 0x084 /* DCR: memory bank register 4 */
+#define br5 0x085 /* DCR: memory bank register 5 */
+#define br6 0x086 /* DCR: memory bank register 6 */
+#define br7 0x087 /* DCR: memory bank register 7 */
+/* end of IBM400 series register definitions */
+
+#elif defined(mpc555)
+/* The following registers are for the MPC5xx */
+#define eie 0x050 /* External Interrupt Enable Register */
+#define eid 0x051 /* External Interrupt Disable Register */
+#define nri 0x052 /* Non-Recoverable Interrupt Register */
+
+#elif defined(mpc860) || defined(mpc821)
+/* The following registers are for the MPC8x0 */
+#define der 0x095 /* Debug Enable Register */
+#define ictrl 0x09E /* Instruction Support Control Register */
+#define immr 0x27E /* Internal Memory Map Register */
+/* end of MPC8x0 registers */
+#endif
+
+/*
+ * Following must be tailor for a particular flavor of the C compiler.
+ * They may need to put underscores in front of the symbols.
+ */
+
+#define PUBLIC_VAR(sym) .globl SYM (sym)
+#define EXTERN_VAR(sym) .extern SYM (sym)
+#define PUBLIC_PROC(sym) .globl PROC (sym)
+#define EXTERN_PROC(sym) .extern PROC (sym)
+
+/* Other potentially assembler specific operations */
+#if PPC_ASM == PPC_ASM_ELF
+#define ALIGN(n,p) .align p
+#define DESCRIPTOR(x) \
+ .section .descriptors,"aw"; \
+ PUBLIC_VAR (x); \
+SYM (x):; \
+ .long PROC (x); \
+ .long s.got; \
+ .long 0
+
+#define EXT_SYM_REF(x) .long x
+#define EXT_PROC_REF(x) .long x
+
+/*
+ * Define macros to handle section beginning and ends.
+ */
+
+#define BEGIN_CODE_DCL .text
+#define END_CODE_DCL
+#define BEGIN_DATA_DCL .data
+#define END_DATA_DCL
+#define BEGIN_CODE .text
+#define END_CODE
+#define BEGIN_DATA .data
+#define END_DATA
+#define BEGIN_BSS .bss
+#define END_BSS
+#define END
+
+#elif PPC_ASM == PPC_ASM_XCOFF
+#define ALIGN(n,p) .align p
+#define DESCRIPTOR(x) \
+ .csect x[DS]; \
+ .globl x[DS]; \
+ .long PROC (x)[PR]; \
+ .long TOC[tc0]
+
+#define EXT_SYM_REF(x) .long x[RW]
+#define EXT_PROC_REF(x) .long x[DS]
+
+/*
+ * Define macros to handle section beginning and ends.
+ */
+
+#define BEGIN_CODE_DCL .csect .text[PR]
+#define END_CODE_DCL
+#define BEGIN_DATA_DCL .csect .data[RW]
+#define END_DATA_DCL
+#define BEGIN_CODE .csect .text[PR]
+#define END_CODE
+#define BEGIN_DATA .csect .data[RW]
+#define END_DATA
+#define BEGIN_BSS .bss
+#define END_BSS
+#define END
+
+#else
+#error "PPC_ASM_TYPE is not properly defined"
+#endif
+#ifndef PPC_ASM
+#error "PPC_ASM_TYPE is not properly defined"
+#endif
+
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/powerpc/rtems/asm.h b/cpukit/score/cpu/powerpc/rtems/asm.h
new file mode 100644
index 0000000000..18144cad5e
--- /dev/null
+++ b/cpukit/score/cpu/powerpc/rtems/asm.h
@@ -0,0 +1,296 @@
+/* asm.h
+ *
+ * This include file attempts to address the problems
+ * caused by incompatible flavors of assemblers and
+ * toolsets. It primarily addresses variations in the
+ * use of leading underscores on symbols and the requirement
+ * that register names be preceded by a %.
+ *
+ *
+ * NOTE: The spacing in the use of these macros
+ * is critical to them working as advertised.
+ *
+ * COPYRIGHT:
+ *
+ * This file is based on similar code found in newlib available
+ * from ftp.cygnus.com. The file which was used had no copyright
+ * notice. This file is freely distributable as long as the source
+ * of the file is noted. This file is:
+ *
+ * COPYRIGHT (c) 1995.
+ * i-cubed ltd.
+ *
+ * COPYRIGHT (c) 1994.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * $Id$
+ */
+
+#ifndef __PPC_ASM_h
+#define __PPC_ASM_h
+
+/*
+ * Indicate we are in an assembly file and get the basic CPU definitions.
+ */
+
+#ifndef ASM
+#define ASM
+#endif
+#include <rtems/score/cpuopts.h>
+#include <rtems/score/powerpc.h>
+
+/*
+ * Recent versions of GNU cpp define variables which indicate the
+ * need for underscores and percents. If not using GNU cpp or
+ * the version does not support this, then you will obviously
+ * have to define these as appropriate.
+ */
+
+#ifndef __USER_LABEL_PREFIX__
+#define __USER_LABEL_PREFIX__
+#endif
+
+#ifndef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__
+#endif
+
+#ifndef __FLOAT_REGISTER_PREFIX__
+#define __FLOAT_REGISTER_PREFIX__ __REGISTER_PREFIX__
+#endif
+
+#if (PPC_ABI == PPC_ABI_POWEROPEN)
+#ifndef __PROC_LABEL_PREFIX__
+#define __PROC_LABEL_PREFIX__ .
+#endif
+#endif
+
+#ifndef __PROC_LABEL_PREFIX__
+#define __PROC_LABEL_PREFIX__ __USER_LABEL_PREFIX__
+#endif
+
+/* ANSI concatenation macros. */
+
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+/* Use the right prefix for global labels. */
+
+#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+
+/* Use the right prefix for procedure labels. */
+
+#define PROC(x) CONCAT1 (__PROC_LABEL_PREFIX__, x)
+
+/* Use the right prefix for registers. */
+
+#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
+
+/* Use the right prefix for floating point registers. */
+
+#define FREG(x) CONCAT1 (__FLOAT_REGISTER_PREFIX__, x)
+
+/*
+ * define macros for all of the registers on this CPU
+ *
+ * EXAMPLE: #define d0 REG (d0)
+ */
+#define r0 REG(0)
+#define r1 REG(1)
+#define r2 REG(2)
+#define r3 REG(3)
+#define r4 REG(4)
+#define r5 REG(5)
+#define r6 REG(6)
+#define r7 REG(7)
+#define r8 REG(8)
+#define r9 REG(9)
+#define r10 REG(10)
+#define r11 REG(11)
+#define r12 REG(12)
+#define r13 REG(13)
+#define r14 REG(14)
+#define r15 REG(15)
+#define r16 REG(16)
+#define r17 REG(17)
+#define r18 REG(18)
+#define r19 REG(19)
+#define r20 REG(20)
+#define r21 REG(21)
+#define r22 REG(22)
+#define r23 REG(23)
+#define r24 REG(24)
+#define r25 REG(25)
+#define r26 REG(26)
+#define r27 REG(27)
+#define r28 REG(28)
+#define r29 REG(29)
+#define r30 REG(30)
+#define r31 REG(31)
+#define f0 FREG(0)
+#define f1 FREG(1)
+#define f2 FREG(2)
+#define f3 FREG(3)
+#define f4 FREG(4)
+#define f5 FREG(5)
+#define f6 FREG(6)
+#define f7 FREG(7)
+#define f8 FREG(8)
+#define f9 FREG(9)
+#define f10 FREG(10)
+#define f11 FREG(11)
+#define f12 FREG(12)
+#define f13 FREG(13)
+#define f14 FREG(14)
+#define f15 FREG(15)
+#define f16 FREG(16)
+#define f17 FREG(17)
+#define f18 FREG(18)
+#define f19 FREG(19)
+#define f20 FREG(20)
+#define f21 FREG(21)
+#define f22 FREG(22)
+#define f23 FREG(23)
+#define f24 FREG(24)
+#define f25 FREG(25)
+#define f26 FREG(26)
+#define f27 FREG(27)
+#define f28 FREG(28)
+#define f29 FREG(29)
+#define f30 FREG(30)
+#define f31 FREG(31)
+
+/*
+ * Some special purpose registers (SPRs).
+ */
+#define srr0 0x01a
+#define srr1 0x01b
+#if defined(ppc403) || defined(ppc405)
+#define srr2 0x3de /* IBM 400 series only */
+#define srr3 0x3df /* IBM 400 series only */
+#endif /* ppc403 or ppc405 */
+
+#define sprg0 0x110
+#define sprg1 0x111
+#define sprg2 0x112
+#define sprg3 0x113
+
+#define dar 0x013 /* Data Address Register */
+#define dec 0x016 /* Decrementer Register */
+
+#if defined(ppc403) || defined(ppc405)
+/* the following SPR/DCR registers exist only in IBM 400 series */
+#define dear 0x3d5
+#define evpr 0x3d6 /* SPR: exception vector prefix register */
+#define iccr 0x3fb /* SPR: instruction cache control reg. */
+#define dccr 0x3fa /* SPR: data cache control reg. */
+
+#if defined (ppc403)
+#define exisr 0x040 /* DCR: external interrupt status register */
+#define exier 0x042 /* DCR: external interrupt enable register */
+#endif /* ppc403 */
+#if defined(ppc405)
+#define exisr 0x0C0 /* DCR: external interrupt status register */
+#define exier 0x0C2 /* DCR: external interrupt enable register */
+#endif /* ppc405 */
+
+#define br0 0x080 /* DCR: memory bank register 0 */
+#define br1 0x081 /* DCR: memory bank register 1 */
+#define br2 0x082 /* DCR: memory bank register 2 */
+#define br3 0x083 /* DCR: memory bank register 3 */
+#define br4 0x084 /* DCR: memory bank register 4 */
+#define br5 0x085 /* DCR: memory bank register 5 */
+#define br6 0x086 /* DCR: memory bank register 6 */
+#define br7 0x087 /* DCR: memory bank register 7 */
+/* end of IBM400 series register definitions */
+
+#elif defined(mpc555)
+/* The following registers are for the MPC5xx */
+#define eie 0x050 /* External Interrupt Enable Register */
+#define eid 0x051 /* External Interrupt Disable Register */
+#define nri 0x052 /* Non-Recoverable Interrupt Register */
+
+#elif defined(mpc860) || defined(mpc821)
+/* The following registers are for the MPC8x0 */
+#define der 0x095 /* Debug Enable Register */
+#define ictrl 0x09E /* Instruction Support Control Register */
+#define immr 0x27E /* Internal Memory Map Register */
+/* end of MPC8x0 registers */
+#endif
+
+/*
+ * Following must be tailor for a particular flavor of the C compiler.
+ * They may need to put underscores in front of the symbols.
+ */
+
+#define PUBLIC_VAR(sym) .globl SYM (sym)
+#define EXTERN_VAR(sym) .extern SYM (sym)
+#define PUBLIC_PROC(sym) .globl PROC (sym)
+#define EXTERN_PROC(sym) .extern PROC (sym)
+
+/* Other potentially assembler specific operations */
+#if PPC_ASM == PPC_ASM_ELF
+#define ALIGN(n,p) .align p
+#define DESCRIPTOR(x) \
+ .section .descriptors,"aw"; \
+ PUBLIC_VAR (x); \
+SYM (x):; \
+ .long PROC (x); \
+ .long s.got; \
+ .long 0
+
+#define EXT_SYM_REF(x) .long x
+#define EXT_PROC_REF(x) .long x
+
+/*
+ * Define macros to handle section beginning and ends.
+ */
+
+#define BEGIN_CODE_DCL .text
+#define END_CODE_DCL
+#define BEGIN_DATA_DCL .data
+#define END_DATA_DCL
+#define BEGIN_CODE .text
+#define END_CODE
+#define BEGIN_DATA .data
+#define END_DATA
+#define BEGIN_BSS .bss
+#define END_BSS
+#define END
+
+#elif PPC_ASM == PPC_ASM_XCOFF
+#define ALIGN(n,p) .align p
+#define DESCRIPTOR(x) \
+ .csect x[DS]; \
+ .globl x[DS]; \
+ .long PROC (x)[PR]; \
+ .long TOC[tc0]
+
+#define EXT_SYM_REF(x) .long x[RW]
+#define EXT_PROC_REF(x) .long x[DS]
+
+/*
+ * Define macros to handle section beginning and ends.
+ */
+
+#define BEGIN_CODE_DCL .csect .text[PR]
+#define END_CODE_DCL
+#define BEGIN_DATA_DCL .csect .data[RW]
+#define END_DATA_DCL
+#define BEGIN_CODE .csect .text[PR]
+#define END_CODE
+#define BEGIN_DATA .csect .data[RW]
+#define END_DATA
+#define BEGIN_BSS .bss
+#define END_BSS
+#define END
+
+#else
+#error "PPC_ASM_TYPE is not properly defined"
+#endif
+#ifndef PPC_ASM
+#error "PPC_ASM_TYPE is not properly defined"
+#endif
+
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/powerpc/rtems/new-exceptions/cpu.h b/cpukit/score/cpu/powerpc/rtems/new-exceptions/cpu.h
new file mode 100644
index 0000000000..23b685c235
--- /dev/null
+++ b/cpukit/score/cpu/powerpc/rtems/new-exceptions/cpu.h
@@ -0,0 +1,948 @@
+/* cpu.h
+ *
+ * This include file contains information pertaining to the PowerPC
+ * processor.
+ *
+ * Modified for MPC8260 Andy Dachs <a.dachs@sstl.co.uk>
+ * Surrey Satellite Technology Limited (SSTL), 2001
+ *
+ * Author: Andrew Bray <andy@i-cubed.co.uk>
+ *
+ * COPYRIGHT (c) 1995 by i-cubed ltd.
+ *
+ * To anyone who acknowledges that this file is provided "AS IS"
+ * without any express or implied warranty:
+ * permission to use, copy, modify, and distribute this file
+ * for any purpose is hereby granted without fee, provided that
+ * the above copyright notice and this notice appears in all
+ * copies, and that the name of i-cubed limited not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ * i-cubed limited makes no representations about the suitability
+ * of this software for any purpose.
+ *
+ * Derived from c/src/exec/cpu/no_cpu/cpu.h:
+ *
+ * COPYRIGHT (c) 1989-1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be found in
+ * the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __CPU_h
+#define __CPU_h
+
+#ifndef _rtems_score_cpu_h
+#error "You should include <rtems/score/cpu.h>"
+#endif
+
+#include <rtems/powerpc/registers.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* conditional compilation parameters */
+
+/*
+ * Does RTEMS manage a dedicated interrupt stack in software?
+ *
+ * If TRUE, then a stack is allocated in _ISR_Handler_initialization.
+ * If FALSE, nothing is done.
+ *
+ * If the CPU supports a dedicated interrupt stack in hardware,
+ * then it is generally the responsibility of the BSP to allocate it
+ * and set it up.
+ *
+ * If the CPU does not support a dedicated interrupt stack, then
+ * the porter has two options: (1) execute interrupts on the
+ * stack of the interrupted task, and (2) have RTEMS manage a dedicated
+ * interrupt stack.
+ *
+ * If this is TRUE, CPU_ALLOCATE_INTERRUPT_STACK should also be TRUE.
+ *
+ * Only one of CPU_HAS_SOFTWARE_INTERRUPT_STACK and
+ * CPU_HAS_HARDWARE_INTERRUPT_STACK should be set to TRUE. It is
+ * possible that both are FALSE for a particular CPU. Although it
+ * is unclear what that would imply about the interrupt processing
+ * procedure on that CPU.
+ */
+
+#define CPU_HAS_SOFTWARE_INTERRUPT_STACK TRUE
+
+/*
+ * Does this CPU have hardware support for a dedicated interrupt stack?
+ *
+ * If TRUE, then it must be installed during initialization.
+ * If FALSE, then no installation is performed.
+ *
+ * If this is TRUE, CPU_ALLOCATE_INTERRUPT_STACK should also be TRUE.
+ *
+ * Only one of CPU_HAS_SOFTWARE_INTERRUPT_STACK and
+ * CPU_HAS_HARDWARE_INTERRUPT_STACK should be set to TRUE. It is
+ * possible that both are FALSE for a particular CPU. Although it
+ * is unclear what that would imply about the interrupt processing
+ * procedure on that CPU.
+ */
+
+#define CPU_HAS_HARDWARE_INTERRUPT_STACK FALSE
+
+/*
+ * Does RTEMS allocate a dedicated interrupt stack in the Interrupt Manager?
+ *
+ * If TRUE, then the memory is allocated during initialization.
+ * If FALSE, then the memory is allocated during initialization.
+ *
+ * This should be TRUE is CPU_HAS_SOFTWARE_INTERRUPT_STACK is TRUE
+ * or CPU_INSTALL_HARDWARE_INTERRUPT_STACK is TRUE.
+ */
+
+#define CPU_ALLOCATE_INTERRUPT_STACK FALSE
+
+/*
+ * Does the RTEMS invoke the user's ISR with the vector number and
+ * a pointer to the saved interrupt frame (1) or just the vector
+ * number (0)?
+ */
+
+#define CPU_ISR_PASSES_FRAME_POINTER 0
+
+/*
+ * Does the CPU have hardware floating point?
+ *
+ * If TRUE, then the RTEMS_FLOATING_POINT task attribute is supported.
+ * If FALSE, then the RTEMS_FLOATING_POINT task attribute is ignored.
+ *
+ * If there is a FP coprocessor such as the i387 or mc68881, then
+ * the answer is TRUE.
+ *
+ * The macro name "PPC_HAS_FPU" should be made CPU specific.
+ * It indicates whether or not this CPU model has FP support. For
+ * example, it would be possible to have an i386_nofp CPU model
+ * which set this to false to indicate that you have an i386 without
+ * an i387 and wish to leave floating point support out of RTEMS.
+ */
+
+#if ( PPC_HAS_FPU == 1 )
+#define CPU_HARDWARE_FP TRUE
+#else
+#define CPU_HARDWARE_FP FALSE
+#endif
+
+/*
+ * Are all tasks RTEMS_FLOATING_POINT tasks implicitly?
+ *
+ * If TRUE, then the RTEMS_FLOATING_POINT task attribute is assumed.
+ * If FALSE, then the RTEMS_FLOATING_POINT task attribute is followed.
+ *
+ * If CPU_HARDWARE_FP is FALSE, then this should be FALSE as well.
+ */
+
+#define CPU_ALL_TASKS_ARE_FP FALSE
+
+/*
+ * Should the IDLE task have a floating point context?
+ *
+ * If TRUE, then the IDLE task is created as a RTEMS_FLOATING_POINT task
+ * and it has a floating point context which is switched in and out.
+ * If FALSE, then the IDLE task does not have a floating point context.
+ *
+ * Setting this to TRUE negatively impacts the time required to preempt
+ * the IDLE task from an interrupt because the floating point context
+ * must be saved as part of the preemption.
+ */
+
+#define CPU_IDLE_TASK_IS_FP FALSE
+
+/*
+ * Should the saving of the floating point registers be deferred
+ * until a context switch is made to another different floating point
+ * task?
+ *
+ * If TRUE, then the floating point context will not be stored until
+ * necessary. It will remain in the floating point registers and not
+ * disturned until another floating point task is switched to.
+ *
+ * If FALSE, then the floating point context is saved when a floating
+ * point task is switched out and restored when the next floating point
+ * task is restored. The state of the floating point registers between
+ * those two operations is not specified.
+ *
+ * If the floating point context does NOT have to be saved as part of
+ * interrupt dispatching, then it should be safe to set this to TRUE.
+ *
+ * Setting this flag to TRUE results in using a different algorithm
+ * for deciding when to save and restore the floating point context.
+ * The deferred FP switch algorithm minimizes the number of times
+ * the FP context is saved and restored. The FP context is not saved
+ * until a context switch is made to another, different FP task.
+ * Thus in a system with only one FP task, the FP context will never
+ * be saved or restored.
+ *
+ * Note, however that compilers may use floating point registers/
+ * instructions for optimization or they may save/restore FP registers
+ * on the stack. You must not use deferred switching in these cases
+ * and on the PowerPC attempting to do so will raise a "FP unavailable"
+ * exception.
+ */
+/*
+ * ACB Note: This could make debugging tricky..
+ */
+
+/* conservative setting (FALSE); probably doesn't affect performance too much */
+#define CPU_USE_DEFERRED_FP_SWITCH FALSE
+
+/*
+ * Does this port provide a CPU dependent IDLE task implementation?
+ *
+ * If TRUE, then the routine _CPU_Thread_Idle_body
+ * must be provided and is the default IDLE thread body instead of
+ * _CPU_Thread_Idle_body.
+ *
+ * If FALSE, then use the generic IDLE thread body if the BSP does
+ * not provide one.
+ *
+ * This is intended to allow for supporting processors which have
+ * a low power or idle mode. When the IDLE thread is executed, then
+ * the CPU can be powered down.
+ *
+ * The order of precedence for selecting the IDLE thread body is:
+ *
+ * 1. BSP provided
+ * 2. CPU dependent (if provided)
+ * 3. generic (if no BSP and no CPU dependent)
+ */
+
+#define CPU_PROVIDES_IDLE_THREAD_BODY FALSE
+
+
+/*
+ * Does the stack grow up (toward higher addresses) or down
+ * (toward lower addresses)?
+ *
+ * If TRUE, then the grows upward.
+ * If FALSE, then the grows toward smaller addresses.
+ */
+
+#define CPU_STACK_GROWS_UP FALSE
+
+/*
+ * The following is the variable attribute used to force alignment
+ * of critical RTEMS structures. On some processors it may make
+ * sense to have these aligned on tighter boundaries than
+ * the minimum requirements of the compiler in order to have as
+ * much of the critical data area as possible in a cache line.
+ *
+ * The placement of this macro in the declaration of the variables
+ * is based on the syntactically requirements of the GNU C
+ * "__attribute__" extension. For example with GNU C, use
+ * the following to force a structures to a 32 byte boundary.
+ *
+ * __attribute__ ((aligned (32)))
+ *
+ * NOTE: Currently only the Priority Bit Map table uses this feature.
+ * To benefit from using this, the data must be heavily
+ * used so it will stay in the cache and used frequently enough
+ * in the executive to justify turning this on.
+ */
+
+#define CPU_STRUCTURE_ALIGNMENT \
+ __attribute__ ((aligned (PPC_CACHE_ALIGNMENT)))
+
+/*
+ * Define what is required to specify how the network to host conversion
+ * routines are handled.
+ */
+
+#define CPU_HAS_OWN_HOST_TO_NETWORK_ROUTINES FALSE
+#define CPU_BIG_ENDIAN TRUE
+#define CPU_LITTLE_ENDIAN FALSE
+
+
+/*
+ * Processor defined structures
+ *
+ * Examples structures include the descriptor tables from the i386
+ * and the processor control structure on the i960ca.
+ */
+
+/* may need to put some structures here. */
+
+/*
+ * Contexts
+ *
+ * Generally there are 2 types of context to save.
+ * 1. Interrupt registers to save
+ * 2. Task level registers to save
+ *
+ * This means we have the following 3 context items:
+ * 1. task level context stuff:: Context_Control
+ * 2. floating point task stuff:: Context_Control_fp
+ * 3. special interrupt level context :: Context_Control_interrupt
+ *
+ * On some processors, it is cost-effective to save only the callee
+ * preserved registers during a task context switch. This means
+ * that the ISR code needs to save those registers which do not
+ * persist across function calls. It is not mandatory to make this
+ * distinctions between the caller/callee saves registers for the
+ * purpose of minimizing context saved during task switch and on interrupts.
+ * If the cost of saving extra registers is minimal, simplicity is the
+ * choice. Save the same context on interrupt entry as for tasks in
+ * this case.
+ *
+ * Additionally, if gdb is to be made aware of RTEMS tasks for this CPU, then
+ * care should be used in designing the context area.
+ *
+ * On some CPUs with hardware floating point support, the Context_Control_fp
+ * structure will not be used or it simply consist of an array of a
+ * fixed number of bytes. This is done when the floating point context
+ * is dumped by a "FP save context" type instruction and the format
+ * is not really defined by the CPU. In this case, there is no need
+ * to figure out the exact format -- only the size. Of course, although
+ * this is enough information for RTEMS, it is probably not enough for
+ * a debugger such as gdb. But that is another problem.
+ */
+
+#ifndef ASM
+
+typedef struct {
+ uint32_t gpr1; /* Stack pointer for all */
+ uint32_t gpr2; /* TOC in PowerOpen, reserved SVR4, section ptr EABI + */
+ uint32_t gpr13; /* First non volatile PowerOpen, section ptr SVR4/EABI */
+ uint32_t gpr14; /* Non volatile for all */
+ uint32_t gpr15; /* Non volatile for all */
+ uint32_t gpr16; /* Non volatile for all */
+ uint32_t gpr17; /* Non volatile for all */
+ uint32_t gpr18; /* Non volatile for all */
+ uint32_t gpr19; /* Non volatile for all */
+ uint32_t gpr20; /* Non volatile for all */
+ uint32_t gpr21; /* Non volatile for all */
+ uint32_t gpr22; /* Non volatile for all */
+ uint32_t gpr23; /* Non volatile for all */
+ uint32_t gpr24; /* Non volatile for all */
+ uint32_t gpr25; /* Non volatile for all */
+ uint32_t gpr26; /* Non volatile for all */
+ uint32_t gpr27; /* Non volatile for all */
+ uint32_t gpr28; /* Non volatile for all */
+ uint32_t gpr29; /* Non volatile for all */
+ uint32_t gpr30; /* Non volatile for all */
+ uint32_t gpr31; /* Non volatile for all */
+ uint32_t cr; /* PART of the CR is non volatile for all */
+ uint32_t pc; /* Program counter/Link register */
+ uint32_t msr; /* Initial interrupt level */
+} Context_Control;
+
+typedef struct {
+ /* The ABIs (PowerOpen/SVR4/EABI) only require saving f14-f31 over
+ * procedure calls. However, this would mean that the interrupt
+ * frame had to hold f0-f13, and the fpscr. And as the majority
+ * of tasks will not have an FP context, we will save the whole
+ * context here.
+ */
+#if (PPC_HAS_DOUBLE == 1)
+ double f[32];
+ double fpscr;
+#else
+ float f[32];
+ float fpscr;
+#endif
+} Context_Control_fp;
+
+typedef struct CPU_Interrupt_frame {
+ uint32_t stacklink; /* Ensure this is a real frame (also reg1 save) */
+ uint32_t calleeLr; /* link register used by callees: SVR4/EABI */
+ /* This is what is left out of the primary contexts */
+ uint32_t gpr0;
+ uint32_t gpr2; /* play safe */
+ uint32_t gpr3;
+ uint32_t gpr4;
+ uint32_t gpr5;
+ uint32_t gpr6;
+ uint32_t gpr7;
+ uint32_t gpr8;
+ uint32_t gpr9;
+ uint32_t gpr10;
+ uint32_t gpr11;
+ uint32_t gpr12;
+ uint32_t gpr13; /* Play safe */
+ uint32_t gpr28; /* For internal use by the IRQ handler */
+ uint32_t gpr29; /* For internal use by the IRQ handler */
+ uint32_t gpr30; /* For internal use by the IRQ handler */
+ uint32_t gpr31; /* For internal use by the IRQ handler */
+ uint32_t cr; /* Bits of this are volatile, so no-one may save */
+ uint32_t ctr;
+ uint32_t xer;
+ uint32_t lr;
+ uint32_t pc;
+ uint32_t msr;
+ uint32_t pad[3];
+} CPU_Interrupt_frame;
+
+/*
+ * The following table contains the information required to configure
+ * the PowerPC processor specific parameters.
+ */
+
+typedef struct {
+ void (*pretasking_hook)( void );
+ void (*predriver_hook)( void );
+ void (*postdriver_hook)( void );
+ void (*idle_task)( void );
+ boolean do_zero_of_workspace;
+ uint32_t idle_task_stack_size;
+ uint32_t interrupt_stack_size;
+ uint32_t extra_mpci_receive_server_stack;
+ void * (*stack_allocate_hook)( uint32_t );
+ void (*stack_free_hook)( void* );
+ /* end of fields required on all CPUs */
+
+ uint32_t clicks_per_usec; /* Timer clicks per microsecond */
+ boolean exceptions_in_RAM; /* TRUE if in RAM */
+
+#if (defined(ppc403) || defined(mpc860) || defined(mpc821) || defined(mpc8260))
+ uint32_t serial_per_sec; /* Serial clocks per second */
+ boolean serial_external_clock;
+ boolean serial_xon_xoff;
+ boolean serial_cts_rts;
+ uint32_t serial_rate;
+ uint32_t timer_average_overhead; /* Average overhead of timer in ticks */
+ uint32_t timer_least_valid; /* Least valid number from timer */
+ boolean timer_internal_clock; /* TRUE, when timer runs with CPU clk */
+#endif
+
+#if (defined(mpc555) || defined(mpc860) || defined(mpc821) || defined(mpc8260))
+ uint32_t clock_speed; /* Speed of CPU in Hz */
+#endif
+} rtems_cpu_table;
+
+/*
+ * Macros to access required entires in the CPU Table are in
+ * the file rtems/system.h.
+ */
+
+/*
+ * Macros to access PowerPC MPC750 specific additions to the CPU Table
+ */
+
+#define rtems_cpu_configuration_get_clicks_per_usec() \
+ (_CPU_Table.clicks_per_usec)
+
+#define rtems_cpu_configuration_get_exceptions_in_ram() \
+ (_CPU_Table.exceptions_in_RAM)
+
+/*
+ * This variable is optional. It is used on CPUs on which it is difficult
+ * to generate an "uninitialized" FP context. It is filled in by
+ * _CPU_Initialize and copied into the task's FP context area during
+ * _CPU_Context_Initialize.
+ */
+
+/* EXTERN Context_Control_fp _CPU_Null_fp_context; */
+
+/*
+ * On some CPUs, RTEMS supports a software managed interrupt stack.
+ * This stack is allocated by the Interrupt Manager and the switch
+ * is performed in _ISR_Handler. These variables contain pointers
+ * to the lowest and highest addresses in the chunk of memory allocated
+ * for the interrupt stack. Since it is unknown whether the stack
+ * grows up or down (in general), this give the CPU dependent
+ * code the option of picking the version it wants to use.
+ *
+ * NOTE: These two variables are required if the macro
+ * CPU_HAS_SOFTWARE_INTERRUPT_STACK is defined as TRUE.
+ */
+
+SCORE_EXTERN void *_CPU_Interrupt_stack_low;
+SCORE_EXTERN void *_CPU_Interrupt_stack_high;
+
+#endif /* ndef ASM */
+
+/*
+ * This defines the number of levels and the mask used to pick those
+ * bits out of a thread mode.
+ */
+
+#define CPU_MODES_INTERRUPT_LEVEL 0x00000001 /* interrupt level in mode */
+#define CPU_MODES_INTERRUPT_MASK 0x00000001 /* interrupt level in mode */
+
+/*
+ * With some compilation systems, it is difficult if not impossible to
+ * call a high-level language routine from assembly language. This
+ * is especially true of commercial Ada compilers and name mangling
+ * C++ ones. This variable can be optionally defined by the CPU porter
+ * and contains the address of the routine _Thread_Dispatch. This
+ * can make it easier to invoke that routine at the end of the interrupt
+ * sequence (if a dispatch is necessary).
+ */
+
+/* EXTERN void (*_CPU_Thread_dispatch_pointer)(); */
+
+/*
+ * Nothing prevents the porter from declaring more CPU specific variables.
+ */
+
+#ifndef ASM
+
+SCORE_EXTERN struct {
+ uint32_t *Disable_level;
+ void *Stack;
+ volatile boolean *Switch_necessary;
+ boolean *Signal;
+
+} _CPU_IRQ_info CPU_STRUCTURE_ALIGNMENT;
+
+#endif /* ndef ASM */
+
+/*
+ * The size of the floating point context area. On some CPUs this
+ * will not be a "sizeof" because the format of the floating point
+ * area is not defined -- only the size is. This is usually on
+ * CPUs with a "floating point save context" instruction.
+ */
+
+#define CPU_CONTEXT_FP_SIZE sizeof( Context_Control_fp )
+
+/*
+ * (Optional) # of bytes for libmisc/stackchk to check
+ * If not specifed, then it defaults to something reasonable
+ * for most architectures.
+ */
+
+#define CPU_STACK_CHECK_SIZE (128)
+
+/*
+ * Amount of extra stack (above minimum stack size) required by
+ * MPCI receive server thread. Remember that in a multiprocessor
+ * system this thread must exist and be able to process all directives.
+ */
+
+#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 0
+
+/*
+ * This defines the number of entries in the ISR_Vector_table managed
+ * by RTEMS.
+ */
+
+#define CPU_INTERRUPT_NUMBER_OF_VECTORS (PPC_INTERRUPT_MAX)
+#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (PPC_INTERRUPT_MAX - 1)
+
+/*
+ * This is defined if the port has a special way to report the ISR nesting
+ * level. Most ports maintain the variable _ISR_Nest_level. Note that
+ * this is not an option - RTEMS/score _relies_ on _ISR_Nest_level
+ * being maintained (e.g. watchdog queues).
+ */
+
+#define CPU_PROVIDES_ISR_IS_IN_PROGRESS FALSE
+
+/*
+ * Should be large enough to run all RTEMS tests. This insures
+ * that a "reasonable" small application should not have any problems.
+ */
+
+#define CPU_STACK_MINIMUM_SIZE (1024*8)
+
+/*
+ * CPU's worst alignment requirement for data types on a byte boundary. This
+ * alignment does not take into account the requirements for the stack.
+ */
+
+#define CPU_ALIGNMENT (PPC_ALIGNMENT)
+
+/*
+ * This number corresponds to the byte alignment requirement for the
+ * heap handler. This alignment requirement may be stricter than that
+ * for the data types alignment specified by CPU_ALIGNMENT. It is
+ * common for the heap to follow the same alignment requirement as
+ * CPU_ALIGNMENT. If the CPU_ALIGNMENT is strict enough for the heap,
+ * then this should be set to CPU_ALIGNMENT.
+ *
+ * NOTE: This does not have to be a power of 2. It does have to
+ * be greater or equal to than CPU_ALIGNMENT.
+ */
+
+#define CPU_HEAP_ALIGNMENT (PPC_ALIGNMENT)
+
+/*
+ * This number corresponds to the byte alignment requirement for memory
+ * buffers allocated by the partition manager. This alignment requirement
+ * may be stricter than that for the data types alignment specified by
+ * CPU_ALIGNMENT. It is common for the partition to follow the same
+ * alignment requirement as CPU_ALIGNMENT. If the CPU_ALIGNMENT is strict
+ * enough for the partition, then this should be set to CPU_ALIGNMENT.
+ *
+ * NOTE: This does not have to be a power of 2. It does have to
+ * be greater or equal to than CPU_ALIGNMENT.
+ */
+
+#define CPU_PARTITION_ALIGNMENT (PPC_ALIGNMENT)
+
+/*
+ * This number corresponds to the byte alignment requirement for the
+ * stack. This alignment requirement may be stricter than that for the
+ * data types alignment specified by CPU_ALIGNMENT. If the CPU_ALIGNMENT
+ * is strict enough for the stack, then this should be set to 0.
+ *
+ * NOTE: This must be a power of 2 either 0 or greater than CPU_ALIGNMENT.
+ */
+
+#define CPU_STACK_ALIGNMENT (PPC_STACK_ALIGNMENT)
+
+/*
+ * Needed for Interrupt stack
+ */
+#define CPU_MINIMUM_STACK_FRAME_SIZE 8
+
+
+/*
+ * ISR handler macros
+ */
+
+#define _CPU_Initialize_vectors()
+
+/*
+ * Disable all interrupts for an RTEMS critical section. The previous
+ * level is returned in _isr_cookie.
+ */
+
+#ifndef ASM
+
+static inline uint32_t _CPU_ISR_Get_level( void )
+{
+ register unsigned int msr;
+ _CPU_MSR_GET(msr);
+ if (msr & MSR_EE) return 0;
+ else return 1;
+}
+
+static inline void _CPU_ISR_Set_level( uint32_t level )
+{
+ register unsigned int msr;
+ _CPU_MSR_GET(msr);
+ if (!(level & CPU_MODES_INTERRUPT_MASK)) {
+ msr |= MSR_EE;
+ }
+ else {
+ msr &= ~MSR_EE;
+ }
+ _CPU_MSR_SET(msr);
+}
+
+void BSP_panic(char *);
+#define _CPU_ISR_install_vector(irq, new, old) \
+ {BSP_panic("_CPU_ISR_install_vector called\n");}
+
+/* Context handler macros */
+
+/*
+ * Initialize the context to a state suitable for starting a
+ * task after a context restore operation. Generally, this
+ * involves:
+ *
+ * - setting a starting address
+ * - preparing the stack
+ * - preparing the stack and frame pointers
+ * - setting the proper interrupt level in the context
+ * - initializing the floating point context
+ *
+ * This routine generally does not set any unnecessary register
+ * in the context. The state of the "general data" registers is
+ * undefined at task start time.
+ *
+ * NOTE: Implemented as a subroutine for the SPARC port.
+ */
+
+void _CPU_Context_Initialize(
+ Context_Control *the_context,
+ uint32_t *stack_base,
+ uint32_t size,
+ uint32_t new_level,
+ void *entry_point,
+ boolean is_fp
+);
+
+/*
+ * This routine is responsible for somehow restarting the currently
+ * executing task. If you are lucky, then all that is necessary
+ * is restoring the context. Otherwise, there will need to be
+ * a special assembly routine which does something special in this
+ * case. Context_Restore should work most of the time. It will
+ * not work if restarting self conflicts with the stack frame
+ * assumptions of restoring a context.
+ */
+
+#define _CPU_Context_Restart_self( _the_context ) \
+ _CPU_Context_restore( (_the_context) );
+
+/*
+ * The purpose of this macro is to allow the initial pointer into
+ * a floating point context area (used to save the floating point
+ * context) to be at an arbitrary place in the floating point
+ * context area.
+ *
+ * This is necessary because some FP units are designed to have
+ * their context saved as a stack which grows into lower addresses.
+ * Other FP units can be saved by simply moving registers into offsets
+ * from the base of the context area. Finally some FP units provide
+ * a "dump context" instruction which could fill in from high to low
+ * or low to high based on the whim of the CPU designers.
+ */
+
+#define _CPU_Context_Fp_start( _base, _offset ) \
+ ( (void *) _Addresses_Add_offset( (_base), (_offset) ) )
+
+/*
+ * This routine initializes the FP context area passed to it to.
+ * There are a few standard ways in which to initialize the
+ * floating point context. The code included for this macro assumes
+ * that this is a CPU in which a "initial" FP context was saved into
+ * _CPU_Null_fp_context and it simply copies it to the destination
+ * context passed to it.
+ *
+ * Other models include (1) not doing anything, and (2) putting
+ * a "null FP status word" in the correct place in the FP context.
+ */
+
+#define _CPU_Context_Initialize_fp( _destination ) \
+ { \
+ ((Context_Control_fp *) *((void **) _destination))->fpscr = PPC_INIT_FPSCR; \
+ }
+
+/* end of Context handler macros */
+
+/* Fatal Error manager macros */
+
+/*
+ * This routine copies _error into a known place -- typically a stack
+ * location or a register, optionally disables interrupts, and
+ * halts/stops the CPU.
+ */
+
+void _BSP_Fatal_error(unsigned int);
+
+#define _CPU_Fatal_halt( _error ) \
+ _BSP_Fatal_error(_error)
+
+/* end of Fatal Error manager macros */
+
+/* Bitfield handler macros */
+
+/*
+ * This routine sets _output to the bit number of the first bit
+ * set in _value. _value is of CPU dependent type Priority_Bit_map_control.
+ * This type may be either 16 or 32 bits wide although only the 16
+ * least significant bits will be used.
+ *
+ * There are a number of variables in using a "find first bit" type
+ * instruction.
+ *
+ * (1) What happens when run on a value of zero?
+ * (2) Bits may be numbered from MSB to LSB or vice-versa.
+ * (3) The numbering may be zero or one based.
+ * (4) The "find first bit" instruction may search from MSB or LSB.
+ *
+ * RTEMS guarantees that (1) will never happen so it is not a concern.
+ * (2),(3), (4) are handled by the macros _CPU_Priority_mask() and
+ * _CPU_Priority_Bits_index(). These three form a set of routines
+ * which must logically operate together. Bits in the _value are
+ * set and cleared based on masks built by _CPU_Priority_mask().
+ * The basic major and minor values calculated by _Priority_Major()
+ * and _Priority_Minor() are "massaged" by _CPU_Priority_Bits_index()
+ * to properly range between the values returned by the "find first bit"
+ * instruction. This makes it possible for _Priority_Get_highest() to
+ * calculate the major and directly index into the minor table.
+ * This mapping is necessary to ensure that 0 (a high priority major/minor)
+ * is the first bit found.
+ *
+ * This entire "find first bit" and mapping process depends heavily
+ * on the manner in which a priority is broken into a major and minor
+ * components with the major being the 4 MSB of a priority and minor
+ * the 4 LSB. Thus (0 << 4) + 0 corresponds to priority 0 -- the highest
+ * priority. And (15 << 4) + 14 corresponds to priority 254 -- the next
+ * to the lowest priority.
+ *
+ * If your CPU does not have a "find first bit" instruction, then
+ * there are ways to make do without it. Here are a handful of ways
+ * to implement this in software:
+ *
+ * - a series of 16 bit test instructions
+ * - a "binary search using if's"
+ * - _number = 0
+ * if _value > 0x00ff
+ * _value >>=8
+ * _number = 8;
+ *
+ * if _value > 0x0000f
+ * _value >=8
+ * _number += 4
+ *
+ * _number += bit_set_table[ _value ]
+ *
+ * where bit_set_table[ 16 ] has values which indicate the first
+ * bit set
+ */
+
+#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
+ { \
+ asm volatile ("cntlzw %0, %1" : "=r" ((_output)), "=r" ((_value)) : \
+ "1" ((_value))); \
+ }
+
+/* end of Bitfield handler macros */
+
+/*
+ * This routine builds the mask which corresponds to the bit fields
+ * as searched by _CPU_Bitfield_Find_first_bit(). See the discussion
+ * for that routine.
+ */
+
+#define _CPU_Priority_Mask( _bit_number ) \
+ ( 0x80000000 >> (_bit_number) )
+
+/*
+ * This routine translates the bit numbers returned by
+ * _CPU_Bitfield_Find_first_bit() into something suitable for use as
+ * a major or minor component of a priority. See the discussion
+ * for that routine.
+ */
+
+#define _CPU_Priority_bits_index( _priority ) \
+ (_priority)
+
+/* end of Priority handler macros */
+
+/* variables */
+
+extern const uint32_t _CPU_msrs[4];
+
+/* functions */
+
+/*
+ * _CPU_Initialize
+ *
+ * This routine performs CPU dependent initialization.
+ *
+ * Until all new-exception processing BSPs have fixed
+ * PR288, we let the good BSPs pass
+ *
+ * PPC_BSP_HAS_FIXED_PR288
+ *
+ * in SPRG0 and let _CPU_Initialize assert this.
+ */
+
+#define PPC_BSP_HAS_FIXED_PR288 0x600dbabe
+
+void _CPU_Initialize(
+ rtems_cpu_table *cpu_table,
+ void (*thread_dispatch)
+);
+
+
+/*
+ * _CPU_Install_interrupt_stack
+ *
+ * This routine installs the hardware interrupt stack pointer.
+ *
+ * NOTE: It need only be provided if CPU_HAS_HARDWARE_INTERRUPT_STACK
+ * is TRUE.
+ */
+
+void _CPU_Install_interrupt_stack( void );
+
+/*
+ * _CPU_Context_switch
+ *
+ * This routine switches from the run context to the heir context.
+ */
+
+void _CPU_Context_switch(
+ Context_Control *run,
+ Context_Control *heir
+);
+
+/*
+ * _CPU_Context_restore
+ *
+ * This routine is generallu used only to restart self in an
+ * efficient manner. It may simply be a label in _CPU_Context_switch.
+ *
+ * NOTE: May be unnecessary to reload some registers.
+ */
+
+void _CPU_Context_restore(
+ Context_Control *new_context
+);
+
+/*
+ * _CPU_Context_save_fp
+ *
+ * This routine saves the floating point context passed to it.
+ */
+
+void _CPU_Context_save_fp(
+ void **fp_context_ptr
+);
+
+/*
+ * _CPU_Context_restore_fp
+ *
+ * This routine restores the floating point context passed to it.
+ */
+
+void _CPU_Context_restore_fp(
+ void **fp_context_ptr
+);
+
+void _CPU_Fatal_error(
+ uint32_t _error
+);
+
+/* The following routine swaps the endian format of an unsigned int.
+ * It must be static because it is referenced indirectly.
+ *
+ * This version will work on any processor, but if there is a better
+ * way for your CPU PLEASE use it. The most common way to do this is to:
+ *
+ * swap least significant two bytes with 16-bit rotate
+ * swap upper and lower 16-bits
+ * swap most significant two bytes with 16-bit rotate
+ *
+ * Some CPUs have special instructions which swap a 32-bit quantity in
+ * a single instruction (e.g. i486). It is probably best to avoid
+ * an "endian swapping control bit" in the CPU. One good reason is
+ * that interrupts would probably have to be disabled to insure that
+ * an interrupt does not try to access the same "chunk" with the wrong
+ * endian. Another good reason is that on some CPUs, the endian bit
+ * endianness for ALL fetches -- both code and data -- so the code
+ * will be fetched incorrectly.
+ */
+
+static inline unsigned int CPU_swap_u32(
+ unsigned int value
+)
+{
+ uint32_t swapped;
+
+ asm volatile("rlwimi %0,%1,8,24,31;"
+ "rlwimi %0,%1,24,16,23;"
+ "rlwimi %0,%1,8,8,15;"
+ "rlwimi %0,%1,24,0,7;" :
+ "=&r" ((swapped)) : "r" ((value)));
+
+ return( swapped );
+}
+
+#define CPU_swap_u16( value ) \
+ (((value&0xff) << 8) | ((value >> 8)&0xff))
+
+#endif /* ndef ASM */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/score/cpu/powerpc/rtems/old-exceptions/cpu.h b/cpukit/score/cpu/powerpc/rtems/old-exceptions/cpu.h
new file mode 100644
index 0000000000..0788a797c9
--- /dev/null
+++ b/cpukit/score/cpu/powerpc/rtems/old-exceptions/cpu.h
@@ -0,0 +1,1152 @@
+/* cpu.h
+ *
+ * This include file contains information pertaining to the PowerPC
+ * processor.
+ *
+ * Author: Andrew Bray <andy@i-cubed.co.uk>
+ *
+ * COPYRIGHT (c) 1995 by i-cubed ltd.
+ *
+ * To anyone who acknowledges that this file is provided "AS IS"
+ * without any express or implied warranty:
+ * permission to use, copy, modify, and distribute this file
+ * for any purpose is hereby granted without fee, provided that
+ * the above copyright notice and this notice appears in all
+ * copies, and that the name of i-cubed limited not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ * i-cubed limited makes no representations about the suitability
+ * of this software for any purpose.
+ *
+ * Derived from c/src/exec/cpu/no_cpu/cpu.h:
+ *
+ * COPYRIGHT (c) 1989-1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may in
+ * the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __CPU_h
+#define __CPU_h
+
+#ifndef _rtems_score_cpu_h
+#error "You should include <rtems/score/cpu.h>"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef ASM
+struct CPU_Interrupt_frame;
+typedef void ( *ppc_isr_entry )( int, struct CPU_Interrupt_frame * );
+#endif
+
+/* conditional compilation parameters */
+
+/*
+ * Does RTEMS manage a dedicated interrupt stack in software?
+ *
+ * If TRUE, then a stack is allocated in _ISR_Handler_initialization.
+ * If FALSE, nothing is done.
+ *
+ * If the CPU supports a dedicated interrupt stack in hardware,
+ * then it is generally the responsibility of the BSP to allocate it
+ * and set it up.
+ *
+ * If the CPU does not support a dedicated interrupt stack, then
+ * the porter has two options: (1) execute interrupts on the
+ * stack of the interrupted task, and (2) have RTEMS manage a dedicated
+ * interrupt stack.
+ *
+ * If this is TRUE, CPU_ALLOCATE_INTERRUPT_STACK should also be TRUE.
+ *
+ * Only one of CPU_HAS_SOFTWARE_INTERRUPT_STACK and
+ * CPU_HAS_HARDWARE_INTERRUPT_STACK should be set to TRUE. It is
+ * possible that both are FALSE for a particular CPU. Although it
+ * is unclear what that would imply about the interrupt processing
+ * procedure on that CPU.
+ */
+
+#define CPU_HAS_SOFTWARE_INTERRUPT_STACK FALSE
+
+/*
+ * Does this CPU have hardware support for a dedicated interrupt stack?
+ *
+ * If TRUE, then it must be installed during initialization.
+ * If FALSE, then no installation is performed.
+ *
+ * If this is TRUE, CPU_ALLOCATE_INTERRUPT_STACK should also be TRUE.
+ *
+ * Only one of CPU_HAS_SOFTWARE_INTERRUPT_STACK and
+ * CPU_HAS_HARDWARE_INTERRUPT_STACK should be set to TRUE. It is
+ * possible that both are FALSE for a particular CPU. Although it
+ * is unclear what that would imply about the interrupt processing
+ * procedure on that CPU.
+ */
+
+/*
+ * ACB: This is a lie, but it gets us a handle on a call to set up
+ * a variable derived from the top of the interrupt stack.
+ */
+
+#define CPU_HAS_HARDWARE_INTERRUPT_STACK TRUE
+
+/*
+ * Does RTEMS allocate a dedicated interrupt stack in the Interrupt Manager?
+ *
+ * If TRUE, then the memory is allocated during initialization.
+ * If FALSE, then the memory is allocated during initialization.
+ *
+ * This should be TRUE is CPU_HAS_SOFTWARE_INTERRUPT_STACK is TRUE
+ * or CPU_INSTALL_HARDWARE_INTERRUPT_STACK is TRUE.
+ */
+
+#define CPU_ALLOCATE_INTERRUPT_STACK TRUE
+
+/*
+ * Does the RTEMS invoke the user's ISR with the vector number and
+ * a pointer to the saved interrupt frame (1) or just the vector
+ * number (0)?
+ */
+
+#define CPU_ISR_PASSES_FRAME_POINTER 1
+
+/*
+ * Does the CPU have hardware floating point?
+ *
+ * If TRUE, then the RTEMS_FLOATING_POINT task attribute is supported.
+ * If FALSE, then the RTEMS_FLOATING_POINT task attribute is ignored.
+ *
+ * If there is a FP coprocessor such as the i387 or mc68881, then
+ * the answer is TRUE.
+ *
+ * The macro name "PPC_HAS_FPU" should be made CPU specific.
+ * It indicates whether or not this CPU model has FP support. For
+ * example, it would be possible to have an i386_nofp CPU model
+ * which set this to false to indicate that you have an i386 without
+ * an i387 and wish to leave floating point support out of RTEMS.
+ */
+
+#if ( PPC_HAS_FPU == 1 )
+#define CPU_HARDWARE_FP TRUE
+#else
+#define CPU_HARDWARE_FP FALSE
+#endif
+
+/*
+ * Are all tasks RTEMS_FLOATING_POINT tasks implicitly?
+ *
+ * If TRUE, then the RTEMS_FLOATING_POINT task attribute is assumed.
+ * If FALSE, then the RTEMS_FLOATING_POINT task attribute is followed.
+ *
+ * If CPU_HARDWARE_FP is FALSE, then this should be FALSE as well.
+ */
+
+#define CPU_ALL_TASKS_ARE_FP FALSE
+
+/*
+ * Should the IDLE task have a floating point context?
+ *
+ * If TRUE, then the IDLE task is created as a RTEMS_FLOATING_POINT task
+ * and it has a floating point context which is switched in and out.
+ * If FALSE, then the IDLE task does not have a floating point context.
+ *
+ * Setting this to TRUE negatively impacts the time required to preempt
+ * the IDLE task from an interrupt because the floating point context
+ * must be saved as part of the preemption.
+ */
+
+#define CPU_IDLE_TASK_IS_FP FALSE
+
+/*
+ * Should the saving of the floating point registers be deferred
+ * until a context switch is made to another different floating point
+ * task?
+ *
+ * If TRUE, then the floating point context will not be stored until
+ * necessary. It will remain in the floating point registers and not
+ * disturned until another floating point task is switched to.
+ *
+ * If FALSE, then the floating point context is saved when a floating
+ * point task is switched out and restored when the next floating point
+ * task is restored. The state of the floating point registers between
+ * those two operations is not specified.
+ *
+ * If the floating point context does NOT have to be saved as part of
+ * interrupt dispatching, then it should be safe to set this to TRUE.
+ *
+ * Setting this flag to TRUE results in using a different algorithm
+ * for deciding when to save and restore the floating point context.
+ * The deferred FP switch algorithm minimizes the number of times
+ * the FP context is saved and restored. The FP context is not saved
+ * until a context switch is made to another, different FP task.
+ * Thus in a system with only one FP task, the FP context will never
+ * be saved or restored.
+ */
+/*
+ * ACB Note: This could make debugging tricky..
+ */
+
+#define CPU_USE_DEFERRED_FP_SWITCH TRUE
+
+/*
+ * Does this port provide a CPU dependent IDLE task implementation?
+ *
+ * If TRUE, then the routine _CPU_Thread_Idle_body
+ * must be provided and is the default IDLE thread body instead of
+ * _CPU_Thread_Idle_body.
+ *
+ * If FALSE, then use the generic IDLE thread body if the BSP does
+ * not provide one.
+ *
+ * This is intended to allow for supporting processors which have
+ * a low power or idle mode. When the IDLE thread is executed, then
+ * the CPU can be powered down.
+ *
+ * The order of precedence for selecting the IDLE thread body is:
+ *
+ * 1. BSP provided
+ * 2. CPU dependent (if provided)
+ * 3. generic (if no BSP and no CPU dependent)
+ */
+
+#define CPU_PROVIDES_IDLE_THREAD_BODY FALSE
+
+/*
+ * Does the stack grow up (toward higher addresses) or down
+ * (toward lower addresses)?
+ *
+ * If TRUE, then the grows upward.
+ * If FALSE, then the grows toward smaller addresses.
+ */
+
+#define CPU_STACK_GROWS_UP FALSE
+
+/*
+ * The following is the variable attribute used to force alignment
+ * of critical RTEMS structures. On some processors it may make
+ * sense to have these aligned on tighter boundaries than
+ * the minimum requirements of the compiler in order to have as
+ * much of the critical data area as possible in a cache line.
+ *
+ * The placement of this macro in the declaration of the variables
+ * is based on the syntactically requirements of the GNU C
+ * "__attribute__" extension. For example with GNU C, use
+ * the following to force a structures to a 32 byte boundary.
+ *
+ * __attribute__ ((aligned (32)))
+ *
+ * NOTE: Currently only the Priority Bit Map table uses this feature.
+ * To benefit from using this, the data must be heavily
+ * used so it will stay in the cache and used frequently enough
+ * in the executive to justify turning this on.
+ */
+
+#define CPU_STRUCTURE_ALIGNMENT \
+ __attribute__ ((aligned (PPC_CACHE_ALIGNMENT)))
+
+/*
+ * Define what is required to specify how the network to host conversion
+ * routines are handled.
+ */
+
+#define CPU_HAS_OWN_HOST_TO_NETWORK_ROUTINES FALSE
+#define CPU_BIG_ENDIAN TRUE
+#define CPU_LITTLE_ENDIAN FALSE
+
+/*
+ * The following defines the number of bits actually used in the
+ * interrupt field of the task mode. How those bits map to the
+ * CPU interrupt levels is defined by the routine _CPU_ISR_Set_level().
+ *
+ * The interrupt level is bit mapped for the PowerPC family. The
+ * bits are set to 0 to indicate that a particular exception source
+ * enabled and 1 if it is disabled. This keeps with RTEMS convention
+ * that interrupt level 0 means all sources are enabled.
+ *
+ * The bits are assigned to correspond to enable bits in the MSR.
+ */
+
+#define PPC_INTERRUPT_LEVEL_ME 0x01
+#define PPC_INTERRUPT_LEVEL_EE 0x02
+#define PPC_INTERRUPT_LEVEL_CE 0x04
+
+/* XXX should these be maskable? */
+#if 0
+#define PPC_INTERRUPT_LEVEL_DE 0x08
+#define PPC_INTERRUPT_LEVEL_BE 0x10
+#define PPC_INTERRUPT_LEVEL_SE 0x20
+#endif
+
+#define CPU_MODES_INTERRUPT_MASK 0x00000007
+
+/*
+ * Processor defined structures
+ *
+ * Examples structures include the descriptor tables from the i386
+ * and the processor control structure on the i960ca.
+ */
+
+/* may need to put some structures here. */
+
+/*
+ * Contexts
+ *
+ * Generally there are 2 types of context to save.
+ * 1. Interrupt registers to save
+ * 2. Task level registers to save
+ *
+ * This means we have the following 3 context items:
+ * 1. task level context stuff:: Context_Control
+ * 2. floating point task stuff:: Context_Control_fp
+ * 3. special interrupt level context :: Context_Control_interrupt
+ *
+ * On some processors, it is cost-effective to save only the callee
+ * preserved registers during a task context switch. This means
+ * that the ISR code needs to save those registers which do not
+ * persist across function calls. It is not mandatory to make this
+ * distinctions between the caller/callee saves registers for the
+ * purpose of minimizing context saved during task switch and on interrupts.
+ * If the cost of saving extra registers is minimal, simplicity is the
+ * choice. Save the same context on interrupt entry as for tasks in
+ * this case.
+ *
+ * Additionally, if gdb is to be made aware of RTEMS tasks for this CPU, then
+ * care should be used in designing the context area.
+ *
+ * On some CPUs with hardware floating point support, the Context_Control_fp
+ * structure will not be used or it simply consist of an array of a
+ * fixed number of bytes. This is done when the floating point context
+ * is dumped by a "FP save context" type instruction and the format
+ * is not really defined by the CPU. In this case, there is no need
+ * to figure out the exact format -- only the size. Of course, although
+ * this is enough information for RTEMS, it is probably not enough for
+ * a debugger such as gdb. But that is another problem.
+ */
+
+typedef struct {
+ uint32_t gpr1; /* Stack pointer for all */
+ uint32_t gpr2; /* TOC in PowerOpen, reserved SVR4, section ptr EABI + */
+ uint32_t gpr13; /* First non volatile PowerOpen, section ptr SVR4/EABI */
+ uint32_t gpr14; /* Non volatile for all */
+ uint32_t gpr15; /* Non volatile for all */
+ uint32_t gpr16; /* Non volatile for all */
+ uint32_t gpr17; /* Non volatile for all */
+ uint32_t gpr18; /* Non volatile for all */
+ uint32_t gpr19; /* Non volatile for all */
+ uint32_t gpr20; /* Non volatile for all */
+ uint32_t gpr21; /* Non volatile for all */
+ uint32_t gpr22; /* Non volatile for all */
+ uint32_t gpr23; /* Non volatile for all */
+ uint32_t gpr24; /* Non volatile for all */
+ uint32_t gpr25; /* Non volatile for all */
+ uint32_t gpr26; /* Non volatile for all */
+ uint32_t gpr27; /* Non volatile for all */
+ uint32_t gpr28; /* Non volatile for all */
+ uint32_t gpr29; /* Non volatile for all */
+ uint32_t gpr30; /* Non volatile for all */
+ uint32_t gpr31; /* Non volatile for all */
+ uint32_t cr; /* PART of the CR is non volatile for all */
+ uint32_t pc; /* Program counter/Link register */
+ uint32_t msr; /* Initial interrupt level */
+} Context_Control;
+
+typedef struct {
+ /* The ABIs (PowerOpen/SVR4/EABI) only require saving f14-f31 over
+ * procedure calls. However, this would mean that the interrupt
+ * frame had to hold f0-f13, and the fpscr. And as the majority
+ * of tasks will not have an FP context, we will save the whole
+ * context here.
+ */
+#if (PPC_HAS_DOUBLE == 1)
+ double f[32];
+ double fpscr;
+#else
+ float f[32];
+ float fpscr;
+#endif
+} Context_Control_fp;
+
+typedef struct CPU_Interrupt_frame {
+ uint32_t stacklink; /* Ensure this is a real frame (also reg1 save) */
+#if (PPC_ABI == PPC_ABI_POWEROPEN || PPC_ABI == PPC_ABI_GCC27)
+ uint32_t dummy[13]; /* Used by callees: PowerOpen ABI */
+#else
+ uint32_t dummy[1]; /* Used by callees: SVR4/EABI */
+#endif
+ /* This is what is left out of the primary contexts */
+ uint32_t gpr0;
+ uint32_t gpr2; /* play safe */
+ uint32_t gpr3;
+ uint32_t gpr4;
+ uint32_t gpr5;
+ uint32_t gpr6;
+ uint32_t gpr7;
+ uint32_t gpr8;
+ uint32_t gpr9;
+ uint32_t gpr10;
+ uint32_t gpr11;
+ uint32_t gpr12;
+ uint32_t gpr13; /* Play safe */
+ uint32_t gpr28; /* For internal use by the IRQ handler */
+ uint32_t gpr29; /* For internal use by the IRQ handler */
+ uint32_t gpr30; /* For internal use by the IRQ handler */
+ uint32_t gpr31; /* For internal use by the IRQ handler */
+ uint32_t cr; /* Bits of this are volatile, so no-one may save */
+ uint32_t ctr;
+ uint32_t xer;
+ uint32_t lr;
+ uint32_t pc;
+ uint32_t msr;
+ uint32_t pad[3];
+} CPU_Interrupt_frame;
+
+
+/*
+ * The following table contains the information required to configure
+ * the PowerPC processor specific parameters.
+ */
+
+typedef struct {
+ void (*pretasking_hook)( void );
+ void (*predriver_hook)( void );
+ void (*postdriver_hook)( void );
+ void (*idle_task)( void );
+ boolean do_zero_of_workspace;
+ uint32_t idle_task_stack_size;
+ uint32_t interrupt_stack_size;
+ uint32_t extra_mpci_receive_server_stack;
+ void * (*stack_allocate_hook)( uint32_t );
+ void (*stack_free_hook)( void* );
+ /* end of fields required on all CPUs */
+
+ uint32_t clicks_per_usec; /* Timer clicks per microsecond */
+ void (*spurious_handler)(uint32_t vector, CPU_Interrupt_frame *);
+ boolean exceptions_in_RAM; /* TRUE if in RAM */
+
+#if (defined(ppc403) || defined(ppc405) || defined(mpc860) || defined(mpc821))
+ uint32_t serial_per_sec; /* Serial clocks per second */
+ boolean serial_external_clock;
+ boolean serial_xon_xoff;
+ boolean serial_cts_rts;
+ uint32_t serial_rate;
+ uint32_t timer_average_overhead; /* Average overhead of timer in ticks */
+ uint32_t timer_least_valid; /* Least valid number from timer */
+ boolean timer_internal_clock; /* TRUE, when timer runs with CPU clk */
+#endif
+
+#if (defined(mpc860) || defined(mpc821))
+ uint32_t clock_speed; /* Speed of CPU in Hz */
+#endif
+} rtems_cpu_table;
+
+/*
+ * Macros to access required entires in the CPU Table are in
+ * the file rtems/system.h.
+ */
+
+/*
+ * Macros to access PowerPC specific additions to the CPU Table
+ */
+
+#define rtems_cpu_configuration_get_clicks_per_usec() \
+ (_CPU_Table.clicks_per_usec)
+
+#define rtems_cpu_configuration_get_spurious_handler() \
+ (_CPU_Table.spurious_handler)
+
+#define rtems_cpu_configuration_get_exceptions_in_ram() \
+ (_CPU_Table.exceptions_in_RAM)
+
+#if (defined(ppc403) || defined(ppc405) || defined(mpc860) || defined(mpc821))
+
+#define rtems_cpu_configuration_get_serial_per_sec() \
+ (_CPU_Table.serial_per_sec)
+
+#define rtems_cpu_configuration_get_serial_external_clock() \
+ (_CPU_Table.serial_external_clock)
+
+#define rtems_cpu_configuration_get_serial_xon_xoff() \
+ (_CPU_Table.serial_xon_xoff)
+
+#define rtems_cpu_configuration_get_serial_cts_rts() \
+ (_CPU_Table.serial_cts_rts)
+
+#define rtems_cpu_configuration_get_serial_rate() \
+ (_CPU_Table.serial_rate)
+
+#define rtems_cpu_configuration_get_timer_average_overhead() \
+ (_CPU_Table.timer_average_overhead)
+
+#define rtems_cpu_configuration_get_timer_least_valid() \
+ (_CPU_Table.timer_least_valid)
+
+#define rtems_cpu_configuration_get_timer_internal_clock() \
+ (_CPU_Table.timer_internal_clock)
+
+#endif
+
+#if (defined(mpc860) || defined(mpc821))
+#define rtems_cpu_configuration_get_clock_speed() \
+ (_CPU_Table.clock_speed)
+#endif
+
+
+/*
+ * The following type defines an entry in the PPC's trap table.
+ *
+ * NOTE: The instructions chosen are RTEMS dependent although one is
+ * obligated to use two of the four instructions to perform a
+ * long jump. The other instructions load one register with the
+ * trap type (a.k.a. vector) and another with the psr.
+ */
+
+typedef struct {
+ uint32_t stwu_r1; /* stwu %r1, -(??+IP_END)(%1)*/
+ uint32_t stw_r0; /* stw %r0, IP_0(%r1) */
+ uint32_t li_r0_IRQ; /* li %r0, _IRQ */
+ uint32_t b_Handler; /* b PROC (_ISR_Handler) */
+} CPU_Trap_table_entry;
+
+/*
+ * This variable is optional. It is used on CPUs on which it is difficult
+ * to generate an "uninitialized" FP context. It is filled in by
+ * _CPU_Initialize and copied into the task's FP context area during
+ * _CPU_Context_Initialize.
+ */
+
+/* EXTERN Context_Control_fp _CPU_Null_fp_context; */
+
+/*
+ * On some CPUs, RTEMS supports a software managed interrupt stack.
+ * This stack is allocated by the Interrupt Manager and the switch
+ * is performed in _ISR_Handler. These variables contain pointers
+ * to the lowest and highest addresses in the chunk of memory allocated
+ * for the interrupt stack. Since it is unknown whether the stack
+ * grows up or down (in general), this give the CPU dependent
+ * code the option of picking the version it wants to use.
+ *
+ * NOTE: These two variables are required if the macro
+ * CPU_HAS_SOFTWARE_INTERRUPT_STACK is defined as TRUE.
+ */
+
+SCORE_EXTERN void *_CPU_Interrupt_stack_low;
+SCORE_EXTERN void *_CPU_Interrupt_stack_high;
+
+/*
+ * With some compilation systems, it is difficult if not impossible to
+ * call a high-level language routine from assembly language. This
+ * is especially true of commercial Ada compilers and name mangling
+ * C++ ones. This variable can be optionally defined by the CPU porter
+ * and contains the address of the routine _Thread_Dispatch. This
+ * can make it easier to invoke that routine at the end of the interrupt
+ * sequence (if a dispatch is necessary).
+ */
+
+/* EXTERN void (*_CPU_Thread_dispatch_pointer)(); */
+
+/*
+ * Nothing prevents the porter from declaring more CPU specific variables.
+ */
+
+
+SCORE_EXTERN struct {
+ uint32_t volatile* Nest_level;
+ uint32_t volatile* Disable_level;
+ void *Vector_table;
+ void *Stack;
+#if (PPC_ABI == PPC_ABI_POWEROPEN)
+ uint32_t Dispatch_r2;
+#else
+ uint32_t Default_r2;
+#if (PPC_ABI != PPC_ABI_GCC27)
+ uint32_t Default_r13;
+#endif
+#endif
+ volatile boolean *Switch_necessary;
+ boolean *Signal;
+
+ uint32_t msr_initial;
+} _CPU_IRQ_info CPU_STRUCTURE_ALIGNMENT;
+
+/*
+ * The size of the floating point context area. On some CPUs this
+ * will not be a "sizeof" because the format of the floating point
+ * area is not defined -- only the size is. This is usually on
+ * CPUs with a "floating point save context" instruction.
+ */
+
+#define CPU_CONTEXT_FP_SIZE sizeof( Context_Control_fp )
+
+/*
+ * (Optional) # of bytes for libmisc/stackchk to check
+ * If not specifed, then it defaults to something reasonable
+ * for most architectures.
+ */
+
+#define CPU_STACK_CHECK_SIZE (128)
+
+/*
+ * Amount of extra stack (above minimum stack size) required by
+ * MPCI receive server thread. Remember that in a multiprocessor
+ * system this thread must exist and be able to process all directives.
+ */
+
+#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 0
+
+/*
+ * This defines the number of entries in the ISR_Vector_table managed
+ * by RTEMS.
+ */
+
+#define CPU_INTERRUPT_NUMBER_OF_VECTORS (PPC_INTERRUPT_MAX)
+#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (PPC_INTERRUPT_MAX - 1)
+
+/*
+ * This is defined if the port has a special way to report the ISR nesting
+ * level. Most ports maintain the variable _ISR_Nest_level.
+ */
+
+#define CPU_PROVIDES_ISR_IS_IN_PROGRESS TRUE
+
+/*
+ * Should be large enough to run all RTEMS tests. This insures
+ * that a "reasonable" small application should not have any problems.
+ */
+
+#define CPU_STACK_MINIMUM_SIZE (1024*8)
+
+/*
+ * CPU's worst alignment requirement for data types on a byte boundary. This
+ * alignment does not take into account the requirements for the stack.
+ */
+
+#define CPU_ALIGNMENT (PPC_ALIGNMENT)
+
+/*
+ * This number corresponds to the byte alignment requirement for the
+ * heap handler. This alignment requirement may be stricter than that
+ * for the data types alignment specified by CPU_ALIGNMENT. It is
+ * common for the heap to follow the same alignment requirement as
+ * CPU_ALIGNMENT. If the CPU_ALIGNMENT is strict enough for the heap,
+ * then this should be set to CPU_ALIGNMENT.
+ *
+ * NOTE: This does not have to be a power of 2. It does have to
+ * be greater or equal to than CPU_ALIGNMENT.
+ */
+
+#define CPU_HEAP_ALIGNMENT (PPC_ALIGNMENT)
+
+/*
+ * This number corresponds to the byte alignment requirement for memory
+ * buffers allocated by the partition manager. This alignment requirement
+ * may be stricter than that for the data types alignment specified by
+ * CPU_ALIGNMENT. It is common for the partition to follow the same
+ * alignment requirement as CPU_ALIGNMENT. If the CPU_ALIGNMENT is strict
+ * enough for the partition, then this should be set to CPU_ALIGNMENT.
+ *
+ * NOTE: This does not have to be a power of 2. It does have to
+ * be greater or equal to than CPU_ALIGNMENT.
+ */
+
+#define CPU_PARTITION_ALIGNMENT (PPC_ALIGNMENT)
+
+/*
+ * This number corresponds to the byte alignment requirement for the
+ * stack. This alignment requirement may be stricter than that for the
+ * data types alignment specified by CPU_ALIGNMENT. If the CPU_ALIGNMENT
+ * is strict enough for the stack, then this should be set to 0.
+ *
+ * NOTE: This must be a power of 2 either 0 or greater than CPU_ALIGNMENT.
+ */
+
+#define CPU_STACK_ALIGNMENT (PPC_STACK_ALIGNMENT)
+
+/*
+ * ISR handler macros
+ */
+
+void _CPU_Initialize_vectors(void);
+
+/*
+ * Disable all interrupts for an RTEMS critical section. The previous
+ * level is returned in _isr_cookie.
+ */
+
+#define _CPU_MSR_Value( _msr_value ) \
+ do { \
+ _msr_value = 0; \
+ asm volatile ("mfmsr %0" : "=&r" ((_msr_value)) : "0" ((_msr_value))); \
+ } while (0)
+
+#define _CPU_MSR_SET( _msr_value ) \
+{ asm volatile ("mtmsr %0" : "=&r" ((_msr_value)) : "0" ((_msr_value))); }
+
+#if 0
+#define _CPU_ISR_Disable( _isr_cookie ) \
+ { register unsigned int _disable_mask = PPC_MSR_DISABLE_MASK; \
+ _isr_cookie = 0; \
+ asm volatile (
+ "mfmsr %0" : \
+ "=r" ((_isr_cookie)) : \
+ "0" ((_isr_cookie)) \
+ ); \
+ asm volatile (
+ "andc %1,%0,%1" : \
+ "=r" ((_isr_cookie)), "=&r" ((_disable_mask)) : \
+ "0" ((_isr_cookie)), "1" ((_disable_mask)) \
+ ); \
+ asm volatile (
+ "mtmsr %1" : \
+ "=r" ((_disable_mask)) : \
+ "0" ((_disable_mask)) \
+ ); \
+ }
+#endif
+
+#define _CPU_ISR_Disable( _isr_cookie ) \
+ { register unsigned int _disable_mask = PPC_MSR_DISABLE_MASK; \
+ _isr_cookie = 0; \
+ asm volatile ( \
+ "mfmsr %0; andc %1,%0,%1; mtmsr %1" : \
+ "=&r" ((_isr_cookie)), "=&r" ((_disable_mask)) : \
+ "0" ((_isr_cookie)), "1" ((_disable_mask)) \
+ ); \
+ }
+
+/*
+ * Enable interrupts to the previous level (returned by _CPU_ISR_Disable).
+ * This indicates the end of an RTEMS critical section. The parameter
+ * _isr_cookie is not modified.
+ */
+
+#define _CPU_ISR_Enable( _isr_cookie ) \
+ { \
+ asm volatile ( "mtmsr %0" : \
+ "=r" ((_isr_cookie)) : \
+ "0" ((_isr_cookie))); \
+ }
+
+/*
+ * This temporarily restores the interrupt to _isr_cookie before immediately
+ * disabling them again. This is used to divide long RTEMS critical
+ * sections into two or more parts. The parameter _isr_cookie is not
+ * modified.
+ *
+ * NOTE: The version being used is not very optimized but it does
+ * not trip a problem in gcc where the disable mask does not
+ * get loaded. Check this for future (post 10/97 gcc versions.
+ */
+
+#define _CPU_ISR_Flash( _isr_cookie ) \
+ { register unsigned int _disable_mask = PPC_MSR_DISABLE_MASK; \
+ asm volatile ( \
+ "mtmsr %0; andc %1,%0,%1; mtmsr %1" : \
+ "=r" ((_isr_cookie)), "=r" ((_disable_mask)) : \
+ "0" ((_isr_cookie)), "1" ((_disable_mask)) \
+ ); \
+ }
+
+/*
+ * Map interrupt level in task mode onto the hardware that the CPU
+ * actually provides. Currently, interrupt levels which do not
+ * map onto the CPU in a generic fashion are undefined. Someday,
+ * it would be nice if these were "mapped" by the application
+ * via a callout. For example, m68k has 8 levels 0 - 7, levels
+ * 8 - 255 would be available for bsp/application specific meaning.
+ * This could be used to manage a programmable interrupt controller
+ * via the rtems_task_mode directive.
+ */
+
+uint32_t _CPU_ISR_Calculate_level(
+ uint32_t new_level
+);
+
+void _CPU_ISR_Set_level(
+ uint32_t new_level
+);
+
+uint32_t _CPU_ISR_Get_level( void );
+
+void _CPU_ISR_install_raw_handler(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+);
+
+/* end of ISR handler macros */
+
+/*
+ * Simple spin delay in microsecond units for device drivers.
+ * This is very dependent on the clock speed of the target.
+ */
+
+#define CPU_Get_timebase_low( _value ) \
+ asm volatile( "mftb %0" : "=r" (_value) )
+
+#define rtems_bsp_delay( _microseconds ) \
+ do { \
+ uint32_t start, ticks, now; \
+ CPU_Get_timebase_low( start ) ; \
+ ticks = (_microseconds) * _CPU_Table.clicks_per_usec; \
+ do \
+ CPU_Get_timebase_low( now ) ; \
+ while (now - start < ticks); \
+ } while (0)
+
+#define rtems_bsp_delay_in_bus_cycles( _cycles ) \
+ do { \
+ uint32_t start, now; \
+ CPU_Get_timebase_low( start ); \
+ do \
+ CPU_Get_timebase_low( now ); \
+ while (now - start < (_cycles)); \
+ } while (0)
+
+
+
+/* Context handler macros */
+
+/*
+ * Initialize the context to a state suitable for starting a
+ * task after a context restore operation. Generally, this
+ * involves:
+ *
+ * - setting a starting address
+ * - preparing the stack
+ * - preparing the stack and frame pointers
+ * - setting the proper interrupt level in the context
+ * - initializing the floating point context
+ *
+ * This routine generally does not set any unnecessary register
+ * in the context. The state of the "general data" registers is
+ * undefined at task start time.
+ *
+ * NOTE: Implemented as a subroutine for the SPARC port.
+ */
+
+void _CPU_Context_Initialize(
+ Context_Control *the_context,
+ uint32_t *stack_base,
+ uint32_t size,
+ uint32_t new_level,
+ void *entry_point,
+ boolean is_fp
+);
+
+/*
+ * This routine is responsible for somehow restarting the currently
+ * executing task. If you are lucky, then all that is necessary
+ * is restoring the context. Otherwise, there will need to be
+ * a special assembly routine which does something special in this
+ * case. Context_Restore should work most of the time. It will
+ * not work if restarting self conflicts with the stack frame
+ * assumptions of restoring a context.
+ */
+
+#define _CPU_Context_Restart_self( _the_context ) \
+ _CPU_Context_restore( (_the_context) );
+
+/*
+ * The purpose of this macro is to allow the initial pointer into
+ * a floating point context area (used to save the floating point
+ * context) to be at an arbitrary place in the floating point
+ * context area.
+ *
+ * This is necessary because some FP units are designed to have
+ * their context saved as a stack which grows into lower addresses.
+ * Other FP units can be saved by simply moving registers into offsets
+ * from the base of the context area. Finally some FP units provide
+ * a "dump context" instruction which could fill in from high to low
+ * or low to high based on the whim of the CPU designers.
+ */
+
+#define _CPU_Context_Fp_start( _base, _offset ) \
+ ( (void *) _Addresses_Add_offset( (_base), (_offset) ) )
+
+/*
+ * This routine initializes the FP context area passed to it to.
+ * There are a few standard ways in which to initialize the
+ * floating point context. The code included for this macro assumes
+ * that this is a CPU in which a "initial" FP context was saved into
+ * _CPU_Null_fp_context and it simply copies it to the destination
+ * context passed to it.
+ *
+ * Other models include (1) not doing anything, and (2) putting
+ * a "null FP status word" in the correct place in the FP context.
+ */
+
+#define _CPU_Context_Initialize_fp( _destination ) \
+ { \
+ ((Context_Control_fp *) *((void **) _destination))->fpscr = PPC_INIT_FPSCR; \
+ }
+
+/* end of Context handler macros */
+
+/* Fatal Error manager macros */
+
+/*
+ * This routine copies _error into a known place -- typically a stack
+ * location or a register, optionally disables interrupts, and
+ * halts/stops the CPU.
+ */
+
+#define _CPU_Fatal_halt( _error ) \
+ _CPU_Fatal_error(_error)
+
+/* end of Fatal Error manager macros */
+
+/* Bitfield handler macros */
+
+/*
+ * This routine sets _output to the bit number of the first bit
+ * set in _value. _value is of CPU dependent type Priority_Bit_map_control.
+ * This type may be either 16 or 32 bits wide although only the 16
+ * least significant bits will be used.
+ *
+ * There are a number of variables in using a "find first bit" type
+ * instruction.
+ *
+ * (1) What happens when run on a value of zero?
+ * (2) Bits may be numbered from MSB to LSB or vice-versa.
+ * (3) The numbering may be zero or one based.
+ * (4) The "find first bit" instruction may search from MSB or LSB.
+ *
+ * RTEMS guarantees that (1) will never happen so it is not a concern.
+ * (2),(3), (4) are handled by the macros _CPU_Priority_mask() and
+ * _CPU_Priority_Bits_index(). These three form a set of routines
+ * which must logically operate together. Bits in the _value are
+ * set and cleared based on masks built by _CPU_Priority_mask().
+ * The basic major and minor values calculated by _Priority_Major()
+ * and _Priority_Minor() are "massaged" by _CPU_Priority_Bits_index()
+ * to properly range between the values returned by the "find first bit"
+ * instruction. This makes it possible for _Priority_Get_highest() to
+ * calculate the major and directly index into the minor table.
+ * This mapping is necessary to ensure that 0 (a high priority major/minor)
+ * is the first bit found.
+ *
+ * This entire "find first bit" and mapping process depends heavily
+ * on the manner in which a priority is broken into a major and minor
+ * components with the major being the 4 MSB of a priority and minor
+ * the 4 LSB. Thus (0 << 4) + 0 corresponds to priority 0 -- the highest
+ * priority. And (15 << 4) + 14 corresponds to priority 254 -- the next
+ * to the lowest priority.
+ *
+ * If your CPU does not have a "find first bit" instruction, then
+ * there are ways to make do without it. Here are a handful of ways
+ * to implement this in software:
+ *
+ * - a series of 16 bit test instructions
+ * - a "binary search using if's"
+ * - _number = 0
+ * if _value > 0x00ff
+ * _value >>=8
+ * _number = 8;
+ *
+ * if _value > 0x0000f
+ * _value >=8
+ * _number += 4
+ *
+ * _number += bit_set_table[ _value ]
+ *
+ * where bit_set_table[ 16 ] has values which indicate the first
+ * bit set
+ */
+
+#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
+ { \
+ asm volatile ("cntlzw %0, %1" : "=r" ((_output)), "=r" ((_value)) : \
+ "1" ((_value))); \
+ }
+
+/* end of Bitfield handler macros */
+
+/*
+ * This routine builds the mask which corresponds to the bit fields
+ * as searched by _CPU_Bitfield_Find_first_bit(). See the discussion
+ * for that routine.
+ */
+
+#define _CPU_Priority_Mask( _bit_number ) \
+ ( 0x80000000 >> (_bit_number) )
+
+/*
+ * This routine translates the bit numbers returned by
+ * _CPU_Bitfield_Find_first_bit() into something suitable for use as
+ * a major or minor component of a priority. See the discussion
+ * for that routine.
+ */
+
+#define _CPU_Priority_bits_index( _priority ) \
+ (_priority)
+
+/* end of Priority handler macros */
+
+/* variables */
+
+extern const uint32_t _CPU_msrs[4];
+
+/* functions */
+
+/*
+ * _CPU_Initialize
+ *
+ * This routine performs CPU dependent initialization.
+ */
+
+void _CPU_Initialize(
+ rtems_cpu_table *cpu_table,
+ void (*thread_dispatch)
+);
+
+/*
+ * _CPU_ISR_install_vector
+ *
+ * This routine installs an interrupt vector.
+ */
+
+void _CPU_ISR_install_vector(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+);
+
+/*
+ * _CPU_Install_interrupt_stack
+ *
+ * This routine installs the hardware interrupt stack pointer.
+ *
+ * NOTE: It need only be provided if CPU_HAS_HARDWARE_INTERRUPT_STACK
+ * is TRUE.
+ */
+
+void _CPU_Install_interrupt_stack( void );
+
+/*
+ * _CPU_Context_switch
+ *
+ * This routine switches from the run context to the heir context.
+ */
+
+void _CPU_Context_switch(
+ Context_Control *run,
+ Context_Control *heir
+);
+
+/*
+ * _CPU_Context_restore
+ *
+ * This routine is generallu used only to restart self in an
+ * efficient manner. It may simply be a label in _CPU_Context_switch.
+ *
+ * NOTE: May be unnecessary to reload some registers.
+ */
+
+void _CPU_Context_restore(
+ Context_Control *new_context
+);
+
+/*
+ * _CPU_Context_save_fp
+ *
+ * This routine saves the floating point context passed to it.
+ */
+
+void _CPU_Context_save_fp(
+ void **fp_context_ptr
+);
+
+/*
+ * _CPU_Context_restore_fp
+ *
+ * This routine restores the floating point context passed to it.
+ */
+
+void _CPU_Context_restore_fp(
+ void **fp_context_ptr
+);
+
+void _CPU_Fatal_error(
+ uint32_t _error
+);
+
+/* The following routine swaps the endian format of an unsigned int.
+ * It must be static because it is referenced indirectly.
+ *
+ * This version will work on any processor, but if there is a better
+ * way for your CPU PLEASE use it. The most common way to do this is to:
+ *
+ * swap least significant two bytes with 16-bit rotate
+ * swap upper and lower 16-bits
+ * swap most significant two bytes with 16-bit rotate
+ *
+ * Some CPUs have special instructions which swap a 32-bit quantity in
+ * a single instruction (e.g. i486). It is probably best to avoid
+ * an "endian swapping control bit" in the CPU. One good reason is
+ * that interrupts would probably have to be disabled to insure that
+ * an interrupt does not try to access the same "chunk" with the wrong
+ * endian. Another good reason is that on some CPUs, the endian bit
+ * endianness for ALL fetches -- both code and data -- so the code
+ * will be fetched incorrectly.
+ */
+
+static inline unsigned int CPU_swap_u32(
+ unsigned int value
+)
+{
+ uint32_t swapped;
+
+ asm volatile("rlwimi %0,%1,8,24,31;"
+ "rlwimi %0,%1,24,16,23;"
+ "rlwimi %0,%1,8,8,15;"
+ "rlwimi %0,%1,24,0,7;" :
+ "=&r" ((swapped)) : "r" ((value)));
+
+ return( swapped );
+}
+
+#define CPU_swap_u16( value ) \
+ (((value&0xff) << 8) | ((value >> 8)&0xff))
+
+/*
+ * Routines to access the decrementer register
+ */
+
+#define PPC_Set_decrementer( _clicks ) \
+ do { \
+ asm volatile( "mtdec %0" : "=r" ((_clicks)) : "r" ((_clicks)) ); \
+ } while (0)
+
+/*
+ * Routines to access the time base register
+ */
+
+static inline uint64_t PPC_Get_timebase_register( void )
+{
+ uint32_t tbr_low;
+ uint32_t tbr_high;
+ uint32_t tbr_high_old;
+ uint64_t tbr;
+
+ do {
+ asm volatile( "mftbu %0" : "=r" (tbr_high_old));
+ asm volatile( "mftb %0" : "=r" (tbr_low));
+ asm volatile( "mftbu %0" : "=r" (tbr_high));
+ } while ( tbr_high_old != tbr_high );
+
+ tbr = tbr_high;
+ tbr <<= 32;
+ tbr |= tbr_low;
+ return tbr;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/score/cpu/powerpc/rtems/powerpc/registers.h b/cpukit/score/cpu/powerpc/rtems/powerpc/registers.h
new file mode 100644
index 0000000000..b3afabe504
--- /dev/null
+++ b/cpukit/score/cpu/powerpc/rtems/powerpc/registers.h
@@ -0,0 +1,310 @@
+/*
+ * This file contains some powerpc MSR and registers access definitions.
+ *
+ * Copyright (C) 1999 Eric Valette (valette@crf.canon.fr)
+ * Canon Centre Recherche France.
+ *
+ * Added MPC8260 Andy Dachs <a.dachs@sstl.co.uk>
+ * Surrey Satellite Technology Limited
+ *
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __rtems_powerpc_registers_h
+#define __rtems_powerpc_registers_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Bit encodings for Machine State Register (MSR) */
+#define MSR_POW (1<<18) /* Enable Power Management */
+#define MSR_TGPR (1<<17) /* TLB Update registers in use */
+#define MSR_ILE (1<<16) /* Interrupt Little-Endian enable */
+#define MSR_EE (1<<15) /* External Interrupt enable */
+#define MSR_PR (1<<14) /* Supervisor/User privilege */
+#define MSR_FP (1<<13) /* Floating Point enable */
+#define MSR_ME (1<<12) /* Machine Check enable */
+#define MSR_FE0 (1<<11) /* Floating Exception mode 0 */
+#define MSR_SE (1<<10) /* Single Step */
+#define MSR_BE (1<<9) /* Branch Trace */
+#define MSR_FE1 (1<<8) /* Floating Exception mode 1 */
+#define MSR_IP (1<<6) /* Exception prefix 0x000/0xFFF */
+#define MSR_IR (1<<5) /* Instruction MMU enable */
+#define MSR_DR (1<<4) /* Data MMU enable */
+#define MSR_RI (1<<1) /* Recoverable Exception */
+#define MSR_LE (1<<0) /* Little-Endian enable */
+
+#define MSR_ MSR_ME|MSR_RI
+#define MSR_KERNEL MSR_|MSR_IR|MSR_DR
+#define MSR_USER MSR_KERNEL|MSR_PR|MSR_EE
+
+/* Bit encodings for Hardware Implementation Register (HID0)
+ on PowerPC 603, 604, etc. processors (not 601). */
+#define HID0_EMCP (1<<31) /* Enable Machine Check pin */
+#define HID0_EBA (1<<29) /* Enable Bus Address Parity */
+#define HID0_EBD (1<<28) /* Enable Bus Data Parity */
+#define HID0_SBCLK (1<<27)
+#define HID0_EICE (1<<26)
+#define HID0_ECLK (1<<25)
+#define HID0_PAR (1<<24)
+#define HID0_DOZE (1<<23)
+#define HID0_NAP (1<<22)
+#define HID0_SLEEP (1<<21)
+#define HID0_DPM (1<<20)
+#define HID0_ICE (1<<15) /* Instruction Cache Enable */
+#define HID0_DCE (1<<14) /* Data Cache Enable */
+#define HID0_ILOCK (1<<13) /* Instruction Cache Lock */
+#define HID0_DLOCK (1<<12) /* Data Cache Lock */
+#define HID0_ICFI (1<<11) /* Instruction Cache Flash Invalidate */
+#define HID0_DCI (1<<10) /* Data Cache Invalidate */
+#define HID0_SIED (1<<7) /* Serial Instruction Execution [Disable] */
+#define HID0_BTIC (1<<5) /* Branch Target Instruction Cache [Enable] */
+#define HID0_BHTE (1<<2) /* Branch History Table Enable */
+#define HID0_BTCD (1<<1) /* Branch target cache disable */
+
+/* fpscr settings */
+#define FPSCR_FX (1<<31)
+#define FPSCR_FEX (1<<30)
+
+#define _MACH_prep 1
+#define _MACH_Pmac 2 /* pmac or pmac clone (non-chrp) */
+#define _MACH_chrp 4 /* chrp machine */
+#define _MACH_mbx 8 /* Motorola MBX board */
+#define _MACH_apus 16 /* amiga with phase5 powerup */
+#define _MACH_fads 32 /* Motorola FADS board */
+
+/* see residual.h for these */
+#define _PREP_Motorola 0x01 /* motorola prep */
+#define _PREP_Firm 0x02 /* firmworks prep */
+#define _PREP_IBM 0x00 /* ibm prep */
+#define _PREP_Bull 0x03 /* bull prep */
+
+/* these are arbitrary */
+#define _CHRP_Motorola 0x04 /* motorola chrp, the cobra */
+#define _CHRP_IBM 0x05 /* IBM chrp, the longtrail and longtrail 2 */
+
+#define _GLOBAL(n)\
+ .globl n;\
+n:
+
+#define TBRU 269 /* Time base Upper/Lower (Reading) */
+#define TBRL 268
+#define TBWU 284 /* Time base Upper/Lower (Writing) */
+#define TBWL 285
+#define XER 1
+#define LR 8
+#define CTR 9
+#define HID0 1008 /* Hardware Implementation */
+#define HID1 1009 /* Hardware Implementation */
+#define DABR 1013 /* Data Access Breakpoint */
+#define PVR 287 /* Processor Version */
+#define IBAT0U 528 /* Instruction BAT #0 Upper/Lower */
+#define IBAT0L 529
+#define IBAT1U 530 /* Instruction BAT #1 Upper/Lower */
+#define IBAT1L 531
+#define IBAT2U 532 /* Instruction BAT #2 Upper/Lower */
+#define IBAT2L 533
+#define IBAT3U 534 /* Instruction BAT #3 Upper/Lower */
+#define IBAT3L 535
+#define DBAT0U 536 /* Data BAT #0 Upper/Lower */
+#define DBAT0L 537
+#define DBAT1U 538 /* Data BAT #1 Upper/Lower */
+#define DBAT1L 539
+#define DBAT2U 540 /* Data BAT #2 Upper/Lower */
+#define DBAT2L 541
+#define DBAT3U 542 /* Data BAT #3 Upper/Lower */
+#define DBAT3L 543
+#define DMISS 976 /* TLB Lookup/Refresh registers */
+#define DCMP 977
+#define HASH1 978
+#define HASH2 979
+#define IMISS 980
+#define ICMP 981
+#define RPA 982
+#define SDR1 25 /* MMU hash base register */
+#define DAR 19 /* Data Address Register */
+#define SPR0 272 /* Supervisor Private Registers */
+#define SPRG0 272
+#define SPR1 273
+#define SPRG1 273
+#define SPR2 274
+#define SPRG2 274
+#define SPR3 275
+#define SPRG3 275
+#define DSISR 18
+#define SRR0 26 /* Saved Registers (exception) */
+#define SRR1 27
+#define IABR 1010 /* Instruction Address Breakpoint */
+#define DEC 22 /* Decrementer */
+#define EAR 282 /* External Address Register */
+#define L2CR 1017 /* PPC 750 L2 control register */
+
+#define THRM1 1020
+#define THRM2 1021
+#define THRM3 1022
+#define THRM1_TIN (1<<(31-0))
+#define THRM1_TIV (1<<(31-1))
+#define THRM1_THRES (0x7f<<(31-8))
+#define THRM1_TID (1<<(31-29))
+#define THRM1_TIE (1<<(31-30))
+#define THRM1_V (1<<(31-31))
+#define THRM3_SITV (0x1fff << (31-30))
+#define THRM3_E (1<<(31-31))
+
+/* Segment Registers */
+#define SR0 0
+#define SR1 1
+#define SR2 2
+#define SR3 3
+#define SR4 4
+#define SR5 5
+#define SR6 6
+#define SR7 7
+#define SR8 8
+#define SR9 9
+#define SR10 10
+#define SR11 11
+#define SR12 12
+#define SR13 13
+#define SR14 14
+#define SR15 15
+
+#ifndef ASM
+/*
+ * Routines to access the time base register
+ */
+
+static inline unsigned long long PPC_Get_timebase_register( void )
+{
+ unsigned long tbr_low;
+ unsigned long tbr_high;
+ unsigned long tbr_high_old;
+ unsigned long long tbr;
+
+ do {
+ asm volatile( "mftbu %0" : "=r" (tbr_high_old));
+ asm volatile( "mftb %0" : "=r" (tbr_low));
+ asm volatile( "mftbu %0" : "=r" (tbr_high));
+ } while ( tbr_high_old != tbr_high );
+
+ tbr = tbr_high;
+ tbr <<= 32;
+ tbr |= tbr_low;
+ return tbr;
+}
+
+static inline void PPC_Set_timebase_register (unsigned long long tbr)
+{
+ unsigned long tbr_low;
+ unsigned long tbr_high;
+
+ tbr_low = (tbr & 0xffffffff) ;
+ tbr_high = (tbr >> 32) & 0xffffffff;
+ asm volatile( "mtspr 284, %0" : : "r" (tbr_low));
+ asm volatile( "mtspr 285, %0" : : "r" (tbr_high));
+
+}
+#endif
+
+#define _CPU_MSR_GET( _msr_value ) \
+ do { \
+ _msr_value = 0; \
+ asm volatile ("mfmsr %0" : "=&r" ((_msr_value)) : "0" ((_msr_value))); \
+ } while (0)
+
+#define _CPU_MSR_SET( _msr_value ) \
+{ asm volatile ("mtmsr %0" : "=&r" ((_msr_value)) : "0" ((_msr_value))); }
+
+#define _CPU_ISR_Disable( _isr_cookie ) \
+ { register unsigned int _disable_mask = MSR_EE; \
+ _isr_cookie = 0; \
+ asm volatile ( \
+ "mfmsr %0; andc %1,%0,%1; mtmsr %1" : \
+ "=&r" ((_isr_cookie)), "=&r" ((_disable_mask)) : \
+ "0" ((_isr_cookie)), "1" ((_disable_mask)) \
+ ); \
+ }
+
+
+/*
+ * Enable interrupts to the previous level (returned by _CPU_ISR_Disable).
+ * This indicates the end of an RTEMS critical section. The parameter
+ * _isr_cookie is not modified.
+ */
+
+#define _CPU_ISR_Enable( _isr_cookie ) \
+ { \
+ asm volatile ( "mtmsr %0" : \
+ "=r" ((_isr_cookie)) : \
+ "0" ((_isr_cookie))); \
+ }
+
+/*
+ * This temporarily restores the interrupt to _isr_cookie before immediately
+ * disabling them again. This is used to divide long RTEMS critical
+ * sections into two or more parts. The parameter _isr_cookie is not
+ * modified.
+ *
+ * NOTE: The version being used is not very optimized but it does
+ * not trip a problem in gcc where the disable mask does not
+ * get loaded. Check this for future (post 10/97 gcc versions.
+ */
+
+#define _CPU_ISR_Flash( _isr_cookie ) \
+ { register unsigned int _disable_mask = MSR_EE; \
+ asm volatile ( \
+ "mtmsr %0; andc %1,%0,%1; mtmsr %1" : \
+ "=r" ((_isr_cookie)), "=r" ((_disable_mask)) : \
+ "0" ((_isr_cookie)), "1" ((_disable_mask)) \
+ ); \
+ }
+
+
+/* end of ISR handler macros */
+
+/*
+ * Simple spin delay in microsecond units for device drivers.
+ * This is very dependent on the clock speed of the target.
+ */
+
+#define CPU_Get_timebase_low( _value ) \
+ asm volatile( "mftb %0" : "=r" (_value) )
+
+#define rtems_bsp_delay( _microseconds ) \
+ do { \
+ uint32_t start, ticks, now; \
+ CPU_Get_timebase_low( start ) ; \
+ ticks = (_microseconds) * rtems_cpu_configuration_get_clicks_per_usec(); \
+ do \
+ CPU_Get_timebase_low( now ) ; \
+ while (now - start < ticks); \
+ } while (0)
+
+#define rtems_bsp_delay_in_bus_cycles( _cycles ) \
+ do { \
+ uint32_t start, now; \
+ CPU_Get_timebase_low( start ); \
+ do \
+ CPU_Get_timebase_low( now ); \
+ while (now - start < (_cycles)); \
+ } while (0)
+
+#define PPC_Set_decrementer( _clicks ) \
+ do { \
+ asm volatile( "mtdec %0" : : "r" ((_clicks)) ); \
+ } while (0)
+
+#define PPC_Get_decrementer( _clicks ) \
+ asm volatile( "mfdec %0" : "=r" (_clicks) )
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __rtems_powerpc_registers_h */
diff --git a/cpukit/score/cpu/powerpc/rtems/score/cpu.h b/cpukit/score/cpu/powerpc/rtems/score/cpu.h
new file mode 100644
index 0000000000..2d35a82f4c
--- /dev/null
+++ b/cpukit/score/cpu/powerpc/rtems/score/cpu.h
@@ -0,0 +1,60 @@
+/*
+ * $Id$
+ */
+
+#ifndef _rtems_score_cpu_h
+#define _rtems_score_cpu_h
+
+#include <rtems/score/powerpc.h> /* pick up machine definitions */
+#ifndef ASM
+#include <rtems/score/types.h>
+#endif
+
+/* conditional compilation parameters */
+
+/*
+ * Should the calls to _Thread_Enable_dispatch be inlined?
+ *
+ * If TRUE, then they are inlined.
+ * If FALSE, then a subroutine call is made.
+ *
+ * Basically this is an example of the classic trade-off of size
+ * versus speed. Inlining the call (TRUE) typically increases the
+ * size of RTEMS while speeding up the enabling of dispatching.
+ * [NOTE: In general, the _Thread_Dispatch_disable_level will
+ * only be 0 or 1 unless you are in an interrupt handler and that
+ * interrupt handler invokes the executive.] When not inlined
+ * something calls _Thread_Enable_dispatch which in turns calls
+ * _Thread_Dispatch. If the enable dispatch is inlined, then
+ * one subroutine call is avoided entirely.]
+ */
+
+#define CPU_INLINE_ENABLE_DISPATCH FALSE
+
+/*
+ * Should the body of the search loops in _Thread_queue_Enqueue_priority
+ * be unrolled one time? In unrolled each iteration of the loop examines
+ * two "nodes" on the chain being searched. Otherwise, only one node
+ * is examined per iteration.
+ *
+ * If TRUE, then the loops are unrolled.
+ * If FALSE, then the loops are not unrolled.
+ *
+ * The primary factor in making this decision is the cost of disabling
+ * and enabling interrupts (_ISR_Flash) versus the cost of rest of the
+ * body of the loop. On some CPUs, the flash is more expensive than
+ * one iteration of the loop body. In this case, it might be desirable
+ * to unroll the loop. It is important to note that on some CPUs, this
+ * code is the longest interrupt disable period in RTEMS. So it is
+ * necessary to strike a balance when setting this parameter.
+ */
+
+#define CPU_UNROLL_ENQUEUE_PRIORITY FALSE
+
+#ifdef _OLD_EXCEPTIONS
+#include <rtems/old-exceptions/cpu.h>
+#else
+#include <rtems/new-exceptions/cpu.h>
+#endif
+
+#endif
diff --git a/cpukit/score/cpu/powerpc/rtems/score/powerpc.h b/cpukit/score/cpu/powerpc/rtems/score/powerpc.h
new file mode 100644
index 0000000000..061772b656
--- /dev/null
+++ b/cpukit/score/cpu/powerpc/rtems/score/powerpc.h
@@ -0,0 +1,744 @@
+/* powerpc.h
+ *
+ * This file contains definitions for the IBM/Motorola PowerPC
+ * family members.
+ *
+ * Author: Andrew Bray <andy@i-cubed.co.uk>
+ *
+ * COPYRIGHT (c) 1995 by i-cubed ltd.
+ *
+ * MPC860 support code was added by Jay Monkman <jmonkman@frasca.com>
+ * MPC8260 support added by Andy Dachs <a.dachs@sstl.co.uk>
+ * Surrey Satellite Technology Limited
+ *
+ * To anyone who acknowledges that this file is provided "AS IS"
+ * without any express or implied warranty:
+ * permission to use, copy, modify, and distribute this file
+ * for any purpose is hereby granted without fee, provided that
+ * the above copyright notice and this notice appears in all
+ * copies, and that the name of i-cubed limited not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ * i-cubed limited makes no representations about the suitability
+ * of this software for any purpose.
+ *
+ * Derived from c/src/exec/cpu/no_cpu/no_cpu.h:
+ *
+ * COPYRIGHT (c) 1989-1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may in
+ * the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ *
+ * Note:
+ * This file is included by both C and assembler code ( -DASM )
+ *
+ * $Id$
+ */
+
+
+#ifndef _INCLUDE_PPC_h
+#define _INCLUDE_PPC_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/types.h>
+
+/*
+ * Define the name of the CPU family.
+ */
+
+#define CPU_NAME "PowerPC"
+
+/*
+ * This file contains the information required to build
+ * RTEMS for a particular member of the PowerPC family. It does
+ * this by setting variables to indicate which implementation
+ * dependent features are present in a particular member
+ * of the family.
+ *
+ * The following architectural feature definitions are defaulted
+ * unless specifically set by the model definition:
+ *
+ * + PPC_INTERRUPT_MAX - 16
+ * + PPC_CACHE_ALIGNMENT - 32
+ * + PPC_LOW_POWER_MODE - PPC_LOW_POWER_MODE_NONE
+ * + PPC_HAS_EXCEPTION_PREFIX - 1
+ * + PPC_HAS_FPU - 1
+ * + PPC_HAS_DOUBLE - 1 if PPC_HAS_FPU,
+ * - 0 otherwise
+ * + PPC_USE_MULTIPLE - 0
+ */
+
+/*
+ * Define the low power mode models
+ *
+ * Standard: as defined for 603e
+ * Nap Mode: nap mode only (604)
+ * XXX 403GB, 603, 603e, 604, 821
+ */
+
+#define PPC_LOW_POWER_MODE_NONE 0
+#define PPC_LOW_POWER_MODE_STANDARD 1
+
+/*
+ * Figure out all CPU Model Feature Flags based upon compiler
+ * predefines.
+ */
+
+#if defined(ppc403) || defined(ppc405)
+/*
+ * IBM 403
+ *
+ * Developed for 403GA. Book checked for 403GB.
+ *
+ * Does not have user mode.
+ */
+
+#if defined(ppc403)
+#define CPU_MODEL_NAME "PowerPC 403"
+#elif defined (ppc405)
+#define CPU_MODEL_NAME "PowerPC 405"
+#endif
+#define PPC_ALIGNMENT 4
+#define PPC_CACHE_ALIGNMENT 16
+#define PPC_HAS_RFCI 1
+#define PPC_HAS_FPU 0
+#define PPC_USE_MULTIPLE 1
+#define PPC_I_CACHE 2048
+#define PPC_D_CACHE 1024
+
+#define PPC_HAS_EXCEPTION_PREFIX 0
+#define PPC_HAS_EVPR 1
+
+#elif defined(mpc555)
+
+#define CPU_MODEL_NAME "PowerPC 555"
+
+/* Copied from mpc505 */
+#define PPC_ALIGNMENT 4
+#define PPC_CACHE_ALIGNMENT 16
+
+/* Added by querbach@realtime.bc.ca */
+#define PPC_LOW_POWER_MODE PPC_LOW_POWER_MODE_STANDARD
+
+/* Based on comments by Sergei Organov <osv@Javad.RU> */
+#define PPC_I_CACHE 0
+#define PPC_D_CACHE 0
+
+#elif defined(mpc505) || defined(mpc509)
+/*
+ * Submitted by Sergei Organov <osv@Javad.RU> as a patch against
+ * 3.6.0 long after 4.0 was released. This is just an attempt
+ * to get the setting correct.
+ */
+
+#define CPU_MODEL_NAME "PowerPC 505/509"
+
+#define PPC_ALIGNMENT 4
+#define PPC_CACHE_ALIGNMENT 16
+#define PPC_I_CACHE 4096
+#define PPC_D_CACHE 0
+
+
+#elif defined(ppc601)
+
+/*
+ * Submitted with original port -- book checked only.
+ */
+
+#define CPU_MODEL_NAME "PowerPC 601"
+
+#define PPC_ALIGNMENT 8
+#define PPC_USE_MULTIPLE 1
+#define PPC_I_CACHE 0
+#define PPC_D_CACHE 32768
+
+#elif defined(ppc602)
+/*
+ * Submitted with original port -- book checked only.
+ */
+
+#define CPU_MODEL_NAME "PowerPC 602"
+
+#define PPC_ALIGNMENT 4
+#define PPC_HAS_DOUBLE 0
+#define PPC_I_CACHE 4096
+#define PPC_D_CACHE 4096
+
+#elif defined(ppc603)
+/*
+ * Submitted with original port -- book checked only.
+ */
+
+#define CPU_MODEL_NAME "PowerPC 603"
+
+#define PPC_ALIGNMENT 8
+#define PPC_I_CACHE 8192
+#define PPC_D_CACHE 8192
+
+#elif defined(ppc603e)
+
+#define CPU_MODEL_NAME "PowerPC 603e"
+/*
+ * Submitted with original port.
+ *
+ * Known to work on real hardware.
+ */
+
+#define PPC_ALIGNMENT 8
+#define PPC_I_CACHE 16384
+#define PPC_D_CACHE 16384
+
+#define PPC_LOW_POWER_MODE PPC_LOW_POWER_MODE_STANDARD
+
+#elif defined(mpc604)
+/*
+ * Submitted with original port -- book checked only.
+ */
+
+#define CPU_MODEL_NAME "PowerPC 604"
+
+#define PPC_ALIGNMENT 8
+#define PPC_I_CACHE 16384
+#define PPC_D_CACHE 16384
+
+#elif defined(mpc860)
+/*
+ * Added by Jay Monkman (jmonkman@frasca.com) 6/28/98
+ * with some changes by Darlene Stewart (Darlene.Stewart@iit.nrc.ca)
+ */
+#define CPU_MODEL_NAME "PowerPC MPC860"
+
+#define PPC_ALIGNMENT 4
+#define PPC_I_CACHE 4096
+#define PPC_D_CACHE 4096
+#define PPC_CACHE_ALIGNMENT 16
+#define PPC_INTERRUPT_MAX 71
+#define PPC_HAS_FPU 0
+#define PPC_HAS_DOUBLE 0
+#define PPC_USE_MULTIPLE 1
+
+#define PPC_MSR_0 0x00009000
+#define PPC_MSR_1 0x00001000
+#define PPC_MSR_2 0x00001000
+#define PPC_MSR_3 0x00000000
+
+#elif defined(mpc821)
+/*
+ * Added by Andrew Bray <andy@chaos.org.uk> 6/April/1999
+ */
+#define CPU_MODEL_NAME "PowerPC MPC821"
+
+#define PPC_ALIGNMENT 4
+#define PPC_I_CACHE 4096
+#define PPC_D_CACHE 4096
+#define PPC_CACHE_ALIGNMENT 16
+#define PPC_INTERRUPT_MAX 71
+#define PPC_HAS_FPU 0
+#define PPC_HAS_DOUBLE 0
+
+#define PPC_MSR_0 0x00009000
+#define PPC_MSR_1 0x00001000
+#define PPC_MSR_2 0x00001000
+#define PPC_MSR_3 0x00000000
+
+#elif defined(mpc750)
+
+#define CPU_MODEL_NAME "PowerPC 750"
+
+#define PPC_ALIGNMENT 8
+#define PPC_I_CACHE 16384
+#define PPC_D_CACHE 16384
+
+#elif defined(mpc7400)
+
+#define CPU_MODEL_NAME "PowerPC 7400"
+
+#define PPC_ALIGNMENT 8
+#define PPC_I_CACHE 32768
+#define PPC_D_CACHE 32768
+
+#elif defined(mpc8260)
+/*
+ * Added by Andy Dachs <a.dachs@sstl.co.uk> 23/11/2000
+ */
+#define CPU_MODEL_NAME "PowerPC MPC8260"
+
+#define PPC_ALIGNMENT 4
+#define PPC_I_CACHE 16384
+#define PPC_D_CACHE 16384
+#define PPC_CACHE_ALIGNMENT 32
+#define PPC_INTERRUPT_MAX 125
+/*#define PPC_HAS_FPU 0 */ /* my 8260 is one the few with no FPU */
+#define PPC_HAS_FPU 1 /* the rest do have one */
+#define PPC_HAS_DOUBLE 1
+#define PPC_USE_MULTIPLE 1
+#else
+
+#error "Unsupported CPU Model"
+
+#endif
+
+/*
+ * Application binary interfaces.
+ *
+ * PPC_ABI MUST be defined as one of these.
+ * Only PPC_ABI_POWEROPEN is currently fully supported.
+ * Only EABI will be supported in the end when
+ * the tools are there.
+ * Only big endian is currently supported.
+ */
+/*
+ * PowerOpen ABI. This is Andy's hack of the
+ * PowerOpen ABI to ELF. ELF rather than a
+ * XCOFF assembler is used. This may work
+ * if PPC_ASM == PPC_ASM_XCOFF is defined.
+ */
+#define PPC_ABI_POWEROPEN 0
+/*
+ * GCC 2.7.0 munched version of EABI, with
+ * PowerOpen calling convention and stack frames,
+ * but EABI style indirect function calls.
+ */
+#define PPC_ABI_GCC27 1
+/*
+ * SVR4 ABI
+ */
+#define PPC_ABI_SVR4 2
+/*
+ * Embedded ABI
+ */
+#define PPC_ABI_EABI 3
+
+/*
+ * Default to the EABI used by current GNU tools
+ */
+
+#ifndef PPC_ABI
+#define PPC_ABI PPC_ABI_EABI
+#endif
+
+#if (PPC_ABI == PPC_ABI_POWEROPEN)
+#define PPC_STACK_ALIGNMENT 8
+#elif (PPC_ABI == PPC_ABI_GCC27)
+#define PPC_STACK_ALIGNMENT 8
+#elif (PPC_ABI == PPC_ABI_SVR4)
+#define PPC_STACK_ALIGNMENT 16
+#elif (PPC_ABI == PPC_ABI_EABI)
+#define PPC_STACK_ALIGNMENT 8
+#else
+#error "PPC_ABI is not properly defined"
+#endif
+#ifndef PPC_ABI
+#error "PPC_ABI is not properly defined"
+#endif
+
+/*
+ * Assemblers.
+ * PPC_ASM MUST be defined as one of these.
+ *
+ * PPC_ASM_ELF: ELF assembler. Currently used for all ABIs.
+ * PPC_ASM_XCOFF: XCOFF assembler. May be needed for PowerOpen ABI.
+ *
+ * NOTE: Only PPC_ABI_ELF is currently fully supported.
+ */
+
+#define PPC_ASM_ELF 0
+#define PPC_ASM_XCOFF 1
+
+/*
+ * Default to the assembler format used by the current GNU tools.
+ */
+
+#ifndef PPC_ASM
+#define PPC_ASM PPC_ASM_ELF
+#endif
+
+/*
+ * If the maximum number of exception sources has not been defined,
+ * then default it to 16.
+ */
+
+#ifndef PPC_INTERRUPT_MAX
+#define PPC_INTERRUPT_MAX 16
+#endif
+
+/*
+ * Unless specified otherwise, the cache line size is defaulted to 32.
+ *
+ * The derive the power of 2 the cache line is.
+ */
+
+#ifndef PPC_CACHE_ALIGNMENT
+#define PPC_CACHE_ALIGNMENT 32
+#endif
+
+#if (PPC_CACHE_ALIGNMENT == 16)
+#define PPC_CACHE_ALIGN_POWER 4
+#elif (PPC_CACHE_ALIGNMENT == 32)
+#define PPC_CACHE_ALIGN_POWER 5
+#else
+#error "Undefined power of 2 for PPC_CACHE_ALIGNMENT"
+#endif
+
+/*
+ * Unless otherwise specified, assume the model has an IP/EP bit to
+ * set the exception address prefix.
+ */
+
+#ifndef PPC_HAS_EXCEPTION_PREFIX
+#define PPC_HAS_EXCEPTION_PREFIX 1
+#endif
+
+/*
+ * Unless otherwise specified, assume the model does NOT have
+ * 403 style EVPR register to set the exception address prefix.
+ */
+
+#ifndef PPC_HAS_EVPR
+#define PPC_HAS_EVPR 0
+#endif
+
+/*
+ * If no low power mode model was specified, then assume there is none.
+ */
+
+#ifndef PPC_LOW_POWER_MODE
+#define PPC_LOW_POWER_MODE PPC_LOW_POWER_MODE_NONE
+#endif
+
+/*
+ * Unless specified above, then assume the model has FP support.
+ */
+
+#ifndef PPC_HAS_FPU
+#define PPC_HAS_FPU 1
+#endif
+
+/*
+ * Unless specified above, If the model has FP support, it is assumed to
+ * support doubles (8-byte floating point numbers).
+ *
+ * If the model does NOT have FP support, then the model does
+ * NOT have double length FP registers.
+ */
+
+#ifndef PPC_HAS_DOUBLE
+#if (PPC_HAS_FPU)
+#define PPC_HAS_DOUBLE 1
+#else
+#define PPC_HAS_DOUBLE 0
+#endif
+#endif
+
+/*
+ * Unless specified above, then assume the model does NOT have critical
+ * interrupt support.
+ */
+
+#ifndef PPC_HAS_RFCI
+#define PPC_HAS_RFCI 0
+#endif
+
+/*
+ * Unless specified above, do not use the load/store multiple instructions
+ * in a context switch.
+ */
+
+#ifndef PPC_USE_MULTIPLE
+#define PPC_USE_MULTIPLE 0
+#endif
+
+/*
+ * The following exceptions are not maskable, and are not
+ * necessarily predictable, so cannot be offered to RTEMS:
+ * Alignment exception - handled by the CPU module
+ * Data exceptions.
+ * Instruction exceptions.
+ */
+
+/*
+ * Base Interrupt vectors supported on all models.
+ */
+#define PPC_IRQ_SYSTEM_RESET 0 /* 0x00100 - System reset. */
+#define PPC_IRQ_MCHECK 1 /* 0x00200 - Machine check */
+#define PPC_IRQ_PROTECT 2 /* 0x00300 - Protection violation */
+#define PPC_IRQ_ISI 3 /* 0x00400 - Instruction Fetch error */
+#define PPC_IRQ_EXTERNAL 4 /* 0x00500 - External interrupt */
+#define PPC_IRQ_ALIGNMENT 5 /* 0X00600 - Alignment exception */
+#define PPC_IRQ_PROGRAM 6 /* 0x00700 - Program exception */
+#define PPC_IRQ_NOFP 7 /* 0x00800 - Floating point unavailable */
+#define PPC_IRQ_DECREMENTER 8 /* 0x00900 - Decrementer interrupt */
+#define PPC_IRQ_RESERVED_A 9 /* 0x00a00 - Implementation Reserved */
+#define PPC_IRQ_RESERVED_B 10 /* 0x00b00 - Implementation Reserved */
+#define PPC_IRQ_SCALL 11 /* 0x00c00 - System call */
+#define PPC_IRQ_TRACE 12 /* 0x00d00 - Trace Exception */
+#define PPC_IRQ_FP_ASST 13 /* ox00e00 - Floating point assist */
+#define PPC_STD_IRQ_LAST PPC_IRQ_FP_ASST
+
+#define PPC_IRQ_FIRST PPC_IRQ_SYSTEM_RESET
+
+#if defined(ppc403) || defined(ppc405)
+
+#define PPC_IRQ_CRIT PPC_IRQ_SYSTEM_RESET /*0x00100- Critical int. pin */
+#define PPC_IRQ_PIT (PPC_STD_IRQ_LAST+1) /*0x01000- Pgm interval timer*/
+#define PPC_IRQ_FIT (PPC_STD_IRQ_LAST+2) /*0x01010- Fixed int. timer */
+#define PPC_IRQ_WATCHDOG (PPC_STD_IRQ_LAST+3) /*0x01020- Watchdog timer */
+#define PPC_IRQ_DEBUG (PPC_STD_IRQ_LAST+4) /*0x02000- Debug exceptions */
+#define PPC_IRQ_LAST PPC_IRQ_DEBUG
+
+#elif defined(mpc505) || defined(mpc509)
+#define PPC_IRQ_SOFTEMU (PPC_STD_IRQ_LAST+1) /* Software emulation. */
+#define PPC_IRQ_DATA_BP (PPC_STD_IRQ_LAST+ 2)
+#define PPC_IRQ_INST_BP (PPC_STD_IRQ_LAST+ 3)
+#define PPC_IRQ_MEXT_BP (PPC_STD_IRQ_LAST+ 4)
+#define PPC_IRQ_NMEXT_BP (PPC_STD_IRQ_LAST+ 5)
+
+#elif defined(mpc555)
+#define PPC_IRQ_SOFTEMU (PPC_STD_IRQ_LAST+1) /* Software emulation. */
+#define PPC_IRQ_INST_PE (PPC_STD_IRQ_LAST+2) /* Insn protection error */
+#define PPC_IRQ_DATA_PE (PPC_STD_IRQ_LAST+3) /* Data protection error */
+#define PPC_IRQ_DATA_BP (PPC_STD_IRQ_LAST+4) /* Data breakpoint */
+#define PPC_IRQ_INST_BP (PPC_STD_IRQ_LAST+5) /* Insn breakpoint */
+#define PPC_IRQ_MEXT_BP (PPC_STD_IRQ_LAST+6) /* Maskable ext bkpt */
+#define PPC_IRQ_NMEXT_BP (PPC_STD_IRQ_LAST+7) /* Non-maskable ext bkpt */
+#define PPC_IRQ_LAST PPC_IRQ_NMEXT_BP
+
+#elif defined(ppc601)
+#define PPC_IRQ_TRACE (PPC_STD_IRQ_LAST+1) /*0x02000-Run/Trace Exception*/
+#define PPC_IRQ_LAST PPC_IRQ_TRACE
+
+#elif defined(ppc602)
+#define PPC_IRQ_LAST (PPC_STD_IRQ_LAST)
+
+#elif defined(ppc603)
+#define PPC_IRQ_TRANS_MISS (PPC_STD_IRQ_LAST+1) /*0x1000-Ins Translation Miss*/
+#define PPC_IRQ_DATA_LOAD (PPC_STD_IRQ_LAST+2) /*0x1100-Data Load Trans Miss*/
+#define PPC_IRQ_DATA_STORE (PPC_STD_IRQ_LAST+3) /*0x1200-Data Store Miss */
+#define PPC_IRQ_ADDR_BRK (PPC_STD_IRQ_LAST+4) /*0x1300-Instruction Bkpoint */
+#define PPC_IRQ_SYS_MGT (PPC_STD_IRQ_LAST+5) /*0x1400-System Management */
+#define PPC_IRQ_LAST PPC_IRQ_SYS_MGT
+
+#elif defined(ppc603e)
+#define PPC_TLB_INST_MISS (PPC_STD_IRQ_LAST+1) /*0x1000-Instruction TLB Miss*/
+#define PPC_TLB_LOAD_MISS (PPC_STD_IRQ_LAST+2) /*0x1100-TLB miss on load */
+#define PPC_TLB_STORE_MISS (PPC_STD_IRQ_LAST+3) /*0x1200-TLB Miss on store */
+#define PPC_IRQ_ADDRBRK (PPC_STD_IRQ_LAST+4) /*0x1300-Instruct addr break */
+#define PPC_IRQ_SYS_MGT (PPC_STD_IRQ_LAST+5) /*0x1400-System Management */
+#define PPC_IRQ_LAST PPC_IRQ_SYS_MGT
+
+
+#elif defined(mpc604)
+#define PPC_IRQ_ADDR_BRK (PPC_STD_IRQ_LAST+1) /*0x1300- Inst. addr break */
+#define PPC_IRQ_SYS_MGT (PPC_STD_IRQ_LAST+2) /*0x1400- System Management */
+#define PPC_IRQ_LAST PPC_IRQ_SYS_MGT
+
+#elif defined(mpc860) || defined(mpc821)
+#define PPC_IRQ_EMULATE (PPC_STD_IRQ_LAST+1) /*0x1000-Software emulation */
+#define PPC_IRQ_INST_MISS (PPC_STD_IRQ_LAST+2) /*0x1100-Instruction TLB miss*/
+#define PPC_IRQ_DATA_MISS (PPC_STD_IRQ_LAST+3) /*0x1200-Data TLB miss */
+#define PPC_IRQ_INST_ERR (PPC_STD_IRQ_LAST+4) /*0x1300-Instruction TLB err */
+#define PPC_IRQ_DATA_ERR (PPC_STD_IRQ_LAST+5) /*0x1400-Data TLB error */
+#define PPC_IRQ_DATA_BPNT (PPC_STD_IRQ_LAST+6) /*0x1C00-Data breakpoint */
+#define PPC_IRQ_INST_BPNT (PPC_STD_IRQ_LAST+7) /*0x1D00-Inst breakpoint */
+#define PPC_IRQ_IO_BPNT (PPC_STD_IRQ_LAST+8) /*0x1E00-Peripheral breakpnt */
+#define PPC_IRQ_DEV_PORT (PPC_STD_IRQ_LAST+9) /*0x1F00-Development port */
+#define PPC_IRQ_IRQ0 (PPC_STD_IRQ_LAST + 10)
+#define PPC_IRQ_LVL0 (PPC_STD_IRQ_LAST + 11)
+#define PPC_IRQ_IRQ1 (PPC_STD_IRQ_LAST + 12)
+#define PPC_IRQ_LVL1 (PPC_STD_IRQ_LAST + 13)
+#define PPC_IRQ_IRQ2 (PPC_STD_IRQ_LAST + 14)
+#define PPC_IRQ_LVL2 (PPC_STD_IRQ_LAST + 15)
+#define PPC_IRQ_IRQ3 (PPC_STD_IRQ_LAST + 16)
+#define PPC_IRQ_LVL3 (PPC_STD_IRQ_LAST + 17)
+#define PPC_IRQ_IRQ4 (PPC_STD_IRQ_LAST + 18)
+#define PPC_IRQ_LVL4 (PPC_STD_IRQ_LAST + 19)
+#define PPC_IRQ_IRQ5 (PPC_STD_IRQ_LAST + 20)
+#define PPC_IRQ_LVL5 (PPC_STD_IRQ_LAST + 21)
+#define PPC_IRQ_IRQ6 (PPC_STD_IRQ_LAST + 22)
+#define PPC_IRQ_LVL6 (PPC_STD_IRQ_LAST + 23)
+#define PPC_IRQ_IRQ7 (PPC_STD_IRQ_LAST + 24)
+#define PPC_IRQ_LVL7 (PPC_STD_IRQ_LAST + 25)
+#define PPC_IRQ_CPM_ERROR (PPC_STD_IRQ_LAST + 26)
+#define PPC_IRQ_CPM_PC4 (PPC_STD_IRQ_LAST + 27)
+#define PPC_IRQ_CPM_PC5 (PPC_STD_IRQ_LAST + 28)
+#define PPC_IRQ_CPM_SMC2 (PPC_STD_IRQ_LAST + 29)
+#define PPC_IRQ_CPM_SMC1 (PPC_STD_IRQ_LAST + 30)
+#define PPC_IRQ_CPM_SPI (PPC_STD_IRQ_LAST + 31)
+#define PPC_IRQ_CPM_PC6 (PPC_STD_IRQ_LAST + 32)
+#define PPC_IRQ_CPM_TIMER4 (PPC_STD_IRQ_LAST + 33)
+#define PPC_IRQ_CPM_RESERVED_8 (PPC_STD_IRQ_LAST + 34)
+#define PPC_IRQ_CPM_PC7 (PPC_STD_IRQ_LAST + 35)
+#define PPC_IRQ_CPM_PC8 (PPC_STD_IRQ_LAST + 36)
+#define PPC_IRQ_CPM_PC9 (PPC_STD_IRQ_LAST + 37)
+#define PPC_IRQ_CPM_TIMER3 (PPC_STD_IRQ_LAST + 38)
+#define PPC_IRQ_CPM_RESERVED_D (PPC_STD_IRQ_LAST + 39)
+#define PPC_IRQ_CPM_PC10 (PPC_STD_IRQ_LAST + 40)
+#define PPC_IRQ_CPM_PC11 (PPC_STD_IRQ_LAST + 41)
+#define PPC_IRQ_CPM_I2C (PPC_STD_IRQ_LAST + 42)
+#define PPC_IRQ_CPM_RISC_TIMER (PPC_STD_IRQ_LAST + 43)
+#define PPC_IRQ_CPM_TIMER2 (PPC_STD_IRQ_LAST + 44)
+#define PPC_IRQ_CPM_RESERVED_13 (PPC_STD_IRQ_LAST + 45)
+#define PPC_IRQ_CPM_IDMA2 (PPC_STD_IRQ_LAST + 46)
+#define PPC_IRQ_CPM_IDMA1 (PPC_STD_IRQ_LAST + 47)
+#define PPC_IRQ_CPM_SDMA_ERROR (PPC_STD_IRQ_LAST + 48)
+#define PPC_IRQ_CPM_PC12 (PPC_STD_IRQ_LAST + 49)
+#define PPC_IRQ_CPM_PC13 (PPC_STD_IRQ_LAST + 50)
+#define PPC_IRQ_CPM_TIMER1 (PPC_STD_IRQ_LAST + 51)
+#define PPC_IRQ_CPM_PC14 (PPC_STD_IRQ_LAST + 52)
+#define PPC_IRQ_CPM_SCC4 (PPC_STD_IRQ_LAST + 53)
+#define PPC_IRQ_CPM_SCC3 (PPC_STD_IRQ_LAST + 54)
+#define PPC_IRQ_CPM_SCC2 (PPC_STD_IRQ_LAST + 55)
+#define PPC_IRQ_CPM_SCC1 (PPC_STD_IRQ_LAST + 56)
+#define PPC_IRQ_CPM_PC15 (PPC_STD_IRQ_LAST + 57)
+
+#define PPC_IRQ_LAST PPC_IRQ_CPM_PC15
+
+#elif defined(mpc8260)
+
+#define PPC_IRQ_INST_MISS (PPC_STD_IRQ_LAST+1) /*0x1000-Instruction TLB miss*/
+#define PPC_IRQ_DATA_MISS (PPC_STD_IRQ_LAST+2) /*0x1100-Data TLB miss */
+#define PPC_IRQ_DATA_L_MISS (PPC_STD_IRQ_LAST+3) /*0x1200-Data TLB load miss */
+#define PPC_IRQ_DATA_S_MISS (PPC_STD_IRQ_LAST+4) /*0x1300-Data TLB store miss */
+#define PPC_IRQ_INST_BPNT (PPC_STD_IRQ_LAST+5) /*0x1400-Inst address breakpoint */
+#define PPC_IRQ_SYS_MGT (PPC_STD_IRQ_LAST+6) /*0x1500-System Management */
+/* 0x1600 - 0x2F00 reserved */
+#define PPC_IRQ_CPM_NONE (PPC_STD_IRQ_LAST + 50)
+#define PPC_IRQ_CPM_I2C (PPC_STD_IRQ_LAST + 51)
+#define PPC_IRQ_CPM_SPI (PPC_STD_IRQ_LAST + 52)
+#define PPC_IRQ_CPM_RISC_TIMER (PPC_STD_IRQ_LAST + 53)
+#define PPC_IRQ_CPM_SMC1 (PPC_STD_IRQ_LAST + 54)
+#define PPC_IRQ_CPM_SMC2 (PPC_STD_IRQ_LAST + 55)
+#define PPC_IRQ_CPM_IDMA1 (PPC_STD_IRQ_LAST + 56)
+#define PPC_IRQ_CPM_IDMA2 (PPC_STD_IRQ_LAST + 57)
+#define PPC_IRQ_CPM_IDMA3 (PPC_STD_IRQ_LAST + 58)
+#define PPC_IRQ_CPM_IDMA4 (PPC_STD_IRQ_LAST + 59)
+#define PPC_IRQ_CPM_SDMA (PPC_STD_IRQ_LAST + 60)
+#define PPC_IRQ_CPM_RES_A (PPC_STD_IRQ_LAST + 61)
+#define PPC_IRQ_CPM_TIMER1 (PPC_STD_IRQ_LAST + 62)
+#define PPC_IRQ_CPM_TIMER2 (PPC_STD_IRQ_LAST + 63)
+#define PPC_IRQ_CPM_TIMER3 (PPC_STD_IRQ_LAST + 64)
+#define PPC_IRQ_CPM_TIMER4 (PPC_STD_IRQ_LAST + 65)
+#define PPC_IRQ_CPM_TMCNT (PPC_STD_IRQ_LAST + 66)
+#define PPC_IRQ_CPM_PIT (PPC_STD_IRQ_LAST + 67)
+#define PPC_IRQ_CPM_RES_B (PPC_STD_IRQ_LAST + 68)
+#define PPC_IRQ_CPM_IRQ1 (PPC_STD_IRQ_LAST + 69)
+#define PPC_IRQ_CPM_IRQ2 (PPC_STD_IRQ_LAST + 70)
+#define PPC_IRQ_CPM_IRQ3 (PPC_STD_IRQ_LAST + 71)
+#define PPC_IRQ_CPM_IRQ4 (PPC_STD_IRQ_LAST + 72)
+#define PPC_IRQ_CPM_IRQ5 (PPC_STD_IRQ_LAST + 73)
+#define PPC_IRQ_CPM_IRQ6 (PPC_STD_IRQ_LAST + 74)
+#define PPC_IRQ_CPM_IRQ7 (PPC_STD_IRQ_LAST + 75)
+#define PPC_IRQ_CPM_RES_C (PPC_STD_IRQ_LAST + 76)
+#define PPC_IRQ_CPM_RES_D (PPC_STD_IRQ_LAST + 77)
+#define PPC_IRQ_CPM_RES_E (PPC_STD_IRQ_LAST + 78)
+#define PPC_IRQ_CPM_RES_F (PPC_STD_IRQ_LAST + 79)
+#define PPC_IRQ_CPM_RES_G (PPC_STD_IRQ_LAST + 80)
+#define PPC_IRQ_CPM_RES_H (PPC_STD_IRQ_LAST + 81)
+#define PPC_IRQ_CPM_FCC1 (PPC_STD_IRQ_LAST + 82)
+#define PPC_IRQ_CPM_FCC2 (PPC_STD_IRQ_LAST + 83)
+#define PPC_IRQ_CPM_FCC3 (PPC_STD_IRQ_LAST + 84)
+#define PPC_IRQ_CPM_RES_I (PPC_STD_IRQ_LAST + 85)
+#define PPC_IRQ_CPM_MCC1 (PPC_STD_IRQ_LAST + 86)
+#define PPC_IRQ_CPM_MCC2 (PPC_STD_IRQ_LAST + 87)
+#define PPC_IRQ_CPM_RES_J (PPC_STD_IRQ_LAST + 88)
+#define PPC_IRQ_CPM_RES_K (PPC_STD_IRQ_LAST + 89)
+#define PPC_IRQ_CPM_SCC1 (PPC_STD_IRQ_LAST + 90)
+#define PPC_IRQ_CPM_SCC2 (PPC_STD_IRQ_LAST + 91)
+#define PPC_IRQ_CPM_SCC3 (PPC_STD_IRQ_LAST + 92)
+#define PPC_IRQ_CPM_SCC4 (PPC_STD_IRQ_LAST + 93)
+#define PPC_IRQ_CPM_RES_L (PPC_STD_IRQ_LAST + 94)
+#define PPC_IRQ_CPM_RES_M (PPC_STD_IRQ_LAST + 95)
+#define PPC_IRQ_CPM_RES_N (PPC_STD_IRQ_LAST + 96)
+#define PPC_IRQ_CPM_RES_O (PPC_STD_IRQ_LAST + 97)
+#define PPC_IRQ_CPM_PC15 (PPC_STD_IRQ_LAST + 98)
+#define PPC_IRQ_CPM_PC14 (PPC_STD_IRQ_LAST + 99)
+#define PPC_IRQ_CPM_PC13 (PPC_STD_IRQ_LAST + 100)
+#define PPC_IRQ_CPM_PC12 (PPC_STD_IRQ_LAST + 101)
+#define PPC_IRQ_CPM_PC11 (PPC_STD_IRQ_LAST + 102)
+#define PPC_IRQ_CPM_PC10 (PPC_STD_IRQ_LAST + 103)
+#define PPC_IRQ_CPM_PC9 (PPC_STD_IRQ_LAST + 104)
+#define PPC_IRQ_CPM_PC8 (PPC_STD_IRQ_LAST + 105)
+#define PPC_IRQ_CPM_PC7 (PPC_STD_IRQ_LAST + 106)
+#define PPC_IRQ_CPM_PC6 (PPC_STD_IRQ_LAST + 107)
+#define PPC_IRQ_CPM_PC5 (PPC_STD_IRQ_LAST + 108)
+#define PPC_IRQ_CPM_PC4 (PPC_STD_IRQ_LAST + 109)
+#define PPC_IRQ_CPM_PC3 (PPC_STD_IRQ_LAST + 110)
+#define PPC_IRQ_CPM_PC2 (PPC_STD_IRQ_LAST + 111)
+#define PPC_IRQ_CPM_PC1 (PPC_STD_IRQ_LAST + 112)
+#define PPC_IRQ_CPM_PC0 (PPC_STD_IRQ_LAST + 113)
+
+#define PPC_IRQ_LAST PPC_IRQ_CPM_PC0
+
+#endif
+
+
+/*
+ * If the maximum number of exception sources is too low,
+ * then fix it
+ */
+
+#if PPC_INTERRUPT_MAX <= PPC_IRQ_LAST
+#undef PPC_INTERRUPT_MAX
+#define PPC_INTERRUPT_MAX ((PPC_IRQ_LAST) + 1)
+#endif
+
+/*
+ * Machine Status Register (MSR) Constants Used by RTEMS
+ */
+
+/*
+ * Some PPC model manuals refer to the Exception Prefix (EP) bit as
+ * IP for no apparent reason.
+ */
+
+#define PPC_MSR_RI 0x000000002 /* bit 30 - recoverable exception */
+#define PPC_MSR_DR 0x000000010 /* bit 27 - data address translation */
+#define PPC_MSR_IR 0x000000020 /* bit 26 - instruction addr translation*/
+
+#if (PPC_HAS_EXCEPTION_PREFIX)
+#define PPC_MSR_EP 0x000000040 /* bit 25 - exception prefix */
+#else
+#define PPC_MSR_EP 0x000000000 /* bit 25 - exception prefix */
+#endif
+
+#if (PPC_HAS_FPU)
+#define PPC_MSR_FP 0x000002000 /* bit 18 - floating point enable */
+#else
+#define PPC_MSR_FP 0x000000000 /* bit 18 - floating point enable */
+#endif
+
+#if (PPC_LOW_POWER_MODE == PPC_LOW_POWER_MODE_NONE)
+#define PPC_MSR_POW 0x000000000 /* bit 13 - power management enable */
+#else
+#define PPC_MSR_POW 0x000040000 /* bit 13 - power management enable */
+#endif
+
+#define PPC_MSR_ME 0x000001000 /* bit 19 - machine check enable */
+#define PPC_MSR_EE 0x000008000 /* bit 16 - external interrupt enable */
+
+#if (PPC_HAS_RFCI)
+#define PPC_MSR_CE 0x000020000 /* bit 14 - critical interrupt enable */
+#else
+#define PPC_MSR_CE 0x000000000 /* bit 14 - critical interrupt enable */
+#endif
+
+#define PPC_MSR_DISABLE_MASK (PPC_MSR_ME|PPC_MSR_EE|PPC_MSR_CE)
+
+/*
+ * Initial value for the FPSCR register
+ */
+
+#define PPC_INIT_FPSCR 0x000000f8
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ! _INCLUDE_PPC_h */
+/* end of include file */
diff --git a/cpukit/score/cpu/powerpc/rtems/score/ppc.h b/cpukit/score/cpu/powerpc/rtems/score/ppc.h
new file mode 100644
index 0000000000..3104bc7f1c
--- /dev/null
+++ b/cpukit/score/cpu/powerpc/rtems/score/ppc.h
@@ -0,0 +1,15 @@
+/*
+ * The license and distribution terms for this file may in
+ * the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __rtems_score_ppc_h
+#define __rtems_score_ppc_h
+#ifndef RTEMS_NO_WARN_DEPRECATED
+#warning <rtems/score/ppc.h> is deprecated, use <rtems/score/powerpc.h> instead
+#endif
+#include <rtems/score/powerpc.h>
+#endif
diff --git a/cpukit/score/cpu/powerpc/rtems/score/types.h b/cpukit/score/cpu/powerpc/rtems/score/types.h
new file mode 100644
index 0000000000..e7ec4b5b4b
--- /dev/null
+++ b/cpukit/score/cpu/powerpc/rtems/score/types.h
@@ -0,0 +1,72 @@
+/* types.h
+ *
+ * This include file contains type definitions pertaining to the PowerPC
+ * processor family.
+ *
+ * Author: Andrew Bray <andy@i-cubed.co.uk>
+ *
+ * COPYRIGHT (c) 1995 by i-cubed ltd.
+ *
+ * To anyone who acknowledges that this file is provided "AS IS"
+ * without any express or implied warranty:
+ * permission to use, copy, modify, and distribute this file
+ * for any purpose is hereby granted without fee, provided that
+ * the above copyright notice and this notice appears in all
+ * copies, and that the name of i-cubed limited not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ * i-cubed limited makes no representations about the suitability
+ * of this software for any purpose.
+ *
+ * Derived from c/src/exec/cpu/no_cpu/no_cputypes.h:
+ *
+ * COPYRIGHT (c) 1989-1997.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may in
+ * the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __PPC_TYPES_h
+#define __PPC_TYPES_h
+
+#ifndef ASM
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This section defines the basic types for this processor.
+ */
+
+typedef unsigned char unsigned8; /* unsigned 8-bit integer */
+typedef unsigned short unsigned16; /* unsigned 16-bit integer */
+typedef unsigned int unsigned32; /* unsigned 32-bit integer */
+typedef unsigned long long unsigned64; /* unsigned 64-bit integer */
+
+typedef unsigned32 Priority_Bit_map_control;
+
+typedef signed char signed8; /* 8-bit signed integer */
+typedef signed short signed16; /* 16-bit signed integer */
+typedef signed int signed32; /* 32-bit signed integer */
+typedef signed long long signed64; /* 64 bit signed integer */
+
+typedef unsigned32 boolean; /* Boolean value */
+
+typedef float single_precision; /* single precision float */
+typedef double double_precision; /* double precision float */
+
+typedef void ppc_isr;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !ASM */
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/sh/.cvsignore b/cpukit/score/cpu/sh/.cvsignore
new file mode 100644
index 0000000000..282522db03
--- /dev/null
+++ b/cpukit/score/cpu/sh/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/cpukit/score/cpu/sh/ChangeLog b/cpukit/score/cpu/sh/ChangeLog
new file mode 100644
index 0000000000..fb46590955
--- /dev/null
+++ b/cpukit/score/cpu/sh/ChangeLog
@@ -0,0 +1,253 @@
+2004-04-06 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * configure.ac: Remove (Merged into$(top_srcdir)/configure.ac).
+ * Makefile.am: Don't include multilib.am.
+ Reflect merging configure.ac into $(top_srcdir)/configure.ac.
+
+2004-04-01 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * Makefile.am: Install asm.h to $(includedir)/rtems.
+
+2004-03-30 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * cpu.c, rtems/score/cpu.h, rtems/score/sh.h, rtems/score/sh_io.h:
+ Convert to using c99 fixed size types.
+
+2004-03-29 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * configure.ac: RTEMS_TOP([../../../..]).
+
+2004-01-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Move RTEMS_TOP one subdir down.
+
+2004-01-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add PREINSTALL_DIRS.
+
+2004-01-14 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Re-add dirstamps to PREINSTALL_FILES.
+ Add PREINSTALL_FILES to CLEANFILES.
+
+2004-01-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Requires automake >= 1.8.1.
+
+2004-01-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include compile.am, again.
+
+2004-01-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Convert to using automake compilation rules.
+
+2003-12-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use mkdir_p. Remove dirs from PREINSTALL_FILES.
+
+2003-12-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Require automake >= 1.8, autoconf >= 2.59.
+
+2003-12-01 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Remove TMPINSTALL_FILES.
+
+2003-11-30 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add $(dirstamp) to preinstallation rules.
+
+2003-11-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Don't use gmake rules for preinstallation.
+
+2003-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_CANONICAL_HOST.
+
+2003-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_CHECK_CPU.
+
+2003-09-26 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/cpu.h: Obsoleting HP PA-RISC port and removing all
+ references.
+
+2003-09-04 Joel Sherrill <joel@OARcorp.com>
+
+ * asm.h, cpu.c, rtems/score/cpu.h, rtems/score/sh.h,
+ rtems/score/sh_io.h, rtems/score/types.h: URL for license changed.
+
+2003-08-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use rtems-bugs@rtems.com as bug report email address.
+
+2003-03-06 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove AC_CONFIG_AUX_DIR.
+
+2002-12-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Require autoconf-2.57 + automake-1.7.2.
+ * Makefile.am: Eliminate C_O_FILES, S_O_FILES, libscorecpu_a_OBJECTS.
+
+2002-11-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Fix package name.
+
+2002-10-25 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Add nostdinc to AM_INIT_AUTOMAKE.
+
+2002-10-25 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/score/sh.h: Fix typo in comment (Starus->Status).
+
+2002-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * .cvsignore: Reformat.
+ Add autom4te*cache.
+ Remove autom4te.cache.
+
+2002-07-26 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Build libscorecpu.a instead of rtems-cpu.rel.
+
+2002-07-22 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use .$(OBJEXT) instead of .o.
+
+2002-07-05 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: RTEMS_TOP(../../../..).
+
+2002-07-03 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems.c: Remove.
+ * Makefile.am: Reflect changes above.
+
+2002-07-01 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_PROJECT_ROOT.
+
+2002-06-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Add RTEMS_PROG_CCAS
+
+2002-06-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use AC_CONFIG_AUX_DIR(../../../..).
+ Add AC_PROG_RANLIB.
+
+2002-06-17 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include $(top_srcdir)/../../../automake/*.am.
+ Use ../../../aclocal.
+
+2002-04-06 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems.c: Adaptation to gcc-3.0.x.
+
+2001-04-03 Joel Sherrill <joel@OARcorp.com>
+
+ * Per PR94, all rtems/score/CPUtypes.h are named rtems/score/types.h.
+ * rtems/score/shtypes.h: Removed.
+ * rtems/score/types.h: New file via CVS magic.
+ * Makefile.am, rtems/score/cpu.h: Account for name change.
+
+2002-03-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac:
+ AC_INIT(package,_RTEMS_VERSION,_RTEMS_BUGS).
+ AM_INIT_AUTOMAKE([no-define foreign 1.6]).
+ * Makefile.am: Remove AUTOMAKE_OPTIONS.
+
+2002-01-31 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Reflect 2002-01-23 changes.
+
+2002-01-31 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Reflect 2002-01-23 changes.
+
+2002-01-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/Makefile.am: Removed.
+ * rtems/score/Makefile.am: Removed.
+ * configure.ac: Reflect changes above.
+
+2001-12-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add multilib support.
+
+2001-11-28 Joel Sherrill <joel@OARcorp.com>,
+
+ This was tracked as PR91.
+ * rtems/score/cpu.h: Added CPU_PROVIDES_ISR_IS_IN_PROGRESS macro which
+ is used to specify if the port uses the standard macro for this (FALSE).
+ A TRUE setting indicates the port provides its own implementation.
+
+2001-10-15 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * cpu.c: Fix #ifdefs, add missing #endif.
+
+2001-10-12 Joel Sherrill <joel@OARcorp.com>
+
+ * asm.h, cpu.c, rtems.c, rtems/score/cpu.h, rtems/score/sh.h,
+ rtems/score/sh_io.h, rtems/score/shtypes.h: Consistency changes
+ and made sure there were no includes from the libcpu tree.
+
+2001-10-12 Alexandra Kossovsky <sasha@oktet.ru>
+
+ * cpu.c, rtems/score/cpu.h, rtems/score/sh.h: Modified to
+ support SH4. Reviewed by Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+ who did the original SH port.
+
+2001-10-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * .cvsignore: Add autom4te.cache for autoconf > 2.52.
+ * configure.in: Remove.
+ * configure.ac: New file, generated from configure.in by autoupdate.
+
+2001-09-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/score/Makefile.am: Use 'PREINSTALL_FILES ='.
+ * Makefile.am: Use 'PREINSTALL_FILES ='.
+
+2001-07-25 Radzislaw Galler <rgaller@et.put.poznan.pl>
+
+ * cpu.c (_CPU_ISR_install_vector): Corrected interrupt range
+ checking which was SH1 specific. It didn't work for SH2 (has more
+ interrupt sources).
+
+2001-02-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am, rtems/score/Makefile.am:
+ Apply include_*HEADERS instead of H_FILES.
+
+2001-01-03 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/cpu.h: Added _CPU_Initialize_vectors().
+
+2000-11-09 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use ... instead of RTEMS_TOPdir in ACLOCAL_AMFLAGS.
+
+2000-11-02 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Switch to ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal.
+
+2000-10-25 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: ACLOCAL_AMFLAGS= -I $(RTEMS_TOPdir)/macros.
+ Switch to GNU canonicalization.
+
+2000-09-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include compile.am.
+
+2000-08-10 Joel Sherrill <joel@OARcorp.com>
+
+ * ChangeLog: New file.
diff --git a/cpukit/score/cpu/sh/Makefile.am b/cpukit/score/cpu/sh/Makefile.am
new file mode 100644
index 0000000000..004c0d9878
--- /dev/null
+++ b/cpukit/score/cpu/sh/Makefile.am
@@ -0,0 +1,62 @@
+##
+## $Id$
+##
+
+include $(top_srcdir)/automake/compile.am
+
+include_rtemsdir = $(includedir)/rtems
+include_rtems_HEADERS= asm.h
+
+include_rtems_scoredir = $(includedir)/rtems/score
+include_rtems_score_HEADERS = rtems/score/cpu.h rtems/score/types.h \
+ rtems/score/sh.h rtems/score/sh_io.h
+
+EXTRA_LIBRARIES = libscorecpu.a
+CLEANFILES = libscorecpu.a
+libscorecpu_a_SOURCES = cpu.c
+libscorecpu_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libscorecpu_g.a
+CLEANFILES += libscorecpu_g.a
+libscorecpu_g_a_SOURCES = $(libscorecpu_a_SOURCES)
+libscorecpu_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+all-local: $(PREINSTALL_FILES) libscorecpu$(LIB_VARIANT).a
+
+PREINSTALL_DIRS =
+PREINSTALL_FILES =
+
+$(PROJECT_INCLUDE)/rtems/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems
+ @: > $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/asm.h: asm.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/asm.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/asm.h
+
+$(PROJECT_INCLUDE)/rtems/score/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems/score
+ @: > $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/score/cpu.h: rtems/score/cpu.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/cpu.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/cpu.h
+
+$(PROJECT_INCLUDE)/rtems/score/types.h: rtems/score/types.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/types.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/types.h
+
+$(PROJECT_INCLUDE)/rtems/score/sh.h: rtems/score/sh.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/sh.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/sh.h
+
+$(PROJECT_INCLUDE)/rtems/score/sh_io.h: rtems/score/sh_io.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/sh_io.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/sh_io.h
+
+CLEANFILES += $(PREINSTALL_FILES)
+DISTCLEANFILES = $(PREINSTALL_DIRS)
+
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/score/cpu/sh/asm.h b/cpukit/score/cpu/sh/asm.h
new file mode 100644
index 0000000000..9a8a272d4c
--- /dev/null
+++ b/cpukit/score/cpu/sh/asm.h
@@ -0,0 +1,136 @@
+/* asm.h
+ *
+ * This include file attempts to address the problems
+ * caused by incompatible flavors of assemblers and
+ * toolsets. It primarily addresses variations in the
+ * use of leading underscores on symbols and the requirement
+ * that register names be preceded by a %.
+ *
+ * Authors: Ralf Corsepius (corsepiu@faw.uni-ulm.de) and
+ * Bernd Becker (becker@faw.uni-ulm.de)
+ *
+ * NOTE: The spacing in the use of these macros
+ * is critical to them working as advertised.
+ *
+ * COPYRIGHT:
+ *
+ * This file is based on similar code found in newlib available
+ * from ftp.cygnus.com. The file which was used had no copyright
+ * notice. This file is freely distributable as long as the source
+ * of the file is noted. This file is:
+ *
+ *
+ * COPYRIGHT (c) 1997-1998, FAW Ulm, Germany
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *
+ * COPYRIGHT (c) 1998-2001.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __CPU_SH_ASM_h
+#define __CPU_SH_ASM_h
+
+/*
+ * Indicate we are in an assembly file and get the basic CPU definitions.
+ */
+
+#ifndef ASM
+#define ASM
+#endif
+
+#include <rtems/score/cpuopts.h>
+#include <rtems/score/sh.h>
+
+/*
+ * Recent versions of GNU cpp define variables which indicate the
+ * need for underscores and percents. If not using GNU cpp or
+ * the version does not support this, then you will obviously
+ * have to define these as appropriate.
+ */
+
+#ifndef __USER_LABEL_PREFIX__
+#define __USER_LABEL_PREFIX__ _
+#endif
+
+#ifndef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__
+#endif
+
+/* ANSI concatenation macros. */
+
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+/* Use the right prefix for global labels. */
+
+#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+
+/* Use the right prefix for registers. */
+
+#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
+
+/*
+ * define macros for all of the registers on this CPU
+ *
+ * EXAMPLE: #define d0 REG (d0)
+ */
+#define r0 REG (r0)
+#define r1 REG (r1)
+#define r2 REG (r2)
+#define r3 REG (r3)
+#define r4 REG (r4)
+#define r5 REG (r5)
+#define r6 REG (r6)
+#define r7 REG (r7)
+#define r8 REG (r8)
+#define r9 REG (r9)
+#define r10 REG (r10)
+#define r11 REG (r11)
+#define r12 REG (r12)
+#define r13 REG (r13)
+#define r14 REG (r14)
+#define r15 REG (r15)
+#define vbr REG (vbr)
+#define gbr REG (gbr)
+#define pr REG (pr)
+#define mach REG (mach)
+#define macl REG (macl)
+#define sr REG (sr)
+#define pc REG (pc)
+
+/*
+ * Define macros to handle section beginning and ends.
+ */
+
+
+#define BEGIN_CODE_DCL .text
+#define END_CODE_DCL
+#define BEGIN_DATA_DCL .data
+#define END_DATA_DCL
+#define BEGIN_CODE .text
+#define END_CODE
+#define BEGIN_DATA
+#define END_DATA
+#define BEGIN_BSS
+#define END_BSS
+#define END
+
+/*
+ * Following must be tailor for a particular flavor of the C compiler.
+ * They may need to put underscores in front of the symbols.
+ */
+
+#define PUBLIC(sym) .global SYM (sym)
+#define EXTERN(sym) .global SYM (sym)
+
+#endif
diff --git a/cpukit/score/cpu/sh/cpu.c b/cpukit/score/cpu/sh/cpu.c
new file mode 100644
index 0000000000..aa646946e6
--- /dev/null
+++ b/cpukit/score/cpu/sh/cpu.c
@@ -0,0 +1,254 @@
+/*
+ * This file contains information pertaining to the Hitachi SH
+ * processor.
+ *
+ * Authors: Ralf Corsepius (corsepiu@faw.uni-ulm.de) and
+ * Bernd Becker (becker@faw.uni-ulm.de)
+ *
+ * COPYRIGHT (c) 1997-1998, FAW Ulm, Germany
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *
+ * COPYRIGHT (c) 1998-2001.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/sh_io.h>
+#include <rtems/score/cpu.h>
+#include <rtems/score/sh.h>
+
+/* referenced in start.S */
+extern proc_ptr vectab[] ;
+
+proc_ptr vectab[256] ;
+
+extern proc_ptr _Hardware_isr_Table[];
+
+/* _CPU_Initialize
+ *
+ * This routine performs processor dependent initialization.
+ *
+ * INPUT PARAMETERS:
+ * cpu_table - CPU table to initialize
+ * thread_dispatch - address of disptaching routine
+ */
+
+
+void _CPU_Initialize(
+ rtems_cpu_table *cpu_table,
+ void (*thread_dispatch) /* ignored on this CPU */
+)
+{
+ register uint32_t level = 0;
+
+ /*
+ * The thread_dispatch argument is the address of the entry point
+ * for the routine called at the end of an ISR once it has been
+ * decided a context switch is necessary. On some compilation
+ * systems it is difficult to call a high-level language routine
+ * from assembly. This allows us to trick these systems.
+ *
+ * If you encounter this problem save the entry point in a CPU
+ * dependent variable.
+ */
+
+ _CPU_Thread_dispatch_pointer = thread_dispatch;
+
+ /*
+ * If there is not an easy way to initialize the FP context
+ * during Context_Initialize, then it is usually easier to
+ * save an "uninitialized" FP context here and copy it to
+ * the task's during Context_Initialize.
+ */
+
+ /* FP context initialization support goes here */
+ /* FIXME: When not to use SH4_FPSCR_PR ? */
+#ifdef __SH4__
+ _CPU_Null_fp_context.fpscr = SH4_FPSCR_DN | SH4_FPSCR_RM | SH4_FPSCR_PR;
+#endif
+#ifdef __SH3E__
+ /* FIXME: Wild guess :) */
+ _CPU_Null_fp_context.fpscr = SH4_FPSCR_DN | SH4_FPSCR_RM;
+#endif
+
+ _CPU_Table = *cpu_table;
+
+ /* enable interrupts */
+ _CPU_ISR_Set_level( level);
+}
+
+/*PAGE
+ *
+ * _CPU_ISR_Get_level
+ */
+
+uint32_t _CPU_ISR_Get_level( void )
+{
+ /*
+ * This routine returns the current interrupt level.
+ */
+
+ register uint32_t _mask ;
+
+ sh_get_interrupt_level( _mask );
+
+ return ( _mask);
+}
+
+/*PAGE
+ *
+ * _CPU_ISR_install_raw_handler
+ */
+
+void _CPU_ISR_install_raw_handler(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+)
+{
+ /*
+ * This is where we install the interrupt handler into the "raw" interrupt
+ * table used by the CPU to dispatch interrupt handlers.
+ */
+ volatile proc_ptr *vbr ;
+
+#if SH_PARANOID_ISR
+ uint32_t level ;
+
+ sh_disable_interrupts( level );
+#endif
+
+ /* get vbr */
+ asm ( "stc vbr,%0" : "=r" (vbr) );
+
+ *old_handler = vbr[vector] ;
+ vbr[vector] = new_handler ;
+
+#if SH_PARANOID_ISR
+ sh_enable_interrupts( level );
+#endif
+}
+
+
+/*PAGE
+ *
+ * _CPU_ISR_install_vector
+ *
+ * This kernel routine installs the RTEMS handler for the
+ * specified vector.
+ *
+ * Input parameters:
+ * vector - interrupt vector number
+ * old_handler - former ISR for this vector number
+ * new_handler - replacement ISR for this vector number
+ *
+ * Output parameters: NONE
+ *
+ */
+
+#if defined(__sh1__) || defined(__sh2__)
+void _CPU_ISR_install_vector(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+)
+{
+ proc_ptr ignored ;
+#if 0
+ if(( vector <= 113) && ( vector >= 11))
+ {
+#endif
+ *old_handler = _ISR_Vector_table[ vector ];
+
+ /*
+ * If the interrupt vector table is a table of pointer to isr entry
+ * points, then we need to install the appropriate RTEMS interrupt
+ * handler for this vector number.
+ */
+ _CPU_ISR_install_raw_handler(vector,
+ _Hardware_isr_Table[vector],
+ &ignored );
+
+ /*
+ * We put the actual user ISR address in '_ISR_Vector_table'.
+ * This will be used by __ISR_Handler so the user gets control.
+ */
+
+ _ISR_Vector_table[ vector ] = new_handler;
+#if 0
+ }
+#endif
+}
+#endif /* _CPU_ISR_install_vector */
+
+/*PAGE
+ *
+ * _CPU_Thread_Idle_body
+ *
+ * NOTES:
+ *
+ * 1. This is the same as the regular CPU independent algorithm.
+ *
+ * 2. If you implement this using a "halt", "idle", or "shutdown"
+ * instruction, then don't forget to put it in an infinite loop.
+ *
+ * 3. Be warned. Some processors with onboard DMA have been known
+ * to stop the DMA if the CPU were put in IDLE mode. This might
+ * also be a problem with other on-chip peripherals. So use this
+ * hook with caution.
+ */
+
+#if (CPU_PROVIDES_IDLE_THREAD_BODY == TRUE)
+void _CPU_Thread_Idle_body( void )
+{
+
+ for( ; ; )
+ {
+ asm volatile("nop");
+ }
+ /* insert your "halt" instruction here */ ;
+}
+#endif
+
+#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
+
+uint8_t _bit_set_table[16] =
+ { 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 2, 2, 1,0};
+
+
+#endif
+
+void _CPU_Context_Initialize(
+ Context_Control *_the_context,
+ void *_stack_base,
+ uint32_t _size,
+ uint32_t _isr,
+ void (*_entry_point)(void),
+ int _is_fp )
+{
+ _the_context->r15 = (uint32_t *) ((uint32_t ) (_stack_base) + (_size) );
+#if defined(__sh1__) || defined(__sh2__)
+ _the_context->sr = (_isr << 4) & 0x00f0 ;
+#else
+ _the_context->sr = SH4_SR_MD | ((_isr << 4) & 0x00f0);
+#endif
+ _the_context->pr = (uint32_t *) _entry_point ;
+
+
+#if 0 && SH_HAS_FPU
+ /* Disable FPU if it is non-fp task */
+ if(!_is_fp)
+ _the_context->sr |= SH4_SR_FD;
+#endif
+}
diff --git a/cpukit/score/cpu/sh/rtems/asm.h b/cpukit/score/cpu/sh/rtems/asm.h
new file mode 100644
index 0000000000..9a8a272d4c
--- /dev/null
+++ b/cpukit/score/cpu/sh/rtems/asm.h
@@ -0,0 +1,136 @@
+/* asm.h
+ *
+ * This include file attempts to address the problems
+ * caused by incompatible flavors of assemblers and
+ * toolsets. It primarily addresses variations in the
+ * use of leading underscores on symbols and the requirement
+ * that register names be preceded by a %.
+ *
+ * Authors: Ralf Corsepius (corsepiu@faw.uni-ulm.de) and
+ * Bernd Becker (becker@faw.uni-ulm.de)
+ *
+ * NOTE: The spacing in the use of these macros
+ * is critical to them working as advertised.
+ *
+ * COPYRIGHT:
+ *
+ * This file is based on similar code found in newlib available
+ * from ftp.cygnus.com. The file which was used had no copyright
+ * notice. This file is freely distributable as long as the source
+ * of the file is noted. This file is:
+ *
+ *
+ * COPYRIGHT (c) 1997-1998, FAW Ulm, Germany
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *
+ * COPYRIGHT (c) 1998-2001.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __CPU_SH_ASM_h
+#define __CPU_SH_ASM_h
+
+/*
+ * Indicate we are in an assembly file and get the basic CPU definitions.
+ */
+
+#ifndef ASM
+#define ASM
+#endif
+
+#include <rtems/score/cpuopts.h>
+#include <rtems/score/sh.h>
+
+/*
+ * Recent versions of GNU cpp define variables which indicate the
+ * need for underscores and percents. If not using GNU cpp or
+ * the version does not support this, then you will obviously
+ * have to define these as appropriate.
+ */
+
+#ifndef __USER_LABEL_PREFIX__
+#define __USER_LABEL_PREFIX__ _
+#endif
+
+#ifndef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__
+#endif
+
+/* ANSI concatenation macros. */
+
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+/* Use the right prefix for global labels. */
+
+#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+
+/* Use the right prefix for registers. */
+
+#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
+
+/*
+ * define macros for all of the registers on this CPU
+ *
+ * EXAMPLE: #define d0 REG (d0)
+ */
+#define r0 REG (r0)
+#define r1 REG (r1)
+#define r2 REG (r2)
+#define r3 REG (r3)
+#define r4 REG (r4)
+#define r5 REG (r5)
+#define r6 REG (r6)
+#define r7 REG (r7)
+#define r8 REG (r8)
+#define r9 REG (r9)
+#define r10 REG (r10)
+#define r11 REG (r11)
+#define r12 REG (r12)
+#define r13 REG (r13)
+#define r14 REG (r14)
+#define r15 REG (r15)
+#define vbr REG (vbr)
+#define gbr REG (gbr)
+#define pr REG (pr)
+#define mach REG (mach)
+#define macl REG (macl)
+#define sr REG (sr)
+#define pc REG (pc)
+
+/*
+ * Define macros to handle section beginning and ends.
+ */
+
+
+#define BEGIN_CODE_DCL .text
+#define END_CODE_DCL
+#define BEGIN_DATA_DCL .data
+#define END_DATA_DCL
+#define BEGIN_CODE .text
+#define END_CODE
+#define BEGIN_DATA
+#define END_DATA
+#define BEGIN_BSS
+#define END_BSS
+#define END
+
+/*
+ * Following must be tailor for a particular flavor of the C compiler.
+ * They may need to put underscores in front of the symbols.
+ */
+
+#define PUBLIC(sym) .global SYM (sym)
+#define EXTERN(sym) .global SYM (sym)
+
+#endif
diff --git a/cpukit/score/cpu/sh/rtems/score/cpu.h b/cpukit/score/cpu/sh/rtems/score/cpu.h
new file mode 100644
index 0000000000..db209875b7
--- /dev/null
+++ b/cpukit/score/cpu/sh/rtems/score/cpu.h
@@ -0,0 +1,945 @@
+/*
+ * This include file contains information pertaining to the Hitachi SH
+ * processor.
+ *
+ * Authors: Ralf Corsepius (corsepiu@faw.uni-ulm.de) and
+ * Bernd Becker (becker@faw.uni-ulm.de)
+ *
+ * COPYRIGHT (c) 1997-1998, FAW Ulm, Germany
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *
+ * COPYRIGHT (c) 1998-2001.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef _SH_CPU_h
+#define _SH_CPU_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/sh.h> /* pick up machine definitions */
+#ifndef ASM
+#include <rtems/score/types.h>
+#endif
+#if 0 && defined(__SH4__)
+#include <rtems/score/sh4_regs.h>
+#endif
+
+/* conditional compilation parameters */
+
+/*
+ * Should the calls to _Thread_Enable_dispatch be inlined?
+ *
+ * If TRUE, then they are inlined.
+ * If FALSE, then a subroutine call is made.
+ *
+ * Basically this is an example of the classic trade-off of size
+ * versus speed. Inlining the call (TRUE) typically increases the
+ * size of RTEMS while speeding up the enabling of dispatching.
+ * [NOTE: In general, the _Thread_Dispatch_disable_level will
+ * only be 0 or 1 unless you are in an interrupt handler and that
+ * interrupt handler invokes the executive.] When not inlined
+ * something calls _Thread_Enable_dispatch which in turns calls
+ * _Thread_Dispatch. If the enable dispatch is inlined, then
+ * one subroutine call is avoided entirely.]
+ */
+
+#define CPU_INLINE_ENABLE_DISPATCH FALSE
+
+/*
+ * Should the body of the search loops in _Thread_queue_Enqueue_priority
+ * be unrolled one time? In unrolled each iteration of the loop examines
+ * two "nodes" on the chain being searched. Otherwise, only one node
+ * is examined per iteration.
+ *
+ * If TRUE, then the loops are unrolled.
+ * If FALSE, then the loops are not unrolled.
+ *
+ * The primary factor in making this decision is the cost of disabling
+ * and enabling interrupts (_ISR_Flash) versus the cost of rest of the
+ * body of the loop. On some CPUs, the flash is more expensive than
+ * one iteration of the loop body. In this case, it might be desirable
+ * to unroll the loop. It is important to note that on some CPUs, this
+ * code is the longest interrupt disable period in RTEMS. So it is
+ * necessary to strike a balance when setting this parameter.
+ */
+
+#define CPU_UNROLL_ENQUEUE_PRIORITY TRUE
+
+/*
+ * Does RTEMS manage a dedicated interrupt stack in software?
+ *
+ * If TRUE, then a stack is allocated in _ISR_Handler_initialization.
+ * If FALSE, nothing is done.
+ *
+ * If the CPU supports a dedicated interrupt stack in hardware,
+ * then it is generally the responsibility of the BSP to allocate it
+ * and set it up.
+ *
+ * If the CPU does not support a dedicated interrupt stack, then
+ * the porter has two options: (1) execute interrupts on the
+ * stack of the interrupted task, and (2) have RTEMS manage a dedicated
+ * interrupt stack.
+ *
+ * If this is TRUE, CPU_ALLOCATE_INTERRUPT_STACK should also be TRUE.
+ *
+ * Only one of CPU_HAS_SOFTWARE_INTERRUPT_STACK and
+ * CPU_HAS_HARDWARE_INTERRUPT_STACK should be set to TRUE. It is
+ * possible that both are FALSE for a particular CPU. Although it
+ * is unclear what that would imply about the interrupt processing
+ * procedure on that CPU.
+ */
+
+#define CPU_HAS_SOFTWARE_INTERRUPT_STACK TRUE
+#define CPU_HAS_HARDWARE_INTERRUPT_STACK FALSE
+
+/*
+ * We define the interrupt stack in the linker script
+ */
+#define CPU_ALLOCATE_INTERRUPT_STACK FALSE
+
+/*
+ * Does the RTEMS invoke the user's ISR with the vector number and
+ * a pointer to the saved interrupt frame (1) or just the vector
+ * number (0)?
+ */
+
+#define CPU_ISR_PASSES_FRAME_POINTER 0
+
+/*
+ * Does the CPU have hardware floating point?
+ *
+ * If TRUE, then the RTEMS_FLOATING_POINT task attribute is supported.
+ * If FALSE, then the RTEMS_FLOATING_POINT task attribute is ignored.
+ *
+ * We currently support sh1 only, which has no FPU, other SHes have an FPU
+ *
+ * The macro name "NO_CPU_HAS_FPU" should be made CPU specific.
+ * It indicates whether or not this CPU model has FP support. For
+ * example, it would be possible to have an i386_nofp CPU model
+ * which set this to false to indicate that you have an i386 without
+ * an i387 and wish to leave floating point support out of RTEMS.
+ */
+
+#if SH_HAS_FPU
+#define CPU_HARDWARE_FP TRUE
+#define CPU_SOFTWARE_FP FALSE
+#else
+#define CPU_SOFTWARE_FP FALSE
+#define CPU_HARDWARE_FP FALSE
+#endif
+
+/*
+ * Are all tasks RTEMS_FLOATING_POINT tasks implicitly?
+ *
+ * If TRUE, then the RTEMS_FLOATING_POINT task attribute is assumed.
+ * If FALSE, then the RTEMS_FLOATING_POINT task attribute is followed.
+ *
+ * If CPU_HARDWARE_FP is FALSE, then this should be FALSE as well.
+ */
+
+#if SH_HAS_FPU
+#define CPU_ALL_TASKS_ARE_FP TRUE
+#else
+#define CPU_ALL_TASKS_ARE_FP FALSE
+#endif
+
+/*
+ * Should the IDLE task have a floating point context?
+ *
+ * If TRUE, then the IDLE task is created as a RTEMS_FLOATING_POINT task
+ * and it has a floating point context which is switched in and out.
+ * If FALSE, then the IDLE task does not have a floating point context.
+ *
+ * Setting this to TRUE negatively impacts the time required to preempt
+ * the IDLE task from an interrupt because the floating point context
+ * must be saved as part of the preemption.
+ */
+
+#if SH_HAS_FPU
+#define CPU_IDLE_TASK_IS_FP TRUE
+#else
+#define CPU_IDLE_TASK_IS_FP FALSE
+#endif
+
+/*
+ * Should the saving of the floating point registers be deferred
+ * until a context switch is made to another different floating point
+ * task?
+ *
+ * If TRUE, then the floating point context will not be stored until
+ * necessary. It will remain in the floating point registers and not
+ * disturned until another floating point task is switched to.
+ *
+ * If FALSE, then the floating point context is saved when a floating
+ * point task is switched out and restored when the next floating point
+ * task is restored. The state of the floating point registers between
+ * those two operations is not specified.
+ *
+ * If the floating point context does NOT have to be saved as part of
+ * interrupt dispatching, then it should be safe to set this to TRUE.
+ *
+ * Setting this flag to TRUE results in using a different algorithm
+ * for deciding when to save and restore the floating point context.
+ * The deferred FP switch algorithm minimizes the number of times
+ * the FP context is saved and restored. The FP context is not saved
+ * until a context switch is made to another, different FP task.
+ * Thus in a system with only one FP task, the FP context will never
+ * be saved or restored.
+ */
+
+#if SH_HAS_FPU
+#define CPU_USE_DEFERRED_FP_SWITCH FALSE
+#else
+#define CPU_USE_DEFERRED_FP_SWITCH TRUE
+#endif
+
+/*
+ * Does this port provide a CPU dependent IDLE task implementation?
+ *
+ * If TRUE, then the routine _CPU_Thread_Idle_body
+ * must be provided and is the default IDLE thread body instead of
+ * _CPU_Thread_Idle_body.
+ *
+ * If FALSE, then use the generic IDLE thread body if the BSP does
+ * not provide one.
+ *
+ * This is intended to allow for supporting processors which have
+ * a low power or idle mode. When the IDLE thread is executed, then
+ * the CPU can be powered down.
+ *
+ * The order of precedence for selecting the IDLE thread body is:
+ *
+ * 1. BSP provided
+ * 2. CPU dependent (if provided)
+ * 3. generic (if no BSP and no CPU dependent)
+ */
+
+#define CPU_PROVIDES_IDLE_THREAD_BODY TRUE
+
+/*
+ * Does the stack grow up (toward higher addresses) or down
+ * (toward lower addresses)?
+ *
+ * If TRUE, then the grows upward.
+ * If FALSE, then the grows toward smaller addresses.
+ */
+
+#define CPU_STACK_GROWS_UP FALSE
+
+/*
+ * The following is the variable attribute used to force alignment
+ * of critical RTEMS structures. On some processors it may make
+ * sense to have these aligned on tighter boundaries than
+ * the minimum requirements of the compiler in order to have as
+ * much of the critical data area as possible in a cache line.
+ *
+ * The placement of this macro in the declaration of the variables
+ * is based on the syntactically requirements of the GNU C
+ * "__attribute__" extension. For example with GNU C, use
+ * the following to force a structures to a 32 byte boundary.
+ *
+ * __attribute__ ((aligned (32)))
+ *
+ * NOTE: Currently only the Priority Bit Map table uses this feature.
+ * To benefit from using this, the data must be heavily
+ * used so it will stay in the cache and used frequently enough
+ * in the executive to justify turning this on.
+ */
+
+#define CPU_STRUCTURE_ALIGNMENT __attribute__ ((aligned(16)))
+
+/*
+ * Define what is required to specify how the network to host conversion
+ * routines are handled.
+ *
+ * NOTE: SHes can be big or little endian, the default is big endian
+ */
+
+#define CPU_HAS_OWN_HOST_TO_NETWORK_ROUTINES FALSE
+
+/* __LITTLE_ENDIAN__ is defined if -ml is given to gcc */
+#if defined(__LITTLE_ENDIAN__)
+#define CPU_BIG_ENDIAN FALSE
+#define CPU_LITTLE_ENDIAN TRUE
+#else
+#define CPU_BIG_ENDIAN TRUE
+#define CPU_LITTLE_ENDIAN FALSE
+#endif
+
+/*
+ * The following defines the number of bits actually used in the
+ * interrupt field of the task mode. How those bits map to the
+ * CPU interrupt levels is defined by the routine _CPU_ISR_Set_level().
+ */
+
+#define CPU_MODES_INTERRUPT_MASK 0x0000000f
+
+/*
+ * Processor defined structures
+ *
+ * Examples structures include the descriptor tables from the i386
+ * and the processor control structure on the i960ca.
+ */
+
+/* may need to put some structures here. */
+
+/*
+ * Contexts
+ *
+ * Generally there are 2 types of context to save.
+ * 1. Interrupt registers to save
+ * 2. Task level registers to save
+ *
+ * This means we have the following 3 context items:
+ * 1. task level context stuff:: Context_Control
+ * 2. floating point task stuff:: Context_Control_fp
+ * 3. special interrupt level context :: Context_Control_interrupt
+ *
+ * On some processors, it is cost-effective to save only the callee
+ * preserved registers during a task context switch. This means
+ * that the ISR code needs to save those registers which do not
+ * persist across function calls. It is not mandatory to make this
+ * distinctions between the caller/callee saves registers for the
+ * purpose of minimizing context saved during task switch and on interrupts.
+ * If the cost of saving extra registers is minimal, simplicity is the
+ * choice. Save the same context on interrupt entry as for tasks in
+ * this case.
+ *
+ * Additionally, if gdb is to be made aware of RTEMS tasks for this CPU, then
+ * care should be used in designing the context area.
+ *
+ * On some CPUs with hardware floating point support, the Context_Control_fp
+ * structure will not be used or it simply consist of an array of a
+ * fixed number of bytes. This is done when the floating point context
+ * is dumped by a "FP save context" type instruction and the format
+ * is not really defined by the CPU. In this case, there is no need
+ * to figure out the exact format -- only the size. Of course, although
+ * this is enough information for RTEMS, it is probably not enough for
+ * a debugger such as gdb. But that is another problem.
+ */
+
+typedef struct {
+ uint32_t *r15; /* stack pointer */
+
+ uint32_t macl;
+ uint32_t mach;
+ uint32_t *pr;
+
+ uint32_t *r14; /* frame pointer/call saved */
+
+ uint32_t r13; /* call saved */
+ uint32_t r12; /* call saved */
+ uint32_t r11; /* call saved */
+ uint32_t r10; /* call saved */
+ uint32_t r9; /* call saved */
+ uint32_t r8; /* call saved */
+
+ uint32_t *r7; /* arg in */
+ uint32_t *r6; /* arg in */
+
+#if 0
+ uint32_t *r5; /* arg in */
+ uint32_t *r4; /* arg in */
+#endif
+
+ uint32_t *r3; /* scratch */
+ uint32_t *r2; /* scratch */
+ uint32_t *r1; /* scratch */
+
+ uint32_t *r0; /* arg return */
+
+ uint32_t gbr;
+ uint32_t sr;
+
+} Context_Control;
+
+typedef struct {
+#if SH_HAS_FPU
+#ifdef SH4_USE_X_REGISTERS
+ union {
+ float f[16];
+ double d[8];
+ } x;
+#endif
+ union {
+ float f[16];
+ double d[8];
+ } r;
+ float fpul; /* fp communication register */
+ uint32_t fpscr; /* fp control register */
+#endif /* SH_HAS_FPU */
+} Context_Control_fp;
+
+typedef struct {
+} CPU_Interrupt_frame;
+
+
+/*
+ * The following table contains the information required to configure
+ * the SH processor specific parameters.
+ */
+
+typedef struct {
+ void (*pretasking_hook)( void );
+ void (*predriver_hook)( void );
+ void (*postdriver_hook)( void );
+ void (*idle_task)( void );
+ boolean do_zero_of_workspace;
+ uint32_t idle_task_stack_size;
+ uint32_t interrupt_stack_size;
+ uint32_t extra_mpci_receive_server_stack;
+ void * (*stack_allocate_hook)( uint32_t );
+ void (*stack_free_hook)( void* );
+ /* end of fields required on all CPUs */
+ uint32_t clicks_per_second ; /* cpu frequency in Hz */
+} rtems_cpu_table;
+
+/*
+ * Macros to access required entires in the CPU Table are in
+ * the file rtems/system.h.
+ */
+
+/*
+ * Macros to access SH specific additions to the CPU Table
+ */
+
+#define rtems_cpu_configuration_get_clicks_per_second() \
+ (_CPU_Table.clicks_per_second)
+
+/*
+ * This variable is optional. It is used on CPUs on which it is difficult
+ * to generate an "uninitialized" FP context. It is filled in by
+ * _CPU_Initialize and copied into the task's FP context area during
+ * _CPU_Context_Initialize.
+ */
+
+#if SH_HAS_FPU
+SCORE_EXTERN Context_Control_fp _CPU_Null_fp_context;
+#endif
+
+/*
+ * On some CPUs, RTEMS supports a software managed interrupt stack.
+ * This stack is allocated by the Interrupt Manager and the switch
+ * is performed in _ISR_Handler. These variables contain pointers
+ * to the lowest and highest addresses in the chunk of memory allocated
+ * for the interrupt stack. Since it is unknown whether the stack
+ * grows up or down (in general), this give the CPU dependent
+ * code the option of picking the version it wants to use.
+ *
+ * NOTE: These two variables are required if the macro
+ * CPU_HAS_SOFTWARE_INTERRUPT_STACK is defined as TRUE.
+ */
+
+SCORE_EXTERN void *_CPU_Interrupt_stack_low;
+SCORE_EXTERN void *_CPU_Interrupt_stack_high;
+
+/*
+ * With some compilation systems, it is difficult if not impossible to
+ * call a high-level language routine from assembly language. This
+ * is especially true of commercial Ada compilers and name mangling
+ * C++ ones. This variable can be optionally defined by the CPU porter
+ * and contains the address of the routine _Thread_Dispatch. This
+ * can make it easier to invoke that routine at the end of the interrupt
+ * sequence (if a dispatch is necessary).
+ */
+
+SCORE_EXTERN void (*_CPU_Thread_dispatch_pointer)();
+
+/*
+ * Nothing prevents the porter from declaring more CPU specific variables.
+ */
+
+/* XXX: if needed, put more variables here */
+SCORE_EXTERN void CPU_delay( uint32_t microseconds );
+
+/*
+ * The size of the floating point context area. On some CPUs this
+ * will not be a "sizeof" because the format of the floating point
+ * area is not defined -- only the size is. This is usually on
+ * CPUs with a "floating point save context" instruction.
+ */
+
+#define CPU_CONTEXT_FP_SIZE sizeof( Context_Control_fp )
+
+/*
+ * Amount of extra stack (above minimum stack size) required by
+ * MPCI receive server thread. Remember that in a multiprocessor
+ * system this thread must exist and be able to process all directives.
+ */
+
+#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 0
+
+/*
+ * This defines the number of entries in the ISR_Vector_table managed
+ * by RTEMS.
+ */
+
+#define CPU_INTERRUPT_NUMBER_OF_VECTORS 256
+#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1)
+
+/*
+ * This is defined if the port has a special way to report the ISR nesting
+ * level. Most ports maintain the variable _ISR_Nest_level.
+ */
+
+#define CPU_PROVIDES_ISR_IS_IN_PROGRESS FALSE
+
+/*
+ * Should be large enough to run all RTEMS tests. This insures
+ * that a "reasonable" small application should not have any problems.
+ *
+ * We have been able to run the sptests with this value, but have not
+ * been able to run the tmtest suite.
+ */
+
+#define CPU_STACK_MINIMUM_SIZE 4096
+
+/*
+ * CPU's worst alignment requirement for data types on a byte boundary. This
+ * alignment does not take into account the requirements for the stack.
+ */
+#if defined(__SH4__)
+/* FIXME: sh3 and SH3E? */
+#define CPU_ALIGNMENT 8
+#else
+#define CPU_ALIGNMENT 4
+#endif
+
+/*
+ * This number corresponds to the byte alignment requirement for the
+ * heap handler. This alignment requirement may be stricter than that
+ * for the data types alignment specified by CPU_ALIGNMENT. It is
+ * common for the heap to follow the same alignment requirement as
+ * CPU_ALIGNMENT. If the CPU_ALIGNMENT is strict enough for the heap,
+ * then this should be set to CPU_ALIGNMENT.
+ *
+ * NOTE: This does not have to be a power of 2. It does have to
+ * be greater or equal to than CPU_ALIGNMENT.
+ */
+
+#define CPU_HEAP_ALIGNMENT CPU_ALIGNMENT
+
+/*
+ * This number corresponds to the byte alignment requirement for memory
+ * buffers allocated by the partition manager. This alignment requirement
+ * may be stricter than that for the data types alignment specified by
+ * CPU_ALIGNMENT. It is common for the partition to follow the same
+ * alignment requirement as CPU_ALIGNMENT. If the CPU_ALIGNMENT is strict
+ * enough for the partition, then this should be set to CPU_ALIGNMENT.
+ *
+ * NOTE: This does not have to be a power of 2. It does have to
+ * be greater or equal to than CPU_ALIGNMENT.
+ */
+
+#define CPU_PARTITION_ALIGNMENT CPU_ALIGNMENT
+
+/*
+ * This number corresponds to the byte alignment requirement for the
+ * stack. This alignment requirement may be stricter than that for the
+ * data types alignment specified by CPU_ALIGNMENT. If the CPU_ALIGNMENT
+ * is strict enough for the stack, then this should be set to 0.
+ *
+ * NOTE: This must be a power of 2 either 0 or greater than CPU_ALIGNMENT.
+ */
+
+#define CPU_STACK_ALIGNMENT CPU_ALIGNMENT
+
+/*
+ * ISR handler macros
+ */
+
+/*
+ * Support routine to initialize the RTEMS vector table after it is allocated.
+ *
+ * SH Specific Information: NONE
+ */
+
+#define _CPU_Initialize_vectors()
+
+/*
+ * Disable all interrupts for an RTEMS critical section. The previous
+ * level is returned in _level.
+ */
+
+#define _CPU_ISR_Disable( _level) \
+ sh_disable_interrupts( _level )
+
+/*
+ * Enable interrupts to the previous level (returned by _CPU_ISR_Disable).
+ * This indicates the end of an RTEMS critical section. The parameter
+ * _level is not modified.
+ */
+
+#define _CPU_ISR_Enable( _level) \
+ sh_enable_interrupts( _level)
+
+/*
+ * This temporarily restores the interrupt to _level before immediately
+ * disabling them again. This is used to divide long RTEMS critical
+ * sections into two or more parts. The parameter _level is not
+ * modified.
+ */
+
+#define _CPU_ISR_Flash( _level) \
+ sh_flash_interrupts( _level)
+
+/*
+ * Map interrupt level in task mode onto the hardware that the CPU
+ * actually provides. Currently, interrupt levels which do not
+ * map onto the CPU in a generic fashion are undefined. Someday,
+ * it would be nice if these were "mapped" by the application
+ * via a callout. For example, m68k has 8 levels 0 - 7, levels
+ * 8 - 255 would be available for bsp/application specific meaning.
+ * This could be used to manage a programmable interrupt controller
+ * via the rtems_task_mode directive.
+ */
+
+#define _CPU_ISR_Set_level( _newlevel) \
+ sh_set_interrupt_level(_newlevel)
+
+uint32_t _CPU_ISR_Get_level( void );
+
+/* end of ISR handler macros */
+
+/* Context handler macros */
+
+/*
+ * Initialize the context to a state suitable for starting a
+ * task after a context restore operation. Generally, this
+ * involves:
+ *
+ * - setting a starting address
+ * - preparing the stack
+ * - preparing the stack and frame pointers
+ * - setting the proper interrupt level in the context
+ * - initializing the floating point context
+ *
+ * This routine generally does not set any unnecessary register
+ * in the context. The state of the "general data" registers is
+ * undefined at task start time.
+ *
+ * NOTE: This is_fp parameter is TRUE if the thread is to be a floating
+ * point thread. This is typically only used on CPUs where the
+ * FPU may be easily disabled by software such as on the SPARC
+ * where the PSR contains an enable FPU bit.
+ */
+
+/*
+ * FIXME: defined as a function for debugging - should be a macro
+ */
+SCORE_EXTERN void _CPU_Context_Initialize(
+ Context_Control *_the_context,
+ void *_stack_base,
+ uint32_t _size,
+ uint32_t _isr,
+ void (*_entry_point)(void),
+ int _is_fp );
+
+/*
+ * This routine is responsible for somehow restarting the currently
+ * executing task. If you are lucky, then all that is necessary
+ * is restoring the context. Otherwise, there will need to be
+ * a special assembly routine which does something special in this
+ * case. Context_Restore should work most of the time. It will
+ * not work if restarting self conflicts with the stack frame
+ * assumptions of restoring a context.
+ */
+
+#define _CPU_Context_Restart_self( _the_context ) \
+ _CPU_Context_restore( (_the_context) );
+
+/*
+ * The purpose of this macro is to allow the initial pointer into
+ * a floating point context area (used to save the floating point
+ * context) to be at an arbitrary place in the floating point
+ * context area.
+ *
+ * This is necessary because some FP units are designed to have
+ * their context saved as a stack which grows into lower addresses.
+ * Other FP units can be saved by simply moving registers into offsets
+ * from the base of the context area. Finally some FP units provide
+ * a "dump context" instruction which could fill in from high to low
+ * or low to high based on the whim of the CPU designers.
+ */
+
+#define _CPU_Context_Fp_start( _base, _offset ) \
+ ( (void *) _Addresses_Add_offset( (_base), (_offset) ) )
+
+/*
+ * This routine initializes the FP context area passed to it to.
+ * There are a few standard ways in which to initialize the
+ * floating point context. The code included for this macro assumes
+ * that this is a CPU in which a "initial" FP context was saved into
+ * _CPU_Null_fp_context and it simply copies it to the destination
+ * context passed to it.
+ *
+ * Other models include (1) not doing anything, and (2) putting
+ * a "null FP status word" in the correct place in the FP context.
+ * SH1, SH2, SH3 have no FPU, but the SH3e and SH4 have.
+ */
+
+#if SH_HAS_FPU
+#define _CPU_Context_Initialize_fp( _destination ) \
+ do { \
+ *((Context_Control_fp *) *((void **) _destination)) = _CPU_Null_fp_context;\
+ } while(0)
+#else
+#define _CPU_Context_Initialize_fp( _destination ) \
+ { }
+#endif
+
+/* end of Context handler macros */
+
+/* Fatal Error manager macros */
+
+/*
+ * FIXME: Trap32 ???
+ *
+ * This routine copies _error into a known place -- typically a stack
+ * location or a register, optionally disables interrupts, and
+ * invokes a Trap32 Instruction which returns to the breakpoint
+ * routine of cmon.
+ */
+
+#ifdef BSP_FATAL_HALT
+ /* we manage the fatal error in the board support package */
+ void bsp_fatal_halt( uint32_t _error);
+#define _CPU_Fatal_halt( _error ) bsp_fatal_halt( _error)
+#else
+#define _CPU_Fatal_halt( _error)\
+{ \
+ asm volatile("mov.l %0,r0"::"m" (_error)); \
+ asm volatile("mov #1, r4"); \
+ asm volatile("trapa #34"); \
+}
+#endif
+
+/* end of Fatal Error manager macros */
+
+/* Bitfield handler macros */
+
+/*
+ * This routine sets _output to the bit number of the first bit
+ * set in _value. _value is of CPU dependent type Priority_Bit_map_control.
+ * This type may be either 16 or 32 bits wide although only the 16
+ * least significant bits will be used.
+ *
+ * There are a number of variables in using a "find first bit" type
+ * instruction.
+ *
+ * (1) What happens when run on a value of zero?
+ * (2) Bits may be numbered from MSB to LSB or vice-versa.
+ * (3) The numbering may be zero or one based.
+ * (4) The "find first bit" instruction may search from MSB or LSB.
+ *
+ * RTEMS guarantees that (1) will never happen so it is not a concern.
+ * (2),(3), (4) are handled by the macros _CPU_Priority_mask() and
+ * _CPU_Priority_bits_index(). These three form a set of routines
+ * which must logically operate together. Bits in the _value are
+ * set and cleared based on masks built by _CPU_Priority_mask().
+ * The basic major and minor values calculated by _Priority_Major()
+ * and _Priority_Minor() are "massaged" by _CPU_Priority_bits_index()
+ * to properly range between the values returned by the "find first bit"
+ * instruction. This makes it possible for _Priority_Get_highest() to
+ * calculate the major and directly index into the minor table.
+ * This mapping is necessary to ensure that 0 (a high priority major/minor)
+ * is the first bit found.
+ *
+ * This entire "find first bit" and mapping process depends heavily
+ * on the manner in which a priority is broken into a major and minor
+ * components with the major being the 4 MSB of a priority and minor
+ * the 4 LSB. Thus (0 << 4) + 0 corresponds to priority 0 -- the highest
+ * priority. And (15 << 4) + 14 corresponds to priority 254 -- the next
+ * to the lowest priority.
+ *
+ * If your CPU does not have a "find first bit" instruction, then
+ * there are ways to make do without it. Here are a handful of ways
+ * to implement this in software:
+ *
+ * - a series of 16 bit test instructions
+ * - a "binary search using if's"
+ * - _number = 0
+ * if _value > 0x00ff
+ * _value >>=8
+ * _number = 8;
+ *
+ * if _value > 0x0000f
+ * _value >=8
+ * _number += 4
+ *
+ * _number += bit_set_table[ _value ]
+ *
+ * where bit_set_table[ 16 ] has values which indicate the first
+ * bit set
+ */
+
+#define CPU_USE_GENERIC_BITFIELD_CODE TRUE
+#define CPU_USE_GENERIC_BITFIELD_DATA TRUE
+
+#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
+
+extern uint8_t _bit_set_table[];
+
+#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
+ { \
+ _output = 0;\
+ if(_value > 0x00ff) \
+ { _value >>= 8; _output = 8; } \
+ if(_value > 0x000f) \
+ { _output += 4; _value >>= 4; } \
+ _output += _bit_set_table[ _value]; }
+
+#endif
+
+/* end of Bitfield handler macros */
+
+/*
+ * This routine builds the mask which corresponds to the bit fields
+ * as searched by _CPU_Bitfield_Find_first_bit(). See the discussion
+ * for that routine.
+ */
+
+#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
+
+#define _CPU_Priority_Mask( _bit_number ) \
+ ( 1 << (_bit_number) )
+
+#endif
+
+/*
+ * This routine translates the bit numbers returned by
+ * _CPU_Bitfield_Find_first_bit() into something suitable for use as
+ * a major or minor component of a priority. See the discussion
+ * for that routine.
+ */
+
+#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
+
+#define _CPU_Priority_bits_index( _priority ) \
+ (_priority)
+
+#endif
+
+/* end of Priority handler macros */
+
+/* functions */
+
+/*
+ * _CPU_Initialize
+ *
+ * This routine performs CPU dependent initialization.
+ */
+
+void _CPU_Initialize(
+ rtems_cpu_table *cpu_table,
+ void (*thread_dispatch)
+);
+
+/*
+ * _CPU_ISR_install_raw_handler
+ *
+ * This routine installs a "raw" interrupt handler directly into the
+ * processor's vector table.
+ */
+
+void _CPU_ISR_install_raw_handler(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+);
+
+/*
+ * _CPU_ISR_install_vector
+ *
+ * This routine installs an interrupt vector.
+ */
+
+void _CPU_ISR_install_vector(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+);
+
+/*
+ * _CPU_Install_interrupt_stack
+ *
+ * This routine installs the hardware interrupt stack pointer.
+ *
+ * NOTE: It needs only be provided if CPU_HAS_HARDWARE_INTERRUPT_STACK
+ * is TRUE.
+ */
+
+void _CPU_Install_interrupt_stack( void );
+
+/*
+ * _CPU_Thread_Idle_body
+ *
+ * This routine is the CPU dependent IDLE thread body.
+ *
+ * NOTE: It need only be provided if CPU_PROVIDES_IDLE_THREAD_BODY
+ * is TRUE.
+ */
+
+void _CPU_Thread_Idle_body( void );
+
+/*
+ * _CPU_Context_switch
+ *
+ * This routine switches from the run context to the heir context.
+ */
+
+void _CPU_Context_switch(
+ Context_Control *run,
+ Context_Control *heir
+);
+
+/*
+ * _CPU_Context_restore
+ *
+ * This routine is generally used only to restart self in an
+ * efficient manner. It may simply be a label in _CPU_Context_switch.
+ */
+
+void _CPU_Context_restore(
+ Context_Control *new_context
+);
+
+/*
+ * _CPU_Context_save_fp
+ *
+ * This routine saves the floating point context passed to it.
+ */
+
+void _CPU_Context_save_fp(
+ void **fp_context_ptr
+);
+
+/*
+ * _CPU_Context_restore_fp
+ *
+ * This routine restores the floating point context passed to it.
+ */
+
+void _CPU_Context_restore_fp(
+ void **fp_context_ptr
+);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/score/cpu/sh/rtems/score/sh.h b/cpukit/score/cpu/sh/rtems/score/sh.h
new file mode 100644
index 0000000000..691332e540
--- /dev/null
+++ b/cpukit/score/cpu/sh/rtems/score/sh.h
@@ -0,0 +1,269 @@
+/* sh.h
+ *
+ * This include file contains information pertaining to the Hitachi SH
+ * processor.
+ *
+ * Authors: Ralf Corsepius (corsepiu@faw.uni-ulm.de) and
+ * Bernd Becker (becker@faw.uni-ulm.de)
+ *
+ * COPYRIGHT (c) 1997-1998, FAW Ulm, Germany
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
+ *
+ *
+ * COPYRIGHT (c) 1998-2001.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef _sh_h
+#define _sh_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This file contains the information required to build
+ * RTEMS for a particular member of the "SH" family.
+ *
+ * It does this by setting variables to indicate which implementation
+ * dependent features are present in a particular member of the family.
+ */
+
+/*
+ * Figure out all CPU Model Feature Flags based upon compiler
+ * predefines.
+ */
+
+#if defined(__SH3E__) || defined(__SH4__) || defined(__SH4_SINGLE_ONLY__)
+
+/*
+ * Define this if you want to use XD-registers.
+ * Then this registers will be saved/restored on context switch.
+ * ! They will not be saved/restored on interrupts!
+ */
+#define SH4_USE_X_REGISTERS 0
+
+#if defined(__LITTLE_ENDIAN__)
+#define SH_HAS_FPU 1
+#else
+/* FIXME: Context_Control_fp does not support big endian */
+#warning FPU not supported
+#define SH_HAS_FPU 0
+#endif
+
+#elif defined(__sh1__) || defined(__sh2__) || defined(__sh3__)
+#define SH_HAS_FPU 0
+#else
+#warning Cannot detect FPU support, assuming no FPU
+#define SH_HAS_FPU 0
+#endif
+
+/* this should not be here */
+#ifndef CPU_MODEL_NAME
+#define CPU_MODEL_NAME "SH-Multilib"
+#endif
+
+/*
+ * If the following macro is set to 0 there will be no software irq stack
+ */
+
+#ifndef SH_HAS_SEPARATE_STACKS
+#define SH_HAS_SEPARATE_STACKS 1
+#endif
+
+/*
+ * Define the name of the CPU family.
+ */
+
+#define CPU_NAME "Hitachi SH"
+
+#ifndef ASM
+
+#if defined(__sh1__) || defined(__sh2__)
+
+/*
+ * Mask for disabling interrupts
+ */
+#define SH_IRQDIS_VALUE 0xf0
+
+#define sh_disable_interrupts( _level ) \
+ asm volatile ( \
+ "stc sr,%0\n\t" \
+ "ldc %1,sr\n\t"\
+ : "=&r" (_level ) \
+ : "r" (SH_IRQDIS_VALUE) );
+
+#define sh_enable_interrupts( _level ) \
+ asm volatile( "ldc %0,sr\n\t" \
+ "nop\n\t" \
+ :: "r" (_level) );
+
+/*
+ * This temporarily restores the interrupt to _level before immediately
+ * disabling them again. This is used to divide long RTEMS critical
+ * sections into two or more parts. The parameter _level is not
+ * modified.
+ */
+
+#define sh_flash_interrupts( _level ) \
+ asm volatile( \
+ "ldc %1,sr\n\t" \
+ "nop\n\t" \
+ "ldc %0,sr\n\t" \
+ "nop\n\t" \
+ : : "r" (SH_IRQDIS_VALUE), "r" (_level) );
+
+#else
+
+#define SH_IRQDIS_MASK 0xf0
+
+#define sh_disable_interrupts( _level ) \
+ asm volatile ( \
+ "stc sr,%0\n\t" \
+ "mov %0,r5\n\t" \
+ "or %1,r5\n\t" \
+ "ldc r5,sr\n\t"\
+ : "=&r" (_level ) \
+ : "r" (SH_IRQDIS_MASK) \
+ : "r5" );
+
+#define sh_enable_interrupts( _level ) \
+ asm volatile( "ldc %0,sr\n\t" \
+ "nop\n\t" \
+ :: "r" (_level) );
+
+/*
+ * This temporarily restores the interrupt to _level before immediately
+ * disabling them again. This is used to divide long RTEMS critical
+ * sections into two or more parts. The parameter _level is not
+ * modified.
+ */
+
+#define sh_flash_interrupts( _level ) \
+ asm volatile( \
+ "stc sr,r5\n\t" \
+ "ldc %1,sr\n\t" \
+ "nop\n\t" \
+ "or %0,r5\n\t" \
+ "ldc r5,sr\n\t" \
+ "nop\n\t" \
+ : : "r" (SH_IRQDIS_MASK), "r" (_level) : "r5");
+
+#endif
+
+#define sh_get_interrupt_level( _level ) \
+{ \
+ register uint32_t _tmpsr ; \
+ \
+ asm volatile( "stc sr, %0" : "=r" (_tmpsr) ); \
+ _level = (_tmpsr & 0xf0) >> 4 ; \
+}
+
+#define sh_set_interrupt_level( _newlevel ) \
+{ \
+ register uint32_t _tmpsr; \
+ \
+ asm volatile ( "stc sr, %0" : "=r" (_tmpsr) ); \
+ _tmpsr = ( _tmpsr & ~0xf0 ) | ((_newlevel) << 4) ; \
+ asm volatile( "ldc %0,sr" :: "r" (_tmpsr) ); \
+}
+
+/*
+ * The following routine swaps the endian format of an unsigned int.
+ * It must be static because it is referenced indirectly.
+ */
+
+static inline unsigned int sh_swap_u32(
+ unsigned int value
+)
+{
+ register unsigned int swapped;
+
+ asm volatile (
+ "swap.b %1,%0; "
+ "swap.w %0,%0; "
+ "swap.b %0,%0"
+ : "=r" (swapped)
+ : "r" (value) );
+
+ return( swapped );
+}
+
+static inline unsigned int sh_swap_u16(
+ unsigned int value
+)
+{
+ register unsigned int swapped ;
+
+ asm volatile ( "swap.b %1,%0" : "=r" (swapped) : "r" (value) );
+
+ return( swapped );
+}
+
+#define CPU_swap_u32( value ) sh_swap_u32( value )
+#define CPU_swap_u16( value ) sh_swap_u16( value )
+
+extern unsigned int sh_set_irq_priority(
+ unsigned int irq,
+ unsigned int prio );
+
+#endif /* !ASM */
+
+/*
+ * Bits on SH-4 registers.
+ * See SH-4 Programming manual for more details.
+ *
+ * Added by Alexandra Kossovsky <sasha@oktet.ru>
+ */
+
+#if defined(__SH4__)
+#define SH4_SR_MD 0x40000000 /* Priveleged mode */
+#define SH4_SR_RB 0x20000000 /* General register bank specifier */
+#define SH4_SR_BL 0x10000000 /* Exeption/interrupt masking bit */
+#define SH4_SR_FD 0x00008000 /* FPU disable bit */
+#define SH4_SR_M 0x00000200 /* For signed division:
+ divisor (module) is negative */
+#define SH4_SR_Q 0x00000100 /* For signed division:
+ dividend (and quotient) is negative */
+#define SH4_SR_IMASK 0x000000f0 /* Interrupt mask level */
+#define SH4_SR_IMASK_S 4
+#define SH4_SR_S 0x00000002 /* Saturation for MAC instruction:
+ if set, data in MACH/L register
+ is restricted to 48/32 bits
+ for MAC.W/L instructions */
+#define SH4_SR_T 0x00000001 /* 1 if last condiyion was true */
+#define SH4_SR_RESERV 0x8fff7d0d /* Reserved bits, read/write as 0 */
+
+/* FPSCR -- FPU Status/Control Register */
+#define SH4_FPSCR_FR 0x00200000 /* FPU register bank specifier */
+#define SH4_FPSCR_SZ 0x00100000 /* FMOV 64-bit transfer mode */
+#define SH4_FPSCR_PR 0x00080000 /* Double-percision floating-point
+ operations flag */
+ /* SH4_FPSCR_SZ & SH4_FPSCR_PR != 1 */
+#define SH4_FPSCR_DN 0x00040000 /* Treat denormalized number as zero */
+#define SH4_FPSCR_CAUSE 0x0003f000 /* FPU exeption cause field */
+#define SH4_FPSCR_CAUSE_S 12
+#define SH4_FPSCR_ENABLE 0x00000f80 /* FPU exeption enable field */
+#define SH4_FPSCR_ENABLE_s 7
+#define SH4_FPSCR_FLAG 0x0000007d /* FPU exeption flag field */
+#define SH4_FPSCR_FLAG_S 2
+#define SH4_FPSCR_RM 0x00000001 /* Rounding mode:
+ 1/0 -- round to zero/nearest */
+#define SH4_FPSCR_RESERV 0xffd00000 /* Reserved bits, read/write as 0 */
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/score/cpu/sh/rtems/score/sh_io.h b/cpukit/score/cpu/sh/rtems/score/sh_io.h
new file mode 100644
index 0000000000..5be558093e
--- /dev/null
+++ b/cpukit/score/cpu/sh/rtems/score/sh_io.h
@@ -0,0 +1,47 @@
+/*
+ * These are some macros to access memory mapped devices
+ * on the SH7000-architecture.
+ *
+ * Inspired from the linux kernel's include/asm/io.h
+ *
+ * Authors: Ralf Corsepius (corsepiu@faw.uni-ulm.de) and
+ * Bernd Becker (becker@faw.uni-ulm.de)
+ *
+ * COPYRIGHT (c) 1996-1998, FAW Ulm, Germany
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *
+ * COPYRIGHT (c) 1998-2001.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef _asm_io_h
+#define _asm_io_h
+
+#define readb(addr) (*(volatile unsigned char *) (addr))
+#define readw(addr) (*(volatile unsigned short *) (addr))
+#define readl(addr) (*(volatile unsigned int *) (addr))
+#define read8(addr) (*(volatile uint8_t *) (addr))
+#define read16(addr) (*(volatile uint16_t *) (addr))
+#define read32(addr) (*(volatile uint32_t *) (addr))
+
+#define writeb(b,addr) ((*(volatile unsigned char *) (addr)) = (b))
+#define writew(b,addr) ((*(volatile unsigned short *) (addr)) = (b))
+#define writel(b,addr) ((*(volatile unsigned int *) (addr)) = (b))
+#define write8(b,addr) ((*(volatile uint8_t *) (addr)) = (b))
+#define write16(b,addr) ((*(volatile uint16_t *) (addr)) = (b))
+#define write32(b,addr) ((*(volatile uint32_t *) (addr)) = (b))
+
+#define inb(addr) readb(addr)
+#define outb(b,addr) writeb(b,addr)
+
+#endif
diff --git a/cpukit/score/cpu/sh/rtems/score/types.h b/cpukit/score/cpu/sh/rtems/score/types.h
new file mode 100644
index 0000000000..d60a0ae9b5
--- /dev/null
+++ b/cpukit/score/cpu/sh/rtems/score/types.h
@@ -0,0 +1,65 @@
+/*
+ * This include file contains information pertaining to the Hitachi SH
+ * processor.
+ *
+ * Authors: Ralf Corsepius (corsepiu@faw.uni-ulm.de) and
+ * Bernd Becker (becker@faw.uni-ulm.de)
+ *
+ * COPYRIGHT (c) 1997-1998, FAW Ulm, Germany
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *
+ * COPYRIGHT (c) 1998-2001.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __CPU_SH_TYPES_h
+#define __CPU_SH_TYPES_h
+
+#ifndef ASM
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This section defines the basic types for this processor.
+ */
+
+typedef unsigned char unsigned8; /* unsigned 8-bit integer */
+typedef unsigned short unsigned16; /* unsigned 16-bit integer */
+typedef unsigned int unsigned32; /* unsigned 32-bit integer */
+typedef unsigned long long unsigned64; /* unsigned 64-bit integer */
+
+typedef unsigned16 Priority_Bit_map_control;
+
+typedef signed char signed8; /* 8-bit signed integer */
+typedef signed short signed16; /* 16-bit signed integer */
+typedef signed int signed32; /* 32-bit signed integer */
+typedef signed long long signed64; /* 64 bit signed integer */
+
+typedef unsigned16 boolean; /* Boolean value, external */
+ /* data bus has 16 bits */
+
+typedef float single_precision; /* single precision float */
+typedef double double_precision; /* double precision float */
+
+typedef void sh_isr;
+typedef void ( *sh_isr_entry )( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !ASM */
+
+#endif
diff --git a/cpukit/score/cpu/sparc/.cvsignore b/cpukit/score/cpu/sparc/.cvsignore
new file mode 100644
index 0000000000..282522db03
--- /dev/null
+++ b/cpukit/score/cpu/sparc/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/cpukit/score/cpu/sparc/ChangeLog b/cpukit/score/cpu/sparc/ChangeLog
new file mode 100644
index 0000000000..81919f9e92
--- /dev/null
+++ b/cpukit/score/cpu/sparc/ChangeLog
@@ -0,0 +1,269 @@
+2004-04-06 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * configure.ac: Remove (Merged into$(top_srcdir)/configure.ac).
+ * Makefile.am: Don't include multilib.am.
+ Reflect merging configure.ac into $(top_srcdir)/configure.ac.
+
+2004-04-01 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * Makefile.am: Install asm.h to $(includedir)/rtems.
+
+2004-04-01 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * cpu_asm.S: Include <rtems/asm.h> instead of <asm.h>.
+
+2004-03-30 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * cpu.c, rtems/score/cpu.h, rtems/score/sparc.h: Convert to using
+ c99 fixed size types.
+
+2004-03-29 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * configure.ac: RTEMS_TOP([../../../..]).
+
+2004-02-26 Andreas Karlsson <andreas.karlsson@space.se>
+
+ 604/bsps
+ * cpu_asm.S: Close window while restoring interrupted task state which
+ resulted in CWP corruption.
+
+2004-01-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Move RTEMS_TOP one subdir down.
+
+2004-01-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add PREINSTALL_DIRS.
+
+2004-01-14 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Re-add dirstamps to PREINSTALL_FILES.
+ Add PREINSTALL_FILES to CLEANFILES.
+
+2004-01-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Requires automake >= 1.8.1.
+
+2004-01-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include compile.am, again.
+
+2004-01-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Convert to using automake compilation rules.
+
+2003-12-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use mkdir_p. Remove dirs from PREINSTALL_FILES.
+
+2003-12-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Require automake >= 1.8, autoconf >= 2.59.
+
+2003-12-01 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Remove TMPINSTALL_FILES.
+
+2003-11-30 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add $(dirstamp) to preinstallation rules.
+
+2003-11-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Don't use gmake rules for preinstallation.
+
+2003-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_CANONICAL_HOST.
+
+2003-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_CHECK_CPU.
+
+2003-09-04 Joel Sherrill <joel@OARcorp.com>
+
+ * cpu.c, cpu_asm.S, rtems/score/cpu.h, rtems/score/sparc.h,
+ rtems/score/types.h: URL for license changed.
+
+2003-08-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use rtems-bugs@rtems.com as bug report email address.
+
+2003-03-06 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove AC_CONFIG_AUX_DIR.
+
+2002-12-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Require autoconf-2.57 + automake-1.7.2.
+ * Makefile.am: Eliminate C_O_FILES, S_O_FILES, libscorecpu_a_OBJECTS.
+
+2002-11-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Fix package name.
+
+2002-10-25 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Add nostdinc to AM_INIT_AUTOMAKE.
+
+2002-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * .cvsignore: Reformat.
+ Add autom4te*cache.
+ Remove autom4te.cache.
+
+2002-08-08 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * cpu.c: Move pointer into #ifdef to avoid compiler warning.
+
+2002-07-26 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Build libscorecpu.a instead of rtems-cpu.rel.
+
+2002-07-22 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use .$(OBJEXT) instead of .o.
+
+2002-07-05 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: RTEMS_TOP(../../../..).
+
+2002-07-03 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems.S: Remove.
+ * Makefile.am: Reflect changes above.
+
+2002-07-01 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_PROJECT_ROOT.
+
+2002-06-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Add RTEMS_PROG_CCAS
+
+2002-06-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use AC_CONFIG_AUX_DIR(../../../..).
+ Add AC_PROG_RANLIB.
+
+2002-06-17 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include $(top_srcdir)/../../../automake/*.am.
+ Use ../../../aclocal.
+
+2002-04-01 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * cpu.c: Remove call to sparc_init_tbr/NO_TABLE_MOVE.
+ * rtems/score/cpu.h: Remove NO_TABLE_MOVE conditional code.
+
+
+2001-04-03 Joel Sherrill <joel@OARcorp.com>
+
+ * Per PR94, all rtems/score/CPUtypes.h are named rtems/score/types.h.
+ * rtems/score/sparctypes.h: Removed.
+ * rtems/score/types.h: New file via CVS magic.
+ * Makefile.am, rtems/score/cpu.h: Account for name change.
+
+2002-03-28 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * cpu.c: Replace NO_TABLE_MOVE-support by external function
+ (code moved to libcpu/sparc/tbr/tbr.c).
+ * cpu.h: Replace NO_TABLE_MOVE-support by external function
+ (code moved to libcpu/sparc/tbr/tbr.h).
+ * sparc.h: Add sparc_init_tbr (implemented in libcpu/sparc/tbr/tbr.c).
+
+2002-03-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac:
+ AC_INIT(package,_RTEMS_VERSION,_RTEMS_BUGS).
+ AM_INIT_AUTOMAKE([no-define foreign 1.6]).
+ * Makefile.am: Remove AUTOMAKE_OPTIONS.
+
+2002-01-31 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Reflect 2002-01-23 changes.
+
+2001-01-30 Joel Sherrill <joel@OARcorp.com>
+
+ * Makefile.am: Corrected so .h files from rtems/score/ are installed.
+
+2002-01-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/Makefile.am: Removed.
+ * rtems/score/Makefile.am: Removed.
+ * configure.ac: Reflect changes above.
+
+2001-12-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add multilib support.
+
+2001-11-28 Joel Sherrill <joel@OARcorp.com>,
+
+ This was tracked as PR91.
+ * rtems/score/cpu.h: Added CPU_PROVIDES_ISR_IS_IN_PROGRESS macro which
+ is used to specify if the port uses the standard macro for this (FALSE).
+ A TRUE setting indicates the port provides its own implementation.
+
+2001-10-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * .cvsignore: Add autom4te.cache for autoconf > 2.52.
+ * configure.in: Remove.
+ * configure.ac: New file, generated from configure.in by autoupdate.
+
+2001-09-27 Jiri Gaisler <jiri@gaisler.com>
+
+ * cpu_asm.S: Small patch to fix a bug in the rtems sparc port. The
+ bug has been there all the time, but only hits the leon bsp since the
+ leon cpu has a 5-stage pipeline (erc32 has 4 stages).
+
+2001-09-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/score/Makefile.am: Use 'PREINSTALL_FILES ='.
+ * Makefile.am: Use 'PREINSTALL_FILES ='.
+
+
+2001-02-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am, rtems/score/Makefile.am:
+ Apply include_*HEADERS instead of H_FILES.
+
+2001-01-03 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/cpu.h: Added _CPU_Initialize_vectors().
+ * cpu_asm.S: Modify to properly dereference _ISR_Vector_table
+ now that it is dynamically allocated.
+
+2000-12-06 Joel Sherrill <joel@OARcorp.com>
+
+ * cpu.c: Added include of <rtems/rtems/cache.h> to eliminate warning.
+
+2000-11-21 Jiri Gaisler <jgais@ws.estec.esa.nl>
+
+ * cpu_asm.S: Fix for CPUs with FPU revision B or C.
+
+2000-11-14 Jiri Gaisler <jgais@ws.estec.esa.nl>
+
+ * cpu.c, rtems/cpu/sparc.h: Make floating point optional based
+ on gcc arguments. Do not initialize FP context if there is
+ no FPU. Flush instruction cache after installing RTEMS trap handler.
+
+2000-11-09 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use ... instead of RTEMS_TOPdir in ACLOCAL_AMFLAGS.
+
+2000-11-02 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Switch to ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal.
+
+2000-10-25 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: ACLOCAL_AMFLAGS= -I $(RTEMS_TOPdir)/macros.
+ Switch to GNU canonicalization.
+
+2000-09-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include compile.am.
+
+2000-08-10 Joel Sherrill <joel@OARcorp.com>
+
+ * ChangeLog: New file.
diff --git a/cpukit/score/cpu/sparc/Makefile.am b/cpukit/score/cpu/sparc/Makefile.am
new file mode 100644
index 0000000000..9918078740
--- /dev/null
+++ b/cpukit/score/cpu/sparc/Makefile.am
@@ -0,0 +1,58 @@
+##
+## $Id$
+##
+
+include $(top_srcdir)/automake/compile.am
+
+include_rtemsdir = $(includedir)/rtems
+include_rtems_HEADERS = asm.h
+
+include_rtems_scoredir = $(includedir)/rtems/score
+include_rtems_score_HEADERS = rtems/score/sparc.h rtems/score/cpu.h \
+ rtems/score/types.h
+
+EXTRA_LIBRARIES = libscorecpu.a
+CLEANFILES = libscorecpu.a
+libscorecpu_a_SOURCES = cpu.c cpu_asm.S
+libscorecpu_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libscorecpu_g.a
+CLEANFILES += libscorecpu_g.a
+libscorecpu_g_a_SOURCES = $(libscorecpu_a_SOURCES)
+libscorecpu_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+all-local: $(PREINSTALL_FILES) libscorecpu$(LIB_VARIANT).a
+
+PREINSTALL_DIRS =
+PREINSTALL_FILES =
+
+$(PROJECT_INCLUDE)/rtems/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems
+ @: > $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/asm.h: asm.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/asm.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/asm.h
+
+$(PROJECT_INCLUDE)/rtems/score/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems/score
+ @: > $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/score/sparc.h: rtems/score/sparc.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/sparc.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/sparc.h
+
+$(PROJECT_INCLUDE)/rtems/score/cpu.h: rtems/score/cpu.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/cpu.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/cpu.h
+
+$(PROJECT_INCLUDE)/rtems/score/types.h: rtems/score/types.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/types.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/types.h
+
+CLEANFILES += $(PREINSTALL_FILES)
+DISTCLEANFILES = $(PREINSTALL_DIRS)
+
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/score/cpu/sparc/README b/cpukit/score/cpu/sparc/README
new file mode 100644
index 0000000000..c4c2200075
--- /dev/null
+++ b/cpukit/score/cpu/sparc/README
@@ -0,0 +1,110 @@
+#
+# $Id$
+#
+
+This file discusses SPARC specific issues which are important to
+this port. The primary topics in this file are:
+
+ + Global Register Usage
+ + Stack Frame
+ + EF bit in the PSR
+
+
+Global Register Usage
+=====================
+
+This information on register usage is based heavily on a comment in the
+file gcc-2.7.0/config/sparc/sparc.h in the the gcc 2.7.0 source.
+
+ + g0 is hardwired to 0
+ + On non-v9 systems:
+ - g1 is free to use as temporary.
+ - g2-g4 are reserved for applications. Gcc normally uses them as
+ temporaries, but this can be disabled via the -mno-app-regs option.
+ - g5 through g7 are reserved for the operating system.
+ + On v9 systems:
+ - g1 and g5 are free to use as temporaries.
+ - g2-g4 are reserved for applications (the compiler will not normally use
+ them, but they can be used as temporaries with -mapp-regs).
+ - g6-g7 are reserved for the operating system.
+
+ NOTE: As of gcc 2.7.0 register g1 was used in the following scenarios:
+
+ + as a temporary by the 64 bit sethi pattern
+ + when restoring call-preserved registers in large stack frames
+
+RTEMS places no constraints on the usage of the global registers. Although
+gcc assumes that either g5-g7 (non-V9) or g6-g7 (V9) are reserved for the
+operating system, RTEMS does not assume any special use for them.
+
+
+
+Stack Frame
+===========
+
+The stack grows downward (i.e. to lower addresses) on the SPARC architecture.
+
+The following is the organization of the stack frame:
+
+
+
+ | ............... |
+ fp | |
+ +-------------------------------+
+ | |
+ | Local registers, temporaries, |
+ | and saved floats | x bytes
+ | |
+ sp + x +-------------------------------+
+ | |
+ | outgoing parameters past |
+ | the sixth one | x bytes
+ | |
+ sp + 92 +-------------------------------+ *
+ | | *
+ | area for callee to save | *
+ | register arguments | * 24 bytes
+ | | *
+ sp + 68 +-------------------------------+ *
+ | | *
+ | structure return pointer | * 4 bytes
+ | | *
+ sp + 64 +-------------------------------+ *
+ | | *
+ | local register set | * 32 bytes
+ | | *
+ sp + 32 +-------------------------------+ *
+ | | *
+ | input register set | * 32 bytes
+ | | *
+ sp +-------------------------------+ *
+
+
+* = minimal stack frame
+
+x = optional components
+
+EF bit in the PSR
+=================
+
+The EF (enable floating point unit) in the PSR is utilized in this port to
+prevent non-floating point tasks from performing floating point
+operations. This bit is maintained as part of the integer context.
+However, the floating point context is switched BEFORE the integer
+context. Thus the EF bit in place at the time of the FP switch may
+indicate that FP operations are disabled. This occurs on certain task
+switches, when the EF bit will be 0 for the outgoing task and thus a fault
+will be generated on the first FP operation of the FP context save.
+
+The remedy for this is to enable FP access as the first step in both the
+save and restore of the FP context area. This bit will be subsequently
+reloaded by the integer context switch.
+
+Two of the scenarios which demonstrate this problem are outlined below:
+
+1. When the first FP task is switched to. The system tasks are not FP and
+thus would be unable to restore the FP context of the incoming task.
+
+2. On a deferred FP context switch. In this case, the system might switch
+from FP Task A to non-FP Task B and then to FP Task C. In this scenario,
+the floating point state must technically be saved by a non-FP task.
diff --git a/cpukit/score/cpu/sparc/asm.h b/cpukit/score/cpu/sparc/asm.h
new file mode 100644
index 0000000000..96ce49f03a
--- /dev/null
+++ b/cpukit/score/cpu/sparc/asm.h
@@ -0,0 +1,121 @@
+/* asm.h
+ *
+ * This include file attempts to address the problems
+ * caused by incompatible flavors of assemblers and
+ * toolsets. It primarily addresses variations in the
+ * use of leading underscores on symbols and the requirement
+ * that register names be preceded by a %.
+ *
+ *
+ * NOTE: The spacing in the use of these macros
+ * is critical to them working as advertised.
+ *
+ * COPYRIGHT:
+ *
+ * This file is based on similar code found in newlib available
+ * from ftp.cygnus.com. The file which was used had no copyright
+ * notice. This file is freely distributable as long as the source
+ * of the file is noted.
+ *
+ * $Id$
+ */
+
+#ifndef __SPARC_ASM_h
+#define __SPARC_ASM_h
+
+/*
+ * Indicate we are in an assembly file and get the basic CPU definitions.
+ */
+
+#ifndef ASM
+#define ASM
+#endif
+
+#include <rtems/score/cpuopts.h>
+#include <rtems/score/cpu.h>
+
+/*
+ * Recent versions of GNU cpp define variables which indicate the
+ * need for underscores and percents. If not using GNU cpp or
+ * the version does not support this, then you will obviously
+ * have to define these as appropriate.
+ */
+
+/* XXX __USER_LABEL_PREFIX__ and __REGISTER_PREFIX__ do not work on gcc 2.7.0 */
+/* XXX The following ifdef magic fixes the problem but results in a warning */
+/* XXX when compiling assembly code. */
+
+#ifndef __USER_LABEL_PREFIX__
+#define __USER_LABEL_PREFIX__ _
+#endif
+
+#ifndef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__
+#endif
+
+/* ANSI concatenation macros. */
+
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+/* Use the right prefix for global labels. */
+
+#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+
+/* Use the right prefix for registers. */
+
+#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
+
+/*
+ * define macros for all of the registers on this CPU
+ *
+ * EXAMPLE: #define d0 REG (d0)
+ */
+
+/*
+ * Define macros to handle section beginning and ends.
+ */
+
+
+#define BEGIN_CODE_DCL .text
+#define END_CODE_DCL
+#define BEGIN_DATA_DCL .data
+#define END_DATA_DCL
+#define BEGIN_CODE .text
+#define END_CODE
+#define BEGIN_DATA
+#define END_DATA
+#define BEGIN_BSS
+#define END_BSS
+#define END
+
+/*
+ * Following must be tailor for a particular flavor of the C compiler.
+ * They may need to put underscores in front of the symbols.
+ */
+
+#define PUBLIC(sym) .globl SYM (sym)
+#define EXTERN(sym) .globl SYM (sym)
+
+/*
+ * Entry for traps which jump to a programmer-specified trap handler.
+ */
+
+#define TRAP(_vector, _handler) \
+ mov %psr, %l0 ; \
+ sethi %hi(_handler), %l4 ; \
+ jmp %l4+%lo(_handler); \
+ mov _vector, %l3
+
+/*
+ * Used for the reset trap to avoid a supervisor instruction
+ */
+
+#define RTRAP(_vector, _handler) \
+ mov %g0, %l0 ; \
+ sethi %hi(_handler), %l4 ; \
+ jmp %l4+%lo(_handler); \
+ mov _vector, %l3
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/sparc/cpu.c b/cpukit/score/cpu/sparc/cpu.c
new file mode 100644
index 0000000000..16f7c81dfb
--- /dev/null
+++ b/cpukit/score/cpu/sparc/cpu.c
@@ -0,0 +1,330 @@
+/*
+ * SPARC Dependent Source
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/rtems/cache.h>
+
+/*
+ * This initializes the set of opcodes placed in each trap
+ * table entry. The routine which installs a handler is responsible
+ * for filling in the fields for the _handler address and the _vector
+ * trap type.
+ *
+ * The constants following this structure are masks for the fields which
+ * must be filled in when the handler is installed.
+ */
+
+const CPU_Trap_table_entry _CPU_Trap_slot_template = {
+ 0xa1480000, /* mov %psr, %l0 */
+ 0x29000000, /* sethi %hi(_handler), %l4 */
+ 0x81c52000, /* jmp %l4 + %lo(_handler) */
+ 0xa6102000 /* mov _vector, %l3 */
+};
+
+/*PAGE
+ *
+ * _CPU_Initialize
+ *
+ * This routine performs processor dependent initialization.
+ *
+ * Input Parameters:
+ * cpu_table - CPU table to initialize
+ * thread_dispatch - address of disptaching routine
+ *
+ * Output Parameters: NONE
+ *
+ * NOTE: There is no need to save the pointer to the thread dispatch routine.
+ * The SPARC's assembly code can reference it directly with no problems.
+ */
+
+void _CPU_Initialize(
+ rtems_cpu_table *cpu_table,
+ void (*thread_dispatch) /* ignored on this CPU */
+)
+{
+#if (SPARC_HAS_FPU == 1)
+ void *pointer;
+
+ /*
+ * This seems to be the most appropriate way to obtain an initial
+ * FP context on the SPARC. The NULL fp context is copied it to
+ * the task's FP context during Context_Initialize.
+ */
+
+ pointer = &_CPU_Null_fp_context;
+ _CPU_Context_save_fp( &pointer );
+#endif
+
+ /*
+ * Grab our own copy of the user's CPU table.
+ */
+
+ _CPU_Table = *cpu_table;
+}
+
+/*PAGE
+ *
+ * _CPU_ISR_Get_level
+ *
+ * Input Parameters: NONE
+ *
+ * Output Parameters:
+ * returns the current interrupt level (PIL field of the PSR)
+ */
+
+uint32_t _CPU_ISR_Get_level( void )
+{
+ uint32_t level;
+
+ sparc_get_interrupt_level( level );
+
+ return level;
+}
+
+/*PAGE
+ *
+ * _CPU_ISR_install_raw_handler
+ *
+ * This routine installs the specified handler as a "raw" non-executive
+ * supported trap handler (a.k.a. interrupt service routine).
+ *
+ * Input Parameters:
+ * vector - trap table entry number plus synchronous
+ * vs. asynchronous information
+ * new_handler - address of the handler to be installed
+ * old_handler - pointer to an address of the handler previously installed
+ *
+ * Output Parameters: NONE
+ * *new_handler - address of the handler previously installed
+ *
+ * NOTE:
+ *
+ * On the SPARC, there are really only 256 vectors. However, the executive
+ * has no easy, fast, reliable way to determine which traps are synchronous
+ * and which are asynchronous. By default, synchronous traps return to the
+ * instruction which caused the interrupt. So if you install a software
+ * trap handler as an executive interrupt handler (which is desirable since
+ * RTEMS takes care of window and register issues), then the executive needs
+ * to know that the return address is to the trap rather than the instruction
+ * following the trap.
+ *
+ * So vectors 0 through 255 are treated as regular asynchronous traps which
+ * provide the "correct" return address. Vectors 256 through 512 are assumed
+ * by the executive to be synchronous and to require that the return address
+ * be fudged.
+ *
+ * If you use this mechanism to install a trap handler which must reexecute
+ * the instruction which caused the trap, then it should be installed as
+ * an asynchronous trap. This will avoid the executive changing the return
+ * address.
+ */
+
+void _CPU_ISR_install_raw_handler(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+)
+{
+ uint32_t real_vector;
+ CPU_Trap_table_entry *tbr;
+ CPU_Trap_table_entry *slot;
+ uint32_t u32_tbr;
+ uint32_t u32_handler;
+
+ /*
+ * Get the "real" trap number for this vector ignoring the synchronous
+ * versus asynchronous indicator included with our vector numbers.
+ */
+
+ real_vector = SPARC_REAL_TRAP_NUMBER( vector );
+
+ /*
+ * Get the current base address of the trap table and calculate a pointer
+ * to the slot we are interested in.
+ */
+
+ sparc_get_tbr( u32_tbr );
+
+ u32_tbr &= 0xfffff000;
+
+ tbr = (CPU_Trap_table_entry *) u32_tbr;
+
+ slot = &tbr[ real_vector ];
+
+ /*
+ * Get the address of the old_handler from the trap table.
+ *
+ * NOTE: The old_handler returned will be bogus if it does not follow
+ * the RTEMS model.
+ */
+
+#define HIGH_BITS_MASK 0xFFFFFC00
+#define HIGH_BITS_SHIFT 10
+#define LOW_BITS_MASK 0x000003FF
+
+ if ( slot->mov_psr_l0 == _CPU_Trap_slot_template.mov_psr_l0 ) {
+ u32_handler =
+ ((slot->sethi_of_handler_to_l4 & HIGH_BITS_MASK) << HIGH_BITS_SHIFT) |
+ (slot->jmp_to_low_of_handler_plus_l4 & LOW_BITS_MASK);
+ *old_handler = (proc_ptr) u32_handler;
+ } else
+ *old_handler = 0;
+
+ /*
+ * Copy the template to the slot and then fix it.
+ */
+
+ *slot = _CPU_Trap_slot_template;
+
+ u32_handler = (uint32_t ) new_handler;
+
+ slot->mov_vector_l3 |= vector;
+ slot->sethi_of_handler_to_l4 |=
+ (u32_handler & HIGH_BITS_MASK) >> HIGH_BITS_SHIFT;
+ slot->jmp_to_low_of_handler_plus_l4 |= (u32_handler & LOW_BITS_MASK);
+
+ /* need to flush icache after this !!! */
+
+ rtems_cache_invalidate_entire_instruction();
+
+}
+
+/*PAGE
+ *
+ * _CPU_ISR_install_vector
+ *
+ * This kernel routine installs the RTEMS handler for the
+ * specified vector.
+ *
+ * Input parameters:
+ * vector - interrupt vector number
+ * new_handler - replacement ISR for this vector number
+ * old_handler - pointer to former ISR for this vector number
+ *
+ * Output parameters:
+ * *old_handler - former ISR for this vector number
+ *
+ */
+
+void _CPU_ISR_install_vector(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+)
+{
+ uint32_t real_vector;
+ proc_ptr ignored;
+
+ /*
+ * Get the "real" trap number for this vector ignoring the synchronous
+ * versus asynchronous indicator included with our vector numbers.
+ */
+
+ real_vector = SPARC_REAL_TRAP_NUMBER( vector );
+
+ /*
+ * Return the previous ISR handler.
+ */
+
+ *old_handler = _ISR_Vector_table[ real_vector ];
+
+ /*
+ * Install the wrapper so this ISR can be invoked properly.
+ */
+
+ _CPU_ISR_install_raw_handler( vector, _ISR_Handler, &ignored );
+
+ /*
+ * We put the actual user ISR address in '_ISR_vector_table'. This will
+ * be used by the _ISR_Handler so the user gets control.
+ */
+
+ _ISR_Vector_table[ real_vector ] = new_handler;
+}
+
+/*PAGE
+ *
+ * _CPU_Context_Initialize
+ *
+ * This kernel routine initializes the basic non-FP context area associated
+ * with each thread.
+ *
+ * Input parameters:
+ * the_context - pointer to the context area
+ * stack_base - address of memory for the SPARC
+ * size - size in bytes of the stack area
+ * new_level - interrupt level for this context area
+ * entry_point - the starting execution point for this this context
+ * is_fp - TRUE if this context is associated with an FP thread
+ *
+ * Output parameters: NONE
+ */
+
+void _CPU_Context_Initialize(
+ Context_Control *the_context,
+ uint32_t *stack_base,
+ uint32_t size,
+ uint32_t new_level,
+ void *entry_point,
+ boolean is_fp
+)
+{
+ uint32_t stack_high; /* highest "stack aligned" address */
+ uint32_t the_size;
+ uint32_t tmp_psr;
+
+ /*
+ * On CPUs with stacks which grow down (i.e. SPARC), we build the stack
+ * based on the stack_high address.
+ */
+
+ stack_high = ((uint32_t )(stack_base) + size);
+ stack_high &= ~(CPU_STACK_ALIGNMENT - 1);
+
+ the_size = size & ~(CPU_STACK_ALIGNMENT - 1);
+
+ /*
+ * See the README in this directory for a diagram of the stack.
+ */
+
+ the_context->o7 = ((uint32_t ) entry_point) - 8;
+ the_context->o6_sp = stack_high - CPU_MINIMUM_STACK_FRAME_SIZE;
+ the_context->i6_fp = stack_high;
+
+ /*
+ * Build the PSR for the task. Most everything can be 0 and the
+ * CWP is corrected during the context switch.
+ *
+ * The EF bit determines if the floating point unit is available.
+ * The FPU is ONLY enabled if the context is associated with an FP task
+ * and this SPARC model has an FPU.
+ */
+
+ sparc_get_psr( tmp_psr );
+ tmp_psr &= ~SPARC_PSR_PIL_MASK;
+ tmp_psr |= (new_level << 8) & SPARC_PSR_PIL_MASK;
+ tmp_psr &= ~SPARC_PSR_EF_MASK; /* disabled by default */
+
+#if (SPARC_HAS_FPU == 1)
+ /*
+ * If this bit is not set, then a task gets a fault when it accesses
+ * a floating point register. This is a nice way to detect floating
+ * point tasks which are not currently declared as such.
+ */
+
+ if ( is_fp )
+ tmp_psr |= SPARC_PSR_EF_MASK;
+#endif
+ the_context->psr = tmp_psr;
+}
diff --git a/cpukit/score/cpu/sparc/cpu_asm.S b/cpukit/score/cpu/sparc/cpu_asm.S
new file mode 100644
index 0000000000..95d5627be5
--- /dev/null
+++ b/cpukit/score/cpu/sparc/cpu_asm.S
@@ -0,0 +1,806 @@
+/* cpu_asm.s
+ *
+ * This file contains the basic algorithms for all assembly code used
+ * in an specific CPU port of RTEMS. These algorithms must be implemented
+ * in assembly language.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * Ported to ERC32 implementation of the SPARC by On-Line Applications
+ * Research Corporation (OAR) under contract to the European Space
+ * Agency (ESA).
+ *
+ * ERC32 modifications of respective RTEMS file: COPYRIGHT (c) 1995.
+ * European Space Agency.
+ *
+ * $Id$
+ */
+
+#include <rtems/asm.h>
+
+#if (SPARC_HAS_FPU == 1)
+
+/*
+ * void _CPU_Context_save_fp(
+ * void **fp_context_ptr
+ * )
+ *
+ * This routine is responsible for saving the FP context
+ * at *fp_context_ptr. If the point to load the FP context
+ * from is changed then the pointer is modified by this routine.
+ *
+ * NOTE: See the README in this directory for information on the
+ * management of the "EF" bit in the PSR.
+ */
+
+ .align 4
+ PUBLIC(_CPU_Context_save_fp)
+SYM(_CPU_Context_save_fp):
+ save %sp, -CPU_MINIMUM_STACK_FRAME_SIZE, %sp
+
+ /*
+ * The following enables the floating point unit.
+ */
+
+ mov %psr, %l0
+ sethi %hi(SPARC_PSR_EF_MASK), %l1
+ or %l1, %lo(SPARC_PSR_EF_MASK), %l1
+ or %l0, %l1, %l0
+ mov %l0, %psr ! **** ENABLE FLOAT ACCESS ****
+ nop; nop; nop; ! Need three nops before EF is
+ ld [%i0], %l0 ! active due to pipeline delay!!!
+ std %f0, [%l0 + FO_F1_OFFSET]
+ std %f2, [%l0 + F2_F3_OFFSET]
+ std %f4, [%l0 + F4_F5_OFFSET]
+ std %f6, [%l0 + F6_F7_OFFSET]
+ std %f8, [%l0 + F8_F9_OFFSET]
+ std %f10, [%l0 + F1O_F11_OFFSET]
+ std %f12, [%l0 + F12_F13_OFFSET]
+ std %f14, [%l0 + F14_F15_OFFSET]
+ std %f16, [%l0 + F16_F17_OFFSET]
+ std %f18, [%l0 + F18_F19_OFFSET]
+ std %f20, [%l0 + F2O_F21_OFFSET]
+ std %f22, [%l0 + F22_F23_OFFSET]
+ std %f24, [%l0 + F24_F25_OFFSET]
+ std %f26, [%l0 + F26_F27_OFFSET]
+ std %f28, [%l0 + F28_F29_OFFSET]
+ std %f30, [%l0 + F3O_F31_OFFSET]
+ st %fsr, [%l0 + FSR_OFFSET]
+ ret
+ restore
+
+/*
+ * void _CPU_Context_restore_fp(
+ * void **fp_context_ptr
+ * )
+ *
+ * This routine is responsible for restoring the FP context
+ * at *fp_context_ptr. If the point to load the FP context
+ * from is changed then the pointer is modified by this routine.
+ *
+ * NOTE: See the README in this directory for information on the
+ * management of the "EF" bit in the PSR.
+ */
+
+ .align 4
+ PUBLIC(_CPU_Context_restore_fp)
+SYM(_CPU_Context_restore_fp):
+ save %sp, -CPU_MINIMUM_STACK_FRAME_SIZE , %sp
+
+ /*
+ * The following enables the floating point unit.
+ */
+
+ mov %psr, %l0
+ sethi %hi(SPARC_PSR_EF_MASK), %l1
+ or %l1, %lo(SPARC_PSR_EF_MASK), %l1
+ or %l0, %l1, %l0
+ mov %l0, %psr ! **** ENABLE FLOAT ACCESS ****
+ nop; nop; nop; ! Need three nops before EF is
+ ld [%i0], %l0 ! active due to pipeline delay!!!
+ ldd [%l0 + FO_F1_OFFSET], %f0
+ ldd [%l0 + F2_F3_OFFSET], %f2
+ ldd [%l0 + F4_F5_OFFSET], %f4
+ ldd [%l0 + F6_F7_OFFSET], %f6
+ ldd [%l0 + F8_F9_OFFSET], %f8
+ ldd [%l0 + F1O_F11_OFFSET], %f10
+ ldd [%l0 + F12_F13_OFFSET], %f12
+ ldd [%l0 + F14_F15_OFFSET], %f14
+ ldd [%l0 + F16_F17_OFFSET], %f16
+ ldd [%l0 + F18_F19_OFFSET], %f18
+ ldd [%l0 + F2O_F21_OFFSET], %f20
+ ldd [%l0 + F22_F23_OFFSET], %f22
+ ldd [%l0 + F24_F25_OFFSET], %f24
+ ldd [%l0 + F26_F27_OFFSET], %f26
+ ldd [%l0 + F28_F29_OFFSET], %f28
+ ldd [%l0 + F3O_F31_OFFSET], %f30
+ ld [%l0 + FSR_OFFSET], %fsr
+ ret
+ restore
+
+#endif /* SPARC_HAS_FPU */
+
+/*
+ * void _CPU_Context_switch(
+ * Context_Control *run,
+ * Context_Control *heir
+ * )
+ *
+ * This routine performs a normal non-FP context switch.
+ */
+
+ .align 4
+ PUBLIC(_CPU_Context_switch)
+SYM(_CPU_Context_switch):
+ ! skip g0
+ st %g1, [%o0 + G1_OFFSET] ! save the global registers
+ std %g2, [%o0 + G2_OFFSET]
+ std %g4, [%o0 + G4_OFFSET]
+ std %g6, [%o0 + G6_OFFSET]
+
+ std %l0, [%o0 + L0_OFFSET] ! save the local registers
+ std %l2, [%o0 + L2_OFFSET]
+ std %l4, [%o0 + L4_OFFSET]
+ std %l6, [%o0 + L6_OFFSET]
+
+ std %i0, [%o0 + I0_OFFSET] ! save the input registers
+ std %i2, [%o0 + I2_OFFSET]
+ std %i4, [%o0 + I4_OFFSET]
+ std %i6, [%o0 + I6_FP_OFFSET]
+
+ std %o0, [%o0 + O0_OFFSET] ! save the output registers
+ std %o2, [%o0 + O2_OFFSET]
+ std %o4, [%o0 + O4_OFFSET]
+ std %o6, [%o0 + O6_SP_OFFSET]
+
+ rd %psr, %o2
+ st %o2, [%o0 + PSR_OFFSET] ! save status register
+
+ /*
+ * This is entered from _CPU_Context_restore with:
+ * o1 = context to restore
+ * o2 = psr
+ */
+
+ PUBLIC(_CPU_Context_restore_heir)
+SYM(_CPU_Context_restore_heir):
+ /*
+ * Flush all windows with valid contents except the current one.
+ * In examining the set register windows, one may logically divide
+ * the windows into sets (some of which may be empty) based on their
+ * current status:
+ *
+ * + current (i.e. in use),
+ * + used (i.e. a restore would not trap)
+ * + invalid (i.e. 1 in corresponding bit in WIM)
+ * + unused
+ *
+ * Either the used or unused set of windows may be empty.
+ *
+ * NOTE: We assume only one bit is set in the WIM at a time.
+ *
+ * Given a CWP of 5 and a WIM of 0x1, the registers are divided
+ * into sets as follows:
+ *
+ * + 0 - invalid
+ * + 1-4 - unused
+ * + 5 - current
+ * + 6-7 - used
+ *
+ * In this case, we only would save the used windows -- 6 and 7.
+ *
+ * Traps are disabled for the same logical period as in a
+ * flush all windows trap handler.
+ *
+ * Register Usage while saving the windows:
+ * g1 = current PSR
+ * g2 = current wim
+ * g3 = CWP
+ * g4 = wim scratch
+ * g5 = scratch
+ */
+
+ ld [%o1 + PSR_OFFSET], %g1 ! g1 = saved psr
+
+ and %o2, SPARC_PSR_CWP_MASK, %g3 ! g3 = CWP
+ ! g1 = psr w/o cwp
+ andn %g1, SPARC_PSR_ET_MASK | SPARC_PSR_CWP_MASK, %g1
+ or %g1, %g3, %g1 ! g1 = heirs psr
+ mov %g1, %psr ! restore status register and
+ ! **** DISABLE TRAPS ****
+ mov %wim, %g2 ! g2 = wim
+ mov 1, %g4
+ sll %g4, %g3, %g4 ! g4 = WIM mask for CW invalid
+
+save_frame_loop:
+ sll %g4, 1, %g5 ! rotate the "wim" left 1
+ srl %g4, SPARC_NUMBER_OF_REGISTER_WINDOWS - 1, %g4
+ or %g4, %g5, %g4 ! g4 = wim if we do one restore
+
+ /*
+ * If a restore would not underflow, then continue.
+ */
+
+ andcc %g4, %g2, %g0 ! Any windows to flush?
+ bnz done_flushing ! No, then continue
+ nop
+
+ restore ! back one window
+
+ /*
+ * Now save the window just as if we overflowed to it.
+ */
+
+ std %l0, [%sp + CPU_STACK_FRAME_L0_OFFSET]
+ std %l2, [%sp + CPU_STACK_FRAME_L2_OFFSET]
+ std %l4, [%sp + CPU_STACK_FRAME_L4_OFFSET]
+ std %l6, [%sp + CPU_STACK_FRAME_L6_OFFSET]
+
+ std %i0, [%sp + CPU_STACK_FRAME_I0_OFFSET]
+ std %i2, [%sp + CPU_STACK_FRAME_I2_OFFSET]
+ std %i4, [%sp + CPU_STACK_FRAME_I4_OFFSET]
+ std %i6, [%sp + CPU_STACK_FRAME_I6_FP_OFFSET]
+
+ ba save_frame_loop
+ nop
+
+done_flushing:
+
+ add %g3, 1, %g3 ! calculate desired WIM
+ and %g3, SPARC_NUMBER_OF_REGISTER_WINDOWS - 1, %g3
+ mov 1, %g4
+ sll %g4, %g3, %g4 ! g4 = new WIM
+ mov %g4, %wim
+
+ or %g1, SPARC_PSR_ET_MASK, %g1
+ mov %g1, %psr ! **** ENABLE TRAPS ****
+ ! and restore CWP
+ nop
+ nop
+ nop
+
+ ! skip g0
+ ld [%o1 + G1_OFFSET], %g1 ! restore the global registers
+ ldd [%o1 + G2_OFFSET], %g2
+ ldd [%o1 + G4_OFFSET], %g4
+ ldd [%o1 + G6_OFFSET], %g6
+
+ ldd [%o1 + L0_OFFSET], %l0 ! restore the local registers
+ ldd [%o1 + L2_OFFSET], %l2
+ ldd [%o1 + L4_OFFSET], %l4
+ ldd [%o1 + L6_OFFSET], %l6
+
+ ldd [%o1 + I0_OFFSET], %i0 ! restore the output registers
+ ldd [%o1 + I2_OFFSET], %i2
+ ldd [%o1 + I4_OFFSET], %i4
+ ldd [%o1 + I6_FP_OFFSET], %i6
+
+ ldd [%o1 + O2_OFFSET], %o2 ! restore the output registers
+ ldd [%o1 + O4_OFFSET], %o4
+ ldd [%o1 + O6_SP_OFFSET], %o6
+ ! do o0/o1 last to avoid destroying heir context pointer
+ ldd [%o1 + O0_OFFSET], %o0 ! overwrite heir pointer
+
+ jmp %o7 + 8 ! return
+ nop ! delay slot
+
+/*
+ * void _CPU_Context_restore(
+ * Context_Control *new_context
+ * )
+ *
+ * This routine is generally used only to perform restart self.
+ *
+ * NOTE: It is unnecessary to reload some registers.
+ */
+
+ .align 4
+ PUBLIC(_CPU_Context_restore)
+SYM(_CPU_Context_restore):
+ save %sp, -CPU_MINIMUM_STACK_FRAME_SIZE, %sp
+ rd %psr, %o2
+ ba SYM(_CPU_Context_restore_heir)
+ mov %i0, %o1 ! in the delay slot
+
+/*
+ * void _ISR_Handler()
+ *
+ * This routine provides the RTEMS interrupt management.
+ *
+ * We enter this handler from the 4 instructions in the trap table with
+ * the following registers assumed to be set as shown:
+ *
+ * l0 = PSR
+ * l1 = PC
+ * l2 = nPC
+ * l3 = trap type
+ *
+ * NOTE: By an executive defined convention, trap type is between 0 and 255 if
+ * it is an asynchonous trap and 256 and 511 if it is synchronous.
+ */
+
+ .align 4
+ PUBLIC(_ISR_Handler)
+SYM(_ISR_Handler):
+ /*
+ * Fix the return address for synchronous traps.
+ */
+
+ andcc %l3, SPARC_SYNCHRONOUS_TRAP_BIT_MASK, %g0
+ ! Is this a synchronous trap?
+ be,a win_ovflow ! No, then skip the adjustment
+ nop ! DELAY
+ mov %l1, %l6 ! save trapped pc for debug info
+ mov %l2, %l1 ! do not return to the instruction
+ add %l2, 4, %l2 ! indicated
+
+win_ovflow:
+ /*
+ * Save the globals this block uses.
+ *
+ * These registers are not restored from the locals. Their contents
+ * are saved directly from the locals into the ISF below.
+ */
+
+ mov %g4, %l4 ! save the globals this block uses
+ mov %g5, %l5
+
+ /*
+ * When at a "window overflow" trap, (wim == (1 << cwp)).
+ * If we get here like that, then process a window overflow.
+ */
+
+ rd %wim, %g4
+ srl %g4, %l0, %g5 ! g5 = win >> cwp ; shift count and CWP
+ ! are LS 5 bits ; how convenient :)
+ cmp %g5, 1 ! Is this an invalid window?
+ bne dont_do_the_window ! No, then skip all this stuff
+ ! we are using the delay slot
+
+ /*
+ * The following is same as a 1 position right rotate of WIM
+ */
+
+ srl %g4, 1, %g5 ! g5 = WIM >> 1
+ sll %g4, SPARC_NUMBER_OF_REGISTER_WINDOWS-1 , %g4
+ ! g4 = WIM << (Number Windows - 1)
+ or %g4, %g5, %g4 ! g4 = (WIM >> 1) |
+ ! (WIM << (Number Windows - 1))
+
+ /*
+ * At this point:
+ *
+ * g4 = the new WIM
+ * g5 is free
+ */
+
+ /*
+ * Since we are tinkering with the register windows, we need to
+ * make sure that all the required information is in global registers.
+ */
+
+ save ! Save into the window
+ wr %g4, 0, %wim ! WIM = new WIM
+ nop ! delay slots
+ nop
+ nop
+
+ /*
+ * Now save the window just as if we overflowed to it.
+ */
+
+ std %l0, [%sp + CPU_STACK_FRAME_L0_OFFSET]
+ std %l2, [%sp + CPU_STACK_FRAME_L2_OFFSET]
+ std %l4, [%sp + CPU_STACK_FRAME_L4_OFFSET]
+ std %l6, [%sp + CPU_STACK_FRAME_L6_OFFSET]
+
+ std %i0, [%sp + CPU_STACK_FRAME_I0_OFFSET]
+ std %i2, [%sp + CPU_STACK_FRAME_I2_OFFSET]
+ std %i4, [%sp + CPU_STACK_FRAME_I4_OFFSET]
+ std %i6, [%sp + CPU_STACK_FRAME_I6_FP_OFFSET]
+
+ restore
+ nop
+
+dont_do_the_window:
+ /*
+ * Global registers %g4 and %g5 are saved directly from %l4 and
+ * %l5 directly into the ISF below.
+ */
+
+save_isf:
+
+ /*
+ * Save the state of the interrupted task -- especially the global
+ * registers -- in the Interrupt Stack Frame. Note that the ISF
+ * includes a regular minimum stack frame which will be used if
+ * needed by register window overflow and underflow handlers.
+ *
+ * REGISTERS SAME AS AT _ISR_Handler
+ */
+
+ sub %fp, CONTEXT_CONTROL_INTERRUPT_FRAME_SIZE, %sp
+ ! make space for ISF
+
+ std %l0, [%sp + ISF_PSR_OFFSET] ! save psr, PC
+ st %l2, [%sp + ISF_NPC_OFFSET] ! save nPC
+ st %g1, [%sp + ISF_G1_OFFSET] ! save g1
+ std %g2, [%sp + ISF_G2_OFFSET] ! save g2, g3
+ std %l4, [%sp + ISF_G4_OFFSET] ! save g4, g5 -- see above
+ std %g6, [%sp + ISF_G6_OFFSET] ! save g6, g7
+
+ std %i0, [%sp + ISF_I0_OFFSET] ! save i0, i1
+ std %i2, [%sp + ISF_I2_OFFSET] ! save i2, i3
+ std %i4, [%sp + ISF_I4_OFFSET] ! save i4, i5
+ std %i6, [%sp + ISF_I6_FP_OFFSET] ! save i6/fp, i7
+
+ rd %y, %g1
+ st %g1, [%sp + ISF_Y_OFFSET] ! save y
+ st %l6, [%sp + ISF_TPC_OFFSET] ! save real trapped pc
+
+ mov %sp, %o1 ! 2nd arg to ISR Handler
+
+ /*
+ * Increment ISR nest level and Thread dispatch disable level.
+ *
+ * Register usage for this section:
+ *
+ * l4 = _Thread_Dispatch_disable_level pointer
+ * l5 = _ISR_Nest_level pointer
+ * l6 = _Thread_Dispatch_disable_level value
+ * l7 = _ISR_Nest_level value
+ *
+ * NOTE: It is assumed that l4 - l7 will be preserved until the ISR
+ * nest and thread dispatch disable levels are unnested.
+ */
+
+ sethi %hi(SYM(_Thread_Dispatch_disable_level)), %l4
+ ld [%l4 + %lo(SYM(_Thread_Dispatch_disable_level))], %l6
+ sethi %hi(SYM(_ISR_Nest_level)), %l5
+ ld [%l5 + %lo(SYM(_ISR_Nest_level))], %l7
+
+ add %l6, 1, %l6
+ st %l6, [%l4 + %lo(SYM(_Thread_Dispatch_disable_level))]
+
+ add %l7, 1, %l7
+ st %l7, [%l5 + %lo(SYM(_ISR_Nest_level))]
+
+ /*
+ * If ISR nest level was zero (now 1), then switch stack.
+ */
+
+ mov %sp, %fp
+ subcc %l7, 1, %l7 ! outermost interrupt handler?
+ bnz dont_switch_stacks ! No, then do not switch stacks
+
+ sethi %hi(SYM(_CPU_Interrupt_stack_high)), %g4
+ ld [%g4 + %lo(SYM(_CPU_Interrupt_stack_high))], %sp
+
+dont_switch_stacks:
+ /*
+ * Make sure we have a place on the stack for the window overflow
+ * trap handler to write into. At this point it is safe to
+ * enable traps again.
+ */
+
+ sub %sp, CPU_MINIMUM_STACK_FRAME_SIZE, %sp
+
+ /*
+ * Check if we have an external interrupt (trap 0x11 - 0x1f). If so,
+ * set the PIL in the %psr to mask off interrupts with lower priority.
+ * The original %psr in %l0 is not modified since it will be restored
+ * when the interrupt handler returns.
+ */
+
+ mov %l0, %g5
+ and %l3, 0x0ff, %g4
+
+/* This is a fix for ERC32 with FPU rev.B or rev.C */
+
+#if defined(FPU_REVB)
+
+
+ subcc %g4, 0x08, %g0
+ be fpu_revb
+ subcc %g4, 0x11, %g0
+ bl dont_fix_pil
+ subcc %g4, 0x1f, %g0
+ bg dont_fix_pil
+ sll %g4, 8, %g4
+ and %g4, SPARC_PSR_PIL_MASK, %g4
+ andn %l0, SPARC_PSR_PIL_MASK, %g5
+ or %g4, %g5, %g5
+ srl %l0, 12, %g4
+ andcc %g4, 1, %g0
+ be dont_fix_pil
+ nop
+ ba,a enable_irq
+
+
+fpu_revb:
+ srl %l0, 12, %g4 ! check if EF is set in %psr
+ andcc %g4, 1, %g0
+ be dont_fix_pil ! if FPU disabled than continue as normal
+ and %l3, 0xff, %g4
+ subcc %g4, 0x08, %g0
+ bne enable_irq ! if not a FPU exception then do two fmovs
+ set __sparc_fq, %g4
+ st %fsr, [%g4] ! if FQ is not empty and FQ[1] = fmovs
+ ld [%g4], %g4 ! than this is bug 3.14
+ srl %g4, 13, %g4
+ andcc %g4, 1, %g0
+ be dont_fix_pil
+ set __sparc_fq, %g4
+ std %fq, [%g4]
+ ld [%g4+4], %g4
+ set 0x81a00020, %g5
+ subcc %g4, %g5, %g0
+ bne,a dont_fix_pil2
+ wr %l0, SPARC_PSR_ET_MASK, %psr ! **** ENABLE TRAPS ****
+ ba,a simple_return
+
+enable_irq:
+ or %g5, SPARC_PSR_PIL_MASK, %g4
+ wr %g4, SPARC_PSR_ET_MASK, %psr ! **** ENABLE TRAPS ****
+ nop; nop; nop
+ fmovs %f0, %f0
+ ba dont_fix_pil
+ fmovs %f0, %f0
+
+ .data
+ .global __sparc_fq
+ .align 8
+__sparc_fq:
+ .word 0,0
+
+ .text
+/* end of ERC32 FPU rev.B/C fix */
+
+#else
+
+ subcc %g4, 0x11, %g0
+ bl dont_fix_pil
+ subcc %g4, 0x1f, %g0
+ bg dont_fix_pil
+ sll %g4, 8, %g4
+ and %g4, SPARC_PSR_PIL_MASK, %g4
+ andn %l0, SPARC_PSR_PIL_MASK, %g5
+ or %g4, %g5, %g5
+#endif
+
+dont_fix_pil:
+ wr %g5, SPARC_PSR_ET_MASK, %psr ! **** ENABLE TRAPS ****
+dont_fix_pil2:
+
+ /*
+ * Vector to user's handler.
+ *
+ * NOTE: TBR may no longer have vector number in it since
+ * we just enabled traps. It is definitely in l3.
+ */
+
+ sethi %hi(SYM(_ISR_Vector_table)), %g4
+ ld [%g4+%lo(SYM(_ISR_Vector_table))], %g4
+ and %l3, 0xFF, %g5 ! remove synchronous trap indicator
+ sll %g5, 2, %g5 ! g5 = offset into table
+ ld [%g4 + %g5], %g4 ! g4 = _ISR_Vector_table[ vector ]
+
+
+ ! o1 = 2nd arg = address of the ISF
+ ! WAS LOADED WHEN ISF WAS SAVED!!!
+ mov %l3, %o0 ! o0 = 1st arg = vector number
+ call %g4, 0
+ nop ! delay slot
+
+ /*
+ * Redisable traps so we can finish up the interrupt processing.
+ * This is a VERY conservative place to do this.
+ *
+ * NOTE: %l0 has the PSR which was in place when we took the trap.
+ */
+
+ mov %l0, %psr ! **** DISABLE TRAPS ****
+
+ /*
+ * Decrement ISR nest level and Thread dispatch disable level.
+ *
+ * Register usage for this section:
+ *
+ * l4 = _Thread_Dispatch_disable_level pointer
+ * l5 = _ISR_Nest_level pointer
+ * l6 = _Thread_Dispatch_disable_level value
+ * l7 = _ISR_Nest_level value
+ */
+
+ sub %l6, 1, %l6
+ st %l6, [%l4 + %lo(SYM(_Thread_Dispatch_disable_level))]
+
+ st %l7, [%l5 + %lo(SYM(_ISR_Nest_level))]
+
+ /*
+ * If dispatching is disabled (includes nested interrupt case),
+ * then do a "simple" exit.
+ */
+
+ orcc %l6, %g0, %g0 ! Is dispatching disabled?
+ bnz simple_return ! Yes, then do a "simple" exit
+ nop ! delay slot
+
+ /*
+ * If a context switch is necessary, then do fudge stack to
+ * return to the interrupt dispatcher.
+ */
+
+ sethi %hi(SYM(_Context_Switch_necessary)), %l4
+ ld [%l4 + %lo(SYM(_Context_Switch_necessary))], %l5
+
+ orcc %l5, %g0, %g0 ! Is thread switch necessary?
+ bnz SYM(_ISR_Dispatch) ! yes, then invoke the dispatcher
+ nop ! delay slot
+
+ /*
+ * Finally, check to see if signals were sent to the currently
+ * executing task. If so, we need to invoke the interrupt dispatcher.
+ */
+
+ sethi %hi(SYM(_ISR_Signals_to_thread_executing)), %l6
+ ld [%l6 + %lo(SYM(_ISR_Signals_to_thread_executing))], %l7
+
+ orcc %l7, %g0, %g0 ! Were signals sent to the currently
+ ! executing thread?
+ bz simple_return ! yes, then invoke the dispatcher
+ ! use the delay slot to clear the signals
+ ! to the currently executing task flag
+ st %g0, [%l6 + %lo(SYM(_ISR_Signals_to_thread_executing))]
+
+
+ /*
+ * Invoke interrupt dispatcher.
+ */
+
+ PUBLIC(_ISR_Dispatch)
+SYM(_ISR_Dispatch):
+
+ /*
+ * The following subtract should get us back on the interrupted
+ * tasks stack and add enough room to invoke the dispatcher.
+ * When we enable traps, we are mostly back in the context
+ * of the task and subsequent interrupts can operate normally.
+ */
+
+ sub %fp, CPU_MINIMUM_STACK_FRAME_SIZE, %sp
+
+ or %l0, SPARC_PSR_ET_MASK, %l7 ! l7 = PSR with ET=1
+ mov %l7, %psr ! **** ENABLE TRAPS ****
+ nop
+ nop
+ nop
+
+ call SYM(_Thread_Dispatch), 0
+ nop
+
+ /*
+ * We invoked _Thread_Dispatch in a state similar to the interrupted
+ * task. In order to safely be able to tinker with the register
+ * windows and get the task back to its pre-interrupt state,
+ * we need to disable interrupts disabled so we can safely tinker
+ * with the register windowing. In particular, the CWP in the PSR
+ * is fragile during this period. (See PR578.)
+ */
+ mov 2,%g1 ! syscall (disable interrupts)
+ ta 0 ! syscall (disable interrupts)
+
+ /*
+ * The CWP in place at this point may be different from
+ * that which was in effect at the beginning of the ISR if we
+ * have been context switched between the beginning of this invocation
+ * of _ISR_Handler and this point. Thus the CWP and WIM should
+ * not be changed back to their values at ISR entry time. Any
+ * changes to the PSR must preserve the CWP.
+ */
+
+simple_return:
+ ld [%fp + ISF_Y_OFFSET], %l5 ! restore y
+ wr %l5, 0, %y
+
+ ldd [%fp + ISF_PSR_OFFSET], %l0 ! restore psr, PC
+ ld [%fp + ISF_NPC_OFFSET], %l2 ! restore nPC
+ rd %psr, %l3
+ and %l3, SPARC_PSR_CWP_MASK, %l3 ! want "current" CWP
+ andn %l0, SPARC_PSR_CWP_MASK, %l0 ! want rest from task
+ or %l3, %l0, %l0 ! install it later...
+ andn %l0, SPARC_PSR_ET_MASK, %l0
+
+ /*
+ * Restore tasks global and out registers
+ */
+
+ mov %fp, %g1
+
+ ! g1 is restored later
+ ldd [%fp + ISF_G2_OFFSET], %g2 ! restore g2, g3
+ ldd [%fp + ISF_G4_OFFSET], %g4 ! restore g4, g5
+ ldd [%fp + ISF_G6_OFFSET], %g6 ! restore g6, g7
+
+ ldd [%fp + ISF_I0_OFFSET], %i0 ! restore i0, i1
+ ldd [%fp + ISF_I2_OFFSET], %i2 ! restore i2, i3
+ ldd [%fp + ISF_I4_OFFSET], %i4 ! restore i4, i5
+ ldd [%fp + ISF_I6_FP_OFFSET], %i6 ! restore i6/fp, i7
+
+ /*
+ * Registers:
+ *
+ * ALL global registers EXCEPT G1 and the input registers have
+ * already been restored and thuse off limits.
+ *
+ * The following is the contents of the local registers:
+ *
+ * l0 = original psr
+ * l1 = return address (i.e. PC)
+ * l2 = nPC
+ * l3 = CWP
+ */
+
+ /*
+ * if (CWP + 1) is an invalid window then we need to reload it.
+ *
+ * WARNING: Traps should now be disabled
+ */
+
+ mov %l0, %psr ! **** DISABLE TRAPS ****
+ nop
+ nop
+ nop
+ rd %wim, %l4
+ add %l0, 1, %l6 ! l6 = cwp + 1
+ and %l6, SPARC_PSR_CWP_MASK, %l6 ! do the modulo on it
+ srl %l4, %l6, %l5 ! l5 = win >> cwp + 1 ; shift count
+ ! and CWP are conveniently LS 5 bits
+ cmp %l5, 1 ! Is tasks window invalid?
+ bne good_task_window
+
+ /*
+ * The following code is the same as a 1 position left rotate of WIM.
+ */
+
+ sll %l4, 1, %l5 ! l5 = WIM << 1
+ srl %l4, SPARC_NUMBER_OF_REGISTER_WINDOWS-1 , %l4
+ ! l4 = WIM >> (Number Windows - 1)
+ or %l4, %l5, %l4 ! l4 = (WIM << 1) |
+ ! (WIM >> (Number Windows - 1))
+
+ /*
+ * Now restore the window just as if we underflowed to it.
+ */
+
+ wr %l4, 0, %wim ! WIM = new WIM
+ nop ! must delay after writing WIM
+ nop
+ nop
+ restore ! now into the tasks window
+
+ ldd [%g1 + CPU_STACK_FRAME_L0_OFFSET], %l0
+ ldd [%g1 + CPU_STACK_FRAME_L2_OFFSET], %l2
+ ldd [%g1 + CPU_STACK_FRAME_L4_OFFSET], %l4
+ ldd [%g1 + CPU_STACK_FRAME_L6_OFFSET], %l6
+ ldd [%g1 + CPU_STACK_FRAME_I0_OFFSET], %i0
+ ldd [%g1 + CPU_STACK_FRAME_I2_OFFSET], %i2
+ ldd [%g1 + CPU_STACK_FRAME_I4_OFFSET], %i4
+ ldd [%g1 + CPU_STACK_FRAME_I6_FP_OFFSET], %i6
+ ! reload of sp clobbers ISF
+ save ! Back to ISR dispatch window
+
+good_task_window:
+
+ mov %l0, %psr ! **** DISABLE TRAPS ****
+ ! and restore condition codes.
+ ld [%g1 + ISF_G1_OFFSET], %g1 ! restore g1
+ jmp %l1 ! transfer control and
+ rett %l2 ! go back to tasks window
+
+/* end of file */
diff --git a/cpukit/score/cpu/sparc/rtems/asm.h b/cpukit/score/cpu/sparc/rtems/asm.h
new file mode 100644
index 0000000000..96ce49f03a
--- /dev/null
+++ b/cpukit/score/cpu/sparc/rtems/asm.h
@@ -0,0 +1,121 @@
+/* asm.h
+ *
+ * This include file attempts to address the problems
+ * caused by incompatible flavors of assemblers and
+ * toolsets. It primarily addresses variations in the
+ * use of leading underscores on symbols and the requirement
+ * that register names be preceded by a %.
+ *
+ *
+ * NOTE: The spacing in the use of these macros
+ * is critical to them working as advertised.
+ *
+ * COPYRIGHT:
+ *
+ * This file is based on similar code found in newlib available
+ * from ftp.cygnus.com. The file which was used had no copyright
+ * notice. This file is freely distributable as long as the source
+ * of the file is noted.
+ *
+ * $Id$
+ */
+
+#ifndef __SPARC_ASM_h
+#define __SPARC_ASM_h
+
+/*
+ * Indicate we are in an assembly file and get the basic CPU definitions.
+ */
+
+#ifndef ASM
+#define ASM
+#endif
+
+#include <rtems/score/cpuopts.h>
+#include <rtems/score/cpu.h>
+
+/*
+ * Recent versions of GNU cpp define variables which indicate the
+ * need for underscores and percents. If not using GNU cpp or
+ * the version does not support this, then you will obviously
+ * have to define these as appropriate.
+ */
+
+/* XXX __USER_LABEL_PREFIX__ and __REGISTER_PREFIX__ do not work on gcc 2.7.0 */
+/* XXX The following ifdef magic fixes the problem but results in a warning */
+/* XXX when compiling assembly code. */
+
+#ifndef __USER_LABEL_PREFIX__
+#define __USER_LABEL_PREFIX__ _
+#endif
+
+#ifndef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__
+#endif
+
+/* ANSI concatenation macros. */
+
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+/* Use the right prefix for global labels. */
+
+#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+
+/* Use the right prefix for registers. */
+
+#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
+
+/*
+ * define macros for all of the registers on this CPU
+ *
+ * EXAMPLE: #define d0 REG (d0)
+ */
+
+/*
+ * Define macros to handle section beginning and ends.
+ */
+
+
+#define BEGIN_CODE_DCL .text
+#define END_CODE_DCL
+#define BEGIN_DATA_DCL .data
+#define END_DATA_DCL
+#define BEGIN_CODE .text
+#define END_CODE
+#define BEGIN_DATA
+#define END_DATA
+#define BEGIN_BSS
+#define END_BSS
+#define END
+
+/*
+ * Following must be tailor for a particular flavor of the C compiler.
+ * They may need to put underscores in front of the symbols.
+ */
+
+#define PUBLIC(sym) .globl SYM (sym)
+#define EXTERN(sym) .globl SYM (sym)
+
+/*
+ * Entry for traps which jump to a programmer-specified trap handler.
+ */
+
+#define TRAP(_vector, _handler) \
+ mov %psr, %l0 ; \
+ sethi %hi(_handler), %l4 ; \
+ jmp %l4+%lo(_handler); \
+ mov _vector, %l3
+
+/*
+ * Used for the reset trap to avoid a supervisor instruction
+ */
+
+#define RTRAP(_vector, _handler) \
+ mov %g0, %l0 ; \
+ sethi %hi(_handler), %l4 ; \
+ jmp %l4+%lo(_handler); \
+ mov _vector, %l3
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/sparc/rtems/score/cpu.h b/cpukit/score/cpu/sparc/rtems/score/cpu.h
new file mode 100644
index 0000000000..7207267579
--- /dev/null
+++ b/cpukit/score/cpu/sparc/rtems/score/cpu.h
@@ -0,0 +1,1000 @@
+/* cpu.h
+ *
+ * This include file contains information pertaining to the port of
+ * the executive to the SPARC processor.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __CPU_h
+#define __CPU_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/sparc.h> /* pick up machine definitions */
+#ifndef ASM
+#include <rtems/score/types.h>
+#endif
+
+/* conditional compilation parameters */
+
+/*
+ * Should the calls to _Thread_Enable_dispatch be inlined?
+ *
+ * If TRUE, then they are inlined.
+ * If FALSE, then a subroutine call is made.
+ */
+
+#define CPU_INLINE_ENABLE_DISPATCH TRUE
+
+/*
+ * Should the body of the search loops in _Thread_queue_Enqueue_priority
+ * be unrolled one time? In unrolled each iteration of the loop examines
+ * two "nodes" on the chain being searched. Otherwise, only one node
+ * is examined per iteration.
+ *
+ * If TRUE, then the loops are unrolled.
+ * If FALSE, then the loops are not unrolled.
+ *
+ * This parameter could go either way on the SPARC. The interrupt flash
+ * code is relatively lengthy given the requirements for nops following
+ * writes to the psr. But if the clock speed were high enough, this would
+ * not represent a great deal of time.
+ */
+
+#define CPU_UNROLL_ENQUEUE_PRIORITY TRUE
+
+/*
+ * Does the executive manage a dedicated interrupt stack in software?
+ *
+ * If TRUE, then a stack is allocated in _ISR_Handler_initialization.
+ * If FALSE, nothing is done.
+ *
+ * The SPARC does not have a dedicated HW interrupt stack and one has
+ * been implemented in SW.
+ */
+
+#define CPU_HAS_SOFTWARE_INTERRUPT_STACK TRUE
+
+/*
+ * Does this CPU have hardware support for a dedicated interrupt stack?
+ *
+ * If TRUE, then it must be installed during initialization.
+ * If FALSE, then no installation is performed.
+ *
+ * The SPARC does not have a dedicated HW interrupt stack.
+ */
+
+#define CPU_HAS_HARDWARE_INTERRUPT_STACK FALSE
+
+/*
+ * Do we allocate a dedicated interrupt stack in the Interrupt Manager?
+ *
+ * If TRUE, then the memory is allocated during initialization.
+ * If FALSE, then the memory is allocated during initialization.
+ */
+
+#define CPU_ALLOCATE_INTERRUPT_STACK TRUE
+
+/*
+ * Does the RTEMS invoke the user's ISR with the vector number and
+ * a pointer to the saved interrupt frame (1) or just the vector
+ * number (0)?
+ */
+
+#define CPU_ISR_PASSES_FRAME_POINTER 0
+
+/*
+ * Does the CPU have hardware floating point?
+ *
+ * If TRUE, then the FLOATING_POINT task attribute is supported.
+ * If FALSE, then the FLOATING_POINT task attribute is ignored.
+ */
+
+#if ( SPARC_HAS_FPU == 1 )
+#define CPU_HARDWARE_FP TRUE
+#else
+#define CPU_HARDWARE_FP FALSE
+#endif
+#define CPU_SOFTWARE_FP FALSE
+
+/*
+ * Are all tasks FLOATING_POINT tasks implicitly?
+ *
+ * If TRUE, then the FLOATING_POINT task attribute is assumed.
+ * If FALSE, then the FLOATING_POINT task attribute is followed.
+ */
+
+#define CPU_ALL_TASKS_ARE_FP FALSE
+
+/*
+ * Should the IDLE task have a floating point context?
+ *
+ * If TRUE, then the IDLE task is created as a FLOATING_POINT task
+ * and it has a floating point context which is switched in and out.
+ * If FALSE, then the IDLE task does not have a floating point context.
+ */
+
+#define CPU_IDLE_TASK_IS_FP FALSE
+
+/*
+ * Should the saving of the floating point registers be deferred
+ * until a context switch is made to another different floating point
+ * task?
+ *
+ * If TRUE, then the floating point context will not be stored until
+ * necessary. It will remain in the floating point registers and not
+ * disturned until another floating point task is switched to.
+ *
+ * If FALSE, then the floating point context is saved when a floating
+ * point task is switched out and restored when the next floating point
+ * task is restored. The state of the floating point registers between
+ * those two operations is not specified.
+ */
+
+#define CPU_USE_DEFERRED_FP_SWITCH TRUE
+
+/*
+ * Does this port provide a CPU dependent IDLE task implementation?
+ *
+ * If TRUE, then the routine _CPU_Thread_Idle_body
+ * must be provided and is the default IDLE thread body instead of
+ * _CPU_Thread_Idle_body.
+ *
+ * If FALSE, then use the generic IDLE thread body if the BSP does
+ * not provide one.
+ */
+
+#define CPU_PROVIDES_IDLE_THREAD_BODY FALSE
+
+/*
+ * Does the stack grow up (toward higher addresses) or down
+ * (toward lower addresses)?
+ *
+ * If TRUE, then the grows upward.
+ * If FALSE, then the grows toward smaller addresses.
+ *
+ * The stack grows to lower addresses on the SPARC.
+ */
+
+#define CPU_STACK_GROWS_UP FALSE
+
+/*
+ * The following is the variable attribute used to force alignment
+ * of critical data structures. On some processors it may make
+ * sense to have these aligned on tighter boundaries than
+ * the minimum requirements of the compiler in order to have as
+ * much of the critical data area as possible in a cache line.
+ *
+ * The SPARC does not appear to have particularly strict alignment
+ * requirements. This value was chosen to take advantages of caches.
+ */
+
+#define CPU_STRUCTURE_ALIGNMENT __attribute__ ((aligned (16)))
+
+/*
+ * Define what is required to specify how the network to host conversion
+ * routines are handled.
+ */
+
+#define CPU_HAS_OWN_HOST_TO_NETWORK_ROUTINES FALSE
+#define CPU_BIG_ENDIAN TRUE
+#define CPU_LITTLE_ENDIAN FALSE
+
+/*
+ * The following defines the number of bits actually used in the
+ * interrupt field of the task mode. How those bits map to the
+ * CPU interrupt levels is defined by the routine _CPU_ISR_Set_level().
+ *
+ * The SPARC has 16 interrupt levels in the PIL field of the PSR.
+ */
+
+#define CPU_MODES_INTERRUPT_MASK 0x0000000F
+
+/*
+ * This structure represents the organization of the minimum stack frame
+ * for the SPARC. More framing information is required in certain situaions
+ * such as when there are a large number of out parameters or when the callee
+ * must save floating point registers.
+ */
+
+#ifndef ASM
+
+typedef struct {
+ uint32_t l0;
+ uint32_t l1;
+ uint32_t l2;
+ uint32_t l3;
+ uint32_t l4;
+ uint32_t l5;
+ uint32_t l6;
+ uint32_t l7;
+ uint32_t i0;
+ uint32_t i1;
+ uint32_t i2;
+ uint32_t i3;
+ uint32_t i4;
+ uint32_t i5;
+ uint32_t i6_fp;
+ uint32_t i7;
+ void *structure_return_address;
+ /*
+ * The following are for the callee to save the register arguments in
+ * should this be necessary.
+ */
+ uint32_t saved_arg0;
+ uint32_t saved_arg1;
+ uint32_t saved_arg2;
+ uint32_t saved_arg3;
+ uint32_t saved_arg4;
+ uint32_t saved_arg5;
+ uint32_t pad0;
+} CPU_Minimum_stack_frame;
+
+#endif /* ASM */
+
+#define CPU_STACK_FRAME_L0_OFFSET 0x00
+#define CPU_STACK_FRAME_L1_OFFSET 0x04
+#define CPU_STACK_FRAME_L2_OFFSET 0x08
+#define CPU_STACK_FRAME_L3_OFFSET 0x0c
+#define CPU_STACK_FRAME_L4_OFFSET 0x10
+#define CPU_STACK_FRAME_L5_OFFSET 0x14
+#define CPU_STACK_FRAME_L6_OFFSET 0x18
+#define CPU_STACK_FRAME_L7_OFFSET 0x1c
+#define CPU_STACK_FRAME_I0_OFFSET 0x20
+#define CPU_STACK_FRAME_I1_OFFSET 0x24
+#define CPU_STACK_FRAME_I2_OFFSET 0x28
+#define CPU_STACK_FRAME_I3_OFFSET 0x2c
+#define CPU_STACK_FRAME_I4_OFFSET 0x30
+#define CPU_STACK_FRAME_I5_OFFSET 0x34
+#define CPU_STACK_FRAME_I6_FP_OFFSET 0x38
+#define CPU_STACK_FRAME_I7_OFFSET 0x3c
+#define CPU_STRUCTURE_RETURN_ADDRESS_OFFSET 0x40
+#define CPU_STACK_FRAME_SAVED_ARG0_OFFSET 0x44
+#define CPU_STACK_FRAME_SAVED_ARG1_OFFSET 0x48
+#define CPU_STACK_FRAME_SAVED_ARG2_OFFSET 0x4c
+#define CPU_STACK_FRAME_SAVED_ARG3_OFFSET 0x50
+#define CPU_STACK_FRAME_SAVED_ARG4_OFFSET 0x54
+#define CPU_STACK_FRAME_SAVED_ARG5_OFFSET 0x58
+#define CPU_STACK_FRAME_PAD0_OFFSET 0x5c
+
+#define CPU_MINIMUM_STACK_FRAME_SIZE 0x60
+
+/*
+ * Contexts
+ *
+ * Generally there are 2 types of context to save.
+ * 1. Interrupt registers to save
+ * 2. Task level registers to save
+ *
+ * This means we have the following 3 context items:
+ * 1. task level context stuff:: Context_Control
+ * 2. floating point task stuff:: Context_Control_fp
+ * 3. special interrupt level context :: Context_Control_interrupt
+ *
+ * On the SPARC, we are relatively conservative in that we save most
+ * of the CPU state in the context area. The ET (enable trap) bit and
+ * the CWP (current window pointer) fields of the PSR are considered
+ * system wide resources and are not maintained on a per-thread basis.
+ */
+
+#ifndef ASM
+
+typedef struct {
+ /*
+ * Using a double g0_g1 will put everything in this structure on a
+ * double word boundary which allows us to use double word loads
+ * and stores safely in the context switch.
+ */
+ double g0_g1;
+ uint32_t g2;
+ uint32_t g3;
+ uint32_t g4;
+ uint32_t g5;
+ uint32_t g6;
+ uint32_t g7;
+
+ uint32_t l0;
+ uint32_t l1;
+ uint32_t l2;
+ uint32_t l3;
+ uint32_t l4;
+ uint32_t l5;
+ uint32_t l6;
+ uint32_t l7;
+
+ uint32_t i0;
+ uint32_t i1;
+ uint32_t i2;
+ uint32_t i3;
+ uint32_t i4;
+ uint32_t i5;
+ uint32_t i6_fp;
+ uint32_t i7;
+
+ uint32_t o0;
+ uint32_t o1;
+ uint32_t o2;
+ uint32_t o3;
+ uint32_t o4;
+ uint32_t o5;
+ uint32_t o6_sp;
+ uint32_t o7;
+
+ uint32_t psr;
+} Context_Control;
+
+#endif /* ASM */
+
+/*
+ * Offsets of fields with Context_Control for assembly routines.
+ */
+
+#define G0_OFFSET 0x00
+#define G1_OFFSET 0x04
+#define G2_OFFSET 0x08
+#define G3_OFFSET 0x0C
+#define G4_OFFSET 0x10
+#define G5_OFFSET 0x14
+#define G6_OFFSET 0x18
+#define G7_OFFSET 0x1C
+
+#define L0_OFFSET 0x20
+#define L1_OFFSET 0x24
+#define L2_OFFSET 0x28
+#define L3_OFFSET 0x2C
+#define L4_OFFSET 0x30
+#define L5_OFFSET 0x34
+#define L6_OFFSET 0x38
+#define L7_OFFSET 0x3C
+
+#define I0_OFFSET 0x40
+#define I1_OFFSET 0x44
+#define I2_OFFSET 0x48
+#define I3_OFFSET 0x4C
+#define I4_OFFSET 0x50
+#define I5_OFFSET 0x54
+#define I6_FP_OFFSET 0x58
+#define I7_OFFSET 0x5C
+
+#define O0_OFFSET 0x60
+#define O1_OFFSET 0x64
+#define O2_OFFSET 0x68
+#define O3_OFFSET 0x6C
+#define O4_OFFSET 0x70
+#define O5_OFFSET 0x74
+#define O6_SP_OFFSET 0x78
+#define O7_OFFSET 0x7C
+
+#define PSR_OFFSET 0x80
+
+#define CONTEXT_CONTROL_SIZE 0x84
+
+/*
+ * The floating point context area.
+ */
+
+#ifndef ASM
+
+typedef struct {
+ double f0_f1;
+ double f2_f3;
+ double f4_f5;
+ double f6_f7;
+ double f8_f9;
+ double f10_f11;
+ double f12_f13;
+ double f14_f15;
+ double f16_f17;
+ double f18_f19;
+ double f20_f21;
+ double f22_f23;
+ double f24_f25;
+ double f26_f27;
+ double f28_f29;
+ double f30_f31;
+ uint32_t fsr;
+} Context_Control_fp;
+
+#endif /* ASM */
+
+/*
+ * Offsets of fields with Context_Control_fp for assembly routines.
+ */
+
+#define FO_F1_OFFSET 0x00
+#define F2_F3_OFFSET 0x08
+#define F4_F5_OFFSET 0x10
+#define F6_F7_OFFSET 0x18
+#define F8_F9_OFFSET 0x20
+#define F1O_F11_OFFSET 0x28
+#define F12_F13_OFFSET 0x30
+#define F14_F15_OFFSET 0x38
+#define F16_F17_OFFSET 0x40
+#define F18_F19_OFFSET 0x48
+#define F2O_F21_OFFSET 0x50
+#define F22_F23_OFFSET 0x58
+#define F24_F25_OFFSET 0x60
+#define F26_F27_OFFSET 0x68
+#define F28_F29_OFFSET 0x70
+#define F3O_F31_OFFSET 0x78
+#define FSR_OFFSET 0x80
+
+#define CONTEXT_CONTROL_FP_SIZE 0x84
+
+#ifndef ASM
+
+/*
+ * Context saved on stack for an interrupt.
+ *
+ * NOTE: The PSR, PC, and NPC are only saved in this structure for the
+ * benefit of the user's handler.
+ */
+
+typedef struct {
+ CPU_Minimum_stack_frame Stack_frame;
+ uint32_t psr;
+ uint32_t pc;
+ uint32_t npc;
+ uint32_t g1;
+ uint32_t g2;
+ uint32_t g3;
+ uint32_t g4;
+ uint32_t g5;
+ uint32_t g6;
+ uint32_t g7;
+ uint32_t i0;
+ uint32_t i1;
+ uint32_t i2;
+ uint32_t i3;
+ uint32_t i4;
+ uint32_t i5;
+ uint32_t i6_fp;
+ uint32_t i7;
+ uint32_t y;
+ uint32_t tpc;
+} CPU_Interrupt_frame;
+
+#endif /* ASM */
+
+/*
+ * Offsets of fields with CPU_Interrupt_frame for assembly routines.
+ */
+
+#define ISF_STACK_FRAME_OFFSET 0x00
+#define ISF_PSR_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x00
+#define ISF_PC_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x04
+#define ISF_NPC_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x08
+#define ISF_G1_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x0c
+#define ISF_G2_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x10
+#define ISF_G3_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x14
+#define ISF_G4_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x18
+#define ISF_G5_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x1c
+#define ISF_G6_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x20
+#define ISF_G7_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x24
+#define ISF_I0_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x28
+#define ISF_I1_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x2c
+#define ISF_I2_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x30
+#define ISF_I3_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x34
+#define ISF_I4_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x38
+#define ISF_I5_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x3c
+#define ISF_I6_FP_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x40
+#define ISF_I7_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x44
+#define ISF_Y_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x48
+#define ISF_TPC_OFFSET CPU_MINIMUM_STACK_FRAME_SIZE + 0x4c
+
+#define CONTEXT_CONTROL_INTERRUPT_FRAME_SIZE CPU_MINIMUM_STACK_FRAME_SIZE + 0x50
+#ifndef ASM
+
+/*
+ * The following table contains the information required to configure
+ * the processor specific parameters.
+ */
+
+typedef struct {
+ void (*pretasking_hook)( void );
+ void (*predriver_hook)( void );
+ void (*postdriver_hook)( void );
+ void (*idle_task)( void );
+ boolean do_zero_of_workspace;
+ uint32_t idle_task_stack_size;
+ uint32_t interrupt_stack_size;
+ uint32_t extra_mpci_receive_server_stack;
+ void * (*stack_allocate_hook)( uint32_t );
+ void (*stack_free_hook)( void* );
+ /* end of fields required on all CPUs */
+
+} rtems_cpu_table;
+
+/*
+ * Macros to access required entires in the CPU Table are in
+ * the file rtems/system.h.
+ */
+
+/*
+ * Macros to access SPARC specific additions to the CPU Table
+ */
+
+/* There are no CPU specific additions to the CPU Table for this port. */
+
+/*
+ * This variable is contains the initialize context for the FP unit.
+ * It is filled in by _CPU_Initialize and copied into the task's FP
+ * context area during _CPU_Context_Initialize.
+ */
+
+SCORE_EXTERN Context_Control_fp _CPU_Null_fp_context CPU_STRUCTURE_ALIGNMENT;
+
+/*
+ * This stack is allocated by the Interrupt Manager and the switch
+ * is performed in _ISR_Handler. These variables contain pointers
+ * to the lowest and highest addresses in the chunk of memory allocated
+ * for the interrupt stack. Since it is unknown whether the stack
+ * grows up or down (in general), this give the CPU dependent
+ * code the option of picking the version it wants to use. Thus
+ * both must be present if either is.
+ *
+ * The SPARC supports a software based interrupt stack and these
+ * are required.
+ */
+
+SCORE_EXTERN void *_CPU_Interrupt_stack_low;
+SCORE_EXTERN void *_CPU_Interrupt_stack_high;
+
+/*
+ * The following type defines an entry in the SPARC's trap table.
+ *
+ * NOTE: The instructions chosen are RTEMS dependent although one is
+ * obligated to use two of the four instructions to perform a
+ * long jump. The other instructions load one register with the
+ * trap type (a.k.a. vector) and another with the psr.
+ */
+
+typedef struct {
+ uint32_t mov_psr_l0; /* mov %psr, %l0 */
+ uint32_t sethi_of_handler_to_l4; /* sethi %hi(_handler), %l4 */
+ uint32_t jmp_to_low_of_handler_plus_l4; /* jmp %l4 + %lo(_handler) */
+ uint32_t mov_vector_l3; /* mov _vector, %l3 */
+} CPU_Trap_table_entry;
+
+/*
+ * This is the set of opcodes for the instructions loaded into a trap
+ * table entry. The routine which installs a handler is responsible
+ * for filling in the fields for the _handler address and the _vector
+ * trap type.
+ *
+ * The constants following this structure are masks for the fields which
+ * must be filled in when the handler is installed.
+ */
+
+extern const CPU_Trap_table_entry _CPU_Trap_slot_template;
+
+/*
+ * The size of the floating point context area.
+ */
+
+#define CPU_CONTEXT_FP_SIZE sizeof( Context_Control_fp )
+
+#endif
+
+/*
+ * Amount of extra stack (above minimum stack size) required by
+ * MPCI receive server thread. Remember that in a multiprocessor
+ * system this thread must exist and be able to process all directives.
+ */
+
+#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 1024
+
+/*
+ * This defines the number of entries in the ISR_Vector_table managed
+ * by the executive.
+ *
+ * On the SPARC, there are really only 256 vectors. However, the executive
+ * has no easy, fast, reliable way to determine which traps are synchronous
+ * and which are asynchronous. By default, synchronous traps return to the
+ * instruction which caused the interrupt. So if you install a software
+ * trap handler as an executive interrupt handler (which is desirable since
+ * RTEMS takes care of window and register issues), then the executive needs
+ * to know that the return address is to the trap rather than the instruction
+ * following the trap.
+ *
+ * So vectors 0 through 255 are treated as regular asynchronous traps which
+ * provide the "correct" return address. Vectors 256 through 512 are assumed
+ * by the executive to be synchronous and to require that the return address
+ * be fudged.
+ *
+ * If you use this mechanism to install a trap handler which must reexecute
+ * the instruction which caused the trap, then it should be installed as
+ * an asynchronous trap. This will avoid the executive changing the return
+ * address.
+ */
+
+#define CPU_INTERRUPT_NUMBER_OF_VECTORS 256
+#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER 511
+
+#define SPARC_SYNCHRONOUS_TRAP_BIT_MASK 0x100
+#define SPARC_ASYNCHRONOUS_TRAP( _trap ) (_trap)
+#define SPARC_SYNCHRONOUS_TRAP( _trap ) ((_trap) + 256 )
+
+#define SPARC_REAL_TRAP_NUMBER( _trap ) ((_trap) % 256)
+
+/*
+ * This is defined if the port has a special way to report the ISR nesting
+ * level. Most ports maintain the variable _ISR_Nest_level.
+ */
+
+#define CPU_PROVIDES_ISR_IS_IN_PROGRESS FALSE
+
+/*
+ * Should be large enough to run all tests. This insures
+ * that a "reasonable" small application should not have any problems.
+ *
+ * This appears to be a fairly generous number for the SPARC since
+ * represents a call depth of about 20 routines based on the minimum
+ * stack frame.
+ */
+
+#define CPU_STACK_MINIMUM_SIZE (1024*4)
+
+/*
+ * CPU's worst alignment requirement for data types on a byte boundary. This
+ * alignment does not take into account the requirements for the stack.
+ *
+ * On the SPARC, this is required for double word loads and stores.
+ */
+
+#define CPU_ALIGNMENT 8
+
+/*
+ * This number corresponds to the byte alignment requirement for the
+ * heap handler. This alignment requirement may be stricter than that
+ * for the data types alignment specified by CPU_ALIGNMENT. It is
+ * common for the heap to follow the same alignment requirement as
+ * CPU_ALIGNMENT. If the CPU_ALIGNMENT is strict enough for the heap,
+ * then this should be set to CPU_ALIGNMENT.
+ *
+ * NOTE: This does not have to be a power of 2. It does have to
+ * be greater or equal to than CPU_ALIGNMENT.
+ */
+
+#define CPU_HEAP_ALIGNMENT CPU_ALIGNMENT
+
+/*
+ * This number corresponds to the byte alignment requirement for memory
+ * buffers allocated by the partition manager. This alignment requirement
+ * may be stricter than that for the data types alignment specified by
+ * CPU_ALIGNMENT. It is common for the partition to follow the same
+ * alignment requirement as CPU_ALIGNMENT. If the CPU_ALIGNMENT is strict
+ * enough for the partition, then this should be set to CPU_ALIGNMENT.
+ *
+ * NOTE: This does not have to be a power of 2. It does have to
+ * be greater or equal to than CPU_ALIGNMENT.
+ */
+
+#define CPU_PARTITION_ALIGNMENT CPU_ALIGNMENT
+
+/*
+ * This number corresponds to the byte alignment requirement for the
+ * stack. This alignment requirement may be stricter than that for the
+ * data types alignment specified by CPU_ALIGNMENT. If the CPU_ALIGNMENT
+ * is strict enough for the stack, then this should be set to 0.
+ *
+ * NOTE: This must be a power of 2 either 0 or greater than CPU_ALIGNMENT.
+ *
+ * The alignment restrictions for the SPARC are not that strict but this
+ * should unsure that the stack is always sufficiently alignment that the
+ * window overflow, underflow, and flush routines can use double word loads
+ * and stores.
+ */
+
+#define CPU_STACK_ALIGNMENT 16
+
+#ifndef ASM
+
+extern unsigned int sparc_disable_interrupts();
+extern void sparc_enable_interrupts();
+
+/*
+ * ISR handler macros
+ */
+
+/*
+ * Support routine to initialize the RTEMS vector table after it is allocated.
+ */
+
+#define _CPU_Initialize_vectors()
+
+/*
+ * Disable all interrupts for a critical section. The previous
+ * level is returned in _level.
+ */
+
+#define _CPU_ISR_Disable( _level ) \
+ (_level) = sparc_disable_interrupts()
+
+/*
+ * Enable interrupts to the previous level (returned by _CPU_ISR_Disable).
+ * This indicates the end of a critical section. The parameter
+ * _level is not modified.
+ */
+
+#define _CPU_ISR_Enable( _level ) \
+ sparc_enable_interrupts( _level )
+/*
+ * This temporarily restores the interrupt to _level before immediately
+ * disabling them again. This is used to divide long critical
+ * sections into two or more parts. The parameter _level is not
+ * modified.
+ */
+
+#define _CPU_ISR_Flash( _level ) \
+ sparc_flash_interrupts( _level )
+
+/*
+ * Map interrupt level in task mode onto the hardware that the CPU
+ * actually provides. Currently, interrupt levels which do not
+ * map onto the CPU in a straight fashion are undefined.
+ */
+
+#define _CPU_ISR_Set_level( _newlevel ) \
+ sparc_enable_interrupts( _newlevel << 8)
+
+uint32_t _CPU_ISR_Get_level( void );
+
+/* end of ISR handler macros */
+
+/* Context handler macros */
+
+/*
+ * Initialize the context to a state suitable for starting a
+ * task after a context restore operation. Generally, this
+ * involves:
+ *
+ * - setting a starting address
+ * - preparing the stack
+ * - preparing the stack and frame pointers
+ * - setting the proper interrupt level in the context
+ * - initializing the floating point context
+ *
+ * NOTE: Implemented as a subroutine for the SPARC port.
+ */
+
+void _CPU_Context_Initialize(
+ Context_Control *the_context,
+ uint32_t *stack_base,
+ uint32_t size,
+ uint32_t new_level,
+ void *entry_point,
+ boolean is_fp
+);
+
+/*
+ * This routine is responsible for somehow restarting the currently
+ * executing task.
+ *
+ * On the SPARC, this is is relatively painless but requires a small
+ * amount of wrapper code before using the regular restore code in
+ * of the context switch.
+ */
+
+#define _CPU_Context_Restart_self( _the_context ) \
+ _CPU_Context_restore( (_the_context) );
+
+/*
+ * The FP context area for the SPARC is a simple structure and nothing
+ * special is required to find the "starting load point"
+ */
+
+#define _CPU_Context_Fp_start( _base, _offset ) \
+ ( (void *) _Addresses_Add_offset( (_base), (_offset) ) )
+
+/*
+ * This routine initializes the FP context area passed to it to.
+ *
+ * The SPARC allows us to use the simple initialization model
+ * in which an "initial" FP context was saved into _CPU_Null_fp_context
+ * at CPU initialization and it is simply copied into the destination
+ * context.
+ */
+
+#define _CPU_Context_Initialize_fp( _destination ) \
+ do { \
+ *((Context_Control_fp *) *((void **) _destination)) = _CPU_Null_fp_context; \
+ } while (0)
+
+/* end of Context handler macros */
+
+/* Fatal Error manager macros */
+
+/*
+ * This routine copies _error into a known place -- typically a stack
+ * location or a register, optionally disables interrupts, and
+ * halts/stops the CPU.
+ */
+
+#define _CPU_Fatal_halt( _error ) \
+ do { \
+ uint32_t level; \
+ \
+ level = sparc_disable_interrupts(); \
+ asm volatile ( "mov %0, %%g1 " : "=r" (level) : "0" (level) ); \
+ while (1); /* loop forever */ \
+ } while (0)
+
+/* end of Fatal Error manager macros */
+
+/* Bitfield handler macros */
+
+/*
+ * The SPARC port uses the generic C algorithm for bitfield scan if the
+ * CPU model does not have a scan instruction.
+ */
+
+#if ( SPARC_HAS_BITSCAN == 0 )
+#define CPU_USE_GENERIC_BITFIELD_CODE TRUE
+#define CPU_USE_GENERIC_BITFIELD_DATA TRUE
+#else
+#error "scan instruction not currently supported by RTEMS!!"
+#endif
+
+/* end of Bitfield handler macros */
+
+/* Priority handler handler macros */
+
+/*
+ * The SPARC port uses the generic C algorithm for bitfield scan if the
+ * CPU model does not have a scan instruction.
+ */
+
+#if ( SPARC_HAS_BITSCAN == 1 )
+#error "scan instruction not currently supported by RTEMS!!"
+#endif
+
+/* end of Priority handler macros */
+
+/* functions */
+
+/*
+ * _CPU_Initialize
+ *
+ * This routine performs CPU dependent initialization.
+ */
+
+void _CPU_Initialize(
+ rtems_cpu_table *cpu_table,
+ void (*thread_dispatch)
+);
+
+/*
+ * _CPU_ISR_install_raw_handler
+ *
+ * This routine installs new_handler to be directly called from the trap
+ * table.
+ */
+
+void _CPU_ISR_install_raw_handler(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+);
+
+/*
+ * _CPU_ISR_install_vector
+ *
+ * This routine installs an interrupt vector.
+ */
+
+void _CPU_ISR_install_vector(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+);
+
+#if (CPU_PROVIDES_IDLE_THREAD_BODY == TRUE)
+
+/*
+ * _CPU_Thread_Idle_body
+ *
+ * Some SPARC implementations have low power, sleep, or idle modes. This
+ * tries to take advantage of those models.
+ */
+
+void _CPU_Thread_Idle_body( void );
+
+#endif /* CPU_PROVIDES_IDLE_THREAD_BODY */
+
+/*
+ * _CPU_Context_switch
+ *
+ * This routine switches from the run context to the heir context.
+ */
+
+void _CPU_Context_switch(
+ Context_Control *run,
+ Context_Control *heir
+);
+
+/*
+ * _CPU_Context_restore
+ *
+ * This routine is generally used only to restart self in an
+ * efficient manner.
+ */
+
+void _CPU_Context_restore(
+ Context_Control *new_context
+);
+
+/*
+ * _CPU_Context_save_fp
+ *
+ * This routine saves the floating point context passed to it.
+ */
+
+void _CPU_Context_save_fp(
+ void **fp_context_ptr
+);
+
+/*
+ * _CPU_Context_restore_fp
+ *
+ * This routine restores the floating point context passed to it.
+ */
+
+void _CPU_Context_restore_fp(
+ void **fp_context_ptr
+);
+
+/*
+ * CPU_swap_u32
+ *
+ * The following routine swaps the endian format of an unsigned int.
+ * It must be static because it is referenced indirectly.
+ *
+ * This version will work on any processor, but if you come across a better
+ * way for the SPARC PLEASE use it. The most common way to swap a 32-bit
+ * entity as shown below is not any more efficient on the SPARC.
+ *
+ * swap least significant two bytes with 16-bit rotate
+ * swap upper and lower 16-bits
+ * swap most significant two bytes with 16-bit rotate
+ *
+ * It is not obvious how the SPARC can do significantly better than the
+ * generic code. gcc 2.7.0 only generates about 12 instructions for the
+ * following code at optimization level four (i.e. -O4).
+ */
+
+static inline unsigned int CPU_swap_u32(
+ unsigned int value
+)
+{
+ uint32_t byte1, byte2, byte3, byte4, swapped;
+
+ byte4 = (value >> 24) & 0xff;
+ byte3 = (value >> 16) & 0xff;
+ byte2 = (value >> 8) & 0xff;
+ byte1 = value & 0xff;
+
+ swapped = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
+ return( swapped );
+}
+
+#define CPU_swap_u16( value ) \
+ (((value&0xff) << 8) | ((value >> 8)&0xff))
+
+#endif ASM
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/score/cpu/sparc/rtems/score/sparc.h b/cpukit/score/cpu/sparc/rtems/score/sparc.h
new file mode 100644
index 0000000000..07fe0fb3c9
--- /dev/null
+++ b/cpukit/score/cpu/sparc/rtems/score/sparc.h
@@ -0,0 +1,266 @@
+/* sparc.h
+ *
+ * This include file contains information pertaining to the SPARC
+ * processor family.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef _INCLUDE_SPARC_h
+#define _INCLUDE_SPARC_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This file contains the information required to build
+ * RTEMS for a particular member of the "sparc" family. It does
+ * this by setting variables to indicate which implementation
+ * dependent features are present in a particular member
+ * of the family.
+ *
+ * Currently recognized feature flags:
+ *
+ * + SPARC_HAS_FPU
+ * 0 - no HW FPU
+ * 1 - has HW FPU (assumed to be compatible w/90C602)
+ *
+ * + SPARC_HAS_BITSCAN
+ * 0 - does not have scan instructions
+ * 1 - has scan instruction (not currently implemented)
+ *
+ * + SPARC_NUMBER_OF_REGISTER_WINDOWS
+ * 8 is the most common number supported by SPARC implementations.
+ * SPARC_PSR_CWP_MASK is derived from this value.
+ */
+
+/*
+ * Some higher end SPARCs have a bitscan instructions. It would
+ * be nice to take advantage of them. Right now, there is no
+ * port to a CPU model with this feature and no (untested) code
+ * that is based on this feature flag.
+ */
+
+#define SPARC_HAS_BITSCAN 0
+
+/*
+ * This should be OK until a port to a higher end SPARC processor
+ * is made that has more than 8 register windows. If this cannot
+ * be determined based on multilib settings (v7/v8/v9), then the
+ * cpu_asm.S code that depends on this will have to move to libcpu.
+ */
+
+#define SPARC_NUMBER_OF_REGISTER_WINDOWS 8
+
+/*
+ * This should be determined based on some soft float derived
+ * cpp predefine but gcc does not currently give us that information.
+ */
+
+
+#if defined(_SOFT_FLOAT)
+#define SPARC_HAS_FPU 0
+#else
+#define SPARC_HAS_FPU 1
+#endif
+
+#if SPARC_HAS_FPU
+#define CPU_MODEL_NAME "w/FPU"
+#else
+#define CPU_MODEL_NAME "w/soft-float"
+#endif
+
+/*
+ * Define the name of the CPU family.
+ */
+
+#define CPU_NAME "SPARC"
+
+/*
+ * Miscellaneous constants
+ */
+
+/*
+ * PSR masks and starting bit positions
+ *
+ * NOTE: Reserved bits are ignored.
+ */
+
+#if (SPARC_NUMBER_OF_REGISTER_WINDOWS == 8)
+#define SPARC_PSR_CWP_MASK 0x07 /* bits 0 - 4 */
+#elif (SPARC_NUMBER_OF_REGISTER_WINDOWS == 16)
+#define SPARC_PSR_CWP_MASK 0x0F /* bits 0 - 4 */
+#elif (SPARC_NUMBER_OF_REGISTER_WINDOWS == 32)
+#define SPARC_PSR_CWP_MASK 0x1F /* bits 0 - 4 */
+#else
+#error "Unsupported number of register windows for this cpu"
+#endif
+
+#define SPARC_PSR_ET_MASK 0x00000020 /* bit 5 */
+#define SPARC_PSR_PS_MASK 0x00000040 /* bit 6 */
+#define SPARC_PSR_S_MASK 0x00000080 /* bit 7 */
+#define SPARC_PSR_PIL_MASK 0x00000F00 /* bits 8 - 11 */
+#define SPARC_PSR_EF_MASK 0x00001000 /* bit 12 */
+#define SPARC_PSR_EC_MASK 0x00002000 /* bit 13 */
+#define SPARC_PSR_ICC_MASK 0x00F00000 /* bits 20 - 23 */
+#define SPARC_PSR_VER_MASK 0x0F000000 /* bits 24 - 27 */
+#define SPARC_PSR_IMPL_MASK 0xF0000000 /* bits 28 - 31 */
+
+#define SPARC_PSR_CWP_BIT_POSITION 0 /* bits 0 - 4 */
+#define SPARC_PSR_ET_BIT_POSITION 5 /* bit 5 */
+#define SPARC_PSR_PS_BIT_POSITION 6 /* bit 6 */
+#define SPARC_PSR_S_BIT_POSITION 7 /* bit 7 */
+#define SPARC_PSR_PIL_BIT_POSITION 8 /* bits 8 - 11 */
+#define SPARC_PSR_EF_BIT_POSITION 12 /* bit 12 */
+#define SPARC_PSR_EC_BIT_POSITION 13 /* bit 13 */
+#define SPARC_PSR_ICC_BIT_POSITION 20 /* bits 20 - 23 */
+#define SPARC_PSR_VER_BIT_POSITION 24 /* bits 24 - 27 */
+#define SPARC_PSR_IMPL_BIT_POSITION 28 /* bits 28 - 31 */
+
+#ifndef ASM
+
+/*
+ * Standard nop
+ */
+
+#define nop() \
+ do { \
+ asm volatile ( "nop" ); \
+ } while ( 0 )
+
+/*
+ * Get and set the PSR
+ */
+
+#define sparc_get_psr( _psr ) \
+ do { \
+ (_psr) = 0; \
+ asm volatile( "rd %%psr, %0" : "=r" (_psr) : "0" (_psr) ); \
+ } while ( 0 )
+
+#define sparc_set_psr( _psr ) \
+ do { \
+ asm volatile ( "mov %0, %%psr " : "=r" ((_psr)) : "0" ((_psr)) ); \
+ nop(); \
+ nop(); \
+ nop(); \
+ } while ( 0 )
+
+/*
+ * Get and set the TBR
+ */
+
+#define sparc_get_tbr( _tbr ) \
+ do { \
+ (_tbr) = 0; /* to avoid unitialized warnings */ \
+ asm volatile( "rd %%tbr, %0" : "=r" (_tbr) : "0" (_tbr) ); \
+ } while ( 0 )
+
+#define sparc_set_tbr( _tbr ) \
+ do { \
+ asm volatile( "wr %0, 0, %%tbr" : "=r" (_tbr) : "0" (_tbr) ); \
+ } while ( 0 )
+
+/*
+ * Get and set the WIM
+ */
+
+#define sparc_get_wim( _wim ) \
+ do { \
+ asm volatile( "rd %%wim, %0" : "=r" (_wim) : "0" (_wim) ); \
+ } while ( 0 )
+
+#define sparc_set_wim( _wim ) \
+ do { \
+ asm volatile( "wr %0, %%wim" : "=r" (_wim) : "0" (_wim) ); \
+ nop(); \
+ nop(); \
+ nop(); \
+ } while ( 0 )
+
+/*
+ * Get and set the Y
+ */
+
+#define sparc_get_y( _y ) \
+ do { \
+ asm volatile( "rd %%y, %0" : "=r" (_y) : "0" (_y) ); \
+ } while ( 0 )
+
+#define sparc_set_y( _y ) \
+ do { \
+ asm volatile( "wr %0, %%y" : "=r" (_y) : "0" (_y) ); \
+ } while ( 0 )
+
+/*
+ * Manipulate the interrupt level in the psr
+ *
+ */
+
+/*
+#define sparc_disable_interrupts( _level ) \
+ do { \
+ register unsigned int _newlevel; \
+ \
+ sparc_get_psr( _level ); \
+ (_newlevel) = (_level) | SPARC_PSR_PIL_MASK; \
+ sparc_set_psr( _newlevel ); \
+ } while ( 0 )
+
+#define sparc_enable_interrupts( _level ) \
+ do { \
+ unsigned int _tmp; \
+ \
+ sparc_get_psr( _tmp ); \
+ _tmp &= ~SPARC_PSR_PIL_MASK; \
+ _tmp |= (_level) & SPARC_PSR_PIL_MASK; \
+ sparc_set_psr( _tmp ); \
+ } while ( 0 )
+*/
+
+#define sparc_flash_interrupts( _level ) \
+ do { \
+ register uint32_t _ignored = 0; \
+ \
+ sparc_enable_interrupts( (_level) ); \
+ sparc_disable_interrupts( _ignored ); \
+ } while ( 0 )
+
+/*
+#define sparc_set_interrupt_level( _new_level ) \
+ do { \
+ register uint32_t _new_psr_level = 0; \
+ \
+ sparc_get_psr( _new_psr_level ); \
+ _new_psr_level &= ~SPARC_PSR_PIL_MASK; \
+ _new_psr_level |= \
+ (((_new_level) << SPARC_PSR_PIL_BIT_POSITION) & SPARC_PSR_PIL_MASK); \
+ sparc_set_psr( _new_psr_level ); \
+ } while ( 0 )
+*/
+
+#define sparc_get_interrupt_level( _level ) \
+ do { \
+ register uint32_t _psr_level = 0; \
+ \
+ sparc_get_psr( _psr_level ); \
+ (_level) = \
+ (_psr_level & SPARC_PSR_PIL_MASK) >> SPARC_PSR_PIL_BIT_POSITION; \
+ } while ( 0 )
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ! _INCLUDE_SPARC_h */
+/* end of include file */
diff --git a/cpukit/score/cpu/sparc/rtems/score/types.h b/cpukit/score/cpu/sparc/rtems/score/types.h
new file mode 100644
index 0000000000..7179747993
--- /dev/null
+++ b/cpukit/score/cpu/sparc/rtems/score/types.h
@@ -0,0 +1,56 @@
+/* sparctypes.h
+ *
+ * This include file contains type definitions pertaining to the
+ * SPARC processor family.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __SPARC_TYPES_h
+#define __SPARC_TYPES_h
+
+#ifndef ASM
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This section defines the basic types for this processor.
+ */
+
+typedef unsigned char unsigned8; /* unsigned 8-bit integer */
+typedef unsigned short unsigned16; /* unsigned 16-bit integer */
+typedef unsigned int unsigned32; /* unsigned 32-bit integer */
+typedef unsigned long long unsigned64; /* unsigned 64-bit integer */
+
+typedef unsigned16 Priority_Bit_map_control;
+
+typedef signed char signed8; /* 8-bit signed integer */
+typedef signed short signed16; /* 16-bit signed integer */
+typedef signed int signed32; /* 32-bit signed integer */
+typedef signed long long signed64; /* 64 bit signed integer */
+
+typedef unsigned32 boolean; /* Boolean value */
+
+typedef float single_precision; /* single precision float */
+typedef double double_precision; /* double precision float */
+
+typedef void sparc_isr;
+typedef void ( *sparc_isr_entry )( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !ASM */
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/unix/.cvsignore b/cpukit/score/cpu/unix/.cvsignore
new file mode 100644
index 0000000000..6e8f9300d4
--- /dev/null
+++ b/cpukit/score/cpu/unix/.cvsignore
@@ -0,0 +1,3 @@
+Makefile
+Makefile.in
+stamp-h.in
diff --git a/cpukit/score/cpu/unix/ChangeLog b/cpukit/score/cpu/unix/ChangeLog
new file mode 100644
index 0000000000..80d0db7c68
--- /dev/null
+++ b/cpukit/score/cpu/unix/ChangeLog
@@ -0,0 +1,277 @@
+2004-04-13 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * asm.h: New (stub file. For consistency with other ports, only).
+ * Makefile.am: Add asm.h.
+
+2004-04-12 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * rtems/score/cpu.h: Remove defining _POSIX_C_SOURCE for solaris.
+
+2004-04-09 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * Makefile.am: Remove LIBC_DEFINES (Unsupported).
+
+2004-04-06 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * rtems/score/cpu.h: Remove unixsize.h.
+ * configure.ac: Remove (Merged into $(top_srcdir)/configure.ac).
+ * Makefile.am: Remove unixsize.h.
+ Don't include multilib.am.
+ Reflect merging configure.ac into $(top_srcdir)/configure.ac.
+
+2004-03-30 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * cpu.c, rtems/score/cpu.h: Convert to using c99 fixed size types.
+
+2004-03-29 Ralf Corsepius <ralf_corsepius@rtems.org>
+
+ * configure.ac: RTEMS_TOP([../../../..]).
+
+2004-01-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Move RTEMS_TOP one subdir down.
+
+2004-01-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add PREINSTALL_DIRS.
+
+2004-01-14 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Re-add dirstamps to PREINSTALL_FILES.
+ Add PREINSTALL_FILES to CLEANFILES.
+
+2004-01-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Requires automake >= 1.8.1.
+
+2004-01-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include compile.am, again.
+
+2004-01-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Convert to using automake compilation rules.
+
+2003-12-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use mkdir_p. Remove dirs from PREINSTALL_FILES.
+
+2003-12-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Require automake >= 1.8, autoconf >= 2.59.
+
+2003-12-01 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Remove TMPINSTALL_FILES.
+
+2003-11-30 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add $(dirstamp) to preinstallation rules.
+
+2003-11-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Don't use gmake rules for preinstallation.
+
+2003-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_CANONICAL_HOST.
+
+2003-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_CHECK_CPU.
+
+2003-09-26 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/cpu.h: Obsoleting HP PA-RISC port and removing all
+ references.
+
+2003-09-04 Joel Sherrill <joel@OARcorp.com>
+
+ * cpu.c, rtems/score/cpu.h, rtems/score/types.h, rtems/score/unix.h:
+ URL for license changed.
+
+2003-08-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use rtems-bugs@rtems.com as bug report email address.
+
+2003-04-17 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add PREINSTALL_FILES and TMPINSTALL_FILES to
+ all-local (Sync with other Makefile.ams).
+
+2003-03-06 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove AC_CONFIG_AUX_DIR.
+
+2003-01-03 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/cpu.h: Per PR315, eliminate warning for structure
+ alignment requests that are too large.
+
+2002-12-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Require autoconf-2.57 + automake-1.7.2.
+ * Makefile.am: Eliminate C_O_FILES, S_O_FILES, libscorecpu_a_OBJECTS.
+
+2002-11-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Fix package name.
+
+2002-11-12 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Generate unixsize.h on the fly, filter out
+ autoconf-2.53 PACKAGE crap.
+ * rtems/score/.cvsignore: unixsize*
+
+2002-10-25 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Add nostdinc to AM_INIT_AUTOMAKE.
+
+2002-10-21 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * .cvsignore: Reformat.
+ Add autom4te*cache.
+ Remove autom4te.cache.
+
+2002-07-26 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Build libscorecpu.a instead of rtems-cpu.rel.
+
+2002-07-22 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use .$(OBJEXT) instead of .o.
+
+2002-07-05 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: RTEMS_TOP(../../../..).
+
+2002-07-01 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove RTEMS_PROJECT_ROOT.
+
+2002-06-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Use AC_CONFIG_AUX_DIR(../../../..).
+ Add AC_PROG_RANLIB.
+
+2002-06-26 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Remove references to RTEMS_BSP.
+
+2002-06-17 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include $(top_srcdir)/../../../automake/*.am.
+ Use ../../../aclocal.
+
+2001-04-03 Joel Sherrill <joel@OARcorp.com>
+
+ * Per PR94, all rtems/score/CPUtypes.h are named rtems/score/types.h.
+ * rtems/score/unixtypes.h: Removed.
+ * rtems/score/types.h: New file via CVS magic.
+ * Makefile.am, rtems/score/cpu.h: Account for name change.
+
+2001-03-28 Joel Sherrill <joel@OARcorp.com>
+
+ * cpu.c: Define fix_syscall_errno() to nothing so MP links.
+
+2002-03-27 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac:
+ AC_INIT(package,_RTEMS_VERSION,_RTEMS_BUGS).
+ AM_INIT_AUTOMAKE([no-define foreign 1.6]).
+ * Makefile.am: Remove AUTOMAKE_OPTIONS.
+
+2002-02-13 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * configure.ac: Fix the test to determine cpu context size.
+
+2001-02-05 Joel Sherrill <joel@OARcorp.com>
+
+ * .cvsignore: Added stamp-h.in.
+
+2002-01-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Merge in rtems/Makefile.am and
+ rtems/score/Makefile.am. Remove gensize. Require automake-1.5.
+ * rtems/Makefile.am: Removed.
+ * rtems/score/Makefile.am: Removed.
+ * rtems/score/.cvsignore: Add unixsize.h*. Add stamp-h*.
+ * configure.ac: Add AM_CONFIG_HEADER(rtems/score/unixsize.h).
+ * rtems/score/cpu.h: Replace CPU_CONTEXT_SIZE_IN_BYTES with
+ SIZEOF_CPU_CONTEXT.
+
+2001-12-19 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Add multilib support.
+
+2001-11-28 Joel Sherrill <joel@OARcorp.com>,
+
+ This was tracked as PR91.
+ * rtems/score/cpu.h: Added CPU_PROVIDES_ISR_IS_IN_PROGRESS macro which
+ is used to specify if the port uses the standard macro for this (FALSE).
+ A TRUE setting indicates the port provides its own implementation.
+
+2001-11-28 Joel Sherrill <joel@OARcorp.com>,
+
+ This was tracked as PR91.
+ * rtems/score/cpu.h: Added CPU_PROVIDES_ISR_IS_IN_PROGRESS macro which
+ is used to specify if the port uses the standard macro for this (FALSE).
+ A TRUE setting indicates the port provides its own implementation.
+
+2001-10-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * .cvsignore: Add autom4te.cache for autoconf > 2.52.
+ * configure.in: Remove.
+ * configure.ac: New file, generated from configure.in by autoupdate.
+
+2001-09-23 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/score/Makefile.am: Use 'PREINSTALL_FILES ='.
+
+2001-05-07 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/score/cpu.h: Remove #undef __STRICT_ANSI__.
+
+2001-02-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am, rtems/score/Makefile.am:
+ Apply include_*HEADERS instead of H_FILES.
+
+2001-01-25 Joel Sherrill <joel@OARcorp.com>
+
+ * cpu.c, rtems/score/cpu.h: Bug report from Peter Mueller
+ <peter.o.mueller@gmx.de> because of not correcting for the ISR
+ vector table now being allocated from the workspace.
+
+2001-01-03 Joel Sherrill <joel@OARcorp.com>
+
+ * rtems/score/cpu.h: Added _CPU_Initialize_vectors().
+
+2000-11-09 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use ... instead of RTEMS_TOPdir in ACLOCAL_AMFLAGS.
+
+2000-11-02 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Switch to ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal.
+
+2000-10-25 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: ACLOCAL_AMFLAGS= -I $(RTEMS_TOPdir)/macros.
+ Switch to GNU canonicalization.
+
+2000-09-11 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Use += to set up AM_CPPFLAGS.
+
+2000-09-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * rtems/score/Makefile.am: Use PROJECT_TOPdir in path to gensize.
+
+2000-09-04 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
+
+ * Makefile.am: Include compile.am.
+
+2000-08-10 Joel Sherrill <joel@OARcorp.com>
+
+ * ChangeLog: New file.
diff --git a/cpukit/score/cpu/unix/Makefile.am b/cpukit/score/cpu/unix/Makefile.am
new file mode 100644
index 0000000000..5da21f5edc
--- /dev/null
+++ b/cpukit/score/cpu/unix/Makefile.am
@@ -0,0 +1,60 @@
+##
+## $Id$
+##
+
+include $(top_srcdir)/automake/compile.am
+
+AM_CPPFLAGS += -DCPU_SYNC_IO
+
+include_rtemsdir = $(includedir)/rtems
+include_rtems_HEADERS = asm.h
+
+include_rtems_scoredir = $(includedir)/rtems/score
+include_rtems_score_HEADERS = rtems/score/types.h rtems/score/cpu.h \
+ rtems/score/unix.h
+
+EXTRA_LIBRARIES = libscorecpu.a
+CLEANFILES = libscorecpu.a
+libscorecpu_a_SOURCES = cpu.c
+libscorecpu_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libscorecpu_g.a
+CLEANFILES += libscorecpu_g.a
+libscorecpu_g_a_SOURCES = $(libscorecpu_a_SOURCES)
+libscorecpu_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+all-local: $(PREINSTALL_FILES) libscorecpu$(LIB_VARIANT).a
+
+PREINSTALL_DIRS =
+PREINSTALL_FILES =
+
+$(PROJECT_INCLUDE)/rtems/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems
+ @: > $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/asm.h: asm.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/asm.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/asm.h
+
+$(PROJECT_INCLUDE)/rtems/score/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems/score
+ @: > $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/score/types.h: rtems/score/types.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/types.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/types.h
+
+$(PROJECT_INCLUDE)/rtems/score/cpu.h: rtems/score/cpu.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/cpu.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/cpu.h
+
+$(PROJECT_INCLUDE)/rtems/score/unix.h: rtems/score/unix.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/unix.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/unix.h
+
+CLEANFILES += $(PREINSTALL_FILES)
+DISTCLEANFILES = $(PREINSTALL_DIRS)
+
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/score/cpu/unix/asm.h b/cpukit/score/cpu/unix/asm.h
new file mode 100644
index 0000000000..820e1ec050
--- /dev/null
+++ b/cpukit/score/cpu/unix/asm.h
@@ -0,0 +1,33 @@
+/* asm.h
+ *
+ * This include file attempts to address the problems
+ * caused by incompatible flavors of assemblers and
+ * toolsets. It primarily addresses variations in the
+ * use of leading underscores on symbols and the requirement
+ * that register names be preceded by a %.
+ *
+ * This file is a "just an incomplete stub" and provided for consistency
+ * with other ports, only.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __UNIX_ASM_h
+#define __UNIX_ASM_h
+
+/*
+ * Indicate we are in an assembly file and get the basic CPU definitions.
+ */
+
+#ifndef ASM
+#define ASM
+#endif
+
+#include <rtems/score/cpuopts.h>
+#include <rtems/score/unix.h>
+
+#endif
diff --git a/cpukit/score/cpu/unix/cpu.c b/cpukit/score/cpu/unix/cpu.c
new file mode 100644
index 0000000000..c0c700fab6
--- /dev/null
+++ b/cpukit/score/cpu/unix/cpu.c
@@ -0,0 +1,1137 @@
+/*
+ * UNIX Simulator Dependent Source
+ *
+ * COPYRIGHT (c) 1994,95 by Division Incorporated
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/interr.h>
+
+#if defined(__linux__)
+#define _XOPEN_SOURCE
+#define MALLOC_0_RETURNS_NULL
+#endif
+
+#include <sys/types.h>
+#include <sys/times.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <time.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <unistd.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/sem.h>
+#endif
+#include <string.h> /* memset */
+
+#ifndef SA_RESTART
+#define SA_RESTART 0
+#endif
+
+typedef struct {
+ jmp_buf regs;
+ int isr_level;
+} Context_Control_overlay;
+
+void _CPU_Signal_initialize(void);
+void _CPU_Stray_signal(int);
+void _CPU_ISR_Handler(int);
+
+static sigset_t _CPU_Signal_mask;
+static Context_Control_overlay _CPU_Context_Default_with_ISRs_enabled;
+static Context_Control_overlay _CPU_Context_Default_with_ISRs_disabled;
+
+/*
+ * Sync IO support, an entry for each fd that can be set
+ */
+
+void _CPU_Sync_io_Init();
+
+static rtems_sync_io_handler _CPU_Sync_io_handlers[FD_SETSIZE];
+static int sync_io_nfds;
+static fd_set sync_io_readfds;
+static fd_set sync_io_writefds;
+static fd_set sync_io_exceptfds;
+
+/*
+ * Which cpu are we? Used by libcpu and libbsp.
+ */
+
+int cpu_number;
+
+/*PAGE
+ *
+ * _CPU_Initialize_vectors()
+ *
+ * Support routine to initialize the RTEMS vector table after it is allocated.
+ *
+ * UNIX Specific Information:
+ *
+ * Complete initialization since the table is now allocated.
+ */
+
+sigset_t posix_empty_mask;
+
+void _CPU_Initialize_vectors(void)
+{
+ uint32_t i;
+ proc_ptr old_handler;
+
+ /*
+ * Generate an empty mask to be used by disable_support
+ */
+
+ sigemptyset(&posix_empty_mask);
+
+ /*
+ * Block all the signals except SIGTRAP for the debugger
+ * and fatal error signals.
+ */
+
+ (void) sigfillset(&_CPU_Signal_mask);
+ (void) sigdelset(&_CPU_Signal_mask, SIGTRAP);
+ (void) sigdelset(&_CPU_Signal_mask, SIGABRT);
+#if !defined(__CYGWIN__)
+ (void) sigdelset(&_CPU_Signal_mask, SIGIOT);
+#endif
+ (void) sigdelset(&_CPU_Signal_mask, SIGCONT);
+ (void) sigdelset(&_CPU_Signal_mask, SIGSEGV);
+ (void) sigdelset(&_CPU_Signal_mask, SIGBUS);
+ (void) sigdelset(&_CPU_Signal_mask, SIGFPE);
+
+ _CPU_ISR_Enable(1);
+
+ /*
+ * Set the handler for all signals to be signal_handler
+ * which will then vector out to the correct handler
+ * for whichever signal actually happened. Initially
+ * set the vectors to the stray signal handler.
+ */
+
+ for (i = 0; i < CPU_INTERRUPT_NUMBER_OF_VECTORS; i++)
+ (void)_CPU_ISR_install_vector(i, _CPU_Stray_signal, &old_handler);
+
+ _CPU_Signal_initialize();
+}
+
+void _CPU_Signal_initialize( void )
+{
+ struct sigaction act;
+ sigset_t mask;
+
+ /* mark them all active except for TraceTrap and Abort */
+
+ mask = _CPU_Signal_mask;
+ sigprocmask(SIG_UNBLOCK, &mask, 0);
+
+ act.sa_handler = _CPU_ISR_Handler;
+ act.sa_mask = mask;
+ act.sa_flags = SA_RESTART;
+
+ sigaction(SIGHUP, &act, 0);
+ sigaction(SIGINT, &act, 0);
+ sigaction(SIGQUIT, &act, 0);
+ sigaction(SIGILL, &act, 0);
+#ifdef SIGEMT
+ sigaction(SIGEMT, &act, 0);
+#endif
+ sigaction(SIGFPE, &act, 0);
+ sigaction(SIGKILL, &act, 0);
+ sigaction(SIGBUS, &act, 0);
+ sigaction(SIGSEGV, &act, 0);
+#ifdef SIGSYS
+ sigaction(SIGSYS, &act, 0);
+#endif
+ sigaction(SIGPIPE, &act, 0);
+ sigaction(SIGALRM, &act, 0);
+ sigaction(SIGTERM, &act, 0);
+ sigaction(SIGUSR1, &act, 0);
+ sigaction(SIGUSR2, &act, 0);
+ sigaction(SIGCHLD, &act, 0);
+#ifdef SIGCLD
+ sigaction(SIGCLD, &act, 0);
+#endif
+#ifdef SIGPWR
+ sigaction(SIGPWR, &act, 0);
+#endif
+ sigaction(SIGVTALRM, &act, 0);
+ sigaction(SIGPROF, &act, 0);
+ sigaction(SIGIO, &act, 0);
+ sigaction(SIGWINCH, &act, 0);
+ sigaction(SIGSTOP, &act, 0);
+ sigaction(SIGTTIN, &act, 0);
+ sigaction(SIGTTOU, &act, 0);
+ sigaction(SIGURG, &act, 0);
+#ifdef SIGLOST
+ sigaction(SIGLOST, &act, 0);
+#endif
+}
+
+/*PAGE
+ *
+ * _CPU_Context_From_CPU_Init
+ */
+
+void _CPU_Context_From_CPU_Init()
+{
+
+#if defined(__hppa__) && defined(RTEMS_UNIXLIB_SETJMP)
+ /*
+ * HACK - set the _SYSTEM_ID to 0x20c so that setjmp/longjmp
+ * will handle the full 32 floating point registers.
+ */
+
+ {
+ extern uint32_t _SYSTEM_ID;
+
+ _SYSTEM_ID = 0x20c;
+ }
+#endif
+
+ /*
+ * get default values to use in _CPU_Context_Initialize()
+ */
+
+ if ( sizeof(Context_Control_overlay) > sizeof(Context_Control) )
+ _CPU_Fatal_halt( 0xdeadf00d );
+
+ (void) memset(
+ &_CPU_Context_Default_with_ISRs_enabled,
+ 0,
+ sizeof(Context_Control_overlay)
+ );
+ (void) memset(
+ &_CPU_Context_Default_with_ISRs_disabled,
+ 0,
+ sizeof(Context_Control_overlay)
+ );
+
+ _CPU_ISR_Set_level( 0 );
+ _CPU_Context_switch(
+ (Context_Control *) &_CPU_Context_Default_with_ISRs_enabled,
+ (Context_Control *) &_CPU_Context_Default_with_ISRs_enabled
+ );
+
+ _CPU_ISR_Set_level( 1 );
+ _CPU_Context_switch(
+ (Context_Control *) &_CPU_Context_Default_with_ISRs_disabled,
+ (Context_Control *) &_CPU_Context_Default_with_ISRs_disabled
+ );
+}
+
+/*PAGE
+ *
+ * _CPU_Sync_io_Init
+ */
+
+void _CPU_Sync_io_Init()
+{
+ int fd;
+
+ for (fd = 0; fd < FD_SETSIZE; fd++)
+ _CPU_Sync_io_handlers[fd] = NULL;
+
+ sync_io_nfds = 0;
+ FD_ZERO(&sync_io_readfds);
+ FD_ZERO(&sync_io_writefds);
+ FD_ZERO(&sync_io_exceptfds);
+}
+
+/*PAGE
+ *
+ * _CPU_ISR_Get_level
+ */
+
+uint32_t _CPU_ISR_Get_level( void )
+{
+ sigset_t old_mask;
+
+ sigemptyset( &old_mask );
+ sigprocmask(SIG_BLOCK, 0, &old_mask);
+
+ if (memcmp((void *)&posix_empty_mask, (void *)&old_mask, sizeof(sigset_t)))
+ return 1;
+
+ return 0;
+}
+
+/* _CPU_Initialize
+ *
+ * This routine performs processor dependent initialization.
+ *
+ * INPUT PARAMETERS:
+ * cpu_table - CPU table to initialize
+ * thread_dispatch - address of disptaching routine
+ */
+
+
+void _CPU_Initialize(
+ rtems_cpu_table *cpu_table,
+ void (*thread_dispatch) /* ignored on this CPU */
+)
+{
+ /*
+ * If something happened where the public Context_Control is not
+ * at least as large as the private Context_Control_overlay, then
+ * we are in trouble.
+ */
+
+ if ( sizeof(Context_Control_overlay) > sizeof(Context_Control) )
+ _CPU_Fatal_error(0x100 + 1);
+
+ /*
+ * The thread_dispatch argument is the address of the entry point
+ * for the routine called at the end of an ISR once it has been
+ * decided a context switch is necessary. On some compilation
+ * systems it is difficult to call a high-level language routine
+ * from assembly. This allows us to trick these systems.
+ *
+ * If you encounter this problem save the entry point in a CPU
+ * dependent variable.
+ */
+
+ _CPU_Thread_dispatch_pointer = thread_dispatch;
+
+ /*
+ * XXX; If there is not an easy way to initialize the FP context
+ * during Context_Initialize, then it is usually easier to
+ * save an "uninitialized" FP context here and copy it to
+ * the task's during Context_Initialize.
+ */
+
+ /* XXX: FP context initialization support */
+
+ _CPU_Table = *cpu_table;
+
+ _CPU_Sync_io_Init();
+
+ _CPU_Context_From_CPU_Init();
+
+}
+
+/*PAGE
+ *
+ * _CPU_ISR_install_raw_handler
+ */
+
+void _CPU_ISR_install_raw_handler(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+)
+{
+ _CPU_Fatal_halt( 0xdeaddead );
+}
+
+/*PAGE
+ *
+ * _CPU_ISR_install_vector
+ *
+ * This kernel routine installs the RTEMS handler for the
+ * specified vector.
+ *
+ * Input parameters:
+ * vector - interrupt vector number
+ * old_handler - former ISR for this vector number
+ * new_handler - replacement ISR for this vector number
+ *
+ * Output parameters: NONE
+ *
+ */
+
+
+void _CPU_ISR_install_vector(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+)
+{
+ *old_handler = _ISR_Vector_table[ vector ];
+
+ /*
+ * If the interrupt vector table is a table of pointer to isr entry
+ * points, then we need to install the appropriate RTEMS interrupt
+ * handler for this vector number.
+ */
+
+ /*
+ * We put the actual user ISR address in '_ISR_vector_table'. This will
+ * be used by the _CPU_ISR_Handler so the user gets control.
+ */
+
+ _ISR_Vector_table[ vector ] = new_handler;
+}
+
+/*PAGE
+ *
+ * _CPU_Install_interrupt_stack
+ */
+
+void _CPU_Install_interrupt_stack( void )
+{
+}
+
+/*PAGE
+ *
+ * _CPU_Thread_Idle_body
+ *
+ * Stop until we get a signal which is the logically the same thing
+ * entering low-power or sleep mode on a real processor and waiting for
+ * an interrupt. This significantly reduces the consumption of host
+ * CPU cycles which is again similar to low power mode.
+ */
+
+void _CPU_Thread_Idle_body( void )
+{
+#if CPU_SYNC_IO
+ extern void _Thread_Dispatch(void);
+ int fd;
+#endif
+
+ while (1) {
+#ifdef RTEMS_DEBUG
+ /* interrupts had better be enabled at this point! */
+ if (_CPU_ISR_Get_level() != 0)
+ abort();
+#endif
+
+ /*
+ * Block on a select statement, the CPU interface added allow the
+ * user to add new descriptors which are to be blocked on
+ */
+
+#if CPU_SYNC_IO
+ if (sync_io_nfds) {
+ int result;
+ fd_set readfds, writefds, exceptfds;
+
+ readfds = sync_io_readfds;
+ writefds = sync_io_writefds;
+ exceptfds = sync_io_exceptfds;
+ result = select(sync_io_nfds,
+ &readfds,
+ &writefds,
+ &exceptfds,
+ NULL);
+
+ if (result < 0) {
+ if (errno != EINTR)
+ _CPU_Fatal_error(0x200); /* FIXME : what number should go here !! */
+ _Thread_Dispatch();
+ continue;
+ }
+
+ for (fd = 0; fd < sync_io_nfds; fd++) {
+ boolean read = FD_ISSET(fd, &readfds);
+ boolean write = FD_ISSET(fd, &writefds);
+ boolean except = FD_ISSET(fd, &exceptfds);
+
+ if (_CPU_Sync_io_handlers[fd] && (read || write || except))
+ _CPU_Sync_io_handlers[fd](fd, read, write, except);
+ }
+
+ _Thread_Dispatch();
+ } else
+ pause();
+#else
+ pause();
+#endif
+
+ }
+
+}
+
+/*PAGE
+ *
+ * _CPU_Context_Initialize
+ */
+
+void _CPU_Context_Initialize(
+ Context_Control *_the_context,
+ uint32_t *_stack_base,
+ uint32_t _size,
+ uint32_t _new_level,
+ void *_entry_point,
+ boolean _is_fp
+)
+{
+ uint32_t *addr;
+ uint32_t jmp_addr;
+ uint32_t _stack_low; /* lowest "stack aligned" address */
+ uint32_t _stack_high; /* highest "stack aligned" address */
+ uint32_t _the_size;
+
+ jmp_addr = (uint32_t ) _entry_point;
+
+ /*
+ * On CPUs with stacks which grow down, we build the stack
+ * based on the _stack_high address. On CPUs with stacks which
+ * grow up, we build the stack based on the _stack_low address.
+ */
+
+ _stack_low = (uint32_t )(_stack_base) + CPU_STACK_ALIGNMENT - 1;
+ _stack_low &= ~(CPU_STACK_ALIGNMENT - 1);
+
+ _stack_high = (uint32_t )(_stack_base) + _size;
+ _stack_high &= ~(CPU_STACK_ALIGNMENT - 1);
+
+ if (_stack_high > _stack_low)
+ _the_size = _stack_high - _stack_low;
+ else
+ _the_size = _stack_low - _stack_high;
+
+ /*
+ * Slam our jmp_buf template into the context we are creating
+ */
+
+ if ( _new_level == 0 )
+ *(Context_Control_overlay *)_the_context =
+ _CPU_Context_Default_with_ISRs_enabled;
+ else
+ *(Context_Control_overlay *)_the_context =
+ _CPU_Context_Default_with_ISRs_disabled;
+
+ addr = (uint32_t *)_the_context;
+
+#if defined(__hppa__)
+ *(addr + RP_OFF) = jmp_addr;
+ *(addr + SP_OFF) = (uint32_t )(_stack_low + CPU_FRAME_SIZE);
+
+ /*
+ * See if we are using shared libraries by checking
+ * bit 30 in 24 off of newp. If bit 30 is set then
+ * we are using shared libraries and the jump address
+ * points to the pointer, so we put that into rp instead.
+ */
+
+ if (jmp_addr & 0x40000000) {
+ jmp_addr &= 0xfffffffc;
+ *(addr + RP_OFF) = *(uint32_t *)jmp_addr;
+ }
+#elif defined(__sparc__)
+
+ /*
+ * See /usr/include/sys/stack.h in Solaris 2.3 for a nice
+ * diagram of the stack.
+ */
+
+ asm ("ta 0x03"); /* flush registers */
+
+ *(addr + RP_OFF) = jmp_addr + ADDR_ADJ_OFFSET;
+ *(addr + SP_OFF) = (uint32_t )(_stack_high - CPU_FRAME_SIZE);
+ *(addr + FP_OFF) = (uint32_t )(_stack_high);
+
+#elif defined(__i386__)
+
+ /*
+ * This information was gathered by disassembling setjmp().
+ */
+
+ {
+ uint32_t stack_ptr;
+
+ stack_ptr = _stack_high - CPU_FRAME_SIZE;
+
+ *(addr + EBX_OFF) = 0xFEEDFEED;
+ *(addr + ESI_OFF) = 0xDEADDEAD;
+ *(addr + EDI_OFF) = 0xDEAFDEAF;
+ *(addr + EBP_OFF) = stack_ptr;
+ *(addr + ESP_OFF) = stack_ptr;
+ *(addr + RET_OFF) = jmp_addr;
+
+ addr = (uint32_t *) stack_ptr;
+
+ addr[ 0 ] = jmp_addr;
+ addr[ 1 ] = (uint32_t ) stack_ptr;
+ addr[ 2 ] = (uint32_t ) stack_ptr;
+ }
+
+#else
+#error "UNKNOWN CPU!!!"
+#endif
+
+}
+
+/*PAGE
+ *
+ * _CPU_Context_restore
+ */
+
+void _CPU_Context_restore(
+ Context_Control *next
+)
+{
+ Context_Control_overlay *nextp = (Context_Control_overlay *)next;
+
+ _CPU_ISR_Enable(nextp->isr_level);
+ longjmp( nextp->regs, 0 );
+}
+
+/*PAGE
+ *
+ * _CPU_Context_switch
+ */
+
+static void do_jump(
+ Context_Control_overlay *currentp,
+ Context_Control_overlay *nextp
+);
+
+void _CPU_Context_switch(
+ Context_Control *current,
+ Context_Control *next
+)
+{
+ Context_Control_overlay *currentp = (Context_Control_overlay *)current;
+ Context_Control_overlay *nextp = (Context_Control_overlay *)next;
+#if 0
+ int status;
+#endif
+
+ currentp->isr_level = _CPU_ISR_Disable_support();
+
+ do_jump( currentp, nextp );
+
+#if 0
+ if (sigsetjmp(currentp->regs, 1) == 0) { /* Save the current context */
+ siglongjmp(nextp->regs, 0); /* Switch to the new context */
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ TRUE,
+ status
+ );
+ }
+#endif
+
+#ifdef RTEMS_DEBUG
+ if (_CPU_ISR_Get_level() == 0)
+ abort();
+#endif
+
+ _CPU_ISR_Enable(currentp->isr_level);
+}
+
+static void do_jump(
+ Context_Control_overlay *currentp,
+ Context_Control_overlay *nextp
+)
+{
+ int status;
+
+ if (setjmp(currentp->regs) == 0) { /* Save the current context */
+ longjmp(nextp->regs, 0); /* Switch to the new context */
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ TRUE,
+ status
+ );
+ }
+}
+
+/*PAGE
+ *
+ * _CPU_Save_float_context
+ */
+
+void _CPU_Save_float_context(
+ Context_Control_fp *fp_context
+)
+{
+}
+
+/*PAGE
+ *
+ * _CPU_Restore_float_context
+ */
+
+void _CPU_Restore_float_context(
+ Context_Control_fp *fp_context
+)
+{
+}
+
+/*PAGE
+ *
+ * _CPU_ISR_Disable_support
+ */
+
+uint32_t _CPU_ISR_Disable_support(void)
+{
+ int status;
+ sigset_t old_mask;
+
+ sigemptyset( &old_mask );
+ status = sigprocmask(SIG_BLOCK, &_CPU_Signal_mask, &old_mask);
+ if ( status )
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ TRUE,
+ status
+ );
+
+ if (memcmp((void *)&posix_empty_mask, (void *)&old_mask, sizeof(sigset_t)))
+ return 1;
+
+ return 0;
+}
+
+/*PAGE
+ *
+ * _CPU_ISR_Enable
+ */
+
+void _CPU_ISR_Enable(
+ uint32_t level
+)
+{
+ int status;
+
+ if (level == 0)
+ status = sigprocmask(SIG_UNBLOCK, &_CPU_Signal_mask, 0);
+ else
+ status = sigprocmask(SIG_BLOCK, &_CPU_Signal_mask, 0);
+
+ if ( status )
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ TRUE,
+ status
+ );
+}
+
+/*PAGE
+ *
+ * _CPU_ISR_Handler
+ *
+ * External interrupt handler.
+ * This is installed as a UNIX signal handler.
+ * It vectors out to specific user interrupt handlers.
+ */
+
+void _CPU_ISR_Handler(int vector)
+{
+ extern void _Thread_Dispatch(void);
+ extern uint32_t _Thread_Dispatch_disable_level;
+ extern boolean _Context_Switch_necessary;
+
+ if (_ISR_Nest_level++ == 0) {
+ /* switch to interrupt stack */
+ }
+
+ _Thread_Dispatch_disable_level++;
+
+ if (_ISR_Vector_table[vector]) {
+ _ISR_Vector_table[vector](vector);
+ } else {
+ _CPU_Stray_signal(vector);
+ }
+
+ if (_ISR_Nest_level-- == 0) {
+ /* switch back to original stack */
+ }
+
+ _Thread_Dispatch_disable_level--;
+
+ if (_Thread_Dispatch_disable_level == 0 &&
+ (_Context_Switch_necessary || _ISR_Signals_to_thread_executing)) {
+ _ISR_Signals_to_thread_executing = FALSE;
+ _CPU_ISR_Enable(0);
+ _Thread_Dispatch();
+ }
+}
+
+/*PAGE
+ *
+ * _CPU_Stray_signal
+ */
+
+void _CPU_Stray_signal(int sig_num)
+{
+ char buffer[ 4 ];
+
+ /*
+ * print "stray" msg about ones which that might mean something
+ * Avoid using the stdio section of the library.
+ * The following is generally safe.
+ */
+
+ switch (sig_num)
+ {
+#ifdef SIGCLD
+ case SIGCLD:
+ break;
+#endif
+ default:
+ {
+ /*
+ * We avoid using the stdio section of the library.
+ * The following is generally safe
+ */
+
+ int digit;
+ int number = sig_num;
+ int len = 0;
+
+ digit = number / 100;
+ number %= 100;
+ if (digit) buffer[len++] = '0' + digit;
+
+ digit = number / 10;
+ number %= 10;
+ if (digit || len) buffer[len++] = '0' + digit;
+
+ digit = number;
+ buffer[len++] = '0' + digit;
+
+ buffer[ len++ ] = '\n';
+
+ write( 2, "Stray signal ", 13 );
+ write( 2, buffer, len );
+
+ }
+ }
+
+ /*
+ * If it was a "fatal" signal, then exit here
+ * If app code has installed a hander for one of these, then
+ * we won't call _CPU_Stray_signal, so this is ok.
+ */
+
+ switch (sig_num) {
+ case SIGINT:
+ case SIGHUP:
+ case SIGQUIT:
+ case SIGILL:
+#ifdef SIGEMT
+ case SIGEMT:
+#endif
+ case SIGKILL:
+ case SIGBUS:
+ case SIGSEGV:
+ case SIGTERM:
+#if !defined(__CYGWIN__)
+ case SIGIOT:
+#endif
+ _CPU_Fatal_error(0x100 + sig_num);
+ }
+}
+
+/*PAGE
+ *
+ * _CPU_Fatal_error
+ */
+
+void _CPU_Fatal_error(uint32_t error)
+{
+ setitimer(ITIMER_REAL, 0, 0);
+
+ if ( error ) {
+#ifdef RTEMS_DEBUG
+ abort();
+#endif
+ if (getenv("RTEMS_DEBUG"))
+ abort();
+ }
+
+ _exit(error);
+}
+
+/*
+ * Special Purpose Routines to hide the use of UNIX system calls.
+ */
+
+int _CPU_Set_sync_io_handler(
+ int fd,
+ boolean read,
+ boolean write,
+ boolean except,
+ rtems_sync_io_handler handler
+)
+{
+ if ((fd < FD_SETSIZE) && (_CPU_Sync_io_handlers[fd] == NULL)) {
+ if (read)
+ FD_SET(fd, &sync_io_readfds);
+ else
+ FD_CLR(fd, &sync_io_readfds);
+ if (write)
+ FD_SET(fd, &sync_io_writefds);
+ else
+ FD_CLR(fd, &sync_io_writefds);
+ if (except)
+ FD_SET(fd, &sync_io_exceptfds);
+ else
+ FD_CLR(fd, &sync_io_exceptfds);
+ _CPU_Sync_io_handlers[fd] = handler;
+ if ((fd + 1) > sync_io_nfds)
+ sync_io_nfds = fd + 1;
+ return 0;
+ }
+ return -1;
+}
+
+int _CPU_Clear_sync_io_handler(
+ int fd
+)
+{
+ if ((fd < FD_SETSIZE) && _CPU_Sync_io_handlers[fd]) {
+ FD_CLR(fd, &sync_io_readfds);
+ FD_CLR(fd, &sync_io_writefds);
+ FD_CLR(fd, &sync_io_exceptfds);
+ _CPU_Sync_io_handlers[fd] = NULL;
+ sync_io_nfds = 0;
+ for (fd = 0; fd < FD_SETSIZE; fd++)
+ if (FD_ISSET(fd, &sync_io_readfds) ||
+ FD_ISSET(fd, &sync_io_writefds) ||
+ FD_ISSET(fd, &sync_io_exceptfds))
+ sync_io_nfds = fd + 1;
+ return 0;
+ }
+ return -1;
+}
+
+int _CPU_Get_clock_vector( void )
+{
+ return SIGALRM;
+}
+
+void _CPU_Start_clock(
+ int microseconds
+)
+{
+ struct itimerval new;
+
+ new.it_value.tv_sec = 0;
+ new.it_value.tv_usec = microseconds;
+ new.it_interval.tv_sec = 0;
+ new.it_interval.tv_usec = microseconds;
+
+ setitimer(ITIMER_REAL, &new, 0);
+}
+
+void _CPU_Stop_clock( void )
+{
+ struct itimerval new;
+ struct sigaction act;
+
+ /*
+ * Set the SIGALRM signal to ignore any last
+ * signals that might come in while we are
+ * disarming the timer and removing the interrupt
+ * vector.
+ */
+
+ (void) memset(&act, 0, sizeof(act));
+ act.sa_handler = SIG_IGN;
+
+ sigaction(SIGALRM, &act, 0);
+
+ (void) memset(&new, 0, sizeof(new));
+ setitimer(ITIMER_REAL, &new, 0);
+}
+
+#if 0
+extern void fix_syscall_errno( void );
+#endif
+#define fix_syscall_errno()
+
+#if defined(RTEMS_MULTIPROCESSING)
+int _CPU_SHM_Semid;
+
+void _CPU_SHM_Init(
+ uint32_t maximum_nodes,
+ boolean is_master_node,
+ void **shm_address,
+ uint32_t *shm_length
+)
+{
+ int i;
+ int shmid;
+ char *shm_addr;
+ key_t shm_key;
+ key_t sem_key;
+ int status = 0; /* to avoid unitialized warnings */
+ int shm_size;
+
+ if (getenv("RTEMS_SHM_KEY"))
+ shm_key = strtol(getenv("RTEMS_SHM_KEY"), 0, 0);
+ else
+#ifdef RTEMS_SHM_KEY
+ shm_key = RTEMS_SHM_KEY;
+#else
+ shm_key = 0xa000;
+#endif
+
+ if (getenv("RTEMS_SHM_SIZE"))
+ shm_size = strtol(getenv("RTEMS_SHM_SIZE"), 0, 0);
+ else
+#ifdef RTEMS_SHM_SIZE
+ shm_size = RTEMS_SHM_SIZE;
+#else
+ shm_size = 64 * 1024;
+#endif
+
+ if (getenv("RTEMS_SHM_SEMAPHORE_KEY"))
+ sem_key = strtol(getenv("RTEMS_SHM_SEMAPHORE_KEY"), 0, 0);
+ else
+#ifdef RTEMS_SHM_SEMAPHORE_KEY
+ sem_key = RTEMS_SHM_SEMAPHORE_KEY;
+#else
+ sem_key = 0xa001;
+#endif
+
+ shmid = shmget(shm_key, shm_size, IPC_CREAT | 0660);
+ if ( shmid == -1 ) {
+ fix_syscall_errno(); /* in case of newlib */
+ perror( "shmget" );
+ _CPU_Fatal_halt( 0xdead0001 );
+ }
+
+ shm_addr = shmat(shmid, (char *)0, SHM_RND);
+ if ( shm_addr == (void *)-1 ) {
+ fix_syscall_errno(); /* in case of newlib */
+ perror( "shmat" );
+ _CPU_Fatal_halt( 0xdead0002 );
+ }
+
+ _CPU_SHM_Semid = semget(sem_key, maximum_nodes + 1, IPC_CREAT | 0660);
+ if ( _CPU_SHM_Semid == -1 ) {
+ fix_syscall_errno(); /* in case of newlib */
+ perror( "semget" );
+ _CPU_Fatal_halt( 0xdead0003 );
+ }
+
+ if ( is_master_node ) {
+ for ( i=0 ; i <= maximum_nodes ; i++ ) {
+#if !HAS_UNION_SEMUN
+ union semun {
+ int val;
+ struct semid_ds *buf;
+ unsigned short int *array;
+#if defined(__linux__)
+ struct seminfo *__buf;
+#endif
+ } ;
+#endif
+ union semun help ;
+ help.val = 1;
+ status = semctl( _CPU_SHM_Semid, i, SETVAL, help );
+
+ fix_syscall_errno(); /* in case of newlib */
+ if ( status == -1 ) {
+ _CPU_Fatal_halt( 0xdead0004 );
+ }
+ }
+ }
+
+ *shm_address = shm_addr;
+ *shm_length = shm_size;
+
+}
+#endif
+
+int _CPU_Get_pid( void )
+{
+ return getpid();
+}
+
+#if defined(RTEMS_MULTIPROCESSING)
+/*
+ * Define this to use signals for MPCI shared memory driver.
+ * If undefined, the shared memory driver will poll from the
+ * clock interrupt.
+ * Ref: ../shmsupp/getcfg.c
+ *
+ * BEWARE:: many UN*X kernels and debuggers become severely confused when
+ * debugging programs which use signals. The problem is *much*
+ * worse when using multiple signals, since ptrace(2) tends to
+ * drop all signals except 1 in the case of multiples.
+ * On hpux9, this problem was so bad, we couldn't use interrupts
+ * with the shared memory driver if we ever hoped to debug
+ * RTEMS programs.
+ * Maybe systems that use /proc don't have this problem...
+ */
+
+
+int _CPU_SHM_Get_vector( void )
+{
+#ifdef CPU_USE_SHM_INTERRUPTS
+ return SIGUSR1;
+#else
+ return 0;
+#endif
+}
+
+void _CPU_SHM_Send_interrupt(
+ int pid,
+ int vector
+)
+{
+ kill((pid_t) pid, vector);
+}
+
+void _CPU_SHM_Lock(
+ int semaphore
+)
+{
+ struct sembuf sb;
+
+ sb.sem_num = semaphore;
+ sb.sem_op = -1;
+ sb.sem_flg = 0;
+
+ while (1) {
+ int status = -1;
+
+ status = semop(_CPU_SHM_Semid, &sb, 1);
+ if ( status >= 0 )
+ break;
+ if ( status == -1 ) {
+ fix_syscall_errno(); /* in case of newlib */
+ if (errno == EINTR)
+ continue;
+ perror("shm lock");
+ _CPU_Fatal_halt( 0xdead0005 );
+ }
+ }
+
+}
+
+void _CPU_SHM_Unlock(
+ int semaphore
+)
+{
+ struct sembuf sb;
+ int status;
+
+ sb.sem_num = semaphore;
+ sb.sem_op = 1;
+ sb.sem_flg = 0;
+
+ while (1) {
+ status = semop(_CPU_SHM_Semid, &sb, 1);
+ if ( status >= 0 )
+ break;
+
+ if ( status == -1 ) {
+ fix_syscall_errno(); /* in case of newlib */
+ if (errno == EINTR)
+ continue;
+ perror("shm unlock");
+ _CPU_Fatal_halt( 0xdead0006 );
+ }
+ }
+
+}
+#endif
diff --git a/cpukit/score/cpu/unix/rtems/asm.h b/cpukit/score/cpu/unix/rtems/asm.h
new file mode 100644
index 0000000000..820e1ec050
--- /dev/null
+++ b/cpukit/score/cpu/unix/rtems/asm.h
@@ -0,0 +1,33 @@
+/* asm.h
+ *
+ * This include file attempts to address the problems
+ * caused by incompatible flavors of assemblers and
+ * toolsets. It primarily addresses variations in the
+ * use of leading underscores on symbols and the requirement
+ * that register names be preceded by a %.
+ *
+ * This file is a "just an incomplete stub" and provided for consistency
+ * with other ports, only.
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __UNIX_ASM_h
+#define __UNIX_ASM_h
+
+/*
+ * Indicate we are in an assembly file and get the basic CPU definitions.
+ */
+
+#ifndef ASM
+#define ASM
+#endif
+
+#include <rtems/score/cpuopts.h>
+#include <rtems/score/unix.h>
+
+#endif
diff --git a/cpukit/score/cpu/unix/rtems/score/cpu.h b/cpukit/score/cpu/unix/rtems/score/cpu.h
new file mode 100644
index 0000000000..901b5b5af1
--- /dev/null
+++ b/cpukit/score/cpu/unix/rtems/score/cpu.h
@@ -0,0 +1,1105 @@
+/* cpu.h
+ *
+ * This include file contains information pertaining to the
+ * UNIX port of RTEMS.
+ *
+ * COPYRIGHT (c) 1994 by Division Incorporated
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __CPU_h
+#define __CPU_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/unix.h> /* pick up machine definitions */
+#ifndef ASM
+#include <rtems/score/types.h>
+#endif
+
+#if defined(linux)
+#define MALLOC_0_RETURNS_NULL
+#endif
+
+/* conditional compilation parameters */
+
+/*
+ * Should the calls to _Thread_Enable_dispatch be inlined?
+ *
+ * If TRUE, then they are inlined.
+ * If FALSE, then a subroutine call is made.
+ *
+ * Basically this is an example of the classic trade-off of size
+ * versus speed. Inlining the call (TRUE) typically increases the
+ * size of RTEMS while speeding up the enabling of dispatching.
+ * [NOTE: In general, the _Thread_Dispatch_disable_level will
+ * only be 0 or 1 unless you are in an interrupt handler and that
+ * interrupt handler invokes the executive.] When not inlined
+ * something calls _Thread_Enable_dispatch which in turns calls
+ * _Thread_Dispatch. If the enable dispatch is inlined, then
+ * one subroutine call is avoided entirely.]
+ */
+
+#define CPU_INLINE_ENABLE_DISPATCH FALSE
+
+/*
+ * Should the body of the search loops in _Thread_queue_Enqueue_priority
+ * be unrolled one time? In unrolled each iteration of the loop examines
+ * two "nodes" on the chain being searched. Otherwise, only one node
+ * is examined per iteration.
+ *
+ * If TRUE, then the loops are unrolled.
+ * If FALSE, then the loops are not unrolled.
+ *
+ * The primary factor in making this decision is the cost of disabling
+ * and enabling interrupts (_ISR_Flash) versus the cost of rest of the
+ * body of the loop. On some CPUs, the flash is more expensive than
+ * one iteration of the loop body. In this case, it might be desirable
+ * to unroll the loop. It is important to note that on some CPUs, this
+ * code is the longest interrupt disable period in RTEMS. So it is
+ * necessary to strike a balance when setting this parameter.
+ */
+
+#define CPU_UNROLL_ENQUEUE_PRIORITY TRUE
+
+/*
+ * Does RTEMS manage a dedicated interrupt stack in software?
+ *
+ * If TRUE, then a stack is allocated in _ISR_Handler_initialization.
+ * If FALSE, nothing is done.
+ *
+ * If the CPU supports a dedicated interrupt stack in hardware,
+ * then it is generally the responsibility of the BSP to allocate it
+ * and set it up.
+ *
+ * If the CPU does not support a dedicated interrupt stack, then
+ * the porter has two options: (1) execute interrupts on the
+ * stack of the interrupted task, and (2) have RTEMS manage a dedicated
+ * interrupt stack.
+ *
+ * If this is TRUE, CPU_ALLOCATE_INTERRUPT_STACK should also be TRUE.
+ *
+ * Only one of CPU_HAS_SOFTWARE_INTERRUPT_STACK and
+ * CPU_HAS_HARDWARE_INTERRUPT_STACK should be set to TRUE. It is
+ * possible that both are FALSE for a particular CPU. Although it
+ * is unclear what that would imply about the interrupt processing
+ * procedure on that CPU.
+ */
+
+#define CPU_HAS_SOFTWARE_INTERRUPT_STACK FALSE
+
+/*
+ * Does this CPU have hardware support for a dedicated interrupt stack?
+ *
+ * If TRUE, then it must be installed during initialization.
+ * If FALSE, then no installation is performed.
+ *
+ * If this is TRUE, CPU_ALLOCATE_INTERRUPT_STACK should also be TRUE.
+ *
+ * Only one of CPU_HAS_SOFTWARE_INTERRUPT_STACK and
+ * CPU_HAS_HARDWARE_INTERRUPT_STACK should be set to TRUE. It is
+ * possible that both are FALSE for a particular CPU. Although it
+ * is unclear what that would imply about the interrupt processing
+ * procedure on that CPU.
+ */
+
+#define CPU_HAS_HARDWARE_INTERRUPT_STACK TRUE
+
+/*
+ * Does RTEMS allocate a dedicated interrupt stack in the Interrupt Manager?
+ *
+ * If TRUE, then the memory is allocated during initialization.
+ * If FALSE, then the memory is allocated during initialization.
+ *
+ * This should be TRUE if CPU_HAS_SOFTWARE_INTERRUPT_STACK is TRUE
+ * or CPU_INSTALL_HARDWARE_INTERRUPT_STACK is TRUE.
+ */
+
+#define CPU_ALLOCATE_INTERRUPT_STACK FALSE
+
+/*
+ * Does the RTEMS invoke the user's ISR with the vector number and
+ * a pointer to the saved interrupt frame (1) or just the vector
+ * number (0)?
+ */
+
+#define CPU_ISR_PASSES_FRAME_POINTER 0
+
+/*
+ * Does the CPU have hardware floating point?
+ *
+ * If TRUE, then the RTEMS_FLOATING_POINT task attribute is supported.
+ * If FALSE, then the RTEMS_FLOATING_POINT task attribute is ignored.
+ *
+ * If there is a FP coprocessor such as the i387 or mc68881, then
+ * the answer is TRUE.
+ *
+ * The macro name "NO_CPU_HAS_FPU" should be made CPU specific.
+ * It indicates whether or not this CPU model has FP support. For
+ * example, it would be possible to have an i386_nofp CPU model
+ * which set this to false to indicate that you have an i386 without
+ * an i387 and wish to leave floating point support out of RTEMS.
+ */
+
+#define CPU_HARDWARE_FP TRUE
+#define CPU_SOFTWARE_FP FALSE
+
+/*
+ * Are all tasks RTEMS_FLOATING_POINT tasks implicitly?
+ *
+ * If TRUE, then the RTEMS_FLOATING_POINT task attribute is assumed.
+ * If FALSE, then the RTEMS_FLOATING_POINT task attribute is followed.
+ *
+ * If CPU_HARDWARE_FP is FALSE, then this should be FALSE as well.
+ */
+
+#define CPU_ALL_TASKS_ARE_FP FALSE
+
+/*
+ * Should the IDLE task have a floating point context?
+ *
+ * If TRUE, then the IDLE task is created as a RTEMS_FLOATING_POINT task
+ * and it has a floating point context which is switched in and out.
+ * If FALSE, then the IDLE task does not have a floating point context.
+ *
+ * Setting this to TRUE negatively impacts the time required to preempt
+ * the IDLE task from an interrupt because the floating point context
+ * must be saved as part of the preemption.
+ */
+
+#define CPU_IDLE_TASK_IS_FP FALSE
+
+/*
+ * Should the saving of the floating point registers be deferred
+ * until a context switch is made to another different floating point
+ * task?
+ *
+ * If TRUE, then the floating point context will not be stored until
+ * necessary. It will remain in the floating point registers and not
+ * disturned until another floating point task is switched to.
+ *
+ * If FALSE, then the floating point context is saved when a floating
+ * point task is switched out and restored when the next floating point
+ * task is restored. The state of the floating point registers between
+ * those two operations is not specified.
+ *
+ * If the floating point context does NOT have to be saved as part of
+ * interrupt dispatching, then it should be safe to set this to TRUE.
+ *
+ * Setting this flag to TRUE results in using a different algorithm
+ * for deciding when to save and restore the floating point context.
+ * The deferred FP switch algorithm minimizes the number of times
+ * the FP context is saved and restored. The FP context is not saved
+ * until a context switch is made to another, different FP task.
+ * Thus in a system with only one FP task, the FP context will never
+ * be saved or restored.
+ */
+
+#define CPU_USE_DEFERRED_FP_SWITCH TRUE
+
+/*
+ * Does this port provide a CPU dependent IDLE task implementation?
+ *
+ * If TRUE, then the routine _CPU_Thread_Idle_body
+ * must be provided and is the default IDLE thread body instead of
+ * _CPU_Thread_Idle_body.
+ *
+ * If FALSE, then use the generic IDLE thread body if the BSP does
+ * not provide one.
+ *
+ * This is intended to allow for supporting processors which have
+ * a low power or idle mode. When the IDLE thread is executed, then
+ * the CPU can be powered down.
+ *
+ * The order of precedence for selecting the IDLE thread body is:
+ *
+ * 1. BSP provided
+ * 2. CPU dependent (if provided)
+ * 3. generic (if no BSP and no CPU dependent)
+ */
+
+#define CPU_PROVIDES_IDLE_THREAD_BODY TRUE
+
+/*
+ * Does the stack grow up (toward higher addresses) or down
+ * (toward lower addresses)?
+ *
+ * If TRUE, then the grows upward.
+ * If FALSE, then the grows toward smaller addresses.
+ */
+
+#if defined(__hppa__)
+#define CPU_STACK_GROWS_UP TRUE
+#elif defined(__sparc__) || defined(__i386__)
+#define CPU_STACK_GROWS_UP FALSE
+#else
+#error "unknown CPU!!"
+#endif
+
+
+/*
+ * The following is the variable attribute used to force alignment
+ * of critical RTEMS structures. On some processors it may make
+ * sense to have these aligned on tighter boundaries than
+ * the minimum requirements of the compiler in order to have as
+ * much of the critical data area as possible in a cache line.
+ *
+ * The placement of this macro in the declaration of the variables
+ * is based on the syntactically requirements of the GNU C
+ * "__attribute__" extension. For example with GNU C, use
+ * the following to force a structures to a 32 byte boundary.
+ *
+ * __attribute__ ((aligned (32)))
+ *
+ * NOTE: Currently only the Priority Bit Map table uses this feature.
+ * To benefit from using this, the data must be heavily
+ * used so it will stay in the cache and used frequently enough
+ * in the executive to justify turning this on.
+ *
+ * This is really not critical on the POSIX simulator ports as
+ * performance is not the goal here.
+ */
+
+#define CPU_STRUCTURE_ALIGNMENT
+
+/*
+ * Define what is required to specify how the network to host conversion
+ * routines are handled.
+ */
+
+#if defined(__hppa__) || defined(__sparc__)
+#define CPU_HAS_OWN_HOST_TO_NETWORK_ROUTINES FALSE
+#define CPU_BIG_ENDIAN TRUE
+#define CPU_LITTLE_ENDIAN FALSE
+#elif defined(__i386__)
+#define CPU_HAS_OWN_HOST_TO_NETWORK_ROUTINES FALSE
+#define CPU_BIG_ENDIAN FALSE
+#define CPU_LITTLE_ENDIAN TRUE
+#else
+#error "Unknown CPU!!!"
+#endif
+
+/*
+ * The following defines the number of bits actually used in the
+ * interrupt field of the task mode. How those bits map to the
+ * CPU interrupt levels is defined by the routine _CPU_ISR_Set_level().
+ */
+
+#define CPU_MODES_INTERRUPT_MASK 0x00000001
+
+#define CPU_NAME "UNIX"
+
+/*
+ * Processor defined structures
+ *
+ * Examples structures include the descriptor tables from the i386
+ * and the processor control structure on the i960ca.
+ */
+
+/* may need to put some structures here. */
+
+#if defined(__hppa__)
+/*
+ * Word indices within a jmp_buf structure
+ */
+
+#ifdef RTEMS_NEWLIB_SETJMP
+#define RP_OFF 6
+#define SP_OFF 2
+#define R3_OFF 10
+#define R4_OFF 11
+#define R5_OFF 12
+#define R6_OFF 13
+#define R7_OFF 14
+#define R8_OFF 15
+#define R9_OFF 16
+#define R10_OFF 17
+#define R11_OFF 18
+#define R12_OFF 19
+#define R13_OFF 20
+#define R14_OFF 21
+#define R15_OFF 22
+#define R16_OFF 23
+#define R17_OFF 24
+#define R18_OFF 25
+#define DP_OFF 26
+#endif
+
+#ifdef RTEMS_UNIXLIB_SETJMP
+#define RP_OFF 0
+#define SP_OFF 1
+#define R3_OFF 4
+#define R4_OFF 5
+#define R5_OFF 6
+#define R6_OFF 7
+#define R7_OFF 8
+#define R8_OFF 9
+#define R9_OFF 10
+#define R10_OFF 11
+#define R11_OFF 12
+#define R12_OFF 13
+#define R13_OFF 14
+#define R14_OFF 15
+#define R15_OFF 16
+#define R16_OFF 17
+#define R17_OFF 18
+#define R18_OFF 19
+#define DP_OFF 20
+#endif
+#endif
+
+#if defined(__i386__)
+
+#ifdef RTEMS_NEWLIB
+#error "Newlib not installed"
+#endif
+
+/*
+ * For i386 targets
+ */
+
+#ifdef RTEMS_UNIXLIB
+#if defined(__FreeBSD__)
+#define RET_OFF 0
+#define EBX_OFF 1
+#define EBP_OFF 2
+#define ESP_OFF 3
+#define ESI_OFF 4
+#define EDI_OFF 5
+#elif defined(__CYGWIN__)
+#define EAX_OFF 0
+#define EBX_OFF 1
+#define ECX_OFF 2
+#define EDX_OFF 3
+#define ESI_OFF 4
+#define EDI_OFF 5
+#define EBP_OFF 6
+#define ESP_OFF 7
+#define RET_OFF 8
+#else
+/* Linux */
+#define EBX_OFF 0
+#define ESI_OFF 1
+#define EDI_OFF 2
+#define EBP_OFF 3
+#define ESP_OFF 4
+#define RET_OFF 5
+#endif
+#endif
+
+#endif
+
+#if defined(__sparc__)
+
+/*
+ * Word indices within a jmp_buf structure
+ */
+
+#ifdef RTEMS_NEWLIB
+#define ADDR_ADJ_OFFSET -8
+#define SP_OFF 0
+#define RP_OFF 1
+#define FP_OFF 2
+#endif
+
+#ifdef RTEMS_UNIXLIB
+#define ADDR_ADJ_OFFSET 0
+#define G0_OFF 0
+#define SP_OFF 1
+#define RP_OFF 2
+#define FP_OFF 3
+#define I7_OFF 4
+#endif
+
+#endif
+
+/*
+ * Contexts
+ *
+ * Generally there are 2 types of context to save.
+ * 1. Interrupt registers to save
+ * 2. Task level registers to save
+ *
+ * This means we have the following 3 context items:
+ * 1. task level context stuff:: Context_Control
+ * 2. floating point task stuff:: Context_Control_fp
+ * 3. special interrupt level context :: Context_Control_interrupt
+ *
+ * On some processors, it is cost-effective to save only the callee
+ * preserved registers during a task context switch. This means
+ * that the ISR code needs to save those registers which do not
+ * persist across function calls. It is not mandatory to make this
+ * distinctions between the caller/callee saves registers for the
+ * purpose of minimizing context saved during task switch and on interrupts.
+ * If the cost of saving extra registers is minimal, simplicity is the
+ * choice. Save the same context on interrupt entry as for tasks in
+ * this case.
+ *
+ * Additionally, if gdb is to be made aware of RTEMS tasks for this CPU, then
+ * care should be used in designing the context area.
+ *
+ * On some CPUs with hardware floating point support, the Context_Control_fp
+ * structure will not be used or it simply consist of an array of a
+ * fixed number of bytes. This is done when the floating point context
+ * is dumped by a "FP save context" type instruction and the format
+ * is not really defined by the CPU. In this case, there is no need
+ * to figure out the exact format -- only the size. Of course, although
+ * this is enough information for RTEMS, it is probably not enough for
+ * a debugger such as gdb. But that is another problem.
+ */
+
+/*
+ * This is really just the area for the following fields.
+ *
+ * jmp_buf regs;
+ * uint32_t isr_level;
+ *
+ * Doing it this way avoids conflicts between the native stuff and the
+ * RTEMS stuff.
+ *
+ * NOTE:
+ * hpux9 setjmp is optimized for the case where the setjmp buffer
+ * is 8 byte aligned. In a RISC world, this seems likely to enable
+ * 8 byte copies, especially for the float registers.
+ * So we always align them on 8 byte boundaries.
+ */
+
+#ifdef __GNUC__
+#define CONTEXT_STRUCTURE_ALIGNMENT __attribute__ ((aligned (8)))
+#else
+#define CONTEXT_STRUCTURE_ALIGNMENT
+#endif
+
+typedef struct {
+ char Area[ SIZEOF_CPU_CONTEXT ] CONTEXT_STRUCTURE_ALIGNMENT;
+} Context_Control;
+
+typedef struct {
+} Context_Control_fp;
+
+typedef struct {
+} CPU_Interrupt_frame;
+
+
+/*
+ * The following table contains the information required to configure
+ * the UNIX Simulator specific parameters.
+ */
+
+typedef struct {
+ void (*pretasking_hook)( void );
+ void (*predriver_hook)( void );
+ void (*postdriver_hook)( void );
+ void (*idle_task)( void );
+ boolean do_zero_of_workspace;
+ uint32_t idle_task_stack_size;
+ uint32_t interrupt_stack_size;
+ uint32_t extra_mpci_receive_server_stack;
+ void * (*stack_allocate_hook)( uint32_t );
+ void (*stack_free_hook)( void* );
+ /* end of required fields */
+} rtems_cpu_table;
+
+/*
+ * Macros to access required entires in the CPU Table are in
+ * the file rtems/system.h.
+ */
+
+/*
+ * Macros to access UNIX specific additions to the CPU Table
+ */
+
+/* There are no CPU specific additions to the CPU Table for this port. */
+
+/*
+ * This variable is optional. It is used on CPUs on which it is difficult
+ * to generate an "uninitialized" FP context. It is filled in by
+ * _CPU_Initialize and copied into the task's FP context area during
+ * _CPU_Context_Initialize.
+ */
+
+SCORE_EXTERN Context_Control_fp _CPU_Null_fp_context;
+
+/*
+ * On some CPUs, RTEMS supports a software managed interrupt stack.
+ * This stack is allocated by the Interrupt Manager and the switch
+ * is performed in _ISR_Handler. These variables contain pointers
+ * to the lowest and highest addresses in the chunk of memory allocated
+ * for the interrupt stack. Since it is unknown whether the stack
+ * grows up or down (in general), this give the CPU dependent
+ * code the option of picking the version it wants to use.
+ *
+ * NOTE: These two variables are required if the macro
+ * CPU_HAS_SOFTWARE_INTERRUPT_STACK is defined as TRUE.
+ */
+
+SCORE_EXTERN void *_CPU_Interrupt_stack_low;
+SCORE_EXTERN void *_CPU_Interrupt_stack_high;
+
+/*
+ * With some compilation systems, it is difficult if not impossible to
+ * call a high-level language routine from assembly language. This
+ * is especially true of commercial Ada compilers and name mangling
+ * C++ ones. This variable can be optionally defined by the CPU porter
+ * and contains the address of the routine _Thread_Dispatch. This
+ * can make it easier to invoke that routine at the end of the interrupt
+ * sequence (if a dispatch is necessary).
+ */
+
+SCORE_EXTERN void (*_CPU_Thread_dispatch_pointer)();
+
+/*
+ * Nothing prevents the porter from declaring more CPU specific variables.
+ */
+
+/* XXX: if needed, put more variables here */
+
+/*
+ * The size of the floating point context area. On some CPUs this
+ * will not be a "sizeof" because the format of the floating point
+ * area is not defined -- only the size is. This is usually on
+ * CPUs with a "floating point save context" instruction.
+ */
+
+#define CPU_CONTEXT_FP_SIZE sizeof( Context_Control_fp )
+
+/*
+ * The size of a frame on the stack
+ */
+
+#if defined(__hppa__)
+#define CPU_FRAME_SIZE (32 * 4)
+#elif defined(__sparc__)
+#define CPU_FRAME_SIZE (112) /* based on disassembled test code */
+#elif defined(__i386__)
+#define CPU_FRAME_SIZE (24) /* return address, sp, and bp pushed plus fudge */
+#else
+#error "Unknown CPU!!!"
+#endif
+
+/*
+ * Amount of extra stack (above minimum stack size) required by
+ * MPCI receive server thread. Remember that in a multiprocessor
+ * system this thread must exist and be able to process all directives.
+ */
+
+#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 0
+
+/*
+ * This defines the number of entries in the ISR_Vector_table managed
+ * by RTEMS.
+ */
+
+#define CPU_INTERRUPT_NUMBER_OF_VECTORS 64
+#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1)
+
+/*
+ * This is defined if the port has a special way to report the ISR nesting
+ * level. Most ports maintain the variable _ISR_Nest_level.
+ */
+
+#define CPU_PROVIDES_ISR_IS_IN_PROGRESS FALSE
+
+/*
+ * Should be large enough to run all RTEMS tests. This insures
+ * that a "reasonable" small application should not have any problems.
+ */
+
+#define CPU_STACK_MINIMUM_SIZE (16 * 1024)
+
+/*
+ * CPU's worst alignment requirement for data types on a byte boundary. This
+ * alignment does not take into account the requirements for the stack.
+ */
+
+#define CPU_ALIGNMENT 8
+
+/*
+ * This number corresponds to the byte alignment requirement for the
+ * heap handler. This alignment requirement may be stricter than that
+ * for the data types alignment specified by CPU_ALIGNMENT. It is
+ * common for the heap to follow the same alignment requirement as
+ * CPU_ALIGNMENT. If the CPU_ALIGNMENT is strict enough for the heap,
+ * then this should be set to CPU_ALIGNMENT.
+ *
+ * NOTE: This does not have to be a power of 2. It does have to
+ * be greater or equal to than CPU_ALIGNMENT.
+ */
+
+#define CPU_HEAP_ALIGNMENT CPU_ALIGNMENT
+
+/*
+ * This number corresponds to the byte alignment requirement for memory
+ * buffers allocated by the partition manager. This alignment requirement
+ * may be stricter than that for the data types alignment specified by
+ * CPU_ALIGNMENT. It is common for the partition to follow the same
+ * alignment requirement as CPU_ALIGNMENT. If the CPU_ALIGNMENT is strict
+ * enough for the partition, then this should be set to CPU_ALIGNMENT.
+ *
+ * NOTE: This does not have to be a power of 2. It does have to
+ * be greater or equal to than CPU_ALIGNMENT.
+ */
+
+#define CPU_PARTITION_ALIGNMENT CPU_ALIGNMENT
+
+/*
+ * This number corresponds to the byte alignment requirement for the
+ * stack. This alignment requirement may be stricter than that for the
+ * data types alignment specified by CPU_ALIGNMENT. If the CPU_ALIGNMENT
+ * is strict enough for the stack, then this should be set to 0.
+ *
+ * NOTE: This must be a power of 2 either 0 or greater than CPU_ALIGNMENT.
+ */
+
+#define CPU_STACK_ALIGNMENT 64
+
+/*
+ * ISR handler macros
+ */
+
+/*
+ * Support routine to initialize the RTEMS vector table after it is allocated.
+ */
+
+void _CPU_Initialize_vectors(void);
+
+/*
+ * Disable all interrupts for an RTEMS critical section. The previous
+ * level is returned in _level.
+ */
+
+extern uint32_t _CPU_ISR_Disable_support(void);
+
+#define _CPU_ISR_Disable( _level ) \
+ do { \
+ (_level) = _CPU_ISR_Disable_support(); \
+ } while ( 0 )
+
+/*
+ * Enable interrupts to the previous level (returned by _CPU_ISR_Disable).
+ * This indicates the end of an RTEMS critical section. The parameter
+ * _level is not modified.
+ */
+
+void _CPU_ISR_Enable(uint32_t level);
+
+/*
+ * This temporarily restores the interrupt to _level before immediately
+ * disabling them again. This is used to divide long RTEMS critical
+ * sections into two or more parts. The parameter _level is not
+ * modified.
+ */
+
+#define _CPU_ISR_Flash( _level ) \
+ do { \
+ register uint32_t _ignored = 0; \
+ _CPU_ISR_Enable( (_level) ); \
+ _CPU_ISR_Disable( _ignored ); \
+ } while ( 0 )
+
+/*
+ * Map interrupt level in task mode onto the hardware that the CPU
+ * actually provides. Currently, interrupt levels which do not
+ * map onto the CPU in a generic fashion are undefined. Someday,
+ * it would be nice if these were "mapped" by the application
+ * via a callout. For example, m68k has 8 levels 0 - 7, levels
+ * 8 - 255 would be available for bsp/application specific meaning.
+ * This could be used to manage a programmable interrupt controller
+ * via the rtems_task_mode directive.
+ */
+
+#define _CPU_ISR_Set_level( new_level ) \
+ { \
+ if ( new_level == 0 ) _CPU_ISR_Enable( 0 ); \
+ else _CPU_ISR_Enable( 1 ); \
+ }
+
+uint32_t _CPU_ISR_Get_level( void );
+
+/* end of ISR handler macros */
+
+/* Context handler macros */
+
+/*
+ * This routine is responsible for somehow restarting the currently
+ * executing task. If you are lucky, then all that is necessary
+ * is restoring the context. Otherwise, there will need to be
+ * a special assembly routine which does something special in this
+ * case. Context_Restore should work most of the time. It will
+ * not work if restarting self conflicts with the stack frame
+ * assumptions of restoring a context.
+ */
+
+#define _CPU_Context_Restart_self( _the_context ) \
+ _CPU_Context_restore( (_the_context) );
+
+/*
+ * The purpose of this macro is to allow the initial pointer into
+ * a floating point context area (used to save the floating point
+ * context) to be at an arbitrary place in the floating point
+ * context area.
+ *
+ * This is necessary because some FP units are designed to have
+ * their context saved as a stack which grows into lower addresses.
+ * Other FP units can be saved by simply moving registers into offsets
+ * from the base of the context area. Finally some FP units provide
+ * a "dump context" instruction which could fill in from high to low
+ * or low to high based on the whim of the CPU designers.
+ */
+
+#define _CPU_Context_Fp_start( _base, _offset ) \
+ ( (void *) _Addresses_Add_offset( (_base), (_offset) ) )
+
+/*
+ * This routine initializes the FP context area passed to it to.
+ * There are a few standard ways in which to initialize the
+ * floating point context. The code included for this macro assumes
+ * that this is a CPU in which a "initial" FP context was saved into
+ * _CPU_Null_fp_context and it simply copies it to the destination
+ * context passed to it.
+ *
+ * Other models include (1) not doing anything, and (2) putting
+ * a "null FP status word" in the correct place in the FP context.
+ */
+
+#define _CPU_Context_Initialize_fp( _destination ) \
+ { \
+ *((Context_Control_fp *) *((void **) _destination)) = _CPU_Null_fp_context; \
+ }
+
+#define _CPU_Context_save_fp( _fp_context ) \
+ _CPU_Save_float_context( *(Context_Control_fp **)(_fp_context))
+
+#define _CPU_Context_restore_fp( _fp_context ) \
+ _CPU_Restore_float_context( *(Context_Control_fp **)(_fp_context))
+
+extern void _CPU_Context_Initialize(
+ Context_Control *_the_context,
+ uint32_t *_stack_base,
+ uint32_t _size,
+ uint32_t _new_level,
+ void *_entry_point,
+ boolean _is_fp
+);
+
+/* end of Context handler macros */
+
+/* Fatal Error manager macros */
+
+/*
+ * This routine copies _error into a known place -- typically a stack
+ * location or a register, optionally disables interrupts, and
+ * halts/stops the CPU.
+ */
+
+#define _CPU_Fatal_halt( _error ) \
+ _CPU_Fatal_error( _error )
+
+/* end of Fatal Error manager macros */
+
+/* Bitfield handler macros */
+
+/*
+ * This routine sets _output to the bit number of the first bit
+ * set in _value. _value is of CPU dependent type Priority_Bit_map_control.
+ * This type may be either 16 or 32 bits wide although only the 16
+ * least significant bits will be used.
+ *
+ * There are a number of variables in using a "find first bit" type
+ * instruction.
+ *
+ * (1) What happens when run on a value of zero?
+ * (2) Bits may be numbered from MSB to LSB or vice-versa.
+ * (3) The numbering may be zero or one based.
+ * (4) The "find first bit" instruction may search from MSB or LSB.
+ *
+ * RTEMS guarantees that (1) will never happen so it is not a concern.
+ * (2),(3), (4) are handled by the macros _CPU_Priority_mask() and
+ * _CPU_Priority_bits_index(). These three form a set of routines
+ * which must logically operate together. Bits in the _value are
+ * set and cleared based on masks built by _CPU_Priority_mask().
+ * The basic major and minor values calculated by _Priority_Major()
+ * and _Priority_Minor() are "massaged" by _CPU_Priority_bits_index()
+ * to properly range between the values returned by the "find first bit"
+ * instruction. This makes it possible for _Priority_Get_highest() to
+ * calculate the major and directly index into the minor table.
+ * This mapping is necessary to ensure that 0 (a high priority major/minor)
+ * is the first bit found.
+ *
+ * This entire "find first bit" and mapping process depends heavily
+ * on the manner in which a priority is broken into a major and minor
+ * components with the major being the 4 MSB of a priority and minor
+ * the 4 LSB. Thus (0 << 4) + 0 corresponds to priority 0 -- the highest
+ * priority. And (15 << 4) + 14 corresponds to priority 254 -- the next
+ * to the lowest priority.
+ *
+ * If your CPU does not have a "find first bit" instruction, then
+ * there are ways to make do without it. Here are a handful of ways
+ * to implement this in software:
+ *
+ * - a series of 16 bit test instructions
+ * - a "binary search using if's"
+ * - _number = 0
+ * if _value > 0x00ff
+ * _value >>=8
+ * _number = 8;
+ *
+ * if _value > 0x0000f
+ * _value >=8
+ * _number += 4
+ *
+ * _number += bit_set_table[ _value ]
+ *
+ * where bit_set_table[ 16 ] has values which indicate the first
+ * bit set
+ */
+
+/*
+ * The UNIX port uses the generic C algorithm for bitfield scan to avoid
+ * dependencies on either a native bitscan instruction or an ffs() in the
+ * C library.
+ */
+
+#define CPU_USE_GENERIC_BITFIELD_CODE TRUE
+#define CPU_USE_GENERIC_BITFIELD_DATA TRUE
+
+/* end of Bitfield handler macros */
+
+/* Priority handler handler macros */
+
+/*
+ * The UNIX port uses the generic C algorithm for bitfield scan to avoid
+ * dependencies on either a native bitscan instruction or an ffs() in the
+ * C library.
+ */
+
+/* end of Priority handler macros */
+
+/* functions */
+
+/*
+ * _CPU_Initialize
+ *
+ * This routine performs CPU dependent initialization.
+ */
+
+void _CPU_Initialize(
+ rtems_cpu_table *cpu_table,
+ void (*thread_dispatch)
+);
+
+/*
+ * _CPU_ISR_install_raw_handler
+ *
+ * This routine installs a "raw" interrupt handler directly into the
+ * processor's vector table.
+ */
+
+void _CPU_ISR_install_raw_handler(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+);
+
+/*
+ * _CPU_ISR_install_vector
+ *
+ * This routine installs an interrupt vector.
+ */
+
+void _CPU_ISR_install_vector(
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
+);
+
+/*
+ * _CPU_Install_interrupt_stack
+ *
+ * This routine installs the hardware interrupt stack pointer.
+ *
+ * NOTE: It need only be provided if CPU_HAS_HARDWARE_INTERRUPT_STACK
+ * is TRUE.
+ */
+
+void _CPU_Install_interrupt_stack( void );
+
+/*
+ * _CPU_Thread_Idle_body
+ *
+ * This routine is the CPU dependent IDLE thread body.
+ *
+ * NOTE: It need only be provided if CPU_PROVIDES_IDLE_THREAD_BODY
+ * is TRUE.
+ */
+
+void _CPU_Thread_Idle_body( void );
+
+/*
+ * _CPU_Context_switch
+ *
+ * This routine switches from the run context to the heir context.
+ */
+
+void _CPU_Context_switch(
+ Context_Control *run,
+ Context_Control *heir
+);
+
+/*
+ * _CPU_Context_restore
+ *
+ * This routine is generally used only to restart self in an
+ * efficient manner. It may simply be a label in _CPU_Context_switch.
+ *
+ * NOTE: May be unnecessary to reload some registers.
+ */
+
+void _CPU_Context_restore(
+ Context_Control *new_context
+);
+
+/*
+ * _CPU_Save_float_context
+ *
+ * This routine saves the floating point context passed to it.
+ */
+
+void _CPU_Save_float_context(
+ Context_Control_fp *fp_context_ptr
+);
+
+/*
+ * _CPU_Restore_float_context
+ *
+ * This routine restores the floating point context passed to it.
+ */
+
+void _CPU_Restore_float_context(
+ Context_Control_fp *fp_context_ptr
+);
+
+
+void _CPU_ISR_Set_signal_level(
+ uint32_t level
+);
+
+void _CPU_Fatal_error(
+ uint32_t _error
+);
+
+/* The following routine swaps the endian format of an unsigned int.
+ * It must be static because it is referenced indirectly.
+ *
+ * This version will work on any processor, but if there is a better
+ * way for your CPU PLEASE use it. The most common way to do this is to:
+ *
+ * swap least significant two bytes with 16-bit rotate
+ * swap upper and lower 16-bits
+ * swap most significant two bytes with 16-bit rotate
+ *
+ * Some CPUs have special instructions which swap a 32-bit quantity in
+ * a single instruction (e.g. i486). It is probably best to avoid
+ * an "endian swapping control bit" in the CPU. One good reason is
+ * that interrupts would probably have to be disabled to insure that
+ * an interrupt does not try to access the same "chunk" with the wrong
+ * endian. Another good reason is that on some CPUs, the endian bit
+ * endianness for ALL fetches -- both code and data -- so the code
+ * will be fetched incorrectly.
+ */
+
+static inline unsigned int CPU_swap_u32(
+ unsigned int value
+)
+{
+ uint32_t byte1, byte2, byte3, byte4, swapped;
+
+ byte4 = (value >> 24) & 0xff;
+ byte3 = (value >> 16) & 0xff;
+ byte2 = (value >> 8) & 0xff;
+ byte1 = value & 0xff;
+
+ swapped = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
+ return( swapped );
+}
+
+#define CPU_swap_u16( value ) \
+ (((value&0xff) << 8) | ((value >> 8)&0xff))
+
+/*
+ * Special Purpose Routines to hide the use of UNIX system calls.
+ */
+
+
+/*
+ * Pointer to a sync io Handler
+ */
+
+typedef void ( *rtems_sync_io_handler )(
+ int fd,
+ boolean read,
+ boolean wrtie,
+ boolean except
+);
+
+/* returns -1 if fd to large, 0 is successful */
+int _CPU_Set_sync_io_handler(
+ int fd,
+ boolean read,
+ boolean write,
+ boolean except,
+ rtems_sync_io_handler handler
+);
+
+/* returns -1 if fd to large, o if successful */
+int _CPU_Clear_sync_io_handler(
+ int fd
+);
+
+int _CPU_Get_clock_vector( void );
+
+void _CPU_Start_clock(
+ int microseconds
+);
+
+void _CPU_Stop_clock( void );
+
+#if defined(RTEMS_MULTIPROCESSING)
+
+void _CPU_SHM_Init(
+ uint32_t maximum_nodes,
+ boolean is_master_node,
+ void **shm_address,
+ uint32_t *shm_length
+);
+
+int _CPU_Get_pid( void );
+
+int _CPU_SHM_Get_vector( void );
+
+void _CPU_SHM_Send_interrupt(
+ int pid,
+ int vector
+);
+
+void _CPU_SHM_Lock(
+ int semaphore
+);
+
+void _CPU_SHM_Unlock(
+ int semaphore
+);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/score/cpu/unix/rtems/score/types.h b/cpukit/score/cpu/unix/rtems/score/types.h
new file mode 100644
index 0000000000..d15a6f98ef
--- /dev/null
+++ b/cpukit/score/cpu/unix/rtems/score/types.h
@@ -0,0 +1,71 @@
+/* unixtypes.h
+ *
+ * This include file contains type definitions which are appropriate
+ * for a typical modern UNIX box using GNU C for the RTEMS simulator.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __UNIX_TYPES_h
+#define __UNIX_TYPES_h
+
+#ifndef ASM
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * some C++ compilers (eg: HP's) don't do 'signed' or 'volatile'
+ */
+#if defined(__cplusplus) && !defined(__GNUC__)
+#define signed
+#define volatile
+#endif
+
+/*
+ * This section defines the basic types for this processor.
+ */
+
+typedef unsigned char unsigned8; /* unsigned 8-bit integer */
+typedef unsigned short unsigned16; /* unsigned 16-bit integer */
+typedef unsigned int unsigned32; /* unsigned 32-bit integer */
+
+typedef unsigned16 Priority_Bit_map_control;
+
+typedef signed char signed8; /* 8-bit signed integer */
+typedef signed short signed16; /* 16-bit signed integer */
+typedef signed int signed32; /* 32-bit signed integer */
+
+/*
+ * some C++ compilers (eg: HP's) don't do 'long long'
+ */
+#if defined(__GNUC__)
+typedef unsigned long long unsigned64; /* unsigned 64-bit integer */
+typedef signed long long signed64; /* 64 bit signed integer */
+#endif
+
+typedef unsigned32 boolean; /* Boolean value */
+
+typedef float single_precision; /* single precision float */
+typedef double double_precision; /* double precision float */
+
+typedef void unix_isr;
+
+typedef unix_isr ( *unix_isr_entry )( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !ASM */
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/cpu/unix/rtems/score/unix.h b/cpukit/score/cpu/unix/rtems/score/unix.h
new file mode 100644
index 0000000000..db3c3e6591
--- /dev/null
+++ b/cpukit/score/cpu/unix/rtems/score/unix.h
@@ -0,0 +1,71 @@
+/* unix.h
+ *
+ * This include file contains the definitions required by RTEMS
+ * which are typical for a modern UNIX computer using GCC.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __UNIX_h
+#define __UNIX_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This file contains the information required to build
+ * RTEMS for a particular member of the "unix"
+ * family when executing in protected mode. It does
+ * this by setting variables to indicate which implementation
+ * dependent features are present in a particular member
+ * of the family.
+ */
+
+#if defined(rtems_multilib)
+/*
+ * Figure out all CPU Model Feature Flags based upon compiler
+ * predefines.
+ */
+
+#define CPU_MODEL_NAME "rtems_multilib"
+
+#elif defined(hpux)
+
+#define CPU_MODEL_NAME "HP-UX"
+
+#elif defined(solaris2)
+
+#define CPU_MODEL_NAME "Solaris"
+
+#elif defined(__linux__) || defined(linux)
+
+#define CPU_MODEL_NAME "Linux"
+
+#elif defined(__CYGWIN__)
+
+#define CPU_MODEL_NAME "Cygwin"
+
+#elif defined(__FreeBSD__)
+
+#define CPU_MODEL_NAME "FreeBSD"
+
+#else
+
+#error "Unsupported CPU Model"
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/include/rtems/debug.h b/cpukit/score/include/rtems/debug.h
new file mode 100644
index 0000000000..0946cd5b91
--- /dev/null
+++ b/cpukit/score/include/rtems/debug.h
@@ -0,0 +1,97 @@
+/* debug.h
+ *
+ * This include file contains the information pertaining to the debug
+ * support within RTEMS. It is currently cast in the form of a
+ * Manager since it is externally accessible.
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_DEBUG_h
+#define __RTEMS_DEBUG_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * The following type is used to manage the debug mask.
+ */
+
+typedef uint32_t rtems_debug_control;
+
+/*
+ * These constants represent various classes of debugging.
+ */
+
+#define RTEMS_DEBUG_ALL_MASK 0xffffffff
+#define RTEMS_DEBUG_REGION 0x00000001
+
+/*
+ * This variable contains the current debug level.
+ */
+
+SCORE_EXTERN rtems_debug_control _Debug_Level;
+
+/*
+ * _Debug_Manager_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this manager.
+ */
+
+void _Debug_Manager_initialization( void );
+
+/*
+ * rtems_debug_enable
+ *
+ * DESCRIPTION:
+ *
+ * This routine enables the specified types of debug checks.
+ */
+
+void rtems_debug_enable (
+ rtems_debug_control to_be_enabled
+);
+
+/*
+ * rtems_debug_disable
+ *
+ * DESCRIPTION:
+ *
+ * This routine disables the specified types of debug checks.
+ */
+
+void rtems_debug_disable (
+ rtems_debug_control to_be_disabled
+);
+
+/*
+ *
+ * _Debug_Is_enabled
+ *
+ * DESCRIPTION:
+ *
+ * This routine returns TRUE if the requested debug level is
+ * enabled, and FALSE otherwise.
+ */
+
+boolean _Debug_Is_enabled(
+ rtems_debug_control level
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/include/rtems/score/.cvsignore b/cpukit/score/include/rtems/score/.cvsignore
new file mode 100644
index 0000000000..918bba0b73
--- /dev/null
+++ b/cpukit/score/include/rtems/score/.cvsignore
@@ -0,0 +1,6 @@
+stamp-h
+stamp-h.in
+cpuopts.h
+cpuopts.h.in
+cpuopts-tmp.h
+cpuopts-tmp.h.in
diff --git a/cpukit/score/include/rtems/score/address.h b/cpukit/score/include/rtems/score/address.h
new file mode 100644
index 0000000000..587d42a07f
--- /dev/null
+++ b/cpukit/score/include/rtems/score/address.h
@@ -0,0 +1,30 @@
+/* address.h
+ *
+ * This include file contains the information required to manipulate
+ * physical addresses.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_ADDRESSES_h
+#define __RTEMS_ADDRESSES_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/address.inl>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/include/rtems/score/apiext.h b/cpukit/score/include/rtems/score/apiext.h
new file mode 100644
index 0000000000..d5e496c001
--- /dev/null
+++ b/cpukit/score/include/rtems/score/apiext.h
@@ -0,0 +1,101 @@
+/* apiext.h
+ *
+ * This is the API Extensions Handler.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+
+#ifndef __API_EXTENSIONS_h
+#define __API_EXTENSIONS_h
+
+#include <rtems/score/chain.h>
+#include <rtems/score/thread.h>
+
+/*
+ * The control structure which defines the points at which an API
+ * can add an extension to the system initialization thread.
+ */
+
+typedef void (*API_extensions_Predriver_hook)(void);
+typedef void (*API_extensions_Postdriver_hook)(void);
+typedef void (*API_extensions_Postswitch_hook)(
+ Thread_Control *
+ );
+
+
+typedef struct {
+ Chain_Node Node;
+ API_extensions_Predriver_hook predriver_hook;
+ API_extensions_Postdriver_hook postdriver_hook;
+ API_extensions_Postswitch_hook postswitch_hook;
+} API_extensions_Control;
+
+/*
+ * This is the list of API extensions to the system initialization.
+ */
+
+SCORE_EXTERN Chain_Control _API_extensions_List;
+
+/*
+ * _API_extensions_Initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine initializes the API extension handler.
+ *
+ */
+
+void _API_extensions_Initialization( void );
+
+/*
+ * _API_extensions_Add
+ *
+ * DESCRIPTION:
+ *
+ * XXX
+ */
+
+void _API_extensions_Add(
+ API_extensions_Control *the_extension
+);
+
+/*
+ * _API_extensions_Run_predriver
+ *
+ * DESCRIPTION:
+ *
+ * XXX
+ */
+
+void _API_extensions_Run_predriver( void );
+
+/*
+ * _API_extensions_Run_postdriver
+ *
+ * DESCRIPTION:
+ *
+ * XXX
+ */
+
+void _API_extensions_Run_postdriver( void );
+
+/*
+ * _API_extensions_Run_postswitch
+ *
+ * DESCRIPTION:
+ *
+ * XXX
+ */
+
+void _API_extensions_Run_postswitch( void );
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/include/rtems/score/apimutex.h b/cpukit/score/include/rtems/score/apimutex.h
new file mode 100644
index 0000000000..ed345c7c76
--- /dev/null
+++ b/cpukit/score/include/rtems/score/apimutex.h
@@ -0,0 +1,154 @@
+/* apimutex.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the API Mutex Handler. This handler is used by API level
+ * routines to manage mutual exclusion.
+ *
+ * COPYRIGHT (c) 1989-2002.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __API_MUTEX_h
+#define __API_MUTEX_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/coremutex.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+
+/*
+ * The following defines the control block used to manage each mutex.
+ */
+
+typedef struct {
+ Objects_Control Object;
+ CORE_mutex_Control Mutex;
+} API_Mutex_Control;
+
+/*
+ * The following defines the information control block used to manage
+ * this class of objects.
+ */
+
+SCORE_EXTERN Objects_Information _API_Mutex_Information;
+
+/*
+ * _API_Mutex_Initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this handler.
+ */
+
+#if defined(RTEMS_MULTIPROCESSING)
+#define _API_Mutex_Initialization( _maximum_mutexes ) \
+ _Objects_Initialize_information( \
+ &_API_Mutex_Information, \
+ OBJECTS_INTERNAL_API, \
+ OBJECTS_INTERNAL_MUTEXES, \
+ _maximum_mutexes, \
+ sizeof( API_Mutex_Control ), \
+ FALSE, \
+ 0, \
+ FALSE, \
+ NULL \
+ );
+#else
+#define _API_Mutex_Initialization( _maximum_mutexes ) \
+ _Objects_Initialize_information( \
+ &_API_Mutex_Information, \
+ OBJECTS_INTERNAL_API, \
+ OBJECTS_INTERNAL_MUTEXES, \
+ _maximum_mutexes, \
+ sizeof( API_Mutex_Control ), \
+ FALSE, \
+ 0 \
+ );
+#endif
+
+/*
+ * _API_Mutex_Allocate
+ *
+ * DESCRIPTION:
+ *
+ * This routine allocates an api mutex from the inactive set.
+ */
+
+#define _API_Mutex_Allocate( _the_mutex ) \
+ do { \
+ CORE_mutex_Attributes attr = \
+ { CORE_MUTEX_NESTING_IS_ERROR, FALSE, \
+ CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT, 0 }; \
+ (_the_mutex) = (API_Mutex_Control *) \
+ _Objects_Allocate( &_API_Mutex_Information ); \
+ _CORE_mutex_Initialize( \
+ &(_the_mutex)->Mutex, &attr, CORE_MUTEX_UNLOCKED ); \
+ } while (0)
+
+/*
+ * _API_Mutex_Lock
+ *
+ * DESCRIPTION:
+ *
+ * This routine acquires the specified api mutex.
+ */
+
+#define _API_Mutex_Lock( _the_mutex ) \
+ do { \
+ ISR_Level _level; \
+ _ISR_Disable( _level ); \
+ _CORE_mutex_Seize( \
+ &(_the_mutex)->Mutex, (_the_mutex)->Object.id, TRUE, 0, (_level) ); \
+ } while (0)
+
+/*
+ * _API_Mutex_Unlock
+ *
+ * DESCRIPTION:
+ *
+ * This routine releases the specified api mutex.
+ */
+
+#define _API_Mutex_Unlock( _the_mutex ) \
+ do { \
+ _Thread_Disable_dispatch(); \
+ _CORE_mutex_Surrender( \
+ &(_the_mutex)->Mutex, (_the_mutex)->Object.id, NULL ); \
+ _Thread_Enable_dispatch(); \
+ } while (0);
+
+/*XXX when the APIs all use this for allocation and deallocation
+ *XXX protection, then they should be renamed and probably moved
+ */
+
+SCORE_EXTERN API_Mutex_Control *_RTEMS_Allocator_Mutex;
+
+#define _RTEMS_Lock_allocator() \
+ _API_Mutex_Lock( _RTEMS_Allocator_Mutex )
+
+#define _RTEMS_Unlock_allocator() \
+ _API_Mutex_Unlock( _RTEMS_Allocator_Mutex )
+
+/*
+ * There are no inlines for this handler.
+ */
+
+#ifndef __RTEMS_APPLICATION__
+/* #include <rtems/score/apimutex.inl> */
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/include/rtems/score/bitfield.h b/cpukit/score/include/rtems/score/bitfield.h
new file mode 100644
index 0000000000..5b4c678457
--- /dev/null
+++ b/cpukit/score/include/rtems/score/bitfield.h
@@ -0,0 +1,97 @@
+/* bitfield.h
+ *
+ * This include file contains all bit field manipulation routines.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_BITFIELD_h
+#define __RTEMS_BITFIELD_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * _Bitfield_Find_first_bit
+ *
+ * DESCRIPTION:
+ *
+ * This routine returns the bit_number of the first bit set
+ * in the specified value. The correspondence between bit_number
+ * and actual bit position is processor dependent. The search for
+ * the first bit set may run from most to least significant bit
+ * or vice-versa.
+ *
+ * NOTE:
+ *
+ * This routine is used when the executing thread is removed
+ * from the ready state and, as a result, its performance has a
+ * significant impact on the performance of the executive as a whole.
+ */
+
+#if ( CPU_USE_GENERIC_BITFIELD_DATA == TRUE )
+
+#ifndef SCORE_INIT
+extern const unsigned char __log2table[256];
+#else
+const unsigned char __log2table[256] = {
+ 7, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+#endif
+
+#endif
+
+#if ( CPU_USE_GENERIC_BITFIELD_CODE == FALSE )
+
+#define _Bitfield_Find_first_bit( _value, _bit_number ) \
+ _CPU_Bitfield_Find_first_bit( _value, _bit_number )
+
+#else
+
+/*
+ * The following must be a macro because if a CPU specific version
+ * is used it will most likely use inline assembly.
+ */
+
+#define _Bitfield_Find_first_bit( _value, _bit_number ) \
+ { \
+ register uint32_t __value = (uint32_t ) (_value); \
+ register const unsigned char *__p = __log2table; \
+ \
+ if ( __value < 0x100 ) \
+ (_bit_number) = __p[ __value ] + 8; \
+ else \
+ (_bit_number) = __p[ __value >> 8 ]; \
+ }
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/include/rtems/score/chain.h b/cpukit/score/include/rtems/score/chain.h
new file mode 100644
index 0000000000..5e70652f43
--- /dev/null
+++ b/cpukit/score/include/rtems/score/chain.h
@@ -0,0 +1,167 @@
+/* chain.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the Doubly Linked Chain Handler.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_CHAIN_h
+#define __RTEMS_CHAIN_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/address.h>
+
+/*
+ * This is used to manage each element (node) which is placed
+ * on a chain.
+ *
+ * NOTE: Typically, a more complicated structure will use the
+ * chain package. The more complicated structure will
+ * include a chain node as the first element in its
+ * control structure. It will then call the chain package
+ * with a pointer to that node element. The node pointer
+ * and the higher level structure start at the same address
+ * so the user can cast the pointers back and forth.
+ *
+ */
+
+typedef struct Chain_Node_struct Chain_Node;
+
+struct Chain_Node_struct {
+ Chain_Node *next;
+ Chain_Node *previous;
+};
+
+/*
+ * This is used to manage a chain. A chain consists of a doubly
+ * linked list of zero or more nodes.
+ *
+ * NOTE: This implementation does not require special checks for
+ * manipulating the first and last elements on the chain.
+ * To accomplish this the chain control structure is
+ * treated as two overlapping chain nodes. The permanent
+ * head of the chain overlays a node structure on the
+ * first and permanent_null fields. The permanent tail
+ * of the chain overlays a node structure on the
+ * permanent_null and last elements of the structure.
+ *
+ */
+
+typedef struct {
+ Chain_Node *first;
+ Chain_Node *permanent_null;
+ Chain_Node *last;
+} Chain_Control;
+
+/*
+ * _Chain_Initialize
+ *
+ * DESCRIPTION:
+ *
+ * This routine initializes the_chain structure to manage the
+ * contiguous array of number_nodes nodes which starts at
+ * starting_address. Each node is of node_size bytes.
+ *
+ */
+
+void _Chain_Initialize(
+ Chain_Control *the_chain,
+ void *starting_address,
+ uint32_t number_nodes,
+ uint32_t node_size
+);
+
+/*
+ * _Chain_Get_first_unprotected
+ */
+
+#ifndef RTEMS_INLINES
+Chain_Node *_Chain_Get_first_unprotected(
+ Chain_Control *the_chain
+);
+#endif
+
+/*
+ * _Chain_Extract
+ *
+ * DESCRIPTION:
+ *
+ * This routine extracts the_node from the chain on which it resides.
+ * It disables interrupts to insure the atomicity of the
+ * extract operation.
+ *
+ */
+
+void _Chain_Extract(
+ Chain_Node *the_node
+);
+
+/*
+ * _Chain_Get
+ *
+ * DESCRIPTION:
+ *
+ * This function removes the first node from the_chain and returns
+ * a pointer to that node. If the_chain is empty, then NULL is returned.
+ * It disables interrupts to insure the atomicity of the
+ * get operation.
+ *
+ */
+
+Chain_Node *_Chain_Get(
+ Chain_Control *the_chain
+);
+
+/*
+ * _Chain_Insert
+ *
+ * DESCRIPTION:
+ *
+ * This routine inserts the_node on a chain immediately following
+ * after_node. It disables interrupts to insure the atomicity
+ * of the extract operation.
+ *
+ */
+
+void _Chain_Insert(
+ Chain_Node *after_node,
+ Chain_Node *the_node
+);
+
+/*
+ * _Chain_Append
+ *
+ * DESCRIPTION:
+ *
+ * This routine appends the_node onto the end of the_chain.
+ * It disables interrupts to insure the atomicity of the
+ * append operation.
+ *
+ */
+
+void _Chain_Append(
+ Chain_Control *the_chain,
+ Chain_Node *the_node
+);
+
+#ifndef __RTEMS_APPLICATION__
+#include <rtems/score/chain.inl>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/include/rtems/score/context.h b/cpukit/score/include/rtems/score/context.h
new file mode 100644
index 0000000000..f1ea268c13
--- /dev/null
+++ b/cpukit/score/include/rtems/score/context.h
@@ -0,0 +1,133 @@
+/* context.h
+ *
+ * This include file contains all information about a context.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_CONTEXT_h
+#define __RTEMS_CONTEXT_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/cpu.h>
+
+/*
+ * The following constant defines the number of bytes required
+ * to store a full floating point context.
+ */
+
+#define CONTEXT_FP_SIZE CPU_CONTEXT_FP_SIZE
+
+/*
+ * The following variable is set to TRUE when a reschedule operation
+ * has determined that the processor should be taken away from the
+ * currently executing thread and given to the heir thread.
+ */
+
+SCORE_EXTERN volatile boolean _Context_Switch_necessary;
+
+/*
+ * _Context_Initialize
+ *
+ * DESCRIPTION:
+ *
+ * This routine initializes THE_CONTEXT such that the stack
+ * pointer, interrupt level, and entry point are correct for the
+ * thread's initial state.
+ */
+
+#define \
+ _Context_Initialize( _the_context, _stack, _size, _isr, _entry, _is_fp ) \
+ _CPU_Context_Initialize( _the_context, _stack, _size, _isr, _entry, _is_fp )
+
+/*
+ * _Context_Switch
+ *
+ * DESCRIPTION:
+ *
+ * This routine saves the current context into the EXECUTING
+ * context record and restores the context specified by HEIR.
+ */
+
+#define _Context_Switch( _executing, _heir ) \
+ _CPU_Context_switch( _executing, _heir )
+
+/*
+ * _Context_Restart_self
+ *
+ * DESCRIPTION:
+ *
+ * This routine restarts the calling thread by restoring its initial
+ * stack pointer and returning to the thread's entry point.
+ */
+
+#define _Context_Restart_self( _the_context ) \
+ _CPU_Context_Restart_self( _the_context )
+
+/*
+ * _Context_Fp_start
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the starting address of the floating
+ * point context save area. It is assumed that the are reserved
+ * for the floating point save area is large enough.
+ */
+
+#define _Context_Fp_start( _base, _offset ) \
+ _CPU_Context_Fp_start( (_base), (_offset) )
+
+/*
+ * _Context_Initialize_fp
+ *
+ * DESCRIPTION:
+ *
+ * This routine initializes the floating point context save
+ * area to contain an initial known state.
+ */
+
+#define _Context_Initialize_fp( _fp_area ) \
+ _CPU_Context_Initialize_fp( _fp_area )
+
+/*
+ * _Context_Restore_fp
+ *
+ * DESCRIPTION:
+ *
+ * This routine restores the floating point context contained
+ * in the FP_CONTEXT area. It is assumed that the current
+ * floating point context has been saved by a previous invocation
+ * of SAVE_FP.
+ */
+
+#define _Context_Restore_fp( _fp ) \
+ _CPU_Context_restore_fp( _fp )
+
+/*
+ * _Context_Save_fp
+ *
+ * DESCRIPTION:
+ *
+ * This routine saves the current floating point context
+ * in the FP_CONTEXT area.
+ */
+
+#define _Context_Save_fp( _fp ) \
+ _CPU_Context_save_fp( _fp )
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/include/rtems/score/copyrt.h b/cpukit/score/include/rtems/score/copyrt.h
new file mode 100644
index 0000000000..f18e3c675e
--- /dev/null
+++ b/cpukit/score/include/rtems/score/copyrt.h
@@ -0,0 +1,40 @@
+/* copyrt.h
+ *
+ * This include file contains the copyright notice for RTEMS
+ * which is included in every binary copy of the executive.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_COPYRIGHT_h
+#define __RTEMS_COPYRIGHT_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef SCORE_INIT
+
+const char _Copyright_Notice[] =
+"COPYRIGHT (c) 1989-1999.\n\
+On-Line Applications Research Corporation (OAR).\n";
+
+#else
+
+extern const char _Copyright_Notice[];
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/include/rtems/score/coremsg.h b/cpukit/score/include/rtems/score/coremsg.h
new file mode 100644
index 0000000000..70906135a4
--- /dev/null
+++ b/cpukit/score/include/rtems/score/coremsg.h
@@ -0,0 +1,299 @@
+/* coremsg.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the Message queue Handler.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_CORE_MESSAGE_QUEUE_h
+#define __RTEMS_CORE_MESSAGE_QUEUE_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <limits.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/watchdog.h>
+
+/*
+ * The following type defines the callout which the API provides
+ * to support global/multiprocessor operations on message_queues.
+ */
+
+typedef void ( *CORE_message_queue_API_mp_support_callout )(
+ Thread_Control *,
+ Objects_Id
+ );
+
+/*
+ * The following defines the data types needed to manipulate
+ * the contents of message buffers.
+ *
+ * NOTE: The buffer field is normally longer than a single uint32_t .
+ * but since messages are variable length we just make a ptr to 1.
+ */
+
+typedef struct {
+ uint32_t size;
+ uint32_t buffer[1];
+} CORE_message_queue_Buffer;
+
+/*
+ * The following records define the organization of a message
+ * buffer.
+ */
+
+typedef struct {
+ Chain_Node Node;
+ int priority;
+ CORE_message_queue_Buffer Contents;
+} CORE_message_queue_Buffer_control;
+
+/*
+ * Blocking disciplines for a message_queue.
+ */
+
+typedef enum {
+ CORE_MESSAGE_QUEUE_DISCIPLINES_FIFO,
+ CORE_MESSAGE_QUEUE_DISCIPLINES_PRIORITY
+} CORE_message_queue_Disciplines;
+
+/*
+ * The following enumerated type details the modes in which a message
+ * may be submitted to a message queue. The message may be posted
+ * in a send or urgent fashion.
+ *
+ * NOTE: All other values are message priorities. Numerically smaller
+ * priorities indicate higher priority messages.
+ *
+ */
+
+#define CORE_MESSAGE_QUEUE_SEND_REQUEST INT_MAX
+#define CORE_MESSAGE_QUEUE_URGENT_REQUEST INT_MIN
+
+typedef int CORE_message_queue_Submit_types;
+
+/*
+ * Core Message queue handler return statuses.
+ */
+
+typedef enum {
+ CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL,
+ CORE_MESSAGE_QUEUE_STATUS_INVALID_SIZE,
+ CORE_MESSAGE_QUEUE_STATUS_TOO_MANY,
+ CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED,
+ CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_NOWAIT,
+ CORE_MESSAGE_QUEUE_STATUS_WAS_DELETED,
+ CORE_MESSAGE_QUEUE_STATUS_TIMEOUT,
+ CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_WAIT
+} CORE_message_queue_Status;
+
+/*
+ * The following defines the control block used to manage the
+ * attributes of each message queue.
+ */
+
+typedef struct {
+ CORE_message_queue_Disciplines discipline;
+} CORE_message_queue_Attributes;
+
+/*
+ * The following defines the type for a Notification handler. A notification
+ * handler is invoked when the message queue makes a 0->1 transition on
+ * pending messages.
+ */
+
+typedef void (*CORE_message_queue_Notify_Handler)( void * );
+
+/*
+ * The following defines the control block used to manage each
+ * counting message_queue.
+ */
+
+typedef struct {
+ Thread_queue_Control Wait_queue;
+ CORE_message_queue_Attributes Attributes;
+ uint32_t maximum_pending_messages;
+ uint32_t number_of_pending_messages;
+ uint32_t maximum_message_size;
+ Chain_Control Pending_messages;
+ CORE_message_queue_Buffer *message_buffers;
+ CORE_message_queue_Notify_Handler notify_handler;
+ void *notify_argument;
+ Chain_Control Inactive_messages;
+} CORE_message_queue_Control;
+
+/*
+ * _CORE_message_queue_Initialize
+ *
+ * DESCRIPTION:
+ *
+ * This routine initializes the message_queue based on the parameters passed.
+ */
+
+boolean _CORE_message_queue_Initialize(
+ CORE_message_queue_Control *the_message_queue,
+ CORE_message_queue_Attributes *the_message_queue_attributes,
+ uint32_t maximum_pending_messages,
+ uint32_t maximum_message_size
+);
+
+/*
+ * _CORE_message_queue_Close
+ *
+ * DESCRIPTION:
+ *
+ * This function closes a message by returning all allocated space and
+ * flushing the message_queue's task wait queue.
+ */
+
+void _CORE_message_queue_Close(
+ CORE_message_queue_Control *the_message_queue,
+ Thread_queue_Flush_callout remote_extract_callout,
+ uint32_t status
+);
+
+/*
+ * _CORE_message_queue_Flush
+ *
+ * DESCRIPTION:
+ *
+ * This function flushes the message_queue's pending message queue. The
+ * number of messages flushed from the queue is returned.
+ *
+ */
+
+uint32_t _CORE_message_queue_Flush(
+ CORE_message_queue_Control *the_message_queue
+);
+
+/*
+ * _CORE_message_queue_Flush_support
+ *
+ * DESCRIPTION:
+ *
+ * This routine flushes all outstanding messages and returns
+ * them to the inactive message chain.
+ */
+
+uint32_t _CORE_message_queue_Flush_support(
+ CORE_message_queue_Control *the_message_queue
+);
+
+/*
+ * _CORE_message_queue_Flush_waiting_threads
+ *
+ * DESCRIPTION:
+ *
+ * This function flushes the threads which are blocked on this
+ * message_queue's pending message queue. They are unblocked whether
+ * blocked sending or receiving.
+ */
+
+void _CORE_message_queue_Flush_waiting_threads(
+ CORE_message_queue_Control *the_message_queue
+);
+
+/*
+ * _CORE_message_queue_Broadcast
+ *
+ * DESCRIPTION:
+ *
+ * This function sends a message for every thread waiting on the queue and
+ * returns the number of threads made ready by the message.
+ *
+ */
+
+CORE_message_queue_Status _CORE_message_queue_Broadcast(
+ CORE_message_queue_Control *the_message_queue,
+ void *buffer,
+ uint32_t size,
+ Objects_Id id,
+ CORE_message_queue_API_mp_support_callout api_message_queue_mp_support,
+ uint32_t *count
+);
+
+/*
+ * _CORE_message_queue_Submit
+ *
+ * DESCRIPTION:
+ *
+ * This routine implements the send and urgent message functions. It
+ * processes a message that is to be submitted to the designated
+ * message queue. The message will either be processed as a
+ * send message which it will be inserted at the rear of the queue
+ * or it will be processed as an urgent message which will be inserted
+ * at the front of the queue.
+ *
+ */
+
+CORE_message_queue_Status _CORE_message_queue_Submit(
+ CORE_message_queue_Control *the_message_queue,
+ void *buffer,
+ uint32_t size,
+ Objects_Id id,
+ CORE_message_queue_API_mp_support_callout api_message_queue_mp_support,
+ CORE_message_queue_Submit_types submit_type,
+ boolean wait,
+ Watchdog_Interval timeout
+);
+
+/*
+ * _CORE_message_queue_Seize
+ *
+ * DESCRIPTION:
+ *
+ * This kernel routine dequeues a message, copies the message buffer to
+ * a given destination buffer, and frees the message buffer to the
+ * inactive message pool. The thread will be blocked if wait is TRUE,
+ * otherwise an error will be given to the thread if no messages are available.
+ *
+ * NOTE: Returns message priority via return are in TCB.
+ */
+
+void _CORE_message_queue_Seize(
+ CORE_message_queue_Control *the_message_queue,
+ Objects_Id id,
+ void *buffer,
+ uint32_t *size,
+ boolean wait,
+ Watchdog_Interval timeout
+);
+
+/*
+ * _CORE_message_queue_Insert_message
+ *
+ * DESCRIPTION:
+ *
+ * This kernel routine inserts the specified message into the
+ * message queue. It is assumed that the message has been filled
+ * in before this routine is called.
+ */
+
+void _CORE_message_queue_Insert_message(
+ CORE_message_queue_Control *the_message_queue,
+ CORE_message_queue_Buffer_control *the_message,
+ CORE_message_queue_Submit_types submit_type
+);
+
+#ifndef __RTEMS_APPLICATION__
+#include <rtems/score/coremsg.inl>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/include/rtems/score/coremutex.h b/cpukit/score/include/rtems/score/coremutex.h
new file mode 100644
index 0000000000..ec55009843
--- /dev/null
+++ b/cpukit/score/include/rtems/score/coremutex.h
@@ -0,0 +1,236 @@
+/* mutex.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the Mutex Handler. A mutex is an enhanced version of the standard
+ * Dijkstra binary semaphore used to provide synchronization and mutual
+ * exclusion capabilities.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_CORE_MUTEX_h
+#define __RTEMS_CORE_MUTEX_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/sysstate.h>
+
+/*
+ * The following type defines the callout which the API provides
+ * to support global/multiprocessor operations on mutexes.
+ */
+
+typedef void ( *CORE_mutex_API_mp_support_callout )(
+ Thread_Control *,
+ Objects_Id
+ );
+
+/*
+ * Blocking disciplines for a mutex.
+ */
+
+typedef enum {
+ CORE_MUTEX_DISCIPLINES_FIFO,
+ CORE_MUTEX_DISCIPLINES_PRIORITY,
+ CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT,
+ CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING
+} CORE_mutex_Disciplines;
+
+/*
+ * Mutex handler return statuses.
+ */
+
+typedef enum {
+ CORE_MUTEX_STATUS_SUCCESSFUL,
+ CORE_MUTEX_STATUS_UNSATISFIED_NOWAIT,
+ CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED,
+ CORE_MUTEX_STATUS_NOT_OWNER_OF_RESOURCE,
+ CORE_MUTEX_WAS_DELETED,
+ CORE_MUTEX_TIMEOUT,
+ CORE_MUTEX_STATUS_CEILING_VIOLATED
+} CORE_mutex_Status;
+
+/*
+ * Mutex lock nesting behavior
+ *
+ * CORE_MUTEX_NESTING_ACQUIRES:
+ * This sequence has no blocking or errors:
+ * lock(m)
+ * lock(m)
+ * unlock(m)
+ * unlock(m)
+ *
+ * CORE_MUTEX_NESTING_IS_ERROR
+ * This sequence returns an error at the indicated point:
+ * lock(m)
+ * lock(m) - already locked error
+ * unlock(m)
+ *
+ * CORE_MUTEX_NESTING_BLOCKS
+ * This sequence performs as indicated:
+ * lock(m)
+ * lock(m) - deadlocks or timeouts
+ * unlock(m) - releases
+ */
+
+typedef enum {
+ CORE_MUTEX_NESTING_ACQUIRES,
+ CORE_MUTEX_NESTING_IS_ERROR,
+ CORE_MUTEX_NESTING_BLOCKS
+} CORE_mutex_Nesting_behaviors;
+
+/*
+ * Locked and unlocked values
+ */
+
+#define CORE_MUTEX_UNLOCKED 1
+#define CORE_MUTEX_LOCKED 0
+
+/*
+ * The following defines the control block used to manage the
+ * attributes of each mutex.
+ */
+
+typedef struct {
+ CORE_mutex_Nesting_behaviors lock_nesting_behavior;
+ boolean only_owner_release;
+ CORE_mutex_Disciplines discipline;
+ Priority_Control priority_ceiling;
+} CORE_mutex_Attributes;
+
+/*
+ * The following defines the control block used to manage each mutex.
+ */
+
+typedef struct {
+ Thread_queue_Control Wait_queue;
+ CORE_mutex_Attributes Attributes;
+ uint32_t lock;
+ uint32_t nest_count;
+ uint32_t blocked_count;
+ Thread_Control *holder;
+ Objects_Id holder_id;
+} CORE_mutex_Control;
+
+/*
+ * _CORE_mutex_Initialize
+ *
+ * DESCRIPTION:
+ *
+ * This routine initializes the mutex based on the parameters passed.
+ */
+
+void _CORE_mutex_Initialize(
+ CORE_mutex_Control *the_mutex,
+ CORE_mutex_Attributes *the_mutex_attributes,
+ uint32_t initial_lock
+);
+
+/*
+ * _CORE_mutex_Seize
+ *
+ * DESCRIPTION:
+ *
+ * This routine attempts to receive a unit from the_mutex.
+ * If a unit is available or if the wait flag is FALSE, then the routine
+ * returns. Otherwise, the calling task is blocked until a unit becomes
+ * available.
+ *
+ * NOTE: For performance reasons, this routine is implemented as
+ * a macro that uses two support routines.
+ */
+
+
+#ifndef __RTEMS_APPLICATION__
+RTEMS_INLINE_ROUTINE int _CORE_mutex_Seize_interrupt_trylock(
+ CORE_mutex_Control *the_mutex,
+ ISR_Level *level_p
+);
+
+void _CORE_mutex_Seize_interrupt_blocking(
+ CORE_mutex_Control *the_mutex,
+ Watchdog_Interval timeout
+);
+
+#define _CORE_mutex_Seize( \
+ _the_mutex, _id, _wait, _timeout, _level ) \
+ do { \
+ if ( _Thread_Dispatch_disable_level \
+ && (_wait) \
+ && (_System_state_Get() >= SYSTEM_STATE_BEGIN_MULTITASKING ) \
+ ) { \
+ _Internal_error_Occurred( \
+ INTERNAL_ERROR_CORE, \
+ FALSE, \
+ 18 /* called from wrong environment */); \
+ } \
+ if ( _CORE_mutex_Seize_interrupt_trylock( _the_mutex, &_level ) ) { \
+ if ( !_wait ) { \
+ _ISR_Enable( _level ); \
+ _Thread_Executing->Wait.return_code = \
+ CORE_MUTEX_STATUS_UNSATISFIED_NOWAIT; \
+ } else { \
+ _Thread_queue_Enter_critical_section( &(_the_mutex)->Wait_queue ); \
+ _Thread_Executing->Wait.queue = &(_the_mutex)->Wait_queue; \
+ _Thread_Executing->Wait.id = _id; \
+ _Thread_Disable_dispatch(); \
+ _ISR_Enable( _level ); \
+ _CORE_mutex_Seize_interrupt_blocking( _the_mutex, _timeout ); \
+ } \
+ } \
+ } while (0)
+
+/*
+ * _CORE_mutex_Surrender
+ *
+ * DESCRIPTION:
+ *
+ * This routine frees a unit to the mutex. If a task was blocked waiting for
+ * a unit from this mutex, then that task will be readied and the unit
+ * given to that task. Otherwise, the unit will be returned to the mutex.
+ */
+
+CORE_mutex_Status _CORE_mutex_Surrender(
+ CORE_mutex_Control *the_mutex,
+ Objects_Id id,
+ CORE_mutex_API_mp_support_callout api_mutex_mp_support
+);
+
+/*
+ * _CORE_mutex_Flush
+ *
+ * DESCRIPTION:
+ *
+ * This routine assists in the deletion of a mutex by flushing the associated
+ * wait queue.
+ */
+
+void _CORE_mutex_Flush(
+ CORE_mutex_Control *the_mutex,
+ Thread_queue_Flush_callout remote_extract_callout,
+ uint32_t status
+);
+
+#include <rtems/score/coremutex.inl>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/include/rtems/score/coresem.h b/cpukit/score/include/rtems/score/coresem.h
new file mode 100644
index 0000000000..e9be0036ab
--- /dev/null
+++ b/cpukit/score/include/rtems/score/coresem.h
@@ -0,0 +1,154 @@
+/* core_sem.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the Counting Semaphore Handler. A counting semaphore is the
+ * standard Dijkstra binary semaphore used to provide synchronization
+ * and mutual exclusion capabilities.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_CORE_COUNTING_SEMAPHORE_h
+#define __RTEMS_CORE_COUNTING_SEMAPHORE_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/watchdog.h>
+
+/*
+ * The following type defines the callout which the API provides
+ * to support global/multiprocessor operations on semaphores.
+ */
+
+typedef void ( *CORE_semaphore_API_mp_support_callout )(
+ Thread_Control *,
+ Objects_Id
+ );
+
+/*
+ * Blocking disciplines for a semaphore.
+ */
+
+typedef enum {
+ CORE_SEMAPHORE_DISCIPLINES_FIFO,
+ CORE_SEMAPHORE_DISCIPLINES_PRIORITY
+} CORE_semaphore_Disciplines;
+
+/*
+ * Core Semaphore handler return statuses.
+ */
+
+typedef enum {
+ CORE_SEMAPHORE_STATUS_SUCCESSFUL,
+ CORE_SEMAPHORE_STATUS_UNSATISFIED_NOWAIT,
+ CORE_SEMAPHORE_WAS_DELETED,
+ CORE_SEMAPHORE_TIMEOUT,
+ CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED
+} CORE_semaphore_Status;
+
+/*
+ * The following defines the control block used to manage the
+ * attributes of each semaphore.
+ */
+
+typedef struct {
+ uint32_t maximum_count;
+ CORE_semaphore_Disciplines discipline;
+} CORE_semaphore_Attributes;
+
+/*
+ * The following defines the control block used to manage each
+ * counting semaphore.
+ */
+
+typedef struct {
+ Thread_queue_Control Wait_queue;
+ CORE_semaphore_Attributes Attributes;
+ uint32_t count;
+} CORE_semaphore_Control;
+
+/*
+ * _CORE_semaphore_Initialize
+ *
+ * DESCRIPTION:
+ *
+ * This routine initializes the semaphore based on the parameters passed.
+ */
+
+void _CORE_semaphore_Initialize(
+ CORE_semaphore_Control *the_semaphore,
+ CORE_semaphore_Attributes *the_semaphore_attributes,
+ uint32_t initial_value
+);
+
+/*
+ * _CORE_semaphore_Seize
+ *
+ * DESCRIPTION:
+ *
+ * This routine attempts to receive a unit from the_semaphore.
+ * If a unit is available or if the wait flag is FALSE, then the routine
+ * returns. Otherwise, the calling task is blocked until a unit becomes
+ * available.
+ */
+
+void _CORE_semaphore_Seize(
+ CORE_semaphore_Control *the_semaphore,
+ Objects_Id id,
+ boolean wait,
+ Watchdog_Interval timeout
+);
+
+/*
+ * _CORE_semaphore_Surrender
+ *
+ * DESCRIPTION:
+ *
+ * This routine frees a unit to the semaphore. If a task was blocked waiting
+ * for a unit from this semaphore, then that task will be readied and the unit
+ * given to that task. Otherwise, the unit will be returned to the semaphore.
+ */
+
+CORE_semaphore_Status _CORE_semaphore_Surrender(
+ CORE_semaphore_Control *the_semaphore,
+ Objects_Id id,
+ CORE_semaphore_API_mp_support_callout api_semaphore_mp_support
+);
+
+/*
+ * _CORE_semaphore_Flush
+ *
+ * DESCRIPTION:
+ *
+ * This routine assists in the deletion of a semaphore by flushing the
+ * associated wait queue.
+ */
+
+void _CORE_semaphore_Flush(
+ CORE_semaphore_Control *the_semaphore,
+ Thread_queue_Flush_callout remote_extract_callout,
+ uint32_t status
+);
+
+#ifndef __RTEMS_APPLICATION__
+#include <rtems/score/coresem.inl>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/include/rtems/score/heap.h b/cpukit/score/include/rtems/score/heap.h
new file mode 100644
index 0000000000..9b1387ecbf
--- /dev/null
+++ b/cpukit/score/include/rtems/score/heap.h
@@ -0,0 +1,269 @@
+/* heap.h
+ *
+ * This include file contains the information pertaining to the Heap
+ * Handler. A heap is a doubly linked list of variable size
+ * blocks which are allocated using the first fit method. Garbage
+ * collection is performed each time a block is returned to the heap by
+ * coalescing neighbor blocks. Control information for both allocated
+ * and unallocated blocks is contained in the heap space. A heap header
+ * contains control information for the heap.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_HEAP_h
+#define __RTEMS_HEAP_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Status codes for heap_extend
+ */
+
+typedef enum {
+ HEAP_EXTEND_SUCCESSFUL,
+ HEAP_EXTEND_ERROR,
+ HEAP_EXTEND_NOT_IMPLEMENTED
+} Heap_Extend_status;
+
+/*
+ * Status codes for _Heap_Get_information
+ */
+
+typedef enum {
+ HEAP_GET_INFORMATION_SUCCESSFUL = 0,
+ HEAP_GET_INFORMATION_SYSTEM_STATE_ERROR,
+ HEAP_GET_INFORMATION_BLOCK_ERROR
+} Heap_Get_information_status;
+
+/*
+ * Information block returned by _Heap_Get_information
+ */
+
+typedef struct {
+ uint32_t free_blocks;
+ uint32_t free_size;
+ uint32_t used_blocks;
+ uint32_t used_size;
+} Heap_Information_block;
+
+/*
+ * Constants used in the size/used field of each heap block to
+ * indicate when a block is free or in use.
+ */
+
+#define HEAP_BLOCK_USED 1 /* indicates block is in use */
+#define HEAP_BLOCK_FREE 0 /* indicates block is free */
+
+/*
+ * The size/used field value for the dummy front and back flags.
+ */
+
+#define HEAP_DUMMY_FLAG (0 + HEAP_BLOCK_USED)
+
+/*
+ * The following constants reflect various requirements of the
+ * heap data structures which impact the management of a heap.
+ *
+ * NOTE: Because free block overhead is greater than used block
+ * overhead AND a portion of the allocated space is from
+ * the extra free block overhead, the absolute lower bound
+ * of the minimum fragment size is equal to the size of
+ * the free block overhead.
+ */
+
+#define HEAP_OVERHEAD \
+ (sizeof( uint32_t ) * 2) /* size dummy first and last blocks */
+#define HEAP_BLOCK_USED_OVERHEAD \
+ (sizeof( void * ) * 2) /* num bytes overhead in used block */
+#define HEAP_MINIMUM_SIZE \
+ (HEAP_OVERHEAD + sizeof (Heap_Block))
+ /* min number of bytes the user may */
+ /* specify for the heap size */
+
+/*
+ * The following defines the data structure used to manage
+ * individual blocks in a heap. When the block is allocated, the
+ * next and previous fields are not used by the Heap Handler
+ * and thus the address returned for the block starts at
+ * the address of the next field.
+ *
+ * NOTE: The next and previous pointers are only valid when the
+ * block is free. Caution must be exercised to insure that
+ * allocated blocks are large enough to contain them and
+ * that they are not accidentally overwritten when the
+ * block is actually allocated.
+ */
+
+typedef struct Heap_Block_struct Heap_Block;
+
+struct Heap_Block_struct {
+ uint32_t back_flag; /* size and status of prev block */
+ uint32_t front_flag; /* size and status of block */
+ Heap_Block *next; /* pointer to next block */
+ Heap_Block *previous; /* pointer to previous block */
+};
+
+/*
+ * The following defines the control block used to manage each heap.
+ *
+ * NOTE:
+ *
+ * This structure is layed out such that it can be used a a dummy
+ * first and last block on the free block chain. The extra padding
+ * insures the dummy last block is the correct size.
+ *
+ * The first Heap_Block starts at first while the second starts at
+ * final. This is effectively the same trick as is used in the Chain
+ * Handler.
+ */
+
+typedef struct {
+ Heap_Block *start; /* first valid block address in heap */
+ Heap_Block *final; /* last valid block address in heap */
+
+ Heap_Block *first; /* pointer to first block in heap */
+ Heap_Block *permanent_null; /* always NULL pointer */
+ Heap_Block *last; /* pointer to last block in heap */
+ uint32_t page_size; /* allocation unit */
+ uint32_t reserved;
+} Heap_Control;
+
+/*
+ * _Heap_Initialize
+ *
+ * DESCRIPTION:
+ *
+ * This routine initializes the_heap record to manage the
+ * contiguous heap of size bytes which starts at starting_address.
+ * Blocks of memory are allocated from the heap in multiples of
+ * page_size byte units.
+ */
+
+uint32_t _Heap_Initialize(
+ Heap_Control *the_heap,
+ void *starting_address,
+ uint32_t size,
+ uint32_t page_size
+);
+
+/*
+ * _Heap_Extend
+ *
+ * DESCRIPTION:
+ *
+ * This routine grows the_heap memory area using the size bytes which
+ * begin at starting_address.
+ */
+
+Heap_Extend_status _Heap_Extend(
+ Heap_Control *the_heap,
+ void *starting_address,
+ uint32_t size,
+ uint32_t *amount_extended
+);
+
+/*
+ * _Heap_Allocate
+ *
+ * DESCRIPTION:
+ *
+ * DESCRIPTION:
+ *
+ * This function attempts to allocate a block of size bytes from
+ * the_heap. If insufficient memory is free in the_heap to allocate
+ * a block of the requested size, then NULL is returned.
+ */
+
+void *_Heap_Allocate(
+ Heap_Control *the_heap,
+ uint32_t size
+);
+
+/*
+ * _Heap_Size_of_user_area
+ *
+ * DESCRIPTION:
+ *
+ * This kernel routine sets size to the size of the given heap block.
+ * It returns TRUE if the starting_address is in the heap, and FALSE
+ * otherwise.
+ */
+
+boolean _Heap_Size_of_user_area(
+ Heap_Control *the_heap,
+ void *starting_address,
+ uint32_t *size
+);
+
+/*
+ * _Heap_Free
+ *
+ * DESCRIPTION:
+ *
+ * This routine returns the block of memory which begins
+ * at starting_address to the_heap. Any coalescing which is
+ * possible with the freeing of this routine is performed.
+ */
+
+boolean _Heap_Free(
+ Heap_Control *the_heap,
+ void *start_address
+);
+
+/*
+ * _Heap_Walk
+ *
+ * DESCRIPTION:
+ *
+ * This routine walks the heap to verify its integrity.
+ */
+
+void _Heap_Walk(
+ Heap_Control *the_heap,
+ int source,
+ boolean do_dump
+);
+
+/*PAGE
+ *
+ * _Heap_Get_information
+ *
+ * This kernel routine walks the heap and tots up the free and allocated
+ * sizes. Derived from _Heap_Walk.
+ *
+ * Input parameters:
+ * the_heap - pointer to heap header
+ * the_info - pointer to information block
+ *
+ * Output parameters:
+ * *the_info - status information
+ * return 0=success, otherwise heap is corrupt.
+ */
+
+
+Heap_Get_information_status _Heap_Get_information(
+ Heap_Control *the_heap,
+ Heap_Information_block *the_info
+);
+
+
+#ifndef __RTEMS_APPLICATION__
+#include <rtems/score/heap.inl>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/include/rtems/score/interr.h b/cpukit/score/include/rtems/score/interr.h
new file mode 100644
index 0000000000..536e30bef0
--- /dev/null
+++ b/cpukit/score/include/rtems/score/interr.h
@@ -0,0 +1,96 @@
+/* interr.h
+ *
+ * This include file contains constants and prototypes related
+ * to the Internal Error Handler.
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_INTERNAL_ERROR_h
+#define __RTEMS_INTERNAL_ERROR_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This type lists the possible sources from which an error
+ * can be reported.
+ */
+
+typedef enum {
+ INTERNAL_ERROR_CORE,
+ INTERNAL_ERROR_RTEMS_API,
+ INTERNAL_ERROR_POSIX_API,
+ INTERNAL_ERROR_ITRON_API
+} Internal_errors_Source;
+
+/*
+ * A list of errors which are generated internally by the executive core.
+ */
+
+typedef enum {
+ INTERNAL_ERROR_NO_CONFIGURATION_TABLE,
+ INTERNAL_ERROR_NO_CPU_TABLE,
+ INTERNAL_ERROR_INVALID_WORKSPACE_ADDRESS,
+ INTERNAL_ERROR_TOO_LITTLE_WORKSPACE,
+ INTERNAL_ERROR_WORKSPACE_ALLOCATION,
+ INTERNAL_ERROR_INTERRUPT_STACK_TOO_SMALL,
+ INTERNAL_ERROR_THREAD_EXITTED,
+ INTERNAL_ERROR_INCONSISTENT_MP_INFORMATION,
+ INTERNAL_ERROR_INVALID_NODE,
+ INTERNAL_ERROR_NO_MPCI,
+ INTERNAL_ERROR_BAD_PACKET,
+ INTERNAL_ERROR_OUT_OF_PACKETS,
+ INTERNAL_ERROR_OUT_OF_GLOBAL_OBJECTS,
+ INTERNAL_ERROR_OUT_OF_PROXIES,
+ INTERNAL_ERROR_INVALID_GLOBAL_ID,
+ INTERNAL_ERROR_BAD_STACK_HOOK,
+ INTERNAL_ERROR_BAD_ATTRIBUTES
+} Internal_errors_Core_list;
+
+/*
+ * This type holds the fatal error information.
+ */
+
+typedef struct {
+ Internal_errors_Source the_source;
+ boolean is_internal;
+ uint32_t the_error;
+} Internal_errors_Information;
+
+/*
+ * When a fatal error occurs, the error information is stored here.
+ */
+
+SCORE_EXTERN Internal_errors_Information Internal_errors_What_happened;
+
+/*
+ * _Internal_error_Occurred
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked when the application or the executive itself
+ * determines that a fatal error has occurred.
+ */
+
+void volatile _Internal_error_Occurred(
+ Internal_errors_Source the_source,
+ boolean is_internal,
+ uint32_t the_error
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/include/rtems/score/isr.h b/cpukit/score/include/rtems/score/isr.h
new file mode 100644
index 0000000000..6064d1ed1e
--- /dev/null
+++ b/cpukit/score/include/rtems/score/isr.h
@@ -0,0 +1,248 @@
+/* isr.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the management of processor interrupt levels. This handler
+ * supports interrupt critical sections, vectoring of user interrupt
+ * handlers, nesting of interrupts, and manipulating interrupt levels.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ISR_h
+#define __ISR_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * The following type defines the control block used to manage
+ * the interrupt level portion of the status register.
+ */
+
+typedef uint32_t ISR_Level;
+
+/*
+ * The following type defines the type used to manage the vectors.
+ */
+
+typedef uint32_t ISR_Vector_number;
+
+/*
+ * Return type for ISR Handler
+ */
+
+typedef void ISR_Handler;
+
+/*
+ * Pointer to an ISR Handler
+ */
+
+#if (CPU_ISR_PASSES_FRAME_POINTER == 1)
+typedef ISR_Handler ( *ISR_Handler_entry )(
+ ISR_Vector_number,
+ CPU_Interrupt_frame *
+ );
+#else
+typedef ISR_Handler ( *ISR_Handler_entry )(
+ ISR_Vector_number
+ );
+#endif
+/*
+ * This constant promotes out the number of vectors truly supported by
+ * the current CPU being used. This is usually the number of distinct vectors
+ * the cpu can vector.
+ */
+
+#define ISR_NUMBER_OF_VECTORS CPU_INTERRUPT_NUMBER_OF_VECTORS
+
+/*
+ * This constant promotes out the highest valid interrupt vector number.
+ */
+
+#define ISR_INTERRUPT_MAXIMUM_VECTOR_NUMBER CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER
+
+/*
+ * The following is TRUE if signals have been sent to the currently
+ * executing thread by an ISR handler.
+ */
+
+SCORE_EXTERN boolean _ISR_Signals_to_thread_executing;
+
+/*
+ * The following contains the interrupt service routine nest level.
+ * When this variable is zero, a thread is executing.
+ */
+
+SCORE_EXTERN volatile uint32_t _ISR_Nest_level;
+
+/*
+ * The following declares the Vector Table. Application
+ * interrupt service routines are vectored by the ISR Handler via this table.
+ */
+
+SCORE_EXTERN ISR_Handler_entry *_ISR_Vector_table;
+
+/*
+ * _ISR_Handler_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this handler.
+ */
+
+void _ISR_Handler_initialization ( void );
+
+/*
+ * _ISR_Disable
+ *
+ * DESCRIPTION:
+ *
+ * This routine disables all interrupts so that a critical section
+ * of code can be executing without being interrupted. Upon return,
+ * the argument _level will contain the previous interrupt mask level.
+ */
+
+#define _ISR_Disable( _level ) \
+ _CPU_ISR_Disable( _level )
+
+/*
+ * _ISR_Enable
+ *
+ * DESCRIPTION:
+ *
+ * This routine enables interrupts to the previous interrupt mask
+ * LEVEL. It is used at the end of a critical section of code to
+ * enable interrupts so they can be processed again.
+ */
+
+#define _ISR_Enable( _level ) \
+ _CPU_ISR_Enable( _level )
+
+/*
+ * _ISR_Flash
+ *
+ * DESCRIPTION:
+ *
+ * This routine temporarily enables interrupts to the previous
+ * interrupt mask level and then disables all interrupts so that
+ * the caller can continue into the second part of a critical
+ * section. This routine is used to temporarily enable interrupts
+ * during a long critical section. It is used in long sections of
+ * critical code when a point is reached at which interrupts can
+ * be temporarily enabled. Deciding where to flash interrupts
+ * in a long critical section is often difficult and the point
+ * must be selected with care to insure that the critical section
+ * properly protects itself.
+ */
+
+#define _ISR_Flash( _level ) \
+ _CPU_ISR_Flash( _level )
+
+/*
+ * _ISR_Install_vector
+ *
+ * DESCRIPTION:
+ *
+ * This routine installs new_handler as the interrupt service routine
+ * for the specified vector. The previous interrupt service routine is
+ * returned as old_handler.
+ */
+
+#define _ISR_Install_vector( _vector, _new_handler, _old_handler ) \
+ _CPU_ISR_install_vector( _vector, _new_handler, _old_handler )
+
+/*
+ * _ISR_Get_level
+ *
+ * DESCRIPTION:
+ *
+ * This routine returns the current interrupt level.
+ */
+
+#define _ISR_Get_level() \
+ _CPU_ISR_Get_level()
+
+/*
+ * _ISR_Set_level
+ *
+ * DESCRIPTION:
+ *
+ * This routine sets the current interrupt level to that specified
+ * by new_level. The new interrupt level is effective when the
+ * routine exits.
+ */
+
+#define _ISR_Set_level( _new_level ) \
+ _CPU_ISR_Set_level( _new_level )
+
+/*
+ * _ISR_Handler
+ *
+ * DESCRIPTION:
+ *
+ * This routine is the interrupt dispatcher. ALL interrupts
+ * are vectored to this routine so that minimal context can be saved
+ * and setup performed before the application's high-level language
+ * interrupt service routine is invoked. After the application's
+ * interrupt service routine returns control to this routine, it
+ * will determine if a thread dispatch is necessary. If so, it will
+ * insure that the necessary thread scheduling operations are
+ * performed when the outermost interrupt service routine exits.
+ *
+ * NOTE: Implemented in assembly language.
+ */
+
+void _ISR_Handler( void );
+
+/*
+ * _ISR_Dispatch
+ *
+ * DESCRIPTION:
+ *
+ * This routine provides a wrapper so that the routine
+ * _Thread_Dispatch can be invoked when a reschedule is necessary
+ * at the end of the outermost interrupt service routine. This
+ * wrapper is necessary to establish the processor context needed
+ * by _Thread_Dispatch and to save the processor context which is
+ * corrupted by _Thread_Dispatch. This context typically consists
+ * of registers which are not preserved across routine invocations.
+ *
+ * NOTE: Implemented in assembly language.
+ */
+
+void _ISR_Dispatch( void );
+
+/*PAGE
+ *
+ * _ISR_Is_in_progress
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the processor is currently servicing
+ * and interrupt and FALSE otherwise. A return value of TRUE indicates
+ * that the caller is an interrupt service routine, NOT a thread. The
+ */
+
+#if (CPU_PROVIDES_ISR_IS_IN_PROGRESS == TRUE)
+boolean _ISR_Is_in_progress( void );
+#else
+#define _ISR_Is_in_progress() \
+ (_ISR_Nest_level != 0)
+#endif
+
+#include <rtems/score/isr.inl>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/include/rtems/score/mpci.h b/cpukit/score/include/rtems/score/mpci.h
new file mode 100644
index 0000000000..118e31afaa
--- /dev/null
+++ b/cpukit/score/include/rtems/score/mpci.h
@@ -0,0 +1,411 @@
+/* mpci.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the MPCI layer. It provides mechanisms to utilize packets.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __MPCI_h
+#define __MPCI_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/mppkt.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/score/coresem.h>
+
+/*
+ * The following constants define the stack size requirements for
+ * the system threads.
+ */
+
+#define MPCI_RECEIVE_SERVER_STACK_SIZE \
+ ( STACK_MINIMUM_SIZE + \
+ CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK + \
+ _CPU_Table.extra_mpci_receive_server_stack \
+ )
+
+/*
+ * The following defines the node number used when a broadcast is desired.
+ */
+
+#define MPCI_ALL_NODES 0
+
+/*
+ * For packets associated with requests that don't already have a timeout,
+ * use the one specified by this MPCI driver. The value specified by
+ * the MPCI driver sets an upper limit on how long a remote request
+ * should take to complete.
+ */
+
+#define MPCI_DEFAULT_TIMEOUT 0xFFFFFFFF
+
+/*
+ * The following records define the Multiprocessor Communications
+ * Interface (MPCI) Table. This table defines the user-provided
+ * MPCI which is a required part of a multiprocessor system.
+ *
+ * For non-blocking local operations that become remote operations,
+ * we need a timeout. This is a per-driver timeout: default_timeout
+ */
+
+typedef void MPCI_Entry;
+
+typedef MPCI_Entry ( *MPCI_initialization_entry )( void );
+
+typedef MPCI_Entry ( *MPCI_get_packet_entry )(
+ MP_packet_Prefix **
+ );
+
+typedef MPCI_Entry ( *MPCI_return_packet_entry )(
+ MP_packet_Prefix *
+ );
+
+typedef MPCI_Entry ( *MPCI_send_entry )(
+ uint32_t ,
+ MP_packet_Prefix *
+ );
+
+typedef MPCI_Entry ( *MPCI_receive_entry )(
+ MP_packet_Prefix **
+ );
+
+typedef struct {
+ uint32_t default_timeout; /* in ticks */
+ uint32_t maximum_packet_size;
+ MPCI_initialization_entry initialization;
+ MPCI_get_packet_entry get_packet;
+ MPCI_return_packet_entry return_packet;
+ MPCI_send_entry send_packet;
+ MPCI_receive_entry receive_packet;
+} MPCI_Control;
+
+/*
+ * The following defines the type for packet processing routines
+ * invoked by the MPCI Receive server.
+ */
+
+typedef void (*MPCI_Packet_processor)( MP_packet_Prefix * );
+
+/*
+ * The following enumerated type defines the list of
+ * internal MP operations.
+ */
+
+typedef enum {
+ MPCI_PACKETS_SYSTEM_VERIFY = 0
+} MPCI_Internal_Remote_operations;
+
+/*
+ * The following data structure defines the packet used to perform
+ * remote event operations.
+ */
+
+typedef struct {
+ MP_packet_Prefix Prefix;
+ MPCI_Internal_Remote_operations operation;
+ uint32_t maximum_nodes;
+ uint32_t maximum_global_objects;
+} MPCI_Internal_packet;
+
+/*
+ * This is the core semaphore which the MPCI Receive Server blocks on.
+ */
+
+SCORE_EXTERN CORE_semaphore_Control _MPCI_Semaphore;
+/*
+ * The following thread queue is used to maintain a list of tasks
+ * which currently have outstanding remote requests.
+ */
+
+SCORE_EXTERN Thread_queue_Control _MPCI_Remote_blocked_threads;
+
+/*
+ * The following define the internal pointers to the user's
+ * configuration information.
+ */
+
+SCORE_EXTERN MPCI_Control *_MPCI_table;
+
+/*
+ * The following points to the MPCI Receive Server.
+ */
+
+SCORE_EXTERN Thread_Control *_MPCI_Receive_server_tcb;
+
+/*
+ * The following table contains the process packet routines provided
+ * by each object that supports MP operations.
+ */
+
+SCORE_EXTERN MPCI_Packet_processor
+ _MPCI_Packet_processors[MP_PACKET_CLASSES_LAST+1];
+
+/*
+ * _MPCI_Handler_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this handler.
+ */
+
+void _MPCI_Handler_initialization(
+ MPCI_Control *users_mpci_table,
+ uint32_t timeout_status
+);
+
+/*
+ * _MPCI_Create_server
+ *
+ * DESCRIPTION:
+ *
+ * This routine creates the packet receive server used in MP systems.
+ */
+
+void _MPCI_Create_server( void );
+
+/*
+ * _MPCI_Initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine initializes the MPCI driver by
+ * invoking the user provided MPCI initialization callout.
+ */
+
+void _MPCI_Initialization ( void );
+
+/*
+ * _MPCI_Register_packet_processor
+ *
+ * DESCRIPTION:
+ *
+ * This routine registers the MPCI packet processor for the
+ * designated object class.
+ */
+
+void _MPCI_Register_packet_processor(
+ MP_packet_Classes the_class,
+ MPCI_Packet_processor the_packet_processor
+
+);
+
+/*
+ * _MPCI_Get_packet
+ *
+ * DESCRIPTION:
+ *
+ * This function obtains a packet by invoking the user provided
+ * MPCI get packet callout.
+ */
+
+MP_packet_Prefix *_MPCI_Get_packet ( void );
+
+/*
+ * _MPCI_Return_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine returns a packet by invoking the user provided
+ * MPCI return packet callout.
+ */
+
+void _MPCI_Return_packet (
+ MP_packet_Prefix *the_packet
+);
+
+/*
+ * _MPCI_Send_process_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine sends a process packet by invoking the user provided
+ * MPCI send callout.
+ */
+
+void _MPCI_Send_process_packet (
+ uint32_t destination,
+ MP_packet_Prefix *the_packet
+);
+
+/*
+ * _MPCI_Send_request_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine sends a request packet by invoking the user provided
+ * MPCI send callout.
+ */
+
+uint32_t _MPCI_Send_request_packet (
+ uint32_t destination,
+ MP_packet_Prefix *the_packet,
+ States_Control extra_state
+);
+
+/*
+ * _MPCI_Send_response_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine sends a response packet by invoking the user provided
+ * MPCI send callout.
+ */
+
+void _MPCI_Send_response_packet (
+ uint32_t destination,
+ MP_packet_Prefix *the_packet
+);
+
+/*
+ * _MPCI_Receive_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine receives a packet by invoking the user provided
+ * MPCI receive callout.
+ */
+
+MP_packet_Prefix *_MPCI_Receive_packet ( void );
+
+/*
+ * _MPCI_Process_response
+ *
+ * DESCRIPTION:
+ *
+ * This routine obtains a packet by invoking the user provided
+ * MPCI get packet callout.
+ */
+
+Thread_Control *_MPCI_Process_response (
+ MP_packet_Prefix *the_packet
+);
+
+/*PAGE
+ *
+ * _MPCI_Receive_server
+ *
+ */
+
+Thread _MPCI_Receive_server(
+ uint32_t ignored
+);
+
+/*PAGE
+ *
+ * _MPCI_Announce
+ *
+ * DESCRIPTION:
+ *
+ * XXX
+ */
+
+void _MPCI_Announce ( void );
+
+/*
+ * _MPCI_Internal_packets_Send_process_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * process operation can be performed on another node.
+ */
+
+void _MPCI_Internal_packets_Send_process_packet (
+ MPCI_Internal_Remote_operations operation
+);
+
+/*
+ * _MPCI_Internal_packets_Send_request_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * directive operation can be initiated on another node.
+ *
+ * This routine is not needed since there are no request
+ * packets to be sent by this manager.
+ */
+
+/*
+ * _MPCI_Internal_packets_Send_response_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs a remote procedure call so that a
+ * directive can be performed on another node.
+ *
+ * This routine is not needed since there are no response
+ * packets to be sent by this manager.
+ */
+
+/*
+ *
+ * _MPCI_Internal_packets_Process_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the actions specific to this package for
+ * the request from another node.
+ */
+
+void _MPCI_Internal_packets_Process_packet (
+ MP_packet_Prefix *the_packet_prefix
+);
+
+/*
+ * _MPCI_Internal_packets_Send_object_was_deleted
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked indirectly by the thread queue
+ * when a proxy has been removed from the thread queue and
+ * the remote node must be informed of this.
+ *
+ * This routine is not needed since there are no objects
+ * deleted by this manager.
+ */
+
+/*
+ * _MPCI_Internal_packets_Send_extract_proxy
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked when a task is deleted and it
+ * has a proxy which must be removed from a thread queue and
+ * the remote node must be informed of this.
+ *
+ * This routine is not needed since there are no objects
+ * deleted by this manager.
+ */
+
+/*
+ * _MPCI_Internal_packets_Get_packet
+ *
+ * DESCRIPTION:
+ *
+ * This routine is used to obtain a internal threads mp packet.
+ */
+
+ MPCI_Internal_packet *_MPCI_Internal_packets_Get_packet ( void );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/include/rtems/score/mppkt.h b/cpukit/score/include/rtems/score/mppkt.h
new file mode 100644
index 0000000000..b4cff19342
--- /dev/null
+++ b/cpukit/score/include/rtems/score/mppkt.h
@@ -0,0 +1,100 @@
+/* mppkt.h
+ *
+ * This package is the specification for the Packet Handler.
+ * This handler defines the basic packet and provides
+ * mechanisms to utilize packets based on this prefix.
+ * Packets are the fundamental basis for messages passed between
+ * nodes in an MP system.
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __MP_PACKET_h
+#define __MP_PACKET_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/watchdog.h>
+
+/*
+ * The following enumerated type defines the packet classes.
+ *
+ * NOTE: In general, each class corresponds to a manager
+ * which supports global operations. Each manager
+ * defines the set of supported operations.
+ */
+
+typedef enum {
+ MP_PACKET_MPCI_INTERNAL = 0,
+ MP_PACKET_TASKS = 1,
+ MP_PACKET_MESSAGE_QUEUE = 2,
+ MP_PACKET_SEMAPHORE = 3,
+ MP_PACKET_PARTITION = 4,
+ MP_PACKET_REGION = 5,
+ MP_PACKET_EVENT = 6,
+ MP_PACKET_SIGNAL = 7
+} MP_packet_Classes;
+
+#define MP_PACKET_CLASSES_FIRST MP_PACKET_MPCI_INTERNAL
+#define MP_PACKET_CLASSES_LAST MP_PACKET_SIGNAL
+
+/*
+ * The following record contains the prefix for every packet
+ * passed between nodes in an MP system.
+ *
+ * NOTE: This structure is padded to insure that anything
+ * following it is on a 16 byte boundary. This is
+ * the most stringent structure alignment rule
+ * encountered yet (i960CA).
+ */
+
+typedef struct {
+ MP_packet_Classes the_class;
+ Objects_Id id;
+ Objects_Id source_tid;
+ Priority_Control source_priority;
+ uint32_t return_code;
+ uint32_t length;
+ uint32_t to_convert;
+ Watchdog_Interval timeout;
+} MP_packet_Prefix;
+
+/*
+ * An MPCI must support packets of at least this size.
+ */
+
+#define MP_PACKET_MINIMUM_PACKET_SIZE 64
+
+/*
+ * The following constant defines the number of uint32_t 's
+ * in a packet which must be converted to native format in a
+ * heterogeneous system. In packets longer than
+ * MP_PACKET_MINIMUN_HETERO_CONVERSION uint32_t 's, some of the "extra" data
+ * may a user message buffer which is not automatically endian swapped.
+ */
+
+#define MP_PACKET_MINIMUN_HETERO_CONVERSION \
+ ( sizeof( MP_packet_Prefix ) / sizeof( uint32_t ) )
+
+#ifndef __RTEMS_APPLICATION__
+#include <rtems/score/mppkt.inl>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/include/rtems/score/object.h b/cpukit/score/include/rtems/score/object.h
new file mode 100644
index 0000000000..71c9e190db
--- /dev/null
+++ b/cpukit/score/include/rtems/score/object.h
@@ -0,0 +1,570 @@
+/* object.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the Object Handler. This Handler provides mechanisms which
+ * can be used to initialize and manipulate all objects which have
+ * ids.
+ *
+ * COPYRIGHT (c) 1989-2002.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __OBJECTS_h
+#define __OBJECTS_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+
+/*
+ * Mask to enable unlimited objects. This is used in the configuration
+ * table when specifying the number of configured objects.
+ */
+
+#define OBJECTS_UNLIMITED_OBJECTS 0x80000000
+
+/*
+ * The following type defines the control block used to manage
+ * object names.
+ */
+
+typedef void * Objects_Name;
+
+/*
+ * Space for object names is allocated in multiples of this.
+ *
+ * NOTE: Must be a power of 2. Matches the name manipulation routines.
+ */
+
+#define OBJECTS_NAME_ALIGNMENT sizeof( uint32_t )
+
+/*
+ * Functions which compare names are prototyped like this.
+ */
+
+typedef boolean (*Objects_Name_comparators)(
+ void * /* name_1 */,
+ void * /* name_2 */,
+ uint32_t /* length */
+);
+
+/*
+ * The following type defines the control block used to manage
+ * object IDs. The format is as follows (0=LSB):
+ *
+ * Bits 0 .. 15 = index (up to 65535 objects of a type)
+ * Bits 16 .. 23 = node (up to 255 nodes)
+ * Bits 24 .. 26 = API (up to 7 API classes)
+ * Bits 27 .. 31 = class (up to 31 object types per API)
+ */
+
+typedef uint32_t Objects_Id;
+
+#define OBJECTS_INDEX_START_BIT 0
+#define OBJECTS_NODE_START_BIT 16
+#define OBJECTS_API_START_BIT 24
+#define OBJECTS_CLASS_START_BIT 27
+
+#define OBJECTS_INDEX_MASK (Objects_Id)0x0000ffff
+#define OBJECTS_NODE_MASK (Objects_Id)0x00ff0000
+#define OBJECTS_API_MASK (Objects_Id)0x07000000
+#define OBJECTS_CLASS_MASK (Objects_Id)0xf8000000
+
+#define OBJECTS_INDEX_VALID_BITS (Objects_Id)0x0000ffff
+#define OBJECTS_NODE_VALID_BITS (Objects_Id)0x000000ff
+#define OBJECTS_API_VALID_BITS (Objects_Id)0x00000007
+#define OBJECTS_CLASS_VALID_BITS (Objects_Id)0x0000001f
+
+/*
+ * This enumerated type is used in the class field of the object ID.
+ */
+
+#define OBJECTS_NO_CLASS 0
+
+typedef enum {
+ OBJECTS_NO_API = 0,
+ OBJECTS_INTERNAL_API = 1,
+ OBJECTS_CLASSIC_API = 2,
+ OBJECTS_POSIX_API = 3,
+ OBJECTS_ITRON_API = 4
+} Objects_APIs;
+
+#define OBJECTS_APIS_LAST OBJECTS_ITRON_API
+
+typedef enum {
+ OBJECTS_INTERNAL_NO_CLASS = 0,
+ OBJECTS_INTERNAL_THREADS = 1,
+ OBJECTS_INTERNAL_MUTEXES = 2
+} Objects_Internal_API;
+
+#define OBJECTS_INTERNAL_CLASSES_LAST OBJECTS_INTERNAL_MUTEXES
+
+typedef enum {
+ OBJECTS_CLASSIC_NO_CLASS = 0,
+ OBJECTS_RTEMS_TASKS = 1,
+ OBJECTS_RTEMS_TIMERS = 2,
+ OBJECTS_RTEMS_SEMAPHORES = 3,
+ OBJECTS_RTEMS_MESSAGE_QUEUES = 4,
+ OBJECTS_RTEMS_PARTITIONS = 5,
+ OBJECTS_RTEMS_REGIONS = 6,
+ OBJECTS_RTEMS_PORTS = 7,
+ OBJECTS_RTEMS_PERIODS = 8,
+ OBJECTS_RTEMS_EXTENSIONS = 9
+} Objects_Classic_API;
+
+#define OBJECTS_RTEMS_CLASSES_LAST OBJECTS_RTEMS_EXTENSIONS
+
+typedef enum {
+ OBJECTS_POSIX_NO_CLASS = 0,
+ OBJECTS_POSIX_THREADS = 1,
+ OBJECTS_POSIX_KEYS = 2,
+ OBJECTS_POSIX_INTERRUPTS = 3,
+ OBJECTS_POSIX_MESSAGE_QUEUE_FDS = 4,
+ OBJECTS_POSIX_MESSAGE_QUEUES = 5,
+ OBJECTS_POSIX_MUTEXES = 6,
+ OBJECTS_POSIX_SEMAPHORES = 7,
+ OBJECTS_POSIX_CONDITION_VARIABLES = 8
+} Objects_POSIX_API;
+
+#define OBJECTS_POSIX_CLASSES_LAST OBJECTS_POSIX_CONDITION_VARIABLES
+
+typedef enum {
+ OBJECTS_ITRON_NO_CLASS = 0,
+ OBJECTS_ITRON_TASKS = 1,
+ OBJECTS_ITRON_EVENTFLAGS = 2,
+ OBJECTS_ITRON_MAILBOXES = 3,
+ OBJECTS_ITRON_MESSAGE_BUFFERS = 4,
+ OBJECTS_ITRON_PORTS = 5,
+ OBJECTS_ITRON_SEMAPHORES = 6,
+ OBJECTS_ITRON_VARIABLE_MEMORY_POOLS = 7,
+ OBJECTS_ITRON_FIXED_MEMORY_POOLS = 8
+} Objects_ITRON_API;
+
+#define OBJECTS_ITRON_CLASSES_LAST OBJECTS_ITRON_FIXED_MEMORY_POOLS
+
+/*
+ * This enumerated type lists the locations which may be returned
+ * by _Objects_Get. These codes indicate the success of locating
+ * an object with the specified ID.
+ */
+
+typedef enum {
+ OBJECTS_LOCAL = 0, /* object is local */
+ OBJECTS_REMOTE = 1, /* object is remote */
+ OBJECTS_ERROR = 2 /* id was invalid */
+} Objects_Locations;
+
+/*
+ * The following type defines the callout used when a local task
+ * is extracted from a remote thread queue (i.e. it's proxy must
+ * extracted from the remote queue).
+ */
+
+typedef void ( *Objects_Thread_queue_Extract_callout )( void * );
+
+
+/*
+ * The following defines the Object Control Block used to manage
+ * each object local to this node.
+ */
+
+typedef struct {
+ Chain_Node Node;
+ Objects_Id id;
+ Objects_Name name;
+} Objects_Control;
+
+/*
+ * The following defines the structure for the information used to
+ * manage each class of objects.
+ */
+
+typedef struct {
+ Objects_APIs the_api; /* API of this object */
+ uint32_t the_class; /* class of this object */
+ Objects_Id minimum_id; /* minimum valid id of this type */
+ Objects_Id maximum_id; /* maximum valid id of this type */
+ uint32_t maximum; /* maximum number of objects */
+ boolean auto_extend; /* TRUE if unlimited objects */
+ uint32_t allocation_size; /* number of objects in a block */
+ uint32_t size; /* size of the objects */
+ Objects_Control **local_table;
+ Objects_Name *name_table;
+ Chain_Control Inactive; /* chain of inactive ctl blocks */
+ uint32_t inactive; /* number of objects on the InActive list */
+ uint32_t *inactive_per_block; /* used to release a block */
+ void **object_blocks; /* the object memory to remove */
+ boolean is_string; /* TRUE if names are strings */
+ uint32_t name_length; /* maximum length of names */
+ Objects_Thread_queue_Extract_callout *extract;
+#if defined(RTEMS_MULTIPROCESSING)
+ Chain_Control *global_table; /* pointer to global table */
+#endif
+} Objects_Information;
+
+/*
+ * The following defines the data storage which contains the
+ * node number of the local node.
+ */
+
+SCORE_EXTERN uint32_t _Objects_Local_node;
+SCORE_EXTERN uint32_t _Objects_Maximum_nodes;
+
+/*
+ * The following is the list of information blocks per API for each object
+ * class. From the ID, we can go to one of these information blocks,
+ * and obtain a pointer to the appropriate object control block.
+ */
+
+SCORE_EXTERN Objects_Information
+ **_Objects_Information_table[OBJECTS_APIS_LAST + 1];
+
+/*
+ * The following defines the constant which may be used
+ * with _Objects_Get to manipulate the calling task.
+ *
+ */
+
+#define OBJECTS_ID_OF_SELF ((Objects_Id) 0)
+
+/*
+ * The following define the constants which may be used in name searches.
+ */
+
+#define OBJECTS_SEARCH_ALL_NODES 0
+#define OBJECTS_SEARCH_OTHER_NODES 0x7FFFFFFE
+#define OBJECTS_SEARCH_LOCAL_NODE 0x7FFFFFFF
+#define OBJECTS_WHO_AM_I 0
+
+/*
+ * Parameters and return id's for _Objects_Get_next
+ */
+
+#define OBJECTS_ID_INITIAL_INDEX (0)
+#define OBJECTS_ID_FINAL_INDEX (0xffff)
+
+#define OBJECTS_ID_INITIAL(_api, _class, _node) \
+ _Objects_Build_id( (_api), (_class), (_node), OBJECTS_ID_INITIAL_INDEX )
+
+#define OBJECTS_ID_FINAL ((Objects_Id)~0)
+
+/*
+ * _Objects_Handler_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This function performs the initialization necessary for this handler.
+ *
+ */
+
+void _Objects_Handler_initialization(
+ uint32_t node,
+ uint32_t maximum_nodes,
+ uint32_t maximum_global_objects
+);
+
+/*
+ * _Objects_Extend_information
+ *
+ * DESCRIPTION:
+ *
+ * This function extends an object class information record.
+ */
+
+void _Objects_Extend_information(
+ Objects_Information *information
+);
+
+/*
+ * _Objects_Shrink_information
+ *
+ * DESCRIPTION:
+ *
+ * This function shrink an object class information record.
+ */
+
+void _Objects_Shrink_information(
+ Objects_Information *information
+);
+
+/*
+ * _Objects_Initialize_information
+ *
+ * DESCRIPTION:
+ *
+ * This function initializes an object class information record.
+ * SUPPORTS_GLOBAL is TRUE if the object class supports global
+ * objects, and FALSE otherwise. Maximum indicates the number
+ * of objects required in this class and size indicates the size
+ * in bytes of each control block for this object class. The
+ * name length and string designator are also set. In addition,
+ * the class may be a task, therefore this information is also included.
+ */
+
+void _Objects_Initialize_information (
+ Objects_Information *information,
+ Objects_APIs the_api,
+ uint32_t the_class,
+ uint32_t maximum,
+ uint32_t size,
+ boolean is_string,
+ uint32_t maximum_name_length
+#if defined(RTEMS_MULTIPROCESSING)
+ ,
+ boolean supports_global,
+ Objects_Thread_queue_Extract_callout *extract
+#endif
+);
+
+/*PAGE
+ *
+ * _Objects_Allocate
+ *
+ * DESCRIPTION:
+ *
+ * This function allocates a object control block from
+ * the inactive chain of free object control blocks.
+ */
+
+Objects_Control *_Objects_Allocate(
+ Objects_Information *information
+);
+
+/*
+ * _Objects_Allocate_by_index
+ *
+ * DESCRIPTION:
+ *
+ * This function allocates the object control block
+ * specified by the index from the inactive chain of
+ * free object control blocks.
+ */
+
+Objects_Control *_Objects_Allocate_by_index(
+ Objects_Information *information,
+ uint32_t index,
+ uint32_t sizeof_control
+);
+
+/*PAGE
+ *
+ * _Objects_Free
+ *
+ * DESCRIPTION:
+ *
+ * This function frees a object control block to the
+ * inactive chain of free object control blocks.
+ */
+
+void _Objects_Free(
+ Objects_Information *information,
+ Objects_Control *the_object
+);
+
+/*
+ * _Objects_Clear_name
+ *
+ * DESCRIPTION:
+ *
+ * This method zeroes out the name.
+ */
+
+void _Objects_Clear_name(
+ void *name,
+ uint32_t length
+);
+
+/*
+ * _Objects_Copy_name_string
+ *
+ * DESCRIPTION:
+ *
+ * This method copies a string style object name from source to destination.
+ */
+
+void _Objects_Copy_name_string(
+ void *source,
+ void *destination
+);
+
+/*
+ * _Objects_Copy_name_raw
+ *
+ * DESCRIPTION:
+ *
+ * This method copies a raw style object name from source to destination.
+ */
+
+void _Objects_Copy_name_raw(
+ void *source,
+ void *destination,
+ uint32_t length
+);
+
+/*
+ * _Objects_Compare_name_string
+ *
+ * DESCRIPTION:
+ *
+ * This method compares two string style object names.
+ */
+
+boolean _Objects_Compare_name_string(
+ void *name_1,
+ void *name_2,
+ uint32_t length
+);
+
+/*
+ * _Objects_Compare_name_raw
+ *
+ * DESCRIPTION:
+ *
+ * This method compares two raw style object names.
+ */
+
+boolean _Objects_Compare_name_raw(
+ void *name_1,
+ void *name_2,
+ uint32_t length
+);
+
+/*
+ * _Objects_Name_to_id
+ *
+ * DESCRIPTION:
+ *
+ * This function implements the common portion of the object
+ * identification directives. This directive returns the object
+ * id associated with name. If more than one object of this class
+ * is named name, then the object to which the id belongs is
+ * arbitrary. Node indicates the extent of the search for the
+ * id of the object named name. If the object class supports global
+ * objects, then the search can be limited to a particular node
+ * or allowed to encompass all nodes.
+ *
+ */
+
+typedef enum {
+ OBJECTS_NAME_OR_ID_LOOKUP_SUCCESSFUL,
+ OBJECTS_INVALID_NAME,
+ OBJECTS_INVALID_ADDRESS,
+ OBJECTS_INVALID_ID,
+ OBJECTS_INVALID_NODE
+} Objects_Name_or_id_lookup_errors;
+
+#define OBJECTS_NAME_ERRORS_FIRST OBJECTS_NAME_OR_ID_LOOKUP_SUCCESSFUL
+#define OBJECTS_NAME_ERRORS_LAST OBJECTS_INVALID_NODE
+
+Objects_Name_or_id_lookup_errors _Objects_Name_to_id(
+ Objects_Information *information,
+ Objects_Name name,
+ uint32_t node,
+ Objects_Id *id
+);
+
+/*
+ * _Objects_Id_to_Name
+ *
+ * DESCRIPTION:
+ *
+ * This function implements the common portion of the object Id
+ * to name directives. This function returns the name
+ * associated with object id.
+ *
+ * NOTE:
+ *
+ * This function currently does not support string names.
+ */
+
+Objects_Name_or_id_lookup_errors _Objects_Id_to_name (
+ Objects_Id id,
+ Objects_Name *name
+);
+
+/*
+ * _Objects_Get
+ *
+ * DESCRIPTION:
+ *
+ * This function maps object ids to object control blocks.
+ * If id corresponds to a local object, then it returns
+ * the_object control pointer which maps to id and location
+ * is set to OBJECTS_LOCAL. If the object class supports global
+ * objects and the object id is global and resides on a remote
+ * node, then location is set to OBJECTS_REMOTE, and the_object
+ * is undefined. Otherwise, location is set to OBJECTS_ERROR
+ * and the_object is undefined.
+ *
+ * NOTE: _Objects_Get returns with dispatching disabled for
+ * local and remote objects.
+ * _Objects_Get_isr_disable returns with dispatching
+ * disabled for remote objects and interrupts for local
+ * objects.
+ */
+
+Objects_Control *_Objects_Get (
+ Objects_Information *information,
+ Objects_Id id,
+ Objects_Locations *location
+);
+
+Objects_Control *_Objects_Get_isr_disable(
+ Objects_Information *information,
+ Objects_Id id,
+ Objects_Locations *location,
+ ISR_Level *level
+);
+
+Objects_Control *_Objects_Get_by_index (
+ Objects_Information *information,
+ Objects_Id id,
+ Objects_Locations *location
+);
+
+Objects_Control *_Objects_Get_no_protection(
+ Objects_Information *information,
+ Objects_Id id,
+ Objects_Locations *location
+);
+
+/*
+ * _Objects_Get_next
+ *
+ * DESCRIPTION:
+ *
+ * Like _Objects_Get, but is used to find "next" open object.
+ *
+ */
+
+Objects_Control *_Objects_Get_next(
+ Objects_Information *information,
+ Objects_Id id,
+ Objects_Locations *location_p,
+ Objects_Id *next_id_p
+);
+
+/*
+ * Pieces of object.inl are promoted out to the user
+ */
+
+#include <rtems/score/object.inl>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/objectmp.h>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/include/rtems/score/objectmp.h b/cpukit/score/include/rtems/score/objectmp.h
new file mode 100644
index 0000000000..947b03c59d
--- /dev/null
+++ b/cpukit/score/include/rtems/score/objectmp.h
@@ -0,0 +1,151 @@
+/* objectmp.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the manipulation of Global RTEMS Objects.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_OBJECTS_MP_h
+#define __RTEMS_OBJECTS_MP_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This defines the Global Object Control Block used to manage
+ * objects resident on other nodes.
+ */
+
+typedef struct {
+ Objects_Control Object;
+ uint32_t name; /* XXX broken but works */
+ /* XXX If any API is MP with variable length names .. BOOM!!!! */
+} Objects_MP_Control;
+
+/*
+ * _Objects_MP_Handler_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine intializes the inactive global object chain
+ * based on the maximum number of global objects configured.
+ */
+
+void _Objects_MP_Handler_initialization (
+ uint32_t node,
+ uint32_t maximum_nodes,
+ uint32_t maximum_global_objects
+);
+
+/*PAGE
+ *
+ * _Objects_MP_Open
+ *
+ * DESCRIPTION:
+ *
+ * This routine place the specified global object in the
+ * specified information table.
+ */
+
+void _Objects_MP_Open (
+ Objects_Information *information,
+ Objects_MP_Control *the_global_object,
+ uint32_t the_name, /* XXX -- wrong for variable */
+ Objects_Id the_id
+);
+
+/*
+ * _Objects_MP_Allocate_and_open
+ *
+ * DESCRIPTION:
+ *
+ * This routine allocates a global object control block
+ * and places it in the specified information table. If the
+ * allocation fails, then is_fatal_error determines the
+ * error processing actions taken.
+ */
+
+boolean _Objects_MP_Allocate_and_open (
+ Objects_Information *information,
+ uint32_t the_name, /* XXX -- wrong for variable length */
+ Objects_Id the_id,
+ boolean is_fatal_error
+);
+
+/*
+ * _Objects_MP_Close
+ *
+ * DESCRIPTION:
+ *
+ * This routine removes a global object from the specified
+ * information table and deallocates the global object control block.
+ */
+
+void _Objects_MP_Close (
+ Objects_Information *information,
+ Objects_Id the_id
+);
+
+/*
+ * _Objects_MP_Global_name_search
+ *
+ * DESCRIPTION:
+ *
+ * This routine looks for the object with the_name in the global
+ * object tables indicated by information. It returns the ID of the
+ * object with that name if one is found.
+ */
+
+Objects_Name_or_id_lookup_errors _Objects_MP_Global_name_search (
+ Objects_Information *information,
+ Objects_Name the_name,
+ uint32_t nodes_to_search,
+ Objects_Id *the_id
+);
+
+/*
+ * _Objects_MP_Is_remote
+ *
+ * DESCRIPTION:
+ *
+ * This function searches the Global Object Table managed
+ * by information for the object indicated by ID. If the object
+ * is found, then location is set to objects_remote, otherwise
+ * location is set to objects_error. In both cases, the_object
+ * is undefined.
+ */
+
+void _Objects_MP_Is_remote (
+ Objects_Information *information,
+ Objects_Id the_id,
+ Objects_Locations *location,
+ Objects_Control **the_object
+);
+
+/*
+ * The following chain header is used to manage the set of
+ * inactive global object control blocks.
+ */
+
+SCORE_EXTERN uint32_t _Objects_MP_Maximum_global_objects;
+SCORE_EXTERN Chain_Control _Objects_MP_Inactive_global_objects;
+
+#ifndef __RTEMS_APPLICATION__
+#include <rtems/score/objectmp.inl>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/include/rtems/score/priority.h b/cpukit/score/include/rtems/score/priority.h
new file mode 100644
index 0000000000..3c8454f203
--- /dev/null
+++ b/cpukit/score/include/rtems/score/priority.h
@@ -0,0 +1,96 @@
+/* priority.h
+ *
+ * This include file contains all thread priority manipulation routines.
+ * This Handler provides mechanisms which can be used to
+ * initialize and manipulate thread priorities.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __PRIORITY_h
+#define __PRIORITY_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * The following type defines the control block used to manage
+ * thread priorities.
+ *
+ * NOTE: Priority 0 is reserved for internal threads only.
+ */
+
+typedef uint32_t Priority_Control;
+
+#define PRIORITY_MINIMUM 0 /* highest thread priority */
+#define PRIORITY_MAXIMUM 255 /* lowest thread priority */
+
+/*
+ * The following record defines the information associated with
+ * each thread to manage its interaction with the priority bit maps.
+ */
+
+typedef struct {
+ Priority_Bit_map_control *minor; /* addr of minor bit map slot */
+ Priority_Bit_map_control ready_major; /* priority bit map ready mask */
+ Priority_Bit_map_control ready_minor; /* priority bit map ready mask */
+ Priority_Bit_map_control block_major; /* priority bit map block mask */
+ Priority_Bit_map_control block_minor; /* priority bit map block mask */
+} Priority_Information;
+
+/*
+ * The following data items are the priority bit map.
+ * Each of the sixteen bits used in the _Priority_Major_bit_map is
+ * associated with one of the sixteen entries in the _Priority_Bit_map.
+ * Each bit in the _Priority_Bit_map indicates whether or not there are
+ * threads ready at a particular priority. The mapping of
+ * individual priority levels to particular bits is processor
+ * dependent as is the value of each bit used to indicate that
+ * threads are ready at that priority.
+ */
+
+SCORE_EXTERN volatile Priority_Bit_map_control _Priority_Major_bit_map;
+SCORE_EXTERN Priority_Bit_map_control
+ _Priority_Bit_map[16] CPU_STRUCTURE_ALIGNMENT;
+
+/*
+ * The definition of the Priority_Bit_map_control type is CPU dependent.
+ *
+ */
+
+/*
+ * Priority Bitfield Manipulation Routines
+ *
+ * NOTE:
+ *
+ * These may simply be pass throughs to CPU dependent routines.
+ */
+
+#if ( CPU_USE_GENERIC_BITFIELD_CODE == FALSE )
+
+#define _Priority_Mask( _bit_number ) \
+ _CPU_Priority_Mask( _bit_number )
+
+#define _Priority_Bits_index( _priority ) \
+ _CPU_Priority_bits_index( _priority )
+
+#endif
+
+#ifndef __RTEMS_APPLICATION__
+#include <rtems/score/priority.inl>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/include/rtems/score/stack.h b/cpukit/score/include/rtems/score/stack.h
new file mode 100644
index 0000000000..16c01f7ea3
--- /dev/null
+++ b/cpukit/score/include/rtems/score/stack.h
@@ -0,0 +1,49 @@
+/* stack.h
+ *
+ * This include file contains all information about the thread
+ * Stack Handler. This Handler provides mechanisms which can be used to
+ * initialize and utilize stacks.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __STACK_h
+#define __STACK_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * The following constant defines the minimum stack size which every
+ * thread must exceed.
+ */
+
+#define STACK_MINIMUM_SIZE CPU_STACK_MINIMUM_SIZE
+
+/*
+ * The following defines the control block used to manage each stack.
+ */
+
+typedef struct {
+ uint32_t size; /* stack size */
+ void *area; /* low memory addr of stack */
+} Stack_Control;
+
+#ifndef __RTEMS_APPLICATION__
+#include <rtems/score/stack.inl>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/include/rtems/score/states.h b/cpukit/score/include/rtems/score/states.h
new file mode 100644
index 0000000000..59d27c274e
--- /dev/null
+++ b/cpukit/score/include/rtems/score/states.h
@@ -0,0 +1,83 @@
+/* states.h
+ *
+ * This include file contains thread execution state information.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_STATES_h
+#define __RTEMS_STATES_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * The following type defines the control block used to manage a
+ * thread's state.
+ */
+
+typedef uint32_t States_Control;
+
+/*
+ * The following constants define the individual states which may be
+ * be used to compose and manipulate a thread's state.
+ */
+
+#define STATES_ALL_SET 0xfffff /* all states */
+#define STATES_READY 0x00000 /* ready to run */
+#define STATES_DORMANT 0x00001 /* created not started */
+#define STATES_SUSPENDED 0x00002 /* waiting for resume */
+#define STATES_TRANSIENT 0x00004 /* in transition */
+#define STATES_DELAYING 0x00008 /* wait for timeout */
+#define STATES_WAITING_FOR_TIME 0x00010 /* wait for TOD */
+#define STATES_WAITING_FOR_BUFFER 0x00020
+#define STATES_WAITING_FOR_SEGMENT 0x00040
+#define STATES_WAITING_FOR_MESSAGE 0x00080
+#define STATES_WAITING_FOR_EVENT 0x00100
+#define STATES_WAITING_FOR_SEMAPHORE 0x00200
+#define STATES_WAITING_FOR_MUTEX 0x00400
+#define STATES_WAITING_FOR_CONDITION_VARIABLE 0x00800
+#define STATES_WAITING_FOR_JOIN_AT_EXIT 0x01000
+#define STATES_WAITING_FOR_RPC_REPLY 0x02000
+#define STATES_WAITING_FOR_PERIOD 0x04000
+#define STATES_WAITING_FOR_SIGNAL 0x08000
+#define STATES_INTERRUPTIBLE_BY_SIGNAL 0x10000
+
+#define STATES_LOCALLY_BLOCKED ( STATES_WAITING_FOR_BUFFER | \
+ STATES_WAITING_FOR_SEGMENT | \
+ STATES_WAITING_FOR_MESSAGE | \
+ STATES_WAITING_FOR_SEMAPHORE | \
+ STATES_WAITING_FOR_MUTEX | \
+ STATES_WAITING_FOR_CONDITION_VARIABLE | \
+ STATES_WAITING_FOR_JOIN_AT_EXIT | \
+ STATES_WAITING_FOR_SIGNAL )
+
+#define STATES_WAITING_ON_THREAD_QUEUE \
+ ( STATES_LOCALLY_BLOCKED | \
+ STATES_WAITING_FOR_RPC_REPLY )
+
+#define STATES_BLOCKED ( STATES_DELAYING | \
+ STATES_WAITING_FOR_TIME | \
+ STATES_WAITING_FOR_PERIOD | \
+ STATES_WAITING_FOR_EVENT | \
+ STATES_WAITING_ON_THREAD_QUEUE | \
+ STATES_INTERRUPTIBLE_BY_SIGNAL )
+
+#ifndef __RTEMS_APPLICATION__
+#include <rtems/score/states.inl>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/include/rtems/score/sysstate.h b/cpukit/score/include/rtems/score/sysstate.h
new file mode 100644
index 0000000000..2f0636399b
--- /dev/null
+++ b/cpukit/score/include/rtems/score/sysstate.h
@@ -0,0 +1,66 @@
+/* sysstates.h
+ *
+ * This include file contains information regarding the system state.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_SYSTEM_STATE_h
+#define __RTEMS_SYSTEM_STATE_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* types */
+
+/* enumerated constants */
+
+/*
+ * The following type defines the possible system states.
+ */
+
+typedef enum {
+ SYSTEM_STATE_BEFORE_INITIALIZATION, /* start -> end of 1st init part */
+ SYSTEM_STATE_BEFORE_MULTITASKING, /* end of 1st -> beginning of 2nd */
+ SYSTEM_STATE_BEGIN_MULTITASKING, /* just before multitasking starts */
+ SYSTEM_STATE_UP, /* normal operation */
+ SYSTEM_STATE_SHUTDOWN, /* shutdown */
+ SYSTEM_STATE_FAILED /* fatal error occurred */
+} System_state_Codes;
+
+#define SYSTEM_STATE_CODES_FIRST SYSTEM_STATE_BEFORE_INITIALIZATION
+#define SYSTEM_STATE_CODES_LAST SYSTEM_STATE_FAILED
+
+/*
+ * The following variable indicates whether or not this is
+ * an multiprocessing system.
+ */
+
+SCORE_EXTERN boolean _System_state_Is_multiprocessing;
+
+/*
+ * The following variable contains the current system state.
+ */
+
+SCORE_EXTERN System_state_Codes _System_state_Current;
+
+/*
+ * Make it possible for the application to get the system state information.
+ */
+
+#include <rtems/score/sysstate.inl>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/include/rtems/score/thread.h b/cpukit/score/include/rtems/score/thread.h
new file mode 100644
index 0000000000..8090656461
--- /dev/null
+++ b/cpukit/score/include/rtems/score/thread.h
@@ -0,0 +1,792 @@
+/* thread.h
+ *
+ * This include file contains all constants and structures associated
+ * with the thread control block.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __THREAD_h
+#define __THREAD_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/context.h>
+#include <rtems/score/cpu.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mppkt.h>
+#endif
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/stack.h>
+#include <rtems/score/states.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/tqdata.h>
+#include <rtems/score/watchdog.h>
+
+/*
+ * The following defines the "return type" of a thread.
+ *
+ * NOTE: This cannot always be right. Some APIs have void
+ * tasks/threads, others return pointers, others may
+ * return a numeric value. Hopefully a pointer is
+ * always at least as big as an uint32_t . :)
+ */
+
+typedef void *Thread;
+
+/*
+ * The following defines the ways in which the entry point for a
+ * thread can be invoked. Basically, it can be passed any
+ * combination/permutation of a pointer and an uint32_t value.
+ *
+ * NOTE: For now, we are ignoring the return type.
+ */
+
+typedef enum {
+ THREAD_START_NUMERIC,
+ THREAD_START_POINTER,
+ THREAD_START_BOTH_POINTER_FIRST,
+ THREAD_START_BOTH_NUMERIC_FIRST
+} Thread_Start_types;
+
+typedef Thread ( *Thread_Entry )(); /* basic type */
+
+typedef Thread ( *Thread_Entry_numeric )( uint32_t );
+typedef Thread ( *Thread_Entry_pointer )( void * );
+typedef Thread ( *Thread_Entry_both_pointer_first )( void *, uint32_t );
+typedef Thread ( *Thread_Entry_both_numeric_first )( uint32_t , void * );
+
+/*
+ * The following lists the algorithms used to manage the thread cpu budget.
+ *
+ * Reset Timeslice: At each context switch, reset the time quantum.
+ * Exhaust Timeslice: Only reset the quantum once it is consumed.
+ * Callout: Execute routine when budget is consumed.
+ */
+
+typedef enum {
+ THREAD_CPU_BUDGET_ALGORITHM_NONE,
+ THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE,
+ THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE,
+ THREAD_CPU_BUDGET_ALGORITHM_CALLOUT
+} Thread_CPU_budget_algorithms;
+
+typedef struct Thread_Control_struct Thread_Control;
+
+typedef void (*Thread_CPU_budget_algorithm_callout )( Thread_Control * );
+
+/*
+ * Per task variable structure
+ */
+
+struct rtems_task_variable_tt;
+
+struct rtems_task_variable_tt {
+ struct rtems_task_variable_tt *next;
+ void **ptr;
+ void *gval;
+ void *tval;
+ void (*dtor)(void *);
+};
+
+typedef struct rtems_task_variable_tt rtems_task_variable_t;
+
+/*
+ * The following structure contains the information which defines
+ * the starting state of a thread.
+ */
+
+typedef struct {
+ Thread_Entry entry_point; /* starting thread address */
+ Thread_Start_types prototype; /* how task is invoked */
+ void *pointer_argument; /* pointer argument */
+ uint32_t numeric_argument; /* numeric argument */
+ /* initial execution modes */
+ boolean is_preemptible;
+ Thread_CPU_budget_algorithms budget_algorithm;
+ Thread_CPU_budget_algorithm_callout budget_callout;
+ uint32_t isr_level;
+ Priority_Control initial_priority; /* initial priority */
+ boolean core_allocated_stack;
+ Stack_Control Initial_stack; /* stack information */
+#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+ void *fp_context; /* initial FP context area address */
+#endif
+ void *stack; /* initial stack area address */
+} Thread_Start_information;
+
+/*
+ * The following structure contains the information necessary to manage
+ * a thread which it is waiting for a resource.
+ */
+
+#define THREAD_STATUS_PROXY_BLOCKING 0x1111111
+
+typedef struct {
+ Objects_Id id; /* waiting on this object */
+ uint32_t count; /* "generic" fields to be used */
+ void *return_argument; /* when blocking */
+ void *return_argument_1;
+ uint32_t option;
+
+ /*
+ * NOTE: The following assumes that all API return codes can be
+ * treated as an uint32_t .
+ */
+ uint32_t return_code; /* status for thread awakened */
+
+ Chain_Control Block2n; /* 2 - n priority blocked chain */
+ Thread_queue_Control *queue; /* pointer to thread queue */
+} Thread_Wait_information;
+
+/*
+ * The following defines the control block used to manage
+ * each thread proxy.
+ *
+ * NOTE: It is critical that proxies and threads have identical
+ * memory images for the shared part.
+ */
+
+typedef struct {
+ Objects_Control Object;
+ States_Control current_state;
+ Priority_Control current_priority;
+ Priority_Control real_priority;
+ uint32_t resource_count;
+ Thread_Wait_information Wait;
+ Watchdog_Control Timer;
+#if defined(RTEMS_MULTIPROCESSING)
+ MP_packet_Prefix *receive_packet;
+#endif
+ /****************** end of common block ********************/
+ Chain_Node Active;
+} Thread_Proxy_control;
+
+
+/*
+ * The following record defines the control block used
+ * to manage each thread.
+ *
+ * NOTE: It is critical that proxies and threads have identical
+ * memory images for the shared part.
+ */
+
+typedef enum {
+ THREAD_API_RTEMS,
+ THREAD_API_POSIX,
+ THREAD_API_ITRON
+} Thread_APIs;
+
+#define THREAD_API_FIRST THREAD_API_RTEMS
+#define THREAD_API_LAST THREAD_API_ITRON
+
+struct Thread_Control_struct {
+ Objects_Control Object;
+ States_Control current_state;
+ Priority_Control current_priority;
+ Priority_Control real_priority;
+ uint32_t resource_count;
+ Thread_Wait_information Wait;
+ Watchdog_Control Timer;
+#if defined(RTEMS_MULTIPROCESSING)
+ MP_packet_Prefix *receive_packet;
+#endif
+ /****************** end of common block ********************/
+ uint32_t suspend_count;
+ boolean is_global;
+ boolean do_post_task_switch_extension;
+
+ boolean is_preemptible;
+ void *rtems_ada_self;
+ uint32_t cpu_time_budget;
+ Thread_CPU_budget_algorithms budget_algorithm;
+ Thread_CPU_budget_algorithm_callout budget_callout;
+
+ uint32_t ticks_executed;
+ Chain_Control *ready;
+ Priority_Information Priority_map;
+ Thread_Start_information Start;
+ Context_Control Registers;
+#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+ void *fp_context;
+#endif
+ struct _reent *libc_reent;
+ void *API_Extensions[ THREAD_API_LAST + 1 ];
+ void **extensions;
+ rtems_task_variable_t *task_variables;
+};
+
+/*
+ * Self for the GNU Ada Run-Time
+ */
+
+SCORE_EXTERN void *rtems_ada_self;
+
+/*
+ * The following defines the information control block used to
+ * manage this class of objects.
+ */
+
+SCORE_EXTERN Objects_Information _Thread_Internal_information;
+
+/*
+ * The following define the thread control pointers used to access
+ * and manipulate the idle thread.
+ */
+
+SCORE_EXTERN Thread_Control *_Thread_Idle;
+
+/*
+ * The following context area contains the context of the "thread"
+ * which invoked the start multitasking routine. This context is
+ * restored as the last action of the stop multitasking routine. Thus
+ * control of the processor can be returned to the environment
+ * which initiated the system.
+ */
+
+SCORE_EXTERN Context_Control _Thread_BSP_context;
+
+/*
+ * The following declares the dispatch critical section nesting
+ * counter which is used to prevent context switches at inopportune
+ * moments.
+ */
+
+SCORE_EXTERN volatile uint32_t _Thread_Dispatch_disable_level;
+
+/*
+ * If this is non-zero, then the post-task switch extension
+ * is run regardless of the state of the per thread flag.
+ */
+
+SCORE_EXTERN uint32_t _Thread_Do_post_task_switch_extension;
+
+/*
+ * The following holds how many user extensions are in the system. This
+ * is used to determine how many user extension data areas to allocate
+ * per thread.
+ */
+
+SCORE_EXTERN uint32_t _Thread_Maximum_extensions;
+
+/*
+ * The following is used to manage the length of a timeslice quantum.
+ */
+
+SCORE_EXTERN uint32_t _Thread_Ticks_per_timeslice;
+
+/*
+ * The following points to the array of FIFOs used to manage the
+ * set of ready threads.
+ */
+
+SCORE_EXTERN Chain_Control *_Thread_Ready_chain;
+
+/*
+ * The following points to the thread which is currently executing.
+ * This thread is implicitly manipulated by numerous directives.
+ */
+
+SCORE_EXTERN Thread_Control *_Thread_Executing;
+
+/*
+ * The following points to the highest priority ready thread
+ * in the system. Unless the current thread is not preemptibl,
+ * then this thread will be context switched to when the next
+ * dispatch occurs.
+ */
+
+SCORE_EXTERN Thread_Control *_Thread_Heir;
+
+/*
+ * The following points to the thread whose floating point
+ * context is currently loaded.
+ */
+
+#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+SCORE_EXTERN Thread_Control *_Thread_Allocated_fp;
+#endif
+
+/*
+ * The C library re-enter-rant global pointer. Some C library implementations
+ * such as newlib have a single global pointer that changed during a context
+ * switch. The pointer points to that global pointer. The Thread control block
+ * holds a pointer to the task specific data.
+ */
+SCORE_EXTERN struct _reent **_Thread_libc_reent;
+
+/*
+ * _Thread_Handler_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this handler.
+ */
+
+void _Thread_Handler_initialization (
+ uint32_t ticks_per_timeslice,
+ uint32_t maximum_extensions,
+ uint32_t maximum_proxies
+);
+
+/*
+ * _Thread_Create_idle
+ *
+ * DESCRIPTION:
+ *
+ * This routine creates the idle thread.
+ *
+ * WARNING!! No thread should be created before this one.
+ */
+
+void _Thread_Create_idle( void );
+
+/*
+ * _Thread_Start_multitasking
+ *
+ * DESCRIPTION:
+ *
+ * This routine initiates multitasking. It is invoked only as
+ * part of initialization and its invocation is the last act of
+ * the non-multitasking part of the system initialization.
+ */
+
+void _Thread_Start_multitasking( void );
+
+/*
+ * _Thread_Dispatch
+ *
+ * DESCRIPTION:
+ *
+ * This routine is responsible for transferring control of the
+ * processor from the executing thread to the heir thread. As part
+ * of this process, it is responsible for the following actions:
+ *
+ * + saving the context of the executing thread
+ * + restoring the context of the heir thread
+ * + dispatching any signals for the resulting executing thread
+ */
+
+void _Thread_Dispatch( void );
+
+/*
+ * _Thread_Stack_Allocate
+ *
+ * DESCRIPTION:
+ *
+ * Allocate the requested stack space for the thread.
+ * return the actual size allocated after any adjustment
+ * or return zero if the allocation failed.
+ * Set the Start.stack field to the address of the stack
+ *
+ * NOTES: NONE
+ *
+ */
+
+uint32_t _Thread_Stack_Allocate(
+ Thread_Control *the_thread,
+ uint32_t stack_size
+);
+
+/*
+ * _Thread_Stack_Free
+ *
+ * DESCRIPTION:
+ *
+ * Deallocate the Thread's stack.
+ * NOTES: NONE
+ *
+ */
+
+void _Thread_Stack_Free(
+ Thread_Control *the_thread
+);
+
+/*
+ * _Thread_Initialize
+ *
+ * DESCRIPTION:
+ *
+ * This routine initializes the specified the thread. It allocates
+ * all memory associated with this thread. It completes by adding
+ * the thread to the local object table so operations on this
+ * thread id are allowed.
+ *
+ * NOTES:
+ *
+ * If stack_area is NULL, it is allocated from the workspace.
+ *
+ * If the stack is allocated from the workspace, then it is guaranteed to be
+ * of at least minimum size.
+ */
+
+boolean _Thread_Initialize(
+ Objects_Information *information,
+ Thread_Control *the_thread,
+ void *stack_area,
+ uint32_t stack_size,
+ boolean is_fp,
+ Priority_Control priority,
+ boolean is_preemptible,
+ Thread_CPU_budget_algorithms budget_algorithm,
+ Thread_CPU_budget_algorithm_callout budget_callout,
+ uint32_t isr_level,
+ Objects_Name name
+);
+
+/*
+ * _Thread_Start
+ *
+ * DESCRIPTION:
+ *
+ * This routine initializes the executable information for a thread
+ * and makes it ready to execute. After this routine executes, the
+ * thread competes with all other threads for CPU time.
+ */
+
+boolean _Thread_Start(
+ Thread_Control *the_thread,
+ Thread_Start_types the_prototype,
+ void *entry_point,
+ void *pointer_argument,
+ uint32_t numeric_argument
+);
+
+/*
+ * _Thread_Restart
+ *
+ * DESCRIPTION:
+ *
+ * This support routine restarts the specified task in a way that the
+ * next time this thread executes, it will begin execution at its
+ * original starting point.
+ */
+
+/* XXX multiple task arg profiles */
+
+boolean _Thread_Restart(
+ Thread_Control *the_thread,
+ void *pointer_argument,
+ uint32_t numeric_argument
+);
+
+/*
+ * _Thread_Reset
+ *
+ * DESCRIPTION:
+ *
+ * This routine resets a thread to its initial state but does
+ * not restart it.
+ */
+
+void _Thread_Reset(
+ Thread_Control *the_thread,
+ void *pointer_argument,
+ uint32_t numeric_argument
+);
+
+/*
+ * _Thread_Close
+ *
+ * DESCRIPTION:
+ *
+ * This routine frees all memory associated with the specified
+ * thread and removes it from the local object table so no further
+ * operations on this thread are allowed.
+ */
+
+void _Thread_Close(
+ Objects_Information *information,
+ Thread_Control *the_thread
+);
+
+/*
+ * _Thread_Ready
+ *
+ * DESCRIPTION:
+ *
+ * This routine removes any set states for the_thread. It performs
+ * any necessary scheduling operations including the selection of
+ * a new heir thread.
+ */
+
+void _Thread_Ready(
+ Thread_Control *the_thread
+);
+
+/*
+ * _Thread_Clear_state
+ *
+ * DESCRIPTION:
+ *
+ * This routine clears the indicated STATES for the_thread. It performs
+ * any necessary scheduling operations including the selection of
+ * a new heir thread.
+ */
+
+void _Thread_Clear_state(
+ Thread_Control *the_thread,
+ States_Control state
+);
+
+/*
+ * _Thread_Set_state
+ *
+ * DESCRIPTION:
+ *
+ * This routine sets the indicated states for the_thread. It performs
+ * any necessary scheduling operations including the selection of
+ * a new heir thread.
+ *
+ */
+
+void _Thread_Set_state(
+ Thread_Control *the_thread,
+ States_Control state
+);
+
+/*
+ * _Thread_Set_transient
+ *
+ * DESCRIPTION:
+ *
+ * This routine sets the TRANSIENT state for the_thread. It performs
+ * any necessary scheduling operations including the selection of
+ * a new heir thread.
+ */
+
+void _Thread_Set_transient(
+ Thread_Control *the_thread
+);
+
+/*
+ * _Thread_Reset_timeslice
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked upon expiration of the currently
+ * executing thread's timeslice. If no other thread's are ready
+ * at the priority of the currently executing thread, then the
+ * executing thread's timeslice is reset. Otherwise, the
+ * currently executing thread is placed at the rear of the
+ * FIFO for this priority and a new heir is selected.
+ */
+
+void _Thread_Reset_timeslice( void );
+
+/*
+ * _Thread_Tickle_timeslice
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked as part of processing each clock tick.
+ * It is responsible for determining if the current thread allows
+ * timeslicing and, if so, when its timeslice expires.
+ */
+
+void _Thread_Tickle_timeslice( void );
+
+/*
+ * _Thread_Yield_processor
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked when a thread wishes to voluntarily
+ * transfer control of the processor to another thread of equal
+ * or greater priority.
+ */
+
+void _Thread_Yield_processor( void );
+
+/*
+ * _Thread_Rotate_Ready_Queue
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked to rotate the ready queue for the
+ * given priority. It can be used to yeild the processor
+ * by rotating the executing threads ready queue.
+ */
+
+void _Thread_Rotate_Ready_Queue(
+ Priority_Control priority
+);
+
+/*
+ * _Thread_Load_environment
+ *
+ * DESCRIPTION:
+ *
+ * This routine initializes the context of the_thread to its
+ * appropriate starting state.
+ */
+
+void _Thread_Load_environment(
+ Thread_Control *the_thread
+);
+
+/*
+ * _Thread_Handler
+ *
+ * DESCRIPTION:
+ *
+ * This routine is the wrapper function for all threads. It is
+ * the starting point for all threads. The user provided thread
+ * entry point is invoked by this routine. Operations
+ * which must be performed immediately before and after the user's
+ * thread executes are found here.
+ */
+
+void _Thread_Handler( void );
+
+/*
+ * _Thread_Delay_ended
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked when a thread must be unblocked at the
+ * end of a time based delay (i.e. wake after or wake when).
+ */
+
+void _Thread_Delay_ended(
+ Objects_Id id,
+ void *ignored
+);
+
+/*
+ * _Thread_Change_priority
+ *
+ * DESCRIPTION:
+ *
+ * This routine changes the current priority of the_thread to
+ * new_priority. It performs any necessary scheduling operations
+ * including the selection of a new heir thread.
+ */
+
+void _Thread_Change_priority (
+ Thread_Control *the_thread,
+ Priority_Control new_priority,
+ boolean prepend_it
+);
+
+/*
+ * _Thread_Set_priority
+ *
+ * DESCRIPTION:
+ *
+ * This routine updates the priority related fields in the_thread
+ * control block to indicate the current priority is now new_priority.
+ */
+
+void _Thread_Set_priority(
+ Thread_Control *the_thread,
+ Priority_Control new_priority
+);
+
+/*
+ * _Thread_Suspend
+ *
+ * DESCRIPTION:
+ *
+ * This routine updates the related suspend fields in the_thread
+ * control block to indicate the current nested level.
+ */
+
+void _Thread_Suspend(
+ Thread_Control *the_thread
+);
+
+/*
+ * _Thread_Resume
+ *
+ * DESCRIPTION:
+ *
+ * This routine updates the related suspend fields in the_thread
+ * control block to indicate the current nested level. A force
+ * parameter of TRUE will force a resume and clear the suspend count.
+ */
+
+void _Thread_Resume(
+ Thread_Control *the_thread,
+ boolean force
+);
+
+/*
+ * _Thread_Evaluate_mode
+ *
+ * DESCRIPTION:
+ *
+ * This routine evaluates the current scheduling information for the
+ * system and determines if a context switch is required. This
+ * is usually called after changing an execution mode such as preemptability
+ * for a thread.
+ */
+
+boolean _Thread_Evaluate_mode( void );
+
+/*
+ * _Thread_Get
+ *
+ * NOTE: If we are not using static inlines, this must be a real
+ * subroutine call.
+ */
+
+#ifndef RTEMS_INLINES
+Thread_Control *_Thread_Get (
+ Objects_Id id,
+ Objects_Locations *location
+);
+#endif
+
+/*
+ * _Thread_Idle_body
+ *
+ * DESCRIPTION:
+ *
+ * This routine is the body of the system idle thread.
+ */
+
+#if (CPU_PROVIDES_IDLE_THREAD_BODY == FALSE)
+Thread _Thread_Idle_body(
+ uint32_t ignored
+);
+#endif
+
+/*
+ * rtems_iterate_over_all_tasks
+ *
+ * DESCRIPTION:
+ *
+ * This routine iterates over all threads regardless of API and
+ * invokes the specified routine.
+ */
+
+typedef void (*rtems_per_thread_routine)( Thread_Control * );
+
+void rtems_iterate_over_all_threads(
+ rtems_per_thread_routine routine
+);
+
+#ifndef __RTEMS_APPLICATION__
+#include <rtems/score/thread.inl>
+#endif
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/threadmp.h>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/include/rtems/score/threadmp.h b/cpukit/score/include/rtems/score/threadmp.h
new file mode 100644
index 0000000000..ad5efb7fb0
--- /dev/null
+++ b/cpukit/score/include/rtems/score/threadmp.h
@@ -0,0 +1,88 @@
+/* threadmp.h
+ *
+ * This include file contains the specification for all routines
+ * and data specific to the multiprocessing portion of the thread package.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_THREAD_MP_h
+#define __RTEMS_THREAD_MP_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * _Thread_MP_Handler_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine initializes the multiprocessing portion of the Thread Handler.
+ */
+
+void _Thread_MP_Handler_initialization (
+ uint32_t maximum_proxies
+);
+
+/*
+ * _Thread_MP_Allocate_proxy
+ *
+ * DESCRIPTION:
+ *
+ * This allocates a proxy control block from
+ * the inactive chain of free proxy control blocks.
+ *
+ * NOTE: This function returns a thread control pointer
+ * because proxies are substitutes for remote threads.
+ */
+
+Thread_Control *_Thread_MP_Allocate_proxy (
+ States_Control the_state
+);
+
+/*
+ * _Thread_MP_Find_proxy
+ *
+ * DESCRIPTION:
+ *
+ * This function removes the proxy control block for the specified
+ * id from the active chain of proxy control blocks.
+ */
+
+Thread_Control *_Thread_MP_Find_proxy (
+ Objects_Id the_id
+);
+
+/*
+ * The following is used to determine when the multiprocessing receive
+ * thread is executing so that a proxy can be allocated instead of
+ * blocking the multiprocessing receive thread.
+ */
+
+SCORE_EXTERN Thread_Control *_Thread_MP_Receive;
+
+/*
+ * The following chains are used to manage proxies.
+ */
+
+SCORE_EXTERN Chain_Control _Thread_MP_Active_proxies;
+SCORE_EXTERN Chain_Control _Thread_MP_Inactive_proxies;
+
+#ifndef __RTEMS_APPLICATION__
+#include <rtems/score/threadmp.inl>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/include/rtems/score/threadq.h b/cpukit/score/include/rtems/score/threadq.h
new file mode 100644
index 0000000000..cbbb85e345
--- /dev/null
+++ b/cpukit/score/include/rtems/score/threadq.h
@@ -0,0 +1,300 @@
+/* threadq.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the manipulation of objects.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __THREAD_QUEUE_h
+#define __THREAD_QUEUE_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/tqdata.h>
+
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/watchdog.h>
+
+/*
+ * Constant for indefinite wait.
+ */
+
+#define THREAD_QUEUE_WAIT_FOREVER WATCHDOG_NO_TIMEOUT
+
+/*
+ * The following type defines the callout used when a remote task
+ * is extracted from a local thread queue.
+ */
+
+typedef void ( *Thread_queue_Flush_callout )(
+ Thread_Control *
+ );
+
+/*
+ * The following type defines the callout used when a local task
+ * is extracted from a remote thread queue (i.e. it's proxy must
+ * extracted from the remote queue).
+ */
+
+#if 0
+typedef void ( *Thread_queue_Extract_callout )(
+ Thread_Control *
+ );
+
+SCORE_EXTERN Thread_queue_Extract_callout
+ _Thread_queue_Extract_table[ OBJECTS_CLASSES_LAST + 1 ];
+#endif
+
+/*
+ * _Thread_queue_Dequeue
+ *
+ * DESCRIPTION:
+ *
+ * This function returns a pointer to a thread waiting on
+ * the_thread_queue. The selection of this thread is based on
+ * the discipline of the_thread_queue. If no threads are waiting
+ * on the_thread_queue, then NULL is returned.
+ */
+
+Thread_Control *_Thread_queue_Dequeue(
+ Thread_queue_Control *the_thread_queue
+);
+
+/*
+ * _Thread_queue_Enqueue
+ *
+ * DESCRIPTION:
+ *
+ * This routine enqueues the currently executing thread on
+ * the_thread_queue with an optional timeout.
+ */
+
+void _Thread_queue_Enqueue(
+ Thread_queue_Control *the_thread_queue,
+ Watchdog_Interval timeout
+);
+
+/*
+ * _Thread_queue_Extract
+ *
+ * DESCRIPTION:
+ *
+ * This routine removes the_thread from the_thread_queue
+ * and cancels any timeouts associated with this blocking.
+ */
+
+void _Thread_queue_Extract(
+ Thread_queue_Control *the_thread_queue,
+ Thread_Control *the_thread
+);
+
+/*
+ * _Thread_queue_Extract_with_proxy
+ *
+ * DESCRIPTION:
+ *
+ * This routine extracts the_thread from the_thread_queue
+ * and ensures that if there is a proxy for this task on
+ * another node, it is also dealt with.
+ */
+
+boolean _Thread_queue_Extract_with_proxy(
+ Thread_Control *the_thread
+);
+
+/*
+ * _Thread_queue_First
+ *
+ * DESCRIPTION:
+ *
+ * This function returns a pointer to the "first" thread
+ * on the_thread_queue. The "first" thread is selected
+ * based on the discipline of the_thread_queue.
+ */
+
+Thread_Control *_Thread_queue_First(
+ Thread_queue_Control *the_thread_queue
+);
+
+/*
+ * _Thread_queue_Flush
+ *
+ * DESCRIPTION:
+ *
+ * This routine unblocks all threads blocked on the_thread_queue
+ * and cancels any associated timeouts.
+ */
+
+void _Thread_queue_Flush(
+ Thread_queue_Control *the_thread_queue,
+ Thread_queue_Flush_callout remote_extract_callout,
+ uint32_t status
+);
+
+/*
+ * _Thread_queue_Initialize
+ *
+ * DESCRIPTION:
+ *
+ * This routine initializes the_thread_queue based on the
+ * discipline indicated in attribute_set. The state set on
+ * threads which block on the_thread_queue is state.
+ */
+
+void _Thread_queue_Initialize(
+ Thread_queue_Control *the_thread_queue,
+ Thread_queue_Disciplines the_discipline,
+ States_Control state,
+ uint32_t timeout_status
+);
+
+/*
+ * _Thread_queue_Dequeue_priority
+ *
+ * DESCRIPTION:
+ *
+ * This function returns a pointer to the highest priority
+ * thread waiting on the_thread_queue. If no threads are waiting
+ * on the_thread_queue, then NULL is returned.
+ */
+
+Thread_Control *_Thread_queue_Dequeue_priority(
+ Thread_queue_Control *the_thread_queue
+);
+
+/*
+ * _Thread_queue_Enqueue_priority
+ *
+ * DESCRIPTION:
+ *
+ * This routine enqueues the currently executing thread on
+ * the_thread_queue with an optional timeout using the
+ * priority discipline.
+ */
+
+void _Thread_queue_Enqueue_priority(
+ Thread_queue_Control *the_thread_queue,
+ Thread_Control *the_thread,
+ Watchdog_Interval timeout
+);
+
+/*
+ * _Thread_queue_Extract_priority
+ *
+ * DESCRIPTION:
+ *
+ * This routine removes the_thread from the_thread_queue
+ * and cancels any timeouts associated with this blocking.
+ */
+
+void _Thread_queue_Extract_priority(
+ Thread_queue_Control *the_thread_queue,
+ Thread_Control *the_thread
+);
+
+/*
+ * _Thread_queue_First_priority
+ *
+ * DESCRIPTION:
+ *
+ * This function returns a pointer to the "first" thread
+ * on the_thread_queue. The "first" thread is the highest
+ * priority thread waiting on the_thread_queue.
+ */
+
+Thread_Control *_Thread_queue_First_priority(
+ Thread_queue_Control *the_thread_queue
+);
+
+/*
+ * _Thread_queue_Dequeue_FIFO
+ *
+ * DESCRIPTION:
+ *
+ * This function returns a pointer to the thread which has
+ * been waiting the longest on the_thread_queue. If no
+ * threads are waiting on the_thread_queue, then NULL is returned.
+ */
+
+Thread_Control *_Thread_queue_Dequeue_fifo(
+ Thread_queue_Control *the_thread_queue
+);
+
+/*
+ * _Thread_queue_Enqueue_FIFO
+ *
+ * DESCRIPTION:
+ *
+ * This routine enqueues the currently executing thread on
+ * the_thread_queue with an optional timeout using the
+ * FIFO discipline.
+ */
+
+void _Thread_queue_Enqueue_fifo(
+ Thread_queue_Control *the_thread_queue,
+ Thread_Control *the_thread,
+ Watchdog_Interval timeout
+);
+
+/*
+ * _Thread_queue_Extract_FIFO
+ *
+ * DESCRIPTION:
+ *
+ * This routine removes the_thread from the_thread_queue
+ * and cancels any timeouts associated with this blocking.
+ */
+
+void _Thread_queue_Extract_fifo(
+ Thread_queue_Control *the_thread_queue,
+ Thread_Control *the_thread
+);
+
+/*
+ * _Thread_queue_First_FIFO
+ *
+ * DESCRIPTION:
+ *
+ * This function returns a pointer to the "first" thread
+ * on the_thread_queue. The first thread is the thread
+ * which has been waiting longest on the_thread_queue.
+ */
+
+Thread_Control *_Thread_queue_First_fifo(
+ Thread_queue_Control *the_thread_queue
+);
+
+/*
+ * _Thread_queue_timeout
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked when a task's request has not
+ * been satisfied after the timeout interval specified to
+ * enqueue. The task represented by ID will be unblocked and
+ * its status code will be set in it's control block to indicate
+ * that a timeout has occurred.
+ */
+
+void _Thread_queue_Timeout (
+ Objects_Id id,
+ void *ignored
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/include/rtems/score/tod.h b/cpukit/score/include/rtems/score/tod.h
new file mode 100644
index 0000000000..8966c8b06c
--- /dev/null
+++ b/cpukit/score/include/rtems/score/tod.h
@@ -0,0 +1,276 @@
+/* tod.h
+ *
+ * This include file contains all the constants and structures associated
+ * with the Time of Day Handler.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __TIME_OF_DAY_h
+#define __TIME_OF_DAY_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/object.h>
+#include <rtems/score/watchdog.h>
+
+/*
+ * The following constants are related to the time of day.
+ */
+
+#define TOD_SECONDS_PER_MINUTE (uint32_t )60
+#define TOD_MINUTES_PER_HOUR (uint32_t )60
+#define TOD_MONTHS_PER_YEAR (uint32_t )12
+#define TOD_DAYS_PER_YEAR (uint32_t )365
+#define TOD_HOURS_PER_DAY (uint32_t )24
+#define TOD_SECONDS_PER_DAY (uint32_t ) (TOD_SECONDS_PER_MINUTE * \
+ TOD_MINUTES_PER_HOUR * \
+ TOD_HOURS_PER_DAY)
+
+#define TOD_SECONDS_PER_NON_LEAP_YEAR (365 * TOD_SECONDS_PER_DAY)
+
+#define TOD_MILLISECONDS_PER_SECOND (uint32_t )1000
+#define TOD_MICROSECONDS_PER_SECOND (uint32_t )1000000
+#define TOD_NANOSECONDS_PER_SECOND (uint32_t )1000000000
+#define TOD_NANOSECONDS_PER_MICROSECOND (uint32_t )1000
+
+/*
+ * The following constant define the earliest year to which an
+ * time of day can be initialized. This is considered the
+ * epoch.
+ */
+
+#define TOD_BASE_YEAR 1988
+
+/*
+ * The following record defines the time of control block. This
+ * control block is used to maintain the current time of day.
+ */
+
+typedef struct { /* RTEID style time/date */
+ uint32_t year; /* year, A.D. */
+ uint32_t month; /* month, 1 -> 12 */
+ uint32_t day; /* day, 1 -> 31 */
+ uint32_t hour; /* hour, 0 -> 23 */
+ uint32_t minute; /* minute, 0 -> 59 */
+ uint32_t second; /* second, 0 -> 59 */
+ uint32_t ticks; /* elapsed ticks between secs */
+} TOD_Control;
+
+/*
+ * The following is TRUE if the application has set the current
+ * time of day, and FALSE otherwise.
+ */
+
+SCORE_EXTERN boolean _TOD_Is_set;
+
+/*
+ * The following contains the current time of day.
+ */
+
+SCORE_EXTERN TOD_Control _TOD_Current;
+
+/*
+ * The following contains the number of seconds from 00:00:00
+ * January 1, TOD_BASE_YEAR until the current time of day.
+ */
+
+SCORE_EXTERN Watchdog_Interval _TOD_Seconds_since_epoch;
+
+/*
+ * The following contains the number of microseconds per tick.
+ */
+
+SCORE_EXTERN uint32_t _TOD_Microseconds_per_tick;
+
+/*
+ * The following contains the number of clock ticks per second.
+ *
+ * NOTE:
+ *
+ * If one second is NOT evenly divisible by the number of microseconds
+ * per clock tick, this value will contain only the integer portion
+ * of the division. This means that the interval between clock ticks
+ * can be a source of error in the current time of day.
+ */
+
+SCORE_EXTERN uint32_t _TOD_Ticks_per_second;
+
+/*
+ * This is the control structure for the watchdog timer which
+ * fires to service the seconds chain.
+ */
+
+SCORE_EXTERN Watchdog_Control _TOD_Seconds_watchdog;
+
+#ifdef SCORE_INIT
+
+/*
+ * The following array contains the number of days in all months.
+ * The first dimension should be 1 for leap years, and 0 otherwise.
+ * The second dimension should range from 1 to 12 for January to
+ * February, respectively.
+ */
+
+const uint32_t _TOD_Days_per_month[ 2 ][ 13 ] = {
+ { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+ { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+};
+
+/*
+ * The following array contains the number of days in all months
+ * up to the month indicated by the index of the second dimension.
+ * The first dimension should be 1 for leap years, and 0 otherwise.
+ */
+
+const uint16_t _TOD_Days_to_date[2][13] = {
+ { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 },
+ { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }
+};
+
+/*
+ * The following array contains the number of days in the years
+ * since the last leap year. The index should be 0 for leap
+ * years, and the number of years since the beginning of a leap
+ * year otherwise.
+ */
+
+const uint16_t _TOD_Days_since_last_leap_year[4] = { 0, 366, 731, 1096 };
+
+#else
+
+extern const uint16_t _TOD_Days_to_date[2][13]; /* Julian days */
+extern const uint16_t _TOD_Days_since_last_leap_year[4];
+extern const uint32_t _TOD_Days_per_month[2][13];
+
+#endif
+
+/*
+ * _TOD_Handler_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this handler.
+ */
+
+void _TOD_Handler_initialization(
+ uint32_t microseconds_per_tick
+);
+
+/*
+ * _TOD_Set
+ *
+ * DESCRIPTION:
+ *
+ * This routine sets the current time of day to THE_TOD and
+ * the equivalent SECONDS_SINCE_EPOCH.
+ */
+
+void _TOD_Set(
+ TOD_Control *the_tod,
+ Watchdog_Interval seconds_since_epoch
+);
+
+/*
+ * _TOD_Validate
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if THE_TOD contains
+ * a valid time of day, and FALSE otherwise.
+ */
+
+boolean _TOD_Validate(
+ TOD_Control *the_tod
+);
+
+/*
+ * _TOD_To_seconds
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the number seconds between the epoch and THE_TOD.
+ */
+
+Watchdog_Interval _TOD_To_seconds(
+ TOD_Control *the_tod
+);
+
+/*
+ * _TOD_Tickle
+ *
+ * DESCRIPTION:
+ *
+ * This routine is scheduled as a watchdog function and is invoked at
+ * each second boundary. It updates the current time of day to indicate
+ * that a second has passed and processes the seconds watchdog chain.
+ */
+
+void _TOD_Tickle(
+ Objects_Id id,
+ void *ignored
+);
+
+/*
+ * TOD_MILLISECONDS_TO_MICROSECONDS
+ *
+ * DESCRIPTION:
+ *
+ * This routine converts an interval expressed in milliseconds to microseconds.
+ *
+ * NOTE:
+ *
+ * This must be a macro so it can be used in "static" tables.
+ */
+
+#define TOD_MILLISECONDS_TO_MICROSECONDS(_ms) ((_ms) * 1000)
+
+/*
+ * TOD_MICROSECONDS_TO_TICKS
+ *
+ * DESCRIPTION:
+ *
+ * This routine converts an interval expressed in microseconds to ticks.
+ *
+ * NOTE:
+ *
+ * This must be a macro so it can be used in "static" tables.
+ */
+
+#define TOD_MICROSECONDS_TO_TICKS(_us) \
+ ((_us) / _TOD_Microseconds_per_tick)
+
+/*
+ * TOD_MILLISECONDS_TO_TICKS
+ *
+ * DESCRIPTION:
+ *
+ * This routine converts an interval expressed in milliseconds to ticks.
+ *
+ * NOTE:
+ *
+ * This must be a macro so it can be used in "static" tables.
+ */
+
+#define TOD_MILLISECONDS_TO_TICKS(_ms) \
+ (TOD_MILLISECONDS_TO_MICROSECONDS(_ms) / _TOD_Microseconds_per_tick)
+
+#ifndef __RTEMS_APPLICATION__
+#include <rtems/score/tod.inl>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/include/rtems/score/tqdata.h b/cpukit/score/include/rtems/score/tqdata.h
new file mode 100644
index 0000000000..4945c74e3f
--- /dev/null
+++ b/cpukit/score/include/rtems/score/tqdata.h
@@ -0,0 +1,89 @@
+/* tqdata.h
+ *
+ * This include file contains all the constants and structures
+ * needed to declare a thread queue.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __THREAD_QUEUE_DATA_h
+#define __THREAD_QUEUE_DATA_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/chain.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+
+/*
+ * The following enumerated type details all of the disciplines
+ * supported by the Thread Queue Handler.
+ */
+
+typedef enum {
+ THREAD_QUEUE_DISCIPLINE_FIFO, /* FIFO queue discipline */
+ THREAD_QUEUE_DISCIPLINE_PRIORITY /* PRIORITY queue discipline */
+} Thread_queue_Disciplines;
+
+/*
+ * The following enumerated types indicate what happened while the thread
+ * queue was in the synchronization window.
+ */
+
+typedef enum {
+ THREAD_QUEUE_SYNCHRONIZED,
+ THREAD_QUEUE_NOTHING_HAPPENED,
+ THREAD_QUEUE_TIMEOUT,
+ THREAD_QUEUE_SATISFIED
+} Thread_queue_States;
+
+/*
+ * The following constants are used to manage the priority queues.
+ *
+ * There are four chains used to maintain a priority -- each chain
+ * manages a distinct set of task priorities. The number of chains
+ * is determined by TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS.
+ * The following set must be consistent.
+ *
+ * The set below configures 4 headers -- each contains 64 priorities.
+ * Header x manages priority range (x*64) through ((x*64)+63). If
+ * the priority is more than half way through the priority range it
+ * is in, then the search is performed from the rear of the chain.
+ * This halves the search time to find the insertion point.
+ */
+
+#define TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS 4
+#define TASK_QUEUE_DATA_PRIORITIES_PER_HEADER 64
+#define TASK_QUEUE_DATA_REVERSE_SEARCH_MASK 0x20
+
+typedef struct {
+ union {
+ Chain_Control Fifo; /* FIFO discipline list */
+ Chain_Control Priority[TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS];
+ /* priority discipline list */
+ } Queues;
+ Thread_queue_States sync_state; /* alloc/dealloc critical section */
+ Thread_queue_Disciplines discipline; /* queue discipline */
+ States_Control state; /* state of threads on Thread_q */
+ uint32_t timeout_status;
+} Thread_queue_Control;
+
+#ifndef __RTEMS_APPLICATION__
+#include <rtems/score/tqdata.inl>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/include/rtems/score/userext.h b/cpukit/score/include/rtems/score/userext.h
new file mode 100644
index 0000000000..c0f5a4b0a8
--- /dev/null
+++ b/cpukit/score/include/rtems/score/userext.h
@@ -0,0 +1,230 @@
+/* userext.h
+ *
+ * This include file contains all information about user extensions. This
+ * Handler provides mechanisms which can be used to initialize and manipulate
+ * all user extensions.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __USER_EXTENSIONS_h
+#define __USER_EXTENSIONS_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/interr.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/thread.h>
+
+/*
+ * The following records defines the User Extension Table.
+ * This table defines the application dependent routines which
+ * are invoked at critical points in the life of each thread and
+ * the system as a whole.
+ */
+
+typedef void User_extensions_routine;
+
+typedef boolean ( *User_extensions_thread_create_extension )(
+ Thread_Control *,
+ Thread_Control *
+ );
+
+typedef User_extensions_routine ( *User_extensions_thread_delete_extension )(
+ Thread_Control *,
+ Thread_Control *
+ );
+
+typedef User_extensions_routine ( *User_extensions_thread_start_extension )(
+ Thread_Control *,
+ Thread_Control *
+ );
+
+typedef User_extensions_routine ( *User_extensions_thread_restart_extension )(
+ Thread_Control *,
+ Thread_Control *
+ );
+
+typedef User_extensions_routine ( *User_extensions_thread_switch_extension )(
+ Thread_Control *,
+ Thread_Control *
+ );
+
+typedef User_extensions_routine (
+ *User_extensions_thread_post_switch_extension )(
+ Thread_Control *
+ );
+
+typedef User_extensions_routine ( *User_extensions_thread_begin_extension )(
+ Thread_Control *
+ );
+
+typedef User_extensions_routine ( *User_extensions_thread_exitted_extension )(
+ Thread_Control *
+ );
+
+typedef User_extensions_routine ( *User_extensions_fatal_extension )(
+ Internal_errors_Source /* the_source */,
+ boolean /* is_internal */,
+ uint32_t /* the_error */
+ );
+
+
+typedef struct {
+ User_extensions_thread_create_extension thread_create;
+ User_extensions_thread_start_extension thread_start;
+ User_extensions_thread_restart_extension thread_restart;
+ User_extensions_thread_delete_extension thread_delete;
+ User_extensions_thread_switch_extension thread_switch;
+ User_extensions_thread_begin_extension thread_begin;
+ User_extensions_thread_exitted_extension thread_exitted;
+ User_extensions_fatal_extension fatal;
+} User_extensions_Table;
+
+/*
+ * The following is used to manage the list of switch handlers.
+ */
+
+typedef struct {
+ Chain_Node Node;
+ User_extensions_thread_switch_extension thread_switch;
+} User_extensions_Switch_control;
+
+/*
+ * The following is used to manage each user extension set.
+ * The switch control is part of the extensions control even
+ * if not used due to the extension not having a switch
+ * handler.
+ */
+
+typedef struct {
+ Chain_Node Node;
+ User_extensions_Switch_control Switch;
+ User_extensions_Table Callouts;
+} User_extensions_Control;
+
+/*
+ * The following is used to manage the list of active extensions.
+ */
+
+SCORE_EXTERN Chain_Control _User_extensions_List;
+
+/*
+ * The following is used to manage a chain of user extension task
+ * switch nodes.
+ */
+
+SCORE_EXTERN Chain_Control _User_extensions_Switches_list;
+
+/*
+ * _User_extensions_Thread_create
+ *
+ * DESCRIPTION:
+ *
+ * This routine is used to invoke the user extension for
+ * the thread creation operate.
+ */
+
+boolean _User_extensions_Thread_create (
+ Thread_Control *the_thread
+);
+
+/*
+ * _User_extensions_Thread_delete
+ *
+ * DESCRIPTION:
+ *
+ * This routine is used to invoke the user extension for
+ * the thread deletion operation.
+ */
+
+void _User_extensions_Thread_delete (
+ Thread_Control *the_thread
+);
+
+/*
+ * _User_extensions_Thread_start
+ *
+ * DESCRIPTION:
+ *
+ * This routine is used to invoke the user extension for
+ * the thread start operation.
+ */
+
+void _User_extensions_Thread_start (
+ Thread_Control *the_thread
+);
+
+/*
+ * _User_extensions_Thread_restart
+ *
+ * DESCRIPTION:
+ *
+ * This routine is used to invoke the user extension for
+ * the thread restart operation.
+ */
+
+void _User_extensions_Thread_restart (
+ Thread_Control *the_thread
+);
+
+/*
+ * _User_extensions_Thread_begin
+ *
+ * DESCRIPTION:
+ *
+ * This routine is used to invoke the user extension which
+ * is invoked when a thread begins.
+ */
+
+void _User_extensions_Thread_begin (
+ Thread_Control *executing
+);
+
+/*
+ * _User_extensions_Thread_exitted
+ *
+ * DESCRIPTION:
+ *
+ * This routine is used to invoke the user extension which
+ * is invoked when a thread exits.
+ */
+
+void _User_extensions_Thread_exitted (
+ Thread_Control *executing
+);
+
+/*
+ * _User_extensions_Fatal
+ *
+ * DESCRIPTION:
+ *
+ * This routine is used to invoke the user extension invoked
+ * when a fatal error occurs.
+ */
+
+void _User_extensions_Fatal (
+ Internal_errors_Source the_source,
+ boolean is_internal,
+ uint32_t the_error
+);
+
+#ifndef __RTEMS_APPLICATION__
+#include <rtems/score/userext.inl>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/include/rtems/score/watchdog.h b/cpukit/score/include/rtems/score/watchdog.h
new file mode 100644
index 0000000000..cb70d13120
--- /dev/null
+++ b/cpukit/score/include/rtems/score/watchdog.h
@@ -0,0 +1,195 @@
+/* watchdog.h
+ *
+ * This include file contains all the constants and structures associated
+ * with watchdog timers. This Handler provides mechanisms which can be
+ * used to initialize and manipulate watchdog timers.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __WATCHDOG_h
+#define __WATCHDOG_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/object.h>
+
+/*
+ * The following type defines the control block used to manage
+ * intervals.
+ */
+
+#define WATCHDOG_MAXIMUM_INTERVAL ((Watchdog_Interval) 0xffffffff)
+
+typedef uint32_t Watchdog_Interval;
+
+/*
+ * The following types define a pointer to a watchdog service routine.
+ */
+
+typedef void Watchdog_Service_routine;
+
+typedef Watchdog_Service_routine ( *Watchdog_Service_routine_entry )(
+ Objects_Id,
+ void *
+ );
+
+/*
+ * Constant for indefinite wait. (actually an illegal interval)
+ */
+
+#define WATCHDOG_NO_TIMEOUT 0
+
+/*
+ * The following enumerated type lists the states in which a
+ * watchdog timer may be at any given time.
+ */
+
+typedef enum {
+ WATCHDOG_INACTIVE, /* off all chains */
+ WATCHDOG_BEING_INSERTED, /* off all chains, searching for insertion point */
+ WATCHDOG_ACTIVE, /* on chain, allowed to fire */
+ WATCHDOG_REMOVE_IT /* on chain, remove without firing if expires */
+} Watchdog_States;
+
+/*
+ * The following enumerated type details the manner in which
+ * a watchdog chain may be adjusted by the Watchdog_Adjust
+ * routine. The direction indicates a movement FORWARD
+ * or BACKWARD in time.
+ */
+
+typedef enum {
+ WATCHDOG_FORWARD, /* adjust delta value forward */
+ WATCHDOG_BACKWARD /* adjust delta value backward */
+} Watchdog_Adjust_directions;
+
+/*
+ * The following record defines the control block used
+ * to manage each watchdog timer.
+ */
+
+typedef struct {
+ Chain_Node Node;
+ Watchdog_States state;
+ Watchdog_Interval initial;
+ Watchdog_Interval delta_interval;
+ Watchdog_Interval start_time;
+ Watchdog_Interval stop_time;
+ Watchdog_Service_routine_entry routine;
+ Objects_Id id;
+ void *user_data;
+} Watchdog_Control;
+
+/*
+ * The following are used for synchronization purposes
+ * during an insert on a watchdog delta chain.
+ */
+
+SCORE_EXTERN volatile uint32_t _Watchdog_Sync_level;
+SCORE_EXTERN volatile uint32_t _Watchdog_Sync_count;
+
+/*
+ * The following contains the number of ticks since the
+ * system was booted.
+ */
+
+SCORE_EXTERN volatile Watchdog_Interval _Watchdog_Ticks_since_boot;
+
+/*
+ * The following defines the watchdog chains which are managed
+ * on ticks and second boundaries.
+ */
+
+SCORE_EXTERN Chain_Control _Watchdog_Ticks_chain;
+SCORE_EXTERN Chain_Control _Watchdog_Seconds_chain;
+
+/*
+ * _Watchdog_Handler_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine initializes the watchdog handler. The watchdog
+ * synchronization flag is initialized and the watchdog chains are
+ * initialized and emptied.
+ */
+
+void _Watchdog_Handler_initialization( void );
+
+/*
+ * _Watchdog_Remove
+ *
+ * DESCRIPTION:
+ *
+ * This routine removes THE_WATCHDOG from the watchdog chain on which
+ * it resides and returns the state THE_WATCHDOG timer was in.
+ */
+
+Watchdog_States _Watchdog_Remove (
+ Watchdog_Control *the_watchdog
+);
+
+/*
+ * _Watchdog_Adjust
+ *
+ * DESCRIPTION:
+ *
+ * This routine adjusts the HEADER watchdog chain in the forward
+ * or backward DIRECTION for UNITS ticks.
+ */
+
+void _Watchdog_Adjust (
+ Chain_Control *header,
+ Watchdog_Adjust_directions direction,
+ Watchdog_Interval units
+);
+
+/*
+ * _Watchdog_Insert
+ *
+ * DESCRIPTION:
+ *
+ * This routine inserts THE_WATCHDOG into the HEADER watchdog chain
+ * for a time of UNITS. The INSERT_MODE indicates whether
+ * THE_WATCHDOG is to be activated automatically or later, explicitly
+ * by the caller.
+ *
+ */
+
+void _Watchdog_Insert (
+ Chain_Control *header,
+ Watchdog_Control *the_watchdog
+);
+
+/*
+ * _Watchdog_Tickle
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked at appropriate intervals to update
+ * the HEADER watchdog chain.
+ */
+
+void _Watchdog_Tickle (
+ Chain_Control *header
+);
+
+#ifndef __RTEMS_APPLICATION__
+#include <rtems/score/watchdog.inl>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/include/rtems/score/wkspace.h b/cpukit/score/include/rtems/score/wkspace.h
new file mode 100644
index 0000000000..aff79c78d5
--- /dev/null
+++ b/cpukit/score/include/rtems/score/wkspace.h
@@ -0,0 +1,70 @@
+/* wkspace.h
+ *
+ * This include file contains information related to the
+ * RAM Workspace. This Handler provides mechanisms which can be used to
+ * define, initialize and manipulate the workspace.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __WORKSPACE_h
+#define __WORKSPACE_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems/score/heap.h>
+#include <rtems/score/interr.h>
+
+/*
+ * The following is used to manage the Workspace.
+ *
+ */
+
+SCORE_EXTERN Heap_Control _Workspace_Area; /* executive heap header */
+
+/*
+ * _Workspace_Handler_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this handler.
+ */
+
+void _Workspace_Handler_initialization(
+ void *starting_address,
+ uint32_t size
+);
+
+/*
+ * _Workspace_Allocate_or_fatal_error
+ *
+ * DESCRIPTION:
+ *
+ * This routine returns the address of a block of memory of size
+ * bytes. If a block of the appropriate size cannot be allocated
+ * from the workspace, then the internal error handler is invoked.
+ */
+
+void *_Workspace_Allocate_or_fatal_error(
+ uint32_t size
+);
+
+#ifndef __RTEMS_APPLICATION__
+#include <rtems/score/wkspace.inl>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/include/rtems/seterr.h b/cpukit/score/include/rtems/seterr.h
new file mode 100644
index 0000000000..d45345ba6d
--- /dev/null
+++ b/cpukit/score/include/rtems/seterr.h
@@ -0,0 +1,22 @@
+/*
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_SET_ERRNO_h
+#define __RTEMS_SET_ERRNO_h
+
+#define rtems_set_errno_and_return_minus_one( _error ) \
+ do { errno = (_error); return -1; } while(0)
+
+#define rtems_set_errno_and_return_minus_one_cast( _error, _cast ) \
+ do { errno = (_error); return (_cast) -1; } while(0)
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/include/rtems/system.h b/cpukit/score/include/rtems/system.h
new file mode 100644
index 0000000000..c2fbf7694b
--- /dev/null
+++ b/cpukit/score/include/rtems/system.h
@@ -0,0 +1,219 @@
+/* system.h
+ *
+ * This include file contains information that is included in every
+ * function in the executive. This must be the first include file
+ * included in all internal RTEMS files.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __RTEMS_SYSTEM_h
+#define __RTEMS_SYSTEM_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Major, minor, revision version numbers of RTEMS.
+ * Use these macros to test for features in specific releases.
+ */
+#define __RTEMS_MAJOR__ 4
+#define __RTEMS_MINOR__ 6
+#define __RTEMS_REVISION__ 0
+
+/*
+ * The cpu options include file defines all cpu dependent
+ * parameters for this build of RTEMS. It must be included
+ * first so the basic macro definitions are in place.
+ */
+
+#include <rtems/score/cpuopts.h>
+
+/*
+ * The following ensures that all data is declared in the space
+ * of the initialization routine for either the Initialization Manager
+ * or the initialization file for the appropriate API. It is
+ * referenced as "external" in every other file.
+ */
+
+#ifdef SCORE_INIT
+#undef SCORE_EXTERN
+#define SCORE_EXTERN
+#else
+#undef SCORE_EXTERN
+#define SCORE_EXTERN extern
+#endif
+
+#ifdef SAPI_INIT
+#undef SAPI_EXTERN
+#define SAPI_EXTERN
+#else
+#undef SAPI_EXTERN
+#define SAPI_EXTERN extern
+#endif
+
+#ifdef RTEMS_API_INIT
+#undef RTEMS_EXTERN
+#define RTEMS_EXTERN
+#else
+#undef RTEMS_EXTERN
+#define RTEMS_EXTERN extern
+#endif
+
+#ifdef POSIX_API_INIT
+#undef POSIX_EXTERN
+#define POSIX_EXTERN
+#else
+#undef POSIX_EXTERN
+#define POSIX_EXTERN extern
+#endif
+
+#ifdef ITRON_API_INIT
+#undef ITRON_EXTERN
+#define ITRON_EXTERN
+#else
+#undef ITRON_EXTERN
+#define ITRON_EXTERN extern
+#endif
+
+/*
+ * The following (in conjunction with compiler arguments) are used
+ * to choose between the use of static inline functions and macro
+ * functions. The static inline implementation allows better
+ * type checking with no cost in code size or execution speed.
+ */
+
+#ifdef RTEMS_INLINES
+# ifdef __GNUC__
+# define RTEMS_INLINE_ROUTINE static __inline__
+# else
+# define RTEMS_INLINE_ROUTINE static inline
+# endif
+#else
+# define RTEMS_INLINE_ROUTINE
+#endif
+
+/*
+ * The following are used by the POSIX implementation to catch bad paths.
+ */
+
+#ifdef RTEMS_POSIX_API
+int POSIX_MP_NOT_IMPLEMENTED( void );
+int POSIX_NOT_IMPLEMENTED( void );
+int POSIX_BOTTOM_REACHED( void );
+#endif
+
+/*
+ * Include a base set of files.
+ */
+
+/*
+ * XXX: Eventually proc_ptr needs to disappear!!!
+ */
+
+typedef void * proc_ptr;
+
+/*
+ * Define NULL
+ */
+
+#ifndef NULL
+#define NULL 0 /* NULL value */
+#endif
+
+/*
+ * Boolean constants
+ */
+
+#if !defined( TRUE ) || (TRUE != 1)
+#undef TRUE
+#define TRUE (1)
+#endif
+
+#if !defined( FALSE ) || (FALSE != 0)
+#undef FALSE
+#define FALSE (0)
+#endif
+
+#include <rtems/stdint.h>
+#include <rtems/score/cpu.h> /* processor specific information */
+
+#define stringify( _x ) # _x
+
+#define RTEMS_offsetof(type, field) \
+ ((uint32_t ) &(((type *) 0)->field))
+
+/*
+ * The following is the extern for the RTEMS version string.
+ * The contents of this string are CPU specific.
+ */
+
+extern const char _RTEMS_version[]; /* RTEMS version string */
+extern const char _Copyright_Notice[]; /* RTEMS copyright string */
+
+/*
+ * The following defines the CPU dependent information table.
+ */
+
+SCORE_EXTERN rtems_cpu_table _CPU_Table; /* CPU dependent info */
+
+/*
+ * Macros to access CPU Table fields required by ALL ports.
+ *
+ * NOTE: Similar macros to access port specific fields in in the
+ * appropriate cpu.h file.
+ */
+
+#define rtems_cpu_configuration_get_table() \
+ (&_CPU_Table)
+
+#define rtems_cpu_configuration_get_pretasking_hook() \
+ (_CPU_Table.pretasking_hook)
+
+#define rtems_cpu_configuration_get_predriver_hook() \
+ (_CPU_Table.predriver_hook)
+
+#define rtems_cpu_configuration_get_postdriver_hook() \
+ (_CPU_Table.postdriver_hook)
+
+#define rtems_cpu_configuration_get_idle_task() \
+ (_CPU_Table.idle_task)
+
+#define rtems_cpu_configuration_get_do_zero_of_workspace() \
+ (_CPU_Table.do_zero_of_workspace)
+
+#define rtems_cpu_configuration_get_idle_task_stack_size() \
+ (_CPU_Table.idle_task_stack_size)
+
+#define rtems_cpu_configuration_get_interrupt_stack_size() \
+ (_CPU_Table.interrupt_stack_size)
+
+#define rtems_cpu_configuration_get_extra_mpci_receive_server_stack() \
+ (_CPU_Table.extra_mpci_receive_server_stack)
+
+#define rtems_cpu_configuration_get_stack_allocate_hook() \
+ (_CPU_Table.stack_allocate_hook)
+
+#define rtems_cpu_configuration_get_stack_free_hook() \
+ (_CPU_Table.stack_free_hook)
+
+/*
+ * XXX weird RTEMS stuff that probably should be somewhere else.
+ */
+
+#define RTEMS_MAXIMUM_NAME_LENGTH sizeof(rtems_name)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/inline/rtems/score/address.inl b/cpukit/score/inline/rtems/score/address.inl
new file mode 100644
index 0000000000..28fa7f5c77
--- /dev/null
+++ b/cpukit/score/inline/rtems/score/address.inl
@@ -0,0 +1,125 @@
+/* inline/address.inl
+ *
+ * This include file contains the bodies of the routines
+ * about addresses which are inlined.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __INLINE_ADDRESSES_inl
+#define __INLINE_ADDRESSES_inl
+
+/*PAGE
+ *
+ * _Addresses_Add_offset
+ *
+ * DESCRIPTION:
+ *
+ * This function is used to add an offset to a base address.
+ * It returns the resulting address. This address is typically
+ * converted to an access type before being used further.
+ */
+
+RTEMS_INLINE_ROUTINE void *_Addresses_Add_offset (
+ void *base,
+ uint32_t offset
+)
+{
+ return (void *)((char *)base + offset);
+}
+
+/*PAGE
+ *
+ * _Addresses_Subtract_offset
+ *
+ * DESCRIPTION:
+ *
+ * This function is used to subtract an offset from a base
+ * address. It returns the resulting address. This address is
+ * typically converted to an access type before being used further.
+ */
+
+RTEMS_INLINE_ROUTINE void *_Addresses_Subtract_offset (
+ void *base,
+ uint32_t offset
+)
+{
+ return (void *)((char *)base - offset);
+}
+
+/*PAGE
+ *
+ * _Addresses_Subtract
+ *
+ * DESCRIPTION:
+ *
+ * This function is used to subtract two addresses. It returns the
+ * resulting offset.
+ *
+ * NOTE: The cast of an address to an uint32_t makes this code
+ * dependent on an addresses being thirty two bits.
+ */
+
+RTEMS_INLINE_ROUTINE uint32_t _Addresses_Subtract (
+ void *left,
+ void *right
+)
+{
+ return ((char *) left - (char *) right);
+}
+
+/*PAGE
+ *
+ * _Addresses_Is_aligned
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the given address is correctly
+ * aligned for this processor and FALSE otherwise. Proper alignment
+ * is based on correctness and efficiency.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Addresses_Is_aligned (
+ void *address
+)
+{
+#if (CPU_ALIGNMENT == 0)
+ return TRUE;
+#elif defined(RTEMS_CPU_HAS_16_BIT_ADDRESSES)
+ return ( ( (unsigned short)address % CPU_ALIGNMENT ) == 0 );
+#else
+ return ( ( (uint32_t )address % CPU_ALIGNMENT ) == 0 );
+#endif
+}
+
+/*PAGE
+ *
+ * _Addresses_Is_in_range
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the given address is within the
+ * memory range specified and FALSE otherwise. base is the address
+ * of the first byte in the memory range and limit is the address
+ * of the last byte in the memory range. The base address is
+ * assumed to be lower than the limit address.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Addresses_Is_in_range (
+ void *address,
+ void *base,
+ void *limit
+)
+{
+ return ( address >= base && address <= limit );
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/inline/rtems/score/chain.inl b/cpukit/score/inline/rtems/score/chain.inl
new file mode 100644
index 0000000000..8f9c68389d
--- /dev/null
+++ b/cpukit/score/inline/rtems/score/chain.inl
@@ -0,0 +1,389 @@
+/* inline/chain.inl
+ *
+ * This include file contains the bodies of the routines which are
+ * associated with doubly linked chains and inlined.
+ *
+ * NOTE: The routines in this file are ordered from simple
+ * to complex. No other Chain Handler routine is referenced
+ * unless it has already been defined.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __INLINE_CHAIN_inl
+#define __INLINE_CHAIN_inl
+
+/*PAGE
+ *
+ * _Chain_Are_nodes_equal
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if LEFT and RIGHT are equal,
+ * and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Chain_Are_nodes_equal(
+ Chain_Node *left,
+ Chain_Node *right
+)
+{
+ return left == right;
+}
+
+/*PAGE
+ *
+ * _Chain_Is_null
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_chain is NULL and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Chain_Is_null(
+ Chain_Control *the_chain
+)
+{
+ return ( the_chain == NULL );
+}
+
+/*PAGE
+ *
+ * _Chain_Is_null_node
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_node is NULL and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Chain_Is_null_node(
+ Chain_Node *the_node
+)
+{
+ return ( the_node == NULL );
+}
+
+/*PAGE
+ *
+ * _Chain_Head
+ *
+ * DESCRIPTION:
+ *
+ * This function returns a pointer to the first node on the chain.
+ */
+
+RTEMS_INLINE_ROUTINE Chain_Node *_Chain_Head(
+ Chain_Control *the_chain
+)
+{
+ return (Chain_Node *) the_chain;
+}
+
+/*PAGE
+ *
+ * _Chain_Tail
+ *
+ * DESCRIPTION:
+ *
+ * This function returns a pointer to the last node on the chain.
+ */
+
+RTEMS_INLINE_ROUTINE Chain_Node *_Chain_Tail(
+ Chain_Control *the_chain
+)
+{
+ return (Chain_Node *) &the_chain->permanent_null;
+}
+
+/*PAGE
+ *
+ * _Chain_Is_empty
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if there a no nodes on the_chain and
+ * FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Chain_Is_empty(
+ Chain_Control *the_chain
+)
+{
+ return ( the_chain->first == _Chain_Tail( the_chain ) );
+}
+
+/*PAGE
+ *
+ * _Chain_Is_first
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_node is the first node on a chain and
+ * FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Chain_Is_first(
+ Chain_Node *the_node
+)
+{
+ return ( the_node->previous == NULL );
+}
+
+/*PAGE
+ *
+ * _Chain_Is_last
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_node is the last node on a chain and
+ * FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Chain_Is_last(
+ Chain_Node *the_node
+)
+{
+ return ( the_node->next == NULL );
+}
+
+/*PAGE
+ *
+ * _Chain_Has_only_one_node
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if there is only one node on the_chain and
+ * FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Chain_Has_only_one_node(
+ Chain_Control *the_chain
+)
+{
+ return ( the_chain->first == the_chain->last );
+}
+
+/*PAGE
+ *
+ * _Chain_Is_head
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_node is the head of the_chain and
+ * FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Chain_Is_head(
+ Chain_Control *the_chain,
+ Chain_Node *the_node
+)
+{
+ return ( the_node == _Chain_Head( the_chain ) );
+}
+
+/*PAGE
+ *
+ * _Chain_Is_tail
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_node is the tail of the_chain and
+ * FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Chain_Is_tail(
+ Chain_Control *the_chain,
+ Chain_Node *the_node
+)
+{
+ return ( the_node == _Chain_Tail( the_chain ) );
+}
+
+/*PAGE
+ *
+ * Chain_Initialize_empty
+ *
+ * DESCRIPTION:
+ *
+ * This routine initializes the specified chain to contain zero nodes.
+ */
+
+RTEMS_INLINE_ROUTINE void _Chain_Initialize_empty(
+ Chain_Control *the_chain
+)
+{
+ the_chain->first = _Chain_Tail( the_chain );
+ the_chain->permanent_null = NULL;
+ the_chain->last = _Chain_Head( the_chain );
+}
+
+/*PAGE
+ *
+ * _Chain_Extract_unprotected
+ *
+ * DESCRIPTION:
+ *
+ * This routine extracts the_node from the chain on which it resides.
+ * It does NOT disable interrupts to insure the atomicity of the
+ * extract operation.
+ */
+
+RTEMS_INLINE_ROUTINE void _Chain_Extract_unprotected(
+ Chain_Node *the_node
+)
+{
+ Chain_Node *next;
+ Chain_Node *previous;
+
+ next = the_node->next;
+ previous = the_node->previous;
+ next->previous = previous;
+ previous->next = next;
+}
+
+/*PAGE
+ *
+ * _Chain_Get_first_unprotected
+ *
+ * DESCRIPTION:
+ *
+ * This function removes the first node from the_chain and returns
+ * a pointer to that node. It does NOT disable interrupts to insure
+ * the atomicity of the get operation.
+ */
+
+RTEMS_INLINE_ROUTINE Chain_Node *_Chain_Get_first_unprotected(
+ Chain_Control *the_chain
+)
+{
+ Chain_Node *return_node;
+ Chain_Node *new_first;
+
+ return_node = the_chain->first;
+ new_first = return_node->next;
+ the_chain->first = new_first;
+ new_first->previous = _Chain_Head( the_chain );
+
+ return return_node;
+}
+
+/*PAGE
+ *
+ * Chain_Get_unprotected
+ *
+ * DESCRIPTION:
+ *
+ * This function removes the first node from the_chain and returns
+ * a pointer to that node. If the_chain is empty, then NULL is returned.
+ * It does NOT disable interrupts to insure the atomicity of the
+ * get operation.
+ */
+
+RTEMS_INLINE_ROUTINE Chain_Node *_Chain_Get_unprotected(
+ Chain_Control *the_chain
+)
+{
+ if ( !_Chain_Is_empty( the_chain ) )
+ return _Chain_Get_first_unprotected( the_chain );
+ else
+ return NULL;
+}
+
+/*PAGE
+ *
+ * _Chain_Insert_unprotected
+ *
+ * DESCRIPTION:
+ *
+ * This routine inserts the_node on a chain immediately following
+ * after_node. It does NOT disable interrupts to insure the atomicity
+ * of the extract operation.
+ */
+
+RTEMS_INLINE_ROUTINE void _Chain_Insert_unprotected(
+ Chain_Node *after_node,
+ Chain_Node *the_node
+)
+{
+ Chain_Node *before_node;
+
+ the_node->previous = after_node;
+ before_node = after_node->next;
+ after_node->next = the_node;
+ the_node->next = before_node;
+ before_node->previous = the_node;
+}
+
+/*PAGE
+ *
+ * _Chain_Append_unprotected
+ *
+ * DESCRIPTION:
+ *
+ * This routine appends the_node onto the end of the_chain.
+ * It does NOT disable interrupts to insure the atomicity of the
+ * append operation.
+ */
+
+RTEMS_INLINE_ROUTINE void _Chain_Append_unprotected(
+ Chain_Control *the_chain,
+ Chain_Node *the_node
+)
+{
+ Chain_Node *old_last_node;
+
+ the_node->next = _Chain_Tail( the_chain );
+ old_last_node = the_chain->last;
+ the_chain->last = the_node;
+ old_last_node->next = the_node;
+ the_node->previous = old_last_node;
+}
+
+/*PAGE
+ *
+ * _Chain_Prepend_unprotected
+ *
+ * DESCRIPTION:
+ *
+ * This routine prepends the_node onto the front of the_chain.
+ * It does NOT disable interrupts to insure the atomicity of the
+ * prepend operation.
+ */
+
+RTEMS_INLINE_ROUTINE void _Chain_Prepend_unprotected(
+ Chain_Control *the_chain,
+ Chain_Node *the_node
+)
+{
+ _Chain_Insert_unprotected( _Chain_Head( the_chain ), the_node );
+
+}
+
+/*PAGE
+ *
+ * _Chain_Prepend
+ *
+ * DESCRIPTION:
+ *
+ * This routine prepends the_node onto the front of the_chain.
+ * It disables interrupts to insure the atomicity of the
+ * prepend operation.
+ */
+
+RTEMS_INLINE_ROUTINE void _Chain_Prepend(
+ Chain_Control *the_chain,
+ Chain_Node *the_node
+)
+{
+ _Chain_Insert( _Chain_Head( the_chain ), the_node );
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/inline/rtems/score/coremsg.inl b/cpukit/score/inline/rtems/score/coremsg.inl
new file mode 100644
index 0000000000..7d152aec6b
--- /dev/null
+++ b/cpukit/score/inline/rtems/score/coremsg.inl
@@ -0,0 +1,275 @@
+/* coremsg.inl
+ *
+ * This include file contains the static inline implementation of all
+ * inlined routines in the Core Message Handler.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __CORE_MESSAGE_QUEUE_inl
+#define __CORE_MESSAGE_QUEUE_inl
+
+#include <string.h> /* needed for memcpy */
+
+/*PAGE
+ *
+ * _CORE_message_queue_Send
+ *
+ * DESCRIPTION:
+ *
+ * This routine sends a message to the end of the specified message queue.
+ */
+
+RTEMS_INLINE_ROUTINE CORE_message_queue_Status _CORE_message_queue_Send(
+ CORE_message_queue_Control *the_message_queue,
+ void *buffer,
+ uint32_t size,
+ Objects_Id id,
+ CORE_message_queue_API_mp_support_callout api_message_queue_mp_support,
+ boolean wait,
+ Watchdog_Interval timeout
+)
+{
+ return _CORE_message_queue_Submit(
+ the_message_queue,
+ buffer,
+ size,
+ id,
+#if defined(RTEMS_MULTIPROCESSING)
+ api_message_queue_mp_support,
+#else
+ NULL,
+#endif
+ CORE_MESSAGE_QUEUE_SEND_REQUEST,
+ wait, /* sender may block */
+ timeout /* timeout interval */
+ );
+}
+
+/*PAGE
+ *
+ * _CORE_message_queue_Urgent
+ *
+ * DESCRIPTION:
+ *
+ * This routine sends a message to the front of the specified message queue.
+ */
+
+RTEMS_INLINE_ROUTINE CORE_message_queue_Status _CORE_message_queue_Urgent(
+ CORE_message_queue_Control *the_message_queue,
+ void *buffer,
+ uint32_t size,
+ Objects_Id id,
+ CORE_message_queue_API_mp_support_callout api_message_queue_mp_support,
+ boolean wait,
+ Watchdog_Interval timeout
+)
+{
+ return _CORE_message_queue_Submit(
+ the_message_queue,
+ buffer,
+ size,
+ id,
+#if defined(RTEMS_MULTIPROCESSING)
+ api_message_queue_mp_support,
+#else
+ NULL,
+#endif
+ CORE_MESSAGE_QUEUE_URGENT_REQUEST,
+ wait, /* sender may block */
+ timeout /* timeout interval */
+ );
+}
+
+/*PAGE
+ *
+ * _CORE_message_queue_Copy_buffer
+ *
+ * DESCRIPTION:
+ *
+ * This routine copies the contents of the source message buffer
+ * to the destination message buffer.
+ */
+
+RTEMS_INLINE_ROUTINE void _CORE_message_queue_Copy_buffer (
+ void *source,
+ void *destination,
+ uint32_t size
+)
+{
+ memcpy(destination, source, size);
+}
+
+/*PAGE
+ *
+ * _CORE_message_queue_Allocate_message_buffer
+ *
+ * DESCRIPTION:
+ *
+ * This function allocates a message buffer from the inactive
+ * message buffer chain.
+ */
+
+RTEMS_INLINE_ROUTINE CORE_message_queue_Buffer_control *
+_CORE_message_queue_Allocate_message_buffer (
+ CORE_message_queue_Control *the_message_queue
+)
+{
+ return (CORE_message_queue_Buffer_control *)
+ _Chain_Get( &the_message_queue->Inactive_messages );
+}
+
+/*PAGE
+ *
+ * _CORE_message_queue_Free_message_buffer
+ *
+ * DESCRIPTION:
+ *
+ * This routine frees a message buffer to the inactive
+ * message buffer chain.
+ */
+
+RTEMS_INLINE_ROUTINE void _CORE_message_queue_Free_message_buffer (
+ CORE_message_queue_Control *the_message_queue,
+ CORE_message_queue_Buffer_control *the_message
+)
+{
+ _Chain_Append( &the_message_queue->Inactive_messages, &the_message->Node );
+}
+
+/*PAGE
+ *
+ * _CORE_message_queue_Get_pending_message
+ *
+ * DESCRIPTION:
+ *
+ * This function removes the first message from the_message_queue
+ * and returns a pointer to it.
+ */
+
+RTEMS_INLINE_ROUTINE
+ CORE_message_queue_Buffer_control *_CORE_message_queue_Get_pending_message (
+ CORE_message_queue_Control *the_message_queue
+)
+{
+ return (CORE_message_queue_Buffer_control *)
+ _Chain_Get_unprotected( &the_message_queue->Pending_messages );
+}
+
+/*PAGE
+ *
+ * _CORE_message_queue_Is_priority
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the priority attribute is
+ * enabled in the attribute_set and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _CORE_message_queue_Is_priority(
+ CORE_message_queue_Attributes *the_attribute
+)
+{
+ return (the_attribute->discipline == CORE_MESSAGE_QUEUE_DISCIPLINES_PRIORITY);
+}
+
+/*PAGE
+ *
+ * _CORE_message_queue_Append
+ *
+ * DESCRIPTION:
+ *
+ * This routine places the_message at the rear of the outstanding
+ * messages on the_message_queue.
+ */
+
+RTEMS_INLINE_ROUTINE void _CORE_message_queue_Append (
+ CORE_message_queue_Control *the_message_queue,
+ CORE_message_queue_Buffer_control *the_message
+)
+{
+ _Chain_Append( &the_message_queue->Pending_messages, &the_message->Node );
+}
+
+/*PAGE
+ *
+ * _CORE_message_queue_Prepend
+ *
+ * DESCRIPTION:
+ *
+ * This routine places the_message at the front of the outstanding
+ * messages on the_message_queue.
+ */
+
+RTEMS_INLINE_ROUTINE void _CORE_message_queue_Prepend (
+ CORE_message_queue_Control *the_message_queue,
+ CORE_message_queue_Buffer_control *the_message
+)
+{
+ _Chain_Prepend(
+ &the_message_queue->Pending_messages,
+ &the_message->Node
+ );
+}
+
+/*PAGE
+ *
+ * _CORE_message_queue_Is_null
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_message_queue is TRUE and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _CORE_message_queue_Is_null (
+ CORE_message_queue_Control *the_message_queue
+)
+{
+ return ( the_message_queue == NULL );
+}
+
+/*PAGE
+ *
+ * _CORE_message_queue_Is_notify_enabled
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if notification is enabled on this message
+ * queue and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _CORE_message_queue_Is_notify_enabled (
+ CORE_message_queue_Control *the_message_queue
+)
+{
+ return (the_message_queue->notify_handler != NULL);
+}
+
+/*PAGE
+ *
+ * _CORE_message_queue_Set_notify
+ *
+ * DESCRIPTION:
+ *
+ * This routine initializes the notification information for the_message_queue.
+ */
+
+RTEMS_INLINE_ROUTINE void _CORE_message_queue_Set_notify (
+ CORE_message_queue_Control *the_message_queue,
+ CORE_message_queue_Notify_Handler the_handler,
+ void *the_argument
+)
+{
+ the_message_queue->notify_handler = the_handler;
+ the_message_queue->notify_argument = the_argument;
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/inline/rtems/score/coremutex.inl b/cpukit/score/inline/rtems/score/coremutex.inl
new file mode 100644
index 0000000000..2d884b79f9
--- /dev/null
+++ b/cpukit/score/inline/rtems/score/coremutex.inl
@@ -0,0 +1,196 @@
+/* inline/coremutex.inl
+ *
+ * This include file contains all of the inlined routines associated
+ * with the CORE mutexes.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __INLINE_CORE_MUTEX_inl
+#define __INLINE_CORE_MUTEX_inl
+
+/*PAGE
+ *
+ * _CORE_mutex_Is_locked
+ *
+ * DESCRIPTION:
+ *
+ * This routine returns TRUE if the mutex specified is locked and FALSE
+ * otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _CORE_mutex_Is_locked(
+ CORE_mutex_Control *the_mutex
+)
+{
+ return the_mutex->lock == CORE_MUTEX_LOCKED;
+}
+
+/*PAGE
+ *
+ * _CORE_mutex_Is_fifo
+ *
+ * DESCRIPTION:
+ *
+ * This routine returns TRUE if the mutex's wait discipline is FIFO and FALSE
+ * otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _CORE_mutex_Is_fifo(
+ CORE_mutex_Attributes *the_attribute
+)
+{
+ return the_attribute->discipline == CORE_MUTEX_DISCIPLINES_FIFO;
+}
+
+/*PAGE
+ *
+ * _CORE_mutex_Is_priority
+ *
+ * DESCRIPTION:
+ *
+ * This routine returns TRUE if the mutex's wait discipline is PRIORITY and
+ * FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _CORE_mutex_Is_priority(
+ CORE_mutex_Attributes *the_attribute
+)
+{
+ return the_attribute->discipline == CORE_MUTEX_DISCIPLINES_PRIORITY;
+}
+
+/*PAGE
+ *
+ * _CORE_mutex_Is_inherit_priority
+ *
+ * DESCRIPTION:
+ *
+ * This routine returns TRUE if the mutex's wait discipline is
+ * INHERIT_PRIORITY and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _CORE_mutex_Is_inherit_priority(
+ CORE_mutex_Attributes *the_attribute
+)
+{
+ return the_attribute->discipline == CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT;
+}
+
+/*PAGE
+ *
+ * _CORE_mutex_Is_priority_ceiling
+ *
+ * DESCRIPTION:
+ *
+ * This routine returns TRUE if the mutex's wait discipline is
+ * PRIORITY_CEILING and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _CORE_mutex_Is_priority_ceiling(
+ CORE_mutex_Attributes *the_attribute
+)
+{
+ return the_attribute->discipline == CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING;
+}
+
+/*PAGE
+ *
+ * _CORE_mutex_Seize_interrupt_trylock
+ *
+ * DESCRIPTION:
+ *
+ * This routine returns 0 if "trylock" can resolve whether or not the
+ * mutex is immediately obtained or there was an error attempting to
+ * get it. It returns 1 to indicate that the caller cannot obtain
+ * the mutex and will have to block to do so.
+ *
+ * NOTE: There is no MACRO version of this routine.
+ * A body is in coremutexseize.c that is duplicated
+ * from the .inl by hand.
+ */
+
+RTEMS_INLINE_ROUTINE int _CORE_mutex_Seize_interrupt_trylock(
+ CORE_mutex_Control *the_mutex,
+ ISR_Level *level_p
+)
+{
+ Thread_Control *executing;
+ ISR_Level level = *level_p;
+
+ /* disabled when you get here */
+
+ executing = _Thread_Executing;
+ executing->Wait.return_code = CORE_MUTEX_STATUS_SUCCESSFUL;
+ if ( !_CORE_mutex_Is_locked( the_mutex ) ) {
+ the_mutex->lock = CORE_MUTEX_LOCKED;
+ the_mutex->holder = executing;
+ the_mutex->holder_id = executing->Object.id;
+ the_mutex->nest_count = 1;
+ if ( _CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) ||
+ _CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) )
+ executing->resource_count++;
+ if ( !_CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) ) {
+ _ISR_Enable( level );
+ return 0;
+ }
+ /* else must be CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING */
+ {
+ Priority_Control ceiling;
+ Priority_Control current;
+
+ ceiling = the_mutex->Attributes.priority_ceiling;
+ current = executing->current_priority;
+ if ( current == ceiling ) {
+ _ISR_Enable( level );
+ return 0;
+ }
+ if ( current > ceiling ) {
+ _Thread_Disable_dispatch();
+ _ISR_Enable( level );
+ _Thread_Change_priority(
+ the_mutex->holder,
+ the_mutex->Attributes.priority_ceiling,
+ FALSE
+ );
+ _Thread_Enable_dispatch();
+ return 0;
+ }
+ /* if ( current < ceiling ) */ {
+ executing->Wait.return_code = CORE_MUTEX_STATUS_CEILING_VIOLATED;
+ the_mutex->nest_count = 0; /* undo locking above */
+ executing->resource_count--; /* undo locking above */
+ _ISR_Enable( level );
+ return 0;
+ }
+ }
+ return 0;
+ }
+
+ if ( _Thread_Is_executing( the_mutex->holder ) ) {
+ switch ( the_mutex->Attributes.lock_nesting_behavior ) {
+ case CORE_MUTEX_NESTING_ACQUIRES:
+ the_mutex->nest_count++;
+ _ISR_Enable( level );
+ return 0;
+ case CORE_MUTEX_NESTING_IS_ERROR:
+ executing->Wait.return_code = CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED;
+ _ISR_Enable( level );
+ return 0;
+ case CORE_MUTEX_NESTING_BLOCKS:
+ break;
+ }
+ }
+
+ return 1;
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/inline/rtems/score/coresem.inl b/cpukit/score/inline/rtems/score/coresem.inl
new file mode 100644
index 0000000000..4c39764e23
--- /dev/null
+++ b/cpukit/score/inline/rtems/score/coresem.inl
@@ -0,0 +1,107 @@
+/* inline/coresem.inl
+ *
+ * This include file contains all of the inlined routines associated
+ * with the CORE semaphore.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __INLINE_CORE_SEMAPHORE_inl
+#define __INLINE_CORE_SEMAPHORE_inl
+
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+
+/*PAGE
+ *
+ * _CORE_semaphore_Is_priority
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the priority attribute is
+ * enabled in the attribute_set and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _CORE_semaphore_Is_priority(
+ CORE_semaphore_Attributes *the_attribute
+)
+{
+ return ( the_attribute->discipline == CORE_SEMAPHORE_DISCIPLINES_PRIORITY );
+}
+
+/*PAGE
+ *
+ * _CORE_semaphore_Get_count
+ *
+ * DESCRIPTION:
+ *
+ * This routine returns the current count associated with the semaphore.
+ */
+
+RTEMS_INLINE_ROUTINE uint32_t _CORE_semaphore_Get_count(
+ CORE_semaphore_Control *the_semaphore
+)
+{
+ return the_semaphore->count;
+}
+
+/*PAGE
+ *
+ * _CORE_semaphore_Seize_isr_disable
+ *
+ * DESCRIPTION:
+ *
+ * This routine attempts to receive a unit from the_semaphore.
+ * If a unit is available or if the wait flag is FALSE, then the routine
+ * returns. Otherwise, the calling task is blocked until a unit becomes
+ * available.
+ *
+ * NOTE: There is currently no MACRO version of this routine.
+ */
+
+RTEMS_INLINE_ROUTINE void _CORE_semaphore_Seize_isr_disable(
+ CORE_semaphore_Control *the_semaphore,
+ Objects_Id id,
+ boolean wait,
+ Watchdog_Interval timeout,
+ ISR_Level *level_p
+)
+{
+ Thread_Control *executing;
+ ISR_Level level = *level_p;
+
+ /* disabled when you get here */
+
+ executing = _Thread_Executing;
+ executing->Wait.return_code = CORE_SEMAPHORE_STATUS_SUCCESSFUL;
+ if ( the_semaphore->count != 0 ) {
+ the_semaphore->count -= 1;
+ _ISR_Enable( level );
+ return;
+ }
+
+ if ( !wait ) {
+ _ISR_Enable( level );
+ executing->Wait.return_code = CORE_SEMAPHORE_STATUS_UNSATISFIED_NOWAIT;
+ return;
+ }
+
+ _Thread_Disable_dispatch();
+ _Thread_queue_Enter_critical_section( &the_semaphore->Wait_queue );
+ executing->Wait.queue = &the_semaphore->Wait_queue;
+ executing->Wait.id = id;
+ _ISR_Enable( level );
+
+ _Thread_queue_Enqueue( &the_semaphore->Wait_queue, timeout );
+ _Thread_Enable_dispatch();
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/inline/rtems/score/heap.inl b/cpukit/score/inline/rtems/score/heap.inl
new file mode 100644
index 0000000000..ae41cf6244
--- /dev/null
+++ b/cpukit/score/inline/rtems/score/heap.inl
@@ -0,0 +1,273 @@
+/* heap.inl
+ *
+ * This file contains the static inline implementation of the inlined
+ * routines from the heap handler.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __HEAP_inl
+#define __HEAP_inl
+
+#include <rtems/score/address.h>
+
+/*PAGE
+ *
+ * _Heap_Head
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the head of the specified heap.
+ */
+
+RTEMS_INLINE_ROUTINE Heap_Block *_Heap_Head (
+ Heap_Control *the_heap
+)
+{
+ return (Heap_Block *)&the_heap->start;
+}
+
+/*PAGE
+ *
+ * _Heap_Tail
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the tail of the specified heap.
+ */
+
+RTEMS_INLINE_ROUTINE Heap_Block *_Heap_Tail (
+ Heap_Control *the_heap
+)
+{
+ return (Heap_Block *)&the_heap->final;
+}
+
+/*PAGE
+ *
+ * _Heap_Previous_block
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the address of the block which physically
+ * precedes the_block in memory.
+ */
+
+RTEMS_INLINE_ROUTINE Heap_Block *_Heap_Previous_block (
+ Heap_Block *the_block
+)
+{
+ return (Heap_Block *) _Addresses_Subtract_offset(
+ (void *)the_block,
+ the_block->back_flag & ~ HEAP_BLOCK_USED
+ );
+}
+
+/*PAGE
+ *
+ * _Heap_Next_block
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the address of the block which physically
+ * follows the_block in memory.
+ *
+ * NOTE: Next_block assumes that the block is free.
+ */
+
+RTEMS_INLINE_ROUTINE Heap_Block *_Heap_Next_block (
+ Heap_Block *the_block
+)
+{
+ return (Heap_Block *) _Addresses_Add_offset(
+ (void *)the_block,
+ the_block->front_flag & ~ HEAP_BLOCK_USED
+ );
+}
+
+/*PAGE
+ *
+ * _Heap_Block_at
+ *
+ * DESCRIPTION:
+ *
+ * This function calculates and returns a block's location (address)
+ * in the heap based upon a base address and an offset.
+ */
+
+RTEMS_INLINE_ROUTINE Heap_Block *_Heap_Block_at(
+ void *base,
+ uint32_t offset
+)
+{
+ return (Heap_Block *) _Addresses_Add_offset( (void *)base, offset );
+}
+
+/*PAGE
+ *
+ * _Heap_User_block_at
+ *
+ * DESCRIPTION:
+ *
+ * XXX
+ */
+
+RTEMS_INLINE_ROUTINE Heap_Block *_Heap_User_block_at(
+ void *base
+)
+{
+ uint32_t offset;
+
+ offset = *(((uint32_t *) base) - 1);
+ return _Heap_Block_at( base, -offset + -HEAP_BLOCK_USED_OVERHEAD);
+}
+
+/*PAGE
+ *
+ * _Heap_Is_previous_block_free
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the previous block of the_block
+ * is free, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Heap_Is_previous_block_free (
+ Heap_Block *the_block
+)
+{
+ return !(the_block->back_flag & HEAP_BLOCK_USED);
+}
+
+/*PAGE
+ *
+ * _Heap_Is_block_free
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the block is free, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Heap_Is_block_free (
+ Heap_Block *the_block
+)
+{
+ return !(the_block->front_flag & HEAP_BLOCK_USED);
+}
+
+/*PAGE
+ *
+ * _Heap_Is_block_used
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the block is currently allocated,
+ * and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Heap_Is_block_used (
+ Heap_Block *the_block
+)
+{
+ return (the_block->front_flag & HEAP_BLOCK_USED);
+}
+
+/*PAGE
+ *
+ * _Heap_Block_size
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the size of the_block in bytes.
+ */
+
+RTEMS_INLINE_ROUTINE uint32_t _Heap_Block_size (
+ Heap_Block *the_block
+)
+{
+ return (the_block->front_flag & ~HEAP_BLOCK_USED);
+}
+
+/*PAGE
+ *
+ * _Heap_Start_of_user_area
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the starting address of the portion of the block
+ * which the user may access.
+ */
+
+RTEMS_INLINE_ROUTINE void *_Heap_Start_of_user_area (
+ Heap_Block *the_block
+)
+{
+ return (void *) &the_block->next;
+}
+
+/*PAGE
+ *
+ * _Heap_Is_block_in
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_block is within the memory area
+ * managed by the_heap, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Heap_Is_block_in (
+ Heap_Control *the_heap,
+ Heap_Block *the_block
+)
+{
+ return _Addresses_Is_in_range( the_block, the_heap->start, the_heap->final );
+}
+
+/*PAGE
+ *
+ * _Heap_Is_page_size_valid
+ *
+ * DESCRIPTION:
+ *
+ * This function validates a specified heap page size. If the page size
+ * is 0 or if lies outside a page size alignment boundary it is invalid
+ * and FALSE is returned. Otherwise, the page size is valid and TRUE is
+ * returned.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Heap_Is_page_size_valid(
+ uint32_t page_size
+)
+{
+ return ((page_size != 0) &&
+ ((page_size % CPU_HEAP_ALIGNMENT) == 0));
+}
+
+/*PAGE
+ *
+ * _Heap_Build_flag
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the block flag composed of size and in_use_flag.
+ * The flag returned is suitable for use as a back or front flag in a
+ * heap block.
+ */
+
+RTEMS_INLINE_ROUTINE uint32_t _Heap_Build_flag (
+ uint32_t size,
+ uint32_t in_use_flag
+)
+{
+ return size | in_use_flag;
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/inline/rtems/score/isr.inl b/cpukit/score/inline/rtems/score/isr.inl
new file mode 100644
index 0000000000..637098b297
--- /dev/null
+++ b/cpukit/score/inline/rtems/score/isr.inl
@@ -0,0 +1,55 @@
+/* isr.inl
+ *
+ * This include file contains the static implementation of all
+ * inlined routines in the Interrupt Handler.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ISR_inl
+#define __ISR_inl
+
+/*PAGE
+ *
+ * _ISR_Is_vector_number_valid
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the vector is a valid vector number
+ * for this processor and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _ISR_Is_vector_number_valid (
+ uint32_t vector
+)
+{
+ return ( vector <= CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER );
+}
+
+/*PAGE
+ *
+ * _ISR_Is_valid_user_handler
+ *
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if handler is the entry point of a valid
+ * use interrupt service routine and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _ISR_Is_valid_user_handler (
+ void *handler
+)
+{
+ return ( handler != NULL);
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/inline/rtems/score/mppkt.inl b/cpukit/score/inline/rtems/score/mppkt.inl
new file mode 100644
index 0000000000..a26713776d
--- /dev/null
+++ b/cpukit/score/inline/rtems/score/mppkt.inl
@@ -0,0 +1,57 @@
+/* inline/mppkt.inl
+ *
+ * This package is the implementation of the Packet Handler
+ * routines which are inlined.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __INLINE_MP_PACKET_inl
+#define __INLINE_MP_PACKET_inl
+
+/*PAGE
+ *
+ * _Mp_packet_Is_valid_packet_class
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the the_packet_class is valid,
+ * and FALSE otherwise.
+ *
+ * NOTE: Check for lower bounds (MP_PACKET_CLASSES_FIRST ) is unnecessary
+ * because this enum starts at lower bound of zero.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Mp_packet_Is_valid_packet_class (
+ MP_packet_Classes the_packet_class
+)
+{
+ return ( the_packet_class <= MP_PACKET_CLASSES_LAST );
+}
+
+/*PAGE
+ *
+ * _Mp_packet_Is_null
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the the_packet_class is null,
+ * and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Mp_packet_Is_null (
+ MP_packet_Prefix *the_packet
+)
+{
+ return the_packet == NULL;
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/inline/rtems/score/object.inl b/cpukit/score/inline/rtems/score/object.inl
new file mode 100644
index 0000000000..fa2c0478e5
--- /dev/null
+++ b/cpukit/score/inline/rtems/score/object.inl
@@ -0,0 +1,315 @@
+/* object.inl
+ *
+ * This include file contains the static inline implementation of all
+ * of the inlined routines in the Object Handler.
+ *
+ * COPYRIGHT (c) 1989-2002.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __OBJECTS_inl
+#define __OBJECTS_inl
+
+/*PAGE
+ *
+ * _Objects_Build_id
+ *
+ * DESCRIPTION:
+ *
+ * This function builds an object's id from the processor node and index
+ * values specified.
+ */
+
+RTEMS_INLINE_ROUTINE Objects_Id _Objects_Build_id(
+ Objects_APIs the_api,
+ uint32_t the_class,
+ uint32_t node,
+ uint32_t index
+)
+{
+ return (( (Objects_Id) the_api ) << OBJECTS_API_START_BIT) |
+ (( (Objects_Id) the_class ) << OBJECTS_CLASS_START_BIT) |
+ (( (Objects_Id) node ) << OBJECTS_NODE_START_BIT) |
+ (( (Objects_Id) index ) << OBJECTS_INDEX_START_BIT);
+}
+
+/*PAGE
+ *
+ * _Objects_Get_API
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the API portion of the ID.
+ */
+
+RTEMS_INLINE_ROUTINE Objects_APIs _Objects_Get_API(
+ Objects_Id id
+)
+{
+ return (Objects_APIs) ((id >> OBJECTS_API_START_BIT) & OBJECTS_API_VALID_BITS);
+}
+
+/*PAGE
+ *
+ * _Objects_Get_class
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the class portion of the ID.
+ */
+
+RTEMS_INLINE_ROUTINE uint32_t _Objects_Get_class(
+ Objects_Id id
+)
+{
+ return (uint32_t )
+ ((id >> OBJECTS_CLASS_START_BIT) & OBJECTS_CLASS_VALID_BITS);
+}
+
+/*PAGE
+ *
+ * _Objects_Get_node
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the node portion of the ID.
+ */
+
+RTEMS_INLINE_ROUTINE uint32_t _Objects_Get_node(
+ Objects_Id id
+)
+{
+ return (id >> OBJECTS_NODE_START_BIT) & OBJECTS_NODE_VALID_BITS;
+}
+
+/*PAGE
+ *
+ * _Objects_Get_index
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the index portion of the ID.
+ */
+
+RTEMS_INLINE_ROUTINE uint32_t _Objects_Get_index(
+ Objects_Id id
+)
+{
+ return (id >> OBJECTS_INDEX_START_BIT) & OBJECTS_INDEX_VALID_BITS;
+}
+
+/*PAGE
+ *
+ * _Objects_Is_class_valid
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the class is valid.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Objects_Is_class_valid(
+ uint32_t the_class
+)
+{
+ /* XXX how do we determine this now? */
+ return TRUE; /* the_class && the_class <= OBJECTS_CLASSES_LAST; */
+}
+
+/*PAGE
+ *
+ * _Objects_Is_local_node
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the node is of the local object, and
+ * FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Objects_Is_local_node(
+ uint32_t node
+)
+{
+ return ( node == _Objects_Local_node );
+}
+
+/*PAGE
+ *
+ * _Objects_Is_local_id
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the id is of a local object, and
+ * FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Objects_Is_local_id(
+ Objects_Id id
+)
+{
+ return _Objects_Is_local_node( _Objects_Get_node(id) );
+}
+
+/*PAGE
+ *
+ * _Objects_Are_ids_equal
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if left and right are equal,
+ * and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Objects_Are_ids_equal(
+ Objects_Id left,
+ Objects_Id right
+)
+{
+ return ( left == right );
+}
+
+/*PAGE
+ *
+ * _Objects_Get_local_object
+ *
+ * DESCRIPTION:
+ *
+ * This function returns a pointer to the local_table object
+ * referenced by the index.
+ */
+
+RTEMS_INLINE_ROUTINE Objects_Control *_Objects_Get_local_object(
+ Objects_Information *information,
+ uint32_t index
+)
+{
+ if ( index > information->maximum )
+ return NULL;
+ return information->local_table[ index ];
+}
+
+/*PAGE
+ *
+ * _Objects_Set_local_object
+ *
+ * DESCRIPTION:
+ *
+ * This function sets the pointer to the local_table object
+ * referenced by the index.
+ */
+
+RTEMS_INLINE_ROUTINE void _Objects_Set_local_object(
+ Objects_Information *information,
+ uint32_t index,
+ Objects_Control *the_object
+)
+{
+ if ( index <= information->maximum )
+ information->local_table[ index ] = the_object;
+}
+
+
+/*PAGE
+ *
+ * _Objects_Get_information
+ *
+ * DESCRIPTION:
+ *
+ * This function return the information structure given
+ * an id of an object.
+ */
+
+RTEMS_INLINE_ROUTINE Objects_Information *_Objects_Get_information(
+ Objects_Id id
+)
+{
+ Objects_APIs the_api;
+ uint32_t the_class;
+
+
+ the_class = _Objects_Get_class( id );
+
+ if ( !_Objects_Is_class_valid( the_class ) )
+ return NULL;
+
+ the_api = _Objects_Get_API( id );
+ return _Objects_Information_table[ the_api ][ the_class ];
+}
+
+/*PAGE
+ *
+ * _Objects_Open
+ *
+ * DESCRIPTION:
+ *
+ * This function places the_object control pointer and object name
+ * in the Local Pointer and Local Name Tables, respectively.
+ */
+
+RTEMS_INLINE_ROUTINE void _Objects_Open(
+ Objects_Information *information,
+ Objects_Control *the_object,
+ Objects_Name name
+)
+{
+ uint32_t index;
+
+ index = _Objects_Get_index( the_object->id );
+ _Objects_Set_local_object( information, index, the_object );
+
+ if ( information->is_string )
+ /* _Objects_Copy_name_string( name, the_object->name ); */
+ the_object->name = name;
+ else
+ /* _Objects_Copy_name_raw( name, the_object->name, information->name_length ); */
+ the_object->name = name;
+}
+
+/*PAGE
+ *
+ * _Objects_Close
+ *
+ * DESCRIPTION:
+ *
+ * This function removes the_object control pointer and object name
+ * in the Local Pointer and Local Name Tables.
+ */
+
+RTEMS_INLINE_ROUTINE void _Objects_Close(
+ Objects_Information *information,
+ Objects_Control *the_object
+)
+{
+ uint32_t index;
+
+ index = _Objects_Get_index( the_object->id );
+ _Objects_Set_local_object( information, index, NULL );
+ /* _Objects_Clear_name( the_object->name, information->name_length ); */
+ the_object->name = 0;
+}
+
+/*PAGE
+ *
+ * _Objects_Namespace_remove
+ *
+ * DESCRIPTION:
+ *
+ * This function removes the_object from the namespace.
+ */
+
+RTEMS_INLINE_ROUTINE void _Objects_Namespace_remove(
+ Objects_Information *information,
+ Objects_Control *the_object
+)
+{
+ /* _Objects_Clear_name( the_object->name, information->name_length ); */
+ the_object->name = 0;
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/inline/rtems/score/objectmp.inl b/cpukit/score/inline/rtems/score/objectmp.inl
new file mode 100644
index 0000000000..462a670876
--- /dev/null
+++ b/cpukit/score/inline/rtems/score/objectmp.inl
@@ -0,0 +1,72 @@
+/* inline/objectmp.inl
+ *
+ * This include file contains the bodies of all inlined routines
+ * which deal with global objects.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __INLINE_MP_OBJECTS_inl
+#define __INLINE_MP_OBJECTS_inl
+
+/*PAGE
+ *
+ * _Objects_MP_Allocate_global_object
+ *
+ * DESCRIPTION:
+ *
+ * This function allocates a Global Object control block.
+ */
+
+RTEMS_INLINE_ROUTINE Objects_MP_Control *_Objects_MP_Allocate_global_object (
+ void
+)
+{
+ return (Objects_MP_Control *)
+ _Chain_Get( &_Objects_MP_Inactive_global_objects );
+}
+
+/*PAGE
+ *
+ * _Objects_MP_Free_global_object
+ *
+ * DESCRIPTION:
+ *
+ * This routine deallocates a Global Object control block.
+ */
+
+RTEMS_INLINE_ROUTINE void _Objects_MP_Free_global_object (
+ Objects_MP_Control *the_object
+)
+{
+ _Chain_Append(
+ &_Objects_MP_Inactive_global_objects,
+ &the_object->Object.Node
+ );
+}
+
+/*PAGE
+ *
+ * _Objects_MP_Is_null_global_object
+ *
+ * DESCRIPTION:
+ *
+ * This function returns whether the global object is NULL or not.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Objects_MP_Is_null_global_object (
+ Objects_MP_Control *the_object
+)
+{
+ return( the_object == NULL );
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/inline/rtems/score/priority.inl b/cpukit/score/inline/rtems/score/priority.inl
new file mode 100644
index 0000000000..ef7e366213
--- /dev/null
+++ b/cpukit/score/inline/rtems/score/priority.inl
@@ -0,0 +1,246 @@
+/* priority.inl
+ *
+ * This file contains the static inline implementation of all inlined
+ * routines in the Priority Handler.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __PRIORITY_inl
+#define __PRIORITY_inl
+
+#include <rtems/score/bitfield.h>
+
+/*PAGE
+ *
+ * _Priority_Handler_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this handler.
+ */
+
+RTEMS_INLINE_ROUTINE void _Priority_Handler_initialization( void )
+{
+ uint32_t index;
+
+ _Priority_Major_bit_map = 0;
+ for ( index=0 ; index <16 ; index++ )
+ _Priority_Bit_map[ index ] = 0;
+}
+
+/*PAGE
+ *
+ * _Priority_Is_valid
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_priority if valid for a
+ * user task, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Priority_Is_valid (
+ Priority_Control the_priority
+)
+{
+ /*
+ * Since PRIORITY_MINIMUM is 0 and priorities are stored unsigned,
+ * then checking for less than 0 is unnecessary.
+ */
+
+ return ( the_priority <= PRIORITY_MAXIMUM );
+}
+
+/*PAGE
+ *
+ * _Priority_Major
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the major portion of the_priority.
+ */
+
+RTEMS_INLINE_ROUTINE uint32_t _Priority_Major (
+ Priority_Control the_priority
+)
+{
+ return ( the_priority / 16 );
+}
+
+/*PAGE
+ *
+ * _Priority_Minor
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the minor portion of the_priority.
+ */
+
+RTEMS_INLINE_ROUTINE uint32_t _Priority_Minor (
+ Priority_Control the_priority
+)
+{
+ return ( the_priority % 16 );
+}
+
+#if ( CPU_USE_GENERIC_BITFIELD_CODE == TRUE )
+
+/*PAGE
+ *
+ * _Priority_Mask
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the mask associated with the major or minor
+ * number passed to it.
+ */
+
+RTEMS_INLINE_ROUTINE uint32_t _Priority_Mask (
+ uint32_t bit_number
+)
+{
+ return (0x8000 >> bit_number);
+}
+
+
+/*PAGE
+ *
+ * _Priority_Bits_index
+ *
+ * DESCRIPTION:
+ *
+ * This function translates the bit numbers returned by the bit scan
+ * of a priority bit field into something suitable for use as
+ * a major or minor component of a priority.
+ */
+
+RTEMS_INLINE_ROUTINE uint32_t _Priority_Bits_index (
+ uint32_t bit_number
+)
+{
+ return bit_number;
+}
+
+#endif
+
+/*PAGE
+ *
+ * _Priority_Add_to_bit_map
+ *
+ * DESCRIPTION:
+ *
+ * This routine uses the_priority_map to update the priority
+ * bit maps to indicate that a thread has been readied.
+ */
+
+RTEMS_INLINE_ROUTINE void _Priority_Add_to_bit_map (
+ Priority_Information *the_priority_map
+)
+{
+ *the_priority_map->minor |= the_priority_map->ready_minor;
+ _Priority_Major_bit_map |= the_priority_map->ready_major;
+}
+
+/*PAGE
+ *
+ * _Priority_Remove_from_bit_map
+ *
+ * DESCRIPTION:
+ *
+ * This routine uses the_priority_map to update the priority
+ * bit maps to indicate that a thread has been removed from the
+ * ready state.
+ */
+
+RTEMS_INLINE_ROUTINE void _Priority_Remove_from_bit_map (
+ Priority_Information *the_priority_map
+)
+{
+ *the_priority_map->minor &= the_priority_map->block_minor;
+ if ( *the_priority_map->minor == 0 )
+ _Priority_Major_bit_map &= the_priority_map->block_major;
+}
+
+/*PAGE
+ *
+ * _Priority_Get_highest
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the priority of the highest priority
+ * ready thread.
+ */
+
+RTEMS_INLINE_ROUTINE Priority_Control _Priority_Get_highest( void )
+{
+ Priority_Bit_map_control minor;
+ Priority_Bit_map_control major;
+
+ _Bitfield_Find_first_bit( _Priority_Major_bit_map, major );
+ _Bitfield_Find_first_bit( _Priority_Bit_map[major], minor );
+
+ return (_Priority_Bits_index( major ) << 4) +
+ _Priority_Bits_index( minor );
+}
+
+/*PAGE
+ *
+ * _Priority_Initialize_information
+ *
+ * DESCRIPTION:
+ *
+ * This routine initializes the_priority_map so that it
+ * contains the information necessary to manage a thread
+ * at new_priority.
+ */
+
+RTEMS_INLINE_ROUTINE void _Priority_Initialize_information(
+ Priority_Information *the_priority_map,
+ Priority_Control new_priority
+)
+{
+ Priority_Bit_map_control major;
+ Priority_Bit_map_control minor;
+ Priority_Bit_map_control mask;
+
+ major = _Priority_Major( new_priority );
+ minor = _Priority_Minor( new_priority );
+
+ the_priority_map->minor =
+ &_Priority_Bit_map[ _Priority_Bits_index(major) ];
+
+ mask = _Priority_Mask( major );
+ the_priority_map->ready_major = mask;
+ the_priority_map->block_major = ~mask;
+
+ mask = _Priority_Mask( minor );
+ the_priority_map->ready_minor = mask;
+ the_priority_map->block_minor = ~mask;
+}
+
+/*PAGE
+ *
+ * _Priority_Is_group_empty
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the priority GROUP is empty, and
+ * FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Priority_Is_group_empty (
+ Priority_Control the_priority
+)
+{
+ return the_priority == 0;
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/inline/rtems/score/stack.inl b/cpukit/score/inline/rtems/score/stack.inl
new file mode 100644
index 0000000000..5bfd3c1622
--- /dev/null
+++ b/cpukit/score/inline/rtems/score/stack.inl
@@ -0,0 +1,80 @@
+/* stack.inl
+ *
+ * This file contains the static inline implementation of the inlined
+ * routines from the Stack Handler.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __STACK_inl
+#define __STACK_inl
+
+/*PAGE
+ *
+ * _Stack_Initialize
+ *
+ * DESCRIPTION:
+ *
+ * This routine initializes the_stack record to indicate that
+ * size bytes of memory starting at starting_address have been
+ * reserved for a stack.
+ */
+
+RTEMS_INLINE_ROUTINE void _Stack_Initialize (
+ Stack_Control *the_stack,
+ void *starting_address,
+ uint32_t size
+)
+{
+ the_stack->area = starting_address;
+ the_stack->size = size;
+}
+
+/*PAGE
+ *
+ * _Stack_Is_enough
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if size bytes is enough memory for
+ * a valid stack area on this processor, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Stack_Is_enough (
+ uint32_t size
+)
+{
+ return ( size >= STACK_MINIMUM_SIZE );
+}
+
+/*PAGE
+ *
+ * _Stack_Adjust_size
+ *
+ * DESCRIPTION:
+ *
+ * This function increases the stack size to insure that the thread
+ * has the desired amount of stack space after the initial stack
+ * pointer is determined based on alignment restrictions.
+ *
+ * NOTE:
+ *
+ * The amount of adjustment for alignment is CPU dependent.
+ */
+
+RTEMS_INLINE_ROUTINE uint32_t _Stack_Adjust_size (
+ uint32_t size
+)
+{
+ return size + CPU_STACK_ALIGNMENT;
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/inline/rtems/score/states.inl b/cpukit/score/inline/rtems/score/states.inl
new file mode 100644
index 0000000000..0122f74e7d
--- /dev/null
+++ b/cpukit/score/inline/rtems/score/states.inl
@@ -0,0 +1,383 @@
+/* states.inl
+ *
+ * This file contains the macro implementation of the inlined
+ * routines associated with thread state information.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __STATES_inl
+#define __STATES_inl
+
+/*PAGE
+ *
+ * _States_Set
+ *
+ * DESCRIPTION:
+ *
+ * This function sets the given states_to_set into the current_state
+ * passed in. The result is returned to the user in current_state.
+ */
+
+RTEMS_INLINE_ROUTINE States_Control _States_Set (
+ States_Control states_to_set,
+ States_Control current_state
+)
+{
+ return (current_state | states_to_set);
+}
+
+/*PAGE
+ *
+ * _States_Clear
+ *
+ * DESCRIPTION:
+ *
+ * This function clears the given states_to_clear into the current_state
+ * passed in. The result is returned to the user in current_state.
+ */
+
+RTEMS_INLINE_ROUTINE States_Control _States_Clear (
+ States_Control states_to_clear,
+ States_Control current_state
+)
+{
+ return (current_state & ~states_to_clear);
+}
+
+/*PAGE
+ *
+ * _States_Is_ready
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_states indicates that the
+ * state is READY, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _States_Is_ready (
+ States_Control the_states
+)
+{
+ return (the_states == STATES_READY);
+}
+
+/*PAGE
+ *
+ * _States_Is_only_dormant
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the DORMANT state is the ONLY state
+ * set in the_states, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _States_Is_only_dormant (
+ States_Control the_states
+)
+{
+ return (the_states == STATES_DORMANT);
+}
+
+/*PAGE
+ *
+ * _States_Is_dormant
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the DORMANT state is set in
+ * the_states, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _States_Is_dormant (
+ States_Control the_states
+)
+{
+ return (the_states & STATES_DORMANT);
+}
+
+/*PAGE
+ *
+ * _States_Is_suspended
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the SUSPENDED state is set in
+ * the_states, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _States_Is_suspended (
+ States_Control the_states
+)
+{
+ return (the_states & STATES_SUSPENDED);
+}
+
+/*PAGE
+ *
+ * _States_Is_Transient
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the TRANSIENT state is set in
+ * the_states, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _States_Is_transient (
+ States_Control the_states
+)
+{
+ return (the_states & STATES_TRANSIENT);
+}
+
+/*PAGE
+ *
+ * _States_Is_delaying
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the DELAYING state is set in
+ * the_states, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _States_Is_delaying (
+ States_Control the_states
+)
+{
+ return (the_states & STATES_DELAYING);
+}
+
+/*PAGE
+ *
+ * _States_Is_waiting_for_buffer
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the WAITING_FOR_BUFFER state is set in
+ * the_states, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _States_Is_waiting_for_buffer (
+ States_Control the_states
+)
+{
+ return (the_states & STATES_WAITING_FOR_BUFFER);
+}
+
+/*PAGE
+ *
+ * _States_Is_waiting_for_segment
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the WAITING_FOR_SEGMENT state is set in
+ * the_states, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _States_Is_waiting_for_segment (
+ States_Control the_states
+)
+{
+ return (the_states & STATES_WAITING_FOR_SEGMENT);
+}
+
+/*PAGE
+ *
+ * _States_Is_waiting_for_message
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the WAITING_FOR_MESSAGE state is set in
+ * the_states, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _States_Is_waiting_for_message (
+ States_Control the_states
+)
+{
+ return (the_states & STATES_WAITING_FOR_MESSAGE);
+}
+
+/*PAGE
+ *
+ * _States_Is_waiting_for_event
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the WAITING_FOR_EVENT state is set in
+ * the_states, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _States_Is_waiting_for_event (
+ States_Control the_states
+)
+{
+ return (the_states & STATES_WAITING_FOR_EVENT);
+}
+
+/*PAGE
+ *
+ * _States_Is_waiting_for_mutex
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the WAITING_FOR_MUTEX state
+ * is set in the_states, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _States_Is_waiting_for_mutex (
+ States_Control the_states
+)
+{
+ return (the_states & STATES_WAITING_FOR_MUTEX);
+}
+
+/*PAGE
+ *
+ * _States_Is_waiting_for_semaphore
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the WAITING_FOR_SEMAPHORE state
+ * is set in the_states, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _States_Is_waiting_for_semaphore (
+ States_Control the_states
+)
+{
+ return (the_states & STATES_WAITING_FOR_SEMAPHORE);
+}
+
+/*PAGE
+ *
+ * _States_Is_waiting_for_time
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the WAITING_FOR_TIME state is set in
+ * the_states, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _States_Is_waiting_for_time (
+ States_Control the_states
+)
+{
+ return (the_states & STATES_WAITING_FOR_TIME);
+}
+
+/*PAGE
+ *
+ * _States_Is_waiting_for_rpc_reply
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the WAITING_FOR_TIME state is set in
+ * the_states, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _States_Is_waiting_for_rpc_reply (
+ States_Control the_states
+)
+{
+ return (the_states & STATES_WAITING_FOR_RPC_REPLY);
+}
+
+/*PAGE
+ *
+ * _States_Is_waiting_for_period
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the WAITING_FOR_PERIOD state is set in
+ * the_states, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _States_Is_waiting_for_period (
+ States_Control the_states
+)
+{
+ return (the_states & STATES_WAITING_FOR_PERIOD);
+}
+
+/*PAGE
+ *
+ * _States_Is_locally_blocked
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if one of the states which indicates
+ * that a task is blocked waiting for a local resource is set in
+ * the_states, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _States_Is_locally_blocked (
+ States_Control the_states
+)
+{
+ return (the_states & STATES_LOCALLY_BLOCKED);
+}
+
+/*PAGE
+ *
+ * _States_Is_waiting_on_thread_queue
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if one of the states which indicates
+ * that a task is blocked waiting for a local resource is set in
+ * the_states, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _States_Is_waiting_on_thread_queue (
+ States_Control the_states
+)
+{
+ return (the_states & STATES_WAITING_ON_THREAD_QUEUE);
+}
+
+/*PAGE
+ *
+ * _States_Is_blocked
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if one of the states which indicates
+ * that a task is blocked is set in the_states, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _States_Is_blocked (
+ States_Control the_states
+)
+{
+ return (the_states & STATES_BLOCKED);
+}
+
+/*PAGE
+ *
+ *
+ * _States_Are_set
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if any of the states in the mask
+ * are set in the_states, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _States_Are_set (
+ States_Control the_states,
+ States_Control mask
+)
+{
+ return ( (the_states & mask) != STATES_READY);
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/inline/rtems/score/sysstate.inl b/cpukit/score/inline/rtems/score/sysstate.inl
new file mode 100644
index 0000000000..4aa3295efe
--- /dev/null
+++ b/cpukit/score/inline/rtems/score/sysstate.inl
@@ -0,0 +1,153 @@
+/* sysstates.inl
+ *
+ * This file contains the inline implementation of routines regarding the
+ * system state.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __SYSTEM_STATE_inl
+#define __SYSTEM_STATE_inl
+
+/*PAGE
+ *
+ * _System_state_Handler_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine initializes the system state handler.
+ */
+
+RTEMS_INLINE_ROUTINE void _System_state_Handler_initialization (
+ boolean is_multiprocessing
+)
+{
+ _System_state_Current = SYSTEM_STATE_BEFORE_INITIALIZATION;
+ _System_state_Is_multiprocessing = is_multiprocessing;
+}
+
+/*PAGE
+ *
+ * _System_state_Set
+ *
+ * DESCRIPTION:
+ *
+ * This routine sets the current system state to that specified by
+ * the called.
+ */
+
+RTEMS_INLINE_ROUTINE void _System_state_Set (
+ System_state_Codes state
+)
+{
+ _System_state_Current = state;
+}
+
+/*PAGE
+ *
+ * _System_state_Get
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the current system state.
+ */
+
+RTEMS_INLINE_ROUTINE System_state_Codes _System_state_Get ( void )
+{
+ return _System_state_Current;
+}
+
+/*PAGE
+ *
+ * _System_state_Is_before_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the state is equal to the
+ * "before initialization" state, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _System_state_Is_before_initialization (
+ System_state_Codes state
+)
+{
+ return (state == SYSTEM_STATE_BEFORE_INITIALIZATION);
+}
+
+/*PAGE
+ *
+ * _System_state_Is_before_multitasking
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the state is equal to the
+ * "before multitasking" state, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _System_state_Is_before_multitasking (
+ System_state_Codes state
+)
+{
+ return (state == SYSTEM_STATE_BEFORE_MULTITASKING);
+}
+
+/*PAGE
+ *
+ * _System_state_Is_begin_multitasking
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the state is equal to the
+ * "begin multitasking" state, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _System_state_Is_begin_multitasking (
+ System_state_Codes state
+)
+{
+ return (state == SYSTEM_STATE_BEGIN_MULTITASKING);
+}
+
+/*PAGE
+ *
+ * _System_state_Is_up
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the state is equal to the
+ * "up" state, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _System_state_Is_up (
+ System_state_Codes state
+)
+{
+ return (state == SYSTEM_STATE_UP);
+}
+
+/*PAGE
+ *
+ * _System_state_Is_failed
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the state is equal to the
+ * "failed" state, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _System_state_Is_failed (
+ System_state_Codes state
+)
+{
+ return (state == SYSTEM_STATE_FAILED);
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/inline/rtems/score/thread.inl b/cpukit/score/inline/rtems/score/thread.inl
new file mode 100644
index 0000000000..e4f113f70c
--- /dev/null
+++ b/cpukit/score/inline/rtems/score/thread.inl
@@ -0,0 +1,427 @@
+/* thread.inl
+ *
+ * This file contains the macro implementation of the inlined
+ * routines from the Thread handler.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __THREAD_inl
+#define __THREAD_inl
+
+/*PAGE
+ *
+ * _Thread_Stop_multitasking
+ *
+ * DESCRIPTION:
+ *
+ * This routine halts multitasking and returns control to
+ * the "thread" (i.e. the BSP) which initially invoked the
+ * routine which initialized the system.
+ */
+
+RTEMS_INLINE_ROUTINE void _Thread_Stop_multitasking( void )
+{
+ _Context_Switch( &_Thread_Executing->Registers, &_Thread_BSP_context );
+}
+
+/*PAGE
+ *
+ * _Thread_Is_executing
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_thread is the currently executing
+ * thread, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Thread_Is_executing (
+ Thread_Control *the_thread
+)
+{
+ return ( the_thread == _Thread_Executing );
+}
+
+/*PAGE
+ *
+ * _Thread_Is_heir
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_thread is the heir
+ * thread, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Thread_Is_heir (
+ Thread_Control *the_thread
+)
+{
+ return ( the_thread == _Thread_Heir );
+}
+
+/*PAGE
+ *
+ * _Thread_Is_executing_also_the_heir
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the currently executing thread
+ * is also the heir thread, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Thread_Is_executing_also_the_heir( void )
+{
+ return ( _Thread_Executing == _Thread_Heir );
+}
+
+/*PAGE
+ *
+ * _Thread_Unblock
+ *
+ * DESCRIPTION:
+ *
+ * This routine clears any blocking state for the_thread. It performs
+ * any necessary scheduling operations including the selection of
+ * a new heir thread.
+ */
+
+RTEMS_INLINE_ROUTINE void _Thread_Unblock (
+ Thread_Control *the_thread
+)
+{
+ _Thread_Clear_state( the_thread, STATES_BLOCKED );
+}
+
+/*PAGE
+ *
+ * _Thread_Restart_self
+ *
+ * DESCRIPTION:
+ *
+ * This routine resets the current context of the calling thread
+ * to that of its initial state.
+ */
+
+RTEMS_INLINE_ROUTINE void _Thread_Restart_self( void )
+{
+#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+ if ( _Thread_Executing->fp_context != NULL )
+ _Context_Restore_fp( &_Thread_Executing->fp_context );
+#endif
+
+ _CPU_Context_Restart_self( &_Thread_Executing->Registers );
+}
+
+/*PAGE
+ *
+ * _Thread_Calculate_heir
+ *
+ * DESCRIPTION:
+ *
+ * This function returns a pointer to the highest priority
+ * ready thread.
+ */
+
+RTEMS_INLINE_ROUTINE void _Thread_Calculate_heir( void )
+{
+ _Thread_Heir = (Thread_Control *)
+ _Thread_Ready_chain[ _Priority_Get_highest() ].first;
+}
+
+/*PAGE
+ *
+ * _Thread_Is_allocated_fp
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the floating point context of
+ * the_thread is currently loaded in the floating point unit, and
+ * FALSE otherwise.
+ */
+
+#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+RTEMS_INLINE_ROUTINE boolean _Thread_Is_allocated_fp (
+ Thread_Control *the_thread
+)
+{
+ return ( the_thread == _Thread_Allocated_fp );
+}
+#endif
+
+/*PAGE
+ *
+ * _Thread_Deallocate_fp
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked when the currently loaded floating
+ * point context is now longer associated with an active thread.
+ */
+
+#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+RTEMS_INLINE_ROUTINE void _Thread_Deallocate_fp( void )
+{
+ _Thread_Allocated_fp = NULL;
+}
+#endif
+
+/*PAGE
+ *
+ * _Thread_Disable_dispatch
+ *
+ * DESCRIPTION:
+ *
+ * This routine prevents dispatching.
+ */
+
+RTEMS_INLINE_ROUTINE void _Thread_Disable_dispatch( void )
+{
+ _Thread_Dispatch_disable_level += 1;
+}
+
+/*PAGE
+ *
+ * _Thread_Enable_dispatch
+ *
+ * DESCRIPTION:
+ *
+ * This routine allows dispatching to occur again. If this is
+ * the outer most dispatching critical section, then a dispatching
+ * operation will be performed and, if necessary, control of the
+ * processor will be transferred to the heir thread.
+ */
+
+#if ( CPU_INLINE_ENABLE_DISPATCH == TRUE )
+RTEMS_INLINE_ROUTINE void _Thread_Enable_dispatch()
+{
+ if ( (--_Thread_Dispatch_disable_level) == 0 )
+ _Thread_Dispatch();
+}
+#endif
+
+#if ( CPU_INLINE_ENABLE_DISPATCH == FALSE )
+void _Thread_Enable_dispatch( void );
+#endif
+
+/*PAGE
+ *
+ * _Thread_Unnest_dispatch
+ *
+ * DESCRIPTION:
+ *
+ * This routine allows dispatching to occur again. However,
+ * no dispatching operation is performed even if this is the outer
+ * most dispatching critical section.
+ */
+
+RTEMS_INLINE_ROUTINE void _Thread_Unnest_dispatch( void )
+{
+ _Thread_Dispatch_disable_level -= 1;
+}
+
+/*PAGE
+ *
+ * _Thread_Is_dispatching_enabled
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if dispatching is disabled, and FALSE
+ * otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Thread_Is_dispatching_enabled( void )
+{
+ return ( _Thread_Dispatch_disable_level == 0 );
+}
+
+/*PAGE
+ *
+ * _Thread_Is_context_switch_necessary
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if dispatching is disabled, and FALSE
+ * otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Thread_Is_context_switch_necessary( void )
+{
+ return ( _Context_Switch_necessary );
+}
+
+/*PAGE
+ *
+ * _Thread_Dispatch_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine initializes the thread dispatching subsystem.
+ */
+
+RTEMS_INLINE_ROUTINE void _Thread_Dispatch_initialization( void )
+{
+ _Thread_Dispatch_disable_level = 1;
+}
+
+/*PAGE
+ *
+ * _Thread_Is_null
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_thread is NULL and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Thread_Is_null (
+ Thread_Control *the_thread
+)
+{
+ return ( the_thread == NULL );
+}
+
+/*PAGE
+ *
+ * _Thread_Get
+ *
+ * DESCRIPTION:
+ *
+ * This function maps thread IDs to thread control
+ * blocks. If ID corresponds to a local thread, then it
+ * returns the_thread control pointer which maps to ID
+ * and location is set to OBJECTS_LOCAL. If the thread ID is
+ * global and resides on a remote node, then location is set
+ * to OBJECTS_REMOTE, and the_thread is undefined.
+ * Otherwise, location is set to OBJECTS_ERROR and
+ * the_thread is undefined.
+ *
+ * NOTE: XXX... This routine may be able to be optimized.
+ */
+
+RTEMS_INLINE_ROUTINE Thread_Control *_Thread_Get (
+ Objects_Id id,
+ Objects_Locations *location
+)
+{
+ uint32_t the_api;
+ uint32_t the_class;
+ Objects_Information *information;
+ Thread_Control *tp = (Thread_Control *) 0;
+
+ if ( _Objects_Are_ids_equal( id, OBJECTS_ID_OF_SELF ) ) {
+ _Thread_Disable_dispatch();
+ *location = OBJECTS_LOCAL;
+ tp = _Thread_Executing;
+ goto done;
+ }
+
+ the_api = _Objects_Get_API( id );
+ if ( the_api && the_api > OBJECTS_APIS_LAST ) {
+ *location = OBJECTS_ERROR;
+ goto done;
+ }
+
+ the_class = _Objects_Get_class( id );
+ if ( the_class != 1 ) { /* threads are always first class :) */
+ *location = OBJECTS_ERROR;
+ goto done;
+ }
+
+ information = _Objects_Information_table[ the_api ][ the_class ];
+
+ if ( !information ) {
+ *location = OBJECTS_ERROR;
+ goto done;
+ }
+
+ tp = (Thread_Control *) _Objects_Get( information, id, location );
+
+done:
+ return tp;
+}
+
+
+/*
+ * _Thread_Is_proxy_blocking
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the status code is equal to the
+ * status which indicates that a proxy is blocking, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Thread_Is_proxy_blocking (
+ uint32_t code
+)
+{
+ return (code == THREAD_STATUS_PROXY_BLOCKING);
+}
+
+/*PAGE
+ *
+ * _Thread_Internal_allocate
+ *
+ * DESCRIPTION:
+ *
+ * This routine allocates an internal thread.
+ */
+
+RTEMS_INLINE_ROUTINE Thread_Control *_Thread_Internal_allocate( void )
+{
+ return (Thread_Control *) _Objects_Allocate( &_Thread_Internal_information );
+}
+
+/*PAGE
+ *
+ * _Thread_Internal_free
+ *
+ * DESCRIPTION:
+ *
+ * This routine frees an internal thread.
+ */
+
+RTEMS_INLINE_ROUTINE void _Thread_Internal_free (
+ Thread_Control *the_task
+)
+{
+ _Objects_Free( &_Thread_Internal_information, &the_task->Object );
+}
+
+/*PAGE
+ *
+ * _Thread_Get_libc_reent
+ *
+ * DESCRIPTION:
+ *
+ * This routine returns the C library re-enterant pointer.
+ */
+
+RTEMS_INLINE_ROUTINE struct _reent **_Thread_Get_libc_reent( void )
+{
+ return _Thread_libc_reent;
+}
+
+/*PAGE
+ *
+ * _Thread_Set_libc_reent
+ *
+ * DESCRIPTION:
+ *
+ * This routine set the C library re-enterant pointer.
+ */
+
+RTEMS_INLINE_ROUTINE void _Thread_Set_libc_reent (
+ struct _reent **libc_reent
+)
+{
+ _Thread_libc_reent = libc_reent;
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/inline/rtems/score/threadmp.inl b/cpukit/score/inline/rtems/score/threadmp.inl
new file mode 100644
index 0000000000..fbb247c49c
--- /dev/null
+++ b/cpukit/score/inline/rtems/score/threadmp.inl
@@ -0,0 +1,60 @@
+/* inline/threadmp.inl
+ *
+ * This include file contains the bodies of all inlined routines
+ * for the multiprocessing part of thread package.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __INLINE_MP_THREAD_inl
+#define __INLINE_MP_THREAD_inl
+
+/*PAGE
+ *
+ * _Thread_MP_Is_receive
+ *
+ * DESCRIPTION:
+ *
+ * This function returns true if the thread in question is the
+ * multiprocessing receive thread.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Thread_MP_Is_receive (
+ Thread_Control *the_thread
+)
+{
+ return the_thread == _Thread_MP_Receive;
+}
+
+/*PAGE
+ *
+ * _Thread_MP_Free_proxy
+ *
+ * DESCRIPTION:
+ *
+ * This routine frees a proxy control block to the
+ * inactive chain of free proxy control blocks.
+ */
+
+RTEMS_INLINE_ROUTINE void _Thread_MP_Free_proxy (
+ Thread_Control *the_thread
+)
+{
+ Thread_Proxy_control *the_proxy;
+
+ the_proxy = (Thread_Proxy_control *) the_thread;
+
+ _Chain_Extract( &the_proxy->Active );
+
+ _Chain_Append( &_Thread_MP_Inactive_proxies, &the_thread->Object.Node );
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/inline/rtems/score/tod.inl b/cpukit/score/inline/rtems/score/tod.inl
new file mode 100644
index 0000000000..7c2a4ffdfc
--- /dev/null
+++ b/cpukit/score/inline/rtems/score/tod.inl
@@ -0,0 +1,66 @@
+/* tod.inl
+ *
+ * This file contains the static inline implementation of the inlined routines
+ * from the Time of Day Handler.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __TIME_OF_DAY_inl
+#define __TIME_OF_DAY_inl
+
+/*PAGE
+ *
+ * _TOD_Tickle_ticks
+ *
+ * DESCRIPTION:
+ *
+ * This routine increments the ticks field of the current time of
+ * day at each clock tick.
+ */
+
+RTEMS_INLINE_ROUTINE void _TOD_Tickle_ticks( void )
+{
+ _TOD_Current.ticks += 1;
+ _Watchdog_Ticks_since_boot += 1;
+}
+
+/*PAGE
+ *
+ * _TOD_Deactivate
+ *
+ * DESCRIPTION:
+ *
+ * This routine deactivates updating of the current time of day.
+ */
+
+RTEMS_INLINE_ROUTINE void _TOD_Deactivate( void )
+{
+ _Watchdog_Remove( &_TOD_Seconds_watchdog );
+}
+
+/*PAGE
+ *
+ * _TOD_Activate
+ *
+ * DESCRIPTION:
+ *
+ * This routine activates updating of the current time of day.
+ */
+
+RTEMS_INLINE_ROUTINE void _TOD_Activate(
+ Watchdog_Interval ticks
+)
+{
+ _Watchdog_Insert_ticks( &_TOD_Seconds_watchdog, ticks );
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/inline/rtems/score/tqdata.inl b/cpukit/score/inline/rtems/score/tqdata.inl
new file mode 100644
index 0000000000..aff81708b8
--- /dev/null
+++ b/cpukit/score/inline/rtems/score/tqdata.inl
@@ -0,0 +1,72 @@
+/* tqdata.inl
+ *
+ * This file contains the static inline implementation of the inlined
+ * routines needed to support the Thread Queue Data.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __THREAD_QUEUE_DATA_inl
+#define __THREAD_QUEUE_DATA_inl
+
+/*PAGE
+ *
+ * _Thread_queue_Header_number
+ *
+ * DESCRIPTION:
+ *
+ * This function returns the index of the priority chain on which
+ * a thread of the_priority should be placed.
+ */
+
+RTEMS_INLINE_ROUTINE uint32_t _Thread_queue_Header_number (
+ Priority_Control the_priority
+)
+{
+ return (the_priority / TASK_QUEUE_DATA_PRIORITIES_PER_HEADER);
+}
+
+/*PAGE
+ *
+ * _Thread_queue_Is_reverse_search
+ *
+ * DESCRIPTION:
+ *
+ * This function returns TRUE if the_priority indicates that the
+ * enqueue search should start at the front of this priority
+ * group chain, and FALSE if the search should start at the rear.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Thread_queue_Is_reverse_search (
+ Priority_Control the_priority
+)
+{
+ return ( the_priority & TASK_QUEUE_DATA_REVERSE_SEARCH_MASK );
+}
+
+/*PAGE
+ *
+ * _Thread_queue_Enter_critical_section
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked to indicate that the specified thread queue is
+ * entering a critical section.
+ */
+
+RTEMS_INLINE_ROUTINE void _Thread_queue_Enter_critical_section (
+ Thread_queue_Control *the_thread_queue
+)
+{
+ the_thread_queue->sync_state = THREAD_QUEUE_NOTHING_HAPPENED;
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/inline/rtems/score/userext.inl b/cpukit/score/inline/rtems/score/userext.inl
new file mode 100644
index 0000000000..2aef8001ff
--- /dev/null
+++ b/cpukit/score/inline/rtems/score/userext.inl
@@ -0,0 +1,169 @@
+/* userext.inl
+ *
+ * This file contains the macro implementation of the inlined routines
+ * from the User Extension Handler
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __USER_EXTENSIONS_inl
+#define __USER_EXTENSIONS_inl
+
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _User_extensions_Add_set
+ *
+ * DESCRIPTION:
+ *
+ * This routine is used to add a user extension set to the active list.
+ *
+ * NOTE: Must be before _User_extensions_Handler_initialization to
+ * ensure proper inlining.
+ */
+
+RTEMS_INLINE_ROUTINE void _User_extensions_Add_set (
+ User_extensions_Control *the_extension,
+ User_extensions_Table *extension_table
+)
+{
+ the_extension->Callouts = *extension_table;
+
+ _Chain_Append( &_User_extensions_List, &the_extension->Node );
+
+ /*
+ * If a switch handler is present, append it to the switch chain.
+ */
+
+ if ( extension_table->thread_switch != NULL ) {
+ the_extension->Switch.thread_switch = extension_table->thread_switch;
+ _Chain_Append( &_User_extensions_Switches_list, &the_extension->Switch.Node );
+ }
+}
+
+/*PAGE
+ *
+ * _User_extensions_Handler_initialization
+ *
+ * DESCRIPTION:
+ *
+ * This routine performs the initialization necessary for this handler.
+ */
+
+RTEMS_INLINE_ROUTINE void _User_extensions_Handler_initialization (
+ uint32_t number_of_extensions,
+ User_extensions_Table *initial_extensions
+)
+{
+ User_extensions_Control *extension;
+ uint32_t i;
+
+ _Chain_Initialize_empty( &_User_extensions_List );
+ _Chain_Initialize_empty( &_User_extensions_Switches_list );
+
+ if ( initial_extensions ) {
+ extension = (User_extensions_Control *)
+ _Workspace_Allocate_or_fatal_error(
+ number_of_extensions * sizeof( User_extensions_Control )
+ );
+
+ memset (
+ extension,
+ 0,
+ number_of_extensions * sizeof( User_extensions_Control )
+ );
+
+ for ( i = 0 ; i < number_of_extensions ; i++ ) {
+ _User_extensions_Add_set (extension, &initial_extensions[i]);
+ extension++;
+ }
+ }
+}
+
+/*PAGE
+ *
+ * _User_extensions_Add_API_set
+ *
+ * DESCRIPTION:
+ *
+ * This routine is used to add an API extension set to the active list.
+ */
+
+RTEMS_INLINE_ROUTINE void _User_extensions_Add_API_set (
+ User_extensions_Control *the_extension
+)
+{
+ _Chain_Append( &_User_extensions_List, &the_extension->Node );
+
+ /*
+ * If a switch handler is present, append it to the switch chain.
+ */
+
+ if ( the_extension->Callouts.thread_switch != NULL ) {
+ the_extension->Switch.thread_switch = the_extension->Callouts.thread_switch;
+ _Chain_Append(
+ &_User_extensions_Switches_list, &the_extension->Switch.Node );
+ }
+}
+
+/*PAGE
+ *
+ * _User_extensions_Remove_set
+ *
+ * DESCRIPTION:
+ *
+ * This routine is used to remove a user extension set from the active list.
+ */
+
+RTEMS_INLINE_ROUTINE void _User_extensions_Remove_set (
+ User_extensions_Control *the_extension
+)
+{
+ _Chain_Extract( &the_extension->Node );
+
+ /*
+ * If a switch handler is present, remove it.
+ */
+
+ if ( the_extension->Callouts.thread_switch != NULL )
+ _Chain_Extract( &the_extension->Switch.Node );
+}
+
+/*PAGE
+ *
+ * _User_extensions_Thread_switch
+ *
+ * DESCRIPTION:
+ *
+ * This routine is used to invoke the user extension which
+ * is invoked when a context switch occurs.
+ */
+
+RTEMS_INLINE_ROUTINE void _User_extensions_Thread_switch (
+ Thread_Control *executing,
+ Thread_Control *heir
+)
+{
+ Chain_Node *the_node;
+ User_extensions_Switch_control *the_extension_switch;
+
+ for ( the_node = _User_extensions_Switches_list.first ;
+ !_Chain_Is_tail( &_User_extensions_Switches_list, the_node ) ;
+ the_node = the_node->next ) {
+
+ the_extension_switch = (User_extensions_Switch_control *) the_node;
+
+ (*the_extension_switch->thread_switch)( executing, heir );
+ }
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/inline/rtems/score/watchdog.inl b/cpukit/score/inline/rtems/score/watchdog.inl
new file mode 100644
index 0000000000..aace2123a6
--- /dev/null
+++ b/cpukit/score/inline/rtems/score/watchdog.inl
@@ -0,0 +1,323 @@
+/* watchdog.inl
+ *
+ * This file contains the static inline implementation of all inlined
+ * routines in the Watchdog Handler.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __WATCHDOG_inl
+#define __WATCHDOG_inl
+
+/*PAGE
+ *
+ * _Watchdog_Initialize
+ *
+ * DESCRIPTION:
+ *
+ * This routine initializes the specified watchdog. The watchdog is
+ * made inactive, the watchdog id and handler routine are set to the
+ * specified values.
+ */
+
+RTEMS_INLINE_ROUTINE void _Watchdog_Initialize(
+ Watchdog_Control *the_watchdog,
+ Watchdog_Service_routine_entry routine,
+ Objects_Id id,
+ void *user_data
+)
+{
+ the_watchdog->state = WATCHDOG_INACTIVE;
+ the_watchdog->routine = routine;
+ the_watchdog->id = id;
+ the_watchdog->user_data = user_data;
+}
+
+/*PAGE
+ *
+ * _Watchdog_Is_active
+ *
+ * DESCRIPTION:
+ *
+ * This routine returns TRUE if the watchdog timer is in the ACTIVE
+ * state, and FALSE otherwise.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Watchdog_Is_active(
+ Watchdog_Control *the_watchdog
+)
+{
+
+ return ( the_watchdog->state == WATCHDOG_ACTIVE );
+
+}
+
+/*PAGE
+ *
+ * _Watchdog_Activate
+ *
+ * DESCRIPTION:
+ *
+ * This routine activates THE_WATCHDOG timer which is already
+ * on a watchdog chain.
+ */
+
+RTEMS_INLINE_ROUTINE void _Watchdog_Activate(
+ Watchdog_Control *the_watchdog
+)
+{
+
+ the_watchdog->state = WATCHDOG_ACTIVE;
+
+}
+
+/*PAGE
+ *
+ * _Watchdog_Deactivate
+ *
+ * DESCRIPTION:
+ *
+ * This routine deactivates THE_WATCHDOG timer which will remain
+ * on a watchdog chain.
+ */
+
+RTEMS_INLINE_ROUTINE void _Watchdog_Deactivate(
+ Watchdog_Control *the_watchdog
+)
+{
+
+ the_watchdog->state = WATCHDOG_REMOVE_IT;
+
+}
+
+/*PAGE
+ *
+ * _Watchdog_Tickle_ticks
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked at each clock tick to update the ticks
+ * watchdog chain.
+ */
+
+RTEMS_INLINE_ROUTINE void _Watchdog_Tickle_ticks( void )
+{
+
+ _Watchdog_Tickle( &_Watchdog_Ticks_chain );
+
+}
+
+/*PAGE
+ *
+ * _Watchdog_Tickle_seconds
+ *
+ * DESCRIPTION:
+ *
+ * This routine is invoked at each clock tick to update the seconds
+ * watchdog chain.
+ */
+
+RTEMS_INLINE_ROUTINE void _Watchdog_Tickle_seconds( void )
+{
+
+ _Watchdog_Tickle( &_Watchdog_Seconds_chain );
+
+}
+
+/*PAGE
+ *
+ * _Watchdog_Insert_ticks
+ *
+ * DESCRIPTION:
+ *
+ * This routine inserts THE_WATCHDOG into the ticks watchdog chain
+ * for a time of UNITS ticks. The INSERT_MODE indicates whether
+ * THE_WATCHDOG is to be activated automatically or later, explicitly
+ * by the caller.
+ */
+
+RTEMS_INLINE_ROUTINE void _Watchdog_Insert_ticks(
+ Watchdog_Control *the_watchdog,
+ Watchdog_Interval units
+)
+{
+
+ the_watchdog->initial = units;
+
+ _Watchdog_Insert( &_Watchdog_Ticks_chain, the_watchdog );
+
+}
+
+/*PAGE
+ *
+ * _Watchdog_Insert_seconds
+ *
+ * DESCRIPTION:
+ *
+ * This routine inserts THE_WATCHDOG into the seconds watchdog chain
+ * for a time of UNITS seconds. The INSERT_MODE indicates whether
+ * THE_WATCHDOG is to be activated automatically or later, explicitly
+ * by the caller.
+ */
+
+RTEMS_INLINE_ROUTINE void _Watchdog_Insert_seconds(
+ Watchdog_Control *the_watchdog,
+ Watchdog_Interval units
+)
+{
+
+ the_watchdog->initial = units;
+
+ _Watchdog_Insert( &_Watchdog_Seconds_chain, the_watchdog );
+
+}
+
+/*PAGE
+ *
+ * _Watchdog_Adjust_seconds
+ *
+ * DESCRIPTION:
+ *
+ * This routine adjusts the seconds watchdog chain in the forward
+ * or backward DIRECTION for UNITS seconds. This is invoked when the
+ * current time of day is changed.
+ */
+
+RTEMS_INLINE_ROUTINE void _Watchdog_Adjust_seconds(
+ Watchdog_Adjust_directions direction,
+ Watchdog_Interval units
+)
+{
+
+ _Watchdog_Adjust( &_Watchdog_Seconds_chain, direction, units );
+
+}
+
+/*PAGE
+ *
+ * _Watchdog_Adjust_ticks
+ *
+ * DESCRIPTION:
+ *
+ * This routine adjusts the ticks watchdog chain in the forward
+ * or backward DIRECTION for UNITS ticks.
+ */
+
+RTEMS_INLINE_ROUTINE void _Watchdog_Adjust_ticks(
+ Watchdog_Adjust_directions direction,
+ Watchdog_Interval units
+)
+{
+
+ _Watchdog_Adjust( &_Watchdog_Ticks_chain, direction, units );
+
+}
+
+/*PAGE
+ *
+ * _Watchdog_Reset
+ *
+ * DESCRIPTION:
+ *
+ * This routine resets THE_WATCHDOG timer to its state at INSERT
+ * time. This routine is valid only on interval watchdog timers
+ * and is used to make an interval watchdog timer fire "every" so
+ * many ticks.
+ */
+
+RTEMS_INLINE_ROUTINE void _Watchdog_Reset(
+ Watchdog_Control *the_watchdog
+)
+{
+
+ (void) _Watchdog_Remove( the_watchdog );
+
+ _Watchdog_Insert( &_Watchdog_Ticks_chain, the_watchdog );
+
+}
+
+/*PAGE
+ *
+ * _Watchdog_Next
+ *
+ * DESCRIPTION:
+ *
+ * This routine returns a pointer to the watchdog timer following
+ * THE_WATCHDOG on the watchdog chain.
+ */
+
+RTEMS_INLINE_ROUTINE Watchdog_Control *_Watchdog_Next(
+ Watchdog_Control *the_watchdog
+)
+{
+
+ return ( (Watchdog_Control *) the_watchdog->Node.next );
+
+}
+
+/*PAGE
+ *
+ * _Watchdog_Previous
+ *
+ * DESCRIPTION:
+ *
+ * This routine returns a pointer to the watchdog timer preceding
+ * THE_WATCHDOG on the watchdog chain.
+ */
+
+RTEMS_INLINE_ROUTINE Watchdog_Control *_Watchdog_Previous(
+ Watchdog_Control *the_watchdog
+)
+{
+
+ return ( (Watchdog_Control *) the_watchdog->Node.previous );
+
+}
+
+/*PAGE
+ *
+ * _Watchdog_First
+ *
+ * DESCRIPTION:
+ *
+ * This routine returns a pointer to the first watchdog timer
+ * on the watchdog chain HEADER.
+ */
+
+RTEMS_INLINE_ROUTINE Watchdog_Control *_Watchdog_First(
+ Chain_Control *header
+)
+{
+
+ return ( (Watchdog_Control *) header->first );
+
+}
+
+/*PAGE
+ *
+ * _Watchdog_Last
+ *
+ * DESCRIPTION:
+ *
+ * This routine returns a pointer to the last watchdog timer
+ * on the watchdog chain HEADER.
+ */
+
+RTEMS_INLINE_ROUTINE Watchdog_Control *_Watchdog_Last(
+ Chain_Control *header
+)
+{
+
+ return ( (Watchdog_Control *) header->last );
+
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/inline/rtems/score/wkspace.inl b/cpukit/score/inline/rtems/score/wkspace.inl
new file mode 100644
index 0000000000..baa6297220
--- /dev/null
+++ b/cpukit/score/inline/rtems/score/wkspace.inl
@@ -0,0 +1,56 @@
+/* wkspace.inl
+ *
+ * This include file contains the bodies of the routines which contains
+ * information related to the RAM Workspace.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __WORKSPACE_inl
+#define __WORKSPACE_inl
+
+/*PAGE
+ *
+ * _Workspace_Allocate
+ *
+ * DESCRIPTION:
+ *
+ * This routine returns the address of a block of memory of size
+ * bytes. If a block of the appropriate size cannot be allocated
+ * from the workspace, then NULL is returned.
+ */
+
+RTEMS_INLINE_ROUTINE void *_Workspace_Allocate(
+ uint32_t size
+)
+{
+ return _Heap_Allocate( &_Workspace_Area, size );
+}
+
+/*PAGE
+ *
+ * _Workspace_Free
+ *
+ * DESCRIPTION:
+ *
+ * This function frees the specified block of memory. If the block
+ * belongs to the Workspace and can be successfully freed, then
+ * TRUE is returned. Otherwise FALSE is returned.
+ */
+
+RTEMS_INLINE_ROUTINE boolean _Workspace_Free(
+ void *block
+)
+{
+ return _Heap_Free( &_Workspace_Area, block );
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/macros/README b/cpukit/score/macros/README
new file mode 100644
index 0000000000..b2f0c4d481
--- /dev/null
+++ b/cpukit/score/macros/README
@@ -0,0 +1,18 @@
+#
+# $Id$
+#
+
+The files in this directory are not considered the "primary" source
+of inlined routines for RTEMS. The "inline" directory contains
+the implementations of the inlined basis which are regularly
+tested. In general, an effort is made to keep the contents of
+this directory up to date but testing is only performed irregularly
+and even then it is usually with a single target processor and BSP.
+
+The primary purpose of the code in this directory is to insure
+that RTEMS can be compiled using a C compiler which does not support
+static inline routines.
+
+These were last successfully tested on 2/1/95 on a prerelease version
+of 3.2.0. The testing was done only on the Force CPU386 i386 target board.
+No testing was done on version of the code in the final release.
diff --git a/cpukit/score/macros/rtems/score/address.inl b/cpukit/score/macros/rtems/score/address.inl
new file mode 100644
index 0000000000..77d2d576c2
--- /dev/null
+++ b/cpukit/score/macros/rtems/score/address.inl
@@ -0,0 +1,75 @@
+/* macros/address.h
+ *
+ * This include file contains the bodies of the routines
+ * about addresses which are inlined.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __MACROS_ADDRESSES_h
+#define __MACROS_ADDRESSES_h
+
+/*PAGE
+ *
+ * _Addresses_Add_offset
+ *
+ */
+
+#define _Addresses_Add_offset( _base, _offset ) \
+ ((void *)((char *)(_base) + (_offset)))
+
+/*PAGE
+ *
+ * _Addresses_Subtract_offset
+ *
+ */
+
+#define _Addresses_Subtract_offset( _base, _offset ) \
+ ((void *)((char *)(_base) - (_offset)))
+
+/*PAGE
+ *
+ * _Addresses_Subtract
+ *
+ * NOTE: The cast of an address to an uint32_t makes this code
+ * dependent on an addresses being thirty two bits.
+ */
+
+#define _Addresses_Subtract( _left, _right ) \
+ ((void *)(_left) - (void *)(_right))
+
+/*PAGE
+ *
+ * _Addresses_Is_aligned
+ *
+ */
+
+#if (CPU_ALIGNMENT == 0)
+#define _Addresses_Is_aligned( _address ) \
+ (TRUE)
+#elif defined(RTEMS_CPU_HAS_16_BIT_ADDRESSES)
+#define _Addresses_Is_aligned( _address ) \
+ ( ( (unsigned short)(_address) % CPU_ALIGNMENT ) == 0 )
+#else
+#define _Addresses_Is_aligned( _address ) \
+ ( ( (uint32_t )(_address) % CPU_ALIGNMENT ) == 0 )
+#endif
+
+/*PAGE
+ *
+ * _Addresses_Is_in_range
+ *
+ */
+
+#define _Addresses_Is_in_range( _address, _base, _limit ) \
+ ( (_address) >= (_base) && (_address) <= (_limit) )
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/macros/rtems/score/chain.inl b/cpukit/score/macros/rtems/score/chain.inl
new file mode 100644
index 0000000000..1694130464
--- /dev/null
+++ b/cpukit/score/macros/rtems/score/chain.inl
@@ -0,0 +1,199 @@
+/* macros/chain.h
+ *
+ * This include file contains the bodies of the routines which are
+ * associated with doubly linked chains and inlined.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __MACROS_CHAIN_h
+#define __MACROS_CHAIN_h
+
+/*PAGE
+ *
+ * _Chain_Are_nodes_equal
+ */
+
+#define _Chain_Are_nodes_equal( _left, _right ) \
+ ( (_left) == (_right) )
+
+/*PAGE
+ *
+ * _Chain_Is_null
+ */
+
+#define _Chain_Is_null( _the_chain ) \
+ ( (_the_chain) == NULL )
+
+/*PAGE
+ *
+ * _Chain_Is_null_node
+ */
+
+#define _Chain_Is_null_node( _the_node ) \
+ ( (_the_node) == NULL )
+
+/*PAGE
+ *
+ * _Chain_Head
+ */
+
+#define _Chain_Head( _the_chain ) \
+ ((Chain_Node *) ((void *)(_the_chain)))
+
+/*PAGE
+ *
+ * _Chain_Tail
+ */
+
+#define _Chain_Tail( _the_chain ) \
+ ((Chain_Node *) ((void *)&(_the_chain)->permanent_null))
+
+/*PAGE
+ *
+ * _Chain_Is_empty
+ */
+
+#define _Chain_Is_empty( _the_chain ) \
+ ( (_the_chain)->first == _Chain_Tail( (_the_chain) ) )
+
+/*PAGE
+ *
+ * _Chain_Is_first
+ */
+
+#define _Chain_Is_first( _the_node ) \
+ ( (the_node)->previous == NULL )
+
+/*PAGE
+ *
+ * _Chain_Is_last
+ */
+
+#define _Chain_Is_last( _the_node ) \
+ ( (_the_node)->next == NULL )
+
+/*PAGE
+ *
+ * _Chain_Has_only_one_node
+ */
+
+#define _Chain_Has_only_one_node( _the_chain ) \
+ ( (_the_chain)->first == (_the_chain)->last )
+
+/*PAGE
+ *
+ * _Chain_Is_head
+ */
+
+#define _Chain_Is_head( _the_chain, _the_node ) \
+ ( (_the_node) == _Chain_Head( (_the_chain) ) )
+
+/*PAGE
+ *
+ * _Chain_Is_tail
+ */
+
+#define _Chain_Is_tail( _the_chain, _the_node ) \
+ ( (_the_node) == _Chain_Tail( (_the_chain) ) )
+
+/*PAGE
+ *
+ * Chain_Initialize_empty
+ */
+
+#define _Chain_Initialize_empty( _the_chain ) \
+{ \
+ (_the_chain)->first = _Chain_Tail( (_the_chain) ); \
+ (_the_chain)->permanent_null = NULL; \
+ (_the_chain)->last = _Chain_Head( (_the_chain) ); \
+}
+
+/*PAGE
+ *
+ * _Chain_Extract_unprotected
+ */
+
+#define _Chain_Extract_unprotected( _the_node ) \
+{ \
+ Chain_Node *_next; \
+ Chain_Node *_previous; \
+ \
+ _next = (_the_node)->next; \
+ _previous = (_the_node)->previous; \
+ _next->previous = _previous; \
+ _previous->next = _next; \
+}
+
+/*PAGE
+ *
+ * _Chain_Get_unprotected
+ */
+
+/*PAGE
+ *
+ * Chain_Get_unprotected
+ */
+
+#define _Chain_Get_unprotected( _the_chain ) \
+ (( !_Chain_Is_empty( (_the_chain) ) ) \
+ ? _Chain_Get_first_unprotected( (_the_chain) ) \
+ : NULL)
+
+/*PAGE
+ *
+ * _Chain_Insert_unprotected
+ */
+
+#define _Chain_Insert_unprotected( _after_node, _the_node ) \
+do { \
+ Chain_Node *_before_node; \
+ \
+ (_the_node)->previous = (_after_node); \
+ _before_node = (_after_node)->next; \
+ (_after_node)->next = (_the_node); \
+ (_the_node)->next = _before_node; \
+ _before_node->previous = (_the_node); \
+} while (0)
+
+/*PAGE
+ *
+ * _Chain_Append_unprotected
+ */
+
+#define _Chain_Append_unprotected( _the_chain, _the_node ) \
+{ \
+ Chain_Node *_old_last_node; \
+ \
+ (_the_node)->next = _Chain_Tail( (_the_chain) ); \
+ _old_last_node = (_the_chain)->last; \
+ (_the_chain)->last = (_the_node); \
+ _old_last_node->next = (_the_node); \
+ (_the_node)->previous = _old_last_node; \
+}
+
+/*PAGE
+ *
+ * _Chain_Prepend_unprotected
+ */
+
+#define _Chain_Prepend_unprotected( _the_chain, _the_node ) \
+ _Chain_Insert_unprotected( _Chain_Head( (_the_chain) ), (_the_node) )
+
+/*PAGE
+ *
+ * _Chain_Prepend
+ */
+
+#define _Chain_Prepend( _the_chain, _the_node ) \
+ _Chain_Insert( _Chain_Head( (_the_chain) ), (_the_node) )
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/macros/rtems/score/coremsg.inl b/cpukit/score/macros/rtems/score/coremsg.inl
new file mode 100644
index 0000000000..488d06904b
--- /dev/null
+++ b/cpukit/score/macros/rtems/score/coremsg.inl
@@ -0,0 +1,146 @@
+/* coremsg.inl
+ *
+ * This include file contains the macro implementation of all
+ * inlined routines in the Core Message Handler.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __CORE_MESSAGE_QUEUE_inl
+#define __CORE_MESSAGE_QUEUE_inl
+
+#include <string.h> /* for memcpy */
+
+/*PAGE
+ *
+ * _CORE_message_queue_Send
+ *
+ */
+
+#define _CORE_message_queue_Send( _the_message_queue, _buffer, _size, \
+ _id, _api_message_queue_mp_support, _wait, _timeout ) \
+ _CORE_message_queue_Submit( (_the_message_queue), (_buffer), (_size), \
+ (_id), (_api_message_queue_mp_support), \
+ CORE_MESSAGE_QUEUE_SEND_REQUEST, (_wait), (_timeout) )
+
+/*PAGE
+ *
+ * _CORE_message_queue_Urgent
+ *
+ */
+
+#define _CORE_message_queue_Urgent( _the_message_queue, _buffer, _size, \
+ _id, _api_message_queue_mp_support, _wait, _timeout ) \
+ _CORE_message_queue_Submit( (_the_message_queue), (_buffer), (_size), \
+ (_id), (_api_message_queue_mp_support), \
+ CORE_MESSAGE_QUEUE_URGENT_REQUEST, (_wait), (_timeout) )
+
+/*PAGE
+ *
+ * _CORE_message_queue_Copy_buffer
+ */
+
+#define _CORE_message_queue_Copy_buffer( _source, _destination, _size ) \
+ memcpy( _destination, _source, _size)
+
+/*PAGE
+ *
+ * _CORE_message_queue_Allocate_message_buffer
+ *
+ */
+
+#define _CORE_message_queue_Allocate_message_buffer( _the_message_queue ) \
+ (CORE_message_queue_Buffer_control *) \
+ _Chain_Get( &(_the_message_queue)->Inactive_messages )
+
+/*PAGE
+ *
+ * _CORE_message_queue_Free_message_buffer
+ *
+ */
+
+#define _CORE_message_queue_Free_message_buffer( _the_message_queue, _the_message ) \
+ _Chain_Append( \
+ &(_the_message_queue)->Inactive_messages, \
+ &(_the_message)->Node \
+ )
+
+/*PAGE
+ *
+ * _CORE_message_queue_Is_priority
+ *
+ */
+
+#define _CORE_message_queue_Is_priority( _the_attribute ) \
+ ((_the_attribute)->discipline == CORE_MESSAGE_QUEUE_DISCIPLINES_PRIORITY)
+
+/*PAGE
+ *
+ * _CORE_message_queue_Get_pending_message
+ *
+ */
+
+#define _CORE_message_queue_Get_pending_message( _the_message_queue ) \
+ (CORE_message_queue_Buffer_control *) \
+ _Chain_Get_unprotected( &(_the_message_queue)->Pending_messages )
+
+/*PAGE
+ *
+ * _CORE_message_queue_Append
+ *
+ */
+
+#define _CORE_message_queue_Append( _the_message_queue, _the_message ) \
+ _Chain_Append( &(_the_message_queue)->Pending_messages, \
+ &(_the_message)->Node )
+
+/*PAGE
+ *
+ * _CORE_message_queue_Prepend
+ *
+ */
+
+#define _CORE_message_queue_Prepend( _the_message_queue, _the_message ) \
+ _Chain_Prepend( &(_the_message_queue)->Pending_messages, \
+ &(_the_message)->Node )
+
+/*PAGE
+ *
+ * _CORE_message_queue_Is_null
+ *
+ */
+
+#define _CORE_message_queue_Is_null( _the_message_queue ) \
+ ( (_the_message_queue) == NULL )
+
+/*PAGE
+ *
+ * _CORE_message_queue_Is_notify_enabled
+ *
+ */
+
+#define _CORE_message_queue_Is_notify_enabled( _the_message_queue ) \
+ ( (_the_message_queue)->notify_handler != NULL )
+
+/*PAGE
+ *
+ * _CORE_message_queue_Set_notify
+ *
+ */
+
+#define _CORE_message_queue_Set_notify( \
+ _the_message_queue, _the_handler, _the_argument ) \
+ do { \
+ (_the_message_queue)->notify_handler = (_the_handler); \
+ (_the_message_queue)->notify_argument = (_the_argument); \
+ } while ( 0 )
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/macros/rtems/score/coremutex.inl b/cpukit/score/macros/rtems/score/coremutex.inl
new file mode 100644
index 0000000000..ef020d81c5
--- /dev/null
+++ b/cpukit/score/macros/rtems/score/coremutex.inl
@@ -0,0 +1,81 @@
+/* macros/coremutex.h
+ *
+ * This include file contains all of the inlined routines associated
+ * with core mutexes.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __MACROS_CORE_MUTEX_h
+#define __MACROS_CORE_MUTEX_h
+
+
+/*PAGE
+ *
+ * _CORE_mutex_Is_locked
+ *
+ */
+
+#define _CORE_mutex_Is_locked( _the_mutex ) \
+ ( (_the_mutex)->lock == CORE_MUTEX_LOCKED )
+
+/*PAGE
+ *
+ * _CORE_mutex_Is_fifo
+ *
+ */
+
+#define _CORE_mutex_Is_fifo( _the_attribute ) \
+ ( (_the_attribute)->discipline == CORE_MUTEX_DISCIPLINES_FIFO )
+
+/*PAGE
+ *
+ * _CORE_mutex_Is_priority
+ *
+ */
+
+#define _CORE_mutex_Is_priority( _the_attribute ) \
+ ( (_the_attribute)->discipline == CORE_MUTEX_DISCIPLINES_PRIORITY )
+
+/*PAGE
+ *
+ * _CORE_mutex_Is_inherit_priority
+ *
+ */
+
+#define _CORE_mutex_Is_inherit_priority( _the_attribute ) \
+ ( (_the_attribute)->discipline == \
+ CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT )
+
+/*PAGE
+ *
+ * _CORE_mutex_Is_priority_ceiling
+ *
+ */
+
+#define _CORE_mutex_Is_priority_ceiling( _the_attribute )\
+ ( (_the_attribute)->discipline == CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING )
+
+/*PAGE
+ *
+ * _CORE_mutex_Seize_interrupt_trylock
+ *
+ * NOTE: This is not really a MACRO version of this routine.
+ * A body is in coremutexseize.c that is duplicated
+ * from the .inl by hand.
+ */
+
+int _CORE_mutex_Seize_interrupt_trylock(
+ CORE_mutex_Control *the_mutex,
+ ISR_Level *level_p
+);
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/macros/rtems/score/coresem.inl b/cpukit/score/macros/rtems/score/coresem.inl
new file mode 100644
index 0000000000..6afb95ff12
--- /dev/null
+++ b/cpukit/score/macros/rtems/score/coresem.inl
@@ -0,0 +1,71 @@
+/* macros/coresem.h
+ *
+ * This include file contains all of the inlined routines associated
+ * with core semaphores.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __MACROS_CORE_SEMAPHORE_h
+#define __MACROS_CORE_SEMAPHORE_h
+
+/*PAGE
+ *
+ * _CORE_semaphore_Is_priority
+ *
+ */
+
+#define _CORE_semaphore_Is_priority( _the_attribute ) \
+ ( (_the_attribute)->discipline == CORE_SEMAPHORE_DISCIPLINES_PRIORITY )
+
+/*PAGE
+ *
+ * _CORE_semaphore_Get_count
+ *
+ */
+
+#define _CORE_semaphore_Get_count( _the_semaphore ) \
+ ( (_the_semaphore)->count )
+
+/*PAGE
+ *
+ * _CORE_semaphore_Seize_isr_disable
+ */
+
+#define _CORE_semaphore_Seize_isr_disable( \
+ _the_semaphore, _id, _wait, _timeout, _level_p) \
+{ \
+ Thread_Control *executing; \
+ ISR_Level level = *(_level_p); \
+ \
+ /* disabled when you get here */ \
+ \
+ executing = _Thread_Executing; \
+ executing->Wait.return_code = CORE_SEMAPHORE_STATUS_SUCCESSFUL; \
+ if ( (_the_semaphore)->count != 0 ) { \
+ (_the_semaphore)->count -= 1; \
+ _ISR_Enable( level ); \
+ } else if ( !(_wait) ) { \
+ _ISR_Enable( level ); \
+ executing->Wait.return_code = CORE_SEMAPHORE_STATUS_UNSATISFIED_NOWAIT; \
+ } else { \
+ _Thread_Disable_dispatch(); \
+ _Thread_queue_Enter_critical_section( &(_the_semaphore)->Wait_queue ); \
+ executing->Wait.queue = &(_the_semaphore)->Wait_queue; \
+ executing->Wait.id = (_id); \
+ _ISR_Enable( level ); \
+ \
+ _Thread_queue_Enqueue( &(_the_semaphore)->Wait_queue, (_timeout) ); \
+ _Thread_Enable_dispatch(); \
+ } \
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/macros/rtems/score/heap.inl b/cpukit/score/macros/rtems/score/heap.inl
new file mode 100644
index 0000000000..9c0b3cc77c
--- /dev/null
+++ b/cpukit/score/macros/rtems/score/heap.inl
@@ -0,0 +1,149 @@
+/* heap.inl
+ *
+ * This file contains the macro implementation of the inlined
+ * routines from the heap handler.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __HEAP_inl
+#define __HEAP_inl
+
+#include <rtems/score/address.h>
+
+/*PAGE
+ *
+ * _Heap_Head
+ */
+
+#define _Heap_Head( _the_heap ) \
+ ((Heap_Block *)&(_the_heap)->start)
+
+/*PAGE
+ *
+ * _Heap_Tail
+ */
+
+#define _Heap_Tail( _the_heap ) \
+ ((Heap_Block *)&(_the_heap)->final)
+
+/*PAGE
+ *
+ * _Heap_Previous_block
+ */
+
+#define _Heap_Previous_block( _the_block ) \
+ ( (Heap_Block *) _Addresses_Subtract_offset( \
+ (void *)(_the_block), \
+ (_the_block)->back_flag & ~ HEAP_BLOCK_USED \
+ ) \
+ )
+
+/*PAGE
+ *
+ * _Heap_Next_block
+ */
+
+#define _Heap_Next_block( _the_block ) \
+ ( (Heap_Block *) _Addresses_Add_offset( \
+ (void *)(_the_block), \
+ (_the_block)->front_flag & ~ HEAP_BLOCK_USED \
+ ) \
+ )
+
+/*PAGE
+ *
+ * _Heap_Block_at
+ */
+
+#define _Heap_Block_at( _base, _offset ) \
+ ( (Heap_Block *) \
+ _Addresses_Add_offset( (void *)(_base), (_offset) ) )
+
+/*PAGE
+ *
+ * _Heap_User_block_at
+ *
+ */
+
+#define _Heap_User_block_at( _base ) \
+ _Heap_Block_at( \
+ (_base), \
+ -*(((uint32_t *) (_base)) - 1) + -HEAP_BLOCK_USED_OVERHEAD \
+ )
+
+/*PAGE
+ *
+ * _Heap_Is_previous_block_free
+ */
+
+#define _Heap_Is_previous_block_free( _the_block ) \
+ ( !((_the_block)->back_flag & HEAP_BLOCK_USED) )
+
+/*PAGE
+ *
+ * _Heap_Is_block_free
+ */
+
+#define _Heap_Is_block_free( _the_block ) \
+ ( !((_the_block)->front_flag & HEAP_BLOCK_USED) )
+
+/*PAGE
+ *
+ * _Heap_Is_block_used
+ */
+
+#define _Heap_Is_block_used( _the_block ) \
+ ((_the_block)->front_flag & HEAP_BLOCK_USED)
+
+/*PAGE
+ *
+ * _Heap_Block_size
+ */
+
+#define _Heap_Block_size( _the_block ) \
+ ((_the_block)->front_flag & ~HEAP_BLOCK_USED)
+
+/*PAGE
+ *
+ * _Heap_Start_of_user_area
+ */
+
+#define _Heap_Start_of_user_area( _the_block ) \
+ ((void *) &(_the_block)->next)
+
+/*PAGE
+ *
+ * _Heap_Is_block_in
+ */
+
+#define _Heap_Is_block_in( _the_heap, _the_block ) \
+ ( ((_the_block) >= (_the_heap)->start) && \
+ ((_the_block) <= (_the_heap)->final) )
+
+/*PAGE
+ *
+ * _Heap_Is_page_size_valid
+ */
+
+#define _Heap_Is_page_size_valid( _page_size ) \
+ ( ((_page_size) != 0) && \
+ (((_page_size) % CPU_HEAP_ALIGNMENT) == 0) )
+
+/*PAGE
+ *
+ * _Heap_Build_flag
+ */
+
+#define _Heap_Build_flag( _size, _in_use_flag ) \
+ ( (_size) | (_in_use_flag))
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/macros/rtems/score/isr.inl b/cpukit/score/macros/rtems/score/isr.inl
new file mode 100644
index 0000000000..7ffb9cc210
--- /dev/null
+++ b/cpukit/score/macros/rtems/score/isr.inl
@@ -0,0 +1,38 @@
+/* isr.inl
+ *
+ * This include file contains the macro implementation of all
+ * inlined routines in the Interrupt Handler.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __ISR_inl
+#define __ISR_inl
+
+/*PAGE
+ *
+ * _ISR_Is_vector_number_valid
+ *
+ */
+
+#define _ISR_Is_vector_number_valid( _vector ) \
+ ( (_vector) <= CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER )
+
+/*PAGE
+ *
+ * _ISR_Is_valid_user_handler
+ *
+ */
+
+#define _ISR_Is_valid_user_handler( _handler ) \
+ ((_handler) != NULL)
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/macros/rtems/score/mppkt.inl b/cpukit/score/macros/rtems/score/mppkt.inl
new file mode 100644
index 0000000000..155a48e775
--- /dev/null
+++ b/cpukit/score/macros/rtems/score/mppkt.inl
@@ -0,0 +1,40 @@
+/* macros/mppkt.h
+ *
+ * This package is the implementation of the Packet Handler
+ * routines which are inlined.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __MACROS_MP_PACKET_h
+#define __MACROS_MP_PACKET_h
+
+/*PAGE
+ *
+ * _Mp_packet_Is_valid_packet_class
+ *
+ * NOTE: Check for lower bounds (MP_PACKET_CLASSES_FIRST ) is unnecessary
+ * because this enum starts at lower bound of zero.
+ */
+
+#define _Mp_packet_Is_valid_packet_class( _the_packet_class ) \
+ ( (_the_packet_class) <= MP_PACKET_CLASSES_LAST )
+
+/*PAGE
+ *
+ * _Mp_packet_Is_null
+ *
+ */
+
+#define _Mp_packet_Is_null ( _the_packet ) \
+ ( (_the_packet) == NULL )
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/macros/rtems/score/object.inl b/cpukit/score/macros/rtems/score/object.inl
new file mode 100644
index 0000000000..79702927f9
--- /dev/null
+++ b/cpukit/score/macros/rtems/score/object.inl
@@ -0,0 +1,188 @@
+/* object.inl
+ *
+ * This include file contains the macro implementation of all
+ * of the inlined routines in the Object Handler.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __OBJECTS_inl
+#define __OBJECTS_inl
+
+/*PAGE
+ *
+ * _Objects_Build_id
+ *
+ */
+
+#define _Objects_Build_id( _the_api, _the_class, _node, _index ) \
+ ( (( (Objects_Id) _the_api ) << OBJECTS_API_START_BIT) | \
+ (( (Objects_Id) _the_class ) << OBJECTS_CLASS_START_BIT) | \
+ (( (Objects_Id) _node ) << OBJECTS_NODE_START_BIT) | \
+ (( (Objects_Id) _index ) << OBJECTS_INDEX_START_BIT) )
+
+/*PAGE
+ *
+ * _Objects_Get_API
+ */
+
+#define _Objects_Get_API( _id ) \
+ (Objects_APIs) \
+ (((_id) >> OBJECTS_API_START_BIT) & OBJECTS_API_VALID_BITS)
+
+/*PAGE
+ *
+ * _Objects_Get_class
+ */
+
+#define _Objects_Get_class( _id ) \
+ (uint32_t ) \
+ (((_id) >> OBJECTS_CLASS_START_BIT) & OBJECTS_CLASS_VALID_BITS)
+
+/*PAGE
+ *
+ * _Objects_Get_node
+ *
+ */
+
+#define _Objects_Get_node( _id ) \
+ (((_id) >> OBJECTS_NODE_START_BIT) & OBJECTS_NODE_VALID_BITS)
+
+/*PAGE
+ *
+ * _Objects_Get_index
+ *
+ */
+
+#define _Objects_Get_index( _id ) \
+ (((_id) >> OBJECTS_INDEX_START_BIT) & OBJECTS_INDEX_VALID_BITS)
+
+/*PAGE
+ *
+ * _Objects_Is_class_valid
+ *
+ */
+
+#define _Objects_Is_class_valid( _the_class ) \
+ ( (_the_class) /* XXX && (_the_class) <= OBJECTS_CLASSES_LAST */ )
+
+/*PAGE
+ *
+ * _Objects_Is_local_node
+ *
+ */
+
+#define _Objects_Is_local_node( _node ) \
+ ( (_node) == _Objects_Local_node )
+
+/*PAGE
+ *
+ * _Objects_Is_local_id
+ *
+ */
+
+#define _Objects_Is_local_id( _id ) \
+ _Objects_Is_local_node( _Objects_Get_node(_id) )
+
+/*PAGE
+ *
+ * _Objects_Are_ids_equal
+ *
+ */
+
+#define _Objects_Are_ids_equal( _left, _right ) \
+ ( (_left) == (_right) )
+
+/*PAGE
+ *
+ * _Objects_Get_local_object
+ *
+ */
+
+#define _Objects_Get_local_object( _information, _index ) \
+ ( ( (_index) > (_information)->maximum) ? NULL : \
+ (_information)->local_table[ (_index) ] )
+
+/*PAGE
+ *
+ * _Objects_Set_local_object
+ *
+ */
+
+#define _Objects_Set_local_object( information, index, the_object ) \
+ { \
+ if ( index <= information->maximum) \
+ information->local_table[ index ] = the_object; \
+ }
+
+
+/*PAGE
+ *
+ * _Objects_Get_information
+ *
+ */
+
+#define _Objects_Get_information( id ) \
+ ( \
+ ( !_Objects_Is_class_valid( _Objects_Get_class( id ) ) ) ? \
+ NULL : \
+ _Objects_Information_table[ _Objects_Get_API( id ) ] \
+ [ _Objects_Get_class( id ) ] \
+ )
+
+/*PAGE
+ *
+ * _Objects_Open
+ *
+ */
+
+#define _Objects_Open( _information, _the_object, _name ) \
+ do { \
+ uint32_t _index; \
+ \
+ _index = _Objects_Get_index( (_the_object)->id ); \
+ (_information)->local_table[ _index ] = (_the_object); \
+ \
+ if ( (_information)->is_string ) \
+ /* _Objects_Copy_name_string( (_name), (_the_object)->name ); */\
+ (_the_object)->name = (_name); \
+ else \
+ /* _Objects_Copy_name_raw( \
+ (_name), (_the_object)->name, (_information)->name_length ); */ \
+ (_the_object)->name = (_name); \
+ } while (0)
+
+/*PAGE
+ *
+ * _Objects_Close
+ *
+ */
+
+#define _Objects_Close( _information, _the_object ) \
+ do { \
+ uint32_t _index; \
+ \
+ _index = _Objects_Get_index( (_the_object)->id ); \
+ (_information)->local_table[ _index ] = (Objects_Control *) NULL; \
+ /* _Objects_Clear_name( (_the_object)->name, (_information)->name_length ); */ \
+ (_the_object)->name = 0; \
+ } while (0)
+
+/*PAGE
+ *
+ * _Objects_Namespace_remove
+ */
+
+#define _Objects_Namespace_remove( _information, _the_object ) \
+ (_the_object)->name = 0; \
+ /* _Objects_Clear_name( (_the_object)->name, (_information)->name_length ) */
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/macros/rtems/score/objectmp.inl b/cpukit/score/macros/rtems/score/objectmp.inl
new file mode 100644
index 0000000000..c8952b4f2d
--- /dev/null
+++ b/cpukit/score/macros/rtems/score/objectmp.inl
@@ -0,0 +1,49 @@
+/* macros/objectmp.inl
+ *
+ * This include file contains the bodies of all inlined routines
+ * which deal with global objects.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __MACROS_MP_OBJECTS_inl
+#define __MACROS_MP_OBJECTS_inl
+
+/*PAGE
+ *
+ * _Objects_MP_Allocate_global_object
+ *
+ */
+
+#define _Objects_MP_Allocate_global_object() \
+ (Objects_MP_Control *) \
+ _Chain_Get( &_Objects_MP_Inactive_global_objects )
+
+/*PAGE
+ * _Objects_MP_Free_global_object
+ *
+ */
+
+#define _Objects_MP_Free_global_object( _the_object ) \
+ _Chain_Append( \
+ &_Objects_MP_Inactive_global_objects, \
+ &(_the_object)->Object.Node \
+ )
+
+/*PAGE
+ * _Objects_MP_Is_null_global_object
+ *
+ */
+
+#define _Objects_MP_Is_null_global_object( _the_object ) \
+ ( (_the_object) == NULL )
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/macros/rtems/score/priority.inl b/cpukit/score/macros/rtems/score/priority.inl
new file mode 100644
index 0000000000..057f36ea65
--- /dev/null
+++ b/cpukit/score/macros/rtems/score/priority.inl
@@ -0,0 +1,169 @@
+/* priority.inl
+ *
+ * This file contains the macro implementation of all inlined routines
+ * in the Priority Handler.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __PRIORITY_inl
+#define __PRIORITY_inl
+
+#include <rtems/score/bitfield.h>
+
+/*PAGE
+ *
+ * _Priority_Handler_initialization
+ *
+ */
+
+#define _Priority_Handler_initialization() \
+ { \
+ uint32_t index; \
+ \
+ _Priority_Major_bit_map = 0; \
+ for ( index=0 ; index <16 ; index++ ) \
+ _Priority_Bit_map[ index ] = 0; \
+ }
+
+/*PAGE
+ *
+ * _Priority_Is_valid
+ *
+ */
+
+ /*
+ * Since PRIORITY_MINIMUM is 0 and priorities are stored unsigned,
+ * then checking for less than 0 is unnecessary.
+ */
+
+#define _Priority_Is_valid( _the_priority ) \
+ ( (_the_priority) <= PRIORITY_MAXIMUM )
+
+/*PAGE
+ *
+ * _Priority_Major
+ *
+ */
+
+#define _Priority_Major( _the_priority ) ( (_the_priority) / 16 )
+
+/*PAGE
+ *
+ * _Priority_Minor
+ *
+ */
+
+#define _Priority_Minor( _the_priority ) ( (_the_priority) % 16 )
+
+#if ( CPU_USE_GENERIC_BITFIELD_CODE == TRUE )
+
+/*PAGE
+ *
+ * _Priority_Mask
+ *
+ */
+
+#define _Priority_Mask( _bit_number ) \
+ (0x8000 >> _bit_number)
+
+/*PAGE
+ *
+ * _Priority_Bits_index
+ *
+ */
+
+#define _Priority_Bits_index( _bit_number ) \
+ (_bit_number)
+
+#endif
+
+/*PAGE
+ *
+ * _Priority_Add_to_bit_map
+ *
+ */
+
+#define _Priority_Add_to_bit_map( _the_priority_map ) \
+ { \
+ *(_the_priority_map)->minor |= (_the_priority_map)->ready_minor; \
+ _Priority_Major_bit_map |= (_the_priority_map)->ready_major; \
+ }
+
+/*PAGE
+ *
+ * _Priority_Remove_from_bit_map
+ *
+ */
+
+#define _Priority_Remove_from_bit_map( _the_priority_map ) \
+ { \
+ *(_the_priority_map)->minor &= (_the_priority_map)->block_minor; \
+ if ( *(_the_priority_map)->minor == 0 ) \
+ _Priority_Major_bit_map &= (_the_priority_map)->block_major; \
+ }
+
+/*PAGE
+ *
+ * _Priority_Get_highest
+ *
+ */
+
+#define _Priority_Get_highest( _high_priority ) \
+ { \
+ Priority_Bit_map_control minor; \
+ Priority_Bit_map_control major; \
+ \
+ _Bitfield_Find_first_bit( _Priority_Major_bit_map, major ); \
+ _Bitfield_Find_first_bit( _Priority_Bit_map[major], minor ); \
+ \
+ (_high_priority) = (_Priority_Bits_index( major ) * 16) + \
+ _Priority_Bits_index( minor ); \
+ }
+
+/*PAGE
+ *
+ * _Priority_Initialize_information
+ *
+ */
+
+#define _Priority_Initialize_information( \
+ _the_priority_map, _new_priority ) \
+ { \
+ Priority_Bit_map_control _major; \
+ Priority_Bit_map_control _minor; \
+ Priority_Bit_map_control _mask; \
+ \
+ _major = _Priority_Major( (_new_priority) ); \
+ _minor = _Priority_Minor( (_new_priority) ); \
+ \
+ (_the_priority_map)->minor = \
+ &_Priority_Bit_map[ _Priority_Bits_index(_major) ]; \
+ \
+ _mask = _Priority_Mask( _major ); \
+ (_the_priority_map)->ready_major = _mask; \
+ (_the_priority_map)->block_major = ~_mask; \
+ \
+ _mask = _Priority_Mask( _minor ); \
+ (_the_priority_map)->ready_minor = _mask; \
+ (_the_priority_map)->block_minor = ~_mask; \
+ }
+
+/*PAGE
+ *
+ * _Priority_Is_group_empty
+ *
+ */
+
+#define _Priority_Is_group_empty ( _the_priority ) \
+ ( (_the_priority) == 0 )
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/macros/rtems/score/stack.inl b/cpukit/score/macros/rtems/score/stack.inl
new file mode 100644
index 0000000000..3b3deb6bbf
--- /dev/null
+++ b/cpukit/score/macros/rtems/score/stack.inl
@@ -0,0 +1,49 @@
+/* stack.inl
+ *
+ * This file contains the macro implementation of the inlined
+ * routines from the Stack Handler.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __STACK_inl
+#define __STACK_inl
+
+/*PAGE
+ *
+ * _Stack_Initialize
+ *
+ */
+
+#define _Stack_Initialize( _the_stack, _starting_address, _size ) \
+ { \
+ (_the_stack)->area = (_starting_address); \
+ (_the_stack)->size = (_size); \
+ }
+
+/*PAGE
+ *
+ * _Stack_Is_enough
+ *
+ */
+
+#define _Stack_Is_enough( _size ) \
+ ( (_size) >= STACK_MINIMUM_SIZE )
+
+/*PAGE
+ *
+ * _Stack_Adjust_size
+ */
+
+#define _Stack_Adjust_size( _size ) \
+ ((_size) + CPU_STACK_ALIGNMENT)
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/macros/rtems/score/states.inl b/cpukit/score/macros/rtems/score/states.inl
new file mode 100644
index 0000000000..545271dc79
--- /dev/null
+++ b/cpukit/score/macros/rtems/score/states.inl
@@ -0,0 +1,209 @@
+/* states.inl
+ *
+ * This file contains the macro implementation of the inlined
+ * routines associated with thread state information.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __STATES_inl
+#define __STATES_inl
+
+/*PAGE
+ *
+ * _States_Set
+ *
+ */
+
+#define _States_Set( _states_to_set, _current_state ) \
+ ((_current_state) | (_states_to_set))
+
+/*PAGE
+ *
+ * _States_Clear
+ *
+ */
+
+#define _States_Clear( _states_to_clear, _current_state ) \
+ ((_current_state) & ~(_states_to_clear))
+
+/*PAGE
+ *
+ * _States_Is_ready
+ *
+ */
+
+#define _States_Is_ready( _the_states ) \
+ ( (_the_states) == STATES_READY )
+
+/*PAGE
+ *
+ * _States_Is_only_dormant
+ *
+ */
+
+#define _States_Is_only_dormant( _the_states ) \
+ ( (_the_states) == STATES_DORMANT )
+
+/*PAGE
+ *
+ * _States_Is_dormant
+ *
+ */
+
+#define _States_Is_dormant( _the_states ) \
+ ( (_the_states) & STATES_DORMANT )
+
+/*PAGE
+ *
+ * _States_Is_suspended
+ *
+ */
+
+#define _States_Is_suspended( _the_states ) \
+ ( (_the_states) & STATES_SUSPENDED )
+
+/*PAGE
+ *
+ * _States_Is_Transient
+ *
+ */
+
+#define _States_Is_transient( _the_states ) \
+ ( (_the_states) & STATES_TRANSIENT )
+
+/*PAGE
+ *
+ * _States_Is_delaying
+ *
+ */
+
+#define _States_Is_delaying( _the_states ) \
+ ( (_the_states) & STATES_DELAYING )
+
+/*PAGE
+ *
+ * _States_Is_waiting_for_buffer
+ *
+ */
+
+#define _States_Is_waiting_for_buffer( _the_states ) \
+ ( (_the_states) & STATES_WAITING_FOR_BUFFER )
+
+/*PAGE
+ *
+ * _States_Is_waiting_for_segment
+ *
+ */
+
+#define _States_Is_waiting_for_segment( _the_states ) \
+ ( (_the_states) & STATES_WAITING_FOR_SEGMENT )
+
+/*PAGE
+ *
+ * _States_Is_waiting_for_message
+ *
+ */
+
+#define _States_Is_waiting_for_message( _the_states ) \
+ ( (_the_states) & STATES_WAITING_FOR_MESSAGE )
+
+/*PAGE
+ *
+ * _States_Is_waiting_for_event
+ *
+ */
+
+#define _States_Is_waiting_for_event( _the_states ) \
+ ( (_the_states) & STATES_WAITING_FOR_EVENT )
+
+/*PAGE
+ *
+ * _States_Is_waiting_for_mutex
+ *
+ */
+
+#define _States_Is_waiting_for_mutex( _the_states ) \
+ ( (_the_states) & STATES_WAITING_FOR_MUTEX )
+
+/*PAGE
+ *
+ * _States_Is_waiting_for_semaphore
+ *
+ */
+
+#define _States_Is_waiting_for_semaphore( _the_states ) \
+ ( (_the_states) & STATES_WAITING_FOR_SEMAPHORE )
+
+/*PAGE
+ *
+ * _States_Is_waiting_for_time
+ *
+ */
+
+#define _States_Is_waiting_for_time( _the_states ) \
+ ( (_the_states) & STATES_WAITING_FOR_TIME )
+
+/*PAGE
+ *
+ * _States_Is_waiting_for_rpc_reply
+ *
+ */
+
+#define _States_Is_waiting_for_rpc_reply( _the_states ) \
+ ( (_the_states) & STATES_WAITING_FOR_RPC_REPLY )
+
+/*PAGE
+ *
+ * _States_Is_waiting_for_period
+ *
+ */
+
+#define _States_Is_waiting_for_period( _the_states ) \
+ ( (_the_states) & STATES_WAITING_FOR_PERIOD )
+
+/*PAGE
+ *
+ * _States_Is_locally_blocked
+ *
+ */
+
+#define _States_Is_locally_blocked( _the_states ) \
+ ( (_the_states) & STATES_LOCALLY_BLOCKED )
+
+/*PAGE
+ *
+ * _States_Is_waiting_on_thread_queue
+ *
+ */
+
+#define _States_Is_waiting_on_thread_queue( _the_states ) \
+ ( (_the_states) & STATES_WAITING_ON_THREAD_QUEUE )
+
+/*PAGE
+ *
+ * _States_Is_blocked
+ *
+ */
+
+#define _States_Is_blocked( _the_states ) \
+ ( (_the_states) & STATES_BLOCKED )
+
+/*PAGE
+ *
+ * _States_Are_set
+ *
+ */
+
+#define _States_Are_set( _the_states, _mask ) \
+ ( ((_the_states) & (_mask)) != STATES_READY )
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/macros/rtems/score/sysstate.inl b/cpukit/score/macros/rtems/score/sysstate.inl
new file mode 100644
index 0000000000..b19bf67386
--- /dev/null
+++ b/cpukit/score/macros/rtems/score/sysstate.inl
@@ -0,0 +1,89 @@
+/* sysstates.inl
+ *
+ * This file contains the macro implementation of routines regarding the
+ * system state.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __SYSTEM_STATE_inl
+#define __SYSTEM_STATE_inl
+
+/*PAGE
+ *
+ * _System_state_Handler_initialization
+ */
+
+#define _System_state_Handler_initialization( _is_multiprocessing ) \
+ do { \
+ _System_state_Current = SYSTEM_STATE_BEFORE_INITIALIZATION; \
+ _System_state_Is_multiprocessing = (_is_multiprocessing); \
+ } while ( 0 )
+
+/*PAGE
+ *
+ * _System_state_Set
+ */
+
+#define _System_state_Set( _state ) \
+ do { \
+ _System_state_Current = (_state); \
+ } while ( 0 )
+
+/*PAGE
+ *
+ * _System_state_Get
+ */
+
+#define _System_state_Get() \
+ (_System_state_Current)
+
+/*PAGE
+ *
+ * _System_state_Is_before_initialization
+ */
+
+#define _System_state_Is_before_initialization( _state ) \
+ ((_state) == SYSTEM_STATE_BEFORE_INITIALIZATION)
+
+/*PAGE
+ *
+ * _System_state_Is_before_multitasking
+ */
+
+#define _System_state_Is_before_multitasking( _state ) \
+ ((_state) == SYSTEM_STATE_BEFORE_MULTITASKING)
+
+/*PAGE
+ *
+ * _System_state_Is_begin_multitasking
+ */
+
+#define _System_state_Is_begin_multitasking( _state ) \
+ ((_state) == SYSTEM_STATE_BEGIN_MULTITASKING)
+
+/*PAGE
+ *
+ * _System_state_Is_up
+ */
+
+#define _System_state_Is_up( _state ) \
+ ((_state) == SYSTEM_STATE_UP)
+
+/*PAGE
+ *
+ * _System_state_Is_failed
+ */
+
+#define _System_state_Is_failed( _state ) \
+ ((_state) == SYSTEM_STATE_FAILED)
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/macros/rtems/score/thread.inl b/cpukit/score/macros/rtems/score/thread.inl
new file mode 100644
index 0000000000..090552e845
--- /dev/null
+++ b/cpukit/score/macros/rtems/score/thread.inl
@@ -0,0 +1,234 @@
+/* thread.inl
+ *
+ * This file contains the macro implementation of the inlined
+ * routines from the Thread handler.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __THREAD_inl
+#define __THREAD_inl
+
+/*PAGE
+ *
+ * _Thread_Stop_multitasking
+ *
+ */
+
+#define _Thread_Stop_multitasking() \
+ _Context_Switch( &_Thread_Executing->Registers, &_Thread_BSP_context );
+
+/*PAGE
+ *
+ * _Thread_Is_executing
+ *
+ */
+
+#define _Thread_Is_executing( _the_thread ) \
+ ( (_the_thread) == _Thread_Executing )
+
+/*PAGE
+ *
+ * _Thread_Is_heir
+ *
+ */
+
+#define _Thread_Is_heir( _the_thread ) \
+ ( (_the_thread) == _Thread_Heir )
+
+/*PAGE
+ *
+ * _Thread_Is_executing_also_the_heir
+ *
+ */
+
+#define _Thread_Is_executing_also_the_heir() \
+ ( _Thread_Executing == _Thread_Heir )
+
+/*PAGE
+ *
+ * _Thread_Unblock
+ *
+ */
+
+#define _Thread_Unblock( _the_thread ) \
+ _Thread_Clear_state( (_the_thread), STATES_BLOCKED );
+
+/*PAGE
+ *
+ * _Thread_Restart_self
+ *
+ */
+
+#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+#define _Thread_Restart_self() \
+ { \
+ if ( _Thread_Executing->fp_context != NULL ) \
+ _Context_Restore_fp( &_Thread_Executing->fp_context ); \
+ \
+ _CPU_Context_Restart_self( &_Thread_Executing->Registers ); \
+ }
+#else
+#define _Thread_Restart_self() \
+ { \
+ _CPU_Context_Restart_self( &_Thread_Executing->Registers ); \
+ }
+#endif
+
+/*PAGE
+ *
+ * _Thread_Calculate_heir
+ *
+ */
+
+#define _Thread_Calculate_heir() \
+ { \
+ Priority_Control highest; \
+ \
+ _Priority_Get_highest( highest ); \
+ \
+ _Thread_Heir = (Thread_Control *) _Thread_Ready_chain[ highest ].first; \
+ }
+
+/*PAGE
+ *
+ * _Thread_Is_allocated_fp
+ *
+ */
+
+#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+#define _Thread_Is_allocated_fp( _the_thread ) \
+ ( (_the_thread) == _Thread_Allocated_fp )
+#endif
+
+/*PAGE
+ *
+ * _Thread_Deallocate_fp
+ *
+ */
+
+#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+#define _Thread_Deallocate_fp() \
+ _Thread_Allocated_fp = NULL
+#endif
+
+/*PAGE
+ *
+ * _Thread_Disable_dispatch
+ *
+ */
+
+#define _Thread_Disable_dispatch() \
+ _Thread_Dispatch_disable_level += 1
+
+/*PAGE
+ *
+ * _Thread_Enable_dispatch
+ *
+ */
+
+#if ( CPU_INLINE_ENABLE_DISPATCH == TRUE )
+#define _Thread_Enable_dispatch() \
+ { if ( (--_Thread_Dispatch_disable_level) == 0 ) \
+ _Thread_Dispatch(); \
+ }
+#endif
+
+#if ( CPU_INLINE_ENABLE_DISPATCH == FALSE )
+void _Thread_Enable_dispatch( void );
+#endif
+
+/*PAGE
+ *
+ * _Thread_Unnest_dispatch
+ *
+ */
+
+#define _Thread_Unnest_dispatch() \
+ _Thread_Dispatch_disable_level -= 1
+
+/*PAGE
+ *
+ * _Thread_Is_dispatching_enabled
+ *
+ */
+
+#define _Thread_Is_dispatching_enabled() \
+ ( _Thread_Dispatch_disable_level == 0 )
+
+/*PAGE
+ *
+ * _Thread_Is_context_switch_necessary
+ *
+ */
+
+#define _Thread_Is_context_switch_necessary() \
+ ( _Context_Switch_necessary == TRUE )
+
+/*PAGE
+ *
+ * _Thread_Dispatch_initialization
+ *
+ */
+
+#define _Thread_Dispatch_initialization() \
+ _Thread_Dispatch_disable_level = 1
+
+/*PAGE
+ *
+ * _Thread_Is_null
+ *
+ */
+
+#define _Thread_Is_null( _the_thread ) \
+ ( (_the_thread) == NULL )
+
+/*
+ * _Thread_Is_proxy_blocking
+ *
+ */
+
+#define _Thread_Is_proxy_blocking( _code ) \
+ ( (_code) == THREAD_STATUS_PROXY_BLOCKING )
+
+/*
+ * _Thread_Internal_allocate
+ *
+ */
+
+#define _Thread_Internal_allocate() \
+ ((Thread_Control *) _Objects_Allocate( &_Thread_Internal_information ))
+
+/*
+ * _Thread_Internal_free
+ *
+ */
+
+#define _Thread_Internal_free( _the_task ) \
+ _Objects_Free( &_Thread_Internal_information, &(_the_task)->Object )
+
+/*
+ * _Thread_Get_libc_reent
+ */
+
+#define _Thread_Get_libc_reent() \
+ (_Thread_libc_reent)
+
+/*
+ * _Thread_Set_libc_reent
+ */
+
+#define _Thread_Set_libc_reent(_libc_reent) \
+ do { \
+ _Thread_libc_reent = (_libc_reent); \
+ } while (0)
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/macros/rtems/score/threadmp.inl b/cpukit/score/macros/rtems/score/threadmp.inl
new file mode 100644
index 0000000000..c78789e255
--- /dev/null
+++ b/cpukit/score/macros/rtems/score/threadmp.inl
@@ -0,0 +1,49 @@
+/* macros/threadmp.h
+ *
+ * This include file contains the bodies of all inlined routines
+ * for the multiprocessing part of thread package.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __MACROS_MP_THREAD_h
+#define __MACROS_MP_THREAD_h
+
+/*PAGE
+ *
+ * _Thread_MP_Is_receive
+ *
+ */
+
+#define _Thread_MP_Is_receive( _the_thread ) \
+ ( (_the_thread) == _Thread_MP_Receive)
+
+/*PAGE
+ *
+ * _Thread_MP_Free_proxy
+ *
+ */
+
+#define _Thread_MP_Free_proxy( _the_thread ) \
+{ \
+ Thread_Proxy_control *_the_proxy; \
+ \
+ _the_proxy = (Thread_Proxy_control *) (_the_thread); \
+ \
+ _Chain_Extract( &_the_proxy->Active ); \
+ \
+ _Chain_Append( \
+ &_Thread_MP_Inactive_proxies, \
+ &(_the_thread)->Object.Node \
+ ); \
+}
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/macros/rtems/score/tod.inl b/cpukit/score/macros/rtems/score/tod.inl
new file mode 100644
index 0000000000..850a53acb9
--- /dev/null
+++ b/cpukit/score/macros/rtems/score/tod.inl
@@ -0,0 +1,48 @@
+/* tod.inl
+ *
+ * This file contains the macro implementation of the inlined routines
+ * from the Time of Day Handler.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __TIME_OF_DAY_inl
+#define __TIME_OF_DAY_inl
+
+/*PAGE
+ *
+ * _TOD_Tickle_ticks
+ *
+ */
+
+#define _TOD_Tickle_ticks() \
+ _TOD_Current.ticks++; \
+ _Watchdog_Ticks_since_boot++
+
+/*PAGE
+ *
+ * _TOD_Deactivate
+ *
+ */
+
+#define _TOD_Deactivate() \
+ _Watchdog_Remove( &_TOD_Seconds_watchdog )
+
+/*PAGE
+ *
+ * _TOD_Activate
+ *
+ */
+
+#define _TOD_Activate( _ticks ) \
+ _Watchdog_Insert_ticks( &_TOD_Seconds_watchdog, (_ticks) )
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/macros/rtems/score/tqdata.inl b/cpukit/score/macros/rtems/score/tqdata.inl
new file mode 100644
index 0000000000..35145ff971
--- /dev/null
+++ b/cpukit/score/macros/rtems/score/tqdata.inl
@@ -0,0 +1,49 @@
+/* tqdata.inl
+ *
+ * This file contains the macro implementation of the inlined
+ * routines needed to support the Thread Queue Data.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __THREAD_QUEUE_DATA_inl
+#define __THREAD_QUEUE_DATA_inl
+
+/*PAGE
+ *
+ * _Thread_queue_Header_number
+ *
+ */
+
+#define _Thread_queue_Header_number( _the_priority ) \
+ ((_the_priority) / TASK_QUEUE_DATA_PRIORITIES_PER_HEADER)
+
+/*PAGE
+ *
+ * _Thread_queue_Is_reverse_search
+ *
+ */
+
+#define _Thread_queue_Is_reverse_search( _the_priority ) \
+ ( (_the_priority) & TASK_QUEUE_DATA_REVERSE_SEARCH_MASK )
+
+/*PAGE
+ *
+ * _Thread_queue_Enter_critical_section
+ *
+ */
+
+#define _Thread_queue_Enter_critical_section( _the_thread_queue ) \
+ do { \
+ (_the_thread_queue)->sync_state = THREAD_QUEUE_NOTHING_HAPPENED; \
+ } while ( 0 )
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/macros/rtems/score/userext.inl b/cpukit/score/macros/rtems/score/userext.inl
new file mode 100644
index 0000000000..cbb72b24f9
--- /dev/null
+++ b/cpukit/score/macros/rtems/score/userext.inl
@@ -0,0 +1,133 @@
+/* userext.inl
+ *
+ * This file contains the macro implementation of the inlined routines
+ * from the User Extension Handler
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __USER_EXTENSIONS_inl
+#define __USER_EXTENSIONS_inl
+
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _User_extensions_Add_set
+ *
+ * NOTE: Must be before _User_extensions_Handler_initialization to
+ * ensure proper inlining.
+ */
+
+#define _User_extensions_Add_set( _the_extension, _extension_table ) \
+ do { \
+ (_the_extension)->Callouts = *(_extension_table); \
+ \
+ _Chain_Append( &_User_extensions_List, &(_the_extension)->Node ); \
+ \
+ if ( (_the_extension)->Callouts.thread_switch != NULL ) { \
+ (_the_extension)->Switch.thread_switch = \
+ (_the_extension)->Callouts.thread_switch; \
+ _Chain_Append( \
+ &_User_extensions_Switches_list, \
+ &(_the_extension)->Switch.Node \
+ ); \
+ } \
+ } while ( 0 )
+
+
+/*PAGE
+ *
+ * _User_extensions_Handler_initialization
+ *
+ */
+
+#define _User_extensions_Handler_initialization( \
+ _number_of_extensions, _initial_extensions \
+) \
+ { \
+ User_extensions_Control *extension; \
+ uint32_t i; \
+ \
+ _Chain_Initialize_empty( &_User_extensions_List ); \
+ _Chain_Initialize_empty( &_User_extensions_Switches_list ); \
+ \
+ if ( (_initial_extensions) ) { \
+ extension = (User_extensions_Control *) \
+ _Workspace_Allocate_or_fatal_error( \
+ sizeof(User_extensions_Control) * _number_of_extensions ); \
+ \
+ memset ( \
+ extension, \
+ 0, \
+ _number_of_extensions * sizeof( User_extensions_Control ) \
+ ); \
+ \
+ for ( i = 0 ; i < _number_of_extensions ; i++ ) { \
+ _User_extensions_Add_set (extension, &_initial_extensions[i]); \
+ extension++; \
+ } \
+ } \
+ }
+
+/*PAGE
+ *
+ * _User_extensions_Add_API_set
+ */
+
+#define _User_extensions_Add_API_set( _the_extension ) \
+ do { \
+ _Chain_Append( &_User_extensions_List, &(_the_extension)->Node ); \
+ \
+ if ( (_the_extension)->Callouts.thread_switch != NULL ) { \
+ (_the_extension)->Switch.thread_switch = \
+ (_the_extension)->Callouts.thread_switch; \
+ _Chain_Append( \
+ &_User_extensions_Switches_list, &(_the_extension)->Switch.Node ); \
+ } \
+ } while ( 0 )
+
+/*PAGE
+ *
+ * _User_extensions_Remove_set
+ */
+
+#define _User_extensions_Remove_set( _the_extension ) \
+ do { \
+ _Chain_Extract( &(_the_extension)->Node ); \
+ \
+ if ( (_the_extension)->Callouts.thread_switch != NULL ) { \
+ _Chain_Extract( &(_the_extension)->Node ); \
+ } \
+ } while (0)
+
+/*PAGE
+ *
+ * _User_extensions_Thread_switch
+ *
+ */
+
+#define _User_extensions_Thread_switch( _executing, _heir ) \
+ do { \
+ Chain_Node *the_node; \
+ User_extensions_Switch_control *the_extension_switch; \
+ \
+ for ( the_node = _User_extensions_Switches_list.first ; \
+ !_Chain_Is_tail( &_User_extensions_Switches_list, the_node ) ; \
+ the_node = the_node->next ) { \
+ \
+ the_extension_switch = (User_extensions_Switch_control *) the_node; \
+ \
+ (*the_extension_switch->thread_switch)( _executing, _heir ); \
+ } \
+ } while (0)
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/macros/rtems/score/watchdog.inl b/cpukit/score/macros/rtems/score/watchdog.inl
new file mode 100644
index 0000000000..895fd55743
--- /dev/null
+++ b/cpukit/score/macros/rtems/score/watchdog.inl
@@ -0,0 +1,171 @@
+/* watchdog.inl
+ *
+ * This file contains the macro implementation of all inlined routines
+ * in the Watchdog Handler.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __WATCHDOG_inl
+#define __WATCHDOG_inl
+
+#include <rtems/score/object.h>
+
+/*PAGE
+ *
+ * _Watchdog_Initialize
+ *
+ */
+
+#define _Watchdog_Initialize( _the_watchdog, _routine, _id, _user_data ) \
+ { \
+ (_the_watchdog)->state = WATCHDOG_INACTIVE; \
+ (_the_watchdog)->routine = (_routine); \
+ (_the_watchdog)->id = (_id); \
+ (_the_watchdog)->user_data = (_user_data); \
+ }
+
+/*PAGE
+ *
+ * _Watchdog_Is_active
+ *
+ */
+
+#define _Watchdog_Is_active( _the_watchdog ) \
+ ( (_the_watchdog)->state == WATCHDOG_ACTIVE )
+
+/*PAGE
+ *
+ * _Watchdog_Activate
+ *
+ */
+
+#define _Watchdog_Activate( _the_watchdog ) \
+ (_the_watchdog)->state = WATCHDOG_ACTIVE
+
+/*PAGE
+ *
+ * _Watchdog_Deactivate
+ *
+ */
+
+#define _Watchdog_Deactivate( _the_watchdog ) \
+ (_the_watchdog)->state = WATCHDOG_REMOVE_IT
+
+/*PAGE
+ *
+ * _Watchdog_Tickle_ticks
+ *
+ */
+
+#define _Watchdog_Tickle_ticks() \
+ _Watchdog_Tickle( &_Watchdog_Ticks_chain )
+
+/*PAGE
+ *
+ * _Watchdog_Tickle_seconds
+ *
+ */
+
+#define _Watchdog_Tickle_seconds() \
+ _Watchdog_Tickle( &_Watchdog_Seconds_chain )
+
+/*PAGE
+ *
+ * _Watchdog_Insert_ticks
+ *
+ */
+
+#define _Watchdog_Insert_ticks( _the_watchdog, _units ) \
+ do { \
+ (_the_watchdog)->initial = (_units); \
+ _Watchdog_Insert( &_Watchdog_Ticks_chain, (_the_watchdog) ); \
+ } while ( 0 )
+
+/*PAGE
+ *
+ * _Watchdog_Insert_seconds
+ *
+ */
+
+#define _Watchdog_Insert_seconds( _the_watchdog, _units ) \
+ do { \
+ (_the_watchdog)->initial = (_units); \
+ _Watchdog_Insert( &_Watchdog_Seconds_chain, (_the_watchdog) ); \
+ } while ( 0 )
+
+/*PAGE
+ *
+ * _Watchdog_Adjust_seconds
+ *
+ */
+
+#define _Watchdog_Adjust_seconds( _direction, _units ) \
+ _Watchdog_Adjust( &_Watchdog_Seconds_chain, (_direction), (_units) )
+
+/*PAGE
+ *
+ * _Watchdog_Adjust_ticks
+ *
+ */
+
+#define _Watchdog_Adjust_ticks( _direction, _units ) \
+ _Watchdog_Adjust( &_Watchdog_Ticks_chain, (_direction), (_units) )
+
+/*PAGE
+ *
+ * _Watchdog_Reset
+ *
+ */
+
+#define _Watchdog_Reset( _the_watchdog ) \
+ { \
+ (void) _Watchdog_Remove( (_the_watchdog) ); \
+ _Watchdog_Insert( &_Watchdog_Ticks_chain, (_the_watchdog) ); \
+ }
+
+/*PAGE
+ *
+ * _Watchdog_Next
+ *
+ */
+
+#define _Watchdog_Next( _watchdog ) \
+ ((Watchdog_Control *) (_watchdog)->Node.next)
+
+/*PAGE
+ *
+ * _Watchdog_Previous
+ *
+ */
+
+#define _Watchdog_Previous( _watchdog ) \
+ ((Watchdog_Control *) (_watchdog)->Node.previous)
+
+/*PAGE
+ *
+ * _Watchdog_First
+ *
+ */
+
+#define _Watchdog_First( _header ) \
+ ((Watchdog_Control *) (_header)->first)
+
+/*PAGE
+ *
+ * _Watchdog_Last
+ *
+ */
+
+#define _Watchdog_Last( _header ) \
+ ((Watchdog_Control *) (_header)->last)
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/macros/rtems/score/wkspace.inl b/cpukit/score/macros/rtems/score/wkspace.inl
new file mode 100644
index 0000000000..239bb54e68
--- /dev/null
+++ b/cpukit/score/macros/rtems/score/wkspace.inl
@@ -0,0 +1,38 @@
+/* wkspace.inl
+ *
+ * This file contains the macro implementation of the inlined routines
+ * from the RAM Workspace Handler.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#ifndef __WORKSPACE_inl
+#define __WORKSPACE_inl
+
+/*PAGE
+ *
+ * _Workspace_Allocate
+ *
+ */
+
+#define _Workspace_Allocate( _size ) \
+ _Heap_Allocate( &_Workspace_Area, (_size) )
+
+/*PAGE
+ *
+ * _Workspace_Free
+ *
+ */
+
+#define _Workspace_Free( _block ) \
+ _Heap_Free( &_Workspace_Area, (_block) )
+
+#endif
+/* end of include file */
diff --git a/cpukit/score/src/Unlimited.txt b/cpukit/score/src/Unlimited.txt
new file mode 100644
index 0000000000..be777d338a
--- /dev/null
+++ b/cpukit/score/src/Unlimited.txt
@@ -0,0 +1,387 @@
+#
+# $Id$
+#
+
+This document explains how the unlimited objects support works. This was
+written by Chris Johns <ccj@acm.org> of Objective Design Systems as a
+design document. This was submitted as part of the patch which added
+this capability.
+
+Unlimited Local Node Objects
+============================
+
+1. Why ?
+
+This patch changes the way RTEMS allocates, frees, and manages the
+'Objects_Control' structure.
+
+The 'Objects_Control' structure is at the root of all objects in
+RTEMS. The RTEMS and POSIX API allows users to create tasks, message
+queues, semaphores and other resources. These are all a type of
+Object. The POSIX API allow similar operations. These also map to
+Objects.
+
+Currently the number of objects that can be created is a static value
+loaded into the Configuration table before starting the kernel. The
+application cannot exceed these limits. Various means are used to tune
+this value. During development the value is usually set large. This
+saves having to change it everytime a developer adds a new
+resource. With a large team of developers the configuration table file
+can cycle through a large number of revisions. The wasted memory is
+only recovered when memory runs short. The issue of the configuration
+table parameters become more important the less memory you have.
+
+The Configuration table requires a calculation to occur at compile
+time to set the size of the Workspace. The calculation is an
+estimate. You need to specify an overhead value for memory that can
+not be calculated. An example of memory that cannot be calculated is
+stack sizes. This issue is not directly related to allowing unlimited
+objects how-ever the need to calculate the memory usage for a system
+in this manner is prone to error.
+
+I would like to see download support added to RTEMS. The kernel
+configuration being set at boot time means a download application can
+be limited. This can defeat one of the purposes of using downloaded
+code, no need to change ROMs. In a system I worked on the cost to
+change ROMS in a complete system was high and could take a week. This
+change is the first phase of supporting downloaded applications.
+
+1.1 How do Objects work ?
+
+All applications interact with the super core (c/src/exec/score) via
+an API. The central structure used in the super core is the
+`object'. Two application interfaces exist. They are RTEMS and
+POSIX. Both map to the super core using objects.
+
+An object in RTEMS is a resource which the user (through the API)
+creates. The different types of objects are referred to as classes of
+objects. An object is referenced by an id. This is of type `rtems_id'
+and is a 32bit unsigned integer. The id is unique for each object no
+matter what class.
+
+Objects are anchored by the `_Object_Information' structure. There is
+one per type or class of object. A global table of pointers to each
+information structure for a class of objects is held in
+`Objects_Information_table'.
+
+Objects consist of 6 main structures. The `_Object_Information' is the
+root structure. It contains pointers to the `local_table',
+`name_table', `global_table', the Inactive chain, and the object
+memory. It also contains the various variables which describe the
+object. We are only concerned with the `local_table', `name_table',
+Inactive chain, and the object memory to support unlimited objects.
+
+The `local_table' holds the pointers to open objects. A `local_table
+entry which is null is free and the object will be sitting on the
+Inactive chain. The index into the table is based on part of the
+id. Given an id the you can find the index into the `local_table', and
+therefore the object. The `local_table' has the entries for the
+indexes below the minimum_id's index. The minimum_id is always set to
+1 (the change allows another value to be selected if require). The
+index of 0 is reserved and never used. This allows any actions using
+an id of zero to fail or map to a special case.
+
+The `name_table' holds the names of the objects. Each entry in this
+table is the maximum size the name of the object can be. The size of
+names is not constrained by the object code (but is by the MP object
+code, and the API and should be fixed).
+
+The `global_table' and code that uses it has not changed. I did not
+look at the this code, and I am not farmilar with it.
+
+The Inactive chain stores objects which are free or not
+allocated. This design saves searching for a free object when
+allocating therefore providing a deterministic allocation scheme. When
+the chain is empty a null is returned.
+
+The change documented below basically extends the `local_table' and
+`name_table' structures at run-time. The memory used be these table
+is not large compared to the memory for the objects, and so are never
+reduced in size once extended. The object's memory grows and shrinks
+depending of the user's usage.
+
+Currently, the user specifies the total number of objects in the
+Configuration table. The change alters the function of the values in
+the Configuration table. A flag can be masked on to the value which
+selects the extending mode. If the user does not set the flag the
+object code operates with an object ceiling. A small performance
+overhead will be incurred as the allocate and free routines are now
+not inlined and a check of the auto_extend flag is made. The remaining
+value field of the Configuration table entry is total number of
+objects that can be allocated when not in unlimited mode.
+
+If the user masks the flag on to a value on the Configuration table
+auto-exdending mode is selected for that class of object. The value
+becomes the allocation unit size. If there are no free objects the
+object's tables are extended by the allocation unit number of
+objects. The object table is shrunk when the user frees objects. The
+table must have one free allocation block, and at least half the
+allocation size of another block before the object memory of the free
+allocation block is returned to the heap. This stops threshold
+thrashing when objects around the allocation unit size and created and
+destroyed.
+
+At least one allocation block size of objects is created and never
+destroyed.
+
+The change to support unlimited objects has extended the object
+information structure.
+
+The flag, `auto_extend' controls if the object can be automatically
+extended. The user masks the flag RTEMS_UNLIMITED_FLAGS onto the
+Configuration table number to select the auto-extend mode. This is
+passed to the `_Objects_Initialize_information' function in the
+parameter maximum. The flag is tested for and the auto_extend flag
+updated to reflect the state of the flag before being stipped from the
+maximum.
+
+The `allocation_size' is set to the parameter maxium in the function
+`_Objects_Initialize_information' if `auto_extend' is true. Making the
+allocation size small causes the memory to be allocated and freed more
+often. This only effects the performance times for creating a resource
+such as a task. It does how-ever give you fine grain memory
+control. If the performance of creating resources is not a problem
+make the size small.
+
+The size of the object is required to be stored. It is used when
+extending the object information.
+
+A count of the object on the Inactive list is maintained. This is used
+during freeing objects. If the count is above 1.5 times the
+`allocation_size' an attempt is made to shrink the object
+informtation. Shrinking might not always succeed as a single
+allocation block might not be free. Random freeing of objects can
+result in some fragmentation. Any further allocations will use the
+free objects before extending the object's information tables.
+
+A table of inactive objects per block is maintained. This table, like
+the `local_table' and `name_table' grows as more blocks are
+allocated. A check is made of a blocks inactive count when an object
+which is part of that block is freed. If the total inactive count
+exceeds 1.5 times the allocation size, and the block's inactive count
+is the allocation_size, the objects data block is returnd to the
+workspace heap.
+
+The `objects_blocks' is a table of pointers. The object_block's pointers
+point to the object's data block. The object's data block is a single
+allocation of the name space and object space. This was two separate
+allocations but is now one. The objects_block's table is use to
+determine if a block is allocated, and the address of the memory block
+to be returned to the workspace heap when the object informtation
+space is shrunk.
+
+2.0 Detail Of the Auto-Extend Patch to rtems-4.0.0, Snapshot 19990302
+
+o Configuration table support.
+
+ Added a flag OBJECTS_UNLIMITED_OBJECTS to score/headers/object.h
+ header file. This is referenced in the file sapi/headers/config.h to
+ create the flag RTEMS_UNLIMITED_OBJECTS. A macro is provided to take
+ a resource count and apply the flag. The macro is called
+ `rtems_resource_unlimited'. The user uses this macro when building a
+ configuration table. It can be used with the condefs.h header file.
+
+o Object Information Structure
+
+ The object information structure, Objects_Information, has been
+ extended with the follow fields :
+
+ boolean auto_extend -
+
+ When true the object's information tables can be extended untill
+ all memory is used. When false the current functionallity is
+ maintained.
+
+ uint32_t allocation_size -
+
+ When auto_extend is true, it is the value in the Configuration
+ table and is the number of objects the object's information
+ tables are extended or shrunk.
+
+ uint32_t size -
+
+ The size of the object. It is used to calculate the size of
+ memory required to be allocated when extending the table.
+
+ uint32_t inactive -
+
+ The number of elements on the Inactive chain.
+
+ uint32_t *inactive_per_block -
+
+ Pointer to a table of counts of the inactive objects from a
+ block on the Inactive chain. It is used to know which blocks are
+ all free and therefore can be returned to the heap.
+
+ void **object_blocks -
+
+ Pointer to a table of pointers to the object data. The table
+ holds the pointer used to return a block to the heap when
+ shrinking the object's information tables.
+
+o Changes to Existing Object Functions
+
+ Two functions prototypes are added. They are :
+
+ _Objects_Extend_information,
+ _Objects_Shrink_information
+ _Object_Allocate, and
+ _Object_Free
+
+ The last were inlined, how-ever now they are not as they are too
+ complex to implement as macros now.
+
+o Object Inline and Macro Changes
+
+ The functions :
+
+ _Object_Allocate, and
+ _Object_Free
+
+ are now not inlined. The function :
+
+ _Objects_Get_local_object, and
+ _Objects_Set_local_object
+
+ have been added. There was no provided interface to allow an API to
+ get/set an objects local pointer given an index. The POSIX code
+ should be updated to use this interface.
+
+ The function :
+
+ _Objects_Get_information
+
+ has been moved to be an inline function. It is used in the get
+ object call which the API uses for every object reference.
+
+o Object Initialisation
+
+ The function _Objects_Initialize_information has been changed to
+ initialisation of the information structure's fields then call the
+ new function _Objects_Extend_information.
+
+ The first block of objects is always allocated and never
+ released. This means with the auto-extend flag set to true the user
+ still sees the same behaviour expected without this change. That is
+ the number objects specified in the Configuration table is the
+ number of object allocated during RTEMS initialisation. If not
+ enough memory is found during this initial extend a fatal error
+ occurs. The fatal error only occurs for this case of extending the
+ object's information tables.
+
+o Object Information Extend
+
+ The _Object_Information_Extend is a new function. It takes some of
+ the code form the old _Object_Initialize_information function. The
+ function extends an object's information base.
+
+ Extending the first time is a special case. The function assumes the
+ maximum index will be less than the minimum index. This means the
+ minimum index must be greater than 0 at initialisation. The other
+ special case made is coping the tables from the old location to the
+ new location. The first block case is trapped and tables are
+ initialised instead. Workspace allocation for the first block is
+ tested for an if the first block the allocate or fatal error call is
+ made. This traps an RTEMS initialise allocation error.
+
+ The remainder of the code deals with all cases of extending the
+ object's information.
+
+ The current block count is first determined, then a scan of the
+ object_block table is made to locate a free slot. Blocks can be
+ freed in any order. The index base for the block is also determined.
+
+ If the index base is greater than the maximum index, the tables must
+ grow. To grow the tables, a new larger memory block is allocated and
+ the tables copied. The object's information structure is then
+ updated to point to the new tables. The tables are allocated in one
+ memory block from the work-space heap. The single block is then
+ broken down in the required tables.
+
+ Once the tables are copied, and the new extended parts initialised
+ the table pointers in the object's information structure are
+ updated. This is protected by masking interrupts.
+
+ The old table's memory block is returned to the heap.
+
+ The names table and object is allocated. This again is a single
+ block which is divided.
+
+ The objects are initialised onto a local Inactive chain. They are
+ then copied to the object's Inactive chain to complete the
+ initialisation.
+
+o Object Informtation Shrink
+
+ The _Object_Shrink_information function is new. It is required to
+ scan all the blocks to see which one has no objects allocated. The
+ last object freed might not belong to a block which is completely
+ free.
+
+ Once a block is located, the Inactive chain is interated down
+ looking for objects which belong to the block of object being
+ released.
+
+ Once the Inactive chain scan is complete the names table and object
+ memory is returned to the work-space heap and the table references cleared.
+
+ XXX - I am not sure if this should occur if better protection or
+ different code to provide better protection.
+
+ The information tables do not change size. Once extended they never
+ shrink.
+
+o Object Allocation
+
+ The _Objects_Allocate attempts to get an object from the Inactive
+ chain. If auto-extend mode is not enabled no further processing
+ occurs. The extra overhead for this implemetation is the function is
+ not inlined and check of a boolean occurs. It should effect the
+ timing figures.
+
+ If auto-extend is enabled, a further check is made to see if the get
+ from the Inactive chain suceeded in getting an object. If it failed
+ a call is made to extend the object's information tables.
+
+ The get from the Inactive chain is retried. The result of this is
+ returned to the user. A failure here is the users problem.
+
+o Object Free
+
+ The _Objects_Free puts the object back onto the Inactive
+ chain. Again if auto-extend mode is not enabled no further
+ processing occurs and performance overhead will low.
+
+ If auto-extend mode is enabled, a check is to see if the number of
+ Inactive objects is one and a half times the allocation size. If
+ there are that many free objects an attempt is made to shrink the
+ object's information.
+
+o Object Index and the Get Function
+
+ The existing code allocates the number of object specified in the
+ configuration table, how-ever it makes the local_table have one more
+ element. This is the slot for an id of 0. The 0 slot is always a
+ NULL providing a simple check for a 0 id for object classes.
+
+ The existing _Objects_Get code removes the minimum id, which I think
+ could only be 1 from the index, then adds one for the 0 slot.
+
+ This change removes this index adjustment code in _Objects_Get.
+
+ The extend information starts the index count when scanning for free
+ blocks at the minumun index. This means the base index for a block
+ will always be adjusted by the minimum index. The extend information
+ function only ever allocates the allocation size of
+ objects. Finially the object's local_table size is the maximum plus
+ the minumum index size. The maximum is really the maximum index.
+
+ This means the values in the object's information structure and
+ tables do not need the index adjustments which existed before.
+
+o The Test
+
+ A new sample test, unlimited is provided. It attempts to test this
+ change.
+
+
diff --git a/cpukit/score/src/apiext.c b/cpukit/score/src/apiext.c
new file mode 100644
index 0000000000..bdb223dd09
--- /dev/null
+++ b/cpukit/score/src/apiext.c
@@ -0,0 +1,104 @@
+/* apiext.c
+ *
+ * XXX
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+
+/*PAGE
+ *
+ * _API_extensions_Initialization
+ */
+
+void _API_extensions_Initialization( void )
+{
+ _Chain_Initialize_empty( &_API_extensions_List );
+}
+
+/*PAGE
+ *
+ * _API_extensions_Add
+ */
+
+void _API_extensions_Add(
+ API_extensions_Control *the_extension
+)
+{
+ _Chain_Append( &_API_extensions_List, &the_extension->Node );
+}
+
+/*PAGE
+ *
+ * _API_extensions_Run_predriver
+ */
+
+void _API_extensions_Run_predriver( void )
+{
+ Chain_Node *the_node;
+ API_extensions_Control *the_extension;
+
+ for ( the_node = _API_extensions_List.first ;
+ !_Chain_Is_tail( &_API_extensions_List, the_node ) ;
+ the_node = the_node->next ) {
+
+ the_extension = (API_extensions_Control *) the_node;
+
+ if ( the_extension->predriver_hook )
+ (*the_extension->predriver_hook)();
+ }
+}
+
+/*PAGE
+ *
+ * _API_extensions_Run_postdriver
+ */
+
+void _API_extensions_Run_postdriver( void )
+{
+ Chain_Node *the_node;
+ API_extensions_Control *the_extension;
+
+ for ( the_node = _API_extensions_List.first ;
+ !_Chain_Is_tail( &_API_extensions_List, the_node ) ;
+ the_node = the_node->next ) {
+
+ the_extension = (API_extensions_Control *) the_node;
+
+ if ( the_extension->postdriver_hook )
+ (*the_extension->postdriver_hook)();
+ }
+}
+
+/*PAGE
+ *
+ * _API_extensions_Run_postswitch
+ */
+
+void _API_extensions_Run_postswitch( void )
+{
+ Chain_Node *the_node;
+ API_extensions_Control *the_extension;
+
+ for ( the_node = _API_extensions_List.first ;
+ !_Chain_Is_tail( &_API_extensions_List, the_node ) ;
+ the_node = the_node->next ) {
+
+ the_extension = (API_extensions_Control *) the_node;
+
+ if ( the_extension->postswitch_hook )
+ (*the_extension->postswitch_hook)( _Thread_Executing );
+ }
+}
+
+/* end of file */
diff --git a/cpukit/score/src/chain.c b/cpukit/score/src/chain.c
new file mode 100644
index 0000000000..4e280fecd7
--- /dev/null
+++ b/cpukit/score/src/chain.c
@@ -0,0 +1,201 @@
+/*
+ * Chain Handler
+ *
+ * NOTE:
+ *
+ * The order of this file is to allow proper compilation due to the
+ * order of inlining required by the compiler.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+
+/*PAGE
+ *
+ * _Chain_Initialize
+ *
+ * This kernel routine initializes a doubly linked chain.
+ *
+ * Input parameters:
+ * the_chain - pointer to chain header
+ * starting_address - starting address of first node
+ * number_nodes - number of nodes in chain
+ * node_size - size of node in bytes
+ *
+ * Output parameters: NONE
+ */
+
+void _Chain_Initialize(
+ Chain_Control *the_chain,
+ void *starting_address,
+ uint32_t number_nodes,
+ uint32_t node_size
+)
+{
+ uint32_t count;
+ Chain_Node *current;
+ Chain_Node *next;
+
+ count = number_nodes;
+ current = _Chain_Head( the_chain );
+ the_chain->permanent_null = NULL;
+ next = (Chain_Node *)starting_address;
+ while ( count-- ) {
+ current->next = next;
+ next->previous = current;
+ current = next;
+ next = (Chain_Node *)
+ _Addresses_Add_offset( (void *) next, node_size );
+ }
+ current->next = _Chain_Tail( the_chain );
+ the_chain->last = current;
+}
+
+/*PAGE
+ *
+ * _Chain_Get_first_unprotected
+ */
+
+#ifndef RTEMS_INLINES
+Chain_Node *_Chain_Get_first_unprotected(
+ Chain_Control *the_chain
+)
+{
+ Chain_Node *return_node;
+ Chain_Node *new_first;
+
+ return_node = the_chain->first;
+ new_first = return_node->next;
+ the_chain->first = new_first;
+ new_first->previous = _Chain_Head( the_chain );
+
+ return return_node;
+}
+#endif /* RTEMS_INLINES */
+
+/*PAGE
+ *
+ * _Chain_Get
+ *
+ * This kernel routine returns a pointer to a node taken from the
+ * given chain.
+ *
+ * Input parameters:
+ * the_chain - pointer to chain header
+ *
+ * Output parameters:
+ * return_node - pointer to node in chain allocated
+ * CHAIN_END - if no nodes available
+ *
+ * INTERRUPT LATENCY:
+ * only case
+ */
+
+Chain_Node *_Chain_Get(
+ Chain_Control *the_chain
+)
+{
+ ISR_Level level;
+ Chain_Node *return_node;
+
+ return_node = NULL;
+ _ISR_Disable( level );
+ if ( !_Chain_Is_empty( the_chain ) )
+ return_node = _Chain_Get_first_unprotected( the_chain );
+ _ISR_Enable( level );
+ return return_node;
+}
+
+/*PAGE
+ *
+ * _Chain_Append
+ *
+ * This kernel routine puts a node on the end of the specified chain.
+ *
+ * Input parameters:
+ * the_chain - pointer to chain header
+ * node - address of node to put at rear of chain
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY:
+ * only case
+ */
+
+void _Chain_Append(
+ Chain_Control *the_chain,
+ Chain_Node *node
+)
+{
+ ISR_Level level;
+
+ _ISR_Disable( level );
+ _Chain_Append_unprotected( the_chain, node );
+ _ISR_Enable( level );
+}
+
+/*PAGE
+ *
+ * _Chain_Extract
+ *
+ * This kernel routine deletes the given node from a chain.
+ *
+ * Input parameters:
+ * node - pointer to node in chain to be deleted
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY:
+ * only case
+ */
+
+void _Chain_Extract(
+ Chain_Node *node
+)
+{
+ ISR_Level level;
+
+ _ISR_Disable( level );
+ _Chain_Extract_unprotected( node );
+ _ISR_Enable( level );
+}
+
+/*PAGE
+ *
+ * _Chain_Insert
+ *
+ * This kernel routine inserts a given node after a specified node
+ * a requested chain.
+ *
+ * Input parameters:
+ * after_node - pointer to node in chain to be inserted after
+ * node - pointer to node to be inserted
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY:
+ * only case
+ */
+
+void _Chain_Insert(
+ Chain_Node *after_node,
+ Chain_Node *node
+)
+{
+ ISR_Level level;
+
+ _ISR_Disable( level );
+ _Chain_Insert_unprotected( after_node, node );
+ _ISR_Enable( level );
+}
diff --git a/cpukit/score/src/coremsg.c b/cpukit/score/src/coremsg.c
new file mode 100644
index 0000000000..678da1d0b8
--- /dev/null
+++ b/cpukit/score/src/coremsg.c
@@ -0,0 +1,103 @@
+/*
+ * CORE Message Queue Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the CORE Message Queue Handler.
+ * This core object provides task synchronization and communication functions
+ * via messages passed to queue objects.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/coremsg.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+
+/*PAGE
+ *
+ * _CORE_message_queue_Initialize
+ *
+ * This routine initializes a newly created message queue based on the
+ * specified data.
+ *
+ * Input parameters:
+ * the_message_queue - the message queue to initialize
+ * the_class - the API specific object class
+ * the_message_queue_attributes - the message queue's attributes
+ * maximum_pending_messages - maximum message and reserved buffer count
+ * maximum_message_size - maximum size of each message
+ *
+ * Output parameters:
+ * TRUE - if the message queue is initialized
+ * FALSE - if the message queue is NOT initialized
+ */
+
+boolean _CORE_message_queue_Initialize(
+ CORE_message_queue_Control *the_message_queue,
+ CORE_message_queue_Attributes *the_message_queue_attributes,
+ uint32_t maximum_pending_messages,
+ uint32_t maximum_message_size
+)
+{
+ uint32_t message_buffering_required;
+ uint32_t allocated_message_size;
+
+ the_message_queue->maximum_pending_messages = maximum_pending_messages;
+ the_message_queue->number_of_pending_messages = 0;
+ the_message_queue->maximum_message_size = maximum_message_size;
+ _CORE_message_queue_Set_notify( the_message_queue, NULL, NULL );
+
+ /*
+ * round size up to multiple of a ptr for chain init
+ */
+
+ allocated_message_size = maximum_message_size;
+ if (allocated_message_size & (sizeof(uint32_t ) - 1)) {
+ allocated_message_size += sizeof(uint32_t );
+ allocated_message_size &= ~(sizeof(uint32_t ) - 1);
+ }
+
+ message_buffering_required = maximum_pending_messages *
+ (allocated_message_size + sizeof(CORE_message_queue_Buffer_control));
+
+ the_message_queue->message_buffers = (CORE_message_queue_Buffer *)
+ _Workspace_Allocate( message_buffering_required );
+
+ if (the_message_queue->message_buffers == 0)
+ return FALSE;
+
+ _Chain_Initialize (
+ &the_message_queue->Inactive_messages,
+ the_message_queue->message_buffers,
+ maximum_pending_messages,
+ allocated_message_size + sizeof( CORE_message_queue_Buffer_control )
+ );
+
+ _Chain_Initialize_empty( &the_message_queue->Pending_messages );
+
+ _Thread_queue_Initialize(
+ &the_message_queue->Wait_queue,
+ _CORE_message_queue_Is_priority( the_message_queue_attributes ) ?
+ THREAD_QUEUE_DISCIPLINE_PRIORITY : THREAD_QUEUE_DISCIPLINE_FIFO,
+ STATES_WAITING_FOR_MESSAGE,
+ CORE_MESSAGE_QUEUE_STATUS_TIMEOUT
+ );
+
+ return TRUE;
+}
diff --git a/cpukit/score/src/coremsgbroadcast.c b/cpukit/score/src/coremsgbroadcast.c
new file mode 100644
index 0000000000..1d6340991c
--- /dev/null
+++ b/cpukit/score/src/coremsgbroadcast.c
@@ -0,0 +1,111 @@
+/*
+ * CORE Message Queue Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the CORE Message Queue Handler.
+ * This core object provides task synchronization and communication functions
+ * via messages passed to queue objects.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/coremsg.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+
+/*PAGE
+ *
+ * _CORE_message_queue_Broadcast
+ *
+ * This function sends a message for every thread waiting on the queue and
+ * returns the number of threads made ready by the message.
+ *
+ * Input parameters:
+ * the_message_queue - message is submitted to this message queue
+ * buffer - pointer to message buffer
+ * size - size in bytes of message to send
+ * id - id of message queue
+ * api_message_queue_mp_support - api specific mp support callout
+ * count - area to store number of threads made ready
+ *
+ * Output parameters:
+ * count - number of threads made ready
+ * CORE_MESSAGE_QUEUE_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+CORE_message_queue_Status _CORE_message_queue_Broadcast(
+ CORE_message_queue_Control *the_message_queue,
+ void *buffer,
+ uint32_t size,
+ Objects_Id id,
+ CORE_message_queue_API_mp_support_callout api_message_queue_mp_support,
+ uint32_t *count
+)
+{
+ Thread_Control *the_thread;
+ uint32_t number_broadcasted;
+ Thread_Wait_information *waitp;
+ uint32_t constrained_size;
+
+ /*
+ * If there are pending messages, then there can't be threads
+ * waiting for us to send them a message.
+ *
+ * NOTE: This check is critical because threads can block on
+ * send and receive and this ensures that we are broadcasting
+ * the message to threads waiting to receive -- not to send.
+ */
+
+ if ( the_message_queue->number_of_pending_messages != 0 ) {
+ *count = 0;
+ return CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
+ }
+
+ /*
+ * There must be no pending messages if there is a thread waiting to
+ * receive a message.
+ */
+
+ number_broadcasted = 0;
+ while ((the_thread = _Thread_queue_Dequeue(&the_message_queue->Wait_queue))) {
+ waitp = &the_thread->Wait;
+ number_broadcasted += 1;
+
+ constrained_size = size;
+ if ( size > the_message_queue->maximum_message_size )
+ constrained_size = the_message_queue->maximum_message_size;
+
+ _CORE_message_queue_Copy_buffer(
+ buffer,
+ waitp->return_argument,
+ constrained_size
+ );
+
+ *(uint32_t *)the_thread->Wait.return_argument_1 = size;
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( !_Objects_Is_local_id( the_thread->Object.id ) )
+ (*api_message_queue_mp_support) ( the_thread, id );
+#endif
+
+ }
+ *count = number_broadcasted;
+ return CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
+}
diff --git a/cpukit/score/src/coremsgclose.c b/cpukit/score/src/coremsgclose.c
new file mode 100644
index 0000000000..53b3aaea51
--- /dev/null
+++ b/cpukit/score/src/coremsgclose.c
@@ -0,0 +1,76 @@
+/*
+ * CORE Message Queue Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the CORE Message Queue Handler.
+ * This core object provides task synchronization and communication functions
+ * via messages passed to queue objects.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/coremsg.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+
+/*PAGE
+ *
+ * _CORE_message_queue_Close
+ *
+ * This function closes a message by returning all allocated space and
+ * flushing the message_queue's task wait queue.
+ *
+ * Input parameters:
+ * the_message_queue - the message_queue to be flushed
+ * remote_extract_callout - function to invoke remotely
+ * status - status to pass to thread
+ *
+ * Output parameters: NONE
+ */
+
+void _CORE_message_queue_Close(
+ CORE_message_queue_Control *the_message_queue,
+ Thread_queue_Flush_callout remote_extract_callout,
+ uint32_t status
+)
+{
+
+ /*
+ * This will flush blocked threads whether they were blocked on
+ * a send or receive.
+ */
+
+ _Thread_queue_Flush(
+ &the_message_queue->Wait_queue,
+ remote_extract_callout,
+ status
+ );
+
+ /*
+ * This removes all messages from the pending message queue. Since
+ * we just flushed all waiting threads, we don't have to worry about
+ * the flush satisfying any blocked senders as a side-effect.
+ */
+
+ if ( the_message_queue->number_of_pending_messages != 0 )
+ (void) _CORE_message_queue_Flush_support( the_message_queue );
+
+ (void) _Workspace_Free( the_message_queue->message_buffers );
+
+}
diff --git a/cpukit/score/src/coremsgflush.c b/cpukit/score/src/coremsgflush.c
new file mode 100644
index 0000000000..f6e0d6836a
--- /dev/null
+++ b/cpukit/score/src/coremsgflush.c
@@ -0,0 +1,54 @@
+/*
+ * CORE Message Queue Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the CORE Message Queue Handler.
+ * This core object provides task synchronization and communication functions
+ * via messages passed to queue objects.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/coremsg.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+
+/*PAGE
+ *
+ * _CORE_message_queue_Flush
+ *
+ * This function flushes the message_queue's pending message queue. The
+ * number of messages flushed from the queue is returned.
+ *
+ * Input parameters:
+ * the_message_queue - the message_queue to be flushed
+ *
+ * Output parameters:
+ * returns - the number of messages flushed from the queue
+ */
+
+uint32_t _CORE_message_queue_Flush(
+ CORE_message_queue_Control *the_message_queue
+)
+{
+ if ( the_message_queue->number_of_pending_messages != 0 )
+ return _CORE_message_queue_Flush_support( the_message_queue );
+ else
+ return 0;
+}
diff --git a/cpukit/score/src/coremsgflushsupp.c b/cpukit/score/src/coremsgflushsupp.c
new file mode 100644
index 0000000000..ddde563232
--- /dev/null
+++ b/cpukit/score/src/coremsgflushsupp.c
@@ -0,0 +1,104 @@
+/*
+ * CORE Message Queue Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the CORE Message Queue Handler.
+ * This core object provides task synchronization and communication functions
+ * via messages passed to queue objects.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/coremsg.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+
+/*PAGE
+ *
+ * _CORE_message_queue_Flush_support
+ *
+ * This message handler routine removes all messages from a message queue
+ * and returns them to the inactive message pool. The number of messages
+ * flushed from the queue is returned
+ *
+ * Input parameters:
+ * the_message_queue - pointer to message queue
+ *
+ * Output parameters:
+ * returns - number of messages placed on inactive chain
+ *
+ * INTERRUPT LATENCY:
+ * only case
+ */
+
+uint32_t _CORE_message_queue_Flush_support(
+ CORE_message_queue_Control *the_message_queue
+)
+{
+ ISR_Level level;
+ Chain_Node *inactive_first;
+ Chain_Node *message_queue_first;
+ Chain_Node *message_queue_last;
+ uint32_t count;
+
+ /*
+ * Currently, RTEMS supports no API that has both flush and blocking
+ * sends. Thus, this routine assumes that there are no senders
+ * blocked waiting to send messages. In the event, that an API is
+ * added that can flush a message queue when threads are blocked
+ * waiting to send, there are two basic behaviors envisioned:
+ *
+ * (1) The thread queue of pending senders is a logical extension
+ * of the pending message queue. In this case, it should be
+ * flushed using the _Thread_queue_Flush() service with a status
+ * such as CORE_MESSAGE_QUEUE_SENDER_FLUSHED (which currently does
+ * not exist). This can be implemented without changing the "big-O"
+ * of the message flushing part of the routine.
+ *
+ * (2) Only the actual messages queued should be purged. In this case,
+ * the blocked sender threads must be allowed to send their messages.
+ * In this case, the implementation will be forced to individually
+ * dequeue the senders and queue their messages. This will force
+ * this routine to have "big O(n)" where n is the number of blocked
+ * senders. If there are more messages pending than senders blocked,
+ * then the existing flush code can be used to dispose of the remaining
+ * pending messages.
+ *
+ * For now, though, we are very happy to have a small routine with
+ * fixed execution time that only deals with pending messages.
+ */
+
+ _ISR_Disable( level );
+ inactive_first = the_message_queue->Inactive_messages.first;
+ message_queue_first = the_message_queue->Pending_messages.first;
+ message_queue_last = the_message_queue->Pending_messages.last;
+
+ the_message_queue->Inactive_messages.first = message_queue_first;
+ message_queue_last->next = inactive_first;
+ inactive_first->previous = message_queue_last;
+ message_queue_first->previous =
+ _Chain_Head( &the_message_queue->Inactive_messages );
+
+ _Chain_Initialize_empty( &the_message_queue->Pending_messages );
+
+ count = the_message_queue->number_of_pending_messages;
+ the_message_queue->number_of_pending_messages = 0;
+ _ISR_Enable( level );
+ return count;
+}
diff --git a/cpukit/score/src/coremsgflushwait.c b/cpukit/score/src/coremsgflushwait.c
new file mode 100644
index 0000000000..c7687ca797
--- /dev/null
+++ b/cpukit/score/src/coremsgflushwait.c
@@ -0,0 +1,69 @@
+/*
+ * CORE Message Queue Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the CORE Message Queue Handler.
+ * This core object provides task synchronization and communication functions
+ * via messages passed to queue objects.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/coremsg.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+
+/*PAGE
+ *
+ * _CORE_message_queue_Flush_waiting_threads
+ *
+ * This function flushes the message_queue's task wait queue. The number
+ * of messages flushed from the queue is returned.
+ *
+ * Input parameters:
+ * the_message_queue - the message_queue to be flushed
+ *
+ * Output parameters:
+ * returns - the number of messages flushed from the queue
+ */
+
+void _CORE_message_queue_Flush_waiting_threads(
+ CORE_message_queue_Control *the_message_queue
+)
+{
+ /* XXX this is not supported for global message queues */
+
+ /*
+ * IF there are no pending messages,
+ * THEN threads may be blocked waiting to RECEIVE a message,
+ *
+ * IF the pending message queue is full
+ * THEN threads may be blocked waiting to SEND a message
+ *
+ * But in either case, we will return "unsatisfied nowait"
+ * to indicate that the blocking condition was not satisfied
+ * and that the blocking state was canceled.
+ */
+
+ _Thread_queue_Flush(
+ &the_message_queue->Wait_queue,
+ NULL,
+ CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_NOWAIT
+ );
+}
diff --git a/cpukit/score/src/coremsginsert.c b/cpukit/score/src/coremsginsert.c
new file mode 100644
index 0000000000..698cf3b60f
--- /dev/null
+++ b/cpukit/score/src/coremsginsert.c
@@ -0,0 +1,102 @@
+/*
+ * CORE Message Queue Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the CORE Message Queue Handler.
+ * This core object provides task synchronization and communication functions
+ * via messages passed to queue objects.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/coremsg.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+
+/*PAGE
+ *
+ * _CORE_message_queue_Insert_message
+ *
+ * This kernel routine inserts the specified message into the
+ * message queue. It is assumed that the message has been filled
+ * in before this routine is called.
+ *
+ * Input parameters:
+ * the_message_queue - pointer to message queue
+ * the_message - message to insert
+ * priority - insert indication
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY:
+ * insert
+ */
+
+void _CORE_message_queue_Insert_message(
+ CORE_message_queue_Control *the_message_queue,
+ CORE_message_queue_Buffer_control *the_message,
+ CORE_message_queue_Submit_types submit_type
+)
+{
+ the_message_queue->number_of_pending_messages += 1;
+
+ the_message->priority = submit_type;
+
+ switch ( submit_type ) {
+ case CORE_MESSAGE_QUEUE_SEND_REQUEST:
+ _CORE_message_queue_Append( the_message_queue, the_message );
+ break;
+ case CORE_MESSAGE_QUEUE_URGENT_REQUEST:
+ _CORE_message_queue_Prepend( the_message_queue, the_message );
+ break;
+ default:
+ /* XXX interrupt critical section needs to be addressed */
+ {
+ CORE_message_queue_Buffer_control *this_message;
+ Chain_Node *the_node;
+ Chain_Control *the_header;
+
+ the_header = &the_message_queue->Pending_messages;
+ the_node = the_header->first;
+ while ( !_Chain_Is_tail( the_header, the_node ) ) {
+
+ this_message = (CORE_message_queue_Buffer_control *) the_node;
+
+ if ( this_message->priority <= the_message->priority ) {
+ the_node = the_node->next;
+ continue;
+ }
+
+ break;
+ }
+ _Chain_Insert( the_node->previous, &the_message->Node );
+ }
+ break;
+ }
+
+ /*
+ * According to POSIX, does this happen before or after the message
+ * is actually enqueued. It is logical to think afterwards, because
+ * the message is actually in the queue at this point.
+ */
+
+ if ( the_message_queue->number_of_pending_messages == 1 &&
+ the_message_queue->notify_handler )
+ (*the_message_queue->notify_handler)( the_message_queue->notify_argument );
+}
diff --git a/cpukit/score/src/coremsgseize.c b/cpukit/score/src/coremsgseize.c
new file mode 100644
index 0000000000..050d361769
--- /dev/null
+++ b/cpukit/score/src/coremsgseize.c
@@ -0,0 +1,136 @@
+/*
+ * CORE Message Queue Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the CORE Message Queue Handler.
+ * This core object provides task synchronization and communication functions
+ * via messages passed to queue objects.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/coremsg.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+
+/*PAGE
+ *
+ * _CORE_message_queue_Seize
+ *
+ * This kernel routine dequeues a message, copies the message buffer to
+ * a given destination buffer, and frees the message buffer to the
+ * inactive message pool. The thread will be blocked if wait is TRUE,
+ * otherwise an error will be given to the thread if no messages are available.
+ *
+ * Input parameters:
+ * the_message_queue - pointer to message queue
+ * id - id of object we are waitig on
+ * buffer - pointer to message buffer to be filled
+ * size - pointer to the size of buffer to be filled
+ * wait - TRUE if wait is allowed, FALSE otherwise
+ * timeout - time to wait for a message
+ *
+ * Output parameters: NONE
+ *
+ * NOTE: Dependent on BUFFER_LENGTH
+ *
+ * INTERRUPT LATENCY:
+ * available
+ * wait
+ */
+
+void _CORE_message_queue_Seize(
+ CORE_message_queue_Control *the_message_queue,
+ Objects_Id id,
+ void *buffer,
+ uint32_t *size,
+ boolean wait,
+ Watchdog_Interval timeout
+)
+{
+ ISR_Level level;
+ CORE_message_queue_Buffer_control *the_message;
+ Thread_Control *executing;
+ Thread_Control *the_thread;
+
+ executing = _Thread_Executing;
+ executing->Wait.return_code = CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
+ _ISR_Disable( level );
+ if ( the_message_queue->number_of_pending_messages != 0 ) {
+ the_message_queue->number_of_pending_messages -= 1;
+
+ the_message = _CORE_message_queue_Get_pending_message( the_message_queue );
+ _ISR_Enable( level );
+
+ *size = the_message->Contents.size;
+ _Thread_Executing->Wait.count = the_message->priority;
+ _CORE_message_queue_Copy_buffer(the_message->Contents.buffer,buffer,*size);
+
+ /*
+ * There could be a thread waiting to send a message. If there
+ * is not, then we can go ahead and free the buffer.
+ *
+ * NOTE: If we note that the queue was not full before this receive,
+ * then we can avoid this dequeue.
+ */
+
+ the_thread = _Thread_queue_Dequeue( &the_message_queue->Wait_queue );
+ if ( !the_thread ) {
+ _CORE_message_queue_Free_message_buffer( the_message_queue, the_message );
+ return;
+ }
+
+ /*
+ * There was a thread waiting to send a message. This code
+ * puts the messages in the message queue on behalf of the
+ * waiting task.
+ */
+
+ the_message->priority = the_thread->Wait.count;
+ the_message->Contents.size = (uint32_t )the_thread->Wait.return_argument_1;
+ _CORE_message_queue_Copy_buffer(
+ the_thread->Wait.return_argument,
+ the_message->Contents.buffer,
+ the_message->Contents.size
+ );
+
+ _CORE_message_queue_Insert_message(
+ the_message_queue,
+ the_message,
+ the_message->priority
+ );
+ return;
+ }
+
+ if ( !wait ) {
+ _ISR_Enable( level );
+ executing->Wait.return_code = CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_NOWAIT;
+ return;
+ }
+
+ _Thread_queue_Enter_critical_section( &the_message_queue->Wait_queue );
+ executing->Wait.queue = &the_message_queue->Wait_queue;
+ executing->Wait.id = id;
+ executing->Wait.return_argument = buffer;
+ executing->Wait.return_argument_1 = (void *)size;
+ /* Wait.count will be filled in with the message priority */
+ _ISR_Enable( level );
+
+ _Thread_queue_Enqueue( &the_message_queue->Wait_queue, timeout );
+}
diff --git a/cpukit/score/src/coremsgsubmit.c b/cpukit/score/src/coremsgsubmit.c
new file mode 100644
index 0000000000..4c57535c13
--- /dev/null
+++ b/cpukit/score/src/coremsgsubmit.c
@@ -0,0 +1,175 @@
+/*
+ * CORE Message Queue Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the CORE Message Queue Handler.
+ * This core object provides task synchronization and communication functions
+ * via messages passed to queue objects.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/coremsg.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+
+/*PAGE
+ *
+ * _CORE_message_queue_Submit
+ *
+ * This routine implements the send and urgent message functions. It
+ * processes a message that is to be submitted to the designated
+ * message queue. The message will either be processed as a
+ * send message which it will be inserted at the rear of the queue
+ * or it will be processed as an urgent message which will be inserted
+ * at the front of the queue.
+ *
+ * Input parameters:
+ * the_message_queue - message is submitted to this message queue
+ * buffer - pointer to message buffer
+ * size - size in bytes of message to send
+ * id - id of message queue
+ * api_message_queue_mp_support - api specific mp support callout
+ * submit_type - send or urgent message
+ *
+ * Output parameters:
+ * CORE_MESSAGE_QUEUE_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+CORE_message_queue_Status _CORE_message_queue_Submit(
+ CORE_message_queue_Control *the_message_queue,
+ void *buffer,
+ uint32_t size,
+ Objects_Id id,
+ CORE_message_queue_API_mp_support_callout api_message_queue_mp_support,
+ CORE_message_queue_Submit_types submit_type,
+ boolean wait,
+ Watchdog_Interval timeout
+)
+{
+ ISR_Level level;
+ CORE_message_queue_Buffer_control *the_message;
+ Thread_Control *the_thread;
+
+ if ( size > the_message_queue->maximum_message_size ) {
+ return CORE_MESSAGE_QUEUE_STATUS_INVALID_SIZE;
+ }
+
+ /*
+ * Is there a thread currently waiting on this message queue?
+ */
+
+ if ( the_message_queue->number_of_pending_messages == 0 ) {
+ the_thread = _Thread_queue_Dequeue( &the_message_queue->Wait_queue );
+ if ( the_thread ) {
+ _CORE_message_queue_Copy_buffer(
+ buffer,
+ the_thread->Wait.return_argument,
+ size
+ );
+ *(uint32_t *)the_thread->Wait.return_argument_1 = size;
+ the_thread->Wait.count = submit_type;
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( !_Objects_Is_local_id( the_thread->Object.id ) )
+ (*api_message_queue_mp_support) ( the_thread, id );
+#endif
+ return CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
+ }
+ }
+
+ /*
+ * No one waiting on the message queue at this time, so attempt to
+ * queue the message up for a future receive.
+ */
+
+ if ( the_message_queue->number_of_pending_messages <
+ the_message_queue->maximum_pending_messages ) {
+
+ the_message =
+ _CORE_message_queue_Allocate_message_buffer( the_message_queue );
+
+ /*
+ * NOTE: If the system is consistent, this error should never occur.
+ */
+
+ if ( !the_message ) {
+ return CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED;
+ }
+
+ _CORE_message_queue_Copy_buffer(
+ buffer,
+ the_message->Contents.buffer,
+ size
+ );
+ the_message->Contents.size = size;
+ the_message->priority = submit_type;
+
+ _CORE_message_queue_Insert_message(
+ the_message_queue,
+ the_message,
+ submit_type
+ );
+ return CORE_MESSAGE_QUEUE_STATUS_SUCCESSFUL;
+ }
+
+ /*
+ * No message buffers were available so we may need to return an
+ * overflow error or block the sender until the message is placed
+ * on the queue.
+ */
+
+ if ( !wait ) {
+ return CORE_MESSAGE_QUEUE_STATUS_TOO_MANY;
+ }
+
+ /*
+ * Do NOT block on a send if the caller is in an ISR. It is
+ * deadly to block in an ISR.
+ */
+
+ if ( _ISR_Is_in_progress() ) {
+ return CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED;
+ }
+
+ /*
+ * WARNING!! executing should NOT be used prior to this point.
+ * Thus the unusual choice to open a new scope and declare
+ * it as a variable. Doing this emphasizes how dangerous it
+ * would be to use this variable prior to here.
+ */
+
+ {
+ Thread_Control *executing = _Thread_Executing;
+
+ _ISR_Disable( level );
+ _Thread_queue_Enter_critical_section( &the_message_queue->Wait_queue );
+ executing->Wait.queue = &the_message_queue->Wait_queue;
+ executing->Wait.id = id;
+ executing->Wait.return_argument = buffer;
+ executing->Wait.return_argument_1 = (void *)size;
+ executing->Wait.count = submit_type;
+ _ISR_Enable( level );
+
+ _Thread_queue_Enqueue( &the_message_queue->Wait_queue, timeout );
+ }
+
+ return CORE_MESSAGE_QUEUE_STATUS_UNSATISFIED_WAIT;
+}
diff --git a/cpukit/score/src/coremutex.c b/cpukit/score/src/coremutex.c
new file mode 100644
index 0000000000..8e8b7456d8
--- /dev/null
+++ b/cpukit/score/src/coremutex.c
@@ -0,0 +1,88 @@
+/*
+ * Mutex Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the Mutex Handler.
+ * This handler provides synchronization and mutual exclusion capabilities.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+
+/*PAGE
+ *
+ * _CORE_mutex_Initialize
+ *
+ * This routine initializes a mutex at create time and set the control
+ * structure according to the values passed.
+ *
+ * Input parameters:
+ * the_mutex - the mutex control block to initialize
+ * the_mutex_attributes - the mutex attributes specified at create time
+ * initial_lock - mutex initial lock or unlocked status
+ *
+ * Output parameters: NONE
+ */
+
+void _CORE_mutex_Initialize(
+ CORE_mutex_Control *the_mutex,
+ CORE_mutex_Attributes *the_mutex_attributes,
+ uint32_t initial_lock
+)
+{
+
+/* Add this to the RTEMS environment later ?????????
+ rtems_assert( initial_lock == CORE_MUTEX_LOCKED ||
+ initial_lock == CORE_MUTEX_UNLOCKED );
+ */
+
+ the_mutex->Attributes = *the_mutex_attributes;
+ the_mutex->lock = initial_lock;
+ the_mutex->blocked_count = 0;
+
+#if 0
+ if ( !the_mutex_attributes->only_owner_release &&
+ the_mutex_attributes->nesting_allowed ) {
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ TRUE,
+ INTERNAL_ERROR_BAD_ATTRIBUTES
+ );
+ }
+#endif
+
+ if ( initial_lock == CORE_MUTEX_LOCKED ) {
+ the_mutex->nest_count = 1;
+ the_mutex->holder = _Thread_Executing;
+ the_mutex->holder_id = _Thread_Executing->Object.id;
+ if ( _CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) ||
+ _CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) )
+ _Thread_Executing->resource_count++;
+ } else {
+ the_mutex->nest_count = 0;
+ the_mutex->holder = NULL;
+ the_mutex->holder_id = 0;
+ }
+
+ _Thread_queue_Initialize(
+ &the_mutex->Wait_queue,
+ _CORE_mutex_Is_fifo( the_mutex_attributes ) ?
+ THREAD_QUEUE_DISCIPLINE_FIFO : THREAD_QUEUE_DISCIPLINE_PRIORITY,
+ STATES_WAITING_FOR_MUTEX,
+ CORE_MUTEX_TIMEOUT
+ );
+}
diff --git a/cpukit/score/src/coremutexflush.c b/cpukit/score/src/coremutexflush.c
new file mode 100644
index 0000000000..2ac5e2d397
--- /dev/null
+++ b/cpukit/score/src/coremutexflush.c
@@ -0,0 +1,51 @@
+/*
+ * Mutex Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the Mutex Handler.
+ * This handler provides synchronization and mutual exclusion capabilities.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+
+/*PAGE
+ *
+ * _CORE_mutex_Flush
+ *
+ * This function a flushes the mutex's task wait queue.
+ *
+ * Input parameters:
+ * the_mutex - the mutex to be flushed
+ * remote_extract_callout - function to invoke remotely
+ * status - status to pass to thread
+ *
+ * Output parameters: NONE
+ */
+
+void _CORE_mutex_Flush(
+ CORE_mutex_Control *the_mutex,
+ Thread_queue_Flush_callout remote_extract_callout,
+ uint32_t status
+)
+{
+ _Thread_queue_Flush(
+ &the_mutex->Wait_queue,
+ remote_extract_callout,
+ status
+ );
+}
diff --git a/cpukit/score/src/coremutexseize.c b/cpukit/score/src/coremutexseize.c
new file mode 100644
index 0000000000..2645bcc5d8
--- /dev/null
+++ b/cpukit/score/src/coremutexseize.c
@@ -0,0 +1,154 @@
+/*
+ * Mutex Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the Mutex Handler.
+ * This handler provides synchronization and mutual exclusion capabilities.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+
+/*PAGE
+ *
+ * _CORE_mutex_Seize (interrupt blocking support)
+ *
+ * This routine blocks the caller thread after an attempt attempts to obtain
+ * the specified mutex has failed.
+ *
+ * Input parameters:
+ * the_mutex - pointer to mutex control block
+ * timeout - number of ticks to wait (0 means forever)
+ */
+
+void _CORE_mutex_Seize_interrupt_blocking(
+ CORE_mutex_Control *the_mutex,
+ Watchdog_Interval timeout
+)
+{
+ Thread_Control *executing;
+
+ executing = _Thread_Executing;
+ if ( _CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) ) {
+ if ( the_mutex->holder->current_priority > executing->current_priority ) {
+ _Thread_Change_priority(
+ the_mutex->holder,
+ executing->current_priority,
+ FALSE
+ );
+ }
+ }
+
+ the_mutex->blocked_count++;
+ _Thread_queue_Enqueue( &the_mutex->Wait_queue, timeout );
+
+ if ( _Thread_Executing->Wait.return_code == CORE_MUTEX_STATUS_SUCCESSFUL ) {
+ /*
+ * if CORE_MUTEX_DISCIPLINES_PRIORITY_INHERIT then nothing to do
+ * because this task is already the highest priority.
+ */
+
+ if ( _CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) ) {
+ if (the_mutex->Attributes.priority_ceiling < executing->current_priority){
+ _Thread_Change_priority(
+ executing,
+ the_mutex->Attributes.priority_ceiling,
+ FALSE
+ );
+ }
+ }
+ }
+ _Thread_Enable_dispatch();
+}
+
+#if !defined(RTEMS_INLINES)
+int _CORE_mutex_Seize_interrupt_trylock(
+ CORE_mutex_Control *the_mutex,
+ ISR_Level *level_p
+)
+{
+ Thread_Control *executing;
+ ISR_Level level = *level_p;
+
+ /* disabled when you get here */
+
+ executing = _Thread_Executing;
+ executing->Wait.return_code = CORE_MUTEX_STATUS_SUCCESSFUL;
+ if ( !_CORE_mutex_Is_locked( the_mutex ) ) {
+ the_mutex->lock = CORE_MUTEX_LOCKED;
+ the_mutex->holder = executing;
+ the_mutex->holder_id = executing->Object.id;
+ the_mutex->nest_count = 1;
+ if ( _CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) ||
+ _CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) )
+ executing->resource_count++;
+
+ if ( !_CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) ) {
+ _ISR_Enable( level );
+ return 0;
+ }
+ /* else must be CORE_MUTEX_DISCIPLINES_PRIORITY_CEILING */
+ {
+ Priority_Control ceiling;
+ Priority_Control current;
+
+ ceiling = the_mutex->Attributes.priority_ceiling;
+ current = executing->current_priority;
+ if ( current == ceiling ) {
+ _ISR_Enable( level );
+ return 0;
+ }
+ if ( current > ceiling ) {
+ _Thread_Disable_dispatch();
+ _ISR_Enable( level );
+ _Thread_Change_priority(
+ the_mutex->holder,
+ the_mutex->Attributes.priority_ceiling,
+ FALSE
+ );
+ _Thread_Enable_dispatch();
+ return 0;
+ }
+ /* if ( current < ceiling ) */ {
+ executing->Wait.return_code = CORE_MUTEX_STATUS_CEILING_VIOLATED;
+ the_mutex->nest_count = 0; /* undo locking above */
+ executing->resource_count--; /* undo locking above */
+ _ISR_Enable( level );
+ return 0;
+ }
+ }
+ return 0;
+ }
+
+ if ( _Thread_Is_executing( the_mutex->holder ) ) {
+ switch ( the_mutex->Attributes.lock_nesting_behavior ) {
+ case CORE_MUTEX_NESTING_ACQUIRES:
+ the_mutex->nest_count++;
+ _ISR_Enable( level );
+ return 0;
+ case CORE_MUTEX_NESTING_IS_ERROR:
+ executing->Wait.return_code = CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED;
+ _ISR_Enable( level );
+ return 0;
+ case CORE_MUTEX_NESTING_BLOCKS:
+ break;
+ }
+ }
+
+ return 1;
+}
+#endif
diff --git a/cpukit/score/src/coremutexsurrender.c b/cpukit/score/src/coremutexsurrender.c
new file mode 100644
index 0000000000..d527d1fa79
--- /dev/null
+++ b/cpukit/score/src/coremutexsurrender.c
@@ -0,0 +1,141 @@
+/*
+ * Mutex Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the Mutex Handler.
+ * This handler provides synchronization and mutual exclusion capabilities.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/coremutex.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+
+/*
+ * _CORE_mutex_Surrender
+ *
+ * DESCRIPTION:
+ *
+ * This routine frees a unit to the mutex. If a task was blocked waiting for
+ * a unit from this mutex, then that task will be readied and the unit
+ * given to that task. Otherwise, the unit will be returned to the mutex.
+ *
+ * Input parameters:
+ * the_mutex - the mutex to be flushed
+ * id - id of parent mutex
+ * api_mutex_mp_support - api dependent MP support actions
+ *
+ * Output parameters:
+ * CORE_MUTEX_STATUS_SUCCESSFUL - if successful
+ * core error code - if unsuccessful
+ */
+
+CORE_mutex_Status _CORE_mutex_Surrender(
+ CORE_mutex_Control *the_mutex,
+ Objects_Id id,
+ CORE_mutex_API_mp_support_callout api_mutex_mp_support
+)
+{
+ Thread_Control *the_thread;
+ Thread_Control *holder;
+
+ holder = the_mutex->holder;
+
+ /*
+ * The following code allows a thread (or ISR) other than the thread
+ * which acquired the mutex to release that mutex. This is only
+ * allowed when the mutex in quetion is FIFO or simple Priority
+ * discipline. But Priority Ceiling or Priority Inheritance mutexes
+ * must be released by the thread which acquired them.
+ */
+
+ if ( the_mutex->Attributes.only_owner_release ) {
+ if ( !_Thread_Is_executing( holder ) )
+ return CORE_MUTEX_STATUS_NOT_OWNER_OF_RESOURCE;
+ }
+
+ /* XXX already unlocked -- not right status */
+
+ if ( !the_mutex->nest_count )
+ return CORE_MUTEX_STATUS_SUCCESSFUL;
+
+ the_mutex->nest_count--;
+
+ if ( the_mutex->nest_count != 0 ) {
+ switch ( the_mutex->Attributes.lock_nesting_behavior ) {
+ case CORE_MUTEX_NESTING_ACQUIRES:
+ return CORE_MUTEX_STATUS_SUCCESSFUL;
+ case CORE_MUTEX_NESTING_IS_ERROR:
+ /* should never occur */
+ return CORE_MUTEX_STATUS_NESTING_NOT_ALLOWED;
+ case CORE_MUTEX_NESTING_BLOCKS:
+ /* Currently no API exercises this behavior. */
+ break;
+ }
+ }
+
+ if ( _CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) ||
+ _CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) )
+ holder->resource_count--;
+ the_mutex->holder = NULL;
+ the_mutex->holder_id = 0;
+
+ /*
+ * Whether or not someone is waiting for the mutex, an
+ * inherited priority must be lowered if this is the last
+ * mutex (i.e. resource) this task has.
+ */
+
+ if ( _CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) ||
+ _CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) ) {
+ if ( holder->resource_count == 0 &&
+ holder->real_priority != holder->current_priority ) {
+ _Thread_Change_priority( holder, holder->real_priority, TRUE );
+ }
+ }
+
+ if ( ( the_thread = _Thread_queue_Dequeue( &the_mutex->Wait_queue ) ) ) {
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( !_Objects_Is_local_id( the_thread->Object.id ) ) {
+
+ the_mutex->holder = NULL;
+ the_mutex->holder_id = the_thread->Object.id;
+ the_mutex->nest_count = 1;
+
+ ( *api_mutex_mp_support)( the_thread, id );
+
+ } else
+#endif
+ {
+
+ the_mutex->holder = the_thread;
+ the_mutex->holder_id = the_thread->Object.id;
+ if ( _CORE_mutex_Is_inherit_priority( &the_mutex->Attributes ) ||
+ _CORE_mutex_Is_priority_ceiling( &the_mutex->Attributes ) )
+ the_thread->resource_count++;
+ the_mutex->nest_count = 1;
+
+ /*
+ * No special action for priority inheritance or priority ceiling
+ * because the_thread is guaranteed to be the highest priority
+ * thread waiting for the mutex.
+ */
+ }
+ } else
+ the_mutex->lock = CORE_MUTEX_UNLOCKED;
+
+ return CORE_MUTEX_STATUS_SUCCESSFUL;
+}
diff --git a/cpukit/score/src/coresem.c b/cpukit/score/src/coresem.c
new file mode 100644
index 0000000000..8c77878b76
--- /dev/null
+++ b/cpukit/score/src/coresem.c
@@ -0,0 +1,62 @@
+/*
+ * CORE Semaphore Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the CORE Semaphore Handler.
+ * This core object utilizes standard Dijkstra counting semaphores to provide
+ * synchronization and mutual exclusion capabilities.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/coresem.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+
+/*PAGE
+ *
+ * CORE_semaphore_Initialize
+ *
+ * This function initialize a semaphore and sets the initial value based
+ * on the given count.
+ *
+ * Input parameters:
+ * the_semaphore - the semaphore control block to initialize
+ * the_semaphore_attributes - the attributes specified at create time
+ * initial_value - semaphore's initial value
+ *
+ * Output parameters: NONE
+ */
+
+void _CORE_semaphore_Initialize(
+ CORE_semaphore_Control *the_semaphore,
+ CORE_semaphore_Attributes *the_semaphore_attributes,
+ uint32_t initial_value
+)
+{
+
+ the_semaphore->Attributes = *the_semaphore_attributes;
+ the_semaphore->count = initial_value;
+
+ _Thread_queue_Initialize(
+ &the_semaphore->Wait_queue,
+ _CORE_semaphore_Is_priority( the_semaphore_attributes ) ?
+ THREAD_QUEUE_DISCIPLINE_PRIORITY : THREAD_QUEUE_DISCIPLINE_FIFO,
+ STATES_WAITING_FOR_SEMAPHORE,
+ CORE_SEMAPHORE_TIMEOUT
+ );
+}
diff --git a/cpukit/score/src/coresemflush.c b/cpukit/score/src/coresemflush.c
new file mode 100644
index 0000000000..ce2a62d85d
--- /dev/null
+++ b/cpukit/score/src/coresemflush.c
@@ -0,0 +1,57 @@
+/*
+ * CORE Semaphore Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the CORE Semaphore Handler.
+ * This core object utilizes standard Dijkstra counting semaphores to provide
+ * synchronization and mutual exclusion capabilities.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/coresem.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+
+/*PAGE
+ *
+ * _CORE_semaphore_Flush
+ *
+ * This function a flushes the semaphore's task wait queue.
+ *
+ * Input parameters:
+ * the_semaphore - the semaphore to be flushed
+ * remote_extract_callout - function to invoke remotely
+ * status - status to pass to thread
+ *
+ * Output parameters: NONE
+ */
+
+void _CORE_semaphore_Flush(
+ CORE_semaphore_Control *the_semaphore,
+ Thread_queue_Flush_callout remote_extract_callout,
+ uint32_t status
+)
+{
+
+ _Thread_queue_Flush(
+ &the_semaphore->Wait_queue,
+ remote_extract_callout,
+ status
+ );
+
+}
diff --git a/cpukit/score/src/coresemseize.c b/cpukit/score/src/coresemseize.c
new file mode 100644
index 0000000000..457af2cbff
--- /dev/null
+++ b/cpukit/score/src/coresemseize.c
@@ -0,0 +1,80 @@
+/*
+ * CORE Semaphore Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the CORE Semaphore Handler.
+ * This core object utilizes standard Dijkstra counting semaphores to provide
+ * synchronization and mutual exclusion capabilities.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/coresem.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+
+/*PAGE
+ *
+ * _CORE_semaphore_Seize
+ *
+ * This routine attempts to allocate a core semaphore to the calling thread.
+ *
+ * Input parameters:
+ * the_semaphore - pointer to semaphore control block
+ * id - id of object to wait on
+ * wait - TRUE if wait is allowed, FALSE otherwise
+ * timeout - number of ticks to wait (0 means forever)
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY:
+ * available
+ * wait
+ */
+
+void _CORE_semaphore_Seize(
+ CORE_semaphore_Control *the_semaphore,
+ Objects_Id id,
+ boolean wait,
+ Watchdog_Interval timeout
+)
+{
+ Thread_Control *executing;
+ ISR_Level level;
+
+ executing = _Thread_Executing;
+ executing->Wait.return_code = CORE_SEMAPHORE_STATUS_SUCCESSFUL;
+ _ISR_Disable( level );
+ if ( the_semaphore->count != 0 ) {
+ the_semaphore->count -= 1;
+ _ISR_Enable( level );
+ return;
+ }
+
+ if ( !wait ) {
+ _ISR_Enable( level );
+ executing->Wait.return_code = CORE_SEMAPHORE_STATUS_UNSATISFIED_NOWAIT;
+ return;
+ }
+
+ _Thread_queue_Enter_critical_section( &the_semaphore->Wait_queue );
+ executing->Wait.queue = &the_semaphore->Wait_queue;
+ executing->Wait.id = id;
+ _ISR_Enable( level );
+
+ _Thread_queue_Enqueue( &the_semaphore->Wait_queue, timeout );
+}
diff --git a/cpukit/score/src/coresemsurrender.c b/cpukit/score/src/coresemsurrender.c
new file mode 100644
index 0000000000..a5f9d544d6
--- /dev/null
+++ b/cpukit/score/src/coresemsurrender.c
@@ -0,0 +1,73 @@
+/*
+ * CORE Semaphore Handler
+ *
+ * DESCRIPTION:
+ *
+ * This package is the implementation of the CORE Semaphore Handler.
+ * This core object utilizes standard Dijkstra counting semaphores to provide
+ * synchronization and mutual exclusion capabilities.
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/coresem.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#endif
+
+/*PAGE
+ *
+ * _CORE_semaphore_Surrender
+ *
+ * Input parameters:
+ * the_semaphore - the semaphore to be flushed
+ * id - id of parent semaphore
+ * api_semaphore_mp_support - api dependent MP support actions
+ *
+ * Output parameters:
+ * CORE_SEMAPHORE_STATUS_SUCCESSFUL - if successful
+ * core error code - if unsuccessful
+ *
+ * Output parameters:
+ */
+
+CORE_semaphore_Status _CORE_semaphore_Surrender(
+ CORE_semaphore_Control *the_semaphore,
+ Objects_Id id,
+ CORE_semaphore_API_mp_support_callout api_semaphore_mp_support
+)
+{
+ Thread_Control *the_thread;
+ ISR_Level level;
+ CORE_semaphore_Status status;
+
+ status = CORE_SEMAPHORE_STATUS_SUCCESSFUL;
+
+ if ( (the_thread = _Thread_queue_Dequeue(&the_semaphore->Wait_queue)) ) {
+
+ if ( !_Objects_Is_local_id( the_thread->Object.id ) )
+ (*api_semaphore_mp_support) ( the_thread, id );
+
+ } else {
+ _ISR_Disable( level );
+ if ( the_semaphore->count < the_semaphore->Attributes.maximum_count )
+ the_semaphore->count += 1;
+ else
+ status = CORE_SEMAPHORE_MAXIMUM_COUNT_EXCEEDED;
+ _ISR_Enable( level );
+ }
+
+ return status;
+}
diff --git a/cpukit/score/src/coretod.c b/cpukit/score/src/coretod.c
new file mode 100644
index 0000000000..30824108ac
--- /dev/null
+++ b/cpukit/score/src/coretod.c
@@ -0,0 +1,59 @@
+/*
+ * Time of Day (TOD) Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * _TOD_Handler_initialization
+ *
+ * This routine initializes the time of day handler.
+ *
+ * Input parameters:
+ * microseconds_per_tick - microseconds between clock ticks
+ *
+ * Output parameters: NONE
+ */
+
+void _TOD_Handler_initialization(
+ uint32_t microseconds_per_tick
+)
+{
+ _TOD_Microseconds_per_tick = microseconds_per_tick;
+
+ _TOD_Seconds_since_epoch = 0;
+
+ _TOD_Current.year = TOD_BASE_YEAR;
+ _TOD_Current.month = 1;
+ _TOD_Current.day = 1;
+ _TOD_Current.hour = 0;
+ _TOD_Current.minute = 0;
+ _TOD_Current.second = 0;
+ _TOD_Current.ticks = 0;
+
+ if ( microseconds_per_tick == 0 )
+ _TOD_Ticks_per_second = 0;
+ else
+ _TOD_Ticks_per_second =
+ TOD_MICROSECONDS_PER_SECOND / microseconds_per_tick;
+
+ _Watchdog_Initialize( &_TOD_Seconds_watchdog, _TOD_Tickle, 0, NULL );
+
+ _TOD_Is_set = FALSE;
+ _TOD_Activate( _TOD_Ticks_per_second );
+}
diff --git a/cpukit/score/src/coretodset.c b/cpukit/score/src/coretodset.c
new file mode 100644
index 0000000000..c679e5e8f4
--- /dev/null
+++ b/cpukit/score/src/coretodset.c
@@ -0,0 +1,62 @@
+/*
+ * Time of Day (TOD) Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * _TOD_Set
+ *
+ * This rountine sets the current date and time with the specified
+ * new date and time structure.
+ *
+ * Input parameters:
+ * the_tod - pointer to the time and date structure
+ * seconds_since_epoch - seconds since system epoch
+ *
+ * Output parameters: NONE
+ */
+
+void _TOD_Set(
+ TOD_Control *the_tod,
+ Watchdog_Interval seconds_since_epoch
+)
+{
+ Watchdog_Interval ticks_until_next_second;
+
+ _Thread_Disable_dispatch();
+ _TOD_Deactivate();
+
+ if ( seconds_since_epoch < _TOD_Seconds_since_epoch )
+ _Watchdog_Adjust_seconds( WATCHDOG_BACKWARD,
+ _TOD_Seconds_since_epoch - seconds_since_epoch );
+ else
+ _Watchdog_Adjust_seconds( WATCHDOG_FORWARD,
+ seconds_since_epoch - _TOD_Seconds_since_epoch );
+
+ ticks_until_next_second = _TOD_Ticks_per_second;
+ if ( ticks_until_next_second > the_tod->ticks )
+ ticks_until_next_second -= the_tod->ticks;
+
+ _TOD_Current = *the_tod;
+ _TOD_Seconds_since_epoch = seconds_since_epoch;
+ _TOD_Is_set = TRUE;
+ _TOD_Activate( ticks_until_next_second );
+
+ _Thread_Enable_dispatch();
+}
diff --git a/cpukit/score/src/coretodtickle.c b/cpukit/score/src/coretodtickle.c
new file mode 100644
index 0000000000..408b819ac2
--- /dev/null
+++ b/cpukit/score/src/coretodtickle.c
@@ -0,0 +1,67 @@
+/*
+ * Time of Day (TOD) Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * _TOD_Tickle
+ *
+ * This routine updates the calendar time and tickles the
+ * per second watchdog timer chain.
+ *
+ * Input parameters:
+ * ignored - this parameter is ignored
+ *
+ * Output parameters: NONE
+ *
+ * NOTE: This routine only works for leap-years through 2099.
+ */
+
+void _TOD_Tickle(
+ Objects_Id id,
+ void *ignored
+)
+{
+ uint32_t leap;
+
+ _TOD_Current.ticks = 0;
+ ++_TOD_Seconds_since_epoch;
+ if ( ++_TOD_Current.second >= TOD_SECONDS_PER_MINUTE ) {
+ _TOD_Current.second = 0;
+ if ( ++_TOD_Current.minute >= TOD_MINUTES_PER_HOUR ) {
+ _TOD_Current.minute = 0;
+ if ( ++_TOD_Current.hour >= TOD_HOURS_PER_DAY ) {
+ _TOD_Current.hour = 0;
+ if ( _TOD_Current.year & 0x3 ) leap = 0;
+ else leap = 1;
+ if ( ++_TOD_Current.day >
+ _TOD_Days_per_month[ leap ][ _TOD_Current.month ]) {
+ _TOD_Current.day = 1;
+ if ( ++_TOD_Current.month > TOD_MONTHS_PER_YEAR ) {
+ _TOD_Current.month = 1;
+ _TOD_Current.year++;
+ }
+ }
+ }
+ }
+ }
+
+ _Watchdog_Tickle_seconds();
+ _Watchdog_Insert_ticks( &_TOD_Seconds_watchdog, _TOD_Ticks_per_second );
+}
diff --git a/cpukit/score/src/coretodtoseconds.c b/cpukit/score/src/coretodtoseconds.c
new file mode 100644
index 0000000000..ae60f512b0
--- /dev/null
+++ b/cpukit/score/src/coretodtoseconds.c
@@ -0,0 +1,63 @@
+/*
+ * Time of Day (TOD) Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * _TOD_To_seconds
+ *
+ * This routine returns the seconds from the epoch until the
+ * current date and time.
+ *
+ * Input parameters:
+ * the_tod - pointer to the time and date structure
+ *
+ * Output parameters:
+ * returns - seconds since epoch until the_tod
+ */
+
+uint32_t _TOD_To_seconds(
+ TOD_Control *the_tod
+)
+{
+ uint32_t time;
+ uint32_t year_mod_4;
+
+ time = the_tod->day - 1;
+ year_mod_4 = the_tod->year & 3;
+
+ if ( year_mod_4 == 0 )
+ time += _TOD_Days_to_date[ 1 ][ the_tod->month ];
+ else
+ time += _TOD_Days_to_date[ 0 ][ the_tod->month ];
+
+ time += ( (the_tod->year - TOD_BASE_YEAR) / 4 ) *
+ ( (TOD_DAYS_PER_YEAR * 4) + 1);
+
+ time += _TOD_Days_since_last_leap_year[ year_mod_4 ];
+
+ time *= TOD_SECONDS_PER_DAY;
+
+ time += ((the_tod->hour * TOD_MINUTES_PER_HOUR) + the_tod->minute)
+ * TOD_SECONDS_PER_MINUTE;
+
+ time += the_tod->second;
+
+ return( time );
+}
diff --git a/cpukit/score/src/coretodvalidate.c b/cpukit/score/src/coretodvalidate.c
new file mode 100644
index 0000000000..1a92f81c57
--- /dev/null
+++ b/cpukit/score/src/coretodvalidate.c
@@ -0,0 +1,63 @@
+/*
+ * Time of Day (TOD) Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/tod.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * _TOD_Validate
+ *
+ * This kernel routine checks the validity of a date and time structure.
+ *
+ * Input parameters:
+ * the_tod - pointer to a time and date structure
+ *
+ * Output parameters:
+ * TRUE - if the date, time, and tick are valid
+ * FALSE - if the the_tod is invalid
+ *
+ * NOTE: This routine only works for leap-years through 2099.
+ */
+
+boolean _TOD_Validate(
+ TOD_Control *the_tod
+)
+{
+ uint32_t days_in_month;
+
+ if ((!the_tod) ||
+ (the_tod->ticks >= _TOD_Ticks_per_second) ||
+ (the_tod->second >= TOD_SECONDS_PER_MINUTE) ||
+ (the_tod->minute >= TOD_MINUTES_PER_HOUR) ||
+ (the_tod->hour >= TOD_HOURS_PER_DAY) ||
+ (the_tod->month == 0) ||
+ (the_tod->month > TOD_MONTHS_PER_YEAR) ||
+ (the_tod->year < TOD_BASE_YEAR) ||
+ (the_tod->day == 0) )
+ return FALSE;
+
+ if ( (the_tod->year % 4) == 0 )
+ days_in_month = _TOD_Days_per_month[ 1 ][ the_tod->month ];
+ else
+ days_in_month = _TOD_Days_per_month[ 0 ][ the_tod->month ];
+
+ if ( the_tod->day > days_in_month )
+ return FALSE;
+
+ return TRUE;
+}
diff --git a/cpukit/score/src/heap.c b/cpukit/score/src/heap.c
new file mode 100644
index 0000000000..6d6873ebed
--- /dev/null
+++ b/cpukit/score/src/heap.c
@@ -0,0 +1,92 @@
+/*
+ * Heap Handler
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+
+#include <rtems/system.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/heap.h>
+
+/*PAGE
+ *
+ * _Heap_Initialize
+ *
+ * This kernel routine initializes a heap.
+ *
+ * Input parameters:
+ * the_heap - pointer to heap header
+ * starting_address - starting address of heap
+ * size - size of heap
+ * page_size - allocatable unit of memory
+ *
+ * Output parameters:
+ * returns - maximum memory available if RTEMS_SUCCESSFUL
+ * 0 - otherwise
+ *
+ * This is what a heap looks like in memory immediately
+ * after initialization:
+ *
+ * +--------------------------------+
+ * 0 | size = 0 | status = used | a.k.a. dummy back flag
+ * +--------------------------------+
+ * 4 | size = size-8 | status = free | a.k.a. front flag
+ * +--------------------------------+
+ * 8 | next = PERM HEAP_TAIL |
+ * +--------------------------------+
+ * 12 | previous = PERM HEAP_HEAD |
+ * +--------------------------------+
+ * | |
+ * | memory available |
+ * | for allocation |
+ * | |
+ * +--------------------------------+
+ * size - 8 | size = size-8 | status = free | a.k.a. back flag
+ * +--------------------------------+
+ * size - 4 | size = 0 | status = used | a.k.a. dummy front flag
+ * +--------------------------------+
+ */
+
+uint32_t _Heap_Initialize(
+ Heap_Control *the_heap,
+ void *starting_address,
+ uint32_t size,
+ uint32_t page_size
+)
+{
+ Heap_Block *the_block;
+ uint32_t the_size;
+
+ if ( !_Heap_Is_page_size_valid( page_size ) ||
+ (size < HEAP_MINIMUM_SIZE) )
+ return 0;
+
+ the_heap->page_size = page_size;
+ the_size = size - HEAP_OVERHEAD;
+
+ the_block = (Heap_Block *) starting_address;
+ the_block->back_flag = HEAP_DUMMY_FLAG;
+ the_block->front_flag = the_size;
+ the_block->next = _Heap_Tail( the_heap );
+ the_block->previous = _Heap_Head( the_heap );
+
+ the_heap->start = the_block;
+ the_heap->first = the_block;
+ the_heap->permanent_null = NULL;
+ the_heap->last = the_block;
+
+ the_block = _Heap_Next_block( the_block );
+ the_block->back_flag = the_size;
+ the_block->front_flag = HEAP_DUMMY_FLAG;
+ the_heap->final = the_block;
+
+ return ( the_size - HEAP_BLOCK_USED_OVERHEAD );
+}
diff --git a/cpukit/score/src/heapallocate.c b/cpukit/score/src/heapallocate.c
new file mode 100644
index 0000000000..54bdd58e45
--- /dev/null
+++ b/cpukit/score/src/heapallocate.c
@@ -0,0 +1,113 @@
+/*
+ * Heap Handler
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+
+#include <rtems/system.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/heap.h>
+
+/*PAGE
+ *
+ * _Heap_Allocate
+ *
+ * This kernel routine allocates the requested size of memory
+ * from the specified heap.
+ *
+ * Input parameters:
+ * the_heap - pointer to heap header.
+ * size - size in bytes of the memory block to allocate.
+ *
+ * Output parameters:
+ * returns - starting address of memory block allocated
+ */
+
+void *_Heap_Allocate(
+ Heap_Control *the_heap,
+ uint32_t size
+)
+{
+ uint32_t excess;
+ uint32_t the_size;
+ Heap_Block *the_block;
+ Heap_Block *next_block;
+ Heap_Block *temporary_block;
+ void *ptr;
+ uint32_t offset;
+
+ /*
+ * Catch the case of a user allocating close to the limit of the
+ * uint32_t .
+ */
+
+ if ( size >= (-1 - HEAP_BLOCK_USED_OVERHEAD) )
+ return( NULL );
+
+ excess = size % the_heap->page_size;
+ the_size = size + the_heap->page_size + HEAP_BLOCK_USED_OVERHEAD;
+
+ if ( excess )
+ the_size += the_heap->page_size - excess;
+
+ if ( the_size < sizeof( Heap_Block ) )
+ the_size = sizeof( Heap_Block );
+
+ for ( the_block = the_heap->first;
+ ;
+ the_block = the_block->next ) {
+ if ( the_block == _Heap_Tail( the_heap ) )
+ return( NULL );
+ if ( the_block->front_flag >= the_size )
+ break;
+ }
+
+ if ( (the_block->front_flag - the_size) >
+ (the_heap->page_size + HEAP_BLOCK_USED_OVERHEAD) ) {
+ the_block->front_flag -= the_size;
+ next_block = _Heap_Next_block( the_block );
+ next_block->back_flag = the_block->front_flag;
+
+ temporary_block = _Heap_Block_at( next_block, the_size );
+ temporary_block->back_flag =
+ next_block->front_flag = _Heap_Build_flag( the_size,
+ HEAP_BLOCK_USED );
+ ptr = _Heap_Start_of_user_area( next_block );
+ } else {
+ next_block = _Heap_Next_block( the_block );
+ next_block->back_flag = _Heap_Build_flag( the_block->front_flag,
+ HEAP_BLOCK_USED );
+ the_block->front_flag = next_block->back_flag;
+ the_block->next->previous = the_block->previous;
+ the_block->previous->next = the_block->next;
+ ptr = _Heap_Start_of_user_area( the_block );
+ }
+
+ /*
+ * round ptr up to a multiple of page size
+ * Have to save the bump amount in the buffer so that free can figure it out
+ */
+
+ offset = the_heap->page_size - (((uint32_t ) ptr) & (the_heap->page_size - 1));
+ ptr = _Addresses_Add_offset( ptr, offset );
+ *(((uint32_t *) ptr) - 1) = offset;
+
+#ifdef RTEMS_DEBUG
+ {
+ uint32_t ptr_u32;
+ ptr_u32 = (uint32_t ) ptr;
+ if (ptr_u32 & (the_heap->page_size - 1))
+ abort();
+ }
+#endif
+
+ return ptr;
+}
diff --git a/cpukit/score/src/heapextend.c b/cpukit/score/src/heapextend.c
new file mode 100644
index 0000000000..3cb318d70b
--- /dev/null
+++ b/cpukit/score/src/heapextend.c
@@ -0,0 +1,111 @@
+/*
+ * Heap Handler
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+
+#include <rtems/system.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/heap.h>
+
+/*PAGE
+ *
+ * _Heap_Extend
+ *
+ * This routine grows the_heap memory area using the size bytes which
+ * begin at starting_address.
+ *
+ * Input parameters:
+ * the_heap - pointer to heap header.
+ * starting_address - pointer to the memory area.
+ * size - size in bytes of the memory block to allocate.
+ *
+ * Output parameters:
+ * *amount_extended - amount of memory added to the_heap
+ */
+
+Heap_Extend_status _Heap_Extend(
+ Heap_Control *the_heap,
+ void *starting_address,
+ uint32_t size,
+ uint32_t *amount_extended
+)
+{
+ Heap_Block *the_block;
+ uint32_t *p;
+
+ /*
+ * The overhead was taken from the original heap memory.
+ */
+
+ Heap_Block *old_final;
+ Heap_Block *new_final;
+
+ /*
+ * There are five possibilities for the location of starting
+ * address:
+ *
+ * 1. non-contiguous lower address (NOT SUPPORTED)
+ * 2. contiguous lower address (NOT SUPPORTED)
+ * 3. in the heap (ERROR)
+ * 4. contiguous higher address (SUPPORTED)
+ * 5. non-contiguous higher address (NOT SUPPORTED)
+ *
+ * As noted, this code only supports (4).
+ */
+
+ if ( starting_address >= (void *) the_heap->start && /* case 3 */
+ starting_address <= (void *) the_heap->final
+ )
+ return HEAP_EXTEND_ERROR;
+
+ if ( starting_address < (void *) the_heap->start ) { /* cases 1 and 2 */
+
+ return HEAP_EXTEND_NOT_IMPLEMENTED; /* cases 1 and 2 */
+
+ } else { /* cases 4 and 5 */
+
+ the_block = (Heap_Block *)
+ _Addresses_Subtract_offset( starting_address, HEAP_OVERHEAD );
+ if ( the_block != the_heap->final )
+ return HEAP_EXTEND_NOT_IMPLEMENTED; /* case 5 */
+ }
+
+ /*
+ * Currently only case 4 should make it to this point.
+ * The basic trick is to make the extend area look like a used
+ * block and free it.
+ */
+
+ *amount_extended = size;
+
+ old_final = the_heap->final;
+ new_final = _Addresses_Add_offset( old_final, size );
+ /* SAME AS: _Addresses_Add_offset( starting_address, size-HEAP_OVERHEAD ); */
+
+ the_heap->final = new_final;
+
+ old_final->front_flag =
+ new_final->back_flag = _Heap_Build_flag( size, HEAP_BLOCK_USED );
+ new_final->front_flag = HEAP_DUMMY_FLAG;
+
+ /*
+ * Must pass in address of "user" area
+ * So add in the offset field.
+ */
+
+ p = (uint32_t *) &old_final->next;
+ *p = sizeof(uint32_t );
+ p++;
+ _Heap_Free( the_heap, p );
+
+ return HEAP_EXTEND_SUCCESSFUL;
+}
diff --git a/cpukit/score/src/heapfree.c b/cpukit/score/src/heapfree.c
new file mode 100644
index 0000000000..40e56a7b88
--- /dev/null
+++ b/cpukit/score/src/heapfree.c
@@ -0,0 +1,103 @@
+/*
+ * Heap Handler
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+
+#include <rtems/system.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/heap.h>
+
+/*PAGE
+ *
+ * _Heap_Free
+ *
+ * This kernel routine returns the memory designated by the
+ * given heap and given starting address to the memory pool.
+ *
+ * Input parameters:
+ * the_heap - pointer to heap header
+ * starting_address - starting address of the memory block to free.
+ *
+ * Output parameters:
+ * TRUE - if starting_address is valid heap address
+ * FALSE - if starting_address is invalid heap address
+ */
+
+boolean _Heap_Free(
+ Heap_Control *the_heap,
+ void *starting_address
+)
+{
+ Heap_Block *the_block;
+ Heap_Block *next_block;
+ Heap_Block *new_next_block;
+ Heap_Block *previous_block;
+ Heap_Block *temporary_block;
+ uint32_t the_size;
+
+ the_block = _Heap_User_block_at( starting_address );
+
+ if ( !_Heap_Is_block_in( the_heap, the_block ) ||
+ _Heap_Is_block_free( the_block ) ) {
+ return( FALSE );
+ }
+
+ the_size = _Heap_Block_size( the_block );
+ next_block = _Heap_Block_at( the_block, the_size );
+
+ if ( !_Heap_Is_block_in( the_heap, next_block ) ||
+ (the_block->front_flag != next_block->back_flag) ) {
+ return( FALSE );
+ }
+
+ if ( _Heap_Is_previous_block_free( the_block ) ) {
+ previous_block = _Heap_Previous_block( the_block );
+
+ if ( !_Heap_Is_block_in( the_heap, previous_block ) ) {
+ return( FALSE );
+ }
+
+ if ( _Heap_Is_block_free( next_block ) ) { /* coalesce both */
+ previous_block->front_flag += next_block->front_flag + the_size;
+ temporary_block = _Heap_Next_block( previous_block );
+ temporary_block->back_flag = previous_block->front_flag;
+ next_block->next->previous = next_block->previous;
+ next_block->previous->next = next_block->next;
+ }
+ else { /* coalesce prev */
+ previous_block->front_flag =
+ next_block->back_flag = previous_block->front_flag + the_size;
+ }
+ }
+ else if ( _Heap_Is_block_free( next_block ) ) { /* coalesce next */
+ the_block->front_flag = the_size + next_block->front_flag;
+ new_next_block = _Heap_Next_block( the_block );
+ new_next_block->back_flag = the_block->front_flag;
+ the_block->next = next_block->next;
+ the_block->previous = next_block->previous;
+ next_block->previous->next = the_block;
+ next_block->next->previous = the_block;
+
+ if (the_heap->first == next_block)
+ the_heap->first = the_block;
+ }
+ else { /* no coalesce */
+ next_block->back_flag =
+ the_block->front_flag = the_size;
+ the_block->previous = _Heap_Head( the_heap );
+ the_block->next = the_heap->first;
+ the_heap->first = the_block;
+ the_block->next->previous = the_block;
+ }
+
+ return( TRUE );
+}
diff --git a/cpukit/score/src/heapgetinfo.c b/cpukit/score/src/heapgetinfo.c
new file mode 100644
index 0000000000..b3f878f5f2
--- /dev/null
+++ b/cpukit/score/src/heapgetinfo.c
@@ -0,0 +1,101 @@
+/*
+ * Heap Handler
+ *
+ * COPYRIGHT (c) 1989-2000.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ */
+
+
+#include <rtems/system.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/heap.h>
+
+/*PAGE
+ *
+ * _Heap_Get_information
+ *
+ * This kernel routine walks the heap and tots up the free and allocated
+ * sizes. Derived from _Heap_Walk.
+ *
+ * Input parameters:
+ * the_heap - pointer to heap header
+ * the_info - pointer for information to be returned
+ *
+ * Output parameters:
+ * *the_info - contains information about heap
+ * return 0=success, otherwise heap is corrupt.
+ */
+
+
+Heap_Get_information_status _Heap_Get_information(
+ Heap_Control *the_heap,
+ Heap_Information_block *the_info
+)
+{
+ Heap_Block *the_block = 0; /* avoid warnings */
+ Heap_Block *next_block = 0; /* avoid warnings */
+ int notdone = 1;
+
+
+ the_info->free_blocks = 0;
+ the_info->free_size = 0;
+ the_info->used_blocks = 0;
+ the_info->used_size = 0;
+
+ /*
+ * We don't want to allow walking the heap until we have
+ * transferred control to the user task so we watch the
+ * system state.
+ */
+
+ if ( !_System_state_Is_up( _System_state_Get() ) )
+ return HEAP_GET_INFORMATION_SYSTEM_STATE_ERROR;
+
+ the_block = the_heap->start;
+
+ /*
+ * Handle the 1st block
+ */
+
+ if ( the_block->back_flag != HEAP_DUMMY_FLAG ) {
+ return HEAP_GET_INFORMATION_BLOCK_ERROR;
+ }
+
+ while (notdone) {
+
+ /*
+ * Accumulate size
+ */
+
+ if ( _Heap_Is_block_free(the_block) ) {
+ the_info->free_blocks++;
+ the_info->free_size += _Heap_Block_size(the_block);
+ } else {
+ the_info->used_blocks++;
+ the_info->used_size += _Heap_Block_size(the_block);
+ }
+
+ /*
+ * Handle the last block
+ */
+
+ if ( the_block->front_flag != HEAP_DUMMY_FLAG ) {
+ next_block = _Heap_Next_block(the_block);
+ if ( the_block->front_flag != next_block->back_flag ) {
+ return HEAP_GET_INFORMATION_BLOCK_ERROR;
+ }
+ }
+
+ if ( the_block->front_flag == HEAP_DUMMY_FLAG )
+ notdone = 0;
+ else
+ the_block = next_block;
+ } /* while(notdone) */
+
+ return HEAP_GET_INFORMATION_SUCCESSFUL;
+}
diff --git a/cpukit/score/src/heapsizeofuserarea.c b/cpukit/score/src/heapsizeofuserarea.c
new file mode 100644
index 0000000000..b140247afe
--- /dev/null
+++ b/cpukit/score/src/heapsizeofuserarea.c
@@ -0,0 +1,62 @@
+/*
+ * Heap Handler
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+
+#include <rtems/system.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/heap.h>
+
+/*PAGE
+ *
+ * _Heap_Size_of_user_area
+ *
+ * This kernel routine returns the size of the memory area
+ * given heap block.
+ *
+ * Input parameters:
+ * the_heap - pointer to heap header
+ * starting_address - starting address of the memory block to free.
+ * size - pointer to size of area
+ *
+ * Output parameters:
+ * size - size of area filled in
+ * TRUE - if starting_address is valid heap address
+ * FALSE - if starting_address is invalid heap address
+ */
+
+boolean _Heap_Size_of_user_area(
+ Heap_Control *the_heap,
+ void *starting_address,
+ uint32_t *size
+)
+{
+ Heap_Block *the_block;
+ Heap_Block *next_block;
+ uint32_t the_size;
+
+ the_block = _Heap_User_block_at( starting_address );
+
+ if ( !_Heap_Is_block_in( the_heap, the_block ) ||
+ _Heap_Is_block_free( the_block ) )
+ return( FALSE );
+
+ the_size = _Heap_Block_size( the_block );
+ next_block = _Heap_Block_at( the_block, the_size );
+
+ if ( !_Heap_Is_block_in( the_heap, next_block ) ||
+ (the_block->front_flag != next_block->back_flag) )
+ return( FALSE );
+
+ *size = the_size;
+ return( TRUE );
+}
diff --git a/cpukit/score/src/heapwalk.c b/cpukit/score/src/heapwalk.c
new file mode 100644
index 0000000000..4f93ae7be0
--- /dev/null
+++ b/cpukit/score/src/heapwalk.c
@@ -0,0 +1,149 @@
+/*
+ * Heap Handler
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+
+#include <rtems/system.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/heap.h>
+
+/*PAGE
+ *
+ * _Heap_Walk
+ *
+ * This kernel routine walks the heap and verifies its correctness.
+ *
+ * Input parameters:
+ * the_heap - pointer to heap header
+ * source - a numeric indicator of the invoker of this routine
+ * do_dump - when TRUE print the information
+ *
+ * Output parameters: NONE
+ */
+
+#ifndef RTEMS_DEBUG
+
+void _Heap_Walk(
+ Heap_Control *the_heap,
+ int source,
+ boolean do_dump
+)
+{
+}
+
+#else
+
+#include <stdio.h>
+#include <unistd.h>
+
+void _Heap_Walk(
+ Heap_Control *the_heap,
+ int source,
+ boolean do_dump
+)
+{
+ Heap_Block *the_block = 0; /* avoid warnings */
+ Heap_Block *next_block = 0; /* avoid warnings */
+ int notdone = 1;
+ int error = 0;
+ int passes = 0;
+
+ /*
+ * We don't want to allow walking the heap until we have
+ * transferred control to the user task so we watch the
+ * system state.
+ */
+
+ if ( !_System_state_Is_up( _System_state_Get() ) )
+ return;
+
+ the_block = the_heap->start;
+
+ if (do_dump == TRUE) {
+ printf("\nPASS: %d start @ 0x%p final 0x%p, first 0x%p last 0x%p\n",
+ source, the_heap->start, the_heap->final,
+ the_heap->first, the_heap->last
+ );
+ }
+
+ /*
+ * Handle the 1st block
+ */
+
+ if (the_block->back_flag != HEAP_DUMMY_FLAG) {
+ printf("PASS: %d Back flag of 1st block isn't HEAP_DUMMY_FLAG\n", source);
+ error = 1;
+ }
+
+ while (notdone) {
+ passes++;
+ if (error && (passes > 10))
+ abort();
+
+ if (do_dump == TRUE) {
+ printf("PASS: %d Block @ 0x%p Back %d, Front %d",
+ source, the_block,
+ the_block->back_flag, the_block->front_flag);
+ if ( _Heap_Is_block_free(the_block) ) {
+ printf( " Prev 0x%p, Next 0x%p\n",
+ the_block->previous, the_block->next);
+ } else {
+ printf("\n");
+ }
+ }
+
+ /*
+ * Handle the last block
+ */
+
+ if ( the_block->front_flag != HEAP_DUMMY_FLAG ) {
+ next_block = _Heap_Next_block(the_block);
+ if ( the_block->front_flag != next_block->back_flag ) {
+ error = 1;
+ printf("PASS: %d Front and back flags don't match\n", source);
+ printf(" Current Block (%p): Back - %d, Front - %d",
+ the_block, the_block->back_flag, the_block->front_flag);
+ if (do_dump == TRUE) {
+ if (_Heap_Is_block_free(the_block)) {
+ printf(" Prev 0x%p, Next 0x%p\n",
+ the_block->previous, the_block->next);
+ } else {
+ printf("\n");
+ }
+ } else {
+ printf("\n");
+ }
+ printf(" Next Block (%p): Back - %d, Front - %d",
+ next_block, next_block->back_flag, next_block->front_flag);
+ if (do_dump == TRUE) {
+ if (_Heap_Is_block_free(next_block)) {
+ printf(" Prev 0x%p, Next 0x%p\n",
+ the_block->previous, the_block->next);
+ } else {
+ printf("\n");
+ }
+ } else {
+ printf("\n");
+ }
+ }
+ }
+
+ if (the_block->front_flag == HEAP_DUMMY_FLAG)
+ notdone = 0;
+ else
+ the_block = next_block;
+ }
+
+ if (error)
+ abort();
+}
+#endif
diff --git a/cpukit/score/src/interr.c b/cpukit/score/src/interr.c
new file mode 100644
index 0000000000..3dda8e6f9d
--- /dev/null
+++ b/cpukit/score/src/interr.c
@@ -0,0 +1,60 @@
+/*
+ * Internal Error Handler
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/userext.h>
+
+/*PAGE
+ *
+ * _Internal_error_Occurred
+ *
+ * This routine will invoke the fatal error handler supplied by the user
+ * followed by the the default one provided by the executive. The default
+ * error handler assumes no hardware is present to help inform the user
+ * of the problem. Halt stores the error code in a known register,
+ * disables interrupts, and halts the CPU. If the CPU does not have a
+ * halt instruction, it will loop to itself.
+ *
+ * Input parameters:
+ * the_source - what subsystem the error originated in
+ * is_internal - if the error was internally generated
+ * the_error - fatal error status code
+ *
+ * Output parameters:
+ * As much information as possible is stored in a CPU dependent fashion.
+ * See the CPU dependent code for more information.
+ *
+ * NOTE: The the_error is not necessarily a directive status code.
+ */
+
+void volatile _Internal_error_Occurred(
+ Internal_errors_Source the_source,
+ boolean is_internal,
+ uint32_t the_error
+)
+{
+
+ Internal_errors_What_happened.the_source = the_source;
+ Internal_errors_What_happened.is_internal = is_internal;
+ Internal_errors_What_happened.the_error = the_error;
+
+ _User_extensions_Fatal( the_source, is_internal, the_error );
+
+ _System_state_Set( SYSTEM_STATE_FAILED );
+
+ _CPU_Fatal_halt( the_error );
+
+ /* will not return from this routine */
+}
diff --git a/cpukit/score/src/isr.c b/cpukit/score/src/isr.c
new file mode 100644
index 0000000000..b1cf2e5c0d
--- /dev/null
+++ b/cpukit/score/src/isr.c
@@ -0,0 +1,65 @@
+/*
+ * ISR Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/stack.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/wkspace.h>
+
+/* _ISR_Handler_initialization
+ *
+ * This routine initializes the ISR handler.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ */
+
+void _ISR_Handler_initialization( void )
+{
+ _ISR_Signals_to_thread_executing = FALSE;
+
+ _ISR_Nest_level = 0;
+
+ _ISR_Vector_table = _Workspace_Allocate_or_fatal_error(
+ sizeof(ISR_Handler_entry) * ISR_NUMBER_OF_VECTORS
+ );
+
+ _CPU_Initialize_vectors();
+
+#if ( CPU_ALLOCATE_INTERRUPT_STACK == TRUE )
+
+ if ( _CPU_Table.interrupt_stack_size < STACK_MINIMUM_SIZE )
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ TRUE,
+ INTERNAL_ERROR_INTERRUPT_STACK_TOO_SMALL
+ );
+
+ _CPU_Interrupt_stack_low =
+ _Workspace_Allocate_or_fatal_error( _CPU_Table.interrupt_stack_size );
+
+ _CPU_Interrupt_stack_high = _Addresses_Add_offset(
+ _CPU_Interrupt_stack_low,
+ _CPU_Table.interrupt_stack_size
+ );
+
+#endif
+
+#if ( CPU_HAS_HARDWARE_INTERRUPT_STACK == TRUE )
+ _CPU_Install_interrupt_stack();
+#endif
+
+}
diff --git a/cpukit/score/src/iterateoverthreads.c b/cpukit/score/src/iterateoverthreads.c
new file mode 100644
index 0000000000..7577c317c7
--- /dev/null
+++ b/cpukit/score/src/iterateoverthreads.c
@@ -0,0 +1,46 @@
+/*
+ * rtems_iterate_over_all_threads
+ *
+ * This function operates by as follows:
+ * for all threads
+ * invoke specified function
+ *
+ * COPYRIGHT (c) 1989-2003.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/thread.h>
+
+void rtems_iterate_over_all_threads(rtems_per_thread_routine routine)
+{
+ uint32_t i;
+ uint32_t api_index;
+ Thread_Control *the_thread;
+ Objects_Information *information;
+
+ for ( api_index = 1 ;
+ api_index <= OBJECTS_APIS_LAST ;
+ api_index++ ) {
+ if ( !_Objects_Information_table[ api_index ] )
+ continue;
+ information = _Objects_Information_table[ api_index ][ 1 ];
+ if ( information ) {
+ for ( i=1 ; i <= information->maximum ; i++ ) {
+ the_thread = (Thread_Control *)information->local_table[ i ];
+
+ if ( !the_thread )
+ continue;
+
+ (*routine)(the_thread);
+ }
+ }
+ }
+
+}
diff --git a/cpukit/score/src/mpci.c b/cpukit/score/src/mpci.c
new file mode 100644
index 0000000000..adc2690dc6
--- /dev/null
+++ b/cpukit/score/src/mpci.c
@@ -0,0 +1,524 @@
+/*
+ * Multiprocessing Communications Interface (MPCI) Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/cpu.h>
+#include <rtems/score/interr.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/mpci.h>
+#include <rtems/score/mppkt.h>
+#endif
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+#include <rtems/score/watchdog.h>
+#include <rtems/score/sysstate.h>
+
+#include <rtems/score/coresem.h>
+
+/*PAGE
+ *
+ * _MPCI_Handler_initialization
+ *
+ * This subprogram performs the initialization necessary for this handler.
+ */
+
+void _MPCI_Handler_initialization(
+ MPCI_Control *users_mpci_table,
+ uint32_t timeout_status
+)
+{
+ CORE_semaphore_Attributes attributes;
+
+ if ( _System_state_Is_multiprocessing && !users_mpci_table )
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ TRUE,
+ INTERNAL_ERROR_NO_MPCI
+ );
+
+ _MPCI_table = users_mpci_table;
+
+ if ( !_System_state_Is_multiprocessing )
+ return;
+
+ /*
+ * Register the MP Process Packet routine.
+ */
+
+ _MPCI_Register_packet_processor(
+ MP_PACKET_MPCI_INTERNAL,
+ _MPCI_Internal_packets_Process_packet
+ );
+
+ /*
+ * Create the counting semaphore used by the MPCI Receive Server.
+ */
+
+ attributes.discipline = CORE_SEMAPHORE_DISCIPLINES_FIFO;
+
+ _CORE_semaphore_Initialize(
+ &_MPCI_Semaphore,
+ &attributes, /* the_semaphore_attributes */
+ 0 /* initial_value */
+ );
+
+ _Thread_queue_Initialize(
+ &_MPCI_Remote_blocked_threads,
+ THREAD_QUEUE_DISCIPLINE_FIFO,
+ STATES_WAITING_FOR_RPC_REPLY,
+ timeout_status
+ );
+}
+
+/*PAGE
+ *
+ * _MPCI_Create_server
+ *
+ * This subprogram creates the MPCI receive server.
+ */
+
+char *_MPCI_Internal_name = "MPCI";
+
+void _MPCI_Create_server( void )
+{
+
+ if ( !_System_state_Is_multiprocessing )
+ return;
+
+ /*
+ * Initialize the MPCI Receive Server
+ */
+
+ _MPCI_Receive_server_tcb = _Thread_Internal_allocate();
+
+ _Thread_Initialize(
+ &_Thread_Internal_information,
+ _MPCI_Receive_server_tcb,
+ NULL, /* allocate the stack */
+ MPCI_RECEIVE_SERVER_STACK_SIZE,
+ CPU_ALL_TASKS_ARE_FP,
+ PRIORITY_MINIMUM,
+ FALSE, /* no preempt */
+ THREAD_CPU_BUDGET_ALGORITHM_NONE,
+ NULL, /* no budget algorithm callout */
+ 0, /* all interrupts enabled */
+ _MPCI_Internal_name
+ );
+
+ _Thread_Start(
+ _MPCI_Receive_server_tcb,
+ THREAD_START_NUMERIC,
+ (void *) _MPCI_Receive_server,
+ NULL,
+ 0
+ );
+}
+
+/*PAGE
+ *
+ * _MPCI_Initialization
+ *
+ * This subprogram initializes the MPCI driver by
+ * invoking the user provided MPCI initialization callout.
+ */
+
+void _MPCI_Initialization ( void )
+{
+ (*_MPCI_table->initialization)();
+}
+
+/*PAGE
+ *
+ * _MPCI_Register_packet_processor
+ *
+ * This routine registers the MPCI packet processor for the
+ * designated object class.
+ */
+
+void _MPCI_Register_packet_processor(
+ MP_packet_Classes the_class,
+ MPCI_Packet_processor the_packet_processor
+
+)
+{
+ _MPCI_Packet_processors[ the_class ] = the_packet_processor;
+}
+
+/*PAGE
+ *
+ * _MPCI_Get_packet
+ *
+ * This subprogram obtains a packet by invoking the user provided
+ * MPCI get packet callout.
+ */
+
+MP_packet_Prefix *_MPCI_Get_packet ( void )
+{
+ MP_packet_Prefix *the_packet;
+
+ (*_MPCI_table->get_packet)( &the_packet );
+
+ if ( the_packet == NULL )
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ TRUE,
+ INTERNAL_ERROR_OUT_OF_PACKETS
+ );
+
+ /*
+ * Put in a default timeout that will be used for
+ * all packets that do not otherwise have a timeout.
+ */
+
+ the_packet->timeout = MPCI_DEFAULT_TIMEOUT;
+
+ return the_packet;
+}
+
+/*PAGE
+ *
+ * _MPCI_Return_packet
+ *
+ * This subprogram returns a packet by invoking the user provided
+ * MPCI return packet callout.
+ */
+
+void _MPCI_Return_packet (
+ MP_packet_Prefix *the_packet
+)
+{
+ (*_MPCI_table->return_packet)( the_packet );
+}
+
+/*PAGE
+ *
+ * _MPCI_Send_process_packet
+ *
+ * This subprogram sends a process packet by invoking the user provided
+ * MPCI send callout.
+ */
+
+void _MPCI_Send_process_packet (
+ uint32_t destination,
+ MP_packet_Prefix *the_packet
+)
+{
+ the_packet->source_tid = _Thread_Executing->Object.id;
+ the_packet->to_convert =
+ ( the_packet->to_convert - sizeof(MP_packet_Prefix) ) /
+ sizeof(uint32_t );
+
+ (*_MPCI_table->send_packet)( destination, the_packet );
+}
+
+/*PAGE
+ *
+ * _MPCI_Send_request_packet
+ *
+ * This subprogram sends a request packet by invoking the user provided
+ * MPCI send callout.
+ */
+
+uint32_t _MPCI_Send_request_packet (
+ uint32_t destination,
+ MP_packet_Prefix *the_packet,
+ States_Control extra_state
+)
+{
+ the_packet->source_tid = _Thread_Executing->Object.id;
+ the_packet->source_priority = _Thread_Executing->current_priority;
+ the_packet->to_convert =
+ ( the_packet->to_convert - sizeof(MP_packet_Prefix) ) /
+ sizeof(uint32_t );
+
+ _Thread_Executing->Wait.id = the_packet->id;
+
+ _Thread_Executing->Wait.queue = &_MPCI_Remote_blocked_threads;
+
+ _Thread_Disable_dispatch();
+
+ (*_MPCI_table->send_packet)( destination, the_packet );
+
+ _Thread_queue_Enter_critical_section( &_MPCI_Remote_blocked_threads );
+
+ /*
+ * See if we need a default timeout
+ */
+
+ if (the_packet->timeout == MPCI_DEFAULT_TIMEOUT)
+ the_packet->timeout = _MPCI_table->default_timeout;
+
+ _Thread_queue_Enqueue( &_MPCI_Remote_blocked_threads, the_packet->timeout );
+
+ _Thread_Executing->current_state =
+ _States_Set( extra_state, _Thread_Executing->current_state );
+
+ _Thread_Enable_dispatch();
+
+ return _Thread_Executing->Wait.return_code;
+}
+
+/*PAGE
+ *
+ * _MPCI_Send_response_packet
+ *
+ * This subprogram sends a response packet by invoking the user provided
+ * MPCI send callout.
+ */
+
+void _MPCI_Send_response_packet (
+ uint32_t destination,
+ MP_packet_Prefix *the_packet
+)
+{
+ the_packet->source_tid = _Thread_Executing->Object.id;
+
+ (*_MPCI_table->send_packet)( destination, the_packet );
+}
+
+/*PAGE
+ *
+ * _MPCI_Receive_packet
+ *
+ * This subprogram receives a packet by invoking the user provided
+ * MPCI receive callout.
+ */
+
+MP_packet_Prefix *_MPCI_Receive_packet ( void )
+{
+ MP_packet_Prefix *the_packet;
+
+ (*_MPCI_table->receive_packet)( &the_packet );
+
+ return the_packet;
+}
+
+/*PAGE
+ *
+ * _MPCI_Process_response
+ *
+ * This subprogram obtains a packet by invoking the user provided
+ * MPCI get packet callout.
+ */
+
+Thread_Control *_MPCI_Process_response (
+ MP_packet_Prefix *the_packet
+)
+{
+ Thread_Control *the_thread;
+ Objects_Locations location;
+
+ the_thread = _Thread_Get( the_packet->id, &location );
+ switch ( location ) {
+ case OBJECTS_ERROR:
+ case OBJECTS_REMOTE:
+ the_thread = NULL; /* IMPOSSIBLE */
+ break;
+ case OBJECTS_LOCAL:
+ _Thread_queue_Extract( &_MPCI_Remote_blocked_threads, the_thread );
+ the_thread->Wait.return_code = the_packet->return_code;
+ _Thread_Unnest_dispatch();
+ break;
+ }
+
+ return the_thread;
+}
+
+/*PAGE
+ *
+ * _MPCI_Receive_server
+ *
+ */
+
+Thread _MPCI_Receive_server(
+ uint32_t ignored
+)
+{
+
+ MP_packet_Prefix *the_packet;
+ MPCI_Packet_processor the_function;
+ Thread_Control *executing;
+
+ executing = _Thread_Executing;
+
+ for ( ; ; ) {
+
+ executing->receive_packet = NULL;
+
+ _Thread_Disable_dispatch();
+ _CORE_semaphore_Seize( &_MPCI_Semaphore, 0, TRUE, WATCHDOG_NO_TIMEOUT );
+ _Thread_Enable_dispatch();
+
+ for ( ; ; ) {
+ the_packet = _MPCI_Receive_packet();
+
+ if ( !the_packet )
+ break;
+
+ executing->receive_packet = the_packet;
+
+ if ( !_Mp_packet_Is_valid_packet_class ( the_packet->the_class ) )
+ break;
+
+ the_function = _MPCI_Packet_processors[ the_packet->the_class ];
+
+ if ( !the_function )
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ TRUE,
+ INTERNAL_ERROR_BAD_PACKET
+ );
+
+ (*the_function)( the_packet );
+ }
+ }
+
+ return 0; /* unreached - only to remove warnings */
+}
+
+/*PAGE
+ *
+ * _MPCI_Announce
+ *
+ */
+
+void _MPCI_Announce ( void )
+{
+ _Thread_Disable_dispatch();
+ (void) _CORE_semaphore_Surrender( &_MPCI_Semaphore, 0, 0 );
+ _Thread_Enable_dispatch();
+}
+
+/*PAGE
+ *
+ * _MPCI_Internal_packets_Send_process_packet
+ *
+ */
+
+void _MPCI_Internal_packets_Send_process_packet (
+ MPCI_Internal_Remote_operations operation
+)
+{
+ MPCI_Internal_packet *the_packet;
+
+ switch ( operation ) {
+
+ case MPCI_PACKETS_SYSTEM_VERIFY:
+
+ the_packet = _MPCI_Internal_packets_Get_packet();
+ the_packet->Prefix.the_class = MP_PACKET_MPCI_INTERNAL;
+ the_packet->Prefix.length = sizeof ( MPCI_Internal_packet );
+ the_packet->Prefix.to_convert = sizeof ( MPCI_Internal_packet );
+ the_packet->operation = operation;
+
+ the_packet->maximum_nodes = _Objects_Maximum_nodes;
+
+ the_packet->maximum_global_objects = _Objects_MP_Maximum_global_objects;
+
+ _MPCI_Send_process_packet( MPCI_ALL_NODES, &the_packet->Prefix );
+ break;
+ }
+}
+
+/*PAGE
+ *
+ * _MPCI_Internal_packets_Send_request_packet
+ *
+ * This subprogram is not needed since there are no request
+ * packets to be sent by this manager.
+ *
+ */
+
+/*PAGE
+ *
+ * _MPCI_Internal_packets_Send_response_packet
+ *
+ * This subprogram is not needed since there are no response
+ * packets to be sent by this manager.
+ *
+ */
+
+/*PAGE
+ *
+ *
+ * _MPCI_Internal_packets_Process_packet
+ *
+ */
+
+void _MPCI_Internal_packets_Process_packet (
+ MP_packet_Prefix *the_packet_prefix
+)
+{
+ MPCI_Internal_packet *the_packet;
+ uint32_t maximum_nodes;
+ uint32_t maximum_global_objects;
+
+ the_packet = (MPCI_Internal_packet *) the_packet_prefix;
+
+ switch ( the_packet->operation ) {
+
+ case MPCI_PACKETS_SYSTEM_VERIFY:
+
+ maximum_nodes = the_packet->maximum_nodes;
+ maximum_global_objects = the_packet->maximum_global_objects;
+ if ( maximum_nodes != _Objects_Maximum_nodes ||
+ maximum_global_objects != _Objects_MP_Maximum_global_objects ) {
+
+ _MPCI_Return_packet( the_packet_prefix );
+
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ TRUE,
+ INTERNAL_ERROR_INCONSISTENT_MP_INFORMATION
+ );
+ }
+
+ _MPCI_Return_packet( the_packet_prefix );
+
+ break;
+ }
+}
+
+/*PAGE
+ *
+ * _MPCI_Internal_packets_Send_object_was_deleted
+ *
+ * This subprogram is not needed since there are no objects
+ * deleted by this manager.
+ *
+ */
+
+/*PAGE
+ *
+ * _MPCI_Internal_packets_Send_extract_proxy
+ *
+ * This subprogram is not needed since there are no objects
+ * deleted by this manager.
+ *
+ */
+
+/*PAGE
+ *
+ * _MPCI_Internal_packets_Get_packet
+ *
+ */
+
+MPCI_Internal_packet *_MPCI_Internal_packets_Get_packet ( void )
+{
+ return ( (MPCI_Internal_packet *) _MPCI_Get_packet() );
+}
+
+/* end of file */
diff --git a/cpukit/score/src/object.c b/cpukit/score/src/object.c
new file mode 100644
index 0000000000..56b3dad4a2
--- /dev/null
+++ b/cpukit/score/src/object.c
@@ -0,0 +1,64 @@
+/*
+ * Object Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/object.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/objectmp.h>
+#endif
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/isr.h>
+
+/*PAGE
+ *
+ * _Objects_Handler_initialization
+ *
+ * This routine initializes the object handler.
+ *
+ * Input parameters:
+ * node - local node
+ * maximum_nodes - number of nodes in the system
+ * maximum_global_objects - number of configured global objects
+ *
+ * Output parameters: NONE
+ */
+
+void _Objects_Handler_initialization(
+ uint32_t node,
+ uint32_t maximum_nodes,
+ uint32_t maximum_global_objects
+)
+{
+ if ( node < 1 || node > maximum_nodes )
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ TRUE,
+ INTERNAL_ERROR_INVALID_NODE
+ );
+
+ _Objects_Local_node = node;
+ _Objects_Maximum_nodes = maximum_nodes;
+
+#if defined(RTEMS_MULTIPROCESSING)
+ _Objects_MP_Handler_initialization(
+ node,
+ maximum_nodes,
+ maximum_global_objects
+ );
+#endif
+}
diff --git a/cpukit/score/src/objectallocate.c b/cpukit/score/src/objectallocate.c
new file mode 100644
index 0000000000..4ad0da6756
--- /dev/null
+++ b/cpukit/score/src/objectallocate.c
@@ -0,0 +1,68 @@
+/*
+ * Object Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/object.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/objectmp.h>
+#endif
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/isr.h>
+
+/*PAGE
+ *
+ * _Objects_Allocate
+ *
+ * DESCRIPTION:
+ *
+ * This function allocates a object control block from
+ * the inactive chain of free object control blocks.
+ */
+
+Objects_Control *_Objects_Allocate(
+ Objects_Information *information
+)
+{
+ Objects_Control *the_object =
+ (Objects_Control *) _Chain_Get( &information->Inactive );
+
+ if ( information->auto_extend ) {
+ /*
+ * If the list is empty then we are out of objects and need to
+ * extend information base.
+ */
+
+ if ( !the_object ) {
+ _Objects_Extend_information( information );
+ the_object = (Objects_Control *) _Chain_Get( &information->Inactive );
+ }
+
+ if ( the_object ) {
+ uint32_t block;
+
+ block = _Objects_Get_index( the_object->id ) -
+ _Objects_Get_index( information->minimum_id );
+ block /= information->allocation_size;
+
+ information->inactive_per_block[ block ]--;
+ information->inactive--;
+ }
+ }
+
+ return the_object;
+}
diff --git a/cpukit/score/src/objectallocatebyindex.c b/cpukit/score/src/objectallocatebyindex.c
new file mode 100644
index 0000000000..d3ca6423f1
--- /dev/null
+++ b/cpukit/score/src/objectallocatebyindex.c
@@ -0,0 +1,73 @@
+/*
+ * Object Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/object.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/objectmp.h>
+#endif
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/isr.h>
+
+/*PAGE
+ *
+ * _Objects_Allocate_by_index
+ *
+ * DESCRIPTION:
+ *
+ * This function allocates the object control block
+ * specified by the index from the inactive chain of
+ * free object control blocks.
+ */
+
+Objects_Control *_Objects_Allocate_by_index(
+ Objects_Information *information,
+ uint32_t index,
+ uint32_t sizeof_control
+)
+{
+ Objects_Control *the_object;
+
+ if ( index && information->maximum >= index ) {
+ the_object = information->local_table[ index ];
+ if ( the_object )
+ return NULL;
+
+ /* XXX
+ * This whole section of code needs to be addressed.
+ * + The 0 should be dealt with more properly so we can autoextend.
+ * + The pointer arithmetic is probably too expensive.
+ * + etc.
+ */
+
+ the_object = (Objects_Control *) _Addresses_Add_offset(
+ information->object_blocks[ 0 ],
+ (sizeof_control * (index - 1))
+ );
+ _Chain_Extract( &the_object->Node );
+
+ return the_object;
+ }
+
+ /*
+ * Autoextend will have to be thought out as it applies
+ * to user assigned indices.
+ */
+
+ return NULL;
+}
diff --git a/cpukit/score/src/objectclearname.c b/cpukit/score/src/objectclearname.c
new file mode 100644
index 0000000000..4ba3514f84
--- /dev/null
+++ b/cpukit/score/src/objectclearname.c
@@ -0,0 +1,46 @@
+/*
+ * Object Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/object.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/objectmp.h>
+#endif
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/isr.h>
+
+/*PAGE
+ *
+ * _Objects_Clear_name
+ *
+ * This method clears the specified name so that no caller can do a name to
+ * ID/object lookup past this point.
+ */
+
+void _Objects_Clear_name(
+ void *name,
+ uint32_t length
+)
+{
+ uint32_t index;
+ uint32_t maximum = length / OBJECTS_NAME_ALIGNMENT;
+ uint32_t *name_ptr = (uint32_t *) name;
+
+ for ( index=0 ; index < maximum ; index++ )
+ *name_ptr++ = 0;
+}
diff --git a/cpukit/score/src/objectcomparenameraw.c b/cpukit/score/src/objectcomparenameraw.c
new file mode 100644
index 0000000000..f15db929fe
--- /dev/null
+++ b/cpukit/score/src/objectcomparenameraw.c
@@ -0,0 +1,57 @@
+/*
+ * Object Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/object.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/objectmp.h>
+#endif
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/isr.h>
+
+/*PAGE
+ *
+ * _Objects_Compare_name_raw
+ *
+ * XXX
+ */
+
+boolean _Objects_Compare_name_raw(
+ void *name_1,
+ void *name_2,
+ uint32_t length
+)
+{
+#if 0
+ uint32_t *name_1_p = (uint32_t *) name_1;
+ uint32_t *name_2_p = (uint32_t *) name_2;
+ uint32_t tmp_length = length / OBJECTS_NAME_ALIGNMENT;
+#endif
+
+ if ( name_1 == name_2 )
+ return TRUE;
+ return FALSE;
+
+#if 0
+ while ( tmp_length-- )
+ if ( *name_1_p++ != *name_2_p++ )
+ return FALSE;
+
+ return TRUE;
+#endif
+}
diff --git a/cpukit/score/src/objectcomparenamestring.c b/cpukit/score/src/objectcomparenamestring.c
new file mode 100644
index 0000000000..53dcd25d7f
--- /dev/null
+++ b/cpukit/score/src/objectcomparenamestring.c
@@ -0,0 +1,53 @@
+/*
+ * Object Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-2002.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/object.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/objectmp.h>
+#endif
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/isr.h>
+
+#include <string.h>
+
+/*PAGE
+ *
+ * _Objects_Compare_name_string
+ *
+ * This routine compares the name of an object with the specified string.
+ *
+ * Input parameters:
+ * name_1 - one name
+ * name_2 - other name
+ * length - maximum length to compare
+ *
+ * Output parameters:
+ * returns - TRUE on a match
+ */
+
+boolean _Objects_Compare_name_string(
+ void *name_1,
+ void *name_2,
+ uint32_t length
+)
+{
+ if ( !strncmp( name_1, name_2, length ) )
+ return TRUE;
+ return FALSE;
+}
diff --git a/cpukit/score/src/objectcopynameraw.c b/cpukit/score/src/objectcopynameraw.c
new file mode 100644
index 0000000000..c40328a3e1
--- /dev/null
+++ b/cpukit/score/src/objectcopynameraw.c
@@ -0,0 +1,46 @@
+/*
+ * Object Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/object.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/objectmp.h>
+#endif
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/isr.h>
+
+/*PAGE
+ *
+ * _Objects_Copy_name_raw
+ *
+ * XXX
+ */
+
+void _Objects_Copy_name_raw(
+ void *source,
+ void *destination,
+ uint32_t length
+)
+{
+ uint32_t *source_p = (uint32_t *) source;
+ uint32_t *destination_p = (uint32_t *) destination;
+ uint32_t tmp_length = length / OBJECTS_NAME_ALIGNMENT;
+
+ while ( tmp_length-- )
+ *destination_p++ = *source_p++;
+}
diff --git a/cpukit/score/src/objectcopynamestring.c b/cpukit/score/src/objectcopynamestring.c
new file mode 100644
index 0000000000..3969d09c67
--- /dev/null
+++ b/cpukit/score/src/objectcopynamestring.c
@@ -0,0 +1,48 @@
+/*
+ * Object Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/object.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/objectmp.h>
+#endif
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/isr.h>
+
+/*PAGE
+ *
+ * _Objects_Copy_name_string
+ *
+ * XXX
+ */
+
+void _Objects_Copy_name_string(
+ void *source,
+ void *destination
+)
+{
+ uint8_t *source_p = (uint8_t *) source;
+ uint8_t *destination_p = (uint8_t *) destination;
+
+ *destination_p = '\0';
+ if ( source_p ) {
+ do {
+ *destination_p++ = *source_p;
+ } while ( *source_p++ );
+ }
+}
diff --git a/cpukit/score/src/objectextendinformation.c b/cpukit/score/src/objectextendinformation.c
new file mode 100644
index 0000000000..b8652a4567
--- /dev/null
+++ b/cpukit/score/src/objectextendinformation.c
@@ -0,0 +1,291 @@
+/*
+ * Object Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/object.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/objectmp.h>
+#endif
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/isr.h>
+
+#include <string.h> /* for memcpy() */
+
+/*PAGE
+ *
+ * _Objects_Extend_information
+ *
+ * This routine extends all object information related data structures.
+ *
+ * Input parameters:
+ * information - object information table
+ *
+ * Output parameters: NONE
+ */
+
+void _Objects_Extend_information(
+ Objects_Information *information
+)
+{
+ Objects_Control *the_object;
+ void *name_area;
+ Chain_Control Inactive;
+ uint32_t block_count;
+ uint32_t block;
+ uint32_t index_base;
+ uint32_t minimum_index;
+ uint32_t index;
+
+ /*
+ * Search for a free block of indexes. The block variable ends up set
+ * to block_count + 1 if the table needs to be extended.
+ */
+
+ minimum_index = _Objects_Get_index( information->minimum_id );
+ index_base = minimum_index;
+ block = 0;
+
+ if ( information->maximum < minimum_index )
+ block_count = 0;
+ else {
+ block_count = information->maximum / information->allocation_size;
+
+ for ( ; block < block_count; block++ ) {
+ if ( information->object_blocks[ block ] == NULL )
+ break;
+ else
+ index_base += information->allocation_size;
+ }
+ }
+
+ /*
+ * If the index_base is the maximum we need to grow the tables.
+ */
+
+ if (index_base >= information->maximum ) {
+ ISR_Level level;
+ void **object_blocks;
+ Objects_Name *name_table;
+ uint32_t *inactive_per_block;
+ Objects_Control **local_table;
+ uint32_t maximum;
+ void *old_tables;
+
+ /*
+ * Growing the tables means allocating a new area, doing a copy and
+ * updating the information table.
+ *
+ * If the maximum is minimum we do not have a table to copy. First
+ * time through.
+ *
+ * The allocation has :
+ *
+ * void *objects[block_count];
+ * uint32_t inactive_count[block_count];
+ * Objects_Name *name_table[block_count];
+ * Objects_Control *local_table[maximum];
+ *
+ * This is the order in memory. Watch changing the order. See the memcpy
+ * below.
+ */
+
+ /*
+ * Up the block count and maximum
+ */
+
+ block_count++;
+
+ maximum = information->maximum + information->allocation_size;
+
+ /*
+ * Allocate the tables and break it up.
+ */
+
+ if ( information->auto_extend ) {
+ object_blocks = (void**)
+ _Workspace_Allocate(
+ block_count *
+ (sizeof(void *) + sizeof(uint32_t ) + sizeof(Objects_Name *)) +
+ ((maximum + minimum_index) * sizeof(Objects_Control *))
+ );
+
+ if ( !object_blocks )
+ return;
+ }
+ else {
+ object_blocks = (void**)
+ _Workspace_Allocate_or_fatal_error(
+ block_count *
+ (sizeof(void *) + sizeof(uint32_t ) + sizeof(Objects_Name *)) +
+ ((maximum + minimum_index) * sizeof(Objects_Control *))
+ );
+ }
+
+ /*
+ * Break the block into the various sections.
+ *
+ */
+
+ inactive_per_block = (uint32_t *) _Addresses_Add_offset(
+ object_blocks, block_count * sizeof(void*) );
+ name_table = (Objects_Name *) _Addresses_Add_offset(
+ inactive_per_block, block_count * sizeof(uint32_t ) );
+ local_table = (Objects_Control **) _Addresses_Add_offset(
+ name_table, block_count * sizeof(Objects_Name *) );
+
+ /*
+ * Take the block count down. Saves all the (block_count - 1)
+ * in the copies.
+ */
+
+ block_count--;
+
+ if ( information->maximum > minimum_index ) {
+
+ /*
+ * Copy each section of the table over. This has to be performed as
+ * separate parts as size of each block has changed.
+ */
+
+ memcpy( object_blocks,
+ information->object_blocks,
+ block_count * sizeof(void*) );
+ memcpy( inactive_per_block,
+ information->inactive_per_block,
+ block_count * sizeof(uint32_t ) );
+ memcpy( name_table,
+ information->name_table,
+ block_count * sizeof(Objects_Name *) );
+ memcpy( local_table,
+ information->local_table,
+ (information->maximum + minimum_index) * sizeof(Objects_Control *) );
+ }
+ else {
+
+ /*
+ * Deal with the special case of the 0 to minimum_index
+ */
+ for ( index = 0; index < minimum_index; index++ ) {
+ local_table[ index ] = NULL;
+ }
+ }
+
+ /*
+ * Initialise the new entries in the table.
+ */
+
+ object_blocks[block_count] = NULL;
+ inactive_per_block[block_count] = 0;
+ name_table[block_count] = NULL;
+
+ for ( index=index_base ;
+ index < ( information->allocation_size + index_base );
+ index++ ) {
+ local_table[ index ] = NULL;
+ }
+
+ _ISR_Disable( level );
+
+ old_tables = information->object_blocks;
+
+ information->object_blocks = object_blocks;
+ information->inactive_per_block = inactive_per_block;
+ information->name_table = name_table;
+ information->local_table = local_table;
+ information->maximum = maximum;
+ information->maximum_id = _Objects_Build_id(
+ information->the_api,
+ information->the_class,
+ _Objects_Local_node,
+ information->maximum
+ );
+
+ _ISR_Enable( level );
+
+ if ( old_tables )
+ _Workspace_Free( old_tables );
+
+ block_count++;
+ }
+
+ /*
+ * Allocate the name table, and the objects
+ */
+
+ if ( information->auto_extend ) {
+ information->object_blocks[ block ] =
+ _Workspace_Allocate(
+ (information->allocation_size * information->name_length) +
+ (information->allocation_size * information->size)
+ );
+
+ if ( !information->object_blocks[ block ] )
+ return;
+ }
+ else {
+ information->object_blocks[ block ] =
+ _Workspace_Allocate_or_fatal_error(
+ (information->allocation_size * information->name_length) +
+ (information->allocation_size * information->size)
+ );
+ }
+
+ name_area = (Objects_Name *) _Addresses_Add_offset(
+ information->object_blocks[ block ],
+ (information->allocation_size * information->size)
+ );
+ information->name_table[ block ] = name_area;
+
+ /*
+ * Initialize objects .. add to a local chain first.
+ */
+
+ _Chain_Initialize(
+ &Inactive,
+ information->object_blocks[ block ],
+ information->allocation_size,
+ information->size
+ );
+
+ /*
+ * Move from the local chain, initialise, then append to the inactive chain
+ */
+
+ index = index_base;
+
+ while ( (the_object = (Objects_Control *) _Chain_Get( &Inactive ) ) != NULL ) {
+
+ the_object->id = _Objects_Build_id(
+ information->the_api,
+ information->the_class,
+ _Objects_Local_node,
+ index
+ );
+
+ the_object->name = (void *) name_area;
+
+ name_area = _Addresses_Add_offset( name_area, information->name_length );
+
+ _Chain_Append( &information->Inactive, &the_object->Node );
+
+ index++;
+ }
+
+ information->inactive_per_block[ block ] = information->allocation_size;
+ information->inactive += information->allocation_size;
+}
diff --git a/cpukit/score/src/objectfree.c b/cpukit/score/src/objectfree.c
new file mode 100644
index 0000000000..8d768b2f55
--- /dev/null
+++ b/cpukit/score/src/objectfree.c
@@ -0,0 +1,65 @@
+/*
+ * Object Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/object.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/objectmp.h>
+#endif
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/isr.h>
+
+/*PAGE
+ *
+ * _Objects_Free
+ *
+ * DESCRIPTION:
+ *
+ * This function frees a object control block to the
+ * inactive chain of free object control blocks.
+ */
+
+void _Objects_Free(
+ Objects_Information *information,
+ Objects_Control *the_object
+)
+{
+ uint32_t allocation_size = information->allocation_size;
+
+ _Chain_Append( &information->Inactive, &the_object->Node );
+
+ if ( information->auto_extend ) {
+ uint32_t block;
+
+ block =
+ _Objects_Get_index( the_object->id ) - _Objects_Get_index( information->minimum_id );
+ block /= information->allocation_size;
+
+ information->inactive_per_block[ block ]++;
+ information->inactive++;
+
+ /*
+ * Check if the threshold level has been met of
+ * 1.5 x allocation_size are free.
+ */
+
+ if ( information->inactive > ( allocation_size + ( allocation_size >> 1 ) ) ) {
+ _Objects_Shrink_information( information );
+ }
+ }
+}
diff --git a/cpukit/score/src/objectget.c b/cpukit/score/src/objectget.c
new file mode 100644
index 0000000000..9b524899e5
--- /dev/null
+++ b/cpukit/score/src/objectget.c
@@ -0,0 +1,83 @@
+/*
+ * Object Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/object.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/objectmp.h>
+#endif
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/isr.h>
+
+/*PAGE
+ *
+ * _Objects_Get
+ *
+ * This routine sets the object pointer for the given
+ * object id based on the given object information structure.
+ *
+ * Input parameters:
+ * information - pointer to entry in table for this class
+ * id - object id to search for
+ * location - address of where to store the location
+ *
+ * Output parameters:
+ * returns - address of object if local
+ * location - one of the following:
+ * OBJECTS_ERROR - invalid object ID
+ * OBJECTS_REMOTE - remote object
+ * OBJECTS_LOCAL - local object
+ */
+
+Objects_Control *_Objects_Get(
+ Objects_Information *information,
+ Objects_Id id,
+ Objects_Locations *location
+)
+{
+ Objects_Control *the_object;
+ uint32_t index;
+
+#if defined(RTEMS_MULTIPROCESSING)
+ index = id - information->minimum_id + 1;
+#else
+ /* index = _Objects_Get_index( id ); */
+ index = id & 0x0000ffff;
+ /* This should work but doesn't always :( */
+ /* index = (uint16_t ) id; */
+#endif
+
+ if ( information->maximum >= index ) {
+ _Thread_Disable_dispatch();
+ if ( (the_object = information->local_table[ index ]) != NULL ) {
+ *location = OBJECTS_LOCAL;
+ return the_object;
+ }
+ _Thread_Enable_dispatch();
+ *location = OBJECTS_ERROR;
+ return NULL;
+ }
+ *location = OBJECTS_ERROR;
+
+#if defined(RTEMS_MULTIPROCESSING)
+ _Objects_MP_Is_remote( information, id, location, &the_object );
+ return the_object;
+#else
+ return NULL;
+#endif
+}
diff --git a/cpukit/score/src/objectgetbyindex.c b/cpukit/score/src/objectgetbyindex.c
new file mode 100644
index 0000000000..f83562e753
--- /dev/null
+++ b/cpukit/score/src/objectgetbyindex.c
@@ -0,0 +1,73 @@
+/*
+ * Object Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/object.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/objectmp.h>
+#endif
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/isr.h>
+
+/*PAGE
+ *
+ * _Objects_Get_by_index
+ *
+ * This routine sets the object pointer for the given
+ * object id based on the given object information structure.
+ *
+ * Input parameters:
+ * information - pointer to entry in table for this class
+ * index - object index to check for
+ * location - address of where to store the location
+ *
+ * Output parameters:
+ * returns - address of object if local
+ * location - one of the following:
+ * OBJECTS_ERROR - invalid object ID
+ * OBJECTS_REMOTE - remote object
+ * OBJECTS_LOCAL - local object
+ */
+
+Objects_Control *_Objects_Get_by_index(
+ Objects_Information *information,
+ uint32_t index,
+ Objects_Locations *location
+)
+{
+ Objects_Control *the_object;
+
+ if ( information->maximum >= index ) {
+ _Thread_Disable_dispatch();
+ the_object = information->local_table[ index ];
+ if ( the_object ) {
+ *location = OBJECTS_LOCAL;
+ return( the_object );
+ }
+ _Thread_Enable_dispatch();
+ *location = OBJECTS_ERROR;
+ return( NULL );
+ }
+
+ /*
+ * With just an index, you can't access a remote object.
+ */
+
+ *location = OBJECTS_ERROR;
+ return NULL;
+}
diff --git a/cpukit/score/src/objectgetisr.c b/cpukit/score/src/objectgetisr.c
new file mode 100644
index 0000000000..2f25025bcf
--- /dev/null
+++ b/cpukit/score/src/objectgetisr.c
@@ -0,0 +1,89 @@
+/*
+ * Object Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/object.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/objectmp.h>
+#endif
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/isr.h>
+
+/*PAGE
+ *
+ * _Objects_Get_isr_disable
+ *
+ * This routine sets the object pointer for the given
+ * object id based on the given object information structure.
+ *
+ * Input parameters:
+ * information - pointer to entry in table for this class
+ * id - object id to search for
+ * location - address of where to store the location
+ * level - pointer to previous interrupt level
+ *
+ * Output parameters:
+ * returns - address of object if local
+ * location - one of the following:
+ * OBJECTS_ERROR - invalid object ID
+ * OBJECTS_REMOTE - remote object
+ * OBJECTS_LOCAL - local object
+ * *level - previous interrupt level
+ */
+
+Objects_Control *_Objects_Get_isr_disable(
+ Objects_Information *information,
+ Objects_Id id,
+ Objects_Locations *location,
+ ISR_Level *level_p
+)
+{
+ Objects_Control *the_object;
+ uint32_t index;
+ ISR_Level level;
+
+#if defined(RTEMS_MULTIPROCESSING)
+ index = id - information->minimum_id + 1;
+#else
+ /* index = _Objects_Get_index( id ); */
+ index = id & 0x0000ffff;
+ /* This should work but doesn't always :( */
+ /* index = (uint16_t ) id; */
+#endif
+
+ _ISR_Disable( level );
+ if ( information->maximum >= index ) {
+ if ( (the_object = information->local_table[ index ]) != NULL ) {
+ *location = OBJECTS_LOCAL;
+ *level_p = level;
+ return the_object;
+ }
+ _ISR_Enable( level );
+ *location = OBJECTS_ERROR;
+ return NULL;
+ }
+ _ISR_Enable( level );
+ *location = OBJECTS_ERROR;
+
+#if defined(RTEMS_MULTIPROCESSING)
+ _Objects_MP_Is_remote( information, id, location, &the_object );
+ return the_object;
+#else
+ return NULL;
+#endif
+}
diff --git a/cpukit/score/src/objectgetnext.c b/cpukit/score/src/objectgetnext.c
new file mode 100644
index 0000000000..383d2735c9
--- /dev/null
+++ b/cpukit/score/src/objectgetnext.c
@@ -0,0 +1,90 @@
+/*
+ * Object Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/object.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/objectmp.h>
+#endif
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/isr.h>
+
+/*PAGE
+ *
+ * _Objects_Get_next
+ *
+ * Like _Objects_Get, but considers the 'id' as a "hint" and
+ * finds next valid one after that point.
+ * Mostly used for monitor and debug traversal of an object.
+ *
+ * Input parameters:
+ * information - pointer to entry in table for this class
+ * id - object id to search for
+ * location - address of where to store the location
+ * next_id - address to store next id to try
+ *
+ * Output parameters:
+ * returns - address of object if local
+ * location - one of the following:
+ * OBJECTS_ERROR - invalid object ID
+ * OBJECTS_REMOTE - remote object
+ * OBJECTS_LOCAL - local object
+ * next_id - will contain a reasonable "next" id to continue traversal
+ *
+ * NOTE:
+ * assumes can add '1' to an id to get to next index.
+ */
+
+Objects_Control *
+_Objects_Get_next(
+ Objects_Information *information,
+ Objects_Id id,
+ Objects_Locations *location_p,
+ Objects_Id *next_id_p
+)
+{
+ Objects_Control *object;
+ Objects_Id next_id;
+
+ if (_Objects_Get_index(id) == OBJECTS_ID_INITIAL_INDEX)
+ next_id = information->minimum_id;
+ else
+ next_id = id;
+
+ do {
+ /* walked off end of list? */
+ if (_Objects_Get_index(next_id) > information->maximum)
+ {
+ *location_p = OBJECTS_ERROR;
+ goto final;
+ }
+
+ /* try to grab one */
+ object = _Objects_Get(information, next_id, location_p);
+
+ next_id++;
+
+ } while (*location_p != OBJECTS_LOCAL);
+
+ *next_id_p = next_id;
+ return object;
+
+final:
+ *next_id_p = OBJECTS_ID_FINAL;
+ return 0;
+}
diff --git a/cpukit/score/src/objectgetnoprotection.c b/cpukit/score/src/objectgetnoprotection.c
new file mode 100644
index 0000000000..667eae291c
--- /dev/null
+++ b/cpukit/score/src/objectgetnoprotection.c
@@ -0,0 +1,83 @@
+/*
+ * Object Handler -- Object Get
+ *
+ *
+ * COPYRIGHT (c) 1989-2002.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/object.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/objectmp.h>
+#endif
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/isr.h>
+
+/*PAGE
+ *
+ * _Objects_Get_no_protection
+ *
+ * This routine sets the object pointer for the given
+ * object id based on the given object information structure.
+ *
+ * Input parameters:
+ * information - pointer to entry in table for this class
+ * id - object id to search for
+ * location - address of where to store the location
+ *
+ * Output parameters:
+ * returns - address of object if local
+ * location - one of the following:
+ * OBJECTS_ERROR - invalid object ID
+ * OBJECTS_REMOTE - remote object
+ * OBJECTS_LOCAL - local object
+ */
+
+Objects_Control *_Objects_Get_no_protection(
+ Objects_Information *information,
+ Objects_Id id,
+ Objects_Locations *location
+)
+{
+ Objects_Control *the_object;
+ uint32_t index;
+
+#if defined(RTEMS_MULTIPROCESSING)
+ index = id - information->minimum_id + 1;
+#else
+ /* index = _Objects_Get_index( id ); */
+ index = id & 0x0000ffff;
+ /* This should work but doesn't always :( */
+ /* index = (uint16_t ) id; */
+#endif
+
+ if ( information->maximum >= index ) {
+ if ( (the_object = information->local_table[ index ]) != NULL ) {
+ *location = OBJECTS_LOCAL;
+ return the_object;
+ }
+ *location = OBJECTS_ERROR;
+ return NULL;
+ }
+ *location = OBJECTS_ERROR;
+
+/*
+ * Not supported for multiprocessing
+ */
+#if 0 && defined(RTEMS_MULTIPROCESSING)
+ _Objects_MP_Is_remote( information, id, location, &the_object );
+ return the_object;
+#endif
+ return NULL;
+}
diff --git a/cpukit/score/src/objectidtoname.c b/cpukit/score/src/objectidtoname.c
new file mode 100644
index 0000000000..41c20815c2
--- /dev/null
+++ b/cpukit/score/src/objectidtoname.c
@@ -0,0 +1,67 @@
+/*
+ * Obtain Object Name Given ID
+ *
+ *
+ * COPYRIGHT (c) 1989-2003.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/object.h>
+
+/*PAGE
+ *
+ * _Objects_Id_to_name
+ *
+ * DESCRIPTION:
+ *
+ * This routine returns the name associated with the given ID.
+ *
+ * INPUT:
+ *
+ * id - id of object to lookup name
+ * name - pointer to location in which to store name
+ *
+ */
+
+
+Objects_Name_or_id_lookup_errors _Objects_Id_to_name (
+ Objects_Id id,
+ Objects_Name *name
+)
+{
+ uint32_t the_api;
+ uint32_t the_class;
+ Objects_Information *information;
+ Objects_Control *the_object = (Objects_Control *) 0;
+ Objects_Locations ignored_location;
+
+ if ( !name )
+ return OBJECTS_INVALID_NAME;
+
+ the_api = _Objects_Get_API( id );
+ if ( the_api && the_api > OBJECTS_APIS_LAST )
+ return OBJECTS_INVALID_ID;
+
+ the_class = _Objects_Get_class( id );
+
+ information = _Objects_Information_table[ the_api ][ the_class ];
+ if ( !information )
+ return OBJECTS_INVALID_ID;
+
+ if ( information->is_string )
+ return OBJECTS_INVALID_ID;
+
+ the_object = _Objects_Get( information, id, &ignored_location );
+ if (!the_object)
+ return OBJECTS_INVALID_ID;
+
+ *name = the_object->name;
+ return OBJECTS_NAME_OR_ID_LOOKUP_SUCCESSFUL;
+}
diff --git a/cpukit/score/src/objectinitializeinformation.c b/cpukit/score/src/objectinitializeinformation.c
new file mode 100644
index 0000000000..88555a2944
--- /dev/null
+++ b/cpukit/score/src/objectinitializeinformation.c
@@ -0,0 +1,177 @@
+/*
+ * Object Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/object.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/objectmp.h>
+#endif
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/isr.h>
+
+/*PAGE
+ *
+ * _Objects_Initialize_information
+ *
+ * This routine initializes all object information related data structures.
+ *
+ * Input parameters:
+ * information - object information table
+ * maximum - maximum objects of this class
+ * size - size of this object's control block
+ * is_string - TRUE if names for this object are strings
+ * maximum_name_length - maximum length of each object's name
+ * When multiprocessing is configured,
+ * supports_global - TRUE if this is a global object class
+ * extract_callout - pointer to threadq extract callout if MP
+ *
+ * Output parameters: NONE
+ */
+
+void _Objects_Initialize_information(
+ Objects_Information *information,
+ Objects_APIs the_api,
+ uint32_t the_class,
+ uint32_t maximum,
+ uint32_t size,
+ boolean is_string,
+ uint32_t maximum_name_length
+#if defined(RTEMS_MULTIPROCESSING)
+ ,
+ boolean supports_global,
+ Objects_Thread_queue_Extract_callout *extract
+#endif
+)
+{
+ static Objects_Control *null_local_table = NULL;
+ uint32_t minimum_index;
+ uint32_t name_length;
+#if defined(RTEMS_MULTIPROCESSING)
+ uint32_t index;
+#endif
+
+ information->the_api = the_api;
+ information->the_class = the_class;
+ information->is_string = is_string;
+
+ information->local_table = 0;
+ information->name_table = 0;
+ information->inactive_per_block = 0;
+ information->object_blocks = 0;
+
+ information->inactive = 0;
+
+ /*
+ * Set the entry in the object information table.
+ */
+
+ _Objects_Information_table[ the_api ][ the_class ] = information;
+
+ /*
+ * Set the size of the object
+ */
+
+ information->size = size;
+
+ /*
+ * Are we operating in unlimited, or auto-extend mode
+ */
+
+ information->auto_extend = (maximum & OBJECTS_UNLIMITED_OBJECTS) ? TRUE : FALSE;
+ maximum &= ~OBJECTS_UNLIMITED_OBJECTS;
+
+ /*
+ * The allocation unit is the maximum value
+ */
+
+ information->allocation_size = maximum;
+
+ /*
+ * Provide a null local table entry for the case of any empty table.
+ */
+
+ information->local_table = &null_local_table;
+
+ /*
+ * Calculate minimum and maximum Id's
+ */
+
+ if ( maximum == 0 ) minimum_index = 0;
+ else minimum_index = 1;
+
+ information->minimum_id =
+ _Objects_Build_id( the_api, the_class, _Objects_Local_node, minimum_index );
+
+ /*
+ * Calculate the maximum name length
+ */
+
+ name_length = maximum_name_length;
+
+ if ( name_length & (OBJECTS_NAME_ALIGNMENT-1) )
+ name_length = (name_length + OBJECTS_NAME_ALIGNMENT) &
+ ~(OBJECTS_NAME_ALIGNMENT-1);
+
+ information->name_length = name_length;
+
+ _Chain_Initialize_empty( &information->Inactive );
+
+ /*
+ * Initialize objects .. if there are any
+ */
+
+ if ( maximum ) {
+
+ /*
+ * Reset the maximum value. It will be updated when the information is
+ * extended.
+ */
+
+ information->maximum = 0;
+
+ /*
+ * Always have the maximum size available so the current performance
+ * figures are create are met. If the user moves past the maximum
+ * number then a performance hit is taken.
+ */
+
+ _Objects_Extend_information( information );
+
+ }
+
+ /*
+ * Take care of multiprocessing
+ */
+
+#if defined(RTEMS_MULTIPROCESSING)
+ information->extract = extract;
+
+ if ( supports_global == TRUE && _System_state_Is_multiprocessing ) {
+
+ information->global_table =
+ (Chain_Control *) _Workspace_Allocate_or_fatal_error(
+ (_Objects_Maximum_nodes + 1) * sizeof(Chain_Control)
+ );
+
+ for ( index=1; index <= _Objects_Maximum_nodes ; index++ )
+ _Chain_Initialize_empty( &information->global_table[ index ] );
+ }
+ else
+ information->global_table = NULL;
+#endif
+}
diff --git a/cpukit/score/src/objectmp.c b/cpukit/score/src/objectmp.c
new file mode 100644
index 0000000000..15a358d51b
--- /dev/null
+++ b/cpukit/score/src/objectmp.c
@@ -0,0 +1,276 @@
+/*
+ * Multiprocessing Support for the Object Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/thread.h>
+
+/*PAGE
+ *
+ * _Objects_MP_Handler_initialization
+ *
+ */
+
+void _Objects_MP_Handler_initialization (
+ uint32_t node,
+ uint32_t maximum_nodes,
+ uint32_t maximum_global_objects
+)
+{
+ _Objects_MP_Maximum_global_objects = maximum_global_objects;
+
+ if ( maximum_global_objects == 0 ) {
+ _Chain_Initialize_empty( &_Objects_MP_Inactive_global_objects );
+ return;
+ }
+
+ _Chain_Initialize(
+ &_Objects_MP_Inactive_global_objects,
+ _Workspace_Allocate_or_fatal_error(
+ maximum_global_objects * sizeof( Objects_MP_Control )
+ ),
+ maximum_global_objects,
+ sizeof( Objects_MP_Control )
+ );
+
+}
+
+/*PAGE
+ *
+ * _Objects_MP_Open
+ *
+ */
+
+void _Objects_MP_Open (
+ Objects_Information *information,
+ Objects_MP_Control *the_global_object,
+ uint32_t the_name, /* XXX -- wrong for variable */
+ Objects_Id the_id
+)
+{
+ the_global_object->Object.id = the_id;
+ the_global_object->name = the_name;
+
+ _Chain_Prepend(
+ &information->global_table[ _Objects_Get_node( the_id ) ],
+ &the_global_object->Object.Node
+ );
+
+}
+
+/*PAGE
+ *
+ * _Objects_MP_Allocate_and_open
+ *
+ */
+
+boolean _Objects_MP_Allocate_and_open (
+ Objects_Information *information,
+ uint32_t the_name, /* XXX -- wrong for variable */
+ Objects_Id the_id,
+ boolean is_fatal_error
+)
+{
+ Objects_MP_Control *the_global_object;
+
+ the_global_object = _Objects_MP_Allocate_global_object();
+ if ( _Objects_MP_Is_null_global_object( the_global_object ) ) {
+
+ if ( is_fatal_error == FALSE )
+ return FALSE;
+
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ TRUE,
+ INTERNAL_ERROR_OUT_OF_GLOBAL_OBJECTS
+ );
+
+ }
+
+ _Objects_MP_Open( information, the_global_object, the_name, the_id );
+
+ return TRUE;
+}
+
+/*PAGE
+ *
+ * _Objects_MP_Close
+ *
+ */
+
+void _Objects_MP_Close (
+ Objects_Information *information,
+ Objects_Id the_id
+)
+{
+ Chain_Control *the_chain;
+ Chain_Node *the_node;
+ Objects_MP_Control *the_object;
+
+ the_chain = &information->global_table[ _Objects_Get_node( the_id ) ];
+
+ for ( the_node = the_chain->first ;
+ !_Chain_Is_tail( the_chain, the_node ) ;
+ the_node = the_node->next ) {
+
+ the_object = (Objects_MP_Control *) the_node;
+
+ if ( _Objects_Are_ids_equal( the_object->Object.id, the_id ) ) {
+
+ _Chain_Extract( the_node );
+ _Objects_MP_Free_global_object( the_object );
+ return;
+ }
+
+ }
+
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ TRUE,
+ INTERNAL_ERROR_INVALID_GLOBAL_ID
+ );
+}
+
+/*PAGE
+ *
+ * _Objects_MP_Global_name_search
+ *
+ */
+
+Objects_Name_or_id_lookup_errors _Objects_MP_Global_name_search (
+ Objects_Information *information,
+ Objects_Name the_name,
+ uint32_t nodes_to_search,
+ Objects_Id *the_id
+)
+{
+ uint32_t low_node;
+ uint32_t high_node;
+ uint32_t node_index;
+ Chain_Control *the_chain;
+ Chain_Node *the_node;
+ Objects_MP_Control *the_object;
+ uint32_t name_to_use;
+
+ name_to_use = *(uint32_t *)the_name; /* XXX only fixed length names */
+
+ if ( nodes_to_search > _Objects_Maximum_nodes )
+ return OBJECTS_INVALID_NODE;
+
+ if ( information->global_table == NULL )
+ return OBJECTS_INVALID_NAME;
+
+ if ( nodes_to_search == OBJECTS_SEARCH_ALL_NODES ||
+ nodes_to_search == OBJECTS_SEARCH_OTHER_NODES ) {
+ low_node = 1;
+ high_node = _Objects_Maximum_nodes;
+ } else {
+ low_node =
+ high_node = nodes_to_search;
+ }
+
+ _Thread_Disable_dispatch();
+
+ for ( node_index = low_node ; node_index <= high_node ; node_index++ ) {
+
+ /*
+ * NOTE: The local node was search (if necessary) by
+ * _Objects_Name_to_id before this was invoked.
+ */
+
+ if ( !_Objects_Is_local_node( node_index ) ) {
+ the_chain = &information->global_table[ node_index ];
+
+ for ( the_node = the_chain->first ;
+ !_Chain_Is_tail( the_chain, the_node ) ;
+ the_node = the_node->next ) {
+
+ the_object = (Objects_MP_Control *) the_node;
+
+ if ( the_object->name == name_to_use ) {
+ *the_id = the_object->Object.id;
+ _Thread_Enable_dispatch();
+ return OBJECTS_NAME_OR_ID_LOOKUP_SUCCESSFUL;
+ }
+ }
+ }
+ }
+
+ _Thread_Enable_dispatch();
+ return OBJECTS_INVALID_NAME;
+}
+
+/*PAGE
+ *
+ * _Objects_MP_Is_remote
+ *
+ */
+
+void _Objects_MP_Is_remote (
+ Objects_Information *information,
+ Objects_Id the_id,
+ Objects_Locations *location,
+ Objects_Control **the_object
+)
+{
+ uint32_t node;
+ Chain_Control *the_chain;
+ Chain_Node *the_node;
+ Objects_MP_Control *the_global_object;
+
+ node = _Objects_Get_node( the_id );
+
+ /*
+ * NOTE: The local node was search (if necessary) by
+ * _Objects_Name_to_id before this was invoked.
+ *
+ * The NODE field of an object id cannot be 0
+ * because 0 is an invalid node number.
+ */
+
+ if ( node == 0 ||
+ _Objects_Is_local_node( node ) ||
+ node > _Objects_Maximum_nodes ||
+ information->global_table == NULL ) {
+
+ *location = OBJECTS_ERROR;
+ *the_object = NULL;
+ return;
+ }
+
+ _Thread_Disable_dispatch();
+
+ the_chain = &information->global_table[ node ];
+
+ for ( the_node = the_chain->first ;
+ !_Chain_Is_tail( the_chain, the_node ) ;
+ the_node = the_node->next ) {
+
+ the_global_object = (Objects_MP_Control *) the_node;
+
+ if ( _Objects_Are_ids_equal( the_global_object->Object.id, the_id ) ) {
+ _Thread_Unnest_dispatch();
+ *location = OBJECTS_REMOTE;
+ *the_object = (Objects_Control *) the_global_object;
+ return;
+ }
+ }
+
+ _Thread_Enable_dispatch();
+ *location = OBJECTS_ERROR;
+ *the_object = NULL;
+
+}
diff --git a/cpukit/score/src/objectnametoid.c b/cpukit/score/src/objectnametoid.c
new file mode 100644
index 0000000000..c5a1a70a9d
--- /dev/null
+++ b/cpukit/score/src/objectnametoid.c
@@ -0,0 +1,98 @@
+/*
+ * Object Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/object.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/objectmp.h>
+#endif
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/isr.h>
+
+/*PAGE
+ *
+ * _Objects_Name_to_id
+ *
+ * These kernel routines search the object table(s) for the given
+ * object name and returns the associated object id.
+ *
+ * Input parameters:
+ * information - object information
+ * name - user defined object name
+ * node - node indentifier (0 indicates any node)
+ * id - address of return ID
+ *
+ * Output parameters:
+ * id - object id
+ * OBJECTS_NAME_OR_ID_LOOKUP_SUCCESSFUL - if successful
+ * error code - if unsuccessful
+ */
+
+Objects_Name_or_id_lookup_errors _Objects_Name_to_id(
+ Objects_Information *information,
+ Objects_Name name,
+ uint32_t node,
+ Objects_Id *id
+)
+{
+ boolean search_local_node;
+ Objects_Control *the_object;
+ uint32_t index;
+ uint32_t name_length;
+ Objects_Name_comparators compare_them;
+
+ if ( !id )
+ return OBJECTS_INVALID_ADDRESS;
+
+ if ( name == 0 )
+ return OBJECTS_INVALID_NAME;
+
+ search_local_node = FALSE;
+
+ if ( information->maximum != 0 &&
+ (node == OBJECTS_SEARCH_ALL_NODES || node == OBJECTS_SEARCH_LOCAL_NODE ||
+ _Objects_Is_local_node( node ) ) )
+ search_local_node = TRUE;
+
+ if ( search_local_node ) {
+ name_length = information->name_length;
+
+ if ( information->is_string ) compare_them = _Objects_Compare_name_string;
+ else compare_them = _Objects_Compare_name_raw;
+
+ for ( index = 1; index <= information->maximum; index++ ) {
+ the_object = information->local_table[ index ];
+ if ( !the_object || !the_object->name )
+ continue;
+
+ if ( (*compare_them)( name, the_object->name, name_length ) ) {
+ *id = the_object->id;
+ return OBJECTS_NAME_OR_ID_LOOKUP_SUCCESSFUL;
+ }
+ }
+ }
+
+ if ( _Objects_Is_local_node( node ) || node == OBJECTS_SEARCH_LOCAL_NODE )
+ return OBJECTS_INVALID_NAME;
+
+#if defined(RTEMS_MULTIPROCESSING)
+ return ( _Objects_MP_Global_name_search( information, name, node, id ) );
+#else
+ return OBJECTS_INVALID_NAME;
+#endif
+}
diff --git a/cpukit/score/src/objectshrinkinformation.c b/cpukit/score/src/objectshrinkinformation.c
new file mode 100644
index 0000000000..d71d1348c3
--- /dev/null
+++ b/cpukit/score/src/objectshrinkinformation.c
@@ -0,0 +1,115 @@
+/*
+ * Object Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/address.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/object.h>
+#if defined(RTEMS_MULTIPROCESSING)
+#include <rtems/score/objectmp.h>
+#endif
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/isr.h>
+
+/*PAGE
+ *
+ * _Objects_Shrink_information
+ *
+ * This routine shrinks object information related data structures.
+ * The object's name and object space are released. The local_table
+ * etc block does not shrink. The InActive list needs to be scanned
+ * to find the objects are remove them.
+ * Input parameters:
+ * information - object information table
+ * the_block - the block to remove
+ *
+ * Output parameters: NONE
+ */
+
+void _Objects_Shrink_information(
+ Objects_Information *information
+)
+{
+ Objects_Control *the_object;
+ Objects_Control *extract_me;
+ uint32_t block_count;
+ uint32_t block;
+ uint32_t index_base;
+ uint32_t index;
+
+ /*
+ * Search the list to find block or chunnk with all objects inactive.
+ */
+
+ index_base = _Objects_Get_index( information->minimum_id );
+ block_count = ( information->maximum - index_base ) / information->allocation_size;
+
+ for ( block = 0; block < block_count; block++ ) {
+ if ( information->inactive_per_block[ block ] == information->allocation_size ) {
+
+ /*
+ * XXX - Not to sure how to use a chain where you need to iterate and
+ * and remove elements.
+ */
+
+ the_object = (Objects_Control *) information->Inactive.first;
+
+ /*
+ * Assume the Inactive chain is never empty at this point
+ */
+
+ do {
+ index = _Objects_Get_index( the_object->id );
+
+ if ((index >= index_base) &&
+ (index < (index_base + information->allocation_size))) {
+
+ /*
+ * Get the next node before the node is extracted
+ */
+
+ extract_me = the_object;
+
+ if ( !_Chain_Is_last( &the_object->Node ) )
+ the_object = (Objects_Control *) the_object->Node.next;
+ else
+ the_object = NULL;
+
+ _Chain_Extract( &extract_me->Node );
+ }
+ else {
+ the_object = (Objects_Control *) the_object->Node.next;
+ }
+ }
+ while ( the_object && !_Chain_Is_last( &the_object->Node ) );
+
+ /*
+ * Free the memory and reset the structures in the object' information
+ */
+
+ _Workspace_Free( information->object_blocks[ block ] );
+ information->name_table[ block ] = NULL;
+ information->object_blocks[ block ] = NULL;
+ information->inactive_per_block[ block ] = 0;
+
+ information->inactive -= information->allocation_size;
+
+ return;
+ }
+
+ index_base += information->allocation_size;
+ }
+}
diff --git a/cpukit/score/src/thread.c b/cpukit/score/src/thread.c
new file mode 100644
index 0000000000..9b3a2c35f9
--- /dev/null
+++ b/cpukit/score/src/thread.c
@@ -0,0 +1,107 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _Thread_Handler_initialization
+ *
+ * This routine initializes all thread manager related data structures.
+ *
+ * Input parameters:
+ * ticks_per_timeslice - clock ticks per quantum
+ * maximum_proxies - number of proxies to initialize
+ *
+ * Output parameters: NONE
+ */
+
+void _Thread_Handler_initialization(
+ uint32_t ticks_per_timeslice,
+ uint32_t maximum_extensions,
+ uint32_t maximum_proxies
+)
+{
+ uint32_t index;
+
+ /*
+ * BOTH stacks hooks must be set or both must be NULL.
+ * Do not allow mixture.
+ */
+
+ if ( !( ( _CPU_Table.stack_allocate_hook == 0 )
+ == ( _CPU_Table.stack_free_hook == 0 ) ) )
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ TRUE,
+ INTERNAL_ERROR_BAD_STACK_HOOK
+ );
+
+ _Context_Switch_necessary = FALSE;
+ _Thread_Executing = NULL;
+ _Thread_Heir = NULL;
+#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+ _Thread_Allocated_fp = NULL;
+#endif
+
+ _Thread_Do_post_task_switch_extension = 0;
+
+ _Thread_Maximum_extensions = maximum_extensions;
+
+ _Thread_Ticks_per_timeslice = ticks_per_timeslice;
+
+ _Thread_Ready_chain = (Chain_Control *) _Workspace_Allocate_or_fatal_error(
+ (PRIORITY_MAXIMUM + 1) * sizeof(Chain_Control)
+ );
+
+ for ( index=0; index <= PRIORITY_MAXIMUM ; index++ )
+ _Chain_Initialize_empty( &_Thread_Ready_chain[ index ] );
+
+#if defined(RTEMS_MULTIPROCESSING)
+ _Thread_MP_Handler_initialization( maximum_proxies );
+#endif
+
+ /*
+ * Initialize this class of objects.
+ */
+
+ _Objects_Initialize_information(
+ &_Thread_Internal_information,
+ OBJECTS_INTERNAL_API,
+ OBJECTS_INTERNAL_THREADS,
+ ( _System_state_Is_multiprocessing ) ? 2 : 1,
+ sizeof( Thread_Control ),
+ /* size of this object's control block */
+ TRUE, /* TRUE if names for this object are strings */
+ 8 /* maximum length of each object's name */
+#if defined(RTEMS_MULTIPROCESSING)
+ ,
+ FALSE, /* TRUE if this is a global object class */
+ NULL /* Proxy extraction support callout */
+#endif
+ );
+
+}
diff --git a/cpukit/score/src/threadchangepriority.c b/cpukit/score/src/threadchangepriority.c
new file mode 100644
index 0000000000..eda2cd7dfa
--- /dev/null
+++ b/cpukit/score/src/threadchangepriority.c
@@ -0,0 +1,113 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _Thread_Change_priority
+ *
+ * This kernel routine changes the priority of the thread. The
+ * thread chain is adjusted if necessary.
+ *
+ * Input parameters:
+ * the_thread - pointer to thread control block
+ * new_priority - ultimate priority
+ * prepend_it - TRUE if the thread should be prepended to the chain
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY:
+ * ready chain
+ * select heir
+ */
+
+void _Thread_Change_priority(
+ Thread_Control *the_thread,
+ Priority_Control new_priority,
+ boolean prepend_it
+)
+{
+ ISR_Level level;
+ /* boolean do_prepend = FALSE; */
+
+ /*
+ * If this is a case where prepending the task to its priority is
+ * potentially desired, then we need to consider whether to do it.
+ * This usually occurs when a task lowers its priority implcitly as
+ * the result of losing inherited priority. Normal explicit priority
+ * change calls (e.g. rtems_task_set_priority) should always do an
+ * append not a prepend.
+ */
+
+ /*
+ * Techically, the prepend should conditional on the thread lowering
+ * its priority but that does allow cxd2004 of the acvc 2.0.1 to
+ * pass with rtems 4.0.0. This should change when gnat redoes its
+ * priority scheme.
+ */
+/*
+ if ( prepend_it &&
+ _Thread_Is_executing( the_thread ) &&
+ new_priority >= the_thread->current_priority )
+ prepend_it = TRUE;
+*/
+
+ _Thread_Set_transient( the_thread );
+
+ if ( the_thread->current_priority != new_priority )
+ _Thread_Set_priority( the_thread, new_priority );
+
+ _ISR_Disable( level );
+
+ the_thread->current_state =
+ _States_Clear( STATES_TRANSIENT, the_thread->current_state );
+
+ if ( ! _States_Is_ready( the_thread->current_state ) ) {
+ /*
+ * XXX If a task is to be reordered while blocked on a priority
+ * XXX priority ordered thread queue, then this is where that
+ * XXX should occur.
+ */
+ _ISR_Enable( level );
+ return;
+ }
+
+ _Priority_Add_to_bit_map( &the_thread->Priority_map );
+ if ( prepend_it )
+ _Chain_Prepend_unprotected( the_thread->ready, &the_thread->Object.Node );
+ else
+ _Chain_Append_unprotected( the_thread->ready, &the_thread->Object.Node );
+
+ _ISR_Flash( level );
+
+ _Thread_Calculate_heir();
+
+ if ( !_Thread_Is_executing_also_the_heir() &&
+ _Thread_Executing->is_preemptible )
+ _Context_Switch_necessary = TRUE;
+ _ISR_Enable( level );
+}
diff --git a/cpukit/score/src/threadclearstate.c b/cpukit/score/src/threadclearstate.c
new file mode 100644
index 0000000000..9833805b8c
--- /dev/null
+++ b/cpukit/score/src/threadclearstate.c
@@ -0,0 +1,81 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _Thread_Clear_state
+ *
+ * This kernel routine clears the appropriate states in the
+ * requested thread. The thread ready chain is adjusted if
+ * necessary and the Heir thread is set accordingly.
+ *
+ * Input parameters:
+ * the_thread - pointer to thread control block
+ * state - state set to clear
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY:
+ * priority map
+ * select heir
+ */
+
+
+void _Thread_Clear_state(
+ Thread_Control *the_thread,
+ States_Control state
+)
+{
+ ISR_Level level;
+ States_Control current_state;
+
+ _ISR_Disable( level );
+ current_state = the_thread->current_state;
+
+ if ( current_state & state ) {
+ current_state =
+ the_thread->current_state = _States_Clear( state, current_state );
+
+ if ( _States_Is_ready( current_state ) ) {
+
+ _Priority_Add_to_bit_map( &the_thread->Priority_map );
+
+ _Chain_Append_unprotected(the_thread->ready, &the_thread->Object.Node);
+
+ _ISR_Flash( level );
+
+ if ( the_thread->current_priority < _Thread_Heir->current_priority ) {
+ _Thread_Heir = the_thread;
+ if ( _Thread_Executing->is_preemptible ||
+ the_thread->current_priority == 0 )
+ _Context_Switch_necessary = TRUE;
+ }
+ }
+ }
+ _ISR_Enable( level );
+}
diff --git a/cpukit/score/src/threadclose.c b/cpukit/score/src/threadclose.c
new file mode 100644
index 0000000000..750a4d8b8a
--- /dev/null
+++ b/cpukit/score/src/threadclose.c
@@ -0,0 +1,73 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*
+ * _Thread_Close
+ *
+ * DESCRIPTION:
+ *
+ * This routine frees all memory associated with the specified
+ * thread and removes it from the local object table so no further
+ * operations on this thread are allowed.
+ */
+
+void _Thread_Close(
+ Objects_Information *information,
+ Thread_Control *the_thread
+)
+{
+ _User_extensions_Thread_delete( the_thread );
+
+ _Objects_Close( information, &the_thread->Object );
+
+ _Thread_Set_state( the_thread, STATES_TRANSIENT );
+
+ if ( !_Thread_queue_Extract_with_proxy( the_thread ) ) {
+ if ( _Watchdog_Is_active( &the_thread->Timer ) )
+ (void) _Watchdog_Remove( &the_thread->Timer );
+ }
+
+#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+#if ( CPU_USE_DEFERRED_FP_SWITCH == TRUE )
+ if ( _Thread_Is_allocated_fp( the_thread ) )
+ _Thread_Deallocate_fp();
+#endif
+ the_thread->fp_context = NULL;
+
+ if ( the_thread->Start.fp_context )
+ (void) _Workspace_Free( the_thread->Start.fp_context );
+#endif
+
+ _Thread_Stack_Free( the_thread );
+
+ if ( the_thread->extensions )
+ (void) _Workspace_Free( the_thread->extensions );
+
+ the_thread->Start.stack = NULL;
+ the_thread->extensions = NULL;
+}
diff --git a/cpukit/score/src/threadcreateidle.c b/cpukit/score/src/threadcreateidle.c
new file mode 100644
index 0000000000..fdfb24acf4
--- /dev/null
+++ b/cpukit/score/src/threadcreateidle.c
@@ -0,0 +1,96 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _Thread_Create_idle
+ */
+
+const char *_Thread_Idle_name = "IDLE";
+
+void _Thread_Create_idle( void )
+{
+ void *idle;
+ uint32_t idle_task_stack_size;
+
+ /*
+ * The entire workspace is zeroed during its initialization. Thus, all
+ * fields not explicitly assigned were explicitly zeroed by
+ * _Workspace_Initialization.
+ */
+
+ _Thread_Idle = _Thread_Internal_allocate();
+
+ /*
+ * Initialize the IDLE task.
+ */
+
+#if (CPU_PROVIDES_IDLE_THREAD_BODY == TRUE)
+ idle = (void *) _CPU_Thread_Idle_body;
+#else
+ idle = (void *) _Thread_Idle_body;
+#endif
+
+ if ( _CPU_Table.idle_task )
+ idle = _CPU_Table.idle_task;
+
+ idle_task_stack_size = _CPU_Table.idle_task_stack_size;
+ if ( idle_task_stack_size < STACK_MINIMUM_SIZE )
+ idle_task_stack_size = STACK_MINIMUM_SIZE;
+
+ _Thread_Initialize(
+ &_Thread_Internal_information,
+ _Thread_Idle,
+ NULL, /* allocate the stack */
+ idle_task_stack_size,
+ CPU_IDLE_TASK_IS_FP,
+ PRIORITY_MAXIMUM,
+ TRUE, /* preemptable */
+ THREAD_CPU_BUDGET_ALGORITHM_NONE,
+ NULL, /* no budget algorithm callout */
+ 0, /* all interrupts enabled */
+ (Objects_Name) _Thread_Idle_name
+ );
+
+ /*
+ * WARNING!!! This is necessary to "kick" start the system and
+ * MUST be done before _Thread_Start is invoked.
+ */
+
+ _Thread_Heir =
+ _Thread_Executing = _Thread_Idle;
+
+ _Thread_Start(
+ _Thread_Idle,
+ THREAD_START_NUMERIC,
+ idle,
+ NULL,
+ 0
+ );
+
+}
diff --git a/cpukit/score/src/threaddelayended.c b/cpukit/score/src/threaddelayended.c
new file mode 100644
index 0000000000..e5d831b95e
--- /dev/null
+++ b/cpukit/score/src/threaddelayended.c
@@ -0,0 +1,60 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _Thread_Delay_ended
+ *
+ * This routine processes a thread whose delay period has ended.
+ * It is called by the watchdog handler.
+ *
+ * Input parameters:
+ * id - thread id
+ *
+ * Output parameters: NONE
+ */
+
+void _Thread_Delay_ended(
+ Objects_Id id,
+ void *ignored
+)
+{
+ Thread_Control *the_thread;
+ Objects_Locations location;
+
+ the_thread = _Thread_Get( id, &location );
+ switch ( location ) {
+ case OBJECTS_ERROR:
+ case OBJECTS_REMOTE: /* impossible */
+ break;
+ case OBJECTS_LOCAL:
+ _Thread_Unblock( the_thread );
+ _Thread_Unnest_dispatch();
+ break;
+ }
+}
diff --git a/cpukit/score/src/threaddispatch.c b/cpukit/score/src/threaddispatch.c
new file mode 100644
index 0000000000..a4f5a1072f
--- /dev/null
+++ b/cpukit/score/src/threaddispatch.c
@@ -0,0 +1,141 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _Thread_Dispatch
+ *
+ * This kernel routine determines if a dispatch is needed, and if so
+ * dispatches to the heir thread. Once the heir is running an attempt
+ * is made to dispatch any ASRs.
+ *
+ * ALTERNATE ENTRY POINTS:
+ * void _Thread_Enable_dispatch();
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY:
+ * dispatch thread
+ * no dispatch thread
+ */
+
+#if ( CPU_INLINE_ENABLE_DISPATCH == FALSE )
+void _Thread_Enable_dispatch( void )
+{
+ if ( --_Thread_Dispatch_disable_level )
+ return;
+ _Thread_Dispatch();
+}
+#endif
+
+void _Thread_Dispatch( void )
+{
+ Thread_Control *executing;
+ Thread_Control *heir;
+ ISR_Level level;
+
+ executing = _Thread_Executing;
+ _ISR_Disable( level );
+ while ( _Context_Switch_necessary == TRUE ) {
+ heir = _Thread_Heir;
+ _Thread_Dispatch_disable_level = 1;
+ _Context_Switch_necessary = FALSE;
+ _Thread_Executing = heir;
+ executing->rtems_ada_self = rtems_ada_self;
+ rtems_ada_self = heir->rtems_ada_self;
+ _ISR_Enable( level );
+
+ heir->ticks_executed++;
+
+ /*
+ * Switch libc's task specific data.
+ */
+ if ( _Thread_libc_reent ) {
+ executing->libc_reent = *_Thread_libc_reent;
+ *_Thread_libc_reent = heir->libc_reent;
+ }
+
+ _User_extensions_Thread_switch( executing, heir );
+
+ if ( heir->budget_algorithm == THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE )
+ heir->cpu_time_budget = _Thread_Ticks_per_timeslice;
+
+ /*
+ * If the CPU has hardware floating point, then we must address saving
+ * and restoring it as part of the context switch.
+ *
+ * The second conditional compilation section selects the algorithm used
+ * to context switch between floating point tasks. The deferred algorithm
+ * can be significantly better in a system with few floating point tasks
+ * because it reduces the total number of save and restore FP context
+ * operations. However, this algorithm can not be used on all CPUs due
+ * to unpredictable use of FP registers by some compilers for integer
+ * operations.
+ */
+
+#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+#if ( CPU_USE_DEFERRED_FP_SWITCH != TRUE )
+ if ( executing->fp_context != NULL )
+ _Context_Save_fp( &executing->fp_context );
+#endif
+#endif
+
+ _Context_Switch( &executing->Registers, &heir->Registers );
+
+#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+#if ( CPU_USE_DEFERRED_FP_SWITCH == TRUE )
+ if ( (executing->fp_context != NULL) && !_Thread_Is_allocated_fp( executing ) ) {
+ if ( _Thread_Allocated_fp != NULL )
+ _Context_Save_fp( &_Thread_Allocated_fp->fp_context );
+ _Context_Restore_fp( &executing->fp_context );
+ _Thread_Allocated_fp = executing;
+ }
+#else
+ if ( executing->fp_context != NULL )
+ _Context_Restore_fp( &executing->fp_context );
+#endif
+#endif
+
+ executing = _Thread_Executing;
+
+ _ISR_Disable( level );
+ }
+
+ _Thread_Dispatch_disable_level = 0;
+
+ _ISR_Enable( level );
+
+ if ( _Thread_Do_post_task_switch_extension ||
+ executing->do_post_task_switch_extension ) {
+ executing->do_post_task_switch_extension = FALSE;
+ _API_extensions_Run_postswitch();
+ }
+
+}
diff --git a/cpukit/score/src/threadevaluatemode.c b/cpukit/score/src/threadevaluatemode.c
new file mode 100644
index 0000000000..dc8b1061cd
--- /dev/null
+++ b/cpukit/score/src/threadevaluatemode.c
@@ -0,0 +1,49 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _Thread_Evaluate_mode
+ *
+ * XXX
+ */
+
+boolean _Thread_Evaluate_mode( void )
+{
+ Thread_Control *executing;
+
+ executing = _Thread_Executing;
+
+ if ( !_States_Is_ready( executing->current_state ) ||
+ ( !_Thread_Is_heir( executing ) && executing->is_preemptible ) ) {
+ _Context_Switch_necessary = TRUE;
+ return TRUE;
+ }
+
+ return FALSE;
+}
diff --git a/cpukit/score/src/threadget.c b/cpukit/score/src/threadget.c
new file mode 100644
index 0000000000..2db332d80c
--- /dev/null
+++ b/cpukit/score/src/threadget.c
@@ -0,0 +1,83 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _Thread_Get
+ *
+ * NOTE: If we are not using static inlines, this must be a real
+ * subroutine call.
+ *
+ * NOTE: XXX... This routine may be able to be optimized.
+ */
+
+#ifndef RTEMS_INLINES
+
+Thread_Control *_Thread_Get (
+ Objects_Id id,
+ Objects_Locations *location
+)
+{
+ uint32_t the_api;
+ uint32_t the_class;
+ Objects_Information *information;
+ Thread_Control *tp = (Thread_Control *) 0;
+
+ if ( _Objects_Are_ids_equal( id, OBJECTS_ID_OF_SELF ) ) {
+ _Thread_Disable_dispatch();
+ *location = OBJECTS_LOCAL;
+ tp = _Thread_Executing;
+ goto done;
+ }
+
+ the_api = _Objects_Get_API( id );
+ if ( the_api && the_api > OBJECTS_APIS_LAST ) {
+ *location = OBJECTS_ERROR;
+ goto done;
+ }
+
+ the_class = _Objects_Get_class( id );
+ if ( the_class != 1 ) { /* threads are always first class :) */
+ *location = OBJECTS_ERROR;
+ goto done;
+ }
+
+ information = _Objects_Information_table[ the_api ][ the_class ];
+
+ if ( !information ) {
+ *location = OBJECTS_ERROR;
+ goto done;
+ }
+
+ tp = (Thread_Control *) _Objects_Get( information, id, location );
+
+done:
+ return tp;
+}
+
+#endif
diff --git a/cpukit/score/src/threadhandler.c b/cpukit/score/src/threadhandler.c
new file mode 100644
index 0000000000..a0d54e8579
--- /dev/null
+++ b/cpukit/score/src/threadhandler.c
@@ -0,0 +1,164 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _Thread_Handler
+ *
+ * This routine is the "primal" entry point for all threads.
+ * _Context_Initialize() dummies up the thread's initial context
+ * to cause the first Context_Switch() to jump to _Thread_Handler().
+ *
+ * This routine is the default thread exitted error handler. It is
+ * returned to when a thread exits. The configured fatal error handler
+ * is invoked to process the exit.
+ *
+ * NOTE:
+ *
+ * On entry, it is assumed all interrupts are blocked and that this
+ * routine needs to set the initial isr level. This may or may not
+ * actually be needed by the context switch routine and as a result
+ * interrupts may already be at there proper level. Either way,
+ * setting the initial isr level properly here is safe.
+ *
+ * Currently this is only really needed for the posix port,
+ * ref: _Context_Switch in unix/cpu.c
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ */
+
+void _Thread_Handler( void )
+{
+ ISR_Level level;
+ Thread_Control *executing;
+#if defined(__USE_INIT_FINI__) || defined(__USE__MAIN__)
+ static char doneConstructors;
+ char doneCons;
+#endif
+#if defined(__USE_INIT_FINI__)
+ extern void _init(void);
+#endif
+#if defined(__USE__MAIN__)
+ extern void _main(void);
+#endif
+
+ executing = _Thread_Executing;
+
+ /*
+ * have to put level into a register for those cpu's that use
+ * inline asm here
+ */
+
+ level = executing->Start.isr_level;
+ _ISR_Set_level(level);
+
+#if defined(__USE_INIT_FINI__) || defined(__USE__MAIN__)
+ doneCons = doneConstructors;
+ doneConstructors = 1;
+#endif
+
+#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+#if ( CPU_USE_DEFERRED_FP_SWITCH == TRUE )
+ if ( (executing->fp_context != NULL) && !_Thread_Is_allocated_fp( executing ) ) {
+ if ( _Thread_Allocated_fp != NULL )
+ _Context_Save_fp( &_Thread_Allocated_fp->fp_context );
+ _Thread_Allocated_fp = executing;
+ }
+#endif
+#endif
+
+
+ /*
+ * Take care that 'begin' extensions get to complete before
+ * 'switch' extensions can run. This means must keep dispatch
+ * disabled until all 'begin' extensions complete.
+ */
+
+ _User_extensions_Thread_begin( executing );
+
+ /*
+ * At this point, the dispatch disable level BETTER be 1.
+ */
+
+ _Thread_Enable_dispatch();
+#if defined(__USE_INIT_FINI__)
+ if (!doneCons && _init)
+ _init ();
+#endif
+#if defined(__USE__MAIN__)
+ if (!doneCons && _main)
+ __main ();
+#endif
+
+
+ switch ( executing->Start.prototype ) {
+ case THREAD_START_NUMERIC:
+ executing->Wait.return_argument =
+ (*(Thread_Entry_numeric) executing->Start.entry_point)(
+ executing->Start.numeric_argument
+ );
+ break;
+ case THREAD_START_POINTER:
+ executing->Wait.return_argument =
+ (*(Thread_Entry_pointer) executing->Start.entry_point)(
+ executing->Start.pointer_argument
+ );
+ break;
+ case THREAD_START_BOTH_POINTER_FIRST:
+ executing->Wait.return_argument =
+ (*(Thread_Entry_both_pointer_first) executing->Start.entry_point)(
+ executing->Start.pointer_argument,
+ executing->Start.numeric_argument
+ );
+ break;
+ case THREAD_START_BOTH_NUMERIC_FIRST:
+ executing->Wait.return_argument =
+ (*(Thread_Entry_both_numeric_first) executing->Start.entry_point)(
+ executing->Start.numeric_argument,
+ executing->Start.pointer_argument
+ );
+ break;
+ }
+
+ /*
+ * In the switch above, the return code from the user thread body
+ * was placed in return_argument. This assumed that if it returned
+ * anything (which is not supporting in all APIs), then it would be
+ * able to fit in a (void *).
+ */
+
+ _User_extensions_Thread_exitted( executing );
+
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ TRUE,
+ INTERNAL_ERROR_THREAD_EXITTED
+ );
+}
diff --git a/cpukit/score/src/threadidlebody.c b/cpukit/score/src/threadidlebody.c
new file mode 100644
index 0000000000..18c4504c1d
--- /dev/null
+++ b/cpukit/score/src/threadidlebody.c
@@ -0,0 +1,51 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _Thread_Idle_body
+ *
+ * This kernel routine is the idle thread. The idle thread runs any time
+ * no other thread is ready to run. This thread loops forever with
+ * interrupts enabled.
+ *
+ * Input parameters:
+ * ignored - this parameter is ignored
+ *
+ * Output parameters: NONE
+ */
+
+#if (CPU_PROVIDES_IDLE_THREAD_BODY == FALSE)
+Thread _Thread_Idle_body(
+ uint32_t ignored
+)
+{
+ for( ; ; ) ;
+ return 0; /* to avoid warning */
+}
+#endif
diff --git a/cpukit/score/src/threadinitialize.c b/cpukit/score/src/threadinitialize.c
new file mode 100644
index 0000000000..f319fc73d9
--- /dev/null
+++ b/cpukit/score/src/threadinitialize.c
@@ -0,0 +1,218 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _Thread_Initialize
+ *
+ * This routine initializes the specified the thread. It allocates
+ * all memory associated with this thread. It completes by adding
+ * the thread to the local object table so operations on this
+ * thread id are allowed.
+ */
+
+boolean _Thread_Initialize(
+ Objects_Information *information,
+ Thread_Control *the_thread,
+ void *stack_area,
+ uint32_t stack_size,
+ boolean is_fp,
+ Priority_Control priority,
+ boolean is_preemptible,
+ Thread_CPU_budget_algorithms budget_algorithm,
+ Thread_CPU_budget_algorithm_callout budget_callout,
+ uint32_t isr_level,
+ Objects_Name name
+)
+{
+ uint32_t actual_stack_size = 0;
+ void *stack = NULL;
+#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+ void *fp_area;
+#endif
+ void *extensions_area;
+
+ /*
+ * Initialize the Ada self pointer
+ */
+
+ the_thread->rtems_ada_self = NULL;
+
+ /*
+ * Allocate and Initialize the stack for this thread.
+ */
+
+
+ if ( !stack_area ) {
+ if ( !_Stack_Is_enough( stack_size ) )
+ actual_stack_size = STACK_MINIMUM_SIZE;
+ else
+ actual_stack_size = stack_size;
+
+ actual_stack_size = _Thread_Stack_Allocate( the_thread, actual_stack_size );
+
+ if ( !actual_stack_size )
+ return FALSE; /* stack allocation failed */
+
+ stack = the_thread->Start.stack;
+ the_thread->Start.core_allocated_stack = TRUE;
+ } else {
+ stack = stack_area;
+ actual_stack_size = stack_size;
+ the_thread->Start.core_allocated_stack = FALSE;
+ }
+
+ _Stack_Initialize(
+ &the_thread->Start.Initial_stack,
+ stack,
+ actual_stack_size
+ );
+
+ /*
+ * Allocate the floating point area for this thread
+ */
+
+#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+ if ( is_fp ) {
+
+ fp_area = _Workspace_Allocate( CONTEXT_FP_SIZE );
+ if ( !fp_area ) {
+ _Thread_Stack_Free( the_thread );
+ return FALSE;
+ }
+ fp_area = _Context_Fp_start( fp_area, 0 );
+
+ } else
+ fp_area = NULL;
+
+ the_thread->fp_context = fp_area;
+ the_thread->Start.fp_context = fp_area;
+#endif
+
+ /*
+ * Clear the libc reent hook.
+ */
+
+ the_thread->libc_reent = NULL;
+
+ /*
+ * Allocate the extensions area for this thread
+ */
+
+ if ( _Thread_Maximum_extensions ) {
+ extensions_area = _Workspace_Allocate(
+ (_Thread_Maximum_extensions + 1) * sizeof( void * )
+ );
+
+ if ( !extensions_area ) {
+#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+ if ( fp_area )
+ (void) _Workspace_Free( fp_area );
+#endif
+
+ _Thread_Stack_Free( the_thread );
+
+ return FALSE;
+ }
+ } else
+ extensions_area = NULL;
+
+ the_thread->extensions = (void **) extensions_area;
+
+ /*
+ * Clear the extensions area so extension users can determine
+ * if they are linked to the thread. An extension user may
+ * create the extension long after tasks have been created
+ * so they cannot rely on the thread create user extension
+ * call.
+ */
+
+ if ( the_thread->extensions ) {
+ int i;
+ for ( i = 0; i < (_Thread_Maximum_extensions + 1); i++ )
+ the_thread->extensions[i] = NULL;
+ }
+
+ /*
+ * General initialization
+ */
+
+ the_thread->Start.is_preemptible = is_preemptible;
+ the_thread->Start.budget_algorithm = budget_algorithm;
+ the_thread->Start.budget_callout = budget_callout;
+
+ switch ( budget_algorithm ) {
+ case THREAD_CPU_BUDGET_ALGORITHM_NONE:
+ case THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE:
+ break;
+ case THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE:
+ the_thread->cpu_time_budget = _Thread_Ticks_per_timeslice;
+ break;
+ case THREAD_CPU_BUDGET_ALGORITHM_CALLOUT:
+ break;
+ }
+
+ the_thread->Start.isr_level = isr_level;
+
+ the_thread->current_state = STATES_DORMANT;
+ the_thread->resource_count = 0;
+ the_thread->suspend_count = 0;
+ the_thread->real_priority = priority;
+ the_thread->Start.initial_priority = priority;
+ the_thread->ticks_executed = 0;
+
+ _Thread_Set_priority( the_thread, priority );
+
+ /*
+ * Open the object
+ */
+
+ _Objects_Open( information, &the_thread->Object, name );
+
+ /*
+ * Invoke create extensions
+ */
+
+ if ( !_User_extensions_Thread_create( the_thread ) ) {
+
+ if ( extensions_area )
+ (void) _Workspace_Free( extensions_area );
+
+#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+ if ( fp_area )
+ (void) _Workspace_Free( fp_area );
+#endif
+
+ _Thread_Stack_Free( the_thread );
+
+ return FALSE;
+ }
+
+ return TRUE;
+
+}
diff --git a/cpukit/score/src/threadloadenv.c b/cpukit/score/src/threadloadenv.c
new file mode 100644
index 0000000000..2087d91aa7
--- /dev/null
+++ b/cpukit/score/src/threadloadenv.c
@@ -0,0 +1,72 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _Thread_Load_environment
+ *
+ * Load starting environment for another thread from its start area in the
+ * thread. Only called from t_restart and t_start.
+ *
+ * Input parameters:
+ * the_thread - thread control block pointer
+ *
+ * Output parameters: NONE
+ */
+
+void _Thread_Load_environment(
+ Thread_Control *the_thread
+)
+{
+ boolean is_fp;
+
+#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+ if ( the_thread->Start.fp_context ) {
+ the_thread->fp_context = the_thread->Start.fp_context;
+ _Context_Initialize_fp( &the_thread->fp_context );
+ is_fp = TRUE;
+ } else
+#endif
+ is_fp = FALSE;
+
+
+ the_thread->do_post_task_switch_extension = FALSE;
+ the_thread->is_preemptible = the_thread->Start.is_preemptible;
+ the_thread->budget_algorithm = the_thread->Start.budget_algorithm;
+ the_thread->budget_callout = the_thread->Start.budget_callout;
+
+ _Context_Initialize(
+ &the_thread->Registers,
+ the_thread->Start.Initial_stack.area,
+ the_thread->Start.Initial_stack.size,
+ the_thread->Start.isr_level,
+ _Thread_Handler,
+ is_fp
+ );
+
+}
diff --git a/cpukit/score/src/threadmp.c b/cpukit/score/src/threadmp.c
new file mode 100644
index 0000000000..f399e6d896
--- /dev/null
+++ b/cpukit/score/src/threadmp.c
@@ -0,0 +1,163 @@
+/*
+ * Multiprocessing Support for the Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/isr.h>
+
+/*PAGE
+ *
+ * _Thread_MP_Handler_initialization
+ *
+ */
+
+void _Thread_MP_Handler_initialization (
+ uint32_t maximum_proxies
+)
+{
+
+ _Chain_Initialize_empty( &_Thread_MP_Active_proxies );
+
+ if ( maximum_proxies == 0 ) {
+ _Chain_Initialize_empty( &_Thread_MP_Inactive_proxies );
+ return;
+ }
+
+
+ _Chain_Initialize(
+ &_Thread_MP_Inactive_proxies,
+ _Workspace_Allocate_or_fatal_error(
+ maximum_proxies * sizeof( Thread_Proxy_control )
+ ),
+ maximum_proxies,
+ sizeof( Thread_Proxy_control )
+ );
+
+}
+
+/*PAGE
+ *
+ * _Thread_MP_Allocate_proxy
+ *
+ */
+
+Thread_Control *_Thread_MP_Allocate_proxy (
+ States_Control the_state
+)
+{
+ Thread_Control *the_thread;
+ Thread_Proxy_control *the_proxy;
+
+ the_thread = (Thread_Control *)_Chain_Get( &_Thread_MP_Inactive_proxies );
+
+ if ( !_Thread_Is_null( the_thread ) ) {
+
+ the_proxy = (Thread_Proxy_control *) the_thread;
+
+ _Thread_Executing->Wait.return_code = THREAD_STATUS_PROXY_BLOCKING;
+
+ the_proxy->receive_packet = _Thread_MP_Receive->receive_packet;
+
+ the_proxy->Object.id = _Thread_MP_Receive->receive_packet->source_tid;
+
+ the_proxy->current_priority =
+ _Thread_MP_Receive->receive_packet->source_priority;
+
+ the_proxy->current_state = _States_Set( STATES_DORMANT, the_state );
+
+ the_proxy->Wait = _Thread_Executing->Wait;
+
+ _Chain_Append( &_Thread_MP_Active_proxies, &the_proxy->Active );
+
+ return the_thread;
+ }
+
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ TRUE,
+ INTERNAL_ERROR_OUT_OF_PROXIES
+ );
+
+ /*
+ * NOTE: The following return insures that the compiler will
+ * think that all paths return a value.
+ */
+
+ return NULL;
+}
+
+/*PAGE
+ *
+ * _Thread_MP_Find_proxy
+ *
+ */
+
+/*
+ * The following macro provides the offset of the Active element
+ * in the Thread_Proxy_control structure. This is the logical
+ * equivalent of the POSITION attribute in Ada.
+ */
+
+#define _Thread_MP_Proxy_Active_offset \
+ ((uint32_t )&(((Thread_Proxy_control *)0))->Active)
+
+Thread_Control *_Thread_MP_Find_proxy (
+ Objects_Id the_id
+)
+{
+
+ Chain_Node *proxy_node;
+ Thread_Control *the_thread;
+ ISR_Level level;
+
+restart:
+
+ _ISR_Disable( level );
+
+ for ( proxy_node = _Thread_MP_Active_proxies.first;
+ !_Chain_Is_tail( &_Thread_MP_Active_proxies, proxy_node ) ;
+ ) {
+
+ the_thread = (Thread_Control *) _Addresses_Subtract_offset(
+ proxy_node,
+ _Thread_MP_Proxy_Active_offset
+ );
+
+ if ( _Objects_Are_ids_equal( the_thread->Object.id, the_id ) ) {
+ _ISR_Enable( level );
+ return the_thread;
+ }
+
+ _ISR_Flash( level );
+
+ proxy_node = proxy_node->next;
+
+ /*
+ * A proxy which is only dormant is not in a blocking state.
+ * Therefore, we are looking at proxy which has been moved from
+ * active to inactive chain (by an ISR) and need to restart
+ * the search.
+ */
+
+ if ( _States_Is_only_dormant( the_thread->current_state ) ) {
+ _ISR_Enable( level );
+ goto restart;
+ }
+ }
+
+ _ISR_Enable( level );
+ return NULL;
+}
diff --git a/cpukit/score/src/threadq.c b/cpukit/score/src/threadq.c
new file mode 100644
index 0000000000..7177de7280
--- /dev/null
+++ b/cpukit/score/src/threadq.c
@@ -0,0 +1,65 @@
+/*
+ * Thread Queue Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+/*PAGE
+ *
+ * _Thread_queue_Initialize
+ *
+ * This routine initializes the specified threadq.
+ *
+ * Input parameters:
+ * the_thread_queue - pointer to a threadq header
+ * discipline - queueing discipline
+ * state - state of waiting threads
+ * timeout_status - return on a timeout
+ *
+ * Output parameters: NONE
+ */
+
+void _Thread_queue_Initialize(
+ Thread_queue_Control *the_thread_queue,
+ Thread_queue_Disciplines the_discipline,
+ States_Control state,
+ uint32_t timeout_status
+)
+{
+ uint32_t index;
+
+ the_thread_queue->state = state;
+ the_thread_queue->discipline = the_discipline;
+ the_thread_queue->timeout_status = timeout_status;
+ the_thread_queue->sync_state = THREAD_QUEUE_SYNCHRONIZED;
+
+ switch ( the_discipline ) {
+ case THREAD_QUEUE_DISCIPLINE_FIFO:
+ _Chain_Initialize_empty( &the_thread_queue->Queues.Fifo );
+ break;
+ case THREAD_QUEUE_DISCIPLINE_PRIORITY:
+ for( index=0 ;
+ index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ;
+ index++)
+ _Chain_Initialize_empty( &the_thread_queue->Queues.Priority[index] );
+ break;
+ }
+
+}
diff --git a/cpukit/score/src/threadqdequeue.c b/cpukit/score/src/threadqdequeue.c
new file mode 100644
index 0000000000..cee4d255bf
--- /dev/null
+++ b/cpukit/score/src/threadqdequeue.c
@@ -0,0 +1,61 @@
+/*
+ * Thread Queue Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+/*PAGE
+ *
+ * _Thread_queue_Dequeue
+ *
+ * This routine removes a thread from the specified threadq. If the
+ * threadq discipline is FIFO, it unblocks a thread, and cancels its
+ * timeout timer. Priority discipline is processed elsewhere.
+ *
+ * Input parameters:
+ * the_thread_queue - pointer to threadq
+ *
+ * Output parameters:
+ * returns - thread dequeued or NULL
+ *
+ * INTERRUPT LATENCY:
+ * check sync
+ */
+
+Thread_Control *_Thread_queue_Dequeue(
+ Thread_queue_Control *the_thread_queue
+)
+{
+ Thread_Control *the_thread;
+
+ switch ( the_thread_queue->discipline ) {
+ case THREAD_QUEUE_DISCIPLINE_FIFO:
+ the_thread = _Thread_queue_Dequeue_fifo( the_thread_queue );
+ break;
+ case THREAD_QUEUE_DISCIPLINE_PRIORITY:
+ the_thread = _Thread_queue_Dequeue_priority( the_thread_queue );
+ break;
+ default: /* this is only to prevent warnings */
+ the_thread = NULL;
+ break;
+ }
+
+ return( the_thread );
+}
diff --git a/cpukit/score/src/threadqdequeuefifo.c b/cpukit/score/src/threadqdequeuefifo.c
new file mode 100644
index 0000000000..b3a7e10495
--- /dev/null
+++ b/cpukit/score/src/threadqdequeuefifo.c
@@ -0,0 +1,85 @@
+/*
+ * Thread Queue Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+/*PAGE
+ *
+ * _Thread_queue_Dequeue_fifo
+ *
+ * This routine removes a thread from the specified threadq.
+ *
+ * Input parameters:
+ * the_thread_queue - pointer to threadq
+ *
+ * Output parameters:
+ * returns - thread dequeued or NULL
+ *
+ * INTERRUPT LATENCY:
+ * check sync
+ * FIFO
+ */
+
+Thread_Control *_Thread_queue_Dequeue_fifo(
+ Thread_queue_Control *the_thread_queue
+)
+{
+ ISR_Level level;
+ Thread_Control *the_thread;
+
+ _ISR_Disable( level );
+ if ( !_Chain_Is_empty( &the_thread_queue->Queues.Fifo ) ) {
+
+ the_thread = (Thread_Control *)
+ _Chain_Get_first_unprotected( &the_thread_queue->Queues.Fifo );
+
+ if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
+ _ISR_Enable( level );
+ _Thread_Unblock( the_thread );
+ } else {
+ _Watchdog_Deactivate( &the_thread->Timer );
+ _ISR_Enable( level );
+ (void) _Watchdog_Remove( &the_thread->Timer );
+ _Thread_Unblock( the_thread );
+ }
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( !_Objects_Is_local_id( the_thread->Object.id ) )
+ _Thread_MP_Free_proxy( the_thread );
+#endif
+
+ return the_thread;
+ }
+
+ switch ( the_thread_queue->sync_state ) {
+ case THREAD_QUEUE_SYNCHRONIZED:
+ case THREAD_QUEUE_SATISFIED:
+ _ISR_Enable( level );
+ return NULL;
+
+ case THREAD_QUEUE_NOTHING_HAPPENED:
+ case THREAD_QUEUE_TIMEOUT:
+ the_thread_queue->sync_state = THREAD_QUEUE_SATISFIED;
+ _ISR_Enable( level );
+ return _Thread_Executing;
+ }
+ return NULL; /* this is only to prevent warnings */
+}
diff --git a/cpukit/score/src/threadqdequeuepriority.c b/cpukit/score/src/threadqdequeuepriority.c
new file mode 100644
index 0000000000..2646b44e17
--- /dev/null
+++ b/cpukit/score/src/threadqdequeuepriority.c
@@ -0,0 +1,124 @@
+/*
+ * Thread Queue Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+/*PAGE
+ *
+ * _Thread_queue_Dequeue_priority
+ *
+ * This routine removes a thread from the specified PRIORITY based
+ * threadq, unblocks it, and cancels its timeout timer.
+ *
+ * Input parameters:
+ * the_thread_queue - pointer to thread queue
+ *
+ * Output parameters:
+ * returns - thread dequeued or NULL
+ *
+ * INTERRUPT LATENCY:
+ * only case
+ */
+
+Thread_Control *_Thread_queue_Dequeue_priority(
+ Thread_queue_Control *the_thread_queue
+)
+{
+ uint32_t index;
+ ISR_Level level;
+ Thread_Control *the_thread = NULL; /* just to remove warnings */
+ Thread_Control *new_first_thread;
+ Chain_Node *new_first_node;
+ Chain_Node *new_second_node;
+ Chain_Node *last_node;
+ Chain_Node *next_node;
+ Chain_Node *previous_node;
+
+ _ISR_Disable( level );
+ for( index=0 ;
+ index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ;
+ index++ ) {
+ if ( !_Chain_Is_empty( &the_thread_queue->Queues.Priority[ index ] ) ) {
+ the_thread = (Thread_Control *)
+ the_thread_queue->Queues.Priority[ index ].first;
+ goto dequeue;
+ }
+ }
+
+ switch ( the_thread_queue->sync_state ) {
+ case THREAD_QUEUE_SYNCHRONIZED:
+ case THREAD_QUEUE_SATISFIED:
+ _ISR_Enable( level );
+ return NULL;
+
+ case THREAD_QUEUE_NOTHING_HAPPENED:
+ case THREAD_QUEUE_TIMEOUT:
+ the_thread_queue->sync_state = THREAD_QUEUE_SATISFIED;
+ _ISR_Enable( level );
+ return _Thread_Executing;
+ }
+
+dequeue:
+ new_first_node = the_thread->Wait.Block2n.first;
+ new_first_thread = (Thread_Control *) new_first_node;
+ next_node = the_thread->Object.Node.next;
+ previous_node = the_thread->Object.Node.previous;
+
+ if ( !_Chain_Is_empty( &the_thread->Wait.Block2n ) ) {
+ last_node = the_thread->Wait.Block2n.last;
+ new_second_node = new_first_node->next;
+
+ previous_node->next = new_first_node;
+ next_node->previous = new_first_node;
+ new_first_node->next = next_node;
+ new_first_node->previous = previous_node;
+
+ if ( !_Chain_Has_only_one_node( &the_thread->Wait.Block2n ) ) {
+ /* > two threads on 2-n */
+ new_second_node->previous =
+ _Chain_Head( &new_first_thread->Wait.Block2n );
+
+ new_first_thread->Wait.Block2n.first = new_second_node;
+ new_first_thread->Wait.Block2n.last = last_node;
+
+ last_node->next = _Chain_Tail( &new_first_thread->Wait.Block2n );
+ }
+ } else {
+ previous_node->next = next_node;
+ next_node->previous = previous_node;
+ }
+
+ if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
+ _ISR_Enable( level );
+ _Thread_Unblock( the_thread );
+ } else {
+ _Watchdog_Deactivate( &the_thread->Timer );
+ _ISR_Enable( level );
+ (void) _Watchdog_Remove( &the_thread->Timer );
+ _Thread_Unblock( the_thread );
+ }
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( !_Objects_Is_local_id( the_thread->Object.id ) )
+ _Thread_MP_Free_proxy( the_thread );
+#endif
+ return( the_thread );
+}
diff --git a/cpukit/score/src/threadqenqueue.c b/cpukit/score/src/threadqenqueue.c
new file mode 100644
index 0000000000..4a0964e8c1
--- /dev/null
+++ b/cpukit/score/src/threadqenqueue.c
@@ -0,0 +1,76 @@
+/*
+ * Thread Queue Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+/*PAGE
+ *
+ * _Thread_queue_Enqueue
+ *
+ * This routine blocks a thread, places it on a thread, and optionally
+ * starts a timeout timer.
+ *
+ * Input parameters:
+ * the_thread_queue - pointer to threadq
+ * timeout - interval to wait
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY:
+ * only case
+ */
+
+void _Thread_queue_Enqueue(
+ Thread_queue_Control *the_thread_queue,
+ Watchdog_Interval timeout
+)
+{
+ Thread_Control *the_thread;
+
+ the_thread = _Thread_Executing;
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( _Thread_MP_Is_receive( the_thread ) && the_thread->receive_packet )
+ the_thread = _Thread_MP_Allocate_proxy( the_thread_queue->state );
+ else
+#endif
+ _Thread_Set_state( the_thread, the_thread_queue->state );
+
+ if ( timeout ) {
+ _Watchdog_Initialize(
+ &the_thread->Timer,
+ _Thread_queue_Timeout,
+ the_thread->Object.id,
+ NULL
+ );
+
+ _Watchdog_Insert_ticks( &the_thread->Timer, timeout );
+ }
+
+ switch( the_thread_queue->discipline ) {
+ case THREAD_QUEUE_DISCIPLINE_FIFO:
+ _Thread_queue_Enqueue_fifo( the_thread_queue, the_thread, timeout );
+ break;
+ case THREAD_QUEUE_DISCIPLINE_PRIORITY:
+ _Thread_queue_Enqueue_priority( the_thread_queue, the_thread, timeout );
+ break;
+ }
+}
diff --git a/cpukit/score/src/threadqenqueuefifo.c b/cpukit/score/src/threadqenqueuefifo.c
new file mode 100644
index 0000000000..87058b594a
--- /dev/null
+++ b/cpukit/score/src/threadqenqueuefifo.c
@@ -0,0 +1,100 @@
+/*
+ * Thread Queue Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+/*PAGE
+ *
+ * _Thread_queue_Enqueue_fifo
+ *
+ * This routine blocks a thread, places it on a thread, and optionally
+ * starts a timeout timer.
+ *
+ * Input parameters:
+ * the_thread_queue - pointer to threadq
+ * the_thread - pointer to the thread to block
+ * timeout - interval to wait
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY:
+ * only case
+ */
+
+void _Thread_queue_Enqueue_fifo (
+ Thread_queue_Control *the_thread_queue,
+ Thread_Control *the_thread,
+ Watchdog_Interval timeout
+)
+{
+ ISR_Level level;
+ Thread_queue_States sync_state;
+
+ _ISR_Disable( level );
+
+ sync_state = the_thread_queue->sync_state;
+ the_thread_queue->sync_state = THREAD_QUEUE_SYNCHRONIZED;
+
+ switch ( sync_state ) {
+ case THREAD_QUEUE_SYNCHRONIZED:
+ /*
+ * This should never happen. It indicates that someone did not
+ * enter a thread queue critical section.
+ */
+ break;
+
+ case THREAD_QUEUE_NOTHING_HAPPENED:
+ _Chain_Append_unprotected(
+ &the_thread_queue->Queues.Fifo,
+ &the_thread->Object.Node
+ );
+ _ISR_Enable( level );
+ return;
+
+ case THREAD_QUEUE_TIMEOUT:
+ the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
+ _ISR_Enable( level );
+ break;
+
+ case THREAD_QUEUE_SATISFIED:
+ if ( _Watchdog_Is_active( &the_thread->Timer ) ) {
+ _Watchdog_Deactivate( &the_thread->Timer );
+ _ISR_Enable( level );
+ (void) _Watchdog_Remove( &the_thread->Timer );
+ } else
+ _ISR_Enable( level );
+ break;
+ }
+
+ /*
+ * Global objects with thread queue's should not be operated on from an
+ * ISR. But the sync code still must allow short timeouts to be processed
+ * correctly.
+ */
+
+ _Thread_Unblock( the_thread );
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( !_Objects_Is_local_id( the_thread->Object.id ) )
+ _Thread_MP_Free_proxy( the_thread );
+#endif
+
+}
diff --git a/cpukit/score/src/threadqenqueuepriority.c b/cpukit/score/src/threadqenqueuepriority.c
new file mode 100644
index 0000000000..8e56d984d4
--- /dev/null
+++ b/cpukit/score/src/threadqenqueuepriority.c
@@ -0,0 +1,220 @@
+/*
+ * Thread Queue Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+/*PAGE
+ *
+ * _Thread_queue_Enqueue_priority
+ *
+ * This routine blocks a thread, places it on a thread, and optionally
+ * starts a timeout timer.
+ *
+ * Input parameters:
+ * the_thread_queue - pointer to threadq
+ * thread - thread to insert
+ * timeout - timeout interval in ticks
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY:
+ * forward less than
+ * forward equal
+ */
+
+void _Thread_queue_Enqueue_priority(
+ Thread_queue_Control *the_thread_queue,
+ Thread_Control *the_thread,
+ Watchdog_Interval timeout
+)
+{
+ Priority_Control search_priority;
+ Thread_Control *search_thread;
+ ISR_Level level;
+ Chain_Control *header;
+ uint32_t header_index;
+ Chain_Node *the_node;
+ Chain_Node *next_node;
+ Chain_Node *previous_node;
+ Chain_Node *search_node;
+ Priority_Control priority;
+ States_Control block_state;
+ Thread_queue_States sync_state;
+
+ _Chain_Initialize_empty( &the_thread->Wait.Block2n );
+
+ priority = the_thread->current_priority;
+ header_index = _Thread_queue_Header_number( priority );
+ header = &the_thread_queue->Queues.Priority[ header_index ];
+ block_state = the_thread_queue->state;
+
+ if ( _Thread_queue_Is_reverse_search( priority ) )
+ goto restart_reverse_search;
+
+restart_forward_search:
+ search_priority = PRIORITY_MINIMUM - 1;
+ _ISR_Disable( level );
+ search_thread = (Thread_Control *) header->first;
+ while ( !_Chain_Is_tail( header, (Chain_Node *)search_thread ) ) {
+ search_priority = search_thread->current_priority;
+ if ( priority <= search_priority )
+ break;
+
+#if ( CPU_UNROLL_ENQUEUE_PRIORITY == TRUE )
+ search_thread = (Thread_Control *) search_thread->Object.Node.next;
+ if ( _Chain_Is_tail( header, (Chain_Node *)search_thread ) )
+ break;
+ search_priority = search_thread->current_priority;
+ if ( priority <= search_priority )
+ break;
+#endif
+ _ISR_Flash( level );
+ if ( !_States_Are_set( search_thread->current_state, block_state) ) {
+ _ISR_Enable( level );
+ goto restart_forward_search;
+ }
+ search_thread =
+ (Thread_Control *)search_thread->Object.Node.next;
+ }
+
+ if ( the_thread_queue->sync_state != THREAD_QUEUE_NOTHING_HAPPENED )
+ goto synchronize;
+
+ the_thread_queue->sync_state = THREAD_QUEUE_SYNCHRONIZED;
+
+ if ( priority == search_priority )
+ goto equal_priority;
+
+ search_node = (Chain_Node *) search_thread;
+ previous_node = search_node->previous;
+ the_node = (Chain_Node *) the_thread;
+
+ the_node->next = search_node;
+ the_node->previous = previous_node;
+ previous_node->next = the_node;
+ search_node->previous = the_node;
+ _ISR_Enable( level );
+ return;
+
+restart_reverse_search:
+ search_priority = PRIORITY_MAXIMUM + 1;
+
+ _ISR_Disable( level );
+ search_thread = (Thread_Control *) header->last;
+ while ( !_Chain_Is_head( header, (Chain_Node *)search_thread ) ) {
+ search_priority = search_thread->current_priority;
+ if ( priority >= search_priority )
+ break;
+#if ( CPU_UNROLL_ENQUEUE_PRIORITY == TRUE )
+ search_thread = (Thread_Control *) search_thread->Object.Node.previous;
+ if ( _Chain_Is_head( header, (Chain_Node *)search_thread ) )
+ break;
+ search_priority = search_thread->current_priority;
+ if ( priority >= search_priority )
+ break;
+#endif
+ _ISR_Flash( level );
+ if ( !_States_Are_set( search_thread->current_state, block_state) ) {
+ _ISR_Enable( level );
+ goto restart_reverse_search;
+ }
+ search_thread = (Thread_Control *)
+ search_thread->Object.Node.previous;
+ }
+
+ if ( the_thread_queue->sync_state != THREAD_QUEUE_NOTHING_HAPPENED )
+ goto synchronize;
+
+ the_thread_queue->sync_state = THREAD_QUEUE_SYNCHRONIZED;
+
+ if ( priority == search_priority )
+ goto equal_priority;
+
+ search_node = (Chain_Node *) search_thread;
+ next_node = search_node->next;
+ the_node = (Chain_Node *) the_thread;
+
+ the_node->next = next_node;
+ the_node->previous = search_node;
+ search_node->next = the_node;
+ next_node->previous = the_node;
+ _ISR_Enable( level );
+ return;
+
+equal_priority: /* add at end of priority group */
+ search_node = _Chain_Tail( &search_thread->Wait.Block2n );
+ previous_node = search_node->previous;
+ the_node = (Chain_Node *) the_thread;
+
+ the_node->next = search_node;
+ the_node->previous = previous_node;
+ previous_node->next = the_node;
+ search_node->previous = the_node;
+ _ISR_Enable( level );
+ return;
+
+synchronize:
+
+ sync_state = the_thread_queue->sync_state;
+ the_thread_queue->sync_state = THREAD_QUEUE_SYNCHRONIZED;
+
+ switch ( sync_state ) {
+ case THREAD_QUEUE_SYNCHRONIZED:
+ /*
+ * This should never happen. It indicates that someone did not
+ * enter a thread queue critical section.
+ */
+ break;
+
+ case THREAD_QUEUE_NOTHING_HAPPENED:
+ /*
+ * This should never happen. All of this was dealt with above.
+ */
+ break;
+
+ case THREAD_QUEUE_TIMEOUT:
+ the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
+ _ISR_Enable( level );
+ break;
+
+ case THREAD_QUEUE_SATISFIED:
+ if ( _Watchdog_Is_active( &the_thread->Timer ) ) {
+ _Watchdog_Deactivate( &the_thread->Timer );
+ _ISR_Enable( level );
+ (void) _Watchdog_Remove( &the_thread->Timer );
+ } else
+ _ISR_Enable( level );
+ break;
+ }
+
+ /*
+ * Global objects with thread queue's should not be operated on from an
+ * ISR. But the sync code still must allow short timeouts to be processed
+ * correctly.
+ */
+
+ _Thread_Unblock( the_thread );
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( !_Objects_Is_local_id( the_thread->Object.id ) )
+ _Thread_MP_Free_proxy( the_thread );
+#endif
+}
diff --git a/cpukit/score/src/threadqextract.c b/cpukit/score/src/threadqextract.c
new file mode 100644
index 0000000000..0d2696ed61
--- /dev/null
+++ b/cpukit/score/src/threadqextract.c
@@ -0,0 +1,53 @@
+/*
+ * Thread Queue Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+/*PAGE
+ *
+ * _Thread_queue_Extract
+ *
+ * This routine removes a specific thread from the specified threadq,
+ * deletes any timeout, and unblocks the thread.
+ *
+ * Input parameters:
+ * the_thread_queue - pointer to a threadq header
+ * the_thread - pointer to a thread control block
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY: NONE
+ */
+
+void _Thread_queue_Extract(
+ Thread_queue_Control *the_thread_queue,
+ Thread_Control *the_thread
+)
+{
+ switch ( the_thread_queue->discipline ) {
+ case THREAD_QUEUE_DISCIPLINE_FIFO:
+ _Thread_queue_Extract_fifo( the_thread_queue, the_thread );
+ break;
+ case THREAD_QUEUE_DISCIPLINE_PRIORITY:
+ _Thread_queue_Extract_priority( the_thread_queue, the_thread );
+ break;
+ }
+}
diff --git a/cpukit/score/src/threadqextractfifo.c b/cpukit/score/src/threadqextractfifo.c
new file mode 100644
index 0000000000..714e2628d9
--- /dev/null
+++ b/cpukit/score/src/threadqextractfifo.c
@@ -0,0 +1,72 @@
+/*
+ * Thread Queue Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+/*PAGE
+ *
+ * _Thread_queue_Extract_fifo
+ *
+ * This routine removes a specific thread from the specified threadq,
+ * deletes any timeout, and unblocks the thread.
+ *
+ * Input parameters:
+ * the_thread_queue - pointer to a threadq header
+ * the_thread - pointer to the thread to block
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY:
+ * EXTRACT_FIFO
+ */
+
+void _Thread_queue_Extract_fifo(
+ Thread_queue_Control *the_thread_queue,
+ Thread_Control *the_thread
+)
+{
+ ISR_Level level;
+
+ _ISR_Disable( level );
+
+ if ( !_States_Is_waiting_on_thread_queue( the_thread->current_state ) ) {
+ _ISR_Enable( level );
+ return;
+ }
+
+ _Chain_Extract_unprotected( &the_thread->Object.Node );
+
+ if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
+ _ISR_Enable( level );
+ } else {
+ _Watchdog_Deactivate( &the_thread->Timer );
+ _ISR_Enable( level );
+ (void) _Watchdog_Remove( &the_thread->Timer );
+ }
+
+ _Thread_Unblock( the_thread );
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( !_Objects_Is_local_id( the_thread->Object.id ) )
+ _Thread_MP_Free_proxy( the_thread );
+#endif
+
+}
diff --git a/cpukit/score/src/threadqextractpriority.c b/cpukit/score/src/threadqextractpriority.c
new file mode 100644
index 0000000000..5836c17de2
--- /dev/null
+++ b/cpukit/score/src/threadqextractpriority.c
@@ -0,0 +1,103 @@
+/*
+ * Thread Queue Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+/*PAGE
+ *
+ * _Thread_queue_Extract_priority
+ *
+ * This routine removes a specific thread from the specified threadq,
+ * deletes any timeout, and unblocks the thread.
+ *
+ * Input parameters:
+ * the_thread_queue - pointer to a threadq header
+ * the_thread - pointer to a thread control block
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY:
+ * EXTRACT_PRIORITY
+ */
+
+void _Thread_queue_Extract_priority(
+ Thread_queue_Control *the_thread_queue,
+ Thread_Control *the_thread
+)
+{
+ ISR_Level level;
+ Chain_Node *the_node;
+ Chain_Node *next_node;
+ Chain_Node *previous_node;
+ Thread_Control *new_first_thread;
+ Chain_Node *new_first_node;
+ Chain_Node *new_second_node;
+ Chain_Node *last_node;
+
+ the_node = (Chain_Node *) the_thread;
+ _ISR_Disable( level );
+ if ( _States_Is_waiting_on_thread_queue( the_thread->current_state ) ) {
+ next_node = the_node->next;
+ previous_node = the_node->previous;
+
+ if ( !_Chain_Is_empty( &the_thread->Wait.Block2n ) ) {
+ new_first_node = the_thread->Wait.Block2n.first;
+ new_first_thread = (Thread_Control *) new_first_node;
+ last_node = the_thread->Wait.Block2n.last;
+ new_second_node = new_first_node->next;
+
+ previous_node->next = new_first_node;
+ next_node->previous = new_first_node;
+ new_first_node->next = next_node;
+ new_first_node->previous = previous_node;
+
+ if ( !_Chain_Has_only_one_node( &the_thread->Wait.Block2n ) ) {
+ /* > two threads on 2-n */
+ new_second_node->previous =
+ _Chain_Head( &new_first_thread->Wait.Block2n );
+ new_first_thread->Wait.Block2n.first = new_second_node;
+
+ new_first_thread->Wait.Block2n.last = last_node;
+ last_node->next = _Chain_Tail( &new_first_thread->Wait.Block2n );
+ }
+ } else {
+ previous_node->next = next_node;
+ next_node->previous = previous_node;
+ }
+
+ if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
+ _ISR_Enable( level );
+ _Thread_Unblock( the_thread );
+ } else {
+ _Watchdog_Deactivate( &the_thread->Timer );
+ _ISR_Enable( level );
+ (void) _Watchdog_Remove( &the_thread->Timer );
+ _Thread_Unblock( the_thread );
+ }
+
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( !_Objects_Is_local_id( the_thread->Object.id ) )
+ _Thread_MP_Free_proxy( the_thread );
+#endif
+ }
+ else
+ _ISR_Enable( level );
+}
diff --git a/cpukit/score/src/threadqextractwithproxy.c b/cpukit/score/src/threadqextractwithproxy.c
new file mode 100644
index 0000000000..6666b1a71a
--- /dev/null
+++ b/cpukit/score/src/threadqextractwithproxy.c
@@ -0,0 +1,62 @@
+/*
+ * Thread Queue Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+/*PAGE
+ *
+ * _Thread_queue_Extract_with_proxy
+ *
+ * This routine extracts the_thread from the_thread_queue
+ * and ensures that if there is a proxy for this task on
+ * another node, it is also dealt with.
+ *
+ * XXX
+ */
+
+boolean _Thread_queue_Extract_with_proxy(
+ Thread_Control *the_thread
+)
+{
+ States_Control state;
+ Objects_Information *the_information;
+ Objects_Thread_queue_Extract_callout proxy_extract_callout;
+
+ state = the_thread->current_state;
+
+ if ( _States_Is_waiting_on_thread_queue( state ) ) {
+ if ( _States_Is_waiting_for_rpc_reply( state ) &&
+ _States_Is_locally_blocked( state ) ) {
+
+ the_information = _Objects_Get_information( the_thread->Wait.id );
+
+ proxy_extract_callout =
+ (Objects_Thread_queue_Extract_callout) the_information->extract;
+
+ if ( proxy_extract_callout )
+ (*proxy_extract_callout)( the_thread );
+ }
+ _Thread_queue_Extract( the_thread->Wait.queue, the_thread );
+
+ return TRUE;
+ }
+ return FALSE;
+}
diff --git a/cpukit/score/src/threadqfirst.c b/cpukit/score/src/threadqfirst.c
new file mode 100644
index 0000000000..9b9db708e1
--- /dev/null
+++ b/cpukit/score/src/threadqfirst.c
@@ -0,0 +1,57 @@
+/*
+ * Thread Queue Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+/*PAGE
+ *
+ * _Thread_queue_First
+ *
+ * This routines returns a pointer to the first thread on the
+ * specified threadq.
+ *
+ * Input parameters:
+ * the_thread_queue - pointer to thread queue
+ *
+ * Output parameters:
+ * returns - first thread or NULL
+ */
+
+Thread_Control *_Thread_queue_First(
+ Thread_queue_Control *the_thread_queue
+)
+{
+ Thread_Control *the_thread;
+
+ switch ( the_thread_queue->discipline ) {
+ case THREAD_QUEUE_DISCIPLINE_FIFO:
+ the_thread = _Thread_queue_First_fifo( the_thread_queue );
+ break;
+ case THREAD_QUEUE_DISCIPLINE_PRIORITY:
+ the_thread = _Thread_queue_First_priority( the_thread_queue );
+ break;
+ default: /* this is only to prevent warnings */
+ the_thread = NULL;
+ break;
+ }
+
+ return the_thread;
+}
diff --git a/cpukit/score/src/threadqfirstfifo.c b/cpukit/score/src/threadqfirstfifo.c
new file mode 100644
index 0000000000..15cb1f4969
--- /dev/null
+++ b/cpukit/score/src/threadqfirstfifo.c
@@ -0,0 +1,46 @@
+/*
+ * Thread Queue Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+/*PAGE
+ *
+ * _Thread_queue_First_fifo
+ *
+ * This routines returns a pointer to the first thread on the
+ * specified threadq.
+ *
+ * Input parameters:
+ * the_thread_queue - pointer to threadq
+ *
+ * Output parameters:
+ * returns - first thread or NULL
+ */
+
+Thread_Control *_Thread_queue_First_fifo(
+ Thread_queue_Control *the_thread_queue
+)
+{
+ if ( !_Chain_Is_empty( &the_thread_queue->Queues.Fifo ) )
+ return (Thread_Control *) the_thread_queue->Queues.Fifo.first;
+
+ return NULL;
+}
diff --git a/cpukit/score/src/threadqfirstpriority.c b/cpukit/score/src/threadqfirstpriority.c
new file mode 100644
index 0000000000..474b27c630
--- /dev/null
+++ b/cpukit/score/src/threadqfirstpriority.c
@@ -0,0 +1,52 @@
+/*
+ * Thread Queue Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+/*PAGE
+ *
+ * _Thread_queue_First_priority
+ *
+ * This routines returns a pointer to the first thread on the
+ * specified threadq.
+ *
+ * Input parameters:
+ * the_thread_queue - pointer to thread queue
+ *
+ * Output parameters:
+ * returns - first thread or NULL
+ */
+
+Thread_Control *_Thread_queue_First_priority (
+ Thread_queue_Control *the_thread_queue
+)
+{
+ uint32_t index;
+
+ for( index=0 ;
+ index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ;
+ index++ ) {
+ if ( !_Chain_Is_empty( &the_thread_queue->Queues.Priority[ index ] ) )
+ return (Thread_Control *)
+ the_thread_queue->Queues.Priority[ index ].first;
+ }
+ return NULL;
+}
diff --git a/cpukit/score/src/threadqflush.c b/cpukit/score/src/threadqflush.c
new file mode 100644
index 0000000000..99aa002f90
--- /dev/null
+++ b/cpukit/score/src/threadqflush.c
@@ -0,0 +1,54 @@
+/*
+ * Thread Queue Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+/*PAGE
+ *
+ * _Thread_queue_Flush
+ *
+ * This kernel routine flushes the given thread queue.
+ *
+ * Input parameters:
+ * the_thread_queue - pointer to threadq to be flushed
+ * remote_extract_callout - pointer to routine which extracts a remote thread
+ * status - status to return to the thread
+ *
+ * Output parameters: NONE
+ */
+
+void _Thread_queue_Flush(
+ Thread_queue_Control *the_thread_queue,
+ Thread_queue_Flush_callout remote_extract_callout,
+ uint32_t status
+)
+{
+ Thread_Control *the_thread;
+
+ while ( (the_thread = _Thread_queue_Dequeue( the_thread_queue )) ) {
+#if defined(RTEMS_MULTIPROCESSING)
+ if ( !_Objects_Is_local_id( the_thread->Object.id ) )
+ ( *remote_extract_callout )( the_thread );
+ else
+#endif
+ the_thread->Wait.return_code = status;
+ }
+}
diff --git a/cpukit/score/src/threadqtimeout.c b/cpukit/score/src/threadqtimeout.c
new file mode 100644
index 0000000000..487b882702
--- /dev/null
+++ b/cpukit/score/src/threadqtimeout.c
@@ -0,0 +1,77 @@
+/*
+ * Thread Queue Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/states.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/tqdata.h>
+
+/*PAGE
+ *
+ * _Thread_queue_Timeout
+ *
+ * This routine processes a thread which timeouts while waiting on
+ * a thread queue. It is called by the watchdog handler.
+ *
+ * Input parameters:
+ * id - thread id
+ *
+ * Output parameters: NONE
+ */
+
+void _Thread_queue_Timeout(
+ Objects_Id id,
+ void *ignored
+)
+{
+ Thread_Control *the_thread;
+ Thread_queue_Control *the_thread_queue;
+ Objects_Locations location;
+
+ the_thread = _Thread_Get( id, &location );
+ switch ( location ) {
+ case OBJECTS_ERROR:
+ case OBJECTS_REMOTE: /* impossible */
+ break;
+ case OBJECTS_LOCAL:
+ the_thread_queue = the_thread->Wait.queue;
+
+ /*
+ * If the_thread_queue is not synchronized, then it is either
+ * "nothing happened", "timeout", or "satisfied". If the_thread
+ * is the executing thread, then it is in the process of blocking
+ * and it is the thread which is responsible for the synchronization
+ * process.
+ *
+ * If it is not satisfied, then it is "nothing happened" and
+ * this is the "timeout" transition. After a request is satisfied,
+ * a timeout is not allowed to occur.
+ */
+
+ if ( the_thread_queue->sync_state != THREAD_QUEUE_SYNCHRONIZED &&
+ _Thread_Is_executing( the_thread ) ) {
+ if ( the_thread_queue->sync_state != THREAD_QUEUE_SATISFIED )
+ the_thread_queue->sync_state = THREAD_QUEUE_TIMEOUT;
+ } else {
+ the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
+ _Thread_queue_Extract( the_thread->Wait.queue, the_thread );
+ }
+ _Thread_Unnest_dispatch();
+ break;
+ }
+}
diff --git a/cpukit/score/src/threadready.c b/cpukit/score/src/threadready.c
new file mode 100644
index 0000000000..cf80801b20
--- /dev/null
+++ b/cpukit/score/src/threadready.c
@@ -0,0 +1,74 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _Thread_Ready
+ *
+ * This kernel routine readies the requested thread, the thread chain
+ * is adjusted. A new heir thread may be selected.
+ *
+ * Input parameters:
+ * the_thread - pointer to thread control block
+ *
+ * Output parameters: NONE
+ *
+ * NOTE: This routine uses the "blocking" heir selection mechanism.
+ * This insures the correct heir after a thread restart.
+ *
+ * INTERRUPT LATENCY:
+ * ready chain
+ * select heir
+ */
+
+void _Thread_Ready(
+ Thread_Control *the_thread
+)
+{
+ ISR_Level level;
+ Thread_Control *heir;
+
+ _ISR_Disable( level );
+
+ the_thread->current_state = STATES_READY;
+
+ _Priority_Add_to_bit_map( &the_thread->Priority_map );
+
+ _Chain_Append_unprotected( the_thread->ready, &the_thread->Object.Node );
+
+ _ISR_Flash( level );
+
+ _Thread_Calculate_heir();
+
+ heir = _Thread_Heir;
+
+ if ( !_Thread_Is_executing( heir ) && _Thread_Executing->is_preemptible )
+ _Context_Switch_necessary = TRUE;
+
+ _ISR_Enable( level );
+}
diff --git a/cpukit/score/src/threadreset.c b/cpukit/score/src/threadreset.c
new file mode 100644
index 0000000000..4e3afe2a9f
--- /dev/null
+++ b/cpukit/score/src/threadreset.c
@@ -0,0 +1,64 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*
+ * _Thread_Reset
+ *
+ * DESCRIPTION:
+ *
+ * This routine resets a thread to its initial stat but does
+ * not actually restart it. Some APIs do this in separate
+ * operations and this division helps support this.
+ */
+
+void _Thread_Reset(
+ Thread_Control *the_thread,
+ void *pointer_argument,
+ uint32_t numeric_argument
+)
+{
+ the_thread->resource_count = 0;
+ the_thread->suspend_count = 0;
+ the_thread->is_preemptible = the_thread->Start.is_preemptible;
+ the_thread->budget_algorithm = the_thread->Start.budget_algorithm;
+ the_thread->budget_callout = the_thread->Start.budget_callout;
+
+ the_thread->Start.pointer_argument = pointer_argument;
+ the_thread->Start.numeric_argument = numeric_argument;
+
+ if ( !_Thread_queue_Extract_with_proxy( the_thread ) ) {
+
+ if ( _Watchdog_Is_active( &the_thread->Timer ) )
+ (void) _Watchdog_Remove( &the_thread->Timer );
+ }
+
+ if ( the_thread->current_priority != the_thread->Start.initial_priority ) {
+ the_thread->real_priority = the_thread->Start.initial_priority;
+ _Thread_Set_priority( the_thread, the_thread->Start.initial_priority );
+ }
+}
diff --git a/cpukit/score/src/threadresettimeslice.c b/cpukit/score/src/threadresettimeslice.c
new file mode 100644
index 0000000000..64734b2e6d
--- /dev/null
+++ b/cpukit/score/src/threadresettimeslice.c
@@ -0,0 +1,71 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _Thread_Reset_timeslice
+ *
+ * This routine will remove the running thread from the ready chain
+ * and place it immediately at the rear of this chain and then the
+ * timeslice counter is reset. The heir THREAD will be updated if
+ * the running is also the currently the heir.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY:
+ * ready chain
+ * select heir
+ */
+
+void _Thread_Reset_timeslice( void )
+{
+ ISR_Level level;
+ Thread_Control *executing;
+ Chain_Control *ready;
+
+ executing = _Thread_Executing;
+ ready = executing->ready;
+ _ISR_Disable( level );
+ if ( _Chain_Has_only_one_node( ready ) ) {
+ _ISR_Enable( level );
+ return;
+ }
+ _Chain_Extract_unprotected( &executing->Object.Node );
+ _Chain_Append_unprotected( ready, &executing->Object.Node );
+
+ _ISR_Flash( level );
+
+ if ( _Thread_Is_heir( executing ) )
+ _Thread_Heir = (Thread_Control *) ready->first;
+
+ _Context_Switch_necessary = TRUE;
+
+ _ISR_Enable( level );
+}
diff --git a/cpukit/score/src/threadrestart.c b/cpukit/score/src/threadrestart.c
new file mode 100644
index 0000000000..606ae6e79c
--- /dev/null
+++ b/cpukit/score/src/threadrestart.c
@@ -0,0 +1,64 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*
+ * _Thread_Restart
+ *
+ * DESCRIPTION:
+ *
+ * This support routine restarts the specified task in a way that the
+ * next time this thread executes, it will begin execution at its
+ * original starting point.
+ */
+
+boolean _Thread_Restart(
+ Thread_Control *the_thread,
+ void *pointer_argument,
+ uint32_t numeric_argument
+)
+{
+ if ( !_States_Is_dormant( the_thread->current_state ) ) {
+
+ _Thread_Set_transient( the_thread );
+
+ _Thread_Reset( the_thread, pointer_argument, numeric_argument );
+
+ _Thread_Load_environment( the_thread );
+
+ _Thread_Ready( the_thread );
+
+ _User_extensions_Thread_restart( the_thread );
+
+ if ( _Thread_Is_executing ( the_thread ) )
+ _Thread_Restart_self();
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
diff --git a/cpukit/score/src/threadresume.c b/cpukit/score/src/threadresume.c
new file mode 100644
index 0000000000..65882d37ca
--- /dev/null
+++ b/cpukit/score/src/threadresume.c
@@ -0,0 +1,94 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _Thread_Resume
+ *
+ * This kernel routine clears the SUSPEND state if the suspend_count
+ * drops below one. If the force parameter is set the suspend_count
+ * is forced back to zero. The thread ready chain is adjusted if
+ * necessary and the Heir thread is set accordingly.
+ *
+ * Input parameters:
+ * the_thread - pointer to thread control block
+ * force - force the suspend count back to 0
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY:
+ * priority map
+ * select heir
+ */
+
+
+void _Thread_Resume(
+ Thread_Control *the_thread,
+ boolean force
+)
+{
+
+ ISR_Level level;
+ States_Control current_state;
+
+ _ISR_Disable( level );
+
+ if ( force == TRUE )
+ the_thread->suspend_count = 0;
+ else
+ the_thread->suspend_count--;
+
+ if ( the_thread->suspend_count > 0 ) {
+ _ISR_Enable( level );
+ return;
+ }
+
+ current_state = the_thread->current_state;
+ if ( current_state & STATES_SUSPENDED ) {
+ current_state =
+ the_thread->current_state = _States_Clear(STATES_SUSPENDED, current_state);
+
+ if ( _States_Is_ready( current_state ) ) {
+
+ _Priority_Add_to_bit_map( &the_thread->Priority_map );
+
+ _Chain_Append_unprotected(the_thread->ready, &the_thread->Object.Node);
+
+ _ISR_Flash( level );
+
+ if ( the_thread->current_priority < _Thread_Heir->current_priority ) {
+ _Thread_Heir = the_thread;
+ if ( _Thread_Executing->is_preemptible ||
+ the_thread->current_priority == 0 )
+ _Context_Switch_necessary = TRUE;
+ }
+ }
+ }
+
+ _ISR_Enable( level );
+}
diff --git a/cpukit/score/src/threadrotatequeue.c b/cpukit/score/src/threadrotatequeue.c
new file mode 100644
index 0000000000..c9ddf2ba8c
--- /dev/null
+++ b/cpukit/score/src/threadrotatequeue.c
@@ -0,0 +1,86 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _Thread_Rotate_Ready_Queue
+ *
+ * This kernel routine will rotate the ready queue.
+ * remove the running THREAD from the ready chain
+ * and place it immediatly at the rear of this chain. Reset timeslice
+ * and yield the processor functions both use this routine, therefore if
+ * reset is TRUE and this is the only thread on the chain then the
+ * timeslice counter is reset. The heir THREAD will be updated if the
+ * running is also the currently the heir.
+ *
+ * Input parameters:
+ * Priority of the queue we wish to modify.
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY:
+ * ready chain
+ * select heir
+ */
+
+void _Thread_Rotate_Ready_Queue(
+ Priority_Control priority
+)
+{
+ ISR_Level level;
+ Thread_Control *executing;
+ Chain_Control *ready;
+ Chain_Node *node;
+
+ ready = &_Thread_Ready_chain[ priority ];
+ executing = _Thread_Executing;
+
+ if ( ready == executing->ready ) {
+ _Thread_Yield_processor();
+ return;
+ }
+
+ _ISR_Disable( level );
+
+ if ( !_Chain_Is_empty( ready ) ) {
+ if (!_Chain_Has_only_one_node( ready ) ) {
+ node = _Chain_Get_first_unprotected( ready );
+ _Chain_Append_unprotected( ready, node );
+ }
+ }
+
+ _ISR_Flash( level );
+
+ if ( _Thread_Heir->ready == ready )
+ _Thread_Heir = (Thread_Control *) ready->first;
+
+ if ( executing != _Thread_Heir )
+ _Context_Switch_necessary = TRUE;
+
+ _ISR_Enable( level );
+}
diff --git a/cpukit/score/src/threadsetpriority.c b/cpukit/score/src/threadsetpriority.c
new file mode 100644
index 0000000000..034d07b94c
--- /dev/null
+++ b/cpukit/score/src/threadsetpriority.c
@@ -0,0 +1,52 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _Thread_Set_priority
+ *
+ * This directive enables and disables several modes of
+ * execution for the requesting thread.
+ *
+ * Input parameters:
+ * the_thread - pointer to thread priority
+ * new_priority - new priority
+ *
+ * Output: NONE
+ */
+
+void _Thread_Set_priority(
+ Thread_Control *the_thread,
+ Priority_Control new_priority
+)
+{
+ the_thread->current_priority = new_priority;
+ the_thread->ready = &_Thread_Ready_chain[ new_priority ];
+
+ _Priority_Initialize_information( &the_thread->Priority_map, new_priority );
+}
diff --git a/cpukit/score/src/threadsetstate.c b/cpukit/score/src/threadsetstate.c
new file mode 100644
index 0000000000..2f53546a04
--- /dev/null
+++ b/cpukit/score/src/threadsetstate.c
@@ -0,0 +1,83 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _Thread_Set_state
+ *
+ * This kernel routine sets the requested state in the THREAD. The
+ * THREAD chain is adjusted if necessary.
+ *
+ * Input parameters:
+ * the_thread - pointer to thread control block
+ * state - state to be set
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY:
+ * ready chain
+ * select map
+ */
+
+void _Thread_Set_state(
+ Thread_Control *the_thread,
+ States_Control state
+)
+{
+ ISR_Level level;
+ Chain_Control *ready;
+
+ ready = the_thread->ready;
+ _ISR_Disable( level );
+ if ( !_States_Is_ready( the_thread->current_state ) ) {
+ the_thread->current_state =
+ _States_Set( state, the_thread->current_state );
+ _ISR_Enable( level );
+ return;
+ }
+
+ the_thread->current_state = state;
+
+ if ( _Chain_Has_only_one_node( ready ) ) {
+
+ _Chain_Initialize_empty( ready );
+ _Priority_Remove_from_bit_map( &the_thread->Priority_map );
+
+ } else
+ _Chain_Extract_unprotected( &the_thread->Object.Node );
+
+ _ISR_Flash( level );
+
+ if ( _Thread_Is_heir( the_thread ) )
+ _Thread_Calculate_heir();
+
+ if ( _Thread_Is_executing( the_thread ) )
+ _Context_Switch_necessary = TRUE;
+
+ _ISR_Enable( level );
+}
diff --git a/cpukit/score/src/threadsettransient.c b/cpukit/score/src/threadsettransient.c
new file mode 100644
index 0000000000..0147c3f578
--- /dev/null
+++ b/cpukit/score/src/threadsettransient.c
@@ -0,0 +1,73 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _Thread_Set_transient
+ *
+ * This kernel routine places the requested thread in the transient state
+ * which will remove it from the ready queue, if necessary. No
+ * rescheduling is necessary because it is assumed that the transient
+ * state will be cleared before dispatching is enabled.
+ *
+ * Input parameters:
+ * the_thread - pointer to thread control block
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY:
+ * only case
+ */
+
+void _Thread_Set_transient(
+ Thread_Control *the_thread
+)
+{
+ ISR_Level level;
+ uint32_t old_state;
+ Chain_Control *ready;
+
+ ready = the_thread->ready;
+ _ISR_Disable( level );
+
+ old_state = the_thread->current_state;
+ the_thread->current_state = _States_Set( STATES_TRANSIENT, old_state );
+
+ if ( _States_Is_ready( old_state ) ) {
+ if ( _Chain_Has_only_one_node( ready ) ) {
+
+ _Chain_Initialize_empty( ready );
+ _Priority_Remove_from_bit_map( &the_thread->Priority_map );
+
+ } else
+ _Chain_Extract_unprotected( &the_thread->Object.Node );
+ }
+
+ _ISR_Enable( level );
+
+}
diff --git a/cpukit/score/src/threadstackallocate.c b/cpukit/score/src/threadstackallocate.c
new file mode 100644
index 0000000000..74872d91f5
--- /dev/null
+++ b/cpukit/score/src/threadstackallocate.c
@@ -0,0 +1,81 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _Thread_Stack_Allocate
+ *
+ * Allocate the requested stack space for the thread.
+ * return the actual size allocated after any adjustment
+ * or return zero if the allocation failed.
+ * Set the Start.stack field to the address of the stack
+ */
+
+uint32_t _Thread_Stack_Allocate(
+ Thread_Control *the_thread,
+ uint32_t stack_size
+)
+{
+ void *stack_addr = 0;
+
+ if ( !_Stack_Is_enough( stack_size ) )
+ stack_size = STACK_MINIMUM_SIZE;
+
+ /*
+ * Call ONLY the CPU table stack allocate hook, _or_ the
+ * the RTEMS workspace allocate. This is so the stack free
+ * routine can call the correct deallocation routine.
+ */
+
+ if ( _CPU_Table.stack_allocate_hook )
+ {
+ stack_addr = (*_CPU_Table.stack_allocate_hook)( stack_size );
+ } else {
+
+ /*
+ * First pad the requested size so we allocate enough memory
+ * so the context initialization can align it properly. The address
+ * returned the workspace allocate must be directly stored in the
+ * stack control block because it is later used in the free sequence.
+ *
+ * Thus it is the responsibility of the CPU dependent code to
+ * get and keep the stack adjust factor, the stack alignment, and
+ * the context initialization sequence in sync.
+ */
+
+ stack_size = _Stack_Adjust_size( stack_size );
+ stack_addr = _Workspace_Allocate( stack_size );
+ }
+
+ if ( !stack_addr )
+ stack_size = 0;
+
+ the_thread->Start.stack = stack_addr;
+
+ return stack_size;
+}
diff --git a/cpukit/score/src/threadstackfree.c b/cpukit/score/src/threadstackfree.c
new file mode 100644
index 0000000000..ee1357292b
--- /dev/null
+++ b/cpukit/score/src/threadstackfree.c
@@ -0,0 +1,56 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*
+ * _Thread_Stack_Free
+ *
+ * Deallocate the Thread's stack.
+ */
+
+void _Thread_Stack_Free(
+ Thread_Control *the_thread
+)
+{
+ /*
+ * If the API provided the stack space, then don't free it.
+ */
+
+ if ( !the_thread->Start.core_allocated_stack )
+ return;
+
+ /*
+ * Call ONLY the CPU table stack free hook, or the
+ * the RTEMS workspace free. This is so the free
+ * routine properly matches the allocation of the stack.
+ */
+
+ if ( _CPU_Table.stack_free_hook )
+ (*_CPU_Table.stack_free_hook)( the_thread->Start.Initial_stack.area );
+ else
+ _Workspace_Free( the_thread->Start.Initial_stack.area );
+}
diff --git a/cpukit/score/src/threadstart.c b/cpukit/score/src/threadstart.c
new file mode 100644
index 0000000000..b55d8dc478
--- /dev/null
+++ b/cpukit/score/src/threadstart.c
@@ -0,0 +1,66 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*
+ * _Thread_Start
+ *
+ * DESCRIPTION:
+ *
+ * This routine initializes the executable information for a thread
+ * and makes it ready to execute. After this routine executes, the
+ * thread competes with all other threads for CPU time.
+ */
+
+boolean _Thread_Start(
+ Thread_Control *the_thread,
+ Thread_Start_types the_prototype,
+ void *entry_point,
+ void *pointer_argument,
+ uint32_t numeric_argument
+)
+{
+ if ( _States_Is_dormant( the_thread->current_state ) ) {
+
+ the_thread->Start.entry_point = (Thread_Entry) entry_point;
+
+ the_thread->Start.prototype = the_prototype;
+ the_thread->Start.pointer_argument = pointer_argument;
+ the_thread->Start.numeric_argument = numeric_argument;
+
+ _Thread_Load_environment( the_thread );
+
+ _Thread_Ready( the_thread );
+
+ _User_extensions_Thread_start( the_thread );
+
+ return TRUE;
+ }
+
+ return FALSE;
+
+}
diff --git a/cpukit/score/src/threadstartmultitasking.c b/cpukit/score/src/threadstartmultitasking.c
new file mode 100644
index 0000000000..6ce9a0529c
--- /dev/null
+++ b/cpukit/score/src/threadstartmultitasking.c
@@ -0,0 +1,89 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _Thread_Start_multitasking
+ *
+ * This kernel routine readies the requested thread, the thread chain
+ * is adjusted. A new heir thread may be selected.
+ *
+ * Input parameters:
+ * system_thread - pointer to system initialization thread control block
+ * idle_thread - pointer to idle thread control block
+ *
+ * Output parameters: NONE
+ *
+ * NOTE: This routine uses the "blocking" heir selection mechanism.
+ * This insures the correct heir after a thread restart.
+ *
+ * INTERRUPT LATENCY:
+ * ready chain
+ * select heir
+ */
+
+void _Thread_Start_multitasking( void )
+{
+ /*
+ * The system is now multitasking and completely initialized.
+ * This system thread now either "goes away" in a single processor
+ * system or "turns into" the server thread in an MP system.
+ */
+
+ _System_state_Set( SYSTEM_STATE_UP );
+
+ _Context_Switch_necessary = FALSE;
+
+ _Thread_Executing = _Thread_Heir;
+
+ /*
+ * Get the init task(s) running.
+ *
+ * Note: Thread_Dispatch() is normally used to dispatch threads. As
+ * part of its work, Thread_Dispatch() restores floating point
+ * state for the heir task.
+ *
+ * This code avoids Thread_Dispatch(), and so we have to restore
+ * (actually initialize) the floating point state "by hand".
+ *
+ * Ignore the CPU_USE_DEFERRED_FP_SWITCH because we must always
+ * switch in the first thread if it is FP.
+ */
+
+
+#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
+ /*
+ * don't need to worry about saving BSP's floating point state
+ */
+
+ if ( _Thread_Heir->fp_context != NULL )
+ _Context_Restore_fp( &_Thread_Heir->fp_context );
+#endif
+
+ _Context_Switch( &_Thread_BSP_context, &_Thread_Heir->Registers );
+}
diff --git a/cpukit/score/src/threadsuspend.c b/cpukit/score/src/threadsuspend.c
new file mode 100644
index 0000000000..418e279415
--- /dev/null
+++ b/cpukit/score/src/threadsuspend.c
@@ -0,0 +1,82 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _Thread_Suspend
+ *
+ * This kernel routine sets the SUSPEND state in the THREAD. The
+ * THREAD chain and suspend count are adjusted if necessary.
+ *
+ * Input parameters:
+ * the_thread - pointer to thread control block
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY:
+ * ready chain
+ * select map
+ */
+
+void _Thread_Suspend(
+ Thread_Control *the_thread
+)
+{
+ ISR_Level level;
+ Chain_Control *ready;
+
+ ready = the_thread->ready;
+ _ISR_Disable( level );
+ the_thread->suspend_count++;
+ if ( !_States_Is_ready( the_thread->current_state ) ) {
+ the_thread->current_state =
+ _States_Set( STATES_SUSPENDED, the_thread->current_state );
+ _ISR_Enable( level );
+ return;
+ }
+
+ the_thread->current_state = STATES_SUSPENDED;
+
+ if ( _Chain_Has_only_one_node( ready ) ) {
+
+ _Chain_Initialize_empty( ready );
+ _Priority_Remove_from_bit_map( &the_thread->Priority_map );
+
+ } else
+ _Chain_Extract_unprotected( &the_thread->Object.Node );
+
+ _ISR_Flash( level );
+
+ if ( _Thread_Is_heir( the_thread ) )
+ _Thread_Calculate_heir();
+
+ if ( _Thread_Is_executing( the_thread ) )
+ _Context_Switch_necessary = TRUE;
+
+ _ISR_Enable( level );
+}
diff --git a/cpukit/score/src/threadtickletimeslice.c b/cpukit/score/src/threadtickletimeslice.c
new file mode 100644
index 0000000000..db2c9461ef
--- /dev/null
+++ b/cpukit/score/src/threadtickletimeslice.c
@@ -0,0 +1,86 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _Thread_Tickle_timeslice
+ *
+ * This scheduler routine determines if timeslicing is enabled
+ * for the currently executing thread and, if so, updates the
+ * timeslice count and checks for timeslice expiration.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ */
+
+void _Thread_Tickle_timeslice( void )
+{
+ Thread_Control *executing;
+
+ executing = _Thread_Executing;
+
+ /*
+ * Increment the number of ticks this thread has been executing
+ */
+
+ executing->ticks_executed++;
+
+ /*
+ * If the thread is not preemptible or is not ready, then
+ * just return.
+ */
+
+ if ( !executing->is_preemptible )
+ return;
+
+ if ( !_States_Is_ready( executing->current_state ) )
+ return;
+
+ /*
+ * The cpu budget algorithm determines what happens next.
+ */
+
+ switch ( executing->budget_algorithm ) {
+ case THREAD_CPU_BUDGET_ALGORITHM_NONE:
+ break;
+
+ case THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE:
+ case THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE:
+ if ( --executing->cpu_time_budget == 0 ) {
+ _Thread_Reset_timeslice();
+ executing->cpu_time_budget = _Thread_Ticks_per_timeslice;
+ }
+ break;
+
+ case THREAD_CPU_BUDGET_ALGORITHM_CALLOUT:
+ if ( --executing->cpu_time_budget == 0 )
+ (*executing->budget_callout)( executing );
+ break;
+ }
+}
diff --git a/cpukit/score/src/threadyieldprocessor.c b/cpukit/score/src/threadyieldprocessor.c
new file mode 100644
index 0000000000..39dd1c092b
--- /dev/null
+++ b/cpukit/score/src/threadyieldprocessor.c
@@ -0,0 +1,72 @@
+/*
+ * Thread Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/apiext.h>
+#include <rtems/score/context.h>
+#include <rtems/score/interr.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/object.h>
+#include <rtems/score/priority.h>
+#include <rtems/score/states.h>
+#include <rtems/score/sysstate.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threadq.h>
+#include <rtems/score/userext.h>
+#include <rtems/score/wkspace.h>
+
+/*PAGE
+ *
+ * _Thread_Yield_processor
+ *
+ * This kernel routine will remove the running THREAD from the ready chain
+ * and place it immediatly at the rear of this chain. Reset timeslice
+ * and yield the processor functions both use this routine, therefore if
+ * reset is TRUE and this is the only thread on the chain then the
+ * timeslice counter is reset. The heir THREAD will be updated if the
+ * running is also the currently the heir.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * INTERRUPT LATENCY:
+ * ready chain
+ * select heir
+ */
+
+void _Thread_Yield_processor( void )
+{
+ ISR_Level level;
+ Thread_Control *executing;
+ Chain_Control *ready;
+
+ executing = _Thread_Executing;
+ ready = executing->ready;
+ _ISR_Disable( level );
+ if ( !_Chain_Has_only_one_node( ready ) ) {
+ _Chain_Extract_unprotected( &executing->Object.Node );
+ _Chain_Append_unprotected( ready, &executing->Object.Node );
+
+ _ISR_Flash( level );
+
+ if ( _Thread_Is_heir( executing ) )
+ _Thread_Heir = (Thread_Control *) ready->first;
+ _Context_Switch_necessary = TRUE;
+ }
+ else if ( !_Thread_Is_heir( executing ) )
+ _Context_Switch_necessary = TRUE;
+
+ _ISR_Enable( level );
+}
diff --git a/cpukit/score/src/userext.c b/cpukit/score/src/userext.c
new file mode 100644
index 0000000000..d3421838c8
--- /dev/null
+++ b/cpukit/score/src/userext.c
@@ -0,0 +1,201 @@
+/*
+ * User Extension Handler
+ *
+ * NOTE: XXX
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/userext.h>
+
+/*PAGE
+ *
+ * _User_extensions_Thread_create
+ */
+
+boolean _User_extensions_Thread_create (
+ Thread_Control *the_thread
+)
+{
+ Chain_Node *the_node;
+ User_extensions_Control *the_extension;
+ boolean status;
+
+ for ( the_node = _User_extensions_List.first ;
+ !_Chain_Is_tail( &_User_extensions_List, the_node ) ;
+ the_node = the_node->next ) {
+
+ the_extension = (User_extensions_Control *) the_node;
+
+ if ( the_extension->Callouts.thread_create != NULL ) {
+ status = (*the_extension->Callouts.thread_create)(
+ _Thread_Executing,
+ the_thread
+ );
+ if ( !status )
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/*PAGE
+ *
+ * _User_extensions_Thread_delete
+ */
+
+void _User_extensions_Thread_delete (
+ Thread_Control *the_thread
+)
+{
+ Chain_Node *the_node;
+ User_extensions_Control *the_extension;
+
+ for ( the_node = _User_extensions_List.last ;
+ !_Chain_Is_head( &_User_extensions_List, the_node ) ;
+ the_node = the_node->previous ) {
+
+ the_extension = (User_extensions_Control *) the_node;
+
+ if ( the_extension->Callouts.thread_delete != NULL )
+ (*the_extension->Callouts.thread_delete)(
+ _Thread_Executing,
+ the_thread
+ );
+ }
+}
+
+/*PAGE
+ *
+ * _User_extensions_Thread_start
+ *
+ */
+
+void _User_extensions_Thread_start (
+ Thread_Control *the_thread
+)
+{
+ Chain_Node *the_node;
+ User_extensions_Control *the_extension;
+
+ for ( the_node = _User_extensions_List.first ;
+ !_Chain_Is_tail( &_User_extensions_List, the_node ) ;
+ the_node = the_node->next ) {
+
+ the_extension = (User_extensions_Control *) the_node;
+
+ if ( the_extension->Callouts.thread_start != NULL )
+ (*the_extension->Callouts.thread_start)(
+ _Thread_Executing,
+ the_thread
+ );
+ }
+}
+
+/*PAGE
+ *
+ * _User_extensions_Thread_restart
+ *
+ */
+
+void _User_extensions_Thread_restart (
+ Thread_Control *the_thread
+)
+{
+ Chain_Node *the_node;
+ User_extensions_Control *the_extension;
+
+ for ( the_node = _User_extensions_List.first ;
+ !_Chain_Is_tail( &_User_extensions_List, the_node ) ;
+ the_node = the_node->next ) {
+
+ the_extension = (User_extensions_Control *) the_node;
+
+ if ( the_extension->Callouts.thread_restart != NULL )
+ (*the_extension->Callouts.thread_restart)(
+ _Thread_Executing,
+ the_thread
+ );
+ }
+}
+
+/*PAGE
+ *
+ * _User_extensions_Thread_begin
+ *
+ */
+
+void _User_extensions_Thread_begin (
+ Thread_Control *executing
+)
+{
+ Chain_Node *the_node;
+ User_extensions_Control *the_extension;
+
+ for ( the_node = _User_extensions_List.first ;
+ !_Chain_Is_tail( &_User_extensions_List, the_node ) ;
+ the_node = the_node->next ) {
+
+ the_extension = (User_extensions_Control *) the_node;
+
+ if ( the_extension->Callouts.thread_begin != NULL )
+ (*the_extension->Callouts.thread_begin)( executing );
+ }
+}
+
+/*PAGE
+ *
+ * _User_extensions_Thread_exitted
+ */
+
+void _User_extensions_Thread_exitted (
+ Thread_Control *executing
+)
+{
+ Chain_Node *the_node;
+ User_extensions_Control *the_extension;
+
+ for ( the_node = _User_extensions_List.last ;
+ !_Chain_Is_head( &_User_extensions_List, the_node ) ;
+ the_node = the_node->previous ) {
+
+ the_extension = (User_extensions_Control *) the_node;
+
+ if ( the_extension->Callouts.thread_exitted != NULL )
+ (*the_extension->Callouts.thread_exitted)( executing );
+ }
+}
+
+/*PAGE
+ *
+ * _User_extensions_Fatal
+ */
+
+void _User_extensions_Fatal (
+ Internal_errors_Source the_source,
+ boolean is_internal,
+ uint32_t the_error
+)
+{
+ Chain_Node *the_node;
+ User_extensions_Control *the_extension;
+
+ for ( the_node = _User_extensions_List.last ;
+ !_Chain_Is_head( &_User_extensions_List, the_node ) ;
+ the_node = the_node->previous ) {
+
+ the_extension = (User_extensions_Control *) the_node;
+
+ if ( the_extension->Callouts.fatal != NULL )
+ (*the_extension->Callouts.fatal)( the_source, is_internal, the_error );
+ }
+}
diff --git a/cpukit/score/src/watchdog.c b/cpukit/score/src/watchdog.c
new file mode 100644
index 0000000000..a9d4d21964
--- /dev/null
+++ b/cpukit/score/src/watchdog.c
@@ -0,0 +1,38 @@
+/*
+ * Watchdog Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * _Watchdog_Handler_initialization
+ *
+ * This routine initializes the watchdog handler.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ */
+
+void _Watchdog_Handler_initialization( void )
+{
+ _Watchdog_Sync_count = 0;
+ _Watchdog_Sync_level = 0;
+ _Watchdog_Ticks_since_boot = 0;
+
+ _Chain_Initialize_empty( &_Watchdog_Ticks_chain );
+ _Chain_Initialize_empty( &_Watchdog_Seconds_chain );
+}
diff --git a/cpukit/score/src/watchdogadjust.c b/cpukit/score/src/watchdogadjust.c
new file mode 100644
index 0000000000..2a6dda4c45
--- /dev/null
+++ b/cpukit/score/src/watchdogadjust.c
@@ -0,0 +1,83 @@
+/*
+ * Watchdog Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * _Watchdog_Adjust
+ *
+ * This routine adjusts the delta chain backward or forward in response
+ * to a time change.
+ *
+ * Input parameters:
+ * header - pointer to the delta chain to be adjusted
+ * direction - forward or backward adjustment to delta chain
+ * units - units to adjust
+ *
+ * Output parameters:
+ */
+
+void _Watchdog_Adjust(
+ Chain_Control *header,
+ Watchdog_Adjust_directions direction,
+ Watchdog_Interval units
+)
+{
+ ISR_Level level;
+
+ _ISR_Disable( level );
+
+ /*
+ * NOTE: It is safe NOT to make 'header' a pointer
+ * to volatile data (contrast this with watchdoginsert.c)
+ * because we call _Watchdog_Tickle() below and
+ * hence the compiler must not assume *header to remain
+ * unmodified across that call.
+ *
+ * Till Straumann, 7/2003
+ */
+ if ( !_Chain_Is_empty( header ) ) {
+ switch ( direction ) {
+ case WATCHDOG_BACKWARD:
+ _Watchdog_First( header )->delta_interval += units;
+ break;
+ case WATCHDOG_FORWARD:
+ while ( units ) {
+ if ( units < _Watchdog_First( header )->delta_interval ) {
+ _Watchdog_First( header )->delta_interval -= units;
+ break;
+ } else {
+ units -= _Watchdog_First( header )->delta_interval;
+ _Watchdog_First( header )->delta_interval = 1;
+
+ _ISR_Enable( level );
+
+ _Watchdog_Tickle( header );
+
+ _ISR_Disable( level );
+
+ if ( _Chain_Is_empty( header ) )
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ _ISR_Enable( level );
+
+}
diff --git a/cpukit/score/src/watchdoginsert.c b/cpukit/score/src/watchdoginsert.c
new file mode 100644
index 0000000000..c09135289e
--- /dev/null
+++ b/cpukit/score/src/watchdoginsert.c
@@ -0,0 +1,109 @@
+/*
+ * Watchdog Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * _Watchdog_Insert
+ *
+ * This routine inserts a watchdog timer on to the appropriate delta
+ * chain while updating the delta interval counters.
+ */
+
+void _Watchdog_Insert(
+ Chain_Control *header,
+ Watchdog_Control *the_watchdog
+)
+{
+ ISR_Level level;
+ Watchdog_Control *after;
+ uint32_t insert_isr_nest_level;
+ Watchdog_Interval delta_interval;
+
+
+ insert_isr_nest_level = _ISR_Nest_level;
+ the_watchdog->state = WATCHDOG_BEING_INSERTED;
+
+ _ISR_Disable( level );
+
+ _Watchdog_Sync_count++;
+
+restart:
+ delta_interval = the_watchdog->initial;
+
+ /*
+ * We CANT use _Watchdog_First() here, because a TICK interrupt
+ * could modify the chain during the _ISR_Flash() below. Hence,
+ * the header is pointing to volatile data. The _Watchdog_First()
+ * INLINE routine (but not the macro - note the subtle difference)
+ * casts away the 'volatile'...
+ *
+ * Also, this is only necessary because we call no other routine
+ * from this piece of code, hence the compiler thinks it's safe to
+ * cache *header!!
+ *
+ * Till Straumann, 7/2003 (gcc-3.2.2 -O4 on powerpc)
+ *
+ */
+ for ( after = (Watchdog_Control *) ((volatile Chain_Control *)header)->first ;
+ ;
+ after = _Watchdog_Next( after ) ) {
+
+ if ( delta_interval == 0 || !_Watchdog_Next( after ) )
+ break;
+
+ if ( delta_interval < after->delta_interval ) {
+ after->delta_interval -= delta_interval;
+ break;
+ }
+
+ delta_interval -= after->delta_interval;
+
+ /*
+ * If you experience problems comment out the _ISR_Flash line.
+ * 3.2.0 was the first release with this critical section redesigned.
+ * Under certain circumstances, the PREVIOUS critical section algorithm
+ * used around this flash point allowed interrupts to execute
+ * which violated the design assumptions. The critical section
+ * mechanism used here WAS redesigned to address this.
+ */
+
+ _ISR_Flash( level );
+
+ if ( the_watchdog->state != WATCHDOG_BEING_INSERTED ) {
+ goto exit_insert;
+ }
+
+ if ( _Watchdog_Sync_level > insert_isr_nest_level ) {
+ _Watchdog_Sync_level = insert_isr_nest_level;
+ goto restart;
+ }
+ }
+
+ _Watchdog_Activate( the_watchdog );
+
+ the_watchdog->delta_interval = delta_interval;
+
+ _Chain_Insert_unprotected( after->Node.previous, &the_watchdog->Node );
+
+ the_watchdog->start_time = _Watchdog_Ticks_since_boot;
+
+exit_insert:
+ _Watchdog_Sync_level = insert_isr_nest_level;
+ _Watchdog_Sync_count--;
+ _ISR_Enable( level );
+}
diff --git a/cpukit/score/src/watchdogremove.c b/cpukit/score/src/watchdogremove.c
new file mode 100644
index 0000000000..91e4c30340
--- /dev/null
+++ b/cpukit/score/src/watchdogremove.c
@@ -0,0 +1,69 @@
+/*
+ * Watchdog Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * _Watchdog_Remove
+ *
+ * The routine removes a watchdog from a delta chain and updates
+ * the delta counters of the remaining watchdogs.
+ */
+
+Watchdog_States _Watchdog_Remove(
+ Watchdog_Control *the_watchdog
+)
+{
+ ISR_Level level;
+ Watchdog_States previous_state;
+ Watchdog_Control *next_watchdog;
+
+ _ISR_Disable( level );
+ previous_state = the_watchdog->state;
+ switch ( previous_state ) {
+ case WATCHDOG_INACTIVE:
+ break;
+
+ case WATCHDOG_BEING_INSERTED:
+
+ /*
+ * It is not actually on the chain so just change the state and
+ * the Insert operation we interrupted will be aborted.
+ */
+ the_watchdog->state = WATCHDOG_INACTIVE;
+ break;
+
+ case WATCHDOG_ACTIVE:
+ case WATCHDOG_REMOVE_IT:
+
+ the_watchdog->state = WATCHDOG_INACTIVE;
+ next_watchdog = _Watchdog_Next( the_watchdog );
+
+ if ( _Watchdog_Next(next_watchdog) )
+ next_watchdog->delta_interval += the_watchdog->delta_interval;
+
+ if ( _Watchdog_Sync_count )
+ _Watchdog_Sync_level = _ISR_Nest_level;
+
+ _Chain_Extract_unprotected( &the_watchdog->Node );
+ break;
+ }
+ the_watchdog->stop_time = _Watchdog_Ticks_since_boot;
+
+ _ISR_Enable( level );
+ return( previous_state );
+}
diff --git a/cpukit/score/src/watchdogtickle.c b/cpukit/score/src/watchdogtickle.c
new file mode 100644
index 0000000000..9d5060fec4
--- /dev/null
+++ b/cpukit/score/src/watchdogtickle.c
@@ -0,0 +1,97 @@
+/*
+ * Watchdog Handler
+ *
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/watchdog.h>
+
+/*PAGE
+ *
+ * _Watchdog_Tickle
+ *
+ * This routine decrements the delta counter in response to a tick. The
+ * delta chain is updated accordingly.
+ *
+ * Input parameters:
+ * header - pointer to the delta chain to be tickled
+ *
+ * Output parameters: NONE
+ */
+
+void _Watchdog_Tickle(
+ Chain_Control *header
+)
+{
+ ISR_Level level;
+ Watchdog_Control *the_watchdog;
+ Watchdog_States watchdog_state;
+
+ /*
+ * See the comment in watchdoginsert.c and watchdogadjust.c
+ * about why it's safe not to declare header a pointer to
+ * volatile data - till, 2003/7
+ */
+
+ _ISR_Disable( level );
+
+ if ( _Chain_Is_empty( header ) )
+ goto leave;
+
+ the_watchdog = _Watchdog_First( header );
+ the_watchdog->delta_interval--;
+ if ( the_watchdog->delta_interval != 0 )
+ goto leave;
+
+ do {
+ watchdog_state = _Watchdog_Remove( the_watchdog );
+
+ _ISR_Enable( level );
+
+ switch( watchdog_state ) {
+ case WATCHDOG_ACTIVE:
+ (*the_watchdog->routine)(
+ the_watchdog->id,
+ the_watchdog->user_data
+ );
+ break;
+
+ case WATCHDOG_INACTIVE:
+ /*
+ * This state indicates that the watchdog is not on any chain.
+ * Thus, it is NOT on a chain being tickled. This case should
+ * never occur.
+ */
+ break;
+
+ case WATCHDOG_BEING_INSERTED:
+ /*
+ * This state indicates that the watchdog is in the process of
+ * BEING inserted on the chain. Thus, it can NOT be on a chain
+ * being tickled. This case should never occur.
+ */
+ break;
+
+ case WATCHDOG_REMOVE_IT:
+ break;
+ }
+
+ _ISR_Disable( level );
+
+ the_watchdog = _Watchdog_First( header );
+ } while ( !_Chain_Is_empty( header ) &&
+ (the_watchdog->delta_interval == 0) );
+
+leave:
+ _ISR_Enable(level);
+}
diff --git a/cpukit/score/src/wkspace.c b/cpukit/score/src/wkspace.c
new file mode 100644
index 0000000000..e0cb4a5c1d
--- /dev/null
+++ b/cpukit/score/src/wkspace.c
@@ -0,0 +1,87 @@
+/*
+ * Workspace Handler
+ *
+ * XXX
+ *
+ * NOTE:
+ *
+ * COPYRIGHT (c) 1989-1999.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#include <rtems/system.h>
+#include <rtems/score/wkspace.h>
+#include <rtems/score/interr.h>
+
+/*PAGE
+ *
+ * _Workspace_Handler_initialization
+ */
+
+void _Workspace_Handler_initialization(
+ void *starting_address,
+ uint32_t size
+)
+{
+ uint32_t *zero_out_array;
+ uint32_t index;
+ uint32_t memory_available;
+
+ if ( !starting_address || !_Addresses_Is_aligned( starting_address ) )
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ TRUE,
+ INTERNAL_ERROR_INVALID_WORKSPACE_ADDRESS
+ );
+
+ if ( _CPU_Table.do_zero_of_workspace ) {
+ for( zero_out_array = (uint32_t *) starting_address, index = 0 ;
+ index < size / sizeof( uint32_t ) ;
+ index++ )
+ zero_out_array[ index ] = 0;
+ }
+
+ memory_available = _Heap_Initialize(
+ &_Workspace_Area,
+ starting_address,
+ size,
+ CPU_HEAP_ALIGNMENT
+ );
+
+ if ( memory_available == 0 )
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ TRUE,
+ INTERNAL_ERROR_TOO_LITTLE_WORKSPACE
+ );
+}
+
+/*PAGE
+ *
+ * _Workspace_Allocate_or_fatal_error
+ *
+ */
+
+void *_Workspace_Allocate_or_fatal_error(
+ uint32_t size
+)
+{
+ void *memory;
+
+ memory = _Workspace_Allocate( size );
+
+ if ( memory == NULL )
+ _Internal_error_Occurred(
+ INTERNAL_ERROR_CORE,
+ TRUE,
+ INTERNAL_ERROR_WORKSPACE_ALLOCATION
+ );
+
+ return memory;
+}
diff --git a/cpukit/telnetd/Makefile.am b/cpukit/telnetd/Makefile.am
new file mode 100644
index 0000000000..99deb79186
--- /dev/null
+++ b/cpukit/telnetd/Makefile.am
@@ -0,0 +1,52 @@
+##
+## $Id$
+##
+
+include $(top_srcdir)/automake/compile.am
+
+EXTRA_LIBRARIES =
+CLEANFILES =
+
+if HAS_NETWORKING
+include_rtemsdir = $(includedir)/rtems
+include_rtems_HEADERS = pty.h telnetd.h
+
+EXTRA_LIBRARIES += libtelnetd.a
+CLEANFILES += libtelnetd.a
+libtelnetd_a_SOURCES = pty.c pty.h telnetd.c telnetd.h icmds.c
+libtelnetd_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_OPTIMIZE_V)
+
+EXTRA_LIBRARIES += libtelnetd_g.a
+CLEANFILES += libtelnetd_g.a
+libtelnetd_g_a_SOURCES = $(libtelnetd_a_SOURCES)
+libtelnetd_g_a_CPPFLAGS = $(AM_CPPFLAGS) $(CFLAGS_DEBUG_V)
+
+noinst_DATA = libtelnetd$(LIB_VARIANT).a
+endif
+
+EXTRA_DIST = README
+
+all-local: $(PREINSTALL_FILES)
+
+PREINSTALL_DIRS =
+PREINSTALL_FILES =
+
+if HAS_NETWORKING
+$(PROJECT_INCLUDE)/rtems/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_INCLUDE)/rtems
+ @: > $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+PREINSTALL_DIRS += $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+
+$(PROJECT_INCLUDE)/rtems/pty.h: pty.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/pty.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/pty.h
+
+$(PROJECT_INCLUDE)/rtems/telnetd.h: telnetd.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/telnetd.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/telnetd.h
+endif
+
+CLEANFILES += $(PREINSTALL_FILES)
+DISTCLEANFILES = $(PREINSTALL_DIRS)
+
+include $(top_srcdir)/automake/local.am
diff --git a/cpukit/telnetd/README b/cpukit/telnetd/README
new file mode 100644
index 0000000000..0c964c412d
--- /dev/null
+++ b/cpukit/telnetd/README
@@ -0,0 +1,28 @@
+#
+# $Id$
+#
+
+Author: fernando.ruiz@ctv.es (correo@fernando-ruiz.com)
+
+This directory contains a telnetd server
+primary features:
+
+ + create a user shell pseudo-terminal task.
+
+This code has not been extensively tested. It is provided as a tool
+for RTEMS users to open more shell tcp/ip pseudo-terminal.
+Suggestions and comments are appreciated.
+
+Read libmisc/shell for more information.
+
+NOTES:
+
+1. OOB not yet implemented. Only a reduced negotiation is implemented.
+
+2. If you have tcp/ip inited you can start telnetd daemon.
+ You need register pseudo-terminals driver into device drivers table.
+ 16 ptyX termios device terminales are created into /dev/.
+ Calling rtems_initialize_telnetd() starts the daemon.
+ Enjoy it.
+
+FUTURE:
diff --git a/cpukit/telnetd/icmds.c b/cpukit/telnetd/icmds.c
new file mode 100644
index 0000000000..b416692ec5
--- /dev/null
+++ b/cpukit/telnetd/icmds.c
@@ -0,0 +1,47 @@
+#include <rtems/shell.h>
+#include <rtems/rtems_bsdnet.h>
+/*+++++++++++++++++++++++++++++++++++++++++++++*/
+int main_inet(int argc,char * argv[]) {
+ rtems_bsdnet_show_inet_routes ();
+ return 0;
+}
+/*+++++++++++++++++++++++++++++++++++++++++++++*/
+int main_mbuf(int argc,char * argv[]) {
+ rtems_bsdnet_show_mbuf_stats ();
+ return 0;
+}
+/*+++++++++++++++++++++++++++++++++++++++++++++*/
+int main_if(int argc,char * argv[]) {
+ rtems_bsdnet_show_if_stats ();
+ return 0;
+}
+/*+++++++++++++++++++++++++++++++++++++++++++++*/
+int main_ip(int argc,char * argv[]) {
+ rtems_bsdnet_show_ip_stats ();
+ return 0;
+}
+/*+++++++++++++++++++++++++++++++++++++++++++++*/
+int main_icmp(int argc,char * argv[]) {
+ rtems_bsdnet_show_icmp_stats ();
+ return 0;
+}
+/*+++++++++++++++++++++++++++++++++++++++++++++*/
+int main_tcp(int argc,char * argv[]) {
+ rtems_bsdnet_show_tcp_stats ();
+ return 0;
+}
+/*+++++++++++++++++++++++++++++++++++++++++++++*/
+int main_udp(int argc,char * argv[]) {
+ rtems_bsdnet_show_udp_stats ();
+ return 0;
+}
+/*+++++++++++++++++++++++++++++++++++++++++++++*/
+void register_icmds(void) {
+ shell_add_cmd("inet" ,"net","inet routes" ,main_inet);
+ shell_add_cmd("mbuf" ,"net","mbuf stats" ,main_mbuf);
+ shell_add_cmd("if" ,"net","if stats" ,main_if );
+ shell_add_cmd("ip" ,"net","ip stats" ,main_ip );
+ shell_add_cmd("icmp" ,"net","icmp stats" ,main_icmp);
+ shell_add_cmd("tcp" ,"net","tcp stats" ,main_tcp );
+ shell_add_cmd("udp" ,"net","udp stats" ,main_udp );
+}
diff --git a/cpukit/telnetd/pty.c b/cpukit/telnetd/pty.c
new file mode 100644
index 0000000000..c19d05db37
--- /dev/null
+++ b/cpukit/telnetd/pty.c
@@ -0,0 +1,407 @@
+/*
+ * /dev/ptyXX (A first version for pseudo-terminals)
+ *
+ * Author: Fernando RUIZ CASAS (fernando.ruiz@ctv.es)
+ * May 2001
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * $Id$
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*-----------------------------------------*/
+#include <termios.h>
+#include <rtems.h>
+#include <rtems/libio.h>
+#include <rtems/pty.h>
+#include <rtems/bspIo.h>
+/*-----------------------------------------*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+/*-----------------------------------------*/
+#define IAC_ESC 255
+#define IAC_DONT 254
+#define IAC_DO 253
+#define IAC_WONT 252
+#define IAC_WILL 251
+#define IAC_SB 250
+#define IAC_GA 249
+#define IAC_EL 248
+#define IAC_EC 247
+#define IAC_AYT 246
+#define IAC_AO 245
+#define IAC_IP 244
+#define IAC_BRK 243
+#define IAC_DMARK 242
+#define IAC_NOP 241
+#define IAC_SE 240
+#define IAC_EOR 239
+
+struct pty_tt;
+typedef struct pty_tt pty_t;
+
+struct pty_tt {
+ char *devname;
+ struct rtems_termios_tty *ttyp;
+ tcflag_t c_cflag;
+ int opened;
+ int socket;
+
+ int last_cr;
+ int iac_mode;
+};
+
+
+int ptys_initted=FALSE;
+pty_t ptys[MAX_PTYS];
+
+/* This procedure returns the devname for a pty slot free.
+ * If not slot availiable (field socket>=0)
+ * then the socket argument is closed
+ */
+
+char * get_pty(int socket) {
+ int ndx;
+ if (!ptys_initted) return NULL;
+ for (ndx=0;ndx<MAX_PTYS;ndx++) {
+ if (ptys[ndx].socket<0) {
+ ptys[ndx].socket=socket;
+ return ptys[ndx].devname;
+ };
+ };
+ close(socket);
+ return NULL;
+}
+
+
+/*-----------------------------------------------------------*/
+/*
+ * The NVT terminal is negociated in PollRead and PollWrite
+ * with every BYTE sendded or received.
+ * A litle status machine in the pty_read_byte(int minor)
+ *
+ */
+const char IAC_AYT_RSP[]="\r\nAYT? Yes, RTEMS-SHELL is here\r\n";
+const char IAC_BRK_RSP[]="<*Break*>";
+const char IAC_IP_RSP []="<*Interrupt*>";
+
+
+static
+int send_iac(int minor,unsigned char mode,unsigned char option) {
+ unsigned char buf[3];
+ buf[0]=IAC_ESC;
+ buf[1]=mode;
+ buf[2]=option;
+ return write(ptys[minor].socket,buf,sizeof(buf));
+}
+
+int read_pty(int minor) { /* Characters writed in the client side*/
+ unsigned char value;
+ int count;
+ int result;
+ count=read(ptys[minor].socket,&value,sizeof(value));
+ if (count<1) {
+ fclose(stdin);
+ fclose(stdout);
+ fclose(stderr);
+ /* If you don't read from the socket the system ends the task */
+ rtems_task_delete(RTEMS_SELF);
+ };
+ switch(ptys[minor].iac_mode) {
+ case IAC_ESC:
+ ptys[minor].iac_mode=0;
+ switch(value) {
+ case IAC_ESC :
+ return IAC_ESC;
+ case IAC_DONT:
+ case IAC_DO :
+ case IAC_WONT:
+ case IAC_WILL:
+ ptys[minor].iac_mode=value;
+ return -1;
+ case IAC_SB :
+ return -100;
+ case IAC_GA :
+ return -1;
+ case IAC_EL :
+ return 0x03; /* Ctrl-C*/
+ case IAC_EC :
+ return '\b';
+ case IAC_AYT :
+ write(ptys[minor].socket,IAC_AYT_RSP,strlen(IAC_AYT_RSP));
+ return -1;
+ case IAC_AO :
+ return -1;
+ case IAC_IP :
+ write(ptys[minor].socket,IAC_IP_RSP,strlen(IAC_IP_RSP));
+ return -1;
+ case IAC_BRK :
+ write(ptys[minor].socket,IAC_BRK_RSP,strlen(IAC_BRK_RSP));
+ return -1;
+ case IAC_DMARK:
+ return -2;
+ case IAC_NOP :
+ return -1;
+ case IAC_SE :
+ return -101;
+ case IAC_EOR :
+ return -102;
+ default :
+ return -1;
+ };
+ break;
+ case IAC_WILL:
+ ptys[minor].iac_mode=0;
+ if (value==34){send_iac(minor,IAC_DONT, 34); /*LINEMODE*/
+ send_iac(minor,IAC_DO , 1);} else /*ECHO */
+ {send_iac(minor,IAC_DONT,value);};
+ return -1;
+ case IAC_DONT:
+ ptys[minor].iac_mode=0;
+ return -1;
+ case IAC_DO :
+ ptys[minor].iac_mode=0;
+ if (value==3) {send_iac(minor,IAC_WILL, 3);} else /* GO AHEAD*/
+ if (value==1) { } else /* ECHO */
+ {send_iac(minor,IAC_WONT,value);};
+ return -1;
+ case IAC_WONT:
+ ptys[minor].iac_mode=0;
+ if (value==1) {send_iac(minor,IAC_WILL, 1);} else /* ECHO */
+ {send_iac(minor,IAC_WONT,value);};
+ return -1;
+ default:
+ ptys[minor].iac_mode=0;
+ if (value==IAC_ESC) {
+ ptys[minor].iac_mode=value;
+ return -1;
+ } else {
+ result=value;
+ if ((value=='\n') && (ptys[minor].last_cr)) result=-1;
+ ptys[minor].last_cr=(value=='\r');
+ return result;
+ };
+ };
+
+}
+
+/*-----------------------------------------------------------*/
+static int ptySetAttributes(int minor,const struct termios *t);
+static int ptyPollInitialize(int major,int minor,void * arg) ;
+static int ptyShutdown(int major,int minor,void * arg) ;
+static int ptyPollWrite(int minor, const char * buf,int len) ;
+static int ptyPollRead(int minor) ;
+const rtems_termios_callbacks * pty_get_termios_handlers(int polled) ;
+/*-----------------------------------------------------------*/
+/* Set the 'Hardware' */
+/*-----------------------------------------------------------*/
+static int
+ptySetAttributes(int minor,const struct termios *t) {
+ if (minor<MAX_PTYS) {
+ ptys[minor].c_cflag=t->c_cflag;
+ } else {
+ return -1;
+ };
+ return 0;
+}
+/*-----------------------------------------------------------*/
+static int
+ptyPollInitialize(int major,int minor,void * arg) {
+ rtems_libio_open_close_args_t * args = arg;
+ struct termios t;
+ if (minor<MAX_PTYS) {
+ if (ptys[minor].socket<0) return -1;
+ ptys[minor].opened=TRUE;
+ ptys[minor].ttyp=args->iop->data1;
+ t.c_cflag=B9600|CS8;/* termios default */
+ return ptySetAttributes(minor,&t);
+ } else {
+ return -1;
+ };
+}
+/*-----------------------------------------------------------*/
+static int
+ptyShutdown(int major,int minor,void * arg) {
+ if (minor<MAX_PTYS) {
+ ptys[minor].opened=FALSE;
+ if (ptys[minor].socket>=0) close(ptys[minor].socket);
+ ptys[minor].socket=-1;
+ chown(ptys[minor].devname,2,0);
+ } else {
+ return -1;
+ };
+ return 0;
+}
+/*-----------------------------------------------------------*/
+/* Write Characters into pty device */
+/*-----------------------------------------------------------*/
+static int
+ptyPollWrite(int minor, const char * buf,int len) {
+ int count;
+ if (minor<MAX_PTYS) {
+ if (ptys[minor].socket<0) return -1;
+ count=write(ptys[minor].socket,buf,len);
+ } else {
+ count=-1;
+ };
+ return count;
+}
+/*-----------------------------------------------------------*/
+static int
+ptyPollRead(int minor) {
+ int result;
+ if (minor<MAX_PTYS) {
+ if (ptys[minor].socket<0) return -1;
+ result=read_pty(minor);
+ return result;
+ };
+ return -1;
+}
+/*-----------------------------------------------------------*/
+static const rtems_termios_callbacks pty_poll_callbacks = {
+ ptyPollInitialize, /* FirstOpen*/
+ ptyShutdown, /* LastClose*/
+ ptyPollRead, /* PollRead */
+ ptyPollWrite, /* Write */
+ ptySetAttributes, /* setAttributes */
+ NULL, /* stopRemoteTX */
+ NULL, /* StartRemoteTX */
+ 0 /* outputUsesInterrupts */
+};
+/*-----------------------------------------------------------*/
+const rtems_termios_callbacks * pty_get_termios_handlers(int polled) {
+ return &pty_poll_callbacks;
+}
+/*-----------------------------------------------------------*/
+void init_ptys(void) {
+ int ndx;
+ for (ndx=0;ndx<MAX_PTYS;ndx++) {
+ ptys[ndx].devname=malloc(strlen("/dev/ptyXX")+1);
+ sprintf(ptys[ndx].devname,"/dev/pty%X",ndx);
+ ptys[ndx].ttyp=NULL;
+ ptys[ndx].c_cflag=CS8|B9600;
+ ptys[ndx].socket=-1;
+ ptys[ndx].opened=FALSE;
+
+ };
+ ptys_initted=TRUE;
+}
+
+
+/*-----------------------------------------------------------*/
+/* pty_initialize
+ *
+ * This routine initializes the pty IO driver.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * Return values:
+ */
+/*-----------------------------------------------------------*/
+rtems_device_driver pty_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ int ndx;
+ rtems_status_code status ;
+
+ /*
+ * Set up ptys
+ */
+
+ init_ptys();
+
+ /*
+ * Register the devices
+ */
+ for (ndx=0;ndx<MAX_PTYS;ndx++) {
+ status = rtems_io_register_name(ptys[ndx].devname, major, ndx);
+ if (status != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred(status);
+ chmod(ptys[ndx].devname,0660);
+ chown(ptys[ndx].devname,2,0); /* tty,root*/
+ };
+ printk("Device: /dev/pty%X../dev/pty%X (%d)pseudo-terminals registered.\n",0,MAX_PTYS-1,MAX_PTYS);
+
+ return RTEMS_SUCCESSFUL;
+}
+
+
+/*
+ * Open entry point
+ */
+
+rtems_device_driver pty_open(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ rtems_status_code sc ;
+ sc = rtems_termios_open(major,minor,arg,pty_get_termios_handlers(FALSE));
+ return sc;
+}
+
+/*
+ * Close entry point
+ */
+
+rtems_device_driver pty_close(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ return rtems_termios_close(arg);
+}
+
+/*
+ * read bytes from the pty
+ */
+
+rtems_device_driver pty_read(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ return rtems_termios_read(arg);
+}
+
+/*
+ * write bytes to the pty
+ */
+
+rtems_device_driver pty_write(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ return rtems_termios_write(arg);
+}
+
+/*
+ * IO Control entry point
+ */
+
+rtems_device_driver pty_control(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ return rtems_termios_ioctl(arg);
+}
diff --git a/cpukit/telnetd/pty.h b/cpukit/telnetd/pty.h
new file mode 100644
index 0000000000..9d3d6295ce
--- /dev/null
+++ b/cpukit/telnetd/pty.h
@@ -0,0 +1,63 @@
+/*
+ * /dev/ptyXX (A first version for pseudo-terminals)
+ *
+ * Author: Fernando RUIZ CASAS (fernando.ruiz@ctv.es)
+ * May 2001
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * $Id$
+ */
+
+#ifndef __PTY_H
+#define __PTY_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rtems.h>
+
+#ifndef MAX_PTYS
+#define MAX_PTYS 16
+#endif
+
+char * get_pty(int socket);
+
+rtems_device_driver pty_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg);
+rtems_device_driver pty_open(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg);
+rtems_device_driver pty_close(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg);
+rtems_device_driver pty_read(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg);
+rtems_device_driver pty_write(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg);
+rtems_device_driver pty_control(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg);
+
+
+#define PTY_DRIVER_TABLE_ENTRY \
+ { pty_initialize , pty_open , pty_close , \
+ pty_read , pty_write , pty_control }
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/telnetd/telnetd.c b/cpukit/telnetd/telnetd.c
new file mode 100644
index 0000000000..bc8449ae96
--- /dev/null
+++ b/cpukit/telnetd/telnetd.c
@@ -0,0 +1,133 @@
+/***********************************************************/
+/*
+ *
+ * The telnet DAEMON
+ *
+ * Author: 17,may 2001
+ *
+ * WORK: fernando.ruiz@ctv.es
+ * HOME: correo@fernando-ruiz.com
+ *
+ * After start the net you can start this daemon.
+ * It uses the previously inited pseudo-terminales (pty.c)
+ * getting a new terminal with getpty(). This function
+ * gives a terminal name passing a opened socket like parameter.
+ *
+ * With register_telnetd() you add a new command in the shell to start
+ * this daemon interactively. (Login in /dev/console of course)
+ *
+ * Sorry but OOB is not still implemented. (This is the first version)
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <rtems/error.h>
+#include <rtems/pty.h>
+#include <rtems/shell.h>
+#include <rtems/telnetd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h> /* memset */
+#include <stdio.h>
+/***********************************************************/
+rtems_id telnetd_task_id =0;
+rtems_unsigned32 telnetd_stack_size =16384;
+rtems_task_priority telnetd_task_priority=100;
+/***********************************************************/
+rtems_task rtems_task_telnetd(rtems_task_argument task_argument) {
+ int des_socket,
+ acp_socket;
+ struct sockaddr_in srv;
+ char * devname;
+ int i=1;
+ int size_adr;
+ if ((des_socket=socket(PF_INET,SOCK_STREAM,0))<0) {
+ perror("telnetd:socket");
+ rtems_task_delete(RTEMS_SELF);
+ };
+ setsockopt(des_socket,SOL_SOCKET,0,&i,sizeof(i));
+ memset(&srv,0,sizeof(srv));
+ srv.sin_family=AF_INET;
+ srv.sin_port=htons(23);
+ size_adr=sizeof(srv);
+ if ((bind(des_socket,(struct sockaddr *)&srv,size_adr))<0) {
+ perror("telnetd:bind");
+ close(des_socket);
+ rtems_task_delete(RTEMS_SELF);
+ };
+ if ((listen(des_socket,5))<0) {
+ perror("telnetd:listen");
+ close(des_socket);
+ rtems_task_delete(RTEMS_SELF);
+ };
+ do {
+ acp_socket=accept(des_socket,(struct sockaddr*)&srv,&size_adr);
+ if (acp_socket<0) {
+ perror("telnetd:accept");
+ break;
+ };
+ if ((devname = get_pty(acp_socket)) ) {
+ shell_init(&devname[5],
+ telnetd_stack_size,
+ telnetd_task_priority,
+ devname,B9600|CS8,FALSE);
+ } else {
+ close(acp_socket);
+ };
+ } while(1);
+ close(des_socket);
+ rtems_task_delete(RTEMS_SELF);
+}
+/***********************************************************/
+int rtems_initialize_telnetd(void) {
+ void register_icmds(void);
+ rtems_status_code sc;
+
+ register_icmds(); /* stats for tcp/ip */
+
+ if (telnetd_task_id ) return RTEMS_RESOURCE_IN_USE;
+ if (telnetd_stack_size<=0 ) telnetd_stack_size =16384;
+ if (telnetd_task_priority<=2) telnetd_task_priority=100;
+ sc=rtems_task_create(new_rtems_name("tlnd"),
+ 100,RTEMS_MINIMUM_STACK_SIZE,
+ RTEMS_DEFAULT_MODES,
+ RTEMS_DEFAULT_ATTRIBUTES,
+ &telnetd_task_id);
+ if (sc!=RTEMS_SUCCESSFUL) {
+ rtems_error(sc,"creating task telnetd");
+ return (int)sc;
+ };
+ sc=rtems_task_start(telnetd_task_id,
+ rtems_task_telnetd,
+ (rtems_task_argument)NULL);
+ if (sc!=RTEMS_SUCCESSFUL) {
+ rtems_error(sc,"starting task telnetd");
+ };
+ return (int)sc;
+}
+/***********************************************************/
+int main_telnetd(int argc,char * argv[]) {
+ rtems_status_code sc;
+ if (telnetd_task_id) {
+ printf("ERROR:telnetd already started\n");
+ return 1;
+ };
+ if (argc>1) telnetd_stack_size =str2int(argv[1]);
+ if (argc>2) telnetd_task_priority=str2int(argv[2]);
+ sc=rtems_initialize_telnetd();
+ if (sc!=RTEMS_SUCCESSFUL) return sc;
+ printf("rtems_telnetd() started with stacksize=%u,priority=%d\n",
+ telnetd_stack_size,telnetd_task_priority);
+ return 0;
+}
+/***********************************************************/
+int register_telnetd(void) {
+ shell_add_cmd("telnetd","telnet","telnetd [stacksize [tsk_priority]]",main_telnetd);
+ return 0;
+}
+/***********************************************************/
diff --git a/cpukit/telnetd/telnetd.h b/cpukit/telnetd/telnetd.h
new file mode 100644
index 0000000000..01c7e58409
--- /dev/null
+++ b/cpukit/telnetd/telnetd.h
@@ -0,0 +1,34 @@
+/*
+ * (A first version for telnetd)
+ *
+ * Author: Fernando RUIZ CASAS (fernando.ruiz@ctv.es)
+ * May 2001
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * rtems_initialize_telnetd() starts the daemon.
+ * main_telnetd() is the main_proc for the command telnetd in the shell
+ * register_telnetd() add a new command in the shell to start
+ * interactively the telnetd daemon.
+ *
+ * $Id$
+ */
+
+#ifndef __TELNETD_H
+#define __TELNETD_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int rtems_initialize_telnetd(void);
+int main_telnetd(int argc,char * argv[]);
+int register_telnetd(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cpukit/wrapup/.cvsignore b/cpukit/wrapup/.cvsignore
new file mode 100644
index 0000000000..282522db03
--- /dev/null
+++ b/cpukit/wrapup/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/cpukit/wrapup/Makefile.am b/cpukit/wrapup/Makefile.am
new file mode 100644
index 0000000000..08686197bc
--- /dev/null
+++ b/cpukit/wrapup/Makefile.am
@@ -0,0 +1,122 @@
+##
+## $Id$
+##
+
+include $(top_srcdir)/automake/multilib.am
+include $(top_srcdir)/automake/compile.am
+
+## Setup the variant build subdirectory
+ARCH_OPTIMIZE_V = o-optimize
+ARCH_DEBUG_V = o-debug
+
+ARCH__V = $(ARCH_OPTIMIZE_V)
+ARCH = $(ARCH_$(VARIANT_V)_V)
+
+project_lib_DATA = $(ARCH)/librtemscpu$(LIB_VARIANT).a
+CLEANFILES = o-optimize/librtemscpu.a
+CLEANFILES += o-debug/librtemscpu_g.a
+
+TMP_LIBS =
+if LIBSCORECPU
+TMP_LIBS += ../score/cpu/@RTEMS_CPU@/libscorecpu$(LIB_VARIANT).a
+endif
+TMP_LIBS += ../score/libscore$(LIB_VARIANT).a
+TMP_LIBS += ../sapi/libsapi$(LIB_VARIANT).a
+TMP_LIBS += ../rtems/librtems$(LIB_VARIANT).a
+
+if HAS_POSIX
+TMP_LIBS += ../posix/libposix$(LIB_VARIANT).a
+endif
+
+if HAS_ITRON
+TMP_LIBS += ../itron/libitron$(LIB_VARIANT).a
+endif
+
+TMP_LIBS += ../libcsupport/libcsupport$(LIB_VARIANT).a
+if !UNIX
+TMP_LIBS += ../libblock/libblock$(LIB_VARIANT).a
+TMP_LIBS += ../libfs/libdosfs$(LIB_VARIANT).a
+endif
+TMP_LIBS += ../libfs/libimfs$(LIB_VARIANT).a
+
+TMP_LIBS += ../libmisc/libmonitor$(LIB_VARIANT).a
+TMP_LIBS += ../libmisc/libuntar$(LIB_VARIANT).a
+TMP_LIBS += ../libmisc/libstackchk$(LIB_VARIANT).a
+TMP_LIBS += ../libmisc/libcpuuse$(LIB_VARIANT).a
+TMP_LIBS += ../libmisc/librtmonuse$(LIB_VARIANT).a
+
+## XXX temporarily removed because it causes a
+## XXX number of BSPs to not link "main(){}" used by autoconf
+# if LIBSERDBG
+# TMP_LIBS += ../libmisc/libserdbg$(LIB_VARIANT).a
+# endif
+
+if LIBSHELL
+TMP_LIBS += ../libmisc/libshell$(LIB_VARIANT).a
+endif
+
+TMP_LIBS += ../libmisc/libdumpbuf$(LIB_VARIANT).a
+TMP_LIBS += ../libmisc/libdevnull$(LIB_VARIANT).a
+TMP_LIBS += ../libmisc/libdummy$(LIB_VARIANT).a
+TMP_LIBS += ../libmisc/libmw-fb$(LIB_VARIANT).a
+TMP_LIBS += ../libmisc/libcapture$(LIB_VARIANT).a
+TMP_LIBS += ../libmisc/libfsmount$(LIB_VARIANT).a
+
+if HAS_NETWORKING
+TMP_LIBS += ../libnetworking/libnetworking$(LIB_VARIANT).a
+TMP_LIBS += ../libnetworking/libc$(LIB_VARIANT).a
+TMP_LIBS += ../libnetworking/lib$(LIB_VARIANT).a
+endif
+
+if LIBRPC
+TMP_LIBS += ../librpc/librpc$(LIB_VARIANT).a
+TMP_LIBS += ../librpc/libxdr$(LIB_VARIANT).a
+endif
+
+$(ARCH)/librtemscpu$(LIB_VARIANT).a: $(TMP_LIBS)
+ rm -f $@
+ $(mkdir_p) $(ARCH)
+ rm -rf $(ARCH)/*.$(OBJEXT) $(ARCH)/*.rel
+ for f in $(TMP_LIBS); do \
+ case $$f in \
+ *.$(OBJEXT) | *.rel) \
+ if test -f $(ARCH)/`basename $$f`; then \
+ if cmp $$f $(ARCH)/`basename $$f`; then \
+ true; \
+ else \
+ echo 1>&2 "ERROR -- `basename $$f` in multiple files"; \
+ exit 1; \
+ fi; \
+ else \
+ cp $$f $(ARCH)/; \
+ chmod a-w $(ARCH)/`basename $$f`; \
+ fi; \
+ ;; \
+ *.a) \
+ cd $(ARCH); \
+ $(AR) xv ../$$f || exit 1; \
+ chmod a-w * ; \
+ cd ..; \
+ ;; \
+ esac; \
+ done
+ $(AR) rc $@ $(ARCH)/*
+ rm -f $(ARCH)/*.$(OBJEXT) $(ARCH)/*.rel
+ $(RANLIB) $@
+
+all-local: $(TMPINSTALL_FILES)
+
+TMPINSTALL_FILES =
+
+$(PROJECT_LIB)/$(dirstamp):
+ @$(mkdir_p) $(PROJECT_LIB)
+ @: > $(PROJECT_LIB)/$(dirstamp)
+TMPINSTALL_FILES += $(PROJECT_LIB)/$(dirstamp)
+
+$(PROJECT_LIB)/librtemscpu$(LIB_VARIANT).a: $(ARCH)/librtemscpu$(LIB_VARIANT).a $(PROJECT_LIB)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_LIB)/librtemscpu$(LIB_VARIANT).a
+TMPINSTALL_FILES += $(PROJECT_LIB)/librtemscpu$(LIB_VARIANT).a
+
+CLEANFILES += $(TMPINSTALL_FILES)
+
+include $(top_srcdir)/automake/local.am